package js/d.ts

This commit is contained in:
Rowan 2025-05-18 20:05:52 -05:00
parent 4afb0e8e27
commit 0c9b2778c5
32 changed files with 955 additions and 2 deletions

12
dist/case.d.ts vendored Normal file
View file

@ -0,0 +1,12 @@
export declare const CaseConvention: Readonly<{
readonly Lowercase: 0;
readonly Uppercase: 1;
readonly PascalCase: 2;
readonly CamelCase: 3;
readonly SnakeCase: 4;
readonly ScreamingSnakeCase: 5;
readonly KebabCase: 6;
readonly ScreamingKebabCase: 7;
}>;
export type CaseConvention = typeof CaseConvention[keyof typeof CaseConvention];
export declare function convertCase(value: string, convention: CaseConvention): string;

56
dist/case.js vendored Normal file
View file

@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CaseConvention = void 0;
exports.convertCase = convertCase;
exports.CaseConvention = Object.freeze({
Lowercase: 0,
Uppercase: 1,
PascalCase: 2,
CamelCase: 3,
SnakeCase: 4,
ScreamingSnakeCase: 5,
KebabCase: 6,
ScreamingKebabCase: 7
});
const wordBoundaryRegex = /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g;
function identifyWords(value) {
return value && value.match(wordBoundaryRegex);
}
const lower = (ch) => ch.toLowerCase();
const upper = (ch) => ch.toUpperCase();
const first = (xs) => xs && xs[0];
const tail = (xs) => xs && xs.slice(1);
function upperFirst(xs) {
return upper(first(xs)) + tail(xs);
}
function toPascalCase(words) {
return words.map(lower).map(upperFirst).join('');
}
const joinMap = (fn, delim, xs) => {
return xs.map(fn).join(delim);
};
function convertCase(value, convention) {
const words = identifyWords(value);
if (!words || words.length <= 0) {
return '';
}
switch (convention) {
case exports.CaseConvention.Lowercase:
return words.join('').toLowerCase();
case exports.CaseConvention.Uppercase:
return words.join('').toUpperCase();
case exports.CaseConvention.PascalCase:
return toPascalCase(words);
case exports.CaseConvention.CamelCase:
const pascal = toPascalCase(words);
return first(pascal).toLowerCase() + tail(pascal);
case exports.CaseConvention.SnakeCase:
return joinMap(lower, '_', words);
case exports.CaseConvention.ScreamingSnakeCase:
return joinMap(upper, '_', words);
case exports.CaseConvention.KebabCase:
return joinMap(lower, '-', words);
case exports.CaseConvention.ScreamingKebabCase:
return joinMap(upper, '-', words);
}
}

15
dist/de/generic.d.ts vendored Normal file
View file

@ -0,0 +1,15 @@
import { Deserialize, Deserializer, IterableAccess, MapAccess, Visitor } from './interface';
export declare class GenericSeed<T> implements Deserialize<T> {
static deserialize<T, D extends Deserializer>(deserializer: D): T;
deserialize<D extends Deserializer>(deserializer: D): T;
}
export declare class GenericVisitor<T> implements Visitor<T> {
visitString(value: string): T;
visitNumber(value: number): T;
visitBigInt(value: bigint): T;
visitBoolean(value: boolean): T;
visitSymbol(value: symbol): T;
visitNull(): T;
visitObject(access: MapAccess): T;
visitIterable(access: IterableAccess): T;
}

60
dist/de/generic.js vendored Normal file
View file

@ -0,0 +1,60 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var GenericSeed_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericVisitor = exports.GenericSeed = void 0;
const utils_1 = require("../utils");
let GenericSeed = GenericSeed_1 = class GenericSeed {
static deserialize(deserializer) {
return deserializer.deserializeAny(new GenericVisitor());
}
deserialize(deserializer) {
return GenericSeed_1.deserialize(deserializer);
}
};
exports.GenericSeed = GenericSeed;
exports.GenericSeed = GenericSeed = GenericSeed_1 = __decorate([
(0, utils_1.staticImplements)()
], GenericSeed);
class GenericVisitor {
visitString(value) {
return value;
}
visitNumber(value) {
return value;
}
visitBigInt(value) {
return value;
}
visitBoolean(value) {
return value;
}
visitSymbol(value) {
return value;
}
visitNull() {
return null;
}
visitObject(access) {
const result = {};
let entry;
while ((entry = access.nextEntry())) {
result[entry[0]] = entry[1];
}
return result;
}
visitIterable(access) {
const result = new Array(access.sizeHint());
let element;
while ((element = access.nextElement())) {
result.push(element);
}
return result;
}
}
exports.GenericVisitor = GenericVisitor;

7
dist/de/impl.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
import { SerdeOptions } from '../options';
import { Deserialize, Deserializer } from './interface';
type DeserializeConstructor<T> = Deserialize<T> & {
new (): Deserialize<T>;
};
export declare function deserializeWith<T, D extends Deserializer, E extends DeserializeConstructor<T>>(deserializer: D, into: E, options: SerdeOptions): T;
export {};

21
dist/de/impl.js vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deserializeWith = deserializeWith;
const options_1 = require("../options");
const generic_1 = require("./generic");
function deserializeWith(deserializer, into, options) {
const visitor = new generic_1.GenericVisitor();
const obj = deserializer.deserializeObject(visitor);
const target = new into();
const newObject = {};
for (const property in target) {
const name = options.getPropertyName(property, options_1.Stage.Deserialize);
const value = obj[name] || options.getDefault(property);
newObject[property] = value;
delete obj[name];
}
if (options.options.denyUnknownFields && Object.keys(obj).length > 0) {
throw new TypeError(`Unexpected fields: ${Object.keys(obj).join(', ')}`);
}
return Object.assign(target, newObject);
}

3
dist/de/index.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
export * from './interface';
export * from './generic';
export * from './mixin';

19
dist/de/index.js vendored Normal file
View file

@ -0,0 +1,19 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./interface"), exports);
__exportStar(require("./generic"), exports);
__exportStar(require("./mixin"), exports);

52
dist/de/interface.d.ts vendored Normal file
View file

@ -0,0 +1,52 @@
import { Nullable } from '../utils';
export interface MapAccess {
nextKeySeed<T, K extends Deserialize<T>>(seed: K): Nullable<T>;
nextValueSeed<T, V extends Deserialize<T>>(seed: V): Nullable<T>;
nextEntrySeed<TK, TV, K extends Deserialize<TK>, V extends Deserialize<TV>>(kseed: K, vseed: V): Nullable<[TK, TV]>;
nextKey<T>(): Nullable<T>;
nextValue<T>(): Nullable<T>;
nextEntry<K, V>(): Nullable<[K, V]>;
}
export declare abstract class DefaultMapAccessImpl implements MapAccess {
abstract nextKeySeed<T, K extends Deserialize<T>>(seed: K): Nullable<T>;
abstract nextValueSeed<T, V extends Deserialize<T>>(seed: V): Nullable<T>;
nextEntrySeed<TK, TV, K extends Deserialize<TK>, V extends Deserialize<TV>>(kseed: K, vseed: V): Nullable<[TK, TV]>;
nextKey<T>(): Nullable<T>;
nextValue<T>(): Nullable<T>;
nextEntry<K, V>(): Nullable<[K, V]>;
}
export interface IterableAccess {
nextElementSeed<T, I extends Deserialize<T>>(seed: I): Nullable<T>;
nextElement<T>(): Nullable<T>;
sizeHint(): number;
}
export declare abstract class DefaultIterableAccessImpl implements IterableAccess {
abstract nextElementSeed<T, I extends Deserialize<T>>(seed: I): Nullable<T>;
nextElement<T>(): Nullable<T>;
sizeHint(): number;
}
export interface Visitor<T> {
visitString(value: string): T;
visitNumber(value: number): T;
visitBigInt(value: bigint): T;
visitBoolean(value: boolean): T;
visitSymbol(value: symbol): T;
visitNull(): T;
visitObject(value: MapAccess): T;
visitIterable?(value: IterableAccess): T;
}
export interface Deserializer {
deserializeAny<T, V extends Visitor<T>>(visitor: V): T;
deserializeString<T, V extends Visitor<T>>(visitor: V): T;
deserializeNumber<T, V extends Visitor<T>>(visitor: V): T;
deserializeBigInt<T, V extends Visitor<T>>(visitor: V): T;
deserializeBoolean<T, V extends Visitor<T>>(visitor: V): T;
deserializeSymbol<T, V extends Visitor<T>>(visitor: V): T;
deserializeNull<T, V extends Visitor<T>>(visitor: V): T;
deserializeObject<T, V extends Visitor<T>>(visitor: V): T;
deserializeClass<T, V extends Visitor<T>>(name: string, fields: string[], visitor: V): T;
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T;
}
export interface Deserialize<T> {
deserialize<D extends Deserializer>(deserializer: D): T;
}

32
dist/de/interface.js vendored Normal file
View file

@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultIterableAccessImpl = exports.DefaultMapAccessImpl = void 0;
const generic_1 = require("./generic");
class DefaultMapAccessImpl {
nextEntrySeed(kseed, vseed) {
const key = this.nextKeySeed(kseed);
if (key !== undefined) {
const value = this.nextValueSeed(vseed);
if (value !== undefined) {
return [key, value];
}
}
}
nextKey() {
return this.nextValueSeed((generic_1.GenericSeed));
}
nextValue() {
return this.nextValueSeed((generic_1.GenericSeed));
}
nextEntry() {
return this.nextEntrySeed((generic_1.GenericSeed), (generic_1.GenericSeed));
}
}
exports.DefaultMapAccessImpl = DefaultMapAccessImpl;
class DefaultIterableAccessImpl {
nextElement() {
return this.nextElementSeed((generic_1.GenericSeed));
}
sizeHint() { return 0; }
}
exports.DefaultIterableAccessImpl = DefaultIterableAccessImpl;

9
dist/de/mixin.d.ts vendored Normal file
View file

@ -0,0 +1,9 @@
import { Constructor } from '../utils';
import { Deserializer } from './interface';
export declare function deserialize<T, C extends Constructor>(constructor: C): {
new (...args: any[]): {
[x: string]: any;
};
name: string;
deserialize<D extends Deserializer>(deserializer: D): T;
} & C;

31
dist/de/mixin.js vendored Normal file
View file

@ -0,0 +1,31 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deserialize = deserialize;
const decorator_1 = require("../decorator");
const utils_1 = require("../utils");
const impl_1 = require("./impl");
function deserialize(constructor) {
let Deserializable = class Deserializable extends constructor {
static deserialize(deserializer) {
return (0, impl_1.deserializeWith)(deserializer, this, (0, decorator_1.getMetadata)(this));
}
};
Object.defineProperty(Deserializable, "name", {
enumerable: true,
configurable: true,
writable: true,
value: constructor.name
});
Deserializable = __decorate([
(0, utils_1.staticImplements)()
], Deserializable);
// @ts-ignore
Deserializable[decorator_1.Serde] = constructor[decorator_1.Serde];
return Deserializable;
}

6
dist/decorator.d.ts vendored Normal file
View file

@ -0,0 +1,6 @@
import { ContainerOptions, PropertyOptions } from './options';
import { Registry } from './registry';
export declare const Serde: unique symbol;
export declare function serde(options: ContainerOptions | PropertyOptions): (target: any, property?: PropertyKey) => any;
export declare function getMetadata(value: any): any;
export declare function register(registry?: Registry): (target: any) => any;

54
dist/decorator.js vendored Normal file
View file

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Serde = void 0;
exports.serde = serde;
exports.getMetadata = getMetadata;
exports.register = register;
const options_1 = require("./options");
const registry_1 = require("./registry");
exports.Serde = Symbol('Serde');
function decorateContainer(options, constructor) {
if (constructor[exports.Serde] == null) {
constructor[exports.Serde] = new options_1.SerdeOptions(constructor, options);
}
else {
constructor[exports.Serde].options = options;
}
return constructor;
}
function decorateProperty(options, target, property) {
let constructor;
if (typeof target === 'function') {
constructor = target;
}
else {
constructor = target.constructor;
}
if (constructor[exports.Serde] == null) {
constructor[exports.Serde] = options_1.SerdeOptions.from(target);
}
constructor[exports.Serde].properties.set(property, options);
return target;
}
function serde(options) {
return function (target, property) {
if (property != null) {
return decorateProperty(options, target, property);
}
else {
return decorateContainer(options, target);
}
};
}
function getMetadata(value) {
return value[exports.Serde];
}
function register(registry = registry_1.GlobalRegistry) {
return function (target) {
if (target[exports.Serde] == null) {
target[exports.Serde] = options_1.SerdeOptions.from(target);
}
registry.add(target);
return target;
};
}

6
dist/index.d.ts vendored Normal file
View file

@ -0,0 +1,6 @@
export * as ser from './ser/index';
export * as de from './de/index';
export * from './case';
export * from './registry';
export * from './decorator';
export * from './options';

45
dist/index.js vendored Normal file
View file

@ -0,0 +1,45 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.de = exports.ser = void 0;
exports.ser = __importStar(require("./ser/index"));
exports.de = __importStar(require("./de/index"));
__exportStar(require("./case"), exports);
__exportStar(require("./registry"), exports);
__exportStar(require("./decorator"), exports);
__exportStar(require("./options"), exports);

63
dist/options.d.ts vendored Normal file
View file

@ -0,0 +1,63 @@
import { CaseConvention } from './case';
import { Deserializer } from './de';
import { Serializer } from './ser';
import { Registry } from './registry';
export interface RenameOptions {
serialize?: string;
deserialize?: string;
}
export interface RenameAllOptions {
serialize?: CaseConvention;
deserialize?: CaseConvention;
}
export interface ContainerOptions {
default?: () => any;
denyUnknownFields?: boolean;
expecting?: string;
rename?: RenameOptions | string;
renameAll?: RenameAllOptions | CaseConvention;
registry?: Registry;
tag?: string;
content?: string;
untagged?: boolean;
}
export interface ConditionalSkipOptions {
if: (value: any) => boolean;
}
export interface SkipOptions {
serializing?: ConditionalSkipOptions | boolean;
deserializing?: ConditionalSkipOptions | boolean;
}
export type CustomSerializer = <T, V, S extends Serializer<T>>(value: V, serializer: S) => T;
export type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T;
export interface PropertyOptions {
alias?: string;
default?: () => any;
flatten?: boolean;
rename?: RenameOptions | string;
skip?: SkipOptions | ConditionalSkipOptions | boolean;
}
export declare const Stage: Readonly<{
readonly Serialize: 0;
readonly Deserialize: 1;
}>;
export type Stage = typeof Stage[keyof typeof Stage];
export declare class SerdeOptions {
private readonly target;
readonly options: ContainerOptions;
readonly properties: Map<string, PropertyOptions>;
get registry(): Registry;
constructor(target: any, options?: ContainerOptions, properties?: Map<string, PropertyOptions>);
static from(target: any): SerdeOptions;
getClassName(stage: Stage): any;
private getPropertyRename;
private getPropertyCase;
getPropertyName(property: string, stage: Stage): string;
getSerializationName(property: string): string;
getDeserializationName(property: string): string;
getDefault(property: string): any;
private isConditionalSkip;
shouldSkip(property: string, value: any, stage: Stage): boolean;
shouldSkipSerializing(property: string, value: any): boolean;
shouldSkipDeserializing(property: string, value: any): boolean;
}

156
dist/options.js vendored Normal file
View file

@ -0,0 +1,156 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SerdeOptions = exports.Stage = void 0;
const case_1 = require("./case");
const utils_1 = require("./utils");
const registry_1 = require("./registry");
exports.Stage = Object.freeze({
Serialize: 0,
Deserialize: 1
});
class SerdeOptions {
get registry() {
return this.options.registry || registry_1.GlobalRegistry;
}
constructor(target, options = {}, properties = new Map()) {
Object.defineProperty(this, "target", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "options", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "properties", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.target = target;
this.options = options;
this.properties = properties;
}
static from(target) {
return new this(target);
}
getClassName(stage) {
var _a, _b;
if ((0, utils_1.isString)(this.options.rename)) {
return this.options.rename;
}
else if (stage === exports.Stage.Serialize && (0, utils_1.isString)((_a = this.options.rename) === null || _a === void 0 ? void 0 : _a.serialize)) {
return this.options.rename.serialize;
}
else if (stage === exports.Stage.Deserialize && (0, utils_1.isString)((_b = this.options.rename) === null || _b === void 0 ? void 0 : _b.deserialize)) {
return this.options.rename.deserialize;
}
else {
return this.target.constructor.name;
}
}
getPropertyRename(property, stage, options) {
var _a, _b;
if (options != null) {
if ((0, utils_1.isString)(options.rename)) {
return options.rename;
}
else if (stage === exports.Stage.Serialize && (0, utils_1.isString)((_a = options.rename) === null || _a === void 0 ? void 0 : _a.serialize)) {
return options.rename.serialize;
}
else if (stage === exports.Stage.Deserialize && (0, utils_1.isString)((_b = options.rename) === null || _b === void 0 ? void 0 : _b.deserialize)) {
return options.rename.deserialize;
}
}
return property;
}
getPropertyCase(name, stage) {
var _a, _b;
if ((0, utils_1.isNumber)(this.options.renameAll)) {
return (0, case_1.convertCase)(name, this.options.renameAll);
}
else if (stage === exports.Stage.Serialize && (0, utils_1.isNumber)((_a = this.options.renameAll) === null || _a === void 0 ? void 0 : _a.serialize)) {
return (0, case_1.convertCase)(name, this.options.renameAll.serialize);
}
else if (stage === exports.Stage.Deserialize && (0, utils_1.isNumber)((_b = this.options.renameAll) === null || _b === void 0 ? void 0 : _b.deserialize)) {
return (0, case_1.convertCase)(name, this.options.renameAll.deserialize);
}
else {
return name;
}
}
getPropertyName(property, stage) {
const options = this.properties.get(property);
const name = options != null ? this.getPropertyRename(property, stage, options) : property;
return this.getPropertyCase(name, stage);
}
getSerializationName(property) {
return this.getPropertyName(property, exports.Stage.Serialize);
}
getDeserializationName(property) {
return this.getPropertyName(property, exports.Stage.Deserialize);
}
getDefault(property) {
const options = this.properties.get(property);
if (options && (0, utils_1.isFunction)(options.default)) {
return options.default();
}
else if ((0, utils_1.isFunction)(this.options.default)) {
return this.options.default();
}
}
//getCustomImpl(property: string, stage: Stage) {
// const options = this.properties.get(property)
// if (options != null) {
// if (stage === Stage.Serialize && isFunction(options.serializeWith)) {
// return options.serializeWith
// } else if (stage === Stage.Deserialize && isFunction(options.deserializeWith)) {
// return options.deserializeWith
// }
// }
//}
//getSerializer(property: string): Nullable<CustomSerializer> {
// return this.getCustomImpl(property, Stage.Serialize) as CustomSerializer
//}
//getDeserializer(property: string): Nullable<CustomDeserializer> {
// return this.getCustomImpl(property, Stage.Deserialize) as CustomDeserializer
//}
isConditionalSkip(skip) {
return 'if' in skip && (0, utils_1.isFunction)(skip.if);
}
shouldSkip(property, value, stage) {
const options = this.properties.get(property);
if (options != null && options.skip != null) {
if (typeof options.skip === 'boolean') {
return options.skip;
}
else if (this.isConditionalSkip(options.skip)) {
return options.skip.if(value);
}
else if (stage === exports.Stage.Serialize && typeof options.skip.serializing === 'boolean') {
return options.skip.serializing;
}
else if (stage === exports.Stage.Serialize && this.isConditionalSkip(options.skip.serializing)) {
return options.skip.serializing.if(value);
}
else if (stage === exports.Stage.Deserialize && typeof options.skip.deserializing === 'boolean') {
return options.skip.deserializing;
}
else if (stage === exports.Stage.Deserialize && this.isConditionalSkip(options.skip.deserializing)) {
return options.skip.deserializing.if(value);
}
}
return false;
}
shouldSkipSerializing(property, value) {
return this.shouldSkip(property, value, exports.Stage.Serialize);
}
shouldSkipDeserializing(property, value) {
return this.shouldSkip(property, value, exports.Stage.Deserialize);
}
}
exports.SerdeOptions = SerdeOptions;

7
dist/registry.d.ts vendored Normal file
View file

@ -0,0 +1,7 @@
import { Constructor } from './utils';
export declare class Registry {
registeredClasses: Map<string, Constructor>;
add(ctor: Constructor, key?: string): void;
get(name: string): Constructor | undefined;
}
export declare const GlobalRegistry: Registry;

21
dist/registry.js vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GlobalRegistry = exports.Registry = void 0;
class Registry {
constructor() {
Object.defineProperty(this, "registeredClasses", {
enumerable: true,
configurable: true,
writable: true,
value: new Map()
});
}
add(ctor, key = ctor.name) {
this.registeredClasses.set(key, ctor);
}
get(name) {
return this.registeredClasses.get(name);
}
}
exports.Registry = Registry;
exports.GlobalRegistry = new Registry();

4
dist/ser/impl.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
import { Serializable, Serializer } from './interface';
import { SerdeOptions } from '../options';
import { Nullable } from '../utils';
export declare function serializeWith<T>(serializer: Serializer<T>, value: Serializable, optionsGetter?: (value: any) => Nullable<SerdeOptions>): Nullable<T>;

64
dist/ser/impl.js vendored Normal file
View file

@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serializeWith = serializeWith;
const decorator_1 = require("../decorator");
const options_1 = require("../options");
const utils_1 = require("../utils");
const unhandledType = (serializer, value) => new TypeError(`'${serializer.constructor.name}' has no method for value type '${typeof value}'`);
function serializeEntries(serializer, value, options) {
var _a;
let state;
for (const [key, val] of value) {
if (options === null || options === void 0 ? void 0 : options.shouldSkipSerializing(key, val)) {
continue;
}
const name = (_a = options === null || options === void 0 ? void 0 : options.getPropertyName(key, options_1.Stage.Serialize)) !== null && _a !== void 0 ? _a : key;
console.log('prop name for', key, name);
state = serializer.serializeKey(name);
state = serializer.serializeValue(val);
}
return serializer.end();
}
function serializeClass(serializer, value, options) {
const classSerializer = serializer.serializeClass(value.constructor.name);
return serializeEntries(classSerializer, Object.entries(value), options);
}
function serializeObject(serializer, value, options) {
return serializeEntries(serializer.serializeObject(), Object.entries(value), options);
}
function serializeIter(serializer, value, options) {
let state;
for (const val of value) {
state = serializer.serializeElement(val);
}
return serializer.end();
}
function defaultOptions(value) {
return value.constructor[decorator_1.Serde];
}
// dispatches in the order of serializeType -> serializeAny -> throw TypeError
function serializeWith(serializer, value, optionsGetter = defaultOptions) {
// prepare fallback methods
const serializeAny = (0, utils_1.orElse)(serializer, serializer.serializeAny, (value) => unhandledType(serializer, value));
const serialize = (0, utils_1.ifNull)(serializer, serializeAny, value);
switch (typeof value) {
case 'string': return serialize(serializer.serializeString);
case 'number': return serialize(serializer.serializeNumber);
case 'bigint': return serialize(serializer.serializeBigInt);
case 'boolean': return serialize(serializer.serializeBoolean);
case 'symbol': return serialize(serializer.serializeSymbol);
case 'undefined': return serialize(serializer.serializeNull);
case 'object':
const options = optionsGetter(value);
if ((0, utils_1.isIterable)(value) && (0, utils_1.isFunction)(serializer.serializeIterable)) {
return serializeIter(serializer.serializeIterable(), value, options);
}
if (!(0, utils_1.isPlainObject)(value)) {
return serializeClass(serializer, value, options);
}
else if ((0, utils_1.isFunction)(serializer.serializeObject)) {
return serializeObject(serializer, value, options);
} // deliberate fallthrough when the above fail
default: return serializeAny(value);
}
}

3
dist/ser/index.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
export * from './interface';
export * from './mixin';
export * from './impl';

19
dist/ser/index.js vendored Normal file
View file

@ -0,0 +1,19 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./interface"), exports);
__exportStar(require("./mixin"), exports);
__exportStar(require("./impl"), exports);

31
dist/ser/interface.d.ts vendored Normal file
View file

@ -0,0 +1,31 @@
import { Primitive, ToString } from "../utils";
export interface ObjectSerializer<T = void> {
serializeKey<U extends Serializable>(key: U): T;
serializeValue<U extends Serializable>(value: U): T;
end(): T;
}
export interface IterableSerializer<T = void> {
serializeElement<U extends Serializable>(element: U): T;
end(): T;
}
interface TypeSerializer<T> {
serializeString(value: string): T;
serializeNumber(value: number): T;
serializeBigInt(value: bigint): T;
serializeBoolean(value: boolean): T;
serializeSymbol(value: Symbol): T;
serializeNull(): T;
serializeObject(): ObjectSerializer<T>;
serializeIterable?(): IterableSerializer<T>;
serializeClass(name: PropertyKey): ObjectSerializer<T>;
}
interface AnySerializer<T> {
serializeAny?(value?: any): T;
}
export declare function isGenericSerializer(value: any): boolean;
export type Serializer<T> = Partial<TypeSerializer<T>> & Partial<AnySerializer<T>>;
export type Serializable = Primitive | ToString | Serialize;
export interface Serialize {
serialize<T, S extends Serializer<T>>(serializer: S): T;
}
export {};

21
dist/ser/interface.js vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isGenericSerializer = isGenericSerializer;
const utils_1 = require("../utils");
const TypeSerializerMethods = [
'serializeString',
'serializeNumber',
'serializeBigInt',
'serializeBoolean',
'serializeSymbol',
//'serializeMap',
'serializeIterable',
'serializeNull',
'serializeObject',
'serializeClass',
];
const AnySerializerMethods = ['serializeAny'];
function isGenericSerializer(value) {
return AnySerializerMethods.every(k => (0, utils_1.isFunction)(value[k])) &&
TypeSerializerMethods.every(k => !(0, utils_1.isFunction)(value[k]));
}

9
dist/ser/mixin.d.ts vendored Normal file
View file

@ -0,0 +1,9 @@
import { Constructor } from '../utils';
import { Serializer } from './interface';
export declare function serialize<T extends Constructor>(constructor: T): {
new (...args: any[]): {
[x: string]: any;
serialize<U>(serializer: Serializer<U>): U;
};
name: string;
} & T;

27
dist/ser/mixin.js vendored Normal file
View file

@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serialize = serialize;
const decorator_1 = require("../decorator");
const impl_1 = require("./impl");
const interface_1 = require("./interface");
function serialize(constructor) {
class Serializable extends constructor {
serialize(serializer) {
// shortcut for serializers with only the serializeAny method
if ((0, interface_1.isGenericSerializer)(serializer)) {
return serializer.serializeAny(this);
}
else {
return (0, impl_1.serializeWith)(serializer, this);
}
}
}
Object.defineProperty(Serializable, "name", {
enumerable: true,
configurable: true,
writable: true,
value: constructor.name
});
Serializable[decorator_1.Serde] = constructor[decorator_1.Serde];
return Serializable;
}

28
dist/utils.d.ts vendored Normal file
View file

@ -0,0 +1,28 @@
export type Nullable<T> = T | undefined;
export interface Morphism<T = any, U = any> {
(value: T): U;
}
export type Primitive = string | number | boolean | symbol | bigint | null | undefined;
export interface ToString {
toString(): string;
}
export declare function staticImplements<T>(): <U extends T>(constructor: U) => void;
export declare function isPlainObject(value: any): boolean;
export declare function isFunction(value: any): value is Function;
export declare function isIterable(value: any): value is Iterable<any>;
export declare function isString(value: any): value is string;
export declare function isNumber(value: any): value is number;
export type Constructor<T = any> = new (...args: any[]) => T;
export declare function orElse(thisArg: any, a: Nullable<Function>, b: Function): (...args: any) => any;
export declare function ifNull(thisArg: any, b: Function, ...args: any): (a: Nullable<Function>) => any;
export declare function mixin<U = any>(impl: Function): <TBase extends Constructor<U>>(constructor: TBase) => TBase;
type AnyFunc = (...arg: any) => any;
type PipeArgs<F extends AnyFunc[], Acc extends AnyFunc[] = []> = F extends [
(...args: infer A) => infer B
] ? [...Acc, (...args: A) => B] : F extends [(...args: infer A) => any, ...infer Tail] ? Tail extends [(arg: infer B) => any, ...any[]] ? PipeArgs<Tail, [...Acc, (...args: A) => B]> : Acc : Acc;
type LastFnReturnType<F extends Array<AnyFunc>, Else = never> = F extends [
...any[],
(...arg: any) => infer R
] ? R : Else;
export declare function pipe<FirstFn extends AnyFunc, F extends AnyFunc[]>(arg: Parameters<FirstFn>[0], firstFn: FirstFn, ...fns: PipeArgs<F> extends F ? F : PipeArgs<F>): LastFnReturnType<F, ReturnType<FirstFn>>;
export {};

58
dist/utils.js vendored Normal file
View file

@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.staticImplements = staticImplements;
exports.isPlainObject = isPlainObject;
exports.isFunction = isFunction;
exports.isIterable = isIterable;
exports.isString = isString;
exports.isNumber = isNumber;
exports.orElse = orElse;
exports.ifNull = ifNull;
exports.mixin = mixin;
exports.pipe = pipe;
function staticImplements() {
return (constructor) => { constructor; };
}
function isPlainObject(value) {
return Object.getPrototypeOf(value) === Object.prototype;
}
function isFunction(value) {
return value != null && typeof value === 'function';
}
function isIterable(value) {
return isFunction(value[Symbol.iterator]);
}
function isString(value) {
return typeof value === 'string';
}
function isNumber(value) {
return !isNaN(value);
}
function orElse(thisArg, a, b) {
return function (...args) {
const fn = a != null ? a : b;
return fn.apply(thisArg, args);
};
}
function ifNull(thisArg, b, ...args) {
return function (a) {
return orElse(thisArg, a, b).apply(thisArg, args);
};
}
function applyMixins(derivedCtor, constructors) {
constructors.forEach((baseCtor) => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
Object.create(null));
});
});
}
function mixin(impl) {
return function (constructor) {
applyMixins(constructor, [impl]);
return constructor;
};
}
function pipe(arg, firstFn, ...fns) {
return fns.reduce((acc, fn) => fn(acc), firstFn(arg));
}

View file

@ -3,6 +3,20 @@
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"exports": {
".": {
"types": "dist/index.d.ts",
"default": "src/index.ts"
},
"./ser": {
"types": "dist/ser/index.d.ts",
"default": "dist/ser/index.js"
},
"./de": {
"types": "dist/de/index.d.ts",
"default": "dist/de/index.js"
}
},
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"

View file

@ -52,14 +52,14 @@
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
"outDir": "./dist/", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */