@guildadev/jsonapi-to-model
Advanced tools
Comparing version
72
index.js
@@ -6,2 +6,4 @@ // packages/jsonapi-to-model/src/symbols.ts | ||
var INCLUDED_METADATA_KEY = Symbol.for("includeds"); | ||
var LINKS_METADATA_KEY = Symbol.for("Links"); | ||
var INCLUDED_LINKS_METADATA_KEY = Symbol.for("IncludedLinks"); | ||
@@ -56,2 +58,17 @@ // packages/jsonapi-to-model/src/decorators/Attributes.ts | ||
// packages/jsonapi-to-model/src/decorators/Linked.ts | ||
function Links(metaKey) { | ||
return function(target, mapperKey) { | ||
const originaKey = metaKey || mapperKey; | ||
if (!target.hasOwnProperty(kClassMapping)) { | ||
target[kClassMapping] = []; | ||
} | ||
target[kClassMapping].push({ | ||
originaKey, | ||
mapperKey, | ||
kind: LINKS_METADATA_KEY | ||
}); | ||
}; | ||
} | ||
// packages/jsonapi-to-model/src/index.ts | ||
@@ -64,6 +81,6 @@ var BaseEntity = class { | ||
properties.forEach( | ||
({ originaKey, mapperKey, kind }) => { | ||
({ originaKey, mapperKey, kind, includedAssociation }) => { | ||
Object.defineProperty(this, mapperKey, { | ||
get: () => { | ||
return this.getDataByKind(kind, originaKey); | ||
return this.getDataByKind(kind, originaKey, includedAssociation); | ||
}, | ||
@@ -76,3 +93,12 @@ configurable: true, | ||
} | ||
getDataByKind(kind, objectKey) { | ||
// ============ | ||
// protected API | ||
// ============ | ||
get isCollection() { | ||
return Array.isArray(this._rawPayload?.data); | ||
} | ||
// ============ | ||
// private API | ||
// ============ | ||
getDataByKind(kind, objectKey, includedAssociation) { | ||
switch (kind) { | ||
@@ -85,2 +111,9 @@ case ATTRIBUTE_METADATA_KEY: | ||
return this.getAssociationsIncluded(objectKey); | ||
case LINKS_METADATA_KEY: | ||
return this.getAssociationsLinked(objectKey); | ||
case INCLUDED_LINKS_METADATA_KEY: | ||
return this.getAssociationsIncludedLinked( | ||
includedAssociation || "", | ||
objectKey | ||
); | ||
default: | ||
@@ -118,8 +151,10 @@ return null; | ||
} | ||
getAssociationsIncludedLinked(includedAssociation, associationType) { | ||
return this.getAssociationsIncluded(includedAssociation, []).map( | ||
(item) => item.links?.[associationType] | ||
).at(0); | ||
} | ||
get isCollectionMember() { | ||
return Object(this._rawPayload || {}).hasOwnProperty("attributes"); | ||
} | ||
get isCollection() { | ||
return Array.isArray(this._rawPayload?.data); | ||
} | ||
constructorBuilder(collection_object) { | ||
@@ -132,2 +167,5 @@ const instance = new this.constructor( | ||
} | ||
// ============ | ||
// Public API | ||
// ============ | ||
get all() { | ||
@@ -152,2 +190,5 @@ if (this.isCollection) { | ||
} | ||
getAssociationsLinked(associationType) { | ||
return this._rawPayload.links?.[associationType]; | ||
} | ||
getAttribute(objectKey) { | ||
@@ -165,2 +206,20 @@ if (this.isCollectionMember) { | ||
} | ||
find_included_by(type) { | ||
if (!this.isCollectionMember) { | ||
return this.getAssociationsIncluded(type, []) ?? []; | ||
} | ||
let relation_type = ""; | ||
for (const key in this._rawPayload.relationships) { | ||
if (this._rawPayload.relationships[key].data.type === type) { | ||
relation_type = key; | ||
break; | ||
} | ||
} | ||
if (!relation_type) { | ||
return []; | ||
} | ||
const relationship_id = this._rawPayload.relationships[relation_type].data.id; | ||
const result = this.getAssociationsIncluded(relation_type, [relationship_id]) ?? []; | ||
return result; | ||
} | ||
}; | ||
@@ -172,3 +231,4 @@ export { | ||
Included, | ||
Links, | ||
Meta | ||
}; |
{ | ||
"name": "@guildadev/jsonapi-to-model", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"private": false, | ||
@@ -5,0 +5,0 @@ "dependencies": {}, |
@@ -9,12 +9,23 @@ # Introduction | ||
´´´bash | ||
```bash | ||
yarn add @guidadev/jsonapi-to-model | ||
´´´ | ||
``` | ||
or | ||
´´´bash | ||
```bash | ||
npm install @guidadev/jsonapi-to-model | ||
´´´ | ||
``` | ||
## Performance | ||
I created a benchmark to compare the performance of deserializing JSON:API data and directly accessing the included data. The results are as follows: | ||
| Benchmark Type | Total Items | Deserialization Time | Total Time | Get Photos in Included | Photos IDs | Included Length | | ||
|---------------------|-------------|----------------------|------------|------------------------|------------|-----------------| | ||
| Deserialize | 1000 | 70ms | 70ms | 0ms | 10877 | 1000 | | ||
| Model | 1000 | 0ms | 0ms | 1ms | 10877 | 1000 | | ||
Why is the model faster? Because we don't need to parse the entire JSON:API payload. We only need to allocate the object, which is faster than parsing the entire JSON:API payload. | ||
# Usage | ||
@@ -21,0 +32,0 @@ |
export declare class BaseEntity { | ||
private _rawPayload; | ||
constructor(payload: any); | ||
protected get isCollection(): boolean; | ||
private getDataByKind; | ||
private getAssociationsIncluded; | ||
private getAssociationsIncludedLinked; | ||
private get isCollectionMember(); | ||
protected get isCollection(): boolean; | ||
private constructorBuilder; | ||
@@ -12,4 +13,6 @@ get all(): this[]; | ||
get raw(): any; | ||
getAssociationsLinked(associationType: string): any; | ||
getAttribute(objectKey: string): any; | ||
getMetaAttribute(objectKey: string): any; | ||
find_included_by<T = any>(type: string): T[]; | ||
} | ||
@@ -20,1 +23,2 @@ export { Attribute } from "./decorators/Attributes"; | ||
export { ArrayMeta } from "./decorators/ArrayMetas"; | ||
export { Links } from "./decorators/Linked"; |
@@ -5,1 +5,3 @@ export declare const kClassMapping: unique symbol; | ||
export declare const INCLUDED_METADATA_KEY: unique symbol; | ||
export declare const LINKS_METADATA_KEY: unique symbol; | ||
export declare const INCLUDED_LINKS_METADATA_KEY: unique symbol; |
@@ -5,2 +5,3 @@ export type AttributeReflector = { | ||
kind: symbol; | ||
includedAssociation?: string; | ||
}; |
Sorry, the diff of this file is not supported yet
19237
35.22%12
9.09%506
33.51%114
10.68%