@squidcloud/cli 1.0.449 → 1.0.451
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 +521 -121
- package/dist/resources/claude/skills/squid-development/SKILL.md +1 -1
- package/dist/resources/claude/skills/squid-development/reference/backend.md +2 -2
- package/dist/resources/claude/skills/squid-development/reference/databases.md +139 -0
- package/dist/resources/user-build.webpack.config.js +9 -0
- package/package.json +2 -2
|
@@ -18,7 +18,7 @@ Squid is a backend-as-a-service platform that provides:
|
|
|
18
18
|
- **[client.md](reference/client.md)** → client SDK, initialization, setup, auth, login, tokens, OAuth, appId, region, environmentId, apiKey, authProvider, getToken, setAuthProvider, Squid client, frontend, collection, executeFunction, executeFunctionWithHeaders, getWebhookUrl, externalAuth, saveAuthCode, getAccessToken, storage, uploadFile, downloadUrl, queues, produce, consume, distributed locks, acquireLock, withLock, web, aiSearch, getUrlContent, createShortUrl, jobs, getJob, awaitJob, observability, metrics, reportMetric, queryMetrics, notifications, publishNotification, observeNotifications
|
|
19
19
|
- **[console.md](reference/console.md)** → Squid Console, web UI, organizations, applications, AI Studio, knowledge bases, integrations, monitoring, logs, API keys, secrets, testing, debugging, profile settings, management API keys
|
|
20
20
|
- **[ai.md](reference/ai.md)** → AI agents, chat, ask, askWithAnnotations, askAsync, askWithVoiceResponse, transcribeAndChat, transcribeAndAsk, knowledge bases, RAG, embeddings, image generation, audio, transcription, text-to-speech, TTS, connectedAgents, connectedIntegrations, connectedKnowledgeBases, @aiFunction, @secureAiAgent, @secureAiQuery, memory, memoryOptions, voiceOptions, OpenAI, Anthropic, Gemini, Grok, DALL-E, Whisper, MCP, @mcpServer, @mcpTool, executeAiQuery, executeAiApiCall, extraction, createPdf, upsert agent, listAgents
|
|
21
|
-
- **[databases.md](reference/databases.md)** → collections, documents, queries, subscriptions, snapshots, insert, update, delete, CRUD, real-time, dereference, pagination, transactions, query operators, eq, neq, gt, gte, lt, lte, like, in, nin, arrayIncludesSome, arrayIncludesAll, sortBy, limit, join queries, OR queries, @trigger, native queries, SQL, MongoDB, Elasticsearch, incrementInPath, decrementInPath, watch changes, doc()
|
|
21
|
+
- **[databases.md](reference/databases.md)** → collections, documents, queries, subscriptions, snapshots, insert, update, delete, CRUD, real-time, dereference, pagination, transactions, query operators, eq, neq, gt, gte, lt, lte, like, in, nin, arrayIncludesSome, arrayIncludesAll, sortBy, limit, join queries, OR queries, @trigger, native queries, SQL, MongoDB, Elasticsearch, incrementInPath, decrementInPath, watch changes, doc(), projectFields, field projection, __docId__, __id
|
|
22
22
|
- **[backend.md](reference/backend.md)** → SquidService, @executable, @webhook, @trigger, TriggerRequest, @scheduler, @limits, rate limiting, quotas, decorators, backend functions, WebhookRequest, CronExpression, cron, file handling, SquidFile, getUserAuth, isAuthenticated, assertIsAuthenticated, createWebhookResponse, this.squid, this.secrets, @clientConnectionStateHandler, CLI, squid init, squid start, squid deploy, squid build, project structure
|
|
23
23
|
- **[security.md](reference/security.md)** → security rules, @secureDatabase, @secureCollection, @secureTopic, @secureStorage, @secureApi, @secureNativeQuery, @secureAiQuery, @secureAiAgent, @secureDistributedLock, @secureGraphQL, QueryContext, MutationContext, isSubqueryOf, affectsPath, permissions, authorization, row-level security, role-based access
|
|
24
24
|
- **[admin.md](reference/admin.md)** → ManagementClient, management API keys, organizations, applications, programmatic management, CI/CD, automation, integrations admin, secrets admin, upsertIntegration, discoverDataConnectionSchema, testDataConnection, createOrganization, createApplication
|
|
@@ -393,8 +393,8 @@ export class MyService extends SquidService {
|
|
|
393
393
|
Handle client connection and disconnection events.
|
|
394
394
|
|
|
395
395
|
```typescript
|
|
396
|
-
import { SquidService, clientConnectionStateHandler
|
|
397
|
-
import { ClientId } from '@squidcloud/client';
|
|
396
|
+
import { SquidService, clientConnectionStateHandler } from '@squidcloud/backend';
|
|
397
|
+
import { ClientConnectionState, ClientId } from '@squidcloud/client';
|
|
398
398
|
|
|
399
399
|
export class MyService extends SquidService {
|
|
400
400
|
@clientConnectionStateHandler()
|
|
@@ -11,6 +11,7 @@ Squid provides database functionality similar to Firestore but more powerful, wi
|
|
|
11
11
|
- OR Queries
|
|
12
12
|
- Join Queries
|
|
13
13
|
- Dereference
|
|
14
|
+
- Field Projection
|
|
14
15
|
- Pagination
|
|
15
16
|
- Watch Changes
|
|
16
17
|
- Transactions
|
|
@@ -314,6 +315,144 @@ const userData = await users.query()
|
|
|
314
315
|
// - You need DocumentReference methods like .update() or .delete()
|
|
315
316
|
```
|
|
316
317
|
|
|
318
|
+
## Field Projection
|
|
319
|
+
|
|
320
|
+
Return only specific fields from queries to reduce bandwidth and improve performance.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// Basic usage
|
|
324
|
+
const results = await users.query()
|
|
325
|
+
.projectFields(['name', 'email'])
|
|
326
|
+
.dereference()
|
|
327
|
+
.snapshot();
|
|
328
|
+
|
|
329
|
+
// Works with all query methods
|
|
330
|
+
const results = await users.query()
|
|
331
|
+
.eq('status', 'active')
|
|
332
|
+
.sortBy('name')
|
|
333
|
+
.limit(50)
|
|
334
|
+
.projectFields(['name', 'email', 'status'])
|
|
335
|
+
.dereference()
|
|
336
|
+
.snapshot();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Always-Included Fields
|
|
340
|
+
|
|
341
|
+
These fields are **always** included in results regardless of projection:
|
|
342
|
+
|
|
343
|
+
| Field | Present On | Description |
|
|
344
|
+
|-------|------------|-------------|
|
|
345
|
+
| `__docId__` | All integrations | JSON-stringified document identifier |
|
|
346
|
+
| `__id` | `built_in_db` only | Primary key value |
|
|
347
|
+
|
|
348
|
+
For **composite primary keys**, individual key fields are automatically spread to the top level:
|
|
349
|
+
```typescript
|
|
350
|
+
// Document with composite PK (pk1, pk2)
|
|
351
|
+
// Result includes: { name: 'Alice', __docId__: '{"pk1":"a","pk2":1}', pk1: 'a', pk2: 1 }
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Nested Fields
|
|
355
|
+
|
|
356
|
+
Use dot notation for nested paths:
|
|
357
|
+
```typescript
|
|
358
|
+
const results = await users.query()
|
|
359
|
+
.projectFields(['name', 'address.city', 'address.zip'])
|
|
360
|
+
.dereference()
|
|
361
|
+
.snapshot();
|
|
362
|
+
// Result: { name: 'Alice', address: { city: 'NYC', zip: '10001' } }
|
|
363
|
+
// Other address fields NOT included
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Validation Rules
|
|
367
|
+
|
|
368
|
+
**Filter fields must be projected:**
|
|
369
|
+
```typescript
|
|
370
|
+
// ERROR: Cannot filter by 'email' not in projectFields
|
|
371
|
+
users.query().eq('email', 'test@example.com').projectFields(['name']);
|
|
372
|
+
|
|
373
|
+
// CORRECT: Include filter field
|
|
374
|
+
users.query().eq('email', 'test@example.com').projectFields(['name', 'email']);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Sort fields must be projected:**
|
|
378
|
+
```typescript
|
|
379
|
+
// ERROR: Cannot sort by 'email' not in projectFields
|
|
380
|
+
users.query().sortBy('email').projectFields(['name']);
|
|
381
|
+
|
|
382
|
+
// CORRECT: Include sort field
|
|
383
|
+
users.query().sortBy('email').projectFields(['name', 'email']);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
**Exception:** `__docId__` can always be used for filtering/sorting without being in projection:
|
|
387
|
+
```typescript
|
|
388
|
+
// ALLOWED: __docId__ is always available
|
|
389
|
+
users.query().where('__docId__', '>=', 'user_100').projectFields(['name']);
|
|
390
|
+
users.query().sortBy('__docId__').projectFields(['name']);
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Composite conditions must use projected fields:**
|
|
394
|
+
```typescript
|
|
395
|
+
// ERROR: Cannot filter by 'email' not in projectFields
|
|
396
|
+
users.query().projectFields(['name']).addCompositeCondition([{ fieldName: 'email', operator: '>=', value: 'a' }]);
|
|
397
|
+
|
|
398
|
+
// ALLOWED: __docId__ works without projection
|
|
399
|
+
users.query().projectFields(['name']).addCompositeCondition([{ fieldName: '__docId__', operator: '>=', value: 'a' }]);
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Calling projectFields twice:** Second call must be a subset of the first:
|
|
403
|
+
```typescript
|
|
404
|
+
// ALLOWED: ['name'] is subset of ['name', 'age', 'email']
|
|
405
|
+
users.query().projectFields(['name', 'age', 'email']).projectFields(['name']);
|
|
406
|
+
|
|
407
|
+
// ERROR: 'email' was not in first projection
|
|
408
|
+
users.query().projectFields(['name', 'age']).projectFields(['name', 'email']);
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Cloning:** `projectFields` returns a cloned QueryBuilder - original is unmodified:
|
|
412
|
+
```typescript
|
|
413
|
+
const base = collection.query().where('age', '>=', 18);
|
|
414
|
+
const projected = base.projectFields(['name']); // Returns clone
|
|
415
|
+
// base still returns all fields, projected returns only 'name'
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Empty Array Behavior
|
|
419
|
+
|
|
420
|
+
| Integration | Behavior |
|
|
421
|
+
|-------------|----------|
|
|
422
|
+
| `built_in_db` | Returns documents with only `__docId__` and `__id`, no user fields |
|
|
423
|
+
| External DBs | **Throws error** - must specify at least one field |
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
// built_in_db: returns { __docId__: '...', __id: '...' }
|
|
427
|
+
await builtInCollection.query().projectFields([]).snapshot();
|
|
428
|
+
|
|
429
|
+
// External DB: throws error
|
|
430
|
+
await postgresCollection.query().projectFields([]); // Error!
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Edge Cases
|
|
434
|
+
|
|
435
|
+
- **Non-existent fields:** Silently ignored, no error thrown
|
|
436
|
+
- **Duplicate fields:** Handled gracefully, no duplication in results
|
|
437
|
+
- **Including `__id` explicitly:** Not duplicated if already auto-included
|
|
438
|
+
- **Optimistic updates:** Local updates respect the projection - document store only contains projected fields. Multiple subscriptions with different projections maintain isolated views of the same document.
|
|
439
|
+
|
|
440
|
+
### Without dereference()
|
|
441
|
+
|
|
442
|
+
When not using `dereference()`, you get `DocumentReference` objects. Access projected data via `.data`:
|
|
443
|
+
```typescript
|
|
444
|
+
const refs = await users.query().projectFields(['name']).snapshot();
|
|
445
|
+
console.log(refs[0].data.name); // Projected data on .data property
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Works With
|
|
449
|
+
|
|
450
|
+
- One-time queries (`.snapshot()`)
|
|
451
|
+
- Real-time subscriptions (`.snapshots()`)
|
|
452
|
+
- Pagination (`.paginate()`)
|
|
453
|
+
- Join queries
|
|
454
|
+
- All database integrations (MongoDB, PostgreSQL, MySQL, ClickHouse, MS SQL, built_in_db)
|
|
455
|
+
|
|
317
456
|
## Pagination
|
|
318
457
|
|
|
319
458
|
```typescript
|
|
@@ -21,6 +21,15 @@ module.exports = function (env, argv) {
|
|
|
21
21
|
'bufferutil': 'commonjs bufferutil',
|
|
22
22
|
'utf-8-validate': 'commonjs utf-8-validate',
|
|
23
23
|
},
|
|
24
|
+
// Suppress warnings from dependencies that use dynamic requires.
|
|
25
|
+
// These are typically dev dependencies used during build and don't affect runtime.
|
|
26
|
+
ignoreWarnings: [
|
|
27
|
+
{ module: /tsoa/ },
|
|
28
|
+
{ module: /@tsoa\/cli/ },
|
|
29
|
+
{ module: /handlebars/ },
|
|
30
|
+
{ module: /typescript/ },
|
|
31
|
+
{ module: /yargs/ },
|
|
32
|
+
],
|
|
24
33
|
output: {
|
|
25
34
|
path: path.resolve(process.cwd(), 'dist'),
|
|
26
35
|
filename: 'index.js',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squidcloud/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.451",
|
|
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.451",
|
|
32
32
|
"adm-zip": "^0.5.16",
|
|
33
33
|
"copy-webpack-plugin": "^12.0.2",
|
|
34
34
|
"decompress": "^4.2.1",
|