chore: update collection option

This commit is contained in:
Chareice 2024-01-25 09:31:30 +08:00
parent 5bcc44a768
commit fc175a7730
No known key found for this signature in database
7 changed files with 120 additions and 59 deletions

View File

@ -1,7 +1,11 @@
import { CollectionOptions, ICollection, ICollectionManager, IRepository } from './types';
import { default as lodash } from 'lodash';
import merge from 'deepmerge';
import { Field } from '@nocobase/database';
export class Collection implements ICollection {
repository: IRepository;
fields: Map<string, any> = new Map<string, any>();
constructor(
protected options: CollectionOptions,
@ -10,6 +14,30 @@ export class Collection implements ICollection {
this.setRepository(options.repository);
}
updateOptions(options: CollectionOptions, mergeOptions?: any) {
let newOptions = lodash.cloneDeep(options);
newOptions = merge(this.options, newOptions, mergeOptions);
this.options = newOptions;
if (options.repository) {
this.setRepository(options.repository);
}
return this;
}
setField(name: string, options: any) {
const field = this.getField(name);
if (field) {
field.updateOptions(options);
}
}
getField<F extends Field>(name: string): F {
return this.fields.get(name);
}
protected setRepository(repository: any) {
this.repository = this.collectionManager.getRegisteredRepository(repository || 'Repository');
}

View File

@ -7,6 +7,8 @@ export type CollectionOptions = {
export interface ICollection {
repository: any;
updateOptions(options: any): void;
setField(name: string, options: any): void;
[key: string]: any;
}
export interface IModel {
@ -36,11 +38,13 @@ export interface ICollectionManager {
getRegisteredRepository(key: string): IRepository;
defineCollection(options: CollectionOptions): ICollection;
extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): ICollection;
hasCollection(name: string): boolean;
getCollection(name: string): ICollection;
getCollections(): Array<ICollection>;
getRepository<R = IRepository>(name: string, sourceId?: string | number): R;
sync(): Promise<void>;
}

View File

@ -44,57 +44,85 @@ describe('data source', async () => {
expect(mockDataSource).toBeInstanceOf(MockDataSource);
});
it('should get collections from datasource', async () => {
const loadFn = vi.fn();
describe('data source collections', () => {
beforeEach(async () => {
class MockCollectionManager extends CollectionManager {}
class MockDataSource extends DataSource {
async load(): Promise<void> {
this.collectionManager.defineCollection({
name: 'posts',
fields: [
{
type: 'string',
name: 'title',
},
{
type: 'hasMany',
name: 'comments',
},
],
});
class MockCollectionManager extends CollectionManager {}
class MockDataSource extends DataSource {
async load(): Promise<void> {
this.collectionManager.defineCollection({
name: 'mock',
fields: [
{
type: 'string',
name: 'title',
},
],
});
this.collectionManager.defineCollection({
name: 'comments',
fields: [
{
type: 'string',
name: 'content',
},
{
type: 'belongsTo',
name: 'post',
},
],
});
}
this.collectionManager.defineCollection({
name: 'mock2',
fields: [
{
type: 'string',
name: 'title',
},
],
});
createCollectionManager(options?: any) {
return new MockCollectionManager();
}
}
createCollectionManager(options?: any) {
return new MockCollectionManager();
}
}
app.dataSourceManager.factory.register('mock', MockDataSource);
app.dataSourceManager.factory.register('mock', MockDataSource);
await app.db.getRepository('dataSources').create({
values: {
key: 'mockInstance1',
type: 'mock',
displayName: 'Mock',
options: {},
},
await app.db.getRepository('dataSources').create({
values: {
key: 'mockInstance1',
type: 'mock',
displayName: 'Mock',
options: {},
},
});
});
const listResp = await app.agent().resource('dataSources').list();
expect(listResp.status).toBe(200);
it('should get collections from datasource', async () => {
const listResp = await app.agent().resource('dataSources').list();
expect(listResp.status).toBe(200);
// get collections
const collectionsResp = await app.agent().resource('dataSources.collections', 'mockInstance1').list();
expect(collectionsResp.status).toBe(200);
const data = collectionsResp.body.data;
// get collections
const collectionsResp = await app.agent().resource('dataSources.collections', 'mockInstance1').list();
expect(collectionsResp.status).toBe(200);
const data = collectionsResp.body.data;
expect(data.length).toBe(2);
expect(data.length).toBe(2);
});
it('should edit datasource collections', async () => {
// edit collections
const editResp = await app
.agent()
.resource('dataSources.collections', 'mockInstance1.posts')
.update({
values: {
title: '标题 Collection',
},
});
expect(editResp.status).toBe(200);
const dataSource = app.dataSourceManager.dataSources.get('mockInstance1');
const collection = dataSource.collectionManager.getCollection('posts');
expect(collection.options.title).toBe('标题 Collection');
});
});
});

View File

@ -11,6 +11,7 @@ export class DataSourceModel extends MagicAttributeModel {
...createOptions,
name: this.get('key'),
});
await app.dataSourceManager.add(instance);
}
}

View File

@ -6,10 +6,9 @@ export class RemoteCollectionModel extends MagicAttributeModel {
const { app } = loadOptions;
const collectionOptions = this.get();
const databaseName = this.get('connectionName');
const database = app.getDb(databaseName);
const collectionName = this.get('name');
const collection = database.getCollection(collectionName);
const dataSourceName = this.get('dataSourceKey');
const dataSource = app.dataSourceManager.dataSources.get(dataSourceName);
const collection = dataSource.collectionManager.getCollection(collectionOptions.name);
collection.updateOptions(collectionOptions);
}
}

View File

@ -155,7 +155,7 @@ export class PluginDataSourceManagerServer extends Plugin {
});
});
this.app.db.on('remoteCollections.afterSave', async (model: RemoteCollectionModel) => {
this.app.db.on('dataSourcesCollections.afterSave', async (model: RemoteCollectionModel) => {
model.load({
app: this.app,
});

View File

@ -47,31 +47,32 @@ export default {
async update(ctx, next) {
const params = ctx.action.params;
const { filterByTk: name } = params;
const databaseName = ctx.get('x-database');
const { filterByTk: name, associatedIndex: collectionWithDataSource } = params;
let remoteCollectionRecord = await ctx.db.getRepository('remoteCollections').findOne({
const [dataSourceKey, collectionName] = collectionWithDataSource.split('.');
let dataSourceCollectionRecord = await ctx.db.getRepository('dataSourcesCollections').findOne({
filter: {
name,
connectionName: databaseName,
name: collectionName,
dataSourceKey,
},
});
if (!remoteCollectionRecord) {
remoteCollectionRecord = await ctx.db.getRepository('remoteCollections').create({
if (!dataSourceCollectionRecord) {
dataSourceCollectionRecord = await ctx.db.getRepository('dataSourcesCollections').create({
values: {
...params.values,
name,
connectionName: databaseName,
name: collectionName,
dataSourceKey,
},
});
} else {
await remoteCollectionRecord.update({
await dataSourceCollectionRecord.update({
...params.values,
});
}
ctx.body = remoteCollectionRecord.toJSON();
ctx.body = dataSourceCollectionRecord.toJSON();
await next();
},