@wbce-d9/api 12.2.0 → 12.3.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.
@@ -42,7 +42,7 @@ export class BaseOAuthDriver extends LocalAuthDriver {
42
42
  // Update user to update refresh_token and other properties that might have changed
43
43
  await this.getUserService().updateOne(userId, {
44
44
  ...updatedUserPayload,
45
- auth_data: userPayload.auth_data,
45
+ auth_data: userPayload.auth_data ?? null,
46
46
  });
47
47
  return userId;
48
48
  }
@@ -4,7 +4,7 @@ import flatten from 'flat';
4
4
  import jwt from 'jsonwebtoken';
5
5
  import { Issuer, generators } from 'openid-client';
6
6
  import { getAuthProvider } from '../../auth.js';
7
- import { ACCESS_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS } from '../../constants.js';
7
+ import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_CLEAR_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS, } from '../../constants.js';
8
8
  import env from '../../env.js';
9
9
  import { InvalidConfigException, InvalidCredentialsException, InvalidTokenException, InvalidPayloadException, } from '../../exceptions/index.js';
10
10
  import logger from '../../logger.js';
@@ -127,10 +127,7 @@ export function createOAuth2AuthRouter(providerName) {
127
127
  expiresIn: '5m',
128
128
  issuer: 'directus',
129
129
  });
130
- res.cookie(`oauth2.${providerName}`, token, {
131
- httpOnly: true,
132
- sameSite: 'lax',
133
- });
130
+ res.cookie(`oauth2.${providerName}`, token, OAUTH2_COOKIE_OPTIONS);
134
131
  return res.redirect(provider.generateAuthUrl(codeVerifier, prompt));
135
132
  }, respond);
136
133
  router.post('/callback', express.urlencoded({ extended: false }), (req, res) => {
@@ -164,7 +161,7 @@ export function createOAuth2AuthRouter(providerName) {
164
161
  });
165
162
  let authResponse;
166
163
  try {
167
- res.clearCookie(`oauth2.${providerName}`);
164
+ res.clearCookie(`oauth2.${providerName}`, OAUTH2_COOKIE_CLEAR_OPTIONS);
168
165
  authResponse = await authenticationService.login(providerName, {
169
166
  code: req.query['code'],
170
167
  codeVerifier: verifier,
@@ -4,7 +4,7 @@ import flatten from 'flat';
4
4
  import jwt from 'jsonwebtoken';
5
5
  import { Issuer, generators } from 'openid-client';
6
6
  import { getAuthProvider } from '../../auth.js';
7
- import { ACCESS_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS } from '../../constants.js';
7
+ import { ACCESS_COOKIE_OPTIONS, OAUTH2_COOKIE_CLEAR_OPTIONS, OAUTH2_COOKIE_OPTIONS, REFRESH_COOKIE_OPTIONS, } from '../../constants.js';
8
8
  import env from '../../env.js';
9
9
  import { InvalidConfigException, InvalidCredentialsException, InvalidTokenException, InvalidPayloadException, } from '../../exceptions/index.js';
10
10
  import logger from '../../logger.js';
@@ -168,10 +168,7 @@ export function createOpenIDAuthRouter(providerName) {
168
168
  const urlParams = new URL(authUrl);
169
169
  const state = urlParams.searchParams.get('state');
170
170
  const cookieName = `openid.${providerName}.${state || ''}`;
171
- res.cookie(cookieName, token, {
172
- httpOnly: true,
173
- sameSite: 'lax',
174
- });
171
+ res.cookie(cookieName, token, OAUTH2_COOKIE_OPTIONS);
175
172
  return res.redirect(authUrl);
176
173
  }), respond);
177
174
  router.post('/callback', express.urlencoded({ extended: false }), (req, res) => {
@@ -214,7 +211,7 @@ export function createOpenIDAuthRouter(providerName) {
214
211
  });
215
212
  let authResponse;
216
213
  try {
217
- res.clearCookie(cookieName);
214
+ res.clearCookie(cookieName, OAUTH2_COOKIE_CLEAR_OPTIONS);
218
215
  authResponse = await authenticationService.login(providerName, {
219
216
  code: req.query['code'],
220
217
  codeVerifier: verifier,
@@ -307,8 +307,8 @@ EXTENSIONS_AUTO_RELOAD=false
307
307
  ####################################################################################################
308
308
  ### Email
309
309
 
310
- # Email address from which emails are sent ["no-reply@directus.io"]
311
- EMAIL_FROM="no-reply@directus.io"
310
+ # Email address from which emails are sent
311
+ EMAIL_FROM="no-reply@example.com"
312
312
 
313
313
  # What to use to send emails. One of
314
314
  # sendmail, smtp, mailgun, sendgrid, ses.
@@ -13,6 +13,8 @@ export declare const REFRESH_COOKIE_CLEAR_OPTIONS: CookieOptions;
13
13
  export declare const GET_SET_HEADER: (cookieValue: string) => string;
14
14
  export declare const ACCESS_COOKIE_OPTIONS: CookieOptions;
15
15
  export declare const ACCESS_COOKIE_CLEAR_OPTIONS: CookieOptions;
16
+ export declare const OAUTH2_COOKIE_OPTIONS: CookieOptions;
17
+ export declare const OAUTH2_COOKIE_CLEAR_OPTIONS: CookieOptions;
16
18
  export declare const OAS_REQUIRED_SCHEMAS: string[];
17
19
  /** Formats from which transformation is supported */
18
20
  export declare const SUPPORTED_IMAGE_TRANSFORM_FORMATS: string[];
package/dist/constants.js CHANGED
@@ -82,6 +82,20 @@ export const ACCESS_COOKIE_CLEAR_OPTIONS = (() => {
82
82
  delete rest.expires;
83
83
  return rest;
84
84
  })();
85
+ export const OAUTH2_COOKIE_OPTIONS = {
86
+ httpOnly: true,
87
+ domain: env['OAUTH2_TOKEN_COOKIE_DOMAIN'] || env['ACCESS_TOKEN_COOKIE_DOMAIN'],
88
+ maxAge: getMilliseconds(env['OAUTH2_TOKEN_TTL'] || env['ACCESS_TOKEN_TTL']),
89
+ secure: (env['OAUTH2_TOKEN_COOKIE_SECURE'] || env['ACCESS_TOKEN_COOKIE_SECURE']) ?? false,
90
+ sameSite: env['OAUTH2_TOKEN_COOKIE_SAME_SITE'] || 'lax',
91
+ path: '/auth',
92
+ };
93
+ export const OAUTH2_COOKIE_CLEAR_OPTIONS = (() => {
94
+ const { ...rest } = ACCESS_COOKIE_OPTIONS;
95
+ delete rest.maxAge;
96
+ delete rest.expires;
97
+ return rest;
98
+ })();
85
99
  export const OAS_REQUIRED_SCHEMAS = ['Diff', 'Schema', 'Query', 'x-metadata'];
86
100
  /** Formats from which transformation is supported */
87
101
  export const SUPPORTED_IMAGE_TRANSFORM_FORMATS = ['image/jpeg', 'image/png', 'image/webp', 'image/tiff', 'image/avif'];
@@ -7,7 +7,7 @@ columns:
7
7
  type: string
8
8
  length: 100
9
9
  nullable: false
10
- default: 'Directus'
10
+ default: 'd9'
11
11
  project_url:
12
12
  type: string
13
13
  length: 255
@@ -63,6 +63,8 @@ fields:
63
63
  placeholder: $t:field_options.directus_files.filename_disk
64
64
  readonly: true
65
65
  width: half
66
+ special:
67
+ - system-only
66
68
 
67
69
  - field: filename_download
68
70
  interface: input
@@ -180,3 +180,6 @@ fields:
180
180
 
181
181
  - field: auth_data
182
182
  hidden: true
183
+ special:
184
+ - system-only
185
+ - conceal
@@ -51,7 +51,7 @@ export const handler = async (req, _res, next) => {
51
51
  })
52
52
  .from('directus_sessions AS s')
53
53
  .leftJoin('directus_users AS u', 's.user', 'u.id')
54
- .where('s.token', payload.refresh_token)
54
+ .where('s.session_id', payload.session_id)
55
55
  .andWhere('s.expires', '>=', new Date())
56
56
  .first();
57
57
  if (!user) {
@@ -3,7 +3,7 @@ import env from '../env.js';
3
3
  let corsMiddleware = (_req, _res, next) => next();
4
4
  if (env['CORS_ENABLED'] === true) {
5
5
  corsMiddleware = cors({
6
- origin: env['CORS_ORIGIN'] || true,
6
+ origin: env['CORS_ORIGIN'] || false,
7
7
  methods: env['CORS_METHODS'] || 'GET,POST,PATCH,DELETE',
8
8
  allowedHeaders: env['CORS_ALLOWED_HEADERS'],
9
9
  exposedHeaders: env['CORS_EXPOSED_HEADERS'],
@@ -135,7 +135,7 @@ export class AuthenticationService {
135
135
  role: user.role,
136
136
  app_access: user.app_access,
137
137
  admin_access: user.admin_access,
138
- refresh_token: refreshToken,
138
+ session_id: sessionId,
139
139
  };
140
140
  const customClaims = await emitter.emitFilter('auth.jwt', tokenPayload, {
141
141
  status: 'pending',
@@ -309,7 +309,7 @@ export class AuthenticationService {
309
309
  role: record.role_id,
310
310
  app_access: record.role_app_access,
311
311
  admin_access: record.role_admin_access,
312
- refresh_token: newRefreshToken,
312
+ session_id: sessionId,
313
313
  };
314
314
  if (record.share_id) {
315
315
  tokenPayload.share = record.share_id;
@@ -449,7 +449,13 @@ export class AuthorizationService {
449
449
  const originalItems = await mainItemService.readMany(keys);
450
450
  for (let i = 0; i < originalItems.length; i++) {
451
451
  const originalItem = originalItems[i];
452
- const emptyItemsToAdd = originalItem[fieldKey].length - field.update?.length - field.delete?.length;
452
+ const alreadyExistingItems = originalItem[fieldKey].length;
453
+ const updatedItemsIds = field.update.map((f) => f.id);
454
+ const deletedItemsIds = field.delete.map((f) => f?.id || f);
455
+ const twoTimesCountedItems = originalItem[fieldKey].reduce((n, item) => {
456
+ return n + Number(updatedItemsIds.includes(item) || deletedItemsIds.includes(item));
457
+ }, 0);
458
+ const emptyItemsToAdd = alreadyExistingItems - twoTimesCountedItems;
453
459
  const finalArrayToValidate = arrayToValidate.concat(Array(emptyItemsToAdd).fill({}));
454
460
  // validate partial items until the last key
455
461
  if (i == keys.length - 1) {
@@ -72,7 +72,7 @@ export class MailService {
72
72
  .from('directus_settings')
73
73
  .first();
74
74
  return {
75
- projectName: projectInfo?.project_name || 'Directus',
75
+ projectName: projectInfo?.project_name || 'd9',
76
76
  projectColor: projectInfo?.project_color || '#546e7a',
77
77
  projectLogo: getProjectLogoURL(projectInfo?.project_logo),
78
78
  projectUrl: projectInfo?.project_url || '',
@@ -105,6 +105,12 @@ export class PayloadService {
105
105
  return new Date(helpers.date.writeTimestamp(new Date().toISOString()));
106
106
  return value;
107
107
  },
108
+ async 'system-only'({ value, accountability }) {
109
+ if (accountability && (value === null || value)) {
110
+ throw new ForbiddenException();
111
+ }
112
+ return value;
113
+ },
108
114
  async 'cast-csv'({ action, value }) {
109
115
  if (Array.isArray(value) === false && typeof value !== 'string')
110
116
  return;
@@ -81,7 +81,7 @@ export class SharesService extends ItemsService {
81
81
  item: record.share_item,
82
82
  collection: record.share_collection,
83
83
  },
84
- refresh_token: refreshToken,
84
+ session_id: sessionId,
85
85
  };
86
86
  const accessToken = jwt.sign(tokenPayload, env['SECRET'], {
87
87
  expiresIn: env['ACCESS_TOKEN_TTL'],
@@ -31,7 +31,7 @@ export class TFAService {
31
31
  const project = await this.knex.select('project_name').from('directus_settings').limit(1).first();
32
32
  return {
33
33
  secret,
34
- url: authenticator.keyuri(user.email, project?.project_name || 'Directus', secret),
34
+ url: authenticator.keyuri(user.email, project?.project_name || 'd9', secret),
35
35
  };
36
36
  }
37
37
  async enableTFA(key, otp, secret) {
@@ -34,7 +34,7 @@ export type DirectusTokenPayload = {
34
34
  collection: string;
35
35
  item: string;
36
36
  };
37
- refresh_token: string;
37
+ session_id: string;
38
38
  };
39
39
  export type ShareData = {
40
40
  share_id: string;
@@ -1,3 +1,4 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
2
3
  export declare function compress(raw: Record<string, any> | Record<string, any>[]): Promise<Buffer>;
3
4
  export declare function decompress(compressed: Buffer): Promise<any>;
@@ -13,5 +13,5 @@ export function getIPFromReq(req) {
13
13
  }
14
14
  }
15
15
  // IP addresses starting with ::ffff: are IPv4 addresses in IPv6 format. We can strip the prefix to get back to IPv4
16
- return ip.startsWith('::ffff:') ? ip.substring(7) : ip;
16
+ return ip?.startsWith('::ffff:') ? ip.substring(7) : ip ?? '';
17
17
  }
package/dist/utils/jwt.js CHANGED
@@ -21,9 +21,9 @@ export function verifyJWT(token, secret) {
21
21
  return payload;
22
22
  }
23
23
  export function verifyAccessJWT(token, secret) {
24
- const { id, role, app_access, admin_access, share, share_scope, refresh_token } = verifyJWT(token, secret);
25
- if (role === undefined || app_access === undefined || admin_access === undefined || refresh_token === undefined) {
24
+ const { id, role, app_access, admin_access, share, share_scope, session_id } = verifyJWT(token, secret);
25
+ if (role === undefined || app_access === undefined || admin_access === undefined || session_id === undefined) {
26
26
  throw new InvalidTokenException('Invalid token payload.');
27
27
  }
28
- return { id, role, app_access, admin_access, share, share_scope, refresh_token };
28
+ return { id, role, app_access, admin_access, share, share_scope, session_id };
29
29
  }
@@ -1,3 +1,4 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
2
3
  export declare function parseIptc(buffer: Buffer): Record<string, unknown>;
3
4
  export declare function parseXmp(buffer: Buffer): Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wbce-d9/api",
3
- "version": "12.2.0",
3
+ "version": "12.3.0",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -22,7 +22,7 @@
22
22
  "framework",
23
23
  "vue"
24
24
  ],
25
- "homepage": "https://directus.io",
25
+ "homepage": "https://github.com/LaWebcapsule/directus9",
26
26
  "bugs": {
27
27
  "url": "https://github.com/LaWebcapsule/directus9/issues"
28
28
  },
@@ -63,75 +63,77 @@
63
63
  "!**/__*__/"
64
64
  ],
65
65
  "dependencies": {
66
- "@authenio/samlify-node-xmllint": "2.0.0",
67
- "@aws-sdk/client-sesv2": "3.916.0",
68
- "@godaddy/terminus": "4.12.0",
69
- "@rollup/plugin-alias": "5.0.0",
70
66
  "@rollup/plugin-node-resolve": "15.0.2",
71
67
  "@rollup/plugin-virtual": "3.0.1",
72
68
  "@wbce-d9/format-title": "10.0.0",
73
- "argon2": "0.30.3",
74
- "async": "3.2.4",
75
69
  "axios": "^1.12.0",
70
+ "chalk": "5.2.0",
71
+ "commander": "10.0.1",
72
+ "date-fns": "2.29.3",
73
+ "execa": "7.1.1",
74
+ "express": "^4.21.2",
75
+ "fs-extra": "11.1.1",
76
+ "inquirer": "9.1.5",
77
+ "joi": "17.9.1",
78
+ "js-yaml": "4.1.1",
79
+ "json2csv": "5.0.7",
80
+ "knex": "3.1.0",
81
+ "lodash-es": "4.17.23",
82
+ "marked": "4.3.0",
83
+ "micromustache": "8.0.3",
84
+ "nanoid": "5.0.9",
85
+ "openapi3-ts": "3.2.0",
86
+ "ora": "6.3.0",
87
+ "pino": "8.11.0",
88
+ "rollup": "3.29.5",
89
+ "uuid": "9.0.0",
90
+ "wellknown": "0.5.0",
91
+ "@authenio/samlify-node-xmllint": "2.0.0",
92
+ "@aws-sdk/client-sesv2": "3.1004.0",
93
+ "@godaddy/terminus": "4.12.0",
94
+ "@rollup/plugin-alias": "5.0.0",
95
+ "argon2": "0.44.0",
96
+ "async": "3.2.4",
76
97
  "busboy": "1.6.0",
77
98
  "bytes": "3.1.2",
78
99
  "camelcase": "7.0.1",
79
- "chalk": "5.2.0",
80
100
  "chokidar": "3.5.3",
81
- "commander": "10.0.1",
82
101
  "content-disposition": "0.5.4",
83
102
  "cookie-parser": "1.4.7",
84
103
  "cors": "2.8.5",
85
104
  "csv-parser": "3.0.0",
86
- "date-fns": "2.29.3",
87
105
  "deep-diff": "1.0.2",
88
106
  "destroy": "1.2.0",
89
107
  "dotenv": "16.0.3",
90
108
  "encodeurl": "1.0.2",
91
109
  "eventemitter2": "6.4.9",
92
- "execa": "7.1.1",
93
110
  "exif-reader": "1.2.0",
94
- "express": "^4.21.2",
95
111
  "fast-redact": "^3.5.0",
96
112
  "flat": "5.0.2",
97
- "fs-extra": "11.1.1",
98
113
  "graphql": "16.8.1",
99
114
  "graphql-compose": "9.0.10",
100
115
  "helmet": "6.1.5",
101
116
  "icc": "3.0.0",
102
- "inquirer": "9.1.5",
103
117
  "ioredis": "5.3.2",
104
118
  "isolated-vm": "^6.0.1",
105
- "joi": "17.9.1",
106
- "js-yaml": "4.1.1",
107
119
  "js2xmlparser": "5.0.0",
108
- "json2csv": "5.0.7",
109
120
  "jsonwebtoken": "9.0.0",
110
121
  "keyv": "4.5.2",
111
- "knex": "3.1.0",
112
122
  "ldapjs": "2.3.3",
113
123
  "liquidjs": "10.7.0",
114
- "lodash-es": "4.17.23",
115
- "marked": "4.3.0",
116
- "micromustache": "8.0.3",
117
124
  "mime-types": "2.1.35",
118
125
  "ms": "2.1.3",
119
- "nanoid": "5.0.9",
120
126
  "node-cron": "3.0.2",
121
127
  "node-machine-id": "1.1.12",
122
128
  "nodemailer": "7.0.11",
123
129
  "object-hash": "3.0.0",
124
- "openapi3-ts": "3.2.0",
125
130
  "openid-client": "5.4.0",
126
- "ora": "6.3.0",
127
131
  "otplib": "12.0.1",
128
- "pino": "8.11.0",
129
132
  "pino-http": "8.3.3",
130
133
  "pino-http-print": "3.1.0",
131
134
  "pino-pretty": "10.0.0",
132
- "qs": "6.14.1",
135
+ "qs": "6.14.2",
133
136
  "rate-limiter-flexible": "2.4.1",
134
- "rollup": "3.29.5",
135
137
  "samlify": "2.10.0",
136
138
  "sanitize-html": "2.12.1",
137
139
  "sharp": "0.32.6",
@@ -140,26 +142,39 @@
140
142
  "strip-bom-stream": "5.0.0",
141
143
  "tmp-promise": "3.0.3",
142
144
  "tsx": "3.12.6",
143
- "uuid": "9.0.0",
144
145
  "uuid-validate": "0.0.3",
145
- "wellknown": "0.5.0",
146
- "@wbce-d9/constants": "10.0.0",
147
- "@wbce-d9/app": "9.35.1",
146
+ "@wbce-d9/app": "10.0.0",
148
147
  "@wbce-d9/exceptions": "10.0.0",
149
148
  "@wbce-d9/extensions-sdk": "10.0.2",
149
+ "@wbce-d9/constants": "10.0.0",
150
+ "@wbce-d9/schema": "10.0.0",
150
151
  "@wbce-d9/specs": "9.26.5",
151
152
  "@wbce-d9/storage": "10.0.0",
152
153
  "@wbce-d9/storage-driver-azure": "10.0.1",
153
- "@wbce-d9/schema": "10.0.0",
154
- "@wbce-d9/storage-driver-cloudinary": "10.0.1",
155
- "@wbce-d9/storage-driver-local": "10.0.1",
156
- "@wbce-d9/storage-driver-s3": "10.0.1",
157
154
  "@wbce-d9/storage-driver-gcs": "10.0.1",
155
+ "@wbce-d9/storage-driver-s3": "10.0.1",
156
+ "@wbce-d9/storage-driver-local": "10.0.1",
157
+ "@wbce-d9/utils": "10.0.1",
158
158
  "@wbce-d9/update-check": "10.0.1",
159
- "@wbce-d9/utils": "10.0.1"
159
+ "@wbce-d9/storage-driver-cloudinary": "10.0.1"
160
160
  },
161
161
  "devDependencies": {
162
162
  "@ngneat/falso": "6.4.0",
163
+ "@types/fs-extra": "11.0.1",
164
+ "@types/inquirer": "9.0.3",
165
+ "@types/js-yaml": "4.0.5",
166
+ "@types/json2csv": "5.0.3",
167
+ "@types/lodash-es": "4.17.7",
168
+ "@types/marked": "4.0.8",
169
+ "@types/node": "22.15.29",
170
+ "@types/supertest": "2.0.12",
171
+ "@types/uuid": "9.0.1",
172
+ "@types/wellknown": "0.5.4",
173
+ "@vitest/coverage-v8": "4.1.0",
174
+ "@wbce-d9/tsconfig": "2.0.0",
175
+ "supertest": "6.3.3",
176
+ "typescript": "5.0.4",
177
+ "vitest": "4.1.0",
163
178
  "@types/async": "3.2.19",
164
179
  "@types/busboy": "1.5.0",
165
180
  "@types/bytes": "3.1.1",
@@ -170,40 +185,25 @@
170
185
  "@types/destroy": "1.0.0",
171
186
  "@types/encodeurl": "1.0.0",
172
187
  "@types/exif-reader": "1.0.0",
173
- "@types/express": "4.17.17",
174
- "@types/express-serve-static-core": "4.17.33",
188
+ "@types/express": "4.17.25",
189
+ "@types/express-serve-static-core": "4.19.8",
175
190
  "@types/fast-redact": "3.0.2",
176
191
  "@types/flat": "5.0.2",
177
- "@types/fs-extra": "11.0.1",
178
- "@types/inquirer": "9.0.3",
179
- "@types/js-yaml": "4.0.5",
180
- "@types/json2csv": "5.0.3",
181
192
  "@types/jsonwebtoken": "9.0.1",
182
193
  "@types/keyv": "4.2.0",
183
194
  "@types/ldapjs": "2.2.5",
184
- "@types/lodash-es": "4.17.7",
185
- "@types/marked": "4.0.8",
186
195
  "@types/mime-types": "2.1.1",
187
196
  "@types/ms": "0.7.31",
188
- "@types/node": "18.15.13",
189
197
  "@types/node-cron": "3.0.7",
190
198
  "@types/nodemailer": "6.4.7",
191
199
  "@types/object-hash": "3.0.2",
192
- "@types/qs": "6.9.7",
200
+ "@types/qs": "6.14.0",
193
201
  "@types/sanitize-html": "2.9.0",
194
202
  "@types/stream-json": "1.7.3",
195
- "@types/supertest": "2.0.12",
196
- "@types/uuid": "9.0.1",
197
203
  "@types/uuid-validate": "0.0.1",
198
- "@types/wellknown": "0.5.4",
199
- "@vitest/coverage-c8": "0.30.1",
200
- "@wbce-d9/tsconfig": "2.0.0",
201
204
  "copyfiles": "2.4.1",
202
205
  "form-data": "4.0.4",
203
206
  "knex-mock-client": "3.0.2",
204
- "supertest": "6.3.3",
205
- "typescript": "5.0.4",
206
- "vitest": "0.30.1",
207
207
  "@wbce-d9/types": "10.1.0"
208
208
  },
209
209
  "optionalDependencies": {