@shoper/cli 0.1.0-34 → 0.1.0-35

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.
@@ -0,0 +1,12 @@
1
+ export const CONTROLS_DTO_TYPES = {
2
+ text: 'text',
3
+ number: 'number',
4
+ select: 'select',
5
+ multiSelectDropDown: 'multiSelectDropDown'
6
+ };
7
+ export const CONTROLS_TYPES = {
8
+ text: 'text',
9
+ number: 'number',
10
+ select: 'select',
11
+ multiSelect: 'multiSelect'
12
+ };
@@ -1,4 +1,4 @@
1
- import { CONTROLS_TYPES } from './ui/form_constants.js';
1
+ import { CONTROLS_DTO_TYPES, CONTROLS_TYPES } from './controls_constants.js';
2
2
  export const toTextControl = ({ validators, label, isRequired, defaultValue, name }) => {
3
3
  return {
4
4
  type: CONTROLS_TYPES.text,
@@ -11,7 +11,7 @@ export const toTextControl = ({ validators, label, isRequired, defaultValue, nam
11
11
  };
12
12
  export const toNumberControl = ({ validators, label, isRequired, name }) => {
13
13
  return {
14
- type: 'number',
14
+ type: CONTROLS_TYPES.number,
15
15
  name,
16
16
  label,
17
17
  isRequired,
@@ -20,7 +20,7 @@ export const toNumberControl = ({ validators, label, isRequired, name }) => {
20
20
  };
21
21
  export const toSelectControl = ({ label, isRequired, name, options }) => {
22
22
  return {
23
- type: 'list',
23
+ type: CONTROLS_TYPES.select,
24
24
  name,
25
25
  label,
26
26
  isRequired,
@@ -28,12 +28,28 @@ export const toSelectControl = ({ label, isRequired, name, options }) => {
28
28
  };
29
29
  };
30
30
  export const toMultiSelectControl = ({ label, isRequired, name, options }) => {
31
- //TODO multiple checkboxes
32
31
  return {
33
- type: 'checkbox',
32
+ type: CONTROLS_TYPES.multiSelect,
34
33
  name,
35
34
  label,
36
35
  isRequired,
37
36
  options: options.selectOptions.map(({ label, key }) => ({ label, value: key }))
38
37
  };
39
38
  };
39
+ export const toControls = (controls) => {
40
+ return controls.map(toControl);
41
+ };
42
+ export const toControl = (control) => {
43
+ switch (control.type) {
44
+ case CONTROLS_DTO_TYPES.text:
45
+ return toTextControl(control);
46
+ case CONTROLS_DTO_TYPES.number:
47
+ return toNumberControl(control);
48
+ case CONTROLS_DTO_TYPES.select:
49
+ return toSelectControl(control);
50
+ case CONTROLS_DTO_TYPES.multiSelectDropDown:
51
+ return toMultiSelectControl(control);
52
+ default:
53
+ throw new Error(`Unknown control type`);
54
+ }
55
+ };
@@ -1,4 +1,5 @@
1
- export const toTextControl = ({ validators, label, isRequired, defaultValue, name }) => {
1
+ import { CONTROLS_TYPES } from '../controls_constants.js';
2
+ const toTextControl = ({ validators, label, isRequired, defaultValue, name }) => {
2
3
  return {
3
4
  type: 'input',
4
5
  name,
@@ -7,7 +8,7 @@ export const toTextControl = ({ validators, label, isRequired, defaultValue, nam
7
8
  validate: toInquirerValidate(validators)
8
9
  };
9
10
  };
10
- export const toNumberControl = ({ validators, label, isRequired, defaultValue, name }) => {
11
+ const toNumberControl = ({ validators, label, isRequired, defaultValue, name }) => {
11
12
  return {
12
13
  type: 'number',
13
14
  name,
@@ -16,7 +17,7 @@ export const toNumberControl = ({ validators, label, isRequired, defaultValue, n
16
17
  validate: toInquirerValidate(validators)
17
18
  };
18
19
  };
19
- export const toSelectControl = ({ validators, label, isRequired, defaultValue, name, options }) => {
20
+ const toSelectControl = ({ validators, label, isRequired, defaultValue, name, options }) => {
20
21
  return {
21
22
  type: 'list',
22
23
  name,
@@ -26,7 +27,7 @@ export const toSelectControl = ({ validators, label, isRequired, defaultValue, n
26
27
  validate: toInquirerValidate(validators)
27
28
  };
28
29
  };
29
- export const toMultiSelectControl = ({ validators, label, isRequired, defaultValue, name, options }) => {
30
+ const toMultiSelectControl = ({ validators, label, isRequired, defaultValue, name, options }) => {
30
31
  //TODO multiple checkboxes
31
32
  return {
32
33
  type: 'checkbox',
@@ -37,6 +38,23 @@ export const toMultiSelectControl = ({ validators, label, isRequired, defaultVal
37
38
  validate: toInquirerValidate(validators)
38
39
  };
39
40
  };
41
+ export const toInquirerControls = (controls) => {
42
+ return controls.map(toInquirerControl);
43
+ };
44
+ export const toInquirerControl = (control) => {
45
+ switch (control.type) {
46
+ case CONTROLS_TYPES.text:
47
+ return toTextControl(control);
48
+ case CONTROLS_TYPES.number:
49
+ return toNumberControl(control);
50
+ case CONTROLS_TYPES.select:
51
+ return toSelectControl(control);
52
+ case CONTROLS_TYPES.multiSelect:
53
+ return toMultiSelectControl(control);
54
+ default:
55
+ throw new Error(`Unknown control type`);
56
+ }
57
+ };
40
58
  export const toInquirerValidate = (validators) => {
41
59
  return (value) => {
42
60
  return validators?.find((v) => !v.isValid(value))?.getErrorMessage() ?? true;
@@ -1,5 +1,4 @@
1
1
  import inquirer from 'inquirer';
2
- import { CONTROL_TYPE_TO_MAPPERS } from './form_constants.js';
3
2
  export const Form = ({ controls, onSubmit }) => {
4
- inquirer.prompt(controls.map((control) => CONTROL_TYPE_TO_MAPPERS[control.type]?.(control))).then(onSubmit);
3
+ inquirer.prompt(controls).then(onSubmit);
5
4
  };
@@ -1,13 +1,7 @@
1
- import { toMultiSelectControl, toNumberControl, toSelectControl, toTextControl } from './controls_mappers.js';
2
- export const CONTROLS_TYPES = {
3
- text: 'text',
4
- number: 'number',
5
- select: 'select',
6
- multiSelect: 'multiSelect'
7
- };
8
- export const CONTROL_TYPE_TO_MAPPERS = {
9
- [CONTROLS_TYPES.text]: toTextControl,
10
- [CONTROLS_TYPES.number]: toNumberControl,
11
- [CONTROLS_TYPES.select]: toSelectControl,
12
- [CONTROLS_TYPES.multiSelect]: toMultiSelectControl
13
- };
1
+ export {};
2
+ // export const CONTROL_TYPE_TO_MAPPERS: Record<TControlType, Function> = {
3
+ // [CONTROLS_TYPES.text]: toTextControl,
4
+ // [CONTROLS_TYPES.number]: toNumberControl,
5
+ // [CONTROLS_TYPES.select]: toSelectControl,
6
+ // [CONTROLS_TYPES.multiSelect]: toMultiSelectControl
7
+ // };
@@ -1,7 +1,7 @@
1
1
  import { Args } from '@oclif/core';
2
2
  import { BaseThemeCommand } from '../../class/base_theme_command.js';
3
3
  import { CLI_AUTH_API_NAME } from '../../../cli/auth/cli_auth_constants.js';
4
- import { THEME_ACTION_NOT_FOUND_ERROR_CODE } from '../../features/theme/actions/theme_actions_constants.js';
4
+ import { THEME_ACTION_NOT_FOUND_ERROR_CODE, THEME_ACTIONS_API_NAME, THEME_ACTIONS_TYPES } from '../../features/theme/actions/theme_actions_constants.js';
5
5
  import { EXECUTION_CONTEXT_API_NAME, EXECUTION_CONTEXTS } from '../../../cli/features/execution_context/execution_context_constants.js';
6
6
  import { renderOnce } from '../../../ui/ui_utils.js';
7
7
  import { MissingCredentialsError } from '../../../cli/commands/auth/ui/missing_credentials_error.js';
@@ -11,6 +11,7 @@ import { Error } from '../../../ui/message_box/error.js';
11
11
  import { Text } from '../../../ui/text.js';
12
12
  import { MissingThemeIdError } from '../ui/missing_theme_id_error.js';
13
13
  import { THEME_SKINSTORE_API_NAME } from '../../features/theme/skinstore/theme_publish_constants.js';
14
+ import { Form } from '../../../cli/features/controls/ui/form.js';
14
15
  export class ThemePublishCommand extends BaseThemeCommand {
15
16
  static summary = 'Permanently deletes the specified theme from your store.';
16
17
  static description = 'This action cannot be undone, so make sure you really want to remove this theme.\n\nYou can run this command from a specific theme directory (ID not needed) or outside any theme directory (theme ID required).';
@@ -53,9 +54,23 @@ export class ThemePublishCommand extends BaseThemeCommand {
53
54
  renderOnce(React.createElement(MissingThemeIdError, null));
54
55
  return;
55
56
  }
57
+ const themeActionsApi = this.getApi(THEME_ACTIONS_API_NAME);
56
58
  const themeSkinstoreApi = this.getApi(THEME_SKINSTORE_API_NAME);
57
- const formData = await themeSkinstoreApi.getPublishFormData();
58
- console.log('formData', formData);
59
+ const pushAction = themeActionsApi.getThemeAction({
60
+ actionType: THEME_ACTIONS_TYPES.publishForm,
61
+ themeId: _themeId,
62
+ credentials
63
+ });
64
+ const controls = await themeSkinstoreApi.getPublishFormData({
65
+ actionData: pushAction.data,
66
+ credentials
67
+ });
68
+ Form({
69
+ controls,
70
+ onSubmit: (formData) => {
71
+ console.log('formData', formData);
72
+ }
73
+ });
59
74
  }
60
75
  catch (err) {
61
76
  this._handleError(err, themeId);
@@ -6,7 +6,7 @@ export const THEME_ACTIONS_TYPES = {
6
6
  push: 'push',
7
7
  pull: 'pull',
8
8
  delete: 'delete',
9
- publish_form: 'publish_form',
9
+ publishForm: 'publish_form',
10
10
  publish: 'publish'
11
11
  };
12
12
  export const THEME_ACTION_DATA_TYPE = {
@@ -25,66 +25,73 @@ export class ThemePushService {
25
25
  }
26
26
  async push({ pushAction, filesStructure, credentials, executionContext, themeChecksums }) {
27
27
  const { path: tmpDir } = await tmp.dir({ unsafeCleanup: true });
28
- if (await themeChecksums.hasThemeFileBeenCreated(ThemePublishUtils.getSkinStoreSettingsFilePath(executionContext.themeRootDir)))
28
+ const themeRootDir = executionContext.themeRootDir;
29
+ if (await themeChecksums.hasThemeFileBeenCreated(ThemePublishUtils.getSkinStoreSettingsFilePath(themeRootDir)))
29
30
  throw ThemePushErrorsFactory.createErrorWhilePushingUnpublishedThemeWithSkinstoreData(credentials.shopUrl);
30
- const { uploadData, localFiles } = await this._getActionDataForFilesToUpload({
31
- pushAction,
32
- filesStructure,
33
- executionContext,
34
- themeChecksums
35
- });
36
- if (uploadData.length) {
37
- await this._uploadThemeFiles({
38
- filesToUpload: uploadData,
39
- credentials,
40
- localFiles,
41
- themeRootDir: executionContext.themeRootDir
42
- });
43
- }
44
- else {
45
- await this._createAFilesListFile(executionContext.themeRootDir, localFiles);
46
- }
47
- const themeArchivePath = join(tmpDir, `${uuid()}.zip`);
48
31
  try {
32
+ const { uploadData, localFiles } = await this._getActionDataForFilesToUpload({
33
+ pushAction,
34
+ filesStructure,
35
+ executionContext,
36
+ themeChecksums
37
+ });
38
+ if (uploadData.length) {
39
+ const { newFiles } = await this._uploadThemeFiles({
40
+ filesToUpload: uploadData,
41
+ credentials,
42
+ localFiles,
43
+ themeRootDir
44
+ });
45
+ await this._createAFilesListFile(themeRootDir, newFiles);
46
+ }
47
+ else {
48
+ await this._createAFilesListFile(themeRootDir, localFiles);
49
+ }
50
+ const themeArchivePath = join(tmpDir, `${uuid()}.zip`);
49
51
  await this._createThemeArchive({
50
- themeRootDir: executionContext.themeRootDir,
52
+ themeRootDir: themeRootDir,
51
53
  filesToArchive: ThemeActionsUtils.getFilesGlobsThatMatchesActionName({
52
54
  actionType: THEME_ACTIONS_TYPES.push,
53
55
  actionValue: THEME_WILDCARD_ACTION_NAME,
54
56
  filesStructure
55
57
  }),
56
- dist: themeArchivePath
58
+ dist: themeArchivePath,
59
+ credentials
60
+ });
61
+ const { resources, modules } = await this._uploadThemeArchive({
62
+ themeArchivePath,
63
+ credentials,
64
+ pushAction
65
+ });
66
+ if (modules)
67
+ await this._updateDataForNewCreatedModules({ modules, themeRootDir });
68
+ if (resources) {
69
+ await removeOldResources(themeRootDir, resources);
70
+ await this.#themeFetchApi.fetchResources(credentials.shopUrl, themeRootDir, resources);
71
+ }
72
+ await themeChecksums.updateAllChecksums();
73
+ }
74
+ finally {
75
+ await removeFile(join(themeRootDir, THEME_FILES_LIST_FILE_NAME));
76
+ }
77
+ }
78
+ async _createThemeArchive({ themeRootDir, filesToArchive, dist, credentials }) {
79
+ try {
80
+ const filesInThemeDirectory = await globs(filesToArchive, {
81
+ suppressErrors: true,
82
+ onlyFiles: true,
83
+ cwd: themeRootDir
84
+ });
85
+ await this._formatJsonFiles(themeRootDir, filesInThemeDirectory);
86
+ return createZip({
87
+ files: filesInThemeDirectory,
88
+ baseDir: themeRootDir,
89
+ dist
57
90
  });
58
91
  }
59
92
  catch (err) {
60
93
  throw ThemePushErrorsFactory.createErrorWhileCreatingThemeArchive(credentials.shopUrl, err);
61
94
  }
62
- const { resources, modules } = await this._uploadThemeArchive({
63
- themeArchivePath,
64
- credentials,
65
- pushAction
66
- });
67
- if (modules)
68
- await this._updateDataForNewCreatedModules({ modules, themeRootDir: executionContext.themeRootDir });
69
- if (resources) {
70
- await removeOldResources(executionContext.themeRootDir, resources);
71
- await this.#themeFetchApi.fetchResources(credentials.shopUrl, executionContext.themeRootDir, resources);
72
- }
73
- await removeFile(join(executionContext.themeRootDir, THEME_FILES_LIST_FILE_NAME));
74
- await themeChecksums.updateAllChecksums();
75
- }
76
- async _createThemeArchive({ themeRootDir, filesToArchive, dist }) {
77
- const filesInThemeDirectory = await globs(filesToArchive, {
78
- suppressErrors: true,
79
- onlyFiles: true,
80
- cwd: themeRootDir
81
- });
82
- await this._formatJsonFiles(themeRootDir, filesInThemeDirectory);
83
- return createZip({
84
- files: filesInThemeDirectory,
85
- baseDir: themeRootDir,
86
- dist
87
- });
88
95
  }
89
96
  async _uploadThemeArchive({ themeArchivePath, credentials, pushAction }) {
90
97
  try {
@@ -116,7 +123,7 @@ export class ThemePushService {
116
123
  await ThemeImagesUtils.removeUploadedOriginalFiles(themeRootDir, uploadedImageData);
117
124
  if (rejectedImageData.length)
118
125
  await this._removeUploadedThemeFiles(rejectedImageData, themeRootDir);
119
- await this._createAFilesListFile(themeRootDir, newFilesList);
126
+ return { newFiles: newFilesList };
120
127
  }
121
128
  catch (err) {
122
129
  throw ThemePushErrorsFactory.createErrorWhileUploadingThemeFiles(credentials.shopUrl, err);
@@ -7,8 +7,8 @@ export class ThemeSkinstoreApi extends FeatureApi {
7
7
  super();
8
8
  this.#service = service;
9
9
  }
10
- async getPublishFormData() {
11
- // return this.#service.getPublishFormData();
10
+ async getPublishFormData(props) {
11
+ return this.#service.getPublishFormData(props);
12
12
  }
13
13
  async publish(themeId) {
14
14
  // return this.#service.publish(themeId);
@@ -1,6 +1,7 @@
1
1
  import { STATUS_CODES } from '@dreamcommerce/star_core';
2
2
  import { HttpErrorsFactory } from '../../../../../cli/class/errors/http/http_errors_factory.js';
3
3
  import { DownloadFileErrorsFactory } from '../../../../../utils/download_file/download_file_errors_factory.js';
4
+ import { toControls } from '../../../../../cli/features/controls/controls_dto_mappers.js';
4
5
  export class ThemeSkinstoreService {
5
6
  #httpApi;
6
7
  constructor(httpApi) {
@@ -11,8 +12,8 @@ export class ThemeSkinstoreService {
11
12
  const { response: request } = this.#httpApi.getPublishFormData({ actionData, shopUrl: credentials.shopUrl });
12
13
  const response = await request;
13
14
  if (response?.status !== STATUS_CODES.ok)
14
- return;
15
- return response?.data;
15
+ throw response;
16
+ return response?.data ? toControls(response.data) : [];
16
17
  }
17
18
  catch (err) {
18
19
  //TODO to basic class
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@shoper/cli",
3
3
  "packageManager": "yarn@3.2.0",
4
4
  "sideEffects": false,
5
- "version": "0.1.0-34",
5
+ "version": "0.1.0-35",
6
6
  "description": "CLI tool for Shoper",
7
7
  "author": "Joanna Firek",
8
8
  "license": "MIT",