@yumerijs/core 3.0.0-alpha.1 → 3.0.0-alpha.3
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/dist/context.d.ts +1 -8
- package/dist/core.d.ts +19 -6
- package/dist/core.js +54 -4
- package/dist/route.js +205 -107
- package/package.json +2 -1
package/dist/context.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import { Core } from './core.js';
|
|
1
|
+
import { Core, Plugin } from './core.js';
|
|
2
2
|
import { Route } from './route.js';
|
|
3
3
|
import { HookHandler } from './hook.js';
|
|
4
4
|
import { Middleware } from './middleware.js';
|
|
5
5
|
import { IRenderer } from '@yumerijs/types';
|
|
6
|
-
interface Plugin {
|
|
7
|
-
apply: (ctx: Context, config: any) => any;
|
|
8
|
-
disable: (ctx: Context) => Promise<void>;
|
|
9
|
-
depend: Array<string>;
|
|
10
|
-
provide: Array<string>;
|
|
11
|
-
}
|
|
12
6
|
export interface Components {
|
|
13
7
|
[key: string]: any;
|
|
14
8
|
}
|
|
@@ -123,4 +117,3 @@ export declare class Context {
|
|
|
123
117
|
*/
|
|
124
118
|
dispose(): Promise<void>;
|
|
125
119
|
}
|
|
126
|
-
export {};
|
package/dist/core.d.ts
CHANGED
|
@@ -9,12 +9,25 @@ import { HookHandler, Hook } from './hook.js';
|
|
|
9
9
|
import { Server as CoreServer } from './server.js';
|
|
10
10
|
import { I18n } from './i18n.js';
|
|
11
11
|
import { IRenderer } from '@yumerijs/types';
|
|
12
|
-
interface Plugin {
|
|
13
|
-
apply
|
|
14
|
-
disable
|
|
15
|
-
depend
|
|
16
|
-
provide
|
|
12
|
+
export interface Plugin {
|
|
13
|
+
apply?: (ctx: Context, config: Config) => Promise<void> | void;
|
|
14
|
+
disable?: (ctx: Context) => Promise<void> | void;
|
|
15
|
+
depend?: Array<string>;
|
|
16
|
+
provide?: Array<string>;
|
|
17
|
+
render?: string;
|
|
18
|
+
config?: Schema<any>;
|
|
17
19
|
}
|
|
20
|
+
type PluginConstructor = new (ctx: Context, config: Config) => Plugin;
|
|
21
|
+
type PluginModuleLike = Plugin | PluginConstructor | ((ctx: Context, config: Config) => Promise<void> | void) | {
|
|
22
|
+
default?: Plugin | PluginConstructor | ((ctx: Context, config: Config) => Promise<void> | void);
|
|
23
|
+
apply?: ((ctx: Context, config: Config) => Promise<void> | void);
|
|
24
|
+
disable?: (ctx: Context) => Promise<void> | void;
|
|
25
|
+
depend?: Array<string>;
|
|
26
|
+
provide?: Array<string>;
|
|
27
|
+
render?: string;
|
|
28
|
+
config?: Schema<any>;
|
|
29
|
+
};
|
|
30
|
+
export declare function resolvePluginModule(module: PluginModuleLike, context: Context, config: Config): Plugin;
|
|
18
31
|
export interface CoreOptions {
|
|
19
32
|
port?: number;
|
|
20
33
|
host?: string;
|
|
@@ -50,7 +63,7 @@ export declare class Core {
|
|
|
50
63
|
getRendererForPlugin(pluginName: string): string | undefined;
|
|
51
64
|
runCore(): Promise<void>;
|
|
52
65
|
getShortPluginName(pluginName: string): string;
|
|
53
|
-
plugin(module:
|
|
66
|
+
plugin(module: PluginModuleLike, context: Context, config: Config): Promise<void>;
|
|
54
67
|
registerComponent(name: string, component: any): void;
|
|
55
68
|
getComponent(name: string): any;
|
|
56
69
|
unregisterComponent(name: string): void;
|
package/dist/core.js
CHANGED
|
@@ -6,6 +6,55 @@ import { Hook } from './hook.js';
|
|
|
6
6
|
import { Server as CoreServer } from './server.js';
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
const version = JSON.parse(await fs.promises.readFile(new URL('../package.json', import.meta.url), 'utf-8')).version;
|
|
9
|
+
function isClassPlugin(value) {
|
|
10
|
+
if (typeof value !== 'function')
|
|
11
|
+
return false;
|
|
12
|
+
const source = Function.prototype.toString.call(value);
|
|
13
|
+
return source.startsWith('class ');
|
|
14
|
+
}
|
|
15
|
+
function mergePluginMeta(target, source) {
|
|
16
|
+
if (!source || typeof source !== 'object')
|
|
17
|
+
return target;
|
|
18
|
+
if (target.depend == null && Array.isArray(source.depend))
|
|
19
|
+
target.depend = source.depend;
|
|
20
|
+
if (target.provide == null && Array.isArray(source.provide))
|
|
21
|
+
target.provide = source.provide;
|
|
22
|
+
if (target.render == null && typeof source.render === 'string')
|
|
23
|
+
target.render = source.render;
|
|
24
|
+
if (target.config == null && source.config)
|
|
25
|
+
target.config = source.config;
|
|
26
|
+
if (target.disable == null && typeof source.disable === 'function')
|
|
27
|
+
target.disable = source.disable.bind(source);
|
|
28
|
+
return target;
|
|
29
|
+
}
|
|
30
|
+
export function resolvePluginModule(module, context, config) {
|
|
31
|
+
let candidate;
|
|
32
|
+
// 只有对象模块才取 default/apply
|
|
33
|
+
if (typeof module === 'object' && module !== null) {
|
|
34
|
+
candidate = module.default ?? module.apply ?? module;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
candidate = module;
|
|
38
|
+
}
|
|
39
|
+
let plugin;
|
|
40
|
+
if (isClassPlugin(candidate)) {
|
|
41
|
+
plugin = new candidate(context, config);
|
|
42
|
+
}
|
|
43
|
+
else if (typeof candidate === 'function') {
|
|
44
|
+
plugin = { apply: candidate };
|
|
45
|
+
}
|
|
46
|
+
else if (candidate && typeof candidate === 'object') {
|
|
47
|
+
plugin = candidate;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
throw new TypeError('Invalid plugin module. Expected class, function, or plugin object.');
|
|
51
|
+
}
|
|
52
|
+
mergePluginMeta(plugin, module);
|
|
53
|
+
if (candidate !== module) {
|
|
54
|
+
mergePluginMeta(plugin, candidate);
|
|
55
|
+
}
|
|
56
|
+
return plugin;
|
|
57
|
+
}
|
|
9
58
|
export const coreConfigSchema = Schema.object({
|
|
10
59
|
port: Schema.number('监听端口').default(14510),
|
|
11
60
|
host: Schema.string('监听地址').default('0.0.0.0'),
|
|
@@ -82,10 +131,11 @@ export class Core {
|
|
|
82
131
|
return pluginName;
|
|
83
132
|
}
|
|
84
133
|
async plugin(module, context, config) {
|
|
134
|
+
const plugin = resolvePluginModule(module, context, config);
|
|
85
135
|
const shortName = this.getShortPluginName(context.pluginname);
|
|
86
|
-
context.module =
|
|
136
|
+
context.module = plugin;
|
|
87
137
|
// 自动依赖注入
|
|
88
|
-
const depend =
|
|
138
|
+
const depend = plugin.depend || [];
|
|
89
139
|
for (const name of depend) {
|
|
90
140
|
const component = this.getComponent(name);
|
|
91
141
|
if (component) {
|
|
@@ -93,8 +143,8 @@ export class Core {
|
|
|
93
143
|
}
|
|
94
144
|
}
|
|
95
145
|
this.logger.info(`apply plugin ${shortName}`);
|
|
96
|
-
if (
|
|
97
|
-
await
|
|
146
|
+
if (plugin.apply) {
|
|
147
|
+
await plugin.apply(context, config);
|
|
98
148
|
}
|
|
99
149
|
}
|
|
100
150
|
registerComponent(name, component) {
|
package/dist/route.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WebSocketServer } from 'ws';
|
|
2
|
+
import { isIP } from 'node:net';
|
|
2
3
|
function parsePatternToSegments(pattern) {
|
|
3
4
|
// Normalize: remove leading/trailing slashes for consistent splitting
|
|
4
5
|
const norm = pattern.replace(/^\/+|\/+$/g, '');
|
|
@@ -22,22 +23,195 @@ function parsePatternToSegments(pattern) {
|
|
|
22
23
|
}
|
|
23
24
|
return { segments, params };
|
|
24
25
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
const parts = hostPattern.split('.');
|
|
28
|
-
return parts.map(part => {
|
|
29
|
-
// 简单的参数解析逻辑
|
|
30
|
-
if (part.startsWith(':')) {
|
|
31
|
-
const lastChar = part[part.length - 1];
|
|
32
|
-
const hasModifier = ['?', '+', '*'].includes(lastChar);
|
|
33
|
-
return {
|
|
34
|
-
type: 'param',
|
|
35
|
-
name: hasModifier ? part.slice(1, -1) : part.slice(1),
|
|
36
|
-
modifier: hasModifier ? lastChar : '',
|
|
37
|
-
};
|
|
38
|
-
}
|
|
26
|
+
function parseSegmentToken(part) {
|
|
27
|
+
if (!part.startsWith(':')) {
|
|
39
28
|
return { type: 'static', value: part };
|
|
40
|
-
}
|
|
29
|
+
}
|
|
30
|
+
let name = part.slice(1);
|
|
31
|
+
let modifier = '';
|
|
32
|
+
const lastChar = name[name.length - 1];
|
|
33
|
+
if (lastChar === '?' || lastChar === '*' || lastChar === '+') {
|
|
34
|
+
modifier = lastChar;
|
|
35
|
+
name = name.slice(0, -1);
|
|
36
|
+
}
|
|
37
|
+
return { type: 'param', name, modifier };
|
|
38
|
+
}
|
|
39
|
+
function splitHostAndPortPattern(pattern) {
|
|
40
|
+
const normalized = pattern.trim().toLowerCase();
|
|
41
|
+
if (normalized.startsWith('[')) {
|
|
42
|
+
const end = normalized.indexOf(']');
|
|
43
|
+
if (end === -1)
|
|
44
|
+
return { hostPart: normalized };
|
|
45
|
+
const hostPart = normalized.slice(1, end);
|
|
46
|
+
const rest = normalized.slice(end + 1);
|
|
47
|
+
if (rest.startsWith(':')) {
|
|
48
|
+
return { hostPart, portPart: rest.slice(1) };
|
|
49
|
+
}
|
|
50
|
+
return { hostPart };
|
|
51
|
+
}
|
|
52
|
+
const colonCount = (normalized.match(/:/g) || []).length;
|
|
53
|
+
const lastColon = normalized.lastIndexOf(':');
|
|
54
|
+
const hasDots = normalized.includes('.');
|
|
55
|
+
if (lastColon === -1) {
|
|
56
|
+
return { hostPart: normalized };
|
|
57
|
+
}
|
|
58
|
+
const suffix = normalized.slice(lastColon + 1);
|
|
59
|
+
const prefix = normalized.slice(0, lastColon);
|
|
60
|
+
const isPortToken = /^\d+$/.test(suffix) || /^:[a-z_][a-z0-9_]*[?*+]?$/.test(`:${suffix}`);
|
|
61
|
+
if (!isPortToken) {
|
|
62
|
+
return { hostPart: normalized };
|
|
63
|
+
}
|
|
64
|
+
if (normalized.startsWith(':') && !hasDots) {
|
|
65
|
+
const paramBody = prefix.slice(1);
|
|
66
|
+
if (/^[a-z_][a-z0-9_]*$/.test(paramBody)) {
|
|
67
|
+
return { hostPart: prefix, portPart: suffix };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (colonCount === 1 && !normalized.startsWith(':')) {
|
|
71
|
+
return { hostPart: prefix, portPart: suffix };
|
|
72
|
+
}
|
|
73
|
+
if (hasDots) {
|
|
74
|
+
return { hostPart: prefix, portPart: suffix };
|
|
75
|
+
}
|
|
76
|
+
return { hostPart: normalized };
|
|
77
|
+
}
|
|
78
|
+
function parseHostPattern(hostPattern) {
|
|
79
|
+
const { hostPart, portPart } = splitHostAndPortPattern(hostPattern);
|
|
80
|
+
const matchWholeHost = !hostPart.includes('.') || hostPart.includes(':');
|
|
81
|
+
const rawParts = matchWholeHost ? [hostPart] : hostPart.split('.');
|
|
82
|
+
return {
|
|
83
|
+
hostSegments: rawParts.map(parseSegmentToken),
|
|
84
|
+
portSegment: portPart ? parseSegmentToken(portPart) : undefined,
|
|
85
|
+
matchWholeHost,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function parseAuthority(host) {
|
|
89
|
+
const normalized = host.trim().toLowerCase();
|
|
90
|
+
if (normalized.startsWith('[')) {
|
|
91
|
+
const end = normalized.indexOf(']');
|
|
92
|
+
if (end !== -1) {
|
|
93
|
+
const hostname = normalized.slice(1, end);
|
|
94
|
+
const rest = normalized.slice(end + 1);
|
|
95
|
+
const port = rest.startsWith(':') ? rest.slice(1) : undefined;
|
|
96
|
+
return { hostname, port, kind: 'ipv6' };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (isIP(normalized) === 6) {
|
|
100
|
+
return { hostname: normalized, kind: 'ipv6' };
|
|
101
|
+
}
|
|
102
|
+
const lastColon = normalized.lastIndexOf(':');
|
|
103
|
+
if (lastColon !== -1 && normalized.indexOf(':') === lastColon) {
|
|
104
|
+
const maybePort = normalized.slice(lastColon + 1);
|
|
105
|
+
if (/^\d+$/.test(maybePort)) {
|
|
106
|
+
const hostname = normalized.slice(0, lastColon);
|
|
107
|
+
if (isIP(hostname) === 4) {
|
|
108
|
+
return { hostname, port: maybePort, kind: 'ipv4' };
|
|
109
|
+
}
|
|
110
|
+
return { hostname, port: maybePort, kind: 'domain' };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (isIP(normalized) === 4) {
|
|
114
|
+
return { hostname: normalized, kind: 'ipv4' };
|
|
115
|
+
}
|
|
116
|
+
return { hostname: normalized, kind: 'domain' };
|
|
117
|
+
}
|
|
118
|
+
function matchSingleSegment(seg, value, params) {
|
|
119
|
+
if (seg.type === 'static') {
|
|
120
|
+
return value === seg.value;
|
|
121
|
+
}
|
|
122
|
+
switch (seg.modifier) {
|
|
123
|
+
case '':
|
|
124
|
+
case '+':
|
|
125
|
+
case '*':
|
|
126
|
+
if (value == null || value === '') {
|
|
127
|
+
if (seg.modifier === '*') {
|
|
128
|
+
params[seg.name] = undefined;
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
params[seg.name] = value;
|
|
134
|
+
return true;
|
|
135
|
+
case '?':
|
|
136
|
+
params[seg.name] = value || undefined;
|
|
137
|
+
return true;
|
|
138
|
+
default:
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function matchHostSegments(segments, parts, joiner, params) {
|
|
143
|
+
let hi = 0;
|
|
144
|
+
let hj = 0;
|
|
145
|
+
while (hi < segments.length) {
|
|
146
|
+
const seg = segments[hi];
|
|
147
|
+
const nextSegIsStatic = !!segments[hi + 1] && segments[hi + 1].type === 'static';
|
|
148
|
+
if (seg.type === 'static') {
|
|
149
|
+
if (hj >= parts.length || parts[hj] !== seg.value)
|
|
150
|
+
return false;
|
|
151
|
+
hi++;
|
|
152
|
+
hj++;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
switch (seg.modifier) {
|
|
156
|
+
case '':
|
|
157
|
+
if (hj >= parts.length)
|
|
158
|
+
return false;
|
|
159
|
+
params[seg.name] = parts[hj];
|
|
160
|
+
hi++;
|
|
161
|
+
hj++;
|
|
162
|
+
break;
|
|
163
|
+
case '?':
|
|
164
|
+
if (hj < parts.length) {
|
|
165
|
+
if (nextSegIsStatic && parts[hj] === segments[hi + 1].value) {
|
|
166
|
+
params[seg.name] = undefined;
|
|
167
|
+
hi++;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
params[seg.name] = parts[hj];
|
|
171
|
+
hi++;
|
|
172
|
+
hj++;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
params[seg.name] = undefined;
|
|
177
|
+
hi++;
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case '+': {
|
|
181
|
+
if (hj >= parts.length)
|
|
182
|
+
return false;
|
|
183
|
+
let end = parts.length;
|
|
184
|
+
if (nextSegIsStatic) {
|
|
185
|
+
const nextStatic = segments[hi + 1].value;
|
|
186
|
+
const found = parts.indexOf(nextStatic, hj);
|
|
187
|
+
if (found === -1 || found === hj)
|
|
188
|
+
return false;
|
|
189
|
+
end = found;
|
|
190
|
+
}
|
|
191
|
+
params[seg.name] = parts.slice(hj, end).join(joiner);
|
|
192
|
+
hj = end;
|
|
193
|
+
hi++;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case '*': {
|
|
197
|
+
let end = parts.length;
|
|
198
|
+
if (nextSegIsStatic) {
|
|
199
|
+
const nextStatic = segments[hi + 1].value;
|
|
200
|
+
const found = parts.indexOf(nextStatic, hj);
|
|
201
|
+
if (found !== -1)
|
|
202
|
+
end = found;
|
|
203
|
+
}
|
|
204
|
+
const value = parts.slice(hj, end).join(joiner);
|
|
205
|
+
params[seg.name] = value || undefined;
|
|
206
|
+
hj = end;
|
|
207
|
+
hi++;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
default:
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return hj === parts.length;
|
|
41
215
|
}
|
|
42
216
|
/**
|
|
43
217
|
* Route class using segment-based matching (no fragile capture-group-index mapping).
|
|
@@ -113,102 +287,26 @@ export class Route {
|
|
|
113
287
|
if (this.routehost && this.routehost.length > 0) {
|
|
114
288
|
if (!host)
|
|
115
289
|
return null; // 如果设置了 host 限制但没有传入 host,直接失败
|
|
116
|
-
const
|
|
117
|
-
const hostParts = actualHost.split('.');
|
|
290
|
+
const actual = parseAuthority(host);
|
|
118
291
|
let hostMatched = false;
|
|
119
292
|
for (const pattern of this.routehost) {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
293
|
+
const parsedPattern = parseHostPattern(pattern);
|
|
294
|
+
const hostParts = parsedPattern.matchWholeHost || actual.kind === 'ipv6'
|
|
295
|
+
? [actual.hostname]
|
|
296
|
+
: actual.hostname.split('.');
|
|
297
|
+
const joiner = parsedPattern.matchWholeHost || actual.kind === 'ipv6' ? ':' : '.';
|
|
123
298
|
let tempParams = {};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
hi++;
|
|
134
|
-
hj++;
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
// 参数匹配逻辑 (:, ?, +, *)
|
|
138
|
-
switch (seg.modifier) {
|
|
139
|
-
case '': // required single
|
|
140
|
-
if (hj >= hostParts.length) {
|
|
141
|
-
possible = false;
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
tempParams[seg.name] = hostParts[hj];
|
|
145
|
-
hi++;
|
|
146
|
-
hj++;
|
|
147
|
-
break;
|
|
148
|
-
case '?': // optional single
|
|
149
|
-
if (hj < hostParts.length) {
|
|
150
|
-
if (nextSegIsStatic && hostParts[hj] === hSegments[hi + 1].value.toLowerCase()) {
|
|
151
|
-
tempParams[seg.name] = undefined;
|
|
152
|
-
hi++;
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
tempParams[seg.name] = hostParts[hj];
|
|
156
|
-
hj++;
|
|
157
|
-
hi++;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
tempParams[seg.name] = undefined;
|
|
162
|
-
hi++;
|
|
163
|
-
}
|
|
164
|
-
break;
|
|
165
|
-
case '+': // required multi
|
|
166
|
-
if (hj >= hostParts.length) {
|
|
167
|
-
possible = false;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
let endP = hostParts.length;
|
|
171
|
-
if (nextSegIsStatic) {
|
|
172
|
-
let found = hostParts.indexOf(hSegments[hi + 1].value.toLowerCase(), hj);
|
|
173
|
-
if (found === -1) {
|
|
174
|
-
possible = false;
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
endP = found;
|
|
178
|
-
}
|
|
179
|
-
if (endP === hj) {
|
|
180
|
-
possible = false;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
tempParams[seg.name] = hostParts.slice(hj, endP).join('.');
|
|
184
|
-
hj = endP;
|
|
185
|
-
hi++;
|
|
186
|
-
break;
|
|
187
|
-
case '*': // optional multi
|
|
188
|
-
let endS = hostParts.length;
|
|
189
|
-
if (nextSegIsStatic) {
|
|
190
|
-
let found = hostParts.indexOf(hSegments[hi + 1].value.toLowerCase(), hj);
|
|
191
|
-
if (found !== -1)
|
|
192
|
-
endS = found;
|
|
193
|
-
}
|
|
194
|
-
const val = hostParts.slice(hj, endS).join('.');
|
|
195
|
-
tempParams[seg.name] = val === '' ? undefined : val;
|
|
196
|
-
hj = endS;
|
|
197
|
-
hi++;
|
|
198
|
-
break;
|
|
199
|
-
default:
|
|
200
|
-
possible = false;
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
if (!possible)
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
if (possible && hj === hostParts.length) {
|
|
208
|
-
hostMatched = true;
|
|
209
|
-
hostParams = tempParams;
|
|
210
|
-
break; // 只要匹配到一个 host pattern 就行
|
|
299
|
+
const hostOk = matchHostSegments(parsedPattern.hostSegments, hostParts, joiner, tempParams);
|
|
300
|
+
if (!hostOk)
|
|
301
|
+
continue;
|
|
302
|
+
if (parsedPattern.portSegment) {
|
|
303
|
+
const portOk = matchSingleSegment(parsedPattern.portSegment, actual.port, tempParams);
|
|
304
|
+
if (!portOk)
|
|
305
|
+
continue;
|
|
211
306
|
}
|
|
307
|
+
hostMatched = true;
|
|
308
|
+
hostParams = tempParams;
|
|
309
|
+
break; // 只要匹配到一个 host pattern 就行
|
|
212
310
|
}
|
|
213
311
|
if (!hostMatched)
|
|
214
312
|
return null;
|
package/package.json
CHANGED