@ditojs/server 2.80.0 → 2.82.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/server",
3
- "version": "2.80.0",
3
+ "version": "2.82.0",
4
4
  "type": "module",
5
5
  "description": "Dito.js Server – Dito.js is a declarative and modern web framework, based on Objection.js, Koa.js and Vue.js",
6
6
  "repository": "https://github.com/ditojs/dito/tree/master/packages/server",
@@ -26,10 +26,10 @@
26
26
  "node >= 18"
27
27
  ],
28
28
  "dependencies": {
29
- "@ditojs/admin": "^2.80.0",
30
- "@ditojs/build": "^2.80.0",
31
- "@ditojs/router": "^2.80.0",
32
- "@ditojs/utils": "^2.80.0",
29
+ "@ditojs/admin": "^2.82.0",
30
+ "@ditojs/build": "^2.82.0",
31
+ "@ditojs/router": "^2.82.0",
32
+ "@ditojs/utils": "^2.82.0",
33
33
  "@koa/cors": "^5.0.0",
34
34
  "@koa/etag": "^5.0.2",
35
35
  "@koa/multer": "^4.0.0",
@@ -63,11 +63,11 @@
63
63
  "passthrough-counter": "^1.0.0",
64
64
  "picocolors": "^1.1.1",
65
65
  "picomatch": "^4.0.3",
66
- "pino": "^10.3.0",
66
+ "pino": "^10.3.1",
67
67
  "pino-pretty": "^13.1.3",
68
68
  "pluralize": "^8.0.0",
69
69
  "repl": "^0.1.3",
70
- "type-fest": "^5.4.1",
70
+ "type-fest": "^5.4.4",
71
71
  "uuid": "^13.0.0"
72
72
  },
73
73
  "peerDependencies": {
@@ -85,10 +85,10 @@
85
85
  "@types/koa-session": "^6.4.5",
86
86
  "@types/koa-static": "^4.0.4",
87
87
  "@types/koa__cors": "^5.0.1",
88
- "@types/node": "^25.0.10",
88
+ "@types/node": "^25.2.2",
89
89
  "knex": "^3.1.0",
90
90
  "objection": "^3.1.5",
91
91
  "typescript": "^5.9.3"
92
92
  },
93
- "gitHead": "fd999439023af0616fa1e8afd51909eff651161d"
93
+ "gitHead": "7e721714e882dd1a02bf13354569a3744d4fefbe"
94
94
  }
@@ -305,6 +305,14 @@ export class QueryBuilder extends objection.QueryBuilder {
305
305
  }
306
306
 
307
307
  applyFilter(name, ...args) {
308
+ if (isObject(name)) {
309
+ // Multiple filters: applyFilter({ active: [], recent: [30] })
310
+ for (const [key, value] of Object.entries(name)) {
311
+ this.applyFilter(key, ...asArray(value))
312
+ }
313
+ return this
314
+ }
315
+
308
316
  if (this.#allowFilters && !this.#allowFilters[name]) {
309
317
  throw new QueryBuilderError(`Query filter '${name}' is not allowed.`)
310
318
  }
@@ -13,11 +13,14 @@ QueryParameters.register({
13
13
 
14
14
  filter(query, key, value) {
15
15
  try {
16
- for (const filter of asArray(value)) {
17
- const [, name, json] = filter.match(/^(\w+):(.*)$/)
18
- const args = asArray(JSON.parse(`[${json}]`))
19
- query.applyFilter(name, ...args)
20
- }
16
+ query.applyFilter(
17
+ Object.fromEntries(
18
+ asArray(value).map(filter => {
19
+ const [, name, json] = filter.match(/^(\w+):(.*)$/)
20
+ return [name, JSON.parse(`[${json}]`)]
21
+ })
22
+ )
23
+ )
21
24
  } catch (error) {
22
25
  throw error instanceof ResponseError
23
26
  ? error
@@ -10,6 +10,7 @@ import {
10
10
  isObject,
11
11
  isArray,
12
12
  isString,
13
+ isFunction,
13
14
  asArray,
14
15
  capitalize,
15
16
  camelize
@@ -153,9 +154,9 @@ export function convertRelation(schema, models) {
153
154
  inverse,
154
155
  modify,
155
156
  scope,
157
+ filter,
156
158
  // Objection.js-style relation description (`modify` is shared)
157
159
  join,
158
- filter,
159
160
  // Pluck Dito.js-related properties that should not end up in `rest`:
160
161
  nullable,
161
162
  owner,
@@ -213,15 +214,20 @@ export function convertRelation(schema, models) {
213
214
  } else if (through) {
214
215
  throw new RelationError('Unsupported through join definition')
215
216
  }
216
- // Combine `modify` and `filter`. Setting both together is not supported.
217
- modify ||= filter
217
+ // Combine `modify` and `filter` when `filter` is a function (Objection.js
218
+ // backward-compatible style). Otherwise, handle `filter` as a Dito.js-style
219
+ // filter name/array below.
220
+ if (isFunction(filter)) {
221
+ modify ||= filter
222
+ filter = null
223
+ }
218
224
  if (isObject(modify)) {
219
225
  // Convert a find-filter object to a filter function, same as in the
220
226
  // handling of definition.scopes, see Model.js
221
227
  modify = query => query.find(modify)
222
228
  }
223
229
  if (scope) {
224
- // Create a new modify function that merges scope and modify them:
230
+ // Create a new modify function that merges scope and modify:
225
231
  const origModify = modify
226
232
  modify = query => {
227
233
  query.applyScope(
@@ -235,6 +241,16 @@ export function convertRelation(schema, models) {
235
241
  }
236
242
  }
237
243
  }
244
+ if (filter) {
245
+ // Create a new modify function that merges filter and modify:
246
+ const origModify = modify
247
+ modify = query => {
248
+ query.applyFilter(filter)
249
+ if (origModify) {
250
+ query.modify(origModify)
251
+ }
252
+ }
253
+ }
238
254
  if (isString(modelClass)) {
239
255
  const modelName = modelClass
240
256
  modelClass = models[modelName]
@@ -146,15 +146,17 @@ export function convertSchema(
146
146
  }
147
147
  hasConvertedProperties = true
148
148
  }
149
- if (schema.patternProperties) {
150
- // TODO: Don't we need to handle required here too?
151
- const { properties } = convertProperties(
152
- schema.patternProperties,
153
- options,
154
- entry
155
- )
156
- schema.patternProperties = properties
157
- hasConvertedProperties = true
149
+ for (const key of ['additionalProperties', 'patternProperties']) {
150
+ if (isObject(schema[key])) {
151
+ // TODO: Don't we need to handle required here too?
152
+ const { properties } = convertProperties(
153
+ schema[key],
154
+ options,
155
+ entry
156
+ )
157
+ schema[key] = properties
158
+ hasConvertedProperties = true
159
+ }
158
160
  }
159
161
  if (
160
162
  jsonType &&
package/types/index.d.ts CHANGED
@@ -493,6 +493,13 @@ export interface ModelRelation {
493
493
  * class' scopes definitions.
494
494
  */
495
495
  scope?: string
496
+ /**
497
+ * Optionally, a filter can be defined to be applied when loading the
498
+ * relation's models. The filter needs to be defined in the related model
499
+ * class' filters definitions. Can be a single filter name or an object with
500
+ * filter names as keys and argument arrays as values.
501
+ */
502
+ filter?: string | { [name: string]: any[] }
496
503
  /**
497
504
  * Controls whether the auto-inserted foreign key property should be marked as
498
505
  * nullable. This only makes sense on a 'belongsTo' relation, where the model
@@ -1471,7 +1478,11 @@ export class QueryBuilder<
1471
1478
  applyScope: (...scopes: string[]) => this
1472
1479
  allowScope: (...scopes: string[]) => void
1473
1480
  clearAllowScope: () => void
1474
- applyFilter: (name: string, ...args: any[]) => this
1481
+ applyFilter: {
1482
+ (name: string, ...args: any[]): this
1483
+ (filters: { [name: string]: any[] }): this
1484
+ }
1485
+
1475
1486
  allowFilter: (...filters: string[]) => void
1476
1487
  withGraph: (
1477
1488
  expr: objection.RelationExpression<M>,