@plyaz/db 0.0.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.
Files changed (118) hide show
  1. package/README.md +169 -0
  2. package/dist/adapters/drizzle/DrizzleAdapter.d.ts +269 -0
  3. package/dist/adapters/drizzle/DrizzleAdapter.d.ts.map +1 -0
  4. package/dist/adapters/index.d.ts +20 -0
  5. package/dist/adapters/index.d.ts.map +1 -0
  6. package/dist/adapters/sql/SQLAdapter.d.ts +282 -0
  7. package/dist/adapters/sql/SQLAdapter.d.ts.map +1 -0
  8. package/dist/adapters/supabase/SupabaseAdapter.d.ts +305 -0
  9. package/dist/adapters/supabase/SupabaseAdapter.d.ts.map +1 -0
  10. package/dist/advanced/backup/BackupService.d.ts +159 -0
  11. package/dist/advanced/backup/BackupService.d.ts.map +1 -0
  12. package/dist/advanced/backup/index.d.ts +2 -0
  13. package/dist/advanced/backup/index.d.ts.map +1 -0
  14. package/dist/advanced/caching/CacheEvict.decorator.d.ts +3 -0
  15. package/dist/advanced/caching/CacheEvict.decorator.d.ts.map +1 -0
  16. package/dist/advanced/caching/Cacheable.decorator.d.ts +99 -0
  17. package/dist/advanced/caching/Cacheable.decorator.d.ts.map +1 -0
  18. package/dist/advanced/caching/RedisCache.d.ts +417 -0
  19. package/dist/advanced/caching/RedisCache.d.ts.map +1 -0
  20. package/dist/advanced/caching/index.d.ts +4 -0
  21. package/dist/advanced/caching/index.d.ts.map +1 -0
  22. package/dist/advanced/connection-pool/DynamicPool.d.ts +234 -0
  23. package/dist/advanced/connection-pool/DynamicPool.d.ts.map +1 -0
  24. package/dist/advanced/connection-pool/index.d.ts +2 -0
  25. package/dist/advanced/connection-pool/index.d.ts.map +1 -0
  26. package/dist/advanced/index.d.ts +8 -0
  27. package/dist/advanced/index.d.ts.map +1 -0
  28. package/dist/advanced/monitoring/AlertManager.d.ts +72 -0
  29. package/dist/advanced/monitoring/AlertManager.d.ts.map +1 -0
  30. package/dist/advanced/monitoring/MetricsCollector.d.ts +81 -0
  31. package/dist/advanced/monitoring/MetricsCollector.d.ts.map +1 -0
  32. package/dist/advanced/monitoring/index.d.ts +3 -0
  33. package/dist/advanced/monitoring/index.d.ts.map +1 -0
  34. package/dist/advanced/multi-tenancy/TenantContext.d.ts +52 -0
  35. package/dist/advanced/multi-tenancy/TenantContext.d.ts.map +1 -0
  36. package/dist/advanced/multi-tenancy/TenantRepository.d.ts +292 -0
  37. package/dist/advanced/multi-tenancy/TenantRepository.d.ts.map +1 -0
  38. package/dist/advanced/multi-tenancy/index.d.ts +3 -0
  39. package/dist/advanced/multi-tenancy/index.d.ts.map +1 -0
  40. package/dist/advanced/read-replica/ReadReplicaAdapter.d.ts +516 -0
  41. package/dist/advanced/read-replica/ReadReplicaAdapter.d.ts.map +1 -0
  42. package/dist/advanced/read-replica/ReadReplicaManager.d.ts +68 -0
  43. package/dist/advanced/read-replica/ReadReplicaManager.d.ts.map +1 -0
  44. package/dist/advanced/read-replica/UseReplica.decorator.d.ts +24 -0
  45. package/dist/advanced/read-replica/UseReplica.decorator.d.ts.map +1 -0
  46. package/dist/advanced/read-replica/index.d.ts +3 -0
  47. package/dist/advanced/read-replica/index.d.ts.map +1 -0
  48. package/dist/advanced/sharding/ShardKey.d.ts +80 -0
  49. package/dist/advanced/sharding/ShardKey.d.ts.map +1 -0
  50. package/dist/advanced/sharding/ShardRouter.d.ts +66 -0
  51. package/dist/advanced/sharding/ShardRouter.d.ts.map +1 -0
  52. package/dist/advanced/sharding/index.d.ts +3 -0
  53. package/dist/advanced/sharding/index.d.ts.map +1 -0
  54. package/dist/builder/query/index.d.ts +7 -0
  55. package/dist/builder/query/index.d.ts.map +1 -0
  56. package/dist/builder/query/orm.d.ts +22 -0
  57. package/dist/builder/query/orm.d.ts.map +1 -0
  58. package/dist/builder/query/sql.d.ts +29 -0
  59. package/dist/builder/query/sql.d.ts.map +1 -0
  60. package/dist/extensions/AuditExtension.d.ts +468 -0
  61. package/dist/extensions/AuditExtension.d.ts.map +1 -0
  62. package/dist/extensions/CachingAdapter.d.ts +451 -0
  63. package/dist/extensions/CachingAdapter.d.ts.map +1 -0
  64. package/dist/extensions/EncryptionExtension.d.ts +95 -0
  65. package/dist/extensions/EncryptionExtension.d.ts.map +1 -0
  66. package/dist/extensions/ReadReplicaAdapter.d.ts +32 -0
  67. package/dist/extensions/ReadReplicaAdapter.d.ts.map +1 -0
  68. package/dist/extensions/SoftDeleteExtension.d.ts +430 -0
  69. package/dist/extensions/SoftDeleteExtension.d.ts.map +1 -0
  70. package/dist/extensions/index.d.ts +79 -0
  71. package/dist/extensions/index.d.ts.map +1 -0
  72. package/dist/factory/AdapterFactory.d.ts +111 -0
  73. package/dist/factory/AdapterFactory.d.ts.map +1 -0
  74. package/dist/factory/createDatabaseService.d.ts +121 -0
  75. package/dist/factory/createDatabaseService.d.ts.map +1 -0
  76. package/dist/index.cjs +8518 -0
  77. package/dist/index.cjs.map +1 -0
  78. package/dist/index.d.ts +19 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.mjs +8480 -0
  81. package/dist/index.mjs.map +1 -0
  82. package/dist/repository/BaseRepository.d.ts +209 -0
  83. package/dist/repository/BaseRepository.d.ts.map +1 -0
  84. package/dist/repository/index.d.ts +80 -0
  85. package/dist/repository/index.d.ts.map +1 -0
  86. package/dist/security/index.cjs +118 -0
  87. package/dist/security/index.cjs.map +1 -0
  88. package/dist/security/index.d.ts +3 -0
  89. package/dist/security/index.d.ts.map +1 -0
  90. package/dist/security/index.mjs +114 -0
  91. package/dist/security/index.mjs.map +1 -0
  92. package/dist/security/sanitizers/html.sanitizer.d.ts +31 -0
  93. package/dist/security/sanitizers/html.sanitizer.d.ts.map +1 -0
  94. package/dist/security/serializers/DataValidation.d.ts +34 -0
  95. package/dist/security/serializers/DataValidation.d.ts.map +1 -0
  96. package/dist/service/DatabaseService.d.ts +136 -0
  97. package/dist/service/DatabaseService.d.ts.map +1 -0
  98. package/dist/service/EventEmitter.d.ts +110 -0
  99. package/dist/service/EventEmitter.d.ts.map +1 -0
  100. package/dist/service/HealthManager.d.ts +166 -0
  101. package/dist/service/HealthManager.d.ts.map +1 -0
  102. package/dist/utils/ConfigMerger.d.ts +227 -0
  103. package/dist/utils/ConfigMerger.d.ts.map +1 -0
  104. package/dist/utils/databaseResultHelpers.d.ts +98 -0
  105. package/dist/utils/databaseResultHelpers.d.ts.map +1 -0
  106. package/dist/utils/index.d.ts +7 -0
  107. package/dist/utils/index.d.ts.map +1 -0
  108. package/dist/utils/normalizeDetails.d.ts +111 -0
  109. package/dist/utils/normalizeDetails.d.ts.map +1 -0
  110. package/dist/utils/pagination.d.ts +77 -0
  111. package/dist/utils/pagination.d.ts.map +1 -0
  112. package/dist/utils/regex.d.ts +199 -0
  113. package/dist/utils/regex.d.ts.map +1 -0
  114. package/dist/utils/typeGuards.d.ts +57 -0
  115. package/dist/utils/typeGuards.d.ts.map +1 -0
  116. package/dist/utils/validation.d.ts +146 -0
  117. package/dist/utils/validation.d.ts.map +1 -0
  118. package/package.json +156 -0
@@ -0,0 +1,292 @@
1
+ import type { DatabaseAdapterType, DatabaseResult, PaginatedResult, QueryOptions } from "@plyaz/types/db";
2
+ /**
3
+ * TENANT REPOSITORY - Multi-Tenant Database Operations
4
+ *
5
+ * Base repository that automatically handles tenant isolation for all database operations.
6
+ * Ensures data security by automatically filtering records by tenant ID and validating access.
7
+ *
8
+ * **RESPONSIBILITIES:**
9
+ * 1. Tenant Isolation - Automatically filters all queries by current tenant
10
+ * 2. Access Control - Validates tenant access for all operations
11
+ * 3. Auto-Assignment - Automatically assigns tenant ID on record creation
12
+ * 4. Validation - Ensures all operations respect tenant boundaries
13
+ *
14
+ * **USAGE PATTERN:**
15
+ * Extend this class for each entity that requires tenant isolation.
16
+ *
17
+ * @template TEntity - The entity type that includes a tenant ID field
18
+ *
19
+ * @example
20
+ * ### Basic Implementation
21
+ * ```typescript
22
+ * interface User {
23
+ * id: string;
24
+ * name: string;
25
+ * email: string;
26
+ * tenantId: string; // Required for tenant isolation
27
+ * }
28
+ *
29
+ * class UserRepository extends TenantRepository<User> {
30
+ * constructor(adapter: DatabaseAdapterType) {
31
+ * super(adapter, 'users');
32
+ * }
33
+ *
34
+ * protected getTenantIdField(): keyof User {
35
+ * return 'tenantId';
36
+ * }
37
+ *
38
+ * // Custom methods with automatic tenant isolation
39
+ * async findByEmail(email: string) {
40
+ * return this.findMany({ filter: { field: 'email', operator: 'eq', value: email } });
41
+ * }
42
+ * }
43
+ * ```
44
+ *
45
+ * @example
46
+ * ### Usage with Tenant Context
47
+ * ```typescript
48
+ * // Set tenant context (usually in middleware)
49
+ * TenantContext.set({ id: 'tenant-123', name: 'Acme Corp' });
50
+ *
51
+ * const userRepo = new UserRepository(adapter);
52
+ *
53
+ * // All operations automatically filtered by tenant
54
+ * const users = await userRepo.findMany(); // Only returns users for tenant-123
55
+ * const user = await userRepo.findById('user-456'); // Validates tenant access
56
+ *
57
+ * // New records automatically get tenant ID
58
+ * const newUser = await userRepo.create({
59
+ * name: 'John Doe',
60
+ * email: 'john@example.com'
61
+ * // tenantId automatically set to 'tenant-123'
62
+ * });
63
+ * ```
64
+ */
65
+ export interface TenantContextType {
66
+ id: string;
67
+ }
68
+ export interface TenantValidationContext {
69
+ id: string;
70
+ }
71
+ export declare abstract class TenantRepository<TEntity extends object> {
72
+ protected adapter: DatabaseAdapterType;
73
+ protected tableName: string;
74
+ /**
75
+ * Creates a new tenant repository instance.
76
+ *
77
+ * @param adapter - Database adapter for operations
78
+ * @param tableName - Name of the database table
79
+ */
80
+ constructor(adapter: DatabaseAdapterType, tableName: string);
81
+ /**
82
+ * ABSTRACT METHOD - Tenant ID Field Specification
83
+ *
84
+ * Must be implemented by subclasses to specify which field contains the tenant ID.
85
+ * This field is used for automatic filtering and validation.
86
+ *
87
+ * @returns The key of the tenant ID field in the entity
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * protected getTenantIdField(): keyof User {
92
+ * return 'tenantId'; // or 'organizationId', 'companyId', etc.
93
+ * }
94
+ * ```
95
+ */
96
+ protected abstract getTenantIdField(): keyof TEntity;
97
+ /**
98
+ * FIND BY ID - Tenant-Safe Record Retrieval
99
+ *
100
+ * Finds a single record by ID with automatic tenant access validation.
101
+ * Only returns records that belong to the current tenant.
102
+ *
103
+ * **SECURITY:** Validates that the found record belongs to the current tenant
104
+ * **BEHAVIOR:** Returns null if record doesn't exist or belongs to different tenant
105
+ *
106
+ * @param id - The unique identifier of the record to find
107
+ * @returns Promise resolving to the record or null if not found/no access
108
+ *
109
+ * @throws {DatabaseError} When ID is invalid or access is denied
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Set tenant context
114
+ * TenantContext.set({ id: 'tenant-123' });
115
+ *
116
+ * const userRepo = new UserRepository(adapter);
117
+ *
118
+ * // Find user - only returns if belongs to tenant-123
119
+ * const result = await userRepo.findById('user-456');
120
+ * if (result.success && result.value) {
121
+ * console.log('User found:', result.value.name);
122
+ * } else {
123
+ * console.log('User not found or access denied');
124
+ * }
125
+ * ```
126
+ */
127
+ findById(id: string): Promise<DatabaseResult<TEntity | null>>;
128
+ /**
129
+ * FIND MANY - Tenant-Filtered Query
130
+ *
131
+ * Finds multiple records with automatic tenant filtering applied.
132
+ * All results are guaranteed to belong to the current tenant.
133
+ *
134
+ * **SECURITY:** Automatically adds tenant filter to all queries
135
+ * **PERFORMANCE:** Uses database-level filtering for efficiency
136
+ *
137
+ * @param options - Optional query options (filters, sorting, pagination)
138
+ * @returns Promise resolving to paginated results for current tenant only
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * // Set tenant context
143
+ * TenantContext.set({ id: 'tenant-123' });
144
+ *
145
+ * const userRepo = new UserRepository(adapter);
146
+ *
147
+ * // Get all users for current tenant
148
+ * const allUsers = await userRepo.findMany();
149
+ *
150
+ * // Get active users with pagination
151
+ * const activeUsers = await userRepo.findMany({
152
+ * filter: { field: 'status', operator: 'eq', value: 'active' },
153
+ * pagination: { page: 1, limit: 10 },
154
+ * sort: { field: 'name', direction: 'asc' }
155
+ * });
156
+ *
157
+ * // Results automatically filtered by tenantId = 'tenant-123'
158
+ * ```
159
+ */
160
+ findMany(options?: QueryOptions): Promise<DatabaseResult<PaginatedResult<TEntity>>>;
161
+ /**
162
+ * CREATE - Tenant-Safe Record Creation
163
+ *
164
+ * Creates a new record with automatic tenant ID assignment.
165
+ * The tenant ID is automatically set from the current tenant context.
166
+ *
167
+ * **SECURITY:** Automatically assigns current tenant ID to new records
168
+ * **CONVENIENCE:** No need to manually set tenant ID in application code
169
+ *
170
+ * @param entity - The entity data to create (tenant ID will be auto-assigned)
171
+ * @returns Promise resolving to the created record with tenant ID
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Set tenant context
176
+ * TenantContext.set({ id: 'tenant-123' });
177
+ *
178
+ * const userRepo = new UserRepository(adapter);
179
+ *
180
+ * // Create user - tenantId automatically set to 'tenant-123'
181
+ * const result = await userRepo.create({
182
+ * name: 'John Doe',
183
+ * email: 'john@example.com',
184
+ * status: 'active'
185
+ * // No need to set tenantId - automatically assigned
186
+ * });
187
+ *
188
+ * if (result.success) {
189
+ * console.log('Created user:', result.value.id);
190
+ * console.log('Tenant ID:', result.value.tenantId); // 'tenant-123'
191
+ * }
192
+ * ```
193
+ */
194
+ create(entity: Omit<TEntity, "id">): Promise<DatabaseResult<TEntity>>;
195
+ /**
196
+ * UPDATE - Tenant-Safe Record Update
197
+ *
198
+ * Updates an existing record with tenant access validation.
199
+ * Only allows updates to records that belong to the current tenant.
200
+ *
201
+ * **SECURITY:** Validates tenant access before allowing updates
202
+ * **SAFETY:** Prevents cross-tenant data modification
203
+ *
204
+ * @param id - The unique identifier of the record to update
205
+ * @param entity - Partial entity data with fields to update
206
+ * @returns Promise resolving to the updated record
207
+ *
208
+ * @throws {DatabaseError} When record not found, access denied, or invalid parameters
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * // Set tenant context
213
+ * TenantContext.set({ id: 'tenant-123' });
214
+ *
215
+ * const userRepo = new UserRepository(adapter);
216
+ *
217
+ * // Update user - only works if user belongs to tenant-123
218
+ * const result = await userRepo.update('user-456', {
219
+ * name: 'Jane Doe',
220
+ * email: 'jane@example.com'
221
+ * });
222
+ *
223
+ * if (result.success) {
224
+ * console.log('Updated user:', result.value.name);
225
+ * } else {
226
+ * console.log('Update failed:', result.error?.message);
227
+ * }
228
+ * ```
229
+ */
230
+ update(id: string, entity: Partial<TEntity>): Promise<DatabaseResult<TEntity>>;
231
+ /**
232
+ * DELETE - Tenant-Safe Record Deletion
233
+ *
234
+ * Deletes a record with tenant access validation.
235
+ * Only allows deletion of records that belong to the current tenant.
236
+ *
237
+ * **SECURITY:** Validates tenant access before allowing deletion
238
+ * **SAFETY:** Prevents cross-tenant data deletion
239
+ *
240
+ * @param id - The unique identifier of the record to delete
241
+ * @returns Promise resolving to void on successful deletion
242
+ *
243
+ * @throws {DatabaseError} When record not found, access denied, or invalid ID
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * // Set tenant context
248
+ * TenantContext.set({ id: 'tenant-123' });
249
+ *
250
+ * const userRepo = new UserRepository(adapter);
251
+ *
252
+ * // Delete user - only works if user belongs to tenant-123
253
+ * const result = await userRepo.delete('user-456');
254
+ *
255
+ * if (result.success) {
256
+ * console.log('User deleted successfully');
257
+ * } else {
258
+ * console.log('Delete failed:', result.error?.message);
259
+ * }
260
+ * ```
261
+ */
262
+ delete(id: string): Promise<DatabaseResult<void>>;
263
+ /**
264
+ * Validates that the entity is a valid object.
265
+ * @private
266
+ * @param entity - The entity to validate
267
+ * @throws {DatabaseError} When entity is invalid
268
+ */
269
+ private validateEntity;
270
+ /**
271
+ * Validates that tenant context exists and has an ID.
272
+ * @private
273
+ * @param tenant - The tenant context to validate
274
+ * @throws {DatabaseError} When tenant context is invalid
275
+ */
276
+ private validateTenantContext;
277
+ /**
278
+ * Validates that the entity has a tenant ID.
279
+ * @private
280
+ * @param tenantId - The tenant ID from the entity
281
+ * @throws {DatabaseError} When tenant ID is missing
282
+ */
283
+ private validateEntityTenantId;
284
+ /**
285
+ * Validates that the current tenant has access to the entity.
286
+ * @private
287
+ * @param entity - The entity to validate access for
288
+ * @throws {DatabaseError} When access is denied
289
+ */
290
+ private validateTenantAccess;
291
+ }
292
+ //# sourceMappingURL=TenantRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantRepository.d.ts","sourceRoot":"","sources":["../../../src/advanced/multi-tenancy/TenantRepository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,YAAY,EACb,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,8BAAsB,gBAAgB,CAAC,OAAO,SAAS,MAAM;IAQzD,SAAS,CAAC,OAAO,EAAE,mBAAmB;IACtC,SAAS,CAAC,SAAS,EAAE,MAAM;IAR7B;;;;;OAKG;gBAES,OAAO,EAAE,mBAAmB,EAC5B,SAAS,EAAE,MAAM;IAG7B;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,QAAQ,CAAC,gBAAgB,IAAI,MAAM,OAAO;IAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IA0CnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,QAAQ,CACZ,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAiBpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAU3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GACvB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAsDnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IA8DvD;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IActB;;;;;OAKG;IAEH,OAAO,CAAC,qBAAqB;IAc7B;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CAkC7B"}
@@ -0,0 +1,3 @@
1
+ export { TenantContext } from "./TenantContext";
2
+ export { TenantRepository } from "./TenantRepository";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/advanced/multi-tenancy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}