{"id":23885156,"url":"https://github.com/sh20raj/sheetflow","last_synced_at":"2026-02-12T14:06:09.279Z","repository":{"id":270537970,"uuid":"910690214","full_name":"SH20RAJ/SheetFlow","owner":"SH20RAJ","description":"Turns your spreadsheets (Google Sheets) into powerful, customizable REST APIs act as lightweight, dynamic databases.","archived":false,"fork":false,"pushed_at":"2025-01-10T04:09:24.000Z","size":83,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T00:09:09.793Z","etag":null,"topics":["sheetflow","spreadsheet"],"latest_commit_sha":null,"homepage":"https://sh20raj.github.io/SheetFlow/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SH20RAJ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-01T04:42:32.000Z","updated_at":"2025-01-10T04:11:37.000Z","dependencies_parsed_at":"2025-01-01T05:29:25.112Z","dependency_job_id":"38bb165e-18dd-4bcf-ab60-e3499764cc30","html_url":"https://github.com/SH20RAJ/SheetFlow","commit_stats":null,"previous_names":["sh20raj/sheetflow"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SH20RAJ%2FSheetFlow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SH20RAJ%2FSheetFlow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SH20RAJ%2FSheetFlow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SH20RAJ%2FSheetFlow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SH20RAJ","download_url":"https://codeload.github.com/SH20RAJ/SheetFlow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248981268,"owners_count":21193147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sheetflow","spreadsheet"],"created_at":"2025-01-04T04:41:07.083Z","updated_at":"2026-02-12T14:06:04.237Z","avatar_url":"https://github.com/SH20RAJ.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sheet-Flow 📊\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/SH20RAJ/SheetFlow/refs/heads/main/logo.svg\" width=\"200\" height=\"66\" /\u003e\n\n[![npm version](https://img.shields.io/npm/v/@sh20raj/sheet-flow.svg)](https://www.npmjs.com/package/@sh20raj/sheet-flow)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)\n[![Visitors](https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fgithub.com%2FSH20RAJ%2FSheetFlow\u0026labelColor=%2337d67a\u0026countColor=%23ba68c8\u0026style=flat)](https://visitorbadge.io/status?path=https%3A%2F%2Fgithub.com%2FSH20RAJ%2FSheetFlow)\n\n\u003c/div\u003e\n\n**Sheet-Flow** transforms your Google Sheets into powerful, production-ready databases with a RESTful API interface. Built for modern applications, it provides enterprise-grade features while maintaining the simplicity and flexibility of spreadsheets.\n\n## 🌟 Key Features\n\n### Core Functionality\n- **🔄 Real-Time Sync**: Bi-directional synchronization between your API and spreadsheets\n- **🔐 Enterprise-Grade Security**: Row-level access control, API key authentication, and rate limiting\n- **🚀 High Performance**: Intelligent caching and connection pooling for optimal performance\n- **📦 Type Safety**: Full TypeScript support with automatic type inference from sheet headers\n\n### Advanced Features\n- **🔍 Advanced Querying**\n  - Complex filters and search operations\n  - Pagination and sorting\n  - Relationship support between sheets\n  - Aggregation functions\n  \n- **🎯 Data Validation**\n  - Schema validation using Joi\n  - Custom validation rules\n  - Data transformation hooks\n  \n- **🔌 Integration Features**\n  - Webhooks for real-time updates\n  - Event system for data changes\n  - Custom middleware support\n  - Batch operations\n  \n- **🛠 Developer Experience**\n  - Auto-generated TypeScript types\n  - Comprehensive error handling\n  - Detailed logging and monitoring\n  - OpenAPI/Swagger documentation\n\n## 📚 Quick Start\n\n### Installation\n\n```bash\nnpm install @sh20raj/sheet-flow\n```\n\n### Basic Usage\n\n```typescript\nimport { SheetFlow } from '@sh20raj/sheet-flow';\n\n// Initialize SheetFlow\nconst sheetflow = new SheetFlow({\n  credentials: {\n    client_email: process.env.GOOGLE_CLIENT_EMAIL,\n    private_key: process.env.GOOGLE_PRIVATE_KEY,\n  },\n  spreadsheetId: 'your-spreadsheet-id'\n});\n\n// Define your schema (optional)\nconst userSchema = {\n  name: 'string:required',\n  email: 'string:email:required',\n  age: 'number:min(0)',\n};\n\n// Create a table\nconst Users = sheetflow.defineTable('Users', {\n  schema: userSchema,\n  timestamps: true, // Adds createdAt and updatedAt\n});\n\n// CRUD Operations\nasync function examples() {\n  // Create\n  const newUser = await Users.create({\n    name: 'John Doe',\n    email: 'john@example.com',\n    age: 25\n  });\n\n  // Read with filtering\n  const adults = await Users.find({\n    where: {\n      age: { $gte: 18 }\n    },\n    sort: { name: 'asc' },\n    limit: 10\n  });\n\n  // Update\n  await Users.update(\n    { age: { $lt: 18 } },\n    { status: 'minor' }\n  );\n\n  // Delete\n  await Users.delete({\n    email: 'john@example.com'\n  });\n}\n```\n\n## 🔧 Advanced Configuration\n\n```typescript\nconst config: SheetFlowConfig = {\n  credentials: {\n    client_email: process.env.GOOGLE_CLIENT_EMAIL,\n    private_key: process.env.GOOGLE_PRIVATE_KEY,\n  },\n  spreadsheetId: 'your-spreadsheet-id',\n  options: {\n    cache: {\n      enabled: true,\n      ttl: 60000, // 1 minute\n    },\n    sync: {\n      interval: 5000, // 5 seconds\n      strategy: 'optimistic',\n    },\n    security: {\n      encryption: {\n        enabled: true,\n        fields: ['email', 'phone'],\n      },\n      rateLimit: {\n        windowMs: 15 * 60 * 1000, // 15 minutes\n        max: 100, // limit each IP to 100 requests per windowMs\n      },\n    },\n    logging: {\n      level: 'info',\n      format: 'json',\n    },\n  },\n};\n```\n\n## 🔐 Authentication \u0026 Security\n\n### API Key Authentication\n\n```typescript\nimport { SheetFlow, auth } from '@sh20raj/sheet-flow';\n\nconst app = express();\n\n// Add authentication middleware\napp.use(auth.apiKey({\n  header: 'X-API-Key',\n  keys: ['your-api-key'],\n}));\n```\n\n### Row-Level Security\n\n```typescript\nconst Users = sheetflow.defineTable('Users', {\n  schema: userSchema,\n  security: {\n    policies: {\n      read: (user, row) =\u003e user.id === row.userId || user.role === 'admin',\n      write: (user, row) =\u003e user.role === 'admin',\n    },\n  },\n});\n```\n\n## 🎯 Event Handling\n\n```typescript\n// Subscribe to events\nUsers.on('beforeCreate', async (data) =\u003e {\n  // Validate or transform data before creation\n  data.createdBy = currentUser.id;\n});\n\nUsers.on('afterUpdate', async (oldData, newData) =\u003e {\n  // Trigger webhooks or other side effects\n  await notifyWebhooks({\n    event: 'user.updated',\n    data: { old: oldData, new: newData },\n  });\n});\n```\n\n## 📊 Relationships \u0026 Joins\n\n```typescript\nconst Orders = sheetflow.defineTable('Orders', {\n  schema: orderSchema,\n  relationships: {\n    user: {\n      type: 'belongsTo',\n      table: 'Users',\n      foreignKey: 'userId',\n    },\n  },\n});\n\n// Query with joins\nconst ordersWithUsers = await Orders.find({\n  include: ['user'],\n  where: {\n    'user.country': 'USA',\n  },\n});\n```\n\n## 🔍 Advanced Queries\n\n```typescript\n// Complex filtering\nconst results = await Users.find({\n  where: {\n    $or: [\n      { age: { $gt: 18 } },\n      { status: 'approved' },\n    ],\n    country: { $in: ['USA', 'Canada'] },\n    lastLogin: { $gte: new Date('2023-01-01') },\n  },\n  select: ['id', 'name', 'email'],\n  sort: { age: 'desc' },\n  limit: 20,\n  offset: 0,\n});\n\n// Aggregations\nconst stats = await Users.aggregate({\n  $group: {\n    _id: '$country',\n    avgAge: { $avg: '$age' },\n    total: { $count: true },\n  },\n  having: {\n    total: { $gt: 100 },\n  },\n});\n```\n\n## 🚨 Error Handling\n\n```typescript\ntry {\n  await Users.create({\n    name: 'John',\n    email: 'invalid-email',\n  });\n} catch (error) {\n  if (error instanceof SheetFlowValidationError) {\n    console.error('Validation failed:', error.details);\n  } else if (error instanceof SheetFlowConnectionError) {\n    console.error('Connection failed:', error.message);\n  }\n}\n```\n\n## 📈 Monitoring \u0026 Logging\n\n```typescript\n// Custom logger\nsheetflow.setLogger({\n  info: (msg, meta) =\u003e winston.info(msg, meta),\n  error: (msg, meta) =\u003e winston.error(msg, meta),\n});\n\n// Monitor performance\nsheetflow.on('query', (stats) =\u003e {\n  console.log(`Query took ${stats.duration}ms`);\n});\n```\n\n## 🔄 Migration Tools\n\n```typescript\nimport { migrate } from '@sh20raj/sheet-flow/tools';\n\n// Create a migration\nconst migration = {\n  up: async (sheet) =\u003e {\n    await sheet.addColumn('status', { type: 'string', default: 'active' });\n    await sheet.renameColumn('userName', 'fullName');\n  },\n  down: async (sheet) =\u003e {\n    await sheet.removeColumn('status');\n    await sheet.renameColumn('fullName', 'userName');\n  },\n};\n\n// Run migrations\nawait migrate.up();\n```\n\n## 🧪 Testing\n\n```typescript\nimport { createTestClient } from '@sh20raj/sheet-flow/testing';\n\ndescribe('User API', () =\u003e {\n  let client;\n\n  beforeEach(() =\u003e {\n    client = createTestClient();\n  });\n\n  it('should create a user', async () =\u003e {\n    const user = await client.Users.create({\n      name: 'Test User',\n      email: 'test@example.com',\n    });\n    expect(user.id).toBeDefined();\n  });\n});\n```\n\n## 📝 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙋‍♂️ Support\n\n- 📚 [Documentation](https://sheet-flow.docs.com)\n- 💬 [Discord Community](https://discord.gg/sheet-flow)\n- 🐛 [Issue Tracker](https://github.com/username/sheet-flow/issues)\n- 📧 [Email Support](mailto:support@sheet-flow.com)\n\n---\n\n\u003cdiv align=\"center\"\u003e\nMade with ❤️ by the Sheet-Flow Team\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsh20raj%2Fsheetflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsh20raj%2Fsheetflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsh20raj%2Fsheetflow/lists"}