@hubspot/local-dev-lib 0.4.1-experimental.0 → 0.4.3-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/appsDev.d.ts +1 -0
- package/api/appsDev.js +10 -1
- package/api/crm.d.ts +3 -0
- package/api/crm.js +29 -0
- package/api/github.js +28 -22
- package/api/localDevAuth.d.ts +1 -1
- package/config/CLIConfiguration.js +11 -8
- package/config/configUtils.js +2 -2
- package/config/config_DEPRECATED.js +2 -4
- package/config/migrate.js +2 -0
- package/config/state.d.ts +3 -0
- package/config/state.js +104 -0
- package/constants/config.d.ts +4 -0
- package/constants/config.js +5 -1
- package/lang/en.json +36 -7
- package/lib/cms/uploadFolder.js +35 -13
- package/lib/crm.d.ts +6 -0
- package/lib/crm.js +55 -0
- package/lib/gitignore.js +1 -1
- package/lib/hubdb.d.ts +1 -1
- package/lib/isDeepEqual.d.ts +1 -0
- package/lib/isDeepEqual.js +35 -0
- package/lib/portManager.d.ts +1 -0
- package/lib/portManager.js +6 -1
- package/package.json +5 -2
- package/types/Build.d.ts +1 -0
- package/types/Config.d.ts +4 -1
- package/types/Crm.d.ts +26 -0
- package/types/Crm.js +2 -0
- package/types/Deploy.d.ts +1 -2
- package/utils/accounts.js +2 -2
package/api/appsDev.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export declare function fetchPublicAppDeveloperTestAccountInstallData(appId: num
|
|
|
5
5
|
export declare function fetchPublicAppProductionInstallCounts(appId: number, accountId: number): HubSpotPromise<PublicAppInstallCounts>;
|
|
6
6
|
export declare function fetchPublicAppMetadata(appId: number, accountId: number): HubSpotPromise<PublicApp>;
|
|
7
7
|
export declare function installStaticAuthAppOnTestAccount(appId: number, accountId: number, scopeGroupIds: number[]): HubSpotPromise<void>;
|
|
8
|
+
export declare function fetchAppMetadataByUid(appUid: string, accountId: number): HubSpotPromise<PublicApp>;
|
package/api/appsDev.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.installStaticAuthAppOnTestAccount = exports.fetchPublicAppMetadata = exports.fetchPublicAppProductionInstallCounts = exports.fetchPublicAppDeveloperTestAccountInstallData = exports.fetchPublicAppsForPortal = void 0;
|
|
3
|
+
exports.fetchAppMetadataByUid = exports.installStaticAuthAppOnTestAccount = exports.fetchPublicAppMetadata = exports.fetchPublicAppProductionInstallCounts = exports.fetchPublicAppDeveloperTestAccountInstallData = exports.fetchPublicAppsForPortal = void 0;
|
|
4
4
|
const http_1 = require("../http");
|
|
5
5
|
const APPS_DEV_API_PATH = 'apps-dev/external/public/v3';
|
|
6
6
|
const APPS_HUBLETS_API_PATH = 'apps-hublets/external/static-token/v3';
|
|
@@ -39,3 +39,12 @@ function installStaticAuthAppOnTestAccount(appId, accountId, scopeGroupIds) {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
exports.installStaticAuthAppOnTestAccount = installStaticAuthAppOnTestAccount;
|
|
42
|
+
function fetchAppMetadataByUid(appUid, accountId) {
|
|
43
|
+
return http_1.http.get(accountId, {
|
|
44
|
+
url: `${APPS_DEV_API_PATH}/full/portal/sourceId`,
|
|
45
|
+
params: {
|
|
46
|
+
sourceId: appUid,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
exports.fetchAppMetadataByUid = fetchAppMetadataByUid;
|
package/api/crm.d.ts
ADDED
package/api/crm.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createImport = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
10
|
+
const http_1 = require("../http");
|
|
11
|
+
const path_2 = require("../lib/path");
|
|
12
|
+
const HUBSPOT_CRM_IMPORT_PATH = '/crm/v3/imports';
|
|
13
|
+
function createImport(accountId, importRequest, dataFileNames) {
|
|
14
|
+
const jsonImportRequest = JSON.stringify(importRequest);
|
|
15
|
+
const formData = new form_data_1.default();
|
|
16
|
+
formData.append('importRequest', jsonImportRequest);
|
|
17
|
+
dataFileNames.forEach(file => {
|
|
18
|
+
const stream = fs_extra_1.default.createReadStream(path_1.default.resolve((0, path_2.getCwd)(), file));
|
|
19
|
+
formData.append('files', stream, file);
|
|
20
|
+
});
|
|
21
|
+
return http_1.http.post(accountId, {
|
|
22
|
+
url: `${HUBSPOT_CRM_IMPORT_PATH}`,
|
|
23
|
+
data: formData,
|
|
24
|
+
headers: {
|
|
25
|
+
...formData.getHeaders(),
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.createImport = createImport;
|
package/api/github.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.fetchRepoContents = exports.fetchRepoFileByDownloadUrl = exports.fetchRepoFile = exports.fetchRepoAsZip = exports.fetchRepoReleaseData = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const getAxiosConfig_1 = require("../http/getAxiosConfig");
|
|
9
|
+
const errors_1 = require("../errors");
|
|
9
10
|
const GITHUB_REPOS_API = 'https://api.github.com/repos';
|
|
10
11
|
const GITHUB_RAW_CONTENT_API_PATH = 'https://raw.githubusercontent.com';
|
|
11
12
|
function getAdditionalHeaders() {
|
|
@@ -18,16 +19,33 @@ function getAdditionalHeaders() {
|
|
|
18
19
|
}
|
|
19
20
|
return headers;
|
|
20
21
|
}
|
|
22
|
+
function githubRequestWithFallback(url, responseType) {
|
|
23
|
+
const headersWithAuth = {
|
|
24
|
+
...(0, getAxiosConfig_1.getDefaultUserAgentHeader)(),
|
|
25
|
+
...getAdditionalHeaders(),
|
|
26
|
+
};
|
|
27
|
+
if (headersWithAuth.authorization) {
|
|
28
|
+
return axios_1.default
|
|
29
|
+
.get(url, { headers: headersWithAuth, responseType })
|
|
30
|
+
.catch(error => {
|
|
31
|
+
// 404 with an auth token might mean an SSO issue so retry without the authorization header
|
|
32
|
+
if ((0, errors_1.isSpecifiedError)(error, { statusCode: 404 })) {
|
|
33
|
+
return axios_1.default.get(url, {
|
|
34
|
+
headers: { ...(0, getAxiosConfig_1.getDefaultUserAgentHeader)() },
|
|
35
|
+
responseType,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// No auth token, proceed normally
|
|
42
|
+
return axios_1.default.get(url, { headers: headersWithAuth, responseType });
|
|
43
|
+
}
|
|
21
44
|
// Returns information about the repo's releases. Defaults to "latest" if no tag is provided
|
|
22
45
|
// https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-a-release-by-tag-name
|
|
23
46
|
function fetchRepoReleaseData(repoPath, tag = '') {
|
|
24
47
|
const URL = `${GITHUB_REPOS_API}/${repoPath}/releases`;
|
|
25
|
-
return
|
|
26
|
-
headers: {
|
|
27
|
-
...(0, getAxiosConfig_1.getDefaultUserAgentHeader)(),
|
|
28
|
-
...getAdditionalHeaders(),
|
|
29
|
-
},
|
|
30
|
-
});
|
|
48
|
+
return githubRequestWithFallback(`${URL}/${tag ? `tags/${tag}` : 'latest'}`);
|
|
31
49
|
}
|
|
32
50
|
exports.fetchRepoReleaseData = fetchRepoReleaseData;
|
|
33
51
|
// Returns the entire repo content as a zip, using the zipball_url from fetchRepoReleaseData()
|
|
@@ -41,31 +59,19 @@ function fetchRepoAsZip(zipUrl) {
|
|
|
41
59
|
exports.fetchRepoAsZip = fetchRepoAsZip;
|
|
42
60
|
// Returns the raw file contents via the raw.githubusercontent endpoint
|
|
43
61
|
function fetchRepoFile(repoPath, filePath, ref) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
...(0, getAxiosConfig_1.getDefaultUserAgentHeader)(),
|
|
47
|
-
...getAdditionalHeaders(),
|
|
48
|
-
},
|
|
49
|
-
});
|
|
62
|
+
const url = `${GITHUB_RAW_CONTENT_API_PATH}/${repoPath}/${ref}/${filePath}`;
|
|
63
|
+
return githubRequestWithFallback(url);
|
|
50
64
|
}
|
|
51
65
|
exports.fetchRepoFile = fetchRepoFile;
|
|
52
66
|
// Returns the raw file contents via the raw.githubusercontent endpoint
|
|
53
67
|
function fetchRepoFileByDownloadUrl(downloadUrl) {
|
|
54
|
-
return
|
|
55
|
-
headers: { ...(0, getAxiosConfig_1.getDefaultUserAgentHeader)(), ...getAdditionalHeaders() },
|
|
56
|
-
responseType: 'arraybuffer',
|
|
57
|
-
});
|
|
68
|
+
return githubRequestWithFallback(downloadUrl, 'arraybuffer');
|
|
58
69
|
}
|
|
59
70
|
exports.fetchRepoFileByDownloadUrl = fetchRepoFileByDownloadUrl;
|
|
60
71
|
// Returns the contents of a file or directory in a repository by path
|
|
61
72
|
// https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-repository-content
|
|
62
73
|
function fetchRepoContents(repoPath, path, ref) {
|
|
63
74
|
const refQuery = ref ? `?ref=${ref}` : '';
|
|
64
|
-
return
|
|
65
|
-
headers: {
|
|
66
|
-
...(0, getAxiosConfig_1.getDefaultUserAgentHeader)(),
|
|
67
|
-
...getAdditionalHeaders(),
|
|
68
|
-
},
|
|
69
|
-
});
|
|
75
|
+
return githubRequestWithFallback(`${GITHUB_REPOS_API}/${repoPath}/contents/${path}${refQuery}`);
|
|
70
76
|
}
|
|
71
77
|
exports.fetchRepoContents = fetchRepoContents;
|
package/api/localDevAuth.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ export declare function fetchAccessToken(personalAccessKey: string, env?: Enviro
|
|
|
7
7
|
export declare function fetchScopeData(accountId: number, scopeGroup: string): HubSpotPromise<ScopeData>;
|
|
8
8
|
export declare function fetchScopeAuthorizationData(accountId: number): HubSpotPromise<ScopeAuthorizationResponse>;
|
|
9
9
|
export declare function fetchAppInstallationData(portalId: number, projectId: number, appUid: string, requiredScopeGroups: Array<string>, optionalScopeGroups?: Array<string>): HubSpotPromise<PublicAppInstallationData>;
|
|
10
|
-
export declare function fetchEnabledFeatures(accountId: number): Promise<import("axios").AxiosResponse<EnabledFeaturesResponse, any>>;
|
|
10
|
+
export declare function fetchEnabledFeatures(accountId: number): Promise<import("axios").AxiosResponse<EnabledFeaturesResponse, any, {}>>;
|
|
@@ -46,7 +46,7 @@ class _CLIConfiguration {
|
|
|
46
46
|
const configFromEnv = (0, environment_1.loadConfigFromEnvironment)();
|
|
47
47
|
if (configFromEnv) {
|
|
48
48
|
logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.load.configFromEnv`, {
|
|
49
|
-
accountId: configFromEnv.accounts[0].accountId
|
|
49
|
+
accountId: `${configFromEnv.accounts?.[0].accountId}`,
|
|
50
50
|
}));
|
|
51
51
|
this.useEnvConfig = true;
|
|
52
52
|
this.config = this.handleLegacyCmsPublishMode(configFromEnv);
|
|
@@ -168,11 +168,11 @@ class _CLIConfiguration {
|
|
|
168
168
|
}
|
|
169
169
|
let account = null;
|
|
170
170
|
if (name) {
|
|
171
|
-
account = this.config.accounts
|
|
171
|
+
account = this.config.accounts?.find(a => a.name === name) || null;
|
|
172
172
|
}
|
|
173
173
|
if (accountId && !account) {
|
|
174
174
|
account =
|
|
175
|
-
this.config.accounts
|
|
175
|
+
this.config.accounts?.find(a => accountId === a.accountId) || null;
|
|
176
176
|
}
|
|
177
177
|
return account;
|
|
178
178
|
}
|
|
@@ -230,7 +230,7 @@ class _CLIConfiguration {
|
|
|
230
230
|
return account.name || account.accountId;
|
|
231
231
|
}
|
|
232
232
|
getAccountIndex(accountId) {
|
|
233
|
-
return this.config
|
|
233
|
+
return this.config && Array.isArray(this.config.accounts)
|
|
234
234
|
? this.config.accounts.findIndex(account => account.accountId === accountId)
|
|
235
235
|
: -1;
|
|
236
236
|
}
|
|
@@ -243,10 +243,10 @@ class _CLIConfiguration {
|
|
|
243
243
|
isAccountInConfig(nameOrId) {
|
|
244
244
|
if (typeof nameOrId === 'string') {
|
|
245
245
|
return (!!this.config &&
|
|
246
|
-
this.config.accounts &&
|
|
246
|
+
!!this.config.accounts &&
|
|
247
247
|
!!this.getAccountId(nameOrId.toLowerCase()));
|
|
248
248
|
}
|
|
249
|
-
return (!!this.config && this.config.accounts && !!this.getAccountId(nameOrId));
|
|
249
|
+
return (!!this.config && !!this.config.accounts && !!this.getAccountId(nameOrId));
|
|
250
250
|
}
|
|
251
251
|
getAndLoadConfigIfNeeded(options) {
|
|
252
252
|
if (!this.config) {
|
|
@@ -341,7 +341,7 @@ class _CLIConfiguration {
|
|
|
341
341
|
safelyApplyUpdates('accountType', this.getAccountType(updatedAccountType, sandboxAccountType));
|
|
342
342
|
safelyApplyUpdates('parentAccountId', parentAccountId);
|
|
343
343
|
const completedAccountConfig = nextAccountConfig;
|
|
344
|
-
if (!
|
|
344
|
+
if (!Array.isArray(this.config.accounts)) {
|
|
345
345
|
this.config.accounts = [];
|
|
346
346
|
}
|
|
347
347
|
if (currentAccountConfig) {
|
|
@@ -429,7 +429,10 @@ class _CLIConfiguration {
|
|
|
429
429
|
if (accountConfig) {
|
|
430
430
|
logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.removeAccountFromConfig.deleting`, { accountId }));
|
|
431
431
|
const index = this.getAccountIndex(accountId);
|
|
432
|
-
|
|
432
|
+
if (index === -1) {
|
|
433
|
+
return removedAccountIsDefault;
|
|
434
|
+
}
|
|
435
|
+
this.config.accounts?.splice(index, 1);
|
|
433
436
|
if (this.getDefaultAccount() === accountConfig.name) {
|
|
434
437
|
removedAccountIsDefault = true;
|
|
435
438
|
}
|
package/config/configUtils.js
CHANGED
|
@@ -24,7 +24,7 @@ function getOrderedConfig(unorderedConfig) {
|
|
|
24
24
|
httpTimeout,
|
|
25
25
|
allowUsageTracking,
|
|
26
26
|
...rest,
|
|
27
|
-
accounts: accounts
|
|
27
|
+
accounts: accounts?.map(getOrderedAccount) || [],
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
exports.getOrderedConfig = getOrderedConfig;
|
|
@@ -80,7 +80,7 @@ function generateConfig(type, options) {
|
|
|
80
80
|
return null;
|
|
81
81
|
}
|
|
82
82
|
if (configAccount) {
|
|
83
|
-
config.accounts
|
|
83
|
+
config.accounts?.push(configAccount);
|
|
84
84
|
}
|
|
85
85
|
return config;
|
|
86
86
|
}
|
|
@@ -14,7 +14,6 @@ const auth_1 = require("../constants/auth");
|
|
|
14
14
|
const files_1 = require("../constants/files");
|
|
15
15
|
const environment_1 = require("../lib/environment");
|
|
16
16
|
const logger_1 = require("../lib/logger");
|
|
17
|
-
const git_1 = require("../utils/git");
|
|
18
17
|
const errors_DEPRECATED_1 = require("../errors/errors_DEPRECATED");
|
|
19
18
|
const ALL_CMS_PUBLISH_MODES = Object.values(files_1.CMS_PUBLISH_MODE);
|
|
20
19
|
let _config;
|
|
@@ -191,12 +190,11 @@ function readConfigFile() {
|
|
|
191
190
|
return { source, error };
|
|
192
191
|
}
|
|
193
192
|
try {
|
|
194
|
-
(0, git_1.isConfigPathInGitRepo)(_configPath);
|
|
195
193
|
source = fs_extra_1.default.readFileSync(_configPath);
|
|
196
194
|
}
|
|
197
195
|
catch (err) {
|
|
198
196
|
error = err;
|
|
199
|
-
logger_1.logger.error(
|
|
197
|
+
logger_1.logger.error(`Config file could not be read: ${_configPath}`);
|
|
200
198
|
(0, errors_DEPRECATED_1.logFileSystemErrorInstance)(error, {
|
|
201
199
|
filepath: _configPath,
|
|
202
200
|
operation: 'read',
|
|
@@ -215,7 +213,7 @@ function parseConfig(configSource) {
|
|
|
215
213
|
}
|
|
216
214
|
catch (err) {
|
|
217
215
|
error = err;
|
|
218
|
-
logger_1.logger.error(
|
|
216
|
+
logger_1.logger.error(`Config file could not be parsed: ${_configPath}`);
|
|
219
217
|
(0, errors_DEPRECATED_1.logErrorInstance)(err);
|
|
220
218
|
}
|
|
221
219
|
return { parsed, error };
|
package/config/migrate.js
CHANGED
|
@@ -105,6 +105,8 @@ function mergeConfigProperties(globalConfig, deprecatedConfig, force) {
|
|
|
105
105
|
config_1.ENV,
|
|
106
106
|
config_1.HTTP_USE_LOCALHOST,
|
|
107
107
|
config_1.ALLOW_USAGE_TRACKING,
|
|
108
|
+
config_1.AUTO_OPEN_BROWSER,
|
|
109
|
+
config_1.ALLOW_AUTO_UPDATES,
|
|
108
110
|
];
|
|
109
111
|
const conflicts = [];
|
|
110
112
|
propertiesToCheck.forEach(prop => {
|
package/config/state.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.setStateValue = exports.getStateValue = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const lang_1 = require("../utils/lang");
|
|
30
|
+
const config_1 = require("../constants/config");
|
|
31
|
+
const logger_1 = require("../lib/logger");
|
|
32
|
+
const i18nKey = 'config.state';
|
|
33
|
+
const DEFAULT_STATE = {
|
|
34
|
+
mcpTotalToolCalls: 0,
|
|
35
|
+
};
|
|
36
|
+
function ensureCLIDirectory() {
|
|
37
|
+
try {
|
|
38
|
+
const dir = path.dirname(config_1.STATE_FILE_PATH);
|
|
39
|
+
if (!fs.existsSync(dir)) {
|
|
40
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error((0, lang_1.i18n)(`${i18nKey}.ensureCLIDirectory.errors.cannotCreateDirectory`, {
|
|
45
|
+
error: error instanceof Error ? error.message : String(error),
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function sanitizeAndMerge(parsed) {
|
|
50
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
51
|
+
return structuredClone(DEFAULT_STATE);
|
|
52
|
+
}
|
|
53
|
+
const state = parsed;
|
|
54
|
+
const result = structuredClone(DEFAULT_STATE);
|
|
55
|
+
for (const key in DEFAULT_STATE) {
|
|
56
|
+
const typedKey = key;
|
|
57
|
+
if (key in state &&
|
|
58
|
+
typeof state[typedKey] === typeof DEFAULT_STATE[typedKey]) {
|
|
59
|
+
result[typedKey] = state[typedKey];
|
|
60
|
+
}
|
|
61
|
+
// keys not in parsed file remain as DEFAULT values
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
function getCurrentState() {
|
|
66
|
+
try {
|
|
67
|
+
if (!fs.existsSync(config_1.STATE_FILE_PATH)) {
|
|
68
|
+
return structuredClone(DEFAULT_STATE);
|
|
69
|
+
}
|
|
70
|
+
const data = fs.readFileSync(config_1.STATE_FILE_PATH, 'utf-8');
|
|
71
|
+
if (!data?.trim()) {
|
|
72
|
+
logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.getCurrentState.debug.emptyStateFile`));
|
|
73
|
+
return structuredClone(DEFAULT_STATE);
|
|
74
|
+
}
|
|
75
|
+
const parsed = JSON.parse(data);
|
|
76
|
+
return sanitizeAndMerge(parsed);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.getCurrentState.errors.errorReading`, {
|
|
80
|
+
error: error instanceof Error ? error.message : String(error),
|
|
81
|
+
}));
|
|
82
|
+
return structuredClone(DEFAULT_STATE);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function getStateValue(key) {
|
|
86
|
+
ensureCLIDirectory();
|
|
87
|
+
const state = getCurrentState();
|
|
88
|
+
return state[key];
|
|
89
|
+
}
|
|
90
|
+
exports.getStateValue = getStateValue;
|
|
91
|
+
function setStateValue(key, value) {
|
|
92
|
+
ensureCLIDirectory();
|
|
93
|
+
const currentState = getCurrentState();
|
|
94
|
+
const newState = { ...currentState, [key]: value };
|
|
95
|
+
try {
|
|
96
|
+
fs.writeFileSync(config_1.STATE_FILE_PATH, JSON.stringify(newState, null, 2), 'utf-8');
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error((0, lang_1.i18n)(`${i18nKey}.setStateValue.errors.failedToWrite`, {
|
|
100
|
+
error: error instanceof Error ? error.message : String(error),
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.setStateValue = setStateValue;
|
package/constants/config.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ export declare const DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME = "hubspot.config.yml
|
|
|
2
2
|
export declare const ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME = "archived.hubspot.config.yml";
|
|
3
3
|
export declare const HUBSPOT_CONFIGURATION_FOLDER = ".hscli";
|
|
4
4
|
export declare const HUBSPOT_CONFIGURATION_FILE = "config.yml";
|
|
5
|
+
export declare const HUBSPOT_STATE_FILE = "state.json";
|
|
5
6
|
export declare const GLOBAL_CONFIG_PATH: string;
|
|
7
|
+
export declare const STATE_FILE_PATH: string;
|
|
6
8
|
export declare const DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME = ".hsaccount";
|
|
7
9
|
export declare const DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID = "DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID";
|
|
8
10
|
export declare const DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND = "DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND";
|
|
@@ -11,6 +13,8 @@ export declare const HTTP_TIMEOUT = "httpTimeout";
|
|
|
11
13
|
export declare const ENV = "env";
|
|
12
14
|
export declare const HTTP_USE_LOCALHOST = "httpUseLocalhost";
|
|
13
15
|
export declare const ALLOW_USAGE_TRACKING = "allowUsageTracking";
|
|
16
|
+
export declare const AUTO_OPEN_BROWSER = "autoOpenBrowser";
|
|
17
|
+
export declare const ALLOW_AUTO_UPDATES = "allowAutoUpdates";
|
|
14
18
|
export declare const DEFAULT_ACCOUNT = "defaultAccount";
|
|
15
19
|
export declare const DEFAULT_PORTAL = "defaultPortal";
|
|
16
20
|
export declare const MIN_HTTP_TIMEOUT = 3000;
|
package/constants/config.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.HUBSPOT_ACCOUNT_TYPE_STRINGS = exports.HUBSPOT_ACCOUNT_TYPES = exports.MIN_HTTP_TIMEOUT = exports.DEFAULT_PORTAL = exports.DEFAULT_ACCOUNT = exports.ALLOW_USAGE_TRACKING = exports.HTTP_USE_LOCALHOST = exports.ENV = exports.HTTP_TIMEOUT = exports.DEFAULT_CMS_PUBLISH_MODE = exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND = exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID = exports.DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME = exports.GLOBAL_CONFIG_PATH = exports.HUBSPOT_CONFIGURATION_FILE = exports.HUBSPOT_CONFIGURATION_FOLDER = exports.ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME = exports.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME = void 0;
|
|
6
|
+
exports.HUBSPOT_ACCOUNT_TYPE_STRINGS = exports.HUBSPOT_ACCOUNT_TYPES = exports.MIN_HTTP_TIMEOUT = exports.DEFAULT_PORTAL = exports.DEFAULT_ACCOUNT = exports.ALLOW_AUTO_UPDATES = exports.AUTO_OPEN_BROWSER = exports.ALLOW_USAGE_TRACKING = exports.HTTP_USE_LOCALHOST = exports.ENV = exports.HTTP_TIMEOUT = exports.DEFAULT_CMS_PUBLISH_MODE = exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND = exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID = exports.DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME = exports.STATE_FILE_PATH = exports.GLOBAL_CONFIG_PATH = exports.HUBSPOT_STATE_FILE = exports.HUBSPOT_CONFIGURATION_FILE = exports.HUBSPOT_CONFIGURATION_FOLDER = exports.ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME = exports.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME = void 0;
|
|
7
7
|
const lang_1 = require("../utils/lang");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
@@ -11,7 +11,9 @@ exports.DEFAULT_HUBSPOT_CONFIG_YAML_FILE_NAME = 'hubspot.config.yml';
|
|
|
11
11
|
exports.ARCHIVED_HUBSPOT_CONFIG_YAML_FILE_NAME = 'archived.hubspot.config.yml';
|
|
12
12
|
exports.HUBSPOT_CONFIGURATION_FOLDER = '.hscli';
|
|
13
13
|
exports.HUBSPOT_CONFIGURATION_FILE = 'config.yml';
|
|
14
|
+
exports.HUBSPOT_STATE_FILE = 'state.json';
|
|
14
15
|
exports.GLOBAL_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), exports.HUBSPOT_CONFIGURATION_FOLDER, exports.HUBSPOT_CONFIGURATION_FILE);
|
|
16
|
+
exports.STATE_FILE_PATH = path_1.default.join(os_1.default.homedir(), exports.HUBSPOT_CONFIGURATION_FOLDER, exports.HUBSPOT_STATE_FILE);
|
|
15
17
|
exports.DEFAULT_ACCOUNT_OVERRIDE_FILE_NAME = '.hsaccount';
|
|
16
18
|
exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID = 'DEFAULT_ACCOUNT_OVERRIDE_ERROR_INVALID_ID';
|
|
17
19
|
exports.DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND = 'DEFAULT_ACCOUNT_OVERRIDE_ERROR_ACCOUNT_NOT_FOUND';
|
|
@@ -20,6 +22,8 @@ exports.HTTP_TIMEOUT = 'httpTimeout';
|
|
|
20
22
|
exports.ENV = 'env';
|
|
21
23
|
exports.HTTP_USE_LOCALHOST = 'httpUseLocalhost';
|
|
22
24
|
exports.ALLOW_USAGE_TRACKING = 'allowUsageTracking';
|
|
25
|
+
exports.AUTO_OPEN_BROWSER = 'autoOpenBrowser';
|
|
26
|
+
exports.ALLOW_AUTO_UPDATES = 'allowAutoUpdates';
|
|
23
27
|
exports.DEFAULT_ACCOUNT = 'defaultAccount';
|
|
24
28
|
exports.DEFAULT_PORTAL = 'defaultPortal';
|
|
25
29
|
exports.MIN_HTTP_TIMEOUT = 3000;
|
package/lang/en.json
CHANGED
|
@@ -78,6 +78,15 @@
|
|
|
78
78
|
"invalidPersonalAccessKey": "Error while retrieving new access token: {{ errorMessage }}"
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
|
+
"crm": {
|
|
82
|
+
"importData": {
|
|
83
|
+
"errors": {
|
|
84
|
+
"fileNotFound": "The file {{ fileName }} does not exist",
|
|
85
|
+
"notJson": "You must provide a JSON file for the import data request schema.",
|
|
86
|
+
"noFiles": "You must provide at least one data file for the import data request schema."
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
81
90
|
"cms": {
|
|
82
91
|
"modules": {
|
|
83
92
|
"createModule": {
|
|
@@ -243,13 +252,13 @@
|
|
|
243
252
|
"empty": "The config file was empty. Initializing an empty config."
|
|
244
253
|
},
|
|
245
254
|
"validate": {
|
|
246
|
-
"noConfig": "
|
|
247
|
-
"noConfigAccounts": "
|
|
248
|
-
"emptyAccountConfig": "
|
|
249
|
-
"noAccountId": "
|
|
250
|
-
"duplicateAccountIds": "
|
|
251
|
-
"duplicateAccountNames": "
|
|
252
|
-
"nameContainsSpaces": "
|
|
255
|
+
"noConfig": "Validation failed: No config was found.",
|
|
256
|
+
"noConfigAccounts": "Validation failed: config.accounts[] is not defined.",
|
|
257
|
+
"emptyAccountConfig": "Validation failed: config.accounts[] has an empty entry.",
|
|
258
|
+
"noAccountId": "Validation failed: config.accounts[] has an entry missing accountId.",
|
|
259
|
+
"duplicateAccountIds": "Validation failed: config.accounts[] has multiple entries with {{ accountId }}.",
|
|
260
|
+
"duplicateAccountNames": "Validation failed: config.accounts[] has multiple entries with {{ accountName }}.",
|
|
261
|
+
"nameContainsSpaces": "Validation failed: config.name {{ accountName }} cannot contain spaces."
|
|
253
262
|
},
|
|
254
263
|
"updateAccount": {
|
|
255
264
|
"noConfigToUpdate": "No config to update.",
|
|
@@ -311,6 +320,26 @@
|
|
|
311
320
|
"configUtils": {
|
|
312
321
|
"unknownType": "Unknown auth type {{ type }}"
|
|
313
322
|
},
|
|
323
|
+
"state": {
|
|
324
|
+
"ensureCLIDirectory": {
|
|
325
|
+
"errors": {
|
|
326
|
+
"cannotCreateDirectory": "Cannot create CLI state directory: {{ error }}"
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
"getCurrentState": {
|
|
330
|
+
"debug": {
|
|
331
|
+
"emptyStateFile": "State file is empty, using default state"
|
|
332
|
+
},
|
|
333
|
+
"errors": {
|
|
334
|
+
"errorReading": "Error reading CLI state, using defaults: {{ error }}"
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
"setStateValue": {
|
|
338
|
+
"errors": {
|
|
339
|
+
"failedToWrite": "Failed to write CLI state: {{ error }}"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
314
343
|
"environment": {
|
|
315
344
|
"loadConfig": {
|
|
316
345
|
"missingAccountId": "Unable to load config from environment variables: Missing accountId",
|
package/lib/cms/uploadFolder.js
CHANGED
|
@@ -38,6 +38,16 @@ function getFileType(filePath) {
|
|
|
38
38
|
return files_1.FILE_TYPES.other;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
+
function isMetaJsonFile(filePath) {
|
|
42
|
+
return path_1.default.basename(filePath).toLowerCase() === 'meta.json';
|
|
43
|
+
}
|
|
44
|
+
function resolveUploadPath(file, fieldsJsPaths, tmpDirRegex, regex, dest) {
|
|
45
|
+
const fieldsJsFileInfo = fieldsJsPaths.find(f => f.outputPath === file);
|
|
46
|
+
const relativePath = file.replace(fieldsJsFileInfo ? tmpDirRegex : regex, '');
|
|
47
|
+
const destPath = (0, path_2.convertToUnixPath)(path_1.default.join(dest, relativePath));
|
|
48
|
+
const originalFilePath = fieldsJsFileInfo ? fieldsJsFileInfo.filePath : file;
|
|
49
|
+
return { fieldsJsFileInfo, relativePath, destPath, originalFilePath };
|
|
50
|
+
}
|
|
41
51
|
async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOptions) {
|
|
42
52
|
const { convertFields, fieldOptions } = commandOptions;
|
|
43
53
|
const projectDirRegex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(projectDir)}`);
|
|
@@ -106,6 +116,12 @@ const defaultUploadFinalErrorCallback = (accountId, file, destPath, error) => {
|
|
|
106
116
|
payload: file,
|
|
107
117
|
});
|
|
108
118
|
};
|
|
119
|
+
async function uploadMetaJsonFiles(moduleFiles, uploadFile) {
|
|
120
|
+
const moduleMetaJsonFiles = moduleFiles.filter(isMetaJsonFile);
|
|
121
|
+
if (moduleMetaJsonFiles.length > 0) {
|
|
122
|
+
await queue.addAll(moduleMetaJsonFiles.map(uploadFile));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
109
125
|
async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOptions = {}, filePaths = [], cmsPublishMode = null) {
|
|
110
126
|
const { saveOutput, convertFields, onAttemptCallback, onSuccessCallback, onFirstErrorCallback, onRetryCallback, onFinalErrorCallback, } = commandOptions;
|
|
111
127
|
const _onAttemptCallback = onAttemptCallback || defaultUploadAttemptCallback;
|
|
@@ -120,23 +136,15 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
120
136
|
const apiOptions = (0, fileMapper_1.getFileMapperQueryValues)(cmsPublishMode, fileMapperOptions);
|
|
121
137
|
const failures = [];
|
|
122
138
|
let fieldsJsPaths = [];
|
|
123
|
-
|
|
139
|
+
const tmpDirRegex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(tmpDir || '')}`);
|
|
124
140
|
const [filesByType, fieldsJsObjects] = await getFilesByType(filePaths, src, tmpDir, commandOptions);
|
|
125
|
-
const fileList = Object.values(filesByType);
|
|
126
141
|
if (fieldsJsObjects.length) {
|
|
127
142
|
fieldsJsPaths = fieldsJsObjects.map(fieldsJs => {
|
|
128
143
|
return { outputPath: fieldsJs.outputPath, filePath: fieldsJs.filePath };
|
|
129
144
|
});
|
|
130
|
-
tmpDirRegex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(tmpDir || '')}`);
|
|
131
145
|
}
|
|
132
146
|
function uploadFile(file) {
|
|
133
|
-
const
|
|
134
|
-
const originalFilePath = fieldsJsFileInfo
|
|
135
|
-
? fieldsJsFileInfo.filePath
|
|
136
|
-
: file;
|
|
137
|
-
// files in fieldsJsPaths always belong to the tmp directory.
|
|
138
|
-
const relativePath = file.replace(fieldsJsFileInfo ? tmpDirRegex : regex, '');
|
|
139
|
-
const destPath = (0, path_2.convertToUnixPath)(path_1.default.join(dest, relativePath));
|
|
147
|
+
const { originalFilePath, destPath } = resolveUploadPath(file, fieldsJsPaths, tmpDirRegex, regex, dest);
|
|
140
148
|
return async () => {
|
|
141
149
|
_onAttemptCallback(originalFilePath, destPath);
|
|
142
150
|
try {
|
|
@@ -155,9 +163,23 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
155
163
|
}
|
|
156
164
|
};
|
|
157
165
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
166
|
+
// Upload all meta.json files first
|
|
167
|
+
await uploadMetaJsonFiles(filesByType[files_1.FILE_TYPES.module] || [], uploadFile);
|
|
168
|
+
// Collect all remaining files for upload
|
|
169
|
+
const deferredFiles = [];
|
|
170
|
+
Object.entries(filesByType).forEach(([fileType, files]) => {
|
|
171
|
+
if (fileType === files_1.FILE_TYPES.module) {
|
|
172
|
+
// Add non-meta.json module files
|
|
173
|
+
deferredFiles.push(...files.filter(f => !isMetaJsonFile(f)));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Add all non-module files
|
|
177
|
+
deferredFiles.push(...files);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// Upload all remaining files concurrently
|
|
181
|
+
if (deferredFiles.length > 0) {
|
|
182
|
+
await queue.addAll(deferredFiles.map(uploadFile));
|
|
161
183
|
}
|
|
162
184
|
const results = await queue
|
|
163
185
|
.addAll(failures.map(({ file, destPath }) => {
|
package/lib/crm.d.ts
ADDED
package/lib/crm.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateImportRequestFile = exports.getImportDataRequest = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const path_2 = require("./path");
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const lang_1 = require("../utils/lang");
|
|
11
|
+
function getImportDataRequest(fileName) {
|
|
12
|
+
validateImportRequestFile(fileName);
|
|
13
|
+
const importRequest = fs_extra_1.default.readJsonSync(path_1.default.resolve((0, path_2.getCwd)(), fileName));
|
|
14
|
+
const dataFileNames = importRequest.files.map(file => file.fileName);
|
|
15
|
+
// allow relative paths in the provided import request
|
|
16
|
+
importRequest.files = importRequest.files.map(file => ({
|
|
17
|
+
...file,
|
|
18
|
+
fileName: path_1.default.basename(file.fileName),
|
|
19
|
+
}));
|
|
20
|
+
if (dataFileNames.length === 0) {
|
|
21
|
+
throw new Error((0, lang_1.i18n)('lib.crm.importData.errors.noFiles'));
|
|
22
|
+
}
|
|
23
|
+
dataFileNames.forEach(fileName => {
|
|
24
|
+
if (!fileExists(fileName)) {
|
|
25
|
+
throw new Error((0, lang_1.i18n)('lib.crm.importData.errors.fileNotFound', { fileName }));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return { importRequest, dataFileNames };
|
|
29
|
+
}
|
|
30
|
+
exports.getImportDataRequest = getImportDataRequest;
|
|
31
|
+
function validateImportRequestFile(fileName) {
|
|
32
|
+
if (!fileExists(fileName)) {
|
|
33
|
+
throw new Error((0, lang_1.i18n)('lib.crm.importData.errors.fileNotFound', { fileName }));
|
|
34
|
+
}
|
|
35
|
+
if (path_1.default.extname(fileName) !== '.json') {
|
|
36
|
+
throw new Error((0, lang_1.i18n)('lib.crm.importData.errors.notJson'));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.validateImportRequestFile = validateImportRequestFile;
|
|
40
|
+
function fileExists(_path) {
|
|
41
|
+
try {
|
|
42
|
+
const absoluteSrcPath = path_1.default.resolve((0, path_2.getCwd)(), _path);
|
|
43
|
+
if (!absoluteSrcPath)
|
|
44
|
+
return false;
|
|
45
|
+
const stats = fs_extra_1.default.statSync(absoluteSrcPath);
|
|
46
|
+
const isFile = stats.isFile();
|
|
47
|
+
if (!isFile) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
package/lib/gitignore.js
CHANGED
|
@@ -18,7 +18,7 @@ function checkAndAddConfigToGitignore(configPath) {
|
|
|
18
18
|
return;
|
|
19
19
|
let gitignoreFilePath = gitignoreFiles && gitignoreFiles.length ? gitignoreFiles[0] : null;
|
|
20
20
|
if (!gitignoreFilePath) {
|
|
21
|
-
gitignoreFilePath = path_1.default.
|
|
21
|
+
gitignoreFilePath = path_1.default.join(path_1.default.dirname(configPath), GITIGNORE_FILE);
|
|
22
22
|
(0, fs_extra_1.writeFileSync)(gitignoreFilePath, '');
|
|
23
23
|
}
|
|
24
24
|
const gitignoreContents = (0, fs_extra_1.readFileSync)(gitignoreFilePath).toString();
|
package/lib/hubdb.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare function createHubDbTable(accountId: number, src: string): Promis
|
|
|
8
8
|
tableId: string;
|
|
9
9
|
rowCount: number;
|
|
10
10
|
}>;
|
|
11
|
-
export declare function updateHubDbTable(accountId: number, tableId: string, src: string): Promise<AxiosResponse<Table, any>>;
|
|
11
|
+
export declare function updateHubDbTable(accountId: number, tableId: string, src: string): Promise<AxiosResponse<Table, any, {}>>;
|
|
12
12
|
export declare function downloadHubDbTable(accountId: number, tableId: string, dest: string): Promise<{
|
|
13
13
|
filePath: string;
|
|
14
14
|
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isDeepEqual(object1: unknown, object2: unknown, ignoreKeys?: string[]): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDeepEqual = void 0;
|
|
4
|
+
function isDeepEqual(object1, object2, ignoreKeys) {
|
|
5
|
+
if (object1 === object2) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
if (object1 === null ||
|
|
9
|
+
object2 === null ||
|
|
10
|
+
typeof object1 !== 'object' ||
|
|
11
|
+
typeof object2 !== 'object') {
|
|
12
|
+
return object1 === object2;
|
|
13
|
+
}
|
|
14
|
+
if (typeof object1 !== typeof object2) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const isArray1 = Array.isArray(object1);
|
|
18
|
+
const isArray2 = Array.isArray(object2);
|
|
19
|
+
if (isArray1 !== isArray2) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const objKeys1 = Object.keys(object1).filter(key => !ignoreKeys?.includes(key));
|
|
23
|
+
const objKeys2 = Object.keys(object2).filter(key => !ignoreKeys?.includes(key));
|
|
24
|
+
if (objKeys1.length !== objKeys2.length)
|
|
25
|
+
return false;
|
|
26
|
+
for (const key of objKeys1) {
|
|
27
|
+
const value1 = object1[key];
|
|
28
|
+
const value2 = object2[key];
|
|
29
|
+
if (!isDeepEqual(value1, value2, ignoreKeys)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
exports.isDeepEqual = isDeepEqual;
|
package/lib/portManager.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export declare function stopPortManagerServer(): Promise<void>;
|
|
|
7
7
|
export declare function requestPorts(portData: Array<RequestPortsData>): Promise<{
|
|
8
8
|
[instanceId: string]: number;
|
|
9
9
|
}>;
|
|
10
|
+
export declare function getServerPortByInstanceId(serverInstanceId: string): Promise<number>;
|
|
10
11
|
export declare function deleteServerInstance(serverInstanceId: string): Promise<void>;
|
|
11
12
|
export declare function portManagerHasActiveServers(): Promise<boolean>;
|
package/lib/portManager.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.portManagerHasActiveServers = exports.deleteServerInstance = exports.requestPorts = exports.stopPortManagerServer = exports.startPortManagerServer = exports.isPortManagerServerRunning = exports.isPortManagerPortAvailable = exports.BASE_URL = void 0;
|
|
6
|
+
exports.portManagerHasActiveServers = exports.deleteServerInstance = exports.getServerPortByInstanceId = exports.requestPorts = exports.stopPortManagerServer = exports.startPortManagerServer = exports.isPortManagerServerRunning = exports.isPortManagerPortAvailable = exports.BASE_URL = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const PortManagerServer_1 = require("../utils/PortManagerServer");
|
|
9
9
|
const ports_1 = require("../constants/ports");
|
|
@@ -46,6 +46,11 @@ async function requestPorts(portData) {
|
|
|
46
46
|
return data.ports;
|
|
47
47
|
}
|
|
48
48
|
exports.requestPorts = requestPorts;
|
|
49
|
+
async function getServerPortByInstanceId(serverInstanceId) {
|
|
50
|
+
const { data } = await axios_1.default.get(`${exports.BASE_URL}/servers/${serverInstanceId}`);
|
|
51
|
+
return data.port;
|
|
52
|
+
}
|
|
53
|
+
exports.getServerPortByInstanceId = getServerPortByInstanceId;
|
|
49
54
|
async function deleteServerInstance(serverInstanceId) {
|
|
50
55
|
await axios_1.default.delete(`${exports.BASE_URL}/servers/${serverInstanceId}`);
|
|
51
56
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/local-dev-lib",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3-experimental.0",
|
|
4
4
|
"description": "Provides library functionality for HubSpot local development tooling, including the HubSpot CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"devDependencies": {
|
|
23
|
+
"@hubspot/npm-scripts": "0.0.4",
|
|
23
24
|
"@inquirer/prompts": "^7.0.1",
|
|
24
25
|
"@types/content-disposition": "^0.5.5",
|
|
25
26
|
"@types/cors": "^2.8.15",
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
"./http/*": "./http/*.js",
|
|
52
53
|
"./config/getAccountIdentifier": "./config/getAccountIdentifier.js",
|
|
53
54
|
"./config/migrate": "./config/migrate.js",
|
|
55
|
+
"./config/state": "./config/state.js",
|
|
54
56
|
"./config": "./config/index.js",
|
|
55
57
|
"./constants/*": "./constants/*.js",
|
|
56
58
|
"./models/*": "./models/*.js",
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
},
|
|
62
64
|
"dependencies": {
|
|
63
65
|
"address": "2.0.2",
|
|
64
|
-
"axios": "1.
|
|
66
|
+
"axios": "1.12.0",
|
|
65
67
|
"chalk": "2.4.2",
|
|
66
68
|
"chokidar": "3.6.0",
|
|
67
69
|
"content-disposition": "0.5.4",
|
|
@@ -70,6 +72,7 @@
|
|
|
70
72
|
"express": "4.21.2",
|
|
71
73
|
"extract-zip": "2.0.1",
|
|
72
74
|
"findup-sync": "5.0.0",
|
|
75
|
+
"form-data": "^4.0.4",
|
|
73
76
|
"fs-extra": "11.2.0",
|
|
74
77
|
"ignore": "5.3.1",
|
|
75
78
|
"js-yaml": "4.1.0",
|
package/types/Build.d.ts
CHANGED
package/types/Config.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { CLIAccount_NEW, CLIAccount_DEPRECATED } from './Accounts';
|
|
|
3
3
|
import { CmsPublishMode } from './Files';
|
|
4
4
|
import { ValueOf } from './Utils';
|
|
5
5
|
export interface CLIConfig_NEW {
|
|
6
|
-
accounts
|
|
6
|
+
accounts?: Array<CLIAccount_NEW>;
|
|
7
7
|
allowUsageTracking?: boolean;
|
|
8
8
|
allowAutoUpdates?: boolean;
|
|
9
9
|
defaultAccount?: string | number;
|
|
@@ -44,3 +44,6 @@ export type GitInclusionResult = {
|
|
|
44
44
|
configIgnored: boolean;
|
|
45
45
|
gitignoreFiles: Array<string>;
|
|
46
46
|
};
|
|
47
|
+
export type HubSpotState = {
|
|
48
|
+
mcpTotalToolCalls: number;
|
|
49
|
+
};
|
package/types/Crm.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ImportRequest {
|
|
2
|
+
name: string;
|
|
3
|
+
importOperations: {
|
|
4
|
+
[objectTypeId: string]: 'CREATE' | 'UPDATE' | 'UPSERT';
|
|
5
|
+
};
|
|
6
|
+
dateFormat?: string;
|
|
7
|
+
marketableContactImport?: boolean;
|
|
8
|
+
createContactListFromImport?: boolean;
|
|
9
|
+
files: Array<{
|
|
10
|
+
fileName: string;
|
|
11
|
+
fileFormat: 'CSV' | 'XLSX' | 'XLS';
|
|
12
|
+
fileImportPage: {
|
|
13
|
+
hasHeader: boolean;
|
|
14
|
+
columnMappings: Array<{
|
|
15
|
+
columnObjectTypeId: string;
|
|
16
|
+
columnName: string;
|
|
17
|
+
propertyName: string;
|
|
18
|
+
columnType?: string;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface ImportResponse {
|
|
24
|
+
id: string;
|
|
25
|
+
state: 'STARTED' | 'PROCESSING' | 'DONE' | 'FAILED' | 'CANCELED' | 'DEFERRED';
|
|
26
|
+
}
|
package/types/Crm.js
ADDED
package/types/Deploy.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export type ProjectDeployResponseQueued = {
|
|
|
42
42
|
status: string;
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
|
-
type SubdeployValidationIssue = {
|
|
45
|
+
export type SubdeployValidationIssue = {
|
|
46
46
|
uid: string;
|
|
47
47
|
componentTypeName: string;
|
|
48
48
|
errorMessages: string[];
|
|
@@ -56,4 +56,3 @@ export type ProjectDeployResponseBlocked = {
|
|
|
56
56
|
issues: SubdeployValidationIssue[];
|
|
57
57
|
};
|
|
58
58
|
export type ProjectDeployResponse = ProjectDeployResponseQueued | ProjectDeployResponseBlocked;
|
|
59
|
-
export {};
|
package/utils/accounts.js
CHANGED
|
@@ -5,10 +5,10 @@ function getAccounts(config) {
|
|
|
5
5
|
if (!config) {
|
|
6
6
|
return [];
|
|
7
7
|
}
|
|
8
|
-
else if (
|
|
8
|
+
else if ('portals' in config && Array.isArray(config.portals)) {
|
|
9
9
|
return config.portals;
|
|
10
10
|
}
|
|
11
|
-
else if (
|
|
11
|
+
else if ('accounts' in config && Array.isArray(config.accounts)) {
|
|
12
12
|
return config.accounts;
|
|
13
13
|
}
|
|
14
14
|
return [];
|