@point-hub/papi 0.1.5 → 0.1.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.
- package/package.json +4 -3
- package/src/app.spec.ts +8 -0
- package/src/app.ts +13 -0
- package/src/console/commands/make-command/index.command.ts +52 -0
- package/src/console/commands/make-command/index.spec.ts +58 -0
- package/src/console/commands/make-middleware/index.command.ts +86 -0
- package/src/console/commands/make-middleware/index.spec.ts +73 -0
- package/src/console/index.spec.ts +14 -0
- package/src/console/index.ts +23 -0
- package/src/database/connection.ts +78 -0
- package/src/database/mongodb/connection.ts +339 -0
- package/src/database/mongodb/mongodb-error-handler.ts +63 -0
- package/src/database/mongodb/mongodb-helper.ts +109 -0
- package/src/database/mongodb/mongodb-querystring.spec.ts +80 -0
- package/src/database/mongodb/mongodb-querystring.ts +143 -0
- package/src/index.ts +42 -0
- package/src/server.spec.ts +68 -0
- package/src/server.ts +49 -0
- package/src/types/controller.d.ts +18 -0
- package/src/types/database.d.ts +104 -0
- package/src/types/use-case.d.ts +3 -0
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@point-hub/papi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Point API Framework",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "
|
|
6
|
+
"main": "src/index.ts",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
9
|
"lib/",
|
|
10
|
-
"stub/"
|
|
10
|
+
"stub/",
|
|
11
|
+
"src/"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"check-types": "tsc -p tsconfig.json",
|
package/src/app.spec.ts
ADDED
package/src/app.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import express, { Express, Request, Response } from 'express'
|
|
2
|
+
|
|
3
|
+
export async function createApp() {
|
|
4
|
+
const app: Express = express()
|
|
5
|
+
|
|
6
|
+
app.get('/', (req: Request, res: Response) => {
|
|
7
|
+
res.status(200).json({
|
|
8
|
+
message: 'Papi',
|
|
9
|
+
})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
return app
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BaseCommand, Color } from '@point-hub/express-cli'
|
|
2
|
+
import { camelCase, kebabCase, pascalCase } from '@point-hub/express-utils'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
|
|
6
|
+
import { stubDir } from '../../../index'
|
|
7
|
+
|
|
8
|
+
export default class MakeCommand extends BaseCommand {
|
|
9
|
+
constructor() {
|
|
10
|
+
super({
|
|
11
|
+
name: 'make:command',
|
|
12
|
+
description: 'Make a new console command',
|
|
13
|
+
summary: 'Make a new console command',
|
|
14
|
+
arguments: [
|
|
15
|
+
{
|
|
16
|
+
name: 'name',
|
|
17
|
+
description: 'Name of console command',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
options: [],
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
async handle(): Promise<void> {
|
|
24
|
+
// Check if command directory is already exists
|
|
25
|
+
if (fs.existsSync(`${process.cwd()}/src/console/commands/${kebabCase(this.args.name)}`)) {
|
|
26
|
+
console.error(Color.red('Command directory is exists'))
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Create directory
|
|
31
|
+
fs.mkdirSync(`${process.cwd()}/src/console/commands/${kebabCase(this.args.name)}`, { recursive: true })
|
|
32
|
+
|
|
33
|
+
// Copy command file
|
|
34
|
+
const stubCommand = fs
|
|
35
|
+
.readFileSync(path.resolve(stubDir, './command/index.command.ts'))
|
|
36
|
+
.toString()
|
|
37
|
+
.replace('[name]', kebabCase(this.args.name))
|
|
38
|
+
.replace('NewCommand', `${pascalCase(this.args.name)}Command`)
|
|
39
|
+
fs.writeFileSync(`${process.cwd()}/src/console/commands/${kebabCase(this.args.name)}/index.command.ts`, stubCommand)
|
|
40
|
+
|
|
41
|
+
// Copy test file
|
|
42
|
+
const stubTest = fs
|
|
43
|
+
.readFileSync(path.resolve(stubDir, './command/index.spec.ts'))
|
|
44
|
+
.toString()
|
|
45
|
+
.replace(/NewCommand/g, `${pascalCase(this.args.name)}Command`)
|
|
46
|
+
.replace(/newCommand/g, `${camelCase(this.args.name)}Command`)
|
|
47
|
+
fs.writeFileSync(`${process.cwd()}/src/console/commands/${kebabCase(this.args.name)}/index.spec.ts`, stubTest)
|
|
48
|
+
|
|
49
|
+
console.info(`src/console/commands/${kebabCase(this.args.name)}/index.command.ts`, 'has been created')
|
|
50
|
+
console.info(`src/console/commands/${kebabCase(this.args.name)}/index.spec.ts`, 'has been created')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Color } from '@point-hub/express-cli'
|
|
2
|
+
import { beforeAll, describe, expect, it, spyOn } from 'bun:test'
|
|
3
|
+
import crypto from 'crypto'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import shell from 'shelljs'
|
|
6
|
+
|
|
7
|
+
import MakeCommand from './index.command'
|
|
8
|
+
|
|
9
|
+
const dir = 'src/console/commands'
|
|
10
|
+
|
|
11
|
+
function generateRandomName() {
|
|
12
|
+
let exists = true
|
|
13
|
+
let name = 'test'
|
|
14
|
+
while (exists) {
|
|
15
|
+
name = `test-${crypto.randomBytes(4).toString('hex')}`
|
|
16
|
+
exists = fs.existsSync(`${dir}/${name}`)
|
|
17
|
+
}
|
|
18
|
+
return name
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('make:command', () => {
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
spyOn(console, 'error').mockImplementation(() => '')
|
|
24
|
+
spyOn(console, 'info').mockImplementation(() => '')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should create new command', async () => {
|
|
28
|
+
const makeCommand = new MakeCommand()
|
|
29
|
+
makeCommand.args = {
|
|
30
|
+
name: generateRandomName(),
|
|
31
|
+
}
|
|
32
|
+
const spy = spyOn(makeCommand, 'handle')
|
|
33
|
+
await makeCommand.handle()
|
|
34
|
+
|
|
35
|
+
shell.rm('-rf', `${dir}/${makeCommand.args.name}`)
|
|
36
|
+
|
|
37
|
+
expect(spy).toHaveBeenCalled()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it("should return error 'command directory exists'", async () => {
|
|
41
|
+
const makeCommand = new MakeCommand()
|
|
42
|
+
makeCommand.args = {
|
|
43
|
+
name: generateRandomName(),
|
|
44
|
+
}
|
|
45
|
+
const spy = spyOn(makeCommand, 'handle')
|
|
46
|
+
|
|
47
|
+
// first attempt it will create new command
|
|
48
|
+
await makeCommand.handle()
|
|
49
|
+
// second attempt it should return error because command directory exists
|
|
50
|
+
await makeCommand.handle()
|
|
51
|
+
|
|
52
|
+
shell.rm('-rf', `${dir}/${makeCommand.args.name}`)
|
|
53
|
+
|
|
54
|
+
expect(console.error).toHaveBeenCalled()
|
|
55
|
+
expect(console.error).toHaveBeenCalledWith(Color.red('Command directory is exists'))
|
|
56
|
+
expect(spy).toHaveBeenCalled()
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { BaseCommand, Color } from '@point-hub/express-cli'
|
|
2
|
+
import { kebabCase, pascalCase } from '@point-hub/express-utils'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
|
|
6
|
+
import { stubDir } from '../../../index'
|
|
7
|
+
|
|
8
|
+
export default class MakeMiddleware extends BaseCommand {
|
|
9
|
+
constructor() {
|
|
10
|
+
super({
|
|
11
|
+
name: 'make:middleware',
|
|
12
|
+
description: 'Make a new middleware',
|
|
13
|
+
summary: 'Make a new middleware',
|
|
14
|
+
arguments: [
|
|
15
|
+
{
|
|
16
|
+
name: 'name',
|
|
17
|
+
description: 'Name of middleware',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
options: [
|
|
21
|
+
{
|
|
22
|
+
type: 'boolean',
|
|
23
|
+
flag: '--configurable',
|
|
24
|
+
shorthand: '-c',
|
|
25
|
+
description: 'Export a function which accepts an options',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async handle(): Promise<void> {
|
|
32
|
+
// Check if middleware directory is already exists
|
|
33
|
+
if (fs.existsSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}`)) {
|
|
34
|
+
console.error(Color.red('Middleware directory is exists'))
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Create middleware directory
|
|
39
|
+
fs.mkdirSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}`, { recursive: true })
|
|
40
|
+
|
|
41
|
+
// Copy middleware
|
|
42
|
+
if (this.opts['--configurable']) {
|
|
43
|
+
this.copyConfigureableMiddleware()
|
|
44
|
+
} else {
|
|
45
|
+
this.copyMiddleware()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private copyMiddleware() {
|
|
50
|
+
// Copy middleware file
|
|
51
|
+
const stubMiddleware = fs
|
|
52
|
+
.readFileSync(path.resolve(stubDir, './middleware/new.middleware.ts'))
|
|
53
|
+
.toString()
|
|
54
|
+
.replace('NewMiddleware', `${pascalCase(this.args.name)}Middleware`)
|
|
55
|
+
fs.writeFileSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}/index.middleware.ts`, stubMiddleware)
|
|
56
|
+
|
|
57
|
+
// Copy test file
|
|
58
|
+
const stubTest = fs
|
|
59
|
+
.readFileSync(path.resolve(stubDir, './middleware/new.spec.ts'))
|
|
60
|
+
.toString()
|
|
61
|
+
.replace('new.middleware.ts', `index.middleware.ts`)
|
|
62
|
+
fs.writeFileSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}/index.spec.ts`, stubTest)
|
|
63
|
+
|
|
64
|
+
console.info(`src/middleware/${kebabCase(this.args.name)}/index.middleware.ts`, 'has been created')
|
|
65
|
+
console.info(`src/middleware/${kebabCase(this.args.name)}/index.spec.ts`, 'has been created')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private copyConfigureableMiddleware() {
|
|
69
|
+
// Copy middleware file
|
|
70
|
+
const stubMiddleware = fs
|
|
71
|
+
.readFileSync(path.resolve(stubDir, './middleware/configurable.middleware.ts'))
|
|
72
|
+
.toString()
|
|
73
|
+
.replace('NewMiddleware', `${pascalCase(this.args.name)}Middleware`)
|
|
74
|
+
fs.writeFileSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}/index.middleware.ts`, stubMiddleware)
|
|
75
|
+
|
|
76
|
+
// Copy test file
|
|
77
|
+
const stubTest = fs
|
|
78
|
+
.readFileSync(path.resolve(stubDir, './middleware/configurable.spec.ts'))
|
|
79
|
+
.toString()
|
|
80
|
+
.replace('configurable.middleware.ts', `index.middleware.ts`)
|
|
81
|
+
fs.writeFileSync(`${process.cwd()}/src/middleware/${kebabCase(this.args.name)}/index.spec.ts`, stubTest)
|
|
82
|
+
|
|
83
|
+
console.info(`src/middleware/${kebabCase(this.args.name)}/index.middleware.ts`, 'has been created')
|
|
84
|
+
console.info(`src/middleware/${kebabCase(this.args.name)}/index.spec.ts`, 'has been created')
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Color } from '@point-hub/express-cli'
|
|
2
|
+
import { beforeAll, describe, expect, it, spyOn } from 'bun:test'
|
|
3
|
+
import crypto from 'crypto'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import shell from 'shelljs'
|
|
6
|
+
|
|
7
|
+
import MakeMiddlewareCommand from './index.command'
|
|
8
|
+
|
|
9
|
+
const dir = 'src/middleware'
|
|
10
|
+
|
|
11
|
+
function generateRandomName() {
|
|
12
|
+
let exists = true
|
|
13
|
+
let name = 'test'
|
|
14
|
+
while (exists) {
|
|
15
|
+
name = `test-${crypto.randomBytes(4).toString('hex')}`
|
|
16
|
+
exists = fs.existsSync(`${dir}/${name}`)
|
|
17
|
+
}
|
|
18
|
+
return name
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('make:middleware', () => {
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
spyOn(console, 'error').mockImplementation(() => '')
|
|
24
|
+
spyOn(console, 'info').mockImplementation(() => '')
|
|
25
|
+
})
|
|
26
|
+
it('should create new middleware', async () => {
|
|
27
|
+
const makeMiddlewareCommand = new MakeMiddlewareCommand()
|
|
28
|
+
makeMiddlewareCommand.args = {
|
|
29
|
+
name: generateRandomName(),
|
|
30
|
+
}
|
|
31
|
+
const spy = spyOn(makeMiddlewareCommand, 'handle')
|
|
32
|
+
await makeMiddlewareCommand.handle()
|
|
33
|
+
|
|
34
|
+
shell.rm('-rf', `${dir}/${makeMiddlewareCommand.args.name}`)
|
|
35
|
+
|
|
36
|
+
expect(spy).toHaveBeenCalled()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('should create new configureable middleware', async () => {
|
|
40
|
+
const makeMiddlewareCommand = new MakeMiddlewareCommand()
|
|
41
|
+
makeMiddlewareCommand.args = {
|
|
42
|
+
name: generateRandomName(),
|
|
43
|
+
}
|
|
44
|
+
makeMiddlewareCommand.opts = {
|
|
45
|
+
'--configurable': true,
|
|
46
|
+
}
|
|
47
|
+
const spy = spyOn(makeMiddlewareCommand, 'handle')
|
|
48
|
+
await makeMiddlewareCommand.handle()
|
|
49
|
+
|
|
50
|
+
shell.rm('-rf', `${dir}/${makeMiddlewareCommand.args.name}`)
|
|
51
|
+
|
|
52
|
+
expect(spy).toHaveBeenCalled()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it("should return error 'middleware directory exists'", async () => {
|
|
56
|
+
const makeMiddlewareCommand = new MakeMiddlewareCommand()
|
|
57
|
+
makeMiddlewareCommand.args = {
|
|
58
|
+
name: generateRandomName(),
|
|
59
|
+
}
|
|
60
|
+
const spy = spyOn(makeMiddlewareCommand, 'handle')
|
|
61
|
+
|
|
62
|
+
// first attempt it will create new middleware
|
|
63
|
+
await makeMiddlewareCommand.handle()
|
|
64
|
+
// second attempt it should return error because middleware directory exists
|
|
65
|
+
await makeMiddlewareCommand.handle()
|
|
66
|
+
|
|
67
|
+
shell.rm('-rf', `${dir}/${makeMiddlewareCommand.args.name}`)
|
|
68
|
+
|
|
69
|
+
expect(console.error).toHaveBeenCalled()
|
|
70
|
+
expect(console.error).toHaveBeenCalledWith(Color.red('Middleware directory is exists'))
|
|
71
|
+
expect(spy).toHaveBeenCalled()
|
|
72
|
+
})
|
|
73
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ExpressCli } from '@point-hub/express-cli'
|
|
2
|
+
import { expect, it } from 'bun:test'
|
|
3
|
+
|
|
4
|
+
import { ConsoleKernel } from './index'
|
|
5
|
+
|
|
6
|
+
it('express cli to be defined', async () => {
|
|
7
|
+
const cli = new ExpressCli('cli', '1.0.0')
|
|
8
|
+
|
|
9
|
+
const kernel = new ConsoleKernel(cli)
|
|
10
|
+
await kernel.register()
|
|
11
|
+
|
|
12
|
+
expect(cli).toBeDefined()
|
|
13
|
+
expect(cli).toBeInstanceOf(ExpressCli)
|
|
14
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ExpressCli } from '@point-hub/express-cli'
|
|
2
|
+
|
|
3
|
+
import MakeCommand from './commands/make-command/index.command'
|
|
4
|
+
import MakeMiddleware from './commands/make-middleware/index.command'
|
|
5
|
+
|
|
6
|
+
export class ConsoleKernel {
|
|
7
|
+
private command: ExpressCli
|
|
8
|
+
|
|
9
|
+
constructor(command: ExpressCli) {
|
|
10
|
+
this.command = command
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Register the commands for the application.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* this.command.register(new ExampleCommand());
|
|
18
|
+
*/
|
|
19
|
+
async register() {
|
|
20
|
+
this.command.register(new MakeCommand())
|
|
21
|
+
this.command.register(new MakeMiddleware())
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export class DatabaseConnection implements IDatabase {
|
|
2
|
+
session: unknown
|
|
3
|
+
constructor(public adapter: IDatabase) {}
|
|
4
|
+
public async open(): Promise<void> {
|
|
5
|
+
await this.adapter.open()
|
|
6
|
+
}
|
|
7
|
+
public async close(): Promise<void> {
|
|
8
|
+
await this.adapter.close()
|
|
9
|
+
}
|
|
10
|
+
public database(name: string): this {
|
|
11
|
+
this.adapter.database(name)
|
|
12
|
+
return this
|
|
13
|
+
}
|
|
14
|
+
public collection(name: string): this {
|
|
15
|
+
this.adapter.collection(name)
|
|
16
|
+
return this
|
|
17
|
+
}
|
|
18
|
+
public async listCollections(): Promise<{ name: string }[]> {
|
|
19
|
+
return this.adapter.listCollections()
|
|
20
|
+
}
|
|
21
|
+
public startSession() {
|
|
22
|
+
return this.adapter.startSession()
|
|
23
|
+
}
|
|
24
|
+
public async endSession() {
|
|
25
|
+
await this.adapter.endSession()
|
|
26
|
+
}
|
|
27
|
+
public startTransaction() {
|
|
28
|
+
this.adapter.startTransaction()
|
|
29
|
+
}
|
|
30
|
+
public async commitTransaction() {
|
|
31
|
+
await this.adapter.commitTransaction()
|
|
32
|
+
}
|
|
33
|
+
public async abortTransaction() {
|
|
34
|
+
await this.adapter.abortTransaction()
|
|
35
|
+
}
|
|
36
|
+
public async createIndex(name: string, spec: unknown, options?: unknown) {
|
|
37
|
+
await this.adapter.createIndex(name, spec, options)
|
|
38
|
+
}
|
|
39
|
+
public async createCollection(name: string, options?: unknown) {
|
|
40
|
+
await this.adapter.createCollection(name, options)
|
|
41
|
+
}
|
|
42
|
+
public async dropCollection(name: string, options?: unknown) {
|
|
43
|
+
await this.adapter.dropCollection(name, options)
|
|
44
|
+
}
|
|
45
|
+
public async updateSchema(name: string, schema: unknown) {
|
|
46
|
+
await this.adapter.updateSchema(name, schema)
|
|
47
|
+
}
|
|
48
|
+
public async create(document: IDocument, options?: unknown): Promise<ICreateOutput> {
|
|
49
|
+
return await this.adapter.create(document, options)
|
|
50
|
+
}
|
|
51
|
+
public async createMany(documents: IDocument[], options?: unknown): Promise<ICreateManyOutput> {
|
|
52
|
+
return await this.adapter.createMany(documents, options)
|
|
53
|
+
}
|
|
54
|
+
public async retrieveAll(query: IQuery, options?: unknown): Promise<IRetrieveAllOutput> {
|
|
55
|
+
return await this.adapter.retrieveAll(query, options)
|
|
56
|
+
}
|
|
57
|
+
public async retrieve(_id: string, options?: unknown): Promise<IRetrieveOutput> {
|
|
58
|
+
return await this.adapter.retrieve(_id, options)
|
|
59
|
+
}
|
|
60
|
+
public async update(_id: string, document: IDocument, options?: unknown): Promise<IUpdateOutput> {
|
|
61
|
+
return await this.adapter.update(_id, document, options)
|
|
62
|
+
}
|
|
63
|
+
public async updateMany(filter: IDocument, document: IDocument, options?: unknown): Promise<IUpdateManyOutput> {
|
|
64
|
+
return await this.adapter.updateMany(filter, document, options)
|
|
65
|
+
}
|
|
66
|
+
public async delete(_id: string, options?: unknown): Promise<IDeleteOutput> {
|
|
67
|
+
return await this.adapter.delete(_id, options)
|
|
68
|
+
}
|
|
69
|
+
public async deleteMany(_ids: string[], options?: unknown): Promise<IDeleteManyOutput> {
|
|
70
|
+
return await this.adapter.deleteMany(_ids, options)
|
|
71
|
+
}
|
|
72
|
+
public async deleteAll(options?: unknown): Promise<IDeleteManyOutput> {
|
|
73
|
+
return await this.adapter.deleteAll(options)
|
|
74
|
+
}
|
|
75
|
+
public async aggregate(pipeline: IPipeline[], query: IQuery, options?: unknown): Promise<IAggregateOutput> {
|
|
76
|
+
return await this.adapter.aggregate(pipeline, query, options)
|
|
77
|
+
}
|
|
78
|
+
}
|