@shoper/cli 0.1.0-9 → 0.2.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.
- package/build/cli/auth/cli_auth_errors_factory.js +1 -1
- package/build/cli/auth/tokens/cli_auth_tokens_errors_factory.js +1 -1
- package/build/cli/auth/tokens/cli_auth_tokens_initalizer.js +1 -1
- package/build/cli/class/errors/file_system_errors_factory.js +1 -1
- package/build/cli/class/errors/http/http_errors_constants.js +1 -0
- package/build/cli/class/errors/{http_errors_factory.js → http/http_errors_factory.js} +3 -2
- package/build/cli/commands/auth/cli_auth_add_token_command.js +22 -19
- package/build/cli/commands/auth/cli_auth_commands_constants.js +3 -0
- package/build/cli/commands/auth/cli_auth_commands_utils.js +46 -0
- package/build/cli/commands/auth/cli_auth_list_tokens_command.js +19 -6
- package/build/cli/commands/auth/cli_auth_remove_token_command.js +36 -10
- package/build/cli/commands/auth/cli_auth_switch_token_command.js +19 -9
- package/build/cli/commands/auth/ui/invalid_token_index_error.js +11 -0
- package/build/cli/commands/auth/ui/missing_credentials_error.js +9 -0
- package/build/cli/commands/auth/ui/missing_token_index_error.js +19 -0
- package/build/cli/commands/cli_ui_dump_command.js +11 -0
- package/build/cli/commands/cli_update_command.js +13 -4
- package/build/cli/commands/commands_constants.js +2 -1
- package/build/cli/core/cli_setup.js +5 -1
- package/build/cli/features/controls/controls_constants.js +12 -0
- package/build/cli/features/controls/controls_dto_mappers.js +55 -0
- package/build/cli/features/controls/ui/controls_mappers.js +62 -0
- package/build/cli/features/controls/ui/form.js +4 -0
- package/build/cli/features/controls/ui/form_constants.js +7 -0
- package/build/cli/features/controls/validators/greater_eq_than_validator.js +5 -0
- package/build/cli/features/controls/validators/length_validator.js +6 -0
- package/build/cli/features/controls/validators/required_validator.js +5 -0
- package/build/cli/features/controls/validators/validator_constants.js +13 -0
- package/build/cli/features/execution_context/execution_context_service.js +5 -5
- package/build/cli/features/http_requester/http_requester_initializer.js +1 -1
- package/build/cli/hooks/authorization/ensure_authorization_hook.js +2 -2
- package/build/cli/hooks/authorization/ensure_authorization_hook_constants.js +8 -8
- package/build/index.js +37 -19
- package/build/theme/class/checksums/theme_checksums.js +174 -0
- package/build/theme/{features/theme/utils → class}/checksums/theme_checksums_error_factory.js +1 -1
- package/build/theme/class/checksums/theme_checksums_utils.js +17 -0
- package/build/theme/class/fetch_resources/fetch_resources.js +1 -0
- package/build/theme/class/fetch_resources/fetch_resources_errors_factory.js +1 -1
- package/build/theme/class/fetch_resources/fetch_resources_utils.js +4 -1
- package/build/theme/commands/delete/theme_delete_command.js +111 -0
- package/build/theme/commands/delete/ui/theme_deleted_successfully.js +15 -0
- package/build/theme/commands/delete/ui/theme_deletion_warning.js +10 -0
- package/build/theme/commands/info/theme_info_command.js +94 -0
- package/build/theme/commands/info/theme_info_command_utils.js +39 -0
- package/build/theme/commands/init/theme_init_command.js +97 -0
- package/build/theme/commands/init/ui/theme_created_success.js +15 -0
- package/build/theme/commands/list/theme_list_command.js +25 -0
- package/build/theme/commands/list/theme_list_command_utils.js +27 -0
- package/build/theme/commands/publish/theme_publish_command.js +92 -0
- package/build/theme/commands/pull/theme_pull_command.js +194 -0
- package/build/theme/commands/pull/ui/theme_pull_id_mismatch_error.js +7 -0
- package/build/theme/commands/pull/ui/theme_pull_unpublished_changes_warning.js +10 -0
- package/build/theme/commands/pull/ui/theme_pulled_success.js +5 -0
- package/build/theme/commands/push/theme_push_command.js +134 -0
- package/build/theme/commands/push/ui/theme_push_skip_into.js +7 -0
- package/build/theme/commands/push/ui/theme_pushed_success.js +5 -0
- package/build/theme/commands/push/ui/theme_unpermitted_actions_error.js +12 -0
- package/build/theme/commands/theme_commands_constants.js +4 -1
- package/build/theme/commands/theme_show_changes_command.js +1 -0
- package/build/theme/commands/theme_verify_command.js +8 -7
- package/build/theme/commands/ui/invalid_theme_id.js +11 -0
- package/build/theme/commands/ui/missing_theme_files.js +15 -0
- package/build/theme/commands/ui/missing_theme_id_error.js +13 -0
- package/build/theme/commands/ui/ouside_of_theme_directory_context_error.js +7 -0
- package/build/theme/commands/ui/theme_directory_context_error.js +7 -0
- package/build/theme/commands/ui/theme_work_url_mismatch.js +17 -0
- package/build/theme/commands/ui/unpermitted_command_error.js +18 -0
- package/build/theme/features/theme/actions/api/theme_actions_api.js +3 -0
- package/build/theme/features/theme/actions/service/theme_actions_service.js +15 -3
- package/build/theme/features/theme/actions/service/theme_actions_service_constants.js +1 -0
- package/build/theme/features/theme/actions/theme_actions_constants.js +3 -1
- package/build/theme/features/theme/actions/theme_actions_initializer.js +1 -1
- package/build/theme/features/theme/actions/theme_actions_utils.js +20 -7
- package/build/theme/features/theme/delete/api/theme_delete_api.js +13 -0
- package/build/theme/features/theme/delete/http/theme_delete_http_api.js +17 -0
- package/build/theme/features/theme/delete/service/theme_delete_service.js +31 -0
- package/build/theme/features/theme/delete/theme_delete_constants.js +2 -0
- package/build/theme/features/theme/delete/theme_delete_initalizer.js +20 -0
- package/build/theme/features/theme/fetch/service/theme_fetch_service.js +30 -10
- package/build/theme/features/theme/info/theme_info_utils.js +9 -0
- package/build/theme/features/theme/init/service/theme_init_service.js +9 -4
- package/build/theme/features/theme/merge/api/theme_merge_api.js +0 -12
- package/build/theme/features/theme/merge/service/theme_merge_service.js +20 -28
- package/build/theme/features/theme/push/service/theme_push_service.js +92 -69
- package/build/theme/features/theme/push/theme_push_constants.js +2 -0
- package/build/theme/features/theme/push/theme_push_errors_factory.js +7 -4
- package/build/theme/features/theme/push/theme_push_initializer.js +0 -3
- package/build/theme/features/theme/push/theme_push_utils.js +25 -0
- package/build/theme/features/theme/skinstore/api/theme_skinstore_api.js +19 -0
- package/build/theme/features/theme/skinstore/http/theme_skinstore_http_api.js +17 -0
- package/build/theme/features/theme/skinstore/service/theme_skinstore_service.js +32 -0
- package/build/theme/features/theme/skinstore/theme_publish_constants.js +4 -0
- package/build/theme/features/theme/skinstore/theme_skinstore_initialzier.js +20 -0
- package/build/theme/features/theme/utils/files_structure/theme_files_structure_utils.js +40 -0
- package/build/theme/features/theme/utils/hidden_directory/hidden_directory_utils.js +32 -0
- package/build/theme/features/theme/utils/meta_data/theme_meta_data_constants.js +1 -0
- package/build/theme/features/theme/utils/meta_data/theme_meta_data_error_factory.js +15 -0
- package/build/theme/features/theme/utils/meta_data/theme_meta_data_utils.js +39 -0
- package/build/theme/features/theme/utils/{directories → resources}/theme_resources_with_id_directory_utils.js +3 -14
- package/build/theme/features/theme/utils/theme_images_utils.js +1 -1
- package/build/theme/features/themes/list/api/themes_list_api.js +3 -0
- package/build/theme/features/themes/list/services/themes_list_service.js +13 -7
- package/build/theme/hooks/{ensure_theme_meta_data_untouched.js → ensure_theme_meta_data_untouched_hook.js} +2 -2
- package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_constants.js +1 -1
- package/build/theme/hooks/theme_checksums/{ensure_theme_current_checksums_up_to_date.js → ensure_theme_current_checksums_up_to_date_hook.js} +2 -5
- package/build/theme/hooks/themes_actions/ensure_themes_actions_hook.js +1 -0
- package/build/theme/hooks/themes_actions/ensure_themes_actions_hook_constants.js +1 -0
- package/build/theme/index.js +11 -5
- package/build/theme/utils/directory_validator/directory_validator_constants.js +2 -6
- package/build/theme/utils/directory_validator/directory_validator_utils.js +7 -25
- package/build/ui/box.js +2 -0
- package/build/ui/color_constants.js +30 -0
- package/build/ui/command.js +6 -0
- package/build/ui/file_name.js +6 -0
- package/build/ui/flag.js +6 -0
- package/build/ui/icons/error_icon.js +7 -0
- package/build/ui/icons/info_icon.js +7 -0
- package/build/ui/icons/success_icon.js +7 -0
- package/build/ui/icons/warning_icon.js +7 -0
- package/build/ui/link.js +8 -0
- package/build/ui/list/list.js +10 -0
- package/build/ui/list/list_constants.js +4 -0
- package/build/ui/list/list_item.js +11 -0
- package/build/ui/message_box/error.js +4 -0
- package/build/ui/message_box/info.js +4 -0
- package/build/ui/message_box/message_box.js +11 -0
- package/build/ui/message_box/message_box_constants.js +24 -0
- package/build/ui/message_box/success.js +4 -0
- package/build/ui/message_box/warning.js +4 -0
- package/build/ui/prompts/prompt_confirmation.js +11 -0
- package/build/ui/prompts/prompt_input.js +10 -0
- package/build/ui/table/t_cell.js +7 -0
- package/build/ui/table/t_header.js +9 -0
- package/build/ui/table/t_row.js +5 -0
- package/build/ui/table/table.js +18 -0
- package/build/ui/text.js +2 -0
- package/build/ui/tip.js +9 -0
- package/build/ui/ui_dump/ui_component_box.js +9 -0
- package/build/ui/ui_dump/ui_dump.js +53 -0
- package/build/ui/ui_dump/ui_dump_constants.js +21 -0
- package/build/ui/ui_utils.js +11 -0
- package/build/ui/validation_errors/validation_error_content.js +19 -0
- package/build/ui/validation_errors/validation_errors.js +21 -0
- package/build/ui/validation_errors/validation_errors_utils.js +17 -0
- package/build/utils/checksums/checksums_utils.js +9 -26
- package/build/utils/download_file/download_file_errors_factory.js +1 -1
- package/build/utils/download_file/download_file_utils.js +4 -2
- package/build/utils/fs/errors/stream_read_error.js +1 -1
- package/build/utils/fs/errors/stream_write_error.js +1 -1
- package/build/utils/fs/fs_utils.js +12 -1
- package/build/utils/path_utils.js +18 -2
- package/build/utils/platform_utils.js +3 -0
- package/build/utils/zip/create_zip_utils.js +1 -1
- package/build/utils/zip/errors/create_zip_error.js +1 -1
- package/build/utils/zip/errors/open_zip_error.js +1 -1
- package/oclif.config.js +2 -2
- package/package.json +13 -8
- package/build/theme/commands/theme_init_command.js +0 -53
- package/build/theme/commands/theme_list_command.js +0 -16
- package/build/theme/commands/theme_pull_command.js +0 -126
- package/build/theme/commands/theme_push_command.js +0 -65
- package/build/theme/features/theme/directory/theme_directory_utils.js +0 -76
- package/build/theme/features/theme/publish/theme_publish_constants.js +0 -2
- package/build/theme/features/theme/utils/checksums/theme_checksums_utils.js +0 -94
- /package/build/cli/{features → class}/caches/cache_factory.js +0 -0
- /package/build/cli/{features → class}/caches/json_cache/json_cache.js +0 -0
- /package/build/cli/{features → class}/caches/memory_cache.js +0 -0
- /package/build/cli/class/errors/{app_error → app}/app_error.js +0 -0
- /package/build/cli/class/errors/{app_error → app}/app_error_constants.js +0 -0
- /package/build/theme/features/theme/{publish → skinstore}/theme_publish_utils.js +0 -0
|
@@ -6,86 +6,92 @@ import { createReadStream } from 'node:fs';
|
|
|
6
6
|
import { v4 as uuid } from 'uuid';
|
|
7
7
|
import globs from 'fast-glob';
|
|
8
8
|
import { THEME_WILDCARD_ACTION_NAME } from '../../actions/service/theme_actions_service_constants.js';
|
|
9
|
-
import {
|
|
9
|
+
import { ThemeActionsUtils } from '../../actions/theme_actions_utils.js';
|
|
10
10
|
import { THEME_FILES_LIST_FILE_NAME, THEME_MODULE_SETTINGS_FILE_NAME } from '../theme_push_constants.js';
|
|
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
|
-
import { computeChecksumsFromSource } from '../../../../../utils/checksums/checksums_utils.js';
|
|
17
|
-
import { ThemeChecksumsUtils } from '../../utils/checksums/theme_checksums_utils.js';
|
|
18
16
|
import { MODULES_DIRECTORY_NAME } from '../../theme_constants.js';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { removeOldResources } from '../../../../class/fetch_resources/fetch_resources_utils.js';
|
|
19
19
|
export class ThemePushService {
|
|
20
20
|
#themePushHttpApi;
|
|
21
|
-
#themeMergeApi;
|
|
22
21
|
#themeFetchApi;
|
|
23
|
-
constructor({ themePushHttpApi,
|
|
22
|
+
constructor({ themePushHttpApi, themeFetchApi }) {
|
|
24
23
|
this.#themePushHttpApi = themePushHttpApi;
|
|
25
|
-
this.#themeMergeApi = themeMergeApi;
|
|
26
24
|
this.#themeFetchApi = themeFetchApi;
|
|
27
25
|
}
|
|
28
|
-
async push({ pushAction, filesStructure, credentials, executionContext }) {
|
|
26
|
+
async push({ pushAction, filesStructure, credentials, executionContext, themeChecksums }) {
|
|
29
27
|
const { path: tmpDir } = await tmp.dir({ unsafeCleanup: true });
|
|
30
|
-
|
|
28
|
+
const themeRootDir = executionContext.themeRootDir;
|
|
29
|
+
if (await themeChecksums.hasThemeFileBeenCreated(ThemePublishUtils.getSkinStoreSettingsFilePath(themeRootDir)))
|
|
31
30
|
throw ThemePushErrorsFactory.createErrorWhilePushingUnpublishedThemeWithSkinstoreData(credentials.shopUrl);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
try {
|
|
32
|
+
const { uploadData, localFiles } = await this._getActionDataForFilesToUpload({
|
|
33
|
+
pushAction,
|
|
34
|
+
filesStructure,
|
|
35
|
+
executionContext,
|
|
36
|
+
themeChecksums
|
|
37
|
+
});
|
|
38
|
+
if (uploadData.length) {
|
|
39
|
+
const { newFiles } = await this._uploadThemeFiles({
|
|
40
|
+
filesToUpload: uploadData,
|
|
41
|
+
credentials,
|
|
42
|
+
localFiles,
|
|
43
|
+
themeRootDir
|
|
44
|
+
});
|
|
45
|
+
await this._createAFilesListFile(themeRootDir, newFiles);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
await this._createAFilesListFile(themeRootDir, localFiles);
|
|
49
|
+
}
|
|
50
|
+
const themeArchivePath = join(tmpDir, `${uuid()}.zip`);
|
|
51
|
+
await this._createThemeArchive({
|
|
52
|
+
themeRootDir: themeRootDir,
|
|
53
|
+
filesToArchive: ThemeActionsUtils.getFilesGlobsThatMatchesActionName({
|
|
54
|
+
actionType: THEME_ACTIONS_TYPES.push,
|
|
55
|
+
actionValue: THEME_WILDCARD_ACTION_NAME,
|
|
56
|
+
filesStructure
|
|
57
|
+
}),
|
|
58
|
+
dist: themeArchivePath,
|
|
59
|
+
credentials
|
|
60
|
+
});
|
|
61
|
+
const { resources, modules } = await this._uploadThemeArchive({
|
|
62
|
+
themeArchivePath,
|
|
41
63
|
credentials,
|
|
42
|
-
|
|
43
|
-
themeRootDir: executionContext.themeRootDir
|
|
64
|
+
pushAction
|
|
44
65
|
});
|
|
66
|
+
if (modules)
|
|
67
|
+
await this._updateDataForNewCreatedModules({ modules, themeRootDir });
|
|
68
|
+
if (resources) {
|
|
69
|
+
await removeOldResources(themeRootDir, resources);
|
|
70
|
+
await this.#themeFetchApi.fetchResources(credentials.shopUrl, themeRootDir, resources);
|
|
71
|
+
}
|
|
72
|
+
await themeChecksums.updateAllChecksums();
|
|
45
73
|
}
|
|
46
|
-
|
|
47
|
-
await
|
|
74
|
+
finally {
|
|
75
|
+
await removeFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME));
|
|
48
76
|
}
|
|
49
|
-
|
|
77
|
+
}
|
|
78
|
+
async _createThemeArchive({ themeRootDir, filesToArchive, dist, credentials }) {
|
|
50
79
|
try {
|
|
51
|
-
await
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
80
|
+
const filesInThemeDirectory = await globs(filesToArchive, {
|
|
81
|
+
suppressErrors: true,
|
|
82
|
+
onlyFiles: true,
|
|
83
|
+
cwd: themeRootDir
|
|
84
|
+
});
|
|
85
|
+
await this._formatJsonFiles(themeRootDir, filesInThemeDirectory);
|
|
86
|
+
return createZip({
|
|
87
|
+
files: filesInThemeDirectory,
|
|
88
|
+
baseDir: themeRootDir,
|
|
89
|
+
dist
|
|
58
90
|
});
|
|
59
91
|
}
|
|
60
92
|
catch (err) {
|
|
61
93
|
throw ThemePushErrorsFactory.createErrorWhileCreatingThemeArchive(credentials.shopUrl, err);
|
|
62
94
|
}
|
|
63
|
-
const { resources, modules } = await this._uploadThemeArchive({
|
|
64
|
-
themeArchivePath,
|
|
65
|
-
credentials,
|
|
66
|
-
pushAction
|
|
67
|
-
});
|
|
68
|
-
if (modules)
|
|
69
|
-
await this._updateDataForNewCreatedModules({ modules, themeRootDir: executionContext.themeRootDir });
|
|
70
|
-
console.log(JSON.stringify(resources));
|
|
71
|
-
if (resources)
|
|
72
|
-
await this.#themeFetchApi.fetchResources(credentials.shopUrl, executionContext.themeRootDir, resources);
|
|
73
|
-
await removeFile(join(executionContext.themeRootDir, THEME_FILES_LIST_FILE_NAME));
|
|
74
|
-
const checksums = await computeChecksumsFromSource(executionContext.themeRootDir);
|
|
75
|
-
await ThemeChecksumsUtils.createThemeChecksumsFiles(executionContext.themeRootDir, checksums);
|
|
76
|
-
}
|
|
77
|
-
async _createThemeArchive({ themeRootDir, filesToArchive, dist }) {
|
|
78
|
-
const filesInThemeDirectory = await globs(filesToArchive, {
|
|
79
|
-
suppressErrors: true,
|
|
80
|
-
onlyFiles: true,
|
|
81
|
-
cwd: themeRootDir
|
|
82
|
-
});
|
|
83
|
-
await this._formatJsonFiles(themeRootDir, filesInThemeDirectory);
|
|
84
|
-
return createZip({
|
|
85
|
-
files: filesInThemeDirectory,
|
|
86
|
-
baseDir: themeRootDir,
|
|
87
|
-
dist
|
|
88
|
-
});
|
|
89
95
|
}
|
|
90
96
|
async _uploadThemeArchive({ themeArchivePath, credentials, pushAction }) {
|
|
91
97
|
try {
|
|
@@ -100,7 +106,6 @@ export class ThemePushService {
|
|
|
100
106
|
return response.data;
|
|
101
107
|
}
|
|
102
108
|
catch (err) {
|
|
103
|
-
console.log('error', err.response.data.messages);
|
|
104
109
|
throw ThemePushErrorsFactory.createErrorWhileUploadingTheme(credentials.shopUrl, err.response.data.messages);
|
|
105
110
|
}
|
|
106
111
|
}
|
|
@@ -109,20 +114,27 @@ export class ThemePushService {
|
|
|
109
114
|
.filter((path) => extname(path).toLowerCase() === '.json')
|
|
110
115
|
.map((jsonFile) => formatJSONFile(join(themeRootDir, jsonFile))));
|
|
111
116
|
}
|
|
117
|
+
//TODO osobna klasa do uploadu
|
|
112
118
|
async _uploadThemeFiles({ filesToUpload, themeRootDir, localFiles, credentials }) {
|
|
113
119
|
try {
|
|
114
|
-
const uploadedImageData = await this._uploadFiles(filesToUpload, credentials);
|
|
120
|
+
const { uploadedImageData, rejectedImageData } = await this._uploadFiles(filesToUpload, credentials);
|
|
115
121
|
const newFilesList = ThemeImagesUtils.updateOriginalFilenameToUploadedFilename(localFiles, uploadedImageData);
|
|
116
122
|
if (uploadedImageData.length)
|
|
117
123
|
await ThemeImagesUtils.removeUploadedOriginalFiles(themeRootDir, uploadedImageData);
|
|
118
|
-
|
|
124
|
+
if (rejectedImageData.length)
|
|
125
|
+
await this._removeUploadedThemeFiles(rejectedImageData, themeRootDir);
|
|
126
|
+
return { newFiles: newFilesList };
|
|
119
127
|
}
|
|
120
128
|
catch (err) {
|
|
121
129
|
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, err);
|
|
122
130
|
}
|
|
123
131
|
}
|
|
132
|
+
async _removeUploadedThemeFiles(uploadedImageData, themeRootDir) {
|
|
133
|
+
await Promise.all(uploadedImageData.map(({ location, originalFilename }) => removeFile(join(themeRootDir, location, originalFilename))));
|
|
134
|
+
}
|
|
124
135
|
async _uploadFiles(uploadData, credentials) {
|
|
125
136
|
const uploadedImageData = [];
|
|
137
|
+
const rejectedImageData = [];
|
|
126
138
|
await Promise.all(uploadData.map(({ actionData, path }) => this.#themePushHttpApi
|
|
127
139
|
.pushThemeData({
|
|
128
140
|
actionData,
|
|
@@ -130,22 +142,33 @@ export class ThemePushService {
|
|
|
130
142
|
shopUrl: credentials.shopUrl
|
|
131
143
|
})
|
|
132
144
|
.response.then((response) => {
|
|
133
|
-
if (response.status !== 200 || !response.data.isSuccess)
|
|
134
|
-
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, response.data?.messages ?? []);
|
|
135
145
|
uploadedImageData.push({
|
|
136
146
|
location: dirname(path),
|
|
137
147
|
originalFilename: basename(path),
|
|
138
148
|
uploadedFilename: response.data.imageId
|
|
139
149
|
});
|
|
150
|
+
})
|
|
151
|
+
.catch(() => {
|
|
152
|
+
rejectedImageData.push({
|
|
153
|
+
location: dirname(path),
|
|
154
|
+
originalFilename: basename(path)
|
|
155
|
+
});
|
|
140
156
|
})));
|
|
141
|
-
return
|
|
157
|
+
return {
|
|
158
|
+
uploadedImageData,
|
|
159
|
+
rejectedImageData
|
|
160
|
+
};
|
|
142
161
|
}
|
|
143
|
-
async _getActionDataForFilesToUpload({ pushAction, filesStructure, executionContext }) {
|
|
162
|
+
async _getActionDataForFilesToUpload({ pushAction, filesStructure, executionContext, themeChecksums }) {
|
|
144
163
|
const uploadData = [];
|
|
145
164
|
const localFiles = {};
|
|
146
165
|
for (const [actionKey, actionData] of Object.entries(pushAction.data)) {
|
|
147
166
|
if (actionData.type === THEME_ACTION_DATA_TYPE.file) {
|
|
148
|
-
const filesGlobs = getFilesGlobsThatMatchesActionName(
|
|
167
|
+
const filesGlobs = ThemeActionsUtils.getFilesGlobsThatMatchesActionName({
|
|
168
|
+
actionType: THEME_ACTIONS_TYPES.push,
|
|
169
|
+
actionValue: actionKey,
|
|
170
|
+
filesStructure
|
|
171
|
+
});
|
|
149
172
|
for (const fileGlob of filesGlobs) {
|
|
150
173
|
const files = await globs(fileGlob, {
|
|
151
174
|
suppressErrors: true,
|
|
@@ -162,8 +185,8 @@ export class ThemePushService {
|
|
|
162
185
|
localFiles[fileGlob] = files.length ? basename(files[0]) : null;
|
|
163
186
|
}
|
|
164
187
|
for (const filePath of files) {
|
|
165
|
-
if ((await
|
|
166
|
-
(await
|
|
188
|
+
if ((await themeChecksums.hasThemeFileBeenCreated(filePath)) ||
|
|
189
|
+
(await themeChecksums.hasThemeFileBeenModified(filePath))) {
|
|
167
190
|
uploadData.push({
|
|
168
191
|
actionData,
|
|
169
192
|
actionKey,
|
|
@@ -187,9 +210,9 @@ export class ThemePushService {
|
|
|
187
210
|
async _createAFilesListFile(themeRootDir, filesList) {
|
|
188
211
|
if (!filesList || !Object.keys(filesList).length)
|
|
189
212
|
return;
|
|
190
|
-
const toUnixStyleFilesList = Object.entries(filesList).reduce((acc, [
|
|
191
|
-
const unixPath = toUnixPath(
|
|
192
|
-
const finalPath = looksLikeDirectory(
|
|
213
|
+
const toUnixStyleFilesList = Object.entries(filesList).reduce((acc, [filePath, value]) => {
|
|
214
|
+
const unixPath = toUnixPath(filePath);
|
|
215
|
+
const finalPath = looksLikeDirectory(unixPath) ? `${unixPath}${path.posix.sep}` : unixPath;
|
|
193
216
|
return {
|
|
194
217
|
...acc,
|
|
195
218
|
[finalPath]: value
|
|
@@ -2,3 +2,5 @@ export const THEME_PUSH_FEATURE_NAME = 'ThemePush';
|
|
|
2
2
|
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
|
+
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,11 +1,14 @@
|
|
|
1
|
-
import { AppError } from '../../../../cli/class/errors/
|
|
1
|
+
import { AppError } from '../../../../cli/class/errors/app/app_error.js';
|
|
2
|
+
import { THEME_ARCHIVE_UPLOAD_ERROR, THEME_FILES_UPLOAD_ERROR } from './theme_push_constants.js';
|
|
2
3
|
export class ThemePushErrorsFactory {
|
|
3
4
|
static createErrorWhileUploadingThemeFiles(shopUrl, messages) {
|
|
4
5
|
return new AppError({
|
|
5
|
-
code:
|
|
6
|
+
code: THEME_FILES_UPLOAD_ERROR,
|
|
6
7
|
message: `Error while uploading theme files to shop "${shopUrl}"`,
|
|
7
8
|
level: 'error',
|
|
8
|
-
details:
|
|
9
|
+
details: {
|
|
10
|
+
messages
|
|
11
|
+
}
|
|
9
12
|
});
|
|
10
13
|
}
|
|
11
14
|
static createErrorWhileCreatingThemeArchive(shopUrl, error) {
|
|
@@ -32,7 +35,7 @@ export class ThemePushErrorsFactory {
|
|
|
32
35
|
}
|
|
33
36
|
static createErrorWhileUploadingTheme(shopUrl, messages) {
|
|
34
37
|
return new AppError({
|
|
35
|
-
code:
|
|
38
|
+
code: THEME_ARCHIVE_UPLOAD_ERROR,
|
|
36
39
|
message: `Error while uploading theme to shop "${shopUrl}"`,
|
|
37
40
|
level: 'error',
|
|
38
41
|
details: messages
|
|
@@ -3,16 +3,13 @@ import { ThemePushService } from './service/theme_push_service.js';
|
|
|
3
3
|
import { THEME_PUSH_FEATURE_NAME } from './theme_push_constants.js';
|
|
4
4
|
import { ThemePushApi } from './api/theme_push_api.js';
|
|
5
5
|
import { ThemePushHttpApi } from './http_api/theme_push_http_api.js';
|
|
6
|
-
import { THEME_MERGE_API_NAME } from '../merge/theme_merge_constants.js';
|
|
7
6
|
import { THEME_FETCH_API_NAME } from '../fetch/theme_fetch_constants.js';
|
|
8
7
|
export class ThemePushInitializer extends SyncFeatureInitializer {
|
|
9
8
|
static featureName = THEME_PUSH_FEATURE_NAME;
|
|
10
9
|
init() {
|
|
11
10
|
const httpApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
12
|
-
const themeMergeApi = this.getApiSync(THEME_MERGE_API_NAME);
|
|
13
11
|
const service = new ThemePushService({
|
|
14
12
|
themePushHttpApi: new ThemePushHttpApi(httpApi),
|
|
15
|
-
themeMergeApi,
|
|
16
13
|
themeFetchApi: this.getApiSync(THEME_FETCH_API_NAME)
|
|
17
14
|
});
|
|
18
15
|
return {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import globs from 'fast-glob';
|
|
2
|
+
import { AppError } from '../../../../cli/class/errors/app/app_error.js';
|
|
3
|
+
import { toUnixPath } from '../../../../utils/path_utils.js';
|
|
4
|
+
import { ThemeFilesStructureUtils } from '../utils/files_structure/theme_files_structure_utils.js';
|
|
5
|
+
export class ThemePushUtils {
|
|
6
|
+
static async getAllFilesThatAreSendToRemote(themeDir) {
|
|
7
|
+
const filesStructure = await ThemeFilesStructureUtils.getThemeFilesStructure(themeDir);
|
|
8
|
+
if (!filesStructure)
|
|
9
|
+
throw new AppError({
|
|
10
|
+
message: `Files structure not found in theme directory: ${themeDir}`,
|
|
11
|
+
code: 'theme_files_structure_not_found'
|
|
12
|
+
});
|
|
13
|
+
//need unix styles globs
|
|
14
|
+
const filesToArchive = Object.keys(filesStructure)
|
|
15
|
+
.map((path) => toUnixPath(path))
|
|
16
|
+
.filter((path) => path !== '*');
|
|
17
|
+
//need unix styles globs
|
|
18
|
+
filesToArchive.push('styles/src/**/*');
|
|
19
|
+
return await globs(filesToArchive, {
|
|
20
|
+
suppressErrors: true,
|
|
21
|
+
onlyFiles: true,
|
|
22
|
+
cwd: themeDir
|
|
23
|
+
}).then((files) => files.sort());
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FeatureApi } from '@dreamcommerce/star_core';
|
|
2
|
+
import { THEME_SKINSTORE_API_NAME } from '../theme_publish_constants.js';
|
|
3
|
+
export class ThemeSkinstoreApi extends FeatureApi {
|
|
4
|
+
moduleName = THEME_SKINSTORE_API_NAME;
|
|
5
|
+
#service;
|
|
6
|
+
constructor(service) {
|
|
7
|
+
super();
|
|
8
|
+
this.#service = service;
|
|
9
|
+
}
|
|
10
|
+
async getPublishFormData(props) {
|
|
11
|
+
return this.#service.getPublishFormData(props);
|
|
12
|
+
}
|
|
13
|
+
async publish(themeId) {
|
|
14
|
+
// return this.#service.publish(themeId);
|
|
15
|
+
}
|
|
16
|
+
async update() {
|
|
17
|
+
// return this.#service.update();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class ThemeSkinstoreHttpApi {
|
|
2
|
+
#httpApi;
|
|
3
|
+
constructor(httpApi) {
|
|
4
|
+
this.#httpApi = httpApi;
|
|
5
|
+
}
|
|
6
|
+
getPublishFormData({ actionData, shopUrl }) {
|
|
7
|
+
const { method, url } = actionData;
|
|
8
|
+
return this.#httpApi.fetch({
|
|
9
|
+
url: `${shopUrl}${url}`,
|
|
10
|
+
method,
|
|
11
|
+
sanitizeOptions: {
|
|
12
|
+
disable: true
|
|
13
|
+
},
|
|
14
|
+
isPrivate: true
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { STATUS_CODES } from '@dreamcommerce/star_core';
|
|
2
|
+
import { HttpErrorsFactory } from '../../../../../cli/class/errors/http/http_errors_factory.js';
|
|
3
|
+
import { DownloadFileErrorsFactory } from '../../../../../utils/download_file/download_file_errors_factory.js';
|
|
4
|
+
import { toControls } from '../../../../../cli/features/controls/controls_dto_mappers.js';
|
|
5
|
+
export class ThemeSkinstoreService {
|
|
6
|
+
#httpApi;
|
|
7
|
+
constructor(httpApi) {
|
|
8
|
+
this.#httpApi = httpApi;
|
|
9
|
+
}
|
|
10
|
+
async getPublishFormData({ credentials, actionData }) {
|
|
11
|
+
try {
|
|
12
|
+
const { response: request } = this.#httpApi.getPublishFormData({ actionData, shopUrl: credentials.shopUrl });
|
|
13
|
+
const response = await request;
|
|
14
|
+
if (response?.status !== STATUS_CODES.ok)
|
|
15
|
+
throw response;
|
|
16
|
+
return response?.data ? toControls(response.data) : [];
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
//TODO to basic class
|
|
20
|
+
switch (err.response?.status) {
|
|
21
|
+
case 403:
|
|
22
|
+
throw HttpErrorsFactory.createForbiddenError();
|
|
23
|
+
case 401:
|
|
24
|
+
throw HttpErrorsFactory.createUnauthorizedError();
|
|
25
|
+
case 404:
|
|
26
|
+
throw HttpErrorsFactory.createNotFoundError();
|
|
27
|
+
default:
|
|
28
|
+
throw DownloadFileErrorsFactory.downloadError(err.response.status);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FEATURE_CORES_TYPES, HTTP_REQUESTER_API_NAME, SyncFeatureInitializer } from '@dreamcommerce/star_core';
|
|
2
|
+
import { THEME_SKINSTORE_FEATURE_NAME } from './theme_publish_constants.js';
|
|
3
|
+
import { ThemeSkinstoreService } from './service/theme_skinstore_service.js';
|
|
4
|
+
import { ThemeSkinstoreHttpApi } from './http/theme_skinstore_http_api.js';
|
|
5
|
+
import { ThemeSkinstoreApi } from './api/theme_skinstore_api.js';
|
|
6
|
+
export class ThemeSkinstoreInitializer extends SyncFeatureInitializer {
|
|
7
|
+
static featureName = THEME_SKINSTORE_FEATURE_NAME;
|
|
8
|
+
init() {
|
|
9
|
+
const httpApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
10
|
+
const service = new ThemeSkinstoreService(new ThemeSkinstoreHttpApi(httpApi));
|
|
11
|
+
return {
|
|
12
|
+
cores: [
|
|
13
|
+
{
|
|
14
|
+
type: FEATURE_CORES_TYPES.api,
|
|
15
|
+
instance: new ThemeSkinstoreApi(service)
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readJSONFile, writeJSONFile } from '../../../../../utils/fs/fs_utils.js';
|
|
2
|
+
import { join, looksLikeDirectory, mapKeysPathsToWindowPlatform } from '../../../../../utils/path_utils.js';
|
|
3
|
+
import { SHOPER_THEME_METADATA_DIR } from '../../../../constants/directory_contstants.js';
|
|
4
|
+
import { THEME_FILES_STRUCTURE_FILE_NAME } from '../../theme_constants.js';
|
|
5
|
+
import { isWindowsOs } from '../../../../../utils/platform_utils.js';
|
|
6
|
+
import { validateDirectory } from '../../../../utils/directory_validator/directory_validator_utils.js';
|
|
7
|
+
export class ThemeFilesStructureUtils {
|
|
8
|
+
static async getThemeFilesStructure(themeDirectory) {
|
|
9
|
+
const filesStructure = await readJSONFile(join(themeDirectory, SHOPER_THEME_METADATA_DIR, THEME_FILES_STRUCTURE_FILE_NAME));
|
|
10
|
+
if (!isWindowsOs())
|
|
11
|
+
return filesStructure;
|
|
12
|
+
return mapKeysPathsToWindowPlatform(filesStructure);
|
|
13
|
+
}
|
|
14
|
+
static async writeThemeFilesStructure(themeDirectory, filesStructure) {
|
|
15
|
+
const filePath = join(themeDirectory, SHOPER_THEME_METADATA_DIR, THEME_FILES_STRUCTURE_FILE_NAME);
|
|
16
|
+
await writeJSONFile(filePath, filesStructure);
|
|
17
|
+
}
|
|
18
|
+
static async getFilesPermissions(themeDirectory) {
|
|
19
|
+
const fileStructure = await ThemeFilesStructureUtils.getThemeFilesStructure(themeDirectory);
|
|
20
|
+
return Object.entries(fileStructure).reduce((acc, [key, value]) => {
|
|
21
|
+
return {
|
|
22
|
+
...acc,
|
|
23
|
+
[key]: value.permissions
|
|
24
|
+
};
|
|
25
|
+
}, {});
|
|
26
|
+
}
|
|
27
|
+
static async validateThemeDirectoryStructure({ checksums, permissions, rootDirectory }) {
|
|
28
|
+
return await validateDirectory({
|
|
29
|
+
permissions,
|
|
30
|
+
checksums,
|
|
31
|
+
rootDirectory
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
static async getThemeRootDirectories(themeDirectory) {
|
|
35
|
+
const filesStructure = await ThemeFilesStructureUtils.getThemeFilesStructure(themeDirectory);
|
|
36
|
+
return Object.keys(filesStructure).filter((path) => {
|
|
37
|
+
return looksLikeDirectory(path);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getAllFilesNamesInside } from '../../../../../utils/fs/fs_utils.js';
|
|
2
|
+
import { THEME_CURRENT_CHECKSUMS_FILE_NAME, THEME_CURRENT_CHECKSUMS_VERITY_FILE_NAME, THEME_INITIAL_CHECKSUMS_FILE_NAME, THEME_INITIAL_CHECKSUMS_VERITY_FILE_NAME } from '../../theme_constants.js';
|
|
3
|
+
import { join } from '../../../../../utils/path_utils.js';
|
|
4
|
+
import { SHOPER_THEME_METADATA_DIR } from '../../../../constants/directory_contstants.js';
|
|
5
|
+
import { computeFileChecksum } from '../../../../../utils/checksums/checksums_utils.js';
|
|
6
|
+
import { ThemeChecksums } from '../../../../class/checksums/theme_checksums.js';
|
|
7
|
+
export class HiddenDirectoryUtils {
|
|
8
|
+
static async ensureFilesInsideThemeMetaDataDirectoryUntouched(themeDirectory) {
|
|
9
|
+
const themeMetadataPath = this.getThemeHiddenDirectoryPath(themeDirectory);
|
|
10
|
+
const themeChecksums = new ThemeChecksums(themeDirectory);
|
|
11
|
+
if (!(await themeChecksums.verify()))
|
|
12
|
+
throw new Error('Theme checksum file is not valid');
|
|
13
|
+
const filesNames = (await getAllFilesNamesInside(themeMetadataPath)).filter((fileName) => fileName !== THEME_CURRENT_CHECKSUMS_FILE_NAME &&
|
|
14
|
+
fileName !== THEME_CURRENT_CHECKSUMS_VERITY_FILE_NAME &&
|
|
15
|
+
fileName !== THEME_INITIAL_CHECKSUMS_FILE_NAME &&
|
|
16
|
+
fileName !== THEME_INITIAL_CHECKSUMS_VERITY_FILE_NAME);
|
|
17
|
+
for (const fileName of filesNames) {
|
|
18
|
+
if (fileName === THEME_CURRENT_CHECKSUMS_FILE_NAME)
|
|
19
|
+
continue;
|
|
20
|
+
const fileFullPath = join(themeMetadataPath, fileName);
|
|
21
|
+
const fileRelativePath = join(SHOPER_THEME_METADATA_DIR, fileName);
|
|
22
|
+
const currentChecksum = await computeFileChecksum(fileFullPath);
|
|
23
|
+
const initialChecksum = await themeChecksums.getInitialChecksumFromPath(fileRelativePath);
|
|
24
|
+
if (currentChecksum !== initialChecksum) {
|
|
25
|
+
throw new Error(`File ${fileName} inside theme metadata directory (${themeMetadataPath}) has been modified. You cannot modify files inside .shoper directory`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
static getThemeHiddenDirectoryPath(themeDirectory) {
|
|
30
|
+
return join(themeDirectory, SHOPER_THEME_METADATA_DIR);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const THEME_WORK_URL_MISMATCH_ERROR = 'theme.meta_data.error_work_url_mismatch';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AppError } from '../../../../../cli/class/errors/app/app_error.js';
|
|
2
|
+
import { THEME_WORK_URL_MISMATCH_ERROR } from './theme_meta_data_constants.js';
|
|
3
|
+
export class ThemeMetaDataErrorFactory {
|
|
4
|
+
static createThemeWorkUrlMismatchError(executionUrl, themeWorkUrl) {
|
|
5
|
+
return new AppError({
|
|
6
|
+
code: THEME_WORK_URL_MISMATCH_ERROR,
|
|
7
|
+
message: `Theme work URL "${themeWorkUrl}" does not match execution URL "${executionUrl}".`,
|
|
8
|
+
level: 'error',
|
|
9
|
+
details: {
|
|
10
|
+
executionUrl,
|
|
11
|
+
themeWorkUrl
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { closestFile, readJSONFile, writeJSONFile } from '../../../../../utils/fs/fs_utils.js';
|
|
2
|
+
import { SHOPER_THEME_METADATA_DIR } from '../../../../constants/directory_contstants.js';
|
|
3
|
+
import { join } from '../../../../../utils/path_utils.js';
|
|
4
|
+
import { HiddenDirectoryUtils } from '../hidden_directory/hidden_directory_utils.js';
|
|
5
|
+
import { ThemeMetaDataErrorFactory } from './theme_meta_data_error_factory.js';
|
|
6
|
+
export class ThemeMetaDataUtils {
|
|
7
|
+
static async closestThemeRootDirectory(path) {
|
|
8
|
+
return closestFile(SHOPER_THEME_METADATA_DIR, path);
|
|
9
|
+
}
|
|
10
|
+
static getThemeMetadataFilePath(themeDirectory) {
|
|
11
|
+
return join(HiddenDirectoryUtils.getThemeHiddenDirectoryPath(themeDirectory), 'metadata.json');
|
|
12
|
+
}
|
|
13
|
+
static async getThemeMetadata(themeDirectory) {
|
|
14
|
+
const filePath = this.getThemeMetadataFilePath(themeDirectory);
|
|
15
|
+
const metadataFileContent = await readJSONFile(filePath);
|
|
16
|
+
return {
|
|
17
|
+
themeId: String(metadataFileContent.skin_id)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
static async updateThemeMetadata(themeDirectory, data) {
|
|
21
|
+
const filePath = this.getThemeMetadataFilePath(themeDirectory);
|
|
22
|
+
const newData = {
|
|
23
|
+
...data,
|
|
24
|
+
skin_id: data.themeId
|
|
25
|
+
};
|
|
26
|
+
delete newData.themeId;
|
|
27
|
+
await writeJSONFile(filePath, newData);
|
|
28
|
+
}
|
|
29
|
+
static async getThemeWorkUrl(themeDirectory) {
|
|
30
|
+
const metadataFilePath = this.getThemeMetadataFilePath(themeDirectory);
|
|
31
|
+
const metadata = await readJSONFile(metadataFilePath);
|
|
32
|
+
return metadata.workUrl || '';
|
|
33
|
+
}
|
|
34
|
+
static async ensureThemeWorkUrlMatch(themeDirectory, executionWorkUrl) {
|
|
35
|
+
const metadataWorkUrl = await this.getThemeWorkUrl(themeDirectory);
|
|
36
|
+
if (metadataWorkUrl !== executionWorkUrl)
|
|
37
|
+
throw ThemeMetaDataErrorFactory.createThemeWorkUrlMismatchError(executionWorkUrl, metadataWorkUrl);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -3,12 +3,9 @@ import walkSync from 'walk-sync';
|
|
|
3
3
|
import { THEME_FILES_OPERATIONS } from '../../merge/theme_merge_constants.js';
|
|
4
4
|
import { fileExists, readJSONFile, renameFile } from '../../../../../utils/fs/fs_utils.js';
|
|
5
5
|
import { join } from '../../../../../utils/path_utils.js';
|
|
6
|
-
import
|
|
7
|
-
import fsPromises from 'node:fs/promises';
|
|
8
|
-
import { computeChecksumsFromSource } from '../../../../../utils/checksums/checksums_utils.js';
|
|
9
|
-
import { ThemeChecksumsUtils } from '../checksums/theme_checksums_utils.js';
|
|
6
|
+
import { ThemeChecksums } from '../../../../class/checksums/theme_checksums.js';
|
|
10
7
|
export class ThemeResourcesWithIdDirectoryUtils {
|
|
11
|
-
static async updateDirectoryNamesOfResourcesWithIdAccordingToLocalThemeNames(localResourcesDir,
|
|
8
|
+
static async updateDirectoryNamesOfResourcesWithIdAccordingToLocalThemeNames(localResourcesDir, remoteResourcesDir, remoteThemeDir) {
|
|
12
9
|
const localThemeTree = new FSTree({
|
|
13
10
|
entries: walkSync.entries(localResourcesDir, {
|
|
14
11
|
globs: ['*/'],
|
|
@@ -37,18 +34,10 @@ export class ThemeResourcesWithIdDirectoryUtils {
|
|
|
37
34
|
if (!remoteResourceDirectoryRelativePath)
|
|
38
35
|
continue;
|
|
39
36
|
await renameFile(join(remoteResourcesDir, remoteResourceDirectoryRelativePath), join(remoteResourcesDir, resourceDirectoryRelativePath));
|
|
40
|
-
const resultPath = join(remoteResourcesDir, resourceDirectoryRelativePath);
|
|
41
|
-
const stat = fs.lstatSync(resultPath);
|
|
42
|
-
console.log('stat', stat.isDirectory());
|
|
43
|
-
if (stat.isSymbolicLink()) {
|
|
44
|
-
console.warn(`[WARN] Renamed path became a symlink: ${resultPath}`);
|
|
45
|
-
console.warn(`Points to: ${await fsPromises.readlink(resultPath)}`);
|
|
46
|
-
}
|
|
47
37
|
/**
|
|
48
38
|
* If these become performance bottlenecks, we can consider computing checksums only for the changed directories.
|
|
49
39
|
*/
|
|
50
|
-
|
|
51
|
-
await ThemeChecksumsUtils.createThemeChecksumsFiles(remoteThemeDir, checksums);
|
|
40
|
+
await new ThemeChecksums(remoteThemeDir).updateAllChecksums();
|
|
52
41
|
}
|
|
53
42
|
}
|
|
54
43
|
static async _getResourceIdToFilePathMap(entries) {
|
|
@@ -21,7 +21,7 @@ export class ThemeImagesUtils {
|
|
|
21
21
|
}
|
|
22
22
|
static async removeUploadedOriginalFiles(themeRootDir, uploadedImagesData) {
|
|
23
23
|
await Promise.all(uploadedImagesData
|
|
24
|
-
.filter(({ originalFilename }) => Boolean(originalFilename))
|
|
24
|
+
.filter(({ originalFilename, uploadedFilename }) => Boolean(originalFilename) && Boolean(uploadedFilename))
|
|
25
25
|
.map(({ originalFilename, location }) => {
|
|
26
26
|
const originalFilePath = join(themeRootDir, location, originalFilename);
|
|
27
27
|
return removeFile(originalFilePath);
|