bunsane 0.1.4 → 0.2.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.
- package/.claude/settings.local.json +47 -0
- package/.claude/skills/update-memory.md +74 -0
- package/.prettierrc +4 -0
- package/.serena/memories/architectural-decision-no-dependency-injection.md +76 -0
- package/.serena/memories/architecture.md +154 -0
- package/.serena/memories/cache-interface-refactoring-2026-01-24.md +165 -0
- package/.serena/memories/code_style_and_conventions.md +76 -0
- package/.serena/memories/project_overview.md +43 -0
- package/.serena/memories/schema-dsl-plan.md +107 -0
- package/.serena/memories/suggested_commands.md +80 -0
- package/.serena/memories/typescript-compilation-status.md +54 -0
- package/.serena/project.yml +114 -0
- package/TODO.md +1 -7
- package/bun.lock +150 -4
- package/bunfig.toml +10 -0
- package/config/cache.config.ts +77 -0
- package/config/upload.config.ts +4 -5
- package/core/App.ts +870 -123
- package/core/ArcheType.ts +2268 -377
- package/core/BatchLoader.ts +181 -71
- package/core/Config.ts +153 -0
- package/core/Decorators.ts +4 -1
- package/core/Entity.ts +621 -92
- package/core/EntityHookManager.ts +1 -1
- package/core/EntityInterface.ts +3 -1
- package/core/EntityManager.ts +1 -13
- package/core/ErrorHandler.ts +8 -2
- package/core/Logger.ts +9 -0
- package/core/Middleware.ts +34 -0
- package/core/RequestContext.ts +5 -1
- package/core/RequestLoaders.ts +227 -93
- package/core/SchedulerManager.ts +193 -52
- package/core/cache/CacheAnalytics.ts +399 -0
- package/core/cache/CacheFactory.ts +145 -0
- package/core/cache/CacheManager.ts +520 -0
- package/core/cache/CacheProvider.ts +34 -0
- package/core/cache/CacheWarmer.ts +157 -0
- package/core/cache/CompressionUtils.ts +110 -0
- package/core/cache/MemoryCache.ts +251 -0
- package/core/cache/MultiLevelCache.ts +180 -0
- package/core/cache/NoOpCache.ts +53 -0
- package/core/cache/RedisCache.ts +464 -0
- package/core/cache/TTLStrategy.ts +254 -0
- package/core/cache/index.ts +6 -0
- package/core/components/BaseComponent.ts +120 -0
- package/core/{ComponentRegistry.ts → components/ComponentRegistry.ts} +148 -54
- package/core/components/Decorators.ts +88 -0
- package/core/components/Interfaces.ts +7 -0
- package/core/components/index.ts +5 -0
- package/core/decorators/EntityHooks.ts +0 -3
- package/core/decorators/IndexedField.ts +26 -0
- package/core/decorators/ScheduledTask.ts +0 -47
- package/core/events/EntityLifecycleEvents.ts +1 -1
- package/core/health.ts +112 -0
- package/core/metadata/definitions/ArcheType.ts +14 -0
- package/core/metadata/definitions/Component.ts +9 -0
- package/core/metadata/definitions/gqlObject.ts +1 -1
- package/core/metadata/index.ts +42 -1
- package/core/metadata/metadata-storage.ts +28 -2
- package/core/middleware/AccessLog.ts +59 -0
- package/core/middleware/RequestId.ts +38 -0
- package/core/middleware/SecurityHeaders.ts +62 -0
- package/core/middleware/index.ts +3 -0
- package/core/scheduler/DistributedLock.ts +266 -0
- package/core/scheduler/index.ts +15 -0
- package/core/validateEnv.ts +92 -0
- package/database/DatabaseHelper.ts +416 -40
- package/database/IndexingStrategy.ts +342 -0
- package/database/PreparedStatementCache.ts +226 -0
- package/database/index.ts +32 -7
- package/database/sqlHelpers.ts +14 -2
- package/endpoints/archetypes.ts +362 -0
- package/endpoints/components.ts +58 -0
- package/endpoints/entity.ts +80 -0
- package/endpoints/index.ts +27 -0
- package/endpoints/query.ts +93 -0
- package/endpoints/stats.ts +76 -0
- package/endpoints/tables.ts +212 -0
- package/endpoints/types.ts +155 -0
- package/gql/ArchetypeOperations.ts +32 -86
- package/gql/Generator.ts +27 -315
- package/gql/GeneratorV2.ts +37 -0
- package/gql/builders/InputTypeBuilder.ts +99 -0
- package/gql/builders/ResolverBuilder.ts +234 -0
- package/gql/builders/TypeDefBuilder.ts +105 -0
- package/gql/builders/index.ts +3 -0
- package/gql/decorators/Upload.ts +1 -1
- package/gql/depthLimit.ts +85 -0
- package/gql/graph/GraphNode.ts +224 -0
- package/gql/graph/SchemaGraph.ts +278 -0
- package/gql/helpers.ts +8 -2
- package/gql/index.ts +56 -4
- package/gql/middleware.ts +79 -0
- package/gql/orchestration/GraphQLSchemaOrchestrator.ts +241 -0
- package/gql/orchestration/index.ts +1 -0
- package/gql/scanner/ServiceScanner.ts +347 -0
- package/gql/schema/index.ts +458 -0
- package/gql/strategies/TypeGenerationStrategy.ts +329 -0
- package/gql/types.ts +1 -0
- package/gql/utils/TypeSignature.ts +220 -0
- package/gql/utils/index.ts +1 -0
- package/gql/visitors/ArchetypePreprocessorVisitor.ts +80 -0
- package/gql/visitors/DeduplicationVisitor.ts +82 -0
- package/gql/visitors/GraphVisitor.ts +78 -0
- package/gql/visitors/ResolverGeneratorVisitor.ts +122 -0
- package/gql/visitors/SchemaGeneratorVisitor.ts +851 -0
- package/gql/visitors/TypeCollectorVisitor.ts +79 -0
- package/gql/visitors/VisitorComposer.ts +96 -0
- package/gql/visitors/index.ts +7 -0
- package/package.json +59 -37
- package/plugins/index.ts +2 -2
- package/query/CTENode.ts +97 -0
- package/query/ComponentInclusionNode.ts +689 -0
- package/query/FilterBuilder.ts +127 -0
- package/query/FilterBuilderRegistry.ts +202 -0
- package/query/OrNode.ts +517 -0
- package/query/OrQuery.ts +42 -0
- package/query/Query.ts +1022 -0
- package/query/QueryContext.ts +170 -0
- package/query/QueryDAG.ts +122 -0
- package/query/QueryNode.ts +65 -0
- package/query/SourceNode.ts +53 -0
- package/query/builders/FullTextSearchBuilder.ts +236 -0
- package/query/index.ts +21 -0
- package/scheduler/index.ts +40 -8
- package/service/Service.ts +2 -1
- package/service/ServiceRegistry.ts +6 -5
- package/{core/storage → storage}/LocalStorageProvider.ts +2 -2
- package/storage/S3StorageProvider.ts +316 -0
- package/{core/storage → storage}/StorageProvider.ts +7 -3
- package/studio/bun.lock +482 -0
- package/studio/index.html +13 -0
- package/studio/package.json +39 -0
- package/studio/postcss.config.js +6 -0
- package/studio/src/components/DataTable.tsx +211 -0
- package/studio/src/components/Layout.tsx +13 -0
- package/studio/src/components/PageContainer.tsx +9 -0
- package/studio/src/components/PageHeader.tsx +13 -0
- package/studio/src/components/SearchBar.tsx +57 -0
- package/studio/src/components/Sidebar.tsx +294 -0
- package/studio/src/components/ui/button.tsx +56 -0
- package/studio/src/components/ui/checkbox.tsx +26 -0
- package/studio/src/components/ui/input.tsx +25 -0
- package/studio/src/hooks/useDataTable.ts +131 -0
- package/studio/src/index.css +36 -0
- package/studio/src/lib/api.ts +186 -0
- package/studio/src/lib/utils.ts +13 -0
- package/studio/src/main.tsx +17 -0
- package/studio/src/pages/ArcheType.tsx +239 -0
- package/studio/src/pages/Components.tsx +124 -0
- package/studio/src/pages/EntityInspector.tsx +302 -0
- package/studio/src/pages/QueryRunner.tsx +246 -0
- package/studio/src/pages/Table.tsx +94 -0
- package/studio/src/pages/Welcome.tsx +241 -0
- package/studio/src/routes.tsx +45 -0
- package/studio/src/store/archeTypeSettings.ts +30 -0
- package/studio/src/store/studio.ts +65 -0
- package/studio/src/utils/columnHelpers.tsx +114 -0
- package/studio/studio-instructions.md +81 -0
- package/studio/tailwind.config.js +77 -0
- package/studio/tsconfig.json +24 -0
- package/studio/utils.ts +54 -0
- package/studio/vite.config.js +19 -0
- package/swagger/generator.ts +1 -1
- package/tests/e2e/http.test.ts +126 -0
- package/tests/fixtures/archetypes/TestUserArchetype.ts +21 -0
- package/tests/fixtures/components/TestOrder.ts +23 -0
- package/tests/fixtures/components/TestProduct.ts +23 -0
- package/tests/fixtures/components/TestUser.ts +20 -0
- package/tests/fixtures/components/index.ts +6 -0
- package/tests/graphql/SchemaGeneration.test.ts +90 -0
- package/tests/graphql/builders/ResolverBuilder.test.ts +223 -0
- package/tests/graphql/builders/TypeDefBuilder.test.ts +153 -0
- package/tests/integration/archetype/ArcheType.persistence.test.ts +241 -0
- package/tests/integration/cache/CacheInvalidation.test.ts +259 -0
- package/tests/integration/entity/Entity.persistence.test.ts +333 -0
- package/tests/integration/query/Query.exec.test.ts +523 -0
- package/tests/pglite-setup.ts +61 -0
- package/tests/setup.ts +164 -0
- package/tests/stress/BenchmarkRunner.ts +203 -0
- package/tests/stress/DataSeeder.ts +190 -0
- package/tests/stress/StressTestReporter.ts +229 -0
- package/tests/stress/cursor-perf-test.ts +171 -0
- package/tests/stress/fixtures/StressTestComponents.ts +58 -0
- package/tests/stress/index.ts +7 -0
- package/tests/stress/scenarios/query-benchmarks.test.ts +285 -0
- package/tests/unit/BatchLoader.test.ts +82 -0
- package/tests/unit/archetype/ArcheType.test.ts +107 -0
- package/tests/unit/cache/CacheManager.test.ts +347 -0
- package/tests/unit/cache/MemoryCache.test.ts +260 -0
- package/tests/unit/cache/RedisCache.test.ts +411 -0
- package/tests/unit/entity/Entity.components.test.ts +244 -0
- package/tests/unit/entity/Entity.test.ts +345 -0
- package/tests/unit/gql/depthLimit.test.ts +203 -0
- package/tests/unit/gql/operationMiddleware.test.ts +293 -0
- package/tests/unit/health/Health.test.ts +129 -0
- package/tests/unit/middleware/AccessLog.test.ts +37 -0
- package/tests/unit/middleware/Middleware.test.ts +98 -0
- package/tests/unit/middleware/RequestId.test.ts +54 -0
- package/tests/unit/middleware/SecurityHeaders.test.ts +66 -0
- package/tests/unit/query/FilterBuilder.test.ts +111 -0
- package/tests/unit/query/Query.test.ts +308 -0
- package/tests/unit/scheduler/DistributedLock.test.ts +274 -0
- package/tests/unit/schema/schema-integration.test.ts +426 -0
- package/tests/unit/schema/schema.test.ts +580 -0
- package/tests/unit/storage/S3StorageProvider.test.ts +571 -0
- package/tests/unit/upload/RestUpload.test.ts +267 -0
- package/tests/unit/validateEnv.test.ts +82 -0
- package/tests/utils/entity-tracker.ts +57 -0
- package/tests/utils/index.ts +13 -0
- package/tests/utils/test-context.ts +149 -0
- package/tsconfig.json +5 -1
- package/types/archetype.types.ts +6 -0
- package/types/hooks.types.ts +1 -1
- package/types/query.types.ts +110 -0
- package/types/scheduler.types.ts +68 -7
- package/types/upload.types.ts +1 -0
- package/{core → upload}/FileValidator.ts +10 -1
- package/upload/RestUpload.ts +130 -0
- package/{core/components → upload}/UploadComponent.ts +11 -11
- package/{core → upload}/UploadManager.ts +3 -3
- package/upload/index.ts +23 -7
- package/utils/UploadHelper.ts +27 -6
- package/utils/cronParser.ts +16 -6
- package/.github/workflows/deploy-docs.yml +0 -57
- package/core/Components.ts +0 -202
- package/core/EntityCache.ts +0 -15
- package/core/Query.ts +0 -880
- package/docs/README.md +0 -149
- package/docs/_coverpage.md +0 -36
- package/docs/_sidebar.md +0 -23
- package/docs/api/core.md +0 -568
- package/docs/api/hooks.md +0 -554
- package/docs/api/index.md +0 -222
- package/docs/api/query.md +0 -678
- package/docs/api/service.md +0 -744
- package/docs/core-concepts/archetypes.md +0 -512
- package/docs/core-concepts/components.md +0 -498
- package/docs/core-concepts/entity.md +0 -314
- package/docs/core-concepts/hooks.md +0 -683
- package/docs/core-concepts/query.md +0 -588
- package/docs/core-concepts/services.md +0 -647
- package/docs/examples/code-examples.md +0 -425
- package/docs/getting-started.md +0 -337
- package/docs/index.html +0 -97
- package/tests/bench/insert.bench.ts +0 -60
- package/tests/bench/relations.bench.ts +0 -270
- package/tests/bench/sorting.bench.ts +0 -416
- package/tests/component-hooks-simple.test.ts +0 -117
- package/tests/component-hooks.test.ts +0 -1461
- package/tests/component.test.ts +0 -339
- package/tests/errorHandling.test.ts +0 -155
- package/tests/hooks.test.ts +0 -667
- package/tests/query-sorting.test.ts +0 -101
- package/tests/query.test.ts +0 -81
- package/tests/relations.test.ts +0 -170
- package/tests/scheduler.test.ts +0 -724
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(bun test:*)",
|
|
5
|
+
"mcp__serena__check_onboarding_performed",
|
|
6
|
+
"mcp__serena__activate_project",
|
|
7
|
+
"mcp__serena__onboarding",
|
|
8
|
+
"mcp__serena__list_dir",
|
|
9
|
+
"mcp__serena__find_file",
|
|
10
|
+
"mcp__serena__get_symbols_overview",
|
|
11
|
+
"mcp__serena__find_symbol",
|
|
12
|
+
"mcp__serena__think_about_collected_information",
|
|
13
|
+
"mcp__serena__write_memory",
|
|
14
|
+
"mcp__serena__list_memories",
|
|
15
|
+
"Bash(grep:*)",
|
|
16
|
+
"mcp__serena__initial_instructions",
|
|
17
|
+
"mcp__serena__read_memory",
|
|
18
|
+
"mcp__serena__search_for_pattern",
|
|
19
|
+
"mcp__serena__think_about_whether_you_are_done",
|
|
20
|
+
"mcp__serena__replace_symbol_body",
|
|
21
|
+
"Bash(find:*)",
|
|
22
|
+
"mcp__serena__get_current_config",
|
|
23
|
+
"mcp__serena__think_about_task_adherence",
|
|
24
|
+
"Bash(bun run tsc:*)",
|
|
25
|
+
"mcp__serena__insert_after_symbol",
|
|
26
|
+
"Bash(npx tsc:*)",
|
|
27
|
+
"Bash(STRESS_RECORD_COUNT=10000 bun test:*)",
|
|
28
|
+
"Bash(STRESS_RECORD_COUNT=1000 bun test:*)",
|
|
29
|
+
"mcp__serena__find_referencing_symbols",
|
|
30
|
+
"Bash(bun tsc:*)",
|
|
31
|
+
"mcp__serena__edit_memory",
|
|
32
|
+
"Bash(bunx tsc:*)",
|
|
33
|
+
"Bash(wc:*)",
|
|
34
|
+
"Bash(bun run:*)",
|
|
35
|
+
"Bash(BUN_CONFIG_FILE=/dev/null bun test:*)",
|
|
36
|
+
"Bash(echo:*)",
|
|
37
|
+
"WebSearch",
|
|
38
|
+
"Bash(bun:*)",
|
|
39
|
+
"Bash(tsc:*)",
|
|
40
|
+
"Bash(SKIP_TEST_DB_SETUP=true bun test:*)"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"statusLine": {
|
|
44
|
+
"type": "command",
|
|
45
|
+
"command": "input=$(cat); model=$(echo \"$input\" | jq -r '.model.display_name'); used=$(echo \"$input\" | jq -r '.context_window.used_percentage // empty'); remaining=$(echo \"$input\" | jq -r '.context_window.remaining_percentage // empty'); if [ -n \"$remaining\" ]; then printf \"%s | Context: %.1f%% used, %.1f%% remaining\" \"$model\" \"$used\" \"$remaining\"; else echo \"$model\"; fi"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update-memory
|
|
3
|
+
description: Updating project memories with new information
|
|
4
|
+
disable-model-invocation: false
|
|
5
|
+
allowed-tools: Read, Grep
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Update Memory Skill
|
|
9
|
+
|
|
10
|
+
This skill helps you update Serena project memories with new or changed information.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
Use `/update-memory` when you need to:
|
|
15
|
+
- Record architectural decisions or patterns discovered during work
|
|
16
|
+
- Update project conventions based on new practices
|
|
17
|
+
- Document important findings from code exploration
|
|
18
|
+
- Add new information to existing memory files
|
|
19
|
+
- Create new memory files for undocumented aspects
|
|
20
|
+
|
|
21
|
+
## Instructions
|
|
22
|
+
|
|
23
|
+
1. **List existing memories** first to see what's available:
|
|
24
|
+
- Use `mcp__serena__list_memories` to see all memory files
|
|
25
|
+
|
|
26
|
+
2. **Read the relevant memory** (if updating existing):
|
|
27
|
+
- Use `mcp__serena__read_memory` with the memory file name
|
|
28
|
+
- Understand the current content and structure
|
|
29
|
+
|
|
30
|
+
3. **Determine the action**:
|
|
31
|
+
- **Update existing**: Use `mcp__serena__edit_memory` for targeted changes
|
|
32
|
+
- **Create new**: Use `mcp__serena__write_memory` for new topics
|
|
33
|
+
- **Delete obsolete**: Use `mcp__serena__delete_memory` (only if user confirms)
|
|
34
|
+
|
|
35
|
+
4. **For updates**, use `edit_memory` with:
|
|
36
|
+
- `mode: "literal"` for exact string replacement
|
|
37
|
+
- `mode: "regex"` for pattern-based changes
|
|
38
|
+
- Keep the existing format and style
|
|
39
|
+
|
|
40
|
+
5. **For new memories**, use descriptive kebab-case names:
|
|
41
|
+
- `project_overview` - General project info
|
|
42
|
+
- `architecture` - System architecture
|
|
43
|
+
- `code_style_and_conventions` - Coding standards
|
|
44
|
+
- `{feature}-implementation` - Feature-specific docs
|
|
45
|
+
|
|
46
|
+
## Memory Naming Conventions
|
|
47
|
+
|
|
48
|
+
| Pattern | Purpose |
|
|
49
|
+
|---------|---------|
|
|
50
|
+
| `project_overview` | High-level project description |
|
|
51
|
+
| `architecture` | Directory structure, core concepts |
|
|
52
|
+
| `code_style_and_conventions` | Formatting, naming, patterns |
|
|
53
|
+
| `{topic}-decisions` | Architectural decisions on topic |
|
|
54
|
+
| `{feature}-implementation` | How a feature works |
|
|
55
|
+
| `suggested_commands` | Useful commands for the project |
|
|
56
|
+
| `task_completion_checklist` | Steps to verify work is complete |
|
|
57
|
+
|
|
58
|
+
## Example Usage
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
User: /update-memory Add that we use Bun for testing
|
|
62
|
+
Assistant: [Lists memories, reads code_style_and_conventions, updates with new testing info]
|
|
63
|
+
|
|
64
|
+
User: /update-memory Create a memory about the caching system
|
|
65
|
+
Assistant: [Creates new memory file: caching-system.md with relevant information]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Important Notes
|
|
69
|
+
|
|
70
|
+
- Always read existing content before editing to preserve context
|
|
71
|
+
- Use markdown format for memory content
|
|
72
|
+
- Keep memories focused and organized
|
|
73
|
+
- Ask for confirmation before deleting memories
|
|
74
|
+
- After updating, summarize what was changed
|
package/.prettierrc
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Architectural Decision: No Dependency Injection (For Now)
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-21
|
|
4
|
+
**Status:** Decided
|
|
5
|
+
**Context:** Framework v0.1.5 (experimental)
|
|
6
|
+
|
|
7
|
+
## Decision
|
|
8
|
+
|
|
9
|
+
BunSane will NOT implement a formal Dependency Injection (DI) container at this stage.
|
|
10
|
+
|
|
11
|
+
## Current Approach
|
|
12
|
+
|
|
13
|
+
The framework uses:
|
|
14
|
+
- **Singleton patterns** for shared services (`CacheManager.getInstance()`, `EntityManager.instance`, `ComponentRegistry`)
|
|
15
|
+
- **Global exports** for database (`import db from "database"`) and logger
|
|
16
|
+
- **ApplicationLifecycle phases** for managing initialization order
|
|
17
|
+
- **Metadata-driven decorators** for component/service registration
|
|
18
|
+
|
|
19
|
+
## Rationale
|
|
20
|
+
|
|
21
|
+
### Why DI Was Considered
|
|
22
|
+
- Testing pain points: type-unsafe hacks like `(EntityManager as any).dbReady = true`
|
|
23
|
+
- Hard to mock/swap implementations in tests
|
|
24
|
+
- Singletons share global state between tests
|
|
25
|
+
|
|
26
|
+
### Why DI Was Rejected (For Now)
|
|
27
|
+
|
|
28
|
+
1. **Framework is experimental (v0.1.5)** - Too early for such fundamental architectural changes
|
|
29
|
+
|
|
30
|
+
2. **Added complexity outweighs benefits** - DI adds another abstraction layer to an already complex ECS + GraphQL framework
|
|
31
|
+
|
|
32
|
+
3. **Current approach works** - ApplicationLifecycle phases already manage dependency initialization order effectively
|
|
33
|
+
|
|
34
|
+
4. **Users don't need to swap implementations** - Extensions happen via Components, Services, and Plugins, none of which benefit significantly from DI
|
|
35
|
+
|
|
36
|
+
5. **Testing pain can be solved simpler** - Lightweight patterns like `reset()` methods or optional instance injection suffice
|
|
37
|
+
|
|
38
|
+
6. **Bun ecosystem norms** - DI isn't a common pattern in modern Bun/TypeScript frameworks
|
|
39
|
+
|
|
40
|
+
7. **Runtime overhead** - Relevant concern for a performance-focused framework
|
|
41
|
+
|
|
42
|
+
## Alternative: Lightweight Testability Pattern
|
|
43
|
+
|
|
44
|
+
Instead of full DI, use optional instance injection for testability:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
class CacheManager {
|
|
48
|
+
private static _instance: CacheManager | null = null;
|
|
49
|
+
|
|
50
|
+
static getInstance(): CacheManager {
|
|
51
|
+
return this._instance ??= new CacheManager();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// For testing only
|
|
55
|
+
static setInstance(instance: CacheManager | null): void {
|
|
56
|
+
this._instance = instance;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## When to Revisit
|
|
62
|
+
|
|
63
|
+
Consider DI if/when:
|
|
64
|
+
- Framework reaches v1.0 with stable APIs
|
|
65
|
+
- Users request ability to swap implementations
|
|
66
|
+
- Codebase grows significantly larger (200+ files)
|
|
67
|
+
- Multiple database/cache backends become first-class options
|
|
68
|
+
|
|
69
|
+
## Related Files
|
|
70
|
+
|
|
71
|
+
- `core/cache/CacheManager.ts` - Singleton cache manager
|
|
72
|
+
- `core/EntityManager.ts` - Singleton entity manager
|
|
73
|
+
- `core/components/ComponentRegistry.ts` - Singleton component registry
|
|
74
|
+
- `service/ServiceRegistry.ts` - Singleton service registry
|
|
75
|
+
- `core/ApplicationLifecycle.ts` - Lifecycle phase management
|
|
76
|
+
- `database/index.ts` - Global database export
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Project Architecture
|
|
2
|
+
|
|
3
|
+
## Directory Structure
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
bunsane/
|
|
7
|
+
├── core/ # Core framework
|
|
8
|
+
│ ├── App.ts # Main application entry point
|
|
9
|
+
│ ├── Entity.ts # Entity class (base data unit)
|
|
10
|
+
│ ├── EntityManager.ts # Entity lifecycle management
|
|
11
|
+
│ ├── ArcheType.ts # Entity templates with component definitions
|
|
12
|
+
│ ├── BatchLoader.ts # DataLoader for batching DB queries
|
|
13
|
+
│ ├── Config.ts # Configuration management
|
|
14
|
+
│ ├── Logger.ts # Pino logging setup
|
|
15
|
+
│ ├── ErrorHandler.ts # Error handling utilities
|
|
16
|
+
│ ├── RequestContext.ts # Request-scoped context
|
|
17
|
+
│ ├── ApplicationLifecycle.ts # App state management
|
|
18
|
+
│ ├── cache/ # Caching system
|
|
19
|
+
│ │ ├── CacheManager.ts # Main cache orchestration
|
|
20
|
+
│ │ ├── CacheProvider.ts # Standard interface (all providers implement this)
|
|
21
|
+
│ │ ├── MemoryCache.ts # In-memory cache provider
|
|
22
|
+
│ │ ├── RedisCache.ts # Redis cache provider
|
|
23
|
+
│ │ ├── MultiLevelCache.ts # L1/L2 cache strategy (wrapper)
|
|
24
|
+
│ │ ├── CacheAnalytics.ts # Analytics wrapper provider
|
|
25
|
+
│ │ ├── TTLStrategy.ts # Adaptive TTL wrapper provider
|
|
26
|
+
│ │ └── ...
|
|
27
|
+
│ ├── components/ # Component system
|
|
28
|
+
│ │ ├── BaseComponent.ts # Base class for components
|
|
29
|
+
│ │ ├── ComponentRegistry.ts # Component registration
|
|
30
|
+
│ │ ├── Decorators.ts # @Component, @CompData decorators
|
|
31
|
+
│ │ └── ...
|
|
32
|
+
│ ├── decorators/ # Additional decorators
|
|
33
|
+
│ ├── events/ # Event system
|
|
34
|
+
│ └── metadata/ # Metadata utilities
|
|
35
|
+
├── database/ # Database layer
|
|
36
|
+
│ ├── index.ts # PostgreSQL connection (postgres.js)
|
|
37
|
+
│ ├── DatabaseHelper.ts # DB setup and migrations
|
|
38
|
+
│ ├── PreparedStatementCache.ts # Query caching
|
|
39
|
+
│ └── IndexingStrategy.ts # Index management
|
|
40
|
+
├── query/ # Query builder
|
|
41
|
+
│ ├── Query.ts # Main query class
|
|
42
|
+
│ ├── FilterBuilder.ts # Filter construction
|
|
43
|
+
│ ├── QueryDAG.ts # Query execution graph
|
|
44
|
+
│ └── ...
|
|
45
|
+
├── gql/ # GraphQL generation
|
|
46
|
+
│ ├── Generator.ts # Schema generation
|
|
47
|
+
│ ├── builders/ # Type/resolver builders
|
|
48
|
+
│ ├── decorators/ # GQL decorators
|
|
49
|
+
│ ├── strategies/ # Type generation strategies
|
|
50
|
+
│ └── visitors/ # Schema visitors
|
|
51
|
+
├── service/ # Service layer
|
|
52
|
+
│ ├── Service.ts # Base service class
|
|
53
|
+
│ └── ServiceRegistry.ts # Service registration
|
|
54
|
+
├── plugins/ # Plugin system
|
|
55
|
+
├── scheduler/ # Task scheduling
|
|
56
|
+
├── storage/ # File storage
|
|
57
|
+
├── upload/ # File upload handling
|
|
58
|
+
├── rest/ # REST endpoint support
|
|
59
|
+
├── swagger/ # OpenAPI documentation
|
|
60
|
+
├── studio/ # BunSane Studio (web UI)
|
|
61
|
+
├── test/ # Tests
|
|
62
|
+
│ ├── setup.ts # Test environment setup
|
|
63
|
+
│ ├── integration/ # Integration tests
|
|
64
|
+
│ └── gql/ # GraphQL tests
|
|
65
|
+
├── types/ # Type definitions
|
|
66
|
+
└── utils/ # Utility functions
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Core Concepts Flow
|
|
70
|
+
|
|
71
|
+
1. **App** initializes the application, sets up GraphQL Yoga server
|
|
72
|
+
2. **Components** are registered via `@Component` decorator
|
|
73
|
+
3. **Entities** are created and manipulated, storing component data
|
|
74
|
+
4. **ArcheTypes** define entity templates for type-safe component access
|
|
75
|
+
5. **Query** builder retrieves entities with filters and component population
|
|
76
|
+
6. **Services** define business logic and auto-generate GraphQL resolvers
|
|
77
|
+
7. **CacheManager** handles caching at entity/component/query levels
|
|
78
|
+
|
|
79
|
+
## Cache System Architecture
|
|
80
|
+
|
|
81
|
+
All cache providers implement the standardized `CacheProvider` interface:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
interface CacheProvider {
|
|
85
|
+
get<T>(key: string): Promise<T | null>;
|
|
86
|
+
set<T>(key: string, value: T, ttl?: number): Promise<void>;
|
|
87
|
+
delete(key: string | string[]): Promise<void>; // Supports single or multiple
|
|
88
|
+
clear(): Promise<void>;
|
|
89
|
+
getMany<T>(keys: string[]): Promise<(T | null)[]>; // Returns ordered array
|
|
90
|
+
setMany<T>(entries: Array<{key, value, ttl?}>): Promise<void>; // Per-entry TTL
|
|
91
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
92
|
+
invalidatePattern(pattern: string): Promise<void>;
|
|
93
|
+
ping(): Promise<boolean>; // Health check
|
|
94
|
+
getStats(): Promise<CacheStats>; // Metrics
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Cache Providers**:
|
|
99
|
+
- **MemoryCache**: In-memory LRU cache (base implementation)
|
|
100
|
+
- **RedisCache**: Redis-backed cache (base implementation)
|
|
101
|
+
- **MultiLevelCacheProvider**: L1 (memory) + L2 (Redis) wrapper
|
|
102
|
+
- **AnalyticsCacheProvider**: Metrics and latency tracking wrapper
|
|
103
|
+
- **AdaptiveTTLProvider**: Dynamic TTL adjustment wrapper
|
|
104
|
+
|
|
105
|
+
**Key Design Decisions** (as of 2026-01-24):
|
|
106
|
+
- Batch operations use arrays instead of Maps for ordering and flexibility
|
|
107
|
+
- `delete()` accepts both single string and string array for convenience
|
|
108
|
+
- `ping()` replaces `healthCheck()` for conventional naming
|
|
109
|
+
- All wrappers maintain full interface compliance
|
|
110
|
+
|
|
111
|
+
## Import Resolution (as of 2026-02-05)
|
|
112
|
+
|
|
113
|
+
All internal imports use **relative paths** (`./`, `../`). Bare imports like `from "core/Logger"` that rely on `baseUrl` are NOT allowed because they break TypeScript type checking for consumers who install bunsane as a dependency (their tsconfig does not have baseUrl pointing to bunsane root).
|
|
114
|
+
|
|
115
|
+
## Data Model
|
|
116
|
+
|
|
117
|
+
- **Entity**: UUID-identified record in `entities` table
|
|
118
|
+
- **Component**: JSONB data in `components` table, linked to entity
|
|
119
|
+
- Components are identified by `entity_id` + `component_type`
|
|
120
|
+
- Supports indexing specific component fields for queries
|
|
121
|
+
|
|
122
|
+
## CORS System (as of 2026-02-04)
|
|
123
|
+
|
|
124
|
+
The App class (`core/App.ts`) provides comprehensive CORS support with proper spec compliance.
|
|
125
|
+
|
|
126
|
+
**CorsConfig Type**:
|
|
127
|
+
```typescript
|
|
128
|
+
type CorsConfig = {
|
|
129
|
+
origin?: string | string[] | ((origin: string) => boolean);
|
|
130
|
+
credentials?: boolean;
|
|
131
|
+
allowedHeaders?: string[];
|
|
132
|
+
exposedHeaders?: string[]; // For Access-Control-Expose-Headers
|
|
133
|
+
methods?: string[];
|
|
134
|
+
maxAge?: number; // Preflight cache duration in seconds
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Key Features**:
|
|
139
|
+
- **Origin Validation**: Validates request Origin header against configured origins
|
|
140
|
+
- **Array Origins**: Returns the matching origin (not comma-joined) per spec
|
|
141
|
+
- **Function Origins**: Supports `(origin: string) => boolean` for dynamic validation
|
|
142
|
+
- **Credentials + Wildcard**: When credentials=true with origin="*", reflects actual origin instead of wildcard
|
|
143
|
+
- **Vary Header**: Always includes `Vary: Origin` for proper caching
|
|
144
|
+
- **All Endpoints**: CORS headers applied to all response paths (health, docs, openapi, studio, errors)
|
|
145
|
+
|
|
146
|
+
**Usage**:
|
|
147
|
+
```typescript
|
|
148
|
+
app.setCors({
|
|
149
|
+
origin: ["http://localhost:3000", "https://myapp.com"],
|
|
150
|
+
credentials: true,
|
|
151
|
+
maxAge: 86400,
|
|
152
|
+
exposedHeaders: ["X-Custom-Header"]
|
|
153
|
+
});
|
|
154
|
+
```
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Cache Interface Refactoring - January 24, 2026
|
|
2
|
+
|
|
3
|
+
## Status: COMPLETED
|
|
4
|
+
**Completion Date**: 2026-01-24
|
|
5
|
+
**Outcome**: Successfully standardized CacheProvider interface implementation across all cache-related files
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
Fixed TypeScript compilation errors caused by mismatches between the `CacheProvider` interface and its implementations. The interface was correct, but several wrapper classes and test files had outdated method signatures.
|
|
9
|
+
|
|
10
|
+
## Impact
|
|
11
|
+
- **Errors Reduced**: From 100+ TypeScript errors to 69
|
|
12
|
+
- **Cache Errors**: Fully resolved (0 remaining)
|
|
13
|
+
- **Remaining Errors**: Unrelated to cache (SchedulerManager, GraphQL builders, test access to private members)
|
|
14
|
+
|
|
15
|
+
## Files Modified
|
|
16
|
+
|
|
17
|
+
### Core Cache Files (3 files)
|
|
18
|
+
|
|
19
|
+
#### 1. `core/cache/CacheAnalytics.ts`
|
|
20
|
+
**Class**: `AnalyticsCacheProvider`
|
|
21
|
+
|
|
22
|
+
Changes:
|
|
23
|
+
- Changed import to type-only import: `import type { CacheProvider } from './CacheProvider'`
|
|
24
|
+
- Made `recordLatency` method public
|
|
25
|
+
- Fixed method signatures:
|
|
26
|
+
- `delete(key: string | string[]): Promise<void>` (was single key only)
|
|
27
|
+
- `getMany<T>(keys: string[]): Promise<(T | null)[]>` (was returning Map)
|
|
28
|
+
- `setMany<T>(entries: Array<{key, value, ttl?}>): Promise<void>` (was using Map)
|
|
29
|
+
- `deleteMany(keys: string[]): Promise<void>` (added proper typing)
|
|
30
|
+
- `ping(): Promise<boolean>` (replaced `healthCheck()`)
|
|
31
|
+
- `getStats(): Promise<CacheStats>` (was async but not typed correctly)
|
|
32
|
+
- Removed `has()` method (not in interface)
|
|
33
|
+
|
|
34
|
+
#### 2. `core/cache/MultiLevelCache.ts`
|
|
35
|
+
**Class**: `MultiLevelCacheProvider`
|
|
36
|
+
|
|
37
|
+
Changes:
|
|
38
|
+
- Fixed import path and made type-only
|
|
39
|
+
- Applied same method signature fixes as CacheAnalytics
|
|
40
|
+
- Added proper type guards for array access in `delete()` method
|
|
41
|
+
- Ensured L1/L2 cache coordination respects new interface
|
|
42
|
+
|
|
43
|
+
#### 3. `core/cache/TTLStrategy.ts`
|
|
44
|
+
**Class**: `AdaptiveTTLProvider`
|
|
45
|
+
|
|
46
|
+
Changes:
|
|
47
|
+
- Applied same method signature fixes as above
|
|
48
|
+
- Ensured TTL adaptation logic works with updated interface
|
|
49
|
+
|
|
50
|
+
### Config Files (1 file)
|
|
51
|
+
|
|
52
|
+
#### 4. `config/cache.config.ts`
|
|
53
|
+
|
|
54
|
+
Changes:
|
|
55
|
+
- Added `'multilevel'` to provider type union
|
|
56
|
+
- Added `query` property with structure:
|
|
57
|
+
```typescript
|
|
58
|
+
query: {
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
ttl: number;
|
|
61
|
+
maxSize: number;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Test Files (7 files)
|
|
66
|
+
|
|
67
|
+
#### 5. `tests/unit/cache/MemoryCache.test.ts`
|
|
68
|
+
- Added explicit type parameters to `cache.get<T>()` calls
|
|
69
|
+
- Ensures type safety in test assertions
|
|
70
|
+
|
|
71
|
+
#### 6. `tests/unit/cache/RedisCache.test.ts`
|
|
72
|
+
- Added explicit type parameters to `cache.get<T>()` calls
|
|
73
|
+
|
|
74
|
+
#### 7-11. Test Configuration Files
|
|
75
|
+
Added `maxSize` to query config objects in:
|
|
76
|
+
- `tests/integration/cache/CacheInvalidation.test.ts`
|
|
77
|
+
- `tests/setup.ts`
|
|
78
|
+
- `tests/stress/cursor-perf-test.ts`
|
|
79
|
+
- `tests/unit/cache/CacheManager.test.ts`
|
|
80
|
+
- `tests/utils/test-context.ts`
|
|
81
|
+
|
|
82
|
+
## Key Interface Contract
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
interface CacheProvider {
|
|
86
|
+
// Single operations
|
|
87
|
+
get<T>(key: string): Promise<T | null>;
|
|
88
|
+
set<T>(key: string, value: T, ttl?: number): Promise<void>;
|
|
89
|
+
delete(key: string | string[]): Promise<void>;
|
|
90
|
+
clear(): Promise<void>;
|
|
91
|
+
|
|
92
|
+
// Batch operations
|
|
93
|
+
getMany<T>(keys: string[]): Promise<(T | null)[]>;
|
|
94
|
+
setMany<T>(entries: Array<{key: string, value: T, ttl?: number}>): Promise<void>;
|
|
95
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
96
|
+
|
|
97
|
+
// Pattern operations
|
|
98
|
+
invalidatePattern(pattern: string): Promise<void>;
|
|
99
|
+
|
|
100
|
+
// Health and metrics
|
|
101
|
+
ping(): Promise<boolean>;
|
|
102
|
+
getStats(): Promise<CacheStats>;
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Critical Design Decisions
|
|
107
|
+
|
|
108
|
+
### 1. Array Return for getMany
|
|
109
|
+
**Decision**: `getMany` returns `Promise<(T | null)[]>` instead of `Map<string, T | null>`
|
|
110
|
+
**Rationale**:
|
|
111
|
+
- Maintains order of requested keys
|
|
112
|
+
- Simpler type handling
|
|
113
|
+
- Better performance for indexed access
|
|
114
|
+
|
|
115
|
+
### 2. Entry Array for setMany
|
|
116
|
+
**Decision**: `setMany` takes `Array<{key, value, ttl?}>` instead of `Map`
|
|
117
|
+
**Rationale**:
|
|
118
|
+
- Supports per-entry TTL configuration
|
|
119
|
+
- More flexible than Map-based approach
|
|
120
|
+
- Aligns with common cache API patterns
|
|
121
|
+
|
|
122
|
+
### 3. Flexible Delete
|
|
123
|
+
**Decision**: `delete(key: string | string[])` accepts both single and multiple keys
|
|
124
|
+
**Rationale**:
|
|
125
|
+
- Reduces API surface area (no need for separate deleteOne/deleteMany)
|
|
126
|
+
- Convenience for common use cases
|
|
127
|
+
- Backward compatible with single-key usage
|
|
128
|
+
|
|
129
|
+
### 4. Ping Instead of HealthCheck
|
|
130
|
+
**Decision**: Renamed `healthCheck()` to `ping()`
|
|
131
|
+
**Rationale**:
|
|
132
|
+
- Shorter, more conventional name
|
|
133
|
+
- Matches Redis and memcached naming
|
|
134
|
+
- Clearer intent (simple connectivity check)
|
|
135
|
+
|
|
136
|
+
## Verification
|
|
137
|
+
|
|
138
|
+
### TypeScript Compilation
|
|
139
|
+
- All cache-related files now compile without errors
|
|
140
|
+
- Type safety enforced across all implementations
|
|
141
|
+
- No type assertions or `any` types introduced
|
|
142
|
+
|
|
143
|
+
### Interface Compliance
|
|
144
|
+
All three wrapper implementations now fully comply:
|
|
145
|
+
- AnalyticsCacheProvider (wraps any provider with metrics)
|
|
146
|
+
- MultiLevelCacheProvider (L1/L2 cache coordination)
|
|
147
|
+
- AdaptiveTTLProvider (dynamic TTL adjustment)
|
|
148
|
+
|
|
149
|
+
## Follow-Up Items
|
|
150
|
+
|
|
151
|
+
None for cache. Remaining TypeScript errors are in:
|
|
152
|
+
1. **SchedulerManager**: Unrelated to cache
|
|
153
|
+
2. **GraphQL builders**: Schema generation issues
|
|
154
|
+
3. **Test files**: Access to private members (test-specific issues)
|
|
155
|
+
|
|
156
|
+
## Lessons Learned
|
|
157
|
+
|
|
158
|
+
1. **Interface-First Design**: Having a well-defined interface is only half the battle; keeping implementations in sync is critical
|
|
159
|
+
2. **Type-Only Imports**: Using `import type` helps clarify when you're only referencing types vs. runtime values
|
|
160
|
+
3. **Batch Operations**: The switch from Map to Array for batch ops required careful consideration of ordering and flexibility
|
|
161
|
+
4. **Test Coverage**: Tests that use explicit type parameters catch more type mismatches earlier
|
|
162
|
+
|
|
163
|
+
## Related Memories
|
|
164
|
+
- See `architecture` for overall cache system design
|
|
165
|
+
- See `code_style_and_conventions` for TypeScript patterns used
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Code Style and Conventions
|
|
2
|
+
|
|
3
|
+
## Formatting
|
|
4
|
+
- **Indentation**: 4 spaces (configured in `.prettierrc`)
|
|
5
|
+
- **No tabs**: Spaces only
|
|
6
|
+
- **Prettier**: Used for formatting
|
|
7
|
+
|
|
8
|
+
## TypeScript Configuration
|
|
9
|
+
- **Strict mode**: Enabled
|
|
10
|
+
- **Experimental decorators**: Enabled
|
|
11
|
+
- **Emit decorator metadata**: Enabled
|
|
12
|
+
- **Module**: ESNext/Preserve
|
|
13
|
+
- **Path alias**: `@/*` maps to `./*`
|
|
14
|
+
|
|
15
|
+
## Naming Conventions
|
|
16
|
+
- **Classes**: PascalCase (e.g., `Entity`, `BaseComponent`, `CacheManager`)
|
|
17
|
+
- **Methods/Functions**: camelCase (e.g., `createEntity`, `getEntityWithID`)
|
|
18
|
+
- **Variables**: camelCase
|
|
19
|
+
- **Constants**: camelCase or UPPER_SNAKE_CASE for environment-like values
|
|
20
|
+
- **Private properties**: Prefix with underscore (e.g., `_dirty`, `_persisted`)
|
|
21
|
+
- **Interfaces**: PascalCase, often prefixed with `I` (e.g., `IEntity`)
|
|
22
|
+
- **Types**: PascalCase
|
|
23
|
+
|
|
24
|
+
## Decorators Usage
|
|
25
|
+
The framework heavily uses TypeScript decorators:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Component definition
|
|
29
|
+
@Component
|
|
30
|
+
class MyComponent extends BaseComponent {
|
|
31
|
+
@CompData()
|
|
32
|
+
myField!: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ArcheType definition
|
|
36
|
+
class MyArcheType extends BaseArcheType {
|
|
37
|
+
@ArcheTypeField(MyComponent)
|
|
38
|
+
myComponent!: MyComponent;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Import Style
|
|
43
|
+
- **ALWAYS use relative imports** (`./`, `../`) for all internal modules
|
|
44
|
+
- Do NOT use bare imports like `from "core/Logger"` - they rely on `baseUrl` and break consumer typechecking
|
|
45
|
+
- The `@/` path alias is configured but not used in practice; prefer relative imports
|
|
46
|
+
- Group imports: external packages first, then internal modules
|
|
47
|
+
- **Type-only imports**: Use `import type` for interface/type imports when only used for type checking:
|
|
48
|
+
```typescript
|
|
49
|
+
import type { CacheProvider } from './CacheProvider';
|
|
50
|
+
```
|
|
51
|
+
Benefits: Clearer intent, reduced runtime dependencies, better tree-shaking
|
|
52
|
+
|
|
53
|
+
## Testing Conventions
|
|
54
|
+
- Test files: `*.test.ts`
|
|
55
|
+
- Use Bun's built-in test runner (`bun:test`)
|
|
56
|
+
- Structure: `describe` blocks for grouping, `test` for individual cases
|
|
57
|
+
- Use `beforeAll`/`afterAll` for setup/cleanup
|
|
58
|
+
- Integration tests should clean up created entities
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { describe, test, expect, beforeAll, afterAll } from 'bun:test';
|
|
62
|
+
|
|
63
|
+
describe('FeatureName', () => {
|
|
64
|
+
beforeAll(async () => { /* setup */ });
|
|
65
|
+
afterAll(async () => { /* cleanup */ });
|
|
66
|
+
|
|
67
|
+
test('should do something', async () => {
|
|
68
|
+
expect(result).toBe(expected);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Documentation
|
|
74
|
+
- Use JSDoc comments for public APIs
|
|
75
|
+
- Block comments for file headers explaining purpose
|
|
76
|
+
- Inline comments sparingly, only when logic is complex
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# BunSane Project Overview
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
BunSane is a batteries-included TypeScript API framework for Bun with:
|
|
5
|
+
- Entity–Component storage on PostgreSQL (auto-migrates base tables on first run)
|
|
6
|
+
- Fluent, performant Query builder
|
|
7
|
+
- Zero-boilerplate GraphQL with GraphQL Yoga
|
|
8
|
+
- Declarative Components with decorators and indexed fields
|
|
9
|
+
|
|
10
|
+
**Status**: EXPERIMENTAL - Not Production Ready
|
|
11
|
+
|
|
12
|
+
## Tech Stack
|
|
13
|
+
- **Runtime**: Bun
|
|
14
|
+
- **Language**: TypeScript 5.9+ (strict mode, experimental decorators)
|
|
15
|
+
- **Database**: PostgreSQL
|
|
16
|
+
- **GraphQL**: GraphQL Yoga + GQLoom (@gqloom/core, @gqloom/zod)
|
|
17
|
+
- **Validation**: Zod 4.x
|
|
18
|
+
- **Logging**: Pino (with pino-pretty for development)
|
|
19
|
+
- **Cache**: Memory and Redis support (ioredis)
|
|
20
|
+
- **Data Loading**: dataloader for batching
|
|
21
|
+
|
|
22
|
+
## Key Concepts
|
|
23
|
+
1. **Entity**: Base unit of data storage, identified by UUID
|
|
24
|
+
2. **Component**: Data attached to entities (decorators: @Component, @CompData)
|
|
25
|
+
3. **ArcheType**: Defines a template of components an entity should have
|
|
26
|
+
4. **Query**: Fluent query builder for retrieving entities with components
|
|
27
|
+
5. **Service**: Business logic layer with auto-generated GraphQL schema
|
|
28
|
+
|
|
29
|
+
## Environment Variables
|
|
30
|
+
Database configuration via environment variables:
|
|
31
|
+
- `POSTGRES_HOST`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`
|
|
32
|
+
- `POSTGRES_MAX_CONNECTIONS`
|
|
33
|
+
- `LOG_LEVEL`, `LOG_PRETTY`
|
|
34
|
+
|
|
35
|
+
## Cache Configuration
|
|
36
|
+
Cache system supports multiple providers (configured in `config/cache.config.ts`):
|
|
37
|
+
- **Providers**: `memory`, `redis`, `multilevel`
|
|
38
|
+
- **Query cache**: Can be enabled with configurable TTL and max size
|
|
39
|
+
- All providers implement standardized `CacheProvider` interface
|
|
40
|
+
- Wrapper providers available: Analytics, MultiLevel, AdaptiveTTL
|
|
41
|
+
|
|
42
|
+
## Repository
|
|
43
|
+
https://github.com/yaaruu/bunsane
|