@fluojs/graphql 1.0.0-beta.1

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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +158 -0
  3. package/README.md +158 -0
  4. package/dist/dataloader/dataloader.d.ts +127 -0
  5. package/dist/dataloader/dataloader.d.ts.map +1 -0
  6. package/dist/dataloader/dataloader.js +151 -0
  7. package/dist/dataloader.d.ts +2 -0
  8. package/dist/dataloader.d.ts.map +1 -0
  9. package/dist/dataloader.js +1 -0
  10. package/dist/decorators.d.ts +21 -0
  11. package/dist/decorators.d.ts.map +1 -0
  12. package/dist/decorators.js +111 -0
  13. package/dist/discovery.d.ts +4 -0
  14. package/dist/discovery.d.ts.map +1 -0
  15. package/dist/discovery.js +142 -0
  16. package/dist/guardrails.d.ts +35 -0
  17. package/dist/guardrails.d.ts.map +1 -0
  18. package/dist/guardrails.js +162 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +4 -0
  22. package/dist/internal-tokens.d.ts +7 -0
  23. package/dist/internal-tokens.d.ts.map +1 -0
  24. package/dist/internal-tokens.js +4 -0
  25. package/dist/metadata.d.ts +20 -0
  26. package/dist/metadata.d.ts.map +1 -0
  27. package/dist/metadata.js +120 -0
  28. package/dist/module.d.ts +22 -0
  29. package/dist/module.d.ts.map +1 -0
  30. package/dist/module.js +33 -0
  31. package/dist/pipeline/input-pipeline.d.ts +34 -0
  32. package/dist/pipeline/input-pipeline.d.ts.map +1 -0
  33. package/dist/pipeline/input-pipeline.js +129 -0
  34. package/dist/schema/schema.d.ts +20 -0
  35. package/dist/schema/schema.d.ts.map +1 -0
  36. package/dist/schema/schema.js +278 -0
  37. package/dist/service.d.ts +58 -0
  38. package/dist/service.d.ts.map +1 -0
  39. package/dist/service.js +602 -0
  40. package/dist/transport/transport.d.ts +5 -0
  41. package/dist/transport/transport.d.ts.map +1 -0
  42. package/dist/transport/transport.js +119 -0
  43. package/dist/types.d.ts +221 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +132 -0
  46. package/package.json +61 -0
@@ -0,0 +1,111 @@
1
+ import { metadataSymbol } from '@fluojs/core/internal';
2
+ import { argMetadataSymbol, handlerMetadataSymbol, resolverMetadataSymbol } from './metadata.js';
3
+ function getStandardMetadataBag(metadata) {
4
+ void metadataSymbol;
5
+ return metadata;
6
+ }
7
+ function normalizeResolverTypeName(typeName, fallbackName) {
8
+ const trimmed = typeName?.trim();
9
+ if (trimmed) {
10
+ return trimmed;
11
+ }
12
+ return fallbackName;
13
+ }
14
+ function normalizeMethodMetadata(type, fieldNameOrOptions) {
15
+ if (typeof fieldNameOrOptions === 'string') {
16
+ return {
17
+ fieldName: fieldNameOrOptions.trim() || undefined,
18
+ type
19
+ };
20
+ }
21
+ if (!fieldNameOrOptions) {
22
+ return {
23
+ type
24
+ };
25
+ }
26
+ return {
27
+ argTypes: fieldNameOrOptions.argTypes,
28
+ fieldName: fieldNameOrOptions.fieldName?.trim() || undefined,
29
+ inputClass: fieldNameOrOptions.input,
30
+ outputType: fieldNameOrOptions.outputType,
31
+ topics: fieldNameOrOptions.topics,
32
+ type
33
+ };
34
+ }
35
+ function defineStandardResolverMetadata(metadata, resolverMetadata) {
36
+ const bag = getStandardMetadataBag(metadata);
37
+ bag[resolverMetadataSymbol] = {
38
+ typeName: resolverMetadata.typeName
39
+ };
40
+ }
41
+ function defineStandardHandlerMetadata(metadata, propertyKey, handlerMetadata) {
42
+ const bag = getStandardMetadataBag(metadata);
43
+ const current = bag[handlerMetadataSymbol];
44
+ const map = current ?? new Map();
45
+ map.set(propertyKey, {
46
+ argTypes: handlerMetadata.argTypes,
47
+ fieldName: handlerMetadata.fieldName,
48
+ inputClass: handlerMetadata.inputClass,
49
+ outputType: handlerMetadata.outputType,
50
+ topics: handlerMetadata.topics,
51
+ type: handlerMetadata.type
52
+ });
53
+ bag[handlerMetadataSymbol] = map;
54
+ }
55
+ function defineStandardArgFieldMetadata(metadata, propertyKey, argFieldMetadata) {
56
+ const bag = getStandardMetadataBag(metadata);
57
+ const current = bag[argMetadataSymbol];
58
+ const map = current ?? new Map();
59
+ map.set(propertyKey, {
60
+ argName: argFieldMetadata.argName,
61
+ fieldName: argFieldMetadata.fieldName
62
+ });
63
+ bag[argMetadataSymbol] = map;
64
+ }
65
+ function createMethodDecorator(type, fieldNameOrOptions) {
66
+ const metadata = normalizeMethodMetadata(type, fieldNameOrOptions);
67
+ const decorator = (_value, context) => {
68
+ const name = type === 'query' ? 'Query' : type === 'mutation' ? 'Mutation' : 'Subscription';
69
+ if (context.private) {
70
+ throw new Error(`@${name}() cannot be used on private methods.`);
71
+ }
72
+ if (context.static) {
73
+ throw new Error(`@${name}() cannot be used on static methods.`);
74
+ }
75
+ defineStandardHandlerMetadata(context.metadata, context.name, metadata);
76
+ };
77
+ return decorator;
78
+ }
79
+ export function Resolver(typeName) {
80
+ const decorator = (value, context) => {
81
+ defineStandardResolverMetadata(context.metadata, {
82
+ typeName: normalizeResolverTypeName(typeName, value.name || 'Resolver')
83
+ });
84
+ };
85
+ return decorator;
86
+ }
87
+ export function Query(fieldNameOrOptions) {
88
+ return createMethodDecorator('query', fieldNameOrOptions);
89
+ }
90
+ export function Mutation(fieldNameOrOptions) {
91
+ return createMethodDecorator('mutation', fieldNameOrOptions);
92
+ }
93
+ export function Subscription(fieldNameOrOptions) {
94
+ return createMethodDecorator('subscription', fieldNameOrOptions);
95
+ }
96
+ export function Arg(argName) {
97
+ const decorator = (_value, context) => {
98
+ if (context.private) {
99
+ throw new Error('@Arg() cannot be used on private fields.');
100
+ }
101
+ if (context.static) {
102
+ throw new Error('@Arg() cannot be used on static fields.');
103
+ }
104
+ const fieldName = typeof context.name === 'symbol' ? context.name.toString() : context.name;
105
+ defineStandardArgFieldMetadata(context.metadata, context.name, {
106
+ argName: argName?.trim() || fieldName,
107
+ fieldName
108
+ });
109
+ };
110
+ return decorator;
111
+ }
@@ -0,0 +1,4 @@
1
+ import type { CompiledModule } from '@fluojs/runtime';
2
+ import type { GraphqlModuleOptions, ResolverDescriptor } from './types.js';
3
+ export declare function discoverResolverDescriptors(compiledModules: readonly CompiledModule[], options: GraphqlModuleOptions): ResolverDescriptor[];
4
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAkI3E,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,EAAE,CA+CtB"}
@@ -0,0 +1,142 @@
1
+ import { getClassDiMetadata } from '@fluojs/core/internal';
2
+ import { getArgFieldMetadataEntries, getResolverHandlerMetadataEntries, getResolverMetadata } from './metadata.js';
3
+ function scopeFromProvider(provider, factoryResolverClass) {
4
+ if (typeof provider === 'function') {
5
+ return getClassDiMetadata(provider)?.scope ?? 'singleton';
6
+ }
7
+ if ('useClass' in provider) {
8
+ return provider.scope ?? getClassDiMetadata(provider.useClass)?.scope ?? 'singleton';
9
+ }
10
+ if ('useFactory' in provider) {
11
+ return provider.scope ?? (factoryResolverClass ? getClassDiMetadata(factoryResolverClass)?.scope : undefined) ?? 'singleton';
12
+ }
13
+ return 'singleton';
14
+ }
15
+ function isClassProvider(provider) {
16
+ return typeof provider === 'object' && provider !== null && 'useClass' in provider;
17
+ }
18
+ function isValueProvider(provider) {
19
+ return typeof provider === 'object' && provider !== null && 'useValue' in provider;
20
+ }
21
+ function isFactoryProvider(provider) {
22
+ return typeof provider === 'object' && provider !== null && 'useFactory' in provider;
23
+ }
24
+ function methodKeyToName(methodKey) {
25
+ return typeof methodKey === 'symbol' ? methodKey.toString() : methodKey;
26
+ }
27
+ function normalizeAllowedResolverSet(resolvers) {
28
+ if (!resolvers || resolvers.length === 0) {
29
+ return undefined;
30
+ }
31
+ return new Set(resolvers);
32
+ }
33
+ function discoveryCandidates(compiledModules) {
34
+ const candidates = [];
35
+ for (const compiledModule of compiledModules) {
36
+ for (const provider of compiledModule.definition.providers ?? []) {
37
+ if (typeof provider === 'function') {
38
+ candidates.push({
39
+ moduleName: compiledModule.type.name,
40
+ scope: scopeFromProvider(provider),
41
+ targetType: provider,
42
+ token: provider
43
+ });
44
+ continue;
45
+ }
46
+ if (isClassProvider(provider)) {
47
+ candidates.push({
48
+ moduleName: compiledModule.type.name,
49
+ scope: scopeFromProvider(provider),
50
+ targetType: provider.useClass,
51
+ token: provider.provide
52
+ });
53
+ continue;
54
+ }
55
+ if (isValueProvider(provider)) {
56
+ const value = provider.useValue;
57
+ if (typeof value === 'function') {
58
+ candidates.push({
59
+ moduleName: compiledModule.type.name,
60
+ scope: 'singleton',
61
+ targetType: value,
62
+ token: provider.provide
63
+ });
64
+ continue;
65
+ }
66
+ if (typeof value === 'object' && value !== null) {
67
+ const constructor = value.constructor;
68
+ if (constructor && constructor !== Object) {
69
+ candidates.push({
70
+ moduleName: compiledModule.type.name,
71
+ scope: 'singleton',
72
+ targetType: constructor,
73
+ token: provider.provide
74
+ });
75
+ }
76
+ }
77
+ continue;
78
+ }
79
+ if (isFactoryProvider(provider)) {
80
+ const resolverClass = provider.resolverClass;
81
+ if (resolverClass) {
82
+ candidates.push({
83
+ moduleName: compiledModule.type.name,
84
+ scope: scopeFromProvider(provider, resolverClass),
85
+ targetType: resolverClass,
86
+ token: provider.provide
87
+ });
88
+ }
89
+ }
90
+ }
91
+ for (const controller of compiledModule.definition.controllers ?? []) {
92
+ candidates.push({
93
+ moduleName: compiledModule.type.name,
94
+ scope: scopeFromProvider(controller),
95
+ targetType: controller,
96
+ token: controller
97
+ });
98
+ }
99
+ }
100
+ return candidates;
101
+ }
102
+ export function discoverResolverDescriptors(compiledModules, options) {
103
+ const allowedResolvers = normalizeAllowedResolverSet(options.resolvers);
104
+ const seenTargets = new Set();
105
+ const descriptors = [];
106
+ for (const candidate of discoveryCandidates(compiledModules)) {
107
+ if (allowedResolvers && !allowedResolvers.has(candidate.targetType)) {
108
+ continue;
109
+ }
110
+ const resolverMetadata = getResolverMetadata(candidate.targetType);
111
+ if (!resolverMetadata) {
112
+ continue;
113
+ }
114
+ if (seenTargets.has(candidate.targetType)) {
115
+ continue;
116
+ }
117
+ seenTargets.add(candidate.targetType);
118
+ descriptors.push({
119
+ handlers: getResolverHandlerMetadataEntries(candidate.targetType.prototype).map(entry => {
120
+ const inputClass = entry.metadata.inputClass;
121
+ const argFields = inputClass !== undefined ? getArgFieldMetadataEntries(inputClass.prototype).map(argField => argField.metadata) : [];
122
+ return {
123
+ argFields,
124
+ argTypes: entry.metadata.argTypes,
125
+ fieldName: entry.metadata.fieldName ?? methodKeyToName(entry.propertyKey),
126
+ inputClass,
127
+ methodKey: entry.propertyKey,
128
+ methodName: methodKeyToName(entry.propertyKey),
129
+ outputType: entry.metadata.outputType,
130
+ topics: entry.metadata.topics,
131
+ type: entry.metadata.type
132
+ };
133
+ }),
134
+ moduleName: candidate.moduleName,
135
+ scope: candidate.scope,
136
+ targetName: candidate.targetType.name,
137
+ token: candidate.token,
138
+ typeName: resolverMetadata.typeName
139
+ });
140
+ }
141
+ return descriptors;
142
+ }
@@ -0,0 +1,35 @@
1
+ import { GraphQLError, type ExecutionArgs, type ValidationRule } from 'graphql';
2
+ import type { GraphqlRequestLimitsOptions } from './types.js';
3
+ interface GraphqlValidationPluginContext {
4
+ addValidationRule(rule: ValidationRule): void;
5
+ }
6
+ interface GraphqlValidationPlugin {
7
+ onExecute?(payload: GraphqlOperationHookPayload): void;
8
+ onSubscribe?(payload: GraphqlOperationHookPayload): void;
9
+ onValidate?(context: GraphqlValidationPluginContext): void;
10
+ }
11
+ interface GraphqlOperationHookPayload {
12
+ args: Pick<ExecutionArgs, 'document' | 'operationName'>;
13
+ setResultAndStopExecution(result: {
14
+ errors: GraphQLError[];
15
+ }): void;
16
+ }
17
+ /**
18
+ * Resolve the effective GraphQL request budget configuration for one module instance.
19
+ *
20
+ * @param limits User-provided request limit overrides, or `false` to disable built-in budgets.
21
+ * @returns The normalized request limits, or `undefined` when guardrails are explicitly disabled.
22
+ */
23
+ export declare function resolveGraphqlRequestLimits(limits: GraphqlRequestLimitsOptions | false | undefined): Required<GraphqlRequestLimitsOptions> | undefined;
24
+ /**
25
+ * Create the GraphQL plugin that enforces introspection and request-budget guardrails.
26
+ *
27
+ * @param options Effective guardrail settings for introspection and per-request limits.
28
+ * @returns An Envelop-compatible plugin when at least one guardrail is enabled.
29
+ */
30
+ export declare function createGraphqlValidationPlugin(options: {
31
+ introspection: boolean;
32
+ limits: Required<GraphqlRequestLimitsOptions> | undefined;
33
+ }): GraphqlValidationPlugin | undefined;
34
+ export {};
35
+ //# sourceMappingURL=guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../src/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAUlB,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAQ9D,UAAU,8BAA8B;IACtC,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/C;AAED,UAAU,uBAAuB;IAC/B,SAAS,CAAC,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAAC;IACvD,WAAW,CAAC,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAAC;IACzD,UAAU,CAAC,CAAC,OAAO,EAAE,8BAA8B,GAAG,IAAI,CAAC;CAC5D;AAED,UAAU,2BAA2B;IACnC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,eAAe,CAAC,CAAC;IACxD,yBAAyB,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CACrE;AAcD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,2BAA2B,GAAG,KAAK,GAAG,SAAS,GACtD,QAAQ,CAAC,2BAA2B,CAAC,GAAG,SAAS,CAUnD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,QAAQ,CAAC,2BAA2B,CAAC,GAAG,SAAS,CAAC;CAC3D,GAAG,uBAAuB,GAAG,SAAS,CAkCtC"}
@@ -0,0 +1,162 @@
1
+ import { GraphQLError, Kind } from 'graphql';
2
+ const DEFAULT_GRAPHQL_REQUEST_LIMITS = {
3
+ maxComplexity: 250,
4
+ maxCost: 500,
5
+ maxDepth: 12
6
+ };
7
+ /**
8
+ * Resolve the effective GraphQL request budget configuration for one module instance.
9
+ *
10
+ * @param limits User-provided request limit overrides, or `false` to disable built-in budgets.
11
+ * @returns The normalized request limits, or `undefined` when guardrails are explicitly disabled.
12
+ */
13
+ export function resolveGraphqlRequestLimits(limits) {
14
+ if (limits === false) {
15
+ return undefined;
16
+ }
17
+ return {
18
+ maxComplexity: limits?.maxComplexity ?? DEFAULT_GRAPHQL_REQUEST_LIMITS.maxComplexity,
19
+ maxCost: limits?.maxCost ?? DEFAULT_GRAPHQL_REQUEST_LIMITS.maxCost,
20
+ maxDepth: limits?.maxDepth ?? DEFAULT_GRAPHQL_REQUEST_LIMITS.maxDepth
21
+ };
22
+ }
23
+
24
+ /**
25
+ * Create the GraphQL plugin that enforces introspection and request-budget guardrails.
26
+ *
27
+ * @param options Effective guardrail settings for introspection and per-request limits.
28
+ * @returns An Envelop-compatible plugin when at least one guardrail is enabled.
29
+ */
30
+ export function createGraphqlValidationPlugin(options) {
31
+ const validationRules = [];
32
+ if (!options.introspection) {
33
+ validationRules.push(createDisableIntrospectionRule());
34
+ }
35
+ if (validationRules.length === 0 && !options.limits) {
36
+ return undefined;
37
+ }
38
+ const enforceRequestLimits = options.limits ? payload => {
39
+ const errors = evaluateGraphqlRequestLimits(payload.args.document, payload.args.operationName, options.limits);
40
+ if (errors.length > 0) {
41
+ payload.setResultAndStopExecution({
42
+ errors
43
+ });
44
+ }
45
+ } : undefined;
46
+ return {
47
+ ...(enforceRequestLimits ? {
48
+ onExecute: enforceRequestLimits,
49
+ onSubscribe: enforceRequestLimits
50
+ } : {}),
51
+ onValidate({
52
+ addValidationRule
53
+ }) {
54
+ for (const rule of validationRules) {
55
+ addValidationRule(rule);
56
+ }
57
+ }
58
+ };
59
+ }
60
+ function createDisableIntrospectionRule() {
61
+ return context => ({
62
+ Field(node) {
63
+ const fieldName = node.name.value;
64
+ if (fieldName === '__schema' || fieldName === '__type') {
65
+ context.reportError(new GraphQLError(`GraphQL introspection is disabled, but the query requested "${fieldName}".`));
66
+ }
67
+ }
68
+ });
69
+ }
70
+ function evaluateGraphqlRequestLimits(document, operationName, limits) {
71
+ const metrics = analyzeGraphqlOperation(document, operationName);
72
+ if (!metrics) {
73
+ return [];
74
+ }
75
+ const checks = [{
76
+ actual: metrics.maxDepth,
77
+ label: 'depth',
78
+ limit: limits.maxDepth
79
+ }, {
80
+ actual: metrics.complexity,
81
+ label: 'complexity',
82
+ limit: limits.maxComplexity
83
+ }, {
84
+ actual: metrics.cost,
85
+ label: 'cost',
86
+ limit: limits.maxCost
87
+ }];
88
+ return checks.flatMap(check => {
89
+ if (check.actual <= check.limit) {
90
+ return [];
91
+ }
92
+ return [new GraphQLError(`GraphQL query ${check.label} ${String(check.actual)} exceeds the configured limit of ${String(check.limit)}.`)];
93
+ });
94
+ }
95
+ function analyzeGraphqlOperation(document, operationName) {
96
+ const fragments = new Map();
97
+ const operations = [];
98
+ for (const definition of document.definitions) {
99
+ if (definition.kind === Kind.FRAGMENT_DEFINITION) {
100
+ fragments.set(definition.name.value, definition);
101
+ continue;
102
+ }
103
+ if (definition.kind === Kind.OPERATION_DEFINITION) {
104
+ operations.push(definition);
105
+ }
106
+ }
107
+ const operation = resolveOperationDefinition(operations, operationName);
108
+ if (!operation) {
109
+ return undefined;
110
+ }
111
+ const metrics = {
112
+ complexity: 0,
113
+ cost: 0,
114
+ maxDepth: 0
115
+ };
116
+ const walkSelectionSet = (selectionSet, depth, activeFragments) => {
117
+ for (const selection of selectionSet.selections) {
118
+ if (selection.kind === Kind.FIELD) {
119
+ const nextDepth = depth + 1;
120
+ metrics.maxDepth = Math.max(metrics.maxDepth, nextDepth);
121
+ metrics.complexity += 1;
122
+ metrics.cost += nextDepth;
123
+ if (selection.selectionSet) {
124
+ walkSelectionSet(selection.selectionSet, nextDepth, activeFragments);
125
+ }
126
+ continue;
127
+ }
128
+ if (selection.kind === Kind.INLINE_FRAGMENT) {
129
+ walkInlineFragment(selection, depth, activeFragments);
130
+ continue;
131
+ }
132
+ if (selection.kind !== Kind.FRAGMENT_SPREAD) {
133
+ continue;
134
+ }
135
+ walkFragmentSpread(selection, depth, activeFragments);
136
+ }
137
+ };
138
+ const walkInlineFragment = (fragment, depth, activeFragments) => {
139
+ walkSelectionSet(fragment.selectionSet, depth, activeFragments);
140
+ };
141
+ const walkFragmentSpread = (fragmentSpread, depth, activeFragments) => {
142
+ const fragmentName = fragmentSpread.name.value;
143
+ if (activeFragments.has(fragmentName)) {
144
+ return;
145
+ }
146
+ const fragment = fragments.get(fragmentName);
147
+ if (!fragment) {
148
+ return;
149
+ }
150
+ activeFragments.add(fragmentName);
151
+ walkSelectionSet(fragment.selectionSet, depth, activeFragments);
152
+ activeFragments.delete(fragmentName);
153
+ };
154
+ walkSelectionSet(operation.selectionSet, 0, new Set());
155
+ return metrics;
156
+ }
157
+ function resolveOperationDefinition(operations, operationName) {
158
+ if (operationName) {
159
+ return operations.find(operation => operation.name?.value === operationName);
160
+ }
161
+ return operations.length === 1 ? operations[0] : undefined;
162
+ }
@@ -0,0 +1,6 @@
1
+ export * from './dataloader.js';
2
+ export * from './decorators.js';
3
+ export { GraphqlModule } from './module.js';
4
+ export { isGraphqlListTypeRef, listOf, } from './types.js';
5
+ export type { ArgFieldMetadata, GraphQLContext, GraphqlArgType, GraphqlListTypeRef, GraphqlModuleOptions, GraphqlRequestLimitsOptions, GraphqlRequestContext, GraphqlRootOutputNamedType, GraphqlRootOutputType, GraphqlScalarTypeName, GraphqlSubscriptionsOptions, GraphqlWebSocketSubscriptionsOptions, ResolverHandlerMetadata, ResolverHandlerType, ResolverMetadata, } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,oBAAoB,EACpB,MAAM,GACP,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,oCAAoC,EACpC,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './dataloader.js';
2
+ export * from './decorators.js';
3
+ export { GraphqlModule } from './module.js';
4
+ export { isGraphqlListTypeRef, listOf } from './types.js';
@@ -0,0 +1,7 @@
1
+ import type { Token } from '@fluojs/core';
2
+ import type { GraphqlModuleOptions } from './types.js';
3
+ /**
4
+ * DI token for providing GraphQL module configuration options.
5
+ */
6
+ export declare const GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN: Token<GraphqlModuleOptions>;
7
+ //# sourceMappingURL=internal-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-tokens.d.ts","sourceRoot":"","sources":["../src/internal-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,qCAAqC,EAAE,KAAK,CAAC,oBAAoB,CAE7E,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * DI token for providing GraphQL module configuration options.
3
+ */
4
+ export const GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN = Symbol.for('fluo.graphql.module-options');
@@ -0,0 +1,20 @@
1
+ import type { MetadataPropertyKey } from '@fluojs/core';
2
+ import type { ArgFieldMetadata, ResolverHandlerMetadata, ResolverMetadata } from './types.js';
3
+ export declare function defineResolverMetadata(target: object, metadata: ResolverMetadata): void;
4
+ export declare function getResolverMetadata(target: object): ResolverMetadata | undefined;
5
+ export declare function defineResolverHandlerMetadata(target: object, propertyKey: MetadataPropertyKey, metadata: ResolverHandlerMetadata): void;
6
+ export declare function getResolverHandlerMetadata(target: object, propertyKey: MetadataPropertyKey): ResolverHandlerMetadata | undefined;
7
+ export declare function getResolverHandlerMetadataEntries(target: object): Array<{
8
+ metadata: ResolverHandlerMetadata;
9
+ propertyKey: MetadataPropertyKey;
10
+ }>;
11
+ export declare function defineArgFieldMetadata(target: object, propertyKey: MetadataPropertyKey, metadata: ArgFieldMetadata): void;
12
+ export declare function getArgFieldMetadata(target: object, propertyKey: MetadataPropertyKey): ArgFieldMetadata | undefined;
13
+ export declare function getArgFieldMetadataEntries(target: object): Array<{
14
+ metadata: ArgFieldMetadata;
15
+ propertyKey: MetadataPropertyKey;
16
+ }>;
17
+ export declare const resolverMetadataSymbol: symbol;
18
+ export declare const handlerMetadataSymbol: symbol;
19
+ export declare const argMetadataSymbol: symbol;
20
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAyH9F,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEvF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAShF;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,uBAAuB,GAAG,SAAS,CASrC;AAED,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,uBAAuB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAOhF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEzH;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,CASlH;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAEzE;AAED,eAAO,MAAM,sBAAsB,QAA8B,CAAC;AAClE,eAAO,MAAM,qBAAqB,QAA6B,CAAC;AAChE,eAAO,MAAM,iBAAiB,QAA8B,CAAC"}
@@ -0,0 +1,120 @@
1
+ const symbolWithMetadata = Symbol;
2
+ const metadataSymbol = symbolWithMetadata.metadata ?? Symbol.for('fluo.symbol.metadata');
3
+ if (!symbolWithMetadata.metadata) {
4
+ Object.defineProperty(Symbol, 'metadata', {
5
+ configurable: true,
6
+ value: metadataSymbol
7
+ });
8
+ }
9
+ const standardResolverMetadataKey = Symbol.for('fluo.graphql.standard.resolver');
10
+ const standardHandlerMetadataKey = Symbol.for('fluo.graphql.standard.handler');
11
+ const standardArgFieldMetadataKey = Symbol.for('fluo.graphql.standard.arg-field');
12
+ const resolverMetadataStore = new WeakMap();
13
+ const handlerMetadataStore = new WeakMap();
14
+ const argFieldMetadataStore = new WeakMap();
15
+ function cloneResolverMetadata(metadata) {
16
+ return {
17
+ typeName: metadata.typeName
18
+ };
19
+ }
20
+ function cloneHandlerMetadata(metadata) {
21
+ return {
22
+ argTypes: metadata.argTypes,
23
+ fieldName: metadata.fieldName,
24
+ inputClass: metadata.inputClass,
25
+ outputType: metadata.outputType,
26
+ topics: metadata.topics,
27
+ type: metadata.type
28
+ };
29
+ }
30
+ function cloneArgFieldMetadata(metadata) {
31
+ return {
32
+ argName: metadata.argName,
33
+ fieldName: metadata.fieldName
34
+ };
35
+ }
36
+ function getStandardMetadataBag(target) {
37
+ return target[metadataSymbol];
38
+ }
39
+ function getStandardResolverMetadata(target) {
40
+ const metadata = getStandardMetadataBag(target)?.[standardResolverMetadataKey];
41
+ if (!metadata) {
42
+ return undefined;
43
+ }
44
+ return cloneResolverMetadata(metadata);
45
+ }
46
+ function getStandardHandlerMap(target) {
47
+ const constructor = target.constructor;
48
+ return constructor ? getStandardMetadataBag(constructor)?.[standardHandlerMetadataKey] : undefined;
49
+ }
50
+ function getStandardArgFieldMap(target) {
51
+ const constructor = target.constructor;
52
+ return constructor ? getStandardMetadataBag(constructor)?.[standardArgFieldMetadataKey] : undefined;
53
+ }
54
+ function getOrCreateHandlerMetadataMap(target) {
55
+ let map = handlerMetadataStore.get(target);
56
+ if (!map) {
57
+ map = new Map();
58
+ handlerMetadataStore.set(target, map);
59
+ }
60
+ return map;
61
+ }
62
+ function getOrCreateArgFieldMetadataMap(target) {
63
+ let map = argFieldMetadataStore.get(target);
64
+ if (!map) {
65
+ map = new Map();
66
+ argFieldMetadataStore.set(target, map);
67
+ }
68
+ return map;
69
+ }
70
+ function getMergedMetadataEntries(target, stored, standard, resolve) {
71
+ const storedMap = stored ?? new Map();
72
+ const standardMap = standard ?? new Map();
73
+ const keys = new Set([...storedMap.keys(), ...standardMap.keys()]);
74
+ return Array.from(keys).map(propertyKey => ({
75
+ metadata: resolve(target, propertyKey),
76
+ propertyKey
77
+ })).filter(entry => entry.metadata !== undefined);
78
+ }
79
+ export function defineResolverMetadata(target, metadata) {
80
+ resolverMetadataStore.set(target, cloneResolverMetadata(metadata));
81
+ }
82
+ export function getResolverMetadata(target) {
83
+ const stored = resolverMetadataStore.get(target);
84
+ const standard = getStandardResolverMetadata(target);
85
+ if (!stored && !standard) {
86
+ return undefined;
87
+ }
88
+ return cloneResolverMetadata(stored ?? standard);
89
+ }
90
+ export function defineResolverHandlerMetadata(target, propertyKey, metadata) {
91
+ getOrCreateHandlerMetadataMap(target).set(propertyKey, cloneHandlerMetadata(metadata));
92
+ }
93
+ export function getResolverHandlerMetadata(target, propertyKey) {
94
+ const stored = handlerMetadataStore.get(target)?.get(propertyKey);
95
+ const standard = getStandardHandlerMap(target)?.get(propertyKey);
96
+ if (!stored && !standard) {
97
+ return undefined;
98
+ }
99
+ return cloneHandlerMetadata(stored ?? standard);
100
+ }
101
+ export function getResolverHandlerMetadataEntries(target) {
102
+ return getMergedMetadataEntries(target, handlerMetadataStore.get(target), getStandardHandlerMap(target), getResolverHandlerMetadata);
103
+ }
104
+ export function defineArgFieldMetadata(target, propertyKey, metadata) {
105
+ getOrCreateArgFieldMetadataMap(target).set(propertyKey, cloneArgFieldMetadata(metadata));
106
+ }
107
+ export function getArgFieldMetadata(target, propertyKey) {
108
+ const stored = argFieldMetadataStore.get(target)?.get(propertyKey);
109
+ const standard = getStandardArgFieldMap(target)?.get(propertyKey);
110
+ if (!stored && !standard) {
111
+ return undefined;
112
+ }
113
+ return cloneArgFieldMetadata(stored ?? standard);
114
+ }
115
+ export function getArgFieldMetadataEntries(target) {
116
+ return getMergedMetadataEntries(target, argFieldMetadataStore.get(target), getStandardArgFieldMap(target), getArgFieldMetadata);
117
+ }
118
+ export const resolverMetadataSymbol = standardResolverMetadataKey;
119
+ export const handlerMetadataSymbol = standardHandlerMetadataKey;
120
+ export const argMetadataSymbol = standardArgFieldMetadataKey;
@@ -0,0 +1,22 @@
1
+ import type { Provider } from '@fluojs/di';
2
+ import { type ModuleType } from '@fluojs/runtime';
3
+ import type { GraphqlModuleOptions } from './types.js';
4
+ /**
5
+ * Creates GraphQL runtime providers for module-level options and lifecycle wiring.
6
+ *
7
+ * @param options GraphQL module options used by the lifecycle service and endpoint controller.
8
+ * @returns Provider definitions that register only the internal options token and GraphQL lifecycle service; this helper
9
+ * does not register `GraphqlEndpointController` or mount the `/graphql` endpoint by itself.
10
+ */
11
+ export declare function createGraphqlProviders(options: GraphqlModuleOptions): Provider[];
12
+ export declare class GraphqlModule {
13
+ /**
14
+ * Registers the GraphQL endpoint controller together with lifecycle providers.
15
+ *
16
+ * @param options Optional GraphQL module options for schema, resolver discovery, context, and plugins.
17
+ * @returns A module definition that wires GraphQL runtime behavior and mounts the GraphQL endpoint controller; use this
18
+ * module path (not `createGraphqlProviders(...)` alone) when the application should expose `/graphql`.
19
+ */
20
+ static forRoot(options?: GraphqlModuleOptions): ModuleType;
21
+ }
22
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,GAAG,QAAQ,EAAE,CAQhF;AAED,qBAAa,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,oBAAyB,GAAG,UAAU;CAS/D"}