@flareflow/cli 0.0.1 → 0.0.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/README.md +179 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# flareflow
|
|
2
|
+
|
|
3
|
+
### The Operating System for Edge Apps on Cloudflare
|
|
4
|
+
|
|
5
|
+
flareflow is a high-level, production-grade backend framework and infrastructure abstraction layer built specifically for the **Cloudflare** ecosystem.
|
|
6
|
+
|
|
7
|
+
If Firebase is for GCP and Supabase is for Postgres, then **flareflow is for Cloudflare**.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
- **Unified Context**: Access `db`, `cache`, `storage`, `jobs`, `actors`, and `auth` from a single, type-safe `ctx` object.
|
|
14
|
+
- **Stateful Edge Actors**: Durable Objects as first-class business entities with typed RPC and automatic state persistence.
|
|
15
|
+
- **Durable Workflow Engine**: Multi-step, resumable orchestrations (Sagas) with automatic retries and compensation logic.
|
|
16
|
+
- **Realtime Rooms**: WebSocket-based rooms with built-in presence and broadcasting using Durable Objects.
|
|
17
|
+
- **Type-safe SQL**: Integrated **Drizzle ORM** over **Cloudflare D1**.
|
|
18
|
+
- **Edge Auth & RBAC**: Stateless JWT-based authentication and Role-Based Access Control optimized for the edge.
|
|
19
|
+
- **Background Jobs**: Typed async tasks powered by **Cloudflare Queues**.
|
|
20
|
+
- **Modern CLI**: Scaffolding, boilerplate generators, and a typed `flareflow.config.ts`.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 📦 Project Structure
|
|
25
|
+
|
|
26
|
+
flareflow is a modular TypeScript monorepo:
|
|
27
|
+
|
|
28
|
+
- `@flareflow/core`: The heart of the framework, HTTP engine (Hono), and DI Context.
|
|
29
|
+
- `@flareflow/db`: D1 wrapper with Drizzle ORM.
|
|
30
|
+
- `@flareflow/actor`: Durable Object abstraction and RPC bridge.
|
|
31
|
+
- `@flareflow/workflow`: Durable saga/workflow engine.
|
|
32
|
+
- `@flareflow/realtime`: WebSocket room management.
|
|
33
|
+
- `@flareflow/auth`: Edge-optimized authentication and RBAC.
|
|
34
|
+
- `@flareflow/jobs`: Cloudflare Queues abstraction.
|
|
35
|
+
- `@flareflow/cache`: KV-based typed caching.
|
|
36
|
+
- `@flareflow/storage`: R2-based object storage.
|
|
37
|
+
- `@flareflow/cli`: The `flareflow` command-line developer tool.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🚀 Getting Started
|
|
42
|
+
|
|
43
|
+
### 1. Initialize a new project
|
|
44
|
+
```bash
|
|
45
|
+
npx @flareflow/cli init my-edge-app
|
|
46
|
+
cd my-edge-app
|
|
47
|
+
npm install
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Configure your app (`flareflow.config.ts`)
|
|
51
|
+
flareflow replaces manual `wrangler.toml` management with a typed TypeScript configuration.
|
|
52
|
+
```typescript
|
|
53
|
+
import { defineConfig } from "@flareflow/cli";
|
|
54
|
+
|
|
55
|
+
export default defineConfig({
|
|
56
|
+
name: "my-edge-app",
|
|
57
|
+
compatibilityDate: "2024-04-05",
|
|
58
|
+
resources: {
|
|
59
|
+
db: { type: "d1", name: "prod-db", database_id: "xxxx-yyyy-zzzz" },
|
|
60
|
+
cache: { type: "kv", name: "prod-cache", id: "aaaa-bbbb-cccc" }
|
|
61
|
+
},
|
|
62
|
+
actors: ["CounterActor"],
|
|
63
|
+
rooms: ["ChatRoom"],
|
|
64
|
+
workflows: ["OrderWorkflow"]
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Start development
|
|
69
|
+
```bash
|
|
70
|
+
flareflow dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 🛠️ Core Abstractions
|
|
76
|
+
|
|
77
|
+
### Entities (D1 + Drizzle)
|
|
78
|
+
Define your schema once, and it's automatically available on `ctx.db`.
|
|
79
|
+
```typescript
|
|
80
|
+
import { entity, field } from "@flareflow/db";
|
|
81
|
+
|
|
82
|
+
export const Users = entity("users", {
|
|
83
|
+
id: field.id(),
|
|
84
|
+
name: field.string("name"),
|
|
85
|
+
email: field.string("email").unique(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// usage in a route
|
|
89
|
+
app.get("/users/:id", async (ctx) => {
|
|
90
|
+
return await ctx.db.select().from(Users).where(eq(Users.id, ctx.param("id")));
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Actors (Durable Objects)
|
|
95
|
+
Business logic that lives in a stateful, single-threaded isolate at the edge.
|
|
96
|
+
```typescript
|
|
97
|
+
export const CounterActor = actor("CounterActor", {
|
|
98
|
+
state: { count: 0 },
|
|
99
|
+
methods: {
|
|
100
|
+
async increment(ctx) {
|
|
101
|
+
ctx.state.count++; // State is automatically persisted
|
|
102
|
+
return ctx.state.count;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// call from an HTTP handler
|
|
108
|
+
const count = await ctx.actor(CounterActor).id("global-counter").increment();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Workflows (Durable Sagas)
|
|
112
|
+
Orchestrate complex, multi-step business logic with failure recovery.
|
|
113
|
+
```typescript
|
|
114
|
+
export const OrderWorkflow = workflow("OrderWorkflow", {
|
|
115
|
+
steps: [
|
|
116
|
+
{
|
|
117
|
+
name: "reserve-inventory",
|
|
118
|
+
action: async (ctx, state) => Inventory.reserve(state.itemId),
|
|
119
|
+
compensate: async (ctx, state) => Inventory.release(state.itemId)
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "charge-card",
|
|
123
|
+
action: async (ctx, state) => Stripe.charge(state.amount)
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// trigger the workflow
|
|
129
|
+
await ctx.workflow(OrderWorkflow).start("order_123", { itemId: "sku_1", amount: 100 });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Realtime (WebSockets)
|
|
133
|
+
Built-in pub/sub and presence rooms.
|
|
134
|
+
```typescript
|
|
135
|
+
export const ChatRoom = room("ChatRoom", {
|
|
136
|
+
onJoin: (ctx, client) => ctx.broadcast("user_joined", { id: client.id }),
|
|
137
|
+
onMessage: (ctx, client, msg) => ctx.broadcast("message", { from: client.id, text: msg.text })
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// upgrade to WebSocket in a route
|
|
141
|
+
app.get("/chat/:id", (ctx) => ctx.realtime(ChatRoom).id(ctx.param("id")).upgrade());
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 💻 CLI Commands
|
|
147
|
+
|
|
148
|
+
- `flareflow init <dir>`: Scaffold a new project.
|
|
149
|
+
- `flareflow dev`: Start local development with hot-reloading and infrastructure simulation.
|
|
150
|
+
- `flareflow generate <type> <name>`: Generate boilerplate for `entity`, `actor`, `job`, `workflow`, or `room`.
|
|
151
|
+
- `flareflow db:generate`: Generate SQL migrations from your Entities.
|
|
152
|
+
- `flareflow db:migrate`: Apply migrations to D1 (local or remote).
|
|
153
|
+
- `flareflow deploy`: Automatically generate `wrangler.toml` and deploy to Cloudflare.
|
|
154
|
+
- `flareflow studio`: Start the local web dashboard to inspect your data, actors, and workflows.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 🛠️ Development & Publishing
|
|
159
|
+
flareflow is managed as a monorepo using **npm workspaces** and **Changesets**.
|
|
160
|
+
|
|
161
|
+
### Running local builds
|
|
162
|
+
```bash
|
|
163
|
+
npm run build
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Proposing a release
|
|
167
|
+
To suggest a version bump and generate a changelog, run:
|
|
168
|
+
```bash
|
|
169
|
+
npx changeset
|
|
170
|
+
```
|
|
171
|
+
Follow the prompts to select which packages are affected.
|
|
172
|
+
|
|
173
|
+
### Automatic Publishing
|
|
174
|
+
The project uses GitHub Actions to automate publishing to npm. Once a changeset PR is merged into `main`, the packages will be built and published under the `@flareflow` scope.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 📄 License
|
|
179
|
+
MIT
|