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: removes warning about --experimental flags #1

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
PagesJS is a collection of tools that make it easy to develop on [Yext Pages](https://www.yext.com/platform/pages). It provides 2 main tools:

1. A default development server, backed by [Vite](https://vitejs.dev/), that makes local development fast and easy.
1. A Vite plugin used to bundle your assets and templates for Yext Pages.
2. A Vite plugin used to bundle your assets and templates for Yext Pages.

## Packages

Expand All @@ -17,11 +17,11 @@ PagesJS is a collection of tools that make it easy to develop on [Yext Pages](ht
## Utility Functions

| Function |
| -------------------------------------------------------------------------------------------------------- | --- |
| -------------------------------------------------------------------------------------------------------- |
| [fetch()](https://github.com/yext/pages/blob/main/packages/pages/src/util/README.md#fetch) |
| [getRuntime()](https://github.com/yext/pages/blob/main/packages/pages/src/util/README.md#getRuntime) |
| [isProduction()](https://github.com/yext/pages/blob/main/packages/pages/src/util/README.md#isProduction) |
| [useDocument()](https://github.com/yext/pages/blob/main/packages/pages/src/util/README.md#useDocument) | |
| [useDocument()](https://github.com/yext/pages/blob/main/packages/pages/src/util/README.md#useDocument) |

## Development

Expand Down
26 changes: 26 additions & 0 deletions packages/pages/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
#### 1.2.0-beta.0 (2024-08-01)

##### New Features

* **dev:**
* override document visual configuration (#534) (f7b7e7e9)
* add pageSets to global variable in header in dev mode (#531) (b239cbb5)
* **scaffold:**
* create dynamic and static templates on scaffold (#533) (0008e583)
* create ve template on scaffold (#532) (4039f5bd)
* add prompts for scaffold template (#529) (529ee240)
* **util:** add useDocument hook (#528) (f27199ab)

##### Bug Fixes

* pnpm actions (083a7a54)

##### Other Changes

* [email protected] (2953ca7a)
* [email protected] (dfb04527)
Comment on lines +20 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Duplicate version entry. Consider removing one


##### Refactors

* change the type of additionalProperties in TemplateConfig to 'Record<string, any>' (#527) (8fd95b19)

#### 1.1.1 (2024-06-13)

##### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion packages/pages/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yext/pages",
"version": "1.1.1",
"version": "1.2.0-beta.0",
"description": "The default React development toolchain provided by Yext",
"author": "[email protected]",
"license": "BSD-3-Clause",
Expand Down
20 changes: 0 additions & 20 deletions packages/pages/src/bin/loader.js

This file was deleted.

18 changes: 1 addition & 17 deletions packages/pages/src/bin/spawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,11 @@ import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const filePrefix = path.sep === path.win32.sep ? "file:\\\\" : "";
const pathToPagesScript = path.resolve(__dirname, "./pages.js");
const pathToLoader = filePrefix + path.resolve(__dirname, "./loader.js");

const nodeVersion = Number(
spawnSync("node", ["-v"], { encoding: "utf-8" })
.stdout.substring(1)
.split(".")[0]
);

const experimentalFlags = ["--experimental-vm-modules"];
if (nodeVersion === 18) {
experimentalFlags.push("--experimental-specifier-resolution=node");
} else {
experimentalFlags.push("--experimental-loader");
experimentalFlags.push(pathToLoader);
}

const results = spawnSync(
"node",
[...experimentalFlags, pathToPagesScript, ...process.argv.slice(2)],
[pathToPagesScript, ...process.argv.slice(2)],
{
stdio: "inherit",
}
Expand Down
32 changes: 32 additions & 0 deletions packages/pages/src/common/src/parsers/puckConfigParser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, it, expect } from "vitest";
import fs from "node:fs";
import { addDataToPuckConfig } from "./puckConfigParser.js";

describe("addDataToPuckConfig", () => {
it("should throw an error if the filepath is invalid", () => {
expect(() => addDataToPuckConfig("fileName", "invalid/filepath")).toThrow(
'Filepath "invalid/filepath" is invalid.'
);
});

it("correctly adds new config to the puck config file", () => {
try {
fs.writeFileSync(
"test.tsx",
`export const puckConfigs = new Map<string, Config<any>>([
["location", locationConfig],
]);`
);
addDataToPuckConfig("foo", "test.tsx");
const modifiedContent = fs.readFileSync("test.tsx", "utf-8");
expect(modifiedContent).toContain('["foo", fooConfig]');
expect(modifiedContent).toContain(
`export const fooConfig: Config<FooProps>`
);
} finally {
if (fs.existsSync("test.tsx")) {
fs.unlinkSync("test.tsx");
}
Comment on lines +27 to +29
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Use fs.promises.unlink for consistent async operations

}
});
});
43 changes: 43 additions & 0 deletions packages/pages/src/common/src/parsers/puckConfigParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import fs from "node:fs";
import SourceFileParser, { createTsMorphProject } from "./sourceFileParser.js";
import { newConfig } from "../../../scaffold/template/sampleTemplates.js";
import { SyntaxKind } from "ts-morph";

/**
* Adds variables to the puck config file and adds the new config to
* the exported map.
* @param fileName template name with invalid chars and spaces removed
* @param filepath /src/puck/ve.config.ts
*/
export function addDataToPuckConfig(fileName: string, filepath: string) {
if (!fs.existsSync(filepath)) {
throw new Error(`Filepath "${filepath}" is invalid.`);
}
Comment on lines +13 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using a more specific error message that includes the expected file path format.

const parser = new SourceFileParser(filepath, createTsMorphProject());

const puckConfigsStatement = parser.getVariableStatement("puckConfigs");

const formattedTemplateName =
fileName.charAt(0).toUpperCase() + fileName.slice(1);
Comment on lines +20 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using fileName.charAt(0).toUpperCase() + fileName.slice(1).toLowerCase() to ensure consistent formatting.


const puckConfigsStartLocation = puckConfigsStatement.getStart();
parser.insertStatement(
newConfig(formattedTemplateName, fileName),
puckConfigsStartLocation
);

const puckConfigsDeclaration = parser.getVariableDeclaration("puckConfigs");
const puckConfigsInitializer = puckConfigsDeclaration.getInitializer();
if (
puckConfigsInitializer &&
puckConfigsInitializer.getKind() === SyntaxKind.NewExpression
) {
const newExpression = puckConfigsInitializer;
const puckConfigsArray = newExpression.getFirstChildByKindOrThrow(
SyntaxKind.ArrayLiteralExpression
);
puckConfigsArray.addElement(`["${fileName}", ${fileName}Config]`);
}
parser.format();
parser.save();
}
12 changes: 12 additions & 0 deletions packages/pages/src/common/src/parsers/sourceFileParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,16 @@ export default class SourceFileParser {
removeUnusedImports() {
this.sourceFile.fixUnusedIdentifiers();
}

format() {
this.sourceFile.formatText();
}

getVariableStatement(variableName: string) {
return this.sourceFile.getVariableStatementOrThrow(variableName);
}

getVariableDeclaration(variableName: string) {
return this.sourceFile.getVariableDeclarationOrThrow(variableName);
}
Comment on lines +285 to +291
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: These methods throw errors if the variable is not found. Consider adding error handling or returning undefined instead

}
11 changes: 10 additions & 1 deletion packages/pages/src/common/src/template/hydration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HeadConfig, renderHeadConfigToString } from "./head.js";
import { convertToPosixPath } from "./paths.js";
import { TemplateRenderProps } from "./types.js";
import { FeaturesConfig } from "../feature/features.js";

/**
* Imports the custom hydration template and entrypoint template as modules and calls
Expand Down Expand Up @@ -134,21 +135,29 @@ const getCommonInjectedIndexHtml = (
* @param clientHydrationString
* @param indexHtml
* @param appLanguage
* @param templatesConfig
* @param headConfig
* @returns the server template to render in the Vite dev environment
*/
export const getIndexTemplateDev = (
clientHydrationString: string | undefined,
indexHtml: string,
appLanguage: string,
templatesConfig: FeaturesConfig,
headConfig?: HeadConfig
): string => {
return getCommonInjectedIndexHtml(
let commonIndex = getCommonInjectedIndexHtml(
clientHydrationString,
indexHtml,
appLanguage,
headConfig
);
commonIndex = injectIntoEndOfHead(
commonIndex,
`<script>const pageSets = ${JSON.stringify(templatesConfig, null)}</script>`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: consider using JSON.stringify(templatesConfig, null, 2) for better readability in the browser

);

return commonIndex;
};

/**
Expand Down
13 changes: 13 additions & 0 deletions packages/pages/src/dev/server/middleware/sendAppHTML.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import {
getHydrationTemplateDev,
getIndexTemplateDev,
} from "../../../common/src/template/hydration.js";
import {
getTemplateModules,
getTemplatesConfig,
} from "../../../generate/templates/createTemplatesJson.js";
import { FeaturesConfig } from "../../../common/src/feature/features.js";
Comment on lines +16 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider moving these imports to the top of the file for consistency.


/**
* Renders the HTML for a given {@link TemplateModuleInternal}
Expand Down Expand Up @@ -53,6 +58,13 @@ export default async function sendAppHTML(
clientServerRenderTemplates.serverRenderTemplatePath
)) as ServerRenderTemplate;

const { templateModules, redirectModules } =
await getTemplateModules(projectStructure);
const templatesConfig: FeaturesConfig = getTemplatesConfig(
templateModules,
redirectModules
);

const clientInjectedIndexHtml = getIndexTemplateDev(
clientHydrationString,
serverRenderTemplateModule.getIndexHtml
Expand All @@ -62,6 +74,7 @@ export default async function sendAppHTML(
})
: serverRenderTemplateModule.indexHtml,
getLang(headConfig, props),
templatesConfig,
headConfig
);

Expand Down
4 changes: 4 additions & 0 deletions packages/pages/src/dev/server/middleware/serverRenderRoute.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RequestHandler } from "express-serve-static-core";
import { ViteDevServer } from "vite";
import merge from "lodash/merge.js";
import { propsLoader } from "../ssr/propsLoader.js";
import {
parseAsStaticUrl,
Expand Down Expand Up @@ -88,6 +89,9 @@ export const serverRenderRoute =
return;
}

const overrides = JSON.parse(req?.body?.overrides ?? "{}");
merge(document, overrides);
Comment on lines +92 to +93
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: New functionality to parse and merge overrides from request body. Consider potential security implications of allowing client-side modifications to server-side data.


const props = await propsLoader({
templateModuleInternal,
document,
Expand Down
11 changes: 10 additions & 1 deletion packages/pages/src/dev/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,18 @@ export const createServer = async (
}
});

app.post(
/^\/(.+)/,
serverRenderRoute({
vite,
dynamicGenerateData,
projectStructure,
})
);
Comment on lines +194 to +201
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: New POST route handler uses same middleware as GET. Consider if POST requests need different processing.


// When a page is requested that is anything except the root, call our
// serverRenderRoute middleware.
app.use(
app.get(
/^\/(.+)/,
useProdURLs
? serverRenderSlugRoute({
Expand Down
15 changes: 1 addition & 14 deletions packages/pages/src/generate/features/features.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
import { ProjectStructure } from "../../common/src/project/structure.js";
import { getTemplateFilepaths } from "../../common/src/template/internal/getTemplateFilepaths.js";
import { Command } from "commander";
import { createTemplatesJson } from "../templates/createTemplatesJson.js";
import { logErrorAndExit } from "../../util/logError.js";
import { getRedirectFilePaths } from "../../common/src/redirect/internal/getRedirectFilepaths.js";

const handler = async ({ scope }: { scope: string }): Promise<void> => {
const projectStructure = await ProjectStructure.init({ scope });
const templateFilepaths = getTemplateFilepaths(
projectStructure.getTemplatePaths()
);
const redirectFilepaths = getRedirectFilePaths(
projectStructure.getRedirectPaths()
);

try {
await createTemplatesJson(
templateFilepaths,
redirectFilepaths,
projectStructure,
"FEATURES"
);
await createTemplatesJson(projectStructure, "FEATURES");
} catch (error) {
logErrorAndExit(error);
}
Expand Down
Loading