问题
Several days that I am stuck on something so basic as adding remote models using feathersjs. Starting to feel really stupid to be stuck on something so basic. :-/
How to create a tag then add it a post: Tags.addPost({[...]})
How to access sequelize models?
https://sequelize.org/master/manual/assocs.html#special-methods-mixins-added-to-instances
const tags = sequelizeClient.define(
'tags',
{
title: {
type: DataTypes.STRING,
},
}
const tags = sequelizeClient.define(
'posts',
{
title: {
type: DataTypes.STRING,
},
}
// [...]
(posts as any).associate = function (models: any) {
// Define associations here
// See http://docs.sequelizejs.com/en/latest/docs/associations/
const { tags, posts } = models;
posts.belongsTo(tags);
tags.hasMany(posts);
};
app.services.tags
.create({
title: 'myTag',
})
.then(myTag => {
// has anybody found how to do something similar to
// myTag.addPost({ title: 'myPost'}) ?
})
回答1:
This is part of the solution I found.
Based on this Using feathers-client and sequelize many-to-many relation So using hooks this is how I include remote models on demand.
Still have to find how to Tag.addPost({...}) Any help welcome
src/shared/hooks/index.ts
import { HookContext } from '@feathersjs/feathers';
import logger from '../logger';
// https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge
// Note that this will lead to infinite recursion on circular references.
/**
* Simple object check.
* @param item
* @returns {boolean}
*/
export function isObject(item: any) {
return item && typeof item === 'object' && !Array.isArray(item);
}
/**
* Deep merge two objects.
* @param target
* @param ...sources
*/
export function mergeDeep(target: any, ...sources: [any]): any {
if (!sources.length) return target;
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
mergeDeep(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return mergeDeep(target, ...sources);
}
export default () => {
return (context: HookContext) => {
if (context.params && context.params.query && '$include' in context.params.query) {
const { $include } = context.params.query;
// Remove from the query so that it doesn't get included
// in the actual database query
delete context.params.query.$include;
const sequelize = {
include: new Array(),
raw: false,
};
// console.log(`context.service.Model`, context.service.Model.name);
// console.log(`context.service.Model.associations`, context.service.Model.associations);
// see https://jsperf.com/array-coerce
(Array.isArray($include) ? $include : [$include]).forEach((name: string) => {
if (name in context.service.Model.associations) {
sequelize.include.push({
association: context.service.Model.associations[name],
as: name,
});
} else {
logger.error(
`Requested association '${name}' of model '%s' doesn't exist. Available associations are: %O`,
context.service.Model.name,
context.service.Model.associations
);
}
});
// context.params.sequelize = { ...context.params.sequelize, ...sequelize };
context.params.sequelize = mergeDeep(context.params.sequelize || {}, sequelize);
}
return Promise.resolve(context);
};
};
Edit 1: we don't want to specify Model, but association
Edit 2: if association doesn't exist, dont crash in loop and log error
src/app.hooks.ts
import { includeRemoteModels } from './shared/hooks';
// Application hooks that run for every service
// Don't remove this comment. It's needed to format import lines nicely.
export default {
before: {
all: [includeRemoteModels()],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: [],
},
after: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: [],
},
error: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: [],
},
};
来源:https://stackoverflow.com/questions/61419970/feathers-sequelize-add-include-remote-model