starlight-server 1.5.0 → 1.6.2
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/router/index.d.ts +7 -3
- package/dist/router/index.js +1 -0
- package/dist/swagger/factories.js +4 -1
- package/package.json +20 -16
- package/src/demo/index.ts +1 -1
- package/src/router/index.ts +9 -5
- package/src/swagger/factories.ts +12 -10
package/dist/router/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
import { type validators } from '@anjianshi/utils/validators/index.js';
|
|
1
2
|
import { type CORSRule } from '../http/cors.js';
|
|
2
3
|
import { type Request, type ResponseUtils } from '../http/index.js';
|
|
3
4
|
import { Swagger, type Method } from '../swagger/index.js';
|
|
4
5
|
import * as helpers from './helpers.js';
|
|
5
6
|
import { type PathParameters } from './match-path.js';
|
|
7
|
+
type WithoutThis<T extends (...args: any[]) => unknown> = (...args: Parameters<T>) => ReturnType<T>;
|
|
6
8
|
export interface BasicContext {
|
|
7
9
|
request: Request;
|
|
8
10
|
response: ResponseUtils;
|
|
9
11
|
pathParameters: PathParameters;
|
|
10
|
-
validatePathParameters: typeof helpers.validatePathParameters
|
|
11
|
-
validateQuery: typeof helpers.validateQuery
|
|
12
|
-
validateBody: typeof helpers.validateBody
|
|
12
|
+
validatePathParameters: WithoutThis<typeof helpers.validatePathParameters>;
|
|
13
|
+
validateQuery: WithoutThis<typeof helpers.validateQuery>;
|
|
14
|
+
validateBody: WithoutThis<typeof helpers.validateBody>;
|
|
15
|
+
validators: typeof validators;
|
|
13
16
|
}
|
|
14
17
|
/** 使用者可自行补充 Context 定义 */
|
|
15
18
|
export interface Context extends BasicContext {
|
|
@@ -65,3 +68,4 @@ export declare class Router {
|
|
|
65
68
|
*/
|
|
66
69
|
readonly handle: (request: Request, response: ResponseUtils) => Promise<void>;
|
|
67
70
|
}
|
|
71
|
+
export {};
|
package/dist/router/index.js
CHANGED
|
@@ -99,6 +99,7 @@ export class Router {
|
|
|
99
99
|
request,
|
|
100
100
|
response,
|
|
101
101
|
pathParameters: matched.parameters,
|
|
102
|
+
validatePathParameters: helpers.validatePathParameters.bind(basicContext),
|
|
102
103
|
validateQuery: helpers.validateQuery.bind(basicContext),
|
|
103
104
|
validateBody: helpers.validateBody.bind(basicContext),
|
|
104
105
|
});
|
|
@@ -22,7 +22,10 @@ export function makeOperation(options = {}) {
|
|
|
22
22
|
? query
|
|
23
23
|
: query
|
|
24
24
|
? Object.entries(query).reduce((result, [name, options]) => {
|
|
25
|
-
const query = makeQuery({
|
|
25
|
+
const query = makeQuery({
|
|
26
|
+
name,
|
|
27
|
+
...('schema' in options ? options : { schema: options }),
|
|
28
|
+
});
|
|
26
29
|
return [...result, query];
|
|
27
30
|
}, [])
|
|
28
31
|
: undefined;
|
package/package.json
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "starlight-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "Simple But Powerful Node.js HTTP Server",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "rimraf dist && (concurrently --raw \"tsc -w\" \"sleep 5 && tsc-alias -w\" \"sleep 6 && nodemon dist/demo/index.js\")",
|
|
8
|
-
"build": "rimraf dist && tsc && tsc-alias",
|
|
9
|
-
"prepublishOnly": "npm run build"
|
|
10
|
-
},
|
|
11
6
|
"keywords": [
|
|
12
7
|
"web",
|
|
13
8
|
"app",
|
|
@@ -29,26 +24,35 @@
|
|
|
29
24
|
"publishConfig": {
|
|
30
25
|
"registry": "https://registry.npmjs.org/"
|
|
31
26
|
},
|
|
27
|
+
"main": "dist/index.js",
|
|
32
28
|
"dependencies": {
|
|
33
|
-
"@anjianshi/utils": "^
|
|
29
|
+
"@anjianshi/utils": "^2.0.7",
|
|
34
30
|
"chalk": "^5.3.0",
|
|
31
|
+
"dayjs": "^1.11.10",
|
|
35
32
|
"debug": "^4.3.4",
|
|
36
|
-
"
|
|
33
|
+
"lodash": "^4.17.21",
|
|
34
|
+
"swagger-ui-dist": "^5.15.1"
|
|
37
35
|
},
|
|
38
36
|
"devDependencies": {
|
|
39
|
-
"@anjianshi/presets-eslint-node": "^
|
|
40
|
-
"@anjianshi/presets-eslint-typescript": "^
|
|
41
|
-
"@anjianshi/presets-prettier": "^
|
|
42
|
-
"@anjianshi/presets-typescript": "^1.
|
|
37
|
+
"@anjianshi/presets-eslint-node": "^4.0.3",
|
|
38
|
+
"@anjianshi/presets-eslint-typescript": "^4.0.3",
|
|
39
|
+
"@anjianshi/presets-prettier": "^3.0.0",
|
|
40
|
+
"@anjianshi/presets-typescript": "^3.1.3",
|
|
43
41
|
"@types/debug": "^4.1.9",
|
|
44
42
|
"@types/lodash": "^4.14.199",
|
|
45
43
|
"@types/node": "^20.8.6",
|
|
46
44
|
"@types/swagger-ui-dist": "^3.30.4",
|
|
47
45
|
"concurrently": "^8.2.1",
|
|
48
46
|
"nodemon": "^3.0.2",
|
|
49
|
-
"rimraf": "^
|
|
50
|
-
"tsc-alias": "^1.8.8"
|
|
47
|
+
"rimraf": "^5.0.5",
|
|
48
|
+
"tsc-alias": "^1.8.8",
|
|
49
|
+
"typescript": "^5.4.5"
|
|
51
50
|
},
|
|
52
51
|
"eslintIgnore": [],
|
|
53
|
-
"prettier": "@anjianshi/presets-prettier/prettierrc"
|
|
54
|
-
|
|
52
|
+
"prettier": "@anjianshi/presets-prettier/prettierrc",
|
|
53
|
+
"scripts": {
|
|
54
|
+
"dev": "rimraf dist && (concurrently --raw \"tsc-with-alias --watch\" \"nodemon dist/demo/index.js\")",
|
|
55
|
+
"build": "rimraf dist && tsc-with-alias",
|
|
56
|
+
"lint": "tsc --noEmit && eslint './src/**/*'"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/demo/index.ts
CHANGED
package/src/router/index.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { joinPath } from '@anjianshi/utils'
|
|
2
|
+
import { type validators } from '@anjianshi/utils/validators/index.js'
|
|
2
3
|
import { getPreflightRequestMethod, handleCORS, type CORSRule } from '@/http/cors.js'
|
|
3
4
|
import { HTTPError, type Request, type ResponseUtils } from '@/http/index.js'
|
|
4
5
|
import { Swagger, type Method } from '@/swagger/index.js'
|
|
5
6
|
import * as helpers from './helpers.js'
|
|
6
7
|
import { matchPath, type PathParameters } from './match-path.js'
|
|
7
8
|
|
|
9
|
+
type WithoutThis<T extends (...args: any[]) => unknown> = (...args: Parameters<T>) => ReturnType<T>
|
|
8
10
|
export interface BasicContext {
|
|
9
11
|
request: Request
|
|
10
12
|
response: ResponseUtils
|
|
11
13
|
pathParameters: PathParameters
|
|
12
|
-
validatePathParameters: typeof helpers.validatePathParameters
|
|
13
|
-
validateQuery: typeof helpers.validateQuery
|
|
14
|
-
validateBody: typeof helpers.validateBody
|
|
14
|
+
validatePathParameters: WithoutThis<typeof helpers.validatePathParameters>
|
|
15
|
+
validateQuery: WithoutThis<typeof helpers.validateQuery>
|
|
16
|
+
validateBody: WithoutThis<typeof helpers.validateBody>
|
|
17
|
+
validators: typeof validators
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
/** 使用者可自行补充 Context 定义 */
|
|
@@ -108,7 +111,7 @@ export class Router {
|
|
|
108
111
|
readonly handle = async (request: Request, response: ResponseUtils) => {
|
|
109
112
|
const pathMatchedRoutes = matchPath(
|
|
110
113
|
this.routes.map(route => route.path),
|
|
111
|
-
request.path
|
|
114
|
+
request.path,
|
|
112
115
|
).map(result => ({ route: this.routes[result.index]!, parameters: result.parameters }))
|
|
113
116
|
if (!pathMatchedRoutes.length) throw new HTTPError(404) // 没有路径匹配的路由
|
|
114
117
|
|
|
@@ -117,7 +120,7 @@ export class Router {
|
|
|
117
120
|
if (!matched) {
|
|
118
121
|
const preflightTargetMethod = getPreflightRequestMethod(request) // 对于 CORS Preflight 请求,此为客户端原本希望请求的 method
|
|
119
122
|
const preflightMatched = pathMatchedRoutes.find(
|
|
120
|
-
match => match.route.method === preflightTargetMethod
|
|
123
|
+
match => match.route.method === preflightTargetMethod,
|
|
121
124
|
)
|
|
122
125
|
if (preflightMatched) {
|
|
123
126
|
const corsRule = preflightMatched.route.cors ?? this.cors
|
|
@@ -133,6 +136,7 @@ export class Router {
|
|
|
133
136
|
request,
|
|
134
137
|
response,
|
|
135
138
|
pathParameters: matched.parameters,
|
|
139
|
+
validatePathParameters: helpers.validatePathParameters.bind(basicContext),
|
|
136
140
|
validateQuery: helpers.validateQuery.bind(basicContext),
|
|
137
141
|
validateBody: helpers.validateBody.bind(basicContext),
|
|
138
142
|
})
|
package/src/swagger/factories.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type {
|
|
|
13
13
|
Reference,
|
|
14
14
|
Parameter,
|
|
15
15
|
RequestBody,
|
|
16
|
-
Components,
|
|
17
16
|
} from './specification.js'
|
|
18
17
|
|
|
19
18
|
type SchemaOrRef = Schema | Reference
|
|
@@ -45,11 +44,14 @@ export function makeOperation(options: OperationOptions = {}): Operation {
|
|
|
45
44
|
const parameters = Array.isArray(query)
|
|
46
45
|
? query
|
|
47
46
|
: query
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
? Object.entries(query).reduce<Parameter[]>((result, [name, options]) => {
|
|
48
|
+
const query = makeQuery({
|
|
49
|
+
name,
|
|
50
|
+
...('schema' in options ? options : { schema: options }),
|
|
51
|
+
})
|
|
52
|
+
return [...result, query]
|
|
53
|
+
}, [])
|
|
54
|
+
: undefined
|
|
53
55
|
const requestBody = body ? ('$ref' in body ? (body as Reference) : makeBody(body)) : undefined
|
|
54
56
|
const responses = response
|
|
55
57
|
? '$ref' in response
|
|
@@ -79,7 +81,7 @@ export function isOperationOptions(value: unknown): value is OperationOptions {
|
|
|
79
81
|
if (typeof value !== 'object' || value === null) return false
|
|
80
82
|
return (
|
|
81
83
|
['category', 'query', 'body', 'response'].find(key =>
|
|
82
|
-
truthy((value as Record<string, unknown>)[key])
|
|
84
|
+
truthy((value as Record<string, unknown>)[key]),
|
|
83
85
|
) !== undefined
|
|
84
86
|
)
|
|
85
87
|
}
|
|
@@ -116,7 +118,7 @@ export function makeHeader(options: ParameterOptions): Parameter {
|
|
|
116
118
|
*/
|
|
117
119
|
export function makeBody(
|
|
118
120
|
input: Record<string, SchemaOrRef> | ObjectOptions | Schema,
|
|
119
|
-
description?: string
|
|
121
|
+
description?: string,
|
|
120
122
|
): RequestBody {
|
|
121
123
|
return {
|
|
122
124
|
description,
|
|
@@ -152,7 +154,7 @@ export function makeResponsesBy(response: Response | Reference): Responses {
|
|
|
152
154
|
/** 生成 Response 定义 */
|
|
153
155
|
export function makeResponse(
|
|
154
156
|
schema: Schema | Record<string, SchemaOrRef>,
|
|
155
|
-
description?: string
|
|
157
|
+
description?: string,
|
|
156
158
|
): Response {
|
|
157
159
|
return {
|
|
158
160
|
description,
|
|
@@ -175,7 +177,7 @@ export function isSchema(value: unknown): value is Schema {
|
|
|
175
177
|
if (typeof value !== 'object' || value === null) return false
|
|
176
178
|
return (
|
|
177
179
|
['type', 'allOf', 'anyOf', 'oneOf', 'not'].find(key =>
|
|
178
|
-
truthy((value as Record<string, unknown>)[key])
|
|
180
|
+
truthy((value as Record<string, unknown>)[key]),
|
|
179
181
|
) !== undefined
|
|
180
182
|
)
|
|
181
183
|
}
|