lua-cli 2.2.8-alpha.2 → 2.3.0-alpha.1

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 (193) hide show
  1. package/API_REFERENCE.md +1408 -0
  2. package/CLI_REFERENCE.md +818 -0
  3. package/GETTING_STARTED.md +1040 -0
  4. package/README.md +738 -424
  5. package/TEMPLATE_GUIDE.md +1398 -0
  6. package/dist/api/agent.api.service.d.ts +33 -6
  7. package/dist/api/agent.api.service.js +27 -0
  8. package/dist/api/auth.api.service.d.ts +31 -2
  9. package/dist/api/auth.api.service.js +29 -0
  10. package/dist/api/basket.api.service.d.ts +53 -11
  11. package/dist/api/basket.api.service.js +63 -14
  12. package/dist/api/chat.api.service.d.ts +15 -3
  13. package/dist/api/chat.api.service.js +12 -0
  14. package/dist/api/credentials.d.ts +24 -0
  15. package/dist/api/credentials.js +46 -0
  16. package/dist/api/custom.data.api.service.d.ts +45 -9
  17. package/dist/api/custom.data.api.service.js +43 -9
  18. package/dist/api/lazy-instances.d.ts +49 -0
  19. package/dist/api/lazy-instances.js +95 -0
  20. package/dist/api/order.api.service.d.ts +34 -4
  21. package/dist/api/order.api.service.js +41 -3
  22. package/dist/api/products.api.service.d.ts +39 -9
  23. package/dist/api/products.api.service.js +43 -5
  24. package/dist/api/skills.api.service.d.ts +49 -2
  25. package/dist/api/skills.api.service.js +47 -1
  26. package/dist/api/tool.api.service.d.ts +39 -1
  27. package/dist/api/tool.api.service.js +38 -0
  28. package/dist/api/user.data.api.service.d.ts +23 -1
  29. package/dist/api/user.data.api.service.js +22 -0
  30. package/dist/api-exports.d.ts +236 -5
  31. package/dist/api-exports.js +264 -81
  32. package/dist/cli/command-definitions.d.ts +30 -0
  33. package/dist/cli/command-definitions.js +71 -0
  34. package/dist/commands/agents.d.ts +20 -0
  35. package/dist/commands/agents.js +24 -2
  36. package/dist/commands/apiKey.d.ts +23 -0
  37. package/dist/commands/apiKey.js +23 -0
  38. package/dist/commands/compile.d.ts +24 -0
  39. package/dist/commands/compile.js +67 -759
  40. package/dist/commands/configure.d.ts +24 -0
  41. package/dist/commands/configure.js +31 -96
  42. package/dist/commands/deploy.d.ts +31 -19
  43. package/dist/commands/deploy.js +45 -74
  44. package/dist/commands/destroy.d.ts +27 -0
  45. package/dist/commands/destroy.js +27 -1
  46. package/dist/commands/dev.d.ts +25 -62
  47. package/dist/commands/dev.js +58 -878
  48. package/dist/commands/init.d.ts +27 -0
  49. package/dist/commands/init.js +98 -260
  50. package/dist/commands/push.d.ts +24 -21
  51. package/dist/commands/push.js +39 -92
  52. package/dist/commands/test.d.ts +26 -0
  53. package/dist/commands/test.js +41 -188
  54. package/dist/common/basket.instance.d.ts +54 -3
  55. package/dist/common/basket.instance.js +56 -3
  56. package/dist/common/data.entry.instance.d.ts +25 -2
  57. package/dist/common/data.entry.instance.js +24 -0
  58. package/dist/common/http.client.d.ts +51 -1
  59. package/dist/common/http.client.js +50 -0
  60. package/dist/common/order.instance.d.ts +22 -0
  61. package/dist/common/order.instance.js +31 -4
  62. package/dist/common/product.instance.d.ts +22 -1
  63. package/dist/common/product.instance.js +24 -6
  64. package/dist/common/product.pagination.instance.d.ts +22 -2
  65. package/dist/common/product.pagination.instance.js +22 -1
  66. package/dist/common/product.search.instance.d.ts +13 -3
  67. package/dist/common/product.search.instance.js +12 -1
  68. package/dist/common/user.instance.d.ts +27 -3
  69. package/dist/common/user.instance.js +28 -7
  70. package/dist/config/auth.constants.d.ts +11 -0
  71. package/dist/config/auth.constants.js +11 -0
  72. package/dist/config/compile.constants.d.ts +67 -0
  73. package/dist/config/compile.constants.js +99 -0
  74. package/dist/config/constants.d.ts +5 -0
  75. package/dist/config/constants.js +5 -0
  76. package/dist/config/dev.constants.d.ts +65 -0
  77. package/dist/config/dev.constants.js +79 -0
  78. package/dist/config/init.constants.d.ts +23 -0
  79. package/dist/config/init.constants.js +41 -0
  80. package/dist/index.d.ts +19 -3
  81. package/dist/index.js +28 -44
  82. package/dist/interfaces/admin.d.ts +56 -50
  83. package/dist/interfaces/admin.js +4 -0
  84. package/dist/interfaces/agent.d.ts +21 -0
  85. package/dist/interfaces/agent.js +4 -0
  86. package/dist/interfaces/baskets.d.ts +60 -0
  87. package/dist/interfaces/baskets.js +12 -0
  88. package/dist/interfaces/chat.d.ts +48 -4
  89. package/dist/interfaces/chat.js +4 -0
  90. package/dist/interfaces/common.d.ts +62 -0
  91. package/dist/interfaces/common.js +8 -0
  92. package/dist/interfaces/compile.d.ts +11 -0
  93. package/dist/interfaces/compile.js +4 -0
  94. package/dist/interfaces/custom.data.d.ts +49 -19
  95. package/dist/interfaces/custom.data.js +4 -0
  96. package/dist/interfaces/deploy.d.ts +29 -0
  97. package/dist/interfaces/deploy.js +4 -0
  98. package/dist/interfaces/dev.d.ts +53 -0
  99. package/dist/interfaces/dev.js +5 -0
  100. package/dist/interfaces/init.d.ts +60 -0
  101. package/dist/interfaces/init.js +4 -0
  102. package/dist/interfaces/orders.d.ts +37 -0
  103. package/dist/interfaces/orders.js +12 -0
  104. package/dist/interfaces/product.d.ts +38 -10
  105. package/dist/interfaces/product.js +4 -0
  106. package/dist/interfaces/push.d.ts +26 -0
  107. package/dist/interfaces/push.js +4 -0
  108. package/dist/interfaces/test.d.ts +36 -0
  109. package/dist/interfaces/test.js +4 -0
  110. package/dist/services/auth.d.ts +54 -99
  111. package/dist/services/auth.js +76 -12
  112. package/dist/types/api-contracts.d.ts +211 -0
  113. package/dist/types/api-contracts.js +8 -0
  114. package/dist/types/compile.types.d.ts +76 -0
  115. package/dist/types/compile.types.js +4 -0
  116. package/dist/types/index.d.ts +23 -121
  117. package/dist/types/index.js +25 -14
  118. package/dist/types/skill.d.ts +142 -0
  119. package/dist/{skill.js → types/skill.js} +66 -17
  120. package/dist/types/tool-validation.d.ts +34 -0
  121. package/dist/types/tool-validation.js +42 -0
  122. package/dist/utils/auth-flows.d.ts +26 -0
  123. package/dist/utils/auth-flows.js +141 -0
  124. package/dist/utils/bundling.d.ts +36 -0
  125. package/dist/utils/bundling.js +137 -0
  126. package/dist/utils/compile.d.ts +37 -0
  127. package/dist/utils/compile.js +242 -0
  128. package/dist/utils/deploy-api.d.ts +26 -0
  129. package/dist/utils/deploy-api.js +53 -0
  130. package/dist/utils/deploy-helpers.d.ts +46 -0
  131. package/dist/utils/deploy-helpers.js +86 -0
  132. package/dist/utils/deployment.d.ts +25 -0
  133. package/dist/utils/deployment.js +161 -0
  134. package/dist/utils/dev-api.d.ts +61 -0
  135. package/dist/utils/dev-api.js +262 -0
  136. package/dist/utils/dev-helpers.d.ts +46 -0
  137. package/dist/utils/dev-helpers.js +83 -0
  138. package/dist/utils/dev-server.d.ts +24 -0
  139. package/dist/utils/dev-server.js +555 -0
  140. package/dist/utils/dev-watcher.d.ts +31 -0
  141. package/dist/utils/dev-watcher.js +110 -0
  142. package/dist/utils/files.js +0 -5
  143. package/dist/utils/init-agent.d.ts +34 -0
  144. package/dist/utils/init-agent.js +129 -0
  145. package/dist/utils/init-helpers.d.ts +41 -0
  146. package/dist/utils/init-helpers.js +73 -0
  147. package/dist/utils/init-prompts.d.ts +47 -0
  148. package/dist/utils/init-prompts.js +168 -0
  149. package/dist/utils/push-api.d.ts +15 -0
  150. package/dist/utils/push-api.js +48 -0
  151. package/dist/utils/push-helpers.d.ts +38 -0
  152. package/dist/utils/push-helpers.js +84 -0
  153. package/dist/utils/sandbox-storage.d.ts +27 -0
  154. package/dist/utils/sandbox-storage.js +71 -0
  155. package/dist/utils/sandbox.js +78 -114
  156. package/dist/utils/skill-management.d.ts +14 -0
  157. package/dist/utils/skill-management.js +148 -0
  158. package/dist/utils/test-helpers.d.ts +40 -0
  159. package/dist/utils/test-helpers.js +92 -0
  160. package/dist/utils/test-prompts.d.ts +23 -0
  161. package/dist/utils/test-prompts.js +186 -0
  162. package/dist/utils/tool-detection.d.ts +18 -0
  163. package/dist/utils/tool-detection.js +110 -0
  164. package/dist/web/app.css +14 -9
  165. package/package.json +7 -4
  166. package/template/QUICKSTART.md +299 -144
  167. package/template/README.md +928 -349
  168. package/template/TOOL_EXAMPLES.md +655 -0
  169. package/template/package-lock.json +5 -5
  170. package/template/package.json +1 -1
  171. package/template/src/index.ts +147 -207
  172. package/template/src/tools/BasketTool.ts +128 -0
  173. package/template/src/tools/CustomDataTool.ts +7 -13
  174. package/template/src/tools/OrderTool.ts +54 -0
  175. package/template/src/tools/PaymentTool.ts +1 -1
  176. package/template/src/tools/ProductsTool.ts +56 -118
  177. package/template/src/tools/UserDataTool.ts +4 -26
  178. package/dist/common/config.d.ts +0 -5
  179. package/dist/common/config.js +0 -5
  180. package/dist/custom-data-api.d.ts +0 -72
  181. package/dist/custom-data-api.js +0 -174
  182. package/dist/product-api.d.ts +0 -189
  183. package/dist/product-api.js +0 -141
  184. package/dist/services/api.d.ts +0 -549
  185. package/dist/services/api.js +0 -596
  186. package/dist/skill.d.ts +0 -50
  187. package/dist/types.d.ts +0 -1
  188. package/dist/types.js +0 -2
  189. package/dist/user-data-api.d.ts +0 -39
  190. package/dist/user-data-api.js +0 -50
  191. package/template/API.md +0 -604
  192. package/template/DEVELOPER.md +0 -771
  193. package/template/lua.skill.yaml +0 -7
@@ -1,771 +0,0 @@
1
- # Lua CLI Developer Documentation
2
-
3
- This document provides detailed technical information for developers building LuaSkills with the Lua CLI framework.
4
-
5
- ## 🏗️ Architecture Overview
6
-
7
- The Lua CLI framework consists of several key components:
8
-
9
- ```
10
- ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
11
- │ LuaSkill │ │ LuaTool │ │ Services │
12
- │ (Orchestrator)│ │ (Individual │ │ (Shared │
13
- │ │ │ Functions) │ │ Logic) │
14
- └─────────────────┘ └─────────────────┘ └─────────────────┘
15
- │ │ │
16
- └───────────────────────┼───────────────────────┘
17
-
18
- ┌─────────────────┐
19
- │ Bundler │
20
- │ (esbuild) │
21
- └─────────────────┘
22
- ```
23
-
24
- ### Core Components
25
-
26
- 1. **LuaSkill**: Main orchestrator that manages tools and handles execution
27
- 2. **LuaTool**: Individual tool implementations with input/output schemas
28
- 3. **Services**: Reusable business logic shared across tools
29
- 4. **Bundler**: Compiles and bundles dependencies using esbuild
30
-
31
- ## 🔧 Tool Development
32
-
33
- ### Tool Lifecycle
34
-
35
- ```typescript
36
- // 1. Definition
37
- class MyTool implements LuaTool<InputSchema, OutputSchema> {
38
- // Tool metadata
39
- name = "my_tool";
40
- description = "Tool description";
41
-
42
- // 2. Schema Definition
43
- inputSchema = z.object({...});
44
- outputSchema = z.object({...});
45
-
46
- // 3. Execution
47
- async execute(input) {
48
- // Tool logic
49
- return result;
50
- }
51
- }
52
-
53
- // 4. Registration
54
- const skill = new LuaSkill();
55
- skill.addTool(new MyTool());
56
-
57
- // 5. Execution
58
- const result = await skill.run({ tool: "my_tool", ... });
59
- ```
60
-
61
- ### Schema Design Patterns
62
-
63
- #### 1. Simple Input/Output
64
- ```typescript
65
- inputSchema = z.object({
66
- text: z.string().describe("Text to process")
67
- });
68
-
69
- outputSchema = z.object({
70
- result: z.string(),
71
- length: z.number()
72
- });
73
- ```
74
-
75
- #### 2. Optional Parameters
76
- ```typescript
77
- inputSchema = z.object({
78
- required: z.string(),
79
- optional: z.string().optional(),
80
- withDefault: z.string().default("default value")
81
- });
82
- ```
83
-
84
- #### 3. Union Types
85
- ```typescript
86
- inputSchema = z.object({
87
- format: z.enum(["json", "xml", "csv"]),
88
- data: z.union([z.string(), z.object({})])
89
- });
90
- ```
91
-
92
- #### 4. Complex Nested Objects
93
- ```typescript
94
- inputSchema = z.object({
95
- user: z.object({
96
- name: z.string(),
97
- email: z.string().email(),
98
- preferences: z.object({
99
- theme: z.enum(["light", "dark"]),
100
- notifications: z.boolean()
101
- }).optional()
102
- }),
103
- settings: z.record(z.string(), z.any())
104
- });
105
- ```
106
-
107
- ### Error Handling Strategies
108
-
109
- #### 1. Graceful Degradation
110
- ```typescript
111
- async execute(input) {
112
- try {
113
- const result = await riskyOperation(input);
114
- return { success: true, data: result };
115
- } catch (error) {
116
- return {
117
- success: false,
118
- error: error.message,
119
- fallback: await getFallbackData(input)
120
- };
121
- }
122
- }
123
- ```
124
-
125
- #### 2. Validation Errors
126
- ```typescript
127
- async execute(input) {
128
- // Input is already validated by the framework
129
- // But you can add additional validation
130
- if (input.value < 0) {
131
- throw new Error("Value must be positive");
132
- }
133
-
134
- return { result: input.value * 2 };
135
- }
136
- ```
137
-
138
- #### 3. Retry Logic
139
- ```typescript
140
- async execute(input) {
141
- const maxRetries = 3;
142
- let lastError;
143
-
144
- for (let i = 0; i < maxRetries; i++) {
145
- try {
146
- return await unreliableOperation(input);
147
- } catch (error) {
148
- lastError = error;
149
- if (i < maxRetries - 1) {
150
- await new Promise(resolve => setTimeout(resolve, 1000 * i));
151
- }
152
- }
153
- }
154
-
155
- throw lastError;
156
- }
157
- ```
158
-
159
- ## 🌐 Service Architecture
160
-
161
- ### Service Design Patterns
162
-
163
- #### 1. Singleton Service
164
- ```typescript
165
- class DatabaseService {
166
- private static instance: DatabaseService;
167
- private connection: Connection;
168
-
169
- private constructor() {
170
- this.connection = new Connection();
171
- }
172
-
173
- static getInstance(): DatabaseService {
174
- if (!DatabaseService.instance) {
175
- DatabaseService.instance = new DatabaseService();
176
- }
177
- return DatabaseService.instance;
178
- }
179
-
180
- async query(sql: string) {
181
- return this.connection.query(sql);
182
- }
183
- }
184
- ```
185
-
186
- #### 2. Factory Service
187
- ```typescript
188
- class ApiServiceFactory {
189
- static createService(type: 'rest' | 'graphql'): ApiService {
190
- switch (type) {
191
- case 'rest':
192
- return new RestApiService();
193
- case 'graphql':
194
- return new GraphQLApiService();
195
- default:
196
- throw new Error(`Unknown service type: ${type}`);
197
- }
198
- }
199
- }
200
- ```
201
-
202
- #### 3. Dependency Injection
203
- ```typescript
204
- class UserService {
205
- constructor(
206
- private dbService: DatabaseService,
207
- private cacheService: CacheService
208
- ) {}
209
-
210
- async getUser(id: string) {
211
- // Check cache first
212
- const cached = await this.cacheService.get(`user:${id}`);
213
- if (cached) return cached;
214
-
215
- // Fetch from database
216
- const user = await this.dbService.query(`SELECT * FROM users WHERE id = ?`, [id]);
217
-
218
- // Cache the result
219
- await this.cacheService.set(`user:${id}`, user, 3600);
220
-
221
- return user;
222
- }
223
- }
224
- ```
225
-
226
- ### Service Integration Examples
227
-
228
- #### 1. HTTP Client Service
229
- ```typescript
230
- import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
231
-
232
- export class HttpClientService {
233
- private client: AxiosInstance;
234
-
235
- constructor(baseURL: string, timeout = 5000) {
236
- this.client = axios.create({
237
- baseURL,
238
- timeout,
239
- headers: {
240
- 'Content-Type': 'application/json',
241
- 'User-Agent': 'LuaSkill/1.0'
242
- }
243
- });
244
-
245
- // Add request interceptor
246
- this.client.interceptors.request.use(
247
- (config) => {
248
- console.log(`Making ${config.method?.toUpperCase()} request to ${config.url}`);
249
- return config;
250
- },
251
- (error) => Promise.reject(error)
252
- );
253
-
254
- // Add response interceptor
255
- this.client.interceptors.response.use(
256
- (response) => response,
257
- (error) => {
258
- console.error(`Request failed: ${error.message}`);
259
- return Promise.reject(error);
260
- }
261
- );
262
- }
263
-
264
- async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
265
- const response = await this.client.get(url, config);
266
- return response.data;
267
- }
268
-
269
- async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
270
- const response = await this.client.post(url, data, config);
271
- return response.data;
272
- }
273
- }
274
- ```
275
-
276
- #### 2. Database Service
277
- ```typescript
278
- export class DatabaseService {
279
- private pool: Pool;
280
-
281
- constructor(connectionString: string) {
282
- this.pool = new Pool({ connectionString });
283
- }
284
-
285
- async query<T = any>(sql: string, params: any[] = []): Promise<T[]> {
286
- const client = await this.pool.connect();
287
- try {
288
- const result = await client.query(sql, params);
289
- return result.rows;
290
- } finally {
291
- client.release();
292
- }
293
- }
294
-
295
- async transaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T> {
296
- const client = await this.pool.connect();
297
- try {
298
- await client.query('BEGIN');
299
- const result = await callback(client);
300
- await client.query('COMMIT');
301
- return result;
302
- } catch (error) {
303
- await client.query('ROLLBACK');
304
- throw error;
305
- } finally {
306
- client.release();
307
- }
308
- }
309
- }
310
- ```
311
-
312
- ## 📦 Bundling and Dependencies
313
-
314
- ### How Bundling Works
315
-
316
- 1. **Dependency Detection**: The bundler scans tool files for imports
317
- 2. **Dependency Resolution**: Uses esbuild to resolve and bundle dependencies
318
- 3. **Code Generation**: Creates self-contained JavaScript bundles
319
- 4. **Compression**: Compresses the final code for storage
320
-
321
- ### Supported Import Types
322
-
323
- #### 1. Default Imports
324
- ```typescript
325
- import axios from 'axios';
326
- // Bundled as: const axios = require('axios');
327
- ```
328
-
329
- #### 2. Named Imports
330
- ```typescript
331
- import { z } from 'zod';
332
- // Bundled as: const { z } = require('zod');
333
- ```
334
-
335
- #### 3. Namespace Imports
336
- ```typescript
337
- import * as fs from 'fs';
338
- // Bundled as: const fs = require('fs');
339
- ```
340
-
341
- #### 4. Local Imports
342
- ```typescript
343
- import ApiService from '../services/ApiService';
344
- // Resolved relative to tool file location
345
- ```
346
-
347
- ### Bundling Configuration
348
-
349
- The bundler uses the following esbuild configuration:
350
-
351
- ```typescript
352
- {
353
- bundle: true,
354
- format: 'cjs', // CommonJS for Node.js compatibility
355
- platform: 'node', // Node.js platform
356
- target: 'node16', // Node.js 16+ features
357
- external: [], // Bundle everything (no externals)
358
- minify: false, // Keep readable for debugging
359
- sourcemap: false, // No source maps
360
- resolveExtensions: ['.js', '.ts', '.json'],
361
- mainFields: ['main', 'module', 'browser'],
362
- conditions: ['node']
363
- }
364
- ```
365
-
366
- ### Handling Different Package Types
367
-
368
- #### 1. CommonJS Packages
369
- ```typescript
370
- // These work out of the box
371
- import fs from 'fs';
372
- import path from 'path';
373
- ```
374
-
375
- #### 2. ES Module Packages
376
- ```typescript
377
- // Bundled automatically
378
- import axios from 'axios';
379
- import { z } from 'zod';
380
- ```
381
-
382
- #### 3. Native Modules
383
- ```typescript
384
- // May require special handling
385
- import { createHash } from 'crypto';
386
- ```
387
-
388
- ## 🧪 Testing Strategies
389
-
390
- ### Unit Testing Tools
391
-
392
- ```typescript
393
- import { describe, it, expect, beforeEach } from 'vitest';
394
- import MyTool from '../tools/MyTool';
395
-
396
- describe('MyTool', () => {
397
- let tool: MyTool;
398
-
399
- beforeEach(() => {
400
- tool = new MyTool();
401
- });
402
-
403
- it('should process valid input', async () => {
404
- const input = { text: 'Hello World' };
405
- const result = await tool.execute(input);
406
-
407
- expect(result).toEqual({
408
- result: 'HELLO WORLD',
409
- length: 11
410
- });
411
- });
412
-
413
- it('should handle invalid input', async () => {
414
- const input = { text: '' };
415
-
416
- await expect(tool.execute(input)).rejects.toThrow('Text cannot be empty');
417
- });
418
- });
419
- ```
420
-
421
- ### Integration Testing
422
-
423
- ```typescript
424
- import { LuaSkill } from 'lua-cli/skill';
425
- import MyTool from '../tools/MyTool';
426
-
427
- describe('Skill Integration', () => {
428
- let skill: LuaSkill;
429
-
430
- beforeEach(() => {
431
- skill = new LuaSkill();
432
- skill.addTool(new MyTool());
433
- });
434
-
435
- it('should execute tool through skill', async () => {
436
- const result = await skill.run({
437
- tool: 'my_tool',
438
- text: 'Hello World'
439
- });
440
-
441
- expect(result.result).toBe('HELLO WORLD');
442
- });
443
- });
444
- ```
445
-
446
- ### Mocking External Dependencies
447
-
448
- ```typescript
449
- import { vi } from 'vitest';
450
- import axios from 'axios';
451
-
452
- // Mock axios
453
- vi.mock('axios');
454
- const mockedAxios = vi.mocked(axios);
455
-
456
- describe('ApiTool', () => {
457
- it('should handle API responses', async () => {
458
- mockedAxios.get.mockResolvedValue({
459
- data: { message: 'Success' },
460
- status: 200
461
- });
462
-
463
- const tool = new ApiTool();
464
- const result = await tool.execute({ url: 'https://api.example.com' });
465
-
466
- expect(result.success).toBe(true);
467
- expect(result.data.message).toBe('Success');
468
- });
469
- });
470
- ```
471
-
472
- ## 🚀 Performance Optimization
473
-
474
- ### 1. Lazy Loading
475
- ```typescript
476
- class ExpensiveTool {
477
- private expensiveService?: ExpensiveService;
478
-
479
- private getService() {
480
- if (!this.expensiveService) {
481
- this.expensiveService = new ExpensiveService();
482
- }
483
- return this.expensiveService;
484
- }
485
-
486
- async execute(input) {
487
- const service = this.getService();
488
- return service.process(input);
489
- }
490
- }
491
- ```
492
-
493
- ### 2. Caching
494
- ```typescript
495
- class CachedTool {
496
- private cache = new Map<string, any>();
497
-
498
- async execute(input) {
499
- const cacheKey = JSON.stringify(input);
500
-
501
- if (this.cache.has(cacheKey)) {
502
- return this.cache.get(cacheKey);
503
- }
504
-
505
- const result = await expensiveOperation(input);
506
- this.cache.set(cacheKey, result);
507
-
508
- return result;
509
- }
510
- }
511
- ```
512
-
513
- ### 3. Connection Pooling
514
- ```typescript
515
- class DatabaseTool {
516
- private static pool: Pool;
517
-
518
- static {
519
- DatabaseTool.pool = new Pool({
520
- connectionString: process.env.DATABASE_URL,
521
- max: 20,
522
- idleTimeoutMillis: 30000,
523
- connectionTimeoutMillis: 2000
524
- });
525
- }
526
-
527
- async execute(input) {
528
- const client = await DatabaseTool.pool.connect();
529
- try {
530
- return await client.query(input.sql);
531
- } finally {
532
- client.release();
533
- }
534
- }
535
- }
536
- ```
537
-
538
- ## 🔒 Security Considerations
539
-
540
- ### 1. Input Sanitization
541
- ```typescript
542
- import DOMPurify from 'dompurify';
543
-
544
- class SafeTool {
545
- async execute(input) {
546
- // Sanitize HTML input
547
- const cleanHtml = DOMPurify.sanitize(input.html);
548
-
549
- // Validate file paths
550
- const safePath = path.resolve(input.basePath, input.fileName);
551
- if (!safePath.startsWith(input.basePath)) {
552
- throw new Error('Invalid file path');
553
- }
554
-
555
- return { cleanHtml, safePath };
556
- }
557
- }
558
- ```
559
-
560
- ### 2. Rate Limiting
561
- ```typescript
562
- class RateLimitedTool {
563
- private requests = new Map<string, number[]>();
564
-
565
- async execute(input) {
566
- const now = Date.now();
567
- const windowMs = 60000; // 1 minute
568
- const maxRequests = 10;
569
-
570
- const userRequests = this.requests.get(input.userId) || [];
571
- const recentRequests = userRequests.filter(time => now - time < windowMs);
572
-
573
- if (recentRequests.length >= maxRequests) {
574
- throw new Error('Rate limit exceeded');
575
- }
576
-
577
- recentRequests.push(now);
578
- this.requests.set(input.userId, recentRequests);
579
-
580
- return await processRequest(input);
581
- }
582
- }
583
- ```
584
-
585
- ### 3. Secret Management
586
- ```typescript
587
- class SecureTool {
588
- async execute(input) {
589
- // Never log sensitive data
590
- const sanitizedInput = { ...input };
591
- delete sanitizedInput.password;
592
- delete sanitizedInput.apiKey;
593
-
594
- console.log('Processing request:', sanitizedInput);
595
-
596
- // Use environment variables for secrets
597
- const apiKey = process.env.API_KEY;
598
- if (!apiKey) {
599
- throw new Error('API key not configured');
600
- }
601
-
602
- return await makeSecureRequest(input, apiKey);
603
- }
604
- }
605
- ```
606
-
607
- ## 📊 Monitoring and Logging
608
-
609
- ### 1. Structured Logging
610
- ```typescript
611
- class LoggedTool {
612
- async execute(input) {
613
- const startTime = Date.now();
614
- const requestId = crypto.randomUUID();
615
-
616
- console.log(JSON.stringify({
617
- level: 'info',
618
- message: 'Tool execution started',
619
- requestId,
620
- tool: this.name,
621
- timestamp: new Date().toISOString()
622
- }));
623
-
624
- try {
625
- const result = await this.processInput(input);
626
-
627
- console.log(JSON.stringify({
628
- level: 'info',
629
- message: 'Tool execution completed',
630
- requestId,
631
- duration: Date.now() - startTime,
632
- success: true
633
- }));
634
-
635
- return result;
636
- } catch (error) {
637
- console.log(JSON.stringify({
638
- level: 'error',
639
- message: 'Tool execution failed',
640
- requestId,
641
- duration: Date.now() - startTime,
642
- error: error.message,
643
- success: false
644
- }));
645
-
646
- throw error;
647
- }
648
- }
649
- }
650
- ```
651
-
652
- ### 2. Metrics Collection
653
- ```typescript
654
- class MetricsTool {
655
- private metrics = {
656
- executionCount: 0,
657
- successCount: 0,
658
- errorCount: 0,
659
- averageDuration: 0
660
- };
661
-
662
- async execute(input) {
663
- const startTime = Date.now();
664
- this.metrics.executionCount++;
665
-
666
- try {
667
- const result = await this.processInput(input);
668
- this.metrics.successCount++;
669
- return result;
670
- } catch (error) {
671
- this.metrics.errorCount++;
672
- throw error;
673
- } finally {
674
- const duration = Date.now() - startTime;
675
- this.updateAverageDuration(duration);
676
- }
677
- }
678
-
679
- private updateAverageDuration(duration: number) {
680
- const total = this.metrics.successCount + this.metrics.errorCount;
681
- this.metrics.averageDuration =
682
- (this.metrics.averageDuration * (total - 1) + duration) / total;
683
- }
684
-
685
- getMetrics() {
686
- return { ...this.metrics };
687
- }
688
- }
689
- ```
690
-
691
- ## 🔧 Advanced Patterns
692
-
693
- ### 1. Plugin Architecture
694
- ```typescript
695
- interface ToolPlugin {
696
- name: string;
697
- beforeExecute?(input: any): any;
698
- afterExecute?(result: any): any;
699
- onError?(error: Error): void;
700
- }
701
-
702
- class PluggableTool {
703
- private plugins: ToolPlugin[] = [];
704
-
705
- addPlugin(plugin: ToolPlugin) {
706
- this.plugins.push(plugin);
707
- }
708
-
709
- async execute(input) {
710
- let processedInput = input;
711
-
712
- // Run before plugins
713
- for (const plugin of this.plugins) {
714
- if (plugin.beforeExecute) {
715
- processedInput = plugin.beforeExecute(processedInput);
716
- }
717
- }
718
-
719
- try {
720
- let result = await this.processInput(processedInput);
721
-
722
- // Run after plugins
723
- for (const plugin of this.plugins) {
724
- if (plugin.afterExecute) {
725
- result = plugin.afterExecute(result);
726
- }
727
- }
728
-
729
- return result;
730
- } catch (error) {
731
- // Run error plugins
732
- for (const plugin of this.plugins) {
733
- if (plugin.onError) {
734
- plugin.onError(error);
735
- }
736
- }
737
- throw error;
738
- }
739
- }
740
- }
741
- ```
742
-
743
- ### 2. Middleware Pattern
744
- ```typescript
745
- type Middleware = (input: any, next: () => Promise<any>) => Promise<any>;
746
-
747
- class MiddlewareTool {
748
- private middlewares: Middleware[] = [];
749
-
750
- use(middleware: Middleware) {
751
- this.middlewares.push(middleware);
752
- }
753
-
754
- async execute(input) {
755
- let index = 0;
756
-
757
- const next = async (): Promise<any> => {
758
- if (index >= this.middlewares.length) {
759
- return this.processInput(input);
760
- }
761
-
762
- const middleware = this.middlewares[index++];
763
- return middleware(input, next);
764
- };
765
-
766
- return next();
767
- }
768
- }
769
- ```
770
-
771
- This developer documentation provides comprehensive technical guidance for building robust, scalable LuaSkills with the Lua CLI framework.