feat: upgrade plugin-action-logs
This commit is contained in:
parent
864223d26a
commit
c56cd8674d
26
.env.example
Normal file
26
.env.example
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
DB_DIALECT=sqlite
|
||||||
|
DB_STORAGE=db.sqlite
|
||||||
|
|
||||||
|
# STORAGE (Initialization only)
|
||||||
|
|
||||||
|
# local or ali-oss
|
||||||
|
DEFAULT_STORAGE_TYPE=local
|
||||||
|
STORAGE_TYPE=local
|
||||||
|
|
||||||
|
# LOCAL STORAGE
|
||||||
|
LOCAL_STORAGE_USE_STATIC_SERVER=true
|
||||||
|
LOCAL_STORAGE_BASE_URL=
|
||||||
|
|
||||||
|
# ALI OSS STORAGE
|
||||||
|
ALI_OSS_STORAGE_BASE_URL=
|
||||||
|
ALI_OSS_REGION=oss-cn-beijing
|
||||||
|
ALI_OSS_ACCESS_KEY_ID=
|
||||||
|
ALI_OSS_ACCESS_KEY_SECRET=
|
||||||
|
ALI_OSS_BUCKET=
|
||||||
|
|
||||||
|
# AWS
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_S3_REGION=
|
||||||
|
AWS_S3_BUCKET=
|
||||||
|
AWS_S3_STORAGE_BASE_URL=
|
@ -73,6 +73,7 @@ export class Collection<
|
|||||||
const m = this.context.database.sequelize.model(name);
|
const m = this.context.database.sequelize.model(name);
|
||||||
if ((m as any).isThrough) {
|
if ((m as any).isThrough) {
|
||||||
this.model = m;
|
this.model = m;
|
||||||
|
Object.defineProperty(this.model, 'database', { value: this.context.database });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,6 +84,7 @@ export class Collection<
|
|||||||
}
|
}
|
||||||
this.model = class extends M {};
|
this.model = class extends M {};
|
||||||
this.model.init(null, this.sequelizeModelOptions());
|
this.model.init(null, this.sequelizeModelOptions());
|
||||||
|
Object.defineProperty(this.model, 'database', { value: this.context.database });
|
||||||
}
|
}
|
||||||
|
|
||||||
setRepository(repository?: RepositoryType | string) {
|
setRepository(repository?: RepositoryType | string) {
|
||||||
|
@ -6,3 +6,4 @@ export * from './relation-repository/belongs-to-many-repository';
|
|||||||
export * from './relation-repository/belongs-to-repository';
|
export * from './relation-repository/belongs-to-repository';
|
||||||
export { Model } from 'sequelize';
|
export { Model } from 'sequelize';
|
||||||
export * from './fields';
|
export * from './fields';
|
||||||
|
export * from './update-associations';
|
@ -2,7 +2,9 @@ import {
|
|||||||
Association,
|
Association,
|
||||||
BulkCreateOptions,
|
BulkCreateOptions,
|
||||||
CreateOptions as SequelizeCreateOptions,
|
CreateOptions as SequelizeCreateOptions,
|
||||||
|
UpdateOptions as SequelizeUpdateOptions,
|
||||||
FindAndCountOptions as SequelizeAndCountOptions,
|
FindAndCountOptions as SequelizeAndCountOptions,
|
||||||
|
DestroyOptions as SequelizeDestroyOptions,
|
||||||
FindOptions as SequelizeFindOptions,
|
FindOptions as SequelizeFindOptions,
|
||||||
Model,
|
Model,
|
||||||
ModelCtor,
|
ModelCtor,
|
||||||
@ -79,7 +81,7 @@ export interface CommonFindOptions {
|
|||||||
|
|
||||||
interface FindOneOptions extends FindOptions, CommonFindOptions {}
|
interface FindOneOptions extends FindOptions, CommonFindOptions {}
|
||||||
|
|
||||||
export interface DestroyOptions extends TransactionAble {
|
export interface DestroyOptions extends SequelizeDestroyOptions {
|
||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
filterByPk?: PrimaryKey | PrimaryKey[];
|
filterByPk?: PrimaryKey | PrimaryKey[];
|
||||||
truncate?: boolean;
|
truncate?: boolean;
|
||||||
@ -98,20 +100,22 @@ interface FindAndCountOptions extends Omit<SequelizeAndCountOptions, 'where' | '
|
|||||||
sort?: Sort;
|
sort?: Sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateOptions extends TransactionAble {
|
export interface CreateOptions extends SequelizeCreateOptions {
|
||||||
values?: Values;
|
values?: Values;
|
||||||
whitelist?: WhiteList;
|
whitelist?: WhiteList;
|
||||||
blacklist?: BlackList;
|
blacklist?: BlackList;
|
||||||
updateAssociationValues?: AssociationKeysToBeUpdate;
|
updateAssociationValues?: AssociationKeysToBeUpdate;
|
||||||
|
context?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateOptions extends TransactionAble {
|
export interface UpdateOptions extends SequelizeUpdateOptions {
|
||||||
values: Values;
|
values: Values;
|
||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
filterByPk?: PrimaryKey;
|
filterByPk?: PrimaryKey;
|
||||||
whitelist?: WhiteList;
|
whitelist?: WhiteList;
|
||||||
blacklist?: BlackList;
|
blacklist?: BlackList;
|
||||||
updateAssociationValues?: AssociationKeysToBeUpdate;
|
updateAssociationValues?: AssociationKeysToBeUpdate;
|
||||||
|
context?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RelatedQueryOptions {
|
interface RelatedQueryOptions {
|
||||||
@ -287,13 +291,17 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
|||||||
const guard = UpdateGuard.fromOptions(this.model, options);
|
const guard = UpdateGuard.fromOptions(this.model, options);
|
||||||
const values = guard.sanitize(options.values || {});
|
const values = guard.sanitize(options.values || {});
|
||||||
|
|
||||||
const instance = await this.model.create<any>(values, { transaction });
|
const instance = await this.model.create<any>(values, {
|
||||||
|
...options,
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateAssociations(instance, values, {
|
await updateAssociations(instance, values, {
|
||||||
|
...options,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -316,7 +324,7 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < instances.length; i++) {
|
for (let i = 0; i < instances.length; i++) {
|
||||||
await updateAssociations(instances[i], records[i], { transaction });
|
await updateAssociations(instances[i], records[i], { ...options, transaction });
|
||||||
}
|
}
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
@ -344,6 +352,7 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
|||||||
|
|
||||||
for (const instance of instances) {
|
for (const instance of instances) {
|
||||||
await updateModelByValues(instance, values, {
|
await updateModelByValues(instance, values, {
|
||||||
|
...options,
|
||||||
sanitized: true,
|
sanitized: true,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
7
packages/plugin-action-logs/.npmignore
Normal file
7
packages/plugin-action-logs/.npmignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
node_modules
|
||||||
|
*.log
|
||||||
|
docs
|
||||||
|
__tests__
|
||||||
|
tsconfig.json
|
||||||
|
src
|
||||||
|
.fatherrc.ts
|
15
packages/plugin-action-logs/package.json
Normal file
15
packages/plugin-action-logs/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "@nocobase/plugin-action-logs",
|
||||||
|
"version": "0.6.0-alpha.0",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
|
||||||
|
"build:cjs": "tsc --project tsconfig.build.json",
|
||||||
|
"build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nocobase/test": "^0.6.0-alpha.0"
|
||||||
|
},
|
||||||
|
"gitHead": "e7df1f93c4e23b9a666d99ee7372c02bdaec97c4"
|
||||||
|
}
|
105
packages/plugin-action-logs/src/__tests__/hook.test.ts
Normal file
105
packages/plugin-action-logs/src/__tests__/hook.test.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import Database from '@nocobase/database';
|
||||||
|
import { mockServer, MockServer } from '@nocobase/test';
|
||||||
|
import logPlugin from '../server';
|
||||||
|
|
||||||
|
describe('hook', () => {
|
||||||
|
let api: MockServer;
|
||||||
|
let db: Database;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
api = mockServer();
|
||||||
|
// api.plugin(require('@nocobase/plugin-users').default);
|
||||||
|
api.plugin(logPlugin);
|
||||||
|
await api.load();
|
||||||
|
db = api.db;
|
||||||
|
db.collection({
|
||||||
|
name: 'posts',
|
||||||
|
logging: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'title',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'status',
|
||||||
|
defaultValue: 'draft',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
db.collection({
|
||||||
|
name: 'users',
|
||||||
|
logging: false,
|
||||||
|
fields: [
|
||||||
|
{ type: 'string', name: 'nickname' },
|
||||||
|
{ type: 'string', name: 'token' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
await db.sync();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await api.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('model', async () => {
|
||||||
|
const Post = db.getCollection('posts').model;
|
||||||
|
const post = await Post.create({ title: 't1' });
|
||||||
|
await post.update({ title: 't2' });
|
||||||
|
await post.destroy();
|
||||||
|
const ActionLog = db.getCollection('action_logs').model;
|
||||||
|
const count = await ActionLog.count();
|
||||||
|
expect(count).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('repository', async () => {
|
||||||
|
const Post = db.getCollection('posts');
|
||||||
|
const User = db.getCollection('users').model;
|
||||||
|
const user = await User.create({ nickname: 'a', token: 'token1' });
|
||||||
|
await Post.repository.create({
|
||||||
|
values: { title: 't1' },
|
||||||
|
context: {
|
||||||
|
state: {
|
||||||
|
currentUser: user,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const ActionLog = db.getCollection('action_logs');
|
||||||
|
const log = await ActionLog.repository.findOne({
|
||||||
|
appends: ['changes'],
|
||||||
|
});
|
||||||
|
expect(log.toJSON()).toMatchObject({
|
||||||
|
collectionName: 'posts',
|
||||||
|
type: 'create',
|
||||||
|
userId: 1,
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
field: {
|
||||||
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
before: null,
|
||||||
|
after: 't1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('resource', async () => {
|
||||||
|
const agent = api.agent();
|
||||||
|
agent.set('Authorization', `Bearer token1`);
|
||||||
|
const response = await agent.resource('posts').create({
|
||||||
|
values: { title: 't1' },
|
||||||
|
});
|
||||||
|
await agent.resource('posts').update({
|
||||||
|
resourceIndex: response.body.data.id,
|
||||||
|
values: { title: 't2' },
|
||||||
|
});
|
||||||
|
await agent.resource('posts').destroy({
|
||||||
|
resourceIndex: response.body.data.id,
|
||||||
|
});
|
||||||
|
const ActionLog = db.getCollection('action_logs').model;
|
||||||
|
const count = await ActionLog.count();
|
||||||
|
expect(count).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,30 @@
|
|||||||
|
import { CollectionOptions } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'action_changes',
|
||||||
|
title: '变动值',
|
||||||
|
createdBy: false,
|
||||||
|
updatedBy: false,
|
||||||
|
createdAt: false,
|
||||||
|
updatedAt: false,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'log',
|
||||||
|
target: 'action_logs',
|
||||||
|
foreignKey: 'actionLogId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'json',
|
||||||
|
name: 'field',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'json',
|
||||||
|
name: 'before',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'json',
|
||||||
|
name: 'after',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as CollectionOptions;
|
46
packages/plugin-action-logs/src/collections/action_logs.ts
Normal file
46
packages/plugin-action-logs/src/collections/action_logs.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { CollectionOptions } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'action_logs',
|
||||||
|
title: '操作记录',
|
||||||
|
createdBy: false,
|
||||||
|
updatedBy: false,
|
||||||
|
updatedAt: false,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'date',
|
||||||
|
name: 'createdAt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'user',
|
||||||
|
target: 'users',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'collectionName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'collection',
|
||||||
|
target: 'collections',
|
||||||
|
targetKey: 'name',
|
||||||
|
sourceKey: 'collectionName',
|
||||||
|
constraints: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'integer',
|
||||||
|
name: 'index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'hasMany',
|
||||||
|
name: 'changes',
|
||||||
|
target: 'action_changes',
|
||||||
|
foreignKey: 'actionLogId',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as CollectionOptions;
|
3
packages/plugin-action-logs/src/constants.ts
Normal file
3
packages/plugin-action-logs/src/constants.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const LOG_TYPE_CREATE = 'create';
|
||||||
|
export const LOG_TYPE_UPDATE = 'update';
|
||||||
|
export const LOG_TYPE_DESTROY = 'destroy';
|
51
packages/plugin-action-logs/src/hooks/after-create.ts
Normal file
51
packages/plugin-action-logs/src/hooks/after-create.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import Database, { updateAssociations } from '@nocobase/database';
|
||||||
|
import { LOG_TYPE_CREATE } from '../constants';
|
||||||
|
|
||||||
|
export async function afterCreate(model, options) {
|
||||||
|
const db = model.constructor.database as Database;
|
||||||
|
const collection = db.getCollection(model.constructor.name);
|
||||||
|
if (!collection.options.logging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const transaction = options.transaction;
|
||||||
|
const ActionLog = db.getCollection('action_logs');
|
||||||
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
|
try {
|
||||||
|
const log = await ActionLog.model.create(
|
||||||
|
{
|
||||||
|
type: LOG_TYPE_CREATE,
|
||||||
|
collectionName: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
createdAt: model.get('createdAt'),
|
||||||
|
userId: currentUserId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
hooks: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const changes = [];
|
||||||
|
const changed = model.changed();
|
||||||
|
if (changed) {
|
||||||
|
changed.forEach((key: string) => {
|
||||||
|
const field = collection.findField((field) => {
|
||||||
|
return field.name === key || field.options.field === key;
|
||||||
|
});
|
||||||
|
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
after: model.get(key),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await updateAssociations(log, { changes }, { transaction });
|
||||||
|
}
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.commit();
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.rollback();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
47
packages/plugin-action-logs/src/hooks/after-destroy.ts
Normal file
47
packages/plugin-action-logs/src/hooks/after-destroy.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import Database, { updateAssociations } from '@nocobase/database';
|
||||||
|
import { LOG_TYPE_DESTROY } from '../constants';
|
||||||
|
|
||||||
|
export async function afterDestroy(model, options) {
|
||||||
|
const db = model.constructor.database as Database;
|
||||||
|
const collection = db.getCollection(model.constructor.name);
|
||||||
|
if (!collection.options.logging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const transaction = options.transaction;
|
||||||
|
const ActionLog = db.getCollection('action_logs');
|
||||||
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
|
try {
|
||||||
|
const log = await ActionLog.model.create(
|
||||||
|
{
|
||||||
|
type: LOG_TYPE_DESTROY,
|
||||||
|
collectionName: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
userId: currentUserId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
hooks: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const changes = [];
|
||||||
|
Object.keys(model.get()).forEach((key: string) => {
|
||||||
|
const field = collection.findField((field) => {
|
||||||
|
return field.name === key || field.options.field === key;
|
||||||
|
});
|
||||||
|
if (field) {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
before: model.get(key),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await updateAssociations(log, { changes }, { transaction });
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.commit();
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.rollback();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
56
packages/plugin-action-logs/src/hooks/after-update.ts
Normal file
56
packages/plugin-action-logs/src/hooks/after-update.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import Database, { updateAssociations } from '@nocobase/database';
|
||||||
|
import { LOG_TYPE_UPDATE } from '../constants';
|
||||||
|
|
||||||
|
export async function afterUpdate(model, options) {
|
||||||
|
const db = model.constructor.database as Database;
|
||||||
|
const collection = db.getCollection(model.constructor.name);
|
||||||
|
if (!collection.options.logging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const changed = model.changed();
|
||||||
|
if (!changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const transaction = options.transaction;
|
||||||
|
const ActionLog = db.getCollection('action_logs');
|
||||||
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
|
const changes = [];
|
||||||
|
changed.forEach((key: string) => {
|
||||||
|
const field = collection.findField((field) => {
|
||||||
|
return field.name === key || field.options.field === key;
|
||||||
|
});
|
||||||
|
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
after: model.get(key),
|
||||||
|
before: model.previous(key),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!changes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const log = await ActionLog.model.create(
|
||||||
|
{
|
||||||
|
type: LOG_TYPE_UPDATE,
|
||||||
|
collectionName: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
createdAt: model.get('updatedAt'),
|
||||||
|
userId: currentUserId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
hooks: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await updateAssociations(log, { changes }, { transaction });
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.commit();
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
// if (!options.transaction) {
|
||||||
|
// await transaction.rollback();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
3
packages/plugin-action-logs/src/hooks/index.ts
Normal file
3
packages/plugin-action-logs/src/hooks/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './after-create';
|
||||||
|
export * from './after-update';
|
||||||
|
export * from './after-destroy';
|
1
packages/plugin-action-logs/src/index.ts
Normal file
1
packages/plugin-action-logs/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './server';
|
16
packages/plugin-action-logs/src/server.ts
Normal file
16
packages/plugin-action-logs/src/server.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { IPlugin } from '@nocobase/server';
|
||||||
|
import { afterCreate, afterUpdate, afterDestroy } from './hooks';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'action-logs',
|
||||||
|
async load() {
|
||||||
|
const database = this.app.db;
|
||||||
|
await database.import({
|
||||||
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
|
});
|
||||||
|
database.on('afterCreate', afterCreate);
|
||||||
|
database.on('afterUpdate', afterUpdate);
|
||||||
|
database.on('afterDestroy', afterDestroy);
|
||||||
|
},
|
||||||
|
} as IPlugin;
|
9
packages/plugin-action-logs/tsconfig.build.json
Normal file
9
packages/plugin-action-logs/tsconfig.build.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.build.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./lib",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
|
||||||
|
"exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
|
||||||
|
}
|
5
packages/plugin-action-logs/tsconfig.json
Normal file
5
packages/plugin-action-logs/tsconfig.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
|
||||||
|
"exclude": ["./esm/*", "./lib/*"]
|
||||||
|
}
|
@ -4640,13 +4640,6 @@ crypto-random-string@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
|
resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
|
||||||
integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
|
integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
|
||||||
|
|
||||||
crypto-random-string@^3.3.0:
|
|
||||||
version "3.3.1"
|
|
||||||
resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-3.3.1.tgz#13cee94cac8001e4842501608ef779e0ed08f82d"
|
|
||||||
integrity sha512-5j88ECEn6h17UePrLi6pn1JcLtAiANa3KExyr9y9Z5vo2mv56Gh3I4Aja/B9P9uyMwyxNHAHWv+nE72f30T5Dg==
|
|
||||||
dependencies:
|
|
||||||
type-fest "^0.8.1"
|
|
||||||
|
|
||||||
css-blank-pseudo@^0.1.4:
|
css-blank-pseudo@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5"
|
resolved "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5"
|
||||||
|
Loading…
Reference in New Issue
Block a user