tina4ruby 3.13.127 → 3.13.129
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/lib/tina4/cli.rb +196 -23
- data/lib/tina4/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0792f247e0fc7d10a52db84896d8cd475d509e258a1b121b06564e45cfa3913
|
|
4
|
+
data.tar.gz: 91ecd21265adabfd4874596c68b63f10c36bab1cb39fd49c4be4b0db1d8ec289
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a464c761ff621eeb3a10068a1ad436fe1b71d1403792885a07442b1f8dc475d80c1f64736e3a456c2a71edd72c0fee6fabd215e8fb61e6eb543e2d2b02531831
|
|
7
|
+
data.tar.gz: 86c6e9cb683134790b85159c797225c3bb8d126fe8fbc1d0bfc8d0f3aeaf1dfcf781b5a21ae4d8cf414c04875726a32db98cc5cfd12b87b10603e815d805e17a
|
data/lib/tina4/cli.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "set"
|
|
|
6
6
|
require "json"
|
|
7
7
|
require "tmpdir" # Dir.mktmpdir — used by the ADR-0063 sandbox edit-hint scan
|
|
8
8
|
require "stringio" # StringIO — captures generator stdout during the sandbox run
|
|
9
|
+
require "open3" # Open3.capture2e — captures `ruby -c` output+status for `lint`
|
|
9
10
|
require_relative "port_takeover"
|
|
10
11
|
|
|
11
12
|
module Tina4
|
|
@@ -29,7 +30,7 @@ module Tina4
|
|
|
29
30
|
# handlers take (name, flags); COMMANDS handlers take (argv).
|
|
30
31
|
|
|
31
32
|
GENERATORS = {
|
|
32
|
-
"model" => { handler: :generate_model, usage: '<Name> [--fields "name:string,price:float"]', summary: "ORM model + matching migration" },
|
|
33
|
+
"model" => { handler: :generate_model, usage: '<Name> [--fields "name:string,price:float"] [--table-name <name>]', summary: "ORM model + matching migration" },
|
|
33
34
|
"route" => { handler: :generate_route, usage: "<name> [--model Name] [--public]", summary: "CRUD route file, secure by default (--public opens writes)" },
|
|
34
35
|
"crud" => { handler: :generate_crud, usage: '<Name> [--fields "..."] [--public]', summary: "Model + migration + routes + form + view + test" },
|
|
35
36
|
"migration" => { handler: :generate_migration, usage: "<description>", summary: "Timestamped migration file (UP/DOWN)" },
|
|
@@ -70,6 +71,7 @@ module Tina4
|
|
|
70
71
|
"test" => { handler: :cmd_test, summary: "Run inline tests" },
|
|
71
72
|
"queue" => { handler: :cmd_queue, usage: "<work|stats|retry|clear> [topic]", subcommands: QUEUE_SUBCOMMANDS.keys, summary: "Run queue workers and manage jobs" },
|
|
72
73
|
"build" => { handler: :cmd_build, usage: "[--tag NAME] [--file PATH]", summary: "Build the deployable Docker image" },
|
|
74
|
+
"lint" => { handler: :cmd_lint, usage: "[--fix] [--no-install]", summary: "Lint src/ + app.rb (rubocop, installed dev-only on demand, else ruby -c)" },
|
|
73
75
|
"version" => { handler: :cmd_version, summary: "Show Tina4 version" },
|
|
74
76
|
"routes" => { handler: :cmd_routes, summary: "List all registered routes" },
|
|
75
77
|
"console" => { handler: :cmd_console, summary: "Start an interactive console" },
|
|
@@ -282,6 +284,52 @@ module Tina4
|
|
|
282
284
|
pluralize_table(to_snake_case(name))
|
|
283
285
|
end
|
|
284
286
|
|
|
287
|
+
# The table name a generator uses, honouring `--table-name` and speaking up
|
|
288
|
+
# instead of renaming silently (issue #123). Mirrors `_resolve_table` in
|
|
289
|
+
# tina4-python/tina4_python/cli/__init__.py:98.
|
|
290
|
+
#
|
|
291
|
+
# `announce` prints the note/warning; it is TRUE only for `generate_model`
|
|
292
|
+
# (where the table is born). Composite generators (crud) let the model
|
|
293
|
+
# sub-call announce, and generators that target an EXISTING table
|
|
294
|
+
# (seeder/form/view) still honour `--table-name` but stay quiet so the note
|
|
295
|
+
# is not repeated. `build_model_resolution` calls it with announce:false too,
|
|
296
|
+
# so the envelope's table_name/migration_path equal what lands on disk.
|
|
297
|
+
#
|
|
298
|
+
# * `--table-name <name>` wins verbatim. If that name is ITSELF a reserved
|
|
299
|
+
# word, warn loudly: Tina4 interpolates table names UNQUOTED, so the ORM's
|
|
300
|
+
# generated SQL will fail on it and quoting it in raw SQL + migrations is
|
|
301
|
+
# now the developer's job (we do NOT silently quote — identifier quoting is
|
|
302
|
+
# a global storage invariant, not a local fix).
|
|
303
|
+
# * Otherwise fall back to `to_table_name`. When that auto-pluralises a
|
|
304
|
+
# reserved-word class name (Order -> orders), print a one-line note naming
|
|
305
|
+
# the rename and the `--table-name` escape hatch, so the developer is
|
|
306
|
+
# informed rather than surprised.
|
|
307
|
+
def resolve_table(name, flags = {}, announce: false)
|
|
308
|
+
flags ||= {}
|
|
309
|
+
override = flags["table-name"]
|
|
310
|
+
# A real value only — a bare `--table-name` parses to `true` and an empty
|
|
311
|
+
# `--table-name ""` to "", both of which fall through to the pluralise path
|
|
312
|
+
# (parity with Python's `if override and not isinstance(override, bool)`).
|
|
313
|
+
if override.is_a?(String) && !override.empty?
|
|
314
|
+
if announce && SQL_RESERVED_TABLE_NAMES.include?(to_snake_case(override))
|
|
315
|
+
puts " ! table_name '#{override}' is a SQL reserved word. Tina4 interpolates " \
|
|
316
|
+
"table names UNQUOTED, so the ORM's generated SQL will fail on it -- " \
|
|
317
|
+
"quote it yourself in raw SQL and migrations."
|
|
318
|
+
end
|
|
319
|
+
return override
|
|
320
|
+
end
|
|
321
|
+
bare = to_snake_case(name)
|
|
322
|
+
if SQL_RESERVED_TABLE_NAMES.include?(bare)
|
|
323
|
+
table = pluralize_table(bare)
|
|
324
|
+
if announce
|
|
325
|
+
puts " · '#{bare}' is a SQL reserved word; using table_name '#{table}' " \
|
|
326
|
+
"(Tina4 interpolates table names unquoted). Override with --table-name <name>."
|
|
327
|
+
end
|
|
328
|
+
return table
|
|
329
|
+
end
|
|
330
|
+
bare
|
|
331
|
+
end
|
|
332
|
+
|
|
285
333
|
# Called without --fields, the generators fall back to a single `name`
|
|
286
334
|
# string column. That default MUST be materialised here, in one place, and
|
|
287
335
|
# then flow into the model, the migration, the form, the view and the spec
|
|
@@ -516,7 +564,7 @@ module Tina4
|
|
|
516
564
|
# Parse --key value and --flag from args. Returns [flags_hash, positional_array]
|
|
517
565
|
def parse_flags(args)
|
|
518
566
|
# Boolean-only flags that never take a value argument
|
|
519
|
-
boolean_flags = %w[no-browser no-reload production managed all clear dev json public no-migration once dry-run]
|
|
567
|
+
boolean_flags = %w[no-browser no-reload production managed all clear dev json public no-migration once dry-run fix no-install]
|
|
520
568
|
|
|
521
569
|
flags = {}
|
|
522
570
|
positional = []
|
|
@@ -1206,6 +1254,126 @@ module Tina4
|
|
|
1206
1254
|
puts " Run: docker run -p 7147:7147 #{tag}"
|
|
1207
1255
|
end
|
|
1208
1256
|
|
|
1257
|
+
# ── lint ──────────────────────────────────────────────────────────────
|
|
1258
|
+
#
|
|
1259
|
+
# Lint the project's source. The framework ships NO linter (so a Tina4 app
|
|
1260
|
+
# stays zero-dependency); `tina4ruby lint` uses the project's own rubocop and
|
|
1261
|
+
# INSTALLS it as a DEV dependency on demand when it is absent. Layers:
|
|
1262
|
+
#
|
|
1263
|
+
# * rubocop present (bundled via the project Gemfile, or on PATH): run it.
|
|
1264
|
+
# `--fix` runs `rubocop -a` (safe autocorrect). rubocop reports syntax
|
|
1265
|
+
# too, so it is the whole pass when present.
|
|
1266
|
+
# * rubocop absent: silently `bundle add rubocop --group development` --
|
|
1267
|
+
# running `tina4ruby lint` is the consent to add it -- then run it. It
|
|
1268
|
+
# lands in the development group only, never the app's runtime
|
|
1269
|
+
# dependencies. `--no-install` skips this.
|
|
1270
|
+
# * Baseline (zero dependency): the built-in `ruby -c` syntax parse -- no
|
|
1271
|
+
# execution, nothing written, no dependency. Used with `--no-install` or
|
|
1272
|
+
# when the install cannot run (no bundler/Gemfile, offline).
|
|
1273
|
+
#
|
|
1274
|
+
# Contract (identical across all four frameworks): exit 0 = clean, non-zero =
|
|
1275
|
+
# findings; the summary names the tool that ran in [brackets]. Scope is the
|
|
1276
|
+
# user's app (`src/` recursively + `app.rb`), mirroring how `tina4ruby test`
|
|
1277
|
+
# runs the project's own specs -- not the framework's code. Ruby mirror of
|
|
1278
|
+
# the Python master's `_lint` (tina4-python/tina4_python/cli/__init__.py).
|
|
1279
|
+
#
|
|
1280
|
+
# tina4ruby lint # rubocop (installed dev-only on demand), else baseline
|
|
1281
|
+
# tina4ruby lint --fix # rubocop -a
|
|
1282
|
+
# tina4ruby lint --no-install # rubocop if already present, else the syntax baseline
|
|
1283
|
+
def cmd_lint(argv)
|
|
1284
|
+
flags, _positional = parse_flags(argv)
|
|
1285
|
+
fix = flags["fix"] == true
|
|
1286
|
+
no_install = flags["no-install"] == true
|
|
1287
|
+
|
|
1288
|
+
rb_files = []
|
|
1289
|
+
rb_files.concat(Dir.glob(File.join("src", "**", "*.rb")).sort) if File.directory?("src")
|
|
1290
|
+
rb_files << "app.rb" if File.file?("app.rb")
|
|
1291
|
+
|
|
1292
|
+
if rb_files.empty?
|
|
1293
|
+
puts " lint: nothing to lint (no src/ or app.rb)."
|
|
1294
|
+
exit 0
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1297
|
+
rubocop = resolve_rubocop
|
|
1298
|
+
|
|
1299
|
+
# Silent on-demand install: running `tina4ruby lint` is the consent to add
|
|
1300
|
+
# rubocop as a DEV dependency of the project. --no-install opts out (CI /
|
|
1301
|
+
# offline) and falls through to the zero-dependency baseline. Needs bundler
|
|
1302
|
+
# AND a Gemfile to mutate.
|
|
1303
|
+
if rubocop.nil? && !no_install
|
|
1304
|
+
bundle = which_executable("bundle")
|
|
1305
|
+
if bundle && File.file?("Gemfile")
|
|
1306
|
+
puts " · rubocop not found -- adding it as a dev dependency (bundle add rubocop --group development)..."
|
|
1307
|
+
if system(bundle, "add", "rubocop", "--group", "development")
|
|
1308
|
+
rubocop = resolve_rubocop
|
|
1309
|
+
else
|
|
1310
|
+
puts " · could not install rubocop -- using the zero-dependency syntax baseline."
|
|
1311
|
+
end
|
|
1312
|
+
end
|
|
1313
|
+
end
|
|
1314
|
+
|
|
1315
|
+
if rubocop
|
|
1316
|
+
label = fix ? "rubocop -a" : "rubocop"
|
|
1317
|
+
command = rubocop + (fix ? ["-a"] : []) + rb_files
|
|
1318
|
+
ok = system(*command) # inherits stdio — rubocop prints its own report
|
|
1319
|
+
if ok
|
|
1320
|
+
puts " ✓ lint clean -- #{rb_files.length} file(s) [#{label}]"
|
|
1321
|
+
exit 0
|
|
1322
|
+
end
|
|
1323
|
+
puts " ✗ lint failed -- #{rb_files.length} file(s) [#{label}]"
|
|
1324
|
+
exit 1
|
|
1325
|
+
end
|
|
1326
|
+
|
|
1327
|
+
# Zero-dependency baseline: the built-in `ruby -c` syntax parse. No
|
|
1328
|
+
# execution, nothing written, no dependency added.
|
|
1329
|
+
puts " · syntax baseline has no autofix (--no-install, or rubocop unavailable)." if fix
|
|
1330
|
+
|
|
1331
|
+
syntax_errors = 0
|
|
1332
|
+
rb_files.each do |rel|
|
|
1333
|
+
output, status = Open3.capture2e("ruby", "-c", rel)
|
|
1334
|
+
next if status.success? # "Syntax OK"
|
|
1335
|
+
|
|
1336
|
+
syntax_errors += 1
|
|
1337
|
+
# `ruby -c` names the file+line in its first diagnostic line
|
|
1338
|
+
# (e.g. "ruby: src/broken.rb:2: syntax errors found (SyntaxError)"); drop
|
|
1339
|
+
# the redundant leading "ruby: " so the shape matches the Python master's
|
|
1340
|
+
# "file:lineno: msg".
|
|
1341
|
+
first_line = output.strip.sub(/\Aruby:\s*/, "").lines.first.to_s.rstrip
|
|
1342
|
+
first_line = "#{rel}: syntax error" if first_line.empty?
|
|
1343
|
+
puts " ✗ #{first_line}"
|
|
1344
|
+
end
|
|
1345
|
+
|
|
1346
|
+
if syntax_errors.positive?
|
|
1347
|
+
puts " ✗ lint failed -- #{syntax_errors} syntax error(s) in #{rb_files.length} file(s) [ruby -c]"
|
|
1348
|
+
exit 1
|
|
1349
|
+
end
|
|
1350
|
+
puts " ✓ lint clean -- #{rb_files.length} file(s) [ruby -c, syntax only]"
|
|
1351
|
+
exit 0
|
|
1352
|
+
end
|
|
1353
|
+
|
|
1354
|
+
# Resolve a runnable rubocop for the rich lint pass. Returns the argv PREFIX
|
|
1355
|
+
# to invoke it (`[<bundle>, "exec", "rubocop"]` when the project's Gemfile
|
|
1356
|
+
# bundles it — the version the project pins — or `[<rubocop-path>]` on PATH),
|
|
1357
|
+
# or nil to fall back to the `ruby -c` baseline. Mirrors the Python master's
|
|
1358
|
+
# `_resolve_ruff` (resolve the project's OWN linter). The bundler probe
|
|
1359
|
+
# (`bundle exec rubocop --version`) is a REAL resolve check: exit 0 only when
|
|
1360
|
+
# the gem is actually in the bundle. Bundler is preferred over a bare PATH
|
|
1361
|
+
# rubocop because inside a bundled project the pinned version is the correct
|
|
1362
|
+
# one (and a bare `rubocop` may trip Bundler's "not part of the bundle").
|
|
1363
|
+
def resolve_rubocop
|
|
1364
|
+
# Only the PROJECT's own bundled rubocop counts -- linting must be
|
|
1365
|
+
# reproducible from the project's pinned dev dependency, NOT a stray global
|
|
1366
|
+
# rubocop on PATH (which would also make the on-demand install
|
|
1367
|
+
# non-deterministic: a global tool would preempt it). When the project has
|
|
1368
|
+
# none, the caller installs it dev-only via `bundle add`.
|
|
1369
|
+
bundle = which_executable("bundle")
|
|
1370
|
+
if bundle && File.file?("Gemfile") &&
|
|
1371
|
+
system(bundle, "exec", "rubocop", "--version", out: File::NULL, err: File::NULL)
|
|
1372
|
+
return [bundle, "exec", "rubocop"]
|
|
1373
|
+
end
|
|
1374
|
+
nil
|
|
1375
|
+
end
|
|
1376
|
+
|
|
1209
1377
|
# Locate an executable on PATH — the stdlib-only equivalent of Python's
|
|
1210
1378
|
# shutil.which (no new gem). Honours PATHEXT on Windows.
|
|
1211
1379
|
def which_executable(cmd)
|
|
@@ -1494,21 +1662,19 @@ module Tina4
|
|
|
1494
1662
|
|
|
1495
1663
|
def build_model_resolution(name, flags)
|
|
1496
1664
|
raw = to_snake_case(name)
|
|
1665
|
+
# Honour --table-name (silent here; generate_model announces). The envelope
|
|
1666
|
+
# thus reports the SAME table_name/migration_path the generator writes.
|
|
1667
|
+
table = resolve_table(name, flags)
|
|
1497
1668
|
transformations = []
|
|
1498
|
-
table
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
}
|
|
1508
|
-
plural
|
|
1509
|
-
else
|
|
1510
|
-
raw
|
|
1511
|
-
end
|
|
1669
|
+
if SQL_RESERVED_TABLE_NAMES.include?(raw) && raw != table
|
|
1670
|
+
transformations << {
|
|
1671
|
+
"kind" => "reserved_word_pluralize",
|
|
1672
|
+
"from" => raw,
|
|
1673
|
+
"to" => table,
|
|
1674
|
+
"reason" => "SQL reserved word '#{raw}' would break CREATE TABLE",
|
|
1675
|
+
"override" => "--table-name <name> (table names interpolate unquoted; forcing a reserved name is yours to quote in raw SQL)"
|
|
1676
|
+
}
|
|
1677
|
+
end
|
|
1512
1678
|
# The migration filename embeds a timestamp; predict it deterministically
|
|
1513
1679
|
# so a `--dry-run` and the real run agree on the same second. Two
|
|
1514
1680
|
# generations within the same second collide anyway (existing behaviour).
|
|
@@ -1675,8 +1841,9 @@ module Tina4
|
|
|
1675
1841
|
pluralized = resolution["transformations"].find { |t| t["kind"] == "reserved_word_pluralize" }
|
|
1676
1842
|
if pluralized
|
|
1677
1843
|
lines << ""
|
|
1678
|
-
lines << " To
|
|
1679
|
-
lines << " tina4ruby generate #{target} #{name} --table
|
|
1844
|
+
lines << " To set the table name yourself:"
|
|
1845
|
+
lines << " tina4ruby generate #{target} #{name} --table-name <name>"
|
|
1846
|
+
lines << " Tina4 interpolates table names unquoted; if you force the reserved '#{pluralized['from']}', you own the quoting in raw SQL."
|
|
1680
1847
|
end
|
|
1681
1848
|
# ADR-0063 v1.1: surface `edit_hints[]` under "Edit these lines:" and
|
|
1682
1849
|
# `next[]` under "Next:" — both additive; missing / empty arrays elide
|
|
@@ -1725,7 +1892,9 @@ module Tina4
|
|
|
1725
1892
|
|
|
1726
1893
|
def generate_model(name, flags, emit_test: true)
|
|
1727
1894
|
fields = fields_or_default(flags["fields"])
|
|
1728
|
-
table
|
|
1895
|
+
# announce: this is where the table is born, so a reserved-word pluralise
|
|
1896
|
+
# (Order -> orders) or a forced reserved --table-name speaks up (#123).
|
|
1897
|
+
table = resolve_table(name, flags, announce: true)
|
|
1729
1898
|
snake = to_snake_case(name)
|
|
1730
1899
|
|
|
1731
1900
|
# Build field lines
|
|
@@ -1971,7 +2140,8 @@ module Tina4
|
|
|
1971
2140
|
# ── Generator: crud ──────────────────────────────────────────────────
|
|
1972
2141
|
|
|
1973
2142
|
def generate_crud(name, flags)
|
|
1974
|
-
|
|
2143
|
+
# Quiet here — the generate_model sub-call below announces once (#123).
|
|
2144
|
+
table = resolve_table(name, flags)
|
|
1975
2145
|
# Always derive the plural route from the CLASS NAME, not by appending
|
|
1976
2146
|
# "s" to the table — otherwise a reserved-word table (already plural,
|
|
1977
2147
|
# Order -> orders) becomes orderss, and a `y`-ending class (Category)
|
|
@@ -2300,7 +2470,8 @@ module Tina4
|
|
|
2300
2470
|
|
|
2301
2471
|
def generate_form(name, flags = {})
|
|
2302
2472
|
fields = fields_or_default(flags["fields"])
|
|
2303
|
-
table
|
|
2473
|
+
# Targets an existing table — honour --table-name but stay quiet (#123).
|
|
2474
|
+
table = resolve_table(name, flags)
|
|
2304
2475
|
route_name = to_route_name(name)
|
|
2305
2476
|
|
|
2306
2477
|
# Input type mapping
|
|
@@ -2383,7 +2554,8 @@ module Tina4
|
|
|
2383
2554
|
|
|
2384
2555
|
def generate_view(name, flags = {})
|
|
2385
2556
|
fields = fields_or_default(flags["fields"])
|
|
2386
|
-
table
|
|
2557
|
+
# Targets an existing table — honour --table-name but stay quiet (#123).
|
|
2558
|
+
table = resolve_table(name, flags)
|
|
2387
2559
|
route_name = to_route_name(name)
|
|
2388
2560
|
|
|
2389
2561
|
cols = fields.map { |f, _| f }
|
|
@@ -2816,7 +2988,8 @@ module Tina4
|
|
|
2816
2988
|
#
|
|
2817
2989
|
# tina4ruby generate seeder Product
|
|
2818
2990
|
def generate_seeder(name, flags = {})
|
|
2819
|
-
table
|
|
2991
|
+
# Targets an existing table — honour --table-name but stay quiet (#123).
|
|
2992
|
+
table = resolve_table(name, flags)
|
|
2820
2993
|
model_snake = to_snake_case(name)
|
|
2821
2994
|
dir = "seeds"
|
|
2822
2995
|
FileUtils.mkdir_p(dir)
|
data/lib/tina4/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tina4ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.13.
|
|
4
|
+
version: 3.13.129
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tina4 Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -276,20 +276,6 @@ dependencies:
|
|
|
276
276
|
- - "~>"
|
|
277
277
|
- !ruby/object:Gem::Version
|
|
278
278
|
version: '3.12'
|
|
279
|
-
- !ruby/object:Gem::Dependency
|
|
280
|
-
name: rubocop
|
|
281
|
-
requirement: !ruby/object:Gem::Requirement
|
|
282
|
-
requirements:
|
|
283
|
-
- - "~>"
|
|
284
|
-
- !ruby/object:Gem::Version
|
|
285
|
-
version: '1.50'
|
|
286
|
-
type: :development
|
|
287
|
-
prerelease: false
|
|
288
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
289
|
-
requirements:
|
|
290
|
-
- - "~>"
|
|
291
|
-
- !ruby/object:Gem::Version
|
|
292
|
-
version: '1.50'
|
|
293
279
|
- !ruby/object:Gem::Dependency
|
|
294
280
|
name: openapi3_parser
|
|
295
281
|
requirement: !ruby/object:Gem::Requirement
|