{"id":25945509,"url":"https://github.com/anchovycation/metronom","last_synced_at":"2025-03-04T09:17:50.320Z","repository":{"id":43402352,"uuid":"456436512","full_name":"anchovycation/metronom","owner":"anchovycation","description":"Easy to use Redis ORM based on node-redis with TypeScript support","archived":false,"fork":false,"pushed_at":"2023-02-22T20:02:06.000Z","size":1196,"stargazers_count":7,"open_issues_count":13,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-04T04:17:39.918Z","etag":null,"topics":["javascript","node","node-redis","nodejs","orm","orm-library","redis","typescript"],"latest_commit_sha":null,"homepage":"https://anchovycation.github.io/metronom/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anchovycation.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-07T09:25:08.000Z","updated_at":"2023-08-19T11:49:57.000Z","dependencies_parsed_at":"2024-06-21T20:23:07.637Z","dependency_job_id":"a3047522-4c7e-43b5-a0ee-ec81dc419765","html_url":"https://github.com/anchovycation/metronom","commit_stats":{"total_commits":62,"total_committers":4,"mean_commits":15.5,"dds":0.532258064516129,"last_synced_commit":"b7ca806108671de9d39fd15eebe37157414e5f44"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anchovycation%2Fmetronom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anchovycation%2Fmetronom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anchovycation%2Fmetronom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anchovycation%2Fmetronom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anchovycation","download_url":"https://codeload.github.com/anchovycation/metronom/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241780462,"owners_count":20019061,"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":["javascript","node","node-redis","nodejs","orm","orm-library","redis","typescript"],"created_at":"2025-03-04T09:17:49.730Z","updated_at":"2025-03-04T09:17:50.303Z","avatar_url":"https://github.com/anchovycation.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg/ width=\"280\" src=\"images/metronom.svg\" alt=\"metronom logo\"\u003e \u003cbr\u003e\n  \u003ca href=\"https://anchovycation.github.io/metronom/\"\u003emetronom\u003c/a\u003e\n\u003c/h1\u003e\n\n\u003ch6 align=\"center\"\u003e\n\n[![npm version](https://badgen.net/npm/v/metronom)](https://www.npmjs.com/package/metronom)\n[![download](https://badgen.net/npm/dt/metronom)](https://www.npmjs.com/package/metronom)\n[![merged prs](https://badgen.net/github/merged-prs/anchovycation/metronom)](https://github.com/anchovycation/metronom)\n[![last commit](https://badgen.net/github/last-commit/anchovycation/metronom/main)](https://github.com/anchovycation/metronom)\n[![types](https://badgen.net/npm/types/metronom)](https://github.com/anchovycation/metronom)\n[![license](https://badgen.net/npm/license/metronom)](https://www.npmjs.com/package/metronom)\n\n\u003c/h6\u003e\n\nMetronom is user friendly Redis ORM based on  [node-redis](https://github.com/redis/node-redis) \n\nYou can  **save**,  **read**,  **update**,  **filter**,  **delete**  and  **bulk**  operations JavaScript objects in Redis  **without needing to know Redis commands**.\n\nIt is used effortlessly without installing any plugins like RedisJSON. The system works with Hashes. It shreds the objects and saves them as key strings in the hash, and while reading, they break it down again according to the given scheme and type conversion with TypeScript. ***Also you can use String Data type too.***\n\n\u003e Although currently only Hash and String types are processed, our [new version](https://github.com/anchovycation/metronom/milestone/2 \"see v3.0.0 milestone\") that will support [all core types](https://redis.io/docs/data-types/) is on the way.\n\n| Documentation | Source Code | Package |\n| ------- | ----------- | ------- |\n| [anchovycation.github.io/metronom](https://anchovycation.github.io/metronom/) | [GitHub](https://github.com/anchovycation/metronom) | [npm](https://www.npmjs.com/package/metronom) |\n\n---\n\n## Let's start\n### 1. Install `metronom`\nFirstly, install this package to your project via your package manager.\n\n**npm**:\n```bash\nnpm i metronom\n```\n**yarn**:\n```bash\nyarn add metronom\n```\n### 2. Create `Metronom` object\nThe `Metronom` object is create `Model` with your defined options like `port`, `host`, `url` or `ttl`. This step is not required but **recomended** because at the unnormal usage scenario(you need to use diffirent url from default redis ...) you must to pass that options to all `Model` defines otherwise `Metronom` object do it automatically.\n\n```js\nimport { Metronom } from 'metronom';\n\nconst metronom = new Metronom({\n  redisClientOptions: {\n    host: '172.168.1.123',\n    port: 1234\n  }\n});\n```\n\n#### 2.1 Get/Set String Key\n  Now, you can get/set key from defined metronom object\n  ```js\n  \n    const isSuccess = await metronom.setKey('foo', 'bar'); // its return \"OK\"\n    const value = await metronom.getKey('foo'); // bar\n  ```\n\n### 3. Define `Model`\n`Model` is redis hash maper. It has two diffirent flow.\n+ `flex`: you don't need to define schema. All hash keys dynamically mapped\n+ `schema based`: You define type, default value etc. in to the schema and metronom use it read/write operations. Keys not found in the schema are ignored.\n```js\nconst userModel = metronom.define(\n// const userModel = new Model(\n  schema, redisKeyPrefix, modelOptions\n);\n```\n### 4. Use model's query inferface\nNow, you can use all metronom queries(`Metronom`, `Model` and `ModelInstance`) like `Model.create`, `Model.findById`, `Model.destroy`, `ModelInstance.save`, etc. .\n\nStart coding the project that will save the world :)\n\n**For example**:\n```js\nconst { Metronom, Model, Types, LogLevels } = require('metronom');\n\nconst metronom = new Metronom({\n  redisClientOptions: {\n    host: '172.168.1.123',\n    port: 1234\n  },\n  log: LogLevels.Error\n});\n\nconst userModel = metronom.define(\n// const userModel = new Model(\n  {\n    name: {\n      type: Types.String,\n    },\n    surname: {\n      type: Types.String,\n    },\n    age: {\n      type: Types.Number,\n      default: 1\n    },\n    isAdmin: {\n      type: Types.Boolean,\n      dafeult: false,\n    }\n  },\n  'users', // default `object`\n  { \n    keyUnique: 'name', // if you don't define, we use unix timestamp for `keyUniqe` value\n    log: LogLevels.All, // default is `None`\n    // set `flexSchema` to true and never define schema\n  }\n);\n\nlet user = await userModel.create({\n  name: 'Chandler',\n  surname: 'Bing',\n  age: 18,\n});\n// Redis key - 'users:Chandler'\n// {\n//  name: 'Chandler',\n//  surname: 'Bing',\n//  age: 18,\n//  isAdmin: false\n// }\n\nuser.isAdmin = true;\nawait user.save();\n\nlet admin = userModel.findById('Chandler');\n// {\n//  name: 'Chandler',\n//  surname: 'Bing',\n//  age: 18,\n//  isAdmin: true\n// }\n\n// del users:Chandler\nawait admin.destroy();\n```\n\n## Commands\n### Metronom Basic\nMetronom object is main and static operator object which `Model` creator and non-hash type operator.\n\n```js\nconst metronom = new Metronom({\n  redisClientOptions: {\n    url: 'redis://localhost:6380',\n    // host: '172.168.1.123',\n    // port: 1234\n  }\n});\n```\n\n### Configs\n\n**Paramaters:**\n\u003e All keys in to the one object\n\n| Key | Type | Default Value |\n| --- | ---- | ------------- |\n| `redisClientOptions` | `RedisClientOptions` `object` | `undefined` |\n| `log` | `boolean` `LogLevels` | `false` |\n\n#### `define`\nIt create `Model` from this `Metronom` options. For detail  go to [Model Basics](#model-basics)\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| schema | `Schema` |  |\n| key prefix | `string` | `objects` |\n| model options | `ModelOptions` | `undefined` |\n\n```js\n    const tokenModel = await metronom.define({}, 'tokens', { flexSchema: true });\n```\n\n#### `setKey`\nSet String key\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| key | `string` |  |\n| value | `string` |  |\n\n```js\n  const isOk = await metronom.setKey('foo', 'bar'); // OK\n```\n\n#### `getKey`\nGet String key\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| key | `string` |  |\n\n```js\n  // await metronom.setKey('foo', 'bar');\n  const value = await metronom.getKey('foo'); // bar\n```\n\n### Model Basics\nRepresents the Redis object you created in your database. You can create, read, update, delete, filter operations. It also includes system information.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| schema | `Schema` |  |\n| key prefix | `string` | `objects` |\n| model options | `ModelOptions` | `undefined` |\n\n```js\n// create user model\n// new Model(\u003cmodel-schema\u003e, \u003credis-key-prefix\u003e, \u003cmodel-options\u003e)\nconst userModel = new Model(\n  {\n    name: {\n      type: Types.String,\n      default: 'Joe',\n    },\n    surname: {\n      type: Types.String,\n    },\n    age: {\n      type: Types.Number,\n      default: 1,\n    },\n    isAdmin: {\n      type: Types.Boolean,\n      default: false,\n    },\n  },\n  'users', // default `object`\n  {\n    keyUnique: 'name', // if you don't define, we use unix timestamp for `keyUniqe` value\n    // set `flexSchema` to true and never define schema\n    // you can set custom `redisClientOptions` here\n  }\n);\n\n// const tokenModel = new Model({}, 'tokens', {isFlex: true});\n```\n### CREATE Methods\n#### `create`\n\nCreates `ModelInstance` by parameter then saves it to Redis and returns it.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| data | `object` | `{}` |\n\n```js\n// create user\n// create(\u003cvalue-object\u003e)\nconst user = await userModel.create({ name: \"Beyza\", surname: \"Erkan\" });\n// { \n//   firstName: \"Beyza\",\n//   lastName: \"Erkan\",\n//   age: 1,\n//   isAdmin: false,\n//   _Model: {\n//     _model: [Model Object],\n//     _dataInfo: {\n//       redisKey: 'users:Beyza'\n//     }\n//   }\n// }\n\n```\n### READ Methods\n#### `findById`\nFetches record by  `keyUnique` . Returns ModelInstance or null.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| key unique | `number` `string` |  |\n\n```js\n// find user with id\n// findById(\u003cid\u003e)\nuser = await userModel.findById(user.name);\nconsole.log({ user: user.getPureData() });\n```\n#### `getAll`\nFetches all records with the same  `keyPrefix`  value. Returns list of ModelInstance.\n\n**Paramaters:**\n\u003e All keys in to the one object\n\n| Key | Type | Default Value |\n| --- | ---- | ------------- |\n| `limit` | `number` | undefined |\n\n\n```js\n// find all users\nlet users = await userModel.getAll();\nconsole.log({ users });\n```\n#### `filter`\nFilters in the same way as  `Array.filter`, pulling all records with the same  `keyPrefix`  value. Returns filtred ModelInstances or empty array.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| filter function | `FilterFunction` |  |\n\n```js\n// filters users by condition\n// filter(filter-function)\n// filter function takes the values  (value, index, array) and returns  `true`  then the record is filtered. It can be asynchronous function\nlet users = await  userModel.filter((user) =\u003e  user.age \u003e 18);\nconsole.log({ users })\n```\n### DELETE Methods\n#### `deleteById`\nDelete record by `keyUnique`.  Returns deleted records count it always '1' if it succesfull.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| key unique | `number` `string` |  |\n\n```js\n// delete user with id\n// deleteById(\u003cid\u003e)\nlet isDeleted = await userModel.deleteById(user.name);\nconsole.log({ isDeleted });\n```\n#### `deleteAll`\nDelete all records with the same  `keyPrefix`  value. Returns deleted records count or 0.\n```js\n// delete all users\nawait userModel.deleteAll();\n```\n### Other Methods\n#### `runCommand`\nRedis command executer.\n\n**Paramaters:**\n| paramater | Type | Default Value |\n| --- | ---- | ------------- |\n| command array | `array` |  |\n\n```js\n// runCommand(\u003ccommands\u003e)\nuserModel.runCommand(['hget', 'user:1234', 'name'])\n```\n\n## ModelInstance Basics\nIt is the object from the Redis. You can directly process on the record then save or destroy it.\n### UPDATE Methods\n#### `save`\nSaves the current state of the object to Redis.\n```js\n// update user and save\nlet user = await userModel.create({ name: \"Beyza\", surname: \"Erkan\" });\nuser.age = 20;\nawait user.save();\n```\n\n### DELETE Methods\n#### `destroy`\nDestroy the object from Redis. Returns true or false that it has been deleted.\n```js\n// destroy this user object\nawait  user.destroy();\n```\n\n### OTHER Methods\n#### `getPureData`\nClears all metronom-related data within the object and restores it to its raw state. Returns raw data.\n```js\n// get raw data of user\nuser = await  userModel.findById(user.name);\nconsole.log({ user:  user.getPureData() });\n```\n#### `toJSON`\nConverts the object to JSON. Returns stringified object.\n```js\n// convert the user object to JSON\nuser = await  userModel.findById(user.name);\nconsole.log({ user: user.toJSON() });\n```\n\n## Contributors\n\u003ca href = \"https://github.com/anchovycation/metronom/graphs/contributors\"\u003e\n  \u003cimg src = \"https://contrib.rocks/image?repo=anchovycation/metronom\"/\u003e\n\u003c/a\u003e\n\n## License\n[GNU GENERAL PUBLIC LICENSE Version 3](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanchovycation%2Fmetronom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanchovycation%2Fmetronom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanchovycation%2Fmetronom/lists"}