js-routes 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 242f329ab92abe8be4a2fa3790f72a3f161a6c2355b2392eae484a36a91d3a24
4
- data.tar.gz: 120e5191eccfe3a8978c89ecb690a4f93a62279b249c58bc84b9273fe3e900c7
3
+ metadata.gz: 54158654106dece477c1fdf36afa52b504a43b8210c4c8d30f98d41ccd0ef600
4
+ data.tar.gz: a67b36754269392839bb6d2e86a20899ec2575437ac9667f10cdd9feb7306185
5
5
  SHA512:
6
- metadata.gz: e1998fd3c98dff227905bfcd8a09be8bb6901d3da7293b60d1a6f11c3a2627c623372324a13010cbe425eb7b93781fa64db042c08e7b4123d4a50ec8bd8814b2
7
- data.tar.gz: 5395c808f148bd39a99de0ce748cbb3a57c27620f048764bfcf6a455ac6ce2bbc43e282f4c660ba019f8d4b5df39a316728bb673d56b2667aecb667dde82d91b
6
+ metadata.gz: 582b6a39a062f6fcfd7b2cb4a57b4fd4573e343f93d5751ef764b7e3617cb7243801caf61ee971224a2c1a41e43a2f51221e5d3a40c12d5db21af98f47467044
7
+ data.tar.gz: f54b26ed68ed8ef2a6b4ad5ebf2e0322bfbec7385756a8578b5c11c01eca646d42baa5634d16cef6d16520e3eed4d1b1a37260e4ade943ee568b6b4755153cea
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  ## master
2
2
 
3
+ ## v2.2.1
4
+
5
+ * Improve generator to update route files on `assets:precompile` and add them to `.gitignore by default` [#288](https://github.com/railsware/js-routes/issues/288#issuecomment-1012182815)
6
+
7
+ ## v2.2.0
8
+
9
+ * Use Rack Middleware to automatically update routes file in development [#288](https://github.com/railsware/js-routes/issues/288)
10
+ * 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)
11
+
12
+ ## v2.1.3
13
+
14
+ * Fix `default_url_options` bug. [#290](https://github.com/railsware/js-routes/issues/290)
15
+
16
+ ## v2.1.2
17
+
18
+ * Improve browser window object detection. [#287](https://github.com/railsware/js-routes/issues/287)
19
+
20
+ ## v2.1.1
21
+
22
+ * Added webpacker generator `./bin/rails generate js_routes:webpacker`
23
+ * Reorganized Readme to describe different setups with their pros and cons more clearly
24
+
3
25
  ## v2.1.0
4
26
 
5
27
  * Support typescript defintions file aka `routes.d.ts`. See [Readme.md](./Readme.md#definitions) for more information.
data/Readme.md CHANGED
@@ -16,40 +16,84 @@ gem "js-routes"
16
16
 
17
17
  ## Setup
18
18
 
19
+ There are several 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 ERB Loader](#webpacker)
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
 
21
- Run:
36
+ Setup [Rack Middleware](https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack)
37
+ to automatically generate and maintain `routes.js` file and corresponding
38
+ [Typescript definitions](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html) `routes.d.ts`:
39
+
40
+ #### Use a Generator
41
+
42
+ Run a command:
22
43
 
23
44
  ``` sh
24
- rake js:routes
25
- # OR for typescript support
26
- rake js:routes:typescript
45
+ rails generate js_routes:middleware
27
46
  ```
28
47
 
48
+ #### Setup Manually
29
49
 
30
- Individual routes can be imported using:
50
+ Add the following to `config/environments/development.rb`:
31
51
 
32
- ``` javascript
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"
52
+ ``` ruby
53
+ config.middleware.use(JsRoutes::Middleware)
36
54
  ```
37
55
 
38
- Make routes available globally in `app/javascript/packs/application.js`:
56
+ Use it in `app/javascript/packs/application.js`:
39
57
 
40
58
  ``` javascript
41
- import * as Routes from 'routes';
42
- window.Routes = Routes;
59
+ import * as Routes from '../routes';
60
+ // window.Routes = Routes;
61
+ alert(Routes.post_path(1))
43
62
  ```
44
63
 
45
- **Note**: that this setup requires `rake js:routes` to be run each time routes file is updated.
64
+ Upgrade `rake assets:precompile` to update js-routes files:
65
+
66
+ ``` ruby
67
+ namespace :assets do
68
+ task :precompile => "js:routes:typescript"
69
+ end
70
+ ```
71
+
72
+ Add js-routes files to `.gitignore`:
73
+
74
+ ```
75
+ /app/javascript/routes.js
76
+ /app/javascript/routes.d.ts
77
+ ```
46
78
 
47
79
  <div id='webpacker'></div>
48
80
 
49
- #### Webpacker + automatic updates
81
+ ### Webpacker ERB loader
82
+
83
+ **IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
84
+
50
85
 
86
+ #### Use a Generator
51
87
 
52
- This setup can automatically update your routes without `rake js:routes` being called manually.
88
+ Run a command:
89
+
90
+ ``` sh
91
+ ./bin/rails generate js_routes:webpacker
92
+ ```
93
+
94
+ #### Setup manually
95
+
96
+ The routes files can be automatically updated without `rake` task being called manually.
53
97
  It requires [rails-erb-loader](https://github.com/usabilityhub/rails-erb-loader) npm package to work.
54
98
 
55
99
  Add `erb` loader to webpacker:
@@ -63,16 +107,16 @@ Create webpack ERB config `config/webpack/loaders/erb.js`:
63
107
 
64
108
  ``` javascript
65
109
  module.exports = {
66
- test: /\.js\.erb$/,
67
- enforce: 'pre',
68
- exclude: /node_modules/,
69
- use: [{
70
- loader: 'rails-erb-loader',
71
- options: {
72
- runner: (/^win/.test(process.platform) ? 'ruby ' : '') + 'bin/rails runner'
73
- }
74
- }]
75
- }
110
+ module: {
111
+ rules: [
112
+ {
113
+ test: /\.erb$/,
114
+ enforce: 'pre',
115
+ loader: 'rails-erb-loader'
116
+ },
117
+ ]
118
+ }
119
+ };
76
120
  ```
77
121
 
78
122
  Enable `erb` extension in `config/webpack/environment.js`:
@@ -95,23 +139,77 @@ import * as Routes from 'routes.js.erb';
95
139
  window.Routes = Routes;
96
140
  ```
97
141
 
142
+ <div id='advanced-setup'></div>
143
+
144
+ ### Advanced Setup
145
+
146
+ **IMPORTANT**: that this setup requires the JS routes file to be updates manually
147
+
148
+ Routes file can be generated with a `rake` task:
149
+
150
+ ``` sh
151
+ rake js:routes
152
+ # OR for typescript support
153
+ rake js:routes:typescript
154
+ ```
155
+
156
+ In case you need multiple route files for different parts of your application, you have to create the files manually.
157
+ If your application has an `admin` and an `application` namespace for example:
158
+
159
+ **IMPORTANT**: Requires [Webpacker ERB Loader](#webpacker) setup.
160
+
161
+ ``` erb
162
+ // app/javascript/admin/routes.js.erb
163
+ <%= JsRoutes.generate(include: /admin/) %>
164
+ ```
165
+
166
+ ``` erb
167
+ // app/javascript/customer/routes.js.erb
168
+ <%= JsRoutes.generate(exclude: /admin/) %>
169
+ ```
170
+
171
+ You can manipulate the generated helper manually by injecting ruby into javascript:
172
+
173
+ ``` erb
174
+ export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
175
+ ```
176
+
177
+ If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
178
+
179
+ ``` ruby
180
+ path = Rails.root.join("app/javascript")
181
+
182
+ JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
183
+ JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
184
+ JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
185
+ ```
186
+
98
187
  <div id='definitions'></div>
99
188
 
100
189
  #### Typescript Definitions
101
190
 
102
- JsRoutes has typescript support out of the box. In order to generate typscript definitions file (aka `routes.d.ts`) you can call:
191
+ JsRoutes has typescript support out of the box.
192
+
193
+ Restrictions:
194
+
195
+ * Only available if `module_type` is set to `ESM` (strongly recommended and default).
196
+ * Webpacker Automatic Updates are not available because typescript compiler can not be configured to understand `.erb` extensions.
197
+
198
+ For the basic setup of typscript definitions see [Quick Start](#quick-start) setup.
199
+ More advanced setup would involve calling manually:
103
200
 
104
201
  ``` ruby
105
- JsRoutes.definitions!
202
+ JsRoutes.definitions! # to output to file
203
+ # or
204
+ JsRoutes.definitions # to output to string
106
205
  ```
107
206
 
108
- Or create an automatic updates file at `app/javascript/routes.d.ts.erb`:
207
+ Even more advanced setups can be achieved by setting `module_type` to `DTS` inside [configuration](#module_type)
208
+ which will cause any `JsRoutes` instance to generate defintions instead of routes themselves.
109
209
 
110
- ``` erb
111
- <%= JsRoutes.defintions %>
112
- ```
210
+ <div id="sprockets"></div>
113
211
 
114
- #### Sprockets (Deprecated)
212
+ ### Sprockets (Deprecated)
115
213
 
116
214
  If you are using [Sprockets](https://github.com/rails/sprockets-rails) you may configure js-routes in the following way.
117
215
 
@@ -140,7 +238,7 @@ This cache is not flushed on server restart in development environment.
140
238
 
141
239
  **Important:** If routes.js file is not updated after some configuration change you need to run this rake task again.
142
240
 
143
- ### Configuration
241
+ ## Configuration
144
242
 
145
243
  You can configure JsRoutes in two main ways. Either with an initializer (e.g. `config/initializers/js_routes.rb`):
146
244
 
@@ -150,7 +248,7 @@ JsRoutes.setup do |config|
150
248
  end
151
249
  ```
152
250
 
153
- Or dynamically in JavaScript, although only [Formatter Options](#formatter-options) are supported (see below)
251
+ Or dynamically in JavaScript, although only [Formatter Options](#formatter-options) are supported:
154
252
 
155
253
  ``` js
156
254
  import * as Routes from 'routes'
@@ -160,12 +258,14 @@ Routes.configure({
160
258
  Routes.config(); // current config
161
259
  ```
162
260
 
163
- #### Available Options
261
+ ### Available Options
164
262
 
165
- ##### Generator Options
263
+ #### Generator Options
166
264
 
167
265
  Options to configure JavaScript file generator. These options are only available in Ruby context but not JavaScript.
168
266
 
267
+ <div id='module-type'></div>
268
+
169
269
  * `module_type` - JavaScript module type for generated code. [Article](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm)
170
270
  * Options: `ESM`, `UMD`, `CJS`, `AMD`, `DTS`, `nil`.
171
271
  * Default: `ESM`
@@ -196,7 +296,9 @@ Options to configure JavaScript file generator. These options are only available
196
296
  * `file` - a file location where generated routes are stored
197
297
  * Default: `app/javascript/routes.js` if setup with Webpacker, otherwise `app/assets/javascripts/routes.js` if setup with Sprockets.
198
298
 
199
- ##### Formatter Options
299
+ <div id="formatter-options"></div>
300
+
301
+ #### Formatter Options
200
302
 
201
303
  Options to configure routes formatting. These options are available both in Ruby and JavaScript context.
202
304
 
@@ -214,36 +316,6 @@ Options to configure routes formatting. These options are available both in Ruby
214
316
  * This option exists because JS doesn't provide a difference between an object and a hash
215
317
  * Default: `_options`
216
318
 
217
- ### Advanced Setup
218
-
219
- In case you need multiple route files for different parts of your application, you have to create the files manually.
220
- If your application has an `admin` and an `application` namespace for example:
221
-
222
- ``` erb
223
- // app/javascript/admin/routes.js.erb
224
- <%= JsRoutes.generate(include: /admin/) %>
225
- ```
226
-
227
- ``` erb
228
- // app/javascript/customer/routes.js.erb
229
- <%= JsRoutes.generate(exclude: /admin/) %>
230
- ```
231
-
232
- You can manipulate the generated helper manually by injecting ruby into javascript:
233
-
234
- ``` erb
235
- export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
236
- ```
237
-
238
- If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
239
-
240
- ``` ruby
241
- path = Rails.root.join("app/javascript")
242
-
243
- JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
244
- JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
245
- JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
246
- ```
247
319
 
248
320
  ## Usage
249
321
 
@@ -252,22 +324,34 @@ Configuration above will create a nice javascript file with `Routes` object that
252
324
  ``` js
253
325
  import * as Routes from 'routes';
254
326
 
255
- Routes.users_path() // => "/users"
256
- Routes.user_path(1) // => "/users/1"
257
- Routes.user_path(1, {format: 'json'}) // => "/users/1.json"
258
- Routes.user_path(1, {anchor: 'profile'}) // => "/users/1#profile"
259
- Routes.new_user_project_path(1, {format: 'json'}) // => "/users/1/projects/new.json"
260
- Routes.user_project_path(1,2, {q: 'hello', custom: true}) // => "/users/1/projects/2?q=hello&custom=true"
261
- Routes.user_project_path(1,2, {hello: ['world', 'mars']}) // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
262
- ```
327
+ Routes.users_path()
328
+ // => "/users"
263
329
 
264
- Using serialized object as route function arguments:
330
+ Routes.user_path(1)
331
+ // => "/users/1"
332
+
333
+ Routes.user_path(1, {format: 'json'})
334
+ // => "/users/1.json"
335
+
336
+ Routes.user_path(1, {anchor: 'profile'})
337
+ // => "/users/1#profile"
338
+
339
+ Routes.new_user_project_path(1, {format: 'json'})
340
+ // => "/users/1/projects/new.json"
341
+
342
+ Routes.user_project_path(1,2, {q: 'hello', custom: true})
343
+ // => "/users/1/projects/2?q=hello&custom=true"
344
+
345
+ Routes.user_project_path(1,2, {hello: ['world', 'mars']})
346
+ // => "/users/1/projects/2?hello%5B%5D=world&hello%5B%5D=mars"
265
347
 
266
- ``` js
267
348
  var google = {id: 1, name: "Google"};
268
- Routes.company_path(google) // => "/companies/1"
349
+ Routes.company_path(google)
350
+ // => "/companies/1"
351
+
269
352
  var google = {id: 1, name: "Google", to_param: "google"};
270
- Routes.company_path(google) // => "/companies/google"
353
+ Routes.company_path(google)
354
+ // => "/companies/google"
271
355
  ```
272
356
 
273
357
  In order to make routes helpers available globally:
@@ -276,7 +360,7 @@ In order to make routes helpers available globally:
276
360
  jQuery.extend(window, Routes)
277
361
  ```
278
362
 
279
- ## Get spec of routes and required params
363
+ ### Get spec of routes and required params
280
364
 
281
365
  Possible to get `spec` of route by function `toString`:
282
366
 
@@ -361,14 +445,6 @@ Advantages of this one are:
361
445
  * Support Rails `#to_param` convention for seo optimized paths
362
446
  * Well tested
363
447
 
364
- ## Version 2 TODO
365
-
366
- * Add routes generation .d.ts file
367
- * Add config option on the output format: js, ts, d.ts
368
- * Add prettier
369
- * Add eslint
370
- * Add development guide
371
-
372
448
  #### Thanks to [contributors](https://github.com/railsware/js-routes/contributors)
373
449
 
374
450
  #### Have fun
@@ -0,0 +1,58 @@
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
+ inject_into_file "app/javascript/packs/application.js", pack_content
10
+ inject_into_file "config/environments/development.rb", middleware_content, before: /^end\n\z/
11
+ inject_into_file "Rakefile", rakefile_content
12
+ inject_into_file ".gitignore", gitignore_content
13
+ JsRoutes.generate!
14
+ JsRoutes.definitions!
15
+ end
16
+
17
+ protected
18
+
19
+ def pack_content
20
+ <<-JS
21
+ import * as Routes from '../routes';
22
+ window.Routes = Routes;
23
+ JS
24
+ end
25
+
26
+ def middleware_content
27
+ <<-RB
28
+
29
+ # Automatically update js-routes file
30
+ # when routes.rb is changed
31
+ config.middleware.use(JsRoutes::Middleware)
32
+ RB
33
+ end
34
+
35
+ def rakefile_content
36
+ <<-RB
37
+
38
+ # Update js-routes file before assets precompile
39
+ namespace :assets do
40
+ task :precompile => "js:routes:typescript"
41
+ end
42
+ RB
43
+ end
44
+
45
+ def gitignore_content
46
+ banner = <<-TXT
47
+
48
+ # Ignore automatically generated js-routes files.
49
+ TXT
50
+
51
+ banner + [
52
+ {},
53
+ {module_type: 'DTS'}
54
+ ].map do |config|
55
+ File.join('/', JsRoutes.new(config).configuration.output_file) + "\n"
56
+ end.join
57
+ end
58
+ 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