@kevisual/router 0.0.26 → 0.0.27

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,3 @@
1
+ declare const parseXml: (req: any) => Promise<any>;
2
+
3
+ export { parseXml };
@@ -0,0 +1,35 @@
1
+ import xml2js from 'xml2js';
2
+
3
+ const parseXml = async (req) => {
4
+ return await new Promise((resolve) => {
5
+ // 读取请求数据
6
+ let data = '';
7
+ req.setEncoding('utf8');
8
+ // 监听data事件,接收数据片段
9
+ req.on('data', (chunk) => {
10
+ data += chunk;
11
+ });
12
+ // 当请求结束时处理数据
13
+ req.on('end', () => {
14
+ try {
15
+ // 使用xml2js解析XML
16
+ xml2js.parseString(data, function (err, result) {
17
+ if (err) {
18
+ console.error('XML解析错误:', err);
19
+ resolve(null);
20
+ }
21
+ else {
22
+ const jsonString = JSON.stringify(result);
23
+ resolve(jsonString);
24
+ }
25
+ });
26
+ }
27
+ catch (error) {
28
+ console.error('处理请求时出错:', error);
29
+ resolve(null);
30
+ }
31
+ });
32
+ });
33
+ };
34
+
35
+ export { parseXml };
@@ -8,7 +8,7 @@ function requireDist () {
8
8
  if (hasRequiredDist) return dist;
9
9
  hasRequiredDist = 1;
10
10
  Object.defineProperty(dist, "__esModule", { value: true });
11
- dist.TokenData = void 0;
11
+ dist.PathError = dist.TokenData = void 0;
12
12
  dist.parse = parse;
13
13
  dist.compile = compile;
14
14
  dist.match = match;
@@ -18,7 +18,6 @@ function requireDist () {
18
18
  const NOOP_VALUE = (value) => value;
19
19
  const ID_START = /^[$_\p{ID_Start}]$/u;
20
20
  const ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
21
- const DEBUG_URL = "https://git.new/pathToRegexpError";
22
21
  const SIMPLE_TOKENS = {
23
22
  // Groups.
24
23
  "{": "{",
@@ -36,7 +35,7 @@ function requireDist () {
36
35
  * Escape text for stringify to path.
37
36
  */
38
37
  function escapeText(str) {
39
- return str.replace(/[{}()\[\]+?!:*]/g, "\\$&");
38
+ return str.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
40
39
  }
41
40
  /**
42
41
  * Escape a regular expression string.
@@ -45,161 +44,135 @@ function requireDist () {
45
44
  return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
46
45
  }
47
46
  /**
48
- * Tokenize input string.
47
+ * Tokenized path instance.
48
+ */
49
+ class TokenData {
50
+ constructor(tokens, originalPath) {
51
+ this.tokens = tokens;
52
+ this.originalPath = originalPath;
53
+ }
54
+ }
55
+ dist.TokenData = TokenData;
56
+ /**
57
+ * ParseError is thrown when there is an error processing the path.
49
58
  */
50
- function* lexer(str) {
59
+ class PathError extends TypeError {
60
+ constructor(message, originalPath) {
61
+ let text = message;
62
+ if (originalPath)
63
+ text += `: ${originalPath}`;
64
+ text += `; visit https://git.new/pathToRegexpError for info`;
65
+ super(text);
66
+ this.originalPath = originalPath;
67
+ }
68
+ }
69
+ dist.PathError = PathError;
70
+ /**
71
+ * Parse a string for the raw tokens.
72
+ */
73
+ function parse(str, options = {}) {
74
+ const { encodePath = NOOP_VALUE } = options;
51
75
  const chars = [...str];
52
- let i = 0;
76
+ const tokens = [];
77
+ let index = 0;
78
+ let pos = 0;
53
79
  function name() {
54
80
  let value = "";
55
- if (ID_START.test(chars[++i])) {
56
- value += chars[i];
57
- while (ID_CONTINUE.test(chars[++i])) {
58
- value += chars[i];
59
- }
81
+ if (ID_START.test(chars[index])) {
82
+ do {
83
+ value += chars[index++];
84
+ } while (ID_CONTINUE.test(chars[index]));
60
85
  }
61
- else if (chars[i] === '"') {
62
- let pos = i;
63
- while (i < chars.length) {
64
- if (chars[++i] === '"') {
65
- i++;
66
- pos = 0;
86
+ else if (chars[index] === '"') {
87
+ let quoteStart = index;
88
+ while (index++ < chars.length) {
89
+ if (chars[index] === '"') {
90
+ index++;
91
+ quoteStart = 0;
67
92
  break;
68
93
  }
69
- if (chars[i] === "\\") {
70
- value += chars[++i];
71
- }
72
- else {
73
- value += chars[i];
74
- }
94
+ // Increment over escape characters.
95
+ if (chars[index] === "\\")
96
+ index++;
97
+ value += chars[index];
75
98
  }
76
- if (pos) {
77
- throw new TypeError(`Unterminated quote at ${pos}: ${DEBUG_URL}`);
99
+ if (quoteStart) {
100
+ throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
78
101
  }
79
102
  }
80
103
  if (!value) {
81
- throw new TypeError(`Missing parameter name at ${i}: ${DEBUG_URL}`);
104
+ throw new PathError(`Missing parameter name at index ${index}`, str);
82
105
  }
83
106
  return value;
84
107
  }
85
- while (i < chars.length) {
86
- const value = chars[i];
108
+ while (index < chars.length) {
109
+ const value = chars[index];
87
110
  const type = SIMPLE_TOKENS[value];
88
111
  if (type) {
89
- yield { type, index: i++, value };
112
+ tokens.push({ type, index: index++, value });
90
113
  }
91
114
  else if (value === "\\") {
92
- yield { type: "ESCAPED", index: i++, value: chars[i++] };
115
+ tokens.push({ type: "escape", index: index++, value: chars[index++] });
93
116
  }
94
117
  else if (value === ":") {
95
- const value = name();
96
- yield { type: "PARAM", index: i, value };
118
+ tokens.push({ type: "param", index: index++, value: name() });
97
119
  }
98
120
  else if (value === "*") {
99
- const value = name();
100
- yield { type: "WILDCARD", index: i, value };
121
+ tokens.push({ type: "wildcard", index: index++, value: name() });
101
122
  }
102
123
  else {
103
- yield { type: "CHAR", index: i, value: chars[i++] };
124
+ tokens.push({ type: "char", index: index++, value });
104
125
  }
105
126
  }
106
- return { type: "END", index: i, value: "" };
107
- }
108
- class Iter {
109
- constructor(tokens) {
110
- this.tokens = tokens;
111
- }
112
- peek() {
113
- if (!this._peek) {
114
- const next = this.tokens.next();
115
- this._peek = next.value;
116
- }
117
- return this._peek;
118
- }
119
- tryConsume(type) {
120
- const token = this.peek();
121
- if (token.type !== type)
122
- return;
123
- this._peek = undefined; // Reset after consumed.
124
- return token.value;
125
- }
126
- consume(type) {
127
- const value = this.tryConsume(type);
128
- if (value !== undefined)
129
- return value;
130
- const { type: nextType, index } = this.peek();
131
- throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}: ${DEBUG_URL}`);
132
- }
133
- text() {
134
- let result = "";
135
- let value;
136
- while ((value = this.tryConsume("CHAR") || this.tryConsume("ESCAPED"))) {
137
- result += value;
138
- }
139
- return result;
140
- }
141
- }
142
- /**
143
- * Tokenized path instance.
144
- */
145
- class TokenData {
146
- constructor(tokens) {
147
- this.tokens = tokens;
148
- }
149
- }
150
- dist.TokenData = TokenData;
151
- /**
152
- * Parse a string for the raw tokens.
153
- */
154
- function parse(str, options = {}) {
155
- const { encodePath = NOOP_VALUE } = options;
156
- const it = new Iter(lexer(str));
157
- function consume(endType) {
158
- const tokens = [];
127
+ tokens.push({ type: "end", index, value: "" });
128
+ function consumeUntil(endType) {
129
+ const output = [];
159
130
  while (true) {
160
- const path = it.text();
161
- if (path)
162
- tokens.push({ type: "text", value: encodePath(path) });
163
- const param = it.tryConsume("PARAM");
164
- if (param) {
165
- tokens.push({
166
- type: "param",
167
- name: param,
131
+ const token = tokens[pos++];
132
+ if (token.type === endType)
133
+ break;
134
+ if (token.type === "char" || token.type === "escape") {
135
+ let path = token.value;
136
+ let cur = tokens[pos];
137
+ while (cur.type === "char" || cur.type === "escape") {
138
+ path += cur.value;
139
+ cur = tokens[++pos];
140
+ }
141
+ output.push({
142
+ type: "text",
143
+ value: encodePath(path),
168
144
  });
169
145
  continue;
170
146
  }
171
- const wildcard = it.tryConsume("WILDCARD");
172
- if (wildcard) {
173
- tokens.push({
174
- type: "wildcard",
175
- name: wildcard,
147
+ if (token.type === "param" || token.type === "wildcard") {
148
+ output.push({
149
+ type: token.type,
150
+ name: token.value,
176
151
  });
177
152
  continue;
178
153
  }
179
- const open = it.tryConsume("{");
180
- if (open) {
181
- tokens.push({
154
+ if (token.type === "{") {
155
+ output.push({
182
156
  type: "group",
183
- tokens: consume("}"),
157
+ tokens: consumeUntil("}"),
184
158
  });
185
159
  continue;
186
160
  }
187
- it.consume(endType);
188
- return tokens;
161
+ throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
189
162
  }
163
+ return output;
190
164
  }
191
- const tokens = consume("END");
192
- return new TokenData(tokens);
165
+ return new TokenData(consumeUntil("end"), str);
193
166
  }
194
167
  /**
195
168
  * Compile a string to a template function for the path.
196
169
  */
197
170
  function compile(path, options = {}) {
198
171
  const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
199
- const data = path instanceof TokenData ? path : parse(path, options);
172
+ const data = typeof path === "object" ? path : parse(path, options);
200
173
  const fn = tokensToFunction(data.tokens, delimiter, encode);
201
- return function path(data = {}) {
202
- const [path, ...missing] = fn(data);
174
+ return function path(params = {}) {
175
+ const [path, ...missing] = fn(params);
203
176
  if (missing.length) {
204
177
  throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
205
178
  }
@@ -296,14 +269,12 @@ function requireDist () {
296
269
  function pathToRegexp(path, options = {}) {
297
270
  const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true, } = options;
298
271
  const keys = [];
299
- const sources = [];
300
272
  const flags = sensitive ? "" : "i";
301
- const paths = Array.isArray(path) ? path : [path];
302
- const items = paths.map((path) => path instanceof TokenData ? path : parse(path, options));
303
- for (const { tokens } of items) {
304
- for (const seq of flatten(tokens, 0, [])) {
305
- const regexp = sequenceToRegExp(seq, delimiter, keys);
306
- sources.push(regexp);
273
+ const sources = [];
274
+ for (const input of pathsToArray(path, [])) {
275
+ const data = typeof input === "object" ? input : parse(input, options);
276
+ for (const tokens of flatten(data.tokens, 0, [])) {
277
+ sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
307
278
  }
308
279
  }
309
280
  let pattern = `^(?:${sources.join("|")})`;
@@ -313,6 +284,19 @@ function requireDist () {
313
284
  const regexp = new RegExp(pattern, flags);
314
285
  return { regexp, keys };
315
286
  }
287
+ /**
288
+ * Convert a path or array of paths into a flat array.
289
+ */
290
+ function pathsToArray(paths, init) {
291
+ if (Array.isArray(paths)) {
292
+ for (const p of paths)
293
+ pathsToArray(p, init);
294
+ }
295
+ else {
296
+ init.push(paths);
297
+ }
298
+ return init;
299
+ }
316
300
  /**
317
301
  * Generate a flat list of sequence tokens from the given tokens.
318
302
  */
@@ -322,8 +306,7 @@ function requireDist () {
322
306
  }
323
307
  const token = tokens[index];
324
308
  if (token.type === "group") {
325
- const fork = init.slice();
326
- for (const seq of flatten(token.tokens, 0, fork)) {
309
+ for (const seq of flatten(token.tokens, 0, init.slice())) {
327
310
  yield* flatten(tokens, index + 1, seq);
328
311
  }
329
312
  }
@@ -335,12 +318,11 @@ function requireDist () {
335
318
  /**
336
319
  * Transform a flat sequence of tokens into a regular expression.
337
320
  */
338
- function sequenceToRegExp(tokens, delimiter, keys) {
321
+ function toRegExpSource(tokens, delimiter, keys, originalPath) {
339
322
  let result = "";
340
323
  let backtrack = "";
341
324
  let isSafeSegmentParam = true;
342
- for (let i = 0; i < tokens.length; i++) {
343
- const token = tokens[i];
325
+ for (const token of tokens) {
344
326
  if (token.type === "text") {
345
327
  result += escape(token.value);
346
328
  backtrack += token.value;
@@ -349,7 +331,7 @@ function requireDist () {
349
331
  }
350
332
  if (token.type === "param" || token.type === "wildcard") {
351
333
  if (!isSafeSegmentParam && !backtrack) {
352
- throw new TypeError(`Missing text after "${token.name}": ${DEBUG_URL}`);
334
+ throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
353
335
  }
354
336
  if (token.type === "param") {
355
337
  result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
@@ -365,6 +347,9 @@ function requireDist () {
365
347
  }
366
348
  return result;
367
349
  }
350
+ /**
351
+ * Block backtracking on previous text and ignore delimiter string.
352
+ */
368
353
  function negate(delimiter, backtrack) {
369
354
  if (backtrack.length < 2) {
370
355
  if (delimiter.length < 2)
@@ -377,36 +362,57 @@ function requireDist () {
377
362
  return `(?:(?!${escape(backtrack)}|${escape(delimiter)})[\\s\\S])`;
378
363
  }
379
364
  /**
380
- * Stringify token data into a path string.
365
+ * Stringify an array of tokens into a path string.
381
366
  */
382
- function stringify(data) {
383
- return data.tokens
384
- .map(function stringifyToken(token, index, tokens) {
385
- if (token.type === "text")
386
- return escapeText(token.value);
367
+ function stringifyTokens(tokens) {
368
+ let value = "";
369
+ let i = 0;
370
+ function name(value) {
371
+ const isSafe = isNameSafe(value) && isNextNameSafe(tokens[i]);
372
+ return isSafe ? value : JSON.stringify(value);
373
+ }
374
+ while (i < tokens.length) {
375
+ const token = tokens[i++];
376
+ if (token.type === "text") {
377
+ value += escapeText(token.value);
378
+ continue;
379
+ }
387
380
  if (token.type === "group") {
388
- return `{${token.tokens.map(stringifyToken).join("")}}`;
381
+ value += `{${stringifyTokens(token.tokens)}}`;
382
+ continue;
389
383
  }
390
- const isSafe = isNameSafe(token.name) && isNextNameSafe(tokens[index + 1]);
391
- const key = isSafe ? token.name : JSON.stringify(token.name);
392
- if (token.type === "param")
393
- return `:${key}`;
394
- if (token.type === "wildcard")
395
- return `*${key}`;
396
- throw new TypeError(`Unexpected token: ${token}`);
397
- })
398
- .join("");
384
+ if (token.type === "param") {
385
+ value += `:${name(token.name)}`;
386
+ continue;
387
+ }
388
+ if (token.type === "wildcard") {
389
+ value += `*${name(token.name)}`;
390
+ continue;
391
+ }
392
+ throw new TypeError(`Unknown token type: ${token.type}`);
393
+ }
394
+ return value;
399
395
  }
396
+ /**
397
+ * Stringify token data into a path string.
398
+ */
399
+ function stringify(data) {
400
+ return stringifyTokens(data.tokens);
401
+ }
402
+ /**
403
+ * Validate the parameter name contains valid ID characters.
404
+ */
400
405
  function isNameSafe(name) {
401
406
  const [first, ...rest] = name;
402
- if (!ID_START.test(first))
403
- return false;
404
- return rest.every((char) => ID_CONTINUE.test(char));
407
+ return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
405
408
  }
409
+ /**
410
+ * Validate the next token does not interfere with the current param name.
411
+ */
406
412
  function isNextNameSafe(token) {
407
- if ((token === null || token === void 0 ? void 0 : token.type) !== "text")
408
- return true;
409
- return !ID_CONTINUE.test(token.value[0]);
413
+ if (token && token.type === "text")
414
+ return !ID_CONTINUE.test(token.value[0]);
415
+ return true;
410
416
  }
411
417
 
412
418
  return dist;
package/dist/router.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { z } from 'zod';
1
+ import { Schema } from 'zod';
2
2
  export { Schema } from 'zod';
3
3
  import http, { IncomingMessage, ServerResponse } from 'node:http';
4
4
  import https from 'node:https';
5
5
  import http2 from 'node:http2';
6
6
  import * as cookie from 'cookie';
7
7
  import { WebSocketServer, WebSocket } from 'ws';
8
+ import { IncomingMessage as IncomingMessage$1, ServerResponse as ServerResponse$1 } from 'http';
8
9
  import { RouteOpts as RouteOpts$1, QueryRouterServer as QueryRouterServer$1, RouteMiddleware as RouteMiddleware$1, Run as Run$1 } from '@kevisual/router';
9
10
  import { Query, DataOpts, Result } from '@kevisual/query/query';
10
11
 
@@ -41,7 +42,7 @@ type RuleAny = {
41
42
  type: 'any';
42
43
  } & BaseRule;
43
44
  type Rule = RuleString | RuleNumber | RuleBoolean | RuleArray | RuleObject | RuleAny;
44
- declare const createSchema: (rule: Rule) => z.ZodType<any, any, any>;
45
+ declare const createSchema: (rule: Rule) => Schema;
45
46
 
46
47
  type RouterContextT = {
47
48
  code?: number;
@@ -143,7 +144,7 @@ type RouteOpts = {
143
144
  [key: string]: Rule;
144
145
  };
145
146
  schema?: {
146
- [key: string]: any;
147
+ [key: string]: Schema<any>;
147
148
  };
148
149
  isVerify?: boolean;
149
150
  verify?: (ctx?: RouteContext, dev?: boolean) => boolean;
@@ -184,7 +185,7 @@ declare class Route<U = {
184
185
  type?: string;
185
186
  private _validator?;
186
187
  schema?: {
187
- [key: string]: any;
188
+ [key: string]: Schema<any>;
188
189
  };
189
190
  data?: any;
190
191
  /**
@@ -406,6 +407,36 @@ declare class QueryRouterServer extends QueryRouter {
406
407
  }): Promise<any>;
407
408
  }
408
409
 
410
+ declare class Connect {
411
+ path: string;
412
+ key?: string;
413
+ _fn?: (ctx?: RouteContext) => Promise<RouteContext>;
414
+ description?: string;
415
+ connects: {
416
+ path: string;
417
+ key?: string;
418
+ }[];
419
+ share: boolean;
420
+ constructor(path: string);
421
+ use(path: string): void;
422
+ useList(paths: string[]): void;
423
+ useConnect(connect: Connect): void;
424
+ useConnectList(connects: Connect[]): void;
425
+ getPathList(): string[];
426
+ set fn(fn: (ctx?: RouteContext) => Promise<RouteContext>);
427
+ get fn(): (ctx?: RouteContext) => Promise<RouteContext>;
428
+ }
429
+ declare class QueryConnect {
430
+ connects: Connect[];
431
+ constructor();
432
+ add(connect: Connect): void;
433
+ remove(connect: Connect): void;
434
+ getList(): {
435
+ path: string;
436
+ key: string;
437
+ }[];
438
+ }
439
+
409
440
  type Listener = (...args: any[]) => void;
410
441
  type CookieFn = (name: string, value: string, options?: cookie.SerializeOptions, end?: boolean) => void;
411
442
  type HandleCtx = {
@@ -689,12 +720,12 @@ declare class App<T = {}, U = AppReqRes> {
689
720
  importRoutes(routes: any[]): void;
690
721
  importApp(app: App): void;
691
722
  throw(code?: number | string, message?: string, tips?: string): void;
692
- static handleRequest(req: IncomingMessage, res: ServerResponse): Promise<{
723
+ static handleRequest(req: IncomingMessage$1, res: ServerResponse$1): Promise<{
693
724
  cookies: Record<string, string>;
694
725
  token: string;
695
726
  }>;
696
- onServerRequest(fn: (req: IncomingMessage, res: ServerResponse) => void): void;
727
+ onServerRequest(fn: (req: IncomingMessage$1, res: ServerResponse$1) => void): void;
697
728
  }
698
729
 
699
- export { App, CustomError, QueryRouter, QueryRouterServer, QueryUtil, Route, Server, createSchema, define, handleServer, util };
730
+ export { App, Connect, CustomError, QueryConnect, QueryRouter, QueryRouterServer, QueryUtil, Route, Server, createSchema, define, handleServer, util };
700
731
  export type { RouteArray, RouteContext, RouteMiddleware, RouteObject, RouteOpts, Rule, Run };