Skip to content

Latest commit

 

History

History
216 lines (168 loc) · 6.66 KB

README-zh_CN.md

File metadata and controls

216 lines (168 loc) · 6.66 KB

简体中文 | English

License Version Downloads

Keeper是一个用于安全访问js对象属性的库。

它通过接收一个描述对象类型的字符串来生成一个守护者实例(Keeper),通过这个实例提供的API,我们可以访问符合预期的安全数据类型,或者创建一个完全符合类型描述的新对象来使用。

Keeper还具有出色的TypeScript支持。它可以根据接收到的类型描述字符串生成相应的类型声明文件,从而无需手动创建这些文件。

一个简单的例子:

const userKeeper = createKeeper(`
  name string
  age  int    renamefrom:user_age
`);

// this type is {name: string, age: number}
const data = userKeeper.from({
  name: "bruce",
  user_age: "18.0",
});

console.log(data); // { name: 'bruce', age: 18 }
const age = userKeeper.read({ user_age: "18.2" }, "age"); // 18

📦 安装

npm i keeper-js

🔨 使用

类型描述

Keeper通过接收一个描述对象的字符串文本来定义对象,该字符遵循以下格式:

<property> <type> <extentions>
  • <property>:属性名称,支持字符串或数字。
  • <type>:属性类型,可以是基础类型(如 string、int、float,详情见下文)或数组类型(如 int[])。此外,也支持使用 *<extends> 格式来实现类型的嵌套
  • <extentions>(可选):当前属性的额外描述,目前支持<copyas>:<alias>(复制当前类型为属性名为<alias>的新属性) 以及<renamefrom>:<property>(当前属性值从源对象的<property>属性返回)

每个描述项之间以一个或多个空格隔开,对象描述支持多行,每行描述一个属性,同时也支持以//进行注释。示例:

import { createKeeper } from "keeper-js";

const userInfo = createKeeper(`
   // name
   name    string
   // age
   age     int      renamefrom:user_age
`);

const human = createKeeper(
  `
  id      int
  scores  float[]
  info    *userInfo
`,
  { extends: { userInfo } },
); // Declare the inherited attributes of userInfo.

const data = human.from({
  id: "1",
  scores: ["80.1", "90"],
  info: { name: "bruce", user_age: "18.0" },
});

// data: {
//   id: 1,
//   scores: [80.1, 90], // Transform string into float number.
//   info: {
//     name: 'bruce',
//     age:  18,   // Retrieve the value from 'user_age' and convert the float string into an integer number.
//   }
// }

对象访问

Keeper实例提供两个方法用于获取数据,from(obj)read(obj, path)分别用于根据类型描述和源对象生成一个新对象和根据类型描述获取源对象中指定path的值。

当我们需要安全获取对象中的某个值时,可以用 read API 来操作,例如

const sourceData = {
  id: "1",
  scores: ["80.1", "90"],
  info: { name: "bruce", user_age: "18.0" },
};
const name = human.read(sourceData, "id"); // 1

该方法支持多层嵌套访问,例如:

const userInfo = createKeeper(`
   name    string
   age     int      renamefrom:user_age
`);

const human = createKeeper(
  `
  id       int
  bros     *userInfo[]
  baseInfo *userInfo
`,
  { extends: { userInfo } },
); // Declare the inherited attributes of userInfo.

const sourceData = {
  id: "1",
  bros: [
    { name: "bro1", user_age: "16.0" },
    { name: "bro2", user_age: "17.2" },
  ],
  info: { name: "bruce", user_age: "18.1" },
};
const name = human.read(sourceData, "info.name"); // 'bruce'
const bro1Name = human.read(sourceData, "bros[0].name"); // 'bro1'

当我们期望从源数据修正并得到一个完全符合类型声明定义的对象时,可以用 from API 来操作,例如:

const sourceData = {
  id: "1",
  bros: [],
  info: { name: "bruce", user_age: "18.1" },
};
human.from(sourceData); // { id: 1, bros: [], { name: 'bruce', age: 18 } }

注意,当原数据为空并且对应声明属性不为空类型时(null|undefined),会根据声明的类型给出一个默认值,例如:

const sourceData = {
  id: "1",
  bros: [],
  info: {},
};
human.from(sourceData); // { id: 1, bros: [], { name: '', age: 0 } }
human.read(sourceData, "bros[0].age"); // 0

Typescript支持

Keeper拥有良好的ts支持,可以通过导出的DefineKeeperInterface类型从定义的keeper实例获取ts类型 Monosnap screencast 2024-02-24 01-12-58

除此之外,from()read方法也拥有良好的ts支持: Monosnap screencast 2024-02-24 01-22-08 Monosnap screencast 2024-02-24 01-23-19

Lazy延迟解析

createKeeper的第二个参数可以设置lazytrue,这样Keeper会在第一次访问时才解析类型,而不是在创建时就解析。

const userInfo = createKeeper(
  `
  name    string
  age     int      renamefrom:user_age
`,
  { lazy: true },
);

userInfo.properties.has("name"); // false
userInfo.get({ name: "bruce", user_age: "18.0" }, "name");
userInfo.properties.has("name"); // true

支持的类型

数据类型 对于js类型 默认值 备注
bool boolean false -
int number 0 整数类型
float number 0 浮点数类型
string string '' -
null null null -
undefined undefined undefined -
func Function () => {} -
object Object {} -

Benchmark

Files: benchmark/index.js

result: benchmark.html lazy.api.html

开源协议

Keeper 遵循 MIT 协议