Skip to content

Commit b8f318a

Browse files
committed
feat: add schema.secret type
1 parent 724ce4e commit b8f318a

File tree

4 files changed

+81
-4
lines changed

4 files changed

+81
-4
lines changed

src/env.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
* file that was distributed with this source code.
88
*/
99

10-
import { schema as envSchema } from '@poppinss/validator-lite'
1110
import type { ValidateFn } from '@poppinss/validator-lite/types'
1211

1312
import { EnvParser } from './parser.ts'
1413
import { EnvValidator } from './validator.ts'
1514
import { EnvProcessor } from './processor.ts'
15+
import { schema as envSchema } from './schema.ts'
1616

1717
/**
1818
* A wrapper over "process.env" with types information.

src/parser.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
* file that was distributed with this source code.
88
*/
99

10+
import { readFile } from 'node:fs/promises'
1011
import dotenv, { type DotenvParseOutput } from 'dotenv'
12+
import { RuntimeException } from '@poppinss/utils/exception'
13+
1114
import { type EnvIdentifierCallback } from './types.ts'
1215
import { E_IDENTIFIER_ALREADY_DEFINED } from './errors.ts'
13-
import { readFile } from 'node:fs/promises'
14-
import { RuntimeException } from '@poppinss/utils/exception'
1516

1617
/**
1718
* Env parser parses the environment variables from a string formatted

src/schema.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* @adonisjs/env
3+
*
4+
* (c) AdonisJS
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
import { Secret } from '@poppinss/utils'
11+
import { type Prettify } from '@poppinss/utils/types'
12+
import { schema as envSchema } from '@poppinss/validator-lite'
13+
import { type SchemaFnOptions } from '@poppinss/validator-lite/types'
14+
15+
function secret(options?: SchemaFnOptions) {
16+
return function validate(key: string, value?: string): Secret<string> {
17+
if (!value) {
18+
throw new Error(options?.message ?? `Missing environment variable "${key}"`)
19+
}
20+
return new Secret(value)
21+
}
22+
}
23+
24+
/**
25+
* Same as the Secret rule, but allows non-existing values too
26+
*/
27+
secret.optional = function optionalString() {
28+
return function validate(_: string, value?: string): Secret<string> | undefined {
29+
if (!value) {
30+
return undefined
31+
}
32+
return new Secret(value)
33+
}
34+
}
35+
36+
/**
37+
* Same as the optional rule, but allows a condition to decide when to
38+
* validate the value
39+
*/
40+
secret.optionalWhen = function optionalWhenString(
41+
condition: boolean | ((key: string, value?: string) => boolean),
42+
options?: SchemaFnOptions
43+
) {
44+
return function validate(key: string, value?: string): Secret<string> | undefined {
45+
if (typeof condition === 'function' ? condition(key, value) : condition) {
46+
return secret.optional()(key, value)
47+
}
48+
49+
return secret(options)(key, value)
50+
}
51+
}
52+
53+
export const schema: Prettify<
54+
typeof envSchema & {
55+
secret: typeof secret
56+
}
57+
> = {
58+
...envSchema,
59+
secret,
60+
}

tests/validator.spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
import { test } from '@japa/runner'
1111
import string from '@poppinss/utils/string'
12-
import { schema } from '@poppinss/validator-lite'
12+
13+
import { schema } from '../src/schema.ts'
1314
import { EnvValidator } from '../src/validator.ts'
1415
import { E_INVALID_ENV_VARIABLES } from '../src/errors.ts'
16+
import { Secret } from '@poppinss/utils'
1517

1618
test.group('Env Validator', () => {
1719
test('validate values against pre-defined schema', async ({ assert, expectTypeOf }) => {
@@ -103,4 +105,18 @@ test.group('Env Validator', () => {
103105
expectTypeOf(output).toEqualTypeOf<{ PORT: number }>()
104106
assert.deepEqual(output, { PORT: 3333 })
105107
})
108+
109+
test('convert value to a secret', async ({ assert, expectTypeOf }) => {
110+
const validator = new EnvValidator({
111+
PASSWORD: schema.secret(),
112+
})
113+
114+
const values = { PASSWORD: 'helloworld' }
115+
const output = validator.validate(values)
116+
expectTypeOf(output).toEqualTypeOf<{ PASSWORD: Secret<string> }>()
117+
118+
assert.instanceOf(output.PASSWORD, Secret)
119+
assert.equal(output.PASSWORD.release(), 'helloworld')
120+
assert.deepEqual(values, { PASSWORD: 'helloworld' })
121+
})
106122
})

0 commit comments

Comments
 (0)