js-routes 2.0.8 → 2.1.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/CHANGELOG.md +4 -0
- data/Readme.md +30 -10
- data/js-routes.gemspec +1 -1
- data/lib/js_routes/version.rb +1 -1
- data/lib/js_routes.rb +152 -92
- data/lib/routes.d.ts +33 -11
- data/lib/routes.js +17 -25
- data/lib/routes.ts +78 -52
- data/lib/tasks/js_routes.rake +8 -2
- 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/zzz_last_post_rails_init_spec.rb +2 -2
- data/spec/tsconfig.json +4 -0
- data/tsconfig.json +3 -7
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 242f329ab92abe8be4a2fa3790f72a3f161a6c2355b2392eae484a36a91d3a24
|
4
|
+
data.tar.gz: 120e5191eccfe3a8978c89ecb690a4f93a62279b249c58bc84b9273fe3e900c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1998fd3c98dff227905bfcd8a09be8bb6901d3da7293b60d1a6f11c3a2627c623372324a13010cbe425eb7b93781fa64db042c08e7b4123d4a50ec8bd8814b2
|
7
|
+
data.tar.gz: 5395c808f148bd39a99de0ce748cbb3a57c27620f048764bfcf6a455ac6ce2bbc43e282f4c660ba019f8d4b5df39a316728bb673d56b2667aecb667dde82d91b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
## master
|
2
2
|
|
3
|
+
## v2.1.0
|
4
|
+
|
5
|
+
* Support typescript defintions file aka `routes.d.ts`. See [Readme.md](./Readme.md#definitions) for more information.
|
6
|
+
|
3
7
|
## v2.0.8
|
4
8
|
|
5
9
|
* Forbid usage of `namespace` option if `module_type` is not `nil`. [#281](https://github.com/railsware/js-routes/issues/281).
|
data/Readme.md
CHANGED
@@ -20,22 +20,26 @@ gem "js-routes"
|
|
20
20
|
|
21
21
|
Run:
|
22
22
|
|
23
|
-
```
|
23
|
+
``` sh
|
24
24
|
rake js:routes
|
25
|
+
# OR for typescript support
|
26
|
+
rake js:routes:typescript
|
25
27
|
```
|
26
28
|
|
27
|
-
|
29
|
+
|
30
|
+
Individual routes can be imported using:
|
28
31
|
|
29
32
|
``` javascript
|
30
|
-
import
|
31
|
-
|
33
|
+
import {edit_post_path, posts_path} from 'routes';
|
34
|
+
console.log(posts_path({format: 'json'})) // => "/posts.json"
|
35
|
+
console.log(edit_post_path(1)) // => "/posts/1/edit"
|
32
36
|
```
|
33
37
|
|
34
|
-
|
38
|
+
Make routes available globally in `app/javascript/packs/application.js`:
|
35
39
|
|
36
40
|
``` javascript
|
37
|
-
import
|
38
|
-
|
41
|
+
import * as Routes from 'routes';
|
42
|
+
window.Routes = Routes;
|
39
43
|
```
|
40
44
|
|
41
45
|
**Note**: that this setup requires `rake js:routes` to be run each time routes file is updated.
|
@@ -91,6 +95,22 @@ import * as Routes from 'routes.js.erb';
|
|
91
95
|
window.Routes = Routes;
|
92
96
|
```
|
93
97
|
|
98
|
+
<div id='definitions'></div>
|
99
|
+
|
100
|
+
#### Typescript Definitions
|
101
|
+
|
102
|
+
JsRoutes has typescript support out of the box. In order to generate typscript definitions file (aka `routes.d.ts`) you can call:
|
103
|
+
|
104
|
+
``` ruby
|
105
|
+
JsRoutes.definitions!
|
106
|
+
```
|
107
|
+
|
108
|
+
Or create an automatic updates file at `app/javascript/routes.d.ts.erb`:
|
109
|
+
|
110
|
+
``` erb
|
111
|
+
<%= JsRoutes.defintions %>
|
112
|
+
```
|
113
|
+
|
94
114
|
#### Sprockets (Deprecated)
|
95
115
|
|
96
116
|
If you are using [Sprockets](https://github.com/rails/sprockets-rails) you may configure js-routes in the following way.
|
@@ -147,7 +167,7 @@ Routes.config(); // current config
|
|
147
167
|
Options to configure JavaScript file generator. These options are only available in Ruby context but not JavaScript.
|
148
168
|
|
149
169
|
* `module_type` - JavaScript module type for generated code. [Article](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm)
|
150
|
-
* Options: `ESM`, `UMD`, `CJS`, `AMD`, `nil`.
|
170
|
+
* Options: `ESM`, `UMD`, `CJS`, `AMD`, `DTS`, `nil`.
|
151
171
|
* Default: `ESM`
|
152
172
|
* `nil` option can be used in case you don't want generated code to export anything.
|
153
173
|
* `documentation` - specifies if each route should be annotated with [JSDoc](https://jsdoc.app/) comment
|
@@ -324,9 +344,9 @@ Split your routes into multiple files related to each section of your website li
|
|
324
344
|
|
325
345
|
``` javascript
|
326
346
|
// admin-routes.js.erb
|
327
|
-
<%= JsRoutes.generate(include: /^admin_/)
|
347
|
+
<%= JsRoutes.generate(include: /^admin_/) %>
|
328
348
|
// app-routes.js.erb
|
329
|
-
<%= JsRoutes.generate(exclude: /^admin_/)
|
349
|
+
<%= JsRoutes.generate(exclude: /^admin_/) %>
|
330
350
|
```
|
331
351
|
|
332
352
|
## Advantages over alternatives
|
data/js-routes.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.add_runtime_dependency(%q<railties>, [">= 4"])
|
27
27
|
s.add_development_dependency(%q<sprockets-rails>)
|
28
|
-
s.add_development_dependency(%q<rspec>, [">= 3.
|
28
|
+
s.add_development_dependency(%q<rspec>, [">= 3.10.0"])
|
29
29
|
s.add_development_dependency(%q<bundler>, [">= 1.1.0"])
|
30
30
|
s.add_development_dependency(%q<appraisal>, [">= 0.5.2"])
|
31
31
|
s.add_development_dependency(%q<bump>, [">= 0.10.0"])
|
data/lib/js_routes/version.rb
CHANGED
data/lib/js_routes.rb
CHANGED
@@ -7,48 +7,26 @@ require 'active_support/core_ext/string/indent'
|
|
7
7
|
|
8
8
|
class JsRoutes
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
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)
|
13
29
|
|
14
|
-
DEFAULTS = {
|
15
|
-
namespace: nil,
|
16
|
-
exclude: [],
|
17
|
-
include: //,
|
18
|
-
file: -> do
|
19
|
-
webpacker_dir = Rails.root.join('app', 'javascript')
|
20
|
-
sprockets_dir = Rails.root.join('app','assets','javascripts')
|
21
|
-
sprockets_file = sprockets_dir.join('routes.js')
|
22
|
-
webpacker_file = webpacker_dir.join('routes.js')
|
23
|
-
!Dir.exist?(webpacker_dir) && defined?(::Sprockets) ? sprockets_file : webpacker_file
|
24
|
-
end,
|
25
|
-
prefix: -> { Rails.application.config.relative_url_root || "" },
|
26
|
-
url_links: false,
|
27
|
-
camel_case: false,
|
28
|
-
default_url_options: {},
|
29
|
-
compact: false,
|
30
|
-
serializer: nil,
|
31
|
-
special_options_key: "_options",
|
32
|
-
application: -> { Rails.application },
|
33
|
-
module_type: 'ESM',
|
34
|
-
documentation: true,
|
35
|
-
} #:nodoc:
|
36
|
-
|
37
|
-
NODE_TYPES = {
|
38
|
-
GROUP: 1,
|
39
|
-
CAT: 2,
|
40
|
-
SYMBOL: 3,
|
41
|
-
OR: 4,
|
42
|
-
STAR: 5,
|
43
|
-
LITERAL: 6,
|
44
|
-
SLASH: 7,
|
45
|
-
DOT: 8
|
46
|
-
} #:nodoc:
|
47
|
-
|
48
|
-
FILTERED_DEFAULT_PARTS = [:controller, :action] #:nodoc:
|
49
|
-
URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain] #:nodoc:
|
50
|
-
|
51
|
-
class Configuration < Struct.new(*DEFAULTS.keys)
|
52
30
|
def initialize(attributes = nil)
|
53
31
|
assign(DEFAULTS)
|
54
32
|
return unless attributes
|
@@ -80,6 +58,27 @@ class JsRoutes
|
|
80
58
|
module_type === 'ESM'
|
81
59
|
end
|
82
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
|
+
|
83
82
|
def normalize_and_verify
|
84
83
|
normalize
|
85
84
|
verify
|
@@ -87,6 +86,10 @@ class JsRoutes
|
|
87
86
|
|
88
87
|
protected
|
89
88
|
|
89
|
+
def default_file_name
|
90
|
+
dts? ? "routes.d.ts" : "routes.js"
|
91
|
+
end
|
92
|
+
|
90
93
|
def normalize
|
91
94
|
self.module_type = module_type&.upcase || 'NIL'
|
92
95
|
end
|
@@ -116,12 +119,13 @@ class JsRoutes
|
|
116
119
|
new(opts).generate
|
117
120
|
end
|
118
121
|
|
119
|
-
def generate!(file_name=nil, opts
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
def generate!(file_name=nil, **opts)
|
123
|
+
new(file: file_name, **opts).generate!
|
124
|
+
end
|
125
|
+
|
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!
|
125
129
|
end
|
126
130
|
|
127
131
|
def json(string)
|
@@ -142,48 +146,55 @@ class JsRoutes
|
|
142
146
|
if named_routes.to_a.empty? && application.respond_to?(:reload_routes!)
|
143
147
|
application.reload_routes!
|
144
148
|
end
|
149
|
+
content = File.read(@configuration.source_file)
|
145
150
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
'RAILS_VERSION' => ActionPack.version,
|
150
|
-
'DEPRECATED_GLOBBING_BEHAVIOR' => ActionPack::VERSION::MAJOR == 4 && ActionPack::VERSION::MINOR == 0,
|
151
|
-
|
152
|
-
'APP_CLASS' => application.class.to_s,
|
153
|
-
'NAMESPACE' => json(@configuration.namespace),
|
154
|
-
'DEFAULT_URL_OPTIONS' => json(@configuration.default_url_options),
|
155
|
-
'PREFIX' => json(@configuration.prefix),
|
156
|
-
'SPECIAL_OPTIONS_KEY' => json(@configuration.special_options_key),
|
157
|
-
'SERIALIZER' => @configuration.serializer || json(nil),
|
158
|
-
'MODULE_TYPE' => json(@configuration.module_type),
|
159
|
-
'WRAPPER' => @configuration.esm? ? 'const __jsr = ' : '',
|
160
|
-
}.inject(File.read(File.dirname(__FILE__) + "/routes.js")) do |js, (key, value)|
|
161
|
-
js.gsub!("RubyVariables.#{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) ||
|
162
154
|
raise("Missing key #{key} in JS template")
|
163
|
-
|
155
|
+
end
|
156
|
+
end
|
157
|
+
content + routes_export + prevent_types_export
|
164
158
|
end
|
165
159
|
|
166
|
-
def generate!
|
167
|
-
# Some libraries like Devise
|
168
|
-
# until initialization process
|
160
|
+
def generate!
|
161
|
+
# Some libraries like Devise did not load their routes yet
|
162
|
+
# so we will wait until initialization process finishes
|
169
163
|
# https://github.com/railsware/js-routes/issues/7
|
170
164
|
Rails.configuration.after_initialize do
|
171
|
-
|
172
|
-
|
173
|
-
js_content = generate
|
165
|
+
file_path = Rails.root.join(@configuration.output_file)
|
166
|
+
source_code = generate
|
174
167
|
|
175
168
|
# We don't need to rewrite file if it already exist and have same content.
|
176
169
|
# It helps asset pipeline or webpack understand that file wasn't changed.
|
177
|
-
next if File.exist?(file_path) && File.read(file_path) ==
|
170
|
+
next if File.exist?(file_path) && File.read(file_path) == source_code
|
178
171
|
|
179
172
|
File.open(file_path, 'w') do |f|
|
180
|
-
f.write
|
173
|
+
f.write source_code
|
181
174
|
end
|
182
175
|
end
|
183
176
|
end
|
184
177
|
|
185
178
|
protected
|
186
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
|
+
|
187
198
|
def application
|
188
199
|
@configuration.application
|
189
200
|
end
|
@@ -197,32 +208,52 @@ class JsRoutes
|
|
197
208
|
end
|
198
209
|
|
199
210
|
def routes_object
|
200
|
-
return json({}) if @configuration.
|
211
|
+
return json({}) if @configuration.modern?
|
201
212
|
properties = routes_list.map do |comment, name, body|
|
202
213
|
"#{comment}#{name}: #{body}".indent(2)
|
203
214
|
end
|
204
215
|
"{\n" + properties.join(",\n\n") + "}\n"
|
205
216
|
end
|
206
217
|
|
207
|
-
|
208
|
-
[
|
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
|
209
227
|
end
|
210
228
|
|
211
229
|
def routes_export
|
212
|
-
return "" unless @configuration.
|
213
|
-
[*
|
214
|
-
"#{comment}export const #{name}
|
215
|
-
end.join
|
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? ? ': ' : ' = '
|
216
247
|
end
|
217
248
|
|
218
249
|
def routes_list
|
219
250
|
named_routes.sort_by(&:first).flat_map do |_, route|
|
220
251
|
route_helpers_if_match(route) + mounted_app_routes(route)
|
221
|
-
end
|
252
|
+
end
|
222
253
|
end
|
223
254
|
|
224
255
|
def mounted_app_routes(route)
|
225
|
-
rails_engine_app =
|
256
|
+
rails_engine_app = app_from_route(route)
|
226
257
|
if rails_engine_app.respond_to?(:superclass) &&
|
227
258
|
rails_engine_app.superclass == Rails::Engine && !route.path.anchored
|
228
259
|
rails_engine_app.routes.named_routes.flat_map do |_, engine_route|
|
@@ -233,7 +264,7 @@ class JsRoutes
|
|
233
264
|
end
|
234
265
|
end
|
235
266
|
|
236
|
-
def
|
267
|
+
def app_from_route(route)
|
237
268
|
# rails engine in Rails 4.2 use additional
|
238
269
|
# ActionDispatch::Routing::Mapper::Constraints, which contain app
|
239
270
|
if route.app.respond_to?(:app) && route.app.respond_to?(:constraints)
|
@@ -248,6 +279,19 @@ class JsRoutes
|
|
248
279
|
end
|
249
280
|
|
250
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
|
+
|
251
295
|
attr_reader :configuration, :route, :parent_route
|
252
296
|
|
253
297
|
def initialize(configuration, route, parent_route = nil)
|
@@ -257,24 +301,36 @@ class JsRoutes
|
|
257
301
|
end
|
258
302
|
|
259
303
|
def helpers
|
260
|
-
|
261
|
-
[]
|
262
|
-
else
|
263
|
-
[false, true].map do |absolute|
|
264
|
-
absolute && !@configuration[:url_links] ?
|
265
|
-
nil : [ documentation, helper_name(absolute), body(absolute) ]
|
266
|
-
end
|
304
|
+
helper_types.map do |absolute|
|
305
|
+
[ documentation, helper_name(absolute), body(absolute) ]
|
267
306
|
end
|
268
307
|
end
|
269
308
|
|
270
|
-
|
309
|
+
def helper_types
|
310
|
+
return [] unless match_configuration?
|
311
|
+
@configuration[:url_links] ? [true, false] : [false]
|
312
|
+
end
|
271
313
|
|
272
314
|
def body(absolute)
|
273
|
-
|
315
|
+
@configuration.dts? ?
|
316
|
+
definition_body : "__jsr.r(#{arguments(absolute).map{|a| json(a)}.join(', ')})"
|
274
317
|
end
|
275
318
|
|
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
|
324
|
+
|
325
|
+
def optional_parts_type
|
326
|
+
@optional_parts_type ||=
|
327
|
+
"{" + optional_parts.map {|p| "#{p}?: OptionalRouteParameter"}.join(', ') + "}"
|
328
|
+
end
|
329
|
+
|
330
|
+
protected
|
331
|
+
|
276
332
|
def arguments(absolute)
|
277
|
-
absolute ? base_arguments
|
333
|
+
absolute ? [*base_arguments, true] : base_arguments
|
278
334
|
end
|
279
335
|
|
280
336
|
def match_configuration?
|
@@ -319,6 +375,10 @@ JS
|
|
319
375
|
route.required_parts
|
320
376
|
end
|
321
377
|
|
378
|
+
def optional_parts
|
379
|
+
route.path.optional_names
|
380
|
+
end
|
381
|
+
|
322
382
|
def base_arguments
|
323
383
|
@base_arguments ||= [parts_table, serialize(spec, parent_spec)]
|
324
384
|
end
|
data/lib/routes.d.ts
CHANGED
@@ -2,14 +2,38 @@
|
|
2
2
|
* File generated by js-routes RubyVariables.GEM_VERSION
|
3
3
|
* Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
|
4
4
|
*/
|
5
|
-
declare type
|
6
|
-
|
7
|
-
|
8
|
-
declare type
|
9
|
-
|
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 = {
|
10
26
|
requiredParams(): string[];
|
11
27
|
toString(): string;
|
12
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;
|
13
37
|
declare type RouteHelpers = Record<string, RouteHelper>;
|
14
38
|
declare type Configuration = {
|
15
39
|
prefix: string;
|
@@ -17,9 +41,6 @@ declare type Configuration = {
|
|
17
41
|
special_options_key: string;
|
18
42
|
serializer: Serializer;
|
19
43
|
};
|
20
|
-
declare type Optional<T> = {
|
21
|
-
[P in keyof T]?: T[P] | null;
|
22
|
-
};
|
23
44
|
interface RouterExposedMethods {
|
24
45
|
config(): Configuration;
|
25
46
|
configure(arg: Partial<Configuration>): Configuration;
|
@@ -29,15 +50,16 @@ declare type KeywordUrlOptions = Optional<{
|
|
29
50
|
host: string;
|
30
51
|
protocol: string;
|
31
52
|
subdomain: string;
|
32
|
-
port: string;
|
53
|
+
port: string | number;
|
33
54
|
anchor: string;
|
34
55
|
trailing_slash: boolean;
|
35
56
|
}>;
|
57
|
+
declare type RouteOptions = KeywordUrlOptions & RouteParameters;
|
36
58
|
declare type PartsTable = Record<string, {
|
37
59
|
r?: boolean;
|
38
|
-
d?:
|
60
|
+
d?: OptionalRouteParameter;
|
39
61
|
}>;
|
40
|
-
declare type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "NIL";
|
62
|
+
declare type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "DTS" | "NIL";
|
41
63
|
declare const RubyVariables: {
|
42
64
|
PREFIX: string;
|
43
65
|
DEPRECATED_GLOBBING_BEHAVIOR: boolean;
|
data/lib/routes.js
CHANGED
@@ -76,6 +76,15 @@ RubyVariables.WRAPPER((that) => {
|
|
76
76
|
return !!Root;
|
77
77
|
},
|
78
78
|
},
|
79
|
+
DTS: {
|
80
|
+
// Acts the same as ESM
|
81
|
+
define(routes) {
|
82
|
+
ModuleReferences.ESM.define(routes);
|
83
|
+
},
|
84
|
+
isSupported() {
|
85
|
+
return ModuleReferences.ESM.isSupported();
|
86
|
+
},
|
87
|
+
},
|
79
88
|
};
|
80
89
|
class ParametersMissing extends Error {
|
81
90
|
constructor(...keys) {
|
@@ -162,7 +171,7 @@ RubyVariables.WRAPPER((that) => {
|
|
162
171
|
}
|
163
172
|
looks_like_serialized_model(object) {
|
164
173
|
return (this.is_object(object) &&
|
165
|
-
!
|
174
|
+
!(this.configuration.special_options_key in object) &&
|
166
175
|
("id" in object || "to_param" in object || "toParam" in object));
|
167
176
|
}
|
168
177
|
path_identifier(object) {
|
@@ -320,9 +329,7 @@ RubyVariables.WRAPPER((that) => {
|
|
320
329
|
}
|
321
330
|
}
|
322
331
|
encode_segment(segment) {
|
323
|
-
return segment.replace(UriEncoderSegmentRegex,
|
324
|
-
return encodeURIComponent(str);
|
325
|
-
});
|
332
|
+
return segment.replace(UriEncoderSegmentRegex, (str) => encodeURIComponent(str));
|
326
333
|
}
|
327
334
|
is_optional_node(node) {
|
328
335
|
return [NodeTypes.STAR, NodeTypes.SYMBOL, NodeTypes.CAT].includes(node);
|
@@ -410,32 +417,17 @@ RubyVariables.WRAPPER((that) => {
|
|
410
417
|
port = port ? ":" + port : "";
|
411
418
|
return protocol + "://" + subdomain + hostname + port;
|
412
419
|
}
|
413
|
-
has_location() {
|
414
|
-
return this.is_not_nullable(window) && !!window.location;
|
415
|
-
}
|
416
420
|
current_host() {
|
417
|
-
|
418
|
-
|
419
|
-
}
|
420
|
-
else {
|
421
|
-
return null;
|
422
|
-
}
|
421
|
+
var _a;
|
422
|
+
return ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.hostname) || "";
|
423
423
|
}
|
424
424
|
current_protocol() {
|
425
|
-
|
426
|
-
|
427
|
-
}
|
428
|
-
else {
|
429
|
-
return "http";
|
430
|
-
}
|
425
|
+
var _a, _b;
|
426
|
+
return ((_b = (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.protocol) === null || _b === void 0 ? void 0 : _b.replace(/:$/, "")) || "http";
|
431
427
|
}
|
432
428
|
current_port() {
|
433
|
-
|
434
|
-
|
435
|
-
}
|
436
|
-
else {
|
437
|
-
return "";
|
438
|
-
}
|
429
|
+
var _a;
|
430
|
+
return ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.port) || "";
|
439
431
|
}
|
440
432
|
is_object(value) {
|
441
433
|
return (typeof value === "object" &&
|
data/lib/routes.ts
CHANGED
@@ -3,15 +3,51 @@
|
|
3
3
|
* Based on Rails RubyVariables.RAILS_VERSION routes of RubyVariables.APP_CLASS
|
4
4
|
*/
|
5
5
|
|
6
|
-
type
|
7
|
-
type
|
8
|
-
type
|
9
|
-
type
|
10
|
-
|
6
|
+
type Optional<T> = { [P in keyof T]?: T[P] | null };
|
7
|
+
type BaseRouteParameter = string | boolean | Date | number;
|
8
|
+
type MethodRouteParameter = BaseRouteParameter | (() => BaseRouteParameter);
|
9
|
+
type ModelRouteParameter =
|
10
|
+
| { id: MethodRouteParameter }
|
11
|
+
| { to_param: MethodRouteParameter }
|
12
|
+
| { toParam: MethodRouteParameter };
|
13
|
+
type RequiredRouteParameter = BaseRouteParameter | ModelRouteParameter;
|
14
|
+
type OptionalRouteParameter = undefined | null | RequiredRouteParameter;
|
15
|
+
type QueryRouteParameter =
|
16
|
+
| OptionalRouteParameter
|
17
|
+
| QueryRouteParameter[]
|
18
|
+
| { [k: string]: QueryRouteParameter };
|
19
|
+
type RouteParameters = Record<string, QueryRouteParameter>;
|
20
|
+
|
21
|
+
type Serializable = Record<string, unknown>;
|
22
|
+
type Serializer = (value: Serializable) => string;
|
23
|
+
type RouteHelperExtras = {
|
11
24
|
requiredParams(): string[];
|
12
25
|
toString(): string;
|
13
26
|
};
|
14
27
|
|
28
|
+
type RequiredParameters<T extends number> = T extends 1
|
29
|
+
? [RequiredRouteParameter]
|
30
|
+
: T extends 2
|
31
|
+
? [RequiredRouteParameter, RequiredRouteParameter]
|
32
|
+
: T extends 3
|
33
|
+
? [RequiredRouteParameter, RequiredRouteParameter, RequiredRouteParameter]
|
34
|
+
: T extends 4
|
35
|
+
? [
|
36
|
+
RequiredRouteParameter,
|
37
|
+
RequiredRouteParameter,
|
38
|
+
RequiredRouteParameter,
|
39
|
+
RequiredRouteParameter
|
40
|
+
]
|
41
|
+
: RequiredRouteParameter[];
|
42
|
+
|
43
|
+
type RouteHelperOptions<T extends string> = RouteOptions &
|
44
|
+
Optional<Record<T, OptionalRouteParameter>>;
|
45
|
+
|
46
|
+
type RouteHelper<T extends number = number, U extends string = string> = ((
|
47
|
+
...args: [...RequiredParameters<T>, RouteHelperOptions<U>]
|
48
|
+
) => string) &
|
49
|
+
RouteHelperExtras;
|
50
|
+
|
15
51
|
type RouteHelpers = Record<string, RouteHelper>;
|
16
52
|
|
17
53
|
type Configuration = {
|
@@ -21,7 +57,6 @@ type Configuration = {
|
|
21
57
|
serializer: Serializer;
|
22
58
|
};
|
23
59
|
|
24
|
-
type Optional<T> = { [P in keyof T]?: T[P] | null };
|
25
60
|
interface RouterExposedMethods {
|
26
61
|
config(): Configuration;
|
27
62
|
configure(arg: Partial<Configuration>): Configuration;
|
@@ -32,14 +67,16 @@ type KeywordUrlOptions = Optional<{
|
|
32
67
|
host: string;
|
33
68
|
protocol: string;
|
34
69
|
subdomain: string;
|
35
|
-
port: string;
|
70
|
+
port: string | number;
|
36
71
|
anchor: string;
|
37
72
|
trailing_slash: boolean;
|
38
73
|
}>;
|
39
74
|
|
40
|
-
type
|
75
|
+
type RouteOptions = KeywordUrlOptions & RouteParameters;
|
41
76
|
|
42
|
-
type
|
77
|
+
type PartsTable = Record<string, { r?: boolean; d?: OptionalRouteParameter }>;
|
78
|
+
|
79
|
+
type ModuleType = "CJS" | "AMD" | "UMD" | "ESM" | "DTS" | "NIL";
|
43
80
|
|
44
81
|
declare const RubyVariables: {
|
45
82
|
PREFIX: string;
|
@@ -93,7 +130,7 @@ RubyVariables.WRAPPER(
|
|
93
130
|
|
94
131
|
const Root = that;
|
95
132
|
type ModuleDefinition = {
|
96
|
-
define: (routes:
|
133
|
+
define: (routes: RouterExposedMethods) => void;
|
97
134
|
isSupported: () => boolean;
|
98
135
|
};
|
99
136
|
const ModuleReferences: Record<ModuleType, ModuleDefinition> = {
|
@@ -155,6 +192,15 @@ RubyVariables.WRAPPER(
|
|
155
192
|
return !!Root;
|
156
193
|
},
|
157
194
|
},
|
195
|
+
DTS: {
|
196
|
+
// Acts the same as ESM
|
197
|
+
define(routes) {
|
198
|
+
ModuleReferences.ESM.define(routes);
|
199
|
+
},
|
200
|
+
isSupported() {
|
201
|
+
return ModuleReferences.ESM.isSupported();
|
202
|
+
},
|
203
|
+
},
|
158
204
|
};
|
159
205
|
|
160
206
|
class ParametersMissing extends Error {
|
@@ -225,16 +271,16 @@ RubyVariables.WRAPPER(
|
|
225
271
|
return result.join("&");
|
226
272
|
}
|
227
273
|
|
228
|
-
serialize(object:
|
274
|
+
serialize(object: Serializable): string {
|
229
275
|
return this.configuration.serializer(object);
|
230
276
|
}
|
231
277
|
|
232
278
|
extract_options(
|
233
279
|
number_of_params: number,
|
234
|
-
args:
|
280
|
+
args: OptionalRouteParameter[]
|
235
281
|
): {
|
236
|
-
args:
|
237
|
-
options:
|
282
|
+
args: OptionalRouteParameter[];
|
283
|
+
options: RouteOptions;
|
238
284
|
} {
|
239
285
|
const last_el = args[args.length - 1];
|
240
286
|
if (
|
@@ -247,32 +293,27 @@ RubyVariables.WRAPPER(
|
|
247
293
|
}
|
248
294
|
return {
|
249
295
|
args: args.slice(0, args.length - 1),
|
250
|
-
options: last_el as
|
296
|
+
options: (last_el as any) as RouteOptions,
|
251
297
|
};
|
252
298
|
} else {
|
253
299
|
return { args, options: {} };
|
254
300
|
}
|
255
301
|
}
|
256
302
|
|
257
|
-
looks_like_serialized_model(
|
258
|
-
object: any
|
259
|
-
): object is
|
260
|
-
| { id: unknown }
|
261
|
-
| { to_param: unknown }
|
262
|
-
| { toParam: unknown } {
|
303
|
+
looks_like_serialized_model(object: any): object is ModelRouteParameter {
|
263
304
|
return (
|
264
305
|
this.is_object(object) &&
|
265
|
-
!
|
306
|
+
!(this.configuration.special_options_key in object) &&
|
266
307
|
("id" in object || "to_param" in object || "toParam" in object)
|
267
308
|
);
|
268
309
|
}
|
269
310
|
|
270
|
-
path_identifier(object:
|
311
|
+
path_identifier(object: QueryRouteParameter): string {
|
271
312
|
const result = this.unwrap_path_identifier(object);
|
272
313
|
return this.is_nullable(result) || result === false ? "" : "" + result;
|
273
314
|
}
|
274
315
|
|
275
|
-
unwrap_path_identifier(object:
|
316
|
+
unwrap_path_identifier(object: QueryRouteParameter): unknown {
|
276
317
|
let result: any = object;
|
277
318
|
if (!this.is_object(object)) {
|
278
319
|
return object;
|
@@ -293,7 +334,7 @@ RubyVariables.WRAPPER(
|
|
293
334
|
parts: string[],
|
294
335
|
required_params: string[],
|
295
336
|
default_options: RouteParameters,
|
296
|
-
call_arguments:
|
337
|
+
call_arguments: OptionalRouteParameter[]
|
297
338
|
): {
|
298
339
|
keyword_parameters: KeywordUrlOptions;
|
299
340
|
query_parameters: RouteParameters;
|
@@ -357,7 +398,7 @@ RubyVariables.WRAPPER(
|
|
357
398
|
default_options: RouteParameters,
|
358
399
|
route: RouteTree,
|
359
400
|
absolute: boolean,
|
360
|
-
args:
|
401
|
+
args: OptionalRouteParameter[]
|
361
402
|
): string {
|
362
403
|
const {
|
363
404
|
keyword_parameters,
|
@@ -467,9 +508,9 @@ RubyVariables.WRAPPER(
|
|
467
508
|
}
|
468
509
|
|
469
510
|
encode_segment(segment: string): string {
|
470
|
-
return segment.replace(UriEncoderSegmentRegex,
|
471
|
-
|
472
|
-
|
511
|
+
return segment.replace(UriEncoderSegmentRegex, (str) =>
|
512
|
+
encodeURIComponent(str)
|
513
|
+
);
|
473
514
|
}
|
474
515
|
|
475
516
|
is_optional_node(node: NodeTypes): boolean {
|
@@ -550,7 +591,7 @@ RubyVariables.WRAPPER(
|
|
550
591
|
default_options[part] = value;
|
551
592
|
}
|
552
593
|
}
|
553
|
-
const result = (...args:
|
594
|
+
const result = (...args: OptionalRouteParameter[]): string => {
|
554
595
|
return this.build_route(
|
555
596
|
parts,
|
556
597
|
required_params,
|
@@ -564,7 +605,7 @@ RubyVariables.WRAPPER(
|
|
564
605
|
result.toString = () => {
|
565
606
|
return this.build_path_spec(route_spec);
|
566
607
|
};
|
567
|
-
return result;
|
608
|
+
return result as any;
|
568
609
|
}
|
569
610
|
|
570
611
|
route_url(route_defaults: KeywordUrlOptions): string {
|
@@ -583,31 +624,16 @@ RubyVariables.WRAPPER(
|
|
583
624
|
return protocol + "://" + subdomain + hostname + port;
|
584
625
|
}
|
585
626
|
|
586
|
-
|
587
|
-
return
|
588
|
-
}
|
589
|
-
|
590
|
-
current_host(): string | null {
|
591
|
-
if (this.has_location()) {
|
592
|
-
return window.location.hostname;
|
593
|
-
} else {
|
594
|
-
return null;
|
595
|
-
}
|
627
|
+
current_host(): string {
|
628
|
+
return window?.location?.hostname || "";
|
596
629
|
}
|
597
630
|
|
598
631
|
current_protocol(): string {
|
599
|
-
|
600
|
-
return window.location.protocol.replace(/:$/, "");
|
601
|
-
} else {
|
602
|
-
return "http";
|
603
|
-
}
|
632
|
+
return window?.location?.protocol?.replace(/:$/, "") || "http";
|
604
633
|
}
|
634
|
+
|
605
635
|
current_port(): string {
|
606
|
-
|
607
|
-
return window.location.port;
|
608
|
-
} else {
|
609
|
-
return "";
|
610
|
-
}
|
636
|
+
return window?.location?.port || "";
|
611
637
|
}
|
612
638
|
|
613
639
|
is_object(value: unknown): value is Record<string, unknown> {
|
@@ -694,7 +720,7 @@ RubyVariables.WRAPPER(
|
|
694
720
|
config: (): Configuration => {
|
695
721
|
return Utils.config();
|
696
722
|
},
|
697
|
-
serialize: (object:
|
723
|
+
serialize: (object: Serializable): string => {
|
698
724
|
return Utils.serialize(object);
|
699
725
|
},
|
700
726
|
...RubyVariables.ROUTES_OBJECT,
|
data/lib/tasks/js_routes.rake
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
namespace :js do
|
2
|
-
desc "Make a js file
|
2
|
+
desc "Make a js file with all rails route URL helpers"
|
3
3
|
task routes: :environment do
|
4
4
|
require "js-routes"
|
5
|
-
|
6
5
|
JsRoutes.generate!
|
7
6
|
end
|
7
|
+
|
8
|
+
namespace :routes do
|
9
|
+
desc "Make a js file with all rails route URL helpers and typescript definitions for them"
|
10
|
+
task typescript: "js:routes" do
|
11
|
+
JsRoutes.definitions!
|
12
|
+
end
|
13
|
+
end
|
8
14
|
end
|
@@ -0,0 +1,114 @@
|
|
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;
|
80
|
+
export const configure: RouterExposedMethods['configure'];
|
81
|
+
|
82
|
+
export const config: RouterExposedMethods['config'];
|
83
|
+
|
84
|
+
export const serialize: RouterExposedMethods['serialize'];
|
85
|
+
|
86
|
+
/**
|
87
|
+
* Generates rails route to
|
88
|
+
* /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
|
89
|
+
* @param {any} inbox_id
|
90
|
+
* @param {any} message_id
|
91
|
+
* @param {any} id
|
92
|
+
* @param {object | undefined} options
|
93
|
+
* @returns {string} route path
|
94
|
+
*/
|
95
|
+
export const inbox_message_attachment_path: ((
|
96
|
+
inbox_id: RequiredRouteParameter,
|
97
|
+
message_id: RequiredRouteParameter,
|
98
|
+
id: RequiredRouteParameter,
|
99
|
+
options?: {format?: OptionalRouteParameter} & RouteOptions
|
100
|
+
) => string) & RouteHelperExtras;
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Generates rails route to
|
104
|
+
* /inboxes(.:format)
|
105
|
+
* @param {object | undefined} options
|
106
|
+
* @returns {string} route path
|
107
|
+
*/
|
108
|
+
export const inboxes_path: ((
|
109
|
+
options?: {format?: OptionalRouteParameter} & RouteOptions
|
110
|
+
) => string) & RouteHelperExtras;
|
111
|
+
|
112
|
+
// By some reason this line prevents all types in a file
|
113
|
+
// from being automatically exported
|
114
|
+
export {};
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import {
|
2
|
+
inbox_message_attachment_path,
|
3
|
+
inboxes_path,
|
4
|
+
serialize,
|
5
|
+
configure,
|
6
|
+
config,
|
7
|
+
} from "./routes.spec";
|
8
|
+
|
9
|
+
// Route Helpers
|
10
|
+
inboxes_path();
|
11
|
+
inboxes_path({
|
12
|
+
locale: "en",
|
13
|
+
search: {
|
14
|
+
q: "ukraine",
|
15
|
+
page: 3,
|
16
|
+
keywords: ["large", "small", { advanced: true }],
|
17
|
+
},
|
18
|
+
});
|
19
|
+
|
20
|
+
inbox_message_attachment_path(1, "2", true);
|
21
|
+
inbox_message_attachment_path(
|
22
|
+
{ id: 1 },
|
23
|
+
{ to_param: () => "2" },
|
24
|
+
{ toParam: () => true }
|
25
|
+
);
|
26
|
+
inbox_message_attachment_path(1, "2", true, { format: "json" });
|
27
|
+
inboxes_path.toString();
|
28
|
+
inboxes_path.requiredParams();
|
29
|
+
|
30
|
+
// serialize test
|
31
|
+
const SerializerArgument = {
|
32
|
+
locale: "en",
|
33
|
+
search: {
|
34
|
+
q: "ukraine",
|
35
|
+
page: 3,
|
36
|
+
keywords: ["large", "small", { advanced: true }],
|
37
|
+
},
|
38
|
+
};
|
39
|
+
serialize(SerializerArgument);
|
40
|
+
config().serializer(SerializerArgument);
|
41
|
+
|
42
|
+
// configure test
|
43
|
+
configure({
|
44
|
+
default_url_options: { port: 1, host: null },
|
45
|
+
prefix: "",
|
46
|
+
special_options_key: "_options",
|
47
|
+
serializer: (value) => JSON.stringify(value),
|
48
|
+
});
|
49
|
+
|
50
|
+
// config tests
|
51
|
+
const Config = config();
|
52
|
+
console.log(
|
53
|
+
Config.prefix,
|
54
|
+
Config.default_url_options,
|
55
|
+
Config.special_options_key
|
56
|
+
);
|
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
require "active_support/core_ext/string/strip"
|
3
|
+
require "fileutils"
|
4
|
+
require "open3"
|
5
|
+
require "spec_helper"
|
6
|
+
|
7
|
+
describe JsRoutes, "compatibility with DTS" do
|
8
|
+
|
9
|
+
OPTIONS = {module_type: 'DTS', include: [/^inboxes$/, /^inbox_message_attachment$/]}
|
10
|
+
let(:extra_options) do
|
11
|
+
{}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:generated_js) do
|
15
|
+
JsRoutes.generate({**OPTIONS, **extra_options})
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when file is generated" do
|
19
|
+
let(:dir_name) do
|
20
|
+
File.expand_path(__dir__ + "/dts")
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:file_name) do
|
24
|
+
dir_name + "/routes.spec.d.ts"
|
25
|
+
end
|
26
|
+
|
27
|
+
before do
|
28
|
+
FileUtils.mkdir_p(dir_name)
|
29
|
+
File.write(file_name, generated_js)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "has no compile errors", :slow do
|
33
|
+
command = "yarn tsc --strict --noEmit -p spec/tsconfig.json"
|
34
|
+
stdout, stderr, status = Open3.capture3(command)
|
35
|
+
expect(stderr).to eq("")
|
36
|
+
expect(stdout).to include("Done in ")
|
37
|
+
expect(status).to eq(0)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when camel case is enabled" do
|
42
|
+
let(:extra_options) { {camel_case: true} }
|
43
|
+
|
44
|
+
it "camelizes route name and arguments" do
|
45
|
+
|
46
|
+
expect(generated_js).to include(<<-DOC.rstrip)
|
47
|
+
/**
|
48
|
+
* Generates rails route to
|
49
|
+
* /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
|
50
|
+
* @param {any} inboxId
|
51
|
+
* @param {any} messageId
|
52
|
+
* @param {any} id
|
53
|
+
* @param {object | undefined} options
|
54
|
+
* @returns {string} route path
|
55
|
+
*/
|
56
|
+
export const inboxMessageAttachmentPath: ((
|
57
|
+
inboxId: RequiredRouteParameter,
|
58
|
+
messageId: RequiredRouteParameter,
|
59
|
+
id: RequiredRouteParameter,
|
60
|
+
options?: {format?: OptionalRouteParameter} & RouteOptions
|
61
|
+
) => string) & RouteHelperExtras;
|
62
|
+
DOC
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "exports route helpers" do
|
67
|
+
expect(generated_js).to include(<<-DOC.rstrip)
|
68
|
+
/**
|
69
|
+
* Generates rails route to
|
70
|
+
* /inboxes(.:format)
|
71
|
+
* @param {object | undefined} options
|
72
|
+
* @returns {string} route path
|
73
|
+
*/
|
74
|
+
export const inboxes_path: ((
|
75
|
+
options?: {format?: OptionalRouteParameter} & RouteOptions
|
76
|
+
) => string) & RouteHelperExtras;
|
77
|
+
DOC
|
78
|
+
expect(generated_js).to include(<<-DOC.rstrip)
|
79
|
+
/**
|
80
|
+
* Generates rails route to
|
81
|
+
* /inboxes/:inbox_id/messages/:message_id/attachments/:id(.:format)
|
82
|
+
* @param {any} inbox_id
|
83
|
+
* @param {any} message_id
|
84
|
+
* @param {any} id
|
85
|
+
* @param {object | undefined} options
|
86
|
+
* @returns {string} route path
|
87
|
+
*/
|
88
|
+
export const inbox_message_attachment_path: ((
|
89
|
+
inbox_id: RequiredRouteParameter,
|
90
|
+
message_id: RequiredRouteParameter,
|
91
|
+
id: RequiredRouteParameter,
|
92
|
+
options?: {format?: OptionalRouteParameter} & RouteOptions
|
93
|
+
) => string) & RouteHelperExtras
|
94
|
+
DOC
|
95
|
+
end
|
96
|
+
|
97
|
+
it "exports utility methods" do
|
98
|
+
expect(generated_js).to include("export const serialize: RouterExposedMethods['serialize'];")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "prevents all types from automatic export" do
|
102
|
+
expect(generated_js).to include("export {};")
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "compiled javascript asset" do
|
106
|
+
subject { ERB.new(File.read("app/assets/javascripts/js-routes.js.erb")).result(binding) }
|
107
|
+
it "should have js routes code" do
|
108
|
+
is_expected.to include("export const inbox_message_path = __jsr.r(")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
require 'spec_helper'
|
6
6
|
require "fileutils"
|
7
7
|
|
8
|
-
describe "after Rails initialization" do
|
8
|
+
describe "after Rails initialization", :slow do
|
9
9
|
NAME = Rails.root.join('app', 'assets', 'javascripts', 'routes.js').to_s
|
10
10
|
|
11
11
|
def sprockets_v3?
|
@@ -122,7 +122,7 @@ describe "after Rails initialization" do
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
describe "JSRoutes thread safety" do
|
125
|
+
describe "JSRoutes thread safety", :slow do
|
126
126
|
before do
|
127
127
|
begin
|
128
128
|
Rails.application.initialize!
|
data/spec/tsconfig.json
ADDED
data/tsconfig.json
CHANGED
@@ -3,14 +3,10 @@
|
|
3
3
|
"target": "es2019",
|
4
4
|
"lib": ["es2020", "dom"],
|
5
5
|
"module": "commonjs",
|
6
|
-
"outDir": "lib",
|
7
6
|
"sourceMap": false,
|
8
7
|
"declaration": true,
|
9
8
|
"allowSyntheticDefaultImports": true,
|
10
|
-
"resolveJsonModule":
|
11
|
-
"typeRoots": ["node_modules/@types", "./@types"],
|
12
|
-
|
13
|
-
"strict": true,
|
9
|
+
"resolveJsonModule": false,
|
14
10
|
"strictNullChecks": true,
|
15
11
|
"noImplicitAny": true,
|
16
12
|
"noImplicitThis": true,
|
@@ -22,11 +18,11 @@
|
|
22
18
|
"forceConsistentCasingInFileNames": true,
|
23
19
|
"emitDecoratorMetadata": true,
|
24
20
|
"experimentalDecorators": true
|
21
|
+
|
25
22
|
},
|
26
23
|
"ts-node": {
|
27
24
|
"files": true,
|
28
25
|
"transpileOnly": false
|
29
26
|
},
|
30
|
-
"include": ["
|
31
|
-
"exclude": ["node_modules", "**/thorn", "**/support", "**/tmp"]
|
27
|
+
"include": ["lib/*.ts"]
|
32
28
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: js-routes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdan Gusiev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 3.
|
47
|
+
version: 3.10.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 3.
|
54
|
+
version: 3.10.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,6 +183,9 @@ files:
|
|
183
183
|
- spec/js_routes/default_serializer_spec.rb
|
184
184
|
- spec/js_routes/module_types/amd_spec.rb
|
185
185
|
- spec/js_routes/module_types/cjs_spec.rb
|
186
|
+
- spec/js_routes/module_types/dts/routes.spec.d.ts
|
187
|
+
- spec/js_routes/module_types/dts/test.spec.ts
|
188
|
+
- spec/js_routes/module_types/dts_spec.rb
|
186
189
|
- spec/js_routes/module_types/esm_spec.rb
|
187
190
|
- spec/js_routes/module_types/umd_spec.rb
|
188
191
|
- spec/js_routes/options_spec.rb
|
@@ -190,6 +193,7 @@ files:
|
|
190
193
|
- spec/js_routes/zzz_last_post_rails_init_spec.rb
|
191
194
|
- spec/spec_helper.rb
|
192
195
|
- spec/support/routes.rb
|
196
|
+
- spec/tsconfig.json
|
193
197
|
- tsconfig.json
|
194
198
|
- yarn.lock
|
195
199
|
homepage: http://github.com/railsware/js-routes
|