connectbase-client 0.5.1 → 0.6.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.
package/README.md CHANGED
@@ -443,6 +443,158 @@ await cb.database.updateData('table-id', 'data-id', {
443
443
  await cb.database.deleteData('table-id', 'data-id')
444
444
  ```
445
445
 
446
+ #### Aggregation (MongoDB-style Pipeline)
447
+
448
+ ```typescript
449
+ const result = await cb.database.aggregate('table-id', [
450
+ { match: { status: 'active' } },
451
+ { group: { _id: '$category', total: { $sum: '$price' }, count: { $sum: 1 } } },
452
+ { sort: { total: -1 } },
453
+ { limit: 10 }
454
+ ])
455
+ console.log(result.results) // [{ _id: 'electronics', total: 5000, count: 12 }, ...]
456
+ ```
457
+
458
+ #### Full-Text Search
459
+
460
+ ```typescript
461
+ // Fuzzy search with highlighting
462
+ const results = await cb.database.search('table-id', 'smrt phone', ['name', 'description'], {
463
+ fuzzy: true,
464
+ fuzzy_distance: 2,
465
+ highlight: true,
466
+ limit: 10
467
+ })
468
+
469
+ results.results.forEach(item => {
470
+ console.log(item.data.name, item.score, item.highlights)
471
+ })
472
+
473
+ // Autocomplete
474
+ const suggestions = await cb.database.autocomplete('table-id', 'sma', 'name', { limit: 5 })
475
+ ```
476
+
477
+ #### Geo Queries
478
+
479
+ ```typescript
480
+ // Find locations within 5km radius
481
+ const nearby = await cb.database.geoQuery('table-id', 'location', {
482
+ near: {
483
+ center: { latitude: 37.5665, longitude: 126.9780 },
484
+ max_distance: 5000
485
+ }
486
+ }, { limit: 20 })
487
+
488
+ nearby.results.forEach(place => {
489
+ console.log(place.data.name, `${place.distance}m away`)
490
+ })
491
+ ```
492
+
493
+ #### Batch & Transactions
494
+
495
+ ```typescript
496
+ // Batch: atomic multi-table operations
497
+ await cb.database.batch([
498
+ { type: 'create', table: 'orders', data: { product: 'A', qty: 1 } },
499
+ { type: 'update', table: 'inventory', doc_id: 'item-a', operators: {
500
+ qty: { type: 'increment', value: -1 }
501
+ }},
502
+ { type: 'update', table: 'stats', doc_id: 'daily', operators: {
503
+ order_count: { type: 'increment', value: 1 },
504
+ last_order: { type: 'serverTimestamp' }
505
+ }}
506
+ ])
507
+
508
+ // Transaction: read-then-write with ACID guarantees
509
+ await cb.database.transaction(
510
+ [{ table: 'accounts', doc_id: 'user-1', alias: 'sender' }],
511
+ [{ type: 'update', table: 'accounts', doc_id: 'user-1', operators: {
512
+ balance: { type: 'increment', value: -100 }
513
+ }}]
514
+ )
515
+ ```
516
+
517
+ #### Populate (Relation Query / JOIN)
518
+
519
+ ```typescript
520
+ // Query with related data populated
521
+ const posts = await cb.database.getDataWithPopulate('posts-table', {
522
+ limit: 10,
523
+ populate: [
524
+ { field: 'author_id', from: 'users', as: 'author', select: ['name', 'avatar'] },
525
+ { field: 'id', from: 'comments', as: 'comments', limit: 5, orderBy: 'created_at', order: 'desc' }
526
+ ]
527
+ })
528
+ ```
529
+
530
+ #### Security Rules (RLS)
531
+
532
+ ```typescript
533
+ // Set row-level security rules
534
+ await cb.database.createSecurityRule('app-id', {
535
+ table_name: 'posts',
536
+ rules: {
537
+ read: 'true', // Anyone can read
538
+ create: 'auth.member_id != null', // Only authenticated users
539
+ update: 'auth.member_id == data.author_id', // Only author
540
+ delete: 'auth.member_id == data.author_id'
541
+ }
542
+ })
543
+
544
+ // List rules
545
+ const rules = await cb.database.listSecurityRules('app-id')
546
+ ```
547
+
548
+ #### Indexes
549
+
550
+ ```typescript
551
+ // Create unique index
552
+ await cb.database.createIndex('app-id', 'table-id', {
553
+ name: 'idx_email_unique',
554
+ fields: ['email'],
555
+ unique: true
556
+ })
557
+
558
+ // Analyze and get recommendations
559
+ const analysis = await cb.database.analyzeIndexes('app-id', 'table-id')
560
+ analysis.recommendations.forEach(rec => {
561
+ console.log(`Recommended: ${rec.fields.join(', ')} — ${rec.reason}`)
562
+ })
563
+ ```
564
+
565
+ #### Triggers
566
+
567
+ ```typescript
568
+ // Auto-execute function on data change
569
+ await cb.database.createTrigger('app-id', {
570
+ name: 'on-order-created',
571
+ table_name: 'orders',
572
+ event: 'create',
573
+ handler_type: 'function',
574
+ handler_id: 'send-notification-fn-id'
575
+ })
576
+ ```
577
+
578
+ #### Lifecycle (TTL / Retention)
579
+
580
+ ```typescript
581
+ // Auto-delete expired sessions
582
+ await cb.database.setTTL('app-id', {
583
+ table_name: 'sessions',
584
+ field: 'expires_at',
585
+ enabled: true
586
+ })
587
+
588
+ // Archive old logs after 90 days
589
+ await cb.database.setRetentionPolicy('app-id', {
590
+ table_name: 'logs',
591
+ retention_days: 90,
592
+ action: 'archive',
593
+ archive_table: 'archived_logs',
594
+ enabled: true
595
+ })
596
+ ```
597
+
446
598
  ### Storage
447
599
 
448
600
  ```typescript
package/dist/cli.js CHANGED
@@ -375,6 +375,11 @@ ${colors.blue}?${colors.reset} \uC120\uD0DD (\uBC88\uD638): `);
375
375
  success(".connectbaserc \uC0DD\uC131 \uC644\uB8CC");
376
376
  addToGitignore(".connectbaserc");
377
377
  addDeployScript(deployDir);
378
+ const setupClaude = await prompt(`
379
+ ${colors.blue}?${colors.reset} Claude Code \uC124\uC815\uC744 \uCD94\uAC00\uD560\uAE4C\uC694? (CLAUDE.md, MCP \uC124\uC815) (Y/n): `);
380
+ if (setupClaude.toLowerCase() !== "n") {
381
+ await setupClaudeCode(apiKey);
382
+ }
378
383
  log(`
379
384
  ${colors.green}\uCD08\uAE30\uD654 \uC644\uB8CC!${colors.reset}
380
385
  `);
@@ -432,6 +437,157 @@ function addDeployScript(deployDir) {
432
437
  warn("package.json \uC218\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4");
433
438
  }
434
439
  }
440
+ async function setupClaudeCode(apiKey) {
441
+ const claudeDir = path.join(process.cwd(), ".claude");
442
+ const claudeMdPath = path.join(claudeDir, "CLAUDE.md");
443
+ const mcpConfigPath = path.join(process.cwd(), ".mcp.json");
444
+ if (!fs.existsSync(claudeDir)) {
445
+ fs.mkdirSync(claudeDir, { recursive: true });
446
+ }
447
+ const claudeMdContent = `# CLAUDE.md
448
+
449
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
450
+
451
+ ## Connect Base SDK
452
+
453
+ \uC774 \uD504\uB85C\uC81D\uD2B8\uB294 Connect Base SDK\uB97C \uC0AC\uC6A9\uD569\uB2C8\uB2E4.
454
+
455
+ ### \uC124\uCE58
456
+
457
+ \`\`\`bash
458
+ npm install connectbase-client
459
+ \`\`\`
460
+
461
+ ### \uAE30\uBCF8 \uC0AC\uC6A9\uBC95
462
+
463
+ \`\`\`typescript
464
+ import ConnectBase from 'connectbase-client'
465
+
466
+ const cb = new ConnectBase({
467
+ apiKey: 'YOUR_API_KEY'
468
+ })
469
+ \`\`\`
470
+
471
+ ### Database API
472
+
473
+ \`\`\`typescript
474
+ // \uB370\uC774\uD130 \uC870\uD68C
475
+ const { data, total } = await cb.database.getData('table-id', {
476
+ limit: 20,
477
+ offset: 0,
478
+ select: ['id', 'name', 'thumbnail'], // \uD2B9\uC815 \uD544\uB4DC\uB9CC \uC870\uD68C
479
+ exclude: ['html_content'] // \uD2B9\uC815 \uD544\uB4DC \uC81C\uC678
480
+ })
481
+
482
+ // \uC870\uAC74\uBD80 \uCFFC\uB9AC
483
+ const result = await cb.database.queryData('table-id', {
484
+ where: { field: 'status', operator: 'eq', value: 'active' },
485
+ orderBy: 'created_at',
486
+ orderDirection: 'desc'
487
+ })
488
+
489
+ // \uB370\uC774\uD130 \uC0DD\uC131
490
+ const newItem = await cb.database.createData('table-id', {
491
+ data: { name: 'John', email: 'john@example.com' }
492
+ })
493
+
494
+ // \uB370\uC774\uD130 \uC218\uC815
495
+ await cb.database.updateData('table-id', 'data-id', {
496
+ data: { name: 'Jane' }
497
+ })
498
+
499
+ // \uB370\uC774\uD130 \uC0AD\uC81C
500
+ await cb.database.deleteData('table-id', 'data-id')
501
+ \`\`\`
502
+
503
+ ### Storage API
504
+
505
+ \`\`\`typescript
506
+ // \uD30C\uC77C \uC5C5\uB85C\uB4DC
507
+ const result = await cb.storage.uploadFile(file)
508
+
509
+ // \uD30C\uC77C \uBAA9\uB85D \uC870\uD68C
510
+ const files = await cb.storage.listFiles()
511
+ \`\`\`
512
+
513
+ ### Auth API
514
+
515
+ \`\`\`typescript
516
+ // \uD68C\uC6D0\uAC00\uC785
517
+ await cb.auth.signUp({ email, password })
518
+
519
+ // \uB85C\uADF8\uC778
520
+ const { member, tokens } = await cb.auth.signIn({ email, password })
521
+
522
+ // \uB85C\uADF8\uC544\uC6C3
523
+ await cb.auth.signOut()
524
+ \`\`\`
525
+
526
+ ### Functions API
527
+
528
+ \`\`\`typescript
529
+ // Serverless \uD568\uC218 \uD638\uCD9C
530
+ const result = await cb.functions.invoke('function-name', {
531
+ param1: 'value1'
532
+ })
533
+ \`\`\`
534
+
535
+ ### Realtime API
536
+
537
+ \`\`\`typescript
538
+ // WebSocket \uC5F0\uACB0
539
+ cb.realtime.connect()
540
+
541
+ // \uCC44\uB110 \uAD6C\uB3C5
542
+ cb.realtime.subscribe('channel-name', (message) => {
543
+ console.log('\uBC1B\uC740 \uBA54\uC2DC\uC9C0:', message)
544
+ })
545
+
546
+ // \uBA54\uC2DC\uC9C0 \uC804\uC1A1
547
+ cb.realtime.send('channel-name', { text: 'Hello!' })
548
+ \`\`\`
549
+
550
+ ## Where \uC5F0\uC0B0\uC790
551
+
552
+ | \uC5F0\uC0B0\uC790 | \uC124\uBA85 |
553
+ |--------|------|
554
+ | \`eq\` | \uAC19\uC74C (=) |
555
+ | \`neq\` | \uAC19\uC9C0 \uC54A\uC74C (!=) |
556
+ | \`gt\` | \uD07C (>) |
557
+ | \`gte\` | \uD06C\uAC70\uB098 \uAC19\uC74C (>=) |
558
+ | \`lt\` | \uC791\uC74C (<) |
559
+ | \`lte\` | \uC791\uAC70\uB098 \uAC19\uC74C (<=) |
560
+ | \`like\` | \uBD80\uBD84 \uC77C\uCE58 |
561
+ | \`in\` | \uBC30\uC5F4\uC5D0 \uD3EC\uD568 |
562
+ | \`nin\` | \uBC30\uC5F4\uC5D0 \uBBF8\uD3EC\uD568 |
563
+ | \`between\` | \uBC94\uC704 \uB0B4 |
564
+ | \`is_null\` | NULL \uCCB4\uD06C |
565
+ | \`regex\` | \uC815\uADDC\uC2DD \uB9E4\uCE6D |
566
+ | \`array_contains\` | \uBC30\uC5F4 \uD544\uB4DC\uC5D0 \uAC12 \uD3EC\uD568 |
567
+
568
+ ## \uBC30\uD3EC
569
+
570
+ \`\`\`bash
571
+ npm run deploy
572
+ \`\`\`
573
+ `;
574
+ fs.writeFileSync(claudeMdPath, claudeMdContent);
575
+ success(".claude/CLAUDE.md \uC0DD\uC131 \uC644\uB8CC");
576
+ const mcpConfig = {
577
+ mcpServers: {
578
+ connectbase: {
579
+ url: "https://mcp.connectbase.world/mcp",
580
+ headers: {
581
+ Authorization: `Bearer ${apiKey}`
582
+ }
583
+ }
584
+ }
585
+ };
586
+ fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + "\n");
587
+ success(".mcp.json \uC0DD\uC131 \uC644\uB8CC");
588
+ addToGitignore(".mcp.json");
589
+ info("Claude Code\uC5D0\uC11C MCP \uC11C\uBC84\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 .mcp.json \uD30C\uC77C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4");
590
+ }
435
591
  function createWsTextFrame(payload) {
436
592
  const data = Buffer.from(payload, "utf-8");
437
593
  const len = data.length;