@gencow/core 0.1.2 → 0.1.3
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/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/reactive.d.ts +76 -0
- package/dist/reactive.js +42 -0
- package/package.json +34 -35
- package/src/index.ts +2 -2
- package/src/reactive.ts +98 -0
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Provides: query, mutation, storage, scheduler, auth
|
|
5
5
|
* All with Convex-compatible DX patterns.
|
|
6
6
|
*/
|
|
7
|
-
export type { GencowCtx, AuthCtx, UserIdentity, QueryDef, MutationDef, RealtimeCtx } from "./reactive";
|
|
8
|
-
export { query, mutation, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations } from "./reactive";
|
|
7
|
+
export type { GencowCtx, AuthCtx, UserIdentity, QueryDef, MutationDef, RealtimeCtx, HttpActionDef, HttpActionRequest, HttpActionResponse, HttpActionHandler } from "./reactive";
|
|
8
|
+
export { query, mutation, httpAction, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations, getRegisteredHttpActions } from "./reactive";
|
|
9
9
|
export type { Storage } from "./storage";
|
|
10
10
|
export { createScheduler, getSchedulerInfo } from "./scheduler";
|
|
11
11
|
export type { Scheduler } from "./scheduler";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides: query, mutation, storage, scheduler, auth
|
|
5
5
|
* All with Convex-compatible DX patterns.
|
|
6
6
|
*/
|
|
7
|
-
export { query, mutation, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations } from "./reactive";
|
|
7
|
+
export { query, mutation, httpAction, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations, getRegisteredHttpActions } from "./reactive";
|
|
8
8
|
export { createScheduler, getSchedulerInfo } from "./scheduler";
|
|
9
9
|
export { v, parseArgs, GencowValidationError } from "./v";
|
|
10
10
|
export { withRetry } from "./retry";
|
package/dist/reactive.d.ts
CHANGED
|
@@ -49,6 +49,38 @@ export interface GencowCtx {
|
|
|
49
49
|
}
|
|
50
50
|
type QueryHandler<TArgs = any, TReturn = any> = (ctx: GencowCtx, args: TArgs) => Promise<TReturn>;
|
|
51
51
|
type MutationHandler<TArgs = any, TReturn = any> = (ctx: GencowCtx, args: TArgs) => Promise<TReturn>;
|
|
52
|
+
/**
|
|
53
|
+
* httpAction 핸들러의 Request/Response 타입.
|
|
54
|
+
* Hono의 Context를 직접 받아 full HTTP 제어 가능.
|
|
55
|
+
*/
|
|
56
|
+
export type HttpActionHandler = (ctx: GencowCtx, req: HttpActionRequest) => Promise<HttpActionResponse>;
|
|
57
|
+
export interface HttpActionRequest {
|
|
58
|
+
/** HTTP method (GET, POST, PUT, DELETE, PATCH) */
|
|
59
|
+
method: string;
|
|
60
|
+
/** Full URL */
|
|
61
|
+
url: string;
|
|
62
|
+
/** URL path (e.g. /api/cli/auth-start) */
|
|
63
|
+
path: string;
|
|
64
|
+
/** Route params (e.g. { id: "abc" } for /api/apps/:id) */
|
|
65
|
+
params: Record<string, string>;
|
|
66
|
+
/** Query string params */
|
|
67
|
+
query: Record<string, string>;
|
|
68
|
+
/** Request headers */
|
|
69
|
+
headers: Record<string, string>;
|
|
70
|
+
/** Parse JSON body */
|
|
71
|
+
json: <T = unknown>() => Promise<T>;
|
|
72
|
+
/** Parse form data */
|
|
73
|
+
formData: () => Promise<FormData>;
|
|
74
|
+
/** Raw body as ArrayBuffer */
|
|
75
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
76
|
+
/** Raw body as text */
|
|
77
|
+
text: () => Promise<string>;
|
|
78
|
+
}
|
|
79
|
+
export interface HttpActionResponse {
|
|
80
|
+
status?: number;
|
|
81
|
+
headers?: Record<string, string>;
|
|
82
|
+
body?: unknown;
|
|
83
|
+
}
|
|
52
84
|
export interface QueryDef<TSchema = any, TReturn = any> {
|
|
53
85
|
key: string;
|
|
54
86
|
handler: QueryHandler<InferArgs<TSchema>, TReturn>;
|
|
@@ -67,6 +99,17 @@ export interface MutationDef<TSchema = any, TReturn = any> {
|
|
|
67
99
|
_args?: InferArgs<TSchema>;
|
|
68
100
|
_return?: TReturn;
|
|
69
101
|
}
|
|
102
|
+
/** httpAction 정의. 커스텀 HTTP 엔드포인트를 선언적으로 등록. */
|
|
103
|
+
export interface HttpActionDef {
|
|
104
|
+
/** HTTP method */
|
|
105
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
106
|
+
/** URL path (Hono 패턴 — /api/cli/:code 형태 지원) */
|
|
107
|
+
path: string;
|
|
108
|
+
/** true = 인증 없이 접근 가능, false(기본) = auth 필수 */
|
|
109
|
+
isPublic: boolean;
|
|
110
|
+
/** 핸들러 */
|
|
111
|
+
handler: HttpActionHandler;
|
|
112
|
+
}
|
|
70
113
|
declare global {
|
|
71
114
|
var __gencow_queryRegistry: Map<string, QueryDef<any, any>>;
|
|
72
115
|
var __gencow_mutationRegistry: (MutationDef<any, any> & {
|
|
@@ -74,6 +117,7 @@ declare global {
|
|
|
74
117
|
})[];
|
|
75
118
|
var __gencow_subscribers: Map<string, Set<WSContext>>;
|
|
76
119
|
var __gencow_connectedClients: Set<WSContext>;
|
|
120
|
+
var __gencow_httpActionRegistry: HttpActionDef[];
|
|
77
121
|
}
|
|
78
122
|
export declare function query<TSchema = any, TReturn = any>(key: string, handlerOrDef: QueryHandler<InferArgs<TSchema>, TReturn> | {
|
|
79
123
|
args?: TSchema;
|
|
@@ -87,6 +131,38 @@ export declare function mutation<TSchema = any, TReturn = any>(invalidatesOrDef:
|
|
|
87
131
|
invalidates: string[];
|
|
88
132
|
handler: MutationHandler<InferArgs<TSchema>, TReturn>;
|
|
89
133
|
}, handler?: MutationHandler<InferArgs<TSchema>, TReturn>, name?: string): MutationDef<TSchema, TReturn>;
|
|
134
|
+
/**
|
|
135
|
+
* 커스텀 HTTP 엔드포인트를 선언적으로 등록합니다.
|
|
136
|
+
* query/mutation은 RPC 패턴이지만, httpAction은 RESTful HTTP 라우트를 직접 정의합니다.
|
|
137
|
+
*
|
|
138
|
+
* 사용 사례:
|
|
139
|
+
* - CLI Device Auth (POST /api/cli/auth-start)
|
|
140
|
+
* - 파일 업로드 (POST /api/apps/:id/deploy)
|
|
141
|
+
* - Webhook 수신
|
|
142
|
+
* - 외부 서비스 콜백
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* import { httpAction } from "@gencow/core";
|
|
147
|
+
*
|
|
148
|
+
* export const authStart = httpAction({
|
|
149
|
+
* method: "POST",
|
|
150
|
+
* path: "/api/cli/auth-start",
|
|
151
|
+
* public: true,
|
|
152
|
+
* handler: async (ctx, req) => {
|
|
153
|
+
* const code = crypto.randomUUID().slice(0, 8);
|
|
154
|
+
* return { body: { code, url: `https://gencow.com/cli-auth?code=${code}` } };
|
|
155
|
+
* },
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export declare function httpAction(def: {
|
|
160
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
161
|
+
path: string;
|
|
162
|
+
public?: boolean;
|
|
163
|
+
handler: HttpActionHandler;
|
|
164
|
+
}): HttpActionDef;
|
|
165
|
+
export declare function getRegisteredHttpActions(): HttpActionDef[];
|
|
90
166
|
export declare function subscribe(queryKey: string, ws: WSContext): void;
|
|
91
167
|
export declare function unsubscribe(ws: WSContext): void;
|
|
92
168
|
/** Register a raw WS connection without any query subscription (e.g. admin dashboard) */
|
package/dist/reactive.js
CHANGED
|
@@ -6,8 +6,11 @@ if (!globalThis.__gencow_subscribers)
|
|
|
6
6
|
globalThis.__gencow_subscribers = new Map();
|
|
7
7
|
if (!globalThis.__gencow_connectedClients)
|
|
8
8
|
globalThis.__gencow_connectedClients = new Set();
|
|
9
|
+
if (!globalThis.__gencow_httpActionRegistry)
|
|
10
|
+
globalThis.__gencow_httpActionRegistry = [];
|
|
9
11
|
const queryRegistry = globalThis.__gencow_queryRegistry;
|
|
10
12
|
const mutationRegistry = globalThis.__gencow_mutationRegistry;
|
|
13
|
+
const httpActionRegistry = globalThis.__gencow_httpActionRegistry;
|
|
11
14
|
const subscribers = globalThis.__gencow_subscribers;
|
|
12
15
|
/**
|
|
13
16
|
* Every WebSocket client that ever establishes a connection is tracked here.
|
|
@@ -63,6 +66,45 @@ export function mutation(invalidatesOrDef, handler, name) {
|
|
|
63
66
|
mutationRegistry.push(def);
|
|
64
67
|
return def;
|
|
65
68
|
}
|
|
69
|
+
// ─── httpAction (커스텀 HTTP 엔드포인트) ────────────────
|
|
70
|
+
/**
|
|
71
|
+
* 커스텀 HTTP 엔드포인트를 선언적으로 등록합니다.
|
|
72
|
+
* query/mutation은 RPC 패턴이지만, httpAction은 RESTful HTTP 라우트를 직접 정의합니다.
|
|
73
|
+
*
|
|
74
|
+
* 사용 사례:
|
|
75
|
+
* - CLI Device Auth (POST /api/cli/auth-start)
|
|
76
|
+
* - 파일 업로드 (POST /api/apps/:id/deploy)
|
|
77
|
+
* - Webhook 수신
|
|
78
|
+
* - 외부 서비스 콜백
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { httpAction } from "@gencow/core";
|
|
83
|
+
*
|
|
84
|
+
* export const authStart = httpAction({
|
|
85
|
+
* method: "POST",
|
|
86
|
+
* path: "/api/cli/auth-start",
|
|
87
|
+
* public: true,
|
|
88
|
+
* handler: async (ctx, req) => {
|
|
89
|
+
* const code = crypto.randomUUID().slice(0, 8);
|
|
90
|
+
* return { body: { code, url: `https://gencow.com/cli-auth?code=${code}` } };
|
|
91
|
+
* },
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function httpAction(def) {
|
|
96
|
+
const actionDef = {
|
|
97
|
+
method: def.method,
|
|
98
|
+
path: def.path,
|
|
99
|
+
isPublic: def.public === true,
|
|
100
|
+
handler: def.handler,
|
|
101
|
+
};
|
|
102
|
+
httpActionRegistry.push(actionDef);
|
|
103
|
+
return actionDef;
|
|
104
|
+
}
|
|
105
|
+
export function getRegisteredHttpActions() {
|
|
106
|
+
return [...httpActionRegistry];
|
|
107
|
+
}
|
|
66
108
|
// ─── WebSocket subscription management ──────────────────
|
|
67
109
|
export function subscribe(queryKey, ws) {
|
|
68
110
|
connectedClients.add(ws);
|
package/package.json
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
"./server": {
|
|
14
|
-
"import": "./dist/server.js",
|
|
15
|
-
"types": "./dist/server.d.ts"
|
|
16
|
-
}
|
|
2
|
+
"name": "@gencow/core",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Gencow core library — defineQuery, defineMutation, reactive subscriptions",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
17
12
|
},
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
],
|
|
22
|
-
"scripts": {
|
|
23
|
-
"build": "tsc",
|
|
24
|
-
"typecheck": "tsc --noEmit",
|
|
25
|
-
"prepublishOnly": "npm run build"
|
|
26
|
-
},
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"@electric-sql/pglite": "^0.3.15",
|
|
29
|
-
"drizzle-orm": "^0.45.1",
|
|
30
|
-
"hono": "^4.12.0",
|
|
31
|
-
"node-cron": "^4.2.1"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/bun": "^1.3.9",
|
|
35
|
-
"@types/node": "^25.3.0",
|
|
36
|
-
"@types/node-cron": "^3.0.11",
|
|
37
|
-
"typescript": "^5.9.3"
|
|
13
|
+
"./server": {
|
|
14
|
+
"import": "./dist/server.js",
|
|
15
|
+
"types": "./dist/server.d.ts"
|
|
38
16
|
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/",
|
|
20
|
+
"src/"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@electric-sql/pglite": "^0.3.15",
|
|
24
|
+
"drizzle-orm": "^0.45.1",
|
|
25
|
+
"hono": "^4.12.0",
|
|
26
|
+
"node-cron": "^4.2.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/bun": "^1.3.9",
|
|
30
|
+
"@types/node": "^25.3.0",
|
|
31
|
+
"@types/node-cron": "^3.0.11",
|
|
32
|
+
"typescript": "^5.9.3"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
}
|
|
39
38
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* All with Convex-compatible DX patterns.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export type { GencowCtx, AuthCtx, UserIdentity, QueryDef, MutationDef, RealtimeCtx } from "./reactive";
|
|
9
|
-
export { query, mutation, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations } from "./reactive";
|
|
8
|
+
export type { GencowCtx, AuthCtx, UserIdentity, QueryDef, MutationDef, RealtimeCtx, HttpActionDef, HttpActionRequest, HttpActionResponse, HttpActionHandler } from "./reactive";
|
|
9
|
+
export { query, mutation, httpAction, invalidateQueries, buildRealtimeCtx, subscribe, unsubscribe, registerClient, deregisterClient, handleWsMessage, getQueryHandler, getQueryDef, getRegisteredQueries, getRegisteredMutations, getRegisteredHttpActions } from "./reactive";
|
|
10
10
|
export type { Storage } from "./storage";
|
|
11
11
|
export { createScheduler, getSchedulerInfo } from "./scheduler";
|
|
12
12
|
export type { Scheduler } from "./scheduler";
|
package/src/reactive.ts
CHANGED
|
@@ -61,6 +61,41 @@ type QueryHandler<TArgs = any, TReturn = any> = (ctx: GencowCtx, args: TArgs) =>
|
|
|
61
61
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
62
|
type MutationHandler<TArgs = any, TReturn = any> = (ctx: GencowCtx, args: TArgs) => Promise<TReturn>;
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* httpAction 핸들러의 Request/Response 타입.
|
|
66
|
+
* Hono의 Context를 직접 받아 full HTTP 제어 가능.
|
|
67
|
+
*/
|
|
68
|
+
export type HttpActionHandler = (ctx: GencowCtx, req: HttpActionRequest) => Promise<HttpActionResponse>;
|
|
69
|
+
|
|
70
|
+
export interface HttpActionRequest {
|
|
71
|
+
/** HTTP method (GET, POST, PUT, DELETE, PATCH) */
|
|
72
|
+
method: string;
|
|
73
|
+
/** Full URL */
|
|
74
|
+
url: string;
|
|
75
|
+
/** URL path (e.g. /api/cli/auth-start) */
|
|
76
|
+
path: string;
|
|
77
|
+
/** Route params (e.g. { id: "abc" } for /api/apps/:id) */
|
|
78
|
+
params: Record<string, string>;
|
|
79
|
+
/** Query string params */
|
|
80
|
+
query: Record<string, string>;
|
|
81
|
+
/** Request headers */
|
|
82
|
+
headers: Record<string, string>;
|
|
83
|
+
/** Parse JSON body */
|
|
84
|
+
json: <T = unknown>() => Promise<T>;
|
|
85
|
+
/** Parse form data */
|
|
86
|
+
formData: () => Promise<FormData>;
|
|
87
|
+
/** Raw body as ArrayBuffer */
|
|
88
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
89
|
+
/** Raw body as text */
|
|
90
|
+
text: () => Promise<string>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface HttpActionResponse {
|
|
94
|
+
status?: number;
|
|
95
|
+
headers?: Record<string, string>;
|
|
96
|
+
body?: unknown;
|
|
97
|
+
}
|
|
98
|
+
|
|
64
99
|
export interface QueryDef<TSchema = any, TReturn = any> {
|
|
65
100
|
key: string;
|
|
66
101
|
handler: QueryHandler<InferArgs<TSchema>, TReturn>;
|
|
@@ -81,6 +116,18 @@ export interface MutationDef<TSchema = any, TReturn = any> {
|
|
|
81
116
|
_return?: TReturn;
|
|
82
117
|
}
|
|
83
118
|
|
|
119
|
+
/** httpAction 정의. 커스텀 HTTP 엔드포인트를 선언적으로 등록. */
|
|
120
|
+
export interface HttpActionDef {
|
|
121
|
+
/** HTTP method */
|
|
122
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
123
|
+
/** URL path (Hono 패턴 — /api/cli/:code 형태 지원) */
|
|
124
|
+
path: string;
|
|
125
|
+
/** true = 인증 없이 접근 가능, false(기본) = auth 필수 */
|
|
126
|
+
isPublic: boolean;
|
|
127
|
+
/** 핸들러 */
|
|
128
|
+
handler: HttpActionHandler;
|
|
129
|
+
}
|
|
130
|
+
|
|
84
131
|
// ─── Registry ───────────────────────────────────────────
|
|
85
132
|
//
|
|
86
133
|
// globalThis 기반 — 서버 번들(인라인)과 node_modules/@gencow/core 양쪽에서
|
|
@@ -96,15 +143,19 @@ declare global {
|
|
|
96
143
|
var __gencow_subscribers: Map<string, Set<WSContext>>;
|
|
97
144
|
// eslint-disable-next-line no-var
|
|
98
145
|
var __gencow_connectedClients: Set<WSContext>;
|
|
146
|
+
// eslint-disable-next-line no-var
|
|
147
|
+
var __gencow_httpActionRegistry: HttpActionDef[];
|
|
99
148
|
}
|
|
100
149
|
|
|
101
150
|
if (!globalThis.__gencow_queryRegistry) globalThis.__gencow_queryRegistry = new Map();
|
|
102
151
|
if (!globalThis.__gencow_mutationRegistry) globalThis.__gencow_mutationRegistry = [];
|
|
103
152
|
if (!globalThis.__gencow_subscribers) globalThis.__gencow_subscribers = new Map();
|
|
104
153
|
if (!globalThis.__gencow_connectedClients) globalThis.__gencow_connectedClients = new Set();
|
|
154
|
+
if (!globalThis.__gencow_httpActionRegistry) globalThis.__gencow_httpActionRegistry = [];
|
|
105
155
|
|
|
106
156
|
const queryRegistry = globalThis.__gencow_queryRegistry;
|
|
107
157
|
const mutationRegistry = globalThis.__gencow_mutationRegistry;
|
|
158
|
+
const httpActionRegistry = globalThis.__gencow_httpActionRegistry;
|
|
108
159
|
const subscribers = globalThis.__gencow_subscribers;
|
|
109
160
|
|
|
110
161
|
/**
|
|
@@ -174,6 +225,53 @@ export function mutation<TSchema = any, TReturn = any>(
|
|
|
174
225
|
return def;
|
|
175
226
|
}
|
|
176
227
|
|
|
228
|
+
// ─── httpAction (커스텀 HTTP 엔드포인트) ────────────────
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 커스텀 HTTP 엔드포인트를 선언적으로 등록합니다.
|
|
232
|
+
* query/mutation은 RPC 패턴이지만, httpAction은 RESTful HTTP 라우트를 직접 정의합니다.
|
|
233
|
+
*
|
|
234
|
+
* 사용 사례:
|
|
235
|
+
* - CLI Device Auth (POST /api/cli/auth-start)
|
|
236
|
+
* - 파일 업로드 (POST /api/apps/:id/deploy)
|
|
237
|
+
* - Webhook 수신
|
|
238
|
+
* - 외부 서비스 콜백
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* import { httpAction } from "@gencow/core";
|
|
243
|
+
*
|
|
244
|
+
* export const authStart = httpAction({
|
|
245
|
+
* method: "POST",
|
|
246
|
+
* path: "/api/cli/auth-start",
|
|
247
|
+
* public: true,
|
|
248
|
+
* handler: async (ctx, req) => {
|
|
249
|
+
* const code = crypto.randomUUID().slice(0, 8);
|
|
250
|
+
* return { body: { code, url: `https://gencow.com/cli-auth?code=${code}` } };
|
|
251
|
+
* },
|
|
252
|
+
* });
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
export function httpAction(def: {
|
|
256
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
257
|
+
path: string;
|
|
258
|
+
public?: boolean;
|
|
259
|
+
handler: HttpActionHandler;
|
|
260
|
+
}): HttpActionDef {
|
|
261
|
+
const actionDef: HttpActionDef = {
|
|
262
|
+
method: def.method,
|
|
263
|
+
path: def.path,
|
|
264
|
+
isPublic: def.public === true,
|
|
265
|
+
handler: def.handler,
|
|
266
|
+
};
|
|
267
|
+
httpActionRegistry.push(actionDef);
|
|
268
|
+
return actionDef;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function getRegisteredHttpActions(): HttpActionDef[] {
|
|
272
|
+
return [...httpActionRegistry];
|
|
273
|
+
}
|
|
274
|
+
|
|
177
275
|
// ─── WebSocket subscription management ──────────────────
|
|
178
276
|
|
|
179
277
|
export function subscribe(queryKey: string, ws: WSContext) {
|