@hubspot/local-dev-lib 0.0.4 → 0.0.6
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/customObjects.d.ts +7 -0
- package/api/customObjects.js +48 -0
- package/api/designManager.d.ts +13 -0
- package/api/designManager.js +21 -0
- package/api/fileManager.d.ts +5 -0
- package/api/fileManager.js +62 -0
- package/api/fileMapper.d.ts +10 -0
- package/api/fileMapper.js +104 -0
- package/api/functions.d.ts +4 -0
- package/api/functions.js +32 -0
- package/api/hubdb.d.ts +10 -0
- package/api/hubdb.js +61 -0
- package/api/lighthouseScore.d.ts +5 -0
- package/api/lighthouseScore.js +29 -0
- package/api/localDevAuth.d.ts +12 -0
- package/api/localDevAuth.js +38 -0
- package/api/marketplaceValidation.d.ts +5 -0
- package/api/marketplaceValidation.js +29 -0
- package/api/projects.d.ts +27 -0
- package/api/projects.js +126 -0
- package/api/sandboxHubs.d.ts +6 -0
- package/api/sandboxHubs.js +50 -0
- package/api/sandboxSync.d.ts +4 -0
- package/api/sandboxSync.js +35 -0
- package/api/secrets.d.ts +8 -0
- package/api/secrets.js +40 -0
- package/api/validateHubl.d.ts +2 -0
- package/api/validateHubl.js +18 -0
- package/config/CLIConfiguration.d.ts +22 -16
- package/config/CLIConfiguration.js +39 -9
- package/config/configFile.d.ts +4 -4
- package/config/configFile.js +2 -2
- package/config/configUtils.d.ts +8 -8
- package/config/config_DEPRECATED.d.ts +78 -0
- package/config/config_DEPRECATED.js +636 -0
- package/config/environment.d.ts +2 -3
- package/config/environment.js +11 -17
- package/config/index.d.ts +38 -0
- package/config/index.js +232 -0
- package/constants/api.d.ts +17 -0
- package/constants/api.js +20 -0
- package/constants/auth.d.ts +13 -0
- package/constants/auth.js +8 -1
- package/constants/config.d.ts +0 -4
- package/constants/config.js +1 -5
- package/constants/environments.d.ts +1 -0
- package/constants/environments.js +1 -0
- package/constants/extensions.d.ts +2 -0
- package/constants/extensions.js +4 -1
- package/constants/files.d.ts +16 -0
- package/constants/files.js +17 -1
- package/enums/build.d.ts +36 -0
- package/enums/build.js +39 -0
- package/enums/deploy.d.ts +11 -0
- package/enums/deploy.js +14 -0
- package/enums/project.d.ts +6 -0
- package/enums/project.js +9 -0
- package/errors/HubSpotAuthError.d.ts +8 -2
- package/errors/HubSpotAuthError.js +14 -0
- package/errors/apiErrors.d.ts +9 -0
- package/errors/apiErrors.js +182 -0
- package/errors/errors_DEPRECATED.d.ts +7 -0
- package/errors/errors_DEPRECATED.js +73 -0
- package/errors/fileSystemErrors.d.ts +1 -7
- package/errors/standardErrors.d.ts +7 -1
- package/errors/standardErrors.js +20 -23
- package/http/getAxiosConfig.d.ts +6 -0
- package/http/getAxiosConfig.js +22 -0
- package/http/index.d.ts +18 -0
- package/http/index.js +175 -0
- package/lang/en.lyaml +247 -0
- package/lib/cms/functions.d.ts +13 -0
- package/lib/cms/functions.js +181 -0
- package/lib/cms/handleFieldsJS.d.ts +2 -1
- package/lib/cms/handleFieldsJS.js +4 -3
- package/lib/cms/modules.js +3 -3
- package/lib/cms/processFieldsJs.d.ts +1 -0
- package/lib/cms/processFieldsJs.js +122 -0
- package/lib/cms/templates.d.ts +25 -0
- package/lib/cms/templates.js +62 -0
- package/lib/cms/themes.js +2 -2
- package/lib/cms/uploadFolder.d.ts +18 -0
- package/lib/cms/uploadFolder.js +182 -0
- package/lib/cms/watch.d.ts +20 -0
- package/lib/cms/watch.js +194 -0
- package/lib/customObjects.d.ts +5 -0
- package/lib/customObjects.js +36 -0
- package/lib/environment.d.ts +2 -1
- package/lib/fileMapper.d.ts +13 -0
- package/lib/fileMapper.js +322 -0
- package/lib/github.d.ts +6 -3
- package/lib/github.js +36 -27
- package/lib/gitignore.js +1 -46
- package/lib/hubdb.d.ts +16 -0
- package/lib/hubdb.js +130 -0
- package/lib/ignoreRules.d.ts +3 -0
- package/lib/ignoreRules.js +69 -0
- package/lib/logging/git.d.ts +2 -0
- package/lib/logging/git.js +54 -0
- package/lib/logging/logger.d.ts +44 -0
- package/lib/logging/logger.js +146 -0
- package/lib/logging/logs.d.ts +22 -0
- package/lib/logging/logs.js +82 -0
- package/lib/logging/table.d.ts +3 -0
- package/lib/logging/table.js +47 -0
- package/lib/oauth.d.ts +7 -0
- package/lib/oauth.js +44 -0
- package/lib/path.d.ts +2 -1
- package/lib/path.js +8 -3
- package/lib/personalAccessKey.d.ts +13 -0
- package/lib/personalAccessKey.js +135 -0
- package/lib/sandboxes.d.ts +14 -0
- package/lib/sandboxes.js +71 -0
- package/lib/trackUsage.d.ts +1 -0
- package/lib/trackUsage.js +53 -0
- package/lib/validate.d.ts +2 -0
- package/lib/validate.js +40 -0
- package/models/OAuth2Manager.d.ts +34 -0
- package/models/OAuth2Manager.js +126 -0
- package/package.json +25 -13
- package/types/Accounts.d.ts +66 -21
- package/types/Activity.d.ts +20 -0
- package/types/Activity.js +2 -0
- package/types/Api.d.ts +2 -0
- package/types/Api.js +2 -0
- package/types/Build.d.ts +41 -0
- package/types/Build.js +2 -0
- package/types/CLIOptions.d.ts +5 -0
- package/types/ComponentStructure.d.ts +20 -0
- package/types/ComponentStructure.js +2 -0
- package/types/Config.d.ts +17 -4
- package/types/Deploy.d.ts +42 -0
- package/types/Deploy.js +2 -0
- package/types/Error.d.ts +32 -7
- package/types/FileManager.d.ts +66 -0
- package/types/FileManager.js +2 -0
- package/types/Files.d.ts +33 -1
- package/types/Functions.d.ts +40 -0
- package/types/Functions.js +2 -0
- package/types/Github.d.ts +6 -0
- package/types/Http.d.ts +33 -0
- package/types/Http.js +2 -0
- package/types/Hubdb.d.ts +90 -0
- package/types/Hubdb.js +2 -0
- package/types/HublValidation.d.ts +59 -0
- package/types/HublValidation.js +2 -0
- package/types/Lighthouse.d.ts +25 -0
- package/types/Lighthouse.js +2 -0
- package/types/MarketplaceValidation.d.ts +28 -0
- package/types/MarketplaceValidation.js +2 -0
- package/types/Project.d.ts +38 -0
- package/types/Project.js +2 -0
- package/types/Sandbox.d.ts +165 -0
- package/types/Sandbox.js +2 -0
- package/types/Schemas.d.ts +42 -0
- package/types/Schemas.js +2 -0
- package/utils/{modules.d.ts → cms/modules.d.ts} +1 -1
- package/utils/{modules.js → cms/modules.js} +3 -3
- package/utils/getAccountIdentifier.d.ts +10 -0
- package/utils/getAccountIdentifier.js +40 -0
- package/utils/git.d.ts +7 -2
- package/utils/git.js +54 -7
- package/utils/lang.d.ts +4 -0
- package/utils/lang.js +9 -2
- package/utils/notify.d.ts +1 -0
- package/utils/notify.js +42 -0
- package/utils/objectUtils.d.ts +8 -0
- package/utils/objectUtils.js +33 -0
- package/constants/index.d.ts +0 -16
- package/constants/index.js +0 -12
- package/http/requestOptions.d.ts +0 -20
- package/http/requestOptions.js +0 -27
- package/lib/cms/index.d.ts +0 -10
- package/lib/cms/index.js +0 -13
- package/lib/index.d.ts +0 -11
- package/lib/index.js +0 -14
- /package/utils/{fieldsJS.d.ts → cms/fieldsJS.d.ts} +0 -0
- /package/utils/{fieldsJS.js → cms/fieldsJS.js} +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
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.createTemplate = exports.isCodedFile = exports.getAnnotationValue = exports.ANNOTATION_KEYS = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const github_1 = require("../../lib/github");
|
|
10
|
+
const standardErrors_1 = require("../../errors/standardErrors");
|
|
11
|
+
const logger_1 = require("../../utils/logger");
|
|
12
|
+
// Matches the .html file extension, excluding module.html
|
|
13
|
+
const TEMPLATE_EXTENSION_REGEX = new RegExp(/(?<!module)\.html$/);
|
|
14
|
+
// Matches an annotation value, ending at space, newline, or end of string
|
|
15
|
+
const ANNOTATION_VALUE_REGEX = ':\\s?([\\S|\\s]*?)(\n|$)';
|
|
16
|
+
exports.ANNOTATION_KEYS = {
|
|
17
|
+
isAvailableForNewContent: 'isAvailableForNewContent',
|
|
18
|
+
templateType: 'templateType',
|
|
19
|
+
label: 'label',
|
|
20
|
+
screenshotPath: 'screenshotPath',
|
|
21
|
+
// 'description' is specific to Sections
|
|
22
|
+
description: 'description',
|
|
23
|
+
};
|
|
24
|
+
function getAnnotationValue(annotations, key) {
|
|
25
|
+
const valueRegex = new RegExp(`${key}${ANNOTATION_VALUE_REGEX}`);
|
|
26
|
+
const match = annotations.match(valueRegex);
|
|
27
|
+
return match ? match[1].trim() : null;
|
|
28
|
+
}
|
|
29
|
+
exports.getAnnotationValue = getAnnotationValue;
|
|
30
|
+
/*
|
|
31
|
+
* Returns true if:
|
|
32
|
+
* .html extension (ignoring module.html)
|
|
33
|
+
*/
|
|
34
|
+
function isCodedFile(filePath) {
|
|
35
|
+
return TEMPLATE_EXTENSION_REGEX.test(filePath);
|
|
36
|
+
}
|
|
37
|
+
exports.isCodedFile = isCodedFile;
|
|
38
|
+
const ASSET_PATHS = {
|
|
39
|
+
'page-template': 'templates/page-template.html',
|
|
40
|
+
partial: 'templates/partial.html',
|
|
41
|
+
'global-partial': 'templates/global-partial.html',
|
|
42
|
+
'email-template': 'templates/email-template.html',
|
|
43
|
+
'blog-listing-template': 'templates/blog-listing-template.html',
|
|
44
|
+
'blog-post-template': 'templates/blog-post-template.html',
|
|
45
|
+
'search-template': 'templates/search-template.html',
|
|
46
|
+
section: 'templates/section.html',
|
|
47
|
+
};
|
|
48
|
+
const templatesCallbackKeys = ['creatingFile'];
|
|
49
|
+
async function createTemplate(name, dest, type = 'page-template', options = { allowExisting: false }, logCallbacks) {
|
|
50
|
+
const assetPath = ASSET_PATHS[type];
|
|
51
|
+
const filename = name.endsWith('.html') ? name : `${name}.html`;
|
|
52
|
+
const filePath = path_1.default.join(dest, filename);
|
|
53
|
+
if (!options.allowExisting && fs_extra_1.default.existsSync(filePath)) {
|
|
54
|
+
(0, standardErrors_1.throwErrorWithMessage)('templates.pathExists', { path: filePath });
|
|
55
|
+
}
|
|
56
|
+
(0, logger_1.debug)('templates.debug.creatingPath', { path: dest });
|
|
57
|
+
fs_extra_1.default.mkdirp(dest);
|
|
58
|
+
const logger = (0, logger_1.makeTypedLogger)(logCallbacks, 'templates.logging');
|
|
59
|
+
logger('creatingFile', { path: filePath });
|
|
60
|
+
await (0, github_1.downloadGithubRepoContents)('HubSpot/cms-sample-assets', assetPath, filePath);
|
|
61
|
+
}
|
|
62
|
+
exports.createTemplate = createTemplate;
|
package/lib/cms/themes.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.getThemePreviewUrl = exports.getThemeJSONPath = void 0;
|
|
|
7
7
|
const findup_sync_1 = __importDefault(require("findup-sync"));
|
|
8
8
|
const urls_1 = require("../urls");
|
|
9
9
|
const environments_1 = require("../../constants/environments");
|
|
10
|
-
const
|
|
10
|
+
const config_1 = require("../../config");
|
|
11
11
|
function getThemeJSONPath(path) {
|
|
12
12
|
return (0, findup_sync_1.default)('theme.json', {
|
|
13
13
|
cwd: path,
|
|
@@ -28,7 +28,7 @@ function getThemePreviewUrl(filePath, accountId) {
|
|
|
28
28
|
const themeName = getThemeNameFromPath(filePath);
|
|
29
29
|
if (!themeName)
|
|
30
30
|
return;
|
|
31
|
-
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)(
|
|
31
|
+
const baseUrl = (0, urls_1.getHubSpotWebsiteOrigin)((0, config_1.getEnv)(accountId) === 'qa' ? environments_1.ENVIRONMENTS.QA : environments_1.ENVIRONMENTS.PROD);
|
|
32
32
|
return `${baseUrl}/theme-previewer/${accountId}/edit/${encodeURIComponent(themeName)}`;
|
|
33
33
|
}
|
|
34
34
|
exports.getThemePreviewUrl = getThemePreviewUrl;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FieldsJs } from './handleFieldsJS';
|
|
2
|
+
import { FileMapperInputOptions } from '../../types/Files';
|
|
3
|
+
import { LogCallbacksArg } from '../../types/LogCallbacks';
|
|
4
|
+
import { UploadFolderResults } from '../../types/Files';
|
|
5
|
+
import { Mode } from '../../types/Files';
|
|
6
|
+
type CommandOptions = {
|
|
7
|
+
convertFields?: boolean;
|
|
8
|
+
fieldOptions?: string;
|
|
9
|
+
saveOutput?: boolean;
|
|
10
|
+
};
|
|
11
|
+
type FilePathsByType = {
|
|
12
|
+
[key: string]: Array<string>;
|
|
13
|
+
};
|
|
14
|
+
export declare function getFilesByType(filePaths: Array<string>, projectDir: string, rootWriteDir: string | null, commandOptions: CommandOptions): Promise<[FilePathsByType, Array<FieldsJs>]>;
|
|
15
|
+
declare const uploadFolderCallbackKeys: string[];
|
|
16
|
+
export declare function uploadFolder(accountId: number, src: string, dest: string, fileMapperOptions: FileMapperInputOptions, commandOptions?: CommandOptions, filePaths?: Array<string>, mode?: Mode | null, logCallbacks?: LogCallbacksArg<typeof uploadFolderCallbackKeys>): Promise<Array<UploadFolderResults>>;
|
|
17
|
+
export declare function hasUploadErrors(results: Array<UploadFolderResults>): boolean;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,182 @@
|
|
|
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.hasUploadErrors = exports.uploadFolder = exports.getFilesByType = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const p_queue_1 = __importDefault(require("p-queue"));
|
|
9
|
+
const handleFieldsJS_1 = require("./handleFieldsJS");
|
|
10
|
+
const fileMapper_1 = require("../fileMapper");
|
|
11
|
+
const fileMapper_2 = require("../../api/fileMapper");
|
|
12
|
+
const modules_1 = require("../../utils/cms/modules");
|
|
13
|
+
const escapeRegExp_1 = require("../../utils/escapeRegExp");
|
|
14
|
+
const logger_1 = require("../../utils/logger");
|
|
15
|
+
const path_2 = require("../path");
|
|
16
|
+
const standardErrors_1 = require("../../errors/standardErrors");
|
|
17
|
+
const apiErrors_1 = require("../../errors/apiErrors");
|
|
18
|
+
const logger_2 = require("../../utils/logger");
|
|
19
|
+
const files_1 = require("../../constants/files");
|
|
20
|
+
const queue = new p_queue_1.default({
|
|
21
|
+
concurrency: 10,
|
|
22
|
+
});
|
|
23
|
+
function getFileType(filePath) {
|
|
24
|
+
const extension = (0, path_2.getExt)(filePath);
|
|
25
|
+
const moduleFolder = (0, modules_1.isModuleFolderChild)({ path: filePath, isLocal: true });
|
|
26
|
+
if (moduleFolder)
|
|
27
|
+
return files_1.FILE_TYPES.module;
|
|
28
|
+
switch (extension) {
|
|
29
|
+
case 'js':
|
|
30
|
+
case 'css':
|
|
31
|
+
return files_1.FILE_TYPES.cssAndJs;
|
|
32
|
+
case 'html':
|
|
33
|
+
return files_1.FILE_TYPES.template;
|
|
34
|
+
case 'json':
|
|
35
|
+
return files_1.FILE_TYPES.json;
|
|
36
|
+
default:
|
|
37
|
+
return files_1.FILE_TYPES.other;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOptions) {
|
|
41
|
+
const { convertFields, fieldOptions } = commandOptions;
|
|
42
|
+
const projectDirRegex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(projectDir)}`);
|
|
43
|
+
const fieldsJsObjects = [];
|
|
44
|
+
// Create object with key-value pairs of form { FileType.type: [] }
|
|
45
|
+
const filePathsByType = Object.values(files_1.FILE_TYPES).reduce((acc, fileType) => {
|
|
46
|
+
return {
|
|
47
|
+
...acc,
|
|
48
|
+
[fileType]: [],
|
|
49
|
+
};
|
|
50
|
+
}, {});
|
|
51
|
+
for (const filePath of filePaths) {
|
|
52
|
+
const fileType = getFileType(filePath);
|
|
53
|
+
const relPath = filePath.replace(projectDirRegex, '');
|
|
54
|
+
if (!convertFields) {
|
|
55
|
+
filePathsByType[fileType].push(filePath);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const convertableFields = (0, handleFieldsJS_1.isConvertableFieldJs)(projectDir, filePath, convertFields);
|
|
59
|
+
if (convertableFields) {
|
|
60
|
+
const rootOrModule = path_1.default.dirname(relPath) === '/' ? files_1.FILE_TYPES.json : files_1.FILE_TYPES.module;
|
|
61
|
+
const fieldsJs = await new handleFieldsJS_1.FieldsJs(projectDir, filePath, rootWriteDir, fieldOptions).init();
|
|
62
|
+
/*
|
|
63
|
+
* A fields.js will be rejected if the promise is rejected or if the some other error occurs.
|
|
64
|
+
* We handle this gracefully by not adding the failed fields.js to the object list.
|
|
65
|
+
*/
|
|
66
|
+
if (fieldsJs.rejected)
|
|
67
|
+
continue;
|
|
68
|
+
fieldsJsObjects.push(fieldsJs);
|
|
69
|
+
filePathsByType[rootOrModule].push(fieldsJs.outputPath || '');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
filePathsByType[fileType].push(filePath);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return [filePathsByType, fieldsJsObjects];
|
|
76
|
+
}
|
|
77
|
+
exports.getFilesByType = getFilesByType;
|
|
78
|
+
const uploadFolderCallbackKeys = ['success'];
|
|
79
|
+
async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOptions = {}, filePaths = [], mode = null, logCallbacks) {
|
|
80
|
+
const logger = (0, logger_2.makeTypedLogger)(logCallbacks, 'cms.uploadFolder');
|
|
81
|
+
const { saveOutput, convertFields } = commandOptions;
|
|
82
|
+
const tmpDir = convertFields
|
|
83
|
+
? (0, handleFieldsJS_1.createTmpDirSync)('hubspot-temp-fieldsjs-output-')
|
|
84
|
+
: null;
|
|
85
|
+
const regex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(src)}`);
|
|
86
|
+
const apiOptions = (0, fileMapper_1.getFileMapperQueryValues)(mode, fileMapperOptions);
|
|
87
|
+
const failures = [];
|
|
88
|
+
let fieldsJsPaths = [];
|
|
89
|
+
let tmpDirRegex;
|
|
90
|
+
const [filesByType, fieldsJsObjects] = await getFilesByType(filePaths, src, tmpDir, commandOptions);
|
|
91
|
+
const fileList = Object.values(filesByType);
|
|
92
|
+
if (fieldsJsObjects.length) {
|
|
93
|
+
fieldsJsPaths = fieldsJsObjects.map(fieldsJs => {
|
|
94
|
+
return { outputPath: fieldsJs.outputPath, filePath: fieldsJs.filePath };
|
|
95
|
+
});
|
|
96
|
+
tmpDirRegex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(tmpDir || '')}`);
|
|
97
|
+
}
|
|
98
|
+
function uploadFile(file) {
|
|
99
|
+
const fieldsJsFileInfo = fieldsJsPaths.find(f => f.outputPath === file);
|
|
100
|
+
const originalFilePath = fieldsJsFileInfo
|
|
101
|
+
? fieldsJsFileInfo.filePath
|
|
102
|
+
: file;
|
|
103
|
+
// files in fieldsJsPaths always belong to the tmp directory.
|
|
104
|
+
const relativePath = file.replace(fieldsJsFileInfo ? tmpDirRegex : regex, '');
|
|
105
|
+
const destPath = (0, path_2.convertToUnixPath)(path_1.default.join(dest, relativePath));
|
|
106
|
+
return async () => {
|
|
107
|
+
(0, logger_1.debug)('cms.uploadFolder.attempt', {
|
|
108
|
+
file: originalFilePath || '',
|
|
109
|
+
destPath,
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
await (0, fileMapper_2.upload)(accountId, file, destPath, apiOptions);
|
|
113
|
+
logger('success', {
|
|
114
|
+
file: originalFilePath || '',
|
|
115
|
+
destPath,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
const error = err;
|
|
120
|
+
if ((0, standardErrors_1.isFatalError)(error)) {
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
(0, logger_1.debug)('cms.uploadFolder.failed', { file, destPath });
|
|
124
|
+
if (error.response && error.response.body) {
|
|
125
|
+
console.debug(error.response.body);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.debug(error.message);
|
|
129
|
+
}
|
|
130
|
+
failures.push({
|
|
131
|
+
file,
|
|
132
|
+
destPath,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
for (let i = 0; i < fileList.length; i++) {
|
|
138
|
+
const filesToUpload = fileList[i];
|
|
139
|
+
await queue.addAll(filesToUpload.map(uploadFile));
|
|
140
|
+
}
|
|
141
|
+
const results = await queue
|
|
142
|
+
.addAll(failures.map(({ file, destPath }) => {
|
|
143
|
+
return async () => {
|
|
144
|
+
(0, logger_1.debug)('cms.uploadFolder.retry', { file, destPath });
|
|
145
|
+
try {
|
|
146
|
+
await (0, fileMapper_2.upload)(accountId, file, destPath, apiOptions);
|
|
147
|
+
logger('success', { file, destPath });
|
|
148
|
+
return {
|
|
149
|
+
resultType: files_1.FILE_UPLOAD_RESULT_TYPES.SUCCESS,
|
|
150
|
+
error: null,
|
|
151
|
+
file,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
(0, logger_1.debug)('cms.uploadFolder.retryFailed', { file, destPath });
|
|
156
|
+
const error = err;
|
|
157
|
+
if ((0, standardErrors_1.isFatalError)(error)) {
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
(0, apiErrors_1.throwApiUploadError)(error, {
|
|
161
|
+
accountId,
|
|
162
|
+
request: destPath,
|
|
163
|
+
payload: file,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}))
|
|
168
|
+
.finally(() => {
|
|
169
|
+
if (!convertFields)
|
|
170
|
+
return;
|
|
171
|
+
if (saveOutput) {
|
|
172
|
+
fieldsJsObjects.forEach(fieldsJs => fieldsJs.saveOutput());
|
|
173
|
+
}
|
|
174
|
+
(0, handleFieldsJS_1.cleanupTmpDirSync)(tmpDir || '');
|
|
175
|
+
});
|
|
176
|
+
return results;
|
|
177
|
+
}
|
|
178
|
+
exports.uploadFolder = uploadFolder;
|
|
179
|
+
function hasUploadErrors(results) {
|
|
180
|
+
return results.some(result => result.resultType === files_1.FILE_UPLOAD_RESULT_TYPES.FAILURE);
|
|
181
|
+
}
|
|
182
|
+
exports.hasUploadErrors = hasUploadErrors;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import chokidar from 'chokidar';
|
|
2
|
+
import { LogCallbacksArg } from '../../types/LogCallbacks';
|
|
3
|
+
import { Mode } from '../../types/Files';
|
|
4
|
+
import { UploadFolderResults } from '../../types/Files';
|
|
5
|
+
import { StatusCodeError } from '../../types/Error';
|
|
6
|
+
declare const watchCallbackKeys: readonly ["notifyOfThemePreview", "uploadSuccess", "deleteSuccess", "folderUploadSuccess", "ready", "deleteSuccessWithType"];
|
|
7
|
+
type WatchLogCallbacks = LogCallbacksArg<typeof watchCallbackKeys>;
|
|
8
|
+
type WatchOptions = {
|
|
9
|
+
mode?: Mode;
|
|
10
|
+
remove?: boolean;
|
|
11
|
+
disableInitial?: boolean;
|
|
12
|
+
notify?: string;
|
|
13
|
+
commandOptions: {
|
|
14
|
+
convertFields?: boolean;
|
|
15
|
+
};
|
|
16
|
+
filePaths?: Array<string>;
|
|
17
|
+
};
|
|
18
|
+
type ErrorHandler = (error: StatusCodeError) => void;
|
|
19
|
+
export declare function watch(accountId: number, src: string, dest: string, { mode, remove, disableInitial, notify, commandOptions, filePaths, }: WatchOptions, postInitialUploadCallback?: ((result: Array<UploadFolderResults>) => void) | null, onUploadFolderError?: ErrorHandler, onQueueAddError?: ErrorHandler, logCallbacks?: WatchLogCallbacks): chokidar.FSWatcher;
|
|
20
|
+
export {};
|
package/lib/cms/watch.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
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.watch = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
9
|
+
const p_queue_1 = __importDefault(require("p-queue"));
|
|
10
|
+
const debounce_1 = require("debounce");
|
|
11
|
+
const apiErrors_1 = require("../../errors/apiErrors");
|
|
12
|
+
const handleFieldsJS_1 = require("./handleFieldsJS");
|
|
13
|
+
const uploadFolder_1 = require("./uploadFolder");
|
|
14
|
+
const ignoreRules_1 = require("../ignoreRules");
|
|
15
|
+
const fileMapper_1 = require("../fileMapper");
|
|
16
|
+
const fileMapper_2 = require("../../api/fileMapper");
|
|
17
|
+
const escapeRegExp_1 = require("../../utils/escapeRegExp");
|
|
18
|
+
const path_2 = require("../path");
|
|
19
|
+
const notify_1 = require("../../utils/notify");
|
|
20
|
+
const themes_1 = require("./themes");
|
|
21
|
+
const logger_1 = require("../../utils/logger");
|
|
22
|
+
const logger_2 = require("../../utils/logger");
|
|
23
|
+
const watchCallbackKeys = [
|
|
24
|
+
'notifyOfThemePreview',
|
|
25
|
+
'uploadSuccess',
|
|
26
|
+
'deleteSuccess',
|
|
27
|
+
'folderUploadSuccess',
|
|
28
|
+
'ready',
|
|
29
|
+
'deleteSuccessWithType',
|
|
30
|
+
];
|
|
31
|
+
const makeLogger = (logger_1.makeTypedLogger);
|
|
32
|
+
const queue = new p_queue_1.default({
|
|
33
|
+
concurrency: 10,
|
|
34
|
+
});
|
|
35
|
+
function _notifyOfThemePreview(filePath, accountId, logCallbacks) {
|
|
36
|
+
const logger = makeLogger(logCallbacks, 'watch');
|
|
37
|
+
if (queue.size > 0)
|
|
38
|
+
return;
|
|
39
|
+
const previewUrl = (0, themes_1.getThemePreviewUrl)(filePath, accountId);
|
|
40
|
+
if (!previewUrl)
|
|
41
|
+
return;
|
|
42
|
+
logger('notifyOfThemePreview', { previewUrl });
|
|
43
|
+
}
|
|
44
|
+
const notifyOfThemePreview = (0, debounce_1.debounce)(_notifyOfThemePreview, 1000);
|
|
45
|
+
async function uploadFile(accountId, file, dest, options, mode = null, logCallbacks) {
|
|
46
|
+
const logger = makeLogger(logCallbacks, 'watch');
|
|
47
|
+
const src = options.src;
|
|
48
|
+
const absoluteSrcPath = path_1.default.resolve((0, path_2.getCwd)(), file);
|
|
49
|
+
const themeJsonPath = (0, themes_1.getThemeJSONPath)(absoluteSrcPath);
|
|
50
|
+
const projectRoot = themeJsonPath
|
|
51
|
+
? path_1.default.dirname(themeJsonPath)
|
|
52
|
+
: path_1.default.dirname((0, path_2.getCwd)());
|
|
53
|
+
const convertFields = (0, handleFieldsJS_1.isConvertableFieldJs)(src, file, options.commandOptions.convertFields);
|
|
54
|
+
if (!(0, path_2.isAllowedExtension)(file) && !convertFields) {
|
|
55
|
+
(0, logger_2.debug)('watch.skipUnsupportedExtension', { file });
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if ((0, ignoreRules_1.shouldIgnoreFile)(file)) {
|
|
59
|
+
(0, logger_2.debug)('watch.skipIgnoreRule', { file });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let fieldsJs = undefined;
|
|
63
|
+
if (convertFields) {
|
|
64
|
+
fieldsJs = await new handleFieldsJS_1.FieldsJs(projectRoot, absoluteSrcPath, undefined, options.fieldOptions).init();
|
|
65
|
+
if (fieldsJs.rejected)
|
|
66
|
+
return;
|
|
67
|
+
// Ensures that the dest path is a .json. The user might pass '.js' accidentally - this ensures it just works.
|
|
68
|
+
dest = (0, path_2.convertToUnixPath)(path_1.default.join(path_1.default.dirname(dest), 'fields.json'));
|
|
69
|
+
}
|
|
70
|
+
const fileToUpload = convertFields && fieldsJs?.outputPath ? fieldsJs.outputPath : file;
|
|
71
|
+
(0, logger_2.debug)('watch.uploadAttempt', { file, dest });
|
|
72
|
+
const apiOptions = (0, fileMapper_1.getFileMapperQueryValues)(mode, options);
|
|
73
|
+
queue.add(() => {
|
|
74
|
+
return (0, fileMapper_2.upload)(accountId, fileToUpload, dest, apiOptions)
|
|
75
|
+
.then(() => {
|
|
76
|
+
logger('uploadSuccess', { file, dest });
|
|
77
|
+
notifyOfThemePreview(file, accountId, logCallbacks);
|
|
78
|
+
})
|
|
79
|
+
.catch(() => {
|
|
80
|
+
(0, logger_2.debug)('watch.uploadFailed', { file, dest });
|
|
81
|
+
(0, logger_2.debug)('watch.uploadRetry', { file, dest });
|
|
82
|
+
return (0, fileMapper_2.upload)(accountId, file, dest, apiOptions).catch((error) => {
|
|
83
|
+
(0, logger_2.debug)('watch.uploadFailed', { file, dest });
|
|
84
|
+
(0, apiErrors_1.throwApiUploadError)(error, {
|
|
85
|
+
accountId,
|
|
86
|
+
request: dest,
|
|
87
|
+
payload: file,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async function deleteRemoteFile(accountId, filePath, remoteFilePath, logCallbacks) {
|
|
94
|
+
const logger = makeLogger(logCallbacks, 'watch');
|
|
95
|
+
if ((0, ignoreRules_1.shouldIgnoreFile)(filePath)) {
|
|
96
|
+
(0, logger_2.debug)('watch.skipIgnoreRule', { file: filePath });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
(0, logger_2.debug)('watch.deleteAttempt', { remoteFilePath });
|
|
100
|
+
return queue.add(() => {
|
|
101
|
+
return (0, fileMapper_2.deleteFile)(accountId, remoteFilePath)
|
|
102
|
+
.then(() => {
|
|
103
|
+
logger('deleteSuccess', { remoteFilePath });
|
|
104
|
+
notifyOfThemePreview(filePath, accountId, logCallbacks);
|
|
105
|
+
})
|
|
106
|
+
.catch((error) => {
|
|
107
|
+
(0, logger_2.debug)('watch.deleteFailed', { remoteFilePath });
|
|
108
|
+
(0, apiErrors_1.throwApiError)(error, {
|
|
109
|
+
accountId,
|
|
110
|
+
request: remoteFilePath,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function watch(accountId, src, dest, { mode, remove, disableInitial, notify, commandOptions, filePaths, }, postInitialUploadCallback = null, onUploadFolderError, onQueueAddError, logCallbacks) {
|
|
116
|
+
const logger = makeLogger(logCallbacks, 'watch');
|
|
117
|
+
const regex = new RegExp(`^${(0, escapeRegExp_1.escapeRegExp)(src)}`);
|
|
118
|
+
if (notify) {
|
|
119
|
+
(0, ignoreRules_1.ignoreFile)(notify);
|
|
120
|
+
}
|
|
121
|
+
const watcher = chokidar_1.default.watch(src, {
|
|
122
|
+
ignoreInitial: true,
|
|
123
|
+
ignored: (file) => (0, ignoreRules_1.shouldIgnoreFile)(file),
|
|
124
|
+
});
|
|
125
|
+
function getDesignManagerPath(file) {
|
|
126
|
+
const relativePath = file.replace(regex, '');
|
|
127
|
+
return (0, path_2.convertToUnixPath)(path_1.default.join(dest, relativePath));
|
|
128
|
+
}
|
|
129
|
+
if (!disableInitial) {
|
|
130
|
+
// Use uploadFolder so that failures of initial upload are retried
|
|
131
|
+
const uploadFolderPromise = (0, uploadFolder_1.uploadFolder)(accountId, src, dest, {}, commandOptions, filePaths, mode || null).then(result => {
|
|
132
|
+
logger('folderUploadSuccess', { src, dest, accountId });
|
|
133
|
+
if (postInitialUploadCallback) {
|
|
134
|
+
postInitialUploadCallback(result);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
if (onUploadFolderError) {
|
|
138
|
+
uploadFolderPromise.catch(onUploadFolderError);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
watcher.on('ready', () => {
|
|
142
|
+
logger('ready', { src });
|
|
143
|
+
});
|
|
144
|
+
watcher.on('add', async (filePath) => {
|
|
145
|
+
const destPath = getDesignManagerPath(filePath);
|
|
146
|
+
const uploadPromise = uploadFile(accountId, filePath, destPath, {
|
|
147
|
+
src,
|
|
148
|
+
commandOptions,
|
|
149
|
+
}, mode, logCallbacks);
|
|
150
|
+
(0, notify_1.triggerNotify)(notify, 'Added', filePath, uploadPromise);
|
|
151
|
+
});
|
|
152
|
+
if (remove) {
|
|
153
|
+
const deleteFileOrFolder = (type) => (filePath) => {
|
|
154
|
+
// 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.
|
|
155
|
+
if ((0, handleFieldsJS_1.isConvertableFieldJs)(src, filePath, commandOptions.convertFields)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const remotePath = getDesignManagerPath(filePath);
|
|
159
|
+
if ((0, ignoreRules_1.shouldIgnoreFile)(filePath)) {
|
|
160
|
+
(0, logger_2.debug)('watch.skipIgnoreRule', { file: filePath });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
(0, logger_2.debug)('watch.deleteAttemptWithType', {
|
|
164
|
+
type,
|
|
165
|
+
remoteFilePath: remotePath,
|
|
166
|
+
});
|
|
167
|
+
const queueAddPromise = queue.add(() => {
|
|
168
|
+
const deletePromise = deleteRemoteFile(accountId, filePath, remotePath, logCallbacks).then(() => {
|
|
169
|
+
logger('deleteSuccessWithType', {
|
|
170
|
+
type,
|
|
171
|
+
remoteFilePath: remotePath,
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
if (onQueueAddError) {
|
|
175
|
+
queueAddPromise.catch(onQueueAddError);
|
|
176
|
+
}
|
|
177
|
+
(0, notify_1.triggerNotify)(notify, 'Removed', filePath, deletePromise);
|
|
178
|
+
return deletePromise;
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
watcher.on('unlink', deleteFileOrFolder('file'));
|
|
182
|
+
watcher.on('unlinkDir', deleteFileOrFolder('folder'));
|
|
183
|
+
}
|
|
184
|
+
watcher.on('change', async (filePath) => {
|
|
185
|
+
const destPath = getDesignManagerPath(filePath);
|
|
186
|
+
const uploadPromise = uploadFile(accountId, filePath, destPath, {
|
|
187
|
+
src,
|
|
188
|
+
commandOptions,
|
|
189
|
+
}, mode, logCallbacks);
|
|
190
|
+
(0, notify_1.triggerNotify)(notify, 'Changed', filePath, uploadPromise);
|
|
191
|
+
});
|
|
192
|
+
return watcher;
|
|
193
|
+
}
|
|
194
|
+
exports.watch = watch;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Schema } from '../types/Schemas';
|
|
2
|
+
export declare function getResolvedPath(dest: string, name: string): string;
|
|
3
|
+
export declare function writeSchemaToDisk(schema: Schema, dest: string): Promise<void>;
|
|
4
|
+
export declare function downloadSchemas(accountId: number, dest: string): Promise<void>;
|
|
5
|
+
export declare function downloadSchema(accountId: number, schemaObjectType: string, dest: string): Promise<void>;
|
|
@@ -0,0 +1,36 @@
|
|
|
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.downloadSchema = exports.downloadSchemas = exports.writeSchemaToDisk = exports.getResolvedPath = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const prettier_1 = __importDefault(require("prettier"));
|
|
10
|
+
const path_2 = require("../lib/path");
|
|
11
|
+
const customObjects_1 = require("../api/customObjects");
|
|
12
|
+
function getResolvedPath(dest, name) {
|
|
13
|
+
if (name)
|
|
14
|
+
return path_1.default.resolve((0, path_2.getCwd)(), dest || '', `${name}.json`);
|
|
15
|
+
return path_1.default.resolve((0, path_2.getCwd)(), dest || '');
|
|
16
|
+
}
|
|
17
|
+
exports.getResolvedPath = getResolvedPath;
|
|
18
|
+
async function writeSchemaToDisk(schema, dest) {
|
|
19
|
+
const formattedSchema = await prettier_1.default.format(JSON.stringify(schema), {
|
|
20
|
+
parser: 'json',
|
|
21
|
+
});
|
|
22
|
+
fs_extra_1.default.outputFileSync(getResolvedPath(dest, schema.name), formattedSchema);
|
|
23
|
+
}
|
|
24
|
+
exports.writeSchemaToDisk = writeSchemaToDisk;
|
|
25
|
+
async function downloadSchemas(accountId, dest) {
|
|
26
|
+
const response = await (0, customObjects_1.fetchObjectSchemas)(accountId);
|
|
27
|
+
if (response.results.length) {
|
|
28
|
+
response.results.forEach((r) => writeSchemaToDisk(r, dest));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.downloadSchemas = downloadSchemas;
|
|
32
|
+
async function downloadSchema(accountId, schemaObjectType, dest) {
|
|
33
|
+
const response = await (0, customObjects_1.fetchObjectSchema)(accountId, schemaObjectType);
|
|
34
|
+
writeSchemaToDisk(response, dest);
|
|
35
|
+
}
|
|
36
|
+
exports.downloadSchema = downloadSchema;
|
package/lib/environment.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Environment } from '../types/Config';
|
|
2
|
+
export declare function getValidEnv(env?: Environment | null, maskedProductionValue?: Environment): Environment;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Mode, FileMapperOptions, FileMapperInputOptions } from '../types/Files';
|
|
2
|
+
import { LogCallbacksArg } from '../types/LogCallbacks';
|
|
3
|
+
export declare function getFileMapperQueryValues(mode: Mode | null, { staging, assetVersion }: FileMapperInputOptions): FileMapperOptions;
|
|
4
|
+
declare const filemapperCallbackKeys: string[];
|
|
5
|
+
/**
|
|
6
|
+
* Fetch a file/folder and write to local file system.
|
|
7
|
+
*
|
|
8
|
+
* @async
|
|
9
|
+
* @param {FileMapperInputArguments} input
|
|
10
|
+
* @returns {Promise}
|
|
11
|
+
*/
|
|
12
|
+
export declare function downloadFileOrFolder(accountId: number, src: string, dest: string, mode: Mode, options: FileMapperInputOptions | undefined, logCallbacks: LogCallbacksArg<typeof filemapperCallbackKeys>): Promise<void>;
|
|
13
|
+
export {};
|