{"id":41782389,"url":"https://github.com/dividedbyzeroco/wander-cli","last_synced_at":"2026-01-25T04:04:28.614Z","repository":{"id":31994151,"uuid":"131263392","full_name":"dividedbyzeroco/wander-cli","owner":"dividedbyzeroco","description":"Migrations for modern web apps","archived":false,"fork":false,"pushed_at":"2022-09-16T21:56:03.000Z","size":2229,"stargazers_count":1,"open_issues_count":8,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-25T05:42:00.617Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dividedbyzeroco.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-27T07:43:51.000Z","updated_at":"2019-06-19T10:19:55.000Z","dependencies_parsed_at":"2022-08-07T17:01:20.311Z","dependency_job_id":null,"html_url":"https://github.com/dividedbyzeroco/wander-cli","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dividedbyzeroco/wander-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dividedbyzeroco%2Fwander-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dividedbyzeroco%2Fwander-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dividedbyzeroco%2Fwander-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dividedbyzeroco%2Fwander-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dividedbyzeroco","download_url":"https://codeload.github.com/dividedbyzeroco/wander-cli/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dividedbyzeroco%2Fwander-cli/sbom","scorecard":{"id":345306,"data":{"date":"2025-08-11","repo":{"name":"github.com/dividedbyzeroco/wander-cli","commit":"81e941e0201633ab396a666ec6955ef81488a2aa"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.3,"checks":[{"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":"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":"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":"Code-Review","score":0,"reason":"Found 1/29 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":"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":"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"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 2 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":"28 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","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-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-3gx7-xhv7-5mx3","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","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-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-8hfj-j24r-96c4","Warn: Project is vulnerable to: GHSA-wc69-rhjr-hc9g","Warn: Project is vulnerable to: GHSA-56x4-j7p9-fcf9","Warn: Project is vulnerable to: GHSA-v78c-4p63-2j6c","Warn: Project is vulnerable to: GHSA-3j8f-xvm3-ffx4","Warn: Project is vulnerable to: GHSA-4p35-cfcx-8653","Warn: Project is vulnerable to: GHSA-7f3x-x4pr-wqhj","Warn: Project is vulnerable to: GHSA-jpp7-7chh-cf67","Warn: Project is vulnerable to: GHSA-q6wq-5p59-983w","Warn: Project is vulnerable to: GHSA-j9fq-vwqv-2fm2","Warn: Project is vulnerable to: GHSA-pqw5-jmp5-px4v","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"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-18T06:54:34.564Z","repository_id":31994151,"created_at":"2025-08-18T06:54:34.564Z","updated_at":"2025-08-18T06:54:34.564Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28742983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T02:46:29.005Z","status":"ssl_error","status_checked_at":"2026-01-25T02:44:29.968Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":[],"created_at":"2026-01-25T04:04:27.908Z","updated_at":"2026-01-25T04:04:28.609Z","avatar_url":"https://github.com/dividedbyzeroco.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wander\n\nDatabase Migrations for Modern Apps\n\n# Introduction\n\n__Wander__ is a command-line tool that enables programmable database changes. Through __Migrations__, you can version control your database and easily `commit` or `revert` changes between versions.\n\n# Supported Databases\n\nCurrently, only `mysql` is supported. Adapters for other databases are still under development.\n\n+ \u0026check; MySQL\n+ \u0026cross; PostgreSQL\n+ \u0026cross; SQL Server\n+ \u0026cross; Oracle DB\n\n# Getting Started\n\nTo get started, globally install `wander-cli`\n\n```bash\n\u003e npm install -g wander-cli\n```\n\n# Initializing Wander\n\nTo initialize a new `wander` project, run `wander init` inside your project folder\n\n```bash\n\u003e mkdir MyDatabase\n\u003e cd MyDatabase\n\u003e wander init\n```\n\nThis will ask you for the name of your `migrations` folder (default: `./migrations`) and your database URI. Once completed, you can now start using wander.\n\n# Changing environments\n\n`wander` supports migrations for different environments. To change your current `wander` environment, run `wander env` inside your project folder\n\n```bash\n\u003e wander env\n```\n\n# Creating a new Migration\n\nTo create a new migration, run `wander new \u003cname\u003e`.\n\n```bash\n\u003e wander new create_post\n```\n\nThis will create a new file inside your `migrations` folder\n\n```markdown\n+ migrations\n  - v1_0_0__create_post.js\n+ wrconfig.json\n+ .gitignore\n```\n\n\u003e Note that you can change the type of version that your new migration will use, using the `-t` or `--version-type` option.\n\n```\n{major}.{minor}.{patch}\n```\n\n__Version Commands:__\n+ major: `wander new create_post -t major` (e.g. 2.0.0)\n+ minor: `wander new crete_post -t minor` (e.g. 1.1.0)\n+ patch: `wander new create_posrt -t patch` (e.g. 1.0.1)\n\nOnce created, the file would look similar to the following.\n\n**v1_0_0__create_post.js**\n```javascript\nmodule.exports = {\n    version() {\n        return '1.0.0';\n    },\n    description() {\n        return `Create post`;\n    },\n    async up({}) {\n    },\n    async down({}) {\n    }\n};\n```\n\n__Description__\n\n+ The `version` method returns the version name of your migration.\n+ The `description` method returns the a brief description of your database changes. You can expand this as you wish.\n+ The `up` method runs whenever the migration is committed\n+ The `down` method runs whenever the migration is reverted\n\nFor the `up` and `down` methods, an object is passed to them for your usage, which includes serveral useful functions. Check the [API](#api) section for more information.\n\n__Example__\n\n```javascript\nmodule.exports = {\n    version() {\n        return '1.0.0';\n    },\n    description() {\n        return `Create post`;\n    },\n    async up({ create, seed }) {\n        create('post', table =\u003e {\n            table.id();\n            table.string('caption');\n            table.timestamps();\n        });\n\n        seed('post', [\n            { caption: 'New post!' },\n            { caption: 'Another post!' }\n        ]);\n    },\n    async down({ drop, truncate }) {\n        truncate('post');\n        drop('post');\n    }\n};\n```\n\n# API\n\n## create\n\n__Parameters__\n\n| Paramter   | Data type                          |\n| ---------- | ---------------------------------- |\n| tableName  | string                             |\n| definition | (table: [Table](#table)) =\u003e void   |\n\n__Description__\n\n+ Accepts a __tableName__ that you want to create, and a definition function.\n+ The definition function has a [Table](#table) parameter that allows you to define the structure of your table.\n\n__Example__\n\n```javascript\ncreate('post', table =\u003e {\n    table.id();\n    table.string('caption');\n    table.timestamps();\n});\n```\n\n## alter\n\n__Parameters__\n\n| Paramter   | Data type                                |\n| ---------- | ---------------------------------------- |\n| tableName  | string                                   |\n| definition | (table: [Table](#table-class)) =\u003e void   |\n\n__Description__\n\n+ Accepts a __tableName__ that you want to alter, and a definition function.\n+ The definition function has a [Table](#table-class) parameter that allows you to define the structure of your table.\n\n__Example__\n\n```javascript\nalter('comment', table =\u003e {\n    table.integer('comment_count').add();\n});\n```\n\n## drop\n\n__Parameters__\n\n| Paramter   | Data type                          |\n| ---------- | ---------------------------------- |\n| tableName  | string                             |\n\n__Description__\n\n+ Accepts a __tableName__ that you want to drop.\n\n__Example__\n\n```javascript\ndrop('comment');\n```\n\n## seed\n\n__Parameters__\n\n| Paramter   | Data type                          |\n| ---------- | ---------------------------------- |\n| tableName  | string                             |\n| seeds      | object[]                           |\n\n__Description__\n\n+ Accepts a __tableName__ that you want to seed with data.\n+ Accepts a __seeds__ array of objects defining the data you want to insert.\n\n\u003e __NOTE:__ Only the columns of the first item in the list will define the columns that will be populated for all of the items.\n\n__Example__\n\n```javascript\nseed('post', [\n    { caption: 'A new post!' },\n    { capton: 'Another post' }\n]);\n```\n\n## truncate\n\n__Parameters__\n\n| Paramter   | Data type                          |\n| ---------- | ---------------------------------- |\n| tableName  | string                             |\n\n__Description__\n\n+ Accepts a __tableName__ that you want to truncate.\n\n__Example__\n\n```javascript\ntruncate('comment');\n```\n\n## execute\n\n__Parameters__\n\n| Paramter   | Data type                          |\n| ---------- | ---------------------------------- |\n| query      | string                             |\n\n__Description__\n\n+ Ideal for running scripts that are too complex or are too specific to the database you are running.\n+ Accepts a __query__ that you want to execute.\n\n\u003e WARNING: Running execute is very dangerous especially if the keys and values you are trying to use are not properly escaped.\n\n__Example__\n\n```javascript\nexecute(`\n    SET sql_safe_updates = 0;\n    UPDATE post SET updated_at = now() WHERE id \u003e 5;\n`);\n```\n\n\n# __Table__ class\n\n__Description__\n\n+ Allows you to define the structue of your table via different methods\n\n__Methods__\n\n+ id(`columnName`?: string) \n    - Adds a primary auto_increment key (default: `id`)\n+ string(`columnName`: string, `length`?: number)\n    - Adds a string column (e.g. on MySQL this is equivalent to `varchar`)\n+ text(`columnName`: string)\n    - Adds a text column (unlike string, there is no limit to the length)\n+ integer(`columnName`: string, `length`?: number)\n    - Adds an integer column\n+ float(`columnName`: string, `length`?: number, `precision`?: number)\n    - Adds a float column\n+ decimal(`columnName`: string, `length`?: number, `precision`?: number)\n    - Adds a decimal column\n+ double(`columnName`: string, `length`?: number, `precision`?: number)\n    - Adds a double column\n+ date(`columnName`: string)\n    - Adds a date column\n+ datetime(`columnName`: string)\n    - Adds a datetime column\n+ boolean(`columnName`: string)\n    - Adds a boolean column (e.g. on MySQL this is equivalent to `bit`)\n+ json(`columnName`: string)\n    - Supported in `MySQL 5.7+`\n+ char(`columnName`: string, `length`?: number)\n    - Adds a char data type column\n+ timestamps()\n    - Creates `created_at`, `updated_at` and `deleted_at` datetime columns\n+ index(`columnName`: string, `alias`?: string)\n    - Create an index on the table\n+ unique(`columnName`: string, `alias`?: string)\n    - Create a unique index on the table\n\nYou can also specify specific options for creation.\n\n+ nullable(`isNullable`?: boolean)\n    - Determine whether the field should be nullable or not nullable\n+ increments()\n    - State that the field should auto-increment\n\n## Key Actions\n\nIn addition, when using the `alter` option, the above methods have specific actions that need to be defined in order to let `wander` know how the columns are going to be changed.\n\n+ add()\n    - Add the column/index/unique key\n+ modify()\n    - Modify the column\n+ drop()\n    - Drop the column/index/unique key\n\nYou can also specify specific options for the alteration.\n\n+ nullable(`isNullable`?: boolean)\n    - Determine whether the field should be nullable or not nullable\n+ increments()\n    - State that the field should auto-increment\n+ first(`column`?: string)\n    - Determine the position of the column\n+ after(`column`?: string)\n    - Determine the position of the column\n\n__Example__    \n\n```javascript\nalter('comment', table =\u003e {\n    table.integer('comment_count').add();\n    table.index('IDENT').drop();\n});\n```\n\n# Sample migration\n\n```javascript\nmodule.exports = {\n    version() {\n        return '1.0.0';\n    },\n    description() {\n        return `\n            Created the post table.\n            Changed the comment table.\n            Populated the post table.\n        `;\n    },\n    async up({ create, alter, seed, execute }) {\n        create('post', table =\u003e {\n            table.id();\n            table.string('caption', 500);\n            table.pointer('user');\n            table.json('info');\n            table.string('identifier');\n            table.index('identifier', 'IDENT');\n            table.timestamps();\n        });\n\n        // Equivalent to the following\n        `\n        CREATE TABLE post (\n        id int AUTO_INCREMENT,\n        caption varchar(500),\n        user_id int(11),\n        info json,\n        identifier varchar(30),\n        PRIMARY KEY (id),\n        INDEX IDENT (identifier));\n        `\n\n        alter('comment', table =\u003e {\n            table.integer('like_count').add();\n            table.string('message', 250).modify();\n            table.pointer('post').drop();\n            table.index('IDENT').drop();\n        });\n\n        // Equivalent to the following\n        `\n        ALTER TABLE comment \n        ADD COLUMN like_count int,\n        MODIFY COLUMN message varchar(250),\n        DROP COLUMN post_id;\n        `\n\n        seed('post', [\n            { caption: 'New caption!' },\n            { caption: 'New caption!' },\n            { caption: 'New caption!' }\n        ]);\n\n        // Equivalent to the following\n        `\n        INSERT INTO post\n        (caption)\n        VALUES\n        ('New caption!'),\n        ('New caption!'),\n        ('New caption!');\n        `\n\n        execute(`\n            SET sql_safe_updates = 0;\n            UPDATE post SET privacy = 'public' WHERE role IS NULL;\n        `);\n    },\n    async down({ alter, drop, truncate }) {\n\n        truncate('post');\n        drop('post');\n\n        alter('comment', () =\u003e {\n            this.integer('like_count').drop();\n            this.string('message', 500).modify();\n            this.pointer('post').add();\n            this.index('identifier', 'IDENT').add();\n        });\n\n        execute(`UPDATE post SET privacy = 'private' WHERE role IS NULL`);\n    }\n};\n```\n\n# Committing Pending Migrations\n\nAfter you've set up your migrations, you can now commit them. To commit pending migrations, run the command below.\n\n```bash\n\u003e wander commit\n```\n\nYou can apply the `--verbose` or `-v` flag to see the actual scripts being run. Note that `wander` runs the migrations in the order of their version number.\n\n# Reverting Commited Migrations\n\nTo revert migrations you've already committed, run the following command.\n\n```bash\n\u003e wander revert\n```\n\nLike `commit`, you can apply the `--verbose` or `-v` flag to see the actual scripts being run. Also, you can specify the `--count` or `-c` parameter in order to tell `wander` how many migrations are going to be reverted, starting from the latest version.\n\n# Resetting All Migrations\n\nTo reset all migrations, run the command below.\n\n```bash\n\u003e wander reset\n```\n\nLike the previous commands, you can apply the `--verbose` or `-v` flag to see the actual scripts being run. The commands are reset from latest to oldest version.\n\n# Up versus Down\n\nIn terms of the `Migrations` standard for databases, the convention is to always have `up` and `down` methods. \n\nThe purpose of the `up` method is to commit the changes you want to apply to the database. Conversely, it is required that you undo everything that you performed, inside the `down` method.\n\nThe reason why this practice is observed is that it allows you, to some extent, to recover from a breaking change that was executed accidentally. Also, it allows you to ensure consistency when changing between database versions.\n\nDo note, however, that unless a `seed` option is defined inside the methods, any data that was __truncated__ or __dropped__ will be __lost__ forever.\n\n# Transactions\n\nFor `wander`, all migrations are executed as a single transaction. That means the [MigrationOptions](#migrationoptions-object) you used will not be fired until the processor has gone through all of them. \n\nThat also means that if anything goes wrong, the scripts will be rolled back (except for cases where database auto-commits occur). See the corresponding manuals of your databases for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdividedbyzeroco%2Fwander-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdividedbyzeroco%2Fwander-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdividedbyzeroco%2Fwander-cli/lists"}