@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.
Files changed (184) hide show
  1. package/build/cli/auth/cli_auth_errors_factory.js +1 -1
  2. package/build/cli/auth/tokens/cli_auth_tokens_errors_factory.js +1 -1
  3. package/build/cli/auth/tokens/cli_auth_tokens_initalizer.js +1 -1
  4. package/build/cli/class/base_command.js +14 -0
  5. package/build/cli/class/errors/file_system_errors_factory.js +1 -1
  6. package/build/cli/class/errors/http/http_errors_constants.js +1 -0
  7. package/build/cli/class/errors/{http_errors_factory.js → http/http_errors_factory.js} +3 -2
  8. package/build/cli/commands/auth/cli_auth_add_token_command.js +22 -19
  9. package/build/cli/commands/auth/cli_auth_commands_constants.js +3 -0
  10. package/build/cli/commands/auth/cli_auth_commands_utils.js +46 -0
  11. package/build/cli/commands/auth/cli_auth_list_tokens_command.js +19 -6
  12. package/build/cli/commands/auth/cli_auth_remove_token_command.js +37 -13
  13. package/build/cli/commands/auth/cli_auth_switch_token_command.js +20 -11
  14. package/build/cli/commands/auth/ui/invalid_token_index_error.js +11 -0
  15. package/build/cli/commands/auth/ui/missing_credentials_error.js +9 -0
  16. package/build/cli/commands/auth/ui/missing_token_index_error.js +19 -0
  17. package/build/cli/commands/cli_ui_dump_command.js +11 -0
  18. package/build/cli/commands/cli_update_command.js +13 -4
  19. package/build/cli/commands/commands_constants.js +6 -4
  20. package/build/cli/core/cli_setup.js +33 -14
  21. package/build/cli/features/controls/controls_constants.js +12 -0
  22. package/build/cli/features/controls/controls_dto_mappers.js +55 -0
  23. package/build/cli/features/controls/ui/controls_mappers.js +62 -0
  24. package/build/cli/features/controls/ui/form.js +4 -0
  25. package/build/cli/features/controls/ui/form_constants.js +7 -0
  26. package/build/cli/features/controls/validators/greater_eq_than_validator.js +5 -0
  27. package/build/cli/features/controls/validators/length_validator.js +6 -0
  28. package/build/cli/features/controls/validators/required_validator.js +5 -0
  29. package/build/cli/features/controls/validators/validator_constants.js +13 -0
  30. package/build/cli/features/execution_context/execution_context_service.js +5 -5
  31. package/build/cli/features/http_requester/http_requester_initializer.js +1 -1
  32. package/build/cli/hooks/authorization/ensure_authorization_hook.js +2 -2
  33. package/build/cli/hooks/authorization/ensure_authorization_hook_constants.js +7 -8
  34. package/build/index.js +37 -19
  35. package/build/theme/class/archive/theme_archive.js +44 -0
  36. package/build/theme/class/archive/theme_archive_errors_factory.js +11 -0
  37. package/build/theme/class/checksums/theme_checksums.js +170 -0
  38. package/build/theme/{features/theme/utils → class}/checksums/theme_checksums_error_factory.js +1 -1
  39. package/build/theme/class/checksums/theme_checksums_utils.js +17 -0
  40. package/build/theme/class/fetch_resources/fetch_resources.js +1 -0
  41. package/build/theme/class/fetch_resources/fetch_resources_errors_factory.js +1 -1
  42. package/build/theme/class/fetch_resources/fetch_resources_utils.js +4 -1
  43. package/build/theme/class/files_upload/theme_files_upload.js +61 -0
  44. package/build/theme/class/files_upload/theme_files_upload_http_api.js +23 -0
  45. package/build/theme/commands/delete/theme_delete_command.js +97 -0
  46. package/build/theme/commands/delete/ui/theme_deleted_successfully.js +15 -0
  47. package/build/theme/commands/delete/ui/theme_deletion_warning.js +10 -0
  48. package/build/theme/commands/info/theme_info_command.js +79 -0
  49. package/build/theme/commands/info/theme_info_command_utils.js +39 -0
  50. package/build/theme/commands/init/theme_init_command.js +84 -0
  51. package/build/theme/commands/init/ui/theme_created_success.js +15 -0
  52. package/build/theme/commands/list/theme_list_command.js +25 -0
  53. package/build/theme/commands/list/theme_list_command_utils.js +27 -0
  54. package/build/theme/commands/publish/theme_publish_command.js +76 -0
  55. package/build/theme/commands/pull/theme_pull_command.js +174 -0
  56. package/build/theme/commands/pull/ui/theme_pull_id_mismatch_error.js +7 -0
  57. package/build/theme/commands/pull/ui/theme_pull_unpublished_changes_warning.js +10 -0
  58. package/build/theme/commands/pull/ui/theme_pulled_success.js +5 -0
  59. package/build/theme/commands/push/theme_push_command.js +112 -0
  60. package/build/theme/commands/push/ui/theme_push_skip_into.js +7 -0
  61. package/build/theme/commands/push/ui/theme_pushed_success.js +5 -0
  62. package/build/theme/commands/push/ui/theme_unpermitted_actions_error.js +12 -0
  63. package/build/theme/commands/theme_commands_constants.js +9 -6
  64. package/build/theme/commands/theme_verify_command.js +64 -22
  65. package/build/theme/commands/ui/invalid_theme_id.js +11 -0
  66. package/build/theme/commands/ui/missing_theme_files.js +15 -0
  67. package/build/theme/commands/ui/missing_theme_id_error.js +13 -0
  68. package/build/theme/commands/ui/ouside_of_theme_directory_context_error.js +7 -0
  69. package/build/theme/commands/ui/theme_directory_context_error.js +7 -0
  70. package/build/theme/commands/ui/theme_error.js +29 -0
  71. package/build/theme/commands/ui/theme_work_url_mismatch.js +17 -0
  72. package/build/theme/commands/ui/unpermitted_command_error.js +18 -0
  73. package/build/theme/features/theme/actions/api/theme_actions_api.js +3 -0
  74. package/build/theme/features/theme/actions/service/theme_actions_service.js +15 -3
  75. package/build/theme/features/theme/actions/service/theme_actions_service_constants.js +1 -0
  76. package/build/theme/features/theme/actions/theme_actions_constants.js +5 -2
  77. package/build/theme/features/theme/actions/theme_actions_initializer.js +1 -1
  78. package/build/theme/features/theme/actions/theme_actions_utils.js +60 -7
  79. package/build/theme/features/theme/delete/api/theme_delete_api.js +13 -0
  80. package/build/theme/features/theme/delete/http/theme_delete_http_api.js +17 -0
  81. package/build/theme/features/theme/delete/service/theme_delete_service.js +31 -0
  82. package/build/theme/features/theme/delete/theme_delete_constants.js +2 -0
  83. package/build/theme/features/theme/delete/theme_delete_initalizer.js +20 -0
  84. package/build/theme/features/theme/fetch/service/theme_fetch_service.js +30 -10
  85. package/build/theme/features/theme/info/theme_info_utils.js +9 -0
  86. package/build/theme/features/theme/init/service/theme_init_service.js +9 -4
  87. package/build/theme/features/theme/init/theme_init_initializer.js +3 -3
  88. package/build/theme/features/theme/merge/api/theme_merge_api.js +0 -12
  89. package/build/theme/features/theme/merge/service/theme_merge_service.js +20 -28
  90. package/build/theme/features/theme/push/service/theme_push_service.js +67 -166
  91. package/build/theme/features/theme/push/theme_push_constants.js +2 -0
  92. package/build/theme/features/theme/push/theme_push_errors_factory.js +7 -4
  93. package/build/theme/features/theme/push/theme_push_initializer.js +1 -7
  94. package/build/theme/features/theme/push/theme_push_utils.js +25 -0
  95. package/build/theme/features/theme/skinstore/api/theme_skinstore_api.js +19 -0
  96. package/build/theme/features/theme/skinstore/http/theme_skinstore_http_api.js +17 -0
  97. package/build/theme/features/theme/skinstore/service/theme_skinstore_service.js +32 -0
  98. package/build/theme/features/theme/skinstore/theme_publish_constants.js +4 -0
  99. package/build/theme/features/theme/skinstore/theme_skinstore_initialzier.js +20 -0
  100. package/build/theme/features/theme/utils/files_structure/theme_file_structure_errors_factory.js +10 -0
  101. package/build/theme/features/theme/utils/files_structure/theme_files_structure_utils.js +76 -0
  102. package/build/theme/features/theme/utils/hidden_directory/hidden_directory_utils.js +32 -0
  103. package/build/theme/features/theme/utils/meta_data/theme_meta_data_constants.js +1 -0
  104. package/build/theme/features/theme/utils/meta_data/theme_meta_data_error_factory.js +15 -0
  105. package/build/theme/features/theme/utils/meta_data/theme_meta_data_utils.js +39 -0
  106. package/build/theme/features/theme/utils/{directories → resources}/theme_resources_with_id_directory_utils.js +3 -14
  107. package/build/theme/features/theme/utils/theme_images_utils.js +1 -19
  108. package/build/theme/features/theme/verify/api/theme_verify_api.js +13 -0
  109. package/build/theme/features/theme/verify/http/theme_verify_http_api.js +30 -0
  110. package/build/theme/features/theme/verify/theme_verify_constants.js +2 -0
  111. package/build/theme/features/theme/verify/theme_verify_initializer.js +19 -0
  112. package/build/theme/features/theme/verify/verify/theme_verify_service.js +55 -0
  113. package/build/theme/features/themes/list/api/themes_list_api.js +3 -0
  114. package/build/theme/features/themes/list/services/themes_list_service.js +13 -7
  115. package/build/theme/hooks/{ensure_theme_meta_data_untouched.js → ensure_theme_meta_data_untouched_hook.js} +2 -2
  116. package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_constants.js +1 -2
  117. 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
  118. package/build/theme/hooks/themes_actions/ensure_themes_actions_hook.js +1 -0
  119. package/build/theme/hooks/themes_actions/ensure_themes_actions_hook_constants.js +1 -1
  120. package/build/theme/index.js +34 -8
  121. package/build/theme/utils/directory_validator/directory_validator_constants.js +2 -6
  122. package/build/theme/utils/directory_validator/directory_validator_utils.js +7 -25
  123. package/build/ui/box.js +2 -0
  124. package/build/ui/color_constants.js +30 -0
  125. package/build/ui/command.js +6 -0
  126. package/build/ui/file_name.js +6 -0
  127. package/build/ui/flag.js +6 -0
  128. package/build/ui/icons/error_icon.js +7 -0
  129. package/build/ui/icons/info_icon.js +7 -0
  130. package/build/ui/icons/success_icon.js +7 -0
  131. package/build/ui/icons/warning_icon.js +7 -0
  132. package/build/ui/link.js +8 -0
  133. package/build/ui/list/list.js +10 -0
  134. package/build/ui/list/list_constants.js +4 -0
  135. package/build/ui/list/list_item.js +11 -0
  136. package/build/ui/message_box/error.js +4 -0
  137. package/build/ui/message_box/info.js +4 -0
  138. package/build/ui/message_box/message_box.js +11 -0
  139. package/build/ui/message_box/message_box_constants.js +24 -0
  140. package/build/ui/message_box/success.js +4 -0
  141. package/build/ui/message_box/warning.js +4 -0
  142. package/build/ui/prompts/prompt_confirmation.js +11 -0
  143. package/build/ui/prompts/prompt_input.js +10 -0
  144. package/build/ui/table/t_cell.js +7 -0
  145. package/build/ui/table/t_header.js +9 -0
  146. package/build/ui/table/t_row.js +5 -0
  147. package/build/ui/table/table.js +18 -0
  148. package/build/ui/text.js +2 -0
  149. package/build/ui/tip.js +9 -0
  150. package/build/ui/ui_dump/ui_component_box.js +9 -0
  151. package/build/ui/ui_dump/ui_dump.js +53 -0
  152. package/build/ui/ui_dump/ui_dump_constants.js +21 -0
  153. package/build/ui/ui_utils.js +11 -0
  154. package/build/ui/validation_errors/validation_error_content.js +19 -0
  155. package/build/ui/validation_errors/validation_errors.js +21 -0
  156. package/build/ui/validation_errors/validation_errors_utils.js +17 -0
  157. package/build/utils/checksums/checksums_utils.js +9 -26
  158. package/build/utils/download_file/download_file_errors_factory.js +1 -1
  159. package/build/utils/download_file/download_file_utils.js +4 -2
  160. package/build/utils/fs/errors/stream_read_error.js +1 -1
  161. package/build/utils/fs/errors/stream_write_error.js +1 -1
  162. package/build/utils/fs/fs_utils.js +12 -1
  163. package/build/utils/path_utils.js +18 -2
  164. package/build/utils/platform_utils.js +3 -0
  165. package/build/utils/zip/create_zip_utils.js +1 -1
  166. package/build/utils/zip/errors/create_zip_error.js +1 -1
  167. package/build/utils/zip/errors/open_zip_error.js +1 -1
  168. package/oclif.config.js +3 -3
  169. package/package.json +14 -9
  170. package/build/cli/commands/files_diff_command.js +0 -174
  171. package/build/theme/commands/theme_init_command.js +0 -53
  172. package/build/theme/commands/theme_list_command.js +0 -16
  173. package/build/theme/commands/theme_pull_command.js +0 -126
  174. package/build/theme/commands/theme_push_command.js +0 -65
  175. package/build/theme/commands/theme_show_changes_command.js +0 -60
  176. package/build/theme/features/theme/directory/theme_directory_utils.js +0 -76
  177. package/build/theme/features/theme/publish/theme_publish_constants.js +0 -2
  178. package/build/theme/features/theme/utils/checksums/theme_checksums_utils.js +0 -94
  179. /package/build/cli/{features → class}/caches/cache_factory.js +0 -0
  180. /package/build/cli/{features → class}/caches/json_cache/json_cache.js +0 -0
  181. /package/build/cli/{features → class}/caches/memory_cache.js +0 -0
  182. /package/build/cli/class/errors/{app_error → app}/app_error.js +0 -0
  183. /package/build/cli/class/errors/{app_error → app}/app_error_constants.js +0 -0
  184. /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,4 @@
1
+ export const THEME_SKINSTORE_LOCATION = 'skinstore';
2
+ export const THEME_SKINSTORE_SETTINGS_FILE_NAME = 'settings.json';
3
+ export const THEME_SKINSTORE_API_NAME = 'ThemeSkinstoreApi';
4
+ export const THEME_SKINSTORE_FEATURE_NAME = 'ThemeSkinstore';
@@ -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,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 fs from 'node:fs';
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, localThemeDir, remoteResourcesDir, remoteThemeDir) {
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
- const checksums = await computeChecksumsFromSource(remoteThemeDir);
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,2 @@
1
+ export const THEME_VERIFY_API_NAME = 'ThemeVerifyApi';
2
+ export const THEME_VERIFY_FEATURE_NAME = 'ThemeVerify';
@@ -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
+ }
@@ -10,4 +10,7 @@ export class ThemesListApi extends FeatureApi {
10
10
  async getThemes(credentials) {
11
11
  return this.#service.getThemes(credentials);
12
12
  }
13
+ async getTheme(props) {
14
+ return this.#service.getTheme(props);
15
+ }
13
16
  }
@@ -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.httpApi = httpApi;
8
+ this.#httpApi = httpApi;
9
9
  }
10
10
  async getThemes({ shopUrl }) {
11
11
  try {
12
- const { response } = this.httpApi.getThemes(shopUrl);
13
- const { data, status } = await response;
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 { ThemeDirectoryUtils } from '../features/theme/directory/theme_directory_utils.js';
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 ThemeDirectoryUtils.ensureFilesInsideThemeMetaDataDirectoryUntouched(executionContext.themeRootDir);
10
+ await HiddenDirectoryUtils.ensureFilesInsideThemeMetaDataDirectoryUntouched(executionContext.themeRootDir);
11
11
  }
12
12
  catch (err) {
13
13
  console.error(err);
@@ -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.showChanges,
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
- const checksums = await computeChecksumsFromSource(executionContext.themeRootDir);
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
@@ -3,5 +3,5 @@ export const THEME_COMMANDS_THAT_REQUIRED_ACTIONS_LIST = [
3
3
  THEME_COMMANDS_NAME.pull,
4
4
  THEME_COMMANDS_NAME.init,
5
5
  THEME_COMMANDS_NAME.push,
6
- THEME_COMMANDS_NAME.showChanges
6
+ THEME_COMMANDS_NAME.delete
7
7
  ];
@@ -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.showChanges]: ThemeShowChangesCommand,
14
- [THEME_COMMANDS_NAME.verify]: ThemeVerifyCommand
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
- };