Skip to content

Commit 4d63606

Browse files
authored
fixes to pos-cli modules download (#666)
* fixes to pos-cli modules download * fix test * fix data.test.js * update tests * push
1 parent 194fea1 commit 4d63606

File tree

5 files changed

+167
-26
lines changed

5 files changed

+167
-26
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 5.4.0
4+
5+
* Improvement: `pos-cli modules download <module>` will by default download version defined in app/pos-modules.lock.json file
6+
* Improvement: `pos-cli modules download <module>` will automatically download all dependencies defined in module's template-values.json file if they do not exist yet
7+
* Improvement: Add `--force-dependencies` flag to `pos-cli modules download <module>` command to force re-downloading dependencies
8+
39
## 5.3.0
410

511
* Feature: `pos-cli modules overwrites` utility commands

bin/pos-cli-modules-download.js

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const downloadFile = require('../lib/downloadFile');
77

88
const { unzip } = require('../lib/unzip');
99
const Portal = require('../lib/portal');
10+
const fs = require('fs');
11+
const path = require('path');
1012

1113
// importing ESM modules in CommonJS project
1214
let ora;
@@ -18,29 +20,74 @@ const initializeEsmModules = async () => {
1820
return true;
1921
}
2022

23+
const downloadModule = async (module, lockData) => {
24+
const filename = 'modules.zip';
25+
try {
26+
if (!module.includes('@') && lockData) {
27+
if (lockData[module] === undefined ) {
28+
logger.Warn(`Warning: Can't find ${module} in app/pos-modules.lock.json, will download the latest version`);
29+
}
30+
const moduleVersion = lockData[module];
31+
if (moduleVersion) {
32+
module = `${module}@${moduleVersion}`;
33+
}
34+
}
35+
36+
logger.Info(`Searching for ${module}...`);
37+
const moduleVersion = await Portal.moduleVersionsSearch(module);
38+
logger.Info(`Downloading ${module}...`);
39+
await downloadFile(moduleVersion['public_archive'], filename);
40+
logger.Info(`Unzipping ${module}...`);
41+
await unzip(filename, `${process.cwd()}/modules`);
42+
shell.rm(filename);
43+
} catch (error) {
44+
if (error.statusCode === 404) {
45+
throw `${module}: 404 not found`;
46+
} else {
47+
throw `${module}: ${error.message}`;
48+
}
49+
}
50+
}
51+
2152
program
2253
.name('pos-cli modules download')
2354
.arguments('<module>', 'module name, ex. core, [email protected]')
55+
.option('--force-dependencies', 'Force downloading dependencies, even if they are already present')
2456
.action(async (module, params) => {
25-
const filename = 'modules.zip';
57+
const lockFilePath = path.join('app', 'pos-modules.lock.json');
58+
const forceDependencies = params.forceDependencies;
2659

2760
await initializeEsmModules();
28-
const spinner = ora({ text: 'Exporting', stream: process.stdout });
29-
spinner.start();
30-
31-
Portal.moduleVersionsSearch(module)
32-
.then(moduleVersion => downloadFile(moduleVersion['public_archive'], filename))
33-
.then(() => unzip(filename, `${process.cwd()}/modules`))
34-
.then(() => shell.rm(filename))
35-
.then(() => spinner.succeed('Downloading files'))
36-
.catch({ statusCode: 404 }, () => {
37-
spinner.fail('Export failed');
38-
logger.Error('[404] Module not found');
39-
})
40-
.catch(e => {
41-
spinner.fail('Export failed');
42-
logger.Error(e.message);
43-
});
61+
62+
let lockData;
63+
64+
if (fs.existsSync(lockFilePath)) {
65+
lockData = JSON.parse(fs.readFileSync(lockFilePath, 'utf-8'))['modules'];
66+
} else {
67+
logger.Warn(`Warning: Can't find app/pos-modules.lock.json`);
68+
}
69+
70+
try {
71+
await downloadModule(module, lockData);
72+
logger.Info("Resolving dependencies...");
73+
const templateValuesPath = path.join('modules', module.split('@')[0], 'template-values.json');
74+
if (fs.existsSync(templateValuesPath)) {
75+
const templateValuesContent = fs.readFileSync(templateValuesPath, 'utf-8');
76+
const templateValues = JSON.parse(templateValuesContent);
77+
const dependencies = templateValues.dependencies || {};
78+
79+
for (const depName of Object.keys(dependencies)) {
80+
if (forceDependencies || !fs.existsSync(`modules/${depName}`)) {
81+
await downloadModule(depName, lockData);
82+
}
83+
}
84+
} else {
85+
logger.Warn(`Warning: No template-values.json file for module ${module} - skipping dependencies`);
86+
}
87+
logger.Success(`Completed downloading ${module}`);
88+
} catch (error) {
89+
logger.Error(error);
90+
}
4491
});
4592

4693
program.parse(process.argv);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"modules": {
3+
"user": "3.0.8"
4+
}
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"modules": {
3+
"user": "3.0.8",
4+
"core": "1.5.5"
5+
}
6+
}

test/modules-download.test.js

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,111 @@ const cwd = name => path.join(process.cwd(), 'test', 'fixtures', name);
1212
const run = async (fixtureName, options) => await exec(`${cliPath} modules download ${options}`, { cwd: cwd(fixtureName), env: process.env });
1313

1414
describe('Successful download', () => {
15-
test('download test module', async () => {
15+
16+
test('download test module in the correct version', async () => {
17+
const pathToModuleJson = `${cwd('deploy/modules_test')}/modules/tests/template-values.json`;
18+
const pathToDirectory = `${cwd('deploy/modules_test')}/modules`;
19+
20+
const { stdout } = await run('deploy/modules_test', 'tests');
21+
expect(stdout).toContain('Downloading [email protected]');
22+
expect(fs.existsSync(pathToModuleJson)).toBeTruthy();
23+
24+
const moduleJson = JSON.parse(fs.readFileSync(pathToModuleJson, 'utf8'));
25+
expect(moduleJson.version).toBe('0.0.3');
26+
27+
fs.rm(pathToDirectory, { recursive: true }, (err) => {
28+
if(err){
29+
console.error(err.message);
30+
return;
31+
}
32+
});
33+
});
34+
35+
test('download test module in a specific version', async () => {
1636
const pathToModuleJson = `${cwd('deploy/modules_test')}/modules/tests/template-values.json`;
1737
const pathToDirectory = `${cwd('deploy/modules_test')}/modules`;
1838

19-
const { stdout, stderr } = await run('deploy/modules_test', 'tests');
20-
expect(stdout).toMatch('Downloading files');
39+
const { stdout } = await run('deploy/modules_test', 'tests@1.0.0');
40+
expect(stdout).toContain('Downloading [email protected]');
2141
expect(fs.existsSync(pathToModuleJson)).toBeTruthy();
2242

43+
const moduleJson = JSON.parse(fs.readFileSync(pathToModuleJson, 'utf8'));
44+
expect(moduleJson.version).toBe('1.0.0');
45+
2346
fs.rm(pathToDirectory, { recursive: true }, (err) => {
2447
if(err){
25-
console.error(err.message);
26-
return;
48+
console.error(err.message);
49+
return;
2750
}
2851
});
2952
});
53+
54+
test('download the latest test module if no app/pos-modules.lock.json', async () => {
55+
const pathToModuleJson = `${cwd('deploy/empty')}/modules/tests/template-values.json`;
56+
const pathToDirectory = `${cwd('deploy/empty')}/modules`;
57+
58+
const { stdout, stderr } = await run('deploy/empty', 'tests');
59+
expect(stdout).toContain('Downloading tests...');
60+
expect(stderr).toContain('Warning: Can\'t find app/pos-modules.lock.json');
61+
expect(fs.existsSync(pathToModuleJson)).toBeTruthy();
62+
63+
fs.rm(pathToDirectory, { recursive: true }, (err) => {
64+
if(err){
65+
console.error(err.message);
66+
return;
67+
}
68+
});
69+
});
70+
71+
72+
test('download user module with dependencies', async () => {
73+
const pathToUserModuleJson = `${cwd('deploy/modules_user')}/modules/user/template-values.json`;
74+
const pathToCoreModuleJson = `${cwd('deploy/modules_user')}/modules/core/template-values.json`;
75+
const pathToDirectory = `${cwd('deploy/modules_user')}/modules`;
76+
77+
const { stdout: stdout1 } = await run('deploy/modules_user', 'user');
78+
expect(stdout1).toContain('Downloading [email protected]');
79+
expect(fs.existsSync(pathToUserModuleJson)).toBeTruthy();
80+
expect(stdout1).toContain('Downloading [email protected]');
81+
expect(fs.existsSync(pathToCoreModuleJson)).toBeTruthy();
82+
83+
const userModuleJson = JSON.parse(fs.readFileSync(pathToUserModuleJson, 'utf8'));
84+
expect(userModuleJson.version).toBe('3.0.8');
85+
const coreModuleJson = JSON.parse(fs.readFileSync(pathToCoreModuleJson, 'utf8'));
86+
expect(coreModuleJson.version).toBe('1.5.5');
87+
88+
// do not download dependency again
89+
90+
const { stdout: stdout2 } = await run('deploy/modules_user', 'user');
91+
expect(stdout2).toContain('Downloading [email protected]');
92+
expect(stdout2).not.toContain('Downloading [email protected]');
93+
94+
// download again if forced
95+
96+
const { stdout: stdout3 } = await run('deploy/modules_user', 'user --force-dependencies');
97+
expect(stdout3).toContain('Downloading [email protected]');
98+
expect(stdout3).toContain('Downloading [email protected]');
99+
100+
fs.rm(pathToDirectory, { recursive: true }, (err) => {
101+
if (err) {
102+
console.error(err.message);
103+
return;
104+
}
105+
});
106+
}, 20000);
30107
});
31108

32109
describe('Failed download', () => {
33110
test('Module not found - non-existing module', async () => {
34-
const { stdout, stderr } = await run('deploy/modules_test', 'moduleNotFound');
35-
expect(stderr).toMatch('Module not found');
111+
const { stderr } = await run('deploy/modules_test', 'moduleNotFound');
112+
expect(stderr).toContain('moduleNotFound: 404 not found');
36113
});
37114
test('Module not found - no name for module', async () => {
38-
const { stdout, stderr } = await run('deploy/modules_test', '');
115+
const { stderr } = await run('deploy/modules_test', '');
39116
expect(stderr).toMatch("error: missing required argument 'module'");
40117
});
41118
test('Unescaped characters in request path', async () => {
42-
const { stdout, stderr } = await run('deploy/modules_test', 'ąę');
119+
const { stderr } = await run('deploy/modules_test', 'ąę');
43120
expect(stderr).toMatch('[ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters');
44121
});
45122
});

0 commit comments

Comments
 (0)