{"id":15417281,"url":"https://github.com/ampatspell/firerules","last_synced_at":"2025-04-05T08:11:34.914Z","repository":{"id":57236785,"uuid":"300039464","full_name":"ampatspell/firerules","owner":"ampatspell","description":"🔥 Firestore rules dsl / generator","archived":false,"fork":false,"pushed_at":"2020-12-11T17:42:10.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-13T15:03:54.377Z","etag":null,"topics":["dsl","firestore","generator","rules","security"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ampatspell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-30T19:35:18.000Z","updated_at":"2020-12-11T17:42:13.000Z","dependencies_parsed_at":"2022-08-26T15:11:29.532Z","dependency_job_id":null,"html_url":"https://github.com/ampatspell/firerules","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ampatspell%2Ffirerules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ampatspell%2Ffirerules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ampatspell%2Ffirerules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ampatspell%2Ffirerules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ampatspell","download_url":"https://codeload.github.com/ampatspell/firerules/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305940,"owners_count":20917208,"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":["dsl","firestore","generator","rules","security"],"created_at":"2024-10-01T17:15:09.935Z","updated_at":"2025-04-05T08:11:34.896Z","avatar_url":"https://github.com/ampatspell.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Firerules\n\nFirestore rules javascript DSL and generator.\n\n``` bash\n$ node ./examples/dsl.js # dsl-only\n$ node ./examples/generate.js # full example (dsl \u0026 ejs)\n```\n\n## Sample\n\n``` javascript\n// firestore.js\nconst { generate } = require('firerules');\n\ngenerate(__dirname, 'firestore.rules', function() {\n\n  this.helper.block('token', function() {\n    return this.prop('_token').type('string').optional().writable();\n  });\n\n  this.helper.block('type', function(values, creatable=true) {\n    let node = this.prop('type').type('string').values(values);\n    if(creatable) {\n      this.create(function() {\n        this.prop('type').writable();\n      });\n    }\n    return node;\n  });\n\n  this.define('thing', function() {\n\n    this.token();\n    this.type([ 'book', 'bookmark' ]);\n\n    this.if(this.eq('type', 'book'), function() {\n\n      this.prop('book').type('string').writable();\n\n      this.create(function() {\n        this.prop('book').optional().nullable();\n      });\n\n      this.map('size').define(function() {\n        this.prop('width').type('int');\n        this.prop('height').type('int');\n      });\n\n      this.update(function() {\n        this.map('size').writable().define(function() {\n          this.prop('width').writable();\n          this.prop('height').writable();\n        });\n      });\n\n    }).elseif(this.eq('type', 'bookmark'), function() {\n\n      this.prop('bookmark').type('string').writable();\n\n    }).else(function() {\n\n      this.prop('fallback').type('string').writable();\n\n    });\n\n  });\n\n});\n```\n\n``` ejs\nrules_version = '2';\n\nservice cloud.firestore {\n  match /databases/{database}/documents {\n\n    match /things/{id} {\n      allow read: if true;\n      allow create: if \u003c%= doc('thing').create(4) %\u003e;\n      allow update: if \u003c%= doc('thing').update(4) %\u003e;\n    }\n\n  }\n}\n```\n\n``` bash\n$ node ./examples/generate.js\nfirestore.rules.ejs → firestore.rules\n```\n\ngenerates:\n\n``` firestore.rules\n// firestore.rules\n\n// ...\n\nallow create: if\n  request.resource.data.keys().toSet().hasOnly([\n      \"_token\",\n      \"type\",\n      \"book\",\n      \"bookmark\",\n      \"fallback\"\n  ]) \u0026\u0026\n  (\n    !(\"_token\" in request.resource.data.keys()) ||\n    request.resource.data._token is string\n  ) \u0026\u0026\n  request.resource.data.type in [ \"book\", \"bookmark\" ].toSet() \u0026\u0026\n  (\n    (\n      request.resource.data.type == \"book\" \u0026\u0026\n      !request.resource.data.keys().toSet().hasAny([ \"bookmark\", \"fallback\" ]) \u0026\u0026\n      (\n        (\n          !(\"book\" in request.resource.data.keys()) ||\n          (\n            request.resource.data.book == null ||\n            request.resource.data.book is string\n          )\n        )\n      )\n    ) ||\n    (\n      request.resource.data.type == \"bookmark\" \u0026\u0026\n      !request.resource.data.keys().toSet().hasAny([ \"book\", \"fallback\" ]) \u0026\u0026\n      (request.resource.data.bookmark is string)\n    ) ||\n    (\n      !request.resource.data.keys().toSet().hasAny([ \"book\", \"bookmark\" ]) \u0026\u0026\n      (request.resource.data.fallback is string)\n    )\n  );\n\nallow update: if\n  request.resource.data.diff(resource.data).affectedKeys().hasOnly([\n    \"_token\",\n    \"book\",\n    \"size\",\n    \"bookmark\",\n    \"fallback\"\n  ]) \u0026\u0026\n  (\n    !(\"_token\" in request.resource.data.keys()) ||\n    request.resource.data._token is string\n  ) \u0026\u0026\n  (\n    (\n      request.resource.data.type == \"book\" \u0026\u0026\n      !request.resource.data.diff(resource.data).affectedKeys().hasAny([\n        \"bookmark\",\n        \"fallback\"\n      ]) \u0026\u0026\n      (\n        request.resource.data.book is string \u0026\u0026\n        (\n          (\n            resource.data.size is map \u0026\u0026\n            request.resource.data.size.diff(resource.data.size).affectedKeys().hasOnly([\n              \"width\",\n              \"height\"\n            ])\n          ) ||\n          request.resource.data.size.keys().toSet().hasOnly([ \"width\", \"height\" ])\n        ) \u0026\u0026\n        request.resource.data.size.width is int \u0026\u0026\n        request.resource.data.size.height is int\n      )\n    ) ||\n    (\n      request.resource.data.type == \"bookmark\" \u0026\u0026\n      !request.resource.data.diff(resource.data).affectedKeys().hasAny([\n        \"book\",\n        \"size\",\n        \"fallback\"\n      ]) \u0026\u0026\n      (\n        request.resource.data.bookmark is string\n      )\n    ) ||\n    (\n      !request.resource.data.diff(resource.data).affectedKeys().hasAny([\n        \"book\",\n        \"size\",\n        \"bookmark\"\n      ]) \u0026\u0026\n      (\n        request.resource.data.fallback is string\n      )\n    )\n  );\n```\n\n``` javascript\nconst firerules = require('firerules');\n// {\n//   generate: [Function: generate],\n//   dsl: {\n//     define: [Function: define],\n//     helper: {\n//       block: [Function],\n//       prop: [Function]\n//     }\n//   },\n//   ejs: {\n//     render: [Function: render]\n//   }\n// }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fampatspell%2Ffirerules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fampatspell%2Ffirerules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fampatspell%2Ffirerules/lists"}