Skip to content

Commit b641b14

Browse files
authored
Merge pull request #2 from MicroAppJS/develop
Develop
2 parents 4834ac3 + 5f08da2 commit b641b14

16 files changed

Lines changed: 936 additions & 96 deletions

File tree

index.d.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// <reference types="node"/>
2+
13
import fs from 'fs-extra';
24
import chalk from 'chalk';
35
import cheerio from 'cheerio';
@@ -11,6 +13,9 @@ import globParent from 'glob-parent';
1113
import isGlob from 'is-glob';
1214
import npa from 'npm-package-arg';
1315
import parseGitUrl from 'git-url-parse';
16+
import multimatch from 'multimatch';
17+
import stringifyObject from 'stringify-object';
18+
import LRU from 'lru-cache';
1419

1520
export function tryRequire( id: string, req?: Object): any | null;
1621
export function assert(value: any, message?: string | Error): void;
@@ -22,15 +27,20 @@ import * as loadFile from './src/loadFile';
2227
import * as logger from './src/logger';
2328
import * as smartMerge from './src/smartMerge';
2429
import * as virtualFile from './src/virtualFile';
30+
import * as openBrowser from './src/openBrowser';
31+
import * as env from './src/env';
32+
import * as validateSchema from './src/validateSchema';
2533

2634
export {
2735
moduleAlias,
2836
getPadLength,
2937
injectHtml,
3038
loadFile,
31-
logger,
3239
smartMerge,
3340
virtualFile,
41+
logger,
42+
openBrowser,
43+
env,
3444
};
3545

3646
export {
@@ -48,4 +58,7 @@ export {
4858
isGlob,
4959
npa,
5060
parseGitUrl,
61+
multimatch,
62+
stringifyObject,
63+
LRU,
5164
}

index.js

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
'use strict';
22

3+
const output = {};
4+
5+
function defineProperty(key, from, to = output) {
6+
if (to[key]) throw new Error(`"${key}" already exsits!`);
7+
// lazy
8+
Object.defineProperty(to, key, {
9+
get() {
10+
return require(from[key]);
11+
},
12+
});
13+
}
14+
315
const internal = [
416
'moduleAlias',
517
'getPadLength',
@@ -8,12 +20,17 @@ const internal = [
820
'logger',
921
'smartMerge',
1022
'virtualFile',
23+
'openBrowser',
24+
'Env',
25+
'validateSchema',
1126
].reduce((obj, key) => {
12-
obj[key] = require(`./src/${key}`);
27+
obj[key] = `./src/${key}`;
1328
return obj;
1429
}, {});
1530

16-
internal.assert = internal.logger.assert.bind(internal.logger);
31+
Object.keys(internal).forEach(key => {
32+
defineProperty(key, internal);
33+
});
1734

1835
const thirdParty = {
1936
fs: 'fs-extra',
@@ -30,15 +47,29 @@ const thirdParty = {
3047
isGlob: 'is-glob',
3148
npa: 'npm-package-arg',
3249
parseGitUrl: 'git-url-parse',
50+
multimatch: 'multimatch',
51+
stringifyObject: 'stringify-object',
52+
LRU: 'lru-cache',
3353
};
3454

3555
Object.keys(thirdParty).forEach(key => {
36-
// lazy
37-
Object.defineProperty(internal, key, {
38-
get() {
39-
return require(thirdParty[key]);
40-
},
56+
defineProperty(key, thirdParty);
57+
});
58+
59+
60+
// ********************
61+
62+
const alias = {
63+
assert: () => {
64+
return output.logger.assert.bind(output.logger);
65+
},
66+
};
67+
68+
Object.keys(alias).forEach(key => {
69+
if (output[key]) throw new Error(`"${key}" already exsits!`);
70+
Object.defineProperty(output, key, {
71+
get: alias[key],
4172
});
4273
});
4374

44-
module.exports = internal;
75+
module.exports = output;

package.json

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@micro-app/shared-utils",
3-
"version": "0.1.0",
3+
"version": "0.1.7",
44
"description": "[Shared] shared utilities for micro-app.",
55
"main": "index.js",
66
"scripts": {
@@ -18,6 +18,7 @@
1818
},
1919
"files": [
2020
"src",
21+
"index.d.ts",
2122
"index.js"
2223
],
2324
"keywords": [
@@ -39,17 +40,19 @@
3940
]
4041
},
4142
"devDependencies": {
42-
"@types/jest": "^24.0.19",
43+
"@types/jest": "^24.0.23",
4344
"babel-eslint": "^10.0.3",
4445
"coveralls": "^3.0.7",
4546
"eslint": "^5.16.0",
4647
"eslint-config-2o3t": "^1.1.17",
47-
"husky": "^3.0.9",
48+
"husky": "^3.1.0",
4849
"jest": "^24.9.0",
49-
"lint-staged": "^9.4.2",
50+
"lint-staged": "^9.4.3",
5051
"webpack-merge": "^4.2.2"
5152
},
5253
"dependencies": {
54+
"ajv": "^6.10.2",
55+
"ajv-keywords": "^3.4.1",
5356
"assert": "^2.0.0",
5457
"chalk": "^2.4.2",
5558
"cheerio": "^1.0.0-rc.3",
@@ -58,16 +61,19 @@
5861
"git-url-parse": "^11.1.2",
5962
"glob-parent": "^5.1.0",
6063
"globby": "^10.0.1",
61-
"import-fresh": "^3.1.0",
64+
"import-fresh": "^3.2.1",
6265
"is-glob": "^4.0.1",
6366
"lodash": "^4.17.15",
67+
"lru-cache": "^5.1.1",
68+
"multimatch": "^4.0.0",
6469
"npm-package-arg": "^6.1.1",
6570
"npmlog": "^4.1.2",
6671
"ora": "^3.4.0",
6772
"parse-json": "^5.0.0",
6873
"semver": "^6.3.0",
6974
"semver-regex": "^3.1.0",
7075
"stream-to-string": "^1.2.0",
76+
"stringify-object": "^3.3.0",
7177
"try-require": "^1.2.1",
7278
"yaml": "^1.7.2"
7379
},

src/Env/index.js

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
'use strict';
2+
3+
const { execSync } = require('child_process');
4+
const fs = require('fs');
5+
const path = require('path');
6+
const LRU = require('lru-cache');
7+
const semver = require('semver');
8+
9+
let _hasYarn;
10+
const _yarnProjects = new LRU({
11+
max: 10,
12+
maxAge: 1000,
13+
});
14+
let _hasGit;
15+
const _gitProjects = new LRU({
16+
max: 10,
17+
maxAge: 1000,
18+
});
19+
20+
// env detection
21+
exports.hasYarn = () => {
22+
if (process.env.MICRO_APP_TEST) {
23+
return true;
24+
}
25+
if (_hasYarn != null) {
26+
return _hasYarn;
27+
}
28+
try {
29+
execSync('yarn --version', { stdio: 'ignore' });
30+
return (_hasYarn = true);
31+
} catch (e) {
32+
return (_hasYarn = false);
33+
}
34+
};
35+
36+
exports.hasProjectYarn = cwd => {
37+
if (_yarnProjects.has(cwd)) {
38+
return checkYarn(_yarnProjects.get(cwd));
39+
}
40+
41+
const lockFile = path.join(cwd, 'yarn.lock');
42+
const result = fs.existsSync(lockFile);
43+
_yarnProjects.set(cwd, result);
44+
return checkYarn(result);
45+
};
46+
47+
function checkYarn(result) {
48+
if (result && !exports.hasYarn()) throw new Error('The project seems to require yarn but it\'s not installed.');
49+
return result;
50+
}
51+
52+
exports.hasGit = () => {
53+
if (process.env.MICRO_APP_TEST) {
54+
return true;
55+
}
56+
if (_hasGit != null) {
57+
return _hasGit;
58+
}
59+
try {
60+
execSync('git --version', { stdio: 'ignore' });
61+
return (_hasGit = true);
62+
} catch (e) {
63+
return (_hasGit = false);
64+
}
65+
};
66+
67+
exports.hasProjectGit = cwd => {
68+
if (_gitProjects.has(cwd)) {
69+
return _gitProjects.get(cwd);
70+
}
71+
72+
let result;
73+
try {
74+
execSync('git status', { stdio: 'ignore', cwd });
75+
result = true;
76+
} catch (e) {
77+
result = false;
78+
}
79+
_gitProjects.set(cwd, result);
80+
return result;
81+
};
82+
83+
let _hasPnpm;
84+
let _pnpmVersion;
85+
const _pnpmProjects = new LRU({
86+
max: 10,
87+
maxAge: 1000,
88+
});
89+
90+
function getPnpmVersion() {
91+
if (_pnpmVersion != null) {
92+
return _pnpmVersion;
93+
}
94+
try {
95+
_pnpmVersion = execSync('pnpm --version', {
96+
stdio: [ 'pipe', 'pipe', 'ignore' ],
97+
}).toString();
98+
// there's a critical bug in pnpm 2
99+
// https://github.com/pnpm/pnpm/issues/1678#issuecomment-469981972
100+
// so we only support pnpm >= 3.0.0
101+
_hasPnpm = true;
102+
} catch (e) {}
103+
return _pnpmVersion || '0.0.0';
104+
}
105+
106+
exports.hasPnpmVersionOrLater = version => {
107+
if (process.env.MICRO_APP_TEST) {
108+
return true;
109+
}
110+
return semver.gte(getPnpmVersion(), version);
111+
};
112+
113+
exports.hasPnpm3OrLater = () => {
114+
return this.hasPnpmVersionOrLater('3.0.0');
115+
};
116+
117+
exports.hasProjectPnpm = cwd => {
118+
if (_pnpmProjects.has(cwd)) {
119+
return checkPnpm(_pnpmProjects.get(cwd));
120+
}
121+
122+
const lockFile = path.join(cwd, 'pnpm-lock.yaml');
123+
const result = fs.existsSync(lockFile);
124+
_pnpmProjects.set(cwd, result);
125+
return checkPnpm(result);
126+
};
127+
128+
function checkPnpm(result) {
129+
if (result && !exports.hasPnpm3OrLater()) {
130+
throw new Error(`The project seems to require pnpm${_hasPnpm ? ' >= 3' : ''} but it's not installed.`);
131+
}
132+
return result;
133+
}
134+
135+
// OS
136+
exports.isWindows = process.platform === 'win32';
137+
exports.isMacintosh = process.platform === 'darwin';
138+
exports.isLinux = process.platform === 'linux';
139+
140+
const browsers = {};
141+
let hasCheckedBrowsers = false;
142+
143+
function tryRun(cmd) {
144+
try {
145+
return execSync(cmd, {
146+
stdio: [ 0, 'pipe', 'ignore' ],
147+
}).toString().trim();
148+
} catch (e) {
149+
return '';
150+
}
151+
}
152+
153+
function getLinuxAppVersion(binary) {
154+
return tryRun(`${binary} --version`).replace(/^.* ([^ ]*)/g, '$1');
155+
}
156+
157+
function getMacAppVersion(bundleIdentifier) {
158+
const bundlePath = tryRun(`mdfind "kMDItemCFBundleIdentifier=='${bundleIdentifier}'"`);
159+
160+
if (bundlePath) {
161+
return tryRun(`/usr/libexec/PlistBuddy -c Print:CFBundleShortVersionString ${
162+
bundlePath.replace(/(\s)/g, '\\ ')
163+
}/Contents/Info.plist`);
164+
}
165+
}
166+
167+
Object.defineProperty(exports, 'installedBrowsers', {
168+
enumerable: true,
169+
get() {
170+
if (hasCheckedBrowsers) {
171+
return browsers;
172+
}
173+
hasCheckedBrowsers = true;
174+
175+
if (exports.isLinux) {
176+
browsers.chrome = getLinuxAppVersion('google-chrome');
177+
browsers.firefox = getLinuxAppVersion('firefox');
178+
} else if (exports.isMacintosh) {
179+
browsers.chrome = getMacAppVersion('com.google.Chrome');
180+
browsers.firefox = getMacAppVersion('org.mozilla.firefox');
181+
} else if (exports.isWindows) {
182+
// get chrome stable version
183+
// https://stackoverflow.com/a/51773107/2302258
184+
const chromeQueryResult = tryRun(
185+
'reg query "HKLM\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}" /v pv /reg:32'
186+
) || tryRun(
187+
'reg query "HKCU\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}" /v pv /reg:32'
188+
);
189+
if (chromeQueryResult) {
190+
const matched = chromeQueryResult.match(/REG_SZ\s+(\S*)$/);
191+
browsers.chrome = matched && matched[1];
192+
}
193+
194+
// get firefox version
195+
// https://community.spiceworks.com/topic/111518-how-to-determine-version-of-installed-firefox-in-windows-batchscript
196+
const ffQueryResult = tryRun(
197+
'reg query "HKLM\\Software\\Mozilla\\Mozilla Firefox" /v CurrentVersion'
198+
);
199+
if (ffQueryResult) {
200+
const matched = ffQueryResult.match(/REG_SZ\s+(\S*)$/);
201+
browsers.firefox = matched && matched[1];
202+
}
203+
}
204+
205+
return browsers;
206+
},
207+
});

src/constants/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
module.exports = {
4+
NAME: 'Micro App',
45
SCOPE_NAME: '@micro-app',
56
INJECT_ID: '_MICRO_APP_INJECT_',
67
};

0 commit comments

Comments
 (0)