{"_id":"@abdokouta/react-multitenancy","name":"@abdokouta/react-multitenancy","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@abdokouta/react-multitenancy","version":"1.0.0","description":"Multi-tenancy support for Refine with dynamic domain resolution","keywords":["refine","multi-tenancy","multitenancy","saas","tenant","domain","subdomain"],"repository":{"type":"git","url":"git+https://github.com/refinedev/refine.git","directory":"packages/multitenancy"},"license":"MIT","author":{"name":"Refine"},"main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest --run","test:watch":"vitest","test:coverage":"vitest --run --coverage","test:ui":"vitest --ui","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\""},"dependencies":{"@abdokouta/react-cache":"^1.0","@abdokouta/react-di":"^2.0","@refinedev/core":"^5.0.11"},"peerDependencies":{"@heroui/react":"^3.0.0","@refinedev/core":"^5.0.0","react":"^18.0.0","react-dom":"^18.0.0"},"peerDependenciesMeta":{"@heroui/react":{"optional":true}},"devDependencies":{"@heroui/react":"^3.0.1","@nesvel/eslint-config":"^1.0.5","@nesvel/prettier-config":"^1.0.3","@nesvel/tsup-config":"^1.0.3","@nesvel/typescript-config":"^1.0.4","@testing-library/jest-dom":"^6.9.1","@testing-library/react":"^16.3.2","@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@vitest/ui":"^4.1.2","jsdom":"^29.0.1","prettier":"^3.8.1","react":"^19.2.4","react-dom":"^19.2.4","tsup":"^8.5.1","typescript":"^6.0.2","vitest":"^4.1.2"},"publishConfig":{"access":"public"},"_id":"@abdokouta/react-multitenancy@1.0.0","gitHead":"84f03582f76c98ff36dacbe9f7473d84c9860824","bugs":{"url":"https://github.com/refinedev/refine/issues"},"homepage":"https://github.com/refinedev/refine#readme","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-kZvGgqFEnM2mVLUTpqgYjedNm9xT84bPMfMRMA4BC+OdU4X+zVqD8zcKDeaHqsdvMsvUrGEnaK364G2ACBmf3Q==","shasum":"72878f8cd1aa99a6b28548bf7b55cdf562e1992f","tarball":"https://registry.npmjs.org/@abdokouta/react-multitenancy/-/react-multitenancy-1.0.0.tgz","fileCount":80,"unpackedSize":800015,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDwUCAko/ofXTJPI0UiGCOjTDBQOoOOj7fy4WISpMuVwQIgVSTVbT8Ad0NfdLhNV6T2V6/eM5/52Wtnr5famPpMS+Q="}]},"_npmUser":{"name":"abdokouta","email":"akouta66@gmail.com"},"directories":{},"maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-multitenancy_1.0.0_1775087290505_0.12149517113803165"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-01T23:48:10.423Z","1.0.0":"2026-04-01T23:48:10.702Z","modified":"2026-04-01T23:48:10.895Z"},"maintainers":[{"name":"abdokouta","email":"akouta66@gmail.com"}],"description":"Multi-tenancy support for Refine with dynamic domain resolution","homepage":"https://github.com/refinedev/refine#readme","keywords":["refine","multi-tenancy","multitenancy","saas","tenant","domain","subdomain"],"repository":{"type":"git","url":"git+https://github.com/refinedev/refine.git","directory":"packages/multitenancy"},"author":{"name":"Refine"},"bugs":{"url":"https://github.com/refinedev/refine/issues"},"license":"MIT","readme":"# Multi-Tenancy Configuration\n\nConfiguration utilities and presets for `@pixielity/multitenancy` package.\n\n## Structure\n\n```\nconfig/\n├── index.ts              # Main exports\n├── utils.ts              # defineConfig helper\n├── presets/\n│   ├── default.preset.ts # Default configuration\n│   ├── header.preset.ts  # Header-based configuration\n│   ├── subdomain.preset.ts # Subdomain-based configuration\n│   └── domain.preset.ts  # Domain-based configuration\n└── README.md\n```\n\n## Usage\n\n### Basic Usage\n\n```typescript\nimport { defineConfig, subdomainPreset } from \"@pixielity/multitenancy/config\";\n\nconst config = defineConfig({\n  ...subdomainPreset,\n  baseDomain: \"myapp.com\",\n  fetchTenants: async () => {\n    const response = await fetch(\"/api/tenants\");\n    return await response.json();\n  }\n});\n```\n\n### Without Preset\n\n```typescript\nimport { defineConfig, TenantMode } from \"@pixielity/multitenancy/config\";\n\nconst config = defineConfig({\n  mode: TenantMode.HEADER,\n  resolvers: [\"subdomain\", \"router\"],\n  baseDomain: \"myapp.com\",\n  headerName: \"X-Tenant-ID\",\n  fetchTenants: async () => {\n    const response = await fetch(\"/api/tenants\");\n    return await response.json();\n  }\n});\n```\n\n## Available Presets\n\n### defaultPreset\nSimple filter-based with router resolver:\n```typescript\n{\n  mode: TenantMode.FILTER,\n  tenantField: \"tenant_id\",\n  headerName: \"X-Tenant-ID\",\n  queryParam: \"tenant_id\",\n  resolvers: [\"router\"]\n}\n```\n\n### headerPreset\nHeader-based tenant identification:\n```typescript\n{\n  mode: TenantMode.HEADER,\n  tenantField: \"tenant_id\",\n  headerName: \"X-Tenant-ID\",\n  queryParam: \"tenant_id\",\n  resolvers: [\"header\", \"router\"]\n}\n```\n\n### subdomainPreset\nSubdomain-based SaaS:\n```typescript\n{\n  mode: TenantMode.HEADER,\n  headerName: \"X-Tenant-ID\",\n  resolvers: [\"subdomain\", \"router\"],\n  baseDomain: \"example.com\"\n}\n```\n\n### domainPreset\nCustom domains with dynamic resolution:\n```typescript\n{\n  mode: TenantMode.HEADER,\n  headerName: \"X-Tenant-ID\",\n  resolvers: [\"dynamic-domain\", \"subdomain\", \"router\"],\n  baseDomain: \"example.com\",\n  dynamicDomainApiUrl: \"/api/tenants/resolve\"\n}\n```\n\n## Configuration Options\n\n### Core Options\n- `mode`: How to pass tenant ID to backend (FILTER, HEADER, URL, QUERY)\n- `resolvers`: Array of resolver names in priority order\n- `fetchTenants`: Function to fetch tenants from your API (required)\n\n### Resolver Configuration\n- `baseDomain`: Base domain for subdomain matching\n- `pathBasedTenants`: Enable path-based tenant resolution\n- `dynamicDomainApiUrl`: API endpoint for dynamic domain resolution\n- `dynamicDomainCacheTTL`: Cache TTL for dynamic domain resolver (ms)\n\n### Defaults\n- `fallback`: Fallback tenant ID\n- `tenantField`: Field name for tenant in filters (default: \"tenant_id\")\n- `headerName`: Header name for HEADER mode (default: \"X-Tenant-ID\")\n- `queryParam`: Query parameter name for QUERY mode (default: \"tenant_id\")\n- `defaultTenant`: Default tenant object\n\n### Feature Flags\n- `logging`: Enable debug logging\n- `throwOnMissingTenant`: Throw error when tenant resolution fails\n- `disableAutoInjection`: Disable automatic tenant context injection\n\n## Dynamic Tenant Resolution\n\nAll tenant data comes from your API dynamically. There are no static mappings.\n\n### Fetching Tenants\n```typescript\nfetchTenants: async () => {\n  const response = await fetch(\"/api/tenants\");\n  return await response.json();\n}\n```\n\n### Dynamic Domain Resolution\n```typescript\n{\n  resolvers: [\"dynamic-domain\"],\n  dynamicDomainApiUrl: \"/api/tenants/resolve\",\n  dynamicDomainCacheTTL: 600000 // 10 minutes\n}\n```\n\n## TypeScript Support\n\nFull TypeScript support with comprehensive type definitions:\n\n```typescript\nimport type { MultiTenancyOptions } from \"@pixielity/multitenancy/config\";\n\nconst config: Partial<MultiTenancyOptions> = {\n  mode: TenantMode.HEADER,\n  resolvers: [\"subdomain\", \"router\"],\n  baseDomain: \"myapp.com\",\n  fetchTenants: async () => {\n    const response = await fetch(\"/api/tenants\");\n    return await response.json();\n  }\n};\n```\n","readmeFilename":"README.md","_rev":"1-57860c6b11848890f43bb415b073b22d"}