spinel_kit 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.
@@ -0,0 +1,87 @@
1
+ # SpinelKit::Log -- minimal levelled logger for spinel-AOT'd apps.
2
+ #
3
+ # WHY THIS EXISTS. CRuby's stdlib `Logger` is metaprogrammed (the severity
4
+ # dispatch loop, the formatter API, the device-rotation logic) and the
5
+ # spinelgems catalog rejects it (unresolved calls). Most app code that wants
6
+ # logging really wants three things: a level guard, a formatted line, and a
7
+ # destination. Ported verbatim from Tep::Logger; toy gains it for free.
8
+ #
9
+ # Surface
10
+ # -------
11
+ # logger = SpinelKit::Log.new
12
+ # logger.set_level("info") # one of: debug / info / warn / error
13
+ # logger.info("server up on " + port.to_s)
14
+ # logger.error("db connect failed")
15
+ #
16
+ # # File output: appends to the path. Leave unset for stderr.
17
+ # logger.to_file("/var/log/app.log")
18
+ #
19
+ # Each line is `[<unix_seconds>] [<level>] <message>`. The integer-seconds
20
+ # timestamp is what spinel exposes from `Time.now`; wider strftime support
21
+ # would need a C-shim (defer until callers ask for it).
22
+ #
23
+ # SPINEL NAMING DISCIPLINE: the method/param names below are the donor's
24
+ # proven-green spellings; the class-side `level_value` keeps the comparison
25
+ # a pure function so spinel pins its arg type to :str cleanly via a consumer
26
+ # type-seed. See docs/spinel-discipline.md.
27
+ module SpinelKit
28
+ class Log
29
+ attr_accessor :min_level, :file_path
30
+
31
+ def initialize
32
+ @min_level = "info"
33
+ @file_path = ""
34
+ end
35
+
36
+ def set_level(name); @min_level = name; end
37
+ def to_file(path); @file_path = path; end
38
+ def to_stderr; @file_path = ""; end
39
+
40
+ def debug(msg); log("debug", msg); end
41
+ def info(msg); log("info", msg); end
42
+ def warn(msg); log("warn", msg); end
43
+ def error(msg); log("error", msg); end
44
+
45
+ def log(level, msg)
46
+ if !should_log?(level)
47
+ return
48
+ end
49
+ line = format_line(level, msg)
50
+ if @file_path.length > 0
51
+ File.open(@file_path, "a") do |f|
52
+ f.puts(line)
53
+ end
54
+ else
55
+ $stderr.puts(line)
56
+ end
57
+ end
58
+
59
+ def should_log?(level)
60
+ Log.level_value(level) >= Log.level_value(@min_level)
61
+ end
62
+
63
+ # Class-side helper so the comparison stays a pure function and spinel
64
+ # pins its arg type to :str cleanly via a consumer-side type-seed.
65
+ def self.level_value(name)
66
+ if name == "debug"
67
+ return 0
68
+ end
69
+ if name == "info"
70
+ return 1
71
+ end
72
+ if name == "warn"
73
+ return 2
74
+ end
75
+ if name == "error"
76
+ return 3
77
+ end
78
+ # Unknown level -- treat as info so misspelled labels don't vanish
79
+ # silently.
80
+ 1
81
+ end
82
+
83
+ def format_line(level, msg)
84
+ "[" + Time.now.to_i.to_s + "] [" + level + "] " + msg
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,6 @@
1
+ # SpinelKit version. Kept in its own file so the gemspec can read it
2
+ # without loading the rest of the library (the json/git/log modules pull
3
+ # in no deps, but this matches the toy/tep convention exactly).
4
+ module SpinelKit
5
+ VERSION = "0.1.0"
6
+ end
data/lib/spinel_kit.rb ADDED
@@ -0,0 +1,39 @@
1
+ # SpinelKit -- the Spinel stdlib-surface gem.
2
+ #
3
+ # A pure-Ruby, Spinel-safe toolkit holding the generic "stdlib substitute"
4
+ # shims that every Spinel-compiled project would otherwise hand-roll. Spinel
5
+ # (the Ruby->native AOT compiler) cannot lower large chunks of CRuby stdlib
6
+ # -- the `json` gem's C-ext fast path and metaprogrammed pure-Ruby fallback,
7
+ # stdlib `Logger`, C-ext git bindings -- and the spinelgems compatibility
8
+ # catalog confirms there is no verified gem to reuse for any of them. So this
9
+ # gem consolidates the shims toy and tep each grew independently:
10
+ #
11
+ # SpinelKit::Json -- JSON encoders (json.rb) + flat-key decoders
12
+ # (json_decoder.rb).
13
+ # SpinelKit::Json::Builder -- incremental ordered-object builder.
14
+ # SpinelKit::Git -- git provenance from .git/HEAD (was Toy::Git).
15
+ # SpinelKit::Log -- minimal levelled logger (was Tep::Logger).
16
+ #
17
+ # MINIMAL-SURFACE REQUIRING. This umbrella requires everything for
18
+ # convenience (and for CRuby use). But because Spinel compiles every loaded
19
+ # method with no tree-shaking, a Spinel-compiled consumer should require ONLY
20
+ # the file(s) it uses, to avoid compiling -- and degrading -- code it never
21
+ # calls:
22
+ #
23
+ # require "spinel_kit/json" # encoders
24
+ # require "spinel_kit/json_decoder" # decoders (require alongside json if you decode)
25
+ # require "spinel_kit/json_builder" # builder
26
+ # require "spinel_kit/git"
27
+ # require "spinel_kit/log"
28
+ #
29
+ # No native extension (spinel-ext.json is []), no runtime dependencies. See
30
+ # docs/adoption.md and docs/spinel-discipline.md.
31
+ require_relative "spinel_kit/version"
32
+ require_relative "spinel_kit/json"
33
+ require_relative "spinel_kit/json_decoder"
34
+ require_relative "spinel_kit/json_builder"
35
+ require_relative "spinel_kit/git"
36
+ require_relative "spinel_kit/log"
37
+
38
+ module SpinelKit
39
+ end
@@ -0,0 +1,8 @@
1
+ module SpinelKit
2
+ class Git
3
+ def initialize: (String sha, String branch) -> void
4
+ def sha: () -> String
5
+ def branch: () -> String
6
+ def self.read: () -> SpinelKit::Git
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # Advisory RBS for SpinelKit::Json encoders (lib/spinel_kit/json.rb).
2
+ # Decoders are in json_decoder.rbs; the builder in json_builder.rbs.
3
+ module SpinelKit
4
+ class Json
5
+ def self.escape: (String s) -> String
6
+ def self.hex2: (Integer n) -> String
7
+ def self.quote: (String s) -> String
8
+ def self.encode_pair_str: (String k, String v) -> String
9
+ def self.encode_pair_int: (String k, Integer v) -> String
10
+ def self.from_str_hash: (Hash[String, String] h) -> String
11
+ def self.from_int_hash: (Hash[String, Integer] h) -> String
12
+ def self.from_str_array: (Array[String] a) -> String
13
+ def self.from_int_array: (Array[Integer] a) -> String
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module SpinelKit
2
+ class Json
3
+ class Builder
4
+ def initialize: () -> void
5
+ def add_str: (String key, String value) -> String
6
+ def add_num: (String key, untyped value) -> String
7
+ def add_bool: (String key, bool value) -> String
8
+ def add_raw: (String key, String raw) -> String
9
+ def add_obj: (String key, SpinelKit::Json::Builder child) -> String
10
+ def dump: () -> String
11
+ def comma: () -> void
12
+
13
+ # self-contained escapers (byte-identical to SpinelKit::Json.*)
14
+ def self.quote: (String s) -> String
15
+ def self.escape: (String s) -> String
16
+ def self.hex2: (Integer n) -> String
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # Advisory RBS for SpinelKit::Json decoders (lib/spinel_kit/json_decoder.rb).
2
+ module SpinelKit
3
+ class Json
4
+ def self.get_str: (String s, String key) -> String
5
+ def self.get_int: (String s, String key) -> Integer
6
+ def self.get_float: (String s, String key) -> Float
7
+ def self.get_int_array: (String s, String key) -> Array[Integer]
8
+ def self.has_key?: (String s, String key) -> bool
9
+
10
+ # internal walkers
11
+ def self.skip_ws: (String s, Integer pos) -> Integer
12
+ def self.skip_str: (String s, Integer pos) -> Integer
13
+ def self.skip_value: (String s, Integer pos) -> Integer
14
+ def self.skip_container: (String s, Integer pos) -> Integer
15
+ def self.parse_str_value: (String s, Integer pos) -> String
16
+ def self.hex_nibble: (String c) -> Integer
17
+ def self.byte_to_chr: (Integer n) -> String
18
+ def self.parse_int_value: (String s, Integer pos) -> Integer
19
+ def self.find_value_start: (String s, String target_key) -> Integer
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module SpinelKit
2
+ class Log
3
+ attr_accessor min_level: String
4
+ attr_accessor file_path: String
5
+
6
+ def initialize: () -> void
7
+ def set_level: (String name) -> String
8
+ def to_file: (String path) -> String
9
+ def to_stderr: () -> String
10
+ def debug: (String msg) -> void
11
+ def info: (String msg) -> void
12
+ def warn: (String msg) -> void
13
+ def error: (String msg) -> void
14
+ def log: (String level, String msg) -> void
15
+ def should_log?: (String level) -> bool
16
+ def self.level_value: (String name) -> Integer
17
+ def format_line: (String level, String msg) -> String
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module SpinelKit
2
+ VERSION: String
3
+ end
data/spinel-ext.json ADDED
@@ -0,0 +1 @@
1
+ []
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spinel_kit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ori Pekelman
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |-
13
+ SpinelKit consolidates the pure-Ruby "stdlib substitute" shims that every
14
+ Spinel-compiled project would otherwise hand-roll. Spinel (the Ruby->native
15
+ AOT compiler) cannot lower the json gem's C-ext fast path / metaprogrammed
16
+ fallback, stdlib Logger, or C-ext git bindings -- and the spinelgems
17
+ compatibility catalog confirms no verified gem exists to reuse. So this gem
18
+ ships a JSON encoder+decoder+builder, .git/HEAD provenance, and a minimal
19
+ levelled logger. Pure Ruby, no native extension, no runtime dependencies --
20
+ it vendors cleanly via bundler-spinel. Pre-alpha.
21
+ email:
22
+ - ori@pekelman.com
23
+ executables: []
24
+ extensions: []
25
+ extra_rdoc_files: []
26
+ files:
27
+ - CHANGELOG.md
28
+ - LICENSE
29
+ - README.md
30
+ - docs/adoption.md
31
+ - docs/gem-audit-first.md
32
+ - docs/spinel-discipline.md
33
+ - docs/spinelgems-issues.md
34
+ - lib/spinel_kit.rb
35
+ - lib/spinel_kit/git.rb
36
+ - lib/spinel_kit/json.rb
37
+ - lib/spinel_kit/json_builder.rb
38
+ - lib/spinel_kit/json_decoder.rb
39
+ - lib/spinel_kit/log.rb
40
+ - lib/spinel_kit/version.rb
41
+ - sig/spinel_kit/git.rbs
42
+ - sig/spinel_kit/json.rbs
43
+ - sig/spinel_kit/json_builder.rbs
44
+ - sig/spinel_kit/json_decoder.rbs
45
+ - sig/spinel_kit/log.rbs
46
+ - sig/spinel_kit/version.rbs
47
+ - spinel-ext.json
48
+ homepage: https://github.com/OriPekelman/spinelkit
49
+ licenses:
50
+ - MIT
51
+ metadata:
52
+ source_code_uri: https://github.com/OriPekelman/spinelkit
53
+ bug_tracker_uri: https://github.com/OriPekelman/spinelkit/issues
54
+ documentation_uri: https://github.com/OriPekelman/spinelkit#readme
55
+ changelog_uri: https://github.com/OriPekelman/spinelkit/blob/main/CHANGELOG.md
56
+ rubygems_mfa_required: 'true'
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 3.2.0
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.6.9
72
+ specification_version: 4
73
+ summary: 'The Spinel stdlib-surface gem: pure-Ruby JSON/Git/Log shims for AOT-compiled
74
+ apps'
75
+ test_files: []