@shoper/cli 0.1.0-3 → 0.1.0-31

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 (228) hide show
  1. package/bin/run.js +0 -1
  2. package/build/cli/auth/api/cli_auth_api.js +16 -0
  3. package/build/cli/auth/cli_auth_constants.js +6 -0
  4. package/build/cli/auth/cli_auth_errors_factory.js +10 -0
  5. package/build/cli/auth/cli_auth_initializer.js +19 -0
  6. package/build/cli/auth/cli_auth_utils.js +22 -0
  7. package/build/cli/auth/model/cli_credentials.js +10 -0
  8. package/build/cli/auth/service/cli_auth_service.js +34 -0
  9. package/build/cli/auth/tokens/api/cli_auth_tokens_api.js +43 -0
  10. package/build/cli/auth/tokens/cli_auth_tokens_constants.js +6 -0
  11. package/build/cli/auth/tokens/cli_auth_tokens_errors_factory.js +10 -0
  12. package/build/cli/auth/tokens/cli_auth_tokens_initalizer.js +35 -0
  13. package/build/cli/auth/tokens/cli_auth_tokens_utils.js +26 -0
  14. package/build/cli/auth/tokens/service/cli_auth_tokens_service.js +86 -0
  15. package/build/cli/auth/tokens/service/cli_auth_tokens_service_constants.js +2 -0
  16. package/build/cli/class/base_cli_command.js +3 -0
  17. package/build/cli/class/errors/app/app_error.js +17 -0
  18. package/build/cli/class/errors/app/app_error_constants.js +7 -0
  19. package/build/cli/class/errors/file_system_errors_factory.js +26 -0
  20. package/build/cli/class/errors/http/http_errors_constants.js +1 -0
  21. package/build/cli/class/errors/http/http_errors_factory.js +22 -0
  22. package/build/cli/cli_constants.js +2 -0
  23. package/build/cli/commands/auth/cli_auth_add_token_command.js +35 -0
  24. package/build/cli/commands/auth/cli_auth_commands_constants.js +3 -0
  25. package/build/cli/commands/auth/cli_auth_commands_utils.js +46 -0
  26. package/build/cli/commands/auth/cli_auth_list_tokens_command.js +30 -0
  27. package/build/cli/commands/auth/cli_auth_remove_token_command.js +63 -0
  28. package/build/cli/commands/auth/cli_auth_switch_token_command.js +46 -0
  29. package/build/cli/commands/auth/ui/invalid_token_index_error.js +11 -0
  30. package/build/cli/commands/auth/ui/missing_credentials_error.js +9 -0
  31. package/build/cli/commands/auth/ui/missing_token_index_error.js +19 -0
  32. package/build/cli/commands/cli_ui_dump_command.js +11 -0
  33. package/build/cli/commands/cli_update_command.js +34 -0
  34. package/build/cli/commands/commands_constants.js +7 -2
  35. package/build/cli/commands/files_diff_command.js +174 -0
  36. package/build/cli/commands/utils/prompt_for_token_utils.js +25 -0
  37. package/build/cli/core/cli_setup.js +30 -7
  38. package/build/cli/features/caches/json_cache/json_cache.js +50 -0
  39. package/build/cli/features/caches/memory_cache.js +6 -0
  40. package/build/cli/features/data_directory/api/cli_data_directory_api.js +16 -0
  41. package/build/cli/features/data_directory/cli_data_directory_constants.js +3 -0
  42. package/build/cli/features/data_directory/cli_data_directory_initializer.js +17 -0
  43. package/build/cli/features/data_directory/cli_data_directory_utils.js +17 -0
  44. package/build/cli/features/data_directory/service/cli_data_directory_service.js +15 -0
  45. package/build/cli/features/execution_context/execution_context_constants.js +1 -2
  46. package/build/cli/features/execution_context/execution_context_service.js +11 -31
  47. package/build/cli/features/http_requester/http_client.js +32 -1
  48. package/build/cli/features/version/api/cli_version_api.js +16 -0
  49. package/build/cli/features/version/cli_version_constants.js +2 -0
  50. package/build/cli/features/version/cli_version_initializer.js +17 -0
  51. package/build/cli/features/version/service/cli_version_service.js +26 -0
  52. package/build/cli/hooks/authorization/ensure_authorization_hook.js +12 -7
  53. package/build/cli/hooks/authorization/ensure_authorization_hook_constants.js +8 -5
  54. package/build/cli/hooks/ensure_cli_initialized_hook.js +12 -0
  55. package/build/index.js +56 -4
  56. package/build/theme/class/checksums/theme_checksums.js +174 -0
  57. package/build/theme/class/checksums/theme_checksums_error_factory.js +10 -0
  58. package/build/theme/class/checksums/theme_checksums_utils.js +17 -0
  59. package/build/theme/class/fetch_resources/fetch_resources.js +127 -0
  60. package/build/theme/class/fetch_resources/fetch_resources_constants.js +2 -0
  61. package/build/theme/class/fetch_resources/fetch_resources_errors_factory.js +11 -0
  62. package/build/theme/class/fetch_resources/fetch_resources_utils.js +35 -0
  63. package/build/theme/commands/delete/theme_delete_command.js +111 -0
  64. package/build/theme/commands/delete/ui/theme_deleted_successfully.js +15 -0
  65. package/build/theme/commands/delete/ui/theme_deletion_warning.js +10 -0
  66. package/build/theme/commands/info/theme_info_command.js +94 -0
  67. package/build/theme/commands/info/theme_info_command_utils.js +39 -0
  68. package/build/theme/commands/init/theme_init_command.js +97 -0
  69. package/build/theme/commands/init/ui/theme_created_success.js +15 -0
  70. package/build/theme/commands/list/theme_list_command.js +25 -0
  71. package/build/theme/commands/list/theme_list_command_utils.js +27 -0
  72. package/build/theme/commands/pull/theme_pull_command.js +192 -0
  73. package/build/theme/commands/pull/ui/theme_pull_id_mismatch_error.js +7 -0
  74. package/build/theme/commands/pull/ui/theme_pull_unpublished_changes_warning.js +10 -0
  75. package/build/theme/commands/pull/ui/theme_pulled_success.js +5 -0
  76. package/build/theme/commands/push/theme_push_command.js +134 -0
  77. package/build/theme/commands/push/ui/theme_push_skip_into.js +7 -0
  78. package/build/theme/commands/push/ui/theme_pushed_success.js +5 -0
  79. package/build/theme/commands/push/ui/theme_unpermitted_actions_error.js +12 -0
  80. package/build/theme/commands/theme_commands_constants.js +10 -0
  81. package/build/theme/commands/theme_show_changes_command.js +61 -0
  82. package/build/theme/commands/theme_verify_command.js +44 -0
  83. package/build/theme/commands/ui/invalid_theme_id.js +11 -0
  84. package/build/theme/commands/ui/missing_theme_files.js +15 -0
  85. package/build/theme/commands/ui/missing_theme_id_error.js +13 -0
  86. package/build/theme/commands/ui/ouside_of_theme_directory_context_error.js +7 -0
  87. package/build/theme/commands/ui/theme_directory_context_error.js +7 -0
  88. package/build/theme/commands/ui/theme_work_url_mismatch.js +17 -0
  89. package/build/theme/commands/ui/unpermitted_command_error.js +18 -0
  90. package/build/theme/features/theme/actions/api/theme_actions_api.js +22 -0
  91. package/build/theme/features/theme/actions/service/theme_actions_service.js +104 -0
  92. package/build/theme/features/theme/actions/service/theme_actions_service_constants.js +3 -0
  93. package/build/theme/features/theme/actions/theme_actions_constants.js +17 -0
  94. package/build/theme/features/theme/actions/theme_actions_initializer.js +27 -0
  95. package/build/theme/features/theme/actions/theme_actions_utils.js +11 -0
  96. package/build/theme/features/theme/delete/api/theme_delete_api.js +13 -0
  97. package/build/theme/features/theme/delete/http/theme_delete_http_api.js +17 -0
  98. package/build/theme/features/theme/delete/service/theme_delete_service.js +31 -0
  99. package/build/theme/features/theme/delete/theme_delete_constants.js +2 -0
  100. package/build/theme/features/theme/delete/theme_delete_initalizer.js +20 -0
  101. package/build/theme/features/theme/fetch/api/theme_fetch_api.js +16 -0
  102. package/build/theme/features/theme/fetch/http/theme_fetch_http_api.js +18 -0
  103. package/build/theme/features/theme/fetch/service/theme_fetch_service.js +132 -0
  104. package/build/theme/features/theme/fetch/theme_fetch_constants.js +7 -0
  105. package/build/theme/features/theme/fetch/theme_fetch_initializer.js +23 -0
  106. package/build/theme/features/theme/info/theme_info_utils.js +9 -0
  107. package/build/theme/features/theme/init/api/theme_init_api.js +13 -0
  108. package/build/theme/features/theme/init/http/theme_init_http_api.js +18 -0
  109. package/build/theme/features/theme/init/service/theme_init_service.js +33 -0
  110. package/build/theme/features/theme/init/theme_init_constants.js +2 -0
  111. package/build/theme/features/theme/init/theme_init_initializer.js +22 -0
  112. package/build/theme/features/theme/merge/api/theme_merge_api.js +16 -0
  113. package/build/theme/features/theme/merge/service/theme_merge_service.js +42 -0
  114. package/build/theme/features/theme/merge/theme_merge_constants.js +9 -0
  115. package/build/theme/features/theme/merge/theme_merge_initializer.js +18 -0
  116. package/build/theme/features/theme/push/api/theme_push_api.js +13 -0
  117. package/build/theme/features/theme/push/http_api/theme_push_http_api.js +21 -0
  118. package/build/theme/features/theme/push/service/theme_push_service.js +205 -0
  119. package/build/theme/features/theme/push/service/theme_push_service_constants.js +1 -0
  120. package/build/theme/features/theme/push/theme_push_constants.js +6 -0
  121. package/build/theme/features/theme/push/theme_push_errors_factory.js +44 -0
  122. package/build/theme/features/theme/push/theme_push_initializer.js +24 -0
  123. package/build/theme/features/theme/push/theme_push_utils.js +25 -0
  124. package/build/theme/features/theme/skinstore/api/theme_skinstore_api.js +17 -0
  125. package/build/theme/features/theme/skinstore/http/theme_skinstore_http_api.js +7 -0
  126. package/build/theme/features/theme/skinstore/service/theme_skinstore_service.js +3 -0
  127. package/build/theme/features/theme/skinstore/theme_publish_constants.js +2 -0
  128. package/build/theme/features/theme/skinstore/theme_publish_utils.js +7 -0
  129. package/build/theme/features/theme/theme_constants.js +6 -0
  130. package/build/theme/features/theme/utils/files_structure/theme_files_structure_utils.js +34 -0
  131. package/build/theme/features/theme/utils/hidden_directory/hidden_directory_utils.js +32 -0
  132. package/build/theme/features/theme/utils/meta_data/theme_meta_data_constants.js +1 -0
  133. package/build/theme/features/theme/utils/meta_data/theme_meta_data_error_factory.js +15 -0
  134. package/build/theme/features/theme/utils/meta_data/theme_meta_data_utils.js +39 -0
  135. package/build/theme/features/theme/utils/resources/theme_resources_with_id_directory_utils.js +69 -0
  136. package/build/theme/features/theme/utils/theme_images_utils.js +30 -0
  137. package/build/theme/features/themes/list/api/themes_list_api.js +16 -0
  138. package/build/theme/features/themes/{http/shoper_themes_http_api.js → list/http/themes_list_http_api.js} +3 -2
  139. package/build/theme/features/themes/{model/theme_metadata.js → list/model/theme_list_metadata.js} +3 -1
  140. package/build/theme/features/themes/list/services/themes_list_service.js +43 -0
  141. package/build/theme/features/themes/list/themes_list_constants.js +2 -0
  142. package/build/theme/features/themes/list/themes_list_initializer.js +20 -0
  143. package/build/theme/hooks/ensure_theme_meta_data_untouched_hook.js +17 -0
  144. package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_constants.js +7 -0
  145. package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_hook.js +18 -0
  146. package/build/theme/hooks/themes_actions/ensure_themes_actions_hook.js +46 -0
  147. package/build/theme/hooks/themes_actions/ensure_themes_actions_hook_constants.js +7 -0
  148. package/build/theme/index.js +17 -4
  149. package/build/theme/utils/directory_validator/directory_validator_constants.js +9 -0
  150. package/build/theme/utils/directory_validator/directory_validator_utils.js +167 -0
  151. package/build/ui/box.js +2 -0
  152. package/build/ui/color_constants.js +30 -0
  153. package/build/ui/command.js +6 -0
  154. package/build/ui/file_name.js +6 -0
  155. package/build/ui/flag.js +6 -0
  156. package/build/ui/form/controls_mappers.js +39 -0
  157. package/build/ui/form/form.js +5 -0
  158. package/build/ui/form/form_constants.js +13 -0
  159. package/build/ui/icons/error_icon.js +7 -0
  160. package/build/ui/icons/info_icon.js +7 -0
  161. package/build/ui/icons/success_icon.js +7 -0
  162. package/build/ui/icons/warning_icon.js +7 -0
  163. package/build/ui/link.js +8 -0
  164. package/build/ui/list/list.js +10 -0
  165. package/build/ui/list/list_constants.js +4 -0
  166. package/build/ui/list/list_item.js +11 -0
  167. package/build/ui/message_box/error.js +4 -0
  168. package/build/ui/message_box/info.js +4 -0
  169. package/build/ui/message_box/message_box.js +11 -0
  170. package/build/ui/message_box/message_box_constants.js +24 -0
  171. package/build/ui/message_box/success.js +4 -0
  172. package/build/ui/message_box/warning.js +4 -0
  173. package/build/ui/prompts/prompt_confirmation.js +11 -0
  174. package/build/ui/prompts/prompt_input.js +10 -0
  175. package/build/ui/table/t_cell.js +7 -0
  176. package/build/ui/table/t_header.js +9 -0
  177. package/build/ui/table/t_row.js +5 -0
  178. package/build/ui/table/table.js +18 -0
  179. package/build/ui/text.js +2 -0
  180. package/build/ui/tip.js +9 -0
  181. package/build/ui/ui_dump/ui_component_box.js +9 -0
  182. package/build/ui/ui_dump/ui_dump.js +53 -0
  183. package/build/ui/ui_dump/ui_dump_constants.js +21 -0
  184. package/build/ui/ui_utils.js +11 -0
  185. package/build/ui/validation_errors/validation_error_content.js +19 -0
  186. package/build/ui/validation_errors/validation_errors.js +21 -0
  187. package/build/ui/validation_errors/validation_errors_utils.js +17 -0
  188. package/build/utils/checksums/checksums_utils.js +78 -0
  189. package/build/utils/checksums/checksums_utils_constants.js +1 -0
  190. package/build/utils/date_utils.js +3 -0
  191. package/build/utils/download_file/download_file_errors_factory.js +9 -0
  192. package/build/utils/download_file/download_file_utils.js +48 -0
  193. package/build/utils/fs/errors/stream_read_error.js +11 -0
  194. package/build/utils/fs/errors/stream_write_error.js +11 -0
  195. package/build/utils/fs/fs_utils.js +166 -0
  196. package/build/utils/http_utils.js +10 -0
  197. package/build/utils/path_utils.js +53 -0
  198. package/build/utils/platform_utils.js +3 -0
  199. package/build/utils/stream_transforms/json_indent_transform.js +21 -0
  200. package/build/utils/url_utils.js +9 -0
  201. package/build/utils/zip/create_zip_utils.js +80 -0
  202. package/build/utils/zip/errors/create_zip_error.js +11 -0
  203. package/build/utils/zip/errors/open_zip_error.js +11 -0
  204. package/build/utils/zip/extract_zip_utils.js +104 -0
  205. package/oclif.config.js +35 -0
  206. package/package.json +48 -11
  207. package/build/cli/commands/init_command.js +0 -19
  208. package/build/cli/features/cli_project/api/cli_project_api.js +0 -16
  209. package/build/cli/features/cli_project/cli_project_constants.js +0 -3
  210. package/build/cli/features/cli_project/cli_project_directory_utils.js +0 -34
  211. package/build/cli/features/cli_project/cli_project_initializer.js +0 -20
  212. package/build/cli/features/cli_project/cli_project_service.js +0 -15
  213. package/build/cli/hooks/ensure_initalized_project_hook.js +0 -1
  214. package/build/cli/hooks/migration/migration_hook.js +0 -4
  215. package/build/theme/commands/list_command.js +0 -12
  216. package/build/theme/commands/pull_command.js +0 -24
  217. package/build/theme/features/theme/directory/theme_directories_utils.js +0 -10
  218. package/build/theme/features/theme/directory/theme_directory_utils.js +0 -29
  219. package/build/theme/features/theme/pull/api/shoper_theme_pull_api.js +0 -9
  220. package/build/theme/features/theme/pull/http/shoper_theme_pull_http_api.js +0 -14
  221. package/build/theme/features/theme/pull/service/shoper_theme_pull_service.js +0 -68
  222. package/build/theme/features/theme/pull/shoper_theme_pull_initializer.js +0 -22
  223. package/build/theme/features/themes/api/shoper_themes_api.js +0 -14
  224. package/build/theme/features/themes/services/shoper_themes_service.js +0 -15
  225. package/build/theme/features/themes/shoper_themes_constants.js +0 -2
  226. package/build/theme/features/themes/shoper_themes_initalizer.js +0 -20
  227. package/build/utils/fs.js +0 -44
  228. package/build/utils/path.js +0 -13
package/bin/run.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import 'reflect-metadata';
3
2
 
4
3
  import { runCLI } from '../build/index.js';
5
4
 
@@ -0,0 +1,16 @@
1
+ import { FeatureApi } from '@dreamcommerce/star_core';
2
+ import { CLI_AUTH_API_NAME } from '../cli_auth_constants.js';
3
+ export class CliAuthApi extends FeatureApi {
4
+ moduleName = CLI_AUTH_API_NAME;
5
+ #cliAuthService;
6
+ constructor(cliAuthService) {
7
+ super();
8
+ this.#cliAuthService = cliAuthService;
9
+ }
10
+ getCredentials() {
11
+ return this.#cliAuthService.getCredentials();
12
+ }
13
+ hasCredentialsExpired() {
14
+ return this.#cliAuthService.hasCredentialsExpired();
15
+ }
16
+ }
@@ -0,0 +1,6 @@
1
+ export const CLI_AUTH_SCOPES = {
2
+ theme: 'theme',
3
+ app: 'app'
4
+ };
5
+ export const CLI_AUTH_FEATURE_NAME = 'CliAuth';
6
+ export const CLI_AUTH_API_NAME = 'CliAuthApi';
@@ -0,0 +1,10 @@
1
+ import { AppError } from '../class/errors/app/app_error.js';
2
+ export class CliAuthErrorsFactory {
3
+ static createCredentialNotFoundError() {
4
+ return new AppError({
5
+ code: 'cli_auth.credential_not_found',
6
+ message: 'Credential not found',
7
+ level: 'error'
8
+ });
9
+ }
10
+ }
@@ -0,0 +1,19 @@
1
+ import { FEATURE_CORES_TYPES, SyncFeatureInitializer } from '@dreamcommerce/star_core';
2
+ import { CliAuthService } from './service/cli_auth_service.js';
3
+ import { CliAuthApi } from './api/cli_auth_api.js';
4
+ import { CLI_AUTH_TOKENS_API_NAME } from './tokens/cli_auth_tokens_constants.js';
5
+ import { CLI_AUTH_FEATURE_NAME } from './cli_auth_constants.js';
6
+ export class CliAuthInitializer extends SyncFeatureInitializer {
7
+ static featureName = CLI_AUTH_FEATURE_NAME;
8
+ init() {
9
+ const cliAuthTokensApi = this.getApiSync(CLI_AUTH_TOKENS_API_NAME);
10
+ return {
11
+ cores: [
12
+ {
13
+ type: FEATURE_CORES_TYPES.api,
14
+ instance: new CliAuthApi(new CliAuthService(cliAuthTokensApi))
15
+ }
16
+ ]
17
+ };
18
+ }
19
+ }
@@ -0,0 +1,22 @@
1
+ import { CLI_AUTH_SCOPES } from './cli_auth_constants.js';
2
+ export class CliAuthUtils {
3
+ static checkCredentials(credentialsApi, command) {
4
+ const credentials = credentialsApi.getCredentials();
5
+ if (!credentials)
6
+ return false;
7
+ if (credentialsApi.hasCredentialsExpired()) {
8
+ console.log('Credentials are expired, please reauthorize');
9
+ return false;
10
+ }
11
+ return CliAuthUtils.ensureScopeAccessRights(credentials.scopes, command.id);
12
+ }
13
+ // We assume for now that scopes names are same as topics names
14
+ static ensureScopeAccessRights(tokenScopes, commandId) {
15
+ if (!CliAuthUtils.isScopedCommand(Object.values(CLI_AUTH_SCOPES), commandId))
16
+ return true;
17
+ return CliAuthUtils.isScopedCommand(tokenScopes, commandId);
18
+ }
19
+ static isScopedCommand(scopes, commandId) {
20
+ return scopes.some((scope) => commandId.includes(scope));
21
+ }
22
+ }
@@ -0,0 +1,10 @@
1
+ export class CliCredentials {
2
+ shopUrl;
3
+ scopes;
4
+ expires;
5
+ constructor({ shopUrl, scopes, expires }) {
6
+ this.expires = expires;
7
+ this.shopUrl = shopUrl;
8
+ this.scopes = scopes;
9
+ }
10
+ }
@@ -0,0 +1,34 @@
1
+ import { CliCredentials } from '../model/cli_credentials.js';
2
+ import { CliAuthErrorsFactory } from '../cli_auth_errors_factory.js';
3
+ export class CliAuthService {
4
+ #cliAuthTokensApi;
5
+ #credentials = null;
6
+ constructor(cliAuthTokensApi) {
7
+ this.#cliAuthTokensApi = cliAuthTokensApi;
8
+ this._setCredentials();
9
+ }
10
+ _setCredentials() {
11
+ const defaultTokenPayload = this.#cliAuthTokensApi.getDefaultTokenPayload();
12
+ if (!defaultTokenPayload)
13
+ return;
14
+ this.#credentials = new CliCredentials({
15
+ shopUrl: defaultTokenPayload.iss,
16
+ scopes: defaultTokenPayload.scope.split(';'),
17
+ expires: defaultTokenPayload.exp
18
+ });
19
+ }
20
+ getCredentials() {
21
+ if (this.#credentials)
22
+ return this.#credentials;
23
+ this._setCredentials();
24
+ return this.#credentials;
25
+ }
26
+ hasCredentialsExpired() {
27
+ if (!this.#credentials)
28
+ throw CliAuthErrorsFactory.createCredentialNotFoundError();
29
+ const defaultTokenIndex = this.#cliAuthTokensApi.getDefaultTokenIndex();
30
+ if (!defaultTokenIndex)
31
+ return true;
32
+ return this.#cliAuthTokensApi.hasTokenExpired(defaultTokenIndex);
33
+ }
34
+ }
@@ -0,0 +1,43 @@
1
+ import { CLI_AUTH_TOKENS_API_NAME } from '../cli_auth_tokens_constants.js';
2
+ import { FeatureApi } from '@dreamcommerce/star_core';
3
+ export class CliAuthTokensApi extends FeatureApi {
4
+ moduleName = CLI_AUTH_TOKENS_API_NAME;
5
+ #service;
6
+ constructor(service) {
7
+ super();
8
+ this.#service = service;
9
+ }
10
+ addToken(token) {
11
+ this.#service.addToken(token);
12
+ }
13
+ removeToken(index) {
14
+ this.#service.removeToken(index);
15
+ }
16
+ setDefaultToken(index) {
17
+ this.#service.setDefaultToken(index);
18
+ }
19
+ getTokenPayload(index) {
20
+ return this.#service.getTokenPayload(index);
21
+ }
22
+ hasToken(index) {
23
+ return this.#service.hasToken(index);
24
+ }
25
+ getAllTokensPayloads() {
26
+ return this.#service.getAllTokensPayloads();
27
+ }
28
+ getDefaultTokenIndex() {
29
+ return this.#service.getDefaultTokenIndex();
30
+ }
31
+ getDefaultToken() {
32
+ return this.#service.getDefaultToken();
33
+ }
34
+ getDefaultTokenPayload() {
35
+ return this.#service.getDefaultTokenPayload();
36
+ }
37
+ hasTokenExpired(index) {
38
+ return this.#service.hasTokenExpired(index);
39
+ }
40
+ getTokensCount() {
41
+ return this.#service.getTokensCount();
42
+ }
43
+ }
@@ -0,0 +1,6 @@
1
+ export const CLI_AUTH_TOKENS_API_NAME = 'CliAuthTokensApi';
2
+ export const CLI_AUTH_TOKENS_FEATURE_NAME = 'CliAuthTokens';
3
+ export const CLI_AUTH_TOKENS_TYPES = {
4
+ jwt: 'jwt'
5
+ };
6
+ export const CLI_AUTH_TOKENS_FILE_NAME = 'credentials';
@@ -0,0 +1,10 @@
1
+ import { AppError } from '../../class/errors/app/app_error.js';
2
+ export class CliAuthTokensErrorsFactory {
3
+ static createTokenNotFoundError(index) {
4
+ return new AppError({
5
+ code: 'cli_auth_tokens.token_not_found',
6
+ message: `Token with index "${index}" not found`,
7
+ level: 'error'
8
+ });
9
+ }
10
+ }
@@ -0,0 +1,35 @@
1
+ import { FEATURE_CORES_TYPES, SyncFeatureInitializer } from '@dreamcommerce/star_core';
2
+ import { CliAuthTokensApi } from './api/cli_auth_tokens_api.js';
3
+ import { CLiAuthTokensService } from './service/cli_auth_tokens_service.js';
4
+ import { CLI_AUTH_TOKENS_FEATURE_NAME, CLI_AUTH_TOKENS_FILE_NAME } from './cli_auth_tokens_constants.js';
5
+ import { CLI_DATA_DIRECTORY_API_NAME } from '../../features/data_directory/cli_data_directory_constants.js';
6
+ import { JsonCache } from '../../features/caches/json_cache/json_cache.js';
7
+ // schema
8
+ // {
9
+ // default: string;
10
+ // tokens: {
11
+ // [key: string]: {
12
+ // type: string;
13
+ // token: string;
14
+ // expires: string;
15
+ // }
16
+ // }
17
+ export class CliAuthTokensInitializer extends SyncFeatureInitializer {
18
+ static featureName = CLI_AUTH_TOKENS_FEATURE_NAME;
19
+ init() {
20
+ const cliDataDirectoryApi = this.getApiSync(CLI_DATA_DIRECTORY_API_NAME);
21
+ const tokensStore = new JsonCache({
22
+ path: cliDataDirectoryApi.getDataDirectoryFullPath(),
23
+ configFileMode: 0o600,
24
+ name: CLI_AUTH_TOKENS_FILE_NAME
25
+ });
26
+ return {
27
+ cores: [
28
+ {
29
+ type: FEATURE_CORES_TYPES.api,
30
+ instance: new CliAuthTokensApi(new CLiAuthTokensService(tokensStore))
31
+ }
32
+ ]
33
+ };
34
+ }
35
+ }
@@ -0,0 +1,26 @@
1
+ import jwt from 'jsonwebtoken';
2
+ export class CLiAuthTokensUtils {
3
+ static getTokenPayload(token) {
4
+ try {
5
+ return jwt.decode(token);
6
+ }
7
+ catch (err) {
8
+ console.error('Error decoding token:', err);
9
+ throw new Error('Invalid token');
10
+ }
11
+ }
12
+ static getTokenName(token) {
13
+ const payload = this.getTokenPayload(token);
14
+ const tokenName = payload?.name;
15
+ if (!tokenName) {
16
+ throw new Error('Token name not found in payload');
17
+ }
18
+ return tokenName;
19
+ }
20
+ static hasTokenExpired(token) {
21
+ const tokenPayload = CLiAuthTokensUtils.getTokenPayload(token);
22
+ if (!tokenPayload)
23
+ return true;
24
+ return tokenPayload.exp - Math.floor(Date.now() / 1000) < 0;
25
+ }
26
+ }
@@ -0,0 +1,86 @@
1
+ import { CLI_AUTH_TOKENS_TYPES } from '../cli_auth_tokens_constants.js';
2
+ import { CLiAuthTokensUtils } from '../cli_auth_tokens_utils.js';
3
+ import { CLI_AUTH_DEFAULT_TOKEN_NAME, CLI_AUTH_TOKENS_KEY } from './cli_auth_tokens_service_constants.js';
4
+ import { CliAuthTokensErrorsFactory } from '../cli_auth_tokens_errors_factory.js';
5
+ export class CLiAuthTokensService {
6
+ #tokensStore;
7
+ constructor(tokensStore) {
8
+ this.#tokensStore = tokensStore;
9
+ }
10
+ addToken(token) {
11
+ const tokeItem = {
12
+ token,
13
+ type: CLI_AUTH_TOKENS_TYPES.jwt
14
+ };
15
+ const tokens = this._getTokenItems() ?? [];
16
+ tokens.push(tokeItem);
17
+ this._setTokens(tokens);
18
+ }
19
+ hasToken(index) {
20
+ return index <= this.getTokensCount();
21
+ }
22
+ removeToken(index) {
23
+ if (!this.hasToken(index))
24
+ return;
25
+ const tokens = this._getTokenItems();
26
+ const newTokens = tokens.filter((_, currIndex) => currIndex !== index - 1);
27
+ this._setTokens(newTokens);
28
+ }
29
+ getDefaultTokenPayload() {
30
+ const defaultTokenIndex = this.getDefaultTokenIndex();
31
+ if (!defaultTokenIndex)
32
+ return null;
33
+ return this.getTokenPayload(defaultTokenIndex);
34
+ }
35
+ getDefaultTokenIndex() {
36
+ return this.#tokensStore.get(CLI_AUTH_DEFAULT_TOKEN_NAME);
37
+ }
38
+ getTokenPayload(index) {
39
+ const tokenItem = this._getTokenItem(index - 1);
40
+ if (!tokenItem)
41
+ return null;
42
+ return CLiAuthTokensUtils.getTokenPayload(tokenItem.token);
43
+ }
44
+ hasTokenExpired(index) {
45
+ const tokenItem = this._getTokenItem(index - 1);
46
+ if (!tokenItem)
47
+ return true;
48
+ return CLiAuthTokensUtils.hasTokenExpired(tokenItem.token);
49
+ }
50
+ /**
51
+ * Index starts from 1
52
+ */
53
+ setDefaultToken(index) {
54
+ const tokens = this._getTokenItems();
55
+ if (tokens.length < index)
56
+ throw CliAuthTokensErrorsFactory.createTokenNotFoundError(index);
57
+ this.#tokensStore.set(CLI_AUTH_DEFAULT_TOKEN_NAME, index);
58
+ }
59
+ _getTokenItems() {
60
+ return this.#tokensStore.get(CLI_AUTH_TOKENS_KEY) ?? [];
61
+ }
62
+ _getTokenItem(index) {
63
+ const tokens = this._getTokenItems();
64
+ return tokens[index] ?? null;
65
+ }
66
+ _setTokens(tokens) {
67
+ this.#tokensStore.set(CLI_AUTH_TOKENS_KEY, tokens);
68
+ }
69
+ getTokensCount() {
70
+ const tokens = this._getTokenItems();
71
+ return tokens.length;
72
+ }
73
+ getDefaultToken() {
74
+ const defaultTokenIndex = this.getDefaultTokenIndex();
75
+ if (!defaultTokenIndex)
76
+ return null;
77
+ const tokenItem = this._getTokenItem(defaultTokenIndex - 1);
78
+ if (!tokenItem)
79
+ return null;
80
+ return tokenItem.token;
81
+ }
82
+ getAllTokensPayloads() {
83
+ const tokens = this._getTokenItems();
84
+ return tokens.map((tokenItem) => CLiAuthTokensUtils.getTokenPayload(tokenItem.token));
85
+ }
86
+ }
@@ -0,0 +1,2 @@
1
+ export const CLI_AUTH_DEFAULT_TOKEN_NAME = 'default';
2
+ export const CLI_AUTH_TOKENS_KEY = 'tokens';
@@ -0,0 +1,3 @@
1
+ import { BaseCommand } from './base_command.js';
2
+ export class BaseCliCommand extends BaseCommand {
3
+ }
@@ -0,0 +1,17 @@
1
+ import { APP_ERRORS_LEVELS } from './app_error_constants.js';
2
+ //TODO errory do zaprojektownia
3
+ export class AppError extends Error {
4
+ code;
5
+ level;
6
+ tags;
7
+ details;
8
+ stack;
9
+ constructor({ code, details, message, level = APP_ERRORS_LEVELS.error, tags, stack }) {
10
+ super(message);
11
+ this.code = code;
12
+ this.details = details;
13
+ this.level = level;
14
+ this.tags = tags;
15
+ this.stack = stack;
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ export const APP_ERRORS_LEVELS = {
2
+ fatal: 'fatal',
3
+ error: 'error',
4
+ warn: 'warn',
5
+ info: 'info',
6
+ debug: 'debug'
7
+ };
@@ -0,0 +1,26 @@
1
+ import { AppError } from './app/app_error.js';
2
+ export class FileSystemErrorsFactory {
3
+ static createDiskFullError() {
4
+ return new AppError({
5
+ code: 'file_system.disk_full',
6
+ message: 'Disk is full',
7
+ level: 'error'
8
+ });
9
+ }
10
+ static createErrorMovingFile(source, destination, err) {
11
+ return new AppError({
12
+ code: 'file_system.error_moving_file',
13
+ message: `Failed to move file from ${source} to ${destination}`,
14
+ level: 'error',
15
+ stack: err.stack
16
+ });
17
+ }
18
+ static createErrorCopyingFile(source, destination, err) {
19
+ return new AppError({
20
+ code: 'file_system.error_copying_file',
21
+ message: `Failed to copy file from ${source} to ${destination}`,
22
+ level: 'error',
23
+ stack: err.stack
24
+ });
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ export const HTTP_NOT_FOUND_ERROR_CODE = 'not_found';
@@ -0,0 +1,22 @@
1
+ import { AppError } from '../app/app_error.js';
2
+ import { HTTP_NOT_FOUND_ERROR_CODE } from './http_errors_constants.js';
3
+ export class HttpErrorsFactory {
4
+ static createUnauthorizedError() {
5
+ return new AppError({
6
+ message: 'Unauthorized',
7
+ code: 'unauthorized'
8
+ });
9
+ }
10
+ static createForbiddenError() {
11
+ return new AppError({
12
+ message: 'Forbidden',
13
+ code: 'forbidden'
14
+ });
15
+ }
16
+ static createNotFoundError() {
17
+ return new AppError({
18
+ message: 'Not found',
19
+ code: HTTP_NOT_FOUND_ERROR_CODE
20
+ });
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ export const CLI_NAME = '@shoper/cli';
2
+ export const JSON_FILE_INDENT = 4;
@@ -0,0 +1,35 @@
1
+ import { BaseCliCommand } from '../../class/base_cli_command.js';
2
+ import { CLI_AUTH_TOKENS_API_NAME } from '../../auth/tokens/cli_auth_tokens_constants.js';
3
+ import { promptInput } from '../../../ui/prompts/prompt_input.js';
4
+ import { renderOnce } from '../../../ui/ui_utils.js';
5
+ import { Success } from '../../../ui/message_box/success.js';
6
+ import { Text } from '../../../ui/text.js';
7
+ import { Box } from '../../../ui/box.js';
8
+ import { Command } from '../../../ui/command.js';
9
+ import React from 'react';
10
+ import { Error } from '../../../ui/message_box/error.js';
11
+ export class CliAuthAddTokenCommand extends BaseCliCommand {
12
+ static summary = 'Adds a new authentication token and saves it locally.';
13
+ static description = 'The added token will be set as your default authentication token.\n\nUse this when you’ve generated a token in your store panel and want to authenticate your CLI commands.';
14
+ static examples = ['<%= config.bin %> <%= command.id %>'];
15
+ async run() {
16
+ const cliAuthTokensApi = this.getApi(CLI_AUTH_TOKENS_API_NAME);
17
+ try {
18
+ const { input: token } = await promptInput('Please paste your CLI token:');
19
+ cliAuthTokensApi.addToken(token);
20
+ cliAuthTokensApi.setDefaultToken(cliAuthTokensApi.getTokensCount());
21
+ renderOnce(React.createElement(Success, null,
22
+ React.createElement(Text, null, "Token saved locally and set as your default. You can now authenticate using this token."),
23
+ React.createElement(Box, null,
24
+ React.createElement(Text, null,
25
+ "Run ",
26
+ React.createElement(Command, null, "shoper auth list-tokens"),
27
+ " to view your saved tokens."))));
28
+ }
29
+ catch (err) {
30
+ renderOnce(React.createElement(Error, { header: "Error: Failed to add token: " },
31
+ React.createElement(Box, null,
32
+ React.createElement(Text, null, err.toString()))));
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,3 @@
1
+ export const TOKEN_SCOPE_TO_DESCRIPTION = {
2
+ theme: 'Edit store themes'
3
+ };
@@ -0,0 +1,46 @@
1
+ import { Text } from '../../../ui/text.js';
2
+ import { TOKEN_SCOPE_TO_DESCRIPTION } from './cli_auth_commands_constants.js';
3
+ import { CSS_BACKGROUND_COLORS, CSS_TEXT_COLORS } from '../../../ui/color_constants.js';
4
+ import { DateUtils } from '@dreamcommerce/utilities';
5
+ import React from 'react';
6
+ export class CliAuthCommandsUtils {
7
+ static mapToTableData(data, defaultIndex, tokensApi) {
8
+ return {
9
+ headers: [
10
+ {
11
+ content: 'Index',
12
+ width: 10
13
+ },
14
+ {
15
+ content: 'Token Name',
16
+ width: 40
17
+ },
18
+ {
19
+ content: 'Store',
20
+ width: 40
21
+ },
22
+ {
23
+ content: 'Access Scope',
24
+ width: 20
25
+ },
26
+ {
27
+ content: 'Valid until',
28
+ width: 20
29
+ }
30
+ ],
31
+ rows: data.map((tokenData, index) => {
32
+ const tokenIndex = index + 1;
33
+ const isDefault = defaultIndex !== null && tokenIndex === defaultIndex;
34
+ const tokenName = isDefault ? React.createElement(Text, { bold: true }, `${tokenData.name} (Default)`) : tokenData.name;
35
+ const hasExpired = tokensApi.hasTokenExpired(tokenIndex);
36
+ return [
37
+ React.createElement(Text, { bold: isDefault }, tokenIndex),
38
+ tokenName,
39
+ React.createElement(Text, { bold: isDefault }, tokenData.iss),
40
+ TOKEN_SCOPE_TO_DESCRIPTION[tokenData.scope],
41
+ React.createElement(Text, { color: hasExpired ? CSS_TEXT_COLORS.invert : undefined, backgroundColor: hasExpired ? CSS_BACKGROUND_COLORS.danger : undefined }, DateUtils.toLocaleDate(new Date(tokenData.exp * 1000), 'pl-PL'))
42
+ ];
43
+ })
44
+ };
45
+ }
46
+ }
@@ -0,0 +1,30 @@
1
+ import { BaseCliCommand } from '../../class/base_cli_command.js';
2
+ import { CLI_AUTH_TOKENS_API_NAME } from '../../auth/tokens/cli_auth_tokens_constants.js';
3
+ import React from 'react';
4
+ import { CliAuthCommandsUtils } from './cli_auth_commands_utils.js';
5
+ import { Table } from '../../../ui/table/table.js';
6
+ import { render } from '../../../ui/ui_utils.js';
7
+ import { Box } from '../../../ui/box.js';
8
+ import { Tip } from '../../../ui/tip.js';
9
+ import { Command } from '../../../ui/command.js';
10
+ import { Text } from '../../../ui/text.js';
11
+ import { Info } from '../../../ui/message_box/info.js';
12
+ export class CliAuthListTokensCommand extends BaseCliCommand {
13
+ static summary = 'Displays a list of all authentication tokens stored locally.';
14
+ static description = 'For each token, you’ll see its name, index, assigned store URL, access scope and expiration date.\n\nUse this to review your tokens and check which one is set as the default.';
15
+ static examples = ['<%= config.bin %> <%= command.id %>'];
16
+ async run() {
17
+ const tokensApi = this.getApi(CLI_AUTH_TOKENS_API_NAME);
18
+ const tokensPayloads = tokensApi.getAllTokensPayloads();
19
+ if (!tokensPayloads.length) {
20
+ await render(React.createElement(Info, null,
21
+ React.createElement(Box, null,
22
+ React.createElement(Text, null, "No tokens found")),
23
+ React.createElement(Tip, null,
24
+ "Generate one using ",
25
+ React.createElement(Command, null, "shoper auth add-token"))));
26
+ return;
27
+ }
28
+ await render(React.createElement(Table, { data: CliAuthCommandsUtils.mapToTableData(tokensPayloads, tokensApi.getDefaultTokenIndex(), tokensApi) }));
29
+ }
30
+ }
@@ -0,0 +1,63 @@
1
+ import { BaseCliCommand } from '../../class/base_cli_command.js';
2
+ import { Args } from '@oclif/core';
3
+ import { CLI_AUTH_TOKENS_API_NAME } from '../../auth/tokens/cli_auth_tokens_constants.js';
4
+ import { renderOnce } from '../../../ui/ui_utils.js';
5
+ import { MissingTokenIndexError } from './ui/missing_token_index_error.js';
6
+ import { InvalidTokenIndexError } from './ui/invalid_token_index_error.js';
7
+ import React from 'react';
8
+ import { Text } from '../../../ui/text.js';
9
+ import { Command } from '../../../ui/command.js';
10
+ import { Box } from '../../../ui/box.js';
11
+ import { promptConfirmation } from '../../../ui/prompts/prompt_confirmation.js';
12
+ import { Info } from '../../../ui/message_box/info.js';
13
+ import { Success } from '../../../ui/message_box/success.js';
14
+ import { Warning } from '../../../ui/message_box/warning.js';
15
+ import { Error } from '../../../ui/message_box/error.js';
16
+ export class CliAuthRemoveTokenCommand extends BaseCliCommand {
17
+ static summary = 'Removes a locally saved authentication token.';
18
+ static description = 'Use this to clean up tokens you no longer need.';
19
+ static examples = [
20
+ {
21
+ description: 'Remove token with index 2',
22
+ command: '<%= config.bin %> <%= command.id %> 2'
23
+ }
24
+ ];
25
+ static args = {
26
+ index: Args.integer({
27
+ description: 'Index of the token to remove',
28
+ required: false
29
+ })
30
+ };
31
+ async run() {
32
+ const cliAuthTokensApi = this.getApi(CLI_AUTH_TOKENS_API_NAME);
33
+ const data = await this.parse(CliAuthRemoveTokenCommand);
34
+ const { args } = data;
35
+ const { index } = args;
36
+ if (!index || !cliAuthTokensApi.hasToken(index)) {
37
+ renderOnce(React.createElement(MissingTokenIndexError, { command: React.createElement(Command, null, "shoper auth remove-token [TOKEN_INDEX]") }));
38
+ return;
39
+ }
40
+ const token = cliAuthTokensApi.getTokenPayload(index);
41
+ if (!token) {
42
+ renderOnce(React.createElement(InvalidTokenIndexError, null));
43
+ return;
44
+ }
45
+ try {
46
+ renderOnce(React.createElement(Warning, { header: `Warning: This will permanently delete the token "${token.name}" assigned to "${token.iss}". This action cannot be undone.` }));
47
+ const { proceed } = await promptConfirmation('Proceed?');
48
+ if (proceed) {
49
+ cliAuthTokensApi.removeToken(index);
50
+ cliAuthTokensApi.setDefaultToken(cliAuthTokensApi.getTokensCount());
51
+ renderOnce(React.createElement(Success, { header: `Success: Token "${token.name}" has been removed.` }));
52
+ return;
53
+ }
54
+ renderOnce(React.createElement(Info, null,
55
+ React.createElement(Text, null, "Token removal was cancelled.")));
56
+ }
57
+ catch (err) {
58
+ renderOnce(React.createElement(Error, { header: "Error: Failed to remove token: " },
59
+ React.createElement(Box, null,
60
+ React.createElement(Text, null, err.toString()))));
61
+ }
62
+ }
63
+ }