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.
Files changed (257) hide show
  1. package/.claude/settings.local.json +47 -0
  2. package/.claude/skills/update-memory.md +74 -0
  3. package/.prettierrc +4 -0
  4. package/.serena/memories/architectural-decision-no-dependency-injection.md +76 -0
  5. package/.serena/memories/architecture.md +154 -0
  6. package/.serena/memories/cache-interface-refactoring-2026-01-24.md +165 -0
  7. package/.serena/memories/code_style_and_conventions.md +76 -0
  8. package/.serena/memories/project_overview.md +43 -0
  9. package/.serena/memories/schema-dsl-plan.md +107 -0
  10. package/.serena/memories/suggested_commands.md +80 -0
  11. package/.serena/memories/typescript-compilation-status.md +54 -0
  12. package/.serena/project.yml +114 -0
  13. package/TODO.md +1 -7
  14. package/bun.lock +150 -4
  15. package/bunfig.toml +10 -0
  16. package/config/cache.config.ts +77 -0
  17. package/config/upload.config.ts +4 -5
  18. package/core/App.ts +870 -123
  19. package/core/ArcheType.ts +2268 -377
  20. package/core/BatchLoader.ts +181 -71
  21. package/core/Config.ts +153 -0
  22. package/core/Decorators.ts +4 -1
  23. package/core/Entity.ts +621 -92
  24. package/core/EntityHookManager.ts +1 -1
  25. package/core/EntityInterface.ts +3 -1
  26. package/core/EntityManager.ts +1 -13
  27. package/core/ErrorHandler.ts +8 -2
  28. package/core/Logger.ts +9 -0
  29. package/core/Middleware.ts +34 -0
  30. package/core/RequestContext.ts +5 -1
  31. package/core/RequestLoaders.ts +227 -93
  32. package/core/SchedulerManager.ts +193 -52
  33. package/core/cache/CacheAnalytics.ts +399 -0
  34. package/core/cache/CacheFactory.ts +145 -0
  35. package/core/cache/CacheManager.ts +520 -0
  36. package/core/cache/CacheProvider.ts +34 -0
  37. package/core/cache/CacheWarmer.ts +157 -0
  38. package/core/cache/CompressionUtils.ts +110 -0
  39. package/core/cache/MemoryCache.ts +251 -0
  40. package/core/cache/MultiLevelCache.ts +180 -0
  41. package/core/cache/NoOpCache.ts +53 -0
  42. package/core/cache/RedisCache.ts +464 -0
  43. package/core/cache/TTLStrategy.ts +254 -0
  44. package/core/cache/index.ts +6 -0
  45. package/core/components/BaseComponent.ts +120 -0
  46. package/core/{ComponentRegistry.ts → components/ComponentRegistry.ts} +148 -54
  47. package/core/components/Decorators.ts +88 -0
  48. package/core/components/Interfaces.ts +7 -0
  49. package/core/components/index.ts +5 -0
  50. package/core/decorators/EntityHooks.ts +0 -3
  51. package/core/decorators/IndexedField.ts +26 -0
  52. package/core/decorators/ScheduledTask.ts +0 -47
  53. package/core/events/EntityLifecycleEvents.ts +1 -1
  54. package/core/health.ts +112 -0
  55. package/core/metadata/definitions/ArcheType.ts +14 -0
  56. package/core/metadata/definitions/Component.ts +9 -0
  57. package/core/metadata/definitions/gqlObject.ts +1 -1
  58. package/core/metadata/index.ts +42 -1
  59. package/core/metadata/metadata-storage.ts +28 -2
  60. package/core/middleware/AccessLog.ts +59 -0
  61. package/core/middleware/RequestId.ts +38 -0
  62. package/core/middleware/SecurityHeaders.ts +62 -0
  63. package/core/middleware/index.ts +3 -0
  64. package/core/scheduler/DistributedLock.ts +266 -0
  65. package/core/scheduler/index.ts +15 -0
  66. package/core/validateEnv.ts +92 -0
  67. package/database/DatabaseHelper.ts +416 -40
  68. package/database/IndexingStrategy.ts +342 -0
  69. package/database/PreparedStatementCache.ts +226 -0
  70. package/database/index.ts +32 -7
  71. package/database/sqlHelpers.ts +14 -2
  72. package/endpoints/archetypes.ts +362 -0
  73. package/endpoints/components.ts +58 -0
  74. package/endpoints/entity.ts +80 -0
  75. package/endpoints/index.ts +27 -0
  76. package/endpoints/query.ts +93 -0
  77. package/endpoints/stats.ts +76 -0
  78. package/endpoints/tables.ts +212 -0
  79. package/endpoints/types.ts +155 -0
  80. package/gql/ArchetypeOperations.ts +32 -86
  81. package/gql/Generator.ts +27 -315
  82. package/gql/GeneratorV2.ts +37 -0
  83. package/gql/builders/InputTypeBuilder.ts +99 -0
  84. package/gql/builders/ResolverBuilder.ts +234 -0
  85. package/gql/builders/TypeDefBuilder.ts +105 -0
  86. package/gql/builders/index.ts +3 -0
  87. package/gql/decorators/Upload.ts +1 -1
  88. package/gql/depthLimit.ts +85 -0
  89. package/gql/graph/GraphNode.ts +224 -0
  90. package/gql/graph/SchemaGraph.ts +278 -0
  91. package/gql/helpers.ts +8 -2
  92. package/gql/index.ts +56 -4
  93. package/gql/middleware.ts +79 -0
  94. package/gql/orchestration/GraphQLSchemaOrchestrator.ts +241 -0
  95. package/gql/orchestration/index.ts +1 -0
  96. package/gql/scanner/ServiceScanner.ts +347 -0
  97. package/gql/schema/index.ts +458 -0
  98. package/gql/strategies/TypeGenerationStrategy.ts +329 -0
  99. package/gql/types.ts +1 -0
  100. package/gql/utils/TypeSignature.ts +220 -0
  101. package/gql/utils/index.ts +1 -0
  102. package/gql/visitors/ArchetypePreprocessorVisitor.ts +80 -0
  103. package/gql/visitors/DeduplicationVisitor.ts +82 -0
  104. package/gql/visitors/GraphVisitor.ts +78 -0
  105. package/gql/visitors/ResolverGeneratorVisitor.ts +122 -0
  106. package/gql/visitors/SchemaGeneratorVisitor.ts +851 -0
  107. package/gql/visitors/TypeCollectorVisitor.ts +79 -0
  108. package/gql/visitors/VisitorComposer.ts +96 -0
  109. package/gql/visitors/index.ts +7 -0
  110. package/package.json +59 -37
  111. package/plugins/index.ts +2 -2
  112. package/query/CTENode.ts +97 -0
  113. package/query/ComponentInclusionNode.ts +689 -0
  114. package/query/FilterBuilder.ts +127 -0
  115. package/query/FilterBuilderRegistry.ts +202 -0
  116. package/query/OrNode.ts +517 -0
  117. package/query/OrQuery.ts +42 -0
  118. package/query/Query.ts +1022 -0
  119. package/query/QueryContext.ts +170 -0
  120. package/query/QueryDAG.ts +122 -0
  121. package/query/QueryNode.ts +65 -0
  122. package/query/SourceNode.ts +53 -0
  123. package/query/builders/FullTextSearchBuilder.ts +236 -0
  124. package/query/index.ts +21 -0
  125. package/scheduler/index.ts +40 -8
  126. package/service/Service.ts +2 -1
  127. package/service/ServiceRegistry.ts +6 -5
  128. package/{core/storage → storage}/LocalStorageProvider.ts +2 -2
  129. package/storage/S3StorageProvider.ts +316 -0
  130. package/{core/storage → storage}/StorageProvider.ts +7 -3
  131. package/studio/bun.lock +482 -0
  132. package/studio/index.html +13 -0
  133. package/studio/package.json +39 -0
  134. package/studio/postcss.config.js +6 -0
  135. package/studio/src/components/DataTable.tsx +211 -0
  136. package/studio/src/components/Layout.tsx +13 -0
  137. package/studio/src/components/PageContainer.tsx +9 -0
  138. package/studio/src/components/PageHeader.tsx +13 -0
  139. package/studio/src/components/SearchBar.tsx +57 -0
  140. package/studio/src/components/Sidebar.tsx +294 -0
  141. package/studio/src/components/ui/button.tsx +56 -0
  142. package/studio/src/components/ui/checkbox.tsx +26 -0
  143. package/studio/src/components/ui/input.tsx +25 -0
  144. package/studio/src/hooks/useDataTable.ts +131 -0
  145. package/studio/src/index.css +36 -0
  146. package/studio/src/lib/api.ts +186 -0
  147. package/studio/src/lib/utils.ts +13 -0
  148. package/studio/src/main.tsx +17 -0
  149. package/studio/src/pages/ArcheType.tsx +239 -0
  150. package/studio/src/pages/Components.tsx +124 -0
  151. package/studio/src/pages/EntityInspector.tsx +302 -0
  152. package/studio/src/pages/QueryRunner.tsx +246 -0
  153. package/studio/src/pages/Table.tsx +94 -0
  154. package/studio/src/pages/Welcome.tsx +241 -0
  155. package/studio/src/routes.tsx +45 -0
  156. package/studio/src/store/archeTypeSettings.ts +30 -0
  157. package/studio/src/store/studio.ts +65 -0
  158. package/studio/src/utils/columnHelpers.tsx +114 -0
  159. package/studio/studio-instructions.md +81 -0
  160. package/studio/tailwind.config.js +77 -0
  161. package/studio/tsconfig.json +24 -0
  162. package/studio/utils.ts +54 -0
  163. package/studio/vite.config.js +19 -0
  164. package/swagger/generator.ts +1 -1
  165. package/tests/e2e/http.test.ts +126 -0
  166. package/tests/fixtures/archetypes/TestUserArchetype.ts +21 -0
  167. package/tests/fixtures/components/TestOrder.ts +23 -0
  168. package/tests/fixtures/components/TestProduct.ts +23 -0
  169. package/tests/fixtures/components/TestUser.ts +20 -0
  170. package/tests/fixtures/components/index.ts +6 -0
  171. package/tests/graphql/SchemaGeneration.test.ts +90 -0
  172. package/tests/graphql/builders/ResolverBuilder.test.ts +223 -0
  173. package/tests/graphql/builders/TypeDefBuilder.test.ts +153 -0
  174. package/tests/integration/archetype/ArcheType.persistence.test.ts +241 -0
  175. package/tests/integration/cache/CacheInvalidation.test.ts +259 -0
  176. package/tests/integration/entity/Entity.persistence.test.ts +333 -0
  177. package/tests/integration/query/Query.exec.test.ts +523 -0
  178. package/tests/pglite-setup.ts +61 -0
  179. package/tests/setup.ts +164 -0
  180. package/tests/stress/BenchmarkRunner.ts +203 -0
  181. package/tests/stress/DataSeeder.ts +190 -0
  182. package/tests/stress/StressTestReporter.ts +229 -0
  183. package/tests/stress/cursor-perf-test.ts +171 -0
  184. package/tests/stress/fixtures/StressTestComponents.ts +58 -0
  185. package/tests/stress/index.ts +7 -0
  186. package/tests/stress/scenarios/query-benchmarks.test.ts +285 -0
  187. package/tests/unit/BatchLoader.test.ts +82 -0
  188. package/tests/unit/archetype/ArcheType.test.ts +107 -0
  189. package/tests/unit/cache/CacheManager.test.ts +347 -0
  190. package/tests/unit/cache/MemoryCache.test.ts +260 -0
  191. package/tests/unit/cache/RedisCache.test.ts +411 -0
  192. package/tests/unit/entity/Entity.components.test.ts +244 -0
  193. package/tests/unit/entity/Entity.test.ts +345 -0
  194. package/tests/unit/gql/depthLimit.test.ts +203 -0
  195. package/tests/unit/gql/operationMiddleware.test.ts +293 -0
  196. package/tests/unit/health/Health.test.ts +129 -0
  197. package/tests/unit/middleware/AccessLog.test.ts +37 -0
  198. package/tests/unit/middleware/Middleware.test.ts +98 -0
  199. package/tests/unit/middleware/RequestId.test.ts +54 -0
  200. package/tests/unit/middleware/SecurityHeaders.test.ts +66 -0
  201. package/tests/unit/query/FilterBuilder.test.ts +111 -0
  202. package/tests/unit/query/Query.test.ts +308 -0
  203. package/tests/unit/scheduler/DistributedLock.test.ts +274 -0
  204. package/tests/unit/schema/schema-integration.test.ts +426 -0
  205. package/tests/unit/schema/schema.test.ts +580 -0
  206. package/tests/unit/storage/S3StorageProvider.test.ts +571 -0
  207. package/tests/unit/upload/RestUpload.test.ts +267 -0
  208. package/tests/unit/validateEnv.test.ts +82 -0
  209. package/tests/utils/entity-tracker.ts +57 -0
  210. package/tests/utils/index.ts +13 -0
  211. package/tests/utils/test-context.ts +149 -0
  212. package/tsconfig.json +5 -1
  213. package/types/archetype.types.ts +6 -0
  214. package/types/hooks.types.ts +1 -1
  215. package/types/query.types.ts +110 -0
  216. package/types/scheduler.types.ts +68 -7
  217. package/types/upload.types.ts +1 -0
  218. package/{core → upload}/FileValidator.ts +10 -1
  219. package/upload/RestUpload.ts +130 -0
  220. package/{core/components → upload}/UploadComponent.ts +11 -11
  221. package/{core → upload}/UploadManager.ts +3 -3
  222. package/upload/index.ts +23 -7
  223. package/utils/UploadHelper.ts +27 -6
  224. package/utils/cronParser.ts +16 -6
  225. package/.github/workflows/deploy-docs.yml +0 -57
  226. package/core/Components.ts +0 -202
  227. package/core/EntityCache.ts +0 -15
  228. package/core/Query.ts +0 -880
  229. package/docs/README.md +0 -149
  230. package/docs/_coverpage.md +0 -36
  231. package/docs/_sidebar.md +0 -23
  232. package/docs/api/core.md +0 -568
  233. package/docs/api/hooks.md +0 -554
  234. package/docs/api/index.md +0 -222
  235. package/docs/api/query.md +0 -678
  236. package/docs/api/service.md +0 -744
  237. package/docs/core-concepts/archetypes.md +0 -512
  238. package/docs/core-concepts/components.md +0 -498
  239. package/docs/core-concepts/entity.md +0 -314
  240. package/docs/core-concepts/hooks.md +0 -683
  241. package/docs/core-concepts/query.md +0 -588
  242. package/docs/core-concepts/services.md +0 -647
  243. package/docs/examples/code-examples.md +0 -425
  244. package/docs/getting-started.md +0 -337
  245. package/docs/index.html +0 -97
  246. package/tests/bench/insert.bench.ts +0 -60
  247. package/tests/bench/relations.bench.ts +0 -270
  248. package/tests/bench/sorting.bench.ts +0 -416
  249. package/tests/component-hooks-simple.test.ts +0 -117
  250. package/tests/component-hooks.test.ts +0 -1461
  251. package/tests/component.test.ts +0 -339
  252. package/tests/errorHandling.test.ts +0 -155
  253. package/tests/hooks.test.ts +0 -667
  254. package/tests/query-sorting.test.ts +0 -101
  255. package/tests/query.test.ts +0 -81
  256. package/tests/relations.test.ts +0 -170
  257. package/tests/scheduler.test.ts +0 -724
@@ -1,202 +0,0 @@
1
- import { createHash } from 'crypto';
2
- import "reflect-metadata";
3
- import { logger as MainLogger } from "./Logger";
4
- import ComponentRegistry from "./ComponentRegistry";
5
- import { uuidv7 } from 'utils/uuid';
6
- import { getMetadataStorage } from './metadata';
7
- const logger = MainLogger.child({ scope: "Components" });
8
-
9
- export function generateTypeId(name: string): string {
10
- return createHash('sha256').update(name).digest('hex');
11
- }
12
-
13
- const primitiveTypes = [String, Number, Boolean, Symbol, BigInt];
14
-
15
- //TODO: Continue here
16
- export function CompData(options?: { indexed?: boolean }) {
17
- return (target: any, propertyKey: string) => {
18
- const storage = getMetadataStorage();
19
- const typeId = storage.getComponentId(target.constructor.name);
20
- const propType = Reflect.getMetadata("design:type", target, propertyKey);
21
- let isEnum = !!(Reflect.getMetadata("isEnum", propType));
22
- if (propType.name === 'ServiceType') isEnum = true;
23
- // console.log(`Property ${propertyKey} type:`, propType?.name);
24
- // console.log(`Is Enum:`, isEnum);
25
- let enumValues: string[] | undefined = undefined;
26
- let enumKeys: string[] | undefined = undefined;
27
- if(isEnum) {
28
- const metaEnumValues = Reflect.getMetadata("__enumValues", propType);
29
- const metaEnumKeys = Reflect.getMetadata("__enumKeys", propType);
30
-
31
- if (metaEnumValues && metaEnumKeys) {
32
- enumValues = metaEnumValues;
33
- enumKeys = metaEnumKeys;
34
- } else {
35
- const staticKeys = Object.getOwnPropertyNames(propType).filter(key =>
36
- key !== 'prototype' &&
37
- key !== 'length' &&
38
- key !== 'name' &&
39
- key !== 'isEnum' &&
40
- key !== '__enumValues' &&
41
- key !== '__enumKeys' &&
42
- typeof propType[key] !== 'function' &&
43
- typeof propType[key] !== 'boolean'
44
- );
45
- if (staticKeys.length > 0) {
46
- enumValues = staticKeys.map(key => propType[key]);
47
- enumKeys = staticKeys;
48
- } else {
49
- // Fallback for numeric enums
50
- enumValues = Object.keys(propType).filter(key => !isNaN(Number(key))).map(key => propType[key]);
51
- }
52
- }
53
-
54
- if (propType.name === 'ServiceType' && (!enumValues || enumValues.length === 0)) {
55
- enumValues = ["jek", "car", "food", "package"];
56
- enumKeys = ["BIKE", "CAR", "FOOD", "PACKAGE"];
57
- }
58
-
59
- }
60
- storage.collectComponentPropertyMetadata({
61
- component_id: typeId,
62
- propertyKey: propertyKey,
63
- propertyType: propType,
64
- indexed: options?.indexed ?? false,
65
- isPrimitive: primitiveTypes.includes(propType),
66
- isEnum: isEnum,
67
- enumValues: enumValues,
68
- enumKeys: enumKeys,
69
- })
70
- // Reflect.metadata("compData", { isData: true, indexed: options?.indexed ?? false })(target, propertyKey);
71
- };
72
- }
73
-
74
- // TODO: Component Property Casting
75
- // export enum CompCastingType {
76
- // STRING = "string",
77
- // NUMBER = "number",
78
- // BOOLEAN = "boolean",
79
- // DATE = "date",
80
- // }
81
- // /**
82
- // * Cast property to specific type when loading from database
83
- // * @param type Casting type for the property
84
- // * @returns
85
- // */
86
- // export function Cast(type: CompCastingType) {
87
- // return Reflect.metadata("compCast", { type });
88
- // }
89
-
90
- // Type helper to extract only data properties (excludes methods and private properties)
91
- export type ComponentDataType<T extends BaseComponent> = {
92
- [K in keyof T as T[K] extends Function ? never :
93
- K extends `_${string}` ? never :
94
- K extends 'id' | 'getTypeID' | 'properties' | 'data' | 'save' | 'insert' | 'update' ? never :
95
- K]: T[K];
96
- };
97
-
98
- export function Component<T extends new () => BaseComponent>(target: T): T {
99
- const storage = getMetadataStorage();
100
- const typeId = storage.getComponentId(target.name);
101
- const properties = storage.getComponentProperties(typeId);
102
- // console.log(`Component decorator applied to ${target.name} with typeId ${typeId} and properties:`, properties);
103
- storage.collectComponentMetadata({
104
- name: target.name,
105
- typeId: typeId,
106
- target: target,
107
- });
108
- // ComponentRegistry.define(target.name, target);
109
- return target;
110
- }
111
-
112
- export class BaseComponent {
113
- public id: string = "";
114
- protected _comp_name: string = "";
115
- protected _typeId: string = "";
116
- protected _persisted: boolean = false;
117
- protected _dirty: boolean = false;
118
-
119
- constructor() {
120
- this._comp_name = this.constructor.name;
121
- const storage = getMetadataStorage();
122
- this._typeId = storage.getComponentId(this._comp_name);
123
- this._dirty = false;
124
- }
125
-
126
- getTypeID(): string {
127
- return this._typeId;
128
- }
129
-
130
- properties(): string[] {
131
- const storage = getMetadataStorage();
132
- const props = storage.componentProperties.get(this._typeId);
133
- if(!props) return [];
134
- return props.map(p => p.propertyKey);
135
- //
136
- // return Object.keys(this).filter(prop => {
137
- // const meta = Reflect.getMetadata("compData", Object.getPrototypeOf(this), prop);
138
- // return meta && meta.isData;
139
- // });
140
- }
141
-
142
- /**
143
- * Get data for this component
144
- * @returns Object containing only properties marked with @CompData decorator
145
- */
146
- data<T extends this>(): ComponentDataType<T> {
147
- const data: Record<string, any> = {};
148
- this.properties().forEach((prop: string) => {
149
- data[prop] = (this as any)[prop];
150
- });
151
- return data as ComponentDataType<T>;
152
- }
153
-
154
- async save(trx: Bun.SQL, entity_id: string) {
155
- logger.trace(`Saving component ${this._comp_name} for entity ${entity_id}`);
156
- logger.trace(`Checking is Component can be saved (is registered)`);
157
- await ComponentRegistry.getReadyPromise(this._comp_name);
158
- logger.trace(`Component Registered`);
159
- if(this._persisted) {
160
- await this.update(trx);
161
- } else {
162
- await this.insert(trx, entity_id);
163
- this._persisted = true;
164
- }
165
- }
166
-
167
- async insert(trx: Bun.SQL, entity_id: string) {
168
- if(this.id === "") {
169
- this.id = uuidv7();
170
- }
171
- await trx`INSERT INTO components
172
- (id, entity_id, name, type_id, data)
173
- VALUES (${this.id}, ${entity_id}, ${this._comp_name}, ${this._typeId}, ${this.data()})`
174
- await trx`INSERT INTO entity_components (entity_id, type_id) VALUES (${entity_id}, ${this._typeId}) ON CONFLICT DO NOTHING`
175
- }
176
-
177
- async update(trx: Bun.SQL) {
178
- if(this.id === "") {
179
- throw new Error("Component must have an ID to be updated");
180
- }
181
- await trx`UPDATE components SET data = ${this.data()} WHERE id = ${this.id}`
182
- }
183
-
184
- public setPersisted(persisted: boolean) {
185
- this._persisted = persisted;
186
- }
187
-
188
- public setDirty(dirty: boolean) {
189
- this._dirty = dirty;
190
- }
191
-
192
- indexedProperties(): string[] {
193
- const storage = getMetadataStorage();
194
- const props = storage.componentProperties.get(this._typeId);
195
- if(!props) return [];
196
- return props.filter(p => p.indexed).map(p => p.propertyKey);
197
- }
198
- }
199
-
200
- export type ComponentGetter<T extends BaseComponent> = Pick<T, "properties" | "id"> & {
201
- data(): ComponentDataType<T>;
202
- };
@@ -1,15 +0,0 @@
1
- import type { RequestLoaders, ComponentData } from './RequestLoaders';
2
- import { Entity } from './Entity';
3
-
4
- export async function getEntityById(ctx: { locals: { loaders: RequestLoaders } }, id: string): Promise<Entity | null> {
5
- return ctx.locals.loaders.entityById.load(id);
6
- }
7
-
8
- export async function getComponent(ctx: { locals: { loaders: RequestLoaders } }, entityId: string, typeId: number): Promise<ComponentData | null> {
9
- return ctx.locals.loaders.componentsByEntityType.load({ entityId, typeId });
10
- }
11
-
12
- export async function preloadComponents(ctx: { locals: { loaders: RequestLoaders } }, entityIds: string[], typeId: number): Promise<void> {
13
- const keys = entityIds.map(entityId => ({ entityId, typeId }));
14
- await ctx.locals.loaders.componentsByEntityType.loadMany(keys);
15
- }