redstone_mapper 0.2.0

  • README.md
  • CHANGELOG.md
  • Installing
  • Versions
  • 5

Redstone Mapper

Build Status

redstone_mapper is a set of utilities for handling common tasks in web applications, including:

  • Encoding and decoding of objects to JSON.
  • Data validation.
  • Database connection management.
  • Encoding and decoding of objects to the database.

Encoding and decoding of objects and data validation can also be used on the client side. redstone_mapper provides a pub transformer that prevents dart2js from generating a bloated javascript file.

Example: Using redstone_mapper with Redstone.dart


import 'package:redstone/server.dart' as app;
import 'package:redstone_mapper/mapper.dart';
import 'package:redstone_mapper/plugin.dart';

main() {

  //When using redstone_mapper as a Redstone.dart plugin,
  //you can use the @Decode and @Encode annotations.
  app.addPlugin(getMapperPlugin());

  app.setupConsoleLog();
  app.start();
}

class User {

  //The @Field annotation is used to specify
  //the fields that can be serialized.
  @Field()
  String username;

  @Field()
  String password;

}

//The @Decode annotation specifies that a parameter value
//must be decoded from the request. By default, it will expect
//that the request has a JSON body.
@app.Route('/services/users/add', methods: const[app.POST])
addUser(@Decode() User user) {
  ...
}

//The @Encode annotation specifies that a route
//response can be encoded to JSON.
@app.Route('/services/users/list')
@Encode()
List<User> listUsers() {
  ...
}

The @Field annotation

To properly encode and decode an object, its class must have every serializable member annotated with @Field.


class User {

  @Field()
  String username;

  @Field()
  String password;

}

It's important to always define the type of the class member, so it can be properly encoded and decoded. If the field is a List or a Map, be sure to specify its parameters. Example:


class User {

  @Field()
  String name;

  @Field()
  List<Address> adresses;

}

class Address {

  @Field()
  String description;

  @Field()
  int number;

}

However, it's not recommended to use other classes that have type parameters, since it's not guaranteed that it will be properly encoded and decoded.

It's also possible to annotate getters and setters:

class User {

  String _name;

  @Field()
  String get name() => _name;

  @Field()
  set name(String value) => _name = value;

}

When encoding or decoding an object to JSON, you can use the view parameter to map a class member to its corresponding JSON field:


class User {

  @Field(view: "user_name")
  String name;

  @Field()
  String pass;

}

Also, if you are encoding or decoding an object to the database, you can use the model parameter to map a class member to its corresponding database field:


class User {

  //JSON: 'user_name'  DATABASE: 'USERNAME'
  @Field(view: "user_name", model: "USERNAME")
  String name;

  //JSON: 'pass'  DATABASE: 'PASSWORD'
  @Field(model: "PASSWORD")
  String pass;
}

Besides, every class that can be encoded or decoded must provide a default constructor, with no required arguments.

Data validation

The Validator class provides a simple and flexible way to build a set of validation rules.

  var userValidator = new Validator()
                      ..add("username", const NotEmpty())
                      ..add("password", const Range(min: 6. required: true));

  ...
  Map user = {"username": "user", "password": "pass"};
  ValidationError err = userValidator.execute(user);
  if (err != null) {
    ...
  }

To validate objects, you must provide the target class to the constructor. Also, you must annotate with @Field all members that can be validated.

Class User {

  @Field()
  String username;

  @Field()
  String password;

}

var userValidator = new Validator(User)
                    ..add("username", const NotEmpty())
                    ..add("password", const Range(min: 6. required: true));

...
User user = new User()
            ..username = "user"
            ..password = "pass";

ValidationError err = userValidator.execute(user);
if (err != null) {
  ...
}

Alternatively, you can set the rules directly in the class.

class User {

  @Field()
  @NotEmpty()
  String username;

  @Field()
  @Range(min: 6, required: true)
  String password;

}

var userValidator = new Validator(User, true);

You can also inherit from the Schema class, which will provide a Validator for you.

class User extends Schema {

  @Field()
  @NotEmpty()
  String username;

  @Field()
  @Range(min: 6, required: true)
  String password;

}

...
var user = new User()
            ..username = "user"
            ..password = "pass";

var err = user.validate();
if (err != null) {
  ...
}

redstone_mapper already provides the following basic rules, that you can use to build a Validator:

  • NotEmpty:
    • If the value is a String, verify if it isn't null, empty, or contains only spaces.
    • If the value is an Iterable, verify if isn't null or empty.
    • For other values, verify if it isn't null.
  • Range:
    • If the value is numeric, verify if it's within the specified range.
    • If the value is a String or an Iterable, verify if its length is within the specified range.
  • Matches:
    • For strings only: verify if the value matches the specified regex.
  • OnlyNumbers:
    • For strings only: verify if the value contains only digit characters.

You can easily build new rules by just inheriting from the ValidationRule class.

Configuration

To install redstone_mapper as a Redstone.dart plugin, you just have to import plugin.dart and call getMapperPlugin():


import 'package:redstone/server.dart' as app;
import 'package:redstone_mapper/plugin.dart';

import 'package:redstone/server.dart' as app;
import 'package:redstone_mapper/mapper.dart';
import 'package:redstone_mapper/plugin.dart';

main() {

  //When using redstone_mapper as a Redstone.dart plugin,
  //you can use the @Decode and @Encode annotations.
  app.addPlugin(getMapperPlugin());

  app.setupConsoleLog();
  app.start();
}

Also, if getMapperPlugin() receives an instance of DatabaseManager, then the plugin will manage the database connections for you. For more information, see one of the redstone_mapper extensions, such as redstone_mapper_pg or redstone_mapper_mongo.

To use with other server-side frameworks, or on the client side, you just have to import mapper_factory.dart and call bootstrapMapper() from the main() function:


import 'package:redstone/server.dart' as app;
import 'package:redstone_mapper/mapper_factory.dart';

main() {

  bootstrapMapper();
  ...
}

To encode and decode objects, you can use the encodeJson() and decodeJson() top level function from mapper.dart:


import 'package:redstone_mapper/mapper.dart';

class User {

  @Field()
  String username;

  @Field()
  String password;

}

var user = new User()
            ..username = "user"
            ..password = "pass";

String userJson = encodeJson(user);

When using on the client side, be sure to set redstone_mapper's transformer to your pubspec.yaml file, so dart2js won't generate a bloated javascript file:

name: my_app
version: 0.1.0
dependencies:
  redstone: any
  redstone_mapper: any
transformers:
- redstone_mapper

Integration with Polymer

Polymer applications usually doesn't have an entry-point (a dart script with the main function), so you have to provide one. Also, the entry-point has to import all libraries that contains encodable classes, so the transformer will be able to map them. You can see a working example which uses polymer and redstone_mapper here.

Database integration

redstone_mapper provides integration with database drivers through extensions. Currently, the following extensions are available:

Note that redstone_mapper doesn't aim to be a full ORM/ODM framework. It just provides some helper functions to easily encode and decode objects to the database. It won't generate database queries, neither hide the default driver API from you. That means you can use the redstone_mapper functions only when it's useful for you, and ignore it when it's just an extra overhead.

What about other databases?

Dart already has support for several databases, including: MongoDb, Redis, CouchDb, MySql, PostgreSql, and so on. I'll try to provide new extensions over time, but if you are interested, you can help me on this task.

Building a redstone_mapper extension is really easy, and you can start by taking a look at the source code of redstone_mapper_pg and redstone_mapper_mongo. If you are willing to build a externsion, please let me know :)

v.0.2.0

  • Added annotation for ignoring value : IgnoreValue.
  • Bumped dependencies

v0.2.0-beta.1+2

  • Updated dependency to work with the new code_transformers version. di.dart still depends on a old one, hence the git dependency.

v0.1.13

  • Fix transformer crash when encoding a Map or List without type parameters.

v0.1.12

  • Fix decode of Map values

v0.1.11

  • Fix: decode and encode of null value now returns null, instead of throwing an error.
  • Fix: directly encoding or decoding core types (for example: decode(42, int);) does not work when compiled to javascript

v0.1.10

  • Fix decoding of inherited properties

v0.1.9

  • Updated dependencies.

Note: this version requires Dart 1.7 or above

v0.1.8+1

This release includes fixes and improvements for the client-side support (thanks to prujohn for all the feedback):

  • Fix: Compilation errors when using the view or model parameters on fields.
  • Fix: When compiled to javascript, the mapper can't encode or decode objects with nested lists or maps.
  • Added the encodeJson() and decodeJson() top-level functions.
  • Improved error handling.
  • Improved documentation:
    • Fixed some typos (thanks to sethladd)
    • Added information about integration with polymer

v0.1.7

  • Widen the version constraint for code_transformers

v0.1.6

  • Fix: When compiled to Javascript, redstone_mapper is not decoding DateTime objects properly.
  • Fix: redstone_mapper should not suppress error messages from the mirrors api.

v0.1.5

  • Fix: when mapping json objects, redstone_mapper should handle DateTime objects as ISO 8601 strings.

v0.1.4

  • Widen the version constraint for analyzer

v0.1.3

  • Fix: Properly handle setter methods.

v0.1.2

  • The @Encode annotation can now be used with groups. If a group is annotated with @Encode, then redstone_mapper will encode the response of all routes within the group.

v0.1.1

  • Fix: transformer is generating broken code for validators.

v0.1.0

  • First release.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  redstone_mapper: ^0.2.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:redstone_mapper/database.dart';
import 'package:redstone_mapper/mapper.dart';
import 'package:redstone_mapper/mapper_factory.dart';
import 'package:redstone_mapper/mapper_factory_static.dart';
import 'package:redstone_mapper/plugin.dart';
import 'package:redstone_mapper/transformer.dart';
  
Version Uploaded Documentation Archive
0.2.0 Aug 10, 2016 Go to the documentation of redstone_mapper 0.2.0 Download redstone_mapper 0.2.0 archive
0.1.13 Mar 4, 2015 Go to the documentation of redstone_mapper 0.1.13 Download redstone_mapper 0.1.13 archive
0.1.12 Jan 31, 2015 Go to the documentation of redstone_mapper 0.1.12 Download redstone_mapper 0.1.12 archive
0.1.11 Jan 6, 2015 Go to the documentation of redstone_mapper 0.1.11 Download redstone_mapper 0.1.11 archive
0.1.10 Dec 24, 2014 Go to the documentation of redstone_mapper 0.1.10 Download redstone_mapper 0.1.10 archive
0.1.9 Oct 12, 2014 Go to the documentation of redstone_mapper 0.1.9 Download redstone_mapper 0.1.9 archive
0.1.8+1 Sep 16, 2014 Go to the documentation of redstone_mapper 0.1.8+1 Download redstone_mapper 0.1.8+1 archive
0.1.8 Sep 16, 2014 Go to the documentation of redstone_mapper 0.1.8 Download redstone_mapper 0.1.8 archive
0.1.7 Sep 3, 2014 Go to the documentation of redstone_mapper 0.1.7 Download redstone_mapper 0.1.7 archive
0.1.6 Aug 29, 2014 Go to the documentation of redstone_mapper 0.1.6 Download redstone_mapper 0.1.6 archive

All 18 versions...

Popularity:
Describes how popular the package is relative to other packages. [more]
9
Health:
Code health derived from static analysis. [more]
0
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
0
Overall:
Weighted score of the above. [more]
5
Learn more about scoring.

The package version is not analyzed, because it does not support Dart 2. Until this is resolved, the package will receive a health and maintenance score of 0.

Analysis issues and suggestions

Support Dart 2 in pubspec.yaml.

The SDK constraint in pubspec.yaml doesn't allow the Dart 2.0.0 release. For information about upgrading it to be Dart 2 compatible, please see https://www.dartlang.org/dart-2#migration.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.9.0-dev.9.1 <2.0.0