ts-japi
Version:
A highly-modular (typescript-friendly)-framework agnostic library for serializing data to the JSON:API specification
105 lines • 4.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const serializer_1 = __importDefault(require("./serializer"));
class PolymorphicSerializer extends serializer_1.default {
serialisers;
key;
constructor(commonName, key, serializers) {
super(commonName);
this.serialisers = serializers;
this.key = key;
}
async serialize(data, options) {
if (Array.isArray(data)) {
const documents = await Promise.all(Object.values(data.reduce((acc, d) => {
// group data by type
const type = d[this.key];
if (!acc[type]) {
acc[type] = [];
}
acc[type].push(d);
return acc;
}, {})).map((d) => {
return this.serializeType(d, options);
}));
// Construct initial document and included data
let document = {
data: [],
};
// Document versioning
if (options?.version) {
document.jsonapi = { ...document.jsonapi, version: options.version };
}
if (options?.metaizers?.jsonapi) {
document.jsonapi = { ...document.jsonapi, meta: options.metaizers.jsonapi.metaize() };
}
document = documents.reduce((result, document) => {
result.data = [result.data ?? [], document.data ?? []].flat();
result.included = [result.included ?? [], document.included ?? []].flat();
return result;
}, document);
// Sort data to match input order - this is important for cases where
// data has been sorted prior to serialization.
if (Array.isArray(document.data)) {
document.data = document.data.sort((a, b) => {
const aIndex = data.findIndex((datum) => datum.id === a.id);
const bIndex = data.findIndex((datum) => datum.id === b.id);
return aIndex - bIndex;
});
}
// Handle meta
if (options?.metaizers?.document) {
document.meta = options.metaizers.document.metaize(data);
}
// Handle links
if (options?.linkers) {
if (options.linkers.document) {
document.links = { ...document.links, self: options.linkers.document.link(data) };
}
if (options.linkers.paginator) {
const pagination = options.linkers.paginator.paginate(data);
if (pagination) {
document.links = { ...document.links, ...pagination };
}
}
}
return document;
}
else if (data) {
return this.serializeType(data, options);
}
return Object.values(this.serialisers)[0].serialize(data, options);
}
createIdentifier(data, options) {
const serializer = this.getSerializerForData(data);
if (serializer) {
return serializer.createIdentifier(data, options);
}
return super.createIdentifier(data, options);
}
async createResource(data, options, helpers, relatorDataCache) {
const serializer = this.getSerializerForData(data);
if (serializer) {
return serializer.createResource(data, options, helpers, relatorDataCache);
}
return super.createResource(data, options, helpers, relatorDataCache);
}
async serializeType(data, options) {
const serializer = this.getSerializerForData(Array.isArray(data) ? data[0] : data);
if (serializer) {
return serializer.serialize(data, options);
}
return super.serialize(data, options);
}
getSerializerForData(data) {
if (this.serialisers[data[this.key]]) {
return this.serialisers[data[this.key]];
}
return null;
}
}
exports.default = PolymorphicSerializer;
//# sourceMappingURL=polymorphic-serialiser.js.map