opencastle 0.33.9 → 0.34.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.
Files changed (112) hide show
  1. package/dist/cli/init.d.ts.map +1 -1
  2. package/dist/cli/init.js +39 -17
  3. package/dist/cli/init.js.map +1 -1
  4. package/dist/cli/stack-config.d.ts.map +1 -1
  5. package/dist/cli/stack-config.js +5 -0
  6. package/dist/cli/stack-config.js.map +1 -1
  7. package/dist/cli/types.d.ts +1 -1
  8. package/dist/cli/types.d.ts.map +1 -1
  9. package/dist/orchestrator/plugins/cloudflare/config.d.ts +3 -0
  10. package/dist/orchestrator/plugins/cloudflare/config.d.ts.map +1 -0
  11. package/dist/orchestrator/plugins/cloudflare/config.js +23 -0
  12. package/dist/orchestrator/plugins/cloudflare/config.js.map +1 -0
  13. package/dist/orchestrator/plugins/coolify/config.d.ts +3 -0
  14. package/dist/orchestrator/plugins/coolify/config.d.ts.map +1 -0
  15. package/dist/orchestrator/plugins/coolify/config.js +28 -0
  16. package/dist/orchestrator/plugins/coolify/config.js.map +1 -0
  17. package/dist/orchestrator/plugins/drizzle/config.d.ts +3 -0
  18. package/dist/orchestrator/plugins/drizzle/config.d.ts.map +1 -0
  19. package/dist/orchestrator/plugins/drizzle/config.js +15 -0
  20. package/dist/orchestrator/plugins/drizzle/config.js.map +1 -0
  21. package/dist/orchestrator/plugins/expo/config.d.ts +3 -0
  22. package/dist/orchestrator/plugins/expo/config.d.ts.map +1 -0
  23. package/dist/orchestrator/plugins/expo/config.js +23 -0
  24. package/dist/orchestrator/plugins/expo/config.js.map +1 -0
  25. package/dist/orchestrator/plugins/index.d.ts.map +1 -1
  26. package/dist/orchestrator/plugins/index.js +12 -0
  27. package/dist/orchestrator/plugins/index.js.map +1 -1
  28. package/dist/orchestrator/plugins/sentry/config.d.ts +3 -0
  29. package/dist/orchestrator/plugins/sentry/config.d.ts.map +1 -0
  30. package/dist/orchestrator/plugins/sentry/config.js +28 -0
  31. package/dist/orchestrator/plugins/sentry/config.js.map +1 -0
  32. package/dist/orchestrator/plugins/stripe/config.d.ts +3 -0
  33. package/dist/orchestrator/plugins/stripe/config.d.ts.map +1 -0
  34. package/dist/orchestrator/plugins/stripe/config.js +42 -0
  35. package/dist/orchestrator/plugins/stripe/config.js.map +1 -0
  36. package/dist/orchestrator/plugins/types.d.ts +1 -1
  37. package/dist/orchestrator/plugins/types.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/src/cli/init.ts +43 -22
  40. package/src/cli/stack-config.ts +5 -0
  41. package/src/cli/types.ts +1 -1
  42. package/src/dashboard/dist/data/convoys/demo-api-v2.json +3 -3
  43. package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +4 -4
  44. package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +12 -12
  45. package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +3 -3
  46. package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +1 -1
  47. package/src/dashboard/dist/data/convoys/demo-docs-update.json +3 -3
  48. package/src/dashboard/dist/data/convoys/demo-perf-opt.json +4 -4
  49. package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
  50. package/src/dashboard/public/data/convoys/demo-api-v2.json +3 -3
  51. package/src/dashboard/public/data/convoys/demo-auth-revamp.json +4 -4
  52. package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +12 -12
  53. package/src/dashboard/public/data/convoys/demo-data-pipeline.json +3 -3
  54. package/src/dashboard/public/data/convoys/demo-deploy-ci.json +1 -1
  55. package/src/dashboard/public/data/convoys/demo-docs-update.json +3 -3
  56. package/src/dashboard/public/data/convoys/demo-perf-opt.json +4 -4
  57. package/src/orchestrator/customizations/agents/skill-matrix.json +24 -4
  58. package/src/orchestrator/customizations/agents/skill-matrix.md +5 -0
  59. package/src/orchestrator/plugins/cloudflare/SKILL.md +111 -0
  60. package/src/orchestrator/plugins/cloudflare/config.ts +24 -0
  61. package/src/orchestrator/plugins/cloudflare/references/deployment.md +147 -0
  62. package/src/orchestrator/plugins/cloudflare/references/storage.md +118 -0
  63. package/src/orchestrator/plugins/cloudflare/references/workers.md +135 -0
  64. package/src/orchestrator/plugins/convex/SKILL.md +62 -20
  65. package/src/orchestrator/plugins/convex/references/auth-auth0.md +116 -0
  66. package/src/orchestrator/plugins/convex/references/auth-clerk.md +113 -0
  67. package/src/orchestrator/plugins/convex/references/auth-convex-auth.md +143 -0
  68. package/src/orchestrator/plugins/convex/references/auth-setup.md +87 -0
  69. package/src/orchestrator/plugins/convex/references/auth-workos.md +114 -0
  70. package/src/orchestrator/plugins/convex/references/components-advanced.md +134 -0
  71. package/src/orchestrator/plugins/convex/references/components.md +171 -0
  72. package/src/orchestrator/plugins/convex/references/function-budget.md +232 -0
  73. package/src/orchestrator/plugins/convex/references/hot-path-rules.md +371 -0
  74. package/src/orchestrator/plugins/convex/references/migrations-component.md +170 -0
  75. package/src/orchestrator/plugins/convex/references/migrations.md +259 -0
  76. package/src/orchestrator/plugins/convex/references/occ-conflicts.md +126 -0
  77. package/src/orchestrator/plugins/convex/references/performance-audit.md +80 -0
  78. package/src/orchestrator/plugins/convex/references/quickstart.md +176 -0
  79. package/src/orchestrator/plugins/convex/references/subscription-cost.md +252 -0
  80. package/src/orchestrator/plugins/coolify/SKILL.md +134 -0
  81. package/src/orchestrator/plugins/coolify/config.ts +29 -0
  82. package/src/orchestrator/plugins/coolify/references/applications.md +65 -0
  83. package/src/orchestrator/plugins/coolify/references/ci-cd-webhooks.md +73 -0
  84. package/src/orchestrator/plugins/coolify/references/databases-services.md +57 -0
  85. package/src/orchestrator/plugins/coolify/references/docker-compose.md +121 -0
  86. package/src/orchestrator/plugins/coolify/references/infrastructure.md +77 -0
  87. package/src/orchestrator/plugins/drizzle/SKILL.md +123 -0
  88. package/src/orchestrator/plugins/drizzle/config.ts +16 -0
  89. package/src/orchestrator/plugins/drizzle/references/migrations.md +112 -0
  90. package/src/orchestrator/plugins/drizzle/references/query-patterns.md +127 -0
  91. package/src/orchestrator/plugins/drizzle/references/schema-patterns.md +105 -0
  92. package/src/orchestrator/plugins/expo/SKILL.md +114 -0
  93. package/src/orchestrator/plugins/expo/config.ts +24 -0
  94. package/src/orchestrator/plugins/expo/references/eas-build.md +73 -0
  95. package/src/orchestrator/plugins/expo/references/native-modules.md +71 -0
  96. package/src/orchestrator/plugins/expo/references/routing.md +83 -0
  97. package/src/orchestrator/plugins/index.ts +12 -0
  98. package/src/orchestrator/plugins/linear/SKILL.md +21 -3
  99. package/src/orchestrator/plugins/sentry/SKILL.md +94 -0
  100. package/src/orchestrator/plugins/sentry/config.ts +29 -0
  101. package/src/orchestrator/plugins/sentry/references/error-patterns.md +112 -0
  102. package/src/orchestrator/plugins/sentry/references/performance.md +66 -0
  103. package/src/orchestrator/plugins/sentry/references/sdk-setup.md +108 -0
  104. package/src/orchestrator/plugins/stripe/SKILL.md +138 -0
  105. package/src/orchestrator/plugins/stripe/config.ts +43 -0
  106. package/src/orchestrator/plugins/stripe/references/api-patterns.md +57 -0
  107. package/src/orchestrator/plugins/stripe/references/projects-setup.md +30 -0
  108. package/src/orchestrator/plugins/stripe/references/upgrade-guide.md +105 -0
  109. package/src/orchestrator/plugins/types.ts +1 -1
  110. package/src/orchestrator/skills/backbone-scaffolding/EXAMPLES.md +1 -1
  111. package/src/orchestrator/skills/backbone-scaffolding/SKILL.md +32 -16
  112. package/src/orchestrator/plugins/convex/REFERENCE.md +0 -9
@@ -77,6 +77,11 @@ When resolving, load **all** skills listed in the slot's entries.
77
77
  | `e2e-testing` | Browser automation | UI/UX Expert, Testing Expert |
78
78
  | `task-management` | Issue tracking, workflow states | Team Lead |
79
79
  | `knowledge-management` | Knowledge base, research, ADRs, specs | Team Lead, Researcher, Documentation Writer, Architect |
80
+ | `design` | Design tokens, component inspection, asset export | UI/UX Expert |
81
+ | `email` | Transactional email, templates, delivery | Developer |
82
+ | `payments` | Payment processing, subscriptions, webhooks | Developer |
83
+ | `observability` | Error tracking, performance monitoring, tracing | DevOps Expert, Performance Expert |
84
+ | `notifications` | Team messaging, alerts, bot integrations | Developer |
80
85
 
81
86
  ### Example: Add a second plugin
82
87
 
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: cloudflare-platform
3
+ description: "Creates and deploys Cloudflare Workers, configures wrangler.toml bindings, sets up KV/D1/R2 storage and Durable Objects, manages Pages deployments, and implements edge function patterns. Use when building or deploying Cloudflare Workers, setting up Pages, working with KV/D1/R2 storage, configuring wrangler.toml, or deploying edge applications."
4
+ ---
5
+
6
+ # Cloudflare Platform
7
+
8
+ ## Topic Routing
9
+
10
+ Read the matching reference before writing code for any of these topics:
11
+
12
+ | Topic | Reference |
13
+ |-------|-----------|
14
+ | Workers & edge functions | `references/workers.md` |
15
+ | Storage (KV, D1, R2) | `references/storage.md` |
16
+ | Pages & deployment | `references/deployment.md` |
17
+
18
+ ## Critical Rules
19
+
20
+ **Workers**
21
+ - Use Web standard Fetch API, not Node.js globals (`process`, `Buffer`, `fs`) — Workers run in V8 isolates
22
+ - Define all bindings (KV, D1, R2, secrets) in `wrangler.toml` and access them via the `env` parameter
23
+ - Workers have 0ms cold starts — keep dependencies minimal; free tier has a 1MB bundle limit
24
+ - Use `ctx.waitUntil(promise)` for non-blocking side effects (logging, analytics) that outlast the response
25
+
26
+ **Storage Selection**
27
+ - **KV** — key-value store for config, sessions, cache (eventually consistent reads)
28
+ - **D1** — SQLite at the edge for relational SQL; strongly consistent
29
+ - **R2** — object/file storage (S3-compatible); no egress costs
30
+ - **Durable Objects** — stateful coordination; use for real-time collaboration, rate limiters, and counters
31
+ - **Queues** — async message processing; use for background tasks
32
+
33
+ **D1**
34
+ - Use `env.DB.prepare(sql).bind(...params).run()` for all DML; always use parameterized queries
35
+ - Use `env.DB.batch([...stmts])` for multiple queries in a single round trip
36
+ - D1 is SQLite — avoid MySQL/Postgres-only SQL syntax
37
+
38
+ **MCP Code Mode**
39
+ - The Cloudflare MCP uses Code Mode: only 2 tools are available — `search` and `execute`
40
+ - `search` searches the Cloudflare API spec; `execute` runs JavaScript against the Cloudflare API
41
+ - This approach uses ~1k tokens per operation vs ~244k for native tool exposure
42
+
43
+ **Wrangler**
44
+ - Use `wrangler.toml` (or `wrangler.jsonc`) for all config — `npx wrangler dev` for local dev
45
+ - `npx wrangler deploy` for production; `wrangler tail` for live log streaming
46
+ - Store secrets with `wrangler secret put VAR_NAME` — never hardcode in `wrangler.toml`
47
+
48
+ **Security**
49
+ - Access secrets via `env.VAR_NAME` — never hardcode credentials in Worker code
50
+ - Use Cloudflare Turnstile for CAPTCHA; configure WAF rules for API protection
51
+ - Validate all inputs at the Worker boundary — Workers are publicly accessible
52
+
53
+ ## Basic Worker with KV
54
+
55
+ ```typescript
56
+ // src/index.ts
57
+ export interface Env {
58
+ SESSIONS: KVNamespace; // bound in wrangler.toml
59
+ API_SECRET: string; // secret bound in wrangler.toml
60
+ }
61
+
62
+ export default {
63
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
64
+ const url = new URL(request.url);
65
+
66
+ if (url.pathname === '/session') {
67
+ const sessionId = request.headers.get('x-session-id');
68
+ if (!sessionId) return new Response('Missing session', { status: 400 });
69
+
70
+ const data = await env.SESSIONS.get(sessionId, { type: 'json' });
71
+ if (!data) return new Response('Not found', { status: 404 });
72
+
73
+ // Non-blocking analytics — does not delay the response
74
+ ctx.waitUntil(logAnalytics(sessionId));
75
+
76
+ return Response.json(data);
77
+ }
78
+
79
+ return new Response('Not found', { status: 404 });
80
+ },
81
+ } satisfies ExportedHandler<Env>;
82
+ ```
83
+
84
+ ## Storage Decision Guide
85
+
86
+ ```
87
+ I need to store data → What type?
88
+ ├── Key-value pairs (cache, sessions, feature flags) → KV
89
+ ├── Relational/SQL data → D1
90
+ ├── Files, images, blobs → R2
91
+ ├── Stateful coordination (counters, locks, chat) → Durable Objects
92
+ └── Async job queue → Queues
93
+ ```
94
+
95
+ ## Reference Files
96
+
97
+ - `references/workers.md` — Worker structure, bindings, env, waitUntil, Durable Objects, Cron Triggers, Wrangler commands
98
+ - `references/storage.md` — KV, D1, R2 APIs; decision guide for choosing between storage types
99
+ - `references/deployment.md` — Pages setup, wrangler.toml, secrets, custom domains, CI/CD integration
100
+
101
+ ## Quick Workflow: Deploy a Cloudflare Worker
102
+ 1. Create project: `npm create cloudflare@latest` and select "Hello World" Worker template
103
+ 2. Define bindings (KV, D1, secrets) in `wrangler.toml` under `[[kv_namespaces]]` / `[[d1_databases]]`
104
+ 3. Verify resources exist: `npx wrangler kv:namespace list` / `npx wrangler d1 list` — create any missing resources before continuing
105
+ - **If resource missing:** `npx wrangler kv:namespace create <NAME>` or `npx wrangler d1 create <DB>` → copy the ID into `wrangler.toml`
106
+ 4. Implement the `fetch` handler in `src/index.ts` — type the `Env` interface to match your bindings
107
+ 5. Test locally: `npx wrangler dev` — verify the worker responds correctly at `http://localhost:8787`
108
+ - **If dev fails:** check `wrangler.toml` syntax → verify binding IDs match → run `npx wrangler whoami` to confirm account auth
109
+ 6. Deploy: `npx wrangler deploy` — confirm the deployment URL is returned
110
+ - **If deploy fails:** check `wrangler.toml` bindings match created resources → verify `compatibility_date` is set → check account permissions
111
+ 7. Monitor with `wrangler tail` for live logs from production
@@ -0,0 +1,24 @@
1
+ import type { PluginConfig } from '../types.js';
2
+
3
+ export const config: PluginConfig = {
4
+ id: 'cloudflare',
5
+ name: 'Cloudflare',
6
+ category: 'tech',
7
+ subCategory: 'deployment',
8
+ label: 'Cloudflare',
9
+ hint: 'Workers, Pages, KV, D1, R2, and edge computing',
10
+ skillName: 'cloudflare-platform',
11
+ mcpServerKey: 'Cloudflare',
12
+ mcpConfig: {
13
+ type: 'http',
14
+ url: 'https://mcp.cloudflare.com/mcp',
15
+ },
16
+ authType: 'oauth',
17
+ envVars: [],
18
+ agentToolMap: {
19
+ 'developer': ['search', 'execute'],
20
+ 'devops-expert': ['search', 'execute'],
21
+ },
22
+ docsUrl: null,
23
+ officialDocs: 'https://developers.cloudflare.com/',
24
+ };
@@ -0,0 +1,147 @@
1
+ # Cloudflare Deployment
2
+
3
+ ## wrangler.toml Reference
4
+
5
+ ```toml
6
+ name = "my-app"
7
+ main = "src/index.ts"
8
+ compatibility_date = "2024-12-01"
9
+ compatibility_flags = ["nodejs_compat"] # enable Node.js compat layer
10
+
11
+ # Environment variables (non-secret)
12
+ [vars]
13
+ ENVIRONMENT = "production"
14
+ API_BASE_URL = "https://api.example.com"
15
+
16
+ # Secrets — set via CLI, NOT stored here:
17
+ # wrangler secret put DB_PASSWORD
18
+
19
+ # KV binding
20
+ [[kv_namespaces]]
21
+ binding = "CACHE"
22
+ id = "abc123def456"
23
+ preview_id = "preview_abc123" # for `wrangler dev --remote`
24
+
25
+ # D1 binding
26
+ [[d1_databases]]
27
+ binding = "DB"
28
+ database_name = "my-database"
29
+ database_id = "xyz789"
30
+
31
+ # R2 binding
32
+ [[r2_buckets]]
33
+ binding = "ASSETS"
34
+ bucket_name = "my-assets"
35
+
36
+ # Service binding (call another Worker)
37
+ [[services]]
38
+ binding = "AUTH_WORKER"
39
+ service = "auth-service"
40
+
41
+ # Cron Triggers
42
+ [triggers]
43
+ crons = ["0 0 * * *"] # midnight UTC daily
44
+
45
+ # Per-environment overrides
46
+ [env.staging]
47
+ name = "my-app-staging"
48
+ vars = { ENVIRONMENT = "staging" }
49
+ ```
50
+
51
+ ## Pages Setup
52
+
53
+ ```bash
54
+ # Create a new Pages project
55
+ npm create cloudflare@latest my-app -- --framework=nextjs
56
+
57
+ # Deploy from CLI
58
+ npx wrangler pages deploy ./dist --project-name=my-app
59
+
60
+ # Deploy a specific branch (creates preview)
61
+ npx wrangler pages deploy ./dist --project-name=my-app --branch=feature-xyz
62
+ ```
63
+
64
+ ### Pages Functions
65
+
66
+ ```typescript
67
+ // functions/api/hello.ts — file-based routing in /functions
68
+ interface Env {
69
+ MY_KV: KVNamespace;
70
+ }
71
+
72
+ export const onRequest: PagesFunction<Env> = async (context) => {
73
+ const data = await context.env.MY_KV.get('greeting');
74
+ return Response.json({ message: data ?? 'Hello!' });
75
+ };
76
+ ```
77
+
78
+ ## Environment Variables & Secrets
79
+
80
+ ```bash
81
+ # List current secrets
82
+ wrangler secret list
83
+
84
+ # Add a secret (prompts for value)
85
+ wrangler secret put DATABASE_URL
86
+
87
+ # Add a secret for a specific environment
88
+ wrangler secret put DATABASE_URL --env staging
89
+
90
+ # Bulk secrets from .dev.vars (local dev only — never commit this file)
91
+ # .dev.vars format: KEY=value (one per line)
92
+ ```
93
+
94
+ ## Custom Domains
95
+
96
+ ```bash
97
+ # Add a custom domain via dashboard or CLI
98
+ wrangler domains add my-worker.example.com
99
+
100
+ # For Pages: configure in the Cloudflare Dashboard under
101
+ # Pages → Project → Custom Domains
102
+ ```
103
+
104
+ ## CI/CD Integration
105
+
106
+ ### GitHub Actions
107
+
108
+ ```yaml
109
+ # .github/workflows/deploy.yml
110
+ name: Deploy
111
+
112
+ on:
113
+ push:
114
+ branches: [main]
115
+
116
+ jobs:
117
+ deploy:
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - uses: actions/checkout@v4
121
+ - uses: cloudflare/wrangler-action@v3
122
+ with:
123
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
124
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
125
+ ```
126
+
127
+ Generate an API token at Cloudflare Dashboard → My Profile → API Tokens → Create Token (use the "Edit Cloudflare Workers" template).
128
+
129
+ ## Preview Deployments
130
+
131
+ ```bash
132
+ # Create a preview deployment (does not affect production)
133
+ npx wrangler deploy --env staging
134
+
135
+ # View deployment history
136
+ npx wrangler deployments list
137
+ ```
138
+
139
+ ## Rollback
140
+
141
+ ```bash
142
+ # List recent deployments with version IDs
143
+ npx wrangler deployments list
144
+
145
+ # Roll back to a previous deployment
146
+ npx wrangler rollback <version-id>
147
+ ```
@@ -0,0 +1,118 @@
1
+ # Cloudflare Storage
2
+
3
+ ## Storage Decision Guide
4
+
5
+ | Need | Use |
6
+ |------|-----|
7
+ | Config, feature flags, sessions, cache | KV (eventually consistent) |
8
+ | Relational SQL data, strong consistency | D1 (SQLite) |
9
+ | Files, images, large blobs | R2 (S3-compatible) |
10
+ | Stateful coordination, locks, real-time sync | Durable Objects |
11
+ | Background job queues | Queues |
12
+
13
+ ---
14
+
15
+ ## KV (Key-Value)
16
+
17
+ ```typescript
18
+ // Read
19
+ const value = await env.MY_KV.get('key');
20
+ const json = await env.MY_KV.get<MyType>('key', { type: 'json' });
21
+ const buffer = await env.MY_KV.get('key', { type: 'arrayBuffer' });
22
+
23
+ // Write
24
+ await env.MY_KV.put('key', 'value');
25
+ await env.MY_KV.put('key', JSON.stringify(data));
26
+ await env.MY_KV.put('key', 'value', {
27
+ expirationTtl: 3600, // expire in 1 hour
28
+ metadata: { userId: '123' }, // up to 1024 bytes of metadata
29
+ });
30
+
31
+ // Delete
32
+ await env.MY_KV.delete('key');
33
+
34
+ // List keys
35
+ const { keys, list_complete, cursor } = await env.MY_KV.list({ prefix: 'user:' });
36
+ for (const key of keys) {
37
+ console.log(key.name, key.metadata);
38
+ }
39
+ ```
40
+
41
+ **KV limits:** Reads are eventually consistent (up to 60s lag). Max value size: 25MB. Max key size: 512 bytes.
42
+
43
+ ---
44
+
45
+ ## D1 (SQLite at Edge)
46
+
47
+ ```typescript
48
+ // Single query
49
+ const stmt = env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId);
50
+ const { results } = await stmt.all<User>();
51
+ const user = await stmt.first<User>();
52
+
53
+ // Insert / update
54
+ const result = await env.DB
55
+ .prepare('INSERT INTO posts (id, title, author_id) VALUES (?, ?, ?)')
56
+ .bind(id, title, authorId)
57
+ .run();
58
+ console.log(result.meta.changes); // rows affected
59
+
60
+ // Batch (multiple queries in one round trip)
61
+ const results = await env.DB.batch([
62
+ env.DB.prepare('INSERT INTO logs (event) VALUES (?)').bind('login'),
63
+ env.DB.prepare('UPDATE users SET last_seen = ? WHERE id = ?').bind(now, userId),
64
+ ]);
65
+
66
+ // Dump (returns all results)
67
+ const { results: allUsers } = await env.DB.prepare('SELECT * FROM users').all<User>();
68
+ ```
69
+
70
+ **Always use parameterized queries** — never interpolate user input into SQL strings.
71
+
72
+ ### D1 Migrations
73
+
74
+ ```bash
75
+ # Create migration file
76
+ wrangler d1 migrations create my-db add-users-table
77
+
78
+ # Apply migrations (local)
79
+ wrangler d1 migrations apply my-db --local
80
+
81
+ # Apply migrations (remote/production)
82
+ wrangler d1 migrations apply my-db --remote
83
+ ```
84
+
85
+ ---
86
+
87
+ ## R2 (Object Storage)
88
+
89
+ ```typescript
90
+ // Upload
91
+ await env.MY_BUCKET.put('images/photo.jpg', imageBuffer, {
92
+ httpMetadata: { contentType: 'image/jpeg' },
93
+ customMetadata: { uploadedBy: userId },
94
+ });
95
+
96
+ // Download
97
+ const object = await env.MY_BUCKET.get('images/photo.jpg');
98
+ if (!object) return new Response('Not found', { status: 404 });
99
+
100
+ // Stream the body directly to the response
101
+ return new Response(object.body, {
102
+ headers: { 'Content-Type': object.httpMetadata?.contentType ?? 'application/octet-stream' },
103
+ });
104
+
105
+ // Delete
106
+ await env.MY_BUCKET.delete('images/photo.jpg');
107
+
108
+ // List
109
+ const { objects, truncated, cursor } = await env.MY_BUCKET.list({ prefix: 'images/' });
110
+
111
+ // Multipart upload (large files >100MB)
112
+ const upload = await env.MY_BUCKET.createMultipartUpload('large-file.zip');
113
+ const part1 = await upload.uploadPart(1, chunk1);
114
+ const part2 = await upload.uploadPart(2, chunk2);
115
+ await upload.complete([part1, part2]);
116
+ ```
117
+
118
+ **R2 is S3-compatible** — existing S3 SDKs work with R2 by pointing to the R2 endpoint URL.
@@ -0,0 +1,135 @@
1
+ # Cloudflare Workers
2
+
3
+ ## Worker Structure
4
+
5
+ ```typescript
6
+ // src/index.ts
7
+ export interface Env {
8
+ // Declare all bindings here — must match wrangler.toml
9
+ MY_KV: KVNamespace;
10
+ MY_DB: D1Database;
11
+ MY_BUCKET: R2Bucket;
12
+ MY_SECRET: string;
13
+ }
14
+
15
+ export default {
16
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
17
+ // Handle HTTP requests
18
+ return new Response('Hello World');
19
+ },
20
+
21
+ async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
22
+ // Handle Cron Triggers
23
+ ctx.waitUntil(doScheduledWork(env));
24
+ },
25
+ } satisfies ExportedHandler<Env>;
26
+ ```
27
+
28
+ ## Bindings in wrangler.toml
29
+
30
+ ```toml
31
+ name = "my-worker"
32
+ main = "src/index.ts"
33
+ compatibility_date = "2024-12-01"
34
+
35
+ [[kv_namespaces]]
36
+ binding = "MY_KV"
37
+ id = "abc123"
38
+
39
+ [[d1_databases]]
40
+ binding = "MY_DB"
41
+ database_name = "my-db"
42
+ database_id = "xyz789"
43
+
44
+ [[r2_buckets]]
45
+ binding = "MY_BUCKET"
46
+ bucket_name = "my-bucket"
47
+
48
+ [vars]
49
+ ENVIRONMENT = "production"
50
+
51
+ # Secrets are NOT stored in wrangler.toml — use: wrangler secret put SECRET_NAME
52
+ ```
53
+
54
+ ## ctx.waitUntil
55
+
56
+ Use `ctx.waitUntil()` for async work that must not block the response:
57
+
58
+ ```typescript
59
+ export default {
60
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
61
+ const response = await handleRequest(request, env);
62
+
63
+ // Logs, analytics, cache warming — run after response is sent
64
+ ctx.waitUntil(logToAnalytics(request, response, env));
65
+
66
+ return response;
67
+ },
68
+ };
69
+ ```
70
+
71
+ ## Routing
72
+
73
+ ```typescript
74
+ import { Router } from 'itty-router'; // popular lightweight router
75
+
76
+ const router = Router();
77
+
78
+ router
79
+ .get('/api/users', (request, env) => handleGetUsers(env))
80
+ .post('/api/users', (request, env) => handleCreateUser(request, env))
81
+ .all('*', () => new Response('Not found', { status: 404 }));
82
+
83
+ export default { fetch: router.fetch } satisfies ExportedHandler<Env>;
84
+ ```
85
+
86
+ ## Durable Objects (basics)
87
+
88
+ ```typescript
89
+ // src/counter.ts
90
+ export class Counter implements DurableObject {
91
+ state: DurableObjectState;
92
+
93
+ constructor(state: DurableObjectState, env: Env) {
94
+ this.state = state;
95
+ }
96
+
97
+ async fetch(request: Request): Promise<Response> {
98
+ const count = (await this.state.storage.get<number>('count')) ?? 0;
99
+ const newCount = count + 1;
100
+ await this.state.storage.put('count', newCount);
101
+ return Response.json({ count: newCount });
102
+ }
103
+ }
104
+ ```
105
+
106
+ ```toml
107
+ # wrangler.toml
108
+ [[durable_objects.bindings]]
109
+ name = "COUNTER"
110
+ class_name = "Counter"
111
+
112
+ [[migrations]]
113
+ tag = "v1"
114
+ new_classes = ["Counter"]
115
+ ```
116
+
117
+ ## Cron Triggers
118
+
119
+ ```toml
120
+ # wrangler.toml
121
+ [triggers]
122
+ crons = ["0 * * * *"] # every hour
123
+ ```
124
+
125
+ ## Wrangler Commands
126
+
127
+ | Command | Purpose |
128
+ |---------|---------|
129
+ | `npx wrangler dev` | Local development server (hot reload) |
130
+ | `npx wrangler deploy` | Deploy to production |
131
+ | `npx wrangler tail` | Live log streaming from production |
132
+ | `wrangler secret put NAME` | Store a secret securely |
133
+ | `wrangler kv:key put --binding=KV key value` | Write a KV value |
134
+ | `wrangler d1 execute DB --command="SELECT 1"` | Run a D1 SQL command |
135
+ | `wrangler whoami` | Verify authenticated account |