{"id":16321475,"url":"https://github.com/doodlewind/bumpover","last_synced_at":"2025-09-11T13:10:32.448Z","repository":{"id":57191499,"uuid":"115863946","full_name":"doodlewind/bumpover","owner":"doodlewind","description":"🚧 Async data transforming with simple rules.","archived":false,"fork":false,"pushed_at":"2018-01-16T03:23:31.000Z","size":231,"stargazers_count":65,"open_issues_count":4,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-24T01:30:33.972Z","etag":null,"topics":["data","json","markup","migration","tree","validation","xml"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/doodlewind.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2017-12-31T13:15:00.000Z","updated_at":"2024-01-13T23:57:42.000Z","dependencies_parsed_at":"2022-09-01T00:52:43.826Z","dependency_job_id":null,"html_url":"https://github.com/doodlewind/bumpover","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/doodlewind/bumpover","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doodlewind%2Fbumpover","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doodlewind%2Fbumpover/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doodlewind%2Fbumpover/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doodlewind%2Fbumpover/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doodlewind","download_url":"https://codeload.github.com/doodlewind/bumpover/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doodlewind%2Fbumpover/sbom","scorecard":{"id":352164,"data":{"date":"2025-08-11","repo":{"name":"github.com/doodlewind/bumpover","commit":"6bfb9785a276dece7255a0a52583989f0263ff93"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"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":"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":"Code-Review","score":0,"reason":"Found 0/20 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":"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":"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":"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":"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":"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 'master'"],"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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 18 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"76 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-rq8g-5pc5-wrhr","Warn: Project is vulnerable to: GHSA-hr2v-3952-633q","Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm","Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h","Warn: Project is vulnerable to: GHSA-qrmc-fj45-qfc2","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-8r6j-v8pm-fqw3","Warn: Project is vulnerable to: MAL-2023-462","Warn: Project is vulnerable to: GHSA-xf7w-r453-m56c","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-q42p-pg8m-cqh6","Warn: Project is vulnerable to: GHSA-w457-6q6x-cgp9","Warn: Project is vulnerable to: GHSA-62gr-4qp9-h98f","Warn: Project is vulnerable to: GHSA-f52g-6jhx-586p","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-44pw-h2cw-w3vq","Warn: Project is vulnerable to: GHSA-jp4x-w63m-7wgm","Warn: Project is vulnerable to: GHSA-c429-5p7v-vgjp","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-4hpf-3wq7-5rpr","Warn: Project is vulnerable to: GHSA-f522-ffg8-j8r6","Warn: Project is vulnerable to: GHSA-p9w8-2mpq-49h9","Warn: Project is vulnerable to: GHSA-2pr6-76vf-7546","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-282f-qqgm-c34q","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-fvqr-27wr-82fm","Warn: Project is vulnerable to: GHSA-4xc9-xhrj-v574","Warn: Project is vulnerable to: GHSA-x5rq-j2xg-h7qm","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-2m96-9w4j-wgv7","Warn: Project is vulnerable to: GHSA-h726-x36v-rx45","Warn: Project is vulnerable to: GHSA-4xcv-9jjx-gfj3","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-6g33-f262-xjp4","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-2m39-62fm-q8r3","Warn: Project is vulnerable to: GHSA-mf6x-7mm4-x2g7","Warn: Project is vulnerable to: GHSA-j44m-qm6p-hp7m","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-38fc-wpqx-33j7","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T08:36:51.436Z","repository_id":57191499,"created_at":"2025-08-18T08:36:51.436Z","updated_at":"2025-08-18T08:36:51.436Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274640910,"owners_count":25322843,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["data","json","markup","migration","tree","validation","xml"],"created_at":"2024-10-10T22:47:54.322Z","updated_at":"2025-09-11T13:10:32.424Z","avatar_url":"https://github.com/doodlewind.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"./docs/images/banner.png\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Async data transforming with simple rules.\n\u003c/p\u003e\n\n\u003cbr/\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e •\n  \u003ca href=\"#why\"\u003eWhy\u003c/a\u003e •\n  \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e •\n  \u003ca href=\"#examples\"\u003eExamples\u003c/a\u003e •\n  \u003ca href=\"#documentation\"\u003eDocumentation\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/doodlewind/bumpover\"\u003e\n    \u003cimg src=\"https://travis-ci.org/doodlewind/bumpover.svg?branch=master\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/doodlewind/bumpover?branch=master\"\u003e\n    \u003cimg src=\"https://img.shields.io/coveralls/doodlewind/bumpover/master.svg?style=flat\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://unpkg.com/bumpover/lib/bumpover.min.js\"\u003e\n    \u003cimg src=\"http://img.badgesize.io/https://unpkg.com/bumpover/lib/bumpover.min.js?compression=gzip\u0026amp;label=size\u0026amp;maxAge=300\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://standardjs.com\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/code_style-standard-brightgreen.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"./package.json\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/bumpover.svg?maxAge=300\u0026label=version\u0026colorB=007ec6\u0026maxAge=300\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"./LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/l/bumpover.svg?maxAge=300\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://juejin.im/post/5a4eaf63f265da3e2744f649\"\u003e\n    \u003cimg src=\"https://badge.juejin.im/entry/5a4ecbf56fb9a01c9405a44d/likes.svg?style=flat\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nBumpover helps you writing data validation \u0026 migration script in a controllable and reliable way, which can be tedious and leaky with your bare arms.\n\nBy utilizing type annotation powered by [superstruct](https://github.com/ianstormtaylor/superstruct), it's super straightforward to define your own complex data types, leaving bumpover deal with your data at runtime. Besides XML and JSON support out of the box, you can even customize bumpover with your own parser, bumping any data format interchangeable with JSON.\n\n\n## Features\n\n* Declarative XML/JSON data validating and upgrading.\n* Friendly type annotation with recursive data shape support.\n* Promise-based async node upgrading, handy for external or linked data shape. e.g., grab image by link defined in XML node, upload it to your cloud storage, then update new node's `src` on response ends.\n* Configurable traversing mechanism, e.g., whether returning beforehand or filtering out unknown nodes.\n* Pluggable serializer and deserializer, supporting new data format in merely tens of lines.\n\n\n## Why\n\nStable data structure is essential for a robust app, while during continual iteration, data structure **always** changes frequently. One common approach for compatibility is introducing more COMPAT code in business logic, which works but quickly stales codebase, sometimes with incompatible versions of data this is even not possible (Think about `.doc` and `.docx`). So here comes the necessity of data migration.\n\nWith modern web, it's trivial to ensure latest version of app code deployed on client. While for user data stored in DB, the difficulty upgrading them with script is pretty underestimated. Especially for data serialized and stored as string, parsing and migrating them can be formidable. Writing script transforming `'\u003cp\u003e123\u003c/p\u003e'` to `{ paragraph: 123 }` is one thing, ensuring validity for gigabytes of data is another - And this is what bumpover is designed to handle.\n\nAnother scenario utilizing bumpover is sanitizing. Say you're working with a rich content editor whose data model supports nesting, it's essential to ensure valid data structure after each user input event, e.g., pasting and dragging. Generally you'll want to write declarative rules normalizing data, and this is also what bumpover offers.\n\nFor cases mentioned above, there are existing **runtime** data validation tools that helps, while they're not really popularized when compared with **compile time** type analysis tools, e.g., [TypeScript](https://www.typescriptlang.org/docs/handbook/basic-types.html) and [Flow](https://flow.org/en/docs/types/). Runtime data validation tools generally offers heavier API without much customizability, making them less friendly to work with. As an alternative, [superstruct](https://github.com/ianstormtaylor/superstruct) provides precise runtime data validation with a grammar closer to pure type annotations, making it powerful to express complex data types. Since bumpover relies deeply on it, it takes the advantage of superstruct to express your custom types and rules.\n\n\n## Usage\n\n\u003e Before getting started, remember to install dependencies:\n\n```\nnpm install --save bumpover superstruct\n```\n\nThen you can import them into your code base:\n\n``` js\nimport { Bumpover } from 'bumpover'\nimport { struct } from 'superstruct'\n```\n\nWith superstruct you can define your own data schema. Say you'd like to verify a node in virtual DOM tree with such shape:\n\n``` js\nconst maybeNode = {\n  name: 'div',\n  props: { background: 'red' },\n  children: []\n}\n```\n\nWe can define a struct validating this structure:\n\n``` js\nimport { struct } from 'superstruct'\n\nconst Node = struct({\n  name: 'string',\n  props: 'object?',\n  children: 'array'\n})\n```\n\nNow we can use `Node` struct to validate data. You can simply call it as a function:\n\n``` js\nNode(maybeNode)\n```\n\nDetailed error will be thrown if data doesn't conform to the `Node` shape, or return the validated data when validation succeeds.\n\nNow suppose we'd like to transform the virtual DOM data above by replacing all `div` tags with `span` tags, keeping all other nodes intact. How do we handle this with reliability? You can manually traverse data, or, simply define `rules`:\n\n``` js\nimport { Bumpover } from 'bumpover'\n\nconst rules = [\n  {\n    match: node =\u003e node.name === 'div',\n    update: node =\u003e Promise.resolve({\n      node: { ...node, name: 'span' }\n    })\n  }\n]\n\nconst bumper = new Bumpover(rules)\nbumper.bump(data).then(console.log)\n\n// Receive new node data.\n```\n\nSimply providing rules converting nodes, then bumpover will walk and transform data for you. Several points:\n\n* Rules are the single source of truth implementing your transform logic.\n* Use `rule.match` to match the node you'd like to transform.\n* Use `rule.update` to update node inside promise, which allows async updating.\n* Wrap new node inside `node` field to be resoveld.\n\n\n## Examples\n\nTry out the [live demo on JSFiddle](https://jsfiddle.net/oqpar65u/2/) to get an idea for how the API works, or to quickly verify your use case. More examples can be found in the [walkthrough](./docs/walkthrough.md) guide.\n\n- [Bumping With Struct Validation](./docs/walkthrough.md#bumping-with-struct-validation)\n- [Bumping XML String](./docs/walkthrough.md#bumping-xml-string)\n- [Bumping Custom Data Format](./docs/walkthrough.md#bumping-custom-data-format)\n- [Async Data Bumping](./docs/walkthrough.md#async-data-bumping)\n- [Return Beforehand](./docs/walkthrough.md#return-beforehand)\n- [Keep or Discard Unknown Nodes](./docs/walkthrough.md#keep-or-discard-unknown-nodes)\n\n\nSee [examples](./examples) for more working examples (WIP).\n\n\n## Documentation\n\nCheck out [API reference](./docs/reference.md) for more details.\n\n\n## Contribution\n\nIssues and pull requests are welcomed! This project is still in its very early age, all kinds of help are precious and appreciated.\n\n\n## License\n\nThis package is [MIT-licensed](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoodlewind%2Fbumpover","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoodlewind%2Fbumpover","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoodlewind%2Fbumpover/lists"}