Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
K
Koishi Utils Schemagen
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
3rdeye
Koishi Utils Schemagen
Commits
368f4ff1
Commit
368f4ff1
authored
Oct 17, 2021
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
auto type infer
parent
d92737fe
Pipeline
#6286
passed with stages
in 1 minute and 24 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
100 additions
and
21 deletions
+100
-21
README.md
README.md
+13
-5
index.ts
index.ts
+3
-0
package.json
package.json
+3
-3
src/decorators.ts
src/decorators.ts
+36
-1
src/def.ts
src/def.ts
+1
-0
src/index.ts
src/index.ts
+0
-3
src/methods.ts
src/methods.ts
+2
-0
test/test-classtype.ts
test/test-classtype.ts
+33
-0
test/test-transform.ts
test/test-transform.ts
+9
-9
No files found.
README.md
View file @
368f4ff1
#
Koishi Utils S
chemagen
#
koishi-utils-s
chemagen
在 Koishi.js 中,使用类装饰器定义 Schema。
在 Koishi.js 中,使用类装饰器定义 Schema。
...
@@ -23,14 +23,18 @@ export class Config {
...
@@ -23,14 +23,18 @@ export class Config {
@
DefineSchema
({
type
:
'
number
'
,
required
:
true
})
@
DefineSchema
({
type
:
'
number
'
,
required
:
true
})
foo
:
number
;
foo
:
number
;
// 非数组类型会尝试自动推断类型
@
DefineSchema
()
fooAutomated
:
number
;
@
DefineSchema
({
type
:
'
string
'
,
default
:
'
shigma
'
})
@
DefineSchema
({
type
:
'
string
'
,
default
:
'
shigma
'
})
bar
:
string
;
bar
:
string
;
@
DefineSchema
({
type
:
'
boolean
'
,
default
:
true
,
hidden
:
true
})
@
DefineSchema
({
type
:
'
boolean
'
,
default
:
true
,
hidden
:
true
})
baz
:
boolean
;
baz
:
boolean
;
// 数组
// 数组
,系统会自动推断该类型为数组,但是此时 type 不可省略
@
DefineSchema
({
type
:
'
string
'
,
array
:
true
,
default
:
[
'
foo
'
,
'
bar
'
]
})
@
DefineSchema
({
type
:
'
string
'
,
default
:
[
'
foo
'
,
'
bar
'
]
})
ant
:
string
[];
ant
:
string
[];
// 也可以用定义好的 Schema
// 也可以用定义好的 Schema
...
@@ -49,7 +53,7 @@ export class Config {
...
@@ -49,7 +53,7 @@ export class Config {
@
ObjectSchema
(
B
)
@
ObjectSchema
(
B
)
anotherB
:
B
;
anotherB
:
B
;
// 字典
// 字典
,type 也不可省略
@
DefineSchema
({
type
:
B
,
dict
:
true
})
@
DefineSchema
({
type
:
B
,
dict
:
true
})
biDict
:
Record
<
string
,
B
>
;
biDict
:
Record
<
string
,
B
>
;
...
@@ -66,4 +70,8 @@ export class Config {
...
@@ -66,4 +70,8 @@ export class Config {
const
schema
=
schemaFromClass
(
Config
);
const
schema
=
schemaFromClass
(
Config
);
// 直接获取 Config 对象并实例化,可以代替 Schema.validate 使用。对于嵌套类会进行循环实例化。
// 直接获取 Config 对象并实例化,可以代替 Schema.validate 使用。对于嵌套类会进行循环实例化。
const
config
=
schemaTransform
(
Config
,
someObject
);
const
config
=
schemaTransform
(
Config
,
someObject
);
```
```
\ No newline at end of file
### 类型推断
koishi-utils-schemagen 会尝试自动从类定义推断 Schema 类型,但是无法自动推断数组和字典类型。
index.ts
0 → 100644
View file @
368f4ff1
export
*
from
'
./src/def
'
;
export
*
from
'
./src/decorators
'
;
export
*
from
'
./src/methods
'
;
package.json
View file @
368f4ff1
{
{
"name"
:
"koishi-utils-schemagen"
,
"name"
:
"koishi-utils-schemagen"
,
"version"
:
"1.
0.7
"
,
"version"
:
"1.
1.0
"
,
"description"
:
"在 Koishi.js 中,使用类装饰器定义 Schema"
,
"description"
:
"在 Koishi.js 中,使用类装饰器定义 Schema"
,
"main"
:
"dist/
src/
index.js"
,
"main"
:
"dist/index.js"
,
"typings"
:
"dist/
src/
index.d.ts"
,
"typings"
:
"dist/index.d.ts"
,
"scripts"
:
{
"scripts"
:
{
"lint"
:
"eslint --fix ."
,
"lint"
:
"eslint --fix ."
,
"build"
:
"tsc"
"build"
:
"tsc"
...
...
src/decorators.ts
View file @
368f4ff1
...
@@ -20,13 +20,48 @@ function transformDict<T>(cl: ClassConstructor<T>, val: any, array: boolean) {
...
@@ -20,13 +20,48 @@ function transformDict<T>(cl: ClassConstructor<T>, val: any, array: boolean) {
}
}
}
}
export
function
DefineSchema
(
options
:
SchemaOptions
):
PropertyDecorator
{
function
getStringFromNativeType
(
nativeType
:
any
)
{
if
(
!
nativeType
)
{
return
;
}
const
nativeTypeString
=
nativeType
.
toString
()
as
string
;
if
(
!
nativeTypeString
)
{
return
;
}
if
(
nativeTypeString
.
startsWith
(
'
class
'
))
{
return
'
class
'
;
}
if
(
!
nativeTypeString
.
startsWith
(
'
function
'
))
{
return
;
}
const
firstLeftBracketPos
=
nativeTypeString
.
indexOf
(
'
()
'
);
if
(
firstLeftBracketPos
===
-
1
)
{
return
;
}
const
typeString
=
nativeTypeString
.
slice
(
9
,
firstLeftBracketPos
);
return
typeString
.
toLowerCase
();
}
export
function
DefineSchema
(
options
:
SchemaOptions
=
{}):
PropertyDecorator
{
return
(
obj
,
key
)
=>
{
return
(
obj
,
key
)
=>
{
const
objClass
=
obj
.
constructor
;
const
objClass
=
obj
.
constructor
;
const
keys
:
string
[]
=
const
keys
:
string
[]
=
Reflect
.
getMetadata
(
SchemaKeysMetaKey
,
objClass
)
||
[];
Reflect
.
getMetadata
(
SchemaKeysMetaKey
,
objClass
)
||
[];
keys
.
push
(
key
.
toString
());
keys
.
push
(
key
.
toString
());
Reflect
.
defineMetadata
(
SchemaKeysMetaKey
,
keys
,
objClass
);
Reflect
.
defineMetadata
(
SchemaKeysMetaKey
,
keys
,
objClass
);
const
nativeType
=
Reflect
.
getMetadata
(
'
design:type
'
,
obj
,
key
);
const
nativeTypeString
=
getStringFromNativeType
(
nativeType
);
if
(
!
options
.
type
)
{
if
(
nativeTypeString
&&
nativeTypeString
!==
'
array
'
)
{
options
.
type
=
nativeTypeString
===
'
class
'
?
nativeType
:
nativeTypeString
;
}
else
{
options
.
type
=
'
any
'
;
}
}
if
(
nativeTypeString
===
'
array
'
)
{
options
.
array
=
true
;
}
Reflect
.
defineMetadata
(
SchemaMetaKey
,
options
,
objClass
,
key
);
Reflect
.
defineMetadata
(
SchemaMetaKey
,
options
,
objClass
,
key
);
if
(
options
.
type
&&
typeof
options
.
type
!==
'
string
'
)
{
if
(
options
.
type
&&
typeof
options
.
type
!==
'
string
'
)
{
const
cl
=
options
.
type
as
ClassConstructor
<
any
>
;
const
cl
=
options
.
type
as
ClassConstructor
<
any
>
;
...
...
src/def.ts
View file @
368f4ff1
...
@@ -5,6 +5,7 @@ export type SchemaType =
...
@@ -5,6 +5,7 @@ export type SchemaType =
|
'
string
'
|
'
string
'
|
'
number
'
|
'
number
'
|
'
boolean
'
|
'
boolean
'
|
'
object
'
|
'
any
'
|
'
any
'
|
'
never
'
|
'
never
'
|
ClassConstructor
<
any
>
;
|
ClassConstructor
<
any
>
;
...
...
src/index.ts
deleted
100644 → 0
View file @
d92737fe
export
*
from
'
./def
'
;
export
*
from
'
./decorators
'
;
export
*
from
'
./methods
'
;
src/methods.ts
View file @
368f4ff1
...
@@ -27,6 +27,8 @@ function getBasePropertySchemaFromOptions(options: SchemaOptions) {
...
@@ -27,6 +27,8 @@ function getBasePropertySchemaFromOptions(options: SchemaOptions) {
return
Schema
.
number
();
return
Schema
.
number
();
case
'
boolean
'
:
case
'
boolean
'
:
return
Schema
.
boolean
();
return
Schema
.
boolean
();
case
'
object
'
:
return
Schema
.
object
({},
true
);
default
:
default
:
return
Schema
.
any
();
return
Schema
.
any
();
}
}
...
...
test/test-classtype.ts
0 → 100644
View file @
368f4ff1
import
'
reflect-metadata
'
;
function
LogType
():
PropertyDecorator
{
return
(
target
,
key
)
=>
{
const
t
=
Reflect
.
getMetadata
(
'
design:type
'
,
target
,
key
);
console
.
log
(
key
,
t
,
typeof
t
,
t
.
toString
());
};
}
class
B
<
T
>
{
foo
:
T
;
}
class
A
{
@
LogType
()
foo
:
string
;
@
LogType
()
bar
:
number
;
@
LogType
()
a
:
Date
;
@
LogType
()
m
:
Map
<
string
,
any
>
;
@
LogType
()
s
:
Set
<
any
>
;
@
LogType
()
b
:
B
<
string
>
;
@
LogType
()
c
:
boolean
;
@
LogType
()
d
:
B
<
any
>
[];
@
LogType
()
aaa
:
any
;
}
test/test-transform.ts
View file @
368f4ff1
...
@@ -3,17 +3,17 @@ import {
...
@@ -3,17 +3,17 @@ import {
SchemaConf
,
SchemaConf
,
schemaFromClass
,
schemaFromClass
,
schemaTransform
,
schemaTransform
,
}
from
'
..
/src
'
;
}
from
'
..
'
;
import
{
Schema
}
from
'
koishi
'
;
import
{
Schema
}
from
'
koishi
'
;
@
SchemaConf
({
@
SchemaConf
({
desc
:
'
my desc
'
,
desc
:
'
my desc
'
,
})
})
class
B
{
class
B
{
@
DefineSchema
({
type
:
'
number
'
,
default
:
2
,
desc
:
'
aaaaa
'
})
@
DefineSchema
({
default
:
2
,
desc
:
'
aaaaa
'
})
aa
:
number
;
aa
:
number
;
@
DefineSchema
({
type
:
'
boolean
'
,
default
:
true
})
@
DefineSchema
({
default
:
true
})
bb
:
boolean
;
bb
:
boolean
;
}
}
...
@@ -21,22 +21,22 @@ class B {
...
@@ -21,22 +21,22 @@ class B {
desc
:
'
my base desc
'
,
desc
:
'
my base desc
'
,
})
})
class
A
{
class
A
{
@
DefineSchema
({
type
:
'
number
'
,
required
:
true
})
@
DefineSchema
({
required
:
true
})
a
:
number
;
a
:
number
;
@
DefineSchema
({
type
:
'
string
'
,
default
:
'
shigma
'
})
@
DefineSchema
({
default
:
'
shigma
'
})
b
:
string
;
b
:
string
;
@
DefineSchema
({
type
:
'
string
'
,
array
:
true
,
default
:
[
'
foo
'
,
'
bar
'
]
})
@
DefineSchema
({
type
:
'
string
'
,
default
:
[
'
foo
'
,
'
bar
'
]
})
c
:
string
[];
c
:
string
[];
@
DefineSchema
(
{
type
:
B
}
)
@
DefineSchema
()
bi
:
B
;
bi
:
B
;
@
DefineSchema
({
type
:
B
,
array
:
true
})
@
DefineSchema
({
type
:
B
})
biArr
:
B
[];
biArr
:
B
[];
@
DefineSchema
({
type
:
B
,
dict
:
true
,
array
:
true
})
@
DefineSchema
({
type
:
B
,
dict
:
true
})
biDict
:
Record
<
string
,
B
>
[];
biDict
:
Record
<
string
,
B
>
[];
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment