bunsane 0.1.0 → 0.1.2

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 (82) hide show
  1. package/.github/workflows/deploy-docs.yml +57 -0
  2. package/LICENSE.md +1 -1
  3. package/README.md +2 -28
  4. package/TODO.md +8 -1
  5. package/bun.lock +3 -0
  6. package/config/upload.config.ts +135 -0
  7. package/core/App.ts +168 -4
  8. package/core/ArcheType.ts +122 -0
  9. package/core/BatchLoader.ts +100 -0
  10. package/core/ComponentRegistry.ts +4 -3
  11. package/core/Components.ts +2 -2
  12. package/core/Decorators.ts +15 -8
  13. package/core/Entity.ts +193 -14
  14. package/core/EntityCache.ts +15 -0
  15. package/core/EntityHookManager.ts +855 -0
  16. package/core/EntityManager.ts +12 -2
  17. package/core/ErrorHandler.ts +64 -7
  18. package/core/FileValidator.ts +284 -0
  19. package/core/Query.ts +503 -85
  20. package/core/RequestContext.ts +24 -0
  21. package/core/RequestLoaders.ts +89 -0
  22. package/core/SchedulerManager.ts +710 -0
  23. package/core/UploadManager.ts +261 -0
  24. package/core/components/UploadComponent.ts +206 -0
  25. package/core/decorators/EntityHooks.ts +190 -0
  26. package/core/decorators/ScheduledTask.ts +83 -0
  27. package/core/events/EntityLifecycleEvents.ts +177 -0
  28. package/core/processors/ImageProcessor.ts +423 -0
  29. package/core/storage/LocalStorageProvider.ts +290 -0
  30. package/core/storage/StorageProvider.ts +112 -0
  31. package/database/DatabaseHelper.ts +183 -58
  32. package/database/index.ts +5 -5
  33. package/database/sqlHelpers.ts +7 -0
  34. package/docs/README.md +149 -0
  35. package/docs/_coverpage.md +36 -0
  36. package/docs/_sidebar.md +23 -0
  37. package/docs/api/core.md +568 -0
  38. package/docs/api/hooks.md +554 -0
  39. package/docs/api/index.md +222 -0
  40. package/docs/api/query.md +678 -0
  41. package/docs/api/service.md +744 -0
  42. package/docs/core-concepts/archetypes.md +512 -0
  43. package/docs/core-concepts/components.md +498 -0
  44. package/docs/core-concepts/entity.md +314 -0
  45. package/docs/core-concepts/hooks.md +683 -0
  46. package/docs/core-concepts/query.md +588 -0
  47. package/docs/core-concepts/services.md +647 -0
  48. package/docs/examples/code-examples.md +425 -0
  49. package/docs/getting-started.md +337 -0
  50. package/docs/index.html +97 -0
  51. package/gql/Generator.ts +58 -35
  52. package/gql/decorators/Upload.ts +176 -0
  53. package/gql/helpers.ts +67 -0
  54. package/gql/index.ts +65 -31
  55. package/gql/types.ts +1 -1
  56. package/index.ts +79 -11
  57. package/package.json +19 -10
  58. package/rest/Generator.ts +3 -0
  59. package/rest/index.ts +22 -0
  60. package/service/Service.ts +1 -1
  61. package/service/ServiceRegistry.ts +10 -6
  62. package/service/index.ts +12 -1
  63. package/tests/bench/insert.bench.ts +59 -0
  64. package/tests/bench/relations.bench.ts +269 -0
  65. package/tests/bench/sorting.bench.ts +415 -0
  66. package/tests/component-hooks.test.ts +1409 -0
  67. package/tests/component.test.ts +338 -0
  68. package/tests/errorHandling.test.ts +155 -0
  69. package/tests/hooks.test.ts +666 -0
  70. package/tests/query-sorting.test.ts +101 -0
  71. package/tests/relations.test.ts +169 -0
  72. package/tests/scheduler.test.ts +724 -0
  73. package/tsconfig.json +35 -34
  74. package/types/graphql.types.ts +87 -0
  75. package/types/hooks.types.ts +141 -0
  76. package/types/scheduler.types.ts +165 -0
  77. package/types/upload.types.ts +184 -0
  78. package/upload/index.ts +140 -0
  79. package/utils/UploadHelper.ts +305 -0
  80. package/utils/cronParser.ts +366 -0
  81. package/utils/errorMessages.ts +151 -0
  82. package/core/Events.ts +0 -0
@@ -0,0 +1,512 @@
1
+ # ArcheType System
2
+
3
+ ArcheTypes are BunSane's powerful abstraction layer that provides reusable templates for creating entities with predefined sets of components. They eliminate code duplication and ensure consistency across your application by defining entity "blueprints".
4
+
5
+ ## 🎯 What is an ArcheType?
6
+
7
+ An ArcheType is a template that defines a specific combination of components that should be present on an entity. Think of it as a "class" in traditional OOP, but with the flexibility of composition.
8
+
9
+ ### Key Benefits
10
+
11
+ - **Consistency**: Ensures entities have the correct component combinations
12
+ - **Reusability**: Define once, use everywhere
13
+ - **Type Safety**: Full TypeScript support with compile-time guarantees
14
+ - **Data Integrity**: Guarantees required components are always present
15
+ - **Code Organization**: Clear separation of entity types and their capabilities
16
+
17
+ ## 🏗️ Creating ArcheTypes
18
+
19
+ ### Basic ArcheType Definition
20
+
21
+ ```typescript
22
+ import { ArcheType, Component, CompData, BaseComponent } from 'bunsane';
23
+
24
+ @Component
25
+ export class UserProfile extends BaseComponent {
26
+ @CompData()
27
+ name: string = '';
28
+
29
+ @CompData()
30
+ email: string = '';
31
+ }
32
+
33
+ @Component
34
+ export class UserPreferences extends BaseComponent {
35
+ @CompData()
36
+ theme: 'light' | 'dark' = 'light';
37
+
38
+ @CompData()
39
+ notifications: boolean = true;
40
+ }
41
+
42
+ @Component
43
+ export class UserStats extends BaseComponent {
44
+ @CompData()
45
+ loginCount: number = 0;
46
+
47
+ @CompData()
48
+ lastLogin: Date = new Date();
49
+ }
50
+
51
+ // Create ArcheType
52
+ export const UserArcheType = new ArcheType([
53
+ UserProfile,
54
+ UserPreferences,
55
+ UserStats
56
+ ]);
57
+ ```
58
+
59
+ ### Complex ArcheType with Relationships
60
+
61
+ ```typescript
62
+ @Component
63
+ export class BlogPost extends BaseComponent {
64
+ @CompData()
65
+ title: string = '';
66
+
67
+ @CompData()
68
+ content: string = '';
69
+
70
+ @CompData({ indexed: true })
71
+ authorId: string = '';
72
+
73
+ @CompData()
74
+ tags: string[] = [];
75
+ }
76
+
77
+ @Component
78
+ export class PostMetadata extends BaseComponent {
79
+ @CompData()
80
+ publishedAt: Date = new Date();
81
+
82
+ @CompData()
83
+ readingTime: number = 0; // in minutes
84
+
85
+ @CompData()
86
+ wordCount: number = 0;
87
+ }
88
+
89
+ @Component
90
+ export class PostStats extends BaseComponent {
91
+ @CompData()
92
+ viewCount: number = 0;
93
+
94
+ @CompData()
95
+ likeCount: number = 0;
96
+
97
+ @CompData()
98
+ commentCount: number = 0;
99
+ }
100
+
101
+ export const BlogPostArcheType = new ArcheType([
102
+ BlogPost,
103
+ PostMetadata,
104
+ PostStats
105
+ ]);
106
+ ```
107
+
108
+ ## 🎨 Using ArcheTypes
109
+
110
+ ### Creating Entities from ArcheTypes
111
+
112
+ ```typescript
113
+ // Create entity with all archetype components
114
+ const userEntity = UserArcheType.createEntity();
115
+
116
+ // The entity now has UserProfile, UserPreferences, and UserStats components
117
+ console.log(userEntity.has(UserProfile)); // true
118
+ console.log(userEntity.has(UserPreferences)); // true
119
+ console.log(userEntity.has(UserStats)); // true
120
+ ```
121
+
122
+ ### Filling ArcheTypes with Data
123
+
124
+ ```typescript
125
+ // Fill archetype with data before creating entity
126
+ const userData = {
127
+ userProfile: {
128
+ name: 'John Doe',
129
+ email: 'john@example.com'
130
+ },
131
+ userPreferences: {
132
+ theme: 'dark',
133
+ notifications: false
134
+ },
135
+ userStats: {
136
+ loginCount: 1,
137
+ lastLogin: new Date()
138
+ }
139
+ };
140
+
141
+ const userEntity = UserArcheType.fill(userData).createEntity();
142
+ await userEntity.save();
143
+ ```
144
+
145
+ ### Creating and Saving in One Step
146
+
147
+ ```typescript
148
+ // Create and save entity in one operation
149
+ const userEntity = await UserArcheType.fill(userData).createAndSaveEntity();
150
+
151
+ // Entity is now saved to database
152
+ console.log(userEntity._persisted); // true
153
+ ```
154
+
155
+ ## 🔄 ArcheType Operations
156
+
157
+ ### Updating Entities
158
+
159
+ ```typescript
160
+ // Update existing entity using archetype
161
+ const existingUser = await Entity.FindById(userId);
162
+
163
+ const updates = {
164
+ userProfile: {
165
+ name: 'Jane Doe'
166
+ },
167
+ userPreferences: {
168
+ theme: 'light'
169
+ }
170
+ };
171
+
172
+ await UserArcheType.updateEntity(existingUser, updates);
173
+ await existingUser.save();
174
+ ```
175
+
176
+ ### Unwrapping Entities
177
+
178
+ ```typescript
179
+ // Convert entity back to plain object
180
+ const userEntity = await Entity.FindById(userId);
181
+ const userData = await UserArcheType.Unwrap(userEntity);
182
+
183
+ console.log(userData);
184
+ // {
185
+ // userProfile: { name: 'John Doe', email: 'john@example.com' },
186
+ // userPreferences: { theme: 'dark', notifications: true },
187
+ // userStats: { loginCount: 5, lastLogin: '2025-09-17T...' }
188
+ // }
189
+ ```
190
+
191
+ ### Unwrapping with Field Exclusion
192
+
193
+ ```typescript
194
+ // Exclude sensitive data when unwrapping
195
+ const publicUserData = await UserArcheType.Unwrap(userEntity, ['email', 'loginCount']);
196
+
197
+ console.log(publicUserData);
198
+ // {
199
+ // userProfile: { name: 'John Doe' }, // email excluded
200
+ // userPreferences: { theme: 'dark', notifications: true },
201
+ // userStats: { lastLogin: '2025-09-17T...' } // loginCount excluded
202
+ // }
203
+ ```
204
+
205
+ ## 🏷️ ArcheType Inheritance and Composition
206
+
207
+ ### Base ArcheTypes
208
+
209
+ ```typescript
210
+ // Base archetype for all content
211
+ export const ContentArcheType = new ArcheType([
212
+ BaseContent,
213
+ ContentMetadata
214
+ ]);
215
+
216
+ // Extended archetypes
217
+ export const BlogPostArcheType = new ArcheType([
218
+ ...ContentArcheType.getComponents(),
219
+ BlogPost,
220
+ PostStats
221
+ ]);
222
+
223
+ export const PageArcheType = new ArcheType([
224
+ ...ContentArcheType.getComponents(),
225
+ PageContent,
226
+ PageSettings
227
+ ]);
228
+ ```
229
+
230
+ ### Specialized ArcheTypes
231
+
232
+ ```typescript
233
+ // Admin user archetype (extends regular user)
234
+ export const AdminUserArcheType = new ArcheType([
235
+ ...UserArcheType.getComponents(),
236
+ AdminPermissions,
237
+ AdminStats
238
+ ]);
239
+
240
+ // Premium user archetype
241
+ export const PremiumUserArcheType = new ArcheType([
242
+ ...UserArcheType.getComponents(),
243
+ PremiumFeatures,
244
+ BillingInfo
245
+ ]);
246
+ ```
247
+
248
+ ## 🔍 ArcheType Queries
249
+
250
+ ### Querying by ArcheType
251
+
252
+ ```typescript
253
+ import { Query } from 'bunsane';
254
+
255
+ // Find all users
256
+ const userQuery = new Query()
257
+ .with(UserProfile) // Must have UserProfile component
258
+ .with(UserPreferences); // Must have UserPreferences component
259
+
260
+ const users = await userQuery.exec();
261
+
262
+ // Find premium users
263
+ const premiumQuery = new Query()
264
+ .with(UserProfile)
265
+ .with(PremiumFeatures);
266
+
267
+ const premiumUsers = await premiumQuery.exec();
268
+ ```
269
+
270
+ ### ArcheType-Specific Queries
271
+
272
+ ```typescript
273
+ // Query with archetype filtering
274
+ const adminUsers = await new Query()
275
+ .with(UserProfile)
276
+ .with(AdminPermissions)
277
+ .exec();
278
+
279
+ // Get user count
280
+ const userCount = await new Query()
281
+ .with(UserProfile)
282
+ .count();
283
+ ```
284
+
285
+ ## 🎭 Advanced ArcheType Patterns
286
+
287
+ ### Dynamic ArcheTypes
288
+
289
+ ```typescript
290
+ class DynamicArcheType extends ArcheType {
291
+ constructor(userType: 'basic' | 'premium' | 'admin') {
292
+ const baseComponents = [UserProfile, UserPreferences];
293
+
294
+ const additionalComponents = {
295
+ basic: [],
296
+ premium: [PremiumFeatures, BillingInfo],
297
+ admin: [AdminPermissions, AdminStats, AuditLog]
298
+ };
299
+
300
+ super([...baseComponents, ...additionalComponents[userType]]);
301
+ }
302
+ }
303
+
304
+ // Usage
305
+ const basicUserArchetype = new DynamicArcheType('basic');
306
+ const premiumUserArchetype = new DynamicArcheType('premium');
307
+ const adminUserArchetype = new DynamicArcheType('admin');
308
+ ```
309
+
310
+ ### Conditional Components
311
+
312
+ ```typescript
313
+ class ConditionalArcheType extends ArcheType {
314
+ constructor(includeStats: boolean = false, includeAudit: boolean = false) {
315
+ const components = [UserProfile, UserPreferences];
316
+
317
+ if (includeStats) {
318
+ components.push(UserStats);
319
+ }
320
+
321
+ if (includeAudit) {
322
+ components.push(AuditLog);
323
+ }
324
+
325
+ super(components);
326
+ }
327
+ }
328
+
329
+ // Usage
330
+ const minimalUserArchetype = new ConditionalArcheType();
331
+ const fullUserArchetype = new ConditionalArcheType(true, true);
332
+ ```
333
+
334
+ ### ArcheType Factories
335
+
336
+ ```typescript
337
+ class ArcheTypeFactory {
338
+ static createUserArchetype(userType: string): ArcheType {
339
+ switch (userType) {
340
+ case 'admin':
341
+ return new ArcheType([
342
+ UserProfile,
343
+ UserPreferences,
344
+ AdminPermissions,
345
+ AdminStats
346
+ ]);
347
+
348
+ case 'premium':
349
+ return new ArcheType([
350
+ UserProfile,
351
+ UserPreferences,
352
+ PremiumFeatures,
353
+ BillingInfo
354
+ ]);
355
+
356
+ default:
357
+ return new ArcheType([
358
+ UserProfile,
359
+ UserPreferences
360
+ ]);
361
+ }
362
+ }
363
+
364
+ static createContentArchetype(contentType: string): ArcheType {
365
+ const baseComponents = [BaseContent, ContentMetadata];
366
+
367
+ switch (contentType) {
368
+ case 'blog':
369
+ return new ArcheType([...baseComponents, BlogPost, PostStats]);
370
+
371
+ case 'page':
372
+ return new ArcheType([...baseComponents, PageContent, PageSettings]);
373
+
374
+ case 'product':
375
+ return new ArcheType([...baseComponents, ProductInfo, Inventory]);
376
+
377
+ default:
378
+ return new ArcheType(baseComponents);
379
+ }
380
+ }
381
+ }
382
+
383
+ // Usage
384
+ const adminArchetype = ArcheTypeFactory.createUserArchetype('admin');
385
+ const blogArchetype = ArcheTypeFactory.createContentArchetype('blog');
386
+ ```
387
+
388
+ ## 🔧 ArcheType Management
389
+
390
+ ### ArcheType Registry
391
+
392
+ ```typescript
393
+ // Register archetypes for easy access
394
+ class ArcheTypeRegistry {
395
+ private static archetypes: Map<string, ArcheType> = new Map();
396
+
397
+ static register(name: string, archetype: ArcheType) {
398
+ this.archetypes.set(name, archetype);
399
+ }
400
+
401
+ static get(name: string): ArcheType | undefined {
402
+ return this.archetypes.get(name);
403
+ }
404
+
405
+ static getAll(): Map<string, ArcheType> {
406
+ return this.archetypes;
407
+ }
408
+ }
409
+
410
+ // Register common archetypes
411
+ ArcheTypeRegistry.register('user', UserArcheType);
412
+ ArcheTypeRegistry.register('admin', AdminUserArcheType);
413
+ ArcheTypeRegistry.register('blog-post', BlogPostArcheType);
414
+
415
+ // Usage
416
+ const userArchetype = ArcheTypeRegistry.get('user');
417
+ const adminArchetype = ArcheTypeRegistry.get('admin');
418
+ ```
419
+
420
+ ### ArcheType Validation
421
+
422
+ ```typescript
423
+ class ValidatedArcheType extends ArcheType {
424
+ constructor(components: any[], requiredComponents: any[] = []) {
425
+ super(components);
426
+ this.requiredComponents = requiredComponents;
427
+ }
428
+
429
+ validateEntity(entity: Entity): boolean {
430
+ // Check if entity has all required components
431
+ return this.requiredComponents.every(component =>
432
+ entity.has(component)
433
+ );
434
+ }
435
+
436
+ createValidatedEntity(data?: any): Entity {
437
+ const entity = this.fill(data || {}).createEntity();
438
+
439
+ if (!this.validateEntity(entity)) {
440
+ throw new Error('Entity does not meet archetype requirements');
441
+ }
442
+
443
+ return entity;
444
+ }
445
+ }
446
+
447
+ // Usage
448
+ const validatedUserArchetype = new ValidatedArcheType(
449
+ [UserProfile, UserPreferences, UserStats],
450
+ [UserProfile] // UserProfile is required
451
+ );
452
+
453
+ try {
454
+ const user = validatedUserArchetype.createValidatedEntity(userData);
455
+ } catch (error) {
456
+ console.error('Validation failed:', error);
457
+ }
458
+ ```
459
+
460
+ ## 📊 Best Practices
461
+
462
+ ### ArcheType Design
463
+
464
+ - **Clear Purpose**: Each archetype should have a single, clear responsibility
465
+ - **Minimal Components**: Include only essential components to avoid bloat
466
+ - **Consistent Naming**: Use descriptive names that indicate the archetype's purpose
467
+ - **Versioning**: Consider versioning for archetypes that evolve over time
468
+ - **Documentation**: Document the purpose and usage of each archetype
469
+
470
+ ### Performance Considerations
471
+
472
+ - **Component Loading**: Be mindful of the number of components in an archetype
473
+ - **Query Optimization**: Design archetypes to support efficient queries
474
+ - **Memory Usage**: Consider the memory impact of large archetypes
475
+ - **Caching**: Cache frequently used archetypes to improve performance
476
+
477
+ ### Error Handling
478
+
479
+ ```typescript
480
+ try {
481
+ // Validate data before creating entity
482
+ if (!userData.email || !userData.name) {
483
+ throw new Error('Missing required user data');
484
+ }
485
+
486
+ const userEntity = await UserArcheType.fill(userData).createAndSaveEntity();
487
+ console.log('User created successfully:', userEntity.id);
488
+
489
+ } catch (error) {
490
+ console.error('Failed to create user:', error);
491
+
492
+ // Log error details for debugging
493
+ logger.error('User creation failed', {
494
+ error: error.message,
495
+ userData: userData,
496
+ archetype: 'UserArcheType'
497
+ });
498
+ }
499
+ ```
500
+
501
+ ## 🚀 What's Next?
502
+
503
+ Now that you understand ArcheTypes, let's explore:
504
+
505
+ - **[Services](services.md)** - Business logic and GraphQL integration
506
+ - **[Query System](query.md)** - Efficient data retrieval
507
+ - **[Entity System](entity.md)** - How entities work with archetypes
508
+ - **[Lifecycle Hooks](hooks.md)** - Business logic integration
509
+
510
+ ---
511
+
512
+ *Ready to build with archetypes? Let's look at [Services](services.md) next!* 🚀