{"id":23152406,"url":"https://github.com/1amageek/scenario","last_synced_at":"2025-08-17T20:32:51.145Z","repository":{"id":38773913,"uuid":"267500950","full_name":"1amageek/scenario","owner":"1amageek","description":"The scenario is the Cloud Functions support library. It is possible to clarify the dependency and limit the side effects.","archived":false,"fork":false,"pushed_at":"2023-01-10T00:40:51.000Z","size":2813,"stargazers_count":6,"open_issues_count":16,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-24T16:42:53.706Z","etag":null,"topics":["cloudfunctions","firebase-functions","google-cloud-platform"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/1amageek.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-05-28T05:25:53.000Z","updated_at":"2023-01-31T13:12:09.000Z","dependencies_parsed_at":"2023-02-08T16:15:47.762Z","dependency_job_id":null,"html_url":"https://github.com/1amageek/scenario","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/1amageek%2Fscenario","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1amageek%2Fscenario/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1amageek%2Fscenario/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1amageek%2Fscenario/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/1amageek","download_url":"https://codeload.github.com/1amageek/scenario/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230167887,"owners_count":18183846,"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":["cloudfunctions","firebase-functions","google-cloud-platform"],"created_at":"2024-12-17T19:14:36.661Z","updated_at":"2024-12-17T19:14:37.303Z","avatar_url":"https://github.com/1amageek.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# scenario\n\n`scenario` is a framework for describing CloudFunctions based on data relationships.\n\nWe designed the following for large scale development in CloudFunctions.\nFirst, we separated CloudFirestore's data by domain based on the SRP (Single Responsibility Principle).\n\nFor example.\nWe used `social` for the treatment of social features, and separated it with `message` for the treatment of message features.\n\n```\nsocial/v1/users/:uid\n```\n\n```\nmessage/v1/users/:uid\n```\n\nThis design works very well with the scalability of the specification. \nWe prohibited client-side cross-domain processing and left it to CloudFunctions to handle. This is because coding across domains can complicate management and make maintenance difficult for clients.\n\nProcessing using the API is coded procedurally. Programs that run sequentially are easy to understand, even if there is processing across multiple domains.\nEven today, APIs using Callable Functions are easier to understand if you write them that way.\nHowever, in order to take advantage of the features of Firestore SDK, it is not a good idea to make extensive use of Callable Functions. This is because we can't support offline and we can't use WriteBatch.\nIt's important to use the Firestore Trigger efficiently in order to develop with the advantages of Firestore.\n\nWe decided to use Cloud Functions, specifically the Firestore Trigger, to do the inter-domain processing. But it also created a new problem. Firestore Trigger was difficult to describe the order in which it would be executed and the relationships between the data, making it significantly less maintainable.\n\n__Scenario__ allows for redundancy in Cloud Functions and focuses on the flow of data across domains.\n\n![scenario](https://github.com/1amageek/scenario/blob/master/docs/concept.png)\n\n![scenario](https://github.com/1amageek/scenario/blob/master/docs/image0.png)\n\n![scenario](https://github.com/1amageek/scenario/blob/master/docs/image1.png)\n\n![scenario](https://github.com/1amageek/scenario/blob/master/docs/image2.png)\n\n## Usage\n\n```typescript\nexport const sendPushNotification = Builder(functions.region('us-central1'), context =\u003e {\n\n    context.handler('/socail/{version}/users/{uid}/feeds/{feedId}/actions/{actionId}', document =\u003e {\n        document.onCreate(async (snapshot, _) =\u003e {\n            const from: string = snapshot.data()!.from\n            const to: string = snapshot.data()!.to\n            const id: string = [from, to].sort().join('')\n            await admin.firestore().collection(`/message/v1/rooms/${id}/transcripts`).doc().set({\n                'message': 'You have new message.'\n            })\n        })\n    })\n\n    context.handler('/message/{version}/rooms/{roomId}/transcripts/{transcriptId}', document =\u003e {\n        document.onCreate((snapshot, _) =\u003e {\n            // Send PushNotification\n        })\n    })\n})\n```\n\n### with Dependency\n\nScenario allows you to limit the sphere of influence within which side effects occur in a field. If there are no changes in the fields defined in the Dependency List, no side effects will occur.\n\nIn the following example, the same DocumentReference is defined, but the side effects depend on changes to `createdAt` and `updatedAt`. In addition, CloudFunctions is defined as two Functions.\n\n```typescript\nexport const productChangeLog = Builder(functions.region('us-central1'), context =\u003e {\n\n    context.handler('/commerce/{version}/product/{productId}', document =\u003e {\n        document.onWrite(async (snapshot, ctx) =\u003e {\n            await snapshot.after.ref.collection('logs').doc().set({\n                editorId: ctx.auth!.uid,\n                type: 'create'\n            })\n        }, ['createdAt'])\n    })\n\n    context.handler('/commerce/{version}/product/{productId}', document =\u003e {\n        document.onWrite(async (snapshot, ctx) =\u003e {\n            await snapshot.after.ref.collection('logs').doc().set({\n                editorId: ctx.auth!.uid,\n                type: 'update'                \n            })\n        }, ['updatedAt'])\n    })\n\n    context.handler('/commerce/{version}/product/{productId}/logs/{logId}', document =\u003e {\n        document.onCreate((snapshot, _) =\u003e {\n            // Send Message\n        })\n    })\n})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1amageek%2Fscenario","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F1amageek%2Fscenario","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1amageek%2Fscenario/lists"}