keryx 0.1.2 → 0.2.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/classes/API.ts +24 -0
- package/config/index.ts +2 -0
- package/index.ts +2 -1
- package/package.json +2 -1
- package/util/config.ts +29 -0
- package/util/scaffold.ts +33 -0
package/classes/API.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { Glob } from "bun";
|
|
2
|
+
import fs from "fs";
|
|
1
3
|
import path from "path";
|
|
2
4
|
import { config } from "../config";
|
|
5
|
+
import { deepMerge } from "../util/config";
|
|
3
6
|
import { globLoader } from "../util/glob";
|
|
4
7
|
import type { Initializer, InitializerSortKeys } from "./Initializer";
|
|
5
8
|
import { Logger } from "./Logger";
|
|
@@ -43,6 +46,7 @@ export class API {
|
|
|
43
46
|
this.logger.warn("--- 🔄 Initializing process ---");
|
|
44
47
|
this.initialized = false;
|
|
45
48
|
|
|
49
|
+
await this.loadLocalConfig();
|
|
46
50
|
await this.findInitializers();
|
|
47
51
|
this.sortInitializers("loadPriority");
|
|
48
52
|
|
|
@@ -138,6 +142,26 @@ export class API {
|
|
|
138
142
|
flapPreventer = false;
|
|
139
143
|
}
|
|
140
144
|
|
|
145
|
+
private async loadLocalConfig() {
|
|
146
|
+
if (this.rootDir === this.packageDir) return;
|
|
147
|
+
|
|
148
|
+
const configDir = path.join(this.rootDir, "config");
|
|
149
|
+
if (!fs.existsSync(configDir)) return;
|
|
150
|
+
|
|
151
|
+
const glob = new Glob("**/*.ts");
|
|
152
|
+
for await (const file of glob.scan(configDir)) {
|
|
153
|
+
if (file.startsWith(".")) continue;
|
|
154
|
+
|
|
155
|
+
const fullPath = path.join(configDir, file);
|
|
156
|
+
const mod = await import(fullPath);
|
|
157
|
+
const overrides = mod.default ?? mod;
|
|
158
|
+
if (overrides && typeof overrides === "object") {
|
|
159
|
+
deepMerge(config, overrides);
|
|
160
|
+
this.logger.debug(`Loaded user config from config/${file}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
141
165
|
private async findInitializers() {
|
|
142
166
|
// Load framework initializers from the package directory
|
|
143
167
|
const frameworkInitializers = await globLoader<Initializer>(
|
package/config/index.ts
CHANGED
package/index.ts
CHANGED
|
@@ -19,7 +19,8 @@ import "./initializers/swagger";
|
|
|
19
19
|
export * from "./api";
|
|
20
20
|
export type { ActionMiddleware } from "./classes/Action";
|
|
21
21
|
export { ErrorStatusCodes, ErrorType, TypedError } from "./classes/TypedError";
|
|
22
|
-
export {
|
|
22
|
+
export type { KeryxConfig } from "./config";
|
|
23
|
+
export { deepMerge, loadFromEnvIfSet } from "./util/config";
|
|
23
24
|
export { globLoader } from "./util/glob";
|
|
24
25
|
export {
|
|
25
26
|
isSecret,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keryx",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"start": "bun keryx.ts start",
|
|
62
62
|
"dev": "bun --watch keryx.ts start",
|
|
63
63
|
"migrations": "bun run migrations.ts",
|
|
64
|
+
"test": "tsc && bun test",
|
|
64
65
|
"compile": "bun build keryx.ts --compile --outfile keryx",
|
|
65
66
|
"lint": "tsc && prettier --check .",
|
|
66
67
|
"format": "tsc && prettier --write ."
|
package/util/config.ts
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deep-merges source into target, mutating target in place.
|
|
3
|
+
Only plain objects are recursively merged; arrays and primitives are overwritten.
|
|
4
|
+
*/
|
|
5
|
+
export function deepMerge<T extends Record<string, any>>(
|
|
6
|
+
target: T,
|
|
7
|
+
source: Record<string, any>,
|
|
8
|
+
): T {
|
|
9
|
+
for (const key of Object.keys(source)) {
|
|
10
|
+
const targetVal = target[key];
|
|
11
|
+
const sourceVal = source[key];
|
|
12
|
+
|
|
13
|
+
if (
|
|
14
|
+
targetVal &&
|
|
15
|
+
sourceVal &&
|
|
16
|
+
typeof targetVal === "object" &&
|
|
17
|
+
typeof sourceVal === "object" &&
|
|
18
|
+
!Array.isArray(targetVal) &&
|
|
19
|
+
!Array.isArray(sourceVal)
|
|
20
|
+
) {
|
|
21
|
+
deepMerge(targetVal, sourceVal);
|
|
22
|
+
} else {
|
|
23
|
+
(target as any)[key] = sourceVal;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return target;
|
|
28
|
+
}
|
|
29
|
+
|
|
1
30
|
/**
|
|
2
31
|
Loads a value from the environment, if it's set, otherwise returns the default value.
|
|
3
32
|
*/
|
package/util/scaffold.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Glob } from "bun";
|
|
1
2
|
import fs from "fs";
|
|
2
3
|
import Mustache from "mustache";
|
|
3
4
|
import path from "path";
|
|
@@ -152,6 +153,38 @@ export async function scaffoldProject(
|
|
|
152
153
|
await writeTemplate("keryx.ts", "keryx.ts.mustache");
|
|
153
154
|
await writeTemplate(".env.example", "env.example.mustache");
|
|
154
155
|
await writeTemplate(".gitignore", "gitignore.mustache");
|
|
156
|
+
// Copy config files from the framework, adjusting imports for user projects
|
|
157
|
+
const configDir = path.join(import.meta.dir, "..", "config");
|
|
158
|
+
const glob = new Glob("**/*.ts");
|
|
159
|
+
for await (const file of glob.scan(configDir)) {
|
|
160
|
+
let content = await Bun.file(path.join(configDir, file)).text();
|
|
161
|
+
|
|
162
|
+
// Rewrite relative imports to package imports
|
|
163
|
+
content = content.replace(
|
|
164
|
+
/from ["']\.\.\/\.\.\/util\/config["']/g,
|
|
165
|
+
'from "keryx"',
|
|
166
|
+
);
|
|
167
|
+
content = content.replace(
|
|
168
|
+
/from ["']\.\.\/util\/config["']/g,
|
|
169
|
+
'from "keryx"',
|
|
170
|
+
);
|
|
171
|
+
content = content.replace(
|
|
172
|
+
/from ["']\.\.\/classes\/Logger["']/g,
|
|
173
|
+
'from "keryx/classes/Logger.ts"',
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// In index.ts, change `export const config` to `export default`
|
|
177
|
+
// and remove the KeryxConfig type export (it comes from the package)
|
|
178
|
+
if (file === "index.ts") {
|
|
179
|
+
content = content.replace("export const config =", "export default");
|
|
180
|
+
content = content.replace(
|
|
181
|
+
/\nexport type KeryxConfig = typeof config;\n/,
|
|
182
|
+
"\n",
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
await write(`config/${file}`, content);
|
|
187
|
+
}
|
|
155
188
|
|
|
156
189
|
// Create empty directories with .gitkeep
|
|
157
190
|
await write("initializers/.gitkeep", "");
|