코드 이식
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
import { every, isString } from "lodash-es";
|
||||
import type { JsonifiableClassObj, PlainJson, PlainJsonObj } from "./jsonify.js";
|
||||
|
||||
type BsonifiableLite = string | number | boolean | bigint | null | undefined;
|
||||
|
||||
export type PlainBsonItem =
|
||||
string | number | boolean | null | undefined |
|
||||
Date | ArrayBuffer | SharedArrayBuffer | ArrayBufferView |
|
||||
PlainBsonItem[] |
|
||||
{ [key: string]: PlainBsonItem };
|
||||
|
||||
export type PlainBson =
|
||||
{ [key: string]: PlainBsonItem };
|
||||
|
||||
export type BsonifiableItem =
|
||||
BsonifiableLite |
|
||||
Date | ArrayBuffer | SharedArrayBuffer | ArrayBufferView |
|
||||
Array<BsonifiableItem> |
|
||||
Map<BsonifiableLite, BsonifiableItem> |
|
||||
Set<BsonifiableLite> |
|
||||
BsonifiableClassObj<PlainBson> |
|
||||
JsonifiableClassObj<PlainJson> |
|
||||
{ [key: string]: BsonifiableItem } |
|
||||
ReadonlyArray<BsonifiableItem>;
|
||||
|
||||
export type Bsonifiable =
|
||||
Map<string, BsonifiableItem> |
|
||||
BsonifiableClassObj<PlainBson> |
|
||||
JsonifiableClassObj<PlainJsonObj> |
|
||||
{ [key: string]: BsonifiableItem };
|
||||
|
||||
|
||||
export interface BsonifiableClassObj<T extends PlainBson> {
|
||||
bsonify(): T;
|
||||
}
|
||||
|
||||
type MaybeBsonifiedItem<T> = T extends BsonifiableItem ? BsonifiedItem<T> : never;
|
||||
type MaybeBsonified<T> = T extends Bsonifiable ? Bsonified<T> : never;
|
||||
|
||||
export type BsonifiedItem<T extends BsonifiableItem | unknown> =
|
||||
T extends string ? T :
|
||||
T extends number ? T :
|
||||
T extends boolean ? T :
|
||||
T extends bigint ? ReturnType<T['toString']> :
|
||||
T extends null ? T :
|
||||
T extends undefined ? T :
|
||||
T extends Date ? T :
|
||||
T extends ArrayBuffer ? T :
|
||||
T extends SharedArrayBuffer ? T :
|
||||
T extends ArrayBufferView ? T :
|
||||
T extends Map<infer K extends string, infer V> ? { [key in K]: MaybeBsonified<V> } :
|
||||
T extends Map<infer K, infer V> ? [MaybeBsonified<K>, MaybeBsonified<V>][] :
|
||||
T extends Set<infer V> ? MaybeBsonified<V>[] :
|
||||
T extends BsonifiableClassObj<PlainBson> ? ReturnType<T['bsonify']> :
|
||||
T extends JsonifiableClassObj<PlainJson> ? ReturnType<T['jsonify']> :
|
||||
T extends object ? { [key in keyof T]: MaybeBsonified<T[key]> } :
|
||||
T extends unknown ? unknown :
|
||||
never;
|
||||
|
||||
export type Bsonified<T extends Bsonifiable | unknown> =
|
||||
T extends Map<infer K extends string, infer V> ? { [key in K]: MaybeBsonifiedItem<V> } :
|
||||
T extends BsonifiableClassObj<PlainBson> ? ReturnType<T['bsonify']> :
|
||||
T extends JsonifiableClassObj<PlainJsonObj> ? ReturnType<T['jsonify']> :
|
||||
T extends object ? { [key in keyof T]: MaybeBsonifiedItem<T[key]> } :
|
||||
T extends unknown ? unknown :
|
||||
never;
|
||||
|
||||
/**
|
||||
* Convert any object to BSON-safe object
|
||||
*/
|
||||
export function bsonifyItem<T extends BsonifiableItem>(item: T): BsonifiedItem<T> {
|
||||
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
||||
return item as BsonifiedItem<T>;
|
||||
}
|
||||
|
||||
if (typeof item === 'bigint') {
|
||||
return item.toString() as BsonifiedItem<T>;
|
||||
}
|
||||
|
||||
if (typeof item === 'undefined') {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if (item === null) {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if (item instanceof Date) {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if (item instanceof ArrayBuffer) {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if ('SharedArrayBuffer' in globalThis && item instanceof SharedArrayBuffer) {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(item)) {
|
||||
return item as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
//HACK: depth hack, escape ts(2589)
|
||||
if (item instanceof Map) {
|
||||
const onlyStringKey = every(item.keys, isString);
|
||||
if (onlyStringKey) {
|
||||
const result: { [key: string]: string } = {};
|
||||
for (const [k, v] of item.entries()) {
|
||||
result[k as string] = bsonifyItem(v as string);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
const result: [string, string][] = [];
|
||||
for (const [k, v] of item.entries()) {
|
||||
result.push([bsonifyItem(k as string), bsonifyItem(v as string)]);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (item instanceof Set) {
|
||||
const result: string[] = [];
|
||||
for (const v of item.values()) {
|
||||
result.push(bsonifyItem(v as string));
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (Array.isArray(item)) {
|
||||
const result: string[] = [];
|
||||
for (const v of item) {
|
||||
result.push(bsonifyItem(v as string));
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (typeof item !== 'object') {
|
||||
throw new Error(`jsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if ('bsonify' in item && typeof item.bsonify === 'function') {
|
||||
return item.bsonify() as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
if ('jsonify' in item && typeof item.jsonify === 'function') {
|
||||
return item.jsonify() as BsonifiedItem<typeof item>;
|
||||
}
|
||||
|
||||
const result: { [key: string]: unknown } = {};
|
||||
for (const [k, v] of Object.entries(item)) {
|
||||
if (typeof k !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (k === 'prototype') {
|
||||
continue;
|
||||
}
|
||||
if (k === '__proto__ ') {
|
||||
continue;
|
||||
}
|
||||
if (typeof v === 'function') {
|
||||
continue;
|
||||
}
|
||||
result[k] = bsonifyItem(v as BsonifiableItem);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert any object to BSON-document object
|
||||
*/
|
||||
export function bsonify<T extends Bsonifiable>(item: T): Bsonified<T> {
|
||||
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (typeof item === 'bigint') {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (typeof item === 'undefined') {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item === null) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item instanceof Date) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item instanceof ArrayBuffer) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if ('SharedArrayBuffer' in globalThis && item instanceof SharedArrayBuffer) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(item)) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
//HACK: depth hack, escape ts(2589)
|
||||
if (item instanceof Map) {
|
||||
const onlyStringKey = every(item.keys, isString);
|
||||
if (onlyStringKey) {
|
||||
const result: { [key: string]: unknown } = {};
|
||||
for (const [k, v] of item.entries()) {
|
||||
result[k as string] = bsonifyItem(v as string);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item instanceof Set) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (Array.isArray(item)) {
|
||||
throw new Error(`bsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (typeof item !== 'object') {
|
||||
throw new Error(`jsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if ('bsonify' in item && typeof item.bsonify === 'function') {
|
||||
return item.bsonify() as Bsonified<typeof item>;
|
||||
}
|
||||
|
||||
if ('jsonify' in item && typeof item.jsonify === 'function') {
|
||||
return item.jsonify() as Bsonified<typeof item>;
|
||||
}
|
||||
|
||||
const result: { [key: string]: unknown } = {};
|
||||
for (const [k, v] of Object.entries(item)) {
|
||||
if (typeof k !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (k === 'prototype') {
|
||||
continue;
|
||||
}
|
||||
if (k === '__proto__ ') {
|
||||
continue;
|
||||
}
|
||||
if (typeof v === 'function') {
|
||||
continue;
|
||||
}
|
||||
result[k] = bsonifyItem(v);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export class NotNullExpected extends TypeError {
|
||||
public override name = 'NotNullExpected';
|
||||
}
|
||||
|
||||
export class RuntimeError extends Error {
|
||||
public override name = 'RuntimeError';
|
||||
constructor(public override message: string = '') {
|
||||
super(message);
|
||||
}
|
||||
override toString(): string {
|
||||
if (this.message) {
|
||||
return this.name + ': ' + this.message;
|
||||
}
|
||||
else {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
export * from "./bsonify.js"
|
||||
export * from "./jsonify.js"
|
||||
export * from "./error.js"
|
||||
export * from "./unwrap.js"
|
||||
export * from "./types.js"
|
||||
|
||||
export function isEmail(addr: string): boolean {
|
||||
return String(addr)
|
||||
.toLowerCase()
|
||||
.match(
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
) !== null;
|
||||
}
|
||||
|
||||
export function isIPAddr4(addr: string): boolean {
|
||||
if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(addr)) {
|
||||
return (true)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function calcBase64Len(length: number) {
|
||||
return ((4 * length / 3) + 3) & ~3;
|
||||
}
|
||||
|
||||
/** Buffer이지만 ts에서 타입 구분 편의를 제공 */
|
||||
export interface WrappedBuffer extends Buffer {
|
||||
/** 타입구분자. 항상 undefined일 것이다 */
|
||||
_w_type?: string;
|
||||
}
|
||||
|
||||
/** ArrayBuffer,Uint8Array,Buffer를 WrappedBuffer로 변환
|
||||
*/
|
||||
export function wrapBuffer<T extends WrappedBuffer>(buffer: BufferSource): T {
|
||||
/**
|
||||
* Buffer라면 wrapBuffer없이 그대로 대입 가능
|
||||
* ArrayBuffer, Uint8Array 등이라면 Buffer.from을 사용 가능
|
||||
* DataView 등인 경우는 ArrayBufferView 활용
|
||||
* 그냥 써도 되지만, 위 방법보다 아무렇게나 쓰기 좋다는 장점은 있음
|
||||
*/
|
||||
if (buffer instanceof Buffer) {
|
||||
return buffer as T;
|
||||
}
|
||||
if (buffer instanceof ArrayBuffer) {
|
||||
return Buffer.from(buffer) as T;
|
||||
}
|
||||
if (buffer instanceof SharedArrayBuffer) {
|
||||
return Buffer.from(buffer) as T;
|
||||
}
|
||||
return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength) as T;
|
||||
}
|
||||
|
||||
/** 호출할 필요 없이 바로 Buffer에 대입해도 되지만, 누군가 찾을 수 있어서. */
|
||||
export function unwrapBuffer<T extends WrappedBuffer>(buffer: T): Buffer {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
export function delay(time: number): Promise<void>;
|
||||
export function delay<T>(time: number, result: T): Promise<T>;
|
||||
export function delay<T = undefined>(time: number, result?: T): Promise<T | void> {
|
||||
return new Promise(resolve =>
|
||||
setTimeout(() => {
|
||||
resolve(result);
|
||||
}, time)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* base64 string에 내부 타입으로 WrappedBuffer를 보관한 형태
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type Base64String<T extends Buffer> = string & {
|
||||
/** 타입구분자. 항상 undefined일 것이다 */
|
||||
_b_type?: T;
|
||||
}
|
||||
|
||||
export function base64FromWrappedBuffer<T extends WrappedBuffer>(buffer: T | ArrayBuffer | Uint8Array): Base64String<T> {
|
||||
return Buffer.from(buffer).toString('base64');
|
||||
}
|
||||
|
||||
export function wrappedBufferFromBase64<T extends WrappedBuffer>(base64: Base64String<T>): T {
|
||||
return Buffer.from(base64, 'base64') as T;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
import { every, isString } from "lodash-es";
|
||||
import type { BsonifiableClassObj, PlainBson } from "./bsonify.js";
|
||||
|
||||
export type PlainJson =
|
||||
string | number | boolean | null | PlainJson[] | { [key: string]: PlainJson };
|
||||
|
||||
//엄밀히는 PlainJsonItem 스스로가 PlainJson이어야 하지만, Bson의 document와 호환을 맞추기 위해 object만 허용
|
||||
export type PlainJsonObj =
|
||||
{ [key: string]: PlainJson };
|
||||
|
||||
type JsonifiableLite =
|
||||
string | number | boolean | bigint | null | undefined;
|
||||
|
||||
export type Jsonifiable =
|
||||
JsonifiableLite |
|
||||
Date | ArrayBuffer | SharedArrayBuffer | ArrayBufferView |
|
||||
Array<Jsonifiable> |
|
||||
Map<JsonifiableLite, Jsonifiable> |
|
||||
Set<JsonifiableLite> |
|
||||
JsonifiableClassObj<PlainJson> |
|
||||
BsonifiableClassObj<PlainBson> |
|
||||
{ [key: string]: Jsonifiable } |
|
||||
ReadonlyArray<Jsonifiable>;
|
||||
|
||||
export type JsonifiableObj =
|
||||
Map<string, Jsonifiable> |
|
||||
JsonifiableClassObj<PlainJsonObj> |
|
||||
BsonifiableClassObj<PlainBson> |
|
||||
{ [key: string]: Jsonifiable };
|
||||
|
||||
export interface JsonifiableClassObj<T extends PlainJson> {
|
||||
jsonify(): T;
|
||||
}
|
||||
|
||||
type MaybeJsonified<T> = T extends Jsonifiable ? Jsonified<T> : never;
|
||||
type MaybeJsonifiedObj<T> = T extends JsonifiableObj ? JsonifiedObj<T> : never;
|
||||
|
||||
export type Jsonified<T extends Jsonifiable|unknown> =
|
||||
T extends string ? T :
|
||||
T extends number ? T :
|
||||
T extends boolean ? T :
|
||||
T extends bigint ? ReturnType<T['toString']> :
|
||||
T extends null ? T :
|
||||
T extends undefined ? T :
|
||||
T extends Date ? string :
|
||||
T extends ArrayBuffer ? string :
|
||||
T extends SharedArrayBuffer ? string :
|
||||
T extends ArrayBufferView ? string :
|
||||
T extends Map<infer K extends string, infer V> ? { [key in K]: MaybeJsonified<V> } :
|
||||
T extends Map<infer K, infer V> ? [MaybeJsonified<K>, MaybeJsonified<V>][] :
|
||||
T extends Set<infer V> ? MaybeJsonified<V>[] :
|
||||
T extends JsonifiableClassObj<PlainJson> ? ReturnType<T['jsonify']> :
|
||||
T extends BsonifiableClassObj<PlainBson> ? Jsonified<ReturnType<T['bsonify']>> :
|
||||
T extends object ? { [key in keyof T]: MaybeJsonified<T[key]> } :
|
||||
T extends unknown ? unknown :
|
||||
never;
|
||||
|
||||
export type JsonifiedObj<T extends JsonifiableObj|unknown> =
|
||||
T extends Map<infer K extends string, infer V> ? { [key in K]: MaybeJsonifiedObj<V> } :
|
||||
T extends JsonifiableClassObj<PlainJson> ? ReturnType<T['jsonify']> :
|
||||
T extends BsonifiableClassObj<PlainBson> ? Jsonified<ReturnType<T['bsonify']>> :
|
||||
T extends object ? { [key in keyof T]: MaybeJsonified<T[key]> } :
|
||||
T extends unknown ? unknown :
|
||||
never;
|
||||
|
||||
/**
|
||||
* Convert any object to JSON-safe object
|
||||
*/
|
||||
export function jsonify<T extends Jsonifiable>(item: T): Jsonified<T> {
|
||||
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
||||
return item as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (typeof item === 'bigint') {
|
||||
return item.toString() as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (typeof item === 'undefined') {
|
||||
return item as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (item === null) {
|
||||
return item as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (item instanceof Date) {
|
||||
return item.toISOString() as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (item instanceof ArrayBuffer) {
|
||||
return Buffer.from(item).toString('base64') as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if ('SharedArrayBuffer' in globalThis && item instanceof SharedArrayBuffer) {
|
||||
return Buffer.from(item).toString('base64') as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(item)) {
|
||||
return Buffer.from(item.buffer, item.byteOffset, item.byteLength).toString('base64') as Jsonified<typeof item>;
|
||||
}
|
||||
|
||||
//HACK: depth hack, escape ts(2589)
|
||||
if (item instanceof Map) {
|
||||
const onlyStringKey = every(item.keys, isString);
|
||||
if (onlyStringKey) {
|
||||
const result: { [key: string]: string } = {};
|
||||
for (const [k, v] of item.entries()) {
|
||||
result[k as string] = jsonify(v as string);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
const result: [string, string][] = [];
|
||||
for (const [k, v] of item.entries()) {
|
||||
result.push([jsonify(k as string), jsonify(v as string)]);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (item instanceof Set) {
|
||||
const result: string[] = [];
|
||||
for (const v of item.values()) {
|
||||
result.push(jsonify(v as string));
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (Array.isArray(item)) {
|
||||
const result: string[] = [];
|
||||
for (const v of item) {
|
||||
result.push(jsonify(v as string));
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
if (typeof item !== 'object') {
|
||||
throw new Error(`jsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if ('jsonify' in item && typeof item.jsonify === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item.jsonify() as any;
|
||||
}
|
||||
|
||||
if ('bsonify' in item && typeof item.bsonify === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return jsonify(item.bsonify() as Record<string,string>) as any;
|
||||
}
|
||||
|
||||
const result: { [key: string]: string } = {};
|
||||
for (const [k, v] of Object.entries(item)) {
|
||||
if (typeof k !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (k === 'prototype') {
|
||||
continue;
|
||||
}
|
||||
if (k === '__proto__ ') {
|
||||
continue;
|
||||
}
|
||||
if (typeof v === 'function') {
|
||||
continue;
|
||||
}
|
||||
result[k] = jsonify(v as string);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
export function jsonifyObj<T extends JsonifiableObj>(item: T): JsonifiedObj<T> {
|
||||
if (item === null) {
|
||||
throw new Error(`jsonifyObj: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item === undefined) {
|
||||
throw new Error(`jsonifyObj: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
//HACK: depth hack, escape ts(2589)
|
||||
if (item instanceof Map) {
|
||||
const onlyStringKey = every(item.keys, isString);
|
||||
if (onlyStringKey) {
|
||||
const result: { [key: string]: unknown } = {};
|
||||
for (const [k, v] of item.entries()) {
|
||||
result[k as string] = jsonify(v as Record<string,string>);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
|
||||
throw new Error(`jsonifyObj: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (Array.isArray(item)) {
|
||||
throw new Error(`jsonifyObj: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (item instanceof Set) {
|
||||
throw new Error(`jsonifyObj: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if (typeof item !== 'object') {
|
||||
throw new Error(`jsonify: invalid type ${typeof item}`);
|
||||
}
|
||||
|
||||
if ('jsonify' in item && typeof item.jsonify === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return item.jsonify() as any;
|
||||
}
|
||||
|
||||
if ('bsonify' in item && typeof item.bsonify === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return jsonify(item.bsonify() as Record<string,string>) as any;
|
||||
}
|
||||
|
||||
const result: { [key: string]: unknown } = {};
|
||||
for (const [k, v] of Object.entries(item)) {
|
||||
if (typeof k !== 'string') {
|
||||
continue;
|
||||
}
|
||||
if (k === 'prototype') {
|
||||
continue;
|
||||
}
|
||||
if (k === '__proto__ ') {
|
||||
continue;
|
||||
}
|
||||
if (typeof v === 'function') {
|
||||
continue;
|
||||
}
|
||||
result[k] = jsonify(v as Record<string,string>);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return result as any;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export type Nullable<T> = T | null | undefined;
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { Nullable } from './types.js';
|
||||
import { NotNullExpected } from "./error.js";
|
||||
|
||||
export function unwrap<T>(result: Nullable<T>): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new NotNullExpected();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function unwrap_any<T>(result: Nullable<unknown>): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new NotNullExpected();
|
||||
}
|
||||
return result as T;
|
||||
}
|
||||
|
||||
type ErrType<T> = { new(msg?: string): T }
|
||||
|
||||
export function unwrap_err<T, ErrT extends Error>(result: Nullable<T>, errType: ErrType<ErrT>, errMsg?: string): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new errType(errMsg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user