Skip to content

Commit

Permalink
✨ map,set,json,object coverter
Browse files Browse the repository at this point in the history
  • Loading branch information
trydofor committed Oct 24, 2024
1 parent 9faf4c6 commit 57588d6
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 17 deletions.
6 changes: 0 additions & 6 deletions layers/common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# @fessional/razor-common

## 0.1.30

### Patch Changes

- ffa8942: ➕ pinia store #70

## 0.1.29

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion layers/common/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fessional/razor-common",
"type": "module",
"version": "0.1.30",
"version": "0.1.29",
"description": "common layer for mobile and desktop",
"main": "./nuxt.config.ts",
"types": "./index.d.ts",
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import { safeString, safeNumber, safeBigint, safeValues, safeKeys, safeEntries } from '../utils/safe-converter';
import { safeString, safeNumber, safeBigint, safeValues, safeKeys, safeEntries, safeJson, safeObjMap, safeArrSet, safeMapObj, safeSetArr } from '../utils/safe-converter';

describe('safeString', () => {
it('should return defaults if null or undefined', () => {
Expand Down Expand Up @@ -226,3 +226,138 @@ describe('numberKey;', () => {
expect(strMap.has(d3)).toBe(false);
});
});

describe('safeJson', () => {
it('json map and obj', () => {
const obj = {
firstName: 'John',
lastName: 'Doe',
age: 30,
};

expect(JSON.stringify(obj)).toBe('{"firstName":"John","lastName":"Doe","age":30}');

const map = new Map();
map.set('firstName', 'John');
map.set('lastName', 'Doe');
map.set('age', 30);

expect(JSON.stringify(map)).toBe('{}');
});

it('should convert BigInt to string', () => {
const input = { value: 42n };
const result = safeJson(input);
expect(result).toEqual('{"value":"42"}');
});

it('should convert Map to object', () => {
const input = {
scores: new Map([
['math', 90],
['science', 85],
]),
};
const result = safeJson(input);
expect(result).toEqual('{"scores":{"math":90,"science":85}}');
});

it('should convert Set to array', () => {
const input = {
uniqueItems: new Set([1, 2, 3, 4]),
};
const result = safeJson(input);
expect(result).toEqual('{"uniqueItems":[1,2,3,4]}');
});

it('should not modify other types', () => {
const input = {
name: 'Alice',
age: 30,
active: true,
};
const result = safeJson(input);
expect(result).toEqual('{"name":"Alice","age":30,"active":true}');
});

it('should handle mixed types', () => {
const input = {
name: 'Alice',
age: 30n,
scores: new Map([
['math', 90],
['science', 85],
]),
uniqueItems: new Set([1, 2, 3, 4]),
};
const result = safeJson(input);
expect(result).toEqual('{"name":"Alice","age":"30","scores":{"math":90,"science":85},"uniqueItems":[1,2,3,4]}');
});

it('should return unchanged for null and undefined', () => {
const input = { a: null, b: undefined };
const result = safeJson(input);
expect(result).toEqual('{"a":null}');
});
});

describe('safeObjMap', () => {
it('should convert object to Map', () => {
const obj = { a: 1, b: 2 };
const result = safeObjMap(obj);
expect(result instanceof Map).toBe(true);
expect(result.size).toBe(2);
expect(result.get('a')).toBe(1);
expect(result.get('b')).toBe(2);
});

it('should return empty Map if null or undefined', () => {
expect(safeObjMap(null).size).toBe(0);
expect(safeObjMap(undefined).size).toBe(0);
});
});

describe('safeArrSet', () => {
it('should convert array to Set', () => {
const arr = [1, 2, 3, 2, 1];
const result = safeArrSet(arr);
expect(result instanceof Set).toBe(true);
expect(result.size).toBe(3);
expect(result.has(1)).toBe(true);
expect(result.has(2)).toBe(true);
expect(result.has(3)).toBe(true);
});

it('should return empty Set if null or undefined', () => {
expect(safeArrSet(null).size).toBe(0);
expect(safeArrSet(undefined).size).toBe(0);
});
});

describe('safeMapObj', () => {
it('should convert Map to object', () => {
const map = new Map([['a', 1], ['b', 2]]);
const result = safeMapObj(map);
expect(typeof result).toBe('object');
expect(result).toEqual({ a: 1, b: 2 });
});

it('should return empty object if null or undefined', () => {
expect(safeMapObj(null)).toEqual({});
expect(safeMapObj(undefined)).toEqual({});
});
});

describe('safeSetArr', () => {
it('should convert Set to array', () => {
const set = new Set([1, 2, 3]);
const result = safeSetArr(set);
expect(Array.isArray(result)).toBe(true);
expect(result).toEqual([1, 2, 3]);
});

it('should return empty array if null or undefined', () => {
expect(safeSetArr(null)).toEqual([]);
expect(safeSetArr(undefined)).toEqual([]);
});
});
File renamed without changes.
File renamed without changes.
47 changes: 46 additions & 1 deletion layers/common/utils/safe-converter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
/**
* stringify, bigint as string, Map as object, Set as array
*/
export function jsonReplacer(k: string, v: unknown) {
if (typeof v === 'bigint') return v.toString();
if (v instanceof Map) return Object.fromEntries(v);
if (v instanceof Set) return Array.from(v);
return v;
}

/**
* stringify, bigint as string, Map as object, Set as array
*/
export function safeJson(obj: unknown): string {
return JSON.stringify(obj, jsonReplacer);
}

/**
* get non-null converted value
*
* @param valOrFun value or function
Expand Down Expand Up @@ -36,7 +53,7 @@ export function safeString(valOrFun: any, defaults: string = ''): string {
case 'bigint':
return String(value);
default:
return JSON.stringify(value, (_, v) => typeof v === 'bigint' ? v.toString() : v);
return safeJson(value);
}
});
}
Expand Down Expand Up @@ -144,3 +161,31 @@ export function safeKeys(valOrFun: any, defaults: string[] = []): string[] {
export function safeEntries<T>(valOrFun: any, defaults: [string, T][] = []): [string, T][] {
return safeConvert(valOrFun, defaults, Object.entries);
}

/**
* convert object to Map
*/
export function safeObjMap<T>(obj?: Record<string, T> | null): Map<string, T> {
return obj == null ? new Map() : new Map(Object.entries(obj));
}

/**
* convert array to Set
*/
export function safeArrSet<T>(arr?: T[] | null): Set<T> {
return arr == null ? new Set() : new Set(arr);
}

/**
* convert Map to object
*/
export function safeMapObj<T>(map?: Map<string, T> | null): Record<string, T> {
return map == null ? {} : Object.fromEntries(map);
}

/**
* convert Set to array
*/
export function safeSetArr<T>(set?: Set<T> | null): T[] {
return set == null ? [] : Array.from(set);
}
6 changes: 0 additions & 6 deletions layers/mobile/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# @fessional/razor-mobile

## 0.1.30

### Patch Changes

- ffa8942: ➕ pinia store #70

## 0.1.29

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion layers/mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fessional/razor-mobile",
"type": "module",
"version": "0.1.30",
"version": "0.1.29",
"description": "mobile layer with ionic and capacitor",
"main": "./nuxt.config.ts",
"scripts": {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fessional/razor",
"type": "module",
"version": "0.1.30",
"version": "0.1.29",
"description": "Use front-end tech (Nuxt/Ts) to build multi-platform from one codebase, suitable for small team and app to write app once, apply almost anywhere.",
"packageManager": "[email protected]",
"engines": {
Expand Down

0 comments on commit 57588d6

Please sign in to comment.