@shoper/cli 0.1.0-8 → 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 +5 -3
- 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 +102 -73
- 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 +5 -6
- 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 +18 -38
- 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 +17 -3
- package/build/utils/path_utils.js +20 -1
- 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 +15 -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 -124
- 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
|
@@ -1,92 +1,97 @@
|
|
|
1
1
|
import tmp from 'tmp-promise';
|
|
2
2
|
import { THEME_ACTION_DATA_TYPE, THEME_ACTIONS_TYPES } from '../../actions/theme_actions_constants.js';
|
|
3
3
|
import { createZip } from '../../../../../utils/zip/create_zip_utils.js';
|
|
4
|
-
import { basename, dirname, extname, join, looksLikeDirectory } from '../../../../../utils/path_utils.js';
|
|
4
|
+
import { basename, dirname, extname, join, looksLikeDirectory, toUnixPath } from '../../../../../utils/path_utils.js';
|
|
5
5
|
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
|
-
|
|
41
|
-
|
|
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,
|
|
42
63
|
credentials,
|
|
43
|
-
|
|
44
|
-
themeRootDir: executionContext.themeRootDir
|
|
64
|
+
pushAction
|
|
45
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();
|
|
46
73
|
}
|
|
47
|
-
|
|
48
|
-
await
|
|
74
|
+
finally {
|
|
75
|
+
await removeFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME));
|
|
49
76
|
}
|
|
50
|
-
|
|
77
|
+
}
|
|
78
|
+
async _createThemeArchive({ themeRootDir, filesToArchive, dist, credentials }) {
|
|
51
79
|
try {
|
|
52
|
-
await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
59
90
|
});
|
|
60
91
|
}
|
|
61
92
|
catch (err) {
|
|
62
93
|
throw ThemePushErrorsFactory.createErrorWhileCreatingThemeArchive(credentials.shopUrl, err);
|
|
63
94
|
}
|
|
64
|
-
const { resources, modules } = await this._uploadThemeArchive({
|
|
65
|
-
themeArchivePath,
|
|
66
|
-
credentials,
|
|
67
|
-
pushAction
|
|
68
|
-
});
|
|
69
|
-
if (modules)
|
|
70
|
-
await this._updateDataForNewCreatedModules({ modules, themeRootDir: executionContext.themeRootDir });
|
|
71
|
-
console.log('resources', resources);
|
|
72
|
-
if (resources)
|
|
73
|
-
await this.#themeFetchApi.fetchResources(credentials.shopUrl, executionContext.themeRootDir, resources);
|
|
74
|
-
await removeFile(join(executionContext.themeRootDir, THEME_FILES_LIST_FILE_NAME));
|
|
75
|
-
const checksums = await computeChecksumsFromSource(executionContext.themeRootDir);
|
|
76
|
-
await ThemeChecksumsUtils.createThemeChecksumsFiles(executionContext.themeRootDir, checksums);
|
|
77
|
-
}
|
|
78
|
-
async _createThemeArchive({ themeRootDir, filesToArchive, dist }) {
|
|
79
|
-
const filesInThemeDirectory = await globs(filesToArchive, {
|
|
80
|
-
suppressErrors: true,
|
|
81
|
-
onlyFiles: true,
|
|
82
|
-
cwd: themeRootDir
|
|
83
|
-
});
|
|
84
|
-
await this._formatJsonFiles(themeRootDir, filesInThemeDirectory);
|
|
85
|
-
return createZip({
|
|
86
|
-
files: filesInThemeDirectory,
|
|
87
|
-
baseDir: themeRootDir,
|
|
88
|
-
dist
|
|
89
|
-
});
|
|
90
95
|
}
|
|
91
96
|
async _uploadThemeArchive({ themeArchivePath, credentials, pushAction }) {
|
|
92
97
|
try {
|
|
@@ -101,7 +106,6 @@ export class ThemePushService {
|
|
|
101
106
|
return response.data;
|
|
102
107
|
}
|
|
103
108
|
catch (err) {
|
|
104
|
-
console.log('error', err.response.data.messages);
|
|
105
109
|
throw ThemePushErrorsFactory.createErrorWhileUploadingTheme(credentials.shopUrl, err.response.data.messages);
|
|
106
110
|
}
|
|
107
111
|
}
|
|
@@ -110,20 +114,27 @@ export class ThemePushService {
|
|
|
110
114
|
.filter((path) => extname(path).toLowerCase() === '.json')
|
|
111
115
|
.map((jsonFile) => formatJSONFile(join(themeRootDir, jsonFile))));
|
|
112
116
|
}
|
|
117
|
+
//TODO osobna klasa do uploadu
|
|
113
118
|
async _uploadThemeFiles({ filesToUpload, themeRootDir, localFiles, credentials }) {
|
|
114
119
|
try {
|
|
115
|
-
const uploadedImageData = await this._uploadFiles(filesToUpload, credentials);
|
|
120
|
+
const { uploadedImageData, rejectedImageData } = await this._uploadFiles(filesToUpload, credentials);
|
|
116
121
|
const newFilesList = ThemeImagesUtils.updateOriginalFilenameToUploadedFilename(localFiles, uploadedImageData);
|
|
117
122
|
if (uploadedImageData.length)
|
|
118
|
-
await ThemeImagesUtils.
|
|
119
|
-
|
|
123
|
+
await ThemeImagesUtils.removeUploadedOriginalFiles(themeRootDir, uploadedImageData);
|
|
124
|
+
if (rejectedImageData.length)
|
|
125
|
+
await this._removeUploadedThemeFiles(rejectedImageData, themeRootDir);
|
|
126
|
+
return { newFiles: newFilesList };
|
|
120
127
|
}
|
|
121
128
|
catch (err) {
|
|
122
129
|
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, err);
|
|
123
130
|
}
|
|
124
131
|
}
|
|
132
|
+
async _removeUploadedThemeFiles(uploadedImageData, themeRootDir) {
|
|
133
|
+
await Promise.all(uploadedImageData.map(({ location, originalFilename }) => removeFile(join(themeRootDir, location, originalFilename))));
|
|
134
|
+
}
|
|
125
135
|
async _uploadFiles(uploadData, credentials) {
|
|
126
136
|
const uploadedImageData = [];
|
|
137
|
+
const rejectedImageData = [];
|
|
127
138
|
await Promise.all(uploadData.map(({ actionData, path }) => this.#themePushHttpApi
|
|
128
139
|
.pushThemeData({
|
|
129
140
|
actionData,
|
|
@@ -131,22 +142,33 @@ export class ThemePushService {
|
|
|
131
142
|
shopUrl: credentials.shopUrl
|
|
132
143
|
})
|
|
133
144
|
.response.then((response) => {
|
|
134
|
-
if (response.status !== 200 || !response.data.isSuccess)
|
|
135
|
-
throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, response.data?.messages ?? []);
|
|
136
145
|
uploadedImageData.push({
|
|
137
146
|
location: dirname(path),
|
|
138
147
|
originalFilename: basename(path),
|
|
139
148
|
uploadedFilename: response.data.imageId
|
|
140
149
|
});
|
|
150
|
+
})
|
|
151
|
+
.catch(() => {
|
|
152
|
+
rejectedImageData.push({
|
|
153
|
+
location: dirname(path),
|
|
154
|
+
originalFilename: basename(path)
|
|
155
|
+
});
|
|
141
156
|
})));
|
|
142
|
-
return
|
|
157
|
+
return {
|
|
158
|
+
uploadedImageData,
|
|
159
|
+
rejectedImageData
|
|
160
|
+
};
|
|
143
161
|
}
|
|
144
|
-
async _getActionDataForFilesToUpload({ pushAction, filesStructure, executionContext }) {
|
|
162
|
+
async _getActionDataForFilesToUpload({ pushAction, filesStructure, executionContext, themeChecksums }) {
|
|
145
163
|
const uploadData = [];
|
|
146
164
|
const localFiles = {};
|
|
147
165
|
for (const [actionKey, actionData] of Object.entries(pushAction.data)) {
|
|
148
166
|
if (actionData.type === THEME_ACTION_DATA_TYPE.file) {
|
|
149
|
-
const filesGlobs = getFilesGlobsThatMatchesActionName(
|
|
167
|
+
const filesGlobs = ThemeActionsUtils.getFilesGlobsThatMatchesActionName({
|
|
168
|
+
actionType: THEME_ACTIONS_TYPES.push,
|
|
169
|
+
actionValue: actionKey,
|
|
170
|
+
filesStructure
|
|
171
|
+
});
|
|
150
172
|
for (const fileGlob of filesGlobs) {
|
|
151
173
|
const files = await globs(fileGlob, {
|
|
152
174
|
suppressErrors: true,
|
|
@@ -163,8 +185,8 @@ export class ThemePushService {
|
|
|
163
185
|
localFiles[fileGlob] = files.length ? basename(files[0]) : null;
|
|
164
186
|
}
|
|
165
187
|
for (const filePath of files) {
|
|
166
|
-
if ((await
|
|
167
|
-
(await
|
|
188
|
+
if ((await themeChecksums.hasThemeFileBeenCreated(filePath)) ||
|
|
189
|
+
(await themeChecksums.hasThemeFileBeenModified(filePath))) {
|
|
168
190
|
uploadData.push({
|
|
169
191
|
actionData,
|
|
170
192
|
actionKey,
|
|
@@ -186,9 +208,16 @@ export class ThemePushService {
|
|
|
186
208
|
}
|
|
187
209
|
}
|
|
188
210
|
async _createAFilesListFile(themeRootDir, filesList) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
211
|
+
if (!filesList || !Object.keys(filesList).length)
|
|
212
|
+
return;
|
|
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;
|
|
216
|
+
return {
|
|
217
|
+
...acc,
|
|
218
|
+
[finalPath]: value
|
|
219
|
+
};
|
|
220
|
+
}, {});
|
|
221
|
+
await writeJSONFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME), toUnixStyleFilesList);
|
|
193
222
|
}
|
|
194
223
|
}
|
|
@@ -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) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from '../../../../utils/path_utils.js';
|
|
2
|
-
import {
|
|
2
|
+
import { removeFile } from '../../../../utils/fs/fs_utils.js';
|
|
3
3
|
export class ThemeImagesUtils {
|
|
4
4
|
static updateOriginalFilenameToUploadedFilename(filesList, uploadedImageData) {
|
|
5
5
|
const newFilesList = { ...filesList };
|
|
@@ -19,13 +19,12 @@ export class ThemeImagesUtils {
|
|
|
19
19
|
});
|
|
20
20
|
return newFilesList;
|
|
21
21
|
}
|
|
22
|
-
static async
|
|
22
|
+
static async removeUploadedOriginalFiles(themeRootDir, uploadedImagesData) {
|
|
23
23
|
await Promise.all(uploadedImagesData
|
|
24
|
-
.filter(({ originalFilename }) => Boolean(originalFilename))
|
|
25
|
-
.map(({
|
|
24
|
+
.filter(({ originalFilename, uploadedFilename }) => Boolean(originalFilename) && Boolean(uploadedFilename))
|
|
25
|
+
.map(({ originalFilename, location }) => {
|
|
26
26
|
const originalFilePath = join(themeRootDir, location, originalFilename);
|
|
27
|
-
|
|
28
|
-
return renameFile(originalFilePath, newFilePath);
|
|
27
|
+
return removeFile(originalFilePath);
|
|
29
28
|
}));
|
|
30
29
|
}
|
|
31
30
|
}
|