Update README for the new version and add tests status badge.
All checks were successful
/ test (push) Successful in 22s
All checks were successful
/ test (push) Successful in 22s
This commit is contained in:
parent
7e86e6fe86
commit
df829bbac6
1 changed files with 177 additions and 56 deletions
233
README.md
233
README.md
|
@ -19,42 +19,64 @@
|
|||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Version 3.3.0" src="https://img.shields.io/badge/version-3.3.0-blue" />
|
||||
<a href="https://www.npmjs.com/package/@sharkitek/core" target="_blank">
|
||||
<img alt="Latest release" src="https://code.zeptotech.net/Sharkitek/Core/release.svg" />
|
||||
</a>
|
||||
<img alt="Tests status" src="https://code.zeptotech.net/Sharkitek/Core/badges/workflows/test.yaml/badge.svg" />
|
||||
</p>
|
||||
|
||||
## Introduction
|
||||
|
||||
Sharkitek is a Javascript / TypeScript library designed to ease development of client-side models.
|
||||
Sharkitek is a lightweight Javascript / TypeScript library designed to ease development of models.
|
||||
|
||||
With Sharkitek, you define the architecture of your models by specifying their properties and their types.
|
||||
Then, you can use the defined methods like `serialize`, `deserialize`, `patch` or `serializeDiff`.
|
||||
Then, you can use the defined methods like `serialize`, `parse`, `patch` or `serializeDiff`.
|
||||
|
||||
```typescript
|
||||
class Example extends s.model({
|
||||
id: s.property.numeric(),
|
||||
name: s.property.string(),
|
||||
})
|
||||
class Example
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: Example,
|
||||
properties: {
|
||||
id: s.property.numeric(),
|
||||
name: s.property.string(),
|
||||
},
|
||||
identifier: "id",
|
||||
});
|
||||
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
## Quick start
|
||||
|
||||
### Simple model definition
|
||||
**Note**: by convention, we define our models in a `model` static variable in the model's class. It is a good way to keep your model declaration near the actual class, and its usage will be more natural.
|
||||
|
||||
### Model definition
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* A person.
|
||||
*/
|
||||
class Person extends s.model({
|
||||
id: s.property.numeric(),
|
||||
name: s.property.string(),
|
||||
firstName: s.property.string(),
|
||||
email: s.property.string(),
|
||||
createdAt: s.property.date(),
|
||||
active: s.property.boolean(),
|
||||
}, "id")
|
||||
class Person
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: Person,
|
||||
properties: {
|
||||
id: s.property.numeric(),
|
||||
name: s.property.string(),
|
||||
email: s.property.string(),
|
||||
createdAt: s.property.date(),
|
||||
active: s.property.boolean(),
|
||||
},
|
||||
identifier: "id",
|
||||
});
|
||||
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
createdAt: Date;
|
||||
active: boolean = true;
|
||||
}
|
||||
```
|
||||
|
@ -63,22 +85,28 @@ class Person extends s.model({
|
|||
/**
|
||||
* An article.
|
||||
*/
|
||||
class Article extends s.model({
|
||||
id: s.property.numeric(),
|
||||
title: s.property.string(),
|
||||
authors: s.property.array(s.property.model(Author)),
|
||||
text: s.property.string(),
|
||||
evaluation: s.property.decimal(),
|
||||
tags: s.property.array(
|
||||
s.property.object({
|
||||
name: s.property.string(),
|
||||
})
|
||||
),
|
||||
}, "id")
|
||||
class Article
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: Article,
|
||||
properties: {
|
||||
id: s.property.numeric(),
|
||||
title: s.property.string(),
|
||||
authors: s.property.array(s.property.model(Person)),
|
||||
text: s.property.string(),
|
||||
evaluation: s.property.decimal(),
|
||||
tags: s.property.array(
|
||||
s.property.object({
|
||||
name: s.property.string(),
|
||||
})
|
||||
),
|
||||
},
|
||||
identifier: "id",
|
||||
});
|
||||
|
||||
id: number;
|
||||
title: string;
|
||||
authors: Author[] = [];
|
||||
authors: Person[] = [];
|
||||
text: string;
|
||||
evaluation: number;
|
||||
tags: {
|
||||
|
@ -87,6 +115,84 @@ class Article extends s.model({
|
|||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* A model with composite keys.
|
||||
*/
|
||||
class CompositeKeys
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: CompositeKeys,
|
||||
properties: {
|
||||
id1: s.property.numeric(),
|
||||
id2: s.property.string(),
|
||||
},
|
||||
identifier: ["id1", "id2"],
|
||||
});
|
||||
|
||||
id1: number;
|
||||
id2: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Model functions
|
||||
|
||||
#### Serialization
|
||||
|
||||
```typescript
|
||||
const instance = new Person();
|
||||
instance.id = 1;
|
||||
instance.createdAt = new Date();
|
||||
instance.name = "John Doe";
|
||||
instance.email = "john@doe.test";
|
||||
instance.active = true;
|
||||
const serialized = Person.model.model(instance).serialize();
|
||||
console.log(serialized); // { id: 1, createdAt: "YYYY-MM-DDTHH:mm:ss.sssZ", name: "John Doe", email: "john@doe.test", active: true }
|
||||
```
|
||||
|
||||
#### Deserialization
|
||||
|
||||
```typescript
|
||||
const instance = Person.model.parse({
|
||||
id: 1,
|
||||
createdAt: "2011-10-05T14:48:00.000Z",
|
||||
name: "John Doe",
|
||||
email: "john@doe.test",
|
||||
active: true,
|
||||
});
|
||||
console.log(instance instanceof Person); // true
|
||||
console.log(instance.createdAt instanceof Date); // true
|
||||
```
|
||||
|
||||
#### Patch
|
||||
|
||||
```typescript
|
||||
const instance = Person.model.parse({
|
||||
id: 1,
|
||||
createdAt: "2011-10-05T14:48:00.000Z",
|
||||
name: "John Doe",
|
||||
email: "john@doe.test",
|
||||
active: true,
|
||||
});
|
||||
|
||||
instance.name = "Johnny";
|
||||
|
||||
// Patch serialized only changed properties and the identifier.
|
||||
console.log(Person.model.model(instance).patch()); // { id: 1, name: "Johnny" }
|
||||
// If you run it one more time, already patched properties will not be included again.
|
||||
console.log(Person.model.model(instance).patch()); // { id: 1 }
|
||||
```
|
||||
|
||||
#### Identifier
|
||||
|
||||
```typescript
|
||||
const instance = new CompositeKeys();
|
||||
instance.id1 = 5;
|
||||
instance.id2 = "foo";
|
||||
const instanceIdentifier = CompositeKeys.model.model(instance).getIdentifier();
|
||||
console.log(instanceIdentifier); // [5, "foo"]
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Types
|
||||
|
@ -95,7 +201,7 @@ Types are defined by a class extending `Type`.
|
|||
|
||||
Sharkitek defines some basic types by default, in these classes:
|
||||
|
||||
- `BoolType`: boolean value in the model, boolean value in the serialized object.
|
||||
- `BooleanType`: boolean value in the model, boolean value in the serialized object.
|
||||
- `StringType`: string in the model, string in the serialized object.
|
||||
- `NumericType`: number in the model, number in the serialized object.
|
||||
- `DecimalType`: number in the model, formatted string in the serialized object.
|
||||
|
@ -107,18 +213,22 @@ Sharkitek defines some basic types by default, in these classes:
|
|||
When you are defining a property of a Sharkitek model, you must provide its type by instantiating one of these classes.
|
||||
|
||||
```typescript
|
||||
class Example extends s.model({
|
||||
foo: s.property.define(new StringType()),
|
||||
})
|
||||
class Example
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: Example,
|
||||
properties: {
|
||||
foo: s.property.define(new StringType()),
|
||||
},
|
||||
});
|
||||
|
||||
foo: string;
|
||||
}
|
||||
```
|
||||
|
||||
To ease the use of these classes and reduce read complexity,
|
||||
properties of each type are easily definable with a function for each type.
|
||||
To ease the use of these classes and reduce read complexity, properties of each type are easily definable with a function for each type.
|
||||
|
||||
- `BoolType` => `s.property.boolean`
|
||||
- `BooleanType` => `s.property.boolean`
|
||||
- `StringType` => `s.property.string`
|
||||
- `NumericType` => `s.property.numeric`
|
||||
- `DecimalType` => `s.property.decimal`
|
||||
|
@ -127,21 +237,32 @@ properties of each type are easily definable with a function for each type.
|
|||
- `ObjectType` => `s.property.object`
|
||||
- `ModelType` => `s.property.model`
|
||||
|
||||
Type implementers should provide a corresponding function for each defined type. They can even provide
|
||||
multiple functions or constants with predefined parameters.
|
||||
(For example, we could define `s.property.stringArray()` which would be similar to `s.property.array(s.property.string())`.)
|
||||
Type implementers should provide a corresponding function for each defined type. They can even provide multiple functions or constants with predefined parameters. For example, we could define `s.property.stringArray()` which would be similar to `s.property.array(s.property.string())`.
|
||||
|
||||
```typescript
|
||||
class Example extends s.model({
|
||||
foo: s.property.string(),
|
||||
})
|
||||
class Example
|
||||
{
|
||||
static model = defineModel({
|
||||
Class: Example,
|
||||
properties: {
|
||||
foo: s.property.string(),
|
||||
},
|
||||
});
|
||||
|
||||
foo: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Models
|
||||
|
||||
#### `model(instance)`
|
||||
|
||||
Get a model class (which has all the sharkitek models' functions) from a model instance.
|
||||
|
||||
```typescript
|
||||
const model = definedModel.model(modelInstance);
|
||||
```
|
||||
|
||||
#### `serialize()`
|
||||
|
||||
Serialize the model.
|
||||
|
@ -149,17 +270,17 @@ Serialize the model.
|
|||
Example:
|
||||
|
||||
```typescript
|
||||
const serializedObject = model.serialize();
|
||||
const serializedObject = definedModel.model(modelInstance).serialize();
|
||||
```
|
||||
|
||||
#### `deserialize(serializedObject)`
|
||||
#### `parse(serializedObject)`
|
||||
|
||||
Deserialize the model.
|
||||
|
||||
Example:
|
||||
|
||||
```typescript
|
||||
const model = (new TestModel()).deserialize({
|
||||
const modelInstance = definedModel.parse({
|
||||
id: 5,
|
||||
title: "Hello World!",
|
||||
users: [
|
||||
|
@ -178,7 +299,7 @@ Serialize the difference between current model state and original one.
|
|||
Example:
|
||||
|
||||
```typescript
|
||||
const model = (new TestModel()).deserialize({
|
||||
const modelInstance = definedModel.parse({
|
||||
id: 5,
|
||||
title: "Hello World!",
|
||||
users: [
|
||||
|
@ -189,9 +310,9 @@ const model = (new TestModel()).deserialize({
|
|||
],
|
||||
});
|
||||
|
||||
model.title = "A new title for a new world";
|
||||
modelInstance.title = "A new title for a new world";
|
||||
|
||||
const result = model.serializeDiff();
|
||||
const result = definedModel.model(modelInstance).serializeDiff();
|
||||
// if `id` is defined as the model identifier:
|
||||
// result = { id: 5, title: "A new title for a new world" }
|
||||
// if `id` is not defined as the model identifier:
|
||||
|
@ -205,7 +326,7 @@ Set current properties values as original values.
|
|||
Example:
|
||||
|
||||
```typescript
|
||||
const model = (new TestModel()).deserialize({
|
||||
const modelInstance = definedModel.parse({
|
||||
id: 5,
|
||||
title: "Hello World!",
|
||||
users: [
|
||||
|
@ -216,11 +337,11 @@ const model = (new TestModel()).deserialize({
|
|||
],
|
||||
});
|
||||
|
||||
model.title = "A new title for a new world";
|
||||
modelInstance.title = "A new title for a new world";
|
||||
|
||||
model.resetDiff();
|
||||
definedModel.model(modelInstance).resetDiff();
|
||||
|
||||
const result = model.serializeDiff();
|
||||
const result = definedModel.model(modelInstance).serializeDiff();
|
||||
// if `id` is defined as the model identifier:
|
||||
// result = { id: 5 }
|
||||
// if `id` is not defined as the model identifier:
|
||||
|
@ -233,7 +354,7 @@ Get difference between original values and current ones, then reset it.
|
|||
Similar to call `serializeDiff()` then `resetDiff()`.
|
||||
|
||||
```typescript
|
||||
const model = (new TestModel()).deserialize({
|
||||
const modelInstance = definedModel.parse({
|
||||
id: 5,
|
||||
title: "Hello World!",
|
||||
users: [
|
||||
|
@ -244,9 +365,9 @@ const model = (new TestModel()).deserialize({
|
|||
],
|
||||
});
|
||||
|
||||
model.title = "A new title for a new world";
|
||||
modelInstance.title = "A new title for a new world";
|
||||
|
||||
const result = model.patch();
|
||||
const result = definedModel.model(modelInstance).patch();
|
||||
// if `id` is defined as the model identifier:
|
||||
// result = { id: 5, title: "A new title for a new world" }
|
||||
// if `id` is not defined as the model identifier:
|
||||
|
|
Loading…
Add table
Reference in a new issue