{"id":20173132,"url":"https://github.com/apitable/apphook","last_synced_at":"2025-04-10T03:16:57.448Z","repository":{"id":61805932,"uuid":"555359236","full_name":"apitable/apphook","owner":"apitable","description":"`apphook` is a way to implant/modify other piece of code.","archived":false,"fork":false,"pushed_at":"2023-03-24T19:24:48.000Z","size":263,"stargazers_count":23,"open_issues_count":2,"forks_count":6,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2024-10-29T15:01:45.905Z","etag":null,"topics":["event-manager","hooks","typescript","wordpress"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/apphook","language":"TypeScript","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/apitable.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-21T12:29:33.000Z","updated_at":"2024-10-20T14:01:54.000Z","dependencies_parsed_at":"2024-06-18T21:27:10.150Z","dependency_job_id":"bf99c327-9ac8-48e9-b4e2-43e26c196a6a","html_url":"https://github.com/apitable/apphook","commit_stats":{"total_commits":24,"total_committers":1,"mean_commits":24.0,"dds":0.0,"last_synced_commit":"47db163942a7573c5dcaae485f3fbd82cdf74d02"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apitable%2Fapphook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apitable%2Fapphook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apitable%2Fapphook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apitable%2Fapphook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apitable","download_url":"https://codeload.github.com/apitable/apphook/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247861118,"owners_count":21008427,"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":["event-manager","hooks","typescript","wordpress"],"created_at":"2024-11-14T01:33:51.276Z","updated_at":"2025-04-10T03:16:57.424Z","avatar_url":"https://github.com/apitable.png","language":"TypeScript","readme":"\n![apphook](https://socialify.git.ci/apitable/apphook/image?description=1\u0026font=Inter\u0026language=1\u0026name=1\u0026pattern=Diagonal%20Stripes\u0026stargazers=1\u0026theme=Dark)\n# apphook: Event-Manager Hook Engine \n\n[![npm](https://img.shields.io/npm/v/apphook)](https://www.npmjs.com/package/apphook)\n[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/apitable/apphook/npm-publish)](https://github.com/apitable/apphook/actions)\n[![npm bundle size](https://img.shields.io/bundlephobia/min/apphook)](https://www.npmjs.com/package/apphook)\n[![npm](https://img.shields.io/npm/dm/apphook)](https://www.npmjs.com/package/apphook)\n\n`apphook` is a way to implant/modify other piece of code.\n\nIt is a lightweight Event-Manager that inspired by [Wordpress Hooks](https://developer.wordpress.org/plugins/hooks/)\n\nComputer software is a sort of sequence. We build software according to the business.\n\nHowever, the user's behaviors are out-of-sequence and chaos.\n\nYou will never know what users want, how they use your software, what they want to customization.\n\nSo, we need to prepare a system to deal with out-of-sequence and chaos, which can make big changes and flexible customization available.\n\nThat's why we should know `AppHook`.\n\n`AppHook` is a hooks engine which Event-Driven. It can intercept users' behaviors and extend our functionalities.\n\n## Quick Start\n\n```bash\nnpm i --save apphook\n```\n\n\nTypeScript types declarations (.d.ts) are ready.\n\nSee [examples](#example) for usage examples.\n\n## Principle\n\nWe place AppHook hooks in code and trigger event.\n\nFor example, when user click the button A,  we can trigger a event called \"click:button:A\"\n\nWe have two way to trigger event:\n\n1. Trigger. When event appear, do some actions or behaviors, it would not change code pipeline path.\n2. Filter. When event appear, it will do some actions and behaviors, return a object. It can be an interceptor.\n\n\n## Use Case\n\n- Event Tracking：Don't need to hard code in the code anymore, we can put all event tracking code in the file by bind and unbind.\n- Rookie Onboarding: New register user onboarding\n- Help Guiding: when the 10th click on a button, popup a UI window.\n- Users Tasks: check whether user finished some tasks.\n- Marketing Events: If match some condition, do something like popup a marketing ui windows.\n- Users Recall: If user has not login 30 days, do something.\n- Payment Interception: When click a feature button, users have no payment yet, trigger and open a UI windows until payment finished and go on.\n- Third Party: customize 3rd plugins or more features\n- ......\n\n## Terms\n\n- hook：\n    - hookState：\n    - hookArgs：\n- binding：\n    - add_trigger：\n    - remove_trigger：\n    - add_filter：\n    - remove_filter：\n- trigger\n    - triggerCommand:\n    - triggerCommandArg ：any\n- filter：\n    - filterCommand:\n    - filterCommandArg:\n- rule \n    - condition\n    - conditionArgs\n- action:\n    - trigger action: \n        - trigger command: \n        - arg: \n    - filter action: \n        - filter command: \n        - filter command arg: \n- listener ：\n    - trigger Listner：\n    - filter Listner：\n\n\n\n\n## Example\n\n### Use Trigger to Event Tracking\n\n```typescript\n// Window.tsx\n// ...\nonClickLoginButton: () =\u003e {\n    // ...\n    apphook.doTrigger('user:click_login_button');\n\n}\n// ...\n```\n\n```typescript\n//  EventTracking.ts, a independent file for event tracking \napphook.addTrigger('user:click_login_button', (args) =\u003e {\n\n    // Event Tracking Code\n    EventTracking.track('user:click_login_button', {...});\n\n    tracker.track('user:click_login_button', {...});\n    tracker.setProfile({email:'xxx@xxx.com'});\n});\n```\n\n\n### Use Filter, make contact number nickname customizable\n\n```typescript\napphook.addFilter('get_form_name', (defaultValue, args) =\u003e {\n    let user = args[0];\n    if (user.is_cloud) {\n        return \"Member ID\";\n    } else if (user.is_self_hosted) {\n        return \"Employee ID\";\n    }\n    return defaultValue;\n});\n```\n\n```typescript\n// UI.tsx\n\u003cForm name=\"{apphook.applyFilters('get_form_name', 'ID')}\" /\u003e  \n// Here will get the result \"Member ID\" or \"Employee ID\" or \"ID\"\n```\n\n## Rookie popup guiding\n\nIf you want: \n\u003e When a female user get into your product the 10 times, popup \"congratulation, you have used 10 times\"\n\nBreak it down:\n\n- trigger: user get into the 10th times\n    - hook: get into product(application:start)\n    - hookState: the 10th times\n    - rule: female\n        - condition: gender == femail\n    - action: \n        - command: popup\n        - command: \"congratulation, you have used 10 times\"\n        \n\nRelevant code:\n```typescript\n// trigger event\napphook.doTrigger('application:start', [],  10) // the 10th times get in\n\n// add trigger\napphook.addTrigger('application:start', (args, hookState) =\u003e {\n    if (hookState == 10) {\n        showWindow('congratulation, you have used 10 times');\n    }\n}, {\n    doCheck: (args) =\u003e {\n            return user.gender === 'female';\n}});\n```\n\n    \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapitable%2Fapphook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapitable%2Fapphook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapitable%2Fapphook/lists"}