ts-japi
Advanced tools
Comparing version 1.5.1 to 1.6.0
@@ -1,2 +0,2 @@ | ||
import Benchmark from "benchmark"; | ||
import Benchmark from 'benchmark'; | ||
@@ -6,6 +6,6 @@ const suite = new Benchmark.Suite(); | ||
const a: any = new Map(); | ||
a.set("test", "test"); | ||
a.set('test', 'test'); | ||
const b: any = {}; | ||
b.test = "test"; | ||
b.test = 'test'; | ||
@@ -18,4 +18,4 @@ var length = 100; // user defined length | ||
for (var i = 0; i < length; i++) { | ||
array.push(i); | ||
map.set(i, 0); | ||
array.push(i); | ||
map.set(i, 0); | ||
} | ||
@@ -26,28 +26,28 @@ const tobepushed = [1, 2, 3]; | ||
suite | ||
.add("Array#ForOf", async function () { | ||
const g = []; | ||
for (const test of array) { | ||
g.push(test); | ||
} | ||
}) | ||
.add("Array#index", async function () { | ||
const g = []; | ||
for (let i = 0, len = array.length; i < len; i++) { | ||
g.push(array[i]); | ||
} | ||
}) | ||
.add("Array#indexWithTemp", async function () { | ||
const g = []; | ||
for (let i = 0, temp = array[i]; i < array.length; temp = array[++i]) { | ||
g.push(temp); | ||
} | ||
}) | ||
// add listeners | ||
.on("cycle", function (event: any) { | ||
console.log(String(event.target)); | ||
}) | ||
.on("complete", function (this: any) { | ||
console.log("Fastest is " + this.filter("fastest").map("name")); | ||
}) | ||
// run async | ||
.run({ async: true }); | ||
.add('Array#ForOf', async function () { | ||
const g = []; | ||
for (const test of array) { | ||
g.push(test); | ||
} | ||
}) | ||
.add('Array#index', async function () { | ||
const g = []; | ||
for (let i = 0, len = array.length; i < len; i++) { | ||
g.push(array[i]); | ||
} | ||
}) | ||
.add('Array#indexWithTemp', async function () { | ||
const g = []; | ||
for (let i = 0, temp = array[i]; i < array.length; temp = array[++i]) { | ||
g.push(temp); | ||
} | ||
}) | ||
// add listeners | ||
.on('cycle', function (event: any) { | ||
console.log(String(event.target)); | ||
}) | ||
.on('complete', function (this: any) { | ||
console.log('Fastest is ' + this.filter('fastest').map('name')); | ||
}) | ||
// run async | ||
.run({ async: true }); |
@@ -1,4 +0,4 @@ | ||
import Benchmark from "benchmark"; | ||
import { Relator, Serializer } from "../src"; | ||
import { Article, Comment, User } from "../test/models"; | ||
import Benchmark from 'benchmark'; | ||
import { Relator, Serializer } from '../src'; | ||
import { Article, Comment, User } from '../test/models'; | ||
@@ -8,27 +8,27 @@ const suite = new Benchmark.Suite(); | ||
for (let i = 0; i < 5; i++) { | ||
User.save(new User(String(i))); | ||
User.save(new User(String(i))); | ||
} | ||
for (let i = 0; i < 5; i++) { | ||
Article.save(new Article(String(i), User.storage[0])); | ||
Article.save(new Article(String(i), User.storage[0])); | ||
} | ||
for (let i = 0; i < 10; i++) { | ||
Comment.save(new Comment(String(i), User.storage[0], Article.storage[0])); | ||
Comment.save(new Comment(String(i), User.storage[0], Article.storage[0])); | ||
} | ||
let UserSerializer = new Serializer<User>("users", { | ||
depth: 0, // Change to 2 to see the difference | ||
cache: true | ||
let UserSerializer = new Serializer<User>('users', { | ||
depth: 0, // Change to 2 to see the difference | ||
cache: true, | ||
}); | ||
let CommentSerializer = new Serializer<Comment>("comments"); | ||
let ArticleSerializer = new Serializer<Article>("articles"); | ||
let CommentSerializer = new Serializer<Comment>('comments'); | ||
let ArticleSerializer = new Serializer<Article>('articles'); | ||
const UserArticleRelator = new Relator<User, Article>( | ||
async (user: User) => user.getArticles(), | ||
ArticleSerializer | ||
async (user: User) => user.getArticles(), | ||
ArticleSerializer | ||
); | ||
const ArticleCommentRelator = new Relator<Article, Comment>( | ||
async (article: Article) => article.getComments(), | ||
CommentSerializer | ||
async (article: Article) => article.getComments(), | ||
CommentSerializer | ||
); | ||
const CommentUserRelator = new Relator<Comment, User>( | ||
async (comment: Comment) => comment.getAuthor(), | ||
UserSerializer | ||
async (comment: Comment) => comment.getAuthor(), | ||
UserSerializer | ||
); | ||
@@ -43,13 +43,13 @@ CommentSerializer.setRelators(CommentUserRelator); | ||
suite | ||
.add("Serializer#Test", async function () { | ||
await UserSerializer.serialize(user); | ||
}) | ||
// add listeners | ||
.on("cycle", function (event: any) { | ||
console.log(String(event.target)); | ||
}) | ||
.on("complete", function (this: any) { | ||
console.log("Fastest is " + this.filter("fastest").map("name")); | ||
}) | ||
// run async | ||
.run({ async: true }); | ||
.add('Serializer#Test', async function () { | ||
await UserSerializer.serialize(user); | ||
}) | ||
// add listeners | ||
.on('cycle', function (event: any) { | ||
console.log(String(event.target)); | ||
}) | ||
.on('complete', function (this: any) { | ||
console.log('Fastest is ' + this.filter('fastest').map('name')); | ||
}) | ||
// run async | ||
.run({ async: true }); |
# Changelog | ||
## 1.6.0 | ||
### Minor Changes | ||
- bd4c358: Add `relatorDataCache` in serialize method to avoid duplicate lookups during | ||
`recurseRelators` call | ||
## 1.5.1 | ||
@@ -26,4 +33,8 @@ | ||
- Added an `isErrorDocument` function to detect JSON:API Error documents. This function allows you to treat the argument _as if it were an error document_ (there is obviously no way to know if it really is a JSON:API error document at runtime). | ||
- Added an `isLikeJapiError` function to detect JSON:API Error. This function allows you to treat the argument _as if it were an JSON:API error_ (there is obviously no way to know if it really is a JSON:API error at runtime). | ||
- Added an `isErrorDocument` function to detect JSON:API Error documents. This function allows you | ||
to treat the argument _as if it were an error document_ (there is obviously no way to know if it | ||
really is a JSON:API error document at runtime). | ||
- Added an `isLikeJapiError` function to detect JSON:API Error. This function allows you to treat | ||
the argument _as if it were an JSON:API error_ (there is obviously no way to know if it really is | ||
a JSON:API error at runtime). | ||
@@ -51,3 +62,4 @@ ### Changed | ||
- Exported interfaces related to JSON:API. | ||
- The Error and Data document interfaces now require the "errors" and "data" properties respectively. | ||
- The Error and Data document interfaces now require the "errors" and "data" properties | ||
respectively. | ||
- The Base document interface has been abstracted further by removing the "meta" property. | ||
@@ -73,4 +85,6 @@ - A _new_ Meta document interface is now available for type-checking. | ||
- A new `Cache` class is now available to use for caching. You can set this in the `cache` option for a `Serializer` (use `true` if you want the built in cache). | ||
- With caching, there is a ~586% speed improvement (412,768 ops/sec over the previous 70,435 ops/sec). Without-caching rates have stayed the same. | ||
- A new `Cache` class is now available to use for caching. You can set this in the `cache` option | ||
for a `Serializer` (use `true` if you want the built in cache). | ||
- With caching, there is a ~586% speed improvement (412,768 ops/sec over the previous 70,435 | ||
ops/sec). Without-caching rates have stayed the same. | ||
@@ -85,7 +99,11 @@ ## [1.2.1] - 2020-05-27 | ||
So, `ts-japi` has only been released a few days, but after some significant use in my APIs, I have realized a few things: | ||
So, `ts-japi` has only been released a few days, but after some significant use in my APIs, I have | ||
realized a few things: | ||
1. Linkers and certain classes should be allowed to parse `nullish` data (`nullish` meaning `undefined` or `null`). | ||
2. The `relationships object` should be allowed to have custom keys, not dependent on the `relators` options | ||
- `Relator`s should always have a `Serializer`; otherwise, they wouldn't relate to any `resource` per se. | ||
1. Linkers and certain classes should be allowed to parse `nullish` data (`nullish` meaning | ||
`undefined` or `null`). | ||
2. The `relationships object` should be allowed to have custom keys, not dependent on the `relators` | ||
options | ||
- `Relator`s should always have a `Serializer`; otherwise, they wouldn't relate to any `resource` | ||
per se. | ||
3. Projections should be "choose included" or "choose excluded" similar to MongoDB's. | ||
@@ -98,5 +116,10 @@ 4. The code can be faster. | ||
- **[Breaking Change]** Every relator must define a `Serializer` as the second argument in its constructor (as opposed to the relator's options. Options can go in the third argument. | ||
- It may be subtle, but the reason for this lies in the fact `relationships object` must be keyed by the related object. If the relator has no serializer, then the relator has no related name, hence there is no canonical way to key the relationship. | ||
- We will now allow objects of relators to be defined as an option for `relators` on `Serializer`s. By using objects, the key for the relationship generated by the relator will correspond to the same key for that of the relator's. | ||
- **[Breaking Change]** Every relator must define a `Serializer` as the second argument in its | ||
constructor (as opposed to the relator's options. Options can go in the third argument. | ||
- It may be subtle, but the reason for this lies in the fact `relationships object` must be keyed | ||
by the related object. If the relator has no serializer, then the relator has no related name, | ||
hence there is no canonical way to key the relationship. | ||
- We will now allow objects of relators to be defined as an option for `relators` on | ||
`Serializer`s. By using objects, the key for the relationship generated by the relator will | ||
correspond to the same key for that of the relator's. | ||
- Several functional options now allow for `nullish` (`null` or `undefined`) arguments: | ||
@@ -106,4 +129,6 @@ - Resource Linkers can now type-safely use `nullish` arguments. | ||
- Several plain options now allow for `nullish` (`null` or `undefined`): | ||
- Serializer `projection` option has changed significantly (see the option itself) with `nullish` values. | ||
- There is a ~33% speed improvement. (70,435 ops/sec over 52,843 ops/sec on a low-end Macbook Pro 15") | ||
- Serializer `projection` option has changed significantly (see the option itself) with `nullish` | ||
values. | ||
- There is a ~33% speed improvement. (70,435 ops/sec over 52,843 ops/sec on a low-end Macbook Pro | ||
15") | ||
@@ -116,2 +141,5 @@ ### Added | ||
I want to say this IS unusual to have a breaking change without depreciation, but given the fact this package is only a few days old, I want to apologize if you are bothered by the above break. However, I will guarantee that API changes will go through depreciation before removal, so happy coding :) | ||
I want to say this IS unusual to have a breaking change without depreciation, but given the fact | ||
this package is only a few days old, I want to apologize if you are bothered by the above break. | ||
However, I will guarantee that API changes will go through depreciation before removal, so happy | ||
coding :) |
@@ -1,5 +0,5 @@ | ||
import { SerializerOptions } from "../interfaces/serializer.interface"; | ||
import { DataDocument } from "../interfaces/json-api.interface"; | ||
import { SingleOrArray, nullish } from "../types/global.types"; | ||
import { CacheOptions } from "../interfaces/cache.interface"; | ||
import { SerializerOptions } from '../interfaces/serializer.interface'; | ||
import { DataDocument } from '../interfaces/json-api.interface'; | ||
import { SingleOrArray, nullish } from '../types/global.types'; | ||
import { CacheOptions } from '../interfaces/cache.interface'; | ||
export default class Cache<PrimaryType> { | ||
@@ -6,0 +6,0 @@ /** |
@@ -1,4 +0,4 @@ | ||
import { ErrorSerializerOptions } from "../interfaces/error-serializer.interface"; | ||
import { ErrorDocument } from "../interfaces/json-api.interface"; | ||
import { SingleOrArray } from "../types/global.types"; | ||
import { ErrorSerializerOptions } from '../interfaces/error-serializer.interface'; | ||
import { ErrorDocument } from '../interfaces/json-api.interface'; | ||
import { SingleOrArray } from '../types/global.types'; | ||
/** | ||
@@ -5,0 +5,0 @@ * The {@linkcode ErrorSerializer} class is used to serialize errors. |
@@ -182,11 +182,11 @@ "use strict"; | ||
ErrorSerializer.defaultOptions = { | ||
version: "1.0", | ||
version: '1.0', | ||
attributes: { | ||
id: "id", | ||
status: "code", | ||
code: "name", | ||
title: "reason", | ||
detail: "message", | ||
id: 'id', | ||
status: 'code', | ||
code: 'name', | ||
title: 'reason', | ||
detail: 'message', | ||
source: { | ||
pointer: "location", | ||
pointer: 'location', | ||
parameter: undefined | ||
@@ -193,0 +193,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { LinkerOptions } from "../interfaces/linker.interface"; | ||
import Link from "../models/link.model"; | ||
import { VariadicFunction } from "../types/global.types"; | ||
import { LinkerOptions } from '../interfaces/linker.interface'; | ||
import Link from '../models/link.model'; | ||
import { VariadicFunction } from '../types/global.types'; | ||
/** | ||
@@ -5,0 +5,0 @@ * The {@linkcode Linker} class is used to construct a [link](https://jsonapi.org/format/#document-links). |
@@ -18,5 +18,6 @@ "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 __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
@@ -52,4 +53,4 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return options.metaizer | ||
? new link_model_1["default"](link.apply(void 0, __spread(datas)), (_a = options.metaizer).metaize.apply(_a, __spread(datas))) | ||
: new link_model_1["default"](link.apply(void 0, __spread(datas))); | ||
? new link_model_1["default"](link.apply(void 0, __spreadArray([], __read(datas))), (_a = options.metaizer).metaize.apply(_a, __spreadArray([], __read(datas)))) | ||
: new link_model_1["default"](link.apply(void 0, __spreadArray([], __read(datas)))); | ||
}; | ||
@@ -56,0 +57,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import Meta from "../models/meta.model"; | ||
import { Dictionary, VariadicFunction } from "../types/global.types"; | ||
import Meta from '../models/meta.model'; | ||
import { Dictionary, VariadicFunction } from '../types/global.types'; | ||
/** | ||
@@ -4,0 +4,0 @@ * The {@linkcode Metaizer} class is used to construct [meta information](https://jsonapi.org/format/#document-meta). |
@@ -18,5 +18,6 @@ "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 __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
@@ -49,3 +50,3 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||
} | ||
return new meta_model_1["default"](metaize.apply(void 0, __spread(datas))); | ||
return new meta_model_1["default"](metaize.apply(void 0, __spreadArray([], __read(datas)))); | ||
}; | ||
@@ -52,0 +53,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import { PaginationOf } from "../interfaces/paginator.interface"; | ||
import Link from "../models/link.model"; | ||
import { SingleOrArray } from "../types/global.types"; | ||
import { PaginationOf } from '../interfaces/paginator.interface'; | ||
import Link from '../models/link.model'; | ||
import { SingleOrArray } from '../types/global.types'; | ||
/** | ||
@@ -5,0 +5,0 @@ * The {@linkcode Paginator} class is used to construct [pagination links](https://jsonapi.org/format/#fetching-pagination). |
@@ -27,6 +27,6 @@ "use strict"; | ||
return { | ||
first: typeof links.first === "string" ? new link_model_1["default"](links.first) : links.first, | ||
last: typeof links.last === "string" ? new link_model_1["default"](links.last) : links.last, | ||
prev: typeof links.prev === "string" ? new link_model_1["default"](links.prev) : links.prev, | ||
next: typeof links.next === "string" ? new link_model_1["default"](links.next) : links.next | ||
first: typeof links.first === 'string' ? new link_model_1["default"](links.first) : links.first, | ||
last: typeof links.last === 'string' ? new link_model_1["default"](links.last) : links.last, | ||
prev: typeof links.prev === 'string' ? new link_model_1["default"](links.prev) : links.prev, | ||
next: typeof links.next === 'string' ? new link_model_1["default"](links.next) : links.next | ||
}; | ||
@@ -33,0 +33,0 @@ }; |
@@ -1,10 +0,11 @@ | ||
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 ResourceIdentifier from "../models/resource-identifier.model"; | ||
import Resource from "../models/resource.model"; | ||
import { Dictionary, nullish } from "../types/global.types"; | ||
import Serializer from "./serializer"; | ||
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 ResourceIdentifier from '../models/resource-identifier.model'; | ||
import Resource from '../models/resource.model'; | ||
import { Dictionary, nullish } from '../types/global.types'; | ||
import { Helpers } from '../utils/serializer.utils'; | ||
import Serializer from './serializer'; | ||
/** | ||
@@ -46,10 +47,10 @@ * The {@linkcode Relator} class is used to generate top-level [included data](https://jsonapi.org/format/#document-top-level) | ||
/** @internal Creates related resources */ | ||
getRelatedResource: (data: RelatedType, options?: SerializerOptions<RelatedType>) => Promise<Resource<RelatedType>>; | ||
getRelatedResource: (data: RelatedType, options?: SerializerOptions<RelatedType>, helpers?: Helpers<RelatedType>, relatorDataCache?: Map<Relator<any>, Dictionary<any>[]>) => 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; | ||
getRelatedLinks(data: PrimaryType, relatedData: RelatedType | RelatedType[] | nullish): Dictionary<nullish | Link> | 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}. */ | ||
getRelationship(data: PrimaryType): Promise<Relationship>; | ||
getRelationship(data: PrimaryType, relatedDataCache?: Dictionary<any>[]): Promise<Relationship>; | ||
} | ||
//# sourceMappingURL=relator.d.ts.map |
@@ -49,2 +49,23 @@ "use strict"; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -103,3 +124,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
/** @internal Creates a {@linkcode Relationship}. */ | ||
Relator.prototype.getRelationship = function (data) { | ||
Relator.prototype.getRelationship = function (data, relatedDataCache) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -115,2 +136,5 @@ var relationshipOptions, relatedData, links, meta; | ||
relatedData = _a.sent(); | ||
if (relatedData && relatedDataCache) { | ||
relatedDataCache.push.apply(relatedDataCache, __spreadArray([], __read((Array.isArray(relatedData) ? relatedData : [relatedData])))); | ||
} | ||
links = this.getRelatedLinks(data, relatedData); | ||
@@ -117,0 +141,0 @@ if (links) |
@@ -1,8 +0,9 @@ | ||
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, nullish, SingleOrArray } from "../types/global.types"; | ||
import { Helpers } from "../utils/serializer.utils"; | ||
import Cache from "./cache"; | ||
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, nullish, SingleOrArray } from '../types/global.types'; | ||
import { Helpers } from '../utils/serializer.utils'; | ||
import Cache from './cache'; | ||
import Relator from './relator'; | ||
/** | ||
@@ -60,11 +61,11 @@ * The {@linkcode Serializer} class is the main class used to serializer data | ||
*/ | ||
getRelators(): Record<string, import("./relator").default<PrimaryType, any>> | undefined; | ||
getRelators(): Record<string, Relator<PrimaryType, any>> | undefined; | ||
/** | ||
* Sets the {@linkcode Relator}s associated with this serializer | ||
*/ | ||
setRelators(relators: SerializerOptions<PrimaryType>["relators"]): void; | ||
setRelators(relators: SerializerOptions<PrimaryType>['relators']): void; | ||
/** @internal Generates a `ResourceIdentifier`. */ | ||
createIdentifier(data: PrimaryType, options?: SerializerOptions<PrimaryType>): ResourceIdentifier; | ||
/** @internal Generates a `Resource`. */ | ||
createResource(data: PrimaryType, options?: SerializerOptions<PrimaryType>, helpers?: Helpers<PrimaryType>): Promise<Resource<PrimaryType>>; | ||
createResource(data: PrimaryType, options?: SerializerOptions<PrimaryType>, helpers?: Helpers<PrimaryType>, relatorDataCache?: Map<Relator<any>, Dictionary<any>[]>): Promise<Resource<PrimaryType>>; | ||
/** | ||
@@ -71,0 +72,0 @@ * The actual serialization function. |
@@ -130,3 +130,3 @@ "use strict"; | ||
/** @internal Generates a `Resource`. */ | ||
Serializer.prototype.createResource = function (data, options, helpers) { | ||
Serializer.prototype.createResource = function (data, options, helpers, relatorDataCache) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -153,9 +153,13 @@ var resourceOptions, id, type, relationships_1; | ||
return __awaiter(_this, void 0, void 0, function () { | ||
var _c, _d; | ||
var relatedDataCache, _c, _d; | ||
return __generator(this, function (_e) { | ||
switch (_e.label) { | ||
case 0: | ||
if (relatorDataCache) { | ||
relatedDataCache = relatorDataCache.get(relator) || []; | ||
relatorDataCache.set(relator, relatedDataCache); | ||
} | ||
_c = relationships_1; | ||
_d = name; | ||
return [4 /*yield*/, relator.getRelationship(data)]; | ||
return [4 /*yield*/, relator.getRelationship(data, relatedDataCache)]; | ||
case 1: | ||
@@ -193,3 +197,3 @@ _c[_d] = _e.sent(); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var o, h, cache, storedDocument, document, keys, wasSingle, dto, createIdentifier, createResource, relators, relator_1, relatedData, links, meta, pagination, _a, _b, _c, _d, _e; | ||
var o, h, cache, storedDocument, document, relatorDataCache, keys, wasSingle, dto, createIdentifier, createResource, relators, relator_1, relatedData, links, meta, pagination, _a, _b, _c, _d, _e; | ||
var _this = this; | ||
@@ -220,2 +224,3 @@ return __generator(this, function (_f) { | ||
} | ||
relatorDataCache = new Map(); | ||
keys = []; | ||
@@ -281,3 +286,3 @@ wasSingle = false; | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.createResource(datum, o, h)]; | ||
case 0: return [4 /*yield*/, this.createResource(datum, o, h, relatorDataCache)]; | ||
case 1: | ||
@@ -327,3 +332,3 @@ resource = _a.sent(); | ||
_e = (_d = (document.included || [])).concat; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators(dto, relators, o.depth, keys)]; | ||
return [4 /*yield*/, serializer_utils_1.recurseRelators(dto, relators, o.depth, keys, relatorDataCache)]; | ||
case 8: | ||
@@ -345,4 +350,4 @@ _c.included = _e.apply(_d, [_f.sent()]); | ||
Serializer.defaultOptions = { | ||
idKey: "id", | ||
version: "1.0", | ||
idKey: 'id', | ||
version: '1.0', | ||
onlyIdentifier: false, | ||
@@ -349,0 +354,0 @@ nullData: false, |
@@ -1,21 +0,21 @@ | ||
export { default as Cache } from "./classes/cache"; | ||
export { default as Linker } from "./classes/linker"; | ||
export { default as Metaizer } from "./classes/metaizer"; | ||
export { default as Paginator } from "./classes/paginator"; | ||
export { default as Relator } from "./classes/relator"; | ||
export { default as JapiError } from "./models/error.model"; | ||
export { default as ErrorSerializer } from "./classes/error-serializer"; | ||
export { default as Serializer } from "./classes/serializer"; | ||
export * from "./interfaces/cache.interface"; | ||
export * from "./interfaces/error-serializer.interface"; | ||
export * from "./interfaces/error.interface"; | ||
export * from "./interfaces/json-api.interface"; | ||
export * from "./interfaces/linker.interface"; | ||
export * from "./interfaces/paginator.interface"; | ||
export * from "./interfaces/relator.interface"; | ||
export * from "./interfaces/serializer.interface"; | ||
export * from "./types/global.types"; | ||
export * from "./utils/is-error-document"; | ||
export * from "./utils/is-plain-object"; | ||
export * from "./utils/is-object"; | ||
export { default as Cache } from './classes/cache'; | ||
export { default as Linker } from './classes/linker'; | ||
export { default as Metaizer } from './classes/metaizer'; | ||
export { default as Paginator } from './classes/paginator'; | ||
export { default as Relator } from './classes/relator'; | ||
export { default as JapiError } from './models/error.model'; | ||
export { default as ErrorSerializer } from './classes/error-serializer'; | ||
export { default as Serializer } from './classes/serializer'; | ||
export * from './interfaces/cache.interface'; | ||
export * from './interfaces/error-serializer.interface'; | ||
export * from './interfaces/error.interface'; | ||
export * from './interfaces/json-api.interface'; | ||
export * from './interfaces/linker.interface'; | ||
export * from './interfaces/paginator.interface'; | ||
export * from './interfaces/relator.interface'; | ||
export * from './interfaces/serializer.interface'; | ||
export * from './types/global.types'; | ||
export * from './utils/is-error-document'; | ||
export * from './utils/is-plain-object'; | ||
export * from './utils/is-object'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import { SingleOrArray, nullish } from "../types/global.types"; | ||
import { SingleOrArray, nullish } from '../types/global.types'; | ||
export interface CacheOptions<DataType> { | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,5 +0,5 @@ | ||
import Linker from "../classes/linker"; | ||
import Metaizer from "../classes/metaizer"; | ||
import JapiError from "../models/error.model"; | ||
import { Dictionary } from "../types/global.types"; | ||
import Linker from '../classes/linker'; | ||
import Metaizer from '../classes/metaizer'; | ||
import JapiError from '../models/error.model'; | ||
import { Dictionary } from '../types/global.types'; | ||
export interface ErrorAttributeOption<T> { | ||
@@ -6,0 +6,0 @@ /** |
@@ -1,8 +0,8 @@ | ||
import JapiError from "../models/error.model"; | ||
import Link from "../models/link.model"; | ||
import Meta from "../models/meta.model"; | ||
import ResourceIdentifier from "../models/resource-identifier.model"; | ||
import Resource from "../models/resource.model"; | ||
import { Dictionary, SingleOrArray, nullish } from "../types/global.types"; | ||
import { PaginationOf } from "./paginator.interface"; | ||
import JapiError from '../models/error.model'; | ||
import Link from '../models/link.model'; | ||
import Meta from '../models/meta.model'; | ||
import ResourceIdentifier from '../models/resource-identifier.model'; | ||
import Resource from '../models/resource.model'; | ||
import { Dictionary, SingleOrArray, nullish } from '../types/global.types'; | ||
import { PaginationOf } from './paginator.interface'; | ||
export interface DataDocument<PrimaryType extends Dictionary<any>> extends Partial<MetaDocument> { | ||
@@ -9,0 +9,0 @@ links?: Dictionary<Link | nullish> | PaginationOf<Link>; |
@@ -1,2 +0,2 @@ | ||
import Metaizer from "../classes/metaizer"; | ||
import Metaizer from '../classes/metaizer'; | ||
export interface LinkerOptions<Dependencies extends any[]> { | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { nullish } from "../types/global.types"; | ||
import { nullish } from '../types/global.types'; | ||
export interface PaginationOf<T> { | ||
@@ -3,0 +3,0 @@ first: T | nullish; |
@@ -1,4 +0,4 @@ | ||
import Linker from "../classes/linker"; | ||
import Metaizer from "../classes/metaizer"; | ||
import { Dictionary, nullish, SingleOrArray } from "../types/global.types"; | ||
import Linker from '../classes/linker'; | ||
import Metaizer from '../classes/metaizer'; | ||
import { Dictionary, nullish, SingleOrArray } from '../types/global.types'; | ||
export interface RelatorOptions<PrimaryType, RelatedType extends Dictionary<any> = any> { | ||
@@ -5,0 +5,0 @@ /** |
@@ -1,7 +0,7 @@ | ||
import Linker from "../classes/linker"; | ||
import Metaizer from "../classes/metaizer"; | ||
import Paginator from "../classes/paginator"; | ||
import Relator from "../classes/relator"; | ||
import { Dictionary, SingleOrArray, nullish } from "../types/global.types"; | ||
import Cache from "../classes/cache"; | ||
import Linker from '../classes/linker'; | ||
import Metaizer from '../classes/metaizer'; | ||
import Paginator from '../classes/paginator'; | ||
import Relator from '../classes/relator'; | ||
import { Dictionary, SingleOrArray, nullish } from '../types/global.types'; | ||
import Cache from '../classes/cache'; | ||
export interface SerializerOptions<PrimaryType extends Dictionary<any> = any> { | ||
@@ -8,0 +8,0 @@ /** |
@@ -1,5 +0,5 @@ | ||
import { Dictionary, nullish } from ".."; | ||
import { ErrorOptions } from "../interfaces/error.interface"; | ||
import Link from "./link.model"; | ||
import Meta from "./meta.model"; | ||
import { Dictionary, nullish } from '..'; | ||
import { ErrorOptions } from '../interfaces/error.interface'; | ||
import Link from './link.model'; | ||
import Meta from './meta.model'; | ||
export default class JapiError { | ||
@@ -6,0 +6,0 @@ /** |
@@ -29,6 +29,6 @@ "use strict"; | ||
return false; | ||
return (["id", "status", "code", "title", "detail", "source", "links", "meta"].some(function (attrName) { return attrName in error; }) && | ||
return (['id', 'status', 'code', 'title', 'detail', 'source', 'links', 'meta'].some(function (attrName) { return attrName in error; }) && | ||
[ | ||
["id", "status", "code", "title", "detail"].every(function (attrName) { return !(attrName in error) || typeof error[attrName] === "string"; }), | ||
["source", "links", "meta"].every(function (attrName) { return !(attrName in error) || is_object_1.isObject(error[attrName]); }), | ||
['id', 'status', 'code', 'title', 'detail'].every(function (attrName) { return !(attrName in error) || typeof error[attrName] === 'string'; }), | ||
['source', 'links', 'meta'].every(function (attrName) { return !(attrName in error) || is_object_1.isObject(error[attrName]); }), | ||
].every(function (v) { return v; })); | ||
@@ -35,0 +35,0 @@ }; |
/// <reference types="node" /> | ||
import { URL } from "url"; | ||
import Meta from "./meta.model"; | ||
import { URL } from 'url'; | ||
import Meta from './meta.model'; | ||
export default class Link { | ||
@@ -5,0 +5,0 @@ url: URL; |
@@ -1,5 +0,5 @@ | ||
import { Dictionary, nullish } from ".."; | ||
import { ResourceLinkage } from "../interfaces/json-api.interface"; | ||
import Link from "./link.model"; | ||
import Meta from "./meta.model"; | ||
import { Dictionary, nullish } from '..'; | ||
import { ResourceLinkage } from '../interfaces/json-api.interface'; | ||
import Link from './link.model'; | ||
import Meta from './meta.model'; | ||
/** @internal */ | ||
@@ -6,0 +6,0 @@ export interface RelationshipOptions { |
@@ -6,3 +6,3 @@ "use strict"; | ||
// data can be explicitly set to null for empty to-one relationships | ||
if (typeof options.data !== "undefined") | ||
if (typeof options.data !== 'undefined') | ||
this.data = options.data; | ||
@@ -13,4 +13,4 @@ if (options.links) | ||
this.meta = options.meta; | ||
if (typeof options.data === "undefined" && !this.links && !this.meta) { | ||
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."); | ||
if (typeof options.data === 'undefined' && !this.links && !this.meta) { | ||
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.'); | ||
} | ||
@@ -17,0 +17,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Meta from "./meta.model"; | ||
import Meta from './meta.model'; | ||
/** @internal */ | ||
@@ -3,0 +3,0 @@ export interface ResourceIdentifierOptions { |
@@ -1,5 +0,5 @@ | ||
import Link from "../models/link.model"; | ||
import { Dictionary, nullish } from "../types/global.types"; | ||
import Relationship from "./relationship.model"; | ||
import ResourceIdentifier, { ResourceIdentifierOptions } from "./resource-identifier.model"; | ||
import Link from '../models/link.model'; | ||
import { Dictionary, nullish } from '../types/global.types'; | ||
import Relationship from './relationship.model'; | ||
import ResourceIdentifier, { ResourceIdentifierOptions } from './resource-identifier.model'; | ||
/** @internal */ | ||
@@ -6,0 +6,0 @@ export interface ResourceOptions<T> extends ResourceIdentifierOptions { |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -12,0 +14,0 @@ function __() { this.constructor = d; } |
@@ -1,2 +0,2 @@ | ||
import { ErrorDocument } from "../interfaces/json-api.interface"; | ||
import { ErrorDocument } from '../interfaces/json-api.interface'; | ||
/** | ||
@@ -3,0 +3,0 @@ * Detects an `ErrorDocument` like object |
@@ -17,3 +17,3 @@ "use strict"; | ||
Array.isArray(document.errors) && | ||
("jsonapi" in document || | ||
('jsonapi' in document || | ||
document.errors.every(function (error) { | ||
@@ -20,0 +20,0 @@ return error instanceof error_model_1["default"] ? true : error_model_1["default"].isLikeJapiError(error); |
@@ -5,5 +5,5 @@ "use strict"; | ||
function isObject(o) { | ||
return typeof o === "object" && Object.prototype.toString.call(o) === "[object Object]"; | ||
return typeof o === 'object' && Object.prototype.toString.call(o) === '[object Object]'; | ||
} | ||
exports.isObject = isObject; | ||
//# sourceMappingURL=is-object.js.map |
@@ -9,3 +9,3 @@ "use strict"; | ||
// If constructor was modified | ||
if (typeof o.constructor !== "function") | ||
if (typeof o.constructor !== 'function') | ||
return false; | ||
@@ -16,3 +16,3 @@ // If prototype was modified | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (!o.constructor.prototype.hasOwnProperty("isPrototypeOf")) | ||
if (!o.constructor.prototype.hasOwnProperty('isPrototypeOf')) | ||
return false; | ||
@@ -19,0 +19,0 @@ return true; |
@@ -1,2 +0,2 @@ | ||
import { Dictionary, UnionToIntersection } from "../types/global.types"; | ||
import { Dictionary, UnionToIntersection } from '../types/global.types'; | ||
/** | ||
@@ -3,0 +3,0 @@ * Deep merge two objects over their enumerable properties. |
@@ -29,5 +29,6 @@ "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 __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
@@ -73,5 +74,5 @@ exports.__esModule = true; | ||
} | ||
return merge.apply(void 0, __spread([target], sources)); | ||
return merge.apply(void 0, __spreadArray([target], __read(sources))); | ||
} | ||
exports["default"] = merge; | ||
//# sourceMappingURL=merge.js.map |
@@ -1,5 +0,6 @@ | ||
import Relator from "../classes/relator"; | ||
import { SerializerOptions } from "../interfaces/serializer.interface"; | ||
export declare function recurseRelators(data: any[], relators: Record<string, Relator<any>>, depth: number, keys: string[]): Promise<any[]>; | ||
export declare function normalizeRelators<T>(relators: SerializerOptions<T>["relators"]): Record<string, Relator<T, any>> | undefined; | ||
import Relator from '../classes/relator'; | ||
import { SerializerOptions } from '../interfaces/serializer.interface'; | ||
import { Dictionary } from '../types/global.types'; | ||
export declare function recurseRelators(data: any[], relators: Record<string, Relator<any>>, depth: number, keys: string[], relatorDataCache?: Map<Relator<any>, Dictionary<any>[]>): Promise<any[]>; | ||
export declare function normalizeRelators<T>(relators: SerializerOptions<T>['relators']): Record<string, Relator<T, any>> | undefined; | ||
export declare class Helpers<PrimaryType> { | ||
@@ -6,0 +7,0 @@ projectAttributes: (data: PrimaryType) => Partial<PrimaryType> | undefined; |
@@ -38,2 +38,13 @@ "use strict"; | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
@@ -55,12 +66,6 @@ var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from) { | ||
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) | ||
to[j] = from[i]; | ||
return to; | ||
}; | ||
@@ -73,69 +78,99 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||
var relator_1 = __importDefault(require("../classes/relator")); | ||
function recurseRelators(data, relators, depth, keys) { | ||
function recurseRelators(data, relators, depth, keys, relatorDataCache) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var included, queue, _a, data_1, relators_1, _loop_1, i, len; | ||
var _this = this; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
var included, curRelatorDataCache, _a, _b, _i, name_1, cache, data_1, data_1_1, datum, relatedData, e_1_1, newRelatorDataCache, curRelatorDataCache_1, curRelatorDataCache_1_1, _c, relator, cache, i, resource, key, e_2_1; | ||
var e_1, _d, e_2, _e; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
included = []; | ||
queue = [[data, Object.values(relators)]]; | ||
console.log(data); | ||
_b.label = 1; | ||
curRelatorDataCache = relatorDataCache || new Map(); | ||
if (!(!relatorDataCache && depth > 0)) return [3 /*break*/, 10]; | ||
_a = []; | ||
for (_b in relators) | ||
_a.push(_b); | ||
_i = 0; | ||
_f.label = 1; | ||
case 1: | ||
if (!(queue.length > 0 && depth-- > 0)) return [3 /*break*/, 6]; | ||
_a = __read(queue.shift(), 2), data_1 = _a[0], relators_1 = _a[1]; | ||
_loop_1 = function (i, len) { | ||
var relator, relatedData, newRelators, newData; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
relator = relators_1[i]; | ||
return [4 /*yield*/, Promise.all(data_1.map(relator.getRelatedData))]; | ||
case 1: | ||
relatedData = _a.sent(); | ||
newRelators = relator.getRelatedRelators(); | ||
newData = []; | ||
return [4 /*yield*/, Promise.all(relatedData | ||
.flat() | ||
.filter(function (d) { return d !== null; }) | ||
.map(function (datum) { return __awaiter(_this, void 0, void 0, function () { | ||
var resource, key; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, relator.getRelatedResource(datum)]; | ||
case 1: | ||
resource = _a.sent(); | ||
key = resource.getKey(); | ||
if (!keys.includes(key)) { | ||
keys.push(key); | ||
included.push(resource); | ||
newData.push(datum); | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }))]; | ||
case 2: | ||
_a.sent(); | ||
if (newData.length > 0 && newRelators) { | ||
queue.push([newData, Object.values(newRelators)]); | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}; | ||
i = 0, len = relators_1.length; | ||
_b.label = 2; | ||
if (!(_i < _a.length)) return [3 /*break*/, 10]; | ||
name_1 = _a[_i]; | ||
cache = curRelatorDataCache.get(relators[name_1]) || []; | ||
curRelatorDataCache.set(relators[name_1], cache); | ||
_f.label = 2; | ||
case 2: | ||
if (!(i < len)) return [3 /*break*/, 5]; | ||
return [5 /*yield**/, _loop_1(i, len)]; | ||
_f.trys.push([2, 7, 8, 9]); | ||
data_1 = (e_1 = void 0, __values(data)), data_1_1 = data_1.next(); | ||
_f.label = 3; | ||
case 3: | ||
_b.sent(); | ||
_b.label = 4; | ||
if (!!data_1_1.done) return [3 /*break*/, 6]; | ||
datum = data_1_1.value; | ||
return [4 /*yield*/, relators[name_1].getRelatedData(datum)]; | ||
case 4: | ||
relatedData = _f.sent(); | ||
if (relatedData !== null) { | ||
cache.push.apply(cache, __spreadArray([], __read((Array.isArray(relatedData) ? relatedData : [relatedData])))); | ||
} | ||
_f.label = 5; | ||
case 5: | ||
data_1_1 = data_1.next(); | ||
return [3 /*break*/, 3]; | ||
case 6: return [3 /*break*/, 9]; | ||
case 7: | ||
e_1_1 = _f.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
try { | ||
if (data_1_1 && !data_1_1.done && (_d = data_1["return"])) _d.call(data_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
return [7 /*endfinally*/]; | ||
case 9: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 10: | ||
if (!(depth-- > 0 && curRelatorDataCache.size > 0)) return [3 /*break*/, 21]; | ||
newRelatorDataCache = new Map(); | ||
_f.label = 11; | ||
case 11: | ||
_f.trys.push([11, 18, 19, 20]); | ||
curRelatorDataCache_1 = (e_2 = void 0, __values(curRelatorDataCache)), curRelatorDataCache_1_1 = curRelatorDataCache_1.next(); | ||
_f.label = 12; | ||
case 12: | ||
if (!!curRelatorDataCache_1_1.done) return [3 /*break*/, 17]; | ||
_c = __read(curRelatorDataCache_1_1.value, 2), relator = _c[0], cache = _c[1]; | ||
i = 0; | ||
_f.label = 13; | ||
case 13: | ||
if (!(i < cache.length)) return [3 /*break*/, 16]; | ||
return [4 /*yield*/, relator.getRelatedResource(cache[i], undefined, undefined, newRelatorDataCache)]; | ||
case 14: | ||
resource = _f.sent(); | ||
key = resource.getKey(); | ||
if (!keys.includes(key)) { | ||
keys.push(key); | ||
included.push(resource); | ||
} | ||
_f.label = 15; | ||
case 15: | ||
i++; | ||
return [3 /*break*/, 2]; | ||
case 5: return [3 /*break*/, 1]; | ||
case 6: return [2 /*return*/, included]; | ||
return [3 /*break*/, 13]; | ||
case 16: | ||
curRelatorDataCache_1_1 = curRelatorDataCache_1.next(); | ||
return [3 /*break*/, 12]; | ||
case 17: return [3 /*break*/, 20]; | ||
case 18: | ||
e_2_1 = _f.sent(); | ||
e_2 = { error: e_2_1 }; | ||
return [3 /*break*/, 20]; | ||
case 19: | ||
try { | ||
if (curRelatorDataCache_1_1 && !curRelatorDataCache_1_1.done && (_e = curRelatorDataCache_1["return"])) _e.call(curRelatorDataCache_1); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
return [7 /*endfinally*/]; | ||
case 20: | ||
curRelatorDataCache = newRelatorDataCache; | ||
return [3 /*break*/, 10]; | ||
case 21: return [2 /*return*/, included]; | ||
} | ||
@@ -147,3 +182,3 @@ }); | ||
function normalizeRelators(relators) { | ||
var e_1, _a; | ||
var e_3, _a; | ||
var normalizedRelators = {}; | ||
@@ -157,13 +192,13 @@ if (relators) { | ||
try { | ||
for (var relators_2 = __values(relators), relators_2_1 = relators_2.next(); !relators_2_1.done; relators_2_1 = relators_2.next()) { | ||
var relator = relators_2_1.value; | ||
for (var relators_1 = __values(relators), relators_1_1 = relators_1.next(); !relators_1_1.done; relators_1_1 = relators_1.next()) { | ||
var relator = relators_1_1.value; | ||
normalizedRelators[relator.relatedName] = relator; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (relators_2_1 && !relators_2_1.done && (_a = relators_2["return"])) _a.call(relators_2); | ||
if (relators_1_1 && !relators_1_1.done && (_a = relators_1["return"])) _a.call(relators_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
@@ -170,0 +205,0 @@ return normalizedRelators; |
{ | ||
"name": "ts-japi", | ||
"version": "1.5.1", | ||
"version": "1.6.0", | ||
"description": "A highly-modular (typescript-friendly)-framework agnostic library for serializing data to the JSON:API specification", | ||
@@ -10,15 +10,5 @@ "main": "lib/index.js", | ||
"playground": "ts-node ./benchmarks/playground.benchmark", | ||
"build-docs": "npm run clean-docs && typedoc && rsync -a ./src/docs/assets ./docs", | ||
"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", | ||
"clean-docs": "rm -f -r ./docs", | ||
"clean-readme": "rm -f ./README.md", | ||
"clean-lib": "rm -f -r ./lib", | ||
"clean-test": "rm -f -r ./coverage", | ||
"docs": "npm run build-docs && npm run build-readme", | ||
"all": "npm run setup && npm run build && npm run test && npm run docs", | ||
"setup": "npm i -g npm && npm install && npm audit fix", | ||
"build": "npm run clean-lib && tsc", | ||
"test": " npm run clean-test && jest --runInBand --verbose --coverage", | ||
"snyk-protect": "snyk protect", | ||
"prepare": "npm run snyk-protect" | ||
"clean": "make clean", | ||
"build": "make -j3", | ||
"test": " jest --runInBand --verbose --coverage" | ||
}, | ||
@@ -29,3 +19,3 @@ "publishConfig": { | ||
}, | ||
"author": "mu.io <dev@mathematic.io>", | ||
"author": "jun-sheaf <rjung@mathematic.io>", | ||
"license": "MIT", | ||
@@ -50,9 +40,9 @@ "keywords": [ | ||
"devDependencies": { | ||
"@babel/cli": "^7.12.17", | ||
"@babel/core": "^7.12.17", | ||
"@babel/plugin-proposal-class-properties": "^7.12.13", | ||
"@babel/cli": "^7.13.0", | ||
"@babel/core": "^7.13.8", | ||
"@babel/plugin-proposal-class-properties": "^7.13.0", | ||
"@babel/plugin-proposal-export-namespace-from": "^7.12.13", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.12.13", | ||
"@babel/preset-env": "^7.12.17", | ||
"@babel/preset-typescript": "^7.12.17", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.13.8", | ||
"@babel/preset-env": "^7.13.9", | ||
"@babel/preset-typescript": "^7.13.0", | ||
"@changesets/cli": "^2.14.1", | ||
@@ -63,29 +53,20 @@ "@types/benchmark": "^2.1.0", | ||
"@types/uuid": "^8.3.0", | ||
"@typescript-eslint/eslint-plugin": "^4.15.1", | ||
"@typescript-eslint/parser": "^4.15.1", | ||
"@typescript-eslint/eslint-plugin": "^4.16.1", | ||
"@typescript-eslint/parser": "^4.16.1", | ||
"babel-jest": "^26.6.3", | ||
"benchmark": "^2.1.4", | ||
"core-js": "^3.9.0", | ||
"eslint": "^7.20.0", | ||
"eslint-config-prettier": "^7.2.0", | ||
"core-js": "^3.9.1", | ||
"eslint": "^7.21.0", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-plugin-prettier": "^3.3.1", | ||
"jest": "^26.6.3", | ||
"lodash": "^4.17.20", | ||
"lodash": "^4.17.21", | ||
"prettier": "^2.2.1", | ||
"regenerator-runtime": "^0.13.7", | ||
"snyk": "^1.458.0", | ||
"ts-node": "^9.1.1", | ||
"typedoc": "^0.20.25", | ||
"typedoc-plugin-markdown": "^3.5.0", | ||
"typescript": "^4.1.5", | ||
"typedoc": "^0.20.29", | ||
"typedoc-plugin-markdown": "^3.6.0", | ||
"typescript": "^4.2.3", | ||
"uuid": "^8.3.2" | ||
}, | ||
"snyk": true, | ||
"prettier": { | ||
"tabWidth": 1, | ||
"printWidth": 100, | ||
"parser": "typescript", | ||
"semi": true, | ||
"quoteProps": "consistent" | ||
}, | ||
"babel": { | ||
@@ -92,0 +73,0 @@ "presets": [ |
188
README.md
@@ -0,1 +1,3 @@ | ||
ts-japi / [Exports](modules.html) | ||
<br /> | ||
@@ -5,3 +7,2 @@ <img src="https://raw.githubusercontent.com/mu-io/ts-japi/master/docs/assets/images/logo.svg" alt="{ts:japi}" width="350"/> | ||
[![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/mu-io/ts-japi)](https://snyk.io/test/github/mu-io/ts-japi) | ||
![node-current](https://img.shields.io/node/v/ts-japi) | ||
@@ -27,2 +28,3 @@ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) | ||
- [FAQ](#faq) | ||
- [For Developers](#for-developers) | ||
- [Contributing](#contributing) | ||
@@ -33,3 +35,3 @@ - [License](#license) | ||
- This is the **only** typescript-compatible library that fully types the JSON:API specification and performs *proper* serialization. | ||
- This is the **only** typescript-compatible library that fully types the JSON:API specification and performs *proper* serialization. | ||
- [**Zero dependencies**](#zdg). | ||
@@ -79,25 +81,25 @@ - This is the **only** library with [resource recursion](#wirr). | ||
```typescript | ||
import { Serializer } from "../src"; | ||
import { User } from "../test/models"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { Serializer } from '../src'; | ||
import { User } from '../test/models'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
const UserSerializer = new Serializer("users"); | ||
const UserSerializer = new Serializer('users'); | ||
(async () => { | ||
const user = new User("sample_user_id"); | ||
console.log("Output:", getJSON(await UserSerializer.serialize(user))); | ||
const user = new User('sample_user_id'); | ||
// Output: { | ||
// jsonapi: { version: '1.0' }, | ||
// data: { | ||
// type: 'users', | ||
// id: 'sample_user_id', | ||
// attributes: { | ||
// createdAt: '2020-05-20T15:44:37.650Z', | ||
// articles: [], | ||
// comments: [] | ||
// } | ||
// } | ||
// } | ||
console.log('Output:', getJSON(await UserSerializer.serialize(user))); | ||
// Output: { | ||
// jsonapi: { version: '1.0' }, | ||
// data: { | ||
// type: 'users', | ||
// id: 'sample_user_id', | ||
// attributes: { | ||
// createdAt: '2020-05-20T15:44:37.650Z', | ||
// articles: [], | ||
// comments: [] | ||
// } | ||
// } | ||
// } | ||
})(); | ||
@@ -114,5 +116,5 @@ | ||
```typescript | ||
import { Linker } from "../src"; | ||
import { User, Article } from "../test/models"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { Linker } from '../src'; | ||
import { User, Article } from '../test/models'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
@@ -122,5 +124,5 @@ // The last argument should almost always be an array or a single object type. | ||
const UserArticleLinker = new Linker((user: User, articles: Article | Article[]) => { | ||
return Array.isArray(articles) | ||
? `https://www.example.com/users/${user.id}/articles/` | ||
: `https://www.example.com/users/${user.id}/articles/${articles.id}`; | ||
return Array.isArray(articles) | ||
? `https://www.example.com/users/${user.id}/articles/` | ||
: `https://www.example.com/users/${user.id}/articles/${articles.id}`; | ||
}); | ||
@@ -130,8 +132,8 @@ | ||
(async () => { | ||
const user = new User("sample_user_id"); | ||
const article = new Article("same_article_id", user); | ||
const user = new User('sample_user_id'); | ||
const article = new Article('same_article_id', user); | ||
console.log("Output:", getJSON(UserArticleLinker.link(user, article))); | ||
console.log('Output:', getJSON(UserArticleLinker.link(user, article))); | ||
// Output: https://www.example.com/users/sample_user_id/articles/same_article_id | ||
// Output: https://www.example.com/users/sample_user_id/articles/same_article_id | ||
})(); | ||
@@ -148,18 +150,18 @@ | ||
```typescript | ||
import { Paginator } from "../src"; | ||
import { User, Article } from "../test/models"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { Paginator } from '../src'; | ||
import { User, Article } from '../test/models'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
const ArticlePaginator = new Paginator((articles: Article | Article[]) => { | ||
if (Array.isArray(articles)) { | ||
const nextPage = Number(articles[0].id) + 1; | ||
const prevPage = Number(articles[articles.length - 1].id) - 1; | ||
return { | ||
first: `https://www.example.com/articles/0`, | ||
last: `https://www.example.com/articles/10`, | ||
next: nextPage <= 10 ? `https://www.example.com/articles/${nextPage}` : null, | ||
prev: prevPage >= 0 ? `https://www.example.com/articles/${prevPage}` : null, | ||
}; | ||
} | ||
return; | ||
if (Array.isArray(articles)) { | ||
const nextPage = Number(articles[0].id) + 1; | ||
const prevPage = Number(articles[articles.length - 1].id) - 1; | ||
return { | ||
first: `https://www.example.com/articles/0`, | ||
last: `https://www.example.com/articles/10`, | ||
next: nextPage <= 10 ? `https://www.example.com/articles/${nextPage}` : null, | ||
prev: prevPage >= 0 ? `https://www.example.com/articles/${prevPage}` : null, | ||
}; | ||
} | ||
return; | ||
}); | ||
@@ -169,13 +171,13 @@ | ||
(async () => { | ||
const user = new User("sample_user_id"); | ||
const article = new Article("same_article_id", user); | ||
const user = new User('sample_user_id'); | ||
const article = new Article('same_article_id', user); | ||
console.log("Output:", getJSON(ArticlePaginator.paginate([article]))); | ||
console.log('Output:', getJSON(ArticlePaginator.paginate([article]))); | ||
// Output: { | ||
// first: 'https://www.example.com/articles/0', | ||
// last: 'https://www.example.com/articles/10', | ||
// prev: null, | ||
// next: null | ||
// } | ||
// Output: { | ||
// first: 'https://www.example.com/articles/0', | ||
// last: 'https://www.example.com/articles/10', | ||
// prev: null, | ||
// next: null | ||
// } | ||
})(); | ||
@@ -194,10 +196,10 @@ | ||
```typescript | ||
import { Serializer, Relator } from "../src"; | ||
import { User, Article } from "../test/models"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { Serializer, Relator } from '../src'; | ||
import { User, Article } from '../test/models'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
const ArticleSerializer = new Serializer<Article>("articles"); | ||
const ArticleSerializer = new Serializer<Article>('articles'); | ||
const UserArticleRelator = new Relator<User, Article>( | ||
async (user) => user.getArticles(), | ||
ArticleSerializer | ||
async (user) => user.getArticles(), | ||
ArticleSerializer | ||
); | ||
@@ -207,10 +209,10 @@ | ||
(async () => { | ||
const user = new User("sample_user_id"); | ||
const article = new Article("same_article_id", user); | ||
User.save(user); | ||
Article.save(article); | ||
const user = new User('sample_user_id'); | ||
const article = new Article('same_article_id', user); | ||
User.save(user); | ||
Article.save(article); | ||
console.log("Output:", getJSON(await UserArticleRelator.getRelationship(user))); | ||
console.log('Output:', getJSON(await UserArticleRelator.getRelationship(user))); | ||
// Output: { data: [ { type: 'articles', id: 'same_article_id' } ] } | ||
// Output: { data: [ { type: 'articles', id: 'same_article_id' } ] } | ||
})(); | ||
@@ -225,5 +227,5 @@ | ||
- [`ErrorSerializerOptions.metaizers`](https://mu-io.github.io/ts-japi/interfaces/errorserializeroptions.html#metaizers) | ||
- [`RelatorOptions.metaizer`](https://mu-io.github.io/ts-japi/interfaces/relatoroptions.html#optional-metaizer) | ||
- [`RelatorOptions.metaizer`](https://mu-io.github.io/ts-japi/interfaces/relatoroptions.html#metaizer) | ||
- [`SerializerOptions.metaizers`](https://mu-io.github.io/ts-japi/interfaces/serializeroptions.html#metaizers) | ||
- [`LinkerOptions.metaizer`](https://mu-io.github.io/ts-japi/interfaces/linkeroptions.html#optional-metaizer) | ||
- [`LinkerOptions.metaizer`](https://mu-io.github.io/ts-japi/interfaces/linkeroptions.html#metaizer) | ||
@@ -235,5 +237,5 @@ Like [`Linker`](https://mu-io.github.io/ts-japi/classes/linker.html), its methods are not meant to be called. | ||
```typescript | ||
import { User, Article } from "../test/models"; | ||
import { Metaizer } from "../src"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { User, Article } from '../test/models'; | ||
import { Metaizer } from '../src'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
@@ -243,5 +245,5 @@ // The last argument should almost always be an array or a single object type. | ||
const UserArticleMetaizer = new Metaizer((user: User, articles: Article | Article[]) => { | ||
return Array.isArray(articles) | ||
? { user_created: user.createdAt, article_created: articles.map((a) => a.createdAt) } | ||
: { user_created: user.createdAt, article_created: articles.createdAt }; | ||
return Array.isArray(articles) | ||
? { user_created: user.createdAt, article_created: articles.map((a) => a.createdAt) } | ||
: { user_created: user.createdAt, article_created: articles.createdAt }; | ||
}); | ||
@@ -251,11 +253,11 @@ | ||
(async () => { | ||
const user = new User("sample_user_id"); | ||
const article = new Article("same_article_id", user); | ||
const user = new User('sample_user_id'); | ||
const article = new Article('same_article_id', user); | ||
console.log("Output:", getJSON(UserArticleMetaizer.metaize(user, article))); | ||
console.log('Output:', getJSON(UserArticleMetaizer.metaize(user, article))); | ||
// Output: { | ||
// user_created: '2020-05-20T15:39:43.277Z', | ||
// article_created: '2020-05-20T15:39:43.277Z' | ||
// } | ||
// Output: { | ||
// user_created: '2020-05-20T15:39:43.277Z', | ||
// article_created: '2020-05-20T15:39:43.277Z' | ||
// } | ||
})(); | ||
@@ -274,4 +276,4 @@ | ||
```typescript | ||
import { ErrorSerializer } from "../src"; | ||
import { getJSON } from "../test/utils/get-json"; | ||
import { ErrorSerializer } from '../src'; | ||
import { getJSON } from '../test/utils/get-json'; | ||
@@ -281,10 +283,10 @@ const PrimitiveErrorSerializer = new ErrorSerializer(); | ||
(async () => { | ||
const error = new Error("badness"); | ||
const error = new Error('badness'); | ||
console.log("Output:", getJSON(PrimitiveErrorSerializer.serialize(error))); | ||
console.log('Output:', getJSON(PrimitiveErrorSerializer.serialize(error))); | ||
// Output: { | ||
// errors: [ { code: 'Error', detail: 'badness' } ], | ||
// jsonapi: { version: '1.0' } | ||
// } | ||
// Output: { | ||
// errors: [ { code: 'Error', detail: 'badness' } ], | ||
// jsonapi: { version: '1.0' } | ||
// } | ||
})(); | ||
@@ -302,3 +304,3 @@ | ||
We stress the following: There are many clients readily built to consume JSON:API endpoints (see [here](https://jsonapi.org/implementations/)). It is **highly recommended** to use them and only use this for serialization. | ||
We stress the following: Given that there are many clients readily built to consume JSON:API endpoints (see [here](https://jsonapi.org/implementations/)), we do not provide deserialization. In particular, since unmarshalling data is strongly related to the code it will be used in (e.g. React), tighter integration is recommended over an unnecessary abstraction. | ||
@@ -321,4 +323,8 @@ ## Remarks | ||
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://mu-io.github.io/ts-japi/interfaces/serializeroptions.html#depth) and [this example](https://github.com/mu-io/ts-japi/blob/master/examples/resource-recursion.example.ts)) | ||
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 primary data relations. This is should be done with caution (see [`SerializerOptions.depth`](https://mu-io.github.io/ts-japi/interfaces/serializeroptions.html#depth) and [this example](https://github.com/mu-io/ts-japi/blob/master/examples/resource-recursion.example.ts)) | ||
## For Developers | ||
To get started in developing this library, run `yarn install`, `yarn build` and `yarn test` (in this precise order) to assure everything is in working order. | ||
## Contributing | ||
@@ -325,0 +331,0 @@ |
@@ -68,5 +68,4 @@ { | ||
"typedocOptions": { | ||
"mode": "library", | ||
"out": "docs", | ||
"inputFiles": [ | ||
"entryPoints": [ | ||
"./src/index.ts" | ||
@@ -77,8 +76,5 @@ ], | ||
], | ||
"gaID": "UA-99757611-3", | ||
"plugin": "none", | ||
"theme": "../typedoc-classic-theme/bin/default", | ||
"exclude": "**/*+(.spec|.e2e|.test).ts", | ||
"readme": "src/docs/README.md", | ||
"stripInternal": true, | ||
"categorizeByGroup": true, | ||
@@ -85,0 +81,0 @@ "gitRevision": "master" |
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
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
198213
29
128
2513
324