{"id":18460695,"url":"https://github.com/jou-amjs/super-inspector","last_synced_at":"2026-04-24T16:03:31.254Z","repository":{"id":57374541,"uuid":"347401067","full_name":"JOU-amjs/super-inspector","owner":"JOU-amjs","description":"🔍🔍🔍A validate library for dynamic \u0026 complex forms.And for your beautiful code","archived":false,"fork":false,"pushed_at":"2022-06-29T06:59:29.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-03T11:38:18.563Z","etag":null,"topics":["complex-form","form-validation","javascript","library","super-inspector"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JOU-amjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-13T15:04:22.000Z","updated_at":"2022-06-29T06:59:32.000Z","dependencies_parsed_at":"2022-08-29T14:51:58.874Z","dependency_job_id":null,"html_url":"https://github.com/JOU-amjs/super-inspector","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/JOU-amjs/super-inspector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JOU-amjs%2Fsuper-inspector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JOU-amjs%2Fsuper-inspector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JOU-amjs%2Fsuper-inspector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JOU-amjs%2Fsuper-inspector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JOU-amjs","download_url":"https://codeload.github.com/JOU-amjs/super-inspector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JOU-amjs%2Fsuper-inspector/sbom","scorecard":{"id":69073,"data":{"date":"2025-08-11","repo":{"name":"github.com/JOU-amjs/super-inspector","commit":"53924215a693a4d407257127b035c92d00da7ae2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/6 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-15T03:23:05.447Z","repository_id":57374541,"created_at":"2025-08-15T03:23:05.447Z","updated_at":"2025-08-15T03:23:05.447Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32230421,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["complex-form","form-validation","javascript","library","super-inspector"],"created_at":"2024-11-06T08:27:45.369Z","updated_at":"2026-04-24T16:03:31.225Z","avatar_url":"https://github.com/JOU-amjs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [Super Inspector](https://github.com/JOU-amjs/super-inspector)\n[![npm](https://img.shields.io/npm/v/super-inspector)](https://www.npmjs.com/package/super-inspector)\n![size](https://img.shields.io/bundlephobia/min/super-inspector)\n![license](https://img.shields.io/badge/license-MIT-blue.svg)\n[![Coverage Status](https://coveralls.io/repos/github/JOU-amjs/super-inspector/badge.svg)](https://coveralls.io/github/JOU-amjs/super-inspector)\n![jslib](https://img.shields.io/badge/Powered%20by-jslib%20base-brightgreen.svg)\n\n🔎🔎🔎 一个为开发动态和复杂表单而生的验证库，还为了你优雅的代码\n\n## **特性**\n1. 支持动态联合验证，通过声明依赖关系决定需要验证的值\n2. 支持定义通用错误类型\n3. 支持多层级嵌套验证器\n4. 支持异步验证\n5. 支持TypeScript\n\n## **例子**\n\u003e 可拷贝至本地并使用浏览器运行\n\nVue -\u003e [vue.example.html](https://github.com/JOU-amjs/super-inspector/blob/main/example/vue.html)\n\nReact -\u003e [react.example.html](https://github.com/JOU-amjs/super-inspector/blob/main/example/react.html)\n\n## **安装**\n```bash\n$ npm install --save super-inspector\n```\n---\n## **使用**\n### *导入*\ncommonjs(Node.js)\n```js\nvar SuperInspector = require('super-inspector').default;\n```\n\nES6 Module\n```js\nimport SuperInspector from 'super-inspector';\n```\n浏览器\n```html\n\u003cscript src=\"https://unpkg.com/super-inspector/dist/super-inspector.umd.js\"\u003e\u003c/script\u003e\n```\n\n### *创建对象*\n在原config对象上修改\n```javascript\nlet sp = new SuperInspector(config =\u003e {\n  // throwError为true时，验证失败将会抛出错误\n  // throwError为false时，调用验证函数将返回验证结果(成功或失败)\n  // 默认为false\n  config.throwError = false;\n\n  // 可自定义任意名称的通用错误集合\n  // 具体使用见api介绍\n  config.errors.falsy = (value, rule, key, extra, depValue) =\u003e {\n    return key + ' is required but got empty';\n  }\n\n  // 当验证规则中required: true时，falsyValues数组中的值将被作为判断是否为空的参考值\n  // 默认为[undefined, null]\n  config.falsyValues.push('');\n\n  // 如果验证失败，抛出或返回错误前将调用transformError钩子函数转换数据\n  config.transformError = errors =\u003e {\n    return errors.map(({ key, error }) =\u003e `[${key}]${error}`).join('\\n');\n  }\n});\n```\n返回新的config对象\n```javascript\nlet sp = new SuperInspector(config =\u003e {\n  return {\n    errors: {\n      falsy: '参数必填',\n    },\n    throwError: true,\n  };\n});\n```\n\n### *验证单个值*\n```javascript\n// 调用inspect将返回Promise对象\n// 验证通过时，result的值为{code: 'ok', error: ''}\n// 验证失败时，result的值为{code: 'fail', error: '错误信息'}\nlet result = await sp.inspect(1314520, Number);\n```\n### *批量验证多个值*\n```javascript\n// 调用batchInspect将返回Promise对象\nlet result = await sp.batchInspect({\n  username: 'John123',\n  password: 'qwertyu12',\n}, {\n  username: String,\n  password: /^.{8,20}$/,\n});\n```\n\n### *动态联合验证*\n```javascript\n// 以登录举例，当loginType的值为username时，username、password才会进行验证\n// 当loginType的值为mobile时，mobileNumber和captcha才会进行验证\n// 具体验证规则可查看api介绍\nlet result = await sp.batchInspect({\n  loginType: 'username',\n  username: 'John123',\n  password: 'qwertyu12',\n\n  mobileNumber: '',\n  captcha: '',\n}, {\n  loginType: /^(username|mobile)$/,\n  username: {\n    // required默认为true，因此这边也可以省略\n    required: true,\n    validator: String,\n    deps: {\n      // 表示当loginType的值符合次正则表达式时，username值才会进行验证\n      // 也可以设置多个依赖项，只要其中一项验证通过，该值会进行验证\n      loginType: /^username$/\n    },\n  },\n  password: {\n    validator: /^.{8,20}$/,\n    deps: {\n      loginType: /^username$/\n    }\n  },\n  mobileNumber: {\n    validator: /^.{8,20}$/,\n    deps: {\n      loginType: /^mobile$/\n    }\n  },\n  captcha: {\n    validator: /[0-9]{6}/,\n    deps: {\n      loginType: /^mobile$/\n    }\n  },\n});\n```\n### *自定义验证器*\n同步\n```javascript\n// 自定义函数参数分别为：验证值、验证规则、验证key(调用只有batchInspect时才有值)、依赖项的值(验证规则声明了依赖项时才有值)\n// 通过new Error抛出错误不会被验证库捕获，因此只能通过this.throw抛出抛出错误表示验证失败\n// 不抛出错误表示验证通过\nlet result = await sp.inspect(\n  '[1,2,3].join(\",\")',\n  function(value, rule, key, depValue) {\n    if (!value) {\n      // 抛出自定义内容的错误(表示验证失败)\n      this.throw(key + '的值不能为空');\n    }\n    else if (/\u003c[a-zA-Z]{1,10}\u003e/.test(value)) {\n      // 抛出一个通用异常(创建对象时配置)表示验证失败\n      this.throw.containHtmls();\n    }\n  }\n);\n```\n异步\n```javascript\n// 声明异步函数，也可以声明一个返回promise对象的普通函数\nlet result = await sp.inspect(\n  'john@gmail.com',\n  async function(value, rule, key, depValue) {\n    let validRes = await fetch('https://host?email=' + value)\n    .then(response =\u003e response.json());\n    if (validRes.code !== 200) {\n      this.throw('邮箱地址已被占用');\n    }\n  }\n);\n```\n### *内置的验证器*\n数组验证器(验证数组项)\n```javascript\nimport { $Array } from 'super-inspector';\n// 验证数组每项的值是否为图片(数组简单项)\nlet result1 = await sp.inspect([\n  'https://img1.png',\n  'https://img2.jpg'\n], $Array(/(png|jpg|jpeg|webp)$/));\n\n// 验证批量添加的人员信息(数组复杂项)\nlet result2 = await sp.inspect([\n  { avatar: '', name: 'Ann', age: 24 },\n  { avatar: 'https://avatar1.png', name: 'Tom', age: 26 },\n], $Array({\n  avatar: { required: false, validator: /^(png|jpg|jpeg|webp)$/ },\n  name: String,\n  age: Number\n}));\n```\n对象验证器(验证对象值)\n```javascript\nimport { $Object } from 'super-inspector';\n// 验证每个人的头像是否为图片(对象简单值)\nlet result1 = await sp.inspect({\n  avatar_Ann: 'https://img1.png',\n  avatar_Tom: 'https://img2.jpg'\n}, $Object(/(png|jpg|jpeg|bmp|webp)$/));\n\n// 验证每个人的位置是否正确(对象复杂值)\nlet reuslt2 = await sp.inspect({\n  coordinate_Ann: { lat: 24.443729, lng: 118.128319 },\n  coordinate_Ann: { lat: 32.827119, lng: 120.293013 },\n}, $Object({\n  lat: Number,\n  lng: Number\n}));\n```\n\n联合验证器(等价于\"或\")\n```javascript\nimport { $Union } from 'super-inspector';\n// 满足$Union中其中一个验证规则可通过\nlet result1 = await sp.inspect(\n  'https://img1.png',\n  $Union(/png$/, /jpg$/, /jpeg$/, /webp$/)\n);\n\n// 与$Array嵌套使用\nlet res = await sp.inspect([\n  'https://img1.png',\n  'https://img2.jpg'\n], $Array(\n  $Union(/png$/, /jpg$/, /jpeg$/, /webp$/)\n));\n```\n\n交叉验证器(等价于\"与\")\n```javascript\nimport { $Intersect } from 'super-inspector';\n// 满足$Intersect中所有验证规则才可通过\nlet res = await sp.inspect('javascript', $Intersect(String, function(value) {\n  if (value.length \u003c 8) {\n    this.throw('必须填写至少8个字符');\n  }\n}));\n```\n### *错误类型*\n针对错误信息的需求，super-inspector提供了3种错误类型\n1. 多个表单项需要返回相同的错误信息时，在创建对象时定义若干个通用错误类型\n```javascript\n// 创建验证对象\nlet sp = new SuperInspector(config =\u003e {\n  // 固定错误使用字符串\n  config.errors.containHtmls = '不能包含html标签';\n  // 动态错误使用函数，函数必须返回字符串\n  // extra为调用错误抛出函数时传入的额外数据\n  config.errors.exceedLength10 = (value, rule, key, extra, depValue) =\u003e {\n    return (rule.label || key) + '的长度不能超过10' + '(当前长度为' + value.length + ')';\n  }\n});\n\n// 在自定义验证器中抛出通用错误\nfunction customValidator(value) {\n  if (value.length \u003e 10) {\n    this.throw.exceedLength10();\n  }\n}\n```\n2. 自定义验证器中抛出任意的错误信息\n```javascript\nfunction customerValidator() {\n  this.throw('自定义的错误信息');\n}\n```\n3. 特定表单项需要返回特定的错误信息时，可在验证规则中指定替换的错误信息\n```javascript\n// 当自定义验证器中抛出错误时，result内的信息会被替换为error字段中的信息\nlet result = await sp.inspect(\n  '[1,2,3].join(\",\")',\n  {\n    error: '文本信息不能为空，且不能包含html标签信息',\n    validator: function(value, rule, key, depValue) {\n      if (!value) {\n        // 抛出自定义内容的错误(表示验证失败)\n        this.throw(key + '的值不能为空');\n      }\n      else if (/\u003c[a-zA-Z]{1,10}\u003e/.test(value)) {\n        // 抛出一个通用异常(创建对象时配置)表示验证失败\n        this.throw.containHtmls();\n      }\n    }\n  }\n);\n```\n\n### *导出参与验证的项*\n在动态表单中，我们通常需要将不参与验证的表单项隐藏，`affectedItems`函数将会告诉我们哪些表单项需要参与验证，哪些不需要\n```javascript\n// result的值为{ loginType: true, username: true, password: true, mobileNumber: false, captcha: false }\n// 我们可根据此数据隐藏值为false的表单项\nlet result = await sp.affectedItems({\n  loginType: 'username',\n  username: 'John123',\n  password: 'qwertyu12',\n\n  mobileNumber: '',\n  captcha: '',\n}, {\n  loginType: /^(username|mobile)$/,\n  username: {\n    // required默认为true，因此这边也可以省略\n    required: true,\n    validator: String,\n    deps: {\n      // 表示当loginType的值符合次正则表达式时，username值才会进行验证\n      // 也可以设置多个依赖项，只要其中一项验证通过，该值会进行验证\n      loginType: /^username$/\n    },\n  },\n  password: {\n    validator: /^.{8,20}$/,\n    deps: {\n      loginType: /^username$/\n    }\n  },\n  mobileNumber: {\n    validator: /^.{8,20}$/,\n    deps: {\n      loginType: /^mobile$/\n    }\n  },\n  captcha: {\n    validator: /[0-9]{6}/,\n    deps: {\n      loginType: /^mobile$/\n    }\n  },\n});\n```\n\n## **APIs**\n[点此查看API文档](https://github.com/JOU-amjs/super-inspector/blob/main/API.md)\n\n\n## **后项**\n- [提交一个issue](https://github.com/JOU-amjs/super-inspector/issues)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjou-amjs%2Fsuper-inspector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjou-amjs%2Fsuper-inspector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjou-amjs%2Fsuper-inspector/lists"}