@hubspot/local-dev-lib 0.7.7-experimental.0 → 0.7.9-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/api/projects.d.ts +6 -1
- package/api/projects.js +38 -0
- package/api/sandboxHubs.js +2 -0
- package/config/defaultAccountOverride.d.ts +1 -0
- package/config/defaultAccountOverride.js +15 -0
- package/config/hsSettings.d.ts +4 -0
- package/config/hsSettings.js +58 -0
- package/config/index.d.ts +1 -0
- package/config/index.js +31 -11
- package/config/state.js +7 -9
- package/constants/config.d.ts +9 -0
- package/constants/config.js +9 -0
- package/constants/ports.js +2 -0
- package/constants/projects.d.ts +1 -0
- package/constants/projects.js +1 -0
- package/lib/cms/functions.js +1 -1
- package/lib/github.js +1 -1
- package/lib/gitignore.d.ts +1 -0
- package/lib/gitignore.js +22 -1
- package/lib/portManager.d.ts +2 -2
- package/lib/portManager.js +13 -11
- package/models/HubSpotHttpError.js +7 -1
- package/package.json +4 -3
- package/types/Config.d.ts +3 -2
- package/types/Config.js +1 -1
- package/types/HsSettings.d.ts +4 -0
- package/types/HsSettings.js +1 -0
- package/types/Project.d.ts +30 -0
- package/utils/PortManagerServer.d.ts +6 -7
- package/utils/PortManagerServer.js +14 -5
package/api/projects.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HubSpotPromise, QueryParams } from '../types/Http.js';
|
|
2
|
-
import { Project, FetchProjectResponse, UploadProjectResponse, ProjectSettings, FetchPlatformVersionResponse, WarnLogsResponse, UploadIRResponse } from '../types/Project.js';
|
|
2
|
+
import { Project, FetchProjectResponse, UploadProjectResponse, ProjectSettings, FetchPlatformVersionResponse, WarnLogsResponse, UploadIRResponse, Release, FetchListReleasesResponse, AutoReleaseResponse, AutoReleaseStatusResponse } from '../types/Project.js';
|
|
3
3
|
import { Build, FetchProjectBuildsResponse } from '../types/Build.js';
|
|
4
4
|
import { ComponentStructureResponse, ProjectComponentsMetadata } from '../types/ComponentStructure.js';
|
|
5
5
|
import { Deploy, ProjectDeployResponse, ProjectDeployResponseV1, ProjectDeletionResponse } from '../types/Deploy.js';
|
|
@@ -39,6 +39,11 @@ export declare function deleteFileFromBuild(accountId: number, projectName: stri
|
|
|
39
39
|
export declare function cancelStagedBuild(accountId: number, projectName: string): HubSpotPromise<void>;
|
|
40
40
|
export declare function fetchBuildWarnLogs(accountId: number, projectName: string, buildId: number): HubSpotPromise<WarnLogsResponse>;
|
|
41
41
|
export declare function fetchDeployWarnLogs(accountId: number, projectName: string, deployId: number): HubSpotPromise<WarnLogsResponse>;
|
|
42
|
+
export declare function createRelease(accountId: number, projectName: string, buildId: number): HubSpotPromise<Release>;
|
|
43
|
+
export declare function listReleases(accountId: number, projectName: string, params?: QueryParams): HubSpotPromise<FetchListReleasesResponse>;
|
|
44
|
+
export declare function getReleaseInfo(accountId: number, projectName: string, releaseTag: string): HubSpotPromise<Release>;
|
|
45
|
+
export declare function triggerAutoRelease(accountId: number, projectId: number, buildId: number, targetPortalId: number): HubSpotPromise<AutoReleaseResponse>;
|
|
46
|
+
export declare function getAutoReleaseStatus(accountId: number, projectId: number, targetPortalId: number, expectedReleaseTag: string, appId: number): HubSpotPromise<AutoReleaseStatusResponse>;
|
|
42
47
|
/**
|
|
43
48
|
* @deprecated
|
|
44
49
|
*/
|
package/api/projects.js
CHANGED
|
@@ -215,6 +215,44 @@ export function fetchDeployWarnLogs(accountId, projectName, deployId) {
|
|
|
215
215
|
url: `${PROJECTS_LOGS_API_PATH}/logs/projects/${encodeURIComponent(projectName)}/deploys/${deployId}/combined/warn`,
|
|
216
216
|
});
|
|
217
217
|
}
|
|
218
|
+
export function createRelease(accountId, projectName, buildId) {
|
|
219
|
+
return http.post(accountId, {
|
|
220
|
+
url: `${PROJECTS_API_PATH}/${encodeURIComponent(projectName)}/releases`,
|
|
221
|
+
data: { buildId },
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
export function listReleases(accountId, projectName, params = {}) {
|
|
225
|
+
return http.get(accountId, {
|
|
226
|
+
url: `${PROJECTS_API_PATH}/${encodeURIComponent(projectName)}/releases`,
|
|
227
|
+
params,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
export function getReleaseInfo(accountId, projectName, releaseTag) {
|
|
231
|
+
return http.get(accountId, {
|
|
232
|
+
url: `${PROJECTS_API_PATH}/${encodeURIComponent(projectName)}/releases/${encodeURIComponent(releaseTag)}`,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
export function triggerAutoRelease(accountId, projectId, buildId, targetPortalId) {
|
|
236
|
+
return http.post(accountId, {
|
|
237
|
+
url: `${PROJECTS_DEPLOY_API_PATH}/auto-release`,
|
|
238
|
+
data: {
|
|
239
|
+
projectId,
|
|
240
|
+
buildId,
|
|
241
|
+
targetPortalId,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export function getAutoReleaseStatus(accountId, projectId, targetPortalId, expectedReleaseTag, appId) {
|
|
246
|
+
return http.get(accountId, {
|
|
247
|
+
url: `${PROJECTS_DEPLOY_API_PATH}/auto-release/status`,
|
|
248
|
+
params: {
|
|
249
|
+
projectId,
|
|
250
|
+
targetPortalId,
|
|
251
|
+
expectedReleaseTag,
|
|
252
|
+
appId,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
}
|
|
218
256
|
/**
|
|
219
257
|
* @deprecated
|
|
220
258
|
*/
|
package/api/sandboxHubs.js
CHANGED
|
@@ -16,6 +16,7 @@ export function createSandbox(accountId, name, type) {
|
|
|
16
16
|
export function deleteSandbox(parentAccountId, sandboxAccountId) {
|
|
17
17
|
return http.delete(parentAccountId, {
|
|
18
18
|
url: `${SANDBOX_API_PATH}/${sandboxAccountId}`,
|
|
19
|
+
timeout: SANDBOX_TIMEOUT,
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
export function getSandboxUsageLimits(parentAccountId) {
|
|
@@ -27,6 +28,7 @@ export function createV2Sandbox(accountId, name, type, syncObjectRecords) {
|
|
|
27
28
|
return http.post(accountId, {
|
|
28
29
|
url: `${SANDBOX_API_PATH_V2}/sandboxes`,
|
|
29
30
|
data: { name, type, syncObjectRecords },
|
|
31
|
+
timeout: SANDBOX_TIMEOUT,
|
|
30
32
|
});
|
|
31
33
|
}
|
|
32
34
|
export function getSandboxPersonalAccessKey(accountId, sandboxId) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { HubSpotConfigAccount } from '../types/Accounts.js';
|
|
2
2
|
export declare function getDefaultAccountOverrideAccountId(accounts: Array<HubSpotConfigAccount>): number | null;
|
|
3
|
+
export declare function removeDefaultAccountOverrideFile(): void;
|
|
3
4
|
export declare function getDefaultAccountOverrideFilePath(): string | null;
|
|
@@ -40,6 +40,21 @@ export function getDefaultAccountOverrideAccountId(accounts) {
|
|
|
40
40
|
}
|
|
41
41
|
return account.accountId;
|
|
42
42
|
}
|
|
43
|
+
export function removeDefaultAccountOverrideFile() {
|
|
44
|
+
const filePath = getDefaultAccountOverrideFilePath();
|
|
45
|
+
if (!filePath) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
fs.unlinkSync(filePath);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
throw new FileSystemError({ cause: e }, {
|
|
53
|
+
filepath: filePath,
|
|
54
|
+
operation: 'write',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
43
58
|
export function getDefaultAccountOverrideFilePath() {
|
|
44
59
|
return findup([DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME], {
|
|
45
60
|
cwd: getCwd(),
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { HsSettingsFile } from '../types/HsSettings.js';
|
|
2
|
+
export declare function getHsSettingsFilePath(): string | null;
|
|
3
|
+
export declare function getHsSettingsFileIfExists(): HsSettingsFile | null;
|
|
4
|
+
export declare function writeHsSettingsFile(settingsFile: HsSettingsFile): void;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import findupSync from 'findup-sync';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { HS_FOLDER, HS_README_FILENAME, HS_SETTINGS_FILENAME, } from '../constants/config.js';
|
|
5
|
+
import { getCwd } from '../lib/path.js';
|
|
6
|
+
import { FileSystemError } from '../models/FileSystemError.js';
|
|
7
|
+
const HS_README_CONTENTS = `Why do I have a folder named ".hs" in my project?
|
|
8
|
+
The ".hs" folder is created when you link a directory to a HubSpot project.
|
|
9
|
+
|
|
10
|
+
What does the "settings.json" file contain?
|
|
11
|
+
The "settings.json" file contains:
|
|
12
|
+
- The ID(s) of the HubSpot account(s) that you linked ("accounts")
|
|
13
|
+
- The ID of the HubSpot account that you set as the default for this directory ("linkedDefaultAccount")
|
|
14
|
+
|
|
15
|
+
Should I commit the ".hs" folder?
|
|
16
|
+
No, the ".hs" folder should not be committed to version control. It is automatically added to your .gitignore file when the directory is linked.
|
|
17
|
+
`;
|
|
18
|
+
export function getHsSettingsFilePath() {
|
|
19
|
+
return findupSync([`${HS_FOLDER}/${HS_SETTINGS_FILENAME}`], {
|
|
20
|
+
cwd: getCwd(),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function getHsSettingsFileIfExists() {
|
|
24
|
+
const hsSettingsFilePath = getHsSettingsFilePath();
|
|
25
|
+
if (!hsSettingsFilePath) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(fs.readFileSync(hsSettingsFilePath, 'utf-8'));
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
throw new FileSystemError({ cause: e }, {
|
|
33
|
+
filepath: hsSettingsFilePath,
|
|
34
|
+
operation: 'read',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function writeHsSettingsFile(settingsFile) {
|
|
39
|
+
const existingFilePath = getHsSettingsFilePath();
|
|
40
|
+
const dir = getCwd();
|
|
41
|
+
const hsFolderPath = existingFilePath
|
|
42
|
+
? path.dirname(existingFilePath)
|
|
43
|
+
: path.join(dir, HS_FOLDER);
|
|
44
|
+
const isFirstScaffold = !fs.existsSync(hsFolderPath);
|
|
45
|
+
try {
|
|
46
|
+
fs.mkdirSync(hsFolderPath, { recursive: true });
|
|
47
|
+
fs.writeFileSync(path.join(hsFolderPath, HS_SETTINGS_FILENAME), JSON.stringify(settingsFile, null, 2), 'utf8');
|
|
48
|
+
if (isFirstScaffold) {
|
|
49
|
+
fs.writeFileSync(path.join(hsFolderPath, HS_README_FILENAME), HS_README_CONTENTS, 'utf8');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
throw new FileSystemError({ cause: err }, {
|
|
54
|
+
filepath: dir,
|
|
55
|
+
operation: 'write',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
package/config/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare function getConfigAccountIfExists(identifier: number | string): H
|
|
|
18
18
|
export declare function getConfigDefaultAccount(): HubSpotConfigAccount;
|
|
19
19
|
export declare function getConfigDefaultAccountIfExists(): HubSpotConfigAccount | undefined;
|
|
20
20
|
export declare function getAllConfigAccounts(): HubSpotConfigAccount[];
|
|
21
|
+
export declare function getLinkedOrAllConfigAccounts(): HubSpotConfigAccount[];
|
|
21
22
|
export declare function getConfigAccountEnvironment(identifier: number | string): Environment;
|
|
22
23
|
export declare function addConfigAccount(accountToAdd: HubSpotConfigAccount): void;
|
|
23
24
|
export declare function updateConfigAccount(updatedAccount: HubSpotConfigAccount): void;
|
package/config/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { HubSpotConfigError } from '../models/HubSpotConfigError.js';
|
|
|
11
11
|
import { HUBSPOT_CONFIG_ERROR_TYPES } from '../constants/config.js';
|
|
12
12
|
import { isDeepEqual } from '../lib/isDeepEqual.js';
|
|
13
13
|
import { getCwd } from '../lib/path.js';
|
|
14
|
+
import { getHsSettingsFileIfExists } from './hsSettings.js';
|
|
14
15
|
const EMPTY_CONFIG = { accounts: [] };
|
|
15
16
|
export function getGlobalConfigFilePath() {
|
|
16
17
|
return GLOBAL_CONFIG_PATH;
|
|
@@ -152,11 +153,17 @@ export function getConfigAccountIfExists(identifier) {
|
|
|
152
153
|
export function getConfigDefaultAccount() {
|
|
153
154
|
const { accounts, defaultAccount } = getConfig();
|
|
154
155
|
let defaultAccountToUse = defaultAccount;
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
const hsSettingsFile = getHsSettingsFileIfExists();
|
|
157
|
+
if (hsSettingsFile && hsSettingsFile.localDefaultAccount) {
|
|
158
|
+
defaultAccountToUse = hsSettingsFile.localDefaultAccount;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const currentConfigPath = getConfigFilePath();
|
|
162
|
+
const globalConfigPath = getGlobalConfigFilePath();
|
|
163
|
+
if (currentConfigPath === globalConfigPath && globalConfigFileExists()) {
|
|
164
|
+
const defaultAccountOverrideAccountId = getDefaultAccountOverrideAccountId(accounts);
|
|
165
|
+
defaultAccountToUse = defaultAccountOverrideAccountId || defaultAccount;
|
|
166
|
+
}
|
|
160
167
|
}
|
|
161
168
|
if (!defaultAccountToUse) {
|
|
162
169
|
throw new HubSpotConfigError(i18n('config.getConfigDefaultAccount.fieldMissingError'), HUBSPOT_CONFIG_ERROR_TYPES.NO_DEFAULT_ACCOUNT, HUBSPOT_CONFIG_OPERATIONS.READ);
|
|
@@ -172,12 +179,17 @@ export function getConfigDefaultAccount() {
|
|
|
172
179
|
export function getConfigDefaultAccountIfExists() {
|
|
173
180
|
const { accounts, defaultAccount } = getConfig();
|
|
174
181
|
let defaultAccountToUse = defaultAccount;
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
182
|
+
const hsSettingsFile = getHsSettingsFileIfExists();
|
|
183
|
+
if (hsSettingsFile && hsSettingsFile.localDefaultAccount) {
|
|
184
|
+
defaultAccountToUse = hsSettingsFile.localDefaultAccount;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
const currentConfigPath = getConfigFilePath();
|
|
188
|
+
const globalConfigPath = getGlobalConfigFilePath();
|
|
189
|
+
if (currentConfigPath === globalConfigPath && globalConfigFileExists()) {
|
|
190
|
+
const defaultAccountOverrideAccountId = getDefaultAccountOverrideAccountId(accounts);
|
|
191
|
+
defaultAccountToUse = defaultAccountOverrideAccountId || defaultAccount;
|
|
192
|
+
}
|
|
181
193
|
}
|
|
182
194
|
if (!defaultAccountToUse) {
|
|
183
195
|
return;
|
|
@@ -189,6 +201,14 @@ export function getAllConfigAccounts() {
|
|
|
189
201
|
const { accounts } = getConfig();
|
|
190
202
|
return accounts;
|
|
191
203
|
}
|
|
204
|
+
export function getLinkedOrAllConfigAccounts() {
|
|
205
|
+
const { accounts } = getConfig();
|
|
206
|
+
const hsSettingsFile = getHsSettingsFileIfExists();
|
|
207
|
+
if (!hsSettingsFile || hsSettingsFile.accounts.length === 0) {
|
|
208
|
+
return accounts;
|
|
209
|
+
}
|
|
210
|
+
return accounts.filter(a => hsSettingsFile.accounts.includes(a.accountId));
|
|
211
|
+
}
|
|
192
212
|
export function getConfigAccountEnvironment(identifier) {
|
|
193
213
|
const config = getConfig();
|
|
194
214
|
const account = getConfigAccountByInferredIdentifier(config.accounts, identifier);
|
package/config/state.js
CHANGED
|
@@ -7,6 +7,7 @@ import { STATE_FLAGS } from '../constants/config.js';
|
|
|
7
7
|
const i18nKey = 'config.state';
|
|
8
8
|
const DEFAULT_STATE = {
|
|
9
9
|
[STATE_FLAGS.MCP_TOTAL_TOOL_CALLS]: 0,
|
|
10
|
+
[STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION]: undefined,
|
|
10
11
|
};
|
|
11
12
|
function ensureCLIDirectory() {
|
|
12
13
|
try {
|
|
@@ -21,19 +22,16 @@ function ensureCLIDirectory() {
|
|
|
21
22
|
}));
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
|
-
function
|
|
25
|
+
function parseState(parsed) {
|
|
25
26
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
26
27
|
return structuredClone(DEFAULT_STATE);
|
|
27
28
|
}
|
|
28
|
-
const
|
|
29
|
+
const record = parsed;
|
|
29
30
|
const result = structuredClone(DEFAULT_STATE);
|
|
30
|
-
for (const key
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
typeof state[typedKey] === typeof DEFAULT_STATE[typedKey]) {
|
|
34
|
-
result[typedKey] = state[typedKey];
|
|
31
|
+
for (const key of Object.keys(DEFAULT_STATE)) {
|
|
32
|
+
if (key in record && record[key] !== undefined) {
|
|
33
|
+
Object.assign(result, { [key]: record[key] });
|
|
35
34
|
}
|
|
36
|
-
// keys not in parsed file remain as DEFAULT values
|
|
37
35
|
}
|
|
38
36
|
return result;
|
|
39
37
|
}
|
|
@@ -48,7 +46,7 @@ function getCurrentState() {
|
|
|
48
46
|
return structuredClone(DEFAULT_STATE);
|
|
49
47
|
}
|
|
50
48
|
const parsed = JSON.parse(data);
|
|
51
|
-
return
|
|
49
|
+
return parseState(parsed);
|
|
52
50
|
}
|
|
53
51
|
catch (error) {
|
|
54
52
|
logger.debug(i18n(`${i18nKey}.getCurrentState.errors.errorReading`, {
|
package/constants/config.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ export declare const HUBSPOT_ACCOUNT_TYPE_STRINGS: {
|
|
|
56
56
|
};
|
|
57
57
|
export declare const STATE_FLAGS: {
|
|
58
58
|
readonly MCP_TOTAL_TOOL_CALLS: "mcpTotalToolCalls";
|
|
59
|
+
readonly USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION: "usageTrackingMessageLastShowVersion";
|
|
59
60
|
};
|
|
60
61
|
export declare const CONFIG_FLAGS: {
|
|
61
62
|
readonly DEFAULT_CMS_PUBLISH_MODE: "defaultCmsPublishMode";
|
|
@@ -102,3 +103,11 @@ export declare const HUBSPOT_CONFIG_OPERATIONS: {
|
|
|
102
103
|
readonly WRITE: "WRITE";
|
|
103
104
|
readonly DELETE: "DELETE";
|
|
104
105
|
};
|
|
106
|
+
export declare const HS_FOLDER = ".hs";
|
|
107
|
+
export declare const HS_SETTINGS_FILENAME = "settings.json";
|
|
108
|
+
export declare const HS_README_FILENAME = "README.txt";
|
|
109
|
+
export declare const DEFAULT_HS_SETTINGS_PATH = ".hs/settings.json";
|
|
110
|
+
export declare const EMPTY_HS_SETTINGS_FILE: {
|
|
111
|
+
localDefaultAccount: undefined;
|
|
112
|
+
accounts: never[];
|
|
113
|
+
};
|
package/constants/config.js
CHANGED
|
@@ -59,6 +59,7 @@ export const HUBSPOT_ACCOUNT_TYPE_STRINGS = {
|
|
|
59
59
|
};
|
|
60
60
|
export const STATE_FLAGS = {
|
|
61
61
|
MCP_TOTAL_TOOL_CALLS: 'mcpTotalToolCalls',
|
|
62
|
+
USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION: 'usageTrackingMessageLastShowVersion',
|
|
62
63
|
};
|
|
63
64
|
export const CONFIG_FLAGS = {
|
|
64
65
|
DEFAULT_CMS_PUBLISH_MODE: 'defaultCmsPublishMode',
|
|
@@ -105,3 +106,11 @@ export const HUBSPOT_CONFIG_OPERATIONS = {
|
|
|
105
106
|
WRITE: 'WRITE',
|
|
106
107
|
DELETE: 'DELETE',
|
|
107
108
|
};
|
|
109
|
+
export const HS_FOLDER = '.hs';
|
|
110
|
+
export const HS_SETTINGS_FILENAME = 'settings.json';
|
|
111
|
+
export const HS_README_FILENAME = 'README.txt';
|
|
112
|
+
export const DEFAULT_HS_SETTINGS_PATH = `${HS_FOLDER}/${HS_SETTINGS_FILENAME}`;
|
|
113
|
+
export const EMPTY_HS_SETTINGS_FILE = {
|
|
114
|
+
localDefaultAccount: undefined,
|
|
115
|
+
accounts: [],
|
|
116
|
+
};
|
package/constants/ports.js
CHANGED
package/constants/projects.d.ts
CHANGED
package/constants/projects.js
CHANGED
package/lib/cms/functions.js
CHANGED
|
@@ -19,7 +19,7 @@ export function createEndpoint(endpointMethod, filename) {
|
|
|
19
19
|
}
|
|
20
20
|
export function createConfig({ endpointPath, endpointMethod, functionFile, }) {
|
|
21
21
|
return {
|
|
22
|
-
runtime: '
|
|
22
|
+
runtime: 'nodejs20.x',
|
|
23
23
|
version: '1.0',
|
|
24
24
|
environment: {},
|
|
25
25
|
secrets: [],
|
package/lib/github.js
CHANGED
|
@@ -96,7 +96,7 @@ export async function fetchGitHubRepoContentFromDownloadUrl(dest, downloadUrl) {
|
|
|
96
96
|
const resp = await fetchRepoFileByDownloadUrl(downloadUrl);
|
|
97
97
|
const contentType = resp.headers['content-type'];
|
|
98
98
|
let fileContents;
|
|
99
|
-
if (contentType.startsWith('text')) {
|
|
99
|
+
if (typeof contentType === 'string' && contentType.startsWith('text')) {
|
|
100
100
|
fileContents = Buffer.from(resp.data).toString('utf8');
|
|
101
101
|
}
|
|
102
102
|
else {
|
package/lib/gitignore.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { GitInclusionResult } from '../types/Config.js';
|
|
2
2
|
export declare function checkAndAddConfigToGitignore(configPath: string): void;
|
|
3
|
+
export declare function checkAndAddHsFolderToGitignore(settingsPath: string): void;
|
|
3
4
|
export declare function checkGitInclusion(configPath: string): GitInclusionResult;
|
package/lib/gitignore.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { isConfigPathInGitRepo, getGitignoreFiles, configFilenameIsIgnoredByGitignore, } from '../utils/git.js';
|
|
4
|
-
import { DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME } from '../constants/config.js';
|
|
4
|
+
import { DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME, HS_FOLDER, } from '../constants/config.js';
|
|
5
5
|
import { i18n } from '../utils/lang.js';
|
|
6
6
|
const i18nKey = 'lib.gitignore';
|
|
7
7
|
const GITIGNORE_FILE = '.gitignore';
|
|
@@ -23,6 +23,27 @@ export function checkAndAddConfigToGitignore(configPath) {
|
|
|
23
23
|
throw new Error(i18n(`${i18nKey}.errors.configIgnore`), { cause: e });
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
export function checkAndAddHsFolderToGitignore(settingsPath) {
|
|
27
|
+
try {
|
|
28
|
+
const hsDirPath = path.resolve(path.dirname(settingsPath));
|
|
29
|
+
const { configIgnored, gitignoreFiles } = checkGitInclusion(hsDirPath);
|
|
30
|
+
if (configIgnored)
|
|
31
|
+
return;
|
|
32
|
+
let gitignoreFilePath = gitignoreFiles && gitignoreFiles.length ? gitignoreFiles[0] : null;
|
|
33
|
+
if (!gitignoreFilePath) {
|
|
34
|
+
gitignoreFilePath = path.join(path.dirname(hsDirPath), GITIGNORE_FILE);
|
|
35
|
+
fs.writeFileSync(gitignoreFilePath, '');
|
|
36
|
+
}
|
|
37
|
+
const gitignoreContents = fs.readFileSync(gitignoreFilePath).toString();
|
|
38
|
+
if (gitignoreContents.includes(HS_FOLDER))
|
|
39
|
+
return;
|
|
40
|
+
const updatedContents = `${gitignoreContents.trim()}\n\n# HubSpot link folder\n${HS_FOLDER}\n`;
|
|
41
|
+
fs.writeFileSync(gitignoreFilePath, updatedContents);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
throw new Error(i18n(`${i18nKey}.errors.configIgnore`), { cause: e });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
26
47
|
export function checkGitInclusion(configPath) {
|
|
27
48
|
const result = {
|
|
28
49
|
inGit: false,
|
package/lib/portManager.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RequestPortsData, ServerPortMap } from '../types/PortManager.js';
|
|
2
|
-
export declare
|
|
2
|
+
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
3
3
|
export declare function isPortManagerPortAvailable(): Promise<boolean>;
|
|
4
4
|
export declare function isPortManagerServerRunning(): Promise<boolean>;
|
|
5
|
-
export declare function startPortManagerServer(): Promise<void>;
|
|
5
|
+
export declare function startPortManagerServer(port?: number): Promise<void>;
|
|
6
6
|
export declare function stopPortManagerServer(): Promise<void>;
|
|
7
7
|
export declare function requestPorts(portData: Array<RequestPortsData>): Promise<{
|
|
8
8
|
[instanceId: string]: number;
|
package/lib/portManager.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import { HEALTH_CHECK_PATH, PortManagerServer, SERVICE_HEALTHY, } from '../utils/PortManagerServer.js';
|
|
3
|
-
import {
|
|
3
|
+
import { detectPort } from '../utils/detectPort.js';
|
|
4
4
|
import { logger } from './logger.js';
|
|
5
|
-
export
|
|
5
|
+
export async function isPortAvailable(port) {
|
|
6
|
+
return (await detectPort(port)) === port;
|
|
7
|
+
}
|
|
6
8
|
export async function isPortManagerPortAvailable() {
|
|
7
9
|
return PortManagerServer.portAvailable();
|
|
8
10
|
}
|
|
9
11
|
export async function isPortManagerServerRunning() {
|
|
10
12
|
try {
|
|
11
|
-
const { data } = await axios.get(`${
|
|
13
|
+
const { data } = await axios.get(`${PortManagerServer.baseUrl}${HEALTH_CHECK_PATH}`);
|
|
12
14
|
return data.status === SERVICE_HEALTHY;
|
|
13
15
|
}
|
|
14
16
|
catch (e) {
|
|
@@ -16,36 +18,36 @@ export async function isPortManagerServerRunning() {
|
|
|
16
18
|
return false;
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
|
-
export async function startPortManagerServer() {
|
|
21
|
+
export async function startPortManagerServer(port) {
|
|
20
22
|
const isRunning = await isPortManagerServerRunning();
|
|
21
23
|
if (!isRunning) {
|
|
22
|
-
await PortManagerServer.init();
|
|
24
|
+
await PortManagerServer.init(port);
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
export async function stopPortManagerServer() {
|
|
26
28
|
const isRunning = await isPortManagerServerRunning();
|
|
27
29
|
if (isRunning) {
|
|
28
|
-
await axios.post(`${
|
|
30
|
+
await axios.post(`${PortManagerServer.baseUrl}/close`);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
export async function requestPorts(portData) {
|
|
32
|
-
const { data } = await axios.post(`${
|
|
34
|
+
const { data } = await axios.post(`${PortManagerServer.baseUrl}/servers`, {
|
|
33
35
|
portData: portData,
|
|
34
36
|
});
|
|
35
37
|
return data.ports;
|
|
36
38
|
}
|
|
37
39
|
export async function getActiveServers() {
|
|
38
|
-
const { data } = await axios.get(`${
|
|
40
|
+
const { data } = await axios.get(`${PortManagerServer.baseUrl}/servers`);
|
|
39
41
|
return data.servers;
|
|
40
42
|
}
|
|
41
43
|
export async function getServerPortByInstanceId(serverInstanceId) {
|
|
42
|
-
const { data } = await axios.get(`${
|
|
44
|
+
const { data } = await axios.get(`${PortManagerServer.baseUrl}/servers/${serverInstanceId}`);
|
|
43
45
|
return data.port;
|
|
44
46
|
}
|
|
45
47
|
export async function deleteServerInstance(serverInstanceId) {
|
|
46
|
-
await axios.delete(`${
|
|
48
|
+
await axios.delete(`${PortManagerServer.baseUrl}/servers/${serverInstanceId}`);
|
|
47
49
|
}
|
|
48
50
|
export async function portManagerHasActiveServers() {
|
|
49
|
-
const { data } = await axios.get(`${
|
|
51
|
+
const { data } = await axios.get(`${PortManagerServer.baseUrl}/servers`);
|
|
50
52
|
return data.count > 0;
|
|
51
53
|
}
|
|
@@ -101,7 +101,13 @@ export class HubSpotHttpError extends Error {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
generatedContext.accountId = cause.config?.params?.portalId;
|
|
104
|
-
|
|
104
|
+
// Axios serializes request bodies before the error fires, so `config.data`
|
|
105
|
+
// is often already a JSON string. Avoid re-stringifying so debug output is
|
|
106
|
+
// readable instead of escape-soup.
|
|
107
|
+
generatedContext.payload =
|
|
108
|
+
typeof cause.config?.data === 'string'
|
|
109
|
+
? cause.config.data
|
|
110
|
+
: JSON.stringify(cause.config?.data);
|
|
105
111
|
// This will just be the url path
|
|
106
112
|
generatedContext.request = cause.config?.url;
|
|
107
113
|
// Allow the provided context to override the generated context
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/local-dev-lib",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9-experimental.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Provides library functionality for HubSpot local development tooling, including the HubSpot CLI",
|
|
6
6
|
"files": [
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"./config/defaultAccountOverride": "./config/defaultAccountOverride.js",
|
|
60
60
|
"./config/migrate": "./config/migrate.js",
|
|
61
61
|
"./config/state": "./config/state.js",
|
|
62
|
+
"./config/hsSettings": "./config/hsSettings.js",
|
|
62
63
|
"./config": "./config/index.js",
|
|
63
64
|
"./constants/*": "./constants/*.js",
|
|
64
65
|
"./enums/*": "./enums/*.js",
|
|
@@ -70,13 +71,13 @@
|
|
|
70
71
|
},
|
|
71
72
|
"dependencies": {
|
|
72
73
|
"address": "2.0.2",
|
|
73
|
-
"axios": "1.
|
|
74
|
+
"axios": "1.15.2",
|
|
74
75
|
"chalk": "5.6.2",
|
|
75
76
|
"chokidar": "3.6.0",
|
|
76
77
|
"content-disposition": "0.5.4",
|
|
77
78
|
"cors": "2.8.5",
|
|
78
79
|
"debounce": "1.2.1",
|
|
79
|
-
"express": "4.
|
|
80
|
+
"express": "4.22.1",
|
|
80
81
|
"extract-zip": "2.0.1",
|
|
81
82
|
"findup-sync": "5.0.0",
|
|
82
83
|
"form-data": "^4.0.4",
|
package/types/Config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONFIG_FLAGS, HUBSPOT_CONFIG_ERROR_TYPES, HUBSPOT_CONFIG_OPERATIONS } from '../constants/config.js';
|
|
1
|
+
import { CONFIG_FLAGS, HUBSPOT_CONFIG_ERROR_TYPES, HUBSPOT_CONFIG_OPERATIONS, STATE_FLAGS } from '../constants/config.js';
|
|
2
2
|
import { DeprecatedHubSpotConfigAccountFields, Environment, HubSpotConfigAccount } from './Accounts.js';
|
|
3
3
|
import { CmsPublishMode } from './Files.js';
|
|
4
4
|
import { ValueOf } from './Utils.js';
|
|
@@ -28,7 +28,8 @@ export type GitInclusionResult = {
|
|
|
28
28
|
};
|
|
29
29
|
export type ConfigFlag = ValueOf<typeof CONFIG_FLAGS>;
|
|
30
30
|
export type HubSpotState = {
|
|
31
|
-
|
|
31
|
+
[STATE_FLAGS.MCP_TOTAL_TOOL_CALLS]: number;
|
|
32
|
+
[STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION]?: string;
|
|
32
33
|
};
|
|
33
34
|
export type HubSpotConfigErrorType = ValueOf<typeof HUBSPOT_CONFIG_ERROR_TYPES>;
|
|
34
35
|
export type HubSpotConfigOperation = ValueOf<typeof HUBSPOT_CONFIG_OPERATIONS>;
|
package/types/Config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import { STATE_FLAGS, } from '../constants/config.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/types/Project.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Build } from './Build.js';
|
|
2
2
|
import { GithubSourceData } from './Github.js';
|
|
3
3
|
import { ProjectLog } from './ProjectLog.js';
|
|
4
|
+
import { ValueOf } from './Utils.js';
|
|
5
|
+
import { SUBBUILD_TYPES } from '../enums/build.js';
|
|
4
6
|
export type Project = {
|
|
5
7
|
createdAt: number;
|
|
6
8
|
deletedAt: number;
|
|
@@ -48,3 +50,31 @@ export type FetchPlatformVersionResponse = {
|
|
|
48
50
|
export type WarnLogsResponse = {
|
|
49
51
|
logs: Array<ProjectLog>;
|
|
50
52
|
};
|
|
53
|
+
export type Release = {
|
|
54
|
+
releaseTag: string;
|
|
55
|
+
buildId: number;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
components?: Array<{
|
|
58
|
+
buildType: ValueOf<typeof SUBBUILD_TYPES>;
|
|
59
|
+
buildName?: string;
|
|
60
|
+
rootPath?: string;
|
|
61
|
+
id?: string;
|
|
62
|
+
}>;
|
|
63
|
+
};
|
|
64
|
+
export type FetchListReleasesResponse = {
|
|
65
|
+
results: Array<Release>;
|
|
66
|
+
paging: {
|
|
67
|
+
next: {
|
|
68
|
+
after: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export type AutoReleaseResponse = {
|
|
73
|
+
releaseTag: string;
|
|
74
|
+
status: string;
|
|
75
|
+
appId: number;
|
|
76
|
+
};
|
|
77
|
+
export type AutoReleaseStatusResponse = {
|
|
78
|
+
status: 'PENDING' | 'COMPLETE';
|
|
79
|
+
currentReleaseTag?: string;
|
|
80
|
+
};
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Express } from 'express';
|
|
2
|
-
import { Server } from 'http';
|
|
3
|
-
import { ServerPortMap } from '../types/PortManager.js';
|
|
4
1
|
export declare const HEALTH_CHECK_PATH = "/port-manager-health-check";
|
|
5
2
|
export declare const SERVICE_HEALTHY = "OK";
|
|
6
3
|
declare class _PortManagerServer {
|
|
7
|
-
app
|
|
8
|
-
server
|
|
9
|
-
serverPortMap
|
|
4
|
+
private app?;
|
|
5
|
+
private server?;
|
|
6
|
+
private serverPortMap;
|
|
7
|
+
private port;
|
|
10
8
|
constructor();
|
|
11
|
-
|
|
9
|
+
get baseUrl(): string;
|
|
10
|
+
init(port?: number): Promise<void>;
|
|
12
11
|
private reset;
|
|
13
12
|
portAvailable(): Promise<boolean>;
|
|
14
13
|
private listen;
|
|
@@ -11,13 +11,21 @@ class _PortManagerServer {
|
|
|
11
11
|
app;
|
|
12
12
|
server;
|
|
13
13
|
serverPortMap;
|
|
14
|
+
port;
|
|
14
15
|
constructor() {
|
|
15
16
|
this.serverPortMap = {};
|
|
17
|
+
this.port = PORT_MANAGER_SERVER_PORT;
|
|
16
18
|
}
|
|
17
|
-
|
|
19
|
+
get baseUrl() {
|
|
20
|
+
return `http://localhost:${this.port}`;
|
|
21
|
+
}
|
|
22
|
+
async init(port) {
|
|
23
|
+
if (port) {
|
|
24
|
+
this.port = port;
|
|
25
|
+
}
|
|
18
26
|
if (!(await this.portAvailable())) {
|
|
19
27
|
throw new Error(i18n(`${i18nKey}.errors.portInUse`, {
|
|
20
|
-
port:
|
|
28
|
+
port: this.port,
|
|
21
29
|
}));
|
|
22
30
|
}
|
|
23
31
|
if (this.app) {
|
|
@@ -34,15 +42,16 @@ class _PortManagerServer {
|
|
|
34
42
|
this.app = undefined;
|
|
35
43
|
this.server = undefined;
|
|
36
44
|
this.serverPortMap = {};
|
|
45
|
+
this.port = PORT_MANAGER_SERVER_PORT;
|
|
37
46
|
}
|
|
38
47
|
async portAvailable() {
|
|
39
|
-
return (
|
|
48
|
+
return (await detectPort(this.port)) === this.port;
|
|
40
49
|
}
|
|
41
50
|
listen() {
|
|
42
51
|
return new Promise((resolve, reject) => {
|
|
43
|
-
const server = this.app.listen(
|
|
52
|
+
const server = this.app.listen(this.port, () => {
|
|
44
53
|
logger.debug(i18n(`${i18nKey}.started`, {
|
|
45
|
-
port:
|
|
54
|
+
port: this.port,
|
|
46
55
|
}));
|
|
47
56
|
resolve(server);
|
|
48
57
|
}).on('error', (err) => {
|