@hubspot/cli 7.7.19-experimental.1 → 7.7.19-experimental.2
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/install.d.ts +8 -0
- package/commands/app/install.js +127 -0
- package/commands/app.js +6 -1
- package/commands/testAccount/create.js +3 -0
- package/lang/en.d.ts +22 -0
- package/lang/en.js +22 -0
- package/lib/buildAccount.js +2 -2
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +2 -1
- package/lib/projects/upload.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule, JSONOutputArgs } from '../../types/Yargs';
|
|
2
|
+
type InstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
|
+
appUid?: string;
|
|
4
|
+
projectName?: string;
|
|
5
|
+
testAccountId: number;
|
|
6
|
+
};
|
|
7
|
+
declare const installAppCommand: YargsCommandModule<unknown, InstallAppArgs>;
|
|
8
|
+
export default installAppCommand;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const developerTestAccounts_1 = require("@hubspot/local-dev-lib/api/developerTestAccounts");
|
|
7
|
+
const usageTracking_1 = require("../../lib/usageTracking");
|
|
8
|
+
const en_1 = require("../../lang/en");
|
|
9
|
+
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
10
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
11
|
+
const constants_1 = require("../../lib/constants");
|
|
12
|
+
const logger_1 = require("../../lib/ui/logger");
|
|
13
|
+
const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
|
|
14
|
+
const errorHandlers_1 = require("../../lib/errorHandlers");
|
|
15
|
+
const polling_1 = require("../../lib/polling");
|
|
16
|
+
const config_1 = require("../../lib/projects/config");
|
|
17
|
+
const upload_1 = require("../../lib/projects/upload");
|
|
18
|
+
const structure_1 = require("../../lib/projects/structure");
|
|
19
|
+
const command = 'install <test-account-id>';
|
|
20
|
+
const describe = undefined; // commands.app.subcommands.install.describe;
|
|
21
|
+
async function handler(args) {
|
|
22
|
+
const { derivedAccountId, appUid, projectName, testAccountId, formatOutputAsJson, } = args;
|
|
23
|
+
(0, usageTracking_1.trackCommandUsage)('app-install', {}, derivedAccountId);
|
|
24
|
+
const jsonOutput = {};
|
|
25
|
+
let targetProjectName = projectName;
|
|
26
|
+
let targetAppUid = appUid;
|
|
27
|
+
const { projectConfig, projectDir } = await (0, config_1.getProjectConfig)();
|
|
28
|
+
if (!targetProjectName) {
|
|
29
|
+
(0, config_1.validateProjectConfig)(projectConfig, projectDir);
|
|
30
|
+
targetProjectName = projectConfig?.name;
|
|
31
|
+
}
|
|
32
|
+
if (!targetProjectName) {
|
|
33
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.mustSpecifyProjectName);
|
|
34
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
35
|
+
}
|
|
36
|
+
let isAppOauth = true;
|
|
37
|
+
if (!targetAppUid) {
|
|
38
|
+
const intermediateRepresentation = await (0, upload_1.handleTranslate)(projectDir, projectConfig, derivedAccountId, true, undefined);
|
|
39
|
+
if (intermediateRepresentation) {
|
|
40
|
+
Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).forEach(node => {
|
|
41
|
+
if ((0, structure_1.isAppIRNode)(node)) {
|
|
42
|
+
targetAppUid = node.uid;
|
|
43
|
+
isAppOauth = node.config.auth.type === constants_1.APP_AUTH_TYPES.OAUTH;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (!targetAppUid) {
|
|
49
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.noAppUidFound);
|
|
50
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
51
|
+
}
|
|
52
|
+
if (!isAppOauth) {
|
|
53
|
+
logger_1.uiLogger.error(en_1.commands.app.subcommands.install.errors.appMustBeOauth);
|
|
54
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const { data } = await (0, developerTestAccounts_1.installOauthAppIntoDeveloperTestAccount)(derivedAccountId, testAccountId, targetProjectName, targetAppUid);
|
|
58
|
+
if (data?.authCodes.length > 0) {
|
|
59
|
+
jsonOutput.authCode = data.authCodes[0].authCode;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
(0, errorHandlers_1.logError)(err);
|
|
64
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
65
|
+
}
|
|
66
|
+
SpinniesManager_1.default.init({
|
|
67
|
+
succeedColor: 'white',
|
|
68
|
+
});
|
|
69
|
+
SpinniesManager_1.default.add('installApp', {
|
|
70
|
+
text: en_1.commands.app.subcommands.install.polling.start,
|
|
71
|
+
});
|
|
72
|
+
let appInstallSucceeded = false;
|
|
73
|
+
try {
|
|
74
|
+
await (0, polling_1.poll)(() => (0, developerTestAccounts_1.fetchDeveloperTestAccountOauthAppInstallStatus)(derivedAccountId, targetProjectName, targetAppUid), {
|
|
75
|
+
successStates: ['SUCCESS'],
|
|
76
|
+
errorStates: [],
|
|
77
|
+
});
|
|
78
|
+
appInstallSucceeded = true;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
SpinniesManager_1.default.fail('installApp');
|
|
82
|
+
(0, errorHandlers_1.logError)(err);
|
|
83
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
84
|
+
}
|
|
85
|
+
if (!appInstallSucceeded) {
|
|
86
|
+
SpinniesManager_1.default.fail('installApp');
|
|
87
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
88
|
+
}
|
|
89
|
+
SpinniesManager_1.default.succeed('installApp', {
|
|
90
|
+
text: en_1.commands.app.subcommands.install.polling.success,
|
|
91
|
+
});
|
|
92
|
+
if (formatOutputAsJson) {
|
|
93
|
+
logger_1.uiLogger.json(jsonOutput);
|
|
94
|
+
}
|
|
95
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
96
|
+
}
|
|
97
|
+
function installAppBuilder(yargs) {
|
|
98
|
+
yargs.positional('test-account-id', {
|
|
99
|
+
describe: en_1.commands.app.subcommands.install.positionals.testAccountId,
|
|
100
|
+
required: true,
|
|
101
|
+
type: 'number',
|
|
102
|
+
});
|
|
103
|
+
yargs.option('app-uid', {
|
|
104
|
+
describe: en_1.commands.app.subcommands.install.options.appUid,
|
|
105
|
+
type: 'string',
|
|
106
|
+
});
|
|
107
|
+
yargs.option('project-name', {
|
|
108
|
+
describe: en_1.commands.app.subcommands.install.options.projectName,
|
|
109
|
+
type: 'string',
|
|
110
|
+
});
|
|
111
|
+
yargs.example('install 1234567890 --app-uid=my-app-uid --project-name=my-project', en_1.commands.app.subcommands.install.example);
|
|
112
|
+
return yargs;
|
|
113
|
+
}
|
|
114
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(installAppBuilder, command, en_1.commands.app.subcommands.install.describe, {
|
|
115
|
+
useGlobalOptions: true,
|
|
116
|
+
useAccountOptions: true,
|
|
117
|
+
useConfigOptions: true,
|
|
118
|
+
useEnvironmentOptions: true,
|
|
119
|
+
useJSONOutputOptions: true,
|
|
120
|
+
});
|
|
121
|
+
const installAppCommand = {
|
|
122
|
+
command,
|
|
123
|
+
describe,
|
|
124
|
+
handler,
|
|
125
|
+
builder,
|
|
126
|
+
};
|
|
127
|
+
exports.default = installAppCommand;
|
package/commands/app.js
CHANGED
|
@@ -5,12 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const migrate_1 = __importDefault(require("./app/migrate"));
|
|
7
7
|
const secret_1 = __importDefault(require("./app/secret"));
|
|
8
|
+
const install_1 = __importDefault(require("./app/install"));
|
|
8
9
|
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
9
10
|
const command = ['app', 'apps'];
|
|
10
11
|
// Keep the command hidden for now
|
|
11
12
|
const describe = undefined;
|
|
12
13
|
function appBuilder(yargs) {
|
|
13
|
-
yargs
|
|
14
|
+
yargs
|
|
15
|
+
.command(migrate_1.default)
|
|
16
|
+
.command(secret_1.default)
|
|
17
|
+
.command(install_1.default)
|
|
18
|
+
.demandCommand(1, '');
|
|
14
19
|
return yargs;
|
|
15
20
|
}
|
|
16
21
|
const builder = (0, yargsUtils_1.makeYargsBuilder)(appBuilder, command, describe);
|
|
@@ -81,6 +81,9 @@ async function handler(args) {
|
|
|
81
81
|
testAccountId = result.accountId;
|
|
82
82
|
}
|
|
83
83
|
catch (err) {
|
|
84
|
+
SpinniesManager_1.default.fail('createTestAccount', {
|
|
85
|
+
text: en_1.commands.testAccount.create.polling.createFailure,
|
|
86
|
+
});
|
|
84
87
|
(0, errorHandlers_1.logError)(err);
|
|
85
88
|
SpinniesManager_1.default.fail('createTestAccount', {
|
|
86
89
|
text: en_1.commands.testAccount.create.polling.createFailure,
|
package/lang/en.d.ts
CHANGED
|
@@ -1502,6 +1502,28 @@ ${string}`;
|
|
|
1502
1502
|
readonly app: {
|
|
1503
1503
|
readonly describe: "Commands for managing apps.";
|
|
1504
1504
|
readonly subcommands: {
|
|
1505
|
+
readonly install: {
|
|
1506
|
+
readonly describe: "Install an OAuth app into a test account.";
|
|
1507
|
+
readonly options: {
|
|
1508
|
+
readonly appUid: "The uid of the app to install";
|
|
1509
|
+
readonly projectName: "The name of the project that contains the app";
|
|
1510
|
+
};
|
|
1511
|
+
readonly positionals: {
|
|
1512
|
+
readonly testAccountId: "The id of the test account to install the app into";
|
|
1513
|
+
};
|
|
1514
|
+
readonly errors: {
|
|
1515
|
+
readonly mustSpecifyProjectName: `You must specify a project name. Use the ${string} flag to specify the project name or run this command from within a project directory.`;
|
|
1516
|
+
readonly noAppUidFound: `No app uid found. Please specify the app uid with the ${string} flag or run this command from within a project that contains an app.`;
|
|
1517
|
+
readonly appMustBeOauth: "This command only supports installing oauth apps. Please specify an app with oauth auth type.";
|
|
1518
|
+
};
|
|
1519
|
+
readonly polling: {
|
|
1520
|
+
readonly start: "Installing app...";
|
|
1521
|
+
readonly success: "App installed successfully";
|
|
1522
|
+
readonly failure: "App installation failed";
|
|
1523
|
+
readonly error: "Error installing app";
|
|
1524
|
+
};
|
|
1525
|
+
readonly example: "Install the app with uid my-app-uid from the project named \"my-project\" into the target account with id 1234567890";
|
|
1526
|
+
};
|
|
1505
1527
|
readonly secret: {
|
|
1506
1528
|
readonly describe: "Commands for managing secrets.";
|
|
1507
1529
|
readonly subcommands: {
|
package/lang/en.js
CHANGED
|
@@ -1500,6 +1500,28 @@ exports.commands = {
|
|
|
1500
1500
|
app: {
|
|
1501
1501
|
describe: 'Commands for managing apps.',
|
|
1502
1502
|
subcommands: {
|
|
1503
|
+
install: {
|
|
1504
|
+
describe: 'Install an OAuth app into a test account.',
|
|
1505
|
+
options: {
|
|
1506
|
+
appUid: 'The uid of the app to install',
|
|
1507
|
+
projectName: 'The name of the project that contains the app',
|
|
1508
|
+
},
|
|
1509
|
+
positionals: {
|
|
1510
|
+
testAccountId: 'The id of the test account to install the app into',
|
|
1511
|
+
},
|
|
1512
|
+
errors: {
|
|
1513
|
+
mustSpecifyProjectName: `You must specify a project name. Use the ${(0, ui_1.uiCommandReference)('--project-name')} flag to specify the project name or run this command from within a project directory.`,
|
|
1514
|
+
noAppUidFound: `No app uid found. Please specify the app uid with the ${(0, ui_1.uiCommandReference)('--app-uid')} flag or run this command from within a project that contains an app.`,
|
|
1515
|
+
appMustBeOauth: 'This command only supports installing oauth apps. Please specify an app with oauth auth type.',
|
|
1516
|
+
},
|
|
1517
|
+
polling: {
|
|
1518
|
+
start: 'Installing app...',
|
|
1519
|
+
success: 'App installed successfully',
|
|
1520
|
+
failure: 'App installation failed',
|
|
1521
|
+
error: 'Error installing app',
|
|
1522
|
+
},
|
|
1523
|
+
example: 'Install the app with uid my-app-uid from the project named "my-project" into the target account with id 1234567890',
|
|
1524
|
+
},
|
|
1503
1525
|
secret: {
|
|
1504
1526
|
describe: 'Commands for managing secrets.',
|
|
1505
1527
|
subcommands: {
|
package/lib/buildAccount.js
CHANGED
|
@@ -81,8 +81,8 @@ async function createDeveloperTestAccountV3(parentAccountId, testAccountConfig)
|
|
|
81
81
|
throw new Error(en_1.lib.buildAccount.createDeveloperTestAccountV3.syncFailure);
|
|
82
82
|
}
|
|
83
83
|
// HACK: The status endpoint sometimes returns an early success status.
|
|
84
|
-
// Sleep for an extra
|
|
85
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
84
|
+
// Sleep for an extra 6 minutes to make sure the sync is actually complete.
|
|
85
|
+
await new Promise(resolve => setTimeout(resolve, 360000));
|
|
86
86
|
try {
|
|
87
87
|
// Attempt to generate a new personal access key for the test account now that gate sync is complete.
|
|
88
88
|
const { data } = await (0, developerTestAccounts_1.generateDeveloperTestAccountPersonalAccessKey)(parentAccountId, result.accountId);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects';
|
|
2
|
-
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
2
|
+
import { IntermediateRepresentationNode, IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types';
|
|
3
3
|
import { AppIRNode } from '../../types/ProjectComponents';
|
|
4
4
|
export declare const CONFIG_FILES: {
|
|
5
5
|
[k in ComponentTypes]: string;
|
|
@@ -15,4 +15,4 @@ export declare function getProjectComponentTypes(components: Array<Component>):
|
|
|
15
15
|
export declare function getComponentUid(component?: Component | null): string | null;
|
|
16
16
|
export declare function componentIsApp(component?: Component | null): component is Component<PublicAppComponentConfig | PrivateAppComponentConfig>;
|
|
17
17
|
export declare function componentIsPublicApp(component?: Component | null): component is Component<PublicAppComponentConfig>;
|
|
18
|
-
export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev): component is AppIRNode;
|
|
18
|
+
export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev | IntermediateRepresentationNode): component is AppIRNode;
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FileResult } from 'tmp';
|
|
2
|
+
import { IntermediateRepresentation } from '@hubspot/project-parsing-lib';
|
|
2
3
|
import { ProjectConfig } from '../../types/Projects';
|
|
3
4
|
type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
|
|
4
5
|
type ProjectUploadResult<T> = {
|
|
@@ -20,5 +21,5 @@ type HandleProjectUploadArg<T> = {
|
|
|
20
21
|
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
21
22
|
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
|
|
22
23
|
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
23
|
-
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<
|
|
24
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<IntermediateRepresentation | undefined>;
|
|
24
25
|
export {};
|
package/lib/projects/upload.js
CHANGED
package/package.json
CHANGED