Move system collection rows out of DB

This commit is contained in:
rijkvanzanten
2020-10-28 16:26:46 -04:00
parent 53fb7a099a
commit 23fd029687
40 changed files with 129 additions and 133 deletions

View File

@@ -7,9 +7,6 @@ columns:
type: string
length: 64
nullable: false
references:
table: directus_collections
column: collection
field:
type: string
length: 64

View File

@@ -25,9 +25,6 @@ columns:
type: string
length: 64
nullable: false
references:
table: directus_collections
column: collection
item:
type: string
length: 255

View File

@@ -12,9 +12,6 @@ columns:
type: string
length: 64
nullable: false
references:
table: directus_collections
column: collection
action:
type: string
length: 10

View File

@@ -19,9 +19,6 @@ columns:
collection:
type: string
length: 64
references:
table: directus_collections
column: collection
search:
type: string
length: 100

View File

@@ -7,9 +7,6 @@ columns:
type: string
length: 64
nullable: false
references:
table: directus_collections
column: collection
many_field:
type: string
length: 64
@@ -21,9 +18,6 @@ columns:
one_collection:
type: string
length: 64
references:
table: directus_collections
column: collection
one_field:
type: string
length: 64

View File

@@ -14,9 +14,6 @@ columns:
type: string
length: 64
nullable: false
references:
table: directus_collections
column: collection
item:
type: string
length: 255

View File

@@ -25,33 +25,6 @@ type TableSeed = {
};
};
type RowSeed = {
table: string;
defaults: Record<string, any>;
data: Record<string, any>[];
};
type FieldSeed = {
table: string;
fields: {
collection: string;
field: string;
special: string | null;
interface: string | null;
options: Record<string, any> | null;
display: string | null;
display_options: Record<string, any> | null;
locked: boolean;
readonly: boolean;
hidden: boolean;
sort: number | null;
width: string | null;
group: number | null;
translations: Record<string, any> | null;
note: string | null;
}[];
};
export default async function runSeed(database: Knex) {
const exists = await database.schema.hasTable('directus_collections');
@@ -59,19 +32,13 @@ export default async function runSeed(database: Knex) {
throw new Error('Database is already installed');
}
await createTables(database);
await insertRows(database);
await insertFields(database);
}
async function createTables(database: Knex) {
const tableSeeds = await fse.readdir(path.resolve(__dirname, './01-tables/'));
const tableSeeds = await fse.readdir(path.resolve(__dirname));
for (const tableSeedFile of tableSeeds) {
const yamlRaw = await fse.readFile(
path.resolve(__dirname, './01-tables', tableSeedFile),
'utf8'
);
if (tableSeedFile === 'run.ts') continue;
const yamlRaw = await fse.readFile(path.resolve(__dirname, tableSeedFile), 'utf8');
const seedData = yaml.safeLoad(yamlRaw) as TableSeed;
await database.schema.createTable(seedData.table, (tableBuilder) => {
@@ -129,60 +96,60 @@ async function createTables(database: Knex) {
}
}
async function insertRows(database: Knex) {
const rowSeeds = await fse.readdir(path.resolve(__dirname, './02-rows/'));
// async function insertRows(database: Knex) {
// const rowSeeds = await fse.readdir(path.resolve(__dirname, './02-rows/'));
for (const rowSeedFile of rowSeeds) {
const yamlRaw = await fse.readFile(
path.resolve(__dirname, './02-rows', rowSeedFile),
'utf8'
);
const seedData = yaml.safeLoad(yamlRaw) as RowSeed;
// for (const rowSeedFile of rowSeeds) {
// const yamlRaw = await fse.readFile(
// path.resolve(__dirname, './02-rows', rowSeedFile),
// 'utf8'
// );
// const seedData = yaml.safeLoad(yamlRaw) as RowSeed;
const dataWithDefaults = seedData.data.map((row) => {
for (const [key, value] of Object.entries(row)) {
if (value !== null && (typeof value === 'object' || Array.isArray(value))) {
row[key] = JSON.stringify(value);
}
}
// const dataWithDefaults = seedData.data.map((row) => {
// for (const [key, value] of Object.entries(row)) {
// if (value !== null && (typeof value === 'object' || Array.isArray(value))) {
// row[key] = JSON.stringify(value);
// }
// }
return merge({}, seedData.defaults, row);
});
// return merge({}, seedData.defaults, row);
// });
await database.batchInsert(seedData.table, dataWithDefaults);
}
}
// await database.batchInsert(seedData.table, dataWithDefaults);
// }
// }
async function insertFields(database: Knex) {
const fieldSeeds = await fse.readdir(path.resolve(__dirname, './03-fields/'));
// async function insertFields(database: Knex) {
// const fieldSeeds = await fse.readdir(path.resolve(__dirname, './03-fields/'));
const defaultsYaml = await fse.readFile(
path.resolve(__dirname, './03-fields/_defaults.yaml'),
'utf8'
);
const defaults = yaml.safeLoad(defaultsYaml) as FieldSeed;
// const defaultsYaml = await fse.readFile(
// path.resolve(__dirname, './03-fields/_defaults.yaml'),
// 'utf8'
// );
// const defaults = yaml.safeLoad(defaultsYaml) as FieldSeed;
for (const fieldSeedFile of fieldSeeds) {
const yamlRaw = await fse.readFile(
path.resolve(__dirname, './03-fields', fieldSeedFile),
'utf8'
);
const seedData = yaml.safeLoad(yamlRaw) as FieldSeed;
// for (const fieldSeedFile of fieldSeeds) {
// const yamlRaw = await fse.readFile(
// path.resolve(__dirname, './03-fields', fieldSeedFile),
// 'utf8'
// );
// const seedData = yaml.safeLoad(yamlRaw) as FieldSeed;
if (fieldSeedFile === '_defaults.yaml') {
continue;
}
// if (fieldSeedFile === '_defaults.yaml') {
// continue;
// }
const dataWithDefaults = seedData.fields.map((row) => {
for (const [key, value] of Object.entries(row)) {
if (value !== null && (typeof value === 'object' || Array.isArray(value))) {
(row as any)[key] = JSON.stringify(value);
}
}
// const dataWithDefaults = seedData.fields.map((row) => {
// for (const [key, value] of Object.entries(row)) {
// if (value !== null && (typeof value === 'object' || Array.isArray(value))) {
// (row as any)[key] = JSON.stringify(value);
// }
// }
return merge({}, defaults, row);
});
// return merge({}, defaults, row);
// });
await database.batchInsert('directus_fields', dataWithDefaults);
}
}
// await database.batchInsert('directus_fields', dataWithDefaults);
// }
// }

View File

@@ -0,0 +1,11 @@
import { requireYAML } from '../../../utils/require-yaml';
import { merge } from 'lodash';
import { CollectionMeta } from '../../../types';
const systemData = requireYAML(require.resolve('./collections.yaml'));
export const systemCollectionRows: CollectionMeta[] = systemData.data.map(
(row: Record<string, any>) => {
return merge({}, systemData.defaults, row);
}
);

View File

@@ -6,6 +6,8 @@ import { RequestHandler } from 'express';
import asyncHandler from 'express-async-handler';
import database from '../database';
import { ForbiddenException } from '../exceptions';
import { systemCollectionRows } from '../database/system-data/collections';
import { Collection } from '../types';
const collectionExists: RequestHandler = asyncHandler(async (req, res, next) => {
if (!req.params.collection) return next();
@@ -18,13 +20,21 @@ const collectionExists: RequestHandler = asyncHandler(async (req, res, next) =>
req.collection = req.params.collection;
const collectionInfo = await database
.select('singleton')
.from('directus_collections')
.where({ collection: req.collection })
.first();
if (req.collection.startsWith('directus_')) {
const systemRow = systemCollectionRows.find((collection) => {
return collection?.collection === req.collection;
});
req.singleton = collectionInfo?.singleton === true || collectionInfo?.singleton === 1;
req.singleton = !!systemRow?.singleton;
} else {
const collectionInfo = await database
.select('singleton')
.from('directus_collections')
.where({ collection: req.collection })
.first();
req.singleton = collectionInfo?.singleton === true || collectionInfo?.singleton === 1;
}
return next();
});

View File

@@ -1,5 +1,11 @@
import database, { schemaInspector } from '../database';
import { AbstractServiceOptions, Accountability, Collection, Relation } from '../types';
import {
AbstractServiceOptions,
Accountability,
Collection,
CollectionMeta,
Relation,
} from '../types';
import Knex from 'knex';
import { ForbiddenException, InvalidPayloadException } from '../exceptions';
import SchemaInspector from 'knex-schema-inspector';
@@ -7,6 +13,7 @@ import { FieldsService } from '../services/fields';
import { ItemsService } from '../services/items';
import cache from '../cache';
import { toArray } from '../utils/to-array';
import { systemCollectionRows } from '../database/system-data/collections';
export class CollectionsService {
knex: Knex;
@@ -106,6 +113,7 @@ export class CollectionsService {
knex: this.knex,
accountability: this.accountability,
});
const collectionKeys = toArray(collection);
if (this.accountability && this.accountability.admin !== true) {
@@ -135,7 +143,9 @@ export class CollectionsService {
const tables = tablesInDatabase.filter((table) => collectionKeys.includes(table.name));
const meta = (await collectionItemsService.readByQuery({
filter: { collection: { _in: collectionKeys } },
})) as Collection['meta'][];
})) as CollectionMeta[];
meta.push(...systemCollectionRows);
const collections: Collection[] = [];
@@ -173,7 +183,9 @@ export class CollectionsService {
const tablesToFetchInfoFor = tablesInDatabase.map((table) => table.name);
const meta = (await collectionItemsService.readByQuery({
filter: { collection: { _in: tablesToFetchInfoFor } },
})) as Collection['meta'][];
})) as CollectionMeta[];
meta.push(...systemCollectionRows);
const collections: Collection[] = [];

View File

@@ -7,7 +7,6 @@ import {
Field,
Relation,
Query,
AbstractService,
} from '../types';
import {
GraphQLString,
@@ -49,6 +48,7 @@ import { UsersService } from './users';
import { WebhooksService } from './webhooks';
import { getRelationType } from '../utils/get-relation-type';
import { systemCollectionRows } from '../database/system-data/collections';
export class GraphQLService {
accountability: Accountability | null;
@@ -504,11 +504,16 @@ export class GraphQLService {
});
}
const collectionInfo = await this.knex
.select('singleton')
.from('directus_collections')
.where({ collection: collection })
.first();
const collectionInfo =
(await this.knex
.select('singleton')
.from('directus_collections')
.where({ collection: collection })
.first()) ||
systemCollectionRows.find(
(collectionMeta) => collectionMeta?.collection === collection
);
const result =
collectionInfo?.singleton === true
? await service.readSingleton(query)

View File

@@ -3,6 +3,7 @@ import database from '../database';
import Knex from 'knex';
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
import SchemaInspector from 'knex-schema-inspector';
import { systemCollectionRows } from '../database/system-data/collections';
export class UtilsService {
knex: Knex;
@@ -16,11 +17,12 @@ export class UtilsService {
async sort(collection: string, { item, to }: { item: PrimaryKey; to: PrimaryKey }) {
const schemaInspector = SchemaInspector(this.knex);
const sortFieldResponse = await this.knex
.select('sort_field')
.from('directus_collections')
.where({ collection })
.first();
const sortFieldResponse =
(await this.knex
.select('sort_field')
.from('directus_collections')
.where({ collection })
.first()) || systemCollectionRows;
const sortField = sortFieldResponse?.sort_field;

View File

@@ -1,16 +1,18 @@
import { Field } from './field';
import { Table } from 'knex-schema-inspector/lib/types/table';
export type CollectionMeta = {
collection: string;
note: string | null;
hidden: boolean;
singleton: boolean;
icon: string | null;
translations: Record<string, string>;
};
export type Collection = {
collection: string;
fields?: Field[];
meta: {
collection: string;
note: string | null;
hidden: boolean;
singleton: boolean;
icon: string | null;
translations: Record<string, string>;
} | null;
meta: CollectionMeta | null;
schema: Table;
};

View File

@@ -0,0 +1,8 @@
import fse from 'fs-extra';
import yaml from 'js-yaml';
export function requireYAML(filepath: string) {
const yamlRaw = fse.readFileSync(filepath, 'utf8');
return yaml.safeLoad(yamlRaw) as Record<string, any>;
}