generator-realm-migration
v1.1.7
Published
A generator for creating linear migration objects for realm-js(i.e. schemas, scheamVersion, migrationFunction tuples)
Downloads
4
Maintainers
Readme
Realm Migration Generator
A generator for creating linear migrations for realm-js projects
Index
- Summary
- Getting Started
- Usage
- Commands
- Todo
Summary
- This generator will created a
mirgrations
directory. - In that directory there will be sub directories for each migration that contain previous versions of the ObjectSchema for each Model.
- The subdirectories are named after the schema description for that migration and the computed schema version(i.e. 0-added-dogs_object_schema).
- In addition there is a
migration.js
file generated in each sub directory that is responsible for doing the migration business logic to reach that schema version. - The scaffolded
migrations
directory is intended to expose an array of linear migrations that could consumed by client code.
Getting Started
- Install
yeoman
globally:npm i -g yeoman
- Install
generator-realm-migration
:npm i --save generator-realm-migration
- From your React Native project dir run:
yo realm-migration:init
- Then after adding some Models to your models directory, run:
yo realm-migration --schemaDesc="updated_one_of_my_tables"
Usage
Requirements
- MODELS DIRECTORY : You must have one. In that directory you should have [Realm.ObjectClass](the https://realm.io/docs/javascript/1.1.1/api/Realm.html#~ObjectClass) files only. An
index.js
file in the only exception. - MODEL FILES : Each must have named export for an [Realm.ObjectClass](the https://realm.io/docs/javascript/1.1.1/api/Realm.html#~ObjectClass) that matches the file name minus the extension.
- MIGRATIONS DIRECTORY : You will have one after running the init command:
yo realm-migration:init
. This default command(i.eyo realm-migration
) will scaffold migration directories in there and update theindex.js
file for the benefit of importing the export of each migration directory.
User Input for Default Command
- The default command will ask you to delete a temp Directory. This is normal because we create that directory for transpilation purposes so that we can consume the output.
- The default command will ask you to overwrite the
migrations/index.js
file. This is normal because you will continue to add more migrations which necessitates an update of that file.
Example Command Usage
- Default Command
- All option defaults:
yo realm-migration
- With schema change description option:
yo realm-migration --schemaDesc="added-dog_object_schema"
- With all options specified:
yo realm-migration --schemaDesc="added-dog_object_schema" --objectSchemaFileSuffix='Model' --schemaVersion="0" --isTypescript=1 --sourceDir="source/" --modelDir='resources/models/' --migrationDir="config/migrations/"
- All option defaults:
- Init Command
- All option defaults:
yo realm-migration:init
- With all options specified:
yo realm-migration:init --migrationDir="source/config/migrations/" --isTypescript=1
- All option defaults:
Full Example with Source and Output Files
Structure
Beggining Structure
/ /src /models Dog.ts index.js migrateRealm.js index.js ...
Structure after
yo realm-migration:init
/ /src /models Dog.js index.js /migrations index.js migrateRealm.js index.js ...
Structure after
yo realm-migration --schemaDesc='added-dog_object_schema'
/ /src /models Dog.ts index.js /migrations index.js /0-added-dog_object_schema Dog.js migration.js index.js migrateRealm.js index.js ...
Files
models/Dog.js
const schema = {
name: 'Dog',
properties: {
name: {type: 'string'},
},
};
export class Dog {
static schema = schema;
name = '';
}
models/index.js
import { Dog } from './Dog';
export const Models = [Dog];
migrations/index.js
const migrations = [];
import migration1 from './0-added-dog_object_schema/';
migrations.push(migration1);
export default migrations;
migrations/0-added-dog_object_schema/Dog.js
export default {
name: 'Dog',
properties: {
name: {type: 'string'},
},
};
migrations/0-added-dog_object_schema/migration.js
(Example here)
export default (oldRealm, newRealm) => {
// TODO: Do something in here for the migration!
}
migrations/0-added-dog_object_schema/index.js
import migrationCallback from './migration';
const schemas = [];
import Dog from './Dog';
schemas.push(Dog);
export default {
schema: schemas,
schemaVersion: 0,
migration: migrationCallback,
};
migrateRealm.js
import { Models } from './models/';
import Realm from 'realm';
import migrations from './migrations/';
export const migrateRealm = () => {
// Will be -1 if the Realm at the path has never been opened before.
let schemaVersion = Realm.schemaVersion('dogs-realm');
schemaVersion = schemaVersion !== -1 ? schemaVersion : 0;
if (migrations.length === 0) {
return {schema: Models, path: 'dogs-realm', schemaVersion };
}
// 2. Get the index of the migration where we are currently at
let nextMigrationsIndex = -1;
for (let index = 0; index < migrations.length; index++) {
const migration = migrations[index];
if (migration.schemaVersion === schemaVersion) {
nextMigrationsIndex = index;
break;
}
}
// 3. Lets move onto the next migration, since we know that this one has already been migrated to
nextMigrationsIndex++;
// 4. The next migration and all others that follow are going to be executed so that we incrementally migrate the Realm
for (; nextMigrationsIndex < migrations.length; nextMigrationsIndex++) {
const migratedRealm: Realm = new Realm({
...migrations[nextMigrationsIndex],
path: 'dogs-realm',
});
migratedRealm.close();
}
// 5. Now that we have migrated the Realm up to the most current version let's return the proper configuration
return {
schema: Models,
schemaVersion: migrations[migrations.length - 1].schemaVersion,
path: 'dogs-realm'
};
};
index.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { migrateRealm } from './migrateRealm';
import Realm from 'realm';
export default class RealmMigrate extends Component {
constructor(props) {
super(props);
this.state = { realm: undefined, status: 'Loading App...', version: -1 };
}
componentWillMount() {
const configuration = migrateRealm();
const version = configuration.schemaVersion;
return Realm.open(configuration)
.catch((e) => {
const isTypeError = e instanceof TypeError;
const isFailedNetworkRequest = e.message === 'Network request failed';
if (isTypeError && isFailedNetworkRequest) {
this.setState({status: 'Server could not be reached.'});
} else if (isTypeError) {
this.setState({status: e.message});
} else {
this.setState({status: 'Unknown error'});
}
})
.then((realm) => {
this.setState({realm, version });
})
;
}
render() {
if (this.state.realm === undefined) {
return (
<View>
<Text>{this.state.status}</Text>
</View>
);
}
return (
<View style={{flex: 1}}>
<Text>{`Realm Migrations Example rendered for Version ${this.state.version}!`}</Text>
</View>
);
}
}
Commands
Default command: realm-migration
NOTE - All <name>Dir options must include an ending slash(i.e. src/). sourceDir and modelDir must be relative.
Used for generating migrations after the init command has been executed.
Options
Name | Default | Purpose
------------ | ------------- |-------------
isTypescript | false | Indicates whether or not Typescript should be consumed and outputted.
sourceDir | src/ | Indicates where the root of your Migration and Model directories reside.
modelDir | models/ | Indicates the directory relative to sourceDir where your Models reside.
migrationDir | migrations/ | Indicates the directory relative to sourceDir where your Migrations reside.
tempDir | temp/ | Indicates what the name of the temporary directory relative to where you run the command should be. The dir gets deleted at the end of the generating a migration.
shcemaVersion | 0 | Explicitly specify the schema version number.Good for when your first saved schema version is greater than 0.This is the case if you have an exsiting project that uses Realm where the schema version is past 0.
schemaDesc | '' | Describes the migration that is going to be created(i.e. (computed schema version)-(added/removed/updated)-(x)_object_schema
)
objectSchemaFileSuffix | '' | Indicates what the suffix of the [Realm.ObjectClass](the https://realm.io/docs/javascript/1.1.1/api/Realm.html#~ObjectClass) file should be(i.e. object 'Event' would have a 'EventModel' class in a file named 'EventModel') This will be DEPRECATED
soon because it's actually not necessary.
Init command: realm-migration:init
NOTE - All <name>Dir options must include an ending slash(i.e. src/migrations/).
Used for scaffolding the initial migrations structure such that your code that depends on that structure won't fail if it's not there.
Options
Name | Default | Purpose ------------ | ------------- |------------- isTypescript | false | Indicates whether or not Typescript should be consumed and outputted. migrationDir | src/migrations | Indicates where the migrations directory resides in your project
Todo
- [ ] Write tests
- [ ] More flexibility for options and how Realm ObjectSchemas can be defined/consumed by the generator
- [X] Add code for sample React Native component that calls migrateRealm.