@ditojs/server 1.12.0 → 1.13.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.
- package/package.json +24 -8
- package/src/services/Service.js +6 -0
- package/types/index.d.ts +2177 -0
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,2177 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
// Type definitions for Dito.js server
|
|
4
|
+
// Project: <https://github.com/ditojs/dito/>
|
|
5
|
+
|
|
6
|
+
// Export the entire Dito namespace.
|
|
7
|
+
|
|
8
|
+
import { DateFormat } from '@dito/utils'
|
|
9
|
+
import koaCors from '@koa/cors'
|
|
10
|
+
import * as Ajv from 'ajv/dist/2020.js'
|
|
11
|
+
import * as aws from 'aws-sdk'
|
|
12
|
+
import * as dbErrors from 'db-errors'
|
|
13
|
+
import * as EventEmitter2 from 'eventemitter2'
|
|
14
|
+
import helmet from 'helmet'
|
|
15
|
+
import * as Knex from 'knex'
|
|
16
|
+
import * as Koa from 'koa'
|
|
17
|
+
import koaBodyParser from 'koa-bodyparser'
|
|
18
|
+
import koaCompress from 'koa-compress'
|
|
19
|
+
import koaLogger from 'koa-logger'
|
|
20
|
+
import mount from 'koa-mount'
|
|
21
|
+
import koaPinoLogger from 'koa-pino-logger'
|
|
22
|
+
import koaResponseTime from 'koa-response-time'
|
|
23
|
+
import koaSession from 'koa-session'
|
|
24
|
+
import * as objection from 'objection'
|
|
25
|
+
import { KnexSnakeCaseMappersFactory } from 'objection'
|
|
26
|
+
import {
|
|
27
|
+
Class,
|
|
28
|
+
ConditionalExcept,
|
|
29
|
+
ConditionalKeys,
|
|
30
|
+
Constructor, SetOptional, SetReturnType
|
|
31
|
+
} from 'type-fest'
|
|
32
|
+
import { UserConfig } from 'vite'
|
|
33
|
+
|
|
34
|
+
export type Page<$Model extends Model> = {
|
|
35
|
+
total: number
|
|
36
|
+
results: $Model[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ApplicationConfig = {
|
|
40
|
+
/** @defaultValue `production` */
|
|
41
|
+
env?: 'production' | 'development'
|
|
42
|
+
/** The server configuration */
|
|
43
|
+
server?: {
|
|
44
|
+
/** The ip address or hostname used to serve requests */
|
|
45
|
+
host?: string
|
|
46
|
+
/** The port to listen on for connections */
|
|
47
|
+
port?: string
|
|
48
|
+
}
|
|
49
|
+
/** Logging options */
|
|
50
|
+
log?: {
|
|
51
|
+
/**
|
|
52
|
+
* Enable logging requests to console by passing `true` or pick between
|
|
53
|
+
* 'console' for logging to console and 'file' for logging to file
|
|
54
|
+
*
|
|
55
|
+
* @defaultValue `false`
|
|
56
|
+
*/
|
|
57
|
+
requests?: boolean | 'console' | 'file'
|
|
58
|
+
/**
|
|
59
|
+
* Whether to output route (Controller) logs
|
|
60
|
+
*
|
|
61
|
+
* @defaultValue `false`
|
|
62
|
+
*/
|
|
63
|
+
routes?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* Whether to log relation mappings
|
|
66
|
+
*
|
|
67
|
+
* @defaultValue `false`
|
|
68
|
+
*/
|
|
69
|
+
relations?: boolean
|
|
70
|
+
/**
|
|
71
|
+
* Whether to log the json schema generated out of the model property
|
|
72
|
+
* definitions
|
|
73
|
+
*
|
|
74
|
+
* @defaultValue `false`
|
|
75
|
+
*/
|
|
76
|
+
schema?: boolean
|
|
77
|
+
/**
|
|
78
|
+
* Whether to log sql queries
|
|
79
|
+
*
|
|
80
|
+
* @defaultValue `false`
|
|
81
|
+
*/
|
|
82
|
+
sql?: boolean
|
|
83
|
+
/** Whether to turn off all logging */
|
|
84
|
+
silent?: boolean
|
|
85
|
+
errors?:
|
|
86
|
+
| boolean
|
|
87
|
+
| {
|
|
88
|
+
/** Whether to log sql errors */
|
|
89
|
+
sql?: boolean
|
|
90
|
+
/** Whether to log the error stack */
|
|
91
|
+
stack?: boolean
|
|
92
|
+
json?: boolean
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
api?: ApiConfig
|
|
96
|
+
app?: {
|
|
97
|
+
/**
|
|
98
|
+
* Whether to normalize paths from camel case to kebab case.
|
|
99
|
+
*
|
|
100
|
+
* @defaultValue `false`
|
|
101
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/controllers.md#path-normalization|Path Normalization}
|
|
102
|
+
*/
|
|
103
|
+
normalizePaths?: boolean
|
|
104
|
+
/**
|
|
105
|
+
* Whether proxy header fields will be trusted.
|
|
106
|
+
*
|
|
107
|
+
* @defaultValue `false`
|
|
108
|
+
*/
|
|
109
|
+
proxy?: Koa['proxy']
|
|
110
|
+
/**
|
|
111
|
+
* Whether to include X-Response-Time header in responses
|
|
112
|
+
*
|
|
113
|
+
* @defaultValue `true`
|
|
114
|
+
*/
|
|
115
|
+
responseTime?: boolean | Parameters<typeof koaResponseTime>[0]
|
|
116
|
+
/**
|
|
117
|
+
* Whether to use koa-helmet middleware which provides important security
|
|
118
|
+
* headers to make your app more secure by default.
|
|
119
|
+
*
|
|
120
|
+
* @defaultValue `true`
|
|
121
|
+
* @see https://github.com/venables/koa-helmet
|
|
122
|
+
* @see https://github.com/helmetjs/helmet
|
|
123
|
+
*/
|
|
124
|
+
helmet?: boolean | Parameters<typeof helmet>[0]
|
|
125
|
+
logger?:
|
|
126
|
+
| Parameters<typeof koaLogger>[0]
|
|
127
|
+
| Parameters<typeof koaPinoLogger>[0]
|
|
128
|
+
/**
|
|
129
|
+
* Configure body parser.
|
|
130
|
+
*
|
|
131
|
+
* @see https://github.com/koajs/bodyparser#options
|
|
132
|
+
*/
|
|
133
|
+
bodyParser?: koaBodyParser.Options
|
|
134
|
+
/**
|
|
135
|
+
* Enable or configure Cross-Origin Resource Sharing (CORS)
|
|
136
|
+
*
|
|
137
|
+
* @defaultValue `true`
|
|
138
|
+
* @see https://github.com/koajs/cors#corsoptions
|
|
139
|
+
*/
|
|
140
|
+
cors?: boolean | koaCors.Options
|
|
141
|
+
/**
|
|
142
|
+
* Enable or configure server response compression
|
|
143
|
+
*
|
|
144
|
+
* @defaultValue `true`
|
|
145
|
+
* @see https://github.com/koajs/compress#options
|
|
146
|
+
*/
|
|
147
|
+
compress?: boolean | koaCompress.CompressOptions
|
|
148
|
+
/**
|
|
149
|
+
* Enable ETag headers in server responses
|
|
150
|
+
*
|
|
151
|
+
* @defaultValue `true`
|
|
152
|
+
*/
|
|
153
|
+
etag?: boolean
|
|
154
|
+
/**
|
|
155
|
+
* @defaultValue `false`
|
|
156
|
+
* @see https://github.com/koajs/session
|
|
157
|
+
*/
|
|
158
|
+
session?: boolean | (koaSession.opts & { modelClass: string })
|
|
159
|
+
/**
|
|
160
|
+
* Enable passport authentication middleware
|
|
161
|
+
*
|
|
162
|
+
* @defaultValue `false`
|
|
163
|
+
*/
|
|
164
|
+
passport?: boolean
|
|
165
|
+
/**
|
|
166
|
+
* Set signed cookie keys.
|
|
167
|
+
*
|
|
168
|
+
* @see https://github.com/koajs/koa/blob/master/docs/api/index.md#appkeys
|
|
169
|
+
*/
|
|
170
|
+
keys?: Koa['keys']
|
|
171
|
+
}
|
|
172
|
+
admin?: AdminConfig
|
|
173
|
+
knex?: Knex.Config<any> & {
|
|
174
|
+
/** @defaultValue `false` */
|
|
175
|
+
normalizeDbNames?: boolean | Parameters<KnexSnakeCaseMappersFactory>
|
|
176
|
+
// See https://github.com/brianc/node-pg-types/blob/master/index.d.ts#L67
|
|
177
|
+
typeParsers?: Record<number, <I extends string | Buffer>(value: I) => any>
|
|
178
|
+
}
|
|
179
|
+
/** Service configurations. Pass `false` as a value to disable a service. */
|
|
180
|
+
services?: Services
|
|
181
|
+
storages?: StorageConfigs
|
|
182
|
+
assets?: {
|
|
183
|
+
/**
|
|
184
|
+
* Threshold after which unused assets that haven't seen changes for given
|
|
185
|
+
* timeframe are removed.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* '1 hr 20 mins'
|
|
189
|
+
*
|
|
190
|
+
* @default `0`
|
|
191
|
+
* @see https://www.npmjs.com/package/parse-duration
|
|
192
|
+
*/
|
|
193
|
+
cleanupTimeThreshold?: string | number
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export type MulterS3File = {
|
|
198
|
+
bucket: string
|
|
199
|
+
key: string
|
|
200
|
+
acl: string
|
|
201
|
+
contentType: string
|
|
202
|
+
contentDisposition: null
|
|
203
|
+
storageClass: string
|
|
204
|
+
serverSideEncryption: null
|
|
205
|
+
metadata: any
|
|
206
|
+
location: string
|
|
207
|
+
etag: string
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type StorageConfigs = { [key: string]: StorageConfig }
|
|
211
|
+
|
|
212
|
+
export type StorageConfig =
|
|
213
|
+
| {
|
|
214
|
+
type: 's3'
|
|
215
|
+
/** The name of the destination bucket. */
|
|
216
|
+
bucket: aws.S3.BucketName
|
|
217
|
+
/** @default 'private' */
|
|
218
|
+
acl: LiteralUnion<
|
|
219
|
+
| 'private'
|
|
220
|
+
| 'public-read'
|
|
221
|
+
| 'public-read-write'
|
|
222
|
+
| 'authenticated-read'
|
|
223
|
+
| 'aws-exec-read'
|
|
224
|
+
| 'bucket-owner-read'
|
|
225
|
+
| 'bucket-owner-full-control'
|
|
226
|
+
>
|
|
227
|
+
/**
|
|
228
|
+
* Can be used to specify caching behavior along the request/reply chain.
|
|
229
|
+
*
|
|
230
|
+
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.
|
|
231
|
+
*/
|
|
232
|
+
cacheControl?: aws.S3.CacheControl
|
|
233
|
+
/**
|
|
234
|
+
* The type of storage to use for the object.
|
|
235
|
+
*
|
|
236
|
+
* @default 'STANDARD'
|
|
237
|
+
*/
|
|
238
|
+
storageClass?: LiteralUnion<
|
|
239
|
+
| 'STANDARD'
|
|
240
|
+
| 'REDUCED_REDUNDANCY'
|
|
241
|
+
| 'STANDARD_IA'
|
|
242
|
+
| 'ONEZONE_IA'
|
|
243
|
+
| 'INTELLIGENT_TIERING'
|
|
244
|
+
| 'GLACIER'
|
|
245
|
+
| 'DEEP_ARCHIVE'
|
|
246
|
+
>
|
|
247
|
+
/**
|
|
248
|
+
* The server-side encryption algorithm used when storing this object in
|
|
249
|
+
* Amazon S3 (for example, AES256, aws:kms).
|
|
250
|
+
*/
|
|
251
|
+
serverSideEncryption?: aws.S3.ServerSideEncryption
|
|
252
|
+
/**
|
|
253
|
+
* If present, specifies the ID of the AWS Key Management Service (AWS
|
|
254
|
+
* KMS) symmetric customer managed customer master key (CMK)
|
|
255
|
+
*/
|
|
256
|
+
sseKmsKeyId?: aws.S3.SSEKMSKeyId
|
|
257
|
+
s3: aws.S3.ClientConfiguration
|
|
258
|
+
url?: string
|
|
259
|
+
}
|
|
260
|
+
| {
|
|
261
|
+
type: 'disk'
|
|
262
|
+
path: string
|
|
263
|
+
url?: string
|
|
264
|
+
mount?: string
|
|
265
|
+
allowedImports?: string[]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface AdminConfig {
|
|
269
|
+
api?: ApiConfig
|
|
270
|
+
/** Path to the admin's src directory. Mandatory when in development mode. */
|
|
271
|
+
root?: string
|
|
272
|
+
/**
|
|
273
|
+
* Path to the dist/src/admin directory. Mandatory when in production mode.
|
|
274
|
+
*/
|
|
275
|
+
dist?: string
|
|
276
|
+
/** @default Application */
|
|
277
|
+
mode?: 'production' | 'development'
|
|
278
|
+
/** Settings accessible on the browser side as `global.dito.settings`. */
|
|
279
|
+
settings?: Record<string, any>
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface ApiResource {
|
|
283
|
+
type: string
|
|
284
|
+
path?: string
|
|
285
|
+
parent?: ApiResource
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export interface ApiConfig {
|
|
289
|
+
/** The base url to use for api requests. */
|
|
290
|
+
url?: string
|
|
291
|
+
/** @defaultValue 'en-US' */
|
|
292
|
+
locale?: string
|
|
293
|
+
dateFormat?: DateFormat
|
|
294
|
+
/**
|
|
295
|
+
* Whether to display admin notifications.
|
|
296
|
+
*
|
|
297
|
+
* @default `true`
|
|
298
|
+
*/
|
|
299
|
+
notifications?:
|
|
300
|
+
| boolean
|
|
301
|
+
| {
|
|
302
|
+
/**
|
|
303
|
+
* The amount of milliseconds multiplied with the amount of characters
|
|
304
|
+
* displayed in the notification, plus 40 (40 + title + message).
|
|
305
|
+
*
|
|
306
|
+
* @defaultValue `20`
|
|
307
|
+
*/
|
|
308
|
+
durationFactor: number
|
|
309
|
+
}
|
|
310
|
+
cors?: {
|
|
311
|
+
/**
|
|
312
|
+
* Whether cross-site `Access-Control` requests are made using credentials.
|
|
313
|
+
*/
|
|
314
|
+
credentials: boolean
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Setting normalizePaths to `true` sets `api.normalizePath` to hyphenate
|
|
318
|
+
* camelized strings and `api.denormalizePath` to do the opposite. If you
|
|
319
|
+
* prefer to use another path normalization algorithm, they can be defined the
|
|
320
|
+
* api settings passed to the DitoAdmin constructor.
|
|
321
|
+
*
|
|
322
|
+
* @default Defaults to Application.config.app.normalizePaths and then
|
|
323
|
+
*/
|
|
324
|
+
normalizePaths?: boolean
|
|
325
|
+
/** Auth resources */
|
|
326
|
+
users?: {
|
|
327
|
+
path?: string
|
|
328
|
+
login?: {
|
|
329
|
+
/** @defaultValue `'login'` */
|
|
330
|
+
path?: string
|
|
331
|
+
/** @defaultValue `'post'` */
|
|
332
|
+
method?: HTTPMethod
|
|
333
|
+
}
|
|
334
|
+
logout?: {
|
|
335
|
+
/** @defaultValue `'logout'` */
|
|
336
|
+
path?: string
|
|
337
|
+
/** @defaultValue `'post'` */
|
|
338
|
+
method?: HTTPMethod
|
|
339
|
+
}
|
|
340
|
+
session?: {
|
|
341
|
+
/** @defaultValue `'session'` */
|
|
342
|
+
path?: string
|
|
343
|
+
/** @defaultValue `'get'` */
|
|
344
|
+
method?: HTTPMethod
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/** Optionally override resource path handlers. */
|
|
348
|
+
resources?: Record<string, (resource: ApiResource | string) => string>
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Optionally override / extend headers
|
|
352
|
+
*
|
|
353
|
+
* @defaultValue `
|
|
354
|
+
*/
|
|
355
|
+
headers?: Record<string, string>
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export interface ApplicationControllers {
|
|
359
|
+
[k: string]:
|
|
360
|
+
| Class<ModelController<Model>>
|
|
361
|
+
| Class<Controller>
|
|
362
|
+
| ApplicationControllers
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export type Models = Record<string, Class<Model>>
|
|
366
|
+
|
|
367
|
+
export class Application<$Models extends Models> {
|
|
368
|
+
constructor(options: {
|
|
369
|
+
config?: ApplicationConfig
|
|
370
|
+
validator?: Validator
|
|
371
|
+
// TODO: router types
|
|
372
|
+
router?: any
|
|
373
|
+
/**
|
|
374
|
+
* Subscribe to application events. Event names: `'before:start'`,
|
|
375
|
+
* `'after:start'`, `'before:stop'`, `'after:stop'`, `'error'`
|
|
376
|
+
*/
|
|
377
|
+
events?: Record<string, (this: Application<$Models>, ...args: []) => void>
|
|
378
|
+
models: $Models
|
|
379
|
+
controllers?: ApplicationControllers
|
|
380
|
+
// TODO: services docs
|
|
381
|
+
services?: Services
|
|
382
|
+
middleware?: Koa.Middleware
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
models: $Models
|
|
386
|
+
start(): Promise<void>
|
|
387
|
+
stop(timeout?: number): Promise<void>
|
|
388
|
+
startOrExit(): Promise<void>
|
|
389
|
+
addServices(services: Services): void
|
|
390
|
+
addService(service: Service): void
|
|
391
|
+
addController(controllers: Controller, namespace?: string): void
|
|
392
|
+
addControllers(controllers: ApplicationControllers, namespace?: string): void
|
|
393
|
+
addStorages(storages: StorageConfigs): void
|
|
394
|
+
addStorage(storage: StorageConfig): void
|
|
395
|
+
addModels(models: Models): void
|
|
396
|
+
addModel(model: Class<Model>): void
|
|
397
|
+
getAdminViteConfig(config?: UserConfig): UserConfig
|
|
398
|
+
}
|
|
399
|
+
export interface Application
|
|
400
|
+
extends Omit<
|
|
401
|
+
Koa,
|
|
402
|
+
| 'setMaxListeners'
|
|
403
|
+
| 'removeListener'
|
|
404
|
+
| 'removeAllListeners'
|
|
405
|
+
| 'prependOnceListener'
|
|
406
|
+
| 'prependListener'
|
|
407
|
+
| 'once'
|
|
408
|
+
| 'on'
|
|
409
|
+
| 'off'
|
|
410
|
+
| 'listeners'
|
|
411
|
+
| 'addListener'
|
|
412
|
+
| 'listenerCount'
|
|
413
|
+
| 'emit'
|
|
414
|
+
| 'eventNames'
|
|
415
|
+
>,
|
|
416
|
+
EventEmitter {}
|
|
417
|
+
|
|
418
|
+
export type SchemaType = LiteralUnion<
|
|
419
|
+
| 'string'
|
|
420
|
+
| 'number'
|
|
421
|
+
| 'integer'
|
|
422
|
+
| 'boolean'
|
|
423
|
+
| 'object'
|
|
424
|
+
| 'array'
|
|
425
|
+
| 'null'
|
|
426
|
+
| 'date'
|
|
427
|
+
| 'datetime'
|
|
428
|
+
| 'timestamp'
|
|
429
|
+
>
|
|
430
|
+
|
|
431
|
+
export interface ModelRelation {
|
|
432
|
+
/**
|
|
433
|
+
* The type of relation
|
|
434
|
+
*
|
|
435
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-relations.md#relation-types|Relation Types}
|
|
436
|
+
*/
|
|
437
|
+
relation: LiteralUnion<
|
|
438
|
+
'belongsTo' | 'hasMany' | 'hasOne' | 'manyToMany' | 'hasOneThrough'
|
|
439
|
+
>
|
|
440
|
+
/**
|
|
441
|
+
* The model and property name from which the relation is to be built, as a
|
|
442
|
+
* string with both identifiers separated by '.', e.g.:
|
|
443
|
+
* 'FromModelClass.fromPropertyName'
|
|
444
|
+
*/
|
|
445
|
+
from: string
|
|
446
|
+
/**
|
|
447
|
+
* The model and property name to which the relation is to be built, as a
|
|
448
|
+
* string with both identifiers separated by '.', e.g.:
|
|
449
|
+
* 'ToModelClass.toPropertyName'
|
|
450
|
+
*/
|
|
451
|
+
to: string
|
|
452
|
+
/**
|
|
453
|
+
* When set to true the join model class and table is to be built
|
|
454
|
+
* automatically, or allows to specify an existing one manually.
|
|
455
|
+
*
|
|
456
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-relations.md#join-models-and-tables|Join Models and Tables}
|
|
457
|
+
*/
|
|
458
|
+
through?:
|
|
459
|
+
| boolean
|
|
460
|
+
| {
|
|
461
|
+
/**
|
|
462
|
+
* The model and property name or table and column name of an existing
|
|
463
|
+
* join model class or join table from which the through relation is to
|
|
464
|
+
* be built, as a string with both identifiers separated by '.', e.g.:
|
|
465
|
+
* 'FromModelClass.fromPropertyName'
|
|
466
|
+
*/
|
|
467
|
+
from: string
|
|
468
|
+
/**
|
|
469
|
+
* The model and property name or table and column name of an existing
|
|
470
|
+
* join model class or join table to which the through relation is to be
|
|
471
|
+
* built, as a string with both identifiers separated by '.', e.g.:
|
|
472
|
+
* 'toModelClass.toPropertyName'
|
|
473
|
+
*/
|
|
474
|
+
to: string
|
|
475
|
+
/**
|
|
476
|
+
* List additional columns to be added to the related model.
|
|
477
|
+
*
|
|
478
|
+
* When working with a join model class or table, extra columns from it
|
|
479
|
+
* can be added to the related model, as if it was define on its own
|
|
480
|
+
* table. They then appear as additional properties on the related
|
|
481
|
+
* model.
|
|
482
|
+
*/
|
|
483
|
+
extra?: string[]
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Controls whether the relation is the inverse of another relation.
|
|
487
|
+
*
|
|
488
|
+
* This information is only required when working with through relations.
|
|
489
|
+
* Without it, Dito.js wouldn't be able to tell which side of the relation is
|
|
490
|
+
* on the left-hand side, and which is on the right-hand side when
|
|
491
|
+
* automatically creating the join model class and table.
|
|
492
|
+
*/
|
|
493
|
+
inverse?: boolean
|
|
494
|
+
/**
|
|
495
|
+
* Optionally, a scope can be defined to be applied when loading the
|
|
496
|
+
* relation's models. The scope needs to be defined in the related model
|
|
497
|
+
* class' scopes definitions.
|
|
498
|
+
*/
|
|
499
|
+
scope?: string
|
|
500
|
+
/**
|
|
501
|
+
* Controls whether the auto-inserted foreign key property should be marked as
|
|
502
|
+
* nullable. This only makes sense on a 'belongsTo' relation, where the model
|
|
503
|
+
* class holds the foreign key, and only when the foreign key isn't already
|
|
504
|
+
* explicitly defined in the Model Properties.
|
|
505
|
+
*/
|
|
506
|
+
nullable?: boolean
|
|
507
|
+
/**
|
|
508
|
+
* Controls whether the relation owns the models that it holds, or whether it
|
|
509
|
+
* is simply relating to them, and a relation elsewhere is considered to be
|
|
510
|
+
* their owner.
|
|
511
|
+
*/
|
|
512
|
+
owner?: boolean
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export type ModelProperty<T = any> = Schema<T> & {
|
|
516
|
+
/** Marks the column as the primary key in the database. */
|
|
517
|
+
primary?: boolean
|
|
518
|
+
/**
|
|
519
|
+
* Defines if the property is a foreign key.
|
|
520
|
+
*
|
|
521
|
+
* Finds the information about the related model in the relations definition
|
|
522
|
+
* and adds a reference to the related model table in migrations, by calling
|
|
523
|
+
* the .references(columnName).inTable(tableName) method.
|
|
524
|
+
*/
|
|
525
|
+
foreign?: boolean
|
|
526
|
+
/**
|
|
527
|
+
* Adds an index to the database column in the migrations, by calling the
|
|
528
|
+
* .index() method.
|
|
529
|
+
*/
|
|
530
|
+
index?: boolean
|
|
531
|
+
/**
|
|
532
|
+
* Marks the column as nullable in the migrations, by calling the .nullable()
|
|
533
|
+
* method.
|
|
534
|
+
*/
|
|
535
|
+
nullable?: boolean
|
|
536
|
+
/**
|
|
537
|
+
* Adds a unique constraint to the table for the given column in the
|
|
538
|
+
* migrations, by calling the .unique() method. If a string is provided, all
|
|
539
|
+
* columns with the same string value for unique are grouped together in one
|
|
540
|
+
* unique constraint, by calling .unique([column1, column2, …]).
|
|
541
|
+
*/
|
|
542
|
+
unique?: boolean | string
|
|
543
|
+
/**
|
|
544
|
+
* Marks the column for a property of type 'integer' to be unsigned in the
|
|
545
|
+
* migrations, by calling the .index() method.calling the .unsigned() method.
|
|
546
|
+
*/
|
|
547
|
+
unsigned?: boolean
|
|
548
|
+
/**
|
|
549
|
+
* Marks the property as computed.
|
|
550
|
+
*
|
|
551
|
+
* Computed properties are not present as columns in the database itself. They
|
|
552
|
+
* can be created either by an SQL statement (SELECT … AS), or by a getter
|
|
553
|
+
* accessor defined on the model. Computed properties are set when converting
|
|
554
|
+
* to JSON if not present already, and removed again before data is sent to
|
|
555
|
+
* the database.
|
|
556
|
+
*/
|
|
557
|
+
computed?: boolean
|
|
558
|
+
/**
|
|
559
|
+
* Marks the property has hidden, so that it does not show up in data
|
|
560
|
+
* converted to JSON.
|
|
561
|
+
*
|
|
562
|
+
* This can be used for sensitive data.
|
|
563
|
+
*/
|
|
564
|
+
hidden?: boolean
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
export type ModelScope<$Model extends Model> = (
|
|
568
|
+
this: $Model,
|
|
569
|
+
query: QueryBuilder<$Model>,
|
|
570
|
+
applyParentScope: (query: QueryBuilder<$Model>) => QueryBuilder<$Model>
|
|
571
|
+
) => QueryBuilder<$Model, any> | void
|
|
572
|
+
|
|
573
|
+
export type ModelScopes<$Model extends Model> = Record<
|
|
574
|
+
string,
|
|
575
|
+
ModelScope<$Model>
|
|
576
|
+
>
|
|
577
|
+
|
|
578
|
+
export type ModelFilterFunction<$Model extends Model> = (
|
|
579
|
+
queryBuilder: QueryBuilder<$Model>,
|
|
580
|
+
...args: any[]
|
|
581
|
+
) => void
|
|
582
|
+
|
|
583
|
+
export type ModelFilter<$Model extends Model> =
|
|
584
|
+
| {
|
|
585
|
+
filter: 'text' | 'date-range'
|
|
586
|
+
properties?: string[]
|
|
587
|
+
}
|
|
588
|
+
| {
|
|
589
|
+
handler: ModelFilterFunction<$Model>
|
|
590
|
+
parameters?: { [key: string]: Schema }
|
|
591
|
+
// TODO: validate type
|
|
592
|
+
validate?: any
|
|
593
|
+
}
|
|
594
|
+
| ModelFilterFunction<$Model>
|
|
595
|
+
|
|
596
|
+
export type ModelFilters<$Model extends Model> = Record<
|
|
597
|
+
string,
|
|
598
|
+
ModelFilter<$Model>
|
|
599
|
+
>
|
|
600
|
+
|
|
601
|
+
export interface ModelAsset {
|
|
602
|
+
storage: string
|
|
603
|
+
readImageSize?: boolean
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export type ModelAssets = Record<string, ModelAsset>
|
|
607
|
+
|
|
608
|
+
export interface ModelOptions extends objection.ModelOptions {
|
|
609
|
+
graph?: boolean
|
|
610
|
+
async?: boolean
|
|
611
|
+
mutable?: boolean
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
type ModelHookFunction<$Model extends Model> = (
|
|
615
|
+
args: objection.StaticHookArguments<$Model>
|
|
616
|
+
) => void
|
|
617
|
+
export type ModelHooks<$Model extends Model> = {
|
|
618
|
+
[key in `${'before' | 'after'}:${
|
|
619
|
+
| 'find'
|
|
620
|
+
| 'insert'
|
|
621
|
+
| 'update'
|
|
622
|
+
| 'delete'}`]?: ModelHookFunction<$Model>
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export class Model extends objection.Model {
|
|
626
|
+
/** @see {@link https://github.com/ditojs/dito/blob/master/docs/model-properties.md|Model Properties} */
|
|
627
|
+
static properties: ModelProperties
|
|
628
|
+
|
|
629
|
+
/** @see {@link https://github.com/ditojs/dito/blob/master/docs/model-relations.md|Model Relations} */
|
|
630
|
+
static relations: ModelRelations
|
|
631
|
+
|
|
632
|
+
/** @see {@link https://github.com/ditojs/dito/blob/master/docs/model-scopes.md|Model Scopes} */
|
|
633
|
+
static scopes: ModelScopes<Model>
|
|
634
|
+
|
|
635
|
+
/** @see {@link https://github.com/ditojs/dito/blob/master/docs/model-filters.md|Model Filters} */
|
|
636
|
+
static filters: ModelFilters<Model>
|
|
637
|
+
|
|
638
|
+
static hooks: ModelHooks<Model>
|
|
639
|
+
|
|
640
|
+
static assets: ModelAssets
|
|
641
|
+
|
|
642
|
+
static getPropertyOrRelationAtDataPath: (dataPath: OrArrayOf<string>) => any
|
|
643
|
+
|
|
644
|
+
static count: {
|
|
645
|
+
(column?: objection.ColumnRef, options?: { as: string }): number
|
|
646
|
+
(aliasToColumnDict: Record<string, string | string[]>): number
|
|
647
|
+
(...columns: objection.ColumnRef[]): number
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Dito automatically adds an `id` property if a model property with the
|
|
652
|
+
* `primary: true` setting is not already explicitly defined.
|
|
653
|
+
*/
|
|
654
|
+
readonly id: Id
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Dito automatically adds a `foreignKeyId` property if foreign keys occurring
|
|
658
|
+
* in relations definitions are not explicitly defined in the properties.
|
|
659
|
+
*/
|
|
660
|
+
readonly foreignKeyId: Id
|
|
661
|
+
|
|
662
|
+
QueryBuilderType: QueryBuilder<this, this[]>
|
|
663
|
+
|
|
664
|
+
// Todo: include application settings
|
|
665
|
+
$app: Application<Models>
|
|
666
|
+
$is(model: Model): boolean
|
|
667
|
+
$update(
|
|
668
|
+
attributes: Partial<ExtractModelProperties<this>>,
|
|
669
|
+
trx?: objection.Transaction
|
|
670
|
+
): objection.SingleQueryBuilder<objection.QueryBuilderType<this>>
|
|
671
|
+
|
|
672
|
+
$patch(
|
|
673
|
+
attributes: Partial<ExtractModelProperties<this>>,
|
|
674
|
+
trx?: objection.Transaction
|
|
675
|
+
): objection.SingleQueryBuilder<objection.QueryBuilderType<this>>
|
|
676
|
+
|
|
677
|
+
$validate<$JSON extends null | {}>(
|
|
678
|
+
json?: $JSON,
|
|
679
|
+
options?: ModelOptions & Record<string, any>
|
|
680
|
+
): Promise<$JSON | this>
|
|
681
|
+
|
|
682
|
+
$validateGraph(options: ModelOptions & Record<string, any>): Promise<this>
|
|
683
|
+
|
|
684
|
+
/* -------------------- Start QueryBuilder.mixin(Model) ------------------- */
|
|
685
|
+
static first: StaticQueryBuilderMethod<'first'>
|
|
686
|
+
static find: StaticQueryBuilderMethod<'find'>
|
|
687
|
+
static findOne: StaticQueryBuilderMethod<'findOne'>
|
|
688
|
+
static findById: StaticQueryBuilderMethod<'findById'>
|
|
689
|
+
|
|
690
|
+
static withGraph: StaticQueryBuilderMethod<'withGraph'>
|
|
691
|
+
static withGraphFetched: StaticQueryBuilderMethod<'withGraphFetched'>
|
|
692
|
+
static withGraphJoined: StaticQueryBuilderMethod<'withGraphJoined'>
|
|
693
|
+
static clearWithGraph: StaticQueryBuilderMethod<'clearWithGraph'>
|
|
694
|
+
|
|
695
|
+
static withScope: StaticQueryBuilderMethod<'withScope'>
|
|
696
|
+
static applyScope: StaticQueryBuilderMethod<'applyScope'>
|
|
697
|
+
static clearWithScope: StaticQueryBuilderMethod<'clearWithScope'>
|
|
698
|
+
|
|
699
|
+
static clear: StaticQueryBuilderMethod<'clear'>
|
|
700
|
+
static pick: StaticQueryBuilderMethod<'pick'>
|
|
701
|
+
static omit: StaticQueryBuilderMethod<'omit'>
|
|
702
|
+
static select: StaticQueryBuilderMethod<'select'>
|
|
703
|
+
|
|
704
|
+
static insert: StaticQueryBuilderMethod<'insert'>
|
|
705
|
+
static upsert: StaticQueryBuilderMethod<'upsert'>
|
|
706
|
+
static update: StaticQueryBuilderMethod<'update'>
|
|
707
|
+
static relate: StaticQueryBuilderMethod<'relate'>
|
|
708
|
+
static patch: StaticQueryBuilderMethod<'patch'>
|
|
709
|
+
|
|
710
|
+
static truncate: StaticQueryBuilderMethod<'truncate'>
|
|
711
|
+
static delete: StaticQueryBuilderMethod<'delete'>
|
|
712
|
+
static deleteById: StaticQueryBuilderMethod<'deleteById'>
|
|
713
|
+
|
|
714
|
+
static insertAndFetch: StaticQueryBuilderMethod<'insertAndFetch'>
|
|
715
|
+
static upsertAndFetch: StaticQueryBuilderMethod<'upsertAndFetch'>
|
|
716
|
+
static updateAndFetch: StaticQueryBuilderMethod<'updateAndFetch'>
|
|
717
|
+
static patchAndFetch: StaticQueryBuilderMethod<'patchAndFetch'>
|
|
718
|
+
static patchAndFetchById: StaticQueryBuilderMethod<'patchAndFetchById'>
|
|
719
|
+
static updateAndFetchById: StaticQueryBuilderMethod<'updateAndFetchById'>
|
|
720
|
+
|
|
721
|
+
static insertGraph: StaticQueryBuilderMethod<'insertGraph'>
|
|
722
|
+
static upsertGraph: StaticQueryBuilderMethod<'upsertGraph'>
|
|
723
|
+
static insertGraphAndFetch: StaticQueryBuilderMethod<'insertGraphAndFetch'>
|
|
724
|
+
static upsertGraphAndFetch: StaticQueryBuilderMethod<'upsertGraphAndFetch'>
|
|
725
|
+
|
|
726
|
+
static insertDitoGraph: StaticQueryBuilderMethod<'insertDitoGraph'>
|
|
727
|
+
static upsertDitoGraph: StaticQueryBuilderMethod<'upsertDitoGraph'>
|
|
728
|
+
static updateDitoGraph: StaticQueryBuilderMethod<'updateDitoGraph'>
|
|
729
|
+
static patchDitoGraph: StaticQueryBuilderMethod<'patchDitoGraph'>
|
|
730
|
+
static insertDitoGraphAndFetch:
|
|
731
|
+
StaticQueryBuilderMethod<'insertDitoGraphAndFetch'>
|
|
732
|
+
|
|
733
|
+
static upsertDitoGraphAndFetch:
|
|
734
|
+
StaticQueryBuilderMethod<'upsertDitoGraphAndFetch'>
|
|
735
|
+
|
|
736
|
+
static updateDitoGraphAndFetch:
|
|
737
|
+
StaticQueryBuilderMethod<'updateDitoGraphAndFetch'>
|
|
738
|
+
|
|
739
|
+
static patchDitoGraphAndFetch:
|
|
740
|
+
StaticQueryBuilderMethod<'patchDitoGraphAndFetch'>
|
|
741
|
+
|
|
742
|
+
static upsertDitoGraphAndFetchById:
|
|
743
|
+
StaticQueryBuilderMethod<'upsertDitoGraphAndFetchById'>
|
|
744
|
+
|
|
745
|
+
static updateDitoGraphAndFetchById:
|
|
746
|
+
StaticQueryBuilderMethod<'updateDitoGraphAndFetchById'>
|
|
747
|
+
|
|
748
|
+
static patchDitoGraphAndFetchById:
|
|
749
|
+
StaticQueryBuilderMethod<'patchDitoGraphAndFetchById'>
|
|
750
|
+
|
|
751
|
+
static where: StaticQueryBuilderMethod<'where'>
|
|
752
|
+
static whereNot: StaticQueryBuilderMethod<'whereNot'>
|
|
753
|
+
static whereRaw: StaticQueryBuilderMethod<'whereRaw'>
|
|
754
|
+
static whereWrapped: StaticQueryBuilderMethod<'whereWrapped'>
|
|
755
|
+
static whereExists: StaticQueryBuilderMethod<'whereExists'>
|
|
756
|
+
static whereNotExists: StaticQueryBuilderMethod<'whereNotExists'>
|
|
757
|
+
static whereIn: StaticQueryBuilderMethod<'whereIn'>
|
|
758
|
+
static whereNotIn: StaticQueryBuilderMethod<'whereNotIn'>
|
|
759
|
+
static whereNull: StaticQueryBuilderMethod<'whereNull'>
|
|
760
|
+
static whereNotNull: StaticQueryBuilderMethod<'whereNotNull'>
|
|
761
|
+
static whereBetween: StaticQueryBuilderMethod<'whereBetween'>
|
|
762
|
+
static whereNotBetween: StaticQueryBuilderMethod<'whereNotBetween'>
|
|
763
|
+
static whereColumn: StaticQueryBuilderMethod<'whereColumn'>
|
|
764
|
+
static whereNotColumn: StaticQueryBuilderMethod<'whereNotColumn'>
|
|
765
|
+
static whereComposite: StaticQueryBuilderMethod<'whereComposite'>
|
|
766
|
+
static whereInComposite: StaticQueryBuilderMethod<'whereInComposite'>
|
|
767
|
+
// whereNotInComposite: QueryBuilder<Model>['whereNotInComposite']
|
|
768
|
+
static whereJsonHasAny: StaticQueryBuilderMethod<'whereJsonHasAny'>
|
|
769
|
+
static whereJsonHasAll: StaticQueryBuilderMethod<'whereJsonHasAll'>
|
|
770
|
+
static whereJsonIsArray: StaticQueryBuilderMethod<'whereJsonIsArray'>
|
|
771
|
+
static whereJsonNotArray: StaticQueryBuilderMethod<'whereJsonNotArray'>
|
|
772
|
+
static whereJsonIsObject: StaticQueryBuilderMethod<'whereJsonIsObject'>
|
|
773
|
+
static whereJsonNotObject: StaticQueryBuilderMethod<'whereJsonNotObject'>
|
|
774
|
+
static whereJsonSubsetOf: StaticQueryBuilderMethod<'whereJsonSubsetOf'>
|
|
775
|
+
static whereJsonNotSubsetOf: StaticQueryBuilderMethod<'whereJsonNotSubsetOf'>
|
|
776
|
+
static whereJsonSupersetOf: StaticQueryBuilderMethod<'whereJsonSupersetOf'>
|
|
777
|
+
static whereJsonNotSupersetOf:
|
|
778
|
+
StaticQueryBuilderMethod<'whereJsonNotSupersetOf'>
|
|
779
|
+
|
|
780
|
+
static having: StaticQueryBuilderMethod<'having'>
|
|
781
|
+
static havingIn: StaticQueryBuilderMethod<'havingIn'>
|
|
782
|
+
static havingNotIn: StaticQueryBuilderMethod<'havingNotIn'>
|
|
783
|
+
static havingNull: StaticQueryBuilderMethod<'havingNull'>
|
|
784
|
+
static havingNotNull: StaticQueryBuilderMethod<'havingNotNull'>
|
|
785
|
+
static havingExists: StaticQueryBuilderMethod<'havingExists'>
|
|
786
|
+
static havingNotExists: StaticQueryBuilderMethod<'havingNotExists'>
|
|
787
|
+
static havingBetween: StaticQueryBuilderMethod<'havingBetween'>
|
|
788
|
+
static havingNotBetween: StaticQueryBuilderMethod<'havingNotBetween'>
|
|
789
|
+
static havingRaw: StaticQueryBuilderMethod<'havingRaw'>
|
|
790
|
+
static havingWrapped: StaticQueryBuilderMethod<'havingWrapped'>
|
|
791
|
+
|
|
792
|
+
// deprecated methods that are still supported at the moment.
|
|
793
|
+
// TODO: Remove once we move to Objection 3.0
|
|
794
|
+
|
|
795
|
+
static eager: StaticQueryBuilderMethod<'eager'>
|
|
796
|
+
static joinEager: StaticQueryBuilderMethod<'joinEager'>
|
|
797
|
+
static naiveEager: StaticQueryBuilderMethod<'naiveEager'>
|
|
798
|
+
static mergeEager: StaticQueryBuilderMethod<'mergeEager'>
|
|
799
|
+
static mergeJoinEager: StaticQueryBuilderMethod<'mergeJoinEager'>
|
|
800
|
+
static mergeNaiveEager: StaticQueryBuilderMethod<'mergeNaiveEager'>
|
|
801
|
+
static clearEager: StaticQueryBuilderMethod<'clearEager'>
|
|
802
|
+
|
|
803
|
+
// static scope: QueryBuilder<Model>['scope']
|
|
804
|
+
// static mergeScope: QueryBuilder<Model>['mergeScope']
|
|
805
|
+
// static clearScope: QueryBuilder<Model>['clearScope']
|
|
806
|
+
|
|
807
|
+
/* --------------------- End QueryBuilder.mixin(Model) -------------------- */
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
type StaticQueryBuilderMethod<
|
|
811
|
+
K extends ConditionalKeys<QueryBuilder<Model>, (...a: any[]) => any>
|
|
812
|
+
> = <$Model extends Class<Model>>(
|
|
813
|
+
...args: Parameters<QueryBuilder<InstanceType<$Model>>[K]>
|
|
814
|
+
) => ReturnType<QueryBuilder<InstanceType<$Model>>[K]>
|
|
815
|
+
|
|
816
|
+
// @eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
817
|
+
export interface Model extends EventEmitter {}
|
|
818
|
+
export interface Model extends KnexHelper {}
|
|
819
|
+
|
|
820
|
+
export type ModelClass = Class<Model>
|
|
821
|
+
|
|
822
|
+
export type ModelRelations = Record<string, ModelRelation>
|
|
823
|
+
|
|
824
|
+
export type ModelProperties = Record<string, ModelProperty>
|
|
825
|
+
|
|
826
|
+
export type ControllerAction<$Controller extends Controller> =
|
|
827
|
+
| ControllerActionOptions<$Controller>
|
|
828
|
+
| ControllerActionHandler<$Controller>
|
|
829
|
+
|
|
830
|
+
export class Controller {
|
|
831
|
+
app: Application
|
|
832
|
+
/**
|
|
833
|
+
* Optionally provide the controller path. A default is deducted from the
|
|
834
|
+
* normalized class name otherwise.
|
|
835
|
+
*/
|
|
836
|
+
path?: string
|
|
837
|
+
/**
|
|
838
|
+
* The controller's name. If not provided, it is automatically deducted from
|
|
839
|
+
* the controller class name. If this name ends in 'Controller', that is
|
|
840
|
+
* stripped off the name, so 'GreetingsController' turns into 'Greetings'.
|
|
841
|
+
*/
|
|
842
|
+
name?: string
|
|
843
|
+
/**
|
|
844
|
+
* The controller's namespace, which is prepended to path to generate the
|
|
845
|
+
* absolute controller route. Note that it is rare to provide this manually.
|
|
846
|
+
* Usually Dito.js determines the namespace automatically from the controller
|
|
847
|
+
* object passed to the Dito.js application's constructor and its
|
|
848
|
+
* sub-objects.
|
|
849
|
+
*
|
|
850
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/controllers.md#namespaces Namespaces}
|
|
851
|
+
*/
|
|
852
|
+
namespace?: string
|
|
853
|
+
/**
|
|
854
|
+
* A list of allowed actions. If provided, only the action names listed here
|
|
855
|
+
* as strings will be mapped to routes, everything else will be omitted.
|
|
856
|
+
*/
|
|
857
|
+
allow?: OrReadOnly<ControllerActionName[]>
|
|
858
|
+
|
|
859
|
+
/** Authorization */
|
|
860
|
+
authorize?: Authorize
|
|
861
|
+
actions?: ControllerActions<this>
|
|
862
|
+
|
|
863
|
+
initialize(): void
|
|
864
|
+
setup(isRoot: boolean, setupActionsObject: boolean): void
|
|
865
|
+
// TODO: type reflectActionsObject
|
|
866
|
+
reflectActionsObject(): any
|
|
867
|
+
setupRoute<$ControllerAction extends ControllerAction<any>>(
|
|
868
|
+
method: HTTPMethod,
|
|
869
|
+
url: string,
|
|
870
|
+
transacted: boolean,
|
|
871
|
+
authorize: Authorize,
|
|
872
|
+
action: $ControllerAction,
|
|
873
|
+
handlers: ((ctx: KoaContext, next: Function) => void)[]
|
|
874
|
+
): void
|
|
875
|
+
|
|
876
|
+
setupActions(type: string): string[]
|
|
877
|
+
setupActionRoute(type: any, action: any): void
|
|
878
|
+
setupAssets(): any
|
|
879
|
+
setupAssetRoute(
|
|
880
|
+
dataPath: OrArrayOf<string>,
|
|
881
|
+
config: any,
|
|
882
|
+
authorize: Authorize
|
|
883
|
+
): void
|
|
884
|
+
|
|
885
|
+
compose(): Parameters<typeof mount>[1]
|
|
886
|
+
/** To be overridden by sub-classes. */
|
|
887
|
+
getPath(type: string, path: string): string
|
|
888
|
+
getUrl(type: string, path: string): string
|
|
889
|
+
inheritValues(type: string): any
|
|
890
|
+
processValues(values: any): {
|
|
891
|
+
// Create a filtered `values` object that only contains the allowed fields
|
|
892
|
+
values: any
|
|
893
|
+
allow: string[]
|
|
894
|
+
authorize: Authorize
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
emitHook(
|
|
898
|
+
type: string,
|
|
899
|
+
handleResult: any,
|
|
900
|
+
ctx: any,
|
|
901
|
+
...args: any[]
|
|
902
|
+
): Promise<any>
|
|
903
|
+
|
|
904
|
+
processAuthorize(authorize: any): any
|
|
905
|
+
describeAuthorize(authorize: any): string
|
|
906
|
+
handleAuthorization(): Promise<void>
|
|
907
|
+
/**
|
|
908
|
+
* @param str The string to log.
|
|
909
|
+
* @param [indent=0] The amount of levels to indent (in pairs of two spaces).
|
|
910
|
+
* Default is `0`
|
|
911
|
+
*/
|
|
912
|
+
log(str: string, indent?: number): void
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export type ActionParameter = Schema & { name: string }
|
|
916
|
+
|
|
917
|
+
export type ModelControllerActionHandler<
|
|
918
|
+
$ModelController extends ModelController<Model>
|
|
919
|
+
> = (this: $ModelController, ctx: KoaContext, ...args: any[]) => any
|
|
920
|
+
|
|
921
|
+
export type ControllerActionHandler<$Controller extends Controller> = (
|
|
922
|
+
this: $Controller,
|
|
923
|
+
ctx: KoaContext,
|
|
924
|
+
...args: any[]
|
|
925
|
+
) => any
|
|
926
|
+
|
|
927
|
+
export type ExtractModelProperties<$Model> = {
|
|
928
|
+
[$Key in SelectModelPropertyKeys<$Model>]: $Model[$Key] extends Model
|
|
929
|
+
? ExtractModelProperties<$Model[$Key]>
|
|
930
|
+
: $Model[$Key]
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
export type Extends<$A, $B> = $A extends $B ? 1 : 0
|
|
934
|
+
|
|
935
|
+
export type SelectModelPropertyKeys<$Model extends Model> = {
|
|
936
|
+
[K in keyof $Model]-?: K extends
|
|
937
|
+
| 'QueryBuilderType'
|
|
938
|
+
| 'foreignKeyId'
|
|
939
|
+
| `$${string}`
|
|
940
|
+
? never
|
|
941
|
+
: $Model[K] extends Function
|
|
942
|
+
? never
|
|
943
|
+
: K
|
|
944
|
+
}[keyof $Model]
|
|
945
|
+
|
|
946
|
+
export type Authorize =
|
|
947
|
+
| boolean
|
|
948
|
+
| OrArrayOf<LiteralUnion<'$self' | '$owner'>>
|
|
949
|
+
| ((ctx: KoaContext) => OrPromiseOf<Authorize>)
|
|
950
|
+
| Record<HTTPMethod, string | string[]>
|
|
951
|
+
|
|
952
|
+
export type BaseControllerActionOptions = {
|
|
953
|
+
/**
|
|
954
|
+
* The HTTP method (`'get'`, `'post'`, `'put'`, `'delete'` or `'patch'`) to
|
|
955
|
+
* which the action should listen. By default, the `'get'` method is assigned
|
|
956
|
+
* if none is provided.
|
|
957
|
+
*/
|
|
958
|
+
method?: HTTPMethod
|
|
959
|
+
/**
|
|
960
|
+
* The path to which the action is mapped, defined in relation to the route
|
|
961
|
+
* path of its controller. By default, the normalized method name is used as
|
|
962
|
+
* the action's path.
|
|
963
|
+
*/
|
|
964
|
+
path?: string
|
|
965
|
+
/**
|
|
966
|
+
* Determines whether or how the request is authorized. This value can either
|
|
967
|
+
* be one of the values as described below, an array of them or a function
|
|
968
|
+
* which returns one or more of them.
|
|
969
|
+
*
|
|
970
|
+
* - Boolean: `true` if the action should be authorized, `false` otherwise.
|
|
971
|
+
* - '$self': The requested member is checked against `ctx.state.user` and the
|
|
972
|
+
* action is only authorized if it matches the member.
|
|
973
|
+
* - '$owner': The member is asked if it is owned by `ctx.state.user` through
|
|
974
|
+
* the optional `Model.$hasOwner()` method.
|
|
975
|
+
* - Any string: `ctx.state.user` is checked for this role through the
|
|
976
|
+
* overridable `UserModel.hasRole()` method.
|
|
977
|
+
*/
|
|
978
|
+
authorize?: Authorize
|
|
979
|
+
/**
|
|
980
|
+
* Validates action parameters and maps them to Koa's `ctx.query` object
|
|
981
|
+
* passed to the action handler.
|
|
982
|
+
*
|
|
983
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-properties.md Model Properties}
|
|
984
|
+
*/
|
|
985
|
+
parameters?: { [key: string]: Schema }
|
|
986
|
+
/**
|
|
987
|
+
* Provides a schema for the value returned from the action handler and
|
|
988
|
+
* optionally maps the value to a key inside a returned object when it
|
|
989
|
+
* contains a `name` property.
|
|
990
|
+
*
|
|
991
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-properties.md Model Properties}
|
|
992
|
+
*/
|
|
993
|
+
returns?: Schema & { name?: string }
|
|
994
|
+
/**
|
|
995
|
+
* The scope(s) to be applied to every query executed through the action.
|
|
996
|
+
*
|
|
997
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-scopes.md Model Scopes}
|
|
998
|
+
*/
|
|
999
|
+
scope?: string[]
|
|
1000
|
+
/**
|
|
1001
|
+
* Determines whether queries in the action should be executed within a
|
|
1002
|
+
* transaction. Any failure will mean the database will rollback any queries
|
|
1003
|
+
* executed to the pre-transaction state.
|
|
1004
|
+
*/
|
|
1005
|
+
transacted?: boolean
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
export type ControllerActionOptions<$Controller extends Controller> =
|
|
1009
|
+
BaseControllerActionOptions & {
|
|
1010
|
+
handler: ControllerActionHandler<$Controller>
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
export type ModelControllerActionOptions<
|
|
1014
|
+
$ModelController extends ModelController<Model>
|
|
1015
|
+
> = BaseControllerActionOptions & {
|
|
1016
|
+
/** The function to be called when the action route is requested. */
|
|
1017
|
+
handler: ModelControllerActionHandler<$ModelController>
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
export type MemberActionParameter<M extends Model> =
|
|
1021
|
+
| Schema
|
|
1022
|
+
| {
|
|
1023
|
+
member: true
|
|
1024
|
+
|
|
1025
|
+
/** Sets ctx.query. */
|
|
1026
|
+
query?: Record<string, any>
|
|
1027
|
+
/**
|
|
1028
|
+
* Adds a FOR UPDATE in PostgreSQL and MySQL during a select statement.
|
|
1029
|
+
* FOR UPDATE causes the rows retrieved by the SELECT statement to be
|
|
1030
|
+
* locked as though for update. This prevents them from being locked,
|
|
1031
|
+
* modified or deleted by other transactions until the current transaction
|
|
1032
|
+
* ends.
|
|
1033
|
+
*
|
|
1034
|
+
* @default `false`
|
|
1035
|
+
* @see {@link http://knexjs.org/#Builder-forUpdate}
|
|
1036
|
+
* @see {@link https://www.postgresql.org/docs/12/explicit-locking.html#LOCKING-ROWS}
|
|
1037
|
+
*/
|
|
1038
|
+
forUpdate?: boolean
|
|
1039
|
+
/** Modify the member query. */
|
|
1040
|
+
modify?: (query: QueryBuilder<M>) => QueryBuilder<M>
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
export type ModelControllerAction<
|
|
1044
|
+
$ModelController extends ModelController<Model>
|
|
1045
|
+
> =
|
|
1046
|
+
| ModelControllerActionOptions<$ModelController>
|
|
1047
|
+
| ModelControllerActionHandler<$ModelController>
|
|
1048
|
+
|
|
1049
|
+
export type ModelControllerActions<
|
|
1050
|
+
$ModelController extends ModelController<Model> = ModelController<Model>
|
|
1051
|
+
> = {
|
|
1052
|
+
[name: ControllerActionName]: ModelControllerAction<$ModelController>
|
|
1053
|
+
allow?: OrReadOnly<ControllerActionName[]>
|
|
1054
|
+
authorize?: Authorize
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
type ModelControllerMemberAction<
|
|
1058
|
+
$ModelController extends ModelController<Model>
|
|
1059
|
+
> =
|
|
1060
|
+
| (Omit<ModelControllerActionOptions<$ModelController>, 'parameters'> & {
|
|
1061
|
+
parameters?: {
|
|
1062
|
+
[key: string]: MemberActionParameter<
|
|
1063
|
+
modelFromModelController<$ModelController>
|
|
1064
|
+
>
|
|
1065
|
+
}
|
|
1066
|
+
})
|
|
1067
|
+
| ModelControllerActionHandler<$ModelController>
|
|
1068
|
+
|
|
1069
|
+
export type ModelControllerMemberActions<
|
|
1070
|
+
$ModelController extends ModelController<Model>
|
|
1071
|
+
> = {
|
|
1072
|
+
[name: ControllerActionName]: ModelControllerMemberAction<$ModelController>
|
|
1073
|
+
allow?: OrReadOnly<ControllerActionName[]>
|
|
1074
|
+
authorize?: Authorize
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
export type ControllerActionName = `${HTTPMethod}${string}`
|
|
1078
|
+
|
|
1079
|
+
export type ControllerActions<$Controller extends Controller> = {
|
|
1080
|
+
[name: ControllerActionName]: ControllerAction<$Controller>
|
|
1081
|
+
allow?: OrReadOnly<ControllerActionName[]>
|
|
1082
|
+
authorize?: Authorize
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
export class UsersController<M extends Model> extends ModelController<M> {}
|
|
1086
|
+
|
|
1087
|
+
export class AdminController extends Controller {
|
|
1088
|
+
config: AdminConfig
|
|
1089
|
+
mode: 'production' | 'development'
|
|
1090
|
+
closed: boolean
|
|
1091
|
+
koa: Koa
|
|
1092
|
+
getPath(name: string): string
|
|
1093
|
+
getDitoObject(): {
|
|
1094
|
+
base: string
|
|
1095
|
+
api: AdminConfig['api']
|
|
1096
|
+
settings: AdminConfig['settings']
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
sendDitoObject(ctx: Koa.Context): void
|
|
1100
|
+
middleware(): Koa.Middleware
|
|
1101
|
+
setupViteServer(): void
|
|
1102
|
+
getViteConfig(config: UserConfig): UserConfig
|
|
1103
|
+
}
|
|
1104
|
+
type ModelControllerHookType = 'collection' | 'member'
|
|
1105
|
+
type ModelControllerHookKeys<
|
|
1106
|
+
$Keys extends string,
|
|
1107
|
+
$ModelControllerHookType extends string
|
|
1108
|
+
> = `${'before' | 'after' | '*'}:${$ModelControllerHookType | '*'}:${
|
|
1109
|
+
| Exclude<$Keys, 'allow'>
|
|
1110
|
+
| ControllerActionName
|
|
1111
|
+
| '*'}`
|
|
1112
|
+
type ModelControllerHook<
|
|
1113
|
+
$ModelController extends ModelController<Model> = ModelController<Model>
|
|
1114
|
+
> = (
|
|
1115
|
+
ctx: KoaContext,
|
|
1116
|
+
result: objection.Page<modelFromModelController<$ModelController>>
|
|
1117
|
+
) => any
|
|
1118
|
+
|
|
1119
|
+
type HookHandler = () => void
|
|
1120
|
+
|
|
1121
|
+
type HookKeysFromController<$ModelController extends ModelController<Model>> =
|
|
1122
|
+
| ModelControllerHookKeys<
|
|
1123
|
+
Exclude<
|
|
1124
|
+
keyof Exclude<$ModelController['collection'], undefined>,
|
|
1125
|
+
symbol | number
|
|
1126
|
+
>,
|
|
1127
|
+
'collection'
|
|
1128
|
+
>
|
|
1129
|
+
| ModelControllerHookKeys<
|
|
1130
|
+
Exclude<
|
|
1131
|
+
keyof Exclude<$ModelController['member'], undefined>,
|
|
1132
|
+
symbol | number
|
|
1133
|
+
>,
|
|
1134
|
+
'member'
|
|
1135
|
+
>
|
|
1136
|
+
|
|
1137
|
+
type HandlerFromHookKey<
|
|
1138
|
+
$ModelController extends ModelController<Model>,
|
|
1139
|
+
$Key extends HookKeysFromController<$ModelController>
|
|
1140
|
+
> = $Key extends `${'before' | 'after' | '*'}:${
|
|
1141
|
+
| 'collection'
|
|
1142
|
+
| 'member'
|
|
1143
|
+
| '*'}:${string}`
|
|
1144
|
+
? (this: $ModelController, ctx: KoaContext, ...args: any[]) => any
|
|
1145
|
+
: never
|
|
1146
|
+
|
|
1147
|
+
type ModelControllerHooks<
|
|
1148
|
+
$ModelController extends ModelController<Model> = ModelController<Model>
|
|
1149
|
+
> = {
|
|
1150
|
+
[$Key in HookKeysFromController<$ModelController>]?: HandlerFromHookKey<
|
|
1151
|
+
$ModelController,
|
|
1152
|
+
HookKeysFromController<$ModelController>
|
|
1153
|
+
>
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
export type ModelControllerScope = OrArrayOf<string>
|
|
1157
|
+
|
|
1158
|
+
export class ModelController<$Model extends Model = Model> extends Controller {
|
|
1159
|
+
/**
|
|
1160
|
+
* The model class that this controller represents. If none is provided, the
|
|
1161
|
+
* singularized controller name is used to look up the model class in models
|
|
1162
|
+
* registered with the application. As a convention, model controller names
|
|
1163
|
+
* should always be provided in pluralized form.
|
|
1164
|
+
*/
|
|
1165
|
+
modelClass?: Class<$Model>
|
|
1166
|
+
/**
|
|
1167
|
+
* The controller's collection actions. Instead of being provided on the
|
|
1168
|
+
* instance level as in the controller base class, they are to be wrapped in a
|
|
1169
|
+
* designated object in order to be assigned to the collection.
|
|
1170
|
+
*
|
|
1171
|
+
* To limit which collection actions will be mapped to routes, supply an array
|
|
1172
|
+
* of action names under the `allow` key. Only the action names listed there
|
|
1173
|
+
* will be mapped to routes, everything else will be omitted.
|
|
1174
|
+
*/
|
|
1175
|
+
collection?: ModelControllerActions<ModelController<$Model>>
|
|
1176
|
+
/**
|
|
1177
|
+
* The controller's member actions. Instead of being provided on the instance
|
|
1178
|
+
* level as in the controller base class, they are to be wrapped in a
|
|
1179
|
+
* designated object in order to be assigned to the member.
|
|
1180
|
+
*
|
|
1181
|
+
* To limit which member actions will be mapped to routes, supply an array of
|
|
1182
|
+
* action names under the `allow` key. Only the action names listed there will
|
|
1183
|
+
* be mapped to routes, everything else will be omitted.
|
|
1184
|
+
*/
|
|
1185
|
+
member?: ModelControllerMemberActions<ModelController<$Model>>
|
|
1186
|
+
assets?:
|
|
1187
|
+
| boolean
|
|
1188
|
+
| {
|
|
1189
|
+
allow?: OrArrayOf<string>
|
|
1190
|
+
authorize: Record<string, OrArrayOf<string>>
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* When nothing is returned from a hook, the standard action result is used.
|
|
1195
|
+
*/
|
|
1196
|
+
hooks?: ModelControllerHooks<ModelController<$Model>>
|
|
1197
|
+
/**
|
|
1198
|
+
* Controls whether normal database methods should be used, or their …Graph…
|
|
1199
|
+
* counterparts.
|
|
1200
|
+
*
|
|
1201
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-queries.md#graph-methods Model Queries – Graph Methods}
|
|
1202
|
+
*/
|
|
1203
|
+
graph?: boolean
|
|
1204
|
+
/**
|
|
1205
|
+
* The query parameter(s) allowed to be passed to the default model actions,
|
|
1206
|
+
* both on `collection` and `member` level. If none is provided, every
|
|
1207
|
+
* supported parameter is allowed.
|
|
1208
|
+
*
|
|
1209
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-queries.md#find-methods) Model Queries – Find Methods}
|
|
1210
|
+
*/
|
|
1211
|
+
allowParam?: OrArrayOf<LiteralUnion<keyof QueryParameterOptions>>
|
|
1212
|
+
/**
|
|
1213
|
+
* The scope(s) allowed to be requested when passing the 'scope' query
|
|
1214
|
+
* parameter to the default model actions. If none is provided, every
|
|
1215
|
+
* supported scope is allowed.
|
|
1216
|
+
*
|
|
1217
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-scopes.md Model Scopes}
|
|
1218
|
+
*/
|
|
1219
|
+
allowScope?: boolean | OrArrayOf<string>
|
|
1220
|
+
/**
|
|
1221
|
+
* The filter(s) allowed to be requested when passing the 'filter' query
|
|
1222
|
+
* parameter to the default model actions. If none is provided, every
|
|
1223
|
+
* supported filter is allowed.
|
|
1224
|
+
*
|
|
1225
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-filters.md Model Filters}
|
|
1226
|
+
*/
|
|
1227
|
+
allowFilter?: boolean | OrArrayOf<string>
|
|
1228
|
+
/**
|
|
1229
|
+
* The scope(s) to be applied to every query executed through this controller.
|
|
1230
|
+
*
|
|
1231
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-scopes.md Model Scopes}
|
|
1232
|
+
*/
|
|
1233
|
+
scope?: ModelControllerScope
|
|
1234
|
+
query(): QueryBuilder<$Model>
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
export class Validator extends objection.Validator {
|
|
1238
|
+
constructor(schema?: {
|
|
1239
|
+
options?: {
|
|
1240
|
+
/** @defaultValue `false` */
|
|
1241
|
+
async?: boolean
|
|
1242
|
+
/** @defaultValue `false` */
|
|
1243
|
+
patch?: boolean
|
|
1244
|
+
/** @defaultValue `false` */
|
|
1245
|
+
$data?: boolean
|
|
1246
|
+
/** @defaultValue `false` */
|
|
1247
|
+
$comment?: boolean
|
|
1248
|
+
/** @defaultValue `false` */
|
|
1249
|
+
coerceTypes?: boolean
|
|
1250
|
+
/** @defaultValue `false` */
|
|
1251
|
+
multipleOfPrecision?: boolean
|
|
1252
|
+
/** @defaultValue `true` */
|
|
1253
|
+
ownProperties?: boolean
|
|
1254
|
+
/** @defaultValue `false` */
|
|
1255
|
+
removeAdditional?: boolean
|
|
1256
|
+
/** @defaultValue `true` */
|
|
1257
|
+
uniqueItems?: boolean
|
|
1258
|
+
/** @defaultValue `true` */
|
|
1259
|
+
useDefaults?: boolean
|
|
1260
|
+
/** @defaultValue `false` */
|
|
1261
|
+
verbose?: boolean
|
|
1262
|
+
}
|
|
1263
|
+
keywords?: Record<string, Keyword>
|
|
1264
|
+
formats?: Record<string, Format>
|
|
1265
|
+
})
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// NOTE: Because EventEmitter overrides a number of EventEmitter2 methods with
|
|
1269
|
+
// changed signatures, we are unable to extend it.
|
|
1270
|
+
export class EventEmitter {
|
|
1271
|
+
static mixin: (target: any) => {}
|
|
1272
|
+
constructor(options?: EventEmitter2.ConstructorOptions)
|
|
1273
|
+
responds(event: EventEmitter2.event): boolean
|
|
1274
|
+
emit(
|
|
1275
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1276
|
+
...values: any[]
|
|
1277
|
+
): Promise<any[]>
|
|
1278
|
+
|
|
1279
|
+
on(
|
|
1280
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1281
|
+
listener: EventEmitter2.ListenerFn
|
|
1282
|
+
): this
|
|
1283
|
+
|
|
1284
|
+
off(
|
|
1285
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1286
|
+
listener: EventEmitter2.ListenerFn
|
|
1287
|
+
): this
|
|
1288
|
+
|
|
1289
|
+
once(
|
|
1290
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1291
|
+
listener: EventEmitter2.ListenerFn
|
|
1292
|
+
): this
|
|
1293
|
+
|
|
1294
|
+
setupEmitter(
|
|
1295
|
+
events: Record<string, EventEmitter2.ListenerFn>,
|
|
1296
|
+
options: EventEmitter2.ConstructorOptions
|
|
1297
|
+
): void
|
|
1298
|
+
|
|
1299
|
+
// From EventEmitter2:
|
|
1300
|
+
emitAsync(
|
|
1301
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1302
|
+
...values: any[]
|
|
1303
|
+
): Promise<any[]>
|
|
1304
|
+
|
|
1305
|
+
addListener(
|
|
1306
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1307
|
+
listener: EventEmitter2.ListenerFn
|
|
1308
|
+
): this | EventEmitter2.Listener
|
|
1309
|
+
|
|
1310
|
+
prependListener(
|
|
1311
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1312
|
+
listener: EventEmitter2.ListenerFn,
|
|
1313
|
+
options?: boolean | EventEmitter2.OnOptions
|
|
1314
|
+
): this | EventEmitter2.Listener
|
|
1315
|
+
|
|
1316
|
+
prependOnceListener(
|
|
1317
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1318
|
+
listener: EventEmitter2.ListenerFn,
|
|
1319
|
+
options?: boolean | EventEmitter2.OnOptions
|
|
1320
|
+
): this | EventEmitter2.Listener
|
|
1321
|
+
|
|
1322
|
+
many(
|
|
1323
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1324
|
+
timesToListen: number,
|
|
1325
|
+
listener: EventEmitter2.ListenerFn,
|
|
1326
|
+
options?: boolean | EventEmitter2.OnOptions
|
|
1327
|
+
): this | EventEmitter2.Listener
|
|
1328
|
+
|
|
1329
|
+
prependMany(
|
|
1330
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1331
|
+
timesToListen: number,
|
|
1332
|
+
listener: EventEmitter2.ListenerFn,
|
|
1333
|
+
options?: boolean | EventEmitter2.OnOptions
|
|
1334
|
+
): this | EventEmitter2.Listener
|
|
1335
|
+
|
|
1336
|
+
onAny(listener: EventEmitter2.EventAndListener): this
|
|
1337
|
+
prependAny(listener: EventEmitter2.EventAndListener): this
|
|
1338
|
+
offAny(listener: EventEmitter2.ListenerFn): this
|
|
1339
|
+
removeListener(
|
|
1340
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1341
|
+
listener: EventEmitter2.ListenerFn
|
|
1342
|
+
): this
|
|
1343
|
+
|
|
1344
|
+
removeAllListeners(event?: EventEmitter2.event | EventEmitter2.eventNS): this
|
|
1345
|
+
setMaxListeners(n: number): void
|
|
1346
|
+
getMaxListeners(): number
|
|
1347
|
+
eventNames(
|
|
1348
|
+
nsAsArray?: boolean
|
|
1349
|
+
): (EventEmitter2.event | EventEmitter2.eventNS)[]
|
|
1350
|
+
|
|
1351
|
+
listenerCount(event?: EventEmitter2.event | EventEmitter2.eventNS): number
|
|
1352
|
+
listeners(
|
|
1353
|
+
event?: EventEmitter2.event | EventEmitter2.eventNS
|
|
1354
|
+
): EventEmitter2.ListenerFn[]
|
|
1355
|
+
|
|
1356
|
+
listenersAny(): EventEmitter2.ListenerFn[]
|
|
1357
|
+
waitFor(
|
|
1358
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1359
|
+
timeout?: number
|
|
1360
|
+
): EventEmitter2.CancelablePromise<any[]>
|
|
1361
|
+
|
|
1362
|
+
waitFor(
|
|
1363
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1364
|
+
filter?: EventEmitter2.WaitForFilter
|
|
1365
|
+
): EventEmitter2.CancelablePromise<any[]>
|
|
1366
|
+
|
|
1367
|
+
waitFor(
|
|
1368
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1369
|
+
options?: EventEmitter2.WaitForOptions
|
|
1370
|
+
): EventEmitter2.CancelablePromise<any[]>
|
|
1371
|
+
|
|
1372
|
+
listenTo(
|
|
1373
|
+
target: EventEmitter2.GeneralEventEmitter,
|
|
1374
|
+
events: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1375
|
+
options?: EventEmitter2.ListenToOptions
|
|
1376
|
+
): this
|
|
1377
|
+
|
|
1378
|
+
listenTo(
|
|
1379
|
+
target: EventEmitter2.GeneralEventEmitter,
|
|
1380
|
+
events: EventEmitter2.event[],
|
|
1381
|
+
options?: EventEmitter2.ListenToOptions
|
|
1382
|
+
): this
|
|
1383
|
+
|
|
1384
|
+
listenTo(
|
|
1385
|
+
target: EventEmitter2.GeneralEventEmitter,
|
|
1386
|
+
events: Object,
|
|
1387
|
+
options?: EventEmitter2.ListenToOptions
|
|
1388
|
+
): this
|
|
1389
|
+
|
|
1390
|
+
stopListeningTo(
|
|
1391
|
+
target?: EventEmitter2.GeneralEventEmitter,
|
|
1392
|
+
event?: EventEmitter2.event | EventEmitter2.eventNS
|
|
1393
|
+
): Boolean
|
|
1394
|
+
|
|
1395
|
+
hasListeners(event?: String): Boolean
|
|
1396
|
+
static once(
|
|
1397
|
+
emitter: EventEmitter2.EventEmitter2,
|
|
1398
|
+
event: EventEmitter2.event | EventEmitter2.eventNS,
|
|
1399
|
+
options?: EventEmitter2.OnceOptions
|
|
1400
|
+
): EventEmitter2.CancelablePromise<any[]>
|
|
1401
|
+
|
|
1402
|
+
static defaultMaxListeners: number
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
export interface DitoGraphOptions {
|
|
1406
|
+
fetchStrategy?: 'OnlyNeeded' | 'OnlyIdentifiers' | 'Everything'
|
|
1407
|
+
relate?: boolean
|
|
1408
|
+
allowRefs?: boolean
|
|
1409
|
+
insertMissing?: boolean
|
|
1410
|
+
unrelate?: boolean
|
|
1411
|
+
update?: boolean
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
export type QueryParameterOptions = {
|
|
1415
|
+
scope?: OrArrayOf<string>
|
|
1416
|
+
filter?: OrArrayOf<string>
|
|
1417
|
+
/**
|
|
1418
|
+
* A range between two numbers. When expressed as a string, the value is split
|
|
1419
|
+
* at the ',' character ignoring any spaces on either side. i.e. `'1,2'` and
|
|
1420
|
+
* `'1 , 2'`
|
|
1421
|
+
*/
|
|
1422
|
+
range?: [number, number] | string
|
|
1423
|
+
limit?: number
|
|
1424
|
+
offset?: number
|
|
1425
|
+
order?: 'asc' | 'desc'
|
|
1426
|
+
}
|
|
1427
|
+
export type QueryParameterOptionKey = keyof QueryParameterOptions
|
|
1428
|
+
|
|
1429
|
+
export class Service {
|
|
1430
|
+
constructor(app: Application<Models>, name?: string)
|
|
1431
|
+
|
|
1432
|
+
setup(config: any): void
|
|
1433
|
+
|
|
1434
|
+
initialize(): void
|
|
1435
|
+
|
|
1436
|
+
start(): Promise<void>
|
|
1437
|
+
|
|
1438
|
+
stop(): Promise<void>
|
|
1439
|
+
}
|
|
1440
|
+
export type Services = Record<string, Class<Service> | Service>
|
|
1441
|
+
|
|
1442
|
+
export class QueryBuilder<
|
|
1443
|
+
M extends Model,
|
|
1444
|
+
R = M[]
|
|
1445
|
+
> extends objection.QueryBuilder<M, R> {
|
|
1446
|
+
/**
|
|
1447
|
+
* Returns true if the query defines normal selects: select(), column(),
|
|
1448
|
+
* columns()
|
|
1449
|
+
*/
|
|
1450
|
+
hasNormalSelects: () => boolean
|
|
1451
|
+
/**
|
|
1452
|
+
* Returns true if the query defines special selects: distinct(), count(),
|
|
1453
|
+
* countDistinct(), min(), max(), sum(), sumDistinct(), avg(), avgDistinct()
|
|
1454
|
+
*/
|
|
1455
|
+
hasSpecialSelects: () => boolean
|
|
1456
|
+
withScope: (...scopes: string[]) => this
|
|
1457
|
+
/**
|
|
1458
|
+
* Clear all scopes defined with `withScope()` statements, preserving the
|
|
1459
|
+
* default scope.
|
|
1460
|
+
*/
|
|
1461
|
+
clearWithScope: () => this
|
|
1462
|
+
ignoreScope: (...scopes: string[]) => this
|
|
1463
|
+
applyScope: (...scopes: string[]) => this
|
|
1464
|
+
allowScope: (...scopes: string[]) => void
|
|
1465
|
+
clearAllowScope: () => void
|
|
1466
|
+
applyFilter: (name: string, ...args: any[]) => this
|
|
1467
|
+
allowFilter: (...filters: string[]) => void
|
|
1468
|
+
withGraph: (
|
|
1469
|
+
expr: objection.RelationExpression<M>,
|
|
1470
|
+
options?: objection.GraphOptions & { algorithm: 'fetch' | 'join' }
|
|
1471
|
+
) => this
|
|
1472
|
+
|
|
1473
|
+
toSQL: () => string
|
|
1474
|
+
raw: Knex.RawBuilder
|
|
1475
|
+
selectRaw: SetReturnType<Knex.RawBuilder, this>
|
|
1476
|
+
// TODO: add type for Dito's pluck method, which has a different method
|
|
1477
|
+
// signature than the objection one:
|
|
1478
|
+
// pluck: <K extends objection.ModelProps<M>>(
|
|
1479
|
+
// key: K
|
|
1480
|
+
// ) => QueryBuilder<M, ReflectArrayType<R, M[K]>>
|
|
1481
|
+
loadDataPath: (
|
|
1482
|
+
dataPath: string[] | string,
|
|
1483
|
+
options: objection.GraphOptions & { algorithm: 'fetch' | 'join' }
|
|
1484
|
+
) => this
|
|
1485
|
+
|
|
1486
|
+
upsert: (
|
|
1487
|
+
data: PartialModelObject<M>,
|
|
1488
|
+
options?: {
|
|
1489
|
+
update: boolean
|
|
1490
|
+
fetch: boolean
|
|
1491
|
+
}
|
|
1492
|
+
) => this
|
|
1493
|
+
|
|
1494
|
+
find: (
|
|
1495
|
+
query: QueryParameterOptions,
|
|
1496
|
+
allowParam?:
|
|
1497
|
+
| QueryParameterOptionKey[]
|
|
1498
|
+
| { [key in keyof QueryParameterOptionKey]: boolean }
|
|
1499
|
+
) => this
|
|
1500
|
+
|
|
1501
|
+
patchById: (id: Id, data: PartialModelObject<M>) => this
|
|
1502
|
+
updateById: (id: Id, data: PartialModelObject<M>) => this
|
|
1503
|
+
upsertAndFetch: (data: PartialModelObject<M>) => this
|
|
1504
|
+
insertDitoGraph: (
|
|
1505
|
+
data: PartialDitoModelGraph<M>,
|
|
1506
|
+
options?: DitoGraphOptions
|
|
1507
|
+
) => this
|
|
1508
|
+
|
|
1509
|
+
insertDitoGraphAndFetch: (
|
|
1510
|
+
data: PartialDitoModelGraph<M>,
|
|
1511
|
+
options?: DitoGraphOptions
|
|
1512
|
+
) => this
|
|
1513
|
+
|
|
1514
|
+
upsertDitoGraph: (
|
|
1515
|
+
data: PartialDitoModelGraph<M>,
|
|
1516
|
+
options?: DitoGraphOptions
|
|
1517
|
+
) => this
|
|
1518
|
+
|
|
1519
|
+
upsertDitoGraphAndFetch: (data: any, options?: DitoGraphOptions) => this
|
|
1520
|
+
upsertDitoGraphAndFetchById: (
|
|
1521
|
+
id: Id,
|
|
1522
|
+
data: any,
|
|
1523
|
+
options?: DitoGraphOptions
|
|
1524
|
+
) => QueryBuilder<M, M>
|
|
1525
|
+
|
|
1526
|
+
updateDitoGraph: (
|
|
1527
|
+
data: PartialDitoModelGraph<M>,
|
|
1528
|
+
options?: DitoGraphOptions
|
|
1529
|
+
) => Promise<any>
|
|
1530
|
+
|
|
1531
|
+
updateDitoGraphAndFetch: (
|
|
1532
|
+
data: PartialDitoModelGraph<M>,
|
|
1533
|
+
options?: DitoGraphOptions
|
|
1534
|
+
) => this
|
|
1535
|
+
|
|
1536
|
+
updateDitoGraphAndFetchById: (
|
|
1537
|
+
id: Id,
|
|
1538
|
+
data: any,
|
|
1539
|
+
options?: DitoGraphOptions
|
|
1540
|
+
) => QueryBuilder<M, M>
|
|
1541
|
+
|
|
1542
|
+
patchDitoGraph: (
|
|
1543
|
+
data: PartialDitoModelGraph<M>,
|
|
1544
|
+
options?: DitoGraphOptions
|
|
1545
|
+
) => this
|
|
1546
|
+
|
|
1547
|
+
patchDitoGraphAndFetch: (
|
|
1548
|
+
data: PartialDitoModelGraph<M>,
|
|
1549
|
+
options?: DitoGraphOptions
|
|
1550
|
+
) => this
|
|
1551
|
+
|
|
1552
|
+
patchDitoGraphAndFetchById: (
|
|
1553
|
+
id: Id,
|
|
1554
|
+
data: PartialDitoModelGraph<M>,
|
|
1555
|
+
options?: DitoGraphOptions
|
|
1556
|
+
) => QueryBuilder<M, M>
|
|
1557
|
+
// TODO: static mixin(target)
|
|
1558
|
+
|
|
1559
|
+
ArrayQueryBuilderType: QueryBuilder<M, M[]>
|
|
1560
|
+
SingleQueryBuilderType: QueryBuilder<M, M>
|
|
1561
|
+
NumberQueryBuilderType: QueryBuilder<M, number>
|
|
1562
|
+
PageQueryBuilderType: QueryBuilder<M, objection.Page<M>>
|
|
1563
|
+
}
|
|
1564
|
+
export interface QueryBuilder<M extends Model, R = M[]> extends KnexHelper {}
|
|
1565
|
+
|
|
1566
|
+
export type PartialModelObject<T extends Model> = {
|
|
1567
|
+
[K in objection.NonFunctionPropertyNames<T>]?: objection.Defined<
|
|
1568
|
+
T[K]
|
|
1569
|
+
> extends Model
|
|
1570
|
+
? T[K]
|
|
1571
|
+
: objection.Defined<T[K]> extends Array<infer I>
|
|
1572
|
+
? I extends Model
|
|
1573
|
+
? I[]
|
|
1574
|
+
: objection.Expression<T[K]>
|
|
1575
|
+
: objection.Expression<T[K]>
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
export type PartialDitoModelGraph<M extends Partial<Model>> = {
|
|
1579
|
+
[K in objection.NonFunctionPropertyNames<M>]?: objection.Defined<
|
|
1580
|
+
M[K]
|
|
1581
|
+
> extends Model
|
|
1582
|
+
? PartialDitoModelGraph<M[K]>
|
|
1583
|
+
: objection.Defined<M[K]> extends Array<infer I>
|
|
1584
|
+
? I extends Partial<Model>
|
|
1585
|
+
? PartialDitoModelGraph<I>[]
|
|
1586
|
+
: M[K]
|
|
1587
|
+
: M[K]
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
/* ------------------------------ Start Errors ----------------------------- */
|
|
1591
|
+
export class ResponseError extends Error {
|
|
1592
|
+
constructor()
|
|
1593
|
+
constructor(
|
|
1594
|
+
error:
|
|
1595
|
+
| {
|
|
1596
|
+
/** The http status code. */
|
|
1597
|
+
status: number
|
|
1598
|
+
/** The error message. */
|
|
1599
|
+
message?: string
|
|
1600
|
+
/**
|
|
1601
|
+
* An optional code to be used to distinguish different error
|
|
1602
|
+
* instances.
|
|
1603
|
+
*/
|
|
1604
|
+
code?: string | number
|
|
1605
|
+
}
|
|
1606
|
+
| string,
|
|
1607
|
+
defaults?: { message?: string; status?: number }
|
|
1608
|
+
)
|
|
1609
|
+
|
|
1610
|
+
status: number
|
|
1611
|
+
code?: string | number
|
|
1612
|
+
}
|
|
1613
|
+
export class AssetError extends ResponseError {}
|
|
1614
|
+
export class AuthenticationError extends ResponseError {}
|
|
1615
|
+
export class AuthorizationError extends ResponseError {}
|
|
1616
|
+
export class WrappedError extends ResponseError {}
|
|
1617
|
+
export class DatabaseError extends WrappedError {
|
|
1618
|
+
constructor(
|
|
1619
|
+
error:
|
|
1620
|
+
| dbErrors.CheckViolationError
|
|
1621
|
+
| dbErrors.NotNullViolationError
|
|
1622
|
+
| dbErrors.ConstraintViolationError
|
|
1623
|
+
| dbErrors.DataError
|
|
1624
|
+
| dbErrors.DBError
|
|
1625
|
+
)
|
|
1626
|
+
}
|
|
1627
|
+
export class GraphError extends ResponseError {}
|
|
1628
|
+
export class ModelError extends ResponseError {
|
|
1629
|
+
constructor(model: Class<Model> | Model)
|
|
1630
|
+
}
|
|
1631
|
+
export class NotFoundError extends ResponseError {}
|
|
1632
|
+
export class NotImplementedError extends ResponseError {}
|
|
1633
|
+
export class QueryBuilderError extends ResponseError {}
|
|
1634
|
+
export class RelationError extends ResponseError {}
|
|
1635
|
+
export class ValidationError extends ResponseError {}
|
|
1636
|
+
export class ControllerError extends ResponseError {
|
|
1637
|
+
constructor(controller: { name: string } | { constructor: { name: string } })
|
|
1638
|
+
}
|
|
1639
|
+
/* ------------------------------- End Errors ------------------------------ */
|
|
1640
|
+
|
|
1641
|
+
/* ------------------------------ Start Mixins ----------------------------- */
|
|
1642
|
+
export type Mixin = (
|
|
1643
|
+
target: Object,
|
|
1644
|
+
propertyName: string,
|
|
1645
|
+
propertyDescriptor: PropertyDescriptor
|
|
1646
|
+
) => void
|
|
1647
|
+
|
|
1648
|
+
type AssetFileObject = {
|
|
1649
|
+
// The unique key within the storage (uuid/v4 + file extension)
|
|
1650
|
+
key: string
|
|
1651
|
+
// The original filename
|
|
1652
|
+
name: string
|
|
1653
|
+
// The file's mime-type
|
|
1654
|
+
type: string
|
|
1655
|
+
// The amount of bytes consumed by the file
|
|
1656
|
+
size: number
|
|
1657
|
+
// The public url of the file
|
|
1658
|
+
url: string
|
|
1659
|
+
// The width of the image if the storage defines `config.readImageSize`
|
|
1660
|
+
width: number
|
|
1661
|
+
// The height of the image if the storage defines `config.readImageSize`
|
|
1662
|
+
height: number
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
export class AssetModel extends TimeStampedModel {
|
|
1666
|
+
key: string
|
|
1667
|
+
file: AssetFileObject
|
|
1668
|
+
storage: string
|
|
1669
|
+
count: number
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
export const AssetMixin: <T extends Constructor>(
|
|
1673
|
+
target: T
|
|
1674
|
+
) => Constructor<
|
|
1675
|
+
InstanceType<T> & {
|
|
1676
|
+
key: string
|
|
1677
|
+
file: AssetFileObject
|
|
1678
|
+
storage: string
|
|
1679
|
+
count: number
|
|
1680
|
+
}
|
|
1681
|
+
>
|
|
1682
|
+
|
|
1683
|
+
export class TimeStampedModel extends Model {
|
|
1684
|
+
createdAt: Date
|
|
1685
|
+
updatedAt: Date
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
export const TimeStampedMixin: <T extends Constructor>(
|
|
1689
|
+
target: T
|
|
1690
|
+
) => Constructor<InstanceType<T> & {
|
|
1691
|
+
createdAt: Date
|
|
1692
|
+
updatedAt: Date
|
|
1693
|
+
}>
|
|
1694
|
+
|
|
1695
|
+
export class UserModel extends Model {
|
|
1696
|
+
static options?: {
|
|
1697
|
+
usernameProperty?: string
|
|
1698
|
+
passwordProperty?: string
|
|
1699
|
+
/**
|
|
1700
|
+
* This option can be used to specify (eager) scopes to be applied when the
|
|
1701
|
+
* user is deserialized from the session.
|
|
1702
|
+
*/
|
|
1703
|
+
sessionScope?: OrArrayOf<string>
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
username: string
|
|
1707
|
+
password: string
|
|
1708
|
+
hash: string
|
|
1709
|
+
lastLogin?: Date
|
|
1710
|
+
|
|
1711
|
+
$verifyPassword(password: string): Promise<boolean>
|
|
1712
|
+
|
|
1713
|
+
$hasRole(...roles: string[]): boolean
|
|
1714
|
+
|
|
1715
|
+
$hasOwner(owner: UserModel): boolean
|
|
1716
|
+
|
|
1717
|
+
$isLoggedIn(ctx: KoaContext): boolean
|
|
1718
|
+
|
|
1719
|
+
// TODO: type options
|
|
1720
|
+
static login(ctx: KoaContext, options: any): Promise<void>
|
|
1721
|
+
|
|
1722
|
+
static sessionQuery(trx: Knex.Transaction): QueryBuilder<UserModel>
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
export class SessionModel extends Model {
|
|
1726
|
+
id: string
|
|
1727
|
+
value: { [key: string]: any }
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
export const SessionMixin: <T extends Constructor>(
|
|
1731
|
+
target: T
|
|
1732
|
+
) => Constructor<InstanceType<T> & {
|
|
1733
|
+
id: string
|
|
1734
|
+
value: { [key: string]: any }
|
|
1735
|
+
}>
|
|
1736
|
+
|
|
1737
|
+
export const UserMixin: <T extends Constructor>(
|
|
1738
|
+
target: T
|
|
1739
|
+
) => Constructor<
|
|
1740
|
+
InstanceType<T> & {
|
|
1741
|
+
id: string
|
|
1742
|
+
value: { [key: string]: any }
|
|
1743
|
+
}
|
|
1744
|
+
>
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Apply the action mixin to a controller action, in order to determine which
|
|
1748
|
+
* HTTP method (`'get'`, `'post'`, `'put'`, `'delete'` or `'patch'`) the action
|
|
1749
|
+
* should listen to and optionally the path to which it is mapped, defined in
|
|
1750
|
+
* relation to the route path of its controller. By default, the normalized
|
|
1751
|
+
* method name is used as the action's path, and the `'get'` method is assigned
|
|
1752
|
+
* if none is provided.
|
|
1753
|
+
*/
|
|
1754
|
+
export const action: (method: string, path: string) => Mixin
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Apply the authorize mixin to a controller action, in order to determines
|
|
1758
|
+
* whether or how the request is authorized. This value can either be one of the
|
|
1759
|
+
* values as described below, an array of them or a function which returns one
|
|
1760
|
+
* or more of them.
|
|
1761
|
+
*
|
|
1762
|
+
* - Boolean: `true` if the action should be authorized, `false` otherwise.
|
|
1763
|
+
* - '$self': The requested member is checked against `ctx.state.user` and the
|
|
1764
|
+
* action is only authorized if it matches the member.
|
|
1765
|
+
* - '$owner': The member is asked if it is owned by `ctx.state.user` through
|
|
1766
|
+
* the optional `Model.$hasOwner()` method.
|
|
1767
|
+
* - Any string: `ctx.state.user` is checked for this role through the
|
|
1768
|
+
* overridable `UserModel.hasRole()` method.
|
|
1769
|
+
*/
|
|
1770
|
+
export const authorize: (
|
|
1771
|
+
authorize: (ctx: KoaContext) => void | boolean | OrArrayOf<string>
|
|
1772
|
+
) => Mixin
|
|
1773
|
+
|
|
1774
|
+
/**
|
|
1775
|
+
* Apply the parameters mixin to a controller action, in order to apply
|
|
1776
|
+
* automatic mapping of Koa.js' `ctx.query` object to method parameters along
|
|
1777
|
+
* with their automatic validation.
|
|
1778
|
+
*
|
|
1779
|
+
* @see {@link https://github.com/ditojs/dito/blob/master/docs/model-properties.md Model Properties}
|
|
1780
|
+
*/
|
|
1781
|
+
export const parameters: (params: { [key: string]: Schema }) => Mixin
|
|
1782
|
+
|
|
1783
|
+
/**
|
|
1784
|
+
* Apply the returns mixin to a controller action, in order to provide a schema
|
|
1785
|
+
* for the value returned from the action handler and optionally map the value
|
|
1786
|
+
* to a key inside a returned object when it contains a `name` property.
|
|
1787
|
+
*/
|
|
1788
|
+
export const returns: (
|
|
1789
|
+
returns: Schema & { name?: string },
|
|
1790
|
+
options: any
|
|
1791
|
+
) => Mixin
|
|
1792
|
+
|
|
1793
|
+
/**
|
|
1794
|
+
* Apply the scope mixin to a controller action, in order to determine the
|
|
1795
|
+
* scope(s) to be applied when loading the relation's models. The scope needs to
|
|
1796
|
+
* be defined in the related model class' scopes definitions.
|
|
1797
|
+
*/
|
|
1798
|
+
export const scope: (...scopes: string[]) => Mixin
|
|
1799
|
+
|
|
1800
|
+
/**
|
|
1801
|
+
* Apply the transacted mixin to a controller action in order to determine
|
|
1802
|
+
* whether queries in the action should be executed within a transaction. Any
|
|
1803
|
+
* failure will mean the database will rollback any queries executed to the
|
|
1804
|
+
* pre-transaction state.
|
|
1805
|
+
*/
|
|
1806
|
+
export const transacted: () => Mixin
|
|
1807
|
+
|
|
1808
|
+
/* ------------------------------ End Mixins ----------------------------- */
|
|
1809
|
+
|
|
1810
|
+
export type HTTPMethod =
|
|
1811
|
+
| 'get'
|
|
1812
|
+
| 'post'
|
|
1813
|
+
| 'put'
|
|
1814
|
+
| 'delete'
|
|
1815
|
+
| 'patch'
|
|
1816
|
+
| 'options'
|
|
1817
|
+
| 'trace'
|
|
1818
|
+
| 'connect'
|
|
1819
|
+
|
|
1820
|
+
export interface KnexHelper {
|
|
1821
|
+
getDialect(): string
|
|
1822
|
+
|
|
1823
|
+
isPostgreSQL(): boolean
|
|
1824
|
+
|
|
1825
|
+
isMySQL(): boolean
|
|
1826
|
+
|
|
1827
|
+
isSQLite(): boolean
|
|
1828
|
+
|
|
1829
|
+
isMsSQL(): boolean
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
export type Keyword =
|
|
1833
|
+
| SetOptional<Ajv.MacroKeywordDefinition, 'keyword'>
|
|
1834
|
+
| SetOptional<Ajv.CodeKeywordDefinition, 'keyword'>
|
|
1835
|
+
| SetOptional<Ajv.FuncKeywordDefinition, 'keyword'>
|
|
1836
|
+
export type Format = Ajv.ValidateFunction | Ajv.FormatDefinition<string>
|
|
1837
|
+
export type Id = string | number
|
|
1838
|
+
export type KoaContext<$State = any> = Koa.ParameterizedContext<
|
|
1839
|
+
$State,
|
|
1840
|
+
{
|
|
1841
|
+
transaction: objection.Transaction
|
|
1842
|
+
session: koaSession.ContextSession & { state: { user: any } }
|
|
1843
|
+
}
|
|
1844
|
+
>
|
|
1845
|
+
|
|
1846
|
+
type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>)
|
|
1847
|
+
|
|
1848
|
+
type ReflectArrayType<Source, Target> = Source extends any[] ? Target[] : Target
|
|
1849
|
+
|
|
1850
|
+
type OrArrayOf<T> = T[] | T
|
|
1851
|
+
|
|
1852
|
+
type OrReadOnly<T> = Readonly<T> | T
|
|
1853
|
+
|
|
1854
|
+
type OrPromiseOf<T> = Promise<T> | T
|
|
1855
|
+
|
|
1856
|
+
type modelFromModelController<$ModelController extends ModelController<Model>> =
|
|
1857
|
+
InstanceType<Exclude<$ModelController['modelClass'], undefined>>
|
|
1858
|
+
|
|
1859
|
+
export type SelectModelProperties<T> = {
|
|
1860
|
+
[$Key in SelectModelKeys<T>]: T[$Key] extends Model
|
|
1861
|
+
? SelectModelProperties<T[$Key]>
|
|
1862
|
+
: T[$Key]
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360
|
|
1866
|
+
type AnyGate<
|
|
1867
|
+
$CheckType,
|
|
1868
|
+
$TypeWhenNotAny,
|
|
1869
|
+
$TypeWhenAny = $CheckType
|
|
1870
|
+
> = 0 extends 1 & $CheckType ? $TypeWhenAny : $TypeWhenNotAny
|
|
1871
|
+
|
|
1872
|
+
export type SelectModelKeys<T> = AnyGate<
|
|
1873
|
+
T,
|
|
1874
|
+
Exclude<
|
|
1875
|
+
keyof ConditionalExcept<T, Function>,
|
|
1876
|
+
`$${string}` | 'QueryBuilderType' | 'foreignKeyId'
|
|
1877
|
+
>,
|
|
1878
|
+
string
|
|
1879
|
+
>
|
|
1880
|
+
|
|
1881
|
+
/* ---------------------- Extended from Ajv JSON Schema --------------------- */
|
|
1882
|
+
|
|
1883
|
+
export type Schema<T = any> = JSONSchemaType<T> & {
|
|
1884
|
+
// keywords/_validate.js
|
|
1885
|
+
validate?: (params: {
|
|
1886
|
+
data: any
|
|
1887
|
+
parentData: object | any[]
|
|
1888
|
+
rootData: object | any[]
|
|
1889
|
+
dataPath: string
|
|
1890
|
+
parentIndex?: number
|
|
1891
|
+
parentKey?: string
|
|
1892
|
+
app: Application<Models>
|
|
1893
|
+
validator: Validator
|
|
1894
|
+
options: any
|
|
1895
|
+
}) => boolean | void
|
|
1896
|
+
|
|
1897
|
+
// keywords/_validate.js
|
|
1898
|
+
validateAsync?: (params: {
|
|
1899
|
+
data: any
|
|
1900
|
+
parentData: object | any[]
|
|
1901
|
+
rootData: object | any[]
|
|
1902
|
+
dataPath: string
|
|
1903
|
+
parentIndex?: number
|
|
1904
|
+
parentKey?: string
|
|
1905
|
+
app: Application<Models>
|
|
1906
|
+
validator: Validator
|
|
1907
|
+
options: any
|
|
1908
|
+
}) => Promise<boolean | void>
|
|
1909
|
+
|
|
1910
|
+
// keywords/_instanceof.js
|
|
1911
|
+
/**
|
|
1912
|
+
* Validates whether the value is an instance of at least one of the passed
|
|
1913
|
+
* types.
|
|
1914
|
+
*/
|
|
1915
|
+
instanceof?: OrArrayOf<
|
|
1916
|
+
| LiteralUnion<
|
|
1917
|
+
| 'Object'
|
|
1918
|
+
| 'Array'
|
|
1919
|
+
| 'Function'
|
|
1920
|
+
| 'String'
|
|
1921
|
+
| 'Number'
|
|
1922
|
+
| 'Boolean'
|
|
1923
|
+
| 'Date'
|
|
1924
|
+
| 'RegExp'
|
|
1925
|
+
| 'Buffer'
|
|
1926
|
+
>
|
|
1927
|
+
| Function
|
|
1928
|
+
| typeof Object
|
|
1929
|
+
| typeof Array
|
|
1930
|
+
| typeof Function
|
|
1931
|
+
| typeof String
|
|
1932
|
+
| typeof Number
|
|
1933
|
+
| typeof Boolean
|
|
1934
|
+
| typeof Date
|
|
1935
|
+
| typeof RegExp
|
|
1936
|
+
| typeof Buffer
|
|
1937
|
+
>
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
declare type StrictNullChecksWrapper<
|
|
1941
|
+
Name extends string,
|
|
1942
|
+
Type
|
|
1943
|
+
> = undefined extends null
|
|
1944
|
+
? `strictNullChecks must be true in tsconfig to use ${Name}`
|
|
1945
|
+
: Type
|
|
1946
|
+
declare type UnionToIntersection<U> = (
|
|
1947
|
+
U extends any ? (_: U) => void : never
|
|
1948
|
+
) extends (_: infer I) => void
|
|
1949
|
+
? I
|
|
1950
|
+
: never
|
|
1951
|
+
declare type SomeJSONSchema = UncheckedJSONSchemaType<Known, true>
|
|
1952
|
+
declare type UncheckedPartialSchema<T> = Partial<
|
|
1953
|
+
UncheckedJSONSchemaType<T, true>
|
|
1954
|
+
>
|
|
1955
|
+
declare type PartialSchema<T> = StrictNullChecksWrapper<
|
|
1956
|
+
'PartialSchema',
|
|
1957
|
+
UncheckedPartialSchema<T>
|
|
1958
|
+
>
|
|
1959
|
+
declare type JSONType<
|
|
1960
|
+
T extends string,
|
|
1961
|
+
IsPartial extends boolean
|
|
1962
|
+
> = IsPartial extends true ? T | undefined : T
|
|
1963
|
+
interface NumberKeywords {
|
|
1964
|
+
minimum?: number
|
|
1965
|
+
maximum?: number
|
|
1966
|
+
exclusiveMinimum?: number
|
|
1967
|
+
exclusiveMaximum?: number
|
|
1968
|
+
multipleOf?: number
|
|
1969
|
+
format?: string
|
|
1970
|
+
range?: [number, number]
|
|
1971
|
+
}
|
|
1972
|
+
interface StringKeywords {
|
|
1973
|
+
minLength?: number
|
|
1974
|
+
maxLength?: number
|
|
1975
|
+
pattern?: string
|
|
1976
|
+
format?: LiteralUnion<
|
|
1977
|
+
| 'date'
|
|
1978
|
+
| 'time'
|
|
1979
|
+
| 'uri'
|
|
1980
|
+
| 'uri-reference'
|
|
1981
|
+
| 'uri-template'
|
|
1982
|
+
| 'email'
|
|
1983
|
+
| 'hostname'
|
|
1984
|
+
| 'ipv4'
|
|
1985
|
+
| 'ipv6'
|
|
1986
|
+
| 'uuid'
|
|
1987
|
+
| 'json-pointer'
|
|
1988
|
+
| 'relative-json-pointer'
|
|
1989
|
+
| 'datetime'
|
|
1990
|
+
| 'timestamp'
|
|
1991
|
+
>
|
|
1992
|
+
}
|
|
1993
|
+
declare type UncheckedJSONSchemaType<
|
|
1994
|
+
T,
|
|
1995
|
+
IsPartial extends boolean
|
|
1996
|
+
> = // these two unions allow arbitrary unions of types
|
|
1997
|
+
(| {
|
|
1998
|
+
anyOf: readonly UncheckedJSONSchemaType<T, IsPartial>[]
|
|
1999
|
+
}
|
|
2000
|
+
| {
|
|
2001
|
+
oneOf: readonly UncheckedJSONSchemaType<T, IsPartial>[]
|
|
2002
|
+
}
|
|
2003
|
+
| ({
|
|
2004
|
+
type: readonly (T extends number
|
|
2005
|
+
? JSONType<'number' | 'integer', IsPartial>
|
|
2006
|
+
: T extends string
|
|
2007
|
+
? JSONType<'string', IsPartial>
|
|
2008
|
+
: T extends boolean
|
|
2009
|
+
? JSONType<'boolean', IsPartial>
|
|
2010
|
+
: never)[]
|
|
2011
|
+
} & UnionToIntersection<
|
|
2012
|
+
T extends number
|
|
2013
|
+
? NumberKeywords
|
|
2014
|
+
: T extends string
|
|
2015
|
+
? StringKeywords
|
|
2016
|
+
: T extends boolean
|
|
2017
|
+
? {}
|
|
2018
|
+
: never
|
|
2019
|
+
>)
|
|
2020
|
+
| ((T extends number
|
|
2021
|
+
? {
|
|
2022
|
+
type: JSONType<'number' | 'integer', IsPartial>
|
|
2023
|
+
} & NumberKeywords
|
|
2024
|
+
: T extends string
|
|
2025
|
+
? {
|
|
2026
|
+
type: JSONType<
|
|
2027
|
+
'string' | 'text' | 'date' | 'datetime' | 'timestamp',
|
|
2028
|
+
IsPartial
|
|
2029
|
+
>
|
|
2030
|
+
} & StringKeywords
|
|
2031
|
+
: T extends Date
|
|
2032
|
+
? {
|
|
2033
|
+
type: JSONType<'date' | 'datetime' | 'timestamp', IsPartial>
|
|
2034
|
+
}
|
|
2035
|
+
: T extends boolean
|
|
2036
|
+
? {
|
|
2037
|
+
type: JSONType<'boolean', IsPartial>
|
|
2038
|
+
}
|
|
2039
|
+
: T extends readonly [any, ...any[]]
|
|
2040
|
+
? {
|
|
2041
|
+
type: JSONType<'array', IsPartial>
|
|
2042
|
+
items: {
|
|
2043
|
+
readonly [K in keyof T]-?: UncheckedJSONSchemaType<T[K], false> &
|
|
2044
|
+
Nullable<T[K]>
|
|
2045
|
+
} & {
|
|
2046
|
+
length: T['length']
|
|
2047
|
+
}
|
|
2048
|
+
minItems: T['length']
|
|
2049
|
+
} & (
|
|
2050
|
+
| {
|
|
2051
|
+
maxItems: T['length']
|
|
2052
|
+
}
|
|
2053
|
+
| {
|
|
2054
|
+
additionalItems: false
|
|
2055
|
+
}
|
|
2056
|
+
)
|
|
2057
|
+
: T extends readonly any[]
|
|
2058
|
+
? {
|
|
2059
|
+
type: JSONType<'array', IsPartial>
|
|
2060
|
+
items: UncheckedJSONSchemaType<T[0], false>
|
|
2061
|
+
contains?: UncheckedPartialSchema<T[0]>
|
|
2062
|
+
minItems?: number
|
|
2063
|
+
maxItems?: number
|
|
2064
|
+
minContains?: number
|
|
2065
|
+
maxContains?: number
|
|
2066
|
+
uniqueItems?: true
|
|
2067
|
+
additionalItems?: never
|
|
2068
|
+
}
|
|
2069
|
+
: T extends Record<string, any>
|
|
2070
|
+
? {
|
|
2071
|
+
type: JSONType<'object', IsPartial>
|
|
2072
|
+
additionalProperties?:
|
|
2073
|
+
| boolean
|
|
2074
|
+
| UncheckedJSONSchemaType<T[string], false>
|
|
2075
|
+
unevaluatedProperties?:
|
|
2076
|
+
| boolean
|
|
2077
|
+
| UncheckedJSONSchemaType<T[string], false>
|
|
2078
|
+
properties?: IsPartial extends true
|
|
2079
|
+
? Partial<UncheckedPropertiesSchema<T>>
|
|
2080
|
+
: UncheckedPropertiesSchema<T>
|
|
2081
|
+
patternProperties?: Record<
|
|
2082
|
+
string,
|
|
2083
|
+
UncheckedJSONSchemaType<T[string], false>
|
|
2084
|
+
>
|
|
2085
|
+
propertyNames?: Omit<
|
|
2086
|
+
UncheckedJSONSchemaType<string, false>,
|
|
2087
|
+
'type'
|
|
2088
|
+
> & {
|
|
2089
|
+
type?: 'string'
|
|
2090
|
+
}
|
|
2091
|
+
dependencies?: {
|
|
2092
|
+
[K in keyof T]?: Readonly<(keyof T)[]> | UncheckedPartialSchema<T>
|
|
2093
|
+
}
|
|
2094
|
+
dependentRequired?: {
|
|
2095
|
+
[K in keyof T]?: Readonly<(keyof T)[]>
|
|
2096
|
+
}
|
|
2097
|
+
dependentSchemas?: {
|
|
2098
|
+
[K in keyof T]?: UncheckedPartialSchema<T>
|
|
2099
|
+
}
|
|
2100
|
+
minProperties?: number
|
|
2101
|
+
maxProperties?: number
|
|
2102
|
+
} & (IsPartial extends true
|
|
2103
|
+
? {
|
|
2104
|
+
required: Readonly<(keyof T)[] | boolean>
|
|
2105
|
+
}
|
|
2106
|
+
: [UncheckedRequiredMembers<T>] extends [never]
|
|
2107
|
+
? {
|
|
2108
|
+
required?: Readonly<UncheckedRequiredMembers<T>[]> | boolean
|
|
2109
|
+
}
|
|
2110
|
+
: {
|
|
2111
|
+
required: Readonly<UncheckedRequiredMembers<T>[]> | boolean
|
|
2112
|
+
})
|
|
2113
|
+
: T extends null
|
|
2114
|
+
? {
|
|
2115
|
+
type: JSONType<'null', IsPartial>
|
|
2116
|
+
nullable: true
|
|
2117
|
+
}
|
|
2118
|
+
: never) & {
|
|
2119
|
+
allOf?: Readonly<UncheckedPartialSchema<T>[]>
|
|
2120
|
+
anyOf?: Readonly<UncheckedPartialSchema<T>[]>
|
|
2121
|
+
oneOf?: Readonly<UncheckedPartialSchema<T>[]>
|
|
2122
|
+
if?: UncheckedPartialSchema<T>
|
|
2123
|
+
then?: UncheckedPartialSchema<T>
|
|
2124
|
+
else?: UncheckedPartialSchema<T>
|
|
2125
|
+
not?: UncheckedPartialSchema<T>
|
|
2126
|
+
})
|
|
2127
|
+
) & {
|
|
2128
|
+
[keyword: string]: any
|
|
2129
|
+
$id?: string
|
|
2130
|
+
$ref?: string
|
|
2131
|
+
$defs?: Record<string, UncheckedJSONSchemaType<Known, true>>
|
|
2132
|
+
definitions?: Record<string, UncheckedJSONSchemaType<Known, true>>
|
|
2133
|
+
}
|
|
2134
|
+
declare type JSONSchemaType<T> = StrictNullChecksWrapper<
|
|
2135
|
+
'JSONSchemaType',
|
|
2136
|
+
UncheckedJSONSchemaType<T, false>
|
|
2137
|
+
>
|
|
2138
|
+
declare type Known =
|
|
2139
|
+
| {
|
|
2140
|
+
[key: string]: Known
|
|
2141
|
+
}
|
|
2142
|
+
| [Known, ...Known[]]
|
|
2143
|
+
| Known[]
|
|
2144
|
+
| number
|
|
2145
|
+
| string
|
|
2146
|
+
| boolean
|
|
2147
|
+
| null
|
|
2148
|
+
declare type UncheckedPropertiesSchema<T> = {
|
|
2149
|
+
[K in keyof T]-?:
|
|
2150
|
+
| (UncheckedJSONSchemaType<T[K], false> & Nullable<T[K]>)
|
|
2151
|
+
| {
|
|
2152
|
+
$ref: string
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
declare type PropertiesSchema<T> = StrictNullChecksWrapper<
|
|
2156
|
+
'PropertiesSchema',
|
|
2157
|
+
UncheckedPropertiesSchema<T>
|
|
2158
|
+
>
|
|
2159
|
+
declare type UncheckedRequiredMembers<T> = {
|
|
2160
|
+
[K in keyof T]-?: undefined extends T[K] ? never : K
|
|
2161
|
+
}[keyof T]
|
|
2162
|
+
declare type RequiredMembers<T> = StrictNullChecksWrapper<
|
|
2163
|
+
'RequiredMembers',
|
|
2164
|
+
UncheckedRequiredMembers<T>
|
|
2165
|
+
>
|
|
2166
|
+
declare type Nullable<T> = undefined extends T
|
|
2167
|
+
? {
|
|
2168
|
+
nullable: true
|
|
2169
|
+
const?: null
|
|
2170
|
+
enum?: Readonly<(T | null)[]>
|
|
2171
|
+
default?: T | null
|
|
2172
|
+
}
|
|
2173
|
+
: {
|
|
2174
|
+
const?: T
|
|
2175
|
+
enum?: Readonly<T[]>
|
|
2176
|
+
default?: T
|
|
2177
|
+
}
|