@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
50 lines (49 loc) • 2.01 kB
JavaScript
import getDatabase from '../database/index.js';
import { ForbiddenError } from '@directus/errors';
import { applyDiff } from '../utils/apply-diff.js';
import { getSnapshotDiff } from '../utils/get-snapshot-diff.js';
import { getSnapshot } from '../utils/get-snapshot.js';
import { getVersionedHash } from '../utils/get-versioned-hash.js';
import { validateApplyDiff } from '../utils/validate-diff.js';
import { validateSnapshot } from '../utils/validate-snapshot.js';
export class SchemaService {
knex;
accountability;
constructor(options) {
this.knex = options.knex ?? getDatabase();
this.accountability = options.accountability ?? null;
}
async snapshot() {
if (this.accountability?.admin !== true)
throw new ForbiddenError();
const currentSnapshot = await getSnapshot({ database: this.knex });
return currentSnapshot;
}
async apply(payload) {
if (this.accountability?.admin !== true)
throw new ForbiddenError();
const currentSnapshot = await this.snapshot();
const snapshotWithHash = this.getHashedSnapshot(currentSnapshot);
if (!validateApplyDiff(payload, snapshotWithHash))
return;
await applyDiff(currentSnapshot, payload.diff, { database: this.knex });
}
async diff(snapshot, options) {
if (this.accountability?.admin !== true)
throw new ForbiddenError();
validateSnapshot(snapshot, options?.force);
const currentSnapshot = options?.currentSnapshot ?? (await getSnapshot({ database: this.knex }));
const diff = getSnapshotDiff(currentSnapshot, snapshot);
if (diff.collections.length === 0 && diff.fields.length === 0 && diff.relations.length === 0) {
return null;
}
return diff;
}
getHashedSnapshot(snapshot) {
const snapshotHash = getVersionedHash(snapshot);
return {
...snapshot,
hash: snapshotHash,
};
}
}