Created
February 19, 2019 01:42
-
-
Save joelalejandro/3263151613225fb6ad5ba75f5e590a2a to your computer and use it in GitHub Desktop.
Semi-manual approach to relationship/include resolution (without automatic inference)
This file contains hidden or 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
import { KnexProcessor, Operation } from "@ebryn/jsonapi-ts"; | |
import { relateOneToOne } from "../../utils/relate"; | |
import { sideloadOneFrom } from "../../utils/sideload"; | |
import Book from "./resource"; | |
export default class BookProcessor extends KnexProcessor<Book> { | |
public resourceClass = Book; | |
public async get(op: Operation): Promise<Book[]> { | |
// Get raw data first. | |
const data = await super.get(op); | |
// Move relationship foreign keys to relationship objects. | |
// This would have to be done probably with "reflect-metadata" | |
// targeting the resource definition. | |
const dataWithRelationships = await Promise.all([ | |
...relateOneToOne(data, { | |
authorId: "author", | |
}) | |
]); | |
// This calls processor.include() to buffer up any necessary includes. | |
await sideloadOneFrom(dataWithRelationships, this); | |
return dataWithRelationships as Book[]; | |
} | |
} |
This file contains hidden or 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
import { Resource } from "@ebryn/jsonapi-ts"; | |
export default class Book extends Resource { | |
public attributes: { | |
name: string; | |
}; | |
public relationships: { | |
author: { | |
data: { id: string; type: "author" }; | |
}; | |
}; | |
} |
This file contains hidden or 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
// Converts relationship ID fields into JSONAPI relationship objects. | |
import { Resource } from "@ebryn/jsonapi-ts"; | |
export function relateOneToOne( | |
data: Resource[], | |
relationships: { | |
[key: string]: string; | |
} | |
) { | |
return data.map(async resource => { | |
const dataWithRelationships = { ...resource, relationships: {} }; | |
Object.keys(relationships).forEach(foreignKey => { | |
const foreignType = relationships[foreignKey]; | |
if (resource.attributes[foreignKey]) { | |
dataWithRelationships.relationships[foreignType] = { | |
data: { | |
id: resource.attributes[foreignKey], | |
type: foreignType | |
} | |
}; | |
delete resource.attributes[foreignKey]; | |
} | |
}); | |
return dataWithRelationships; | |
}); | |
} |
This file contains hidden or 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
// Loads any resources defined by 1-1 relationships and buffers them with processor.include(). | |
import { Operation, OperationProcessor, Resource } from "@ebryn/jsonapi-ts"; | |
export function sideloadOneFrom( | |
resources: Resource[], | |
processor: OperationProcessor | |
) { | |
return Promise.all( | |
resources.map(async resource => { | |
const foreignTypes = Object.keys(resource.relationships); | |
if (!foreignTypes.length) { | |
return; | |
} | |
return Promise.all( | |
foreignTypes.map(async foreignType => { | |
const [sideloadedResource] = await processor.app.executeOperations([ | |
{ | |
op: "get", | |
ref: resource.relationships[foreignType].data | |
} as Operation | |
]); | |
processor.include(sideloadedResource.data as Resource[]); | |
}) | |
); | |
}) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment