{"id":19336441,"url":"https://github.com/syarul/requrse","last_synced_at":"2025-02-24T07:44:31.175Z","repository":{"id":186152647,"uuid":"673578344","full_name":"syarul/requrse","owner":"syarul","description":"Lightweight driven query language","archived":false,"fork":false,"pushed_at":"2023-12-11T08:50:04.000Z","size":273,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-26T16:46:40.977Z","etag":null,"topics":["falcor","graphql","query","query-language","query-language-processor"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/syarul.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-02T00:46:10.000Z","updated_at":"2024-07-02T11:34:18.189Z","dependencies_parsed_at":null,"dependency_job_id":"e9b6c5e6-99c6-4713-94b8-713604bd6f91","html_url":"https://github.com/syarul/requrse","commit_stats":null,"previous_names":["syarul/requrse"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syarul%2Frequrse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syarul%2Frequrse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syarul%2Frequrse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syarul%2Frequrse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/syarul","download_url":"https://codeload.github.com/syarul/requrse/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240441872,"owners_count":19801791,"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":["falcor","graphql","query","query-language","query-language-processor"],"created_at":"2024-11-10T03:11:07.876Z","updated_at":"2025-02-24T07:44:31.126Z","avatar_url":"https://github.com/syarul.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reQurse\nLightweight driven query language\n\n[![NPM Version](https://img.shields.io/npm/v/requrse.svg)](https://www.npmjs.com/package/requrse)\n[![requrse CI](https://github.com/syarul/requrse/actions/workflows/main-ci.yml/badge.svg)](https://github.com/syarul/requrse/actions/workflows/main-ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/syarul/requrse/badge.svg?branch=main)](https://coveralls.io/github/syarul/requrse?branch=main)\n\n## What is reQurse\n**reQurse** introduces an innovative approach that overcomes the complexities of CRUD operations. The focus is on delivering a streamlined and efficient CRUD library solution, simplifying API development, and effortlessly handling complex data management tasks. **reQurse** utilized JSON-based queries, allows multi-tenant API sources, avoid writing lengthy procedural APIs and truly embrace Javascript core philosophy as OOP language. This approach promotes a modular and streamlined code structure, retaining the complexity of `Object` tree while enhancing flexibility and maintainability.\n\nHere's the first example to get you started. [Try it here](https://codepen.io/syarul/pen/xxmLMVP)—no build step required!\n\n\u003e This library take some inspirations from NextQL and GraphQL\n\n## Usage\n\nA basic usage of reQurse.\n```javascript\nimport rq from 'requrse'\n\nrq(query, { methods, config })\n```\n- **query**: *(object)* ***required*** JSON like query.\n- **methods**: *(object)* ***required*** define methods/computed fields that exist in the query.\n- **config**: *(object)* ***optional*** extend and added parameterize control over methods.\n```js\nawait rq({\n  Test: {\n    test: {\n      greeting: '*'\n    }\n  }\n},\n{\n  methods: {\n    greeting () {\n      return 'hello world'\n    }\n  }\n}).then(console.log, console.error)\n// { Test: { test: { greeting: 'hello world' } } }\n```\n\n## Advance usage\nA proper query should do more, to demystify the capability of this library, create a few data samples, you can imagine this as a setup that your database may have.\n\n```js\nconst acolyte = { id: '0', progression: ['1', '4'], name: 'Acolyte' }\nconst priest = { id: '1', progression: ['4'], name: 'Priest' }\nconst squire = { id: '2', progression: ['3', '4'], name: 'Squire' }\nconst paladin = { id: '3', progression: ['4'], name: 'Paladin' }\nconst inquisitor = { id: '4', progression: [], name: 'Inquisitor' }\n\n// we also create the relations between them\nconst supportData = {\n  0: acolyte,\n  1: priest,\n  4: inquisitor\n}\n\nconst vanguardData = {\n  2: squire,\n  3: paladin,\n  4: inquisitor\n}\n```\n\nThen the helper functions to access these data\n```js\n/**\n * Helper function to get a class by ID.\n */\nfunction getClass (id) {\n  // Returning a promise just to illustrate query support.\n  return Promise.resolve(supportData[id] || vanguardData[id])\n}\n/**\n * Allows us to query for a classes's progression.\n */\nfunction getProgression (classes) {\n  return classes.progression.map(id =\u003e getClass(id))\n}\n/**\n * Allows us to query for the support class with the given id.\n */\nfunction getSupport (id) {\n  return supportData[id]\n}\n/**\n * Allows us to query for the vanguard class with the given id.\n */\nfunction getVanguard (id) {\n  return vanguardData[id]\n}\n/**\n * Allows us to query for the player class by gameId.\n */\nfunction getPlayer (gameId) {\n  if (gameId === 0) {\n    return acolyte\n  }\n  return inquisitor\n}\n```\n\nThen configure `reQurse` to use these methods\n```js\nconst confParams = {\n  getPlayer, getClass, getProgression, getSupport, getVanguard\n}\n\nconst config = (param) =\u003e confParams[param]\n\nconst methods = {\n  player: 'getPlayer',\n  class: 'getClass',\n  progression: 'getProgression',\n  support: 'getSupport',\n  vanguard: 'getVanguard'\n}\n```\n\nSimple usage\n```js\nawait rq({\n  PlayerClass: {\n    player: {\n      name: 1\n    }\n  }\n}, { methods, config }).then(console.log)\n// { PlayerClass: { player: { name: 'Inquisitor' } } }\n```\n\nUse `$params` to filter result\n```js\nawait rq({\n  PlayerClass: {\n    player: {\n      $params: { gameId: 0 },\n      name: 1\n    }\n  }\n}, { methods, config }).then(console.log)\n// { PlayerClass: { player: { name: 'Acolyte' } } }\n```\n\nOptimize your query by writing efficient methods, i.e., here `progression` return the class next progression seamlessly\n```js\nawait rq({\n  PlayerClass: {\n    player: {\n      $params: { gameId: 0 },\n      id: 1,\n      name: 1,\n      progression: {\n        name: 1\n      }\n    }\n  }\n}, { methods, config }).then(console.log)\n// {\n//   PlayerClass: {\n//     player: {\n//       id: '0',\n//       name: 'Acolyte',\n//       progression: [\n//         { name: 'Priest' },\n//         { name: 'Inquisitor' }\n//       ]\n//     }\n//   }\n// }\n```\n\nYou can have multiple same dataset key name by `/` naming\n```js\nawait rq({\n  vanguard: {\n    'vanguard/paladin': {\n      $params: { id: 3 },\n      name: 1\n    },\n    'vanguard/inquisitor': {\n      $params: { id: 4 },\n      name: 1\n    }\n  }\n}, { methods, config }).then(console.log)\n// {\n//   vanguard: {\n//     'vanguard/paladin': { name: 'Paladin' },\n//     'vanguard/inquisitor': { name: 'Inquisitor' }\n//   }\n// }\n```\n\nNow we expand the dataset to the inventory of the player\n```js\nconst healingPotion = { id: '0', effect: 'heal', dmg: 4, name: 'Healing Potion' }\nconst bandage = { id: '1', effect: 'heal', dmg: 1, name: 'Bandage' }\nconst holyWater = { id: '2', effect: 'cleansing', dmg: 2, name: 'Holy Water' }\n\n// add relations to the inventory data\nconst itemData = {\n  0: healingPotion,\n  1: bandage,\n  2: holyWater\n}\n\n// add relations to how many each class have these items in their inventory\nconst inventoryData = {\n  0: [7, 1, 0],\n  1: [3, 2, 2],\n  2: [0, 5, 0],\n  3: [1, 6, 2],\n  4: [0, 0, 10]\n}\n```\n\nDemonstrate usage of method/computed field to return value that you need, in this case `count` which came from a relational collection that store the value only, you can use such logic to build a powerful query for your api.\n```js\n/**\n * Helper function to get an item by ID.\n */\nfunction getItem (count, id) {\n  // Returning a promise just to illustrate query support.\n  return Promise.resolve({ ...itemData[id], count })\n}\n\n/**\n * Allows us to query for the player class inventoryData.\n */\nfunction getInventory ({ id }) {\n  return inventoryData[id].map(getItem)\n}\n```\n\nExtends the reQurse methods/config\n```js\nconst extConfig = {\n  methods: {\n    ...methods,\n    item: 'getItem',\n    inventory: 'getInventory'\n  },\n  config: (param) =\u003e ({\n    ...confParams,\n    getItem,\n    getInventory\n  })[param]\n}\n```\n\nNow see how it perform!\n```js\nawait rq({\n  PlayerClass: {\n    player: {\n      $params: { gameId: 0 },\n      name: 1,\n      inventory: {\n        id: 1,\n        name: 1,\n        count: 1\n      }\n    }\n  }\n}, extConfig).then(console.log)\n// {\n//   PlayerClass: {\n//     player: {\n//       name: \"Acolyte\",\n//       inventory: [\n//         {\n//           id: \"0\",\n//           name: \"Healing Potion\",\n//           count: 7\n//         },\n//         {\n//           id: \"1\",\n//           name: \"Bandage\",\n//           count: 1\n//         },\n//         {\n//           id: \"2\",\n//           name: \"Holy Water\",\n//           count: 0\n//         }\n//       ]\n//     }\n//   }\n// }\n```\nYou can also return as dataUrl\n```js\nawait rq({\n  PlayerClass: {\n    player: {\n      $params: { gameId: 0 },\n      name: 1,\n      inventory: {\n        id: 1,\n        name: 1,\n        count: 1\n      }\n    }\n  }\n}, { ...extConfig, dataUrl: 'PlayerClass/player/inventory' }).then(console.log)\n// [\n//   {\n//     id: '0',\n//     name: 'Healing Potion',\n//     count: 7\n//   },\n//   {\n//     id: '1',\n//     name: 'Bandage',\n//     count: 1\n//   },\n//   {\n//     id: '2',\n//     name: 'Holy Water',\n//     count: 0\n//   }\n// ]\n```\n\n## More Samples\nYou can check [samples](https://github.com/syarul/requrse/blob/main/samples) folder to see more usage cases with [Mongoose](https://github.com/syarul/requrse/blob/main/samples/mongoose), [Redis](https://github.com/syarul/requrse/blob/main/samples/redis) and the [Starwars](https://github.com/syarul/requrse/blob/main/samples/starwars) examples.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyarul%2Frequrse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyarul%2Frequrse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyarul%2Frequrse/lists"}