mirror of
https://github.com/directus/directus.git
synced 2026-02-06 11:55:00 -05:00
Merge pull request #54 from directus/relational-write
Add relational write
This commit is contained in:
@@ -2,7 +2,7 @@ import express from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import validateQuery from '../middleware/validate-query';
|
||||
import { readActivities, readActivity } from '../services/activity';
|
||||
import * as ActivityService from '../services/activity';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
|
||||
const router = express.Router();
|
||||
@@ -13,7 +13,7 @@ router.get(
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const records = await readActivities(req.sanitizedQuery);
|
||||
const records = await ActivityService.readActivities(req.sanitizedQuery);
|
||||
return res.json({
|
||||
data: records,
|
||||
});
|
||||
@@ -26,7 +26,7 @@ router.get(
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const record = await readActivity(req.params.pk, req.sanitizedQuery);
|
||||
const record = await ActivityService.readActivity(req.params.pk, req.sanitizedQuery);
|
||||
|
||||
return res.json({
|
||||
data: record,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import { createItem, readItems, readItem, updateItem, deleteItem } from '../services/items';
|
||||
import * as ItemsService from '../services/items';
|
||||
import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import validateCollection from '../middleware/validate-collection';
|
||||
import validateSingleton from '../middleware/validate-singleton';
|
||||
@@ -14,8 +14,11 @@ router.post(
|
||||
'/:collection',
|
||||
validateCollection,
|
||||
validateSingleton,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const item = await createItem(req.params.collection, req.body);
|
||||
const primaryKey = await ItemsService.createItem(req.collection, req.body);
|
||||
const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery);
|
||||
|
||||
ActivityService.createActivity({
|
||||
action: ActivityService.Action.CREATE,
|
||||
@@ -38,8 +41,8 @@ router.get(
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const [records, meta] = await Promise.all([
|
||||
readItems(req.params.collection, req.sanitizedQuery),
|
||||
MetaService.getMetaForQuery(req.params.collection, req.sanitizedQuery),
|
||||
ItemsService.readItems(req.collection, req.sanitizedQuery),
|
||||
MetaService.getMetaForQuery(req.collection, req.sanitizedQuery),
|
||||
]);
|
||||
|
||||
return res.json({
|
||||
@@ -52,8 +55,14 @@ router.get(
|
||||
router.get(
|
||||
'/:collection/:pk',
|
||||
validateCollection,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const record = await readItem(req.params.collection, req.params.pk);
|
||||
const record = await ItemsService.readItem(
|
||||
req.collection,
|
||||
req.params.pk,
|
||||
req.sanitizedQuery
|
||||
);
|
||||
|
||||
return res.json({
|
||||
data: record,
|
||||
@@ -64,8 +73,11 @@ router.get(
|
||||
router.patch(
|
||||
'/:collection/:pk',
|
||||
validateCollection,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const item = await updateItem(req.params.collection, req.params.pk, req.body);
|
||||
const primaryKey = await ItemsService.updateItem(req.collection, req.params.pk, req.body);
|
||||
const item = await ItemsService.readItem(req.collection, primaryKey, req.sanitizedQuery);
|
||||
|
||||
ActivityService.createActivity({
|
||||
action: ActivityService.Action.UPDATE,
|
||||
@@ -84,7 +96,7 @@ router.delete(
|
||||
'/:collection/:pk',
|
||||
validateCollection,
|
||||
asyncHandler(async (req, res) => {
|
||||
await deleteItem(req.params.collection, req.params.pk);
|
||||
await ItemsService.deleteItem(req.collection, req.params.pk);
|
||||
|
||||
ActivityService.createActivity({
|
||||
action: ActivityService.Action.DELETE,
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const createCollectionPreset = async (data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.createItem('directus_collection_presets', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_collection_presets', data);
|
||||
return await ItemsService.readItem('directus_collection_presets', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readCollectionPresets = async (query: Query) => {
|
||||
@@ -18,7 +19,8 @@ export const updateCollectionPreset = async (
|
||||
data: Record<string, any>,
|
||||
query: Query
|
||||
) => {
|
||||
return await ItemsService.updateItem('directus_collection_presets', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_collection_presets', pk, data);
|
||||
return await ItemsService.readItem('directus_collection_presets', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteCollectionPreset = async (pk: string | number) => {
|
||||
|
||||
@@ -36,7 +36,7 @@ export const create = async (payload: any) => {
|
||||
});
|
||||
});
|
||||
|
||||
const collection = await ItemsService.createItem('directus_collections', {
|
||||
const primaryKey = await ItemsService.createItem('directus_collections', {
|
||||
collection: payload.collection,
|
||||
hidden: payload.hidden || false,
|
||||
single: payload.single || false,
|
||||
@@ -45,6 +45,8 @@ export const create = async (payload: any) => {
|
||||
translation: payload.translation || null,
|
||||
});
|
||||
|
||||
const collection = await ItemsService.createItem('directus_collections', primaryKey);
|
||||
|
||||
/**
|
||||
* @TODO make this flexible and based on payload
|
||||
*/
|
||||
|
||||
@@ -51,7 +51,8 @@ export const createFile = async (
|
||||
}
|
||||
|
||||
await storage.disk(data.storage).put(payload.filename_disk, stream.pipe(pipeline));
|
||||
return await ItemsService.createItem('directus_files', payload, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_files', payload);
|
||||
return await ItemsService.readItem('directus_files', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readFiles = async (query: Query) => {
|
||||
@@ -90,7 +91,8 @@ export const updateFile = async (
|
||||
await storage.disk(file.storage).put(file.filename_disk, stream as any);
|
||||
}
|
||||
|
||||
return await ItemsService.updateItem('directus_files', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_files', pk, data);
|
||||
return await ItemsService.readItem('directus_files', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteFile = async (pk: string | number) => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -3,16 +3,32 @@ 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);
|
||||
|
||||
payload = await PayloadService.processM2O(collection, payload);
|
||||
|
||||
export const createItem = async (
|
||||
collection: string,
|
||||
data: Record<string, any>,
|
||||
query: Query = {}
|
||||
) => {
|
||||
const payload = await PayloadService.processValues('create', collection, data);
|
||||
const primaryKeyField = await schemaInspector.primary(collection);
|
||||
const result = await database(collection).insert(payload).returning(primaryKeyField);
|
||||
return readItem(collection, result[0], query);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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>>(
|
||||
@@ -51,16 +67,27 @@ export const readItem = async <T = any>(
|
||||
export const updateItem = async (
|
||||
collection: string,
|
||||
pk: number | string,
|
||||
data: Record<string, any>,
|
||||
query: Query = {}
|
||||
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('id');
|
||||
return readItem(collection, result[0], query);
|
||||
.returning(primaryKeyField);
|
||||
|
||||
return primaryKeys[0];
|
||||
};
|
||||
|
||||
export const deleteItem = async (collection: string, pk: number | string) => {
|
||||
|
||||
@@ -9,9 +9,51 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import database from '../database';
|
||||
import { clone } from 'lodash';
|
||||
import { File } from '../types/files';
|
||||
import { Relation } from '../types/relation';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
type Operation = 'create' | 'read' | 'update';
|
||||
|
||||
type Transformers = {
|
||||
[type: string]: (
|
||||
operation: Operation,
|
||||
value: any,
|
||||
payload: Record<string, any>
|
||||
) => Promise<any>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @todo allow this to be extended
|
||||
*/
|
||||
const transformers: Transformers = {
|
||||
async hash(operation, value) {
|
||||
if (!value) return;
|
||||
|
||||
if (operation === 'create' || operation === 'update') {
|
||||
return await argon2.hash(String(value));
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
async uuid(operation, value) {
|
||||
if (operation === 'create' && !value) {
|
||||
return uuidv4();
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
async 'file-info'(operation, value, payload: File) {
|
||||
if (operation === 'read' && payload) {
|
||||
return {
|
||||
asset_url: new URL(`/assets/${payload.id}`, process.env.PUBLIC_URL),
|
||||
};
|
||||
}
|
||||
|
||||
// This is an non-existing column, so there isn't any data to save
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Process and update all the special fields in the given payload
|
||||
*
|
||||
@@ -47,8 +89,6 @@ export const processValues = async (
|
||||
})
|
||||
);
|
||||
|
||||
console.log(processedPayload);
|
||||
|
||||
/** @TODO
|
||||
*
|
||||
* - Make config.ts file in root
|
||||
@@ -69,49 +109,113 @@ async function processField(
|
||||
payload: Record<string, any>,
|
||||
operation: Operation
|
||||
) {
|
||||
switch (field.special) {
|
||||
case 'hash':
|
||||
return await genHash(operation, payload[field.field], payload);
|
||||
case 'uuid':
|
||||
return await genUUID(operation, payload[field.field], payload);
|
||||
case 'file-links':
|
||||
// This is a system special type that only works on directus_files
|
||||
return await genFileLinks(operation, payload[field.field], payload as File);
|
||||
default:
|
||||
return payload[field.field];
|
||||
if (transformers.hasOwnProperty(field.special)) {
|
||||
return await transformers[field.special](operation, payload[field.field], payload);
|
||||
}
|
||||
|
||||
return payload[field.field];
|
||||
}
|
||||
|
||||
/**
|
||||
* @note The following functions can be called _a lot_. Make sure to utilize some form of caching
|
||||
* if you have to rely on heavy operations
|
||||
* 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>) => {
|
||||
const payloadClone = clone(payload);
|
||||
|
||||
async function genHash(operation: Operation, value: any, payload: Record<string, any>) {
|
||||
if (!value) return;
|
||||
const relations = await database
|
||||
.select<Relation[]>('*')
|
||||
.from('directus_relations')
|
||||
.where({ collection_many: collection });
|
||||
|
||||
if (operation === 'create' || operation === 'update') {
|
||||
return await argon2.hash(String(value));
|
||||
}
|
||||
// Only process related records that are actually in the payload
|
||||
const relationsToProcess = relations.filter((relation) => {
|
||||
return (
|
||||
payloadClone.hasOwnProperty(relation.field_many) &&
|
||||
typeof payloadClone[relation.field_many] === 'object'
|
||||
);
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
// Save all nested m2o records
|
||||
await Promise.all(
|
||||
relationsToProcess.map(async (relation) => {
|
||||
const relatedRecord = payloadClone[relation.field_many];
|
||||
const hasPrimaryKey = relatedRecord.hasOwnProperty(relation.primary_one);
|
||||
|
||||
async function genUUID(operation: Operation, value: any, payload: Record<string, any>) {
|
||||
if (operation === 'create' && !value) {
|
||||
return uuidv4();
|
||||
}
|
||||
let relatedPrimaryKey: string | number;
|
||||
|
||||
return value;
|
||||
}
|
||||
if (hasPrimaryKey) {
|
||||
relatedPrimaryKey = relatedRecord[relation.primary_one];
|
||||
await ItemsService.updateItem(
|
||||
relation.collection_one,
|
||||
relatedPrimaryKey,
|
||||
relatedRecord
|
||||
);
|
||||
} else {
|
||||
relatedPrimaryKey = await ItemsService.createItem(
|
||||
relation.collection_one,
|
||||
relatedRecord
|
||||
);
|
||||
}
|
||||
|
||||
async function genFileLinks(operation: Operation, value: undefined, payload: File) {
|
||||
if (operation === 'read' && payload) {
|
||||
return {
|
||||
asset_url: new URL(`/assets/${payload.id}`, process.env.PUBLIC_URL),
|
||||
};
|
||||
}
|
||||
// Overwrite the nested object with just the primary key, so the parent level can be saved correctly
|
||||
payloadClone[relation.field_many] = relatedPrimaryKey;
|
||||
})
|
||||
);
|
||||
|
||||
// This is an non-existing column, so there isn't any data to save
|
||||
return undefined;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const createPermission = async (data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.createItem('directus_permissions', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_permissions', data);
|
||||
return await ItemsService.readItem('directus_permissions', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readPermissions = async (query: Query) => {
|
||||
@@ -18,7 +19,8 @@ export const updatePermission = async (
|
||||
data: Record<string, any>,
|
||||
query: Query
|
||||
) => {
|
||||
return await ItemsService.updateItem('directus_permissions', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_permissions', pk, data);
|
||||
return await ItemsService.readItem('directus_permissions', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deletePermission = async (pk: string | number) => {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const createRelation = async (data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.createItem('directus_relations', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_relations', data);
|
||||
return ItemsService.readItem('directus_relations', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readRelations = async (query: Query) => {
|
||||
@@ -18,7 +19,8 @@ export const updateRelation = async (
|
||||
data: Record<string, any>,
|
||||
query: Query
|
||||
) => {
|
||||
return await ItemsService.updateItem('directus_relations', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_relations', pk, data);
|
||||
return ItemsService.readItem('directus_relations', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteRelation = async (pk: string | number) => {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const createRole = async (data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.createItem('directus_roles', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_roles', data);
|
||||
return await ItemsService.readItem('directus_roles', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readRoles = async (query: Query) => {
|
||||
@@ -14,7 +15,8 @@ export const readRole = async (pk: string | number, query: Query) => {
|
||||
};
|
||||
|
||||
export const updateRole = async (pk: string | number, data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.updateItem('directus_roles', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_roles', pk, data);
|
||||
return await ItemsService.readItem('directus_roles', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteRole = async (pk: string | number) => {
|
||||
|
||||
@@ -16,5 +16,6 @@ export const updateSettings = async (
|
||||
query: Query
|
||||
) => {
|
||||
/** @NOTE I guess this can technically update _all_ items, as we expect there to only be one */
|
||||
return await ItemsService.updateItem('directus_settings', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_settings', pk, data);
|
||||
return await ItemsService.readItem('directus_settings', primaryKey, query);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,8 @@ import argon2 from 'argon2';
|
||||
import { InvalidPayloadException } from '../exceptions';
|
||||
|
||||
export const createUser = async (data: Record<string, any>, query?: Query) => {
|
||||
return await ItemsService.createItem('directus_users', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_users', data);
|
||||
return await ItemsService.readItem('directus_user', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readUsers = async (query?: Query) => {
|
||||
@@ -25,7 +26,8 @@ export const updateUser = async (pk: string | number, data: Record<string, any>,
|
||||
*
|
||||
* Maybe make this an option?
|
||||
*/
|
||||
return await ItemsService.updateItem('directus_users', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_users', pk, data);
|
||||
return await ItemsService.readItem('directus_user', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteUser = async (pk: string | number) => {
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
|
||||
export const createWebhook = async (data: Record<string, any>, query: Query) => {
|
||||
return await ItemsService.createItem('directus_webhooks', data, query);
|
||||
const primaryKey = await ItemsService.createItem('directus_webhooks', data);
|
||||
return await ItemsService.readItem('directus_webhooks', primaryKey, query);
|
||||
};
|
||||
|
||||
export const readWebhooks = async (query: Query) => {
|
||||
@@ -18,7 +19,8 @@ export const updateWebhook = async (
|
||||
data: Record<string, any>,
|
||||
query: Query
|
||||
) => {
|
||||
return await ItemsService.updateItem('directus_webhooks', pk, data, query);
|
||||
const primaryKey = await ItemsService.updateItem('directus_webhooks', pk, data);
|
||||
return await ItemsService.readItem('directus_webhooks', primaryKey, query);
|
||||
};
|
||||
|
||||
export const deleteWebhook = async (pk: string | number) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user