@feathersjs/schema 5.0.0-pre.21 → 5.0.0-pre.24
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/CHANGELOG.md +44 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/resolve.d.ts +14 -7
- package/lib/hooks/resolve.js +37 -25
- package/lib/hooks/resolve.js.map +1 -1
- package/lib/hooks/validate.js +3 -3
- package/lib/hooks/validate.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/query.d.ts +10 -10
- package/lib/query.js +32 -26
- package/lib/query.js.map +1 -1
- package/lib/resolver.js +4 -8
- package/lib/resolver.js.map +1 -1
- package/lib/schema.js +1 -1
- package/lib/schema.js.map +1 -1
- package/package.json +10 -9
- package/src/hooks/index.ts +2 -2
- package/src/hooks/resolve.ts +102 -81
- package/src/hooks/validate.ts +18 -18
- package/src/index.ts +8 -8
- package/src/query.ts +73 -64
- package/src/resolver.ts +61 -59
- package/src/schema.ts +27 -27
package/src/hooks/resolve.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
2
|
-
import { compose } from '@feathersjs/hooks'
|
|
3
|
-
import { Resolver, ResolverStatus } from '../resolver'
|
|
1
|
+
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
2
|
+
import { compose } from '@feathersjs/hooks'
|
|
3
|
+
import { Resolver, ResolverStatus } from '../resolver'
|
|
4
4
|
|
|
5
|
-
const getContext = <H extends HookContext>
|
|
5
|
+
const getContext = <H extends HookContext>(context: H) => {
|
|
6
6
|
return {
|
|
7
7
|
...context,
|
|
8
8
|
params: {
|
|
@@ -12,35 +12,56 @@ const getContext = <H extends HookContext> (context: H) => {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const getData = <H extends HookContext>
|
|
16
|
-
const isPaginated = context.method === 'find' && context.result.data
|
|
17
|
-
const data = isPaginated ? context.result.data : context.result
|
|
15
|
+
const getData = <H extends HookContext>(context: H) => {
|
|
16
|
+
const isPaginated = context.method === 'find' && context.result.data
|
|
17
|
+
const data = isPaginated ? context.result.data : context.result
|
|
18
18
|
|
|
19
|
-
return { isPaginated, data }
|
|
19
|
+
return { isPaginated, data }
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const runResolvers = async <T, H extends HookContext>
|
|
22
|
+
const runResolvers = async <T, H extends HookContext>(
|
|
23
23
|
resolvers: Resolver<T, H>[],
|
|
24
24
|
data: any,
|
|
25
25
|
ctx: H,
|
|
26
26
|
status?: Partial<ResolverStatus<T, H>>
|
|
27
27
|
) => {
|
|
28
|
-
let current: any = data
|
|
28
|
+
let current: any = data
|
|
29
29
|
|
|
30
30
|
for (const resolver of resolvers) {
|
|
31
|
-
|
|
31
|
+
if (resolver && typeof resolver.resolve === 'function') {
|
|
32
|
+
current = await resolver.resolve(current, ctx, status)
|
|
33
|
+
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
return current as T
|
|
36
|
+
return current as T
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ResolverSetting<H extends HookContext> = Resolver<any, H> | Resolver<any, H>[]
|
|
40
|
+
|
|
41
|
+
export type DataResolvers<H extends HookContext> = {
|
|
42
|
+
create: Resolver<any, H>
|
|
43
|
+
patch: Resolver<any, H>
|
|
44
|
+
update: Resolver<any, H>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type ResolveAllSettings<H extends HookContext> = {
|
|
48
|
+
data?: DataResolvers<H>
|
|
49
|
+
query?: Resolver<any, H>
|
|
50
|
+
result?: Resolver<any, H>
|
|
51
|
+
dispatch?: Resolver<any, H>
|
|
35
52
|
}
|
|
36
53
|
|
|
37
|
-
export const DISPATCH = Symbol('@feathersjs/schema/dispatch')
|
|
54
|
+
export const DISPATCH = Symbol('@feathersjs/schema/dispatch')
|
|
38
55
|
|
|
39
|
-
export const
|
|
56
|
+
export const getDispatch = (value: any) =>
|
|
57
|
+
typeof value === 'object' && value !== null && value[DISPATCH] !== undefined ? value[DISPATCH] : value
|
|
58
|
+
|
|
59
|
+
export const resolveQuery =
|
|
60
|
+
<T, H extends HookContext>(...resolvers: Resolver<T, H>[]) =>
|
|
40
61
|
async (context: H, next?: NextFunction) => {
|
|
41
|
-
const ctx = getContext(context)
|
|
42
|
-
const data = context?.params?.query || {}
|
|
43
|
-
const query = await runResolvers(resolvers, data, ctx)
|
|
62
|
+
const ctx = getContext(context)
|
|
63
|
+
const data = context?.params?.query || {}
|
|
64
|
+
const query = await runResolvers(resolvers, data, ctx)
|
|
44
65
|
|
|
45
66
|
context.params = {
|
|
46
67
|
...context.params,
|
|
@@ -48,43 +69,44 @@ export const resolveQuery = <T, H extends HookContext> (...resolvers: Resolver<T
|
|
|
48
69
|
}
|
|
49
70
|
|
|
50
71
|
if (typeof next === 'function') {
|
|
51
|
-
return next()
|
|
72
|
+
return next()
|
|
52
73
|
}
|
|
53
|
-
}
|
|
74
|
+
}
|
|
54
75
|
|
|
55
|
-
export const resolveData =
|
|
76
|
+
export const resolveData =
|
|
77
|
+
<H extends HookContext>(settings: DataResolvers<H> | Resolver<any, H>) =>
|
|
56
78
|
async (context: H, next?: NextFunction) => {
|
|
57
79
|
if (context.method === 'create' || context.method === 'patch' || context.method === 'update') {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
80
|
+
const resolvers = settings instanceof Resolver ? [settings] : [settings[context.method]]
|
|
81
|
+
const ctx = getContext(context)
|
|
82
|
+
const data = context.data
|
|
60
83
|
|
|
61
84
|
const status = {
|
|
62
85
|
originalContext: context
|
|
63
|
-
}
|
|
86
|
+
}
|
|
64
87
|
|
|
65
88
|
if (Array.isArray(data)) {
|
|
66
|
-
context.data = await Promise.all(data.map(current =>
|
|
67
|
-
runResolvers(resolvers, current, ctx, status)
|
|
68
|
-
));
|
|
89
|
+
context.data = await Promise.all(data.map((current) => runResolvers(resolvers, current, ctx, status)))
|
|
69
90
|
} else {
|
|
70
|
-
context.data = await runResolvers(resolvers, data, ctx, status)
|
|
91
|
+
context.data = await runResolvers(resolvers, data, ctx, status)
|
|
71
92
|
}
|
|
72
93
|
}
|
|
73
94
|
|
|
74
95
|
if (typeof next === 'function') {
|
|
75
|
-
return next()
|
|
96
|
+
return next()
|
|
76
97
|
}
|
|
77
|
-
}
|
|
98
|
+
}
|
|
78
99
|
|
|
79
|
-
export const resolveResult =
|
|
100
|
+
export const resolveResult =
|
|
101
|
+
<T, H extends HookContext>(...resolvers: Resolver<T, H>[]) =>
|
|
80
102
|
async (context: H, next?: NextFunction) => {
|
|
81
103
|
if (typeof next === 'function') {
|
|
82
|
-
const { $resolve: properties, ...query } = context.params?.query || {}
|
|
104
|
+
const { $resolve: properties, ...query } = context.params?.query || {}
|
|
83
105
|
const resolve = {
|
|
84
106
|
originalContext: context,
|
|
85
107
|
...context.params.resolve,
|
|
86
108
|
properties
|
|
87
|
-
}
|
|
109
|
+
}
|
|
88
110
|
|
|
89
111
|
context.params = {
|
|
90
112
|
...context.params,
|
|
@@ -92,79 +114,78 @@ export const resolveResult = <T, H extends HookContext> (...resolvers: Resolver<
|
|
|
92
114
|
query
|
|
93
115
|
}
|
|
94
116
|
|
|
95
|
-
await next()
|
|
117
|
+
await next()
|
|
96
118
|
}
|
|
97
119
|
|
|
98
|
-
const ctx = getContext(context)
|
|
99
|
-
const status = context.params.resolve
|
|
100
|
-
const { isPaginated, data } = getData(context)
|
|
120
|
+
const ctx = getContext(context)
|
|
121
|
+
const status = context.params.resolve
|
|
122
|
+
const { isPaginated, data } = getData(context)
|
|
101
123
|
|
|
102
|
-
const result = Array.isArray(data)
|
|
103
|
-
await Promise.all(data.map(async current => runResolvers(resolvers, current, ctx, status)))
|
|
104
|
-
await runResolvers(resolvers, data, ctx, status)
|
|
124
|
+
const result = Array.isArray(data)
|
|
125
|
+
? await Promise.all(data.map(async (current) => runResolvers(resolvers, current, ctx, status)))
|
|
126
|
+
: await runResolvers(resolvers, data, ctx, status)
|
|
105
127
|
|
|
106
128
|
if (isPaginated) {
|
|
107
|
-
context.result.data = result
|
|
129
|
+
context.result.data = result
|
|
108
130
|
} else {
|
|
109
|
-
context.result = result
|
|
131
|
+
context.result = result
|
|
110
132
|
}
|
|
111
|
-
}
|
|
133
|
+
}
|
|
112
134
|
|
|
113
|
-
export const resolveDispatch =
|
|
135
|
+
export const resolveDispatch =
|
|
136
|
+
<T, H extends HookContext>(...resolvers: Resolver<T, H>[]) =>
|
|
114
137
|
async (context: H, next?: NextFunction) => {
|
|
115
138
|
if (typeof next === 'function') {
|
|
116
|
-
await next()
|
|
139
|
+
await next()
|
|
117
140
|
}
|
|
118
141
|
|
|
119
|
-
const ctx = getContext(context)
|
|
120
|
-
const status = context.params.resolve
|
|
121
|
-
const { isPaginated, data } = getData(context)
|
|
122
|
-
const
|
|
123
|
-
const resolved = await runResolvers(resolvers, current, ctx, status)
|
|
142
|
+
const ctx = getContext(context)
|
|
143
|
+
const status = context.params.resolve
|
|
144
|
+
const { isPaginated, data } = getData(context)
|
|
145
|
+
const resolveAndGetDispatch = async (current: any) => {
|
|
146
|
+
const resolved: any = await runResolvers(resolvers, current, ctx, status)
|
|
124
147
|
|
|
125
148
|
return Object.keys(resolved).reduce((res, key) => {
|
|
126
|
-
|
|
127
|
-
const hasDispatch = typeof value === 'object' && value !== null && value[DISPATCH] !== undefined;
|
|
128
|
-
|
|
129
|
-
res[key] = hasDispatch ? value[DISPATCH] : value;
|
|
149
|
+
res[key] = getDispatch(resolved[key])
|
|
130
150
|
|
|
131
151
|
return res
|
|
132
152
|
}, {} as any)
|
|
133
153
|
}
|
|
134
154
|
|
|
135
|
-
const result = await (Array.isArray(data)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
const result = await (Array.isArray(data)
|
|
156
|
+
? Promise.all(data.map(resolveAndGetDispatch))
|
|
157
|
+
: resolveAndGetDispatch(data))
|
|
158
|
+
const dispatch = isPaginated
|
|
159
|
+
? {
|
|
160
|
+
...context.result,
|
|
161
|
+
data: result
|
|
162
|
+
}
|
|
163
|
+
: result
|
|
164
|
+
|
|
165
|
+
context.dispatch = dispatch
|
|
142
166
|
Object.defineProperty(context.result, DISPATCH, {
|
|
143
167
|
value: dispatch,
|
|
144
168
|
enumerable: false,
|
|
145
169
|
configurable: false
|
|
146
|
-
})
|
|
147
|
-
}
|
|
170
|
+
})
|
|
171
|
+
}
|
|
148
172
|
|
|
149
|
-
export
|
|
150
|
-
|
|
151
|
-
query?: Resolver<any, H>|Resolver<any, H>[]
|
|
152
|
-
result?: Resolver<any, H>|Resolver<any, H>[]
|
|
153
|
-
dispatch?: Resolver<any, H>|Resolver<any, H>[]
|
|
154
|
-
}
|
|
173
|
+
export const resolveAll = <H extends HookContext>(map: ResolveAllSettings<H>) => {
|
|
174
|
+
const middleware = []
|
|
155
175
|
|
|
156
|
-
|
|
157
|
-
map: ResolveAllSettings<H>,
|
|
158
|
-
name: keyof ResolveAllSettings<H>
|
|
159
|
-
) => {
|
|
160
|
-
const value = map[name];
|
|
176
|
+
middleware.push(resolveDispatch(map.dispatch))
|
|
161
177
|
|
|
162
|
-
|
|
163
|
-
|
|
178
|
+
if (map.result) {
|
|
179
|
+
middleware.push(resolveResult(map.result))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (map.query) {
|
|
183
|
+
middleware.push(resolveQuery(map.query))
|
|
184
|
+
}
|
|
164
185
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
if (map.data) {
|
|
187
|
+
middleware.push(resolveData(map.data))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return compose(middleware)
|
|
191
|
+
}
|
package/src/hooks/validate.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
2
|
-
import { BadRequest } from '../../../errors/lib'
|
|
3
|
-
import { Schema } from '../schema'
|
|
1
|
+
import { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
2
|
+
import { BadRequest } from '../../../errors/lib'
|
|
3
|
+
import { Schema } from '../schema'
|
|
4
4
|
|
|
5
|
-
export const validateQuery =
|
|
5
|
+
export const validateQuery =
|
|
6
|
+
<H extends HookContext>(schema: Schema<any>) =>
|
|
6
7
|
async (context: H, next?: NextFunction) => {
|
|
7
|
-
const data = context?.params?.query || {}
|
|
8
|
+
const data = context?.params?.query || {}
|
|
8
9
|
|
|
9
10
|
try {
|
|
10
|
-
const query = await schema.validate(data)
|
|
11
|
+
const query = await schema.validate(data)
|
|
11
12
|
|
|
12
13
|
context.params = {
|
|
13
14
|
...context.params,
|
|
@@ -15,30 +16,29 @@ export const validateQuery = <H extends HookContext> (schema: Schema<any>) =>
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
if (typeof next === 'function') {
|
|
18
|
-
return next()
|
|
19
|
+
return next()
|
|
19
20
|
}
|
|
20
21
|
} catch (error: any) {
|
|
21
|
-
throw
|
|
22
|
+
throw error.ajv ? new BadRequest(error.message, error.errors) : error
|
|
22
23
|
}
|
|
23
|
-
}
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
export const validateData =
|
|
27
|
+
<H extends HookContext>(schema: Schema<any>) =>
|
|
26
28
|
async (context: H, next?: NextFunction) => {
|
|
27
|
-
const data = context.data
|
|
29
|
+
const data = context.data
|
|
28
30
|
|
|
29
31
|
try {
|
|
30
32
|
if (Array.isArray(data)) {
|
|
31
|
-
context.data = await Promise.all(data.map(current =>
|
|
32
|
-
schema.validate(current)
|
|
33
|
-
));
|
|
33
|
+
context.data = await Promise.all(data.map((current) => schema.validate(current)))
|
|
34
34
|
} else {
|
|
35
|
-
context.data = await schema.validate(data)
|
|
35
|
+
context.data = await schema.validate(data)
|
|
36
36
|
}
|
|
37
37
|
} catch (error: any) {
|
|
38
|
-
throw
|
|
38
|
+
throw error.ajv ? new BadRequest(error.message, error.errors) : error
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (typeof next === 'function') {
|
|
42
|
-
return next()
|
|
42
|
+
return next()
|
|
43
43
|
}
|
|
44
|
-
}
|
|
44
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { ResolverStatus
|
|
1
|
+
import { ResolverStatus } from './resolver'
|
|
2
2
|
|
|
3
|
-
export * from './schema'
|
|
4
|
-
export * from './resolver'
|
|
5
|
-
export * from './hooks'
|
|
6
|
-
export * from './query'
|
|
3
|
+
export * from './schema'
|
|
4
|
+
export * from './resolver'
|
|
5
|
+
export * from './hooks'
|
|
6
|
+
export * from './query'
|
|
7
7
|
|
|
8
|
-
export type Infer<S extends { _type: any }> = S['_type']
|
|
8
|
+
export type Infer<S extends { _type: any }> = S['_type']
|
|
9
9
|
|
|
10
|
-
export type Combine<S extends { _type: any }, U> = Pick<Infer<S>, Exclude<keyof Infer<S>, keyof U>> & U
|
|
10
|
+
export type Combine<S extends { _type: any }, U> = Pick<Infer<S>, Exclude<keyof Infer<S>, keyof U>> & U
|
|
11
11
|
|
|
12
12
|
declare module '@feathersjs/feathers/lib/declarations' {
|
|
13
13
|
interface Params {
|
|
14
|
-
resolve?: ResolverStatus<any, HookContext
|
|
14
|
+
resolve?: ResolverStatus<any, HookContext>
|
|
15
15
|
}
|
|
16
16
|
}
|
package/src/query.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ } from '@feathersjs/commons'
|
|
2
|
+
import { JSONSchema } from 'json-schema-to-ts'
|
|
2
3
|
|
|
3
4
|
export type PropertyQuery<D extends JSONSchema> = {
|
|
4
5
|
anyOf: [
|
|
5
6
|
D,
|
|
6
7
|
{
|
|
7
|
-
type: 'object'
|
|
8
|
-
additionalProperties: false
|
|
8
|
+
type: 'object'
|
|
9
|
+
additionalProperties: false
|
|
9
10
|
properties: {
|
|
10
|
-
$gt: D
|
|
11
|
-
$gte: D
|
|
12
|
-
$lt: D
|
|
13
|
-
$lte: D
|
|
14
|
-
$ne: D
|
|
11
|
+
$gt: D
|
|
12
|
+
$gte: D
|
|
13
|
+
$lt: D
|
|
14
|
+
$lte: D
|
|
15
|
+
$ne: D
|
|
15
16
|
$in: {
|
|
16
|
-
type: 'array'
|
|
17
|
+
type: 'array'
|
|
17
18
|
items: D
|
|
18
|
-
}
|
|
19
|
+
}
|
|
19
20
|
$nin: {
|
|
20
|
-
type: 'array'
|
|
21
|
+
type: 'array'
|
|
21
22
|
items: D
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -25,64 +26,72 @@ export type PropertyQuery<D extends JSONSchema> = {
|
|
|
25
26
|
]
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
export const queryProperty = <T extends JSONSchema>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
export const queryProperty = <T extends JSONSchema>(def: T) => {
|
|
30
|
+
const definition = _.omit(def, 'default')
|
|
31
|
+
return {
|
|
32
|
+
anyOf: [
|
|
33
|
+
definition,
|
|
34
|
+
{
|
|
35
|
+
type: 'object',
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
properties: {
|
|
38
|
+
$gt: definition,
|
|
39
|
+
$gte: definition,
|
|
40
|
+
$lt: definition,
|
|
41
|
+
$lte: definition,
|
|
42
|
+
$ne: definition,
|
|
43
|
+
$in: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
items: definition
|
|
46
|
+
},
|
|
47
|
+
$nin: {
|
|
48
|
+
type: 'array',
|
|
49
|
+
items: definition
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
53
|
+
]
|
|
54
|
+
} as const
|
|
55
|
+
}
|
|
52
56
|
|
|
53
|
-
export const queryProperties = <T extends { [key: string]: JSONSchema }>
|
|
57
|
+
export const queryProperties = <T extends { [key: string]: JSONSchema }>(definition: T) =>
|
|
54
58
|
Object.keys(definition).reduce((res, key) => {
|
|
55
|
-
|
|
59
|
+
const result = res as any
|
|
60
|
+
|
|
61
|
+
result[key] = queryProperty(definition[key])
|
|
56
62
|
|
|
57
|
-
return
|
|
63
|
+
return result
|
|
58
64
|
}, {} as { [K in keyof T]: PropertyQuery<T[K]> })
|
|
59
65
|
|
|
60
|
-
export const querySyntax = <T extends { [key: string]:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
(res
|
|
73
|
-
|
|
74
|
-
enum: [1, -1]
|
|
75
|
-
}
|
|
66
|
+
export const querySyntax = <T extends { [key: string]: any }>(definition: T) =>
|
|
67
|
+
({
|
|
68
|
+
$limit: {
|
|
69
|
+
type: 'number',
|
|
70
|
+
minimum: 0
|
|
71
|
+
},
|
|
72
|
+
$skip: {
|
|
73
|
+
type: 'number',
|
|
74
|
+
minimum: 0
|
|
75
|
+
},
|
|
76
|
+
$sort: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: Object.keys(definition).reduce((res, key) => {
|
|
79
|
+
const result = res as any
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: '
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
result[key] = {
|
|
82
|
+
type: 'number',
|
|
83
|
+
enum: [1, -1]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result
|
|
87
|
+
}, {} as { [K in keyof T]: { readonly type: 'number'; readonly enum: [1, -1] } })
|
|
88
|
+
},
|
|
89
|
+
$select: {
|
|
90
|
+
type: 'array',
|
|
91
|
+
items: {
|
|
92
|
+
type: 'string',
|
|
93
|
+
enum: Object.keys(definition) as any as (keyof T)[]
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
...queryProperties(definition)
|
|
97
|
+
} as const)
|