{"id":18331656,"url":"https://github.com/yagolopez/metaphasejs-react-demo","last_synced_at":"2025-04-06T03:33:21.299Z","repository":{"id":42107853,"uuid":"131513494","full_name":"YagoLopez/metaphasejs-react-demo","owner":"YagoLopez","description":":fire: MetaphaseJS DEMO: super easy, efficient and agnostic client state manager for Javascript","archived":false,"fork":false,"pushed_at":"2022-12-09T08:36:27.000Z","size":36041,"stargazers_count":4,"open_issues_count":26,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-21T16:12:33.318Z","etag":null,"topics":["database","database-management","frameworkless","javascript","react","react-state-management","redux","redux-sagas","relational","relational-database","state","state-management","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YagoLopez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-29T17:07:55.000Z","updated_at":"2020-09-12T15:57:11.000Z","dependencies_parsed_at":"2022-08-12T06:12:16.159Z","dependency_job_id":null,"html_url":"https://github.com/YagoLopez/metaphasejs-react-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YagoLopez%2Fmetaphasejs-react-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YagoLopez%2Fmetaphasejs-react-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YagoLopez%2Fmetaphasejs-react-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YagoLopez%2Fmetaphasejs-react-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YagoLopez","download_url":"https://codeload.github.com/YagoLopez/metaphasejs-react-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247430837,"owners_count":20937873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","database-management","frameworkless","javascript","react","react-state-management","redux","redux-sagas","relational","relational-database","state","state-management","typescript"],"created_at":"2024-11-05T19:34:15.548Z","updated_at":"2025-04-06T03:33:19.693Z","avatar_url":"https://github.com/YagoLopez.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MetaphaseJS Demo\n\nDemostration of MetaphaseJS framework ( **BETA VERSION** ).\n\n[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges) [![Build Status](https://travis-ci.org/YagoLopez/metaphasejs-react-demo.svg?branch=master)](https://travis-ci.org/YagoLopez/metaphasejs-react-demo) [![Maintainability](https://api.codeclimate.com/v1/badges/c1a754523798b48ec180/maintainability)](https://codeclimate.com/github/YagoLopez/metaphasejs-react-demo/maintainability)\n\n![NPM package](https://nodei.co/npm/metaphasejs.png)\n\n\n**MetaphaseJS** is a super easy, efficient and agnostic state manager for Javascript. It can be used with React, Angular o vanilla JS. In this demo React and Typescript have been used. :arrow_right: ​[Link to repository](https://github.com/YagoLopez/metaphasejs)\n\n## Demo\n\n- [Use this link to access the demo](https://yagolopez.js.org/metaphasejs-react-demo/build/)\n- Or scan the QR code to load the demo in a smartphone:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"qrcode.jpg\"/\u003e\u003c/p\u003e\n\n## Table of Contents\n\n- [Why](#why)\n- [Features](#features)\n- [How](#how)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Contributing](#contributing)\n- [Entity-Relation State Diagram](#entity-relation-state-diagram)\n- [Code](#code)\n- [Credits](#credits)\n- [License](#license)\n\n## Why\n\n- State management is an issue solved decades ago in server-side environments using transactional and relational databases. This is not the case of client-side apps (browser) where it has remained unsolved until the advent of libraries/patterns like Redux/Flux\n- Client-state managers based on Flux architecture produce verbose and complicated code (inmutability adds levels of indirection and therefore complexity) and they are basically reinventing the wheel trying to recreate a sort of in-browser database\n- Store in Redux is essentially a big key-value object which is not appropiate for nested and relational data\n- There are other client databases like IndexDB, LovefieldDB, etc. but they are complicated (callbacks, asynchrony) or very elementary (localStorage)\n- The intention of MetaphaseJS is to apply the same server-side state management techniques to client-side apps.\n\n## Features\n\n- Simplicity: no callbacks, no asynchronous code, no functional nor inmutable complexities \n- Agnostic: it can be used with ReactJS, Angular, Vue, React Native, vanilla JS, etc. Just plug-and-play\n- State is a true relational SQLite database\n- State can be managed with SQL queries generated by Metaphase ORM ([Object-Relational Mapper](https://en.wikipedia.org/wiki/Object-relational_mapping)). It implements the following patterns:\n  - [Repository](https://martinfowler.com/eaaCatalog/repository.html)\n  - [Active-Record](https://en.wikipedia.org/wiki/Active_record_pattern)\n- State can be saved to a database file on disk\n- State can be designed and populated with any db tool that supports SQLite (even using a graphical UI without using code) and after that, it can be imported into an app\n- Great developer productivity and satisfacction. For example, an entire blog sistem could be developed in minutes\n- Ideal for statically generated content (i. e.: static blogs without a server database)\n- Comprehensive and switchable logger system. It can be turned off in production for better performance . A simple url query parameter controls the logger `http://url-app?logger=true/false`\n- Use of [Reflection-Metadata API](https://www.typescriptlang.org/docs/handbook/decorators.html#metadata) and [Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html) to simplify model definitions (when Typescript is used)\n- In SQLite by default all operations are transactional. This means protection against race conditions when state is accessed by asynchronous writes\n\n## How\n\n- [Sql.js](https://github.com/kripken/sql.js) is a Javascript library that uses [Emscriptem](http://kripken.github.io/emscripten-site/)/[WebAssembly](https://webassembly.org/)  to recompile the SQLite C++ code to Javascript. This means you can create a SQLite database in browser and use all its functionality.\n- MetaphaseJS uses `Sql.js` to hold the application state in a **in-memory SQLite database**:\n  1. You create classes for your models (also called *entities*)\n  2. Set up relations between models\n  3. Create collections of models\n  4. Execute operations with models (CRUD)\n- You can use an ORM to execute queries, or raw SQL\n- You can load state:\n  1. From a database file on disk\n  2. From a database created at runtime by code\n- You can save the state to a file on disk\n- As always you can persist the state to a server using http requests.\n\n## Requirements\n\n- Modern browser\n- Yarn package manager (or NPM)\n\n## Installation\n\n- Clone the project\n- Run `yarn install` in the project directory\n\n## Usage\n\n- Run `yarn start`\n- Packages analysis (without gzip compression) `yarn analysis` :arrow_right: [link](https://yagolopez.js.org/metaphasejs-react-demo/analysis/packages.html)\n\n\n## Entity-Relation State Diagram\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"/src/uml/uml.jpg\"/\u003e\u003c/p\u003e\n\n## Code\n\n1. Creation of models and relations in `models.ts`. (Models could have also been defined in individual files).\n\n```typescript\n// File: models.ts\n\n// ---------------------------------------------------------------------\n// This is a simplified example and it is written in Typescript using decorators\n// For regular Javascript you can define columns using \"Column\" class.\n// (See tests)\n// ---------------------------------------------------------------------\n\nimport {Model, column} from 'metaphasejs';\n\n// User model definition (ids are automatically generated) -------------\nexport class User extends Model {\n\n  @column()\n  name: string;\n\n  @column({notNullable: true, index: true}) // Example of db column attributes\n  age: number;\n\n  @column()\n  admin: number;\n\n  hasMany() {\n    return [Post]; // Relation definition: User \"has many\" Post\n  }\n}\n\n// Post model definition ------------------------------------------------\nexport class Post extends Model {\n\n  @column()\n  title: string;\n\n  @column({dbType: DBtype.TEXT})\n  content: string;\n\n  hasMany() {\n    return [Comment];\n  }\n}\n\n// Comment model definition ---------------------------------------------\nexport class Comment extends Model {\n\n  @column()\n  author: string;\n\n  @column()\n  date: string;\n}\n```\n\n\n\n2. Definition of collections and relations in `store.ts`. This concept of \"*store*\" is not the same like in Redux. It is just a place where instances and collections of models are created, but they can be created in any other place in the application.\n\n```typescript\n// File: store.ts\n\nimport {Collection} from 'metaphasejs';\nimport {User, Post, Comment} from 'models';\n\n// Users collection -----------------------------------------------------\nexport const users = new Collection(User);\nconst user1 = new User({name: \"user1\", age: 11, admin: 1});\nconst user2 = new User({name: \"user2\", age: 22, admin: 1});\nconst user3 = new User({name: \"user3\", age: 33, admin: 1});\nusers.save(user1);\nusers.save(user2);\nusers.save(user3);\n\n// Posts collection -----------------------------------------------------\nexport const posts = new Collection(Post);\nconst post1 = new Post({title: 'title post 1', content: 'content post 1'});\nconst post2 = new Post({title: 'title post 2', content: 'content post 2'});\nconst post3 = new Post({title: 'title post 3', content: 'content post 3'});\npost1.belongsTo(user1);\npost2.belongsTo(user1);\npost3.belongsTo(user2);\nposts.save(post1);\nposts.save(post2);\nposts.save(post3);\n\n// Comments collection --------------------------------------------------\nexport const comments = new Collection(Comment);\nconst comment1 = new Comment({author: 'author1', date: '5/16/2018'});\nconst comment2 = new Comment({author: 'author2', date: '6/16/2018'});\ncomment1.belongsTo(post1);\ncomment2.belongsTo(post1);\ncomments.save(comment1);\ncomments.save(comment2);\n```\n\n3. Operations with data\n\n   a) Filtering:\n\n```typescript\n// File: app.ts\n\nimport {users} from \"store\"\nimport {db} from \"metaphasejs\";\n\n// Get all users\nusers.getAll();\n\n// Get all users with children (related models)\nusers.getAll({children: true});\n\n// Get all users using raw sql\ndb.execQuery('select * from users');\n\n// Get user by id = 1\nconst user1 = users.getById(1);\n\n// Get user with name 'user1'\nusers.getByFilter({name: 'user1'})\n\n// Get user with name: 'user1', age: 11 and admin: 0\nusers.getByFilter({name: 'user1', age: 11, admin: 0});\n\n// See tests for more examples\n```\n\n   b) Create/Read/Update/Delete (CRUD):\n\n```typescript\n// File app.ts\n\n// user1 modification\nuser1.name = 'new name';\n\n// Save/update user1 using an instance of Model class\nuser1.save();\n\n// Save/update user1 using an instance of Collection class\nusers.save(user1);\n\n// Delete user1 using an instance of Model class\nuser1.remove();\n\n// Delete user1 using an instance of Collection class\nusers.remove(user1);\n\n// TODO more examples\n\n```\n\n\n## Credits\n\n- [Font Awesome](https://fontawesome.com/license)\n- [Sql.js](https://github.com/kripken/sql.js)\n- [KnexJS](http://knexjs.org)\n\n## License\n\nMIT\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#\"\u003eBack to top :arrow_up:\u003c/a\u003e\u003c/p\u003e \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyagolopez%2Fmetaphasejs-react-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyagolopez%2Fmetaphasejs-react-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyagolopez%2Fmetaphasejs-react-demo/lists"}