@hubspot/cli 7.4.5-beta.0 → 7.4.6-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/app/migrate.d.ts +3 -3
- package/commands/app/migrate.js +8 -6
- package/commands/app.js +0 -2
- package/commands/project/add.d.ts +3 -7
- package/commands/project/add.js +10 -9
- package/commands/project/cloneApp.d.ts +2 -8
- package/commands/project/cloneApp.js +25 -26
- package/commands/project/create.d.ts +10 -1
- package/commands/project/create.js +80 -62
- package/commands/project/deploy.d.ts +3 -6
- package/commands/project/deploy.js +9 -9
- package/commands/project/dev/index.d.ts +4 -2
- package/commands/project/dev/index.js +16 -7
- package/commands/project/download.d.ts +3 -7
- package/commands/project/download.js +9 -9
- package/commands/project/installDeps.d.ts +3 -6
- package/commands/project/installDeps.js +10 -9
- package/commands/project/listBuilds.d.ts +3 -7
- package/commands/project/listBuilds.js +15 -14
- package/commands/project/logs.d.ts +3 -6
- package/commands/project/logs.js +11 -12
- package/commands/project/migrate.d.ts +3 -8
- package/commands/project/migrate.js +17 -18
- package/commands/project/migrateApp.d.ts +2 -7
- package/commands/project/migrateApp.js +18 -18
- package/commands/project/open.d.ts +3 -7
- package/commands/project/open.js +15 -14
- package/commands/project/upload.d.ts +3 -7
- package/commands/project/upload.js +9 -9
- package/commands/project/watch.d.ts +6 -1
- package/commands/project/watch.js +82 -71
- package/commands/project.d.ts +3 -1
- package/commands/project.js +47 -36
- package/lang/en.d.ts +4 -0
- package/lang/en.js +4 -0
- package/lang/en.lyaml +4 -0
- package/lib/app/migrate.js +30 -12
- package/lib/commonOpts.d.ts +1 -1
- package/lib/commonOpts.js +27 -8
- package/lib/middleware/configMiddleware.js +2 -2
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +1 -1
- package/lib/projects/watch.d.ts +1 -1
- package/lib/prompts/createProjectPrompt.d.ts +11 -4
- package/lib/prompts/createProjectPrompt.js +6 -0
- package/lib/ui/index.d.ts +3 -2
- package/lib/ui/index.js +1 -0
- package/lib/yargsUtils.d.ts +1 -1
- package/package.json +1 -1
- package/types/Yargs.d.ts +5 -1
|
@@ -1,105 +1,106 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
exports.describe = uiBetaTag(i18n(`commands.project.subcommands.watch.describe`), false);
|
|
26
|
-
const handleBuildStatus = async (accountId, projectName, buildId) => {
|
|
27
|
-
const { isAutoDeployEnabled, deployStatusTaskLocator } = await pollBuildStatus(accountId, projectName, buildId);
|
|
3
|
+
const projects_1 = require("@hubspot/local-dev-lib/api/projects");
|
|
4
|
+
const index_1 = require("@hubspot/local-dev-lib/errors/index");
|
|
5
|
+
const buildAndDeploy_1 = require("../../lib/projects/buildAndDeploy");
|
|
6
|
+
const ui_1 = require("../../lib/ui");
|
|
7
|
+
const lang_1 = require("../../lib/lang");
|
|
8
|
+
const watch_1 = require("../../lib/projects/watch");
|
|
9
|
+
const index_2 = require("../../lib/errorHandlers/index");
|
|
10
|
+
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
11
|
+
const constants_1 = require("../../lib/constants");
|
|
12
|
+
const usageTracking_1 = require("../../lib/usageTracking");
|
|
13
|
+
const config_1 = require("../../lib/projects/config");
|
|
14
|
+
const ui_2 = require("../../lib/projects/ui");
|
|
15
|
+
const ensureProjectExists_1 = require("../../lib/projects/ensureProjectExists");
|
|
16
|
+
const upload_1 = require("../../lib/projects/upload");
|
|
17
|
+
const buildAndDeploy_2 = require("../../lib/projects/buildAndDeploy");
|
|
18
|
+
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
19
|
+
const process_1 = require("../../lib/process");
|
|
20
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
21
|
+
const command = 'watch';
|
|
22
|
+
const describe = (0, ui_1.uiBetaTag)((0, lang_1.i18n)(`commands.project.subcommands.watch.describe`), false);
|
|
23
|
+
async function handleBuildStatus(accountId, projectName, buildId) {
|
|
24
|
+
const { isAutoDeployEnabled, deployStatusTaskLocator } = await (0, buildAndDeploy_2.pollBuildStatus)(accountId, projectName, buildId, null);
|
|
28
25
|
if (isAutoDeployEnabled && deployStatusTaskLocator) {
|
|
29
|
-
await pollDeployStatus(accountId, projectName, deployStatusTaskLocator.id, buildId);
|
|
26
|
+
await (0, buildAndDeploy_2.pollDeployStatus)(accountId, projectName, Number(deployStatusTaskLocator.id), buildId);
|
|
30
27
|
}
|
|
31
|
-
logFeedbackMessage(buildId);
|
|
32
|
-
}
|
|
33
|
-
|
|
28
|
+
(0, ui_2.logFeedbackMessage)(buildId);
|
|
29
|
+
}
|
|
30
|
+
function handleUserInput(accountId, projectName, currentBuildId) {
|
|
34
31
|
const onTerminate = async () => {
|
|
35
|
-
logger.log(i18n(`commands.project.subcommands.watch.logs.processExited`));
|
|
32
|
+
logger_1.logger.log((0, lang_1.i18n)(`commands.project.subcommands.watch.logs.processExited`));
|
|
36
33
|
if (currentBuildId) {
|
|
37
34
|
try {
|
|
38
|
-
await cancelStagedBuild(accountId, projectName);
|
|
39
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
35
|
+
await (0, projects_1.cancelStagedBuild)(accountId, projectName);
|
|
36
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
40
37
|
}
|
|
41
38
|
catch (err) {
|
|
42
|
-
if (isSpecifiedError(err, {
|
|
43
|
-
subCategory: PROJECT_ERROR_TYPES.BUILD_NOT_IN_PROGRESS,
|
|
39
|
+
if ((0, index_1.isSpecifiedError)(err, {
|
|
40
|
+
subCategory: constants_1.PROJECT_ERROR_TYPES.BUILD_NOT_IN_PROGRESS,
|
|
44
41
|
})) {
|
|
45
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
42
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
46
43
|
}
|
|
47
44
|
else {
|
|
48
|
-
logError(err, new ApiErrorContext({ accountId }));
|
|
49
|
-
process.exit(EXIT_CODES.ERROR);
|
|
45
|
+
(0, index_2.logError)(err, new index_2.ApiErrorContext({ accountId }));
|
|
46
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
50
47
|
}
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
else {
|
|
54
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
51
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
55
52
|
}
|
|
56
53
|
};
|
|
57
|
-
handleExit(onTerminate);
|
|
58
|
-
handleKeypress(key => {
|
|
54
|
+
(0, process_1.handleExit)(onTerminate);
|
|
55
|
+
(0, process_1.handleKeypress)(key => {
|
|
59
56
|
if ((key.ctrl && key.name === 'c') || key.name === 'q') {
|
|
60
57
|
onTerminate();
|
|
61
58
|
}
|
|
62
59
|
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const { initialUpload, derivedAccountId } =
|
|
66
|
-
trackCommandUsage('project-watch',
|
|
67
|
-
const { projectConfig, projectDir } = await getProjectConfig();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
}
|
|
61
|
+
async function handler(args) {
|
|
62
|
+
const { initialUpload, derivedAccountId } = args;
|
|
63
|
+
(0, usageTracking_1.trackCommandUsage)('project-watch', undefined, derivedAccountId);
|
|
64
|
+
const { projectConfig, projectDir } = await (0, config_1.getProjectConfig)();
|
|
65
|
+
(0, config_1.validateProjectConfig)(projectConfig, projectDir);
|
|
66
|
+
if (!projectConfig || !projectDir) {
|
|
67
|
+
logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.watch.errors.projectConfigNotFound`));
|
|
68
|
+
return process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
69
|
+
}
|
|
70
|
+
if ((0, buildAndDeploy_1.useV3Api)(projectConfig.platformVersion)) {
|
|
71
|
+
logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.watch.errors.v3ApiError`, {
|
|
72
|
+
command: (0, ui_1.uiCommandReference)('hs project watch'),
|
|
73
|
+
newCommand: (0, ui_1.uiCommandReference)('hs project dev'),
|
|
72
74
|
platformVersion: projectConfig.platformVersion,
|
|
73
|
-
linkToDocs: uiLink('How to develop locally.', 'https://developers.hubspot.com/docs/guides/crm/ui-extensions/local-development'),
|
|
75
|
+
linkToDocs: (0, ui_1.uiLink)('How to develop locally.', 'https://developers.hubspot.com/docs/guides/crm/ui-extensions/local-development'),
|
|
74
76
|
}));
|
|
75
|
-
return process.exit(EXIT_CODES.ERROR);
|
|
77
|
+
return process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
76
78
|
}
|
|
77
|
-
|
|
78
|
-
await ensureProjectExists(derivedAccountId, projectConfig.name);
|
|
79
|
+
await (0, ensureProjectExists_1.ensureProjectExists)(derivedAccountId, projectConfig.name);
|
|
79
80
|
try {
|
|
80
|
-
const { data: { results: builds }, } = await fetchProjectBuilds(derivedAccountId, projectConfig.name
|
|
81
|
+
const { data: { results: builds }, } = await (0, projects_1.fetchProjectBuilds)(derivedAccountId, projectConfig.name);
|
|
81
82
|
const hasNoBuilds = !builds || !builds.length;
|
|
82
83
|
const startWatching = async () => {
|
|
83
|
-
await createWatcher(derivedAccountId, projectConfig, projectDir, handleBuildStatus, handleUserInput);
|
|
84
|
+
await (0, watch_1.createWatcher)(derivedAccountId, projectConfig, projectDir, handleBuildStatus, handleUserInput);
|
|
84
85
|
};
|
|
85
86
|
// Upload all files if no build exists for this project yet
|
|
86
87
|
if (initialUpload || hasNoBuilds) {
|
|
87
|
-
const { uploadError } = await handleProjectUpload(derivedAccountId, projectConfig, projectDir, startWatching);
|
|
88
|
+
const { uploadError } = await (0, upload_1.handleProjectUpload)(derivedAccountId, projectConfig, projectDir, startWatching);
|
|
88
89
|
if (uploadError) {
|
|
89
|
-
if (isSpecifiedError(uploadError, {
|
|
90
|
-
subCategory: PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
90
|
+
if ((0, index_1.isSpecifiedError)(uploadError, {
|
|
91
|
+
subCategory: constants_1.PROJECT_ERROR_TYPES.PROJECT_LOCKED,
|
|
91
92
|
})) {
|
|
92
|
-
logger.log();
|
|
93
|
-
logger.error(i18n(`commands.project.subcommands.watch.errors.projectLockedError`));
|
|
94
|
-
logger.log();
|
|
93
|
+
logger_1.logger.log();
|
|
94
|
+
logger_1.logger.error((0, lang_1.i18n)(`commands.project.subcommands.watch.errors.projectLockedError`));
|
|
95
|
+
logger_1.logger.log();
|
|
95
96
|
}
|
|
96
97
|
else {
|
|
97
|
-
logError(uploadError, new ApiErrorContext({
|
|
98
|
+
(0, index_2.logError)(uploadError, new index_2.ApiErrorContext({
|
|
98
99
|
accountId: derivedAccountId,
|
|
99
100
|
request: 'project upload',
|
|
100
101
|
}));
|
|
101
102
|
}
|
|
102
|
-
process.exit(EXIT_CODES.ERROR);
|
|
103
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
@@ -107,23 +108,33 @@ exports.handler = async (options) => {
|
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
catch (e) {
|
|
110
|
-
logError(e, new ApiErrorContext({ accountId: derivedAccountId }));
|
|
111
|
+
(0, index_2.logError)(e, new index_2.ApiErrorContext({ accountId: derivedAccountId }));
|
|
111
112
|
}
|
|
112
|
-
}
|
|
113
|
-
|
|
113
|
+
}
|
|
114
|
+
function projectWatchBuilder(yargs) {
|
|
114
115
|
yargs.option('initial-upload', {
|
|
115
116
|
alias: 'i',
|
|
116
|
-
describe: i18n(`commands.project.subcommands.watch.options.initialUpload.describe`),
|
|
117
|
+
describe: (0, lang_1.i18n)(`commands.project.subcommands.watch.options.initialUpload.describe`),
|
|
117
118
|
type: 'boolean',
|
|
118
119
|
});
|
|
119
120
|
yargs.example([
|
|
120
121
|
[
|
|
121
122
|
'$0 project watch',
|
|
122
|
-
i18n(`commands.project.subcommands.watch.examples.default`),
|
|
123
|
+
(0, lang_1.i18n)(`commands.project.subcommands.watch.examples.default`),
|
|
123
124
|
],
|
|
124
125
|
]);
|
|
125
|
-
addConfigOptions(yargs);
|
|
126
|
-
addAccountOptions(yargs);
|
|
127
|
-
addUseEnvironmentOptions(yargs);
|
|
128
126
|
return yargs;
|
|
127
|
+
}
|
|
128
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(projectWatchBuilder, command, describe, {
|
|
129
|
+
useGlobalOptions: true,
|
|
130
|
+
useAccountOptions: true,
|
|
131
|
+
useConfigOptions: true,
|
|
132
|
+
useEnvironmentOptions: true,
|
|
133
|
+
});
|
|
134
|
+
const projectWatchCommand = {
|
|
135
|
+
command,
|
|
136
|
+
describe,
|
|
137
|
+
handler,
|
|
138
|
+
builder,
|
|
129
139
|
};
|
|
140
|
+
exports.default = projectWatchCommand;
|
package/commands/project.d.ts
CHANGED
package/commands/project.js
CHANGED
|
@@ -1,42 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exports.builder = yargs => {
|
|
24
|
-
addGlobalOptions(yargs);
|
|
6
|
+
const lang_1 = require("../lib/lang");
|
|
7
|
+
const ui_1 = require("../lib/ui");
|
|
8
|
+
const deploy_1 = __importDefault(require("./project/deploy"));
|
|
9
|
+
const create_1 = __importDefault(require("./project/create"));
|
|
10
|
+
const upload_1 = __importDefault(require("./project/upload"));
|
|
11
|
+
const listBuilds_1 = __importDefault(require("./project/listBuilds"));
|
|
12
|
+
const logs_1 = __importDefault(require("./project/logs"));
|
|
13
|
+
const watch_1 = __importDefault(require("./project/watch"));
|
|
14
|
+
const download_1 = __importDefault(require("./project/download"));
|
|
15
|
+
const open_1 = __importDefault(require("./project/open"));
|
|
16
|
+
const dev_1 = __importDefault(require("./project/dev"));
|
|
17
|
+
const add_1 = __importDefault(require("./project/add"));
|
|
18
|
+
const migrate_1 = __importDefault(require("./project/migrate"));
|
|
19
|
+
const migrateApp_1 = __importDefault(require("./project/migrateApp"));
|
|
20
|
+
const cloneApp_1 = __importDefault(require("./project/cloneApp"));
|
|
21
|
+
const installDeps_1 = __importDefault(require("./project/installDeps"));
|
|
22
|
+
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
23
|
+
const command = ['project', 'projects'];
|
|
24
|
+
const describe = (0, ui_1.uiBetaTag)((0, lang_1.i18n)(`commands.project.describe`), false);
|
|
25
|
+
function projectBuilder(yargs) {
|
|
25
26
|
yargs
|
|
26
|
-
.command(
|
|
27
|
-
.command(
|
|
28
|
-
.command(
|
|
29
|
-
.command(
|
|
30
|
-
.command(
|
|
31
|
-
.command(
|
|
32
|
-
.command(
|
|
33
|
-
.command(
|
|
34
|
-
.command(
|
|
35
|
-
.command(
|
|
36
|
-
.command(
|
|
37
|
-
.command(
|
|
38
|
-
.command(
|
|
39
|
-
.command(
|
|
27
|
+
.command(create_1.default)
|
|
28
|
+
.command(add_1.default)
|
|
29
|
+
.command(watch_1.default)
|
|
30
|
+
.command(dev_1.default)
|
|
31
|
+
.command(upload_1.default)
|
|
32
|
+
.command(deploy_1.default)
|
|
33
|
+
.command(logs_1.default)
|
|
34
|
+
.command(listBuilds_1.default)
|
|
35
|
+
.command(download_1.default)
|
|
36
|
+
.command(open_1.default)
|
|
37
|
+
.command(migrateApp_1.default)
|
|
38
|
+
.command(migrate_1.default)
|
|
39
|
+
.command(cloneApp_1.default)
|
|
40
|
+
.command(installDeps_1.default)
|
|
40
41
|
.demandCommand(1, '');
|
|
41
42
|
return yargs;
|
|
43
|
+
}
|
|
44
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(projectBuilder, command, describe);
|
|
45
|
+
const projectCommand = {
|
|
46
|
+
command,
|
|
47
|
+
describe,
|
|
48
|
+
builder,
|
|
49
|
+
handler: () => { },
|
|
42
50
|
};
|
|
51
|
+
exports.default = projectCommand;
|
|
52
|
+
// TODO Remove this legacy export once we've migrated all commands to TS
|
|
53
|
+
module.exports = projectCommand;
|
package/lang/en.d.ts
CHANGED
|
@@ -768,6 +768,7 @@ export declare const commands: {
|
|
|
768
768
|
readonly describe: "Create a new project.";
|
|
769
769
|
readonly errors: {
|
|
770
770
|
readonly failedToDownloadProject: "Failed to download project. Please try again later.";
|
|
771
|
+
readonly invalidTemplateSource: "Invalid template source provided. Use the format <Owner>/<Repo> and try again.";
|
|
771
772
|
readonly failedToFetchProjectList: "Failed to fetch the list of available project templates. Please try again later.";
|
|
772
773
|
readonly cannotNestProjects: (projectDir: string | number) => string;
|
|
773
774
|
};
|
|
@@ -1043,6 +1044,8 @@ export declare const commands: {
|
|
|
1043
1044
|
readonly fileAlreadyQueued: (filePath: string | number) => string;
|
|
1044
1045
|
};
|
|
1045
1046
|
readonly errors: {
|
|
1047
|
+
readonly projectConfigNotFound: "No project config found. Please ensure that you are in a project directory.";
|
|
1048
|
+
readonly projectLockedError: `Your project is locked. This may mean that another user is running the ${string} command for this project. If this is you, unlock the project in Projects UI.`;
|
|
1046
1049
|
readonly uploadFailed: (remotePath: string | number, filePath: string | number) => string;
|
|
1047
1050
|
readonly deleteFileFailed: (remotePath: string | number) => string;
|
|
1048
1051
|
readonly deleteFolderFailed: (remotePath: string | number) => string;
|
|
@@ -2457,6 +2460,7 @@ export declare const lib: {
|
|
|
2457
2460
|
readonly invalidDest: "There is an existing project at this destination. Please provide a new path for this project.";
|
|
2458
2461
|
readonly invalidCharacters: "The selected destination contains invalid characters. Please provide a new path and try again.";
|
|
2459
2462
|
readonly invalidTemplate: (template: string | number) => string;
|
|
2463
|
+
readonly projectTemplateRequired: "Project template is required when projectTemplates is provided";
|
|
2460
2464
|
};
|
|
2461
2465
|
};
|
|
2462
2466
|
readonly selectPublicAppPrompt: {
|
package/lang/en.js
CHANGED
|
@@ -778,6 +778,7 @@ exports.commands = {
|
|
|
778
778
|
describe: 'Create a new project.',
|
|
779
779
|
errors: {
|
|
780
780
|
failedToDownloadProject: 'Failed to download project. Please try again later.',
|
|
781
|
+
invalidTemplateSource: 'Invalid template source provided. Use the format <Owner>/<Repo> and try again.',
|
|
781
782
|
failedToFetchProjectList: 'Failed to fetch the list of available project templates. Please try again later.',
|
|
782
783
|
cannotNestProjects: projectDir => `A project already exists at ${projectDir}. Projects cannot be nested within other projects. Please choose a different destination and try again.`,
|
|
783
784
|
},
|
|
@@ -1051,6 +1052,8 @@ exports.commands = {
|
|
|
1051
1052
|
fileAlreadyQueued: filePath => `File "${filePath}" is already queued for upload`,
|
|
1052
1053
|
},
|
|
1053
1054
|
errors: {
|
|
1055
|
+
projectConfigNotFound: 'No project config found. Please ensure that you are in a project directory.',
|
|
1056
|
+
projectLockedError: `Your project is locked. This may mean that another user is running the ${chalk_1.default.bold(`hs project dev`)} command for this project. If this is you, unlock the project in Projects UI.`,
|
|
1054
1057
|
uploadFailed: (remotePath, filePath) => `Failed to upload file "${filePath}" to "${remotePath}"`,
|
|
1055
1058
|
deleteFileFailed: remotePath => `Failed to delete file "${remotePath}"`,
|
|
1056
1059
|
deleteFolderFailed: remotePath => `Failed to delete folder "${remotePath}"`,
|
|
@@ -2465,6 +2468,7 @@ exports.lib = {
|
|
|
2465
2468
|
invalidDest: 'There is an existing project at this destination. Please provide a new path for this project.',
|
|
2466
2469
|
invalidCharacters: 'The selected destination contains invalid characters. Please provide a new path and try again.',
|
|
2467
2470
|
invalidTemplate: template => `[--template] Could not find template "${template}". Please choose an available template:`,
|
|
2471
|
+
projectTemplateRequired: 'Project template is required when projectTemplates is provided',
|
|
2468
2472
|
},
|
|
2469
2473
|
},
|
|
2470
2474
|
selectPublicAppPrompt: {
|
package/lang/en.lyaml
CHANGED
|
@@ -601,6 +601,7 @@ en:
|
|
|
601
601
|
describe: "Create a new project."
|
|
602
602
|
errors:
|
|
603
603
|
failedToDownloadProject: "Failed to download project. Please try again later."
|
|
604
|
+
invalidTemplateSource: "Invalid template source provided. Use the format <Owner>/<Repo> and try again."
|
|
604
605
|
failedToFetchProjectList: "Failed to fetch the list of available project templates. Please try again later."
|
|
605
606
|
cannotNestProjects: "A project already exists at {{ projectDir }}. Projects cannot be nested within other projects. Please choose a different destination and try again."
|
|
606
607
|
logs:
|
|
@@ -806,6 +807,8 @@ en:
|
|
|
806
807
|
attemptNewBuild: "Attempting to create a new build"
|
|
807
808
|
fileAlreadyQueued: "File \"{{ filePath }}\" is already queued for upload"
|
|
808
809
|
errors:
|
|
810
|
+
projectConfigNotFound: "No project config found. Please ensure that you are in a project directory."
|
|
811
|
+
projectLockedError: "Your project is locked. This may mean that another user is running the {{#bold}}`hs project dev`{{/bold}} command for this project. If this is you, unlock the project in Projects UI."
|
|
809
812
|
uploadFailed: "Failed to upload file \"{{ filePath }}\" to \"{{ remotePath }}\""
|
|
810
813
|
deleteFileFailed: "Failed to delete file \"{{ remotePath }}\""
|
|
811
814
|
deleteFolderFailed: "Failed to delete folder \"{{ remotePath }}\""
|
|
@@ -1422,6 +1425,7 @@ en:
|
|
|
1422
1425
|
invalidDest: "There is an existing project at this destination. Please provide a new path for this project."
|
|
1423
1426
|
invalidCharacters: "The selected destination contains invalid characters. Please provide a new path and try again."
|
|
1424
1427
|
invalidTemplate: "[--template] Could not find template \"{{ template }}\". Please choose an available template:"
|
|
1428
|
+
projectTemplateRequired: "Project template is required when projectTemplates is provided"
|
|
1425
1429
|
selectPublicAppPrompt:
|
|
1426
1430
|
selectAppIdMigrate: "[--appId] Choose an app under {{ accountName }} to migrate:"
|
|
1427
1431
|
selectAppIdClone: "[--appId] Choose an app under {{ accountName }} to clone:"
|
package/lib/app/migrate.js
CHANGED
|
@@ -51,6 +51,18 @@ function filterAppsByProjectName(projectConfig) {
|
|
|
51
51
|
return true;
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
function buildErrorMessageFromMigrationStatus(error) {
|
|
55
|
+
const { componentErrors, projectErrorDetail } = error;
|
|
56
|
+
if (!componentErrors || !componentErrors.length) {
|
|
57
|
+
return projectErrorDetail;
|
|
58
|
+
}
|
|
59
|
+
return `${projectErrorDetail}: \n\t- ${componentErrors
|
|
60
|
+
.map(componentError => {
|
|
61
|
+
const { componentType, errorMessage, developerSymbol: uid, } = componentError;
|
|
62
|
+
return `${componentType}${uid ? ` (${uid})` : ''}: ${errorMessage}`;
|
|
63
|
+
})
|
|
64
|
+
.join('\n\t- ')}`;
|
|
65
|
+
}
|
|
54
66
|
async function fetchMigrationApps(appId, derivedAccountId, platformVersion, projectConfig) {
|
|
55
67
|
const { data: { migratableApps, unmigratableApps }, } = await (0, migrate_1.listAppsForMigration)(derivedAccountId, platformVersion);
|
|
56
68
|
const filteredMigratableApps = migratableApps.filter(filterAppsByProjectName(projectConfig));
|
|
@@ -186,7 +198,23 @@ async function beginMigration(derivedAccountId, appId, platformVersion) {
|
|
|
186
198
|
const uidMap = {};
|
|
187
199
|
const { data } = await (0, migrate_1.initializeMigration)(derivedAccountId, appId, platformVersion);
|
|
188
200
|
const { migrationId } = data;
|
|
189
|
-
|
|
201
|
+
let pollResponse;
|
|
202
|
+
try {
|
|
203
|
+
pollResponse = await pollMigrationStatus(derivedAccountId, migrationId, [
|
|
204
|
+
Migration_1.MIGRATION_STATUS.INPUT_REQUIRED,
|
|
205
|
+
]);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
SpinniesManager_1.default.fail('beginningMigration', {
|
|
209
|
+
text: en_1.lib.migrate.spinners.unableToStartMigration,
|
|
210
|
+
});
|
|
211
|
+
if ((0, migrate_1.isMigrationStatus)(error) && error.status === Migration_1.MIGRATION_STATUS.FAILURE) {
|
|
212
|
+
throw new Error(buildErrorMessageFromMigrationStatus(error));
|
|
213
|
+
}
|
|
214
|
+
throw new Error(en_1.lib.migrate.errors.migrationFailed, {
|
|
215
|
+
cause: error,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
190
218
|
if (pollResponse.status !== Migration_1.MIGRATION_STATUS.INPUT_REQUIRED) {
|
|
191
219
|
SpinniesManager_1.default.fail('beginningMigration', {
|
|
192
220
|
text: en_1.lib.migrate.spinners.unableToStartMigration,
|
|
@@ -235,17 +263,7 @@ async function finalizeMigration(derivedAccountId, migrationId, uidMap, projectN
|
|
|
235
263
|
text: en_1.lib.migrate.spinners.migrationFailed,
|
|
236
264
|
});
|
|
237
265
|
if ((0, migrate_1.isMigrationStatus)(error) && error.status === Migration_1.MIGRATION_STATUS.FAILURE) {
|
|
238
|
-
|
|
239
|
-
if (!componentErrors || !componentErrors.length) {
|
|
240
|
-
throw new Error(projectErrorDetail);
|
|
241
|
-
}
|
|
242
|
-
const errorMessage = `${projectErrorDetail}: \n\t- ${componentErrors
|
|
243
|
-
.map(componentError => {
|
|
244
|
-
const { componentType, errorMessage, developerSymbol: uid, } = componentError;
|
|
245
|
-
return `${componentType}${uid ? ` (${uid})` : ''}: ${errorMessage}`;
|
|
246
|
-
})
|
|
247
|
-
.join('\n\t- ')}`;
|
|
248
|
-
throw new Error(errorMessage);
|
|
266
|
+
throw new Error(buildErrorMessageFromMigrationStatus(error));
|
|
249
267
|
}
|
|
250
268
|
throw new Error(en_1.lib.migrate.errors.migrationFailed, {
|
|
251
269
|
cause: error,
|
package/lib/commonOpts.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare function addCmsPublishModeOptions(yargs: Argv, { read, write }: {
|
|
|
11
11
|
}): Argv;
|
|
12
12
|
export declare function addTestingOptions(yargs: Argv): Argv;
|
|
13
13
|
export declare function addUseEnvironmentOptions(yargs: Argv): Argv;
|
|
14
|
-
export declare function addCustomHelpOutput(yargs: Argv, command: string, describe
|
|
14
|
+
export declare function addCustomHelpOutput(yargs: Argv, command: string | string[], describe?: string): Promise<void>;
|
|
15
15
|
export declare function setLogLevel(options: Arguments<{
|
|
16
16
|
debug?: boolean;
|
|
17
17
|
networkDebug?: boolean;
|
package/lib/commonOpts.js
CHANGED
|
@@ -78,26 +78,45 @@ function addTestingOptions(yargs) {
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
function addUseEnvironmentOptions(yargs) {
|
|
81
|
-
|
|
82
|
-
.option('use-env', {
|
|
81
|
+
yargs.option('use-env', {
|
|
83
82
|
describe: (0, lang_1.i18n)(`${i18nKey}.options.useEnv.describe`),
|
|
84
83
|
type: 'boolean',
|
|
85
|
-
})
|
|
86
|
-
|
|
84
|
+
});
|
|
85
|
+
yargs.conflicts('use-env', 'account');
|
|
86
|
+
return yargs;
|
|
87
87
|
}
|
|
88
88
|
async function addCustomHelpOutput(yargs, command, describe) {
|
|
89
89
|
try {
|
|
90
90
|
const parsedArgv = (0, yargs_parser_1.default)(process.argv.slice(2));
|
|
91
91
|
if (parsedArgv && parsedArgv.help) {
|
|
92
|
-
// Construct the full command, including positional arguments
|
|
93
92
|
const commandBase = `hs ${parsedArgv._.slice(0, -1).join(' ')}`;
|
|
94
|
-
|
|
93
|
+
// Make sure we are targeting the correct command by confirming that
|
|
94
|
+
// "command" matches the last part of the user's input command
|
|
95
|
+
const checkIsTargetCommand = (command) => {
|
|
96
|
+
const targetBaseCommand = command.split(' ')[0];
|
|
97
|
+
return targetBaseCommand === parsedArgv._[parsedArgv._.length - 1];
|
|
98
|
+
};
|
|
99
|
+
const isTargetedCommand = Array.isArray(command)
|
|
100
|
+
? command.some(checkIsTargetCommand)
|
|
101
|
+
: checkIsTargetCommand(command);
|
|
102
|
+
if (!isTargetedCommand) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Construct the full command, including positional arguments
|
|
106
|
+
const commandString = Array.isArray(command) ? command[0] : command;
|
|
107
|
+
const fullCommand = `${commandBase.trim()} ${commandString}`;
|
|
95
108
|
// Format the original help output to be more readable
|
|
96
109
|
let commandHelp = await yargs.getHelp();
|
|
97
|
-
['Options:', 'Examples:', 'Positionals:'].forEach(header => {
|
|
110
|
+
['Options:', 'Commands:', 'Examples:', 'Positionals:'].forEach(header => {
|
|
98
111
|
commandHelp = commandHelp.replace(header, chalk_1.default.bold(header));
|
|
99
112
|
});
|
|
100
|
-
|
|
113
|
+
// Remove "hs <command>" from the help output (this shows up for command buckets)
|
|
114
|
+
commandHelp = commandHelp.replace('hs <command>\n', '');
|
|
115
|
+
// Remove the first line of the help output if it's empty
|
|
116
|
+
if (commandHelp.startsWith('\n')) {
|
|
117
|
+
commandHelp = commandHelp.slice(1);
|
|
118
|
+
}
|
|
119
|
+
logger_1.logger.log(`${(0, ui_1.uiCommandReference)(fullCommand, false)}\n\n${describe ? `${describe}\n\n` : ''}${commandHelp}`);
|
|
101
120
|
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
102
121
|
}
|
|
103
122
|
}
|
|
@@ -43,7 +43,7 @@ const SKIP_CONFIG_VALIDATION = {
|
|
|
43
43
|
};
|
|
44
44
|
async function loadConfigMiddleware(argv) {
|
|
45
45
|
// Skip this when no command is provided
|
|
46
|
-
if (!argv._.length) {
|
|
46
|
+
if (!argv._.length || argv.help) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
const maybeValidateConfig = () => {
|
|
@@ -104,7 +104,7 @@ const SKIP_ACCOUNT_VALIDATION = {
|
|
|
104
104
|
};
|
|
105
105
|
async function validateAccountOptions(argv) {
|
|
106
106
|
// Skip this when no command is provided
|
|
107
|
-
if (argv._.length) {
|
|
107
|
+
if (argv._.length && !argv.help) {
|
|
108
108
|
let validAccount = true;
|
|
109
109
|
if (!(0, utils_1.isTargetedCommand)(argv._, SKIP_ACCOUNT_VALIDATION)) {
|
|
110
110
|
validAccount = await (0, validation_1.validateAccount)(argv);
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ type ProjectUploadResult<T> = {
|
|
|
5
5
|
result?: T;
|
|
6
6
|
uploadError?: unknown;
|
|
7
7
|
};
|
|
8
|
-
export declare function handleProjectUpload<T>(accountId: number, projectConfig: ProjectConfig, projectDir: string, callbackFunc: ProjectUploadCallbackFunction<T>, uploadMessage
|
|
8
|
+
export declare function handleProjectUpload<T>(accountId: number, projectConfig: ProjectConfig, projectDir: string, callbackFunc: ProjectUploadCallbackFunction<T>, uploadMessage?: string, sendIR?: boolean, skipValidation?: boolean): Promise<ProjectUploadResult<T>>;
|
|
9
9
|
export {};
|
package/lib/projects/upload.js
CHANGED
|
@@ -45,7 +45,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
45
45
|
}
|
|
46
46
|
return { buildId, error };
|
|
47
47
|
}
|
|
48
|
-
async function handleProjectUpload(accountId, projectConfig, projectDir, callbackFunc, uploadMessage, sendIR = false, skipValidation = false) {
|
|
48
|
+
async function handleProjectUpload(accountId, projectConfig, projectDir, callbackFunc, uploadMessage = '', sendIR = false, skipValidation = false) {
|
|
49
49
|
const srcDir = path_1.default.resolve(projectDir, projectConfig.srcDir);
|
|
50
50
|
const filenames = fs_extra_1.default.readdirSync(srcDir);
|
|
51
51
|
if (!filenames || filenames.length === 0) {
|
package/lib/projects/watch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ProjectConfig } from '../../types/Projects';
|
|
2
|
-
type ProjectWatchHandlerFunction = (accountId: number, projectName: string, currentBuildId: number) => Promise<void
|
|
2
|
+
type ProjectWatchHandlerFunction = (accountId: number, projectName: string, currentBuildId: number) => Promise<void> | void;
|
|
3
3
|
export declare function createWatcher(accountId: number, projectConfig: ProjectConfig, projectDir: string, handleBuildStatusFn: ProjectWatchHandlerFunction, handleUserInputFn: ProjectWatchHandlerFunction): Promise<void>;
|
|
4
4
|
export {};
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { ProjectTemplate } from '../../types/Projects';
|
|
2
|
-
type
|
|
2
|
+
type CreateProjectPromptResponseWithTemplate = {
|
|
3
3
|
name: string;
|
|
4
4
|
dest: string;
|
|
5
|
-
projectTemplate
|
|
5
|
+
projectTemplate: ProjectTemplate;
|
|
6
6
|
};
|
|
7
|
-
|
|
7
|
+
type CreateProjectPromptResponseWithoutTemplate = {
|
|
8
|
+
name: string;
|
|
9
|
+
dest: string;
|
|
10
|
+
projectTemplate?: undefined;
|
|
11
|
+
};
|
|
12
|
+
type PromptOptionsArg = {
|
|
8
13
|
name?: string;
|
|
9
14
|
dest?: string;
|
|
10
15
|
template?: string;
|
|
11
|
-
}
|
|
16
|
+
};
|
|
17
|
+
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates: ProjectTemplate[]): Promise<CreateProjectPromptResponseWithTemplate>;
|
|
18
|
+
export declare function createProjectPrompt(promptOptions: PromptOptionsArg, projectTemplates?: undefined): Promise<CreateProjectPromptResponseWithoutTemplate>;
|
|
12
19
|
export {};
|
|
@@ -86,5 +86,11 @@ async function createProjectPrompt(promptOptions, projectTemplates) {
|
|
|
86
86
|
if (providedTemplateIsValid) {
|
|
87
87
|
result.projectTemplate = findTemplateByNameOrLabel(projectTemplates, promptOptions.template);
|
|
88
88
|
}
|
|
89
|
+
if (projectTemplates && projectTemplates.length > 0) {
|
|
90
|
+
if (!result.projectTemplate) {
|
|
91
|
+
throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.projectTemplateRequired`));
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
89
95
|
return result;
|
|
90
96
|
}
|
package/lib/ui/index.d.ts
CHANGED
|
@@ -11,8 +11,9 @@ export declare function uiCommandReference(command: string, withQuotes?: boolean
|
|
|
11
11
|
export declare function uiFeatureHighlight(features: string[], title?: string): void;
|
|
12
12
|
export declare function uiBetaTag(message: string, log?: true): undefined;
|
|
13
13
|
export declare function uiBetaTag(message: string, log: false): string;
|
|
14
|
-
export declare function uiDeprecatedTag(message: string, log?:
|
|
14
|
+
export declare function uiDeprecatedTag(message: string, log?: true): undefined;
|
|
15
|
+
export declare function uiDeprecatedTag(message: string, log: false): string;
|
|
15
16
|
export declare function uiCommandDisabledBanner(command: string, url?: string, message?: string): void;
|
|
16
|
-
export declare function uiDeprecatedDescription(message: string, command: string, url?: string):
|
|
17
|
+
export declare function uiDeprecatedDescription(message: string, command: string, url?: string): undefined;
|
|
17
18
|
export declare function uiDeprecatedMessage(command: string, url?: string, message?: string): void;
|
|
18
19
|
export declare function indent(level: number): string;
|
package/lib/ui/index.js
CHANGED