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

Support scope in admin-generator #1696

Closed
wants to merge 1 commit into from
Closed
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
48 changes: 39 additions & 9 deletions packages/admin/cms-admin/src/generator/future/generateForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { generateFormField } from "./generateFormField";
import { FormConfig, GeneratorReturn } from "./generator";
import { camelCaseToHumanReadable } from "./utils/camelCaseToHumanReadable";
import { findRootBlocks } from "./utils/findRootBlocks";
import { generateGqlParamDefinition } from "./utils/generateGqlParamDefinition";
import { generateImportsCode, Imports } from "./utils/generateImportsCode";

export function generateForm(
Expand All @@ -16,12 +17,35 @@ export function generateForm(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
config: FormConfig<any>,
): GeneratorReturn {
const gqlQueryScopeParamName = "scope";
const gqlType = config.gqlType;
const title = config.title ?? camelCaseToHumanReadable(gqlType);
const instanceGqlType = gqlType[0].toLowerCase() + gqlType.substring(1);
const gqlDocuments: Record<string, string> = {};
const imports: Imports = [];

const queries = gqlIntrospection.__schema.types.find((type) => type.name === "Query");
if (!queries || queries.kind !== "OBJECT") throw new Error(`Missing Query-Type in schema. Do any queries exist?`);
const mutations = gqlIntrospection.__schema.types.find((type) => type.name === "Mutation");
if (!mutations || mutations.kind !== "OBJECT") throw new Error(`Missing Mutation-Type in schema. Do any mutations exist?`);

const queryName = instanceGqlType;
const introspectedQueryField = queries.fields.find((field) => field.name === queryName);
if (!introspectedQueryField) throw new Error(`query "${queryName}" for ${gqlType} in schema not found`);
const queryScopeParam = introspectedQueryField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const createMutationName = `create${gqlType}`;
const introspectedCreateMutationField = mutations.fields.find((field) => field.name === createMutationName);
if (!introspectedCreateMutationField) throw new Error(`create-mutation "${createMutationName}" for ${gqlType} in schema not found`);
const createMutationScopeParam = introspectedCreateMutationField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const updateMutationName = `update${gqlType}`;
const introspectedUpdateMutationField = mutations.fields.find((field) => field.name === updateMutationName);
if (!introspectedUpdateMutationField) throw new Error(`update-mutation "${updateMutationName}" for ${gqlType} in schema not found`);
const updateMutationScopeParam = introspectedUpdateMutationField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const requiresScope = !!(queryScopeParam || createMutationScopeParam || updateMutationScopeParam);

// TODO make RootBlocks configurable (from config)
const rootBlocks = findRootBlocks({ gqlType, targetDirectory }, gqlIntrospection);

Expand All @@ -36,8 +60,8 @@ export function generateForm(
`;

gqlDocuments[`${instanceGqlType}Query`] = `
query ${gqlType}($id: ID!) {
${instanceGqlType}(id: $id) {
query ${gqlType}($id: ID!${queryScopeParam ? `, $scope: ${generateGqlParamDefinition(queryScopeParam)}` : ""}) {
${queryName}(id: $id${queryScopeParam ? `, scope: $scope` : ""}) {
id
updatedAt
...${fragmentName}
Expand All @@ -47,8 +71,10 @@ export function generateForm(
`;

gqlDocuments[`create${gqlType}Mutation`] = `
mutation Create${gqlType}($input: ${gqlType}Input!) {
create${gqlType}(input: $input) {
mutation Create${gqlType}($input: ${gqlType}Input!${
createMutationScopeParam ? `, $scope: ${generateGqlParamDefinition(createMutationScopeParam)}` : ""
}) {
${createMutationName}(input: $input${createMutationScopeParam ? `, scope: $scope` : ""}) {
id
updatedAt
...${fragmentName}
Expand All @@ -58,8 +84,10 @@ export function generateForm(
`;

gqlDocuments[`update${gqlType}Mutation`] = `
mutation Update${gqlType}($id: ID!, $input: ${gqlType}UpdateInput!, $lastUpdatedAt: DateTime) {
update${gqlType}(id: $id, input: $input, lastUpdatedAt: $lastUpdatedAt) {
mutation Update${gqlType}($id: ID!, $input: ${gqlType}UpdateInput!, $lastUpdatedAt: DateTime${
updateMutationScopeParam ? `, $scope: ${generateGqlParamDefinition(updateMutationScopeParam)}` : ""
}) {
${updateMutationName}(id: $id, input: $input, lastUpdatedAt: $lastUpdatedAt${updateMutationScopeParam ? `, scope: $scope` : ""}) {
id
updatedAt
...${fragmentName}
Expand Down Expand Up @@ -126,6 +154,7 @@ export function generateForm(
GQLUpdate${gqlType}Mutation,
GQLUpdate${gqlType}MutationVariables,
} from "./${baseOutputFilename}.gql.generated";
import { useContentScope } from "@src/common/ContentScopeProvider";
${Object.entries(rootBlocks)
.map(([rootBlockKey, rootBlock]) => `import { ${rootBlock.name} } from "${rootBlock.import}";`)
.join("\n")}
Expand Down Expand Up @@ -163,10 +192,11 @@ export function generateForm(
const mode = id ? "edit" : "add";
const formApiRef = useFormApiRef<FormValues>();
const stackSwitchApi = useStackSwitchApi();
${requiresScope ? `const { scope } = useContentScope()` : ""};

const { data, error, loading, refetch } = useQuery<GQL${gqlType}Query, GQL${gqlType}QueryVariables>(
${instanceGqlType}Query,
id ? { variables: { id } } : { skip: true },
id ? { variables: { id${queryScopeParam ? `, scope` : ""} } } : { skip: true },
);

const initialValues = React.useMemo<Partial<FormValues>>(() => data?.${instanceGqlType}
Expand Down Expand Up @@ -209,12 +239,12 @@ export function generateForm(
if (!id) throw new Error();
await client.mutate<GQLUpdate${gqlType}Mutation, GQLUpdate${gqlType}MutationVariables>({
mutation: update${gqlType}Mutation,
variables: { id, input: output, lastUpdatedAt: data?.${instanceGqlType}.updatedAt },
variables: { id, input: output, lastUpdatedAt: data?.${instanceGqlType}.updatedAt${updateMutationScopeParam ? `, scope` : ""} },
});
} else {
const { data: mutationResponse } = await client.mutate<GQLCreate${gqlType}Mutation, GQLCreate${gqlType}MutationVariables>({
mutation: create${gqlType}Mutation,
variables: { input: output },
variables: { input: output${createMutationScopeParam ? `, scope` : ""} },
});
if (!event.navigatingBack) {
const id = mutationResponse?.create${gqlType}.id;
Expand Down
48 changes: 37 additions & 11 deletions packages/admin/cms-admin/src/generator/future/generateGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { plural } from "pluralize";
import { GeneratorReturn, GridConfig } from "./generator";
import { camelCaseToHumanReadable } from "./utils/camelCaseToHumanReadable";
import { findRootBlocks } from "./utils/findRootBlocks";
import { generateGqlParamDefinition } from "./utils/generateGqlParamDefinition";

function tsCodeRecordToString(object: Record<string, string | undefined>) {
return `{${Object.entries(object)
Expand Down Expand Up @@ -65,6 +66,7 @@ export function generateGrid(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
config: GridConfig<any>,
): GeneratorReturn {
const gqlQueryScopeParamName = "scope";
const gqlType = config.gqlType;
const gqlTypePlural = plural(gqlType);
//const title = config.title ?? camelCaseToHumanReadable(gqlType);
Expand All @@ -74,6 +76,26 @@ export function generateGrid(
const gqlDocuments: Record<string, string> = {};
//const imports: Imports = [];

const queries = gqlIntrospection.__schema.types.find((type) => type.name === "Query");
if (!queries || queries.kind !== "OBJECT") throw new Error(`Missing Query-Type in schema. Do any queries exist?`);
const mutations = gqlIntrospection.__schema.types.find((type) => type.name === "Mutation");
if (!mutations || mutations.kind !== "OBJECT") throw new Error(`Missing Mutation-Type in schema. Do any mutations exist?`);

const queryName = instanceGqlType;
const introspectedQueryField = queries.fields.find((field) => field.name === queryName);
if (!introspectedQueryField) throw new Error(`query "${queryName}" for ${gqlType} in schema not found`);
const queryScopeParam = introspectedQueryField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const createMutationName = `create${gqlType}`;
const introspectedCreateMutationField = mutations.fields.find((field) => field.name === createMutationName);
if (!introspectedCreateMutationField) throw new Error(`create-mutation "${createMutationName}" for ${gqlType} in schema not found`);
const createMutationScopeParam = introspectedCreateMutationField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const deleteMutationName = `delete${gqlType}`;
const introspectedDeleteMutationField = mutations.fields.find((field) => field.name === deleteMutationName);
if (!introspectedDeleteMutationField) throw new Error(`delete-mutation "${deleteMutationName}" for ${gqlType} in schema not found`);
const deleteMutationScopeParam = introspectedDeleteMutationField.args.find((arg) => arg.name === gqlQueryScopeParamName);

const rootBlocks = findRootBlocks({ gqlType, targetDirectory }, gqlIntrospection);

const gridQueryType = findQueryTypeOrThrow(gridQuery, gqlIntrospection);
Expand Down Expand Up @@ -123,7 +145,7 @@ export function generateGrid(
}

const hasSearch = gridQueryType.args.some((arg) => arg.name === "search");
const hasScope = gridQueryType.args.some((arg) => arg.name === "scope");
const requiresScope = !!(queryScopeParam || createMutationScopeParam || deleteMutationScopeParam);

const schemaEntity = gqlIntrospection.__schema.types.find((type) => type.kind === "OBJECT" && type.name === gqlType) as
| IntrospectionObjectType
Expand Down Expand Up @@ -268,10 +290,10 @@ export function generateGrid(
const ${instanceGqlTypePlural}Query = gql\`
query ${gqlTypePlural}Grid($offset: Int, $limit: Int${hasSort ? `, $sort: [${gqlType}Sort!]` : ""}${hasSearch ? `, $search: String` : ""}${
hasFilter ? `, $filter: ${gqlType}Filter` : ""
}${hasScope ? `, $scope: ${gqlType}ContentScopeInput!` : ""}) {
}${queryScopeParam ? `, $scope: ${generateGqlParamDefinition(queryScopeParam)}` : ""}) {
${gridQuery}(offset: $offset, limit: $limit${hasSort ? `, sort: $sort` : ""}${hasSearch ? `, search: $search` : ""}${
hasFilter ? `, filter: $filter` : ""
}${hasScope ? `, scope: $scope` : ""}) {
}${queryScopeParam ? `, scope: $scope` : ""}) {
nodes {
...${fragmentName}
}
Expand All @@ -285,8 +307,10 @@ export function generateGrid(
${
hasDeleteMutation
? `const delete${gqlType}Mutation = gql\`
mutation Delete${gqlType}($id: ID!) {
delete${gqlType}(id: $id)
mutation Delete${gqlType}($id: ID!${
deleteMutationScopeParam ? `, $scope: ${generateGqlParamDefinition(deleteMutationScopeParam)}` : ""
}) {
delete${gqlType}(id: $id${deleteMutationScopeParam ? `, scope: $scope` : ""})
}
\`;`
: ""
Expand All @@ -295,8 +319,10 @@ export function generateGrid(
${
hasCreateMutation
? `const create${gqlType}Mutation = gql\`
mutation Create${gqlType}(${hasScope ? `$scope: ${gqlType}ContentScopeInput!, ` : ""}$input: ${gqlType}Input!) {
create${gqlType}(${hasScope ? `scope: $scope, ` : ""}input: $input) {
mutation Create${gqlType}(${
createMutationScopeParam ? `$scope: ${generateGqlParamDefinition(createMutationScopeParam)}, ` : ""
}$input: ${gqlType}Input!) {
create${gqlType}(${createMutationScopeParam ? `scope: $scope, ` : ""}input: $input) {
id
}
}
Expand Down Expand Up @@ -341,7 +367,7 @@ export function generateGrid(
const client = useApolloClient();
const intl = useIntl();
const dataGridProps = { ...useDataGridRemote(), ...usePersistentColumnState("${gqlTypePlural}Grid") };
${hasScope ? `const { scope } = useContentScope();` : ""}
${requiresScope ? `const { scope } = useContentScope();` : ""}

const columns: GridColDef<GQL${fragmentName}Fragment>[] = [
${gridColumnFields
Expand Down Expand Up @@ -395,7 +421,7 @@ export function generateGrid(
onPaste={async ({ input }) => {
await client.mutate<GQLCreate${gqlType}Mutation, GQLCreate${gqlType}MutationVariables>({
mutation: create${gqlType}Mutation,
variables: { ${hasScope ? `scope, ` : ""}input },
variables: { ${createMutationScopeParam ? `scope, ` : ""}input },
});
}}
`
Expand All @@ -407,7 +433,7 @@ export function generateGrid(
onDelete={async () => {
await client.mutate<GQLDelete${gqlType}Mutation, GQLDelete${gqlType}MutationVariables>({
mutation: delete${gqlType}Mutation,
variables: { id: params.row.id },
variables: { id: params.row.id${deleteMutationScopeParam ? `, scope` : ""} },
});
}}
`
Expand All @@ -431,7 +457,7 @@ export function generateGrid(

const { data, loading, error } = useQuery<GQL${gqlTypePlural}GridQuery, GQL${gqlTypePlural}GridQueryVariables>(${instanceGqlTypePlural}Query, {
variables: {
${hasScope ? `scope,` : ""}
${queryScopeParam ? `scope,` : ""}
${hasFilter ? `filter: gqlFilter,` : ""}
${hasSearch ? `search: gqlSearch,` : ""}
offset: dataGridProps.page * dataGridProps.pageSize,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IntrospectionInputValue } from "graphql";

export function generateGqlParamDefinition(queryParam: IntrospectionInputValue) {
const isRequired = queryParam.type.kind === "NON_NULL";
if (queryParam.type.kind === "NON_NULL") {
if (queryParam.type.ofType.kind === "INPUT_OBJECT") {
return `${queryParam.type.ofType.name}${isRequired ? "!" : ""}`;
} else {
throw new Error(`InputValue-kind ${queryParam.type.ofType.kind} below "NON_NULL" not supported`);
}
} else {
throw new Error(`InputValue-kind ${queryParam.type.kind} not supported`);
}
}
Loading