shoplazza-cli 0.0.4 → 0.0.6
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/README.md +118 -27
- package/bin/shoplazza +19 -1
- package/lib/app/commands/build.js +66 -0
- package/lib/app/commands/deploy.js +213 -0
- package/lib/app/commands/generate.js +50 -0
- package/lib/app/commands/publish.js +52 -0
- package/lib/app/constants.js +7 -0
- package/lib/app/db/partner.js +91 -0
- package/lib/app/extensions/index.js +13 -0
- package/lib/app/extensions/theme-app.js +103 -0
- package/lib/app/index.js +37 -0
- package/lib/app/inquirers/choose-app.js +79 -0
- package/lib/app/inquirers/choose-partner.js +74 -0
- package/lib/app/inquirers/version.js +131 -0
- package/lib/app/log.js +15 -0
- package/lib/app/login.js +126 -0
- package/lib/app/logout.js +16 -0
- package/lib/auth/getCode.js +10 -6
- package/lib/auth/index.js +8 -7
- package/lib/commands/login.js +19 -7
- package/lib/commands/logout.js +14 -5
- package/lib/commands/switch.js +1 -1
- package/lib/config.js +3 -0
- package/lib/utils.js +14 -0
- package/package.json +12 -13
- package/LICENSE +0 -21
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
fs.ensureDirSync(path.join(os.homedir(), '/.cache/shoplazza'));
|
|
6
|
+
const db = require('better-sqlite3')(path.join(os.homedir(), '/.cache/shoplazza/.partner.db'), {});
|
|
7
|
+
|
|
8
|
+
const PARTNER_KEYS = {
|
|
9
|
+
SESSION_ID: 'session_id',
|
|
10
|
+
EXPIRES_IN: 'expires_in',
|
|
11
|
+
LOGIN_TIMESTAMP: 'login_timestamp',
|
|
12
|
+
PARTNER_ID: 'partner_id',
|
|
13
|
+
APP: 'app',
|
|
14
|
+
EXTENSION_TYPE: 'extension_type',
|
|
15
|
+
EXTENSION_NAME: 'extension_name',
|
|
16
|
+
EXTENSION_ID: 'extension_id'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
db.prepare(
|
|
20
|
+
`CREATE TABLE IF NOT EXISTS partner (
|
|
21
|
+
id integer primary key AUTOINCREMENT,
|
|
22
|
+
${PARTNER_KEYS.SESSION_ID} TEXT,
|
|
23
|
+
${PARTNER_KEYS.EXPIRES_IN} TEXT,
|
|
24
|
+
${PARTNER_KEYS.LOGIN_TIMESTAMP} TEXT,
|
|
25
|
+
${PARTNER_KEYS.PARTNER_ID} TEXT,
|
|
26
|
+
${PARTNER_KEYS.APP} TEXT,
|
|
27
|
+
${PARTNER_KEYS.EXTENSION_TYPE} TEXT,
|
|
28
|
+
${PARTNER_KEYS.EXTENSION_NAME} TEXT,
|
|
29
|
+
${PARTNER_KEYS.EXTENSION_ID} TEXT
|
|
30
|
+
)`
|
|
31
|
+
).run();
|
|
32
|
+
|
|
33
|
+
const get = () => {
|
|
34
|
+
return db.prepare('select * from partner limit 0,1;').get();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const getValue = (key) => {
|
|
38
|
+
const partner = get();
|
|
39
|
+
if (partner) {
|
|
40
|
+
return partner[key];
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const getNewValues = (values) => {
|
|
46
|
+
const currentValues = Object.values(PARTNER_KEYS).reduce(
|
|
47
|
+
(res, key) => Object.assign(res, { [key]: getValue(key) }),
|
|
48
|
+
{}
|
|
49
|
+
);
|
|
50
|
+
if (typeof values === 'object' && values !== null && !Array.isArray(values)) {
|
|
51
|
+
return Object.assign(currentValues, values);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return currentValues;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const getApp = () => {
|
|
58
|
+
const appsStr = getValue(PARTNER_KEYS.APP);
|
|
59
|
+
if (appsStr) {
|
|
60
|
+
return JSON.parse(appsStr);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const empty = () => {
|
|
65
|
+
db.prepare(`delete from partner`).run();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const set = (values) => {
|
|
69
|
+
db.prepare(
|
|
70
|
+
`INSERT OR REPLACE INTO partner (id, ${PARTNER_KEYS.SESSION_ID}, ${PARTNER_KEYS.EXPIRES_IN}, ${PARTNER_KEYS.LOGIN_TIMESTAMP}, ${PARTNER_KEYS.PARTNER_ID}, ${PARTNER_KEYS.APP}, ${PARTNER_KEYS.EXTENSION_TYPE}, ${PARTNER_KEYS.EXTENSION_NAME}, ${PARTNER_KEYS.EXTENSION_ID}) values (
|
|
71
|
+
(select id from partner where ${PARTNER_KEYS.SESSION_ID} = @${PARTNER_KEYS.SESSION_ID}),
|
|
72
|
+
@${PARTNER_KEYS.SESSION_ID},
|
|
73
|
+
@${PARTNER_KEYS.EXPIRES_IN},
|
|
74
|
+
@${PARTNER_KEYS.LOGIN_TIMESTAMP},
|
|
75
|
+
@${PARTNER_KEYS.PARTNER_ID},
|
|
76
|
+
@${PARTNER_KEYS.APP},
|
|
77
|
+
@${PARTNER_KEYS.EXTENSION_TYPE},
|
|
78
|
+
@${PARTNER_KEYS.EXTENSION_NAME},
|
|
79
|
+
@${PARTNER_KEYS.EXTENSION_ID}
|
|
80
|
+
)`
|
|
81
|
+
).run(getNewValues(values));
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
module.exports = {
|
|
85
|
+
get,
|
|
86
|
+
getValue,
|
|
87
|
+
getApp,
|
|
88
|
+
set,
|
|
89
|
+
empty,
|
|
90
|
+
PARTNER_KEYS
|
|
91
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { generateThemeDirectory } = require('./theme-app');
|
|
2
|
+
const { done } = require('../log');
|
|
3
|
+
|
|
4
|
+
const themeAppHandler = async (dirname = './') => {
|
|
5
|
+
(await generateThemeDirectory(dirname)) && done();
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const checkoutUIHandler = async () => {};
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
themeAppHandler,
|
|
12
|
+
checkoutUIHandler
|
|
13
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const glob = require('glob');
|
|
5
|
+
const repo = require('download-git-repo');
|
|
6
|
+
const CleanCSS = require('clean-css');
|
|
7
|
+
const UglifyJS = require('uglify-js');
|
|
8
|
+
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { line } = require('../log');
|
|
12
|
+
|
|
13
|
+
const rev = (input) => crypto.createHash('md5').update(input).digest('hex').slice(0, 8);
|
|
14
|
+
const cleanCSS = new CleanCSS({
|
|
15
|
+
advanced: false,
|
|
16
|
+
aggressiveMerging: false
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const generateThemeDirectory = async (dirname = './') => {
|
|
20
|
+
const spinner = ora(chalk.cyan(`Waiting generate your theme app project...`)).start();
|
|
21
|
+
try {
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
repo('Shoplazza/theme-extension-template', dirname, {}, (err) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
reject(JSON.stringify(err));
|
|
26
|
+
} else {
|
|
27
|
+
resolve(true);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
spinner.succeed(chalk.cyan(`Generate app successfully`));
|
|
33
|
+
return true;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
spinner.fail();
|
|
36
|
+
console.log(chalk.red(e));
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const buildThemeAssets = async (outputDir = './dist', pathPrefix = '.') => {
|
|
41
|
+
line();
|
|
42
|
+
ora(chalk.cyan(`Prepare Build assets ...`)).succeed();
|
|
43
|
+
|
|
44
|
+
const manifest = {};
|
|
45
|
+
|
|
46
|
+
// build assets css
|
|
47
|
+
const spinner = ora(chalk.cyan(`Build assets ...`)).start();
|
|
48
|
+
try {
|
|
49
|
+
const cssPathnames = glob.sync('./assets/*.css');
|
|
50
|
+
const jsPathnames = glob.sync('./assets/*.js');
|
|
51
|
+
|
|
52
|
+
const pathnames = [...cssPathnames, ...jsPathnames];
|
|
53
|
+
for (const pathname of pathnames) {
|
|
54
|
+
const filename = path.basename(pathname);
|
|
55
|
+
const extname = path.extname(pathname);
|
|
56
|
+
const fileContent = fs.readFileSync(pathname, 'utf8');
|
|
57
|
+
const hash = rev(fileContent);
|
|
58
|
+
|
|
59
|
+
let minified = '';
|
|
60
|
+
let filenameWithHash = '';
|
|
61
|
+
if (extname.includes('css')) {
|
|
62
|
+
minified = cleanCSS.minify(fileContent);
|
|
63
|
+
if (minified.errors.length) {
|
|
64
|
+
spinner.fail(minified.errors);
|
|
65
|
+
process.exit(-1);
|
|
66
|
+
}
|
|
67
|
+
filenameWithHash = `${filename.split('.')[0]}-${hash}.css`;
|
|
68
|
+
const assetsPath = `${outputDir}/${filenameWithHash}`;
|
|
69
|
+
fs.ensureFileSync(assetsPath);
|
|
70
|
+
fs.writeFileSync(assetsPath, minified.styles);
|
|
71
|
+
} else if (extname.includes('js')) {
|
|
72
|
+
minified = UglifyJS.minify(fileContent);
|
|
73
|
+
if (minified.error) {
|
|
74
|
+
log.error(minified.error);
|
|
75
|
+
process.exit(-1);
|
|
76
|
+
}
|
|
77
|
+
filenameWithHash = `${filename.split('.')[0]}-${hash}.js`;
|
|
78
|
+
const assetsPath = `${outputDir}/${filenameWithHash}`;
|
|
79
|
+
fs.ensureFileSync(assetsPath);
|
|
80
|
+
fs.writeFileSync(assetsPath, minified.code);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
manifest[filename] = pathPrefix + '/assets/' + filenameWithHash;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fs.writeFileSync(`./assets-manifest.json`, JSON.stringify(manifest));
|
|
87
|
+
spinner.succeed(chalk.cyan(`Build assets done`));
|
|
88
|
+
return true;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
spinner.fail(chalk.red(e.message));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// build assets js
|
|
94
|
+
const jsSpinner = ora(chalk.cyan(`Build js ...`)).start();
|
|
95
|
+
try {
|
|
96
|
+
jsSpinner.succeed(chalk.cyan(`Build js done`));
|
|
97
|
+
} catch (e) {}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
generateThemeDirectory,
|
|
102
|
+
buildThemeAssets
|
|
103
|
+
};
|
package/lib/app/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { checkAndLogin } = require('./login');
|
|
2
|
+
const { build } = require('./commands/build');
|
|
3
|
+
const { deploy } = require('./commands/deploy');
|
|
4
|
+
const { generate } = require('./commands/generate');
|
|
5
|
+
const { publish } = require('./commands/publish');
|
|
6
|
+
const { choosePartner } = require('./inquirers/choose-partner');
|
|
7
|
+
const { chooseApp } = require('./inquirers/choose-app');
|
|
8
|
+
|
|
9
|
+
const generateExtension = async () => {
|
|
10
|
+
(await checkAndLogin()) && (await generate());
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const deployExtension = async () => {
|
|
14
|
+
(await checkAndLogin()) && (await deploy());
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const publishExtension = async () => {
|
|
18
|
+
(await checkAndLogin()) && (await publish());
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const retry = async (options) => {
|
|
22
|
+
if (options.partner) {
|
|
23
|
+
(await checkAndLogin()) && (await choosePartner()) && (await chooseApp());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (options.app) {
|
|
27
|
+
(await checkAndLogin()) && (await chooseApp());
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
generateExtension,
|
|
33
|
+
deployExtension,
|
|
34
|
+
publishExtension,
|
|
35
|
+
buildExtension: build,
|
|
36
|
+
retry
|
|
37
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const ora = require('ora');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
|
|
6
|
+
const { getValue, PARTNER_KEYS, set, get } = require('../db/partner');
|
|
7
|
+
const { PARNTER_URL } = require('../constants');
|
|
8
|
+
|
|
9
|
+
const requestAppList = async () => {
|
|
10
|
+
const spinner = ora(chalk.cyan(`Waiting request your apps ...`)).start();
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
14
|
+
if (!partnerId) {
|
|
15
|
+
spinner.fail('You have to choose a partner first!');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const url = `${PARNTER_URL}/api/partners/${partnerId}/apps`;
|
|
20
|
+
const result = await axios.get(url, {
|
|
21
|
+
headers: {
|
|
22
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
23
|
+
'x-shoplazza-partner-id': partnerId
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (!result.data.length) {
|
|
28
|
+
spinner.fail(chalk.red(`You haven't any apps yet, please create one at ${PARNTER_URL} fist!`));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
spinner.succeed();
|
|
33
|
+
return result.data;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
spinner.fail();
|
|
36
|
+
console.log(
|
|
37
|
+
chalk.red(
|
|
38
|
+
`Failed to get partners, please try to run \n ${chalk.green(
|
|
39
|
+
' shoplazza app retry -p '
|
|
40
|
+
)} \nor contact with Shoplazza!`
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const chooseApp = async () => {
|
|
47
|
+
const list = await requestAppList();
|
|
48
|
+
if (!list) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const answer = await inquirer.prompt([
|
|
54
|
+
{
|
|
55
|
+
type: 'list',
|
|
56
|
+
name: 'appId',
|
|
57
|
+
message: 'Choose your app:',
|
|
58
|
+
default: list[0].id,
|
|
59
|
+
prefix: '*',
|
|
60
|
+
choices: list.map((app) => {
|
|
61
|
+
return {
|
|
62
|
+
name: app.name,
|
|
63
|
+
value: app.id
|
|
64
|
+
};
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
const app = list.find((app) => app.id === answer['appId']);
|
|
70
|
+
set({ [PARTNER_KEYS.APP]: JSON.stringify(app) });
|
|
71
|
+
return true;
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.log(e);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
chooseApp
|
|
79
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const ora = require('ora');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
|
|
6
|
+
const { getValue, PARTNER_KEYS, set, get } = require('../db/partner');
|
|
7
|
+
const { PARNTER_URL } = require('../constants');
|
|
8
|
+
const log = require('../../log');
|
|
9
|
+
|
|
10
|
+
const requestPartnerList = async () => {
|
|
11
|
+
const spinner = ora(chalk.cyan(`Waiting request your partners ...`)).start();
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const url = `${PARNTER_URL}/api/partners`;
|
|
15
|
+
const sessionId = getValue(PARTNER_KEYS.SESSION_ID);
|
|
16
|
+
|
|
17
|
+
const result = await axios.get(url, {
|
|
18
|
+
headers: {
|
|
19
|
+
Cookie: `awesomev2=${sessionId}`
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!result.data.length) {
|
|
24
|
+
spinner.fail(chalk.red(`You haven't any partners yet, please create one at ${PARNTER_URL} fist!`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
spinner.succeed();
|
|
29
|
+
return result.data;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
spinner.fail(e.message);
|
|
32
|
+
log.error(
|
|
33
|
+
chalk.red(
|
|
34
|
+
`Failed to get partners, please try to run \n ${chalk.green(
|
|
35
|
+
' shoplazza app retry -p '
|
|
36
|
+
)} \nor contact with Shoplazza!`
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const choosePartner = async () => {
|
|
43
|
+
const list = await requestPartnerList();
|
|
44
|
+
if (!list) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const answer = await inquirer.prompt([
|
|
50
|
+
{
|
|
51
|
+
type: 'list',
|
|
52
|
+
name: 'partnerId',
|
|
53
|
+
message: 'Choose your partner:',
|
|
54
|
+
default: list[0].partner_id,
|
|
55
|
+
prefix: '*',
|
|
56
|
+
choices: list.map((app) => {
|
|
57
|
+
return {
|
|
58
|
+
name: `${app.partner_id} ${app.business_name}`,
|
|
59
|
+
value: String(app.partner_id)
|
|
60
|
+
};
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
set({ [PARTNER_KEYS.PARTNER_ID]: answer['partnerId'] });
|
|
66
|
+
return true;
|
|
67
|
+
} catch (e) {
|
|
68
|
+
console.log(e);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
choosePartner
|
|
74
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
|
|
5
|
+
const { PARNTER_URL } = require('../constants');
|
|
6
|
+
const { getApp, getValue, PARTNER_KEYS } = require('../db/partner');
|
|
7
|
+
const { line } = require('../log');
|
|
8
|
+
|
|
9
|
+
const requestLastVersion = async () => {
|
|
10
|
+
try {
|
|
11
|
+
const app = getApp();
|
|
12
|
+
if (!app) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
|
|
16
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
17
|
+
|
|
18
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/last_version`;
|
|
19
|
+
const res = await axios.get(url, {
|
|
20
|
+
headers: {
|
|
21
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
22
|
+
'x-shoplazza-partner-id': partnerId
|
|
23
|
+
},
|
|
24
|
+
validateStatus(status) {
|
|
25
|
+
if (status === 404) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return status >= 200 && status < 299;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (res.data.errors) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return res.data.version;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.log(chalk.red(e.message || e));
|
|
39
|
+
console.log(chalk.red(JSON.stringify(e.response?.data)));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const requestVersionsData = async (params = {}) => {
|
|
44
|
+
try {
|
|
45
|
+
const app = getApp();
|
|
46
|
+
if (!app) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
|
|
50
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
51
|
+
|
|
52
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/versions`;
|
|
53
|
+
const res = await axios.get(url, {
|
|
54
|
+
params,
|
|
55
|
+
headers: {
|
|
56
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
57
|
+
'x-shoplazza-partner-id': partnerId
|
|
58
|
+
},
|
|
59
|
+
validateStatus(status) {
|
|
60
|
+
if (status === 404) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return status >= 200 && status < 299;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (res.data.errors) {
|
|
68
|
+
throw new Error(JSON.stringify(res.data.errors));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return res.data.data;
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.log(chalk.red(e.message || e));
|
|
74
|
+
console.log(chalk.red(JSON.stringify(e.response?.data)));
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const inputVersion = async () => {
|
|
79
|
+
line();
|
|
80
|
+
const lastVersionData = await requestLastVersion({ limit: 1 });
|
|
81
|
+
const hint = lastVersionData ? chalk.gray(`(last version: ${lastVersionData.version})`) : '';
|
|
82
|
+
|
|
83
|
+
const answer = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: 'input',
|
|
86
|
+
name: 'extensionVersion',
|
|
87
|
+
message: `${chalk.blue('Input your extension version')} ${hint}:`,
|
|
88
|
+
prefix: `${chalk.green('⭐️')}`
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
return answer['extensionVersion'];
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const selectVersion = async () => {
|
|
96
|
+
line();
|
|
97
|
+
|
|
98
|
+
const versionDataList = await requestVersionsData();
|
|
99
|
+
if (!versionDataList) {
|
|
100
|
+
console.log(chalk.red('Please deploy a version first!'));
|
|
101
|
+
line();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const answer = await inquirer.prompt([
|
|
105
|
+
{
|
|
106
|
+
type: 'list',
|
|
107
|
+
name: 'versionData',
|
|
108
|
+
message: `${chalk.blue('Choose a version to publish:')}`,
|
|
109
|
+
default: versionDataList[0].version,
|
|
110
|
+
prefix: `${chalk.blue('🐱')}`,
|
|
111
|
+
choices: versionDataList.map((v) => {
|
|
112
|
+
return {
|
|
113
|
+
name: `${v.version} ${v.published ? chalk.green('published') : ''}`,
|
|
114
|
+
value: {
|
|
115
|
+
version: v.version,
|
|
116
|
+
appId: v.app_id,
|
|
117
|
+
versionId: v.version_id,
|
|
118
|
+
extensionId: v.extension_id
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
return answer['versionData'];
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
inputVersion,
|
|
130
|
+
selectVersion
|
|
131
|
+
};
|
package/lib/app/log.js
ADDED
package/lib/app/login.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const open = require('open');
|
|
4
|
+
const axios = require('axios');
|
|
5
|
+
const { fork } = require('child_process');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const { set, PARTNER_KEYS, get, empty } = require('./db/partner');
|
|
9
|
+
const { getClientId } = require('../utils');
|
|
10
|
+
const { PARNTER_URL, LOGIN_BASE_URL, CLIENT_ID } = require('./constants');
|
|
11
|
+
const { REDIRECT_URI } = require('../config');
|
|
12
|
+
const log = require('../log');
|
|
13
|
+
const { choosePartner } = require('./inquirers/choose-partner');
|
|
14
|
+
const { chooseApp } = require('./inquirers/choose-app');
|
|
15
|
+
|
|
16
|
+
const isLogin = () => {
|
|
17
|
+
const values = get();
|
|
18
|
+
const time = new Date().getTime();
|
|
19
|
+
|
|
20
|
+
if (!values || !values[PARTNER_KEYS.SESSION_ID]) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (Number(time) - Number(values[PARTNER_KEYS.LOGIN_TIMESTAMP]) >= Number(values[PARTNER_KEYS.LOGIN_TIMESTAMP])) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const stop = async (time = 1000) => {
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
resolve(true);
|
|
35
|
+
}, time);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const openLoginPage = () => {
|
|
40
|
+
open(
|
|
41
|
+
`${LOGIN_BASE_URL}/switch_account?lack=0&continue=${encodeURIComponent(
|
|
42
|
+
`${LOGIN_BASE_URL}/api/oauth/authorize?action=login&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code`
|
|
43
|
+
)}`
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const getCode = () => {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const child = fork(path.join(__dirname, '../auth/child.js'), { timeout: 60 * 1000 });
|
|
50
|
+
child.on('message', function (message) {
|
|
51
|
+
if (message.code) {
|
|
52
|
+
resolve(message.code);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
child.on('close', function (message) {
|
|
56
|
+
// Timeout
|
|
57
|
+
if (message === null) {
|
|
58
|
+
log.error(chalk.red('✗ Timed out while waiting for response from Shoplazza'));
|
|
59
|
+
reject('timeout');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
openLoginPage();
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const postAccessToken = async (code) => {
|
|
67
|
+
try {
|
|
68
|
+
const url = `${LOGIN_BASE_URL}/api/oauth/token`;
|
|
69
|
+
const { data } = await axios.post(
|
|
70
|
+
url,
|
|
71
|
+
`client_id=${CLIENT_ID}&code=${code}&grant_type=authorization_code&redirect_uri=${REDIRECT_URI}`,
|
|
72
|
+
{
|
|
73
|
+
headers: {
|
|
74
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
set({
|
|
80
|
+
[PARTNER_KEYS.SESSION_ID]: data.session_id,
|
|
81
|
+
[PARTNER_KEYS.EXPIRES_IN]: data.expires_in,
|
|
82
|
+
[PARTNER_KEYS.LOGIN_TIMESTAMP]: new Date().getTime()
|
|
83
|
+
});
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.log(e);
|
|
86
|
+
log.error(chalk.red('\n✗ Failed to post access token'));
|
|
87
|
+
process.exit(-1);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const login = async () => {
|
|
92
|
+
let spinner;
|
|
93
|
+
try {
|
|
94
|
+
spinner = ora(`Waiting logging in to ${chalk.green(PARNTER_URL)} \r`).start();
|
|
95
|
+
|
|
96
|
+
const code = await getCode(PARNTER_URL);
|
|
97
|
+
await postAccessToken(code);
|
|
98
|
+
|
|
99
|
+
spinner && spinner.succeed();
|
|
100
|
+
log.info('\n', chalk.green(`Logged into ${PARNTER_URL} successfully!`), '\n');
|
|
101
|
+
return true;
|
|
102
|
+
} catch (e) {
|
|
103
|
+
spinner && spinner.fail();
|
|
104
|
+
log.error(chalk.red(`✗ Logged into ${PARNTER_URL} failed`));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const loginAndChoose = async () => {
|
|
109
|
+
(await login()) && (await choosePartner()) && (await chooseApp());
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const checkAndLogin = async () => {
|
|
113
|
+
if (!isLogin()) {
|
|
114
|
+
log.info('\n', chalk.red('Your identity has expired or you are not logged in, please log in first!'), '\n');
|
|
115
|
+
empty();
|
|
116
|
+
await stop(1000);
|
|
117
|
+
await loginAndChoose();
|
|
118
|
+
await stop(1000);
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
loginIntoPartner: loginAndChoose,
|
|
125
|
+
checkAndLogin
|
|
126
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const log = require('../log');
|
|
3
|
+
const { empty } = require('./db/partner');
|
|
4
|
+
|
|
5
|
+
const logoutPartner = () => {
|
|
6
|
+
try {
|
|
7
|
+
empty();
|
|
8
|
+
log.info('\n', chalk.green(`Logged out your partner account successfully!`), '\n');
|
|
9
|
+
} catch (e) {
|
|
10
|
+
log.error(chalk.red(`✗ Failed to logout your partner account`));
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
logoutPartner
|
|
16
|
+
};
|