@lastshotlabs/bunshot 0.0.3 → 0.0.4
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/dist/adapters/memoryAuth.d.ts +22 -0
- package/dist/adapters/mongoAuth.d.ts +2 -0
- package/dist/adapters/sqliteAuth.d.ts +23 -0
- package/dist/app.d.ts +174 -0
- package/dist/cli.js +149 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +2 -0
- package/dist/lib/HttpError.d.ts +4 -0
- package/dist/lib/appConfig.d.ts +17 -0
- package/dist/lib/authAdapter.d.ts +53 -0
- package/dist/lib/authRateLimit.d.ts +11 -0
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/context.d.ts +9 -0
- package/dist/lib/emailVerification.d.ts +9 -0
- package/dist/lib/fingerprint.d.ts +6 -0
- package/dist/lib/jwt.d.ts +2 -0
- package/dist/lib/logger.d.ts +1 -0
- package/dist/lib/mongo.d.ts +34 -0
- package/dist/lib/oauth.d.ts +27 -0
- package/dist/lib/queue.d.ts +5 -0
- package/dist/lib/redis.d.ts +14 -0
- package/dist/lib/roles.d.ts +3 -0
- package/dist/lib/session.d.ts +6 -0
- package/dist/lib/validate.d.ts +2 -0
- package/dist/lib/ws.d.ts +21 -0
- package/dist/middleware/bearerAuth.d.ts +2 -0
- package/dist/middleware/botProtection.d.ts +9 -0
- package/dist/middleware/cacheResponse.d.ts +14 -0
- package/dist/middleware/cors.d.ts +2 -0
- package/dist/middleware/errorHandler.d.ts +2 -0
- package/dist/middleware/identify.d.ts +3 -0
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/logger.d.ts +2 -0
- package/dist/middleware/rateLimit.d.ts +8 -0
- package/dist/middleware/requireRole.d.ts +17 -0
- package/dist/middleware/requireVerifiedEmail.d.ts +12 -0
- package/dist/middleware/userAuth.d.ts +3 -0
- package/dist/models/AuthUser.d.ts +112 -0
- package/dist/routes/auth.d.ts +8 -0
- package/dist/routes/health.d.ts +1 -0
- package/dist/routes/home.d.ts +1 -0
- package/dist/routes/oauth.d.ts +2 -0
- package/dist/schemas/auth.d.ts +10 -0
- package/dist/server.d.ts +25 -0
- package/dist/services/auth.d.ts +6 -0
- package/dist/ws/index.d.ts +10 -0
- package/package.json +18 -6
- package/CLAUDE.md +0 -102
- package/bun.lock +0 -170
- package/src/adapters/memoryAuth.ts +0 -240
- package/src/adapters/mongoAuth.ts +0 -91
- package/src/adapters/sqliteAuth.ts +0 -320
- package/src/app.ts +0 -368
- package/src/cli.ts +0 -265
- package/src/index.ts +0 -52
- package/src/lib/HttpError.ts +0 -5
- package/src/lib/appConfig.ts +0 -29
- package/src/lib/authAdapter.ts +0 -46
- package/src/lib/authRateLimit.ts +0 -104
- package/src/lib/constants.ts +0 -2
- package/src/lib/context.ts +0 -17
- package/src/lib/emailVerification.ts +0 -105
- package/src/lib/fingerprint.ts +0 -43
- package/src/lib/jwt.ts +0 -17
- package/src/lib/logger.ts +0 -9
- package/src/lib/mongo.ts +0 -82
- package/src/lib/oauth.ts +0 -114
- package/src/lib/queue.ts +0 -18
- package/src/lib/redis.ts +0 -56
- package/src/lib/roles.ts +0 -23
- package/src/lib/session.ts +0 -91
- package/src/lib/validate.ts +0 -14
- package/src/lib/ws.ts +0 -82
- package/src/middleware/bearerAuth.ts +0 -15
- package/src/middleware/botProtection.ts +0 -73
- package/src/middleware/cacheResponse.ts +0 -189
- package/src/middleware/cors.ts +0 -19
- package/src/middleware/errorHandler.ts +0 -14
- package/src/middleware/identify.ts +0 -36
- package/src/middleware/index.ts +0 -8
- package/src/middleware/logger.ts +0 -9
- package/src/middleware/rateLimit.ts +0 -37
- package/src/middleware/requireRole.ts +0 -42
- package/src/middleware/requireVerifiedEmail.ts +0 -31
- package/src/middleware/userAuth.ts +0 -9
- package/src/models/AuthUser.ts +0 -17
- package/src/routes/auth.ts +0 -245
- package/src/routes/health.ts +0 -27
- package/src/routes/home.ts +0 -21
- package/src/routes/oauth.ts +0 -174
- package/src/schemas/auth.ts +0 -14
- package/src/server.ts +0 -91
- package/src/services/auth.ts +0 -59
- package/src/ws/index.ts +0 -42
- package/tsconfig.json +0 -43
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type SessionStore = "redis" | "mongo" | "sqlite" | "memory";
|
|
2
|
+
export declare const setSessionStore: (store: SessionStore) => void;
|
|
3
|
+
export declare const createSession: (userId: string, token: string) => Promise<void>;
|
|
4
|
+
export declare const getSession: (userId: string) => Promise<any>;
|
|
5
|
+
export declare const deleteSession: (userId: string) => Promise<void>;
|
|
6
|
+
export {};
|
package/dist/lib/ws.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Server, ServerWebSocket } from "bun";
|
|
2
|
+
type WithRooms = {
|
|
3
|
+
rooms: Set<string>;
|
|
4
|
+
};
|
|
5
|
+
type WithSocketId = {
|
|
6
|
+
id: string;
|
|
7
|
+
} & WithRooms;
|
|
8
|
+
export declare const setWsServer: (server: Server<any>) => void;
|
|
9
|
+
export declare const publish: (topic: string, data: unknown) => void;
|
|
10
|
+
/** All rooms that currently have at least one subscriber */
|
|
11
|
+
export declare const getRooms: () => string[];
|
|
12
|
+
/** Socket IDs subscribed to a given room */
|
|
13
|
+
export declare const getRoomSubscribers: (room: string) => string[];
|
|
14
|
+
type RoomGuard<T extends WithRooms> = (ws: ServerWebSocket<T>, room: string) => boolean | Promise<boolean>;
|
|
15
|
+
export declare const handleRoomActions: <T extends WithSocketId>(ws: ServerWebSocket<T>, message: string | Buffer, onSubscribe?: RoomGuard<T>) => Promise<boolean>;
|
|
16
|
+
export declare const subscribe: <T extends WithSocketId>(ws: ServerWebSocket<T>, room: string) => void;
|
|
17
|
+
export declare const unsubscribe: <T extends WithSocketId>(ws: ServerWebSocket<T>, room: string) => void;
|
|
18
|
+
export declare const getSubscriptions: <T extends WithRooms>(ws: ServerWebSocket<T>) => string[];
|
|
19
|
+
/** Called on socket close to prune the registry. Internal use only. */
|
|
20
|
+
export declare const cleanupSocket: (socketId: string, rooms: Set<string>) => void;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
export interface BotProtectionOptions {
|
|
3
|
+
/**
|
|
4
|
+
* List of IPv4 CIDRs (e.g. "198.51.100.0/24"), IPv4 exact addresses,
|
|
5
|
+
* or IPv6 exact addresses to block with a 403.
|
|
6
|
+
*/
|
|
7
|
+
blockList?: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const botProtection: ({ blockList, }: BotProtectionOptions) => MiddlewareHandler;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
import type { AppEnv } from "../lib/context";
|
|
3
|
+
type CacheStore = "redis" | "mongo" | "sqlite" | "memory";
|
|
4
|
+
export declare const setCacheStore: (store: CacheStore) => void;
|
|
5
|
+
export declare const bustCache: (key: string) => Promise<void>;
|
|
6
|
+
export declare const bustCachePattern: (pattern: string) => Promise<void>;
|
|
7
|
+
type KeyFn = (c: Parameters<MiddlewareHandler<AppEnv>>[0]) => string;
|
|
8
|
+
interface CacheOptions {
|
|
9
|
+
ttl?: number;
|
|
10
|
+
key: string | KeyFn;
|
|
11
|
+
store?: CacheStore;
|
|
12
|
+
}
|
|
13
|
+
export declare const cacheResponse: ({ ttl, key, store }: CacheOptions) => MiddlewareHandler<AppEnv>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
export interface RateLimitOptions {
|
|
3
|
+
windowMs: number;
|
|
4
|
+
max: number;
|
|
5
|
+
/** Also rate-limit by HTTP fingerprint in addition to IP. Default: false */
|
|
6
|
+
fingerprintLimit?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const rateLimit: ({ windowMs, max, fingerprintLimit, }: RateLimitOptions) => MiddlewareHandler;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
import type { AppEnv } from "../lib/context";
|
|
3
|
+
/**
|
|
4
|
+
* Middleware factory that enforces role-based access.
|
|
5
|
+
* Requires `identify` to have run first (authUserId must be set).
|
|
6
|
+
* Roles are fetched lazily on the first role-checked route and cached on the context.
|
|
7
|
+
*
|
|
8
|
+
* The adapter must implement `getRoles` for this to work.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Allow any authenticated user with the "admin" role
|
|
12
|
+
* app.get("/admin", userAuth, requireRole("admin"), handler)
|
|
13
|
+
*
|
|
14
|
+
* // Allow users with either "admin" or "moderator"
|
|
15
|
+
* app.get("/mod", userAuth, requireRole("admin", "moderator"), handler)
|
|
16
|
+
*/
|
|
17
|
+
export declare const requireRole: (...roles: string[]) => MiddlewareHandler<AppEnv>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
import type { AppEnv } from "../lib/context";
|
|
3
|
+
/**
|
|
4
|
+
* Middleware that blocks access for users whose email address has not been verified.
|
|
5
|
+
* Must run after `userAuth` (requires `authUserId` to be set on context).
|
|
6
|
+
*
|
|
7
|
+
* The adapter must implement `getEmailVerified` for this to work.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* router.use("/dashboard", userAuth, requireVerifiedEmail);
|
|
11
|
+
*/
|
|
12
|
+
export declare const requireVerifiedEmail: MiddlewareHandler<AppEnv>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
export declare const AuthUser: mongoose.Model<{
|
|
3
|
+
providerIds: string[];
|
|
4
|
+
emailVerified: boolean;
|
|
5
|
+
roles: string[];
|
|
6
|
+
email?: string | null | undefined;
|
|
7
|
+
password?: string | null | undefined;
|
|
8
|
+
} & mongoose.DefaultTimestampProps, {}, {}, {
|
|
9
|
+
id: string;
|
|
10
|
+
}, mongoose.Document<unknown, {}, {
|
|
11
|
+
providerIds: string[];
|
|
12
|
+
emailVerified: boolean;
|
|
13
|
+
roles: string[];
|
|
14
|
+
email?: string | null | undefined;
|
|
15
|
+
password?: string | null | undefined;
|
|
16
|
+
} & mongoose.DefaultTimestampProps, {
|
|
17
|
+
id: string;
|
|
18
|
+
}, {
|
|
19
|
+
timestamps: true;
|
|
20
|
+
}> & Omit<{
|
|
21
|
+
providerIds: string[];
|
|
22
|
+
emailVerified: boolean;
|
|
23
|
+
roles: string[];
|
|
24
|
+
email?: string | null | undefined;
|
|
25
|
+
password?: string | null | undefined;
|
|
26
|
+
} & mongoose.DefaultTimestampProps & {
|
|
27
|
+
_id: mongoose.Types.ObjectId;
|
|
28
|
+
} & {
|
|
29
|
+
__v: number;
|
|
30
|
+
}, "id"> & {
|
|
31
|
+
id: string;
|
|
32
|
+
}, mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any, any>, {}, {}, {}, {}, {
|
|
33
|
+
timestamps: true;
|
|
34
|
+
}, {
|
|
35
|
+
providerIds: string[];
|
|
36
|
+
emailVerified: boolean;
|
|
37
|
+
roles: string[];
|
|
38
|
+
email?: string | null | undefined;
|
|
39
|
+
password?: string | null | undefined;
|
|
40
|
+
} & mongoose.DefaultTimestampProps, mongoose.Document<unknown, {}, {
|
|
41
|
+
providerIds: string[];
|
|
42
|
+
emailVerified: boolean;
|
|
43
|
+
roles: string[];
|
|
44
|
+
email?: string | null | undefined;
|
|
45
|
+
password?: string | null | undefined;
|
|
46
|
+
} & mongoose.DefaultTimestampProps, {
|
|
47
|
+
id: string;
|
|
48
|
+
}, mongoose.MergeType<mongoose.DefaultSchemaOptions, {
|
|
49
|
+
timestamps: true;
|
|
50
|
+
}>> & Omit<{
|
|
51
|
+
providerIds: string[];
|
|
52
|
+
emailVerified: boolean;
|
|
53
|
+
roles: string[];
|
|
54
|
+
email?: string | null | undefined;
|
|
55
|
+
password?: string | null | undefined;
|
|
56
|
+
} & mongoose.DefaultTimestampProps & {
|
|
57
|
+
_id: mongoose.Types.ObjectId;
|
|
58
|
+
} & {
|
|
59
|
+
__v: number;
|
|
60
|
+
}, "id"> & {
|
|
61
|
+
id: string;
|
|
62
|
+
}, {
|
|
63
|
+
[path: string]: mongoose.SchemaDefinitionProperty<undefined, any, any>;
|
|
64
|
+
} | {
|
|
65
|
+
[x: string]: mongoose.SchemaDefinitionProperty<any, any, mongoose.Document<unknown, {}, {
|
|
66
|
+
providerIds: string[];
|
|
67
|
+
emailVerified: boolean;
|
|
68
|
+
roles: string[];
|
|
69
|
+
email?: string | null | undefined;
|
|
70
|
+
password?: string | null | undefined;
|
|
71
|
+
} & mongoose.DefaultTimestampProps, {
|
|
72
|
+
id: string;
|
|
73
|
+
}, mongoose.MergeType<mongoose.DefaultSchemaOptions, {
|
|
74
|
+
timestamps: true;
|
|
75
|
+
}>> & Omit<{
|
|
76
|
+
providerIds: string[];
|
|
77
|
+
emailVerified: boolean;
|
|
78
|
+
roles: string[];
|
|
79
|
+
email?: string | null | undefined;
|
|
80
|
+
password?: string | null | undefined;
|
|
81
|
+
} & mongoose.DefaultTimestampProps & {
|
|
82
|
+
_id: mongoose.Types.ObjectId;
|
|
83
|
+
} & {
|
|
84
|
+
__v: number;
|
|
85
|
+
}, "id"> & {
|
|
86
|
+
id: string;
|
|
87
|
+
}> | undefined;
|
|
88
|
+
}, {
|
|
89
|
+
providerIds: string[];
|
|
90
|
+
emailVerified: boolean;
|
|
91
|
+
roles: string[];
|
|
92
|
+
email?: string | null | undefined;
|
|
93
|
+
password?: string | null | undefined;
|
|
94
|
+
createdAt: NativeDate;
|
|
95
|
+
updatedAt: NativeDate;
|
|
96
|
+
} & {
|
|
97
|
+
_id: mongoose.Types.ObjectId;
|
|
98
|
+
} & {
|
|
99
|
+
__v: number;
|
|
100
|
+
}>, {
|
|
101
|
+
providerIds: string[];
|
|
102
|
+
emailVerified: boolean;
|
|
103
|
+
roles: string[];
|
|
104
|
+
email?: string | null | undefined;
|
|
105
|
+
password?: string | null | undefined;
|
|
106
|
+
createdAt: NativeDate;
|
|
107
|
+
updatedAt: NativeDate;
|
|
108
|
+
} & {
|
|
109
|
+
_id: mongoose.Types.ObjectId;
|
|
110
|
+
} & {
|
|
111
|
+
__v: number;
|
|
112
|
+
}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrimaryField, EmailVerificationConfig } from "../lib/appConfig";
|
|
2
|
+
import type { AuthRateLimitConfig } from "../app";
|
|
3
|
+
export interface AuthRouterOptions {
|
|
4
|
+
primaryField: PrimaryField;
|
|
5
|
+
emailVerification?: EmailVerificationConfig;
|
|
6
|
+
rateLimit?: AuthRateLimitConfig;
|
|
7
|
+
}
|
|
8
|
+
export declare const createAuthRouter: ({ primaryField, emailVerification, rateLimit }: AuthRouterOptions) => import("@hono/zod-openapi").OpenAPIHono<import("../lib/context").AppEnv, {}, "/">;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../lib/context").AppEnv, {}, "/">;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../lib/context").AppEnv, {}, "/">;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { PrimaryField } from "../lib/appConfig";
|
|
3
|
+
export declare const makeRegisterSchema: (primaryField: PrimaryField) => z.ZodObject<{
|
|
4
|
+
[x: string]: z.ZodString;
|
|
5
|
+
password: z.ZodString;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export declare const makeLoginSchema: (primaryField: PrimaryField) => z.ZodObject<{
|
|
8
|
+
[x: string]: z.ZodString;
|
|
9
|
+
password: z.ZodString;
|
|
10
|
+
}, z.core.$strip>;
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Server, ServerWebSocket, WebSocketHandler } from "bun";
|
|
2
|
+
import { type CreateAppConfig } from "./app";
|
|
3
|
+
import { type SocketData } from "./ws/index";
|
|
4
|
+
export interface WsConfig<T extends object = object> {
|
|
5
|
+
/** Override or extend the default WebSocket handler */
|
|
6
|
+
handler?: WebSocketHandler<SocketData<T>>;
|
|
7
|
+
/** Override the default /ws upgrade handler (auth + upgrade logic) */
|
|
8
|
+
upgradeHandler?: (req: Request, server: Server<SocketData<T>>) => Promise<Response | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* Guard called before a socket joins a room via the subscribe action.
|
|
11
|
+
* Return true to allow, false to deny (client receives { event: "subscribe_denied", room }).
|
|
12
|
+
* ws.data.userId is available for auth checks.
|
|
13
|
+
*/
|
|
14
|
+
onRoomSubscribe?: (ws: ServerWebSocket<SocketData<T>>, room: string) => boolean | Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
export interface CreateServerConfig<T extends object = object> extends CreateAppConfig {
|
|
17
|
+
port?: number;
|
|
18
|
+
/** Absolute path to the service's workers directory — auto-imports all .ts files */
|
|
19
|
+
workersDir?: string;
|
|
20
|
+
/** Set false to disable auto-loading workers. Defaults to true */
|
|
21
|
+
enableWorkers?: boolean;
|
|
22
|
+
/** WebSocket configuration */
|
|
23
|
+
ws?: WsConfig<T>;
|
|
24
|
+
}
|
|
25
|
+
export declare const createServer: <T extends object = object>(config: CreateServerConfig<T>) => Promise<Server<SocketData<T>>>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const register: (identifier: string, password: string) => Promise<string>;
|
|
2
|
+
export declare const login: (identifier: string, password: string) => Promise<{
|
|
3
|
+
token: string;
|
|
4
|
+
emailVerified?: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const logout: (token: string | null) => Promise<void>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Server, WebSocketHandler } from "bun";
|
|
2
|
+
export type SocketData<T extends object = object> = {
|
|
3
|
+
id: string;
|
|
4
|
+
userId: string | null;
|
|
5
|
+
rooms: Set<string>;
|
|
6
|
+
} & T;
|
|
7
|
+
type BaseSocketData = SocketData<object>;
|
|
8
|
+
export declare const createWsUpgradeHandler: (server: Server<BaseSocketData>) => (req: Request) => Promise<Response | undefined>;
|
|
9
|
+
export declare const websocket: WebSocketHandler<BaseSocketData>;
|
|
10
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastshotlabs/bunshot",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Batteries-included Bun + Hono API framework — auth, sessions, rate limiting, WebSocket, queues, and OpenAPI docs out of the box",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,14 +16,24 @@
|
|
|
16
16
|
"websocket",
|
|
17
17
|
"openapi"
|
|
18
18
|
],
|
|
19
|
-
"module": "
|
|
19
|
+
"module": "dist/index.js",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
20
21
|
"exports": {
|
|
21
|
-
".":
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts"
|
|
25
|
+
}
|
|
22
26
|
},
|
|
23
27
|
"bin": {
|
|
24
|
-
"bunshot": "./
|
|
28
|
+
"bunshot": "./dist/cli.js"
|
|
25
29
|
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
26
33
|
"scripts": {
|
|
34
|
+
"build": "bun build src/index.ts --outdir dist --minify --target bun --external '*' && bun build src/cli.ts --outdir dist --minify --target bun --external '*' && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
35
|
+
"prepublishOnly": "bun run build",
|
|
36
|
+
"release": "npm version patch && npm publish",
|
|
27
37
|
"dev": "bun --watch src/index.ts",
|
|
28
38
|
"start": "bun src/index.ts"
|
|
29
39
|
},
|
|
@@ -39,9 +49,11 @@
|
|
|
39
49
|
"zod": "4.3.6"
|
|
40
50
|
},
|
|
41
51
|
"devDependencies": {
|
|
42
|
-
"@types/bun": "1.3.10"
|
|
52
|
+
"@types/bun": "1.3.10",
|
|
53
|
+
"tsc-alias": "^1.8.16",
|
|
54
|
+
"typescript": "^5.9.3"
|
|
43
55
|
},
|
|
44
56
|
"publishConfig": {
|
|
45
57
|
"access": "public"
|
|
46
58
|
}
|
|
47
|
-
}
|
|
59
|
+
}
|
package/CLAUDE.md
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
See @README for project overview
|
|
6
|
-
|
|
7
|
-
Update ReadMe and this file (CLAUDE.md) when adding, modifying, or deleting features to ensure proper documentation
|
|
8
|
-
|
|
9
|
-
## Commands
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
bun run dev # Watch mode (hot reload)
|
|
13
|
-
bun run start # Run without watch
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
There are no build, test, or lint scripts — this is a library package published to npm as `@lastshotlabs/bunshot`.
|
|
17
|
-
|
|
18
|
-
## Architecture
|
|
19
|
-
|
|
20
|
-
This is a **Bun + Hono API framework library** that consuming projects install as a dependency. It provides batteries-included scaffolding: auto-discovery of routes/workers, built-in auth, OpenAPI docs, WebSocket rooms, caching, and rate limiting.
|
|
21
|
-
|
|
22
|
-
### Entry Points
|
|
23
|
-
|
|
24
|
-
- **[src/app.ts](src/app.ts)** — `createApp(config)` factory: sets up Hono with CORS, middleware stack, auto-discovered routes, and OpenAPI/Scalar docs
|
|
25
|
-
- **[src/server.ts](src/server.ts)** — `createServer(config)` factory: wraps app with `Bun.serve()`, adds WebSocket upgrade handling, and auto-discovers BullMQ workers
|
|
26
|
-
- **[src/index.ts](src/index.ts)** — Barrel export for all public APIs
|
|
27
|
-
- **[src/cli.ts](src/cli.ts)** — CLI entry point
|
|
28
|
-
|
|
29
|
-
### Key Patterns
|
|
30
|
-
|
|
31
|
-
**Route auto-discovery:** Consuming projects place routes in a `routes/` directory. The framework scans and registers them automatically. Routes use `@hono/zod-openapi` for type-safe OpenAPI definitions. Load order can be controlled by exporting `export const priority = <number>` from a route file (lower = loaded first; files without it load last).
|
|
32
|
-
|
|
33
|
-
**Worker auto-discovery:** BullMQ workers are placed in a `workers/` directory and auto-started by `createServer`.
|
|
34
|
-
|
|
35
|
-
**Auth flow:** `src/lib/auth.ts` orchestrates login/register/logout/email-verification. The auth store is pluggable via `AuthAdapter` interface (default: `src/adapters/mongoAuth.ts`). Sessions can be stored in Redis, MongoDB, SQLite, or memory — configured via `db.sessions` in `CreateAppConfig`. Login identifier is configurable via `auth.primaryField` (`"email"` | `"username"` | `"phone"`). Email verification is opt-in via `auth.emailVerification` (supports `required: true` to block login until verified).
|
|
36
|
-
|
|
37
|
-
**Context extension:** The framework exposes a typed `AppContext` (Hono `Context`) that consuming apps extend with their own variables.
|
|
38
|
-
|
|
39
|
-
### Lib Layer (`src/lib/`)
|
|
40
|
-
|
|
41
|
-
| File | Purpose |
|
|
42
|
-
|------|---------|
|
|
43
|
-
| `mongo.ts` | Mongoose connection management; `disconnectMongo()` for clean shutdown |
|
|
44
|
-
| `redis.ts` | ioredis client; `disconnectRedis()` for clean shutdown |
|
|
45
|
-
| `jwt.ts` | `jose`-based JWT sign/verify |
|
|
46
|
-
| `session.ts` | Session CRUD — store set via `db.sessions` ("redis" \| "mongo" \| "sqlite" \| "memory") |
|
|
47
|
-
| `auth.ts` | Register/login/logout/password logic |
|
|
48
|
-
| `oauth.ts` | OAuth provider coordination via `arctic` — state store set via `db.oauthState` |
|
|
49
|
-
| `cache.ts` | Response cache — default store set via `db.cache`, overridable per-route; exports `bustCache` (all stores) and `bustCachePattern` (wildcard invalidation) |
|
|
50
|
-
| `rateLimit.ts` | Per-key rate limiting; exports `trackAttempt`, `isLimited`, `bustAuthLimit` for use in custom routes |
|
|
51
|
-
| `ws.ts` | WebSocket room registry, pub/sub helpers (`publish`, `subscribe`, `unsubscribe`, `getSubscriptions`, `handleRoomActions`, `getRooms`, `getRoomSubscribers`) — in-memory, no DB dependency |
|
|
52
|
-
|
|
53
|
-
### Middleware (`src/middleware/`)
|
|
54
|
-
|
|
55
|
-
- `bearerAuth` — API key validation via `Authorization: Bearer` header
|
|
56
|
-
- `identify` — Reads session and attaches user to context (non-blocking)
|
|
57
|
-
- `userAuth` — Requires authenticated user (blocks if not logged in)
|
|
58
|
-
- `requireRole` — RBAC role enforcement
|
|
59
|
-
- `requireVerifiedEmail` — Blocks access for users whose email has not been verified (requires `getEmailVerified` on adapter)
|
|
60
|
-
- `rateLimit` — Request rate limiting
|
|
61
|
-
- `cacheResponse` — Response caching with TTL
|
|
62
|
-
|
|
63
|
-
### Adapters (`src/adapters/`)
|
|
64
|
-
|
|
65
|
-
| File | Purpose |
|
|
66
|
-
|------|---------|
|
|
67
|
-
| `mongoAuth.ts` | Default `AuthAdapter` backed by Mongoose / MongoDB |
|
|
68
|
-
| `sqliteAuth.ts` | `AuthAdapter` + session/OAuth/cache helpers backed by `bun:sqlite`. Exports `setSqliteDb(path)` and `startSqliteCleanup()`. |
|
|
69
|
-
| `memoryAuth.ts` | `AuthAdapter` + session/OAuth/cache helpers backed by in-memory Maps. Exports `clearMemoryStore()` for test isolation. |
|
|
70
|
-
|
|
71
|
-
### Built-in Routes (`src/routes/`)
|
|
72
|
-
|
|
73
|
-
- `auth.ts` — `/auth/register`, `/auth/login`, `/auth/logout`, `/auth/set-password`, `/auth/me`, `/auth/verify-email`, `/auth/resend-verification`
|
|
74
|
-
- `oauth.ts` — OAuth initiation (`GET /auth/{provider}`), callbacks, link (`GET /auth/{provider}/link`), and unlink (`DELETE /auth/{provider}/link`) handlers
|
|
75
|
-
- `health.ts` — Health check
|
|
76
|
-
- `home.ts` — Root endpoint
|
|
77
|
-
|
|
78
|
-
### TypeScript Path Aliases
|
|
79
|
-
|
|
80
|
-
Defined in `tsconfig.json`, used throughout the codebase:
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
@lib/* → src/lib/*
|
|
84
|
-
@middleware/* → src/middleware/*
|
|
85
|
-
@models/* → src/models/*
|
|
86
|
-
@routes/* → src/routes/*
|
|
87
|
-
@workers/* → src/workers/*
|
|
88
|
-
@ws/* → src/ws/*
|
|
89
|
-
@schemas/* → src/schemas/*
|
|
90
|
-
@services/* → src/services/*
|
|
91
|
-
@queues/* → src/queues/*
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### WebSocket
|
|
95
|
-
|
|
96
|
-
`src/ws/index.ts` handles connection upgrades and authenticates via `getSession()` (supports all 4 store backends). Room management lives in `src/lib/ws.ts` using in-memory Maps + Bun's native pub/sub (`ws.subscribe`/`server.publish`).
|
|
97
|
-
|
|
98
|
-
### Environment Variables
|
|
99
|
-
|
|
100
|
-
See README.md for the full reference. All DB/auth vars are split by environment: `*_DEV` / `*_PROD` (selected by `NODE_ENV`). Key groups: `MONGO_*`, `REDIS_*`, `JWT_SECRET_*`, `BEARER_TOKEN_*`, `PORT`.
|
|
101
|
-
|
|
102
|
-
|