@ditojs/server 1.0.0-rc.0 → 1.1.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,7 +1,7 @@
1
1
  {
2
- "type": "module",
3
2
  "name": "@ditojs/server",
4
- "version": "1.0.0-rc.0",
3
+ "version": "1.1.0",
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",
7
7
  "author": "Jürg Lehni <juerg@scratchdisk.com> (http://scratchdisk.com)",
@@ -21,15 +21,15 @@
21
21
  "node >= 14"
22
22
  ],
23
23
  "dependencies": {
24
- "@ditojs/admin": "^1.0.0-rc.0",
25
- "@ditojs/router": "^1.0.0-rc.0",
26
- "@ditojs/utils": "^1.0.0-rc.0",
24
+ "@ditojs/admin": "^1.1.0",
25
+ "@ditojs/router": "^1.1.0",
26
+ "@ditojs/utils": "^1.1.0",
27
27
  "@koa/cors": "^3.2.0",
28
28
  "@koa/multer": "^3.0.0",
29
29
  "@originjs/vite-plugin-commonjs": "^1.0.3",
30
- "ajv": "^7.2.4",
31
- "ajv-formats": "^1.6.1",
32
- "aws-sdk": "^2.1093.0",
30
+ "ajv": "^8.10.0",
31
+ "ajv-formats": "^2.1.1",
32
+ "aws-sdk": "^2.1095.0",
33
33
  "axios": "^0.26.1",
34
34
  "bcryptjs": "^2.4.3",
35
35
  "bytes": "^3.1.2",
@@ -62,8 +62,8 @@
62
62
  "passthrough-counter": "^1.0.0",
63
63
  "picocolors": "^1.0.0",
64
64
  "picomatch": "^2.3.1",
65
- "pino": "^7.8.1",
66
- "pino-pretty": "^7.5.3",
65
+ "pino": "^7.9.1",
66
+ "pino-pretty": "^7.5.4",
67
67
  "pluralize": "^8.0.0",
68
68
  "repl": "^0.1.3",
69
69
  "uuid": "^8.3.2",
@@ -77,10 +77,10 @@
77
77
  "objection": "^2.2.0"
78
78
  },
79
79
  "devDependencies": {
80
- "knex": "^0.21.17",
80
+ "knex": "^0.21.21",
81
81
  "objection": "^2.2.18",
82
82
  "pg": "^8.7.3",
83
83
  "sqlite3": "^5.0.2"
84
84
  },
85
- "gitHead": "e643586e4b26a850f54c52a1f1bf8f0421c05d31"
85
+ "gitHead": "32b276bd5d9eaf468352a69f361bdb5df5ed373c"
86
86
  }
@@ -1,13 +1,10 @@
1
1
  import objection from 'objection'
2
- import ajv from 'ajv'
2
+ import Ajv from 'ajv'
3
3
  import addFormats from 'ajv-formats'
4
4
  import { isArray, isObject, clone, isAsync, isPromise } from '@ditojs/utils'
5
5
  import { formatJson } from '../utils/index.js'
6
6
  import * as schema from '../schema/index.js'
7
7
 
8
- // TODO: Switch to direct import once Ajv is updated / supports ESM.
9
- const Ajv = ajv.default
10
-
11
8
  // Dito does not rely on objection.AjvValidator but instead implements its own
12
9
  // validator instance that is shared across the whole app and handles schema
13
10
  // compilation and caching differently:
@@ -195,7 +192,9 @@ export class Validator extends objection.Validator {
195
192
  const duplicates = {}
196
193
  for (const error of errors) {
197
194
  // Adjust dataPaths to reflect nested validation in Objection.
198
- const dataPath = `${options?.dataPath || ''}${error.dataPath}`
195
+ // NOTE: As of Ajv 8, `error.dataPath` is now called `error.instancePath`,
196
+ // but we stick to `error.dataPath` in Dito.js
197
+ const dataPath = `${options?.dataPath || ''}${error.instancePath}`
199
198
  // Unknown properties are reported in `['propertyName']` notation,
200
199
  // so replace those with dot-notation, see:
201
200
  // https://github.com/epoberezkin/ajv/issues/671
@@ -254,12 +253,15 @@ export class Validator extends objection.Validator {
254
253
  return errorHash
255
254
  }
256
255
 
257
- prefixDataPaths(errors, dataPathPrefix) {
256
+ prefixInstancePaths(errors, instancePathPrefix) {
257
+ // As of Ajv 8, `error.dataPath` is now called `error.instancePath`. In
258
+ // Dito.js we stick to `error.dataPath`, but until the errors pass through
259
+ // `parseErrors()`, we stick to `error.instancePath` for consistency.
258
260
  return errors.map(error => ({
259
261
  ...error,
260
- dataPath: error.dataPath
261
- ? `${dataPathPrefix}${error.dataPath}`
262
- : dataPathPrefix
262
+ instancePath: error.instancePath
263
+ ? `${instancePathPrefix}${error.instancePath}`
264
+ : instancePathPrefix
263
265
  }))
264
266
  }
265
267
 
@@ -71,7 +71,7 @@ export class AdminController extends Controller {
71
71
  // Shield admin views against unauthorized access.
72
72
  const authorization = this.processAuthorize(this.authorize)
73
73
  return async (ctx, next) => {
74
- if (/^\/dito\b/.test(ctx.url)) {
74
+ if (ctx.url === '/dito.js') {
75
75
  // Return without calling `next()`
76
76
  return this.sendDitoObject(ctx)
77
77
  } else if (/\/views\b/.test(ctx.url)) {
@@ -129,6 +129,7 @@ export class AdminController extends Controller {
129
129
 
130
130
  const cwd = path.resolve('.')
131
131
  const root = this.getPath('build')
132
+ const base = `${this.url}/`
132
133
  const views = path.join(root, 'views')
133
134
 
134
135
  // Read `package.json` from the closest package.json, so we can emulate
@@ -138,11 +139,27 @@ export class AdminController extends Controller {
138
139
 
139
140
  return defineConfig(merge({
140
141
  root,
141
- base: `${this.url}/`,
142
+ base,
142
143
  mode: this.mode,
143
144
  envFile: false,
144
145
  configFile: false,
145
- plugins: [createVuePlugin(), createCommonJsPlugin()],
146
+ plugins: [
147
+ createVuePlugin(),
148
+ createCommonJsPlugin(),
149
+ {
150
+ // Private plugin to inject script tag above main module that loads
151
+ // the `dito` object through its own end-point, see `sendDitoObject()`
152
+ name: 'inject-dito-object',
153
+ transformIndexHtml: {
154
+ enforce: 'post',
155
+ transform(html) {
156
+ return html.replace(
157
+ /(\s*)(<script type="module"[^>]*?><\/script>)/,
158
+ `$1<script src="${base}dito.js"></script>$1$2`
159
+ )
160
+ }
161
+ }
162
+ }],
146
163
  build: {
147
164
  ...(development
148
165
  ? {}
@@ -11,8 +11,8 @@ export default class ControllerAction {
11
11
  method = _method,
12
12
  path = _path,
13
13
  scope,
14
- authorize = _authorize,
15
- transacted = controller.transacted,
14
+ authorize,
15
+ transacted,
16
16
  parameters,
17
17
  returns,
18
18
  options = {},
@@ -27,14 +27,17 @@ export default class ControllerAction {
27
27
  this.method = method
28
28
  this.path = path
29
29
  this.scope = scope
30
- this.authorize = authorize
31
- this.transacted = !!(transacted || (
32
- // Core graph and assets operations are always transacted, unless the
33
- // method is 'get':
34
- core && method !== 'get' && (
35
- controller.graph ||
36
- controller.assets
37
- ))
30
+ this.authorize = authorize || _authorize
31
+ this.transacted = !!(
32
+ transacted ||
33
+ controller.transacted || (
34
+ // Core graph and assets operations are always transacted, unless the
35
+ // method is 'get':
36
+ core && method !== 'get' && (
37
+ controller.graph ||
38
+ controller.assets
39
+ )
40
+ )
38
41
  )
39
42
  this.authorization = controller.processAuthorize(this.authorize)
40
43
  this.app = controller.app
@@ -89,7 +89,7 @@ function wrapWithValidation(filter, name, app) {
89
89
  type: 'FilterValidation',
90
90
  message:
91
91
  `The provided data for query filter '${name}' is not valid`,
92
- errors: app.validator.prefixDataPaths(
92
+ errors: app.validator.prefixInstancePaths(
93
93
  error.errors,
94
94
  `.${name}`
95
95
  )
@@ -40,12 +40,12 @@ export const validateAsync = {
40
40
  }
41
41
 
42
42
  function getParams(ctx, data, parentSchema, dataCtx) {
43
- const { dataPath, parentData, parentDataProperty, rootData } = dataCtx
43
+ const { instancePath, parentData, parentDataProperty, rootData } = dataCtx
44
44
  return {
45
45
  data,
46
46
  parentData,
47
47
  rootData,
48
- dataPath,
48
+ instancePath,
49
49
  // NOTE: We rename parentDataProperty to parentKey / parentIndex:
50
50
  [isNumber(parentDataProperty) ? 'parentIndex' : 'parentKey']:
51
51
  parentDataProperty,
@@ -56,7 +56,7 @@ function getParams(ctx, data, parentSchema, dataCtx) {
56
56
  }
57
57
  }
58
58
 
59
- function getErrors(error, { validator, dataPath }) {
59
+ function getErrors(error, { validator, instancePath }) {
60
60
  const errors = isArray(error.errors)
61
61
  // Ajv errors array:
62
62
  ? error.errors
@@ -66,6 +66,6 @@ function getErrors(error, { validator, dataPath }) {
66
66
  message: error.message || error.toString(),
67
67
  params: {}
68
68
  }]
69
- // Return errors prefixed with the current dataPath:
70
- return validator.prefixDataPaths(errors, dataPath)
69
+ // Return errors prefixed with the current instancePath:
70
+ return validator.prefixInstancePaths(errors, instancePath)
71
71
  }