Skip to content

Commit

Permalink
Merge branch 'main' into SUMO-5293-continued
Browse files Browse the repository at this point in the history
  • Loading branch information
asanehisa authored Nov 7, 2023
2 parents a52a9df + 7188a1e commit 060efb6
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 619 deletions.
2 changes: 0 additions & 2 deletions packages/pages/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
"yaml": "^2.3.1"
},
"devDependencies": {
"@babel/core": "^7.22.10",
"@microsoft/api-documenter": "^7.22.33",
"@microsoft/api-extractor": "^7.36.4",
"@testing-library/react": "^14.0.0",
Expand All @@ -105,7 +104,6 @@
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@types/ws": "^8.5.5",
"babel-loader": "^9.1.3",
"esbuild": "^0.19.3",
"generate-license-file": "^2.0.0",
"glob": "^10.3.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const validateGetPathValue = (
value: unknown,
templateIdentifier: string
) => {
if (!value || typeof value !== "string") {
throw new Error(
`getPath does not return a valid string in template '${templateIdentifier}'`
);
}
};
3 changes: 2 additions & 1 deletion packages/pages/src/dev/server/middleware/indexPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { parseYextrcContents } from "../../../util/yextrcContents.js";
import { getPartition } from "../../../util/partition.js";
import { getYextUrlForPartition } from "../../../util/url.js";
import path from "node:path";
import { logWarning } from "../../../util/logError.js";

type Props = {
vite: ViteDevServer;
Expand Down Expand Up @@ -261,7 +262,7 @@ const createEntityPageListItems = (
const entities = localDataManifest.entity.get(templateName) || [];
return entities.reduce((entityAccumulator, { uid, entityId, slug }) => {
if (useProdURLs && !slug) {
console.error(
logWarning(
`No document.slug found for entityId "${entityId}", no link will be rendered in the index page.`
);
return entityAccumulator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ export default async function findMatchingStaticTemplate(
return findTemplateModuleInternal(
vite,
async (t) => {
if (!isStaticTemplateConfig(t.config)) {
return false;
}
const document = await getLocalDataForEntityOrStaticPage({
entityId: "",
locale,
featureName: t.config.name,
});
if (!isStaticTemplateConfig(t.config)) {
return false;
}
return slug === t.getPath({ document });
},
templateFilepaths
Expand Down
13 changes: 11 additions & 2 deletions packages/pages/src/dev/server/ssr/getLocalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import fs from "fs";
import { readdir } from "fs/promises";
import { findTemplateModuleInternal } from "./findTemplateModuleInternal.js";
import { ViteDevServer } from "vite";
import { validateGetPathValue } from "../../../common/src/template/internal/validateGetPathValue.js";
import { logWarning } from "../../../util/logError.js";

const LOCAL_DATA_PATH = "localData";

Expand Down Expand Up @@ -90,7 +92,7 @@ export const getLocalDataManifest = async (
templateFilepaths
);
if (!templateModuleInternal) {
console.error(
logWarning(
`Could not find a static template for feature "${featureName}", skipping.`
);
continue;
Expand All @@ -100,9 +102,16 @@ export const getLocalDataManifest = async (
.get(featureName)
?.locales.push(data.meta.locale);
} else {
const staticURL = templateModuleInternal.getPath({ document: data });
try {
validateGetPathValue(staticURL, templateModuleInternal.path);
} catch (e) {
logWarning(`${(e as Error).message}, skipping."`);
continue;
}
localDataManifest.static.set(featureName, {
featureName,
staticURL: templateModuleInternal.getPath({ document: data }),
staticURL,
locales: [data.meta.locale],
});
}
Expand Down
7 changes: 2 additions & 5 deletions packages/pages/src/dev/server/ssr/propsLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from "../../../common/src/template/types.js";
import { getRelativePrefixToRootFromPath } from "../../../common/src/template/paths.js";
import { TemplateModuleInternal } from "../../../common/src/template/internal/types.js";
import { validateGetPathValue } from "../../../common/src/template/internal/validateGetPathValue.js";

type PageLoaderValues = {
templateModuleInternal: TemplateModuleInternal<any, any>;
Expand Down Expand Up @@ -37,11 +38,7 @@ export const propsLoader = async ({
}

const path = getPath(templateProps);
if (!path) {
throw new Error(
`getPath does not return a valid string in template '${templateModuleInternal.path}'`
);
}
validateGetPathValue(path, templateModuleInternal.path);

return {
...templateProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TemplateModuleInternal,
} from "../../../../common/src/template/internal/types.js";
import { ProjectStructure } from "../../../../common/src/project/structure.js";
import { validateGetPathValue } from "../../../../common/src/template/internal/validateGetPathValue.js";

const pathToModule = new Map<string, TemplateModule<any, any>>();

Expand Down Expand Up @@ -118,11 +119,7 @@ export const generateResponses = async (
}

const path = templateModuleInternal.getPath(templateProps);
if (!path) {
throw new Error(
`getPath does not return a valid string in template '${templateModuleInternal.templateName}'`
);
}
validateGetPathValue(path, templateModuleInternal.templateName);

const templateRenderProps: TemplateRenderProps = {
...templateProps,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import fs from "fs";
import path from "path";
import esbuild from "esbuild";
import { importFromString } from "module-from-string";
import { Project, Node, SyntaxKind } from "ts-morph";
import { glob } from "glob";
import chalk from "chalk";
import os from "os";
import { ProjectStructure } from "../../../common/src/project/structure.js";
import { convertToPosixPath } from "../../../common/src/template/paths.js";

const TEMP_DIR = os.tmpdir();

/** Metadata for a serverless function. */
type FunctionMetadata = {
/** Name of the function. */
entrypoint: string;
};

/** ts-morph project for parsing function metadata */
const project = new Project();

/**
* Returns a mapping of file path (relative to the repo root) to the metadata
* for the function that is the default export of that file. If there is no default
Expand All @@ -34,6 +33,7 @@ const getFunctionMetadataMap = async (
)
.map((f) => path.resolve(f));

project.addSourceFilesAtPaths(filepaths);
const results = await Promise.allSettled(
filepaths.map(generateFunctionMetadata)
);
Expand Down Expand Up @@ -61,21 +61,39 @@ const getFunctionMetadataMap = async (
async function generateFunctionMetadata(
filepath: string
): Promise<[string, FunctionMetadata]> {
const buildResult = await esbuild.build({
entryPoints: [filepath],
outdir: TEMP_DIR,
write: false,
format: "esm",
bundle: true,
});
const importedFile = await importFromString(buildResult.outputFiles[0].text);
const defaultExportDeclaration = project
.getSourceFile(filepath)
?.getDefaultExportSymbol()
?.getDeclarations()[0];
const relativePath = path.relative(process.cwd(), filepath);

if (!importedFile.default) {
throw new Error(`${relativePath} does not contain a default export.`);
if (Node.isExportAssignment(defaultExportDeclaration)) {
const entrypoint = defaultExportDeclaration
.getChildrenOfKind(SyntaxKind.Identifier)[0]
?.getText();
if (!entrypoint) {
throw new Error(
`${relativePath} contains an unsupported default export assignment. ` +
"The default export must be a function, and it must be formatted " +
"as `export default foo;` for function `foo`."
);
}
return [relativePath, { entrypoint }];
} else if (Node.isFunctionDeclaration(defaultExportDeclaration)) {
const entrypoint = defaultExportDeclaration.getName();
if (!entrypoint) {
throw new Error(
`${relativePath} contains an unsupported default function declaration. ` +
"The default export function must be a named function, exported as " +
"`export default function foo(){}` for function `foo`"
);
}
return [relativePath, { entrypoint }];
}

return [relativePath, { entrypoint: importedFile.default.name }];
throw new Error(
`${relativePath} does not contain a properly formatted default export. ` +
"The default export must be named and declared either in the function declaration " +
"or in an `export default ...;` expression."
);
}

/** Generates a functionMetadata.json file from the functions directory. */
Expand Down
Loading

0 comments on commit 060efb6

Please sign in to comment.