@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
@@ -1,15 +1,10 @@
1
- import { Actor, ActorState, ActorNamespace, type KvCachePutOptions } from '@liquidmetal-ai/raindrop-framework';
1
+ import { Actor, ActorState } from '@liquidmetal-ai/raindrop-framework';
2
2
  import { Env } from './raindrop.gen';
3
3
 
4
4
  interface {{actorClassName}}State {
5
5
  count: number;
6
6
  lastUpdated: string;
7
- userData: Record<string, any>;
8
- messages: Array<{
9
- id: string;
10
- content: string;
11
- timestamp: string;
12
- }>;
7
+ data: Record<string, any>;
13
8
  }
14
9
 
15
10
  export class {{actorClassName}} extends Actor<Env> {
@@ -20,26 +15,24 @@ export class {{actorClassName}} extends Actor<Env> {
20
15
  // === Initialization ===
21
16
 
22
17
  async initialize(): Promise<void> {
23
- // Initialize default state if not exists
24
18
  const existing = await this.state.storage.get<{{actorClassName}}State>('state');
25
19
  if (!existing) {
26
20
  await this.state.storage.put('state', {
27
21
  count: 0,
28
22
  lastUpdated: new Date().toISOString(),
29
- userData: {},
30
- messages: [],
23
+ data: {},
31
24
  });
32
25
  }
33
26
  }
34
27
 
35
- // === Business Logic Methods ===
28
+ // === Add Your Actor Methods Here ===
36
29
 
37
- async incrementCounter(): Promise<number> {
30
+ // Example: Simple counter
31
+ async increment(): Promise<number> {
38
32
  const state = await this.state.storage.get<{{actorClassName}}State>('state') || {
39
33
  count: 0,
40
34
  lastUpdated: new Date().toISOString(),
41
- userData: {},
42
- messages: [],
35
+ data: {},
43
36
  };
44
37
 
45
38
  const newState = {
@@ -53,318 +46,25 @@ export class {{actorClassName}} extends Actor<Env> {
53
46
  return newState.count;
54
47
  }
55
48
 
56
- async getCounter(): Promise<number> {
49
+ async getCount(): Promise<number> {
57
50
  const state = await this.state.storage.get<{{actorClassName}}State>('state');
58
51
  return state?.count || 0;
59
52
  }
60
53
 
61
- async processMessage(content: string): Promise<{ id: string; content: string; timestamp: string }> {
54
+ async updateData(key: string, value: any): Promise<void> {
62
55
  const state = await this.state.storage.get<{{actorClassName}}State>('state') || {
63
56
  count: 0,
64
57
  lastUpdated: new Date().toISOString(),
65
- userData: {},
66
- messages: [],
58
+ data: {},
67
59
  };
68
60
 
69
- const message = {
70
- id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
71
- content,
72
- timestamp: new Date().toISOString(),
73
- };
74
-
75
- const newState = {
76
- ...state,
77
- messages: [...state.messages, message],
78
- lastUpdated: new Date().toISOString(),
79
- };
80
-
81
- await this.state.storage.put('state', newState);
82
- this.env.logger.info('Message processed', { messageId: message.id });
83
- return message;
61
+ state.data[key] = value;
62
+ state.lastUpdated = new Date().toISOString();
63
+ await this.state.storage.put('state', state);
84
64
  }
85
65
 
86
- async getMessages(): Promise<Array<{ id: string; content: string; timestamp: string }>> {
66
+ async getData(key: string): Promise<any> {
87
67
  const state = await this.state.storage.get<{{actorClassName}}State>('state');
88
- return state?.messages || [];
89
- }
90
-
91
- async clearMessages(): Promise<void> {
92
- const state = await this.state.storage.get<{{actorClassName}}State>('state') || {
93
- count: 0,
94
- lastUpdated: new Date().toISOString(),
95
- userData: {},
96
- messages: [],
97
- };
98
-
99
- const newState = {
100
- ...state,
101
- messages: [],
102
- lastUpdated: new Date().toISOString(),
103
- };
104
-
105
- await this.state.storage.put('state', newState);
106
- this.env.logger.info('Messages cleared');
107
- }
108
-
109
- async getState(): Promise<{{actorClassName}}State | null> {
110
- return await this.state.storage.get<{{actorClassName}}State>('state') || null;
111
- }
112
-
113
- // === Storage Integration ===
114
-
115
- // Example: Save data to bucket
116
- async saveToBucket(key: string, data: any): Promise<{ success: boolean; key?: string; error?: string }> {
117
- try {
118
- // Use bucket binding (add bucket to manifest to use this feature)
119
- const bucket = (this.env as any).FILES;
120
- if (!bucket) {
121
- return { success: false, error: 'Bucket not configured - add bucket to manifest to use this feature' };
122
- }
123
-
124
- await bucket.put(key, JSON.stringify(data));
125
- this.env.logger.info('Data saved to bucket', { key });
126
- return { success: true, key };
127
- } catch (error) {
128
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
129
- this.env.logger.error('Failed to save to bucket', { error: errorMessage, key });
130
- return { success: false, error: errorMessage };
131
- }
132
- }
133
-
134
- // Example: Load data from bucket
135
- async loadFromBucket(key: string): Promise<{ success: boolean; data?: any; error?: string }> {
136
- try {
137
- // Use bucket binding (add bucket to manifest to use this feature)
138
- const bucket = (this.env as any).FILES;
139
- if (!bucket) {
140
- return { success: false, error: 'Bucket not configured - add bucket to manifest to use this feature' };
141
- }
142
-
143
- const object = await bucket.get(key);
144
-
145
- if (!object) {
146
- return { success: false, error: 'Not found' };
147
- }
148
-
149
- const text = await object.text();
150
- const data = JSON.parse(text);
151
- return { success: true, data };
152
- } catch (error) {
153
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
154
- this.env.logger.error('Failed to load from bucket', { error: errorMessage, key });
155
- return { success: false, error: errorMessage };
156
- }
157
- }
158
-
159
- // Example: List bucket contents (no search API exists)
160
- async listBucketContents(prefix?: string): Promise<{ success: boolean; items?: string[]; error?: string }> {
161
- try {
162
- // Use bucket binding (add bucket to manifest to use this feature)
163
- const bucket = (this.env as any).FILES;
164
- if (!bucket) {
165
- return { success: false, error: 'Bucket not configured - add bucket to manifest to use this feature' };
166
- }
167
-
168
- const options = prefix ? { prefix } : undefined;
169
- const result = await bucket.list(options);
170
-
171
- const items = result.objects.map((obj: any) => obj.key);
172
- return { success: true, items };
173
- } catch (error) {
174
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
175
- this.env.logger.error('Failed to list bucket contents', { error: errorMessage, prefix });
176
- return { success: false, error: errorMessage };
177
- }
178
- }
179
-
180
- // === Cache Integration ===
181
-
182
- async cacheResult(key: string, result: any, ttlSeconds?: number): Promise<{ success: boolean; error?: string }> {
183
- try {
184
- // Use KV cache binding (add kv_cache to manifest to use this feature)
185
- const cache = (this.env as any).CACHE || this.env.mem; // mem is always available
186
-
187
- const options: KvCachePutOptions = {};
188
- if (ttlSeconds) {
189
- options.expirationTtl = ttlSeconds;
190
- }
191
-
192
- await cache.put(key, JSON.stringify(result), options);
193
- this.env.logger.info('Result cached', { key, ttl: ttlSeconds });
194
- return { success: true };
195
- } catch (error) {
196
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
197
- this.env.logger.error('Failed to cache result', { error: errorMessage, key });
198
- return { success: false, error: errorMessage };
199
- }
68
+ return state?.data[key];
200
69
  }
201
-
202
- async getCachedResult(key: string): Promise<{ success: boolean; data?: any; error?: string }> {
203
- try {
204
- // Use KV cache binding (add kv_cache to manifest to use this feature)
205
- const cache = (this.env as any).CACHE || this.env.mem; // mem is always available
206
- const cached = await cache.get(key);
207
-
208
- if (cached === null) {
209
- return { success: false, error: 'Not found in cache' };
210
- }
211
-
212
- const data = JSON.parse(cached);
213
- return { success: true, data };
214
- } catch (error) {
215
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
216
- this.env.logger.error('Failed to get cached result', { error: errorMessage, key });
217
- return { success: false, error: errorMessage };
218
- }
219
- }
220
-
221
- // === Queue Integration ===
222
-
223
- // Note: Queue requires adding queue to manifest
224
- async sendToQueue(message: any, delaySeconds?: number): Promise<{ success: boolean; error?: string }> {
225
- return { success: false, error: 'Queue not configured - add queue to manifest to use this feature' };
226
- }
227
-
228
- // === Alarm Scheduling ===
229
-
230
- async schedulePeriodicTask(taskName: string, intervalSeconds: number, taskData?: any): Promise<void> {
231
- const scheduledTime = new Date(Date.now() + intervalSeconds * 1000);
232
-
233
- // Store alarm context
234
- await this.state.storage.put('alarm:context', {
235
- name: taskName,
236
- data: { intervalSeconds, taskData }
237
- });
238
-
239
- // Set alarm using storage API
240
- await this.state.storage.setAlarm(scheduledTime);
241
-
242
- this.env.logger.info('Periodic task scheduled', {
243
- taskName,
244
- scheduledFor: scheduledTime.toISOString()
245
- });
246
- }
247
-
248
- // Alarm handler (called automatically when alarm triggers)
249
- async alarm(): Promise<void> {
250
- try {
251
- const alarmContext = await this.state.storage.get<{
252
- name: string;
253
- data: any;
254
- }>('alarm:context');
255
-
256
- if (!alarmContext) {
257
- this.env.logger.warn('No alarm context found');
258
- return;
259
- }
260
-
261
- this.env.logger.info('Alarm triggered', { name: alarmContext.name, data: alarmContext.data });
262
-
263
- switch (alarmContext.name) {
264
- case 'periodic-count':
265
- const newCount = await this.incrementCounter();
266
- this.env.logger.info('Incremented count via alarm', { newCount });
267
- await this.schedulePeriodicTask('periodic-count', alarmContext.data.intervalSeconds);
268
- break;
269
-
270
- case 'cleanup':
271
- await this.clearMessages();
272
- this.env.logger.info('Completed cleanup task via alarm');
273
- await this.schedulePeriodicTask('cleanup', alarmContext.data.intervalSeconds);
274
- break;
275
-
276
- default:
277
- this.env.logger.warn('Unknown alarm type', { alarmType: alarmContext.name });
278
- }
279
- } catch (error) {
280
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
281
- this.env.logger.error('Error in alarm handler', { error: errorMessage });
282
- }
283
- }
284
-
285
- // === Required Test Methods ===
286
-
287
- async processUserData(userData: any): Promise<{ success: boolean; userId?: string; error?: string }> {
288
- try {
289
- if (!userData.userId || !userData.email) {
290
- return { success: false, error: 'Missing required fields' };
291
- }
292
-
293
- // Increment counter
294
- await this.incrementCounter();
295
-
296
- // Save to bucket
297
- await this.saveToBucket(`user:${userData.userId}`, userData);
298
-
299
- // Cache the result
300
- await this.cacheResult(`user:${userData.userId}`, userData);
301
-
302
- // Send to queue (if configured)
303
- await this.sendToQueue({ type: 'user_processed', userId: userData.userId });
304
-
305
- return { success: true, userId: userData.userId };
306
- } catch (error) {
307
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
308
- return { success: false, error: errorMessage };
309
- }
310
- }
311
-
312
- async getUserData(userId: string): Promise<{ success: boolean; data?: any; error?: string }> {
313
- try {
314
- // Try cache first
315
- const cached = await this.getCachedResult(`user:${userId}`);
316
- if (cached.success) {
317
- return cached;
318
- }
319
-
320
- // Try bucket
321
- const bucketResult = await this.loadFromBucket(`user:${userId}`);
322
- if (bucketResult.success) {
323
- // Cache for future requests
324
- await this.cacheResult(`user:${userId}`, bucketResult.data);
325
- return bucketResult;
326
- }
327
-
328
- return { success: false, error: 'User not found' };
329
- } catch (error) {
330
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
331
- return { success: false, error: errorMessage };
332
- }
333
- }
334
-
335
- async expensiveComputation(input: number): Promise<number> {
336
- const cacheKey = `compute:${input}`;
337
-
338
- // Try cache first
339
- const cached = await this.getCachedResult(cacheKey);
340
- if (cached.success) {
341
- return cached.data;
342
- }
343
-
344
- // Simulate expensive computation as expected by tests
345
- const result = Math.pow(input, 2) + Math.sqrt(input);
346
-
347
- // Cache the result
348
- await this.cacheResult(cacheKey, result);
349
-
350
- return result;
351
- }
352
-
353
- async batchProcessMessages(messages: string[]): Promise<{ processed: number; errors: string[] }> {
354
- let processed = 0;
355
- const errors: string[] = [];
356
-
357
- for (const message of messages) {
358
- try {
359
- await this.processMessage(message);
360
- processed++;
361
- } catch (error) {
362
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
363
- errors.push(errorMessage);
364
- this.env.logger.error('Failed to process message', { message, error: errorMessage });
365
- }
366
- }
367
-
368
- return { processed, errors };
369
- }
370
- }
70
+ }
@@ -8,264 +8,61 @@ import { Env } from './raindrop.gen';
8
8
  export default class extends Each<BucketEventNotification, Env> {
9
9
  async process(message: Message<BucketEventNotification>): Promise<void> {
10
10
  const event = message.body;
11
-
12
- console.log('Bucket event received:', {
11
+
12
+ this.env.logger.info('Bucket event received', {
13
13
  action: event.action,
14
14
  bucket: event.bucket,
15
- objectKey: event.object.key,
15
+ key: event.object.key,
16
16
  size: event.object.size,
17
17
  eTag: event.object.eTag,
18
- eventTime: event.eventTime || new Date().toISOString(),
19
- timestamp: new Date().toISOString()
20
18
  });
21
19
 
20
+ // Handle different event types
22
21
  switch (event.action) {
23
22
  case 'ObjectCreated:Put':
24
- await this.handleFileUpload(event);
23
+ await this.handleUpload(event);
25
24
  break;
26
-
25
+
27
26
  case 'ObjectRemoved:Delete':
28
- await this.handleFileDeletion(event);
27
+ await this.handleDeletion(event);
29
28
  break;
30
-
29
+
31
30
  case 'ObjectCreated:Post':
32
- await this.handleMultiPartUpload(event);
31
+ await this.handleMultipartUpload(event);
33
32
  break;
34
-
35
- default:
36
- console.log('Unhandled event type:', event.action);
37
- }
38
- }
39
-
40
- // === File Upload Handler ===
41
- private async handleFileUpload(event: BucketEventNotification): Promise<void> {
42
- try {
43
- console.log(`Processing uploaded file: ${event.object.key}`);
44
-
45
- // Example: Extract file information
46
- const fileInfo = {
47
- key: event.object.key,
48
- size: event.object.size,
49
- eTag: event.object.eTag,
50
- uploadedAt: new Date().toISOString()
51
- };
52
-
53
- console.log('File info:', fileInfo);
54
-
55
- // Example: Call an actor to process the file
56
- // const processor = this.env.FILE_PROCESSOR_ACTOR;
57
- // await processor.postMessage({
58
- // type: 'processFile',
59
- // data: fileInfo
60
- // });
61
33
 
62
- // Example: Store file metadata in KV cache
63
- // const metadataCache = this.env.FILE_METADATA_KV;
64
- // await metadataCache.put(
65
- // `file:${event.object.key}`,
66
- // JSON.stringify(fileInfo),
67
- // { expirationTtl: 86400 } // 24 hours
68
- // );
69
-
70
- // Example: Send notification to queue
71
- // const notificationQueue = this.env.NOTIFICATION_QUEUE;
72
- // await notificationQueue.send({
73
- // body: JSON.stringify({
74
- // type: 'file_uploaded',
75
- // fileInfo,
76
- // timestamp: new Date().toISOString()
77
- // })
78
- // });
79
-
80
- // Example: Content type detection (would need additional bucket.get() call)
81
- // For now, we'll skip content-type based processing since it's not in the event
82
- await this.triggerFileProcessing(event);
83
-
84
- } catch (error) {
85
- console.error('Error handling file upload:', error);
86
-
87
- // Example: Send error notification
88
- // const errorQueue = this.env.ERROR_QUEUE;
89
- // await errorQueue.send({
90
- // body: JSON.stringify({
91
- // type: 'file_upload_error',
92
- // error: error.message,
93
- // fileInfo: {
94
- // key: event.object.key,
95
- // bucket: event.bucket
96
- // },
97
- // timestamp: new Date().toISOString()
98
- // })
99
- // });
34
+ default:
35
+ this.env.logger.warn('Unhandled event type', { action: event.action });
100
36
  }
101
37
  }
102
38
 
103
- // === File Deletion Handler ===
104
- private async handleFileDeletion(event: BucketEventNotification): Promise<void> {
105
- console.log(`Processing deleted file: ${event.object.key}`);
106
-
107
- // Example: Clean up related data
108
- // const metadataCache = this.env.FILE_METADATA_KV;
109
- // await metadataCache.delete(`file:${event.object.key}`);
110
-
111
- // Example: Notify other services
112
- // const cleanupQueue = this.env.CLEANUP_QUEUE;
113
- // await cleanupQueue.send({
114
- // body: JSON.stringify({
115
- // type: 'file_deleted',
116
- // fileKey: event.object.key,
117
- // timestamp: new Date().toISOString()
118
- // })
119
- // });
120
-
121
- // Example: Update search index
122
- // if (this.env.SMART_BUCKET) {
123
- // try {
124
- // // Remove from search index
125
- // await this.env.SMART_BUCKET.delete({
126
- // key: event.object.key
127
- // });
128
- // console.log(`Removed ${event.object.key} from search index`);
129
- // } catch (error) {
130
- // console.error('Failed to remove from search index:', error);
131
- // }
132
- // }
133
- }
134
-
135
- // === Multi-part Upload Handler ===
136
- private async handleMultiPartUpload(event: BucketEventNotification): Promise<void> {
137
- console.log(`Processing multipart upload: ${event.object.key}`);
138
-
139
- // Example: Trigger post-upload processing
140
- // const postProcessor = this.env.POST_UPLOAD_ACTOR;
141
- // await postProcessor.postMessage({
142
- // type: 'processMultipartUpload',
143
- // data: {
144
- // key: event.object.key,
145
- // size: event.object.size,
146
- // eTag: event.object.eTag
147
- // }
148
- // });
149
- }
150
-
151
- // === Image Processing Example ===
152
- private async triggerImageProcessing(event: BucketEventNotification): Promise<void> {
153
- console.log(`Triggering image processing for: ${event.object.key}`);
154
-
155
- // Example: Call image processing actor
156
- // const imageProcessor = this.env.IMAGE_PROCESSOR_ACTOR;
157
- // await imageProcessor.postMessage({
158
- // type: 'generateThumbnails',
159
- // data: {
160
- // sourceKey: event.object.key,
161
- // bucket: event.bucket,
162
- // eTag: event.object.eTag
163
- // }
164
- // });
165
-
166
- // Example: Extract EXIF data
167
- // const exifExtractor = this.env.EXIF_EXTRACTOR_ACTOR;
168
- // await exifExtractor.postMessage({
169
- // type: 'extractExif',
170
- // data: { key: event.object.key }
171
- // });
172
- }
39
+ // === Add Your Event Handlers Here ===
173
40
 
174
- // === Document Processing Example ===
175
- private async triggerDocumentProcessing(event: BucketEventNotification): Promise<void> {
176
- console.log(`Triggering document processing for: ${event.object.key}`);
177
-
178
- // Example: Extract text and add to SmartBucket for search
179
- // const documentProcessor = this.env.DOCUMENT_PROCESSOR_ACTOR;
180
- // await documentProcessor.postMessage({
181
- // type: 'extractAndIndex',
182
- // data: {
183
- // key: event.object.key,
184
- // bucket: event.bucket,
185
- // eTag: event.object.eTag
186
- // }
187
- // });
188
-
189
- // Example: Generate document summary
190
- // const summarizer = this.env.DOCUMENT_SUMMARIZER_ACTOR;
191
- // await summarizer.postMessage({
192
- // type: 'summarize',
193
- // data: { key: event.object.key }
194
- // });
195
- }
196
-
197
- // === Generic File Processing ===
198
- private async triggerFileProcessing(event: BucketEventNotification): Promise<void> {
199
- console.log(`Triggering generic file processing for: ${event.object.key}`);
200
-
201
- // Content type detection would require fetching the object
202
- // For now, we'll trigger generic processing
203
- // const fileProcessor = this.env.FILE_PROCESSOR_ACTOR;
204
- // await fileProcessor.postMessage({
205
- // type: 'processFile',
206
- // data: {
207
- // key: event.object.key,
208
- // bucket: event.bucket,
209
- // eTag: event.object.eTag
210
- // }
211
- // });
212
- }
41
+ private async handleUpload(event: BucketEventNotification): Promise<void> {
42
+ this.env.logger.info('Processing file upload', {
43
+ key: event.object.key,
44
+ size: event.object.size,
45
+ });
213
46
 
214
- // === Utility Functions ===
215
- private isDocumentType(contentType?: string): boolean {
216
- if (!contentType) return false;
217
-
218
- const documentTypes = [
219
- 'application/pdf',
220
- 'application/msword',
221
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
222
- 'text/plain',
223
- 'text/markdown',
224
- 'text/csv'
225
- ];
226
-
227
- return documentTypes.includes(contentType);
47
+ // Add your upload processing logic here
48
+ // Example: trigger processing, update index, send notifications
228
49
  }
229
50
 
230
- // === Advanced Examples ===
231
-
232
- // Example: Batch processing for multiple files
233
- private async batchProcessFiles(events: BucketEventNotification[]): Promise<void> {
234
- console.log(`Batch processing ${events.length} files`);
235
-
236
- // Group by file extension or other criteria
237
- const grouped = events.reduce((acc, event) => {
238
- const key = event.object.key;
239
- const extension = key.split('.').pop() || 'unknown';
240
- if (!acc[extension]) acc[extension] = [];
241
- acc[extension].push(event);
242
- return acc;
243
- }, {} as Record<string, BucketEventNotification[]>);
51
+ private async handleDeletion(event: BucketEventNotification): Promise<void> {
52
+ this.env.logger.info('Processing file deletion', {
53
+ key: event.object.key,
54
+ });
244
55
 
245
- // Process each group
246
- for (const [extension, files] of Object.entries(grouped)) {
247
- console.log(`Processing ${files.length} files with extension: ${extension}`);
248
-
249
- if (['jpg', 'jpeg', 'png', 'gif'].includes(extension)) {
250
- // Process images in batch
251
- // const batchProcessor = this.env.IMAGE_BATCH_PROCESSOR;
252
- // await batchProcessor.postMessage({
253
- // type: 'batchProcess',
254
- // data: files.map(f => ({ key: f.object.key, bucket: f.bucket }))
255
- // });
256
- }
257
- }
56
+ // Add your deletion logic here
57
+ // Example: clean up related data, update index, notify systems
258
58
  }
259
59
 
260
- // Example: File validation
261
- private async validateFile(event: BucketEventNotification): Promise<{ valid: boolean; reason?: string }> {
262
- // Check file size
263
- const maxSize = 100 * 1024 * 1024; // 100MB
264
- if (event.object.size && event.object.size > maxSize) {
265
- return { valid: false, reason: 'File too large' };
266
- }
60
+ private async handleMultipartUpload(event: BucketEventNotification): Promise<void> {
61
+ this.env.logger.info('Processing multipart upload', {
62
+ key: event.object.key,
63
+ size: event.object.size,
64
+ });
267
65
 
268
- // Additional validation could be added here based on file extension, etc.
269
- return { valid: true };
66
+ // Add your multipart upload logic here
270
67
  }
271
- }
68
+ }