@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.
Files changed (105) hide show
  1. package/README.md +54 -60
  2. package/bin/sockethub +4 -3
  3. package/package.json +42 -54
  4. package/res/socket.io.js +4908 -0
  5. package/res/sockethub-client.js +602 -0
  6. package/res/sockethub-client.min.js +19 -0
  7. package/sockethub.config.example.json +2 -3
  8. package/src/bootstrap/init.d.ts +16 -13
  9. package/src/bootstrap/init.test.ts +211 -0
  10. package/src/bootstrap/init.ts +152 -76
  11. package/src/bootstrap/load-platforms.ts +151 -0
  12. package/src/config.test.ts +27 -22
  13. package/src/config.ts +82 -86
  14. package/src/defaults.json +24 -16
  15. package/src/index.ts +61 -22
  16. package/src/janitor.test.ts +191 -169
  17. package/src/janitor.ts +141 -118
  18. package/src/listener.ts +148 -58
  19. package/src/middleware/create-activity-object.test.ts +28 -8
  20. package/src/middleware/create-activity-object.ts +16 -10
  21. package/src/middleware/expand-activity-stream.test.data.ts +331 -345
  22. package/src/middleware/expand-activity-stream.test.ts +65 -66
  23. package/src/middleware/expand-activity-stream.ts +26 -21
  24. package/src/middleware/store-credentials.test.ts +74 -60
  25. package/src/middleware/store-credentials.ts +14 -8
  26. package/src/middleware/validate.test.data.ts +240 -242
  27. package/src/middleware/validate.test.ts +39 -78
  28. package/src/middleware/validate.ts +62 -36
  29. package/src/middleware.test.ts +168 -138
  30. package/src/middleware.ts +57 -55
  31. package/src/platform-instance.test.ts +508 -214
  32. package/src/platform-instance.ts +324 -231
  33. package/src/platform.test.ts +375 -0
  34. package/src/platform.ts +306 -117
  35. package/src/process-manager.ts +75 -51
  36. package/src/routes.test.ts +43 -89
  37. package/src/routes.ts +40 -78
  38. package/src/sentry.test.ts +106 -0
  39. package/src/sentry.ts +19 -0
  40. package/src/sockethub.ts +190 -129
  41. package/src/util.ts +5 -0
  42. package/coverage/tmp/coverage-39338-1663949520416-0.json +0 -1
  43. package/dist/bootstrap/init.d.ts +0 -18
  44. package/dist/bootstrap/init.js +0 -64
  45. package/dist/bootstrap/init.js.map +0 -1
  46. package/dist/bootstrap/platforms.js +0 -75
  47. package/dist/config.d.ts +0 -12
  48. package/dist/config.js +0 -107
  49. package/dist/config.js.map +0 -1
  50. package/dist/defaults.json +0 -28
  51. package/dist/index.d.ts +0 -1
  52. package/dist/index.js +0 -29
  53. package/dist/index.js.map +0 -1
  54. package/dist/janitor.d.ts +0 -30
  55. package/dist/janitor.js +0 -120
  56. package/dist/janitor.js.map +0 -1
  57. package/dist/listener.d.ts +0 -31
  58. package/dist/listener.js +0 -94
  59. package/dist/listener.js.map +0 -1
  60. package/dist/middleware/create-activity-object.d.ts +0 -8
  61. package/dist/middleware/create-activity-object.js +0 -19
  62. package/dist/middleware/create-activity-object.js.map +0 -1
  63. package/dist/middleware/expand-activity-stream.d.ts +0 -3
  64. package/dist/middleware/expand-activity-stream.js +0 -36
  65. package/dist/middleware/expand-activity-stream.js.map +0 -1
  66. package/dist/middleware/expand-activity-stream.test.data.d.ts +0 -480
  67. package/dist/middleware/expand-activity-stream.test.data.js +0 -360
  68. package/dist/middleware/expand-activity-stream.test.data.js.map +0 -1
  69. package/dist/middleware/store-credentials.d.ts +0 -3
  70. package/dist/middleware/store-credentials.js +0 -9
  71. package/dist/middleware/store-credentials.js.map +0 -1
  72. package/dist/middleware/validate.d.ts +0 -2
  73. package/dist/middleware/validate.js +0 -56
  74. package/dist/middleware/validate.js.map +0 -1
  75. package/dist/middleware/validate.test.data.d.ts +0 -532
  76. package/dist/middleware/validate.test.data.js +0 -263
  77. package/dist/middleware/validate.test.data.js.map +0 -1
  78. package/dist/middleware.d.ts +0 -21
  79. package/dist/middleware.js +0 -56
  80. package/dist/middleware.js.map +0 -1
  81. package/dist/platform-instance.d.ts +0 -78
  82. package/dist/platform-instance.js +0 -226
  83. package/dist/platform-instance.js.map +0 -1
  84. package/dist/platform.d.ts +0 -6
  85. package/dist/platform.js +0 -176
  86. package/dist/platform.js.map +0 -1
  87. package/dist/process-manager.d.ts +0 -11
  88. package/dist/process-manager.js +0 -82
  89. package/dist/process-manager.js.map +0 -1
  90. package/dist/routes.d.ts +0 -13
  91. package/dist/routes.js +0 -83
  92. package/dist/routes.js.map +0 -1
  93. package/dist/sockethub.d.ts +0 -18
  94. package/dist/sockethub.js +0 -112
  95. package/dist/sockethub.js.map +0 -1
  96. package/src/bootstrap/platforms.js +0 -75
  97. package/test/init-suite.js +0 -41
  98. package/test/sockethub-suite.js +0 -25
  99. package/tsconfig.json +0 -18
  100. package/views/examples/dummy.ejs +0 -95
  101. package/views/examples/feeds.ejs +0 -90
  102. package/views/examples/irc.ejs +0 -239
  103. package/views/examples/shared.js +0 -72
  104. package/views/examples/xmpp.ejs +0 -217
  105. package/views/index.ejs +0 -17
@@ -1,84 +1,160 @@
1
- import debug from 'debug';
2
-
3
- import config from '../config';
4
- import platformLoad from './platforms';
5
-
6
- const log = debug('sockethub:server:bootstrap:init');
7
- log('running init routines');
8
-
9
- // eslint-disable-next-line @typescript-eslint/no-var-requires
10
- const packageJSON = require('./../../package.json');
11
- const platforms = platformLoad(config.get('platforms'));
12
-
13
- if (config.get('info')) {
14
- // eslint-disable-next-line security-node/detect-crlf
15
- console.log('sockethub ' + packageJSON.version);
16
- console.log();
17
-
18
- // eslint-disable-next-line security-node/detect-crlf
19
- console.log('websocket: ws://' + config.get('sockethub:host') + ':'
20
- + config.get('sockethub:port')
21
- + config.get('sockethub:path'));
22
-
23
- console.log();
24
- // eslint-disable-next-line security-node/detect-crlf
25
- console.log('examples: ' + (config.get('examples:enabled') ?
26
- 'http://' +
27
- config.get('public:host') + ':' + config.get('public:port') + config.get('public:path')
28
- : 'disabled'));
29
-
30
- console.log();
31
- if (config.get('redis:url')) {
32
- // eslint-disable-next-line security-node/detect-crlf
33
- console.log('redis URL: ' + config.get('redis:url'));
34
- } else {
35
- // eslint-disable-next-line security-node/detect-crlf
36
- console.log('redis: ' + config.get('redis:host') + ':' + config.get('redis:port'));
37
- }
38
-
39
- console.log();
40
- // eslint-disable-next-line security-node/detect-crlf
41
- console.log('platforms: ' + Array.from(platforms.keys()).join(', '));
42
-
43
- if (platforms.size > 0) {
44
- for (const platform of platforms.values()) {
45
- console.log();
46
- // eslint-disable-next-line security-node/detect-crlf
47
- console.log(platform.moduleName);
48
- // eslint-disable-next-line security-node/detect-crlf
49
- console.log(' name: ' + platform.id + ' version: ' + platform.version);
50
- // eslint-disable-next-line security-node/detect-crlf
51
- console.log(' AS types: ' + platform.types.join(', '));
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
- log('finished init routines');
76
+ let initCalled = false;
77
+ let initWaitCount = 0;
78
+ let cancelWait: Timer;
79
+ const resolveQueue = [];
62
80
 
63
- export interface IInitObject {
64
- version: string,
65
- platforms: Map<string, {
66
- id: string,
67
- moduleName: string,
68
- config: {
69
- persist?: boolean
70
- },
71
- schemas: {
72
- credentials?: object,
73
- messages?: object
74
- },
75
- version: string,
76
- types: Array<string>
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
- const init: IInitObject = {
81
- version: packageJSON.version,
82
- platforms: platforms
83
- };
84
- export default init;
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
+ }
@@ -1,28 +1,33 @@
1
- import { expect } from 'chai';
1
+ import { describe, expect, it } from "bun:test";
2
2
 
3
- import { Config } from './config';
3
+ import { Config } from "./config.js";
4
4
 
5
- describe('config', () => {
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
- it('loads default values', () => {
8
- const config = new Config();
9
- expect(config).to.have.property('get');
10
- expect(config.get('sockethub:host')).to.eql('localhost');
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
- it('overrides from env', () => {
14
- const hostname = 'a host string';
15
- process.env = { HOST: hostname };
16
- const config = new Config();
17
- expect(config).to.have.property('get');
18
- expect(config.get('sockethub:host')).to.eql(hostname);
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
- it('defaults to redis config', () => {
22
- process.env = { REDIS_URL: '' };
23
- const config = new Config();
24
- expect(config).to.have.property('get');
25
- expect(config.get('redis')).to.eql(
26
- {"host": "127.0.0.1", "port": 6379});
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 nconf from 'nconf';
2
- import { debug } from 'debug';
3
- import * as fs from "fs";
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
- const log = debug('sockethub:server:bootstrap:config');
6
+ import { __dirname } from "./util.js";
6
7
 
7
- export type ActivityStreamConfigOptions = {
8
- warnOnUnknownObjectProperties?: boolean;
9
- failOnUnknownObjectProperties?: boolean;
10
- specialObjs?: object;
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
- // get value of flags defined by any command-line params
51
- const examples = nconf.get('examples');
13
+ const defaultConfig = "sockethub.config.json";
52
14
 
53
- // Load the main config
54
- let configFile = nconf.get('config');
55
- if (configFile) {
56
- if (! fs.existsSync(configFile)) {
57
- throw new Error(`Config file not found: ${configFile}`);
58
- }
59
- } else {
60
- configFile = __dirname + '/../sockethub.config.json';
61
- }
62
- nconf.file(configFile);
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
- // only override config file if explicitly mentioned in command-line params
65
- nconf.set('examples:enabled', (examples ? true : nconf.get('examples:enabled')));
52
+ // get value of flags defined by any command-line params
53
+ const examples = nconf.get("examples");
66
54
 
67
- // load defaults
68
- // eslint-disable-next-line @typescript-eslint/no-var-requires
69
- const defaults: object = require(__dirname + '/defaults.json');
70
- nconf.defaults(defaults);
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
- nconf.required(['platforms']);
72
+ // only override config file if explicitly mentioned in command-line params
73
+ nconf.set("examples", examples ? true : nconf.get("examples"));
73
74
 
74
- function defaultEnvParams(host: string, port: string | number, prop: string) {
75
- nconf.set(prop + ':host', host);
76
- nconf.set(prop + ':port', port);
77
- }
75
+ // load defaults
76
+ nconf.defaults(data);
78
77
 
79
- defaultEnvParams(
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
- defaultEnvParams(
86
- process.env.REDIS_HOST || nconf.get('redis:host'),
87
- process.env.REDIS_PORT || nconf.get('redis:port'),
88
- 'redis'
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
- // allow a redis://user:host:port url, takes precedence
92
- if (process.env.REDIS_URL) {
93
- nconf.set('redis:url', process.env.REDIS_URL);
94
- nconf.clear('redis:host');
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();