Update README for the new version and add tests status badge.
This commit is contained in:
		
							parent
							
								
									7e86e6fe86
								
							
						
					
					
						commit
						4570513ab9
					
				
					 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/badges/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