@shoper/cli 0.1.0-7 → 0.1.0-8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli/auth/api/cli_auth_api.js +15 -2
- package/build/cli/auth/cli_auth_constants.js +6 -0
- package/build/cli/auth/cli_auth_errors_factory.js +10 -0
- package/build/cli/auth/cli_auth_initializer.js +19 -0
- package/build/cli/auth/cli_auth_utils.js +22 -0
- package/build/cli/auth/model/cli_credentials.js +10 -0
- package/build/cli/auth/service/cli_auth_service.js +34 -0
- package/build/cli/auth/tokens/api/cli_auth_tokens_api.js +43 -1
- package/build/cli/auth/tokens/cli_auth_tokens_constants.js +6 -0
- package/build/cli/auth/tokens/cli_auth_tokens_errors_factory.js +10 -0
- package/build/cli/auth/tokens/cli_auth_tokens_initalizer.js +35 -1
- package/build/cli/auth/tokens/cli_auth_tokens_utils.js +26 -0
- package/build/cli/auth/tokens/service/cli_auth_tokens_service.js +84 -4
- package/build/cli/auth/tokens/service/cli_auth_tokens_service_constants.js +2 -0
- package/build/cli/class/base_cli_command.js +3 -0
- package/build/cli/class/errors/app_error/app_error.js +17 -0
- package/build/cli/class/errors/app_error/app_error_constants.js +7 -0
- package/build/cli/class/errors/file_system_errors_factory.js +26 -0
- package/build/cli/class/errors/http_errors_factory.js +21 -0
- package/build/cli/cli_constants.js +1 -0
- package/build/cli/commands/auth/cli_auth_add_token_command.js +32 -0
- package/build/cli/commands/auth/cli_auth_list_tokens_command.js +17 -0
- package/build/cli/commands/auth/cli_auth_remove_token_command.js +37 -0
- package/build/cli/commands/auth/cli_auth_switch_token_command.js +36 -0
- package/build/cli/commands/cli_update_command.js +7 -3
- package/build/cli/commands/commands_constants.js +5 -1
- package/build/cli/commands/files_diff_command.js +174 -0
- package/build/cli/commands/utils/prompt_for_token_utils.js +25 -0
- package/build/cli/core/cli_setup.js +20 -7
- package/build/cli/features/caches/json_cache/json_cache.js +50 -0
- package/build/cli/features/caches/memory_cache.js +6 -0
- package/build/cli/features/data_directory/cli_data_directory_constants.js +0 -1
- package/build/cli/features/data_directory/cli_data_directory_utils.js +3 -4
- package/build/cli/features/data_directory/service/cli_data_directory_service.js +2 -2
- package/build/cli/features/execution_context/execution_context_service.js +3 -5
- package/build/cli/features/http_requester/http_client.js +32 -1
- package/build/cli/features/version/service/cli_version_service.js +2 -4
- package/build/cli/hooks/authorization/ensure_authorization_hook.js +11 -6
- package/build/cli/hooks/authorization/ensure_authorization_hook_constants.js +8 -1
- package/build/index.js +34 -1
- package/build/theme/class/fetch_resources/fetch_resources.js +126 -0
- package/build/theme/class/fetch_resources/fetch_resources_constants.js +2 -0
- package/build/theme/class/fetch_resources/fetch_resources_errors_factory.js +11 -0
- package/build/theme/class/fetch_resources/fetch_resources_utils.js +35 -0
- package/build/theme/commands/theme_commands_constants.js +8 -0
- package/build/theme/commands/theme_init_command.js +53 -0
- package/build/theme/commands/theme_list_command.js +16 -0
- package/build/theme/commands/theme_pull_command.js +124 -0
- package/build/theme/commands/theme_push_command.js +65 -0
- package/build/theme/commands/theme_show_changes_command.js +60 -0
- package/build/theme/commands/theme_verify_command.js +43 -0
- package/build/theme/features/theme/actions/api/theme_actions_api.js +19 -0
- package/build/theme/features/theme/actions/service/theme_actions_service.js +92 -0
- package/build/theme/features/theme/actions/service/theme_actions_service_constants.js +2 -0
- package/build/theme/features/theme/actions/theme_actions_constants.js +15 -0
- package/build/theme/features/theme/actions/theme_actions_initializer.js +27 -0
- package/build/theme/features/theme/actions/theme_actions_utils.js +8 -0
- package/build/theme/features/theme/directory/theme_directory_utils.js +61 -14
- package/build/theme/features/theme/fetch/api/theme_fetch_api.js +16 -0
- package/build/theme/features/theme/fetch/http/theme_fetch_http_api.js +18 -0
- package/build/theme/features/theme/fetch/service/theme_fetch_service.js +113 -0
- package/build/theme/features/theme/fetch/theme_fetch_constants.js +7 -0
- package/build/theme/features/theme/fetch/theme_fetch_initializer.js +23 -0
- package/build/theme/features/theme/init/api/theme_init_api.js +13 -0
- package/build/theme/features/theme/init/http/theme_init_http_api.js +18 -0
- package/build/theme/features/theme/init/service/theme_init_service.js +28 -0
- package/build/theme/features/theme/init/theme_init_constants.js +2 -0
- package/build/theme/features/theme/init/theme_init_initializer.js +22 -0
- package/build/theme/features/theme/merge/api/theme_merge_api.js +28 -0
- package/build/theme/features/theme/merge/service/theme_merge_service.js +56 -0
- package/build/theme/features/theme/merge/theme_merge_constants.js +9 -0
- package/build/theme/features/theme/merge/theme_merge_initializer.js +18 -0
- package/build/theme/features/theme/publish/theme_publish_constants.js +2 -0
- package/build/theme/features/theme/publish/theme_publish_utils.js +7 -0
- package/build/theme/features/theme/push/api/theme_push_api.js +13 -0
- package/build/theme/features/theme/push/http_api/theme_push_http_api.js +21 -0
- package/build/theme/features/theme/push/service/theme_push_service.js +194 -0
- package/build/theme/features/theme/push/service/theme_push_service_constants.js +1 -0
- package/build/theme/features/theme/push/theme_push_constants.js +4 -0
- package/build/theme/features/theme/push/theme_push_errors_factory.js +41 -0
- package/build/theme/features/theme/push/theme_push_initializer.js +27 -0
- package/build/theme/features/theme/theme_constants.js +6 -0
- package/build/theme/features/theme/utils/checksums/theme_checksums_error_factory.js +10 -0
- package/build/theme/features/theme/utils/checksums/theme_checksums_utils.js +94 -0
- package/build/theme/features/theme/utils/directories/theme_resources_with_id_directory_utils.js +80 -0
- package/build/theme/features/theme/utils/theme_images_utils.js +31 -0
- package/build/theme/features/themes/list/api/themes_list_api.js +13 -0
- package/build/theme/features/themes/{http/shoper_themes_http_api.js → list/http/themes_list_http_api.js} +3 -2
- package/build/theme/features/themes/{model/theme_metadata.js → list/model/theme_list_metadata.js} +3 -1
- package/build/theme/features/themes/list/services/themes_list_service.js +37 -0
- package/build/theme/features/themes/list/themes_list_constants.js +2 -0
- package/build/theme/features/themes/list/themes_list_initializer.js +20 -0
- package/build/theme/hooks/ensure_theme_meta_data_untouched.js +17 -0
- package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date.js +21 -0
- package/build/theme/hooks/theme_checksums/ensure_theme_current_checksums_up_to_date_constants.js +7 -0
- package/build/theme/hooks/themes_actions/ensure_themes_actions_hook.js +45 -0
- package/build/theme/hooks/themes_actions/ensure_themes_actions_hook_constants.js +7 -0
- package/build/theme/index.js +13 -4
- package/build/theme/utils/directory_validator/directory_validator_constants.js +13 -0
- package/build/theme/utils/directory_validator/directory_validator_utils.js +187 -0
- package/build/utils/checksums/checksums_utils.js +95 -0
- package/build/utils/checksums/checksums_utils_constants.js +1 -0
- package/build/utils/date_utils.js +3 -0
- package/build/utils/download_file/download_file_errors_factory.js +9 -0
- package/build/utils/download_file/download_file_utils.js +46 -0
- package/build/utils/fs/errors/stream_read_error.js +11 -0
- package/build/utils/fs/errors/stream_write_error.js +11 -0
- package/build/utils/fs/fs_utils.js +152 -0
- package/build/utils/http_utils.js +10 -0
- package/build/utils/path_utils.js +34 -0
- package/build/utils/stream_transforms/json_indent_transform.js +21 -0
- package/build/utils/url_utils.js +9 -0
- package/build/utils/zip/create_zip_utils.js +80 -0
- package/build/utils/zip/errors/create_zip_error.js +11 -0
- package/build/utils/zip/errors/open_zip_error.js +11 -0
- package/build/utils/zip/extract_zip_utils.js +104 -0
- package/oclif.config.js +4 -2
- package/package.json +34 -7
- package/build/cli/hooks/migration/migration_hook.js +0 -4
- package/build/theme/commands/list_command.js +0 -12
- package/build/theme/commands/pull_command.js +0 -24
- package/build/theme/features/theme/directory/theme_directories_utils.js +0 -10
- package/build/theme/features/theme/pull/api/shoper_theme_pull_api.js +0 -9
- package/build/theme/features/theme/pull/http/shoper_theme_pull_http_api.js +0 -14
- package/build/theme/features/theme/pull/service/shoper_theme_pull_service.js +0 -68
- package/build/theme/features/theme/pull/shoper_theme_pull_initializer.js +0 -22
- package/build/theme/features/themes/api/shoper_themes_api.js +0 -14
- package/build/theme/features/themes/services/shoper_themes_service.js +0 -15
- package/build/theme/features/themes/shoper_themes_constants.js +0 -2
- package/build/theme/features/themes/shoper_themes_initalizer.js +0 -20
- package/build/utils/fs.js +0 -44
- package/build/utils/path.js +0 -13
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Transform } from 'node:stream';
|
|
2
|
+
import { JSON_FILE_INDENT } from '../../cli/cli_constants.js';
|
|
3
|
+
export const jsonIndentTransform = (space = JSON_FILE_INDENT) => {
|
|
4
|
+
let data = '';
|
|
5
|
+
return new Transform({
|
|
6
|
+
writableObjectMode: true,
|
|
7
|
+
transform(chunk, _, callback) {
|
|
8
|
+
data += chunk.toString();
|
|
9
|
+
callback();
|
|
10
|
+
},
|
|
11
|
+
flush(callback) {
|
|
12
|
+
if (!data) {
|
|
13
|
+
return callback();
|
|
14
|
+
}
|
|
15
|
+
const json = JSON.parse(data);
|
|
16
|
+
const pretty = JSON.stringify(json, null, space);
|
|
17
|
+
this.push(pretty);
|
|
18
|
+
callback();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import process from 'process';
|
|
2
|
+
import { fileExists, isDirectory, removeFiles } from '../fs/fs_utils.js';
|
|
3
|
+
import yazl from 'yazl';
|
|
4
|
+
import { createWriteStream } from 'node:fs';
|
|
5
|
+
import { StreamReadError } from '../fs/errors/stream_read_error.js';
|
|
6
|
+
import { CreateZipError } from './errors/create_zip_error.js';
|
|
7
|
+
import { StreamWriteError } from '../fs/errors/stream_write_error.js';
|
|
8
|
+
import { join } from '../path_utils.js';
|
|
9
|
+
import { AppError } from '../../cli/class/errors/app_error/app_error.js';
|
|
10
|
+
export const createZip = async ({ files, dist, baseDir = process.cwd() }) => {
|
|
11
|
+
const zipfile = new yazl.ZipFile();
|
|
12
|
+
let hasError = false;
|
|
13
|
+
try {
|
|
14
|
+
for (let i = 0; i < files.length; ++i) {
|
|
15
|
+
const file = files[i];
|
|
16
|
+
if (!file)
|
|
17
|
+
continue;
|
|
18
|
+
const fullPath = join(baseDir, file);
|
|
19
|
+
if (!(await fileExists(fullPath)))
|
|
20
|
+
throw new AppError({
|
|
21
|
+
message: `File does not exist: ${fullPath}`,
|
|
22
|
+
code: 'FILE_NOT_FOUND',
|
|
23
|
+
details: { file, baseDir }
|
|
24
|
+
});
|
|
25
|
+
if (await isDirectory(fullPath)) {
|
|
26
|
+
zipfile.addEmptyDirectory(file);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
zipfile.addFile(fullPath, file, {
|
|
30
|
+
//TODO params
|
|
31
|
+
compress: true
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
zipfile.end();
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new AppError({
|
|
39
|
+
message: 'Error creating zip file',
|
|
40
|
+
code: 'ZIP_CREATION_ERROR',
|
|
41
|
+
details: { files, dist, baseDir },
|
|
42
|
+
stack: err instanceof Error ? err.stack : undefined
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const zipOutput = createWriteStream(dist);
|
|
47
|
+
zipOutput.on('error', (err) => {
|
|
48
|
+
hasError = true;
|
|
49
|
+
removeFiles(files).then(() => {
|
|
50
|
+
reject(new StreamWriteError({
|
|
51
|
+
filePath: dist,
|
|
52
|
+
details: { err },
|
|
53
|
+
stack: err.stack
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
zipfile.outputStream.pipe(zipOutput).on('close', () => {
|
|
58
|
+
if (hasError) {
|
|
59
|
+
removeFiles(files).then(() => {
|
|
60
|
+
reject(new CreateZipError({
|
|
61
|
+
file: dist,
|
|
62
|
+
stack: new Error().stack
|
|
63
|
+
}));
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
zipfile.outputStream.on('error', (err) => {
|
|
70
|
+
hasError = true;
|
|
71
|
+
removeFiles(files).then(() => {
|
|
72
|
+
reject(new StreamReadError({
|
|
73
|
+
filePath: dist,
|
|
74
|
+
details: { err },
|
|
75
|
+
stack: err.stack
|
|
76
|
+
}));
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AppError } from '../../../cli/class/errors/app_error/app_error.js';
|
|
2
|
+
export class CreateZipError extends AppError {
|
|
3
|
+
constructor({ details, stack, file }) {
|
|
4
|
+
super({
|
|
5
|
+
code: 'ZIP_FILE_CREATE_ERROR',
|
|
6
|
+
message: `Error creating zip file ${file}`,
|
|
7
|
+
details,
|
|
8
|
+
stack
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AppError } from '../../../cli/class/errors/app_error/app_error.js';
|
|
2
|
+
export class OpenZipError extends AppError {
|
|
3
|
+
constructor({ details, stack, file }) {
|
|
4
|
+
super({
|
|
5
|
+
code: 'ZIP_FILE_OPEN_ERROR',
|
|
6
|
+
message: `Error opening zip file ${file}`,
|
|
7
|
+
details,
|
|
8
|
+
stack
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import yauzl from 'yauzl';
|
|
2
|
+
import { directoryExists, makeDirectory, removeDirectory, removeDirectorySync, removeFile } from '../fs/fs_utils.js';
|
|
3
|
+
import { dirname, join, looksLikeDirectory } from '../path_utils.js';
|
|
4
|
+
import { createWriteStream } from 'node:fs';
|
|
5
|
+
import { StreamWriteError } from '../fs/errors/stream_write_error.js';
|
|
6
|
+
import { StreamReadError } from '../fs/errors/stream_read_error.js';
|
|
7
|
+
import { OpenZipError } from './errors/open_zip_error.js';
|
|
8
|
+
import { pipeline } from 'node:stream/promises';
|
|
9
|
+
export const extractZip = async ({ source, dist, getTransforms = () => [] }) => {
|
|
10
|
+
let createdDirectory = false;
|
|
11
|
+
if (!(await directoryExists(dist))) {
|
|
12
|
+
createdDirectory = true;
|
|
13
|
+
await makeDirectory(dist, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const processedFilesPath = [];
|
|
17
|
+
yauzl.open(source, { lazyEntries: true }, (err, zipfile) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
createdDirectory && removeDirectorySync(dist, { recursive: true });
|
|
20
|
+
return reject(new OpenZipError({
|
|
21
|
+
file: source,
|
|
22
|
+
details: { err },
|
|
23
|
+
stack: err.stack
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
let activeEntries = 0;
|
|
27
|
+
let doneReadingEntries = false;
|
|
28
|
+
const extractedPaths = new Set();
|
|
29
|
+
zipfile.on('entry', (entry) => {
|
|
30
|
+
activeEntries++;
|
|
31
|
+
const filePath = join(dist, entry.fileName);
|
|
32
|
+
const dirPath = dirname(filePath);
|
|
33
|
+
processedFilesPath.push(filePath);
|
|
34
|
+
if (!filePath.startsWith(dist)) {
|
|
35
|
+
return reject(new Error(`Invalid entry path: ${entry.fileName}`));
|
|
36
|
+
}
|
|
37
|
+
if (looksLikeDirectory(entry.fileName)) {
|
|
38
|
+
zipfile.readEntry();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (extractedPaths.has(filePath)) {
|
|
42
|
+
return reject(new Error(`Duplicate entry path detected: ${filePath}`));
|
|
43
|
+
}
|
|
44
|
+
extractedPaths.add(filePath);
|
|
45
|
+
makeDirectory(dirPath, { recursive: true })
|
|
46
|
+
.then(() => {
|
|
47
|
+
zipfile.openReadStream(entry, async (err, readStream) => {
|
|
48
|
+
if (err)
|
|
49
|
+
return reject(err);
|
|
50
|
+
const writeStream = createWriteStream(filePath);
|
|
51
|
+
writeStream.on('finish', () => {
|
|
52
|
+
activeEntries--;
|
|
53
|
+
if (activeEntries === 0 && doneReadingEntries)
|
|
54
|
+
resolve();
|
|
55
|
+
zipfile.readEntry();
|
|
56
|
+
});
|
|
57
|
+
writeStream.on('error', async (err) => {
|
|
58
|
+
await removeFile(filePath);
|
|
59
|
+
reject(new StreamWriteError({
|
|
60
|
+
filePath,
|
|
61
|
+
details: { err },
|
|
62
|
+
stack: err.stack
|
|
63
|
+
}));
|
|
64
|
+
});
|
|
65
|
+
readStream.on('error', async (err) => {
|
|
66
|
+
await removeFile(filePath, { force: true });
|
|
67
|
+
reject(new StreamReadError({
|
|
68
|
+
filePath,
|
|
69
|
+
details: { err },
|
|
70
|
+
stack: err.stack
|
|
71
|
+
}));
|
|
72
|
+
});
|
|
73
|
+
const transforms = getTransforms(entry.fileName);
|
|
74
|
+
if (transforms.length) {
|
|
75
|
+
await pipeline(readStream, ...transforms, writeStream);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
readStream.pipe(writeStream);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
})
|
|
82
|
+
.catch(reject);
|
|
83
|
+
});
|
|
84
|
+
zipfile.on('end', () => {
|
|
85
|
+
doneReadingEntries = true;
|
|
86
|
+
if (activeEntries === 0)
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
zipfile.on('error', async (err) => {
|
|
90
|
+
for (const filePath of processedFilesPath) {
|
|
91
|
+
try {
|
|
92
|
+
await removeFile(filePath, { force: true });
|
|
93
|
+
}
|
|
94
|
+
catch (removeErr) {
|
|
95
|
+
console.error(`Error removing file ${filePath}:`, removeErr);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
createdDirectory && (await removeDirectory(dist, { recursive: true }));
|
|
99
|
+
reject(err);
|
|
100
|
+
});
|
|
101
|
+
zipfile.readEntry();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
};
|
package/oclif.config.js
CHANGED
|
@@ -17,8 +17,10 @@ export default {
|
|
|
17
17
|
hooks: {
|
|
18
18
|
prerun: [
|
|
19
19
|
'./build/cli/hooks/authorization/ensure_authorization_hook.js',
|
|
20
|
-
'./build/cli/hooks/
|
|
21
|
-
'./build/
|
|
20
|
+
'./build/cli/hooks/ensure_cli_initialized_hook.js',
|
|
21
|
+
'./build/theme/hooks/ensure_theme_meta_data_untouched.js',
|
|
22
|
+
'./build/theme/hooks/ensure_theme_current_checksums_up_to_date.js',
|
|
23
|
+
'./build/theme/hooks/themes_actions/ensure_themes_actions_hook.js'
|
|
22
24
|
]
|
|
23
25
|
},
|
|
24
26
|
topicSeparator: ' ',
|
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-
|
|
5
|
+
"version": "0.1.0-8",
|
|
6
6
|
"description": "CLI tool for Shoper",
|
|
7
7
|
"author": "Joanna Firek",
|
|
8
8
|
"license": "MIT",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "rimraf ./build/ && tsc --project tsconfig.json",
|
|
26
26
|
"watch": "rimraf ./build/ && tsc --watch --project tsconfig.json",
|
|
27
|
-
"test": "
|
|
28
|
-
"test:watch": "
|
|
27
|
+
"test": "jest --config config/jest/jest.config.mjs",
|
|
28
|
+
"test:watch": "jest --config config/jest/jest.config.mjs --no-cache --watch",
|
|
29
29
|
"deploy:latest": "npm run build && npm publish --tag latest --access public",
|
|
30
30
|
"deploy:beta": "npm run build && npm publish --tag beta --access public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@dreamcommerce/star_core": "1.
|
|
33
|
+
"@dreamcommerce/star_core": "1.8.1",
|
|
34
34
|
"@oclif/core": "4.2.10",
|
|
35
35
|
"@oclif/plugin-autocomplete": "3.2.27",
|
|
36
36
|
"@oclif/plugin-help": "6.2.27",
|
|
@@ -38,29 +38,56 @@
|
|
|
38
38
|
"@oclif/plugin-version": "2.2.27",
|
|
39
39
|
"@oclif/plugin-warn-if-update-available": "3.1.38",
|
|
40
40
|
"axios": "1.8.4",
|
|
41
|
+
"chalk": "5.4.1",
|
|
42
|
+
"conf": "13.1.0",
|
|
43
|
+
"ink": "5.2.1",
|
|
44
|
+
"inquirer": "12.5.2",
|
|
41
45
|
"is-hidden-file": "1.1.2",
|
|
46
|
+
"jsonwebtoken": "9.0.2",
|
|
42
47
|
"memfs": "4.17.0",
|
|
48
|
+
"ora": "8.2.0",
|
|
49
|
+
"react": "18.3.1",
|
|
43
50
|
"reflect-metadata": "0.2.2",
|
|
44
51
|
"rxjs": "7.8.2",
|
|
45
52
|
"semver": "7.7.1",
|
|
46
53
|
"tmp-promise": "3.0.3",
|
|
47
|
-
"
|
|
54
|
+
"yauzl": "3.2.0",
|
|
55
|
+
"yazl": "3.3.1",
|
|
56
|
+
"fs-tree-diff": "2.0.1",
|
|
57
|
+
"fast-glob": "3.3.3",
|
|
58
|
+
"klaw": "4.1.0",
|
|
59
|
+
"walk-sync": "3.0.0",
|
|
60
|
+
"lodash": "4.17.21",
|
|
61
|
+
"uuid": "11.1.0"
|
|
48
62
|
},
|
|
49
63
|
"devDependencies": {
|
|
64
|
+
"@babel/core": "7.27.1",
|
|
65
|
+
"@babel/preset-env": "7.27.2",
|
|
66
|
+
"@babel/preset-typescript": "7.27.1",
|
|
50
67
|
"@oclif/test": "4.1.12",
|
|
51
68
|
"@tsconfig/node18": "18.2.4",
|
|
69
|
+
"@types/jest": "29.5.14",
|
|
70
|
+
"@types/jsonwebtoken": "9.0.9",
|
|
52
71
|
"@types/node": "18.19.84",
|
|
72
|
+
"@types/react": "19.1.3",
|
|
53
73
|
"@types/semver": "7.7.0",
|
|
54
74
|
"@types/tmp": "0.2.6",
|
|
55
|
-
"@types/
|
|
75
|
+
"@types/yauzl": "2.10.3",
|
|
76
|
+
"@types/yazl": "2.4.6",
|
|
77
|
+
"@types/klaw": "3.0.7",
|
|
78
|
+
"@types/lodash": "4.17.17",
|
|
56
79
|
"@typescript-eslint/eslint-plugin": "8.29.1",
|
|
80
|
+
"babel-jest": "29.7.0",
|
|
57
81
|
"eslint": "9.24.0",
|
|
58
82
|
"eslint-config-prettier": "10.1.1",
|
|
59
83
|
"eslint-plugin-prettier": "5.2.6",
|
|
84
|
+
"jest": "29.7.0",
|
|
60
85
|
"module-alias": "2.2.3",
|
|
61
86
|
"prettier": "3.5.3",
|
|
62
87
|
"rimraf": "5.0.10",
|
|
88
|
+
"ts-jest": "29.3.2",
|
|
89
|
+
"ts-toolbelt": "9.6.0",
|
|
63
90
|
"typescript": "5.8.3",
|
|
64
|
-
"
|
|
91
|
+
"jest-extended": "4.0.2"
|
|
65
92
|
}
|
|
66
93
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { BaseThemeCommand } from '../class/base_theme_command.js';
|
|
2
|
-
import { SHOPER_THEMES_API_NAME } from '../features/themes/shoper_themes_constants.js';
|
|
3
|
-
export class ThemeListCommand extends BaseThemeCommand {
|
|
4
|
-
static description = 'List all shop themes';
|
|
5
|
-
async run() {
|
|
6
|
-
const themesApi = this.getApi(SHOPER_THEMES_API_NAME);
|
|
7
|
-
// TODO get credentials from api
|
|
8
|
-
const themes = await themesApi.getThemes('https://shoper.docker.shoper.tech');
|
|
9
|
-
//TODO UI
|
|
10
|
-
this.log('themes', themes);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Args } from '@oclif/core';
|
|
2
|
-
import { BaseThemeCommand } from '../class/base_theme_command.js';
|
|
3
|
-
export class ThemePullCommand extends BaseThemeCommand {
|
|
4
|
-
static description = 'Pull theme from shop';
|
|
5
|
-
static args = {
|
|
6
|
-
id: Args.string({
|
|
7
|
-
description: 'Theme id',
|
|
8
|
-
name: 'id',
|
|
9
|
-
required: true,
|
|
10
|
-
type: 'string'
|
|
11
|
-
})
|
|
12
|
-
};
|
|
13
|
-
async run() {
|
|
14
|
-
const data = await this.parse(ThemePullCommand);
|
|
15
|
-
const { args } = data;
|
|
16
|
-
//TODO sprawdamy z lista sików przed pullem?
|
|
17
|
-
//TDOO jezeli nie ma id, pobierz z kontekstu jezeli jest w theme
|
|
18
|
-
const themeId = args.id;
|
|
19
|
-
// TODO some automation
|
|
20
|
-
// const themePullApi = new ShoperThemePullInitializer().init();
|
|
21
|
-
// TODO get credentials from api
|
|
22
|
-
// await themePullApi.pullTheme('https://shoper.docker.shoper.tech', themeId);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getAllDirectoriesInside } from '../../../../utils/fs.js';
|
|
2
|
-
import { join } from '../../../../utils/path.js';
|
|
3
|
-
import { ThemeDirectoryUtils } from './theme_directory_utils.js';
|
|
4
|
-
import { asyncFilter } from '../../../../utils/array_utils.js';
|
|
5
|
-
export class ThemeDirectoriesUtils {
|
|
6
|
-
static async getAllThemesDirectories(path) {
|
|
7
|
-
const directories = await getAllDirectoriesInside(path);
|
|
8
|
-
return asyncFilter(directories, async (directory) => ThemeDirectoryUtils.isThemeRootDirectory(join(path, directory)));
|
|
9
|
-
}
|
|
10
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//TODO
|
|
2
|
-
export class ShoperThemePullHttpApi {
|
|
3
|
-
#httpApi;
|
|
4
|
-
constructor(httpApi) {
|
|
5
|
-
this.#httpApi = httpApi;
|
|
6
|
-
}
|
|
7
|
-
pullTheme(shopUrl, id) {
|
|
8
|
-
const controller = new AbortController();
|
|
9
|
-
const resp = fetch(`${shopUrl}/webapi/cli/themes/${id}`, {
|
|
10
|
-
signal: controller.signal
|
|
11
|
-
});
|
|
12
|
-
return { response: resp, controller };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createWriteStream } from 'fs';
|
|
2
|
-
import { basename, extname } from '../../../../../utils/path.js';
|
|
3
|
-
import unzipper from 'unzipper';
|
|
4
|
-
import tmp from 'tmp-promise';
|
|
5
|
-
import { EXECUTION_CONTEXTS } from '../../../../../cli/features/execution_context/execution_context_constants.js';
|
|
6
|
-
//TODO fix
|
|
7
|
-
let currentRequest;
|
|
8
|
-
export class ShoperThemePullService {
|
|
9
|
-
#httpApi;
|
|
10
|
-
#executionContext;
|
|
11
|
-
constructor({ httpApi, executionContext }) {
|
|
12
|
-
this.#httpApi = httpApi;
|
|
13
|
-
this.#executionContext = executionContext;
|
|
14
|
-
}
|
|
15
|
-
async pullTheme(shopUrl, id) {
|
|
16
|
-
if (currentRequest)
|
|
17
|
-
currentRequest.abort();
|
|
18
|
-
//TODO error handling
|
|
19
|
-
const { response, controller } = this.#httpApi.pullTheme(shopUrl, id);
|
|
20
|
-
currentRequest = controller;
|
|
21
|
-
const resp = await response;
|
|
22
|
-
if (resp.status === 405) {
|
|
23
|
-
//TODO not authenticated
|
|
24
|
-
throw new Error('Theme not found');
|
|
25
|
-
}
|
|
26
|
-
if (resp.status !== 200) {
|
|
27
|
-
//TODO handle error
|
|
28
|
-
throw new Error('Theme not found');
|
|
29
|
-
}
|
|
30
|
-
const { path, cleanup } = await tmp.dir({
|
|
31
|
-
unsafeCleanup: true
|
|
32
|
-
});
|
|
33
|
-
const filename = /filename="([^"]+)"/.exec(resp.headers.get('content-disposition') ?? '')?.[1];
|
|
34
|
-
if (!filename) {
|
|
35
|
-
//TODO handle error
|
|
36
|
-
throw new Error(`Missing Filename in a content-disposition header ${resp.headers.get('content-disposition') ?? ''}`);
|
|
37
|
-
}
|
|
38
|
-
const file = createWriteStream(`${path}/${filename}`);
|
|
39
|
-
file.on('finish', async () => {
|
|
40
|
-
file.close();
|
|
41
|
-
await this._extractToSpecificDirectory(file.path, path);
|
|
42
|
-
await cleanup();
|
|
43
|
-
});
|
|
44
|
-
file.on('error', (err) => {
|
|
45
|
-
console.log('err', err);
|
|
46
|
-
//TODO
|
|
47
|
-
});
|
|
48
|
-
//@ts-ignore
|
|
49
|
-
resp.body?.pipe(file);
|
|
50
|
-
}
|
|
51
|
-
async _extractToSpecificDirectory(archivePath, tmpDir) {
|
|
52
|
-
console.log('executionContext', this.#executionContext);
|
|
53
|
-
const filenameWithoutExtension = basename(archivePath, extname(archivePath));
|
|
54
|
-
const directory = await unzipper.Open.file(archivePath);
|
|
55
|
-
await directory.extract({ path: `${tmpDir}/${filenameWithoutExtension}` });
|
|
56
|
-
//TODO check if theme exist
|
|
57
|
-
if (this.#executionContext.type === EXECUTION_CONTEXTS.global) {
|
|
58
|
-
//czek if folder exist
|
|
59
|
-
//czek if theme + shop exist
|
|
60
|
-
//if folder not exist create
|
|
61
|
-
// if folder exist clear images file
|
|
62
|
-
// fetch images while copying theme
|
|
63
|
-
}
|
|
64
|
-
if (this.#executionContext.type === EXECUTION_CONTEXTS.theme) {
|
|
65
|
-
//TODO save in storage
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ShoperThemePullService } from './service/shoper_theme_pull_service.js';
|
|
2
|
-
import { ShoperThemePullHttpApi } from './http/shoper_theme_pull_http_api.js';
|
|
3
|
-
import { ShoperThemePullApi } from './api/shoper_theme_pull_api.js';
|
|
4
|
-
import { AsyncFeatureInitializer, FEATURE_CORES_TYPES, HTTP_REQUESTER_API_NAME } from '@dreamcommerce/star_core';
|
|
5
|
-
export class ShoperThemePullInitializer extends AsyncFeatureInitializer {
|
|
6
|
-
async init() {
|
|
7
|
-
const httpApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
8
|
-
const executionContextApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
9
|
-
const service = new ShoperThemePullService({
|
|
10
|
-
httpApi: new ShoperThemePullHttpApi(httpApi),
|
|
11
|
-
executionContext: await executionContextApi.getExecutionContext()
|
|
12
|
-
});
|
|
13
|
-
return {
|
|
14
|
-
cores: [
|
|
15
|
-
{
|
|
16
|
-
type: FEATURE_CORES_TYPES.api,
|
|
17
|
-
instance: new ShoperThemePullApi(service)
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { FeatureApi } from '@dreamcommerce/star_core';
|
|
2
|
-
import { SHOPER_THEMES_API_NAME } from '../shoper_themes_constants.js';
|
|
3
|
-
export class ShoperThemesApi extends FeatureApi {
|
|
4
|
-
moduleName = SHOPER_THEMES_API_NAME;
|
|
5
|
-
#service;
|
|
6
|
-
constructor(service) {
|
|
7
|
-
super();
|
|
8
|
-
this.#service = service;
|
|
9
|
-
}
|
|
10
|
-
//credentialObject
|
|
11
|
-
async getThemes(shopUrl) {
|
|
12
|
-
return this.#service.getThemes(shopUrl);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { STATUS_CODES } from '@dreamcommerce/star_core';
|
|
2
|
-
export class ShoperThemesService {
|
|
3
|
-
httpApi;
|
|
4
|
-
constructor(httpApi) {
|
|
5
|
-
this.httpApi = httpApi;
|
|
6
|
-
}
|
|
7
|
-
async getThemes(shopUrl) {
|
|
8
|
-
//TODO error handling
|
|
9
|
-
const { response } = this.httpApi.getThemes(shopUrl);
|
|
10
|
-
const { data, status } = await response;
|
|
11
|
-
if (status !== STATUS_CODES.ok)
|
|
12
|
-
return;
|
|
13
|
-
return data;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ShoperThemesService } from './services/shoper_themes_service.js';
|
|
2
|
-
import { ShoperThemesApi } from './api/shoper_themes_api.js';
|
|
3
|
-
import { ShoperThemesHttpApi } from './http/shoper_themes_http_api.js';
|
|
4
|
-
import { FEATURE_CORES_TYPES, HTTP_REQUESTER_API_NAME, SyncFeatureInitializer } from '@dreamcommerce/star_core';
|
|
5
|
-
import { SHOPER_THEMES_FEATURE_NAME } from './shoper_themes_constants.js';
|
|
6
|
-
export class ShoperThemesInitializer extends SyncFeatureInitializer {
|
|
7
|
-
static featureName = SHOPER_THEMES_FEATURE_NAME;
|
|
8
|
-
init() {
|
|
9
|
-
const httpApi = this.getApiSync(HTTP_REQUESTER_API_NAME);
|
|
10
|
-
const service = new ShoperThemesService(new ShoperThemesHttpApi(httpApi));
|
|
11
|
-
return {
|
|
12
|
-
cores: [
|
|
13
|
-
{
|
|
14
|
-
type: FEATURE_CORES_TYPES.api,
|
|
15
|
-
instance: new ShoperThemesApi(service)
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
}
|
package/build/utils/fs.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import fsPromises from 'fs/promises';
|
|
2
|
-
import { isHiddenFile } from 'is-hidden-file';
|
|
3
|
-
import process from 'process';
|
|
4
|
-
import { resolve } from './path.js';
|
|
5
|
-
import { parse as parsePath } from 'path';
|
|
6
|
-
export const fileExists = async (path) => {
|
|
7
|
-
try {
|
|
8
|
-
await fsPromises.access(path);
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
export const directoryExists = async (path) => {
|
|
16
|
-
return fileExists(path);
|
|
17
|
-
};
|
|
18
|
-
export const readFile = async (path, options) => {
|
|
19
|
-
return fsPromises.readFile(path, options);
|
|
20
|
-
};
|
|
21
|
-
export const makeDirectory = async (path, options = {}) => {
|
|
22
|
-
return await fsPromises.mkdir(path, { recursive: false, ...options });
|
|
23
|
-
};
|
|
24
|
-
export const getAllDirectoriesInside = async (path, { hidden } = { hidden: true }) => {
|
|
25
|
-
const files = await fsPromises.readdir(path, {
|
|
26
|
-
recursive: true,
|
|
27
|
-
withFileTypes: true
|
|
28
|
-
});
|
|
29
|
-
return files.filter((file) => file.isDirectory() && (hidden ? true : !isHiddenFile(file.name))).map((file) => file.name);
|
|
30
|
-
};
|
|
31
|
-
export const closestFile = async (fileToFind, path = process.cwd()) => {
|
|
32
|
-
let currPath = path;
|
|
33
|
-
const rootDir = getOSRootDirectory();
|
|
34
|
-
while (currPath !== rootDir) {
|
|
35
|
-
const exists = await fileExists(resolve(currPath, fileToFind));
|
|
36
|
-
if (exists)
|
|
37
|
-
return currPath;
|
|
38
|
-
currPath = resolve(currPath, '..');
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
export const closestDirectory = async (path) => {
|
|
42
|
-
return closestFile(path);
|
|
43
|
-
};
|
|
44
|
-
export const getOSRootDirectory = () => parsePath(process.cwd()).root;
|
package/build/utils/path.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { resolve as resolvePath, parse as parsePath, join as pathJoin, basename as pathBaseName, dirname as pathDirname, extname as pathExtname } from 'path';
|
|
2
|
-
export const resolve = (...paths) => {
|
|
3
|
-
return resolvePath(...paths);
|
|
4
|
-
};
|
|
5
|
-
export const parse = (path) => {
|
|
6
|
-
return parsePath(path);
|
|
7
|
-
};
|
|
8
|
-
export const join = (...paths) => {
|
|
9
|
-
return pathJoin(...paths);
|
|
10
|
-
};
|
|
11
|
-
export const basename = (path, ext) => pathBaseName(path, ext);
|
|
12
|
-
export const dirname = (path) => pathDirname(path);
|
|
13
|
-
export const extname = (path) => pathExtname(path);
|