@hubspot/cli 4.1.8-beta.2 → 4.1.8-beta.4
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/bin/cli.js +1 -1
- package/commands/accounts/info.js +1 -1
- package/commands/accounts/list.js +1 -1
- package/commands/accounts/remove.js +1 -1
- package/commands/accounts/rename.js +1 -1
- package/commands/accounts/use.js +1 -1
- package/commands/accounts.js +1 -1
- package/commands/auth.js +1 -1
- package/commands/cms/convertFields.js +1 -1
- package/commands/cms/lighthouseScore.js +1 -1
- package/commands/cms.js +1 -1
- package/commands/config/set/allowUsageTracking.js +1 -1
- package/commands/config/set/defaultMode.js +1 -1
- package/commands/config/set/httpTimeout.js +1 -1
- package/commands/config/set.js +1 -1
- package/commands/config.js +1 -1
- package/commands/create/api-sample.js +1 -1
- package/commands/create/module.js +1 -1
- package/commands/create/template.js +1 -1
- package/commands/create.js +1 -1
- package/commands/customObject/create.js +1 -1
- package/commands/customObject/schema/create.js +1 -1
- package/commands/customObject/schema/delete.js +1 -1
- package/commands/customObject/schema/fetch-all.js +1 -1
- package/commands/customObject/schema/fetch.js +1 -1
- package/commands/customObject/schema/list.js +1 -1
- package/commands/customObject/schema/update.js +1 -1
- package/commands/customObject/schema.js +1 -1
- package/commands/customObject.js +1 -1
- package/commands/feedback.js +1 -1
- package/commands/fetch.js +1 -1
- package/commands/filemanager/fetch.js +1 -1
- package/commands/filemanager/upload.js +1 -1
- package/commands/filemanager.js +1 -1
- package/commands/functions/deploy.js +1 -1
- package/commands/functions/list.js +1 -1
- package/commands/functions/server.js +1 -1
- package/commands/functions.js +1 -1
- package/commands/hubdb/clear.js +1 -1
- package/commands/hubdb/create.js +1 -1
- package/commands/hubdb/delete.js +1 -1
- package/commands/hubdb/fetch.js +1 -1
- package/commands/hubdb.js +1 -1
- package/commands/init.js +1 -1
- package/commands/lint.js +1 -1
- package/commands/list.js +1 -1
- package/commands/logs.js +1 -1
- package/commands/module/marketplace-validate.js +1 -1
- package/commands/module.js +1 -1
- package/commands/mv.js +1 -1
- package/commands/open.js +1 -1
- package/commands/project/add.js +1 -1
- package/commands/project/create.js +1 -1
- package/commands/project/deploy.js +1 -1
- package/commands/project/dev.js +31 -9
- package/commands/project/download.js +1 -1
- package/commands/project/logs.js +1 -1
- package/commands/project/open.js +1 -1
- package/commands/project/upload.js +1 -1
- package/commands/project/watch.js +1 -1
- package/commands/remove.js +1 -1
- package/commands/sandbox/create.js +22 -2
- package/commands/sandbox/delete.js +1 -1
- package/commands/sandbox/sync.js +1 -1
- package/commands/secrets/addSecret.js +1 -1
- package/commands/secrets/deleteSecret.js +1 -1
- package/commands/secrets/listSecrets.js +1 -1
- package/commands/secrets/updateSecret.js +1 -1
- package/commands/secrets.js +1 -1
- package/commands/theme/marketplace-validate.js +1 -1
- package/commands/theme.js +1 -1
- package/commands/upload.js +1 -1
- package/commands/watch.js +1 -1
- package/lang/en.lyaml +1205 -0
- package/lib/DevServerManager.js +74 -0
- package/lib/LocalDevManager.js +41 -30
- package/lib/commonOpts.js +1 -1
- package/lib/interpolation.js +137 -0
- package/lib/interpolationHelpers.js +23 -0
- package/lib/lang.js +95 -0
- package/lib/marketplace-validate.js +1 -1
- package/lib/projects.js +1 -1
- package/lib/prompts/accountsPrompt.js +1 -1
- package/lib/prompts/buildIdPrompt.js +1 -1
- package/lib/prompts/cmsFieldPrompt.js +1 -1
- package/lib/prompts/createApiSamplePrompt.js +1 -1
- package/lib/prompts/createFunctionPrompt.js +1 -1
- package/lib/prompts/createModulePrompt.js +1 -1
- package/lib/prompts/createProjectPrompt.js +1 -1
- package/lib/prompts/createTemplatePrompt.js +1 -1
- package/lib/prompts/downloadProjectPrompt.js +1 -1
- package/lib/prompts/enterAccountNamePrompt.js +1 -1
- package/lib/prompts/feedbackPrompt.js +1 -1
- package/lib/prompts/folderOverwritePrompt.js +1 -1
- package/lib/prompts/personalAccessKeyPrompt.js +1 -1
- package/lib/prompts/projectAddPrompt.js +1 -1
- package/lib/prompts/projectDevTargetAccountPrompt.js +1 -1
- package/lib/prompts/projectNamePrompt.js +1 -1
- package/lib/prompts/projectsLogsPrompt.js +1 -1
- package/lib/prompts/sandboxesPrompt.js +1 -1
- package/lib/prompts/secretPrompt.js +1 -1
- package/lib/prompts/setAsDefaultAccountPrompt.js +1 -1
- package/lib/prompts/uploadPrompt.js +1 -1
- package/lib/sandbox-create.js +1 -1
- package/lib/sandbox-sync.js +1 -1
- package/lib/sandboxes.js +1 -1
- package/lib/ui.js +7 -4
- package/package.json +8 -5
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const bodyParser = require('body-parser');
|
|
3
|
+
const cors = require('cors');
|
|
4
|
+
const { getProjectDetailUrl } = require('./projects');
|
|
5
|
+
|
|
6
|
+
const DEFAULT_PORT = 8080;
|
|
7
|
+
|
|
8
|
+
class DevServerManager {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.server = null;
|
|
11
|
+
this.devServers = {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async iterateDevServers(callback) {
|
|
15
|
+
const serverKeys = Object.keys(this.devServers);
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < serverKeys.length; i++) {
|
|
18
|
+
const serverKey = serverKeys[i];
|
|
19
|
+
const serverInterface = this.devServers[serverKey];
|
|
20
|
+
await callback(serverInterface, serverKey);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async start({ projectConfig, accountId, port }) {
|
|
25
|
+
const app = express();
|
|
26
|
+
|
|
27
|
+
// Install Middleware
|
|
28
|
+
app.use(bodyParser.json({ limit: '50mb' }));
|
|
29
|
+
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
|
30
|
+
app.use(cors());
|
|
31
|
+
|
|
32
|
+
// Configure
|
|
33
|
+
app.set('trust proxy', true);
|
|
34
|
+
|
|
35
|
+
// Initialize a base route
|
|
36
|
+
app.get('/', (req, res) => {
|
|
37
|
+
res.send('HubSpot local dev server');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Initialize URL redirects
|
|
41
|
+
app.get('/hs/project', (req, res) => {
|
|
42
|
+
res.redirect(getProjectDetailUrl(projectConfig.name, accountId));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Initialize component servers
|
|
46
|
+
await this.iterateDevServers(async (serverInterface, serverKey) => {
|
|
47
|
+
if (serverInterface.start) {
|
|
48
|
+
const serverApp = await serverInterface.start(serverKey);
|
|
49
|
+
app.use(`/${serverKey}`, serverApp);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Start server
|
|
54
|
+
this.server = app.listen(port || DEFAULT_PORT);
|
|
55
|
+
|
|
56
|
+
return `http://localhost:${this.server.address().port}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async notify() {
|
|
60
|
+
return { uploadRequired: true };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async execute() {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async cleanup() {
|
|
68
|
+
if (this.server) {
|
|
69
|
+
await this.server.close();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = new DevServerManager();
|
package/lib/LocalDevManager.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const chokidar = require('chokidar');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { default: PQueue } = require('p-queue');
|
|
4
|
-
const { i18n } = require('
|
|
4
|
+
const { i18n } = require('./lang');
|
|
5
5
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
6
6
|
const {
|
|
7
7
|
isSpecifiedError,
|
|
@@ -22,11 +22,9 @@ const {
|
|
|
22
22
|
queueBuild,
|
|
23
23
|
} = require('@hubspot/cli-lib/api/dfs');
|
|
24
24
|
const SpinniesManager = require('./SpinniesManager');
|
|
25
|
+
const DevServerManager = require('./DevServerManager');
|
|
25
26
|
const { EXIT_CODES } = require('./enums/exitCodes');
|
|
26
|
-
const {
|
|
27
|
-
getProjectDetailUrl,
|
|
28
|
-
pollProjectBuildAndDeploy,
|
|
29
|
-
} = require('./projects');
|
|
27
|
+
const { pollProjectBuildAndDeploy } = require('./projects');
|
|
30
28
|
const { uiAccountDescription, uiLink } = require('./ui');
|
|
31
29
|
|
|
32
30
|
const i18nKey = 'cli.lib.LocalDevManager';
|
|
@@ -45,6 +43,7 @@ const UPLOAD_PERMISSIONS = {
|
|
|
45
43
|
manual: 'manual',
|
|
46
44
|
never: 'never',
|
|
47
45
|
};
|
|
46
|
+
|
|
48
47
|
class LocalDevManager {
|
|
49
48
|
constructor(options) {
|
|
50
49
|
this.targetAccountId = options.targetAccountId;
|
|
@@ -53,7 +52,6 @@ class LocalDevManager {
|
|
|
53
52
|
this.uploadPermission =
|
|
54
53
|
options.uploadPermission || UPLOAD_PERMISSIONS.always;
|
|
55
54
|
this.debug = options.debug || false;
|
|
56
|
-
this.mockServers = options.mockServers || false;
|
|
57
55
|
this.projectSourceDir = path.join(
|
|
58
56
|
this.projectDir,
|
|
59
57
|
this.projectConfig.srcDir
|
|
@@ -64,6 +62,8 @@ class LocalDevManager {
|
|
|
64
62
|
this.standbyChanges = [];
|
|
65
63
|
this.debouncedBuild = null;
|
|
66
64
|
this.currentStagedBuildId = null;
|
|
65
|
+
this.port = options.port;
|
|
66
|
+
this.devServerPath = null;
|
|
67
67
|
|
|
68
68
|
if (!this.targetAccountId || !this.projectConfig || !this.projectDir) {
|
|
69
69
|
process.exit(EXIT_CODES.ERROR);
|
|
@@ -90,8 +90,9 @@ class LocalDevManager {
|
|
|
90
90
|
|
|
91
91
|
this.uploadQueue.start();
|
|
92
92
|
|
|
93
|
-
this.logConsoleHeader();
|
|
94
93
|
await this.startServers();
|
|
94
|
+
|
|
95
|
+
this.logConsoleHeader();
|
|
95
96
|
await this.startWatching();
|
|
96
97
|
this.updateKeypressListeners();
|
|
97
98
|
}
|
|
@@ -146,24 +147,27 @@ class LocalDevManager {
|
|
|
146
147
|
logConsoleHeader() {
|
|
147
148
|
this.spinnies.removeAll();
|
|
148
149
|
this.spinnies.add('devModeRunning', {
|
|
149
|
-
text: i18n(`${i18nKey}.running
|
|
150
|
+
text: i18n(`${i18nKey}.header.running`, {
|
|
151
|
+
accountIdentifier: uiAccountDescription(this.targetAccountId),
|
|
152
|
+
projectName: this.projectConfig.name,
|
|
153
|
+
}),
|
|
150
154
|
isParent: true,
|
|
151
155
|
category: 'header',
|
|
152
156
|
});
|
|
153
157
|
this.spinnies.add('devModeStatus', {
|
|
154
|
-
text: i18n(`${i18nKey}.status.clean`),
|
|
158
|
+
text: i18n(`${i18nKey}.header.status.clean`),
|
|
155
159
|
status: 'non-spinnable',
|
|
156
160
|
indent: 1,
|
|
157
161
|
category: 'header',
|
|
158
162
|
});
|
|
159
|
-
const projectDetailUrl = getProjectDetailUrl(
|
|
160
|
-
this.projectConfig.name,
|
|
161
|
-
this.targetAccountId
|
|
162
|
-
);
|
|
163
163
|
this.spinnies.add('viewInHubSpotLink', {
|
|
164
|
-
text: uiLink(
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
text: uiLink(
|
|
165
|
+
i18n(`${i18nKey}.header.viewInHubSpotLink`),
|
|
166
|
+
this.generateLocalURL(`/hs/project`),
|
|
167
|
+
{
|
|
168
|
+
inSpinnies: true,
|
|
169
|
+
}
|
|
170
|
+
),
|
|
167
171
|
status: 'non-spinnable',
|
|
168
172
|
indent: 1,
|
|
169
173
|
category: 'header',
|
|
@@ -174,7 +178,7 @@ class LocalDevManager {
|
|
|
174
178
|
category: 'header',
|
|
175
179
|
});
|
|
176
180
|
this.spinnies.add('keypressMessage', {
|
|
177
|
-
text: i18n(`${i18nKey}.quitHelper`),
|
|
181
|
+
text: i18n(`${i18nKey}.header.quitHelper`),
|
|
178
182
|
status: 'non-spinnable',
|
|
179
183
|
indent: 1,
|
|
180
184
|
category: 'header',
|
|
@@ -223,9 +227,13 @@ class LocalDevManager {
|
|
|
223
227
|
});
|
|
224
228
|
}
|
|
225
229
|
|
|
230
|
+
generateLocalURL(path) {
|
|
231
|
+
return this.devServerPath ? `${this.devServerPath}${path}` : null;
|
|
232
|
+
}
|
|
233
|
+
|
|
226
234
|
updateDevModeStatus(langKey) {
|
|
227
235
|
this.spinnies.update('devModeStatus', {
|
|
228
|
-
text: i18n(`${i18nKey}.status.${langKey}`),
|
|
236
|
+
text: i18n(`${i18nKey}.header.status.${langKey}`),
|
|
229
237
|
status: 'non-spinnable',
|
|
230
238
|
noIndent: true,
|
|
231
239
|
});
|
|
@@ -290,11 +298,13 @@ class LocalDevManager {
|
|
|
290
298
|
remotePath: path.relative(this.projectSourceDir, filePath),
|
|
291
299
|
};
|
|
292
300
|
|
|
293
|
-
const
|
|
301
|
+
const notifyResponse = await this.notifyServers(changeInfo);
|
|
294
302
|
|
|
295
|
-
if (
|
|
303
|
+
if (!notifyResponse.uploadRequired) {
|
|
296
304
|
this.updateDevModeStatus('supportedChange');
|
|
297
305
|
this.addChangeToStandbyQueue({ ...changeInfo, supported: true });
|
|
306
|
+
|
|
307
|
+
await this.executeServers(notifyResponse, changeInfo);
|
|
298
308
|
return;
|
|
299
309
|
}
|
|
300
310
|
|
|
@@ -503,23 +513,24 @@ class LocalDevManager {
|
|
|
503
513
|
}
|
|
504
514
|
|
|
505
515
|
async startServers() {
|
|
506
|
-
|
|
507
|
-
|
|
516
|
+
this.devServerPath = await DevServerManager.start({
|
|
517
|
+
accountId: this.targetAccountId,
|
|
518
|
+
projectConfig: this.projectConfig,
|
|
519
|
+
port: this.port,
|
|
520
|
+
});
|
|
508
521
|
}
|
|
509
522
|
|
|
510
523
|
async notifyServers(changeInfo) {
|
|
511
|
-
const
|
|
524
|
+
const notifyResponse = await DevServerManager.notify(changeInfo);
|
|
525
|
+
return notifyResponse;
|
|
526
|
+
}
|
|
512
527
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
return !remotePath.endsWith('app.json');
|
|
516
|
-
}
|
|
517
|
-
return false;
|
|
528
|
+
async executeServers(notifyResponse, changeInfo) {
|
|
529
|
+
await DevServerManager.execute(notifyResponse, changeInfo);
|
|
518
530
|
}
|
|
519
531
|
|
|
520
532
|
async cleanupServers() {
|
|
521
|
-
|
|
522
|
-
return;
|
|
533
|
+
await DevServerManager.cleanup();
|
|
523
534
|
}
|
|
524
535
|
}
|
|
525
536
|
|
package/lib/commonOpts.js
CHANGED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const helpers = require('./interpolationHelpers');
|
|
2
|
+
const delimiters = {
|
|
3
|
+
interpolation: {
|
|
4
|
+
start: '{{',
|
|
5
|
+
end: '}}',
|
|
6
|
+
},
|
|
7
|
+
helpers: {
|
|
8
|
+
start: '#',
|
|
9
|
+
end: '/',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const isHelperIdentifier = identifier => {
|
|
14
|
+
return (
|
|
15
|
+
identifier.startsWith(delimiters.helpers.start) ||
|
|
16
|
+
identifier.startsWith(delimiters.helpers.end)
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const generateReplaceFn = (matchedText, startIndex, replacementString) => {
|
|
21
|
+
return currentStringValue =>
|
|
22
|
+
`${currentStringValue.slice(0, startIndex)}${replacementString ||
|
|
23
|
+
''}${currentStringValue.slice(startIndex + matchedText.length)}`;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Interpolate a string with data
|
|
28
|
+
* @param {string} stringValue - The string to interpolate
|
|
29
|
+
* @param {object} interpolationData - The data to interpolate with
|
|
30
|
+
* @returns {string} - The interpolated string
|
|
31
|
+
* @example
|
|
32
|
+
* interpolation('Hello {{name}}', { name: 'World' })
|
|
33
|
+
* // 'Hello World'
|
|
34
|
+
*/
|
|
35
|
+
const interpolation = (stringValue, interpolationData) => {
|
|
36
|
+
const interpolationIdentifierRegEx = new RegExp(
|
|
37
|
+
`${delimiters.interpolation.start}(.*?)${delimiters.interpolation.end}`,
|
|
38
|
+
'g'
|
|
39
|
+
);
|
|
40
|
+
const replaceQueue = [];
|
|
41
|
+
let match;
|
|
42
|
+
|
|
43
|
+
// while & reduce necessary because RegExp.exec is stateful and only runs
|
|
44
|
+
// from beginning to end of string
|
|
45
|
+
while ((match = interpolationIdentifierRegEx.exec(stringValue)) != null) {
|
|
46
|
+
const { 0: matchedText, 1: rawIdentifier, index } = match;
|
|
47
|
+
const identifier = rawIdentifier.trim();
|
|
48
|
+
|
|
49
|
+
if (identifier && !isHelperIdentifier(identifier)) {
|
|
50
|
+
replaceQueue.unshift(
|
|
51
|
+
generateReplaceFn(matchedText, index, interpolationData[identifier])
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const compiledString = replaceQueue.reduce(
|
|
57
|
+
(currentValue, replaceFn) => replaceFn(currentValue),
|
|
58
|
+
stringValue
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return compiledString;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Compile a string using a specified helper function
|
|
66
|
+
* @param {string} stringValue - The string to modify
|
|
67
|
+
* @param {object} helperIdentifier - Helper name
|
|
68
|
+
* @param {function} helperFn - Helper function to call on string
|
|
69
|
+
* @returns {string} - The modified string
|
|
70
|
+
* @example
|
|
71
|
+
* compileHelper('White {{#yellow}}yellow{{/yellow}}', 'yellow', (string) => { chalk.reset.yellow(string) }))))
|
|
72
|
+
* // 'White yellow' (with 'yellow' colored yellow)
|
|
73
|
+
*/
|
|
74
|
+
const compileHelper = (stringValue, helperIdentifier, helperFn) => {
|
|
75
|
+
const helperIdentifierRegEx = new RegExp(
|
|
76
|
+
`${delimiters.interpolation.start}(${delimiters.helpers.start}${helperIdentifier})${delimiters.interpolation.end}(.*?)${delimiters.interpolation.start}(${delimiters.helpers.end}${helperIdentifier})${delimiters.interpolation.end}`,
|
|
77
|
+
'g'
|
|
78
|
+
);
|
|
79
|
+
const replaceQueue = [];
|
|
80
|
+
let match;
|
|
81
|
+
|
|
82
|
+
// while & reduce necessary because RegExp.exec is stateful and only runs
|
|
83
|
+
// from beginning to end of string
|
|
84
|
+
while ((match = helperIdentifierRegEx.exec(stringValue)) != null) {
|
|
85
|
+
const {
|
|
86
|
+
0: matchedText,
|
|
87
|
+
1: rawHelperIdentifierStart,
|
|
88
|
+
2: innerText,
|
|
89
|
+
index,
|
|
90
|
+
} = match;
|
|
91
|
+
const identifier = rawHelperIdentifierStart
|
|
92
|
+
.replace(delimiters.helpers.start, '')
|
|
93
|
+
.trim();
|
|
94
|
+
|
|
95
|
+
if (identifier && helperFn) {
|
|
96
|
+
replaceQueue.unshift(
|
|
97
|
+
generateReplaceFn(matchedText, index, helperFn(innerText))
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const compiledString = replaceQueue.reduce(
|
|
103
|
+
(currentValue, replaceFn) => replaceFn(currentValue),
|
|
104
|
+
stringValue
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return compiledString;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const compileHelpers = stringValue => {
|
|
111
|
+
return Object.keys(helpers).reduce((currentStringValue, helperIdentifier) => {
|
|
112
|
+
return compileHelper(
|
|
113
|
+
currentStringValue,
|
|
114
|
+
helperIdentifier,
|
|
115
|
+
helpers[helperIdentifier]
|
|
116
|
+
);
|
|
117
|
+
}, stringValue);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Interpolate a string with data and compile helpers on the string
|
|
122
|
+
* @param {string} stringValue - The string to interpolate
|
|
123
|
+
* @param {object} interpolationData - The data to interpolate with
|
|
124
|
+
* @returns {string} - The interpolated and helper-compiled string
|
|
125
|
+
* @example
|
|
126
|
+
* interpolateAndCompile('Some {{#bold}}{{text}}{{/bold}} text', { text: 'awesomely bold' })
|
|
127
|
+
* // 'Some awsomely bold text' (with the words 'awesomely bold' in bold)
|
|
128
|
+
*/
|
|
129
|
+
const interpolate = (stringValue, interpolationData) => {
|
|
130
|
+
const interpolatedString = interpolation(stringValue, interpolationData);
|
|
131
|
+
const helperCompiledString = compileHelpers(interpolatedString);
|
|
132
|
+
return helperCompiledString;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
interpolate,
|
|
137
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* These helper methods are used to modify text output within the CLI. They
|
|
5
|
+
* should all take in a string value and output a modified string value.
|
|
6
|
+
*/
|
|
7
|
+
module.exports = {
|
|
8
|
+
bold: function(stringValue) {
|
|
9
|
+
return chalk.bold(stringValue);
|
|
10
|
+
},
|
|
11
|
+
yellow: function(stringValue) {
|
|
12
|
+
return chalk.reset.yellow(stringValue);
|
|
13
|
+
},
|
|
14
|
+
green: function(stringValue) {
|
|
15
|
+
return chalk.reset.green(stringValue);
|
|
16
|
+
},
|
|
17
|
+
red: function(stringValue) {
|
|
18
|
+
return chalk.reset.red(stringValue);
|
|
19
|
+
},
|
|
20
|
+
cyan: function(stringValue) {
|
|
21
|
+
return chalk.cyan(stringValue);
|
|
22
|
+
},
|
|
23
|
+
};
|
package/lib/lang.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const util = require('util');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const yaml = require('js-yaml');
|
|
5
|
+
const { logger } = require('@hubspot/cli-lib/logger');
|
|
6
|
+
const { interpolate } = require('./interpolation');
|
|
7
|
+
|
|
8
|
+
const MISSING_LANGUAGE_DATA_PREFIX = '[Missing language data]';
|
|
9
|
+
|
|
10
|
+
let locale;
|
|
11
|
+
let languageObj;
|
|
12
|
+
|
|
13
|
+
const loadLanguageFromYaml = () => {
|
|
14
|
+
if (languageObj) return;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const nodeLocale = Intl.DateTimeFormat()
|
|
18
|
+
.resolvedOptions()
|
|
19
|
+
.locale.split('-')[0];
|
|
20
|
+
const languageFilePath = path.join(
|
|
21
|
+
__dirname,
|
|
22
|
+
`../lang/${nodeLocale}.lyaml`
|
|
23
|
+
);
|
|
24
|
+
const languageFileExists = fs.existsSync(languageFilePath);
|
|
25
|
+
|
|
26
|
+
// Fall back to using the default language file
|
|
27
|
+
locale = languageFileExists ? nodeLocale : 'en';
|
|
28
|
+
languageObj = yaml.load(
|
|
29
|
+
fs.readFileSync(path.join(__dirname, `../lang/${locale}.lyaml`), 'utf8')
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
logger.debug(
|
|
33
|
+
'Loaded language data: ',
|
|
34
|
+
util.inspect(languageObj, true, 999, true)
|
|
35
|
+
);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
logger.error('Error loading language data: ', e);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const getTextValue = lookupDotNotation => {
|
|
42
|
+
const lookupProps = [locale, ...lookupDotNotation.split('.')];
|
|
43
|
+
const missingTextData = `${MISSING_LANGUAGE_DATA_PREFIX}: ${lookupProps.join(
|
|
44
|
+
'.'
|
|
45
|
+
)}`;
|
|
46
|
+
let textValue = languageObj;
|
|
47
|
+
let previouslyCheckedProp = lookupProps[0];
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
lookupProps.forEach(prop => {
|
|
51
|
+
textValue = textValue[prop];
|
|
52
|
+
previouslyCheckedProp = prop;
|
|
53
|
+
});
|
|
54
|
+
} catch (e) {
|
|
55
|
+
logger.error(
|
|
56
|
+
`Unable to access language property: ${lookupProps.join(
|
|
57
|
+
'.'
|
|
58
|
+
)}. Failed to access prop "${previouslyCheckedProp}".`
|
|
59
|
+
);
|
|
60
|
+
return missingTextData;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!textValue) {
|
|
64
|
+
return missingTextData;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return textValue;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const i18n = (lookupDotNotation, options = {}) => {
|
|
71
|
+
if (!languageObj) {
|
|
72
|
+
loadLanguageFromYaml();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof lookupDotNotation !== 'string') {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`i18n must be passed a string value for lookupDotNotation, received ${typeof lookupDotNotation}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const textValue = getTextValue(lookupDotNotation);
|
|
82
|
+
const shouldInterpolate = !textValue.startsWith(MISSING_LANGUAGE_DATA_PREFIX);
|
|
83
|
+
|
|
84
|
+
return shouldInterpolate ? interpolate(textValue, options) : textValue;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const setLangData = (newLocale, newLangObj) => {
|
|
88
|
+
locale = newLocale;
|
|
89
|
+
languageObj = newLangObj;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
i18n,
|
|
94
|
+
setLangData,
|
|
95
|
+
};
|
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
getValidationStatus,
|
|
7
7
|
getValidationResults,
|
|
8
8
|
} = require('@hubspot/cli-lib/api/marketplaceValidation');
|
|
9
|
-
const { i18n } = require('
|
|
9
|
+
const { i18n } = require('./lang');
|
|
10
10
|
const { EXIT_CODES } = require('./enums/exitCodes');
|
|
11
11
|
|
|
12
12
|
const SLEEP_TIME = 2000;
|
package/lib/projects.js
CHANGED
|
@@ -37,7 +37,7 @@ const { downloadGitHubRepoContents } = require('@hubspot/cli-lib/github');
|
|
|
37
37
|
const { promptUser } = require('./prompts/promptUtils');
|
|
38
38
|
const { EXIT_CODES } = require('./enums/exitCodes');
|
|
39
39
|
const { uiLine, uiLink, uiAccountDescription } = require('../lib/ui');
|
|
40
|
-
const { i18n } = require('
|
|
40
|
+
const { i18n } = require('./lang');
|
|
41
41
|
const SpinniesManager = require('./SpinniesManager');
|
|
42
42
|
const {
|
|
43
43
|
isSpecifiedError,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { updateDefaultAccount } = require('@hubspot/cli-lib/lib/config');
|
|
2
2
|
const { promptUser } = require('./promptUtils');
|
|
3
|
-
const { i18n } = require('
|
|
3
|
+
const { i18n } = require('../lang');
|
|
4
4
|
const { getAccountName } = require('../sandboxes');
|
|
5
5
|
|
|
6
6
|
const mapAccountChoices = portals =>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const { promptUser } = require('./promptUtils');
|
|
4
|
-
const { i18n } = require('
|
|
4
|
+
const { i18n } = require('../lang');
|
|
5
5
|
const escapeRegExp = require('@hubspot/cli-lib/lib/escapeRegExp');
|
|
6
6
|
const i18nKey = 'cli.lib.prompts.uploadPrompt';
|
|
7
7
|
const FIELDS_FILES = ['fields.json', 'fields.js', 'fields.cjs', 'fields.mjs'];
|
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
} = require('@hubspot/cli-lib/lib/constants');
|
|
7
7
|
const { promptUser } = require('./promptUtils');
|
|
8
8
|
const { fetchJsonFromRepository } = require('@hubspot/cli-lib/github');
|
|
9
|
-
const { i18n } = require('
|
|
9
|
+
const { i18n } = require('../lang');
|
|
10
10
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
11
11
|
const { EXIT_CODES } = require('../../lib/enums/exitCodes');
|
|
12
12
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { promptUser } = require('./promptUtils');
|
|
2
2
|
const { getAccountId } = require('@hubspot/cli-lib/lib/config');
|
|
3
3
|
const { fetchProjects } = require('@hubspot/cli-lib/api/dfs');
|
|
4
|
-
const { i18n } = require('
|
|
4
|
+
const { i18n } = require('../lang');
|
|
5
5
|
|
|
6
6
|
const i18nKey = 'cli.lib.prompts.downloadProjectPrompt';
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { accountNameExistsInConfig } = require('@hubspot/cli-lib/lib/config');
|
|
2
2
|
const { STRING_WITH_NO_SPACES_REGEX } = require('../regex');
|
|
3
3
|
const { promptUser } = require('./promptUtils');
|
|
4
|
-
const { i18n } = require('
|
|
4
|
+
const { i18n } = require('../lang');
|
|
5
5
|
|
|
6
6
|
const i18nKey = 'cli.lib.prompts.enterAccountNamePrompt';
|
|
7
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { promptUser } = require('./promptUtils');
|
|
2
|
-
const { i18n } = require('
|
|
2
|
+
const { i18n } = require('../lang');
|
|
3
3
|
const { FEEDBACK_OPTIONS } = require('@hubspot/cli-lib/lib/constants');
|
|
4
4
|
|
|
5
5
|
const i18nKey = 'cli.lib.prompts.feedbackPrompt';
|
|
@@ -8,7 +8,7 @@ const { getHubSpotWebsiteOrigin } = require('@hubspot/cli-lib/lib/urls');
|
|
|
8
8
|
const { logger } = require('@hubspot/cli-lib/logger');
|
|
9
9
|
const { promptUser } = require('./promptUtils');
|
|
10
10
|
const { accountNamePrompt } = require('./enterAccountNamePrompt');
|
|
11
|
-
const { i18n } = require('
|
|
11
|
+
const { i18n } = require('../lang');
|
|
12
12
|
const { uiInfoSection } = require('../ui');
|
|
13
13
|
const { EXIT_CODES } = require('../enums/exitCodes');
|
|
14
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { promptUser } = require('./promptUtils');
|
|
2
2
|
const { fetchJsonFromRepository } = require('@hubspot/cli-lib/github');
|
|
3
|
-
const { i18n } = require('
|
|
3
|
+
const { i18n } = require('../lang');
|
|
4
4
|
const { PROJECT_COMPONENT_TYPES } = require('@hubspot/cli-lib/lib/constants');
|
|
5
5
|
|
|
6
6
|
const i18nKey = 'cli.lib.prompts.projectAddPrompt';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { promptUser } = require('./promptUtils');
|
|
2
|
-
const { i18n } = require('
|
|
2
|
+
const { i18n } = require('../lang');
|
|
3
3
|
const { uiAccountDescription } = require('../ui');
|
|
4
4
|
const { isSandbox, getAccountName } = require('../sandboxes');
|
|
5
5
|
const { getAccountId } = require('@hubspot/cli-lib');
|