@squidcloud/cli 1.0.416 → 1.0.417
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.
package/dist/index.js
CHANGED
|
@@ -30556,7 +30556,7 @@ function exitWithError(...messages) {
|
|
|
30556
30556
|
/***/ ((module) => {
|
|
30557
30557
|
|
|
30558
30558
|
"use strict";
|
|
30559
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@squidcloud/cli","version":"1.0.
|
|
30559
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@squidcloud/cli","version":"1.0.417","description":"The Squid CLI","main":"dist/index.js","scripts":{"start":"node dist/index.js","start-ts":"ts-node -r tsconfig-paths/register src/index.ts","prebuild":"rimraf dist","build":"webpack --mode=production","build:dev":"webpack --mode=development","lint":"eslint","link":"npm run build && chmod 755 dist/index.js && npm link","watch":"webpack --watch","deploy":"npm run build && npm pack --silent | xargs -I {} mv {} package.tgz && npm install -g package.tgz && rm -rf package.tgz","publish:public":"npm run build && npm publish --access public"},"files":["dist/**/*"],"bin":{"squid":"dist/index.js"},"keywords":[],"author":"","license":"ISC","engines":{"node":">=18.0.0"},"dependencies":{"@squidcloud/local-backend":"^1.0.417","adm-zip":"^0.5.16","copy-webpack-plugin":"^12.0.2","decompress":"^4.2.1","nodemon":"^3.1.9","terser-webpack-plugin":"^5.3.10","ts-loader":"^9.5.1","ts-node":"^10.9.2","tsconfig-paths":"^4.2.0","tsconfig-paths-webpack-plugin":"^4.1.0","webpack":"^5.101.3","zip-webpack-plugin":"^4.0.1"},"devDependencies":{"@types/adm-zip":"^0.5.7","@types/decompress":"^4.2.7","@types/node":"^20.19.9","terminal-link":"^3.0.0"}}');
|
|
30560
30560
|
|
|
30561
30561
|
/***/ }),
|
|
30562
30562
|
|
|
@@ -15,6 +15,235 @@ Squid is a backend-as-a-service platform that provides:
|
|
|
15
15
|
- **CLI** (`@squidcloud/cli`) - Local development and deployment tools
|
|
16
16
|
- **Built-in integrations** - Databases, queues, storage, AI, APIs
|
|
17
17
|
|
|
18
|
+
## Squid Architecture: The Three Parts
|
|
19
|
+
|
|
20
|
+
When developing with Squid, you work with three distinct but interconnected parts:
|
|
21
|
+
|
|
22
|
+
### 1. Client (Frontend/External Services)
|
|
23
|
+
|
|
24
|
+
**What it is:** Any application that needs to interact with your Squid backend - web apps, mobile apps, desktop apps, or even other servers.
|
|
25
|
+
|
|
26
|
+
**How it works:**
|
|
27
|
+
- Initializes the Squid Client SDK (`@squidcloud/client`)
|
|
28
|
+
- Communicates with Squid functionality over HTTP/WebSocket
|
|
29
|
+
- Can interact with AI agents, modify agent settings, query databases, call backend functions, etc.
|
|
30
|
+
- Optionally uses authentication (OAuth2.0) for user-specific access
|
|
31
|
+
- Respects security rules defined in the backend
|
|
32
|
+
|
|
33
|
+
**Common use cases:**
|
|
34
|
+
```typescript
|
|
35
|
+
// Web/mobile application
|
|
36
|
+
const squid = new Squid({
|
|
37
|
+
appId: 'your-app-id',
|
|
38
|
+
region: 'us-east-1.aws',
|
|
39
|
+
authProvider: { /* user auth */ }
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Interact with agents
|
|
43
|
+
const agent = squid.ai().agent('support-agent');
|
|
44
|
+
const response = await agent.ask('How do I reset my password?');
|
|
45
|
+
|
|
46
|
+
// Query databases
|
|
47
|
+
const users = await squid.collection('users').query().eq('active', true).snapshot();
|
|
48
|
+
|
|
49
|
+
// Call backend functions
|
|
50
|
+
const result = await squid.executeFunction('processPayment', paymentData);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Key point:** Clients have limited, controlled access based on security rules you define in the backend.
|
|
54
|
+
|
|
55
|
+
### 2. Squid Backend (Your Server-Side Code)
|
|
56
|
+
|
|
57
|
+
**What it is:** TypeScript code that runs on Squid's infrastructure, containing your business logic, security rules, and integrations.
|
|
58
|
+
|
|
59
|
+
**How it works:**
|
|
60
|
+
- Contains services that extend `SquidService`
|
|
61
|
+
- Uses **decorators** to define functionality:
|
|
62
|
+
- `@executable()` - Backend functions callable from clients
|
|
63
|
+
- `@webhook()` - HTTP endpoints for external services
|
|
64
|
+
- `@trigger()` - React to database changes
|
|
65
|
+
- `@scheduler()` - Run code on a schedule (cron jobs)
|
|
66
|
+
- `@secureDatabase()`, `@secureCollection()` - Define who can access data
|
|
67
|
+
- `@secureAiAgent()` - Control agent access
|
|
68
|
+
- `@aiFunction()` - Functions that AI agents can call
|
|
69
|
+
- And many more decorators for security, rate limiting, etc.
|
|
70
|
+
- Has **full access** to all Squid functionality via pre-initialized `this.squid` client (with API key permissions)
|
|
71
|
+
- Deployed to Squid infrastructure using `squid deploy`
|
|
72
|
+
|
|
73
|
+
**Example backend service:**
|
|
74
|
+
```typescript
|
|
75
|
+
import { SquidService, executable, scheduler, trigger, secureCollection } from '@squidcloud/backend';
|
|
76
|
+
|
|
77
|
+
export class MyService extends SquidService {
|
|
78
|
+
// Backend function callable from client
|
|
79
|
+
@executable()
|
|
80
|
+
async processPayment(amount: number, userId: string): Promise<PaymentResult> {
|
|
81
|
+
// Full access to Squid - this.squid has API key permissions
|
|
82
|
+
const user = await this.squid.collection('users').doc({ id: userId }).snapshot();
|
|
83
|
+
|
|
84
|
+
// Your business logic here
|
|
85
|
+
return { success: true, transactionId: '...' };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// React to database changes
|
|
89
|
+
@trigger({ id: 'new-user', collection: 'users', mutationTypes: ['insert'] })
|
|
90
|
+
async onNewUser(request: TriggerRequest<User>): Promise<void> {
|
|
91
|
+
await sendWelcomeEmail(request.docAfter);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Scheduled task (cron job)
|
|
95
|
+
@scheduler({ id: 'daily-report', cron: '0 0 * * *' })
|
|
96
|
+
async generateDailyReport(): Promise<void> {
|
|
97
|
+
// Runs every day at midnight
|
|
98
|
+
const stats = await this.calculateStats();
|
|
99
|
+
await this.sendReport(stats);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Security rule - who can read users collection
|
|
103
|
+
@secureCollection('users', 'read')
|
|
104
|
+
allowUserRead(context: QueryContext): boolean {
|
|
105
|
+
const userId = this.getUserAuth()?.userId;
|
|
106
|
+
// Only allow users to read their own data
|
|
107
|
+
return context.isSubqueryOf('id', '==', userId);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Function that AI agents can call
|
|
111
|
+
@aiFunction('Gets order status', [
|
|
112
|
+
{ name: 'orderId', type: 'string', required: true }
|
|
113
|
+
])
|
|
114
|
+
async getOrderStatus({ orderId }: { orderId: string }): Promise<string> {
|
|
115
|
+
const order = await this.squid.collection('orders').doc({ id: orderId }).snapshot();
|
|
116
|
+
return order?.status || 'not found';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Key points:**
|
|
122
|
+
- Backend code has **full permissions** (API key access)
|
|
123
|
+
- Defines **what clients can and cannot do** through security decorators
|
|
124
|
+
- Contains **business logic** that shouldn't be exposed to clients
|
|
125
|
+
- Automatically deployed and scaled by Squid
|
|
126
|
+
|
|
127
|
+
### 3. Squid Console (Web UI)
|
|
128
|
+
|
|
129
|
+
**What it is:** A web-based management interface at https://console.getsquid.ai/ for setting up and managing your Squid applications.
|
|
130
|
+
|
|
131
|
+
**What you can do in the Console:**
|
|
132
|
+
- **Organizations & Applications:**
|
|
133
|
+
- Create organizations (teams/workspaces)
|
|
134
|
+
- Create applications (projects)
|
|
135
|
+
- Manage API keys and secrets
|
|
136
|
+
- View application logs and metrics
|
|
137
|
+
|
|
138
|
+
- **AI Studio:**
|
|
139
|
+
- Create and configure AI agents visually
|
|
140
|
+
- Set up agent instructions, models, and guardrails
|
|
141
|
+
- Test agents in real-time
|
|
142
|
+
- Connect agents to functions and knowledge bases
|
|
143
|
+
|
|
144
|
+
- **Knowledge Bases:**
|
|
145
|
+
- Create knowledge bases for RAG (Retrieval Augmented Generation)
|
|
146
|
+
- Upload documents and manage contexts
|
|
147
|
+
- Configure embedding models
|
|
148
|
+
|
|
149
|
+
- **Integrations:**
|
|
150
|
+
- Connect databases (PostgreSQL, MySQL, MongoDB, etc.)
|
|
151
|
+
- Connect SaaS services (Stripe, Slack, etc.)
|
|
152
|
+
- Configure OAuth integrations
|
|
153
|
+
- Set up storage providers (AWS S3, etc.)
|
|
154
|
+
- Configure message queues (Kafka, etc.)
|
|
155
|
+
|
|
156
|
+
- **Monitoring & Debugging:**
|
|
157
|
+
- View real-time logs
|
|
158
|
+
- Monitor API usage
|
|
159
|
+
- Debug agent conversations
|
|
160
|
+
- Track performance metrics
|
|
161
|
+
|
|
162
|
+
**Console vs SDK:**
|
|
163
|
+
- **Console is great for:** Initial setup, visual agent configuration, quick testing, monitoring
|
|
164
|
+
- **SDK is more powerful for:** Programmatic control, CI/CD pipelines, dynamic configuration, complex automation
|
|
165
|
+
|
|
166
|
+
**Example: Everything in Console can be done via SDK (except creating orgs/apps):**
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// Console: Click to create an agent with AI Studio
|
|
170
|
+
// SDK equivalent:
|
|
171
|
+
const agent = squid.ai().agent('my-agent');
|
|
172
|
+
await agent.upsert({
|
|
173
|
+
description: 'Customer support agent',
|
|
174
|
+
options: {
|
|
175
|
+
model: 'gpt-4o',
|
|
176
|
+
instructions: 'You are a helpful support agent...'
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Console: Upload document to knowledge base
|
|
181
|
+
// SDK equivalent:
|
|
182
|
+
const kb = squid.ai().knowledgeBase('docs');
|
|
183
|
+
await kb.upsertContext({
|
|
184
|
+
contextId: 'doc-1',
|
|
185
|
+
text: 'Product documentation...'
|
|
186
|
+
}, pdfFile);
|
|
187
|
+
|
|
188
|
+
// Console: Configure database integration
|
|
189
|
+
// SDK equivalent:
|
|
190
|
+
const integrations = squid.admin().integrations();
|
|
191
|
+
await integrations.upsertIntegration({
|
|
192
|
+
integrationId: 'my-db',
|
|
193
|
+
type: 'postgres',
|
|
194
|
+
connectionString: 'postgresql://...'
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Key point:** The Console provides a visual interface for management, but everything (except org/app creation) can be automated through the SDK for more flexibility and control.
|
|
199
|
+
|
|
200
|
+
### How They Work Together
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
┌─────────────────────┐
|
|
204
|
+
│ CLIENT (Web/ │
|
|
205
|
+
│ Mobile/Server) │
|
|
206
|
+
│ │
|
|
207
|
+
│ - Squid SDK init │
|
|
208
|
+
│ - User auth │
|
|
209
|
+
│ - Limited access │
|
|
210
|
+
└──────────┬──────────┘
|
|
211
|
+
│
|
|
212
|
+
│ HTTP/WebSocket
|
|
213
|
+
│
|
|
214
|
+
▼
|
|
215
|
+
┌─────────────────────┐
|
|
216
|
+
│ SQUID BACKEND │
|
|
217
|
+
│ (Your Code) │
|
|
218
|
+
│ │
|
|
219
|
+
│ - SquidService │
|
|
220
|
+
│ - Decorators │
|
|
221
|
+
│ - Full permissions │
|
|
222
|
+
│ - Business logic │
|
|
223
|
+
│ - Security rules │
|
|
224
|
+
└──────────┬──────────┘
|
|
225
|
+
│
|
|
226
|
+
│ Deployed via CLI
|
|
227
|
+
│ or managed via
|
|
228
|
+
▼
|
|
229
|
+
┌─────────────────────┐
|
|
230
|
+
│ SQUID CONSOLE │
|
|
231
|
+
│ (Web UI) │
|
|
232
|
+
│ │
|
|
233
|
+
│ - Manage apps │
|
|
234
|
+
│ - AI Studio │
|
|
235
|
+
│ - Integrations │
|
|
236
|
+
│ - Monitoring │
|
|
237
|
+
└─────────────────────┘
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Development workflow:**
|
|
241
|
+
1. Create application in **Squid Console**
|
|
242
|
+
2. Develop backend services in **Squid Backend** (local development with `squid start`)
|
|
243
|
+
3. Deploy backend to Squid infrastructure (`squid deploy`)
|
|
244
|
+
4. Build **Client** applications that use the Squid Client SDK
|
|
245
|
+
5. Use **Console** for monitoring and management, or use **SDK** for programmatic control
|
|
246
|
+
|
|
18
247
|
## CLI Commands
|
|
19
248
|
|
|
20
249
|
### Installation
|
|
@@ -24,6 +253,7 @@ npm install -g @squidcloud/cli
|
|
|
24
253
|
|
|
25
254
|
### `squid init <project-name>`
|
|
26
255
|
Creates new backend project with `.env` and example service.
|
|
256
|
+
The backend project has access to an already initialized client SDK with API key (full permissions)
|
|
27
257
|
|
|
28
258
|
```bash
|
|
29
259
|
squid init backend --appId YOUR_APP_ID --apiKey YOUR_API_KEY --environmentId dev --squidDeveloperId YOUR_DEV_ID --region us-east-1.aws
|
|
@@ -66,7 +296,7 @@ The Squid Client SDK can be instantiated in various environments:
|
|
|
66
296
|
- **Mobile applications** (React Native, etc.)
|
|
67
297
|
- **Desktop applications** (Electron, etc.)
|
|
68
298
|
|
|
69
|
-
**Important:** When writing backend code that runs on Squid's infrastructure, the Squid client is **already initialized and available** for you (see Backend SDK section). You don't need to manually create a new instance.
|
|
299
|
+
**Important:** When writing backend code that runs on Squid's infrastructure, the Squid client is **already initialized and available with API key and full permissions** for you (see Backend SDK section). You don't need to manually create a new instance.
|
|
70
300
|
|
|
71
301
|
### Initialization
|
|
72
302
|
|
|
@@ -286,6 +516,13 @@ userDoc.snapshots().subscribe(data => {
|
|
|
286
516
|
// Get cached data (no server fetch)
|
|
287
517
|
const cached = userDoc.peek();
|
|
288
518
|
|
|
519
|
+
// Check if document has data populated
|
|
520
|
+
if (userDoc.hasData) {
|
|
521
|
+
console.log('Document is loaded');
|
|
522
|
+
// Access data directly (with defensive copy)
|
|
523
|
+
console.log(userDoc.data);
|
|
524
|
+
}
|
|
525
|
+
|
|
289
526
|
// Bulk operations
|
|
290
527
|
await users.insertMany([
|
|
291
528
|
{ id: 'user-1', data: { name: 'Alice' } },
|
|
@@ -368,11 +605,16 @@ users.query()
|
|
|
368
605
|
snapshot.data.forEach(doc => console.log(doc.data));
|
|
369
606
|
});
|
|
370
607
|
|
|
371
|
-
// Pattern matching
|
|
608
|
+
// Pattern matching (CASE-INSENSITIVE by default)
|
|
372
609
|
const results = await users.query()
|
|
373
610
|
.like('email', '%.com') // case-insensitive by default
|
|
374
611
|
.snapshot();
|
|
375
612
|
|
|
613
|
+
// Case-sensitive pattern matching
|
|
614
|
+
const caseSensitive = await users.query()
|
|
615
|
+
.like('name', 'John%', true) // third parameter: caseSensitive = true
|
|
616
|
+
.snapshot();
|
|
617
|
+
|
|
376
618
|
// Array operators
|
|
377
619
|
const tagged = await posts.query()
|
|
378
620
|
.in('category', ['tech', 'news'])
|
|
@@ -799,6 +1041,26 @@ await myAgent.delete();
|
|
|
799
1041
|
// List all agents
|
|
800
1042
|
const agents = await squid.ai().listAgents();
|
|
801
1043
|
agents.forEach(agent => console.log(`${agent.id}: ${agent.description}`));
|
|
1044
|
+
|
|
1045
|
+
// Manage agent API keys
|
|
1046
|
+
const apiKey = await myAgent.regenerateApiKey();
|
|
1047
|
+
console.log('New API key:', apiKey);
|
|
1048
|
+
|
|
1049
|
+
const existingKey = await myAgent.getApiKey();
|
|
1050
|
+
console.log('Current API key:', existingKey);
|
|
1051
|
+
|
|
1052
|
+
// Update agent options at specific path
|
|
1053
|
+
await myAgent.setAgentOptionInPath('temperature', 0.9);
|
|
1054
|
+
await myAgent.setAgentOptionInPath('options.maxTokens', 2000);
|
|
1055
|
+
|
|
1056
|
+
// Update connected agents
|
|
1057
|
+
await myAgent.updateConnectedAgents([
|
|
1058
|
+
{ agentId: 'helper-agent', description: 'Helps with tasks' }
|
|
1059
|
+
]);
|
|
1060
|
+
|
|
1061
|
+
// Update or delete custom guardrails
|
|
1062
|
+
await myAgent.updateCustomGuardrails('Never reveal sensitive information');
|
|
1063
|
+
await myAgent.deleteCustomGuardrail();
|
|
802
1064
|
```
|
|
803
1065
|
|
|
804
1066
|
**Agent Lifecycle:**
|
|
@@ -1002,9 +1264,13 @@ chatObs.subscribe(text => {
|
|
|
1002
1264
|
const response = await agent.ask('Question?', { /* same options */ });
|
|
1003
1265
|
|
|
1004
1266
|
// Ask with annotations (includes file references, citations)
|
|
1005
|
-
const result = await agent.askWithAnnotations('Question?');
|
|
1267
|
+
const result = await agent.askWithAnnotations('Question?', { /* same options as ask */ });
|
|
1006
1268
|
console.log(result.responseString);
|
|
1007
|
-
console.log(result.annotations);
|
|
1269
|
+
console.log(result.annotations); // File references, sources, etc.
|
|
1270
|
+
|
|
1271
|
+
// Ask asynchronously (doesn't wait for response, uses job system)
|
|
1272
|
+
await agent.askAsync('Long running task', 'job-id-123', { /* same options */ });
|
|
1273
|
+
// Check job status later with squid.job().getJob('job-id-123')
|
|
1008
1274
|
|
|
1009
1275
|
// Voice responses
|
|
1010
1276
|
const voiceResult = await agent.askWithVoiceResponse('Hello', {
|
|
@@ -1018,6 +1284,19 @@ const transcribeResult = await agent.transcribeAndChat(audioFile);
|
|
|
1018
1284
|
console.log(transcribeResult.transcribedPrompt);
|
|
1019
1285
|
transcribeResult.responseStream.subscribe(text => console.log(text));
|
|
1020
1286
|
|
|
1287
|
+
// Transcribe audio and ask (non-streaming)
|
|
1288
|
+
const askResult = await agent.transcribeAndAsk(audioFile, { /* ask options */ });
|
|
1289
|
+
console.log(askResult.transcribedPrompt);
|
|
1290
|
+
console.log(askResult.response);
|
|
1291
|
+
|
|
1292
|
+
// Transcribe audio and get voice response
|
|
1293
|
+
const voiceResponse = await agent.transcribeAndAskWithVoiceResponse(audioFile, {
|
|
1294
|
+
voiceOptions: { modelName: 'tts-1', voice: 'alloy' }
|
|
1295
|
+
});
|
|
1296
|
+
console.log(voiceResponse.transcribedPrompt);
|
|
1297
|
+
console.log(voiceResponse.responseString);
|
|
1298
|
+
console.log(voiceResponse.voiceResponseFile);
|
|
1299
|
+
|
|
1021
1300
|
// Get chat history
|
|
1022
1301
|
const history = await agent.getChatHistory('memory-id-123');
|
|
1023
1302
|
|
|
@@ -1068,6 +1347,22 @@ export class MyService extends SquidService {
|
|
|
1068
1347
|
```typescript
|
|
1069
1348
|
const kb = squid.ai().knowledgeBase('product-docs');
|
|
1070
1349
|
|
|
1350
|
+
// Get knowledge base details
|
|
1351
|
+
const kbDetails = await kb.getKnowledgeBase();
|
|
1352
|
+
console.log(kbDetails);
|
|
1353
|
+
|
|
1354
|
+
// Create or update knowledge base
|
|
1355
|
+
await kb.upsertKnowledgeBase({
|
|
1356
|
+
description: 'Product documentation knowledge base',
|
|
1357
|
+
// ...other options
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
// Delete knowledge base
|
|
1361
|
+
await kb.delete();
|
|
1362
|
+
|
|
1363
|
+
// List all knowledge bases
|
|
1364
|
+
const allKBs = await squid.ai().listKnowledgeBases();
|
|
1365
|
+
|
|
1071
1366
|
// Upsert context (with or without file)
|
|
1072
1367
|
await kb.upsertContext({
|
|
1073
1368
|
contextId: 'doc-123',
|
|
@@ -1118,6 +1413,25 @@ await kb.deleteContexts(['doc-1', 'doc-2']);
|
|
|
1118
1413
|
const allKBs = await squid.ai().listKnowledgeBases();
|
|
1119
1414
|
```
|
|
1120
1415
|
|
|
1416
|
+
### AI - Files
|
|
1417
|
+
|
|
1418
|
+
Manage files stored with AI providers (OpenAI, etc.) for use with agents.
|
|
1419
|
+
|
|
1420
|
+
```typescript
|
|
1421
|
+
const aiFiles = squid.ai().files('openai'); // provider: 'openai' | 'anthropic' | etc.
|
|
1422
|
+
|
|
1423
|
+
// Upload file to AI provider
|
|
1424
|
+
const fileId = await aiFiles.uploadFile({
|
|
1425
|
+
file: myFile, // Browser File object
|
|
1426
|
+
purpose: 'assistants' // Purpose for the file
|
|
1427
|
+
});
|
|
1428
|
+
console.log('Uploaded file ID:', fileId);
|
|
1429
|
+
|
|
1430
|
+
// Delete file from AI provider
|
|
1431
|
+
const deleted = await aiFiles.deleteFile(fileId);
|
|
1432
|
+
console.log('File deleted:', deleted);
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1121
1435
|
### AI - Image & Audio
|
|
1122
1436
|
|
|
1123
1437
|
```typescript
|
|
@@ -1182,6 +1496,84 @@ const apiResult = await squid.ai().executeAiApiCall(
|
|
|
1182
1496
|
);
|
|
1183
1497
|
```
|
|
1184
1498
|
|
|
1499
|
+
### AI - Document Extraction & PDF Creation
|
|
1500
|
+
|
|
1501
|
+
Extract structured data from documents and create PDFs programmatically.
|
|
1502
|
+
|
|
1503
|
+
```typescript
|
|
1504
|
+
const extraction = squid.extraction();
|
|
1505
|
+
|
|
1506
|
+
// Extract data from document file
|
|
1507
|
+
const extractedData = await extraction.extractDataFromDocumentFile(
|
|
1508
|
+
myPdfFile, // File object
|
|
1509
|
+
{
|
|
1510
|
+
schema: {
|
|
1511
|
+
fields: [
|
|
1512
|
+
{ name: 'invoiceNumber', type: 'string', description: 'Invoice number' },
|
|
1513
|
+
{ name: 'total', type: 'number', description: 'Total amount' },
|
|
1514
|
+
{ name: 'date', type: 'date', description: 'Invoice date' }
|
|
1515
|
+
]
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
console.log(extractedData);
|
|
1520
|
+
|
|
1521
|
+
// Extract data from document URL
|
|
1522
|
+
const urlData = await extraction.extractDataFromDocumentUrl(
|
|
1523
|
+
'https://example.com/document.pdf',
|
|
1524
|
+
{
|
|
1525
|
+
schema: {
|
|
1526
|
+
fields: [
|
|
1527
|
+
{ name: 'title', type: 'string' },
|
|
1528
|
+
{ name: 'author', type: 'string' }
|
|
1529
|
+
]
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
);
|
|
1533
|
+
|
|
1534
|
+
// Create PDF from HTML or markdown
|
|
1535
|
+
const pdfResponse = await extraction.createPdf({
|
|
1536
|
+
content: '<h1>Hello</h1><p>This is a PDF</p>',
|
|
1537
|
+
contentType: 'html', // or 'markdown'
|
|
1538
|
+
options: {
|
|
1539
|
+
pageSize: 'A4',
|
|
1540
|
+
margin: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' }
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
console.log('PDF created:', pdfResponse.url);
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
**Use cases:**
|
|
1547
|
+
- Invoice/receipt processing
|
|
1548
|
+
- Form data extraction
|
|
1549
|
+
- PDF report generation
|
|
1550
|
+
- Document digitization
|
|
1551
|
+
- Automated data entry
|
|
1552
|
+
|
|
1553
|
+
### AI - Application Settings
|
|
1554
|
+
|
|
1555
|
+
Manage AI provider settings and API keys for your application.
|
|
1556
|
+
|
|
1557
|
+
```typescript
|
|
1558
|
+
const aiClient = squid.ai();
|
|
1559
|
+
|
|
1560
|
+
// Get application AI settings
|
|
1561
|
+
const settings = await aiClient.getApplicationAiSettings();
|
|
1562
|
+
console.log(settings);
|
|
1563
|
+
|
|
1564
|
+
// Set application AI settings
|
|
1565
|
+
await aiClient.setApplicationAiSettings({
|
|
1566
|
+
defaultModel: 'gpt-4o',
|
|
1567
|
+
// ... other settings
|
|
1568
|
+
});
|
|
1569
|
+
|
|
1570
|
+
// Set AI provider API key secret
|
|
1571
|
+
await aiClient.setAiProviderApiKeySecret(
|
|
1572
|
+
'openai', // providerType: 'openai' | 'anthropic' | 'google' | etc.
|
|
1573
|
+
'OPENAI_API_KEY' // secret key name from secrets manager
|
|
1574
|
+
);
|
|
1575
|
+
```
|
|
1576
|
+
|
|
1185
1577
|
### Storage
|
|
1186
1578
|
|
|
1187
1579
|
```typescript
|
|
@@ -1208,6 +1600,34 @@ await storage.deleteFile('/documents/report.pdf');
|
|
|
1208
1600
|
await storage.deleteFiles(['/docs/file1.pdf', '/docs/file2.pdf']);
|
|
1209
1601
|
```
|
|
1210
1602
|
|
|
1603
|
+
### External OAuth Integration
|
|
1604
|
+
|
|
1605
|
+
Manage OAuth tokens for external integrations. Squid automatically handles token refresh when tokens expire.
|
|
1606
|
+
|
|
1607
|
+
```typescript
|
|
1608
|
+
const externalAuth = squid.externalAuth('google-oauth-integration');
|
|
1609
|
+
|
|
1610
|
+
// Save authorization code (exchange for access token)
|
|
1611
|
+
const tokenResponse = await externalAuth.saveAuthCode(
|
|
1612
|
+
'authorization-code-from-oauth-flow',
|
|
1613
|
+
'user-identifier' // Unique identifier for this user
|
|
1614
|
+
);
|
|
1615
|
+
console.log('Access token:', tokenResponse.accessToken);
|
|
1616
|
+
console.log('Refresh token:', tokenResponse.refreshToken);
|
|
1617
|
+
console.log('Expires at:', tokenResponse.expiresAt);
|
|
1618
|
+
|
|
1619
|
+
// Get access token (auto-refreshes if expired)
|
|
1620
|
+
const token = await externalAuth.getAccessToken('user-identifier');
|
|
1621
|
+
console.log('Current access token:', token.accessToken);
|
|
1622
|
+
```
|
|
1623
|
+
|
|
1624
|
+
**Use cases:**
|
|
1625
|
+
- Google Drive/Calendar integration
|
|
1626
|
+
- GitHub OAuth
|
|
1627
|
+
- Slack OAuth
|
|
1628
|
+
- Any external service requiring OAuth 2.0
|
|
1629
|
+
- Squid handles token refresh automatically
|
|
1630
|
+
|
|
1211
1631
|
### Queues
|
|
1212
1632
|
|
|
1213
1633
|
```typescript
|
|
@@ -1240,13 +1660,22 @@ try {
|
|
|
1240
1660
|
lock.release(); // Note: release() is synchronous
|
|
1241
1661
|
}
|
|
1242
1662
|
|
|
1243
|
-
//
|
|
1244
|
-
|
|
1663
|
+
// Acquire with auto-release timeout (maxHoldTimeMillis)
|
|
1664
|
+
const lockWithTimeout = await squid.acquireLock('my-mutex', {
|
|
1665
|
+
maxHoldTimeMillis: 30000 // Auto-release after 30 seconds
|
|
1666
|
+
});
|
|
1667
|
+
|
|
1668
|
+
// Access lock properties
|
|
1669
|
+
console.log(lock.resourceId); // The mutex name: 'payment-processing'
|
|
1670
|
+
console.log(lock.lockId); // Unique ID for this lock instance
|
|
1671
|
+
console.log(lock.isReleased()); // Check if released: true/false
|
|
1245
1672
|
|
|
1246
1673
|
// Observe release (RxJS Observable)
|
|
1247
1674
|
const sub = lock.observeRelease().subscribe(() => {
|
|
1248
1675
|
console.log('Lock was released');
|
|
1249
1676
|
});
|
|
1677
|
+
// Don't forget to unsubscribe when done
|
|
1678
|
+
sub.unsubscribe();
|
|
1250
1679
|
|
|
1251
1680
|
// Automatic release with withLock (recommended)
|
|
1252
1681
|
const result = await squid.withLock('payment-processing', async (lock) => {
|
|
@@ -1261,6 +1690,7 @@ const result = await squid.withLock('payment-processing', async (lock) => {
|
|
|
1261
1690
|
**Important notes:**
|
|
1262
1691
|
- Lock is automatically released if WebSocket connection is lost
|
|
1263
1692
|
- If lock is already held by another client, `acquireLock()` will reject
|
|
1693
|
+
- `maxHoldTimeMillis` option automatically releases lock after specified duration
|
|
1264
1694
|
- Use `@secureDistributedLock(mutexName?)` decorator to secure lock access
|
|
1265
1695
|
- Without API key, you must define security rules for locks
|
|
1266
1696
|
|
|
@@ -1269,19 +1699,32 @@ const result = await squid.withLock('payment-processing', async (lock) => {
|
|
|
1269
1699
|
```typescript
|
|
1270
1700
|
const api = squid.api();
|
|
1271
1701
|
|
|
1272
|
-
// HTTP methods
|
|
1273
|
-
const
|
|
1702
|
+
// HTTP methods - All return HttpResponse<T> with status, headers, and body
|
|
1703
|
+
const customerResponse = await api.get<Customer>('stripe-api', 'get-customer', {
|
|
1274
1704
|
pathParams: { customerId: 'cus_123' },
|
|
1275
1705
|
queryParams: { expand: 'subscriptions' }
|
|
1276
1706
|
});
|
|
1707
|
+
// Access response details
|
|
1708
|
+
console.log(customerResponse.status); // HTTP status code
|
|
1709
|
+
console.log(customerResponse.headers); // Response headers
|
|
1710
|
+
console.log(customerResponse.body); // Parsed response body
|
|
1277
1711
|
|
|
1278
|
-
const
|
|
1712
|
+
const chargeResponse = await api.post<Charge, ChargeRequest>(
|
|
1279
1713
|
'stripe-api',
|
|
1280
1714
|
'create-charge',
|
|
1281
1715
|
{ amount: 1000, currency: 'usd' },
|
|
1282
1716
|
{ headers: { 'Idempotency-Key': 'unique' } }
|
|
1283
1717
|
);
|
|
1284
1718
|
|
|
1719
|
+
// Generic request method (for custom HTTP methods or complex requests)
|
|
1720
|
+
const response = await api.request<ResponseType, RequestType>(
|
|
1721
|
+
'integration-id',
|
|
1722
|
+
'endpoint-id',
|
|
1723
|
+
requestBody,
|
|
1724
|
+
{ headers: {}, queryParams: {} },
|
|
1725
|
+
'POST' // or 'GET', 'PUT', 'PATCH', 'DELETE'
|
|
1726
|
+
);
|
|
1727
|
+
|
|
1285
1728
|
// Other methods: put, patch, delete
|
|
1286
1729
|
await api.put(integrationId, endpointId, body, options);
|
|
1287
1730
|
await api.patch(integrationId, endpointId, body, options);
|
|
@@ -1354,6 +1797,35 @@ const metrics = await obs.queryMetrics({
|
|
|
1354
1797
|
await obs.flush();
|
|
1355
1798
|
```
|
|
1356
1799
|
|
|
1800
|
+
### Custom Notifications
|
|
1801
|
+
|
|
1802
|
+
Send custom messages between clients for real-time coordination.
|
|
1803
|
+
|
|
1804
|
+
```typescript
|
|
1805
|
+
const notifications = squid.getNotificationClient();
|
|
1806
|
+
|
|
1807
|
+
// Observe incoming notifications
|
|
1808
|
+
const subscription = notifications.observeNotifications().subscribe(payload => {
|
|
1809
|
+
console.log('Received notification:', payload);
|
|
1810
|
+
// payload can be any serializable data
|
|
1811
|
+
});
|
|
1812
|
+
|
|
1813
|
+
// Publish notification to specific clients - can be done only if Squid was initialized with API key.
|
|
1814
|
+
await notifications.publishNotification(
|
|
1815
|
+
{ type: 'update', message: 'Data changed' }, // payload
|
|
1816
|
+
['client-id-1', 'client-id-2'] // target client IDs
|
|
1817
|
+
);
|
|
1818
|
+
|
|
1819
|
+
// Unsubscribe when done
|
|
1820
|
+
subscription.unsubscribe();
|
|
1821
|
+
```
|
|
1822
|
+
|
|
1823
|
+
**Use cases:**
|
|
1824
|
+
- Real-time coordination between users
|
|
1825
|
+
- Custom event notifications
|
|
1826
|
+
- Client-to-client messaging
|
|
1827
|
+
- Broadcast updates to specific users
|
|
1828
|
+
|
|
1357
1829
|
### Jobs
|
|
1358
1830
|
|
|
1359
1831
|
Jobs allow you to track the status of long-running asynchronous operations. Each job has a unique ID that can be used to query its status or wait for completion.
|
|
@@ -1406,6 +1878,24 @@ await integrations.upsertIntegration({
|
|
|
1406
1878
|
// Delete
|
|
1407
1879
|
await integrations.delete('old-integration');
|
|
1408
1880
|
await integrations.deleteMany(['int-1', 'int-2']);
|
|
1881
|
+
|
|
1882
|
+
// Get integration schema
|
|
1883
|
+
const schema = await integrations.getIntegrationSchema<MySchemaType>('postgres-db');
|
|
1884
|
+
console.log(schema);
|
|
1885
|
+
|
|
1886
|
+
// Set integration schema
|
|
1887
|
+
await integrations.setIntegrationSchema('postgres-db', {
|
|
1888
|
+
collections: [
|
|
1889
|
+
{
|
|
1890
|
+
name: 'users',
|
|
1891
|
+
fields: [
|
|
1892
|
+
{ name: 'id', type: 'string', primaryKey: true },
|
|
1893
|
+
{ name: 'email', type: 'string' },
|
|
1894
|
+
{ name: 'name', type: 'string' }
|
|
1895
|
+
]
|
|
1896
|
+
}
|
|
1897
|
+
]
|
|
1898
|
+
});
|
|
1409
1899
|
```
|
|
1410
1900
|
|
|
1411
1901
|
### Admin - Secrets
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squidcloud/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.417",
|
|
4
4
|
"description": "The Squid CLI",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=18.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@squidcloud/local-backend": "^1.0.
|
|
31
|
+
"@squidcloud/local-backend": "^1.0.417",
|
|
32
32
|
"adm-zip": "^0.5.16",
|
|
33
33
|
"copy-webpack-plugin": "^12.0.2",
|
|
34
34
|
"decompress": "^4.2.1",
|