{"id":28455217,"url":"https://github.com/mtdowling/emitter.tl","last_synced_at":"2025-09-15T02:16:20.851Z","repository":{"id":267483327,"uuid":"900932694","full_name":"mtdowling/emitter.tl","owner":"mtdowling","description":"A small, strongly typed event emitter library for Lua and typed with Teal","archived":false,"fork":false,"pushed_at":"2024-12-18T02:44:10.000Z","size":20,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-08T09:46:02.894Z","etag":null,"topics":["events","lua","teal"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/mtdowling.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2024-12-09T18:28:49.000Z","updated_at":"2024-12-18T02:44:13.000Z","dependencies_parsed_at":"2024-12-11T01:51:55.427Z","dependency_job_id":null,"html_url":"https://github.com/mtdowling/emitter.tl","commit_stats":null,"previous_names":["mtdowling/emitter.tl"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mtdowling/emitter.tl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtdowling%2Femitter.tl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtdowling%2Femitter.tl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtdowling%2Femitter.tl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtdowling%2Femitter.tl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtdowling","download_url":"https://codeload.github.com/mtdowling/emitter.tl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtdowling%2Femitter.tl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275194018,"owners_count":25421441,"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","status":"online","status_checked_at":"2025-09-15T02:00:09.272Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["events","lua","teal"],"created_at":"2025-06-06T21:16:02.555Z","updated_at":"2025-09-15T02:16:20.839Z","avatar_url":"https://github.com/mtdowling.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# emitter.tl\n\nA small, strongly typed event emitter library for Lua and typed with\n[Teal](https://github.com/teal-language/tl).\n\n## Key features\n\n* Designed around strongly typed events using Teal. Events are no longer just\n  strings and bags of data.\n* Allows for decoupling logic by subscribing and unsubscribing to events.\n* Support for receiving an event at most once.\n* Can efficiently forward all events from an Emitter to another Emitter.\n  This is great for things like games that have global events and listeners\n  that should only persist for the lifetime of a specific emitter.\n* Listeners can be added or removed while emitting, and removals take effect\n  immediately.\n\n## Usage\n\nFirst, require the module:\n\n```lua\nlocal Emitter = require(\"emitter\")\n```\n\n### Creating an Emitter\n\nAn `Emitter` is used to publish and subscribe to events.\n\n```lua\nlocal emitter = Emitter.new()\n```\n\n### Creating an Event\n\nEvents are strongly typed and require a dedicated type for each kind of event.\n\nFor reference, this is the type definition of Event:\n\n```lua\nlocal interface Event\n    type: self\nend\n```\n\nEach record that implements an Event must define a `type` property of the same\ntype as the event.\n\n```lua\nlocal record WarningEvent is Emitter.Event\n    message: string\nend\n```\n\nThis library doesn't have any requirements on how instances of events are\ncreated.\n\nAn instance of a `WarningEvent` can be created using basic table syntax:\n\n```lua\nlocal e: WarningEvent = {type = WarningEvent, message = \"This is a warning\"}\n```\n\nAlternatively, you can provide a constructor for your events.\n\n```lua\nfunction WarningEvent.new(message: string): WarningEvent\n    return {type = WarningEvent, message = message}\nend\n\nlocal e: WarningEvent = WarningEvent.new(\"This is a warning\")\n```\n\nThis event can now be emitted and subscribed to.\n\n### Subscribing to an Event\n\nListener functions are subscribed to an event using\n`on\u003cE is Event\u003e(emitter: Emitter, E: event, function(E), config?: ListenerConfig)`.\n\n```lua\nemitter:on(WarningEvent, function(event: WarningEvent)\n    print(event.message)\nend)\n```\n\n### Emitting an Event\n\nEvents are emitted using `emit(Event: event)`.\n\n```lua\nemitter:emit(WarningEvent.new(\"This is a warning\"))\n```\n\nEmitting the event will print \"This is a warning\".\n\n### Event listener configuration\n\nAn optional configuration record can be passed when subscribing to an event\nwhen using `on` or `once`:\n\n* `id: string`: An identifier for the listener (defaults to \"\"). An identifier\n  can be used to unsubscribe the listener by ID. No uniqueness checks are\n  performed on the ID; multiple listeners can use the same ID, allowing events\n  to be grouped.\n* `position: \"first\" | \"last\"`: Controls whether the listener is added as the\n  last listener for the event using \"last\" (the default) or the first listener\n  for the event using \"first\".\n\n### Unsubscribing from an Event\n\n`off\u003cE is Event\u003e(event: E, listener: Listener\u003cE\u003e | string)` is used to\nstop a listener from receiving events.\n\nYou can pass in the function that was used to subscribe to the event:\n\n```lua\nlocal function onWarning(event: WarningEvent)\n    print(event.message)\nend\n\nemitter:on(WarningEvent, onWarning)\n\n-- Unsubscribe the function.\nemitter:off(WarningEvent, onWarning)\n```\n\nWhen subscribing to an event, an identifier can be given to the listener\nso that the listener can be unsubscribed by ID rather than the actual function.\n\n```lua\nemitter:on(WarningEvent, onWarning, { id = \"warning\" })\nemitter:off(WarningEvent, \"warning\")\n```\n\nIDs can be used for grouping event listeners.\n\n```lua\n-- While adding listeners, use the same ID to group them.\nemitter:on(WarningEvent, b, { id = \"print-group\" })\nemitter:on(WarningEvent, b, { id = \"print-group\" })\n\n-- Remove both a and b listeners because they both have the id \"print-group\".\nemitter:off(WarningEvent, \"print-group\")\n```\n\n### Receiving an event at most once\n\nThe `once\u003cE is Event\u003e(emitter: Emitter, E: event, function(E))` method can be\nused to subscribe to an event and have the listeners automatically removed\nafter the first event is received.\n\n```lua\nemitter:once(WarningEvent, function(event: WarningEvent)\n    print(\"Once: \" .. event.message)\nend)\n```\n\n### Forwarding events\n\nEmitters can forward all events to another Emitter, allowing for a fan-out\npattern. This is done using `startForwarding(emitter: Emitter)`:\n\n```lua\nlocal forwardEmitter = Emitter.new()\n\nforwardEmitter:on(WarningEvent, function(event: WarningEvent)\n    print(\"Child: \" .. event.message)\nend)\n\nemitter:startForwarding(forwardEmitter)\nemitter:emit(WarningEvent.new(\"This is a warning\"))\n```\n\nWill output:\n\n```text\nThis is a warning\nChild: This is a warning\n```\n\nAn emitter can be detached from another emitter using\n`stopForwarding(emitter: Emitter)`:\n\n```lua\nemitter:stopForwarding(forwardEmitter)\n```\n\n## Clearing and resetting an Emitter\n\n`removeAllListeners(event: Event)` is used to remove all listeners for\nan event type:\n\n```lua\nemitter:removeAllListeners(WarningEvent)\n```\n\n`reset()` is used to unsubscribe all listeners and stop forwarding all events:\n\n```lua\nemitter:reset()\n```\n\n## Installation\n\n**Copy and paste**:\n\nCopy and paste `src/emitter.tl` and/or `src/emitter.lua` into your project.\n\n**Or use LuaRocks**:\n\n```sh\nluarocks install emitter.tl\n```\n\n## Contributing\n\nThe source code is written in Teal and compiled to Lua. The updated and\ncompiled Lua must be part of every code change to the Teal source code.\nYou can compile Teal to Lua and run tests using:\n\n```sh\nmake\n```\n\n## License\n\nThis module is free software; you can redistribute it and/or modify it under\nthe terms of the MIT license. See LICENSE for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtdowling%2Femitter.tl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtdowling%2Femitter.tl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtdowling%2Femitter.tl/lists"}