use symbol.metadata

This commit is contained in:
Rowan 2025-05-18 21:42:39 -05:00
parent 6dc5d9ebed
commit cf3bdfba48
5 changed files with 30 additions and 40 deletions

9
package-lock.json generated
View file

@ -8,6 +8,9 @@
"name": "serde", "name": "serde",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": {
"@tsmetadata/polyfill": "^1.1.3"
},
"devDependencies": { "devDependencies": {
"esbuild": "^0.25.4", "esbuild": "^0.25.4",
"typescript": "^5.8.3" "typescript": "^5.8.3"
@ -438,6 +441,12 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@tsmetadata/polyfill": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@tsmetadata/polyfill/-/polyfill-1.1.3.tgz",
"integrity": "sha512-uSRn4aPO4F3wlSG/cPCAvclF9Sxf01OizWfWbSoSYsSHAK8LnYdua9iJAm7v2ePUrGWMP4ZCn9QjniZEKZHyFg==",
"license": "MIT"
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.25.4", "version": "0.25.4",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",

View file

@ -32,5 +32,8 @@
"devDependencies": { "devDependencies": {
"esbuild": "^0.25.4", "esbuild": "^0.25.4",
"typescript": "^5.8.3" "typescript": "^5.8.3"
},
"dependencies": {
"@tsmetadata/polyfill": "^1.1.3"
} }
} }

View file

@ -1,56 +1,33 @@
import { ContainerOptions, PropertyOptions, SerdeOptions } from './options' import { ContainerOptions, PropertyOptions, SerdeOptions } from './options'
import { GlobalRegistry, Registry } from './registry' import { GlobalRegistry, Registry } from './registry'
export const Serde = Symbol('Serde') function decorateContainer(target: any, context: any, options: ContainerOptions) {
const meta = context.metadata
function decorateContainer(options: ContainerOptions, constructor: any) { const serde = (meta.serde || new SerdeOptions(target))
if (constructor[Serde] == null) { serde.options = options
constructor[Serde] = new SerdeOptions(constructor, options) meta.serde = serde
} else {
constructor[Serde].options = options
}
return constructor
} }
function decorateProperty(options: PropertyOptions, target: any, property: PropertyKey) { function decorateProperty(target: any, context: any, options: PropertyOptions) {
let constructor: any const meta = context.metadata
if (typeof target === 'function') { const serde = (meta.serde || new SerdeOptions(target))
constructor = target serde.properties.set(context, options)
} else { meta.serde = serde
constructor = target.constructor
}
if (constructor[Serde] == null) {
constructor[Serde] = SerdeOptions.from(target)
}
constructor[Serde].properties.set(property, options)
return target
} }
export function serde(options: ContainerOptions | PropertyOptions) { export function serde(options: ContainerOptions | PropertyOptions) {
return function(target: any, property?: PropertyKey) { return function(target: any, context: any) {
if (property != null) { if (context != null) {
return decorateProperty(options as PropertyOptions, target, property) decorateProperty(target, context, options as PropertyOptions)
} else { } else {
return decorateContainer(options, target) decorateContainer(target, context, options as ContainerOptions)
} }
} }
} }
export function getMetadata(value: any) {
return value[Serde]
}
export function register(registry: Registry = GlobalRegistry) { export function register(registry: Registry = GlobalRegistry) {
return function(target: any) { return function(target: any, _context: any) {
if (target[Serde] == null) {
target[Serde] = SerdeOptions.from(target)
}
registry.add(target) registry.add(target)
return target
} }
} }

View file

@ -1,5 +1,4 @@
import { IterableSerializer, ObjectSerializer, Serializable, Serializer } from './interface' import { IterableSerializer, ObjectSerializer, Serializable, Serializer } from './interface'
import { Serde } from '../decorator'
import { SerdeOptions, Stage } from '../options' import { SerdeOptions, Stage } from '../options'
import { ifNull, isFunction, isIterable, isPlainObject, Nullable, orElse } from '../utils' import { ifNull, isFunction, isIterable, isPlainObject, Nullable, orElse } from '../utils'
@ -41,7 +40,7 @@ function serializeIter<T, V extends Iterable<any>>(serializer: IterableSerialize
} }
function defaultOptions(value: any) { function defaultOptions(value: any) {
return value.constructor[Serde] return value.constructor[Symbol.metadata]
} }
// dispatches in the order of serializeType -> serializeAny -> throw TypeError // dispatches in the order of serializeType -> serializeAny -> throw TypeError

View file

@ -1,3 +1,5 @@
import '@tsmetadata/polyfill'
export * from './interface' export * from './interface'
export * from './mixin' export * from './mixin'
export * from './impl' export * from './impl'