Skip to content

Commit

Permalink
feat(scaffold): create dynamic and static templates on scaffold (#533)
Browse files Browse the repository at this point in the history
dependent on #532 

view changes made in last commit for actual PR. The rest of commits are
from PR#532
  • Loading branch information
asanehisa authored Jul 30, 2024
1 parent 4039f5b commit 0008e58
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 3 deletions.
39 changes: 37 additions & 2 deletions packages/pages/src/scaffold/template/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import prompts, { PromptObject } from "prompts";
import { ProjectStructure } from "../../common/src/project/structure.js";
import path from "node:path";
import fs from "node:fs";
import { newConfigFile, visualEditorTemplateCode } from "./sampleTemplates.js";
import {
dynamicTemplate,
newConfigFile,
staticTemplate,
visualEditorTemplateCode,
} from "./sampleTemplates.js";
import { addDataToPuckConfig } from "../../common/src/parsers/puckConfigParser.js";
import {
installDependencies,
Expand Down Expand Up @@ -78,7 +83,9 @@ export const generateTemplate = async (
if (response.isVisualEditor) {
await generateVETemplate(response, projectStructure);
} else {
// TODO (SUMO-5252): handle generating non-VE templates
response.isDynamic
? await generateDynamicTemplate(response, projectStructure)
: await generateStaticTemplate(response.templateName, projectStructure);
}
};

Expand Down Expand Up @@ -168,3 +175,31 @@ const addVEDependencies = async () => {
await updatePackageDependency("@measured/puck", null, true);
await installDependencies();
};

// Creates a file with a basic dynamic template based on provided user responses
const generateDynamicTemplate = async (
response: any,
projectStructure: ProjectStructure
) => {
const templatePath = projectStructure.getTemplatePaths()[0].path;
const templateFileName = formatFileName(response.templateName);

fs.writeFileSync(
path.join(templatePath, `${templateFileName}.tsx`),
dynamicTemplate(templateFileName, response.entityScope, response.filter)
);
};

// Creates a file with a basic static template based templateName provided by user
const generateStaticTemplate = async (
templateName: string,
projectStructure: ProjectStructure
) => {
const templatePath = projectStructure.getTemplatePaths()[0].path;
const templateFileName = formatFileName(templateName);

fs.writeFileSync(
path.join(templatePath, `${templateFileName}.tsx`),
staticTemplate(templateFileName)
);
};
59 changes: 58 additions & 1 deletion packages/pages/src/scaffold/template/sampleTemplates.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { describe, expect, it } from "vitest";
import { newConfigFile, visualEditorTemplateCode } from "./sampleTemplates.js";
import {
dynamicTemplate,
newConfigFile,
staticTemplate,
visualEditorTemplateCode,
} from "./sampleTemplates.js";
import fs from "node:fs";
import { Project } from "ts-morph";

Expand Down Expand Up @@ -58,3 +63,55 @@ describe("visualEditorTemplateCode", () => {
}
});
});

describe("staticTemplate", () => {
it("confirm returned code has no warnings", () => {
const fileContent = staticTemplate("testTemplate");
const filePath = "test.tsx";

try {
fs.writeFileSync(filePath, fileContent);
const project = new Project();
project.addSourceFileAtPath(filePath);
const diagnostics = project
.getPreEmitDiagnostics()
.filter(
(d) =>
!d.getMessageText().toString().includes("Cannot find module") &&
!d.getMessageText().toString().includes("Cannot use JSX")
);
expect(diagnostics.length).toBe(0);
} finally {
if (fs.existsSync("test.tsx")) {
fs.unlinkSync("test.tsx");
}
}
});
});

describe("dynamicTemplate", () => {
it("confirm returned code has no warnings", () => {
const fileContent = dynamicTemplate("testTemplate", "entityTypes", [
"location",
]);
const filePath = "test.tsx";

try {
fs.writeFileSync(filePath, fileContent);
const project = new Project();
project.addSourceFileAtPath(filePath);
const diagnostics = project
.getPreEmitDiagnostics()
.filter(
(d) =>
!d.getMessageText().toString().includes("Cannot find module") &&
!d.getMessageText().toString().includes("Cannot use JSX")
);
expect(diagnostics.length).toBe(0);
} finally {
if (fs.existsSync("test.tsx")) {
fs.unlinkSync("test.tsx");
}
}
});
});
94 changes: 94 additions & 0 deletions packages/pages/src/scaffold/template/sampleTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,97 @@ export const ${fileName}Config: Config<${formattedTemplateName}Props> = {
`;
};

export const dynamicTemplate = (
templateName: string,
entityScope: string,
filter: string[]
) => {
const formattedTemplateName =
templateName.charAt(0).toUpperCase() + templateName.slice(1);
const filterCode = `${entityScope}: ${JSON.stringify(filter)},`;

return `import {
Template,
GetPath,
TemplateConfig,
TemplateProps,
TemplateRenderProps,
GetHeadConfig,
HeadConfig,
} from "@yext/pages";
export const config: TemplateConfig = {
name: "${templateName}",
stream: {
$id: "${templateName}-stream",
filter: {
${filterCode}
},
fields: [
"id",
"name",
"slug",
],
localization: {
locales: ["en"],
},
},
};
export const getHeadConfig: GetHeadConfig<TemplateRenderProps> = ({
document,
}): HeadConfig => {
return {
title: document.name,
charset: "UTF-8",
viewport: "width=device-width, initial-scale=1"
};
};
export const getPath: GetPath<TemplateProps> = ({ document }) => {
return document.slug ? document.slug : "${templateName}/" + document.id;
};
const ${formattedTemplateName}: Template<TemplateRenderProps> = ({ document }) => {
return (
<div>${formattedTemplateName} page</div>
);
};
export default ${formattedTemplateName};
`;
};

export const staticTemplate = (templateName: string) => {
const formattedTemplateName =
templateName.charAt(0).toUpperCase() + templateName.slice(1);

return `import {
GetPath,
TemplateProps,
TemplateRenderProps,
GetHeadConfig,
} from "@yext/pages";
export const getPath: GetPath<TemplateProps> = () => {
return "${templateName}";
};
export const getHeadConfig: GetHeadConfig<TemplateRenderProps> = () => {
return {
title: "${templateName}",
charset: "UTF-8",
viewport: "width=device-width, initial-scale=1",
};
};
const ${formattedTemplateName} = (data: TemplateRenderProps) => {
return (
<div>${templateName} page</div>
);
};
export default ${formattedTemplateName};
`;
};

0 comments on commit 0008e58

Please sign in to comment.