@0layimika/api-response-kit 0.1.0

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 ADDED
@@ -0,0 +1,114 @@
1
+ # api-response-kit
2
+
3
+ > A small, TypeScript-first toolkit for **consistent API success and error responses**.
4
+
5
+ ---
6
+
7
+ ## Why This Exists
8
+
9
+ Most APIs suffer from the same problems:
10
+
11
+ - Inconsistent response shapes across endpoints
12
+ - Ad-hoc error handling (`throw new Error`, random JSON)
13
+ - Frontend has to guess response structures
14
+ - Documentation drifts away from reality
15
+ - Boilerplate `res.status().json()` everywhere
16
+
17
+ **api-response-kit** fixes this by enforcing a **predictable response contract** for **both success and error responses** while keeping your code clean and framework-agnostic.
18
+
19
+ ---
20
+
21
+ ## Core Idea
22
+
23
+ Instead of:
24
+
25
+ ```ts
26
+ res.status(200).json(user)
27
+ res.status(400).json({ error: "Invalid input" })
28
+ ```
29
+
30
+ You write:
31
+ ```ts
32
+ return Ok(user)
33
+ return BadRequest("Invalid input")
34
+ ```
35
+ ## Response Contract
36
+ ### Success Response
37
+ ```ts
38
+ type ApiSuccess<T> = {
39
+ success: true
40
+ data: T
41
+ message?: string
42
+ meta?: Record<string, unknown>
43
+ }
44
+ ```
45
+ ### Error Response
46
+ ```ts
47
+ type ApiError = {
48
+ success: false
49
+ error: {
50
+ code: string
51
+ message: string
52
+ details?: unknown
53
+ }
54
+ }
55
+ ```
56
+ ## Installation
57
+ ```bash
58
+ npm install api-response-kit
59
+
60
+ yarn add api-response-kit
61
+
62
+ pnpm add api-response-kit
63
+ ```
64
+ ## Basic Usage
65
+ ### Success Helpers
66
+ ```ts
67
+ import { Ok, Created, NoContent } from "api-response-kit"
68
+
69
+ return Ok(user)
70
+ return Created(newUser)
71
+ return NoContent()
72
+ ```
73
+ ### Error Helpers
74
+ ```ts
75
+ import { BadRequest, NotFound, Unauthorized } from "api-response-kit"
76
+
77
+ if (!user) return NotFound("User not found")
78
+ if (!email) return BadRequest("Email is required")
79
+ if (!token) return Unauthorized()
80
+ ```
81
+
82
+ ## Controller Example
83
+ ```ts
84
+ export function getUser(id: string) {
85
+ const user = findUser(id)
86
+
87
+ if (!user) {
88
+ return NotFound("User")
89
+ }
90
+
91
+ return Ok(user)
92
+ }
93
+ ```
94
+
95
+ ## Express Adapter Example
96
+ ```ts
97
+ import { sendResponse } from "api-response-kit/express"
98
+
99
+ app.get("/users/:id", (req, res) => {
100
+ const response = getUser(req.params.id)
101
+ sendResponse(res, response)
102
+ })
103
+ ```
104
+ ## Custom Errors
105
+ ```ts
106
+ import { CustomError } from "api-response-kit"
107
+
108
+ return CustomError({
109
+ code: "PAYMENT_FAILED",
110
+ status: 402,
111
+ message: "Payment authorization failed"
112
+ })
113
+ ```
114
+
@@ -0,0 +1,6 @@
1
+ import { Response } from 'express';
2
+ import { b as ApiResponse } from '../response-DV8HnqXP.mjs';
3
+
4
+ declare function sendResponse(res: Response, response: ApiResponse<unknown>): void;
5
+
6
+ export { sendResponse };
@@ -0,0 +1,6 @@
1
+ import { Response } from 'express';
2
+ import { b as ApiResponse } from '../response-DV8HnqXP.js';
3
+
4
+ declare function sendResponse(res: Response, response: ApiResponse<unknown>): void;
5
+
6
+ export { sendResponse };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/adapters/express.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ sendResponse: () => sendResponse
24
+ });
25
+ module.exports = __toCommonJS(express_exports);
26
+
27
+ // src/core/status-map.ts
28
+ var statusMap = {
29
+ Ok: 200,
30
+ Created: 201,
31
+ NoContent: 204,
32
+ BadRequest: 400,
33
+ Unauthorized: 401,
34
+ Forbidden: 403,
35
+ NotFound: 404,
36
+ Conflict: 409,
37
+ InternalError: 500
38
+ };
39
+
40
+ // src/adapters/express.ts
41
+ function sendResponse(res, response) {
42
+ let status = 200;
43
+ if (response.success) {
44
+ status = 200;
45
+ } else {
46
+ const errorCode = response.error.code;
47
+ status = statusMap[errorCode] || 500;
48
+ }
49
+ res.status(status).json(response);
50
+ }
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ sendResponse
54
+ });
55
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/express.ts","../../src/core/status-map.ts"],"sourcesContent":["import {Response as ExResponse} from \"express\"\nimport {ApiResponse} from \"../core/response\";\nimport {statusMap} from \"../core/status-map\";\n\nexport function sendResponse(res: ExResponse, response: ApiResponse<unknown>): void {\n let status = 200\n if (response.success) {\n status = 200\n } else {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n res.status(status).json(response)\n}","export const statusMap: Record<string, number> = {\n Ok: 200,\n Created: 201,\n NoContent: 204,\n BadRequest: 400,\n Unauthorized: 401,\n Forbidden: 403,\n NotFound: 404,\n Conflict: 409,\n InternalError: 500,\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAoC;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AACnB;;;ADNO,SAAS,aAAa,KAAiB,UAAsC;AAChF,MAAI,SAAS;AACb,MAAI,SAAS,SAAS;AAClB,aAAS;AAAA,EACb,OAAO;AACH,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,EAAE,KAAK,QAAQ;AACpC;","names":[]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ sendResponse
3
+ } from "../chunk-5HL56LEG.mjs";
4
+ import "../chunk-VJJRPHMZ.mjs";
5
+ export {
6
+ sendResponse
7
+ };
8
+ //# sourceMappingURL=express.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,6 @@
1
+ import { FastifyReply } from 'fastify';
2
+ import { b as ApiResponse } from '../response-DV8HnqXP.mjs';
3
+
4
+ declare function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void;
5
+
6
+ export { sendResponse };
@@ -0,0 +1,6 @@
1
+ import { FastifyReply } from 'fastify';
2
+ import { b as ApiResponse } from '../response-DV8HnqXP.js';
3
+
4
+ declare function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void;
5
+
6
+ export { sendResponse };
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/adapters/fastify.ts
21
+ var fastify_exports = {};
22
+ __export(fastify_exports, {
23
+ sendResponse: () => sendResponse
24
+ });
25
+ module.exports = __toCommonJS(fastify_exports);
26
+
27
+ // src/core/status-map.ts
28
+ var statusMap = {
29
+ Ok: 200,
30
+ Created: 201,
31
+ NoContent: 204,
32
+ BadRequest: 400,
33
+ Unauthorized: 401,
34
+ Forbidden: 403,
35
+ NotFound: 404,
36
+ Conflict: 409,
37
+ InternalError: 500
38
+ };
39
+
40
+ // src/adapters/fastify.ts
41
+ function sendResponse(reply, response) {
42
+ let status = 200;
43
+ if (!response.success) {
44
+ const errorCode = response.error.code;
45
+ status = statusMap[errorCode] || 500;
46
+ }
47
+ reply.status(status).send(response);
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ sendResponse
52
+ });
53
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/fastify.ts","../../src/core/status-map.ts"],"sourcesContent":["import {FastifyReply} from \"fastify\"\nimport { ApiResponse } from \"../core/response\"\nimport { statusMap } from \"../core/status-map\"\n\nexport function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void {\n let status = 200\n\n if (!response.success) {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n\n reply.status(status).send(response)\n}\n","export const statusMap: Record<string, number> = {\n Ok: 200,\n Created: 201,\n NoContent: 204,\n BadRequest: 400,\n Unauthorized: 401,\n Forbidden: 403,\n NotFound: 404,\n Conflict: 409,\n InternalError: 500,\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAoC;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AACnB;;;ADNO,SAAS,aAAa,OAAqB,UAAsC;AACpF,MAAI,SAAS;AAEb,MAAI,CAAC,SAAS,SAAS;AACnB,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AAEA,QAAM,OAAO,MAAM,EAAE,KAAK,QAAQ;AACtC;","names":[]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ sendResponse
3
+ } from "../chunk-OD5AKNUG.mjs";
4
+ import "../chunk-VJJRPHMZ.mjs";
5
+ export {
6
+ sendResponse
7
+ };
8
+ //# sourceMappingURL=fastify.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,20 @@
1
+ import {
2
+ statusMap
3
+ } from "./chunk-VJJRPHMZ.mjs";
4
+
5
+ // src/adapters/express.ts
6
+ function sendResponse(res, response) {
7
+ let status = 200;
8
+ if (response.success) {
9
+ status = 200;
10
+ } else {
11
+ const errorCode = response.error.code;
12
+ status = statusMap[errorCode] || 500;
13
+ }
14
+ res.status(status).json(response);
15
+ }
16
+
17
+ export {
18
+ sendResponse
19
+ };
20
+ //# sourceMappingURL=chunk-5HL56LEG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/express.ts"],"sourcesContent":["import {Response as ExResponse} from \"express\"\nimport {ApiResponse} from \"../core/response\";\nimport {statusMap} from \"../core/status-map\";\n\nexport function sendResponse(res: ExResponse, response: ApiResponse<unknown>): void {\n let status = 200\n if (response.success) {\n status = 200\n } else {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n res.status(status).json(response)\n}"],"mappings":";;;;;AAIO,SAAS,aAAa,KAAiB,UAAsC;AAChF,MAAI,SAAS;AACb,MAAI,SAAS,SAAS;AAClB,aAAS;AAAA,EACb,OAAO;AACH,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,EAAE,KAAK,QAAQ;AACpC;","names":[]}
@@ -0,0 +1,18 @@
1
+ import {
2
+ statusMap
3
+ } from "./chunk-VJJRPHMZ.mjs";
4
+
5
+ // src/adapters/fastify.ts
6
+ function sendResponse(reply, response) {
7
+ let status = 200;
8
+ if (!response.success) {
9
+ const errorCode = response.error.code;
10
+ status = statusMap[errorCode] || 500;
11
+ }
12
+ reply.status(status).send(response);
13
+ }
14
+
15
+ export {
16
+ sendResponse
17
+ };
18
+ //# sourceMappingURL=chunk-OD5AKNUG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/fastify.ts"],"sourcesContent":["import {FastifyReply} from \"fastify\"\nimport { ApiResponse } from \"../core/response\"\nimport { statusMap } from \"../core/status-map\"\n\nexport function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void {\n let status = 200\n\n if (!response.success) {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n\n reply.status(status).send(response)\n}\n"],"mappings":";;;;;AAIO,SAAS,aAAa,OAAqB,UAAsC;AACpF,MAAI,SAAS;AAEb,MAAI,CAAC,SAAS,SAAS;AACnB,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AAEA,QAAM,OAAO,MAAM,EAAE,KAAK,QAAQ;AACtC;","names":[]}
@@ -0,0 +1,17 @@
1
+ // src/core/status-map.ts
2
+ var statusMap = {
3
+ Ok: 200,
4
+ Created: 201,
5
+ NoContent: 204,
6
+ BadRequest: 400,
7
+ Unauthorized: 401,
8
+ Forbidden: 403,
9
+ NotFound: 404,
10
+ Conflict: 409,
11
+ InternalError: 500
12
+ };
13
+
14
+ export {
15
+ statusMap
16
+ };
17
+ //# sourceMappingURL=chunk-VJJRPHMZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/status-map.ts"],"sourcesContent":["export const statusMap: Record<string, number> = {\n Ok: 200,\n Created: 201,\n NoContent: 204,\n BadRequest: 400,\n Unauthorized: 401,\n Forbidden: 403,\n NotFound: 404,\n Conflict: 409,\n InternalError: 500,\n}"],"mappings":";AAAO,IAAM,YAAoC;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AACnB;","names":[]}
@@ -0,0 +1,26 @@
1
+ import { A as ApiSuccess, a as ApiError } from './response-DV8HnqXP.mjs';
2
+ export { b as ApiResponse } from './response-DV8HnqXP.mjs';
3
+ export { sendResponse as ExpressResponse } from './adapters/express.mjs';
4
+ export { sendResponse as FastifyResponse } from './adapters/fastify.mjs';
5
+ import 'express';
6
+ import 'fastify';
7
+
8
+ declare function Ok<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
9
+ declare function Created<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
10
+ declare function NoContent(message?: string): ApiSuccess<null>;
11
+ declare function CustomSuccess<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
12
+
13
+ declare function BadRequest(message: string, details?: unknown): ApiError;
14
+ declare function Unauthorized(message?: string): ApiError;
15
+ declare function Forbidden(message?: string): ApiError;
16
+ declare function NotFound(resource?: string): ApiError;
17
+ declare function Conflict(message: string): ApiError;
18
+ declare function InternalError(message?: string, details?: unknown): ApiError;
19
+ interface CustomErrorParams {
20
+ code: string;
21
+ message: string;
22
+ details?: unknown;
23
+ }
24
+ declare function CustomError({ code, message, details }: CustomErrorParams): ApiError;
25
+
26
+ export { ApiError, ApiSuccess, BadRequest, Conflict, Created, CustomError, CustomSuccess, Forbidden, InternalError, NoContent, NotFound, Ok, Unauthorized };
@@ -0,0 +1,26 @@
1
+ import { A as ApiSuccess, a as ApiError } from './response-DV8HnqXP.js';
2
+ export { b as ApiResponse } from './response-DV8HnqXP.js';
3
+ export { sendResponse as ExpressResponse } from './adapters/express.js';
4
+ export { sendResponse as FastifyResponse } from './adapters/fastify.js';
5
+ import 'express';
6
+ import 'fastify';
7
+
8
+ declare function Ok<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
9
+ declare function Created<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
10
+ declare function NoContent(message?: string): ApiSuccess<null>;
11
+ declare function CustomSuccess<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>;
12
+
13
+ declare function BadRequest(message: string, details?: unknown): ApiError;
14
+ declare function Unauthorized(message?: string): ApiError;
15
+ declare function Forbidden(message?: string): ApiError;
16
+ declare function NotFound(resource?: string): ApiError;
17
+ declare function Conflict(message: string): ApiError;
18
+ declare function InternalError(message?: string, details?: unknown): ApiError;
19
+ interface CustomErrorParams {
20
+ code: string;
21
+ message: string;
22
+ details?: unknown;
23
+ }
24
+ declare function CustomError({ code, message, details }: CustomErrorParams): ApiError;
25
+
26
+ export { ApiError, ApiSuccess, BadRequest, Conflict, Created, CustomError, CustomSuccess, Forbidden, InternalError, NoContent, NotFound, Ok, Unauthorized };
package/dist/index.js ADDED
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BadRequest: () => BadRequest,
24
+ Conflict: () => Conflict,
25
+ Created: () => Created,
26
+ CustomError: () => CustomError,
27
+ CustomSuccess: () => CustomSuccess,
28
+ ExpressResponse: () => sendResponse,
29
+ FastifyResponse: () => sendResponse2,
30
+ Forbidden: () => Forbidden,
31
+ InternalError: () => InternalError,
32
+ NoContent: () => NoContent,
33
+ NotFound: () => NotFound,
34
+ Ok: () => Ok,
35
+ Unauthorized: () => Unauthorized
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/core/success.ts
40
+ function Ok(data, message, meta) {
41
+ return { success: true, data, message, meta };
42
+ }
43
+ function Created(data, message, meta) {
44
+ return { success: true, data, message, meta };
45
+ }
46
+ function NoContent(message) {
47
+ return { success: true, data: null, message };
48
+ }
49
+ function CustomSuccess(data, message, meta) {
50
+ return { success: true, data, message, meta };
51
+ }
52
+
53
+ // src/core/error.ts
54
+ function BadRequest(message, details) {
55
+ return { success: false, error: { code: "BAD_REQUEST", message, details } };
56
+ }
57
+ function Unauthorized(message = "Unauthorized") {
58
+ return { success: false, error: { code: "UNAUTHORIZED", message } };
59
+ }
60
+ function Forbidden(message = "Forbidden") {
61
+ return { success: false, error: { code: "FORBIDDEN", message } };
62
+ }
63
+ function NotFound(resource = "Resource") {
64
+ return { success: false, error: { code: "NOT_FOUND", message: `${resource} not found` } };
65
+ }
66
+ function Conflict(message) {
67
+ return { success: false, error: { code: "CONFLICT", message } };
68
+ }
69
+ function InternalError(message = "Internal server error", details) {
70
+ return { success: false, error: { code: "INTERNAL_ERROR", message, details } };
71
+ }
72
+ function CustomError({ code, message, details }) {
73
+ return {
74
+ success: false,
75
+ error: {
76
+ code,
77
+ message,
78
+ details
79
+ }
80
+ };
81
+ }
82
+
83
+ // src/core/status-map.ts
84
+ var statusMap = {
85
+ Ok: 200,
86
+ Created: 201,
87
+ NoContent: 204,
88
+ BadRequest: 400,
89
+ Unauthorized: 401,
90
+ Forbidden: 403,
91
+ NotFound: 404,
92
+ Conflict: 409,
93
+ InternalError: 500
94
+ };
95
+
96
+ // src/adapters/express.ts
97
+ function sendResponse(res, response) {
98
+ let status = 200;
99
+ if (response.success) {
100
+ status = 200;
101
+ } else {
102
+ const errorCode = response.error.code;
103
+ status = statusMap[errorCode] || 500;
104
+ }
105
+ res.status(status).json(response);
106
+ }
107
+
108
+ // src/adapters/fastify.ts
109
+ function sendResponse2(reply, response) {
110
+ let status = 200;
111
+ if (!response.success) {
112
+ const errorCode = response.error.code;
113
+ status = statusMap[errorCode] || 500;
114
+ }
115
+ reply.status(status).send(response);
116
+ }
117
+ // Annotate the CommonJS export names for ESM import in node:
118
+ 0 && (module.exports = {
119
+ BadRequest,
120
+ Conflict,
121
+ Created,
122
+ CustomError,
123
+ CustomSuccess,
124
+ ExpressResponse,
125
+ FastifyResponse,
126
+ Forbidden,
127
+ InternalError,
128
+ NoContent,
129
+ NotFound,
130
+ Ok,
131
+ Unauthorized
132
+ });
133
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/success.ts","../src/core/error.ts","../src/core/status-map.ts","../src/adapters/express.ts","../src/adapters/fastify.ts"],"sourcesContent":["export type { ApiSuccess, ApiError, ApiResponse } from \"./core/response\"\n\nexport { Ok, Created, NoContent, CustomSuccess } from \"./core/success\"\n\nexport { BadRequest, Unauthorized, Forbidden, NotFound, Conflict, InternalError, CustomError } from \"./core/error\"\n\nexport {sendResponse as ExpressResponse} from \"./adapters/express\"\nexport {sendResponse as FastifyResponse} from \"./adapters/fastify\"","import {ApiSuccess} from \"./response\";\n\nexport function Ok<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>{\n return {success:true, data, message, meta}\n}\n\nexport function Created<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T> {\n return { success: true, data, message, meta }\n}\n\nexport function NoContent(message?: string): ApiSuccess<null> {\n return { success: true, data: null, message }\n}\n\nexport function CustomSuccess<T>(\n data: T,\n message?: string,\n meta?: Record<string, unknown>\n): ApiSuccess<T> {\n return { success: true, data, message, meta }\n}","import { ApiError } from \"./response\"\n\nexport function BadRequest(message: string, details?: unknown): ApiError {\n return { success: false, error: { code: \"BAD_REQUEST\", message, details } }\n}\n\nexport function Unauthorized(message = \"Unauthorized\"): ApiError {\n return { success: false, error: { code: \"UNAUTHORIZED\", message } }\n}\n\nexport function Forbidden(message = \"Forbidden\"): ApiError {\n return { success: false, error: { code: \"FORBIDDEN\", message } }\n}\n\nexport function NotFound(resource = \"Resource\"): ApiError {\n return { success: false, error: { code: \"NOT_FOUND\", message: `${resource} not found` } }\n}\n\nexport function Conflict(message: string): ApiError {\n return { success: false, error: { code: \"CONFLICT\", message } }\n}\n\nexport function InternalError(message = \"Internal server error\", details?: unknown): ApiError {\n return { success: false, error: { code: \"INTERNAL_ERROR\", message, details } }\n}\n\ninterface CustomErrorParams {\n code: string\n message: string\n details?: unknown\n}\nexport function CustomError({ code, message, details }: CustomErrorParams): ApiError {\n return {\n success: false,\n error: {\n code,\n message,\n details,\n },\n }\n}\n","export const statusMap: Record<string, number> = {\n Ok: 200,\n Created: 201,\n NoContent: 204,\n BadRequest: 400,\n Unauthorized: 401,\n Forbidden: 403,\n NotFound: 404,\n Conflict: 409,\n InternalError: 500,\n}","import {Response as ExResponse} from \"express\"\nimport {ApiResponse} from \"../core/response\";\nimport {statusMap} from \"../core/status-map\";\n\nexport function sendResponse(res: ExResponse, response: ApiResponse<unknown>): void {\n let status = 200\n if (response.success) {\n status = 200\n } else {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n res.status(status).json(response)\n}","import {FastifyReply} from \"fastify\"\nimport { ApiResponse } from \"../core/response\"\nimport { statusMap } from \"../core/status-map\"\n\nexport function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void {\n let status = 200\n\n if (!response.success) {\n const errorCode = response.error.code\n status = statusMap[errorCode] || 500\n }\n\n reply.status(status).send(response)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,SAAS,GAAM,MAAS,SAAkB,MAA8C;AAC3F,SAAO,EAAC,SAAQ,MAAM,MAAM,SAAS,KAAI;AAC7C;AAEO,SAAS,QAAW,MAAS,SAAkB,MAA+C;AACjG,SAAO,EAAE,SAAS,MAAM,MAAM,SAAS,KAAK;AAChD;AAEO,SAAS,UAAU,SAAoC;AAC1D,SAAO,EAAE,SAAS,MAAM,MAAM,MAAM,QAAQ;AAChD;AAEO,SAAS,cACZ,MACA,SACA,MACa;AACb,SAAO,EAAE,SAAS,MAAM,MAAM,SAAS,KAAK;AAChD;;;AClBO,SAAS,WAAW,SAAiB,SAA6B;AACrE,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,eAAe,SAAS,QAAQ,EAAE;AAC9E;AAEO,SAAS,aAAa,UAAU,gBAA0B;AAC7D,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,gBAAgB,QAAQ,EAAE;AACtE;AAEO,SAAS,UAAU,UAAU,aAAuB;AACvD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,aAAa,QAAQ,EAAE;AACnE;AAEO,SAAS,SAAS,WAAW,YAAsB;AACtD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,aAAa,SAAS,GAAG,QAAQ,aAAa,EAAE;AAC5F;AAEO,SAAS,SAAS,SAA2B;AAChD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,YAAY,QAAQ,EAAE;AAClE;AAEO,SAAS,cAAc,UAAU,yBAAyB,SAA6B;AAC1F,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,kBAAkB,SAAS,QAAQ,EAAE;AACjF;AAOO,SAAS,YAAY,EAAE,MAAM,SAAS,QAAQ,GAAgC;AACjF,SAAO;AAAA,IACH,SAAS;AAAA,IACT,OAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AACJ;;;ACxCO,IAAM,YAAoC;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AACnB;;;ACNO,SAAS,aAAa,KAAiB,UAAsC;AAChF,MAAI,SAAS;AACb,MAAI,SAAS,SAAS;AAClB,aAAS;AAAA,EACb,OAAO;AACH,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,EAAE,KAAK,QAAQ;AACpC;;;ACTO,SAASC,cAAa,OAAqB,UAAsC;AACpF,MAAI,SAAS;AAEb,MAAI,CAAC,SAAS,SAAS;AACnB,UAAM,YAAY,SAAS,MAAM;AACjC,aAAS,UAAU,SAAS,KAAK;AAAA,EACrC;AAEA,QAAM,OAAO,MAAM,EAAE,KAAK,QAAQ;AACtC;","names":["sendResponse","sendResponse"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,67 @@
1
+ import {
2
+ sendResponse
3
+ } from "./chunk-5HL56LEG.mjs";
4
+ import {
5
+ sendResponse as sendResponse2
6
+ } from "./chunk-OD5AKNUG.mjs";
7
+ import "./chunk-VJJRPHMZ.mjs";
8
+
9
+ // src/core/success.ts
10
+ function Ok(data, message, meta) {
11
+ return { success: true, data, message, meta };
12
+ }
13
+ function Created(data, message, meta) {
14
+ return { success: true, data, message, meta };
15
+ }
16
+ function NoContent(message) {
17
+ return { success: true, data: null, message };
18
+ }
19
+ function CustomSuccess(data, message, meta) {
20
+ return { success: true, data, message, meta };
21
+ }
22
+
23
+ // src/core/error.ts
24
+ function BadRequest(message, details) {
25
+ return { success: false, error: { code: "BAD_REQUEST", message, details } };
26
+ }
27
+ function Unauthorized(message = "Unauthorized") {
28
+ return { success: false, error: { code: "UNAUTHORIZED", message } };
29
+ }
30
+ function Forbidden(message = "Forbidden") {
31
+ return { success: false, error: { code: "FORBIDDEN", message } };
32
+ }
33
+ function NotFound(resource = "Resource") {
34
+ return { success: false, error: { code: "NOT_FOUND", message: `${resource} not found` } };
35
+ }
36
+ function Conflict(message) {
37
+ return { success: false, error: { code: "CONFLICT", message } };
38
+ }
39
+ function InternalError(message = "Internal server error", details) {
40
+ return { success: false, error: { code: "INTERNAL_ERROR", message, details } };
41
+ }
42
+ function CustomError({ code, message, details }) {
43
+ return {
44
+ success: false,
45
+ error: {
46
+ code,
47
+ message,
48
+ details
49
+ }
50
+ };
51
+ }
52
+ export {
53
+ BadRequest,
54
+ Conflict,
55
+ Created,
56
+ CustomError,
57
+ CustomSuccess,
58
+ sendResponse as ExpressResponse,
59
+ sendResponse2 as FastifyResponse,
60
+ Forbidden,
61
+ InternalError,
62
+ NoContent,
63
+ NotFound,
64
+ Ok,
65
+ Unauthorized
66
+ };
67
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/success.ts","../src/core/error.ts"],"sourcesContent":["import {ApiSuccess} from \"./response\";\n\nexport function Ok<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>{\n return {success:true, data, message, meta}\n}\n\nexport function Created<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T> {\n return { success: true, data, message, meta }\n}\n\nexport function NoContent(message?: string): ApiSuccess<null> {\n return { success: true, data: null, message }\n}\n\nexport function CustomSuccess<T>(\n data: T,\n message?: string,\n meta?: Record<string, unknown>\n): ApiSuccess<T> {\n return { success: true, data, message, meta }\n}","import { ApiError } from \"./response\"\n\nexport function BadRequest(message: string, details?: unknown): ApiError {\n return { success: false, error: { code: \"BAD_REQUEST\", message, details } }\n}\n\nexport function Unauthorized(message = \"Unauthorized\"): ApiError {\n return { success: false, error: { code: \"UNAUTHORIZED\", message } }\n}\n\nexport function Forbidden(message = \"Forbidden\"): ApiError {\n return { success: false, error: { code: \"FORBIDDEN\", message } }\n}\n\nexport function NotFound(resource = \"Resource\"): ApiError {\n return { success: false, error: { code: \"NOT_FOUND\", message: `${resource} not found` } }\n}\n\nexport function Conflict(message: string): ApiError {\n return { success: false, error: { code: \"CONFLICT\", message } }\n}\n\nexport function InternalError(message = \"Internal server error\", details?: unknown): ApiError {\n return { success: false, error: { code: \"INTERNAL_ERROR\", message, details } }\n}\n\ninterface CustomErrorParams {\n code: string\n message: string\n details?: unknown\n}\nexport function CustomError({ code, message, details }: CustomErrorParams): ApiError {\n return {\n success: false,\n error: {\n code,\n message,\n details,\n },\n }\n}\n"],"mappings":";;;;;;;;;AAEO,SAAS,GAAM,MAAS,SAAkB,MAA8C;AAC3F,SAAO,EAAC,SAAQ,MAAM,MAAM,SAAS,KAAI;AAC7C;AAEO,SAAS,QAAW,MAAS,SAAkB,MAA+C;AACjG,SAAO,EAAE,SAAS,MAAM,MAAM,SAAS,KAAK;AAChD;AAEO,SAAS,UAAU,SAAoC;AAC1D,SAAO,EAAE,SAAS,MAAM,MAAM,MAAM,QAAQ;AAChD;AAEO,SAAS,cACZ,MACA,SACA,MACa;AACb,SAAO,EAAE,SAAS,MAAM,MAAM,SAAS,KAAK;AAChD;;;AClBO,SAAS,WAAW,SAAiB,SAA6B;AACrE,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,eAAe,SAAS,QAAQ,EAAE;AAC9E;AAEO,SAAS,aAAa,UAAU,gBAA0B;AAC7D,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,gBAAgB,QAAQ,EAAE;AACtE;AAEO,SAAS,UAAU,UAAU,aAAuB;AACvD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,aAAa,QAAQ,EAAE;AACnE;AAEO,SAAS,SAAS,WAAW,YAAsB;AACtD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,aAAa,SAAS,GAAG,QAAQ,aAAa,EAAE;AAC5F;AAEO,SAAS,SAAS,SAA2B;AAChD,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,YAAY,QAAQ,EAAE;AAClE;AAEO,SAAS,cAAc,UAAU,yBAAyB,SAA6B;AAC1F,SAAO,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,kBAAkB,SAAS,QAAQ,EAAE;AACjF;AAOO,SAAS,YAAY,EAAE,MAAM,SAAS,QAAQ,GAAgC;AACjF,SAAO;AAAA,IACH,SAAS;AAAA,IACT,OAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AACJ;","names":[]}
@@ -0,0 +1,17 @@
1
+ type ApiSuccess<T> = {
2
+ success: true;
3
+ data: T;
4
+ message?: string;
5
+ meta?: Record<string, unknown>;
6
+ };
7
+ type ApiError = {
8
+ success: false;
9
+ error: {
10
+ code: string;
11
+ message: string;
12
+ details?: unknown;
13
+ };
14
+ };
15
+ type ApiResponse<T> = ApiSuccess<T> | ApiError;
16
+
17
+ export type { ApiSuccess as A, ApiError as a, ApiResponse as b };
@@ -0,0 +1,17 @@
1
+ type ApiSuccess<T> = {
2
+ success: true;
3
+ data: T;
4
+ message?: string;
5
+ meta?: Record<string, unknown>;
6
+ };
7
+ type ApiError = {
8
+ success: false;
9
+ error: {
10
+ code: string;
11
+ message: string;
12
+ details?: unknown;
13
+ };
14
+ };
15
+ type ApiResponse<T> = ApiSuccess<T> | ApiError;
16
+
17
+ export type { ApiSuccess as A, ApiError as a, ApiResponse as b };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@0layimika/api-response-kit",
3
+ "version": "0.1.0",
4
+ "description": "A typed toolkit for consistent API success and error responses",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "type": "commonjs",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./express": {
15
+ "import": "./dist/adapters/express.js",
16
+ "require": "./dist/adapters/express.cjs"
17
+ },
18
+ "./fastify": {
19
+ "import": "./dist/adapters/fastify.js",
20
+ "require": "./dist/adapters/fastify.cjs"
21
+ }
22
+ },
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "typecheck": "tsc --noEmit"
27
+ },
28
+ "dependencies": {
29
+ "express": "^5.2.1",
30
+ "fastify": "^5.6.2",
31
+ "tsup": "^8.5.1"
32
+ },
33
+ "devDependencies": {
34
+ "@types/express": "^5.0.6",
35
+ "@types/node": "^25.0.3",
36
+ "ts-node": "^10.9.2",
37
+ "typescript": "^5.9.3"
38
+ },
39
+ "private": false
40
+ }
@@ -0,0 +1,14 @@
1
+ import {Response as ExResponse} from "express"
2
+ import {ApiResponse} from "../core/response";
3
+ import {statusMap} from "../core/status-map";
4
+
5
+ export function sendResponse(res: ExResponse, response: ApiResponse<unknown>): void {
6
+ let status = 200
7
+ if (response.success) {
8
+ status = 200
9
+ } else {
10
+ const errorCode = response.error.code
11
+ status = statusMap[errorCode] || 500
12
+ }
13
+ res.status(status).json(response)
14
+ }
@@ -0,0 +1,14 @@
1
+ import {FastifyReply} from "fastify"
2
+ import { ApiResponse } from "../core/response"
3
+ import { statusMap } from "../core/status-map"
4
+
5
+ export function sendResponse(reply: FastifyReply, response: ApiResponse<unknown>): void {
6
+ let status = 200
7
+
8
+ if (!response.success) {
9
+ const errorCode = response.error.code
10
+ status = statusMap[errorCode] || 500
11
+ }
12
+
13
+ reply.status(status).send(response)
14
+ }
@@ -0,0 +1,41 @@
1
+ import { ApiError } from "./response"
2
+
3
+ export function BadRequest(message: string, details?: unknown): ApiError {
4
+ return { success: false, error: { code: "BAD_REQUEST", message, details } }
5
+ }
6
+
7
+ export function Unauthorized(message = "Unauthorized"): ApiError {
8
+ return { success: false, error: { code: "UNAUTHORIZED", message } }
9
+ }
10
+
11
+ export function Forbidden(message = "Forbidden"): ApiError {
12
+ return { success: false, error: { code: "FORBIDDEN", message } }
13
+ }
14
+
15
+ export function NotFound(resource = "Resource"): ApiError {
16
+ return { success: false, error: { code: "NOT_FOUND", message: `${resource} not found` } }
17
+ }
18
+
19
+ export function Conflict(message: string): ApiError {
20
+ return { success: false, error: { code: "CONFLICT", message } }
21
+ }
22
+
23
+ export function InternalError(message = "Internal server error", details?: unknown): ApiError {
24
+ return { success: false, error: { code: "INTERNAL_ERROR", message, details } }
25
+ }
26
+
27
+ interface CustomErrorParams {
28
+ code: string
29
+ message: string
30
+ details?: unknown
31
+ }
32
+ export function CustomError({ code, message, details }: CustomErrorParams): ApiError {
33
+ return {
34
+ success: false,
35
+ error: {
36
+ code,
37
+ message,
38
+ details,
39
+ },
40
+ }
41
+ }
@@ -0,0 +1,17 @@
1
+ export type ApiSuccess<T> = {
2
+ success:true,
3
+ data:T,
4
+ message?:string,
5
+ meta?: Record<string, unknown>
6
+ }
7
+
8
+ export type ApiError = {
9
+ success:false,
10
+ error:{
11
+ code:string,
12
+ message:string,
13
+ details?:unknown
14
+ }
15
+ }
16
+
17
+ export type ApiResponse<T> = ApiSuccess<T> | ApiError
@@ -0,0 +1,11 @@
1
+ export const statusMap: Record<string, number> = {
2
+ Ok: 200,
3
+ Created: 201,
4
+ NoContent: 204,
5
+ BadRequest: 400,
6
+ Unauthorized: 401,
7
+ Forbidden: 403,
8
+ NotFound: 404,
9
+ Conflict: 409,
10
+ InternalError: 500,
11
+ }
@@ -0,0 +1,21 @@
1
+ import {ApiSuccess} from "./response";
2
+
3
+ export function Ok<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T>{
4
+ return {success:true, data, message, meta}
5
+ }
6
+
7
+ export function Created<T>(data: T, message?: string, meta?: Record<string, unknown>): ApiSuccess<T> {
8
+ return { success: true, data, message, meta }
9
+ }
10
+
11
+ export function NoContent(message?: string): ApiSuccess<null> {
12
+ return { success: true, data: null, message }
13
+ }
14
+
15
+ export function CustomSuccess<T>(
16
+ data: T,
17
+ message?: string,
18
+ meta?: Record<string, unknown>
19
+ ): ApiSuccess<T> {
20
+ return { success: true, data, message, meta }
21
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export type { ApiSuccess, ApiError, ApiResponse } from "./core/response"
2
+
3
+ export { Ok, Created, NoContent, CustomSuccess } from "./core/success"
4
+
5
+ export { BadRequest, Unauthorized, Forbidden, NotFound, Conflict, InternalError, CustomError } from "./core/error"
6
+
7
+ export {sendResponse as ExpressResponse} from "./adapters/express"
8
+ export {sendResponse as FastifyResponse} from "./adapters/fastify"
File without changes
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "outDir": "dist",
9
+ "rootDir": "src",
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": ["src"]
14
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,12 @@
1
+ import {defineConfig} from "tsup";
2
+ export default defineConfig({
3
+ entry: [
4
+ "src/index.ts",
5
+ "src/adapters/express.ts",
6
+ "src/adapters/fastify.ts",
7
+ ],
8
+ format: ["cjs", "esm"],
9
+ dts: true,
10
+ clean: true,
11
+ sourcemap: true,
12
+ })