@steedos/service-package-registry 2.1.50 → 2.1.54
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/main/default/manager/loader.js +1 -1
- package/main/default/manager/login.js +96 -0
- package/main/default/manager/npm_login.js +145 -0
- package/main/default/manager/package-json.js +111 -0
- package/main/default/manager/packages.js +21 -2
- package/main/default/manager/registry.js +6 -4
- package/main/default/routes/registry.router.js +14 -0
- package/package.json +4 -3
- package/package.service.js +89 -8
|
@@ -63,7 +63,7 @@ const loadPackages = async ()=>{
|
|
|
63
63
|
}
|
|
64
64
|
} catch (error) {
|
|
65
65
|
try {
|
|
66
|
-
await registry.installModule(packageName, package.version, package.url)
|
|
66
|
+
await registry.installModule(packageName, package.version, package.url, package.registry_url || '')
|
|
67
67
|
const packageInfo = await loadPackage(packageName);
|
|
68
68
|
appendToPackagesConfig(packageInfo.name, {version: packageInfo.version, description: packageInfo.description, local: false});
|
|
69
69
|
} catch (error) {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
var ncl = require('./npm_login.js');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
const _ = require('lodash');
|
|
5
|
+
const configPath = path.join(process.cwd(), '.steedos', '.npmrc');
|
|
6
|
+
const yarnrcConfigPath = path.join(process.cwd(), '.steedos', '.yarnrc');
|
|
7
|
+
const timeout = 10 * 1000;
|
|
8
|
+
const NPM_TOKENS = {};
|
|
9
|
+
const npmLogin = async function (user, pass, email, registry, scope, quotes, configPath) {
|
|
10
|
+
return await new Promise((resolve, reject) => {
|
|
11
|
+
var finalArgs = ncl.processArguments(user, pass, email, registry, scope, quotes, configPath);
|
|
12
|
+
var response;
|
|
13
|
+
var contents;
|
|
14
|
+
var newContents;
|
|
15
|
+
|
|
16
|
+
ncl.login(finalArgs, function (err, data) {
|
|
17
|
+
if (err) {
|
|
18
|
+
reject(err);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
response = data;
|
|
22
|
+
NPM_TOKENS[registry] = response.token;
|
|
23
|
+
ncl.readFile(finalArgs, function (err, data) {
|
|
24
|
+
if (err) {
|
|
25
|
+
reject(err);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
contents = data;
|
|
29
|
+
newContents = ncl.generateFileContents(finalArgs, contents, response);
|
|
30
|
+
ncl.writeFile(finalArgs, newContents, function (err) {
|
|
31
|
+
if (err) {
|
|
32
|
+
// let users know that it didn't work (could be prettier)
|
|
33
|
+
reject(err);
|
|
34
|
+
}
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
reject({ message: `connect ECONNREFUSED ${registry}` })
|
|
44
|
+
}, timeout)
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
async function login(username, password, email, registry, scope) {
|
|
49
|
+
return await npmLogin(username, password, email, registry, scope, true, configPath);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setYarnrcScopes(scopes, registry) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
_.each(scopes, (scope) => {
|
|
55
|
+
lines.push(`"@${scope}:registry" "${registry}"`);
|
|
56
|
+
})
|
|
57
|
+
fs.writeFileSync(yarnrcConfigPath, lines.join('\n') + '\n');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getYarnrcScopes() {
|
|
61
|
+
const data = fs.readFileSync(yarnrcConfigPath, 'utf-8');
|
|
62
|
+
const scopes = {};
|
|
63
|
+
if (data) {
|
|
64
|
+
// console.log(`data`, data);
|
|
65
|
+
try {
|
|
66
|
+
const lines = data.split('\n');
|
|
67
|
+
_.each(lines, (line) => {
|
|
68
|
+
try {
|
|
69
|
+
let s = line.split(' ');
|
|
70
|
+
if (s.length == 2) {
|
|
71
|
+
scopes[s[0].replace(/\"/g, "")] = s[1].replace(/\"/g, "");
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(error)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.log(error)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return scopes
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getNpmAuthInfo(registry) {
|
|
85
|
+
const token = NPM_TOKENS[registry];
|
|
86
|
+
if (token) {
|
|
87
|
+
return { token: token, type: 'Bearer' }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
loginToRegistry: login,
|
|
93
|
+
setYarnrcScopes,
|
|
94
|
+
getYarnrcScopes,
|
|
95
|
+
getNpmAuthInfo
|
|
96
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
var RegClient = require('npm-registry-client');
|
|
2
|
+
function noop() { }
|
|
3
|
+
var client = new RegClient({
|
|
4
|
+
log: {
|
|
5
|
+
error: noop,
|
|
6
|
+
warn: noop,
|
|
7
|
+
info: noop,
|
|
8
|
+
verbose: noop,
|
|
9
|
+
silly: noop,
|
|
10
|
+
http: noop,
|
|
11
|
+
pause: noop,
|
|
12
|
+
resume: noop
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
var fs = require('fs');
|
|
17
|
+
var path = require('path');
|
|
18
|
+
|
|
19
|
+
// jshint freeze:false
|
|
20
|
+
if (!Array.prototype.findIndex) {
|
|
21
|
+
Array.prototype.findIndex = function (predicate) {
|
|
22
|
+
if (this === null) {
|
|
23
|
+
throw new TypeError('Array.prototype.findIndex called on null or undefined');
|
|
24
|
+
}
|
|
25
|
+
if (typeof predicate !== 'function') {
|
|
26
|
+
throw new TypeError('predicate must be a function');
|
|
27
|
+
}
|
|
28
|
+
var list = Object(this);
|
|
29
|
+
var length = list.length >>> 0;
|
|
30
|
+
var thisArg = arguments[1];
|
|
31
|
+
var value;
|
|
32
|
+
|
|
33
|
+
for (var i = 0; i < length; i++) {
|
|
34
|
+
value = list[i];
|
|
35
|
+
if (predicate.call(thisArg, value, i, list)) {
|
|
36
|
+
return i;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return -1;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// jshint freeze:true
|
|
43
|
+
|
|
44
|
+
function removeSuffix(pattern, suffix) {
|
|
45
|
+
if (pattern.endsWith(suffix)) {
|
|
46
|
+
return pattern.slice(0, -suffix.length);
|
|
47
|
+
}
|
|
48
|
+
return pattern;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
processArguments: function (npmUser, npmPass, npmEmail, npmRegistry, npmScope, quotes, configPath) {
|
|
53
|
+
var registry = npmRegistry || 'https://registry.npmjs.org';
|
|
54
|
+
registry = removeSuffix(registry, '/')
|
|
55
|
+
var homePath = process.env.HOME ? process.env.HOME : process.env.USERPROFILE;
|
|
56
|
+
var finalPath = configPath ? configPath : path.join(homePath, '.npmrc');
|
|
57
|
+
var hasQuotes = quotes ? quotes : false;
|
|
58
|
+
var args = {
|
|
59
|
+
user: npmUser,
|
|
60
|
+
pass: npmPass,
|
|
61
|
+
email: npmEmail,
|
|
62
|
+
registry: registry,
|
|
63
|
+
scope: npmScope,
|
|
64
|
+
quotes: hasQuotes,
|
|
65
|
+
configPath: finalPath
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return args;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
login: function (args, callback) {
|
|
72
|
+
client.adduser(args.registry, {
|
|
73
|
+
auth: {
|
|
74
|
+
username: args.user,
|
|
75
|
+
password: args.pass,
|
|
76
|
+
email: args.email
|
|
77
|
+
}
|
|
78
|
+
}, function (err, data) {
|
|
79
|
+
if (err) {
|
|
80
|
+
return callback(err);
|
|
81
|
+
}
|
|
82
|
+
return callback(null, data);
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
readFile: function (args, callback) {
|
|
87
|
+
fs.readFile(args.configPath, 'utf-8', function (err, contents) {
|
|
88
|
+
if (err) {
|
|
89
|
+
contents = '';
|
|
90
|
+
}
|
|
91
|
+
return callback(null, contents);
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
generateFileContents: function (args, contents, response) {
|
|
96
|
+
// `contents` holds the initial content of the NPMRC file
|
|
97
|
+
// Convert the file contents into an array
|
|
98
|
+
var lines = contents ? contents.split('\n') : [];
|
|
99
|
+
// Regex pattern to detect end of registry
|
|
100
|
+
const registryEndRegexPattern = /\:\//;
|
|
101
|
+
if (args.scope !== undefined) {
|
|
102
|
+
var scopeWrite = lines.findIndex(function (element) {
|
|
103
|
+
if (element.indexOf(args.scope + ':registry=' + args.registry) !== -1) {
|
|
104
|
+
// If an entry for the scope is found, replace it
|
|
105
|
+
element = args.scope + ':registry=' + args.registry;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// If no entry for the scope is found, add one
|
|
111
|
+
if (scopeWrite === -1) {
|
|
112
|
+
lines.push(args.scope + ':registry=' + args.registry);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
var authWrite = lines.findIndex(function (element, index, array) {
|
|
117
|
+
if (element.indexOf(args.registry.slice(args.registry.search(registryEndRegexPattern, '') + 1) +
|
|
118
|
+
'/:_authToken=') !== -1) {
|
|
119
|
+
// If an entry for the auth token is found, replace it
|
|
120
|
+
array[index] = element.replace(/authToken\=.*/, 'authToken=' + (args.quotes ? '"' : '') +
|
|
121
|
+
response.token + (args.quotes ? '"' : ''));
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// If no entry for the auth token is found, add one
|
|
127
|
+
if (authWrite === -1) {
|
|
128
|
+
lines.push(args.registry.slice(args.registry.search(registryEndRegexPattern, '') +
|
|
129
|
+
1) + '/:_authToken=' + (args.quotes ? '"' : '') + response.token + (args.quotes ? '"' : ''));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
var toWrite = lines.filter(function (element) {
|
|
133
|
+
if (element === '') {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return toWrite;
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
writeFile: function (args, lines, callback) {
|
|
143
|
+
fs.writeFile(args.configPath, lines.join('\n') + '\n', callback);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { Agent: HttpAgent } = require('http');
|
|
3
|
+
const { Agent: HttpsAgent } = require('https');
|
|
4
|
+
const got = require('got');
|
|
5
|
+
const registryUrl = require('registry-url');
|
|
6
|
+
const registryAuthToken = require('registry-auth-token');
|
|
7
|
+
const semver = require('semver');
|
|
8
|
+
|
|
9
|
+
// These agent options are chosen to match the npm client defaults and help with performance
|
|
10
|
+
// See: `npm config get maxsockets` and #50
|
|
11
|
+
const agentOptions = {
|
|
12
|
+
keepAlive: true,
|
|
13
|
+
maxSockets: 50
|
|
14
|
+
};
|
|
15
|
+
const httpAgent = new HttpAgent(agentOptions);
|
|
16
|
+
const httpsAgent = new HttpsAgent(agentOptions);
|
|
17
|
+
|
|
18
|
+
class PackageNotFoundError extends Error {
|
|
19
|
+
constructor(packageName) {
|
|
20
|
+
super(`Package \`${packageName}\` could not be found`);
|
|
21
|
+
this.name = 'PackageNotFoundError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class VersionNotFoundError extends Error {
|
|
26
|
+
constructor(packageName, version) {
|
|
27
|
+
super(`Version \`${version}\` for package \`${packageName}\` could not be found`);
|
|
28
|
+
this.name = 'VersionNotFoundError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const packageJson = async (packageName, options) => {
|
|
33
|
+
options = {
|
|
34
|
+
version: 'latest',
|
|
35
|
+
...options
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const scope = packageName.split('/')[0];
|
|
39
|
+
const registryUrl_ = options.registryUrl || registryUrl(scope);
|
|
40
|
+
const packageUrl = new URL(encodeURIComponent(packageName).replace(/^%40/, '@'), registryUrl_);
|
|
41
|
+
const authInfo = options.authInfo || registryAuthToken(registryUrl_.toString(), { recursive: true });
|
|
42
|
+
|
|
43
|
+
const headers = {
|
|
44
|
+
accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (options.fullMetadata) {
|
|
48
|
+
delete headers.accept;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (authInfo) {
|
|
52
|
+
headers.authorization = `${authInfo.type} ${authInfo.token}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const gotOptions = {
|
|
56
|
+
headers,
|
|
57
|
+
agent: {
|
|
58
|
+
http: httpAgent,
|
|
59
|
+
https: httpsAgent
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
if (options.agent) {
|
|
64
|
+
gotOptions.agent = options.agent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let data;
|
|
68
|
+
try {
|
|
69
|
+
data = await got(packageUrl, gotOptions).json();
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error.response.statusCode === 404) {
|
|
72
|
+
throw new PackageNotFoundError(packageName);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (options.allVersions) {
|
|
79
|
+
return data;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let { version } = options;
|
|
83
|
+
const versionError = new VersionNotFoundError(packageName, version);
|
|
84
|
+
|
|
85
|
+
if (data['dist-tags'][version]) {
|
|
86
|
+
data = data.versions[data['dist-tags'][version]];
|
|
87
|
+
} else if (version) {
|
|
88
|
+
if (!data.versions[version]) {
|
|
89
|
+
const versions = Object.keys(data.versions);
|
|
90
|
+
version = semver.maxSatisfying(versions, version);
|
|
91
|
+
|
|
92
|
+
if (!version) {
|
|
93
|
+
throw versionError;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
data = data.versions[version];
|
|
98
|
+
|
|
99
|
+
if (!data) {
|
|
100
|
+
throw versionError;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return data;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
module.exports = packageJson;
|
|
108
|
+
// TODO: remove this in the next major version
|
|
109
|
+
module.exports.default = packageJson;
|
|
110
|
+
module.exports.PackageNotFoundError = PackageNotFoundError;
|
|
111
|
+
module.exports.VersionNotFoundError = VersionNotFoundError;
|
|
@@ -3,8 +3,21 @@ const loader = require('./loader');
|
|
|
3
3
|
const registry = require('./registry');
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const objectql = require('@steedos/objectql');
|
|
6
|
-
const packageJson = require('package-json');
|
|
6
|
+
const packageJson = require('./package-json');
|
|
7
7
|
const _ = require('lodash');
|
|
8
|
+
const login = require('./login');
|
|
9
|
+
|
|
10
|
+
function registryUrl(scope) {
|
|
11
|
+
try {
|
|
12
|
+
const result = login.getYarnrcScopes();
|
|
13
|
+
const url = result[`${scope}:registry`];
|
|
14
|
+
if (url) {
|
|
15
|
+
return url.slice(-1) === '/' ? url : `${url}/`;
|
|
16
|
+
}
|
|
17
|
+
} catch (Exception) {
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
}
|
|
8
21
|
|
|
9
22
|
const getAllPackages = async ()=>{
|
|
10
23
|
// const installPackages = loader.loadPackagesConfig();
|
|
@@ -106,8 +119,14 @@ const maintainSystemFiles = ()=>{
|
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
const getPackageVersions = async (packageName, options)=>{
|
|
122
|
+
//TODO 处理 registry_url
|
|
123
|
+
|
|
124
|
+
let registry_url = registryUrl(packageName.toLowerCase().split('/')[0]);
|
|
125
|
+
|
|
109
126
|
const result = await packageJson(packageName.toLowerCase(), {
|
|
110
|
-
allVersions: true
|
|
127
|
+
allVersions: true,
|
|
128
|
+
registryUrl: registry_url,
|
|
129
|
+
authInfo: login.getNpmAuthInfo(registry_url)
|
|
111
130
|
});
|
|
112
131
|
|
|
113
132
|
const versions = [];
|
|
@@ -112,7 +112,7 @@ function checkModuleIsInstall(module){
|
|
|
112
112
|
return false
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
async function installModule(module,version,url) {
|
|
115
|
+
async function installModule(module, version, url, registry_url) {
|
|
116
116
|
if (Buffer.isBuffer(module)) {
|
|
117
117
|
// return installTarball(module)
|
|
118
118
|
return
|
|
@@ -193,7 +193,11 @@ async function installModule(module,version,url) {
|
|
|
193
193
|
|
|
194
194
|
var installDir = settings.userDir || ".";
|
|
195
195
|
var args = ['install','--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production',installName];
|
|
196
|
-
var yarnArgs = ['add', '-E', installName]; //yarnCommand , '--json' --registry
|
|
196
|
+
var yarnArgs = ['add', '-E', installName, '--json']; //yarnCommand , '--json' --registry
|
|
197
|
+
if (false && registry_url) {
|
|
198
|
+
yarnArgs.push('--registry')
|
|
199
|
+
yarnArgs.push(registry_url)
|
|
200
|
+
}
|
|
197
201
|
return exec.run(yarnCommand,yarnArgs,{
|
|
198
202
|
cwd: installDir
|
|
199
203
|
}, true).then(result => {
|
|
@@ -233,8 +237,6 @@ async function installModule(module,version,url) {
|
|
|
233
237
|
// return require("./registry").setModulePendingUpdated(module,version);
|
|
234
238
|
}
|
|
235
239
|
}).catch(result => {
|
|
236
|
-
console.log(`result error`, result)
|
|
237
|
-
log.error(`result`, result);
|
|
238
240
|
activePromise = Promise.resolve();
|
|
239
241
|
throw result;
|
|
240
242
|
// var output = result.stderr;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const core = require("@steedos/core");
|
|
4
|
+
|
|
5
|
+
let STEEDOS_REGISTRY_URL = process.env.STEEDOS_REGISTRY_URL ? process.env.STEEDOS_REGISTRY_URL : 'https://registry.steedos.cn/';
|
|
6
|
+
|
|
7
|
+
router.get("/api/nodes/registry", core.requireAuthentication, async function (req, res) {
|
|
8
|
+
res.status(200).send([
|
|
9
|
+
{ label: "https://registry.npmjs.org/", value: "https://registry.npmjs.org/" },
|
|
10
|
+
{ label: "https://registry.npm.taobao.org/", value: "https://registry.npm.taobao.org/" },
|
|
11
|
+
{ label: STEEDOS_REGISTRY_URL, value: STEEDOS_REGISTRY_URL },
|
|
12
|
+
]);
|
|
13
|
+
});
|
|
14
|
+
exports.default = router;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/service-package-registry",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.54",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "package.service.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"author": "",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@steedos/service-package-loader": "2.1.
|
|
12
|
+
"@steedos/service-package-loader": "2.1.54",
|
|
13
13
|
"fs-extra": "8.1.0",
|
|
14
14
|
"i18next": "20.3.2",
|
|
15
15
|
"json-stringify-safe": "5.0.1",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"lodash.clonedeep": "^4.5.0",
|
|
19
19
|
"moment-timezone": "0.5.33",
|
|
20
20
|
"npm-package-arg": "~8.1.5",
|
|
21
|
+
"npm-registry-client": "8.6.0",
|
|
21
22
|
"package-json": "^7.0.0",
|
|
22
23
|
"radwag-mass": "~1.0.5"
|
|
23
24
|
},
|
|
@@ -25,5 +26,5 @@
|
|
|
25
26
|
"publishConfig": {
|
|
26
27
|
"access": "public"
|
|
27
28
|
},
|
|
28
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "6b261ebf1924b3ec2dc9d1951ad3e0449de9fdef"
|
|
29
30
|
}
|
package/package.service.js
CHANGED
|
@@ -6,6 +6,7 @@ const loader = require('./main/default/manager/loader');
|
|
|
6
6
|
const packages = require('./main/default/manager/packages');
|
|
7
7
|
const registry = require('./main/default/manager/registry');
|
|
8
8
|
const metadata = require('@steedos/metadata-core')
|
|
9
|
+
const axios = require('axios');
|
|
9
10
|
const _ = require(`lodash`);
|
|
10
11
|
const path = require(`path`);
|
|
11
12
|
const objectql = require('@steedos/objectql');
|
|
@@ -14,6 +15,8 @@ const util = require('./main/default/manager/util');
|
|
|
14
15
|
const fetch = require('node-fetch');
|
|
15
16
|
const { MoleculerError } = require("moleculer").Errors;
|
|
16
17
|
|
|
18
|
+
const login = require('./main/default/manager/login');
|
|
19
|
+
|
|
17
20
|
const HEADER_AUTH = 'Authorization';
|
|
18
21
|
const AUTH_TYPE = 'Bearer';
|
|
19
22
|
|
|
@@ -68,7 +71,8 @@ module.exports = {
|
|
|
68
71
|
},
|
|
69
72
|
STEEDOS_CLOUD_URL: process.env.STEEDOS_CLOUD_URL ? process.env.STEEDOS_CLOUD_URL : 'https://console.steedos.cn',
|
|
70
73
|
STEEDOS_CLOUD_SPACE_ID: process.env.STEEDOS_CLOUD_SPACE_ID,
|
|
71
|
-
STEEDOS_CLOUD_API_KEY: process.env.STEEDOS_CLOUD_API_KEY
|
|
74
|
+
STEEDOS_CLOUD_API_KEY: process.env.STEEDOS_CLOUD_API_KEY,
|
|
75
|
+
STEEDOS_REGISTRY_URL: process.env.STEEDOS_REGISTRY_URL ? process.env.STEEDOS_REGISTRY_URL : 'https://registry.steedos.cn/',
|
|
72
76
|
},
|
|
73
77
|
|
|
74
78
|
/**
|
|
@@ -221,6 +225,7 @@ module.exports = {
|
|
|
221
225
|
try {
|
|
222
226
|
const { name, version, label, description } = _package
|
|
223
227
|
let enable = true; //安装已购买的软件包时先默认启用
|
|
228
|
+
//TODO 处理 registry_url
|
|
224
229
|
const packageInfo = await this.installPackage(name, version, label, description, enable, ctx.broker);
|
|
225
230
|
installPackages.push(packageInfo)
|
|
226
231
|
} catch (error) {
|
|
@@ -263,11 +268,26 @@ module.exports = {
|
|
|
263
268
|
if(!user.is_space_admin){
|
|
264
269
|
throw new Error('not permission!');
|
|
265
270
|
}
|
|
266
|
-
let { module, version, url, auth } = ctx.params
|
|
271
|
+
let { module, version, url, auth, registry_url } = ctx.params
|
|
267
272
|
const enable = true;
|
|
268
|
-
return await this.installPackageFromUrl(module, version, url, auth, enable, ctx.broker)
|
|
273
|
+
return await this.installPackageFromUrl(module, version, url, auth, enable, registry_url, ctx.broker)
|
|
269
274
|
} catch (error) {
|
|
270
|
-
|
|
275
|
+
let errorInfo = error.message || '';
|
|
276
|
+
if (error.stderr) {
|
|
277
|
+
const errors = error.stderr.split('\n');
|
|
278
|
+
errors.forEach(element => {
|
|
279
|
+
if (element) {
|
|
280
|
+
try {
|
|
281
|
+
const item = JSON.parse(element);
|
|
282
|
+
if (item.type === 'error') {
|
|
283
|
+
errorInfo = errorInfo + item.data + '\n'
|
|
284
|
+
}
|
|
285
|
+
} catch (error) {
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
throw new MoleculerError(errorInfo, 500, "ERR_SOMETHING");
|
|
271
291
|
}
|
|
272
292
|
}
|
|
273
293
|
}
|
|
@@ -362,6 +382,7 @@ module.exports = {
|
|
|
362
382
|
},
|
|
363
383
|
upgradePackage: {
|
|
364
384
|
async handler(module, version) {
|
|
385
|
+
//TODO 处理 registry_url
|
|
365
386
|
const packagePath = await registry.installModule(module, version);
|
|
366
387
|
const enable = true;
|
|
367
388
|
if(enable){
|
|
@@ -389,7 +410,7 @@ module.exports = {
|
|
|
389
410
|
}
|
|
390
411
|
},
|
|
391
412
|
installPackageFromUrl: {
|
|
392
|
-
async handler(module, version, url, auth, enable, broker) {
|
|
413
|
+
async handler(module, version, url, auth, enable, registry_url, broker) {
|
|
393
414
|
if(!module || !_.isString(module) || !module.trim()){
|
|
394
415
|
throw new Error(`无效的软件包名称`);
|
|
395
416
|
} else {
|
|
@@ -432,8 +453,7 @@ module.exports = {
|
|
|
432
453
|
url = `${url}/${result.token}`
|
|
433
454
|
console.log(`url`, url);
|
|
434
455
|
}
|
|
435
|
-
|
|
436
|
-
const packagePath = await registry.installModule(module, version, url);
|
|
456
|
+
const packagePath = await registry.installModule(module, version, url, registry_url);
|
|
437
457
|
const packageInfo = loader.getPackageInfo(null, packagePath);
|
|
438
458
|
const packageName = packageInfo.name;
|
|
439
459
|
if(enable){
|
|
@@ -448,6 +468,7 @@ module.exports = {
|
|
|
448
468
|
local: false,
|
|
449
469
|
enable: enable,
|
|
450
470
|
url: url,
|
|
471
|
+
// registry_url: registry_url,
|
|
451
472
|
path: util.getPackageRelativePath(process.cwd(), packagePath)
|
|
452
473
|
}
|
|
453
474
|
loader.appendToPackagesConfig(packageName, packageConfig);
|
|
@@ -462,7 +483,61 @@ module.exports = {
|
|
|
462
483
|
})
|
|
463
484
|
})
|
|
464
485
|
return packageConfig;
|
|
465
|
-
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
getSafeScopes: {
|
|
489
|
+
async handler(spaceId, apiKey, consoleUrl) {
|
|
490
|
+
let result = await axios({
|
|
491
|
+
url: `${consoleUrl}/api/npm-scopes/safe`,
|
|
492
|
+
method: 'post',
|
|
493
|
+
data: {
|
|
494
|
+
cloudSpaceId: spaceId
|
|
495
|
+
},
|
|
496
|
+
timeout: 5 * 1000,
|
|
497
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer apikey,${apiKey}` }
|
|
498
|
+
})
|
|
499
|
+
if (!result.data.success) {
|
|
500
|
+
throw new Error(result.data.error);
|
|
501
|
+
}
|
|
502
|
+
return result.data;
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
loginSteedosRegistry: {
|
|
506
|
+
async handler() {
|
|
507
|
+
const settings = this.settings;
|
|
508
|
+
// 配置主控地址
|
|
509
|
+
const consoleUrl = settings.STEEDOS_CLOUD_URL;
|
|
510
|
+
if (!consoleUrl) {
|
|
511
|
+
console.log(chalk.red('请配置主控地址'));
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// 初始化工作区数据
|
|
516
|
+
// 获取环境变量中工作区信息
|
|
517
|
+
const spaceId = settings.STEEDOS_CLOUD_SPACE_ID;
|
|
518
|
+
const apiKey = settings.STEEDOS_CLOUD_API_KEY;
|
|
519
|
+
|
|
520
|
+
if (!spaceId || !apiKey) {
|
|
521
|
+
console.log(chalk.red('请配置环境变量STEEDOS_CLOUD_SPACE_ID和STEEDOS_CLOUD_API_KEY。'));
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const registryUrl = settings.STEEDOS_REGISTRY_URL
|
|
526
|
+
|
|
527
|
+
// 调用接口获取初始化信息
|
|
528
|
+
const { info, scopes } = await this.getSafeScopes(spaceId, apiKey, consoleUrl);
|
|
529
|
+
const { adminPhone } = info;
|
|
530
|
+
if (!adminPhone) {
|
|
531
|
+
console.log(chalk.red('缺少工作区信息 工作区名称、管理员姓名、管理员手机号,请检查'));
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
// let scope = '';
|
|
535
|
+
// if (scopes && scopes.length > 0) {
|
|
536
|
+
// scope = scopes[0];
|
|
537
|
+
// }
|
|
538
|
+
await login.loginToRegistry(adminPhone, apiKey, `${adminPhone}@steedos.com`, registryUrl, undefined);
|
|
539
|
+
login.setYarnrcScopes(scopes, registryUrl);
|
|
540
|
+
}
|
|
466
541
|
}
|
|
467
542
|
},
|
|
468
543
|
|
|
@@ -477,6 +552,12 @@ module.exports = {
|
|
|
477
552
|
* Service started lifecycle event handler
|
|
478
553
|
*/
|
|
479
554
|
async started() {
|
|
555
|
+
try {
|
|
556
|
+
await this.loginSteedosRegistry();
|
|
557
|
+
console.info(`login steedos registry success`);
|
|
558
|
+
} catch (error) {
|
|
559
|
+
console.error(`login steedos registry fail: `, error.message);
|
|
560
|
+
}
|
|
480
561
|
const PACKAGE_INSTALL_NODE = process.env.PACKAGE_INSTALL_NODE
|
|
481
562
|
if(PACKAGE_INSTALL_NODE){
|
|
482
563
|
await this.broker.call('metadata.add', {key: `#package_install_node.${this.broker.nodeID}`, data: {nodeID: PACKAGE_INSTALL_NODE}}, {meta: {}})
|