@shoper/cli 0.1.0-30 → 0.1.0-32
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/theme/commands/delete/theme_delete_command.js +2 -2
- package/build/theme/commands/init/theme_init_command.js +1 -1
- package/build/theme/commands/list/theme_list_command_utils.js +2 -2
- package/build/theme/commands/push/theme_push_command.js +3 -2
- package/build/theme/features/theme/delete/service/theme_delete_service.js +6 -3
- package/build/theme/features/theme/push/service/theme_push_service.js +2 -1
- package/build/theme/features/theme/skinstore/api/theme_skinstore_api.js +17 -0
- package/build/theme/features/theme/skinstore/http/theme_skinstore_http_api.js +7 -0
- package/build/theme/features/theme/skinstore/service/theme_skinstore_service.js +3 -0
- package/build/theme/features/themes/list/services/themes_list_service.js +4 -5
- package/build/theme/hooks/themes_actions/ensure_themes_actions_hook_constants.js +1 -0
- package/build/ui/form/controls_mappers.js +39 -0
- package/build/ui/form/form.js +5 -0
- package/build/ui/form/form_constants.js +13 -0
- package/build/{cli/ui → ui}/validation_errors/validation_error_content.js +2 -2
- package/build/{cli/ui → ui}/validation_errors/validation_errors.js +3 -3
- package/build/utils/download_file/download_file_utils.js +2 -0
- package/package.json +3 -2
- /package/build/theme/features/theme/{publish → skinstore}/theme_publish_constants.js +0 -0
- /package/build/theme/features/theme/{publish → skinstore}/theme_publish_utils.js +0 -0
- /package/build/{cli/ui → ui}/validation_errors/validation_errors_utils.js +0 -0
|
@@ -78,7 +78,7 @@ export class ThemeDeleteCommand extends BaseThemeCommand {
|
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
const themeDeleteApi = this.getApi(THEME_DELETE_API_NAME);
|
|
81
|
-
const
|
|
81
|
+
const resp = await themeDeleteApi.deleteTheme({
|
|
82
82
|
actionData: deleteAction.data,
|
|
83
83
|
credentials
|
|
84
84
|
});
|
|
@@ -86,7 +86,7 @@ export class ThemeDeleteCommand extends BaseThemeCommand {
|
|
|
86
86
|
themeId: _themeId,
|
|
87
87
|
credentials
|
|
88
88
|
});
|
|
89
|
-
if (!isSuccess)
|
|
89
|
+
if (!resp?.isSuccess)
|
|
90
90
|
return;
|
|
91
91
|
renderOnce(React.createElement(ThemeDeletedSuccessfully, null));
|
|
92
92
|
return;
|
|
@@ -14,7 +14,7 @@ import { ThemeCreatedSuccess } from './ui/theme_created_success.js';
|
|
|
14
14
|
import { Text } from '../../../ui/text.js';
|
|
15
15
|
import { MissingThemeIdError } from '../ui/missing_theme_id_error.js';
|
|
16
16
|
import { Box } from '../../../ui/box.js';
|
|
17
|
-
import { ValidationErrors } from '../../../
|
|
17
|
+
import { ValidationErrors } from '../../../ui/validation_errors/validation_errors.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.';
|
|
@@ -17,8 +17,8 @@ export class ThemeListCommandUtils {
|
|
|
17
17
|
width: 10
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
|
-
rows: themes.map((theme
|
|
21
|
-
React.createElement(Text, null,
|
|
20
|
+
rows: themes.map((theme) => [
|
|
21
|
+
React.createElement(Text, null, theme.skinId),
|
|
22
22
|
React.createElement(Text, null, theme.title),
|
|
23
23
|
React.createElement(Text, null, theme.isActive ? 'active' : 'inactive')
|
|
24
24
|
])
|
|
@@ -24,7 +24,7 @@ import { ThemeWorkUrlMismatch } from '../ui/theme_work_url_mismatch.js';
|
|
|
24
24
|
import { THEME_WORK_URL_MISMATCH_ERROR } from '../../features/theme/utils/meta_data/theme_meta_data_constants.js';
|
|
25
25
|
import { ThemeFilesStructureUtils } from '../../features/theme/utils/files_structure/theme_files_structure_utils.js';
|
|
26
26
|
import { ThemeInfoUtils } from '../../features/theme/info/theme_info_utils.js';
|
|
27
|
-
import { ValidationErrors } from '../../../
|
|
27
|
+
import { ValidationErrors } from '../../../ui/validation_errors/validation_errors.js';
|
|
28
28
|
import { ThemeChecksums } from '../../class/checksums/theme_checksums.js';
|
|
29
29
|
export class ThemePushCommand extends BaseThemeCommand {
|
|
30
30
|
static summary = 'Uploads your local theme files to the store and overwrites the current version of the theme in your store.';
|
|
@@ -118,8 +118,9 @@ export class ThemePushCommand extends BaseThemeCommand {
|
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
120
|
if (err?.code === THEME_FILES_UPLOAD_ERROR) {
|
|
121
|
-
|
|
121
|
+
renderOnce(React.createElement(Error, { header: "Uploading theme files to the shop failed.\n" },
|
|
122
122
|
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.")));
|
|
123
|
+
return;
|
|
123
124
|
}
|
|
124
125
|
if (err?.message) {
|
|
125
126
|
renderOnce(React.createElement(ValidationErrors, { errors: err.message }));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HttpErrorsFactory } from '../../../../../cli/class/errors/http/http_errors_factory.js';
|
|
2
2
|
import { DownloadFileErrorsFactory } from '../../../../../utils/download_file/download_file_errors_factory.js';
|
|
3
|
+
import { STATUS_CODES } from '@dreamcommerce/star_core';
|
|
3
4
|
export class ThemeDeleteService {
|
|
4
5
|
#httpApi;
|
|
5
6
|
constructor(httpApi) {
|
|
@@ -7,9 +8,11 @@ export class ThemeDeleteService {
|
|
|
7
8
|
}
|
|
8
9
|
async deleteTheme({ actionData, credentials }) {
|
|
9
10
|
try {
|
|
10
|
-
const { response } = this.#httpApi.deleteTheme({ actionData, shopUrl: credentials.shopUrl });
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const { response: request } = this.#httpApi.deleteTheme({ actionData, shopUrl: credentials.shopUrl });
|
|
12
|
+
const response = await request;
|
|
13
|
+
if (response?.status !== STATUS_CODES.ok)
|
|
14
|
+
return;
|
|
15
|
+
return response?.data;
|
|
13
16
|
}
|
|
14
17
|
catch (err) {
|
|
15
18
|
//TODO to basic class
|
|
@@ -11,7 +11,7 @@ import { THEME_FILES_LIST_FILE_NAME, THEME_MODULE_SETTINGS_FILE_NAME } from '../
|
|
|
11
11
|
import { THEME_PUSH_WILDCARD_GLOBS_FOR_FILES } from './theme_push_service_constants.js';
|
|
12
12
|
import { ThemePushErrorsFactory } from '../theme_push_errors_factory.js';
|
|
13
13
|
import { ThemeImagesUtils } from '../../utils/theme_images_utils.js';
|
|
14
|
-
import { ThemePublishUtils } from '../../
|
|
14
|
+
import { ThemePublishUtils } from '../../skinstore/theme_publish_utils.js';
|
|
15
15
|
import { formatJSONFile, removeFile, writeJSONFile } from '../../../../../utils/fs/fs_utils.js';
|
|
16
16
|
import { MODULES_DIRECTORY_NAME } from '../../theme_constants.js';
|
|
17
17
|
import path from 'node:path';
|
|
@@ -100,6 +100,7 @@ export class ThemePushService {
|
|
|
100
100
|
.filter((path) => extname(path).toLowerCase() === '.json')
|
|
101
101
|
.map((jsonFile) => formatJSONFile(join(themeRootDir, jsonFile))));
|
|
102
102
|
}
|
|
103
|
+
//TODO osobna klasa do uploadu
|
|
103
104
|
async _uploadThemeFiles({ filesToUpload, themeRootDir, localFiles, credentials }) {
|
|
104
105
|
try {
|
|
105
106
|
const { uploadedImageData, rejectedImageData } = await this._uploadFiles(filesToUpload, credentials);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FeatureApi } from '@dreamcommerce/star_core';
|
|
2
|
+
export class ThemeSkinstoreApi extends FeatureApi {
|
|
3
|
+
#service;
|
|
4
|
+
constructor(service) {
|
|
5
|
+
super();
|
|
6
|
+
this.#service = service;
|
|
7
|
+
}
|
|
8
|
+
async getPublishFormData() {
|
|
9
|
+
return this.#service.getPublishFormData();
|
|
10
|
+
}
|
|
11
|
+
async publish(themeId) {
|
|
12
|
+
// return this.#service.publish(themeId);
|
|
13
|
+
}
|
|
14
|
+
async update() {
|
|
15
|
+
// return this.#service.update();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -9,18 +9,17 @@ export class ThemesListService {
|
|
|
9
9
|
}
|
|
10
10
|
async getThemes({ shopUrl }) {
|
|
11
11
|
try {
|
|
12
|
-
const { response } = this.#httpApi.getThemes(shopUrl);
|
|
13
|
-
const
|
|
14
|
-
if (status !== STATUS_CODES.ok)
|
|
12
|
+
const { response: request } = this.#httpApi.getThemes(shopUrl);
|
|
13
|
+
const response = await request;
|
|
14
|
+
if (response?.status !== STATUS_CODES.ok)
|
|
15
15
|
return;
|
|
16
16
|
//TODO baseHttpApi + model mapper
|
|
17
|
-
return data.map(({ _links, ...rest }) => new ThemeMetaData({
|
|
17
|
+
return response?.data.map(({ _links, ...rest }) => new ThemeMetaData({
|
|
18
18
|
...rest,
|
|
19
19
|
links: _links
|
|
20
20
|
}));
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
23
|
-
//TODO to basic class
|
|
24
23
|
switch (err.response?.status) {
|
|
25
24
|
case 403:
|
|
26
25
|
throw HttpErrorsFactory.createForbiddenError();
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const toTextControl = ({ type, validate, label, isRequired, defaultValue, name }) => {
|
|
2
|
+
return {
|
|
3
|
+
type: 'input',
|
|
4
|
+
name,
|
|
5
|
+
message: isRequired ? `${label} (required)` : label,
|
|
6
|
+
default: defaultValue,
|
|
7
|
+
validate
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export const toNumberControl = ({ type, validate, label, isRequired, defaultValue, name }) => {
|
|
11
|
+
return {
|
|
12
|
+
type: 'number',
|
|
13
|
+
name,
|
|
14
|
+
message: isRequired ? `${label} (required)` : label,
|
|
15
|
+
default: defaultValue,
|
|
16
|
+
validate
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export const toSelectControl = ({ type, validate, label, isRequired, defaultValue, name, choices }) => {
|
|
20
|
+
return {
|
|
21
|
+
type: 'list',
|
|
22
|
+
name,
|
|
23
|
+
message: isRequired ? `${label} (required)` : label,
|
|
24
|
+
choices,
|
|
25
|
+
default: defaultValue,
|
|
26
|
+
validate
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export const toMultiSelectControl = ({ type, validate, label, isRequired, defaultValue, name, choices }) => {
|
|
30
|
+
//TODO multiple checkboxes
|
|
31
|
+
return {
|
|
32
|
+
type: 'checkbox',
|
|
33
|
+
name,
|
|
34
|
+
message: isRequired ? `${label} (required)` : label,
|
|
35
|
+
choices,
|
|
36
|
+
default: defaultValue,
|
|
37
|
+
validate
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { toMultiSelectControl, toNumberControl, toSelectControl, toTextControl } from './controls_mappers.js';
|
|
2
|
+
export const CONTROLS_TYPES = {
|
|
3
|
+
text: 'text',
|
|
4
|
+
number: 'number',
|
|
5
|
+
select: 'select',
|
|
6
|
+
multiSelect: 'multiSelect'
|
|
7
|
+
};
|
|
8
|
+
export const CONTROL_TYPE_TO_MAPPERS = {
|
|
9
|
+
[CONTROLS_TYPES.text]: toTextControl,
|
|
10
|
+
[CONTROLS_TYPES.number]: toNumberControl,
|
|
11
|
+
[CONTROLS_TYPES.select]: toSelectControl,
|
|
12
|
+
[CONTROLS_TYPES.multiSelect]: toMultiSelectControl
|
|
13
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Text } from '
|
|
2
|
-
import { List } from '
|
|
1
|
+
import { Text } from '../text.js';
|
|
2
|
+
import { List } from '../list/list.js';
|
|
3
3
|
import { ValidationErrorsUtils } from './validation_errors_utils.js';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
export const ValidationErrorContent = ({ errors }) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Error } from '
|
|
3
|
-
import { Text } from '
|
|
4
|
-
import { List } from '
|
|
2
|
+
import { Error } from '../message_box/error.js';
|
|
3
|
+
import { Text } from '../text.js';
|
|
4
|
+
import { List } from '../list/list.js';
|
|
5
5
|
import { ValidationErrorContent } from './validation_error_content.js';
|
|
6
6
|
export const ValidationErrors = ({ errors }) => {
|
|
7
7
|
if (typeof errors === 'string') {
|
|
@@ -8,6 +8,8 @@ import { DownloadFileErrorsFactory } from './download_file_errors_factory.js';
|
|
|
8
8
|
export const downloadFile = async ({ dist, request }) => {
|
|
9
9
|
try {
|
|
10
10
|
const resp = (await request);
|
|
11
|
+
if (!resp)
|
|
12
|
+
throw resp;
|
|
11
13
|
const headers = resp.headers;
|
|
12
14
|
const url = new URL(resp.config.url);
|
|
13
15
|
const filename = getFileNameFromHeaders(headers) ?? basename(url.pathname);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@shoper/cli",
|
|
3
3
|
"packageManager": "yarn@3.2.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.1.0-
|
|
5
|
+
"version": "0.1.0-32",
|
|
6
6
|
"description": "CLI tool for Shoper",
|
|
7
7
|
"author": "Joanna Firek",
|
|
8
8
|
"license": "MIT",
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"ink-link": "4.1.0",
|
|
64
64
|
"log-symbols": "7.0.1",
|
|
65
65
|
"figures": "6.1.0",
|
|
66
|
-
"strip-ansi": "7.1.0"
|
|
66
|
+
"strip-ansi": "7.1.0",
|
|
67
|
+
"inquirer-select-line": "1.1.3"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@babel/core": "7.27.1",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|