@hubspot/local-dev-lib 0.0.11 → 0.1.0-experimental.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSE +12 -0
  2. package/README.md +17 -0
  3. package/api/appsDev.d.ts +6 -0
  4. package/api/appsDev.js +29 -0
  5. package/api/customObjects.d.ts +8 -7
  6. package/api/customObjects.js +13 -16
  7. package/api/designManager.d.ts +5 -13
  8. package/api/designManager.js +6 -9
  9. package/api/developerTestAccounts.d.ts +7 -0
  10. package/api/developerTestAccounts.js +48 -0
  11. package/api/fileManager.d.ts +6 -5
  12. package/api/fileManager.js +13 -12
  13. package/api/fileMapper.d.ts +8 -8
  14. package/api/fileMapper.js +19 -18
  15. package/api/fileTransport.d.ts +4 -0
  16. package/api/fileTransport.js +39 -0
  17. package/api/functions.d.ts +7 -3
  18. package/api/functions.js +22 -11
  19. package/api/github.d.ts +11 -0
  20. package/api/github.js +71 -0
  21. package/api/hubdb.d.ts +11 -9
  22. package/api/hubdb.js +28 -22
  23. package/api/lighthouseScore.d.ts +4 -3
  24. package/api/lighthouseScore.js +9 -12
  25. package/api/localDevAuth.d.ts +7 -15
  26. package/api/localDevAuth.js +28 -13
  27. package/api/marketplaceValidation.d.ts +4 -3
  28. package/api/marketplaceValidation.js +8 -11
  29. package/api/projects.d.ts +34 -21
  30. package/api/projects.js +135 -45
  31. package/api/sandboxHubs.d.ts +5 -4
  32. package/api/sandboxHubs.js +10 -11
  33. package/api/sandboxSync.d.ts +4 -4
  34. package/api/sandboxSync.js +5 -14
  35. package/api/secrets.d.ts +6 -8
  36. package/api/secrets.js +9 -12
  37. package/api/validateHubl.d.ts +2 -1
  38. package/api/validateHubl.js +3 -6
  39. package/config/CLIConfiguration.d.ts +13 -10
  40. package/config/CLIConfiguration.js +129 -77
  41. package/config/configFile.js +12 -18
  42. package/config/configUtils.d.ts +2 -21
  43. package/config/configUtils.js +5 -4
  44. package/config/config_DEPRECATED.d.ts +6 -8
  45. package/config/config_DEPRECATED.js +73 -24
  46. package/config/environment.js +5 -4
  47. package/config/getAccountIdentifier.d.ts +2 -0
  48. package/config/getAccountIdentifier.js +15 -0
  49. package/config/index.d.ts +10 -7
  50. package/config/index.js +83 -55
  51. package/constants/api.d.ts +10 -12
  52. package/constants/api.js +10 -12
  53. package/constants/config.d.ts +15 -1
  54. package/constants/config.js +17 -3
  55. package/constants/environments.d.ts +1 -0
  56. package/constants/environments.js +1 -0
  57. package/constants/extensions.d.ts +2 -0
  58. package/constants/extensions.js +3 -1
  59. package/constants/files.d.ts +2 -2
  60. package/constants/files.js +3 -3
  61. package/errors/errors_DEPRECATED.d.ts +1 -5
  62. package/errors/errors_DEPRECATED.js +3 -16
  63. package/errors/index.d.ts +18 -0
  64. package/errors/index.js +63 -0
  65. package/http/addQueryParams.d.ts +2 -0
  66. package/http/addQueryParams.js +14 -0
  67. package/http/getAxiosConfig.d.ts +6 -3
  68. package/http/getAxiosConfig.js +51 -7
  69. package/http/index.d.ts +10 -11
  70. package/http/index.js +35 -41
  71. package/http/unauthed.d.ts +15 -0
  72. package/http/unauthed.js +38 -0
  73. package/lang/en.json +374 -368
  74. package/lib/archive.d.ts +2 -8
  75. package/lib/archive.js +34 -30
  76. package/lib/cms/functions.d.ts +7 -12
  77. package/lib/cms/functions.js +47 -50
  78. package/lib/cms/handleFieldsJS.js +16 -14
  79. package/lib/cms/modules.d.ts +5 -15
  80. package/lib/cms/modules.js +100 -39
  81. package/lib/cms/processFieldsJs.js +10 -33
  82. package/lib/cms/templates.d.ts +43 -3
  83. package/lib/cms/templates.js +51 -11
  84. package/lib/cms/uploadFolder.d.ts +3 -14
  85. package/lib/cms/uploadFolder.js +58 -42
  86. package/lib/{validate.d.ts → cms/validate.d.ts} +1 -1
  87. package/lib/{validate.js → cms/validate.js} +5 -5
  88. package/lib/cms/watch.d.ts +2 -18
  89. package/lib/cms/watch.js +63 -68
  90. package/lib/customObjects.js +4 -15
  91. package/lib/fileManager.d.ts +2 -0
  92. package/lib/fileManager.js +184 -0
  93. package/lib/fileMapper.d.ts +4 -15
  94. package/lib/fileMapper.js +68 -89
  95. package/lib/fs.js +2 -2
  96. package/lib/github.d.ts +6 -18
  97. package/lib/github.js +97 -76
  98. package/lib/gitignore.d.ts +2 -0
  99. package/lib/gitignore.js +21 -4
  100. package/lib/hubdb.d.ts +3 -2
  101. package/lib/hubdb.js +11 -9
  102. package/lib/{logging/logger.d.ts → logger.d.ts} +20 -8
  103. package/{utils → lib}/notify.js +2 -2
  104. package/lib/oauth.d.ts +2 -5
  105. package/lib/oauth.js +14 -25
  106. package/lib/path.d.ts +3 -0
  107. package/lib/path.js +46 -1
  108. package/lib/personalAccessKey.d.ts +7 -10
  109. package/lib/personalAccessKey.js +75 -48
  110. package/lib/portManager.d.ts +3 -5
  111. package/lib/portManager.js +18 -6
  112. package/lib/text.d.ts +1 -0
  113. package/lib/text.js +9 -1
  114. package/lib/trackUsage.js +18 -11
  115. package/lib/urls.js +5 -1
  116. package/models/FileSystemError.d.ts +6 -0
  117. package/models/FileSystemError.js +47 -0
  118. package/models/HubSpotHttpError.d.ts +24 -0
  119. package/models/HubSpotHttpError.js +197 -0
  120. package/models/OAuth2Manager.d.ts +5 -27
  121. package/models/OAuth2Manager.js +41 -64
  122. package/package.json +19 -18
  123. package/types/Accounts.d.ts +86 -3
  124. package/types/Apps.d.ts +77 -0
  125. package/types/Archive.d.ts +9 -0
  126. package/types/Archive.js +2 -0
  127. package/types/ComponentStructure.d.ts +30 -10
  128. package/types/Config.d.ts +19 -2
  129. package/types/DesignManager.d.ts +10 -0
  130. package/types/DesignManager.js +2 -0
  131. package/types/Error.d.ts +12 -34
  132. package/types/FieldsJS.d.ts +1 -0
  133. package/types/FieldsJS.js +2 -0
  134. package/types/FileManager.d.ts +12 -7
  135. package/types/Files.d.ts +43 -4
  136. package/types/Functions.d.ts +26 -0
  137. package/types/Github.d.ts +12 -0
  138. package/types/Http.d.ts +11 -12
  139. package/types/Hubdb.d.ts +9 -0
  140. package/types/Lang.d.ts +3 -0
  141. package/types/Migration.d.ts +28 -0
  142. package/types/Migration.js +10 -0
  143. package/types/Modules.d.ts +11 -0
  144. package/types/PortManager.d.ts +7 -0
  145. package/types/Project.d.ts +4 -0
  146. package/types/ProjectLog.d.ts +9 -0
  147. package/types/ProjectLog.js +2 -0
  148. package/types/Sandbox.d.ts +37 -47
  149. package/types/Schemas.d.ts +12 -0
  150. package/types/Secrets.d.ts +3 -0
  151. package/types/Secrets.js +2 -0
  152. package/types/developerTestAccounts.d.ts +12 -0
  153. package/types/developerTestAccounts.js +2 -0
  154. package/utils/PortManagerServer.d.ts +6 -7
  155. package/utils/PortManagerServer.js +24 -18
  156. package/utils/{getAccountIdentifier.d.ts → accounts.d.ts} +0 -6
  157. package/utils/{getAccountIdentifier.js → accounts.js} +1 -13
  158. package/utils/cms/fieldsJS.d.ts +1 -2
  159. package/utils/cms/modules.js +2 -2
  160. package/utils/detectPort.js +3 -3
  161. package/utils/git.d.ts +1 -7
  162. package/utils/git.js +2 -18
  163. package/utils/lang.d.ts +1 -5
  164. package/constants/github.d.ts +0 -4
  165. package/constants/github.js +0 -7
  166. package/errors/apiErrors.d.ts +0 -23
  167. package/errors/apiErrors.js +0 -197
  168. package/errors/fileSystemErrors.d.ts +0 -5
  169. package/errors/fileSystemErrors.js +0 -31
  170. package/errors/standardErrors.d.ts +0 -26
  171. package/errors/standardErrors.js +0 -64
  172. package/lang/lang/en.json +0 -383
  173. package/lib/logging/git.d.ts +0 -2
  174. package/lib/logging/git.js +0 -54
  175. package/lib/logging/logs.d.ts +0 -22
  176. package/lib/logging/logs.js +0 -86
  177. package/lib/logging/table.d.ts +0 -3
  178. package/lib/logging/table.js +0 -47
  179. package/lib/sandboxes.d.ts +0 -14
  180. package/lib/sandboxes.js +0 -71
  181. package/models/HubSpotAuthError.d.ts +0 -9
  182. package/models/HubSpotAuthError.js +0 -20
  183. package/types/LogCallbacks.d.ts +0 -6
  184. package/utils/logger.d.ts +0 -11
  185. package/utils/logger.js +0 -23
  186. package/utils/objectUtils.d.ts +0 -8
  187. package/utils/objectUtils.js +0 -33
  188. /package/{utils → lib}/escapeRegExp.d.ts +0 -0
  189. /package/{utils → lib}/escapeRegExp.js +0 -0
  190. /package/lib/{logging/logger.js → logger.js} +0 -0
  191. /package/{utils → lib}/notify.d.ts +0 -0
  192. /package/types/{LogCallbacks.js → Apps.js} +0 -0
package/lib/fileMapper.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ // FILE MAPPER - not to be confused with fileManager.ts
2
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
5
  };
@@ -8,13 +9,13 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const p_queue_1 = __importDefault(require("p-queue"));
10
11
  const path_2 = require("./path");
12
+ const logger_1 = require("./logger");
11
13
  const fileMapper_1 = require("../api/fileMapper");
12
- const standardErrors_1 = require("../errors/standardErrors");
13
14
  const extensions_1 = require("../constants/extensions");
14
15
  const files_1 = require("../constants/files");
15
- const fileSystemErrors_1 = require("../errors/fileSystemErrors");
16
- const apiErrors_1 = require("../errors/apiErrors");
17
- const logger_1 = require("../utils/logger");
16
+ const errors_1 = require("../errors");
17
+ const lang_1 = require("../utils/lang");
18
+ const FileSystemError_1 = require("../models/FileSystemError");
18
19
  const i18nKey = 'lib.fileMapper';
19
20
  const queue = new p_queue_1.default({
20
21
  concurrency: 10,
@@ -42,14 +43,14 @@ function isPathToHubspot(filepath) {
42
43
  return /^(\/|\\)?@hubspot/i.test(filepath.trim());
43
44
  }
44
45
  exports.isPathToHubspot = isPathToHubspot;
45
- function useApiBuffer(mode) {
46
- return mode === files_1.MODE.draft;
46
+ function useApiBuffer(cmsPublishMode) {
47
+ return cmsPublishMode === files_1.CMS_PUBLISH_MODE.draft;
47
48
  }
48
- // Determines API param based on mode an options
49
- function getFileMapperQueryValues(mode, { staging, assetVersion } = {}) {
49
+ // Determines API param based on publish mode and options
50
+ function getFileMapperQueryValues(cmsPublishMode, { staging, assetVersion } = {}) {
50
51
  return {
51
52
  params: {
52
- buffer: useApiBuffer(mode),
53
+ buffer: useApiBuffer(cmsPublishMode),
53
54
  environmentId: staging ? 2 : 1,
54
55
  version: assetVersion,
55
56
  },
@@ -75,9 +76,9 @@ function validateFileMapperNode(node) {
75
76
  catch (err) {
76
77
  json = node;
77
78
  }
78
- (0, standardErrors_1.throwTypeErrorWithMessage)(`${i18nKey}.errors.invalidNode`, {
79
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidNode`, {
79
80
  json: JSON.stringify(json),
80
- });
81
+ }));
81
82
  }
82
83
  function getTypeDataFromPath(src) {
83
84
  const isModule = isPathToModule(src);
@@ -123,10 +124,10 @@ async function writeUtimes(accountId, filepath, node) {
123
124
  await fs_extra_1.default.utimes(filepath, atime, mtime);
124
125
  }
125
126
  catch (err) {
126
- (0, fileSystemErrors_1.throwFileSystemError)(err, {
127
+ throw new FileSystemError_1.FileSystemError({ cause: err }, {
127
128
  filepath,
128
129
  accountId,
129
- write: true,
130
+ operation: 'write',
130
131
  });
131
132
  }
132
133
  }
@@ -140,45 +141,33 @@ async function skipExisting(filepath, overwrite = false) {
140
141
  }
141
142
  return false;
142
143
  }
143
- const filemapperCallbackKeys = ['skippedExisting', 'wroteFolder'];
144
- async function fetchAndWriteFileStream(accountId, srcPath, filepath, mode, options = {}, logCallbacks) {
145
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
144
+ async function fetchAndWriteFileStream(accountId, srcPath, filepath, cmsPublishMode, options = {}) {
146
145
  if (typeof srcPath !== 'string' || !srcPath.trim()) {
147
146
  return;
148
147
  }
149
148
  if (await skipExisting(filepath, options.overwrite)) {
150
- logger('skippedExisting', `${i18nKey}.skippedExisting`, { filepath });
149
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.skippedExisting`, { filepath }));
151
150
  return;
152
151
  }
153
- if (!(0, path_2.isAllowedExtension)(srcPath)) {
154
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.invalidFileType`, { srcPath });
155
- }
156
- let node;
157
- try {
158
- node = await (0, fileMapper_1.fetchFileStream)(accountId, srcPath, filepath, getFileMapperQueryValues(mode, options));
159
- }
160
- catch (err) {
161
- (0, apiErrors_1.throwStatusCodeError)(err, {
162
- accountId,
163
- request: srcPath,
164
- });
152
+ if (!(0, path_2.isAllowedExtension)(srcPath, Array.from(extensions_1.JSR_ALLOWED_EXTENSIONS))) {
153
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidFileType`, { srcPath }));
165
154
  }
155
+ const node = await (0, fileMapper_1.fetchFileStream)(accountId, srcPath, filepath, getFileMapperQueryValues(cmsPublishMode, options));
166
156
  await writeUtimes(accountId, filepath, node);
167
157
  }
168
158
  // Writes an individual file or folder (not recursive). If file source is missing, the
169
159
  //file is fetched.
170
- async function writeFileMapperNode(accountId, filepath, node, mode, options = {}, logCallbacks) {
171
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
160
+ async function writeFileMapperNode(accountId, filepath, node, cmsPublishMode, options = {}) {
172
161
  const localFilepath = (0, path_2.convertToLocalFileSystemPath)(path_1.default.resolve(filepath));
173
162
  if (await skipExisting(localFilepath, options.overwrite)) {
174
- logger('skippedExisting', `${i18nKey}.skippedExisting`, {
163
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.skippedExisting`, {
175
164
  filepath: localFilepath,
176
- });
165
+ }));
177
166
  return true;
178
167
  }
179
168
  if (!node.folder) {
180
169
  try {
181
- await fetchAndWriteFileStream(accountId, node.path, localFilepath, mode, options, logCallbacks);
170
+ await fetchAndWriteFileStream(accountId, node.path, localFilepath, cmsPublishMode, options);
182
171
  return true;
183
172
  }
184
173
  catch (err) {
@@ -187,30 +176,25 @@ async function writeFileMapperNode(accountId, filepath, node, mode, options = {}
187
176
  }
188
177
  try {
189
178
  await fs_extra_1.default.ensureDir(localFilepath);
190
- logger('wroteFolder', `${i18nKey}.wroteFolder`, {
179
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.wroteFolder`, {
191
180
  filepath: localFilepath,
192
- });
181
+ }));
193
182
  }
194
183
  catch (err) {
195
- (0, fileSystemErrors_1.throwFileSystemError)(err, {
184
+ throw new FileSystemError_1.FileSystemError({ cause: err }, {
196
185
  filepath: localFilepath,
197
186
  accountId,
198
- write: true,
187
+ operation: 'write',
199
188
  });
200
- return false;
201
189
  }
202
190
  return true;
203
191
  }
204
- function isTimeout(err) {
205
- return !!err && (err.status === 408 || err.code === 'ESOCKETTIMEDOUT');
206
- }
207
- async function downloadFile(accountId, src, destPath, mode, options = {}, logCallbacks) {
208
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
192
+ async function downloadFile(accountId, src, destPath, cmsPublishMode, options = {}) {
209
193
  const { isFile, isHubspot } = getTypeDataFromPath(src);
194
+ if (!isFile) {
195
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidRequest`, { src }));
196
+ }
210
197
  try {
211
- if (!isFile) {
212
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.invalidRequest`, { src });
213
- }
214
198
  const dest = path_1.default.resolve(destPath);
215
199
  const cwd = (0, path_2.getCwd)();
216
200
  let filepath;
@@ -230,59 +214,43 @@ async function downloadFile(accountId, src, destPath, mode, options = {}, logCal
230
214
  : path_1.default.resolve(cwd, dest, name);
231
215
  }
232
216
  const localFsPath = (0, path_2.convertToLocalFileSystemPath)(filepath);
233
- await fetchAndWriteFileStream(accountId, src, localFsPath, mode, options, logCallbacks);
217
+ await fetchAndWriteFileStream(accountId, src, localFsPath, cmsPublishMode, options);
234
218
  await queue.onIdle();
235
- logger('completedFetch', `${i18nKey}.completedFetch`, {
219
+ logger_1.logger.success((0, lang_1.i18n)(`${i18nKey}.completedFetch`, {
236
220
  src,
237
221
  version: getAssetVersionIdentifier(options.assetVersion, src),
238
222
  dest,
239
- });
223
+ }));
240
224
  }
241
225
  catch (err) {
242
226
  const error = err;
243
- if (isHubspot && isTimeout(err)) {
244
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.assetTimeout`, {}, error);
227
+ if (isHubspot && (0, errors_1.isTimeoutError)(error)) {
228
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.assetTimeout`), { cause: error });
245
229
  }
246
230
  else {
247
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.failedToFetchFile`, { src, dest: destPath }, error);
231
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.failedToFetchFile`, { src, dest: destPath }), { cause: error });
248
232
  }
249
233
  }
250
234
  }
251
- async function fetchFolderFromApi(accountId, src, mode, options = {}, logCallbacks) {
252
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
235
+ async function fetchFolderFromApi(accountId, src, cmsPublishMode, options = {}) {
253
236
  const { isRoot, isFolder, isHubspot } = getTypeDataFromPath(src);
254
237
  if (!isFolder) {
255
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.invalidFetchFolderRequest`, {
238
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.invalidFetchFolderRequest`, {
256
239
  src,
257
- });
258
- }
259
- try {
260
- const srcPath = isRoot ? '@root' : src;
261
- const queryValues = getFileMapperQueryValues(mode, options);
262
- const node = isHubspot
263
- ? await (0, fileMapper_1.downloadDefault)(accountId, srcPath, queryValues)
264
- : await (0, fileMapper_1.download)(accountId, srcPath, queryValues);
265
- logger('folderFetch', `${i18nKey}.folderFetch`, { src, accountId });
266
- return node;
267
- }
268
- catch (err) {
269
- const error = err;
270
- if (isHubspot && isTimeout(error)) {
271
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.assetTimeout`, {}, error);
272
- }
273
- else {
274
- (0, apiErrors_1.throwStatusCodeError)(error, {
275
- accountId,
276
- request: src,
277
- });
278
- }
240
+ }));
279
241
  }
242
+ const srcPath = isRoot ? '@root' : src;
243
+ const queryValues = getFileMapperQueryValues(cmsPublishMode, options);
244
+ const { data: node } = isHubspot
245
+ ? await (0, fileMapper_1.downloadDefault)(accountId, srcPath, queryValues)
246
+ : await (0, fileMapper_1.download)(accountId, srcPath, queryValues);
247
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.folderFetch`, { src, accountId }));
248
+ return node;
280
249
  }
281
250
  exports.fetchFolderFromApi = fetchFolderFromApi;
282
- async function downloadFolder(accountId, src, destPath, mode, options = {}, logCallbacks) {
283
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
251
+ async function downloadFolder(accountId, src, destPath, cmsPublishMode, options = {}) {
284
252
  try {
285
- const node = await fetchFolderFromApi(accountId, src, mode, options, logCallbacks);
253
+ const node = await fetchFolderFromApi(accountId, src, cmsPublishMode, options);
286
254
  if (!node) {
287
255
  return;
288
256
  }
@@ -293,27 +261,38 @@ async function downloadFolder(accountId, src, destPath, mode, options = {}, logC
293
261
  let success = true;
294
262
  recurseFolder(node, (childNode, filepath) => {
295
263
  queue.add(async () => {
296
- const succeeded = await writeFileMapperNode(accountId, filepath || '', childNode, mode, options, logCallbacks);
264
+ const succeeded = await writeFileMapperNode(accountId, filepath || '', childNode, cmsPublishMode, options);
297
265
  if (succeeded === false) {
298
266
  success = false;
267
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.errors.failedToFetchFile`, {
268
+ src: childNode.path,
269
+ dest: filepath || '',
270
+ }));
299
271
  }
300
272
  });
301
273
  return success;
302
274
  }, rootPath);
303
275
  await queue.onIdle();
304
276
  if (success) {
305
- logger('completedFolderFetch', `${i18nKey}.completedFolderFetch`, {
277
+ logger_1.logger.success((0, lang_1.i18n)(`${i18nKey}.completedFolderFetch`, {
306
278
  src,
307
279
  version: getAssetVersionIdentifier(options.assetVersion, src),
308
280
  dest,
309
- });
281
+ }));
310
282
  }
311
283
  else {
312
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.incompleteFetch`, { src });
284
+ // TODO: Fix this exception. It is triggering the catch block so this error is being rewritten
285
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.incompleteFetch`, { src }));
313
286
  }
314
287
  }
315
288
  catch (err) {
316
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.failedToFetchFolder`, { src, dest: destPath }, err);
289
+ const error = err;
290
+ if ((0, errors_1.isTimeoutError)(error)) {
291
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.assetTimeout`), { cause: error });
292
+ }
293
+ else {
294
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.failedToFetchFolder`, { src, dest: destPath }), { cause: err });
295
+ }
317
296
  }
318
297
  }
319
298
  /**
@@ -323,16 +302,16 @@ async function downloadFolder(accountId, src, destPath, mode, options = {}, logC
323
302
  * @param {FileMapperInputArguments} input
324
303
  * @returns {Promise}
325
304
  */
326
- async function downloadFileOrFolder(accountId, src, dest, mode, options = {}, logCallbacks) {
305
+ async function downloadFileOrFolder(accountId, src, dest, cmsPublishMode, options = {}) {
327
306
  if (!src) {
328
307
  return;
329
308
  }
330
309
  const { isFile } = getTypeDataFromPath(src);
331
310
  if (isFile) {
332
- await downloadFile(accountId, src, dest, mode, options, logCallbacks);
311
+ await downloadFile(accountId, src, dest, cmsPublishMode, options);
333
312
  }
334
313
  else {
335
- await downloadFolder(accountId, src, dest, mode, options, logCallbacks);
314
+ await downloadFolder(accountId, src, dest, cmsPublishMode, options);
336
315
  }
337
316
  }
338
317
  exports.downloadFileOrFolder = downloadFileOrFolder;
package/lib/fs.js CHANGED
@@ -7,7 +7,7 @@ exports.walk = exports.flattenAndRemoveSymlinks = exports.getFileInfoAsync = voi
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const files_1 = require("../constants/files");
10
- const standardErrors_1 = require("../errors/standardErrors");
10
+ const FileSystemError_1 = require("../models/FileSystemError");
11
11
  function getFileInfoAsync(dir, file) {
12
12
  return new Promise((resolve, reject) => {
13
13
  const filepath = path_1.default.join(dir, file);
@@ -65,7 +65,7 @@ async function walk(dir) {
65
65
  .then(processFiles)
66
66
  .then(flattenAndRemoveSymlinks)
67
67
  .catch(err => {
68
- (0, standardErrors_1.throwError)(err);
68
+ throw new FileSystemError_1.FileSystemError({ cause: err });
69
69
  });
70
70
  }
71
71
  exports.walk = walk;
package/lib/github.d.ts CHANGED
@@ -1,20 +1,8 @@
1
- import { GITHUB_RELEASE_TYPES } from '../constants/github';
2
- import { GithubReleaseData } from '../types/Github';
3
- import { ValueOf } from '../types/Utils';
4
- import { LogCallbacksArg } from '../types/LogCallbacks';
5
- declare global {
6
- var githubToken: string;
7
- }
8
- type RepoPath = `${string}/${string}`;
9
- export declare function fetchJsonFromRepository(repoPath: RepoPath, filePath: string, ref: string): Promise<JSON>;
1
+ /// <reference types="node" />
2
+ import { GithubReleaseData, GithubRepoFile, RepoPath, CloneGithubRepoOptions } from '../types/Github';
3
+ export declare function fetchFileFromRepository(repoPath: RepoPath, filePath: string, ref: string): Promise<Buffer>;
10
4
  export declare function fetchReleaseData(repoPath: RepoPath, tag?: string): Promise<GithubReleaseData>;
11
- type CloneGithubRepoOptions = {
12
- themeVersion?: string;
13
- projectVersion?: string;
14
- releaseType?: ValueOf<typeof GITHUB_RELEASE_TYPES>;
15
- ref?: string;
16
- };
17
- declare const cloneGithubRepoCallbackKeys: string[];
18
- export declare function cloneGithubRepo(dest: string, type: string, repoPath: RepoPath, sourceDir: string, options?: CloneGithubRepoOptions, logCallbacks?: LogCallbacksArg<typeof cloneGithubRepoCallbackKeys>): Promise<boolean>;
5
+ export declare function cloneGithubRepo(repoPath: RepoPath, dest: string, options?: CloneGithubRepoOptions): Promise<boolean>;
6
+ export declare function fetchGitHubRepoContentFromDownloadUrl(dest: string, downloadUrl: string): Promise<void>;
19
7
  export declare function downloadGithubRepoContents(repoPath: RepoPath, contentPath: string, dest: string, ref?: string, filter?: (contentPiecePath: string, downloadPath: string) => boolean): Promise<void>;
20
- export {};
8
+ export declare function listGithubRepoContents(repoPath: RepoPath, contentPath: string, fileFilter?: 'file' | 'dir'): Promise<GithubRepoFile[]>;
package/lib/github.js CHANGED
@@ -3,123 +3,128 @@ 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.downloadGithubRepoContents = exports.cloneGithubRepo = exports.fetchReleaseData = exports.fetchJsonFromRepository = void 0;
7
- const axios_1 = __importDefault(require("axios"));
6
+ exports.listGithubRepoContents = exports.downloadGithubRepoContents = exports.fetchGitHubRepoContentFromDownloadUrl = exports.cloneGithubRepo = exports.fetchReleaseData = exports.fetchFileFromRepository = void 0;
8
7
  const path_1 = __importDefault(require("path"));
9
8
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
- const logger_1 = require("../utils/logger");
11
- const standardErrors_1 = require("../errors/standardErrors");
12
9
  const archive_1 = require("./archive");
13
- const github_1 = require("../constants/github");
14
- const getAxiosConfig_1 = require("../http/getAxiosConfig");
10
+ const logger_1 = require("./logger");
11
+ const github_1 = require("../api/github");
12
+ const lang_1 = require("../utils/lang");
13
+ const errors_1 = require("../errors");
15
14
  const i18nKey = 'lib.github';
16
- const GITHUB_AUTH_HEADERS = {
17
- authorization: global && global.githubToken ? `Bearer ${global.githubToken}` : null,
18
- };
19
- async function fetchJsonFromRepository(repoPath, filePath, ref) {
15
+ async function fetchFileFromRepository(repoPath, filePath, ref) {
20
16
  try {
21
- const URL = `https://raw.githubusercontent.com/${repoPath}/${ref}/${filePath}`;
22
- (0, logger_1.debug)(`${i18nKey}.fetchJsonFromRepository.fetching`, { url: URL });
23
- const { data } = await axios_1.default.get(URL, {
24
- headers: { ...getAxiosConfig_1.DEFAULT_USER_AGENT_HEADERS, ...GITHUB_AUTH_HEADERS },
25
- });
17
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.fetchFileFromRepository.fetching`, {
18
+ path: `${repoPath}/${ref}/${filePath}`,
19
+ }));
20
+ const { data } = await (0, github_1.fetchRepoFile)(repoPath, filePath, ref);
26
21
  return data;
27
22
  }
28
23
  catch (err) {
29
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.fetchJsonFromRepository.errors.fetchFail`, {}, err);
24
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.fetchFileFromRepository.errors.fetchFail`), {
25
+ cause: err,
26
+ });
30
27
  }
31
28
  }
32
- exports.fetchJsonFromRepository = fetchJsonFromRepository;
33
- async function fetchReleaseData(repoPath, tag = '') {
34
- tag = tag.trim().toLowerCase();
35
- if (tag.length && tag[0] !== 'v') {
36
- tag = `v${tag}`;
29
+ exports.fetchFileFromRepository = fetchFileFromRepository;
30
+ // Fetches information about a specific release (Defaults to latest)
31
+ async function fetchReleaseData(repoPath, tag) {
32
+ if (tag) {
33
+ tag = tag.trim().toLowerCase();
34
+ if (tag.length && tag[0] !== 'v') {
35
+ tag = `v${tag}`;
36
+ }
37
37
  }
38
- const URI = tag
39
- ? `https://api.github.com/repos/${repoPath}/releases/tags/${tag}`
40
- : `https://api.github.com/repos/${repoPath}/releases/latest`;
41
38
  try {
42
- const { data } = await axios_1.default.get(URI, {
43
- headers: { ...getAxiosConfig_1.DEFAULT_USER_AGENT_HEADERS, ...GITHUB_AUTH_HEADERS },
44
- });
39
+ const { data } = await (0, github_1.fetchRepoReleaseData)(repoPath, tag);
45
40
  return data;
46
41
  }
47
42
  catch (err) {
48
- const error = err;
49
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.fetchReleaseData.errors.fetchFail`, { tag: tag || 'latest' }, error);
43
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.fetchReleaseData.errors.fetchFail`, {
44
+ tag: tag || 'latest',
45
+ }), { cause: err });
50
46
  }
51
47
  }
52
48
  exports.fetchReleaseData = fetchReleaseData;
53
- async function downloadGithubRepoZip(repoPath, tag = '', releaseType = github_1.GITHUB_RELEASE_TYPES.RELEASE, ref) {
49
+ async function downloadGithubRepoZip(repoPath, isRelease = false, options = {}) {
50
+ const { branch, tag } = options;
54
51
  try {
55
52
  let zipUrl;
56
- if (releaseType === github_1.GITHUB_RELEASE_TYPES.REPOSITORY) {
57
- (0, logger_1.debug)(`${i18nKey}.downloadGithubRepoZip.fetching`, {
58
- releaseType,
59
- repoPath,
60
- });
61
- zipUrl = `https://api.github.com/repos/${repoPath}/zipball${ref ? `/${ref}` : ''}`;
62
- }
63
- else {
53
+ if (isRelease) {
54
+ // If downloading a release, first get the release info using fetchReleaseData().
55
+ // Supports a custom tag, but will default to the latest release
64
56
  const releaseData = await fetchReleaseData(repoPath, tag);
65
57
  zipUrl = releaseData.zipball_url;
66
58
  const { name } = releaseData;
67
- (0, logger_1.debug)(`${i18nKey}.downloadGithubRepoZip.fetchingName`, { name });
59
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoZip.fetchingName`, { name }));
68
60
  }
69
- const { data } = await axios_1.default.get(zipUrl, {
70
- headers: { ...getAxiosConfig_1.DEFAULT_USER_AGENT_HEADERS, ...GITHUB_AUTH_HEADERS },
71
- });
72
- (0, logger_1.debug)(`${i18nKey}.downloadGithubRepoZip.completed`);
61
+ else {
62
+ // If downloading a repository, manually construct the zip url. This url supports both branches and tags as refs
63
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoZip.fetching`, { repoPath }));
64
+ const ref = branch || tag;
65
+ zipUrl = `https://api.github.com/repos/${repoPath}/zipball${ref ? `/${ref}` : ''}`;
66
+ }
67
+ const { data } = await (0, github_1.fetchRepoAsZip)(zipUrl);
68
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoZip.completed`));
73
69
  return data;
74
70
  }
75
71
  catch (err) {
76
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.downloadGithubRepoZip.errors.fetchFail`, {}, err);
72
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoZip.errors.fetchFail`), {
73
+ cause: err,
74
+ });
77
75
  }
78
76
  }
79
- const cloneGithubRepoCallbackKeys = ['success'];
80
- async function cloneGithubRepo(dest, type, repoPath, sourceDir, options = {}, logCallbacks) {
81
- const logger = (0, logger_1.makeTypedLogger)(logCallbacks);
82
- const { themeVersion, projectVersion, releaseType, ref } = options;
83
- const tag = projectVersion || themeVersion;
84
- const zip = await downloadGithubRepoZip(repoPath, tag, releaseType, ref);
77
+ async function cloneGithubRepo(repoPath, dest, options = {}) {
78
+ const { tag, isRelease, branch, sourceDir, type } = options;
79
+ const zip = await downloadGithubRepoZip(repoPath, isRelease, {
80
+ tag,
81
+ branch,
82
+ });
85
83
  const repoName = repoPath.split('/')[1];
86
84
  const success = await (0, archive_1.extractZipArchive)(zip, repoName, dest, { sourceDir });
87
85
  if (success) {
88
- logger('success', `${i18nKey}.cloneGithubRepo.success`, { type, dest });
86
+ logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.cloneGithubRepo.success`, {
87
+ type: type || '',
88
+ dest,
89
+ }));
89
90
  }
90
91
  return success;
91
92
  }
92
93
  exports.cloneGithubRepo = cloneGithubRepo;
93
- async function getGitHubRepoContentsAtPath(repoPath, path, ref) {
94
- const refQuery = ref ? `?ref=${ref}` : '';
95
- const contentsRequestUrl = `https://api.github.com/repos/${repoPath}/contents/${path}${refQuery}`;
96
- const response = await axios_1.default.get(contentsRequestUrl, {
97
- headers: { ...getAxiosConfig_1.DEFAULT_USER_AGENT_HEADERS, ...GITHUB_AUTH_HEADERS },
98
- });
99
- return response.data;
100
- }
101
94
  async function fetchGitHubRepoContentFromDownloadUrl(dest, downloadUrl) {
102
- const resp = await axios_1.default.get(downloadUrl, {
103
- headers: { ...getAxiosConfig_1.DEFAULT_USER_AGENT_HEADERS, ...GITHUB_AUTH_HEADERS },
104
- });
105
- fs_extra_1.default.writeFileSync(dest, resp.data, 'utf8');
95
+ const resp = await (0, github_1.fetchRepoFileByDownloadUrl)(downloadUrl);
96
+ const contentType = resp.headers['content-type'];
97
+ let fileContents;
98
+ if (contentType.startsWith('text')) {
99
+ fileContents = Buffer.from(resp.data).toString('utf8');
100
+ }
101
+ else {
102
+ fileContents = resp.data;
103
+ }
104
+ fs_extra_1.default.outputFileSync(dest, fileContents);
106
105
  }
106
+ exports.fetchGitHubRepoContentFromDownloadUrl = fetchGitHubRepoContentFromDownloadUrl;
107
107
  // Writes files from a public repository to the destination folder
108
108
  async function downloadGithubRepoContents(repoPath, contentPath, dest, ref, filter) {
109
109
  fs_extra_1.default.ensureDirSync(path_1.default.dirname(dest));
110
110
  try {
111
- const contentsResp = await getGitHubRepoContentsAtPath(repoPath, contentPath, ref);
111
+ const { data: contentsResp } = await (0, github_1.fetchRepoContents)(repoPath, contentPath, ref);
112
112
  const downloadContent = async (contentPiece) => {
113
- const { path: contentPiecePath, download_url } = contentPiece;
113
+ const { path: contentPiecePath, download_url, type: contentPieceType, } = contentPiece;
114
114
  const downloadPath = path_1.default.join(dest, contentPiecePath.replace(contentPath, ''));
115
115
  if (filter && !filter(contentPiecePath, downloadPath)) {
116
116
  return Promise.resolve();
117
117
  }
118
- (0, logger_1.debug)(`${i18nKey}.downloadGithubRepoContents.downloading`, {
118
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoContents.downloading`, {
119
119
  contentPiecePath,
120
120
  downloadUrl: download_url,
121
121
  downloadPath,
122
- });
122
+ }));
123
+ if (contentPieceType === 'dir') {
124
+ const { data: innerDirContent } = await (0, github_1.fetchRepoContents)(repoPath, contentPiecePath, ref);
125
+ await Promise.all(innerDirContent.map(downloadContent));
126
+ return Promise.resolve();
127
+ }
123
128
  return fetchGitHubRepoContentFromDownloadUrl(downloadPath, download_url);
124
129
  };
125
130
  let contentPromises;
@@ -129,18 +134,34 @@ async function downloadGithubRepoContents(repoPath, contentPath, dest, ref, filt
129
134
  else {
130
135
  contentPromises = [downloadContent(contentsResp)];
131
136
  }
132
- Promise.all(contentPromises);
137
+ await Promise.all(contentPromises);
133
138
  }
134
139
  catch (e) {
135
- const error = e;
136
- if (error?.error?.message) {
137
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.downloadGithubRepoContents.errors.fetchFail`, {
138
- errorMessage: error.error.message,
139
- }, error);
140
- }
141
- else {
142
- (0, standardErrors_1.throwError)(error);
140
+ if ((0, errors_1.isSystemError)(e) && e?.error?.message) {
141
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoContents.errors.fetchFail`, {
142
+ errorMessage: e.error.message,
143
+ }), { cause: e });
143
144
  }
145
+ throw e;
144
146
  }
145
147
  }
146
148
  exports.downloadGithubRepoContents = downloadGithubRepoContents;
149
+ // Lists content from a public repository at the specified path
150
+ async function listGithubRepoContents(repoPath, contentPath, fileFilter) {
151
+ try {
152
+ const { data: contentsResp } = await (0, github_1.fetchRepoContents)(repoPath, contentPath);
153
+ const filteredFiles = fileFilter && fileFilter != undefined
154
+ ? contentsResp.filter(item => item.type === fileFilter)
155
+ : contentsResp;
156
+ return filteredFiles;
157
+ }
158
+ catch (e) {
159
+ if ((0, errors_1.isHubSpotHttpError)(e) && e.data.message) {
160
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.downloadGithubRepoContents.errors.fetchFail`, {
161
+ errorMessage: e.data.message,
162
+ }));
163
+ }
164
+ throw e;
165
+ }
166
+ }
167
+ exports.listGithubRepoContents = listGithubRepoContents;
@@ -1 +1,3 @@
1
+ import { GitInclusionResult } from '../types/Config';
1
2
  export declare function checkAndAddConfigToGitignore(configPath: string): void;
3
+ export declare function checkGitInclusion(configPath: string): GitInclusionResult;
package/lib/gitignore.js CHANGED
@@ -3,17 +3,17 @@ 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.checkAndAddConfigToGitignore = void 0;
6
+ exports.checkGitInclusion = exports.checkAndAddConfigToGitignore = void 0;
7
7
  const fs_extra_1 = require("fs-extra");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const git_1 = require("../utils/git");
10
10
  const config_1 = require("../constants/config");
11
- const standardErrors_1 = require("../errors/standardErrors");
11
+ const lang_1 = require("../utils/lang");
12
12
  const i18nKey = 'lib.gitignore';
13
13
  const GITIGNORE_FILE = '.gitignore';
14
14
  function checkAndAddConfigToGitignore(configPath) {
15
15
  try {
16
- const { configIgnored, gitignoreFiles } = (0, git_1.checkGitInclusion)(configPath);
16
+ const { configIgnored, gitignoreFiles } = checkGitInclusion(configPath);
17
17
  if (configIgnored)
18
18
  return;
19
19
  let gitignoreFilePath = gitignoreFiles && gitignoreFiles.length ? gitignoreFiles[0] : null;
@@ -26,7 +26,24 @@ function checkAndAddConfigToGitignore(configPath) {
26
26
  (0, fs_extra_1.writeFileSync)(gitignoreFilePath, updatedContents);
27
27
  }
28
28
  catch (e) {
29
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.configIgnore`, {}, e);
29
+ throw new Error((0, lang_1.i18n)(`${i18nKey}.errors.configIgnore`), { cause: e });
30
30
  }
31
31
  }
32
32
  exports.checkAndAddConfigToGitignore = checkAndAddConfigToGitignore;
33
+ function checkGitInclusion(configPath) {
34
+ const result = {
35
+ inGit: false,
36
+ configIgnored: false,
37
+ gitignoreFiles: [],
38
+ };
39
+ if ((0, git_1.isConfigPathInGitRepo)(configPath)) {
40
+ result.inGit = true;
41
+ result.gitignoreFiles = (0, git_1.getGitignoreFiles)(configPath);
42
+ if ((0, git_1.configFilenameIsIgnoredByGitignore)(result.gitignoreFiles, configPath)) {
43
+ // Found ignore statement in .gitignore that matches config filename
44
+ result.configIgnored = true;
45
+ }
46
+ }
47
+ return result;
48
+ }
49
+ exports.checkGitInclusion = checkGitInclusion;