@hubspot/local-dev-lib 0.3.4 → 0.3.5

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/lang/en.json CHANGED
@@ -83,9 +83,7 @@
83
83
  "creatingPath": "Creating {{ path }}",
84
84
  "errors": {
85
85
  "pathExists": "The {{ path }} path already exists",
86
- "failedToWriteMeta": "There was an problem writing the module's meta data at {{ path }}",
87
- "fileReadFailure": "Failed to read file at {{ path }}",
88
- "failedToWrite": "failed to write to file at {{ path }}"
86
+ "fileUpdateFailure": "There was a problem updating the modules files at {{ path }}: {{ errorMessage }}"
89
87
  }
90
88
  },
91
89
  "retrieveDefaultModule": {
package/lang/lang/en.json CHANGED
@@ -83,9 +83,7 @@
83
83
  "creatingPath": "Creating {{ path }}",
84
84
  "errors": {
85
85
  "pathExists": "The {{ path }} path already exists",
86
- "failedToWriteMeta": "There was an problem writing the module's meta data at {{ path }}",
87
- "fileReadFailure": "Failed to read file at {{ path }}",
88
- "failedToWrite": "failed to write to file at {{ path }}"
86
+ "fileUpdateFailure": "There was a problem updating the modules files at {{ path }}: {{ errorMessage }}"
89
87
  }
90
88
  },
91
89
  "retrieveDefaultModule": {
@@ -8,7 +8,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const os_1 = __importDefault(require("os"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const child_process_1 = require("child_process");
11
- const escapeRegExp_1 = require("../../utils/escapeRegExp");
11
+ const escapeRegExp_1 = require("../escapeRegExp");
12
12
  const modules_1 = require("../../utils/cms/modules");
13
13
  const logger_1 = require("../logging/logger");
14
14
  const standardErrors_1 = require("../../errors/standardErrors");
@@ -84,40 +84,43 @@ const MODULE_STRING_TRANSFORMATIONS = [
84
84
  fallback: '',
85
85
  },
86
86
  ];
87
- const transformFileContents = (file, metaData, getInternalVersion) => {
88
- fs_extra_1.default.readFile(file, 'utf8', (err, data) => {
89
- if (err) {
90
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.createModule.errors.fileReadFailure`, {
91
- path: file,
92
- });
93
- }
94
- let results = data;
87
+ const updateFileContents = async (file, metaData, getInternalVersion) => {
88
+ try {
89
+ let fileContents = await fs_extra_1.default.readFile(file, 'utf8'); // returns Promise
95
90
  MODULE_STRING_TRANSFORMATIONS.forEach(entry => {
96
91
  const replacementString = getInternalVersion
97
92
  ? entry.string
98
93
  : entry.fallback;
99
- results = results.replace(entry.regex, replacementString);
100
- });
101
- fs_extra_1.default.writeFile(file, results, 'utf8', err => {
102
- if (err) {
103
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.createModule.errors.failedToWrite`, {
104
- path: file,
105
- });
106
- }
94
+ fileContents = fileContents.replace(entry.regex, replacementString);
107
95
  });
108
- fs_extra_1.default.appendFile(file, 'export const meta = ' + JSON.stringify(metaData, null, ' '), err => {
109
- if (err) {
110
- (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.createModule.errors.failedToWrite`, {
111
- path: file,
112
- });
113
- }
96
+ await fs_extra_1.default.writeFile(file, fileContents, 'utf8');
97
+ await fs_extra_1.default.appendFile(file, 'export const meta = ' + JSON.stringify(metaData, null, ' '));
98
+ }
99
+ catch (error) {
100
+ const { message } = error;
101
+ (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.createModule.errors.fileUpdateFailure`, {
102
+ path: file,
103
+ errorMessage: message,
114
104
  });
115
- });
105
+ }
116
106
  };
117
107
  async function createModule(moduleDefinition, name, dest, getInternalVersion, options = {
118
108
  allowExistingDir: false,
119
109
  }) {
120
- const { reactType: isReactModule } = moduleDefinition;
110
+ const { moduleLabel, contentTypes, global, reactType: isReactModule, } = moduleDefinition;
111
+ const moduleMetaData = {
112
+ label: moduleLabel,
113
+ css_assets: [],
114
+ external_js: [],
115
+ global: global,
116
+ help_text: '',
117
+ host_template_types: contentTypes,
118
+ js_assets: [],
119
+ other_assets: [],
120
+ smart_type: 'NOT_SMART',
121
+ tags: [],
122
+ is_available_for_new_content: false,
123
+ };
121
124
  const folderName = name.endsWith('.module') ? name : `${name}.module`;
122
125
  const destPath = !isReactModule
123
126
  ? path_1.default.join(dest, folderName)
@@ -136,34 +139,12 @@ async function createModule(moduleDefinition, name, dest, getInternalVersion, op
136
139
  logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.createModule.creatingModule`, {
137
140
  path: destPath,
138
141
  }));
139
- // Write module meta
140
- const writeModuleMeta = ({ moduleLabel, contentTypes, global, reactType }, dest) => {
141
- const metaData = {
142
- label: moduleLabel,
143
- css_assets: [],
144
- external_js: [],
145
- global: global,
146
- help_text: '',
147
- host_template_types: contentTypes,
148
- js_assets: [],
149
- other_assets: [],
150
- smart_type: 'NOT_SMART',
151
- tags: [],
152
- is_available_for_new_content: false,
153
- };
154
- if (!reactType) {
155
- fs_extra_1.default.writeJSONSync(dest, metaData, { spaces: 2 });
156
- }
157
- else {
158
- transformFileContents(`${dest}/index.tsx`, metaData, getInternalVersion);
159
- }
160
- };
161
- // Filter out ceratin fetched files from the response
142
+ // Filter out certain fetched files from the response
162
143
  const moduleFileFilter = (src, dest) => {
163
144
  const emailEnabled = moduleDefinition.contentTypes.includes('EMAIL');
164
145
  switch (path_1.default.basename(src)) {
165
146
  case 'meta.json':
166
- writeModuleMeta(moduleDefinition, dest);
147
+ fs_extra_1.default.writeJSONSync(dest, moduleMetaData, { spaces: 2 }); // writing a meta.json file to standard HubL modules
167
148
  return false;
168
149
  case 'module.js':
169
150
  case 'module.css':
@@ -187,17 +168,17 @@ async function createModule(moduleDefinition, name, dest, getInternalVersion, op
187
168
  ? 'Sample.module'
188
169
  : 'SampleReactModule';
189
170
  await (0, github_1.downloadGithubRepoContents)('HubSpot/cms-sample-assets', `modules/${sampleAssetPath}`, destPath, '', moduleFileFilter);
190
- // Mutating React module files after fetch
171
+ // Updating React module files after fetch
191
172
  if (isReactModule) {
192
- writeModuleMeta(moduleDefinition, destPath);
173
+ await updateFileContents(`${destPath}/index.tsx`, moduleMetaData, getInternalVersion);
193
174
  }
194
175
  }
195
176
  exports.createModule = createModule;
196
177
  async function retrieveDefaultModule(name, dest) {
197
178
  if (!name) {
198
- const defaultReactModules = await (0, github_1.listGithubRepoContents)('HubSpot/cms-sample-assets', 'modules/', 'dir');
179
+ const defaultReactModules = await (0, github_1.listGithubRepoContents)('HubSpot/cms-react', 'default-react-modules/src/components/modules/', 'dir');
199
180
  return defaultReactModules;
200
181
  }
201
- await (0, github_1.downloadGithubRepoContents)('HubSpot/cms-sample-assets', `modules/${name}`, dest);
182
+ await (0, github_1.downloadGithubRepoContents)('HubSpot/cms-react', `default-react-modules/src/components/modules/${name}`, dest);
202
183
  }
203
184
  exports.retrieveDefaultModule = retrieveDefaultModule;
@@ -1,3 +1,4 @@
1
+ import { AxiosError } from 'axios';
1
2
  import { FieldsJs } from './handleFieldsJS';
2
3
  import { FileMapperInputOptions } from '../../types/Files';
3
4
  import { UploadFolderResults } from '../../types/Files';
@@ -6,6 +7,11 @@ type CommandOptions = {
6
7
  convertFields?: boolean;
7
8
  fieldOptions?: string;
8
9
  saveOutput?: boolean;
10
+ onAttemptCallback?: (file: string | undefined, destPath: string) => void;
11
+ onSuccessCallback?: (file: string | undefined, destPath: string) => void;
12
+ onFirstErrorCallback?: (file: string, destPath: string, error: AxiosError) => void;
13
+ onRetryCallback?: (file: string, destPath: string) => void;
14
+ onFinalErrorCallback?: (accountId: number, file: string, destPath: string, error: AxiosError) => void;
9
15
  };
10
16
  type FilePathsByType = {
11
17
  [key: string]: Array<string>;
@@ -10,7 +10,7 @@ const handleFieldsJS_1 = require("./handleFieldsJS");
10
10
  const fileMapper_1 = require("../fileMapper");
11
11
  const fileMapper_2 = require("../../api/fileMapper");
12
12
  const modules_1 = require("../../utils/cms/modules");
13
- const escapeRegExp_1 = require("../../utils/escapeRegExp");
13
+ const escapeRegExp_1 = require("../escapeRegExp");
14
14
  const path_2 = require("../path");
15
15
  const standardErrors_1 = require("../../errors/standardErrors");
16
16
  const apiErrors_1 = require("../../errors/apiErrors");
@@ -76,8 +76,39 @@ async function getFilesByType(filePaths, projectDir, rootWriteDir, commandOption
76
76
  return [filePathsByType, fieldsJsObjects];
77
77
  }
78
78
  exports.getFilesByType = getFilesByType;
79
+ const defaultUploadAttemptCallback = (file, destPath) => logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.attempt`, {
80
+ file: file || '',
81
+ destPath,
82
+ }));
83
+ const defaultUploadSuccessCallback = (file, destPath) => logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.uploadFolder.success`, {
84
+ file: file || '',
85
+ destPath,
86
+ }));
87
+ const defaultUploadFirstErrorCallback = (file, destPath, error) => {
88
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.failed`, { file, destPath }));
89
+ if (error.response && error.response.data) {
90
+ logger_1.logger.debug(error.response.data);
91
+ }
92
+ else {
93
+ logger_1.logger.debug(error.message);
94
+ }
95
+ };
96
+ const defaultUploadRetryCallback = (file, destPath) => logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.retry`, { file, destPath }));
97
+ const defaultUploadFinalErrorCallback = (accountId, file, destPath, error) => {
98
+ logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.retryFailed`, { file, destPath }));
99
+ (0, apiErrors_1.throwApiUploadError)(error, {
100
+ accountId,
101
+ request: destPath,
102
+ payload: file,
103
+ });
104
+ };
79
105
  async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOptions = {}, filePaths = [], mode = null) {
80
- const { saveOutput, convertFields } = commandOptions;
106
+ const { saveOutput, convertFields, onAttemptCallback, onSuccessCallback, onFirstErrorCallback, onRetryCallback, onFinalErrorCallback } = commandOptions;
107
+ const _onAttemptCallback = onAttemptCallback || defaultUploadAttemptCallback;
108
+ const _onSuccessCallback = onSuccessCallback || defaultUploadSuccessCallback;
109
+ const _onFirstErrorCallback = onFirstErrorCallback || defaultUploadFirstErrorCallback;
110
+ const _onRetryCallback = onRetryCallback || defaultUploadRetryCallback;
111
+ const _onFinalErrorCallback = onFinalErrorCallback || defaultUploadFinalErrorCallback;
81
112
  const tmpDir = convertFields
82
113
  ? (0, handleFieldsJS_1.createTmpDirSync)('hubspot-temp-fieldsjs-output-')
83
114
  : null;
@@ -103,29 +134,17 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
103
134
  const relativePath = file.replace(fieldsJsFileInfo ? tmpDirRegex : regex, '');
104
135
  const destPath = (0, path_2.convertToUnixPath)(path_1.default.join(dest, relativePath));
105
136
  return async () => {
106
- logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.attempt`, {
107
- file: originalFilePath || '',
108
- destPath,
109
- }));
137
+ _onAttemptCallback(originalFilePath, destPath);
110
138
  try {
111
139
  await (0, fileMapper_2.upload)(accountId, file, destPath, apiOptions);
112
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.uploadFolder.success`, {
113
- file: originalFilePath || '',
114
- destPath,
115
- }));
140
+ _onSuccessCallback(originalFilePath, destPath);
116
141
  }
117
142
  catch (err) {
118
143
  const error = err;
119
144
  if ((0, standardErrors_1.isFatalError)(error)) {
120
145
  throw error;
121
146
  }
122
- logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.failed`, { file, destPath }));
123
- if (error.response && error.response.data) {
124
- logger_1.logger.debug(error.response.data);
125
- }
126
- else {
127
- logger_1.logger.debug(error.message);
128
- }
147
+ _onFirstErrorCallback(file, destPath, error);
129
148
  failures.push({
130
149
  file,
131
150
  destPath,
@@ -140,13 +159,10 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
140
159
  const results = await queue
141
160
  .addAll(failures.map(({ file, destPath }) => {
142
161
  return async () => {
143
- logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.retry`, { file, destPath }));
162
+ _onRetryCallback(file, destPath);
144
163
  try {
145
164
  await (0, fileMapper_2.upload)(accountId, file, destPath, apiOptions);
146
- logger_1.logger.log((0, lang_1.i18n)(`${i18nKey}.uploadFolder.success`, {
147
- file,
148
- destPath,
149
- }));
165
+ _onSuccessCallback(file, destPath);
150
166
  return {
151
167
  resultType: files_1.FILE_UPLOAD_RESULT_TYPES.SUCCESS,
152
168
  error: null,
@@ -154,16 +170,16 @@ async function uploadFolder(accountId, src, dest, fileMapperOptions, commandOpti
154
170
  };
155
171
  }
156
172
  catch (err) {
157
- logger_1.logger.debug((0, lang_1.i18n)(`${i18nKey}.uploadFolder.retryFailed`, { file, destPath }));
158
173
  const error = err;
159
174
  if ((0, standardErrors_1.isFatalError)(error)) {
160
175
  throw error;
161
176
  }
162
- (0, apiErrors_1.throwApiUploadError)(error, {
163
- accountId,
164
- request: destPath,
165
- payload: file,
166
- });
177
+ _onFinalErrorCallback(accountId, file, destPath, error);
178
+ return {
179
+ resultType: files_1.FILE_UPLOAD_RESULT_TYPES.FAILURE,
180
+ error,
181
+ file,
182
+ };
167
183
  }
168
184
  };
169
185
  }))
package/lib/cms/watch.js CHANGED
@@ -14,9 +14,9 @@ const uploadFolder_1 = require("./uploadFolder");
14
14
  const ignoreRules_1 = require("../ignoreRules");
15
15
  const fileMapper_1 = require("../fileMapper");
16
16
  const fileMapper_2 = require("../../api/fileMapper");
17
- const escapeRegExp_1 = require("../../utils/escapeRegExp");
17
+ const escapeRegExp_1 = require("../escapeRegExp");
18
18
  const path_2 = require("../path");
19
- const notify_1 = require("../../utils/notify");
19
+ const notify_1 = require("../notify");
20
20
  const themes_1 = require("./themes");
21
21
  const logger_1 = require("../logging/logger");
22
22
  const lang_1 = require("../../utils/lang");
@@ -12,7 +12,7 @@ const fs_1 = require("./fs");
12
12
  const logger_1 = require("./logging/logger");
13
13
  const ignoreRules_1 = require("./ignoreRules");
14
14
  const http_1 = __importDefault(require("../http"));
15
- const escapeRegExp_1 = require("../utils/escapeRegExp");
15
+ const escapeRegExp_1 = require("./escapeRegExp");
16
16
  const path_2 = require("./path");
17
17
  const apiErrors_1 = require("../errors/apiErrors");
18
18
  const standardErrors_1 = require("../errors/standardErrors");
@@ -5,10 +5,16 @@ type AccessToken = {
5
5
  accessToken: string;
6
6
  expiresAt: string;
7
7
  scopeGroups: Array<string>;
8
+ enabledFeatures?: {
9
+ [key: string]: number;
10
+ };
8
11
  encodedOAuthRefreshToken: string;
9
12
  hubName: string;
10
13
  };
11
14
  export declare function getAccessToken(personalAccessKey: string, env?: Environment, accountId?: number): Promise<AccessToken>;
12
15
  export declare function accessTokenForPersonalAccessKey(accountId: number): Promise<string | undefined>;
16
+ export declare function enabledFeaturesForPersonalAccessKey(accountId: number): Promise<{
17
+ [key: string]: number;
18
+ } | undefined>;
13
19
  export declare function updateConfigWithAccessToken(token: AccessToken, personalAccessKey: string, env?: Environment, name?: string, makeDefault?: boolean): Promise<CLIAccount | null>;
14
20
  export {};
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.updateConfigWithAccessToken = exports.accessTokenForPersonalAccessKey = exports.getAccessToken = void 0;
6
+ exports.updateConfigWithAccessToken = exports.enabledFeaturesForPersonalAccessKey = exports.accessTokenForPersonalAccessKey = exports.getAccessToken = void 0;
7
7
  const moment_1 = __importDefault(require("moment"));
8
8
  const environments_1 = require("../constants/environments");
9
9
  const auth_1 = require("../constants/auth");
@@ -37,13 +37,15 @@ async function getAccessToken(personalAccessKey, env = environments_1.ENVIRONMEN
37
37
  accessToken: response.oauthAccessToken,
38
38
  expiresAt: (0, moment_1.default)(response.expiresAtMillis).toISOString(),
39
39
  scopeGroups: response.scopeGroups,
40
+ enabledFeatures: response.enabledFeatures,
40
41
  encodedOAuthRefreshToken: response.encodedOAuthRefreshToken,
41
42
  hubName: response.hubName,
42
43
  };
43
44
  }
44
45
  exports.getAccessToken = getAccessToken;
45
46
  async function refreshAccessToken(personalAccessKey, env = environments_1.ENVIRONMENTS.PROD, accountId) {
46
- const { accessToken, expiresAt } = await getAccessToken(personalAccessKey, env, accountId);
47
+ const accessTokenResponse = await getAccessToken(personalAccessKey, env, accountId);
48
+ const { accessToken, expiresAt } = accessTokenResponse;
47
49
  const config = (0, config_1.getAccountConfig)(accountId);
48
50
  (0, config_1.updateAccountConfig)({
49
51
  env,
@@ -55,20 +57,20 @@ async function refreshAccessToken(personalAccessKey, env = environments_1.ENVIRO
55
57
  },
56
58
  });
57
59
  (0, config_1.writeConfig)();
58
- return accessToken;
60
+ return accessTokenResponse;
59
61
  }
60
62
  async function getNewAccessToken(accountId, personalAccessKey, expiresAt, env) {
61
63
  const key = getRefreshKey(personalAccessKey, expiresAt);
62
64
  if (refreshRequests.has(key)) {
63
65
  return refreshRequests.get(key);
64
66
  }
65
- let accessToken;
67
+ let accessTokenResponse;
66
68
  try {
67
69
  const refreshAccessPromise = refreshAccessToken(personalAccessKey, env, accountId);
68
70
  if (key) {
69
71
  refreshRequests.set(key, refreshAccessPromise);
70
72
  }
71
- accessToken = await refreshAccessPromise;
73
+ accessTokenResponse = await refreshAccessPromise;
72
74
  }
73
75
  catch (e) {
74
76
  if (key) {
@@ -76,7 +78,7 @@ async function getNewAccessToken(accountId, personalAccessKey, expiresAt, env) {
76
78
  }
77
79
  throw e;
78
80
  }
79
- return accessToken;
81
+ return accessTokenResponse;
80
82
  }
81
83
  async function accessTokenForPersonalAccessKey(accountId) {
82
84
  const account = (0, config_1.getAccountConfig)(accountId);
@@ -88,11 +90,22 @@ async function accessTokenForPersonalAccessKey(accountId) {
88
90
  const authDataExists = authTokenInfo && auth?.tokenInfo?.accessToken;
89
91
  if (!authDataExists ||
90
92
  (0, moment_1.default)().add(5, 'minutes').isAfter((0, moment_1.default)(authTokenInfo.expiresAt))) {
91
- return getNewAccessToken(accountId, personalAccessKey, authTokenInfo && authTokenInfo.expiresAt, env);
93
+ return getNewAccessToken(accountId, personalAccessKey, authTokenInfo && authTokenInfo.expiresAt, env).then(tokenInfo => tokenInfo.accessToken);
92
94
  }
93
95
  return auth?.tokenInfo?.accessToken;
94
96
  }
95
97
  exports.accessTokenForPersonalAccessKey = accessTokenForPersonalAccessKey;
98
+ async function enabledFeaturesForPersonalAccessKey(accountId) {
99
+ const account = (0, config_1.getAccountConfig)(accountId);
100
+ if (!account) {
101
+ (0, standardErrors_1.throwErrorWithMessage)(`${i18nKey}.errors.accountNotFound`, { accountId });
102
+ }
103
+ const { auth, personalAccessKey, env } = account;
104
+ const authTokenInfo = auth && auth.tokenInfo;
105
+ const accessTokenResponse = await getNewAccessToken(accountId, personalAccessKey, authTokenInfo && authTokenInfo.expiresAt, env);
106
+ return accessTokenResponse?.enabledFeatures;
107
+ }
108
+ exports.enabledFeaturesForPersonalAccessKey = enabledFeaturesForPersonalAccessKey;
96
109
  async function updateConfigWithAccessToken(token, personalAccessKey, env, name, makeDefault = false) {
97
110
  const { portalId, accessToken, expiresAt } = token;
98
111
  const accountEnv = env || (0, config_1.getEnv)(name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/local-dev-lib",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Provides library functionality for HubSpot local development tooling, including the HubSpot CLI",
5
5
  "main": "lib/index.js",
6
6
  "repository": {
File without changes
File without changes
File without changes
File without changes