Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to work around id and type field names? #206

Open
jacobq opened this issue May 17, 2020 · 4 comments
Open

How to work around id and type field names? #206

jacobq opened this issue May 17, 2020 · 4 comments

Comments

@jacobq
Copy link

jacobq commented May 17, 2020

I have some Mongoose models/Schema that include id and/or type keys. If I pass these models to JSON_API.dbAdapters.Mongoose(...) and then use that to set up JSON_API.ResourceTypeRegistry it runs fine until a request comes in. Then, if I have debug logging enabled, I can see json-api:warn Errors converted to json-api Result Error: typeandid cannot be used as field names. How can I handle this situation? Perhaps there's a way I can tell json-api that these fields should be remapped/renamed somehow (e.g. type -> typeField)?

@jacobq
Copy link
Author

jacobq commented May 17, 2020

Looking through the source, it seems like I should be able to pass a custom queryTransform somewhere.... There's an example where it's done with Front.customAPIRequest, but could I still use something like app.get('/:type(users|posts|...)', Front.apiRequest) or do I need to split the "odd one" out?

@jacobq
Copy link
Author

jacobq commented May 17, 2020

Tried a hack like the following, but this approach doesn't seem feasible.

class ModMongooseAdapter extends JSON_API.dbAdapters.Mongoose {
  constructor(models, toTypeName, idGenerator) {
    super(models, toTypeName, idGenerator);
    log('ModMongooseAdapter constructor', ...arguments);
  }

  mapReservedFieldNames(doc) {
    const reservedNames = ['id', 'type'];
    const docProps = {};
    for (const fieldName of Object.keys(doc.schema.paths).filter(key => !key.startsWith('__'))) {
      if (reservedNames.includes(fieldName)) {
        const newFieldName = `${fieldName}Field`;
        docProps[newFieldName] = doc[fieldName];
      } else {
        docProps[fieldName] = doc[fieldName];
      }
    }
    // This part doesn't quite work since we don't actually want to change the underlying data
    // plus the Model/Schema still lists `id` and `type` and we still end up with
    // "Error: Cannot construct a ResourceSet with missing data"`
    const modDoc = doc.overwrite({
      ...docProps
    });
    log(`mapReservedFieldNames returning`, modDoc);
    return modDoc;
  }

  docsToResourceData(docs, isPlural, fields) {
    log('docsToResourceData', ...arguments);
    const modDocs = docs.map(this.mapReservedFieldNames);
    super.docsToResourceData(modDocs, isPlural, fields);
  }

  docToResource(doc, fields) {
    log('docToResource', doc, fields);
    const modDoc = this.mapReservedFieldNames(doc);
    return super.docToResource(modDoc, fields);
  }
}

I'm going to try creating alternate schema/models with something like a virtual to get id and type under alternate names. I feel dumb for being so stuck here, but this is a big problem for me.

@ethanresnick
Copy link
Owner

I honestly haven't looked at the code for this library in a long time, so I'd have to refresh my memory to be able to help. I'll try to take a look soonish

@jacobq
Copy link
Author

jacobq commented May 18, 2020

OK. For now I just made a branch with models having different names, e.g. foo.type becomes foo.fooType. This seems like something that shouldn't be all that hard though, and I'd be surprised if it's uncommon as Mongoose doesn't impose requirements about using id or type in Schema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants