feat: adds plugin-relationship-object-ids package (#6045)
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import Ajv from 'ajv'
|
||||
import ObjectIdImport from 'bson-objectid'
|
||||
|
||||
const ObjectId = (ObjectIdImport.default ||
|
||||
ObjectIdImport) as unknown as typeof ObjectIdImport.default
|
||||
|
||||
import type { RichTextAdapter } from '../admin/types.js'
|
||||
import type { Where } from '../types/index.js'
|
||||
@@ -389,8 +393,12 @@ const validateFilterOptions: Validate<
|
||||
const valueIDs: (number | string)[] = []
|
||||
|
||||
values.forEach((val) => {
|
||||
if (typeof val === 'object' && val?.value) {
|
||||
valueIDs.push(val.value)
|
||||
if (typeof val === 'object') {
|
||||
if (val?.value) {
|
||||
valueIDs.push(val.value)
|
||||
} else if (ObjectId.isValid(val)) {
|
||||
valueIDs.push(new ObjectId(val).toHexString())
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof val === 'string' || typeof val === 'number') {
|
||||
@@ -441,6 +449,10 @@ const validateFilterOptions: Validate<
|
||||
if (typeof val === 'string' || typeof val === 'number') {
|
||||
requestedID = val
|
||||
}
|
||||
|
||||
if (typeof val === 'object' && ObjectId.isValid(val)) {
|
||||
requestedID = new ObjectId(val).toHexString()
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(relationTo) && typeof val === 'object' && val?.relationTo) {
|
||||
|
||||
37
packages/plugin-relationship-object-ids/.eslintrc.cjs
Normal file
37
packages/plugin-relationship-object-ids/.eslintrc.cjs
Normal file
@@ -0,0 +1,37 @@
|
||||
/** @type {import('prettier').Config} */
|
||||
module.exports = {
|
||||
extends: ['@payloadcms'],
|
||||
overrides: [
|
||||
{
|
||||
extends: ['plugin:@typescript-eslint/disable-type-checked'],
|
||||
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
|
||||
},
|
||||
{
|
||||
files: ['package.json', 'tsconfig.json'],
|
||||
rules: {
|
||||
'perfectionist/sort-array-includes': 'off',
|
||||
'perfectionist/sort-astro-attributes': 'off',
|
||||
'perfectionist/sort-classes': 'off',
|
||||
'perfectionist/sort-enums': 'off',
|
||||
'perfectionist/sort-exports': 'off',
|
||||
'perfectionist/sort-imports': 'off',
|
||||
'perfectionist/sort-interfaces': 'off',
|
||||
'perfectionist/sort-jsx-props': 'off',
|
||||
'perfectionist/sort-keys': 'off',
|
||||
'perfectionist/sort-maps': 'off',
|
||||
'perfectionist/sort-named-exports': 'off',
|
||||
'perfectionist/sort-named-imports': 'off',
|
||||
'perfectionist/sort-object-types': 'off',
|
||||
'perfectionist/sort-objects': 'off',
|
||||
'perfectionist/sort-svelte-attributes': 'off',
|
||||
'perfectionist/sort-union-types': 'off',
|
||||
'perfectionist/sort-vue-attributes': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
root: true,
|
||||
}
|
||||
7
packages/plugin-relationship-object-ids/.gitignore
vendored
Normal file
7
packages/plugin-relationship-object-ids/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
.env
|
||||
dist
|
||||
demo/uploads
|
||||
build
|
||||
.DS_Store
|
||||
package-lock.json
|
||||
15
packages/plugin-relationship-object-ids/.swcrc
Normal file
15
packages/plugin-relationship-object-ids/.swcrc
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/swcrc",
|
||||
"sourceMaps": true,
|
||||
"jsc": {
|
||||
"target": "esnext",
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"tsx": true,
|
||||
"dts": true
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "es6"
|
||||
}
|
||||
}
|
||||
34
packages/plugin-relationship-object-ids/README.md
Normal file
34
packages/plugin-relationship-object-ids/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Payload Relationship ObjectID Plugin
|
||||
|
||||
This plugin automatically enables all Payload `relationship` and `upload` field types to be stored as `ObjectID`s in MongoDB.
|
||||
|
||||
Minimum required version of Payload: `1.9.5`
|
||||
|
||||
## What it does
|
||||
|
||||
It injects a `beforeChange` field hook into each `relationship` and `upload` field, which converts string-based IDs to `ObjectID`s immediately prior to storage.
|
||||
|
||||
#### Usage
|
||||
|
||||
Simply import and install the plugin to make it work:
|
||||
|
||||
```ts
|
||||
import { relationshipsAsObjectID } from '@payloadcms/plugin-relationship-object-ids'
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
export default buildConfig({
|
||||
// your config here
|
||||
plugins: [
|
||||
// Call the plugin within your `plugins` array
|
||||
relationshipsAsObjectID(),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### Migration
|
||||
|
||||
Note - this plugin will only store newly created or resaved documents' relations as `ObjectID`s. It will not modify any of your existing data. If you'd like to convert existing data into an `ObjectID` format, you should write a migration script to loop over all documents in your database and then simply resave each one.
|
||||
|
||||
### Support
|
||||
|
||||
If you need help with this plugin, [join our Discord](https://t.co/30APlsQUPB) and we'd be happy to give you a hand.
|
||||
56
packages/plugin-relationship-object-ids/package.json
Normal file
56
packages/plugin-relationship-object-ids/package.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-relationship-object-ids",
|
||||
"version": "3.0.0-beta.18",
|
||||
"homepage:": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/payloadcms/payload.git",
|
||||
"directory": "packages/plugin-relationship-object-ids"
|
||||
},
|
||||
"description": "A Payload plugin to store all relationship IDs as ObjectIDs",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types",
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
"author": "dev@payloadcms.com",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"payload": "workspace:*",
|
||||
"mongoose": "6.12.3"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"*.js",
|
||||
"*.d.ts",
|
||||
"!.prettierrc.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"payload": "workspace:*"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./src/index.ts",
|
||||
"require": "./src/index.ts",
|
||||
"types": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import type { Config } from 'payload/config'
|
||||
import type { CollectionConfig, FieldHook, RelationshipField, UploadField } from 'payload/types'
|
||||
|
||||
import mongoose from 'mongoose'
|
||||
import { fieldAffectsData } from 'payload/types'
|
||||
|
||||
const convertValue = ({
|
||||
relatedCollection,
|
||||
value,
|
||||
}: {
|
||||
relatedCollection: CollectionConfig
|
||||
value: number | string
|
||||
}): mongoose.Types.ObjectId | number | string => {
|
||||
const customIDField = relatedCollection.fields.find(
|
||||
(field) => fieldAffectsData(field) && field.name === 'id',
|
||||
)
|
||||
|
||||
if (!customIDField) return new mongoose.Types.ObjectId(value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
interface RelationObject {
|
||||
relationTo: string
|
||||
value: number | string
|
||||
}
|
||||
|
||||
function isValidRelationObject(value: unknown): value is RelationObject {
|
||||
return typeof value === 'object' && value !== null && 'relationTo' in value && 'value' in value
|
||||
}
|
||||
|
||||
export const getBeforeChangeHook =
|
||||
({ config, field }: { config: Config; field: RelationshipField | UploadField }): FieldHook =>
|
||||
({ value }) => {
|
||||
let relatedCollection: CollectionConfig | undefined
|
||||
|
||||
const hasManyRelations = typeof field.relationTo !== 'string'
|
||||
|
||||
if (!hasManyRelations) {
|
||||
relatedCollection = config.collections?.find(({ slug }) => slug === field.relationTo)
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => {
|
||||
// Handle has many
|
||||
if (relatedCollection && val && (typeof val === 'string' || typeof val === 'number')) {
|
||||
return convertValue({
|
||||
relatedCollection,
|
||||
value: val,
|
||||
})
|
||||
}
|
||||
|
||||
// Handle has many - polymorphic
|
||||
if (isValidRelationObject(val)) {
|
||||
const relatedCollectionForSingleValue = config.collections?.find(
|
||||
({ slug }) => slug === val.relationTo,
|
||||
)
|
||||
|
||||
if (relatedCollectionForSingleValue) {
|
||||
return {
|
||||
relationTo: val.relationTo,
|
||||
value: convertValue({
|
||||
relatedCollection: relatedCollectionForSingleValue,
|
||||
value: val.value,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val
|
||||
})
|
||||
}
|
||||
|
||||
// Handle has one - polymorphic
|
||||
if (isValidRelationObject(value)) {
|
||||
relatedCollection = config.collections?.find(({ slug }) => slug === value.relationTo)
|
||||
|
||||
if (relatedCollection) {
|
||||
return {
|
||||
relationTo: value.relationTo,
|
||||
value: convertValue({ relatedCollection, value: value.value }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle has one
|
||||
if (relatedCollection && value && (typeof value === 'string' || typeof value === 'number')) {
|
||||
return convertValue({
|
||||
relatedCollection,
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
80
packages/plugin-relationship-object-ids/src/index.ts
Normal file
80
packages/plugin-relationship-object-ids/src/index.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import type { Config } from 'payload/config'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
import { getBeforeChangeHook } from './hooks/beforeChange.js'
|
||||
|
||||
const traverseFields = ({ config, fields }: { config: Config; fields: Field[] }): Field[] => {
|
||||
return fields.map((field) => {
|
||||
if (field.type === 'relationship' || field.type === 'upload') {
|
||||
return {
|
||||
...field,
|
||||
hooks: {
|
||||
...(field.hooks || {}),
|
||||
beforeChange: [
|
||||
...(field.hooks?.beforeChange || []),
|
||||
getBeforeChangeHook({ config, field }),
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if ('fields' in field) {
|
||||
return {
|
||||
...field,
|
||||
fields: traverseFields({ config, fields: field.fields }),
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'tabs') {
|
||||
return {
|
||||
...field,
|
||||
tabs: field.tabs.map((tab) => {
|
||||
return {
|
||||
...tab,
|
||||
fields: traverseFields({ config, fields: tab.fields }),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'blocks') {
|
||||
return {
|
||||
...field,
|
||||
blocks: field.blocks.map((block) => {
|
||||
return {
|
||||
...block,
|
||||
fields: traverseFields({ config, fields: block.fields }),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
return field
|
||||
})
|
||||
}
|
||||
|
||||
export const relationshipsAsObjectID =
|
||||
(/** Possible args in the future */) =>
|
||||
(config: Config): Config => {
|
||||
return {
|
||||
...config,
|
||||
collections: (config.collections || []).map((collection) => {
|
||||
return {
|
||||
...collection,
|
||||
fields: traverseFields({
|
||||
config,
|
||||
fields: collection.fields,
|
||||
}),
|
||||
}
|
||||
}),
|
||||
globals: (config.globals || []).map((global) => {
|
||||
return {
|
||||
...global,
|
||||
fields: traverseFields({
|
||||
config,
|
||||
fields: global.fields,
|
||||
}),
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
24
packages/plugin-relationship-object-ids/tsconfig.json
Normal file
24
packages/plugin-relationship-object-ids/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true, // Make sure typescript knows that this module depends on their references
|
||||
"noEmit": false /* Do not emit outputs. */,
|
||||
"emitDeclarationOnly": true,
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
"rootDir": "./src" /* Specify the root folder within your source files. */
|
||||
},
|
||||
"exclude": [
|
||||
"dist",
|
||||
"build",
|
||||
"tests",
|
||||
"test",
|
||||
"node_modules",
|
||||
".eslintrc.cjs",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx"
|
||||
],
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
|
||||
"references": [{ "path": "../payload" }]
|
||||
}
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -1075,6 +1075,19 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../payload
|
||||
|
||||
packages/plugin-relationship-object-ids:
|
||||
dependencies:
|
||||
mongoose:
|
||||
specifier: 6.12.3
|
||||
version: 6.12.3
|
||||
devDependencies:
|
||||
'@payloadcms/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../eslint-config-payload
|
||||
payload:
|
||||
specifier: workspace:*
|
||||
version: link:../payload
|
||||
|
||||
packages/plugin-search:
|
||||
dependencies:
|
||||
'@payloadcms/ui':
|
||||
@@ -1619,6 +1632,9 @@ importers:
|
||||
'@payloadcms/plugin-redirects':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-redirects
|
||||
'@payloadcms/plugin-relationship-object-ids':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-relationship-object-ids
|
||||
'@payloadcms/plugin-search':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-search
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@payloadcms/plugin-form-builder": "workspace:*",
|
||||
"@payloadcms/plugin-nested-docs": "workspace:*",
|
||||
"@payloadcms/plugin-redirects": "workspace:*",
|
||||
"@payloadcms/plugin-relationship-object-ids": "workspace:*",
|
||||
"@payloadcms/plugin-search": "workspace:*",
|
||||
"@payloadcms/plugin-sentry": "workspace:*",
|
||||
"@payloadcms/plugin-seo": "workspace:*",
|
||||
|
||||
1
test/plugin-relationship-object-ids/.gitignore
vendored
Normal file
1
test/plugin-relationship-object-ids/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
uploads
|
||||
129
test/plugin-relationship-object-ids/config.ts
Normal file
129
test/plugin-relationship-object-ids/config.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { relationshipsAsObjectID } from '@payloadcms/plugin-relationship-object-ids'
|
||||
import path from 'path'
|
||||
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
collections: [
|
||||
{
|
||||
slug: 'uploads',
|
||||
upload: true,
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
slug: 'pages',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'posts',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'relations',
|
||||
fields: [
|
||||
{
|
||||
name: 'hasOne',
|
||||
type: 'relationship',
|
||||
relationTo: 'posts',
|
||||
filterOptions: ({ id }) => ({ id: { not_equals: id } }),
|
||||
},
|
||||
{
|
||||
name: 'hasOnePoly',
|
||||
type: 'relationship',
|
||||
relationTo: ['pages', 'posts'],
|
||||
},
|
||||
{
|
||||
name: 'hasMany',
|
||||
type: 'relationship',
|
||||
relationTo: 'posts',
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'hasManyPoly',
|
||||
type: 'relationship',
|
||||
relationTo: ['pages', 'posts'],
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'upload',
|
||||
type: 'upload',
|
||||
relationTo: 'uploads',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
plugins: [relationshipsAsObjectID()],
|
||||
onInit: async (payload) => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: 'dev@payloadcms.com',
|
||||
password: 'test',
|
||||
},
|
||||
})
|
||||
|
||||
const page = await payload.create({
|
||||
collection: 'pages',
|
||||
data: {
|
||||
title: 'page',
|
||||
},
|
||||
})
|
||||
|
||||
const post1 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post 1',
|
||||
},
|
||||
})
|
||||
|
||||
const post2 = await payload.create({
|
||||
collection: 'posts',
|
||||
data: {
|
||||
title: 'post 2',
|
||||
},
|
||||
})
|
||||
|
||||
const upload = await payload.create({
|
||||
collection: 'uploads',
|
||||
data: {},
|
||||
filePath: path.resolve(__dirname, './payload-logo.png'),
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'relations',
|
||||
depth: 0,
|
||||
data: {
|
||||
hasOne: post1.id,
|
||||
hasOnePoly: { relationTo: 'pages', value: page.id },
|
||||
hasMany: [post1.id, post2.id],
|
||||
hasManyPoly: [
|
||||
{ relationTo: 'posts', value: post1.id },
|
||||
{ relationTo: 'pages', value: page.id },
|
||||
],
|
||||
upload: upload.id,
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: 'relations',
|
||||
depth: 0,
|
||||
data: {
|
||||
hasOnePoly: { relationTo: 'pages', value: page.id },
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
107
test/plugin-relationship-object-ids/int.spec.ts
Normal file
107
test/plugin-relationship-object-ids/int.spec.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/* eslint-disable jest/no-if */
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
import { initPayloadInt } from '../helpers/initPayloadInt.js'
|
||||
import configPromise from './config.js'
|
||||
|
||||
describe('Relationship Object IDs Plugin', () => {
|
||||
let relations: any
|
||||
let posts: any
|
||||
let payload: Payload
|
||||
|
||||
beforeAll(async () => {
|
||||
;({ payload } = await initPayloadInt(configPromise))
|
||||
})
|
||||
|
||||
it('seeds data accordingly', async () => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const relationsQuery = await payload.find({
|
||||
collection: 'relations',
|
||||
sort: 'createdAt',
|
||||
})
|
||||
|
||||
relations = relationsQuery.docs
|
||||
|
||||
const postsQuery = await payload.find({
|
||||
collection: 'posts',
|
||||
sort: 'createdAt',
|
||||
})
|
||||
|
||||
posts = postsQuery.docs
|
||||
|
||||
expect(relationsQuery.totalDocs).toEqual(2)
|
||||
expect(postsQuery.totalDocs).toEqual(2)
|
||||
}
|
||||
})
|
||||
|
||||
it('stores relations as object ids', async () => {
|
||||
// eslint-disable-next-line jest/no-if
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const docs = await payload.db.collections.relations.find()
|
||||
expect(typeof docs[0].hasOne).toBe('object')
|
||||
expect(typeof docs[0].hasOnePoly.value).toBe('object')
|
||||
expect(typeof docs[0].hasMany[0]).toBe('object')
|
||||
expect(typeof docs[0].hasManyPoly[0].value).toBe('object')
|
||||
expect(typeof docs[0].upload).toBe('object')
|
||||
}
|
||||
})
|
||||
|
||||
it('can query by relationship id', async () => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const { totalDocs } = await payload.find({
|
||||
collection: 'relations',
|
||||
where: {
|
||||
hasOne: {
|
||||
equals: posts[0].id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(totalDocs).toStrictEqual(1)
|
||||
}
|
||||
})
|
||||
|
||||
it('populates relations', () => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const populatedPostTitle =
|
||||
// eslint-disable-next-line jest/no-if
|
||||
typeof relations[0].hasOne === 'object' ? relations[0].hasOne.title : undefined
|
||||
expect(populatedPostTitle).toBeDefined()
|
||||
|
||||
const populatedUploadFilename =
|
||||
typeof relations[0].upload === 'object' ? relations[0].upload.filename : undefined
|
||||
|
||||
expect(populatedUploadFilename).toBeDefined()
|
||||
}
|
||||
})
|
||||
|
||||
it('can query by nested property', async () => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const { totalDocs } = await payload.find({
|
||||
collection: 'relations',
|
||||
where: {
|
||||
'hasOne.title': {
|
||||
equals: 'post 1',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(totalDocs).toStrictEqual(1)
|
||||
}
|
||||
})
|
||||
|
||||
it('can query using the "in" operator', async () => {
|
||||
if (payload.db.name === 'mongoose') {
|
||||
const { totalDocs } = await payload.find({
|
||||
collection: 'relations',
|
||||
where: {
|
||||
hasMany: {
|
||||
in: [posts[0].id],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(totalDocs).toStrictEqual(1)
|
||||
}
|
||||
})
|
||||
})
|
||||
BIN
test/plugin-relationship-object-ids/payload-logo.png
Normal file
BIN
test/plugin-relationship-object-ids/payload-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Reference in New Issue
Block a user