diff --git a/packages/uxpin-merge-cli/.gitignore b/packages/uxpin-merge-cli/.gitignore index 8dde66fbc..c674e86d3 100644 --- a/packages/uxpin-merge-cli/.gitignore +++ b/packages/uxpin-merge-cli/.gitignore @@ -14,6 +14,7 @@ !/test/resources/repos/.gitkeep /reports/* !/reports/.gitkeep +/tmp/** !/test/resources/configs/*.js !/test/resources/components/**/*.js diff --git a/packages/uxpin-merge-cli/bin/uxpin-integrate-package b/packages/uxpin-merge-cli/bin/uxpin-integrate-package new file mode 100755 index 000000000..f19f2e3da --- /dev/null +++ b/packages/uxpin-merge-cli/bin/uxpin-integrate-package @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +const program = require('commander'); +const cp = require('child_process'); +const path = require('path'); +const fs = require('fs-extra'); +const pMapSeries = require("p-map-series"); + +program + .option('--token ', 'Library token') + .option('--packages ', 'NPM Package name') + .option('--components ', 'List of imported components and categories') + .option('--css-resources ', 'Urls or paths to CSS Styles') + .option('--npmrc ', 'Content of .npmrc') + .option('--uxpin-domain ', 'Can be used to set a UXPin private cloud domain. Default: `uxpin.com`'); + +program.parse(process.argv); + +const uxpinMergePath = path.resolve(__dirname, './uxpin-merge'); +const appPath = path.resolve(process.cwd(), program.token); +const commands = [ + spawn.bind(spawn, [ + 'create-app', + `--packages=${program.packages}`, + program.npmrc ? `--npmrc=${program.npmrc}` : '', + `--app-name=${program.token}`, + `--components=${program.components}` + ].filter(Boolean)), + spawn.bind(spawn, [ + 'push', + '--webpack-config=webpack.config.js', + `--disable-version-control`, + program.uxpinDomain ? `--uxpin-domain=${program.uxpinDomain}` : '', + `--token=${program.token}`, + program.cssResources ? `--css-resources=${program.cssResources}` : '' + ].filter(Boolean), { cwd: appPath }) +]; + +async function spawn(args, options = {}) { + return new Promise((resolve, reject) => { + const child = cp.spawn(uxpinMergePath, args, options); + + child.stdout.on('data', (data) => { + console.log(String(data)); + }); + + child.stderr.on('data', function (data) { + console.log(String(data)); + }); + + child.on('close', function (code) { + if (code !== 0) { + reject(`Exited with code ${code}`); + return; + } + resolve(); + }); + }); +} + +async function executeCommands() { + let exitCode = 0; + try { + await pMapSeries(commands, (command) => command()); + } catch (e) { + console.error(e); + exitCode = 1; + } finally { + if (fs.pathExistsSync(appPath)) { + fs.removeSync(appPath); + } + process.exit(exitCode); + } +} + +executeCommands(); diff --git a/packages/uxpin-merge-cli/bin/uxpin-merge b/packages/uxpin-merge-cli/bin/uxpin-merge index b9484986f..19f9e1a91 100755 --- a/packages/uxpin-merge-cli/bin/uxpin-merge +++ b/packages/uxpin-merge-cli/bin/uxpin-merge @@ -31,6 +31,15 @@ program .option('--component-path ', 'path to a component path, relative to the current working directory') .action(() => {}); +program + .command(Command.CREATE_APP) + .description('Create app based on package name') + .option('--app-name ', 'App name') + .option('--components ', 'list of imports statements') + .option('--packages ', 'names and versions of npm packages') + .option('--npmrc ', 'Content of .npmrc') + .action(() => {}); + program .command(Command.PUSH) @@ -42,6 +51,8 @@ program .option('--token ', 'auth token for the library. Default: `UXPIN_AUTH_TOKEN` env variable') .option('--branch ', 'branch to use when uploading. Default: master') .option('--tag ', 'tag this push with a specific name or number. The provided name/number is unique and can be used only once.') + .option('--css-resources ', 'Attach external css styles to pushed js bundle') + .option('--disable-version-control', 'Turn off version control') .option('--force', 'ignore the last commit saved in uxpin db and push the library without checking history. It could break old prototypes if components were created before 07.2021') .action(() => {}); diff --git a/packages/uxpin-merge-cli/package.json b/packages/uxpin-merge-cli/package.json index 141e11294..d770cc03b 100644 --- a/packages/uxpin-merge-cli/package.json +++ b/packages/uxpin-merge-cli/package.json @@ -9,6 +9,7 @@ }, "main": "src/index.js", "bin": { + "uxpin-integrate-package": "bin/uxpin-integrate-package", "uxpin-merge": "bin/uxpin-merge" }, "typings": "src/types.d.ts", diff --git a/packages/uxpin-merge-cli/src/program/args/ProgramArgs.ts b/packages/uxpin-merge-cli/src/program/args/ProgramArgs.ts index 92d01d470..a043f16ca 100644 --- a/packages/uxpin-merge-cli/src/program/args/ProgramArgs.ts +++ b/packages/uxpin-merge-cli/src/program/args/ProgramArgs.ts @@ -17,7 +17,10 @@ export interface ConfigEnabledProgramArgs { uxpinDomain?: string; } +export type WatchProgramArgs = ExperimentProgramArgs; + export type ProgramArgs = + | CreateAppProgramArgs | DumpProgramArgs | ExperimentProgramArgs | InitProgramArgs @@ -66,6 +69,8 @@ export interface PushProgramArgs { // https://github.com/UXPin/uxpin-merge-tools/issues/206 branch?: string; tag?: string; + disableVersionControl?: boolean; + cssResources?: string; } export interface DeleteVersionArgs { @@ -85,6 +90,14 @@ export interface GeneratePresetsProgramArgs { config?: string; } +export interface CreateAppProgramArgs { + command: Command.CREATE_APP; + components?: string; + packages: string; + appName: string; + npmrc?: string; +} + export interface ServerProgramArgs { command: Command.SERVER; cwd: string; diff --git a/packages/uxpin-merge-cli/src/program/args/getProgramArgs.ts b/packages/uxpin-merge-cli/src/program/args/getProgramArgs.ts index 54eca02a0..c1073aa15 100644 --- a/packages/uxpin-merge-cli/src/program/args/getProgramArgs.ts +++ b/packages/uxpin-merge-cli/src/program/args/getProgramArgs.ts @@ -13,6 +13,12 @@ const defaultArgs: { [key in Command]: ProgramArgs } = { config: DEFAULT_CONFIG_PATH, cwd: process.cwd(), }, + [Command.CREATE_APP]: { + appName: 'react-app', + command: Command.CREATE_APP, + npmrc: '', + packages: '', + }, [Command.DUMP]: { command: Command.DUMP, config: DEFAULT_CONFIG_PATH, @@ -63,10 +69,16 @@ const defaultArgs: { [key in Command]: ProgramArgs } = { export function getProgramArgs(program: RawProgramArgs): ProgramArgs { const command: Command = getCommand(program); const cliArgs: ProgramArgs = getCLIArgs(program, command); - const configArgs: ConfigEnabledProgramArgs = pickConfigArgs( - getConfigPath({ ...defaultArgs[command], ...cliArgs }), - command - ); + + if (command === Command.CREATE_APP) { + return { + ...defaultArgs[command], + ...cliArgs, + } as ProgramArgs; + } + + const { cwd = '', config = undefined } = { ...defaultArgs[command], ...cliArgs }; + const configArgs: ConfigEnabledProgramArgs = pickConfigArgs(getConfigPath({ cwd, config }), command); return { ...defaultArgs[command], ...configArgs, diff --git a/packages/uxpin-merge-cli/src/program/args/providers/paths/__tests__/getConfigPath.test.ts b/packages/uxpin-merge-cli/src/program/args/providers/paths/__tests__/getConfigPath.test.ts index 65d89f91d..07d4480ca 100644 --- a/packages/uxpin-merge-cli/src/program/args/providers/paths/__tests__/getConfigPath.test.ts +++ b/packages/uxpin-merge-cli/src/program/args/providers/paths/__tests__/getConfigPath.test.ts @@ -11,7 +11,7 @@ describe('getConfigPath', () => { }; // then - expect(getConfigPath(args as ProgramArgs)).toEqual('/project/root/directory/file.js'); + expect(getConfigPath({ cwd: args.cwd, config: args.config })).toEqual('/project/root/directory/file.js'); }); }); @@ -23,6 +23,6 @@ describe('getConfigPath', () => { }; // then - expect(getConfigPath(args as ProgramArgs)).toEqual('/absolute/directory/file.js'); + expect(getConfigPath({ cwd: args.cwd, config: args.config })).toEqual('/absolute/directory/file.js'); }); }); diff --git a/packages/uxpin-merge-cli/src/program/args/providers/paths/getConfigPath.ts b/packages/uxpin-merge-cli/src/program/args/providers/paths/getConfigPath.ts index 37eb9d5e5..d7ba2aabc 100644 --- a/packages/uxpin-merge-cli/src/program/args/providers/paths/getConfigPath.ts +++ b/packages/uxpin-merge-cli/src/program/args/providers/paths/getConfigPath.ts @@ -1,6 +1,8 @@ import { resolve } from 'path'; -import { ProgramArgs } from '../../ProgramArgs'; -export function getConfigPath({ cwd, config }: ProgramArgs): string { +export function getConfigPath({ cwd, config }: { cwd: string | undefined; config: string | undefined }): string { + if (!cwd) { + return ''; + } return resolve(cwd, config || ''); } diff --git a/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectPaths.ts b/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectPaths.ts index 2516590a9..7c8b977b2 100644 --- a/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectPaths.ts +++ b/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectPaths.ts @@ -1,11 +1,12 @@ import { ProjectPaths } from '../../../../steps/discovery/paths/ProjectPaths'; -import { ProgramArgs } from '../../ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../ProgramArgs'; import { getConfigPath } from './getConfigPath'; import { getProjectRoot } from './getProjectRoot'; -export function getProjectPaths(programArgs: ProgramArgs): ProjectPaths { +export function getProjectPaths(programArgs: Exclude): ProjectPaths { + const { cwd, config } = programArgs; return { - configPath: getConfigPath(programArgs), + configPath: getConfigPath({ cwd, config }), projectRoot: getProjectRoot(programArgs), }; } diff --git a/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectRoot.ts b/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectRoot.ts index 83b2983ca..62d2f6a0a 100644 --- a/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectRoot.ts +++ b/packages/uxpin-merge-cli/src/program/args/providers/paths/getProjectRoot.ts @@ -1,7 +1,7 @@ import { isAbsolute, resolve } from 'path'; -import { ProgramArgs } from '../../ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../ProgramArgs'; -export function getProjectRoot({ cwd }: Pick): string { +export function getProjectRoot({ cwd }: Pick, 'cwd'>): string { if (isAbsolute(cwd)) { return cwd; } diff --git a/packages/uxpin-merge-cli/src/program/args/providers/paths/getTempDirPath.ts b/packages/uxpin-merge-cli/src/program/args/providers/paths/getTempDirPath.ts index 4b3045ae7..f98e16ba2 100644 --- a/packages/uxpin-merge-cli/src/program/args/providers/paths/getTempDirPath.ts +++ b/packages/uxpin-merge-cli/src/program/args/providers/paths/getTempDirPath.ts @@ -1,8 +1,8 @@ import { join } from 'path'; import { TEMP_DIR_PATH } from '../../../../steps/building/config/getConfig'; -import { ProgramArgs } from '../../ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../ProgramArgs'; import { getProjectRoot } from './getProjectRoot'; -export function getTempDirPath(args: Pick): string { +export function getTempDirPath(args: Pick, 'cwd'>): string { return join(getProjectRoot(args), TEMP_DIR_PATH); } diff --git a/packages/uxpin-merge-cli/src/program/command/Command.ts b/packages/uxpin-merge-cli/src/program/command/Command.ts index 11f49e34e..bc5911019 100644 --- a/packages/uxpin-merge-cli/src/program/command/Command.ts +++ b/packages/uxpin-merge-cli/src/program/command/Command.ts @@ -2,6 +2,7 @@ export enum Command { DUMP = 'dump', EXPERIMENT = 'experiment', INIT = 'init', + CREATE_APP = 'create-app', GENERATE_PRESETS = 'generate-presets', PUSH = 'push', DELETE_VERSION = 'delete-version', diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/createApp.ts b/packages/uxpin-merge-cli/src/program/command/create_app/createApp.ts new file mode 100644 index 000000000..93d8ed021 --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/createApp.ts @@ -0,0 +1,23 @@ +import { CreateAppProgramArgs } from '../../args/ProgramArgs'; +import { Step } from '../Step'; +import { createAppDirectory } from './steps/createAppDirectory'; +import { createComponentsFiles } from './steps/createComponentsFiles'; +import { createNpmrcFile } from './steps/createNpmrcFile'; +import { createPackageJsonFile } from './steps/createPackageJsonFile'; +import { createUXPinConfigFile } from './steps/createUXPinConfigFile'; +import { createWebpackConfigFile } from './steps/createWebpackConfigFile'; +import { installPackages } from './steps/installPackages'; +import { installPeerDependencies } from './steps/installPeerDependencies'; + +export function createApp(args: CreateAppProgramArgs): Step[] { + return [ + createAppDirectory(args), + createPackageJsonFile(args), + createNpmrcFile(args), + installPackages(args), + installPeerDependencies(args), + createComponentsFiles(args), + createWebpackConfigFile(args), + createUXPinConfigFile(args), + ]; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createAppDirectory.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createAppDirectory.ts new file mode 100644 index 000000000..7778d1662 --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createAppDirectory.ts @@ -0,0 +1,29 @@ +import { mkdir, pathExists } from 'fs-extra'; +import { resolve } from 'path'; +import { printLine, printWarning } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; + +export let APP_DIRECTORY = ''; + +export function createAppDirectory(args: CreateAppProgramArgs): Step { + return { exec: thunkCreateAppDirectory(args), shouldRun: true }; +} + +export function thunkCreateAppDirectory(args: CreateAppProgramArgs): () => Promise { + return async () => { + if (!args.appName) { + throw new Error('🛑 Invalid app name'); + } + + const appDirectory = resolve(process.cwd(), args.appName); + APP_DIRECTORY = appDirectory; + if (!(await pathExists(appDirectory))) { + await mkdir(appDirectory); + printLine(`✅ App directory "${appDirectory}" created`, { color: PrintColor.GREEN }); + } else { + printWarning(`👉 App directory "${appDirectory}" exists`); + } + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createComponentsFiles.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createComponentsFiles.ts new file mode 100644 index 000000000..71aeab5e8 --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createComponentsFiles.ts @@ -0,0 +1,66 @@ +import { mkdir, pathExists } from 'fs-extra'; +import pMapSeries = require('p-map-series'); +import { resolve } from 'path'; +import { printLine } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { writeToFile } from '../../../../utils/fs/writeToFile'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +export function createComponentsFiles(args: CreateAppProgramArgs): Step { + return { exec: thunkCreateComponentsFiles(args), shouldRun: true }; +} + +const SUFFIX = 'El'; + +export const components: Array<{ name: string; include: string[] }> = []; + +function getComponentContent(name: string, packageName: string): string { + const normalizedName: string = name.replace(/\./g, ''); + return [ + `import React from 'react';`, + `import PropTypes from 'prop-types'`, + `const packageData = require('${packageName}') || {};`, + `let ${normalizedName}${SUFFIX} = null;`, + `try {`, + `${normalizedName}${SUFFIX} = packageData.${name} ? packageData.${name} : packageData.default;`, + '} catch (e) {}', + `const ${normalizedName} = (props) => {`, + `const key = (Math.random() + 1).toString(36).substring(3);`, + `if (!${normalizedName}${SUFFIX}) return
;`, + `return <${normalizedName}${SUFFIX} key={key} {...props} />`, + `};`, + `export default ${normalizedName};`, + ].join('\n'); +} + +export function thunkCreateComponentsFiles(args: CreateAppProgramArgs): () => Promise { + return async () => { + let componentsList: Array<{ categoryName: string; components: Array<{ name: string; packageName: string }> }> = []; + + try { + componentsList = JSON.parse(args.components || ''); + } catch (e) { + console.log(e); + // do nothing + } + + const componentsPath: string = resolve(APP_DIRECTORY, 'components'); + if (!(await pathExists(componentsPath))) { + mkdir(componentsPath); + } + + await pMapSeries(componentsList, async (componentData) => { + components.push({ name: componentData.categoryName, include: [] }); + await pMapSeries(componentData.components, async ({ name, packageName }) => { + const normalizedName: string = name.replace(/\./g, ''); + const componentFile = `${componentsPath}/${normalizedName}.jsx`; + + await writeToFile(componentFile, getComponentContent(name, packageName)); + components[components.length - 1].include.push(`components/${normalizedName}.jsx`); + printLine(`✅ File ${componentFile} created`, { color: PrintColor.GREEN }); + }); + }); + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createNpmrcFile.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createNpmrcFile.ts new file mode 100644 index 000000000..8148078de --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createNpmrcFile.ts @@ -0,0 +1,28 @@ +import { pathExists } from 'fs-extra'; +import { resolve } from 'path'; +import { printLine, printWarning } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { writeToFile } from '../../../../utils/fs/writeToFile'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +export function createNpmrcFile(args: CreateAppProgramArgs): Step { + return { exec: thunkCreateNpmrcFile(args), shouldRun: true }; +} + +export function thunkCreateNpmrcFile(args: CreateAppProgramArgs): () => Promise { + return async () => { + if (!args.npmrc) { + return; + } + + const npmrcFile: string = resolve(APP_DIRECTORY, '.npmrc'); + if (!(await pathExists(npmrcFile))) { + await writeToFile(npmrcFile, args.npmrc); + printLine(`✅ File .npmrc created`, { color: PrintColor.GREEN }); + } else { + printWarning(`👉 File .npmrc exists`); + } + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createPackageJsonFile.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createPackageJsonFile.ts new file mode 100644 index 000000000..10ea611ce --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createPackageJsonFile.ts @@ -0,0 +1,34 @@ +import { pathExists } from 'fs-extra'; +import { resolve } from 'path'; +import { printLine, printWarning } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { writeToFile } from '../../../../utils/fs/writeToFile'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +const INDENT = 2; + +export function createPackageJsonFile(args: CreateAppProgramArgs): Step { + return { exec: thunkCreatePackageJsonFile(args), shouldRun: true }; +} + +export function thunkCreatePackageJsonFile(args: CreateAppProgramArgs): () => Promise { + return async () => { + const packageFile: { + name?: string; + dependencies?: { [key: string]: number | string }; + } = {}; + + packageFile.name = args.appName; + packageFile.dependencies = {}; + + const packageJsonPath: string = resolve(APP_DIRECTORY, 'package.json'); + if (!(await pathExists(packageJsonPath))) { + await writeToFile(packageJsonPath, JSON.stringify(packageFile, null, INDENT)); + printLine(`✅ File package.json created`, { color: PrintColor.GREEN }); + } else { + printWarning(`👉 File package.json exists`); + } + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createUXPinConfigFile.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createUXPinConfigFile.ts new file mode 100644 index 000000000..7b4cff2c0 --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createUXPinConfigFile.ts @@ -0,0 +1,29 @@ +import { resolve } from 'path'; +import { printLine } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { writeToFile } from '../../../../utils/fs/writeToFile'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; +import { components } from './createComponentsFiles'; + +const INDENT = 2; + +export function createUXPinConfigFile(args: CreateAppProgramArgs): Step { + return { exec: thunkCreateUXPinConfigFile(args), shouldRun: true }; +} + +export function thunkCreateUXPinConfigFile(args: CreateAppProgramArgs): () => Promise { + return async () => { + const uxpinConfigFile: any = {}; + + uxpinConfigFile.name = args.appName; + uxpinConfigFile.components = { + categories: components.map(({ name, include }: any) => ({ name, include })), + }; + + const uxpinConfigFilePath: string = resolve(APP_DIRECTORY, 'uxpin.config.js'); + await writeToFile(uxpinConfigFilePath, `module.exports = ${JSON.stringify(uxpinConfigFile, null, INDENT)}`); + printLine(`✅ File uxpin.config.js created`, { color: PrintColor.GREEN }); + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/createWebpackConfigFile.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createWebpackConfigFile.ts new file mode 100644 index 000000000..6f0ace15c --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/createWebpackConfigFile.ts @@ -0,0 +1,93 @@ +import { pathExists } from 'fs-extra'; +import { resolve } from 'path'; +import { printLine, printWarning } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { writeToFile } from '../../../../utils/fs/writeToFile'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +function getWebpackFile(shouldExcludeNodeModules: boolean): string { + return ` + const path = require("path"); + const webpack = require("webpack"); + const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); + + module.exports = { + output: { + path: path.resolve(__dirname, "build"), + filename: "bundle.js", + publicPath: "/" + }, + optimization: { + minimizer: [new UglifyJsPlugin()], + }, + resolve: { + modules: [__dirname, "node_modules"], + extensions: ["*", ".js", ".jsx", ".mjs"] + }, + devtool: "source-map", + module: { + rules: [ + { + test: /\\.mjs$/, + include: /node_modules/, + type: 'javascript/auto' + }, + { + test: /\\.css$/, + use: [ + { + loader: require.resolve('style-loader'), + }, + { + loader: require.resolve('css-loader'), + options: { + importLoaders: 1, + } + }, + ] + }, + { + loader: require.resolve('babel-loader'), + test: /\\.m?jsx?$/, + ${shouldExcludeNodeModules ? 'exclude: /node_modules/,' : ''} + options: { + presets: [ + require.resolve('@babel/preset-env'), + require.resolve('@babel/preset-react') + ], + plugins: [ + require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'), + ], + } + }, + ] + } + } + `; +} +export function createWebpackConfigFile(args: CreateAppProgramArgs): Step { + return { exec: thunkCreateWebpackConfigFile(args), shouldRun: true }; +} + +export function thunkCreateWebpackConfigFile(args: CreateAppProgramArgs): () => Promise { + return async () => { + const webpackConfigFile: string = resolve(APP_DIRECTORY, 'webpack.config.js'); + let packages: Array<{ name: string; version?: string }> = []; + try { + packages = JSON.parse(args.packages || ''); + } catch (e) { + // do nothing + } + + const shouldExcludeNodeModules = !packages.find((packageData) => ['@chakra-ui/react'].includes(packageData.name)); + + if (!(await pathExists(webpackConfigFile))) { + await writeToFile(webpackConfigFile, getWebpackFile(shouldExcludeNodeModules)); + printLine(`✅ File webpack.config.js created`, { color: PrintColor.GREEN }); + } else { + printWarning(`👉 File webpack.config.js exists`); + } + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPackages.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPackages.ts new file mode 100644 index 000000000..331682ade --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPackages.ts @@ -0,0 +1,69 @@ +import * as cp from 'child_process'; +import { printLine } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +export function installPackages(args: CreateAppProgramArgs): Step { + return { exec: thunkInstallPackages(args), shouldRun: true }; +} + +export function thunkInstallPackages(args: CreateAppProgramArgs): () => Promise { + return async () => { + if (!args.packages) { + throw new Error('Invalid package names'); + } + + let packages: Array<{ name: string; version?: string }> = []; + try { + packages = JSON.parse(args.packages || ''); + } catch (e) { + console.log(e); + // do nothing + } + + packages.forEach(({ name, version }) => { + const packageName: string = version ? `${name}@${version}` : name; + const { status } = cp.spawnSync('npm', ['install', packageName], { + cwd: APP_DIRECTORY, + }); + + if (status !== 0) { + throw new Error('🛑 Something went wrong during installing package'); + } + }); + + const { status: babelLoaderStatus } = cp.spawnSync( + 'npm', + [ + 'install', + 'babel-loader@8.2.5', + '@babel/core', + '@babel/preset-env', + '@babel/preset-react', + '@babel/plugin-proposal-nullish-coalescing-operator', + 'style-loader@1.0.0', + 'css-loader@0.23.1', + 'webpack@4.8.1', + 'uglifyjs-webpack-plugin@2.2.0', + 'prop-types', + ], + { + cwd: APP_DIRECTORY, + } + ); + + if (babelLoaderStatus !== 0) { + throw new Error('🛑 Something went wrong during installing babel-loader'); + } + + printLine( + // tslint:disable-next-line:max-line-length + `✅ Packages "${packages + .map(({ name }) => name) + .join(' ')} babel-loader @babel/core @babel/preset-env webpack" installed`, + { color: PrintColor.GREEN } + ); + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPeerDependencies.ts b/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPeerDependencies.ts new file mode 100644 index 000000000..11557446d --- /dev/null +++ b/packages/uxpin-merge-cli/src/program/command/create_app/steps/installPeerDependencies.ts @@ -0,0 +1,37 @@ +import * as cp from 'child_process'; +import { printLine } from '../../../../utils/console/printLine'; +import { PrintColor } from '../../../../utils/console/PrintOptions'; +import { CreateAppProgramArgs } from '../../../args/ProgramArgs'; +import { Step } from '../../Step'; +import { APP_DIRECTORY } from './createAppDirectory'; + +export function installPeerDependencies(args: CreateAppProgramArgs): Step { + return { exec: thunkInstallPeerDependencies(args), shouldRun: true }; +} + +export function thunkInstallPeerDependencies(args: CreateAppProgramArgs): () => Promise { + return async () => { + let packages: Array<{ name: string; version?: string }> = []; + try { + packages = JSON.parse(args.packages || ''); + } catch (e) { + console.log(e); + // do nothing + } + const packageJSON: any = require(`${APP_DIRECTORY}/node_modules/${packages[0].name}/package.json`); + + const peerDependencies: any = packageJSON.peerDependencies || {}; + Object.keys(peerDependencies).forEach((dependencyName) => { + const version: string = peerDependencies[dependencyName]; + const { status } = cp.spawnSync('npm', ['install', `${dependencyName}@${version}`], { + cwd: APP_DIRECTORY, + }); + + if (status !== 0) { + throw new Error(`🛑 Something went wrong during installing package - ${dependencyName}`); + } + + printLine(`✅ Peer dependency "${dependencyName}" installed`, { color: PrintColor.GREEN }); + }); + }; +} diff --git a/packages/uxpin-merge-cli/src/program/command/getSteps.ts b/packages/uxpin-merge-cli/src/program/command/getSteps.ts index 1a64918fc..c86a77fba 100644 --- a/packages/uxpin-merge-cli/src/program/command/getSteps.ts +++ b/packages/uxpin-merge-cli/src/program/command/getSteps.ts @@ -1,5 +1,6 @@ import { ProgramArgs } from '../args/ProgramArgs'; import { Command } from './Command'; +import { createApp } from './create_app/createApp'; import { getDeleteVersionCommandSteps } from './delete_version/getDeleteVersionCommandSteps'; import { getDumpCommandSteps } from './dump/getDumpCommandSteps'; import { getExperimentationCommandSteps } from './experimentation/getExperimentationCommandSteps'; @@ -21,6 +22,9 @@ export function getSteps(args: ProgramArgs): Step[] { case Command.INIT: return getInitCommandSteps(args); + case Command.CREATE_APP: + return createApp(args); + case Command.GENERATE_PRESETS: return getGeneratePresetsCommandSteps(args); diff --git a/packages/uxpin-merge-cli/src/program/command/push/getBuildOptions.ts b/packages/uxpin-merge-cli/src/program/command/push/getBuildOptions.ts index a0cd2d55f..ee135c7bb 100644 --- a/packages/uxpin-merge-cli/src/program/command/push/getBuildOptions.ts +++ b/packages/uxpin-merge-cli/src/program/command/push/getBuildOptions.ts @@ -5,13 +5,27 @@ import { getTempDirPath } from '../../args/providers/paths/getTempDirPath'; import { Command } from '../Command'; export function getBuildOptions(args: BuildProgramArgs): BuildOptions { - const { command, pageHeadTags, token, uxpinDomain, webpackConfig, wrapper, branch, tag, force } = args; + const { + command, + pageHeadTags, + token, + uxpinDomain, + webpackConfig, + wrapper, + branch, + tag, + force, + disableVersionControl, + cssResources, + } = args; return { branch, command, force, pageHeadTags, + cssResources, + disableVersionControl, projectRoot: getProjectRoot(args), tag, token, @@ -35,4 +49,6 @@ export interface BuildProgramArgs { uxpinDomain?: string; webpackConfig?: string; wrapper?: string; + cssResources?: string; + disableVersionControl?: boolean; } diff --git a/packages/uxpin-merge-cli/src/program/command/push/steps/uploadLibrary.ts b/packages/uxpin-merge-cli/src/program/command/push/steps/uploadLibrary.ts index 4b9d8c7a5..6d2333717 100644 --- a/packages/uxpin-merge-cli/src/program/command/push/steps/uploadLibrary.ts +++ b/packages/uxpin-merge-cli/src/program/command/push/steps/uploadLibrary.ts @@ -40,16 +40,18 @@ export function uploadLibrary(buildOptions: BuildOptions): StepExecutor { return designSystem; } - // Get the branches at the current commit - const branchesAtCurrentCommit: string[] = await getBranchesAtCommit(vcsDetails.paths.projectRoot, commitHash); - - // Prevent trying to push non-master commits to master or main - if (!branchesAtCurrentCommit.includes(branch)) { - if (isDefaultBranch(branch) && !branchesAtCurrentCommit.includes(ALTERNATIVE_DEFAULT_BRANCH_NAME)) { - printError( - `🛑 The current commit is not on branch [${branch}], please specify --branch to use a custom branch` - ); - return designSystem; + if (!buildOptions.disableVersionControl) { + // Get the branches at the current commit + const branchesAtCurrentCommit: string[] = await getBranchesAtCommit(vcsDetails.paths.projectRoot, commitHash); + + // Prevent trying to push non-master commits to masteror main + if (!branchesAtCurrentCommit.includes(branch)) { + if (isDefaultBranch(branch) && !branchesAtCurrentCommit.includes(ALTERNATIVE_DEFAULT_BRANCH_NAME)) { + printError( + `🛑 The current commit is not on branch [${branch}], please specify --branch to use a custom branch` + ); + return designSystem; + } } } diff --git a/packages/uxpin-merge-cli/src/program/runProgram.ts b/packages/uxpin-merge-cli/src/program/runProgram.ts index bca6a2c33..3f2d6067d 100644 --- a/packages/uxpin-merge-cli/src/program/runProgram.ts +++ b/packages/uxpin-merge-cli/src/program/runProgram.ts @@ -3,7 +3,7 @@ import { ProjectPaths } from '../steps/discovery/paths/ProjectPaths'; import { getDesignSystemMetadata } from '../steps/serialization/getDesignSystemMetadata'; import { tapPromise } from '../utils/promise/tapPromise'; import { getProgramArgs } from './args/getProgramArgs'; -import { ProgramArgs, RawProgramArgs } from './args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs, RawProgramArgs, WatchProgramArgs } from './args/ProgramArgs'; import { getProjectPaths } from './args/providers/paths/getProjectPaths'; import { Command } from './command/Command'; import { getSteps } from './command/getSteps'; @@ -35,7 +35,7 @@ async function setupProjectWatcher(programArgs: ProgramArgs): Promise { return; } - await setupWatcher(programArgs, thunkRunCommandWhenFilesChanged(programArgs)); + await setupWatcher(programArgs as WatchProgramArgs, thunkRunCommandWhenFilesChanged(programArgs)); } function thunkRunCommandWhenFilesChanged(programArgs: ProgramArgs): (path: string) => void { @@ -54,8 +54,11 @@ async function executeCommandSteps(programArgs: ProgramArgs, steps: Step[]): Pro .map((step) => tapPromise(step.exec)); if (shouldPassDesignSystemToCommand(programArgs)) { - const paths: ProjectPaths = getProjectPaths(programArgs); - const designSystem: DSMetadata = await getDesignSystemMetadata(programArgs, paths); + const paths: ProjectPaths = getProjectPaths(programArgs as Exclude); + const designSystem: DSMetadata = await getDesignSystemMetadata( + programArgs as Exclude, + paths + ); await pMapSeries(stepFunctions as StepExecutor[], (step) => step(designSystem)); } else { await pMapSeries(stepFunctions as StepWithoutDSExecutor[], (step) => step()); @@ -63,7 +66,7 @@ async function executeCommandSteps(programArgs: ProgramArgs, steps: Step[]): Pro } function shouldPassDesignSystemToCommand(programArgs: ProgramArgs): boolean { - return programArgs.command !== Command.GENERATE_PRESETS; + return ![Command.GENERATE_PRESETS, Command.CREATE_APP].includes(programArgs.command); } function isWatchChangesCommand(programArgs: ProgramArgs): boolean { diff --git a/packages/uxpin-merge-cli/src/program/watcher/setupWatcher.ts b/packages/uxpin-merge-cli/src/program/watcher/setupWatcher.ts index 1ae9d2834..1423918b2 100644 --- a/packages/uxpin-merge-cli/src/program/watcher/setupWatcher.ts +++ b/packages/uxpin-merge-cli/src/program/watcher/setupWatcher.ts @@ -1,15 +1,19 @@ import { FSWatcher, watch, WatchOptions } from 'chokidar'; -import { ProgramArgs } from '../args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../args/ProgramArgs'; import { getConfigPath } from '../args/providers/paths/getConfigPath'; import { getTempDirPath } from '../args/providers/paths/getTempDirPath'; const DOT_FILES = /(^|[\/\\])\../; const NODE_MODULES = /\/node_modules\//; -export async function setupWatcher(programArgs: ProgramArgs, onChangeListener: WatchListener): Promise { +export async function setupWatcher( + programArgs: Exclude, + onChangeListener: WatchListener +): Promise { return new Promise((resolve, reject) => { + const { cwd, config } = programArgs; const watchOptions: WatchOptions = { - ignored: [DOT_FILES, NODE_MODULES, getConfigPath(programArgs), getTempDirPath(programArgs)], + ignored: [DOT_FILES, NODE_MODULES, getConfigPath({ cwd, config }), getTempDirPath(programArgs)], }; const watcher: FSWatcher = watch(programArgs.cwd, watchOptions); diff --git a/packages/uxpin-merge-cli/src/steps/building/BuildOptions.ts b/packages/uxpin-merge-cli/src/steps/building/BuildOptions.ts index a328683dd..2ec4ad373 100644 --- a/packages/uxpin-merge-cli/src/steps/building/BuildOptions.ts +++ b/packages/uxpin-merge-cli/src/steps/building/BuildOptions.ts @@ -14,4 +14,6 @@ export interface BuildOptions { uxpinDomain?: string; webpackConfigPath?: string; wrapperPath?: string; + disableVersionControl?: boolean; + cssResources?: string; } diff --git a/packages/uxpin-merge-cli/src/steps/building/library/createComponentsLibrary.ts b/packages/uxpin-merge-cli/src/steps/building/library/createComponentsLibrary.ts index e52bc5444..f5885bfe9 100644 --- a/packages/uxpin-merge-cli/src/steps/building/library/createComponentsLibrary.ts +++ b/packages/uxpin-merge-cli/src/steps/building/library/createComponentsLibrary.ts @@ -7,11 +7,11 @@ import { getLibraryBundleSource } from './getLibraryBundleSource'; export async function createComponentsLibrary( componentInfos: ComponentDefinition[], - { pageHeadTags, uxpinDirPath, wrapperPath }: BuildOptions + { pageHeadTags, uxpinDirPath, wrapperPath, cssResources }: BuildOptions ): Promise { await ensureDir(uxpinDirPath); await writeToFile( getComponentLibraryInputPath(uxpinDirPath), - getLibraryBundleSource(componentInfos, { wrapperPath, pageHeadTags }) + getLibraryBundleSource(componentInfos, { wrapperPath, pageHeadTags, cssResources }) ); } diff --git a/packages/uxpin-merge-cli/src/steps/building/library/getLibraryBundleSource.ts b/packages/uxpin-merge-cli/src/steps/building/library/getLibraryBundleSource.ts index 5f1280874..f79583b5c 100644 --- a/packages/uxpin-merge-cli/src/steps/building/library/getLibraryBundleSource.ts +++ b/packages/uxpin-merge-cli/src/steps/building/library/getLibraryBundleSource.ts @@ -11,10 +11,10 @@ const CLASS_NAME_WRAPPER = 'Wrapper'; const log = debug('uxpin:build'); -type LibraryBundleOptions = Pick; +type LibraryBundleOptions = Pick; export function getLibraryBundleSource(components: ComponentDefinition[], options?: LibraryBundleOptions): string { - const { wrapperPath, pageHeadTags } = options || {}; + const { wrapperPath = '', cssResources = '', pageHeadTags = [] } = options || {}; const libImports: string[] = ["import * as React from 'react';", "import * as ReactDOM from 'react-dom';"]; const imports: string[] = components @@ -25,6 +25,30 @@ export function getLibraryBundleSource(components: ComponentDefinition[], option const namespacedComponentDeclarations: string[] = getNamespacedComponentDeclarations(components); + let cssFiles: string[] = []; + try { + cssFiles = cssResources ? JSON.parse(cssResources) : []; + } catch (e) { + console.error(e); + // do nothing + } + + const cssImports: string[] = cssFiles + .filter((cssFile) => !/^https.*/i.test(cssFile)) + .map((cssImport) => `import '../node_modules/${cssImport}';`); + + const cssUrls: string[] = cssFiles + .filter((cssFile) => /^https.*/i.test(cssFile)) + .map((cssUrl, i) => + [ + `const link${i} = document.createElement('link');`, + `link${i}.rel = 'stylesheet';`, + `link${i}.type = 'text/css';`, + `link${i}.href = "${cssUrl}";`, + `document.getElementsByTagName("head")[0].appendChild(link${i});`, + ].join('\n') + ); + const exports: string[] = [ `export {`, ...components.map((component) => ` ${getExportName(component)},`), @@ -40,7 +64,9 @@ export function getLibraryBundleSource(components: ComponentDefinition[], option ...libImports, ...imports, ...wrapperImport, + ...cssImports, ...namespacedComponentDeclarations, + ...cssUrls, ...exports, scriptToInjectTags, ]).join('\n'); diff --git a/packages/uxpin-merge-cli/src/steps/discovery/component/getComponentInfo.ts b/packages/uxpin-merge-cli/src/steps/discovery/component/getComponentInfo.ts index 9c9a51ae7..f31f98393 100644 --- a/packages/uxpin-merge-cli/src/steps/discovery/component/getComponentInfo.ts +++ b/packages/uxpin-merge-cli/src/steps/discovery/component/getComponentInfo.ts @@ -10,6 +10,7 @@ export async function getComponentInfo(projectRoot: string, implementationPath: if (!implementation) { return null; } + const paths: ComponentPaths = getComponentPaths(projectRoot, implementationPath); return { dirPath: paths.componentDirPath, diff --git a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/decorateWithPresets.ts b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/decorateWithPresets.ts index 51f45963a..7adbf34f0 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/decorateWithPresets.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/decorateWithPresets.ts @@ -1,6 +1,6 @@ import { flatMap } from 'lodash'; import { Warned } from '../../../../common/warning/Warned'; -import { ProgramArgs } from '../../../../program/args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../../../program/args/ProgramArgs'; import { ComponentInfo } from '../../../discovery/component/ComponentInfo'; import { ComponentCategory } from '../categories/ComponentCategory'; import { getAllComponentsFromCategories } from '../categories/getAllComponentsFromCategories'; @@ -12,7 +12,7 @@ import { serializePresets } from './serializePresets'; export async function decorateWithPresets( categories: Array>, - programArgs: ProgramArgs + programArgs: Exclude ): Promise>> { const components: ComponentDefinition[] = getAllComponentsFromCategories(flatMap(categories, (cat) => cat.result)); const bundle: PresetsBundle = await getPresetsBundle(programArgs, components); diff --git a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/createBundleSource.ts b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/createBundleSource.ts index f1c0fea77..fd4530d5b 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/createBundleSource.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/createBundleSource.ts @@ -1,13 +1,16 @@ import { ensureDir } from 'fs-extra'; import { resolve } from 'path'; import { v4 } from 'uuid'; -import { ProgramArgs } from '../../../../../../program/args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../../../../../program/args/ProgramArgs'; import { getTempDirPath } from '../../../../../../program/args/providers/paths/getTempDirPath'; import { writeToFile } from '../../../../../../utils/fs/writeToFile'; import { ComponentDefinition } from '../../../ComponentDefinition'; import { getSourceFileContentToBundle } from './getSourceFileContentToBundle'; -export async function createBundleSource(programArgs: ProgramArgs, components: ComponentDefinition[]): Promise { +export async function createBundleSource( + programArgs: Exclude, + components: ComponentDefinition[] +): Promise { const tempDirPath: string = getTempDirPath(programArgs); await ensureDir(tempDirPath); const bundleSourcePath: string = resolve(tempDirPath, getUniqueFileName()); diff --git a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/getPresetsBundle.ts b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/getPresetsBundle.ts index c0909a4af..7298d7319 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/getPresetsBundle.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/bundle/getPresetsBundle.ts @@ -1,11 +1,11 @@ import { unlink } from 'fs-extra'; -import { ProgramArgs } from '../../../../../../program/args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../../../../../program/args/ProgramArgs'; import { ComponentDefinition } from '../../../ComponentDefinition'; import { compilePresets } from '../compile/compilePresets'; import { PresetsBundle } from './PresetsBundle'; export async function getPresetsBundle( - programArgs: ProgramArgs, + programArgs: Exclude, components: ComponentDefinition[] ): Promise { const bundlePath: string = await compilePresets(programArgs, components); diff --git a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/compile/compilePresets.ts b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/compile/compilePresets.ts index 8d666ca83..822dc291c 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/compile/compilePresets.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/component/presets/jsx/compile/compilePresets.ts @@ -2,7 +2,7 @@ import debug from 'debug'; import { unlink } from 'fs-extra'; import { join, parse } from 'path'; import * as webpack from 'webpack'; -import { ProgramArgs, RawProgramArgs } from '../../../../../../program/args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs, RawProgramArgs } from '../../../../../../program/args/ProgramArgs'; import { getProjectRoot } from '../../../../../../program/args/providers/paths/getProjectRoot'; import { getTempDirPath } from '../../../../../../program/args/providers/paths/getTempDirPath'; import { Compiler } from '../../../../../building/compiler/Compiler'; @@ -14,7 +14,10 @@ import { getPresetsBundleWebpackConfig } from './getPresetsBundleWebpackConfig'; const log = debug('uxpin:serialization:presets'); -export async function compilePresets(programArgs: ProgramArgs, components: ComponentDefinition[]): Promise { +export async function compilePresets( + programArgs: Exclude, + components: ComponentDefinition[] +): Promise { log('Create temporary bundle'); const sourcePath: string = await createBundleSource(programArgs, components); log(`Compile presets with Webpack (${components.length} components)`); @@ -26,7 +29,7 @@ export async function compilePresets(programArgs: ProgramArgs, components: Compo } async function compileWithWebpack( - programArgs: ProgramArgs, + programArgs: Exclude, components: ComponentDefinition[], sourcePath: string ): Promise { diff --git a/packages/uxpin-merge-cli/src/steps/serialization/getDesignSystemMetadata.ts b/packages/uxpin-merge-cli/src/steps/serialization/getDesignSystemMetadata.ts index aae85af77..2f1c7c6bf 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/getDesignSystemMetadata.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/getDesignSystemMetadata.ts @@ -4,7 +4,7 @@ import pMap from 'p-map'; import { joinWarningLists } from '../../common/warning/joinWarningLists'; import { Warned } from '../../common/warning/Warned'; -import { ProgramArgs } from '../../program/args/ProgramArgs'; +import { CreateAppProgramArgs, ProgramArgs } from '../../program/args/ProgramArgs'; import { getBuildOptions } from '../../program/command/push/getBuildOptions'; import { BuildOptions } from '../building/BuildOptions'; import { ComponentCategoryInfo } from '../discovery/component/category/ComponentCategoryInfo'; @@ -25,7 +25,7 @@ import { MergeComponentSerializer } from './serializer'; const log = debug('uxpin'); export async function getDesignSystemMetadata( - programArgs: ProgramArgs, + programArgs: Exclude, paths: ProjectPaths ): Promise> { const buildOptions: BuildOptions = getBuildOptions(programArgs); diff --git a/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/FakeRepositoryAdapter.ts b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/FakeRepositoryAdapter.ts new file mode 100644 index 000000000..319160a7d --- /dev/null +++ b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/FakeRepositoryAdapter.ts @@ -0,0 +1,25 @@ +import { MovedFilePathsMap } from '../../../DesignSystemSnapshot'; +import { AbstractRepositoryAdapter } from '../AbstractRepositoryAdapter'; +import { CommitMetadata, RepositoryAdapter } from '../RepositoryAdapter'; +import { getFakeCommit } from './util/getFakeCommit'; + +export class FakeRepositoryAdapter extends AbstractRepositoryAdapter implements RepositoryAdapter { + constructor() { + super(); + } + + // tslint:disable-next-line:prefer-function-over-method + public async getCurrentBranch(): Promise { + return 'master'; + } + + // tslint:disable-next-line:prefer-function-over-method + public async getMovedFiles(): Promise { + return {}; + } + + // tslint:disable-next-line:prefer-function-over-method + public async getLatestCommit(): Promise { + return getFakeCommit(); + } +} diff --git a/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/util/getFakeCommit.ts b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/util/getFakeCommit.ts new file mode 100644 index 000000000..a7dfd7143 --- /dev/null +++ b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/fake/util/getFakeCommit.ts @@ -0,0 +1,13 @@ +import { createHash } from 'crypto'; +import { CommitMetadata } from '../../RepositoryAdapter'; + +export async function getFakeCommit(): Promise { + return { + author: '', + date: '', + hash: createHash('sha1') + .update(String(+new Date())) + .digest('hex'), + message: '', + }; +} diff --git a/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/getRepositoryAdapter.ts b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/getRepositoryAdapter.ts index e27154fe2..1b768394e 100644 --- a/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/getRepositoryAdapter.ts +++ b/packages/uxpin-merge-cli/src/steps/serialization/vcs/repositories/getRepositoryAdapter.ts @@ -1,4 +1,5 @@ import { BuildOptions } from '../../../building/BuildOptions'; +import { FakeRepositoryAdapter } from './fake/FakeRepositoryAdapter'; import { GitRepositoryAdapter } from './git/GitRepositoryAdapter'; import { isGitRepository } from './git/util/isGitRepository'; import { RepositoryAdapter, RepositoryAdapterOptions } from './RepositoryAdapter'; @@ -11,6 +12,11 @@ export async function getRepositoryAdapter(cwd: string, buildOptions?: BuildOpti options.branchOverride = buildOptions.branch; } + // for npm integration + if (buildOptions && buildOptions.disableVersionControl) { + return new FakeRepositoryAdapter(); + } + // Check and use Git repository if (await isGitRepository(cwd)) { return new GitRepositoryAdapter(options);