bunsane 0.3.0 → 0.3.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 (54) hide show
  1. package/.claude/scheduled_tasks.lock +1 -0
  2. package/CHANGELOG.md +104 -0
  3. package/CLAUDE.md +20 -0
  4. package/config/cache.config.ts +35 -1
  5. package/core/App.ts +24 -1060
  6. package/core/ArcheType.ts +78 -2110
  7. package/core/Entity.ts +136 -41
  8. package/core/RequestContext.ts +85 -36
  9. package/core/RequestLoaders.ts +89 -31
  10. package/core/SchedulerManager.ts +13 -13
  11. package/core/app/bootstrap.ts +133 -0
  12. package/core/app/cors.ts +94 -0
  13. package/core/app/graphqlSetup.ts +56 -0
  14. package/core/app/healthEndpoints.ts +31 -0
  15. package/core/app/metricsCollector.ts +27 -0
  16. package/core/app/preparedStatementWarmup.ts +55 -0
  17. package/core/app/processHandlers.ts +43 -0
  18. package/core/app/requestRouter.ts +309 -0
  19. package/core/app/restRegistry.ts +72 -0
  20. package/core/app/shutdown.ts +97 -0
  21. package/core/app/studioRouter.ts +83 -0
  22. package/core/archetype/customTypes.ts +100 -0
  23. package/core/archetype/decorators.ts +171 -0
  24. package/core/archetype/fieldResolvers.ts +621 -0
  25. package/core/archetype/helpers.ts +29 -0
  26. package/core/archetype/relationLoader.ts +118 -0
  27. package/core/archetype/schemaBuilder.ts +141 -0
  28. package/core/archetype/weaver.ts +218 -0
  29. package/core/archetype/zodSchemaBuilder.ts +527 -0
  30. package/core/cache/CacheManager.ts +144 -9
  31. package/core/components/BaseComponent.ts +12 -2
  32. package/core/middleware/AccessLog.ts +8 -1
  33. package/database/PreparedStatementCache.ts +17 -16
  34. package/database/cancellable.ts +22 -0
  35. package/database/instrumentedDb.ts +141 -0
  36. package/docs/RFC_APP_REFACTOR.md +248 -0
  37. package/docs/RFC_REFACTOR_TARGETS.md +251 -0
  38. package/package.json +1 -1
  39. package/query/ComponentInclusionNode.ts +5 -5
  40. package/query/Query.ts +65 -48
  41. package/service/ServiceRegistry.ts +7 -1
  42. package/service/index.ts +4 -2
  43. package/tests/integration/loaders/RequestLoaders.abort.test.ts +82 -0
  44. package/tests/integration/query/Query.abort.test.ts +66 -0
  45. package/tests/unit/cache/CacheManager.test.ts +152 -1
  46. package/tests/unit/database/cancellable.test.ts +81 -0
  47. package/tests/unit/database/instrumentedDb.test.ts +160 -0
  48. package/tests/unit/entity/Entity.components.test.ts +73 -0
  49. package/tests/unit/entity/Entity.drainSideEffects.test.ts +51 -0
  50. package/tests/unit/entity/Entity.reload.test.ts +63 -0
  51. package/tests/unit/entity/Entity.requireComponents.test.ts +72 -0
  52. package/tests/unit/query/Query.emptyString.test.ts +69 -0
  53. package/tests/unit/query/Query.test.ts +6 -4
  54. package/tests/unit/scheduler/SchedulerManager.timeBased.test.ts +95 -0
@@ -0,0 +1,171 @@
1
+ import type { BaseComponent } from "../components";
2
+ import type { ArcheTypeFieldOptions } from "../metadata/definitions/ArcheType";
3
+ import type { BaseArcheType, ArcheTypeOptions, RelationOptions } from "../ArcheType";
4
+ import { getMetadataStorage } from "../metadata";
5
+ import "reflect-metadata";
6
+
7
+ export const archetypeFunctionsSymbol = Symbol.for("bunsane:archetypeFunctions");
8
+ export const archetypeFieldsSymbol = Symbol.for("bunsane:archetypeFields");
9
+ export const archetypeUnionFieldsSymbol = Symbol.for("bunsane:archetypeUnionFields");
10
+ export const archetypeRelationsSymbol = Symbol.for("bunsane:archetypeRelations");
11
+
12
+ export function ArcheTypeFunction(options?: {
13
+ returnType?: string;
14
+ args?: Array<{
15
+ name: string;
16
+ type: any;
17
+ nullable?: boolean;
18
+ }>;
19
+ }) {
20
+ return function (target: any, propertyKey: string) {
21
+ if (!target[archetypeFunctionsSymbol]) {
22
+ target[archetypeFunctionsSymbol] = [];
23
+ }
24
+ target[archetypeFunctionsSymbol].push({ propertyKey, options });
25
+ };
26
+ }
27
+
28
+ export function ArcheType<T extends new () => BaseArcheType>(
29
+ nameOrOptions?: string | ArcheTypeOptions
30
+ ) {
31
+ return function (target: T): T {
32
+ const storage = getMetadataStorage();
33
+ const typeId = storage.getComponentId(target.name);
34
+
35
+ let archetype_name = target.name;
36
+
37
+ if (typeof nameOrOptions === "string") {
38
+ archetype_name = nameOrOptions;
39
+ } else if (nameOrOptions) {
40
+ archetype_name = nameOrOptions.name || target.name;
41
+ }
42
+
43
+ storage.collectArcheTypeMetadata({
44
+ name: archetype_name,
45
+ typeId: typeId,
46
+ target: target,
47
+ });
48
+
49
+ const prototype = target.prototype;
50
+ const fields = prototype[archetypeFieldsSymbol];
51
+ if (fields) {
52
+ for (const { propertyKey, component, options } of fields) {
53
+ const type = Reflect.getMetadata(
54
+ "design:type",
55
+ target.prototype,
56
+ propertyKey
57
+ );
58
+ storage.collectArchetypeField(
59
+ archetype_name,
60
+ propertyKey,
61
+ component,
62
+ options,
63
+ type
64
+ );
65
+ }
66
+ }
67
+
68
+ const unions = prototype[archetypeUnionFieldsSymbol];
69
+ if (unions) {
70
+ for (const { propertyKey, components, options } of unions) {
71
+ storage.collectArchetypeUnion(
72
+ archetype_name,
73
+ propertyKey,
74
+ components,
75
+ options,
76
+ "union"
77
+ );
78
+ }
79
+ }
80
+
81
+ const relations = prototype[archetypeRelationsSymbol];
82
+ if (relations) {
83
+ for (const {
84
+ propertyKey,
85
+ relatedArcheType,
86
+ relationType,
87
+ options,
88
+ } of relations) {
89
+ const type = Reflect.getMetadata(
90
+ "design:type",
91
+ target.prototype,
92
+ propertyKey
93
+ );
94
+ storage.collectArchetypeRelation(
95
+ archetype_name,
96
+ propertyKey,
97
+ relatedArcheType,
98
+ relationType,
99
+ options,
100
+ type
101
+ );
102
+ }
103
+ }
104
+
105
+ const functions = prototype[archetypeFunctionsSymbol];
106
+ if (functions) {
107
+ storage.collectArcheTypeMetadata({
108
+ name: archetype_name,
109
+ typeId: typeId,
110
+ target: target,
111
+ functions: functions,
112
+ });
113
+ }
114
+
115
+ return target;
116
+ };
117
+ }
118
+
119
+ export function ArcheTypeField<T extends BaseComponent>(
120
+ component: new (...args: any[]) => T,
121
+ options?: ArcheTypeFieldOptions
122
+ ) {
123
+ return function (target: any, propertyKey: string) {
124
+ if (!target[archetypeFieldsSymbol]) {
125
+ target[archetypeFieldsSymbol] = [];
126
+ }
127
+ target[archetypeFieldsSymbol].push({ propertyKey, component, options });
128
+ };
129
+ }
130
+
131
+ export function ArcheTypeUnionField(
132
+ components: (new (...args: any[]) => any)[],
133
+ options?: ArcheTypeFieldOptions
134
+ ) {
135
+ return function (target: any, propertyKey: string) {
136
+ if (!target[archetypeUnionFieldsSymbol]) {
137
+ target[archetypeUnionFieldsSymbol] = [];
138
+ }
139
+ target[archetypeUnionFieldsSymbol].push({
140
+ propertyKey,
141
+ components,
142
+ options,
143
+ });
144
+ };
145
+ }
146
+
147
+ function createRelationDecorator(
148
+ relationType: "hasMany" | "belongsTo" | "hasOne" | "belongsToMany"
149
+ ) {
150
+ return function (relatedArcheType: string, options?: RelationOptions) {
151
+ return function (target: any, propertyKey: string) {
152
+ if (!target[archetypeRelationsSymbol]) {
153
+ target[archetypeRelationsSymbol] = [];
154
+ }
155
+ target[archetypeRelationsSymbol].push({
156
+ propertyKey,
157
+ relatedArcheType,
158
+ relationType,
159
+ options,
160
+ });
161
+ };
162
+ };
163
+ }
164
+
165
+ export const HasMany = createRelationDecorator("hasMany");
166
+ export const BelongsTo = createRelationDecorator("belongsTo");
167
+ export const HasOne = createRelationDecorator("hasOne");
168
+ export const BelongsToMany = createRelationDecorator("belongsToMany");
169
+
170
+ // Keep ArcheTypeRelation as alias for backwards compatibility
171
+ export const ArcheTypeRelation = HasMany;