@forklaunch/core 0.3.0 → 0.3.2
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/lib/dtoMapper/index.js +8 -3
- package/lib/dtoMapper/index.mjs +14 -3
- package/lib/http/index.js +19 -11
- package/lib/http/index.mjs +23 -11
- package/lib/services/index.d.mts +7 -2
- package/lib/services/index.d.ts +7 -2
- package/lib/services/index.js +99 -15
- package/lib/services/index.mjs +97 -14
- package/package.json +45 -45
package/lib/dtoMapper/index.js
CHANGED
@@ -25,7 +25,11 @@ __export(dtoMapper_exports, {
|
|
25
25
|
});
|
26
26
|
module.exports = __toCommonJS(dtoMapper_exports);
|
27
27
|
|
28
|
+
// src/dtoMapper/models/requestDtoMapper.model.ts
|
29
|
+
var import_validator2 = require("@forklaunch/validator");
|
30
|
+
|
28
31
|
// src/dtoMapper/models/baseDtoMapper.model.ts
|
32
|
+
var import_validator = require("@forklaunch/validator");
|
29
33
|
function construct(self, schemaValidator) {
|
30
34
|
return new self(schemaValidator || {});
|
31
35
|
}
|
@@ -67,7 +71,7 @@ var BaseDtoMapper = class {
|
|
67
71
|
_dto
|
68
72
|
);
|
69
73
|
if (!parsedSchema.ok) {
|
70
|
-
throw new Error(
|
74
|
+
throw new Error((0, import_validator.prettyPrintParseErrors)(parsedSchema.errors, "DTO"));
|
71
75
|
}
|
72
76
|
this._dto = _dto;
|
73
77
|
}
|
@@ -112,7 +116,7 @@ var RequestDtoMapper = class extends BaseDtoMapper {
|
|
112
116
|
json
|
113
117
|
);
|
114
118
|
if (!parsedSchema.ok) {
|
115
|
-
throw new Error(
|
119
|
+
throw new Error((0, import_validator2.prettyPrintParseErrors)(parsedSchema.errors, "DTO"));
|
116
120
|
}
|
117
121
|
this.dto = json;
|
118
122
|
return this;
|
@@ -159,6 +163,7 @@ var RequestDtoMapper = class extends BaseDtoMapper {
|
|
159
163
|
};
|
160
164
|
|
161
165
|
// src/dtoMapper/models/responseDtoMapper.model.ts
|
166
|
+
var import_validator3 = require("@forklaunch/validator");
|
162
167
|
var ResponseDtoMapper = class extends BaseDtoMapper {
|
163
168
|
/**
|
164
169
|
* The entity type.
|
@@ -178,7 +183,7 @@ var ResponseDtoMapper = class extends BaseDtoMapper {
|
|
178
183
|
this.dto
|
179
184
|
);
|
180
185
|
if (!parsedSchema.ok) {
|
181
|
-
throw new Error(
|
186
|
+
throw new Error((0, import_validator3.prettyPrintParseErrors)(parsedSchema.errors, "DTO"));
|
182
187
|
}
|
183
188
|
return this.dto;
|
184
189
|
}
|
package/lib/dtoMapper/index.mjs
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
+
// src/dtoMapper/models/requestDtoMapper.model.ts
|
2
|
+
import {
|
3
|
+
prettyPrintParseErrors as prettyPrintParseErrors2
|
4
|
+
} from "@forklaunch/validator";
|
5
|
+
|
1
6
|
// src/dtoMapper/models/baseDtoMapper.model.ts
|
7
|
+
import {
|
8
|
+
prettyPrintParseErrors
|
9
|
+
} from "@forklaunch/validator";
|
2
10
|
function construct(self, schemaValidator) {
|
3
11
|
return new self(schemaValidator || {});
|
4
12
|
}
|
@@ -40,7 +48,7 @@ var BaseDtoMapper = class {
|
|
40
48
|
_dto
|
41
49
|
);
|
42
50
|
if (!parsedSchema.ok) {
|
43
|
-
throw new Error(
|
51
|
+
throw new Error(prettyPrintParseErrors(parsedSchema.errors, "DTO"));
|
44
52
|
}
|
45
53
|
this._dto = _dto;
|
46
54
|
}
|
@@ -85,7 +93,7 @@ var RequestDtoMapper = class extends BaseDtoMapper {
|
|
85
93
|
json
|
86
94
|
);
|
87
95
|
if (!parsedSchema.ok) {
|
88
|
-
throw new Error(
|
96
|
+
throw new Error(prettyPrintParseErrors2(parsedSchema.errors, "DTO"));
|
89
97
|
}
|
90
98
|
this.dto = json;
|
91
99
|
return this;
|
@@ -132,6 +140,9 @@ var RequestDtoMapper = class extends BaseDtoMapper {
|
|
132
140
|
};
|
133
141
|
|
134
142
|
// src/dtoMapper/models/responseDtoMapper.model.ts
|
143
|
+
import {
|
144
|
+
prettyPrintParseErrors as prettyPrintParseErrors3
|
145
|
+
} from "@forklaunch/validator";
|
135
146
|
var ResponseDtoMapper = class extends BaseDtoMapper {
|
136
147
|
/**
|
137
148
|
* The entity type.
|
@@ -151,7 +162,7 @@ var ResponseDtoMapper = class extends BaseDtoMapper {
|
|
151
162
|
this.dto
|
152
163
|
);
|
153
164
|
if (!parsedSchema.ok) {
|
154
|
-
throw new Error(
|
165
|
+
throw new Error(prettyPrintParseErrors3(parsedSchema.errors, "DTO"));
|
155
166
|
}
|
156
167
|
return this.dto;
|
157
168
|
}
|
package/lib/http/index.js
CHANGED
@@ -271,6 +271,9 @@ function enrichDetails(contractDetails, requestSchema, responseSchemas) {
|
|
271
271
|
};
|
272
272
|
}
|
273
273
|
|
274
|
+
// src/http/middleware/request/parse.middleware.ts
|
275
|
+
var import_validator = require("@forklaunch/validator");
|
276
|
+
|
274
277
|
// src/http/guards/isResponseShape.ts
|
275
278
|
function isResponseShape(maybeResponseShape) {
|
276
279
|
return maybeResponseShape != null && "body" in maybeResponseShape && "query" in maybeResponseShape && "params" in maybeResponseShape && "headers" in maybeResponseShape;
|
@@ -296,10 +299,12 @@ function parse(req, _res, next) {
|
|
296
299
|
switch (req.contractDetails.options?.requestValidation) {
|
297
300
|
default:
|
298
301
|
case "error":
|
299
|
-
next?.(
|
302
|
+
next?.(
|
303
|
+
new Error((0, import_validator.prettyPrintParseErrors)(parsedRequest.errors, "Request"))
|
304
|
+
);
|
300
305
|
break;
|
301
306
|
case "warning":
|
302
|
-
console.warn(
|
307
|
+
console.warn((0, import_validator.prettyPrintParseErrors)(parsedRequest.errors, "Request"));
|
303
308
|
break;
|
304
309
|
case "none":
|
305
310
|
break;
|
@@ -2004,10 +2009,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2004
2009
|
description: `${controllerName} Operations`
|
2005
2010
|
});
|
2006
2011
|
router.routes.forEach((route) => {
|
2007
|
-
const fullPath = `${router.basePath}${route.path === "/" ? "" : route.path}`.replace(
|
2008
|
-
/:(\w+)/g,
|
2009
|
-
"{$1}"
|
2010
|
-
);
|
2012
|
+
const fullPath = `${router.basePath}${route.path === "/" ? "" : route.path}`.replace(/:(\w+)/g, "{$1}");
|
2011
2013
|
if (!paths[fullPath]) {
|
2012
2014
|
paths[fullPath] = {};
|
2013
2015
|
}
|
@@ -2087,6 +2089,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2087
2089
|
}
|
2088
2090
|
|
2089
2091
|
// src/http/middleware/response/parse.middleware.ts
|
2092
|
+
var import_validator2 = require("@forklaunch/validator");
|
2090
2093
|
function parse2(req, res, next) {
|
2091
2094
|
console.debug("[MIDDLEWARE] parseResponse started");
|
2092
2095
|
const { headers, responses } = res.responseSchemas;
|
@@ -2100,14 +2103,19 @@ function parse2(req, res, next) {
|
|
2100
2103
|
);
|
2101
2104
|
const parseErrors = [];
|
2102
2105
|
if (!parsedHeaders.ok) {
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
+
const headerErrors = (0, import_validator2.prettyPrintParseErrors)(parsedHeaders.errors, "Header");
|
2107
|
+
if (headerErrors) {
|
2108
|
+
parseErrors.push(headerErrors);
|
2109
|
+
}
|
2106
2110
|
}
|
2107
2111
|
if (!parsedResponse.ok) {
|
2108
|
-
|
2109
|
-
|
2112
|
+
const responseErrors = (0, import_validator2.prettyPrintParseErrors)(
|
2113
|
+
parsedResponse.errors,
|
2114
|
+
"Response"
|
2110
2115
|
);
|
2116
|
+
if (responseErrors) {
|
2117
|
+
parseErrors.push(responseErrors);
|
2118
|
+
}
|
2111
2119
|
}
|
2112
2120
|
if (parseErrors.length > 0) {
|
2113
2121
|
switch (req.contractDetails.options?.responseValidation) {
|
package/lib/http/index.mjs
CHANGED
@@ -213,6 +213,11 @@ function enrichDetails(contractDetails, requestSchema, responseSchemas) {
|
|
213
213
|
};
|
214
214
|
}
|
215
215
|
|
216
|
+
// src/http/middleware/request/parse.middleware.ts
|
217
|
+
import {
|
218
|
+
prettyPrintParseErrors
|
219
|
+
} from "@forklaunch/validator";
|
220
|
+
|
216
221
|
// src/http/guards/isResponseShape.ts
|
217
222
|
function isResponseShape(maybeResponseShape) {
|
218
223
|
return maybeResponseShape != null && "body" in maybeResponseShape && "query" in maybeResponseShape && "params" in maybeResponseShape && "headers" in maybeResponseShape;
|
@@ -238,10 +243,12 @@ function parse(req, _res, next) {
|
|
238
243
|
switch (req.contractDetails.options?.requestValidation) {
|
239
244
|
default:
|
240
245
|
case "error":
|
241
|
-
next?.(
|
246
|
+
next?.(
|
247
|
+
new Error(prettyPrintParseErrors(parsedRequest.errors, "Request"))
|
248
|
+
);
|
242
249
|
break;
|
243
250
|
case "warning":
|
244
|
-
console.warn(
|
251
|
+
console.warn(prettyPrintParseErrors(parsedRequest.errors, "Request"));
|
245
252
|
break;
|
246
253
|
case "none":
|
247
254
|
break;
|
@@ -1946,10 +1953,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
1946
1953
|
description: `${controllerName} Operations`
|
1947
1954
|
});
|
1948
1955
|
router.routes.forEach((route) => {
|
1949
|
-
const fullPath = `${router.basePath}${route.path === "/" ? "" : route.path}`.replace(
|
1950
|
-
/:(\w+)/g,
|
1951
|
-
"{$1}"
|
1952
|
-
);
|
1956
|
+
const fullPath = `${router.basePath}${route.path === "/" ? "" : route.path}`.replace(/:(\w+)/g, "{$1}");
|
1953
1957
|
if (!paths[fullPath]) {
|
1954
1958
|
paths[fullPath] = {};
|
1955
1959
|
}
|
@@ -2029,6 +2033,9 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2029
2033
|
}
|
2030
2034
|
|
2031
2035
|
// src/http/middleware/response/parse.middleware.ts
|
2036
|
+
import {
|
2037
|
+
prettyPrintParseErrors as prettyPrintParseErrors2
|
2038
|
+
} from "@forklaunch/validator";
|
2032
2039
|
function parse2(req, res, next) {
|
2033
2040
|
console.debug("[MIDDLEWARE] parseResponse started");
|
2034
2041
|
const { headers, responses } = res.responseSchemas;
|
@@ -2042,14 +2049,19 @@ function parse2(req, res, next) {
|
|
2042
2049
|
);
|
2043
2050
|
const parseErrors = [];
|
2044
2051
|
if (!parsedHeaders.ok) {
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2052
|
+
const headerErrors = prettyPrintParseErrors2(parsedHeaders.errors, "Header");
|
2053
|
+
if (headerErrors) {
|
2054
|
+
parseErrors.push(headerErrors);
|
2055
|
+
}
|
2048
2056
|
}
|
2049
2057
|
if (!parsedResponse.ok) {
|
2050
|
-
|
2051
|
-
|
2058
|
+
const responseErrors = prettyPrintParseErrors2(
|
2059
|
+
parsedResponse.errors,
|
2060
|
+
"Response"
|
2052
2061
|
);
|
2062
|
+
if (responseErrors) {
|
2063
|
+
parseErrors.push(responseErrors);
|
2064
|
+
}
|
2053
2065
|
}
|
2054
2066
|
if (parseErrors.length > 0) {
|
2055
2067
|
switch (req.contractDetails.options?.responseValidation) {
|
package/lib/services/index.d.mts
CHANGED
@@ -23,6 +23,9 @@ type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigVal
|
|
23
23
|
[M in keyof CV]: CV[M] extends SchemaConstructor<SV> ? Schema<InstanceType<CV[M]>, SV> : CV[M] extends SchemaFunction<SV> ? Schema<ReturnType<CV[M]>, SV> : CV[M] extends Function ? ReturnType<CV[M]> : CV[M] extends Constructor ? InstanceType<CV[M]> : Schema<CV[M], SV>;
|
24
24
|
};
|
25
25
|
type ScopedDependencyFactory<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>, M extends keyof CV> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];
|
26
|
+
type ValidConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = ConfigInjector<SV, CV> & {
|
27
|
+
validResolvedConfigValidator: void;
|
28
|
+
};
|
26
29
|
|
27
30
|
declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> {
|
28
31
|
private schemaValidator;
|
@@ -36,13 +39,15 @@ declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigVal
|
|
36
39
|
constructor(schemaValidator: SV, configShapes: CV, dependenciesDefinition: {
|
37
40
|
[K in keyof CV]: Singleton<ResolvedConfigValidator<SV, CV>[K]> | Constructed<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
|
38
41
|
});
|
39
|
-
validateConfigSingletons(
|
42
|
+
validateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>>;
|
40
43
|
resolve<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): ResolvedConfigValidator<SV, CV>[T];
|
41
44
|
scopedResolver<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T];
|
42
45
|
createScope(): ConfigInjector<SV, CV>;
|
43
46
|
dispose(): void;
|
44
47
|
}
|
45
48
|
|
49
|
+
declare function getEnvVar(name: string): string;
|
50
|
+
|
46
51
|
/**
|
47
52
|
* Interface representing a base service.
|
48
53
|
*
|
@@ -61,4 +66,4 @@ type EntityManager = {
|
|
61
66
|
fork: <Options>(options?: Options) => EntityManager;
|
62
67
|
};
|
63
68
|
|
64
|
-
export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton };
|
69
|
+
export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, type ValidConfigInjector, getEnvVar };
|
package/lib/services/index.d.ts
CHANGED
@@ -23,6 +23,9 @@ type ResolvedConfigValidator<SV extends AnySchemaValidator, CV extends ConfigVal
|
|
23
23
|
[M in keyof CV]: CV[M] extends SchemaConstructor<SV> ? Schema<InstanceType<CV[M]>, SV> : CV[M] extends SchemaFunction<SV> ? Schema<ReturnType<CV[M]>, SV> : CV[M] extends Function ? ReturnType<CV[M]> : CV[M] extends Constructor ? InstanceType<CV[M]> : Schema<CV[M], SV>;
|
24
24
|
};
|
25
25
|
type ScopedDependencyFactory<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>, M extends keyof CV> = (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[M];
|
26
|
+
type ValidConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> = ConfigInjector<SV, CV> & {
|
27
|
+
validResolvedConfigValidator: void;
|
28
|
+
};
|
26
29
|
|
27
30
|
declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigValidator<SV>> {
|
28
31
|
private schemaValidator;
|
@@ -36,13 +39,15 @@ declare class ConfigInjector<SV extends AnySchemaValidator, CV extends ConfigVal
|
|
36
39
|
constructor(schemaValidator: SV, configShapes: CV, dependenciesDefinition: {
|
37
40
|
[K in keyof CV]: Singleton<ResolvedConfigValidator<SV, CV>[K]> | Constructed<Omit<ResolvedConfigValidator<SV, CV>, K>, ResolvedConfigValidator<SV, CV>[K]>;
|
38
41
|
});
|
39
|
-
validateConfigSingletons(
|
42
|
+
validateConfigSingletons(): ParseResult<ValidConfigInjector<SV, CV>>;
|
40
43
|
resolve<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): ResolvedConfigValidator<SV, CV>[T];
|
41
44
|
scopedResolver<T extends keyof CV>(token: T, context?: Record<string, unknown>, resolutionPath?: (keyof CV)[]): (scope?: ConfigInjector<SV, CV>) => ResolvedConfigValidator<SV, CV>[T];
|
42
45
|
createScope(): ConfigInjector<SV, CV>;
|
43
46
|
dispose(): void;
|
44
47
|
}
|
45
48
|
|
49
|
+
declare function getEnvVar(name: string): string;
|
50
|
+
|
46
51
|
/**
|
47
52
|
* Interface representing a base service.
|
48
53
|
*
|
@@ -61,4 +66,4 @@ type EntityManager = {
|
|
61
66
|
fork: <Options>(options?: Options) => EntityManager;
|
62
67
|
};
|
63
68
|
|
64
|
-
export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton };
|
69
|
+
export { type BaseService, ConfigInjector, type ConfigValidator, type Constructed, type Constructor, type EntityManager, type Function, Lifetime, type ResolvedConfigValidator, type SchemaConstructor, type SchemaFunction, type ScopedDependencyFactory, type Singleton, type ValidConfigInjector, getEnvVar };
|
package/lib/services/index.js
CHANGED
@@ -21,13 +21,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
21
21
|
var services_exports = {};
|
22
22
|
__export(services_exports, {
|
23
23
|
ConfigInjector: () => ConfigInjector,
|
24
|
-
Lifetime: () => Lifetime
|
24
|
+
Lifetime: () => Lifetime,
|
25
|
+
getEnvVar: () => getEnvVar
|
25
26
|
});
|
26
27
|
module.exports = __toCommonJS(services_exports);
|
27
28
|
|
28
29
|
// src/services/configInjector.ts
|
29
30
|
var import_common = require("@forklaunch/common");
|
30
31
|
|
32
|
+
// src/services/guards/isConstructed.ts
|
33
|
+
function isConstructed(value) {
|
34
|
+
return typeof value === "object" && value != null && "constructor" in value && value.constructor != null;
|
35
|
+
}
|
36
|
+
|
37
|
+
// src/services/guards/isConstructor.ts
|
38
|
+
function isConstructor(value) {
|
39
|
+
return typeof value === "function" && value.constructor != null && value.prototype != null;
|
40
|
+
}
|
41
|
+
|
31
42
|
// src/services/types/configInjector.types.ts
|
32
43
|
var Lifetime = /* @__PURE__ */ ((Lifetime2) => {
|
33
44
|
Lifetime2[Lifetime2["Singleton"] = 0] = "Singleton";
|
@@ -64,7 +75,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
64
75
|
}
|
65
76
|
if (!injectorArgument.startsWith("{") || !injectorArgument.endsWith("}")) {
|
66
77
|
throw new Error(
|
67
|
-
`Invalid injector argument for ${String(
|
78
|
+
`Invalid injector argument for ${String(
|
79
|
+
token
|
80
|
+
)}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`
|
68
81
|
);
|
69
82
|
}
|
70
83
|
const resolvedArguments = Object.fromEntries(
|
@@ -72,7 +85,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
72
85
|
const newResolutionPath = [...resolutionPath, token];
|
73
86
|
if (resolutionPath.includes(arg)) {
|
74
87
|
throw new Error(
|
75
|
-
`Circular dependency detected: ${newResolutionPath.join(
|
88
|
+
`Circular dependency detected: ${newResolutionPath.join(
|
89
|
+
" -> "
|
90
|
+
)} -> ${arg}`
|
76
91
|
);
|
77
92
|
}
|
78
93
|
const resolvedArg = this.resolve(arg, context, newResolutionPath);
|
@@ -85,17 +100,77 @@ var ConfigInjector = class _ConfigInjector {
|
|
85
100
|
context ?? {}
|
86
101
|
);
|
87
102
|
}
|
88
|
-
validateConfigSingletons(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
103
|
+
validateConfigSingletons() {
|
104
|
+
const validNonSchemaSingletons = Object.entries(this.configShapes).reduce(
|
105
|
+
(acc, [key, value]) => {
|
106
|
+
if (this.dependenciesDefinition[key].lifetime === 0 /* Singleton */ && !this.schemaValidator.isSchema(value) && isConstructor(value)) {
|
107
|
+
if (!(this.dependenciesDefinition[key].value instanceof value)) {
|
108
|
+
const expected = value.name;
|
109
|
+
const receivedValue = this.dependenciesDefinition[key].value;
|
110
|
+
const received = isConstructed(receivedValue) ? receivedValue.constructor.name : typeof receivedValue;
|
111
|
+
if (acc.ok) {
|
112
|
+
acc = {
|
113
|
+
ok: false,
|
114
|
+
errors: []
|
115
|
+
};
|
116
|
+
}
|
117
|
+
acc.errors?.push({
|
118
|
+
message: `Expected ${expected}, received ${received}`,
|
119
|
+
path: [key]
|
120
|
+
});
|
121
|
+
} else {
|
122
|
+
if (acc.ok) {
|
123
|
+
acc = {
|
124
|
+
ok: true,
|
125
|
+
value: {
|
126
|
+
...acc.value,
|
127
|
+
[key]: this.dependenciesDefinition[key].value
|
128
|
+
}
|
129
|
+
};
|
130
|
+
}
|
131
|
+
}
|
132
|
+
return acc;
|
133
|
+
}
|
134
|
+
return acc;
|
135
|
+
},
|
136
|
+
{
|
137
|
+
ok: true,
|
138
|
+
value: {}
|
139
|
+
}
|
98
140
|
);
|
141
|
+
const singletons = Object.fromEntries(
|
142
|
+
Object.entries(this.configShapes).filter(
|
143
|
+
([key, value]) => this.dependenciesDefinition[key].lifetime === 0 /* Singleton */ && this.schemaValidator.isSchema(value)
|
144
|
+
)
|
145
|
+
);
|
146
|
+
const schemaSingletonParseResult = this.schemaValidator.parse(
|
147
|
+
this.schemaValidator.schemify(singletons),
|
148
|
+
Object.fromEntries(
|
149
|
+
Object.keys(singletons).map((key) => {
|
150
|
+
const dependency = this.dependenciesDefinition[key];
|
151
|
+
return [
|
152
|
+
key,
|
153
|
+
dependency.lifetime === 0 /* Singleton */ ? dependency.value : void 0
|
154
|
+
];
|
155
|
+
})
|
156
|
+
)
|
157
|
+
);
|
158
|
+
const configKeys = Object.keys(this.configShapes);
|
159
|
+
return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok ? {
|
160
|
+
ok: true,
|
161
|
+
value: {
|
162
|
+
validResolvedConfigValidator: void 0,
|
163
|
+
...this
|
164
|
+
}
|
165
|
+
} : {
|
166
|
+
ok: false,
|
167
|
+
errors: [
|
168
|
+
...!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors ? validNonSchemaSingletons.errors : [],
|
169
|
+
...!schemaSingletonParseResult.ok && schemaSingletonParseResult.errors ? schemaSingletonParseResult.errors : []
|
170
|
+
].sort(
|
171
|
+
(a, b) => configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])
|
172
|
+
)
|
173
|
+
};
|
99
174
|
}
|
100
175
|
resolve(token, context, resolutionPath = []) {
|
101
176
|
const instance = this.instances[token];
|
@@ -129,7 +204,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
129
204
|
default: {
|
130
205
|
(0, import_common.isNever)(definition);
|
131
206
|
throw new Error(
|
132
|
-
`Unable to resolve lifetime for dependency ${String(
|
207
|
+
`Unable to resolve lifetime for dependency ${String(
|
208
|
+
token
|
209
|
+
)}, ${resolutionPath}`
|
133
210
|
);
|
134
211
|
}
|
135
212
|
}
|
@@ -152,8 +229,15 @@ var ConfigInjector = class _ConfigInjector {
|
|
152
229
|
this.loadSingletons();
|
153
230
|
}
|
154
231
|
};
|
232
|
+
|
233
|
+
// src/services/getEnvVar.ts
|
234
|
+
function getEnvVar(name) {
|
235
|
+
const value = process.env[name];
|
236
|
+
return value;
|
237
|
+
}
|
155
238
|
// Annotate the CommonJS export names for ESM import in node:
|
156
239
|
0 && (module.exports = {
|
157
240
|
ConfigInjector,
|
158
|
-
Lifetime
|
241
|
+
Lifetime,
|
242
|
+
getEnvVar
|
159
243
|
});
|
package/lib/services/index.mjs
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
// src/services/configInjector.ts
|
2
2
|
import { extractArgumentNames, isNever } from "@forklaunch/common";
|
3
3
|
|
4
|
+
// src/services/guards/isConstructed.ts
|
5
|
+
function isConstructed(value) {
|
6
|
+
return typeof value === "object" && value != null && "constructor" in value && value.constructor != null;
|
7
|
+
}
|
8
|
+
|
9
|
+
// src/services/guards/isConstructor.ts
|
10
|
+
function isConstructor(value) {
|
11
|
+
return typeof value === "function" && value.constructor != null && value.prototype != null;
|
12
|
+
}
|
13
|
+
|
4
14
|
// src/services/types/configInjector.types.ts
|
5
15
|
var Lifetime = /* @__PURE__ */ ((Lifetime2) => {
|
6
16
|
Lifetime2[Lifetime2["Singleton"] = 0] = "Singleton";
|
@@ -37,7 +47,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
37
47
|
}
|
38
48
|
if (!injectorArgument.startsWith("{") || !injectorArgument.endsWith("}")) {
|
39
49
|
throw new Error(
|
40
|
-
`Invalid injector argument for ${String(
|
50
|
+
`Invalid injector argument for ${String(
|
51
|
+
token
|
52
|
+
)}: ${injectorArgument}. Please use object destructuring syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment.`
|
41
53
|
);
|
42
54
|
}
|
43
55
|
const resolvedArguments = Object.fromEntries(
|
@@ -45,7 +57,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
45
57
|
const newResolutionPath = [...resolutionPath, token];
|
46
58
|
if (resolutionPath.includes(arg)) {
|
47
59
|
throw new Error(
|
48
|
-
`Circular dependency detected: ${newResolutionPath.join(
|
60
|
+
`Circular dependency detected: ${newResolutionPath.join(
|
61
|
+
" -> "
|
62
|
+
)} -> ${arg}`
|
49
63
|
);
|
50
64
|
}
|
51
65
|
const resolvedArg = this.resolve(arg, context, newResolutionPath);
|
@@ -58,17 +72,77 @@ var ConfigInjector = class _ConfigInjector {
|
|
58
72
|
context ?? {}
|
59
73
|
);
|
60
74
|
}
|
61
|
-
validateConfigSingletons(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
validateConfigSingletons() {
|
76
|
+
const validNonSchemaSingletons = Object.entries(this.configShapes).reduce(
|
77
|
+
(acc, [key, value]) => {
|
78
|
+
if (this.dependenciesDefinition[key].lifetime === 0 /* Singleton */ && !this.schemaValidator.isSchema(value) && isConstructor(value)) {
|
79
|
+
if (!(this.dependenciesDefinition[key].value instanceof value)) {
|
80
|
+
const expected = value.name;
|
81
|
+
const receivedValue = this.dependenciesDefinition[key].value;
|
82
|
+
const received = isConstructed(receivedValue) ? receivedValue.constructor.name : typeof receivedValue;
|
83
|
+
if (acc.ok) {
|
84
|
+
acc = {
|
85
|
+
ok: false,
|
86
|
+
errors: []
|
87
|
+
};
|
88
|
+
}
|
89
|
+
acc.errors?.push({
|
90
|
+
message: `Expected ${expected}, received ${received}`,
|
91
|
+
path: [key]
|
92
|
+
});
|
93
|
+
} else {
|
94
|
+
if (acc.ok) {
|
95
|
+
acc = {
|
96
|
+
ok: true,
|
97
|
+
value: {
|
98
|
+
...acc.value,
|
99
|
+
[key]: this.dependenciesDefinition[key].value
|
100
|
+
}
|
101
|
+
};
|
102
|
+
}
|
103
|
+
}
|
104
|
+
return acc;
|
105
|
+
}
|
106
|
+
return acc;
|
107
|
+
},
|
108
|
+
{
|
109
|
+
ok: true,
|
110
|
+
value: {}
|
111
|
+
}
|
71
112
|
);
|
113
|
+
const singletons = Object.fromEntries(
|
114
|
+
Object.entries(this.configShapes).filter(
|
115
|
+
([key, value]) => this.dependenciesDefinition[key].lifetime === 0 /* Singleton */ && this.schemaValidator.isSchema(value)
|
116
|
+
)
|
117
|
+
);
|
118
|
+
const schemaSingletonParseResult = this.schemaValidator.parse(
|
119
|
+
this.schemaValidator.schemify(singletons),
|
120
|
+
Object.fromEntries(
|
121
|
+
Object.keys(singletons).map((key) => {
|
122
|
+
const dependency = this.dependenciesDefinition[key];
|
123
|
+
return [
|
124
|
+
key,
|
125
|
+
dependency.lifetime === 0 /* Singleton */ ? dependency.value : void 0
|
126
|
+
];
|
127
|
+
})
|
128
|
+
)
|
129
|
+
);
|
130
|
+
const configKeys = Object.keys(this.configShapes);
|
131
|
+
return validNonSchemaSingletons.ok && schemaSingletonParseResult.ok ? {
|
132
|
+
ok: true,
|
133
|
+
value: {
|
134
|
+
validResolvedConfigValidator: void 0,
|
135
|
+
...this
|
136
|
+
}
|
137
|
+
} : {
|
138
|
+
ok: false,
|
139
|
+
errors: [
|
140
|
+
...!validNonSchemaSingletons.ok && validNonSchemaSingletons.errors ? validNonSchemaSingletons.errors : [],
|
141
|
+
...!schemaSingletonParseResult.ok && schemaSingletonParseResult.errors ? schemaSingletonParseResult.errors : []
|
142
|
+
].sort(
|
143
|
+
(a, b) => configKeys.indexOf(a.path[0]) - configKeys.indexOf(b.path[0])
|
144
|
+
)
|
145
|
+
};
|
72
146
|
}
|
73
147
|
resolve(token, context, resolutionPath = []) {
|
74
148
|
const instance = this.instances[token];
|
@@ -102,7 +176,9 @@ var ConfigInjector = class _ConfigInjector {
|
|
102
176
|
default: {
|
103
177
|
isNever(definition);
|
104
178
|
throw new Error(
|
105
|
-
`Unable to resolve lifetime for dependency ${String(
|
179
|
+
`Unable to resolve lifetime for dependency ${String(
|
180
|
+
token
|
181
|
+
)}, ${resolutionPath}`
|
106
182
|
);
|
107
183
|
}
|
108
184
|
}
|
@@ -125,7 +201,14 @@ var ConfigInjector = class _ConfigInjector {
|
|
125
201
|
this.loadSingletons();
|
126
202
|
}
|
127
203
|
};
|
204
|
+
|
205
|
+
// src/services/getEnvVar.ts
|
206
|
+
function getEnvVar(name) {
|
207
|
+
const value = process.env[name];
|
208
|
+
return value;
|
209
|
+
}
|
128
210
|
export {
|
129
211
|
ConfigInjector,
|
130
|
-
Lifetime
|
212
|
+
Lifetime,
|
213
|
+
getEnvVar
|
131
214
|
};
|
package/package.json
CHANGED
@@ -1,52 +1,17 @@
|
|
1
1
|
{
|
2
2
|
"name": "@forklaunch/core",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.2",
|
4
4
|
"description": "forklaunch-js core package. Contains useful building blocks.",
|
5
|
-
"
|
6
|
-
"lib"
|
7
|
-
],
|
8
|
-
"types": "lib/index.d.ts",
|
9
|
-
"author": "Rohin Bhargava",
|
10
|
-
"license": "MIT",
|
11
|
-
"repository": {
|
12
|
-
"type": "git",
|
13
|
-
"url": "git+https://github.com/forklaunch/forklaunch-js.git"
|
14
|
-
},
|
5
|
+
"homepage": "https://github.com/forklaunch/forklaunch-js#readme",
|
15
6
|
"bugs": {
|
16
7
|
"url": "https://github.com/forklaunch/forklaunch-js/issues"
|
17
8
|
},
|
18
|
-
"
|
19
|
-
|
20
|
-
"
|
21
|
-
"@mikro-orm/mongodb": "^6.4.3",
|
22
|
-
"cors": "^2.8.5",
|
23
|
-
"jose": "^5.9.6",
|
24
|
-
"openapi3-ts": "^4.4.0",
|
25
|
-
"redis": "^4.7.0",
|
26
|
-
"uuid": "^11.0.5",
|
27
|
-
"@forklaunch/common": "0.2.0",
|
28
|
-
"@forklaunch/validator": "0.4.0"
|
29
|
-
},
|
30
|
-
"devDependencies": {
|
31
|
-
"@eslint/js": "^9.17.0",
|
32
|
-
"@types/cors": "^2.8.17",
|
33
|
-
"@types/jest": "^29.5.14",
|
34
|
-
"@types/qs": "^6.9.17",
|
35
|
-
"@types/uuid": "^10.0.0",
|
36
|
-
"globals": "^15.14.0",
|
37
|
-
"jest": "^29.7.0",
|
38
|
-
"prettier": "^3.4.2",
|
39
|
-
"testcontainers": "^10.16.0",
|
40
|
-
"ts-jest": "^29.2.5",
|
41
|
-
"ts-node": "^10.9.2",
|
42
|
-
"tsup": "^8.3.5",
|
43
|
-
"typedoc": "^0.27.6",
|
44
|
-
"typescript": "^5.7.3",
|
45
|
-
"typescript-eslint": "^8.19.1"
|
46
|
-
},
|
47
|
-
"directories": {
|
48
|
-
"test": "tests"
|
9
|
+
"repository": {
|
10
|
+
"type": "git",
|
11
|
+
"url": "git+https://github.com/forklaunch/forklaunch-js.git"
|
49
12
|
},
|
13
|
+
"license": "MIT",
|
14
|
+
"author": "Rohin Bhargava",
|
50
15
|
"exports": {
|
51
16
|
"./cache": {
|
52
17
|
"types": "./lib/cache/index.d.ts",
|
@@ -85,14 +50,49 @@
|
|
85
50
|
"default": "./lib/services/index.js"
|
86
51
|
}
|
87
52
|
},
|
53
|
+
"types": "lib/index.d.ts",
|
54
|
+
"directories": {
|
55
|
+
"test": "tests"
|
56
|
+
},
|
57
|
+
"files": [
|
58
|
+
"lib"
|
59
|
+
],
|
60
|
+
"dependencies": {
|
61
|
+
"@mikro-orm/core": "^6.4.3",
|
62
|
+
"@mikro-orm/mongodb": "^6.4.3",
|
63
|
+
"cors": "^2.8.5",
|
64
|
+
"jose": "^5.9.6",
|
65
|
+
"openapi3-ts": "^4.4.0",
|
66
|
+
"redis": "^4.7.0",
|
67
|
+
"uuid": "^11.0.5",
|
68
|
+
"@forklaunch/common": "0.2.0",
|
69
|
+
"@forklaunch/validator": "0.4.1"
|
70
|
+
},
|
71
|
+
"devDependencies": {
|
72
|
+
"@eslint/js": "^9.17.0",
|
73
|
+
"@types/cors": "^2.8.17",
|
74
|
+
"@types/jest": "^29.5.14",
|
75
|
+
"@types/qs": "^6.9.17",
|
76
|
+
"@types/uuid": "^10.0.0",
|
77
|
+
"globals": "^15.14.0",
|
78
|
+
"jest": "^29.7.0",
|
79
|
+
"prettier": "^3.4.2",
|
80
|
+
"testcontainers": "^10.16.0",
|
81
|
+
"ts-jest": "^29.2.5",
|
82
|
+
"ts-node": "^10.9.2",
|
83
|
+
"tsup": "^8.3.5",
|
84
|
+
"typedoc": "^0.27.6",
|
85
|
+
"typescript": "^5.7.3",
|
86
|
+
"typescript-eslint": "^8.19.1"
|
87
|
+
},
|
88
88
|
"scripts": {
|
89
|
-
"test": "vitest --passWithNoTests",
|
90
89
|
"build": "tsc --noEmit && tsup ./src/cache/index.ts ./src/controllers/index.ts ./src/database/index.ts ./src/dtoMapper/index.ts ./src/http/index.ts ./src/services/index.ts --format cjs,esm --no-splitting --dts --tsconfig tsconfig.json --out-dir lib --clean",
|
91
90
|
"clean": "rm -rf lib pnpm.lock.yaml node_modules",
|
92
91
|
"docs": "typedoc --out docs *",
|
92
|
+
"format": "prettier --ignore-path=.prettierignore --config .prettierrc '**/*.{ts,tsx,json}' --write",
|
93
93
|
"lint": "eslint . -c eslint.config.mjs",
|
94
94
|
"lint:fix": "eslint . -c eslint.config.mjs --fix",
|
95
|
-
"
|
96
|
-
"
|
95
|
+
"publish:package": "./publish-package.bash",
|
96
|
+
"test": "vitest --passWithNoTests"
|
97
97
|
}
|
98
98
|
}
|