@hubspot/cli 7.10.0 → 7.11.0-experimental.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/bin/cli.js +5 -4
- package/commands/__tests__/getStarted.test.js +10 -0
- package/commands/__tests__/project.test.js +3 -0
- package/commands/account/__tests__/rename.test.js +10 -3
- package/commands/account/auth.js +10 -14
- package/commands/account/clean.js +11 -19
- package/commands/account/createOverride.js +15 -11
- package/commands/account/info.js +8 -5
- package/commands/account/list.js +15 -19
- package/commands/account/remove.js +23 -22
- package/commands/account/removeOverride.js +6 -6
- package/commands/account/rename.js +2 -2
- package/commands/account/use.js +19 -8
- package/commands/app/__tests__/migrate.test.js +8 -4
- package/commands/app/migrate.js +2 -2
- package/commands/auth.js +18 -14
- package/commands/config/migrate.js +5 -5
- package/commands/customObject/createSchema.js +2 -3
- package/commands/customObject/updateSchema.js +2 -3
- package/commands/getStarted.js +2 -3
- package/commands/hubdb/__tests__/list.test.js +1 -0
- package/commands/hubdb/list.js +2 -2
- package/commands/init.js +36 -32
- package/commands/project/__tests__/deploy.test.js +15 -10
- package/commands/project/__tests__/devUnifiedFlow.test.js +6 -4
- package/commands/project/__tests__/lint.test.js +709 -0
- package/commands/project/__tests__/logs.test.js +4 -0
- package/commands/project/__tests__/validate.test.js +2 -2
- package/commands/project/cloneApp.js +2 -2
- package/commands/project/create.js +20 -14
- package/commands/project/deploy.js +2 -2
- package/commands/project/dev/deprecatedFlow.js +4 -5
- package/commands/project/dev/index.js +6 -3
- package/commands/project/dev/unifiedFlow.js +11 -6
- package/commands/project/lint.d.ts +6 -0
- package/commands/project/lint.js +178 -0
- package/commands/project/logs.js +2 -3
- package/commands/project/migrate.js +4 -13
- package/commands/project/profile/add.js +6 -7
- package/commands/project/profile/delete.js +2 -2
- package/commands/project/upload.js +2 -2
- package/commands/project/validate.js +2 -2
- package/commands/project.js +2 -0
- package/commands/sandbox/__tests__/create.test.js +14 -5
- package/commands/sandbox/create.js +4 -5
- package/commands/sandbox/delete.js +23 -20
- package/commands/testAccount/create.js +2 -2
- package/commands/testAccount/delete.js +9 -8
- package/lang/en.d.ts +53 -12
- package/lang/en.js +63 -16
- package/lib/__tests__/buildAccount.test.js +22 -30
- package/lib/__tests__/commonOpts.test.js +9 -13
- package/lib/__tests__/developerTestAccounts.test.js +29 -17
- package/lib/__tests__/importData.test.js +20 -10
- package/lib/__tests__/oauth.test.js +19 -8
- package/lib/__tests__/sandboxSync.test.js +33 -11
- package/lib/__tests__/sandboxes.test.js +30 -19
- package/lib/__tests__/usageTracking.test.js +10 -10
- package/lib/__tests__/validation.test.js +32 -32
- package/lib/accountTypes.d.ts +9 -9
- package/lib/accountTypes.js +2 -4
- package/lib/app/__tests__/migrate.test.js +15 -0
- package/lib/app/__tests__/migrate_legacy.test.js +9 -0
- package/lib/app/migrate_legacy.d.ts +2 -2
- package/lib/buildAccount.d.ts +4 -4
- package/lib/buildAccount.js +7 -14
- package/lib/commonOpts.js +3 -3
- package/lib/configMigrate.d.ts +2 -2
- package/lib/configMigrate.js +42 -18
- package/lib/configOptions.js +3 -2
- package/lib/developerTestAccounts.d.ts +3 -3
- package/lib/developerTestAccounts.js +4 -7
- package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -1
- package/lib/doctor/DiagnosticInfoBuilder.js +9 -6
- package/lib/doctor/Doctor.js +4 -3
- package/lib/doctor/__tests__/Diagnosis.test.js +4 -3
- package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +17 -9
- package/lib/doctor/__tests__/Doctor.test.js +14 -0
- package/lib/errorHandlers/index.js +8 -3
- package/lib/importData.js +8 -7
- package/lib/links.js +5 -5
- package/lib/middleware/{__test__ → __tests__}/commandTargetingUtils.test.js +3 -3
- package/lib/middleware/{__test__ → __tests__}/configMiddleware.test.js +23 -22
- package/lib/middleware/{__test__ → __tests__}/gitMiddleware.test.js +9 -7
- package/lib/middleware/autoUpdateMiddleware.js +34 -23
- package/lib/middleware/commandTargetingUtils.js +3 -2
- package/lib/middleware/configMiddleware.d.ts +6 -1
- package/lib/middleware/configMiddleware.js +36 -15
- package/lib/middleware/fireAlarmMiddleware.js +4 -15
- package/lib/middleware/gitMiddleware.js +8 -4
- package/lib/oauth.d.ts +2 -2
- package/lib/oauth.js +8 -10
- package/lib/projects/__tests__/AppDevModeInterface.test.js +17 -6
- package/lib/projects/__tests__/DevServerManager.test.js +1 -0
- package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
- package/lib/projects/__tests__/components.test.js +2 -22
- package/lib/projects/__tests__/deploy.test.js +16 -13
- package/lib/projects/__tests__/uieLinting.test.js +640 -0
- package/lib/projects/add/__tests__/legacyAddComponent.test.js +1 -1
- package/lib/projects/add/__tests__/v2AddComponent.test.js +30 -4
- package/lib/projects/add/legacyAddComponent.js +1 -1
- package/lib/projects/add/v2AddComponent.js +16 -5
- package/lib/projects/components.d.ts +8 -1
- package/lib/projects/components.js +91 -8
- package/lib/projects/create/__tests__/v2.test.js +11 -0
- package/lib/projects/deploy.js +21 -8
- package/lib/projects/localDev/AppDevModeInterface.js +2 -2
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +11 -3
- package/lib/projects/localDev/LocalDevLogger.js +4 -4
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
- package/lib/projects/localDev/helpers/account.d.ts +10 -10
- package/lib/projects/localDev/helpers/account.js +6 -11
- package/lib/projects/localDev/helpers/process.js +5 -3
- package/lib/projects/uieLinting.d.ts +33 -0
- package/lib/projects/uieLinting.js +222 -0
- package/lib/projects/urls.js +5 -6
- package/lib/prompts/__tests__/downloadProjectPrompt.test.js +7 -5
- package/lib/prompts/accountNamePrompt.js +3 -3
- package/lib/prompts/accountsPrompt.d.ts +1 -1
- package/lib/prompts/accountsPrompt.js +6 -7
- package/lib/prompts/confirmImportDataPrompt.js +2 -2
- package/lib/prompts/downloadProjectPrompt.d.ts +1 -0
- package/lib/prompts/downloadProjectPrompt.js +5 -2
- package/lib/prompts/importDataTestAccountSelectPrompt.js +4 -5
- package/lib/prompts/personalAccessKeyPrompt.js +2 -2
- package/lib/prompts/projectDevTargetAccountPrompt.d.ts +3 -3
- package/lib/prompts/projectDevTargetAccountPrompt.js +5 -7
- package/lib/prompts/sandboxesPrompt.js +7 -8
- package/lib/prompts/setAsDefaultAccountPrompt.js +7 -6
- package/lib/sandboxSync.d.ts +2 -2
- package/lib/sandboxSync.js +3 -9
- package/lib/sandboxes.d.ts +4 -4
- package/lib/sandboxes.js +6 -11
- package/lib/serverlessLogs.js +2 -2
- package/lib/theme/__tests__/migrate.test.js +15 -0
- package/lib/ui/SpinniesManager.d.ts +5 -7
- package/lib/ui/SpinniesManager.js +9 -12
- package/lib/ui/__tests__/SpinniesManager.test.d.ts +1 -0
- package/lib/ui/__tests__/SpinniesManager.test.js +489 -0
- package/lib/ui/index.js +6 -3
- package/lib/usageTracking.js +15 -8
- package/lib/validation.js +13 -11
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +4 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +4 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +4 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +4 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +3 -1
- package/mcp-server/tools/cms/HsListTool.js +3 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -0
- package/mcp-server/tools/index.js +4 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +4 -2
- package/mcp-server/tools/project/CreateProjectTool.js +4 -2
- package/mcp-server/tools/project/CreateTestAccountTool.js +17 -7
- package/mcp-server/tools/project/DeployProjectTool.js +3 -1
- package/mcp-server/tools/project/DocFetchTool.js +6 -4
- package/mcp-server/tools/project/DocsSearchTool.d.ts +1 -1
- package/mcp-server/tools/project/DocsSearchTool.js +10 -8
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -7
- package/mcp-server/tools/project/GetApplicationInfoTool.js +8 -6
- package/mcp-server/tools/project/GetBuildLogsTool.d.ts +26 -0
- package/mcp-server/tools/project/GetBuildLogsTool.js +125 -0
- package/mcp-server/tools/project/GetBuildStatusTool.d.ts +26 -0
- package/mcp-server/tools/project/GetBuildStatusTool.js +166 -0
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +1 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +1 -1
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +5 -3
- package/mcp-server/tools/project/UploadProjectTools.js +3 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +4 -2
- package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +12 -2
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +5 -1
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +23 -11
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +7 -5
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +7 -5
- package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetBuildLogsTool.test.js +305 -0
- package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.d.ts +1 -0
- package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +240 -0
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -6
- package/mcp-server/utils/__tests__/content.test.js +21 -20
- package/mcp-server/utils/__tests__/feedbackTracking.test.js +34 -28
- package/mcp-server/utils/config.d.ts +1 -0
- package/mcp-server/utils/config.js +10 -0
- package/mcp-server/utils/content.d.ts +1 -1
- package/mcp-server/utils/content.js +2 -2
- package/mcp-server/utils/feedbackTracking.d.ts +1 -1
- package/mcp-server/utils/feedbackTracking.js +3 -3
- package/mcp-server/utils/toolUsageTracking.js +4 -3
- package/package.json +9 -9
- package/ui/components/BoxWithTitle.d.ts +2 -1
- package/ui/components/BoxWithTitle.js +2 -2
- package/ui/components/StatusMessageBoxes.d.ts +5 -4
- package/ui/components/StatusMessageBoxes.js +8 -8
- package/lib/middleware/__test__/notificationsMiddleware.test.js +0 -8
- package/lib/middleware/notificationsMiddleware.d.ts +0 -1
- package/lib/middleware/notificationsMiddleware.js +0 -28
- package/lib/ui/boxen.d.ts +0 -5
- package/lib/ui/boxen.js +0 -26
- package/mcp-server/utils/__tests__/cliConfig.test.js +0 -110
- package/mcp-server/utils/cliConfig.d.ts +0 -1
- package/mcp-server/utils/cliConfig.js +0 -12
- /package/{lib/middleware/__test__/commandTargetingUtils.test.d.ts → commands/project/__tests__/lint.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/configMiddleware.test.d.ts → __tests__/commandTargetingUtils.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/gitMiddleware.test.d.ts → __tests__/configMiddleware.test.d.ts} +0 -0
- /package/lib/middleware/{__test__/notificationsMiddleware.test.d.ts → __tests__/gitMiddleware.test.d.ts} +0 -0
- /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.d.ts +0 -0
- /package/lib/middleware/{__test__ → __tests__}/requestMiddleware.test.js +0 -0
- /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.d.ts +0 -0
- /package/lib/middleware/{__test__ → __tests__}/yargsChecksMiddleware.test.js +0 -0
- /package/{mcp-server/utils/__tests__/cliConfig.test.d.ts → lib/projects/__tests__/uieLinting.test.d.ts} +0 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import SpinniesManager from '../SpinniesManager.js';
|
|
3
|
+
// Mock dependencies
|
|
4
|
+
vi.mock('readline', () => ({
|
|
5
|
+
default: {
|
|
6
|
+
clearScreenDown: vi.fn(),
|
|
7
|
+
moveCursor: vi.fn(),
|
|
8
|
+
clearLine: vi.fn(),
|
|
9
|
+
},
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('cli-cursor', () => ({
|
|
12
|
+
default: {
|
|
13
|
+
hide: vi.fn(),
|
|
14
|
+
show: vi.fn(),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
vi.mock('../logger.js', () => ({
|
|
18
|
+
uiLogger: {
|
|
19
|
+
debug: vi.fn(),
|
|
20
|
+
log: vi.fn(),
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
describe('SpinniesManager', () => {
|
|
24
|
+
let spinniesManager;
|
|
25
|
+
let mockUiLogger;
|
|
26
|
+
beforeEach(async () => {
|
|
27
|
+
// Reset the singleton instance before each test
|
|
28
|
+
vi.clearAllMocks();
|
|
29
|
+
// Get the mocked logger
|
|
30
|
+
const loggerModule = await import('../logger.js');
|
|
31
|
+
mockUiLogger = loggerModule.uiLogger;
|
|
32
|
+
// Mock process.stderr
|
|
33
|
+
Object.defineProperty(process, 'stderr', {
|
|
34
|
+
value: {
|
|
35
|
+
write: vi.fn(),
|
|
36
|
+
isTTY: true,
|
|
37
|
+
columns: 80,
|
|
38
|
+
},
|
|
39
|
+
writable: true,
|
|
40
|
+
});
|
|
41
|
+
// Mock process.env
|
|
42
|
+
delete process.env.CI;
|
|
43
|
+
spinniesManager = SpinniesManager;
|
|
44
|
+
});
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
vi.restoreAllMocks();
|
|
47
|
+
});
|
|
48
|
+
describe('initialization', () => {
|
|
49
|
+
it('should initialize with default options', () => {
|
|
50
|
+
spinniesManager.init();
|
|
51
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('should initialize with custom options', () => {
|
|
54
|
+
const customOptions = {
|
|
55
|
+
spinnerColor: 'red',
|
|
56
|
+
succeedColor: 'blue',
|
|
57
|
+
failColor: 'yellow',
|
|
58
|
+
};
|
|
59
|
+
spinniesManager.init(customOptions);
|
|
60
|
+
spinniesManager.add('test', { text: 'Test spinner' });
|
|
61
|
+
const spinner = spinniesManager.pick('test');
|
|
62
|
+
expect(spinner).toBeDefined();
|
|
63
|
+
});
|
|
64
|
+
it('should set disableSpins to true in CI environment', () => {
|
|
65
|
+
process.env.CI = 'true';
|
|
66
|
+
spinniesManager.init();
|
|
67
|
+
spinniesManager.add('test', { text: 'Test spinner' });
|
|
68
|
+
const spinner = spinniesManager.pick('test');
|
|
69
|
+
expect(spinner).toBeDefined();
|
|
70
|
+
});
|
|
71
|
+
it('should use fallback spinner when terminal does not support unicode', () => {
|
|
72
|
+
Object.defineProperty(process, 'platform', {
|
|
73
|
+
value: 'win32',
|
|
74
|
+
writable: true,
|
|
75
|
+
});
|
|
76
|
+
delete process.env.TERM_PROGRAM;
|
|
77
|
+
delete process.env.WT_SESSION;
|
|
78
|
+
spinniesManager.init();
|
|
79
|
+
spinniesManager.add('test', { text: 'Test spinner' });
|
|
80
|
+
const spinner = spinniesManager.pick('test');
|
|
81
|
+
expect(spinner).toBeDefined();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('spinner management', () => {
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
spinniesManager.init();
|
|
87
|
+
});
|
|
88
|
+
describe('add', () => {
|
|
89
|
+
it('should add a spinner with name', () => {
|
|
90
|
+
spinniesManager.add('test-spinner', {
|
|
91
|
+
text: 'Loading...',
|
|
92
|
+
});
|
|
93
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
94
|
+
expect(spinner).toBeDefined();
|
|
95
|
+
expect(spinner?.text).toBe('Loading...');
|
|
96
|
+
expect(spinner?.status).toBe('spinning');
|
|
97
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('should add a spinner without name and generate one', () => {
|
|
100
|
+
spinniesManager.add('', { text: 'Loading...' });
|
|
101
|
+
// Since we can't get the generated name directly, check that a spinner was added
|
|
102
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it('should use spinner name as text if no text provided', () => {
|
|
105
|
+
spinniesManager.add('test-spinner');
|
|
106
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
107
|
+
expect(spinner?.text).toBe('test-spinner');
|
|
108
|
+
});
|
|
109
|
+
it('should add multiple spinners', () => {
|
|
110
|
+
spinniesManager.add('spinner1', { text: 'First' });
|
|
111
|
+
spinniesManager.add('spinner2', { text: 'Second' });
|
|
112
|
+
const spinner1 = spinniesManager.pick('spinner1');
|
|
113
|
+
const spinner2 = spinniesManager.pick('spinner2');
|
|
114
|
+
expect(spinner1).toBeDefined();
|
|
115
|
+
expect(spinner2).toBeDefined();
|
|
116
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('pick', () => {
|
|
120
|
+
it('should return spinner by name', () => {
|
|
121
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
122
|
+
const picked = spinniesManager.pick('test-spinner');
|
|
123
|
+
expect(picked).toBeDefined();
|
|
124
|
+
expect(picked?.text).toBe('Loading...');
|
|
125
|
+
});
|
|
126
|
+
it('should return undefined for non-existent spinner', () => {
|
|
127
|
+
const picked = spinniesManager.pick('non-existent');
|
|
128
|
+
expect(picked).toBeUndefined();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe('update', () => {
|
|
132
|
+
it('should update spinner properties', () => {
|
|
133
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
134
|
+
spinniesManager.update('test-spinner', {
|
|
135
|
+
text: 'Updated text',
|
|
136
|
+
color: 'red',
|
|
137
|
+
});
|
|
138
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
139
|
+
expect(spinner?.text).toBe('Updated text');
|
|
140
|
+
expect(spinner?.color).toBe('red');
|
|
141
|
+
});
|
|
142
|
+
it('should update spinner status', () => {
|
|
143
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
144
|
+
spinniesManager.update('test-spinner', {
|
|
145
|
+
status: 'succeed',
|
|
146
|
+
});
|
|
147
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
148
|
+
expect(spinner).toBeDefined();
|
|
149
|
+
expect(spinner?.status).toBe('succeed');
|
|
150
|
+
});
|
|
151
|
+
it('should log and return early for invalid spinner name', async () => {
|
|
152
|
+
// @ts-expect-error testing bad input
|
|
153
|
+
spinniesManager.update(123, { text: 'test' });
|
|
154
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('succeed', () => {
|
|
158
|
+
it('should mark spinner as succeeded', () => {
|
|
159
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
160
|
+
spinniesManager.succeed('test-spinner', { text: 'Success!' });
|
|
161
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
162
|
+
expect(spinner?.status).toBe('succeed');
|
|
163
|
+
expect(spinner?.text).toBe('Success!');
|
|
164
|
+
});
|
|
165
|
+
it('should succeed without updating text', () => {
|
|
166
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
167
|
+
spinniesManager.succeed('test-spinner');
|
|
168
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
169
|
+
expect(spinner?.status).toBe('succeed');
|
|
170
|
+
expect(spinner?.text).toBe('Loading...');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('fail', () => {
|
|
174
|
+
it('should mark spinner as failed', () => {
|
|
175
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
176
|
+
spinniesManager.fail('test-spinner', { text: 'Failed!' });
|
|
177
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
178
|
+
expect(spinner?.status).toBe('fail');
|
|
179
|
+
expect(spinner?.text).toBe('Failed!');
|
|
180
|
+
});
|
|
181
|
+
it('should fail without updating text', () => {
|
|
182
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
183
|
+
spinniesManager.fail('test-spinner');
|
|
184
|
+
const spinner = spinniesManager.pick('test-spinner');
|
|
185
|
+
expect(spinner?.status).toBe('fail');
|
|
186
|
+
expect(spinner?.text).toBe('Loading...');
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe('remove', () => {
|
|
190
|
+
it('should remove spinner by name', () => {
|
|
191
|
+
spinniesManager.add('test-spinner', { text: 'Loading...' });
|
|
192
|
+
expect(spinniesManager.pick('test-spinner')).toBeDefined();
|
|
193
|
+
spinniesManager.remove('test-spinner');
|
|
194
|
+
expect(spinniesManager.pick('test-spinner')).toBeUndefined();
|
|
195
|
+
});
|
|
196
|
+
it('should log debug message for invalid name', async () => {
|
|
197
|
+
// @ts-expect-error Testing bad case
|
|
198
|
+
spinniesManager.remove(123);
|
|
199
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
200
|
+
});
|
|
201
|
+
it('should handle undefined name', async () => {
|
|
202
|
+
// @ts-expect-error bad input
|
|
203
|
+
spinniesManager.remove(undefined);
|
|
204
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe('stopAll', () => {
|
|
208
|
+
beforeEach(() => {
|
|
209
|
+
// @ts-expect-error private
|
|
210
|
+
spinniesManager.spinners = {};
|
|
211
|
+
spinniesManager.add('spinner1', { text: 'First' });
|
|
212
|
+
spinniesManager.add('spinner2', { text: 'Second' });
|
|
213
|
+
});
|
|
214
|
+
it('should stop all active spinners with default status', () => {
|
|
215
|
+
// Check spinners exist before stopping
|
|
216
|
+
expect(spinniesManager.pick('spinner1')).toBeDefined();
|
|
217
|
+
expect(spinniesManager.pick('spinner2')).toBeDefined();
|
|
218
|
+
// Mock checkIfActiveSpinners to prevent clearing of spinners
|
|
219
|
+
const originalCheckIfActiveSpinners =
|
|
220
|
+
// @ts-expect-error private method
|
|
221
|
+
spinniesManager.checkIfActiveSpinners;
|
|
222
|
+
// @ts-expect-error private method
|
|
223
|
+
spinniesManager.checkIfActiveSpinners = vi.fn();
|
|
224
|
+
const result = spinniesManager.stopAll();
|
|
225
|
+
// The result should contain the updated spinners
|
|
226
|
+
expect(result.spinner1?.status).toBe('stopped');
|
|
227
|
+
expect(result.spinner2?.status).toBe('stopped');
|
|
228
|
+
expect(result.spinner1?.color).toBe('gray');
|
|
229
|
+
expect(result.spinner2?.color).toBe('gray');
|
|
230
|
+
// @ts-expect-error private method
|
|
231
|
+
spinniesManager.checkIfActiveSpinners = originalCheckIfActiveSpinners;
|
|
232
|
+
});
|
|
233
|
+
it('should stop all active spinners with succeed status', () => {
|
|
234
|
+
// Check spinners exist before stopping
|
|
235
|
+
expect(spinniesManager.pick('spinner1')).toBeDefined();
|
|
236
|
+
expect(spinniesManager.pick('spinner2')).toBeDefined();
|
|
237
|
+
// Mock checkIfActiveSpinners to prevent clearing of spinners
|
|
238
|
+
const originalCheckIfActiveSpinners =
|
|
239
|
+
// @ts-expect-error private method
|
|
240
|
+
spinniesManager.checkIfActiveSpinners;
|
|
241
|
+
// @ts-expect-error private method
|
|
242
|
+
spinniesManager.checkIfActiveSpinners = vi.fn();
|
|
243
|
+
const result = spinniesManager.stopAll('succeed');
|
|
244
|
+
expect(result.spinner1?.status).toBe('succeed');
|
|
245
|
+
expect(result.spinner2?.status).toBe('succeed');
|
|
246
|
+
// @ts-expect-error private method
|
|
247
|
+
spinniesManager.checkIfActiveSpinners = originalCheckIfActiveSpinners;
|
|
248
|
+
});
|
|
249
|
+
it('should stop all active spinners with fail status', () => {
|
|
250
|
+
// Check spinners exist before stopping
|
|
251
|
+
expect(spinniesManager.pick('spinner1')).toBeDefined();
|
|
252
|
+
expect(spinniesManager.pick('spinner2')).toBeDefined();
|
|
253
|
+
// Mock checkIfActiveSpinners to prevent clearing of spinners
|
|
254
|
+
const originalCheckIfActiveSpinners =
|
|
255
|
+
// @ts-expect-error private method
|
|
256
|
+
spinniesManager.checkIfActiveSpinners;
|
|
257
|
+
// @ts-expect-error private method
|
|
258
|
+
spinniesManager.checkIfActiveSpinners = vi.fn();
|
|
259
|
+
const result = spinniesManager.stopAll('fail');
|
|
260
|
+
expect(result.spinner1?.status).toBe('fail');
|
|
261
|
+
expect(result.spinner2?.status).toBe('fail');
|
|
262
|
+
// @ts-expect-error private method
|
|
263
|
+
spinniesManager.checkIfActiveSpinners = originalCheckIfActiveSpinners;
|
|
264
|
+
});
|
|
265
|
+
it('should not change already completed spinners', () => {
|
|
266
|
+
// Add a spinner that is already completed
|
|
267
|
+
spinniesManager.add('completed', { text: 'Done' });
|
|
268
|
+
spinniesManager.succeed('completed');
|
|
269
|
+
// Verify it exists and is succeeded
|
|
270
|
+
expect(spinniesManager.pick('completed')?.status).toBe('succeed');
|
|
271
|
+
// Mock checkIfActiveSpinners to prevent clearing of spinners
|
|
272
|
+
const originalCheckIfActiveSpinners =
|
|
273
|
+
// @ts-expect-error private method
|
|
274
|
+
spinniesManager.checkIfActiveSpinners;
|
|
275
|
+
// @ts-expect-error private method
|
|
276
|
+
spinniesManager.checkIfActiveSpinners = vi.fn();
|
|
277
|
+
const result = spinniesManager.stopAll();
|
|
278
|
+
// Completed spinners should not change status
|
|
279
|
+
expect(result.completed?.status).toBe('succeed');
|
|
280
|
+
// @ts-expect-error private method
|
|
281
|
+
spinniesManager.checkIfActiveSpinners = originalCheckIfActiveSpinners;
|
|
282
|
+
});
|
|
283
|
+
it('should handle non-spinnable status correctly', () => {
|
|
284
|
+
// Add spinner with non-spinnable status
|
|
285
|
+
spinniesManager.add('non-spin', {
|
|
286
|
+
text: 'Non-spinnable',
|
|
287
|
+
status: 'non-spinnable',
|
|
288
|
+
});
|
|
289
|
+
// Verify it exists with correct status
|
|
290
|
+
expect(spinniesManager.pick('non-spin')?.status).toBe('non-spinnable');
|
|
291
|
+
// Mock checkIfActiveSpinners to prevent clearing of spinners
|
|
292
|
+
const originalCheckIfActiveSpinners =
|
|
293
|
+
// @ts-expect-error private method
|
|
294
|
+
spinniesManager.checkIfActiveSpinners;
|
|
295
|
+
// @ts-expect-error private method
|
|
296
|
+
spinniesManager.checkIfActiveSpinners = vi.fn();
|
|
297
|
+
const result = spinniesManager.stopAll();
|
|
298
|
+
// Non-spinnable status should not change
|
|
299
|
+
expect(result['non-spin']?.status).toBe('non-spinnable');
|
|
300
|
+
// @ts-expect-error Testing private method
|
|
301
|
+
spinniesManager.checkIfActiveSpinners = originalCheckIfActiveSpinners;
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
describe('active spinner detection', () => {
|
|
306
|
+
beforeEach(() => {
|
|
307
|
+
spinniesManager.init();
|
|
308
|
+
});
|
|
309
|
+
it('should detect active spinners', () => {
|
|
310
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(false);
|
|
311
|
+
spinniesManager.add('active', { text: 'Loading...' });
|
|
312
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
313
|
+
spinniesManager.succeed('active');
|
|
314
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(false);
|
|
315
|
+
});
|
|
316
|
+
it('should detect multiple active spinners', () => {
|
|
317
|
+
spinniesManager.add('active1', { text: 'Loading 1...' });
|
|
318
|
+
spinniesManager.add('active2', { text: 'Loading 2...' });
|
|
319
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
320
|
+
spinniesManager.succeed('active1');
|
|
321
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
322
|
+
spinniesManager.succeed('active2');
|
|
323
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(false);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
describe('output control', () => {
|
|
327
|
+
beforeEach(() => {
|
|
328
|
+
spinniesManager.init();
|
|
329
|
+
});
|
|
330
|
+
it('should disable output when requested', () => {
|
|
331
|
+
spinniesManager.setDisableOutput(true);
|
|
332
|
+
spinniesManager.add('test', { text: 'Test' });
|
|
333
|
+
// Output should be disabled, so no writes to stderr should occur
|
|
334
|
+
expect(process.stderr.write).not.toHaveBeenCalled();
|
|
335
|
+
});
|
|
336
|
+
it('should enable output by default', () => {
|
|
337
|
+
// Mock process.stderr.write to be a spy
|
|
338
|
+
const mockWrite = vi.fn();
|
|
339
|
+
Object.defineProperty(process.stderr, 'write', {
|
|
340
|
+
value: mockWrite,
|
|
341
|
+
writable: true,
|
|
342
|
+
});
|
|
343
|
+
// Set stderr.isTTY to false to trigger raw output mode
|
|
344
|
+
Object.defineProperty(process.stderr, 'isTTY', {
|
|
345
|
+
value: false,
|
|
346
|
+
writable: true,
|
|
347
|
+
});
|
|
348
|
+
spinniesManager.setDisableOutput(false);
|
|
349
|
+
spinniesManager.init(); // Re-init to pick up the new isTTY value
|
|
350
|
+
spinniesManager.add('test', { text: 'Test' });
|
|
351
|
+
// In non-TTY mode, it should write with raw output
|
|
352
|
+
expect(mockWrite).toHaveBeenCalledWith('- Test\n');
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
describe('error handling', () => {
|
|
356
|
+
beforeEach(() => {
|
|
357
|
+
spinniesManager.init();
|
|
358
|
+
});
|
|
359
|
+
it('should handle missing spinner in update', async () => {
|
|
360
|
+
spinniesManager.update('non-existent', { text: 'test' });
|
|
361
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('No spinner initialized with name non-existent');
|
|
362
|
+
});
|
|
363
|
+
it('should handle missing spinner in setSpinnerProperties', async () => {
|
|
364
|
+
// @ts-expect-error Testing private method
|
|
365
|
+
spinniesManager.setSpinnerProperties('missing', {
|
|
366
|
+
text: 'test',
|
|
367
|
+
});
|
|
368
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('No spinner initialized with name missing');
|
|
369
|
+
});
|
|
370
|
+
it('should handle invalid spinner name types', async () => {
|
|
371
|
+
// @ts-expect-error Testing private method
|
|
372
|
+
spinniesManager.setSpinnerProperties(null, { text: 'test' });
|
|
373
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
374
|
+
// @ts-expect-error Testing private method
|
|
375
|
+
spinniesManager.setSpinnerProperties(undefined, {
|
|
376
|
+
text: 'test',
|
|
377
|
+
});
|
|
378
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
379
|
+
// @ts-expect-error Testing private method
|
|
380
|
+
spinniesManager.setSpinnerProperties(123, { text: 'test' });
|
|
381
|
+
expect(mockUiLogger.debug).toHaveBeenCalledWith('A spinner reference name must be specified');
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
describe('SIGINT handling', () => {
|
|
385
|
+
beforeEach(() => {
|
|
386
|
+
spinniesManager.init();
|
|
387
|
+
});
|
|
388
|
+
it('should bind SIGINT handler on init', () => {
|
|
389
|
+
const processOnSpy = vi.spyOn(process, 'on');
|
|
390
|
+
const processRemoveAllListenersSpy = vi.spyOn(process, 'removeAllListeners');
|
|
391
|
+
spinniesManager.init();
|
|
392
|
+
expect(processRemoveAllListenersSpy).toHaveBeenCalledWith('SIGINT');
|
|
393
|
+
expect(processOnSpy).toHaveBeenCalledWith('SIGINT', expect.any(Function));
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
describe('spinner options validation', () => {
|
|
397
|
+
beforeEach(() => {
|
|
398
|
+
spinniesManager.init();
|
|
399
|
+
});
|
|
400
|
+
it('should handle custom spinner frames', () => {
|
|
401
|
+
const customOptions = {
|
|
402
|
+
spinner: {
|
|
403
|
+
frames: ['|', '/', '-', '\\'],
|
|
404
|
+
interval: 100,
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
spinniesManager.init(customOptions);
|
|
408
|
+
spinniesManager.add('custom', { text: 'Custom spinner' });
|
|
409
|
+
const spinner = spinniesManager.pick('custom');
|
|
410
|
+
expect(spinner).toBeDefined();
|
|
411
|
+
expect(spinner?.text).toBe('Custom spinner');
|
|
412
|
+
});
|
|
413
|
+
it('should handle custom colors', () => {
|
|
414
|
+
spinniesManager.add('colored', {
|
|
415
|
+
text: 'Colored spinner',
|
|
416
|
+
color: 'red',
|
|
417
|
+
spinnerColor: 'blue',
|
|
418
|
+
succeedColor: 'green',
|
|
419
|
+
failColor: 'yellow',
|
|
420
|
+
});
|
|
421
|
+
const spinner = spinniesManager.pick('colored');
|
|
422
|
+
expect(spinner?.color).toBe('red');
|
|
423
|
+
expect(spinner?.spinnerColor).toBe('blue');
|
|
424
|
+
expect(spinner?.succeedColor).toBe('green');
|
|
425
|
+
expect(spinner?.failColor).toBe('yellow');
|
|
426
|
+
});
|
|
427
|
+
it('should handle indentation', () => {
|
|
428
|
+
spinniesManager.add('indented', {
|
|
429
|
+
text: 'Indented spinner',
|
|
430
|
+
indent: 4,
|
|
431
|
+
});
|
|
432
|
+
const spinner = spinniesManager.pick('indented');
|
|
433
|
+
expect(spinner?.indent).toBe(4);
|
|
434
|
+
});
|
|
435
|
+
it('should handle custom prefixes', () => {
|
|
436
|
+
spinniesManager.init({
|
|
437
|
+
succeedPrefix: '[OK]',
|
|
438
|
+
failPrefix: '[ERR]',
|
|
439
|
+
});
|
|
440
|
+
spinniesManager.add('prefixed', {
|
|
441
|
+
text: 'Prefixed spinner',
|
|
442
|
+
});
|
|
443
|
+
const spinner = spinniesManager.pick('prefixed');
|
|
444
|
+
expect(spinner?.succeedPrefix).toBe('[OK]');
|
|
445
|
+
expect(spinner?.failPrefix).toBe('[ERR]');
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
describe('edge cases', () => {
|
|
449
|
+
beforeEach(() => {
|
|
450
|
+
spinniesManager.init();
|
|
451
|
+
});
|
|
452
|
+
it('should handle empty spinner name gracefully', () => {
|
|
453
|
+
spinniesManager.add('', { text: 'No name spinner' });
|
|
454
|
+
// Since we can't get the generated name directly, just verify a spinner was added
|
|
455
|
+
expect(spinniesManager.hasActiveSpinners()).toBe(true);
|
|
456
|
+
});
|
|
457
|
+
it('should handle null/undefined text', () => {
|
|
458
|
+
// @ts-expect-error Testing bad case
|
|
459
|
+
spinniesManager.add('null-text', { text: null });
|
|
460
|
+
const spinner = spinniesManager.pick('null-text');
|
|
461
|
+
expect(spinner?.text).toBe('null-text');
|
|
462
|
+
});
|
|
463
|
+
it('should handle non-TTY environments', () => {
|
|
464
|
+
const mockWrite = vi.fn();
|
|
465
|
+
Object.defineProperty(process.stderr, 'write', {
|
|
466
|
+
value: mockWrite,
|
|
467
|
+
writable: true,
|
|
468
|
+
});
|
|
469
|
+
Object.defineProperty(process.stderr, 'isTTY', {
|
|
470
|
+
value: false,
|
|
471
|
+
writable: true,
|
|
472
|
+
});
|
|
473
|
+
spinniesManager.init();
|
|
474
|
+
spinniesManager.add('no-tty', { text: 'No TTY' });
|
|
475
|
+
const spinner = spinniesManager.pick('no-tty');
|
|
476
|
+
expect(spinner).toBeDefined();
|
|
477
|
+
expect(mockWrite).toHaveBeenCalledWith('- No TTY\n');
|
|
478
|
+
});
|
|
479
|
+
it('should handle missing process.stderr.columns', () => {
|
|
480
|
+
// @ts-expect-error
|
|
481
|
+
delete process.stderr.columns;
|
|
482
|
+
spinniesManager.add('no-columns', {
|
|
483
|
+
text: 'A very long text that would normally be broken into multiple lines but now has to handle missing columns gracefully',
|
|
484
|
+
});
|
|
485
|
+
const spinner = spinniesManager.pick('no-columns');
|
|
486
|
+
expect(spinner).toBeDefined();
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
});
|
package/lib/ui/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { getConfigAccountIfExists, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { uiLogger } from './logger.js';
|
|
4
4
|
import { supportsHyperlinkModule } from './supportHyperlinks.js';
|
|
5
5
|
import { supportsColor } from './supportsColor.js';
|
|
@@ -38,7 +38,7 @@ export function uiLink(linkText, url) {
|
|
|
38
38
|
: `${linkText}: ${encodedUrl}`;
|
|
39
39
|
}
|
|
40
40
|
export function uiAccountDescription(accountId, bold = true) {
|
|
41
|
-
const account =
|
|
41
|
+
const account = accountId ? getConfigAccountIfExists(accountId) : undefined;
|
|
42
42
|
let message;
|
|
43
43
|
if (account && account.accountType) {
|
|
44
44
|
message = `${account.name ? `${account.name} ` : ''}[${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
|
|
@@ -46,6 +46,9 @@ export function uiAccountDescription(accountId, bold = true) {
|
|
|
46
46
|
else {
|
|
47
47
|
message = accountId ? accountId.toString() : '';
|
|
48
48
|
}
|
|
49
|
+
if (message.trim().length === 0) {
|
|
50
|
+
return 'unknown account';
|
|
51
|
+
}
|
|
49
52
|
return bold ? chalk.bold(message) : message;
|
|
50
53
|
}
|
|
51
54
|
export function uiInfoSection(title, logContent) {
|
|
@@ -64,7 +67,7 @@ export function uiCommandReference(command, withQuotes = true) {
|
|
|
64
67
|
: commandReference);
|
|
65
68
|
}
|
|
66
69
|
export function uiAuthCommandReference({ accountId, qa, } = {}) {
|
|
67
|
-
const userIsUsingGlobalConfig =
|
|
70
|
+
const userIsUsingGlobalConfig = globalConfigFileExists();
|
|
68
71
|
let command = 'hs auth';
|
|
69
72
|
if (userIsUsingGlobalConfig) {
|
|
70
73
|
command = 'hs account auth';
|
package/lib/usageTracking.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
|
|
2
|
-
import {
|
|
2
|
+
import { getConfigAccountById, getConfig } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { API_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
|
|
4
4
|
import { uiLogger } from './ui/logger.js';
|
|
5
5
|
import { pkg } from './jsonLoader.js';
|
|
@@ -28,13 +28,17 @@ export function getPlatform() {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
export async function trackCommandUsage(command, meta = {}, accountId) {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
try {
|
|
32
|
+
const config = getConfig();
|
|
33
|
+
if (config?.allowUsageTracking === false) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
33
36
|
}
|
|
37
|
+
catch (e) { }
|
|
34
38
|
uiLogger.debug(`Attempting to track usage of "${command}" command`);
|
|
35
39
|
let authType = 'unknown';
|
|
36
40
|
if (accountId) {
|
|
37
|
-
const accountConfig =
|
|
41
|
+
const accountConfig = getConfigAccountById(accountId);
|
|
38
42
|
authType =
|
|
39
43
|
accountConfig && accountConfig.authType
|
|
40
44
|
? accountConfig.authType
|
|
@@ -49,7 +53,8 @@ export async function trackCommandUsage(command, meta = {}, accountId) {
|
|
|
49
53
|
});
|
|
50
54
|
}
|
|
51
55
|
export async function trackHelpUsage(command) {
|
|
52
|
-
|
|
56
|
+
const config = getConfig();
|
|
57
|
+
if (config?.allowUsageTracking === false) {
|
|
53
58
|
return;
|
|
54
59
|
}
|
|
55
60
|
if (command) {
|
|
@@ -81,13 +86,14 @@ export async function trackAuthAction(command, authType, step, accountId) {
|
|
|
81
86
|
});
|
|
82
87
|
}
|
|
83
88
|
export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
|
|
84
|
-
|
|
89
|
+
const config = getConfig();
|
|
90
|
+
if (config?.allowUsageTracking === false) {
|
|
85
91
|
return;
|
|
86
92
|
}
|
|
87
93
|
uiLogger.debug(`Attempting to track metadata usage of "${command}" command`);
|
|
88
94
|
let authType = 'unknown';
|
|
89
95
|
if (accountId) {
|
|
90
|
-
const accountConfig =
|
|
96
|
+
const accountConfig = getConfigAccountById(accountId);
|
|
91
97
|
authType =
|
|
92
98
|
accountConfig && accountConfig.authType
|
|
93
99
|
? accountConfig.authType
|
|
@@ -103,7 +109,8 @@ export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
|
|
|
103
109
|
}
|
|
104
110
|
async function trackCliInteraction({ action, accountId, command, authType, meta = {}, }) {
|
|
105
111
|
try {
|
|
106
|
-
|
|
112
|
+
const config = getConfig();
|
|
113
|
+
if (config?.allowUsageTracking === false) {
|
|
107
114
|
return;
|
|
108
115
|
}
|
|
109
116
|
const usageTrackingEvent = {
|
package/lib/validation.js
CHANGED
|
@@ -4,16 +4,17 @@ import { uiLogger } from '../lib/ui/logger.js';
|
|
|
4
4
|
import { CMS_PUBLISH_MODE } from '@hubspot/local-dev-lib/constants/files';
|
|
5
5
|
import { API_KEY_AUTH_METHOD, OAUTH_AUTH_METHOD, PERSONAL_ACCESS_KEY_AUTH_METHOD, } from '@hubspot/local-dev-lib/constants/auth';
|
|
6
6
|
import { commaSeparatedValues } from '@hubspot/local-dev-lib/text';
|
|
7
|
-
import {
|
|
7
|
+
import { getConfigFilePath, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
|
|
8
8
|
import { getOauthManager } from '@hubspot/local-dev-lib/oauth';
|
|
9
9
|
import { accessTokenForPersonalAccessKey } from '@hubspot/local-dev-lib/personalAccessKey';
|
|
10
10
|
import { getAbsoluteFilePath, getCwd, getExt, } from '@hubspot/local-dev-lib/path';
|
|
11
|
+
import { ENVIRONMENT_VARIABLES } from '@hubspot/local-dev-lib/constants/config';
|
|
11
12
|
import { getCmsPublishMode } from './commonOpts.js';
|
|
12
13
|
import { logError } from './errorHandlers/index.js';
|
|
13
14
|
import { lib } from '../lang/en.js';
|
|
14
15
|
export async function validateAccount(options) {
|
|
15
16
|
const { derivedAccountId, userProvidedAccount } = options;
|
|
16
|
-
const accountId =
|
|
17
|
+
const accountId = derivedAccountId;
|
|
17
18
|
if (!accountId) {
|
|
18
19
|
if (userProvidedAccount) {
|
|
19
20
|
uiLogger.error(lib.validation.accountNotFoundInConfig(userProvidedAccount));
|
|
@@ -23,33 +24,34 @@ export async function validateAccount(options) {
|
|
|
23
24
|
}
|
|
24
25
|
return false;
|
|
25
26
|
}
|
|
26
|
-
if (userProvidedAccount &&
|
|
27
|
+
if (userProvidedAccount &&
|
|
28
|
+
process.env[ENVIRONMENT_VARIABLES.USE_ENVIRONMENT_HUBSPOT_CONFIG]) {
|
|
27
29
|
throw new Error(lib.validation.userProvidedAccount);
|
|
28
30
|
}
|
|
29
|
-
const accountConfig =
|
|
31
|
+
const accountConfig = getConfigAccountById(accountId);
|
|
30
32
|
if (!accountConfig) {
|
|
31
33
|
uiLogger.error(lib.validation.accountNotConfigured(accountId));
|
|
32
34
|
return false;
|
|
33
35
|
}
|
|
34
|
-
const { authType
|
|
36
|
+
const { authType } = accountConfig;
|
|
35
37
|
if (typeof authType === 'string' && authType !== authType.toLowerCase()) {
|
|
36
|
-
uiLogger.error(lib.validation.invalidAuthType(authType, accountId,
|
|
38
|
+
uiLogger.error(lib.validation.invalidAuthType(authType, accountId, getConfigFilePath(), commaSeparatedValues([
|
|
37
39
|
PERSONAL_ACCESS_KEY_AUTH_METHOD,
|
|
38
40
|
OAUTH_AUTH_METHOD,
|
|
39
41
|
API_KEY_AUTH_METHOD,
|
|
40
42
|
].map(method => method.value))));
|
|
41
43
|
}
|
|
42
44
|
if (authType === 'oauth2') {
|
|
43
|
-
if (typeof auth !== 'object') {
|
|
45
|
+
if (typeof accountConfig.auth !== 'object') {
|
|
44
46
|
uiLogger.error(lib.validation.oauth2ConfigMissing(accountId));
|
|
45
47
|
return false;
|
|
46
48
|
}
|
|
47
|
-
const { clientId, clientSecret, tokenInfo } = auth;
|
|
49
|
+
const { clientId, clientSecret, tokenInfo } = accountConfig.auth;
|
|
48
50
|
if (!clientId || !clientSecret || !tokenInfo || !tokenInfo.refreshToken) {
|
|
49
51
|
uiLogger.error(lib.validation.oauth2ConfigIncorrect(accountId));
|
|
50
52
|
return false;
|
|
51
53
|
}
|
|
52
|
-
const oauth = getOauthManager(
|
|
54
|
+
const oauth = getOauthManager(accountConfig);
|
|
53
55
|
try {
|
|
54
56
|
let accessToken;
|
|
55
57
|
if (oauth) {
|
|
@@ -66,7 +68,7 @@ export async function validateAccount(options) {
|
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
else if (authType === 'personalaccesskey') {
|
|
69
|
-
if (!personalAccessKey) {
|
|
71
|
+
if (!accountConfig.personalAccessKey) {
|
|
70
72
|
uiLogger.error(lib.validation.personalAccessKeyMissing(accountId));
|
|
71
73
|
return false;
|
|
72
74
|
}
|
|
@@ -82,7 +84,7 @@ export async function validateAccount(options) {
|
|
|
82
84
|
return false;
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
|
-
else if (!apiKey) {
|
|
87
|
+
else if (!accountConfig.apiKey) {
|
|
86
88
|
uiLogger.error(lib.validation.authConfigurationMissing(accountId));
|
|
87
89
|
return false;
|
|
88
90
|
}
|