Skip to content

Commit 75530e6

Browse files
committed
feat(utils): create new utils package
Former-commit-id: 785f955
1 parent 9b4b278 commit 75530e6

13 files changed

+592
-1
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,28 @@ The core of the Semaphore protocol is in the [circuit logic](/packages/circuits/
233233
</a>
234234
</td>
235235
</tr>
236+
<tr>
237+
<td>
238+
<a href="/packages/utils">
239+
@semaphore-protocol/utils
240+
</a>
241+
<a href="https://js.semaphore.pse.dev/modules/_semaphore_protocol_utils">
242+
(docs)
243+
</a>
244+
</td>
245+
<td>
246+
<!-- NPM version -->
247+
<a href="https://npmjs.org/package/@semaphore-protocol/utils">
248+
<img src="https://img.shields.io/npm/v/@semaphore-protocol/utils.svg?style=flat-square" alt="NPM version" />
249+
</a>
250+
</td>
251+
<td>
252+
<!-- Downloads -->
253+
<a href="https://npmjs.org/package/@semaphore-protocol/utils">
254+
<img src="https://img.shields.io/npm/dm/@semaphore-protocol/utils.svg?style=flat-square" alt="Downloads" />
255+
</a>
256+
</td>
257+
</tr>
236258
<tr>
237259
<td>
238260
<a href="/packages/heyauthn">

packages/utils/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Ethereum Foundation
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/utils/README.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<p align="center">
2+
<h1 align="center">
3+
Semaphore utils
4+
</h1>
5+
<p align="center">A library to provide utility functions to the other Semaphore packages.</p>
6+
</p>
7+
8+
<p align="center">
9+
<a href="https://github.com/semaphore-protocol">
10+
<img src="https://img.shields.io/badge/project-Semaphore-blue.svg?style=flat-square">
11+
</a>
12+
<a href="https://github.com/semaphore-protocol/semaphore/blob/main/LICENSE">
13+
<img alt="NPM license" src="https://img.shields.io/npm/l/%40semaphore-protocol%2Futils?style=flat-square">
14+
</a>
15+
<a href="https://www.npmjs.com/package/@semaphore-protocol/utils">
16+
<img alt="NPM version" src="https://img.shields.io/npm/v/@semaphore-protocol/utils?style=flat-square" />
17+
</a>
18+
<a href="https://npmjs.org/package/@semaphore-protocol/utils">
19+
<img alt="Downloads" src="https://img.shields.io/npm/dm/@semaphore-protocol/utils.svg?style=flat-square" />
20+
</a>
21+
<a href="https://js.semaphore.pse.dev/utils">
22+
<img alt="Documentation typedoc" src="https://img.shields.io/badge/docs-typedoc-744C7C?style=flat-square">
23+
</a>
24+
<a href="https://eslint.org/">
25+
<img alt="Linter eslint" src="https://img.shields.io/badge/linter-eslint-8080f2?style=flat-square&logo=eslint" />
26+
</a>
27+
<a href="https://prettier.io/">
28+
<img alt="Code style prettier" src="https://img.shields.io/badge/code%20style-prettier-f8bc45?style=flat-square&logo=prettier" />
29+
</a>
30+
</p>
31+
32+
<div align="center">
33+
<h4>
34+
<a href="https://github.com/semaphore-protocol/semaphore/blob/main/CONTRIBUTING.md">
35+
👥 Contributing
36+
</a>
37+
<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
38+
<a href="https://github.com/semaphore-protocol/semaphore/blob/main/CODE_OF_CONDUCT.md">
39+
🤝 Code of conduct
40+
</a>
41+
<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
42+
<a href="https://github.com/semaphore-protocol/semaphore/contribute">
43+
🔎 Issues
44+
</a>
45+
<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
46+
<a href="https://semaphore.pse.dev/discord">
47+
🗣️ Chat &amp; Support
48+
</a>
49+
</h4>
50+
</div>
51+
52+
> [!NOTE]
53+
> Please, for more information on the modules provided by this library, see its code documentation [here](https://js.semaphore.pse.dev/modules/_semaphore_protocol_utils).
54+
55+
## 🛠 Install
56+
57+
### npm or yarn
58+
59+
Install the `@semaphore-protocol/utils` package with npm:
60+
61+
```bash
62+
npm i @semaphore-protocol/utils
63+
```
64+
65+
or yarn:
66+
67+
```bash
68+
yarn add @semaphore-protocol/utils
69+
```
70+
71+
## 📜 Usage
72+
73+
```typescript
74+
// You can import modules from the main bundle.
75+
import { errors, types } from "@semaphore-protocol/utils"
76+
77+
// Or by using conditional exports.
78+
import { requireNumber } from "@semaphore-protocol/utils/errors"
79+
import { isNumber } from "@semaphore-protocol/utils/types"
80+
```

packages/utils/build.tsconfig.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"baseUrl": ".",
5+
"declarationDir": "dist/types"
6+
},
7+
"include": ["src"]
8+
}

packages/utils/package.json

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@semaphore-protocol/utils",
3+
"version": "4.0.0-alpha.8",
4+
"description": "A library to provide utility functions to the other Semaphore packages.",
5+
"type": "module",
6+
"license": "MIT",
7+
"main": "dist/index.js",
8+
"types": "dist/types/index.d.ts",
9+
"exports": {
10+
".": {
11+
"types": "./dist/types/index.d.ts",
12+
"require": "./dist/index.cjs",
13+
"default": "./dist/index.js"
14+
},
15+
"./errors": {
16+
"types": "./dist/types/errors.d.ts",
17+
"require": "./dist/lib.commonjs/errors.cjs",
18+
"default": "./dist/lib.esm/errors.js"
19+
},
20+
"./types": {
21+
"types": "./dist/types/types.d.ts",
22+
"require": "./dist/lib.commonjs/types.cjs",
23+
"default": "./dist/lib.esm/types.js"
24+
}
25+
},
26+
"files": [
27+
"dist/",
28+
"src/",
29+
"LICENSE",
30+
"README.md"
31+
],
32+
"repository": "https://github.com/semaphore-protocol/semaphore",
33+
"homepage": "https://github.com/semaphore-protocol/semaphore/tree/main/packages/utils",
34+
"bugs": {
35+
"url": "https://github.com/semaphore-protocol/semaphore.git/issues"
36+
},
37+
"scripts": {
38+
"build": "rimraf dist && rollup -c rollup.config.ts --configPlugin typescript",
39+
"prepublishOnly": "yarn build"
40+
},
41+
"publishConfig": {
42+
"access": "public"
43+
},
44+
"devDependencies": {
45+
"rollup-plugin-cleanup": "^3.2.1",
46+
"rollup-plugin-typescript2": "^0.36.0"
47+
}
48+
}

packages/utils/rollup.config.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as fs from "fs"
2+
import cleanup from "rollup-plugin-cleanup"
3+
import typescript from "rollup-plugin-typescript2"
4+
5+
const pkg = JSON.parse(fs.readFileSync("./package.json", "utf-8"))
6+
const banner = `/**
7+
* @module ${pkg.name}
8+
* @version ${pkg.version}
9+
* @file ${pkg.description}
10+
* @copyright Ethereum Foundation 2024
11+
* @license ${pkg.license}
12+
* @see [Github]{@link ${pkg.homepage}}
13+
*/`
14+
15+
export default {
16+
input: "src/index.ts",
17+
output: [
18+
{ file: pkg.exports["."].require, format: "cjs", banner, exports: "auto" },
19+
{ file: pkg.exports["."].default, format: "es", banner },
20+
{ dir: "./dist/lib.commonjs", format: "cjs", banner, preserveModules: true },
21+
{ dir: "./dist/lib.esm", format: "es", banner, preserveModules: true }
22+
],
23+
plugins: [
24+
typescript({
25+
tsconfig: "./build.tsconfig.json",
26+
useTsconfigDeclarationDir: true
27+
}),
28+
cleanup({ comments: "jsdoc" })
29+
]
30+
}

packages/utils/src/errors.ts

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* @module Errors
3+
* This module is designed to provide utility functions for validating
4+
* function parameters. It includes functions that throw type errors if
5+
* the parameters do not meet specified criteria, such as being defined,
6+
* a number, a string, a function, or an array. This module helps ensure
7+
* that functions receive the correct types of inputs, enhancing code
8+
* reliability and reducing runtime errors.
9+
*/
10+
11+
import {
12+
SupportedType,
13+
isArray,
14+
isDefined,
15+
isFunction,
16+
isNumber,
17+
isString,
18+
isSupportedType,
19+
isType,
20+
isUint8Array
21+
} from "./types"
22+
23+
/**
24+
* It throws a type error if the parameter value has not been defined.
25+
* @param parameterValue The parameter value.
26+
* @param parameterName The parameter name.
27+
*/
28+
export function requireDefined(parameterValue: any, parameterName: string) {
29+
if (!isDefined(parameterValue)) {
30+
throw new TypeError(`Parameter '${parameterName}' is not defined`)
31+
}
32+
}
33+
34+
/**
35+
* It throws a type error if the parameter value is not a number.
36+
* @param parameterValue The parameter value.
37+
* @param parameterName The parameter name.
38+
*/
39+
export function requireNumber(parameterValue: number, parameterName: string) {
40+
if (!isNumber(parameterValue)) {
41+
throw new TypeError(`Parameter '${parameterName}' is not a number`)
42+
}
43+
}
44+
45+
/**
46+
* It throws a type error if the parameter value is not a string.
47+
* @param parameterValue The parameter value.
48+
* @param parameterName The parameter name.
49+
*/
50+
export function requireString(parameterValue: string, parameterName: string) {
51+
if (!isString(parameterValue)) {
52+
throw new TypeError(`Parameter '${parameterName}' is not a string`)
53+
}
54+
}
55+
56+
/**
57+
* It throws a type error if the parameter value is not a function.
58+
* @param parameterValue The parameter value.
59+
* @param parameterName The parameter name.
60+
*/
61+
export function requireFunction(parameterValue: Function, parameterName: string) {
62+
if (!isFunction(parameterValue)) {
63+
throw new TypeError(`Parameter '${parameterName}' is not a function`)
64+
}
65+
}
66+
67+
/**
68+
* It throws a type error if the parameter value is not an array.
69+
* @param parameterValue The parameter value.
70+
* @param parameterName The parameter name.
71+
*/
72+
export function requireArray(parameterValue: any[], parameterName: string) {
73+
if (!isArray(parameterValue)) {
74+
throw new TypeError(`Parameter '${parameterName}' is not an array`)
75+
}
76+
}
77+
78+
/**
79+
* It throws a type error if the parameter value is not a uint8array.
80+
* @param parameterValue The parameter value.
81+
* @param parameterName The parameter name.
82+
*/
83+
export function requireUint8Array(parameterValue: Uint8Array, parameterName: string) {
84+
if (!isUint8Array(parameterValue)) {
85+
throw new TypeError(`Parameter '${parameterName}' is not a Uint8Array`)
86+
}
87+
}
88+
89+
/**
90+
* It throws a type error if the parameter value type is not part of the list of types.
91+
* @param parameterValue The parameter value.
92+
* @param parameterName The parameter name.
93+
*/
94+
export function requireTypes(parameterValue: any, parameterName: string, types: SupportedType[]) {
95+
for (const type of types) {
96+
if (!isSupportedType(type)) {
97+
throw new Error(`Type '${type}' is not supported`)
98+
}
99+
}
100+
101+
for (const type of types) {
102+
if (isType(parameterValue, type)) {
103+
return
104+
}
105+
}
106+
107+
throw new TypeError(`Parameter '${parameterName}' is none of the following types: ${types.join(", ")}`)
108+
}

packages/utils/src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import * as errors from "./errors"
2+
import * as types from "./types"
3+
4+
export { errors, types }

0 commit comments

Comments
 (0)