js-routes 2.2.1 → 2.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54158654106dece477c1fdf36afa52b504a43b8210c4c8d30f98d41ccd0ef600
4
- data.tar.gz: a67b36754269392839bb6d2e86a20899ec2575437ac9667f10cdd9feb7306185
3
+ metadata.gz: 66ff94f5c78d966f76e2a9f47d1c838c757c3e243c37f03599b24c286b15b9b7
4
+ data.tar.gz: c5803e4a35b99923769970149f07a6893a84c6343f10f76c8a89645974dce959
5
5
  SHA512:
6
- metadata.gz: 582b6a39a062f6fcfd7b2cb4a57b4fd4573e343f93d5751ef764b7e3617cb7243801caf61ee971224a2c1a41e43a2f51221e5d3a40c12d5db21af98f47467044
7
- data.tar.gz: f54b26ed68ed8ef2a6b4ad5ebf2e0322bfbec7385756a8578b5c11c01eca646d42baa5634d16cef6d16520e3eed4d1b1a37260e4ade943ee568b6b4755153cea
6
+ metadata.gz: a34c75f950a02a6634687889e4072f7d88f37520a6dc2ba5bfd2ccbbb71962159a70170bf7ac55b22db45de2727f7c573dfce8c80debc33f34abbd9cb1132c1f
7
+ data.tar.gz: 779b340c9dac721c8b427a16011ed961a05dde4d15594838649fb0860bac42e60344a682718a0b94f35f785350126ca59c7f739dac43cb47e0a7b84e45fa468a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  ## master
2
2
 
3
+ ## v2.2.5
4
+
5
+ * Fix middleware generator [#300](https://github.com/railsware/js-routes/issues/300)
6
+ * Support `params` special parameter
7
+
8
+ ## v2.2.4
9
+
10
+ * Fix rails engine loading if sprockets is not in Gemfile. Fixes [#294](https://github.com/railsware/js-routes/issues/294)
11
+
12
+ ## v2.2.3
13
+
14
+ * Fixed NIL module type namespace defintion [#297](https://github.com/railsware/js-routes/issues/297).
15
+ * The patch may cause a problem with nested `namespace` option
16
+ * Ex. Value like `MyProject.Routes` requires to define `window.MyProject` before importing the routes file
17
+
18
+ ## v2.2.2.
19
+
20
+ * Fix custom file path [#295](https://github.com/railsware/js-routes/issues/295)
21
+
3
22
  ## v2.2.1
4
23
 
5
24
  * Improve generator to update route files on `assets:precompile` and add them to `.gitignore by default` [#288](https://github.com/railsware/js-routes/issues/288#issuecomment-1012182815)
data/Readme.md CHANGED
@@ -20,6 +20,7 @@ There are several possible ways to setup JsRoutes:
20
20
 
21
21
  * [Quick and easy](#quick-start)
22
22
  * Uses Rack Middleware to automatically update routes locally
23
+ * Automatically generates routes files on `assets:precompile` in production
23
24
  * Works great for a simple Rails application
24
25
  * [Webpacker ERB Loader](#webpacker)
25
26
  * Requires ESM module system (the default)
@@ -61,7 +62,7 @@ import * as Routes from '../routes';
61
62
  alert(Routes.post_path(1))
62
63
  ```
63
64
 
64
- Upgrade `rake assets:precompile` to update js-routes files:
65
+ Upgrade `rake assets:precompile` to update js-routes files in `Rakefile`:
65
66
 
66
67
  ``` ruby
67
68
  namespace :assets do
@@ -0,0 +1,111 @@
1
+ require "pathname"
2
+
3
+ module JsRoutes
4
+ class Configuration
5
+ DEFAULTS = {
6
+ namespace: nil,
7
+ exclude: [],
8
+ include: //,
9
+ file: nil,
10
+ prefix: -> { Rails.application.config.relative_url_root || "" },
11
+ url_links: false,
12
+ camel_case: false,
13
+ default_url_options: {},
14
+ compact: false,
15
+ serializer: nil,
16
+ special_options_key: "_options",
17
+ application: -> { Rails.application },
18
+ module_type: 'ESM',
19
+ documentation: true,
20
+ } #:nodoc:
21
+
22
+ attr_accessor(*DEFAULTS.keys)
23
+
24
+ def initialize(attributes = nil)
25
+ assign(DEFAULTS)
26
+ return unless attributes
27
+ assign(attributes)
28
+ end
29
+
30
+ def assign(attributes = nil, &block)
31
+ if !attributes && !block
32
+ raise "Provide attributes or block"
33
+ end
34
+ tap(&block) if block
35
+ if attributes
36
+ attributes.each do |attribute, value|
37
+ value = value.call if value.is_a?(Proc)
38
+ send(:"#{attribute}=", value)
39
+ end
40
+ end
41
+ normalize_and_verify
42
+ self
43
+ end
44
+
45
+ def [](attribute)
46
+ send(attribute)
47
+ end
48
+
49
+ def merge(attributes)
50
+ clone.assign(attributes)
51
+ end
52
+
53
+ def to_hash
54
+ Hash[*members.zip(values).flatten(1)].symbolize_keys
55
+ end
56
+
57
+ def esm?
58
+ module_type === 'ESM'
59
+ end
60
+
61
+ def dts?
62
+ self.module_type === 'DTS'
63
+ end
64
+
65
+ def modern?
66
+ esm? || dts?
67
+ end
68
+
69
+ def require_esm
70
+ raise "ESM module type is required" unless modern?
71
+ end
72
+
73
+ def source_file
74
+ File.dirname(__FILE__) + "/../" + default_file_name
75
+ end
76
+
77
+ def output_file
78
+ webpacker_dir = pathname('app', 'javascript')
79
+ sprockets_dir = pathname('app','assets','javascripts')
80
+ file_name = file || default_file_name
81
+ sprockets_file = sprockets_dir.join(file_name)
82
+ webpacker_file = webpacker_dir.join(file_name)
83
+ !Dir.exist?(webpacker_dir) && defined?(::Sprockets) ? sprockets_file : webpacker_file
84
+ end
85
+
86
+ protected
87
+
88
+ def normalize_and_verify
89
+ normalize
90
+ verify
91
+ end
92
+
93
+ def pathname(*parts)
94
+ Pathname.new(File.join(*parts))
95
+ end
96
+
97
+ def default_file_name
98
+ dts? ? "routes.d.ts" : "routes.js"
99
+ end
100
+
101
+ def normalize
102
+ self.module_type = module_type&.upcase || 'NIL'
103
+ end
104
+
105
+ def verify
106
+ if module_type != 'NIL' && namespace
107
+ raise "JsRoutes namespace option can only be used if module_type is nil"
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,4 +1,4 @@
1
- class JsRoutes
1
+ module JsRoutes
2
2
  class SprocketsExtension
3
3
  def initialize(filename, &block)
4
4
  @filename = filename
@@ -29,32 +29,34 @@ end
29
29
 
30
30
 
31
31
  class Engine < ::Rails::Engine
32
- require 'sprockets/version'
33
- v2 = Gem::Dependency.new('', ' ~> 2')
34
- vgte3 = Gem::Dependency.new('', ' >= 3')
35
- sprockets_version = Gem::Version.new(::Sprockets::VERSION).release
36
- initializer_args = case sprockets_version
37
- when -> (v) { v2.match?('', v) }
38
- { after: "sprockets.environment" }
39
- when -> (v) { vgte3.match?('', v) }
40
- { after: :engines_blank_point, before: :finisher_hook }
41
- else
42
- raise StandardError, "Sprockets version #{sprockets_version} is not supported"
43
- end
44
-
45
- initializer 'js-routes.dependent_on_routes', initializer_args do
46
- case sprockets_version
47
- when -> (v) { v2.match?('', v) },
48
- -> (v) { vgte3.match?('', v) }
49
-
50
- Rails.application.config.assets.configure do |config|
51
- config.register_preprocessor(
52
- "application/javascript",
53
- SprocketsExtension,
54
- )
32
+ if defined?(::Sprockets::Railtie)
33
+ require 'sprockets/version'
34
+ v2 = Gem::Dependency.new('', ' ~> 2')
35
+ vgte3 = Gem::Dependency.new('', ' >= 3')
36
+ sprockets_version = Gem::Version.new(::Sprockets::VERSION).release
37
+ initializer_args = case sprockets_version
38
+ when -> (v) { v2.match?('', v) }
39
+ { after: "sprockets.environment" }
40
+ when -> (v) { vgte3.match?('', v) }
41
+ { after: :engines_blank_point, before: :finisher_hook }
42
+ else
43
+ raise StandardError, "Sprockets version #{sprockets_version} is not supported"
44
+ end
45
+
46
+ initializer 'js-routes.dependent_on_routes', initializer_args do
47
+ case sprockets_version
48
+ when -> (v) { v2.match?('', v) },
49
+ -> (v) { vgte3.match?('', v) }
50
+
51
+ Rails.application.config.assets.configure do |config|
52
+ config.register_preprocessor(
53
+ "application/javascript",
54
+ SprocketsExtension,
55
+ )
56
+ end
57
+ else
58
+ raise StandardError, "Sprockets version #{sprockets_version} is not supported"
55
59
  end
56
- else
57
- raise StandardError, "Sprockets version #{sprockets_version} is not supported"
58
60
  end
59
61
  end
60
62
  end
@@ -52,7 +52,7 @@ end
52
52
  {},
53
53
  {module_type: 'DTS'}
54
54
  ].map do |config|
55
- File.join('/', JsRoutes.new(config).configuration.output_file) + "\n"
55
+ File.join('/', JsRoutes::Configuration.new(config).output_file) + "\n"
56
56
  end.join
57
57
  end
58
58
  end
@@ -0,0 +1,173 @@
1
+ require "js_routes/configuration"
2
+ require "js_routes/route"
3
+
4
+ module JsRoutes
5
+ class Instance # :nodoc:
6
+
7
+ attr_reader :configuration
8
+ #
9
+ # Implementation
10
+ #
11
+
12
+ def initialize(options = {})
13
+ @configuration = JsRoutes.configuration.merge(options)
14
+ end
15
+
16
+ def generate
17
+ # Ensure routes are loaded. If they're not, load them.
18
+ if named_routes.empty? && application.respond_to?(:reload_routes!)
19
+ application.reload_routes!
20
+ end
21
+ content = File.read(@configuration.source_file)
22
+
23
+ if !@configuration.dts?
24
+ content = js_variables.inject(content) do |js, (key, value)|
25
+ js.gsub!("RubyVariables.#{key}", value.to_s) ||
26
+ raise("Missing key #{key} in JS template")
27
+ end
28
+ end
29
+ content + routes_export + prevent_types_export
30
+ end
31
+
32
+ def generate!
33
+ # Some libraries like Devise did not load their routes yet
34
+ # so we will wait until initialization process finishes
35
+ # https://github.com/railsware/js-routes/issues/7
36
+ Rails.configuration.after_initialize do
37
+ file_path = Rails.root.join(@configuration.output_file)
38
+ source_code = generate
39
+
40
+ # We don't need to rewrite file if it already exist and have same content.
41
+ # It helps asset pipeline or webpack understand that file wasn't changed.
42
+ next if File.exist?(file_path) && File.read(file_path) == source_code
43
+
44
+ File.open(file_path, 'w') do |f|
45
+ f.write source_code
46
+ end
47
+ end
48
+ end
49
+
50
+ protected
51
+
52
+ def js_variables
53
+ {
54
+ 'GEM_VERSION' => JsRoutes::VERSION,
55
+ 'ROUTES_OBJECT' => routes_object,
56
+ 'RAILS_VERSION' => ActionPack.version,
57
+ 'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
58
+
59
+ 'APP_CLASS' => application.class.to_s,
60
+ 'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
61
+ 'PREFIX' => json(@configuration.prefix),
62
+ 'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
63
+ 'SERIALIZER' => @configuration.serializer || json(nil),
64
+ 'MODULE_TYPE' => json(@configuration.module_type),
65
+ 'WRAPPER' => wrapper_variable,
66
+ }
67
+ end
68
+
69
+ def wrapper_variable
70
+ case @configuration.module_type
71
+ when 'ESM'
72
+ 'const __jsr = '
73
+ when 'NIL'
74
+ namespace = @configuration.namespace
75
+ if namespace
76
+ if namespace.include?('.')
77
+ "#{namespace} = "
78
+ else
79
+ "(typeof window !== 'undefined' ? window : this).#{namespace} = "
80
+ end
81
+ else
82
+ ''
83
+ end
84
+ else
85
+ ''
86
+ end
87
+ end
88
+
89
+ def application
90
+ @configuration.application
91
+ end
92
+
93
+ def json(string)
94
+ JsRoutes.json(string)
95
+ end
96
+
97
+ def named_routes
98
+ application.routes.named_routes.to_a
99
+ end
100
+
101
+ def routes_object
102
+ return json({}) if @configuration.modern?
103
+ properties = routes_list.map do |comment, name, body|
104
+ "#{comment}#{name}: #{body}".indent(2)
105
+ end
106
+ "{\n" + properties.join(",\n\n") + "}\n"
107
+ end
108
+
109
+ def static_exports
110
+ [:configure, :config, :serialize].map do |name|
111
+ [
112
+ "", name,
113
+ @configuration.dts? ?
114
+ "RouterExposedMethods['#{name}']" :
115
+ "__jsr.#{name}"
116
+ ]
117
+ end
118
+ end
119
+
120
+ def routes_export
121
+ return "" unless @configuration.modern?
122
+ [*static_exports, *routes_list].map do |comment, name, body|
123
+ "#{comment}export const #{name}#{export_separator}#{body};\n\n"
124
+ end.join
125
+ end
126
+
127
+ def prevent_types_export
128
+ return "" unless @configuration.dts?
129
+ <<-JS
130
+ // By some reason this line prevents all types in a file
131
+ // from being automatically exported
132
+ export {};
133
+ JS
134
+ end
135
+
136
+ def export_separator
137
+ @configuration.dts? ? ': ' : ' = '
138
+ end
139
+
140
+ def routes_list
141
+ named_routes.sort_by(&:first).flat_map do |_, route|
142
+ route_helpers_if_match(route) + mounted_app_routes(route)
143
+ end
144
+ end
145
+
146
+ def mounted_app_routes(route)
147
+ rails_engine_app = app_from_route(route)
148
+ if rails_engine_app.respond_to?(:superclass) &&
149
+ rails_engine_app.superclass == Rails::Engine && !route.path.anchored
150
+ rails_engine_app.routes.named_routes.flat_map do |_, engine_route|
151
+ route_helpers_if_match(engine_route, route)
152
+ end
153
+ else
154
+ []
155
+ end
156
+ end
157
+
158
+ def app_from_route(route)
159
+ app = route.app
160
+ # rails engine in Rails 4.2 use additional
161
+ # ActionDispatch::Routing::Mapper::Constraints, which contain app
162
+ if app.respond_to?(:app) && app.respond_to?(:constraints)
163
+ app.app
164
+ else
165
+ app
166
+ end
167
+ end
168
+
169
+ def route_helpers_if_match(route, parent_route = nil)
170
+ Route.new(@configuration, route, parent_route).helpers
171
+ end
172
+ end
173
+ end
@@ -1,4 +1,4 @@
1
- class JsRoutes
1
+ module JsRoutes
2
2
  # A Rack middleware that automatically updates routes file
3
3
  # whenever routes.rb is modified
4
4
  #
@@ -21,12 +21,16 @@ class JsRoutes
21
21
  def update_js_routes
22
22
  new_mtime = routes_mtime
23
23
  unless new_mtime == @mtime
24
- JsRoutes.generate!
25
- JsRoutes.definitions!
24
+ regenerate
26
25
  @mtime = new_mtime
27
26
  end
28
27
  end
29
28
 
29
+ def regenerate
30
+ JsRoutes.generate!
31
+ JsRoutes.definitions!
32
+ end
33
+
30
34
  def routes_mtime
31
35
  File.mtime(@routes_file)
32
36
  rescue Errno::ENOENT
@@ -1,4 +1,4 @@
1
- class JsRoutes
1
+ module JsRoutes
2
2
  class Route #:nodoc:
3
3
  FILTERED_DEFAULT_PARTS = [:controller, :action]
4
4
  URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain]
@@ -1,3 +1,3 @@
1
- class JsRoutes
2
- VERSION = "2.2.1"
1
+ module JsRoutes
2
+ VERSION = "2.2.4"
3
3
  end