angular/adev/shared-docs/pipeline/tutorials/metadata.ts
Alan Agius 4875bc3073 fix(docs-infra): update getAnswerFiles to ensure compatibility with non-POSIX file systems (#57970)
This update modifies the `getAnswerFiles` function to support file systems that do not adhere to POSIX standards.

Prior to this change this method will always fail with the below:

```
Error: Invalid state: could not find start of answers path
```

PR Close #57970
2024-09-26 14:29:45 -07:00

69 lines
2 KiB
TypeScript

import {join, dirname} from 'path';
import {glob} from 'fast-glob';
import {
FileAndContentRecord,
PackageJson,
TutorialConfig,
TutorialMetadata,
} from '../../interfaces';
import {getFileContents} from './utils';
/** Generate the metadata.json content for a provided tutorial config. */
export async function generateMetadata(
path: string,
config: TutorialConfig,
files: FileAndContentRecord,
): Promise<TutorialMetadata> {
const tutorialFiles: FileAndContentRecord = {};
const {dependencies, devDependencies} = JSON.parse(<string>files['package.json']) as PackageJson;
config.openFiles?.forEach((file) => (tutorialFiles[file] = files[file]));
return {
type: config.type,
openFiles: config.openFiles || [],
allFiles: Object.keys(files),
tutorialFiles,
answerFiles: await getAnswerFiles(path, config, files),
hiddenFiles: config.openFiles
? Object.keys(files).filter((filename) => !config.openFiles!.includes(filename))
: [],
dependencies: {
...dependencies,
...devDependencies,
},
};
}
/** Generate the answer files for the metadata.json. */
async function getAnswerFiles(
path: string,
config: TutorialConfig,
files: FileAndContentRecord,
): Promise<FileAndContentRecord> {
const answerFiles: FileAndContentRecord = {};
const answerPrefix = /answer[\\/]/;
if (config.answerSrc) {
const answersDir = join(path, config.answerSrc);
const answerFilePaths = await glob('**/*', {
cwd: answersDir,
onlyFiles: true,
absolute: false,
});
for (const answerFile of answerFilePaths) {
// We use the absolute file in order to read the content, but the key
// needs to be a relative path within the project.
answerFiles[answerFile] = getFileContents(join(answersDir, answerFile));
}
} else {
for (const file of Object.keys(files)) {
if (answerPrefix.test(file)) {
answerFiles[file.replace(answerPrefix, '')] = files[file];
}
}
}
return answerFiles;
}