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 { 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 { export class Collection implements ICollection {
repository: IRepository; repository: IRepository;
fields: Map<string, any> = new Map<string, any>();
constructor( constructor(
protected options: CollectionOptions, protected options: CollectionOptions,
@ -10,6 +14,30 @@ export class Collection implements ICollection {
this.setRepository(options.repository); 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) { protected setRepository(repository: any) {
this.repository = this.collectionManager.getRegisteredRepository(repository || 'Repository'); this.repository = this.collectionManager.getRegisteredRepository(repository || 'Repository');
} }

View File

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

View File

@ -44,57 +44,85 @@ describe('data source', async () => {
expect(mockDataSource).toBeInstanceOf(MockDataSource); expect(mockDataSource).toBeInstanceOf(MockDataSource);
}); });
it('should get collections from datasource', async () => { describe('data source collections', () => {
const loadFn = vi.fn(); 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 {} this.collectionManager.defineCollection({
class MockDataSource extends DataSource { name: 'comments',
async load(): Promise<void> { fields: [
this.collectionManager.defineCollection({ {
name: 'mock', type: 'string',
fields: [ name: 'content',
{ },
type: 'string', {
name: 'title', type: 'belongsTo',
}, name: 'post',
], },
}); ],
});
}
this.collectionManager.defineCollection({ createCollectionManager(options?: any) {
name: 'mock2', return new MockCollectionManager();
fields: [ }
{
type: 'string',
name: 'title',
},
],
});
} }
createCollectionManager(options?: any) { app.dataSourceManager.factory.register('mock', MockDataSource);
return new MockCollectionManager();
}
}
app.dataSourceManager.factory.register('mock', MockDataSource); await app.db.getRepository('dataSources').create({
values: {
await app.db.getRepository('dataSources').create({ key: 'mockInstance1',
values: { type: 'mock',
key: 'mockInstance1', displayName: 'Mock',
type: 'mock', options: {},
displayName: 'Mock', },
options: {}, });
},
}); });
const listResp = await app.agent().resource('dataSources').list(); it('should get collections from datasource', async () => {
expect(listResp.status).toBe(200); const listResp = await app.agent().resource('dataSources').list();
expect(listResp.status).toBe(200);
// get collections // get collections
const collectionsResp = await app.agent().resource('dataSources.collections', 'mockInstance1').list(); const collectionsResp = await app.agent().resource('dataSources.collections', 'mockInstance1').list();
expect(collectionsResp.status).toBe(200); expect(collectionsResp.status).toBe(200);
const data = collectionsResp.body.data; 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, ...createOptions,
name: this.get('key'), name: this.get('key'),
}); });
await app.dataSourceManager.add(instance); await app.dataSourceManager.add(instance);
} }
} }

View File

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

View File

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