Skip to content

Commit ca0994e

Browse files
feat(mongodb): Add Object ID keyword converter and update MongoDB CLI & docs (#3041)
1 parent 77e14dd commit ca0994e

File tree

22 files changed

+5240
-2251
lines changed

22 files changed

+5240
-2251
lines changed

docs/.vitepress/config.sidebar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default {
8080
{
8181
text: 'CLI',
8282
collapsible: true,
83-
collapsed: false,
83+
collapsed: true,
8484
items: [
8585
{
8686
text: '📖 Readme',

docs/.vitepress/highlight.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IThemeRegistration, getHighlighter, HtmlRendererOptions } from 'shiki'
22
import type { ThemeOptions } from 'vitepress'
3-
import { getJavaScript, PRETTIERRC } from '@feathersjs/cli/lib/commons'
3+
import { getJavaScript, PRETTIERRC } from '@feathersjs/generators/lib/commons'
44
import prettier from 'prettier'
55

66
/**

docs/.vitepress/style/main.postcss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ body .bg-base-100 {
8686

8787
#VPSidebarNav:not(:first-child) {
8888
@apply mt-3;
89-
border-top: 1px solid transparent;
9089
border-top-color: var(--vp-c-divider-light);
9190
}
9291

docs/api/databases/mongodb.md

Lines changed: 19 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -394,101 +394,37 @@ For more information on MongoDB's collation feature, visit the [collation refere
394394

395395
MongoDB uses [ObjectId](https://www.mongodb.com/docs/manual/reference/method/ObjectId/) object as primary keys. To store them in the right format they have to be converted from and to strings.
396396

397-
### AJV format
397+
### AJV keyword
398398

399-
To validate an ObjectId via the `format` keyword, add the following to your `validators` file:
399+
To validate and convert strings to an object id using AJV, the `keywordObjectId` [AJV keyword](https://ajv.js.org/api.html#ajv-addkeyword-definition-string-object-ajv) helper can be used. It is set up automatically in a generated application using MongoDB.
400400

401401
```ts
402-
// `objectid` formatter
403-
const formatObjectId = {
404-
type: 'string',
405-
validate: (id: string | ObjectId) => {
406-
if (ObjectId.isValid(id)) {
407-
if (String(new ObjectId(id)) === id) return true
408-
return false
409-
}
410-
return false
411-
}
412-
} as const
413-
414-
dataValidator.addFormat('objectid', formatObjectId)
415-
queryValidator.addFormat('objectid', formatObjectId)
416-
```
417-
418-
Now you can use it as a `format` option in your schema definitions:
419-
420-
```ts
421-
// TypeBox
422-
Type.String({ format: 'objectid' })
423-
// JSON schema
424-
const schema = {
425-
type: 'string',
426-
format: 'objectid'
427-
}
428-
```
429-
430-
### Shared Validator
431-
432-
The following utility can be used to create a shared [TypeBox](../schema/typebox.md) type for object ids (e.g. in a `utilities` file):
433-
434-
```ts
435-
import { Type } from '@feathersjs/typebox'
436-
437-
export const ObjectId = () =>
438-
Type.Union([Type.String({ format: 'objectid' }), Type.Object({}, { additionalProperties: true })])
439-
```
402+
import { keywordObjectId } from '@feathersjs/mongodb'
440403

441-
Which can then be used like this:
404+
const validator = new Ajv()
442405

443-
```ts
444-
import { Type } from '@feathersjs/typebox'
445-
import { ObjectId } from '../utilities'
446-
447-
const userSchema = Type.Object(
448-
{
449-
_id: ObjectId(),
450-
orgIds: Type.Array(ObjectId())
451-
},
452-
{ $id: 'User', additionalProperties: false }
453-
)
454-
```
406+
validator.addKeyword(keywordObjectId)
455407

456-
### AJV converter
457-
458-
To convert Object Ids, one option is to register an AJV specific converter by adding the following to the the `validators` file:
408+
const typeboxSchema = Type.Object({
409+
userId: Type.String({ objectid: true })
410+
})
459411

460-
```ts
461-
// `convert` keyword.
462-
const keywordConvert = {
463-
keyword: 'convert',
464-
type: 'string',
465-
compile(schemaVal: boolean, parentSchema: AnySchemaObject) {
466-
if (!schemaVal) return () => true
467-
468-
if (parentSchema.format === 'objectid') {
469-
return function (value: string, obj: any) {
470-
const { parentData, parentDataProperty } = obj
471-
parentData[parentDataProperty] = new ObjectId(value)
472-
return true
473-
}
412+
const jsonSchema = {
413+
type: 'object',
414+
properties: {
415+
userId: {
416+
type: 'string',
417+
objectid: true
474418
}
475-
return () => true
476419
}
477-
} as const
478-
479-
dataValidator.addKeyword(keywordConvert)
480-
queryValidator.addKeyword(keywordConvert)
420+
}
481421
```
482422

483-
And then update the shared `ObjectId` in `utilities`:
423+
<BlockQuote label="Important" type="warning">
484424

485-
```ts
486-
export const ObjectId = () =>
487-
Type.Union([
488-
Type.String({ format: 'objectid', convert: true }),
489-
Type.Object({}, { additionalProperties: true })
490-
])
491-
```
425+
Usually a converted object id property can be treated like a string but in some cases when working with it on the server you may have to call `toString()` to get the proper type.
426+
427+
</BlockQuote>
492428

493429
### ObjectId resolvers
494430

docs/guides/basics/schemas.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ import { dataValidator, queryValidator } from '../../validators'
161161
// Main data model schema
162162
export const userSchema = Type.Object(
163163
{
164-
_id: Type.String(),
164+
_id: Type.String({ objectid: true }),
165165
email: Type.String(),
166166
password: Type.Optional(Type.String()),
167167
githubId: Type.Optional(Type.Number()),
@@ -275,7 +275,7 @@ export const messageSchema = Type.Object(
275275
id: Type.Number(),
276276
text: Type.String(),
277277
createdAt: Type.Number(),
278-
userId: Type.String(),
278+
userId: Type.Number(),
279279
user: Type.Ref(userSchema)
280280
},
281281
{ $id: 'Message', additionalProperties: false }
@@ -362,10 +362,10 @@ import { userSchema } from '../users/users.schema'
362362
// Main data model schema
363363
export const messageSchema = Type.Object(
364364
{
365-
_id: Type.String(),
365+
_id: Type.String({ objectid: true }),
366366
text: Type.String(),
367367
createdAt: Type.Number(),
368-
userId: Type.String(),
368+
userId: Type.String({ objectid: true }),
369369
user: Type.Ref(userSchema)
370370
},
371371
{ $id: 'Message', additionalProperties: false }

docs/guides/basics/starting.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Since any Feathers application is a Node application, we can create a default [p
4646
```sh
4747
npm init --yes
4848
# Install TypeScript and its NodeJS wrapper
49-
npm i typescript ts-node --save-dev
49+
npm i typescript ts-node @types/node --save-dev
5050
# Also initialize a TS configuration file that uses modern JavaScript
5151
npx tsc --init --target es2020
5252
```
@@ -217,7 +217,6 @@ Then update `app.ts` with the following content:
217217
</LanguageBlock>
218218
<LanguageBlock global-id="js">
219219
220-
221220
```sh
222221
npm install @feathersjs/socketio@pre @feathersjs/koa@pre koa-static --save
223222
```

docs/guides/cli/validators.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ export const queryValidator = addFormats(
4040
formats
4141
)
4242
```
43+
44+
## MongoDB ObjectIds
45+
46+
When choosing MongoDB, the validators file will also register the [`objectid` keyword](../../api/databases/mongodb.md#ajv-keyword) to convert strings to MongoDB Object ids.

0 commit comments

Comments
 (0)