js-routes 2.0.8 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f78bfaf0cba479c48245d0606cc10b262481e854f3fc82e7195a8b58548bf7a
4
- data.tar.gz: 118cafad50e73568ba4b1758821af072194e9570178f1f9caf067785e9f5a0f5
3
+ metadata.gz: 315ddd617bc6630cf5858afc5ba38d2c204f6167a7984ccdaf7171a50404e418
4
+ data.tar.gz: 676d2d36107ee524c07517143499173c0658731cc06d1c52753e3ab2f4e6cb81
5
5
  SHA512:
6
- metadata.gz: 95490b886a00861b0fe4a5e2419c67ec804bbb94a916edefe333acd2e0c94b407137952b97e4bf70d928ad1ebc5cf47333b5b5083f0dc227a43be2d3ebba7648
7
- data.tar.gz: 666d2862d8a86e760176afdfdd62711a34202a4725d08609e5f5bf69732becb8829826ddeccaca0f8cacffa6a78022e69a05872ea26ce550e7352a9bfde0d0e4
6
+ metadata.gz: 6c7f715e9afd02d1daebb882381e328595beca59a6a6d8c10a3a1518801522090e986c6b362174aaa9c51faf91508ee8e1cc6fff8ba118a08c32eb26c7205ba1
7
+ data.tar.gz: 7f70bfa95a1fb42092f20118bb3f22f07e459ccc6f95b8d3b0651faf0457266152465873da6a4dfddc4d52df006d6f5b991e3608a083c1eb524fef5ed77ff0c8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  ## master
2
2
 
3
+ ## v2.2.0
4
+
5
+ * Use Rack Middleware to automatically update routes file in development [#288](https://github.com/railsware/js-routes/issues/288)
6
+ * This setup is now a default recommended due to lack of any downside comparing to [ERB Loader](./Readme.md#webpacker) and [Manual Setup](./Readme.md#advanced-setup)
7
+
8
+ ## v2.1.3
9
+
10
+ * Fix `default_url_options` bug. [#290](https://github.com/railsware/js-routes/issues/290)
11
+
12
+ ## v2.1.2
13
+
14
+ * Improve browser window object detection. [#287](https://github.com/railsware/js-routes/issues/287)
15
+
16
+ ## v2.1.1
17
+
18
+ * Added webpacker generator `./bin/rails generate js_routes:webpacker`
19
+ * Reorganized Readme to describe different setups with their pros and cons more clearly
20
+
21
+ ## v2.1.0
22
+
23
+ * Support typescript defintions file aka `routes.d.ts`. See [Readme.md](./Readme.md#definitions) for more information.
24
+
3
25
  ## v2.0.8
4
26
 
5
27
  * Forbid usage of `namespace` option if `module_type` is not `nil`. [#281](https://github.com/railsware/js-routes/issues/281).
data/Readme.md CHANGED
@@ -16,36 +16,50 @@ gem "js-routes"
16
16
 
17
17
  ## Setup
18
18
 
19
+ There are 3 possible ways to setup JsRoutes:
20
+
21
+ * [Quick and easy](#quick-start)
22
+ * Uses Rack Middleware to automatically update routes locally
23
+ * Works great for a simple Rails application
24
+ * [Webpacker](#webpacker) automatic updates
25
+ * Requires ESM module system (the default)
26
+ * Doesn't support typescript definitions
27
+ * [Advanced Setup](#advanced-setup)
28
+ * Allows very custom setups
29
+ * [Sprockets](#sprockets) legacy
30
+ * Deprecated and not recommended for modern apps
31
+
32
+ <div id='quick-start'></div>
33
+
19
34
  ### Quick Start
20
35
 
36
+ Setup [Rack Middleware](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack) to automatically generate and maintain `routes.js` file and corresponding [Typescript definitions](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html) `routes.d.ts`:
37
+
21
38
  Run:
22
39
 
23
- ```
24
- rake js:routes
40
+ ``` sh
41
+ rails generate js_routes:middleware
25
42
  ```
26
43
 
27
- Make routes available globally in `app/javascript/packs/application.js`:
28
44
 
29
- ``` javascript
30
- import * as Routes from 'routes';
31
- window.Routes = Routes;
32
- ```
45
+ <div id='webpacker'></div>
33
46
 
34
- Individual routes can be imported using:
47
+ ### Webpacker + automatic updates - Typescript
35
48
 
36
- ``` javascript
37
- import {edit_post_path} from 'routes';
38
- console.log(edit_post_path(1))
39
- ```
49
+ **IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
40
50
 
41
- **Note**: that this setup requires `rake js:routes` to be run each time routes file is updated.
42
51
 
43
- <div id='webpacker'></div>
52
+ #### Use a Generator
53
+
54
+ Run a command:
44
55
 
45
- #### Webpacker + automatic updates
56
+ ``` sh
57
+ ./bin/rails generate js_routes:webpacker
58
+ ```
46
59
 
60
+ #### Setup manually
47
61
 
48
- This setup can automatically update your routes without `rake js:routes` being called manually.
62
+ The routes files can be automatically updated without `rake` task being called manually.
49
63
  It requires [rails-erb-loader](https://github.com/usabilityhub/rails-erb-loader) npm package to work.
50
64
 
51
65
  Add `erb` loader to webpacker:
@@ -59,16 +73,16 @@ Create webpack ERB config `config/webpack/loaders/erb.js`:
59
73
 
60
74
  ``` javascript
61
75
  module.exports = {
62
- test: /\.js\.erb$/,
63
- enforce: 'pre',
64
- exclude: /node_modules/,
65
- use: [{
66
- loader: 'rails-erb-loader',
67
- options: {
68
- runner: (/^win/.test(process.platform) ? 'ruby ' : '') + 'bin/rails runner'
69
- }
70
- }]
71
- }
76
+ module: {
77
+ rules: [
78
+ {
79
+ test: /\.erb$/,
80
+ enforce: 'pre',
81
+ loader: 'rails-erb-loader'
82
+ },
83
+ ]
84
+ }
85
+ };
72
86
  ```
73
87
 
74
88
  Enable `erb` extension in `config/webpack/environment.js`:
@@ -91,7 +105,75 @@ import * as Routes from 'routes.js.erb';
91
105
  window.Routes = Routes;
92
106
  ```
93
107
 
94
- #### Sprockets (Deprecated)
108
+ <div id='advanced-setup'></div>
109
+
110
+ ### Advanced Setup
111
+
112
+ **IMPORTANT**: that this setup requires the JS routes file to be updates manually
113
+
114
+ You can run every time you want to generate a routes file:
115
+
116
+ ``` sh
117
+ rake js:routes
118
+ # OR for typescript support
119
+ rake js:routes:typescript
120
+ ```
121
+
122
+ In case you need multiple route files for different parts of your application, you have to create the files manually.
123
+ If your application has an `admin` and an `application` namespace for example:
124
+
125
+ ``` erb
126
+ // app/javascript/admin/routes.js.erb
127
+ <%= JsRoutes.generate(include: /admin/) %>
128
+ ```
129
+
130
+ ``` erb
131
+ // app/javascript/customer/routes.js.erb
132
+ <%= JsRoutes.generate(exclude: /admin/) %>
133
+ ```
134
+
135
+ You can manipulate the generated helper manually by injecting ruby into javascript:
136
+
137
+ ``` erb
138
+ export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
139
+ ```
140
+
141
+ If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
142
+
143
+ ``` ruby
144
+ path = Rails.root.join("app/javascript")
145
+
146
+ JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
147
+ JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
148
+ JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
149
+ ```
150
+
151
+ <div id='definitions'></div>
152
+
153
+ #### Typescript Definitions
154
+
155
+ JsRoutes has typescript support out of the box.
156
+
157
+ Restrictions:
158
+
159
+ * Only available if `module_type` is set to `ESM` (strongly recommended and default).
160
+ * Webpacker Automatic Updates are not available because typescript compiler can not be configured to understand `.erb` extensions.
161
+
162
+ For the basic setup of typscript definitions see [Quick Start](#quick-start) setup.
163
+ More advanced setup would involve calling manually:
164
+
165
+ ``` ruby
166
+ JsRoutes.definitions! # to output to file
167
+ # or
168
+ JsRoutes.definitions # to output to string
169
+ ```
170
+
171
+ Even more advanced setups can be achieved by setting `module_type` to `DTS` inside [configuration](#module_type)
172
+ which will cause any `JsRoutes` instance to generate defintions instead of routes themselves.
173
+
174
+ <div id="sprockets"></div>
175
+
176
+ ### Sprockets (Deprecated)
95
177
 
96
178
  If you are using [Sprockets](https://github.com/rails/sprockets-rails) you may configure js-routes in the following way.
97
179
 
@@ -120,7 +202,7 @@ This cache is not flushed on server restart in development environment.
120
202
 
121
203
  **Important:** If routes.js file is not updated after some configuration change you need to run this rake task again.
122
204
 
123
- ### Configuration
205
+ ## Configuration
124
206
 
125
207
  You can configure JsRoutes in two main ways. Either with an initializer (e.g. `config/initializers/js_routes.rb`):
126
208
 
@@ -130,7 +212,7 @@ JsRoutes.setup do |config|
130
212
  end
131
213
  ```
132
214
 
133
- Or dynamically in JavaScript, although only [Formatter Options](#formatter-options) are supported (see below)
215
+ Or dynamically in JavaScript, although only [Formatter Options](#formatter-options) are supported:
134
216
 
135
217
  ``` js
136
218
  import * as Routes from 'routes'
@@ -140,14 +222,16 @@ Routes.configure({
140
222
  Routes.config(); // current config
141
223
  ```
142
224
 
143
- #### Available Options
225
+ ### Available Options
144
226
 
145
- ##### Generator Options
227
+ #### Generator Options
146
228
 
147
229
  Options to configure JavaScript file generator. These options are only available in Ruby context but not JavaScript.
148
230
 
231
+ <div id='module-type'></div>
232
+
149
233
  * `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`.
234
+ * Options: `ESM`, `UMD`, `CJS`, `AMD`, `DTS`, `nil`.
151
235
  * Default: `ESM`
152
236
  * `nil` option can be used in case you don't want generated code to export anything.
153
237
  * `documentation` - specifies if each route should be annotated with [JSDoc](https://jsdoc.app/) comment
@@ -176,7 +260,9 @@ Options to configure JavaScript file generator. These options are only available
176
260
  * `file` - a file location where generated routes are stored
177
261
  * Default: `app/javascript/routes.js` if setup with Webpacker, otherwise `app/assets/javascripts/routes.js` if setup with Sprockets.
178
262
 
179
- ##### Formatter Options
263
+ <div id="formatter-options"></div>
264
+
265
+ #### Formatter Options
180
266
 
181
267
  Options to configure routes formatting. These options are available both in Ruby and JavaScript context.
182
268
 
@@ -194,36 +280,6 @@ Options to configure routes formatting. These options are available both in Ruby
194
280
  * This option exists because JS doesn't provide a difference between an object and a hash
195
281
  * Default: `_options`
196
282
 
197
- ### Advanced Setup
198
-
199
- In case you need multiple route files for different parts of your application, you have to create the files manually.
200
- If your application has an `admin` and an `application` namespace for example:
201
-
202
- ``` erb
203
- // app/javascript/admin/routes.js.erb
204
- <%= JsRoutes.generate(include: /admin/) %>
205
- ```
206
-
207
- ``` erb
208
- // app/javascript/customer/routes.js.erb
209
- <%= JsRoutes.generate(exclude: /admin/) %>
210
- ```
211
-
212
- You can manipulate the generated helper manually by injecting ruby into javascript:
213
-
214
- ``` erb
215
- export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
216
- ```
217
-
218
- If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
219
-
220
- ``` ruby
221
- path = Rails.root.join("app/javascript")
222
-
223
- JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
224
- JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
225
- JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
226
- ```
227
283
 
228
284
  ## Usage
229
285
 
@@ -232,22 +288,34 @@ Configuration above will create a nice javascript file with `Routes` object that
232
288
  ``` js
233
289
  import * as Routes from 'routes';
234
290
 
235
- Routes.users_path() // => "/users"
236
- Routes.user_path(1) // => "/users/1"
237
- Routes.user_path(1, {format: 'json'}) // => "/users/1.json"
238
- Routes.user_path(1, {anchor: 'profile'}) // => "/users/1#profile"
239
- Routes.new_user_project_path(1, {format: 'json'}) // => "/users/1/projects/new.json"
240
- Routes.user_project_path(1,2, {q: 'hello', custom: true}) // => "/users/1/projects/2?q=hello&custom=true"
241
- Routes.user_project_path(1,2, {hello: ['world', 'mars']}) // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
242
- ```
291
+ Routes.users_path()
292
+ // => "/users"
243
293
 
244
- Using serialized object as route function arguments:
294
+ Routes.user_path(1)
295
+ // => "/users/1"
296
+
297
+ Routes.user_path(1, {format: 'json'})
298
+ // => "/users/1.json"
299
+
300
+ Routes.user_path(1, {anchor: 'profile'})
301
+ // => "/users/1#profile"
302
+
303
+ Routes.new_user_project_path(1, {format: 'json'})
304
+ // => "/users/1/projects/new.json"
305
+
306
+ Routes.user_project_path(1,2, {q: 'hello', custom: true})
307
+ // => "/users/1/projects/2?q=hello&custom=true"
308
+
309
+ Routes.user_project_path(1,2, {hello: ['world', 'mars']})
310
+ // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
245
311
 
246
- ``` js
247
312
  var google = {id: 1, name: "Google"};
248
- Routes.company_path(google) // => "/companies/1"
313
+ Routes.company_path(google)
314
+ // => "/companies/1"
315
+
249
316
  var google = {id: 1, name: "Google", to_param: "google"};
250
- Routes.company_path(google) // => "/companies/google"
317
+ Routes.company_path(google)
318
+ // => "/companies/google"
251
319
  ```
252
320
 
253
321
  In order to make routes helpers available globally:
@@ -256,7 +324,7 @@ In order to make routes helpers available globally:
256
324
  jQuery.extend(window, Routes)
257
325
  ```
258
326
 
259
- ## Get spec of routes and required params
327
+ ### Get spec of routes and required params
260
328
 
261
329
  Possible to get `spec` of route by function `toString`:
262
330
 
@@ -324,9 +392,9 @@ Split your routes into multiple files related to each section of your website li
324
392
 
325
393
  ``` javascript
326
394
  // admin-routes.js.erb
327
- <%= JsRoutes.generate(include: /^admin_/)
395
+ <%= JsRoutes.generate(include: /^admin_/) %>
328
396
  // app-routes.js.erb
329
- <%= JsRoutes.generate(exclude: /^admin_/)
397
+ <%= JsRoutes.generate(exclude: /^admin_/) %>
330
398
  ```
331
399
 
332
400
  ## Advantages over alternatives
@@ -341,14 +409,6 @@ Advantages of this one are:
341
409
  * Support Rails `#to_param` convention for seo optimized paths
342
410
  * Well tested
343
411
 
344
- ## Version 2 TODO
345
-
346
- * Add routes generation .d.ts file
347
- * Add config option on the output format: js, ts, d.ts
348
- * Add prettier
349
- * Add eslint
350
- * Add development guide
351
-
352
412
  #### Thanks to [contributors](https://github.com/railsware/js-routes/contributors)
353
413
 
354
414
  #### Have fun
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.0.0"])
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"])
@@ -0,0 +1,33 @@
1
+ require "rails/generators"
2
+
3
+ class JsRoutes::Generators::Middleware < Rails::Generators::Base
4
+
5
+ source_root File.expand_path(__FILE__ + "/../../../templates")
6
+
7
+ def create_middleware
8
+ copy_file "initializer.rb", "config/initializers/js_routes.rb"
9
+ # copy_file "erb.js", "config/webpack/loaders/erb.js"
10
+ # copy_file "routes.js.erb", "app/javascript/routes.js.erb"
11
+ # inject_into_file "config/webpack/environment.js", loader_content
12
+ inject_into_file "app/javascript/packs/application.js", pack_content
13
+ inject_into_file "config/environments/development.rb", middleware_content, before: /^end\n\z/
14
+ end
15
+
16
+ protected
17
+
18
+ def pack_content
19
+ <<-JS
20
+ import * as Routes from '../routes';
21
+ window.Routes = Routes;
22
+ JS
23
+ end
24
+
25
+ def middleware_content
26
+ <<-RB
27
+
28
+ # Automatically update routes.js file
29
+ # when routes.rb is changed
30
+ config.middleware.use(JsRoutes::Middleware)
31
+ RB
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require "rails/generators"
2
+
3
+ class JsRoutes::Generators::Webpacker < Rails::Generators::Base
4
+
5
+ source_root File.expand_path(__FILE__ + "/../../../templates")
6
+
7
+ def create_webpack
8
+ copy_file "initializer.rb", "config/initializers/js_routes.rb"
9
+ copy_file "erb.js", "config/webpack/loaders/erb.js"
10
+ copy_file "routes.js.erb", "app/javascript/routes.js.erb"
11
+ inject_into_file "config/webpack/environment.js", loader_content
12
+ inject_into_file "app/javascript/packs/application.js", pack_content
13
+ command = Rails.root.join("./bin/yarn add rails-erb-loader")
14
+ run command
15
+ end
16
+
17
+ protected
18
+
19
+ def pack_content
20
+ <<-JS
21
+ import * as Routes from 'routes.js.erb';
22
+ window.Routes = Routes;
23
+ JS
24
+ end
25
+
26
+ def loader_content
27
+ <<-JS
28
+ const erb = require('./loaders/erb')
29
+ environment.loaders.append('erb', erb)
30
+ JS
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ class JsRoutes
2
+ # A Rack middleware that automatically updates routes file
3
+ # whenever routes.rb is modified
4
+ #
5
+ # Inspired by
6
+ # https://github.com/fnando/i18n-js/blob/main/lib/i18n/js/middleware.rb
7
+ class Middleware
8
+ def initialize(app)
9
+ @app = app
10
+ @routes_file = Rails.root.join("config/routes.rb")
11
+ @mtime = nil
12
+ end
13
+
14
+ def call(env)
15
+ update_js_routes
16
+ @app.call(env)
17
+ end
18
+
19
+ protected
20
+
21
+ def update_js_routes
22
+ new_mtime = routes_mtime
23
+ unless new_mtime == @mtime
24
+ JsRoutes.generate!
25
+ JsRoutes.definitions!
26
+ @mtime = new_mtime
27
+ end
28
+ end
29
+
30
+ def routes_mtime
31
+ File.mtime(@routes_file)
32
+ rescue Errno::ENOENT
33
+ nil
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,3 @@
1
1
  class JsRoutes
2
- VERSION = "2.0.8"
2
+ VERSION = "2.2.0"
3
3
  end