@spfn/core 0.1.0-alpha.88 → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +1046 -384
  2. package/dist/boss-D-fGtVgM.d.ts +187 -0
  3. package/dist/cache/index.d.ts +13 -33
  4. package/dist/cache/index.js +14 -703
  5. package/dist/cache/index.js.map +1 -1
  6. package/dist/codegen/index.d.ts +167 -17
  7. package/dist/codegen/index.js +76 -1419
  8. package/dist/codegen/index.js.map +1 -1
  9. package/dist/config/index.d.ts +1191 -0
  10. package/dist/config/index.js +264 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/db/index.d.ts +728 -59
  13. package/dist/db/index.js +1028 -1225
  14. package/dist/db/index.js.map +1 -1
  15. package/dist/env/index.d.ts +579 -308
  16. package/dist/env/index.js +438 -930
  17. package/dist/env/index.js.map +1 -1
  18. package/dist/errors/index.d.ts +417 -29
  19. package/dist/errors/index.js +359 -98
  20. package/dist/errors/index.js.map +1 -1
  21. package/dist/event/index.d.ts +108 -0
  22. package/dist/event/index.js +122 -0
  23. package/dist/event/index.js.map +1 -0
  24. package/dist/job/index.d.ts +172 -0
  25. package/dist/job/index.js +361 -0
  26. package/dist/job/index.js.map +1 -0
  27. package/dist/logger/index.d.ts +20 -79
  28. package/dist/logger/index.js +82 -387
  29. package/dist/logger/index.js.map +1 -1
  30. package/dist/middleware/index.d.ts +2 -11
  31. package/dist/middleware/index.js +49 -703
  32. package/dist/middleware/index.js.map +1 -1
  33. package/dist/nextjs/index.d.ts +120 -0
  34. package/dist/nextjs/index.js +416 -0
  35. package/dist/nextjs/index.js.map +1 -0
  36. package/dist/{client/nextjs/index.d.ts → nextjs/server.d.ts} +288 -262
  37. package/dist/nextjs/server.js +568 -0
  38. package/dist/nextjs/server.js.map +1 -0
  39. package/dist/route/index.d.ts +686 -25
  40. package/dist/route/index.js +440 -1287
  41. package/dist/route/index.js.map +1 -1
  42. package/dist/route/types.d.ts +38 -0
  43. package/dist/route/types.js +3 -0
  44. package/dist/route/types.js.map +1 -0
  45. package/dist/server/index.d.ts +201 -67
  46. package/dist/server/index.js +921 -3182
  47. package/dist/server/index.js.map +1 -1
  48. package/dist/types-BGl4QL1w.d.ts +77 -0
  49. package/dist/types-DRG2XMTR.d.ts +157 -0
  50. package/package.json +52 -47
  51. package/dist/auto-loader-JFaZ9gON.d.ts +0 -80
  52. package/dist/client/index.d.ts +0 -358
  53. package/dist/client/index.js +0 -357
  54. package/dist/client/index.js.map +0 -1
  55. package/dist/client/nextjs/index.js +0 -371
  56. package/dist/client/nextjs/index.js.map +0 -1
  57. package/dist/codegen/generators/index.d.ts +0 -19
  58. package/dist/codegen/generators/index.js +0 -1404
  59. package/dist/codegen/generators/index.js.map +0 -1
  60. package/dist/database-errors-BNNmLTJE.d.ts +0 -86
  61. package/dist/events/index.d.ts +0 -183
  62. package/dist/events/index.js +0 -77
  63. package/dist/events/index.js.map +0 -1
  64. package/dist/index-DHiAqhKv.d.ts +0 -101
  65. package/dist/index.d.ts +0 -8
  66. package/dist/index.js +0 -3674
  67. package/dist/index.js.map +0 -1
  68. package/dist/types/index.d.ts +0 -121
  69. package/dist/types/index.js +0 -38
  70. package/dist/types/index.js.map +0 -1
  71. package/dist/types-BXibIEyj.d.ts +0 -60
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Logger Type Definitions
3
+ *
4
+ * 로깅 시스템 타입 정의
5
+ *
6
+ * ✅ 구현 완료:
7
+ * - LogLevel 타입 정의
8
+ * - LogMetadata 인터페이스
9
+ * - Transport 인터페이스
10
+ * - 환경별 설정 타입
11
+ *
12
+ * 🔗 관련 파일:
13
+ * - src/logger/logger.ts (Logger 클래스)
14
+ * - src/logger/transports/ (Transport 구현체)
15
+ * - src/logger/config.ts (설정)
16
+ */
17
+ /**
18
+ * 로그 레벨
19
+ * debug < info < warn < error < fatal
20
+ */
21
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
22
+ /**
23
+ * 로그 메타데이터
24
+ */
25
+ interface LogMetadata {
26
+ timestamp: Date;
27
+ level: LogLevel;
28
+ message: string;
29
+ module?: string;
30
+ error?: Error;
31
+ context?: Record<string, unknown>;
32
+ }
33
+ /**
34
+ * Transport 인터페이스
35
+ * 모든 Transport는 이 인터페이스를 구현해야 함
36
+ */
37
+ interface Transport {
38
+ /**
39
+ * Transport 이름
40
+ */
41
+ name: string;
42
+ /**
43
+ * 최소 로그 레벨 (이 레벨 이상만 처리)
44
+ */
45
+ level: LogLevel;
46
+ /**
47
+ * 활성화 여부
48
+ */
49
+ enabled: boolean;
50
+ /**
51
+ * 로그 처리 함수
52
+ */
53
+ log(metadata: LogMetadata): Promise<void>;
54
+ /**
55
+ * Transport 종료 (리소스 정리)
56
+ */
57
+ close?(): Promise<void>;
58
+ }
59
+ /**
60
+ * Logger 설정
61
+ */
62
+ interface LoggerConfig {
63
+ /**
64
+ * 기본 로그 레벨
65
+ */
66
+ level: LogLevel;
67
+ /**
68
+ * 모듈명 (context)
69
+ */
70
+ module?: string;
71
+ /**
72
+ * Transport 리스트
73
+ */
74
+ transports: Transport[];
75
+ }
76
+
77
+ export type { LogLevel as L, Transport as T, LoggerConfig as a };
@@ -0,0 +1,157 @@
1
+ import { TSchema, Static } from '@sinclair/typebox';
2
+ import { ErrorRegistry, ErrorRegistryInput } from '@spfn/core/errors';
3
+ import { RouteDef, RouteInput } from '@spfn/core/route';
4
+
5
+ /**
6
+ * Extract structured input from RouteInput
7
+ */
8
+ type StructuredInput<TInput extends RouteInput> = {
9
+ params: TInput['params'] extends TSchema ? Static<TInput['params']> : {};
10
+ query: TInput['query'] extends TSchema ? Static<TInput['query']> : {};
11
+ body: TInput['body'] extends TSchema ? Static<TInput['body']> : {};
12
+ headers: TInput['headers'] extends TSchema ? Static<TInput['headers']> : {};
13
+ cookies: TInput['cookies'] extends TSchema ? Static<TInput['cookies']> : {};
14
+ };
15
+ /**
16
+ * Infer route input type
17
+ */
18
+ type InferRouteInput<TRoute> = TRoute extends RouteDef<infer TInput, any, any> ? StructuredInput<TInput> : never;
19
+ /**
20
+ * Infer route output type
21
+ */
22
+ type InferRouteOutput<TRoute> = TRoute extends RouteDef<any, any, infer TResponse> ? TResponse : never;
23
+ /**
24
+ * Cookie options for setCookie
25
+ */
26
+ interface CookieOptions {
27
+ httpOnly?: boolean;
28
+ secure?: boolean;
29
+ sameSite?: 'strict' | 'lax' | 'none';
30
+ maxAge?: number;
31
+ path?: string;
32
+ domain?: string;
33
+ }
34
+ /**
35
+ * Cookie to set in response
36
+ */
37
+ interface SetCookie {
38
+ name: string;
39
+ value: string;
40
+ options?: CookieOptions;
41
+ }
42
+ /**
43
+ * Request interceptor - called before fetch
44
+ */
45
+ type RequestInterceptor = (url: string, init: RequestInit) => Promise<RequestInit> | RequestInit;
46
+ /**
47
+ * Response interceptor - called after fetch
48
+ */
49
+ type ResponseInterceptor = (response: Response, body: any) => Promise<{
50
+ response: Response;
51
+ body: any;
52
+ }> | {
53
+ response: Response;
54
+ body: any;
55
+ };
56
+ /**
57
+ * Client configuration
58
+ */
59
+ interface ApiConfig {
60
+ /**
61
+ * Base URL for RPC endpoint
62
+ *
63
+ * @default '/api/rpc'
64
+ * @example '/api/rpc', 'http://localhost:3000/api/rpc'
65
+ */
66
+ baseUrl?: string;
67
+ /**
68
+ * Default headers for all requests
69
+ */
70
+ headers?: Record<string, string>;
71
+ /**
72
+ * Request timeout in milliseconds
73
+ *
74
+ * @default 30000
75
+ */
76
+ timeout?: number;
77
+ /**
78
+ * Custom fetch implementation
79
+ */
80
+ fetch?: typeof fetch;
81
+ /**
82
+ * Global request interceptor
83
+ */
84
+ onRequest?: RequestInterceptor;
85
+ /**
86
+ * Global response interceptor
87
+ */
88
+ onResponse?: ResponseInterceptor;
89
+ /**
90
+ * Custom error registry for deserialization
91
+ *
92
+ * Core HTTP errors are automatically registered. Use this to add your custom application errors.
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * import { errorRegistry } from '@spfn/core/errors';
97
+ * import { authErrorRegistry } from '@myapp/auth/errors';
98
+ * import { PaymentFailedError } from '@/server/errors';
99
+ *
100
+ * const api = createApi<AppRouter>({
101
+ * errorRegistry: [errorRegistry, authErrorRegistry, PaymentFailedError]
102
+ * });
103
+ * ```
104
+ */
105
+ errorRegistry?: ErrorRegistry | ErrorRegistryInput[];
106
+ /**
107
+ * Enable debug logging
108
+ *
109
+ * @default false
110
+ */
111
+ debug?: boolean;
112
+ }
113
+ /**
114
+ * Per-call options
115
+ */
116
+ interface CallOptions {
117
+ /**
118
+ * Additional headers for this request
119
+ */
120
+ headers?: Record<string, string>;
121
+ /**
122
+ * Override cookies for this request
123
+ *
124
+ * Note: Cookies are automatically forwarded by the proxy.
125
+ * Use this only when you need to override them.
126
+ */
127
+ cookies?: Record<string, string>;
128
+ /**
129
+ * Request-specific interceptor
130
+ */
131
+ onRequest?: RequestInterceptor;
132
+ /**
133
+ * Response-specific interceptor
134
+ */
135
+ onResponse?: ResponseInterceptor;
136
+ /**
137
+ * Next.js-specific fetch options
138
+ *
139
+ * @example
140
+ * // Time-based revalidation
141
+ * { next: { revalidate: 60 } }
142
+ *
143
+ * // Disable cache
144
+ * { cache: 'no-store' }
145
+ *
146
+ * // Tag-based revalidation
147
+ * { next: { tags: ['users'] } }
148
+ */
149
+ fetchOptions?: RequestInit & {
150
+ next?: {
151
+ revalidate?: number | false;
152
+ tags?: string[];
153
+ };
154
+ };
155
+ }
156
+
157
+ export type { ApiConfig as A, CallOptions as C, InferRouteInput as I, RequestInterceptor as R, SetCookie as S, ResponseInterceptor as a, InferRouteOutput as b };
package/package.json CHANGED
@@ -1,31 +1,34 @@
1
1
  {
2
2
  "name": "@spfn/core",
3
- "version": "0.1.0-alpha.88",
3
+ "version": "0.2.0-beta.2",
4
4
  "description": "SPFN Framework Core - File-based routing, transactions, repository pattern",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
6
  "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js",
12
- "require": "./dist/index.js"
13
- },
14
7
  "./client": {
15
8
  "types": "./dist/client/index.d.ts",
16
9
  "import": "./dist/client/index.js",
17
10
  "require": "./dist/client/index.js"
18
11
  },
19
- "./client/nextjs": {
20
- "types": "./dist/client/nextjs/index.d.ts",
21
- "import": "./dist/client/nextjs/index.js",
22
- "require": "./dist/client/nextjs/index.js"
12
+ "./nextjs": {
13
+ "types": "./dist/nextjs/index.d.ts",
14
+ "import": "./dist/nextjs/index.js",
15
+ "require": "./dist/nextjs/index.js"
16
+ },
17
+ "./nextjs/server": {
18
+ "types": "./dist/nextjs/server.d.ts",
19
+ "import": "./dist/nextjs/server.js",
20
+ "require": "./dist/nextjs/server.js"
23
21
  },
24
22
  "./route": {
25
23
  "types": "./dist/route/index.d.ts",
26
24
  "import": "./dist/route/index.js",
27
25
  "require": "./dist/route/index.js"
28
26
  },
27
+ "./route/types": {
28
+ "types": "./dist/route/types.d.ts",
29
+ "import": "./dist/route/types.js",
30
+ "require": "./dist/route/types.js"
31
+ },
29
32
  "./db": {
30
33
  "types": "./dist/db/index.d.ts",
31
34
  "import": "./dist/db/index.js",
@@ -46,11 +49,6 @@
46
49
  "import": "./dist/middleware/index.js",
47
50
  "require": "./dist/middleware/index.js"
48
51
  },
49
- "./types": {
50
- "types": "./dist/types/index.d.ts",
51
- "import": "./dist/types/index.js",
52
- "require": "./dist/types/index.js"
53
- },
54
52
  "./cache": {
55
53
  "types": "./dist/cache/index.d.ts",
56
54
  "import": "./dist/cache/index.js",
@@ -71,20 +69,20 @@
71
69
  "import": "./dist/logger/index.js",
72
70
  "require": "./dist/logger/index.js"
73
71
  },
74
- "./events": {
75
- "types": "./dist/events/index.d.ts",
76
- "import": "./dist/events/index.js",
77
- "require": "./dist/events/index.js"
72
+ "./config": {
73
+ "types": "./dist/config/index.d.ts",
74
+ "import": "./dist/config/index.js",
75
+ "require": "./dist/config/index.js"
78
76
  },
79
- "./generators": {
80
- "types": "./dist/codegen/generators/index.d.ts",
81
- "import": "./dist/codegen/generators/index.js",
82
- "require": "./dist/codegen/generators/index.js"
77
+ "./job": {
78
+ "types": "./dist/job/index.d.ts",
79
+ "import": "./dist/job/index.js",
80
+ "require": "./dist/job/index.js"
83
81
  },
84
- "./codegen/generators": {
85
- "types": "./dist/codegen/generators/index.d.ts",
86
- "import": "./dist/codegen/generators/index.js",
87
- "require": "./dist/codegen/generators/index.js"
82
+ "./event": {
83
+ "types": "./dist/event/index.d.ts",
84
+ "import": "./dist/event/index.js",
85
+ "require": "./dist/event/index.js"
88
86
  }
89
87
  },
90
88
  "keywords": [
@@ -131,11 +129,12 @@
131
129
  "chalk": "^5.6.2",
132
130
  "chokidar": "^4.0.3",
133
131
  "dotenv": "^17.2.3",
134
- "drizzle-orm": "^0.44.7",
132
+ "drizzle-orm": "^0.45.0",
135
133
  "drizzle-typebox": "^0.1.0",
136
- "hono": "^4.9.0",
134
+ "hono": "^4.10.6",
137
135
  "jiti": "^2.6.1",
138
136
  "micromatch": "^4.0.8",
137
+ "pg-boss": "^11.1.2",
139
138
  "postgres": "^3.4.0",
140
139
  "typescript": "^5.3.3",
141
140
  "zod": "^4.1.11"
@@ -148,12 +147,18 @@
148
147
  "@types/node": "^20.11.0",
149
148
  "@vitest/coverage-v8": "^4.0.6",
150
149
  "drizzle-kit": "^0.31.6",
151
- "next": "^16.0.1",
150
+ "madge": "^8.0.0",
151
+ "next": "16.0.7",
152
152
  "tsup": "^8.5.0",
153
153
  "vitest": "^4.0.6"
154
154
  },
155
155
  "peerDependencies": {
156
- "next": "^16.0.1"
156
+ "next": "^15.0.0 || ^16.0.0"
157
+ },
158
+ "peerDependenciesMeta": {
159
+ "next": {
160
+ "optional": true
161
+ }
157
162
  },
158
163
  "files": [
159
164
  "dist",
@@ -166,25 +171,25 @@
166
171
  "tag": "alpha"
167
172
  },
168
173
  "scripts": {
169
- "build": "tsup",
174
+ "build": "pnpm check:circular && tsup",
170
175
  "dev": "tsup",
171
- "test": "vitest",
172
- "test:unit": "vitest --config vitest.unit.config.ts",
173
- "test:integration": "vitest --config vitest.integration.config.ts",
176
+ "test": "vitest run",
177
+ "test:watch": "vitest",
174
178
  "test:coverage": "vitest run --config vitest.unit.config.ts --coverage",
175
- "test:logger": "vitest src/logger",
176
- "test:errors": "vitest src/errors",
177
- "test:codegen": "vitest src/codegen",
178
- "test:route": "vitest src/route",
179
- "test:client": "vitest src/client",
180
- "test:middleware": "vitest src/middleware",
181
- "test:env": "vitest src/env",
182
- "test:cache": "vitest src/cache --config vitest.integration.config.ts",
183
- "test:db": "vitest src/db --config vitest.integration.config.ts",
184
- "test:server": "vitest src/server --config vitest.integration.config.ts",
179
+ "test:logger": "vitest run src/logger",
180
+ "test:errors": "vitest run src/errors",
181
+ "test:codegen": "vitest run src/codegen",
182
+ "test:route": "vitest run src/route",
183
+ "test:client": "vitest run src/client",
184
+ "test:middleware": "vitest run src/middleware",
185
+ "test:env": "vitest run src/env",
186
+ "test:cache": "vitest run src/cache --config vitest.integration.config.ts",
187
+ "test:db": "vitest run src/db --config vitest.integration.config.ts",
188
+ "test:server": "vitest run src/server --config vitest.integration.config.ts",
185
189
  "docker:test:up": "docker compose -f docker-compose.test.yml up -d",
186
190
  "docker:test:down": "docker compose -f docker-compose.test.yml down",
187
191
  "docker:test:logs": "docker compose -f docker-compose.test.yml logs -f",
192
+ "check:circular": "madge --circular --extensions ts src/",
188
193
  "type-check": "tsc --noEmit"
189
194
  }
190
195
  }
@@ -1,80 +0,0 @@
1
- import { MiddlewareHandler, Hono } from 'hono';
2
-
3
- declare module 'hono' {
4
- interface ContextVariableMap {
5
- _skipMiddlewares?: string[];
6
- }
7
- }
8
- /**
9
- * AutoRouteLoader: Simplified File-based Routing System
10
- *
11
- * Features:
12
- * - Auto-discovery: Scans routes directory and auto-registers
13
- * - Dynamic routes: [id] → :id, [...slug] → *
14
- * - Statistics: Route registration stats for dashboard
15
- * - Grouping: Natural grouping by directory structure
16
- */
17
- type RouteInfo = {
18
- path: string;
19
- file: string;
20
- meta?: {
21
- description?: string;
22
- tags?: string[];
23
- auth?: boolean;
24
- [key: string]: unknown;
25
- };
26
- priority: number;
27
- };
28
- type RouteStats = {
29
- total: number;
30
- byPriority: {
31
- static: number;
32
- dynamic: number;
33
- catchAll: number;
34
- };
35
- byTag: Record<string, number>;
36
- routes: RouteInfo[];
37
- };
38
- declare class AutoRouteLoader {
39
- private routesDir;
40
- private routes;
41
- private readonly debug;
42
- private readonly middlewares;
43
- constructor(routesDir: string, debug?: boolean, middlewares?: Array<{
44
- name: string;
45
- handler: MiddlewareHandler;
46
- }>);
47
- load(app: Hono): Promise<RouteStats>;
48
- /**
49
- * Load routes from an external directory (e.g., from SPFN function packages)
50
- * Reads package.json spfn.prefix and mounts routes under that prefix
51
- *
52
- * @param app - Hono app instance
53
- * @param routesDir - Directory containing route handlers
54
- * @param packageName - Name of the package (for logging)
55
- * @param prefix - Optional prefix to mount routes under (from package.json spfn.prefix)
56
- * @returns Route statistics
57
- */
58
- loadExternalRoutes(app: Hono, routesDir: string, packageName: string, prefix?: string): Promise<RouteStats>;
59
- getStats(): RouteStats;
60
- private scanFiles;
61
- private isValidRouteFile;
62
- private loadRoute;
63
- private extractContractPaths;
64
- private calculateContractPriority;
65
- private validateModule;
66
- private registerContractBasedMiddlewares;
67
- private categorizeAndLogError;
68
- private logStats;
69
- }
70
- declare function loadRoutes(app: Hono, options?: {
71
- routesDir?: string;
72
- debug?: boolean;
73
- middlewares?: Array<{
74
- name: string;
75
- handler: MiddlewareHandler;
76
- }>;
77
- includeFunctionRoutes?: boolean;
78
- }): Promise<RouteStats>;
79
-
80
- export { AutoRouteLoader as A, type RouteInfo as R, type RouteStats as a, loadRoutes as l };