Class: ReactManifest::Generator

Inherits:
Object
  • Object
show all
Includes:
Logging, PathUtils
Defined in:
lib/react_manifest/generator.rb

Overview

Generates all ux_*.js Sprockets manifest files.

Instantiate with a Configuration and call #run!:

ReactManifest::Generator.new(ReactManifest.configuration).run!

Returns an array of result hashes:

[{path: "/abs/path/ux_shared.js", status: :written}, ...]

Possible status values: :written, :unchanged, :skipped_pinned, :dry_run.

Generates:

ux_shared.js   — requires all files from shared dirs (components/, hooks/, lib/, etc.)
ux_<ctrl>.js   — one per controller subdir, requires ux_shared + controller files

All generated files carry the AUTO-GENERATED header and are idempotent (skips write if content unchanged). Writes are atomic (temp-file + rename) to avoid partial reads from concurrent processes.

Never touches application.js, application_dev.js, or files in exclude_paths. rubocop:disable Metrics/ClassLength

Constant Summary collapse

HEADER =
<<~JS.freeze
  // AUTO-GENERATED — DO NOT EDIT
  // react-manifest-rails %<version>s
  // Run `rails react_manifest:generate` to regenerate.
JS

Constants included from PathUtils

PathUtils::STRIPPABLE_EXTENSIONS

Instance Method Summary collapse

Methods included from Logging

#log_debug, #log_info, #log_warn

Methods included from PathUtils

#strip_asset_extension

Constructor Details

#initialize(config = ReactManifest.configuration) ⇒ Generator

Returns a new instance of Generator.



37
38
39
40
# File 'lib/react_manifest/generator.rb', line 37

def initialize(config = ReactManifest.configuration)
  @config     = config
  @classifier = TreeClassifier.new(config)
end

Instance Method Details

#clean!Object

Remove all AUTO-GENERATED ux_*.js manifests. Silently skips files that disappear between the directory scan and the read (TOCTOU-safe). Returns { removed: N, skipped: N }.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/react_manifest/generator.rb', line 69

def clean!
  targets  = [@config.abs_manifest_dir, @config.abs_output_dir].uniq
  removed  = 0
  skipped  = 0

  targets.each do |dir|
    Dir.glob(File.join(dir, "ux_*.js")).each do |file|
      if auto_generated?(file)
        File.delete(file)
        removed += 1
      else
        skipped += 1
      end
    end
  end

  { removed: removed, skipped: skipped }
end

#run!Object

Run full generation. Returns array of status: hashes.

All manifest content is built first (no filesystem writes), then written in a second pass so that a failure midway does not leave some bundles written and others stale/missing.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/react_manifest/generator.rb', line 47

def run!
  classification = @classifier.classify
  controller_context = build_controller_context(classification.controller_dirs)

  # Phase 1: build all content in memory — no I/O.
  shared_manifest = build_shared(classification.shared_dirs)
  manifests = [shared_manifest] + classification.controller_dirs.map do |ctrl|
    build_controller(ctrl, controller_context)
  end

  migrate_legacy_manifests!

  # Phase 2: write — each write is atomic (tmp + rename).
  results = manifests.map { |m| write_manifest(m[:filename], m[:content]) }

  print_summary(results) if @config.verbose?
  results
end