Comparing version 1.1.2 to 1.2.0
import { ErrorSerializerOptions } from "../interfaces/error-serializer.interface"; | ||
import { ErrorDocument } from "../interfaces/document.interface"; | ||
import { SingleOrArray, Dictionary } from "../types/global.types"; | ||
import { ErrorDocument } from "../interfaces/json:api.interface"; | ||
import { SingleOrArray } from "../types/global.types"; | ||
/** | ||
@@ -12,3 +12,3 @@ * The {@linkcode ErrorSerializer} class is used to serialize errors. | ||
*/ | ||
export default class ErrorSerializer<T extends Dictionary<any>> { | ||
export default class ErrorSerializer<ErrorType> { | ||
/** | ||
@@ -43,3 +43,3 @@ * Default options. Can be edited to change default options globally. | ||
*/ | ||
constructor(options?: Partial<ErrorSerializerOptions<T>>); | ||
constructor(options?: Partial<ErrorSerializerOptions<ErrorType>>); | ||
/** | ||
@@ -51,4 +51,4 @@ * The actual serialization function. | ||
*/ | ||
serialize(errors: SingleOrArray<T>, options?: Partial<ErrorSerializerOptions<T>>): ErrorDocument; | ||
serialize(errors: SingleOrArray<ErrorType>, options?: Partial<ErrorSerializerOptions<ErrorType>>): ErrorDocument; | ||
} | ||
//# sourceMappingURL=error-serializer.d.ts.map |
@@ -74,9 +74,10 @@ "use strict"; | ||
var e_1, _a, e_2, _b, e_3, _c, _d; | ||
if (options === void 0) { options = {}; } | ||
// Get options. | ||
var opts = merge_1["default"]({}, this.options, options); | ||
var attributes = opts.attributes; | ||
var linkers = opts.linkers; | ||
var metaizers = opts.metaizers; | ||
var version = opts.version; | ||
var o = this.options; | ||
if (options) | ||
o = merge_1["default"]({}, this.options, options); | ||
var attributes = o.attributes; | ||
var linkers = o.linkers; | ||
var metaizers = o.metaizers; | ||
var version = o.version; | ||
var document = {}; | ||
@@ -88,21 +89,33 @@ // Normalize error input | ||
document.errors = errors.map(function (error) { | ||
return error instanceof error_model_1["default"] | ||
? error | ||
: new error_model_1["default"]({ | ||
id: attributes.id && error[attributes.id], | ||
status: attributes.status && error[attributes.status], | ||
code: attributes.code && error[attributes.code], | ||
title: attributes.title && error[attributes.title], | ||
detail: attributes.detail && error[attributes.detail], | ||
source: (function () { | ||
var source = {}; | ||
if (attributes.source.pointer && error[attributes.source.pointer]) { | ||
source.pointer = error[attributes.source.pointer]; | ||
} | ||
if (attributes.source.parameter && error[attributes.source.parameter]) { | ||
source.parameter = error[attributes.source.parameter]; | ||
} | ||
return Object.keys(source).length > 0 ? source : undefined; | ||
})() | ||
}); | ||
if (error instanceof error_model_1["default"]) | ||
return error; | ||
var errorOptions = {}; | ||
if (attributes.id && error[attributes.id]) { | ||
errorOptions.id = String(error[attributes.id]); | ||
} | ||
if (attributes.status && error[attributes.status]) { | ||
errorOptions.status = String(error[attributes.status]); | ||
} | ||
if (attributes.code && error[attributes.code]) { | ||
errorOptions.code = String(error[attributes.code]); | ||
} | ||
if (attributes.title && error[attributes.title]) { | ||
errorOptions.title = String(error[attributes.title]); | ||
} | ||
if (attributes.detail && error[attributes.detail]) { | ||
errorOptions.detail = String(error[attributes.detail]); | ||
} | ||
if (attributes.source) { | ||
errorOptions.source = {}; | ||
if (attributes.source.pointer && error[attributes.source.pointer]) { | ||
errorOptions.source.pointer = String(error[attributes.source.pointer]); | ||
} | ||
if (attributes.source.parameter && error[attributes.source.parameter]) { | ||
errorOptions.source.parameter = String(error[attributes.source.parameter]); | ||
} | ||
if (Object.keys(errorOptions.source).length === 0) { | ||
delete errorOptions.source; | ||
} | ||
} | ||
return new error_model_1["default"](errorOptions); | ||
}); | ||
@@ -109,0 +122,0 @@ // Constructing base document. |
import { RelatorOptions } from "../interfaces/relator.interface"; | ||
import { SerializerOptions } from "../interfaces/serializer.interface"; | ||
import Link from "../models/link.model"; | ||
import Meta from "../models/meta.model"; | ||
import Relationship from "../models/relationship.model"; | ||
import { Dictionary, SingleOrArray } from "../types/global.types"; | ||
import ResourceIdentifier from "../models/resource-identifier.model"; | ||
import Resource from "../models/resource.model"; | ||
import { Dictionary, nullish } from "../types/global.types"; | ||
import Serializer from "./serializer"; | ||
@@ -20,3 +25,2 @@ /** | ||
linkers: {}; | ||
serializer: Serializer<Record<string | number | symbol, any>>; | ||
}; | ||
@@ -27,2 +31,3 @@ /** | ||
private options; | ||
relatedName: string; | ||
/** | ||
@@ -32,9 +37,18 @@ * Creates a {@linkcode Relator}. | ||
* @param fetch Fetches related data from primary data. | ||
* @param serializer The `Serializer` to use for related data. | ||
* @param options Options for the relator. | ||
*/ | ||
constructor(fetch: (data: PrimaryType) => Promise<SingleOrArray<RelatedType>>, options?: Partial<RelatorOptions<PrimaryType, RelatedType>>); | ||
/** @internal Gets related data from primary data. */ | ||
getRelatedData: (data: PrimaryType) => Promise<SingleOrArray<RelatedType>>; | ||
/** @internal Gets the related resources {@linkcode Serializer}. */ | ||
getRelatedSerializer(): Serializer<RelatedType> | undefined; | ||
constructor(fetch: (data: PrimaryType) => Promise<RelatedType | RelatedType[] | nullish>, serializer: Serializer<RelatedType>, options?: Partial<RelatorOptions<PrimaryType, RelatedType>>); | ||
/** @internal Gets related data from primary data. */ | ||
getRelatedData: (data: PrimaryType) => Promise<RelatedType | RelatedType[] | nullish>; | ||
/** @internal Gets related relators */ | ||
getRelatedRelators: () => Record<string, Relator<RelatedType, any>> | undefined; | ||
/** @internal Creates related identifiers */ | ||
getRelatedIdentifier: (data: RelatedType, options?: SerializerOptions<RelatedType> | undefined) => ResourceIdentifier; | ||
/** @internal Creates related resources */ | ||
getRelatedResource: (data: RelatedType, options?: SerializerOptions<RelatedType>) => Promise<Resource<RelatedType>>; | ||
/** @internal Gets related links from primary data and related data */ | ||
getRelatedLinks(data: PrimaryType, relatedData: RelatedType | RelatedType[] | nullish): Record<string | number | symbol, Link | null | undefined> | undefined; | ||
/** @internal Gets related meta from primary data and related data */ | ||
getRelatedMeta(data: PrimaryType, relatedData: RelatedType | RelatedType[] | nullish): Meta | undefined; | ||
/** @internal Creates a {@linkcode Relationship}. */ | ||
@@ -41,0 +55,0 @@ getRelationship(data: PrimaryType): Promise<Relationship>; |
@@ -55,3 +55,2 @@ "use strict"; | ||
var merge_1 = __importDefault(require("../utils/merge")); | ||
var serializer_1 = __importDefault(require("./serializer")); | ||
/** | ||
@@ -71,40 +70,64 @@ * The {@linkcode Relator} class is used to generate top-level [included data](https://jsonapi.org/format/#document-top-level) | ||
* @param fetch Fetches related data from primary data. | ||
* @param serializer The `Serializer` to use for related data. | ||
* @param options Options for the relator. | ||
*/ | ||
function Relator(fetch, options) { | ||
function Relator(fetch, serializer, options) { | ||
if (options === void 0) { options = {}; } | ||
// Setting default options | ||
this.relatedName = serializer.collectionName; | ||
this.options = merge_1["default"]({}, Relator.defaultOptions, options); | ||
this.getRelatedData = fetch; | ||
this.getRelatedResource = serializer.createResource.bind(serializer); | ||
this.getRelatedIdentifier = serializer.createIdentifier.bind(serializer); | ||
this.getRelatedRelators = serializer.getRelators.bind(serializer); | ||
} | ||
/** @internal Gets the related resources {@linkcode Serializer}. */ | ||
Relator.prototype.getRelatedSerializer = function () { | ||
return this.options.serializer; | ||
/** @internal Gets related links from primary data and related data */ | ||
Relator.prototype.getRelatedLinks = function (data, relatedData) { | ||
var links; | ||
if (this.options.linkers.relationship) { | ||
links = __assign(__assign({}, links), { self: this.options.linkers.relationship.link(data, relatedData) }); | ||
} | ||
if (this.options.linkers.related) { | ||
links = __assign(__assign({}, links), { related: this.options.linkers.related.link(data, relatedData) }); | ||
} | ||
return links; | ||
}; | ||
/** @internal Gets related meta from primary data and related data */ | ||
Relator.prototype.getRelatedMeta = function (data, relatedData) { | ||
var meta; | ||
if (this.options.metaizer) { | ||
meta = this.options.metaizer.metaize(data, relatedData); | ||
} | ||
return meta; | ||
}; | ||
/** @internal Creates a {@linkcode Relationship}. */ | ||
Relator.prototype.getRelationship = function (data) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, serializer, linkers, metaizer, relatedData, links, resourceLinkage, meta; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
var relationshipOptions, relatedData, links, meta; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a = this.options, serializer = _a.serializer, linkers = _a.linkers, metaizer = _a.metaizer; | ||
relationshipOptions = {}; | ||
return [4 /*yield*/, this.getRelatedData(data)]; | ||
case 1: | ||
relatedData = _b.sent(); | ||
if (linkers.relationship) { | ||
links = __assign(__assign({}, links), { self: linkers.relationship.link(data, relatedData) }); | ||
relatedData = _a.sent(); | ||
links = this.getRelatedLinks(data, relatedData); | ||
if (links) | ||
relationshipOptions.links = links; | ||
// Construct related resources. | ||
if (relatedData !== undefined) { | ||
if (relatedData === null) { | ||
relationshipOptions.data = null; | ||
} | ||
else { | ||
relationshipOptions.data = Array.isArray(relatedData) | ||
? relatedData.map(function (data) { return _this.getRelatedIdentifier(data); }) | ||
: this.getRelatedIdentifier(relatedData); | ||
} | ||
} | ||
if (linkers.related) { | ||
links = __assign(__assign({}, links), { related: linkers.related.link(data, relatedData) }); | ||
} | ||
if (serializer) { | ||
resourceLinkage = Array.isArray(relatedData) | ||
? relatedData.map(function (data) { return serializer.constructResourceIdentity(data); }) | ||
: serializer.constructResourceIdentity(relatedData); | ||
} | ||
if (metaizer) { | ||
meta = metaizer.metaize(data, relatedData); | ||
} | ||
return [2 /*return*/, new relationship_model_1["default"]({ links: links, data: resourceLinkage }, meta)]; | ||
meta = this.getRelatedMeta(data, relatedData); | ||
if (meta) | ||
relationshipOptions.meta = meta; | ||
return [2 /*return*/, new relationship_model_1["default"](relationshipOptions)]; | ||
} | ||
@@ -118,4 +141,3 @@ }); | ||
Relator.defaultOptions = { | ||
linkers: {}, | ||
serializer: new serializer_1["default"]("related_data") | ||
linkers: {} | ||
}; | ||
@@ -122,0 +144,0 @@ return Relator; |
@@ -1,6 +0,7 @@ | ||
import { DataDocument } from "../interfaces/document.interface"; | ||
import { DataDocument } from "../interfaces/json:api.interface"; | ||
import { SerializerOptions } from "../interfaces/serializer.interface"; | ||
import ResourceIdentifier from "../models/resource-identifier.model"; | ||
import Resource from "../models/resource.model"; | ||
import { Dictionary, SingleOrArray } from "../types/global.types"; | ||
import { Dictionary, nullish, SingleOrArray } from "../types/global.types"; | ||
import Relator from "./relator"; | ||
/** | ||
@@ -15,3 +16,3 @@ * The {@linkcode Serializer} class is the main class used to serializer data | ||
*/ | ||
export default class Serializer<PrimaryType extends Dictionary<any>> { | ||
export default class Serializer<PrimaryType extends Dictionary<any> = any> { | ||
/** | ||
@@ -28,2 +29,3 @@ * Default options. Can be edited to change default options globally. | ||
depth: number; | ||
projection: null; | ||
linkers: {}; | ||
@@ -47,6 +49,14 @@ metaizers: {}; | ||
constructor(collectionName: string, options?: Partial<SerializerOptions<PrimaryType>>); | ||
/** | ||
* Gets the {@linkcode Relator}s associated with this serializer | ||
*/ | ||
getRelators(): Record<string, Relator<PrimaryType, any>> | undefined; | ||
/** | ||
* Sets the {@linkcode Relator}s associated with this serializer | ||
*/ | ||
setRelators(relators: SerializerOptions<PrimaryType>["relators"]): void; | ||
/** @internal Generates a `ResourceIdentifier`. */ | ||
constructResourceIdentity(data: PrimaryType, options?: Partial<SerializerOptions<PrimaryType>>): ResourceIdentifier; | ||
createIdentifier(data: PrimaryType, options?: SerializerOptions<PrimaryType>): ResourceIdentifier; | ||
/** @internal Generates a `Resource`. */ | ||
constructResource(data: PrimaryType, options?: Partial<SerializerOptions<PrimaryType>>): Promise<Resource<PrimaryType>>; | ||
createResource(data: PrimaryType, options?: SerializerOptions<PrimaryType>): Promise<Resource<PrimaryType>>; | ||
/** | ||
@@ -58,4 +68,4 @@ * The actual serialization function. | ||
*/ | ||
serialize(data?: SingleOrArray<PrimaryType>, options?: Partial<SerializerOptions<PrimaryType>>): Promise<DataDocument<PrimaryType>>; | ||
serialize(data: SingleOrArray<PrimaryType> | nullish, options?: Partial<SerializerOptions<PrimaryType>>): Promise<DataDocument<PrimaryType>>; | ||
} | ||
//# sourceMappingURL=serializer.d.ts.map |
@@ -76,6 +76,2 @@ "use strict"; | ||
}; | ||
var __spread = (this && this.__spread) || function () { | ||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -88,4 +84,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
var merge_1 = __importDefault(require("../utils/merge")); | ||
var metaizer_1 = __importDefault(require("./metaizer")); | ||
var get_array_1 = require("../utils/get-array"); | ||
var serializer_utils_1 = require("../utils/serializer.utils"); | ||
/** | ||
@@ -111,81 +106,119 @@ * The {@linkcode Serializer} class is the main class used to serializer data | ||
this.options = merge_1["default"]({}, Serializer.defaultOptions, options); | ||
this.options.relators = serializer_utils_1.normalizeRelators(this.options.relators); | ||
// Setting type name. | ||
this.collectionName = collectionName; | ||
} | ||
/** | ||
* Gets the {@linkcode Relator}s associated with this serializer | ||
*/ | ||
Serializer.prototype.getRelators = function () { | ||
return this.options.relators; | ||
}; | ||
/** | ||
* Sets the {@linkcode Relator}s associated with this serializer | ||
*/ | ||
Serializer.prototype.setRelators = function (relators) { | ||
this.options.relators = serializer_utils_1.normalizeRelators(relators); | ||
}; | ||
/** @internal Generates a `ResourceIdentifier`. */ | ||
Serializer.prototype.constructResourceIdentity = function (data, options) { | ||
if (options === void 0) { options = {}; } | ||
// Merge options. | ||
var o = merge_1["default"]({}, this.options, options); | ||
return new resource_identifier_model_1["default"]({ type: this.collectionName, id: data[o.idKey] }, o.metaizers.resource ? o.metaizers.resource.metaize(data) : undefined); | ||
Serializer.prototype.createIdentifier = function (data, options) { | ||
// Get options | ||
if (options === undefined) | ||
options = this.options; | ||
var identifierOptions = {}; | ||
if (options.metaizers.resource) { | ||
identifierOptions.meta = options.metaizers.resource.metaize(data); | ||
} | ||
return new resource_identifier_model_1["default"](data[options.idKey], this.collectionName, identifierOptions); | ||
}; | ||
/** @internal Generates a `Resource`. */ | ||
Serializer.prototype.constructResource = function (data, options) { | ||
if (options === void 0) { options = {}; } | ||
Serializer.prototype.createResource = function (data, options) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var o, id, attributes, _a, _b, _c, key, value, _d, _e, _f, key, value, relationships, relators; | ||
var e_1, _g, e_2, _h; | ||
return __generator(this, function (_j) { | ||
switch (_j.label) { | ||
var resourceOptions, id, type, type_1, _a, _b, key, _c, _d, key, relationships_1; | ||
var e_1, _e, e_2, _f; | ||
var _this = this; | ||
return __generator(this, function (_g) { | ||
switch (_g.label) { | ||
case 0: | ||
o = merge_1["default"]({}, this.options, options); | ||
id = data[o.idKey]; | ||
attributes = {}; | ||
if (o.projection) { | ||
try { | ||
for (_a = __values(Object.entries(data)), _b = _a.next(); !_b.done; _b = _a.next()) { | ||
_c = __read(_b.value, 2), key = _c[0], value = _c[1]; | ||
if (o.projection[key]) | ||
attributes[key] = value; | ||
} | ||
// Get options | ||
if (options === undefined) | ||
options = this.options; | ||
resourceOptions = {}; | ||
id = data[options.idKey]; | ||
type = this.collectionName; | ||
// Get attributes | ||
if (options.projection !== undefined) { | ||
if (options.projection === null) { | ||
resourceOptions.attributes = __assign({}, data); | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_b && !_b.done && (_g = _a["return"])) _g.call(_a); | ||
else { | ||
resourceOptions.attributes = {}; | ||
type_1 = Object.values(options.projection)[0]; | ||
if (type_1 === 0) { | ||
try { | ||
for (_a = __values(Object.keys(data)), _b = _a.next(); !_b.done; _b = _a.next()) { | ||
key = _b.value; | ||
if (!(key in options.projection)) { | ||
resourceOptions.attributes[key] = data[key]; | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_b && !_b.done && (_e = _a["return"])) _e.call(_a); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
else { | ||
try { | ||
for (_d = __values(Object.entries(data)), _e = _d.next(); !_e.done; _e = _d.next()) { | ||
_f = __read(_e.value, 2), key = _f[0], value = _f[1]; | ||
attributes[key] = value; | ||
else { | ||
try { | ||
for (_c = __values(Object.keys(options.projection)), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
key = _d.value; | ||
resourceOptions.attributes[key] = data[key]; | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_d && !_d.done && (_f = _c["return"])) _f.call(_c); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_e && !_e.done && (_h = _d["return"])) _h.call(_d); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
delete resourceOptions.attributes[options.idKey]; | ||
} | ||
relationships = {}; | ||
if (!o.relators) return [3 /*break*/, 2]; | ||
relators = get_array_1.getArray(o.relators); | ||
return [4 /*yield*/, Promise.all(relators.map(function (relator) { | ||
var serializer = relator.getRelatedSerializer(); | ||
if (serializer) { | ||
return relator | ||
.getRelationship(data) | ||
.then(function (rship) { return (relationships[serializer.collectionName] = rship); }); | ||
} | ||
else | ||
return; | ||
if (!options.relators) return [3 /*break*/, 2]; | ||
relationships_1 = {}; | ||
return [4 /*yield*/, Promise.all(Object.entries(options.relators).map(function (_a) { | ||
var _b = __read(_a, 2), name = _b[0], relator = _b[1]; | ||
return __awaiter(_this, void 0, void 0, function () { | ||
var _c, _d; | ||
return __generator(this, function (_e) { | ||
switch (_e.label) { | ||
case 0: | ||
_c = relationships_1; | ||
_d = name; | ||
return [4 /*yield*/, relator.getRelationship(data)]; | ||
case 1: | ||
_c[_d] = _e.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}))]; | ||
case 1: | ||
_j.sent(); | ||
_j.label = 2; | ||
_g.sent(); | ||
resourceOptions.relationships = relationships_1; | ||
_g.label = 2; | ||
case 2: | ||
// Delete the ID field. | ||
delete attributes[o.idKey]; | ||
return [2 /*return*/, new resource_model_1["default"]({ | ||
type: this.collectionName, | ||
id: id, | ||
attributes: attributes, | ||
relationships: Object.keys(relationships).length > 0 ? relationships : undefined, | ||
links: o.linkers.resource ? { self: o.linkers.resource.link(data) } : undefined | ||
}, o.metaizers.resource ? o.metaizers.resource.metaize(data) : undefined)]; | ||
// Handling links | ||
if (options.linkers.resource) { | ||
resourceOptions.links = { self: options.linkers.resource.link(data) }; | ||
} | ||
if (options.metaizers.resource) { | ||
resourceOptions.meta = options.metaizers.resource.metaize(data); | ||
} | ||
return [2 /*return*/, new resource_model_1["default"](id, type, resourceOptions)]; | ||
} | ||
@@ -202,180 +235,19 @@ }); | ||
Serializer.prototype.serialize = function (data, options) { | ||
if (options === void 0) { options = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
function recurseResources(data) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var queue, depth, i, len, _a, data_1, relators, relators_1, relators_1_1, relator, serializer, relatedData, newData, relatedData_1, relatedData_1_1, datum, uniqueId, _b, _c, _d, e_8_1, e_9_1; | ||
var e_9, _e, e_8, _f; | ||
return __generator(this, function (_g) { | ||
switch (_g.label) { | ||
case 0: | ||
if (!(o.depth > 0 && o.relators)) return [3 /*break*/, 20]; | ||
queue = [[data, get_array_1.getArray(o.relators)]]; | ||
depth = o.depth; | ||
_g.label = 1; | ||
case 1: | ||
if (!(queue.length > 0 && depth-- > 0)) return [3 /*break*/, 20]; | ||
i = 0, len = queue.length; | ||
_g.label = 2; | ||
case 2: | ||
if (!(i < len)) return [3 /*break*/, 19]; | ||
_a = __read(queue[i], 2), data_1 = _a[0], relators = _a[1]; | ||
_g.label = 3; | ||
case 3: | ||
_g.trys.push([3, 16, 17, 18]); | ||
relators_1 = (e_9 = void 0, __values(relators)), relators_1_1 = relators_1.next(); | ||
_g.label = 4; | ||
case 4: | ||
if (!!relators_1_1.done) return [3 /*break*/, 15]; | ||
relator = relators_1_1.value; | ||
serializer = relator.getRelatedSerializer(); | ||
if (serializer === undefined) | ||
return [3 /*break*/, 14]; | ||
return [4 /*yield*/, Promise.all(data_1.map(relator.getRelatedData))]; | ||
case 5: | ||
relatedData = (_g.sent()).flat(); | ||
if (!(relatedData.length > 0)) return [3 /*break*/, 14]; | ||
newData = []; | ||
_g.label = 6; | ||
case 6: | ||
_g.trys.push([6, 11, 12, 13]); | ||
relatedData_1 = (e_8 = void 0, __values(relatedData)), relatedData_1_1 = relatedData_1.next(); | ||
_g.label = 7; | ||
case 7: | ||
if (!!relatedData_1_1.done) return [3 /*break*/, 10]; | ||
datum = relatedData_1_1.value; | ||
uniqueId = serializer.collectionName + " " + datum[serializer.options.idKey]; | ||
if (!!includedData.has(uniqueId)) return [3 /*break*/, 9]; | ||
if (!(!primaryData.has(uniqueId) || | ||
primaryData.get(uniqueId) instanceof resource_identifier_model_1["default"])) return [3 /*break*/, 9]; | ||
newData.push(datum); | ||
_c = (_b = includedData).set; | ||
_d = [uniqueId]; | ||
return [4 /*yield*/, serializer.constructResource(datum)]; | ||
case 8: | ||
_c.apply(_b, _d.concat([_g.sent()])); | ||
_g.label = 9; | ||
case 9: | ||
relatedData_1_1 = relatedData_1.next(); | ||
return [3 /*break*/, 7]; | ||
case 10: return [3 /*break*/, 13]; | ||
case 11: | ||
e_8_1 = _g.sent(); | ||
e_8 = { error: e_8_1 }; | ||
return [3 /*break*/, 13]; | ||
case 12: | ||
try { | ||
if (relatedData_1_1 && !relatedData_1_1.done && (_f = relatedData_1["return"])) _f.call(relatedData_1); | ||
} | ||
finally { if (e_8) throw e_8.error; } | ||
return [7 /*endfinally*/]; | ||
case 13: | ||
if (newData.length > 0 && serializer.options.relators) { | ||
queue.push([newData, get_array_1.getArray(serializer.options.relators)]); | ||
} | ||
_g.label = 14; | ||
case 14: | ||
relators_1_1 = relators_1.next(); | ||
return [3 /*break*/, 4]; | ||
case 15: return [3 /*break*/, 18]; | ||
case 16: | ||
e_9_1 = _g.sent(); | ||
e_9 = { error: e_9_1 }; | ||
return [3 /*break*/, 18]; | ||
case 17: | ||
try { | ||
if (relators_1_1 && !relators_1_1.done && (_e = relators_1["return"])) _e.call(relators_1); | ||
} | ||
finally { if (e_9) throw e_9.error; } | ||
return [7 /*endfinally*/]; | ||
case 18: | ||
i++; | ||
return [3 /*break*/, 2]; | ||
case 19: return [3 /*break*/, 1]; | ||
case 20: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
var o, includedData, primaryData, document, getIdentifiers, getResources, originallySingular, pagination, _a, _b, _c, identifier, relator, relationship, _d, _e, datum, resources, resources_1, resources_1_1, resource, _f, _g, identifier, resources_2, resources_2_1, resource; | ||
var e_3, _h, e_4, _j, e_5, _k, e_6, _l, e_7, _m; | ||
var o, document, relator_1, relatedData, links, meta, createIdentifier, keys_1, relators, createResource, _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, pagination, createIdentifier, keys_2, relators, createResource, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v; | ||
var _this = this; | ||
return __generator(this, function (_o) { | ||
switch (_o.label) { | ||
return __generator(this, function (_w) { | ||
switch (_w.label) { | ||
case 0: | ||
o = merge_1["default"]({}, this.options, options); | ||
// Validate options. | ||
if (o.depth < 0) { | ||
throw new RangeError("\"depth\" must be greater than or equal to 0"); | ||
o = options ? merge_1["default"]({}, this.options, options) : this.options; | ||
o.relators = serializer_utils_1.normalizeRelators(o.relators); | ||
document = {}; | ||
// Document versioning | ||
if (o.version) { | ||
document.jsonapi = __assign(__assign({}, document.jsonapi), { version: o.version }); | ||
} | ||
if (data === undefined && !(o.metaizers.document instanceof metaizer_1["default"])) { | ||
throw new TypeError("Data or a \"document\" metaizer must be given"); | ||
} | ||
includedData = new Map(); | ||
primaryData = new Map(); | ||
document = {}; | ||
// Constructing base document. | ||
document.jsonapi = { version: o.version }; | ||
// Handling document metadata. | ||
if (o.metaizers.jsonapi) { | ||
document.jsonapi.meta = o.metaizers.jsonapi.metaize(); | ||
document.jsonapi = __assign(__assign({}, document.jsonapi), { meta: o.metaizers.jsonapi.metaize() }); | ||
} | ||
if (o.metaizers.document) { | ||
document.meta = o.metaizers.document.metaize(data); | ||
} | ||
// Handling document linkers | ||
if (o.linkers.document) { | ||
document.links = __assign(__assign({}, document.links), { self: o.linkers.document.link(data) }); | ||
} | ||
getIdentifiers = function (data) { | ||
return data.map(function (datum) { return _this.constructResourceIdentity(datum, o); }); | ||
}; | ||
getResources = function (data) { | ||
return Promise.all(data.map(function (datum) { return _this.constructResource(datum, o); })); | ||
}; | ||
originallySingular = false; | ||
if (!data) return [3 /*break*/, 10]; | ||
if (!Array.isArray(data)) { | ||
originallySingular = true; | ||
data = [data]; | ||
} | ||
// Handling data-based document linkers | ||
if (o.linkers.paginator) { | ||
pagination = o.linkers.paginator.paginate(data); | ||
if (pagination) { | ||
document.links = __assign(__assign({}, document.links), o.linkers.paginator.paginate(data)); | ||
} | ||
} | ||
_a = true; | ||
switch (_a) { | ||
case o.nullData: return [3 /*break*/, 1]; | ||
case o.onlyIdentifier: return [3 /*break*/, 2]; | ||
case !!o.onlyRelationship: return [3 /*break*/, 3]; | ||
} | ||
return [3 /*break*/, 7]; | ||
case 1: | ||
{ | ||
document.data = null; | ||
return [3 /*break*/, 10]; | ||
} | ||
_o.label = 2; | ||
case 2: | ||
{ | ||
try { | ||
for (_b = __values(getIdentifiers(data)), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
identifier = _c.value; | ||
primaryData.set(identifier.type + " " + identifier.id, identifier); | ||
} | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_h = _b["return"])) _h.call(_b); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
return [3 /*break*/, 10]; | ||
} | ||
_o.label = 3; | ||
case 3: | ||
if (!o.onlyRelationship) return [3 /*break*/, 15]; | ||
// Validate options. | ||
@@ -385,104 +257,182 @@ if (o.relators === undefined) { | ||
} | ||
if (!originallySingular) { | ||
if (!data || Array.isArray(data)) { | ||
throw new TypeError("Cannot serialize multiple primary datum using \"onlyRelationship\""); | ||
} | ||
// Reset singularity option | ||
originallySingular = false; | ||
relator = get_array_1.getArray(o.relators).find(function (relator) { var _a; return !!(((_a = relator.getRelatedSerializer()) === null || _a === void 0 ? void 0 : _a.collectionName) === o.onlyRelationship); }); | ||
if (relator === undefined) { | ||
relator_1 = o.relators[o.onlyRelationship]; | ||
if (relator_1 === undefined) { | ||
throw new TypeError("\"onlyRelationship\" is not the name of any collection name among the relators listed in \"relators\""); | ||
} | ||
return [4 /*yield*/, relator.getRelationship(data[0])]; | ||
case 4: | ||
relationship = _o.sent(); | ||
if (relationship.links) { | ||
document.links = relationship.links; | ||
return [4 /*yield*/, relator_1.getRelatedData(data)]; | ||
case 1: | ||
relatedData = _w.sent(); | ||
links = relator_1.getRelatedLinks(data, relatedData); | ||
if (links) | ||
document.links = links; | ||
meta = relator_1.getRelatedMeta(data, relatedData); | ||
if (meta) | ||
document.meta = meta; | ||
if (relatedData === undefined) { | ||
return [2 /*return*/, document]; | ||
} | ||
if (relationship.meta) { | ||
document.meta = relationship.meta; | ||
if (o.nullData || relatedData === null) { | ||
document.data = null; | ||
return [2 /*return*/, document]; | ||
} | ||
if (!relationship.data) return [3 /*break*/, 6]; | ||
if (!Array.isArray(relationship.data)) { | ||
originallySingular = true; | ||
relationship.data = [relationship.data]; | ||
createIdentifier = function (datum) { return relator_1.getRelatedIdentifier(datum); }; | ||
// Handle `onlyIdentifier` option | ||
if (o.onlyIdentifier) { | ||
document.data = Array.isArray(relatedData) | ||
? relatedData.map(createIdentifier) | ||
: createIdentifier(relatedData); | ||
return [2 /*return*/, document]; | ||
} | ||
try { | ||
for (_d = __values(relationship.data), _e = _d.next(); !_e.done; _e = _d.next()) { | ||
datum = _e.value; | ||
primaryData.set(datum.type + " " + datum.id, datum); | ||
} | ||
} | ||
catch (e_4_1) { e_4 = { error: e_4_1 }; } | ||
finally { | ||
try { | ||
if (_e && !_e.done && (_j = _d["return"])) _j.call(_d); | ||
} | ||
finally { if (e_4) throw e_4.error; } | ||
} | ||
return [4 /*yield*/, recurseResources(data)]; | ||
keys_1 = []; | ||
relators = relator_1.getRelatedRelators(); | ||
createResource = function (datum) { return __awaiter(_this, void 0, void 0, function () { | ||
var resource; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, relator_1.getRelatedResource(datum)]; | ||
case 1: | ||
resource = _a.sent(); | ||
keys_1.push(resource.getKey()); | ||
return [2 /*return*/, resource]; | ||
} | ||
}); | ||
}); }; | ||
if (!Array.isArray(relatedData)) return [3 /*break*/, 8]; | ||
if (!o.asIncluded) return [3 /*break*/, 3]; | ||
document.data = relatedData.map(createIdentifier); | ||
_a = document; | ||
return [4 /*yield*/, Promise.all(relatedData.map(createResource))]; | ||
case 2: | ||
_a.included = _w.sent(); | ||
return [3 /*break*/, 5]; | ||
case 3: | ||
_b = document; | ||
return [4 /*yield*/, Promise.all(relatedData.map(createResource))]; | ||
case 4: | ||
_b.data = _w.sent(); | ||
_w.label = 5; | ||
case 5: | ||
_o.sent(); | ||
_o.label = 6; | ||
case 6: return [3 /*break*/, 10]; | ||
case 7: return [4 /*yield*/, getResources(data)]; | ||
if (!(relators && o.depth > 0)) return [3 /*break*/, 7]; | ||
_c = document; | ||
_e = (_d = (document.included || [])).concat; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators(relatedData, relators, o.depth, keys_1)]; | ||
case 6: | ||
_c.included = _e.apply(_d, [_w.sent()]); | ||
_w.label = 7; | ||
case 7: return [3 /*break*/, 14]; | ||
case 8: | ||
resources = _o.sent(); | ||
if (o.asIncluded) { | ||
try { | ||
for (resources_1 = __values(resources), resources_1_1 = resources_1.next(); !resources_1_1.done; resources_1_1 = resources_1.next()) { | ||
resource = resources_1_1.value; | ||
includedData.set(resource.type + " " + resource.id, resource); | ||
} | ||
} | ||
catch (e_5_1) { e_5 = { error: e_5_1 }; } | ||
finally { | ||
try { | ||
if (resources_1_1 && !resources_1_1.done && (_k = resources_1["return"])) _k.call(resources_1); | ||
} | ||
finally { if (e_5) throw e_5.error; } | ||
} | ||
try { | ||
for (_f = __values(getIdentifiers(data)), _g = _f.next(); !_g.done; _g = _f.next()) { | ||
identifier = _g.value; | ||
primaryData.set(identifier.type + " " + identifier.id, identifier); | ||
} | ||
} | ||
catch (e_6_1) { e_6 = { error: e_6_1 }; } | ||
finally { | ||
try { | ||
if (_g && !_g.done && (_l = _f["return"])) _l.call(_f); | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
} | ||
} | ||
else { | ||
try { | ||
for (resources_2 = __values(resources), resources_2_1 = resources_2.next(); !resources_2_1.done; resources_2_1 = resources_2.next()) { | ||
resource = resources_2_1.value; | ||
primaryData.set(resource.type + " " + resource.id, resource); | ||
} | ||
} | ||
catch (e_7_1) { e_7 = { error: e_7_1 }; } | ||
finally { | ||
try { | ||
if (resources_2_1 && !resources_2_1.done && (_m = resources_2["return"])) _m.call(resources_2); | ||
} | ||
finally { if (e_7) throw e_7.error; } | ||
} | ||
} | ||
return [4 /*yield*/, recurseResources(data)]; | ||
if (!o.asIncluded) return [3 /*break*/, 10]; | ||
document.data = createIdentifier(relatedData); | ||
_f = document; | ||
return [4 /*yield*/, createResource(relatedData)]; | ||
case 9: | ||
_o.sent(); | ||
_o.label = 10; | ||
_f.included = [_w.sent()]; | ||
return [3 /*break*/, 12]; | ||
case 10: | ||
if (includedData.size > 0) { | ||
document.included = __spread(includedData.values()); | ||
_g = document; | ||
return [4 /*yield*/, createResource(relatedData)]; | ||
case 11: | ||
_g.data = _w.sent(); | ||
_w.label = 12; | ||
case 12: | ||
if (!(relators && o.depth > 0)) return [3 /*break*/, 14]; | ||
_h = document; | ||
_k = (_j = (document.included || [])).concat; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators([relatedData], relators, o.depth, keys_1)]; | ||
case 13: | ||
_h.included = _k.apply(_j, [_w.sent()]); | ||
_w.label = 14; | ||
case 14: return [2 /*return*/, document]; | ||
case 15: | ||
// Handle meta | ||
if (o.metaizers.document) { | ||
document.meta = o.metaizers.document.metaize(data); | ||
} | ||
if (primaryData.size > 0) { | ||
document.data = originallySingular ? __spread(primaryData.values())[0] : __spread(primaryData.values()); | ||
// Handle links | ||
if (o.linkers.document) { | ||
document.links = __assign(__assign({}, document.links), { self: o.linkers.document.link(data) }); | ||
} | ||
else { | ||
document.data = originallySingular ? null : []; | ||
if (data === undefined) { | ||
return [2 /*return*/, document]; | ||
} | ||
return [2 /*return*/, document]; | ||
if (o.nullData || data === null) { | ||
document.data = null; | ||
return [2 /*return*/, document]; | ||
} | ||
// Data-based document links | ||
if (o.linkers.paginator) { | ||
pagination = o.linkers.paginator.paginate(data); | ||
if (pagination) { | ||
document.links = __assign(__assign({}, document.links), pagination); | ||
} | ||
} | ||
createIdentifier = function (datum) { return _this.createIdentifier(datum, o); }; | ||
// Handle `onlyIdentifier` option | ||
if (o.onlyIdentifier) { | ||
document.data = Array.isArray(data) ? data.map(createIdentifier) : createIdentifier(data); | ||
return [2 /*return*/, document]; | ||
} | ||
keys_2 = []; | ||
relators = o.relators; | ||
createResource = function (datum) { return __awaiter(_this, void 0, void 0, function () { | ||
var resource; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.createResource(datum, o)]; | ||
case 1: | ||
resource = _a.sent(); | ||
keys_2.push(resource.getKey()); | ||
return [2 /*return*/, resource]; | ||
} | ||
}); | ||
}); }; | ||
if (!Array.isArray(data)) return [3 /*break*/, 22]; | ||
if (!o.asIncluded) return [3 /*break*/, 17]; | ||
document.data = data.map(createIdentifier); | ||
_l = document; | ||
return [4 /*yield*/, Promise.all(data.map(createResource))]; | ||
case 16: | ||
_l.included = _w.sent(); | ||
return [3 /*break*/, 19]; | ||
case 17: | ||
_m = document; | ||
return [4 /*yield*/, Promise.all(data.map(createResource))]; | ||
case 18: | ||
_m.data = _w.sent(); | ||
_w.label = 19; | ||
case 19: | ||
if (!(relators && o.depth > 0)) return [3 /*break*/, 21]; | ||
_o = document; | ||
_q = (_p = (document.included || [])).concat; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators(data, relators, o.depth, keys_2)]; | ||
case 20: | ||
_o.included = _q.apply(_p, [_w.sent()]); | ||
_w.label = 21; | ||
case 21: return [3 /*break*/, 28]; | ||
case 22: | ||
if (!o.asIncluded) return [3 /*break*/, 24]; | ||
document.data = createIdentifier(data); | ||
_r = document; | ||
return [4 /*yield*/, createResource(data)]; | ||
case 23: | ||
_r.included = [_w.sent()]; | ||
return [3 /*break*/, 26]; | ||
case 24: | ||
_s = document; | ||
return [4 /*yield*/, createResource(data)]; | ||
case 25: | ||
_s.data = _w.sent(); | ||
_w.label = 26; | ||
case 26: | ||
if (!(relators && o.depth > 0)) return [3 /*break*/, 28]; | ||
_t = document; | ||
_v = (_u = (document.included || [])).concat; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators([data], relators, o.depth, keys_2)]; | ||
case 27: | ||
_t.included = _v.apply(_u, [_w.sent()]); | ||
_w.label = 28; | ||
case 28: return [2 /*return*/, document]; | ||
} | ||
@@ -503,2 +453,3 @@ }); | ||
depth: 0, | ||
projection: null, | ||
linkers: {}, | ||
@@ -505,0 +456,0 @@ metaizers: {} |
@@ -6,3 +6,3 @@ import Metaizer from "./classes/metaizer"; | ||
import Serializer from "./classes/serializer"; | ||
import JAPIError from "./models/error.model"; | ||
import JapiError from "./models/error.model"; | ||
import ErrorSerializer from "./classes/error-serializer"; | ||
@@ -16,3 +16,3 @@ export * from "./interfaces/error.interface"; | ||
export * from "./types/global.types"; | ||
export { Metaizer, Linker, Paginator, Relator, Serializer, JAPIError, ErrorSerializer }; | ||
export { Metaizer, Linker, Paginator, Relator, Serializer, JapiError, ErrorSerializer }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -16,3 +16,3 @@ "use strict"; | ||
exports.__esModule = true; | ||
exports.ErrorSerializer = exports.JAPIError = exports.Serializer = exports.Relator = exports.Paginator = exports.Linker = exports.Metaizer = void 0; | ||
exports.ErrorSerializer = exports.JapiError = exports.Serializer = exports.Relator = exports.Paginator = exports.Linker = exports.Metaizer = void 0; | ||
var metaizer_1 = __importDefault(require("./classes/metaizer")); | ||
@@ -29,3 +29,3 @@ exports.Metaizer = metaizer_1["default"]; | ||
var error_model_1 = __importDefault(require("./models/error.model")); | ||
exports.JAPIError = error_model_1["default"]; | ||
exports.JapiError = error_model_1["default"]; | ||
var error_serializer_1 = __importDefault(require("./classes/error-serializer")); | ||
@@ -32,0 +32,0 @@ exports.ErrorSerializer = error_serializer_1["default"]; |
@@ -43,3 +43,3 @@ import Linker from "../classes/linker"; | ||
*/ | ||
source: ErrorSourceAttribute<T>; | ||
source: Partial<ErrorSourceAttribute<T>>; | ||
} | ||
@@ -73,3 +73,3 @@ export interface ErrorSourceAttribute<T> { | ||
*/ | ||
attributes: ErrorAttributeOption<T>; | ||
attributes: Partial<ErrorAttributeOption<T>>; | ||
/** | ||
@@ -76,0 +76,0 @@ * A set of options for constructing [top-level links](https://jsonapi.org/format/#document-top-level). |
@@ -0,7 +1,8 @@ | ||
import { nullish } from "../types/global.types"; | ||
export interface PaginationOf<T> { | ||
first?: T | null; | ||
last?: T | null; | ||
prev?: T | null; | ||
next?: T | null; | ||
first: T | nullish; | ||
last: T | nullish; | ||
prev: T | nullish; | ||
next: T | nullish; | ||
} | ||
//# sourceMappingURL=paginator.interface.d.ts.map |
import Linker from "../classes/linker"; | ||
import Metaizer from "../classes/metaizer"; | ||
import Serializer from "../classes/serializer"; | ||
import { SingleOrArray, Dictionary } from "../types/global.types"; | ||
import { Dictionary, nullish, SingleOrArray } from "../types/global.types"; | ||
export interface RelatorOptions<PrimaryType, RelatedType extends Dictionary<any> = any> { | ||
/** | ||
* The `Serializer` to use for related data. | ||
*/ | ||
serializer?: Serializer<RelatedType>; | ||
/** | ||
* A dictionary of {@linkcode Linker}s to use for constructing links. | ||
@@ -20,3 +15,3 @@ * | ||
*/ | ||
relationship?: Linker<[PrimaryType, SingleOrArray<RelatedType>]>; | ||
relationship?: Linker<[PrimaryType, SingleOrArray<RelatedType> | nullish]>; | ||
/** | ||
@@ -26,3 +21,3 @@ * A {@linkcode Linker} that gets the [related link](https://jsonapi.org/format/#document-resource-object-relationships) | ||
*/ | ||
related?: Linker<[PrimaryType, SingleOrArray<RelatedType>]>; | ||
related?: Linker<[PrimaryType, SingleOrArray<RelatedType> | nullish]>; | ||
}; | ||
@@ -34,4 +29,4 @@ /** | ||
*/ | ||
metaizer?: Metaizer<[PrimaryType, SingleOrArray<RelatedType>]>; | ||
metaizer?: Metaizer<[PrimaryType, SingleOrArray<RelatedType> | nullish]>; | ||
} | ||
//# sourceMappingURL=relator.interface.d.ts.map |
@@ -5,4 +5,4 @@ import Linker from "../classes/linker"; | ||
import Relator from "../classes/relator"; | ||
import { Dictionary, SingleOrArray } from "../types/global.types"; | ||
export interface SerializerOptions<PrimaryType extends Dictionary<any>> { | ||
import { Dictionary, SingleOrArray, nullish } from "../types/global.types"; | ||
export interface SerializerOptions<PrimaryType extends Dictionary<any> = any> { | ||
/** | ||
@@ -15,7 +15,7 @@ * The key name for the identifier in the resource. | ||
/** | ||
* The highest JSON API version supported. | ||
* The highest JSON API version supported. Set to `null` to omit version. | ||
* | ||
* @default `1.0` | ||
*/ | ||
version: string; | ||
version: string | null; | ||
/** | ||
@@ -25,3 +25,4 @@ * Whether to use `null` value the `data` field. | ||
* This option will ignore options | ||
* {@linkcode SerializerOptions.onlyIdentifier | onlyIdentifier} and | ||
* {@linkcode SerializerOptions.onlyIdentifier | onlyIdentifier}, | ||
* {@linkcode SerializerOptions.linkers | linkers.resource}, and | ||
* {@linkcode SerializerOptions.metaizers | metaizers.resource} | ||
@@ -37,7 +38,3 @@ * (and all options they ignores). | ||
* This option will ignore the options | ||
* {@linkcode SerializerOptions.onlyRelationship | onlyRelationship}, | ||
* {@linkcode SerializerOptions.depth | depth}, and | ||
* {@linkcode SerializerOptions.relators | relators} (and all options they ignore | ||
* except {@linkcode SerializerOptions.linkers | linkers.resource} | ||
* and {@linkcode SerializerOptions.metaizers | metaizers.resource}). | ||
* {@linkcode SerializerOptions.depth | depth} | ||
* | ||
@@ -57,3 +54,2 @@ * @default `false` | ||
* {@linkcode SerializerOptions.projection | projection}, | ||
* {@linkcode SerializerOptions.asIncluded | asIncluded}, | ||
* {@linkcode SerializerOptions.linkers | linkers.resource}, and | ||
@@ -67,2 +63,4 @@ * {@linkcode SerializerOptions.metaizers | metaizers.resource}. | ||
* [top-level data](https://jsonapi.org/format/#document-top-level). | ||
* | ||
* @default `false` | ||
*/ | ||
@@ -84,7 +82,11 @@ asIncluded: boolean; | ||
/** | ||
* An object of 0 and 1 to denote hide and show of attributes respectively. | ||
* Every attribute hides by default, but if `undefined`, then all attributes | ||
* will show. | ||
* An object of 0 *OR* 1 (**NOT BOTH**) to denote hide or show attributes respectively. | ||
* | ||
* If set (directly) to `undefined`, then the `attributes` field will be left `undefined`. | ||
* If set to `null`, then every attribute will show. | ||
* If set to `{}`, then every attribute will hide. | ||
* | ||
* @default `null` | ||
*/ | ||
projection?: Partial<Record<keyof PrimaryType, 0 | 1>>; | ||
projection: Partial<Record<keyof PrimaryType, 0 | 1>> | null | undefined; | ||
/** | ||
@@ -101,3 +103,3 @@ * A {@linkcode Relator} that generates `relationships` for a given primary resource. | ||
*/ | ||
relators?: Relator<PrimaryType> | Array<Relator<PrimaryType>>; | ||
relators?: Relator<PrimaryType> | Array<Relator<PrimaryType>> | Record<string, Relator<PrimaryType>>; | ||
/** | ||
@@ -110,3 +112,3 @@ * A set of options for constructing [top-level links](https://jsonapi.org/format/#document-top-level). | ||
*/ | ||
document?: Linker<[SingleOrArray<PrimaryType> | undefined]>; | ||
document?: Linker<[SingleOrArray<PrimaryType> | nullish]>; | ||
/** | ||
@@ -132,3 +134,3 @@ * A {@linkcode Linker} that represents a [resource-level self link](https://jsonapi.org/format/#document-resource-objects). | ||
*/ | ||
document?: Metaizer<[SingleOrArray<PrimaryType> | undefined]>; | ||
document?: Metaizer<[SingleOrArray<PrimaryType> | nullish]>; | ||
/** | ||
@@ -135,0 +137,0 @@ * Constructs metadata for the [resource objects](https://jsonapi.org/format/#document-resource-objects) |
@@ -0,5 +1,6 @@ | ||
import { Dictionary, nullish } from ".."; | ||
import { ErrorOptions } from "../interfaces/error.interface"; | ||
import { LinkObject } from "../interfaces/document.interface"; | ||
import Link from "./link.model"; | ||
import Meta from "./meta.model"; | ||
export default class JAPIError { | ||
export default class JapiError { | ||
/** @internal */ | ||
@@ -50,3 +51,3 @@ stack: string; | ||
*/ | ||
links?: LinkObject; | ||
links?: Dictionary<Link | nullish>; | ||
/** | ||
@@ -53,0 +54,0 @@ * A meta object containing non-standard meta information about the error. |
"use strict"; | ||
exports.__esModule = true; | ||
var JAPIError = /** @class */ (function () { | ||
function JAPIError(options) { | ||
var JapiError = /** @class */ (function () { | ||
function JapiError(options) { | ||
if (options === void 0) { options = {}; } | ||
@@ -20,5 +20,5 @@ if (options.id) | ||
} | ||
return JAPIError; | ||
return JapiError; | ||
}()); | ||
exports["default"] = JAPIError; | ||
exports["default"] = JapiError; | ||
//# sourceMappingURL=error.model.js.map |
@@ -8,5 +8,11 @@ /// <reference types="node" /> | ||
constructor(href: string, meta?: Meta); | ||
private toJSON; | ||
private toString; | ||
toJSON: () => string | { | ||
href: string; | ||
meta: Meta; | ||
}; | ||
toString(): string | { | ||
href: string; | ||
meta: Meta; | ||
}; | ||
} | ||
//# sourceMappingURL=link.model.d.ts.map |
@@ -1,14 +0,17 @@ | ||
import { LinkObject, ResourceLinkage } from "../interfaces/document.interface"; | ||
import { Dictionary, nullish } from ".."; | ||
import { ResourceLinkage } from "../interfaces/json:api.interface"; | ||
import Link from "./link.model"; | ||
import Meta from "./meta.model"; | ||
interface RelationshipOptions { | ||
links?: LinkObject; | ||
/** @internal */ | ||
export interface RelationshipOptions { | ||
links?: Dictionary<Link | nullish>; | ||
data?: ResourceLinkage; | ||
meta?: Meta; | ||
} | ||
export default class Relationship { | ||
links?: LinkObject; | ||
links?: Dictionary<Link | nullish>; | ||
data?: ResourceLinkage; | ||
meta?: Meta; | ||
constructor(options: RelationshipOptions, meta?: Meta); | ||
constructor(options: RelationshipOptions); | ||
} | ||
export {}; | ||
//# sourceMappingURL=relationship.model.d.ts.map |
"use strict"; | ||
exports.__esModule = true; | ||
var Relationship = /** @class */ (function () { | ||
function Relationship(options, meta) { | ||
function Relationship(options) { | ||
if (options.links) | ||
@@ -9,4 +9,4 @@ this.links = options.links; | ||
this.data = options.data; | ||
if (meta) | ||
this.meta = meta; | ||
if (options.meta) | ||
this.meta = options.meta; | ||
if (!this.links && !this.data && !this.meta) { | ||
@@ -13,0 +13,0 @@ throw new Error("Relationships must contain at least a link, data, or meta. See https://jsonapi.org/format/#document-resource-object-relationships for more information."); |
import Meta from "./meta.model"; | ||
import { ResourceIdentifierOptions } from "../interfaces/resource.interface"; | ||
/** @internal */ | ||
export interface ResourceIdentifierOptions { | ||
meta?: Meta; | ||
} | ||
export default class ResourceIdentifier { | ||
@@ -7,4 +10,5 @@ type: string; | ||
meta?: Meta; | ||
constructor(options: ResourceIdentifierOptions, meta?: Meta); | ||
constructor(id: string, type: string, options: ResourceIdentifierOptions); | ||
getKey(): string; | ||
} | ||
//# sourceMappingURL=resource-identifier.model.d.ts.map |
"use strict"; | ||
exports.__esModule = true; | ||
var ResourceIdentifier = /** @class */ (function () { | ||
function ResourceIdentifier(options, meta) { | ||
this.type = options.type; | ||
this.id = options.id; | ||
if (meta) | ||
this.meta = meta; | ||
function ResourceIdentifier(id, type, options) { | ||
this.type = type; | ||
this.id = id; | ||
if (options.meta) | ||
this.meta = options.meta; | ||
} | ||
ResourceIdentifier.prototype.getKey = function () { | ||
return "[" + this.type + ":" + this.id + "]"; | ||
}; | ||
return ResourceIdentifier; | ||
@@ -11,0 +14,0 @@ }()); |
@@ -1,13 +0,17 @@ | ||
import { LinkObject } from "../interfaces/document.interface"; | ||
import { ResourceOptions } from "../interfaces/resource.interface"; | ||
import { Dictionary } from "../types/global.types"; | ||
import Meta from "./meta.model"; | ||
import Link from "../models/link.model"; | ||
import { Dictionary, nullish } from "../types/global.types"; | ||
import Relationship from "./relationship.model"; | ||
import ResourceIdentifier from "./resource-identifier.model"; | ||
import ResourceIdentifier, { ResourceIdentifierOptions } from "./resource-identifier.model"; | ||
/** @internal */ | ||
export interface ResourceOptions<T> extends ResourceIdentifierOptions { | ||
attributes?: Partial<T>; | ||
relationships?: Record<string, Relationship>; | ||
links?: Dictionary<Link>; | ||
} | ||
export default class Resource<T = Dictionary<any>> extends ResourceIdentifier { | ||
attributes?: Partial<T>; | ||
relationships?: Relationship; | ||
links?: LinkObject; | ||
constructor(options: ResourceOptions<T>, meta?: Meta); | ||
links?: Dictionary<Link | nullish>; | ||
relationships?: Record<string, Relationship>; | ||
constructor(id: string, type: string, options: ResourceOptions<T>); | ||
} | ||
//# sourceMappingURL=resource.model.d.ts.map |
@@ -22,4 +22,4 @@ "use strict"; | ||
__extends(Resource, _super); | ||
function Resource(options, meta) { | ||
var _this = _super.call(this, { id: options.id, type: options.type }, meta) || this; | ||
function Resource(id, type, options) { | ||
var _this = _super.call(this, id, type, options) || this; | ||
if (options.attributes) | ||
@@ -26,0 +26,0 @@ _this.attributes = options.attributes; |
@@ -6,9 +6,10 @@ /** | ||
/** | ||
* A function that takes several arguments and outputs something. | ||
* | ||
* @see {@link https://en.wikipedia.org/wiki/Variadic_function} | ||
*/ | ||
* A function that takes several arguments and outputs something. | ||
* | ||
* @see {@link https://en.wikipedia.org/wiki/Variadic_function} | ||
*/ | ||
export declare type VariadicFunction<Dependencies extends any[], ReturnType> = (...dependencies: Dependencies) => ReturnType; | ||
export declare type Dictionary<T> = Record<string | number | symbol, T>; | ||
export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; | ||
export declare type nullish = null | undefined; | ||
export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; | ||
//# sourceMappingURL=global.types.d.ts.map |
@@ -1,2 +0,2 @@ | ||
export declare function isObject(o: any): boolean; | ||
export declare function isObject(o: any): o is object; | ||
//# sourceMappingURL=is-object-object.d.ts.map |
{ | ||
"name": "ts-japi", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "A highly-modular (typescript-friendly)-framework agnostic library for serializing data to the JSON:API specification", | ||
@@ -8,2 +8,4 @@ "main": "lib/index.js", | ||
"examples": "ts-node ./examples/", | ||
"benchmark": "ts-node ./benchmarks/serializer.benchmark", | ||
"playground": "ts-node ./benchmarks/playground.benchmark", | ||
"build-docs": "npm run clean-docs && typedoc && rsync -a ./src/docs/assets ./docs", | ||
@@ -40,2 +42,3 @@ "build-readme": "npm run clean-readme && typedoc --plugin typedoc-plugin-markdown --out ./md-docs --theme markdown && mv md-docs/README.md README.md && rm -R md-docs && ts-node scripts/readme.script.ts", | ||
"devDependencies": { | ||
"@types/benchmark": "^1.0.33", | ||
"@babel/cli": "^7.8.4", | ||
@@ -54,2 +57,3 @@ "@babel/core": "^7.9.6", | ||
"babel-jest": "^26.0.1", | ||
"benchmark": "^2.1.4", | ||
"core-js": "^3.6.5", | ||
@@ -56,0 +60,0 @@ "eslint": "^7.0.0", |
@@ -190,5 +190,6 @@ <br /> | ||
const ArticleSerializer = new Serializer<Article>("articles"); | ||
const UserArticleRelator = new Relator<User, Article>(async (user) => user.getArticles(), { | ||
serializer: ArticleSerializer, | ||
}); | ||
const UserArticleRelator = new Relator<User, Article>( | ||
async (user) => user.getArticles(), | ||
ArticleSerializer | ||
); | ||
@@ -252,3 +253,3 @@ // ! The rest of this example is just to illustrate some internal behavior. | ||
The [`ErrorSerializer`](https://jun-sheaf.github.io/ts-japi/classes/errorserializer.html) is used to serialize any object considered an error (the [`attributes`](https://jun-sheaf.github.io/ts-japi/interfaces/errorserializeroptions.html#attributes) option allows you to choose what attributes to use during serialization). *Alternatively* (**recommended**), you can construct custom errors by extending the [`JAPIError`](https://jun-sheaf.github.io/ts-japi/classes/japierror.html) class and use those for all server-to-client errors. | ||
The [`ErrorSerializer`](https://jun-sheaf.github.io/ts-japi/classes/errorserializer.html) is used to serialize any object considered an error (the [`attributes`](https://jun-sheaf.github.io/ts-japi/interfaces/errorserializeroptions.html#attributes) option allows you to choose what attributes to use during serialization). *Alternatively* (**recommended**), you can construct custom errors by extending the [`JapiError`](https://jun-sheaf.github.io/ts-japi/classes/japierror.html) class and use those for all server-to-client errors. | ||
@@ -298,3 +299,3 @@ The [error serializer test](https://github.com/jun-sheaf/ts-japi/tree/master/test/error-serializer.test.ts) includes an example of the alternative solution. | ||
Due to [compound documents](https://jsonapi.org/format/#document-compound-documents), it is possible to recurse through related resources via their [resource linkages](https://jsonapi.org/format/#document-resource-object-linkage) and obtain [included resources](https://jsonapi.org/format/#document-top-level) beyond what the primary data gives. This is not preferable and should be done with caution (see [`SerializerOptions.depth`](https://jun-sheaf.github.io/ts-japi/interfaces/serializeroptions.html#depth)) | ||
Due to [compound documents](https://jsonapi.org/format/#document-compound-documents), it is possible to recurse through related resources via their [resource linkages](https://jsonapi.org/format/#document-resource-object-linkage) and obtain [included resources](https://jsonapi.org/format/#document-top-level) beyond what the primary data gives. This is not preferable and should be done with caution (see [`SerializerOptions.depth`](https://jun-sheaf.github.io/ts-japi/interfaces/serializeroptions.html#depth) and [this example](https://github.com/jun-sheaf/ts-japi/blob/master/examples/resource-recursion.example.ts)) | ||
@@ -301,0 +302,0 @@ > Is the "zero dependencies" a gimmick?<a id="zdg"></a> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2298
316
205566
29
112