Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89e596a
commit 8a8df37
Showing
16 changed files
with
315 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,36 @@ | ||
import { merge } from '@ember/polyfills'; | ||
import { buildOperationUrl, _getStoreFromRecord, _getModelName, _getModelClass } from './build-url'; | ||
import Model from 'ember-data/model'; | ||
import { Value as JSONValue } from 'json-typescript'; | ||
import { _getModelClass, _getModelName, _getStoreFromRecord, buildOperationUrl } from './build-url'; | ||
import { EmberDataRequestType, Hook, HTTPVerb, strictifyHttpVerb } from './types'; | ||
|
||
export default function instanceOp(options) { | ||
return function(payload) { | ||
export interface CollectionOperationOptions<IN, OUT> { | ||
type?: HTTPVerb; | ||
path: string; | ||
urlType?: EmberDataRequestType; | ||
ajaxOptions?: any; | ||
before?: Hook<IN, any>; | ||
after?: Hook<any, OUT>; | ||
} | ||
|
||
export default function collectionOp<IN = any, OUT = any>(options: CollectionOperationOptions<IN, OUT>) { | ||
return function runCollectionOp(this: Model, payload: IN): Promise<OUT> { | ||
const recordClass = _getModelClass(this); | ||
const modelName = _getModelName(recordClass); | ||
const store = _getStoreFromRecord(this); | ||
const requestType = (options.type || 'PUT').toUpperCase(); | ||
const urlType = options.urlType || requestType; | ||
const requestType: HTTPVerb = strictifyHttpVerb(options.type || 'put'); | ||
const urlType: EmberDataRequestType = options.urlType || 'updateRecord'; | ||
const adapter = store.adapterFor(modelName); | ||
const fullUrl = buildOperationUrl(this, options.path, urlType, false); | ||
const data = (options.before && options.before.call(this, payload)) || payload; | ||
return adapter.ajax(fullUrl, requestType, merge(options.ajaxOptions || {}, { data })).then(response => { | ||
if (options.after && !this.isDestroyed) { | ||
return options.after.call(this, response); | ||
} | ||
return adapter | ||
.ajax(fullUrl, requestType, merge(options.ajaxOptions || {}, { data })) | ||
.then((response: JSONValue) => { | ||
if (options.after && !this.isDestroyed) { | ||
return options.after.call(this, response); | ||
} | ||
|
||
return response; | ||
}); | ||
return response; | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,45 @@ | ||
import { isArray } from '@ember/array'; | ||
import { typeOf } from '@ember/utils'; | ||
import Model from 'ember-data/model'; | ||
import JSONSerializer from 'ember-data/serializers/json'; | ||
import SerializerRegistry from 'ember-data/types/registries/serializer'; | ||
import { CollectionResourceDoc, Document as JSONApiDoc, DocWithData, SingleResourceDoc } from 'jsonapi-typescript'; | ||
import { _getModelClass, _getModelName, _getStoreFromRecord } from './build-url'; | ||
|
||
export default function serializeAndPush(response) { | ||
const isJsonApi = response.jsonapi && response.jsonapi.version; | ||
if (!isJsonApi) { | ||
// eslint-disable-next-line no-console | ||
console.warn('serializeAndPush may only be used with a JSON API document. Ignoring response. Document must have a mandatory JSON API object. See https://jsonapi.org/format/#document-jsonapi-object.'); | ||
function isJsonApi(raw: any): raw is JSONApiDoc { | ||
return raw.jsonapi && raw.jsonapi.version; | ||
} | ||
function isDocWithData(doc: any): doc is DocWithData { | ||
return isJsonApi(doc) && ['object', 'array'].indexOf(typeOf((doc as DocWithData).data)) >= 0; | ||
} | ||
|
||
export default function serializeAndPush(this: Model, response: any) { | ||
if (!isDocWithData(response)) { | ||
// tslint:disable-next-line:no-console | ||
console.warn( | ||
'serializeAndPush may only be used with a JSON API document. Ignoring response. ' + | ||
'Document must have a mandatory JSON API object. See https://jsonapi.org/format/#document-jsonapi-object.' | ||
); | ||
return response; | ||
} | ||
|
||
const recordClass = _getModelClass(this); | ||
const modelName = _getModelName(recordClass); | ||
const store = _getStoreFromRecord(this); | ||
const serializer = store.serializerFor(modelName); | ||
const normalized = isArray(response.data) ? serializer.normalizeArrayResponse(store, recordClass, response) : | ||
serializer.normalizeSingleResponse(store, recordClass, response); | ||
return this.store.push(normalized); | ||
const serializer: JSONSerializer = store.serializerFor(modelName as keyof SerializerRegistry); | ||
let normalized: {}; | ||
if (isArray(response.data)) { | ||
const doc = response as CollectionResourceDoc; | ||
normalized = serializer.normalizeArrayResponse(store, recordClass as any, doc, null as any, 'findAll'); | ||
} else { | ||
const doc = response as SingleResourceDoc; | ||
normalized = serializer.normalizeSingleResponse( | ||
store, | ||
recordClass as any, | ||
doc, | ||
`${doc.data.id || '(unknown)'}`, | ||
'findRecord' | ||
); | ||
} | ||
return store.push(normalized); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import Model from 'ember-data/model'; | ||
|
||
export type StrictHTTPVerb = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'; | ||
export type HTTPVerb = | ||
| 'GET' | ||
| 'POST' | ||
| 'PUT' | ||
| 'DELETE' | ||
| 'PATCH' | ||
| 'OPTIONS' | ||
| 'HEAD' | ||
| 'get' | ||
| 'post' | ||
| 'put' | ||
| 'delete' | ||
| 'patch' | ||
| 'options' | ||
| 'head'; | ||
|
||
export interface HTTPVerbStrictMap { | ||
GET: 'GET'; | ||
POST: 'POST'; | ||
PUT: 'PUT'; | ||
DELETE: 'DELETE'; | ||
PATCH: 'PATCH'; | ||
OPTIONS: 'OPTIONS'; | ||
HEAD: 'HEAD'; | ||
get: 'GET'; | ||
post: 'POST'; | ||
put: 'PUT'; | ||
delete: 'DELETE'; | ||
patch: 'PATCH'; | ||
options: 'OPTIONS'; | ||
head: 'HEAD'; | ||
} | ||
|
||
export function strictifyHttpVerb<K extends keyof HTTPVerbStrictMap>(notStrict: K): HTTPVerbStrictMap[K] { | ||
return `${notStrict}`.toUpperCase() as HTTPVerbStrictMap[K]; | ||
} | ||
|
||
export type EmberDataRequestType = | ||
| 'findRecord' | ||
| 'findAll' | ||
| 'query' | ||
| 'queryRecord' | ||
| 'findMany' | ||
| 'findHasMany' | ||
| 'findBelongsTo' | ||
| 'createRecord' | ||
| 'updateRecord' | ||
| 'deleteRecord'; | ||
|
||
export type Hook<IN, OUT> = (this: Model, payload: IN) => OUT; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.