Skip to content

Commit ccbe441

Browse files
committed
chore: Add initial project files and configurations
1 parent 448dbb7 commit ccbe441

21 files changed

+3953
-1
lines changed

.editorconfig

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true
11+
max_line_length = 180
12+
13+
[Makefile]
14+
indent_style = tab
15+
16+
[*.md]
17+
trim_trailing_whitespace = false

.eslintrc.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module.exports = {
2+
parser: '@typescript-eslint/parser',
3+
parserOptions: {
4+
project: 'tsconfig.json',
5+
tsconfigRootDir: __dirname,
6+
sourceType: 'module',
7+
},
8+
plugins: ['@typescript-eslint/eslint-plugin'],
9+
extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
10+
root: true,
11+
env: {
12+
node: true,
13+
jest: true,
14+
},
15+
ignorePatterns: ['.eslintrc.js'],
16+
rules: {
17+
'no-console': 0,
18+
'comma-dangle': [2, 'always-multiline'],
19+
'quotes': [2, 'single', { 'avoidEscape': true }],
20+
'@typescript-eslint/interface-name-prefix': 'off',
21+
'@typescript-eslint/explicit-function-return-type': 'off',
22+
'@typescript-eslint/explicit-module-boundary-types': 'off',
23+
'@typescript-eslint/no-inferrable-types': 'off',
24+
'@typescript-eslint/no-explicit-any': 'error',
25+
'@typescript-eslint/no-var-requires': 'off',
26+
'@typescript-eslint/no-unused-vars': 'off',
27+
},
28+
}

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
coverage/
3+
dist/
4+
5+
yarn-debug.log*
6+
yarn-error.log*
7+
.env

.prettierignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
coverage/
3+
dist/
4+
5+
yarn-debug.log*
6+
yarn-error.log*
7+
.env

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2024 Tacx
3+
Copyright (c) 2024 The-Software-Compagny
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Makefile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!make
2+
3+
ifneq (,$(wildcard ./.env))
4+
include .env
5+
export
6+
endif
7+
8+
.PHONY: help
9+
.DEFAULT_GOAL := help
10+
help:
11+
@printf "\033[33mUsage:\033[0m\n make [target] [arg=\"val\"...]\n\n\033[33mTargets:\033[0m\n"
12+
@awk 'BEGIN { FS = ":.*##"; } /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
13+
14+
ncu: ## Check latest versions of all project dependencies
15+
@npx npm-check-updates
16+
17+
ncu-upgrade: ## Upgrade all project dependencies to the latest versions
18+
@npx npm-check-updates -u

README.md

Whitespace-only changes.

SECURITY.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
Use this section to tell people about which versions of your project are
6+
currently being supported with security updates.
7+
8+
| Version | Supported |
9+
| ------- | ------------------ |
10+
| 1.x.x | :white_check_mark: |
11+
| 0.x.x | :x: |
12+
13+
## Reporting a Vulnerability
14+
15+
Use this section to tell people how to report a vulnerability.
16+
17+
Tell them where to go, how often they can expect to get an update on a
18+
reported vulnerability, what to expect if the vulnerability is accepted or
19+
declined, etc.

jest.config.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
moduleFileExtensions: ['js', 'json', 'ts'],
4+
rootDir: '.',
5+
testEnvironment: 'node',
6+
testMatch: ['<rootDir>/src/**/*spec.ts'],
7+
transform: {
8+
'^.+\\.(t|j)s$': [
9+
'ts-jest',
10+
{
11+
tsconfig: '<rootDir>/tsconfig.json',
12+
ignoreCodes: ['TS151001'],
13+
},
14+
],
15+
},
16+
collectCoverage: true,
17+
}

jest.preset.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const nxPreset = require('@nrwl/jest/preset')
2+
3+
module.exports = { ...nxPreset }

package.json

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "@the-software-compagny/nestjs_module_imapflow",
3+
"version": "0.0.1",
4+
"description": "NestJS module for Imapflow to interact with IMAP/POP procotol with NodeJS",
5+
"repository": "https://github.com/The-Software-Compagny/nestjs_module_imapflow.git",
6+
"author": "tacxou <[email protected]> (https://github.com/tacxou)",
7+
"contributors": [
8+
{
9+
"name": " tacxou",
10+
"email": "[email protected]",
11+
"url": "https://github.com/tacxou"
12+
},
13+
{
14+
"name": "Contributors",
15+
"url": "https://github.com/The-Software-Compagny/nestjs_module_imapflow/graphs/contributors"
16+
}
17+
],
18+
"license": "MIT",
19+
"main": "dist/index.js",
20+
"scripts": {
21+
"prebuild": "rimraf dist",
22+
"build": "tsc",
23+
"postbuild": "cpr README.md dist/README.md && cpr LICENSE dist/LICENSE && cpr package.json dist/package.json"
24+
},
25+
"dependencies": {
26+
"imapflow": "^1.0.164"
27+
},
28+
"devDependencies": {
29+
"@nestjs/common": "^10.3.9",
30+
"@nestjs/core": "^10.3.9",
31+
"@nestjs/testing": "^10.3.9",
32+
"@types/jest": "29.5.12",
33+
"@types/node": "^20.14.6",
34+
"@types/supertest": "^6.0.2",
35+
"cpr": "^3.0.1",
36+
"eslint": "^9.5.0",
37+
"jest": "29.7.0",
38+
"prettier": "^3.3.2",
39+
"reflect-metadata": "^0.2.2",
40+
"rimraf": "^5.0.7",
41+
"rxjs": "^7.8.1",
42+
"supertest": "^7.0.0",
43+
"ts-jest": "29.1.5",
44+
"ts-node": "^10.9.2",
45+
"typescript": "^5.4.5"
46+
},
47+
"peerDependencies": {
48+
"@nestjs/common": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0",
49+
"@nestjs/core": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
50+
},
51+
"publishConfig": {
52+
"access": "public"
53+
}
54+
}

src/imapflow.constants.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const IMAPFLOW_MODULE_CONNECTION = 'default'
2+
export const IMAPFLOW_MODULE_CONNECTION_TOKEN = 'ImapflowModuleConnectionToken'
3+
export const IMAPFLOW_MODULE_OPTIONS_TOKEN = 'ImapflowModuleOptionsToken'

src/imapflow.core-module.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { DynamicModule, Global, Module, Provider } from '@nestjs/common'
2+
import { ImapflowModuleAsyncOptions, ImapflowModuleOptions, ImapflowModuleOptionsFactory } from './imapflow.interfaces'
3+
import { createImapflowConnection, getImapflowConnectionToken, getImapflowOptionsToken } from './imapflow.utils'
4+
5+
@Global()
6+
@Module({})
7+
export class ImapflowCoreModule {
8+
public static forRoot(options: ImapflowModuleOptions, connection?: string): DynamicModule {
9+
const imapflowOptionsProvider: Provider = {
10+
provide: getImapflowOptionsToken(connection),
11+
useValue: options,
12+
}
13+
14+
const imapflowConnectionProvider: Provider = {
15+
provide: getImapflowConnectionToken(connection),
16+
useValue: createImapflowConnection(options),
17+
}
18+
19+
return {
20+
module: ImapflowCoreModule,
21+
providers: [imapflowOptionsProvider, imapflowConnectionProvider],
22+
exports: [imapflowOptionsProvider, imapflowConnectionProvider],
23+
}
24+
}
25+
26+
public static forRootAsync(options: ImapflowModuleAsyncOptions, connection: string): DynamicModule {
27+
const imapflowConnectionProvider: Provider = {
28+
provide: getImapflowConnectionToken(connection),
29+
useFactory(options: ImapflowModuleOptions) {
30+
return createImapflowConnection(options)
31+
},
32+
inject: [getImapflowOptionsToken(connection)],
33+
}
34+
35+
return {
36+
module: ImapflowCoreModule,
37+
imports: options.imports,
38+
providers: [...this.createAsyncProviders(options, connection), imapflowConnectionProvider],
39+
exports: [imapflowConnectionProvider],
40+
}
41+
}
42+
43+
public static createAsyncProviders(options: ImapflowModuleAsyncOptions, connection?: string): Provider[] {
44+
if (!(options.useExisting || options.useFactory || options.useClass)) {
45+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting')
46+
}
47+
48+
if (options.useExisting || options.useFactory) {
49+
return [this.createAsyncOptionsProvider(options, connection)]
50+
}
51+
52+
return [
53+
this.createAsyncOptionsProvider(options, connection),
54+
{ provide: options.useClass, useClass: options.useClass },
55+
]
56+
}
57+
58+
public static createAsyncOptionsProvider(options: ImapflowModuleAsyncOptions, connection?: string): Provider {
59+
if (!(options.useExisting || options.useFactory || options.useClass)) {
60+
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting')
61+
}
62+
63+
if (options.useFactory) {
64+
return {
65+
provide: getImapflowOptionsToken(connection),
66+
useFactory: options.useFactory,
67+
inject: options.inject || [],
68+
}
69+
}
70+
71+
return {
72+
provide: getImapflowOptionsToken(connection),
73+
async useFactory(optionsFactory: ImapflowModuleOptionsFactory): Promise<ImapflowModuleOptions> {
74+
// noinspection ES6RedundantAwait
75+
return await optionsFactory.createImapflowModuleOptions()
76+
},
77+
inject: [options.useClass || options.useExisting],
78+
}
79+
}
80+
}

src/imapflow.decorators.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Inject } from '@nestjs/common'
2+
import { getImapflowConnectionToken } from './imapflow.utils'
3+
4+
// noinspection JSUnusedGlobalSymbols
5+
export const InjectImapflow = (connection?: string) => {
6+
return Inject(getImapflowConnectionToken(connection))
7+
}

src/imapflow.interfaces.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ModuleMetadata, Type } from '@nestjs/common'
2+
import { ImapFlowOptions } from 'imapflow'
3+
4+
export interface ImapflowModuleOptions {
5+
config: {
6+
id: string
7+
name: string
8+
imap?: ImapFlowOptions
9+
}[]
10+
}
11+
12+
export interface ImapflowModuleOptionsFactory {
13+
createImapflowModuleOptions(): Promise<ImapflowModuleOptions> | ImapflowModuleOptions
14+
}
15+
16+
export interface ImapflowModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
17+
inject?: any[]
18+
useClass?: Type<ImapflowModuleOptionsFactory>
19+
useExisting?: Type<ImapflowModuleOptionsFactory>
20+
useFactory?: (...args: any[]) => Promise<ImapflowModuleOptions> | ImapflowModuleOptions
21+
}

src/imapflow.module.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { DynamicModule, Global, Module } from '@nestjs/common'
2+
import { ImapflowModuleAsyncOptions, ImapflowModuleOptions } from './imapflow.interfaces'
3+
import { ImapflowCoreModule } from './imapflow.core-module'
4+
5+
@Global()
6+
@Module({})
7+
export class ImapflowModule {
8+
// noinspection JSUnusedGlobalSymbols
9+
public static forRoot(options: ImapflowModuleOptions, connection?: string): DynamicModule {
10+
return {
11+
module: ImapflowModule,
12+
imports: [ImapflowCoreModule.forRoot(options, connection)],
13+
exports: [ImapflowCoreModule],
14+
}
15+
}
16+
17+
public static forRootAsync(options: ImapflowModuleAsyncOptions, connection?: string): DynamicModule {
18+
return {
19+
module: ImapflowModule,
20+
imports: [ImapflowCoreModule.forRootAsync(options, connection)],
21+
exports: [ImapflowCoreModule],
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)