shadwire 0.2.1 → 0.3.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 +4 -4
- data/README.md +15 -4
- data/lib/shadwire/binstub.rb +55 -0
- data/lib/shadwire/cli.rb +1 -1
- data/lib/shadwire/commands/init.rb +63 -8
- data/lib/shadwire/commands/status.rb +20 -1
- data/lib/shadwire/dependencies.rb +30 -11
- data/lib/shadwire/project.rb +6 -0
- data/lib/shadwire/version.rb +1 -1
- data/lib/shadwire.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6294368abb24616f95b0d9a751bb554ba5135904927f03e5d880c3b969448c2a
|
|
4
|
+
data.tar.gz: ebcf2c60b07a68b96d2c97d07759b05b44432bf634809e1e174958adf3ea51f9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e3db758ffe31655123b1460ec872f3ff001b68fa7c0f31e690eff757b1dd8a747af55fc50916ea9a855cfa0585a97c1077bab51930f07b68cb7a9887e85e5892
|
|
7
|
+
data.tar.gz: 91475dc299cd4f7a434684386696bb200c8dd8eb95a57f1d69b0696cfc3d3da045311d46b855e04b0d48fb52dc2f54633d86ea57e743345dd4676112d395c441
|
data/README.md
CHANGED
|
@@ -11,19 +11,29 @@ registry the CLI installs from over HTTP.
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
gem install shadwire # global — then: shadwire init
|
|
15
|
+
bundle add shadwire --group development # in the app — then: bundle exec shadwire init
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
`init` adds `shadwire` to the app's `development` group (if it is not there
|
|
19
|
+
already) and writes the `bin/shadwire` binstub. That binstub is the canonical
|
|
20
|
+
entry point: it resolves through the app's bundle, so everyone who installs the
|
|
21
|
+
development group runs the same CLI version. `init` is the one command you run
|
|
22
|
+
un-prefixed, because it is what creates the binstub.
|
|
23
|
+
|
|
24
|
+
A bundle installed with `--without development` (common for deploy, and for some
|
|
25
|
+
CI jobs) has no `shadwire`, so `bin/shadwire` will not run there. Install the
|
|
26
|
+
development group in any job that runs the CLI — the drift check below, for one.
|
|
27
|
+
|
|
18
28
|
Requires Ruby >= 3.2 and a Rails app (>= 7.1) using ViewComponent and Tailwind CSS.
|
|
19
29
|
|
|
20
30
|
## Commands
|
|
21
31
|
|
|
22
|
-
Run `shadwire help COMMAND` for the built-in usage of any command.
|
|
32
|
+
Run `bin/shadwire help COMMAND` for the built-in usage of any command.
|
|
23
33
|
|
|
24
34
|
| Command | What it does | Flags (besides `--cwd`) |
|
|
25
35
|
| --- | --- | --- |
|
|
26
|
-
| `init` | Bootstrap Shadwire: write `shadwire.json`, install the shared base files (`ui_component.rb`, `shadwire.css`) and base gems, add the Tailwind `@import`. | `--yes`, `--registry URL`, `--force`, `--json` |
|
|
36
|
+
| `init` | Bootstrap Shadwire: write `shadwire.json`, install the shared base files (`ui_component.rb`, `shadwire.css`) and base gems, add `shadwire` to the `development` group, write the `bin/shadwire` binstub, add the Tailwind `@import`. | `--yes`, `--registry URL`, `--force`, `--json` |
|
|
27
37
|
| `add NAME...` | Install one or more components and their registry dependencies; apply their gems and importmap pins; record them in `shadwire.json`. | `--yes`, `--overwrite`, `--no-deps`, `--registry URL`, `--json` |
|
|
28
38
|
| `list` | List every component in the registry catalog. | `--registry URL`, `--json` |
|
|
29
39
|
| `search QUERY` | Search the catalog by name, title, or description. | `--registry URL`, `--json` |
|
|
@@ -43,6 +53,7 @@ the Shadwire agent skill injects it:
|
|
|
43
53
|
{
|
|
44
54
|
"rails": true, "configPresent": true, "registryVersion": "0.2.0",
|
|
45
55
|
"stack": { "importmap": true, "stimulus": true, "tailwindcssRails": true },
|
|
56
|
+
"cli": { "gem": true, "binstub": true },
|
|
46
57
|
"helpers": { "includeAllHelpers": true, "legacyHelperPresent": false },
|
|
47
58
|
"installed": [
|
|
48
59
|
{ "name": "card", "drift": "unchanged",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
module Shadwire
|
|
7
|
+
# The canonical entry point a consuming app uses to run the CLI: bin/shadwire.
|
|
8
|
+
#
|
|
9
|
+
# The template is the shape Rails 8 generates for bin/rubocop and bin/brakeman,
|
|
10
|
+
# so the file reads as native to the app it lands in. Being a bundler binstub,
|
|
11
|
+
# it only works once `gem "shadwire"` is declared in the app's Gemfile —
|
|
12
|
+
# Commands::Init gates the write on that, because a binstub written without it
|
|
13
|
+
# raises Gem::LoadError on first run.
|
|
14
|
+
#
|
|
15
|
+
# Deliberately not routed through Installer: that writes published registry
|
|
16
|
+
# entries tracked in shadwire.json, and it never sets an execute bit.
|
|
17
|
+
module Binstub
|
|
18
|
+
PATH = "bin/shadwire"
|
|
19
|
+
MODE = 0o755
|
|
20
|
+
|
|
21
|
+
TEMPLATE = <<~RUBY
|
|
22
|
+
#!/usr/bin/env ruby
|
|
23
|
+
# frozen_string_literal: true
|
|
24
|
+
require "rubygems"
|
|
25
|
+
require "bundler/setup"
|
|
26
|
+
load Gem.bin_path("shadwire", "shadwire")
|
|
27
|
+
RUBY
|
|
28
|
+
|
|
29
|
+
# The gem that backs the binstub. `init` adds it, `status` reports it.
|
|
30
|
+
GEM = "shadwire"
|
|
31
|
+
|
|
32
|
+
def self.exist?(root)
|
|
33
|
+
File.exist?(File.join(root.to_s, PATH))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Writes bin/shadwire unless it already exists.
|
|
37
|
+
#
|
|
38
|
+
# An existing binstub is left alone: `bundle binstubs shadwire` produces a
|
|
39
|
+
# different, working file, and it is not tracked in shadwire.json, so
|
|
40
|
+
# `shadwire diff` could never report that we replaced it.
|
|
41
|
+
#
|
|
42
|
+
# @param root [String, Pathname] the consuming app root
|
|
43
|
+
# @param force [Boolean] rewrite an existing binstub
|
|
44
|
+
# @return [Hash] { written: Boolean, skipped: Boolean }
|
|
45
|
+
def self.write(root, force: false)
|
|
46
|
+
path = Pathname(root).join(PATH)
|
|
47
|
+
return { written: false, skipped: true } if path.exist? && !force
|
|
48
|
+
|
|
49
|
+
FileUtils.mkdir_p(path.dirname)
|
|
50
|
+
path.write(TEMPLATE)
|
|
51
|
+
path.chmod(MODE)
|
|
52
|
+
{ written: true, skipped: false }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/shadwire/cli.rb
CHANGED
|
@@ -21,7 +21,7 @@ module Shadwire
|
|
|
21
21
|
desc: "Apply dependency changes without prompting"
|
|
22
22
|
method_option :registry, type: :string, desc: "Registry base URL to install from"
|
|
23
23
|
method_option :force, type: :boolean, default: false,
|
|
24
|
-
desc: "
|
|
24
|
+
desc: "Reset shadwire.json and rewrite bin/shadwire, overwriting both"
|
|
25
25
|
method_option :json, type: :boolean, default: false, desc: "Emit machine-readable JSON"
|
|
26
26
|
def init
|
|
27
27
|
run_command do |root, ui|
|
|
@@ -8,6 +8,12 @@ module Shadwire
|
|
|
8
8
|
# files, and applies the base gems + the Tailwind @import (confirm-then-apply,
|
|
9
9
|
# auto on yes:). Idempotent on re-run; --force resets shadwire.json.
|
|
10
10
|
class Init
|
|
11
|
+
# The CLI gem is a development-time tool for the app, deliberately kept out
|
|
12
|
+
# of registry.json: the registry's gems are what the *components* need at
|
|
13
|
+
# runtime, and installed files carry no Shadwire dependency.
|
|
14
|
+
CLI_GEM = Binstub::GEM
|
|
15
|
+
CLI_GEM_GROUP = "development"
|
|
16
|
+
|
|
11
17
|
def initialize(root:, registry: nil, yes: false, force: false, json: false,
|
|
12
18
|
ui: UI.new(yes:), runner: Dependencies::DEFAULT_RUNNER)
|
|
13
19
|
@root = root.to_s
|
|
@@ -31,16 +37,21 @@ module Shadwire
|
|
|
31
37
|
|
|
32
38
|
deps = Dependencies.new(project, runner: @runner)
|
|
33
39
|
confirm = ->(desc) { @ui.confirm?(desc) }
|
|
34
|
-
|
|
40
|
+
base_gems = deps.ensure_gems(Array(base["gems"]), yes: @yes, confirm:)
|
|
41
|
+
cli_gem = deps.ensure_gems([CLI_GEM], yes: @yes, confirm:, group: CLI_GEM_GROUP)
|
|
42
|
+
gems = merge_gem_results(base_gems, cli_gem)
|
|
35
43
|
tailwind = deps.ensure_tailwind_import(
|
|
36
44
|
vendor_css_target(config, base), css_entry: config.tailwind_css, yes: @yes, confirm:
|
|
37
45
|
)
|
|
46
|
+
binstub = write_binstub(cli_gem)
|
|
38
47
|
|
|
39
48
|
config.save
|
|
40
49
|
warn_missing_stack(project)
|
|
41
|
-
result = { config:, report:, gems:, tailwind: }
|
|
50
|
+
result = { config:, report:, gems:, gem_results: [base_gems, cli_gem], tailwind:, binstub: }
|
|
42
51
|
emit(result)
|
|
43
|
-
|
|
52
|
+
# Passed separately, not merged: each result carries its own group, so
|
|
53
|
+
# the recovery command it suggests matches the one that failed.
|
|
54
|
+
Dependencies.raise_on_failure!(base_gems, cli_gem)
|
|
44
55
|
|
|
45
56
|
result
|
|
46
57
|
end
|
|
@@ -55,6 +66,27 @@ module Shadwire
|
|
|
55
66
|
config
|
|
56
67
|
end
|
|
57
68
|
|
|
69
|
+
def merge_gem_results(*results)
|
|
70
|
+
%i[applied skipped pending manual failed]
|
|
71
|
+
.to_h { |key| [key, results.flat_map { |result| result[key] }] }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Only write the binstub once `shadwire` is actually declared in the app's
|
|
75
|
+
# Gemfile — a bundler binstub without it raises Gem::LoadError on first run.
|
|
76
|
+
#
|
|
77
|
+
# The gate reads the ensure_gems result rather than re-reading the Gemfile:
|
|
78
|
+
# it is a direct record of what the command did, and it does not depend on
|
|
79
|
+
# `bundle add` writing a line the Project#gem? regex recognizes.
|
|
80
|
+
def write_binstub(cli_gem)
|
|
81
|
+
present = (cli_gem[:applied] + cli_gem[:skipped]).include?(CLI_GEM)
|
|
82
|
+
# An existing binstub without the gem is a different problem from a
|
|
83
|
+
# missing one: telling someone to create a file that is already there
|
|
84
|
+
# buries the real issue, which is that it cannot run.
|
|
85
|
+
return { status: Binstub.exist?(@root) ? :unusable : :unavailable } unless present
|
|
86
|
+
|
|
87
|
+
Binstub.write(@root, force: @force)[:written] ? { status: :written } : { status: :skipped }
|
|
88
|
+
end
|
|
89
|
+
|
|
58
90
|
def vendor_css_target(config, base)
|
|
59
91
|
File.join(config.aliases.fetch("vendorCss", "vendor/shadwire"), base.dig("tailwind", "css"))
|
|
60
92
|
end
|
|
@@ -74,7 +106,7 @@ module Shadwire
|
|
|
74
106
|
def emit(result)
|
|
75
107
|
return @ui.say(JSON.generate(json_payload(result))) if @json
|
|
76
108
|
|
|
77
|
-
print_summary(result[:report], result[:
|
|
109
|
+
print_summary(result[:report], result[:gem_results], result[:tailwind], result[:binstub])
|
|
78
110
|
end
|
|
79
111
|
|
|
80
112
|
def json_payload(result)
|
|
@@ -83,18 +115,41 @@ module Shadwire
|
|
|
83
115
|
"gems" => { "applied" => result[:gems][:applied], "pending" => result[:gems][:pending],
|
|
84
116
|
"failed" => result[:gems][:failed] },
|
|
85
117
|
"tailwind" => { "applied" => result[:tailwind][:applied], "manual" => result[:tailwind][:manual] },
|
|
118
|
+
"binstub" => { "path" => Binstub::PATH,
|
|
119
|
+
"written" => result[:binstub][:status] == :written,
|
|
120
|
+
"skipped" => result[:binstub][:status] == :skipped },
|
|
86
121
|
"registry" => result[:config].registry
|
|
87
122
|
}
|
|
88
123
|
end
|
|
89
124
|
|
|
90
|
-
def print_summary(report,
|
|
125
|
+
def print_summary(report, gem_results, tailwind, binstub)
|
|
91
126
|
@ui.say("Initialized shadwire (#{report[:written].size} base files).")
|
|
92
127
|
report[:written].each { |t| @ui.say(" create #{t}") }
|
|
93
|
-
|
|
94
|
-
gems[:pending].each { |g| @ui.say(" pending #{g} (not installed — run: bundle add #{g})") }
|
|
95
|
-
gems[:failed].each { |g| @ui.say(" FAILED #{g} (bundle add failed)") }
|
|
128
|
+
gem_results.each { |result| print_gems(result) }
|
|
96
129
|
(tailwind[:applied]).each { |i| @ui.say(" tailwind #{i}") }
|
|
97
130
|
tailwind[:manual].each { |m| @ui.say(" manual #{m}") }
|
|
131
|
+
print_binstub(binstub)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Each result prints its own group, so the command it tells you to run is
|
|
135
|
+
# the one that would actually have worked.
|
|
136
|
+
def print_gems(result)
|
|
137
|
+
suffix = result[:group] ? " --group #{result[:group]}" : ""
|
|
138
|
+
result[:applied].each { |g| @ui.say(" gem #{g}") }
|
|
139
|
+
result[:pending].each { |g| @ui.say(" pending #{g} (not installed — run: bundle add #{g}#{suffix})") }
|
|
140
|
+
result[:failed].each { |g| @ui.say(" FAILED #{g} (bundle add failed)") }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def print_binstub(binstub)
|
|
144
|
+
case binstub[:status]
|
|
145
|
+
when :written then @ui.say(" create #{Binstub::PATH}")
|
|
146
|
+
when :skipped then @ui.say(" skip #{Binstub::PATH} (already exists)")
|
|
147
|
+
when :unusable
|
|
148
|
+
@ui.say(" warn #{Binstub::PATH} exists but `gem \"#{CLI_GEM}\"` is not in the " \
|
|
149
|
+
"Gemfile — it will not run until it is")
|
|
150
|
+
when :unavailable
|
|
151
|
+
@ui.say(" manual #{Binstub::PATH} (add `gem \"#{CLI_GEM}\"` to the Gemfile, then re-run init)")
|
|
152
|
+
end
|
|
98
153
|
end
|
|
99
154
|
end
|
|
100
155
|
end
|
|
@@ -23,8 +23,9 @@ module Shadwire
|
|
|
23
23
|
|
|
24
24
|
def call
|
|
25
25
|
project = Project.new(@root)
|
|
26
|
-
config =
|
|
26
|
+
config, config_error = load_config
|
|
27
27
|
result = context(project, config)
|
|
28
|
+
result["configError"] = config_error if config_error
|
|
28
29
|
|
|
29
30
|
begin
|
|
30
31
|
client = RegistryClient.new(@registry_override || config.registry)
|
|
@@ -41,6 +42,16 @@ module Shadwire
|
|
|
41
42
|
|
|
42
43
|
private
|
|
43
44
|
|
|
45
|
+
# A hand-edited shadwire.json must not raise here. The agent skill injects
|
|
46
|
+
# this command and discards stderr while it chains invocation forms, so a
|
|
47
|
+
# non-zero exit would reach the agent as "no CLI here" with the real
|
|
48
|
+
# diagnostic thrown away. Report it and carry on with defaults instead.
|
|
49
|
+
def load_config
|
|
50
|
+
[Config.load(@root), nil]
|
|
51
|
+
rescue Shadwire::Error => e
|
|
52
|
+
[Config.new(@root, JSON.parse(JSON.generate(Config::DEFAULTS))), e.message]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
def context(project, config)
|
|
45
56
|
{
|
|
46
57
|
"rails" => project.rails?,
|
|
@@ -57,6 +68,12 @@ module Shadwire
|
|
|
57
68
|
"view_component" => project.gem?("view_component"),
|
|
58
69
|
"lucide-rails" => project.gem?("lucide-rails")
|
|
59
70
|
},
|
|
71
|
+
# The canonical entry point, so the skill can name one invocation
|
|
72
|
+
# rather than inspecting the Gemfile to guess at one.
|
|
73
|
+
"cli" => {
|
|
74
|
+
"gem" => project.gem?("shadwire"),
|
|
75
|
+
"binstub" => project.binstub?
|
|
76
|
+
},
|
|
60
77
|
"tailwind" => {
|
|
61
78
|
"css" => config.tailwind_css,
|
|
62
79
|
"importPresent" => tailwind_import?(config)
|
|
@@ -120,11 +137,13 @@ module Shadwire
|
|
|
120
137
|
@ui.say("Stack: importmap=#{result.dig("stack", "importmap")} " \
|
|
121
138
|
"stimulus=#{result.dig("stack", "stimulus")} " \
|
|
122
139
|
"tailwindcss-rails=#{result.dig("stack", "tailwindcssRails")}")
|
|
140
|
+
@ui.say("CLI: binstub=#{result.dig("cli", "binstub")} gem=#{result.dig("cli", "gem")}")
|
|
123
141
|
@ui.say("Installed (#{result["installed"].size} of #{result["availableCount"] || "?"}):")
|
|
124
142
|
result["installed"].each do |item|
|
|
125
143
|
@ui.say(" #{item["drift"].ljust(9)} #{item["name"]} #{item["helpers"].join(", ")}")
|
|
126
144
|
end
|
|
127
145
|
|
|
146
|
+
@ui.warn("shadwire.json unreadable, using defaults: #{result["configError"]}") if result["configError"]
|
|
128
147
|
@ui.warn("Registry unavailable: #{result["registryError"]}") if result["registryError"]
|
|
129
148
|
return unless result.dig("helpers", "legacyHelperPresent")
|
|
130
149
|
|
|
@@ -28,12 +28,25 @@ module Shadwire
|
|
|
28
28
|
# Raises when any of the given result hashes reports something it failed to
|
|
29
29
|
# apply, so a command that could not install a dependency exits non-zero
|
|
30
30
|
# instead of claiming success.
|
|
31
|
+
# Each result carries its own `group:`, so the recovery command it suggests
|
|
32
|
+
# matches the one that failed. Collapsing them would tell the user to
|
|
33
|
+
# `bundle add shadwire`, landing the development-only CLI in the app's
|
|
34
|
+
# runtime dependencies.
|
|
31
35
|
def self.raise_on_failure!(*results)
|
|
32
|
-
|
|
33
|
-
return if
|
|
36
|
+
failing = results.reject { |result| Array(result[:failed]).empty? }
|
|
37
|
+
return if failing.empty?
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
names = failing.flat_map { |result| Array(result[:failed]) }.uniq
|
|
40
|
+
commands = failing.map { |result| bundle_add_command(result) }
|
|
41
|
+
|
|
42
|
+
raise Error, "Failed to install: #{names.join(", ")}. " \
|
|
43
|
+
"Run `#{commands.join("` and `")}` in the app and re-run this command."
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# `bundle add <names...>` for a result, with its group when it has one.
|
|
47
|
+
def self.bundle_add_command(result)
|
|
48
|
+
suffix = result[:group] ? " --group #{result[:group]}" : ""
|
|
49
|
+
"bundle add #{Array(result[:failed]).join(" ")}#{suffix}"
|
|
37
50
|
end
|
|
38
51
|
|
|
39
52
|
def initialize(project, runner: DEFAULT_RUNNER)
|
|
@@ -42,20 +55,26 @@ module Shadwire
|
|
|
42
55
|
end
|
|
43
56
|
|
|
44
57
|
# Ensures each gem name is present, running `bundle add <missing...>`.
|
|
45
|
-
|
|
58
|
+
# `group:` adds them to a bundler group — used for the shadwire CLI itself,
|
|
59
|
+
# which belongs in development, not in the app's runtime dependencies.
|
|
60
|
+
def ensure_gems(names, yes:, confirm: nil, group: nil)
|
|
46
61
|
present = names.select { |name| @project.gem?(name) }
|
|
47
62
|
missing = names - present
|
|
48
63
|
return result(skipped: present) if missing.empty?
|
|
49
64
|
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
suffix = group ? " --group #{group}" : ""
|
|
66
|
+
unless apply?(yes, confirm, "Add gems: #{missing.join(", ")} (bundle add#{suffix})")
|
|
67
|
+
return result(skipped: present, pending: missing, group:)
|
|
52
68
|
end
|
|
53
69
|
|
|
70
|
+
command = ["bundle", "add", *missing]
|
|
71
|
+
command.push("--group", group.to_s) if group
|
|
72
|
+
|
|
54
73
|
# `system` returns false on a non-zero exit and nil when the command could
|
|
55
74
|
# not be run at all; neither means the gems landed.
|
|
56
|
-
return result(skipped: present, failed: missing) unless @runner.call(
|
|
75
|
+
return result(skipped: present, failed: missing, group:) unless @runner.call(command, chdir: @project.root)
|
|
57
76
|
|
|
58
|
-
result(applied: missing, skipped: present)
|
|
77
|
+
result(applied: missing, skipped: present, group:)
|
|
59
78
|
end
|
|
60
79
|
|
|
61
80
|
# Ensures each pin ({ "name" =>, "to" => }) exists in config/importmap.rb.
|
|
@@ -106,8 +125,8 @@ module Shadwire
|
|
|
106
125
|
|
|
107
126
|
private
|
|
108
127
|
|
|
109
|
-
def result(applied: [], skipped: [], pending: [], manual: [], failed: [])
|
|
110
|
-
{ applied:, skipped:, pending:, manual:, failed: }
|
|
128
|
+
def result(applied: [], skipped: [], pending: [], manual: [], failed: [], group: nil)
|
|
129
|
+
{ applied:, skipped:, pending:, manual:, failed:, group: }
|
|
111
130
|
end
|
|
112
131
|
|
|
113
132
|
def apply?(yes, confirm, description)
|
data/lib/shadwire/project.rb
CHANGED
|
@@ -33,6 +33,12 @@ module Shadwire
|
|
|
33
33
|
gem?("stimulus-rails") || File.exist?(path("app/javascript/controllers/index.js"))
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# The canonical CLI entry point. `status` reports it so the agent skill can
|
|
37
|
+
# name one invocation instead of guessing from the Gemfile.
|
|
38
|
+
def binstub?
|
|
39
|
+
Binstub.exist?(@root)
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
def importmap_path
|
|
37
43
|
path("config/importmap.rb")
|
|
38
44
|
end
|
data/lib/shadwire/version.rb
CHANGED
data/lib/shadwire.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shadwire
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eduardo de Moraes
|
|
@@ -36,6 +36,7 @@ files:
|
|
|
36
36
|
- README.md
|
|
37
37
|
- exe/shadwire
|
|
38
38
|
- lib/shadwire.rb
|
|
39
|
+
- lib/shadwire/binstub.rb
|
|
39
40
|
- lib/shadwire/cli.rb
|
|
40
41
|
- lib/shadwire/commands/add.rb
|
|
41
42
|
- lib/shadwire/commands/diff.rb
|