diff --git a/README.md b/README.md
index 635e506..77faf35 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,14 @@
+
🥰 Any kinds of contributions are welcome! 🥰
+
+# Installation
+
+```
+yarn add nestjs-slack-listener
+```
+
# Usage
## Settings
@@ -24,7 +32,7 @@ Import the module at your app module.
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
- SlackHandlerModule.forRootAsync({
+ SlackModule.forRootAsync({
useFactory: async (config: ConfigService) => ({
botToken: config.get('SLACK_BOT_TOKEN'),
}),
diff --git a/package.json b/package.json
index 2b22399..205bfd8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nestjs-slack-listener",
- "version": "1.0.2",
+ "version": "1.0.4",
"description": "NestJS Slack listeners and handlers",
"author": "Chung Hwan Han ",
"license": "MIT",
@@ -74,7 +74,7 @@
"pre-commit": "^1.2.2",
"prettier": "2.6.1",
"reflect-metadata": "^0.1.13",
- "supertest": "6.2.2",
+ "supertest": "^6.3.0",
"ts-jest": "27.1.4",
"ts-node": "10.7.0",
"tsc-watch": "5.0.3",
@@ -82,17 +82,30 @@
"typescript": "4.6.3"
},
"jest": {
+ "moduleDirectories": [
+ "node_modules",
+ "src"
+ ],
"moduleFileExtensions": [
"js",
"json",
"ts"
],
- "rootDir": "src",
- "testRegex": ".spec.ts$",
+ "roots": [
+ "src"
+ ],
+ "testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
+ "collectCoverageFrom": [
+ "**/*.(t|j)s"
+ ],
"coverageDirectory": "../coverage",
- "testEnvironment": "node"
+ "testEnvironment": "node",
+ "moduleNameMapper": {
+ "gaxios": "gaxios",
+ "src/(.*)": "/src/$1"
+ }
}
}
diff --git a/src/handler/index.ts b/src/handler/index.ts
deleted file mode 100644
index 28500d8..0000000
--- a/src/handler/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './decorators';
-export * from './interfaces';
-export * from './slack-handler.module';
diff --git a/src/index.ts b/src/index.ts
index 68ae53f..b7c3666 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1 +1 @@
-export * from './handler';
+export * from './slack';
diff --git a/src/handler/constant/symbol.ts b/src/slack/constant/symbol.ts
similarity index 81%
rename from src/handler/constant/symbol.ts
rename to src/slack/constant/symbol.ts
index 27d980a..2bd1611 100644
--- a/src/handler/constant/symbol.ts
+++ b/src/slack/constant/symbol.ts
@@ -1,3 +1,4 @@
export const SLACK_CONFIG_OPTIONS = 'SLACK_CONFIG_OPTIONS';
export const SLACK_INTERACTIVITY_HANDLER = 'SLACK_INTERACTIVITY_HANDLER';
export const SLACK_EVENT_HANDLER = 'SLACK_EVENT_HANDLER';
+export const SLACK_CLIENT = 'SLACK_CLIENT';
diff --git a/src/slack/decorators/client.decorator.ts b/src/slack/decorators/client.decorator.ts
new file mode 100644
index 0000000..ecbaf08
--- /dev/null
+++ b/src/slack/decorators/client.decorator.ts
@@ -0,0 +1,4 @@
+import { Inject } from '@nestjs/common';
+import { SLACK_CLIENT } from '../constant/symbol';
+
+export const InjectSlackClient = () => Inject(SLACK_CLIENT);
diff --git a/src/handler/decorators/command.decorator.ts b/src/slack/decorators/command.decorator.ts
similarity index 100%
rename from src/handler/decorators/command.decorator.ts
rename to src/slack/decorators/command.decorator.ts
diff --git a/src/handler/decorators/handler.decorator.ts b/src/slack/decorators/handler.decorator.ts
similarity index 100%
rename from src/handler/decorators/handler.decorator.ts
rename to src/slack/decorators/handler.decorator.ts
diff --git a/src/handler/decorators/index.ts b/src/slack/decorators/index.ts
similarity index 67%
rename from src/handler/decorators/index.ts
rename to src/slack/decorators/index.ts
index 801a5e1..adae4e3 100644
--- a/src/handler/decorators/index.ts
+++ b/src/slack/decorators/index.ts
@@ -1,2 +1,3 @@
export * from './command.decorator';
export * from './handler.decorator';
+export * from './client.decorator';
diff --git a/src/handler/handler.explorer.ts b/src/slack/handler.explorer.ts
similarity index 100%
rename from src/handler/handler.explorer.ts
rename to src/slack/handler.explorer.ts
diff --git a/src/slack/index.ts b/src/slack/index.ts
new file mode 100644
index 0000000..328a995
--- /dev/null
+++ b/src/slack/index.ts
@@ -0,0 +1,4 @@
+export * from './decorators';
+export * from './interfaces';
+export * from './types/client';
+export * from './slack.module';
diff --git a/src/handler/interfaces/handler.interface.ts b/src/slack/interfaces/handler.interface.ts
similarity index 100%
rename from src/handler/interfaces/handler.interface.ts
rename to src/slack/interfaces/handler.interface.ts
diff --git a/src/handler/interfaces/incoming.interface.ts b/src/slack/interfaces/incoming.interface.ts
similarity index 100%
rename from src/handler/interfaces/incoming.interface.ts
rename to src/slack/interfaces/incoming.interface.ts
diff --git a/src/handler/interfaces/index.ts b/src/slack/interfaces/index.ts
similarity index 100%
rename from src/handler/interfaces/index.ts
rename to src/slack/interfaces/index.ts
diff --git a/src/handler/interfaces/module-options.interface.ts b/src/slack/interfaces/module-options.interface.ts
similarity index 100%
rename from src/handler/interfaces/module-options.interface.ts
rename to src/slack/interfaces/module-options.interface.ts
diff --git a/src/slack/slack-client.service.ts b/src/slack/slack-client.service.ts
new file mode 100644
index 0000000..c6f8046
--- /dev/null
+++ b/src/slack/slack-client.service.ts
@@ -0,0 +1,13 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { WebClient } from '@slack/web-api';
+import { SLACK_CONFIG_OPTIONS } from './constant/symbol';
+import { SlackModuleOptions } from './interfaces';
+
+@Injectable()
+export class SlackClientService {
+ public readonly client: WebClient;
+
+ constructor(@Inject(SLACK_CONFIG_OPTIONS) options: SlackModuleOptions) {
+ this.client = new WebClient(options.botToken);
+ }
+}
diff --git a/src/handler/slack-handler.controller.ts b/src/slack/slack-handler.controller.ts
similarity index 100%
rename from src/handler/slack-handler.controller.ts
rename to src/slack/slack-handler.controller.ts
diff --git a/src/handler/slack-handler.service.ts b/src/slack/slack-handler.service.ts
similarity index 100%
rename from src/handler/slack-handler.service.ts
rename to src/slack/slack-handler.service.ts
diff --git a/src/handler/slack-handler.module.ts b/src/slack/slack.module.ts
similarity index 71%
rename from src/handler/slack-handler.module.ts
rename to src/slack/slack.module.ts
index f03a57f..b5e8fe6 100644
--- a/src/handler/slack-handler.module.ts
+++ b/src/slack/slack.module.ts
@@ -1,19 +1,21 @@
import { DynamicModule, Module, OnModuleInit, Provider } from '@nestjs/common';
import { MetadataScanner } from '@nestjs/core';
-import { SLACK_CONFIG_OPTIONS } from './constant/symbol';
+import { SLACK_CLIENT, SLACK_CONFIG_OPTIONS } from './constant/symbol';
import { SlackHandlerExplorer } from './handler.explorer';
import { SlackModuleAsyncOptions, SlackModuleOptions } from './interfaces';
+import { SlackClientService } from './slack-client.service';
import { SlackEventsController } from './slack-handler.controller';
import { SlackHandler } from './slack-handler.service';
@Module({
providers: [MetadataScanner, SlackHandlerExplorer],
})
-export class SlackHandlerModule implements OnModuleInit {
+export class SlackModule implements OnModuleInit {
static forRoot(options: SlackModuleOptions): DynamicModule {
const slackServiceProvider = this.createSlackServiceProvider();
+ const slackClientProvider = this.createSlackClientProvider();
return {
- module: SlackHandlerModule,
+ module: SlackModule,
controllers: [SlackEventsController],
providers: [
{
@@ -21,20 +23,22 @@ export class SlackHandlerModule implements OnModuleInit {
useValue: options,
},
slackServiceProvider,
+ slackClientProvider,
],
- exports: [SlackHandler],
+ exports: [SlackHandler, SLACK_CLIENT],
};
}
static forRootAsync(options: SlackModuleAsyncOptions): DynamicModule {
const slackServiceProvider = this.createSlackServiceProvider();
+ const slackClientProvider = this.createSlackClientProvider();
const asyncProviders = this.createAsyncProviders(options);
return {
- module: SlackHandlerModule,
+ module: SlackModule,
controllers: [SlackEventsController],
imports: options.imports || [],
- providers: [...asyncProviders, slackServiceProvider],
- exports: [SlackHandler],
+ providers: [...asyncProviders, slackServiceProvider, slackClientProvider],
+ exports: [SlackHandler, SLACK_CLIENT],
};
}
@@ -46,6 +50,15 @@ export class SlackHandlerModule implements OnModuleInit {
};
}
+ private static createSlackClientProvider(): Provider {
+ return {
+ provide: SLACK_CLIENT,
+ useFactory: (options: SlackModuleOptions) =>
+ new SlackClientService(options).client,
+ inject: [SLACK_CONFIG_OPTIONS],
+ };
+ }
+
private static createAsyncProviders(
options: SlackModuleAsyncOptions,
): Provider[] {
diff --git a/src/slack/types/client.ts b/src/slack/types/client.ts
new file mode 100644
index 0000000..e8cd5dc
--- /dev/null
+++ b/src/slack/types/client.ts
@@ -0,0 +1,3 @@
+import { WebClient } from '@slack/web-api';
+
+export type SlackClient = WebClient;
diff --git a/src/handler/types/event.ts b/src/slack/types/event.ts
similarity index 100%
rename from src/handler/types/event.ts
rename to src/slack/types/event.ts
diff --git a/src/test/slack-handler.module.spec.ts b/src/test/slack-handler.module.spec.ts
deleted file mode 100644
index f8a2e74..0000000
--- a/src/test/slack-handler.module.spec.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-describe('Slack Module Initialization', () => {
- describe('forRoot', () => {
- it('should be defined', () => {
- return;
- });
- });
- describe('forRootAsync', () => {
- it('should be defined', () => {
- return;
- });
- });
-});
diff --git a/src/test/slack.module.spec.ts b/src/test/slack.module.spec.ts
new file mode 100644
index 0000000..124667b
--- /dev/null
+++ b/src/test/slack.module.spec.ts
@@ -0,0 +1,111 @@
+import { Controller, Get, Injectable, Module } from '@nestjs/common';
+import { NestFactory } from '@nestjs/core';
+import { SlackClient, SlackEventListener, SlackModule } from 'src/slack';
+import { InjectSlackClient } from 'src/slack/decorators';
+import * as request from 'supertest';
+
+describe('Slack Module Initialization', () => {
+ describe('forRoot', () => {
+ it('should compile only with botToken option', async () => {
+ @Controller()
+ @SlackEventListener()
+ class TestController {
+ @Get()
+ get() {
+ return '';
+ }
+ }
+ @Module({
+ imports: [SlackModule.forRoot({ botToken: 'test' })],
+ controllers: [TestController],
+ })
+ class TestModule {}
+
+ const app = await NestFactory.create(TestModule);
+ const server = app.getHttpServer();
+
+ await app.init();
+ await request(server).get('/').expect(200);
+ await app.close();
+ });
+ it('should compile including slack client', async () => {
+ @Injectable()
+ class TestService {
+ constructor(@InjectSlackClient() slack: SlackClient) {
+ expect(slack).toBeDefined();
+ }
+ getBotToken() {
+ return 'test';
+ }
+ }
+ @Module({
+ imports: [
+ SlackModule.forRoot({
+ botToken: 'test',
+ }),
+ ],
+ providers: [TestService],
+ })
+ class TestModule {}
+
+ const app = await NestFactory.create(TestModule);
+
+ await app.init();
+ await app.close();
+ });
+ });
+ describe('forRootAsync', () => {
+ it('should compile only with botToken option', async () => {
+ @Controller()
+ @SlackEventListener()
+ class TestController {
+ @Get()
+ get() {
+ return '';
+ }
+ }
+ @Module({
+ imports: [
+ SlackModule.forRootAsync({
+ useFactory: () => ({ botToken: 'test' }),
+ }),
+ ],
+ controllers: [TestController],
+ })
+ class TestModule {}
+
+ const app = await NestFactory.create(TestModule);
+ const server = app.getHttpServer();
+
+ await app.init();
+ await request(server).get('/').expect(200);
+ await app.close();
+ });
+
+ it('should compile including slack client', async () => {
+ @Injectable()
+ class TestService {
+ constructor(@InjectSlackClient() slack: SlackClient) {
+ expect(slack).toBeDefined();
+ }
+ getBotToken() {
+ return 'test';
+ }
+ }
+ @Module({
+ imports: [
+ SlackModule.forRootAsync({
+ useFactory: () => ({ botToken: 'test' }),
+ }),
+ ],
+ providers: [TestService],
+ })
+ class TestModule {}
+
+ const app = await NestFactory.create(TestModule);
+
+ await app.init();
+ await app.close();
+ });
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index 9e6f526..b2de1ab 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -13,5 +13,5 @@
"noLib": false
},
"include": ["src/**/*.ts"],
- "exclude": ["node_modules"]
+ "exclude": ["node_modules", "example"]
}
diff --git a/yarn.lock b/yarn.lock
index 8d665f4..e38325c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1555,7 +1555,7 @@ debug@2.6.9, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
+debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -3289,7 +3289,7 @@ mime@1.6.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-mime@^2.5.0:
+mime@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
@@ -3734,7 +3734,7 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-qs@6.10.3, qs@^6.10.1:
+qs@6.10.3:
version "6.10.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
@@ -3746,6 +3746,13 @@ qs@6.9.3:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e"
integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==
+qs@^6.11.0:
+ version "6.11.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
+ integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+ dependencies:
+ side-channel "^1.0.4"
+
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -3784,15 +3791,6 @@ readable-stream@^2.2.2:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
- integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
- dependencies:
- inherits "^2.0.3"
- string_decoder "^1.1.1"
- util-deprecate "^1.0.1"
-
reflect-metadata@^0.1.13:
version "0.1.13"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
@@ -3870,7 +3868,7 @@ rxjs@^7.x:
dependencies:
tslib "^2.1.0"
-safe-buffer@5.2.1, safe-buffer@~5.2.0:
+safe-buffer@5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -4091,13 +4089,6 @@ string.prototype.trimstart@^1.0.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
-string_decoder@^1.1.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
- integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
- dependencies:
- safe-buffer "~5.2.0"
-
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -4132,30 +4123,29 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-superagent@^7.1.0:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.1.tgz#2ab187d38c3078c31c3771c0b751f10163a27136"
- integrity sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==
+superagent@^8.0.0:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.0.2.tgz#23e753da16f2a0a5afa2fe2b41cafed5b22a5bde"
+ integrity sha512-QtYZ9uaNAMexI7XWl2vAXAh0j4q9H7T0WVEI/y5qaUB3QLwxo+voUgCQ217AokJzUTIVOp0RTo7fhZrwhD7A2Q==
dependencies:
component-emitter "^1.3.0"
cookiejar "^2.1.3"
- debug "^4.3.3"
+ debug "^4.3.4"
fast-safe-stringify "^2.1.1"
form-data "^4.0.0"
formidable "^2.0.1"
methods "^1.1.2"
- mime "^2.5.0"
- qs "^6.10.1"
- readable-stream "^3.6.0"
- semver "^7.3.5"
+ mime "2.6.0"
+ qs "^6.11.0"
+ semver "^7.3.7"
-supertest@6.2.2:
- version "6.2.2"
- resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.2.2.tgz#04a5998fd3efaff187cb69f07a169755d655b001"
- integrity sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg==
+supertest@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.0.tgz#06c21234ff0be9e398ba19f7a75f237930d57442"
+ integrity sha512-QgWju1cNoacP81Rv88NKkQ4oXTzGg0eNZtOoxp1ROpbS4OHY/eK5b8meShuFtdni161o5X0VQvgo7ErVyKK+Ow==
dependencies:
methods "^1.1.2"
- superagent "^7.1.0"
+ superagent "^8.0.0"
supports-color@^5.3.0:
version "5.5.0"
@@ -4428,7 +4418,7 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=