@parsrun/server 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,142 @@
1
+ # @parsrun/server
2
+
3
+ Edge-compatible, multi-tenant server framework for Pars built on Hono.
4
+
5
+ ## Features
6
+
7
+ - **Edge-First**: Cloudflare Workers, Deno Deploy, Vercel Edge
8
+ - **Multi-Tenant**: RLS (Row-Level Security), tenant context
9
+ - **RBAC**: Role-based access control
10
+ - **Modular**: Dynamic module loading
11
+ - **Health Checks**: Kubernetes-ready health endpoints
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pnpm add @parsrun/server hono
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { createApp, createContext } from '@parsrun/server';
23
+
24
+ const app = createApp({
25
+ name: 'my-api',
26
+ version: '1.0.0',
27
+ });
28
+
29
+ app.get('/', (c) => c.json({ status: 'ok' }));
30
+
31
+ export default app;
32
+ ```
33
+
34
+ ## API Overview
35
+
36
+ ### App Creation
37
+
38
+ ```typescript
39
+ import { createApp } from '@parsrun/server';
40
+
41
+ const app = createApp({
42
+ name: 'my-api',
43
+ version: '1.0.0',
44
+ cors: true,
45
+ logging: true,
46
+ });
47
+ ```
48
+
49
+ ### Context & Middleware
50
+
51
+ ```typescript
52
+ import { createContext, withTenant } from '@parsrun/server/context';
53
+
54
+ // Tenant-aware context
55
+ app.use(withTenant());
56
+
57
+ app.get('/data', (c) => {
58
+ const tenantId = c.get('tenantId');
59
+ // ...
60
+ });
61
+ ```
62
+
63
+ ### Row-Level Security (RLS)
64
+
65
+ ```typescript
66
+ import { createRLS } from '@parsrun/server/rls';
67
+
68
+ const rls = createRLS({
69
+ tenantColumn: 'tenant_id',
70
+ userColumn: 'user_id',
71
+ });
72
+
73
+ // Apply RLS to queries
74
+ const query = rls.apply(baseQuery, context);
75
+ ```
76
+
77
+ ### RBAC
78
+
79
+ ```typescript
80
+ import { createRBAC, requireRole, requirePermission } from '@parsrun/server/rbac';
81
+
82
+ const rbac = createRBAC({
83
+ roles: {
84
+ admin: ['users:*', 'settings:*'],
85
+ member: ['users:read', 'content:*'],
86
+ },
87
+ });
88
+
89
+ app.get('/admin', requireRole('admin'), handler);
90
+ app.delete('/users/:id', requirePermission('users:delete'), handler);
91
+ ```
92
+
93
+ ### Health Checks
94
+
95
+ ```typescript
96
+ import { createHealthRoutes } from '@parsrun/server/health';
97
+
98
+ app.route('/health', createHealthRoutes({
99
+ checks: {
100
+ database: async () => ({ status: 'ok' }),
101
+ cache: async () => ({ status: 'ok' }),
102
+ },
103
+ }));
104
+ ```
105
+
106
+ ### Module Loader
107
+
108
+ ```typescript
109
+ import { createModuleLoader } from '@parsrun/server/module-loader';
110
+
111
+ const loader = createModuleLoader({
112
+ modulesDir: './modules',
113
+ autoload: true,
114
+ });
115
+
116
+ await loader.loadModules(app);
117
+ ```
118
+
119
+ ### Validation
120
+
121
+ ```typescript
122
+ import { validate, schemas } from '@parsrun/server/validation';
123
+
124
+ app.post('/users', validate(schemas.createUser), handler);
125
+ ```
126
+
127
+ ## Exports
128
+
129
+ ```typescript
130
+ import { ... } from '@parsrun/server'; // Main exports
131
+ import { ... } from '@parsrun/server/app'; // App creation
132
+ import { ... } from '@parsrun/server/context'; // Context utilities
133
+ import { ... } from '@parsrun/server/rls'; // Row-level security
134
+ import { ... } from '@parsrun/server/rbac'; // Role-based access
135
+ import { ... } from '@parsrun/server/health'; // Health checks
136
+ import { ... } from '@parsrun/server/middleware'; // Middleware
137
+ import { ... } from '@parsrun/server/validation'; // Validation
138
+ ```
139
+
140
+ ## License
141
+
142
+ MIT
package/dist/app.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ import * as hono from 'hono';
2
+ import { ServerConfig, HonoApp } from './context.js';
3
+ import '@parsrun/core';
4
+
5
+ /**
6
+ * Extended server options
7
+ */
8
+ interface CreateServerOptions extends ServerConfig {
9
+ /** Enable request logging */
10
+ logging?: boolean;
11
+ /** Enable request ID generation */
12
+ requestId?: boolean;
13
+ /** Base path for all routes */
14
+ basePath?: string;
15
+ /** Strict mode - trailing slashes matter */
16
+ strict?: boolean;
17
+ }
18
+ /**
19
+ * Create a new Pars server instance
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const app = createServer({
24
+ * database: db,
25
+ * cors: { origin: '*' },
26
+ * logging: true,
27
+ * });
28
+ *
29
+ * app.get('/health', (c) => c.json({ status: 'ok' }));
30
+ *
31
+ * export default app;
32
+ * ```
33
+ */
34
+ declare function createServer(options: CreateServerOptions): HonoApp;
35
+ /**
36
+ * Create a router (sub-app) with shared context
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const usersRouter = createRouter();
41
+ *
42
+ * usersRouter.get('/', async (c) => {
43
+ * const users = await getUsers(c.get('db'));
44
+ * return c.json(success(users));
45
+ * });
46
+ *
47
+ * usersRouter.post('/', async (c) => {
48
+ * // ...
49
+ * });
50
+ *
51
+ * app.route('/api/users', usersRouter);
52
+ * ```
53
+ */
54
+ declare function createRouter(): HonoApp;
55
+ /**
56
+ * Create a versioned API router
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const v1 = createVersionedRouter('v1');
61
+ * v1.get('/users', handler);
62
+ *
63
+ * app.route('/api', v1); // Results in /api/v1/users
64
+ * ```
65
+ */
66
+ declare function createVersionedRouter(version: string): HonoApp;
67
+ /**
68
+ * Create a module router with prefix
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const inventoryModule = createModuleRouter('inventory', {
73
+ * routes: (router) => {
74
+ * router.get('/items', listItems);
75
+ * router.post('/items', createItem);
76
+ * },
77
+ * });
78
+ *
79
+ * app.route('/api', inventoryModule);
80
+ * ```
81
+ */
82
+ declare function createModuleRouter(moduleName: string, options: {
83
+ routes: (router: HonoApp) => void;
84
+ middleware?: Array<(c: hono.Context, next: () => Promise<void>) => Promise<Response | void>>;
85
+ }): HonoApp;
86
+
87
+ export { type CreateServerOptions, createModuleRouter, createRouter, createServer, createVersionedRouter };
package/dist/app.js ADDED
@@ -0,0 +1,59 @@
1
+ // src/app.ts
2
+ import { Hono } from "hono";
3
+ import { createLogger } from "@parsrun/core";
4
+
5
+ // src/context.ts
6
+ function generateRequestId() {
7
+ return crypto.randomUUID();
8
+ }
9
+
10
+ // src/app.ts
11
+ function createServer(options) {
12
+ const app = new Hono({
13
+ strict: options.strict ?? false
14
+ });
15
+ const logger = options.logger ?? createLogger({ name: "pars-server" });
16
+ app.use("*", async (c, next) => {
17
+ c.set("db", options.database);
18
+ c.set("config", options);
19
+ c.set("logger", logger);
20
+ c.set("enabledModules", /* @__PURE__ */ new Set());
21
+ c.set("cookiePrefix", options.cookiePrefix);
22
+ c.set("custom", options.custom ?? {});
23
+ if (options.requestId !== false) {
24
+ const requestId = c.req.header("x-request-id") ?? generateRequestId();
25
+ c.set("requestId", requestId);
26
+ c.header("x-request-id", requestId);
27
+ }
28
+ await next();
29
+ });
30
+ return app;
31
+ }
32
+ function createRouter() {
33
+ return new Hono();
34
+ }
35
+ function createVersionedRouter(version) {
36
+ const router = new Hono();
37
+ const versionedRouter = new Hono();
38
+ versionedRouter.route(`/${version}`, router);
39
+ return versionedRouter;
40
+ }
41
+ function createModuleRouter(moduleName, options) {
42
+ const moduleRouter = new Hono();
43
+ if (options.middleware) {
44
+ for (const mw of options.middleware) {
45
+ moduleRouter.use("*", mw);
46
+ }
47
+ }
48
+ options.routes(moduleRouter);
49
+ const wrappedRouter = new Hono();
50
+ wrappedRouter.route(`/${moduleName}`, moduleRouter);
51
+ return wrappedRouter;
52
+ }
53
+ export {
54
+ createModuleRouter,
55
+ createRouter,
56
+ createServer,
57
+ createVersionedRouter
58
+ };
59
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/app.ts","../src/context.ts"],"sourcesContent":["/**\n * @parsrun/server - App Factory\n * Create and configure Hono server instances\n */\n\nimport { Hono } from \"hono\";\nimport { createLogger } from \"@parsrun/core\";\nimport type {\n ServerConfig,\n ServerContextVariables,\n HonoApp,\n} from \"./context.js\";\nimport { generateRequestId } from \"./context.js\";\n\n/**\n * Extended server options\n */\nexport interface CreateServerOptions extends ServerConfig {\n /** Enable request logging */\n logging?: boolean;\n /** Enable request ID generation */\n requestId?: boolean;\n /** Base path for all routes */\n basePath?: string;\n /** Strict mode - trailing slashes matter */\n strict?: boolean;\n}\n\n/**\n * Create a new Pars server instance\n *\n * @example\n * ```typescript\n * const app = createServer({\n * database: db,\n * cors: { origin: '*' },\n * logging: true,\n * });\n *\n * app.get('/health', (c) => c.json({ status: 'ok' }));\n *\n * export default app;\n * ```\n */\nexport function createServer(options: CreateServerOptions): HonoApp {\n const app = new Hono<{ Variables: ServerContextVariables }>({\n strict: options.strict ?? false,\n });\n\n const logger = options.logger ?? createLogger({ name: \"pars-server\" });\n\n // Initialize context for all requests\n app.use(\"*\", async (c, next) => {\n // Set core context variables\n c.set(\"db\", options.database);\n c.set(\"config\", options);\n c.set(\"logger\", logger);\n c.set(\"enabledModules\", new Set<string>());\n c.set(\"cookiePrefix\", options.cookiePrefix);\n c.set(\"custom\", options.custom ?? {});\n\n // Generate request ID if enabled\n if (options.requestId !== false) {\n const requestId = c.req.header(\"x-request-id\") ?? generateRequestId();\n c.set(\"requestId\", requestId);\n c.header(\"x-request-id\", requestId);\n }\n\n await next();\n });\n\n return app;\n}\n\n/**\n * Create a router (sub-app) with shared context\n *\n * @example\n * ```typescript\n * const usersRouter = createRouter();\n *\n * usersRouter.get('/', async (c) => {\n * const users = await getUsers(c.get('db'));\n * return c.json(success(users));\n * });\n *\n * usersRouter.post('/', async (c) => {\n * // ...\n * });\n *\n * app.route('/api/users', usersRouter);\n * ```\n */\nexport function createRouter(): HonoApp {\n return new Hono<{ Variables: ServerContextVariables }>();\n}\n\n/**\n * Create a versioned API router\n *\n * @example\n * ```typescript\n * const v1 = createVersionedRouter('v1');\n * v1.get('/users', handler);\n *\n * app.route('/api', v1); // Results in /api/v1/users\n * ```\n */\nexport function createVersionedRouter(version: string): HonoApp {\n const router = new Hono<{ Variables: ServerContextVariables }>();\n\n // Add version to all routes\n const versionedRouter = new Hono<{ Variables: ServerContextVariables }>();\n versionedRouter.route(`/${version}`, router);\n\n return versionedRouter;\n}\n\n/**\n * Create a module router with prefix\n *\n * @example\n * ```typescript\n * const inventoryModule = createModuleRouter('inventory', {\n * routes: (router) => {\n * router.get('/items', listItems);\n * router.post('/items', createItem);\n * },\n * });\n *\n * app.route('/api', inventoryModule);\n * ```\n */\nexport function createModuleRouter(\n moduleName: string,\n options: {\n routes: (router: HonoApp) => void;\n middleware?: Array<(c: import(\"hono\").Context, next: () => Promise<void>) => Promise<Response | void>>;\n }\n): HonoApp {\n const moduleRouter = new Hono<{ Variables: ServerContextVariables }>();\n\n // Apply module-specific middleware\n if (options.middleware) {\n for (const mw of options.middleware) {\n moduleRouter.use(\"*\", mw);\n }\n }\n\n // Register routes\n options.routes(moduleRouter);\n\n // Wrap in module path\n const wrappedRouter = new Hono<{ Variables: ServerContextVariables }>();\n wrappedRouter.route(`/${moduleName}`, moduleRouter);\n\n return wrappedRouter;\n}\n","/**\n * @parsrun/server - Server Context\n * Type definitions for server context and configuration\n */\n\nimport type { Logger } from \"@parsrun/core\";\n\n/**\n * Database adapter interface\n * Implement this for your database (Drizzle, Prisma, etc.)\n */\nexport interface DatabaseAdapter {\n /** Execute raw SQL query */\n execute(sql: string): Promise<unknown>;\n /** Check connection */\n ping?(): Promise<boolean>;\n}\n\n/**\n * Module manifest for registering modules\n */\nexport interface ModuleManifest {\n /** Unique module name */\n name: string;\n /** Module version */\n version: string;\n /** Module description */\n description: string;\n /** Required permissions for this module */\n permissions: Record<string, string[]>;\n /** Module dependencies (other module names) */\n dependencies?: string[];\n /** Register routes for this module */\n registerRoutes: (app: HonoApp) => void;\n /** Called when module is enabled */\n onEnable?: () => Promise<void>;\n /** Called when module is disabled */\n onDisable?: () => Promise<void>;\n}\n\n/**\n * Server configuration\n */\nexport interface ServerConfig {\n /** Database adapter */\n database: DatabaseAdapter;\n /** CORS configuration */\n cors?: CorsConfig;\n /** Base path for API */\n basePath?: string;\n /** Cookie prefix for all cookies */\n cookiePrefix?: string;\n /** Logger instance */\n logger?: Logger;\n /** Custom context data */\n custom?: Record<string, unknown>;\n}\n\n/**\n * CORS configuration\n */\nexport interface CorsConfig {\n /** Allowed origins */\n origin: string | string[] | ((origin: string) => boolean);\n /** Allow credentials */\n credentials?: boolean;\n /** Allowed methods */\n methods?: string[];\n /** Allowed headers */\n allowedHeaders?: string[];\n /** Exposed headers */\n exposedHeaders?: string[];\n /** Max age in seconds */\n maxAge?: number;\n}\n\n/**\n * User information in context\n */\nexport interface ContextUser {\n id: string;\n email: string | undefined;\n tenantId: string | undefined;\n role: string | undefined;\n permissions: string[];\n}\n\n/**\n * Tenant information in context\n */\nexport interface ContextTenant {\n id: string;\n slug: string | undefined;\n name: string | undefined;\n status: string;\n}\n\n/**\n * Server context variables\n * Available in Hono context via c.get()\n */\nexport interface ServerContextVariables {\n /** Database adapter */\n db: DatabaseAdapter;\n /** Server configuration */\n config: ServerConfig;\n /** Enabled modules set */\n enabledModules: Set<string>;\n /** Current user (if authenticated) */\n user: ContextUser | undefined;\n /** Current tenant (if resolved) */\n tenant: ContextTenant | undefined;\n /** Request logger */\n logger: Logger;\n /** Request ID */\n requestId: string;\n /** Cookie prefix */\n cookiePrefix: string | undefined;\n /** Custom context data */\n custom: Record<string, unknown>;\n}\n\n/**\n * Hono app type with server context\n */\nexport type HonoApp = import(\"hono\").Hono<{ Variables: ServerContextVariables }>;\n\n/**\n * Hono context type with server context\n */\nexport type HonoContext = import(\"hono\").Context<{ Variables: ServerContextVariables }>;\n\n/**\n * Middleware next function\n */\nexport type HonoNext = () => Promise<void>;\n\n/**\n * Middleware function type\n */\nexport type Middleware = (c: HonoContext, next: HonoNext) => Promise<Response | void>;\n\n/**\n * Route handler function type\n */\nexport type RouteHandler = (c: HonoContext) => Promise<Response> | Response;\n\n/**\n * Permission check input\n */\nexport interface PermissionCheck {\n /** Resource name (e.g., \"users\", \"items\") */\n resource: string;\n /** Action name (e.g., \"read\", \"create\", \"update\", \"delete\") */\n action: string;\n /** Permission scope */\n scope?: \"tenant\" | \"global\" | \"own\";\n}\n\n/**\n * Permission definition\n */\nexport interface PermissionDefinition {\n /** Permission name (e.g., \"users:read\") */\n name: string;\n /** Resource part */\n resource: string;\n /** Action part */\n action: string;\n /** Description */\n description?: string;\n /** Scope */\n scope?: \"tenant\" | \"global\" | \"own\";\n}\n\n/**\n * Role definition\n */\nexport interface RoleDefinition {\n /** Role name */\n name: string;\n /** Display name */\n displayName?: string;\n /** Description */\n description?: string;\n /** Permissions assigned to this role */\n permissions: string[];\n /** Is this a system role */\n isSystem?: boolean;\n}\n\n/**\n * Standard API response structure\n */\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: Record<string, unknown> | undefined;\n };\n meta?: {\n page?: number | undefined;\n limit?: number | undefined;\n total?: number | undefined;\n requestId?: string | undefined;\n } | undefined;\n}\n\n/**\n * Create a success response\n */\nexport function success<T>(data: T, meta?: ApiResponse[\"meta\"]): ApiResponse<T> {\n return {\n success: true,\n data,\n meta: meta ?? undefined,\n };\n}\n\n/**\n * Create an error response\n */\nexport function error(\n code: string,\n message: string,\n details?: Record<string, unknown>\n): ApiResponse<never> {\n return {\n success: false,\n error: { code, message, details: details ?? undefined },\n };\n}\n\n/**\n * Generate a request ID\n */\nexport function generateRequestId(): string {\n return crypto.randomUUID();\n}\n"],"mappings":";AAKA,SAAS,YAAY;AACrB,SAAS,oBAAoB;;;ACwOtB,SAAS,oBAA4B;AAC1C,SAAO,OAAO,WAAW;AAC3B;;;ADpMO,SAAS,aAAa,SAAuC;AAClE,QAAM,MAAM,IAAI,KAA4C;AAAA,IAC1D,QAAQ,QAAQ,UAAU;AAAA,EAC5B,CAAC;AAED,QAAM,SAAS,QAAQ,UAAU,aAAa,EAAE,MAAM,cAAc,CAAC;AAGrE,MAAI,IAAI,KAAK,OAAO,GAAG,SAAS;AAE9B,MAAE,IAAI,MAAM,QAAQ,QAAQ;AAC5B,MAAE,IAAI,UAAU,OAAO;AACvB,MAAE,IAAI,UAAU,MAAM;AACtB,MAAE,IAAI,kBAAkB,oBAAI,IAAY,CAAC;AACzC,MAAE,IAAI,gBAAgB,QAAQ,YAAY;AAC1C,MAAE,IAAI,UAAU,QAAQ,UAAU,CAAC,CAAC;AAGpC,QAAI,QAAQ,cAAc,OAAO;AAC/B,YAAM,YAAY,EAAE,IAAI,OAAO,cAAc,KAAK,kBAAkB;AACpE,QAAE,IAAI,aAAa,SAAS;AAC5B,QAAE,OAAO,gBAAgB,SAAS;AAAA,IACpC;AAEA,UAAM,KAAK;AAAA,EACb,CAAC;AAED,SAAO;AACT;AAqBO,SAAS,eAAwB;AACtC,SAAO,IAAI,KAA4C;AACzD;AAaO,SAAS,sBAAsB,SAA0B;AAC9D,QAAM,SAAS,IAAI,KAA4C;AAG/D,QAAM,kBAAkB,IAAI,KAA4C;AACxE,kBAAgB,MAAM,IAAI,OAAO,IAAI,MAAM;AAE3C,SAAO;AACT;AAiBO,SAAS,mBACd,YACA,SAIS;AACT,QAAM,eAAe,IAAI,KAA4C;AAGrE,MAAI,QAAQ,YAAY;AACtB,eAAW,MAAM,QAAQ,YAAY;AACnC,mBAAa,IAAI,KAAK,EAAE;AAAA,IAC1B;AAAA,EACF;AAGA,UAAQ,OAAO,YAAY;AAG3B,QAAM,gBAAgB,IAAI,KAA4C;AACtE,gBAAc,MAAM,IAAI,UAAU,IAAI,YAAY;AAElD,SAAO;AACT;","names":[]}
@@ -0,0 +1,208 @@
1
+ import * as hono from 'hono';
2
+ import { Logger } from '@parsrun/core';
3
+
4
+ /**
5
+ * Database adapter interface
6
+ * Implement this for your database (Drizzle, Prisma, etc.)
7
+ */
8
+ interface DatabaseAdapter {
9
+ /** Execute raw SQL query */
10
+ execute(sql: string): Promise<unknown>;
11
+ /** Check connection */
12
+ ping?(): Promise<boolean>;
13
+ }
14
+ /**
15
+ * Module manifest for registering modules
16
+ */
17
+ interface ModuleManifest {
18
+ /** Unique module name */
19
+ name: string;
20
+ /** Module version */
21
+ version: string;
22
+ /** Module description */
23
+ description: string;
24
+ /** Required permissions for this module */
25
+ permissions: Record<string, string[]>;
26
+ /** Module dependencies (other module names) */
27
+ dependencies?: string[];
28
+ /** Register routes for this module */
29
+ registerRoutes: (app: HonoApp) => void;
30
+ /** Called when module is enabled */
31
+ onEnable?: () => Promise<void>;
32
+ /** Called when module is disabled */
33
+ onDisable?: () => Promise<void>;
34
+ }
35
+ /**
36
+ * Server configuration
37
+ */
38
+ interface ServerConfig {
39
+ /** Database adapter */
40
+ database: DatabaseAdapter;
41
+ /** CORS configuration */
42
+ cors?: CorsConfig;
43
+ /** Base path for API */
44
+ basePath?: string;
45
+ /** Cookie prefix for all cookies */
46
+ cookiePrefix?: string;
47
+ /** Logger instance */
48
+ logger?: Logger;
49
+ /** Custom context data */
50
+ custom?: Record<string, unknown>;
51
+ }
52
+ /**
53
+ * CORS configuration
54
+ */
55
+ interface CorsConfig {
56
+ /** Allowed origins */
57
+ origin: string | string[] | ((origin: string) => boolean);
58
+ /** Allow credentials */
59
+ credentials?: boolean;
60
+ /** Allowed methods */
61
+ methods?: string[];
62
+ /** Allowed headers */
63
+ allowedHeaders?: string[];
64
+ /** Exposed headers */
65
+ exposedHeaders?: string[];
66
+ /** Max age in seconds */
67
+ maxAge?: number;
68
+ }
69
+ /**
70
+ * User information in context
71
+ */
72
+ interface ContextUser {
73
+ id: string;
74
+ email: string | undefined;
75
+ tenantId: string | undefined;
76
+ role: string | undefined;
77
+ permissions: string[];
78
+ }
79
+ /**
80
+ * Tenant information in context
81
+ */
82
+ interface ContextTenant {
83
+ id: string;
84
+ slug: string | undefined;
85
+ name: string | undefined;
86
+ status: string;
87
+ }
88
+ /**
89
+ * Server context variables
90
+ * Available in Hono context via c.get()
91
+ */
92
+ interface ServerContextVariables {
93
+ /** Database adapter */
94
+ db: DatabaseAdapter;
95
+ /** Server configuration */
96
+ config: ServerConfig;
97
+ /** Enabled modules set */
98
+ enabledModules: Set<string>;
99
+ /** Current user (if authenticated) */
100
+ user: ContextUser | undefined;
101
+ /** Current tenant (if resolved) */
102
+ tenant: ContextTenant | undefined;
103
+ /** Request logger */
104
+ logger: Logger;
105
+ /** Request ID */
106
+ requestId: string;
107
+ /** Cookie prefix */
108
+ cookiePrefix: string | undefined;
109
+ /** Custom context data */
110
+ custom: Record<string, unknown>;
111
+ }
112
+ /**
113
+ * Hono app type with server context
114
+ */
115
+ type HonoApp = hono.Hono<{
116
+ Variables: ServerContextVariables;
117
+ }>;
118
+ /**
119
+ * Hono context type with server context
120
+ */
121
+ type HonoContext = hono.Context<{
122
+ Variables: ServerContextVariables;
123
+ }>;
124
+ /**
125
+ * Middleware next function
126
+ */
127
+ type HonoNext = () => Promise<void>;
128
+ /**
129
+ * Middleware function type
130
+ */
131
+ type Middleware = (c: HonoContext, next: HonoNext) => Promise<Response | void>;
132
+ /**
133
+ * Route handler function type
134
+ */
135
+ type RouteHandler = (c: HonoContext) => Promise<Response> | Response;
136
+ /**
137
+ * Permission check input
138
+ */
139
+ interface PermissionCheck {
140
+ /** Resource name (e.g., "users", "items") */
141
+ resource: string;
142
+ /** Action name (e.g., "read", "create", "update", "delete") */
143
+ action: string;
144
+ /** Permission scope */
145
+ scope?: "tenant" | "global" | "own";
146
+ }
147
+ /**
148
+ * Permission definition
149
+ */
150
+ interface PermissionDefinition {
151
+ /** Permission name (e.g., "users:read") */
152
+ name: string;
153
+ /** Resource part */
154
+ resource: string;
155
+ /** Action part */
156
+ action: string;
157
+ /** Description */
158
+ description?: string;
159
+ /** Scope */
160
+ scope?: "tenant" | "global" | "own";
161
+ }
162
+ /**
163
+ * Role definition
164
+ */
165
+ interface RoleDefinition {
166
+ /** Role name */
167
+ name: string;
168
+ /** Display name */
169
+ displayName?: string;
170
+ /** Description */
171
+ description?: string;
172
+ /** Permissions assigned to this role */
173
+ permissions: string[];
174
+ /** Is this a system role */
175
+ isSystem?: boolean;
176
+ }
177
+ /**
178
+ * Standard API response structure
179
+ */
180
+ interface ApiResponse<T = unknown> {
181
+ success: boolean;
182
+ data?: T;
183
+ error?: {
184
+ code: string;
185
+ message: string;
186
+ details?: Record<string, unknown> | undefined;
187
+ };
188
+ meta?: {
189
+ page?: number | undefined;
190
+ limit?: number | undefined;
191
+ total?: number | undefined;
192
+ requestId?: string | undefined;
193
+ } | undefined;
194
+ }
195
+ /**
196
+ * Create a success response
197
+ */
198
+ declare function success<T>(data: T, meta?: ApiResponse["meta"]): ApiResponse<T>;
199
+ /**
200
+ * Create an error response
201
+ */
202
+ declare function error(code: string, message: string, details?: Record<string, unknown>): ApiResponse<never>;
203
+ /**
204
+ * Generate a request ID
205
+ */
206
+ declare function generateRequestId(): string;
207
+
208
+ export { type ApiResponse, type ContextTenant, type ContextUser, type CorsConfig, type DatabaseAdapter, type HonoApp, type HonoContext, type HonoNext, type Middleware, type ModuleManifest, type PermissionCheck, type PermissionDefinition, type RoleDefinition, type RouteHandler, type ServerConfig, type ServerContextVariables, error, generateRequestId, success };
@@ -0,0 +1,23 @@
1
+ // src/context.ts
2
+ function success(data, meta) {
3
+ return {
4
+ success: true,
5
+ data,
6
+ meta: meta ?? void 0
7
+ };
8
+ }
9
+ function error(code, message, details) {
10
+ return {
11
+ success: false,
12
+ error: { code, message, details: details ?? void 0 }
13
+ };
14
+ }
15
+ function generateRequestId() {
16
+ return crypto.randomUUID();
17
+ }
18
+ export {
19
+ error,
20
+ generateRequestId,
21
+ success
22
+ };
23
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.ts"],"sourcesContent":["/**\n * @parsrun/server - Server Context\n * Type definitions for server context and configuration\n */\n\nimport type { Logger } from \"@parsrun/core\";\n\n/**\n * Database adapter interface\n * Implement this for your database (Drizzle, Prisma, etc.)\n */\nexport interface DatabaseAdapter {\n /** Execute raw SQL query */\n execute(sql: string): Promise<unknown>;\n /** Check connection */\n ping?(): Promise<boolean>;\n}\n\n/**\n * Module manifest for registering modules\n */\nexport interface ModuleManifest {\n /** Unique module name */\n name: string;\n /** Module version */\n version: string;\n /** Module description */\n description: string;\n /** Required permissions for this module */\n permissions: Record<string, string[]>;\n /** Module dependencies (other module names) */\n dependencies?: string[];\n /** Register routes for this module */\n registerRoutes: (app: HonoApp) => void;\n /** Called when module is enabled */\n onEnable?: () => Promise<void>;\n /** Called when module is disabled */\n onDisable?: () => Promise<void>;\n}\n\n/**\n * Server configuration\n */\nexport interface ServerConfig {\n /** Database adapter */\n database: DatabaseAdapter;\n /** CORS configuration */\n cors?: CorsConfig;\n /** Base path for API */\n basePath?: string;\n /** Cookie prefix for all cookies */\n cookiePrefix?: string;\n /** Logger instance */\n logger?: Logger;\n /** Custom context data */\n custom?: Record<string, unknown>;\n}\n\n/**\n * CORS configuration\n */\nexport interface CorsConfig {\n /** Allowed origins */\n origin: string | string[] | ((origin: string) => boolean);\n /** Allow credentials */\n credentials?: boolean;\n /** Allowed methods */\n methods?: string[];\n /** Allowed headers */\n allowedHeaders?: string[];\n /** Exposed headers */\n exposedHeaders?: string[];\n /** Max age in seconds */\n maxAge?: number;\n}\n\n/**\n * User information in context\n */\nexport interface ContextUser {\n id: string;\n email: string | undefined;\n tenantId: string | undefined;\n role: string | undefined;\n permissions: string[];\n}\n\n/**\n * Tenant information in context\n */\nexport interface ContextTenant {\n id: string;\n slug: string | undefined;\n name: string | undefined;\n status: string;\n}\n\n/**\n * Server context variables\n * Available in Hono context via c.get()\n */\nexport interface ServerContextVariables {\n /** Database adapter */\n db: DatabaseAdapter;\n /** Server configuration */\n config: ServerConfig;\n /** Enabled modules set */\n enabledModules: Set<string>;\n /** Current user (if authenticated) */\n user: ContextUser | undefined;\n /** Current tenant (if resolved) */\n tenant: ContextTenant | undefined;\n /** Request logger */\n logger: Logger;\n /** Request ID */\n requestId: string;\n /** Cookie prefix */\n cookiePrefix: string | undefined;\n /** Custom context data */\n custom: Record<string, unknown>;\n}\n\n/**\n * Hono app type with server context\n */\nexport type HonoApp = import(\"hono\").Hono<{ Variables: ServerContextVariables }>;\n\n/**\n * Hono context type with server context\n */\nexport type HonoContext = import(\"hono\").Context<{ Variables: ServerContextVariables }>;\n\n/**\n * Middleware next function\n */\nexport type HonoNext = () => Promise<void>;\n\n/**\n * Middleware function type\n */\nexport type Middleware = (c: HonoContext, next: HonoNext) => Promise<Response | void>;\n\n/**\n * Route handler function type\n */\nexport type RouteHandler = (c: HonoContext) => Promise<Response> | Response;\n\n/**\n * Permission check input\n */\nexport interface PermissionCheck {\n /** Resource name (e.g., \"users\", \"items\") */\n resource: string;\n /** Action name (e.g., \"read\", \"create\", \"update\", \"delete\") */\n action: string;\n /** Permission scope */\n scope?: \"tenant\" | \"global\" | \"own\";\n}\n\n/**\n * Permission definition\n */\nexport interface PermissionDefinition {\n /** Permission name (e.g., \"users:read\") */\n name: string;\n /** Resource part */\n resource: string;\n /** Action part */\n action: string;\n /** Description */\n description?: string;\n /** Scope */\n scope?: \"tenant\" | \"global\" | \"own\";\n}\n\n/**\n * Role definition\n */\nexport interface RoleDefinition {\n /** Role name */\n name: string;\n /** Display name */\n displayName?: string;\n /** Description */\n description?: string;\n /** Permissions assigned to this role */\n permissions: string[];\n /** Is this a system role */\n isSystem?: boolean;\n}\n\n/**\n * Standard API response structure\n */\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: Record<string, unknown> | undefined;\n };\n meta?: {\n page?: number | undefined;\n limit?: number | undefined;\n total?: number | undefined;\n requestId?: string | undefined;\n } | undefined;\n}\n\n/**\n * Create a success response\n */\nexport function success<T>(data: T, meta?: ApiResponse[\"meta\"]): ApiResponse<T> {\n return {\n success: true,\n data,\n meta: meta ?? undefined,\n };\n}\n\n/**\n * Create an error response\n */\nexport function error(\n code: string,\n message: string,\n details?: Record<string, unknown>\n): ApiResponse<never> {\n return {\n success: false,\n error: { code, message, details: details ?? undefined },\n };\n}\n\n/**\n * Generate a request ID\n */\nexport function generateRequestId(): string {\n return crypto.randomUUID();\n}\n"],"mappings":";AAqNO,SAAS,QAAW,MAAS,MAA4C;AAC9E,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,MAAM,QAAQ;AAAA,EAChB;AACF;AAKO,SAAS,MACd,MACA,SACA,SACoB;AACpB,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,EAAE,MAAM,SAAS,SAAS,WAAW,OAAU;AAAA,EACxD;AACF;AAKO,SAAS,oBAA4B;AAC1C,SAAO,OAAO,WAAW;AAC3B;","names":[]}
@@ -0,0 +1,81 @@
1
+ import * as hono_utils_http_status from 'hono/utils/http-status';
2
+ import * as hono from 'hono';
3
+ import { HonoApp, ServerContextVariables } from './context.js';
4
+ import '@parsrun/core';
5
+
6
+ /**
7
+ * Health check status
8
+ */
9
+ type HealthStatus = "healthy" | "degraded" | "unhealthy";
10
+ /**
11
+ * Health check result
12
+ */
13
+ interface HealthCheckResult {
14
+ status: HealthStatus;
15
+ message?: string;
16
+ latency?: number;
17
+ }
18
+ /**
19
+ * Health check function
20
+ */
21
+ type HealthCheck = () => Promise<HealthCheckResult> | HealthCheckResult;
22
+ /**
23
+ * Health response
24
+ */
25
+ interface HealthResponse {
26
+ status: HealthStatus;
27
+ timestamp: string;
28
+ uptime: number;
29
+ checks: Record<string, HealthCheckResult>;
30
+ }
31
+ /**
32
+ * Health check options
33
+ */
34
+ interface HealthCheckOptions {
35
+ /** Custom health checks */
36
+ checks?: Record<string, HealthCheck>;
37
+ /** Include detailed info (disable in production) */
38
+ detailed?: boolean;
39
+ }
40
+ /**
41
+ * Create health check router
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const health = createHealthRouter({
46
+ * checks: {
47
+ * redis: async () => {
48
+ * await redis.ping();
49
+ * return { status: 'healthy' };
50
+ * },
51
+ * external: async () => {
52
+ * const res = await fetch('https://api.example.com/health');
53
+ * return { status: res.ok ? 'healthy' : 'unhealthy' };
54
+ * },
55
+ * },
56
+ * });
57
+ *
58
+ * app.route('/health', health);
59
+ * // GET /health - Full health check
60
+ * // GET /health/live - Liveness probe
61
+ * // GET /health/ready - Readiness probe
62
+ * ```
63
+ */
64
+ declare function createHealthRouter(options?: HealthCheckOptions): HonoApp;
65
+ /**
66
+ * Simple health endpoint handler
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * app.get('/health', healthHandler);
71
+ * ```
72
+ */
73
+ declare function healthHandler(c: hono.Context<{
74
+ Variables: ServerContextVariables;
75
+ }>): Promise<Response & hono.TypedResponse<{
76
+ status: string;
77
+ timestamp: string;
78
+ uptime: number;
79
+ }, hono_utils_http_status.ContentfulStatusCode, "json">>;
80
+
81
+ export { type HealthCheck, type HealthCheckOptions, type HealthCheckResult, type HealthResponse, type HealthStatus, createHealthRouter, healthHandler };