/
githubmirror
/
angular-cli
Обзор
Документация
Войти
/
githubmirror
/
angular-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/angular_devkit/architect/testing/test-project-host.ts
165 строк
5 KB
Charles Lyding
refactor(@angular-devkit/core): deprecate stringToFileBuffer and fileBufferToString
08 май 2026, 15:52
08 май 2026, 15:52
fd336d3
Код
Авторство
О чём код?
/** * @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 { Path, PathFragment, basename, dirname, join, normalize, relative, virtualFs, } from '@angular-devkit/core'; import { NodeJsSyncHost } from '@angular-devkit/core/node'; import { Stats } from 'node:fs'; import { EMPTY, Observable, concatMap, delay, finalize, from, map, mergeMap, of, retry, tap, } from 'rxjs'; /** * @deprecated */ export class TestProjectHost extends NodeJsSyncHost { private _currentRoot: Path | null = null; private _scopedSyncHost: virtualFs.SyncDelegateHost<Stats> | null = null; constructor(protected _templateRoot: Path) { super(); } root(): Path { if (this._currentRoot === null) { throw new Error('TestProjectHost must be initialized before being used.'); } return this._currentRoot; } scopedSync(): virtualFs.SyncDelegateHost<Stats> { if (this._currentRoot === null || this._scopedSyncHost === null) { throw new Error('TestProjectHost must be initialized before being used.'); } return this._scopedSyncHost; } initialize(): Observable<void> { const recursiveList = (path: Path): Observable<Path> => this.list(path).pipe( // Emit each fragment individually. concatMap((fragments) => from(fragments)), // Join the path with fragment. map((fragment) => join(path, fragment)), // Emit directory content paths instead of the directory path. mergeMap((path) => this.isDirectory(path).pipe( concatMap((isDir) => (isDir ? recursiveList(path) : of(path))), ), ), ); // Find a unique folder that we can write to use as current root. return this.findUniqueFolderPath().pipe( // Save the path and create a scoped host for it. tap((newFolderPath) => { this._currentRoot = newFolderPath; this._scopedSyncHost = new virtualFs.SyncDelegateHost( new virtualFs.ScopedHost(this, this.root()), ); }), // List all files in root. concatMap(() => recursiveList(this._templateRoot)), // Copy them over to the current root. concatMap((from) => { const to = join(this.root(), relative(this._templateRoot, from)); return this.read(from).pipe(concatMap((buffer) => this.write(to, buffer))); }), map(() => {}), ); } restore(): Observable<void> { if (this._currentRoot === null) { return EMPTY; } // Delete the current root and clear the variables. // Wait 50ms and retry up to 10 times, to give time for file locks to clear. return this.exists(this.root()).pipe( delay(50), concatMap((exists) => (exists ? this.delete(this.root()) : EMPTY)), retry(10), finalize(() => { this._currentRoot = null; this._scopedSyncHost = null; }), ); } writeMultipleFiles(files: { [path: string]: string | ArrayBufferLike | Buffer }): void { Object.keys(files).forEach((fileName) => { let content = files[fileName]; if (typeof content == 'string') { content = new TextEncoder().encode(content).buffer; } else if (content instanceof Buffer) { content = content.buffer.slice(content.byteOffset, content.byteOffset + content.byteLength); } this.scopedSync().write(normalize(fileName), content as ArrayBufferLike); }); } replaceInFile(path: string, match: RegExp | string, replacement: string): void { const content = new TextDecoder().decode(this.scopedSync().read(normalize(path))); this.scopedSync().write( normalize(path), new TextEncoder().encode(content.replace(match, replacement)).buffer, ); } appendToFile(path: string, str: string): void { const content = new TextDecoder().decode(this.scopedSync().read(normalize(path))); this.scopedSync().write(normalize(path), new TextEncoder().encode(content.concat(str)).buffer); } fileMatchExists(dir: string, regex: RegExp): PathFragment | undefined { const [fileName] = this.scopedSync() .list(normalize(dir)) .filter((name) => name.match(regex)); return fileName || undefined; } copyFile(from: string, to: string): void { const content = this.scopedSync().read(normalize(from)); this.scopedSync().write(normalize(to), content); } private findUniqueFolderPath(): Observable<Path> { // 11 character alphanumeric string. const randomString = Math.random().toString(36).slice(2); const newFolderName = `test-project-host-${basename(this._templateRoot)}-${randomString}`; const newFolderPath = join(dirname(this._templateRoot), newFolderName); return this.exists(newFolderPath).pipe( concatMap((exists) => (exists ? this.findUniqueFolderPath() : of(newFolderPath))), ); } }