{"_id":"@dasheck0/supabase-saas-domain","_rev":"5-a858d0605182b29e9cad2eac739c73c3","name":"@dasheck0/supabase-saas-domain","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.0":{"name":"@dasheck0/supabase-saas-domain","version":"1.0.0","keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"author":{"name":"dasheck0"},"license":"MIT","_id":"@dasheck0/supabase-saas-domain@1.0.0","maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"bin":{"supabase-saas-setup":"dist/setup/cli.js"},"dist":{"shasum":"39591979a65c9280ca6fe6010b5c864b1a0ca54d","tarball":"https://registry.npmjs.org/@dasheck0/supabase-saas-domain/-/supabase-saas-domain-1.0.0.tgz","fileCount":120,"integrity":"sha512-6RSN5IST+SxayS6g6KC2CAg2VThra8t5uLMWCvIOxyLFYOBsWHs27MPcEw0RPfnTwgeCrHMCSDPBYSKJay8tBw==","signatures":[{"sig":"MEQCIFozbuI69U0fIN8Zp96joRHjgyRybcCmMJdBt06cWS7bAiBSjhQakGrzJWanse/aXzZnfMb5sho4LLctztlkTLNeAA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":250111},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","engines":{"npm":">=10.0.0","node":">=20.0.0"},"gitHead":"d90b482a726c6593e41053fafd7484f9e5f0ca28","scripts":{"dev":"tsc --watch","lint":"eslint src/**/*.ts","test":"jest --passWithNoTests","build":"npm run build:cjs && npm run build:esm && npm run build:types && npm run postbuild","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\"","verify":"./scripts/pre-publish.sh","lint:fix":"eslint src/**/*.ts --fix","prebuild":"npm run clean","build:cjs":"tsc --project tsconfig.json","build:esm":"tsc --project tsconfig.esm.json","postbuild":"chmod +x dist/setup/cli.js","test:watch":"jest --watch","build:types":"tsc --project tsconfig.types.json","postversion":"git push && git push --tags","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"dasheck0","email":"stefan@rpdev.net"},"repository":{"url":"git+https://github.com/dasheck0/supabase-saas-domain.git","type":"git"},"_npmVersion":"10.8.2","description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","directories":{},"_nodeVersion":"20.19.5","dependencies":{"commander":"^14.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","react":"^18.2.0","eslint":"^8.54.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","zustand":"^4.4.7","lefthook":"^2.0.2","prettier":"^3.1.0","typescript":"^5.3.2","@types/jest":"^29.5.8","@types/node":"^20.10.0","@types/react":"^18.2.37","@commitlint/cli":"^20.1.0","@supabase/supabase-js":"^2.38.4","@tanstack/react-query":"^5.59.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.1","@typescript-eslint/parser":"^6.13.1","@commitlint/config-conventional":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.13.1","@tanstack/query-persist-client-core":"^5.59.0","@tanstack/query-sync-storage-persister":"^5.59.0"},"peerDependencies":{"react":"^18.0.0","zustand":"^4.0.0","@supabase/supabase-js":"^2.0.0","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/supabase-saas-domain_1.0.0_1762782660871_0.5180866698668753","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@dasheck0/supabase-saas-domain","version":"1.0.1","keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"author":{"name":"dasheck0"},"license":"MIT","_id":"@dasheck0/supabase-saas-domain@1.0.1","maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"bin":{"supabase-saas-setup":"dist/setup/cli.js"},"dist":{"shasum":"60a6774a7850684558368e79ab961bc4b9164dfc","tarball":"https://registry.npmjs.org/@dasheck0/supabase-saas-domain/-/supabase-saas-domain-1.0.1.tgz","fileCount":120,"integrity":"sha512-bwDo1q5ZnMgf95UoezyQf+jf7cF5WleUOJfYnof9Z4Rdq2wNWHOqDGEoLbwN8FIw3u0OkmejrjPdSgSehpA/qw==","signatures":[{"sig":"MEYCIQCXVC/demt2Kdv6UKECdHHWyiycLBxyDkNxMJ+T0/sZrAIhAONIFF1zfkjk95dLbc14YUw8ro0du8/Kc2Av4UcauwF9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249569},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","engines":{"npm":">=10.0.0","node":">=20.0.0"},"gitHead":"3c3eabcbb3d25d2444434cb475cc80cb9520fe6b","scripts":{"dev":"tsc --watch","lint":"eslint src/**/*.ts","test":"jest --passWithNoTests","build":"npm run build:cjs && npm run build:esm && npm run build:types && npm run postbuild","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\"","verify":"./scripts/pre-publish.sh","lint:fix":"eslint src/**/*.ts --fix","prebuild":"npm run clean","build:cjs":"tsc --project tsconfig.json","build:esm":"tsc --project tsconfig.esm.json","postbuild":"chmod +x dist/setup/cli.js","test:watch":"jest --watch","build:types":"tsc --project tsconfig.types.json","postversion":"git push && git push --tags","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"dasheck0","email":"stefan@rpdev.net"},"repository":{"url":"git+https://github.com/dasheck0/supabase-saas-domain.git","type":"git"},"_npmVersion":"10.8.2","description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","directories":{},"_nodeVersion":"20.19.5","dependencies":{"commander":"^14.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","react":"^18.2.0","eslint":"^8.54.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","zustand":"^4.4.7","lefthook":"^2.0.2","prettier":"^3.1.0","typescript":"^5.3.2","@types/jest":"^29.5.8","@types/node":"^20.10.0","@types/react":"^18.2.37","@commitlint/cli":"^20.1.0","@supabase/supabase-js":"^2.38.4","@tanstack/react-query":"^5.59.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.1","@typescript-eslint/parser":"^6.13.1","@commitlint/config-conventional":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.13.1","@tanstack/query-persist-client-core":"^5.59.0","@tanstack/query-sync-storage-persister":"^5.59.0"},"peerDependencies":{"react":"^18.0.0","zustand":"^4.0.0","@supabase/supabase-js":"^2.0.0","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/supabase-saas-domain_1.0.1_1762889483967_0.6481897381462771","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@dasheck0/supabase-saas-domain","version":"1.0.2","keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"author":{"name":"dasheck0"},"license":"MIT","_id":"@dasheck0/supabase-saas-domain@1.0.2","maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"bin":{"supabase-saas-setup":"dist/setup/cli.js"},"dist":{"shasum":"91b291d6955ff9eb46f413bb6c807470d533af90","tarball":"https://registry.npmjs.org/@dasheck0/supabase-saas-domain/-/supabase-saas-domain-1.0.2.tgz","fileCount":120,"integrity":"sha512-MvN5LtFQiqPo5Qk2NQ1fp1rOPHfEmEGMT2lmd65EPBJR40/SBafblqrGPRL/cRPNZUFLKon7Pc9zTkGrL+t/2w==","signatures":[{"sig":"MEUCIAfdVLhL07VYQ/ZbbfQu2P/rLPCC0ldHxstL7AFyLLHyAiEAnhoO7n6B8JZ95bUAWZMnssqZVHScOJlHrggZlHClqxY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249569},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.esm.js","engines":{"npm":">=10.0.0","node":">=20.0.0"},"gitHead":"ada378af27e2a765ba5cfa8545cbdb2dcef9af15","scripts":{"dev":"tsc --watch","lint":"eslint src/**/*.ts","test":"jest --passWithNoTests","build":"npm run build:cjs && npm run build:esm && npm run build:types && npm run postbuild","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\"","verify":"./scripts/pre-publish.sh","lint:fix":"eslint src/**/*.ts --fix","prebuild":"npm run clean","build:cjs":"tsc --project tsconfig.json","build:esm":"tsc --project tsconfig.esm.json","postbuild":"chmod +x dist/setup/cli.js","test:watch":"jest --watch","build:types":"tsc --project tsconfig.types.json","postversion":"git push && git push --tags","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"dasheck0","email":"stefan@rpdev.net"},"repository":{"url":"git+https://github.com/dasheck0/supabase-saas-domain.git","type":"git"},"_npmVersion":"10.8.2","description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","directories":{},"_nodeVersion":"20.19.5","dependencies":{"commander":"^14.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","react":"^18.2.0","eslint":"^8.54.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","zustand":"^4.4.7","lefthook":"^2.0.2","prettier":"^3.1.0","typescript":"^5.3.2","@types/jest":"^29.5.8","@types/node":"^20.10.0","@types/react":"^18.2.37","@commitlint/cli":"^20.1.0","@supabase/supabase-js":"^2.38.4","@tanstack/react-query":"^5.59.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.1","@typescript-eslint/parser":"^6.13.1","@commitlint/config-conventional":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.13.1","@tanstack/query-persist-client-core":"^5.59.0","@tanstack/query-sync-storage-persister":"^5.59.0"},"peerDependencies":{"react":"^18.0.0","zustand":"^4.0.0","@supabase/supabase-js":"^2.0.0","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/supabase-saas-domain_1.0.2_1762889505551_0.45348800668379985","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@dasheck0/supabase-saas-domain","version":"1.0.3","keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"author":{"name":"dasheck0"},"license":"MIT","_id":"@dasheck0/supabase-saas-domain@1.0.3","maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"bin":{"supabase-saas-setup":"dist/setup/cli.js"},"dist":{"shasum":"c4436e53eec79238446f29bca96a6a5dcddc81ee","tarball":"https://registry.npmjs.org/@dasheck0/supabase-saas-domain/-/supabase-saas-domain-1.0.3.tgz","fileCount":121,"integrity":"sha512-hfM19eQdxAsqx7zvQQbb3stdj2aK/PdAm3TIkckR+6IZH2itqyhIHJY6IFX2D8QVCMK5QxvgycpYgMuAw7zPJA==","signatures":[{"sig":"MEQCIHZj8u7bXLxSIf0WE/BBLzgU5ObJOw37LetYh/FXcHqpAiAnuVUvTyNRJp3ikFK9hM1QaaqhubGUFioPI97hhn4fxw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":267970},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.js","engines":{"npm":">=10.0.0","node":">=20.0.0"},"gitHead":"5a94520046a319484ba66c87a00da45648367753","scripts":{"dev":"tsc --watch","lint":"eslint src/**/*.ts","test":"jest --passWithNoTests","build":"npm run build:cjs && npm run build:esm && npm run build:types && npm run postbuild","clean":"rimraf dist","format":"prettier --write \"src/**/*.ts\"","verify":"./scripts/pre-publish.sh","lint:fix":"eslint src/**/*.ts --fix","prebuild":"npm run clean","build:cjs":"tsc --project tsconfig.json","build:esm":"tsc --project tsconfig.esm.json","postbuild":"chmod +x dist/setup/cli.js","test:local":"node scripts/test-local.js","test:watch":"jest --watch","build:types":"tsc --project tsconfig.types.json","postversion":"git push && git push --tags","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"dasheck0","email":"stefan@rpdev.net"},"repository":{"url":"git+https://github.com/dasheck0/supabase-saas-domain.git","type":"git"},"_npmVersion":"10.8.2","description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","directories":{},"_nodeVersion":"20.19.5","dependencies":{"commander":"^14.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","react":"^18.2.0","eslint":"^8.54.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","zustand":"^4.4.7","lefthook":"^2.0.2","prettier":"^3.1.0","typescript":"^5.3.2","@types/jest":"^29.5.8","@types/node":"^20.10.0","@types/react":"^18.2.37","@commitlint/cli":"^20.1.0","@supabase/supabase-js":"^2.38.4","@tanstack/react-query":"^5.59.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.1","@typescript-eslint/parser":"^6.13.1","@commitlint/config-conventional":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.13.1","@tanstack/query-persist-client-core":"^5.59.0","@tanstack/query-sync-storage-persister":"^5.59.0"},"peerDependencies":{"react":"^18.0.0","zustand":"^4.0.0","@supabase/supabase-js":"^2.0.0","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/supabase-saas-domain_1.0.3_1762898484746_0.3382808351896045","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@dasheck0/supabase-saas-domain","version":"1.0.4","description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","bin":{"supabase-saas-setup":"dist/setup/cli.js"},"scripts":{"build":"npm run build:cjs && npm run build:esm && npm run build:types && npm run postbuild","build:cjs":"tsc --project tsconfig.json","build:esm":"tsc --project tsconfig.esm.json","build:types":"tsc --project tsconfig.types.json","postbuild":"chmod +x dist/setup/cli.js","dev":"tsc --watch","clean":"rimraf dist","prebuild":"npm run clean","test":"jest --passWithNoTests","test:watch":"jest --watch","test:coverage":"jest --coverage","test:local":"node scripts/test-local.js","lint":"eslint src/**/*.ts","lint:fix":"eslint src/**/*.ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","prepublishOnly":"npm run build","postversion":"git push && git push --tags","verify":"./scripts/pre-publish.sh"},"keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"author":{"name":"dasheck0"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/dasheck0/supabase-saas-domain.git"},"homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"devDependencies":{"@commitlint/cli":"^20.1.0","@commitlint/config-conventional":"^20.0.0","@supabase/supabase-js":"^2.38.4","@tanstack/query-persist-client-core":"^5.59.0","@tanstack/query-sync-storage-persister":"^5.59.0","@tanstack/react-query":"^5.59.0","@types/jest":"^29.5.8","@types/node":"^20.10.0","@types/react":"^18.2.37","@typescript-eslint/eslint-plugin":"^6.13.1","@typescript-eslint/parser":"^6.13.1","eslint":"^8.54.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.1","jest":"^29.7.0","lefthook":"^2.0.2","prettier":"^3.1.0","react":"^18.2.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","typescript":"^5.3.2","zustand":"^4.4.7"},"peerDependencies":{"@supabase/supabase-js":"^2.0.0","@tanstack/react-query":"^5.0.0","react":"^18.0.0","zustand":"^4.0.0"},"engines":{"node":">=20.0.0","npm":">=10.0.0"},"publishConfig":{"access":"public"},"dependencies":{"commander":"^14.0.2"},"_id":"@dasheck0/supabase-saas-domain@1.0.4","gitHead":"68158a06b1fd317a07b216b99c590a08e2201fb3","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-kNen7sIUXdEGeonc49+g0g9dFEXujuLPIpy7IhNhd1j79rmJUp6i6dCnzsaM0jQR386Aa/lCc6C39rvf4LVHPw==","shasum":"f213dfd07c19f3ebc926eaf7b93cd99ed52d924d","tarball":"https://registry.npmjs.org/@dasheck0/supabase-saas-domain/-/supabase-saas-domain-1.0.4.tgz","fileCount":121,"unpackedSize":267971,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHZ070ckEkBDSpf/4Xxyo1A8fLYV/2iIo1u9ps1d7tFnAiEAoHE22yTkfSxOPJWeBxj2nfg6OWCgrZJ83to7yxswd2E="}]},"_npmUser":{"name":"dasheck0","email":"stefan@rpdev.net"},"directories":{},"maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/supabase-saas-domain_1.0.4_1762950589349_0.449466696247639"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-10T13:51:00.666Z","modified":"2025-11-12T12:29:49.714Z","1.0.0":"2025-11-10T13:51:01.067Z","1.0.1":"2025-11-11T19:31:24.167Z","1.0.2":"2025-11-11T19:31:45.764Z","1.0.3":"2025-11-11T22:01:24.991Z","1.0.4":"2025-11-12T12:29:49.538Z"},"bugs":{"url":"https://github.com/dasheck0/supabase-saas-domain/issues"},"author":{"name":"dasheck0"},"license":"MIT","homepage":"https://github.com/dasheck0/supabase-saas-domain#readme","keywords":["supabase","saas","multi-tenant","typescript","react-query","zustand","rls","tenant-isolation","database-setup","authentication","framework","opinionated"],"repository":{"type":"git","url":"git+https://github.com/dasheck0/supabase-saas-domain.git"},"description":"Opinionated TypeScript framework for building multi-tenant SaaS applications with Supabase. Includes database setup, React Query integration, Zustand state management, and complete tenant isolation.","maintainers":[{"name":"dasheck0","email":"stefan@rpdev.net"}],"readme":"# @dasheck0/supabase-saas-domain\n\nAn **opinionated** TypeScript framework for building multi-tenant SaaS applications with Supabase. This package provides a complete domain layer with authentication, tenant management, profile handling, storage, and row-level security (RLS) patterns.\n\n## 🌟 Philosophy\n\nThis is an **opinionated framework** that makes specific architectural decisions for you:\n\n- **Multi-tenant by design**: Every data operation is tenant-scoped\n- **RLS-first security**: Database-level security with proper tenant isolation\n- **React Query integration**: Optimistic updates, caching, and synchronization\n- **Zustand state management**: Minimal, persistent client state\n- **TypeScript-native**: Full type safety across the stack\n\n## 🚀 Quick Start\n\n### Installation\n\n**Requirements:**\n- Node.js >=20.0.0\n- npm >=10.0.0\n\n```bash\nnpm install @dasheck0/supabase-saas-domain @tanstack/react-query zustand\n```\n\n### Database Setup\n\nThe framework requires a specific database schema with multi-tenant support, RLS policies, and storage configuration. You have several options to set this up:\n\n#### Option 1: CLI Tool (Recommended)\n\n```bash\n# Install the package\nnpm install @dasheck0/supabase-saas-domain\n\n# Run the setup with your Supabase credentials\nnpx supabase-saas-setup run --url YOUR_SUPABASE_URL --key YOUR_SERVICE_ROLE_KEY --verbose\n\n# Or use environment variables\nexport SUPABASE_URL=your_supabase_url\nexport SUPABASE_SERVICE_ROLE_KEY=your_service_role_key\nnpx supabase-saas-setup quick\n```\n\n#### Option 2: Programmatic Setup\n\n```javascript\nconst { setupSaasDatabase } = require('@dasheck0/supabase-saas-domain');\nconst { createClient } = require('@supabase/supabase-js');\n\nconst supabaseClient = createClient(\n  'your-supabase-url',\n  'your-service-role-key',\n  { auth: { autoRefreshToken: false, persistSession: false } }\n);\n\nconst result = await setupSaasDatabase({\n  supabaseClient,\n  verbose: true\n});\n\nif (result.success) {\n  console.log('✅ Database setup complete!');\n} else {\n  console.error('❌ Setup failed:', result.errors);\n}\n```\n\n#### Option 3: Manual Migration\n\n1. Copy all migration files from `/supabase/migrations/` in the package\n2. Apply them to your Supabase project using the Supabase CLI or Dashboard\n3. Create a storage bucket named 'uploads' with public access\n\n#### What Gets Created\n\n- **Tables**: `profiles`, `tenants`, `tenant_memberships` with proper relationships\n- **RLS Policies**: Tenant-scoped security for all data operations  \n- **Storage Bucket**: 'uploads' bucket with RLS policies for file management\n- **Database Functions**: Utility functions for tenant management and SQL execution\n- **Triggers**: Automatic profile and tenant creation on user signup\n- **Migration Tracking**: `schema_migrations` table to prevent duplicate setups\n\n> **Note**: The setup tool uses embedded SQL migrations (not file-based) making the package completely self-contained. This means you don't need to manually copy migration files - everything is bundled with the npm package.\n\n### Basic Setup\n\n```typescript\nimport { SaasProvider } from '@dasheck0/supabase-saas-domain';\nimport { createClient } from '@supabase/supabase-js';\n\nconst supabaseClient = createClient(\n  'your-supabase-url',\n  'your-supabase-anon-key'\n);\n\nfunction App() {\n  return (\n    <SaasProvider supabaseClient={supabaseClient}>\n      <YourApp />\n    </SaasProvider>\n  );\n}\n```\n\n### Authentication Sync\n\nThe framework requires you to sync authentication state:\n\n```typescript\nimport { useSaasUtils } from '@dasheck0/supabase-saas-domain';\n\nfunction AuthSync({ user }: { user: any }) {\n  const { setAuthentication, getUserId } = useSaasUtils();\n\n  useEffect(() => {\n    const currentUserId = getUserId();\n    const newUserId = user?.id || null;\n    \n    if (currentUserId !== newUserId) {\n      if (newUserId) {\n        setAuthentication(newUserId, null);\n      } else {\n        setAuthentication(null, null);\n      }\n    }\n  }, [user?.id, setAuthentication, getUserId]);\n\n  return null;\n}\n```\n\n## 🏗 Core Concepts\n\n### 1. Multi-Tenant Architecture\n\nThe framework enforces a **tenant-first** approach:\n\n```typescript\nimport { useSaasTenantHooks, useTenantSwitcher } from '@dasheck0/supabase-saas-domain';\n\nfunction TenantManager() {\n  const { useTenants, useCreateTenant } = useSaasTenantHooks();\n  const { currentTenant, switchTenant } = useTenantSwitcher();\n  \n  const { data: tenants } = useTenants();\n  const createTenant = useCreateTenant();\n\n  const handleCreateTenant = async () => {\n    const newTenant = await createTenant.mutateAsync({\n      name: 'My Company',\n      description: 'Company workspace'\n    });\n    switchTenant(newTenant);\n  };\n\n  return (\n    <div>\n      <h2>Current: {currentTenant?.name}</h2>\n      {tenants?.map(tenant => (\n        <button key={tenant.id} onClick={() => switchTenant(tenant)}>\n          {tenant.name}\n        </button>\n      ))}\n    </div>\n  );\n}\n```\n\n### 2. Profile Management\n\nUser profiles with tenant-scoped visibility:\n\n```typescript\nimport { useSaasProfileHooks } from '@dasheck0/supabase-saas-domain';\n\nfunction ProfileManager() {\n  const { useProfiles, useCreateProfile, useUpdateProfile } = useSaasProfileHooks();\n  \n  const { data: profiles } = useProfiles(); // Only profiles visible to current user\n  const createProfile = useCreateProfile();\n  const updateProfile = useUpdateProfile();\n\n  return (\n    <div>\n      {profiles?.map(profile => (\n        <div key={profile.id}>\n          {profile.firstName} {profile.lastName}\n          <img src={profile.imageUrl} alt=\"Avatar\" />\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n### 3. Storage with Tenant Isolation\n\nBuilt-in file storage with automatic tenant scoping:\n\n```typescript\nimport { useSaasStorageHooks, ImageUpload } from '@dasheck0/supabase-saas-domain';\n\nfunction AvatarUpload({ userId }: { userId: string }) {\n  const { useUploadAvatar } = useSaasStorageHooks();\n  const { currentTenant } = useTenantSwitcher();\n  const uploadAvatar = useUploadAvatar();\n\n  const handleUpload = async (file: File) => {\n    if (currentTenant) {\n      const result = await uploadAvatar.mutateAsync({\n        userId,\n        tenantId: currentTenant.id,\n        file\n      });\n      console.log('Uploaded:', result.signedUrl);\n    }\n  };\n\n  return (\n    <ImageUpload\n      onImageSelected={handleUpload}\n      placeholder=\"Upload avatar\"\n    />\n  );\n}\n```\n\n### 4. Membership Management\n\nHandle tenant memberships with role-based access:\n\n```typescript\nimport { useSaasMembershipHooks } from '@dasheck0/supabase-saas-domain';\n\nfunction MembershipManager({ tenantId }: { tenantId: string }) {\n  const { useTenantMemberships, useCreateTenantMembership } = useSaasMembershipHooks();\n  \n  const { data: memberships } = useTenantMemberships(tenantId, true); // eager load profiles\n  const createMembership = useCreateTenantMembership();\n\n  const inviteUser = async (email: string) => {\n    await createMembership.mutateAsync({\n      tenantId,\n      userId: email, // In real app, resolve email to userId\n      role: 'member'\n    });\n  };\n\n  return (\n    <div>\n      <h3>Team Members</h3>\n      {memberships?.map(membership => (\n        <div key={membership.id}>\n          {membership.profile?.firstName} - {membership.role}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n## 🛠 Core Hooks API\n\n### Tenant Hooks\n- `useTenants()` - List accessible tenants\n- `useCreateTenant()` - Create new tenant\n- `useUpdateTenant()` - Update tenant details\n- `useDeleteTenant()` - Delete tenant\n- `useTenantSwitcher()` - Switch between tenants\n\n### Profile Hooks  \n- `useProfiles()` - List visible profiles\n- `useCreateProfile()` - Create user profile\n- `useUpdateProfile()` - Update profile\n- `useDeleteProfile()` - Delete profile\n\n### Membership Hooks\n- `useTenantMemberships(tenantId)` - List tenant members\n- `useUserMemberships(userId)` - List user's memberships\n- `useCreateTenantMembership()` - Add member to tenant\n- `useUpdateTenantMembership()` - Update member role\n- `useDeleteTenantMembership()` - Remove member\n\n### Storage Hooks\n- `useUploadAvatar()` - Upload profile pictures\n- `useUploadTenantImage()` - Upload tenant logos\n- `useSignedUrl()` - Get signed URLs for files\n- `useDeleteFile()` - Delete stored files\n\n### Utility Hooks\n- `useAuthState()` - Current authentication state\n- `useSaasUtils()` - Framework utilities\n\n## 🔒 Security Model\n\n### Row-Level Security (RLS)\n\nThe framework enforces security at the database level:\n\n```sql\n-- Users can only see profiles of people in their shared tenants\nCREATE POLICY \"profiles_shared_tenants\" ON public.profiles\n  FOR SELECT USING (\n    EXISTS (\n      SELECT 1 FROM public.tenant_memberships tm1\n      JOIN public.tenant_memberships tm2 ON tm1.tenant_id = tm2.tenant_id\n      WHERE tm1.user_id = auth.uid()\n      AND tm2.user_id = profiles.user_id\n    )\n  );\n```\n\n### Tenant Isolation\n\nAll data operations are automatically scoped to accessible tenants:\n\n- **Storage**: Files uploaded to `{tenantId}/category/{userId}/filename`\n- **Queries**: Filtered by tenant membership  \n- **Mutations**: Validated against tenant permissions\n\n## 📁 Database Schema\n\nThe framework expects these core tables:\n\n```sql\n-- Core Tables\nprofiles (id, user_id, first_name, last_name, image_url, ...)\ntenants (id, name, description, image_url, personal, ...)  \ntenant_memberships (id, tenant_id, user_id, role, ...)\n\n-- Storage Bucket\nuploads (tenant-scoped file storage)\n```\n\n## 🎨 UI Components\n\n### ImageUpload Component\n\n```typescript\nimport { ImageUpload } from '@dasheck0/supabase-saas-domain';\n\n<ImageUpload\n  currentImageUrl={profile.imageUrl}\n  onImageSelected={(file) => handleUpload(file)}\n  onImageCleared={() => setImageUrl('')}\n  placeholder=\"Upload profile picture\"\n/>\n```\n\n### Built-in Components\n- `ImageUpload` - Drag & drop file upload with preview\n- `SaasProvider` - Framework provider component\n\n## ⚙️ Configuration\n\n### Required Props\n\n```typescript\ninterface SaasProviderProps {\n  supabaseClient: SupabaseClient; // Your Supabase client instance\n  children: React.ReactNode;\n}\n```\n\n### Environment Setup\n\n1. **Supabase Project**: Set up with authentication enabled\n2. **Database Migrations**: Run provided migrations for schema\n3. **RLS Policies**: Apply security policies for tenant isolation  \n4. **Storage Bucket**: Create 'uploads' bucket for file storage\n5. **Authentication**: Configure Supabase Auth providers\n\n## � Troubleshooting\n\n### Setup Issues\n\n#### \"Cannot find module 'commander'\" during CLI setup\n```bash\n# Install dependencies if using the CLI directly\nnpm install -g @dasheck0/supabase-saas-domain\n```\n\n#### \"SQL execution failed\" during migration\n- Ensure you're using the **service role key** (not anon key)\n- Check that your Supabase project has the necessary permissions\n- Verify your Supabase URL is correct\n\n#### \"Multiple GoTrueClient instances detected\"\n- The framework uses `peerDependencies` to avoid this\n- Ensure you're passing your app's Supabase client to `SaasProvider`\n- Don't create multiple Supabase clients in your app\n\n#### \"userId is null\" in hooks\n- Make sure you're using the `AuthSync` component\n- Verify that authentication state is being set properly\n- Check that your user is actually authenticated\n\n### RLS Policy Issues\n\n#### \"new row violates row-level security policy\"\n- Ensure the user has a profile record (auto-created on signup)\n- Verify the user is a member of the tenant they're trying to access\n- Check that tenant memberships are properly configured\n\n#### Storage upload failures\n- Confirm the 'uploads' bucket exists and has proper RLS policies\n- Verify the user is authenticated and has tenant membership\n- Check file size limits and allowed file types\n\n### Performance Tips\n\n- Use the `enabled` option in hooks to prevent unnecessary queries\n- Implement proper loading states for better UX\n- Consider pagination for large datasets\n- Use optimistic updates for better perceived performance\n\n## �🚀 Development\n\n### Package Development\n```bash\nnpm install\nnpm run build        # Build TypeScript\nnpm run dev          # Watch mode\nnpm run test         # Run tests\n```\n\n### Example App\n```bash\ncd examples/react-admin\nnpm install\nnpm run dev          # Start example app\n```\n\n## 📦 Package Structure\n\n```\nsrc/\n├── api/              # Data layer (Supabase queries)\n├── components/       # React components  \n├── hooks/            # React Query hooks\n├── models/           # TypeScript models\n├── stores/           # Zustand stores\n├── types/            # Type definitions\n└── index.ts          # Main exports\n\nexamples/\n└── react-admin/      # Full example application\n\nsupabase/\n└── migrations/       # Database migrations\n```\n\n## 🤝 Contributing\n\nThis is an opinionated framework with specific architectural decisions. Contributions should align with:\n\n- Multi-tenant architecture patterns\n- RLS-first security model  \n- React Query + Zustand state management\n- TypeScript-first development\n\n## 📄 License\n\nMIT © dasheck0\n\n---\n\n**Note**: This is an opinionated framework that makes architectural decisions for you. It's designed for teams building multi-tenant SaaS applications who want a complete, secure foundation without reinventing tenant isolation, security patterns, and data management.","readmeFilename":"README.md"}