@ai-devkit/channel-connector 0.6.0 → 0.8.0

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 (35) hide show
  1. package/.swcrc +27 -0
  2. package/dist/ChannelManager.d.ts +1 -1
  3. package/dist/ChannelManager.d.ts.map +1 -1
  4. package/dist/ChannelManager.js +9 -19
  5. package/dist/ChannelManager.js.map +1 -1
  6. package/dist/ConfigStore.d.ts +1 -1
  7. package/dist/ConfigStore.d.ts.map +1 -1
  8. package/dist/ConfigStore.js +25 -57
  9. package/dist/ConfigStore.js.map +1 -1
  10. package/dist/__tests__/ChannelManager.test.js +70 -0
  11. package/dist/__tests__/ChannelManager.test.js.map +1 -0
  12. package/dist/__tests__/ConfigStore.test.js +146 -0
  13. package/dist/__tests__/ConfigStore.test.js.map +1 -0
  14. package/dist/__tests__/adapters/TelegramAdapter.test.js +240 -0
  15. package/dist/__tests__/adapters/TelegramAdapter.test.js.map +1 -0
  16. package/dist/__tests__/utils/telegramHtml.test.js +86 -0
  17. package/dist/__tests__/utils/telegramHtml.test.js.map +1 -0
  18. package/dist/adapters/ChannelAdapter.d.ts +1 -1
  19. package/dist/adapters/ChannelAdapter.d.ts.map +1 -1
  20. package/dist/adapters/ChannelAdapter.js +7 -2
  21. package/dist/adapters/ChannelAdapter.js.map +1 -1
  22. package/dist/adapters/TelegramAdapter.d.ts +2 -2
  23. package/dist/adapters/TelegramAdapter.d.ts.map +1 -1
  24. package/dist/adapters/TelegramAdapter.js +32 -47
  25. package/dist/adapters/TelegramAdapter.js.map +1 -1
  26. package/dist/index.d.ts +6 -6
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -11
  29. package/dist/index.js.map +1 -1
  30. package/dist/types.js +7 -2
  31. package/dist/types.js.map +1 -1
  32. package/dist/utils/telegramHtml.js +36 -35
  33. package/dist/utils/telegramHtml.js.map +1 -1
  34. package/package.json +17 -12
  35. package/vitest.config.ts +20 -0
package/.swcrc ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/swcrc",
3
+ "jsc": {
4
+ "parser": {
5
+ "syntax": "typescript",
6
+ "tsx": true,
7
+ "decorators": false,
8
+ "dynamicImport": true
9
+ },
10
+ "transform": {
11
+ "react": {
12
+ "runtime": "automatic"
13
+ }
14
+ },
15
+ "target": "es2022",
16
+ "loose": false,
17
+ "externalHelpers": false,
18
+ "keepClassNames": true
19
+ },
20
+ "module": {
21
+ "type": "es6",
22
+ "strict": true,
23
+ "noInterop": false
24
+ },
25
+ "sourceMaps": true,
26
+ "minify": false
27
+ }
@@ -1,4 +1,4 @@
1
- import type { ChannelAdapter } from './adapters/ChannelAdapter';
1
+ import type { ChannelAdapter } from './adapters/ChannelAdapter.js';
2
2
  /**
3
3
  * Central registry for channel adapters.
4
4
  * Manages adapter lifecycle (start/stop).
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelManager.d.ts","sourceRoot":"","sources":["../src/ChannelManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;;GAGG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAO9C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIpD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAIjC"}
1
+ {"version":3,"file":"ChannelManager.d.ts","sourceRoot":"","sources":["../src/ChannelManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;GAGG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAO9C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIpD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAIjC"}
@@ -1,19 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChannelManager = void 0;
4
1
  /**
5
2
  * Central registry for channel adapters.
6
3
  * Manages adapter lifecycle (start/stop).
7
- */
8
- class ChannelManager {
9
- constructor() {
10
- this.adapters = new Map();
11
- }
4
+ */ export class ChannelManager {
5
+ adapters = new Map();
12
6
  /**
13
7
  * Register a channel adapter.
14
8
  * @throws If an adapter for the same type is already registered.
15
- */
16
- registerAdapter(adapter) {
9
+ */ registerAdapter(adapter) {
17
10
  if (this.adapters.has(adapter.type)) {
18
11
  throw new Error(`Adapter for type "${adapter.type}" is already registered`);
19
12
  }
@@ -21,24 +14,21 @@ class ChannelManager {
21
14
  }
22
15
  /**
23
16
  * Get a registered adapter by type.
24
- */
25
- getAdapter(type) {
17
+ */ getAdapter(type) {
26
18
  return this.adapters.get(type);
27
19
  }
28
20
  /**
29
21
  * Start all registered adapters.
30
- */
31
- async startAll() {
32
- const startPromises = Array.from(this.adapters.values()).map(a => a.start());
22
+ */ async startAll() {
23
+ const startPromises = Array.from(this.adapters.values()).map((a)=>a.start());
33
24
  await Promise.all(startPromises);
34
25
  }
35
26
  /**
36
27
  * Stop all registered adapters.
37
- */
38
- async stopAll() {
39
- const stopPromises = Array.from(this.adapters.values()).map(a => a.stop());
28
+ */ async stopAll() {
29
+ const stopPromises = Array.from(this.adapters.values()).map((a)=>a.stop());
40
30
  await Promise.all(stopPromises);
41
31
  }
42
32
  }
43
- exports.ChannelManager = ChannelManager;
33
+
44
34
  //# sourceMappingURL=ChannelManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelManager.js","sourceRoot":"","sources":["../src/ChannelManager.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAa,cAAc;IAA3B;QACY,aAAQ,GAAgC,IAAI,GAAG,EAAE,CAAC;IAmC9D,CAAC;IAjCG;;;OAGG;IACH,eAAe,CAAC,OAAuB;QACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACV,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7E,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACT,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3E,MAAM,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;CACJ;AApCD,wCAoCC"}
1
+ {"version":3,"sources":["../src/ChannelManager.ts"],"sourcesContent":["import type { ChannelAdapter } from './adapters/ChannelAdapter.js';\n\n/**\n * Central registry for channel adapters.\n * Manages adapter lifecycle (start/stop).\n */\nexport class ChannelManager {\n private adapters: Map<string, ChannelAdapter> = new Map();\n\n /**\n * Register a channel adapter.\n * @throws If an adapter for the same type is already registered.\n */\n registerAdapter(adapter: ChannelAdapter): void {\n if (this.adapters.has(adapter.type)) {\n throw new Error(`Adapter for type \"${adapter.type}\" is already registered`);\n }\n this.adapters.set(adapter.type, adapter);\n }\n\n /**\n * Get a registered adapter by type.\n */\n getAdapter(type: string): ChannelAdapter | undefined {\n return this.adapters.get(type);\n }\n\n /**\n * Start all registered adapters.\n */\n async startAll(): Promise<void> {\n const startPromises = Array.from(this.adapters.values()).map(a => a.start());\n await Promise.all(startPromises);\n }\n\n /**\n * Stop all registered adapters.\n */\n async stopAll(): Promise<void> {\n const stopPromises = Array.from(this.adapters.values()).map(a => a.stop());\n await Promise.all(stopPromises);\n }\n}\n"],"names":["ChannelManager","adapters","Map","registerAdapter","adapter","has","type","Error","set","getAdapter","get","startAll","startPromises","Array","from","values","map","a","start","Promise","all","stopAll","stopPromises","stop"],"mappings":"AAEA;;;CAGC,GACD,OAAO,MAAMA;IACDC,WAAwC,IAAIC,MAAM;IAE1D;;;KAGC,GACDC,gBAAgBC,OAAuB,EAAQ;QAC3C,IAAI,IAAI,CAACH,QAAQ,CAACI,GAAG,CAACD,QAAQE,IAAI,GAAG;YACjC,MAAM,IAAIC,MAAM,CAAC,kBAAkB,EAAEH,QAAQE,IAAI,CAAC,uBAAuB,CAAC;QAC9E;QACA,IAAI,CAACL,QAAQ,CAACO,GAAG,CAACJ,QAAQE,IAAI,EAAEF;IACpC;IAEA;;KAEC,GACDK,WAAWH,IAAY,EAA8B;QACjD,OAAO,IAAI,CAACL,QAAQ,CAACS,GAAG,CAACJ;IAC7B;IAEA;;KAEC,GACD,MAAMK,WAA0B;QAC5B,MAAMC,gBAAgBC,MAAMC,IAAI,CAAC,IAAI,CAACb,QAAQ,CAACc,MAAM,IAAIC,GAAG,CAACC,CAAAA,IAAKA,EAAEC,KAAK;QACzE,MAAMC,QAAQC,GAAG,CAACR;IACtB;IAEA;;KAEC,GACD,MAAMS,UAAyB;QAC3B,MAAMC,eAAeT,MAAMC,IAAI,CAAC,IAAI,CAACb,QAAQ,CAACc,MAAM,IAAIC,GAAG,CAACC,CAAAA,IAAKA,EAAEM,IAAI;QACvE,MAAMJ,QAAQC,GAAG,CAACE;IACtB;AACJ"}
@@ -1,4 +1,4 @@
1
- import type { ChannelConfig, ChannelEntry } from './types';
1
+ import type { ChannelConfig, ChannelEntry } from './types.js';
2
2
  /**
3
3
  * Persists channel configurations to disk.
4
4
  * Default location: ~/.ai-devkit/channels.json
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigStore.d.ts","sourceRoot":"","sources":["../src/ConfigStore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK3D;;;;GAIG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,CAAC,EAAE,MAAM;IAI/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;IASzC;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;YAKnD,WAAW;CAK5B"}
1
+ {"version":3,"file":"ConfigStore.d.ts","sourceRoot":"","sources":["../src/ConfigStore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK9D;;;;GAIG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,CAAC,EAAE,MAAM;IAI/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;IASzC;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;YAKnD,WAAW;CAK5B"}
@@ -1,93 +1,61 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ConfigStore = void 0;
37
- const fs = __importStar(require("fs"));
38
- const path = __importStar(require("path"));
39
- const os = __importStar(require("os"));
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
40
4
  const DEFAULT_CONFIG_PATH = path.join(os.homedir(), '.ai-devkit', 'channels.json');
41
- const DEFAULT_CONFIG = { channels: {} };
5
+ const DEFAULT_CONFIG = {
6
+ channels: {}
7
+ };
42
8
  /**
43
9
  * Persists channel configurations to disk.
44
10
  * Default location: ~/.ai-devkit/channels.json
45
11
  * File permissions are set to 0600 to protect tokens.
46
- */
47
- class ConfigStore {
48
- constructor(configPath) {
12
+ */ export class ConfigStore {
13
+ configPath;
14
+ constructor(configPath){
49
15
  this.configPath = configPath ?? DEFAULT_CONFIG_PATH;
50
16
  }
51
17
  /**
52
18
  * Read the full config. Returns default empty config if file is missing or corrupt.
53
- */
54
- async getConfig() {
19
+ */ async getConfig() {
55
20
  try {
56
21
  const raw = fs.readFileSync(this.configPath, 'utf-8');
57
22
  return JSON.parse(raw);
58
- }
59
- catch {
60
- return { ...DEFAULT_CONFIG, channels: {} };
23
+ } catch {
24
+ return {
25
+ ...DEFAULT_CONFIG,
26
+ channels: {}
27
+ };
61
28
  }
62
29
  }
63
30
  /**
64
31
  * Save a channel entry. Creates the file and parent directory if needed.
65
- */
66
- async saveChannel(name, entry) {
32
+ */ async saveChannel(name, entry) {
67
33
  const config = await this.getConfig();
68
34
  config.channels[name] = entry;
69
35
  await this.writeConfig(config);
70
36
  }
71
37
  /**
72
38
  * Remove a channel entry by name.
73
- */
74
- async removeChannel(name) {
39
+ */ async removeChannel(name) {
75
40
  const config = await this.getConfig();
76
41
  delete config.channels[name];
77
42
  await this.writeConfig(config);
78
43
  }
79
44
  /**
80
45
  * Get a single channel entry by name.
81
- */
82
- async getChannel(name) {
46
+ */ async getChannel(name) {
83
47
  const config = await this.getConfig();
84
48
  return config.channels[name];
85
49
  }
86
50
  async writeConfig(config) {
87
51
  const dir = path.dirname(this.configPath);
88
- fs.mkdirSync(dir, { recursive: true });
89
- fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), { mode: 0o600 });
52
+ fs.mkdirSync(dir, {
53
+ recursive: true
54
+ });
55
+ fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), {
56
+ mode: 0o600
57
+ });
90
58
  }
91
59
  }
92
- exports.ConfigStore = ConfigStore;
60
+
93
61
  //# sourceMappingURL=ConfigStore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigStore.js","sourceRoot":"","sources":["../src/ConfigStore.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAGzB,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;AACnF,MAAM,cAAc,GAAkB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAEvD;;;;GAIG;AACH,MAAa,WAAW;IAGpB,YAAY,UAAmB;QAC3B,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,mBAAmB,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACX,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,EAAE,GAAG,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC/C,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,KAAmB;QAC/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC9B,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,IAAY;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,IAAY;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,MAAqB;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxF,CAAC;CACJ;AAlDD,kCAkDC"}
1
+ {"version":3,"sources":["../src/ConfigStore.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport type { ChannelConfig, ChannelEntry } from './types.js';\n\nconst DEFAULT_CONFIG_PATH = path.join(os.homedir(), '.ai-devkit', 'channels.json');\nconst DEFAULT_CONFIG: ChannelConfig = { channels: {} };\n\n/**\n * Persists channel configurations to disk.\n * Default location: ~/.ai-devkit/channels.json\n * File permissions are set to 0600 to protect tokens.\n */\nexport class ConfigStore {\n private configPath: string;\n\n constructor(configPath?: string) {\n this.configPath = configPath ?? DEFAULT_CONFIG_PATH;\n }\n\n /**\n * Read the full config. Returns default empty config if file is missing or corrupt.\n */\n async getConfig(): Promise<ChannelConfig> {\n try {\n const raw = fs.readFileSync(this.configPath, 'utf-8');\n return JSON.parse(raw) as ChannelConfig;\n } catch {\n return { ...DEFAULT_CONFIG, channels: {} };\n }\n }\n\n /**\n * Save a channel entry. Creates the file and parent directory if needed.\n */\n async saveChannel(name: string, entry: ChannelEntry): Promise<void> {\n const config = await this.getConfig();\n config.channels[name] = entry;\n await this.writeConfig(config);\n }\n\n /**\n * Remove a channel entry by name.\n */\n async removeChannel(name: string): Promise<void> {\n const config = await this.getConfig();\n delete config.channels[name];\n await this.writeConfig(config);\n }\n\n /**\n * Get a single channel entry by name.\n */\n async getChannel(name: string): Promise<ChannelEntry | undefined> {\n const config = await this.getConfig();\n return config.channels[name];\n }\n\n private async writeConfig(config: ChannelConfig): Promise<void> {\n const dir = path.dirname(this.configPath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), { mode: 0o600 });\n }\n}\n"],"names":["fs","path","os","DEFAULT_CONFIG_PATH","join","homedir","DEFAULT_CONFIG","channels","ConfigStore","configPath","getConfig","raw","readFileSync","JSON","parse","saveChannel","name","entry","config","writeConfig","removeChannel","getChannel","dir","dirname","mkdirSync","recursive","writeFileSync","stringify","mode"],"mappings":"AAAA,YAAYA,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAC7B,YAAYC,QAAQ,KAAK;AAGzB,MAAMC,sBAAsBF,KAAKG,IAAI,CAACF,GAAGG,OAAO,IAAI,cAAc;AAClE,MAAMC,iBAAgC;IAAEC,UAAU,CAAC;AAAE;AAErD;;;;CAIC,GACD,OAAO,MAAMC;IACDC,WAAmB;IAE3B,YAAYA,UAAmB,CAAE;QAC7B,IAAI,CAACA,UAAU,GAAGA,cAAcN;IACpC;IAEA;;KAEC,GACD,MAAMO,YAAoC;QACtC,IAAI;YACA,MAAMC,MAAMX,GAAGY,YAAY,CAAC,IAAI,CAACH,UAAU,EAAE;YAC7C,OAAOI,KAAKC,KAAK,CAACH;QACtB,EAAE,OAAM;YACJ,OAAO;gBAAE,GAAGL,cAAc;gBAAEC,UAAU,CAAC;YAAE;QAC7C;IACJ;IAEA;;KAEC,GACD,MAAMQ,YAAYC,IAAY,EAAEC,KAAmB,EAAiB;QAChE,MAAMC,SAAS,MAAM,IAAI,CAACR,SAAS;QACnCQ,OAAOX,QAAQ,CAACS,KAAK,GAAGC;QACxB,MAAM,IAAI,CAACE,WAAW,CAACD;IAC3B;IAEA;;KAEC,GACD,MAAME,cAAcJ,IAAY,EAAiB;QAC7C,MAAME,SAAS,MAAM,IAAI,CAACR,SAAS;QACnC,OAAOQ,OAAOX,QAAQ,CAACS,KAAK;QAC5B,MAAM,IAAI,CAACG,WAAW,CAACD;IAC3B;IAEA;;KAEC,GACD,MAAMG,WAAWL,IAAY,EAAqC;QAC9D,MAAME,SAAS,MAAM,IAAI,CAACR,SAAS;QACnC,OAAOQ,OAAOX,QAAQ,CAACS,KAAK;IAChC;IAEA,MAAcG,YAAYD,MAAqB,EAAiB;QAC5D,MAAMI,MAAMrB,KAAKsB,OAAO,CAAC,IAAI,CAACd,UAAU;QACxCT,GAAGwB,SAAS,CAACF,KAAK;YAAEG,WAAW;QAAK;QACpCzB,GAAG0B,aAAa,CAAC,IAAI,CAACjB,UAAU,EAAEI,KAAKc,SAAS,CAACT,QAAQ,MAAM,IAAI;YAAEU,MAAM;QAAM;IACrF;AACJ"}
@@ -0,0 +1,70 @@
1
+ import { ChannelManager } from '../ChannelManager.js';
2
+ function createMockAdapter(type) {
3
+ return {
4
+ type,
5
+ start: vi.fn().mockResolvedValue(undefined),
6
+ stop: vi.fn().mockResolvedValue(undefined),
7
+ sendMessage: vi.fn().mockResolvedValue(undefined),
8
+ onMessage: vi.fn(),
9
+ isHealthy: vi.fn().mockResolvedValue(true)
10
+ };
11
+ }
12
+ describe('ChannelManager', ()=>{
13
+ let manager;
14
+ beforeEach(()=>{
15
+ manager = new ChannelManager();
16
+ });
17
+ describe('registerAdapter', ()=>{
18
+ it('should register an adapter', ()=>{
19
+ const adapter = createMockAdapter('telegram');
20
+ manager.registerAdapter(adapter);
21
+ expect(manager.getAdapter('telegram')).toBe(adapter);
22
+ });
23
+ it('should throw on duplicate adapter type', ()=>{
24
+ const adapter1 = createMockAdapter('telegram');
25
+ const adapter2 = createMockAdapter('telegram');
26
+ manager.registerAdapter(adapter1);
27
+ expect(()=>manager.registerAdapter(adapter2)).toThrow('Adapter for type "telegram" is already registered');
28
+ });
29
+ });
30
+ describe('getAdapter', ()=>{
31
+ it('should return undefined for unregistered type', ()=>{
32
+ expect(manager.getAdapter('slack')).toBeUndefined();
33
+ });
34
+ it('should return the registered adapter', ()=>{
35
+ const adapter = createMockAdapter('telegram');
36
+ manager.registerAdapter(adapter);
37
+ expect(manager.getAdapter('telegram')).toBe(adapter);
38
+ });
39
+ });
40
+ describe('startAll', ()=>{
41
+ it('should call start() on all registered adapters', async ()=>{
42
+ const telegram = createMockAdapter('telegram');
43
+ const slack = createMockAdapter('slack');
44
+ manager.registerAdapter(telegram);
45
+ manager.registerAdapter(slack);
46
+ await manager.startAll();
47
+ expect(telegram.start).toHaveBeenCalledTimes(1);
48
+ expect(slack.start).toHaveBeenCalledTimes(1);
49
+ });
50
+ it('should work with no adapters', async ()=>{
51
+ await expect(manager.startAll()).resolves.toBeUndefined();
52
+ });
53
+ });
54
+ describe('stopAll', ()=>{
55
+ it('should call stop() on all registered adapters', async ()=>{
56
+ const telegram = createMockAdapter('telegram');
57
+ const slack = createMockAdapter('slack');
58
+ manager.registerAdapter(telegram);
59
+ manager.registerAdapter(slack);
60
+ await manager.stopAll();
61
+ expect(telegram.stop).toHaveBeenCalledTimes(1);
62
+ expect(slack.stop).toHaveBeenCalledTimes(1);
63
+ });
64
+ it('should work with no adapters', async ()=>{
65
+ await expect(manager.stopAll()).resolves.toBeUndefined();
66
+ });
67
+ });
68
+ });
69
+
70
+ //# sourceMappingURL=ChannelManager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/__tests__/ChannelManager.test.ts"],"sourcesContent":["import type { Mocked } from 'vitest';\nimport { ChannelManager } from '../ChannelManager.js';\nimport type { ChannelAdapter } from '../adapters/ChannelAdapter.js';\n\nfunction createMockAdapter(type: string): Mocked<ChannelAdapter> {\n return {\n type,\n start: vi.fn().mockResolvedValue(undefined),\n stop: vi.fn().mockResolvedValue(undefined),\n sendMessage: vi.fn().mockResolvedValue(undefined),\n onMessage: vi.fn(),\n isHealthy: vi.fn().mockResolvedValue(true),\n };\n}\n\ndescribe('ChannelManager', () => {\n let manager: ChannelManager;\n\n beforeEach(() => {\n manager = new ChannelManager();\n });\n\n describe('registerAdapter', () => {\n it('should register an adapter', () => {\n const adapter = createMockAdapter('telegram');\n manager.registerAdapter(adapter);\n expect(manager.getAdapter('telegram')).toBe(adapter);\n });\n\n it('should throw on duplicate adapter type', () => {\n const adapter1 = createMockAdapter('telegram');\n const adapter2 = createMockAdapter('telegram');\n manager.registerAdapter(adapter1);\n expect(() => manager.registerAdapter(adapter2)).toThrow(\n 'Adapter for type \"telegram\" is already registered'\n );\n });\n });\n\n describe('getAdapter', () => {\n it('should return undefined for unregistered type', () => {\n expect(manager.getAdapter('slack')).toBeUndefined();\n });\n\n it('should return the registered adapter', () => {\n const adapter = createMockAdapter('telegram');\n manager.registerAdapter(adapter);\n expect(manager.getAdapter('telegram')).toBe(adapter);\n });\n });\n\n describe('startAll', () => {\n it('should call start() on all registered adapters', async () => {\n const telegram = createMockAdapter('telegram');\n const slack = createMockAdapter('slack');\n manager.registerAdapter(telegram);\n manager.registerAdapter(slack);\n\n await manager.startAll();\n\n expect(telegram.start).toHaveBeenCalledTimes(1);\n expect(slack.start).toHaveBeenCalledTimes(1);\n });\n\n it('should work with no adapters', async () => {\n await expect(manager.startAll()).resolves.toBeUndefined();\n });\n });\n\n describe('stopAll', () => {\n it('should call stop() on all registered adapters', async () => {\n const telegram = createMockAdapter('telegram');\n const slack = createMockAdapter('slack');\n manager.registerAdapter(telegram);\n manager.registerAdapter(slack);\n\n await manager.stopAll();\n\n expect(telegram.stop).toHaveBeenCalledTimes(1);\n expect(slack.stop).toHaveBeenCalledTimes(1);\n });\n\n it('should work with no adapters', async () => {\n await expect(manager.stopAll()).resolves.toBeUndefined();\n });\n });\n});\n"],"names":["ChannelManager","createMockAdapter","type","start","vi","fn","mockResolvedValue","undefined","stop","sendMessage","onMessage","isHealthy","describe","manager","beforeEach","it","adapter","registerAdapter","expect","getAdapter","toBe","adapter1","adapter2","toThrow","toBeUndefined","telegram","slack","startAll","toHaveBeenCalledTimes","resolves","stopAll"],"mappings":"AACA,SAASA,cAAc,QAAQ,uBAAuB;AAGtD,SAASC,kBAAkBC,IAAY;IACnC,OAAO;QACHA;QACAC,OAAOC,GAAGC,EAAE,GAAGC,iBAAiB,CAACC;QACjCC,MAAMJ,GAAGC,EAAE,GAAGC,iBAAiB,CAACC;QAChCE,aAAaL,GAAGC,EAAE,GAAGC,iBAAiB,CAACC;QACvCG,WAAWN,GAAGC,EAAE;QAChBM,WAAWP,GAAGC,EAAE,GAAGC,iBAAiB,CAAC;IACzC;AACJ;AAEAM,SAAS,kBAAkB;IACvB,IAAIC;IAEJC,WAAW;QACPD,UAAU,IAAIb;IAClB;IAEAY,SAAS,mBAAmB;QACxBG,GAAG,8BAA8B;YAC7B,MAAMC,UAAUf,kBAAkB;YAClCY,QAAQI,eAAe,CAACD;YACxBE,OAAOL,QAAQM,UAAU,CAAC,aAAaC,IAAI,CAACJ;QAChD;QAEAD,GAAG,0CAA0C;YACzC,MAAMM,WAAWpB,kBAAkB;YACnC,MAAMqB,WAAWrB,kBAAkB;YACnCY,QAAQI,eAAe,CAACI;YACxBH,OAAO,IAAML,QAAQI,eAAe,CAACK,WAAWC,OAAO,CACnD;QAER;IACJ;IAEAX,SAAS,cAAc;QACnBG,GAAG,iDAAiD;YAChDG,OAAOL,QAAQM,UAAU,CAAC,UAAUK,aAAa;QACrD;QAEAT,GAAG,wCAAwC;YACvC,MAAMC,UAAUf,kBAAkB;YAClCY,QAAQI,eAAe,CAACD;YACxBE,OAAOL,QAAQM,UAAU,CAAC,aAAaC,IAAI,CAACJ;QAChD;IACJ;IAEAJ,SAAS,YAAY;QACjBG,GAAG,kDAAkD;YACjD,MAAMU,WAAWxB,kBAAkB;YACnC,MAAMyB,QAAQzB,kBAAkB;YAChCY,QAAQI,eAAe,CAACQ;YACxBZ,QAAQI,eAAe,CAACS;YAExB,MAAMb,QAAQc,QAAQ;YAEtBT,OAAOO,SAAStB,KAAK,EAAEyB,qBAAqB,CAAC;YAC7CV,OAAOQ,MAAMvB,KAAK,EAAEyB,qBAAqB,CAAC;QAC9C;QAEAb,GAAG,gCAAgC;YAC/B,MAAMG,OAAOL,QAAQc,QAAQ,IAAIE,QAAQ,CAACL,aAAa;QAC3D;IACJ;IAEAZ,SAAS,WAAW;QAChBG,GAAG,iDAAiD;YAChD,MAAMU,WAAWxB,kBAAkB;YACnC,MAAMyB,QAAQzB,kBAAkB;YAChCY,QAAQI,eAAe,CAACQ;YACxBZ,QAAQI,eAAe,CAACS;YAExB,MAAMb,QAAQiB,OAAO;YAErBZ,OAAOO,SAASjB,IAAI,EAAEoB,qBAAqB,CAAC;YAC5CV,OAAOQ,MAAMlB,IAAI,EAAEoB,qBAAqB,CAAC;QAC7C;QAEAb,GAAG,gCAAgC;YAC/B,MAAMG,OAAOL,QAAQiB,OAAO,IAAID,QAAQ,CAACL,aAAa;QAC1D;IACJ;AACJ"}
@@ -0,0 +1,146 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { ConfigStore } from '../ConfigStore.js';
5
+ describe('ConfigStore', ()=>{
6
+ let tmpDir;
7
+ let configPath;
8
+ let store;
9
+ beforeEach(()=>{
10
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'channel-connector-test-'));
11
+ configPath = path.join(tmpDir, 'channels.json');
12
+ store = new ConfigStore(configPath);
13
+ });
14
+ afterEach(()=>{
15
+ fs.rmSync(tmpDir, {
16
+ recursive: true,
17
+ force: true
18
+ });
19
+ });
20
+ const sampleEntry = {
21
+ type: 'telegram',
22
+ enabled: true,
23
+ createdAt: '2026-04-11T00:00:00Z',
24
+ config: {
25
+ botToken: 'test-token-123',
26
+ botUsername: 'test_bot'
27
+ }
28
+ };
29
+ describe('constructor', ()=>{
30
+ it('should use default path when no configPath provided', async ()=>{
31
+ const defaultStore = new ConfigStore();
32
+ // Should not throw — just uses default path
33
+ const config = await defaultStore.getConfig();
34
+ expect(config).toBeDefined();
35
+ });
36
+ });
37
+ describe('getConfig', ()=>{
38
+ it('should return default empty config when file does not exist', async ()=>{
39
+ const config = await store.getConfig();
40
+ expect(config).toEqual({
41
+ channels: {}
42
+ });
43
+ });
44
+ it('should return parsed config when file exists', async ()=>{
45
+ fs.writeFileSync(configPath, JSON.stringify({
46
+ channels: {
47
+ telegram: sampleEntry
48
+ }
49
+ }));
50
+ const config = await store.getConfig();
51
+ expect(config.channels.telegram).toEqual(sampleEntry);
52
+ });
53
+ it('should handle corrupted JSON gracefully', async ()=>{
54
+ fs.writeFileSync(configPath, 'not valid json{{{');
55
+ const config = await store.getConfig();
56
+ expect(config).toEqual({
57
+ channels: {}
58
+ });
59
+ });
60
+ });
61
+ describe('saveChannel', ()=>{
62
+ it('should create config file with channel entry', async ()=>{
63
+ await store.saveChannel('telegram', sampleEntry);
64
+ const raw = fs.readFileSync(configPath, 'utf-8');
65
+ const config = JSON.parse(raw);
66
+ expect(config.channels.telegram).toEqual(sampleEntry);
67
+ });
68
+ it('should create parent directory if missing', async ()=>{
69
+ const nestedPath = path.join(tmpDir, 'nested', 'dir', 'channels.json');
70
+ const nestedStore = new ConfigStore(nestedPath);
71
+ await nestedStore.saveChannel('telegram', sampleEntry);
72
+ expect(fs.existsSync(nestedPath)).toBe(true);
73
+ });
74
+ it('should set file permissions to 0600', async ()=>{
75
+ await store.saveChannel('telegram', sampleEntry);
76
+ const stats = fs.statSync(configPath);
77
+ const mode = (stats.mode & 0o777).toString(8);
78
+ expect(mode).toBe('600');
79
+ });
80
+ it('should preserve existing channels when adding a new one', async ()=>{
81
+ await store.saveChannel('telegram', sampleEntry);
82
+ await store.saveChannel('slack', {
83
+ ...sampleEntry,
84
+ type: 'slack'
85
+ });
86
+ const config = await store.getConfig();
87
+ expect(Object.keys(config.channels)).toEqual([
88
+ 'telegram',
89
+ 'slack'
90
+ ]);
91
+ });
92
+ it('should preserve separate Telegram configs by channel name', async ()=>{
93
+ await store.saveChannel('personal', {
94
+ ...sampleEntry,
95
+ config: {
96
+ botToken: 'personal-token',
97
+ botUsername: 'personal_bot',
98
+ authorizedChatId: 111
99
+ }
100
+ });
101
+ await store.saveChannel('work', {
102
+ ...sampleEntry,
103
+ config: {
104
+ botToken: 'work-token',
105
+ botUsername: 'work_bot',
106
+ authorizedChatId: 222
107
+ }
108
+ });
109
+ const config = await store.getConfig();
110
+ expect(config.channels.personal.config).toEqual({
111
+ botToken: 'personal-token',
112
+ botUsername: 'personal_bot',
113
+ authorizedChatId: 111
114
+ });
115
+ expect(config.channels.work.config).toEqual({
116
+ botToken: 'work-token',
117
+ botUsername: 'work_bot',
118
+ authorizedChatId: 222
119
+ });
120
+ });
121
+ });
122
+ describe('removeChannel', ()=>{
123
+ it('should remove a channel entry', async ()=>{
124
+ await store.saveChannel('telegram', sampleEntry);
125
+ await store.removeChannel('telegram');
126
+ const config = await store.getConfig();
127
+ expect(config.channels.telegram).toBeUndefined();
128
+ });
129
+ it('should not throw when removing non-existent channel', async ()=>{
130
+ await expect(store.removeChannel('nonexistent')).resolves.toBeUndefined();
131
+ });
132
+ });
133
+ describe('getChannel', ()=>{
134
+ it('should return the channel entry', async ()=>{
135
+ await store.saveChannel('telegram', sampleEntry);
136
+ const entry = await store.getChannel('telegram');
137
+ expect(entry).toEqual(sampleEntry);
138
+ });
139
+ it('should return undefined for non-existent channel', async ()=>{
140
+ const entry = await store.getChannel('slack');
141
+ expect(entry).toBeUndefined();
142
+ });
143
+ });
144
+ });
145
+
146
+ //# sourceMappingURL=ConfigStore.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/__tests__/ConfigStore.test.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { ConfigStore } from '../ConfigStore.js';\nimport type { ChannelEntry } from '../types.js';\n\ndescribe('ConfigStore', () => {\n let tmpDir: string;\n let configPath: string;\n let store: ConfigStore;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'channel-connector-test-'));\n configPath = path.join(tmpDir, 'channels.json');\n store = new ConfigStore(configPath);\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n const sampleEntry: ChannelEntry = {\n type: 'telegram',\n enabled: true,\n createdAt: '2026-04-11T00:00:00Z',\n config: {\n botToken: 'test-token-123',\n botUsername: 'test_bot',\n },\n };\n\n describe('constructor', () => {\n it('should use default path when no configPath provided', async () => {\n const defaultStore = new ConfigStore();\n // Should not throw — just uses default path\n const config = await defaultStore.getConfig();\n expect(config).toBeDefined();\n });\n });\n\n describe('getConfig', () => {\n it('should return default empty config when file does not exist', async () => {\n const config = await store.getConfig();\n expect(config).toEqual({ channels: {} });\n });\n\n it('should return parsed config when file exists', async () => {\n fs.writeFileSync(configPath, JSON.stringify({\n channels: { telegram: sampleEntry }\n }));\n\n const config = await store.getConfig();\n expect(config.channels.telegram).toEqual(sampleEntry);\n });\n\n it('should handle corrupted JSON gracefully', async () => {\n fs.writeFileSync(configPath, 'not valid json{{{');\n\n const config = await store.getConfig();\n expect(config).toEqual({ channels: {} });\n });\n });\n\n describe('saveChannel', () => {\n it('should create config file with channel entry', async () => {\n await store.saveChannel('telegram', sampleEntry);\n\n const raw = fs.readFileSync(configPath, 'utf-8');\n const config = JSON.parse(raw);\n expect(config.channels.telegram).toEqual(sampleEntry);\n });\n\n it('should create parent directory if missing', async () => {\n const nestedPath = path.join(tmpDir, 'nested', 'dir', 'channels.json');\n const nestedStore = new ConfigStore(nestedPath);\n\n await nestedStore.saveChannel('telegram', sampleEntry);\n\n expect(fs.existsSync(nestedPath)).toBe(true);\n });\n\n it('should set file permissions to 0600', async () => {\n await store.saveChannel('telegram', sampleEntry);\n\n const stats = fs.statSync(configPath);\n const mode = (stats.mode & 0o777).toString(8);\n expect(mode).toBe('600');\n });\n\n it('should preserve existing channels when adding a new one', async () => {\n await store.saveChannel('telegram', sampleEntry);\n await store.saveChannel('slack', { ...sampleEntry, type: 'slack' });\n\n const config = await store.getConfig();\n expect(Object.keys(config.channels)).toEqual(['telegram', 'slack']);\n });\n\n it('should preserve separate Telegram configs by channel name', async () => {\n await store.saveChannel('personal', {\n ...sampleEntry,\n config: {\n botToken: 'personal-token',\n botUsername: 'personal_bot',\n authorizedChatId: 111,\n },\n });\n await store.saveChannel('work', {\n ...sampleEntry,\n config: {\n botToken: 'work-token',\n botUsername: 'work_bot',\n authorizedChatId: 222,\n },\n });\n\n const config = await store.getConfig();\n expect(config.channels.personal.config).toEqual({\n botToken: 'personal-token',\n botUsername: 'personal_bot',\n authorizedChatId: 111,\n });\n expect(config.channels.work.config).toEqual({\n botToken: 'work-token',\n botUsername: 'work_bot',\n authorizedChatId: 222,\n });\n });\n });\n\n describe('removeChannel', () => {\n it('should remove a channel entry', async () => {\n await store.saveChannel('telegram', sampleEntry);\n await store.removeChannel('telegram');\n\n const config = await store.getConfig();\n expect(config.channels.telegram).toBeUndefined();\n });\n\n it('should not throw when removing non-existent channel', async () => {\n await expect(store.removeChannel('nonexistent')).resolves.toBeUndefined();\n });\n });\n\n describe('getChannel', () => {\n it('should return the channel entry', async () => {\n await store.saveChannel('telegram', sampleEntry);\n\n const entry = await store.getChannel('telegram');\n expect(entry).toEqual(sampleEntry);\n });\n\n it('should return undefined for non-existent channel', async () => {\n const entry = await store.getChannel('slack');\n expect(entry).toBeUndefined();\n });\n });\n});\n"],"names":["fs","path","os","ConfigStore","describe","tmpDir","configPath","store","beforeEach","mkdtempSync","join","tmpdir","afterEach","rmSync","recursive","force","sampleEntry","type","enabled","createdAt","config","botToken","botUsername","it","defaultStore","getConfig","expect","toBeDefined","toEqual","channels","writeFileSync","JSON","stringify","telegram","saveChannel","raw","readFileSync","parse","nestedPath","nestedStore","existsSync","toBe","stats","statSync","mode","toString","Object","keys","authorizedChatId","personal","work","removeChannel","toBeUndefined","resolves","entry","getChannel"],"mappings":"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"}