@xcanwin/manyoyo 5.8.6 → 5.8.10

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.
@@ -0,0 +1,238 @@
1
+ 'use strict';
2
+
3
+ function readQuotedString(text, startIndex) {
4
+ const quote = text[startIndex];
5
+ let value = '';
6
+
7
+ for (let i = startIndex + 1; i < text.length; i += 1) {
8
+ const ch = text[i];
9
+ if (ch === '\\') {
10
+ value += ch;
11
+ if (i + 1 < text.length) {
12
+ value += text[i + 1];
13
+ i += 1;
14
+ }
15
+ continue;
16
+ }
17
+ if (ch === quote) {
18
+ return {
19
+ value,
20
+ end: i + 1
21
+ };
22
+ }
23
+ value += ch;
24
+ }
25
+
26
+ return null;
27
+ }
28
+
29
+ function isIdentifierStart(ch) {
30
+ return /[A-Za-z_$]/.test(ch);
31
+ }
32
+
33
+ function isIdentifierPart(ch) {
34
+ return /[A-Za-z0-9_$]/.test(ch);
35
+ }
36
+
37
+ function skipTrivia(text, index) {
38
+ let cursor = index;
39
+ while (cursor < text.length) {
40
+ const ch = text[cursor];
41
+ const next = text[cursor + 1];
42
+ if (/\s/.test(ch)) {
43
+ cursor += 1;
44
+ continue;
45
+ }
46
+ if (ch === '/' && next === '/') {
47
+ cursor += 2;
48
+ while (cursor < text.length && text[cursor] !== '\n') {
49
+ cursor += 1;
50
+ }
51
+ continue;
52
+ }
53
+ if (ch === '/' && next === '*') {
54
+ cursor += 2;
55
+ while (cursor + 1 < text.length && !(text[cursor] === '*' && text[cursor + 1] === '/')) {
56
+ cursor += 1;
57
+ }
58
+ cursor = cursor + 1 < text.length ? cursor + 2 : text.length;
59
+ continue;
60
+ }
61
+ break;
62
+ }
63
+ return cursor;
64
+ }
65
+
66
+ function scanValueEnd(text, startIndex) {
67
+ let cursor = startIndex;
68
+ let stringQuote = '';
69
+ let lineComment = false;
70
+ let blockComment = false;
71
+ let depth = 0;
72
+
73
+ for (; cursor < text.length; cursor += 1) {
74
+ const ch = text[cursor];
75
+ const next = text[cursor + 1];
76
+
77
+ if (lineComment) {
78
+ if (ch === '\n') {
79
+ lineComment = false;
80
+ }
81
+ continue;
82
+ }
83
+ if (blockComment) {
84
+ if (ch === '*' && next === '/') {
85
+ blockComment = false;
86
+ cursor += 1;
87
+ }
88
+ continue;
89
+ }
90
+ if (stringQuote) {
91
+ if (ch === '\\') {
92
+ cursor += 1;
93
+ continue;
94
+ }
95
+ if (ch === stringQuote) {
96
+ stringQuote = '';
97
+ }
98
+ continue;
99
+ }
100
+
101
+ if (ch === '/' && next === '/') {
102
+ lineComment = true;
103
+ cursor += 1;
104
+ continue;
105
+ }
106
+ if (ch === '/' && next === '*') {
107
+ blockComment = true;
108
+ cursor += 1;
109
+ continue;
110
+ }
111
+ if (ch === '"' || ch === '\'') {
112
+ stringQuote = ch;
113
+ continue;
114
+ }
115
+ if (ch === '{' || ch === '[' || ch === '(') {
116
+ depth += 1;
117
+ continue;
118
+ }
119
+ if (ch === '}' || ch === ']' || ch === ')') {
120
+ if (depth === 0) {
121
+ break;
122
+ }
123
+ depth -= 1;
124
+ continue;
125
+ }
126
+ if (depth === 0 && ch === ',') {
127
+ break;
128
+ }
129
+ }
130
+
131
+ let end = cursor;
132
+ while (end > startIndex && /\s/.test(text[end - 1])) {
133
+ end -= 1;
134
+ }
135
+ return end;
136
+ }
137
+
138
+ function findRootObjectStart(text) {
139
+ const source = String(text || '');
140
+ const start = skipTrivia(source, 0);
141
+ return source[start] === '{' ? start : -1;
142
+ }
143
+
144
+ function readPropertyToken(text, startIndex) {
145
+ const ch = text[startIndex];
146
+ if (ch === '"' || ch === '\'') {
147
+ return readQuotedString(text, startIndex);
148
+ }
149
+ if (!isIdentifierStart(ch)) {
150
+ return null;
151
+ }
152
+
153
+ let end = startIndex + 1;
154
+ while (end < text.length && isIdentifierPart(text[end])) {
155
+ end += 1;
156
+ }
157
+ return {
158
+ value: text.slice(startIndex, end),
159
+ end
160
+ };
161
+ }
162
+
163
+ function findObjectPropertyValueRange(text, objectStartIndex, propertyName) {
164
+ let cursor = skipTrivia(text, objectStartIndex + 1);
165
+ while (cursor < text.length) {
166
+ cursor = skipTrivia(text, cursor);
167
+ if (text[cursor] === '}') {
168
+ return null;
169
+ }
170
+ const token = readPropertyToken(text, cursor);
171
+ if (!token) {
172
+ return null;
173
+ }
174
+ cursor = skipTrivia(text, token.end);
175
+ if (text[cursor] !== ':') {
176
+ return null;
177
+ }
178
+ const valueStart = skipTrivia(text, cursor + 1);
179
+ const valueEnd = scanValueEnd(text, valueStart);
180
+ if (token.value === propertyName) {
181
+ return { start: valueStart, end: valueEnd };
182
+ }
183
+ cursor = skipTrivia(text, valueEnd);
184
+ if (text[cursor] === ',') {
185
+ cursor += 1;
186
+ continue;
187
+ }
188
+ if (text[cursor] === '}') {
189
+ return null;
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+
195
+ function findValueRangeByPath(text, pathParts) {
196
+ if (!Array.isArray(pathParts) || pathParts.length === 0) {
197
+ return null;
198
+ }
199
+
200
+ let objectStart = findRootObjectStart(text);
201
+ if (objectStart === -1) {
202
+ return null;
203
+ }
204
+
205
+ let range = null;
206
+ for (let i = 0; i < pathParts.length; i += 1) {
207
+ range = findObjectPropertyValueRange(text, objectStart, pathParts[i]);
208
+ if (!range) {
209
+ return null;
210
+ }
211
+ if (i === pathParts.length - 1) {
212
+ return range;
213
+ }
214
+ const nextObjectStart = skipTrivia(text, range.start);
215
+ if (text[nextObjectStart] !== '{') {
216
+ return null;
217
+ }
218
+ objectStart = nextObjectStart;
219
+ }
220
+ return range;
221
+ }
222
+
223
+ function findTopLevelPropertyValueRange(text, propertyName) {
224
+ return findValueRangeByPath(text, [propertyName]);
225
+ }
226
+
227
+ function applyTextReplacements(text, replacements) {
228
+ return replacements
229
+ .slice()
230
+ .sort((a, b) => b.start - a.start)
231
+ .reduce((result, item) => `${result.slice(0, item.start)}${item.text}${result.slice(item.end)}`, text);
232
+ }
233
+
234
+ module.exports = {
235
+ findTopLevelPropertyValueRange,
236
+ findValueRangeByPath,
237
+ applyTextReplacements
238
+ };
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ const os = require('os');
4
+ const path = require('path');
5
+
6
+ function parseEnvEntry(entryText) {
7
+ const text = String(entryText || '');
8
+ const idx = text.indexOf('=');
9
+ if (idx <= 0) {
10
+ throw new Error(`env 格式应为 KEY=VALUE: ${text}`);
11
+ }
12
+
13
+ const key = text.slice(0, idx);
14
+ const value = text.slice(idx + 1);
15
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
16
+ throw new Error(`env key 非法: ${key}`);
17
+ }
18
+ if (/[\r\n\0]/.test(value) || /[;&|`$<>]/.test(value)) {
19
+ throw new Error(`env value 含非法字符: ${key}`);
20
+ }
21
+
22
+ return { key, value };
23
+ }
24
+
25
+ function expandHomeAliasPath(filePath, homeDir = os.homedir()) {
26
+ const text = String(filePath || '').trim();
27
+ if (!text) {
28
+ return text;
29
+ }
30
+ if (text === '~') {
31
+ return homeDir;
32
+ }
33
+ if (text.startsWith('~/')) {
34
+ return path.join(homeDir, text.slice(2));
35
+ }
36
+ if (text === '$HOME') {
37
+ return homeDir;
38
+ }
39
+ if (text.startsWith('$HOME/')) {
40
+ return path.join(homeDir, text.slice('$HOME/'.length));
41
+ }
42
+ return text;
43
+ }
44
+
45
+ function normalizeVolume(volume, homeDir = os.homedir()) {
46
+ const text = String(volume || '').trim();
47
+ if (!text.startsWith('~') && !text.startsWith('$HOME')) {
48
+ return text;
49
+ }
50
+
51
+ const separatorIndex = text.indexOf(':');
52
+ if (separatorIndex === -1) {
53
+ return expandHomeAliasPath(text, homeDir);
54
+ }
55
+
56
+ const hostPath = text.slice(0, separatorIndex);
57
+ const rest = text.slice(separatorIndex);
58
+ return `${expandHomeAliasPath(hostPath, homeDir)}${rest}`;
59
+ }
60
+
61
+ module.exports = {
62
+ parseEnvEntry,
63
+ expandHomeAliasPath,
64
+ normalizeVolume
65
+ };
@@ -0,0 +1,195 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+
5
+ function toArray(value) {
6
+ return Array.isArray(value) ? value : (value ? [value] : []);
7
+ }
8
+
9
+ function resolveRuntimeConfig(options = {}) {
10
+ const params = options;
11
+ const cliOptions = params.cliOptions || {};
12
+ const globalConfig = params.globalConfig || {};
13
+ const runConfig = params.runConfig || {};
14
+ const globalFirstConfig = params.globalFirstConfig || {};
15
+ const runFirstConfig = params.runFirstConfig || {};
16
+ const defaults = params.defaults || {};
17
+ const envVars = params.envVars || process.env;
18
+ const pickConfigValue = params.pickConfigValue;
19
+ const resolveContainerNameTemplate = params.resolveContainerNameTemplate;
20
+ const normalizeCommandSuffix = params.normalizeCommandSuffix;
21
+ const normalizeJsonEnvMap = params.normalizeJsonEnvMap;
22
+ const normalizeCliEnvMap = params.normalizeCliEnvMap;
23
+ const mergeArrayConfig = params.mergeArrayConfig;
24
+ const normalizeVolume = params.normalizeVolume;
25
+ const parseServerListen = params.parseServerListen;
26
+ const argv = Array.isArray(params.argv) ? params.argv : [];
27
+ const isServerMode = params.isServerMode === true;
28
+ const isServerStopMode = params.isServerStopMode === true;
29
+
30
+ let hostPath = pickConfigValue(cliOptions.hostPath, runConfig.hostPath, globalConfig.hostPath, defaults.hostPath) || defaults.hostPath;
31
+ let containerName = defaults.containerName;
32
+ const mergedContainerName = pickConfigValue(cliOptions.contName, runConfig.containerName, globalConfig.containerName);
33
+ if (mergedContainerName) {
34
+ containerName = mergedContainerName;
35
+ }
36
+ containerName = resolveContainerNameTemplate(containerName);
37
+
38
+ let containerPath = defaults.containerPath;
39
+ const mergedContainerPath = pickConfigValue(cliOptions.contPath, runConfig.containerPath, globalConfig.containerPath);
40
+ if (mergedContainerPath) {
41
+ containerPath = mergedContainerPath;
42
+ }
43
+
44
+ const imageName = pickConfigValue(cliOptions.imageName, runConfig.imageName, globalConfig.imageName, defaults.imageName) || defaults.imageName;
45
+ const imageVersion = pickConfigValue(cliOptions.imageVer, runConfig.imageVersion, globalConfig.imageVersion, defaults.imageVersion) || defaults.imageVersion;
46
+
47
+ let execPrefix = '';
48
+ const mergedShellPrefix = pickConfigValue(cliOptions.shellPrefix, runConfig.shellPrefix, globalConfig.shellPrefix);
49
+ if (mergedShellPrefix) {
50
+ execPrefix = `${mergedShellPrefix} `;
51
+ }
52
+
53
+ let execShell = '';
54
+ const mergedShell = pickConfigValue(cliOptions.shell, runConfig.shell, globalConfig.shell);
55
+ if (mergedShell) {
56
+ execShell = mergedShell;
57
+ }
58
+
59
+ let execSuffix = '';
60
+ const mergedShellSuffix = pickConfigValue(cliOptions.shellSuffix, runConfig.shellSuffix, globalConfig.shellSuffix);
61
+ if (mergedShellSuffix) {
62
+ execSuffix = normalizeCommandSuffix(mergedShellSuffix);
63
+ }
64
+
65
+ let firstExecPrefix = '';
66
+ const mergedFirstShellPrefix = pickConfigValue(cliOptions.firstShellPrefix, runFirstConfig.shellPrefix, globalFirstConfig.shellPrefix);
67
+ if (mergedFirstShellPrefix) {
68
+ firstExecPrefix = `${mergedFirstShellPrefix} `;
69
+ }
70
+
71
+ let firstExecShell = '';
72
+ const mergedFirstShell = pickConfigValue(cliOptions.firstShell, runFirstConfig.shell, globalFirstConfig.shell);
73
+ if (mergedFirstShell) {
74
+ firstExecShell = mergedFirstShell;
75
+ }
76
+
77
+ let firstExecSuffix = '';
78
+ const mergedFirstShellSuffix = pickConfigValue(cliOptions.firstShellSuffix, runFirstConfig.shellSuffix, globalFirstConfig.shellSuffix);
79
+ if (mergedFirstShellSuffix) {
80
+ firstExecSuffix = normalizeCommandSuffix(mergedFirstShellSuffix);
81
+ }
82
+
83
+ const envFile = [
84
+ ...toArray(globalConfig.envFile),
85
+ ...toArray(runConfig.envFile),
86
+ ...(cliOptions.envFile || [])
87
+ ].filter(Boolean);
88
+
89
+ const env = {
90
+ ...normalizeJsonEnvMap(globalConfig.env, '全局配置'),
91
+ ...normalizeJsonEnvMap(runConfig.env, '运行配置'),
92
+ ...normalizeCliEnvMap(cliOptions.env)
93
+ };
94
+
95
+ const firstEnvFile = [
96
+ ...toArray(globalFirstConfig.envFile),
97
+ ...toArray(runFirstConfig.envFile),
98
+ ...(cliOptions.firstEnvFile || [])
99
+ ].filter(Boolean);
100
+
101
+ const firstEnv = {
102
+ ...normalizeJsonEnvMap(globalFirstConfig.env, '全局配置 first'),
103
+ ...normalizeJsonEnvMap(runFirstConfig.env, '运行配置 first'),
104
+ ...normalizeCliEnvMap(cliOptions.firstEnv)
105
+ };
106
+
107
+ const volumes = mergeArrayConfig(globalConfig.volumes, runConfig.volumes, cliOptions.volume)
108
+ .map(volume => normalizeVolume(volume));
109
+ const ports = mergeArrayConfig(globalConfig.ports, runConfig.ports, cliOptions.port);
110
+ const imageBuildArgs = mergeArrayConfig(globalConfig.imageBuildArgs, runConfig.imageBuildArgs, cliOptions.imageBuildArg);
111
+
112
+ const yolo = pickConfigValue(cliOptions.yolo, runConfig.yolo, globalConfig.yolo) || '';
113
+ const containerMode = pickConfigValue(cliOptions.contMode, runConfig.containerMode, globalConfig.containerMode) || '';
114
+ const quiet = pickConfigValue(cliOptions.quiet, runConfig.quiet, globalConfig.quiet) || [];
115
+
116
+ if (cliOptions.shellFull) {
117
+ execShell = cliOptions.shellFull.join(' ');
118
+ execPrefix = '';
119
+ execSuffix = '';
120
+ }
121
+
122
+ if (!cliOptions.shellFull) {
123
+ const doubleDashIndex = argv.indexOf('--');
124
+ if (doubleDashIndex !== -1 && doubleDashIndex < argv.length - 1) {
125
+ execSuffix = normalizeCommandSuffix(argv.slice(doubleDashIndex + 1).join(' '));
126
+ }
127
+ }
128
+
129
+ let serverHost = null;
130
+ let serverPort = null;
131
+ if (isServerMode) {
132
+ const listen = parseServerListen(cliOptions.server);
133
+ serverHost = listen.host;
134
+ serverPort = listen.port;
135
+ }
136
+
137
+ let serverUser = pickConfigValue(cliOptions.serverUser, runConfig.serverUser, globalConfig.serverUser, envVars.MANYOYO_SERVER_USER) || '';
138
+ let serverPass = pickConfigValue(cliOptions.serverPass, runConfig.serverPass, globalConfig.serverPass, envVars.MANYOYO_SERVER_PASS) || '';
139
+ let serverPassAuto = false;
140
+ if (isServerMode && !isServerStopMode) {
141
+ if (!serverUser) {
142
+ serverUser = 'admin';
143
+ }
144
+ if (!serverPass) {
145
+ serverPass = crypto.randomBytes(12).toString('hex');
146
+ serverPassAuto = true;
147
+ }
148
+ }
149
+
150
+ if (!hostPath) {
151
+ hostPath = defaults.hostPath;
152
+ }
153
+
154
+ return {
155
+ hostPath,
156
+ containerName,
157
+ containerPath,
158
+ imageName,
159
+ imageVersion,
160
+ envFile,
161
+ env,
162
+ firstEnvFile,
163
+ firstEnv,
164
+ volumes,
165
+ ports,
166
+ imageBuildArgs,
167
+ containerMode,
168
+ yolo,
169
+ quiet,
170
+ server: isServerMode,
171
+ serverHost,
172
+ serverPort,
173
+ serverUser,
174
+ serverPass,
175
+ serverPassAuto,
176
+ exec: {
177
+ prefix: execPrefix,
178
+ shell: execShell,
179
+ suffix: execSuffix
180
+ },
181
+ first: {
182
+ envFile: firstEnvFile,
183
+ env: firstEnv,
184
+ exec: {
185
+ prefix: firstExecPrefix,
186
+ shell: firstExecShell,
187
+ suffix: firstExecSuffix
188
+ }
189
+ }
190
+ };
191
+ }
192
+
193
+ module.exports = {
194
+ resolveRuntimeConfig
195
+ };