te.js 1.0.0 → 1.0.2

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/.prettierrc CHANGED
@@ -1,5 +1,5 @@
1
- {
2
- "singleQuote": true,
3
- "printWidth": 80,
4
- "semi": true
1
+ {
2
+ "singleQuote": true,
3
+ "printWidth": 80,
4
+ "semi": true
5
5
  }
package/database/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import mongo from './mongo.js';
2
-
3
- const database = {
4
- mongodb: mongo,
5
- };
6
-
7
- export default database;
1
+ import mongo from './mongo.js';
2
+
3
+ const database = {
4
+ mongodb: mongo,
5
+ };
6
+
7
+ export default database;
package/database/mongo.js CHANGED
@@ -1,14 +1,67 @@
1
- import mongoose from './../example/node_modules/mongoose';
2
-
3
- const connect = (uri, options, cb) => {
4
- mongoose
5
- .connect(uri, options)
6
- .then(() => {
7
- cb(undefined);
8
- })
9
- .catch((error) => {
10
- cb(error);
11
- });
12
- };
13
-
14
- export default connect;
1
+ import { spawn } from 'node:child_process';
2
+ import { pathToFileURL } from 'node:url';
3
+ import TejLogger from 'tej-logger';
4
+
5
+ const packagePath = `${process.cwd()}/node_modules/mongoose/index.js`;
6
+ const logger = new TejLogger('Tejas CLI');
7
+
8
+ let mongoose = undefined;
9
+
10
+ const connect = async (uri, options, cb) => {
11
+
12
+ try {
13
+ mongoose = await import(pathToFileURL(packagePath));
14
+
15
+ } catch (error) {
16
+ if (error.code === 'ERR_MODULE_NOT_FOUND') {
17
+ await installMongoose('npm install mongoose');
18
+ mongoose = await import(pathToFileURL(packagePath));
19
+
20
+ } else {
21
+ cb(error);
22
+ }
23
+
24
+ } finally {
25
+ mongoose.connect(uri, options).then(() => {
26
+ cb(undefined);
27
+ }).catch((error) => {
28
+ cb(error);
29
+ });
30
+ }
31
+ };
32
+
33
+ function installMongoose(command) {
34
+ return new Promise((resolve, reject) => {
35
+ const spinner = ['|', '/', '-', '\\'];
36
+ let current = 0;
37
+
38
+ // Start the spinner
39
+ const intervalId = setInterval(() => {
40
+ process.stdout.write(`\r${spinner[current]} Installing mongoose...`);
41
+ current = (current + 1) % spinner.length;
42
+ }, 100);
43
+
44
+ // Execute the command asynchronously to keep the spinner going
45
+ const child = spawn(command, { shell: true });
46
+ logger.info('Tejas will install mongoose to connect to mongodb...');
47
+
48
+ child.stderr.on('data', (data) => {
49
+ logger.error(`\n${data}`);
50
+ });
51
+
52
+ child.on('close', (code) => {
53
+ process.stdout.write('\r');
54
+ clearInterval(intervalId);
55
+ if (code === 0) {
56
+ // Remove stdout of Installing mongodb...
57
+ logger.info('Mongoose installed successfully');
58
+ resolve();
59
+ } else {
60
+ logger.error('Mongoose installation failed');
61
+ reject();
62
+ }
63
+ });
64
+ });
65
+ }
66
+
67
+ export default connect;
package/example/index.js CHANGED
@@ -1,6 +1,4 @@
1
- import { Tejas } from 'te.js';
2
- import './routes/index.target.js';
3
-
4
- const tejas = new Tejas();
5
- tejas.connectDatabase();
6
- tejas.takeoff();
1
+ import { Tejas } from 'te.js';
2
+
3
+ const tejas = new Tejas();
4
+ tejas.takeoff();
@@ -0,0 +1,6 @@
1
+ const globalMidair = async (ammo, next) => {
2
+ console.log('Global middleware');
3
+ await next();
4
+ };
5
+
6
+ export { globalMidair };
@@ -12,8 +12,9 @@
12
12
  "author": "",
13
13
  "license": "ISC",
14
14
  "dependencies": {
15
+ "cors": "^2.8.5",
16
+ "mongoose": "^8.3.1",
15
17
  "te.js": "file:..",
16
- "tej-env": "^1.0.2",
17
- "mongoose": "^8.3.1"
18
+ "tej-env": "^1.0.2"
18
19
  }
19
20
  }
@@ -1,10 +1,11 @@
1
- import { Target } from "te.js";
2
-
3
- const target = new Target();
4
-
5
- target.register('/hello', (ammo) => {
6
- ammo.dispatch({
7
- status: 200,
8
- body: 'Hello, World!',
9
- });
10
- });
1
+ import { Target } from 'te.js';
2
+ import auth from '../middlewares/auth.js';
3
+
4
+ const target = new Target();
5
+
6
+ target.register('/hello', (ammo) => {
7
+ ammo.fire({
8
+ status: 200,
9
+ body: 'Hello, World!',
10
+ });
11
+ });
@@ -0,0 +1,17 @@
1
+ import { Target, TejFileUploader } from 'te.js';
2
+
3
+ const target = new Target('/user');
4
+
5
+ const upload = new TejFileUploader({
6
+ destination: 'public/uploads',
7
+ maxFileSize: 5 * 1024 * 1024,
8
+ });
9
+
10
+ target.register(
11
+ '/updateProfileImage',
12
+ upload.files('photos', 'covers'),
13
+ (ammo) => {
14
+ console.log(ammo.payload);
15
+ ammo.fire('Profile image updated successfully!')
16
+ },
17
+ );
@@ -4,8 +4,11 @@
4
4
  "http_requests": true,
5
5
  "exceptions": true
6
6
  },
7
+ "dir":{
8
+ "targets": "targets"
9
+ },
7
10
  "db": {
8
11
  "type": "mongodb",
9
- "uri": "mongodb://localhost:27017/te-js"
12
+ "uri": "mongodb+srv://sheldon-cooper:J1T6P1rK4TYXCzUB@adb-cloaker.bhw9t.mongodb.net/retag-cloaker?retryWrites=true&w=majority"
10
13
  }
11
- }
14
+ }
package/package.json CHANGED
@@ -1,34 +1,36 @@
1
- {
2
- "name": "te.js",
3
- "version": "1.0.0",
4
- "description": "A nodejs framework",
5
- "type": "module",
6
- "main": "te.js",
7
- "scripts": {
8
- "start": "node te.js",
9
- "test": "echo \"Error: no test specified\" && exit 1",
10
- "prepare": "husky"
11
- },
12
- "author": "Hirak",
13
- "license": "ISC",
14
- "devDependencies": {
15
- "@types/node": "^20.12.5",
16
- "husky": "^9.0.11",
17
- "lint-staged": "^15.2.2",
18
- "prettier": "3.2.5"
19
- },
20
- "repository": {
21
- "type": "git",
22
- "url": "git@github.com:hirakchhatbar/te.js.git"
23
- },
24
- "dependencies": {
25
- "ansi-colors": "^4.1.3",
26
- "formidable": "^3.5.1",
27
- "statuses": "^2.0.1",
28
- "tej-env": "^1.0.5",
29
- "tej-logger": "^1.2.1"
30
- },
31
- "lint-staged": {
32
- "**/*.{js,ts}": "prettier --write --ignore-unknown"
33
- }
34
- }
1
+ {
2
+ "name": "te.js",
3
+ "version": "1.0.2",
4
+ "description": "A nodejs framework",
5
+ "type": "module",
6
+ "main": "te.js",
7
+ "scripts": {
8
+ "start": "node te.js",
9
+ "test": "echo \"Error: no test specified\" && exit 1",
10
+ "prepare": "husky"
11
+ },
12
+ "author": "Hirak",
13
+ "license": "ISC",
14
+ "devDependencies": {
15
+ "@types/node": "^20.12.5",
16
+ "husky": "^9.0.11",
17
+ "lint-staged": "^15.2.2",
18
+ "prettier": "3.2.5"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git@github.com:hirakchhatbar/te.js.git"
23
+ },
24
+ "dependencies": {
25
+ "ansi-colors": "^4.1.3",
26
+ "filesize": "^10.1.1",
27
+ "formidable": "^3.5.1",
28
+ "mime": "^4.0.1",
29
+ "statuses": "^2.0.1",
30
+ "tej-env": "^1.0.5",
31
+ "tej-logger": "^1.2.1"
32
+ },
33
+ "lint-staged": {
34
+ "**/*.{js,ts}": "prettier --write --ignore-unknown"
35
+ }
36
+ }
@@ -1,51 +1,93 @@
1
- import formidable from 'formidable';
2
-
3
- async function parseDataBasedOnContentType(req) {
4
- // Check if content type is JSON
5
- if (req.headers['content-type'] === 'application/json') {
6
- return await parseJSONRequestBody(req);
7
- }
8
-
9
- // Check if content type is URL encoded
10
- if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
11
- return await parseUrlEncodedData(req);
12
- }
13
-
14
- return null;
15
- }
16
-
17
- function parseJSONRequestBody(req) {
18
- return new Promise((resolve, reject) => {
19
- let body = '';
20
- req.on('data', (chunk) => {
21
- body += chunk.toString();
22
- });
23
-
24
- req.on('end', () => {
25
- try {
26
- const jsonData = JSON.parse(body);
27
- resolve(jsonData); // Resolve promise with the parsed JSON
28
- } catch (err) {
29
- reject(new Error('Invalid JSON')); // Reject promise if JSON parsing fails
30
- }
31
- });
32
- });
33
- }
34
-
35
- function parseUrlEncodedData(req) {
36
- return new Promise((resolve, reject) => {
37
- let body = '';
38
-
39
- req.on('data', (chunk) => {
40
- body += chunk.toString();
41
- });
42
-
43
- req.on('end', () => {
44
- const data = new URLSearchParams(body);
45
- const parsedData = Object.fromEntries(data);
46
- resolve(parsedData);
47
- });
48
- });
49
- }
50
-
51
- export default parseDataBasedOnContentType;
1
+ async function parseDataBasedOnContentType(req) {
2
+ // Check if content type is JSON
3
+ if (req.headers['content-type'] === 'application/json') {
4
+ return await parseJSONRequestBody(req);
5
+ }
6
+
7
+ // Check if content type is URL encoded
8
+ if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
9
+ return await parseUrlEncodedData(req);
10
+ }
11
+
12
+ // Check if content type is multipart form data
13
+ if (req.headers['content-type']?.startsWith('multipart/form-data')) {
14
+ return await parseFormData(req);
15
+ }
16
+
17
+ return null;
18
+ }
19
+
20
+ function parseJSONRequestBody(req) {
21
+ return new Promise((resolve, reject) => {
22
+ let body = '';
23
+ req.on('data', (chunk) => {
24
+ body += chunk.toString();
25
+ });
26
+
27
+ req.on('end', () => {
28
+ try {
29
+ const jsonData = JSON.parse(body);
30
+ resolve(jsonData); // Resolve promise with the parsed JSON
31
+ } catch (err) {
32
+ reject(new Error('Invalid JSON')); // Reject promise if JSON parsing fails
33
+ }
34
+ });
35
+ });
36
+ }
37
+
38
+ function parseUrlEncodedData(req) {
39
+ return new Promise((resolve, reject) => {
40
+ let body = '';
41
+
42
+ req.on('data', (chunk) => {
43
+ body += chunk.toString();
44
+ });
45
+
46
+ req.on('end', () => {
47
+ const data = new URLSearchParams(body);
48
+ const parsedData = Object.fromEntries(data);
49
+ resolve(parsedData);
50
+ });
51
+ });
52
+ }
53
+
54
+ function parseFormData(req) {
55
+ return new Promise((resolve, reject) => {
56
+ let body = '';
57
+
58
+ let files = [];
59
+ let fields = [];
60
+
61
+ req.on('data', (chunk) => {
62
+ body += chunk.toString();
63
+ });
64
+
65
+ req.on('end', () => {
66
+ // Detect and parse multipart form data
67
+ if (req.headers['content-type'].startsWith('multipart/form-data')) {
68
+ const boundary =
69
+ '--' + req.headers['content-type'].split('boundary=')[1];
70
+ const parts = body
71
+ .split(boundary)
72
+ .filter((part) => part.trim() !== '' && part.trim() !== '--');
73
+
74
+ const parsedData = parts.map((part) => {
75
+ const partData = part.split('\r\n\r\n');
76
+ const headersPart = partData[0].trim().split('\r\n');
77
+ const valuePart = partData[1].trim();
78
+ let headers = {};
79
+
80
+ headersPart.forEach((header) => {
81
+ const [key, value] = header.split(': ');
82
+ headers[key.toLowerCase()] = value;
83
+ });
84
+ return { headers, value: valuePart };
85
+ });
86
+
87
+ resolve(parsedData);
88
+ }
89
+ });
90
+ });
91
+ }
92
+
93
+ export default parseDataBasedOnContentType;
@@ -1,53 +1,53 @@
1
- import status from 'statuses';
2
-
3
- const formattedData = (data) => {
4
- if (typeof data === 'object') return JSON.stringify(data);
5
- if (typeof data === 'string') return data;
6
- if (typeof data === 'number') return status[data];
7
- return data;
8
- };
9
-
10
- const statusAndData = (args) => {
11
- if (!args || args.length === 0)
12
- return {
13
- statusCode: 204,
14
- data: status(204),
15
- contentType: 'text/plain',
16
- };
17
-
18
- if (args.length === 1 && typeof args[0] === 'number')
19
- return {
20
- statusCode: args[0],
21
- data: status(args[0]),
22
- contentType: 'text/plain',
23
- };
24
-
25
- let statusCode = 200;
26
- let data = args[0];
27
- if (args.length > 1) {
28
- statusCode = args[0];
29
- data = args[1];
30
- if (!data) data = status[statusCode];
31
- }
32
-
33
- return {
34
- statusCode,
35
- data: formattedData(data),
36
- contentType: contentType(data),
37
- };
38
- };
39
-
40
- const contentType = (data) => {
41
- switch (typeof data) {
42
- case 'object':
43
- return 'application/json';
44
- case 'string':
45
- return 'text/html';
46
- case 'number':
47
- return 'text/plain';
48
- default:
49
- return 'text/plain';
50
- }
51
- };
52
-
53
- export { statusAndData, contentType };
1
+ import status from 'statuses';
2
+
3
+ const formattedData = (data) => {
4
+ if (typeof data === 'object') return JSON.stringify(data);
5
+ if (typeof data === 'string') return data;
6
+ if (typeof data === 'number') return status[data];
7
+ return data;
8
+ };
9
+
10
+ const statusAndData = (args) => {
11
+ if (!args || args.length === 0)
12
+ return {
13
+ statusCode: 204,
14
+ data: status(204),
15
+ contentType: 'text/plain',
16
+ };
17
+
18
+ if (args.length === 1 && typeof args[0] === 'number')
19
+ return {
20
+ statusCode: args[0],
21
+ data: status(args[0]),
22
+ contentType: 'text/plain',
23
+ };
24
+
25
+ let statusCode = 200;
26
+ let data = args[0];
27
+ if (args.length > 1) {
28
+ statusCode = args[0];
29
+ data = args[1];
30
+ if (!data) data = status[statusCode];
31
+ }
32
+
33
+ return {
34
+ statusCode,
35
+ data: formattedData(data),
36
+ contentType: contentType(data),
37
+ };
38
+ };
39
+
40
+ const contentType = (data) => {
41
+ switch (typeof data) {
42
+ case 'object':
43
+ return 'application/json';
44
+ case 'string':
45
+ return 'text/html';
46
+ case 'number':
47
+ return 'text/plain';
48
+ default:
49
+ return 'text/plain';
50
+ }
51
+ };
52
+
53
+ export { statusAndData, contentType };
@@ -1,53 +1,53 @@
1
- import bodyParser from './body-parser.js';
2
-
3
- function hostname(req) {
4
- let host = req.headers['X-Forwarded-Host'];
5
-
6
- if (!host) {
7
- host = req.headers.host;
8
- } else if (host.indexOf(',') !== -1) {
9
- host = host.substring(0, host.indexOf(',')).trimRight();
10
- }
11
-
12
- return host;
13
- }
14
-
15
- async function generatePayload(req) {
16
- const obj = {};
17
-
18
- const searchParams = new URLSearchParams(req.url.split('?')[1]);
19
- for (const [key, value] of searchParams) {
20
- obj[key] = value;
21
- }
22
-
23
- const body = await bodyParser(req);
24
- if (body) Object.assign(obj, body);
25
- return obj;
26
- }
27
-
28
- function protocol(req) {
29
- const proto = req.connection.encrypted ? 'https' : 'http';
30
-
31
- const header = req.headers['X-Forwarded-Proto'] || proto;
32
- const index = header.indexOf(',');
33
-
34
- return index !== -1 ? header.substring(0, index).trim() : header.trim();
35
- }
36
-
37
- const enhance = async (ammo) => {
38
- const req = ammo.req;
39
-
40
- ammo.ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
41
- ammo.headers = req.headers;
42
- ammo.payload = await generatePayload(req);
43
- ammo.method = req.method;
44
-
45
- ammo.protocol = protocol(req);
46
- ammo.hostname = hostname(req);
47
- ammo.path = req.url;
48
- ammo.endpoint = req.url.split('?')[0];
49
-
50
- ammo.fullURL = `${ammo.protocol}://${ammo.hostname}/${ammo.path}`;
51
- };
52
-
53
- export default enhance;
1
+ import bodyParser from './body-parser.js';
2
+
3
+ function hostname(req) {
4
+ let host = req.headers['X-Forwarded-Host'];
5
+
6
+ if (!host) {
7
+ host = req.headers.host;
8
+ } else if (host.indexOf(',') !== -1) {
9
+ host = host.substring(0, host.indexOf(',')).trimRight();
10
+ }
11
+
12
+ return host;
13
+ }
14
+
15
+ async function generatePayload(req) {
16
+ const obj = {};
17
+
18
+ const searchParams = new URLSearchParams(req.url.split('?')[1]);
19
+ for (const [key, value] of searchParams) {
20
+ obj[key] = value;
21
+ }
22
+
23
+ const body = await bodyParser(req);
24
+ if (body) Object.assign(obj, body);
25
+ return obj;
26
+ }
27
+
28
+ function protocol(req) {
29
+ const proto = req.connection.encrypted ? 'https' : 'http';
30
+
31
+ const header = req.headers['X-Forwarded-Proto'] || proto;
32
+ const index = header.indexOf(',');
33
+
34
+ return index !== -1 ? header.substring(0, index).trim() : header.trim();
35
+ }
36
+
37
+ const enhance = async (ammo) => {
38
+ const req = ammo.req;
39
+
40
+ ammo.ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
41
+ ammo.headers = req.headers;
42
+ ammo.payload = await generatePayload(req);
43
+ ammo.method = req.method;
44
+
45
+ ammo.protocol = protocol(req);
46
+ ammo.hostname = hostname(req);
47
+ ammo.path = req.url;
48
+ ammo.endpoint = req.url.split('?')[0];
49
+
50
+ ammo.fullURL = `${ammo.protocol}://${ammo.hostname}/${ammo.path}`;
51
+ };
52
+
53
+ export default enhance;