-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: serializers, serializers, oh my
- Loading branch information
1 parent
7c32b3a
commit c2bf559
Showing
10 changed files
with
117 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './utils'; | ||
export * from './serializeResourceObject'; | ||
export * from './serializeResourceRelationshipObject'; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { attributesSymbol, idSymbol, linksSymbol, metaSymbol, relationshipsSymbol, resourceSymbol } from "../decorators"; | ||
import { collect } from "./utils/collect"; | ||
import { getMetadataBySymbol } from "./utils/getMetadataBySymbol"; | ||
import { serializeResourceRelationshipObject } from "./serializeResourceRelationshipObject"; | ||
|
||
import type { JSONAPILinksObject, JSONAPIMetaObject, JSONAPIRelationshipObject, JSONAPIResourceObject, JSONObject } from "../types"; | ||
|
||
export const serializeResourceObject = <I extends object>(classInstance: I): JSONAPIResourceObject => { | ||
const relationshipTuples = getMetadataBySymbol<[keyof I, string][]>(classInstance, relationshipsSymbol); | ||
|
||
const relationships = relationshipTuples.reduce((acc, [key]) => { | ||
const related = classInstance[key] as object; | ||
|
||
acc[key] = Array.isArray(related) ? related.map(serializeResourceRelationshipObject) : serializeResourceRelationshipObject(related); | ||
|
||
return acc; | ||
}, {} as Record<keyof I, JSONAPIRelationshipObject | JSONAPIRelationshipObject[]>); | ||
|
||
return { | ||
type: getMetadataBySymbol<string>(classInstance, resourceSymbol), | ||
id: collect<string>(classInstance, idSymbol), | ||
attributes: collect<JSONObject>(classInstance, attributesSymbol), | ||
relationships, | ||
links: collect<JSONAPILinksObject>(classInstance, linksSymbol), | ||
meta: collect<JSONAPIMetaObject>(classInstance, metaSymbol), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { idSymbol, linksSymbol, metaSymbol, resourceSymbol } from "../decorators"; | ||
import { collect } from "./utils/collect"; | ||
import { getMetadataBySymbol } from "./utils/getMetadataBySymbol"; | ||
|
||
import type { JSONAPILinksObject, JSONAPIMetaObject, JSONAPIRelationshipObject } from "../types"; | ||
|
||
export const serializeResourceRelationshipObject = <I extends object>(classInstance: I): JSONAPIRelationshipObject => ({ | ||
data: { | ||
type: getMetadataBySymbol<string>(classInstance, resourceSymbol), | ||
id: collect<string>(classInstance, idSymbol), | ||
}, | ||
links: collect<JSONAPILinksObject>(classInstance, linksSymbol), | ||
meta: collect<JSONAPIMetaObject>(classInstance, metaSymbol), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
export const assertMetadataIsPresent = (candidate: unknown | unknown[]): true => { | ||
if (Symbol.metadata === undefined) { | ||
throw new Error( | ||
'Failed to assert the presence of metadata because the metadata symbol is undefined. You may need to import the `@tsmetadata/polyfill` package.', | ||
); | ||
} | ||
|
||
const objects = Array.isArray(candidate) ? candidate : [candidate]; | ||
|
||
for (const object of objects) { | ||
if(typeof object !== 'object') { | ||
throw new Error( | ||
'Failed to assert the presence of metadata because at least one candidate is not an object, meaning no constructor is present.', | ||
); | ||
} | ||
|
||
const metadata = object.constructor[Symbol.metadata]; | ||
|
||
if (metadata === undefined || metadata === null) { | ||
throw new Error( | ||
'No metadata was found on an object constructor.' | ||
); | ||
} | ||
} | ||
|
||
return true; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { assertMetadataIsPresent } from "./assertMetadataIsPresent"; | ||
import { getMetadataBySymbol } from "./getMetadataBySymbol"; | ||
|
||
export const collect = <T = unknown, O extends object = object>(object: O, symbol: symbol) => { | ||
assertMetadataIsPresent(object); | ||
|
||
const keyOrKeys = getMetadataBySymbol<keyof O | (keyof O)[]>(object, symbol); | ||
|
||
if(Array.isArray(keyOrKeys)) { | ||
const keys = keyOrKeys; | ||
|
||
if (keys.length === 0) { | ||
return {} as T; | ||
} | ||
|
||
return keys.reduce((acc, key) => { | ||
const value = object[key]; | ||
|
||
if (value === undefined) { | ||
return acc; | ||
} | ||
|
||
acc[key] = value; | ||
|
||
return acc; | ||
}, {} as Record<keyof O, unknown>) as T; | ||
} | ||
|
||
const key = keyOrKeys; | ||
|
||
return object[key] as T; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { assertMetadataIsPresent } from "./assertMetadataIsPresent"; | ||
|
||
export const getMetadataBySymbol = <T = unknown, O extends object = object>(object: O, symbol: symbol) => { | ||
assertMetadataIsPresent(object); | ||
|
||
const metadata = object.constructor[Symbol.metadata] as DecoratorMetadataObject; | ||
|
||
return metadata[symbol] as T; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './assertMetadataIsPresent'; | ||
export * from './getMetadataBySymbol'; | ||
export * from './collect'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters