{"id":19078657,"url":"https://github.com/nidorx/chain","last_synced_at":"2025-04-30T05:04:08.861Z","repository":{"id":61623270,"uuid":"535551698","full_name":"nidorx/chain","owner":"nidorx","description":"Machinery to create distributed systems in a simple, elegant and safe way.","archived":false,"fork":false,"pushed_at":"2025-02-14T02:12:21.000Z","size":840,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-30T05:03:48.997Z","etag":null,"topics":["channels","crypto","pubsub","socket"],"latest_commit_sha":null,"homepage":"","language":"Go","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/nidorx.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,"zenodo":null}},"created_at":"2022-09-12T07:14:53.000Z","updated_at":"2025-02-14T02:00:37.000Z","dependencies_parsed_at":"2024-06-20T12:42:08.059Z","dependency_job_id":"badea258-496a-4ef7-93e8-b1e6e4c58caf","html_url":"https://github.com/nidorx/chain","commit_stats":null,"previous_names":["nidorx/chain","syntax-framework/chain"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fchain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fchain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fchain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fchain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nidorx","download_url":"https://codeload.github.com/nidorx/chain/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251644843,"owners_count":21620632,"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":["channels","crypto","pubsub","socket"],"created_at":"2024-11-09T02:11:22.459Z","updated_at":"2025-04-30T05:04:08.843Z","avatar_url":"https://github.com/nidorx.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"./docs/logo.png\" /\u003e\n    \u003cp align=\"center\"\u003e\n        To create distributed systems in a simple, elegant and safe way.\n    \u003c/p\u003e    \n\u003c/div\u003e\n---\n\nChain is a core library that tries to provide all the necessary machinery to create distributed systems in a simple,\nelegant and safe way.\n\n## Feature Overview\n\n- Optimized HTTP Router middleware\n- Realtime Publisher/Subscriber service.\n- Socket \u0026 Channels: A socket implementation that multiplexes messages over channels.\n- Crypto-related functionalities\n\n## Installation\n\n```\ngo get github.com/nidorx/chain\n```\n\n## Router\n\n![router.png](docs/router.png)\n\n**chain** has a lightweight high performance HTTP request router (also called *multiplexer* or just *mux* for short)\nfor [Go](https://golang.org/). In contrast to the [default mux](https://golang.org/pkg/net/http/#ServeMux) of\nGo's `net/http` package, this router supports variables in the routing pattern and matches against the request method.\nIt also scales better.\n\n- Optimized HTTP router which smartly prioritize routes\n- Build robust and scalable RESTful APIs\n- Extensible Middleware framework\n- Handy functions to send variety of HTTP responses\n- Centralized HTTP error handling\n\n```go\npackage main\n\nimport (\n\t\"github.com/nidorx/chain\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc main() {\n\trouter := chain.New()\n\n\t// Middleware\n\trouter.Use(func(ctx *chain.Context, next func() error) error {\n\t\tprintln(\"first middleware\")\n\t\treturn next()\n\t})\n\n\trouter.Use(\"GET\", \"/*\", func(ctx *chain.Context) {\n\t\tprintln(\"second middleware\")\n\t})\n\n\t// Handler\n\trouter.GET(\"/\", func(ctx *chain.Context) {\n\t\tctx.Write([]byte(\"Hello World!\"))\n\t})\n\n\t// Grouping\n\tv1 := router.Group(\"/v1\")\n\t{\n\t\tv1.GET(\"/users\", func(ctx *chain.Context) {\n\t\t\tctx.Write([]byte(\"[001]\"))\n\t\t})\n\t}\n\n\tv2 := router.Group(\"/v2\")\n\t{\n\t\tv2.GET(\"/users\", func(ctx *chain.Context) {\n\t\t\tctx.Write([]byte(\"[002]\"))\n\t\t})\n\t}\n\n\tif err := http.ListenAndServe(\"localhost:8080\", router); err != nil {\n\t\tlog.Fatalf(\"ListenAndServe: %v\", err)\n\t}\n}\n```\n\n### More about Router\n\n- [Router docs](/docs/ROUTER.md)\n- [`/examples/router`](/examples/router)\n\n## PubSub\n\n![pubsub.png](docs/pubsub.png)\n\nRealtime Publisher/Subscriber service.\n\nYou can use the functions in this module to subscribe and broadcast messages:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/nidorx/chain\"\n\t\"github.com/nidorx/chain/pubsub\"\n\t\"time\"\n)\n\ntype MyDispatcher struct {\n}\n\nfunc (d *MyDispatcher) Dispatch(topic string, message any, from string) {\n\tprintln(fmt.Sprintf(\"New Message. Topic: %s, Content: %s\", topic, message))\n}\n\nfunc main() {\n\n\tdispatcher := \u0026MyDispatcher{}\n\tserializer := \u0026chain.JsonSerializer{}\n\n\tpubsub.Subscribe(\"user:123\", dispatcher)\n\n\tbytes, _ := serializer.Encode(map[string]any{\n\t\t\"Event\": \"user_update\",\n\t\t\"Payload\": map[string]any{\n\t\t\t\"Id\":   6,\n\t\t\t\"Name\": \"Gabriel\",\n\t\t},\n\t})\n\tpubsub.Broadcast(\"user:123\", bytes)\n\tpubsub.Broadcast(\"user:123\", []byte(\"Message 2\"))\n\n\t// await\n\t\u003c-time.After(time.Millisecond * 10)\n\n\tpubsub.Unsubscribe(\"user:123\", dispatcher)\n\n\tpubsub.Broadcast(\"user:123\", []byte(\"Message Ignored\"))\n\n\t// await\n\t\u003c-time.After(time.Millisecond * 10)\n}\n```\n\n### More about PubSub\n\n- [PubSub docs](/docs/PUBSUB.md)\n- [`/examples/pubsub`](/examples/pubsub)\n\n## Socket \u0026 Channels\n\n![socket.png](docs/socket.png)\n\nA socket implementation that multiplexes messages over channels.\n\nOnce connected to a socket, incoming and outgoing events are routed to channels. The incoming client data is routed to\nchannels via transports. It is the responsibility of the socket to tie transports and channels together.\n\nChain ships with a JavaScript implementation that interacts with backend and can be used as reference for those\ninterested in implementing custom clients.\n\nServer\n\n```go\npackage main\n\nimport (\n\t\"github.com/nidorx/chain\"\n\t\"github.com/nidorx/chain/socket\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc main() {\n\trouter := chain.New()\n\n\trouter.Configure(\"/socket\", AppSocket)\n\n\tif err := http.ListenAndServe(\":8080\", router); err != nil {\n\t\tlog.Fatalf(\"ListenAndServe: %v\", err)\n\t}\n}\n\nvar AppSocket = \u0026socket.Handler{\n\tChannels: []*socket.Channel{\n\t\tsocket.NewChannel(\"chat:*\", chatChannel),\n\t},\n}\n\nfunc chatChannel(channel *socket.Channel) {\n\n\tchannel.Join(\"chat:lobby\", func(params any, socket *socket.Socket) (reply any, err error) {\n\t\treturn\n\t})\n\n\tchannel.HandleIn(\"my_event\", func(event string, payload any, socket *socket.Socket) (reply any, err error) {\n\t\treply = \"Ok\"\n\n\t\tsocket.Push(\"other_event\", map[string]any{\"value\": 1})\n\t\treturn\n\t})\n}\n```\n\nClient (javascript)\n\n```javascript\nconst socket = chain.Socket('/socket')\nsocket.connect()\n\nconst channel = socket.channel(\"chat:lobby\", {param1: 'foo'})\nchannel.join()\n\nchannel.push('my_event', {name: $inputName.value})\n    .on('ok', (reply) =\u003e chain.log('MyEvent', reply))\n\n\nchannel.on('other_event', (message) =\u003e chain.log('OtherEvent', message))\n```\n\n### More about Socket \u0026 Channels\n\n- [Socket \u0026 Channels docs](/docs/SOCKET.md)\n- [`/examples/socket-chat`](/examples/socket-chat)\n\n## Crypto\n\nSimplify and standardize the use and maintenance of symmetric cryptographic keys.\n\nFeatures:\n\n- **SecretKeyBase** Solution that allows your application to have a single security key and from that it is possible to\n  generate an infinite number of derived keys used in the most diverse features of your project.\n- **Keyring** Allows you to enable key rotation, allowing encryption processes to be performed with a new key and data\n  encrypted with old keys can still be decrypted.\n- **KeyGenerator**: It can be used to derive a number of keys for various purposes from a given secret. This lets\n  applications have a single secure secret, but avoid reusing that key in multiple incompatible contexts.\n- **MessageVerifier**: makes it easy to generate and verify messages which are signed to prevent tampering.\n- **MessageEncryptor** is a simple way to encrypt values which get stored somewhere you don't trust.\n\n### More about Crypto\n\n- [Crypto docs](/docs/CRYPTO.md)\n- [`/examples/crypto`](/examples/crypto)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnidorx%2Fchain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnidorx%2Fchain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnidorx%2Fchain/lists"}