From 900f7ba5430f118cdf52242554c6506ef5906262 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 22 Jul 2022 16:17:50 -0400 Subject: [PATCH] refactor(@angular-devkit/core): add allowed extensions options to JSON workspace reader Adjust the internal `readJsonWorkspace` to allow for future generalization of the allowed unprefixed extension fields for the workspace and project objects. Custom fields that start with a one to three lowercase letter prefix are still allowed in both locations. (cherry picked from commit fa0404daf4c56277e4b083b2de8448d75cb532a5) --- .../core/src/workspace/json/reader.ts | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/angular_devkit/core/src/workspace/json/reader.ts b/packages/angular_devkit/core/src/workspace/json/reader.ts index 50e5f0709c04..fa54e67ed004 100644 --- a/packages/angular_devkit/core/src/workspace/json/reader.ts +++ b/packages/angular_devkit/core/src/workspace/json/reader.ts @@ -20,17 +20,33 @@ import { WorkspaceHost } from '../host'; import { JsonWorkspaceMetadata, JsonWorkspaceSymbol } from './metadata'; import { createVirtualAstObject } from './utilities'; +const ANGULAR_WORKSPACE_EXTENSIONS = Object.freeze([ + 'cli', + 'defaultProject', + 'newProjectRoot', + 'schematics', +]); +const ANGULAR_PROJECT_EXTENSIONS = Object.freeze(['cli', 'schematics', 'projectType', 'i18n']); + interface ParserContext { readonly host: WorkspaceHost; readonly metadata: JsonWorkspaceMetadata; readonly trackChanges: boolean; + readonly unprefixedWorkspaceExtensions: ReadonlySet; + readonly unprefixedProjectExtensions: ReadonlySet; error(message: string, node: JsonValue): void; warn(message: string, node: JsonValue): void; } +export interface JsonWorkspaceOptions { + allowedProjectExtensions?: string[]; + allowedWorkspaceExtensions?: string[]; +} + export async function readJsonWorkspace( path: string, host: WorkspaceHost, + options: JsonWorkspaceOptions = {}, ): Promise { const raw = await host.readFile(path); if (raw === undefined) { @@ -56,6 +72,14 @@ export async function readJsonWorkspace( host, metadata: new JsonWorkspaceMetadata(path, ast, raw), trackChanges: true, + unprefixedWorkspaceExtensions: new Set([ + ...ANGULAR_WORKSPACE_EXTENSIONS, + ...(options.allowedWorkspaceExtensions ?? []), + ]), + unprefixedProjectExtensions: new Set([ + ...ANGULAR_PROJECT_EXTENSIONS, + ...(options.allowedProjectExtensions ?? []), + ]), error(message, _node) { // TODO: Diagnostic reporting support throw new Error(message); @@ -72,10 +96,6 @@ export async function readJsonWorkspace( return workspace; } -const specialWorkspaceExtensions = ['cli', 'defaultProject', 'newProjectRoot', 'schematics']; - -const specialProjectExtensions = ['cli', 'schematics', 'projectType', 'i18n']; - function parseWorkspace(workspaceNode: Node, context: ParserContext): WorkspaceDefinition { const jsonMetadata = context.metadata; let projects; @@ -99,7 +119,7 @@ function parseWorkspace(workspaceNode: Node, context: ParserContext): WorkspaceD projects = parseProjectsObject(nodes, context); } else { - if (!specialWorkspaceExtensions.includes(name) && !/^[a-z]{1,3}-.*/.test(name)) { + if (!context.unprefixedWorkspaceExtensions.has(name) && !/^[a-z]{1,3}-.*/.test(name)) { context.warn(`Project extension with invalid name (${name}) found.`, name); } if (extensions) { @@ -201,7 +221,7 @@ function parseProject( } break; default: - if (!specialProjectExtensions.includes(name) && !/^[a-z]{1,3}-.*/.test(name)) { + if (!context.unprefixedProjectExtensions.has(name) && !/^[a-z]{1,3}-.*/.test(name)) { context.warn(`Project extension with invalid name (${name}) found.`, name); } if (extensions) {