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,82 @@
|
|
|
1
|
+
import { GraphVisitor } from "./GraphVisitor";
|
|
2
|
+
import { TypeNode, OperationNode, FieldNode, InputNode, ScalarNode } from "../graph/GraphNode";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Visitor that tracks and eliminates duplicate type definitions.
|
|
6
|
+
* Ensures that each type name is defined only once in the schema.
|
|
7
|
+
*/
|
|
8
|
+
export class DeduplicationVisitor extends GraphVisitor {
|
|
9
|
+
private seenTypeNames: Set<string> = new Set();
|
|
10
|
+
private duplicateNodes: Set<string> = new Set(); // Node IDs that are duplicates
|
|
11
|
+
|
|
12
|
+
visitTypeNode(node: TypeNode): void {
|
|
13
|
+
if (this.seenTypeNames.has(node.name)) {
|
|
14
|
+
this.duplicateNodes.add(node.id);
|
|
15
|
+
} else {
|
|
16
|
+
this.seenTypeNames.add(node.name);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
visitOperationNode(node: OperationNode): void {
|
|
21
|
+
// Operations don't define new types, so no deduplication needed
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
visitFieldNode(node: FieldNode): void {
|
|
25
|
+
// Fields don't define new types
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
visitInputNode(node: InputNode): void {
|
|
29
|
+
if (this.seenTypeNames.has(node.name)) {
|
|
30
|
+
this.duplicateNodes.add(node.id);
|
|
31
|
+
} else {
|
|
32
|
+
this.seenTypeNames.add(node.name);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
visitScalarNode(node: ScalarNode): void {
|
|
37
|
+
if (this.seenTypeNames.has(node.name)) {
|
|
38
|
+
this.duplicateNodes.add(node.id);
|
|
39
|
+
} else {
|
|
40
|
+
this.seenTypeNames.add(node.name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getResults(): {
|
|
45
|
+
duplicateNodeIds: Set<string>;
|
|
46
|
+
uniqueTypeNames: Set<string>;
|
|
47
|
+
} {
|
|
48
|
+
return {
|
|
49
|
+
duplicateNodeIds: new Set(this.duplicateNodes),
|
|
50
|
+
uniqueTypeNames: new Set(this.seenTypeNames)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a node ID is a duplicate
|
|
56
|
+
*/
|
|
57
|
+
isDuplicate(nodeId: string): boolean {
|
|
58
|
+
return this.duplicateNodes.has(nodeId);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get all duplicate node IDs
|
|
63
|
+
*/
|
|
64
|
+
getDuplicateNodeIds(): string[] {
|
|
65
|
+
return Array.from(this.duplicateNodes);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get all unique type names seen
|
|
70
|
+
*/
|
|
71
|
+
getUniqueTypeNames(): string[] {
|
|
72
|
+
return Array.from(this.seenTypeNames);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear all tracking data
|
|
77
|
+
*/
|
|
78
|
+
clear(): void {
|
|
79
|
+
this.seenTypeNames.clear();
|
|
80
|
+
this.duplicateNodes.clear();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { GraphNode, TypeNode, OperationNode, FieldNode, InputNode, ScalarNode } from "../graph/GraphNode";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base visitor class for traversing GraphQL schema graphs.
|
|
5
|
+
* Implements the Visitor pattern to separate algorithms from data structures.
|
|
6
|
+
*
|
|
7
|
+
* Each concrete visitor implements specific behavior for different node types.
|
|
8
|
+
*/
|
|
9
|
+
export abstract class GraphVisitor {
|
|
10
|
+
/**
|
|
11
|
+
* Visit a generic graph node
|
|
12
|
+
*/
|
|
13
|
+
visit(node: GraphNode): void {
|
|
14
|
+
switch (node.nodeType) {
|
|
15
|
+
case 'TYPE':
|
|
16
|
+
this.visitTypeNode(node as TypeNode);
|
|
17
|
+
break;
|
|
18
|
+
case 'OPERATION':
|
|
19
|
+
this.visitOperationNode(node as OperationNode);
|
|
20
|
+
break;
|
|
21
|
+
case 'FIELD':
|
|
22
|
+
this.visitFieldNode(node as FieldNode);
|
|
23
|
+
break;
|
|
24
|
+
case 'INPUT':
|
|
25
|
+
this.visitInputNode(node as InputNode);
|
|
26
|
+
break;
|
|
27
|
+
case 'SCALAR':
|
|
28
|
+
this.visitScalarNode(node as ScalarNode);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Unknown node type: ${(node as any).nodeType}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Visit a TypeNode
|
|
37
|
+
*/
|
|
38
|
+
abstract visitTypeNode(node: TypeNode): void;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Visit an OperationNode
|
|
42
|
+
*/
|
|
43
|
+
abstract visitOperationNode(node: OperationNode): void;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Visit a FieldNode
|
|
47
|
+
*/
|
|
48
|
+
abstract visitFieldNode(node: FieldNode): void;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Visit an InputNode
|
|
52
|
+
*/
|
|
53
|
+
abstract visitInputNode(node: InputNode): void;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Visit a ScalarNode
|
|
57
|
+
*/
|
|
58
|
+
abstract visitScalarNode(node: ScalarNode): void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Called before visiting a graph to perform setup
|
|
62
|
+
*/
|
|
63
|
+
beforeVisit(): void {
|
|
64
|
+
// Default: no-op
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Called after visiting a graph to perform cleanup or finalization
|
|
69
|
+
*/
|
|
70
|
+
afterVisit(): void {
|
|
71
|
+
// Default: no-op
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the results of the visitation
|
|
76
|
+
*/
|
|
77
|
+
abstract getResults(): any;
|
|
78
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { GraphVisitor } from "./GraphVisitor";
|
|
2
|
+
import { TypeNode, OperationNode, FieldNode, InputNode, ScalarNode } from "../graph/GraphNode";
|
|
3
|
+
import { ResolverBuilder } from "../builders/ResolverBuilder";
|
|
4
|
+
import { logger } from "../../core/Logger";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Visitor that generates the GraphQL resolvers object.
|
|
8
|
+
* Uses the ResolverBuilder from Phase 4 to construct resolver functions.
|
|
9
|
+
*/
|
|
10
|
+
export class ResolverGeneratorVisitor extends GraphVisitor {
|
|
11
|
+
private resolverBuilder: ResolverBuilder;
|
|
12
|
+
private services: any[];
|
|
13
|
+
|
|
14
|
+
constructor(services: any[]) {
|
|
15
|
+
super();
|
|
16
|
+
this.services = services;
|
|
17
|
+
this.resolverBuilder = new ResolverBuilder();
|
|
18
|
+
|
|
19
|
+
// Add Date scalar resolver
|
|
20
|
+
this.resolverBuilder.addScalarResolver('Date', {
|
|
21
|
+
serialize: (value: any) => {
|
|
22
|
+
if (value instanceof Date) {
|
|
23
|
+
return value.toISOString();
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
},
|
|
27
|
+
parseValue: (value: any) => {
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
return new Date(value);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
},
|
|
33
|
+
parseLiteral: (ast: any) => {
|
|
34
|
+
if (ast.kind === 'StringValue') {
|
|
35
|
+
return new Date(ast.value);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
visitTypeNode(node: TypeNode): void {
|
|
43
|
+
// TypeNodes don't directly create resolvers
|
|
44
|
+
// Resolvers for object types are typically handled by archetypes
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
visitOperationNode(node: OperationNode): void {
|
|
48
|
+
// Find the service instance that matches the service name
|
|
49
|
+
const service = this.services.find(s => s.constructor.name === node.metadata.serviceName);
|
|
50
|
+
if (!service) {
|
|
51
|
+
logger.warn(`Service ${node.metadata.serviceName} not found for operation ${node.name}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const type = node.operationType.charAt(0).toUpperCase() + node.operationType.slice(1).toLowerCase() as "Query" | "Mutation" | "Subscription";
|
|
56
|
+
|
|
57
|
+
// Extract Zod schema from input if it's a Zod type (check for '_def' property)
|
|
58
|
+
const input = node.metadata.input;
|
|
59
|
+
const zodSchema = (input && typeof input === 'object' && '_def' in input) ? input as any : null;
|
|
60
|
+
|
|
61
|
+
// Create resolver definitions for operations
|
|
62
|
+
const resolverDef = {
|
|
63
|
+
name: node.name,
|
|
64
|
+
type: type,
|
|
65
|
+
service: service, // Service instance
|
|
66
|
+
propertyKey: node.metadata.propertyKey, // Method name from metadata
|
|
67
|
+
zodSchema: zodSchema, // Zod schema if available
|
|
68
|
+
hasInput: !!node.inputNodeId || !!zodSchema || !!input // Whether this operation has input (InputNode, Zod schema, or raw GraphQL input definition)
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
this.resolverBuilder.addResolver(resolverDef);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
visitFieldNode(node: FieldNode): void {
|
|
75
|
+
// FieldNodes represent individual field resolvers
|
|
76
|
+
// These would typically be added to the resolvers for their parent type
|
|
77
|
+
// For now, we'll skip these as they're handled by archetypes
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
visitInputNode(node: InputNode): void {
|
|
81
|
+
// InputNodes don't create resolvers
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
visitScalarNode(node: ScalarNode): void {
|
|
85
|
+
// ScalarNodes don't create resolvers
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getResults(): Record<string, Record<string, Function>> {
|
|
89
|
+
const resolvers = this.resolverBuilder.getResolvers();
|
|
90
|
+
|
|
91
|
+
// Ensure there's always at least one Query resolver for GraphQL schema validity
|
|
92
|
+
if (!resolvers.Query) {
|
|
93
|
+
resolvers.Query = {};
|
|
94
|
+
}
|
|
95
|
+
if (Object.keys(resolvers.Query).length === 0) {
|
|
96
|
+
resolvers.Query._empty = () => null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return resolvers;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get resolvers for a specific operation type
|
|
104
|
+
*/
|
|
105
|
+
getResolversForType(type: "Query" | "Mutation" | "Subscription"): Record<string, Function> {
|
|
106
|
+
return this.resolverBuilder.getResolversForType(type);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get statistics about generated resolvers
|
|
111
|
+
*/
|
|
112
|
+
getStats(): { queries: number; mutations: number; subscriptions: number } {
|
|
113
|
+
return this.resolverBuilder.getStats();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Clear all resolver data
|
|
118
|
+
*/
|
|
119
|
+
clear(): void {
|
|
120
|
+
this.resolverBuilder.clear();
|
|
121
|
+
}
|
|
122
|
+
}
|