@medyll/idae-api 0.0.1
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/README.md +0 -0
- package/dist/ApiServe.d.ts +10 -0
- package/dist/ApiServe.js +113 -0
- package/dist/engine/DBaseManager.d.ts +15 -0
- package/dist/engine/DBaseManager.js +49 -0
- package/dist/engine/DBaseService.d.ts +16 -0
- package/dist/engine/DBaseService.js +48 -0
- package/dist/engine/tools.d.ts +2 -0
- package/dist/engine/tools.js +11 -0
- package/dist/engine/types.d.ts +9 -0
- package/dist/engine/types.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +62 -0
package/README.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class ApiServe {
|
|
2
|
+
private app;
|
|
3
|
+
private port;
|
|
4
|
+
constructor(port?: number, mdbPort?: number, mdbName?: string);
|
|
5
|
+
private configureMiddleware;
|
|
6
|
+
private getDynamicModel;
|
|
7
|
+
private getCollectionName;
|
|
8
|
+
private configureRoutes;
|
|
9
|
+
start(): void;
|
|
10
|
+
}
|
package/dist/ApiServe.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// ServerConfig.ts
|
|
2
|
+
import express, {} from 'express';
|
|
3
|
+
import DBaseService from './engine/DBaseService.js';
|
|
4
|
+
import DatabaseManager from './engine/DBaseManager.js';
|
|
5
|
+
import mongoose, { Schema, Model, Document } from 'mongoose';
|
|
6
|
+
export class ApiServe {
|
|
7
|
+
constructor(port = 3000, mdbPort = 27017, mdbName = 'idae') {
|
|
8
|
+
this.app = express();
|
|
9
|
+
this.port = port;
|
|
10
|
+
this.configureMiddleware();
|
|
11
|
+
this.configureRoutes();
|
|
12
|
+
}
|
|
13
|
+
configureMiddleware() {
|
|
14
|
+
this.app.use(express.json());
|
|
15
|
+
}
|
|
16
|
+
getDynamicModel(collectionName) {
|
|
17
|
+
if (mongoose.models[collectionName]) {
|
|
18
|
+
return mongoose.models[collectionName];
|
|
19
|
+
}
|
|
20
|
+
const schema = new Schema({}, { strict: false });
|
|
21
|
+
return mongoose.model(collectionName, schema, collectionName);
|
|
22
|
+
}
|
|
23
|
+
getCollectionName(collectionName) {
|
|
24
|
+
let dbName, collection;
|
|
25
|
+
if (collectionName.includes('.')) {
|
|
26
|
+
[dbName, collection] = collectionName.split('.');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
collection = collectionName;
|
|
30
|
+
}
|
|
31
|
+
return collection;
|
|
32
|
+
}
|
|
33
|
+
configureRoutes() {
|
|
34
|
+
this.app.use('/:collectionName', DatabaseManager.connectToDatabase);
|
|
35
|
+
this.app.get('/:collectionName', async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const { collectionName } = req.params;
|
|
38
|
+
const collection = this.getCollectionName(collectionName);
|
|
39
|
+
const databaseService = new DBaseService(collection);
|
|
40
|
+
const documents = await databaseService.findAll(req.query);
|
|
41
|
+
res.send(documents);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
res.status(500).send(error);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
this.app.get('/:collectionName/:id', async (req, res) => {
|
|
48
|
+
try {
|
|
49
|
+
const { collectionName, id } = req.params;
|
|
50
|
+
const collection = this.getCollectionName(collectionName);
|
|
51
|
+
const databaseService = new DBaseService(collection);
|
|
52
|
+
const document = await databaseService.findById(id);
|
|
53
|
+
if (!document) {
|
|
54
|
+
return res.status(404).send({ error: 'Document not found' });
|
|
55
|
+
}
|
|
56
|
+
res.send(document);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
res.status(500).send(error);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
this.app.delete('/:collectionName/:id', async (req, res) => {
|
|
63
|
+
try {
|
|
64
|
+
const { collectionName, id } = req.params;
|
|
65
|
+
const collection = this.getCollectionName(collectionName);
|
|
66
|
+
const databaseService = new DBaseService(collection);
|
|
67
|
+
const result = await databaseService.deleteById(id);
|
|
68
|
+
res.send(result);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
res.status(500).send(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this.app.delete('/:collectionName/', async (req, res) => {
|
|
75
|
+
try {
|
|
76
|
+
const { collectionName } = req.params;
|
|
77
|
+
const collection = this.getCollectionName(collectionName);
|
|
78
|
+
const databaseService = new DBaseService(collection);
|
|
79
|
+
const result = await databaseService.deleteManyByQuery(req.query);
|
|
80
|
+
res.send(result);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
res.status(500).send(error);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
const directCommands = ['findAll', 'create', 'update', 'deleteById', 'deleteManyByQuery'];
|
|
87
|
+
this.app.all('/:collectionName/:command/:params?', async (req, res) => {
|
|
88
|
+
try {
|
|
89
|
+
const { collectionName, command, params } = req.params;
|
|
90
|
+
const collection = this.getCollectionName(collectionName);
|
|
91
|
+
if (!directCommands.includes(command)) {
|
|
92
|
+
return res.status(400).send({ error: 'Command not supported' });
|
|
93
|
+
}
|
|
94
|
+
const databaseService = new DBaseService(collection);
|
|
95
|
+
const decodedParams = params ? databaseService.decodeUrlParams(params) : {};
|
|
96
|
+
const result = await databaseService[command](decodedParams);
|
|
97
|
+
res.status(200).send(result);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
res.status(400).send({ error: error.message });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
start() {
|
|
105
|
+
this.app.listen(this.port, () => {
|
|
106
|
+
console.log(`Server is running on port: ${this.port}`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Usage:
|
|
111
|
+
// import { ServerConfig } from './ServerConfig.js';
|
|
112
|
+
//const server = new ApiServer(3050);
|
|
113
|
+
//server.start();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
declare const defaultDbName: string;
|
|
3
|
+
declare class DBaseManager {
|
|
4
|
+
private static instance;
|
|
5
|
+
static port: number;
|
|
6
|
+
constructor();
|
|
7
|
+
static getInstance(): DBaseManager;
|
|
8
|
+
connectToDatabase(req: Request<{
|
|
9
|
+
dbName: string;
|
|
10
|
+
collectionName: string;
|
|
11
|
+
}>, res: Response, next: NextFunction): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
declare const _default: DBaseManager;
|
|
14
|
+
export default _default;
|
|
15
|
+
export { DBaseManager as DatabaseManager, defaultDbName };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
const defaultDbName = 'idae';
|
|
3
|
+
// this is my middleware to connect to the appropriate database
|
|
4
|
+
class DBaseManager {
|
|
5
|
+
constructor() { }
|
|
6
|
+
static getInstance() {
|
|
7
|
+
if (!DBaseManager.instance) {
|
|
8
|
+
DBaseManager.instance = new DBaseManager();
|
|
9
|
+
}
|
|
10
|
+
return DBaseManager.instance;
|
|
11
|
+
}
|
|
12
|
+
async connectToDatabase(req, res, next) {
|
|
13
|
+
const { collectionName } = req.params;
|
|
14
|
+
let dbName;
|
|
15
|
+
//
|
|
16
|
+
if (collectionName.includes('.')) {
|
|
17
|
+
dbName = collectionName.split('.')[0];
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
dbName = defaultDbName;
|
|
21
|
+
}
|
|
22
|
+
const dbUri = `mongodb://localhost:${DBaseManager.port}/${dbName}`;
|
|
23
|
+
try {
|
|
24
|
+
if (!mongoose.connection.readyState) {
|
|
25
|
+
await mongoose.connect(dbUri, {
|
|
26
|
+
autoIndex: true,
|
|
27
|
+
dbName
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else if (mongoose.connection.name !== dbName) {
|
|
31
|
+
await mongoose.disconnect();
|
|
32
|
+
await mongoose.connect(dbUri, {
|
|
33
|
+
autoIndex: true,
|
|
34
|
+
dbName
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
console.log('connected to db', `${dbName}`);
|
|
38
|
+
next();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
/** @ts-ignore */
|
|
42
|
+
res.status(500).send(`Failed to connect to database ${dbName}: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
DBaseManager.port = 27017;
|
|
47
|
+
// i can call it as a normal class or as a singleton
|
|
48
|
+
export default DBaseManager.getInstance();
|
|
49
|
+
export { DBaseManager as DatabaseManager, defaultDbName };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Document } from 'mongoose';
|
|
2
|
+
import { type RequestParams } from './types';
|
|
3
|
+
declare class DBaseService {
|
|
4
|
+
private model;
|
|
5
|
+
constructor(collection: string);
|
|
6
|
+
create(document: any): Promise<Document>;
|
|
7
|
+
findAll(params: RequestParams): Promise<Document[]>;
|
|
8
|
+
findById(id: string): Promise<Document | null>;
|
|
9
|
+
findOne(params: RequestParams): Promise<Document | null>;
|
|
10
|
+
deleteById(id: string): Promise<Document | null>;
|
|
11
|
+
deleteManyByQuery(params: RequestParams): Promise<{
|
|
12
|
+
deletedCount?: number;
|
|
13
|
+
}>;
|
|
14
|
+
decodeUrlParams(urlParams: string): RequestParams;
|
|
15
|
+
}
|
|
16
|
+
export default DBaseService;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Model, Document } from 'mongoose';
|
|
2
|
+
import { getModel } from './tools';
|
|
3
|
+
import {} from './types';
|
|
4
|
+
class DBaseService {
|
|
5
|
+
constructor(collection) {
|
|
6
|
+
this.model = getModel(collection);
|
|
7
|
+
}
|
|
8
|
+
async create(document) {
|
|
9
|
+
const newDocument = new this.model(document);
|
|
10
|
+
return newDocument.save();
|
|
11
|
+
}
|
|
12
|
+
async findAll(params) {
|
|
13
|
+
const sortOptions = {};
|
|
14
|
+
if (params.sortBy) {
|
|
15
|
+
const sortFields = params.sortBy.split(',');
|
|
16
|
+
sortFields.forEach((field) => {
|
|
17
|
+
const [key, order] = field.split(':');
|
|
18
|
+
sortOptions[key] = order === 'desc' ? -1 : 1;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return this.model.find().sort(sortOptions);
|
|
22
|
+
}
|
|
23
|
+
async findById(id) {
|
|
24
|
+
return this.model.findById(id);
|
|
25
|
+
}
|
|
26
|
+
async findOne(params) {
|
|
27
|
+
return this.model.findOne(params.query);
|
|
28
|
+
}
|
|
29
|
+
async deleteById(id) {
|
|
30
|
+
return this.model.findByIdAndDelete(id);
|
|
31
|
+
}
|
|
32
|
+
async deleteManyByQuery(params) {
|
|
33
|
+
return this.model.deleteMany(params.query);
|
|
34
|
+
}
|
|
35
|
+
decodeUrlParams(urlParams) {
|
|
36
|
+
const params = {};
|
|
37
|
+
const urlParamsArray = urlParams.split('&');
|
|
38
|
+
urlParamsArray.forEach((param) => {
|
|
39
|
+
const [key, value] = param.split('=');
|
|
40
|
+
if (key && value) {
|
|
41
|
+
/** @ts-ignore */
|
|
42
|
+
params[key] = JSON.parse(decodeURIComponent(value));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return params;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export default DBaseService;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import mongoose, { Schema, Document, Model } from "mongoose";
|
|
2
|
+
import AutoIncrementFactory from "mongoose-sequence";
|
|
3
|
+
const AutoIncrement = AutoIncrementFactory(mongoose);
|
|
4
|
+
export const getModel = (collectionName) => {
|
|
5
|
+
if (mongoose.models[collectionName]) {
|
|
6
|
+
return mongoose.models[collectionName];
|
|
7
|
+
}
|
|
8
|
+
const schema = new Schema({}, { strict: false });
|
|
9
|
+
schema.plugin(AutoIncrement, { inc_field: "idFieldName" });
|
|
10
|
+
return mongoose.model(collectionName, schema, collectionName);
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ApiServe } from './ApiServe.js';
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@medyll/idae-api",
|
|
3
|
+
"scope": "@medyll",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite dev",
|
|
7
|
+
"build": "vite build && npm run package",
|
|
8
|
+
"preview": "vite preview",
|
|
9
|
+
"package": "svelte-kit sync && svelte-package && publint",
|
|
10
|
+
"prepublishOnly": "npm run package",
|
|
11
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
12
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
13
|
+
"test": "vitest",
|
|
14
|
+
"lint": "prettier --check . && eslint .",
|
|
15
|
+
"format": "prettier --write ."
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"svelte": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"!dist/**/*.test.*",
|
|
26
|
+
"!dist/**/*.spec.*"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"express": "^4.19.2",
|
|
30
|
+
"mongoose-sequence": "^6.0.1"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"svelte": "^4.0.0 || ^5.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@sveltejs/adapter-auto": "^3.0.0",
|
|
37
|
+
"@sveltejs/kit": "^2.0.0",
|
|
38
|
+
"@sveltejs/package": "^2.0.0",
|
|
39
|
+
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
|
40
|
+
"@types/eslint": "^8.56.7",
|
|
41
|
+
"@types/express": "^4.17.21",
|
|
42
|
+
"@types/mongoose": "^5.11.97",
|
|
43
|
+
"eslint": "^9.0.0",
|
|
44
|
+
"eslint-config-prettier": "^9.1.0",
|
|
45
|
+
"eslint-plugin-svelte": "^2.36.0",
|
|
46
|
+
"globals": "^15.0.0",
|
|
47
|
+
"prettier": "^3.1.1",
|
|
48
|
+
"prettier-plugin-svelte": "^3.1.2",
|
|
49
|
+
"publint": "^0.1.9",
|
|
50
|
+
"svelte": "^5.0.0-next.181",
|
|
51
|
+
"svelte-check": "^3.6.0",
|
|
52
|
+
"tslib": "^2.4.1",
|
|
53
|
+
"tsx": "^4.16.2",
|
|
54
|
+
"typescript": "^5.0.0",
|
|
55
|
+
"typescript-eslint": "^8.0.0-alpha.20",
|
|
56
|
+
"vite": "^5.0.11",
|
|
57
|
+
"vitest": "^1.2.0"
|
|
58
|
+
},
|
|
59
|
+
"svelte": "./dist/index.js",
|
|
60
|
+
"types": "./dist/index.d.ts",
|
|
61
|
+
"type": "module"
|
|
62
|
+
}
|