js-routes 1.4.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.eslintrc.js +15 -0
  3. data/.gitignore +5 -0
  4. data/.nvmrc +1 -0
  5. data/.travis.yml +37 -30
  6. data/Appraisals +16 -13
  7. data/CHANGELOG.md +95 -0
  8. data/Rakefile +6 -2
  9. data/Readme.md +220 -88
  10. data/VERSION_2_UPGRADE.md +66 -0
  11. data/app/assets/javascripts/js-routes.js.erb +1 -1
  12. data/gemfiles/{rails40.gemfile → rails40_sprockets_2.gemfile} +1 -1
  13. data/gemfiles/{rails40_sprockets3.gemfile → rails40_sprockets_3.gemfile} +0 -0
  14. data/gemfiles/{rails41.gemfile → rails41_sprockets_2.gemfile} +1 -1
  15. data/gemfiles/{rails41_sprockets3.gemfile → rails41_sprockets_3.gemfile} +0 -0
  16. data/gemfiles/{rails32.gemfile → rails42_sprockets_2.gemfile} +2 -2
  17. data/gemfiles/{rails42_sprockets3.gemfile → rails42_sprockets_3.gemfile} +1 -1
  18. data/gemfiles/{rails50_sprockets3.gemfile → rails50_sprockets_3.gemfile} +1 -1
  19. data/gemfiles/rails51_sprockets_3.gemfile +8 -0
  20. data/gemfiles/rails52_sprockets_3.gemfile +8 -0
  21. data/js-routes.gemspec +9 -6
  22. data/lib/js_routes/engine.rb +6 -18
  23. data/lib/js_routes/version.rb +1 -1
  24. data/lib/js_routes.rb +329 -171
  25. data/lib/routes.d.ts +79 -0
  26. data/lib/routes.js +499 -485
  27. data/lib/routes.ts +732 -0
  28. data/lib/tasks/js_routes.rake +8 -2
  29. data/package.json +37 -0
  30. data/spec/dummy/app/assets/config/manifest.js +2 -0
  31. data/spec/js_routes/default_serializer_spec.rb +19 -3
  32. data/spec/js_routes/{amd_compatibility_spec.rb → module_types/amd_spec.rb} +1 -9
  33. data/spec/js_routes/module_types/cjs_spec.rb +15 -0
  34. data/spec/js_routes/module_types/dts/routes.spec.d.ts +114 -0
  35. data/spec/js_routes/module_types/dts/test.spec.ts +56 -0
  36. data/spec/js_routes/module_types/dts_spec.rb +111 -0
  37. data/spec/js_routes/module_types/esm_spec.rb +45 -0
  38. data/spec/js_routes/{generated_javascript_spec.rb → module_types/umd_spec.rb} +33 -27
  39. data/spec/js_routes/options_spec.rb +92 -50
  40. data/spec/js_routes/rails_routes_compatibility_spec.rb +107 -45
  41. data/spec/js_routes/zzz_last_post_rails_init_spec.rb +19 -8
  42. data/spec/spec_helper.rb +45 -42
  43. data/spec/support/routes.rb +19 -14
  44. data/spec/tsconfig.json +4 -0
  45. data/tsconfig.json +28 -0
  46. data/yarn.lock +2145 -0
  47. metadata +47 -34
  48. data/gemfiles/rails42.gemfile +0 -8
  49. data/gemfiles/rails50.gemfile +0 -8
  50. data/lib/routes.js.coffee +0 -386
data/lib/js_routes.rb CHANGED
@@ -1,46 +1,32 @@
1
1
  require 'uri'
2
- require 'js_routes/engine' if defined?(Rails)
2
+ if defined?(::Rails) && defined?(::Sprockets::Railtie)
3
+ require 'js_routes/engine'
4
+ end
3
5
  require 'js_routes/version'
6
+ require 'active_support/core_ext/string/indent'
4
7
 
5
8
  class JsRoutes
6
9
 
7
- #
8
- # OPTIONS
9
- #
10
+ class Configuration
11
+ DEFAULTS = {
12
+ namespace: nil,
13
+ exclude: [],
14
+ include: //,
15
+ file: nil,
16
+ prefix: -> { Rails.application.config.relative_url_root || "" },
17
+ url_links: false,
18
+ camel_case: false,
19
+ default_url_options: {},
20
+ compact: false,
21
+ serializer: nil,
22
+ special_options_key: "_options",
23
+ application: -> { Rails.application },
24
+ module_type: 'ESM',
25
+ documentation: true,
26
+ } #:nodoc:
27
+
28
+ attr_accessor(*DEFAULTS.keys)
10
29
 
11
- DEFAULT_PATH = File.join('app','assets','javascripts','routes.js')
12
-
13
- DEFAULTS = {
14
- namespace: "Routes",
15
- exclude: [],
16
- include: //,
17
- file: DEFAULT_PATH,
18
- prefix: -> { Rails.application.config.relative_url_root || "" },
19
- url_links: false,
20
- camel_case: false,
21
- default_url_options: {},
22
- compact: false,
23
- serializer: nil,
24
- special_options_key: "_options",
25
- application: -> { Rails.application }
26
- }
27
-
28
- NODE_TYPES = {
29
- GROUP: 1,
30
- CAT: 2,
31
- SYMBOL: 3,
32
- OR: 4,
33
- STAR: 5,
34
- LITERAL: 6,
35
- SLASH: 7,
36
- DOT: 8
37
- }
38
-
39
- LAST_OPTIONS_KEY = "options".freeze
40
- FILTERED_DEFAULT_PARTS = [:controller, :action, :subdomain]
41
- URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain]
42
-
43
- class Configuration < Struct.new(*DEFAULTS.keys)
44
30
  def initialize(attributes = nil)
45
31
  assign(DEFAULTS)
46
32
  return unless attributes
@@ -52,6 +38,7 @@ class JsRoutes
52
38
  value = value.call if value.is_a?(Proc)
53
39
  send(:"#{attribute}=", value)
54
40
  end
41
+ normalize_and_verify
55
42
  self
56
43
  end
57
44
 
@@ -66,6 +53,52 @@ class JsRoutes
66
53
  def to_hash
67
54
  Hash[*members.zip(values).flatten(1)].symbolize_keys
68
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 source_file
70
+ File.dirname(__FILE__) + "/" + default_file_name
71
+ end
72
+
73
+ def output_file
74
+ webpacker_dir = Rails.root.join('app', 'javascript')
75
+ sprockets_dir = Rails.root.join('app','assets','javascripts')
76
+ file_name = file || default_file_name
77
+ sprockets_file = sprockets_dir.join(file_name)
78
+ webpacker_file = webpacker_dir.join(file_name)
79
+ !Dir.exist?(webpacker_dir) && defined?(::Sprockets) ? sprockets_file : webpacker_file
80
+ end
81
+
82
+ def normalize_and_verify
83
+ normalize
84
+ verify
85
+ end
86
+
87
+ protected
88
+
89
+ def default_file_name
90
+ dts? ? "routes.d.ts" : "routes.js"
91
+ end
92
+
93
+ def normalize
94
+ self.module_type = module_type&.upcase || 'NIL'
95
+ end
96
+
97
+ def verify
98
+ if module_type != 'NIL' && namespace
99
+ raise "JsRoutes namespace option can only be used if module_type is nil"
100
+ end
101
+ end
69
102
  end
70
103
 
71
104
  #
@@ -75,11 +108,7 @@ class JsRoutes
75
108
  class << self
76
109
  def setup(&block)
77
110
  configuration.tap(&block) if block
78
- end
79
-
80
- def options
81
- ActiveSupport::Deprecation.warn('JsRoutes.options method is deprecated use JsRoutes.configuration instead')
82
- configuration
111
+ configuration.normalize_and_verify
83
112
  end
84
113
 
85
114
  def configuration
@@ -90,22 +119,13 @@ class JsRoutes
90
119
  new(opts).generate
91
120
  end
92
121
 
93
- def generate!(file_name=nil, opts = {})
94
- if file_name.is_a?(Hash)
95
- opts = file_name
96
- file_name = opts[:file]
97
- end
98
- new(opts).generate!(file_name)
122
+ def generate!(file_name=nil, **opts)
123
+ new(file: file_name, **opts).generate!
99
124
  end
100
125
 
101
- # Under rails 3.1.1 and higher, perform a check to ensure that the
102
- # full environment will be available during asset compilation.
103
- # This is required to ensure routes are loaded.
104
- def assert_usable_configuration!
105
- if 3 == Rails::VERSION::MAJOR && !Rails.application.config.assets.initialize_on_precompile
106
- raise("Cannot precompile js-routes unless environment is initialized. Please set config.assets.initialize_on_precompile to true.")
107
- end
108
- true
126
+ def definitions!(file_name = nil, **opts)
127
+ file_name ||= configuration.file&.sub!(%r{\.(j|t)s\Z}, ".d.ts")
128
+ new(file: file_name, module_type: 'DTS', **opts).generate!
109
129
  end
110
130
 
111
131
  def json(string)
@@ -126,66 +146,127 @@ class JsRoutes
126
146
  if named_routes.to_a.empty? && application.respond_to?(:reload_routes!)
127
147
  application.reload_routes!
128
148
  end
149
+ content = File.read(@configuration.source_file)
129
150
 
130
- {
131
- "GEM_VERSION" => JsRoutes::VERSION,
132
- "ROUTES" => js_routes,
133
- "DEPRECATED_BEHAVIOR" => Rails.version < "4",
134
- "NODE_TYPES" => json(NODE_TYPES),
135
-
136
- "APP_CLASS" => application.class.to_s,
137
- "NAMESPACE" => json(@configuration.namespace),
138
- "DEFAULT_URL_OPTIONS" => json(@configuration.default_url_options),
139
- "PREFIX" => json(@configuration.prefix),
140
- "SPECIAL_OPTIONS_KEY" => json(@configuration.special_options_key),
141
- "SERIALIZER" => @configuration.serializer || json(nil),
142
- }.inject(File.read(File.dirname(__FILE__) + "/routes.js")) do |js, (key, value)|
143
- js.gsub!(key, value.to_s)
151
+ if !@configuration.dts?
152
+ content = js_variables.inject(content) do |js, (key, value)|
153
+ js.gsub!("RubyVariables.#{key}", value.to_s) ||
154
+ raise("Missing key #{key} in JS template")
155
+ end
144
156
  end
157
+ content + routes_export + prevent_types_export
145
158
  end
146
159
 
147
- def generate!(file_name = nil)
148
- # Some libraries like Devise do not yet loaded their routes so we will wait
149
- # until initialization process finish
160
+ def generate!
161
+ # Some libraries like Devise did not load their routes yet
162
+ # so we will wait until initialization process finishes
150
163
  # https://github.com/railsware/js-routes/issues/7
151
164
  Rails.configuration.after_initialize do
152
- file_name ||= self.class.configuration['file']
153
- File.open(Rails.root.join(file_name), 'w') do |f|
154
- f.write generate
165
+ file_path = Rails.root.join(@configuration.output_file)
166
+ source_code = generate
167
+
168
+ # We don't need to rewrite file if it already exist and have same content.
169
+ # It helps asset pipeline or webpack understand that file wasn't changed.
170
+ next if File.exist?(file_path) && File.read(file_path) == source_code
171
+
172
+ File.open(file_path, 'w') do |f|
173
+ f.write source_code
155
174
  end
156
175
  end
157
176
  end
158
177
 
159
178
  protected
160
179
 
180
+ def js_variables
181
+ {
182
+ 'GEM_VERSION' => JsRoutes::VERSION,
183
+ 'ROUTES_OBJECT' => routes_object,
184
+ 'RAILS_VERSION' => ActionPack.version,
185
+ 'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
186
+
187
+ 'APP_CLASS' => application.class.to_s,
188
+ 'NAMESPACE' => json(@configuration.namespace),
189
+ 'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
190
+ 'PREFIX' => json(@configuration.prefix),
191
+ 'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
192
+ 'SERIALIZER' => @configuration.serializer || json(nil),
193
+ 'MODULE_TYPE' => json(@configuration.module_type),
194
+ 'WRAPPER' => @configuration.esm? ? 'const __jsr = ' : '',
195
+ }
196
+ end
197
+
161
198
  def application
162
199
  @configuration.application
163
200
  end
164
201
 
202
+ def json(string)
203
+ self.class.json(string)
204
+ end
205
+
165
206
  def named_routes
166
207
  application.routes.named_routes.to_a
167
208
  end
168
209
 
169
- def js_routes
170
- js_routes = named_routes.sort_by(&:first).flat_map do |_, route|
171
- [build_route_if_match(route)] + mounted_app_routes(route)
172
- end.compact
173
- "{\n" + js_routes.join(",\n") + "}\n"
210
+ def routes_object
211
+ return json({}) if @configuration.modern?
212
+ properties = routes_list.map do |comment, name, body|
213
+ "#{comment}#{name}: #{body}".indent(2)
214
+ end
215
+ "{\n" + properties.join(",\n\n") + "}\n"
216
+ end
217
+
218
+ def static_exports
219
+ [:configure, :config, :serialize].map do |name|
220
+ [
221
+ "", name,
222
+ @configuration.dts? ?
223
+ "RouterExposedMethods['#{name}']" :
224
+ "__jsr.#{name}"
225
+ ]
226
+ end
227
+ end
228
+
229
+ def routes_export
230
+ return "" unless @configuration.modern?
231
+ [*static_exports, *routes_list].map do |comment, name, body|
232
+ "#{comment}export const #{name}#{export_separator}#{body};\n\n"
233
+ end.join
234
+ end
235
+
236
+ def prevent_types_export
237
+ return "" unless @configuration.dts?
238
+ <<-JS
239
+ // By some reason this line prevents all types in a file
240
+ // from being automatically exported
241
+ export {};
242
+ JS
243
+ end
244
+
245
+ def export_separator
246
+ @configuration.dts? ? ': ' : ' = '
247
+ end
248
+
249
+ def routes_list
250
+ named_routes.sort_by(&:first).flat_map do |_, route|
251
+ route_helpers_if_match(route) + mounted_app_routes(route)
252
+ end
174
253
  end
175
254
 
176
255
  def mounted_app_routes(route)
177
- rails_engine_app = get_app_from_route(route)
178
- if rails_engine_app.respond_to?(:superclass) && rails_engine_app.superclass == Rails::Engine && !route.path.anchored
179
- rails_engine_app.routes.named_routes.map do |_, engine_route|
180
- build_route_if_match(engine_route, route)
256
+ rails_engine_app = app_from_route(route)
257
+ if rails_engine_app.respond_to?(:superclass) &&
258
+ rails_engine_app.superclass == Rails::Engine && !route.path.anchored
259
+ rails_engine_app.routes.named_routes.flat_map do |_, engine_route|
260
+ route_helpers_if_match(engine_route, route)
181
261
  end
182
262
  else
183
263
  []
184
264
  end
185
265
  end
186
266
 
187
- def get_app_from_route(route)
188
- # rails engine in Rails 4.2 use additional ActionDispatch::Routing::Mapper::Constraints, which contain app
267
+ def app_from_route(route)
268
+ # rails engine in Rails 4.2 use additional
269
+ # ActionDispatch::Routing::Mapper::Constraints, which contain app
189
270
  if route.app.respond_to?(:app) && route.app.respond_to?(:constraints)
190
271
  route.app.app
191
272
  else
@@ -193,101 +274,178 @@ class JsRoutes
193
274
  end
194
275
  end
195
276
 
196
- def build_route_if_match(route, parent_route=nil)
197
- if any_match?(route, parent_route, @configuration[:exclude]) || !any_match?(route, parent_route, @configuration[:include])
198
- nil
199
- else
200
- build_js(route, parent_route)
201
- end
277
+ def route_helpers_if_match(route, parent_route = nil)
278
+ JsRoute.new(@configuration, route, parent_route).helpers
202
279
  end
203
280
 
204
- def any_match?(route, parent_route, matchers)
205
- full_route = [parent_route.try(:name), route.name].compact.join('_')
281
+ class JsRoute #:nodoc:
282
+ FILTERED_DEFAULT_PARTS = [:controller, :action]
283
+ URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain]
284
+ NODE_TYPES = {
285
+ GROUP: 1,
286
+ CAT: 2,
287
+ SYMBOL: 3,
288
+ OR: 4,
289
+ STAR: 5,
290
+ LITERAL: 6,
291
+ SLASH: 7,
292
+ DOT: 8
293
+ }
294
+
295
+ attr_reader :configuration, :route, :parent_route
296
+
297
+ def initialize(configuration, route, parent_route = nil)
298
+ @configuration = configuration
299
+ @route = route
300
+ @parent_route = parent_route
301
+ end
206
302
 
207
- matchers = Array(matchers)
208
- matchers.any? {|regex| full_route =~ regex}
209
- end
303
+ def helpers
304
+ helper_types.map do |absolute|
305
+ [ documentation, helper_name(absolute), body(absolute) ]
306
+ end
307
+ end
210
308
 
211
- def build_js(route, parent_route)
212
- name = [parent_route.try(:name), route.name].compact
213
- route_name = generate_route_name(name, (:path unless @configuration[:compact]))
214
- parent_spec = parent_route.try(:path).try(:spec)
215
- route_arguments = route_js_arguments(route, parent_spec)
216
- url_link = generate_url_link(name, route_name, route_arguments, route)
217
- _ = <<-JS.strip!
218
- // #{name.join('.')} => #{parent_spec}#{route.path.spec}
219
- // function(#{build_params(route.required_parts)})
220
- #{route_name}: Utils.route(#{route_arguments})#{",\n" + url_link if url_link.length > 0}
221
- JS
222
- end
309
+ def helper_types
310
+ return [] unless match_configuration?
311
+ @configuration[:url_links] ? [true, false] : [false]
312
+ end
223
313
 
224
- def route_js_arguments(route, parent_spec)
225
- required_parts = route.required_parts
226
- parts_table = route.parts.each_with_object({}) do |part, hash|
227
- hash[part] = required_parts.include?(part)
228
- end
229
- default_options = route.defaults.select do |part, _|
230
- FILTERED_DEFAULT_PARTS.exclude?(part) && URL_OPTIONS.include?(part) || parts_table[part]
231
- end
232
- [
233
- # JS objects don't preserve the order of properties which is crucial,
234
- # so array is a better choice.
235
- parts_table.to_a,
236
- default_options,
237
- serialize(route.path.spec, parent_spec)
238
- ].map do |argument|
239
- json(argument)
240
- end.join(", ")
241
- end
314
+ def body(absolute)
315
+ @configuration.dts? ?
316
+ definition_body : "__jsr.r(#{arguments(absolute).map{|a| json(a)}.join(', ')})"
317
+ end
242
318
 
243
- def generate_url_link(name, route_name, route_arguments, route)
244
- return "" unless @configuration[:url_links]
245
- <<-JS.strip!
246
- #{generate_route_name(name, :url)}: Utils.route(#{route_arguments}, true)
247
- JS
248
- end
319
+ def definition_body
320
+ args = required_parts.map{|p| "#{apply_case(p)}: RequiredRouteParameter"}
321
+ args << "options?: #{optional_parts_type} & RouteOptions"
322
+ "((\n#{args.join(",\n").indent(2)}\n) => string) & RouteHelperExtras"
323
+ end
249
324
 
250
- def generate_route_name(name, suffix)
251
- route_name = name.join('_')
252
- route_name << "_#{ suffix }" if suffix
253
- @configuration[:camel_case] ? route_name.camelize(:lower) : route_name
254
- end
325
+ def optional_parts_type
326
+ @optional_parts_type ||=
327
+ "{" + optional_parts.map {|p| "#{p}?: OptionalRouteParameter"}.join(', ') + "}"
328
+ end
255
329
 
256
- def json(string)
257
- self.class.json(string)
258
- end
330
+ protected
259
331
 
260
- def build_params(required_parts)
261
- params = required_parts + [LAST_OPTIONS_KEY]
262
- params.join(", ")
263
- end
332
+ def arguments(absolute)
333
+ absolute ? [*base_arguments, true] : base_arguments
334
+ end
264
335
 
265
- # This function serializes Journey route into JSON structure
266
- # We do not use Hash for human readable serialization
267
- # And preffer Array serialization because it is shorter.
268
- # Routes.js file will be smaller.
269
- def serialize(spec, parent_spec=nil)
270
- return nil unless spec
271
- return spec.tr(':', '') if spec.is_a?(String)
272
- result = serialize_spec(spec, parent_spec)
273
- if parent_spec && result[1].is_a?(String)
274
- result = [
275
- # We encode node symbols as integer
276
- # to reduce the routes.js file size
277
- NODE_TYPES[:CAT],
278
- serialize_spec(parent_spec),
279
- result
280
- ]
336
+ def match_configuration?
337
+ !match?(@configuration[:exclude]) && match?(@configuration[:include])
338
+ end
339
+
340
+ def base_name
341
+ @base_name ||= parent_route ?
342
+ [parent_route.name, route.name].join('_') : route.name
343
+ end
344
+
345
+ def parent_spec
346
+ parent_route&.path&.spec
347
+ end
348
+
349
+ def spec
350
+ route.path.spec
281
351
  end
282
- result
283
- end
284
352
 
285
- def serialize_spec(spec, parent_spec=nil)
286
- [
287
- NODE_TYPES[spec.type],
288
- serialize(spec.left, parent_spec),
289
- spec.respond_to?(:right) && serialize(spec.right)
290
- ]
353
+ def json(value)
354
+ JsRoutes.json(value)
355
+ end
356
+
357
+ def helper_name(absolute)
358
+ suffix = absolute ? :url : @configuration[:compact] ? nil : :path
359
+ apply_case(base_name, suffix)
360
+ end
361
+
362
+ def documentation
363
+ return nil unless @configuration[:documentation]
364
+ <<-JS
365
+ /**
366
+ * Generates rails route to
367
+ * #{parent_spec}#{spec}#{documentation_params}
368
+ * @param {object | undefined} options
369
+ * @returns {string} route path
370
+ */
371
+ JS
372
+ end
373
+
374
+ def required_parts
375
+ route.required_parts
376
+ end
377
+
378
+ def optional_parts
379
+ route.path.optional_names
380
+ end
381
+
382
+ def base_arguments
383
+ @base_arguments ||= [parts_table, serialize(spec, parent_spec)]
384
+ end
385
+
386
+ def parts_table
387
+ parts_table = {}
388
+ route.parts.each do |part, hash|
389
+ parts_table[part] ||= {}
390
+ if required_parts.include?(part)
391
+ # Using shortened keys to reduce js file size
392
+ parts_table[part][:r] = true
393
+ end
394
+ end
395
+ route.defaults.each do |part, value|
396
+ if FILTERED_DEFAULT_PARTS.exclude?(part) &&
397
+ URL_OPTIONS.include?(part) || parts_table[part]
398
+ parts_table[part] ||= {}
399
+ # Using shortened keys to reduce js file size
400
+ parts_table[part][:d] = value
401
+ end
402
+ end
403
+ parts_table
404
+ end
405
+
406
+ def documentation_params
407
+ required_parts.map do |param|
408
+ "\n * @param {any} #{apply_case(param)}"
409
+ end.join
410
+ end
411
+
412
+ def match?(matchers)
413
+ Array(matchers).any? { |regex| base_name =~ regex }
414
+ end
415
+
416
+ def apply_case(*values)
417
+ value = values.compact.map(&:to_s).join('_')
418
+ @configuration[:camel_case] ? value.camelize(:lower) : value
419
+ end
420
+
421
+ # This function serializes Journey route into JSON structure
422
+ # We do not use Hash for human readable serialization
423
+ # And preffer Array serialization because it is shorter.
424
+ # Routes.js file will be smaller.
425
+ def serialize(spec, parent_spec=nil)
426
+ return nil unless spec
427
+ # Rails 4 globbing requires * removal
428
+ return spec.tr(':*', '') if spec.is_a?(String)
429
+
430
+ result = serialize_spec(spec, parent_spec)
431
+ if parent_spec && result[1].is_a?(String) && parent_spec.type != :SLASH
432
+ result = [
433
+ # We encode node symbols as integer
434
+ # to reduce the routes.js file size
435
+ NODE_TYPES[:CAT],
436
+ serialize_spec(parent_spec),
437
+ result
438
+ ]
439
+ end
440
+ result
441
+ end
442
+
443
+ def serialize_spec(spec, parent_spec = nil)
444
+ [
445
+ NODE_TYPES[spec.type],
446
+ serialize(spec.left, parent_spec),
447
+ spec.respond_to?(:right) ? serialize(spec.right) : nil
448
+ ].compact
449
+ end
291
450
  end
292
451
  end
293
-
data/lib/routes.d.ts ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * File generated by js-routes RubyVariables.GEM_VERSION
3
+ * Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
4
+ */
5
+ declare type Optional<T> = {
6
+ [P in keyof T]?: T[P] | null;
7
+ };
8
+ declare type BaseRouteParameter = string | boolean | Date | number;
9
+ declare type MethodRouteParameter = BaseRouteParameter | (() => BaseRouteParameter);
10
+ declare type ModelRouteParameter = {
11
+ id: MethodRouteParameter;
12
+ } | {
13
+ to_param: MethodRouteParameter;
14
+ } | {
15
+ toParam: MethodRouteParameter;
16
+ };
17
+ declare type RequiredRouteParameter = BaseRouteParameter | ModelRouteParameter;
18
+ declare type OptionalRouteParameter = undefined | null | RequiredRouteParameter;
19
+ declare type QueryRouteParameter = OptionalRouteParameter | QueryRouteParameter[] | {
20
+ [k: string]: QueryRouteParameter;
21
+ };
22
+ declare type RouteParameters = Record<string, QueryRouteParameter>;
23
+ declare type Serializable = Record<string, unknown>;
24
+ declare type Serializer = (value: Serializable) => string;
25
+ declare type RouteHelperExtras = {
26
+ requiredParams(): string[];
27
+ toString(): string;
28
+ };
29
+ declare type RequiredParameters<T extends number> = T extends 1 ? [RequiredRouteParameter] : T extends 2 ? [RequiredRouteParameter, RequiredRouteParameter] : T extends 3 ? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter] : T extends 4 ? [
30
+ RequiredRouteParameter,
31
+ RequiredRouteParameter,
32
+ RequiredRouteParameter,
33
+ RequiredRouteParameter
34
+ ] : RequiredRouteParameter[];
35
+ declare type RouteHelperOptions<T extends string> = RouteOptions & Optional<Record<T, OptionalRouteParameter>>;
36
+ declare type RouteHelper<T extends number = number, U extends string = string> = ((...args: [...RequiredParameters<T>, RouteHelperOptions<U>]) => string) & RouteHelperExtras;
37
+ declare type RouteHelpers = Record<string, RouteHelper>;
38
+ declare type Configuration = {
39
+ prefix: string;
40
+ default_url_options: RouteParameters;
41
+ special_options_key: string;
42
+ serializer: Serializer;
43
+ };
44
+ interface RouterExposedMethods {
45
+ config(): Configuration;
46
+ configure(arg: Partial<Configuration>): Configuration;
47
+ serialize: Serializer;
48
+ }
49
+ declare type KeywordUrlOptions = Optional<{
50
+ host: string;
51
+ protocol: string;
52
+ subdomain: string;
53
+ port: string | number;
54
+ anchor: string;
55
+ trailing_slash: boolean;
56
+ }>;
57
+ declare type RouteOptions = KeywordUrlOptions & RouteParameters;
58
+ declare type PartsTable = Record<string, {
59
+ r?: boolean;
60
+ d?: OptionalRouteParameter;
61
+ }>;
62
+ declare type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "DTS" | "NIL";
63
+ declare const RubyVariables: {
64
+ PREFIX: string;
65
+ DEPRECATED_GLOBBING_BEHAVIOR: boolean;
66
+ SPECIAL_OPTIONS_KEY: string;
67
+ DEFAULT_URL_OPTIONS: RouteParameters;
68
+ SERIALIZER: Serializer;
69
+ NAMESPACE: string;
70
+ ROUTES_OBJECT: RouteHelpers;
71
+ MODULE_TYPE: ModuleType;
72
+ WRAPPER: <T>(callback: T) => T;
73
+ };
74
+ declare const define: undefined | (((arg: unknown[], callback: () => unknown) => void) & {
75
+ amd?: unknown;
76
+ });
77
+ declare const module: {
78
+ exports: any;
79
+ } | undefined;