Skip to content

Commit b094aa5

Browse files
wip
1 parent 13c5b8f commit b094aa5

File tree

7 files changed

+270
-36
lines changed

7 files changed

+270
-36
lines changed

packages/graphql/src/classes/Node.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ class Node extends GraphElement {
190190
...this.temporalFields,
191191
...this.enumFields,
192192
...this.objectFields,
193-
...this.scalarFields,
194-
...this.primitiveFields,
193+
...this.scalarFields, // this are just custom scalars
194+
...this.primitiveFields, // this are instead built-in scalars, confirmed By Alexandra
195195
...this.interfaceFields,
196196
...this.objectFields,
197197
...this.unionFields,
@@ -200,6 +200,7 @@ class Node extends GraphElement {
200200
}
201201

202202
/** Fields you can apply auth allow and bind to */
203+
// Maybe we can remove this as they may not be used anymore in the new auth system
203204
public get authableFields(): AuthableField[] {
204205
return [
205206
...this.primitiveFields,
@@ -254,6 +255,7 @@ class Node extends GraphElement {
254255
};
255256
}
256257

258+
257259
public get fulltextTypeNames(): FulltextTypeNames {
258260
return {
259261
result: `${this.pascalCaseSingular}FulltextResult`,

packages/graphql/src/schema-model/attribute/Attribute.ts

Lines changed: 251 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,29 @@
1818
*/
1919

2020
import { Neo4jGraphQLSchemaValidationError } from "../../classes/Error";
21+
import { AGGREGATION_COMPARISON_OPERATORS } from "../../constants";
22+
import type {
23+
PrimitiveField,
24+
CustomScalarField,
25+
CustomEnumField,
26+
UnionField,
27+
ObjectField,
28+
TemporalField,
29+
PointField,
30+
CypherField,
31+
} from "../../types";
2132
import type { Annotation, Annotations } from "../annotation/Annotation";
2233
import { AnnotationsKey, annotationToKey } from "../annotation/Annotation";
2334

24-
export enum StandardGraphQLScalarType {
35+
export enum GraphQLBuiltInScalarType {
2536
Int = "Int",
2637
Float = "Float",
2738
String = "String",
2839
Boolean = "Boolean",
2940
ID = "ID",
30-
}
41+
}
3142

32-
export enum Neo4jGraphQLPointType {
43+
export enum Neo4jGraphQLSpatialType {
3344
CartesianPoint = "CartesianPoint",
3445
Point = "Point",
3546
}
@@ -47,24 +58,27 @@ export enum Neo4jGraphQLTemporalType {
4758
Duration = "Duration",
4859
}
4960

50-
type Neo4jGraphQLScalarType = Neo4jGraphQLTemporalType | Neo4jGraphQLNumberType | Neo4jGraphQLPointType;
61+
type Neo4jGraphQLScalarType = Neo4jGraphQLTemporalType | Neo4jGraphQLNumberType | Neo4jGraphQLSpatialType;
5162

5263
export type AttributeType = ScalarType | UserScalarType | ObjectType | ListType | EnumType;
5364

65+
export type ScalarTypeType =
66+
| "Neo4jGraphQLTemporalType"
67+
| "Neo4jGraphQLNumberType"
68+
| "Neo4jGraphQLPointType"
69+
| "GraphQLBuiltInScalarType";
5470

55-
export type ScalarTypeType = "Neo4jGraphQLTemporalType" | "Neo4jGraphQLNumberType" | "Neo4jGraphQLPointType" | "StandardGraphQLScalarType";
56-
export class ScalarType {
57-
name: StandardGraphQLScalarType | Neo4jGraphQLScalarType;
71+
export class ScalarType {
72+
name: GraphQLBuiltInScalarType | Neo4jGraphQLScalarType;
5873
isRequired: boolean;
5974
ofType: ScalarTypeType;
60-
constructor (name: StandardGraphQLScalarType | Neo4jGraphQLScalarType, isRequired: boolean, ofType: ScalarTypeType) {
75+
constructor(name: GraphQLBuiltInScalarType | Neo4jGraphQLScalarType, isRequired: boolean, ofType: ScalarTypeType) {
6176
this.name = name;
6277
this.isRequired = isRequired;
6378
this.ofType = ofType;
6479
}
6580
}
6681

67-
6882
export class UserScalarType {
6983
name: string;
7084
isRequired: boolean;
@@ -74,7 +88,7 @@ export class UserScalarType {
7488
}
7589
}
7690

77-
export class ObjectType {
91+
export class ObjectType {
7892
name: string;
7993
isRequired: boolean;
8094
constructor(name: string, isRequired: boolean) {
@@ -104,16 +118,9 @@ export class Attribute {
104118
public readonly annotations: Partial<Annotations> = {};
105119
public readonly type: AttributeType;
106120
public isCypherField = false;
121+
private _attributeModel: AttributeModel | undefined;
107122

108-
constructor({
109-
name,
110-
annotations,
111-
type,
112-
}: {
113-
name: string;
114-
annotations: Annotation[];
115-
type: AttributeType;
116-
}) {
123+
constructor({ name, annotations, type }: { name: string; annotations: Annotation[]; type: AttributeType }) {
117124
this.name = name;
118125
this.type = type;
119126

@@ -130,7 +137,6 @@ export class Attribute {
130137
});
131138
}
132139

133-
134140
private addAnnotation(annotation: Annotation): void {
135141
const annotationKey = annotationToKey(annotation);
136142
if (this.annotations[annotationKey]) {
@@ -144,4 +150,229 @@ export class Attribute {
144150
// There's no reason to narrow either, since we care more about performance.
145151
this.annotations[annotationKey] = annotation as any;
146152
}
153+
154+
get attributeModel(): AttributeModel {
155+
if (!this._attributeModel) {
156+
this._attributeModel = new AttributeModel(this);
157+
}
158+
return this._attributeModel;
159+
}
160+
161+
isInt(): boolean {
162+
return false;
163+
}
164+
165+
isBigInt(): boolean {
166+
return false;
167+
}
168+
169+
isFloat(): boolean {
170+
return false;
171+
}
172+
173+
isList(): boolean {
174+
return false;
175+
}
176+
177+
isRequired(): boolean {
178+
return true;
179+
}
180+
181+
isScalar(): boolean {
182+
return this.type instanceof ScalarType;
183+
}
184+
185+
isCustomScalar(): boolean {
186+
return false;
187+
}
188+
189+
isSpatial(): boolean {
190+
return false;
191+
}
192+
193+
isTemporal(): boolean {
194+
return false;
195+
}
196+
197+
isObject(): boolean {
198+
return false;
199+
}
200+
201+
isEnum(): boolean {
202+
return false;
203+
}
204+
// isGraphQLBuiltInScalarType is the same as isPrimitive
205+
isGraphQLBuiltInScalar(): boolean {
206+
return this.isScalar() && (this.type as ScalarType).ofType === "GraphQLBuiltInScalarType";
207+
}
208+
}
209+
210+
type MutableField =
211+
| PrimitiveField
212+
| CustomScalarField
213+
| CustomEnumField
214+
| UnionField
215+
| ObjectField
216+
| TemporalField
217+
| PointField
218+
| CypherField;
219+
220+
class AttributeModel {
221+
readonly attribute: Attribute;
222+
constructor(attribute: Attribute) {
223+
this.attribute = attribute;
224+
}
225+
226+
isMutable(): boolean {
227+
// this is based on the assumption that interface fields and union fields are object fields
228+
return (
229+
this.isSpatial() || this.isTemporal() || this.isEnum() || this.isObject() || this.isGraphQLBuiltInScalar()
230+
);
231+
}
232+
233+
isUnique(): boolean {
234+
//return this.attribute.annotations.unique ? true : false;
235+
return false;
236+
}
237+
// TODO: remember to figure out constrainableFields
238+
239+
/**
240+
* @throws {Error} if the attribute is not a list
241+
*/
242+
getListModel(): ListModel {
243+
return new ListModel(this);
244+
}
245+
246+
/**
247+
* @throws {Error} if the attribute is not a scalar
248+
*/
249+
getMathModel(): MathModel {
250+
return new MathModel(this);
251+
}
252+
253+
/**
254+
* The following are just proxy methods to the attribute methods for convenience.
255+
* the idea is to improve the ergonomic for the client for case when they want to access information about the Attribute model,
256+
* and they are forced to switch between the attribute and the attribute model.
257+
*
258+
**/
259+
/**
260+
* START OF PROXY METHODS
261+
**/
262+
isCustomScalar(): boolean {
263+
return this.attribute.isCustomScalar();
264+
}
265+
266+
isInt(): boolean {
267+
return this.attribute.isInt();
268+
}
269+
270+
isBigInt(): boolean {
271+
return this.attribute.isBigInt();
272+
}
273+
274+
isFloat(): boolean {
275+
return this.attribute.isFloat();
276+
}
277+
278+
isList(): boolean {
279+
return this.attribute.isList();
280+
}
281+
282+
isRequired(): boolean {
283+
return this.attribute.isRequired();
284+
}
285+
286+
isScalar(): boolean {
287+
return this.attribute.isScalar();
288+
}
289+
290+
isGraphQLBuiltInScalar(): boolean {
291+
return this.attribute.isGraphQLBuiltInScalar();
292+
}
293+
294+
isSpatial(): boolean {
295+
return this.attribute.isSpatial();
296+
}
297+
298+
isTemporal(): boolean {
299+
return this.attribute.isSpatial();
300+
}
301+
302+
isObject(): boolean {
303+
return this.attribute.isObject();
304+
}
305+
306+
isEnum(): boolean {
307+
return this.attribute.isEnum();
308+
}
309+
/**
310+
* END OF PROXY METHODS
311+
**/
312+
}
313+
314+
class MathModel {
315+
readonly attributeModel: AttributeModel;
316+
constructor(attributeModel: AttributeModel) {
317+
if (!attributeModel.isScalar()) {
318+
throw new Error("Attribute is not a scalar");
319+
}
320+
this.attributeModel = attributeModel;
321+
}
322+
323+
getMathMethods(): string[] {
324+
return [this.getAdd()];
325+
}
326+
327+
getAdd(): string {
328+
return this.attributeModel.attribute.isInt() || this.attributeModel.attribute.isBigInt()
329+
? `${this.attributeModel.attribute.name}_ADD`
330+
: `${this.attributeModel.attribute.name}_INCREMENT`;
331+
}
332+
}
333+
334+
class AggregationModel {
335+
readonly attributeModel: AttributeModel;
336+
constructor(attributeModel: AttributeModel) {
337+
if (!attributeModel.isScalar()) {
338+
throw new Error("Attribute is not a scalar");
339+
}
340+
this.attributeModel = attributeModel;
341+
}
342+
343+
getAggregationMethods(): string[] {
344+
return [...this.getAverageMethods()];
345+
}
346+
347+
getAverageMethods(): string[] {
348+
return AGGREGATION_COMPARISON_OPERATORS.map(
349+
(operator) => `${this.attributeModel.attribute.name}_AVERAGE_${operator}`
350+
);
351+
}
352+
isAggregate(string): boolean {
353+
354+
}
355+
}
356+
357+
class ListModel {
358+
readonly attributeModel: AttributeModel;
359+
360+
constructor(attributeModel: AttributeModel) {
361+
if (!attributeModel.attribute.isList()) {
362+
throw new Error("Attribute is not a list");
363+
}
364+
this.attributeModel = attributeModel;
365+
}
366+
367+
getArrayMethods(): string[] {
368+
return [this.getPush(), this.getPop()];
369+
}
370+
371+
getPush(): string {
372+
return `${this.attributeModel.attribute.name}_PUSH`;
373+
}
374+
375+
getPop(): string {
376+
return `${this.attributeModel.attribute.name}_POP`;
377+
}
147378
}

packages/graphql/src/schema-model/entity/ConcreteEntity.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export class ConcreteEntity implements Entity {
3131
public readonly attributes: Map<string, Attribute> = new Map();
3232
public readonly relationships: Map<string, Relationship> = new Map();
3333
public readonly annotations: Partial<Annotations> = {};
34-
// TODO:
3534

3635
constructor({
3736
name,

0 commit comments

Comments
 (0)