mirror of
https://github.com/vale981/Vulcan
synced 2025-03-07 02:21:43 -05:00
545 lines
12 KiB
JavaScript
545 lines
12 KiB
JavaScript
import { Utils } from './utils';
|
|
|
|
export const convertToGraphQL = (fields, indentation) => {
|
|
return fields.length > 0 ? fields.map(f => fieldTemplate(f, indentation)).join('\n') : '';
|
|
};
|
|
|
|
export const arrayToGraphQL = fields => fields.map(f => `${f.name}: ${f.type}`).join(', ');
|
|
|
|
/*
|
|
|
|
For backwards-compatibility reasons, args can either be a string or an array of objects
|
|
|
|
*/
|
|
export const getArguments = args => {
|
|
if (Array.isArray(args) && args.length > 0) {
|
|
return `(${arrayToGraphQL(args)})`;
|
|
} else if (typeof args === 'string') {
|
|
return `(${args})`;
|
|
} else {
|
|
return '';
|
|
}
|
|
};
|
|
|
|
/* ------------------------------------- Generic Field Template ------------------------------------- */
|
|
|
|
// export const fieldTemplate = ({ name, type, args, directive, description, required }, indentation = '') =>
|
|
// `${description ? `${indentation}# ${description}\n` : ''}${indentation}${name}${getArguments(args)}: ${type}${required ? '!' : ''} ${directive ? directive : ''}`;
|
|
|
|
// version that does not make any fields required
|
|
export const fieldTemplate = ({ name, type, args, directive, description, required }, indentation = '') =>
|
|
`${description ? `${indentation}# ${description}\n` : ''}${indentation}${name}${getArguments(args)}: ${type} ${directive ? directive : ''}`;
|
|
|
|
/* ------------------------------------- Main Type ------------------------------------- */
|
|
|
|
/*
|
|
|
|
The main type
|
|
|
|
type Movie{
|
|
_id: String
|
|
title: String
|
|
description: String
|
|
createdAt: Date
|
|
}
|
|
|
|
*/
|
|
export const mainTypeTemplate = ({ typeName, description, interfaces, fields }) =>
|
|
`# ${description}
|
|
type ${typeName} ${interfaces.length ? `implements ${interfaces.join(', ')} ` : ''}{
|
|
${convertToGraphQL(fields, ' ')}
|
|
}
|
|
`;
|
|
|
|
/* ------------------------------------- Selector Types ------------------------------------- */
|
|
|
|
/*
|
|
|
|
The selector type is used to query for one or more documents
|
|
|
|
type MovieSelectorInput {
|
|
AND: [MovieSelectorInput]
|
|
OR: [MovieSelectorInput]
|
|
id: String
|
|
id_not: String
|
|
id_in: [String!]
|
|
id_not_in: [String!]
|
|
...
|
|
name: String
|
|
name_not: String
|
|
name_in: [String!]
|
|
name_not_in: [String!]
|
|
...
|
|
}
|
|
|
|
see https://www.opencrud.org/#sec-Data-types
|
|
|
|
*/
|
|
export const selectorInputTemplate = ({ typeName, fields }) =>
|
|
`input ${typeName}SelectorInput {
|
|
AND: [${typeName}SelectorInput]
|
|
OR: [${typeName}SelectorInput]
|
|
${convertToGraphQL(fields, ' ')}
|
|
}`;
|
|
|
|
/*
|
|
|
|
The unique selector type is used to query for exactly one document
|
|
|
|
type MovieSelectorUniqueInput {
|
|
_id: String
|
|
slug: String
|
|
}
|
|
|
|
*/
|
|
export const selectorUniqueInputTemplate = ({ typeName, fields }) =>
|
|
`input ${typeName}SelectorUniqueInput {
|
|
_id: String
|
|
documentId: String # OpenCRUD backwards compatibility
|
|
slug: String
|
|
${convertToGraphQL(fields, ' ')}
|
|
}`;
|
|
|
|
/*
|
|
|
|
The orderBy type defines which fields a query can be ordered by
|
|
|
|
enum MovieOrderByInput {
|
|
title
|
|
createdAt
|
|
}
|
|
|
|
*/
|
|
export const orderByInputTemplate = ({ typeName, fields }) =>
|
|
`enum ${typeName}OrderByInput {
|
|
foobar
|
|
${fields.join('\n ')}
|
|
}`;
|
|
|
|
/* ------------------------------------- Query Types ------------------------------------- */
|
|
|
|
/*
|
|
|
|
A query for a single document
|
|
|
|
movie(input: SingleMovieInput) : SingleMovieOutput
|
|
|
|
*/
|
|
export const singleQueryTemplate = ({ typeName }) => `${Utils.camelCaseify(typeName)}(input: Single${typeName}Input): Single${typeName}Output`;
|
|
|
|
|
|
/*
|
|
|
|
A query for multiple documents
|
|
|
|
movies(input: MultiMovieInput) : MultiMovieOutput
|
|
|
|
*/
|
|
export const multiQueryTemplate = ({ typeName }) => `${Utils.camelCaseify(Utils.pluralize(typeName))}(input: Multi${typeName}Input): Multi${typeName}Output`;
|
|
|
|
/* ------------------------------------- Query Input Types ------------------------------------- */
|
|
|
|
/*
|
|
|
|
The argument type when querying for a single document
|
|
|
|
type SingleMovieInput {
|
|
selector {
|
|
documentId: String
|
|
# or `_id: String`
|
|
# or `slug: String`
|
|
}
|
|
enableCache: Boolean
|
|
}
|
|
|
|
*/
|
|
export const singleInputTemplate = ({ typeName }) =>
|
|
`input Single${typeName}Input {
|
|
selector: ${typeName}SelectorUniqueInput
|
|
# Whether to enable caching for this query
|
|
enableCache: Boolean
|
|
# Return null instead of throwing MissingDocumentError
|
|
allowNull: Boolean
|
|
}`;
|
|
|
|
/*
|
|
|
|
The argument type when querying for multiple documents
|
|
|
|
type MultiMovieInput {
|
|
terms: JSON
|
|
offset: Int
|
|
limit: Int
|
|
enableCache: Boolean
|
|
}
|
|
|
|
*/
|
|
export const multiInputTemplate = ({ typeName }) =>
|
|
`input Multi${typeName}Input {
|
|
# A JSON object that contains the query terms used to fetch data
|
|
terms: JSON,
|
|
# How much to offset the results by
|
|
offset: Int,
|
|
# A limit for the query
|
|
limit: Int,
|
|
# Whether to enable caching for this query
|
|
enableCache: Boolean
|
|
# Whether to calculate totalCount for this query
|
|
enableTotal: Boolean
|
|
# OpenCRUD fields
|
|
where: ${typeName}SelectorInput
|
|
orderBy: ${typeName}OrderByInput
|
|
skip: Int
|
|
after: String
|
|
before: String
|
|
first: Int
|
|
last: Int
|
|
}`;
|
|
|
|
/* ------------------------------------- Query Output Types ------------------------------------- */
|
|
|
|
/*
|
|
|
|
The type for the return value when querying for a single document
|
|
|
|
type SingleMovieOuput{
|
|
result: Movie
|
|
}
|
|
|
|
*/
|
|
export const singleOutputTemplate = ({ typeName }) =>
|
|
`type Single${typeName}Output{
|
|
result: ${typeName}
|
|
}`;
|
|
|
|
/*
|
|
|
|
The type for the return value when querying for multiple documents
|
|
|
|
type MultiMovieOuput{
|
|
results: [Movie]
|
|
totalCount: Int
|
|
}
|
|
|
|
*/
|
|
export const multiOutputTemplate = ({ typeName }) =>
|
|
`type Multi${typeName}Output{
|
|
results: [${typeName}]
|
|
totalCount: Int
|
|
}`;
|
|
|
|
/* ------------------------------------- Query Queries ------------------------------------- */
|
|
|
|
|
|
/*
|
|
|
|
Single query used on the client
|
|
|
|
query singleMovieQuery($input: SingleMovieInput) {
|
|
movie(input: $input) {
|
|
result {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const singleClientTemplate = ({ typeName, fragmentName, extraQueries }) =>
|
|
`query single${typeName}Query($input: Single${typeName}Input) {
|
|
${Utils.camelCaseify(typeName)}(input: $input) {
|
|
result {
|
|
...${fragmentName}
|
|
}
|
|
__typename
|
|
}
|
|
${extraQueries ? extraQueries : ''}
|
|
}`;
|
|
|
|
|
|
/*
|
|
|
|
Multi query used on the client
|
|
|
|
mutation multiMovieQuery($input: MultiMovieInput) {
|
|
movies(input: $input) {
|
|
results {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
totalCount
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const multiClientTemplate = ({ typeName, fragmentName, extraQueries }) =>
|
|
`query multi${typeName}Query($input: Multi${typeName}Input) {
|
|
${Utils.camelCaseify(Utils.pluralize(typeName))}(input: $input) {
|
|
results {
|
|
...${fragmentName}
|
|
}
|
|
totalCount
|
|
__typename
|
|
}
|
|
${extraQueries ? extraQueries : ''}
|
|
}`;
|
|
|
|
/* ------------------------------------- Mutation Types ------------------------------------- */
|
|
|
|
/*
|
|
|
|
Mutation for creating a new document
|
|
|
|
createMovie(input: CreateMovieInput) : MovieOutput
|
|
|
|
*/
|
|
export const createMutationTemplate = ({ typeName }) =>
|
|
`create${typeName}(data: Create${typeName}DataInput!) : ${typeName}Output`;
|
|
|
|
/*
|
|
|
|
Mutation for updating an existing document
|
|
|
|
updateMovie(input: UpdateMovieInput) : MovieOutput
|
|
|
|
*/
|
|
export const updateMutationTemplate = ({ typeName }) =>
|
|
`update${typeName}(selector: ${typeName}SelectorUniqueInput!, data: Update${typeName}DataInput! ) : ${typeName}Output`;
|
|
|
|
/*
|
|
|
|
Mutation for updating an existing document; or creating it if it doesn't exist yet
|
|
|
|
upsertMovie(input: UpsertMovieInput) : MovieOutput
|
|
|
|
*/
|
|
export const upsertMutationTemplate = ({ typeName }) =>
|
|
`upsert${typeName}(selector: ${typeName}SelectorUniqueInput!, data: Update${typeName}DataInput! ) : ${typeName}Output`;
|
|
|
|
/*
|
|
|
|
Mutation for deleting an existing document
|
|
|
|
deleteMovie(input: DeleteMovieInput) : MovieOutput
|
|
|
|
*/
|
|
export const deleteMutationTemplate = ({ typeName }) =>
|
|
`delete${typeName}(selector: ${typeName}SelectorUniqueInput!) : ${typeName}Output`;
|
|
|
|
/* ------------------------------------- Mutation Input Types ------------------------------------- */
|
|
|
|
// note: not currently used
|
|
|
|
/*
|
|
|
|
Type for create mutation input argument
|
|
|
|
type CreateMovieInput {
|
|
data: CreateMovieDataInput!
|
|
}
|
|
|
|
*/
|
|
export const createInputTemplate = ({ typeName }) =>
|
|
`input Create${typeName}Input{
|
|
data: Create${typeName}DataInput!
|
|
}`;
|
|
|
|
/*
|
|
|
|
Type for update mutation input argument
|
|
|
|
type UpdateMovieInput {
|
|
selector: MovieSelectorUniqueInput!
|
|
data: UpdateMovieDataInput!
|
|
}
|
|
|
|
*/
|
|
export const updateInputTemplate = ({ typeName }) =>
|
|
`input Update${typeName}Input{
|
|
selector: ${typeName}SelectorUniqueInput!
|
|
data: Update${typeName}DataInput!
|
|
}`;
|
|
|
|
/*
|
|
|
|
Type for upsert mutation input argument
|
|
|
|
Note: upsertInputTemplate uses same data type as updateInputTemplate
|
|
|
|
type UpsertMovieInput {
|
|
selector: MovieSelectorUniqueInput!
|
|
data: UpdateMovieDataInput!
|
|
}
|
|
|
|
*/
|
|
export const upsertInputTemplate = ({ typeName }) =>
|
|
`input Upsert${typeName}Input{
|
|
selector: ${typeName}SelectorUniqueInput!
|
|
data: Update${typeName}DataInput!
|
|
}`;
|
|
|
|
/*
|
|
|
|
Type for delete mutation input argument
|
|
|
|
type DeleteMovieInput {
|
|
selector: MovieSelectorUniqueInput!
|
|
}
|
|
|
|
*/
|
|
export const deleteInputTemplate = ({ typeName }) =>
|
|
`input Delete${typeName}Input{
|
|
selector: ${typeName}SelectorUniqueInput!
|
|
}`;
|
|
|
|
/*
|
|
|
|
Type for the create mutation input argument's data property
|
|
|
|
type CreateMovieDataInput {
|
|
title: String
|
|
description: String
|
|
}
|
|
|
|
*/
|
|
export const createDataInputTemplate = ({ typeName, fields }) =>
|
|
`input Create${typeName}DataInput {
|
|
${convertToGraphQL(fields, ' ')}
|
|
}`;
|
|
|
|
/*
|
|
|
|
Type for the update mutation input argument's data property
|
|
|
|
type UpdateMovieDataInput {
|
|
title: String
|
|
description: String
|
|
}
|
|
|
|
*/
|
|
export const updateDataInputTemplate = ({ typeName, fields }) =>
|
|
`input Update${typeName}DataInput {
|
|
${convertToGraphQL(fields, ' ')}
|
|
}`;
|
|
|
|
/* ------------------------------------- Mutation Output Type ------------------------------------- */
|
|
|
|
/*
|
|
|
|
Type for the return value of all mutations
|
|
|
|
type MovieOutput {
|
|
data: Movie
|
|
}
|
|
|
|
*/
|
|
export const mutationOutputTemplate = ({ typeName }) =>
|
|
`type ${typeName}Output{
|
|
data: ${typeName}
|
|
}`;
|
|
|
|
/* ------------------------------------- Mutation Queries ------------------------------------- */
|
|
|
|
/*
|
|
|
|
Create mutation query used on the client
|
|
|
|
mutation createMovie($data: CreateMovieDataInput!) {
|
|
createMovie(data: $data) {
|
|
data {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const createClientTemplate = ({ typeName, fragmentName }) =>
|
|
`mutation create${typeName}($data: Create${typeName}DataInput!) {
|
|
create${typeName}(data: $data) {
|
|
data {
|
|
...${fragmentName}
|
|
}
|
|
}
|
|
}`;
|
|
|
|
/*
|
|
|
|
Update mutation query used on the client
|
|
|
|
mutation updateMovie($selector: MovieSelectorUniqueInput!, $data: UpdateMovieDataInput!) {
|
|
updateMovie(selector: $selector, data: $data) {
|
|
data {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const updateClientTemplate = ({ typeName, fragmentName }) =>
|
|
`mutation update${typeName}($selector: ${typeName}SelectorUniqueInput!, $data: Update${typeName}DataInput!) {
|
|
update${typeName}(selector: $selector, data: $data) {
|
|
data {
|
|
...${fragmentName}
|
|
}
|
|
}
|
|
}`;
|
|
|
|
/*
|
|
|
|
Upsert mutation query used on the client
|
|
|
|
mutation upsertMovie($selector: MovieSelectorUniqueInput!, $data: UpdateMovieDataInput!) {
|
|
upsertMovie(selector: $selector, data: $data) {
|
|
data {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const upsertClientTemplate = ({ typeName, fragmentName }) =>
|
|
`mutation upsert${typeName}($selector: ${typeName}SelectorUniqueInput!, $data: Update${typeName}DataInput!) {
|
|
upsert${typeName}(selector: $selector, data: $data) {
|
|
data {
|
|
...${fragmentName}
|
|
}
|
|
}
|
|
}`;
|
|
|
|
/*
|
|
|
|
Delete mutation query used on the client
|
|
|
|
mutation deleteMovie($selector: MovieSelectorUniqueInput!) {
|
|
deleteMovie(selector: $selector) {
|
|
data {
|
|
_id
|
|
name
|
|
__typename
|
|
}
|
|
__typename
|
|
}
|
|
}
|
|
|
|
*/
|
|
export const deleteClientTemplate = ({ typeName, fragmentName }) =>
|
|
`mutation delete${typeName}($selector: ${typeName}SelectorUniqueInput!) {
|
|
delete${typeName}(selector: $selector) {
|
|
data {
|
|
...${fragmentName}
|
|
}
|
|
}
|
|
}`;
|