@m1kapp/kit 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.
@@ -0,0 +1,71 @@
1
+ declare class HttpError extends Error {
2
+ readonly status: number;
3
+ readonly body: unknown;
4
+ constructor(status: number, body: unknown);
5
+ }
6
+ /** 200 OK with JSON body */
7
+ declare function ok<T>(data: T, status?: number): Response;
8
+ /** 201 Created with JSON body */
9
+ declare function created<T>(data: T): Response;
10
+ /** 204 No Content */
11
+ declare function noContent(): Response;
12
+ /** 400 Bad Request — throw inside handler() */
13
+ declare function badRequest(message?: string, errors?: unknown): never;
14
+ /** 401 Unauthorized — throw inside handler() */
15
+ declare function unauthorized(message?: string): never;
16
+ /** 403 Forbidden — throw inside handler() */
17
+ declare function forbidden(message?: string): never;
18
+ /** 404 Not Found — throw inside handler() */
19
+ declare function notFound(message?: string): never;
20
+ /** 409 Conflict — throw inside handler() */
21
+ declare function conflict(message?: string): never;
22
+ /** 500 Internal Server Error — throw inside handler() */
23
+ declare function serverError(message?: string): never;
24
+
25
+ type NextRequest = Request;
26
+ type RouteContext = {
27
+ params?: Record<string, string | string[]>;
28
+ };
29
+ /**
30
+ * Wraps a Next.js route handler with automatic error handling.
31
+ *
32
+ * - HttpError (thrown by unauthorized/notFound/etc.) → proper HTTP response
33
+ * - Any other thrown error → 500
34
+ * - No try/catch needed in your route
35
+ *
36
+ * @example
37
+ * export const GET = handler(async (req) => {
38
+ * const user = await currentUser();
39
+ * if (!user) unauthorized(); // throws → 401
40
+ *
41
+ * const site = await db.sites.find(id);
42
+ * if (!site) notFound("사이트 없음"); // throws → 404
43
+ *
44
+ * return ok(site);
45
+ * });
46
+ */
47
+ declare function handler(fn: (req: NextRequest, ctx?: RouteContext) => Promise<Response>): (req: NextRequest, ctx?: RouteContext) => Promise<Response>;
48
+
49
+ type SafeOk<T> = {
50
+ ok: true;
51
+ data: T;
52
+ error: null;
53
+ };
54
+ type SafeErr = {
55
+ ok: false;
56
+ data: null;
57
+ error: Error;
58
+ };
59
+ type SafeResult<T> = SafeOk<T> | SafeErr;
60
+ /**
61
+ * Runs an async function and returns a result object instead of throwing.
62
+ * Useful when you want to handle a specific error differently without a try/catch.
63
+ *
64
+ * @example
65
+ * const { ok: success, data, error } = await safely(() => db.users.find(id));
66
+ * if (!success) return serverError("DB 조회 실패");
67
+ * return ok(data);
68
+ */
69
+ declare function safely<T>(fn: () => Promise<T>): Promise<SafeResult<T>>;
70
+
71
+ export { HttpError, badRequest, conflict, created, forbidden, handler, noContent, notFound, ok, safely, serverError, unauthorized };
@@ -0,0 +1,71 @@
1
+ declare class HttpError extends Error {
2
+ readonly status: number;
3
+ readonly body: unknown;
4
+ constructor(status: number, body: unknown);
5
+ }
6
+ /** 200 OK with JSON body */
7
+ declare function ok<T>(data: T, status?: number): Response;
8
+ /** 201 Created with JSON body */
9
+ declare function created<T>(data: T): Response;
10
+ /** 204 No Content */
11
+ declare function noContent(): Response;
12
+ /** 400 Bad Request — throw inside handler() */
13
+ declare function badRequest(message?: string, errors?: unknown): never;
14
+ /** 401 Unauthorized — throw inside handler() */
15
+ declare function unauthorized(message?: string): never;
16
+ /** 403 Forbidden — throw inside handler() */
17
+ declare function forbidden(message?: string): never;
18
+ /** 404 Not Found — throw inside handler() */
19
+ declare function notFound(message?: string): never;
20
+ /** 409 Conflict — throw inside handler() */
21
+ declare function conflict(message?: string): never;
22
+ /** 500 Internal Server Error — throw inside handler() */
23
+ declare function serverError(message?: string): never;
24
+
25
+ type NextRequest = Request;
26
+ type RouteContext = {
27
+ params?: Record<string, string | string[]>;
28
+ };
29
+ /**
30
+ * Wraps a Next.js route handler with automatic error handling.
31
+ *
32
+ * - HttpError (thrown by unauthorized/notFound/etc.) → proper HTTP response
33
+ * - Any other thrown error → 500
34
+ * - No try/catch needed in your route
35
+ *
36
+ * @example
37
+ * export const GET = handler(async (req) => {
38
+ * const user = await currentUser();
39
+ * if (!user) unauthorized(); // throws → 401
40
+ *
41
+ * const site = await db.sites.find(id);
42
+ * if (!site) notFound("사이트 없음"); // throws → 404
43
+ *
44
+ * return ok(site);
45
+ * });
46
+ */
47
+ declare function handler(fn: (req: NextRequest, ctx?: RouteContext) => Promise<Response>): (req: NextRequest, ctx?: RouteContext) => Promise<Response>;
48
+
49
+ type SafeOk<T> = {
50
+ ok: true;
51
+ data: T;
52
+ error: null;
53
+ };
54
+ type SafeErr = {
55
+ ok: false;
56
+ data: null;
57
+ error: Error;
58
+ };
59
+ type SafeResult<T> = SafeOk<T> | SafeErr;
60
+ /**
61
+ * Runs an async function and returns a result object instead of throwing.
62
+ * Useful when you want to handle a specific error differently without a try/catch.
63
+ *
64
+ * @example
65
+ * const { ok: success, data, error } = await safely(() => db.users.find(id));
66
+ * if (!success) return serverError("DB 조회 실패");
67
+ * return ok(data);
68
+ */
69
+ declare function safely<T>(fn: () => Promise<T>): Promise<SafeResult<T>>;
70
+
71
+ export { HttpError, badRequest, conflict, created, forbidden, handler, noContent, notFound, ok, safely, serverError, unauthorized };
package/dist/server.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var u=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var E=(e,r)=>{for(var o in r)u(e,o,{get:r[o],enumerable:!0})},b=(e,r,o,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of T(r))!m.call(e,s)&&s!==o&&u(e,s,{get:()=>r[s],enumerable:!(n=y(r,s))||n.enumerable});return e};var k=e=>b(u({},"__esModule",{value:!0}),e);var v={};E(v,{HttpError:()=>t,badRequest:()=>c,conflict:()=>x,created:()=>i,forbidden:()=>f,handler:()=>w,noContent:()=>p,notFound:()=>l,ok:()=>a,safely:()=>h,serverError:()=>R,unauthorized:()=>d});module.exports=k(v);var t=class extends Error{constructor(o,n){super(`HTTP ${o}`);this.status=o;this.body=n;this.name="HttpError"}};function a(e,r=200){return Response.json(e,{status:r})}function i(e){return Response.json(e,{status:201})}function p(){return new Response(null,{status:204})}function c(e="Bad Request",r){throw new t(400,{error:e,...r?{errors:r}:{}})}function d(e="Unauthorized"){throw new t(401,{error:e})}function f(e="Forbidden"){throw new t(403,{error:e})}function l(e="Not Found"){throw new t(404,{error:e})}function x(e="Conflict"){throw new t(409,{error:e})}function R(e="Internal Server Error"){throw new t(500,{error:e})}function w(e){return async(r,o)=>{try{return await e(r,o)}catch(n){return n instanceof t?Response.json(n.body,{status:n.status}):(console.error("[handler] Unhandled error:",n),Response.json({error:"Internal Server Error"},{status:500}))}}}async function h(e){try{return{ok:!0,data:await e(),error:null}}catch(r){return{ok:!1,data:null,error:r instanceof Error?r:new Error(String(r))}}}0&&(module.exports={HttpError,badRequest,conflict,created,forbidden,handler,noContent,notFound,ok,safely,serverError,unauthorized});
@@ -0,0 +1 @@
1
+ var t=class extends Error{constructor(n,o){super(`HTTP ${n}`);this.status=n;this.body=o;this.name="HttpError"}};function s(e,r=200){return Response.json(e,{status:r})}function u(e){return Response.json(e,{status:201})}function a(){return new Response(null,{status:204})}function i(e="Bad Request",r){throw new t(400,{error:e,...r?{errors:r}:{}})}function p(e="Unauthorized"){throw new t(401,{error:e})}function c(e="Forbidden"){throw new t(403,{error:e})}function d(e="Not Found"){throw new t(404,{error:e})}function f(e="Conflict"){throw new t(409,{error:e})}function l(e="Internal Server Error"){throw new t(500,{error:e})}function x(e){return async(r,n)=>{try{return await e(r,n)}catch(o){return o instanceof t?Response.json(o.body,{status:o.status}):(console.error("[handler] Unhandled error:",o),Response.json({error:"Internal Server Error"},{status:500}))}}}async function R(e){try{return{ok:!0,data:await e(),error:null}}catch(r){return{ok:!1,data:null,error:r instanceof Error?r:new Error(String(r))}}}export{t as HttpError,i as badRequest,f as conflict,u as created,c as forbidden,x as handler,a as noContent,d as notFound,s as ok,R as safely,l as serverError,p as unauthorized};
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@m1kapp/kit",
3
+ "version": "0.0.1",
4
+ "description": "UI, SEO, and PWA utilities for side projects",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./server": {
15
+ "types": "./dist/server.d.ts",
16
+ "import": "./dist/server.mjs",
17
+ "require": "./dist/server.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "rm -rf dist && mkdir -p .tmp && npx @tailwindcss/cli -i src/ui/styles.css -o .tmp/styles.css --minify && node scripts/embed-css.mjs && tsup",
25
+ "dev": "tsup --watch",
26
+ "lint": "tsc --noEmit",
27
+ "demo": "npm run build && cd demo && npm run dev",
28
+ "demo:dev": "cd demo && npm run dev"
29
+ },
30
+ "peerDependencies": {
31
+ "@vercel/og": ">=0.6",
32
+ "react": ">=18",
33
+ "react-dom": ">=18"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "@vercel/og": {
37
+ "optional": true
38
+ }
39
+ },
40
+ "devDependencies": {
41
+ "@tailwindcss/cli": "^4.2.2",
42
+ "@types/react": "^19.0.0",
43
+ "@types/react-dom": "^19.0.0",
44
+ "next": "^16.2.4",
45
+ "react": "^19.0.0",
46
+ "react-dom": "^19.0.0",
47
+ "tailwindcss": "^4.0.0",
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.0.0"
50
+ },
51
+ "keywords": [
52
+ "react",
53
+ "ui",
54
+ "seo",
55
+ "pwa",
56
+ "mobile",
57
+ "side-project",
58
+ "m1k"
59
+ ],
60
+ "license": "MIT",
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/m1kapp/kit.git"
64
+ },
65
+ "homepage": "https://m1k.app"
66
+ }