@fluojs/graphql 1.0.4 → 1.1.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/README.ko.md CHANGED
@@ -22,6 +22,8 @@ fluo를 위한 데코레이터 기반 GraphQL 통합 패키지입니다. **Graph
22
22
  pnpm add @fluojs/graphql graphql graphql-yoga
23
23
  ```
24
24
 
25
+ `@fluojs/graphql`은 Node.js `>=20.16.0`을 지원하며, 이 유효 하한을 `engines.node`로 선언합니다. 필수 dependency graph는 `@fluojs/runtime`을 통해 `@fluojs/config`에 도달하며, `@fluojs/config`도 Node.js `>=20.16.0`을 요구합니다. 다른 필수 first-party dependency가 선언한 더 낮은 하한은 이 범위와 호환됩니다. HTTP query/mutation과 기본 SSE subscription 경로는 내부적으로 Web-standard request/response primitive를 사용하지만, 이 구현 세부 사항이 Bun, Deno, Cloudflare Workers에 대한 package 지원을 의미하지는 않습니다. 전체 dependency metadata와 native runtime suite가 완전한 GraphQL 계약을 입증하기 전까지 해당 runtime은 지원하지 않습니다. 선택적 WebSocket subscription에는 server-backed Node HTTP/S upgrade 표면을 노출하는 adapter도 필요합니다.
26
+
25
27
  ## 사용 시점
26
28
 
27
29
  - TypeScript 데코레이터를 사용하여 타입 안전한 GraphQL API를 구축할 때 (**Code-first**).
@@ -73,15 +75,97 @@ await app.listen(3000);
73
75
  ## 핵심 기능
74
76
 
75
77
  ### Code-first Resolvers
76
- fluo는 표준 데코레이터를 사용하여 GraphQL 스키마를 정의합니다. `@Resolver`, `@Query`, `@Mutation`, `@Subscription`을 사용하여 클래스 메서드를 GraphQL 작업에 매핑합니다. GraphQL 인자는 input DTO 필드에 `@Arg(...)`로 선언하고, resolver 메서드는 작업의 `input` 옵션을 통해 해당 DTO를 받습니다.
78
+ fluo는 표준 데코레이터를 사용하여 GraphQL 스키마를 정의합니다. `@Resolver`, `@Query`, `@Mutation`, `@Subscription`을 사용하여 클래스 메서드를 GraphQL 작업에 매핑합니다. GraphQL 인자는 input DTO 필드에 `@Arg(...)`로 선언하고, resolver 메서드는 작업의 `input` 옵션을 통해 해당 DTO를 받습니다. Object field resolver는 `@Resolver('TypeName')`, `@FieldResolver(...)`, 명시적 `@Parent()` / `@Context()` method binding을 사용합니다.
79
+
80
+ Resolver 반환 타입은 TypeScript metadata에서 추론되지 않습니다. `outputType`이 없는 operation은 GraphQL `String`을 사용합니다. Object 결과에는 GraphQL output type을 전달해야 하고, array 결과에는 item type을 `listOf(...)`로 감싸야 합니다.
81
+
82
+ ```typescript
83
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
84
+ import { listOf, Query, Resolver } from '@fluojs/graphql';
85
+
86
+ const UserType = new GraphQLObjectType({
87
+ name: 'User',
88
+ fields: {
89
+ id: { type: GraphQLString },
90
+ name: { type: GraphQLString },
91
+ },
92
+ });
93
+
94
+ @Resolver()
95
+ class UserResolver {
96
+ @Query({ outputType: UserType })
97
+ async user() {
98
+ return userService.findCurrent();
99
+ }
100
+
101
+ @Query({ outputType: listOf(UserType) })
102
+ async users() {
103
+ return userService.findAll();
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### Object Field Resolver
109
+
110
+ `@FieldResolver(...)`는 provider method를 `@Resolver('TypeName')`이 소유하는 named object type의 field에 연결합니다. 대상 object type은 code-first root operation output에서 도달 가능해야 합니다. 해당 field가 `GraphQLObjectType`에 이미 존재하거나, schema builder가 field를 추가할 수 있도록 field resolver가 `type`을 선언해야 합니다.
111
+
112
+ TC39 표준 데코레이터는 parameter decorator를 지원하지 않습니다. fluo의 standard-decorator 계약을 지키기 위해 `@Parent()`와 `@Context()`는 zero-based parameter index를 바인딩하는 method decorator입니다. 기본값은 parent/source object를 parameter `0`에, `GraphQLContext`를 parameter `1`에 매핑합니다. Method 순서가 다르면 index를 명시적으로 전달하세요.
77
113
 
78
- 현재 `@fluojs/graphql` 런타임은 root operation resolver만 지원합니다. `author(book, context)` 같은 object field resolver 패턴은 아직 런타임 계약이 아니라 `packages/graphql/field-resolver-rfc.md`에 정리된 설계 초안입니다.
114
+ ```typescript
115
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
116
+ import { Context, FieldResolver, Parent, Query, Resolver, type GraphQLContext } from '@fluojs/graphql';
117
+
118
+ const AuthorType = new GraphQLObjectType({
119
+ name: 'Author',
120
+ fields: {
121
+ id: { type: GraphQLString },
122
+ name: { type: GraphQLString },
123
+ },
124
+ });
125
+
126
+ const BookType = new GraphQLObjectType({
127
+ name: 'Book',
128
+ fields: {
129
+ id: { type: GraphQLString },
130
+ title: { type: GraphQLString },
131
+ },
132
+ });
133
+
134
+ @Resolver()
135
+ class BookQueryResolver {
136
+ @Query({ outputType: BookType })
137
+ book() {
138
+ return { id: 'book-1', title: 'Standard GraphQL', authorId: 'author-1' };
139
+ }
140
+ }
141
+
142
+ @Resolver('Book')
143
+ class BookFieldResolver {
144
+ @FieldResolver({ fieldName: 'author', type: AuthorType })
145
+ @Parent()
146
+ @Context()
147
+ author(book: { authorId: string }, context: GraphQLContext) {
148
+ return authorLoader(context).load(book.authorId);
149
+ }
150
+ }
151
+ ```
152
+
153
+ 두 resolver class를 module provider 또는 controller로 등록하고, `GraphqlModule.forRoot({ resolvers })`를 allowlist로 사용할 때는 둘 다 포함하세요. 중복 `TypeName.fieldName` 등록, code-first root output에서 도달할 수 없는 field target, root operation method에 배치한 `@Parent()` / `@Context()` binding은 bootstrap 중 실패합니다. Field argument DTO binding과 schema-first field-resolver attachment는 첫 runtime 계약 범위 밖입니다. `nullable` option은 예약되어 있습니다. 기존 field nullability는 유지되며, `type`으로 추가한 field는 GraphQL의 nullable 기본값을 사용합니다.
79
154
 
80
155
  ### Request-Scoped DataLoaders
81
156
  내장된 DataLoader 통합을 통해 N+1 문제를 효율적으로 해결합니다. Loader는 각 GraphQL 작업마다 자동으로 격리됩니다.
82
157
 
83
158
  ```typescript
84
- import { createDataLoader, type GraphQLContext } from '@fluojs/graphql';
159
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
160
+ import { createDataLoader, type GraphQLContext, Query, Resolver } from '@fluojs/graphql';
161
+
162
+ const UserType = new GraphQLObjectType({
163
+ name: 'User',
164
+ fields: {
165
+ id: { type: GraphQLString },
166
+ name: { type: GraphQLString },
167
+ },
168
+ });
85
169
 
86
170
  const userLoader = createDataLoader(async (ids: string[]) => {
87
171
  const users = await userService.findByIds(ids);
@@ -95,7 +179,7 @@ class UserInput {
95
179
 
96
180
  @Resolver()
97
181
  class UserResolver {
98
- @Query({ input: UserInput })
182
+ @Query({ input: UserInput, outputType: UserType })
99
183
  async user(input: UserInput, context: GraphQLContext) {
100
184
  return userLoader(context).load(input.id);
101
185
  }
@@ -108,6 +192,7 @@ class UserResolver {
108
192
  - Request-scoped provider를 주입하는 resolver는 resolver 자체에도 `@Scope('request')`를 지정해야 합니다. 이렇게 해야 DI lifetime 규칙이 명시적으로 유지되고 singleton-to-request dependency mismatch를 피할 수 있습니다.
109
193
  - `@fluojs/graphql`은 HTTP GraphQL 요청 또는 WebSocket subscription operation마다 operation-scoped DI 컨테이너를 하나 만들고, 해당 operation 안의 resolver 호출들이 이를 공유하며, operation 완료 또는 WebSocket operation 종료 시 dispose합니다.
110
194
  - Resolver 메서드는 `GraphQLContext`를 받으며, 내장 필드에는 fluo `request`, middleware 또는 guard가 설정한 인증된 HTTP `principal`, WebSocket subscription의 `connectionParams`와 `socket`, 그리고 `GraphqlModule.forRoot({ context })`가 반환한 사용자 정의 필드가 포함됩니다.
195
+ - Object field resolver는 root resolver와 같은 provider scope 및 operation container를 사용합니다. `@Parent()`와 `@Context()`는 positional method argument만 제어합니다.
111
196
  - Request-scoped DataLoader helper는 같은 `GraphQLContext` operation 경계를 사용하므로 loader cache는 하나의 GraphQL operation 안에서만 공유됩니다.
112
197
  - 애플리케이션 shutdown은 WebSocket transport를 등록 해제하고, 살아 있는 WebSocket client를 닫으며, 아직 활성 상태인 WebSocket operation container를 정상 operation 완료 때와 같은 request-scoped provider teardown 경로로 dispose합니다.
113
198
 
@@ -139,7 +224,7 @@ class RequestResolver {
139
224
  - **SSE**: Server-Sent Events를 통한 구독(기본값).
140
225
  - **WebSockets**: 활성 adapter가 upgrade listener를 지원하는 Node HTTP/S 서버를 노출할 때(예: Node HTTP adapter) 사용할 수 있는 선택적 `graphql-ws` 실시간 구독 지원.
141
226
 
142
- HTTP query/mutation과 기본 SSE subscription 경로는 fluo의 portable HTTP 추상화를 통해 실행됩니다. 선택적 WebSocket transport 의도적으로 더 좁은 범위를 가집니다. Server-backed Node HTTP/S adapter 표면이 필요하므로 Bun, Deno, Cloudflare Workers 배포에서는 adapter가 호환되는 upgrade listener를 노출하지 않는 기본 SSE 경로를 유지해야 합니다.
227
+ 지원되는 Node.js `>=20.16.0` runtime에서 HTTP query/mutation과 기본 SSE subscription 경로는 fluo의 Web-standard HTTP 추상화를 통해 실행됩니다. 내부 transport seam은 Bun, Deno, Cloudflare Workers 지원 보장이 아닙니다. 선택적 WebSocket transport는 server-backed Node HTTP/S adapter 표면도 필요하므로 지원 범위가 더 좁습니다.
143
228
 
144
229
  ```typescript
145
230
  GraphqlModule.forRoot({
@@ -197,7 +282,8 @@ GraphqlModule.forRoot({
197
282
  ## 공개 API
198
283
 
199
284
  - `GraphqlModule.forRoot(options)`: GraphQL 통합을 위한 메인 엔트리 포인트.
200
- - `Resolver`, `Query`, `Mutation`, `Subscription`: 작업 데코레이터.
285
+ - `Resolver`, `Query`, `Mutation`, `Subscription`: Resolver 및 root operation 데코레이터.
286
+ - `FieldResolver`, `Parent`, `Context`: Code-first object field resolution과 명시적 parent/context parameter-index binding.
201
287
  - `Arg`: Input DTO 필드를 GraphQL 인자로 매핑하는 데코레이터.
202
288
  - `createDataLoader`, `createDataLoaderMap`, `getRequestScopedDataLoader`, `createRequestScopedDataLoaderFactory`, `DataLoader`: DataLoader factory helper와 type.
203
289
  - `listOf`, `isGraphqlListTypeRef`: list output type reference helper.
@@ -214,4 +300,6 @@ GraphqlModule.forRoot({
214
300
  ## 예제 소스
215
301
 
216
302
  - `packages/graphql/src/module.test.ts`: 모듈 등록, resolver 실행, request-scoped container, subscription, guardrail 기본값을 다루는 통합 테스트 및 사용 예제.
217
- - `packages/graphql/field-resolver-rfc.md`: 현재 런타임 계약에 포함되지 않는 field-resolver 패턴의 설계 노트.
303
+ - `packages/graphql/src/field-resolver.test.ts`: Object field resolver의 discovery, schema attachment, parent/context binding, invalid placement를 실행 가능한 형태로 검증하는 테스트.
304
+ - `packages/graphql/src/runtime-support.test.ts`: Package의 Node.js engine 하한이 필수 first-party dependency graph에서 가장 높은 하한 이상인지 검증하는 회귀 테스트.
305
+ - `packages/graphql/field-resolver-rfc.md`: Object field resolver의 구현된 계약과 후속 범위.
package/README.md CHANGED
@@ -22,6 +22,8 @@ Decorator-based GraphQL integration for fluo. Built on **GraphQL Yoga**, it prov
22
22
  pnpm add @fluojs/graphql graphql graphql-yoga
23
23
  ```
24
24
 
25
+ `@fluojs/graphql` supports Node.js `>=20.16.0` and declares that effective floor through `engines.node`. Its mandatory dependency graph reaches `@fluojs/config` through `@fluojs/runtime`; `@fluojs/config` also requires Node.js `>=20.16.0`, while the lower floors declared by other mandatory first-party dependencies remain compatible. HTTP queries/mutations and the default SSE subscription path use Web-standard request/response primitives internally, but that implementation detail does not establish package support for Bun, Deno, or Cloudflare Workers. Those runtimes remain unsupported until the complete dependency metadata and native runtime suites prove the full GraphQL contract. Optional WebSocket subscriptions additionally require an adapter that exposes a server-backed Node HTTP/S upgrade surface.
26
+
25
27
  ## When to Use
26
28
 
27
29
  - When building type-safe GraphQL APIs using TypeScript decorators (**Code-first**).
@@ -73,15 +75,97 @@ await app.listen(3000);
73
75
  ## Core Capabilities
74
76
 
75
77
  ### Code-first Resolvers
76
- fluo uses standard decorators to define your GraphQL schema. Use `@Resolver`, `@Query`, `@Mutation`, and `@Subscription` to map class methods to GraphQL operations. GraphQL arguments are declared on input DTO fields with `@Arg(...)`, then passed to the resolver method through the operation `input` option.
78
+ fluo uses standard decorators to define your GraphQL schema. Use `@Resolver`, `@Query`, `@Mutation`, and `@Subscription` to map class methods to GraphQL operations. GraphQL arguments are declared on input DTO fields with `@Arg(...)`, then passed to the resolver method through the operation `input` option. Object field resolvers use `@Resolver('TypeName')` plus `@FieldResolver(...)` and explicit `@Parent()` / `@Context()` method bindings.
79
+
80
+ Resolver return types are not inferred from TypeScript metadata. An operation without `outputType` uses GraphQL `String`; object results must provide a GraphQL output type, and array results must wrap their item type with `listOf(...)`.
81
+
82
+ ```typescript
83
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
84
+ import { listOf, Query, Resolver } from '@fluojs/graphql';
85
+
86
+ const UserType = new GraphQLObjectType({
87
+ name: 'User',
88
+ fields: {
89
+ id: { type: GraphQLString },
90
+ name: { type: GraphQLString },
91
+ },
92
+ });
93
+
94
+ @Resolver()
95
+ class UserResolver {
96
+ @Query({ outputType: UserType })
97
+ async user() {
98
+ return userService.findCurrent();
99
+ }
100
+
101
+ @Query({ outputType: listOf(UserType) })
102
+ async users() {
103
+ return userService.findAll();
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### Object Field Resolvers
109
+
110
+ `@FieldResolver(...)` attaches a provider method to a field on the named object type owned by `@Resolver('TypeName')`. The target object type must be reachable from a code-first root operation output. The field must already exist on that `GraphQLObjectType`, or the field resolver must declare `type` so the schema builder can add it.
111
+
112
+ TC39 standard decorators do not support parameter decorators. To preserve fluo's standard-decorator contract, `@Parent()` and `@Context()` are method decorators that bind zero-based parameter indexes. Their defaults map the parent/source object to parameter `0` and `GraphQLContext` to parameter `1`; pass an explicit index when your method uses a different order.
77
113
 
78
- `@fluojs/graphql` currently supports root operation resolvers only. Object field-resolver patterns such as `author(book, context)` remain design-only and are documented in `packages/graphql/field-resolver-rfc.md`, not in the runtime contract.
114
+ ```typescript
115
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
116
+ import { Context, FieldResolver, Parent, Query, Resolver, type GraphQLContext } from '@fluojs/graphql';
117
+
118
+ const AuthorType = new GraphQLObjectType({
119
+ name: 'Author',
120
+ fields: {
121
+ id: { type: GraphQLString },
122
+ name: { type: GraphQLString },
123
+ },
124
+ });
125
+
126
+ const BookType = new GraphQLObjectType({
127
+ name: 'Book',
128
+ fields: {
129
+ id: { type: GraphQLString },
130
+ title: { type: GraphQLString },
131
+ },
132
+ });
133
+
134
+ @Resolver()
135
+ class BookQueryResolver {
136
+ @Query({ outputType: BookType })
137
+ book() {
138
+ return { id: 'book-1', title: 'Standard GraphQL', authorId: 'author-1' };
139
+ }
140
+ }
141
+
142
+ @Resolver('Book')
143
+ class BookFieldResolver {
144
+ @FieldResolver({ fieldName: 'author', type: AuthorType })
145
+ @Parent()
146
+ @Context()
147
+ author(book: { authorId: string }, context: GraphQLContext) {
148
+ return authorLoader(context).load(book.authorId);
149
+ }
150
+ }
151
+ ```
152
+
153
+ Register both resolver classes as module providers or controllers and include both when `GraphqlModule.forRoot({ resolvers })` is used as an allowlist. Duplicate `TypeName.fieldName` registrations, field targets that are not reachable from a code-first root output, and `@Parent()` / `@Context()` bindings placed on root operation methods fail during bootstrap. Field argument DTO binding and schema-first field-resolver attachment remain outside this first runtime contract. The `nullable` option is reserved; existing field nullability is preserved, while fields added with `type` use GraphQL's nullable default.
79
154
 
80
155
  ### Request-Scoped DataLoaders
81
156
  Efficiently solve the N+1 problem with built-in DataLoader integration. Loaders are automatically isolated per GraphQL operation.
82
157
 
83
158
  ```typescript
84
- import { createDataLoader, type GraphQLContext } from '@fluojs/graphql';
159
+ import { GraphQLObjectType, GraphQLString } from 'graphql';
160
+ import { createDataLoader, type GraphQLContext, Query, Resolver } from '@fluojs/graphql';
161
+
162
+ const UserType = new GraphQLObjectType({
163
+ name: 'User',
164
+ fields: {
165
+ id: { type: GraphQLString },
166
+ name: { type: GraphQLString },
167
+ },
168
+ });
85
169
 
86
170
  const userLoader = createDataLoader(async (ids: string[]) => {
87
171
  const users = await userService.findByIds(ids);
@@ -95,7 +179,7 @@ class UserInput {
95
179
 
96
180
  @Resolver()
97
181
  class UserResolver {
98
- @Query({ input: UserInput })
182
+ @Query({ input: UserInput, outputType: UserType })
99
183
  async user(input: UserInput, context: GraphQLContext) {
100
184
  return userLoader(context).load(input.id);
101
185
  }
@@ -108,6 +192,7 @@ class UserResolver {
108
192
  - Resolvers that inject request-scoped providers must also be marked with `@Scope('request')`; this keeps DI lifetime rules explicit and avoids singleton-to-request dependency mismatches.
109
193
  - `@fluojs/graphql` creates one operation-scoped DI container for each HTTP GraphQL request or websocket subscription operation, shares it across resolver calls in that operation, and disposes it when the operation completes or the websocket operation disconnects.
110
194
  - Resolver methods receive a `GraphQLContext` whose built-in fields expose the underlying fluo `request`, the authenticated HTTP `principal` when middleware or guards set one, websocket `connectionParams` and `socket` for websocket subscriptions, and any custom fields returned from `GraphqlModule.forRoot({ context })`.
195
+ - Object field resolvers use the same provider scope and operation container as root resolvers; `@Parent()` and `@Context()` only control positional method arguments.
111
196
  - Request-scoped DataLoader helpers use the same `GraphQLContext` operation boundary, so loader caches are shared only within one GraphQL operation.
112
197
  - Application shutdown unregisters the websocket transport, closes live websocket clients, and disposes any still-active websocket operation containers through the same request-scoped provider teardown path used when an operation completes normally.
113
198
 
@@ -139,7 +224,7 @@ class RequestResolver {
139
224
  - **SSE**: Subscriptions over Server-Sent Events (default).
140
225
  - **WebSockets**: Optional `graphql-ws` support for real-time subscriptions when the active adapter exposes a Node HTTP/S server with upgrade listeners (for example, the Node HTTP adapter).
141
226
 
142
- HTTP queries/mutations and the default SSE subscription path run through fluo's portable HTTP abstraction. The optional websocket transport is intentionally narrower: it requires a server-backed Node HTTP/S adapter surface, so Bun, Deno, and Cloudflare Workers deployments should keep the default SSE path unless their adapter exposes compatible upgrade listeners.
227
+ On the supported Node.js `>=20.16.0` runtime, HTTP queries/mutations and the default SSE subscription path run through fluo's Web-standard HTTP abstraction. This internal transport seam is not a Bun, Deno, or Cloudflare Workers support guarantee. The optional websocket transport is narrower still because it requires a server-backed Node HTTP/S adapter surface.
143
228
 
144
229
  ```typescript
145
230
  GraphqlModule.forRoot({
@@ -197,7 +282,8 @@ GraphqlModule.forRoot({
197
282
  ## Public API
198
283
 
199
284
  - `GraphqlModule.forRoot(options)`: Main entry point for GraphQL integration.
200
- - `Resolver`, `Query`, `Mutation`, `Subscription`: Operation decorators.
285
+ - `Resolver`, `Query`, `Mutation`, `Subscription`: Resolver and root operation decorators.
286
+ - `FieldResolver`, `Parent`, `Context`: Code-first object field resolution and explicit parent/context parameter-index bindings.
201
287
  - `Arg`: Input DTO field-to-GraphQL-argument mapping decorator.
202
288
  - `createDataLoader`, `createDataLoaderMap`, `getRequestScopedDataLoader`, `createRequestScopedDataLoaderFactory`, `DataLoader`: DataLoader factory helpers and types.
203
289
  - `listOf`, `isGraphqlListTypeRef`: Helpers for list output type references.
@@ -214,4 +300,6 @@ Supported module options include `schema`, `context`, `plugins`, `graphiql`, `in
214
300
  ## Example Sources
215
301
 
216
302
  - `packages/graphql/src/module.test.ts`: Integration tests and usage examples for module registration, resolver execution, request-scoped containers, subscriptions, and guardrail defaults.
217
- - `packages/graphql/field-resolver-rfc.md`: Design notes for field-resolver patterns that are not part of the current runtime contract.
303
+ - `packages/graphql/src/field-resolver.test.ts`: Executable discovery, schema attachment, parent/context binding, and invalid-placement coverage for object field resolvers.
304
+ - `packages/graphql/src/runtime-support.test.ts`: Regression coverage that keeps the package's Node.js engine floor at or above the highest floor in its mandatory first-party dependency graph.
305
+ - `packages/graphql/field-resolver-rfc.md`: Implemented contract and follow-up boundaries for object field resolvers.
@@ -11,6 +11,14 @@ export interface ResolverMethodOptions {
11
11
  argTypes?: Record<string, GraphqlArgType>;
12
12
  outputType?: GraphqlRootOutputType;
13
13
  }
14
+ /**
15
+ * Describes an object field resolver's field name and optional output type override.
16
+ */
17
+ export interface FieldResolverOptions {
18
+ fieldName?: string;
19
+ type?: GraphqlRootOutputType;
20
+ nullable?: boolean;
21
+ }
14
22
  type ClassDecoratorLike = StandardClassDecoratorFn;
15
23
  type MethodDecoratorLike = StandardMethodDecoratorFn;
16
24
  type FieldDecoratorLike = StandardFieldDecoratorFn;
@@ -42,6 +50,37 @@ export declare function Mutation(fieldNameOrOptions?: string | ResolverMethodOpt
42
50
  * @returns The subscription result.
43
51
  */
44
52
  export declare function Subscription(fieldNameOrOptions?: string | ResolverMethodOptions): MethodDecoratorLike;
53
+ /**
54
+ * Marks a public instance method as the resolver for one field on the object type owned by `@Resolver(typeName)`.
55
+ *
56
+ * @param fieldNameOrOptions Field name or object field resolver options.
57
+ * @returns A TC39 standard method decorator.
58
+ */
59
+ export declare function FieldResolver(fieldNameOrOptions?: string | FieldResolverOptions): MethodDecoratorLike;
60
+ /**
61
+ * Binds a field resolver method parameter to GraphQL's parent/source object.
62
+ *
63
+ * @remarks
64
+ * TC39 standard decorators do not support parameter-decorator syntax, so this
65
+ * standard method decorator records the parameter index explicitly. The default
66
+ * index is `0`.
67
+ *
68
+ * @param parameterIndex Zero-based method parameter index to receive the parent value.
69
+ * @returns A TC39 standard method decorator.
70
+ */
71
+ export declare function Parent(parameterIndex?: number): MethodDecoratorLike;
72
+ /**
73
+ * Binds a field resolver method parameter to the active `GraphQLContext`.
74
+ *
75
+ * @remarks
76
+ * TC39 standard decorators do not support parameter-decorator syntax, so this
77
+ * standard method decorator records the parameter index explicitly. The default
78
+ * index is `1`.
79
+ *
80
+ * @param parameterIndex Zero-based method parameter index to receive the context value.
81
+ * @returns A TC39 standard method decorator.
82
+ */
83
+ export declare function Context(parameterIndex?: number): MethodDecoratorLike;
45
84
  /**
46
85
  * Arg.
47
86
  *
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAoB,cAAc,EAAE,qBAAqB,EAA6C,MAAM,YAAY,CAAC;AAGrI,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AAE1H;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC;AAED,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AACrD,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AAyGnD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAQ9D;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAEjG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAmBxD"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAIV,cAAc,EACd,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AAGpB,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AAE1H;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AACrD,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AA8KnD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAQ9D;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAEjG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,oBAAoB,GAAG,mBAAmB,CAerG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,cAAc,SAAI,GAAG,mBAAmB,CAE9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,cAAc,SAAI,GAAG,mBAAmB,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAmBxD"}
@@ -1,10 +1,14 @@
1
1
  import { ensureMetadataSymbol } from '@fluojs/core/internal';
2
- import { argMetadataSymbol, handlerMetadataSymbol, resolverMetadataSymbol } from './metadata.js';
2
+ import { argMetadataSymbol, fieldResolverParameterMetadataSymbol, handlerMetadataSymbol, resolverMetadataSymbol } from './metadata.js';
3
3
 
4
4
  /**
5
5
  * Describes the resolver method options contract.
6
6
  */
7
7
 
8
+ /**
9
+ * Describes an object field resolver's field name and optional output type override.
10
+ */
11
+
8
12
  ensureMetadataSymbol();
9
13
  function getStandardMetadataBag(metadata) {
10
14
  return metadata;
@@ -53,11 +57,28 @@ function defineStandardHandlerMetadata(metadata, propertyKey, handlerMetadata) {
53
57
  argTypes: handlerMetadata.argTypes,
54
58
  fieldName: handlerMetadata.fieldName,
55
59
  inputClass: handlerMetadata.inputClass,
60
+ nullable: handlerMetadata.nullable,
56
61
  outputType: handlerMetadata.outputType,
57
62
  type: handlerMetadata.type
58
63
  });
59
64
  bag[handlerMetadataSymbol] = map;
60
65
  }
66
+ function defineStandardFieldResolverParameterMetadata(metadata, propertyKey, parameterIndex, kind) {
67
+ const bag = getStandardMetadataBag(metadata);
68
+ const current = bag[fieldResolverParameterMetadataSymbol];
69
+ const methods = current ?? new Map();
70
+ const bindings = methods.get(propertyKey) ?? new Map();
71
+ const existing = bindings.get(parameterIndex);
72
+ if (existing) {
73
+ throw new Error(`GraphQL field resolver parameter ${String(parameterIndex)} on ${String(propertyKey)} is already bound to ${existing.kind}.`);
74
+ }
75
+ bindings.set(parameterIndex, {
76
+ index: parameterIndex,
77
+ kind
78
+ });
79
+ methods.set(propertyKey, bindings);
80
+ bag[fieldResolverParameterMetadataSymbol] = methods;
81
+ }
61
82
  function defineStandardArgFieldMetadata(metadata, propertyKey, argFieldMetadata) {
62
83
  const bag = getStandardMetadataBag(metadata);
63
84
  const current = bag[argMetadataSymbol];
@@ -82,6 +103,36 @@ function createMethodDecorator(type, fieldNameOrOptions) {
82
103
  };
83
104
  return decorator;
84
105
  }
106
+ function normalizeFieldResolverMetadata(fieldNameOrOptions) {
107
+ if (typeof fieldNameOrOptions === 'string') {
108
+ return {
109
+ fieldName: fieldNameOrOptions.trim() || undefined,
110
+ type: 'field'
111
+ };
112
+ }
113
+ return {
114
+ fieldName: fieldNameOrOptions?.fieldName?.trim() || undefined,
115
+ nullable: fieldNameOrOptions?.nullable,
116
+ outputType: fieldNameOrOptions?.type,
117
+ type: 'field'
118
+ };
119
+ }
120
+ function createFieldResolverParameterDecorator(kind, parameterIndex) {
121
+ if (!Number.isSafeInteger(parameterIndex) || parameterIndex < 0) {
122
+ throw new Error(`@${kind === 'parent' ? 'Parent' : 'Context'}() parameter index must be a non-negative integer.`);
123
+ }
124
+ const decorator = (_value, context) => {
125
+ const name = kind === 'parent' ? 'Parent' : 'Context';
126
+ if (context.private) {
127
+ throw new Error(`@${name}() cannot be used on private methods.`);
128
+ }
129
+ if (context.static) {
130
+ throw new Error(`@${name}() cannot be used on static methods.`);
131
+ }
132
+ defineStandardFieldResolverParameterMetadata(context.metadata, context.name, parameterIndex, kind);
133
+ };
134
+ return decorator;
135
+ }
85
136
 
86
137
  /**
87
138
  * Resolver.
@@ -128,6 +179,56 @@ export function Subscription(fieldNameOrOptions) {
128
179
  return createMethodDecorator('subscription', fieldNameOrOptions);
129
180
  }
130
181
 
182
+ /**
183
+ * Marks a public instance method as the resolver for one field on the object type owned by `@Resolver(typeName)`.
184
+ *
185
+ * @param fieldNameOrOptions Field name or object field resolver options.
186
+ * @returns A TC39 standard method decorator.
187
+ */
188
+ export function FieldResolver(fieldNameOrOptions) {
189
+ const metadata = normalizeFieldResolverMetadata(fieldNameOrOptions);
190
+ const decorator = (_value, context) => {
191
+ if (context.private) {
192
+ throw new Error('@FieldResolver() cannot be used on private methods.');
193
+ }
194
+ if (context.static) {
195
+ throw new Error('@FieldResolver() cannot be used on static methods.');
196
+ }
197
+ defineStandardHandlerMetadata(context.metadata, context.name, metadata);
198
+ };
199
+ return decorator;
200
+ }
201
+
202
+ /**
203
+ * Binds a field resolver method parameter to GraphQL's parent/source object.
204
+ *
205
+ * @remarks
206
+ * TC39 standard decorators do not support parameter-decorator syntax, so this
207
+ * standard method decorator records the parameter index explicitly. The default
208
+ * index is `0`.
209
+ *
210
+ * @param parameterIndex Zero-based method parameter index to receive the parent value.
211
+ * @returns A TC39 standard method decorator.
212
+ */
213
+ export function Parent(parameterIndex = 0) {
214
+ return createFieldResolverParameterDecorator('parent', parameterIndex);
215
+ }
216
+
217
+ /**
218
+ * Binds a field resolver method parameter to the active `GraphQLContext`.
219
+ *
220
+ * @remarks
221
+ * TC39 standard decorators do not support parameter-decorator syntax, so this
222
+ * standard method decorator records the parameter index explicitly. The default
223
+ * index is `1`.
224
+ *
225
+ * @param parameterIndex Zero-based method parameter index to receive the context value.
226
+ * @returns A TC39 standard method decorator.
227
+ */
228
+ export function Context(parameterIndex = 1) {
229
+ return createFieldResolverParameterDecorator('context', parameterIndex);
230
+ }
231
+
131
232
  /**
132
233
  * Arg.
133
234
  *
@@ -1 +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;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,EAAE,CA8CtB"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAkI3E;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,EAAE,CAwDtB"}
package/dist/discovery.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getClassDiMetadata } from '@fluojs/core/internal';
2
- import { getArgFieldMetadataEntries, getResolverHandlerMetadataEntries, getResolverMetadata } from './metadata.js';
2
+ import { getArgFieldMetadataEntries, getFieldResolverParameterMetadataEntries, getResolverHandlerMetadataEntries, getResolverMetadata } from './metadata.js';
3
3
  function scopeFromProvider(provider, factoryResolverClass) {
4
4
  if (typeof provider === 'function') {
5
5
  return getClassDiMetadata(provider)?.scope ?? 'singleton';
@@ -127,6 +127,10 @@ export function discoverResolverDescriptors(compiledModules, options) {
127
127
  handlers: getResolverHandlerMetadataEntries(candidate.targetType.prototype).map(entry => {
128
128
  const inputClass = entry.metadata.inputClass;
129
129
  const argFields = inputClass !== undefined ? getArgFieldMetadataEntries(inputClass.prototype).map(argField => argField.metadata) : [];
130
+ const parameterBindings = getFieldResolverParameterMetadataEntries(candidate.targetType.prototype, entry.propertyKey);
131
+ if (entry.metadata.type !== 'field' && parameterBindings.length > 0) {
132
+ throw new Error(`@Parent() and @Context() can only bind parameters on @FieldResolver() methods. ` + `Invalid placement: ${candidate.targetType.name}.${methodKeyToName(entry.propertyKey)}.`);
133
+ }
130
134
  return {
131
135
  argFields,
132
136
  argTypes: entry.metadata.argTypes,
@@ -134,7 +138,9 @@ export function discoverResolverDescriptors(compiledModules, options) {
134
138
  inputClass,
135
139
  methodKey: entry.propertyKey,
136
140
  methodName: methodKeyToName(entry.propertyKey),
141
+ nullable: entry.metadata.nullable,
137
142
  outputType: entry.metadata.outputType,
143
+ parameterBindings,
138
144
  type: entry.metadata.type
139
145
  };
140
146
  }),
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './dataloader.js';
2
2
  export * from './decorators.js';
3
3
  export { GraphqlModule } from './module.js';
4
+ export type { ArgFieldMetadata, FieldResolverParameterBindingMetadata, FieldResolverParameterKind, GraphQLContext, GraphqlArgType, GraphqlListTypeRef, GraphqlModuleOptions, GraphqlRequestContext, GraphqlRequestLimitsOptions, GraphqlRootOutputNamedType, GraphqlRootOutputType, GraphqlScalarTypeName, GraphqlSubscriptionsOptions, GraphqlWebSocketSubscriptionsOptions, ResolverHandlerMetadata, ResolverHandlerType, ResolverMetadata, } from './types.js';
4
5
  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
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
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,YAAY,EACV,gBAAgB,EAChB,qCAAqC,EACrC,0BAA0B,EAC1B,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,oCAAoC,EACpC,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,oBAAoB,EACpB,MAAM,GACP,MAAM,YAAY,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { MetadataPropertyKey } from '@fluojs/core';
2
- import type { ArgFieldMetadata, ResolverHandlerMetadata, ResolverMetadata } from './types.js';
2
+ import type { ArgFieldMetadata, FieldResolverParameterBindingMetadata, ResolverHandlerMetadata, ResolverMetadata } from './types.js';
3
3
  /**
4
4
  * Define resolver metadata.
5
5
  *
@@ -66,6 +66,22 @@ export declare function getArgFieldMetadataEntries(target: object): Array<{
66
66
  metadata: ArgFieldMetadata;
67
67
  propertyKey: MetadataPropertyKey;
68
68
  }>;
69
+ /**
70
+ * Define one positional parameter binding for an object field resolver.
71
+ *
72
+ * @param target Resolver prototype that owns the decorated method.
73
+ * @param propertyKey Decorated method key.
74
+ * @param metadata Positional binding metadata to store.
75
+ */
76
+ export declare function defineFieldResolverParameterMetadata(target: object, propertyKey: MetadataPropertyKey, metadata: FieldResolverParameterBindingMetadata): void;
77
+ /**
78
+ * Get the positional parameter bindings declared for one resolver method.
79
+ *
80
+ * @param target Resolver prototype that owns the decorated method.
81
+ * @param propertyKey Decorated method key.
82
+ * @returns Parameter bindings ordered by their method parameter index.
83
+ */
84
+ export declare function getFieldResolverParameterMetadataEntries(target: object, propertyKey: MetadataPropertyKey): FieldResolverParameterBindingMetadata[];
69
85
  /**
70
86
  * Provides the resolver metadata symbol value.
71
87
  */
@@ -78,4 +94,8 @@ export declare const handlerMetadataSymbol: symbol;
78
94
  * Provides the arg metadata symbol value.
79
95
  */
80
96
  export declare const argMetadataSymbol: symbol;
97
+ /**
98
+ * Provides the object field-resolver parameter metadata symbol value.
99
+ */
100
+ export declare const fieldResolverParameterMetadataSymbol: symbol;
81
101
  //# sourceMappingURL=metadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoG9F;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAShF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,uBAAuB,GAAG,SAAS,CASrC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,uBAAuB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAOhF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEzH;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,CASlH;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAEzE;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,QAA8B,CAAC;AAClE;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAA6B,CAAC;AAChE;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAA8B,CAAC"}
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,OAAO,KAAK,EACV,gBAAgB,EAChB,qCAAqC,EACrC,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAwIpB;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAUhF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,uBAAuB,GAAG,SAAS,CAUrC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,uBAAuB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAOhF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAEzH;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,CAUlH;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAEzE;AAED;;;;;;GAMG;AACH,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,qCAAqC,GAC9C,IAAI,CAKN;AAED;;;;;;GAMG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,GAC/B,qCAAqC,EAAE,CAczC;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,QAA8B,CAAC;AAClE;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAA6B,CAAC;AAChE;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAA8B,CAAC;AAC7D;;GAEG;AACH,eAAO,MAAM,oCAAoC,QAA4C,CAAC"}