starlight-server 0.0.1

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/demo/index.d.ts +1 -0
  4. package/dist/demo/index.js +27 -0
  5. package/dist/http/body/form-data.d.ts +35 -0
  6. package/dist/http/body/form-data.js +141 -0
  7. package/dist/http/body/index.d.ts +23 -0
  8. package/dist/http/body/index.js +47 -0
  9. package/dist/http/body/receive.d.ts +7 -0
  10. package/dist/http/body/receive.js +39 -0
  11. package/dist/http/http-status.d.ts +9 -0
  12. package/dist/http/http-status.js +64 -0
  13. package/dist/http/index.d.ts +9 -0
  14. package/dist/http/index.js +9 -0
  15. package/dist/http/mime-types.d.ts +14 -0
  16. package/dist/http/mime-types.js +764 -0
  17. package/dist/http/request.d.ts +25 -0
  18. package/dist/http/request.js +40 -0
  19. package/dist/http/response.d.ts +32 -0
  20. package/dist/http/response.js +66 -0
  21. package/dist/http/server.d.ts +31 -0
  22. package/dist/http/server.js +52 -0
  23. package/dist/http/types.d.ts +26 -0
  24. package/dist/http/types.js +12 -0
  25. package/dist/index.d.ts +3 -0
  26. package/dist/index.js +4 -0
  27. package/dist/logging.d.ts +24 -0
  28. package/dist/logging.js +30 -0
  29. package/dist/router/cors.d.ts +24 -0
  30. package/dist/router/cors.js +35 -0
  31. package/dist/router/index.d.ts +38 -0
  32. package/dist/router/index.js +36 -0
  33. package/dist/router/match.d.ts +23 -0
  34. package/dist/router/match.js +172 -0
  35. package/dist/router/parameters.d.ts +51 -0
  36. package/dist/router/parameters.js +118 -0
  37. package/dist/router/router.d.ts +127 -0
  38. package/dist/router/router.js +97 -0
  39. package/dist/swagger/index.d.ts +1 -0
  40. package/dist/swagger/index.js +168 -0
  41. package/dist/swagger/openapi-spec.d.ts +261 -0
  42. package/dist/swagger/openapi-spec.js +5 -0
  43. package/dist/validators/array.d.ts +9 -0
  44. package/dist/validators/array.js +28 -0
  45. package/dist/validators/boolean.d.ts +4 -0
  46. package/dist/validators/boolean.js +28 -0
  47. package/dist/validators/common.d.ts +23 -0
  48. package/dist/validators/common.js +25 -0
  49. package/dist/validators/index.d.ts +20 -0
  50. package/dist/validators/index.js +38 -0
  51. package/dist/validators/number.d.ts +10 -0
  52. package/dist/validators/number.js +30 -0
  53. package/dist/validators/object.d.ts +13 -0
  54. package/dist/validators/object.js +36 -0
  55. package/dist/validators/string.d.ts +11 -0
  56. package/dist/validators/string.js +29 -0
  57. package/package.json +54 -0
  58. package/src/demo/index.ts +33 -0
  59. package/src/http/body/form-data.ts +164 -0
  60. package/src/http/body/index.ts +59 -0
  61. package/src/http/body/receive.ts +49 -0
  62. package/src/http/http-status.ts +65 -0
  63. package/src/http/index.ts +9 -0
  64. package/src/http/mime-types.ts +765 -0
  65. package/src/http/request.ts +44 -0
  66. package/src/http/response.ts +73 -0
  67. package/src/http/server.ts +67 -0
  68. package/src/http/types.ts +31 -0
  69. package/src/index.ts +4 -0
  70. package/src/logging.ts +57 -0
  71. package/src/router/cors.ts +54 -0
  72. package/src/router/index.ts +38 -0
  73. package/src/router/match.ts +194 -0
  74. package/src/router/parameters.ts +172 -0
  75. package/src/router/router.ts +233 -0
  76. package/src/swagger/index.ts +184 -0
  77. package/src/swagger/openapi-spec.ts +312 -0
  78. package/src/validators/array.ts +33 -0
  79. package/src/validators/boolean.ts +23 -0
  80. package/src/validators/common.ts +46 -0
  81. package/src/validators/index.ts +50 -0
  82. package/src/validators/number.ts +36 -0
  83. package/src/validators/object.ts +41 -0
  84. package/src/validators/string.ts +38 -0
@@ -0,0 +1,168 @@
1
+ // import fsPromise from 'node:fs/promises'
2
+ // import path from 'node:path'
3
+ // import { getAbsoluteFSPath } from 'swagger-ui-dist'
4
+ // import { HTTPError } from '../http/index.js'
5
+ // import {
6
+ // type Router,
7
+ // type PathParameters,
8
+ // type BaseContext,
9
+ // type ResponseDataType,
10
+ // } from '../router/index.js'
11
+ // import { normalizePath } from '../router/match.js'
12
+ // import type { OpenAPI, Schema, PathItem } from './openapi-spec.js'
13
+ export {};
14
+ // export function registerSwaggerRoute(
15
+ // router: Router,
16
+ // endpoint: string = '/swagger',
17
+ // customFields: OpenAPICustomFields = { info: { title: 'API Document', version: '0.0.1' } },
18
+ // ) {
19
+ // router.register('GET', normalizePath(endpoint) + '/*', pageRoute)
20
+ // router.register(
21
+ // 'GET',
22
+ // normalizePath(endpoint) + '/api-swagger.json',
23
+ // apiRoute.bind(null, router, customFields),
24
+ // )
25
+ // }
26
+ // /**
27
+ // * ---------------------------------
28
+ // * swagger 页面路由
29
+ // * ---------------------------------
30
+ // */
31
+ // async function pageRoute({ response }: BaseContext, pathParameters: PathParameters) {
32
+ // const file = (pathParameters['*'] ?? '') || 'index.html'
33
+ // const swaggerDir = getAbsoluteFSPath()
34
+ // const abspath = path.join(swaggerDir, file)
35
+ // if (!cache.has(abspath)) {
36
+ // try {
37
+ // const stat = await fsPromise.stat(abspath)
38
+ // if (!stat.isFile()) throw new HTTPError(404)
39
+ // } catch (e) {
40
+ // throw new HTTPError(404)
41
+ // }
42
+ // const content = await fsPromise.readFile(abspath)
43
+ // const replacemented = replacement(abspath, content)
44
+ // cache.set(abspath, replacemented)
45
+ // }
46
+ // response.text(cache.get(abspath)!)
47
+ // }
48
+ // const cache = new Map<string, Buffer | string>()
49
+ // function replacement(abspath: string, content: Buffer) {
50
+ // if (/swagger-initializer.js/.exec(abspath)) {
51
+ // return content
52
+ // .toString()
53
+ // .replace('https://petstore.swagger.io/v2/swagger.json', './api-swagger.json')
54
+ // // .replace('SwaggerUIBundle({', 'SwaggerUIBundle({\n defaultModelsExpandDepth: 1,\n defaultModelExpandDepth: 1,')
55
+ // }
56
+ // return content
57
+ // }
58
+ // /**
59
+ // * ---------------------------------
60
+ // * swagger API 路由
61
+ // * ---------------------------------
62
+ // */
63
+ // type OpenAPICustomFields = Omit<OpenAPI, 'openapi' | 'paths' | 'components'>
64
+ // function apiRoute(router: Router, customFields: OpenAPICustomFields, { response }: BaseContext) {
65
+ // const swaggerJSON: OpenAPI = {
66
+ // ...customFields,
67
+ // openapi: '3.1.0',
68
+ // paths: makePaths(router),
69
+ // components: {
70
+ // schemas: makeRefs(router),
71
+ // },
72
+ // }
73
+ // response.json(swaggerJSON)
74
+ // }
75
+ // function makeRefs(router: Router) {
76
+ // const schemas: Record<string, Schema> = {}
77
+ // for (const [id, type] of Object.entries(router.responseReferences)) {
78
+ // schemas[id] = responseDataType2Schema(type)
79
+ // }
80
+ // return schemas
81
+ // }
82
+ // function makePaths(router: Router) {
83
+ // const paths: Record<string, PathItem> = {}
84
+ // return paths
85
+ // }
86
+ // function responseDataType2Schema(type: ResponseDataType): Schema {
87
+ // if (type === 'null') return { nullable: true }
88
+ // if (typeof type === 'object' && 'array' in type && type.array.includes('null')) {
89
+ // return {
90
+ // nullable: true,
91
+ // ...responseDataType2Schema(type as ResponseDataType.filter(v => v !== 'null') as ResponseDataType),
92
+ // }
93
+ // }
94
+ // const nullable = type === 'null' || (Array.isArray(type) && type.includes('null'))
95
+ // return {
96
+ // nullable,
97
+ // }
98
+ // }
99
+ // type Obj = { [k: string]: unknown }
100
+ // function string(desc?: string, options?: Obj) {
101
+ // return { type: 'string', description: desc, ...(options ?? {}) }
102
+ // }
103
+ // function number(desc?: string, options?: Obj) {
104
+ // return { type: 'number', description: desc, ...(options ?? {}) }
105
+ // }
106
+ // function boolean(desc?: string, options?: Obj) {
107
+ // return { type: 'boolean', description: desc, ...(options ?? {}) }
108
+ // }
109
+ // function object(properties: unknown, extra?: Obj) {
110
+ // return { type: 'object', properties, ...(extra ?? {}) }
111
+ // }
112
+ // function array(items: unknown, extra?: Obj) {
113
+ // return { type: 'array', items, ...(extra ?? {}) }
114
+ // }
115
+ // function ref(name: string) {
116
+ // return { $ref: '#/components/schemas/' + name }
117
+ // }
118
+ // function jsonSchema(schema: string | Obj) {
119
+ // return {
120
+ // content: {
121
+ // 'application/json': {
122
+ // schema: typeof schema === 'string' ? ref(schema) : schema,
123
+ // },
124
+ // },
125
+ // }
126
+ // }
127
+ // function route(params: {
128
+ // category: string
129
+ // describe: string
130
+ // path: string
131
+ // body?: string | Obj
132
+ // response?: string | Obj
133
+ // }) {
134
+ // return {
135
+ // [params.path]: {
136
+ // post: {
137
+ // tags: [params.category],
138
+ // summary: params.describe,
139
+ // operationId: params.path,
140
+ // requestBody: params.body !== undefined ? jsonSchema(params.body) : undefined,
141
+ // responses: {
142
+ // default: {
143
+ // description: 'OK',
144
+ // ...jsonSchema(params.response ?? object({})),
145
+ // },
146
+ // },
147
+ // },
148
+ // },
149
+ // }
150
+ // }
151
+ // function response(schema: unknown) {
152
+ // return {
153
+ // type: 'object',
154
+ // properties: {
155
+ // success: boolean(undefined, { enum: [true] }),
156
+ // data: schema,
157
+ // },
158
+ // }
159
+ // }
160
+ // function pageResp(itemSchema: unknown) {
161
+ // return response({
162
+ // type: 'object',
163
+ // properties: {
164
+ // total: number(),
165
+ // list: array(itemSchema),
166
+ // },
167
+ // })
168
+ // }
@@ -0,0 +1,261 @@
1
+ /**
2
+ * OpenAPI Specification
3
+ * https://swagger.io/specification/
4
+ */
5
+ export interface OpenAPI {
6
+ openapi: '3.1.0';
7
+ info: Info;
8
+ servers?: Server[];
9
+ paths: Paths;
10
+ components?: Components;
11
+ security?: SecurityRequirement[];
12
+ tags?: Tag[];
13
+ externalDocs?: ExternalDocumentation;
14
+ }
15
+ export interface Info extends Extendable {
16
+ title: string;
17
+ summary?: string;
18
+ description?: string;
19
+ termsOfService?: string;
20
+ contact?: Contact;
21
+ license?: License;
22
+ version: string;
23
+ }
24
+ export interface Contact extends Extendable {
25
+ name?: string;
26
+ url?: string;
27
+ email?: string;
28
+ }
29
+ export interface License extends Extendable {
30
+ name: string;
31
+ url?: string;
32
+ }
33
+ export interface Server extends Extendable {
34
+ url: string;
35
+ description?: CommonMark;
36
+ variables?: Record<string, ServerVariable>;
37
+ }
38
+ export interface ServerVariable extends Extendable {
39
+ enum?: [string] & string[];
40
+ default: string;
41
+ description: CommonMark;
42
+ }
43
+ export interface Components extends Extendable {
44
+ schemas?: Record<string, Schema>;
45
+ responses?: Record<string, Response | Reference>;
46
+ parameters?: Record<string, Parameter | Reference>;
47
+ examples?: Record<string, Example | Reference>;
48
+ requestBodies?: Record<string, RequestBody | Reference>;
49
+ headers?: Record<string, Header | Reference>;
50
+ securitySchemes?: Record<string, SecurityScheme | Reference>;
51
+ links?: Record<string, Link | Reference>;
52
+ callbacks?: Record<string, Callback | Reference>;
53
+ pathItems?: Record<string, PathItem | Reference>;
54
+ }
55
+ export interface Paths extends Extendable {
56
+ [path: string]: PathItem;
57
+ }
58
+ export interface PathItem extends Extendable {
59
+ $ref?: string;
60
+ summary?: string;
61
+ description?: CommonMark;
62
+ get?: Operation;
63
+ put?: Operation;
64
+ post?: Operation;
65
+ delete?: Operation;
66
+ options?: Operation;
67
+ head?: Operation;
68
+ patch?: Operation;
69
+ trace?: Operation;
70
+ servers?: Server[];
71
+ parameters?: (Parameter | Reference)[];
72
+ }
73
+ export interface Operation {
74
+ tags?: string[];
75
+ summary?: string;
76
+ description?: CommonMark;
77
+ externalDocs?: ExternalDocumentation;
78
+ operationId?: string;
79
+ parameters?: (Parameter | Reference)[];
80
+ requestBody?: RequestBody | Reference;
81
+ responses: Responses;
82
+ callbacks?: Record<string, Callback | Reference>;
83
+ deprecated?: boolean;
84
+ }
85
+ export interface ExternalDocumentation {
86
+ description?: CommonMark;
87
+ url: string;
88
+ }
89
+ export interface Parameter extends Extendable {
90
+ name: string;
91
+ in: ParameterLocation;
92
+ description?: CommonMark;
93
+ required?: boolean;
94
+ deprecated?: boolean;
95
+ allowEmptyValue?: boolean;
96
+ style?: ParameterStyle;
97
+ explode?: boolean;
98
+ allowReserved?: boolean;
99
+ schema?: Schema | Reference;
100
+ example?: unknown;
101
+ examples?: Record<string, Example | Reference>;
102
+ content?: Record<string, MediaType>;
103
+ }
104
+ export type ParameterLocation = 'query' | 'header' | 'path' | 'cookie';
105
+ export type ParameterStyle = string;
106
+ export interface RequestBody extends Extendable {
107
+ description?: CommonMark;
108
+ content: Record<string, MediaType>;
109
+ required?: boolean;
110
+ }
111
+ export interface MediaType extends Extendable {
112
+ schema?: Schema | Reference;
113
+ example?: unknown;
114
+ examples?: Record<string, Example | Reference>;
115
+ encoding?: Record<string, Encoding>;
116
+ }
117
+ export interface Encoding extends Extendable {
118
+ contentType?: string;
119
+ headers?: Record<string, Header | Reference>;
120
+ style?: ParameterStyle;
121
+ explode?: boolean;
122
+ allowReserved?: boolean;
123
+ }
124
+ export interface Responses extends Extendable {
125
+ default: Response | Reference;
126
+ [HTTPStatus: string]: Response | Reference;
127
+ }
128
+ export interface Response extends Extendable {
129
+ descriptoin: CommonMark;
130
+ headers?: Record<string, Header | Reference>;
131
+ content?: Record<string, MediaType>;
132
+ links?: Record<string, Link | Reference>;
133
+ }
134
+ export interface Callback extends Extendable {
135
+ [expression: Expression]: PathItem;
136
+ }
137
+ export interface Example extends Extendable {
138
+ summary?: string;
139
+ description?: CommonMark;
140
+ value?: unknown;
141
+ externalValue?: string;
142
+ }
143
+ export interface Link extends Extendable {
144
+ operationRef?: string;
145
+ operationId?: string;
146
+ parameters?: Record<string, unknown>;
147
+ requestBody?: unknown;
148
+ description?: string;
149
+ server?: Server;
150
+ }
151
+ export type Header = Omit<Parameter, 'name' | 'in'>;
152
+ export interface Tag extends Extendable {
153
+ name: string;
154
+ description?: CommonMark;
155
+ externalDocs?: ExternalDocumentation;
156
+ }
157
+ export interface Reference {
158
+ $ref: string;
159
+ summary: string;
160
+ description: string;
161
+ }
162
+ export interface Schema extends Extendable {
163
+ nullable?: boolean;
164
+ discriminator?: Discriminator;
165
+ readonly?: boolean;
166
+ writeOnly?: boolean;
167
+ xml?: XML;
168
+ externalDocs?: ExternalDocumentation;
169
+ example?: unknown;
170
+ deprecated?: boolean;
171
+ multipleOf?: number;
172
+ maximum?: number;
173
+ exclusiveMaximum?: boolean;
174
+ minimum?: number;
175
+ exclusiveMinimum?: boolean;
176
+ maxLength?: number;
177
+ minLength?: number;
178
+ pattern?: string;
179
+ items?: Schema;
180
+ maxItems?: number;
181
+ minItems?: number;
182
+ uniqueItems?: boolean;
183
+ maxProperties?: number;
184
+ minProperties?: string;
185
+ required?: [string] & string[];
186
+ properties?: Record<string, Schema>;
187
+ additionalProperties?: boolean | Schema;
188
+ enum?: unknown[];
189
+ type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';
190
+ allOf?: Schema[];
191
+ anyOf?: Schema[];
192
+ oneOf?: Schema[];
193
+ not?: Schema;
194
+ title?: string;
195
+ description?: CommonMark;
196
+ default?: unknown;
197
+ format?: string;
198
+ }
199
+ export interface Discriminator {
200
+ propertyName?: string;
201
+ mapping?: Record<string, string>;
202
+ }
203
+ export interface XML extends Extendable {
204
+ name?: string;
205
+ namespace?: string;
206
+ prefix?: string;
207
+ attribute?: boolean;
208
+ wrapped?: boolean;
209
+ }
210
+ export interface SecurityScheme extends Extendable {
211
+ type: string;
212
+ description?: string;
213
+ name: string;
214
+ in: string;
215
+ schema: string;
216
+ bearerFormat?: string;
217
+ flows: OAuthFlows;
218
+ openIdConnectUrl: string;
219
+ }
220
+ export interface OAuthFlows extends Extendable {
221
+ implicit?: OAuthFlow;
222
+ password?: OAuthFlow;
223
+ clientCredentials?: OAuthFlow;
224
+ authorizationCode?: OAuthFlow;
225
+ }
226
+ export interface OAuthFlow extends Extendable {
227
+ authorizationUrl: string;
228
+ tokenUrl: string;
229
+ refreshUrl?: string;
230
+ scopes: Record<string, string>;
231
+ }
232
+ export interface SecurityRequirement {
233
+ [name: string]: string;
234
+ }
235
+ export type Extendable = {};
236
+ export type CommonMark = string;
237
+ export type Expression = string;
238
+ export interface TypedSchema<T> extends Schema {
239
+ allOf?: TypedSchema<T>[];
240
+ anyOf?: TypedSchema<T>[];
241
+ oneOf?: TypedSchema<T>[];
242
+ not?: TypedSchema<T>;
243
+ example?: T;
244
+ enum?: T[];
245
+ default?: T;
246
+ }
247
+ export interface StringSchema extends TypedSchema<string> {
248
+ type: 'string';
249
+ }
250
+ export interface NumberSchema extends TypedSchema<number> {
251
+ type: 'number';
252
+ }
253
+ export interface BooleanSchema extends TypedSchema<boolean> {
254
+ type: 'boolean';
255
+ }
256
+ export interface ObjectSchema extends TypedSchema<Record<string, unknown>> {
257
+ type: 'object';
258
+ }
259
+ export interface ArraySchema extends TypedSchema<unknown[]> {
260
+ type: 'array';
261
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * OpenAPI Specification
3
+ * https://swagger.io/specification/
4
+ */
5
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Validator } from './common.js';
2
+ export interface ArrayOptions {
3
+ item: Validator;
4
+ min?: number;
5
+ max?: number;
6
+ }
7
+ export declare class ArrayValidator extends Validator<ArrayOptions> {
8
+ validate(fieldName: string, value: unknown): import("@anjianshi/utils").Success<unknown> | import("@anjianshi/utils").Failed<string>;
9
+ }
@@ -0,0 +1,28 @@
1
+ import { success, failed } from '@anjianshi/utils';
2
+ import { Validator } from './common.js';
3
+ export class ArrayValidator extends Validator {
4
+ validate(fieldName, value) {
5
+ const superResult = super.validate(fieldName, value);
6
+ if (!superResult.success)
7
+ return superResult;
8
+ value = superResult.data;
9
+ if (value === null || value === undefined)
10
+ return superResult;
11
+ const opt = this.options;
12
+ if (!Array.isArray(value))
13
+ return failed(`${fieldName} should be an array`);
14
+ if (typeof opt.min === 'number' && value.length < opt.min)
15
+ return failed(`array ${fieldName}'s length should >= ${opt.min}`);
16
+ if (typeof opt.max === 'number' && value.length > opt.max)
17
+ return failed(`array ${fieldName}'s length should <= ${opt.max}`);
18
+ const formatted = [];
19
+ for (let i = 0; i < value.length; i++) {
20
+ const itemResult = opt.item.validate(`${fieldName}[${i}]`, value[i]);
21
+ if (itemResult.success)
22
+ formatted.push(itemResult.data);
23
+ else
24
+ return itemResult;
25
+ }
26
+ return success(formatted);
27
+ }
28
+ }
@@ -0,0 +1,4 @@
1
+ import { Validator } from './common.js';
2
+ export declare class BooleanValidator extends Validator {
3
+ validate(fieldName: string, value: unknown): import("@anjianshi/utils").Success<unknown> | import("@anjianshi/utils").Failed<string>;
4
+ }
@@ -0,0 +1,28 @@
1
+ import { success, failed } from '@anjianshi/utils';
2
+ import { Validator } from './common.js';
3
+ export class BooleanValidator extends Validator {
4
+ validate(fieldName, value) {
5
+ const superResult = super.validate(fieldName, value);
6
+ if (!superResult.success)
7
+ return superResult;
8
+ value = superResult.data;
9
+ if (value === null || value === undefined)
10
+ return superResult;
11
+ if (typeof value === 'string') {
12
+ const str = value.trim().toLocaleLowerCase();
13
+ if (['1', 'true', 'on', 'yes'].includes(str))
14
+ value = true;
15
+ else if (['0', 'false', 'off', 'no'].includes(str))
16
+ value = false;
17
+ }
18
+ else if (typeof value === 'number') {
19
+ if (value === 1)
20
+ value = true;
21
+ else if (value === 0)
22
+ value = false;
23
+ }
24
+ if (typeof value !== 'boolean')
25
+ return failed(`${fieldName} must be true or false`);
26
+ return success(value);
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import { type MaySuccess } from '@anjianshi/utils';
2
+ export interface CommonOptions {
3
+ /**
4
+ * allow `null`
5
+ * @default false
6
+ */
7
+ null: boolean;
8
+ /**
9
+ * allow `undefined`
10
+ * @default false
11
+ */
12
+ void: boolean;
13
+ /**
14
+ * 默认值,原值为 undefined 时生效(原值为 null 不会生效),指定后 void 选项将失去作用。
15
+ * default value,used when original value is `undefined`(not for null), and make `void` option no effect.
16
+ */
17
+ defaults: unknown;
18
+ }
19
+ export declare class Validator<Opt = unknown> {
20
+ readonly options: Opt & CommonOptions;
21
+ constructor(options: Opt & Partial<CommonOptions>);
22
+ validate(fieldName: string, value: unknown): MaySuccess<unknown>;
23
+ }
@@ -0,0 +1,25 @@
1
+ import { success, failed } from '@anjianshi/utils';
2
+ export class Validator {
3
+ options;
4
+ constructor(options) {
5
+ this.options = {
6
+ null: false,
7
+ void: false,
8
+ defaults: undefined,
9
+ ...options,
10
+ };
11
+ }
12
+ validate(fieldName, value) {
13
+ if (typeof value === 'undefined') {
14
+ if (typeof this.options.defaults !== 'undefined') {
15
+ value = this.options.defaults;
16
+ }
17
+ else if (!this.options.void) {
18
+ return failed(`${fieldName} must have a value`);
19
+ }
20
+ }
21
+ if (value === null && !this.options.null)
22
+ return failed(`${fieldName} cannot be null`);
23
+ return success(value);
24
+ }
25
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 实现数据验证、格式化
3
+ * Implement data validation and formatting
4
+ */
5
+ import { ArrayValidator } from './array.js';
6
+ import { BooleanValidator } from './boolean.js';
7
+ import { Validator, type CommonOptions } from './common.js';
8
+ import { NumberValidator } from './number.js';
9
+ import { ObjectValidator } from './object.js';
10
+ import { StringValidator } from './string.js';
11
+ /**
12
+ * 仅检查空值,不检查具体格式
13
+ * Check only for empty values, not for specific formatting
14
+ */
15
+ export declare function any(options?: Partial<CommonOptions>): Validator<unknown>;
16
+ export declare function string(...args: ConstructorParameters<typeof StringValidator>): StringValidator;
17
+ export declare function number(...args: ConstructorParameters<typeof NumberValidator>): NumberValidator;
18
+ export declare function boolean(options?: Partial<CommonOptions>): BooleanValidator;
19
+ export declare function array(itemValidator: Validator, options?: Omit<ConstructorParameters<typeof ArrayValidator>[0], 'item'>): ArrayValidator;
20
+ export declare function object(structOrValue: Record<string, Validator> | Validator, options?: Partial<CommonOptions>): ObjectValidator;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 实现数据验证、格式化
3
+ * Implement data validation and formatting
4
+ */
5
+ import { ArrayValidator } from './array.js';
6
+ import { BooleanValidator } from './boolean.js';
7
+ import { Validator } from './common.js';
8
+ import { NumberValidator } from './number.js';
9
+ import { ObjectValidator } from './object.js';
10
+ import { StringValidator } from './string.js';
11
+ /**
12
+ * 仅检查空值,不检查具体格式
13
+ * Check only for empty values, not for specific formatting
14
+ */
15
+ export function any(options) {
16
+ return new Validator(options ?? {});
17
+ }
18
+ export function string(...args) {
19
+ return new StringValidator(...args);
20
+ }
21
+ export function number(...args) {
22
+ return new NumberValidator(...args);
23
+ }
24
+ export function boolean(options) {
25
+ return new BooleanValidator(options ?? {});
26
+ }
27
+ export function array(itemValidator, options) {
28
+ return new ArrayValidator({
29
+ item: itemValidator,
30
+ ...(options ?? {}),
31
+ });
32
+ }
33
+ export function object(structOrValue, options) {
34
+ return new ObjectValidator({
35
+ ...(structOrValue instanceof Validator ? { value: structOrValue } : { struct: structOrValue }),
36
+ ...options,
37
+ });
38
+ }
@@ -0,0 +1,10 @@
1
+ import { Validator, type CommonOptions } from './common.js';
2
+ export interface NumberOptions {
3
+ min?: number;
4
+ max?: number;
5
+ float: boolean;
6
+ }
7
+ export declare class NumberValidator extends Validator<NumberOptions> {
8
+ constructor(options?: Partial<NumberOptions> & Partial<CommonOptions>);
9
+ validate(fieldName: string, value: unknown): import("@anjianshi/utils").Success<unknown> | import("@anjianshi/utils").Failed<string>;
10
+ }
@@ -0,0 +1,30 @@
1
+ import { success, failed } from '@anjianshi/utils';
2
+ import { Validator } from './common.js';
3
+ export class NumberValidator extends Validator {
4
+ constructor(options) {
5
+ super({
6
+ float: false,
7
+ ...(options ?? {}),
8
+ });
9
+ }
10
+ validate(fieldName, value) {
11
+ const superResult = super.validate(fieldName, value);
12
+ if (!superResult.success)
13
+ return superResult;
14
+ value = superResult.data;
15
+ if (value === null || value === undefined)
16
+ return superResult;
17
+ const opt = this.options;
18
+ if (typeof value === 'string')
19
+ value = parseFloat(value);
20
+ if (typeof value !== 'number' || !isFinite(value))
21
+ return failed(`${fieldName} must be a valid number`);
22
+ if (!opt.float && value % 1 !== 0)
23
+ return failed(`${fieldName} must be a integer`);
24
+ if (typeof opt.min === 'number' && value < opt.min)
25
+ return failed(`${fieldName} must >= ${opt.min}`);
26
+ if (typeof opt.max === 'number' && value > opt.max)
27
+ return failed(`${fieldName} must <= ${opt.max}`);
28
+ return success(value);
29
+ }
30
+ }
@@ -0,0 +1,13 @@
1
+ import { Validator } from './common.js';
2
+ /**
3
+ * struct 用于有明确键值对结构的对象;value 用于有任意 key 的对象
4
+ * use `struct` is used for objects with an explicit key-value structure; `value` is used for objects with arbitrary keys.
5
+ */
6
+ export type ObjectOptions = {
7
+ struct: Record<string, Validator>;
8
+ } | {
9
+ value: Validator;
10
+ };
11
+ export declare class ObjectValidator extends Validator<ObjectOptions> {
12
+ validate(fieldName: string, value: unknown): import("@anjianshi/utils").Success<unknown> | import("@anjianshi/utils").Failed<string>;
13
+ }