js-routes 1.4.9 → 2.2.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/.eslintrc.js +15 -0
- data/.gitignore +5 -0
- data/.nvmrc +1 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +85 -0
- data/Rakefile +5 -2
- data/Readme.md +274 -98
- data/VERSION_2_UPGRADE.md +66 -0
- data/js-routes.gemspec +8 -5
- data/lib/js_routes/engine.rb +0 -1
- data/lib/js_routes/generators/middleware.rb +33 -0
- data/lib/js_routes/generators/webpacker.rb +32 -0
- data/lib/js_routes/middleware.rb +36 -0
- data/lib/js_routes/version.rb +1 -1
- data/lib/js_routes.rb +341 -171
- data/lib/routes.d.ts +79 -0
- data/lib/routes.js +501 -519
- data/lib/routes.ts +737 -0
- data/lib/tasks/js_routes.rake +8 -2
- data/lib/templates/erb.js +11 -0
- data/lib/templates/initializer.rb +5 -0
- data/lib/templates/routes.js.erb +1 -0
- data/package.json +37 -0
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/js_routes/default_serializer_spec.rb +19 -3
- data/spec/js_routes/{amd_compatibility_spec.rb → module_types/amd_spec.rb} +7 -14
- data/spec/js_routes/module_types/cjs_spec.rb +15 -0
- data/spec/js_routes/module_types/dts/routes.spec.d.ts +114 -0
- data/spec/js_routes/module_types/dts/test.spec.ts +56 -0
- data/spec/js_routes/module_types/dts_spec.rb +111 -0
- data/spec/js_routes/module_types/esm_spec.rb +45 -0
- data/spec/js_routes/module_types/nil_spec.rb +86 -0
- data/spec/js_routes/{generated_javascript_spec.rb → module_types/umd_spec.rb} +33 -27
- data/spec/js_routes/options_spec.rb +67 -56
- data/spec/js_routes/rails_routes_compatibility_spec.rb +69 -25
- data/spec/js_routes/zzz_last_post_rails_init_spec.rb +4 -4
- data/spec/spec_helper.rb +34 -17
- data/spec/support/routes.rb +10 -4
- data/spec/tsconfig.json +4 -0
- data/tsconfig.json +28 -0
- data/yarn.lock +2145 -0
- metadata +42 -22
- data/lib/routes.js.coffee +0 -411
data/lib/js_routes.rb
CHANGED
@@ -1,46 +1,32 @@
|
|
1
1
|
require 'uri'
|
2
|
-
|
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
|
-
|
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]
|
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,56 @@ 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 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 = Rails.root.join('app', 'javascript')
|
79
|
+
sprockets_dir = Rails.root.join('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
|
+
def normalize_and_verify
|
87
|
+
normalize
|
88
|
+
verify
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def default_file_name
|
94
|
+
dts? ? "routes.d.ts" : "routes.js"
|
95
|
+
end
|
96
|
+
|
97
|
+
def normalize
|
98
|
+
self.module_type = module_type&.upcase || 'NIL'
|
99
|
+
end
|
100
|
+
|
101
|
+
def verify
|
102
|
+
if module_type != 'NIL' && namespace
|
103
|
+
raise "JsRoutes namespace option can only be used if module_type is nil"
|
104
|
+
end
|
105
|
+
end
|
69
106
|
end
|
70
107
|
|
71
108
|
#
|
@@ -75,27 +112,28 @@ class JsRoutes
|
|
75
112
|
class << self
|
76
113
|
def setup(&block)
|
77
114
|
configuration.tap(&block) if block
|
78
|
-
|
79
|
-
|
80
|
-
def options
|
81
|
-
ActiveSupport::Deprecation.warn('JsRoutes.options method is deprecated use JsRoutes.configuration instead')
|
82
|
-
configuration
|
115
|
+
configuration.normalize_and_verify
|
83
116
|
end
|
84
117
|
|
85
118
|
def configuration
|
86
119
|
@configuration ||= Configuration.new
|
87
120
|
end
|
88
121
|
|
89
|
-
def generate(opts
|
122
|
+
def generate(**opts)
|
90
123
|
new(opts).generate
|
91
124
|
end
|
92
125
|
|
93
|
-
def generate!(file_name=nil, opts
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
126
|
+
def generate!(file_name=nil, **opts)
|
127
|
+
new(file: file_name, **opts).generate!
|
128
|
+
end
|
129
|
+
|
130
|
+
def definitions(**opts)
|
131
|
+
generate(module_type: 'DTS', **opts)
|
132
|
+
end
|
133
|
+
|
134
|
+
def definitions!(file_name = nil, **opts)
|
135
|
+
file_name ||= configuration.file&.sub(%r{(\.d)?\.(j|t)s\Z}, ".d.ts")
|
136
|
+
generate!(file_name, module_type: 'DTS', **opts)
|
99
137
|
end
|
100
138
|
|
101
139
|
def json(string)
|
@@ -113,184 +151,316 @@ class JsRoutes
|
|
113
151
|
|
114
152
|
def generate
|
115
153
|
# Ensure routes are loaded. If they're not, load them.
|
116
|
-
if named_routes.
|
154
|
+
if named_routes.empty? && application.respond_to?(:reload_routes!)
|
117
155
|
application.reload_routes!
|
118
156
|
end
|
157
|
+
content = File.read(@configuration.source_file)
|
119
158
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
|
126
|
-
|
127
|
-
'APP_CLASS' => application.class.to_s,
|
128
|
-
'NAMESPACE' => json(@configuration.namespace),
|
129
|
-
'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
|
130
|
-
'PREFIX' => json(@configuration.prefix),
|
131
|
-
'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
|
132
|
-
'SERIALIZER' => @configuration.serializer || json(nil),
|
133
|
-
}.inject(File.read(File.dirname(__FILE__) + "/routes.js")) do |js, (key, value)|
|
134
|
-
js.gsub!(key, value.to_s)
|
159
|
+
if !@configuration.dts?
|
160
|
+
content = js_variables.inject(content) do |js, (key, value)|
|
161
|
+
js.gsub!("RubyVariables.#{key}", value.to_s) ||
|
162
|
+
raise("Missing key #{key} in JS template")
|
163
|
+
end
|
135
164
|
end
|
165
|
+
content + routes_export + prevent_types_export
|
136
166
|
end
|
137
167
|
|
138
|
-
def generate!
|
139
|
-
# Some libraries like Devise
|
140
|
-
# until initialization process
|
168
|
+
def generate!
|
169
|
+
# Some libraries like Devise did not load their routes yet
|
170
|
+
# so we will wait until initialization process finishes
|
141
171
|
# https://github.com/railsware/js-routes/issues/7
|
142
172
|
Rails.configuration.after_initialize do
|
143
|
-
|
144
|
-
|
145
|
-
js_content = generate
|
173
|
+
file_path = Rails.root.join(@configuration.output_file)
|
174
|
+
source_code = generate
|
146
175
|
|
147
176
|
# We don't need to rewrite file if it already exist and have same content.
|
148
177
|
# It helps asset pipeline or webpack understand that file wasn't changed.
|
149
|
-
next if File.exist?(file_path) && File.read(file_path) ==
|
178
|
+
next if File.exist?(file_path) && File.read(file_path) == source_code
|
150
179
|
|
151
180
|
File.open(file_path, 'w') do |f|
|
152
|
-
f.write
|
181
|
+
f.write source_code
|
153
182
|
end
|
154
183
|
end
|
155
184
|
end
|
156
185
|
|
157
186
|
protected
|
158
187
|
|
188
|
+
def js_variables
|
189
|
+
{
|
190
|
+
'GEM_VERSION' => JsRoutes::VERSION,
|
191
|
+
'ROUTES_OBJECT' => routes_object,
|
192
|
+
'RAILS_VERSION' => ActionPack.version,
|
193
|
+
'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
|
194
|
+
|
195
|
+
'APP_CLASS' => application.class.to_s,
|
196
|
+
'NAMESPACE' => json(@configuration.namespace),
|
197
|
+
'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
|
198
|
+
'PREFIX' => json(@configuration.prefix),
|
199
|
+
'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
|
200
|
+
'SERIALIZER' => @configuration.serializer || json(nil),
|
201
|
+
'MODULE_TYPE' => json(@configuration.module_type),
|
202
|
+
'WRAPPER' => @configuration.esm? ? 'const __jsr = ' : '',
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
159
206
|
def application
|
160
207
|
@configuration.application
|
161
208
|
end
|
162
209
|
|
210
|
+
def json(string)
|
211
|
+
self.class.json(string)
|
212
|
+
end
|
213
|
+
|
163
214
|
def named_routes
|
164
215
|
application.routes.named_routes.to_a
|
165
216
|
end
|
166
217
|
|
167
|
-
def
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
218
|
+
def routes_object
|
219
|
+
return json({}) if @configuration.modern?
|
220
|
+
properties = routes_list.map do |comment, name, body|
|
221
|
+
"#{comment}#{name}: #{body}".indent(2)
|
222
|
+
end
|
223
|
+
"{\n" + properties.join(",\n\n") + "}\n"
|
224
|
+
end
|
225
|
+
|
226
|
+
def static_exports
|
227
|
+
[:configure, :config, :serialize].map do |name|
|
228
|
+
[
|
229
|
+
"", name,
|
230
|
+
@configuration.dts? ?
|
231
|
+
"RouterExposedMethods['#{name}']" :
|
232
|
+
"__jsr.#{name}"
|
233
|
+
]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def routes_export
|
238
|
+
return "" unless @configuration.modern?
|
239
|
+
[*static_exports, *routes_list].map do |comment, name, body|
|
240
|
+
"#{comment}export const #{name}#{export_separator}#{body};\n\n"
|
241
|
+
end.join
|
242
|
+
end
|
243
|
+
|
244
|
+
def prevent_types_export
|
245
|
+
return "" unless @configuration.dts?
|
246
|
+
<<-JS
|
247
|
+
// By some reason this line prevents all types in a file
|
248
|
+
// from being automatically exported
|
249
|
+
export {};
|
250
|
+
JS
|
251
|
+
end
|
252
|
+
|
253
|
+
def export_separator
|
254
|
+
@configuration.dts? ? ': ' : ' = '
|
255
|
+
end
|
256
|
+
|
257
|
+
def routes_list
|
258
|
+
named_routes.sort_by(&:first).flat_map do |_, route|
|
259
|
+
route_helpers_if_match(route) + mounted_app_routes(route)
|
260
|
+
end
|
172
261
|
end
|
173
262
|
|
174
263
|
def mounted_app_routes(route)
|
175
|
-
rails_engine_app =
|
264
|
+
rails_engine_app = app_from_route(route)
|
176
265
|
if rails_engine_app.respond_to?(:superclass) &&
|
177
266
|
rails_engine_app.superclass == Rails::Engine && !route.path.anchored
|
178
|
-
rails_engine_app.routes.named_routes.
|
179
|
-
|
267
|
+
rails_engine_app.routes.named_routes.flat_map do |_, engine_route|
|
268
|
+
route_helpers_if_match(engine_route, route)
|
180
269
|
end
|
181
270
|
else
|
182
271
|
[]
|
183
272
|
end
|
184
273
|
end
|
185
274
|
|
186
|
-
def
|
275
|
+
def app_from_route(route)
|
276
|
+
app = route.app
|
187
277
|
# rails engine in Rails 4.2 use additional
|
188
278
|
# ActionDispatch::Routing::Mapper::Constraints, which contain app
|
189
|
-
if
|
190
|
-
|
279
|
+
if app.respond_to?(:app) && app.respond_to?(:constraints)
|
280
|
+
app.app
|
191
281
|
else
|
192
|
-
|
282
|
+
app
|
193
283
|
end
|
194
284
|
end
|
195
285
|
|
196
|
-
def
|
197
|
-
|
198
|
-
!any_match?(route, parent_route, @configuration[:include])
|
199
|
-
nil
|
200
|
-
else
|
201
|
-
build_js(route, parent_route)
|
202
|
-
end
|
286
|
+
def route_helpers_if_match(route, parent_route = nil)
|
287
|
+
JsRoute.new(@configuration, route, parent_route).helpers
|
203
288
|
end
|
204
289
|
|
205
|
-
|
206
|
-
|
290
|
+
class JsRoute #:nodoc:
|
291
|
+
FILTERED_DEFAULT_PARTS = [:controller, :action]
|
292
|
+
URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain]
|
293
|
+
NODE_TYPES = {
|
294
|
+
GROUP: 1,
|
295
|
+
CAT: 2,
|
296
|
+
SYMBOL: 3,
|
297
|
+
OR: 4,
|
298
|
+
STAR: 5,
|
299
|
+
LITERAL: 6,
|
300
|
+
SLASH: 7,
|
301
|
+
DOT: 8
|
302
|
+
}
|
303
|
+
|
304
|
+
attr_reader :configuration, :route, :parent_route
|
305
|
+
|
306
|
+
def initialize(configuration, route, parent_route = nil)
|
307
|
+
@configuration = configuration
|
308
|
+
@route = route
|
309
|
+
@parent_route = parent_route
|
310
|
+
end
|
207
311
|
|
208
|
-
|
209
|
-
|
210
|
-
|
312
|
+
def helpers
|
313
|
+
helper_types.map do |absolute|
|
314
|
+
[ documentation, helper_name(absolute), body(absolute) ]
|
315
|
+
end
|
316
|
+
end
|
211
317
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
route_arguments = route_js_arguments(route, parent_spec)
|
217
|
-
url_link = generate_url_link(name, route_arguments)
|
218
|
-
_ = <<-JS.strip!
|
219
|
-
// #{name.join('.')} => #{parent_spec}#{route.path.spec}
|
220
|
-
// function(#{build_params(route.required_parts)})
|
221
|
-
#{route_name}: Utils.route(#{route_arguments})#{",\n" + url_link if url_link.length > 0}
|
222
|
-
JS
|
223
|
-
end
|
318
|
+
def helper_types
|
319
|
+
return [] unless match_configuration?
|
320
|
+
@configuration[:url_links] ? [true, false] : [false]
|
321
|
+
end
|
224
322
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
end
|
230
|
-
default_options = route.defaults.select do |part, _|
|
231
|
-
FILTERED_DEFAULT_PARTS.exclude?(part) &&
|
232
|
-
URL_OPTIONS.include?(part) || parts_table[part]
|
233
|
-
end
|
234
|
-
[
|
235
|
-
# JS objects don't preserve the order of properties which is crucial,
|
236
|
-
# so array is a better choice.
|
237
|
-
parts_table.to_a,
|
238
|
-
default_options,
|
239
|
-
serialize(route.path.spec, parent_spec)
|
240
|
-
].map do |argument|
|
241
|
-
json(argument)
|
242
|
-
end.join(', ')
|
243
|
-
end
|
323
|
+
def body(absolute)
|
324
|
+
@configuration.dts? ?
|
325
|
+
definition_body : "__jsr.r(#{arguments(absolute).map{|a| json(a)}.join(', ')})"
|
326
|
+
end
|
244
327
|
|
245
|
-
|
246
|
-
|
328
|
+
def definition_body
|
329
|
+
args = required_parts.map{|p| "#{apply_case(p)}: RequiredRouteParameter"}
|
330
|
+
args << "options?: #{optional_parts_type} & RouteOptions"
|
331
|
+
"((\n#{args.join(",\n").indent(2)}\n) => string) & RouteHelperExtras"
|
332
|
+
end
|
247
333
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
334
|
+
def optional_parts_type
|
335
|
+
@optional_parts_type ||=
|
336
|
+
"{" + optional_parts.map {|p| "#{p}?: OptionalRouteParameter"}.join(', ') + "}"
|
337
|
+
end
|
252
338
|
|
253
|
-
|
254
|
-
route_name = parts.compact.join('_')
|
255
|
-
@configuration[:camel_case] ? route_name.camelize(:lower) : route_name
|
256
|
-
end
|
339
|
+
protected
|
257
340
|
|
258
|
-
|
259
|
-
|
260
|
-
|
341
|
+
def arguments(absolute)
|
342
|
+
absolute ? [*base_arguments, true] : base_arguments
|
343
|
+
end
|
261
344
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
end
|
345
|
+
def match_configuration?
|
346
|
+
!match?(@configuration[:exclude]) && match?(@configuration[:include])
|
347
|
+
end
|
266
348
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
# Routes.js file will be smaller.
|
271
|
-
def serialize(spec, parent_spec=nil)
|
272
|
-
return nil unless spec
|
273
|
-
# Rails 4 globbing requires * removal
|
274
|
-
return spec.tr(':*', '') if spec.is_a?(String)
|
275
|
-
|
276
|
-
result = serialize_spec(spec, parent_spec)
|
277
|
-
if parent_spec && result[1].is_a?(String)
|
278
|
-
result = [
|
279
|
-
# We encode node symbols as integer
|
280
|
-
# to reduce the routes.js file size
|
281
|
-
NODE_TYPES[:CAT],
|
282
|
-
serialize_spec(parent_spec),
|
283
|
-
result
|
284
|
-
]
|
349
|
+
def base_name
|
350
|
+
@base_name ||= parent_route ?
|
351
|
+
[parent_route.name, route.name].join('_') : route.name
|
285
352
|
end
|
286
|
-
result
|
287
|
-
end
|
288
353
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
354
|
+
def parent_spec
|
355
|
+
parent_route&.path&.spec
|
356
|
+
end
|
357
|
+
|
358
|
+
def spec
|
359
|
+
route.path.spec
|
360
|
+
end
|
361
|
+
|
362
|
+
def json(value)
|
363
|
+
JsRoutes.json(value)
|
364
|
+
end
|
365
|
+
|
366
|
+
def helper_name(absolute)
|
367
|
+
suffix = absolute ? :url : @configuration[:compact] ? nil : :path
|
368
|
+
apply_case(base_name, suffix)
|
369
|
+
end
|
370
|
+
|
371
|
+
def documentation
|
372
|
+
return nil unless @configuration[:documentation]
|
373
|
+
<<-JS
|
374
|
+
/**
|
375
|
+
* Generates rails route to
|
376
|
+
* #{parent_spec}#{spec}#{documentation_params}
|
377
|
+
* @param {object | undefined} options
|
378
|
+
* @returns {string} route path
|
379
|
+
*/
|
380
|
+
JS
|
381
|
+
end
|
382
|
+
|
383
|
+
def required_parts
|
384
|
+
route.required_parts
|
385
|
+
end
|
386
|
+
|
387
|
+
def optional_parts
|
388
|
+
route.path.optional_names
|
389
|
+
end
|
390
|
+
|
391
|
+
def base_arguments
|
392
|
+
@base_arguments ||= [parts_table, serialize(spec, parent_spec)]
|
393
|
+
end
|
394
|
+
|
395
|
+
def parts_table
|
396
|
+
parts_table = {}
|
397
|
+
route.parts.each do |part, hash|
|
398
|
+
parts_table[part] ||= {}
|
399
|
+
if required_parts.include?(part)
|
400
|
+
# Using shortened keys to reduce js file size
|
401
|
+
parts_table[part][:r] = true
|
402
|
+
end
|
403
|
+
end
|
404
|
+
route.defaults.each do |part, value|
|
405
|
+
if FILTERED_DEFAULT_PARTS.exclude?(part) &&
|
406
|
+
URL_OPTIONS.include?(part) || parts_table[part]
|
407
|
+
parts_table[part] ||= {}
|
408
|
+
# Using shortened keys to reduce js file size
|
409
|
+
parts_table[part][:d] = value
|
410
|
+
end
|
411
|
+
end
|
412
|
+
parts_table
|
413
|
+
end
|
414
|
+
|
415
|
+
def documentation_params
|
416
|
+
required_parts.map do |param|
|
417
|
+
"\n * @param {any} #{apply_case(param)}"
|
418
|
+
end.join
|
419
|
+
end
|
420
|
+
|
421
|
+
def match?(matchers)
|
422
|
+
Array(matchers).any? { |regex| base_name =~ regex }
|
423
|
+
end
|
424
|
+
|
425
|
+
def apply_case(*values)
|
426
|
+
value = values.compact.map(&:to_s).join('_')
|
427
|
+
@configuration[:camel_case] ? value.camelize(:lower) : value
|
428
|
+
end
|
429
|
+
|
430
|
+
# This function serializes Journey route into JSON structure
|
431
|
+
# We do not use Hash for human readable serialization
|
432
|
+
# And preffer Array serialization because it is shorter.
|
433
|
+
# Routes.js file will be smaller.
|
434
|
+
def serialize(spec, parent_spec=nil)
|
435
|
+
return nil unless spec
|
436
|
+
# Rails 4 globbing requires * removal
|
437
|
+
return spec.tr(':*', '') if spec.is_a?(String)
|
438
|
+
|
439
|
+
result = serialize_spec(spec, parent_spec)
|
440
|
+
if parent_spec && result[1].is_a?(String) && parent_spec.type != :SLASH
|
441
|
+
result = [
|
442
|
+
# We encode node symbols as integer
|
443
|
+
# to reduce the routes.js file size
|
444
|
+
NODE_TYPES[:CAT],
|
445
|
+
serialize_spec(parent_spec),
|
446
|
+
result
|
447
|
+
]
|
448
|
+
end
|
449
|
+
result
|
450
|
+
end
|
451
|
+
|
452
|
+
def serialize_spec(spec, parent_spec = nil)
|
453
|
+
[
|
454
|
+
NODE_TYPES[spec.type],
|
455
|
+
serialize(spec.left, parent_spec),
|
456
|
+
spec.respond_to?(:right) ? serialize(spec.right) : nil
|
457
|
+
].compact
|
458
|
+
end
|
459
|
+
end
|
460
|
+
module Generators
|
295
461
|
end
|
296
462
|
end
|
463
|
+
|
464
|
+
require "js_routes/middleware"
|
465
|
+
require "js_routes/generators/webpacker"
|
466
|
+
require "js_routes/generators/middleware"
|
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;
|