@cloudstreamsoftware/claude-tools 1.0.0 → 1.1.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 (189) hide show
  1. package/README.md +152 -37
  2. package/agents/INDEX.md +183 -0
  3. package/agents/architect.md +247 -0
  4. package/agents/build-error-resolver.md +555 -0
  5. package/agents/catalyst-deployer.md +132 -0
  6. package/agents/code-reviewer.md +121 -0
  7. package/agents/compliance-auditor.md +148 -0
  8. package/agents/creator-architect.md +395 -0
  9. package/agents/deluge-reviewer.md +98 -0
  10. package/agents/doc-updater.md +471 -0
  11. package/agents/e2e-runner.md +711 -0
  12. package/agents/planner.md +122 -0
  13. package/agents/refactor-cleaner.md +309 -0
  14. package/agents/security-reviewer.md +582 -0
  15. package/agents/tdd-guide.md +302 -0
  16. package/config/versions.json +63 -0
  17. package/dist/hooks/hooks.json +209 -0
  18. package/dist/index.js +47 -0
  19. package/dist/lib/asset-value.js +609 -0
  20. package/dist/lib/client-manager.js +300 -0
  21. package/dist/lib/command-matcher.js +242 -0
  22. package/dist/lib/cross-session-patterns.js +754 -0
  23. package/dist/lib/intent-classifier.js +1075 -0
  24. package/dist/lib/package-manager.js +374 -0
  25. package/dist/lib/recommendation-engine.js +597 -0
  26. package/dist/lib/session-memory.js +489 -0
  27. package/dist/lib/skill-effectiveness.js +486 -0
  28. package/dist/lib/skill-matcher.js +595 -0
  29. package/dist/lib/tutorial-metrics.js +242 -0
  30. package/dist/lib/tutorial-progress.js +209 -0
  31. package/dist/lib/tutorial-renderer.js +431 -0
  32. package/dist/lib/utils.js +380 -0
  33. package/dist/lib/verify-formatter.js +143 -0
  34. package/dist/lib/workflow-state.js +249 -0
  35. package/hooks/hooks.json +209 -0
  36. package/package.json +5 -1
  37. package/scripts/aggregate-sessions.js +290 -0
  38. package/scripts/branch-name-validator.js +291 -0
  39. package/scripts/build.js +101 -0
  40. package/scripts/commands/client-switch.js +231 -0
  41. package/scripts/deprecate-skill.js +610 -0
  42. package/scripts/diagnose.js +324 -0
  43. package/scripts/doc-freshness.js +168 -0
  44. package/scripts/generate-weekly-digest.js +393 -0
  45. package/scripts/health-check.js +270 -0
  46. package/scripts/hooks/credential-check.js +101 -0
  47. package/scripts/hooks/evaluate-session.js +81 -0
  48. package/scripts/hooks/pre-compact.js +66 -0
  49. package/scripts/hooks/prompt-analyzer.js +276 -0
  50. package/scripts/hooks/prompt-router.js +422 -0
  51. package/scripts/hooks/quality-gate-enforcer.js +371 -0
  52. package/scripts/hooks/session-end.js +156 -0
  53. package/scripts/hooks/session-start.js +195 -0
  54. package/scripts/hooks/skill-injector.js +333 -0
  55. package/scripts/hooks/suggest-compact.js +58 -0
  56. package/scripts/lib/asset-value.js +609 -0
  57. package/scripts/lib/client-manager.js +300 -0
  58. package/scripts/lib/command-matcher.js +242 -0
  59. package/scripts/lib/cross-session-patterns.js +754 -0
  60. package/scripts/lib/intent-classifier.js +1075 -0
  61. package/scripts/lib/package-manager.js +374 -0
  62. package/scripts/lib/recommendation-engine.js +597 -0
  63. package/scripts/lib/session-memory.js +489 -0
  64. package/scripts/lib/skill-effectiveness.js +486 -0
  65. package/scripts/lib/skill-matcher.js +595 -0
  66. package/scripts/lib/tutorial-metrics.js +242 -0
  67. package/scripts/lib/tutorial-progress.js +209 -0
  68. package/scripts/lib/tutorial-renderer.js +431 -0
  69. package/scripts/lib/utils.js +380 -0
  70. package/scripts/lib/verify-formatter.js +143 -0
  71. package/scripts/lib/workflow-state.js +249 -0
  72. package/scripts/onboard.js +363 -0
  73. package/scripts/quarterly-report.js +692 -0
  74. package/scripts/setup-package-manager.js +204 -0
  75. package/scripts/sync-upstream.js +391 -0
  76. package/scripts/test.js +108 -0
  77. package/scripts/tutorial-runner.js +351 -0
  78. package/scripts/validate-all.js +201 -0
  79. package/scripts/verifiers/agents.js +245 -0
  80. package/scripts/verifiers/config.js +186 -0
  81. package/scripts/verifiers/environment.js +123 -0
  82. package/scripts/verifiers/hooks.js +188 -0
  83. package/scripts/verifiers/index.js +38 -0
  84. package/scripts/verifiers/persistence.js +140 -0
  85. package/scripts/verifiers/plugin.js +215 -0
  86. package/scripts/verifiers/skills.js +209 -0
  87. package/scripts/verify-setup.js +164 -0
  88. package/skills/INDEX.md +157 -0
  89. package/skills/backend-patterns/SKILL.md +586 -0
  90. package/skills/backend-patterns/catalyst-patterns.md +128 -0
  91. package/skills/bigquery-patterns/SKILL.md +27 -0
  92. package/skills/bigquery-patterns/performance-optimization.md +518 -0
  93. package/skills/bigquery-patterns/query-patterns.md +372 -0
  94. package/skills/bigquery-patterns/schema-design.md +78 -0
  95. package/skills/cloudstream-project-template/SKILL.md +20 -0
  96. package/skills/cloudstream-project-template/structure.md +65 -0
  97. package/skills/coding-standards/SKILL.md +524 -0
  98. package/skills/coding-standards/deluge-standards.md +83 -0
  99. package/skills/compliance-patterns/SKILL.md +28 -0
  100. package/skills/compliance-patterns/hipaa/audit-requirements.md +251 -0
  101. package/skills/compliance-patterns/hipaa/baa-process.md +298 -0
  102. package/skills/compliance-patterns/hipaa/data-archival-strategy.md +387 -0
  103. package/skills/compliance-patterns/hipaa/phi-handling.md +52 -0
  104. package/skills/compliance-patterns/pci-dss/saq-a-requirements.md +307 -0
  105. package/skills/compliance-patterns/pci-dss/tokenization-patterns.md +382 -0
  106. package/skills/compliance-patterns/pci-dss/zoho-checkout-patterns.md +56 -0
  107. package/skills/compliance-patterns/soc2/access-controls.md +344 -0
  108. package/skills/compliance-patterns/soc2/audit-logging.md +458 -0
  109. package/skills/compliance-patterns/soc2/change-management.md +403 -0
  110. package/skills/compliance-patterns/soc2/deluge-execution-logging.md +407 -0
  111. package/skills/consultancy-workflows/SKILL.md +19 -0
  112. package/skills/consultancy-workflows/client-isolation.md +21 -0
  113. package/skills/consultancy-workflows/documentation-automation.md +454 -0
  114. package/skills/consultancy-workflows/handoff-procedures.md +257 -0
  115. package/skills/consultancy-workflows/knowledge-capture.md +513 -0
  116. package/skills/consultancy-workflows/time-tracking.md +26 -0
  117. package/skills/continuous-learning/SKILL.md +84 -0
  118. package/skills/continuous-learning/config.json +18 -0
  119. package/skills/continuous-learning/evaluate-session.sh +60 -0
  120. package/skills/continuous-learning-v2/SKILL.md +126 -0
  121. package/skills/continuous-learning-v2/config.json +61 -0
  122. package/skills/frontend-patterns/SKILL.md +635 -0
  123. package/skills/frontend-patterns/zoho-widget-patterns.md +103 -0
  124. package/skills/gcp-data-engineering/SKILL.md +36 -0
  125. package/skills/gcp-data-engineering/bigquery/performance-optimization.md +337 -0
  126. package/skills/gcp-data-engineering/dataflow/error-handling.md +496 -0
  127. package/skills/gcp-data-engineering/dataflow/pipeline-patterns.md +444 -0
  128. package/skills/gcp-data-engineering/dbt/model-organization.md +63 -0
  129. package/skills/gcp-data-engineering/dbt/testing-patterns.md +503 -0
  130. package/skills/gcp-data-engineering/medallion-architecture/bronze-layer.md +60 -0
  131. package/skills/gcp-data-engineering/medallion-architecture/gold-layer.md +311 -0
  132. package/skills/gcp-data-engineering/medallion-architecture/layer-transitions.md +517 -0
  133. package/skills/gcp-data-engineering/medallion-architecture/silver-layer.md +305 -0
  134. package/skills/gcp-data-engineering/zoho-to-gcp/data-extraction.md +543 -0
  135. package/skills/gcp-data-engineering/zoho-to-gcp/real-time-vs-batch.md +337 -0
  136. package/skills/security-review/SKILL.md +498 -0
  137. package/skills/security-review/compliance-checklist.md +53 -0
  138. package/skills/strategic-compact/SKILL.md +67 -0
  139. package/skills/tdd-workflow/SKILL.md +413 -0
  140. package/skills/tdd-workflow/zoho-testing.md +124 -0
  141. package/skills/tutorial/SKILL.md +249 -0
  142. package/skills/tutorial/docs/ACCESSIBILITY.md +169 -0
  143. package/skills/tutorial/lessons/00-philosophy-and-workflow.md +198 -0
  144. package/skills/tutorial/lessons/01-basics.md +81 -0
  145. package/skills/tutorial/lessons/02-training.md +86 -0
  146. package/skills/tutorial/lessons/03-commands.md +109 -0
  147. package/skills/tutorial/lessons/04-workflows.md +115 -0
  148. package/skills/tutorial/lessons/05-compliance.md +116 -0
  149. package/skills/tutorial/lessons/06-zoho.md +121 -0
  150. package/skills/tutorial/lessons/07-hooks-system.md +277 -0
  151. package/skills/tutorial/lessons/08-mcp-servers.md +316 -0
  152. package/skills/tutorial/lessons/09-client-management.md +215 -0
  153. package/skills/tutorial/lessons/10-testing-e2e.md +260 -0
  154. package/skills/tutorial/lessons/11-skills-deep-dive.md +272 -0
  155. package/skills/tutorial/lessons/12-rules-system.md +326 -0
  156. package/skills/tutorial/lessons/13-golden-standard-graduation.md +213 -0
  157. package/skills/tutorial/lessons/14-fork-setup-and-sync.md +312 -0
  158. package/skills/tutorial/lessons/15-living-examples-system.md +221 -0
  159. package/skills/tutorial/tracks/accelerated/README.md +134 -0
  160. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-1.md +161 -0
  161. package/skills/tutorial/tracks/accelerated/assessment/checkpoint-2.md +175 -0
  162. package/skills/tutorial/tracks/accelerated/day-1-core-concepts.md +234 -0
  163. package/skills/tutorial/tracks/accelerated/day-2-essential-commands.md +270 -0
  164. package/skills/tutorial/tracks/accelerated/day-3-workflow-mastery.md +305 -0
  165. package/skills/tutorial/tracks/accelerated/day-4-compliance-zoho.md +304 -0
  166. package/skills/tutorial/tracks/accelerated/day-5-hooks-skills.md +344 -0
  167. package/skills/tutorial/tracks/accelerated/day-6-client-testing.md +386 -0
  168. package/skills/tutorial/tracks/accelerated/day-7-graduation.md +369 -0
  169. package/skills/zoho-patterns/CHANGELOG.md +108 -0
  170. package/skills/zoho-patterns/SKILL.md +446 -0
  171. package/skills/zoho-patterns/analytics/dashboard-patterns.md +352 -0
  172. package/skills/zoho-patterns/analytics/zoho-to-bigquery-pipeline.md +427 -0
  173. package/skills/zoho-patterns/catalyst/appsail-deployment.md +349 -0
  174. package/skills/zoho-patterns/catalyst/context-close-patterns.md +354 -0
  175. package/skills/zoho-patterns/catalyst/cron-batch-processing.md +374 -0
  176. package/skills/zoho-patterns/catalyst/function-patterns.md +439 -0
  177. package/skills/zoho-patterns/creator/form-design.md +304 -0
  178. package/skills/zoho-patterns/creator/publish-api-patterns.md +313 -0
  179. package/skills/zoho-patterns/creator/widget-integration.md +306 -0
  180. package/skills/zoho-patterns/creator/workflow-automation.md +253 -0
  181. package/skills/zoho-patterns/deluge/api-patterns.md +468 -0
  182. package/skills/zoho-patterns/deluge/batch-processing.md +403 -0
  183. package/skills/zoho-patterns/deluge/cross-app-integration.md +356 -0
  184. package/skills/zoho-patterns/deluge/error-handling.md +423 -0
  185. package/skills/zoho-patterns/deluge/syntax-reference.md +65 -0
  186. package/skills/zoho-patterns/integration/cors-proxy-architecture.md +426 -0
  187. package/skills/zoho-patterns/integration/crm-books-native-sync.md +277 -0
  188. package/skills/zoho-patterns/integration/oauth-token-management.md +461 -0
  189. package/skills/zoho-patterns/integration/zoho-flow-patterns.md +334 -0
@@ -0,0 +1,586 @@
1
+ ---
2
+ name: backend-patterns
3
+ description: Backend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes.
4
+ version: 1.0.0
5
+ status: active
6
+ introduced: 1.0.0
7
+ lastUpdated: 2026-01-25
8
+ ---
9
+
10
+ # Backend Development Patterns
11
+
12
+ Backend architecture patterns and best practices for scalable server-side applications.
13
+
14
+ ## API Design Patterns
15
+
16
+ ### RESTful API Structure
17
+
18
+ ```typescript
19
+ // ✅ Resource-based URLs
20
+ GET /api/markets # List resources
21
+ GET /api/markets/:id # Get single resource
22
+ POST /api/markets # Create resource
23
+ PUT /api/markets/:id # Replace resource
24
+ PATCH /api/markets/:id # Update resource
25
+ DELETE /api/markets/:id # Delete resource
26
+
27
+ // ✅ Query parameters for filtering, sorting, pagination
28
+ GET /api/markets?status=active&sort=volume&limit=20&offset=0
29
+ ```
30
+
31
+ ### Repository Pattern
32
+
33
+ ```typescript
34
+ // Abstract data access logic
35
+ interface MarketRepository {
36
+ findAll(filters?: MarketFilters): Promise<Market[]>
37
+ findById(id: string): Promise<Market | null>
38
+ create(data: CreateMarketDto): Promise<Market>
39
+ update(id: string, data: UpdateMarketDto): Promise<Market>
40
+ delete(id: string): Promise<void>
41
+ }
42
+
43
+ class SupabaseMarketRepository implements MarketRepository {
44
+ async findAll(filters?: MarketFilters): Promise<Market[]> {
45
+ let query = supabase.from('markets').select('*')
46
+
47
+ if (filters?.status) {
48
+ query = query.eq('status', filters.status)
49
+ }
50
+
51
+ if (filters?.limit) {
52
+ query = query.limit(filters.limit)
53
+ }
54
+
55
+ const { data, error } = await query
56
+
57
+ if (error) throw new Error(error.message)
58
+ return data
59
+ }
60
+
61
+ // Other methods...
62
+ }
63
+ ```
64
+
65
+ ### Service Layer Pattern
66
+
67
+ ```typescript
68
+ // Business logic separated from data access
69
+ class MarketService {
70
+ constructor(private marketRepo: MarketRepository) {}
71
+
72
+ async searchMarkets(query: string, limit: number = 10): Promise<Market[]> {
73
+ // Business logic
74
+ const embedding = await generateEmbedding(query)
75
+ const results = await this.vectorSearch(embedding, limit)
76
+
77
+ // Fetch full data
78
+ const markets = await this.marketRepo.findByIds(results.map(r => r.id))
79
+
80
+ // Sort by similarity
81
+ return markets.sort((a, b) => {
82
+ const scoreA = results.find(r => r.id === a.id)?.score || 0
83
+ const scoreB = results.find(r => r.id === b.id)?.score || 0
84
+ return scoreA - scoreB
85
+ })
86
+ }
87
+
88
+ private async vectorSearch(embedding: number[], limit: number) {
89
+ // Vector search implementation
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Middleware Pattern
95
+
96
+ ```typescript
97
+ // Request/response processing pipeline
98
+ export function withAuth(handler: NextApiHandler): NextApiHandler {
99
+ return async (req, res) => {
100
+ const token = req.headers.authorization?.replace('Bearer ', '')
101
+
102
+ if (!token) {
103
+ return res.status(401).json({ error: 'Unauthorized' })
104
+ }
105
+
106
+ try {
107
+ const user = await verifyToken(token)
108
+ req.user = user
109
+ return handler(req, res)
110
+ } catch (error) {
111
+ return res.status(401).json({ error: 'Invalid token' })
112
+ }
113
+ }
114
+ }
115
+
116
+ // Usage
117
+ export default withAuth(async (req, res) => {
118
+ // Handler has access to req.user
119
+ })
120
+ ```
121
+
122
+ ## Database Patterns
123
+
124
+ ### Query Optimization
125
+
126
+ ```typescript
127
+ // ✅ GOOD: Select only needed columns
128
+ const { data } = await supabase
129
+ .from('markets')
130
+ .select('id, name, status, volume')
131
+ .eq('status', 'active')
132
+ .order('volume', { ascending: false })
133
+ .limit(10)
134
+
135
+ // ❌ BAD: Select everything
136
+ const { data } = await supabase
137
+ .from('markets')
138
+ .select('*')
139
+ ```
140
+
141
+ ### N+1 Query Prevention
142
+
143
+ ```typescript
144
+ // ❌ BAD: N+1 query problem
145
+ const markets = await getMarkets()
146
+ for (const market of markets) {
147
+ market.creator = await getUser(market.creator_id) // N queries
148
+ }
149
+
150
+ // ✅ GOOD: Batch fetch
151
+ const markets = await getMarkets()
152
+ const creatorIds = markets.map(m => m.creator_id)
153
+ const creators = await getUsers(creatorIds) // 1 query
154
+ const creatorMap = new Map(creators.map(c => [c.id, c]))
155
+
156
+ markets.forEach(market => {
157
+ market.creator = creatorMap.get(market.creator_id)
158
+ })
159
+ ```
160
+
161
+ ### Transaction Pattern
162
+
163
+ ```typescript
164
+ async function createMarketWithPosition(
165
+ marketData: CreateMarketDto,
166
+ positionData: CreatePositionDto
167
+ ) {
168
+ // Use Supabase transaction
169
+ const { data, error } = await supabase.rpc('create_market_with_position', {
170
+ market_data: marketData,
171
+ position_data: positionData
172
+ })
173
+
174
+ if (error) throw new Error('Transaction failed')
175
+ return data
176
+ }
177
+
178
+ // SQL function in Supabase
179
+ CREATE OR REPLACE FUNCTION create_market_with_position(
180
+ market_data jsonb,
181
+ position_data jsonb
182
+ )
183
+ RETURNS jsonb
184
+ LANGUAGE plpgsql
185
+ AS $$
186
+ BEGIN
187
+ -- Start transaction automatically
188
+ INSERT INTO markets VALUES (market_data);
189
+ INSERT INTO positions VALUES (position_data);
190
+ RETURN jsonb_build_object('success', true);
191
+ EXCEPTION
192
+ WHEN OTHERS THEN
193
+ -- Rollback happens automatically
194
+ RETURN jsonb_build_object('success', false, 'error', SQLERRM);
195
+ END;
196
+ $$;
197
+ ```
198
+
199
+ ## Caching Strategies
200
+
201
+ ### Redis Caching Layer
202
+
203
+ ```typescript
204
+ class CachedMarketRepository implements MarketRepository {
205
+ constructor(
206
+ private baseRepo: MarketRepository,
207
+ private redis: RedisClient
208
+ ) {}
209
+
210
+ async findById(id: string): Promise<Market | null> {
211
+ // Check cache first
212
+ const cached = await this.redis.get(`market:${id}`)
213
+
214
+ if (cached) {
215
+ return JSON.parse(cached)
216
+ }
217
+
218
+ // Cache miss - fetch from database
219
+ const market = await this.baseRepo.findById(id)
220
+
221
+ if (market) {
222
+ // Cache for 5 minutes
223
+ await this.redis.setex(`market:${id}`, 300, JSON.stringify(market))
224
+ }
225
+
226
+ return market
227
+ }
228
+
229
+ async invalidateCache(id: string): Promise<void> {
230
+ await this.redis.del(`market:${id}`)
231
+ }
232
+ }
233
+ ```
234
+
235
+ ### Cache-Aside Pattern
236
+
237
+ ```typescript
238
+ async function getMarketWithCache(id: string): Promise<Market> {
239
+ const cacheKey = `market:${id}`
240
+
241
+ // Try cache
242
+ const cached = await redis.get(cacheKey)
243
+ if (cached) return JSON.parse(cached)
244
+
245
+ // Cache miss - fetch from DB
246
+ const market = await db.markets.findUnique({ where: { id } })
247
+
248
+ if (!market) throw new Error('Market not found')
249
+
250
+ // Update cache
251
+ await redis.setex(cacheKey, 300, JSON.stringify(market))
252
+
253
+ return market
254
+ }
255
+ ```
256
+
257
+ ## Error Handling Patterns
258
+
259
+ ### Centralized Error Handler
260
+
261
+ ```typescript
262
+ class ApiError extends Error {
263
+ constructor(
264
+ public statusCode: number,
265
+ public message: string,
266
+ public isOperational = true
267
+ ) {
268
+ super(message)
269
+ Object.setPrototypeOf(this, ApiError.prototype)
270
+ }
271
+ }
272
+
273
+ export function errorHandler(error: unknown, req: Request): Response {
274
+ if (error instanceof ApiError) {
275
+ return NextResponse.json({
276
+ success: false,
277
+ error: error.message
278
+ }, { status: error.statusCode })
279
+ }
280
+
281
+ if (error instanceof z.ZodError) {
282
+ return NextResponse.json({
283
+ success: false,
284
+ error: 'Validation failed',
285
+ details: error.errors
286
+ }, { status: 400 })
287
+ }
288
+
289
+ // Log unexpected errors
290
+ console.error('Unexpected error:', error)
291
+
292
+ return NextResponse.json({
293
+ success: false,
294
+ error: 'Internal server error'
295
+ }, { status: 500 })
296
+ }
297
+
298
+ // Usage
299
+ export async function GET(request: Request) {
300
+ try {
301
+ const data = await fetchData()
302
+ return NextResponse.json({ success: true, data })
303
+ } catch (error) {
304
+ return errorHandler(error, request)
305
+ }
306
+ }
307
+ ```
308
+
309
+ ### Retry with Exponential Backoff
310
+
311
+ ```typescript
312
+ async function fetchWithRetry<T>(
313
+ fn: () => Promise<T>,
314
+ maxRetries = 3
315
+ ): Promise<T> {
316
+ let lastError: Error
317
+
318
+ for (let i = 0; i < maxRetries; i++) {
319
+ try {
320
+ return await fn()
321
+ } catch (error) {
322
+ lastError = error as Error
323
+
324
+ if (i < maxRetries - 1) {
325
+ // Exponential backoff: 1s, 2s, 4s
326
+ const delay = Math.pow(2, i) * 1000
327
+ await new Promise(resolve => setTimeout(resolve, delay))
328
+ }
329
+ }
330
+ }
331
+
332
+ throw lastError!
333
+ }
334
+
335
+ // Usage
336
+ const data = await fetchWithRetry(() => fetchFromAPI())
337
+ ```
338
+
339
+ ## Authentication & Authorization
340
+
341
+ ### JWT Token Validation
342
+
343
+ ```typescript
344
+ import jwt from 'jsonwebtoken'
345
+
346
+ interface JWTPayload {
347
+ userId: string
348
+ email: string
349
+ role: 'admin' | 'user'
350
+ }
351
+
352
+ export function verifyToken(token: string): JWTPayload {
353
+ try {
354
+ const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload
355
+ return payload
356
+ } catch (error) {
357
+ throw new ApiError(401, 'Invalid token')
358
+ }
359
+ }
360
+
361
+ export async function requireAuth(request: Request) {
362
+ const token = request.headers.get('authorization')?.replace('Bearer ', '')
363
+
364
+ if (!token) {
365
+ throw new ApiError(401, 'Missing authorization token')
366
+ }
367
+
368
+ return verifyToken(token)
369
+ }
370
+
371
+ // Usage in API route
372
+ export async function GET(request: Request) {
373
+ const user = await requireAuth(request)
374
+
375
+ const data = await getDataForUser(user.userId)
376
+
377
+ return NextResponse.json({ success: true, data })
378
+ }
379
+ ```
380
+
381
+ ### Role-Based Access Control
382
+
383
+ ```typescript
384
+ type Permission = 'read' | 'write' | 'delete' | 'admin'
385
+
386
+ interface User {
387
+ id: string
388
+ role: 'admin' | 'moderator' | 'user'
389
+ }
390
+
391
+ const rolePermissions: Record<User['role'], Permission[]> = {
392
+ admin: ['read', 'write', 'delete', 'admin'],
393
+ moderator: ['read', 'write', 'delete'],
394
+ user: ['read', 'write']
395
+ }
396
+
397
+ export function hasPermission(user: User, permission: Permission): boolean {
398
+ return rolePermissions[user.role].includes(permission)
399
+ }
400
+
401
+ export function requirePermission(permission: Permission) {
402
+ return async (request: Request) => {
403
+ const user = await requireAuth(request)
404
+
405
+ if (!hasPermission(user, permission)) {
406
+ throw new ApiError(403, 'Insufficient permissions')
407
+ }
408
+
409
+ return user
410
+ }
411
+ }
412
+
413
+ // Usage
414
+ export const DELETE = requirePermission('delete')(async (request: Request) => {
415
+ // Handler with permission check
416
+ })
417
+ ```
418
+
419
+ ## Rate Limiting
420
+
421
+ ### Simple In-Memory Rate Limiter
422
+
423
+ ```typescript
424
+ class RateLimiter {
425
+ private requests = new Map<string, number[]>()
426
+
427
+ async checkLimit(
428
+ identifier: string,
429
+ maxRequests: number,
430
+ windowMs: number
431
+ ): Promise<boolean> {
432
+ const now = Date.now()
433
+ const requests = this.requests.get(identifier) || []
434
+
435
+ // Remove old requests outside window
436
+ const recentRequests = requests.filter(time => now - time < windowMs)
437
+
438
+ if (recentRequests.length >= maxRequests) {
439
+ return false // Rate limit exceeded
440
+ }
441
+
442
+ // Add current request
443
+ recentRequests.push(now)
444
+ this.requests.set(identifier, recentRequests)
445
+
446
+ return true
447
+ }
448
+ }
449
+
450
+ const limiter = new RateLimiter()
451
+
452
+ export async function GET(request: Request) {
453
+ const ip = request.headers.get('x-forwarded-for') || 'unknown'
454
+
455
+ const allowed = await limiter.checkLimit(ip, 100, 60000) // 100 req/min
456
+
457
+ if (!allowed) {
458
+ return NextResponse.json({
459
+ error: 'Rate limit exceeded'
460
+ }, { status: 429 })
461
+ }
462
+
463
+ // Continue with request
464
+ }
465
+ ```
466
+
467
+ ## Background Jobs & Queues
468
+
469
+ ### Simple Queue Pattern
470
+
471
+ ```typescript
472
+ class JobQueue<T> {
473
+ private queue: T[] = []
474
+ private processing = false
475
+
476
+ async add(job: T): Promise<void> {
477
+ this.queue.push(job)
478
+
479
+ if (!this.processing) {
480
+ this.process()
481
+ }
482
+ }
483
+
484
+ private async process(): Promise<void> {
485
+ this.processing = true
486
+
487
+ while (this.queue.length > 0) {
488
+ const job = this.queue.shift()!
489
+
490
+ try {
491
+ await this.execute(job)
492
+ } catch (error) {
493
+ console.error('Job failed:', error)
494
+ }
495
+ }
496
+
497
+ this.processing = false
498
+ }
499
+
500
+ private async execute(job: T): Promise<void> {
501
+ // Job execution logic
502
+ }
503
+ }
504
+
505
+ // Usage for indexing markets
506
+ interface IndexJob {
507
+ marketId: string
508
+ }
509
+
510
+ const indexQueue = new JobQueue<IndexJob>()
511
+
512
+ export async function POST(request: Request) {
513
+ const { marketId } = await request.json()
514
+
515
+ // Add to queue instead of blocking
516
+ await indexQueue.add({ marketId })
517
+
518
+ return NextResponse.json({ success: true, message: 'Job queued' })
519
+ }
520
+ ```
521
+
522
+ ## Logging & Monitoring
523
+
524
+ ### Structured Logging
525
+
526
+ ```typescript
527
+ interface LogContext {
528
+ userId?: string
529
+ requestId?: string
530
+ method?: string
531
+ path?: string
532
+ [key: string]: unknown
533
+ }
534
+
535
+ class Logger {
536
+ log(level: 'info' | 'warn' | 'error', message: string, context?: LogContext) {
537
+ const entry = {
538
+ timestamp: new Date().toISOString(),
539
+ level,
540
+ message,
541
+ ...context
542
+ }
543
+
544
+ console.log(JSON.stringify(entry))
545
+ }
546
+
547
+ info(message: string, context?: LogContext) {
548
+ this.log('info', message, context)
549
+ }
550
+
551
+ warn(message: string, context?: LogContext) {
552
+ this.log('warn', message, context)
553
+ }
554
+
555
+ error(message: string, error: Error, context?: LogContext) {
556
+ this.log('error', message, {
557
+ ...context,
558
+ error: error.message,
559
+ stack: error.stack
560
+ })
561
+ }
562
+ }
563
+
564
+ const logger = new Logger()
565
+
566
+ // Usage
567
+ export async function GET(request: Request) {
568
+ const requestId = crypto.randomUUID()
569
+
570
+ logger.info('Fetching markets', {
571
+ requestId,
572
+ method: 'GET',
573
+ path: '/api/markets'
574
+ })
575
+
576
+ try {
577
+ const markets = await fetchMarkets()
578
+ return NextResponse.json({ success: true, data: markets })
579
+ } catch (error) {
580
+ logger.error('Failed to fetch markets', error as Error, { requestId })
581
+ return NextResponse.json({ error: 'Internal error' }, { status: 500 })
582
+ }
583
+ }
584
+ ```
585
+
586
+ **Remember**: Backend patterns enable scalable, maintainable server-side applications. Choose patterns that fit your complexity level.
@@ -0,0 +1,128 @@
1
+ # Catalyst Backend Patterns
2
+
3
+ ## Function Structure (Basic I/O)
4
+ ```javascript
5
+ 'use strict';
6
+
7
+ module.exports = async (context, basicIO) => {
8
+ const response = { status: 'success', data: null, message: '' };
9
+
10
+ try {
11
+ // Parse input
12
+ const input = JSON.parse(basicIO.getArgument('data') || '{}');
13
+
14
+ // Business logic
15
+ const result = await processRequest(input);
16
+
17
+ response.data = result;
18
+ basicIO.write(JSON.stringify(response));
19
+ } catch (error) {
20
+ response.status = 'error';
21
+ response.message = error.message;
22
+ basicIO.write(JSON.stringify(response));
23
+ } finally {
24
+ context.close(); // MANDATORY
25
+ }
26
+ };
27
+ ```
28
+
29
+ ## Cron Function Pattern
30
+ ```javascript
31
+ 'use strict';
32
+
33
+ module.exports = async (cronDetails, context) => {
34
+ console.log('Cron triggered:', cronDetails);
35
+
36
+ try {
37
+ // Batch processing (up to 15 minutes)
38
+ const records = await fetchAllRecords();
39
+ const batches = chunk(records, 100);
40
+
41
+ for (const batch of batches) {
42
+ await processBatch(batch);
43
+ }
44
+
45
+ console.log(`Processed ${records.length} records`);
46
+ } catch (error) {
47
+ console.error('Cron failed:', error);
48
+ // Notify admin via Zoho Cliq or email
49
+ }
50
+
51
+ context.close(); // MANDATORY
52
+ };
53
+
54
+ function chunk(array, size) {
55
+ const chunks = [];
56
+ for (let i = 0; i < array.length; i += size) {
57
+ chunks.push(array.slice(i, i + size));
58
+ }
59
+ return chunks;
60
+ }
61
+ ```
62
+
63
+ ## AppSail Express Pattern
64
+ ```javascript
65
+ const express = require('express');
66
+ const app = express();
67
+ const PORT = process.env.PORT || 8080;
68
+
69
+ app.use(express.json());
70
+
71
+ // Health check (REQUIRED for AppSail)
72
+ app.get('/health', (req, res) => {
73
+ res.json({ status: 'healthy', timestamp: new Date().toISOString() });
74
+ });
75
+
76
+ // API routes
77
+ app.use('/api', require('./routes/api'));
78
+
79
+ // Error handler
80
+ app.use((err, req, res, next) => {
81
+ console.error(err.stack);
82
+ res.status(500).json({ status: 'error', message: 'Internal server error' });
83
+ });
84
+
85
+ app.listen(PORT, () => {
86
+ console.log(`AppSail running on port ${PORT}`);
87
+ });
88
+ ```
89
+
90
+ ## Zoho API Integration from Catalyst
91
+ ```javascript
92
+ const axios = require('axios');
93
+
94
+ class ZohoAPI {
95
+ constructor(accessToken) {
96
+ this.baseURL = 'https://www.zohoapis.com';
97
+ this.token = accessToken;
98
+ }
99
+
100
+ async getRecords(module, criteria = '', page = 1) {
101
+ const params = { page, per_page: 200 };
102
+ if (criteria) params.criteria = criteria;
103
+
104
+ const response = await axios.get(
105
+ `${this.baseURL}/crm/v5/${module}`,
106
+ { headers: { Authorization: `Zoho-oauthtoken ${this.token}` }, params }
107
+ );
108
+ return response.data;
109
+ }
110
+
111
+ async refreshToken(refreshToken, clientId, clientSecret) {
112
+ const response = await axios.post(
113
+ 'https://accounts.zoho.com/oauth/v2/token',
114
+ null,
115
+ { params: { refresh_token: refreshToken, client_id: clientId, client_secret: clientSecret, grant_type: 'refresh_token' } }
116
+ );
117
+ return response.data.access_token;
118
+ }
119
+ }
120
+
121
+ module.exports = ZohoAPI;
122
+ ```
123
+
124
+ ## Environment Variables
125
+ - Use Catalyst Segments for environment-specific config
126
+ - Never hardcode API keys or tokens
127
+ - Access via process.env in Node.js functions
128
+ - Document all required env vars in README