UNPKG

ember-m3

Version:

Alternative to @ember-data/model in which attributes and relationships are derived from API Payloads

133 lines (121 loc) 4.5 kB
import Service from '@ember/service'; import { isArray } from '@ember/array'; import { isResolvedValue as _isResolvedValue } from '../utils/resolve'; export default class DefaultSchema extends Service { computeAttributeReference(/* key, value, modelName, schemaInterface */) { // If the attribute with value `value` under key `key` of `modelName` is // a reference to another model, return `{ type, id }`. If it's an array // of references return an array of `{ type, id }` pairs. Otherwise, // return `null`. return null; } computeNestedModel(/* key, value, modelName, schemaInterface */) { // If the attribute with value `value` under key `key` of `modelName` // should be treated as a nested model instead of a plain POJO, then // return `{ id, type, attributes }`. // // For example with payload // // { // id: 1, // type: 'com.example.library.Book', // attributes: { // bestChapter: { // number: 7, // characterPOV: 'urn:character:2', // } // } // } // // In which you want `bestChapter.characterPOV` to resolve to another // model (as opposed to the string 'urn:character:2') it is necessary for // the attribute `bestChapter` to be treated as a nested model and not // merely as a POJO. // // To have the attribute treated as a POJO return null. // // ## Arrays // // Arrays will have this method invoked for the top level // where you have two choices. // // returning `null` will result in `computeNestedModel` being called // for each individual entry in the array instead. // // alternatively, you may normalize the entire array at once, // returning an array with its contents in jsonapi format. // return null; } includesModel(/* modelName */) { // Return true if modelName should be provided by a MegamorphicModel, // false if it should be handled via the store default (probably a // @ember-data/model) return false; } computeBaseModelName(/* projectionModelName */) { // If the `projectionModelName` represents a projection over some base type, // return the model name of the base type to maintain shared data // between all projections of the same type return null; } /** * Update the RecordData with raw value instead of resolved value * * @param {string} modelName * @param {string} attrName * @param {Object} value * @param {M3SchemaInterface} schemaInterface */ setAttribute(modelName, attrName, value, schemaInterface) { schemaInterface.setAttr(attrName, value); } isAttributeResolved(modelName, attrName, value /*, schemaInterface */) { // by default records and arrays of records are treated as resolved. Note // that we don't want to check against our own record arrays specifically // as ember data record arrays or many arrays should also be treated as // resolved if (_isResolvedValue(value)) { // value is a record return true; } if (isArray(value)) { if (value.length > 0) { // non-empty arrays are treated as resolved only if they are arrays of records return value.every(v => _isResolvedValue(v)); } else { // empty arrays are treated as resolved if they're non-native arrays // (to handle ManyArray, RecordArrays &c.) // // empty native arrays are treated as unresolved as this is the primary // way of setting arrays of new nested models return !Array.isArray(value); } } } /* models: { 'my-model-name': { // an optional whitelist of attributes. If undefined, all attributes // returned by the API will be available on the model attributes: ['foo', 'bar', 'baz'], // an optional list of attribute transforms. Use this if your API // returns values whose types can't be encoded in JSON, such as dates. // Each key is the name of an attribute as it appears in the payload, // and each value is a function that takes the raw api value and returns // the transformed value transforms: { dateAttr: function dateTransform(dateString) { return dateString && new Date(Date.parse(dateString)); }, }, defaults: { tag: 'span', }, aliases: { fullName: 'person.name', }, } } */ }