Skip to content

Commit 87e76ee

Browse files
committed
init nestjs-pubsub
1 parent acf198c commit 87e76ee

14 files changed

+3919
-0
lines changed

.eslintignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
lib/
2+
.cache/
3+
node_modules/

.eslintrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": [
3+
"eslint:recommended",
4+
"plugin:@typescript-eslint/recommended",
5+
"prettier"
6+
]
7+
}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,5 @@ dist
102102

103103
# TernJS port file
104104
.tern-port
105+
106+
lib/

.prettierignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lib/
2+
coverage/

package.json

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"name": "nestjs-pubsub",
3+
"version": "1.0.0",
4+
"main": "lib/index.js",
5+
"scripts": {
6+
"build": "npm run clean && tsc -p .",
7+
"clean": "rimraf lib",
8+
"test": "jest"
9+
},
10+
"peerDependencies": {
11+
"@google-cloud/pubsub": "^2.0.0",
12+
"@nestjs/common": "^8.0.0"
13+
},
14+
"devDependencies": {
15+
"@google-cloud/pubsub": "2.19.4",
16+
"@nestjs/common": "8.4.5",
17+
"@nestjs/core": "8.4.5",
18+
"@nestjs/testing": "8.4.5",
19+
"@types/jest": "27.5.1",
20+
"@typescript-eslint/eslint-plugin": "5.25.0",
21+
"@typescript-eslint/parser": "5.25.0",
22+
"eslint": "8.5.0",
23+
"eslint-config-prettier": "8.5.0",
24+
"jest": "28.1.0",
25+
"lint-staged": "12.4.1",
26+
"prettier": "2.5.1",
27+
"prettier-plugin-organize-imports": "2.3.4",
28+
"prettier-plugin-package": "1.3.0",
29+
"reflect-metadata": "0.1.13",
30+
"rimraf": "3.0.2",
31+
"rxjs": "7.5.5",
32+
"simple-git-hooks": "2.7.0",
33+
"ts-jest": "28.0.2",
34+
"typescript": "4.6.4"
35+
},
36+
"types": "lib/index.d.ts",
37+
"jest": {
38+
"preset": "ts-jest",
39+
"collectCoverage": true,
40+
"coverageReporters": [
41+
[
42+
"lcov"
43+
],
44+
"text-summary"
45+
]
46+
},
47+
"lint-staged": {
48+
"*.{ts,tsx}": [
49+
"prettier --write",
50+
"eslint --fix"
51+
],
52+
"*.{js,jsx,json,yml,toml,md}": [
53+
"prettier --write"
54+
]
55+
},
56+
"prettier": {
57+
"singleQuote": true
58+
},
59+
"simple-git-hooks": {
60+
"pre-commit": "npx lint-staged"
61+
}
62+
}

src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './pubsub.constants';
2+
export * from './pubsub.inject';
3+
export * from './pubsub.interface';
4+
export * from './pubsub.module';

src/pubsub.constants.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const PUBSUB_TOKEN = 'PUBSUB_TOKEN';
2+
export const PUBSUB_MODULE = 'PUBSUB_MODULE';

src/pubsub.inject.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { InjectPubsub } from './pubsub.inject';
2+
3+
it('InjectPubsub', () => expect(InjectPubsub()).toBeDefined());

src/pubsub.inject.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Inject } from '@nestjs/common';
2+
import { PUBSUB_TOKEN } from './pubsub.constants';
3+
4+
export function InjectPubsub() {
5+
return Inject(PUBSUB_TOKEN);
6+
}

src/pubsub.interface.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { ClientConfig } from '@google-cloud/pubsub';
2+
import { ModuleMetadata, Type } from '@nestjs/common';
3+
4+
export interface PubsubOptionsFactory {
5+
createOptions(): Promise<ClientConfig> | ClientConfig;
6+
}
7+
8+
export interface PubsubAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
9+
inject?: any[];
10+
useClass?: Type<PubsubOptionsFactory>;
11+
useExisting?: Type<PubsubOptionsFactory>;
12+
useFactory?: (...arg: any[]) => Promise<ClientConfig> | ClientConfig;
13+
}

src/pubsub.module.spec.ts

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { ClientConfig } from '@google-cloud/pubsub';
2+
import { Test } from '@nestjs/testing';
3+
import { PubsubModule } from './pubsub.module';
4+
5+
describe('PubsubModule', () => {
6+
let module: PubsubModule;
7+
const options: ClientConfig = {
8+
projectId: 'test-project-id',
9+
};
10+
11+
beforeAll(async () => {
12+
const moduleFixture = await Test.createTestingModule({
13+
imports: [PubsubModule],
14+
}).compile();
15+
16+
module = moduleFixture.get(PubsubModule);
17+
});
18+
19+
it('is defined', () => expect(module).toBeDefined());
20+
21+
it('implements forRoot', () => {
22+
const res = PubsubModule.forRoot(options);
23+
24+
expect(res.exports).toHaveLength(1);
25+
expect(res.imports).toBeUndefined();
26+
expect(res.module).toBeDefined();
27+
expect(res.providers).toHaveLength(1);
28+
});
29+
30+
it('implements forRootAsync', () => {
31+
const res = PubsubModule.forRootAsync({});
32+
33+
expect(res.exports).toMatchInlineSnapshot(`
34+
Array [
35+
Object {
36+
"inject": Array [
37+
"PUBSUB_MODULE",
38+
],
39+
"provide": "PUBSUB_TOKEN",
40+
"useFactory": [Function],
41+
},
42+
]
43+
`);
44+
expect(res.imports).toBeUndefined();
45+
expect(res.providers).toMatchInlineSnapshot(`
46+
Array [
47+
Object {
48+
"inject": Array [],
49+
"provide": "PUBSUB_MODULE",
50+
"useFactory": [Function],
51+
},
52+
Object {
53+
"inject": Array [
54+
Array [],
55+
],
56+
"provide": undefined,
57+
"useClass": undefined,
58+
},
59+
Object {
60+
"inject": Array [
61+
"PUBSUB_MODULE",
62+
],
63+
"provide": "PUBSUB_TOKEN",
64+
"useFactory": [Function],
65+
},
66+
]
67+
`);
68+
expect(res.module).toBeDefined();
69+
});
70+
});

src/pubsub.module.ts

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { ClientConfig, PubSub } from '@google-cloud/pubsub';
2+
import {
3+
ClassProvider,
4+
DynamicModule,
5+
Global,
6+
Module,
7+
Provider,
8+
} from '@nestjs/common';
9+
import { PUBSUB_MODULE, PUBSUB_TOKEN } from './pubsub.constants';
10+
import { PubsubAsyncOptions, PubsubOptionsFactory } from './pubsub.interface';
11+
12+
function getClient(options: ClientConfig) {
13+
return new PubSub(options);
14+
}
15+
16+
function createProvider(options: ClientConfig): Provider<PubSub> {
17+
return {
18+
provide: PUBSUB_TOKEN,
19+
useValue: getClient(options),
20+
};
21+
}
22+
23+
function createAsyncOptionsProvider({
24+
inject,
25+
useFactory,
26+
useClass,
27+
useExisting,
28+
}: PubsubAsyncOptions): Provider {
29+
if (useFactory) {
30+
return {
31+
provide: PUBSUB_MODULE,
32+
useFactory,
33+
inject,
34+
};
35+
}
36+
37+
return {
38+
provide: PUBSUB_MODULE,
39+
inject: useExisting ? [useExisting] : useClass ? [useClass] : [],
40+
useFactory: (f: PubsubOptionsFactory) => f.createOptions(),
41+
};
42+
}
43+
44+
function createAsyncProviders(options: PubsubAsyncOptions): Provider[] {
45+
if (options.useExisting || options.useFactory) {
46+
return [createAsyncOptionsProvider(options)];
47+
}
48+
return [
49+
createAsyncOptionsProvider(options),
50+
{
51+
provide: options.useClass,
52+
useClass: options.useClass,
53+
inject: [options.inject ?? []],
54+
} as ClassProvider,
55+
];
56+
}
57+
58+
@Global()
59+
@Module({})
60+
export class PubsubModule {
61+
static forRoot(options: ClientConfig): DynamicModule {
62+
const provider = createProvider(options);
63+
return {
64+
module: PubsubModule,
65+
exports: [provider],
66+
providers: [provider],
67+
};
68+
}
69+
70+
static forRootAsync(options: PubsubAsyncOptions): DynamicModule {
71+
const provider: Provider<PubSub> = {
72+
inject: [PUBSUB_MODULE],
73+
provide: PUBSUB_TOKEN,
74+
useFactory: (options: ClientConfig) => getClient(options),
75+
};
76+
77+
return {
78+
exports: [provider],
79+
imports: options.imports,
80+
module: PubsubModule,
81+
providers: [...createAsyncProviders(options), provider],
82+
};
83+
}
84+
}

tsconfig.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"moduleResolution": "node",
5+
"removeComments": true,
6+
"emitDecoratorMetadata": true,
7+
"experimentalDecorators": true,
8+
"target": "es2020",
9+
"lib": ["ES2020"],
10+
"declaration": true,
11+
"outDir": "./lib",
12+
"rootDir": "./src",
13+
"noEmit": false,
14+
"skipLibCheck": true
15+
},
16+
"include": ["src/**/*"],
17+
"exclude": ["node_modules", "**/*spec.ts"]
18+
}

0 commit comments

Comments
 (0)