build: ship pre-built API bundle; images copy output instead of installing

- API: `pnpm build` bundles dist/ into apps/api/.output (esbuild), with
  Linux musl native packages for sharp and argon2 kept alongside
- docker/api.Dockerfile copies that output; no pnpm install on the server
- add dist/migrate.js (prisma migrate deploy equivalent, same
  _prisma_migrations table and lock) so the Prisma CLI is not needed at runtime
- pnpm-workspace: supportedArchitectures for linux/x64/musl
- admin: apps/admin/.env.production sets VITE_SITE_URL for the production build
- drop NPM_REGISTRY / SITE_URL build args from compose and .env.example
- gitignore: anchor node_modules rules so pre-built node_modules are committed
- README: describe the pre-built deploy flow

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
S. Esmaeili
2026-10-24 14:41:31 +03:30
co-authored by Claude Haiku 5.5
parent ee8258556d
commit 10e453e4be
692 changed files with 303601 additions and 147 deletions
@@ -0,0 +1,3 @@
# `@node-rs/argon2-linux-x64-musl`
This is the **x86_64-unknown-linux-musl** binary for `@node-rs/argon2`
@@ -0,0 +1,42 @@
{
"name": "@node-rs/argon2-linux-x64-musl",
"version": "2.2.2",
"cpu": [
"x64"
],
"main": "argon2.linux-x64-musl.node",
"files": [
"argon2.linux-x64-musl.node"
],
"description": "argon2-rust binding for Node.js",
"keywords": [
"argon2",
"argon2-password",
"crypto",
"encryption",
"hash",
"hashing",
"password",
"secure",
"verify"
],
"homepage": "https://github.com/napi-rs/node-rs",
"license": "MIT",
"engines": {
"node": ">= 10"
},
"repository": {
"type": "git",
"url": "git+https://github.com/napi-rs/node-rs.git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
},
"os": [
"linux"
],
"libc": [
"musl"
]
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-present LongYinan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+166
View File
@@ -0,0 +1,166 @@
# `@node-rs/argon2`
![](https://github.com/napi-rs/node-rs/workflows/CI/badge.svg)
![](https://img.shields.io/npm/dm/@node-rs/argon2.svg?sanitize=true)
[argon2-rust](https://crates.io/crates/argon2-rust) binding for Node.js.
Argon2 is a [key derivation function](https://en.wikipedia.org/wiki/Key_derivation_function) that was selected as the winner of the [Password Hashing Competition(PHC)](https://password-hashing.net) in July 2015.
Argon2 summarizes the state of the art in the design of memory-hard functions and can be used to hash passwords for credential storage, key derivation, or other applications.
It has a simple design aimed at the highest memory filling rate and effective use of multiple computing units, while still providing defense against tradeoff attacks (by exploiting the cache and memory organization of the recent processors).
## Features
- Faster than node-argon2 and `node:crypto.argon2` at the same m/t/p (see Benchmarks).
- No node-gyp and postinstall.
- Cross-platform support, including [Apple M1](https://www.apple.com/newsroom/2020/11/apple-unleashes-m1/).
- Smaller file size after npm installation(476K vs [node-argon2](https://github.com/ranisalt/node-argon2) 3.7M).
- `@node-rs/argon2` supports all three algorithms:
- Argon2i: Optimizes against GPU cracking attacks but vulnerable to side-channels.
Accesses the memory array in a password dependent order, reducing the possibility of time–memory tradeoff (TMTO) attacks.
- Argon2d: Optimized to resist side-channel attacks.
Accesses the memory array in a password independent order, increasing the possibility of time-memory tradeoff (TMTO) attacks.
- **Argon2id**: default value, this is the default algorithm for normative recommendations.
Hybrid that mixes Argon2i and Argon2d passes.
Uses the Argon2i approach for the first half pass over memory and Argon2d approach for subsequent passes. This effectively places it in the “middle” between the other two: it doesn’t provide as good TMTO/GPU cracking resistance as Argon2d, nor as good of side-channel resistance as Argon2i, but overall provides the most well-rounded approach to both classes of attacks.
# Benchmarks
Comparing each library's **defaults** is not 1:1. `@node-rs/argon2` defaults to `m=19456,t=2,p=1`; `argon2` (node-argon2) defaults to `m=65536,t=3,p=4`. See [#841](https://github.com/napi-rs/node-rs/issues/841).
This bench pins the same password, salt, Argon2id v=19, m, t, p, and 32-byte tag. Only the **raw** KDF is timed. The tag is asserted equal on every run. Native impls are interleaved with each other; JS/wasm are a separate group so a 7 ms hash is not timed after a 400 ms JS loop.
Apple M5 Max / arm64 / Node 24 / [argon2-rust 1.1.0](https://crates.io/crates/argon2-rust). Median ms. See [benchmark/](benchmark/argon2.ts).
**Native async raw** — same calling shape as node-argon2 (no sync API there):
| params | @node-rs/argon2 | node-argon2 | node:crypto |
| --------------------- | --------------: | ----------: | ----------: |
| m=19456 KiB, t=2, p=1 | **7.58** | 15.41 | 13.05 |
| m=65536 KiB, t=3, p=1 | **49.35** | 84.57 | 71.71 |
| m=65536 KiB, t=3, p=4 | **13.62** | 22.54 | 20.83 |
**JS / wasm raw** — same params, same tags:
| params | hash-wasm | @noble/hashes |
| --------------------- | --------: | ------------: |
| m=19456 KiB, t=2, p=1 | 19.79 | 86.14 |
| m=65536 KiB, t=3, p=1 | 104.09 | 433.07 |
| m=65536 KiB, t=3, p=4 | 106.06 | 435.39 |
hash-wasm and `@noble/hashes` do not run lanes in parallel, so their p=4 row is the p=1 work.
## API
```typescript
export const enum Algorithm {
Argon2d = 0,
Argon2i = 1,
Argon2id = 2,
}
export const enum Version {
/** Version 16 (0x10 in hex) */
V0x10 = 0,
/**
* Default value
* Version 19 (0x13 in hex, default)
*/
V0x13 = 1,
}
export interface Options {
/**
* The amount of memory to be used by the hash function, in kilobytes. Each thread will have a memory pool of this size. Note that large values for highly concurrent usage will cause starvation and thrashing if your system memory gets full.
*
* Value is an integer in decimal (1 to 10 digits), between 1 and (2^32)-1.
*
* The default value is 19456, meaning a pool of 19 MiB per thread.
*/
memoryCost?: number | undefined | null
/**
* The time cost is the amount of passes (iterations) used by the hash function. It increases hash strength at the cost of time required to compute.
*
* Value is an integer in decimal (1 to 10 digits), between 1 and (2^32)-1.
*
* The default value is 2.
*/
timeCost?: number | undefined | null
/**
* The hash length is the length of the hash function output in bytes. Note that the resulting hash is encoded with Base 64, so the digest will be ~1/3 longer.
*
* The default value is 32, which produces raw hashes of 32 bytes or digests of 43 characters.
*/
outputLen?: number | undefined | null
/**
* The amount of threads to compute the hash on. Each thread has a memory pool with memoryCost size. Note that changing it also changes the resulting hash.
*
* Value is an integer in decimal (1 to 3 digits), between 1 and 255.
*
* The default value is 1, meaning a single thread is used.
*/
parallelism?: number | undefined | null
algorithm?: Algorithm | undefined | null
version?: Version | undefined | null
secret?: Buffer | undefined | null
}
export function hash(
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<string>
export function verify(
hashed: string | Buffer,
password: string | Buffer,
options?: Options | undefined | null,
abortSignal?: AbortSignal | undefined | null,
): Promise<boolean>
```
## `parseOptions` — needs-rehash checks
`parseOptions` parses an encoded PHC hash string and returns the parameters it was created with. Compare them against your current policy to decide whether a stored hash should be rehashed at next login.
```typescript
import { Algorithm, parseOptions, Version } from '@node-rs/argon2'
const POLICY = {
algorithm: Algorithm.Argon2id,
version: Version.V0x13,
memoryCost: 19456,
timeCost: 2,
parallelism: 1,
outputLen: 32,
} as const
function needsRehash(hashed: string): boolean {
const parsed = parseOptions(hashed)
return (
parsed.algorithm !== POLICY.algorithm ||
parsed.version !== POLICY.version ||
parsed.memoryCost !== POLICY.memoryCost ||
parsed.timeCost !== POLICY.timeCost ||
parsed.parallelism !== POLICY.parallelism ||
parsed.outputLen !== POLICY.outputLen ||
parsed.saltLen < 16
)
}
```
```typescript
export interface ParsedHashOptions {
algorithm: Algorithm
version: Version
/** Memory cost in kibibytes (`m=` in the PHC string). */
memoryCost: number
/** Time cost / number of passes (`t=` in the PHC string). */
timeCost: number
/** Degree of parallelism (`p=` in the PHC string). */
parallelism: number
/** Length of the raw hash output in bytes. */
outputLen: number
/** Byte length of the decoded salt. This package generates 16-byte salts; older hashes may carry shorter ones. */
saltLen: number
}
export function parseOptions(hashed: string | Uint8Array): ParsedHashOptions
```
+1
View File
@@ -0,0 +1 @@
export * from '@node-rs/argon2-wasm32-wasi'
+104
View File
@@ -0,0 +1,104 @@
/* auto-generated by NAPI-RS */
/* eslint-disable */
export declare const enum Algorithm {
/**
* Optimizes against GPU cracking attacks but vulnerable to side-channels.
* Accesses the memory array in a password dependent order, reducing the possibility of time–memory tradeoff (TMTO) attacks.
*/
Argon2d = 0,
/**
* Optimized to resist side-channel attacks.
* Accesses the memory array in a password independent order, increasing the possibility of time-memory tradeoff (TMTO) attacks.
*/
Argon2i = 1,
/**
* Default value, this is the default algorithm for normative recommendations.
* Hybrid that mixes Argon2i and Argon2d passes.
* Uses the Argon2i approach for the first half pass over memory and Argon2d approach for subsequent passes. This effectively places it in the “middle” between the other two: it doesn’t provide as good TMTO/GPU cracking resistance as Argon2d, nor as good of side-channel resistance as Argon2i, but overall provides the most well-rounded approach to both classes of attacks.
*/
Argon2id = 2
}
export declare function hash(password: string | Uint8Array, options?: Options | undefined | null, abortSignal?: AbortSignal | undefined | null): Promise<string>
export declare function hashRaw(password: string | Uint8Array, options?: Options | undefined | null, abortSignal?: AbortSignal | undefined | null): Promise<Buffer>
export declare function hashRawSync(password: string | Uint8Array, options?: Options | undefined | null): Buffer
export declare function hashSync(password: string | Uint8Array, options?: Options | undefined | null): string
export interface Options {
/**
* The amount of memory to be used by the hash function, in kilobytes. Each thread will have a memory pool of this size. Note that large values for highly concurrent usage will cause starvation and thrashing if your system memory gets full.
*
* Value is an integer in decimal (1 to 10 digits), between 1 and (2^32)-1.
*
* The default value is 19456, meaning a pool of 19 MiB per thread.
*/
memoryCost?: number
/**
* The time cost is the amount of passes (iterations) used by the hash function. It increases hash strength at the cost of time required to compute.
*
* Value is an integer in decimal (1 to 10 digits), between 1 and (2^32)-1.
*
* The default value is 2.
*/
timeCost?: number
/**
* The hash length is the length of the hash function output in bytes. Note that the resulting hash is encoded with Base 64, so the digest will be ~1/3 longer.
*
* The default value is 32, which produces raw hashes of 32 bytes or digests of 43 characters.
*/
outputLen?: number
/**
* The amount of threads to compute the hash on. Each thread has a memory pool with memoryCost size. Note that changing it also changes the resulting hash.
*
* Value is an integer in decimal (1 to 3 digits), between 1 and 255.
*
* The default value is 1, meaning a single thread is used.
*/
parallelism?: number
algorithm?: Algorithm
version?: Version
secret?: Uint8Array
salt?: Uint8Array
}
export interface ParsedHashOptions {
algorithm: Algorithm
version: Version
/** Memory cost in kibibytes (`m=` in the PHC string). */
memoryCost: number
/** Time cost / number of passes (`t=` in the PHC string). */
timeCost: number
/** Degree of parallelism (`p=` in the PHC string). */
parallelism: number
/** Length of the raw hash output in bytes. */
outputLen: number
/**
* Byte length of the decoded salt. This package generates 16-byte salts;
* older hashes may carry shorter ones.
*/
saltLen: number
}
/**
* Parses an encoded argon2 hash string (PHC format) and returns the parameters
* it was created with. Useful for "needs rehash" checks: compare the returned
* parameters against your current policy and rehash when they differ.
*/
export declare function parseOptions(hashed: string | Uint8Array): ParsedHashOptions
export declare function verify(hashed: string | Uint8Array, password: string | Uint8Array, options?: Options | undefined | null, abortSignal?: AbortSignal | undefined | null): Promise<boolean>
export declare function verifySync(hashed: string | Uint8Array, password: string | Uint8Array, options?: Options | undefined | null): boolean
export declare const enum Version {
/** Version 16 (0x10 in hex) */
V0x10 = 0,
/**
* Default value
* Version 19 (0x13 in hex)
*/
V0x13 = 1
}
+711
View File
@@ -0,0 +1,711 @@
// prettier-ignore
/* eslint-disable */
// @ts-nocheck
/* auto-generated by NAPI-RS */
const { readFileSync } = require('fs')
let nativeBinding = null
const loadErrors = []
const isMusl = () => {
let musl = false
if (process.platform === 'linux') {
musl = isMuslFromFilesystem()
if (musl === null) {
musl = isMuslFromReport()
}
if (musl === null) {
musl = isMuslFromChildProcess()
}
}
return musl
}
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
const isMuslFromFilesystem = () => {
try {
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
} catch {
return null
}
}
const isMuslFromReport = () => {
let report = null
if (process.report && typeof process.report.getReport === 'function') {
process.report.excludeNetwork = true
report = process.report.getReport()
}
if (!report) {
return null
}
if (report.header && report.header.glibcVersionRuntime) {
return false
}
if (Array.isArray(report.sharedObjects)) {
if (report.sharedObjects.some(isFileMusl)) {
return true
}
}
return false
}
const isMuslFromChildProcess = () => {
try {
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
} catch (e) {
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
return false
}
}
function requireNative() {
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
try {
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
} catch (err) {
loadErrors.push(err)
}
} else if (process.platform === 'android') {
if (process.arch === 'arm64') {
try {
return require('./argon2.android-arm64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-android-arm64')
const bindingPackageVersion = require('@node-rs/argon2-android-arm64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'arm') {
try {
return require('./argon2.android-arm-eabi.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-android-arm-eabi')
const bindingPackageVersion = require('@node-rs/argon2-android-arm-eabi/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`))
}
} else if (process.platform === 'win32') {
if (process.arch === 'x64') {
if ((process.config && process.config.variables && process.config.variables.shlib_suffix === 'dll.a') || (process.config && process.config.variables && process.config.variables.node_target_type === 'shared_library')) {
try {
return require('./argon2.win32-x64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-win32-x64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-win32-x64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.win32-x64-msvc.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-win32-x64-msvc')
const bindingPackageVersion = require('@node-rs/argon2-win32-x64-msvc/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'ia32') {
try {
return require('./argon2.win32-ia32-msvc.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-win32-ia32-msvc')
const bindingPackageVersion = require('@node-rs/argon2-win32-ia32-msvc/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'arm64') {
try {
return require('./argon2.win32-arm64-msvc.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-win32-arm64-msvc')
const bindingPackageVersion = require('@node-rs/argon2-win32-arm64-msvc/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`))
}
} else if (process.platform === 'darwin') {
try {
return require('./argon2.darwin-universal.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-darwin-universal')
const bindingPackageVersion = require('@node-rs/argon2-darwin-universal/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
if (process.arch === 'x64') {
try {
return require('./argon2.darwin-x64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-darwin-x64')
const bindingPackageVersion = require('@node-rs/argon2-darwin-x64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'arm64') {
try {
return require('./argon2.darwin-arm64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-darwin-arm64')
const bindingPackageVersion = require('@node-rs/argon2-darwin-arm64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`))
}
} else if (process.platform === 'freebsd') {
if (process.arch === 'x64') {
try {
return require('./argon2.freebsd-x64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-freebsd-x64')
const bindingPackageVersion = require('@node-rs/argon2-freebsd-x64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'arm64') {
try {
return require('./argon2.freebsd-arm64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-freebsd-arm64')
const bindingPackageVersion = require('@node-rs/argon2-freebsd-arm64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`))
}
} else if (process.platform === 'linux') {
if (process.arch === 'x64') {
if (isMusl()) {
try {
return require('./argon2.linux-x64-musl.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-x64-musl')
const bindingPackageVersion = require('@node-rs/argon2-linux-x64-musl/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.linux-x64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-x64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-x64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'arm64') {
if (isMusl()) {
try {
return require('./argon2.linux-arm64-musl.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-arm64-musl')
const bindingPackageVersion = require('@node-rs/argon2-linux-arm64-musl/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.linux-arm64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-arm64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-arm64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'arm') {
if (isMusl()) {
try {
return require('./argon2.linux-arm-musleabihf.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-arm-musleabihf')
const bindingPackageVersion = require('@node-rs/argon2-linux-arm-musleabihf/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.linux-arm-gnueabihf.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-arm-gnueabihf')
const bindingPackageVersion = require('@node-rs/argon2-linux-arm-gnueabihf/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'loong64') {
if (isMusl()) {
try {
return require('./argon2.linux-loong64-musl.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-loong64-musl')
const bindingPackageVersion = require('@node-rs/argon2-linux-loong64-musl/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.linux-loong64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-loong64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-loong64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'riscv64') {
if (isMusl()) {
try {
return require('./argon2.linux-riscv64-musl.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-riscv64-musl')
const bindingPackageVersion = require('@node-rs/argon2-linux-riscv64-musl/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
try {
return require('./argon2.linux-riscv64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-riscv64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-riscv64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
}
} else if (process.arch === 'ppc64') {
try {
return require('./argon2.linux-ppc64-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-ppc64-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-ppc64-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 's390x') {
try {
return require('./argon2.linux-s390x-gnu.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-linux-s390x-gnu')
const bindingPackageVersion = require('@node-rs/argon2-linux-s390x-gnu/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`))
}
} else if (process.platform === 'openharmony') {
if (process.arch === 'arm64') {
try {
return require('./argon2.openharmony-arm64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-openharmony-arm64')
const bindingPackageVersion = require('@node-rs/argon2-openharmony-arm64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'x64') {
try {
return require('./argon2.openharmony-x64.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-openharmony-x64')
const bindingPackageVersion = require('@node-rs/argon2-openharmony-x64/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else if (process.arch === 'arm') {
try {
return require('./argon2.openharmony-arm.node')
} catch (e) {
loadErrors.push(e)
}
try {
const binding = require('@node-rs/argon2-openharmony-arm')
const bindingPackageVersion = require('@node-rs/argon2-openharmony-arm/package.json').version
if (bindingPackageVersion !== '2.1.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
return binding
} catch (e) {
loadErrors.push(e)
}
} else {
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`))
}
} else {
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`))
}
}
function createLoadErrorChain(errors) {
return errors.reduce((previous, current) => {
let message
try {
message =
current && typeof current.message === 'string'
? current.message
: String(current)
} catch {
message = 'Unknown error'
}
const error = new Error(message)
error.cause = previous
return error
}, null)
}
// NAPI_RS_FORCE_WASI is a tri-state flag:
// unset / any other value → native binding preferred, WASI is only a fallback
// 'true' → prefer WASI, but retain native as a lazy fallback
// 'error' → require WASI without initializing a native fallback
// Treating any non-empty string as truthy (the historical behavior) meant
// NAPI_RS_FORCE_WASI=false, NAPI_RS_FORCE_WASI=0, etc. inadvertently triggered
// the WASI path, causing ENOENT for packages shipped without a .wasi.cjs file.
//
// NAPI_RS_WASI_FLAVOR selects one exact generated flavor and implies strict
// WASI loading. It never crosses into another flavor or falls back to native.
const __napiWasiFlavors = ["wasm32-wasi"]
const __napiWasiFlavor = process.env.NAPI_RS_WASI_FLAVOR
const __napiWasiFlavorRequested =
typeof __napiWasiFlavor === 'string' && __napiWasiFlavor.length > 0
if (
__napiWasiFlavorRequested &&
__napiWasiFlavors.indexOf(__napiWasiFlavor) === -1
) {
throw new Error(
'Unsupported WASI flavor "' +
__napiWasiFlavor +
'". Available flavors: ' +
__napiWasiFlavors.join(', '),
)
}
const forceWasiError = process.env.NAPI_RS_FORCE_WASI === 'error'
const forceWasi =
process.env.NAPI_RS_FORCE_WASI === 'true' ||
forceWasiError ||
__napiWasiFlavorRequested
if (!forceWasi) {
nativeBinding = requireNative()
}
if (!nativeBinding || forceWasi) {
let wasiBinding = null
let wasiBindingLoaded = false
const wasiBindingErrors = []
const __napiWasiResolveCandidate = (specifier, isPackage, localArtifacts) => {
try {
require.resolve(specifier)
} catch (resolveError) {
if (!resolveError || resolveError.code !== 'MODULE_NOT_FOUND') {
throw resolveError
}
if (isPackage) {
try {
require.resolve(specifier + '/package.json')
} catch (packageError) {
if (packageError && packageError.code === 'MODULE_NOT_FOUND') {
return resolveError
}
// An exports restriction proves the package exists even when its
// package.json is not public. Preserve the root resolution failure.
throw resolveError
}
// The package exists but its main/export target is broken.
throw resolveError
}
return resolveError
}
if (localArtifacts) {
let artifactError = null
for (let i = 0; i < localArtifacts.length; i++) {
try {
require.resolve(localArtifacts[i])
return null
} catch (resolveError) {
if (!resolveError || resolveError.code !== 'MODULE_NOT_FOUND') {
throw resolveError
}
artifactError = resolveError
}
}
return artifactError
}
return null
}
if (!wasiBindingLoaded && (!__napiWasiFlavorRequested || __napiWasiFlavor === "wasm32-wasi")) {
let candidateError = null
let candidateFailed = false
try {
candidateError = __napiWasiResolveCandidate('./argon2.wasi.cjs', false, ["./argon2.wasm32-wasi.debug.wasm","./argon2.wasm32-wasi.wasm"])
candidateFailed = candidateError !== null
if (!candidateFailed) {
wasiBinding = require('./argon2.wasi.cjs')
nativeBinding = wasiBinding
wasiBindingLoaded = true
}
} catch (err) {
candidateError = err
candidateFailed = true
}
if (candidateFailed) {
wasiBindingErrors.push(candidateError)
loadErrors.push(candidateError)
}
}
if (!wasiBindingLoaded && (!__napiWasiFlavorRequested || __napiWasiFlavor === "wasm32-wasi")) {
let candidateError = null
let candidateFailed = false
try {
candidateError = __napiWasiResolveCandidate('@node-rs/argon2-wasm32-wasi', true, undefined)
candidateFailed = candidateError !== null
if (!candidateFailed) {
if (process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
const bindingPackageVersion = require('@node-rs/argon2-wasm32-wasi/package.json').version
if (bindingPackageVersion !== '2.1.0') {
throw new Error(`WASI binding package version mismatch, expected 2.1.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}
}
wasiBinding = require('@node-rs/argon2-wasm32-wasi')
nativeBinding = wasiBinding
wasiBindingLoaded = true
}
} catch (err) {
candidateError = err
candidateFailed = true
}
if (candidateFailed) {
wasiBindingErrors.push(candidateError)
loadErrors.push(candidateError)
}
}
if (
!wasiBindingLoaded &&
forceWasi &&
!forceWasiError &&
!__napiWasiFlavorRequested
) {
nativeBinding = requireNative()
}
if ((forceWasiError || __napiWasiFlavorRequested) && !wasiBindingLoaded) {
const error = new Error(
__napiWasiFlavorRequested
? 'WASI binding for flavor "' + __napiWasiFlavor + '" not found'
: 'WASI binding not found and NAPI_RS_FORCE_WASI is set to error',
)
error.cause = createLoadErrorChain(wasiBindingErrors)
throw error
}
}
if (!nativeBinding) {
if (loadErrors.length > 0) {
const error = new Error(
`Cannot find native binding. ` +
`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
'Please try `npm i` again after removing both package-lock.json and node_modules directory.',
)
// assign instead of the `new Error(message, { cause })` options form,
// which Node < 16.9 silently ignores
error.cause = createLoadErrorChain(loadErrors)
throw error
}
throw new Error(`Failed to load native binding`)
}
module.exports = nativeBinding
module.exports.Algorithm = nativeBinding.Algorithm
module.exports.hash = nativeBinding.hash
module.exports.hashRaw = nativeBinding.hashRaw
module.exports.hashRawSync = nativeBinding.hashRawSync
module.exports.hashSync = nativeBinding.hashSync
module.exports.parseOptions = nativeBinding.parseOptions
module.exports.verify = nativeBinding.verify
module.exports.verifySync = nativeBinding.verifySync
module.exports.Version = nativeBinding.Version
+95
View File
@@ -0,0 +1,95 @@
{
"name": "@node-rs/argon2",
"version": "2.2.2",
"description": "argon2-rust binding for Node.js",
"keywords": [
"argon2",
"argon2-password",
"crypto",
"encryption",
"hash",
"hashing",
"password",
"secure",
"verify"
],
"homepage": "https://github.com/napi-rs/node-rs",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/napi-rs/node-rs.git"
},
"files": [
"browser.js",
"index.d.ts",
"index.js"
],
"main": "index.js",
"browser": "browser.js",
"types": "index.d.ts",
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"artifacts": "napi artifacts -d ../../artifacts",
"bench": "cross-env NODE_ENV=production node --import @oxc-node/core/register benchmark/argon2.ts",
"build": "oxnode ./build.ts --platform --release",
"build:debug": "oxnode ./build.ts --platform",
"prepublishOnly": "napi prepublish",
"version": "napi version"
},
"devDependencies": {
"@napi-rs/cli": "^3.10.8",
"@noble/hashes": "^2.3.0",
"@oxc-node/cli": "^0.1.0",
"@oxc-node/core": "^0.1.0",
"argon2": "^0.45.1",
"cross-env": "^10.1.0",
"hash-wasm": "^4.12.0",
"tinybench": "^6.1.3"
},
"napi": {
"binaryName": "argon2",
"targets": [
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
"aarch64-linux-android",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"aarch64-pc-windows-msvc",
"armv7-unknown-linux-gnueabihf",
"x86_64-unknown-linux-musl",
"x86_64-unknown-freebsd",
"i686-pc-windows-msvc",
"armv7-linux-androideabi",
"wasm32-wasip1-threads"
],
"wasm": {
"browser": {
"fs": false
}
}
},
"engines": {
"node": ">= 10"
},
"gitHead": "b706e3035f5d4d487ae66ea0549a041cd509e5d4",
"optionalDependencies": {
"@node-rs/argon2-darwin-x64": "2.2.2",
"@node-rs/argon2-darwin-arm64": "2.2.2",
"@node-rs/argon2-win32-x64-msvc": "2.2.2",
"@node-rs/argon2-linux-x64-gnu": "2.2.2",
"@node-rs/argon2-android-arm64": "2.2.2",
"@node-rs/argon2-linux-arm64-gnu": "2.2.2",
"@node-rs/argon2-linux-arm64-musl": "2.2.2",
"@node-rs/argon2-win32-arm64-msvc": "2.2.2",
"@node-rs/argon2-linux-arm-gnueabihf": "2.2.2",
"@node-rs/argon2-linux-x64-musl": "2.2.2",
"@node-rs/argon2-freebsd-x64": "2.2.2",
"@node-rs/argon2-win32-ia32-msvc": "2.2.2",
"@node-rs/argon2-android-arm-eabi": "2.2.2"
}
}