clawfire 0.6.0 → 0.6.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.
- package/dist/cli.js +2 -2
- package/dist/{dev-server-GD445Q6F.js → dev-server-B65DD66L.js} +259 -1
- package/dist/dev.cjs +259 -1
- package/dist/dev.cjs.map +1 -1
- package/dist/dev.js +259 -1
- package/dist/dev.js.map +1 -1
- package/package.json +2 -2
- package/templates/starter/functions/package.json +1 -1
- package/templates/starter/functions/routes/todos/create.ts +1 -1
- package/templates/starter/functions/routes/todos/delete.ts +1 -1
- package/templates/starter/functions/routes/todos/list.ts +1 -1
- package/templates/starter/functions/routes/todos/update.ts +1 -1
- package/templates/starter/functions/store.ts +95 -21
- package/templates/starter/package.json +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawfire",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "AI-First Firebase app framework — Speak. Build. Deploy.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"bin": {
|
|
82
|
-
"clawfire": "
|
|
82
|
+
"clawfire": "dist/cli.js"
|
|
83
83
|
},
|
|
84
84
|
"files": [
|
|
85
85
|
"dist",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* In-
|
|
2
|
+
* Todo Store — Dual Mode (In-Memory + Firestore)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Mode is auto-detected from process.env.CLAWFIRE_FIREBASE_CONFIG.
|
|
5
|
+
* If the env var contains valid Firebase config, Firestore mode is used.
|
|
6
|
+
* Otherwise, falls back to in-memory mode (no setup needed).
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
export interface Todo {
|
|
@@ -12,45 +13,118 @@ export interface Todo {
|
|
|
12
13
|
createdAt: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
// ─── In-Memory Store ──────────────────────────────────────────
|
|
17
|
+
const memoryStore = new Map<string, Todo>();
|
|
16
18
|
let idCounter = 0;
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
// ─── Firestore State (lazy-initialized) ──────────────────────
|
|
21
|
+
let initialized = false;
|
|
22
|
+
let useFirestore = false;
|
|
23
|
+
let firestoreDb: any = null;
|
|
24
|
+
let firestoreMethods: any = null;
|
|
25
|
+
|
|
26
|
+
async function ensureInit(): Promise<void> {
|
|
27
|
+
if (initialized) return;
|
|
28
|
+
initialized = true;
|
|
29
|
+
|
|
30
|
+
const configJson = process.env.CLAWFIRE_FIREBASE_CONFIG;
|
|
31
|
+
if (!configJson) return;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const config = JSON.parse(configJson);
|
|
35
|
+
if (!config.apiKey || config.apiKey.startsWith("YOUR_")) return;
|
|
36
|
+
|
|
37
|
+
const firebaseApp = await import("firebase/app");
|
|
38
|
+
const firebaseFirestore = await import("firebase/firestore");
|
|
39
|
+
|
|
40
|
+
const app =
|
|
41
|
+
firebaseApp.getApps().length === 0
|
|
42
|
+
? firebaseApp.initializeApp(config)
|
|
43
|
+
: firebaseApp.getApps()[0];
|
|
44
|
+
|
|
45
|
+
firestoreDb = firebaseFirestore.getFirestore(app);
|
|
46
|
+
firestoreMethods = firebaseFirestore;
|
|
47
|
+
useFirestore = true;
|
|
48
|
+
console.log(" [store] Firestore mode enabled");
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.warn(" [store] Firestore init failed, using in-memory:", err);
|
|
51
|
+
}
|
|
20
52
|
}
|
|
21
53
|
|
|
54
|
+
// ─── Exported Store (async methods) ──────────────────────────
|
|
22
55
|
export const todoStore = {
|
|
23
|
-
list(): Todo[] {
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
async list(): Promise<Todo[]> {
|
|
57
|
+
await ensureInit();
|
|
58
|
+
if (useFirestore) {
|
|
59
|
+
const { collection, getDocs, query, orderBy } = firestoreMethods;
|
|
60
|
+
const q = query(
|
|
61
|
+
collection(firestoreDb, "todos"),
|
|
62
|
+
orderBy("createdAt", "desc"),
|
|
63
|
+
);
|
|
64
|
+
const snap = await getDocs(q);
|
|
65
|
+
return snap.docs.map((d: any) => ({ id: d.id, ...d.data() }) as Todo);
|
|
66
|
+
}
|
|
67
|
+
return Array.from(memoryStore.values()).sort(
|
|
68
|
+
(a, b) =>
|
|
69
|
+
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
|
26
70
|
);
|
|
27
71
|
},
|
|
28
72
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
create(title: string): Todo {
|
|
73
|
+
async create(title: string): Promise<Todo> {
|
|
74
|
+
await ensureInit();
|
|
34
75
|
const todo: Todo = {
|
|
35
|
-
id:
|
|
76
|
+
id: "",
|
|
36
77
|
title,
|
|
37
78
|
completed: false,
|
|
38
79
|
createdAt: new Date().toISOString(),
|
|
39
80
|
};
|
|
40
|
-
|
|
81
|
+
if (useFirestore) {
|
|
82
|
+
const { collection, addDoc } = firestoreMethods;
|
|
83
|
+
const ref = await addDoc(collection(firestoreDb, "todos"), {
|
|
84
|
+
title: todo.title,
|
|
85
|
+
completed: todo.completed,
|
|
86
|
+
createdAt: todo.createdAt,
|
|
87
|
+
});
|
|
88
|
+
todo.id = ref.id;
|
|
89
|
+
} else {
|
|
90
|
+
todo.id = `todo_${++idCounter}_${Date.now()}`;
|
|
91
|
+
memoryStore.set(todo.id, todo);
|
|
92
|
+
}
|
|
41
93
|
return todo;
|
|
42
94
|
},
|
|
43
95
|
|
|
44
|
-
update(
|
|
45
|
-
|
|
96
|
+
async update(
|
|
97
|
+
id: string,
|
|
98
|
+
data: Partial<Pick<Todo, "title" | "completed">>,
|
|
99
|
+
): Promise<Todo | null> {
|
|
100
|
+
await ensureInit();
|
|
101
|
+
if (useFirestore) {
|
|
102
|
+
const { doc, updateDoc, getDoc } = firestoreMethods;
|
|
103
|
+
const ref = doc(firestoreDb, "todos", id);
|
|
104
|
+
const updateData: Record<string, any> = {};
|
|
105
|
+
if (data.title !== undefined) updateData.title = data.title;
|
|
106
|
+
if (data.completed !== undefined) updateData.completed = data.completed;
|
|
107
|
+
await updateDoc(ref, updateData);
|
|
108
|
+
const snap = await getDoc(ref);
|
|
109
|
+
return snap.exists()
|
|
110
|
+
? ({ id: snap.id, ...snap.data() } as Todo)
|
|
111
|
+
: null;
|
|
112
|
+
}
|
|
113
|
+
const todo = memoryStore.get(id);
|
|
46
114
|
if (!todo) return null;
|
|
47
115
|
if (data.title !== undefined) todo.title = data.title;
|
|
48
116
|
if (data.completed !== undefined) todo.completed = data.completed;
|
|
49
|
-
|
|
117
|
+
memoryStore.set(id, todo);
|
|
50
118
|
return todo;
|
|
51
119
|
},
|
|
52
120
|
|
|
53
|
-
delete(id: string): boolean {
|
|
54
|
-
|
|
121
|
+
async delete(id: string): Promise<boolean> {
|
|
122
|
+
await ensureInit();
|
|
123
|
+
if (useFirestore) {
|
|
124
|
+
const { doc, deleteDoc } = firestoreMethods;
|
|
125
|
+
await deleteDoc(doc(firestoreDb, "todos", id));
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return memoryStore.delete(id);
|
|
55
129
|
},
|
|
56
130
|
};
|