@shoper/cli 0.1.0-25 → 0.1.0-26
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/build/cli/ui/error_item.js +7 -0
- package/build/cli/ui/errors_list.js +15 -0
- package/build/theme/commands/init/theme_init_command.js +4 -3
- package/build/theme/commands/push/theme_push_command.js +9 -4
- package/build/theme/features/theme/push/service/theme_push_service.js +17 -4
- package/build/theme/features/theme/push/theme_push_constants.js +1 -0
- package/build/theme/features/theme/push/theme_push_errors_factory.js +5 -3
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Error } from '../../ui/message_box/error.js';
|
|
2
|
+
import { Text } from '../../ui/text.js';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
export const ErrorItem = ({ error, title }) => {
|
|
5
|
+
return (React.createElement(Error, { header: title },
|
|
6
|
+
React.createElement(Text, null, error)));
|
|
7
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ErrorItem } from './error_item.js';
|
|
3
|
+
import { Error } from '../../ui/message_box/error.js';
|
|
4
|
+
import { Text } from '../../ui/text.js';
|
|
5
|
+
import { Box } from '../../ui/box.js';
|
|
6
|
+
export const ErrorsList = ({ errors }) => {
|
|
7
|
+
if (typeof errors === 'string') {
|
|
8
|
+
return React.createElement(ErrorItem, { error: errors });
|
|
9
|
+
}
|
|
10
|
+
if (Array.isArray(errors)) {
|
|
11
|
+
return errors.map((error, index) => (React.createElement(ErrorItem, { key: index, error: error })));
|
|
12
|
+
}
|
|
13
|
+
return (React.createElement(React.Fragment, null, Object.entries(errors).map(([title, errorMessages], index) => (React.createElement(Error, { key: index, header: title },
|
|
14
|
+
React.createElement(Box, { flexDirection: "column" }, errorMessages.map((message, index) => (React.createElement(Text, { key: index }, message)))))))));
|
|
15
|
+
};
|
|
@@ -12,9 +12,9 @@ import { UnpermittedCommandError } from '../ui/unpermitted_command_error.js';
|
|
|
12
12
|
import { MissingCredentialsError } from '../../../cli/commands/auth/ui/missing_credentials_error.js';
|
|
13
13
|
import { ThemeCreatedSuccess } from './ui/theme_created_success.js';
|
|
14
14
|
import { Text } from '../../../ui/text.js';
|
|
15
|
-
import { Error } from '../../../ui/message_box/error.js';
|
|
16
15
|
import { MissingThemeIdError } from '../ui/missing_theme_id_error.js';
|
|
17
16
|
import { Box } from '../../../ui/box.js';
|
|
17
|
+
import { ErrorsList } from '../../../cli/ui/errors_list.js';
|
|
18
18
|
export class ThemeInitCommand extends BaseThemeCommand {
|
|
19
19
|
static summary = 'Creates a copy of an existing theme by duplicating it.';
|
|
20
20
|
static description = 'The new theme will be named after the source theme with a "Copy" suffix and an incremental number.\n\nYou must run this command from the root directory (not inside any theme folder) and provide the ID of the theme you want to duplicate.';
|
|
@@ -73,6 +73,8 @@ export class ThemeInitCommand extends BaseThemeCommand {
|
|
|
73
73
|
catch (err) {
|
|
74
74
|
spinner?.stop();
|
|
75
75
|
this._handleError(err, themeId);
|
|
76
|
+
//TODO analyze why on nodejs v22 this command does not exit properly, even all promises are resolved
|
|
77
|
+
this.exit();
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
_handleError(err, themeId) {
|
|
@@ -81,8 +83,7 @@ export class ThemeInitCommand extends BaseThemeCommand {
|
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
83
85
|
if (err?.message) {
|
|
84
|
-
renderOnce(React.createElement(
|
|
85
|
-
React.createElement(Text, null, err.message)));
|
|
86
|
+
renderOnce(React.createElement(ErrorsList, { errors: err.message }));
|
|
86
87
|
return;
|
|
87
88
|
}
|
|
88
89
|
this.error(String(err));
|
|
@@ -2,7 +2,7 @@ import { BaseThemeCommand } from '../../class/base_theme_command.js';
|
|
|
2
2
|
import { CLI_AUTH_API_NAME } from '../../../cli/auth/cli_auth_constants.js';
|
|
3
3
|
import { EXECUTION_CONTEXT_API_NAME, EXECUTION_CONTEXTS } from '../../../cli/features/execution_context/execution_context_constants.js';
|
|
4
4
|
import { THEME_ACTION_NOT_FOUND_ERROR_CODE, THEME_ACTIONS_API_NAME, THEME_ACTIONS_TYPES } from '../../features/theme/actions/theme_actions_constants.js';
|
|
5
|
-
import { THEME_ARCHIVE_UPLOAD_ERROR, THEME_PUSH_API_NAME } from '../../features/theme/push/theme_push_constants.js';
|
|
5
|
+
import { THEME_ARCHIVE_UPLOAD_ERROR, THEME_FILES_UPLOAD_ERROR, THEME_PUSH_API_NAME } from '../../features/theme/push/theme_push_constants.js';
|
|
6
6
|
import { ThemeMetaDataUtils } from '../../features/theme/utils/meta_data/theme_meta_data_utils.js';
|
|
7
7
|
import { mapChecksumToTree } from '../../../utils/checksums/checksums_utils.js';
|
|
8
8
|
import { mapToPermissionsTree } from '../../utils/directory_validator/directory_validator_utils.js';
|
|
@@ -26,6 +26,7 @@ import { ThemeWorkUrlMismatch } from '../ui/theme_work_url_mismatch.js';
|
|
|
26
26
|
import { THEME_WORK_URL_MISMATCH_ERROR } from '../../features/theme/utils/meta_data/theme_meta_data_constants.js';
|
|
27
27
|
import { ThemeFilesStructureUtils } from '../../features/theme/utils/files_structure/theme_files_structure_utils.js';
|
|
28
28
|
import { ThemeInfoUtils } from '../../features/theme/info/theme_info_utils.js';
|
|
29
|
+
import { ErrorsList } from '../../../cli/ui/errors_list.js';
|
|
29
30
|
export class ThemePushCommand extends BaseThemeCommand {
|
|
30
31
|
static summary = 'Uploads your local theme files to the store and overwrites the current version of the theme in your store.';
|
|
31
32
|
static description = 'Check your local changes before pushing.\n\nYou must run this command from a specific theme directory (ID not needed).';
|
|
@@ -110,16 +111,20 @@ export class ThemePushCommand extends BaseThemeCommand {
|
|
|
110
111
|
return;
|
|
111
112
|
}
|
|
112
113
|
if (err?.code === THEME_ARCHIVE_UPLOAD_ERROR) {
|
|
113
|
-
|
|
114
|
+
renderOnce(React.createElement(ErrorsList, { errors: err?.details }));
|
|
114
115
|
return;
|
|
115
116
|
}
|
|
116
117
|
if (err?.code === THEME_WORK_URL_MISMATCH_ERROR) {
|
|
117
118
|
this._renderUrlMismatchError();
|
|
118
119
|
return;
|
|
119
120
|
}
|
|
121
|
+
if (err?.code === THEME_FILES_UPLOAD_ERROR) {
|
|
122
|
+
return renderOnce(React.createElement(Error, { header: "Uploading theme files to the shop failed.\n" },
|
|
123
|
+
React.createElement(Text, null, "The rejected files have been removed locally. Please ensure that the files are not corrupted and that the file extensions are supported.")));
|
|
124
|
+
}
|
|
120
125
|
if (err?.message) {
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
console.log('error message', err.message);
|
|
127
|
+
renderOnce(React.createElement(ErrorsList, { errors: err.message }));
|
|
123
128
|
return;
|
|
124
129
|
}
|
|
125
130
|
this.error(String(err));
|
|
@@ -105,18 +105,24 @@ export class ThemePushService {
|
|
|
105
105
|
}
|
|
106
106
|
async _uploadThemeFiles({ filesToUpload, themeRootDir, localFiles, credentials }) {
|
|
107
107
|
try {
|
|
108
|
-
const uploadedImageData = await this._uploadFiles(filesToUpload, credentials);
|
|
108
|
+
const { uploadedImageData, rejectedImageData } = await this._uploadFiles(filesToUpload, credentials);
|
|
109
109
|
const newFilesList = ThemeImagesUtils.updateOriginalFilenameToUploadedFilename(localFiles, uploadedImageData);
|
|
110
110
|
if (uploadedImageData.length)
|
|
111
111
|
await ThemeImagesUtils.removeUploadedOriginalFiles(themeRootDir, uploadedImageData);
|
|
112
|
+
if (rejectedImageData.length)
|
|
113
|
+
await this._removeUploadedThemeFiles(rejectedImageData, themeRootDir);
|
|
112
114
|
await this._createAFilesListFile(themeRootDir, newFilesList);
|
|
113
115
|
}
|
|
114
116
|
catch (err) {
|
|
115
117
|
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, err);
|
|
116
118
|
}
|
|
117
119
|
}
|
|
120
|
+
async _removeUploadedThemeFiles(uploadedImageData, themeRootDir) {
|
|
121
|
+
await Promise.all(uploadedImageData.map(({ location, originalFilename }) => removeFile(join(themeRootDir, location, originalFilename))));
|
|
122
|
+
}
|
|
118
123
|
async _uploadFiles(uploadData, credentials) {
|
|
119
124
|
const uploadedImageData = [];
|
|
125
|
+
const rejectedImageData = [];
|
|
120
126
|
await Promise.all(uploadData.map(({ actionData, path }) => this.#themePushHttpApi
|
|
121
127
|
.pushThemeData({
|
|
122
128
|
actionData,
|
|
@@ -124,15 +130,22 @@ export class ThemePushService {
|
|
|
124
130
|
shopUrl: credentials.shopUrl
|
|
125
131
|
})
|
|
126
132
|
.response.then((response) => {
|
|
127
|
-
if (response.status !== 200 || !response.data.isSuccess)
|
|
128
|
-
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, response.data?.messages ?? []);
|
|
129
133
|
uploadedImageData.push({
|
|
130
134
|
location: dirname(path),
|
|
131
135
|
originalFilename: basename(path),
|
|
132
136
|
uploadedFilename: response.data.imageId
|
|
133
137
|
});
|
|
138
|
+
})
|
|
139
|
+
.catch(() => {
|
|
140
|
+
rejectedImageData.push({
|
|
141
|
+
location: dirname(path),
|
|
142
|
+
originalFilename: basename(path)
|
|
143
|
+
});
|
|
134
144
|
})));
|
|
135
|
-
return
|
|
145
|
+
return {
|
|
146
|
+
uploadedImageData,
|
|
147
|
+
rejectedImageData
|
|
148
|
+
};
|
|
136
149
|
}
|
|
137
150
|
async _getActionDataForFilesToUpload({ pushAction, filesStructure, executionContext }) {
|
|
138
151
|
const uploadData = [];
|
|
@@ -3,3 +3,4 @@ export const THEME_PUSH_API_NAME = 'ThemePushApi';
|
|
|
3
3
|
export const THEME_FILES_LIST_FILE_NAME = 'filesList.json';
|
|
4
4
|
export const THEME_MODULE_SETTINGS_FILE_NAME = 'settings.json';
|
|
5
5
|
export const THEME_ARCHIVE_UPLOAD_ERROR = 'theme.push.error_uploading_theme_archive';
|
|
6
|
+
export const THEME_FILES_UPLOAD_ERROR = 'theme.push.error_uploading_theme_files';
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { AppError } from '../../../../cli/class/errors/app/app_error.js';
|
|
2
|
-
import { THEME_ARCHIVE_UPLOAD_ERROR } from './theme_push_constants.js';
|
|
2
|
+
import { THEME_ARCHIVE_UPLOAD_ERROR, THEME_FILES_UPLOAD_ERROR } from './theme_push_constants.js';
|
|
3
3
|
export class ThemePushErrorsFactory {
|
|
4
4
|
static createErrorWhileUploadingThemeFiles(shopUrl, messages) {
|
|
5
5
|
return new AppError({
|
|
6
|
-
code:
|
|
6
|
+
code: THEME_FILES_UPLOAD_ERROR,
|
|
7
7
|
message: `Error while uploading theme files to shop "${shopUrl}"`,
|
|
8
8
|
level: 'error',
|
|
9
|
-
details:
|
|
9
|
+
details: {
|
|
10
|
+
messages
|
|
11
|
+
}
|
|
10
12
|
});
|
|
11
13
|
}
|
|
12
14
|
static createErrorWhileCreatingThemeArchive(shopUrl, error) {
|