Skip to content

Commit

Permalink
Merge pull request #1115 from HubSpot/revise/clone-app-download
Browse files Browse the repository at this point in the history
Refactor: Create project directory when cloning app
  • Loading branch information
kemmerle committed Jul 23, 2024
2 parents 24f25e7 + 1031c18 commit 5866b8e
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 59 deletions.
55 changes: 35 additions & 20 deletions packages/cli/commands/project/cloneApp.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require('path');
const fs = require('fs');
const {
addAccountOptions,
addConfigOptions,
Expand All @@ -12,8 +13,8 @@ const {
selectPublicAppPrompt,
} = require('../../lib/prompts/selectPublicAppPrompt');
const {
cloneAppLocationPrompt,
} = require('../../lib/prompts/cloneAppLocationPrompt');
createProjectPrompt,
} = require('../../lib/prompts/createProjectPrompt');
const { poll } = require('../../lib/polling');
const {
uiLine,
Expand All @@ -27,6 +28,8 @@ const {
} = require('../../lib/errorHandlers/apiErrors');
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
const { isAppDeveloperAccount } = require('../../lib/accountTypes');
const { writeProjectConfig } = require('../../lib/projects');
const { PROJECT_CONFIG_FILE } = require('../../lib/constants');
const {
cloneApp,
checkCloneStatus,
Expand All @@ -35,9 +38,6 @@ const {
const { getCwd } = require('@hubspot/local-dev-lib/path');
const { logger } = require('@hubspot/local-dev-lib/logger');
const { getAccountConfig } = require('@hubspot/local-dev-lib/config');
const {
fetchPublicAppMetadata,
} = require('@hubspot/local-dev-lib/api/appsDev');
const { extractZipArchive } = require('@hubspot/local-dev-lib/archive');

const i18nKey = 'commands.project.subcommands.cloneApp';
Expand Down Expand Up @@ -68,7 +68,7 @@ exports.handler = async options => {
}

let appId;
let appName;
let name;
let location;
try {
appId = options.appId;
Expand All @@ -82,11 +82,9 @@ exports.handler = async options => {
appId = appIdResponse.appId;
}

const selectedApp = await fetchPublicAppMetadata(appId, accountId);
appName = selectedApp.name;

const locationResponse = await cloneAppLocationPrompt(options, appName);
location = locationResponse.location;
const projectResponse = await createProjectPrompt('', options, true);
name = projectResponse.name;
location = projectResponse.location;
} catch (error) {
logApiErrorInstance(error, new ApiErrorContext({ accountId }));
process.exit(EXIT_CODES.ERROR);
Expand All @@ -101,20 +99,37 @@ exports.handler = async options => {
const { exportId } = await cloneApp(accountId, appId);
const { status } = await poll(checkCloneStatus, accountId, exportId);
if (status === 'SUCCESS') {
const absoluteDestPath = path.resolve(getCwd(), location);
const zippedProject = await downloadClonedProject(accountId, exportId);

await extractZipArchive(
zippedProject,
appName,
path.resolve(absoluteDestPath),
{ includesRootDir: true, hideLogs: true }
);
// Ensure correct project folder structure exists
const baseDestPath = path.resolve(getCwd(), location);
const absoluteDestPath = path.resolve(baseDestPath, 'src', 'app');
fs.mkdirSync(absoluteDestPath, { recursive: true });

// Extract zipped app files and place them in correct directory
const zippedApp = await downloadClonedProject(accountId, exportId);
await extractZipArchive(zippedApp, name, absoluteDestPath, {
includesRootDir: true,
hideLogs: true,
});

// Create hsproject.json file
const configPath = path.join(baseDestPath, PROJECT_CONFIG_FILE);
const configContent = {
name,
srcDir: 'src',
platformVersion: '2023.2',
};
const success = writeProjectConfig(configPath, configContent);

SpinniesManager.succeed('cloneApp', {
text: i18n(`${i18nKey}.cloneStatus.done`),
succeedColor: 'white',
});
if (!success) {
logger.error(
i18n(`${i18nKey}.errors.couldNotWriteConfigPath`),
configPath
);
}
logger.log('');
uiLine();
logger.success(i18n(`${i18nKey}.cloneStatus.success`, { location }));
Expand Down
7 changes: 1 addition & 6 deletions packages/cli/lang/en.lyaml
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ en:
errors:
invalidAccountTypeTitle: "{{#bold}}Developer account not targeted{{/bold}}"
invalidAccountTypeDescription: "Only public apps created in a developer account can be converted to a project component. Select a connected developer account with {{useCommand}} or {{authCommand}} and try again."
couldNotWriteConfigPath: "Failed to write project config at {{ configPath }}"
add:
describe: "Create a new component within a project"
options:
Expand Down Expand Up @@ -1244,12 +1245,6 @@ en:
noAppsCloneMessage: "The selected developer account {{#bold}}{{ accountName }}{{/bold}} doesn't have any apps that can be cloned to the projects framework."
errorFetchingApps: "There was an error fetching public apps."
cannotBeMigrated: "Cannot be migrated"
cloneAppLocationPrompt:
enterLocation: "[--location] Where should the cloned project be created?"
errors:
locationRequired: "A project location is required"
invalidLocation: "The selected destination already exists. Please provide a new path for this project."
invalidCharacters: "The selected destination contains invalid characters. Please provide a new path and try again."
downloadProjectPrompt:
selectProject: "Select a project to download:"
errors:
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/lib/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ const writeProjectConfig = (configPath, config) => {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
logger.debug(`Wrote project config at ${configPath}`);
} catch (e) {
logger.error(`Could not write project config at ${configPath}`);
logger.debug(e);
return false;
}
return true;
};

const getIsInProject = _dir => {
Expand Down
32 changes: 0 additions & 32 deletions packages/cli/lib/prompts/cloneAppLocationPrompt.js

This file was deleted.

0 comments on commit 5866b8e

Please sign in to comment.