@kanjijs/config 0.2.0-beta.13 → 0.2.0-beta.15
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/dist/config/src/index.d.ts +14 -0
- package/dist/contracts/src/index.d.ts +27 -0
- package/dist/core/src/context.d.ts +7 -0
- package/dist/core/src/decorators.d.ts +34 -0
- package/dist/core/src/di/container.d.ts +26 -0
- package/dist/core/src/di/module-compiler.d.ts +11 -0
- package/dist/core/src/exceptions/exception.filter.d.ts +3 -0
- package/dist/core/src/exceptions/http.exception.d.ts +7 -0
- package/dist/core/src/index.d.ts +9 -0
- package/dist/core/src/metadata.d.ts +64 -0
- package/dist/index.js +479 -451
- package/package.json +2 -2
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type DynamicModule } from "@kanjijs/core";
|
|
2
|
+
import type { ZodSchema } from "zod";
|
|
3
|
+
export interface ConfigModuleOptions {
|
|
4
|
+
envFilePath?: string;
|
|
5
|
+
schema?: ZodSchema;
|
|
6
|
+
}
|
|
7
|
+
export declare class ConfigService<T = Record<string, unknown>> {
|
|
8
|
+
private readonly internalConfig;
|
|
9
|
+
constructor(internalConfig: T);
|
|
10
|
+
get<K extends keyof T>(key: K): T[K];
|
|
11
|
+
}
|
|
12
|
+
export declare class ConfigModule {
|
|
13
|
+
static forRoot(options?: ConfigModuleOptions): DynamicModule;
|
|
14
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type SchemaLike = unknown;
|
|
2
|
+
export interface ContractRequestSpec<T = SchemaLike> {
|
|
3
|
+
params?: T;
|
|
4
|
+
query?: T;
|
|
5
|
+
headers?: T;
|
|
6
|
+
cookies?: T;
|
|
7
|
+
body?: T;
|
|
8
|
+
}
|
|
9
|
+
export interface ContractResponseSpec<T = SchemaLike> {
|
|
10
|
+
[status: number]: T;
|
|
11
|
+
}
|
|
12
|
+
export interface ContractSpec<T = SchemaLike> {
|
|
13
|
+
request?: ContractRequestSpec<T>;
|
|
14
|
+
response?: ContractResponseSpec<T>;
|
|
15
|
+
}
|
|
16
|
+
export interface ValidatorAdapter<S = SchemaLike> {
|
|
17
|
+
parse<O = unknown>(schema: S, data: unknown): Promise<{
|
|
18
|
+
success: true;
|
|
19
|
+
data: O;
|
|
20
|
+
} | {
|
|
21
|
+
success: false;
|
|
22
|
+
issues: unknown[];
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export declare class Contract {
|
|
26
|
+
static json<T = SchemaLike>(spec: ContractRequestSpec<T>): ContractSpec<T>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
export interface RequestContext {
|
|
3
|
+
requestId: string;
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
}
|
|
6
|
+
export declare const kanjijsContext: AsyncLocalStorage<RequestContext>;
|
|
7
|
+
export declare function getRequestId(): string | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ContractSpec } from "@kanjijs/contracts";
|
|
2
|
+
import { type ModuleMetadata, type Token } from "./metadata";
|
|
3
|
+
/**
|
|
4
|
+
* @Module({ controllers: [...] })
|
|
5
|
+
*/
|
|
6
|
+
export declare function Module(metadata: ModuleMetadata): ClassDecorator;
|
|
7
|
+
/**
|
|
8
|
+
* @Contract({ ... })
|
|
9
|
+
*/
|
|
10
|
+
export declare function Contract(spec: ContractSpec): MethodDecorator;
|
|
11
|
+
/**
|
|
12
|
+
* @Controller('/users')
|
|
13
|
+
*/
|
|
14
|
+
export declare function Controller(prefix?: string): ClassDecorator;
|
|
15
|
+
export declare function Injectable(): ClassDecorator;
|
|
16
|
+
export declare const Get: (path?: string) => MethodDecorator;
|
|
17
|
+
export declare const Post: (path?: string) => MethodDecorator;
|
|
18
|
+
export declare const Put: (path?: string) => MethodDecorator;
|
|
19
|
+
export declare const Delete: (path?: string) => MethodDecorator;
|
|
20
|
+
export declare const Patch: (path?: string) => MethodDecorator;
|
|
21
|
+
/**
|
|
22
|
+
* @Inject("DATABASE_CLIENT")
|
|
23
|
+
*/
|
|
24
|
+
export declare function Inject(token: Token<unknown>): ParameterDecorator;
|
|
25
|
+
/**
|
|
26
|
+
* @Use(middleware1, middleware2)
|
|
27
|
+
* Attaches middlewares to a controller or method.
|
|
28
|
+
*/
|
|
29
|
+
export declare function Use(...middlewares: unknown[]): MethodDecorator & ClassDecorator;
|
|
30
|
+
export declare const Body: (data?: string) => ParameterDecorator;
|
|
31
|
+
export declare const Query: (data?: string) => ParameterDecorator;
|
|
32
|
+
export declare const Param: (data?: string) => ParameterDecorator;
|
|
33
|
+
export declare const Headers: (data?: string) => ParameterDecorator;
|
|
34
|
+
export declare const Ctx: (data?: string) => ParameterDecorator;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Constructor, type Token } from "../metadata";
|
|
2
|
+
import "reflect-metadata";
|
|
3
|
+
export declare class KanjijsIoC {
|
|
4
|
+
private static providers;
|
|
5
|
+
static register<T>(target: Constructor<T>): void;
|
|
6
|
+
static register<T>(token: Token<T>, provider: {
|
|
7
|
+
useValue?: T;
|
|
8
|
+
useClass?: Constructor<T>;
|
|
9
|
+
}): void;
|
|
10
|
+
static resolve<T>(target: Token<T>): T;
|
|
11
|
+
static clear(): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* V2 STRICT CONTAINER
|
|
15
|
+
* Instance-based, no auto-registration, explicit visibility.
|
|
16
|
+
*/
|
|
17
|
+
export declare class Container {
|
|
18
|
+
private providers;
|
|
19
|
+
register<T>(token: Token<T>, provider: {
|
|
20
|
+
useValue?: T;
|
|
21
|
+
useClass?: Constructor<T>;
|
|
22
|
+
useFactory?: (...args: unknown[]) => T;
|
|
23
|
+
inject?: Array<Token<unknown>>;
|
|
24
|
+
}): void;
|
|
25
|
+
resolve<T>(token: Token<T>): T;
|
|
26
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Constructor } from "../metadata";
|
|
2
|
+
import { Container } from "./container";
|
|
3
|
+
export declare class ModuleCompiler {
|
|
4
|
+
private nodes;
|
|
5
|
+
private globalExportedTokens;
|
|
6
|
+
compile(rootModule: Constructor): Container;
|
|
7
|
+
private scan;
|
|
8
|
+
private processProviders;
|
|
9
|
+
private validate;
|
|
10
|
+
private checkDependencies;
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { ContractRequestSpec, ContractResponseSpec, ContractSpec, SchemaLike, ValidatorAdapter, } from "@kanjijs/contracts";
|
|
2
|
+
export * from "./context";
|
|
3
|
+
export * from "./decorators";
|
|
4
|
+
export * from "./di/container";
|
|
5
|
+
export * from "./di/module-compiler";
|
|
6
|
+
export * from "./exceptions/exception.filter";
|
|
7
|
+
export * from "./exceptions/http.exception";
|
|
8
|
+
export * from "./metadata";
|
|
9
|
+
export declare const GLOBAL_MIDDLEWARE_TOKEN: unique symbol;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ContractSpec } from "@kanjijs/contracts";
|
|
2
|
+
import "reflect-metadata";
|
|
3
|
+
export type Constructor<T = unknown> = new (...args: unknown[]) => T;
|
|
4
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
5
|
+
export type RouteParamType = "BODY" | "QUERY" | "PARAM" | "HEADERS" | "CONTEXT";
|
|
6
|
+
export interface RouteParamMetadata {
|
|
7
|
+
index: number;
|
|
8
|
+
type: RouteParamType;
|
|
9
|
+
data?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RouteMetadata {
|
|
12
|
+
method: HttpMethod;
|
|
13
|
+
path: string;
|
|
14
|
+
contract?: ContractSpec;
|
|
15
|
+
middlewares?: unknown[];
|
|
16
|
+
params?: RouteParamMetadata[];
|
|
17
|
+
}
|
|
18
|
+
export interface ControllerMetadata {
|
|
19
|
+
prefix: string;
|
|
20
|
+
middlewares?: unknown[];
|
|
21
|
+
}
|
|
22
|
+
export type Token<T = unknown> = string | symbol | Constructor<T>;
|
|
23
|
+
export type Provider<T = unknown> = Constructor<T> | {
|
|
24
|
+
provide: Token<T>;
|
|
25
|
+
useValue: T;
|
|
26
|
+
} | {
|
|
27
|
+
provide: Token<T>;
|
|
28
|
+
useClass: Constructor<T>;
|
|
29
|
+
} | {
|
|
30
|
+
provide: Token<T>;
|
|
31
|
+
useFactory: (...args: unknown[]) => T | Promise<T>;
|
|
32
|
+
inject?: Token[];
|
|
33
|
+
};
|
|
34
|
+
export interface DynamicModule {
|
|
35
|
+
module: Constructor;
|
|
36
|
+
providers?: Provider[];
|
|
37
|
+
imports?: Array<Constructor | DynamicModule>;
|
|
38
|
+
exports?: Token[];
|
|
39
|
+
global?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface ModuleMetadata {
|
|
42
|
+
controllers?: Constructor[];
|
|
43
|
+
providers?: Provider[];
|
|
44
|
+
imports?: Array<Constructor | DynamicModule>;
|
|
45
|
+
exports?: Token[];
|
|
46
|
+
global?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface IMetadataStorage {
|
|
49
|
+
addRoute(target: object, methodName: string, meta: RouteMetadata): void;
|
|
50
|
+
addContract(target: object, methodName: string, contract: ContractSpec): void;
|
|
51
|
+
addMiddleware(target: object, middleware: unknown, methodName?: string): void;
|
|
52
|
+
getRoutes(target: object): Map<string, RouteMetadata> | undefined;
|
|
53
|
+
setController(target: object, meta: ControllerMetadata): void;
|
|
54
|
+
getController(target: object): ControllerMetadata | undefined;
|
|
55
|
+
defineModule(target: object, meta: ModuleMetadata): void;
|
|
56
|
+
getModule(target: object): ModuleMetadata | undefined;
|
|
57
|
+
addInjection(target: object, index: number, token: Token<unknown>): void;
|
|
58
|
+
getInjections(target: object): Map<number, Token<unknown>> | undefined;
|
|
59
|
+
addRouteParam(target: object, methodName: string, param: RouteParamMetadata): void;
|
|
60
|
+
}
|
|
61
|
+
declare global {
|
|
62
|
+
var KANJI_METADATA_STORAGE: IMetadataStorage | undefined;
|
|
63
|
+
}
|
|
64
|
+
export declare const MetadataStorage: IMetadataStorage;
|
package/dist/index.js
CHANGED
|
@@ -28,396 +28,22 @@ var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
|
28
28
|
};
|
|
29
29
|
var __require = import.meta.require;
|
|
30
30
|
|
|
31
|
-
// ../../node_modules/.bun/
|
|
32
|
-
var
|
|
33
|
-
module.exports = {
|
|
34
|
-
name: "dotenv",
|
|
35
|
-
version: "16.6.1",
|
|
36
|
-
description: "Loads environment variables from .env file",
|
|
37
|
-
main: "lib/main.js",
|
|
38
|
-
types: "lib/main.d.ts",
|
|
39
|
-
exports: {
|
|
40
|
-
".": {
|
|
41
|
-
types: "./lib/main.d.ts",
|
|
42
|
-
require: "./lib/main.js",
|
|
43
|
-
default: "./lib/main.js"
|
|
44
|
-
},
|
|
45
|
-
"./config": "./config.js",
|
|
46
|
-
"./config.js": "./config.js",
|
|
47
|
-
"./lib/env-options": "./lib/env-options.js",
|
|
48
|
-
"./lib/env-options.js": "./lib/env-options.js",
|
|
49
|
-
"./lib/cli-options": "./lib/cli-options.js",
|
|
50
|
-
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
51
|
-
"./package.json": "./package.json"
|
|
52
|
-
},
|
|
53
|
-
scripts: {
|
|
54
|
-
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
55
|
-
lint: "standard",
|
|
56
|
-
pretest: "npm run lint && npm run dts-check",
|
|
57
|
-
test: "tap run --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
58
|
-
"test:coverage": "tap run --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
|
|
59
|
-
prerelease: "npm test",
|
|
60
|
-
release: "standard-version"
|
|
61
|
-
},
|
|
62
|
-
repository: {
|
|
63
|
-
type: "git",
|
|
64
|
-
url: "git://github.com/motdotla/dotenv.git"
|
|
65
|
-
},
|
|
66
|
-
homepage: "https://github.com/motdotla/dotenv#readme",
|
|
67
|
-
funding: "https://dotenvx.com",
|
|
68
|
-
keywords: [
|
|
69
|
-
"dotenv",
|
|
70
|
-
"env",
|
|
71
|
-
".env",
|
|
72
|
-
"environment",
|
|
73
|
-
"variables",
|
|
74
|
-
"config",
|
|
75
|
-
"settings"
|
|
76
|
-
],
|
|
77
|
-
readmeFilename: "README.md",
|
|
78
|
-
license: "BSD-2-Clause",
|
|
79
|
-
devDependencies: {
|
|
80
|
-
"@types/node": "^18.11.3",
|
|
81
|
-
decache: "^4.6.2",
|
|
82
|
-
sinon: "^14.0.1",
|
|
83
|
-
standard: "^17.0.0",
|
|
84
|
-
"standard-version": "^9.5.0",
|
|
85
|
-
tap: "^19.2.0",
|
|
86
|
-
typescript: "^4.8.4"
|
|
87
|
-
},
|
|
88
|
-
engines: {
|
|
89
|
-
node: ">=12"
|
|
90
|
-
},
|
|
91
|
-
browser: {
|
|
92
|
-
fs: false
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// ../../node_modules/.bun/dotenv@16.6.1/node_modules/dotenv/lib/main.js
|
|
98
|
-
var require_main = __commonJS((exports, module) => {
|
|
99
|
-
var fs = __require("fs");
|
|
100
|
-
var path = __require("path");
|
|
101
|
-
var os = __require("os");
|
|
102
|
-
var crypto2 = __require("crypto");
|
|
103
|
-
var packageJson = require_package();
|
|
104
|
-
var version = packageJson.version;
|
|
105
|
-
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
106
|
-
function parse(src) {
|
|
107
|
-
const obj = {};
|
|
108
|
-
let lines = src.toString();
|
|
109
|
-
lines = lines.replace(/\r\n?/mg, `
|
|
110
|
-
`);
|
|
111
|
-
let match;
|
|
112
|
-
while ((match = LINE.exec(lines)) != null) {
|
|
113
|
-
const key = match[1];
|
|
114
|
-
let value = match[2] || "";
|
|
115
|
-
value = value.trim();
|
|
116
|
-
const maybeQuote = value[0];
|
|
117
|
-
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
118
|
-
if (maybeQuote === '"') {
|
|
119
|
-
value = value.replace(/\\n/g, `
|
|
120
|
-
`);
|
|
121
|
-
value = value.replace(/\\r/g, "\r");
|
|
122
|
-
}
|
|
123
|
-
obj[key] = value;
|
|
124
|
-
}
|
|
125
|
-
return obj;
|
|
126
|
-
}
|
|
127
|
-
function _parseVault(options) {
|
|
128
|
-
options = options || {};
|
|
129
|
-
const vaultPath = _vaultPath(options);
|
|
130
|
-
options.path = vaultPath;
|
|
131
|
-
const result = DotenvModule.configDotenv(options);
|
|
132
|
-
if (!result.parsed) {
|
|
133
|
-
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
134
|
-
err.code = "MISSING_DATA";
|
|
135
|
-
throw err;
|
|
136
|
-
}
|
|
137
|
-
const keys = _dotenvKey(options).split(",");
|
|
138
|
-
const length = keys.length;
|
|
139
|
-
let decrypted;
|
|
140
|
-
for (let i = 0;i < length; i++) {
|
|
141
|
-
try {
|
|
142
|
-
const key = keys[i].trim();
|
|
143
|
-
const attrs = _instructions(result, key);
|
|
144
|
-
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
145
|
-
break;
|
|
146
|
-
} catch (error) {
|
|
147
|
-
if (i + 1 >= length) {
|
|
148
|
-
throw error;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return DotenvModule.parse(decrypted);
|
|
153
|
-
}
|
|
154
|
-
function _warn(message) {
|
|
155
|
-
console.log(`[dotenv@${version}][WARN] ${message}`);
|
|
156
|
-
}
|
|
157
|
-
function _debug(message) {
|
|
158
|
-
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
159
|
-
}
|
|
160
|
-
function _log(message) {
|
|
161
|
-
console.log(`[dotenv@${version}] ${message}`);
|
|
162
|
-
}
|
|
163
|
-
function _dotenvKey(options) {
|
|
164
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
165
|
-
return options.DOTENV_KEY;
|
|
166
|
-
}
|
|
167
|
-
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
168
|
-
return process.env.DOTENV_KEY;
|
|
169
|
-
}
|
|
170
|
-
return "";
|
|
171
|
-
}
|
|
172
|
-
function _instructions(result, dotenvKey) {
|
|
173
|
-
let uri;
|
|
174
|
-
try {
|
|
175
|
-
uri = new URL(dotenvKey);
|
|
176
|
-
} catch (error) {
|
|
177
|
-
if (error.code === "ERR_INVALID_URL") {
|
|
178
|
-
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
179
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
180
|
-
throw err;
|
|
181
|
-
}
|
|
182
|
-
throw error;
|
|
183
|
-
}
|
|
184
|
-
const key = uri.password;
|
|
185
|
-
if (!key) {
|
|
186
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
187
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
188
|
-
throw err;
|
|
189
|
-
}
|
|
190
|
-
const environment = uri.searchParams.get("environment");
|
|
191
|
-
if (!environment) {
|
|
192
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
193
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
194
|
-
throw err;
|
|
195
|
-
}
|
|
196
|
-
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
197
|
-
const ciphertext = result.parsed[environmentKey];
|
|
198
|
-
if (!ciphertext) {
|
|
199
|
-
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
200
|
-
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
201
|
-
throw err;
|
|
202
|
-
}
|
|
203
|
-
return { ciphertext, key };
|
|
204
|
-
}
|
|
205
|
-
function _vaultPath(options) {
|
|
206
|
-
let possibleVaultPath = null;
|
|
207
|
-
if (options && options.path && options.path.length > 0) {
|
|
208
|
-
if (Array.isArray(options.path)) {
|
|
209
|
-
for (const filepath of options.path) {
|
|
210
|
-
if (fs.existsSync(filepath)) {
|
|
211
|
-
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
} else {
|
|
215
|
-
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
216
|
-
}
|
|
217
|
-
} else {
|
|
218
|
-
possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
|
|
219
|
-
}
|
|
220
|
-
if (fs.existsSync(possibleVaultPath)) {
|
|
221
|
-
return possibleVaultPath;
|
|
222
|
-
}
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
function _resolveHome(envPath) {
|
|
226
|
-
return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
227
|
-
}
|
|
228
|
-
function _configVault(options) {
|
|
229
|
-
const debug = Boolean(options && options.debug);
|
|
230
|
-
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
231
|
-
if (debug || !quiet) {
|
|
232
|
-
_log("Loading env from encrypted .env.vault");
|
|
233
|
-
}
|
|
234
|
-
const parsed = DotenvModule._parseVault(options);
|
|
235
|
-
let processEnv = process.env;
|
|
236
|
-
if (options && options.processEnv != null) {
|
|
237
|
-
processEnv = options.processEnv;
|
|
238
|
-
}
|
|
239
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
240
|
-
return { parsed };
|
|
241
|
-
}
|
|
242
|
-
function configDotenv(options) {
|
|
243
|
-
const dotenvPath = path.resolve(process.cwd(), ".env");
|
|
244
|
-
let encoding = "utf8";
|
|
245
|
-
const debug = Boolean(options && options.debug);
|
|
246
|
-
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
247
|
-
if (options && options.encoding) {
|
|
248
|
-
encoding = options.encoding;
|
|
249
|
-
} else {
|
|
250
|
-
if (debug) {
|
|
251
|
-
_debug("No encoding is specified. UTF-8 is used by default");
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
let optionPaths = [dotenvPath];
|
|
255
|
-
if (options && options.path) {
|
|
256
|
-
if (!Array.isArray(options.path)) {
|
|
257
|
-
optionPaths = [_resolveHome(options.path)];
|
|
258
|
-
} else {
|
|
259
|
-
optionPaths = [];
|
|
260
|
-
for (const filepath of options.path) {
|
|
261
|
-
optionPaths.push(_resolveHome(filepath));
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
let lastError;
|
|
266
|
-
const parsedAll = {};
|
|
267
|
-
for (const path2 of optionPaths) {
|
|
268
|
-
try {
|
|
269
|
-
const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
|
|
270
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
271
|
-
} catch (e) {
|
|
272
|
-
if (debug) {
|
|
273
|
-
_debug(`Failed to load ${path2} ${e.message}`);
|
|
274
|
-
}
|
|
275
|
-
lastError = e;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
let processEnv = process.env;
|
|
279
|
-
if (options && options.processEnv != null) {
|
|
280
|
-
processEnv = options.processEnv;
|
|
281
|
-
}
|
|
282
|
-
DotenvModule.populate(processEnv, parsedAll, options);
|
|
283
|
-
if (debug || !quiet) {
|
|
284
|
-
const keysCount = Object.keys(parsedAll).length;
|
|
285
|
-
const shortPaths = [];
|
|
286
|
-
for (const filePath of optionPaths) {
|
|
287
|
-
try {
|
|
288
|
-
const relative = path.relative(process.cwd(), filePath);
|
|
289
|
-
shortPaths.push(relative);
|
|
290
|
-
} catch (e) {
|
|
291
|
-
if (debug) {
|
|
292
|
-
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
293
|
-
}
|
|
294
|
-
lastError = e;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")}`);
|
|
298
|
-
}
|
|
299
|
-
if (lastError) {
|
|
300
|
-
return { parsed: parsedAll, error: lastError };
|
|
301
|
-
} else {
|
|
302
|
-
return { parsed: parsedAll };
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
function config(options) {
|
|
306
|
-
if (_dotenvKey(options).length === 0) {
|
|
307
|
-
return DotenvModule.configDotenv(options);
|
|
308
|
-
}
|
|
309
|
-
const vaultPath = _vaultPath(options);
|
|
310
|
-
if (!vaultPath) {
|
|
311
|
-
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
312
|
-
return DotenvModule.configDotenv(options);
|
|
313
|
-
}
|
|
314
|
-
return DotenvModule._configVault(options);
|
|
315
|
-
}
|
|
316
|
-
function decrypt(encrypted, keyStr) {
|
|
317
|
-
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
318
|
-
let ciphertext = Buffer.from(encrypted, "base64");
|
|
319
|
-
const nonce = ciphertext.subarray(0, 12);
|
|
320
|
-
const authTag = ciphertext.subarray(-16);
|
|
321
|
-
ciphertext = ciphertext.subarray(12, -16);
|
|
322
|
-
try {
|
|
323
|
-
const aesgcm = crypto2.createDecipheriv("aes-256-gcm", key, nonce);
|
|
324
|
-
aesgcm.setAuthTag(authTag);
|
|
325
|
-
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
326
|
-
} catch (error) {
|
|
327
|
-
const isRange = error instanceof RangeError;
|
|
328
|
-
const invalidKeyLength = error.message === "Invalid key length";
|
|
329
|
-
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
330
|
-
if (isRange || invalidKeyLength) {
|
|
331
|
-
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
332
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
333
|
-
throw err;
|
|
334
|
-
} else if (decryptionFailed) {
|
|
335
|
-
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
336
|
-
err.code = "DECRYPTION_FAILED";
|
|
337
|
-
throw err;
|
|
338
|
-
} else {
|
|
339
|
-
throw error;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
function populate(processEnv, parsed, options = {}) {
|
|
344
|
-
const debug = Boolean(options && options.debug);
|
|
345
|
-
const override = Boolean(options && options.override);
|
|
346
|
-
if (typeof parsed !== "object") {
|
|
347
|
-
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
348
|
-
err.code = "OBJECT_REQUIRED";
|
|
349
|
-
throw err;
|
|
350
|
-
}
|
|
351
|
-
for (const key of Object.keys(parsed)) {
|
|
352
|
-
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
353
|
-
if (override === true) {
|
|
354
|
-
processEnv[key] = parsed[key];
|
|
355
|
-
}
|
|
356
|
-
if (debug) {
|
|
357
|
-
if (override === true) {
|
|
358
|
-
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
359
|
-
} else {
|
|
360
|
-
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
} else {
|
|
364
|
-
processEnv[key] = parsed[key];
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
var DotenvModule = {
|
|
369
|
-
configDotenv,
|
|
370
|
-
_configVault,
|
|
371
|
-
_parseVault,
|
|
372
|
-
config,
|
|
373
|
-
decrypt,
|
|
374
|
-
parse,
|
|
375
|
-
populate
|
|
376
|
-
};
|
|
377
|
-
exports.configDotenv = DotenvModule.configDotenv;
|
|
378
|
-
exports._configVault = DotenvModule._configVault;
|
|
379
|
-
exports._parseVault = DotenvModule._parseVault;
|
|
380
|
-
exports.config = DotenvModule.config;
|
|
381
|
-
exports.decrypt = DotenvModule.decrypt;
|
|
382
|
-
exports.parse = DotenvModule.parse;
|
|
383
|
-
exports.populate = DotenvModule.populate;
|
|
384
|
-
module.exports = DotenvModule;
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
// ../core/dist/index.js
|
|
388
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
389
|
-
var __create2 = Object.create;
|
|
390
|
-
var __getProtoOf2 = Object.getPrototypeOf;
|
|
391
|
-
var __defProp2 = Object.defineProperty;
|
|
392
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
393
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
394
|
-
var __toESM2 = (mod, isNodeMode, target) => {
|
|
395
|
-
target = mod != null ? __create2(__getProtoOf2(mod)) : {};
|
|
396
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target;
|
|
397
|
-
for (let key of __getOwnPropNames2(mod))
|
|
398
|
-
if (!__hasOwnProp2.call(to, key))
|
|
399
|
-
__defProp2(to, key, {
|
|
400
|
-
get: () => mod[key],
|
|
401
|
-
enumerable: true
|
|
402
|
-
});
|
|
403
|
-
return to;
|
|
404
|
-
};
|
|
405
|
-
var __commonJS2 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
406
|
-
var require_Reflect = __commonJS2(() => {
|
|
31
|
+
// ../../node_modules/.bun/reflect-metadata@0.2.2/node_modules/reflect-metadata/Reflect.js
|
|
32
|
+
var require_Reflect = __commonJS(() => {
|
|
407
33
|
/*! *****************************************************************************
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
34
|
+
Copyright (C) Microsoft. All rights reserved.
|
|
35
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
36
|
+
this file except in compliance with the License. You may obtain a copy of the
|
|
37
|
+
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
38
|
+
|
|
39
|
+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
40
|
+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
41
|
+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
42
|
+
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
43
|
+
|
|
44
|
+
See the Apache Version 2.0 License for specific language governing permissions
|
|
45
|
+
and limitations under the License.
|
|
46
|
+
***************************************************************************** */
|
|
421
47
|
var Reflect2;
|
|
422
48
|
(function(Reflect3) {
|
|
423
49
|
(function(factory) {
|
|
@@ -1352,52 +978,413 @@ var require_Reflect = __commonJS2(() => {
|
|
|
1352
978
|
return;
|
|
1353
979
|
Object.defineProperty(target, rootKey, { value: HashMap.create() });
|
|
1354
980
|
}
|
|
1355
|
-
return target[rootKey];
|
|
981
|
+
return target[rootKey];
|
|
982
|
+
}
|
|
983
|
+
function FillRandomBytes(buffer, size) {
|
|
984
|
+
for (var i = 0;i < size; ++i)
|
|
985
|
+
buffer[i] = Math.random() * 255 | 0;
|
|
986
|
+
return buffer;
|
|
987
|
+
}
|
|
988
|
+
function GenRandomBytes(size) {
|
|
989
|
+
if (typeof Uint8Array === "function") {
|
|
990
|
+
var array = new Uint8Array(size);
|
|
991
|
+
if (typeof crypto !== "undefined") {
|
|
992
|
+
crypto.getRandomValues(array);
|
|
993
|
+
} else if (typeof msCrypto !== "undefined") {
|
|
994
|
+
msCrypto.getRandomValues(array);
|
|
995
|
+
} else {
|
|
996
|
+
FillRandomBytes(array, size);
|
|
997
|
+
}
|
|
998
|
+
return array;
|
|
999
|
+
}
|
|
1000
|
+
return FillRandomBytes(new Array(size), size);
|
|
1001
|
+
}
|
|
1002
|
+
function CreateUUID() {
|
|
1003
|
+
var data = GenRandomBytes(UUID_SIZE);
|
|
1004
|
+
data[6] = data[6] & 79 | 64;
|
|
1005
|
+
data[8] = data[8] & 191 | 128;
|
|
1006
|
+
var result = "";
|
|
1007
|
+
for (var offset = 0;offset < UUID_SIZE; ++offset) {
|
|
1008
|
+
var byte = data[offset];
|
|
1009
|
+
if (offset === 4 || offset === 6 || offset === 8)
|
|
1010
|
+
result += "-";
|
|
1011
|
+
if (byte < 16)
|
|
1012
|
+
result += "0";
|
|
1013
|
+
result += byte.toString(16).toLowerCase();
|
|
1014
|
+
}
|
|
1015
|
+
return result;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
function MakeDictionary(obj) {
|
|
1019
|
+
obj.__ = undefined;
|
|
1020
|
+
delete obj.__;
|
|
1021
|
+
return obj;
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
})(Reflect2 || (Reflect2 = {}));
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
// ../../node_modules/.bun/dotenv@16.6.1/node_modules/dotenv/package.json
|
|
1028
|
+
var require_package = __commonJS((exports, module) => {
|
|
1029
|
+
module.exports = {
|
|
1030
|
+
name: "dotenv",
|
|
1031
|
+
version: "16.6.1",
|
|
1032
|
+
description: "Loads environment variables from .env file",
|
|
1033
|
+
main: "lib/main.js",
|
|
1034
|
+
types: "lib/main.d.ts",
|
|
1035
|
+
exports: {
|
|
1036
|
+
".": {
|
|
1037
|
+
types: "./lib/main.d.ts",
|
|
1038
|
+
require: "./lib/main.js",
|
|
1039
|
+
default: "./lib/main.js"
|
|
1040
|
+
},
|
|
1041
|
+
"./config": "./config.js",
|
|
1042
|
+
"./config.js": "./config.js",
|
|
1043
|
+
"./lib/env-options": "./lib/env-options.js",
|
|
1044
|
+
"./lib/env-options.js": "./lib/env-options.js",
|
|
1045
|
+
"./lib/cli-options": "./lib/cli-options.js",
|
|
1046
|
+
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
1047
|
+
"./package.json": "./package.json"
|
|
1048
|
+
},
|
|
1049
|
+
scripts: {
|
|
1050
|
+
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
1051
|
+
lint: "standard",
|
|
1052
|
+
pretest: "npm run lint && npm run dts-check",
|
|
1053
|
+
test: "tap run --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
1054
|
+
"test:coverage": "tap run --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
|
|
1055
|
+
prerelease: "npm test",
|
|
1056
|
+
release: "standard-version"
|
|
1057
|
+
},
|
|
1058
|
+
repository: {
|
|
1059
|
+
type: "git",
|
|
1060
|
+
url: "git://github.com/motdotla/dotenv.git"
|
|
1061
|
+
},
|
|
1062
|
+
homepage: "https://github.com/motdotla/dotenv#readme",
|
|
1063
|
+
funding: "https://dotenvx.com",
|
|
1064
|
+
keywords: [
|
|
1065
|
+
"dotenv",
|
|
1066
|
+
"env",
|
|
1067
|
+
".env",
|
|
1068
|
+
"environment",
|
|
1069
|
+
"variables",
|
|
1070
|
+
"config",
|
|
1071
|
+
"settings"
|
|
1072
|
+
],
|
|
1073
|
+
readmeFilename: "README.md",
|
|
1074
|
+
license: "BSD-2-Clause",
|
|
1075
|
+
devDependencies: {
|
|
1076
|
+
"@types/node": "^18.11.3",
|
|
1077
|
+
decache: "^4.6.2",
|
|
1078
|
+
sinon: "^14.0.1",
|
|
1079
|
+
standard: "^17.0.0",
|
|
1080
|
+
"standard-version": "^9.5.0",
|
|
1081
|
+
tap: "^19.2.0",
|
|
1082
|
+
typescript: "^4.8.4"
|
|
1083
|
+
},
|
|
1084
|
+
engines: {
|
|
1085
|
+
node: ">=12"
|
|
1086
|
+
},
|
|
1087
|
+
browser: {
|
|
1088
|
+
fs: false
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
// ../../node_modules/.bun/dotenv@16.6.1/node_modules/dotenv/lib/main.js
|
|
1094
|
+
var require_main = __commonJS((exports, module) => {
|
|
1095
|
+
var fs = __require("fs");
|
|
1096
|
+
var path = __require("path");
|
|
1097
|
+
var os = __require("os");
|
|
1098
|
+
var crypto2 = __require("crypto");
|
|
1099
|
+
var packageJson = require_package();
|
|
1100
|
+
var version = packageJson.version;
|
|
1101
|
+
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
1102
|
+
function parse(src) {
|
|
1103
|
+
const obj = {};
|
|
1104
|
+
let lines = src.toString();
|
|
1105
|
+
lines = lines.replace(/\r\n?/mg, `
|
|
1106
|
+
`);
|
|
1107
|
+
let match;
|
|
1108
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
1109
|
+
const key = match[1];
|
|
1110
|
+
let value = match[2] || "";
|
|
1111
|
+
value = value.trim();
|
|
1112
|
+
const maybeQuote = value[0];
|
|
1113
|
+
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
1114
|
+
if (maybeQuote === '"') {
|
|
1115
|
+
value = value.replace(/\\n/g, `
|
|
1116
|
+
`);
|
|
1117
|
+
value = value.replace(/\\r/g, "\r");
|
|
1118
|
+
}
|
|
1119
|
+
obj[key] = value;
|
|
1120
|
+
}
|
|
1121
|
+
return obj;
|
|
1122
|
+
}
|
|
1123
|
+
function _parseVault(options) {
|
|
1124
|
+
options = options || {};
|
|
1125
|
+
const vaultPath = _vaultPath(options);
|
|
1126
|
+
options.path = vaultPath;
|
|
1127
|
+
const result = DotenvModule.configDotenv(options);
|
|
1128
|
+
if (!result.parsed) {
|
|
1129
|
+
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
1130
|
+
err.code = "MISSING_DATA";
|
|
1131
|
+
throw err;
|
|
1132
|
+
}
|
|
1133
|
+
const keys = _dotenvKey(options).split(",");
|
|
1134
|
+
const length = keys.length;
|
|
1135
|
+
let decrypted;
|
|
1136
|
+
for (let i = 0;i < length; i++) {
|
|
1137
|
+
try {
|
|
1138
|
+
const key = keys[i].trim();
|
|
1139
|
+
const attrs = _instructions(result, key);
|
|
1140
|
+
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
1141
|
+
break;
|
|
1142
|
+
} catch (error) {
|
|
1143
|
+
if (i + 1 >= length) {
|
|
1144
|
+
throw error;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
return DotenvModule.parse(decrypted);
|
|
1149
|
+
}
|
|
1150
|
+
function _warn(message) {
|
|
1151
|
+
console.log(`[dotenv@${version}][WARN] ${message}`);
|
|
1152
|
+
}
|
|
1153
|
+
function _debug(message) {
|
|
1154
|
+
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
1155
|
+
}
|
|
1156
|
+
function _log(message) {
|
|
1157
|
+
console.log(`[dotenv@${version}] ${message}`);
|
|
1158
|
+
}
|
|
1159
|
+
function _dotenvKey(options) {
|
|
1160
|
+
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
1161
|
+
return options.DOTENV_KEY;
|
|
1162
|
+
}
|
|
1163
|
+
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
1164
|
+
return process.env.DOTENV_KEY;
|
|
1165
|
+
}
|
|
1166
|
+
return "";
|
|
1167
|
+
}
|
|
1168
|
+
function _instructions(result, dotenvKey) {
|
|
1169
|
+
let uri;
|
|
1170
|
+
try {
|
|
1171
|
+
uri = new URL(dotenvKey);
|
|
1172
|
+
} catch (error) {
|
|
1173
|
+
if (error.code === "ERR_INVALID_URL") {
|
|
1174
|
+
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
1175
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
1176
|
+
throw err;
|
|
1177
|
+
}
|
|
1178
|
+
throw error;
|
|
1179
|
+
}
|
|
1180
|
+
const key = uri.password;
|
|
1181
|
+
if (!key) {
|
|
1182
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
1183
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
1184
|
+
throw err;
|
|
1185
|
+
}
|
|
1186
|
+
const environment = uri.searchParams.get("environment");
|
|
1187
|
+
if (!environment) {
|
|
1188
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
1189
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
1190
|
+
throw err;
|
|
1191
|
+
}
|
|
1192
|
+
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
1193
|
+
const ciphertext = result.parsed[environmentKey];
|
|
1194
|
+
if (!ciphertext) {
|
|
1195
|
+
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
1196
|
+
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
1197
|
+
throw err;
|
|
1198
|
+
}
|
|
1199
|
+
return { ciphertext, key };
|
|
1200
|
+
}
|
|
1201
|
+
function _vaultPath(options) {
|
|
1202
|
+
let possibleVaultPath = null;
|
|
1203
|
+
if (options && options.path && options.path.length > 0) {
|
|
1204
|
+
if (Array.isArray(options.path)) {
|
|
1205
|
+
for (const filepath of options.path) {
|
|
1206
|
+
if (fs.existsSync(filepath)) {
|
|
1207
|
+
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
1208
|
+
}
|
|
1356
1209
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1210
|
+
} else {
|
|
1211
|
+
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
1212
|
+
}
|
|
1213
|
+
} else {
|
|
1214
|
+
possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
|
|
1215
|
+
}
|
|
1216
|
+
if (fs.existsSync(possibleVaultPath)) {
|
|
1217
|
+
return possibleVaultPath;
|
|
1218
|
+
}
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1221
|
+
function _resolveHome(envPath) {
|
|
1222
|
+
return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
1223
|
+
}
|
|
1224
|
+
function _configVault(options) {
|
|
1225
|
+
const debug = Boolean(options && options.debug);
|
|
1226
|
+
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
1227
|
+
if (debug || !quiet) {
|
|
1228
|
+
_log("Loading env from encrypted .env.vault");
|
|
1229
|
+
}
|
|
1230
|
+
const parsed = DotenvModule._parseVault(options);
|
|
1231
|
+
let processEnv = process.env;
|
|
1232
|
+
if (options && options.processEnv != null) {
|
|
1233
|
+
processEnv = options.processEnv;
|
|
1234
|
+
}
|
|
1235
|
+
DotenvModule.populate(processEnv, parsed, options);
|
|
1236
|
+
return { parsed };
|
|
1237
|
+
}
|
|
1238
|
+
function configDotenv(options) {
|
|
1239
|
+
const dotenvPath = path.resolve(process.cwd(), ".env");
|
|
1240
|
+
let encoding = "utf8";
|
|
1241
|
+
const debug = Boolean(options && options.debug);
|
|
1242
|
+
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
1243
|
+
if (options && options.encoding) {
|
|
1244
|
+
encoding = options.encoding;
|
|
1245
|
+
} else {
|
|
1246
|
+
if (debug) {
|
|
1247
|
+
_debug("No encoding is specified. UTF-8 is used by default");
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
let optionPaths = [dotenvPath];
|
|
1251
|
+
if (options && options.path) {
|
|
1252
|
+
if (!Array.isArray(options.path)) {
|
|
1253
|
+
optionPaths = [_resolveHome(options.path)];
|
|
1254
|
+
} else {
|
|
1255
|
+
optionPaths = [];
|
|
1256
|
+
for (const filepath of options.path) {
|
|
1257
|
+
optionPaths.push(_resolveHome(filepath));
|
|
1361
1258
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
}
|
|
1374
|
-
return FillRandomBytes(new Array(size), size);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
let lastError;
|
|
1262
|
+
const parsedAll = {};
|
|
1263
|
+
for (const path2 of optionPaths) {
|
|
1264
|
+
try {
|
|
1265
|
+
const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
|
|
1266
|
+
DotenvModule.populate(parsedAll, parsed, options);
|
|
1267
|
+
} catch (e) {
|
|
1268
|
+
if (debug) {
|
|
1269
|
+
_debug(`Failed to load ${path2} ${e.message}`);
|
|
1375
1270
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1271
|
+
lastError = e;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
let processEnv = process.env;
|
|
1275
|
+
if (options && options.processEnv != null) {
|
|
1276
|
+
processEnv = options.processEnv;
|
|
1277
|
+
}
|
|
1278
|
+
DotenvModule.populate(processEnv, parsedAll, options);
|
|
1279
|
+
if (debug || !quiet) {
|
|
1280
|
+
const keysCount = Object.keys(parsedAll).length;
|
|
1281
|
+
const shortPaths = [];
|
|
1282
|
+
for (const filePath of optionPaths) {
|
|
1283
|
+
try {
|
|
1284
|
+
const relative = path.relative(process.cwd(), filePath);
|
|
1285
|
+
shortPaths.push(relative);
|
|
1286
|
+
} catch (e) {
|
|
1287
|
+
if (debug) {
|
|
1288
|
+
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
1388
1289
|
}
|
|
1389
|
-
|
|
1290
|
+
lastError = e;
|
|
1390
1291
|
}
|
|
1391
1292
|
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1293
|
+
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")}`);
|
|
1294
|
+
}
|
|
1295
|
+
if (lastError) {
|
|
1296
|
+
return { parsed: parsedAll, error: lastError };
|
|
1297
|
+
} else {
|
|
1298
|
+
return { parsed: parsedAll };
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function config(options) {
|
|
1302
|
+
if (_dotenvKey(options).length === 0) {
|
|
1303
|
+
return DotenvModule.configDotenv(options);
|
|
1304
|
+
}
|
|
1305
|
+
const vaultPath = _vaultPath(options);
|
|
1306
|
+
if (!vaultPath) {
|
|
1307
|
+
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
1308
|
+
return DotenvModule.configDotenv(options);
|
|
1309
|
+
}
|
|
1310
|
+
return DotenvModule._configVault(options);
|
|
1311
|
+
}
|
|
1312
|
+
function decrypt(encrypted, keyStr) {
|
|
1313
|
+
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
1314
|
+
let ciphertext = Buffer.from(encrypted, "base64");
|
|
1315
|
+
const nonce = ciphertext.subarray(0, 12);
|
|
1316
|
+
const authTag = ciphertext.subarray(-16);
|
|
1317
|
+
ciphertext = ciphertext.subarray(12, -16);
|
|
1318
|
+
try {
|
|
1319
|
+
const aesgcm = crypto2.createDecipheriv("aes-256-gcm", key, nonce);
|
|
1320
|
+
aesgcm.setAuthTag(authTag);
|
|
1321
|
+
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
1322
|
+
} catch (error) {
|
|
1323
|
+
const isRange = error instanceof RangeError;
|
|
1324
|
+
const invalidKeyLength = error.message === "Invalid key length";
|
|
1325
|
+
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
1326
|
+
if (isRange || invalidKeyLength) {
|
|
1327
|
+
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
1328
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
1329
|
+
throw err;
|
|
1330
|
+
} else if (decryptionFailed) {
|
|
1331
|
+
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
1332
|
+
err.code = "DECRYPTION_FAILED";
|
|
1333
|
+
throw err;
|
|
1334
|
+
} else {
|
|
1335
|
+
throw error;
|
|
1396
1336
|
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
function populate(processEnv, parsed, options = {}) {
|
|
1340
|
+
const debug = Boolean(options && options.debug);
|
|
1341
|
+
const override = Boolean(options && options.override);
|
|
1342
|
+
if (typeof parsed !== "object") {
|
|
1343
|
+
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
1344
|
+
err.code = "OBJECT_REQUIRED";
|
|
1345
|
+
throw err;
|
|
1346
|
+
}
|
|
1347
|
+
for (const key of Object.keys(parsed)) {
|
|
1348
|
+
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
1349
|
+
if (override === true) {
|
|
1350
|
+
processEnv[key] = parsed[key];
|
|
1351
|
+
}
|
|
1352
|
+
if (debug) {
|
|
1353
|
+
if (override === true) {
|
|
1354
|
+
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
1355
|
+
} else {
|
|
1356
|
+
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
} else {
|
|
1360
|
+
processEnv[key] = parsed[key];
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
var DotenvModule = {
|
|
1365
|
+
configDotenv,
|
|
1366
|
+
_configVault,
|
|
1367
|
+
_parseVault,
|
|
1368
|
+
config,
|
|
1369
|
+
decrypt,
|
|
1370
|
+
parse,
|
|
1371
|
+
populate
|
|
1372
|
+
};
|
|
1373
|
+
exports.configDotenv = DotenvModule.configDotenv;
|
|
1374
|
+
exports._configVault = DotenvModule._configVault;
|
|
1375
|
+
exports._parseVault = DotenvModule._parseVault;
|
|
1376
|
+
exports.config = DotenvModule.config;
|
|
1377
|
+
exports.decrypt = DotenvModule.decrypt;
|
|
1378
|
+
exports.parse = DotenvModule.parse;
|
|
1379
|
+
exports.populate = DotenvModule.populate;
|
|
1380
|
+
module.exports = DotenvModule;
|
|
1399
1381
|
});
|
|
1400
|
-
|
|
1382
|
+
|
|
1383
|
+
// ../core/src/context.ts
|
|
1384
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
1385
|
+
var kanjijsContext = new AsyncLocalStorage;
|
|
1386
|
+
// ../core/src/metadata.ts
|
|
1387
|
+
var import_reflect_metadata = __toESM(require_Reflect(), 1);
|
|
1401
1388
|
var methodMetadataStore = new WeakMap;
|
|
1402
1389
|
var controllerMetadataStore = new WeakMap;
|
|
1403
1390
|
var moduleMetadataStore = new WeakMap;
|
|
@@ -1424,6 +1411,16 @@ if (!globalStore.KANJI_METADATA_STORAGE) {
|
|
|
1424
1411
|
existing.contract = contract;
|
|
1425
1412
|
methods.set(methodName, existing);
|
|
1426
1413
|
},
|
|
1414
|
+
addRouteParam(target, methodName, param) {
|
|
1415
|
+
let methods = methodMetadataStore.get(target);
|
|
1416
|
+
if (!methods) {
|
|
1417
|
+
methods = new Map;
|
|
1418
|
+
methodMetadataStore.set(target, methods);
|
|
1419
|
+
}
|
|
1420
|
+
const existing = methods.get(methodName) || {};
|
|
1421
|
+
existing.params = [...existing.params || [], param];
|
|
1422
|
+
methods.set(methodName, existing);
|
|
1423
|
+
},
|
|
1427
1424
|
addMiddleware(target, middleware, methodName) {
|
|
1428
1425
|
if (methodName) {
|
|
1429
1426
|
let methods = methodMetadataStore.get(target);
|
|
@@ -1469,6 +1466,8 @@ if (!globalStore.KANJI_METADATA_STORAGE) {
|
|
|
1469
1466
|
};
|
|
1470
1467
|
}
|
|
1471
1468
|
var MetadataStorage = globalStore.KANJI_METADATA_STORAGE;
|
|
1469
|
+
|
|
1470
|
+
// ../core/src/decorators.ts
|
|
1472
1471
|
function Module(metadata) {
|
|
1473
1472
|
return (target) => {
|
|
1474
1473
|
MetadataStorage.defineModule(target, metadata);
|
|
@@ -1489,50 +1488,72 @@ var Post = createMethodDecorator("POST");
|
|
|
1489
1488
|
var Put = createMethodDecorator("PUT");
|
|
1490
1489
|
var Delete = createMethodDecorator("DELETE");
|
|
1491
1490
|
var Patch = createMethodDecorator("PATCH");
|
|
1492
|
-
|
|
1491
|
+
function createParamDecorator(type) {
|
|
1492
|
+
return (data) => {
|
|
1493
|
+
return (target, propertyKey, parameterIndex) => {
|
|
1494
|
+
if (propertyKey) {
|
|
1495
|
+
MetadataStorage.addRouteParam(target, propertyKey, {
|
|
1496
|
+
index: parameterIndex,
|
|
1497
|
+
type,
|
|
1498
|
+
data
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
var Body = createParamDecorator("BODY");
|
|
1505
|
+
var Query = createParamDecorator("QUERY");
|
|
1506
|
+
var Param = createParamDecorator("PARAM");
|
|
1507
|
+
var Headers = createParamDecorator("HEADERS");
|
|
1508
|
+
var Ctx = createParamDecorator("CONTEXT");
|
|
1509
|
+
// ../core/src/di/container.ts
|
|
1510
|
+
var import_reflect_metadata2 = __toESM(require_Reflect(), 1);
|
|
1493
1511
|
|
|
1494
1512
|
class KanjijsIoC {
|
|
1495
1513
|
static providers = new Map;
|
|
1496
1514
|
static register(tokenOrTarget, provider) {
|
|
1497
1515
|
if (provider) {
|
|
1498
1516
|
if ("useValue" in provider) {
|
|
1499
|
-
|
|
1517
|
+
KanjijsIoC.providers.set(tokenOrTarget, { useValue: provider.useValue });
|
|
1500
1518
|
} else if ("useClass" in provider) {
|
|
1501
|
-
|
|
1519
|
+
KanjijsIoC.providers.set(tokenOrTarget, { useClass: provider.useClass });
|
|
1502
1520
|
}
|
|
1503
1521
|
} else {
|
|
1504
|
-
|
|
1522
|
+
KanjijsIoC.providers.set(tokenOrTarget, {
|
|
1523
|
+
useClass: tokenOrTarget
|
|
1524
|
+
});
|
|
1505
1525
|
}
|
|
1506
1526
|
}
|
|
1507
1527
|
static resolve(target) {
|
|
1508
|
-
let provider =
|
|
1528
|
+
let provider = KanjijsIoC.providers.get(target);
|
|
1509
1529
|
if (!provider && typeof target === "function") {
|
|
1510
1530
|
provider = { useClass: target };
|
|
1511
|
-
|
|
1531
|
+
KanjijsIoC.providers.set(target, provider);
|
|
1512
1532
|
}
|
|
1513
1533
|
if (!provider) {
|
|
1514
|
-
throw new Error(`Provider not found for token: ${target
|
|
1534
|
+
throw new Error(`Provider not found for token: ${typeof target === "function" ? target.name : String(target)}`);
|
|
1515
1535
|
}
|
|
1516
1536
|
if (provider.instance) {
|
|
1517
1537
|
return provider.instance;
|
|
1518
1538
|
}
|
|
1519
|
-
console.log(`[DI] Creating NEW instance for ${target
|
|
1539
|
+
console.log(`[DI] Creating NEW instance for ${typeof target === "function" ? target.name : String(target)}`);
|
|
1520
1540
|
if (provider.useValue !== undefined) {
|
|
1521
1541
|
provider.instance = provider.useValue;
|
|
1522
1542
|
} else if (provider.useClass) {
|
|
1523
1543
|
const ConcreteClass = provider.useClass;
|
|
1524
1544
|
const paramTypes = Reflect.getMetadata("design:paramtypes", ConcreteClass) || [];
|
|
1525
1545
|
const injectionTokens = MetadataStorage.getInjections(ConcreteClass) || new Map;
|
|
1526
|
-
const injections = paramTypes.map((
|
|
1546
|
+
const injections = paramTypes.map((paramToken, index) => {
|
|
1527
1547
|
const overrideToken = injectionTokens.get(index);
|
|
1528
|
-
|
|
1548
|
+
const resolvedToken = overrideToken || paramToken;
|
|
1549
|
+
return KanjijsIoC.resolve(resolvedToken);
|
|
1529
1550
|
});
|
|
1530
1551
|
provider.instance = new ConcreteClass(...injections);
|
|
1531
1552
|
}
|
|
1532
1553
|
return provider.instance;
|
|
1533
1554
|
}
|
|
1534
1555
|
static clear() {
|
|
1535
|
-
|
|
1556
|
+
KanjijsIoC.providers.clear();
|
|
1536
1557
|
}
|
|
1537
1558
|
}
|
|
1538
1559
|
|
|
@@ -1544,7 +1565,7 @@ class Container {
|
|
|
1544
1565
|
resolve(token) {
|
|
1545
1566
|
const provider = this.providers.get(token);
|
|
1546
1567
|
if (!provider) {
|
|
1547
|
-
throw new Error(`[DI] Provider not found for token: ${token
|
|
1568
|
+
throw new Error(`[DI] Provider not found for token: ${typeof token === "function" ? token.name : String(token)}`);
|
|
1548
1569
|
}
|
|
1549
1570
|
if (provider.instance) {
|
|
1550
1571
|
return provider.instance;
|
|
@@ -1557,7 +1578,8 @@ class Container {
|
|
|
1557
1578
|
const injectionTokens = MetadataStorage.getInjections(ConcreteClass) || new Map;
|
|
1558
1579
|
const injections = paramTypes.map((paramToken, index) => {
|
|
1559
1580
|
const overrideToken = injectionTokens.get(index);
|
|
1560
|
-
|
|
1581
|
+
const resolvedToken = overrideToken || paramToken;
|
|
1582
|
+
return this.resolve(resolvedToken);
|
|
1561
1583
|
});
|
|
1562
1584
|
provider.instance = new ConcreteClass(...injections);
|
|
1563
1585
|
} else if (provider.useFactory) {
|
|
@@ -1567,7 +1589,7 @@ class Container {
|
|
|
1567
1589
|
return provider.instance;
|
|
1568
1590
|
}
|
|
1569
1591
|
}
|
|
1570
|
-
|
|
1592
|
+
// ../core/src/di/module-compiler.ts
|
|
1571
1593
|
class ModuleCompiler {
|
|
1572
1594
|
nodes = new Map;
|
|
1573
1595
|
globalExportedTokens = new Set;
|
|
@@ -1577,7 +1599,8 @@ class ModuleCompiler {
|
|
|
1577
1599
|
const container = new Container;
|
|
1578
1600
|
for (const node of this.nodes.values()) {
|
|
1579
1601
|
for (const [token, provider] of node.providers) {
|
|
1580
|
-
|
|
1602
|
+
const { provide: _provide, ...definition } = provider;
|
|
1603
|
+
container.register(token, definition);
|
|
1581
1604
|
}
|
|
1582
1605
|
}
|
|
1583
1606
|
return container;
|
|
@@ -1596,20 +1619,20 @@ class ModuleCompiler {
|
|
|
1596
1619
|
};
|
|
1597
1620
|
this.nodes.set(moduleClass, node);
|
|
1598
1621
|
const meta = MetadataStorage.getModule(moduleClass) || {};
|
|
1599
|
-
const dynamicMeta = "module" in target ? target :
|
|
1600
|
-
const allProviders = [...meta.providers || [], ...dynamicMeta
|
|
1622
|
+
const dynamicMeta = "module" in target ? target : undefined;
|
|
1623
|
+
const allProviders = [...meta.providers || [], ...dynamicMeta?.providers || []];
|
|
1601
1624
|
this.processProviders(node, allProviders);
|
|
1602
|
-
const allExports = [...meta.exports || [], ...dynamicMeta
|
|
1625
|
+
const allExports = [...meta.exports || [], ...dynamicMeta?.exports || []];
|
|
1603
1626
|
for (const token of allExports) {
|
|
1604
1627
|
node.exports.add(token);
|
|
1605
1628
|
}
|
|
1606
|
-
if (meta.global || dynamicMeta
|
|
1629
|
+
if (meta.global || dynamicMeta?.global) {
|
|
1607
1630
|
node.isGlobal = true;
|
|
1608
1631
|
for (const token of node.exports) {
|
|
1609
1632
|
this.globalExportedTokens.add(token);
|
|
1610
1633
|
}
|
|
1611
1634
|
}
|
|
1612
|
-
const allImports = [...meta.imports || [], ...dynamicMeta
|
|
1635
|
+
const allImports = [...meta.imports || [], ...dynamicMeta?.imports || []];
|
|
1613
1636
|
for (const imp of allImports) {
|
|
1614
1637
|
const importedNode = this.scan(imp);
|
|
1615
1638
|
node.imports.add(importedNode);
|
|
@@ -1648,7 +1671,7 @@ class ModuleCompiler {
|
|
|
1648
1671
|
for (const globalToken of this.globalExportedTokens) {
|
|
1649
1672
|
visibleTokens.add(globalToken);
|
|
1650
1673
|
}
|
|
1651
|
-
for (const [
|
|
1674
|
+
for (const [_token, provider] of node.providers) {
|
|
1652
1675
|
this.checkDependencies(provider, visibleTokens, node.module.name);
|
|
1653
1676
|
}
|
|
1654
1677
|
}
|
|
@@ -1661,19 +1684,24 @@ class ModuleCompiler {
|
|
|
1661
1684
|
targetName = clazz.name;
|
|
1662
1685
|
const paramTypes = Reflect.getMetadata("design:paramtypes", clazz) || [];
|
|
1663
1686
|
const injectionTokens = MetadataStorage.getInjections(clazz) || new Map;
|
|
1664
|
-
dependencies = paramTypes.map((
|
|
1687
|
+
dependencies = paramTypes.map((paramType, index) => {
|
|
1688
|
+
const overrideToken = injectionTokens.get(index);
|
|
1689
|
+
return overrideToken || paramType;
|
|
1690
|
+
});
|
|
1665
1691
|
} else if ("useFactory" in provider) {
|
|
1666
|
-
targetName = provider.provide
|
|
1692
|
+
targetName = typeof provider.provide === "function" ? provider.provide.name : String(provider.provide);
|
|
1667
1693
|
dependencies = provider.inject || [];
|
|
1668
1694
|
}
|
|
1669
1695
|
for (const dep of dependencies) {
|
|
1670
1696
|
if (!visibleTokens.has(dep)) {
|
|
1671
|
-
const depName = dep
|
|
1697
|
+
const depName = typeof dep === "function" ? dep.name : String(dep);
|
|
1672
1698
|
throw new Error(`[Kanjijs] strict-di-error: Provider '${targetName}' in Module '${moduleName}' ` + `depends on '${depName}', but it is not visible. ` + `Make sure it is imported and exported by the source module.`);
|
|
1673
1699
|
}
|
|
1674
1700
|
}
|
|
1675
1701
|
}
|
|
1676
1702
|
}
|
|
1703
|
+
|
|
1704
|
+
// ../core/src/index.ts
|
|
1677
1705
|
var GLOBAL_MIDDLEWARE_TOKEN = Symbol("GLOBAL_MIDDLEWARE_TOKEN");
|
|
1678
1706
|
|
|
1679
1707
|
// src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanjijs/config",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"build": "bun build src/index.ts --outdir dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@kanjijs/core": "^0.2.0-beta.
|
|
16
|
+
"@kanjijs/core": "^0.2.0-beta.15",
|
|
17
17
|
"dotenv": "^16.4.1",
|
|
18
18
|
"zod": "^3.22.4"
|
|
19
19
|
},
|