@ciqol/resenv 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +189 -0
- package/LICENSE +21 -0
- package/README.md +243 -0
- package/SECURITY.md +74 -0
- package/assert-safe-diagnostics.cjs +15 -0
- package/bin/resenv.cjs +91 -0
- package/bin/resenv.mjs +1 -0
- package/commands.cjs +85 -0
- package/docs/build.md +136 -0
- package/docs/dependencies.md +505 -0
- package/docs/doppler.md +146 -0
- package/docs/maintainer-handoff.md +112 -0
- package/docs/maturity.md +61 -0
- package/docs/public-readiness.md +138 -0
- package/docs/release-security.md +134 -0
- package/docs/releasing.md +143 -0
- package/docs/security-exceptions.json +139 -0
- package/docs/security-performance-review.md +150 -0
- package/docs/validation.md +700 -0
- package/doppler/auth.cjs +125 -0
- package/doppler/bridge.cjs +66 -0
- package/doppler/http.cjs +77 -0
- package/doppler/references.cjs +28 -0
- package/doppler/resolve.cjs +58 -0
- package/doppler/system.cjs +99 -0
- package/doppler-worker.cjs +28 -0
- package/doppler-worker.mjs +1 -0
- package/errors.cjs +12 -0
- package/index.cjs +88 -0
- package/index.d.cts +1 -0
- package/index.d.mts +1 -0
- package/index.mjs +1 -0
- package/package.json +89 -0
- package/preload.cjs +31 -0
- package/resolve-commands.cjs +5 -0
- package/resolve-commands.d.cts +1 -0
- package/resolve-commands.d.mts +1 -0
- package/resolve-commands.mjs +1 -0
- package/resolve-doppler.cjs +4 -0
- package/resolve-doppler.d.cts +1 -0
- package/resolve-doppler.d.mts +1 -0
- package/resolve-doppler.mjs +1 -0
- package/resolve.cjs +5 -0
- package/resolve.d.cts +1 -0
- package/resolve.d.mts +1 -0
- package/resolve.mjs +1 -0
- package/types/bin/resenv.d.ts +2 -0
- package/types/src/assert-safe-diagnostics.d.ts +1 -0
- package/types/src/commands.d.ts +4 -0
- package/types/src/doppler/auth.d.ts +19 -0
- package/types/src/doppler/bridge.d.ts +4 -0
- package/types/src/doppler/http.d.ts +9 -0
- package/types/src/doppler/references.d.ts +9 -0
- package/types/src/doppler/resolve.d.ts +9 -0
- package/types/src/doppler/system.d.ts +24 -0
- package/types/src/doppler-worker.d.ts +1 -0
- package/types/src/errors.d.ts +5 -0
- package/types/src/index.d.ts +7 -0
- package/types/src/preload.d.ts +4 -0
- package/types/src/resolve-commands.d.ts +1 -0
- package/types/src/resolve-doppler.d.ts +1 -0
- package/types/src/resolve.d.ts +1 -0
- package/types/src/types.d.ts +9 -0
- package/types/src/values.d.ts +5 -0
- package/values.cjs +20 -0
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ciqol/resenv",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "Replace environment references with their resolved values at application startup",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"tag": "beta",
|
|
9
|
+
"registry": "https://registry.npmjs.org/"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ciqol/resenv.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/ciqol/resenv#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/ciqol/resenv/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"environment",
|
|
21
|
+
"dotenv",
|
|
22
|
+
"secrets",
|
|
23
|
+
"nx"
|
|
24
|
+
],
|
|
25
|
+
"main": "./index.cjs",
|
|
26
|
+
"module": "./index.mjs",
|
|
27
|
+
"types": "./index.d.cts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": {
|
|
31
|
+
"import": "./index.d.mts",
|
|
32
|
+
"require": "./index.d.cts",
|
|
33
|
+
"default": "./index.d.mts"
|
|
34
|
+
},
|
|
35
|
+
"import": "./index.mjs",
|
|
36
|
+
"require": "./index.cjs",
|
|
37
|
+
"default": "./index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./resolve": {
|
|
40
|
+
"types": {
|
|
41
|
+
"import": "./resolve.d.mts",
|
|
42
|
+
"require": "./resolve.d.cts",
|
|
43
|
+
"default": "./resolve.d.mts"
|
|
44
|
+
},
|
|
45
|
+
"import": "./resolve.mjs",
|
|
46
|
+
"require": "./resolve.cjs"
|
|
47
|
+
},
|
|
48
|
+
"./resolve-commands": {
|
|
49
|
+
"types": {
|
|
50
|
+
"import": "./resolve-commands.d.mts",
|
|
51
|
+
"require": "./resolve-commands.d.cts",
|
|
52
|
+
"default": "./resolve-commands.d.mts"
|
|
53
|
+
},
|
|
54
|
+
"import": "./resolve-commands.mjs",
|
|
55
|
+
"require": "./resolve-commands.cjs"
|
|
56
|
+
},
|
|
57
|
+
"./resolve-doppler": {
|
|
58
|
+
"types": {
|
|
59
|
+
"import": "./resolve-doppler.d.mts",
|
|
60
|
+
"require": "./resolve-doppler.d.cts",
|
|
61
|
+
"default": "./resolve-doppler.d.mts"
|
|
62
|
+
},
|
|
63
|
+
"import": "./resolve-doppler.mjs",
|
|
64
|
+
"require": "./resolve-doppler.cjs"
|
|
65
|
+
},
|
|
66
|
+
"./package.json": "./package.json"
|
|
67
|
+
},
|
|
68
|
+
"bin": {
|
|
69
|
+
"resenv": "./bin/resenv.cjs"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=20"
|
|
73
|
+
},
|
|
74
|
+
"dependencies": {},
|
|
75
|
+
"files": [
|
|
76
|
+
"*.cjs",
|
|
77
|
+
"*.mjs",
|
|
78
|
+
"*.d.cts",
|
|
79
|
+
"*.d.mts",
|
|
80
|
+
"doppler",
|
|
81
|
+
"bin",
|
|
82
|
+
"types",
|
|
83
|
+
"README.md",
|
|
84
|
+
"LICENSE",
|
|
85
|
+
"CONTRIBUTING.md",
|
|
86
|
+
"SECURITY.md",
|
|
87
|
+
"docs"
|
|
88
|
+
]
|
|
89
|
+
}
|
package/preload.cjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('./index.cjs');
|
|
4
|
+
var errors = require('./errors.cjs');
|
|
5
|
+
|
|
6
|
+
let activeMode;
|
|
7
|
+
function assertNoPreload() {
|
|
8
|
+
if (activeMode) {
|
|
9
|
+
throw new errors.ResenvError('CONFLICTING_PRELOADS', 'Use the resenv CLI or a resenv preload for this process. Combining them can reinterpret fetched values.');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function resolvePreload(mode) {
|
|
13
|
+
try {
|
|
14
|
+
// A second mode could interpret data fetched by the first as executable input.
|
|
15
|
+
if (activeMode && activeMode !== mode) {
|
|
16
|
+
throw new errors.ResenvError('CONFLICTING_PRELOADS', 'Use one resenv preload per process. To combine Doppler and commands, use resenv run --commands or one library call with commands enabled.');
|
|
17
|
+
}
|
|
18
|
+
if (activeMode) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
activeMode = mode;
|
|
22
|
+
index.resolve(process.env, { replace: true, commands: mode === 'commands' });
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
process.stderr.write(`${index.formatError(err)}\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
exports.assertNoPreload = assertNoPreload;
|
|
31
|
+
exports.resolvePreload = resolvePreload;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve-commands.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve-commands.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './resolve-commands.cjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve-doppler.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve-doppler.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './resolve-doppler.cjs';
|
package/resolve.cjs
ADDED
package/resolve.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve.js'
|
package/resolve.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types/src/resolve.js'
|
package/resolve.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './resolve.cjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function assertSafeDiagnostics(): void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DebugLogger } from 'node:util';
|
|
2
|
+
import type { Environment, ResolveOptions } from './types.js';
|
|
3
|
+
declare function resolveCommands(env: Readonly<Environment>, { commandTimeoutMs }: ResolveOptions, debug: DebugLogger): Environment;
|
|
4
|
+
export { resolveCommands };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Environment } from '../types.js';
|
|
2
|
+
import type { Request } from './http.js';
|
|
3
|
+
import type { CredentialSystem } from './system.js';
|
|
4
|
+
type LoginOptions = {
|
|
5
|
+
readonly cli?: boolean;
|
|
6
|
+
readonly noBrowser?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type LoginDependencies = {
|
|
9
|
+
readonly request?: Request;
|
|
10
|
+
readonly system?: CredentialSystem;
|
|
11
|
+
readonly output?: (text: string) => void;
|
|
12
|
+
readonly interactive?: boolean;
|
|
13
|
+
readonly env?: Readonly<Environment>;
|
|
14
|
+
readonly sleep?: (ms: number) => Promise<unknown>;
|
|
15
|
+
readonly now?: () => number;
|
|
16
|
+
};
|
|
17
|
+
declare function credential(env: Readonly<Environment>, system?: Pick<CredentialSystem, 'read' | 'cliToken'>): Promise<string>;
|
|
18
|
+
declare function login({ cli, noBrowser }?: LoginOptions, { request, system, output, interactive, env, sleep, now }?: LoginDependencies): Promise<'cli' | 'native'>;
|
|
19
|
+
export { credential, login };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type RequestOptions = {
|
|
2
|
+
readonly token?: string;
|
|
3
|
+
readonly body?: Readonly<Record<string, string>>;
|
|
4
|
+
readonly pending?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type Request = (path: string, options?: RequestOptions) => Promise<Record<string, unknown> | null>;
|
|
7
|
+
declare function createClient(fetchImpl?: typeof globalThis.fetch): Request;
|
|
8
|
+
declare function validateToken(token: unknown): string;
|
|
9
|
+
export { createClient, validateToken };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Environment } from '../types.js';
|
|
2
|
+
type Reference = {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly project: string;
|
|
5
|
+
readonly config: string;
|
|
6
|
+
readonly key: string;
|
|
7
|
+
};
|
|
8
|
+
declare function references(env: Readonly<Environment>): Reference[];
|
|
9
|
+
export { references };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Environment } from '../types.js';
|
|
2
|
+
import { credential } from './auth.js';
|
|
3
|
+
import type { Request } from './http.js';
|
|
4
|
+
type ResolveDependencies = {
|
|
5
|
+
readonly request?: Request;
|
|
6
|
+
readonly getCredential?: typeof credential;
|
|
7
|
+
};
|
|
8
|
+
declare function resolveReferences(env: Readonly<Environment>, { request, getCredential }?: ResolveDependencies): Promise<Environment>;
|
|
9
|
+
export { resolveReferences };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SpawnSyncOptionsWithStringEncoding, SpawnSyncReturns } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import type { Environment } from '../types.js';
|
|
4
|
+
type SyncOptions = SpawnSyncOptionsWithStringEncoding & {
|
|
5
|
+
readonly detached?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type SyncRunner = (file: string, args: readonly string[], options: SyncOptions) => SpawnSyncReturns<string>;
|
|
8
|
+
type SystemOptions = {
|
|
9
|
+
readonly platform?: NodeJS.Platform;
|
|
10
|
+
readonly run?: SyncRunner;
|
|
11
|
+
readonly exists?: typeof existsSync;
|
|
12
|
+
};
|
|
13
|
+
export type CredentialSystem = ReturnType<typeof createSystem>;
|
|
14
|
+
declare function helperEnvironment(): Environment;
|
|
15
|
+
declare function createSystem({ platform, run, exists }?: SystemOptions): {
|
|
16
|
+
read: () => string | undefined;
|
|
17
|
+
write: (token: string) => void;
|
|
18
|
+
remove: () => void;
|
|
19
|
+
cliToken: () => string | undefined;
|
|
20
|
+
cliLogin: () => void;
|
|
21
|
+
openBrowser: (url: string) => boolean;
|
|
22
|
+
canStore: boolean;
|
|
23
|
+
};
|
|
24
|
+
export { createSystem, helperEnvironment };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ResenvError } from './errors.js';
|
|
2
|
+
import type { Environment, ResolveOptions } from './types.js';
|
|
3
|
+
export type { Environment, ResolveOptions } from './types.js';
|
|
4
|
+
/** Always return a resolved copy; optionally commit replacements to the input. */
|
|
5
|
+
declare function resolve(env?: Readonly<Environment>, options?: ResolveOptions): Environment;
|
|
6
|
+
declare function formatError(error: unknown): string;
|
|
7
|
+
export { ResenvError, resolve, formatError };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './resolve.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type Environment = Record<string, string | undefined>;
|
|
2
|
+
export type ResolveOptions = {
|
|
3
|
+
/** Also replace values in the input environment. Default false; always return a copy. */
|
|
4
|
+
readonly replace?: boolean;
|
|
5
|
+
/** Execute whole-value $(command) expressions using /bin/sh. Default false. */
|
|
6
|
+
readonly commands?: boolean;
|
|
7
|
+
/** Per-command timeout in milliseconds. Default 30000. */
|
|
8
|
+
readonly commandTimeoutMs?: number;
|
|
9
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Environment } from './types.js';
|
|
2
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
export declare function isEnvironment(value: unknown): value is Environment;
|
|
4
|
+
export declare function hasErrorCode(err: unknown, code: string): boolean;
|
|
5
|
+
export declare function copyEnvironment(env: Readonly<Environment>): Environment;
|
package/values.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function isEnvironment(value) {
|
|
7
|
+
return isRecord(value) && Object.values(value).every(item => typeof item === 'string' || item === undefined);
|
|
8
|
+
}
|
|
9
|
+
function hasErrorCode(err, code) {
|
|
10
|
+
return isRecord(err) && err.code === code;
|
|
11
|
+
}
|
|
12
|
+
function copyEnvironment(env) {
|
|
13
|
+
// This assertion describes the empty dictionary we create, not external data.
|
|
14
|
+
return Object.assign(Object.create(null), env);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.copyEnvironment = copyEnvironment;
|
|
18
|
+
exports.hasErrorCode = hasErrorCode;
|
|
19
|
+
exports.isEnvironment = isEnvironment;
|
|
20
|
+
exports.isRecord = isRecord;
|