@sockethub/server 5.0.0-alpha.4 → 5.0.0-alpha.6
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/README.md +54 -60
- package/bin/sockethub +4 -3
- package/package.json +42 -54
- package/res/socket.io.js +4908 -0
- package/res/sockethub-client.js +602 -0
- package/res/sockethub-client.min.js +19 -0
- package/sockethub.config.example.json +2 -3
- package/src/bootstrap/init.d.ts +16 -13
- package/src/bootstrap/init.test.ts +211 -0
- package/src/bootstrap/init.ts +152 -76
- package/src/bootstrap/load-platforms.ts +151 -0
- package/src/config.test.ts +27 -22
- package/src/config.ts +82 -86
- package/src/defaults.json +24 -16
- package/src/index.ts +61 -22
- package/src/janitor.test.ts +191 -169
- package/src/janitor.ts +141 -118
- package/src/listener.ts +148 -58
- package/src/middleware/create-activity-object.test.ts +28 -8
- package/src/middleware/create-activity-object.ts +16 -10
- package/src/middleware/expand-activity-stream.test.data.ts +331 -345
- package/src/middleware/expand-activity-stream.test.ts +65 -66
- package/src/middleware/expand-activity-stream.ts +26 -21
- package/src/middleware/store-credentials.test.ts +74 -60
- package/src/middleware/store-credentials.ts +14 -8
- package/src/middleware/validate.test.data.ts +240 -242
- package/src/middleware/validate.test.ts +39 -78
- package/src/middleware/validate.ts +62 -36
- package/src/middleware.test.ts +168 -138
- package/src/middleware.ts +57 -55
- package/src/platform-instance.test.ts +508 -214
- package/src/platform-instance.ts +324 -231
- package/src/platform.test.ts +375 -0
- package/src/platform.ts +306 -117
- package/src/process-manager.ts +75 -51
- package/src/routes.test.ts +43 -89
- package/src/routes.ts +40 -78
- package/src/sentry.test.ts +106 -0
- package/src/sentry.ts +19 -0
- package/src/sockethub.ts +190 -129
- package/src/util.ts +5 -0
- package/coverage/tmp/coverage-39338-1663949520416-0.json +0 -1
- package/dist/bootstrap/init.d.ts +0 -18
- package/dist/bootstrap/init.js +0 -64
- package/dist/bootstrap/init.js.map +0 -1
- package/dist/bootstrap/platforms.js +0 -75
- package/dist/config.d.ts +0 -12
- package/dist/config.js +0 -107
- package/dist/config.js.map +0 -1
- package/dist/defaults.json +0 -28
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -29
- package/dist/index.js.map +0 -1
- package/dist/janitor.d.ts +0 -30
- package/dist/janitor.js +0 -120
- package/dist/janitor.js.map +0 -1
- package/dist/listener.d.ts +0 -31
- package/dist/listener.js +0 -94
- package/dist/listener.js.map +0 -1
- package/dist/middleware/create-activity-object.d.ts +0 -8
- package/dist/middleware/create-activity-object.js +0 -19
- package/dist/middleware/create-activity-object.js.map +0 -1
- package/dist/middleware/expand-activity-stream.d.ts +0 -3
- package/dist/middleware/expand-activity-stream.js +0 -36
- package/dist/middleware/expand-activity-stream.js.map +0 -1
- package/dist/middleware/expand-activity-stream.test.data.d.ts +0 -480
- package/dist/middleware/expand-activity-stream.test.data.js +0 -360
- package/dist/middleware/expand-activity-stream.test.data.js.map +0 -1
- package/dist/middleware/store-credentials.d.ts +0 -3
- package/dist/middleware/store-credentials.js +0 -9
- package/dist/middleware/store-credentials.js.map +0 -1
- package/dist/middleware/validate.d.ts +0 -2
- package/dist/middleware/validate.js +0 -56
- package/dist/middleware/validate.js.map +0 -1
- package/dist/middleware/validate.test.data.d.ts +0 -532
- package/dist/middleware/validate.test.data.js +0 -263
- package/dist/middleware/validate.test.data.js.map +0 -1
- package/dist/middleware.d.ts +0 -21
- package/dist/middleware.js +0 -56
- package/dist/middleware.js.map +0 -1
- package/dist/platform-instance.d.ts +0 -78
- package/dist/platform-instance.js +0 -226
- package/dist/platform-instance.js.map +0 -1
- package/dist/platform.d.ts +0 -6
- package/dist/platform.js +0 -176
- package/dist/platform.js.map +0 -1
- package/dist/process-manager.d.ts +0 -11
- package/dist/process-manager.js +0 -82
- package/dist/process-manager.js.map +0 -1
- package/dist/routes.d.ts +0 -13
- package/dist/routes.js +0 -83
- package/dist/routes.js.map +0 -1
- package/dist/sockethub.d.ts +0 -18
- package/dist/sockethub.js +0 -112
- package/dist/sockethub.js.map +0 -1
- package/src/bootstrap/platforms.js +0 -75
- package/test/init-suite.js +0 -41
- package/test/sockethub-suite.js +0 -25
- package/tsconfig.json +0 -18
- package/views/examples/dummy.ejs +0 -95
- package/views/examples/feeds.ejs +0 -90
- package/views/examples/irc.ejs +0 -239
- package/views/examples/shared.js +0 -72
- package/views/examples/xmpp.ejs +0 -217
- package/views/index.ejs +0 -17
package/src/bootstrap/init.ts
CHANGED
|
@@ -1,84 +1,160 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import debug from "debug";
|
|
4
|
+
|
|
5
|
+
import { type RedisConfig, redisCheck } from "@sockethub/data-layer";
|
|
6
|
+
|
|
7
|
+
import { addPlatformSchema } from "@sockethub/schemas";
|
|
8
|
+
import config from "../config.js";
|
|
9
|
+
import loadPlatforms, {
|
|
10
|
+
type PlatformMap,
|
|
11
|
+
type PlatformStruct,
|
|
12
|
+
} from "./load-platforms.js";
|
|
13
|
+
|
|
14
|
+
const log = debug("sockethub:server:bootstrap:init");
|
|
15
|
+
|
|
16
|
+
export interface IInitObject {
|
|
17
|
+
version: string;
|
|
18
|
+
platforms: PlatformMap;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let init: IInitObject;
|
|
22
|
+
|
|
23
|
+
function getExecutablePath(): string {
|
|
24
|
+
// Primary: use the actual invoked script path
|
|
25
|
+
if (process.argv[1]) {
|
|
26
|
+
return process.argv[1];
|
|
27
|
+
}
|
|
28
|
+
// Fallback: resolve from import.meta.url
|
|
29
|
+
return fileURLToPath(import.meta.url);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function printSettingsInfo(
|
|
33
|
+
version: string,
|
|
34
|
+
platforms: Map<string, PlatformStruct>,
|
|
35
|
+
) {
|
|
36
|
+
const execPath = getExecutablePath();
|
|
37
|
+
|
|
38
|
+
console.log(`${chalk.cyan("sockethub")} ${version}`);
|
|
39
|
+
console.log(`${chalk.cyan("executable:")} ${execPath}`);
|
|
40
|
+
|
|
41
|
+
const wsUrl = `ws://${config.get("sockethub:host")}:${config.get("sockethub:port")}${config.get("sockethub:path")}`;
|
|
42
|
+
console.log(`${chalk.cyan("websocket:")} ${chalk.blue(wsUrl)}`);
|
|
43
|
+
|
|
44
|
+
const examplesUrl = `http://${config.get("public:host")}:${config.get(
|
|
45
|
+
"public:port",
|
|
46
|
+
)}${config.get("public:path")}`;
|
|
47
|
+
console.log(
|
|
48
|
+
`${chalk.cyan("examples:")} ${config.get("examples") ? chalk.blue(examplesUrl) : "disabled"}`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
console.log(
|
|
52
|
+
`${chalk.cyan("redis URL:")} ${chalk.blue(config.get("redis:url"))}`,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
console.log(
|
|
56
|
+
`${chalk.cyan("platforms:")} ${Array.from(platforms.keys()).join(", ")}`,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
if (platforms.size > 0) {
|
|
60
|
+
for (const platform of platforms.values()) {
|
|
61
|
+
console.log();
|
|
62
|
+
console.log(chalk.green(`- ${platform.moduleName}`));
|
|
63
|
+
console.log(` ${chalk.dim("version:")} ${platform.version}`);
|
|
64
|
+
console.log(
|
|
65
|
+
` ${chalk.dim("AS types:")} ${platform.types.map((t) => chalk.yellow(t)).join(", ")}`,
|
|
66
|
+
);
|
|
67
|
+
if (platform.modulePath) {
|
|
68
|
+
console.log(` ${chalk.dim("path:")} ${platform.modulePath}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
52
71
|
}
|
|
53
72
|
console.log();
|
|
54
73
|
process.exit();
|
|
55
|
-
} else {
|
|
56
|
-
console.log();
|
|
57
|
-
process.exit();
|
|
58
|
-
}
|
|
59
74
|
}
|
|
60
75
|
|
|
61
|
-
|
|
76
|
+
let initCalled = false;
|
|
77
|
+
let initWaitCount = 0;
|
|
78
|
+
let cancelWait: Timer;
|
|
79
|
+
const resolveQueue = [];
|
|
62
80
|
|
|
63
|
-
export
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
export default async function getInitObject(
|
|
82
|
+
initFunc: () => Promise<IInitObject> = __loadInit,
|
|
83
|
+
): Promise<IInitObject> {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
if (initCalled) {
|
|
86
|
+
if (init) {
|
|
87
|
+
resolve(init);
|
|
88
|
+
} else if (!cancelWait) {
|
|
89
|
+
cancelWait = setInterval(() => {
|
|
90
|
+
if (!init) {
|
|
91
|
+
if (initWaitCount > 10) {
|
|
92
|
+
reject("failed to initialize");
|
|
93
|
+
}
|
|
94
|
+
initWaitCount++;
|
|
95
|
+
} else {
|
|
96
|
+
clearInterval(cancelWait);
|
|
97
|
+
resolve(init);
|
|
98
|
+
for (const resolve of resolveQueue) {
|
|
99
|
+
resolve(init);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}, 1000);
|
|
103
|
+
} else {
|
|
104
|
+
resolveQueue.push(resolve);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
initCalled = true;
|
|
108
|
+
if (init) {
|
|
109
|
+
resolve(init);
|
|
110
|
+
} else {
|
|
111
|
+
initFunc()
|
|
112
|
+
.then((_init) => {
|
|
113
|
+
init = _init;
|
|
114
|
+
return registerPlatforms(_init);
|
|
115
|
+
})
|
|
116
|
+
.then(() => {
|
|
117
|
+
resolve(init);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
78
122
|
}
|
|
79
123
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
124
|
+
export async function registerPlatforms(initObj: IInitObject): Promise<void> {
|
|
125
|
+
for (const [_, platform] of initObj.platforms) {
|
|
126
|
+
for (const key of Object.keys(platform.schemas)) {
|
|
127
|
+
if (!platform.schemas[key]) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
addPlatformSchema(platform.schemas[key], `${platform.id}/${key}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function __loadInit(): Promise<IInitObject> {
|
|
136
|
+
log("running init routines");
|
|
137
|
+
const packageJSON = await import("./../../package.json", {
|
|
138
|
+
with: { type: "json" },
|
|
139
|
+
});
|
|
140
|
+
const version = packageJSON.default.version;
|
|
141
|
+
const platforms = await loadPlatforms(
|
|
142
|
+
config.get("platforms") as Array<string>,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
await redisCheck(config.get("redis") as RedisConfig);
|
|
146
|
+
|
|
147
|
+
if (config.get("info")) {
|
|
148
|
+
printSettingsInfo(packageJSON.default.version, platforms);
|
|
149
|
+
}
|
|
150
|
+
log("finished init routines");
|
|
151
|
+
return {
|
|
152
|
+
version: version,
|
|
153
|
+
platforms: platforms,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function __clearInit() {
|
|
158
|
+
init = undefined;
|
|
159
|
+
initCalled = false;
|
|
160
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bootstrap/platforms.ts
|
|
3
|
+
*
|
|
4
|
+
* A Singleton responsible for finding and loading all valid Sockethub
|
|
5
|
+
* platforms, and whitelisting or blacklisting (or neither) based on the
|
|
6
|
+
* config.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import debug from "debug";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
type PlatformConfig,
|
|
15
|
+
type PlatformInterface,
|
|
16
|
+
type PlatformSchemaStruct,
|
|
17
|
+
type PlatformSession,
|
|
18
|
+
validatePlatformSchema,
|
|
19
|
+
} from "@sockethub/schemas";
|
|
20
|
+
|
|
21
|
+
const log = debug("sockethub:server:bootstrap:platforms");
|
|
22
|
+
|
|
23
|
+
export type PlatformStruct = {
|
|
24
|
+
id: string;
|
|
25
|
+
moduleName: string;
|
|
26
|
+
modulePath?: string;
|
|
27
|
+
config: PlatformConfig;
|
|
28
|
+
schemas: PlatformSchemaStruct;
|
|
29
|
+
version: string;
|
|
30
|
+
types: Array<string>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type PlatformMap = Map<string, PlatformStruct>;
|
|
34
|
+
|
|
35
|
+
const dummySession: PlatformSession = {
|
|
36
|
+
debug: () => {},
|
|
37
|
+
sendToClient: () => {},
|
|
38
|
+
updateActor: async () => {},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// if the platform schema lists valid types it implements (essentially methods/verbs for
|
|
42
|
+
// Sockethub to call) then add it to the supported types list.
|
|
43
|
+
function platformListsSupportedTypes(p): boolean {
|
|
44
|
+
return (
|
|
45
|
+
p.schema.messages.properties?.type?.enum &&
|
|
46
|
+
p.schema.messages.properties.type.enum.length > 0
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Resolve the absolute filesystem path to a platform module
|
|
51
|
+
function resolveModulePath(platformName: string): string | undefined {
|
|
52
|
+
try {
|
|
53
|
+
// Resolve to file:// URL
|
|
54
|
+
const resolved = import.meta.resolve(platformName);
|
|
55
|
+
|
|
56
|
+
// Convert to absolute path
|
|
57
|
+
const filePath = fileURLToPath(resolved);
|
|
58
|
+
|
|
59
|
+
// Walk up to find package.json (package root)
|
|
60
|
+
let dir = dirname(filePath);
|
|
61
|
+
for (let i = 0; i < 5; i++) {
|
|
62
|
+
const pkgPath = join(dir, "package.json");
|
|
63
|
+
if (existsSync(pkgPath)) {
|
|
64
|
+
return dir;
|
|
65
|
+
}
|
|
66
|
+
dir = dirname(dir);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fallback: return directory of entry point
|
|
70
|
+
return dirname(filePath);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
log(
|
|
73
|
+
`failed to resolve module path for ${platformName}: ${err.message}`,
|
|
74
|
+
);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function loadPlatform(platformName: string, injectRequire) {
|
|
80
|
+
log(`loading ${platformName}`);
|
|
81
|
+
let p: PlatformInterface;
|
|
82
|
+
if (injectRequire) {
|
|
83
|
+
const P = await injectRequire(platformName);
|
|
84
|
+
p = new P();
|
|
85
|
+
} else {
|
|
86
|
+
const P = await import(platformName);
|
|
87
|
+
p = new P.default(dummySession);
|
|
88
|
+
}
|
|
89
|
+
const err = validatePlatformSchema(p.schema);
|
|
90
|
+
|
|
91
|
+
if (err) {
|
|
92
|
+
throw new Error(`${platformName} ${err}`);
|
|
93
|
+
}
|
|
94
|
+
if (typeof p.config !== "object") {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`${platformName} platform must have a config property that is an object.`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return p;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default async function loadPlatforms(
|
|
103
|
+
platformsList: Array<string>,
|
|
104
|
+
injectRequire = undefined,
|
|
105
|
+
): Promise<PlatformMap> {
|
|
106
|
+
log(`platforms to load: ${platformsList}`);
|
|
107
|
+
// load platforms from config.platforms
|
|
108
|
+
const platforms = new Map();
|
|
109
|
+
|
|
110
|
+
if (platformsList.length <= 0) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
"No platforms defined. Please check your sockethub.config.json",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const platformName of platformsList) {
|
|
117
|
+
const p = await loadPlatform(platformName, injectRequire);
|
|
118
|
+
let types = [];
|
|
119
|
+
|
|
120
|
+
if (p.schema.credentials) {
|
|
121
|
+
// register the platforms credentials schema
|
|
122
|
+
types.push("credentials");
|
|
123
|
+
} else {
|
|
124
|
+
p.config.requireCredentials = [];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (platformListsSupportedTypes(p)) {
|
|
128
|
+
types = [...types, ...p.schema.messages.properties.type.enum];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Resolve module path (skip in test mode with injectRequire)
|
|
132
|
+
const modulePath = injectRequire
|
|
133
|
+
? undefined
|
|
134
|
+
: resolveModulePath(platformName);
|
|
135
|
+
|
|
136
|
+
platforms.set(p.schema.name, {
|
|
137
|
+
id: p.schema.name,
|
|
138
|
+
moduleName: p.schema.name,
|
|
139
|
+
modulePath: modulePath,
|
|
140
|
+
config: p.config,
|
|
141
|
+
schemas: {
|
|
142
|
+
credentials: p.schema.credentials || {},
|
|
143
|
+
messages: p.schema.messages || {},
|
|
144
|
+
},
|
|
145
|
+
version: p.schema.version,
|
|
146
|
+
types: types,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return platforms;
|
|
151
|
+
}
|
package/src/config.test.ts
CHANGED
|
@@ -1,28 +1,33 @@
|
|
|
1
|
-
import { expect } from
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import { Config } from
|
|
3
|
+
import { Config } from "./config.js";
|
|
4
4
|
|
|
5
|
-
describe(
|
|
5
|
+
describe("config", () => {
|
|
6
|
+
it("loads default values", () => {
|
|
7
|
+
const config = new Config();
|
|
8
|
+
expect(config).toHaveProperty("get");
|
|
9
|
+
expect(config.get("sockethub:host")).toEqual("localhost");
|
|
10
|
+
});
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
it("host overrides from env", () => {
|
|
13
|
+
const hostname = "a host string";
|
|
14
|
+
process.env = { HOST: hostname };
|
|
15
|
+
const config = new Config();
|
|
16
|
+
expect(config).toHaveProperty("get");
|
|
17
|
+
expect(config.get("sockethub:host")).toEqual(hostname);
|
|
18
|
+
});
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
+
it("defaults to redis config", () => {
|
|
21
|
+
process.env = { REDIS_URL: "" };
|
|
22
|
+
const config = new Config();
|
|
23
|
+
expect(config).toHaveProperty("get");
|
|
24
|
+
expect(config.get("redis")).toEqual({ url: "redis://127.0.0.1:6379" });
|
|
25
|
+
});
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
process.env = { REDIS_URL:
|
|
23
|
-
const config = new Config();
|
|
24
|
-
expect(config).
|
|
25
|
-
expect(config.get(
|
|
26
|
-
|
|
27
|
-
});
|
|
27
|
+
// it("redis url overridden by env var", () => {
|
|
28
|
+
// process.env = { REDIS_URL: "foobar83" };
|
|
29
|
+
// const config = new Config();
|
|
30
|
+
// expect(config).toHaveProperty("get");
|
|
31
|
+
// expect(config.get("redis")).toEqual({ url: "foobar83" });
|
|
32
|
+
// });
|
|
28
33
|
});
|
package/src/config.ts
CHANGED
|
@@ -1,101 +1,97 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import debug from "debug";
|
|
4
|
+
import nconf from "nconf";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import { __dirname } from "./util.js";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
customProps?: object;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class Config {
|
|
15
|
-
constructor() {
|
|
16
|
-
log('initializing config');
|
|
17
|
-
// assign config loading priorities (command-line, environment, cfg, defaults)
|
|
18
|
-
nconf.argv({
|
|
19
|
-
'info': {
|
|
20
|
-
type: 'boolean',
|
|
21
|
-
describe: 'Display Sockethub runtime information'
|
|
22
|
-
},
|
|
23
|
-
'examples': {
|
|
24
|
-
type: 'boolean',
|
|
25
|
-
describe: 'Enable the examples pages served at [host]:[port]/examples'
|
|
26
|
-
},
|
|
27
|
-
'config': {
|
|
28
|
-
alias: 'c',
|
|
29
|
-
default: '',
|
|
30
|
-
describe: 'Path to sockethub.config.json'
|
|
31
|
-
},
|
|
32
|
-
'port': {
|
|
33
|
-
alias: 'sockethub.port'
|
|
34
|
-
},
|
|
35
|
-
'host': {
|
|
36
|
-
alias: 'sockethub.host'
|
|
37
|
-
},
|
|
38
|
-
'redis_host': {
|
|
39
|
-
alias: 'redis.host'
|
|
40
|
-
},
|
|
41
|
-
'redis_port': {
|
|
42
|
-
alias: 'redis.port'
|
|
43
|
-
},
|
|
44
|
-
'redis_url': {
|
|
45
|
-
alias: 'redis.url'
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
nconf.env();
|
|
8
|
+
const log = debug("sockethub:server:bootstrap:config");
|
|
9
|
+
const data = JSON.parse(
|
|
10
|
+
fs.readFileSync(path.resolve(__dirname, "defaults.json"), "utf-8"),
|
|
11
|
+
);
|
|
49
12
|
|
|
50
|
-
|
|
51
|
-
const examples = nconf.get('examples');
|
|
13
|
+
const defaultConfig = "sockethub.config.json";
|
|
52
14
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
15
|
+
export class Config {
|
|
16
|
+
constructor() {
|
|
17
|
+
log("initializing config");
|
|
18
|
+
// assign config loading priorities (command-line, environment, cfg, defaults)
|
|
19
|
+
nconf.argv({
|
|
20
|
+
info: {
|
|
21
|
+
type: "boolean",
|
|
22
|
+
describe: "Display Sockethub runtime information",
|
|
23
|
+
},
|
|
24
|
+
examples: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
describe:
|
|
27
|
+
"Enable the examples pages served at [host]:[port]/examples",
|
|
28
|
+
},
|
|
29
|
+
config: {
|
|
30
|
+
alias: "c",
|
|
31
|
+
type: "string",
|
|
32
|
+
describe: "Path to sockethub.config.json",
|
|
33
|
+
},
|
|
34
|
+
port: {
|
|
35
|
+
type: "number",
|
|
36
|
+
alias: "sockethub.port",
|
|
37
|
+
},
|
|
38
|
+
host: {
|
|
39
|
+
type: "string",
|
|
40
|
+
alias: "sockethub.host",
|
|
41
|
+
},
|
|
42
|
+
"redis.url": {
|
|
43
|
+
type: "string",
|
|
44
|
+
describe: "Redis URL e.g. redis://host:port",
|
|
45
|
+
},
|
|
46
|
+
"sentry.dsn": {
|
|
47
|
+
type: "string",
|
|
48
|
+
describe: "Provide your Sentry DSN",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
63
51
|
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
// get value of flags defined by any command-line params
|
|
53
|
+
const examples = nconf.get("examples");
|
|
66
54
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
// Load the main config
|
|
56
|
+
let configFile = nconf.get("config");
|
|
57
|
+
if (configFile) {
|
|
58
|
+
configFile = path.resolve(configFile);
|
|
59
|
+
if (!fs.existsSync(configFile)) {
|
|
60
|
+
throw new Error(`Config file not found: ${configFile}`);
|
|
61
|
+
}
|
|
62
|
+
log(`reading config file at ${configFile}`);
|
|
63
|
+
nconf.file(configFile);
|
|
64
|
+
} else {
|
|
65
|
+
if (fs.existsSync(`${process.cwd()}/${defaultConfig}`)) {
|
|
66
|
+
log(`loading local ${defaultConfig}`);
|
|
67
|
+
nconf.file(`${process.cwd()}/${defaultConfig}`);
|
|
68
|
+
}
|
|
69
|
+
nconf.use("memory");
|
|
70
|
+
}
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
// only override config file if explicitly mentioned in command-line params
|
|
73
|
+
nconf.set("examples", examples ? true : nconf.get("examples"));
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
nconf.set(prop + ':port', port);
|
|
77
|
-
}
|
|
75
|
+
// load defaults
|
|
76
|
+
nconf.defaults(data);
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
process.env.HOST || nconf.get('sockethub:host'),
|
|
81
|
-
process.env.PORT || nconf.get('sockethub:port'),
|
|
82
|
-
'sockethub'
|
|
83
|
-
);
|
|
78
|
+
nconf.required(["platforms"]);
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
nconf.set(
|
|
81
|
+
"sockethub:host",
|
|
82
|
+
process.env.HOST || nconf.get("sockethub:host"),
|
|
83
|
+
);
|
|
84
|
+
nconf.set(
|
|
85
|
+
"sockethub:port",
|
|
86
|
+
process.env.PORT || nconf.get("sockethub:port"),
|
|
87
|
+
);
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
nconf.clear('redis:port');
|
|
89
|
+
// allow a redis://user:host:port url, takes precedence
|
|
90
|
+
if (process.env.REDIS_URL) {
|
|
91
|
+
nconf.set("redis:url", process.env.REDIS_URL);
|
|
92
|
+
}
|
|
96
93
|
}
|
|
97
|
-
|
|
98
|
-
get = (key: string): unknown => nconf.get(key);
|
|
94
|
+
get = (key: string) => nconf.get(key);
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
const config = new Config();
|