angular/adev/prerender/tutorials/utils/webcontainers.ts
2023-11-06 11:15:02 -08:00

91 lines
2.4 KiB
TypeScript

/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {basename, dirname, extname} from 'path';
import {DirectoryNode, FileNode, FileSystemTree} from '@webcontainer/api';
import {ANSWER_DIRECTORY, CONFIG_FILE} from './node-constants';
import {FileAndContent, FileAndContentRecord} from '../tutorials-types';
/**
* Create a WebContainer's FileSystemTree from a list of files and its contents
*/
export function getFileSystemTree(files: string[], filesContents: FileAndContentRecord) {
const fileSystemTree: FileSystemTree = {};
for (let filepath of files) {
const dir = dirname(filepath);
const filename = basename(filepath);
if (dir === '.') {
const fileNode: FileNode = {file: {contents: filesContents[filepath]}};
fileSystemTree[filename] = fileNode;
} else {
const dirParts = dir.split('/');
buildFileSystemTree(fileSystemTree, dirParts, filename, filesContents[filepath]);
}
}
return fileSystemTree;
}
/**
* Builds a WebContainer's file system tree object recursively, mutating the
* `fileSystemTree` parameter.
*
* @see https://webcontainers.io/api#filesystemtree
*/
export function buildFileSystemTree(
fileSystemTree: FileSystemTree,
fileDirectories: string[],
filename: FileAndContent['path'],
fileContents: FileAndContent['content'],
): void {
if (fileDirectories.length === 1) {
const directory = fileDirectories[0];
const fileNode: FileNode = {file: {contents: fileContents}};
fileSystemTree[directory] = {
...fileSystemTree[directory],
directory: {
...(fileSystemTree[directory]
? (fileSystemTree[directory] as DirectoryNode).directory
: undefined),
[filename]: fileNode,
},
};
return;
}
const nextDirectory = fileDirectories.shift();
if (!nextDirectory) return;
if (!fileSystemTree[nextDirectory]) {
fileSystemTree[nextDirectory] = {directory: {}};
}
buildFileSystemTree(
(fileSystemTree[nextDirectory] as DirectoryNode).directory,
fileDirectories,
filename,
fileContents,
);
}
export function shouldUseFileInWebContainer(filename: string) {
return (
basename(filename) !== CONFIG_FILE &&
['.md', '.png', '.jpg'].includes(extname(filename)) === false &&
!filename.includes(`${ANSWER_DIRECTORY}/`)
);
}