kettle-ndjson 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d818c1cc11f08ec406600029ed039531f0e626ab8d5afc32eb0948a7258c224f
4
+ data.tar.gz: 25e10c29c3439993537438f52ea28caf93dcaccd7910a790597fe2b45de8a307
5
+ SHA512:
6
+ metadata.gz: 89f3f1ed53e109402a943638c33136a7165837542c76a4f05d454533323c5c5b5eb10f3f8114ee9b51c586dd124bd35cee760124450710b9d8cf74eb0e6d3fbb
7
+ data.tar.gz: '07845db3f41e4eced50eeec5ad5871ffdccddecc83ab18b639b3474e5c35ad48cacff20c60eb309981326f1ec6b494f07c17b6e0f97d4f30b529c90746032179'
checksums.yaml.gz.sig ADDED
Binary file
data/CHANGELOG.md ADDED
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ [![SemVer 2.0.0][📌semver-img]][📌semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog]
4
+
5
+ All notable changes to this project will be documented in this file.
6
+
7
+ The format is based on [Keep a Changelog][📗keep-changelog],
8
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
9
+ and [yes][📌major-versions-not-sacred], platform and engine support are part of the [public API][📌semver-breaking].
10
+ Please file a bug if you notice a violation of semantic versioning.
11
+
12
+ [📌semver]: https://semver.org/spec/v2.0.0.html
13
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-FFDD67.svg?style=flat
14
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
15
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
16
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
17
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat
18
+
19
+ ## [Unreleased]
20
+
21
+ ### Added
22
+
23
+ ### Changed
24
+
25
+ ### Deprecated
26
+
27
+ ### Removed
28
+
29
+ ### Fixed
30
+
31
+ ### Security
32
+
33
+ ## [0.1.0] - 2026-07-25
34
+
35
+ - TAG: [v0.1.0][0.1.0t]
36
+ - COVERAGE: 100.00% -- 74/74 lines in 2 files
37
+ - BRANCH COVERAGE: 96.15% -- 25/26 branches in 2 files
38
+ - 19.35% documented
39
+ - Initial release
40
+
41
+ ### Added
42
+
43
+ - Added `Kettle::Ndjson` event stream, recorder, filter, timing, step,
44
+ diagnostic, and summary helpers for newline-delimited JSON CLI events.
45
+
46
+ ### Changed
47
+
48
+ - kettle-jem-template-initial - Initial templating by kettle-jem.
49
+
50
+ [Unreleased]: https://github.com/kettle-dev/kettle-ndjson/compare/v0.1.0...HEAD
51
+ [0.1.0]: https://github.com/kettle-dev/kettle-ndjson/compare/b960037607f365b15262f5bf24417ded4dca5378...v0.1.0
52
+ [0.1.0t]: https://github.com/kettle-dev/kettle-ndjson/releases/tag/v0.1.0
data/LICENSE.md ADDED
@@ -0,0 +1,10 @@
1
+ # License
2
+
3
+ This project is made available under the following license.
4
+ Choose the option that best fits your use case:
5
+
6
+ - [MIT](https://github.com/kettle-dev/kettle-ndjson/blob/main/MIT.md)
7
+
8
+ ## Copyright Notice
9
+
10
+ - Copyright (c) 2026 Peter H. Boling
data/README.md ADDED
@@ -0,0 +1,518 @@
1
+ <a href="https://github.com/kettle-dev"><img alt="kettle-dev Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/kettle-dev/avatar-128px.svg" width="14%" align="right"/></a>
2
+
3
+ # 📟️ Kettle::Ndjson
4
+
5
+ [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
6
+
7
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][✉️discord-invite], as I may have missed the [discord notification][✉️discord-invite].
8
+
9
+ ---
10
+
11
+ `if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
12
+
13
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
14
+
15
+ <details markdown="1">
16
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
17
+
18
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
19
+
20
+ </details>
21
+
22
+ ## 🌻 Synopsis <a href="https://discord.gg/3qme4XHNKN"><img alt="Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="8%" align="right"/></a> <a href="https://ruby-toolbox.com"><img alt="ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5" src="https://logos.galtzo.com/assets/images/ruby-lang/avatar-128px.svg" width="8%" align="right"/></a>
23
+
24
+ ## 💡 Info you can shake a stick at
25
+
26
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
27
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
28
+ | Works with JRuby | [![JRuby 10.0 Compat][💎jruby-10.0i]][🚎jruby-10.0-wf] [![JRuby current Compat][💎jruby-c-i]][🚎10-j-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf]|
29
+ | Works with Truffle Ruby | [![Truffle Ruby 24.2 Compat][💎truby-24.2i]][🚎truby-24.2-wf] [![Truffle Ruby 25.0 Compat][💎truby-25.0i]][🚎truby-25.0-wf] [![Truffle Ruby 33.0 Compat][💎truby-33.0i]][🚎truby-33.0-wf] [![Truffle Ruby current Compat][💎truby-c-i]][🚎9-t-wf] [![Truffle Ruby HEAD Compat][💎truby-headi]][🚎3-hd-wf]|
30
+ | Works with MRI Ruby 4 | [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf]|
31
+ | Works with MRI Ruby 3 | [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎ruby-3.2-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎ruby-3.3-wf] [![Ruby 3.4 Compat][💎ruby-3.4i]][🚎ruby-3.4-wf]|
32
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Get help from RubyForum][✉️ruby-forum-img]][✉️ruby-forum] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
33
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on GitHub.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
34
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
35
+ | Compliance | [![License: MIT][📄license-img]][📄license] [![Apache license compatibility: Category A][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
36
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
37
+ | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
38
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
39
+
40
+ ### Compatibility
41
+
42
+ Compatible with MRI Ruby 3.2.0+, and concordant releases of JRuby, and TruffleRuby.
43
+ CI workflows and Appraisals are generated for MRI Ruby 3.2.0+.
44
+ This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
45
+ may be higher than the gem's runtime compatibility floor when legacy Rubies are
46
+ not practical for the current toolchain.
47
+
48
+ <a href="https://github.com/kettle-dev"><img alt="kettle-dev Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/kettle-dev/avatar-128px.svg" width="14%" align="right"/></a>
49
+
50
+ The _amazing_ test matrix is powered by the kettle-dev stack.
51
+
52
+ <details markdown="1">
53
+ <summary>How kettle-dev manages complexity in tests</summary>
54
+
55
+ | Gem | Source | Role | Daily download rank |
56
+ |-----|--------|------|---------------------|
57
+ | [appraisal2](https://bestgems.org/gems/appraisal2) | [GitHub](https://github.com/appraisal-rb/appraisal2) | multi-dependency Appraisal matrix generation | [![Daily download rank for appraisal2](https://img.shields.io/gem/rd/appraisal2.svg?style=flat-square)](https://bestgems.org/gems/appraisal2) |
58
+ | [appraisal2-rubocop](https://bestgems.org/gems/appraisal2-rubocop) | [GitHub](https://github.com/appraisal-rb/appraisal2-rubocop) | RuboCop Appraisal generator integration | [![Daily download rank for appraisal2-rubocop](https://img.shields.io/gem/rd/appraisal2-rubocop.svg?style=flat-square)](https://bestgems.org/gems/appraisal2-rubocop) |
59
+ | [kettle-dev](https://bestgems.org/gems/kettle-dev) | [GitHub](https://github.com/kettle-dev/kettle-dev) | development, release, and CI workflow tooling | [![Daily download rank for kettle-dev](https://img.shields.io/gem/rd/kettle-dev.svg?style=flat-square)](https://bestgems.org/gems/kettle-dev) |
60
+ | [kettle-jem](https://bestgems.org/gems/kettle-jem) | [GitHub](https://github.com/kettle-dev/kettle-jem) | Appraisals & CI workflow templates | [![Daily download rank for kettle-jem](https://img.shields.io/gem/rd/kettle-jem.svg?style=flat-square)](https://bestgems.org/gems/kettle-jem) |
61
+ | [kettle-soup-cover](https://bestgems.org/gems/kettle-soup-cover) | [GitHub](https://github.com/kettle-dev/kettle-soup-cover) | SimpleCov coverage policy and reporting | [![Daily download rank for kettle-soup-cover](https://img.shields.io/gem/rd/kettle-soup-cover.svg?style=flat-square)](https://bestgems.org/gems/kettle-soup-cover) |
62
+ | [kettle-test](https://bestgems.org/gems/kettle-test) | [GitHub](https://github.com/kettle-dev/kettle-test) | standard test runner and coverage harness | [![Daily download rank for kettle-test](https://img.shields.io/gem/rd/kettle-test.svg?style=flat-square)](https://bestgems.org/gems/kettle-test) |
63
+ | [rubocop-lts](https://bestgems.org/gems/rubocop-lts) | [GitHub](https://github.com/rubocop-lts/rubocop-lts) | Ruby-version-aware linting | [![Daily download rank for rubocop-lts](https://img.shields.io/gem/rd/rubocop-lts.svg?style=flat-square)](https://bestgems.org/gems/rubocop-lts) |
64
+ | [turbo_tests2](https://bestgems.org/gems/turbo_tests2) | [GitHub](https://github.com/galtzo-floss/turbo_tests2) | parallel test execution | [![Daily download rank for turbo_tests2](https://img.shields.io/gem/rd/turbo_tests2.svg?style=flat-square)](https://bestgems.org/gems/turbo_tests2) |
65
+
66
+ </details>
67
+
68
+ ### Federated DVCS
69
+
70
+ <details markdown="1">
71
+ <summary>Find this repo on federated forges (Coming soon!)</summary>
72
+
73
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
74
+ |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
75
+ | 🧪 [kettle-dev/kettle-ndjson on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
76
+ | 🧊 [kettle-dev/kettle-ndjson on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
77
+ | 🐙 [kettle-dev/kettle-ndjson on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
78
+ | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
79
+
80
+ </details>
81
+
82
+ [gh-discussions]: https://github.com/kettle-dev/kettle-ndjson/discussions
83
+
84
+ ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/kettle-ndjson)](https://tidelift.com/subscription/pkg/rubygems-kettle-ndjson?utm_source=rubygems-kettle-ndjson&utm_medium=referral&utm_campaign=readme)
85
+
86
+ Available as part of the Tidelift Subscription.
87
+
88
+ <details markdown="1">
89
+ <summary>Need enterprise-level guarantees?</summary>
90
+
91
+ The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
92
+
93
+ [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
94
+
95
+ - 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies
96
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
97
+ - 💡Tidelift pays maintainers to maintain the software you depend on!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers
98
+
99
+ Alternatively:
100
+
101
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
102
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
103
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
104
+
105
+ </details>
106
+
107
+ ## ✨ Installation
108
+
109
+ Install the gem and add to the application's Gemfile by executing:
110
+
111
+ ```console
112
+ bundle add kettle-ndjson
113
+ ```
114
+
115
+ If bundler is not being used to manage dependencies, install the gem by executing:
116
+
117
+ ```console
118
+ gem install kettle-ndjson
119
+ ```
120
+
121
+ ## ⚙️ Configuration
122
+
123
+ ## 🔧 Basic Usage
124
+
125
+ Create an event stream for newline-delimited JSON output:
126
+
127
+ ```ruby
128
+ require "kettle/ndjson"
129
+
130
+ events = Kettle::Ndjson.event_stream($stdout, types: "progress")
131
+ Kettle::Ndjson.emit_phase_event(events, :release, status: "started")
132
+ Kettle::Ndjson.emit_step_event(
133
+ events,
134
+ "command_step",
135
+ {name: "bundle_install", status: "started", command: %w[bundle install]},
136
+ phase: "prepare"
137
+ )
138
+ Kettle::Ndjson.emit_summary_event(events, status: "ok", diagnostics_count: 0)
139
+ ```
140
+
141
+ Use `types:` to filter event streams. Built-in aliases are `default`,
142
+ `progress`, and `all`.
143
+
144
+ ## 🦷 FLOSS Funding
145
+
146
+ While kettle-dev tools are free software and will always be, the project would benefit immensely from some funding.
147
+ Raising a monthly budget of... "dollars" would make the project more sustainable.
148
+
149
+ We welcome both individual and corporate sponsors! We also offer a
150
+ wide array of funding channels to account for your preferences.
151
+ Currently, [Open Collective][🖇osc] is our preferred funding platform.
152
+
153
+ **If you're working in a company that's making significant use of kettle-dev tools we'd
154
+ appreciate it if you suggest to your company to become a kettle-dev sponsor.**
155
+
156
+ You can support the development of kettle-dev tools via
157
+ [GitHub Sponsors][🖇sponsor],
158
+ [Liberapay][⛳liberapay],
159
+ [PayPal][🖇paypal],
160
+ [Open Collective][🖇osc]
161
+ and [Tidelift][🏙️entsup-tidelift].
162
+
163
+ | 📍 NOTE |
164
+ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
165
+ | If doing a sponsorship in the form of donation is problematic for your company <br/> from an accounting standpoint, we'd recommend the use of Tidelift, <br/> where you can get a support-like subscription instead. |
166
+
167
+ ### Open Collective for Individuals
168
+
169
+ Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/kettle-dev#backer)]
170
+
171
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
172
+
173
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
174
+ No backers yet. Be the first!
175
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
176
+
177
+ ### Open Collective for Organizations
178
+
179
+ Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/kettle-dev#sponsor)]
180
+
181
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
182
+
183
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
184
+ No sponsors yet. Be the first!
185
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
186
+
187
+ [kettle-readme-backers]: https://github.com/kettle-dev/kettle-ndjson/blob/main/bin/kettle-readme-backers
188
+
189
+ ### Another way to support open-source
190
+
191
+ I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).
192
+
193
+ If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
194
+
195
+ I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
196
+
197
+ **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
198
+
199
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi]
200
+
201
+ ## 🔐 Security
202
+
203
+ See [SECURITY.md][🔐security].
204
+
205
+ ## 🤝 Contributing
206
+
207
+ If you need some ideas of where to help, you could work on adding more code coverage,
208
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
209
+ or use the gem and think about how it could be better.
210
+
211
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
212
+
213
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
214
+
215
+ ### 🚀 Release Instructions
216
+
217
+ See [CONTRIBUTING.md][🤝contributing].
218
+
219
+ ### Code Coverage
220
+
221
+ <details markdown="1">
222
+ <summary>Coverage service badges</summary>
223
+
224
+ [![Coverage Graph][🏀codecov-g]][🏀codecov]
225
+
226
+ [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls]
227
+
228
+ [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov]
229
+
230
+ </details>
231
+
232
+ ### 🪇 Code of Conduct
233
+
234
+ Everyone interacting with this project's codebases, issue trackers,
235
+ chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
236
+
237
+ ## 🌈 Contributors
238
+
239
+ [![Contributors][🖐contributors-img]][🖐contributors]
240
+
241
+ Made with [contributors-img][🖐contrib-rocks].
242
+
243
+ Also see GitLab Contributors: [https://gitlab.com/kettle-dev/kettle-ndjson/-/graphs/main][🚎contributors-gl]
244
+
245
+ <details markdown="1">
246
+ <summary>⭐️ Star History</summary>
247
+
248
+ <a href="https://star-history.com/kettle-dev/kettle-ndjson&Date">
249
+ <picture>
250
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kettle-dev/kettle-ndjson&type=Date&theme=dark" />
251
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kettle-dev/kettle-ndjson&type=Date" />
252
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kettle-dev/kettle-ndjson&type=Date" />
253
+ </picture>
254
+ </a>
255
+
256
+ </details>
257
+
258
+ ## 📌 Versioning
259
+
260
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
261
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
262
+
263
+ For example:
264
+
265
+ ```ruby
266
+ spec.add_dependency("kettle-ndjson", "~> 0.0")
267
+ ```
268
+
269
+ <details markdown="1">
270
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
271
+
272
+ Dropping support for a platform can be a breaking change for affected users.
273
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
274
+
275
+ To get a better understanding of how SemVer is intended to work over a project's lifetime,
276
+ read this article from the creator of SemVer:
277
+
278
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
279
+
280
+ </details>
281
+
282
+ See [CHANGELOG.md][📌changelog] for a list of releases.
283
+
284
+ ## 📄 License
285
+
286
+ The gem is available as open source under the terms of
287
+ the [MIT](https://github.com/kettle-dev/kettle-ndjson/blob/main/MIT.md) [![License: MIT][📄license-img]][📄license-ref].
288
+
289
+ ### © Copyright
290
+
291
+ See [LICENSE.md][📄license] for the official copyright notice.
292
+
293
+ <details markdown="1">
294
+ <summary>Copyright holders</summary>
295
+
296
+ - Copyright (c) 2026 Peter H. Boling
297
+
298
+ </details>
299
+
300
+ ## 🤑 A request for help
301
+
302
+ Maintainers have teeth and need to pay their dentists.
303
+ After getting laid off in an RIF in March, and encountering difficulty finding a new one,
304
+ I began spending most of my time building open source tools.
305
+ I'm hoping to be able to pay for my kids' health insurance this month,
306
+ so if you value the work I am doing, I need your support.
307
+ Please consider sponsoring me or the project.
308
+
309
+ To join the community or get help 👇️ Join the Discord.
310
+
311
+ [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
312
+
313
+ To say "thanks!" ☝️ Join the Discord or 👇️ send money.
314
+
315
+ [![Sponsor kettle-dev/kettle-ndjson on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal]
316
+
317
+ ### Please give the project a star ⭐ ♥.
318
+
319
+ Many parts of this project are actively managed by a [kettle-jem](https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/kettle-jem) smart template utilizing [StructuredMerge.org](https://structuredmerge.org) merge contracts.
320
+
321
+ Thanks for RTFM. ☺️
322
+
323
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
324
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
325
+ [⛳liberapay]: https://liberapay.com/pboling/donate
326
+ [🖇osc-all-img]: https://img.shields.io/opencollective/all/kettle-dev
327
+ [🖇osc-sponsors-img]: https://img.shields.io/opencollective/sponsors/kettle-dev
328
+ [🖇osc-backers-img]: https://img.shields.io/opencollective/backers/kettle-dev
329
+ [🖇osc-backers]: https://opencollective.com/kettle-dev#backer
330
+ [🖇osc-backers-i]: https://opencollective.com/kettle-dev/backers/badge.svg?style=flat
331
+ [🖇osc-sponsors]: https://opencollective.com/kettle-dev#sponsor
332
+ [🖇osc-sponsors-i]: https://opencollective.com/kettle-dev/sponsors/badge.svg?style=flat
333
+ [🖇osc-all-bottom-img]: https://img.shields.io/opencollective/all/kettle-dev?style=for-the-badge
334
+ [🖇osc-sponsors-bottom-img]: https://img.shields.io/opencollective/sponsors/kettle-dev?style=for-the-badge
335
+ [🖇osc-backers-bottom-img]: https://img.shields.io/opencollective/backers/kettle-dev?style=for-the-badge
336
+ [🖇osc]: https://opencollective.com/kettle-dev
337
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
338
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
339
+ [🖇sponsor]: https://github.com/sponsors/pboling
340
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
341
+ [🖇kofi]: https://ko-fi.com/pboling
342
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
343
+ [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
344
+ [🖇buyme]: https://www.buymeacoffee.com/pboling
345
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
346
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
347
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
348
+ [🖇floss-funding.dev]: https://floss-funding.dev
349
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
350
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
351
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
352
+ [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
353
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
354
+ [✉️ruby-forum-img]: https://img.shields.io/badge/RubyForum-Help-CC342D?style=for-the-badge&logo=ruby&logoColor=white
355
+ [✉️ruby-forum]: https://www.rubyforum.org/c/help/8
356
+
357
+ [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
358
+ [⛳️gem-namespace]: https://github.com/kettle-dev/kettle-ndjson
359
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-Kettle::Ndjson-3C2D2D.svg?style=square&logo=ruby&logoColor=white
360
+ [⛳️gem-name]: https://bestgems.org/gems/kettle-ndjson
361
+ [⛳️name-img]: https://img.shields.io/badge/name-kettle--ndjson-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
362
+ [⛳️tag-img]: https://img.shields.io/github/tag/kettle-dev/kettle-ndjson.svg
363
+ [⛳️tag]: https://github.com/kettle-dev/kettle-ndjson/releases
364
+ [🚂maint-blog]: http://www.railsbling.com/tags/kettle-ndjson
365
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
366
+ [🚂maint-contact]: http://www.railsbling.com/contact
367
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
368
+ [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
369
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
370
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling
371
+ [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
372
+ [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
373
+ [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
374
+ [💖🐘ruby-mast]: https://ruby.social/@galtzo
375
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
376
+ [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
377
+ [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
378
+ [💖🌳linktree]: https://linktr.ee/galtzo
379
+ [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree
380
+ [💖💁🏼‍♂️devto]: https://dev.to/galtzo
381
+ [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white
382
+ [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling
383
+ [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white
384
+ [💖🧊berg]: https://codeberg.org/pboling
385
+ [💖🐙hub]: https://github.org/pboling
386
+ [💖🛖hut]: https://sr.ht/~galtzo/
387
+ [💖🧪lab]: https://gitlab.com/pboling
388
+ [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share
389
+ [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
390
+ [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
391
+ [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
392
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-kettle-ndjson?utm_source=rubygems-kettle-ndjson&utm_medium=referral&utm_campaign=readme
393
+ [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
394
+ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
395
+ [💁🏼‍♂️peterboling]: http://www.peterboling.com
396
+ [🚂railsbling]: http://www.railsbling.com
397
+ [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
398
+ [📜src-gl]: https://gitlab.com/kettle-dev/kettle-ndjson
399
+ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
400
+ [📜src-cb]: https://codeberg.org/kettle-dev/kettle-ndjson
401
+ [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=GitHub&logoColor=green
402
+ [📜src-gh]: https://github.com/kettle-dev/kettle-ndjson
403
+ [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
404
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
405
+ [📜gl-wiki]: https://gitlab.com/kettle-dev/kettle-ndjson/-/wikis/home
406
+ [📜gh-wiki]: https://github.com/kettle-dev/kettle-ndjson/wiki
407
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
408
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
409
+ [👽dl-rank]: https://bestgems.org/gems/kettle-ndjson
410
+ [👽dl-ranki]: https://img.shields.io/gem/rd/kettle-ndjson.svg
411
+ [👽version]: https://bestgems.org/gems/kettle-ndjson
412
+ [👽versioni]: https://img.shields.io/gem/v/kettle-ndjson.svg
413
+ [🏀qlty-mnt]: https://qlty.sh/gh/kettle-dev/projects/kettle-ndjson
414
+ [🏀qlty-mnti]: https://qlty.sh/gh/kettle-dev/projects/kettle-ndjson/maintainability.svg
415
+ [🏀qlty-cov]: https://qlty.sh/gh/kettle-dev/projects/kettle-ndjson/metrics/code?sort=coverageRating
416
+ [🏀qlty-covi]: https://qlty.sh/gh/kettle-dev/projects/kettle-ndjson/coverage.svg
417
+ [🏀codecov]: https://codecov.io/gh/kettle-dev/kettle-ndjson
418
+ [🏀codecovi]: https://codecov.io/gh/kettle-dev/kettle-ndjson/graph/badge.svg
419
+ [🏀coveralls]: https://coveralls.io/github/kettle-dev/kettle-ndjson?branch=main
420
+ [🏀coveralls-img]: https://coveralls.io/repos/github/kettle-dev/kettle-ndjson/badge.svg?branch=main
421
+ [🚎ruby-3.2-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/ruby-3.2.yml
422
+ [🚎ruby-3.3-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/ruby-3.3.yml
423
+ [🚎ruby-3.4-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/ruby-3.4.yml
424
+ [🚎jruby-10.0-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/jruby-10.0.yml
425
+ [🚎truby-24.2-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/truffleruby-24.2.yml
426
+ [🚎truby-25.0-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/truffleruby-25.0.yml
427
+ [🚎truby-33.0-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/truffleruby-33.0.yml
428
+ [🚎2-cov-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/coverage.yml
429
+ [🚎2-cov-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/coverage.yml/badge.svg
430
+ [🚎3-hd-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/heads.yml
431
+ [🚎3-hd-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/heads.yml/badge.svg
432
+ [🚎5-st-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/style.yml
433
+ [🚎5-st-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/style.yml/badge.svg
434
+ [🚎9-t-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/truffle.yml
435
+ [🚎9-t-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/truffle.yml/badge.svg
436
+ [🚎10-j-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/jruby.yml
437
+ [🚎10-j-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/jruby.yml/badge.svg
438
+ [🚎11-c-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/current.yml
439
+ [🚎11-c-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/current.yml/badge.svg
440
+ [🚎12-crh-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/dep-heads.yml
441
+ [🚎12-crh-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/dep-heads.yml/badge.svg
442
+ [🚎13-🔒️-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/locked_deps.yml
443
+ [🚎13-🔒️-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/locked_deps.yml/badge.svg
444
+ [🚎14-🔓️-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/unlocked_deps.yml
445
+ [🚎14-🔓️-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/unlocked_deps.yml/badge.svg
446
+ [🚎15-🪪-wf]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/license-eye.yml
447
+ [🚎15-🪪-wfi]: https://github.com/kettle-dev/kettle-ndjson/actions/workflows/license-eye.yml/badge.svg
448
+ [💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white
449
+ [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white
450
+ [💎ruby-3.4i]: https://img.shields.io/badge/Ruby-3.4-CC342D?style=for-the-badge&logo=ruby&logoColor=white
451
+ [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
452
+ [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue
453
+ [💎truby-24.2i]: https://img.shields.io/badge/Truffle_Ruby-24.2-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
454
+ [💎truby-25.0i]: https://img.shields.io/badge/Truffle_Ruby-25.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
455
+ [💎truby-33.0i]: https://img.shields.io/badge/Truffle_Ruby-33.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
456
+ [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green
457
+ [💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD-34BCB1?style=for-the-badge&logo=ruby&logoColor=blue
458
+ [💎jruby-10.0i]: https://img.shields.io/badge/JRuby-10.0-FBE742?style=for-the-badge&logo=ruby&logoColor=red
459
+ [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
460
+ [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
461
+ [🤝gh-issues]: https://github.com/kettle-dev/kettle-ndjson/issues
462
+ [🤝gh-pulls]: https://github.com/kettle-dev/kettle-ndjson/pulls
463
+ [🤝gl-issues]: https://gitlab.com/kettle-dev/kettle-ndjson/-/issues
464
+ [🤝gl-pulls]: https://gitlab.com/kettle-dev/kettle-ndjson/-/merge_requests
465
+ [🤝cb-issues]: https://codeberg.org/kettle-dev/kettle-ndjson/issues
466
+ [🤝cb-pulls]: https://codeberg.org/kettle-dev/kettle-ndjson/pulls
467
+ [🤝cb-donate]: https://donate.codeberg.org/
468
+ [🤝contributing]: https://github.com/kettle-dev/kettle-ndjson/blob/main/CONTRIBUTING.md
469
+ [🏀codecov-g]: https://codecov.io/gh/kettle-dev/kettle-ndjson/graph/badge.svg
470
+ [🖐contrib-rocks]: https://contrib.rocks
471
+ [🖐contributors]: https://github.com/kettle-dev/kettle-ndjson/graphs/contributors
472
+ [🖐contributors-img]: https://contrib.rocks/image?repo=kettle-dev/kettle-ndjson
473
+ [🚎contributors-gl]: https://gitlab.com/kettle-dev/kettle-ndjson/-/graphs/main
474
+ [🪇conduct]: https://github.com/kettle-dev/kettle-ndjson/blob/main/CODE_OF_CONDUCT.md
475
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
476
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
477
+ [📌semver]: https://semver.org/spec/v2.0.0.html
478
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
479
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
480
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
481
+ [📌changelog]: https://github.com/kettle-dev/kettle-ndjson/blob/main/CHANGELOG.md
482
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
483
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
484
+ [📌gitmoji]: https://gitmoji.dev
485
+ [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
486
+ [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
487
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.074-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
488
+ [🔐security]: https://github.com/kettle-dev/kettle-ndjson/blob/main/SECURITY.md
489
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
490
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
491
+ [📄license]: LICENSE.md
492
+ [📄license-ref]: https://github.com/kettle-dev/kettle-ndjson/blob/main/MIT.md
493
+ [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
494
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-a
495
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-%E2%9C%93-259D6C.svg?style=flat&logo=Apache
496
+
497
+ [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
498
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
499
+ [🚎yard-current]: http://rubydoc.info/gems/kettle-ndjson
500
+ [🚎yard-head]: https://kettle-ndjson.galtzo.com
501
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
502
+ [💎SHA_checksums]: https://gitlab.com/kettle-dev/kettle-ndjson/-/tree/main/checksums
503
+ [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
504
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
505
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
506
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
507
+ [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
508
+
509
+ <!-- kettle-jem:metadata:start -->
510
+ | Field | Value |
511
+ |---|---|
512
+ | Package | kettle-ndjson |
513
+ | Description | 📟️ NDJSON event stream primitives, filters, recorders, and payload helpers shared by Kettle CLI tools. |
514
+ | Homepage | https://github.com/kettle-dev/kettle-ndjson |
515
+ | Source | https://github.com/kettle-dev/kettle-ndjson |
516
+ | License | `MIT` |
517
+ | Funding | https://github.com/sponsors/pboling, https://ko-fi.com/pboling, https://liberapay.com/pboling/donate, https://opencollective.com/kettle-dev, https://thanks.dev/u/gh/pboling, https://tidelift.com/funding/github/rubygems/kettle-ndjson, https://www.buymeacoffee.com/pboling |
518
+ <!-- kettle-jem:metadata:end -->
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kettle
4
+ module Ndjson
5
+ module Version
6
+ VERSION = "0.1.0"
7
+ end
8
+ VERSION = Version::VERSION # Traditional Constant Location
9
+ end
10
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "version_gem"
5
+
6
+ require_relative "ndjson/version"
7
+
8
+ module Kettle
9
+ module Ndjson
10
+ EVENT_TYPES = %w[
11
+ run_start
12
+ phase_start
13
+ phase_finish
14
+ command_step
15
+ diagnostic
16
+ summary
17
+ ].freeze
18
+ DEFAULT_EVENT_TYPES = EVENT_TYPES.freeze
19
+ EVENT_TYPE_ALIASES = {
20
+ "all" => EVENT_TYPES,
21
+ "default" => DEFAULT_EVENT_TYPES,
22
+ "progress" => %w[run_start phase_start phase_finish command_step summary]
23
+ }.freeze
24
+
25
+ class Error < StandardError; end
26
+ class UnknownEventTypeError < Error; end
27
+
28
+ module_function
29
+
30
+ def event_stream(io, types: nil, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES)
31
+ EventStream.new(io, types: normalize_event_types(types, event_types: event_types, aliases: aliases))
32
+ end
33
+
34
+ def event_recorder(stream = nil, phase_timings: [])
35
+ EventRecorder.new(stream, phase_timings)
36
+ end
37
+
38
+ def normalize_event_types(types, event_types: EVENT_TYPES, aliases: EVENT_TYPE_ALIASES)
39
+ requested = types.to_s.strip
40
+ tokens = requested.empty? ? ["default"] : requested.split(",").map { |token| token.strip }.reject(&:empty?)
41
+ normalized = tokens.flat_map do |token|
42
+ normalized_token = token.tr("-", "_")
43
+ aliases.fetch(normalized_token) { normalized_token }
44
+ end.map(&:to_s).uniq
45
+ unknown = normalized - event_types.map(&:to_s)
46
+ raise UnknownEventTypeError, "Unknown event type(s): #{unknown.join(", ")}" unless unknown.empty?
47
+
48
+ normalized
49
+ end
50
+
51
+ def emit_event(events, type, payload = {})
52
+ return unless events
53
+
54
+ events.emit(payload.merge(type: type, event_version: 1))
55
+ end
56
+
57
+ def emit_phase_event(events, phase, status:, **payload)
58
+ event_type = (status.to_s == "started") ? "phase_start" : "phase_finish"
59
+ emit_event(events, event_type, payload.merge(phase: phase.to_s, status: status))
60
+ end
61
+
62
+ def record_phase_timing(events, phase, status:, duration_ms:, payload: {})
63
+ return unless events.respond_to?(:record_phase_timing)
64
+
65
+ events.record_phase_timing(
66
+ compact_payload(
67
+ payload.merge(
68
+ phase: phase.to_s,
69
+ status: status,
70
+ duration_ms: duration_ms
71
+ )
72
+ )
73
+ )
74
+ end
75
+
76
+ def emit_step_event(events, event_type, step, phase:, index: nil, total: nil)
77
+ emit_event(
78
+ events,
79
+ event_type,
80
+ phase: phase.to_s,
81
+ index: index,
82
+ total: total,
83
+ name: payload_value(step, :name),
84
+ status: payload_value(step, :status),
85
+ reason: payload_value(step, :reason),
86
+ command: payload_value(step, :command),
87
+ path: payload_value(step, :path),
88
+ changed_files: Array(payload_value(step, :changed_files) || []),
89
+ changed_count: Array(payload_value(step, :changed_files) || []).length,
90
+ mark: step_event_mark(step)
91
+ )
92
+ end
93
+
94
+ def emit_diagnostic_event(events, diagnostic, index: nil, total: nil)
95
+ payload = diagnostic.respond_to?(:to_h) ? diagnostic.to_h : {message: diagnostic.to_s}
96
+ emit_event(
97
+ events,
98
+ "diagnostic",
99
+ index: index,
100
+ total: total,
101
+ kind: payload[:kind] || payload["kind"] || payload[:key] || payload["key"],
102
+ severity: payload[:severity] || payload["severity"],
103
+ path: payload[:path] || payload["path"],
104
+ message: payload[:message] || payload["message"] || diagnostic.to_s,
105
+ blocking: payload[:blocking] || payload["blocking"]
106
+ )
107
+ end
108
+
109
+ def emit_summary_event(events, payload)
110
+ emit_event(events, "summary", payload.merge(mark: payload.fetch(:mark, ".")))
111
+ end
112
+
113
+ def step_event_mark(step)
114
+ return ">" if payload_value(step, :status).to_s == "started"
115
+ return "F" if %w[failed blocked].include?(payload_value(step, :status).to_s)
116
+
117
+ Array(payload_value(step, :changed_files) || []).empty? ? "." : "*"
118
+ end
119
+
120
+ def payload_value(payload, key)
121
+ return payload.public_send(key) if payload.respond_to?(key)
122
+
123
+ payload.fetch(key, payload.fetch(key.to_s, nil))
124
+ end
125
+
126
+ def compact_payload(payload)
127
+ payload.to_h.compact
128
+ end
129
+
130
+ class EventStream
131
+ def initialize(io, types:)
132
+ @io = io
133
+ @types = types.map(&:to_s)
134
+ end
135
+
136
+ attr_reader :types
137
+
138
+ def emit(payload)
139
+ return unless @types.include?(payload.fetch(:type).to_s)
140
+
141
+ @io.puts(JSON.generate(Kettle::Ndjson.compact_payload(payload)))
142
+ @io.flush if @io.respond_to?(:flush)
143
+ end
144
+ end
145
+
146
+ class EventRecorder
147
+ def initialize(stream = nil, phase_timings = [])
148
+ @stream = stream
149
+ @phase_timings = phase_timings
150
+ end
151
+
152
+ attr_reader :phase_timings
153
+
154
+ def emit(payload)
155
+ @stream&.emit(payload)
156
+ end
157
+
158
+ def record_phase_timing(payload)
159
+ @phase_timings << Kettle::Ndjson.compact_payload(payload)
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ Kettle::Ndjson::Version.class_eval do
166
+ extend VersionGem::Basic
167
+ end
@@ -0,0 +1,44 @@
1
+ module Kettle
2
+ module Ndjson
3
+ VERSION: String
4
+ EVENT_TYPES: Array[String]
5
+ DEFAULT_EVENT_TYPES: Array[String]
6
+ EVENT_TYPE_ALIASES: Hash[String, Array[String]]
7
+
8
+ def self.event_stream: (untyped io, ?types: String? types, ?event_types: Array[String] event_types, ?aliases: Hash[String, Array[String]] aliases) -> EventStream
9
+ def self.event_recorder: (?untyped stream, ?phase_timings: Array[Hash[Symbol, untyped]] phase_timings) -> EventRecorder
10
+ def self.normalize_event_types: (String? types, ?event_types: Array[String] event_types, ?aliases: Hash[String, Array[String]] aliases) -> Array[String]
11
+ def self.emit_event: (untyped events, String type, ?Hash[Symbol, untyped] payload) -> void
12
+ def self.emit_phase_event: (untyped events, String | Symbol phase, status: String status, **untyped payload) -> void
13
+ def self.record_phase_timing: (untyped events, String | Symbol phase, status: String status, duration_ms: Float duration_ms, ?payload: Hash[Symbol, untyped] payload) -> void
14
+ def self.emit_step_event: (untyped events, String event_type, Hash[Symbol | String, untyped] step, phase: String phase, ?index: Integer? index, ?total: Integer? total) -> void
15
+ def self.emit_diagnostic_event: (untyped events, untyped diagnostic, ?index: Integer? index, ?total: Integer? total) -> void
16
+ def self.emit_summary_event: (untyped events, Hash[Symbol, untyped] payload) -> void
17
+ def self.step_event_mark: (Hash[Symbol | String, untyped] step) -> String
18
+ def self.payload_value: (Hash[Symbol | String, untyped] payload, Symbol key) -> untyped
19
+ def self.compact_payload: (Hash[Symbol, untyped] payload) -> Hash[Symbol, untyped]
20
+
21
+ class Error < StandardError
22
+ end
23
+
24
+ class UnknownEventTypeError < Error
25
+ end
26
+
27
+ class EventStream
28
+ attr_reader types: Array[String]
29
+ def initialize: (untyped io, types: Array[String] types) -> void
30
+ def emit: (Hash[Symbol, untyped] payload) -> void
31
+ end
32
+
33
+ class EventRecorder
34
+ attr_reader phase_timings: Array[Hash[Symbol, untyped]]
35
+ def initialize: (?untyped stream, ?Array[Hash[Symbol, untyped]] phase_timings) -> void
36
+ def emit: (Hash[Symbol, untyped] payload) -> void
37
+ def record_phase_timing: (Hash[Symbol, untyped] payload) -> void
38
+ end
39
+
40
+ module Version
41
+ VERSION: String
42
+ end
43
+ end
44
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,296 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kettle-ndjson
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter H. Boling
8
+ bindir: exe
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
13
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
14
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
15
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
16
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
17
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
18
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
19
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
20
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
21
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
22
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
23
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
24
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
25
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
26
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
27
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
28
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
29
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
30
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
31
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
32
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
33
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
34
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
35
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
36
+ L9nRqA==
37
+ -----END CERTIFICATE-----
38
+ date: 1980-01-02 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: version_gem
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.1'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.1.14
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.1'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 1.1.14
60
+ - !ruby/object:Gem::Dependency
61
+ name: kettle-dev
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '2.3'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 2.3.7
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.3'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 2.3.7
80
+ - !ruby/object:Gem::Dependency
81
+ name: bundler-audit
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: 0.9.3
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.3
94
+ - !ruby/object:Gem::Dependency
95
+ name: rake
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '13.0'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '13.0'
108
+ - !ruby/object:Gem::Dependency
109
+ name: require_bench
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '1.0'
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.4
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: 1.0.4
128
+ - !ruby/object:Gem::Dependency
129
+ name: appraisal2
130
+ requirement: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: '3.2'
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 3.2.0
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '3.2'
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: 3.2.0
148
+ - !ruby/object:Gem::Dependency
149
+ name: kettle-test
150
+ requirement: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: '2.0'
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 2.0.15
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '2.0'
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: 2.0.15
168
+ - !ruby/object:Gem::Dependency
169
+ name: turbo_tests2
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '3.2'
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: 3.2.0
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: '3.2'
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: 3.2.0
188
+ - !ruby/object:Gem::Dependency
189
+ name: ruby-progressbar
190
+ requirement: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.13'
195
+ type: :development
196
+ prerelease: false
197
+ version_requirements: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.13'
202
+ - !ruby/object:Gem::Dependency
203
+ name: stone_checksums
204
+ requirement: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.0'
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: 1.0.6
212
+ type: :development
213
+ prerelease: false
214
+ version_requirements: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - "~>"
217
+ - !ruby/object:Gem::Version
218
+ version: '1.0'
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: 1.0.6
222
+ - !ruby/object:Gem::Dependency
223
+ name: gitmoji-regex
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '2.0'
229
+ - - ">="
230
+ - !ruby/object:Gem::Version
231
+ version: 2.0.4
232
+ type: :development
233
+ prerelease: false
234
+ version_requirements: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - "~>"
237
+ - !ruby/object:Gem::Version
238
+ version: '2.0'
239
+ - - ">="
240
+ - !ruby/object:Gem::Version
241
+ version: 2.0.4
242
+ description: "\U0001F4DF️ NDJSON event stream primitives, filters, recorders, and
243
+ payload helpers shared by Kettle CLI tools."
244
+ email:
245
+ - floss@galtzo.com
246
+ executables: []
247
+ extensions: []
248
+ extra_rdoc_files: []
249
+ files:
250
+ - CHANGELOG.md
251
+ - LICENSE.md
252
+ - README.md
253
+ - lib/kettle/ndjson.rb
254
+ - lib/kettle/ndjson/version.rb
255
+ - sig/kettle/ndjson.rbs
256
+ homepage: https://github.com/kettle-dev/kettle-ndjson
257
+ licenses:
258
+ - MIT
259
+ metadata:
260
+ homepage_uri: https://github.com/kettle-dev/kettle-ndjson
261
+ source_code_uri: https://github.com/kettle-dev/kettle-ndjson/tree/v0.1.0
262
+ changelog_uri: https://github.com/kettle-dev/kettle-ndjson/blob/v0.1.0/CHANGELOG.md
263
+ bug_tracker_uri: https://github.com/kettle-dev/kettle-ndjson/issues
264
+ documentation_uri: https://www.rubydoc.info/gems/kettle-ndjson/0.1.0
265
+ funding_uri: https://github.com/sponsors/pboling
266
+ wiki_uri: https://github.com/kettle-dev/kettle-ndjson/wiki
267
+ news_uri: https://www.railsbling.com/tags/kettle-ndjson
268
+ discord_uri: https://discord.gg/3qme4XHNKN
269
+ rubygems_mfa_required: 'true'
270
+ rdoc_options:
271
+ - "--title"
272
+ - "kettle-ndjson - \U0001F4DF️ NDJSON event streaming toolkit for Kettle CLI tools"
273
+ - "--main"
274
+ - README.md
275
+ - "--exclude"
276
+ - "^sig/"
277
+ - "--line-numbers"
278
+ - "--inline-source"
279
+ - "--quiet"
280
+ require_paths:
281
+ - lib
282
+ required_ruby_version: !ruby/object:Gem::Requirement
283
+ requirements:
284
+ - - ">="
285
+ - !ruby/object:Gem::Version
286
+ version: 3.2.0
287
+ required_rubygems_version: !ruby/object:Gem::Requirement
288
+ requirements:
289
+ - - ">="
290
+ - !ruby/object:Gem::Version
291
+ version: '0'
292
+ requirements: []
293
+ rubygems_version: 4.0.17
294
+ specification_version: 4
295
+ summary: "\U0001F4DF️ NDJSON event streaming toolkit for Kettle CLI tools"
296
+ test_files: []
metadata.gz.sig ADDED
Binary file