@hubspot/local-dev-lib 0.6.1-experimental.0 → 0.6.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 +2 -2
- package/api/appsDev.js +13 -22
- package/api/crm.d.ts +2 -2
- package/api/crm.js +9 -16
- package/api/customObjects.d.ts +2 -2
- package/api/customObjects.js +13 -22
- package/api/designManager.d.ts +2 -2
- package/api/designManager.js +5 -10
- package/api/devSecrets.d.ts +2 -2
- package/api/devSecrets.js +9 -16
- package/api/developerTestAccounts.d.ts +2 -4
- package/api/developerTestAccounts.js +23 -55
- package/api/fileManager.d.ts +2 -2
- package/api/fileManager.js +14 -24
- package/api/fileMapper.d.ts +2 -3
- package/api/fileMapper.js +34 -49
- package/api/fileTransport.d.ts +1 -1
- package/api/fileTransport.js +12 -21
- package/api/fireAlarm.d.ts +2 -3
- package/api/fireAlarm.js +5 -9
- package/api/functions.d.ts +2 -2
- package/api/functions.js +11 -19
- package/api/github.d.ts +2 -4
- package/api/github.js +16 -27
- package/api/hubdb.d.ts +2 -2
- package/api/hubdb.js +19 -31
- package/api/lighthouseScore.d.ts +2 -2
- package/api/lighthouseScore.js +7 -13
- package/api/localDevAuth.d.ts +3 -6
- package/api/localDevAuth.js +10 -40
- package/api/marketplaceValidation.d.ts +2 -2
- package/api/marketplaceValidation.js +7 -13
- package/api/projects.d.ts +6 -8
- package/api/projects.js +65 -100
- package/api/sandboxHubs.d.ts +2 -5
- package/api/sandboxHubs.js +15 -45
- package/api/sandboxSync.d.ts +2 -2
- package/api/sandboxSync.js +7 -12
- package/api/secrets.d.ts +2 -2
- package/api/secrets.js +9 -16
- package/api/validateHubl.d.ts +2 -2
- package/api/validateHubl.js +3 -7
- package/config/defaultAccountOverride.d.ts +2 -1
- package/config/defaultAccountOverride.js +16 -26
- package/config/index.d.ts +4 -4
- package/config/index.js +144 -177
- package/config/migrate.d.ts +2 -2
- package/config/migrate.js +26 -37
- package/config/state.d.ts +1 -1
- package/config/state.js +17 -45
- package/config/utils.d.ts +4 -4
- package/config/utils.js +85 -108
- package/constants/api.js +3 -6
- package/constants/auth.js +9 -12
- package/constants/config.d.ts +30 -1
- package/constants/config.js +65 -42
- package/constants/endpoints.d.ts +6 -0
- package/constants/endpoints.js +6 -0
- package/constants/environments.js +1 -4
- package/constants/extensions.js +6 -9
- package/constants/files.js +5 -8
- package/constants/ports.js +3 -6
- package/constants/projects.js +2 -5
- package/enums/build.d.ts +1 -0
- package/enums/build.js +6 -8
- package/enums/deploy.js +2 -5
- package/enums/project.js +1 -4
- package/errors/index.d.ts +4 -5
- package/errors/index.js +17 -39
- package/errors/isSystemError.d.ts +2 -0
- package/errors/isSystemError.js +9 -0
- package/http/addQueryParams.d.ts +1 -1
- package/http/addQueryParams.js +1 -5
- package/http/client.d.ts +1 -0
- package/http/client.js +54 -0
- package/http/getAxiosConfig.d.ts +1 -1
- package/http/getAxiosConfig.js +21 -31
- package/http/index.d.ts +2 -2
- package/http/index.js +39 -124
- package/http/unauthed.d.ts +1 -1
- package/http/unauthed.js +15 -21
- package/lang/en.json +3 -2
- package/lib/archive.d.ts +1 -3
- package/lib/archive.js +37 -67
- package/lib/cms/functions.d.ts +1 -1
- package/lib/cms/functions.js +45 -55
- package/lib/cms/handleFieldsJS.js +36 -44
- package/lib/cms/modules.d.ts +2 -2
- package/lib/cms/modules.js +49 -59
- package/lib/cms/processFieldsJs.js +17 -32
- package/lib/cms/templates.js +17 -26
- package/lib/cms/themes.js +10 -18
- package/lib/cms/uploadFolder.d.ts +4 -4
- package/lib/cms/uploadFolder.js +55 -64
- package/lib/cms/validate.d.ts +1 -1
- package/lib/cms/validate.js +11 -18
- package/lib/cms/watch.d.ts +2 -2
- package/lib/cms/watch.js +66 -73
- package/lib/crm.d.ts +1 -1
- package/lib/crm.js +15 -23
- package/lib/customObjects.d.ts +1 -1
- package/lib/customObjects.js +15 -25
- package/lib/environment.d.ts +1 -1
- package/lib/environment.js +5 -11
- package/lib/escapeRegExp.js +1 -5
- package/lib/fileManager.js +43 -51
- package/lib/fileMapper.d.ts +1 -1
- package/lib/fileMapper.js +68 -84
- package/lib/fs.d.ts +1 -1
- package/lib/fs.js +18 -27
- package/lib/github.d.ts +1 -3
- package/lib/github.js +39 -51
- package/lib/gitignore.d.ts +1 -1
- package/lib/gitignore.js +16 -24
- package/lib/hubdb.d.ts +1 -1
- package/lib/hubdb.js +29 -40
- package/lib/ignoreRules.js +25 -34
- package/lib/isDeepEqual.js +1 -5
- package/lib/logger.d.ts +8 -20
- package/lib/logger.js +47 -59
- package/lib/notify.js +9 -16
- package/lib/oauth.d.ts +2 -2
- package/lib/oauth.js +12 -17
- package/lib/path.d.ts +0 -1
- package/lib/path.js +30 -48
- package/lib/personalAccessKey.d.ts +2 -4
- package/lib/personalAccessKey.js +43 -60
- package/lib/portManager.d.ts +2 -2
- package/lib/portManager.js +26 -41
- package/lib/text.js +2 -7
- package/lib/trackUsage.d.ts +0 -2
- package/lib/trackUsage.js +27 -31
- package/lib/urls.js +4 -9
- package/models/FileSystemError.d.ts +1 -1
- package/models/FileSystemError.js +12 -16
- package/models/HubSpotConfigError.d.ts +1 -1
- package/models/HubSpotConfigError.js +8 -12
- package/models/HubSpotHttpError.d.ts +1 -1
- package/models/HubSpotHttpError.js +22 -26
- package/models/OAuth2Manager.d.ts +1 -1
- package/models/OAuth2Manager.js +17 -24
- package/package.json +21 -17
- package/types/Accounts.d.ts +6 -5
- package/types/Accounts.js +1 -2
- package/types/Activity.d.ts +3 -3
- package/types/Activity.js +1 -2
- package/types/Api.d.ts +1 -1
- package/types/Api.js +1 -2
- package/types/Apps.js +1 -2
- package/types/Archive.js +1 -2
- package/types/Build.d.ts +4 -5
- package/types/Build.js +1 -2
- package/types/CLIOptions.js +1 -2
- package/types/ComponentStructure.d.ts +2 -2
- package/types/ComponentStructure.js +1 -2
- package/types/Config.d.ts +4 -6
- package/types/Config.js +1 -2
- package/types/Crm.js +1 -2
- package/types/Deploy.d.ts +5 -11
- package/types/Deploy.js +1 -2
- package/types/DesignManager.js +1 -2
- package/types/DevSecrets.js +1 -2
- package/types/Error.js +1 -2
- package/types/FieldsJS.js +1 -2
- package/types/FileManager.js +1 -2
- package/types/Files.d.ts +4 -4
- package/types/Files.js +1 -2
- package/types/FireAlarm.js +1 -2
- package/types/Functions.js +1 -2
- package/types/Github.d.ts +1 -1
- package/types/Github.js +1 -2
- package/types/Http.d.ts +0 -4
- package/types/Http.js +1 -2
- package/types/Hubdb.js +1 -2
- package/types/HublValidation.js +1 -2
- package/types/Lang.d.ts +1 -1
- package/types/Lang.js +1 -2
- package/types/Lighthouse.js +1 -2
- package/types/MarketplaceValidation.js +1 -2
- package/types/Migration.d.ts +2 -2
- package/types/Migration.js +1 -4
- package/types/Modules.js +1 -2
- package/types/PortManager.js +1 -2
- package/types/Project.d.ts +3 -21
- package/types/Project.js +1 -2
- package/types/ProjectComponents.d.ts +24 -0
- package/types/ProjectComponents.js +1 -0
- package/types/ProjectLog.js +1 -2
- package/types/Sandbox.js +2 -5
- package/types/Schemas.js +1 -2
- package/types/Secrets.js +1 -2
- package/types/Utils.js +1 -2
- package/types/developerTestAccounts.js +1 -2
- package/utils/PortManagerServer.d.ts +1 -2
- package/utils/PortManagerServer.js +32 -38
- package/utils/cms/fieldsJS.d.ts +1 -1
- package/utils/cms/fieldsJS.js +1 -5
- package/utils/cms/modules.d.ts +1 -1
- package/utils/cms/modules.js +13 -22
- package/utils/detectPort.js +12 -19
- package/utils/git.js +17 -26
- package/utils/lang.d.ts +1 -1
- package/utils/lang.js +5 -14
- package/utils/personalAccessKey.d.ts +8 -0
- package/utils/personalAccessKey.js +51 -0
- package/errors/errors_DEPRECATED.d.ts +0 -3
- package/errors/errors_DEPRECATED.js +0 -60
package/lib/cms/uploadFolder.js
CHANGED
|
@@ -1,59 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const path_2 = require("../path");
|
|
15
|
-
const errors_1 = require("../../errors");
|
|
16
|
-
const logger_1 = require("../logger");
|
|
17
|
-
const files_1 = require("../../constants/files");
|
|
18
|
-
const lang_1 = require("../../utils/lang");
|
|
19
|
-
const HubSpotHttpError_1 = require("../../models/HubSpotHttpError");
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import PQueue from 'p-queue';
|
|
3
|
+
import { isConvertableFieldJs, FieldsJs, createTmpDirSync, cleanupTmpDirSync, } from './handleFieldsJS.js';
|
|
4
|
+
import { getFileMapperQueryValues } from '../fileMapper.js';
|
|
5
|
+
import { upload } from '../../api/fileMapper.js';
|
|
6
|
+
import { isModuleFolderChild } from '../../utils/cms/modules.js';
|
|
7
|
+
import { escapeRegExp } from '../escapeRegExp.js';
|
|
8
|
+
import { convertToUnixPath, getExt } from '../path.js';
|
|
9
|
+
import { isAuthError, isHubSpotHttpError } from '../../errors/index.js';
|
|
10
|
+
import { logger } from '../logger.js';
|
|
11
|
+
import { FILE_TYPES, FILE_UPLOAD_RESULT_TYPES } from '../../constants/files.js';
|
|
12
|
+
import { i18n } from '../../utils/lang.js';
|
|
13
|
+
import { HubSpotHttpError } from '../../models/HubSpotHttpError.js';
|
|
20
14
|
const i18nKey = 'lib.cms.uploadFolder';
|
|
21
|
-
const queue = new
|
|
15
|
+
const queue = new PQueue({
|
|
22
16
|
concurrency: 10,
|
|
23
17
|
});
|
|
24
18
|
function getFileType(filePath) {
|
|
25
|
-
const extension =
|
|
26
|
-
const moduleFolder =
|
|
19
|
+
const extension = getExt(filePath);
|
|
20
|
+
const moduleFolder = isModuleFolderChild({ path: filePath, isLocal: true });
|
|
27
21
|
if (moduleFolder)
|
|
28
|
-
return
|
|
22
|
+
return FILE_TYPES.module;
|
|
29
23
|
switch (extension) {
|
|
30
24
|
case 'js':
|
|
31
25
|
case 'css':
|
|
32
|
-
return
|
|
26
|
+
return FILE_TYPES.cssAndJs;
|
|
33
27
|
case 'html':
|
|
34
|
-
return
|
|
28
|
+
return FILE_TYPES.template;
|
|
35
29
|
case 'json':
|
|
36
|
-
return
|
|
30
|
+
return FILE_TYPES.json;
|
|
37
31
|
default:
|
|
38
|
-
return
|
|
32
|
+
return FILE_TYPES.other;
|
|
39
33
|
}
|
|
40
34
|
}
|
|
41
35
|
function isMetaJsonFile(filePath) {
|
|
42
|
-
return
|
|
36
|
+
return path.basename(filePath).toLowerCase() === 'meta.json';
|
|
43
37
|
}
|
|
44
38
|
function resolveUploadPath(file, fieldsJsPaths, tmpDirRegex, regex, dest) {
|
|
45
39
|
const fieldsJsFileInfo = fieldsJsPaths.find(f => f.outputPath === file);
|
|
46
40
|
const relativePath = file.replace(fieldsJsFileInfo ? tmpDirRegex : regex, '');
|
|
47
|
-
const destPath =
|
|
41
|
+
const destPath = convertToUnixPath(path.join(dest, relativePath));
|
|
48
42
|
const originalFilePath = fieldsJsFileInfo ? fieldsJsFileInfo.filePath : file;
|
|
49
43
|
return { fieldsJsFileInfo, relativePath, destPath, originalFilePath };
|
|
50
44
|
}
|
|
51
|
-
async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOptions) {
|
|
45
|
+
export async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOptions) {
|
|
52
46
|
const { convertFields, fieldOptions } = commandOptions;
|
|
53
|
-
const projectDirRegex = new RegExp(`^${
|
|
47
|
+
const projectDirRegex = new RegExp(`^${escapeRegExp(projectDir)}`);
|
|
54
48
|
const fieldsJsObjects = [];
|
|
55
49
|
// Create object with key-value pairs of form { FileType.type: [] }
|
|
56
|
-
const filePathsByType = Object.values(
|
|
50
|
+
const filePathsByType = Object.values(FILE_TYPES).reduce((acc, fileType) => {
|
|
57
51
|
return {
|
|
58
52
|
...acc,
|
|
59
53
|
[fileType]: [],
|
|
@@ -66,10 +60,10 @@ async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOption
|
|
|
66
60
|
filePathsByType[fileType].push(filePath);
|
|
67
61
|
continue;
|
|
68
62
|
}
|
|
69
|
-
const convertableFields =
|
|
63
|
+
const convertableFields = isConvertableFieldJs(projectDir, filePath, convertFields);
|
|
70
64
|
if (convertableFields) {
|
|
71
|
-
const rootOrModule =
|
|
72
|
-
const fieldsJs = await new
|
|
65
|
+
const rootOrModule = path.dirname(relPath) === '/' ? FILE_TYPES.json : FILE_TYPES.module;
|
|
66
|
+
const fieldsJs = await new FieldsJs(projectDir, filePath, rootWriteDir, fieldOptions).init();
|
|
73
67
|
/*
|
|
74
68
|
* A fields.js will be rejected if the promise is rejected or if the some other error occurs.
|
|
75
69
|
* We handle this gracefully by not adding the failed fields.js to the object list.
|
|
@@ -85,32 +79,31 @@ async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOption
|
|
|
85
79
|
}
|
|
86
80
|
return [filePathsByType, fieldsJsObjects];
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
const defaultUploadAttemptCallback = (file, destPath) => logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.attempt`, {
|
|
82
|
+
const defaultUploadAttemptCallback = (file, destPath) => logger.debug(i18n(`${i18nKey}.uploadFolder.attempt`, {
|
|
90
83
|
file: file || '',
|
|
91
84
|
destPath,
|
|
92
85
|
}));
|
|
93
|
-
const defaultUploadSuccessCallback = (file, destPath) =>
|
|
86
|
+
const defaultUploadSuccessCallback = (file, destPath) => logger.log(i18n(`${i18nKey}.uploadFolder.success`, {
|
|
94
87
|
file: file || '',
|
|
95
88
|
destPath,
|
|
96
89
|
}));
|
|
97
90
|
const defaultUploadFirstErrorCallback = (file, destPath, error) => {
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
91
|
+
logger.debug(i18n(`${i18nKey}.uploadFolder.failed`, { file, destPath }));
|
|
92
|
+
if (isHubSpotHttpError(error)) {
|
|
93
|
+
logger.debug(error.data);
|
|
101
94
|
}
|
|
102
95
|
else if (error instanceof Error) {
|
|
103
|
-
|
|
96
|
+
logger.debug(error.message);
|
|
104
97
|
}
|
|
105
98
|
};
|
|
106
|
-
const defaultUploadRetryCallback = (file, destPath) =>
|
|
99
|
+
const defaultUploadRetryCallback = (file, destPath) => logger.debug(i18n(`${i18nKey}.uploadFolder.retry`, { file, destPath }));
|
|
107
100
|
const defaultUploadFinalErrorCallback = (accountId, file, destPath, error) => {
|
|
108
|
-
const retryFailed =
|
|
101
|
+
const retryFailed = i18n(`${i18nKey}.uploadFolder.retryFailed`, {
|
|
109
102
|
file,
|
|
110
103
|
destPath,
|
|
111
104
|
});
|
|
112
|
-
|
|
113
|
-
throw new
|
|
105
|
+
logger.debug(retryFailed);
|
|
106
|
+
throw new HubSpotHttpError(retryFailed, { cause: error }, {
|
|
114
107
|
accountId,
|
|
115
108
|
request: destPath,
|
|
116
109
|
payload: file,
|
|
@@ -122,7 +115,7 @@ async function uploadMetaJsonFiles(moduleFiles, uploadFile) {
|
|
|
122
115
|
await queue.addAll(moduleMetaJsonFiles.map(uploadFile));
|
|
123
116
|
}
|
|
124
117
|
}
|
|
125
|
-
async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOptions = {}, filePaths = [], cmsPublishMode = null) {
|
|
118
|
+
export async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOptions = {}, filePaths = [], cmsPublishMode = null) {
|
|
126
119
|
const { saveOutput, convertFields, onAttemptCallback, onSuccessCallback, onFirstErrorCallback, onRetryCallback, onFinalErrorCallback, } = commandOptions;
|
|
127
120
|
const _onAttemptCallback = onAttemptCallback || defaultUploadAttemptCallback;
|
|
128
121
|
const _onSuccessCallback = onSuccessCallback || defaultUploadSuccessCallback;
|
|
@@ -130,13 +123,13 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
130
123
|
const _onRetryCallback = onRetryCallback || defaultUploadRetryCallback;
|
|
131
124
|
const _onFinalErrorCallback = onFinalErrorCallback || defaultUploadFinalErrorCallback;
|
|
132
125
|
const tmpDir = convertFields
|
|
133
|
-
?
|
|
126
|
+
? createTmpDirSync('hubspot-temp-fieldsjs-output-')
|
|
134
127
|
: null;
|
|
135
|
-
const regex = new RegExp(`^${
|
|
136
|
-
const apiOptions =
|
|
128
|
+
const regex = new RegExp(`^${escapeRegExp(src)}`);
|
|
129
|
+
const apiOptions = getFileMapperQueryValues(cmsPublishMode, fileMapperOptions);
|
|
137
130
|
const failures = [];
|
|
138
131
|
let fieldsJsPaths = [];
|
|
139
|
-
const tmpDirRegex = new RegExp(`^${
|
|
132
|
+
const tmpDirRegex = new RegExp(`^${escapeRegExp(tmpDir || '')}`);
|
|
140
133
|
const [filesByType, fieldsJsObjects] = await getFilesByType(filePaths, src, tmpDir, commandOptions);
|
|
141
134
|
if (fieldsJsObjects.length) {
|
|
142
135
|
fieldsJsPaths = fieldsJsObjects.map(fieldsJs => {
|
|
@@ -148,11 +141,11 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
148
141
|
return async () => {
|
|
149
142
|
_onAttemptCallback(originalFilePath, destPath);
|
|
150
143
|
try {
|
|
151
|
-
await
|
|
144
|
+
await upload(accountId, file, destPath, apiOptions);
|
|
152
145
|
_onSuccessCallback(originalFilePath, destPath);
|
|
153
146
|
}
|
|
154
147
|
catch (err) {
|
|
155
|
-
if (
|
|
148
|
+
if (isAuthError(err)) {
|
|
156
149
|
throw err;
|
|
157
150
|
}
|
|
158
151
|
_onFirstErrorCallback(file, destPath, err);
|
|
@@ -164,11 +157,11 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
164
157
|
};
|
|
165
158
|
}
|
|
166
159
|
// Upload all meta.json files first
|
|
167
|
-
await uploadMetaJsonFiles(filesByType[
|
|
160
|
+
await uploadMetaJsonFiles(filesByType[FILE_TYPES.module] || [], uploadFile);
|
|
168
161
|
// Collect all remaining files for upload
|
|
169
162
|
const deferredFiles = [];
|
|
170
163
|
Object.entries(filesByType).forEach(([fileType, files]) => {
|
|
171
|
-
if (fileType ===
|
|
164
|
+
if (fileType === FILE_TYPES.module) {
|
|
172
165
|
// Add non-meta.json module files
|
|
173
166
|
deferredFiles.push(...files.filter(f => !isMetaJsonFile(f)));
|
|
174
167
|
}
|
|
@@ -186,21 +179,21 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
186
179
|
return async () => {
|
|
187
180
|
_onRetryCallback(file, destPath);
|
|
188
181
|
try {
|
|
189
|
-
await
|
|
182
|
+
await upload(accountId, file, destPath, apiOptions);
|
|
190
183
|
_onSuccessCallback(file, destPath);
|
|
191
184
|
return {
|
|
192
|
-
resultType:
|
|
185
|
+
resultType: FILE_UPLOAD_RESULT_TYPES.SUCCESS,
|
|
193
186
|
error: null,
|
|
194
187
|
file,
|
|
195
188
|
};
|
|
196
189
|
}
|
|
197
190
|
catch (error) {
|
|
198
|
-
if (
|
|
191
|
+
if (isAuthError(error)) {
|
|
199
192
|
throw error;
|
|
200
193
|
}
|
|
201
194
|
_onFinalErrorCallback(accountId, file, destPath, error);
|
|
202
195
|
return {
|
|
203
|
-
resultType:
|
|
196
|
+
resultType: FILE_UPLOAD_RESULT_TYPES.FAILURE,
|
|
204
197
|
error,
|
|
205
198
|
file,
|
|
206
199
|
};
|
|
@@ -213,12 +206,10 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
|
|
|
213
206
|
if (saveOutput) {
|
|
214
207
|
fieldsJsObjects.forEach(fieldsJs => fieldsJs.saveOutput());
|
|
215
208
|
}
|
|
216
|
-
|
|
209
|
+
cleanupTmpDirSync(tmpDir || '');
|
|
217
210
|
});
|
|
218
211
|
return results;
|
|
219
212
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return results.some(result => result.resultType === files_1.FILE_UPLOAD_RESULT_TYPES.FAILURE);
|
|
213
|
+
export function hasUploadErrors(results) {
|
|
214
|
+
return results.some(result => result.resultType === FILE_UPLOAD_RESULT_TYPES.FAILURE);
|
|
223
215
|
}
|
|
224
|
-
exports.hasUploadErrors = hasUploadErrors;
|
package/lib/cms/validate.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { LintResult } from '../../types/HublValidation';
|
|
1
|
+
import { LintResult } from '../../types/HublValidation.js';
|
|
2
2
|
export declare function lint(accountId: number, filepath: string, callback?: (lintResult: LintResult) => number): Promise<Array<Partial<LintResult>> | void>;
|
package/lib/cms/validate.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const validateHubl_1 = require("../../api/validateHubl");
|
|
10
|
-
const fs_1 = require("../fs");
|
|
11
|
-
const path_1 = require("../path");
|
|
12
|
-
async function lint(accountId, filepath, callback) {
|
|
13
|
-
const stats = await fs_extra_1.default.stat(filepath);
|
|
14
|
-
const files = stats.isDirectory() ? await (0, fs_1.walk)(filepath) : [filepath];
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { HUBL_EXTENSIONS } from '../../constants/extensions.js';
|
|
3
|
+
import { validateHubl } from '../../api/validateHubl.js';
|
|
4
|
+
import { walk } from '../fs.js';
|
|
5
|
+
import { getExt } from '../path.js';
|
|
6
|
+
export async function lint(accountId, filepath, callback) {
|
|
7
|
+
const stats = await fs.stat(filepath);
|
|
8
|
+
const files = stats.isDirectory() ? await walk(filepath) : [filepath];
|
|
15
9
|
if (!(files && files.length)) {
|
|
16
10
|
return [];
|
|
17
11
|
}
|
|
18
12
|
return Promise.all(files
|
|
19
|
-
.filter(file =>
|
|
13
|
+
.filter(file => HUBL_EXTENSIONS.has(getExt(file)))
|
|
20
14
|
.map(async (file) => {
|
|
21
|
-
const source = await
|
|
15
|
+
const source = await fs.readFile(file, { encoding: 'utf8' });
|
|
22
16
|
if (!(source && source.trim())) {
|
|
23
17
|
const result = { file, validation: null };
|
|
24
18
|
if (callback) {
|
|
@@ -26,7 +20,7 @@ async function lint(accountId, filepath, callback) {
|
|
|
26
20
|
}
|
|
27
21
|
return result;
|
|
28
22
|
}
|
|
29
|
-
const { data: validation } = await
|
|
23
|
+
const { data: validation } = await validateHubl(accountId, source);
|
|
30
24
|
const result = {
|
|
31
25
|
file,
|
|
32
26
|
validation,
|
|
@@ -37,4 +31,3 @@ async function lint(accountId, filepath, callback) {
|
|
|
37
31
|
return result;
|
|
38
32
|
}));
|
|
39
33
|
}
|
|
40
|
-
exports.lint = lint;
|
package/lib/cms/watch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import chokidar from 'chokidar';
|
|
2
|
-
import { WatchOptions, WatchErrorHandler } from '../../types/Files';
|
|
3
|
-
import { UploadFolderResults } from '../../types/Files';
|
|
2
|
+
import { WatchOptions, WatchErrorHandler } from '../../types/Files.js';
|
|
3
|
+
import { UploadFolderResults } from '../../types/Files.js';
|
|
4
4
|
export declare function watch(accountId: number, src: string, dest: string, { cmsPublishMode, remove, disableInitial, notify, commandOptions, filePaths, }: WatchOptions, postInitialUploadCallback?: ((result: Array<UploadFolderResults>) => void) | null, onUploadFolderError?: WatchErrorHandler, onQueueAddError?: WatchErrorHandler, onUploadFileError?: (file: string, dest: string, accountId: number) => WatchErrorHandler): chokidar.FSWatcher;
|
package/lib/cms/watch.js
CHANGED
|
@@ -1,48 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const notify_1 = require("../notify");
|
|
19
|
-
const themes_1 = require("./themes");
|
|
20
|
-
const logger_1 = require("../logger");
|
|
21
|
-
const lang_1 = require("../../utils/lang");
|
|
22
|
-
const HubSpotHttpError_1 = require("../../models/HubSpotHttpError");
|
|
23
|
-
const errors_1 = require("../../errors");
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import chokidar from 'chokidar';
|
|
3
|
+
import PQueue from 'p-queue';
|
|
4
|
+
import debounce from 'debounce';
|
|
5
|
+
import { isConvertableFieldJs, FieldsJs } from './handleFieldsJS.js';
|
|
6
|
+
import { uploadFolder } from './uploadFolder.js';
|
|
7
|
+
import { shouldIgnoreFile, ignoreFile } from '../ignoreRules.js';
|
|
8
|
+
import { getFileMapperQueryValues } from '../fileMapper.js';
|
|
9
|
+
import { upload, deleteFile } from '../../api/fileMapper.js';
|
|
10
|
+
import { escapeRegExp } from '../escapeRegExp.js';
|
|
11
|
+
import { convertToUnixPath, isAllowedExtension, getCwd } from '../path.js';
|
|
12
|
+
import { triggerNotify } from '../notify.js';
|
|
13
|
+
import { getThemePreviewUrl, getThemeJSONPath } from './themes.js';
|
|
14
|
+
import { logger } from '../logger.js';
|
|
15
|
+
import { i18n } from '../../utils/lang.js';
|
|
16
|
+
import { HubSpotHttpError } from '../../models/HubSpotHttpError.js';
|
|
17
|
+
import { isHubSpotHttpError } from '../../errors/index.js';
|
|
24
18
|
const i18nKey = 'lib.cms.watch';
|
|
25
|
-
const queue = new
|
|
19
|
+
const queue = new PQueue({
|
|
26
20
|
concurrency: 10,
|
|
27
21
|
});
|
|
28
22
|
function _notifyOfThemePreview(filePath, accountId) {
|
|
29
23
|
if (queue.size > 0)
|
|
30
24
|
return;
|
|
31
|
-
const previewUrl =
|
|
25
|
+
const previewUrl = getThemePreviewUrl(filePath, accountId);
|
|
32
26
|
if (!previewUrl)
|
|
33
27
|
return;
|
|
34
|
-
|
|
28
|
+
logger.log(i18n(`${i18nKey}.notifyOfThemePreview`, {
|
|
35
29
|
previewUrl,
|
|
36
30
|
}));
|
|
37
31
|
}
|
|
38
|
-
const notifyOfThemePreview = (
|
|
32
|
+
const notifyOfThemePreview = debounce(_notifyOfThemePreview, 1000);
|
|
39
33
|
const defaultOnUploadFileError = (file, dest, accountId) => (error) => {
|
|
40
|
-
const uploadFailedMessage =
|
|
34
|
+
const uploadFailedMessage = i18n(`${i18nKey}.uploadFailed`, {
|
|
41
35
|
file,
|
|
42
36
|
dest,
|
|
43
37
|
});
|
|
44
|
-
|
|
45
|
-
throw new
|
|
38
|
+
logger.debug(uploadFailedMessage);
|
|
39
|
+
throw new HubSpotHttpError(uploadFailedMessage, {
|
|
46
40
|
cause: error,
|
|
47
41
|
}, {
|
|
48
42
|
accountId,
|
|
@@ -52,61 +46,61 @@ const defaultOnUploadFileError = (file, dest, accountId) => (error) => {
|
|
|
52
46
|
};
|
|
53
47
|
async function uploadFile(accountId, file, dest, options, cmsPublishMode = null, onUploadFileError = defaultOnUploadFileError) {
|
|
54
48
|
const src = options.src;
|
|
55
|
-
const absoluteSrcPath =
|
|
56
|
-
const themeJsonPath =
|
|
49
|
+
const absoluteSrcPath = path.resolve(getCwd(), file);
|
|
50
|
+
const themeJsonPath = getThemeJSONPath(absoluteSrcPath);
|
|
57
51
|
const projectRoot = themeJsonPath
|
|
58
|
-
?
|
|
59
|
-
:
|
|
60
|
-
const convertFields =
|
|
61
|
-
if (!
|
|
62
|
-
|
|
52
|
+
? path.dirname(themeJsonPath)
|
|
53
|
+
: path.dirname(getCwd());
|
|
54
|
+
const convertFields = isConvertableFieldJs(src, file, options.commandOptions.convertFields);
|
|
55
|
+
if (!isAllowedExtension(file) && !convertFields) {
|
|
56
|
+
logger.debug(i18n(`${i18nKey}.skipUnsupportedExtension`, { file }));
|
|
63
57
|
return;
|
|
64
58
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
59
|
+
if (shouldIgnoreFile(file)) {
|
|
60
|
+
logger.debug(i18n(`${i18nKey}.skipIgnoreRule`, { file }));
|
|
67
61
|
return;
|
|
68
62
|
}
|
|
69
63
|
let fieldsJs = undefined;
|
|
70
64
|
if (convertFields) {
|
|
71
|
-
fieldsJs = await new
|
|
65
|
+
fieldsJs = await new FieldsJs(projectRoot, absoluteSrcPath, undefined, options.fieldOptions).init();
|
|
72
66
|
if (fieldsJs.rejected)
|
|
73
67
|
return;
|
|
74
68
|
// Ensures that the dest path is a .json. The user might pass '.js' accidentally - this ensures it just works.
|
|
75
|
-
dest =
|
|
69
|
+
dest = convertToUnixPath(path.join(path.dirname(dest), 'fields.json'));
|
|
76
70
|
}
|
|
77
71
|
const fileToUpload = convertFields && fieldsJs?.outputPath ? fieldsJs.outputPath : file;
|
|
78
|
-
|
|
79
|
-
const apiOptions =
|
|
72
|
+
logger.debug(i18n(`${i18nKey}.uploadAttempt`, { file, dest }));
|
|
73
|
+
const apiOptions = getFileMapperQueryValues(cmsPublishMode, options);
|
|
80
74
|
queue.add(() => {
|
|
81
|
-
return
|
|
75
|
+
return upload(accountId, fileToUpload, dest, apiOptions)
|
|
82
76
|
.then(() => {
|
|
83
|
-
|
|
77
|
+
logger.log(i18n(`${i18nKey}.uploadSuccess`, { file, dest }));
|
|
84
78
|
notifyOfThemePreview(file, accountId);
|
|
85
79
|
})
|
|
86
80
|
.catch(() => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return
|
|
81
|
+
logger.debug(i18n(`${i18nKey}.uploadFailed`, { file, dest }));
|
|
82
|
+
logger.debug(i18n(`${i18nKey}.uploadRetry`, { file, dest }));
|
|
83
|
+
return upload(accountId, file, dest, apiOptions).catch(onUploadFileError(file, dest, accountId));
|
|
90
84
|
});
|
|
91
85
|
});
|
|
92
86
|
}
|
|
93
87
|
async function deleteRemoteFile(accountId, filePath, remoteFilePath) {
|
|
94
|
-
if (
|
|
95
|
-
|
|
88
|
+
if (shouldIgnoreFile(filePath)) {
|
|
89
|
+
logger.debug(i18n(`${i18nKey}.skipIgnoreRule`, { file: filePath }));
|
|
96
90
|
return;
|
|
97
91
|
}
|
|
98
|
-
|
|
92
|
+
logger.debug(i18n(`${i18nKey}.deleteAttempt`, { remoteFilePath }));
|
|
99
93
|
return queue.add(() => {
|
|
100
|
-
return
|
|
94
|
+
return deleteFile(accountId, remoteFilePath)
|
|
101
95
|
.then(() => {
|
|
102
|
-
|
|
96
|
+
logger.log(i18n(`${i18nKey}.deleteSuccess`, { remoteFilePath }));
|
|
103
97
|
notifyOfThemePreview(filePath, accountId);
|
|
104
98
|
})
|
|
105
99
|
.catch(error => {
|
|
106
|
-
|
|
100
|
+
logger.debug(i18n(`${i18nKey}.deleteFailed`, {
|
|
107
101
|
remoteFilePath,
|
|
108
102
|
}));
|
|
109
|
-
if (
|
|
103
|
+
if (isHubSpotHttpError(error)) {
|
|
110
104
|
error.updateContext({
|
|
111
105
|
accountId,
|
|
112
106
|
request: remoteFilePath,
|
|
@@ -116,23 +110,23 @@ async function deleteRemoteFile(accountId, filePath, remoteFilePath) {
|
|
|
116
110
|
});
|
|
117
111
|
});
|
|
118
112
|
}
|
|
119
|
-
function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, notify, commandOptions, filePaths, }, postInitialUploadCallback = null, onUploadFolderError, onQueueAddError, onUploadFileError) {
|
|
120
|
-
const regex = new RegExp(`^${
|
|
113
|
+
export function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, notify, commandOptions, filePaths, }, postInitialUploadCallback = null, onUploadFolderError, onQueueAddError, onUploadFileError) {
|
|
114
|
+
const regex = new RegExp(`^${escapeRegExp(src)}`);
|
|
121
115
|
if (notify) {
|
|
122
|
-
|
|
116
|
+
ignoreFile(notify);
|
|
123
117
|
}
|
|
124
|
-
const watcher =
|
|
118
|
+
const watcher = chokidar.watch(src, {
|
|
125
119
|
ignoreInitial: true,
|
|
126
|
-
ignored: (file) =>
|
|
120
|
+
ignored: (file) => shouldIgnoreFile(file),
|
|
127
121
|
});
|
|
128
122
|
function getDesignManagerPath(file) {
|
|
129
123
|
const relativePath = file.replace(regex, '');
|
|
130
|
-
return
|
|
124
|
+
return convertToUnixPath(path.join(dest, relativePath));
|
|
131
125
|
}
|
|
132
126
|
if (!disableInitial) {
|
|
133
127
|
// Use uploadFolder so that failures of initial upload are retried
|
|
134
|
-
const uploadFolderPromise =
|
|
135
|
-
|
|
128
|
+
const uploadFolderPromise = uploadFolder(accountId, src, dest, {}, commandOptions, filePaths, cmsPublishMode || null).then(result => {
|
|
129
|
+
logger.log(i18n(`${i18nKey}.folderUploadSuccess`, {
|
|
136
130
|
src,
|
|
137
131
|
dest,
|
|
138
132
|
accountId,
|
|
@@ -146,7 +140,7 @@ function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, n
|
|
|
146
140
|
}
|
|
147
141
|
}
|
|
148
142
|
watcher.on('ready', () => {
|
|
149
|
-
|
|
143
|
+
logger.log(i18n(`${i18nKey}.ready`, { src }));
|
|
150
144
|
});
|
|
151
145
|
watcher.on('add', async (filePath) => {
|
|
152
146
|
const destPath = getDesignManagerPath(filePath);
|
|
@@ -154,26 +148,26 @@ function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, n
|
|
|
154
148
|
src,
|
|
155
149
|
commandOptions,
|
|
156
150
|
}, cmsPublishMode, onUploadFileError);
|
|
157
|
-
|
|
151
|
+
triggerNotify(notify, 'Added', filePath, uploadPromise);
|
|
158
152
|
});
|
|
159
153
|
if (remove) {
|
|
160
154
|
const deleteFileOrFolder = (type) => (filePath) => {
|
|
161
155
|
// If it's a fields.js file that is in a module folder or the root, then ignore because it will not exist on the server.
|
|
162
|
-
if (
|
|
156
|
+
if (isConvertableFieldJs(src, filePath, commandOptions.convertFields)) {
|
|
163
157
|
return;
|
|
164
158
|
}
|
|
165
159
|
const remotePath = getDesignManagerPath(filePath);
|
|
166
|
-
if (
|
|
167
|
-
|
|
160
|
+
if (shouldIgnoreFile(filePath)) {
|
|
161
|
+
logger.debug(i18n(`${i18nKey}.skipIgnoreRule`, { file: filePath }));
|
|
168
162
|
return;
|
|
169
163
|
}
|
|
170
|
-
|
|
164
|
+
logger.debug(i18n(`${i18nKey}.deleteAttemptWithType`, {
|
|
171
165
|
type,
|
|
172
166
|
remoteFilePath: remotePath,
|
|
173
167
|
}));
|
|
174
168
|
const queueAddPromise = queue.add(() => {
|
|
175
169
|
const deletePromise = deleteRemoteFile(accountId, filePath, remotePath).then(() => {
|
|
176
|
-
|
|
170
|
+
logger.log(i18n(`${i18nKey}.deleteSuccessWithType`, {
|
|
177
171
|
type,
|
|
178
172
|
remoteFilePath: remotePath,
|
|
179
173
|
}));
|
|
@@ -181,7 +175,7 @@ function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, n
|
|
|
181
175
|
if (onQueueAddError) {
|
|
182
176
|
queueAddPromise.catch(onQueueAddError);
|
|
183
177
|
}
|
|
184
|
-
|
|
178
|
+
triggerNotify(notify, 'Removed', filePath, deletePromise);
|
|
185
179
|
return deletePromise;
|
|
186
180
|
});
|
|
187
181
|
};
|
|
@@ -194,8 +188,7 @@ function watch(accountId, src, dest, { cmsPublishMode, remove, disableInitial, n
|
|
|
194
188
|
src,
|
|
195
189
|
commandOptions,
|
|
196
190
|
}, cmsPublishMode, onUploadFileError);
|
|
197
|
-
|
|
191
|
+
triggerNotify(notify, 'Changed', filePath, uploadPromise);
|
|
198
192
|
});
|
|
199
193
|
return watcher;
|
|
200
194
|
}
|
|
201
|
-
exports.watch = watch;
|
package/lib/crm.d.ts
CHANGED
package/lib/crm.js
CHANGED
|
@@ -1,48 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
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) {
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { getCwd } from './path.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import { i18n } from '../utils/lang.js';
|
|
5
|
+
export function getImportDataRequest(fileName) {
|
|
12
6
|
validateImportRequestFile(fileName);
|
|
13
|
-
const importRequest =
|
|
7
|
+
const importRequest = fs.readJsonSync(path.resolve(getCwd(), fileName));
|
|
14
8
|
const dataFileNames = importRequest.files.map(file => file.fileName);
|
|
15
9
|
// allow relative paths in the provided import request
|
|
16
10
|
importRequest.files = importRequest.files.map(file => ({
|
|
17
11
|
...file,
|
|
18
|
-
fileName:
|
|
12
|
+
fileName: path.basename(file.fileName),
|
|
19
13
|
}));
|
|
20
14
|
if (dataFileNames.length === 0) {
|
|
21
|
-
throw new Error(
|
|
15
|
+
throw new Error(i18n('lib.crm.importData.errors.noFiles'));
|
|
22
16
|
}
|
|
23
17
|
dataFileNames.forEach(fileName => {
|
|
24
18
|
if (!fileExists(fileName)) {
|
|
25
|
-
throw new Error(
|
|
19
|
+
throw new Error(i18n('lib.crm.importData.errors.fileNotFound', { fileName }));
|
|
26
20
|
}
|
|
27
21
|
});
|
|
28
22
|
return { importRequest, dataFileNames };
|
|
29
23
|
}
|
|
30
|
-
|
|
31
|
-
function validateImportRequestFile(fileName) {
|
|
24
|
+
export function validateImportRequestFile(fileName) {
|
|
32
25
|
if (!fileExists(fileName)) {
|
|
33
|
-
throw new Error(
|
|
26
|
+
throw new Error(i18n('lib.crm.importData.errors.fileNotFound', { fileName }));
|
|
34
27
|
}
|
|
35
|
-
if (
|
|
36
|
-
throw new Error(
|
|
28
|
+
if (path.extname(fileName) !== '.json') {
|
|
29
|
+
throw new Error(i18n('lib.crm.importData.errors.notJson'));
|
|
37
30
|
}
|
|
38
31
|
}
|
|
39
|
-
exports.validateImportRequestFile = validateImportRequestFile;
|
|
40
32
|
function fileExists(_path) {
|
|
41
33
|
try {
|
|
42
|
-
const absoluteSrcPath =
|
|
34
|
+
const absoluteSrcPath = path.resolve(getCwd(), _path);
|
|
43
35
|
if (!absoluteSrcPath)
|
|
44
36
|
return false;
|
|
45
|
-
const stats =
|
|
37
|
+
const stats = fs.statSync(absoluteSrcPath);
|
|
46
38
|
const isFile = stats.isFile();
|
|
47
39
|
if (!isFile) {
|
|
48
40
|
return false;
|
package/lib/customObjects.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema } from '../types/Schemas';
|
|
1
|
+
import { Schema } from '../types/Schemas.js';
|
|
2
2
|
export declare function getResolvedPath(dest?: string, name?: string): string;
|
|
3
3
|
export declare function writeSchemaToDisk(schema: Schema, dest?: string): Promise<void>;
|
|
4
4
|
export declare function downloadSchemas(accountId: number, dest?: string): Promise<Array<Schema>>;
|