I wrote a CLI to migrate Appwrite databases

Alexander PanovAlexander Panov
4 min read

Over the course of the last week end I have been working on my appwrite-migration package.

In this blog post I want to show the functionality, what inspired me and how I am planning to continue this project.

Don't want to read?

Watch the video instead!

I have already recorded and published a demo video about this project. You can find it right here: https://www.youtube.com/watch?v=d1UhZmYRSHM&t=5s

Overview Functionality scope

Usage

    $ appwrite-migration [-v | --version] <command> [<args>]

Options
    --version, -v Show the CLI version
    --databaseId, -d The database id of your project. Currently not supported.
    --projectId, -p The id of your appwrite project
    --collection, -c The id of the collection that you want to operate on
    --endpoint The appwrite instance endpoint url. Defaults to "https://cloud.appwrite.com/v1"
    --file The file path for the operation
    --key The api key for your appwrite account

Commands

    login [-p | --projectId <projectId>] [--endpoint <AppwriteApiUrl>] [--key <apikey>] [--databaseId | -d <id>]
        Use this to enter your credentials. They will be stored in ${credentialsFile}

    new-migration [<migrationName>] [-d | --directory=./migrations]
        Create a new migration inside the directory.

    logout
        Clear the credentials file: ${credentialsFile}

    run [-d | --databaseId] [<migrationPath>]
        Runs the path that lies under this <migrationPath>. If the version specified in the migration is
        older than the metadata of the database. It won't be run.

    backup [-d | --databaseId] [-c | --collection <id>] [<downloadFolder>]
        Downloads all the data from all the collections (or specified within the -c flag)

    restore [-d | --databaseId][<collection> <file>]
        Restore the <collection> with the data from the provided <file>

    import [<schemaPath>]
        Creates the databases and collections from the generated schema.

    generate-schema [-d | --databaseId] [-f | --file <filepath>]
        Generates the schema and prints it out.
        If [--file] is provided stores the schema in the path.

Examples
    $ appwrite-migration --version
    $ appwrite-migration login --projectId 123893
    $ appwrite-migration run migrations/add_lastname_to_users.js -d primary
    $ appwrite-migration backup -c users -c countries ./download/ -d primary
    $ appwrite-migration restore -c users ./download/users.json -d primary

This, excluded of restore and backup, is the current functionality scope.

You can see there is the basic login command, the new-migration, run and run all commands.

Creating a migration script

new-migration is a simple generator that sets up a template for you. It is for convenience and the generated file acts as a guideline.

When creating a new migration script, the file is written to the ./migrations/ directory.

It is prefixed with the current date in seconds. This is to order them correctly. You may want to execute run-all later on. If we didn‘t keep track of the versions, we get a bad database state.

The migration script file itself has another date field. At least currently. When writing this post right now I am thinking of removing it for easier manageability. And falling back to the file name.

Anyways.. in this file you have access to a few symbols.

  1. defineMigration(migrationDate, cb) - a method that you need to call. It receives two parameters:

    1. migrationDate - acts as version and should be of type date

    2. A callback that receives just one parameter: the AppwriteMigrationClient

  1. this.databaseId - the db id it is run for

When building a migration you can call the api endpoints via the AppwriteMigrationClient.

await migrationClient
        .databases
        .createCollection(
            this.databaseId,
            'reports',
            'reports'
        );

The motivation behind it

I have been having this thought for quite a while now. It is/was a hard task to create a similar environment with Appwrite. With my approach I wanted a rails like database migration process.

  • git tracked

  • perfect for open source projects that don‘t share the same Appwrite account.

  • unified way

The projects future

I am planning to get this to a stable version. It is currently published in the name of my company. RoyalZSoftware. And I am also planning to keep it there.

I am thinking of refactoring the code a little, so that the app can be used better without relying on the cli.

Furthermore maybe I will message appwrite to give this thing a shout out, once stable.

Stay tuned and feel free to open a PR.

Did you enjoy this post?

Give it a thumbs up and share it with somebody that has been searching for a solution just like this.

Subscribe to the newsletter, to be the first who is receiving this posts.

0
Subscribe to my newsletter

Read articles from Alexander Panov directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alexander Panov
Alexander Panov

Software developer and CEO at RoyalZSoftware. I build web applications for startups with Ruby on Rails, Angular and React.