@kubun/graphql 0.2.5 → 0.3.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/lib/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { GraphQLAttachmentID, GraphQLDocID } from './identifiers.js';
2
2
  export * as scalars from './scalars.js';
3
- export { type DocumentType, PatchOperation, SchemaBuilder, type SchemaBuilderParams, type SharedDefinitions, toList, } from './schema.js';
4
- export { getUniqueDocValue } from './utils.js';
3
+ export type { ContextType, DocumentType, ReadContextType, SchemaBuilderParams, SharedDefinitions, UpdateMutationInput, WriteContextType, } from './schema.js';
4
+ export { SchemaBuilder, createSchema } from './schema.js';
5
+ export type * from './types.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpE,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,EACL,KAAK,YAAY,EACjB,cAAc,EACd,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,MAAM,GACP,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpE,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,YAAY,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACzD,mBAAmB,YAAY,CAAA"}
package/lib/index.js CHANGED
@@ -1,4 +1,3 @@
1
1
  export { GraphQLAttachmentID, GraphQLDocID } from './identifiers.js';
2
2
  export * as scalars from './scalars.js';
3
- export { PatchOperation, SchemaBuilder, toList } from './schema.js';
4
- export { getUniqueDocValue } from './utils.js';
3
+ export { SchemaBuilder, createSchema } from './schema.js';
package/lib/schema.d.ts CHANGED
@@ -1,53 +1,87 @@
1
1
  import { AttachmentID, DocumentModelID } from '@kubun/id';
2
- import { type ArrayModel, type DocumentData, type DocumentModel, type DocumentModelSchema, type DocumentModelsRecord, type ObjectModel, type ReferencesRecordModel, type ScalarModel, type StringCustomModel, type StringEnumModel, type StringFormatModel, type StringModel, type TypeModel } from '@kubun/protocol';
3
- import { GraphQLEnumType, type GraphQLFieldConfig, type GraphQLFieldConfigMap, GraphQLInputObjectType, type GraphQLInputType, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, type GraphQLOutputType, type GraphQLScalarType, GraphQLSchema } from 'graphql';
4
- import { type Connection, type ConnectionArguments } from 'graphql-relay';
2
+ import type { ArrayModel, DocumentData, DocumentFilter, DocumentModel, DocumentModelSchema, DocumentModelsRecord, DocumentOrderBy, ObjectModel, ReferencesRecordModel, ScalarModel, StringCustomModel, StringEnumModel, StringFormatModel, StringModel, TypeModel } from '@kubun/protocol';
3
+ import { GraphQLEnumType, type GraphQLFieldConfig, type GraphQLFieldConfigMap, GraphQLInputObjectType, type GraphQLInputType, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, type GraphQLOutputType, type GraphQLResolveInfo, type GraphQLScalarType, GraphQLSchema } from 'graphql';
4
+ import { type Connection, type ConnectionArguments, type Edge } from 'graphql-relay';
5
+ import type { PatchOperation as PatchOperationType } from './types.js';
5
6
  export declare function toDocumentModelID(id: DocumentModelID | string): DocumentModelID;
6
7
  export declare function getGlobalID(id: DocumentModelID | string, globalID: DocumentModelID | string): DocumentModelID;
7
8
  export declare function toList(type: GraphQLInputType): GraphQLList<GraphQLNonNull<GraphQLInputType>>;
8
9
  export declare function toOuputList(type: GraphQLOutputType): GraphQLList<GraphQLNonNull<GraphQLOutputType>>;
9
10
  export declare const PatchOperation: GraphQLInputObjectType;
11
+ type AllConnectionArguments = ConnectionArguments & {
12
+ filter?: DocumentFilter;
13
+ orderBy?: DocumentOrderBy;
14
+ };
10
15
  export type DocumentType = {
11
16
  id: string;
12
17
  model: string;
13
18
  owner: string;
14
19
  data: DocumentData | null;
15
20
  };
16
- export type ContextType = Record<string, unknown>;
17
- export type GraphQLNodeDefinitions<Context extends ContextType = ContextType> = {
21
+ /**
22
+ * Query and subscription functions requiring server implementation
23
+ */
24
+ export type ReadContextType<Document extends DocumentType = DocumentType> = {
25
+ getViewer(): string | null;
26
+ loadDocument(id: string): Promise<Document | null>;
27
+ resolveConnection(modelIDs: Array<string>, args: AllConnectionArguments): Promise<Connection<Document>>;
28
+ resolveList(modelIDs: Array<string>, ids: Array<string>): Promise<Array<Document>>;
29
+ subscribeToDocumentCreated(modelIDs: Array<string>): AsyncGenerator<Document>;
30
+ subscribeToDocumentChanged(id: string): AsyncGenerator<Document>;
31
+ subscribeToDocumentRemoved(): AsyncGenerator<string>;
32
+ subscribeToDocumentEdgeAdded(modelIDs: Array<string>, hasRelation: (data: DocumentData) => boolean): AsyncGenerator<Edge<Document>>;
33
+ subscribeToDocumentEdgeRemoved(modelIDs: Array<string>, hasRelation: (data: DocumentData) => boolean): AsyncGenerator<string>;
34
+ };
35
+ /**
36
+ * Mutation function requiring client implementation
37
+ */
38
+ export type WriteContextType<Document extends DocumentType = DocumentType> = {
39
+ executeCreateMutation(modelID: string, data: DocumentData, info: GraphQLResolveInfo): Promise<Document>;
40
+ executeSetMutation(modelID: string, unique: Uint8Array, data: DocumentData, info: GraphQLResolveInfo): Promise<Document>;
41
+ executeUpdateMutation(input: UpdateMutationInput, info: GraphQLResolveInfo): Promise<Document>;
42
+ executeRemoveMutation(id: string, info: GraphQLResolveInfo): Promise<void>;
43
+ };
44
+ export type ContextType<Document extends DocumentType = DocumentType> = ReadContextType<Document> & WriteContextType<Document>;
45
+ export type UpdateMutationInput = {
46
+ id: string;
47
+ patch: Array<PatchOperationType>;
48
+ from?: DocumentData;
49
+ };
50
+ export type GraphQLNodeDefinitions<Context> = {
18
51
  nodeInterface: GraphQLInterfaceType;
19
52
  nodeField: GraphQLFieldConfig<unknown, Context>;
20
53
  nodesField: GraphQLFieldConfig<unknown, Context>;
21
54
  };
22
- export type SharedDefinitions<Document extends DocumentType = DocumentType, Context extends ContextType = ContextType> = GraphQLNodeDefinitions<Context> & {
55
+ export type SharedDefinitions<Document extends DocumentType = DocumentType, Context extends ContextType<Document> = ContextType<Document>> = GraphQLNodeDefinitions<Context> & {
23
56
  accountObject: GraphQLObjectType<string, Context>;
24
57
  attachmentObject: GraphQLObjectType<AttachmentID, Context>;
25
58
  documentInterface: GraphQLInterfaceType;
26
- documentMetadata: GraphQLObjectType<Document, Context>;
59
+ documentNodeFields: GraphQLFieldConfigMap<Document, Context>;
27
60
  queryFields: GraphQLFieldConfigMap<unknown, Context>;
28
61
  };
62
+ type RelationField = {
63
+ model: string;
64
+ isList: boolean;
65
+ };
66
+ type RelationFields = Record<string, RelationField>;
29
67
  export type SchemaBuilderParams = {
30
68
  aliases?: Record<string, string>;
31
69
  record: DocumentModelsRecord;
32
70
  };
33
- export declare class SchemaBuilder<Document extends DocumentType = DocumentType, Context extends ContextType = ContextType, Definitions extends SharedDefinitions<Document, Context> = SharedDefinitions<Document, Context>> {
71
+ export declare class SchemaBuilder<Document extends DocumentType = DocumentType, Context extends ContextType<Document> = ContextType<Document>, Definitions extends SharedDefinitions<Document, Context> = SharedDefinitions<Document, Context>> {
34
72
  _aliases: Record<string, string>;
35
73
  _definitions: Definitions | undefined;
36
74
  _implemented: Record<string, Array<string>>;
37
75
  _inputObjects: Record<string, GraphQLInputObjectType>;
38
- _mutations: Record<string, GraphQLFieldConfig<unknown, Context>>;
76
+ _mutations: GraphQLFieldConfigMap<unknown, Context>;
39
77
  _nodeModelIDs: Array<string>;
40
78
  _record: DocumentModelsRecord;
41
79
  _references: ReferencesRecordModel;
42
- _relationsTo: Record<string, Record<string, string>>;
80
+ _relationsTo: Record<string, RelationFields>;
81
+ _subscriptions: GraphQLFieldConfigMap<unknown, Context>;
43
82
  _types: Record<string, GraphQLOutputType>;
44
83
  constructor(params: SchemaBuilderParams);
45
84
  getModelIDs(id: string | null): Array<string>;
46
- getViewer(ctx: Context): string | null;
47
- loadDocument(id: string, ctx: Context): Promise<Document | null>;
48
- resolveConnection(model: string | null, args: ConnectionArguments, ctx: Context): Promise<Connection<Document>>;
49
- resolveList(model: string | null, ids: Array<string>, ctx: Context): Promise<Array<Document>>;
50
- buildMutations(id: string, definitions: Definitions): void;
51
85
  build(): GraphQLSchema;
52
86
  _getDefinitions(): Definitions;
53
87
  _getReference(path: string, parentName?: string): GraphQLOutputType;
@@ -55,6 +89,8 @@ export declare class SchemaBuilder<Document extends DocumentType = DocumentType,
55
89
  _getReferenceInput(path: string, isPartial: boolean, parentName?: string): GraphQLInputType;
56
90
  _buildSharedDefinitions(): Definitions;
57
91
  _buildDocument(id: string): GraphQLObjectType<Document, Context> | GraphQLInterfaceType;
92
+ _buildDocumentFields(id: string, model: DocumentModel, name: string): GraphQLFieldConfigMap<Document, Context>;
93
+ _buildDocumentDataObject(id: string, model: DocumentModel, name: string): GraphQLInterfaceType | GraphQLObjectType<DocumentData, Context>;
58
94
  _buildDocumentInput(id: string, model: DocumentModel): void;
59
95
  _buildReferenceFilterInput(path: string, parentName?: string): GraphQLInputType;
60
96
  _buildReferenceOrderByInput(path: string, parentName?: string): GraphQLInputType | null;
@@ -65,10 +101,14 @@ export declare class SchemaBuilder<Document extends DocumentType = DocumentType,
65
101
  _buildScalar(id: string, schema: ScalarModel, asInput?: boolean): GraphQLScalarType;
66
102
  _buildArray(schema: ArrayModel, parentName?: string): GraphQLList<GraphQLNonNull<GraphQLOutputType>>;
67
103
  _buildObject(id: string, schema: ObjectModel, parentName?: string): GraphQLObjectType;
68
- _buildObjectFields(id: string, schema: DocumentModelSchema | ObjectModel, model?: DocumentModel): Record<string, GraphQLFieldConfig<Document, Context>>;
104
+ _buildObjectFields(id: string, schema: DocumentModelSchema | ObjectModel): GraphQLFieldConfigMap<Record<string, unknown>, Context>;
105
+ _buildRelationFields(fields: GraphQLFieldConfigMap<Document, Context>, fieldName: string, relation: RelationField): void;
106
+ _buildRelationSubscriptions(fields: GraphQLFieldConfigMap<unknown, Context>, modelID: string, fieldName: string, relation: RelationField): void;
69
107
  _buildString(schema: StringModel, asInput: boolean): GraphQLEnumType | GraphQLObjectType | GraphQLScalarType;
70
108
  _buildCustomString(schema: StringCustomModel, asInput: boolean): GraphQLScalarType<unknown, unknown> | GraphQLObjectType<string, Context> | GraphQLObjectType<AttachmentID, Context>;
71
109
  _buildEnumString(schema: StringEnumModel): GraphQLEnumType;
72
110
  _buildFormatString(schema: StringFormatModel): GraphQLScalarType<unknown, unknown>;
73
111
  }
112
+ export declare function createSchema(record: DocumentModelsRecord, aliases?: Record<string, string>): GraphQLSchema;
113
+ export {};
74
114
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,eAAe,EAAY,MAAM,WAAW,CAAA;AAC/E,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,WAAW,EAEX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,WAAW,EAEX,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAGL,eAAe,EAEf,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAI1B,sBAAsB,EACtB,KAAK,gBAAgB,EAErB,oBAAoB,EACpB,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,aAAa,EAKd,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,IAAI,EAKV,MAAM,eAAe,CAAA;AAUtB,OAAO,KAAK,EAAE,cAAc,IAAI,kBAAkB,EAAE,MAAM,YAAY,CAAA;AA+CtE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,eAAe,GAAG,MAAM,GAAG,eAAe,CAE/E;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,eAAe,GAAG,MAAM,EAC5B,QAAQ,EAAE,eAAe,GAAG,MAAM,GACjC,eAAe,CAGjB;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,gBAAgB,iDAE5C;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,kDAElD;AAyFD,eAAO,MAAM,cAAc,wBAUzB,CAAA;AAUF,KAAK,sBAAsB,GAAG,mBAAmB,GAAG;IAClD,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,OAAO,CAAC,EAAE,eAAe,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,YAAY,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,QAAQ,SAAS,YAAY,GAAG,YAAY,IAAI;IAC1E,SAAS,IAAI,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;IAClD,iBAAiB,CACf,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;IAChC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IAClF,0BAA0B,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC7E,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IAChE,0BAA0B,IAAI,cAAc,CAAC,MAAM,CAAC,CAAA;IACpD,4BAA4B,CAC1B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GAC3C,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjC,8BAA8B,CAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GAC3C,cAAc,CAAC,MAAM,CAAC,CAAA;CAC1B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,QAAQ,SAAS,YAAY,GAAG,YAAY,IAAI;IAC3E,qBAAqB,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpB,kBAAkB,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpB,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9F,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3E,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,YAAY,GAAG,YAAY,IAAI,eAAe,CAAC,QAAQ,CAAC,GAC/F,gBAAgB,CAAC,QAAQ,CAAC,CAAA;AAE5B,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,sBAAsB,CAAC,OAAO,IAAI;IAC5C,aAAa,EAAE,oBAAoB,CAAA;IACnC,SAAS,EAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC/C,UAAU,EAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;CACjD,CAAA;AAED,MAAM,MAAM,iBAAiB,CAC3B,QAAQ,SAAS,YAAY,GAAG,YAAY,EAC5C,OAAO,SAAS,WAAW,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,IAC3D,sBAAsB,CAAC,OAAO,CAAC,GAAG;IACpC,aAAa,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjD,gBAAgB,EAAE,iBAAiB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IAC1D,iBAAiB,EAAE,oBAAoB,CAAA;IACvC,kBAAkB,EAAE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC5D,WAAW,EAAE,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;CACrD,CAAA;AAED,KAAK,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAA;AACvD,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;AAEnD,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,MAAM,EAAE,oBAAoB,CAAA;CAC7B,CAAA;AAED,qBAAa,aAAa,CACxB,QAAQ,SAAS,YAAY,GAAG,YAAY,EAC5C,OAAO,SAAS,WAAW,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,EAC7D,WAAW,SAAS,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC;IAG/F,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,YAAY,EAAE,WAAW,GAAG,SAAS,CAAA;IACrC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAK;IAChD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAA6C;IAClG,UAAU,EAAE,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAK;IACxD,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5B,OAAO,EAAE,oBAAoB,CAAA;IAC7B,WAAW,EAAE,qBAAqB,CAAK;IACvC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAK;IACjD,cAAc,EAAE,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAK;IAC5D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAuB;gBAEpD,MAAM,EAAE,mBAAmB;IA0CvC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IAI7C,KAAK,IAAI,aAAa;IA6EtB,eAAe,IAAI,WAAW;IAO9B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB;IAWnE,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS;IAQ1C,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,SAAK,GAAG,gBAAgB;IAwCvF,uBAAuB,IAAI,WAAW;IA6HtC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,oBAAoB;IA+GvF,oBAAoB,CAClB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,GACX,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC;IAyD3C,wBAAwB,CACtB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,GACX,oBAAoB,GAAG,iBAAiB,CAAC,YAAY,EAAE,OAAO,CAAC;IAoClE,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI;IAgC3D,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,gBAAgB;IAsC3E,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,gBAAgB,GAAG,IAAI;IAcnF,uBAAuB,CACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,mBAAmB,GAAG,WAAW,EACzC,UAAU,SAAK,EACf,UAAU,UAAQ;IAmCpB,wBAAwB,CACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,mBAAmB,GAAG,WAAW,EACzC,UAAU,SAAK,EACf,UAAU,UAAQ;IA4BpB,wBAAwB,CACtB,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,EACzB,aAAa,CAAC,EAAE,MAAM,GACrB,sBAAsB;IA4BzB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,SAAK,GAAG,iBAAiB;IAiBlF,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,UAAQ,GAAG,iBAAiB;IAkBjF,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,SAAK,GAAG,WAAW,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAOhG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,SAAK,GAAG,iBAAiB;IAKjF,kBAAkB,CAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,mBAAmB,GAAG,WAAW,GACxC,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAiB1D,oBAAoB,CAClB,MAAM,EAAE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAChD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,GACtB,IAAI;IA0BP,2BAA2B,CACzB,MAAM,EAAE,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,EAC/C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,aAAa,GACtB,IAAI;IAkCP,YAAY,CACV,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,OAAO,GACf,eAAe,GAAG,iBAAiB,GAAG,iBAAiB;IAa1D,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO;IAqB9D,gBAAgB,CAAC,MAAM,EAAE,eAAe;IAQxC,kBAAkB,CAAC,MAAM,EAAE,iBAAiB;CAO7C;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf"}
package/lib/schema.js CHANGED
@@ -2,7 +2,7 @@ import { AttachmentID, DocumentID, DocumentModelID, decodeID } from '@kubun/id';
2
2
  import { REFERENCE_PREFIX } from '@kubun/protocol';
3
3
  import { pascalCase } from 'change-case';
4
4
  import { GraphQLBoolean, GraphQLEnumType, GraphQLFloat, GraphQLID, GraphQLInputObjectType, GraphQLInt, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLSchema, GraphQLString, isEnumType, isListType, isNonNullType } from 'graphql';
5
- import { connectionArgs, connectionDefinitions, nodeDefinitions } from 'graphql-relay';
5
+ import { connectionArgs, connectionDefinitions, mutationWithClientMutationId, nodeDefinitions } from 'graphql-relay';
6
6
  import { GraphQLDID, GraphQLDuration, GraphQLJSON, GraphQLJSONObject, GraphQLURL } from 'graphql-scalars';
7
7
  import { GraphQLAttachmentID, GraphQLDocID } from './identifiers.js';
8
8
  import { getUniqueDocValue } from './utils.js';
@@ -224,6 +224,7 @@ export class SchemaBuilder {
224
224
  _record;
225
225
  _references = {};
226
226
  _relationsTo = {};
227
+ _subscriptions = {};
227
228
  _types = {
228
229
  OrderByDirection
229
230
  };
@@ -246,9 +247,14 @@ export class SchemaBuilder {
246
247
  // Extract inverse relations
247
248
  for (const [fieldName, meta] of Object.entries(model.fieldsMeta)){
248
249
  if (meta.relationModel != null) {
250
+ const relationRefID = getReferenceID(model.schema.properties[fieldName]?.$ref);
251
+ const isList = this._getReferenceSchema(relationRefID).type === 'array';
249
252
  const relationID = getGlobalID(meta.relationModel, modelID).toString();
250
253
  this._relationsTo[relationID] ??= {};
251
- this._relationsTo[relationID][fieldName] = modelIDstring;
254
+ this._relationsTo[relationID][fieldName] = {
255
+ model: modelIDstring,
256
+ isList
257
+ };
252
258
  }
253
259
  }
254
260
  }
@@ -269,21 +275,6 @@ export class SchemaBuilder {
269
275
  id
270
276
  ];
271
277
  }
272
- getViewer(ctx) {
273
- throw new Error('Must be implemented');
274
- }
275
- async loadDocument(id, ctx) {
276
- throw new Error('Must be implemented');
277
- }
278
- async resolveConnection(model, args, ctx) {
279
- throw new Error('Must be implemented');
280
- }
281
- async resolveList(model, ids, ctx) {
282
- throw new Error('Must be implemented');
283
- }
284
- buildMutations(id, definitions) {
285
- throw new Error('Must be implemented');
286
- }
287
278
  build() {
288
279
  const definitions = this._buildSharedDefinitions();
289
280
  this._definitions = definitions;
@@ -293,25 +284,25 @@ export class SchemaBuilder {
293
284
  };
294
285
  for (const id of Object.keys(this._record)){
295
286
  this._buildDocument(id);
296
- this.buildMutations(id, definitions);
297
287
  const name = this._aliases[id];
288
+ const filterArg = {
289
+ type: this._inputObjects[`${id}-filter`]
290
+ };
298
291
  queryFields[`all${name}`] = {
299
292
  type: this._types[`${id}-connection`],
300
293
  args: {
301
294
  ...connectionArgs,
302
- filter: {
303
- type: this._inputObjects[`${id}-filter`]
304
- },
295
+ filter: filterArg,
305
296
  orderBy: {
306
297
  type: toList(this._inputObjects[`${id}-order`])
307
298
  }
308
299
  },
309
300
  resolve: async (_, args, ctx)=>{
310
- return await this.resolveConnection(id, args, ctx);
301
+ return await ctx.resolveConnection(this.getModelIDs(id), args);
311
302
  }
312
303
  };
313
304
  }
314
- const schemaFields = {
305
+ return new GraphQLSchema({
315
306
  query: new GraphQLObjectType({
316
307
  name: 'Query',
317
308
  fields: queryFields
@@ -319,9 +310,54 @@ export class SchemaBuilder {
319
310
  mutation: new GraphQLObjectType({
320
311
  name: 'Mutation',
321
312
  fields: this._mutations
313
+ }),
314
+ subscription: new GraphQLObjectType({
315
+ name: 'Subscription',
316
+ fields: ()=>{
317
+ const fields = {
318
+ documentChanged: {
319
+ type: new GraphQLNonNull(definitions.documentInterface),
320
+ args: {
321
+ id: {
322
+ type: new GraphQLNonNull(GraphQLID)
323
+ }
324
+ },
325
+ resolve: (doc)=>doc,
326
+ subscribe: (_, args, ctx)=>{
327
+ return ctx.subscribeToDocumentChanged(args.id);
328
+ }
329
+ },
330
+ documentRemoved: {
331
+ type: new GraphQLNonNull(GraphQLID),
332
+ resolve: (id)=>id,
333
+ subscribe: (_src, _args, ctx)=>{
334
+ return ctx.subscribeToDocumentRemoved();
335
+ }
336
+ }
337
+ };
338
+ for (const [id, model] of Object.entries(this._record)){
339
+ const name = this._aliases[id];
340
+ fields[`new${name}Created`] = {
341
+ type: new GraphQLNonNull(this._types[id]),
342
+ resolve: (doc)=>doc,
343
+ subscribe: (_src, _args, ctx)=>{
344
+ return ctx.subscribeToDocumentCreated(this.getModelIDs(id));
345
+ }
346
+ };
347
+ for (const iid of model.interfaces ?? []){
348
+ const interfaceID = getGlobalID(iid, id).toString();
349
+ for (const [fieldName, relationID] of Object.entries(this._relationsTo[interfaceID] ?? {})){
350
+ this._buildRelationSubscriptions(fields, interfaceID, fieldName, relationID);
351
+ }
352
+ }
353
+ for (const [fieldName, relationID] of Object.entries(this._relationsTo[id] ?? {})){
354
+ this._buildRelationSubscriptions(fields, id, fieldName, relationID);
355
+ }
356
+ }
357
+ return fields;
358
+ }
322
359
  })
323
- };
324
- return new GraphQLSchema(schemaFields);
360
+ });
325
361
  }
326
362
  _getDefinitions() {
327
363
  if (this._definitions == null) {
@@ -385,7 +421,7 @@ export class SchemaBuilder {
385
421
  return decoded;
386
422
  }
387
423
  if (decoded instanceof DocumentID) {
388
- return await this.loadDocument(id, ctx);
424
+ return await ctx.loadDocument(id);
389
425
  }
390
426
  throw new Error(`Unsupported node ID: ${id}`);
391
427
  }, (node)=>{
@@ -406,7 +442,7 @@ export class SchemaBuilder {
406
442
  isViewer: {
407
443
  type: new GraphQLNonNull(GraphQLBoolean),
408
444
  description: 'Whether the authenticated request issuer is this account or not',
409
- resolve: (did, _, ctx)=>this.getViewer(ctx) === did
445
+ resolve: (did, _, ctx)=>ctx.getViewer() === did
410
446
  }
411
447
  };
412
448
  for (const [id, model] of Object.entries(this._record)){
@@ -428,10 +464,10 @@ export class SchemaBuilder {
428
464
  }
429
465
  },
430
466
  resolve: async (owner, args, ctx)=>{
431
- return await this.resolveConnection(id, {
467
+ return await ctx.resolveConnection(this.getModelIDs(id), {
432
468
  ...args,
433
469
  owner
434
- }, ctx);
470
+ });
435
471
  }
436
472
  };
437
473
  break;
@@ -449,7 +485,7 @@ export class SchemaBuilder {
449
485
  resolve: async (owner, args, ctx)=>{
450
486
  const unique = getUniqueDocValue(model.uniqueFields, args.with);
451
487
  const docID = await DocumentID.create(id, owner, unique);
452
- return await this.loadDocument(docID.toString(), ctx);
488
+ return await ctx.loadDocument(docID.toString());
453
489
  }
454
490
  };
455
491
  }
@@ -476,40 +512,32 @@ export class SchemaBuilder {
476
512
  }
477
513
  }
478
514
  });
479
- const documentMetadata = new GraphQLObjectType({
480
- name: 'DocumentMetadata',
481
- fields: {
482
- model: {
483
- type: new GraphQLNonNull(GraphQLString),
484
- resolve: (doc)=>doc.model
485
- },
486
- owner: {
487
- type: new GraphQLNonNull(accountObject),
488
- resolve: (doc)=>doc.owner
489
- }
515
+ const documentNodeFields = {
516
+ // Node interface
517
+ id: {
518
+ type: new GraphQLNonNull(GraphQLID)
519
+ },
520
+ // Metadata
521
+ model: {
522
+ type: new GraphQLNonNull(GraphQLString)
523
+ },
524
+ owner: {
525
+ type: new GraphQLNonNull(accountObject)
490
526
  }
491
- });
527
+ };
492
528
  const documentInterface = new GraphQLInterfaceType({
493
529
  name: 'DocumentNode',
494
530
  interfaces: [
495
531
  nodeDefs.nodeInterface
496
532
  ],
497
- fields: {
498
- // Node interface
499
- id: {
500
- type: new GraphQLNonNull(GraphQLID)
501
- },
502
- _doc_metadata: {
503
- type: new GraphQLNonNull(documentMetadata)
504
- }
505
- }
533
+ fields: documentNodeFields
506
534
  });
507
535
  const queryFields = {
508
536
  node: nodeDefs.nodeField,
509
537
  viewer: {
510
538
  type: accountObject,
511
539
  description: 'Account issuing the request, if authenticated',
512
- resolve: (_self, _args, ctx)=>this.getViewer(ctx)
540
+ resolve: (_self, _args, ctx)=>ctx.getViewer()
513
541
  }
514
542
  };
515
543
  return {
@@ -517,7 +545,7 @@ export class SchemaBuilder {
517
545
  accountObject,
518
546
  attachmentObject,
519
547
  documentInterface,
520
- documentMetadata,
548
+ documentNodeFields,
521
549
  queryFields
522
550
  };
523
551
  }
@@ -531,8 +559,9 @@ export class SchemaBuilder {
531
559
  }
532
560
  const definitions = this._getDefinitions();
533
561
  this._aliases[id] ??= pascalCase(model.name);
562
+ const name = this._aliases[id];
534
563
  const config = {
535
- name: this._aliases[id],
564
+ name,
536
565
  interfaces: ()=>{
537
566
  return [
538
567
  definitions.documentInterface,
@@ -541,22 +570,194 @@ export class SchemaBuilder {
541
570
  return this._types[getGlobalID(interfaceID, id).toString()];
542
571
  }));
543
572
  },
544
- fields: ()=>this._buildObjectFields(id, model.schema, model),
545
- isTypeOf: (doc)=>DocumentID.fromString(doc.id).model.toString() === id
573
+ fields: ()=>this._buildDocumentFields(id, model, name)
546
574
  };
547
575
  const isInterface = model.behavior === 'interface';
548
- const nodeType = isInterface ? new GraphQLInterfaceType(config) : new GraphQLObjectType(config);
576
+ const nodeType = isInterface ? new GraphQLInterfaceType({
577
+ ...config,
578
+ resolveType: (doc)=>this._aliases[doc.model]
579
+ }) : new GraphQLObjectType(config);
549
580
  const { connectionType, edgeType } = connectionDefinitions({
550
581
  nodeType
551
582
  });
552
583
  this._types[id] = nodeType;
553
584
  this._types[`${id}-connection`] = connectionType;
554
585
  this._types[`${id}-edge`] = edgeType;
586
+ this._buildDocumentDataObject(id, model, name);
555
587
  this._buildDocumentInput(id, model);
556
- this._buildObjectFilterInput(id, model.schema, model.name, true);
557
- this._buildObjectOrderByInput(id, model.schema, model.name, true);
588
+ this._buildObjectFilterInput(id, model.schema, name, true);
589
+ this._buildObjectOrderByInput(id, model.schema, name, true);
590
+ // TODO: move to dedicated method
591
+ if (!isInterface) {
592
+ if (model.behavior === 'default') {
593
+ this._mutations[`create${name}`] = mutationWithClientMutationId({
594
+ name: `Create${name}`,
595
+ inputFields: ()=>({
596
+ data: {
597
+ type: new GraphQLNonNull(this._inputObjects[id])
598
+ }
599
+ }),
600
+ outputFields: ()=>({
601
+ ...definitions.queryFields,
602
+ document: {
603
+ type: this._types[id]
604
+ }
605
+ }),
606
+ mutateAndGetPayload: async (input, ctx, info)=>{
607
+ const document = await ctx.executeCreateMutation(id, input.data, info);
608
+ return {
609
+ document
610
+ };
611
+ }
612
+ });
613
+ } else if (model.behavior === 'unique') {
614
+ this._mutations[`set${name}`] = mutationWithClientMutationId({
615
+ name: `Set${name}`,
616
+ inputFields: ()=>({
617
+ data: {
618
+ type: new GraphQLNonNull(this._inputObjects[id])
619
+ }
620
+ }),
621
+ outputFields: ()=>({
622
+ ...definitions.queryFields,
623
+ document: {
624
+ type: this._types[id]
625
+ }
626
+ }),
627
+ mutateAndGetPayload: async (input, ctx, info)=>{
628
+ const unique = getUniqueDocValue(model.uniqueFields, input.data);
629
+ const document = await ctx.executeSetMutation(id, unique, input.data, info);
630
+ return {
631
+ document
632
+ };
633
+ }
634
+ });
635
+ }
636
+ this._mutations[`update${name}`] = mutationWithClientMutationId({
637
+ name: `Update${name}`,
638
+ inputFields: ()=>({
639
+ id: {
640
+ type: new GraphQLNonNull(GraphQLID)
641
+ },
642
+ patch: {
643
+ type: new GraphQLNonNull(toList(PatchOperation))
644
+ },
645
+ from: {
646
+ type: this._inputObjects[`${id}-update`]
647
+ }
648
+ }),
649
+ outputFields: ()=>({
650
+ ...definitions.queryFields,
651
+ document: {
652
+ type: this._types[id]
653
+ }
654
+ }),
655
+ mutateAndGetPayload: async (input, ctx, info)=>{
656
+ const document = await ctx.executeUpdateMutation(input, info);
657
+ return {
658
+ document
659
+ };
660
+ }
661
+ });
662
+ this._mutations[`remove${name}`] = mutationWithClientMutationId({
663
+ name: `Remove${name}`,
664
+ inputFields: ()=>({
665
+ id: {
666
+ type: new GraphQLNonNull(GraphQLID)
667
+ }
668
+ }),
669
+ outputFields: ()=>definitions.queryFields,
670
+ mutateAndGetPayload: async (input, ctx, info)=>{
671
+ await ctx.executeRemoveMutation(input.id, info);
672
+ return {};
673
+ }
674
+ });
675
+ }
558
676
  return nodeType;
559
677
  }
678
+ _buildDocumentFields(id, model, name) {
679
+ const dataObject = this._buildDocumentDataObject(id, model, name);
680
+ const definitions = this._getDefinitions();
681
+ const fields = {
682
+ ...definitions.documentNodeFields,
683
+ data: {
684
+ type: new GraphQLNonNull(dataObject)
685
+ }
686
+ };
687
+ for (const [key, field] of Object.entries(dataObject.getFields())){
688
+ const relationModel = model.fieldsMeta[key]?.relationModel;
689
+ if (typeof relationModel !== 'undefined') {
690
+ let relationModelID;
691
+ let relationType;
692
+ if (relationModel === null) {
693
+ relationModelID = null;
694
+ relationType = definitions.documentInterface;
695
+ } else {
696
+ relationModelID = getGlobalID(relationModel, id).toString();
697
+ relationType = this._buildDocument(relationModelID);
698
+ }
699
+ if (isList(field.type)) {
700
+ // TODO: add suport for filters?
701
+ fields[`${key}Documents`] = {
702
+ type: new GraphQLNonNull(toOuputList(relationType)),
703
+ resolve: async (doc, _args, ctx)=>{
704
+ const relationIDs = doc.data?.[key] ?? [];
705
+ return relationIDs.length ? await ctx.resolveList(this.getModelIDs(relationModelID), relationIDs) : [];
706
+ }
707
+ };
708
+ } else {
709
+ fields[`${key}Document`] = {
710
+ type: relationType,
711
+ resolve: async (doc, _args, ctx)=>{
712
+ const relationID = doc.data?.[key];
713
+ return relationID ? await ctx.loadDocument(relationID) : null;
714
+ }
715
+ };
716
+ }
717
+ }
718
+ for (const iid of model.interfaces ?? []){
719
+ const interfaceID = getGlobalID(iid, id).toString();
720
+ for (const [fieldName, relation] of Object.entries(this._relationsTo[interfaceID] ?? {})){
721
+ this._buildRelationFields(fields, fieldName, relation);
722
+ }
723
+ }
724
+ for (const [fieldName, relation] of Object.entries(this._relationsTo[id] ?? {})){
725
+ this._buildRelationFields(fields, fieldName, relation);
726
+ }
727
+ }
728
+ return fields;
729
+ }
730
+ _buildDocumentDataObject(id, model, name) {
731
+ const typeID = `${id}-data`;
732
+ if (this._types[typeID] != null) {
733
+ return this._types[typeID];
734
+ }
735
+ const required = model.schema.required ?? [];
736
+ const fields = {};
737
+ for (const [key, value] of Object.entries(model.schema.properties ?? {})){
738
+ const fieldRef = value.$ref;
739
+ if (fieldRef == null) {
740
+ throw new Error(`Missing ref for field ${key} of object ${id}`);
741
+ }
742
+ const type = this._getReference(fieldRef);
743
+ fields[key] = {
744
+ type: required.includes(key) ? new GraphQLNonNull(type) : type
745
+ };
746
+ }
747
+ const config = {
748
+ name: `${name}Data`,
749
+ interfaces: ()=>{
750
+ return model.interfaces.map((interfaceID)=>{
751
+ const typeID = `${getGlobalID(interfaceID, id).toString()}-data`;
752
+ return this._types[typeID];
753
+ });
754
+ },
755
+ fields
756
+ };
757
+ const object = model.behavior === 'interface' ? new GraphQLInterfaceType(config) : new GraphQLObjectType(config);
758
+ this._types[typeID] = object;
759
+ return object;
760
+ }
560
761
  _buildDocumentInput(id, model) {
561
762
  if (model.behavior === 'interface') {
562
763
  // No mutations for interfaces
@@ -580,11 +781,11 @@ export class SchemaBuilder {
580
781
  }
581
782
  const name = this._aliases[id];
582
783
  this._inputObjects[id] = new GraphQLInputObjectType({
583
- name: model.behavior === 'default' ? `Create${name}` : `Set${name}`,
784
+ name: `${name}Input`,
584
785
  fields: setFields
585
786
  });
586
787
  this._inputObjects[`${id}-update`] = new GraphQLInputObjectType({
587
- name: `Update${name}`,
788
+ name: `Partial${name}Input`,
588
789
  fields: updateFields
589
790
  });
590
791
  }
@@ -596,17 +797,14 @@ export class SchemaBuilder {
596
797
  }
597
798
  if (schema.type === 'array') {
598
799
  const name = this._aliases[id] ?? pascalCase(parentName + schema.title);
599
- const itemType = this._buildReferenceFilterInput(schema.items.$ref, schema.title);
800
+ // const itemType = this._buildReferenceFilterInput(schema.items.$ref, schema.title)
600
801
  return new GraphQLInputObjectType({
601
802
  name: `${name}Filter`,
602
803
  isOneOf: true,
603
804
  fields: {
604
- contains: {
605
- type: toList(itemType)
606
- },
607
- isEmpty: {
608
- type: GraphQLBoolean
609
- },
805
+ // DB does not support filtering on array values
806
+ // contains: { type: toList(itemType) },
807
+ // isEmpty: { type: GraphQLBoolean },
610
808
  isNull: {
611
809
  type: GraphQLBoolean
612
810
  }
@@ -644,7 +842,7 @@ export class SchemaBuilder {
644
842
  }
645
843
  const name = this._aliases[id] ?? pascalCase(parentName + (schema.title ?? ''));
646
844
  const fields = isDocument ? {
647
- _doc_owner: {
845
+ _owner: {
648
846
  type: this._inputObjects.AccountValueFilter
649
847
  }
650
848
  } : {};
@@ -687,10 +885,10 @@ export class SchemaBuilder {
687
885
  }
688
886
  const name = this._aliases[id] ?? pascalCase(parentName + (schema.title ?? ''));
689
887
  const fields = isDocument ? {
690
- _doc_owner: {
888
+ _docOwner: {
691
889
  type: OrderByDirection
692
890
  },
693
- _doc_created_at: {
891
+ _createdAt: {
694
892
  type: OrderByDirection
695
893
  }
696
894
  } : {};
@@ -781,19 +979,9 @@ export class SchemaBuilder {
781
979
  fields
782
980
  });
783
981
  }
784
- _buildObjectFields(id, schema, model) {
785
- const definitions = this._getDefinitions();
982
+ _buildObjectFields(id, schema) {
786
983
  const required = schema.required ?? [];
787
- const fields = model ? {
788
- id: {
789
- type: new GraphQLNonNull(GraphQLID),
790
- resolve: (doc)=>doc.id
791
- },
792
- _doc_metadata: {
793
- type: new GraphQLNonNull(definitions.documentMetadata),
794
- resolve: (doc)=>doc
795
- }
796
- } : {};
984
+ const fields = {};
797
985
  for (const [key, value] of Object.entries(schema.properties ?? {})){
798
986
  const fieldRef = value.$ref;
799
987
  if (fieldRef == null) {
@@ -803,63 +991,82 @@ export class SchemaBuilder {
803
991
  fields[key] = {
804
992
  type: required.includes(key) ? new GraphQLNonNull(type) : type
805
993
  };
806
- if (model == null) {
807
- continue;
808
- }
809
- fields[key].resolve = (doc)=>doc.data?.[key];
810
- const relationModel = model.fieldsMeta[key]?.relationModel;
811
- if (typeof relationModel !== 'undefined') {
812
- let relationModelID;
813
- let relationType;
814
- if (relationModel === null) {
815
- relationModelID = null;
816
- relationType = definitions.documentInterface;
817
- } else {
818
- relationModelID = getGlobalID(relationModel, id).toString();
819
- relationType = this._buildDocument(relationModelID);
994
+ }
995
+ return fields;
996
+ }
997
+ _buildRelationFields(fields, fieldName, relation) {
998
+ if (relation.isList) {
999
+ // DB does not support matches for array containing values
1000
+ return;
1001
+ }
1002
+ const relationID = relation.model;
1003
+ const relationName = `${pascalCase(fieldName)}Of${this._aliases[relationID]}`;
1004
+ fields[`in${relationName}`] = {
1005
+ type: new GraphQLNonNull(this._types[`${relationID}-connection`]),
1006
+ args: {
1007
+ ...connectionArgs,
1008
+ filter: {
1009
+ type: this._inputObjects[`${relationID}-filter`]
1010
+ },
1011
+ orderBy: {
1012
+ type: toList(this._inputObjects[`${relationID}-order`])
820
1013
  }
821
- if (isList(type)) {
822
- // TODO: add suport for filters?
823
- fields[`_${key}_documents`] = {
824
- type: new GraphQLNonNull(toOuputList(relationType)),
825
- resolve: async (doc, _args, ctx)=>{
826
- const relationIDs = doc.data?.[key] ?? [];
827
- return relationIDs.length ? await this.resolveList(relationModelID, relationIDs, ctx) : [];
828
- }
829
- };
830
- } else {
831
- fields[`_${key}_document`] = {
832
- type: relationType,
833
- resolve: async (doc, _args, ctx)=>{
834
- const relationID = doc.data?.[key];
835
- return relationID ? await this.loadDocument(relationID, ctx) : null;
1014
+ },
1015
+ resolve: (doc, args, ctx)=>{
1016
+ const docFilter = {
1017
+ where: {
1018
+ [fieldName]: {
1019
+ equalTo: doc.id
836
1020
  }
837
- };
838
- }
1021
+ }
1022
+ };
1023
+ const filter = args.filter ? {
1024
+ and: [
1025
+ args.filter,
1026
+ docFilter
1027
+ ]
1028
+ } : docFilter;
1029
+ return ctx.resolveConnection(this.getModelIDs(relationID), {
1030
+ ...args,
1031
+ filter
1032
+ });
839
1033
  }
840
- for (const iid of model.interfaces ?? []){
841
- const interfaceID = getGlobalID(iid, id).toString();
842
- for (const [fieldName, relationID] of Object.entries(this._relationsTo[interfaceID] ?? {})){
843
- const relationName = this._aliases[relationID];
844
- fields[`_${fieldName}_of_${relationName}_list`] = {
845
- type: new GraphQLNonNull(this._types[`${relationID}-connection`])
846
- };
847
- fields[`_${fieldName}_of_${relationName}_count`] = {
848
- type: new GraphQLNonNull(GraphQLInt)
849
- };
1034
+ };
1035
+ // TODO: add support for count relation
1036
+ // fields[`_${fieldName}_of_${relationName}_count`] = {
1037
+ // type: new GraphQLNonNull(GraphQLInt),
1038
+ // }
1039
+ }
1040
+ _buildRelationSubscriptions(fields, modelID, fieldName, relation) {
1041
+ if (relation.isList) {
1042
+ // Inverse relations to list fields are not supported in connections so we skip them for subscriptions as well
1043
+ return;
1044
+ }
1045
+ const relationName = `${pascalCase(fieldName)}Of${this._aliases[relation.model]}`;
1046
+ fields[`edgeAddedTo${relationName}`] = {
1047
+ type: new GraphQLNonNull(this._types[`${modelID}-edge`]),
1048
+ args: {
1049
+ id: {
1050
+ type: new GraphQLNonNull(GraphQLID)
850
1051
  }
1052
+ },
1053
+ resolve: (edge)=>edge,
1054
+ subscribe: (_src, args, ctx)=>{
1055
+ return ctx.subscribeToDocumentEdgeAdded(this.getModelIDs(modelID), (data)=>data[fieldName] === args.id);
851
1056
  }
852
- for (const [fieldName, relationID] of Object.entries(this._relationsTo[id] ?? {})){
853
- const relationName = this._aliases[relationID];
854
- fields[`_${fieldName}_of_${relationName}_list`] = {
855
- type: new GraphQLNonNull(this._types[`${relationID}-connection`])
856
- };
857
- fields[`_${fieldName}_of_${relationName}_count`] = {
858
- type: new GraphQLNonNull(GraphQLInt)
859
- };
1057
+ };
1058
+ fields[`edgeRemovedFrom${relationName}`] = {
1059
+ type: new GraphQLNonNull(GraphQLID),
1060
+ args: {
1061
+ id: {
1062
+ type: new GraphQLNonNull(GraphQLID)
1063
+ }
1064
+ },
1065
+ resolve: (id)=>id,
1066
+ subscribe: (_src, args, ctx)=>{
1067
+ return ctx.subscribeToDocumentEdgeRemoved(this.getModelIDs(modelID), (data)=>data[fieldName] === args.id);
860
1068
  }
861
- }
862
- return fields;
1069
+ };
863
1070
  }
864
1071
  _buildString(schema, asInput) {
865
1072
  if (schema.const != null) {
@@ -912,3 +1119,9 @@ export class SchemaBuilder {
912
1119
  return scalar;
913
1120
  }
914
1121
  }
1122
+ export function createSchema(record, aliases) {
1123
+ return new SchemaBuilder({
1124
+ record,
1125
+ aliases
1126
+ }).build();
1127
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ export type PatchAddOperation = {
2
+ op: 'add';
3
+ path: string;
4
+ value: unknown;
5
+ };
6
+ export type PatchRemoveOperation = {
7
+ op: 'remove';
8
+ path: string;
9
+ };
10
+ export type PatchReplaceOperation = {
11
+ op: 'replace';
12
+ path: string;
13
+ value: unknown;
14
+ };
15
+ export type PatchMoveOperation = {
16
+ op: 'move';
17
+ from: string;
18
+ path: string;
19
+ };
20
+ export type PatchCopyOperation = {
21
+ op: 'copy';
22
+ from: string;
23
+ path: string;
24
+ };
25
+ export type PatchOperation = PatchAddOperation | PatchCopyOperation | PatchMoveOperation | PatchRemoveOperation | PatchReplaceOperation;
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AACjE,MAAM,MAAM,qBAAqB,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AACnF,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,cAAc,GACtB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,oBAAoB,GACpB,qBAAqB,CAAA"}
package/lib/types.js ADDED
@@ -0,0 +1 @@
1
+ export { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/graphql",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "license": "see LICENSE.md",
5
5
  "keywords": [],
6
6
  "type": "module",
@@ -15,14 +15,14 @@
15
15
  ],
16
16
  "sideEffects": false,
17
17
  "dependencies": {
18
- "@enkaku/codec": "^0.11.0",
18
+ "@enkaku/codec": "^0.12.0",
19
19
  "change-case": "^5.4.4",
20
20
  "graphql": "^16.9.0",
21
21
  "graphql-relay": "^0.10.2",
22
22
  "graphql-scalars": "^1.24.2",
23
23
  "multiformats": "^13.3.2",
24
- "@kubun/id": "^0.2.0",
25
- "@kubun/protocol": "^0.2.5"
24
+ "@kubun/protocol": "^0.3.0",
25
+ "@kubun/id": "^0.3.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "json-schema-typed": "^8.0.1"