Add relational o2m write

This commit is contained in:
rijkvanzanten
2020-07-08 12:45:21 -04:00
parent 9c36f90192
commit c44bc94af8
5 changed files with 104 additions and 19 deletions

View File

@@ -12,7 +12,8 @@ export enum Action {
}
export const createActivity = async (data: Record<string, any>, query?: Query) => {
return await ItemsService.createItem('directus_activity', data, query);
const primaryKey = await ItemsService.createItem('directus_activity', data);
return await ItemsService.readItem('directus_activity', primaryKey, query);
};
export const readActivities = async (query?: Query) => {

View File

@@ -2,7 +2,8 @@ import { Query } from '../types/query';
import * as ItemsService from './items';
export const createFolder = async (data: Record<string, any>, query: Query) => {
return await ItemsService.createItem('directus_folders', data, query);
const primaryKey = await ItemsService.createItem('directus_folders', data);
return await ItemsService.readItem('directus_folders', primaryKey, query);
};
export const readFolders = async (query: Query) => {
@@ -18,7 +19,8 @@ export const updateFolder = async (
data: Record<string, any>,
query: Query
) => {
return await ItemsService.updateItem('directus_folders', pk, data, query);
const primaryKey = await ItemsService.updateItem('directus_folders', pk, data);
return await ItemsService.readItem('directus_folders', primaryKey, query);
};
export const deleteFolder = async (pk: string | number) => {

View File

@@ -3,6 +3,7 @@ import { Query } from '../types/query';
import runAST from '../database/run-ast';
import getAST from '../utils/get-ast';
import * as PayloadService from './payload';
import { pick } from 'lodash';
export const createItem = async (collection: string, data: Record<string, any>) => {
let payload = await PayloadService.processValues('create', collection, data);
@@ -10,11 +11,24 @@ export const createItem = async (collection: string, data: Record<string, any>)
payload = await PayloadService.processM2O(collection, payload);
const primaryKeyField = await schemaInspector.primary(collection);
const result = await database(collection).insert(payload).returning(primaryKeyField);
// payload process o2m
// Only insert the values that actually save to an existing column. This ensures we ignore aliases etc
const columns = await schemaInspector.columns(collection);
const primaryKeys = await database(collection)
.insert(
pick(
payload,
columns.map(({ column }) => column)
)
)
.returning(primaryKeyField);
return result[0]; // pk
// This allows the o2m values to be populated correctly
payload[primaryKeyField] = primaryKeys[0];
await PayloadService.processO2M(collection, payload);
return primaryKeys[0];
};
export const readItems = async <T = Record<string, any>>(
@@ -55,14 +69,25 @@ export const updateItem = async (
pk: number | string,
data: Record<string, any>
) => {
const payload = await PayloadService.processValues('create', collection, data);
let payload = await PayloadService.processValues('create', collection, data);
payload = await PayloadService.processM2O(collection, payload);
const primaryKeyField = await schemaInspector.primary(collection);
const result = await database(collection)
.update(payload)
// Only insert the values that actually save to an existing column. This ensures we ignore aliases etc
const columns = await schemaInspector.columns(collection);
const primaryKeys = await database(collection)
.update(
pick(
payload,
columns.map(({ column }) => column)
)
)
.where({ [primaryKeyField]: pk })
.returning(primaryKeyField);
return result[0]; // pk
return primaryKeys[0];
};
export const deleteItem = async (collection: string, pk: number | string) => {

View File

@@ -119,10 +119,9 @@ async function processField(
/**
* Recursively checks for nested relational items, and saves them bottom up, to ensure we have IDs etc ready
*/
export const processM2O = async (
collection: string,
payload: Record<string, any> | Record<string, any>[]
) => {
export const processM2O = async (collection: string, payload: Record<string, any>) => {
const payloadClone = clone(payload);
const relations = await database
.select<Relation[]>('*')
.from('directus_relations')
@@ -131,15 +130,15 @@ export const processM2O = async (
// Only process related records that are actually in the payload
const relationsToProcess = relations.filter((relation) => {
return (
payload.hasOwnProperty(relation.field_many) &&
typeof payload[relation.field_many] === 'object'
payloadClone.hasOwnProperty(relation.field_many) &&
typeof payloadClone[relation.field_many] === 'object'
);
});
// Save all nested m2o records
await Promise.all(
relationsToProcess.map(async (relation) => {
const relatedRecord = payload[relation.field_many];
const relatedRecord = payloadClone[relation.field_many];
const hasPrimaryKey = relatedRecord.hasOwnProperty(relation.primary_one);
let relatedPrimaryKey: string | number;
@@ -159,9 +158,64 @@ export const processM2O = async (
}
// Overwrite the nested object with just the primary key, so the parent level can be saved correctly
payload[relation.field_many] = relatedPrimaryKey;
payloadClone[relation.field_many] = relatedPrimaryKey;
})
);
return payload;
return payloadClone;
};
export const processO2M = async (collection: string, payload: Record<string, any>) => {
const payloadClone = clone(payload);
const relations = await database
.select<Relation[]>('*')
.from('directus_relations')
.where({ collection_one: collection });
// Only process related records that are actually in the payload
const relationsToProcess = relations.filter((relation) => {
return (
payloadClone.hasOwnProperty(relation.field_one) &&
Array.isArray(payloadClone[relation.field_one])
);
});
// Save all nested o2m records
await Promise.all(
relationsToProcess.map(async (relation) => {
const relatedRecords = payloadClone[relation.field_one];
await Promise.all(
relatedRecords.map(async (relatedRecord: any, index: number) => {
relatedRecord[relation.field_many] = payloadClone[relation.primary_one];
const hasPrimaryKey = relatedRecord.hasOwnProperty(relation.primary_many);
let relatedPrimaryKey: string | number;
if (hasPrimaryKey) {
relatedPrimaryKey = relatedRecord[relation.primary_many];
await ItemsService.updateItem(
relation.collection_many,
relatedPrimaryKey,
relatedRecord
);
} else {
relatedPrimaryKey = await ItemsService.createItem(
relation.collection_many,
relatedRecord
);
}
relatedRecord[relation.primary_many] = relatedPrimaryKey;
payloadClone[relation.field_one][index] = relatedRecord;
})
);
})
);
return payloadClone;
};

View File

@@ -1,7 +1,10 @@
export type Relation = {
id: number;
collection_many: string;
field_many: string;
primary_many: string;
collection_one: string;
field_one: string;
primary_one: string;