From 18ee249f5b47a99808d01eff8330b31839bf96b5 Mon Sep 17 00:00:00 2001 From: Andrii Shutov Date: Mon, 23 May 2022 13:46:19 -0400 Subject: [PATCH 1/3] feat: subtheme functionality with ability to pull connected components --- src/handlers/componentInstall.ts | 22 +++++++++++++++++++++- src/index.ts | 4 ++++ src/schemas/variant.json | 7 +++++++ src/types/_system.d.ts | 4 ++++ src/types/_variant.d.ts | 4 ++++ src/types/handlers.d.ts | 1 + 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/handlers/componentInstall.ts b/src/handlers/componentInstall.ts index 83b8edd..ee797d3 100644 --- a/src/handlers/componentInstall.ts +++ b/src/handlers/componentInstall.ts @@ -19,7 +19,7 @@ import catchLater from '../util/catchLater'; */ export default async function componentInstall( name: string, - { force, all }: InstallComponentHandlerOptions + { force, all, subtheme }: InstallComponentHandlerOptions ): Promise { const emulsifyConfig = await getEmulsifyConfig(); if (!emulsifyConfig) { @@ -114,6 +114,26 @@ export default async function componentInstall( ]) ); } + // Pull subtheme marked modules. + else if (subtheme && subtheme.length > 0) { + const componentsWithDependencies = variantConf.components.filter( + (component) => component.subtheme?.includes(subtheme) + ); + buildComponentDependencyList(variantConf.components, name); + componentsWithDependencies.forEach((componentName) => { + components.push([ + componentName, + catchLater( + installComponentFromCache( + systemConf, + variantConf, + componentName, + force + ) + ), + ]); + }); + } // If there is only one component to install, add one single promise for the single component. else { const componentsWithDependencies = buildComponentDependencyList( diff --git a/src/index.ts b/src/index.ts index 89a3c21..304e0e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -90,6 +90,10 @@ component '-a --all', 'Use this to install all available components, rather than specifying a single component to install' ) + .option( + '-s --subtheme', + 'This option use name as subtheme to pull group of components from full list of the components' + ) .alias('i') .description( "Install a component from within the current project's system and variant" diff --git a/src/schemas/variant.json b/src/schemas/variant.json index b03a8c2..e0c2b97 100644 --- a/src/schemas/variant.json +++ b/src/schemas/variant.json @@ -56,6 +56,13 @@ "items": { "type": "string" } + }, + "subtheme": { + "type": "array", + "description": "List of all subtheme to which this component belonning to and should be installed as part of subtheme", + "items": { + "type": "string" + } } }, "additionalProperties": false, diff --git a/src/types/_system.d.ts b/src/types/_system.d.ts index c552076..8e39cfd 100644 --- a/src/types/_system.d.ts +++ b/src/types/_system.d.ts @@ -76,6 +76,10 @@ export interface EmulsifySystem { * Array containing list of all components from which depends current conponent */ dependency?: string[]; + /** + * List of all subtheme to which this component belonning to and should be installed as part of subtheme + */ + subtheme?: string[]; }[]; /** * Array containing objects that define general directories. These directories should contain files and assets that do not belong in a structure folder (such as font files) diff --git a/src/types/_variant.d.ts b/src/types/_variant.d.ts index 3103921..b73b158 100644 --- a/src/types/_variant.d.ts +++ b/src/types/_variant.d.ts @@ -46,6 +46,10 @@ export type Components = { * Array containing list of all components from which depends current conponent */ dependency?: string[]; + /** + * List of all subtheme to which this component belonning to and should be installed as part of subtheme + */ + subtheme?: string[]; }[]; /** * Array containing objects that define general directories. These directories should contain files and assets that do not belong in a structure folder (such as font files) diff --git a/src/types/handlers.d.ts b/src/types/handlers.d.ts index d83a6c0..09f9fbe 100644 --- a/src/types/handlers.d.ts +++ b/src/types/handlers.d.ts @@ -19,5 +19,6 @@ declare module '@emulsify-cli/handlers' { export type InstallComponentHandlerOptions = { force?: boolean; all?: boolean; + subtheme: string; }; } From b0dbac4eeef99bc80d3add1ed2dc991a823153bb Mon Sep 17 00:00:00 2001 From: Andrii Shutov Date: Sat, 28 May 2022 09:06:25 -0400 Subject: [PATCH 2/3] feat: subtheme selection with dependency component list build --- src/handlers/componentInstall.ts | 17 +++++---- src/index.ts | 2 +- .../buildComponentDependencyList.test.ts | 14 +++++-- .../project/buildComponentDependencyList.ts | 38 ++++++++++--------- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/handlers/componentInstall.ts b/src/handlers/componentInstall.ts index ee797d3..1a942e6 100644 --- a/src/handlers/componentInstall.ts +++ b/src/handlers/componentInstall.ts @@ -89,10 +89,10 @@ export default async function componentInstall( ); } - if (!name && !all) { + if (!name && !all && !subtheme) { return log( 'error', - 'Please specify a component to install, or pass --all to install all available components.' + 'Please specify a component to install, or subtheme name through option --subtheme, or pass --all to install all available components.' ); } @@ -115,11 +115,14 @@ export default async function componentInstall( ); } // Pull subtheme marked modules. - else if (subtheme && subtheme.length > 0) { - const componentsWithDependencies = variantConf.components.filter( - (component) => component.subtheme?.includes(subtheme) + else if (subtheme) { + const parentComponents = variantConf.components + .filter((component) => component.subtheme?.includes(subtheme)) + .map((component) => component.name); + const componentsWithDependencies = buildComponentDependencyList( + variantConf.components, + parentComponents ); - buildComponentDependencyList(variantConf.components, name); componentsWithDependencies.forEach((componentName) => { components.push([ componentName, @@ -138,7 +141,7 @@ export default async function componentInstall( else { const componentsWithDependencies = buildComponentDependencyList( variantConf.components, - name + [name] ); componentsWithDependencies.forEach((componentName) => { components.push([ diff --git a/src/index.ts b/src/index.ts index 304e0e1..763f346 100644 --- a/src/index.ts +++ b/src/index.ts @@ -91,7 +91,7 @@ component 'Use this to install all available components, rather than specifying a single component to install' ) .option( - '-s --subtheme', + '-s --subtheme ', 'This option use name as subtheme to pull group of components from full list of the components' ) .alias('i') diff --git a/src/util/project/buildComponentDependencyList.test.ts b/src/util/project/buildComponentDependencyList.test.ts index 37d963a..b5ab8bb 100644 --- a/src/util/project/buildComponentDependencyList.test.ts +++ b/src/util/project/buildComponentDependencyList.test.ts @@ -36,17 +36,17 @@ describe('buildComponentDependencyList', () => { ] as Components; it('Build list of components without dependency', () => { - expect(buildComponentDependencyList(components, 'buttons')).toEqual([ + expect(buildComponentDependencyList(components, ['buttons'])).toEqual([ 'buttons', ]); }); it('Build all components dependency for not existing component', () => { - expect(buildComponentDependencyList(components, 'test')).toEqual([]); + expect(buildComponentDependencyList(components, ['test'])).toEqual([]); }); it('Build all components dependency tree returning flat list without duplicates', () => { - expect(buildComponentDependencyList(components, 'card')).toEqual([ + expect(buildComponentDependencyList(components, ['card'])).toEqual([ 'card', 'images', 'text', @@ -56,11 +56,17 @@ describe('buildComponentDependencyList', () => { }); it('Build all components dependency tree with hierarchical dependency', () => { - expect(buildComponentDependencyList(components, 'menus')).toEqual([ + expect(buildComponentDependencyList(components, ['menus'])).toEqual([ 'menus', 'images', 'text', 'links', ]); }); + + it('Build all components dependency tree for 2 components', () => { + expect(buildComponentDependencyList(components, ['menus', 'card'])).toEqual( + ['menus', 'card', 'images', 'text', 'links', 'buttons'] + ); + }); }); diff --git a/src/util/project/buildComponentDependencyList.ts b/src/util/project/buildComponentDependencyList.ts index 0e775c4..dddf669 100644 --- a/src/util/project/buildComponentDependencyList.ts +++ b/src/util/project/buildComponentDependencyList.ts @@ -2,26 +2,28 @@ import type { Components } from '@emulsify-cli/config'; export default function buildComponentDependencyList( components: Components, - name: string + componentsList: string[] ) { - const rootComponent = components.filter( - (component) => component.name == name + const rootComponents = components.filter((component) => + componentsList.includes(component.name) ); - if (rootComponent.length == 0) return []; - let finalList = [name]; - if (rootComponent.length > 0) { - const list = rootComponent[0].dependency as string[]; - if (list && list.length > 0) { - list.forEach((componentName: string) => { - finalList = [ - ...new Set( - finalList.concat( - buildComponentDependencyList(components, componentName) - ) - ), - ]; - }); - } + if (rootComponents.length == 0) return []; + let finalList = [...componentsList]; + if (rootComponents.length > 0) { + rootComponents.forEach((rootComponent) => { + const list = rootComponent.dependency as string[]; + if (list && list.length > 0) { + list.forEach((componentName: string) => { + finalList = [ + ...new Set( + finalList.concat( + buildComponentDependencyList(components, [componentName]) + ) + ), + ]; + }); + } + }); } return finalList; } From 24eb80d0d9c42604cd854090a714855d8fb697a3 Mon Sep 17 00:00:00 2001 From: Andrii Shutov Date: Sat, 30 Jul 2022 07:39:51 -0400 Subject: [PATCH 3/3] feat: change confusing subtheme term into component set --- src/handlers/componentInstall.ts | 12 ++++++------ src/index.ts | 4 ++-- src/schemas/variant.json | 4 ++-- src/types/_system.d.ts | 4 ++-- src/types/_variant.d.ts | 4 ++-- src/types/handlers.d.ts | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/handlers/componentInstall.ts b/src/handlers/componentInstall.ts index 1a942e6..371c254 100644 --- a/src/handlers/componentInstall.ts +++ b/src/handlers/componentInstall.ts @@ -19,7 +19,7 @@ import catchLater from '../util/catchLater'; */ export default async function componentInstall( name: string, - { force, all, subtheme }: InstallComponentHandlerOptions + { force, all, componentSet }: InstallComponentHandlerOptions ): Promise { const emulsifyConfig = await getEmulsifyConfig(); if (!emulsifyConfig) { @@ -89,10 +89,10 @@ export default async function componentInstall( ); } - if (!name && !all && !subtheme) { + if (!name && !all && !componentSet) { return log( 'error', - 'Please specify a component to install, or subtheme name through option --subtheme, or pass --all to install all available components.' + 'Please specify a component to install, or library name through option --component-set, or pass --all to install all available components.' ); } @@ -114,10 +114,10 @@ export default async function componentInstall( ]) ); } - // Pull subtheme marked modules. - else if (subtheme) { + // Pull library marked modules. + else if (componentSet) { const parentComponents = variantConf.components - .filter((component) => component.subtheme?.includes(subtheme)) + .filter((component) => component.componentSet?.includes(componentSet)) .map((component) => component.name); const componentsWithDependencies = buildComponentDependencyList( variantConf.components, diff --git a/src/index.ts b/src/index.ts index 763f346..2fc85ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -91,8 +91,8 @@ component 'Use this to install all available components, rather than specifying a single component to install' ) .option( - '-s --subtheme ', - 'This option use name as subtheme to pull group of components from full list of the components' + '-cs --component-set ', + 'Use this to Install a pre-defined set of related components from your component library' ) .alias('i') .description( diff --git a/src/schemas/variant.json b/src/schemas/variant.json index e0c2b97..21a6d08 100644 --- a/src/schemas/variant.json +++ b/src/schemas/variant.json @@ -57,9 +57,9 @@ "type": "string" } }, - "subtheme": { + "componentSet": { "type": "array", - "description": "List of all subtheme to which this component belonning to and should be installed as part of subtheme", + "description": "List of all component library to which this component belonning to and should be installed as part of library", "items": { "type": "string" } diff --git a/src/types/_system.d.ts b/src/types/_system.d.ts index 8e39cfd..9e47a59 100644 --- a/src/types/_system.d.ts +++ b/src/types/_system.d.ts @@ -77,9 +77,9 @@ export interface EmulsifySystem { */ dependency?: string[]; /** - * List of all subtheme to which this component belonning to and should be installed as part of subtheme + * List of all component library to which this component belonning to and should be installed as part of library */ - subtheme?: string[]; + componentSet?: string[]; }[]; /** * Array containing objects that define general directories. These directories should contain files and assets that do not belong in a structure folder (such as font files) diff --git a/src/types/_variant.d.ts b/src/types/_variant.d.ts index b73b158..ec48d35 100644 --- a/src/types/_variant.d.ts +++ b/src/types/_variant.d.ts @@ -47,9 +47,9 @@ export type Components = { */ dependency?: string[]; /** - * List of all subtheme to which this component belonning to and should be installed as part of subtheme + * List of all component library to which this component belonning to and should be installed as part of library */ - subtheme?: string[]; + componentSet?: string[]; }[]; /** * Array containing objects that define general directories. These directories should contain files and assets that do not belong in a structure folder (such as font files) diff --git a/src/types/handlers.d.ts b/src/types/handlers.d.ts index 09f9fbe..5d866ba 100644 --- a/src/types/handlers.d.ts +++ b/src/types/handlers.d.ts @@ -19,6 +19,6 @@ declare module '@emulsify-cli/handlers' { export type InstallComponentHandlerOptions = { force?: boolean; all?: boolean; - subtheme: string; + componentSet: string; }; }