npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@realm/babel-plugin

v0.2.0

Published

Babel plugin making it easier to declare your Realm schema

Downloads

2,749

Readme

Realm Babel Plugin

Introduction

The Realm Babel plugin enables defining your Realm models using standard Typescript syntax - no need to define a separate schema.

class Task extends Realm.Object<Task, "description"> {
  _id!: Realm.BSON.ObjectId;
  description!: string;
  isComplete!: boolean;

  static schema = {
    name: "Task",
    primaryKey: "_id",
    properties: {
      _id: "objectId",
      description: "string",
      isComplete: {
        type: "bool",
        default: false,
        indexed: true,
      },
    },
  };

  constructor(realm, description: string) {
    super(realm, {
      _id: new Realm.BSON.ObjectId(),
      description,
    });
  }
}
class Task extends Realm.Object<Task, "description"> {
  _id = new Realm.BSON.ObjectId();
  description!: string;
  @index
  isComplete = false;

  static primaryKey = "_id";

  constructor(realm, description: string) {
    super(realm, { description });
  }
}

Features

  • Schema properties can be defined as class properties by using standard TypeScript types or specific Realm.Types types, supporting every Realm type
  • Support for default values using property initialiser syntax
  • Support for specifying additional schema properties (e.g. primary key) using class statics
  • Support for indexing and remapping fields using decorators

Installation

  1. Install the @realm/babel-plugin npm package:

    npm install --save-dev @realm/babel-plugin

  2. If you don't already have it installed, install the @babel/plugin-proposal-decorators package (only required if you need to use the @index or @mapTo decorators):

    npm install --save-dev @babel/plugin-proposal-decorators

    and enable decorators in your tsconfig.json by adding: "experimentalDecorators": true to the compilerOptions.

  3. Update your project's babel.config.js to load these two plugins:

    // Existing babel.config.js content is commented out
    // module.exports = {
      // presets: ['module:metro-react-native-babel-preset'],
    
      // --------------------------
      // Add the following plugins:
      plugins: [
        '@realm/babel-plugin',
        ['@babel/plugin-proposal-decorators', { legacy: true }],
      ],
      // --------------------------
    // };
    
  4. If using React Native, you may need to clear your packager cache for it to pick up the new plugins:

    npm start -- --reset-cache

Usage

Defining model properties

To define your Realm models when using this plugin, simply create classes which extend Realm.Object, and define the model's properties using either supported TypeScript types or Realm.Types types (see supported types). It is recommended that you use the non-null assertion operator (!) after the property name, to tell TypeScript that the property will definitely have a value.

You can use property initialiser syntax to specify a default value for a property, which can either be a static value or a function call for dynamic values.

The recommended pattern for constructing new instances with specified values for properties is to define a constructor which takes the properties as additional arguments. The second type parameter of Realm.Object can be used to specify any fields which are required to be specified in the second fields when an instance is constructed with new - all properties are optional by default.

import Realm from "realm";

// Specify that the name and description fields are required when creating an instance with `new`
export class Task extends Realm.Object<Task, "name" | "description"> {
  // Property initialiser syntax with a dynamic value - each instance will have a unique ID
  _id = new Realm.BSON.ObjectId();
  name!: string;
  description!: string;
  // Property initializer syntax with a static value
  isComplete = false;
  // Specifying the type of number to be stored in the Realm using Realm.Types
  count!: Realm.Types.Int = 0;
}

You can also import Object and Types directly from realm:

import { Object, Types, BSON } from "realm";

export class Task extends Object<Task, "name" | "description"> {
  _id = BSON.ObjectId();
  name: string;
  description!: string;
  isComplete = false;
  count!: Types.Int;
}

Supported types

This plugin supports standard TypeScript types wherever possible, to make defining your model as natural as possible. Some Realm types do not have a direct TypeScript equivalent (e.g. double, int and float are all represented by number in TypeScript), so in these cases you should use the types provided by Realm.Types.

As a rule, we recommend using TypeScript types where possible, and using Realm.Types where you cannot, but you can also exclusively use types from Realm.Types if preferred.

Types which are provided by Realm (e.g. Realm.List) are exported from both the top-level Realm namespace, and from Realm.Types - you can use either variant in your models.

The supported types are shown in the table below. See the Realm documentation and SDK documentation for more details on each type.

| Realm.Types type | Realm schema type | TypeScript type | Realm type | Notes | | -------------------------------------------- | ----------------- | --------------- | ----------------------- | -------------------------------------------------------------------------------------- | | Types.Bool | bool | boolean | | | | Types.String | string | string | | | | Types.Int | int | | | | | Types.Float | float | | | | | Types.Double | double | number | | Double is the default number type | | Types.Decimal128 | decimal128 | | Realm.BSON.Decimal128 | | | Types.ObjectId | objectId | | Realm.BSON.ObjectId | | | Types.UUID | uuid | | Realm.BSON.UUID | | | Types.Date | date | Date | | | | Types.Data | data | ArrayBuffer | | | | Types.List<T> | type[] | | Realm.List<T> | T is the type of objects in the list | | Types.Set<T> | type<> | | Realm.Set<T> | T is the type of objects in the set | | Types.Dictionary<T> | type{} | | Realm.Dictionary<T> | T is the type of objects in the dictionary | | Types.Mixed | mixed | | Realm.Mixed | | | Types.LinkingObjects<T, N> | linkingObjects | | | T is the type of objects, N is the property name of the relationship (as a string) |

Specifying schema properties as statics

Additional schema properties can be specified by adding static properties to your class, as shown in the table below. See the Realm documentation for more details.

| Static property | Type | Notes | | --------------- | --------- | -------------------------------------------------------------------------- | | name | string | Specifies the name of the Realm schema. Defaults to your class name. | | primaryKey | string | Specifies the name of a property to be used as the primary key. | | embedded | boolean | Specifies this is an embedded schema. | | asymmetric | boolean | Specifies this schema should sync unidirectionally if using flexible sync. |

For example:

import Realm from "realm";

export class Task extends Realm.Object<Task, "description"> {
  _id = new Realm.BSON.ObjectId();
  description!: string;
  isComplete = false;

  static primaryKey = "_id";
}

Using decorators to index and remap properties

The @realm/babel-plugin package exports decorators to allow you to specify certain properties should be indexed (using the @index decorators) or should remap to a Realm schema property with a different name (using the @mapTo decorator). To learn more about this functionality, see the documentation.

Note that use of decorators requires using the @babel/plugin-proposal-decorators plugin and for experimentalDecorators to be enabled in your tsconfig.json. There is currently no way to specifying properties to be indexed or remapped without using decorators.

This table shows the available decorators:

| Decorator | Parameters | Notes | |-----------|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | index | none or ("full-text") | Specifies that the decorated property should be indexed by Realm. Providing the string "full-text" specifies that the property should be indexed for full-text search by Realm. | | mapTo | (realmPropertyName: string) | Specifies that the decorated property should be stored as realmPropertyName in the Realm database. |

The example below shows both decorators in use:

import Realm from "realm";
import { mapTo, index } from "@realm/babel-plugin";

export class Task extends Realm.Object {
  _id!: Realm.BSON.ObjectId;
  // Add an index to the `assignee` property
  @index
  assignee!: string;
  // Specify that the `description` property should be indexed for full-text search
  @index("full-text")
  description!: string;
  // Specify that the `isComplete` property should be stored as `complete` in the Realm database
  @mapTo("complete")
  isComplete = false;
}

Restrictions

All class properties will be added to the Realm schema

There is currently no way to specify a property on your class which should not be persisted to the Realm.

Classes extending Realm.Object cannot be constructed with new outside of a write transaction

This plugin does not change the behaviour of Realm.Object, which cannot be constructed using new outside of a write transaction - there is no concept of a Realm.Object which is not stored in a Realm. Constructing a Realm object with new inside a write transaction will create a new object in the Realm - see class-based models in the CHANGELOG.

Debugging your model

To generate the output for your model (let's say it's located in ./models/task.ts) you can run the babel transpiler manually on the file:

npm install --save-dev @babel/cli @babel/preset-typescript
npx babel --presets @babel/preset-typescript --plugins @realm/babel-plugin ./models/task.ts