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.
- package/.claude/scheduled_tasks.lock +1 -0
- package/CHANGELOG.md +104 -0
- package/CLAUDE.md +20 -0
- package/config/cache.config.ts +35 -1
- package/core/App.ts +24 -1060
- package/core/ArcheType.ts +78 -2110
- package/core/Entity.ts +136 -41
- package/core/RequestContext.ts +85 -36
- package/core/RequestLoaders.ts +89 -31
- package/core/SchedulerManager.ts +13 -13
- package/core/app/bootstrap.ts +133 -0
- package/core/app/cors.ts +94 -0
- package/core/app/graphqlSetup.ts +56 -0
- package/core/app/healthEndpoints.ts +31 -0
- package/core/app/metricsCollector.ts +27 -0
- package/core/app/preparedStatementWarmup.ts +55 -0
- package/core/app/processHandlers.ts +43 -0
- package/core/app/requestRouter.ts +309 -0
- package/core/app/restRegistry.ts +72 -0
- package/core/app/shutdown.ts +97 -0
- package/core/app/studioRouter.ts +83 -0
- package/core/archetype/customTypes.ts +100 -0
- package/core/archetype/decorators.ts +171 -0
- package/core/archetype/fieldResolvers.ts +621 -0
- package/core/archetype/helpers.ts +29 -0
- package/core/archetype/relationLoader.ts +118 -0
- package/core/archetype/schemaBuilder.ts +141 -0
- package/core/archetype/weaver.ts +218 -0
- package/core/archetype/zodSchemaBuilder.ts +527 -0
- package/core/cache/CacheManager.ts +144 -9
- package/core/components/BaseComponent.ts +12 -2
- package/core/middleware/AccessLog.ts +8 -1
- package/database/PreparedStatementCache.ts +17 -16
- package/database/cancellable.ts +22 -0
- package/database/instrumentedDb.ts +141 -0
- package/docs/RFC_APP_REFACTOR.md +248 -0
- package/docs/RFC_REFACTOR_TARGETS.md +251 -0
- package/package.json +1 -1
- package/query/ComponentInclusionNode.ts +5 -5
- package/query/Query.ts +65 -48
- package/service/ServiceRegistry.ts +7 -1
- package/service/index.ts +4 -2
- package/tests/integration/loaders/RequestLoaders.abort.test.ts +82 -0
- package/tests/integration/query/Query.abort.test.ts +66 -0
- package/tests/unit/cache/CacheManager.test.ts +152 -1
- package/tests/unit/database/cancellable.test.ts +81 -0
- package/tests/unit/database/instrumentedDb.test.ts +160 -0
- package/tests/unit/entity/Entity.components.test.ts +73 -0
- package/tests/unit/entity/Entity.drainSideEffects.test.ts +51 -0
- package/tests/unit/entity/Entity.reload.test.ts +63 -0
- package/tests/unit/entity/Entity.requireComponents.test.ts +72 -0
- package/tests/unit/query/Query.emptyString.test.ts +69 -0
- package/tests/unit/query/Query.test.ts +6 -4
- 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;
|