在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:rawmodel/framework开源软件地址:https://github.com/rawmodel/framework开源编程语言:TypeScript 82.4%开源软件介绍:Rawmodel FrameworkRawmodel is a strongly-typed JavaScript object with support for validation and error handling. It's a lightweight open source framework for the server and browser (using module bundler), written with TypeScript. It's actively maintained, well tested and already used in production environments. The source code is available on GitHub where you can also find our issue tracker. IntroductionRawmodel provides a mechanism for creating strongly-typed data objects with built-in logic for unified data validation and error handling. It has a simple and intuitive API and tends to be a powerful, magic-free, minimalistic and unopinionated framework for writing application data layers where you have a complete control. It could be a perfect fit when writing an Express.js action, GraphQL resolver or similar and it's easily extendable. InstallationRun the command below to install the package.
This package uses promises thus you need to use Promise polyfill when promises are not supported. ExampleThe code below shows a basic usage example. import { Model, prop } from '@rawmodel/core';
// defining a basic model
class User extends Model {
@prop()
public name: string;
}
// usage example
const model = new User({
'name': 'John Smith',
});
model.name; // => 'John Smith' UsageBelow we explain some of the most important features that this framework provides. Please check the API section to see a complete list of features. Defining PropsModel properties are defined using the import { Model, prop } from '@rawmodel/core';
class User extends Model {
@prop()
public name: string;
}
const user = new User();
user.name = 'John Smith';
user.name; // -> "John Smith" Type CastingEach property has a built-in system for type casting, thus we can force a value to be automatically converted to a specific type when setting a value. import { ParserKind } from '@rawmodel/core';
import { stringParser } from '@rawmodel/parsers';
class User extends Model {
@prop({
parser: {
resolver: stringParser(),
},
})
public name: string;
} Common types are supported by default. A Nested ModelsAs mentioned above, a model class is already a type. This way you can create complex nested structures by nesting models as shown in the example below. import { Model, ParserKind, prop } from '@rawmodel/core';
class Address extends Model {
@prop()
public country: string;
}
class Friend extends Model {
@prop()
public name: string;
}
class User extends Model {
@prop({
parser: {
resolver: Address,
},
})
public address: Address;
@prop({
parser: {
array: true,
resolver: Friend,
},
})
public friends: Friend[];
} Prop Default ValueWe can set a The @prop({
defaultValue() { return new Date() },
})
public now: string; Prop Fake ValueSimilar to default values, we can set a The @prop({
fakeValue() { return new Date() },
})
public today: string; Prop Empty ValueBy default, all defined properties are set to The @prop({
emptyValue() { return '' },
})
public name: string; Prop Value TransformationA property can have a custom @prop({
getter(value) { return value },
setter(value) { return value },
})
public name: string; Value AssignmentsModel's properties are like properties of a Javascript Object. We can easily assign a value to a property through its setter method (e.g. model.populate({
'name': 'John Smith',
'age': 35,
}); We can allow only selected properties to be populated by using population strategies (e.g. useful when populating data received from a form). class User extends Model {
@prop({
populatable: ['internal'], // list population strategy names
})
public id: string;
@prop({
populatable: ['input', 'internal'], // list population strategy names
})
public name: string;
}
const data = {
'id': 100,
'name': 'John Smith'
};
const user = new User();
user.populate(data); // -> { "id": 100, "name": "John Smith" }
user.populate(data, 'internal'); // -> { "id": 100, "name": "John Smith" }
user.serialize(data, 'input'); // -> { id: null, "name": "John Smith" } Model properties also support dynamic data assignments. In translation, this means that we can populate a property using a function that shares the context of the associated model and is realized on property assignment. user.name = () => 'Join'; It's encouraged to use the Serialization & FilteringModel provides useful methods for object serialization and filtering. All enumerable properties are serializable by default and are thus included in the result object returned by the class User extends Model {
@prop({
serializable: ['output'], // list serialization strategy names
})
public id: string;
@prop({
serializable: ['input', 'output'], // list serialization strategy names
})
public name: string;
}
const user = new User({
'id': 100,
'name': 'John Smith',
});
user.serialize(); // -> { "id": 100, "name": "John Smith" }
user.serialize('input'); // -> { "name": "John Smith" }
user.serialize('output'); // -> { "id": 100, "name": "John Smith" } A model can also be serialized into an array by using the user.flatten(); // [{ path, value, prop }, ...]
user.flatten('input');
user.flatten('output'); Commits & RollbacksRawModel tracks changes for all properties and provides a mechanism for committing values and rollbacks. class User extends Model {
@prop()
public name: string;
}
const user = new User();
user.name = 'Mandy Taylor'; // changing property's value
user.isChanged(); // -> true
user.commit(); // set `initialValue` of each property to the value of `value`
user.isChanged(); // -> false
user.name = 'Tina Fey'; // changing property's value
user.rollback(); // -> reset `value` of each property to its `initialValue` (last committed value) Note that the ValidationRawModel provides a simple mechanism for validating properties. All validators shares the context of the associated model. class User extends Model {
@prop({
validators: [ // property validation setup
{ // validator recipe
resolver(v) { return !!v }, // [required] validator function
code: 422, // [optional] error code
},
],
})
public name: string;
}
const user = new User();
user.validate().catch((err) => {
user.collectErrors(); // -> [{ path: ['name'], code: 422 }]
}); Error HandlingRawModel provides a mechanism for handling property-related errors. The logic is aligned with the validation thus the validation and error handling can easily be managed in a unified way. This is great because we always deal with validation errors and can thus directly send these errors back to a user in a unified format. All handlers shares the context of the associated model. class User extends Model {
@prop({
handlers: [ // property error handling setup
{ // handler recipe
resolver(e) { return e.message === 'foo' }, // [required] error resolve function
code: 31000, // [optional] error code
},
],
})
public name: string;
}
const error = new Error();
const user = new User();
user.handle(error).then(() => {
user.collectErrors(); // -> [{ path: ['name'], code: 31000 }]
}); This mechanism is especially handful when saving data to a database. MongoDB database, for example, throws a uniqueness error (E11000) if we try to insert a value that already exists in the database. We can catch that error by using the Raw SchemaJSON Schema is a pretty popular standard for describing JSON objects. It's sufficient for general use cases, but it's not powerful enough to cover all RawModel features. RawModel provides its own schema syntax which allows for the creation of generic models from a JSON definition. We use import { createModelClass } from '@rawmodel/schema';
const schema = { // raw model schema
props: [ // properties definition
{
name: 'email', // property name
},
],
};
const Model = createModelClass(schema); // creates model class We can define static or dynamic default values. Dynamic values must have a resolver under the const schema = {
defaultValues: {
currentDate() { return new Date() },
},
props: [
{
name: 'email',
defaultValue: 'Noname',
},
{
name: 'date',
defaultValue: 'currentDate', // referencing currentDate()
},
],
}; Validators and handlers can be defined in a similar way. import { stringLengthValidator } from '@rawmodel/validators';
const schema = {
validators: { // schema validators
stringLength: stringLengthValidator, // validator resolver
},
props: [ // schema properties
{ // property definition
name: 'title', // property name
validators: [
{
resolver: 'stringLength', // validator resolver name
code: 30001, // validation error code
options: { min: 5 }, // validator arguments
},
],
},
],
}; Schema supports basically all RawModel features. Check the API section for all the details. GraphQLRawModel can be a perfect framework for writing GraphQL resolvers. An instance of a root model, in our case the import { Model } from '@rawmodel/core';
import { graphql, buildSchema } from 'graphql';
class App extends Model { // root resolver
public hello() { // `hello` property resolver
return 'Hello World!';
}
}
const schema = buildSchema(`
type Query {
hello: String
}
`);
const root = new App(); // root resolver
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
}); API@rawmodel/corecreateModelClass(config)
const Model = createModelClass([
{
name: 'name',
prop: {
defaultValue: 'John Smith',
},
},
]); Model(data, config)
全部评论
专题导读
上一篇:sebastianbergmann/phpunit: The PHP Unit Testing framework.发布时间:2022-06-07下一篇:facebook/react-native: A framework for building native applications using React发布时间:2022-06-07热门推荐
热门话题
阅读排行榜
|
请发表评论