Simplify exports

This commit is contained in:
Cayman 2022-04-13 14:36:07 -05:00
parent 501f93e333
commit 269c96832b
No known key found for this signature in database
GPG Key ID: 54B21AEC3C53E1F5
11 changed files with 57 additions and 78 deletions

View File

@ -19,10 +19,10 @@ To use native bindings you must install peer dependency `@chainsafe/blst`
yarn add @chainsafe/bls @chainsafe/blst
```
You must initialize the library once in your application before using it. The result is cached and use across all your imports
By default, native bindings will be used if in NodeJS and they are installed. A WASM implementation ("herumi") is used as a fallback in case any error occurs.
```ts
import {init, SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bls";
import {SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bls";
(async () => {
await init("herumi");
@ -45,7 +45,7 @@ import {init, SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bl
### Browser
If you are in the browser, import from `/herumi` to import directly the WASM version
If you are in the browser, import from `/herumi` to explicitly import the WASM version
```ts
import bls from "@chainsafe/bls/herumi";
@ -53,7 +53,7 @@ import bls from "@chainsafe/bls/herumi";
### Native bindings only
If you are in NodeJS, import from `/blst-native` to skip browser specific code. Also install peer dependency `@chainsafe/blst` which has the native bindings
If you are in NodeJS, import from `/blst-native` to explicitly import the native bindings. Also install peer dependency `@chainsafe/blst` which has the native bindings
```bash
yarn add @chainsafe/bls @chainsafe/blst
@ -63,23 +63,27 @@ yarn add @chainsafe/bls @chainsafe/blst
import bls from "@chainsafe/bls/blst-native";
```
### Native bindings + WASM fallback
### Get implementation at runtime
If you want to offer a fallback in NodeJS, first try to load native bindings and then fallback to WASM. Also install peer dependency `@chainsafe/blst` which has the native bindings
```bash
yarn add @chainsafe/bls @chainsafe/blst
```
If you need to get a bls implementation at runtime, import from `/getImplementation`.
```ts
import {init} from "@chainsafe/bls";
import {getImplementation} from "@chainsafe/bls/getImplementation";
try {
await init("blst-native");
} catch (e) {
await init("herumi");
console.warn("Using WASM");
}
const bls = await getImplementation("herumi");
```
### Switchable singleton
If you need a singleton that is switchable at runtime (the default behavior in <=v6), import from `/switchable`.
```ts
import bls, {init} from "@chainsafe/bls/switchable";
// here `bls` is uninitialized
await init("herumi");
// here `bls` is initialized
// now other modules can `import bls from "@chainsafe/bls/switchable"` and it will be initialized
```
The API is identical for all implementations.

View File

@ -7,14 +7,14 @@
".": {
"import": "./lib/index.js"
},
"./register": {
"import": "./register.js"
},
"./types": {
"import": "./lib/types.js"
},
"./default": {
"import": "./lib/default.js"
"./getImplementation": {
"import": "./lib/getImplementation.js"
},
"./switchable": {
"import": "./lib/switchable.js"
},
"./blst-native": {
"import": "./lib/blst-native/index.js"

View File

@ -1,12 +0,0 @@
// -----------------------------------------
// To be used in NodeJS testing environments
// node -r @chainsafe/bls/register
// -----------------------------------------
// blst-native initialization is syncronous
// Initialize bls here instead of in before() so it's available inside describe() blocks
import("./lib/index.js").then(({init}) => init("blst-native")).catch((e) => {
// eslint-disable-next-line no-console
console.error(e);
process.exit(1);
});

View File

@ -7,13 +7,6 @@ export * from "../constants.js";
export {SecretKey, PublicKey, Signature};
export async function init(): Promise<void> {
// Native bindings require no init() call
}
export function destroy(): void {
// Native bindings require no destroy() call
}
export const bls: IBls = {
implementation: "blst-native",
SecretKey,
@ -21,8 +14,6 @@ export const bls: IBls = {
Signature,
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
init,
destroy,
};
export default bls;

View File

@ -1,14 +0,0 @@
import type {IBls} from "./interface.js";
import {getImplementation} from "./getImplementation.js";
// Thanks https://github.com/iliakan/detect-node/blob/master/index.esm.js
const isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
let bls: IBls;
try {
bls = await getImplementation(isNode ? "blst-native" : "herumi");
} catch (e) {
bls = await getImplementation("herumi");
}
export default bls;

View File

@ -6,9 +6,7 @@ const isNode = Object.prototype.toString.call(typeof process !== "undefined" ? p
export async function getImplementation(impl: Implementation = "herumi"): Promise<IBls> {
switch (impl) {
case "herumi": {
const blsHerumi = (await import("./herumi/index.js")).bls;
await blsHerumi.init();
return blsHerumi;
return (await import("./herumi/index.js")).bls;
}
case "blst-native":

View File

@ -4,6 +4,9 @@ import {Signature} from "./signature.js";
import {init, destroy} from "./context.js";
import {IBls} from "../interface.js";
import {functionalInterfaceFactory} from "../functional.js";
await init();
export * from "../constants.js";
export {SecretKey, PublicKey, Signature, init, destroy};
@ -15,8 +18,6 @@ export const bls: IBls = {
Signature,
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
init,
destroy,
};
export default bls;

View File

@ -1,16 +1,14 @@
import type {IBls, Implementation} from "./interface.js";
import type {IBls} from "./interface.js";
import {getImplementation} from "./getImplementation.js";
export {IBls, Implementation, CoordType, PointFormat} from "./interface.js";
// Thanks https://github.com/iliakan/detect-node/blob/master/index.esm.js
const isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
// TODO: Use a Proxy for example to throw an error if it's not initialized yet
export const bls: IBls = {} as IBls;
export default bls;
export async function init(impl: Implementation): Promise<void> {
// Using Object.assign instead of just bls = getImplementation()
// because otherwise the default import breaks. The reference is lost
// and the imported object is still undefined after calling init()
const blsImpl = await getImplementation(impl);
Object.assign(bls, blsImpl);
let bls: IBls;
try {
bls = await getImplementation(isNode ? "blst-native" : "herumi");
} catch (e) {
bls = await getImplementation("herumi");
}
export default bls;

View File

@ -12,9 +12,6 @@ export interface IBls {
verifyMultiple(publicKeys: Uint8Array[], messages: Uint8Array[], signature: Uint8Array): boolean;
verifyMultipleSignatures(sets: {publicKey: Uint8Array; message: Uint8Array; signature: Uint8Array}[]): boolean;
secretKeyToPublicKey(secretKey: Uint8Array): Uint8Array;
init(): Promise<void>;
destroy(): void;
}
export declare class SecretKey {

16
src/switchable.ts Normal file
View File

@ -0,0 +1,16 @@
import type {IBls, Implementation} from "./interface.js";
import {getImplementation} from "./getImplementation.js";
export * from "./interface.js";
// TODO: Use a Proxy for example to throw an error if it's not initialized yet
const bls: IBls = {} as IBls;
export default bls;
export async function init(impl: Implementation): Promise<void> {
// Using Object.assign instead of just bls = getImplementation()
// because otherwise the default import breaks. The reference is lost
// and the imported object is still undefined after calling init()
const blsImpl = await getImplementation(impl);
Object.assign(bls, blsImpl);
}

View File

@ -3,7 +3,7 @@
"compilerOptions": {
"outDir": "lib",
"target": "es2019",
"module": "es2022",
"module": "esnext",
"moduleResolution": "Node",
"pretty": true,
"lib": ["esnext.bigint", "DOM"],