Skip to content

valian-ca/fireway

Repository files navigation

Fireway

A schema migration tool for Firestore. TypeScript, ESM JavaScript (.mjs), and CommonJS JavaScript (.cjs) are supported.

Usage

Create a migration file in the functions/migration (default directory).
Name the file in the format: v[semver]__[description].ts (TypeScript), .mjs (ESM JavaScript), or .cjs (CommonJS JavaScript).

TypeScript example:

// ./migrations/v0.0.1__typescript_example.ts

import { type IMigrationFunctionsArguments } from '@valian/fireway'

export async function migrate({ firestore }: IMigrationFunctionsArguments) {
  await firestore.collection('my_table').doc('document_id').set({ name: 'Fireway' })
}

ESM JavaScript example:

// ./migrations/v0.0.1__javascript_example.mjs

export const migrate = async ({ firestore }) => {
  await firestore.collection('my_table').doc('document_id').set({ name: 'Fireway' })
}

CommonJS JavaScript example:

// ./migrations/v0.0.1__javascript_example.cjs

module.exports.migrate = async ({ firestore }) => {
  await firestore.collection('my_table').doc('document_id').set({ name: 'Fireway' })
}

Extended example

The library is using Modular SDK for app initialization. It is possible to use the app argument in migration scripts to initialize another Firebase service, for example, auth.

// ./migrations/v0.2.0__typescript_extended_example.ts
import { type IMigrationFunctionsArguments } from '@valian/fireway'
import { getAuth } from 'firebase-admin/auth'
import { FieldValue } from 'firebase-admin/firestore'

export async function migrate({ firestore, app }: IMigrationFunctionsArguments) {
  // Auth example
  const firebaseAuth = getAuth(app)
  const email = 'test-user@test.com'
  // search user identity
  const user = await firebaseAuth.getUserByEmail(email)
  if (!user) {
    await firebaseAuth.createUser({
      email: email,
      emailVerified: true,
      disabled: false,
    })
  }

  // FieldValue example
  await firestore.collection('table').doc('123').ref.update({
    obsoleteField: FieldValue.delete(),
    date: FieldValue.serverTimestamp(),
  })
}

Install

  1. Install NPM package to Firebase functions projects:

    npm i @valian/fireway

Fireway uses jiti to automatically handle TypeScript, ESM, and CommonJS migration files, so no additional configuration is required for TypeScript support.

Running locally

Most likely you'll want to test your migration scripts locally first before running them against Cloud instances.

  1. Ensure that Firestore emulator is set up in firebase.json file.

    {
      "emulators": {
        "firestore": {
          "port": 8080
        }
      }
    }
  2. Start your local emulators with

    firebase emulators:start
  3. Run migrations.

    To connect to the local emulator GCLOUD_PROJECT environment variable is required pointing to your projectId. Check .firebaserc file and the { "projects": { "default": "[project-id]" }} settings. If it is not specified, any value can be provided, e.g. "local".
    Specify FIRESTORE_EMULATOR_HOST variable pointing to your local emulator (default Firestore port is 8080).

    GCLOUD_PROJECT=project-id FIRESTORE_EMULATOR_HOST=localhost:8080 fireway migrate

    Fireway automatically handles TypeScript, ESM (.mjs), and CommonJS (.cjs) files without any additional configuration.

Migration results

Migration results are stored in the fireway collection (can be changed) in Firestore in the format v[semver]__[description].

// fireway/v0.0.1__typescript_example

{
  installed_rank: 3, // 0-based sequence
  checksum: 'fdfe6a55a7c97a4346cb59871b4ce97c',
  description: 'typescript_example',
  execution_time: 1221,
  installed_by: 'system_user_name',
  installed_on: Timestamp(),
  script: 'v0.0.1__typescript_example.ts',
  type: 'ts', // or 'mjs' for ESM, 'cjs' for CommonJS
  version: '0.0.1',
  success: true
}

Re-running script

If script execution failed, the workflow will be stopped. Running migration again will start from the latest failed script.

  1. Generate a Firebase Service Account JSON key by opening: Project Settings -> Service Accounts -> Generate new private key. Private key will have the admin role and contain your project settings.

  2. Set up CI provider to use that key. For Github Actions, add a secret to the Github repository, e.g. FIREBASE_SERVICE_ACCOUNT_JSON_DEV.

    In the Github workflow use google-github-actions/auth@v1 to load the credentials

    jobs:
      build_and_deploy:
        runs-on: ubuntu-latest
        name: Dev workflow
        steps:
          - uses: actions/checkout@v3
          - name: 'NPP install and build steps'
            run: |
              echo "your scripts"
          - name: 'Authenticate to Google Cloud'
            uses: 'google-github-actions/auth@v1'
            with:
              credentials_json: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON_DEV }}'
              create_credentials_file: true
              cleanup_credentials: true
          - name: Deploy functions and run migrations
            run: |
              npm run migrate
              firebase deploy --only functions

    where package.json scripts section has:

    "migrate": "fireway migrate"

Alternatively use GOOGLE_APPLICATION_CREDENTIALS environment variable as described in Firebase Admin Auth instructions.

CLI

Usage
  $ fireway migrate [options]

Available Commands
  migrate    Migrates schema to the latest version

For more info, run any command with the `--help` flag
  $ fireway migrate --help

Options
  --path           Path to migration files  (default "./migrations")
  --collection     Firebase collection name for migration results (default "fireway")
  --dryRun         Simulates changes
  --logLevel       Log level, options: debug, log, warn, error (default "log")
  -v, --version    Displays current version
  -h, --help       Displays this message

Contributing

Fork the repository, make changes, ensure that project is tested:

pnpm install
npm run build && pnpm run test

History

Based on ace-devs/fireway work, which was inspired by kevlened/fireway

License

MIT

About

Schema migration tool for Firestore

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 13