mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2024-12-04 18:00:18 +00:00
Merge branch 'master' into hackathon
This commit is contained in:
commit
fb1fc409ff
@ -6,7 +6,7 @@ Official TypeScript implementation of the Fluence Peer.
|
||||
|
||||
## Getting started
|
||||
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://doc.fluence.dev/docs/js-sdk)
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://fluence.dev/docs/build/fluence-js/)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<a href="#fluence-js" id="fluence-js" style="color: inherit; text-decoration: none;">
|
||||
<h1>Fluence JS</h1>
|
||||
</a>
|
||||
<p>To start developing applications with Fluence JS refer to the official <a href="https://doc.fluence.dev/docs/js-sdk">documentation</a></p>
|
||||
<p>To start developing applications with Fluence JS refer to the official <a href="https://fluence.dev/docs/build/fluence-js/">documentation</a></p>
|
||||
<p>Fluence JS is an implementation of the Fluence protocol for JavaScript-based environments. It can connect browsers, Node.js applications, and so on to the Fluence p2p network.</p>
|
||||
<p>Similar to the <a href="https://github.com/fluencelabs/fluence">Rust Fluence Peer implementation</a> it includes:</p>
|
||||
<ul>
|
||||
@ -11,6 +11,6 @@
|
||||
<li>Builtin services</li>
|
||||
</ul>
|
||||
<p>Fluence JS can call services and functions on the Fluence network, and expose new APIs to the p2p network directly from TypeScript and JavaScript.
|
||||
<a href="https://github.com/fluencelabs/aqua">Aqua language</a> uses Fluence JS as a compilation target, and they are designed to <a href="https://doc.fluence.dev/docs/js-sdk/3_in_depth#understanding-the-aqua-compiler-output">work in tandem</a>.</p>
|
||||
<a href="https://github.com/fluencelabs/aqua">Aqua language</a> uses Fluence JS as a compilation target, and they are designed to <a href="https://fluence.dev/docs/build/fluence-js/in-depth#understanding-the-aqua-compiler-output">work in tandem</a>.</p>
|
||||
<p>Fluence JS can be used with any framework of your choice (or even without frameworks).</p>
|
||||
</div></div><div class="col-4 col-menu menu-sticky-wrap menu-highlight"><nav class="tsd-navigation primary"><ul><li class="current"><a href="modules.html">Exports</a></li></ul></nav><nav class="tsd-navigation secondary menu-sticky"><ul><li class="tsd-kind-class"><a href="classes/FluencePeer.html" class="tsd-kind-icon">Fluence<wbr/>Peer</a></li><li class="tsd-kind-class"><a href="classes/KeyPair.html" class="tsd-kind-icon">Key<wbr/>Pair</a></li><li class="tsd-kind-interface tsd-has-type-parameter"><a href="interfaces/CallParams.html" class="tsd-kind-icon">Call<wbr/>Params</a></li><li class="tsd-kind-interface"><a href="interfaces/PeerConfig.html" class="tsd-kind-icon">Peer<wbr/>Config</a></li><li class="tsd-kind-type-alias"><a href="modules.html#AvmLoglevel" class="tsd-kind-icon">Avm<wbr/>Loglevel</a></li><li class="tsd-kind-type-alias"><a href="modules.html#PeerIdB58" class="tsd-kind-icon">Peer<wbr/>Id<wbr/>B58</a></li><li class="tsd-kind-type-alias"><a href="modules.html#PeerStatus" class="tsd-kind-icon">Peer<wbr/>Status</a></li><li class="tsd-kind-variable"><a href="modules.html#Fluence" class="tsd-kind-icon">Fluence</a></li><li class="tsd-kind-function tsd-is-external"><a href="modules.html#loadWasmFromFileSystem" class="tsd-kind-icon">load<wbr/>Wasm<wbr/>From<wbr/>File<wbr/>System</a></li><li class="tsd-kind-function tsd-is-external"><a href="modules.html#loadWasmFromNpmPackage" class="tsd-kind-icon">load<wbr/>Wasm<wbr/>From<wbr/>Npm<wbr/>Package</a></li><li class="tsd-kind-function tsd-is-external"><a href="modules.html#loadWasmFromServer" class="tsd-kind-icon">load<wbr/>Wasm<wbr/>From<wbr/>Server</a></li><li class="tsd-kind-function"><a href="modules.html#setLogLevel" class="tsd-kind-icon">set<wbr/>Log<wbr/>Level</a></li></ul></nav></div></div></div><footer class="with-border-bottom"><div class="container"><h2>Legend</h2><div class="tsd-legend-group"><ul class="tsd-legend"><li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li><li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li><li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li></ul><ul class="tsd-legend"><li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li></ul></div><h2>Settings</h2><p>Theme <select id="theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></p></div></footer><div class="container tsd-generator"><p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></div><div class="overlay"></div><script src="assets/main.js"></script></body></html>
|
@ -6,7 +6,7 @@ Official TypeScript implementation of the Fluence Peer.
|
||||
|
||||
## Getting started
|
||||
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://doc.fluence.dev/docs/js-sdk)
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://fluence.dev/docs/build/fluence-js/)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fluencelabs/fluence",
|
||||
"version": "0.26.3-snapshot-3",
|
||||
"version": "0.26.3-snapshot-20",
|
||||
"description": "TypeScript implementation of Fluence Peer",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
|
@ -0,0 +1,75 @@
|
||||
import { Particle } from '../../internal/Particle';
|
||||
import { doNothing } from '../../internal/utils';
|
||||
import { FluencePeer } from '../../index';
|
||||
|
||||
let peer: FluencePeer;
|
||||
|
||||
describe('Sig service test suite', () => {
|
||||
afterEach(async () => {
|
||||
if (peer) {
|
||||
await peer.stop();
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
peer = new FluencePeer();
|
||||
await peer.start();
|
||||
});
|
||||
|
||||
it('JSON builtin spec', async () => {
|
||||
const script = `
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
;; create
|
||||
(seq
|
||||
(call %init_peer_id% ("json" "obj") ["name" "nested_first" "num" 1] nested_first)
|
||||
(call %init_peer_id% ("json" "obj") ["name" "nested_second" "num" 2] nested_second)
|
||||
)
|
||||
(call %init_peer_id% ("json" "obj") ["name" "outer_first" "num" 0 "nested" nested_first] outer_first)
|
||||
)
|
||||
(seq
|
||||
;; modify
|
||||
(seq
|
||||
(call %init_peer_id% ("json" "put") [outer_first "nested" nested_second] outer_tmp_second)
|
||||
(call %init_peer_id% ("json" "puts") [outer_tmp_second "name" "outer_second" "num" 3] outer_second)
|
||||
)
|
||||
;; stringify and parse
|
||||
(seq
|
||||
(call %init_peer_id% ("json" "stringify") [outer_first] outer_first_string)
|
||||
(call %init_peer_id% ("json" "parse") [outer_first_string] outer_first_parsed)
|
||||
)
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("res" "res") [nested_first nested_second outer_first outer_second outer_first_string outer_first_parsed])
|
||||
)
|
||||
`;
|
||||
const promise = new Promise<any>((resolve) => {
|
||||
peer.internals.regHandler.common('res', 'res', (req) => {
|
||||
resolve(req.args);
|
||||
return {
|
||||
result: {},
|
||||
retCode: 0,
|
||||
};
|
||||
});
|
||||
});
|
||||
const p = peer.internals.createNewParticle(script) as Particle;
|
||||
await peer.internals.initiateParticle(p, doNothing);
|
||||
|
||||
const [nestedFirst, nestedSecond, outerFirst, outerSecond, outerFirstString, outerFirstParsed] = await promise;
|
||||
|
||||
const nfExpected = { name: 'nested_first', num: 1 };
|
||||
const nsExpected = { name: 'nested_second', num: 2 };
|
||||
|
||||
const ofExpected = { name: 'outer_first', nested: nfExpected, num: 0 };
|
||||
const ofString = JSON.stringify(ofExpected);
|
||||
const osExpected = { name: 'outer_second', num: 3, nested: nsExpected };
|
||||
|
||||
expect(nestedFirst).toMatchObject(nfExpected);
|
||||
expect(nestedSecond).toMatchObject(nsExpected);
|
||||
expect(outerFirst).toMatchObject(ofExpected);
|
||||
expect(outerSecond).toMatchObject(osExpected);
|
||||
expect(outerFirstParsed).toMatchObject(ofExpected);
|
||||
expect(outerFirstString).toBe(ofString);
|
||||
});
|
||||
});
|
@ -111,6 +111,29 @@ describe('Tests for default handler', () => {
|
||||
${'array'} | ${'diff'}" | ${[["a", "b", "c"], ["c", "b", "d"]]} | ${0} | ${["a"]}
|
||||
${'array'} | ${'sdiff'}" | ${[["a", "b", "c"], ["c", "b", "d"]]} | ${0} | ${["a", "d"]}
|
||||
|
||||
${'json'} | ${'obj'}" | ${["a", 10, "b", "string", "c", null]} | ${0} | ${{a: 10, b: "string", c: null}}
|
||||
${'json'} | ${'obj'}" | ${["a", 10, "b", "string", "c"]} | ${1} | ${"Expected even number of argument(s). Got 5"}
|
||||
${'json'} | ${'obj'}" | ${[]} | ${0} | ${{}}
|
||||
|
||||
${'json'} | ${'put'}" | ${[{}, "a", 10]} | ${0} | ${{a: 10}}
|
||||
${'json'} | ${'put'}" | ${[{b: 11}, "a", 10]} | ${0} | ${{a: 10, b: 11}}
|
||||
${'json'} | ${'put'}" | ${["a", "a", 11]} | ${1} | ${"Argument 0 expected to be of type object, Got string"}
|
||||
${'json'} | ${'put'}" | ${[{}, "a", 10, "b", 20]} | ${1} | ${"Expected 3 argument(s). Got 5"}
|
||||
${'json'} | ${'put'}" | ${[{}]} | ${1} | ${"Expected 3 argument(s). Got 1"}
|
||||
|
||||
${'json'} | ${'puts'}" | ${[{}, "a", 10]} | ${0} | ${{a: 10}}
|
||||
${'json'} | ${'puts'}" | ${[{b: 11}, "a", 10]} | ${0} | ${{a: 10, b: 11}}
|
||||
${'json'} | ${'puts'}" | ${[{}, "a", 10, "b", "string", "c", null]} | ${0} | ${{a: 10, b: "string", c: null}}
|
||||
${'json'} | ${'puts'}" | ${[{x: "text"}, "a", 10, "b", "string"]} | ${0} | ${{a: 10, b: "string", x: "text"}}
|
||||
${'json'} | ${'puts'}" | ${[{}]} | ${1} | ${"Expected more than 3 argument(s). Got 1"}
|
||||
${'json'} | ${'puts'}" | ${["a", "a", 11]} | ${1} | ${"Argument 0 expected to be of type object, Got string"}
|
||||
|
||||
${'json'} | ${'stringify'}" | ${[{a: 10, b: "string", c: null}]} | ${0} | ${"{\"a\":10,\"b\":\"string\",\"c\":null}"}
|
||||
${'json'} | ${'stringify'}" | ${[1]} | ${1} | ${"Argument 0 expected to be of type object, Got number"}
|
||||
${'json'} | ${'parse'}" | ${["{\"a\":10,\"b\":\"string\",\"c\":null}"]} | ${0} | ${{a: 10, b: "string", c: null}}
|
||||
${'json'} | ${'parse'}" | ${["incorrect"]} | ${1} | ${"Unexpected token i in JSON at position 0"}
|
||||
${'json'} | ${'parse'}" | ${[10]} | ${1} | ${"Argument 0 expected to be of type string, Got number"}
|
||||
|
||||
`.test(
|
||||
//
|
||||
'$fnName with $args expected retcode: $retCode and result: $result',
|
||||
|
@ -18,7 +18,7 @@ import { encode, decode } from 'bs58';
|
||||
import { sha256 } from 'multiformats/hashes/sha2';
|
||||
import { CallServiceResult } from '@fluencelabs/avm';
|
||||
|
||||
import { GenericCallServiceHandler, ResultCodes } from '../commonTypes';
|
||||
import { CallServiceData, GenericCallServiceHandler, ResultCodes } from '../commonTypes';
|
||||
import { jsonify } from '../utils';
|
||||
import Buffer from '../Buffer';
|
||||
|
||||
@ -40,6 +40,23 @@ const errorNotImpl = (methodName: string) => {
|
||||
return error(`The JS implementation of Peer does not support "${methodName}"`);
|
||||
};
|
||||
|
||||
const makeJsonImpl = (args: Array<any>) => {
|
||||
const [obj, ...kvs] = args;
|
||||
|
||||
const toMerge: Record<string, any> = {};
|
||||
for (let i = 0; i < kvs.length / 2; i++) {
|
||||
const k = kvs[i * 2];
|
||||
if (!isString(k)) {
|
||||
return error(`Argument ${k} is expected to be string`);
|
||||
}
|
||||
const v = kvs[i * 2 + 1];
|
||||
toMerge[k] = v;
|
||||
}
|
||||
|
||||
const res = { ...obj, ...toMerge };
|
||||
return success(res);
|
||||
};
|
||||
|
||||
export const builtInServices: Record<string, Record<string, GenericCallServiceHandler>> = {
|
||||
peer: {
|
||||
identify: () => {
|
||||
@ -467,6 +484,81 @@ export const builtInServices: Record<string, Record<string, GenericCallServiceHa
|
||||
return success(sdiff);
|
||||
},
|
||||
},
|
||||
|
||||
json: {
|
||||
obj: (req) => {
|
||||
let err;
|
||||
if ((err = checkForArgumentsCountEven(req, 1))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return makeJsonImpl([{}, ...req.args]);
|
||||
},
|
||||
|
||||
put: (req) => {
|
||||
let err;
|
||||
if ((err = checkForArgumentsCount(req, 3))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if((err = checkForArgumentType(req, 0, "object"))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return makeJsonImpl(req.args);
|
||||
},
|
||||
|
||||
puts: (req) => {
|
||||
let err;
|
||||
if ((err = checkForArgumentsCountOdd(req, 1))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = checkForArgumentsCountMoreThan(req, 3))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if((err = checkForArgumentType(req, 0, "object"))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return makeJsonImpl(req.args);
|
||||
},
|
||||
|
||||
stringify: (req) => {
|
||||
let err;
|
||||
if ((err = checkForArgumentsCount(req, 1))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if((err = checkForArgumentType(req, 0, "object"))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
const [json] = req.args;
|
||||
const res = JSON.stringify(json);
|
||||
return success(res);
|
||||
},
|
||||
|
||||
parse: (req) => {
|
||||
let err;
|
||||
if ((err = checkForArgumentsCount(req, 1))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if((err = checkForArgumentType(req, 0, "string"))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
const [raw] = req.args;
|
||||
try{
|
||||
const json = JSON.parse(raw);
|
||||
return success(json);
|
||||
} catch(err: any) {
|
||||
return error(err.message);
|
||||
}
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
const checkForArgumentsCount = (req: { args: Array<unknown> }, count: number) => {
|
||||
@ -474,3 +566,37 @@ const checkForArgumentsCount = (req: { args: Array<unknown> }, count: number) =>
|
||||
return error(`Expected ${count} argument(s). Got ${req.args.length}`);
|
||||
}
|
||||
};
|
||||
|
||||
const checkForArgumentsCountMoreThan = (req: { args: Array<unknown> }, count: number) => {
|
||||
if (req.args.length < count) {
|
||||
return error(`Expected more than ${count} argument(s). Got ${req.args.length}`);
|
||||
}
|
||||
};
|
||||
|
||||
const checkForArgumentsCountEven = (req: { args: Array<unknown> }, count: number) => {
|
||||
if (req.args.length % 2 === 1) {
|
||||
return error(`Expected even number of argument(s). Got ${req.args.length}`);
|
||||
}
|
||||
};
|
||||
|
||||
const checkForArgumentsCountOdd = (req: { args: Array<unknown> }, count: number) => {
|
||||
if (req.args.length % 2 === 0) {
|
||||
return error(`Expected odd number of argument(s). Got ${req.args.length}`);
|
||||
}
|
||||
};
|
||||
|
||||
const checkForArgumentType = (req: { args: Array<unknown> }, index: number, type: string) => {
|
||||
const actual = typeof req.args[index];
|
||||
if (actual !== type) {
|
||||
return error(`Argument ${index} expected to be of type ${type}, Got ${actual}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const isString = (unknown: unknown): unknown is string => {
|
||||
return unknown !== null && typeof unknown === 'string';
|
||||
};
|
||||
|
||||
export const isObject = (unknown: unknown): unknown is object => {
|
||||
return unknown !== null && typeof unknown === 'object';
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Fluence JS
|
||||
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://doc.fluence.dev/docs/js-sdk)
|
||||
To start developing applications with Fluence JS refer to the official [documentation](https://fluence.dev/docs/build/fluence-js/)
|
||||
|
||||
Fluence JS is an implementation of the Fluence protocol for JavaScript-based environments. It can connect browsers, Node.js applications, and so on to the Fluence p2p network.
|
||||
|
||||
@ -11,6 +11,6 @@ Similar to the [Rust Fluence Peer implementation](https://github.com/fluencelabs
|
||||
- Builtin services
|
||||
|
||||
Fluence JS can call services and functions on the Fluence network, and expose new APIs to the p2p network directly from TypeScript and JavaScript.
|
||||
[Aqua language](https://github.com/fluencelabs/aqua) uses Fluence JS as a compilation target, and they are designed to [work in tandem](https://doc.fluence.dev/docs/js-sdk/3_in_depth#understanding-the-aqua-compiler-output).
|
||||
[Aqua language](https://github.com/fluencelabs/aqua) uses Fluence JS as a compilation target, and they are designed to [work in tandem](https://fluence.dev/docs/build/fluence-js/in-depth#understanding-the-aqua-compiler-output).
|
||||
|
||||
Fluence JS can be used with any framework of your choice \(or even without frameworks\).
|
||||
|
Loading…
Reference in New Issue
Block a user