@effect-gql/core 1.3.4 → 1.4.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.
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { GraphQLDirective, GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLObjectType, GraphQLUnionType, GraphQLSchema, GraphQLNonNull, GraphQLString, GraphQLFloat, GraphQLBoolean, GraphQLInt, GraphQLList, parse, GraphQLError, validate, execute as execute$1, Kind, specifiedRules, NoSchemaIntrospectionCustomRule, subscribe, GraphQLScalarType } from 'graphql';
2
2
  export { DirectiveLocation, GraphQLBoolean, GraphQLEnumType, GraphQLFloat, GraphQLID, GraphQLInputObjectType, GraphQLInt, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString, GraphQLUnionType, Kind, graphql, lexicographicSortSchema, printSchema } from 'graphql';
3
3
  import { Pipeable, Context, Data, Layer, Effect, Ref, HashMap, Config, Option, Schema, Runtime, Queue, Stream, Fiber, Deferred } from 'effect';
4
- import * as S2 from 'effect/Schema';
4
+ import * as S from 'effect/Schema';
5
5
  import * as AST from 'effect/SchemaAST';
6
6
  import DataLoader from 'dataloader';
7
7
  import { HttpIncomingMessage, HttpServerResponse, HttpServerRequest, HttpRouter } from '@effect/platform';
@@ -21,6 +21,34 @@ var isIntegerType = (ast) => {
21
21
  }
22
22
  return false;
23
23
  };
24
+ var isOptionDeclaration = (ast) => {
25
+ if (ast._tag === "Declaration") {
26
+ const annotations = ast.annotations;
27
+ if (annotations) {
28
+ const TypeConstructorSymbol = /* @__PURE__ */ Symbol.for("effect/annotation/TypeConstructor");
29
+ const typeConstructor = annotations[TypeConstructorSymbol];
30
+ if (typeConstructor && typeConstructor._tag === "effect/Option") {
31
+ return true;
32
+ }
33
+ }
34
+ }
35
+ return false;
36
+ };
37
+ var isOptionTransformation = (ast) => {
38
+ if (ast._tag === "Transformation") {
39
+ return isOptionDeclaration(ast.to);
40
+ }
41
+ return false;
42
+ };
43
+ var getOptionInnerType = (ast) => {
44
+ if (ast._tag === "Declaration") {
45
+ const typeParams = ast.typeParameters;
46
+ if (typeParams && typeParams.length > 0) {
47
+ return typeParams[0];
48
+ }
49
+ }
50
+ return void 0;
51
+ };
24
52
  var toGraphQLType = (schema) => {
25
53
  const ast = schema.ast;
26
54
  if (ast._tag === "StringKeyword") return GraphQLString;
@@ -30,7 +58,7 @@ var toGraphQLType = (schema) => {
30
58
  if (isIntegerType(ast)) {
31
59
  return GraphQLInt;
32
60
  }
33
- return toGraphQLType(S2.make(ast.from));
61
+ return toGraphQLType(S.make(ast.from));
34
62
  }
35
63
  if (ast._tag === "Literal") {
36
64
  if (typeof ast.literal === "string") return GraphQLString;
@@ -42,7 +70,7 @@ var toGraphQLType = (schema) => {
42
70
  if (ast._tag === "TupleType") {
43
71
  const elements = ast.elements;
44
72
  if (elements.length > 0) {
45
- const elementSchema = S2.make(elements[0].type);
73
+ const elementSchema = S.make(elements[0].type);
46
74
  return new GraphQLList(toGraphQLType(elementSchema));
47
75
  }
48
76
  }
@@ -50,7 +78,8 @@ var toGraphQLType = (schema) => {
50
78
  const fields = {};
51
79
  for (const field2 of ast.propertySignatures) {
52
80
  const fieldName = String(field2.name);
53
- const fieldSchema = S2.make(field2.type);
81
+ if (fieldName === "_tag") continue;
82
+ const fieldSchema = S.make(field2.type);
54
83
  let fieldType = toGraphQLType(fieldSchema);
55
84
  if (!field2.isOptional) {
56
85
  fieldType = new GraphQLNonNull(fieldType);
@@ -64,17 +93,35 @@ var toGraphQLType = (schema) => {
64
93
  });
65
94
  }
66
95
  if (ast._tag === "Transformation") {
67
- return toGraphQLType(S2.make(ast.to));
96
+ if (isOptionTransformation(ast)) {
97
+ const innerType = getOptionInnerType(ast.to);
98
+ if (innerType) {
99
+ return toGraphQLType(S.make(innerType));
100
+ }
101
+ }
102
+ return toGraphQLType(S.make(ast.to));
103
+ }
104
+ if (ast._tag === "Declaration") {
105
+ if (isOptionDeclaration(ast)) {
106
+ const innerType = getOptionInnerType(ast);
107
+ if (innerType) {
108
+ return toGraphQLType(S.make(innerType));
109
+ }
110
+ }
111
+ const typeParams = ast.typeParameters;
112
+ if (typeParams && typeParams.length > 0) {
113
+ return toGraphQLType(S.make(typeParams[0]));
114
+ }
68
115
  }
69
116
  if (ast._tag === "Union") {
70
117
  const types = ast.types;
71
118
  if (types.length > 0) {
72
- return toGraphQLType(S2.make(types[0]));
119
+ return toGraphQLType(S.make(types[0]));
73
120
  }
74
121
  }
75
122
  if (ast._tag === "Suspend") {
76
123
  const innerAst = ast.f();
77
- return toGraphQLType(S2.make(innerAst));
124
+ return toGraphQLType(S.make(innerAst));
78
125
  }
79
126
  return GraphQLString;
80
127
  };
@@ -87,7 +134,7 @@ var toGraphQLInputType = (schema) => {
87
134
  if (isIntegerType(ast)) {
88
135
  return GraphQLInt;
89
136
  }
90
- return toGraphQLInputType(S2.make(ast.from));
137
+ return toGraphQLInputType(S.make(ast.from));
91
138
  }
92
139
  if (ast._tag === "Literal") {
93
140
  if (typeof ast.literal === "string") return GraphQLString;
@@ -99,7 +146,7 @@ var toGraphQLInputType = (schema) => {
99
146
  if (ast._tag === "TupleType") {
100
147
  const elements = ast.elements;
101
148
  if (elements.length > 0) {
102
- const elementSchema = S2.make(elements[0].type);
149
+ const elementSchema = S.make(elements[0].type);
103
150
  return new GraphQLList(toGraphQLInputType(elementSchema));
104
151
  }
105
152
  }
@@ -107,7 +154,8 @@ var toGraphQLInputType = (schema) => {
107
154
  const fields = {};
108
155
  for (const field2 of ast.propertySignatures) {
109
156
  const fieldName = String(field2.name);
110
- const fieldSchema = S2.make(field2.type);
157
+ if (fieldName === "_tag") continue;
158
+ const fieldSchema = S.make(field2.type);
111
159
  let fieldType = toGraphQLInputType(fieldSchema);
112
160
  if (!field2.isOptional) {
113
161
  fieldType = new GraphQLNonNull(fieldType);
@@ -121,27 +169,56 @@ var toGraphQLInputType = (schema) => {
121
169
  });
122
170
  }
123
171
  if (ast._tag === "Transformation") {
124
- return toGraphQLInputType(S2.make(ast.from));
172
+ return toGraphQLInputType(S.make(ast.from));
173
+ }
174
+ if (ast._tag === "Declaration") {
175
+ if (isOptionDeclaration(ast)) {
176
+ const innerType = getOptionInnerType(ast);
177
+ if (innerType) {
178
+ return toGraphQLInputType(S.make(innerType));
179
+ }
180
+ }
181
+ const typeParams = ast.typeParameters;
182
+ if (typeParams && typeParams.length > 0) {
183
+ return toGraphQLInputType(S.make(typeParams[0]));
184
+ }
125
185
  }
126
186
  if (ast._tag === "Union") {
127
187
  const types = ast.types;
188
+ const nonNullTypes = types.filter((t) => t._tag !== "Literal" || t.literal !== null).filter((t) => t._tag !== "UndefinedKeyword");
189
+ if (nonNullTypes.length > 0) {
190
+ return toGraphQLInputType(S.make(nonNullTypes[0]));
191
+ }
128
192
  if (types.length > 0) {
129
- return toGraphQLInputType(S2.make(types[0]));
193
+ return toGraphQLInputType(S.make(types[0]));
130
194
  }
131
195
  }
132
196
  if (ast._tag === "Suspend") {
133
197
  const innerAst = ast.f();
134
- return toGraphQLInputType(S2.make(innerAst));
198
+ return toGraphQLInputType(S.make(innerAst));
135
199
  }
136
200
  return GraphQLString;
137
201
  };
138
202
  var toGraphQLObjectType = (name, schema, additionalFields) => {
139
- const ast = schema.ast;
203
+ let ast = schema.ast;
204
+ while (ast._tag === "Transformation") {
205
+ ast = ast.to;
206
+ }
207
+ if (ast._tag === "Declaration") {
208
+ const typeParams = ast.typeParameters;
209
+ if (typeParams && typeParams.length > 0) {
210
+ ast = typeParams[0];
211
+ while (ast._tag === "Transformation") {
212
+ ast = ast.to;
213
+ }
214
+ }
215
+ }
140
216
  if (ast._tag === "TypeLiteral") {
141
217
  const fields = {};
142
218
  for (const field2 of ast.propertySignatures) {
143
219
  const fieldName = String(field2.name);
144
- const fieldSchema = S2.make(field2.type);
220
+ if (fieldName === "_tag") continue;
221
+ const fieldSchema = S.make(field2.type);
145
222
  let fieldType = toGraphQLType(fieldSchema);
146
223
  if (!field2.isOptional) {
147
224
  fieldType = new GraphQLNonNull(fieldType);
@@ -172,7 +249,8 @@ var toGraphQLArgs = (schema) => {
172
249
  const args = {};
173
250
  for (const field2 of ast.propertySignatures) {
174
251
  const fieldName = String(field2.name);
175
- const fieldSchema = S2.make(field2.type);
252
+ if (fieldName === "_tag") continue;
253
+ const fieldSchema = S.make(field2.type);
176
254
  let fieldType = toGraphQLInputType(fieldSchema);
177
255
  if (!field2.isOptional) {
178
256
  fieldType = new GraphQLNonNull(fieldType);
@@ -272,9 +350,21 @@ function toGraphQLTypeWithRegistry(schema, ctx) {
272
350
  if (ast._tag === "TupleType") {
273
351
  return handleTupleTypeAST(ast, ctx);
274
352
  }
353
+ if (ast._tag === "Declaration") {
354
+ if (isOptionDeclaration2(ast)) {
355
+ const innerType = getOptionInnerType2(ast);
356
+ if (innerType) {
357
+ return toGraphQLTypeWithRegistry(S.make(innerType), ctx);
358
+ }
359
+ }
360
+ const typeParams = ast.typeParameters;
361
+ if (typeParams && typeParams.length > 0) {
362
+ return toGraphQLTypeWithRegistry(S.make(typeParams[0]), ctx);
363
+ }
364
+ }
275
365
  if (ast._tag === "Suspend") {
276
366
  const innerAst = ast.f();
277
- return toGraphQLTypeWithRegistry(S2.make(innerAst), ctx);
367
+ return toGraphQLTypeWithRegistry(S.make(innerAst), ctx);
278
368
  }
279
369
  return toGraphQLType(schema);
280
370
  }
@@ -292,20 +382,48 @@ function findRegisteredInterface(schema, ast, ctx) {
292
382
  }
293
383
  return void 0;
294
384
  }
385
+ function isOptionDeclaration2(ast) {
386
+ if (ast._tag === "Declaration") {
387
+ const annotations = ast.annotations;
388
+ if (annotations) {
389
+ const TypeConstructorSymbol = /* @__PURE__ */ Symbol.for("effect/annotation/TypeConstructor");
390
+ const typeConstructor = annotations[TypeConstructorSymbol];
391
+ if (typeConstructor && typeConstructor._tag === "effect/Option") {
392
+ return true;
393
+ }
394
+ }
395
+ }
396
+ return false;
397
+ }
398
+ function getOptionInnerType2(ast) {
399
+ if (ast._tag === "Declaration") {
400
+ const typeParams = ast.typeParameters;
401
+ if (typeParams && typeParams.length > 0) {
402
+ return typeParams[0];
403
+ }
404
+ }
405
+ return void 0;
406
+ }
295
407
  function handleTransformationAST(ast, ctx) {
296
408
  const toAst = ast.to;
409
+ if (isOptionDeclaration2(toAst)) {
410
+ const innerType = getOptionInnerType2(toAst);
411
+ if (innerType) {
412
+ return toGraphQLTypeWithRegistry(S.make(innerType), ctx);
413
+ }
414
+ }
297
415
  if (toAst._tag === "TupleType") {
298
416
  if (toAst.rest && toAst.rest.length > 0) {
299
- const elementSchema = S2.make(toAst.rest[0].type);
417
+ const elementSchema = S.make(toAst.rest[0].type);
300
418
  const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
301
419
  return new GraphQLList(elementType);
302
420
  } else if (toAst.elements.length > 0) {
303
- const elementSchema = S2.make(toAst.elements[0].type);
421
+ const elementSchema = S.make(toAst.elements[0].type);
304
422
  const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
305
423
  return new GraphQLList(elementType);
306
424
  }
307
425
  }
308
- return toGraphQLTypeWithRegistry(S2.make(ast.to), ctx);
426
+ return toGraphQLTypeWithRegistry(S.make(ast.to), ctx);
309
427
  }
310
428
  function handleUnionAST(ast, ctx) {
311
429
  const allLiterals = ast.types.every((t) => t._tag === "Literal");
@@ -317,9 +435,9 @@ function handleUnionAST(ast, ctx) {
317
435
  if (unionType2) return unionType2;
318
436
  }
319
437
  if (ast.types.length > 0) {
320
- return toGraphQLTypeWithRegistry(S2.make(ast.types[0]), ctx);
438
+ return toGraphQLTypeWithRegistry(S.make(ast.types[0]), ctx);
321
439
  }
322
- return toGraphQLType(S2.make(ast));
440
+ return toGraphQLType(S.make(ast));
323
441
  }
324
442
  function findEnumForLiteralUnion(types, ctx) {
325
443
  const literalValues = types.map((t) => String(t.literal)).sort();
@@ -362,15 +480,15 @@ function findEnumForLiteral(ast, ctx) {
362
480
  }
363
481
  function handleTupleTypeAST(ast, ctx) {
364
482
  if (ast.rest && ast.rest.length > 0) {
365
- const elementSchema = S2.make(ast.rest[0].type);
483
+ const elementSchema = S.make(ast.rest[0].type);
366
484
  const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
367
485
  return new GraphQLList(elementType);
368
486
  } else if (ast.elements && ast.elements.length > 0) {
369
- const elementSchema = S2.make(ast.elements[0].type);
487
+ const elementSchema = S.make(ast.elements[0].type);
370
488
  const elementType = toGraphQLTypeWithRegistry(elementSchema, ctx);
371
489
  return new GraphQLList(elementType);
372
490
  }
373
- return toGraphQLType(S2.make(ast));
491
+ return toGraphQLType(S.make(ast));
374
492
  }
375
493
  function schemaToFields(schema, ctx) {
376
494
  let ast = schema.ast;
@@ -379,15 +497,22 @@ function schemaToFields(schema, ctx) {
379
497
  }
380
498
  if (ast._tag === "Declaration") {
381
499
  const typeParams = ast.typeParameters;
382
- if (typeParams && typeParams.length > 0 && typeParams[0]._tag === "TypeLiteral") {
383
- ast = typeParams[0];
500
+ if (typeParams && typeParams.length > 0) {
501
+ let innerAst = typeParams[0];
502
+ while (innerAst._tag === "Transformation") {
503
+ innerAst = innerAst.to;
504
+ }
505
+ if (innerAst._tag === "TypeLiteral") {
506
+ ast = innerAst;
507
+ }
384
508
  }
385
509
  }
386
510
  if (ast._tag === "TypeLiteral") {
387
511
  const fields = {};
388
512
  for (const field2 of ast.propertySignatures) {
389
513
  const fieldName = String(field2.name);
390
- const fieldSchema = S2.make(field2.type);
514
+ if (fieldName === "_tag") continue;
515
+ const fieldSchema = S.make(field2.type);
391
516
  let fieldType = toGraphQLTypeWithRegistry(fieldSchema, ctx);
392
517
  if (!field2.isOptional) {
393
518
  fieldType = getNonNull(fieldType);
@@ -399,12 +524,16 @@ function schemaToFields(schema, ctx) {
399
524
  return {};
400
525
  }
401
526
  function schemaToInputFields(schema, enumRegistry, inputRegistry, inputs, enums, cache) {
402
- const ast = schema.ast;
527
+ let ast = schema.ast;
528
+ while (ast._tag === "Transformation") {
529
+ ast = ast.to;
530
+ }
403
531
  if (ast._tag === "TypeLiteral") {
404
532
  const fields = {};
405
533
  for (const field2 of ast.propertySignatures) {
406
534
  const fieldName = String(field2.name);
407
- const fieldSchema = S2.make(field2.type);
535
+ if (fieldName === "_tag") continue;
536
+ const fieldSchema = S.make(field2.type);
408
537
  let fieldType = toGraphQLInputTypeWithRegistry(
409
538
  fieldSchema,
410
539
  enumRegistry,
@@ -443,17 +572,6 @@ function buildInputTypeLookupCache(inputs, enums) {
443
572
  }
444
573
  function toGraphQLInputTypeWithRegistry(schema, enumRegistry, inputRegistry, inputs, enums, cache) {
445
574
  const ast = schema.ast;
446
- if (ast._tag === "Transformation") {
447
- const toAst = ast.to;
448
- return toGraphQLInputTypeWithRegistry(
449
- S2.make(toAst),
450
- enumRegistry,
451
- inputRegistry,
452
- inputs,
453
- enums,
454
- cache
455
- );
456
- }
457
575
  if (cache?.schemaToInputName || cache?.astToInputName) {
458
576
  const inputName = cache.schemaToInputName?.get(schema) ?? cache.astToInputName?.get(ast);
459
577
  if (inputName) {
@@ -468,12 +586,23 @@ function toGraphQLInputTypeWithRegistry(schema, enumRegistry, inputRegistry, inp
468
586
  }
469
587
  }
470
588
  }
589
+ if (ast._tag === "Transformation") {
590
+ const toAst = ast.to;
591
+ return toGraphQLInputTypeWithRegistry(
592
+ S.make(toAst),
593
+ enumRegistry,
594
+ inputRegistry,
595
+ inputs,
596
+ enums,
597
+ cache
598
+ );
599
+ }
471
600
  if (ast._tag === "Union") {
472
601
  const unionAst = ast;
473
602
  const nonUndefinedTypes = unionAst.types.filter((t) => t._tag !== "UndefinedKeyword");
474
603
  if (nonUndefinedTypes.length === 1 && nonUndefinedTypes[0]._tag === "Union") {
475
604
  return toGraphQLInputTypeWithRegistry(
476
- S2.make(nonUndefinedTypes[0]),
605
+ S.make(nonUndefinedTypes[0]),
477
606
  enumRegistry,
478
607
  inputRegistry,
479
608
  inputs,
@@ -483,7 +612,7 @@ function toGraphQLInputTypeWithRegistry(schema, enumRegistry, inputRegistry, inp
483
612
  }
484
613
  if (nonUndefinedTypes.length === 1 && nonUndefinedTypes[0]._tag === "TypeLiteral") {
485
614
  return toGraphQLInputTypeWithRegistry(
486
- S2.make(nonUndefinedTypes[0]),
615
+ S.make(nonUndefinedTypes[0]),
487
616
  enumRegistry,
488
617
  inputRegistry,
489
618
  inputs,
@@ -523,7 +652,7 @@ function toGraphQLInputTypeWithRegistry(schema, enumRegistry, inputRegistry, inp
523
652
  if (ast._tag === "Suspend") {
524
653
  const innerAst = ast.f();
525
654
  return toGraphQLInputTypeWithRegistry(
526
- S2.make(innerAst),
655
+ S.make(innerAst),
527
656
  enumRegistry,
528
657
  inputRegistry,
529
658
  inputs,
@@ -539,7 +668,8 @@ function toGraphQLArgsWithRegistry(schema, enumRegistry, inputRegistry, inputs,
539
668
  const args = {};
540
669
  for (const field2 of ast.propertySignatures) {
541
670
  const fieldName = String(field2.name);
542
- const fieldSchema = S2.make(field2.type);
671
+ if (fieldName === "_tag") continue;
672
+ const fieldSchema = S.make(field2.type);
543
673
  let fieldType = toGraphQLInputTypeWithRegistry(
544
674
  fieldSchema,
545
675
  enumRegistry,
@@ -557,6 +687,29 @@ function toGraphQLArgsWithRegistry(schema, enumRegistry, inputRegistry, inputs,
557
687
  }
558
688
  return toGraphQLArgs(schema);
559
689
  }
690
+ function isOptionSchema(schema) {
691
+ const ast = schema.ast;
692
+ if (ast._tag === "Transformation") {
693
+ const toAst = ast.to;
694
+ if (toAst._tag === "Declaration") {
695
+ const annotations = toAst.annotations;
696
+ if (annotations) {
697
+ const TypeConstructorSymbol = /* @__PURE__ */ Symbol.for("effect/annotation/TypeConstructor");
698
+ const typeConstructor = annotations[TypeConstructorSymbol];
699
+ if (typeConstructor && typeConstructor._tag === "effect/Option") {
700
+ return true;
701
+ }
702
+ }
703
+ }
704
+ }
705
+ return false;
706
+ }
707
+ function encodeResolverOutput(schema, value) {
708
+ if (isOptionSchema(schema)) {
709
+ return Effect.orDie(S.encode(schema)(value));
710
+ }
711
+ return Effect.succeed(value);
712
+ }
560
713
  function applyDirectives(effect, directives, directiveRegistrations) {
561
714
  if (!directives) return effect;
562
715
  let wrapped = effect;
@@ -591,7 +744,8 @@ function buildField(config, ctx) {
591
744
  );
592
745
  const middlewareContext = { parent: _parent, args, info };
593
746
  effect = applyMiddleware(effect, middlewareContext, ctx.middlewares);
594
- return await Runtime.runPromise(context.runtime)(effect);
747
+ const result = await Runtime.runPromise(context.runtime)(effect);
748
+ return await Runtime.runPromise(context.runtime)(encodeResolverOutput(config.type, result));
595
749
  }
596
750
  };
597
751
  if (config.args) {
@@ -620,7 +774,8 @@ function buildObjectField(config, ctx) {
620
774
  );
621
775
  const middlewareContext = { parent, args, info };
622
776
  effect = applyMiddleware(effect, middlewareContext, ctx.middlewares);
623
- return await Runtime.runPromise(context.runtime)(effect);
777
+ const result = await Runtime.runPromise(context.runtime)(effect);
778
+ return await Runtime.runPromise(context.runtime)(encodeResolverOutput(config.type, result));
624
779
  }
625
780
  };
626
781
  if (config.args) {
@@ -655,13 +810,18 @@ function buildSubscriptionField(config, ctx) {
655
810
  return streamToAsyncIterator(stream, context.runtime);
656
811
  },
657
812
  // The resolve function transforms each yielded value
658
- // If no custom resolve is provided, return the payload directly
813
+ // If no custom resolve is provided, encode and return the payload directly
659
814
  resolve: config.resolve ? async (value, args, context, info) => {
660
815
  let effect = config.resolve(value, args);
661
816
  const middlewareContext = { parent: value, args, info };
662
817
  effect = applyMiddleware(effect, middlewareContext, ctx.middlewares);
663
- return await Runtime.runPromise(context.runtime)(effect);
664
- } : (value) => value
818
+ const result = await Runtime.runPromise(context.runtime)(effect);
819
+ return await Runtime.runPromise(context.runtime)(
820
+ encodeResolverOutput(config.type, result)
821
+ );
822
+ } : async (value, _args, context) => {
823
+ return await Runtime.runPromise(context.runtime)(encodeResolverOutput(config.type, value));
824
+ }
665
825
  };
666
826
  if (config.args) {
667
827
  fieldConfig.args = toGraphQLArgsWithRegistry(