Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues related to creating custom adapters in other projects, #88 #89 #91

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
292 changes: 142 additions & 150 deletions src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,183 +3,175 @@ import IQueryBuilderOptions from "./IQueryBuilderOptions";
import NestedField, { isNestedField } from "./NestedField";
import VariableOptions from "./VariableOptions";

export default class Utils {
public static resolveVariables(operations: IQueryBuilderOptions[]): any {
let ret: any = {};

for (const { variables, fields } of operations) {
ret = {
...ret,
...variables,
...((fields && Utils.getNestedVariables(fields)) || {}),
};
}
return ret;
export function resolveVariables(operations: IQueryBuilderOptions[]): any {
let ret: any = {};

for (const { variables, fields } of operations) {
ret = {
...ret,
...variables,
...((fields && getNestedVariables(fields)) || {}),
};
}
return ret;
}

// Convert object to name and argument map. eg: (id: $id)
public static queryDataNameAndArgumentMap(variables: VariableOptions) {
return variables && Object.keys(variables).length
? `(${Object.entries(variables).reduce((dataString, [key, value], i) => {
return `${dataString}${i !== 0 ? ", " : ""}${
value && value.name ? value.name : key
}: $${key}`;
}, "")})`
: "";
}
// Convert object to name and argument map. eg: (id: $id)
export function queryDataNameAndArgumentMap(variables: VariableOptions) {
return variables && Object.keys(variables).length
? `(${Object.entries(variables).reduce((dataString, [key, value], i) => {
return `${dataString}${i !== 0 ? ", " : ""}${
value && value.name ? value.name : key
}: $${key}`;
}, "")})`
: "";
}

public static queryFieldsMap(fields?: Fields): string {
return fields
? fields
.map((field) => {
if (isNestedField(field)) {
return Utils.queryNestedFieldMap(field);
} else if (typeof field === "object") {
let result = "";

Object.entries<Fields>(field as Record<string, Fields>).forEach(
([key, values], index, array) => {
result += `${key} ${
values.length > 0
? "{ " + this.queryFieldsMap(values) + " }"
: ""
}`;

// If it's not the last item in array, join with comma
if (index < array.length - 1) {
result += ", ";
}
export function queryFieldsMap(fields?: Fields): string {
return fields
? fields
.map((field) => {
if (isNestedField(field)) {
return queryNestedFieldMap(field);
} else if (typeof field === "object") {
let result = "";

Object.entries<Fields>(field as Record<string, Fields>).forEach(
([key, values], index, array) => {
result += `${key} ${
values.length > 0 ? "{ " + queryFieldsMap(values) + " }" : ""
}`;

// If it's not the last item in array, join with comma
if (index < array.length - 1) {
result += ", ";
}
);

return result;
} else {
return `${field}`;
}
})
.join(", ")
: "";
}
}
);

public static operationOrAlias(
operation: IQueryBuilderOptions["operation"]
): string {
return typeof operation === "string"
? operation
: `${operation.alias}: ${operation.name}`;
}
return result;
} else {
return `${field}`;
}
})
.join(", ")
: "";
}

public static isFragment(field: NestedField): boolean {
return field?.fragment === true ?? false;
}
function operationOrAlias(
operation: IQueryBuilderOptions["operation"]
): string {
return typeof operation === "string"
? operation
: `${operation.alias}: ${operation.name}`;
}

public static operationOrFragment(field: NestedField): string {
return Utils.isFragment(field)
? field.operation
: Utils.operationOrAlias(field.operation);
}
function isFragment(field: NestedField): boolean {
return field?.fragment === true ?? false;
}

public static getFragment(field: NestedField): string {
return Utils.isFragment(field) ? "... on " : "";
}
function operationOrFragment(field: NestedField): string {
return isFragment(field)
? field.operation
: operationOrAlias(field.operation);
}

public static queryNestedFieldMap(field: NestedField) {
return `${Utils.getFragment(field)}${Utils.operationOrFragment(field)} ${
this.isFragment(field)
? ""
: this.queryDataNameAndArgumentMap(field.variables)
} ${
field.fields.length > 0
? "{ " + this.queryFieldsMap(field.fields) + " }"
: ""
}`;
}
function getFragment(field: NestedField): string {
return isFragment(field) ? "... on " : "";
}

// Variables map. eg: { "id": 1, "name": "Jon Doe" }
public static queryVariablesMap(variables: any, fields?: Fields) {
const variablesMapped: { [key: string]: unknown } = {};
const update = (vars: any) => {
if (vars) {
Object.keys(vars).map((key) => {
variablesMapped[key] =
typeof vars[key] === "object" ? vars[key].value : vars[key];
});
}
};
export function queryNestedFieldMap(field: NestedField) {
return `${getFragment(field)}${operationOrFragment(field)} ${
isFragment(field) ? "" : queryDataNameAndArgumentMap(field.variables)
} ${
field.fields.length > 0 ? "{ " + queryFieldsMap(field.fields) + " }" : ""
}`;
}

update(variables);
if (fields && typeof fields === "object") {
update(Utils.getNestedVariables(fields));
// Variables map. eg: { "id": 1, "name": "Jon Doe" }
export function queryVariablesMap(variables: any, fields?: Fields) {
const variablesMapped: { [key: string]: unknown } = {};
const update = (vars: any) => {
if (vars) {
Object.keys(vars).map((key) => {
variablesMapped[key] =
typeof vars[key] === "object" ? vars[key].value : vars[key];
});
}
return variablesMapped;
};

update(variables);
if (fields && typeof fields === "object") {
update(getNestedVariables(fields));
}
return variablesMapped;
}

public static getNestedVariables(fields: Fields) {
let variables = {};

function getDeepestVariables(innerFields: Fields) {
innerFields?.forEach((field: string | object | NestedField) => {
if (isNestedField(field)) {
variables = {
...field.variables,
...variables,
...(field.fields && getDeepestVariables(field.fields)),
};
} else {
if (typeof field === "object") {
for (const [, value] of Object.entries(field)) {
getDeepestVariables(value);
}
export function getNestedVariables(fields: Fields) {
let variables = {};

function getDeepestVariables(innerFields: Fields) {
innerFields?.forEach((field: string | object | NestedField) => {
if (isNestedField(field)) {
variables = {
...field.variables,
...variables,
...(field.fields && getDeepestVariables(field.fields)),
};
} else {
if (typeof field === "object") {
for (const [, value] of Object.entries(field)) {
getDeepestVariables(value);
}
}
});

return variables;
}

getDeepestVariables(fields);
}
});

return variables;
}

public static queryDataType(variable: any) {
let type = "String";
getDeepestVariables(fields);

const value = typeof variable === "object" ? variable.value : variable;
return variables;
}

if (variable?.type != null) {
type = variable.type;
} else {
// TODO: Should handle the undefined value (either in array value or single value)
const candidateValue = Array.isArray(value) ? value[0] : value;
switch (typeof candidateValue) {
case "object":
type = "Object";
break;
export function queryDataType(variable: any) {
let type = "String";

case "boolean":
type = "Boolean";
break;
const value = typeof variable === "object" ? variable.value : variable;

case "number":
type = candidateValue % 1 === 0 ? "Int" : "Float";
break;
}
}
if (variable?.type != null) {
type = variable.type;
} else {
// TODO: Should handle the undefined value (either in array value or single value)
const candidateValue = Array.isArray(value) ? value[0] : value;
switch (typeof candidateValue) {
case "object":
type = "Object";
break;

// set object based variable properties
if (typeof variable === "object") {
if (variable.list === true) {
type = `[${type}]`;
} else if (Array.isArray(variable.list)) {
type = `[${type}${variable.list[0] ? "!" : ""}]`;
}
case "boolean":
type = "Boolean";
break;

if (variable.required) {
type += "!";
}
case "number":
type = candidateValue % 1 === 0 ? "Int" : "Float";
break;
}
}

return type;
// set object based variable properties
if (typeof variable === "object") {
if (variable.list === true) {
type = `[${type}]`;
} else if (Array.isArray(variable.list)) {
type = `[${type}${variable.list[0] ? "!" : ""}]`;
}

if (variable.required) {
type += "!";
}
}

return type;
}
10 changes: 5 additions & 5 deletions src/adapters/DefaultAppSyncMutationAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import Fields from "../Fields";
import IQueryBuilderOptions, { IOperation } from "../IQueryBuilderOptions";
import OperationType from "../OperationType";
import Utils from "../Utils";
import IMutationAdapter from "./IMutationAdapter";
import { queryDataType, queryVariablesMap, resolveVariables } from "../Utils";

export default class DefaultAppSyncMutationAdapter implements IMutationAdapter {
private variables: any | undefined;
Expand All @@ -16,7 +16,7 @@ export default class DefaultAppSyncMutationAdapter implements IMutationAdapter {

constructor(options: IQueryBuilderOptions | IQueryBuilderOptions[]) {
if (Array.isArray(options)) {
this.variables = Utils.resolveVariables(options);
this.variables = resolveVariables(options);
} else {
this.variables = options.variables;
this.fields = options.fields;
Expand All @@ -39,7 +39,7 @@ export default class DefaultAppSyncMutationAdapter implements IMutationAdapter {
return this.operationTemplate(opts.operation);
});
return this.operationWrapperTemplate(
Utils.resolveVariables(mutations),
resolveVariables(mutations),
content.join("\n ")
);
}
Expand All @@ -58,7 +58,7 @@ export default class DefaultAppSyncMutationAdapter implements IMutationAdapter {
return Object.keys(variables).length
? `(${Object.keys(variables).reduce(
(dataString, key, i) =>
`${dataString}${i !== 0 ? ", " : ""}$${key}: ${Utils.queryDataType(
`${dataString}${i !== 0 ? ", " : ""}$${key}: ${queryDataType(
variables[key]
)}`,
""
Expand All @@ -77,7 +77,7 @@ export default class DefaultAppSyncMutationAdapter implements IMutationAdapter {
} ${this.queryDataArgumentAndTypeMap(variables)} {
${content}
}`,
variables: Utils.queryVariablesMap(variables),
variables: queryVariablesMap(variables),
};
}

Expand Down
Loading