@shoper/cli 0.1.0-9 → 0.2.1-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/base_command.js +14 -0
- 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 +37 -13
- package/build/cli/commands/auth/cli_auth_switch_token_command.js +20 -11
- 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 +6 -4
- package/build/cli/core/cli_setup.js +33 -14
- 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 +7 -8
- package/build/index.js +37 -19
- package/build/theme/class/archive/theme_archive.js +44 -0
- package/build/theme/class/archive/theme_archive_errors_factory.js +11 -0
- package/build/theme/class/checksums/theme_checksums.js +170 -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/class/files_upload/theme_files_upload.js +61 -0
- package/build/theme/class/files_upload/theme_files_upload_http_api.js +23 -0
- package/build/theme/commands/delete/theme_delete_command.js +97 -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 +79 -0
- package/build/theme/commands/info/theme_info_command_utils.js +39 -0
- package/build/theme/commands/init/theme_init_command.js +84 -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 +76 -0
- package/build/theme/commands/pull/theme_pull_command.js +174 -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 +112 -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 +9 -6
- package/build/theme/commands/theme_verify_command.js +64 -22
- 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_error.js +29 -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 +5 -2
- package/build/theme/features/theme/actions/theme_actions_initializer.js +1 -1
- package/build/theme/features/theme/actions/theme_actions_utils.js +60 -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/init/theme_init_initializer.js +3 -3
- 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 +67 -166
- 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 +1 -7
- 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_file_structure_errors_factory.js +10 -0
- package/build/theme/features/theme/utils/files_structure/theme_files_structure_utils.js +76 -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 -19
- package/build/theme/features/theme/verify/api/theme_verify_api.js +13 -0
- package/build/theme/features/theme/verify/http/theme_verify_http_api.js +30 -0
- package/build/theme/features/theme/verify/theme_verify_constants.js +2 -0
- package/build/theme/features/theme/verify/theme_verify_initializer.js +19 -0
- package/build/theme/features/theme/verify/verify/theme_verify_service.js +55 -0
- 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 -2
- 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 -1
- package/build/theme/index.js +34 -8
- 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 +3 -3
- package/package.json +14 -9
- package/build/cli/commands/files_diff_command.js +0 -174
- 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/commands/theme_show_changes_command.js +0 -60
- 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
|
@@ -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
|
+
}
|
package/build/theme/features/theme/utils/files_structure/theme_file_structure_errors_factory.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AppError } from '../../../../../cli/class/errors/app/app_error.js';
|
|
2
|
+
export class ThemeFileStructureErrorsFactory {
|
|
3
|
+
static createNoFilesStructureError() {
|
|
4
|
+
return new AppError({
|
|
5
|
+
code: 'theme.file_structure.no_files_structure',
|
|
6
|
+
message: 'No files structure found for the theme.',
|
|
7
|
+
level: 'error'
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { readJSONFile, removeFile, writeJSONFile } from '../../../../../utils/fs/fs_utils.js';
|
|
2
|
+
import { join, looksLikeDirectory, mapKeysPathsToWindowPlatform, toUnixPath } 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
|
+
import path from 'node:path';
|
|
8
|
+
import { THEME_FILES_LIST_FILE_NAME } from '../../push/theme_push_constants.js';
|
|
9
|
+
export class ThemeFilesStructureUtils {
|
|
10
|
+
static async getThemeFilesStructure(themeDirectory) {
|
|
11
|
+
const filesStructure = await readJSONFile(join(themeDirectory, SHOPER_THEME_METADATA_DIR, THEME_FILES_STRUCTURE_FILE_NAME));
|
|
12
|
+
if (!isWindowsOs())
|
|
13
|
+
return filesStructure;
|
|
14
|
+
return mapKeysPathsToWindowPlatform(filesStructure);
|
|
15
|
+
}
|
|
16
|
+
static async writeThemeFilesStructure(themeDirectory, filesStructure) {
|
|
17
|
+
const filePath = join(themeDirectory, SHOPER_THEME_METADATA_DIR, THEME_FILES_STRUCTURE_FILE_NAME);
|
|
18
|
+
await writeJSONFile(filePath, filesStructure);
|
|
19
|
+
}
|
|
20
|
+
static async getFilesPermissions(themeDirectory) {
|
|
21
|
+
const fileStructure = await ThemeFilesStructureUtils.getThemeFilesStructure(themeDirectory);
|
|
22
|
+
return Object.entries(fileStructure).reduce((acc, [key, value]) => {
|
|
23
|
+
return {
|
|
24
|
+
...acc,
|
|
25
|
+
[key]: value.permissions
|
|
26
|
+
};
|
|
27
|
+
}, {});
|
|
28
|
+
}
|
|
29
|
+
static async validateThemeDirectoryStructure({ checksums, permissions, rootDirectory }) {
|
|
30
|
+
return await validateDirectory({
|
|
31
|
+
permissions,
|
|
32
|
+
checksums,
|
|
33
|
+
rootDirectory
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
static async getThemeRootDirectories(themeDirectory) {
|
|
37
|
+
const filesStructure = await ThemeFilesStructureUtils.getThemeFilesStructure(themeDirectory);
|
|
38
|
+
return Object.keys(filesStructure).filter((path) => {
|
|
39
|
+
return looksLikeDirectory(path);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
static mapFilesRecordsToFilesList(filesRecords, localFileNameToUploaded = {}) {
|
|
43
|
+
return filesRecords.reduce((acc, { fileGlob, fileName }) => {
|
|
44
|
+
const name = localFileNameToUploaded[fileName] ?? fileName;
|
|
45
|
+
if (looksLikeDirectory(fileGlob)) {
|
|
46
|
+
const existingFiles = acc[fileGlob] || [];
|
|
47
|
+
return {
|
|
48
|
+
...acc,
|
|
49
|
+
[fileGlob]: [...existingFiles, name]
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return {
|
|
54
|
+
...acc,
|
|
55
|
+
[fileGlob]: name
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}, {});
|
|
59
|
+
}
|
|
60
|
+
static async createAFilesListFile(themeRootDir, filesList) {
|
|
61
|
+
if (!filesList || !Object.keys(filesList).length)
|
|
62
|
+
return;
|
|
63
|
+
const toUnixStyleFilesList = Object.entries(filesList).reduce((acc, [filePath, value]) => {
|
|
64
|
+
const unixPath = toUnixPath(filePath);
|
|
65
|
+
const finalPath = looksLikeDirectory(unixPath) ? `${unixPath}${path.posix.sep}` : unixPath;
|
|
66
|
+
return {
|
|
67
|
+
...acc,
|
|
68
|
+
[finalPath]: value
|
|
69
|
+
};
|
|
70
|
+
}, {});
|
|
71
|
+
await writeJSONFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME), toUnixStyleFilesList);
|
|
72
|
+
}
|
|
73
|
+
static async removeAFilesListFile(themeRootDir) {
|
|
74
|
+
await removeFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -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,27 +1,9 @@
|
|
|
1
1
|
import { join } from '../../../../utils/path_utils.js';
|
|
2
2
|
import { removeFile } from '../../../../utils/fs/fs_utils.js';
|
|
3
3
|
export class ThemeImagesUtils {
|
|
4
|
-
static updateOriginalFilenameToUploadedFilename(filesList, uploadedImageData) {
|
|
5
|
-
const newFilesList = { ...filesList };
|
|
6
|
-
uploadedImageData
|
|
7
|
-
.filter(({ uploadedFilename }) => Boolean(uploadedFilename))
|
|
8
|
-
.forEach(({ originalFilename, uploadedFilename, location }) => {
|
|
9
|
-
if (typeof newFilesList[location] === 'string' && uploadedFilename) {
|
|
10
|
-
newFilesList[location] = uploadedFilename;
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (Array.isArray(newFilesList[location]) && uploadedFilename) {
|
|
14
|
-
const indexOfOriginalFilename = newFilesList[location].indexOf(originalFilename);
|
|
15
|
-
if (indexOfOriginalFilename === -1 && !uploadedFilename)
|
|
16
|
-
return;
|
|
17
|
-
newFilesList[location].splice(indexOfOriginalFilename, 1, uploadedFilename);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
return newFilesList;
|
|
21
|
-
}
|
|
22
4
|
static async removeUploadedOriginalFiles(themeRootDir, uploadedImagesData) {
|
|
23
5
|
await Promise.all(uploadedImagesData
|
|
24
|
-
.filter(({ originalFilename }) => Boolean(originalFilename))
|
|
6
|
+
.filter(({ originalFilename, uploadedFilename }) => Boolean(originalFilename) && Boolean(uploadedFilename))
|
|
25
7
|
.map(({ originalFilename, location }) => {
|
|
26
8
|
const originalFilePath = join(themeRootDir, location, originalFilename);
|
|
27
9
|
return removeFile(originalFilePath);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FeatureApi } from '@dreamcommerce/star_core';
|
|
2
|
+
import { THEME_VERIFY_API_NAME } from '../theme_verify_constants.js';
|
|
3
|
+
export class ThemeVerifyApi extends FeatureApi {
|
|
4
|
+
moduleName = THEME_VERIFY_API_NAME;
|
|
5
|
+
#service;
|
|
6
|
+
constructor(service) {
|
|
7
|
+
super();
|
|
8
|
+
this.#service = service;
|
|
9
|
+
}
|
|
10
|
+
async verifyTheme(props) {
|
|
11
|
+
return this.#service.verifyTheme(props);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class ThemeVerifyHttpApi {
|
|
2
|
+
#httpApi;
|
|
3
|
+
constructor(httpApi) {
|
|
4
|
+
this.#httpApi = httpApi;
|
|
5
|
+
}
|
|
6
|
+
verifyTheme(props) {
|
|
7
|
+
return this._verifyThemeData(props);
|
|
8
|
+
}
|
|
9
|
+
verifySkinstoreFiles(props) {
|
|
10
|
+
return this._verifyThemeData(props);
|
|
11
|
+
}
|
|
12
|
+
verifyThumbnail(props) {
|
|
13
|
+
return this._verifyThemeData(props);
|
|
14
|
+
}
|
|
15
|
+
_verifyThemeData({ actionData, shopUrl, stream }) {
|
|
16
|
+
const { method, url } = actionData;
|
|
17
|
+
return this.#httpApi.fetch({
|
|
18
|
+
url: `${shopUrl}${url}`,
|
|
19
|
+
method,
|
|
20
|
+
data: stream,
|
|
21
|
+
sanitizeOptions: {
|
|
22
|
+
disable: true
|
|
23
|
+
},
|
|
24
|
+
headers: {
|
|
25
|
+
'Content-Type': 'application/octet-stream'
|
|
26
|
+
},
|
|
27
|
+
isPrivate: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FEATURE_CORES_TYPES, HTTP_REQUESTER_API_NAME, SyncFeatureInitializer } from '@dreamcommerce/star_core';
|
|
2
|
+
import { ThemeVerifyApi } from './api/theme_verify_api.js';
|
|
3
|
+
import { THEME_VERIFY_FEATURE_NAME } from './theme_verify_constants.js';
|
|
4
|
+
import { ThemeVerifyService } from './verify/theme_verify_service.js';
|
|
5
|
+
export class ThemeVerifyInitializer extends SyncFeatureInitializer {
|
|
6
|
+
static featureName = THEME_VERIFY_FEATURE_NAME;
|
|
7
|
+
init() {
|
|
8
|
+
const httpApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
9
|
+
const service = new ThemeVerifyService();
|
|
10
|
+
return {
|
|
11
|
+
cores: [
|
|
12
|
+
{
|
|
13
|
+
type: FEATURE_CORES_TYPES.api,
|
|
14
|
+
instance: new ThemeVerifyApi(service)
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import tmp from 'tmp-promise';
|
|
2
|
+
import { ThemePublishUtils } from '../../skinstore/theme_publish_utils.js';
|
|
3
|
+
import { ThemePushErrorsFactory } from '../../push/theme_push_errors_factory.js';
|
|
4
|
+
import { join } from '../../../../../utils/path_utils.js';
|
|
5
|
+
import { v4 as uuid } from 'uuid';
|
|
6
|
+
import { ThemeArchive } from '../../../../class/archive/theme_archive.js';
|
|
7
|
+
import { THEME_WILDCARD_ACTION_NAME } from '../../actions/service/theme_actions_service_constants.js';
|
|
8
|
+
import { THEME_ACTIONS_TYPES } from '../../actions/theme_actions_constants.js';
|
|
9
|
+
import { ThemeFilesStructureUtils } from '../../utils/files_structure/theme_files_structure_utils.js';
|
|
10
|
+
import { ThemeActionsUtils } from '../../actions/theme_actions_utils.js';
|
|
11
|
+
import { ArrayUtils } from '@dreamcommerce/utilities';
|
|
12
|
+
export class ThemeVerifyService {
|
|
13
|
+
async verifyTheme({ verifyAction, executionContext, credentials, themeChecksums, filesStructure, themeFilesUploadApi }) {
|
|
14
|
+
const { path: tmpDir } = await tmp.dir({ unsafeCleanup: true });
|
|
15
|
+
const themeRootDir = executionContext.themeRootDir;
|
|
16
|
+
if (await themeChecksums.hasThemeFileBeenCreated(ThemePublishUtils.getSkinStoreSettingsFilePath(themeRootDir)))
|
|
17
|
+
throw ThemePushErrorsFactory.createErrorWhilePushingUnpublishedThemeWithSkinstoreData(credentials.shopUrl);
|
|
18
|
+
try {
|
|
19
|
+
//TODO to do api?
|
|
20
|
+
const filesRecords = await ThemeActionsUtils.getFilesRecordsFromActionData({
|
|
21
|
+
themeRootDir,
|
|
22
|
+
themeAction: verifyAction,
|
|
23
|
+
filesStructure
|
|
24
|
+
});
|
|
25
|
+
const filesToVerify = await ArrayUtils.asyncFilter(filesRecords, async ({ path }) => (await themeChecksums.hasThemeFileBeenModified(path)) || !(await themeChecksums.hasThemeFileBeenCreated(path)));
|
|
26
|
+
if (filesToVerify.length) {
|
|
27
|
+
const { rejectedImageData } = await themeFilesUploadApi.uploadFiles(filesToVerify);
|
|
28
|
+
if (rejectedImageData.length)
|
|
29
|
+
return {
|
|
30
|
+
isSuccess: false,
|
|
31
|
+
messages: rejectedImageData.flatMap((file) => file.messages)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
await this._createFilesList(themeRootDir, filesToVerify);
|
|
35
|
+
const themeArchivePath = join(tmpDir, `${uuid()}.zip`);
|
|
36
|
+
await new ThemeArchive(themeRootDir).createFullArchive({
|
|
37
|
+
dist: themeArchivePath,
|
|
38
|
+
actionValue: THEME_WILDCARD_ACTION_NAME,
|
|
39
|
+
actionType: THEME_ACTIONS_TYPES.push
|
|
40
|
+
});
|
|
41
|
+
const { isSuccess, messages } = await themeFilesUploadApi.uploadArchive({
|
|
42
|
+
action: verifyAction,
|
|
43
|
+
themeArchivePath,
|
|
44
|
+
credentials
|
|
45
|
+
});
|
|
46
|
+
return { isSuccess, messages };
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await ThemeFilesStructureUtils.removeAFilesListFile(themeRootDir);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async _createFilesList(themeRootDir, filesRecords) {
|
|
53
|
+
await ThemeFilesStructureUtils.createAFilesListFile(themeRootDir, ThemeFilesStructureUtils.mapFilesRecordsToFilesList(filesRecords));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { ThemeMetaData } from '../model/theme_list_metadata.js';
|
|
2
2
|
import { STATUS_CODES } from '@dreamcommerce/star_core';
|
|
3
|
-
import { HttpErrorsFactory } from '../../../../../cli/class/errors/http_errors_factory.js';
|
|
3
|
+
import { HttpErrorsFactory } from '../../../../../cli/class/errors/http/http_errors_factory.js';
|
|
4
4
|
import { DownloadFileErrorsFactory } from '../../../../../utils/download_file/download_file_errors_factory.js';
|
|
5
5
|
export class ThemesListService {
|
|
6
|
-
httpApi;
|
|
6
|
+
#httpApi;
|
|
7
7
|
constructor(httpApi) {
|
|
8
|
-
this
|
|
8
|
+
this.#httpApi = httpApi;
|
|
9
9
|
}
|
|
10
10
|
async getThemes({ shopUrl }) {
|
|
11
11
|
try {
|
|
12
|
-
const { response } = this
|
|
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
|
}));
|
|
@@ -34,4 +34,10 @@ export class ThemesListService {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
async getTheme({ themeId, shopUrl }) {
|
|
38
|
+
const themes = await this.getThemes({ shopUrl });
|
|
39
|
+
if (!themes)
|
|
40
|
+
return;
|
|
41
|
+
return themes.find((theme) => String(theme.skinId) === themeId);
|
|
42
|
+
}
|
|
37
43
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useApi } from '../../cli/hooks/ensure_cli_initialized_hook.js';
|
|
2
2
|
import { EXECUTION_CONTEXT_API_NAME, EXECUTION_CONTEXTS } from '../../cli/features/execution_context/execution_context_constants.js';
|
|
3
|
-
import {
|
|
3
|
+
import { HiddenDirectoryUtils } from '../features/theme/utils/hidden_directory/hidden_directory_utils.js';
|
|
4
4
|
const ensureThemeMetaDataUntouched = async () => {
|
|
5
5
|
const executionContextApi = useApi(EXECUTION_CONTEXT_API_NAME);
|
|
6
6
|
const executionContext = await executionContextApi.getExecutionContext();
|
|
7
7
|
if (executionContext.type !== EXECUTION_CONTEXTS.theme)
|
|
8
8
|
return;
|
|
9
9
|
try {
|
|
10
|
-
await
|
|
10
|
+
await HiddenDirectoryUtils.ensureFilesInsideThemeMetaDataDirectoryUntouched(executionContext.themeRootDir);
|
|
11
11
|
}
|
|
12
12
|
catch (err) {
|
|
13
13
|
console.error(err);
|
package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_constants.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { THEME_COMMANDS_NAME } from '../../commands/theme_commands_constants.js';
|
|
2
2
|
export const THEME_COMMANDS_THAT_REQUIRES_UP_TO_DATE_CHECKSUMS = [
|
|
3
3
|
THEME_COMMANDS_NAME.push,
|
|
4
|
-
THEME_COMMANDS_NAME.
|
|
5
|
-
THEME_COMMANDS_NAME.push,
|
|
4
|
+
THEME_COMMANDS_NAME.pull,
|
|
6
5
|
THEME_COMMANDS_NAME.verify
|
|
7
6
|
];
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { EXECUTION_CONTEXT_API_NAME, EXECUTION_CONTEXTS } from '../../../cli/features/execution_context/execution_context_constants.js';
|
|
2
2
|
import { useApi } from '../../../cli/hooks/ensure_cli_initialized_hook.js';
|
|
3
|
-
import { ThemeChecksumsUtils } from '../../features/theme/utils/checksums/theme_checksums_utils.js';
|
|
4
|
-
import { computeChecksumsFromSource } from '../../../utils/checksums/checksums_utils.js';
|
|
5
3
|
import { THEME_COMMANDS_THAT_REQUIRES_UP_TO_DATE_CHECKSUMS } from './ensure_theme_current_checksums_up_to_date_constants.js';
|
|
4
|
+
import { ThemeChecksums } from '../../../theme/class/checksums/theme_checksums.js';
|
|
6
5
|
export const ensureThemeChecksumsUpToDate = async ({ Command }) => {
|
|
7
|
-
console.log('Command', Command.id);
|
|
8
6
|
if (!THEME_COMMANDS_THAT_REQUIRES_UP_TO_DATE_CHECKSUMS.includes(Command.id))
|
|
9
7
|
return;
|
|
10
8
|
const executionContextApi = useApi(EXECUTION_CONTEXT_API_NAME);
|
|
@@ -15,7 +13,6 @@ export const ensureThemeChecksumsUpToDate = async ({ Command }) => {
|
|
|
15
13
|
* Naive solution, recalculate checksums every time a command based on checksums calculation is executed;
|
|
16
14
|
* If performance becomes an issue, we can implement a more sophisticated solution, eg. recalculate checksums only when files in the theme directory have changed.
|
|
17
15
|
*/
|
|
18
|
-
|
|
19
|
-
await ThemeChecksumsUtils.createThemeCurrentChecksumsFile(executionContext.themeRootDir, checksums);
|
|
16
|
+
await new ThemeChecksums(executionContext.themeRootDir).updateCurrentChecksums();
|
|
20
17
|
};
|
|
21
18
|
export default ensureThemeChecksumsUpToDate;
|
|
@@ -31,6 +31,7 @@ const ensureThemesActionsHook = async ({ Command, argv }) => {
|
|
|
31
31
|
console.error('Unauthorized. Please authorize first.');
|
|
32
32
|
const cliAuthTokensApi = useApi(CLI_AUTH_TOKENS_API_NAME);
|
|
33
33
|
await promptForToken(cliAuthTokensApi);
|
|
34
|
+
//TODO loader
|
|
34
35
|
await themesActionsApi.ensureThemesActions({
|
|
35
36
|
credentials,
|
|
36
37
|
themeId
|
package/build/theme/index.js
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
|
-
import { ThemeListCommand } from './commands/theme_list_command.js';
|
|
2
|
-
import { ThemePullCommand } from './commands/theme_pull_command.js';
|
|
3
|
-
import { ThemeInitCommand } from './commands/theme_init_command.js';
|
|
4
|
-
import { THEME_COMMANDS_NAME } from './commands/theme_commands_constants.js';
|
|
5
|
-
import { ThemePushCommand } from './commands/theme_push_command.js';
|
|
6
|
-
import { ThemeShowChangesCommand } from './commands/theme_show_changes_command.js';
|
|
1
|
+
import { ThemeListCommand } from './commands/list/theme_list_command.js';
|
|
2
|
+
import { ThemePullCommand } from './commands/pull/theme_pull_command.js';
|
|
3
|
+
import { ThemeInitCommand } from './commands/init/theme_init_command.js';
|
|
4
|
+
import { THEME_COMMANDS_NAME, THEME_TOPIC_NAME } from './commands/theme_commands_constants.js';
|
|
5
|
+
import { ThemePushCommand } from './commands/push/theme_push_command.js';
|
|
7
6
|
import { ThemeVerifyCommand } from './commands/theme_verify_command.js';
|
|
7
|
+
import { ThemeInfoCommand } from './commands/info/theme_info_command.js';
|
|
8
|
+
import { ThemeDeleteCommand } from './commands/delete/theme_delete_command.js';
|
|
9
|
+
import { ThemePublishCommand } from './commands/publish/theme_publish_command.js';
|
|
10
|
+
import { ThemesListInitializer } from './features/themes/list/themes_list_initializer.js';
|
|
11
|
+
import { ThemeMergeInitializer } from './features/theme/merge/theme_merge_initializer.js';
|
|
12
|
+
import { ThemeFetchInitializer } from './features/theme/fetch/theme_fetch_initializer.js';
|
|
13
|
+
import { ThemeInitInitializer } from './features/theme/init/theme_init_initializer.js';
|
|
14
|
+
import { ThemePushInitializer } from './features/theme/push/theme_push_initializer.js';
|
|
15
|
+
import { ThemeVerifyInitializer } from './features/theme/verify/theme_verify_initializer.js';
|
|
16
|
+
import { ThemeDeleteInitializer } from './features/theme/delete/theme_delete_initalizer.js';
|
|
17
|
+
import { ThemeActionsInitializer } from './features/theme/actions/theme_actions_initializer.js';
|
|
8
18
|
export const COMMANDS = {
|
|
9
19
|
[THEME_COMMANDS_NAME.list]: ThemeListCommand,
|
|
10
20
|
[THEME_COMMANDS_NAME.pull]: ThemePullCommand,
|
|
11
21
|
[THEME_COMMANDS_NAME.init]: ThemeInitCommand,
|
|
12
22
|
[THEME_COMMANDS_NAME.push]: ThemePushCommand,
|
|
13
|
-
[THEME_COMMANDS_NAME.
|
|
14
|
-
[THEME_COMMANDS_NAME.
|
|
23
|
+
[THEME_COMMANDS_NAME.verify]: ThemeVerifyCommand,
|
|
24
|
+
[THEME_COMMANDS_NAME.info]: ThemeInfoCommand,
|
|
25
|
+
[THEME_COMMANDS_NAME.delete]: ThemeDeleteCommand,
|
|
26
|
+
[THEME_COMMANDS_NAME.publish]: ThemePublishCommand
|
|
27
|
+
};
|
|
28
|
+
export const COMMAND_TO_FEATURES_MAP = {
|
|
29
|
+
[THEME_COMMANDS_NAME.pull]: [ThemeMergeInitializer, ThemeFetchInitializer],
|
|
30
|
+
[THEME_COMMANDS_NAME.init]: ThemeInitInitializer,
|
|
31
|
+
[THEME_COMMANDS_NAME.push]: [ThemeFetchInitializer, ThemePushInitializer],
|
|
32
|
+
[THEME_COMMANDS_NAME.verify]: ThemeVerifyInitializer,
|
|
33
|
+
[THEME_COMMANDS_NAME.delete]: ThemeDeleteInitializer
|
|
34
|
+
};
|
|
35
|
+
export const getThemeInitializersForCommand = (commandName) => {
|
|
36
|
+
if (!commandName)
|
|
37
|
+
return [];
|
|
38
|
+
const alwaysIncludedInitializers = [ThemesListInitializer, ThemeActionsInitializer];
|
|
39
|
+
const initializers = COMMAND_TO_FEATURES_MAP[`${THEME_TOPIC_NAME}:${commandName}`] ?? [];
|
|
40
|
+
return [...alwaysIncludedInitializers, ...(Array.isArray(initializers) ? initializers : [initializers])];
|
|
15
41
|
};
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
+
import { platformSeparator } from '../../../utils/path_utils.js';
|
|
1
2
|
export const FILES_MODIFICATION_TYPES = {
|
|
2
3
|
add: 'add',
|
|
3
4
|
remove: 'remove',
|
|
4
5
|
edit: 'edit'
|
|
5
6
|
};
|
|
6
7
|
export const DEFAULT_PERMISSION_FOR_ALL_FILES_KEY = '*';
|
|
7
|
-
export const DEFAULT_PERMISSION_FOR_DIRECTORY_KEY =
|
|
8
|
+
export const DEFAULT_PERMISSION_FOR_DIRECTORY_KEY = `*${platformSeparator}`;
|
|
8
9
|
export const PERMISSION_KEY = '__permission__';
|
|
9
|
-
export const DEFAULT_DIRECTORY_STRUCTURE_PERMISSION = {
|
|
10
|
-
canAdd: false,
|
|
11
|
-
canEdit: false,
|
|
12
|
-
canDelete: false
|
|
13
|
-
};
|