abhijanb 0.1.1 → 0.1.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/a/README.md +15 -0
- package/a/index.ts +26 -0
- package/a/package.json +19 -0
- package/index.ts +3 -24
- package/lib/index.ts +20 -0
- package/package.json +4 -2
- package/util/index.ts +25 -0
- package/util/response.ts +116 -0
- package/util/validate.ts +27 -0
- package/validate.ts +0 -17
- /package/{auth.ts → lib/auth.ts} +0 -0
- /package/{rateLimiter.ts → lib/rateLimiter.ts} +0 -0
- /package/{socket.ts → lib/socket.ts} +0 -0
package/a/README.md
ADDED
package/a/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { startSocket, validate } from 'abhijanb';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
const app = express();
|
|
5
|
+
const {server} = startSocket(app);
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const schema = z.object({
|
|
9
|
+
name: z.string(),
|
|
10
|
+
age: z.number().int().positive(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
app.use(express.json());
|
|
14
|
+
|
|
15
|
+
app.post('/validate', (req, res) => {
|
|
16
|
+
const result = validate(schema, req.body);
|
|
17
|
+
if (result.success) {
|
|
18
|
+
res.json({ message: 'Validation successful', data: result.data });
|
|
19
|
+
} else {
|
|
20
|
+
res.status(400).json({ message: 'Validation failed', errors: result.errors });
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
server.listen(3000, () => {
|
|
25
|
+
console.log('Server is running on port 3000');
|
|
26
|
+
});
|
package/a/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "a",
|
|
3
|
+
"module": "index.ts",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "bun --watch index.ts"
|
|
8
|
+
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/bun": "latest"
|
|
12
|
+
},
|
|
13
|
+
"peerDependencies": {
|
|
14
|
+
"typescript": "^5"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"abhijanb": "^0.1.1"
|
|
18
|
+
}
|
|
19
|
+
}
|
package/index.ts
CHANGED
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
export type { Socket } from "./socket";
|
|
5
|
-
|
|
6
|
-
/** Rate limiter factory: `app.use(limiter(5, 1000))` = 5min window, 1000 req/IP */
|
|
7
|
-
export { limiter } from "./rateLimiter";
|
|
8
|
-
/** Factory — create custom rate limiters: `rateLimit({ windowMs: 60000, max: 20 })` */
|
|
9
|
-
export { rateLimit } from "./rateLimiter";
|
|
10
|
-
|
|
11
|
-
/** JWT middleware — verifies Bearer token, attaches decoded payload to `req.user` */
|
|
12
|
-
export { authMiddleware } from "./auth";
|
|
13
|
-
/** Sign an access token: `signToken({ userId: 1 })` */
|
|
14
|
-
export { signToken } from "./auth";
|
|
15
|
-
/** Sign a refresh token: `signRefreshToken({ userId: 1 })` */
|
|
16
|
-
export { signRefreshToken } from "./auth";
|
|
17
|
-
/** Verify and decode a token: `verifyToken<T>(token)` */
|
|
18
|
-
export { verifyToken } from "./auth";
|
|
19
|
-
/** Refresh: verify refresh token → return new access token */
|
|
20
|
-
export { refreshToken } from "./auth";
|
|
21
|
-
|
|
22
|
-
/** Validate data against Zod schema: `validate(schema, data)` → { success, data, errors } */
|
|
23
|
-
export { validate } from "./validate";
|
|
24
|
-
export type { ValidateResult } from "./validate";
|
|
1
|
+
/** Main entry point — re-exports everything from util/ and lib/ */
|
|
2
|
+
export * from "./util";
|
|
3
|
+
export * from "./lib";
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Start Socket.IO on an Express app: `startSocket(app)` → returns { server, io, socket } */
|
|
2
|
+
export { startSocket, io, socket } from "./socket";
|
|
3
|
+
/** Socket type — for typing event handlers */
|
|
4
|
+
export type { Socket } from "./socket";
|
|
5
|
+
|
|
6
|
+
/** Rate limiter factory: `app.use(limiter(5, 1000))` = 5min window, 1000 req/IP */
|
|
7
|
+
export { limiter } from "./rateLimiter";
|
|
8
|
+
/** Factory — create custom rate limiters: `rateLimit({ windowMs: 60000, max: 20 })` */
|
|
9
|
+
export { rateLimit } from "./rateLimiter";
|
|
10
|
+
|
|
11
|
+
/** JWT middleware — verifies Bearer token, attaches decoded payload to `req.user` */
|
|
12
|
+
export { authMiddleware } from "./auth";
|
|
13
|
+
/** Sign an access token: `signToken({ userId: 1 })` */
|
|
14
|
+
export { signToken } from "./auth";
|
|
15
|
+
/** Sign a refresh token: `signRefreshToken({ userId: 1 })` */
|
|
16
|
+
export { signRefreshToken } from "./auth";
|
|
17
|
+
/** Verify and decode a token: `verifyToken<T>(token)` */
|
|
18
|
+
export { verifyToken } from "./auth";
|
|
19
|
+
/** Refresh: verify refresh token → return new access token */
|
|
20
|
+
export { refreshToken } from "./auth";
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abhijanb",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
|
-
".": "./index.ts"
|
|
7
|
+
".": "./index.ts",
|
|
8
|
+
"./util": "./util/index.ts",
|
|
9
|
+
"./lib": "./lib/index.ts"
|
|
8
10
|
},
|
|
9
11
|
"types": "./index.ts",
|
|
10
12
|
"dependencies": {
|
package/util/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Validate data against Zod schema: `validate(schema, data)` → { success, data, errors } */
|
|
2
|
+
export { validate } from "./validate";
|
|
3
|
+
export type { ValidateResult } from "./validate";
|
|
4
|
+
|
|
5
|
+
/** Response helpers: ok, created, badRequest, notFound, etc. */
|
|
6
|
+
export {
|
|
7
|
+
ok,
|
|
8
|
+
created,
|
|
9
|
+
noContent,
|
|
10
|
+
paginated,
|
|
11
|
+
badRequest,
|
|
12
|
+
unauthorized,
|
|
13
|
+
forbidden,
|
|
14
|
+
notFound,
|
|
15
|
+
conflict,
|
|
16
|
+
internalError,
|
|
17
|
+
fail,
|
|
18
|
+
} from "./response";
|
|
19
|
+
|
|
20
|
+
/** Response namespace: `response.ok(res, data)`, `response.created(res, data)` */
|
|
21
|
+
export { response } from "./response";
|
|
22
|
+
|
|
23
|
+
/** Status codes and error codes constants */
|
|
24
|
+
export { STATUS_CODE, ERROR_CODES } from "./response";
|
|
25
|
+
export type { StatusCode, ErrorCode, ApiResponse, ApiErrorResponse } from "./response";
|
package/util/response.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Response } from "express";
|
|
2
|
+
|
|
3
|
+
const STATUS_CODE = {
|
|
4
|
+
OK: 200,
|
|
5
|
+
CREATED: 201,
|
|
6
|
+
NO_CONTENT: 204,
|
|
7
|
+
BAD_REQUEST: 400,
|
|
8
|
+
UNAUTHORIZED: 401,
|
|
9
|
+
FORBIDDEN: 403,
|
|
10
|
+
NOT_FOUND: 404,
|
|
11
|
+
CONFLICT: 409,
|
|
12
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
const ERROR_CODES = {
|
|
16
|
+
BAD_REQUEST: "BAD_REQUEST",
|
|
17
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
18
|
+
FORBIDDEN: "FORBIDDEN",
|
|
19
|
+
NOT_FOUND: "NOT_FOUND",
|
|
20
|
+
CONFLICT: "CONFLICT",
|
|
21
|
+
INTERNAL_SERVER_ERROR: "INTERNAL_SERVER_ERROR",
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
type StatusCode = (typeof STATUS_CODE)[keyof typeof STATUS_CODE];
|
|
25
|
+
type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
26
|
+
|
|
27
|
+
type ApiResponse<T> = { success: true; data: T; meta?: Record<string, unknown> };
|
|
28
|
+
type ApiErrorResponse = { success: false; error: { code: ErrorCode; message: string; details?: unknown } };
|
|
29
|
+
|
|
30
|
+
function successResponse<T>(data: T, meta?: Record<string, unknown>): ApiResponse<T> {
|
|
31
|
+
return { success: true, data, ...(meta && { meta }) };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function errorResponse(code: ErrorCode, message: string, details?: unknown): ApiErrorResponse {
|
|
35
|
+
return { success: false, error: { code, message, details } };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function ok<T>(res: Response, data: T, meta?: Record<string, unknown>) {
|
|
39
|
+
res.status(STATUS_CODE.OK).json(successResponse(data, meta));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function created<T>(res: Response, data: T) {
|
|
43
|
+
res.status(STATUS_CODE.CREATED).json(successResponse(data));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function noContent(res: Response) {
|
|
47
|
+
res.status(STATUS_CODE.NO_CONTENT).send();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function paginated<T>(
|
|
51
|
+
res: Response,
|
|
52
|
+
items: T[],
|
|
53
|
+
pagination: { page: number; limit: number; totalItems: number }
|
|
54
|
+
) {
|
|
55
|
+
res.status(STATUS_CODE.OK).json(
|
|
56
|
+
successResponse(items, {
|
|
57
|
+
pagination: {
|
|
58
|
+
page: pagination.page,
|
|
59
|
+
limit: pagination.limit,
|
|
60
|
+
totalItems: pagination.totalItems,
|
|
61
|
+
totalPages: Math.ceil(pagination.totalItems / pagination.limit),
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function fail(
|
|
68
|
+
res: Response,
|
|
69
|
+
{ status, code, message, details }: { status: StatusCode; code: ErrorCode; message: string; details?: unknown }
|
|
70
|
+
) {
|
|
71
|
+
res.status(status).json(errorResponse(code, message, details));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function badRequest(res: Response, message: string, details?: unknown) {
|
|
75
|
+
fail(res, { status: STATUS_CODE.BAD_REQUEST, code: ERROR_CODES.BAD_REQUEST, message, details });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function unauthorized(res: Response, message: string, details?: unknown) {
|
|
79
|
+
fail(res, { status: STATUS_CODE.UNAUTHORIZED, code: ERROR_CODES.UNAUTHORIZED, message, details });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function forbidden(res: Response, message: string, details?: unknown) {
|
|
83
|
+
fail(res, { status: STATUS_CODE.FORBIDDEN, code: ERROR_CODES.FORBIDDEN, message, details });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function notFound(res: Response, message: string, details?: unknown) {
|
|
87
|
+
fail(res, { status: STATUS_CODE.NOT_FOUND, code: ERROR_CODES.NOT_FOUND, message, details });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function conflict(res: Response, message: string, details?: unknown) {
|
|
91
|
+
fail(res, { status: STATUS_CODE.CONFLICT, code: ERROR_CODES.CONFLICT, message, details });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function internalError(res: Response, message: string, details?: unknown) {
|
|
95
|
+
fail(res, { status: STATUS_CODE.INTERNAL_SERVER_ERROR, code: ERROR_CODES.INTERNAL_SERVER_ERROR, message, details });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { STATUS_CODE, ERROR_CODES };
|
|
99
|
+
export type { StatusCode, ErrorCode, ApiResponse, ApiErrorResponse };
|
|
100
|
+
|
|
101
|
+
/** Response helper namespace: `response.ok(res, data)`, `response.created(res, data)` */
|
|
102
|
+
export const response = {
|
|
103
|
+
ok,
|
|
104
|
+
created,
|
|
105
|
+
noContent,
|
|
106
|
+
paginated,
|
|
107
|
+
badRequest,
|
|
108
|
+
unauthorized,
|
|
109
|
+
forbidden,
|
|
110
|
+
notFound,
|
|
111
|
+
conflict,
|
|
112
|
+
internalError,
|
|
113
|
+
fail,
|
|
114
|
+
STATUS_CODE,
|
|
115
|
+
ERROR_CODES,
|
|
116
|
+
};
|
package/util/validate.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ZodSchema, ZodError } from "zod";
|
|
3
|
+
|
|
4
|
+
type FormattedError = { field: string; message: string; code: string };
|
|
5
|
+
|
|
6
|
+
type ValidateResult<T> =
|
|
7
|
+
| { success: true; data: T; errors: null }
|
|
8
|
+
| { success: false; data: null; errors: FormattedError[] };
|
|
9
|
+
|
|
10
|
+
function formatZodErrors(error: ZodError): FormattedError[] {
|
|
11
|
+
return error.issues.map((issue) => ({
|
|
12
|
+
field: issue.path.length ? issue.path.join(".") : "root",
|
|
13
|
+
message: issue.message,
|
|
14
|
+
code: issue.code,
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Validate data against Zod schema → { success, data, errors } */
|
|
19
|
+
export function validate<T>(schema: ZodSchema<T>, data: unknown): ValidateResult<T> {
|
|
20
|
+
const result = schema.safeParse(data);
|
|
21
|
+
if (result.success) {
|
|
22
|
+
return { success: true, data: result.data, errors: null };
|
|
23
|
+
}
|
|
24
|
+
return { success: false, data: null, errors: formatZodErrors(result.error) };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { ValidateResult };
|
package/validate.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type { ZodSchema, ZodIssue } from "zod";
|
|
3
|
-
|
|
4
|
-
type ValidateResult<T> =
|
|
5
|
-
| { success: true; data: T; errors: null }
|
|
6
|
-
| { success: false; data: null; errors: ZodIssue[] };
|
|
7
|
-
|
|
8
|
-
/** Validate data against a Zod schema: `validate(schema, data)` → { success, data, errors } */
|
|
9
|
-
export function validate<T>(schema: ZodSchema<T>, data: unknown): ValidateResult<T> {
|
|
10
|
-
const result = schema.safeParse(data);
|
|
11
|
-
if (result.success) {
|
|
12
|
-
return { success: true, data: result.data, errors: null };
|
|
13
|
-
}
|
|
14
|
-
return { success: false, data: null, errors: result.error.issues };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type { ValidateResult };
|
/package/{auth.ts → lib/auth.ts}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|