1/**
2 * Node-compatible implementation of Effect's `Crypto` service.
3 *
4 * This module builds the service from `node:crypto`, using `randomBytes` for
5 * random data and `createHash` for supported digest algorithms. It exports
6 * `make` as the concrete service value and `layer` for providing it through
7 * Effect context.
8 *
9 * @since 1.0.0
10 */
11import * as EffectCrypto from "effect/Crypto"
12import * as Effect from "effect/Effect"
13import * as Layer from "effect/Layer"
14import * as PlatformError from "effect/PlatformError"
15import * as NodeCrypto from "node:crypto"
16
17const toHashAlgorithm = (algorithm: EffectCrypto.DigestAlgorithm): string => {
18 switch (algorithm) {
19 case "SHA-1":
20 return "sha1"
21 case "SHA-256":
22 return "sha256"
23 case "SHA-384":
24 return "sha384"
25 case "SHA-512":
26 return "sha512"
27 }
28}
29
30const digest: EffectCrypto.Crypto["digest"] = (algorithm, data) =>
31 Effect.try({
32 try: () => Uint8Array.from(NodeCrypto.createHash(toHashAlgorithm(algorithm)).update(data).digest()),
33 catch: (cause) =>
34 PlatformError.systemError({
35 module: "Crypto",
36 method: "digest",
37 _tag: "Unknown",
38 description: "Could not compute digest",
39 cause
40 })
41 })
42
43/**
44 * The default Node.js Crypto service implementation.
45 *
46 * @category constructors
47 * @since 1.0.0
48 */
49export const make: EffectCrypto.Crypto = EffectCrypto.make({
50 randomBytes: NodeCrypto.randomBytes,
51 digest
52})
53
54/**
55 * Layer that provides the Node.js Crypto service implementation.
56 *
57 * @category layers
58 * @since 1.0.0
59 */
60export const layer: Layer.Layer<EffectCrypto.Crypto> = Layer.succeed(EffectCrypto.Crypto, make)