@liquidmetal-ai/raindrop 0.13.0 → 0.15.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 (250) hide show
  1. package/README.md +327 -89
  2. package/bundle/build-CBEGQPJT.js +62 -0
  3. package/bundle/{chunk-IEF2XC25.js → chunk-2PH3PHH3.js} +5 -3
  4. package/bundle/{chunk-4HZ22KOV.js → chunk-3CMR7ES5.js} +4 -4
  5. package/bundle/{chunk-JSBM2JYW.js → chunk-3EYKCHIK.js} +1 -1
  6. package/bundle/chunk-5XHDP4VK.js +1697 -0
  7. package/bundle/{chunk-TSQK4HH6.js → chunk-674GMSXY.js} +1 -1
  8. package/bundle/{chunk-PS3WZBDF.js → chunk-6L4V66WZ.js} +1105 -2728
  9. package/bundle/{chunk-5245CEUM.js → chunk-AGG7JZVH.js} +2 -2
  10. package/bundle/{chunk-3GFKUF5D.js → chunk-B3IY2XS6.js} +4 -2
  11. package/bundle/{chunk-WIDI65NO.js → chunk-CBAXTRCS.js} +1 -1
  12. package/bundle/{chunk-JLVDTXO2.js → chunk-DPV5HIG7.js} +4 -4
  13. package/bundle/{chunk-36GNZK4A.js → chunk-EVXLXWP7.js} +1 -1
  14. package/bundle/{chunk-4YVU5KEQ.js → chunk-HN3AAKRY.js} +4 -2
  15. package/bundle/{chunk-NVNEQXHN.js → chunk-IGLE4Y3B.js} +7 -5
  16. package/bundle/{chunk-FGSYWVBA.js → chunk-IQ6HFRA6.js} +1 -1
  17. package/bundle/{chunk-O3QZDJ75.js → chunk-JQONDSHY.js} +2 -2
  18. package/bundle/{chunk-W4IPOFZC.js → chunk-KADMFJLN.js} +8 -6
  19. package/bundle/chunk-KG5BLUGU.js +246 -0
  20. package/bundle/{chunk-V5LHJTYS.js → chunk-KLOYSTZY.js} +13 -2
  21. package/bundle/{chunk-ETC5VU7H.js → chunk-KXHVSLAI.js} +1 -1
  22. package/bundle/{chunk-Y4WFGNPM.js → chunk-L6FRQULN.js} +1 -1
  23. package/bundle/{chunk-3QCVYSRU.js → chunk-LT3BFQ4O.js} +1 -1
  24. package/bundle/{chunk-KQZJHBNG.js → chunk-MBLKVNI5.js} +1 -1
  25. package/bundle/{chunk-6AIUQUUM.js → chunk-MFMVJZW6.js} +71 -15
  26. package/bundle/{chunk-25T7MEKO.js → chunk-MJBLNWG3.js} +1 -1
  27. package/bundle/{chunk-MSJ33O5Y.js → chunk-NRCQIE3Z.js} +95 -115
  28. package/bundle/{chunk-XKKPPSPC.js → chunk-OCYTN4IH.js} +2 -2
  29. package/bundle/{chunk-2GAMWFJE.js → chunk-QEF5D4VE.js} +1 -1
  30. package/bundle/{chunk-4B3QYXBA.js → chunk-T7MQCLXF.js} +5 -3
  31. package/bundle/{chunk-LDFYPOXJ.js → chunk-TFQY5TSY.js} +1 -1
  32. package/bundle/{chunk-BWK4MC7Y.js → chunk-USZXZZAR.js} +8 -6
  33. package/bundle/{chunk-ER2RCPCY.js → chunk-V54KHS5B.js} +2 -2
  34. package/bundle/{chunk-YSKASURB.js → chunk-V6J23FL2.js} +1 -1
  35. package/bundle/{chunk-UHSTDJ7X.js → chunk-VN2QYX4C.js} +1 -1
  36. package/bundle/{chunk-Z4OWKG7J.js → chunk-VOT5MMEY.js} +1 -1
  37. package/bundle/{chunk-W6GU26WO.js → chunk-WG6BDFPZ.js} +1 -1
  38. package/bundle/{chunk-AK77X5GL.js → chunk-XX74I5RK.js} +4 -2
  39. package/bundle/{chunk-6BT265R3.js → chunk-YQCRWPNI.js} +1 -1
  40. package/bundle/commands/annotation/get.js +3 -3
  41. package/bundle/commands/annotation/list.js +3 -3
  42. package/bundle/commands/annotation/put.js +3 -3
  43. package/bundle/commands/auth/apikey.js +2 -2
  44. package/bundle/commands/auth/list.js +2 -2
  45. package/bundle/commands/auth/login.js +2 -2
  46. package/bundle/commands/auth/logout.js +2 -2
  47. package/bundle/commands/auth/select.js +3 -3
  48. package/bundle/commands/bucket/create-credential.js +2 -2
  49. package/bundle/commands/bucket/delete-credential.js +2 -2
  50. package/bundle/commands/bucket/get-credential.js +2 -2
  51. package/bundle/commands/bucket/list-credentials.js +2 -2
  52. package/bundle/commands/build/actor/setup.js +124 -0
  53. package/bundle/commands/build/branch.js +10 -10
  54. package/bundle/commands/build/bucket-events/setup.js +146 -0
  55. package/bundle/commands/build/checkout.js +8 -8
  56. package/bundle/commands/build/clone.js +6 -6
  57. package/bundle/commands/build/delete.js +8 -8
  58. package/bundle/commands/build/deploy.js +10 -10
  59. package/bundle/commands/build/env/get.js +3 -3
  60. package/bundle/commands/build/env/list.js +2 -2
  61. package/bundle/commands/build/env/set.js +3 -3
  62. package/bundle/commands/build/env.js +2 -2
  63. package/bundle/commands/build/features.js +192 -0
  64. package/bundle/commands/build/find.js +4 -4
  65. package/bundle/commands/build/generate.js +52 -3
  66. package/bundle/commands/build/init-workspace.js +3 -3
  67. package/bundle/commands/build/init.js +15 -3
  68. package/bundle/commands/build/list.js +5 -5
  69. package/bundle/commands/build/queue/setup.js +133 -0
  70. package/bundle/commands/build/sandbox.js +6 -6
  71. package/bundle/commands/build/smartbucket/setup.js +165 -0
  72. package/bundle/commands/build/smartmemory/setup.js +171 -0
  73. package/bundle/commands/build/smartsql/setup.js +167 -0
  74. package/bundle/commands/build/start.js +2 -2
  75. package/bundle/commands/build/status.js +5 -5
  76. package/bundle/commands/build/stop.js +2 -2
  77. package/bundle/commands/build/stripe/dashboard.js +3 -3
  78. package/bundle/commands/build/stripe/onboard.js +3 -3
  79. package/bundle/commands/build/stripe/setup.js +3 -3
  80. package/bundle/commands/build/stripe/start.js +14 -14
  81. package/bundle/commands/build/stripe/status.js +3 -3
  82. package/bundle/commands/build/stripe/subscription/create.js +4 -4
  83. package/bundle/commands/build/stripe/subscription/get.js +4 -4
  84. package/bundle/commands/build/stripe/subscription/update.js +4 -4
  85. package/bundle/commands/build/tools/check.js +2 -2
  86. package/bundle/commands/build/tools/fmt.js +2 -2
  87. package/bundle/commands/build/unsandbox.js +6 -6
  88. package/bundle/commands/build/upload.js +5 -5
  89. package/bundle/commands/build/validate.js +85 -14
  90. package/bundle/commands/build/workos/delete.js +6 -6
  91. package/bundle/commands/build/workos/env/attach.js +3 -3
  92. package/bundle/commands/build/workos/env/attached.js +3 -3
  93. package/bundle/commands/build/workos/env/create.js +3 -3
  94. package/bundle/commands/build/workos/env/delete.js +3 -3
  95. package/bundle/commands/build/workos/env/detach.js +3 -3
  96. package/bundle/commands/build/workos/env/dev-login.js +3 -3
  97. package/bundle/commands/build/workos/env/get.js +3 -3
  98. package/bundle/commands/build/workos/env/list.js +3 -3
  99. package/bundle/commands/build/workos/env/set.js +3 -3
  100. package/bundle/commands/build/workos/invite.js +3 -3
  101. package/bundle/commands/build/workos/jwt.js +172 -0
  102. package/bundle/commands/build/workos/setup.js +3 -3
  103. package/bundle/commands/build/workos/status.js +3 -3
  104. package/bundle/commands/dns/create.js +2 -2
  105. package/bundle/commands/dns/delete.js +6 -6
  106. package/bundle/commands/dns/get.js +6 -6
  107. package/bundle/commands/dns/list.js +3 -3
  108. package/bundle/commands/dns/records/create.js +2 -2
  109. package/bundle/commands/dns/records/delete.js +3 -3
  110. package/bundle/commands/dns/records/get.js +2 -2
  111. package/bundle/commands/dns/records/list.js +2 -2
  112. package/bundle/commands/dns/records/update.js +2 -2
  113. package/bundle/commands/doctor.js +309 -0
  114. package/bundle/commands/logs/query.js +3 -3
  115. package/bundle/commands/logs/tail.js +3 -3
  116. package/bundle/commands/mcp/install-claude.js +2 -2
  117. package/bundle/commands/mcp/install-gemini.js +2 -2
  118. package/bundle/commands/mcp/install-goose.js +2 -2
  119. package/bundle/commands/mcp/status.js +2 -2
  120. package/bundle/commands/object/delete.js +5 -37
  121. package/bundle/commands/object/get.js +5 -37
  122. package/bundle/commands/object/list.js +7 -39
  123. package/bundle/commands/object/put.js +5 -37
  124. package/bundle/commands/query/chunk-search.js +14 -46
  125. package/bundle/commands/query/document.js +17 -55
  126. package/bundle/commands/query/events.js +2 -2
  127. package/bundle/commands/query/reindex.js +2 -2
  128. package/bundle/commands/query/search.js +14 -46
  129. package/bundle/commands/tail.js +2 -2
  130. package/bundle/index.js +1 -1
  131. package/dist/commands/build/actor/setup.d.ts +22 -0
  132. package/dist/commands/build/actor/setup.d.ts.map +1 -0
  133. package/dist/commands/build/actor/setup.js +116 -0
  134. package/dist/commands/build/bucket-events/setup.d.ts +22 -0
  135. package/dist/commands/build/bucket-events/setup.d.ts.map +1 -0
  136. package/dist/commands/build/bucket-events/setup.js +134 -0
  137. package/dist/commands/build/features.d.ts +19 -0
  138. package/dist/commands/build/features.d.ts.map +1 -0
  139. package/dist/commands/build/features.js +97 -0
  140. package/dist/commands/build/generate.d.ts +2 -0
  141. package/dist/commands/build/generate.d.ts.map +1 -1
  142. package/dist/commands/build/generate.js +52 -0
  143. package/dist/commands/build/init.d.ts.map +1 -1
  144. package/dist/commands/build/init.js +10 -0
  145. package/dist/commands/build/queue/setup.d.ts +21 -0
  146. package/dist/commands/build/queue/setup.d.ts.map +1 -0
  147. package/dist/commands/build/queue/setup.js +120 -0
  148. package/dist/commands/build/smartbucket/setup.d.ts +23 -0
  149. package/dist/commands/build/smartbucket/setup.d.ts.map +1 -0
  150. package/dist/commands/build/smartbucket/setup.js +167 -0
  151. package/dist/commands/build/smartmemory/setup.d.ts +23 -0
  152. package/dist/commands/build/smartmemory/setup.d.ts.map +1 -0
  153. package/dist/commands/build/smartmemory/setup.js +172 -0
  154. package/dist/commands/build/smartsql/setup.d.ts +23 -0
  155. package/dist/commands/build/smartsql/setup.d.ts.map +1 -0
  156. package/dist/commands/build/smartsql/setup.js +169 -0
  157. package/dist/commands/build/validate.d.ts +2 -0
  158. package/dist/commands/build/validate.d.ts.map +1 -1
  159. package/dist/commands/build/validate.js +80 -8
  160. package/dist/commands/build/workos/jwt.d.ts +23 -0
  161. package/dist/commands/build/workos/jwt.d.ts.map +1 -0
  162. package/dist/commands/build/workos/jwt.js +172 -0
  163. package/dist/commands/doctor.d.ts +27 -0
  164. package/dist/commands/doctor.d.ts.map +1 -0
  165. package/dist/commands/doctor.js +328 -0
  166. package/dist/commands/object/delete.d.ts +0 -2
  167. package/dist/commands/object/delete.d.ts.map +1 -1
  168. package/dist/commands/object/delete.js +3 -38
  169. package/dist/commands/object/get.d.ts +0 -2
  170. package/dist/commands/object/get.d.ts.map +1 -1
  171. package/dist/commands/object/get.js +3 -38
  172. package/dist/commands/object/list.d.ts +0 -2
  173. package/dist/commands/object/list.d.ts.map +1 -1
  174. package/dist/commands/object/list.js +5 -40
  175. package/dist/commands/object/put.d.ts +0 -2
  176. package/dist/commands/object/put.d.ts.map +1 -1
  177. package/dist/commands/object/put.js +3 -38
  178. package/dist/commands/query/chunk-search.d.ts +0 -2
  179. package/dist/commands/query/chunk-search.d.ts.map +1 -1
  180. package/dist/commands/query/chunk-search.js +12 -46
  181. package/dist/commands/query/document.d.ts +1 -3
  182. package/dist/commands/query/document.d.ts.map +1 -1
  183. package/dist/commands/query/document.js +16 -60
  184. package/dist/commands/query/search.d.ts +0 -2
  185. package/dist/commands/query/search.d.ts.map +1 -1
  186. package/dist/commands/query/search.js +12 -46
  187. package/dist/feature-catalog.d.ts +28 -0
  188. package/dist/feature-catalog.d.ts.map +1 -0
  189. package/dist/feature-catalog.js +104 -0
  190. package/dist/index.d.ts.map +1 -1
  191. package/dist/index.js +16 -2
  192. package/oclif.manifest.json +4811 -3433
  193. package/package.json +3 -3
  194. package/templates/examples/smartbucket-minimal.ts.hbs +87 -0
  195. package/templates/examples/smartmemory-minimal.ts.hbs +82 -0
  196. package/templates/examples/smartsql-minimal.ts.hbs +69 -0
  197. package/templates/handlers/actor/index.test.ts.hbs +48 -85
  198. package/templates/handlers/actor/index.ts.hbs +16 -316
  199. package/templates/handlers/bucket-event-notification/index.ts.hbs +32 -235
  200. package/templates/handlers/bucket-event-observer.ts.hbs +79 -0
  201. package/templates/handlers/http-service/index.test.ts.hbs +3 -0
  202. package/templates/handlers/http-service/index.ts.hbs +43 -15
  203. package/templates/handlers/queue-consumer-setup.ts.hbs +45 -0
  204. package/templates/handlers/task/index.test.ts.hbs +30 -112
  205. package/templates/handlers/task/index.ts.hbs +19 -58
  206. package/templates/init/RAINDROP.md.hbs +97 -1
  207. package/templates/init/eslint.config.js +43 -0
  208. package/templates/init/package.json.hbs +4 -1
  209. package/templates/init/tsconfig.json +3 -3
  210. package/bundle/chunk-23UBI7BN.js +0 -48
  211. package/bundle/chunk-2QWMBNE3.js +0 -384
  212. package/bundle/chunk-45IYWQDC.js +0 -384
  213. package/bundle/chunk-5YUO23QU.js +0 -4585
  214. package/bundle/chunk-6MIGCNUO.js +0 -75
  215. package/bundle/chunk-7ZJWA6HP.js +0 -805
  216. package/bundle/chunk-AIYVX2M7.js +0 -44
  217. package/bundle/chunk-BB5TNIEM.js +0 -48
  218. package/bundle/chunk-BUR3HFKH.js +0 -488
  219. package/bundle/chunk-BYSBS7KT.js +0 -488
  220. package/bundle/chunk-CX3RWI62.js +0 -28658
  221. package/bundle/chunk-DLH7MI57.js +0 -305
  222. package/bundle/chunk-E3WJIYJZ.js +0 -12148
  223. package/bundle/chunk-EX7NOPRF.js +0 -12148
  224. package/bundle/chunk-F76JQS2J.js +0 -231
  225. package/bundle/chunk-FBOXMVKD.js +0 -28679
  226. package/bundle/chunk-FTPZ6SQW.js +0 -238909
  227. package/bundle/chunk-H3CFZ7ZH.js +0 -74
  228. package/bundle/chunk-HXOILVWA.js +0 -384
  229. package/bundle/chunk-IMP7O5AC.js +0 -22452
  230. package/bundle/chunk-IPYOAKRE.js +0 -231
  231. package/bundle/chunk-J7HN6XF2.js +0 -4461
  232. package/bundle/chunk-JOLOAALA.js +0 -231
  233. package/bundle/chunk-JZ2G4Q35.js +0 -4585
  234. package/bundle/chunk-KVAWPWF7.js +0 -231
  235. package/bundle/chunk-MEUAAIXV.js +0 -28657
  236. package/bundle/chunk-QBWFE57Z.js +0 -384
  237. package/bundle/chunk-SP3LOXPC.js +0 -46
  238. package/bundle/chunk-T7C564PR.js +0 -28678
  239. package/bundle/chunk-UFH545WJ.js +0 -22452
  240. package/bundle/chunk-UHVMPWM5.js +0 -315
  241. package/bundle/chunk-VB7ZTSZV.js +0 -1089
  242. package/bundle/chunk-VBIJDFMJ.js +0 -384
  243. package/bundle/chunk-VR7RLTE3.js +0 -231
  244. package/bundle/chunk-WFZUJLEC.js +0 -231
  245. package/bundle/chunk-YDGJTLVZ.js +0 -133
  246. package/bundle/chunk-YPNQ7UFK.js +0 -502
  247. package/bundle/chunk-YXFDRMSN.js +0 -384
  248. package/dist/lib/dns-utils.d.ts +0 -7
  249. package/dist/lib/dns-utils.d.ts.map +0 -1
  250. package/dist/lib/dns-utils.js +0 -44
@@ -0,0 +1,79 @@
1
+ import {
2
+ BucketEventNotification,
3
+ Each,
4
+ Message,
5
+ } from '@liquidmetal-ai/raindrop-framework';
6
+ import { Env } from './raindrop.gen';
7
+
8
+ /**
9
+ * Bucket Event Observer
10
+ *
11
+ * This observer reacts to events on the "{{bucketName}}" bucket.
12
+ * It processes upload, deletion, and multipart upload events.
13
+ *
14
+ * Use cases:
15
+ * - File processing pipelines
16
+ * - Automatic indexing
17
+ * - Thumbnail generation
18
+ * - Metadata extraction
19
+ * - Backup and sync operations
20
+ */
21
+ export default class extends Each<BucketEventNotification, Env> {
22
+ async process(message: Message<BucketEventNotification>): Promise<void> {
23
+ const event = message.body;
24
+
25
+ this.env.logger.info('Bucket event received', {
26
+ action: event.action,
27
+ bucket: event.bucket,
28
+ key: event.object.key,
29
+ size: event.object.size,
30
+ eTag: event.object.eTag,
31
+ });
32
+
33
+ // Handle different event types
34
+ switch (event.action) {
35
+ case 'ObjectCreated:Put':
36
+ await this.handleUpload(event);
37
+ break;
38
+
39
+ case 'ObjectRemoved:Delete':
40
+ await this.handleDeletion(event);
41
+ break;
42
+
43
+ case 'ObjectCreated:Post':
44
+ await this.handleMultipartUpload(event);
45
+ break;
46
+
47
+ default:
48
+ this.env.logger.warn('Unhandled event type', { action: event.action });
49
+ }
50
+ }
51
+
52
+ private async handleUpload(event: BucketEventNotification): Promise<void> {
53
+ this.env.logger.info('Processing file upload', {
54
+ key: event.object.key,
55
+ size: event.object.size,
56
+ });
57
+
58
+ // Add your upload processing logic here
59
+ // Example: trigger processing, update index, send notifications
60
+ }
61
+
62
+ private async handleDeletion(event: BucketEventNotification): Promise<void> {
63
+ this.env.logger.info('Processing file deletion', {
64
+ key: event.object.key,
65
+ });
66
+
67
+ // Add your deletion logic here
68
+ // Example: clean up related data, update index, notify systems
69
+ }
70
+
71
+ private async handleMultipartUpload(event: BucketEventNotification): Promise<void> {
72
+ this.env.logger.info('Processing multipart upload', {
73
+ key: event.object.key,
74
+ size: event.object.size,
75
+ });
76
+
77
+ // Add your multipart upload logic here
78
+ }
79
+ }
@@ -31,8 +31,11 @@ function createMockEnv() {
31
31
  import handler from './index.js';
32
32
 
33
33
  describe('{{serviceName}} HTTP Service', () => {
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
35
  let service: any;
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
37
  let env: any;
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
39
  let ctx: any;
37
40
 
38
41
  beforeEach(() => {
@@ -2,12 +2,12 @@ import { Service } from '@liquidmetal-ai/raindrop-framework';
2
2
  import { Hono } from 'hono';
3
3
  import { Env } from './raindrop.gen';
4
4
 
5
- // Web API types that should be available in Cloudflare Workers
6
- // These type aliases ensure compatibility between test and runtime environments
7
- type Headers = globalThis.Headers;
8
- type Blob = globalThis.Blob;
9
- type FormData = globalThis.FormData;
10
- type ReadableStream = globalThis.ReadableStream;
5
+ // Web API types available in Cloudflare Workers runtime:
6
+ // Uncomment these type aliases if you need to ensure compatibility between test and runtime environments
7
+ // type Headers = globalThis.Headers;
8
+ // type Blob = globalThis.Blob;
9
+ // type FormData = globalThis.FormData;
10
+ // type ReadableStream = globalThis.ReadableStream;
11
11
 
12
12
  // Create Hono app
13
13
  const app = new Hono<{ Bindings: Env }>();
@@ -18,6 +18,10 @@ app.get('/health', (c) => {
18
18
  });
19
19
 
20
20
  // === Add Your API Routes Here ===
21
+ //
22
+ // IMPORTANT: The example endpoints below are used by tests.
23
+ // DO NOT remove them - add your new endpoints alongside these examples.
24
+ // Removing these endpoints will break the test suite.
21
25
 
22
26
  // Example: Simple GET endpoint
23
27
  app.get('/api/hello', (c) => {
@@ -46,16 +50,38 @@ app.post('/api/echo', async (c) => {
46
50
  }
47
51
  });
48
52
 
49
- // === Production Patterns Available ===
50
- // Need authentication, database, or file uploads? These are available:
53
+ // Add your production endpoints here (keep examples above for tests):
54
+ // app.post('/chat', async (c) => { /* your logic */ });
55
+ // app.post('/upload', async (c) => { /* your logic */ });
56
+
57
+ // === Add Production Features ===
58
+ // IMPORTANT: Use setup commands to get working examples with correct APIs!
59
+ //
60
+ // $ raindrop build features # See all 8 available features
61
+ // $ raindrop build smartmemory setup # Conversation memory → src/examples/
62
+ // $ raindrop build smartsql setup # Database queries → src/examples/
63
+ // $ raindrop build smartbucket setup # File storage → src/examples/
64
+ // $ raindrop build workos setup # Authentication
65
+ // $ raindrop build stripe setup # Payments
66
+ //
67
+ // Setup commands create src/examples/ with actual API usage.
68
+ // DO NOT guess at APIs - check examples for correct methods!
69
+ //
70
+ // === AI Model Usage ===
71
+ // The AI binding is automatically available via this.env.AI
72
+ // DO NOT declare "ai" in your manifest - it's auto-provided!
51
73
  //
52
- // File storage & AI search → https://docs.liquidmetal.ai/reference/smartbucket
53
- // Database & natural language queries → https://docs.liquidmetal.ai/reference/smartsql
54
- // • AI agent memory management → https://docs.liquidmetal.ai/reference/smartmemory
55
- // Background job processing https://docs.liquidmetal.ai/reference/queue
56
- // • Authentication & security → https://docs.liquidmetal.ai/sdk/authentication
74
+ // Correct usage:
75
+ // const result = await this.env.AI.run('openai', {
76
+ // model: 'gpt-4',
77
+ // messages: [{ role: 'user', content: 'Hello' }]
78
+ // });
57
79
  //
58
- // These production features are automatically configured when you add resources to your raindrop.manifest
80
+ // For Llama models:
81
+ // const result = await this.env.AI.run('openai', {
82
+ // model: 'llama-3.3-70b',
83
+ // messages: [...]
84
+ // });
59
85
 
60
86
  export default class extends Service<Env> {
61
87
  async fetch(request: Request): Promise<Response> {
@@ -65,6 +91,8 @@ export default class extends Service<Env> {
65
91
  // • Rate limiting and security headers
66
92
  // • Metrics collection and health monitoring
67
93
 
68
- return app.fetch(request, this.env, this.ctx);
94
+ // IMPORTANT: Pass this.env so Hono routes can access bindings via c.env
95
+ // DO NOT pass this.ctx (ExecutionContext) - Hono only accepts (request, env)
96
+ return app.fetch(request, this.env);
69
97
  }
70
98
  }
@@ -0,0 +1,45 @@
1
+ import { Each, Message } from '@liquidmetal-ai/raindrop-framework';
2
+ import { Env } from './raindrop.gen';
3
+
4
+ /**
5
+ * {{queueName}} Consumer
6
+ *
7
+ * This observer processes messages from the "{{queueName}}" queue.
8
+ * Messages are processed asynchronously in the background.
9
+ *
10
+ * Use cases:
11
+ * - Background job processing
12
+ * - Async task execution
13
+ * - Event-driven workflows
14
+ * - Decoupling services
15
+ */
16
+ export default class extends Each<MessageBody, Env> {
17
+ async process(message: Message<MessageBody>): Promise<void> {
18
+ this.env.logger.info('Processing queue message', {
19
+ messageId: message.id,
20
+ timestamp: message.timestamp,
21
+ body: message.body,
22
+ });
23
+
24
+ // Add your message processing logic here
25
+ // Example: handle different message types
26
+ const body = message.body;
27
+
28
+ if (body.task === 'example-task') {
29
+ await this.handleExampleTask(body);
30
+ }
31
+
32
+ // Message will be automatically acknowledged on successful return
33
+ // Throw an error to retry the message
34
+ }
35
+
36
+ private async handleExampleTask(body: MessageBody): Promise<void> {
37
+ this.env.logger.info('Handling example task', { body });
38
+ // Add your task logic here
39
+ }
40
+ }
41
+
42
+ export interface MessageBody {
43
+ task?: string;
44
+ [key: string]: any;
45
+ }
@@ -1,18 +1,16 @@
1
1
  /**
2
2
  * Tests for Task Handler
3
- *
4
- * BALANCED TESTING PATTERN:
5
- * - Simple setup (2 minutes)
6
- * - Essential production safety (5 critical tests)
7
- * - No complex mock factories
8
- * - Tests actual business logic, not just "doesn't crash"
9
- *
10
- * For 95% of cases, this template provides adequate safety net.
3
+ *
4
+ * FOCUSED TESTING APPROACH:
5
+ * - Simple, essential tests for scheduled tasks
6
+ * - Tests actual task execution
7
+ * - Covers basic error scenarios
8
+ * - Easy to extend with additional tests
11
9
  */
12
10
 
13
11
  import { expect, test, describe, beforeEach, vi } from 'vitest';
14
12
 
15
- // Simple mock environment - add your actual bindings here
13
+ // Simple mock environment with only what this template uses
16
14
  function createMockEnv() {
17
15
  return {
18
16
  _raindrop: {
@@ -26,10 +24,7 @@ function createMockEnv() {
26
24
  error: vi.fn(),
27
25
  warn: vi.fn(),
28
26
  },
29
- // Add your environment bindings that the task uses:
30
- // DATABASE: { executeQuery: vi.fn() },
31
- // CACHE: { get: vi.fn(), put: vi.fn() },
32
- // EXTERNAL_API: { post: vi.fn() },
27
+ // Add additional bindings here as you add features to your task
33
28
  };
34
29
  }
35
30
 
@@ -46,7 +41,7 @@ describe('{{taskClassName}} Task', () => {
46
41
  task = new handler(ctx, env);
47
42
  });
48
43
 
49
- test('can instantiate task', () => {
44
+ test('task instantiates correctly', () => {
50
45
  expect(task).toBeDefined();
51
46
  expect(typeof task.handle).toBe('function');
52
47
  });
@@ -57,124 +52,47 @@ describe('{{taskClassName}} Task', () => {
57
52
  expect(env._raindrop.app.organizationId).toBe('test-org');
58
53
  });
59
54
 
60
- // === ESSENTIAL PRODUCTION SAFETY TESTS ===
55
+ // === Essential Task Tests ===
61
56
 
62
- test('handles basic scheduled events', async () => {
57
+ test('handles scheduled events', async () => {
63
58
  const event: any = {
64
59
  type: 'scheduled',
65
- scheduledTime: new Date().toISOString(),
60
+ scheduledTime: Date.now(),
66
61
  cron: '0 8 * * *',
67
62
  };
68
63
 
69
- // Should handle the event without throwing
70
- await expect(task.handle(event)).resolves.not.toThrow();
71
- });
72
-
73
- test('handles missing event gracefully', async () => {
74
- // Should handle null/undefined events without crashing
75
- await expect(task.handle(null as any)).resolves.not.toThrow();
76
- await expect(task.handle(undefined as any)).resolves.not.toThrow();
77
- });
64
+ await task.handle(event);
78
65
 
79
- test('handles empty event objects', async () => {
80
- const event = {};
81
-
82
- // Should handle empty events gracefully
83
- await expect(task.handle(event as any)).resolves.not.toThrow();
66
+ expect(env.logger.info).toHaveBeenCalledWith(
67
+ 'Scheduled task executed',
68
+ expect.objectContaining({ cron: '0 8 * * *' })
69
+ );
84
70
  });
85
71
 
86
- test('processes multiple consecutive runs', async () => {
72
+ test('handles errors gracefully', async () => {
87
73
  const event: any = {
88
74
  type: 'scheduled',
89
- scheduledTime: new Date().toISOString(),
75
+ scheduledTime: Date.now(),
76
+ cron: '*/5 * * * *',
90
77
  };
91
78
 
92
- // Should handle multiple calls without issues
93
- await task.handle(event);
94
- await task.handle(event);
95
- await task.handle(event);
96
-
97
- expect(true).toBe(true); // If we get here, no errors thrown
79
+ // Should not throw even if task logic errors
80
+ await expect(task.handle(event)).resolves.toBeUndefined();
98
81
  });
99
82
 
100
- test('logs task execution', async () => {
83
+ test('processes multiple consecutive runs', async () => {
101
84
  const event: any = {
102
85
  type: 'scheduled',
103
- scheduledTime: new Date().toISOString(),
86
+ scheduledTime: Date.now(),
87
+ cron: '0 * * * *',
104
88
  };
105
89
 
90
+ await task.handle(event);
91
+ await task.handle(event);
106
92
  await task.handle(event);
107
93
 
108
- // Verify some logging occurred (for debugging)
109
- expect(env.logger.info || env.logger.warn || env.logger.error).toHaveBeenCalled();
110
- });
111
-
112
- // === EDGE CASE GUARD RAILS ===
113
-
114
- test('handles malformed events gracefully', async () => {
115
- // Guard rail: Catches circular reference issues
116
- const event: any = { type: 'test' };
117
- event.self = event; // Circular reference
118
-
119
- // Should not crash during logging or processing
120
- await expect(task.handle(event)).resolves.not.toThrow();
121
- });
122
-
123
- test('handles events with special characters', async () => {
124
- // Guard rail: Ensures no injection issues
125
- const event: any = {
126
- type: 'test',
127
- data: '<script>alert("xss")</script>',
128
- sqlQuery: "'; DROP TABLE users--",
129
- };
130
-
131
- await expect(task.handle(event)).resolves.not.toThrow();
132
- });
133
-
134
- test('handles events with unicode content', async () => {
135
- // Guard rail: Validates UTF-8 handling
136
- const event: any = {
137
- type: 'test',
138
- message: 'Hello 世界 🌍',
139
- unicodeData: '测试数据',
140
- };
141
-
142
- await expect(task.handle(event)).resolves.not.toThrow();
94
+ expect(env.logger.info).toHaveBeenCalledTimes(6); // 3 executions * 2 logs each
143
95
  });
144
96
 
145
- // ADD CUSTOM BUSINESS LOGIC TESTS HERE
146
- // Example:
147
- // test('processes business logic correctly', async () => {
148
- // const mockDb = {
149
- // executeQuery: vi.fn().mockResolvedValue({ success: true })
150
- // };
151
- // env.DATABASE = mockDb;
152
- //
153
- // const event = {
154
- // type: 'daily_report',
155
- // reportType: 'sales'
156
- // };
157
- //
158
- // await task.handle(event);
159
- //
160
- // expect(mockDb.executeQuery).toHaveBeenCalledWith(
161
- // expect.stringContaining('sales_report')
162
- // );
163
- // });
164
- //
165
- // test('handles external API calls', async () => {
166
- // const mockApi = {
167
- // post: vi.fn().mockResolvedValue({ status: 'ok' })
168
- // };
169
- // env.EXTERNAL_API = mockApi;
170
- //
171
- // const event = {
172
- // type: 'sync_data',
173
- // endpoint: '/webhook'
174
- // };
175
- //
176
- // await task.handle(event);
177
- //
178
- // expect(mockApi.post).toHaveBeenCalled();
179
- // });
180
- });
97
+ // === Add Your Custom Tests Here ===
98
+ });
@@ -4,72 +4,33 @@ import { Env } from './raindrop.gen';
4
4
  export default class extends Task<Env> {
5
5
  async handle(event: Event): Promise<void> {
6
6
  try {
7
- // Basic event validation - Event interface has specific fields
8
- if (!event || typeof event !== 'object') {
9
- this.env.logger.warn('Invalid event received', { eventType: 'invalid' });
10
- return;
11
- }
12
-
13
- // Extract event type safely - Event only has 'scheduled' type
14
- const eventType = event.type || 'scheduled';
15
- const eventData = event; // Event object contains cron, type, scheduledTime
16
-
17
- this.env.logger.info('Task executed', {
18
- eventType,
19
- scheduledTime: event.scheduledTime
7
+ this.env.logger.info('Scheduled task executed', {
8
+ cron: event.cron,
9
+ scheduledTime: event.scheduledTime,
20
10
  });
21
11
 
22
- // Handle different event types (currently only 'scheduled' exists)
23
- if (eventType === 'scheduled') {
24
- await this.handleScheduledTask(eventData);
25
- } else {
26
- // For future event types
27
- this.env.logger.warn('Unknown event type', { eventType });
28
- }
12
+ // === Add Your Task Logic Here ===
13
+
14
+ // Example: Process scheduled data cleanup, reports, etc.
15
+ await this.processScheduledTask(event);
16
+
29
17
  } catch (error) {
30
18
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
31
- this.env.logger.error('Task execution failed', {
19
+ this.env.logger.error('Task execution failed', {
32
20
  error: errorMessage,
33
- eventType: event?.type || 'unknown'
21
+ cron: event.cron,
34
22
  });
35
-
36
- // Don't throw - tasks should handle errors gracefully
37
- return;
38
23
  }
39
24
  }
40
25
 
41
- private async handleScheduledTask(data: any): Promise<void> {
42
- this.env.logger.info('Processing scheduled task', { cron: data.cron });
43
-
44
- // Note: waitUntil background operations
45
- // This depends on execution context - commented out for now
46
- // if ('waitUntil' in this.env) {
47
- // this.env.waitUntil(Promise.resolve('Background operation'));
48
- // }
49
- }
50
-
51
- private async handleManualTask(data: any): Promise<void> {
52
- this.env.logger.info('Processing manual task', { data });
53
- }
54
-
55
- // === Integration Examples ===
26
+ private async processScheduledTask(event: Event): Promise<void> {
27
+ this.env.logger.info('Processing scheduled task', { cron: event.cron });
56
28
 
57
- // Example: Call an actor (if you have actors in manifest)
58
- private async callActor(actorName: string, methodName: string, data: any): Promise<any> {
59
- return { error: 'Actor integration not implemented in this template' };
60
- }
61
-
62
- // Example: Use storage - update bucket binding name to match your manifest
63
- private async saveResult(key: string, data: any): Promise<void> {
64
- try {
65
- // Example: Use FILES binding (if you have bucket "files" in manifest)
66
- // const bucket = this.env.FILES;
67
- // Replace with your actual bucket binding name from raindrop.gen.ts
68
- throw new Error('Bucket binding not configured - update this method to use your bucket binding');
69
- } catch (error) {
70
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
71
- this.env.logger.error('Failed to save result', { error: errorMessage, key });
72
- throw error;
73
- }
29
+ // Add your scheduled task logic here
30
+ // Examples:
31
+ // - Generate daily reports
32
+ // - Clean up old data
33
+ // - Send scheduled notifications
34
+ // - Aggregate metrics
74
35
  }
75
- }
36
+ }
@@ -23,7 +23,18 @@ A Raindrop application built with Hono.js and modern web technologies.
23
23
  raindrop build generate
24
24
  ```
25
25
 
26
- 3. **Deploy to Raindrop**
26
+ 3. **Discover available features** (recommended for new apps)
27
+ ```bash
28
+ raindrop build features
29
+ ```
30
+
31
+ 4. **Add features you need** (example)
32
+ ```bash
33
+ raindrop build smartmemory setup
34
+ raindrop build smartsql setup
35
+ ```
36
+
37
+ 5. **Deploy to Raindrop**
27
38
  ```bash
28
39
  raindrop build deploy --start
29
40
  ```
@@ -33,6 +44,53 @@ A Raindrop application built with Hono.js and modern web technologies.
33
44
  npm run start
34
45
  ```
35
46
 
47
+ ## Best Practices for Using Examples
48
+
49
+ When adding features to your app, follow this workflow to avoid issues:
50
+
51
+ ### ✅ Recommended Workflow
52
+
53
+ 1. **Run setup commands to get examples**
54
+ ```bash
55
+ raindrop build smartmemory setup
56
+ raindrop build smartsql setup
57
+ ```
58
+
59
+ 2. **Test that examples compile**
60
+ ```bash
61
+ npm run build
62
+ ```
63
+ If examples don't compile, check that you ran `raindrop build generate` first.
64
+
65
+ 3. **Study the examples for correct API usage**
66
+ ```bash
67
+ cat src/examples/smartmemory-minimal.ts
68
+ ```
69
+ Examples show actual available methods - do not guess at APIs!
70
+
71
+ 4. **Adapt examples for your use case**
72
+ Copy patterns from examples into your handlers. Don't rewrite from scratch.
73
+
74
+ ### ❌ Common Mistakes to Avoid
75
+
76
+ - **Don't remove template example endpoints** - The `/api/hello`, `/api/echo` endpoints are used by tests. Add your endpoints alongside them, don't replace them.
77
+ - **Don't manually edit manifest without running generate** - You'll be missing TypeScript types
78
+ - **Don't guess at API methods** - Check examples for actual available methods
79
+ - SmartBucket has: `put()`, `get()`, `list()`, `delete()`, `head()` (no `search()`!)
80
+ - SmartMemory has: `startWorkingMemorySession()`, `getWorkingMemorySession(sessionId)`
81
+ - SmartSQL has: `executeQuery({ sqlQuery })`, `executeQuery({ textQuery })`
82
+ - **Don't ignore binding names** - Use the exact names from your manifest in examples
83
+ - **Don't skip `npm run build`** - Compile errors catch API mistakes early
84
+ - **Don't declare `ai` in manifest** - AI is auto-available via `this.env.AI`
85
+
86
+ ### 🔍 Troubleshooting
87
+
88
+ If you see errors about missing types or methods:
89
+ 1. Run `raindrop build generate` to update types
90
+ 2. Check `src/examples/` for correct API patterns
91
+ 3. Verify binding names match between manifest and code
92
+ 4. Run `npm run build` to catch TypeScript errors
93
+
36
94
  ## Raindrop Commands
37
95
 
38
96
  ### Essential Commands
@@ -41,6 +99,7 @@ A Raindrop application built with Hono.js and modern web technologies.
41
99
  |---------|-------------|-------------|
42
100
  | `raindrop build validate` | Validate your manifest | After changing `raindrop.manifest` |
43
101
  | `raindrop build generate` | Generate TypeScript types and handler scaffolding | After changing `raindrop.manifest` |
102
+ | `raindrop build features` | List available features and integrations | When starting or adding functionality |
44
103
  | `raindrop build deploy --start` | Build, upload and start your application | When ready to deploy |
45
104
  | `raindrop build stop` | Stop your running application | To stop services |
46
105
  | `raindrop build status` | Check deployment status | To see current state |
@@ -141,6 +200,40 @@ import { corsAllowAll } from '@liquidmetal-ai/raindrop-framework/core/cors';
141
200
  export const cors = corsAllowAll;
142
201
  ```
143
202
 
203
+ ## Available Features
204
+
205
+ Raindrop provides powerful features you can add to your application. Discover them with:
206
+
207
+ ```bash
208
+ raindrop build features
209
+ ```
210
+
211
+ ### Popular Features
212
+
213
+ | Feature | Description | Setup Command |
214
+ |---------|-------------|---------------|
215
+ | **SmartMemory** | AI conversation memory management | `raindrop build smartmemory setup` |
216
+ | **SmartSQL** | PostgreSQL with natural language queries | `raindrop build smartsql setup` |
217
+ | **SmartBucket** | File storage with AI-powered search | `raindrop build smartbucket setup` |
218
+ | **Stateful Actor** | Durable objects with state management | `raindrop build actor setup` |
219
+ | **Queue Consumer** | Background message processing | `raindrop build queue setup` |
220
+ | **WorkOS Auth** | Authentication with WorkOS | `raindrop build workos setup` |
221
+ | **Stripe Payments** | Payment processing with Stripe | `raindrop build stripe setup` |
222
+
223
+ ### Example: Adding SmartMemory
224
+
225
+ ```bash
226
+ # 1. Set up SmartMemory in your app
227
+ raindrop build smartmemory setup
228
+
229
+ # 2. Generate updated types
230
+ raindrop build generate
231
+
232
+ # 3. Use in your handler
233
+ const { workingMemory } = await this.env.MEMORY.startWorkingMemorySession();
234
+ await workingMemory.putMemory({ content: 'Hello', agent: 'user' });
235
+ ```
236
+
144
237
  ## Manifest Configuration
145
238
 
146
239
  Your `raindrop.manifest` defines all resources and modules:
@@ -194,6 +287,9 @@ Your handlers are generated in `src/handlers/` with comprehensive examples:
194
287
  # After raindrop init
195
288
  npm install
196
289
  raindrop build generate
290
+
291
+ # Optional but recommended: explore features
292
+ raindrop build features
197
293
  ```
198
294
 
199
295
  ### 2. Development Cycle