mirror of
https://github.com/strapi/strapi.git
synced 2025-12-24 13:43:41 +00:00
Add timestamps lifecycles subscriber
This commit is contained in:
parent
59eb3990dd
commit
82fe2a1b87
@ -1,49 +0,0 @@
|
||||
'use strict';
|
||||
const { prop, defaultsDeep } = require('lodash/fp');
|
||||
|
||||
/*
|
||||
config/database.js
|
||||
|
||||
{
|
||||
connector: '',
|
||||
connection: {},
|
||||
migration: {},
|
||||
seed: {},
|
||||
schema: {
|
||||
autoSync: true,
|
||||
forceSync: true
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
class Configuration {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
static from(config) {
|
||||
if (config instanceof Configuration) {
|
||||
return config;
|
||||
}
|
||||
|
||||
return new Configuration(defaultsDeep(config, Configuration.defaults));
|
||||
}
|
||||
|
||||
get(path) {
|
||||
return prop(path, this.config);
|
||||
}
|
||||
}
|
||||
|
||||
Configuration.defaults = {
|
||||
connector: '@strapi/connector-sql',
|
||||
migration: {
|
||||
//
|
||||
},
|
||||
seed: {
|
||||
//
|
||||
},
|
||||
models: [],
|
||||
};
|
||||
|
||||
module.exports = Configuration;
|
||||
@ -95,9 +95,8 @@ const createRepository = (uid, db) => {
|
||||
return db.entityManager.deleteRelations(uid, id);
|
||||
},
|
||||
|
||||
// TODO: add relation API
|
||||
populate(entity, field, params) {
|
||||
return db.entityManager.populate(uid, entity, field, params);
|
||||
populate(entity, populate) {
|
||||
return db.entityManager.populate(uid, entity, populate);
|
||||
},
|
||||
|
||||
load(entity, field, params) {
|
||||
|
||||
5
packages/core/database/lib/fields.d.ts
vendored
5
packages/core/database/lib/fields.d.ts
vendored
@ -1,10 +1,9 @@
|
||||
import { Attribute } from './schema';
|
||||
|
||||
interface Field {
|
||||
config: {};
|
||||
toDB(value: any): any;
|
||||
fromDB(value: any): any;
|
||||
}
|
||||
|
||||
interface Attribute {
|
||||
type: string
|
||||
}
|
||||
export function createField(attribute: Attribute): Field;
|
||||
|
||||
61
packages/core/database/lib/index.d.ts
vendored
61
packages/core/database/lib/index.d.ts
vendored
@ -1,3 +1,7 @@
|
||||
import { LifecycleProvider } from './lifecycles';
|
||||
import { MigrationProvider } from './migrations';
|
||||
import { SchemaProvideer } from './schema';
|
||||
|
||||
type BooleanWhere<T> = {
|
||||
$and?: WhereParams<T>[];
|
||||
$or?: WhereParams<T>[];
|
||||
@ -50,6 +54,43 @@ interface Pagination {
|
||||
total: number;
|
||||
}
|
||||
|
||||
interface PopulateParams {}
|
||||
interface EntityManager {
|
||||
findOne<K extends keyof AllTypes>(uid: K, params: FindParams<AllTypes[K]>): Promise<any>;
|
||||
findMany<K extends keyof AllTypes>(uid: K, params: FindParams<AllTypes[K]>): Promise<any[]>;
|
||||
|
||||
create<K extends keyof AllTypes>(uid: K, params: CreateParams<AllTypes[K]>): Promise<any>;
|
||||
createMany<K extends keyof AllTypes>(
|
||||
uid: K,
|
||||
params: CreateManyParams<AllTypes[K]>
|
||||
): Promise<{ count: number }>;
|
||||
|
||||
update<K extends keyof AllTypes>(uid: K, params: any): Promise<any>;
|
||||
updateMany<K extends keyof AllTypes>(uid: K, params: any): Promise<{ count: number }>;
|
||||
|
||||
delete<K extends keyof AllTypes>(uid: K, params: any): Promise<any>;
|
||||
deleteMany<K extends keyof AllTypes>(uid: K, params: any): Promise<{ count: number }>;
|
||||
|
||||
count<K extends keyof AllTypes>(uid: K, params: any): Promise<number>;
|
||||
|
||||
attachRelations<K extends keyof AllTypes>(uid: K, id: ID, data: any): Promise<any>;
|
||||
updateRelations<K extends keyof AllTypes>(uid: K, id: ID, data: any): Promise<any>;
|
||||
deleteRelations<K extends keyof AllTypes>(uid: K, id: ID): Promise<any>;
|
||||
|
||||
populate<K extends keyof AllTypes, T extends AllTypes[K]>(
|
||||
uid: K,
|
||||
entity: T,
|
||||
populate: PopulateParams
|
||||
): Promise<T>;
|
||||
|
||||
load<K extends keyof AllTypes, T extends AllTypes[K], SK extends keyof T>(
|
||||
uid: K,
|
||||
entity: T,
|
||||
field: SK,
|
||||
populate: PopulateParams
|
||||
): Promise<T[SK]>;
|
||||
}
|
||||
|
||||
interface QueryFromContentType<T extends keyof AllTypes> {
|
||||
findOne(params: FindParams<AllTypes[T]>): Promise<any>;
|
||||
findMany(params: FindParams<AllTypes[T]>): Promise<any[]>;
|
||||
@ -70,6 +111,14 @@ interface QueryFromContentType<T extends keyof AllTypes> {
|
||||
attachRelations(id: ID, data: any): Promise<any>;
|
||||
updateRelations(id: ID, data: any): Promise<any>;
|
||||
deleteRelations(id: ID): Promise<any>;
|
||||
|
||||
populate<S extends AllTypes[T]>(entity: S, populate: PopulateParams): Promise<S>;
|
||||
|
||||
load<S extends AllTypes[T], K extends keyof S>(
|
||||
entity: S,
|
||||
field: K,
|
||||
populate: PopulateParams
|
||||
): Promise<S[K]>;
|
||||
}
|
||||
|
||||
interface ModelConfig {
|
||||
@ -83,15 +132,11 @@ interface DatabaseConfig {
|
||||
connection: ConnectionConfig;
|
||||
models: ModelConfig[];
|
||||
}
|
||||
|
||||
interface DatabaseSchema {
|
||||
sync(): Promise<void>;
|
||||
reset(): Promise<void>;
|
||||
create(): Promise<void>;
|
||||
drop(): Promise<void>;
|
||||
}
|
||||
export interface Database {
|
||||
schema: DatabaseSchema;
|
||||
schema: SchemaProvideer;
|
||||
lifecycles: LifecycleProvider;
|
||||
migrations: MigrationProvider;
|
||||
entityManager: EntityManager;
|
||||
|
||||
query<T extends keyof AllTypes>(uid: T): QueryFromContentType<T>;
|
||||
}
|
||||
|
||||
@ -4,10 +4,10 @@ const knex = require('knex');
|
||||
|
||||
const { getDialect } = require('./dialects');
|
||||
const createSchemaProvider = require('./schema');
|
||||
const createMigrationProvider = require('./migration');
|
||||
const createMetadata = require('./metadata');
|
||||
const { createEntityManager } = require('./entity-manager');
|
||||
const { createLifecyclesManager } = require('./lifecycles');
|
||||
const { createMigrationsProvider } = require('./migrations');
|
||||
const { createLifecyclesProvider } = require('./lifecycles');
|
||||
|
||||
// TODO: move back into strapi
|
||||
const { transformContentTypes } = require('./utils/content-types');
|
||||
@ -26,9 +26,10 @@ class Database {
|
||||
this.dialect.initialize();
|
||||
|
||||
this.schema = createSchemaProvider(this);
|
||||
this.migration = createMigrationProvider(this);
|
||||
|
||||
this.lifecycles = createLifecyclesManager(this);
|
||||
this.migrations = createMigrationsProvider(this);
|
||||
this.lifecycles = createLifecyclesProvider(this);
|
||||
|
||||
this.entityManager = createEntityManager(this);
|
||||
}
|
||||
|
||||
|
||||
50
packages/core/database/lib/lifecycles/index.d.ts
vendored
Normal file
50
packages/core/database/lib/lifecycles/index.d.ts
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
import { Database } from '../';
|
||||
import { Model } from '../schema';
|
||||
import { Subscriber } from './subscribers';
|
||||
|
||||
export type Action =
|
||||
| 'beforeCreate'
|
||||
| 'afterCreate'
|
||||
| 'beforeFindOne'
|
||||
| 'afterFindOne'
|
||||
| 'beforeFindMany'
|
||||
| 'afterFindMany'
|
||||
| 'beforeCount'
|
||||
| 'afterCount'
|
||||
| 'beforeCreateMany'
|
||||
| 'afterCreateMany'
|
||||
| 'beforeUpdate'
|
||||
| 'afterUpdate'
|
||||
| 'beforeUpdateMany'
|
||||
| 'afterUpdateMany'
|
||||
| 'beforeDelete'
|
||||
| 'afterDelete'
|
||||
| 'beforeDeleteMany'
|
||||
| 'afterDeleteMany';
|
||||
|
||||
export interface Params {
|
||||
select?: any;
|
||||
where?: any;
|
||||
_q?: any;
|
||||
orderBy?: any;
|
||||
groupBy?: any;
|
||||
offset?: any;
|
||||
limit?: any;
|
||||
populate?: any;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
action: Action;
|
||||
model: Model;
|
||||
params: Params;
|
||||
}
|
||||
|
||||
export interface LifecycleProvider {
|
||||
subscribe(subscriber: Subscriber): () => void;
|
||||
clear(): void;
|
||||
run(action: Action, uid: string, properties: any): Promise<void>;
|
||||
createEvent(action: Action, uid: string, properties: any): Event;
|
||||
}
|
||||
|
||||
export function createLifecyclesProvider(db: Database): LifecycleProvider;
|
||||
@ -2,22 +2,8 @@
|
||||
|
||||
const assert = require('assert').strict;
|
||||
|
||||
/**
|
||||
* @typedef Event
|
||||
* @property {string} action
|
||||
* @property {Model} model
|
||||
*/
|
||||
|
||||
/**
|
||||
* For each model try to run it's lifecycles function if any is defined
|
||||
* @param {Event} event
|
||||
*/
|
||||
const modelLifecyclesSubscriber = async event => {
|
||||
const { model } = event;
|
||||
if (event.action in model.lifecycles) {
|
||||
await model.lifecycles[event.action](event);
|
||||
}
|
||||
};
|
||||
const timestampsLifecyclesSubscriber = require('./subscribers/timestamps');
|
||||
const modelLifecyclesSubscriber = require('./subscribers/models-lifecycles');
|
||||
|
||||
const isValidSubscriber = subscriber => {
|
||||
return (
|
||||
@ -25,10 +11,13 @@ const isValidSubscriber = subscriber => {
|
||||
);
|
||||
};
|
||||
|
||||
const createLifecyclesManager = db => {
|
||||
let subscribers = [modelLifecyclesSubscriber];
|
||||
/**
|
||||
* @type {import('.').createLifecyclesProvider}
|
||||
*/
|
||||
const createLifecyclesProvider = db => {
|
||||
let subscribers = [timestampsLifecyclesSubscriber, modelLifecyclesSubscriber];
|
||||
|
||||
const lifecycleManager = {
|
||||
return {
|
||||
subscribe(subscriber) {
|
||||
assert(isValidSubscriber(subscriber), 'Invalid subscriber. Expected function or object');
|
||||
|
||||
@ -37,6 +26,10 @@ const createLifecyclesManager = db => {
|
||||
return () => subscribers.splice(subscribers.indexOf(subscriber), 1);
|
||||
},
|
||||
|
||||
clear() {
|
||||
subscribers = [];
|
||||
},
|
||||
|
||||
createEvent(action, uid, properties) {
|
||||
const model = db.metadata.get(uid);
|
||||
|
||||
@ -65,15 +58,9 @@ const createLifecyclesManager = db => {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clear() {
|
||||
subscribers = [];
|
||||
},
|
||||
};
|
||||
|
||||
return lifecycleManager;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createLifecyclesManager,
|
||||
createLifecyclesProvider,
|
||||
};
|
||||
9
packages/core/database/lib/lifecycles/subscribers/index.d.ts
vendored
Normal file
9
packages/core/database/lib/lifecycles/subscribers/index.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { Event, Action } from '../';
|
||||
|
||||
type SubscriberFn = (event: Event) => Promise<void> | void;
|
||||
|
||||
type SubscriberMap = {
|
||||
[k in Action]: SubscriberFn;
|
||||
};
|
||||
|
||||
export type Subscriber = SubscriberFn | SubscriberMap;
|
||||
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import(".").Subscriber } Subscriber
|
||||
*/
|
||||
|
||||
/**
|
||||
* For each model try to run it's lifecycles function if any is defined
|
||||
* @type {Subscriber}
|
||||
*/
|
||||
const modelsLifecyclesSubscriber = async event => {
|
||||
const { model } = event;
|
||||
|
||||
if (event.action in model.lifecycles) {
|
||||
await model.lifecycles[event.action](event);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = modelsLifecyclesSubscriber;
|
||||
@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
/**
|
||||
* @typedef {import(".").Subscriber } Subscriber
|
||||
* @typedef { import("../").Event } Event
|
||||
*/
|
||||
|
||||
// NOTE: we could add onCreate & onUpdate on field level to do this instead
|
||||
|
||||
/**
|
||||
* @type {Subscriber}
|
||||
*/
|
||||
const timestampsLifecyclesSubscriber = {
|
||||
/**
|
||||
* Init created_at & updated_at before create
|
||||
* @param {Event} event
|
||||
*/
|
||||
beforeCreate(event) {
|
||||
const { data } = event.params;
|
||||
|
||||
const now = new Date();
|
||||
_.defaults(data, { created_at: now, updated_at: now });
|
||||
},
|
||||
|
||||
/**
|
||||
* Init created_at & updated_at before create
|
||||
* @param {Event} event
|
||||
*/
|
||||
beforeCreateMany(event) {
|
||||
const { data } = event.params;
|
||||
|
||||
const now = new Date();
|
||||
if (_.isArray(data)) {
|
||||
data.forEach(data => _.defaults(data, { created_at: now, updated_at: now }));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update updated_at before update
|
||||
* @param {Event} event
|
||||
*/
|
||||
beforeUpdate(event) {
|
||||
const { data } = event.params;
|
||||
|
||||
const now = new Date();
|
||||
_.assign(data, { updated_at: now });
|
||||
},
|
||||
|
||||
/**
|
||||
* Update updated_at before update
|
||||
* @param {Event} event
|
||||
*/
|
||||
beforeUpdateMany(event) {
|
||||
const { data } = event.params;
|
||||
|
||||
const now = new Date();
|
||||
if (_.isArray(data)) {
|
||||
data.forEach(data => _.assign(data, { updated_at: now }));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = timestampsLifecyclesSubscriber;
|
||||
@ -1,105 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fse = require('fs-extra');
|
||||
const Umzug = require('umzug');
|
||||
|
||||
class CustomStorage {
|
||||
constructor(opts = {}) {
|
||||
this.tableName = opts.tableName;
|
||||
this.knex = opts.db.connection;
|
||||
}
|
||||
|
||||
async logMigration(migrationName) {
|
||||
await this.knex
|
||||
.insert({
|
||||
name: migrationName,
|
||||
time: new Date(),
|
||||
})
|
||||
.into(this.tableName);
|
||||
}
|
||||
|
||||
async unlogMigration(migrationName) {
|
||||
await this.knex(this.tableName)
|
||||
.del()
|
||||
.where({ name: migrationName });
|
||||
}
|
||||
|
||||
async executed() {
|
||||
if (!(await this.hasMigrationTable())) {
|
||||
await this.createMigrationTable();
|
||||
return [];
|
||||
}
|
||||
|
||||
const logs = await this.knex
|
||||
.select()
|
||||
.from(this.tableName)
|
||||
.orderBy('time');
|
||||
|
||||
return logs.map(log => log.name);
|
||||
}
|
||||
|
||||
hasMigrationTable() {
|
||||
return this.knex.schema.hasTable(this.tableName);
|
||||
}
|
||||
|
||||
createMigrationTable() {
|
||||
return this.knex.schema.createTable(this.tableName, table => {
|
||||
table.increments('id');
|
||||
table.string('name');
|
||||
table.datetime('time', { useTz: false });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const createMigrationProvider = db => {
|
||||
const migrationDir = path.join(strapi.dir, 'database/migrations');
|
||||
|
||||
fse.ensureDirSync(migrationDir);
|
||||
|
||||
const migrations = new Umzug({
|
||||
storage: new CustomStorage({ db, tableName: 'strapi_migrations' }),
|
||||
migrations: {
|
||||
path: migrationDir,
|
||||
pattern: /\.(js|sql)$/,
|
||||
params: [db],
|
||||
wrap(fn) {
|
||||
return db => db.connection.transaction(trx => Promise.resolve(fn(trx)));
|
||||
},
|
||||
customResolver(path) {
|
||||
// if sql file run with knex raw
|
||||
if (path.match(/\.sql$/)) {
|
||||
const sql = fse.readFileSync(path, 'utf8');
|
||||
|
||||
return {
|
||||
// TODO: check multiple commands in one sql statement
|
||||
up: knex => knex.raw(sql),
|
||||
down() {},
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: we can add some ts register if we want to handle ts migration files at some point
|
||||
return require(path);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: add internal migrations for core & plugins
|
||||
// How do we intersperse them
|
||||
|
||||
return {
|
||||
async shouldRun() {
|
||||
const pending = await migrations.pending();
|
||||
|
||||
return pending.length > 0;
|
||||
},
|
||||
async up() {
|
||||
await migrations.up();
|
||||
},
|
||||
async down() {
|
||||
await migrations.down();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = createMigrationProvider;
|
||||
9
packages/core/database/lib/migrations/index.d.ts
vendored
Normal file
9
packages/core/database/lib/migrations/index.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { Database } from '../';
|
||||
|
||||
export interface MigrationProvider {
|
||||
shouldRun(): Promise<boolean>;
|
||||
up(): Promise<void>;
|
||||
down(): Promise<void>;
|
||||
}
|
||||
|
||||
export function createMigrationsProvider(db: Database): MigrationProvider;
|
||||
69
packages/core/database/lib/migrations/index.js
Normal file
69
packages/core/database/lib/migrations/index.js
Normal file
@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fse = require('fs-extra');
|
||||
const Umzug = require('umzug');
|
||||
|
||||
const createStorage = require('./storage');
|
||||
|
||||
// TODO: check multiple commands in one sql statement
|
||||
const migrationResolver = path => {
|
||||
// if sql file run with knex raw
|
||||
if (path.match(/\.sql$/)) {
|
||||
const sql = fse.readFileSync(path, 'utf8');
|
||||
|
||||
return {
|
||||
up: knex => knex.raw(sql),
|
||||
down() {},
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: we can add some ts register if we want to handle ts migration files at some point
|
||||
return require(path);
|
||||
};
|
||||
|
||||
const createUmzugProvider = db => {
|
||||
const migrationDir = path.join(strapi.dir, 'database/migrations');
|
||||
|
||||
fse.ensureDirSync(migrationDir);
|
||||
|
||||
const wrapFn = fn => db => db.connection.transaction(trx => Promise.resolve(fn(trx)));
|
||||
const storage = createStorage({ db, tableName: 'strapi_migrations' });
|
||||
|
||||
return new Umzug({
|
||||
storage,
|
||||
migrations: {
|
||||
path: migrationDir,
|
||||
pattern: /\.(js|sql)$/,
|
||||
params: [db],
|
||||
wrap: wrapFn,
|
||||
customResolver: migrationResolver,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// NOTE: when needed => add internal migrations for core & plugins. How do we overlap them with users migrations ?
|
||||
|
||||
/**
|
||||
* Creates migrations provider
|
||||
* @type {import('.').createMigrationsProvider}
|
||||
*/
|
||||
const createMigrationsProvider = db => {
|
||||
const migrations = createUmzugProvider(db);
|
||||
|
||||
return {
|
||||
async shouldRun() {
|
||||
const pending = await migrations.pending();
|
||||
|
||||
return pending.length > 0;
|
||||
},
|
||||
async up() {
|
||||
await migrations.up();
|
||||
},
|
||||
async down() {
|
||||
await migrations.down();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { createMigrationsProvider };
|
||||
49
packages/core/database/lib/migrations/storage.js
Normal file
49
packages/core/database/lib/migrations/storage.js
Normal file
@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
const createStorage = (opts = {}) => {
|
||||
const tableName = opts.tableName || 'strapi_migrations';
|
||||
const knex = opts.db.connection;
|
||||
|
||||
const hasMigrationTable = () => knex.schema.hasTable(tableName);
|
||||
|
||||
const createMigrationTable = () => {
|
||||
return knex.schema.createTable(tableName, table => {
|
||||
table.increments('id');
|
||||
table.string('name');
|
||||
table.datetime('time', { useTz: false });
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
async logMigration(migrationName) {
|
||||
await knex
|
||||
.insert({
|
||||
name: migrationName,
|
||||
time: new Date(),
|
||||
})
|
||||
.into(tableName);
|
||||
},
|
||||
|
||||
async unlogMigration(migrationName) {
|
||||
await knex(tableName)
|
||||
.del()
|
||||
.where({ name: migrationName });
|
||||
},
|
||||
|
||||
async executed() {
|
||||
if (!(await hasMigrationTable())) {
|
||||
await createMigrationTable();
|
||||
return [];
|
||||
}
|
||||
|
||||
const logs = await knex
|
||||
.select()
|
||||
.from(tableName)
|
||||
.orderBy('time');
|
||||
|
||||
return logs.map(log => log.name);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = createStorage;
|
||||
49
packages/core/database/lib/schema/index.d.ts
vendored
Normal file
49
packages/core/database/lib/schema/index.d.ts
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
import { Database } from '../';
|
||||
import { Action } from '../lifecycles';
|
||||
|
||||
type Type =
|
||||
| 'string'
|
||||
| 'text'
|
||||
| 'richtext'
|
||||
| 'json'
|
||||
| 'enumeration'
|
||||
| 'password'
|
||||
| 'email'
|
||||
| 'integer'
|
||||
| 'biginteger'
|
||||
| 'float'
|
||||
| 'decimal'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'timestamp'
|
||||
| 'boolean'
|
||||
| 'relation';
|
||||
|
||||
export interface Attribute {
|
||||
type: Type;
|
||||
}
|
||||
|
||||
export interface Model {
|
||||
uid: string;
|
||||
tableName: string;
|
||||
attributes: {
|
||||
id: {
|
||||
type: 'increments';
|
||||
};
|
||||
[k: string]: Attribute;
|
||||
};
|
||||
lifecycles?: {
|
||||
[k in Action]: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SchemaProvideer {
|
||||
sync(): Promise<void>;
|
||||
syncSchema(): Promise<void>;
|
||||
reset(): Promise<void>;
|
||||
create(): Promise<void>;
|
||||
drop(): Promise<void>;
|
||||
}
|
||||
|
||||
export default function(db: Database): SchemaProvideer;
|
||||
@ -7,6 +7,9 @@ const createSchemaDiff = require('./diff');
|
||||
const createSchemaStorage = require('./storage');
|
||||
const { metadataToSchema } = require('./schema');
|
||||
|
||||
/**
|
||||
* @type {import('.').default}
|
||||
*/
|
||||
const createSchemaProvider = db => {
|
||||
const schema = metadataToSchema(db.metadata);
|
||||
|
||||
@ -60,9 +63,9 @@ const createSchemaProvider = db => {
|
||||
// TODO: support option to disable auto migration & run a CLI command instead to avoid doing it at startup
|
||||
// TODO: Allow keeping extra indexes / extra tables / extra columns (globally or on a per table basis)
|
||||
async sync() {
|
||||
if (await db.migration.shouldRun()) {
|
||||
if (await db.migrations.shouldRun()) {
|
||||
debug('Found migrations to run');
|
||||
await db.migration.up();
|
||||
await db.migrations.up();
|
||||
|
||||
return this.syncSchema();
|
||||
}
|
||||
|
||||
@ -68,12 +68,10 @@ const createContentType = (uid, definition) => {
|
||||
Object.assign(schema.attributes, {
|
||||
[CREATED_AT_ATTRIBUTE]: {
|
||||
type: 'datetime',
|
||||
default: () => new Date(),
|
||||
},
|
||||
// TODO: handle on edit set to new date
|
||||
[UPDATED_AT_ATTRIBUTE]: {
|
||||
type: 'datetime',
|
||||
default: () => new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user