clawfire 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 +182 -0
- package/dist/admin.cjs +309 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +93 -0
- package/dist/admin.d.ts +93 -0
- package/dist/admin.js +274 -0
- package/dist/admin.js.map +1 -0
- package/dist/auth-DQ3cifhb.d.cts +55 -0
- package/dist/auth-DtnUPbXT.d.ts +55 -0
- package/dist/chunk-37Y2XI7X.js +75 -0
- package/dist/chunk-YGIPORYL.js +339 -0
- package/dist/cli.js +241 -0
- package/dist/client.cjs +97 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +4 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +68 -0
- package/dist/client.js.map +1 -0
- package/dist/codegen.cjs +648 -0
- package/dist/codegen.cjs.map +1 -0
- package/dist/codegen.d.cts +25 -0
- package/dist/codegen.d.ts +25 -0
- package/dist/codegen.js +617 -0
- package/dist/codegen.js.map +1 -0
- package/dist/config-QMBJRn9G.d.cts +46 -0
- package/dist/config-QMBJRn9G.d.ts +46 -0
- package/dist/dev-server-QAVWINAT.js +973 -0
- package/dist/dev.cjs +1388 -0
- package/dist/dev.cjs.map +1 -0
- package/dist/dev.d.cts +111 -0
- package/dist/dev.d.ts +111 -0
- package/dist/dev.js +1349 -0
- package/dist/dev.js.map +1 -0
- package/dist/discover-BPMAZFBD.js +9 -0
- package/dist/discover-DYNqz_ym.d.cts +28 -0
- package/dist/discover-DYNqz_ym.d.ts +28 -0
- package/dist/errors-s_mP7rs9.d.cts +33 -0
- package/dist/errors-s_mP7rs9.d.ts +33 -0
- package/dist/functions.cjs +1156 -0
- package/dist/functions.cjs.map +1 -0
- package/dist/functions.d.cts +115 -0
- package/dist/functions.d.ts +115 -0
- package/dist/functions.js +1108 -0
- package/dist/functions.js.map +1 -0
- package/dist/hosting-7WVFHAYJ.js +85 -0
- package/dist/html-PCUCJGBH.js +7 -0
- package/dist/index.cjs +349 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +312 -0
- package/dist/index.js.map +1 -0
- package/dist/playground.cjs +364 -0
- package/dist/playground.cjs.map +1 -0
- package/dist/playground.d.cts +12 -0
- package/dist/playground.d.ts +12 -0
- package/dist/playground.js +337 -0
- package/dist/playground.js.map +1 -0
- package/dist/router-BVB_I-tu.d.ts +65 -0
- package/dist/router-Cikk8Heq.d.cts +65 -0
- package/dist/schema-BJsictSV.d.cts +172 -0
- package/dist/schema-BJsictSV.d.ts +172 -0
- package/package.json +150 -0
- package/templates/CLAUDE.md +71 -0
- package/templates/app/routes/auth/login.ts +35 -0
- package/templates/app/routes/health.ts +20 -0
- package/templates/app/schemas/user.ts +26 -0
- package/templates/clawfire.config.ts +25 -0
- package/templates/functions/index.ts +43 -0
- package/templates/starter/.claude/skills/clawfire-api/SKILL.md +131 -0
- package/templates/starter/.claude/skills/clawfire-auth/SKILL.md +111 -0
- package/templates/starter/.claude/skills/clawfire-deploy/SKILL.md +95 -0
- package/templates/starter/.claude/skills/clawfire-diagnose/SKILL.md +99 -0
- package/templates/starter/.claude/skills/clawfire-model/SKILL.md +128 -0
- package/templates/starter/CLAUDE.md +227 -0
- package/templates/starter/app/routes/health.ts +20 -0
- package/templates/starter/app/routes/todos/create.ts +25 -0
- package/templates/starter/app/routes/todos/delete.ts +20 -0
- package/templates/starter/app/routes/todos/list.ts +26 -0
- package/templates/starter/app/routes/todos/update.ts +32 -0
- package/templates/starter/app/schemas/todo.ts +16 -0
- package/templates/starter/app/store.ts +56 -0
- package/templates/starter/clawfire.config.ts +25 -0
- package/templates/starter/dev.ts +12 -0
- package/templates/starter/package.json +19 -0
- package/templates/starter/public/index.html +365 -0
- package/templates/starter/tsconfig.json +17 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { ZodType, z, ZodObject, ZodRawShape } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clawfire Schema & Contract System
|
|
5
|
+
*
|
|
6
|
+
* 모든 API는 input/output schema + meta + handler로 구성된 "계약(Contract)"으로 정의됩니다.
|
|
7
|
+
* Zod를 사용하여 타입 안전성과 런타임 검증을 동시에 보장합니다.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** 인증 컨텍스트 */
|
|
11
|
+
interface AuthContext {
|
|
12
|
+
uid: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
emailVerified?: boolean;
|
|
15
|
+
role?: string;
|
|
16
|
+
customClaims?: Record<string, unknown>;
|
|
17
|
+
token?: string;
|
|
18
|
+
}
|
|
19
|
+
/** API 핸들러에 전달되는 컨텍스트 */
|
|
20
|
+
interface HandlerContext {
|
|
21
|
+
auth: AuthContext | null;
|
|
22
|
+
/** 재인증 여부 (민감 작업용) */
|
|
23
|
+
reauthenticated?: boolean;
|
|
24
|
+
/** 원본 요청 헤더 */
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
/** 요청 IP */
|
|
27
|
+
ip?: string;
|
|
28
|
+
}
|
|
29
|
+
/** 권한 수준 */
|
|
30
|
+
type AuthLevel = "public" | "authenticated" | "role" | "reauth";
|
|
31
|
+
/** API 메타데이터 */
|
|
32
|
+
interface APIMeta {
|
|
33
|
+
/** API 설명 (AI/Playground용) */
|
|
34
|
+
description: string;
|
|
35
|
+
/** 태그 (그룹화용) */
|
|
36
|
+
tags?: string[];
|
|
37
|
+
/** 인증 요구 수준 */
|
|
38
|
+
auth?: AuthLevel;
|
|
39
|
+
/** 필요 역할 (auth가 'role'일 때) */
|
|
40
|
+
roles?: string[];
|
|
41
|
+
/** 재인증 필요 여부 */
|
|
42
|
+
reauth?: boolean;
|
|
43
|
+
/** Rate limit (초당 요청 수) */
|
|
44
|
+
rateLimit?: number;
|
|
45
|
+
/** 비활성화 여부 */
|
|
46
|
+
deprecated?: boolean;
|
|
47
|
+
/** 예시 입력값 */
|
|
48
|
+
exampleInput?: unknown;
|
|
49
|
+
/** 예시 출력값 */
|
|
50
|
+
exampleOutput?: unknown;
|
|
51
|
+
}
|
|
52
|
+
/** API 계약 정의 */
|
|
53
|
+
interface APIContract<TInput extends ZodType = ZodType, TOutput extends ZodType = ZodType> {
|
|
54
|
+
/** 입력 스키마 */
|
|
55
|
+
input: TInput;
|
|
56
|
+
/** 출력 스키마 */
|
|
57
|
+
output: TOutput;
|
|
58
|
+
/** 메타데이터 */
|
|
59
|
+
meta: APIMeta;
|
|
60
|
+
/** 핸들러 함수 */
|
|
61
|
+
handler: (input: z.infer<TInput>, ctx: HandlerContext) => Promise<z.infer<TOutput>>;
|
|
62
|
+
}
|
|
63
|
+
/** 모델 필드 정의 */
|
|
64
|
+
interface ModelField {
|
|
65
|
+
type: "string" | "number" | "boolean" | "timestamp" | "array" | "map" | "reference" | "geopoint";
|
|
66
|
+
required?: boolean;
|
|
67
|
+
description?: string;
|
|
68
|
+
default?: unknown;
|
|
69
|
+
/** 배열 아이템 타입 */
|
|
70
|
+
items?: ModelField;
|
|
71
|
+
/** 맵 값 타입 */
|
|
72
|
+
values?: ModelField;
|
|
73
|
+
/** 참조 대상 컬렉션 */
|
|
74
|
+
ref?: string;
|
|
75
|
+
/** enum 값 리스트 */
|
|
76
|
+
enum?: string[];
|
|
77
|
+
}
|
|
78
|
+
/** 모델 정의 */
|
|
79
|
+
interface ModelDefinition {
|
|
80
|
+
/** 컬렉션 이름 */
|
|
81
|
+
collection: string;
|
|
82
|
+
/** 필드 정의 */
|
|
83
|
+
fields: Record<string, ModelField>;
|
|
84
|
+
/** 서브컬렉션 */
|
|
85
|
+
subcollections?: Record<string, ModelDefinition>;
|
|
86
|
+
/** 인덱스 */
|
|
87
|
+
indexes?: ModelIndex[];
|
|
88
|
+
/** 보안 규칙 */
|
|
89
|
+
rules?: ModelRules;
|
|
90
|
+
/** 타임스탬프 자동 생성 */
|
|
91
|
+
timestamps?: boolean;
|
|
92
|
+
/** 소프트 삭제 */
|
|
93
|
+
softDelete?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** Firestore 인덱스 */
|
|
96
|
+
interface ModelIndex {
|
|
97
|
+
fields: Array<{
|
|
98
|
+
field: string;
|
|
99
|
+
order?: "asc" | "desc";
|
|
100
|
+
}>;
|
|
101
|
+
}
|
|
102
|
+
/** 모델 보안 규칙 */
|
|
103
|
+
interface ModelRules {
|
|
104
|
+
read?: AuthLevel;
|
|
105
|
+
create?: AuthLevel;
|
|
106
|
+
update?: AuthLevel;
|
|
107
|
+
delete?: AuthLevel;
|
|
108
|
+
readRoles?: string[];
|
|
109
|
+
createRoles?: string[];
|
|
110
|
+
updateRoles?: string[];
|
|
111
|
+
deleteRoles?: string[];
|
|
112
|
+
/** 소유자만 읽기/쓰기 가능 필드 */
|
|
113
|
+
ownerField?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* API 계약 정의
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* export default defineAPI({
|
|
121
|
+
* input: z.object({ name: z.string() }),
|
|
122
|
+
* output: z.object({ id: z.string(), name: z.string() }),
|
|
123
|
+
* meta: { description: "상품 생성", auth: "authenticated" },
|
|
124
|
+
* handler: async (input, ctx) => {
|
|
125
|
+
* const id = await db.create("products", input);
|
|
126
|
+
* return { id, ...input };
|
|
127
|
+
* }
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function defineAPI<TInput extends ZodType, TOutput extends ZodType>(contract: APIContract<TInput, TOutput>): APIContract<TInput, TOutput>;
|
|
132
|
+
/**
|
|
133
|
+
* 모델(Firestore 컬렉션) 정의
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* export const Product = defineModel({
|
|
138
|
+
* collection: "products",
|
|
139
|
+
* fields: {
|
|
140
|
+
* name: { type: "string", required: true },
|
|
141
|
+
* price: { type: "number", required: true },
|
|
142
|
+
* tags: { type: "array", items: { type: "string" } },
|
|
143
|
+
* },
|
|
144
|
+
* timestamps: true,
|
|
145
|
+
* rules: { read: "public", create: "authenticated" }
|
|
146
|
+
* });
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
declare function defineModel(definition: ModelDefinition): ModelDefinition;
|
|
150
|
+
/** Zod 스키마에서 JSON Schema 생성 (Playground/문서용) */
|
|
151
|
+
declare function zodToJsonSchema(schema: ZodType): Record<string, unknown>;
|
|
152
|
+
/** 모델 정의에서 Zod 스키마 자동 생성 */
|
|
153
|
+
declare function modelToZodSchema(model: ModelDefinition): ZodObject<ZodRawShape>;
|
|
154
|
+
/** API 매니페스트 항목 */
|
|
155
|
+
interface ManifestEntry {
|
|
156
|
+
path: string;
|
|
157
|
+
method: "POST";
|
|
158
|
+
meta: APIMeta;
|
|
159
|
+
inputSchema: Record<string, unknown>;
|
|
160
|
+
outputSchema: Record<string, unknown>;
|
|
161
|
+
}
|
|
162
|
+
/** 전체 매니페스트 */
|
|
163
|
+
interface Manifest {
|
|
164
|
+
version: string;
|
|
165
|
+
generatedAt: string;
|
|
166
|
+
apis: ManifestEntry[];
|
|
167
|
+
models: Record<string, ModelDefinition>;
|
|
168
|
+
}
|
|
169
|
+
/** 계약에서 매니페스트 항목 생성 */
|
|
170
|
+
declare function contractToManifest(path: string, contract: APIContract): ManifestEntry;
|
|
171
|
+
|
|
172
|
+
export { type APIContract as A, type HandlerContext as H, type Manifest as M, type APIMeta as a, type AuthContext as b, type AuthLevel as c, type ManifestEntry as d, type ModelDefinition as e, type ModelField as f, defineAPI as g, defineModel as h, type ModelIndex as i, type ModelRules as j, contractToManifest as k, modelToZodSchema as m, zodToJsonSchema as z };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { ZodType, z, ZodObject, ZodRawShape } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clawfire Schema & Contract System
|
|
5
|
+
*
|
|
6
|
+
* 모든 API는 input/output schema + meta + handler로 구성된 "계약(Contract)"으로 정의됩니다.
|
|
7
|
+
* Zod를 사용하여 타입 안전성과 런타임 검증을 동시에 보장합니다.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** 인증 컨텍스트 */
|
|
11
|
+
interface AuthContext {
|
|
12
|
+
uid: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
emailVerified?: boolean;
|
|
15
|
+
role?: string;
|
|
16
|
+
customClaims?: Record<string, unknown>;
|
|
17
|
+
token?: string;
|
|
18
|
+
}
|
|
19
|
+
/** API 핸들러에 전달되는 컨텍스트 */
|
|
20
|
+
interface HandlerContext {
|
|
21
|
+
auth: AuthContext | null;
|
|
22
|
+
/** 재인증 여부 (민감 작업용) */
|
|
23
|
+
reauthenticated?: boolean;
|
|
24
|
+
/** 원본 요청 헤더 */
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
/** 요청 IP */
|
|
27
|
+
ip?: string;
|
|
28
|
+
}
|
|
29
|
+
/** 권한 수준 */
|
|
30
|
+
type AuthLevel = "public" | "authenticated" | "role" | "reauth";
|
|
31
|
+
/** API 메타데이터 */
|
|
32
|
+
interface APIMeta {
|
|
33
|
+
/** API 설명 (AI/Playground용) */
|
|
34
|
+
description: string;
|
|
35
|
+
/** 태그 (그룹화용) */
|
|
36
|
+
tags?: string[];
|
|
37
|
+
/** 인증 요구 수준 */
|
|
38
|
+
auth?: AuthLevel;
|
|
39
|
+
/** 필요 역할 (auth가 'role'일 때) */
|
|
40
|
+
roles?: string[];
|
|
41
|
+
/** 재인증 필요 여부 */
|
|
42
|
+
reauth?: boolean;
|
|
43
|
+
/** Rate limit (초당 요청 수) */
|
|
44
|
+
rateLimit?: number;
|
|
45
|
+
/** 비활성화 여부 */
|
|
46
|
+
deprecated?: boolean;
|
|
47
|
+
/** 예시 입력값 */
|
|
48
|
+
exampleInput?: unknown;
|
|
49
|
+
/** 예시 출력값 */
|
|
50
|
+
exampleOutput?: unknown;
|
|
51
|
+
}
|
|
52
|
+
/** API 계약 정의 */
|
|
53
|
+
interface APIContract<TInput extends ZodType = ZodType, TOutput extends ZodType = ZodType> {
|
|
54
|
+
/** 입력 스키마 */
|
|
55
|
+
input: TInput;
|
|
56
|
+
/** 출력 스키마 */
|
|
57
|
+
output: TOutput;
|
|
58
|
+
/** 메타데이터 */
|
|
59
|
+
meta: APIMeta;
|
|
60
|
+
/** 핸들러 함수 */
|
|
61
|
+
handler: (input: z.infer<TInput>, ctx: HandlerContext) => Promise<z.infer<TOutput>>;
|
|
62
|
+
}
|
|
63
|
+
/** 모델 필드 정의 */
|
|
64
|
+
interface ModelField {
|
|
65
|
+
type: "string" | "number" | "boolean" | "timestamp" | "array" | "map" | "reference" | "geopoint";
|
|
66
|
+
required?: boolean;
|
|
67
|
+
description?: string;
|
|
68
|
+
default?: unknown;
|
|
69
|
+
/** 배열 아이템 타입 */
|
|
70
|
+
items?: ModelField;
|
|
71
|
+
/** 맵 값 타입 */
|
|
72
|
+
values?: ModelField;
|
|
73
|
+
/** 참조 대상 컬렉션 */
|
|
74
|
+
ref?: string;
|
|
75
|
+
/** enum 값 리스트 */
|
|
76
|
+
enum?: string[];
|
|
77
|
+
}
|
|
78
|
+
/** 모델 정의 */
|
|
79
|
+
interface ModelDefinition {
|
|
80
|
+
/** 컬렉션 이름 */
|
|
81
|
+
collection: string;
|
|
82
|
+
/** 필드 정의 */
|
|
83
|
+
fields: Record<string, ModelField>;
|
|
84
|
+
/** 서브컬렉션 */
|
|
85
|
+
subcollections?: Record<string, ModelDefinition>;
|
|
86
|
+
/** 인덱스 */
|
|
87
|
+
indexes?: ModelIndex[];
|
|
88
|
+
/** 보안 규칙 */
|
|
89
|
+
rules?: ModelRules;
|
|
90
|
+
/** 타임스탬프 자동 생성 */
|
|
91
|
+
timestamps?: boolean;
|
|
92
|
+
/** 소프트 삭제 */
|
|
93
|
+
softDelete?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** Firestore 인덱스 */
|
|
96
|
+
interface ModelIndex {
|
|
97
|
+
fields: Array<{
|
|
98
|
+
field: string;
|
|
99
|
+
order?: "asc" | "desc";
|
|
100
|
+
}>;
|
|
101
|
+
}
|
|
102
|
+
/** 모델 보안 규칙 */
|
|
103
|
+
interface ModelRules {
|
|
104
|
+
read?: AuthLevel;
|
|
105
|
+
create?: AuthLevel;
|
|
106
|
+
update?: AuthLevel;
|
|
107
|
+
delete?: AuthLevel;
|
|
108
|
+
readRoles?: string[];
|
|
109
|
+
createRoles?: string[];
|
|
110
|
+
updateRoles?: string[];
|
|
111
|
+
deleteRoles?: string[];
|
|
112
|
+
/** 소유자만 읽기/쓰기 가능 필드 */
|
|
113
|
+
ownerField?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* API 계약 정의
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* export default defineAPI({
|
|
121
|
+
* input: z.object({ name: z.string() }),
|
|
122
|
+
* output: z.object({ id: z.string(), name: z.string() }),
|
|
123
|
+
* meta: { description: "상품 생성", auth: "authenticated" },
|
|
124
|
+
* handler: async (input, ctx) => {
|
|
125
|
+
* const id = await db.create("products", input);
|
|
126
|
+
* return { id, ...input };
|
|
127
|
+
* }
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function defineAPI<TInput extends ZodType, TOutput extends ZodType>(contract: APIContract<TInput, TOutput>): APIContract<TInput, TOutput>;
|
|
132
|
+
/**
|
|
133
|
+
* 모델(Firestore 컬렉션) 정의
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* export const Product = defineModel({
|
|
138
|
+
* collection: "products",
|
|
139
|
+
* fields: {
|
|
140
|
+
* name: { type: "string", required: true },
|
|
141
|
+
* price: { type: "number", required: true },
|
|
142
|
+
* tags: { type: "array", items: { type: "string" } },
|
|
143
|
+
* },
|
|
144
|
+
* timestamps: true,
|
|
145
|
+
* rules: { read: "public", create: "authenticated" }
|
|
146
|
+
* });
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
declare function defineModel(definition: ModelDefinition): ModelDefinition;
|
|
150
|
+
/** Zod 스키마에서 JSON Schema 생성 (Playground/문서용) */
|
|
151
|
+
declare function zodToJsonSchema(schema: ZodType): Record<string, unknown>;
|
|
152
|
+
/** 모델 정의에서 Zod 스키마 자동 생성 */
|
|
153
|
+
declare function modelToZodSchema(model: ModelDefinition): ZodObject<ZodRawShape>;
|
|
154
|
+
/** API 매니페스트 항목 */
|
|
155
|
+
interface ManifestEntry {
|
|
156
|
+
path: string;
|
|
157
|
+
method: "POST";
|
|
158
|
+
meta: APIMeta;
|
|
159
|
+
inputSchema: Record<string, unknown>;
|
|
160
|
+
outputSchema: Record<string, unknown>;
|
|
161
|
+
}
|
|
162
|
+
/** 전체 매니페스트 */
|
|
163
|
+
interface Manifest {
|
|
164
|
+
version: string;
|
|
165
|
+
generatedAt: string;
|
|
166
|
+
apis: ManifestEntry[];
|
|
167
|
+
models: Record<string, ModelDefinition>;
|
|
168
|
+
}
|
|
169
|
+
/** 계약에서 매니페스트 항목 생성 */
|
|
170
|
+
declare function contractToManifest(path: string, contract: APIContract): ManifestEntry;
|
|
171
|
+
|
|
172
|
+
export { type APIContract as A, type HandlerContext as H, type Manifest as M, type APIMeta as a, type AuthContext as b, type AuthLevel as c, type ManifestEntry as d, type ModelDefinition as e, type ModelField as f, defineAPI as g, defineModel as h, type ModelIndex as i, type ModelRules as j, contractToManifest as k, modelToZodSchema as m, zodToJsonSchema as z };
|
package/package.json
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "clawfire",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI-First Firebase app framework — Speak. Build. Deploy.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./client": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/client.d.ts",
|
|
23
|
+
"default": "./dist/client.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/client.d.cts",
|
|
27
|
+
"default": "./dist/client.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./functions": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/functions.d.ts",
|
|
33
|
+
"default": "./dist/functions.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/functions.d.cts",
|
|
37
|
+
"default": "./dist/functions.cjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"./admin": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/admin.d.ts",
|
|
43
|
+
"default": "./dist/admin.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/admin.d.cts",
|
|
47
|
+
"default": "./dist/admin.cjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"./codegen": {
|
|
51
|
+
"import": {
|
|
52
|
+
"types": "./dist/codegen.d.ts",
|
|
53
|
+
"default": "./dist/codegen.js"
|
|
54
|
+
},
|
|
55
|
+
"require": {
|
|
56
|
+
"types": "./dist/codegen.d.cts",
|
|
57
|
+
"default": "./dist/codegen.cjs"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"./playground": {
|
|
61
|
+
"import": {
|
|
62
|
+
"types": "./dist/playground.d.ts",
|
|
63
|
+
"default": "./dist/playground.js"
|
|
64
|
+
},
|
|
65
|
+
"require": {
|
|
66
|
+
"types": "./dist/playground.d.cts",
|
|
67
|
+
"default": "./dist/playground.cjs"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"./dev": {
|
|
71
|
+
"import": {
|
|
72
|
+
"types": "./dist/dev.d.ts",
|
|
73
|
+
"default": "./dist/dev.js"
|
|
74
|
+
},
|
|
75
|
+
"require": {
|
|
76
|
+
"types": "./dist/dev.d.cts",
|
|
77
|
+
"default": "./dist/dev.cjs"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"bin": {
|
|
82
|
+
"clawfire": "./dist/cli.js"
|
|
83
|
+
},
|
|
84
|
+
"files": [
|
|
85
|
+
"dist",
|
|
86
|
+
"templates",
|
|
87
|
+
"README.md"
|
|
88
|
+
],
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsup",
|
|
91
|
+
"dev": "tsup --watch",
|
|
92
|
+
"typecheck": "tsc --noEmit",
|
|
93
|
+
"prepublishOnly": "npm run build",
|
|
94
|
+
"release": "source .env && npm publish --access public"
|
|
95
|
+
},
|
|
96
|
+
"keywords": [
|
|
97
|
+
"firebase",
|
|
98
|
+
"ai",
|
|
99
|
+
"framework",
|
|
100
|
+
"no-code",
|
|
101
|
+
"clawfire",
|
|
102
|
+
"firestore",
|
|
103
|
+
"functions",
|
|
104
|
+
"hosting",
|
|
105
|
+
"zod",
|
|
106
|
+
"schema",
|
|
107
|
+
"api",
|
|
108
|
+
"contract"
|
|
109
|
+
],
|
|
110
|
+
"author": "nohsangwoo <nsgr12@naver.com>",
|
|
111
|
+
"repository": {
|
|
112
|
+
"type": "git",
|
|
113
|
+
"url": "git+https://github.com/nohsangwoo/clawfire.git"
|
|
114
|
+
},
|
|
115
|
+
"homepage": "https://github.com/nohsangwoo/clawfire#readme",
|
|
116
|
+
"bugs": {
|
|
117
|
+
"url": "https://github.com/nohsangwoo/clawfire/issues"
|
|
118
|
+
},
|
|
119
|
+
"license": "MIT",
|
|
120
|
+
"dependencies": {
|
|
121
|
+
"zod": "^3.23.0"
|
|
122
|
+
},
|
|
123
|
+
"peerDependencies": {
|
|
124
|
+
"firebase": "^10.0.0 || ^11.0.0",
|
|
125
|
+
"firebase-admin": "^12.0.0 || ^13.0.0",
|
|
126
|
+
"firebase-functions": "^5.0.0 || ^6.0.0"
|
|
127
|
+
},
|
|
128
|
+
"peerDependenciesMeta": {
|
|
129
|
+
"firebase": {
|
|
130
|
+
"optional": true
|
|
131
|
+
},
|
|
132
|
+
"firebase-admin": {
|
|
133
|
+
"optional": true
|
|
134
|
+
},
|
|
135
|
+
"firebase-functions": {
|
|
136
|
+
"optional": true
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"devDependencies": {
|
|
140
|
+
"tsup": "^8.0.0",
|
|
141
|
+
"typescript": "^5.5.0",
|
|
142
|
+
"firebase": "^11.0.0",
|
|
143
|
+
"firebase-admin": "^13.0.0",
|
|
144
|
+
"firebase-functions": "^6.0.0",
|
|
145
|
+
"@types/node": "^20.0.0"
|
|
146
|
+
},
|
|
147
|
+
"engines": {
|
|
148
|
+
"node": ">=18.0.0"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Clawfire Project
|
|
2
|
+
|
|
3
|
+
This is a Clawfire project — an AI-First Firebase app framework.
|
|
4
|
+
**"Speak. Build. Deploy."**
|
|
5
|
+
|
|
6
|
+
## Stack (Fixed — do not change)
|
|
7
|
+
- DB: Firestore
|
|
8
|
+
- Auth: Firebase Auth
|
|
9
|
+
- Hosting: Firebase Hosting
|
|
10
|
+
- Backend: Firebase Functions
|
|
11
|
+
- Schema: Zod
|
|
12
|
+
- Language: TypeScript
|
|
13
|
+
- Framework: Clawfire
|
|
14
|
+
|
|
15
|
+
## Project Structure
|
|
16
|
+
```
|
|
17
|
+
app/
|
|
18
|
+
routes/ ← API route handlers (file-based routing)
|
|
19
|
+
schemas/ ← Model definitions (Firestore collections)
|
|
20
|
+
generated/ ← Auto-generated files (DO NOT EDIT)
|
|
21
|
+
api-client.ts ← Typed API client
|
|
22
|
+
manifest.json ← API manifest
|
|
23
|
+
functions/ ← Firebase Functions entry point
|
|
24
|
+
public/ ← Static files for Firebase Hosting
|
|
25
|
+
firebase.json ← Firebase config
|
|
26
|
+
firestore.rules ← Firestore security rules
|
|
27
|
+
clawfire.config.ts ← Clawfire configuration
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Commands (AI Skills)
|
|
31
|
+
- `/clawfire-init` — Initialize project / connect Firebase
|
|
32
|
+
- `/clawfire-model` — Create/modify data models
|
|
33
|
+
- `/clawfire-api` — Create/modify APIs
|
|
34
|
+
- `/clawfire-auth` — Configure authentication & authorization
|
|
35
|
+
- `/clawfire-deploy` — Deploy to Firebase
|
|
36
|
+
- `/clawfire-diagnose` — Diagnose and fix issues
|
|
37
|
+
|
|
38
|
+
## Key Patterns
|
|
39
|
+
|
|
40
|
+
### API Definition
|
|
41
|
+
All APIs use `defineAPI` with input/output Zod schemas:
|
|
42
|
+
```ts
|
|
43
|
+
import { defineAPI, z } from "clawfire";
|
|
44
|
+
export default defineAPI({
|
|
45
|
+
input: z.object({ ... }),
|
|
46
|
+
output: z.object({ ... }),
|
|
47
|
+
meta: { description: "...", auth: "authenticated" },
|
|
48
|
+
handler: async (input, ctx) => { ... },
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Model Definition
|
|
53
|
+
All Firestore collections use `defineModel`:
|
|
54
|
+
```ts
|
|
55
|
+
import { defineModel } from "clawfire";
|
|
56
|
+
export const Product = defineModel({
|
|
57
|
+
collection: "products",
|
|
58
|
+
fields: { ... },
|
|
59
|
+
timestamps: true,
|
|
60
|
+
rules: { read: "public", create: "authenticated" },
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### All APIs are POST
|
|
65
|
+
Clawfire does not use HTTP methods. Everything is POST with JSON body.
|
|
66
|
+
|
|
67
|
+
### Auth Levels
|
|
68
|
+
- `public` — No auth required
|
|
69
|
+
- `authenticated` — Login required
|
|
70
|
+
- `role` — Specific role required
|
|
71
|
+
- `reauth` — Recent re-authentication required
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineAPI, z, Errors } from "clawfire";
|
|
2
|
+
|
|
3
|
+
export default defineAPI({
|
|
4
|
+
input: z.object({
|
|
5
|
+
idToken: z.string().min(1),
|
|
6
|
+
}),
|
|
7
|
+
output: z.object({
|
|
8
|
+
uid: z.string(),
|
|
9
|
+
email: z.string().optional(),
|
|
10
|
+
role: z.string().optional(),
|
|
11
|
+
displayName: z.string().optional(),
|
|
12
|
+
}),
|
|
13
|
+
meta: {
|
|
14
|
+
description: "Verify Firebase ID token and return user info",
|
|
15
|
+
auth: "public",
|
|
16
|
+
tags: ["auth"],
|
|
17
|
+
exampleInput: {
|
|
18
|
+
idToken: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
handler: async (input, ctx) => {
|
|
22
|
+
// In real implementation, this would use verifyToken from clawfire/functions
|
|
23
|
+
// and the Firebase Admin Auth instance
|
|
24
|
+
if (!input.idToken) {
|
|
25
|
+
throw Errors.unauthorized("No token provided");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
uid: "placeholder-uid",
|
|
30
|
+
email: "user@example.com",
|
|
31
|
+
role: "user",
|
|
32
|
+
displayName: "User",
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineAPI, z } from "clawfire";
|
|
2
|
+
|
|
3
|
+
export default defineAPI({
|
|
4
|
+
input: z.object({}),
|
|
5
|
+
output: z.object({
|
|
6
|
+
status: z.string(),
|
|
7
|
+
timestamp: z.string(),
|
|
8
|
+
version: z.string(),
|
|
9
|
+
}),
|
|
10
|
+
meta: {
|
|
11
|
+
description: "Health check endpoint",
|
|
12
|
+
auth: "public",
|
|
13
|
+
tags: ["system"],
|
|
14
|
+
},
|
|
15
|
+
handler: async () => ({
|
|
16
|
+
status: "ok",
|
|
17
|
+
timestamp: new Date().toISOString(),
|
|
18
|
+
version: "1.0.0",
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineModel } from "clawfire";
|
|
2
|
+
|
|
3
|
+
export const User = defineModel({
|
|
4
|
+
collection: "users",
|
|
5
|
+
fields: {
|
|
6
|
+
email: { type: "string", required: true, description: "User email" },
|
|
7
|
+
displayName: { type: "string", required: true, description: "Display name" },
|
|
8
|
+
role: {
|
|
9
|
+
type: "string",
|
|
10
|
+
required: true,
|
|
11
|
+
enum: ["user", "admin", "editor"],
|
|
12
|
+
description: "User role",
|
|
13
|
+
},
|
|
14
|
+
photoURL: { type: "string", description: "Profile photo URL" },
|
|
15
|
+
bio: { type: "string", description: "User bio" },
|
|
16
|
+
},
|
|
17
|
+
timestamps: true,
|
|
18
|
+
rules: {
|
|
19
|
+
read: "authenticated",
|
|
20
|
+
create: "authenticated",
|
|
21
|
+
update: "authenticated",
|
|
22
|
+
delete: "role",
|
|
23
|
+
deleteRoles: ["admin"],
|
|
24
|
+
ownerField: "uid",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { configureClawfire } from "clawfire";
|
|
2
|
+
|
|
3
|
+
export default configureClawfire({
|
|
4
|
+
firebase: {
|
|
5
|
+
apiKey: "YOUR_API_KEY",
|
|
6
|
+
authDomain: "YOUR_PROJECT.firebaseapp.com",
|
|
7
|
+
projectId: "YOUR_PROJECT_ID",
|
|
8
|
+
storageBucket: "YOUR_PROJECT.firebasestorage.app",
|
|
9
|
+
appId: "YOUR_APP_ID",
|
|
10
|
+
},
|
|
11
|
+
server: {
|
|
12
|
+
region: "us-central1",
|
|
13
|
+
cors: [],
|
|
14
|
+
rateLimit: 100,
|
|
15
|
+
},
|
|
16
|
+
security: {
|
|
17
|
+
validateInput: true,
|
|
18
|
+
safeHeaders: true,
|
|
19
|
+
maskLogs: true,
|
|
20
|
+
},
|
|
21
|
+
playground: {
|
|
22
|
+
enabled: true,
|
|
23
|
+
path: "/__playground",
|
|
24
|
+
},
|
|
25
|
+
});
|