feathers sequelize add/include remote model

对着背影说爱祢 提交于 2020-05-28 08:06:14

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!