js-routes 2.1.2 → 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/CHANGELOG.md +9 -0
- data/Readme.md +54 -52
- data/lib/js_routes/generators/middleware.rb +33 -0
- data/lib/js_routes/generators/webpacker.rb +1 -1
- data/lib/js_routes/middleware.rb +36 -0
- data/lib/js_routes/version.rb +1 -1
- data/lib/js_routes.rb +10 -5
- data/lib/routes.js +6 -4
- data/lib/routes.ts +7 -5
- data/spec/js_routes/module_types/amd_spec.rb +6 -5
- data/spec/js_routes/module_types/nil_spec.rb +86 -0
- data/spec/js_routes/module_types/umd_spec.rb +1 -1
- data/spec/js_routes/options_spec.rb +33 -51
- data/spec/spec_helper.rb +1 -2
- data/spec/support/routes.rb +1 -1
- metadata +5 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 315ddd617bc6630cf5858afc5ba38d2c204f6167a7984ccdaf7171a50404e418
         | 
| 4 | 
            +
              data.tar.gz: 676d2d36107ee524c07517143499173c0658731cc06d1c52753e3ab2f4e6cb81
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 6c7f715e9afd02d1daebb882381e328595beca59a6a6d8c10a3a1518801522090e986c6b362174aaa9c51faf91508ee8e1cc6fff8ba118a08c32eb26c7205ba1
         | 
| 7 | 
            +
              data.tar.gz: 7f70bfa95a1fb42092f20118bb3f22f07e459ccc6f95b8d3b0651faf0457266152465873da6a4dfddc4d52df006d6f5b991e3608a083c1eb524fef5ed77ff0c8
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,14 @@ | |
| 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 | 
            +
             | 
| 3 12 | 
             
            ## v2.1.2
         | 
| 4 13 |  | 
| 5 14 | 
             
            * Improve browser window object detection. [#287](https://github.com/railsware/js-routes/issues/287)
         | 
    
        data/Readme.md
    CHANGED
    
    | @@ -19,10 +19,13 @@ gem "js-routes" | |
| 19 19 | 
             
            There are 3 possible ways to setup JsRoutes:
         | 
| 20 20 |  | 
| 21 21 | 
             
            * [Quick and easy](#quick-start)
         | 
| 22 | 
            -
              *  | 
| 22 | 
            +
              * Uses Rack Middleware to automatically update routes locally
         | 
| 23 | 
            +
              * Works great for a simple Rails application
         | 
| 23 24 | 
             
            * [Webpacker](#webpacker) automatic updates
         | 
| 24 25 | 
             
              * Requires ESM module system (the default)
         | 
| 25 26 | 
             
              * Doesn't support typescript definitions
         | 
| 27 | 
            +
            * [Advanced Setup](#advanced-setup)
         | 
| 28 | 
            +
              * Allows very custom setups
         | 
| 26 29 | 
             
            * [Sprockets](#sprockets) legacy
         | 
| 27 30 | 
             
              * Deprecated and not recommended for modern apps
         | 
| 28 31 |  | 
| @@ -30,36 +33,20 @@ There are 3 possible ways to setup JsRoutes: | |
| 30 33 |  | 
| 31 34 | 
             
            ### Quick Start 
         | 
| 32 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 | 
            +
             | 
| 33 38 | 
             
            Run:
         | 
| 34 39 |  | 
| 35 40 | 
             
            ``` sh
         | 
| 36 | 
            -
             | 
| 37 | 
            -
            # OR for typescript support
         | 
| 38 | 
            -
            rake js:routes:typescript
         | 
| 41 | 
            +
            rails generate js_routes:middleware
         | 
| 39 42 | 
             
            ```
         | 
| 40 43 |  | 
| 41 | 
            -
            **IMPORTANT**: that this setup requires the rake task to be run each time routes file is updated.
         | 
| 42 | 
            -
             | 
| 43 | 
            -
            Individual routes can be imported using:
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            ``` javascript
         | 
| 46 | 
            -
            import {edit_post_path, posts_path} from 'routes';
         | 
| 47 | 
            -
            console.log(posts_path({format: 'json'})) // => "/posts.json"
         | 
| 48 | 
            -
            console.log(edit_post_path(1)) // => "/posts/1/edit"
         | 
| 49 | 
            -
            ```
         | 
| 50 | 
            -
             | 
| 51 | 
            -
            Make routes available globally in `app/javascript/packs/application.js`: 
         | 
| 52 | 
            -
             | 
| 53 | 
            -
            ``` javascript
         | 
| 54 | 
            -
            import * as Routes from 'routes';
         | 
| 55 | 
            -
            window.Routes = Routes;
         | 
| 56 | 
            -
            ```
         | 
| 57 44 |  | 
| 58 45 | 
             
            <div id='webpacker'></div>
         | 
| 59 46 |  | 
| 60 47 | 
             
            ### Webpacker + automatic updates - Typescript
         | 
| 61 48 |  | 
| 62 | 
            -
            **IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript]( | 
| 49 | 
            +
            **IMPORTANT**: this setup doesn't support IDE autocompletion with [Typescript](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html)
         | 
| 63 50 |  | 
| 64 51 |  | 
| 65 52 | 
             
            #### Use a Generator
         | 
| @@ -118,9 +105,52 @@ import * as Routes from 'routes.js.erb'; | |
| 118 105 | 
             
            window.Routes = Routes;
         | 
| 119 106 | 
             
            ```
         | 
| 120 107 |  | 
| 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 | 
            +
             | 
| 121 151 | 
             
            <div id='definitions'></div>
         | 
| 122 152 |  | 
| 123 | 
            -
             | 
| 153 | 
            +
            #### Typescript Definitions
         | 
| 124 154 |  | 
| 125 155 | 
             
            JsRoutes has typescript support out of the box. 
         | 
| 126 156 |  | 
| @@ -230,6 +260,8 @@ Options to configure JavaScript file generator. These options are only available | |
| 230 260 | 
             
            * `file` - a file location where generated routes are stored
         | 
| 231 261 | 
             
              * Default: `app/javascript/routes.js` if setup with Webpacker, otherwise `app/assets/javascripts/routes.js` if setup with Sprockets.
         | 
| 232 262 |  | 
| 263 | 
            +
            <div id="formatter-options"></div>
         | 
| 264 | 
            +
             | 
| 233 265 | 
             
            #### Formatter Options
         | 
| 234 266 |  | 
| 235 267 | 
             
            Options to configure routes formatting. These options are available both in Ruby and JavaScript context.
         | 
| @@ -248,36 +280,6 @@ Options to configure routes formatting. These options are available both in Ruby | |
| 248 280 | 
             
              * This option exists because JS doesn't provide a difference between an object and a hash
         | 
| 249 281 | 
             
              * Default: `_options`
         | 
| 250 282 |  | 
| 251 | 
            -
            ## Advanced Setup
         | 
| 252 | 
            -
             | 
| 253 | 
            -
            In case you need multiple route files for different parts of your application, you have to create the files manually.
         | 
| 254 | 
            -
            If your application has an `admin` and an `application` namespace for example:
         | 
| 255 | 
            -
             | 
| 256 | 
            -
            ``` erb
         | 
| 257 | 
            -
            // app/javascript/admin/routes.js.erb
         | 
| 258 | 
            -
            <%= JsRoutes.generate(include: /admin/) %>
         | 
| 259 | 
            -
            ```
         | 
| 260 | 
            -
             | 
| 261 | 
            -
            ``` erb
         | 
| 262 | 
            -
            // app/javascript/customer/routes.js.erb
         | 
| 263 | 
            -
            <%= JsRoutes.generate(exclude: /admin/) %>
         | 
| 264 | 
            -
            ```
         | 
| 265 | 
            -
             | 
| 266 | 
            -
            You can manipulate the generated helper manually by injecting ruby into javascript:
         | 
| 267 | 
            -
             | 
| 268 | 
            -
            ``` erb
         | 
| 269 | 
            -
            export const routes = <%= JsRoutes.generate(module_type: nil, namespace: nil) %>
         | 
| 270 | 
            -
            ```
         | 
| 271 | 
            -
             | 
| 272 | 
            -
            If you want to generate the routes files outside of the asset pipeline, you can use `JsRoutes.generate!`:
         | 
| 273 | 
            -
             | 
| 274 | 
            -
            ``` ruby
         | 
| 275 | 
            -
            path = Rails.root.join("app/javascript")
         | 
| 276 | 
            -
             | 
| 277 | 
            -
            JsRoutes.generate!("#{path}/app_routes.js", exclude: [/^admin_/, /^api_/])
         | 
| 278 | 
            -
            JsRoutes.generate!("#{path}/adm_routes.js", include: /^admin_/)
         | 
| 279 | 
            -
            JsRoutes.generate!("#{path}/api_routes.js", include: /^api_/, default_url_options: {format: "json"})
         | 
| 280 | 
            -
            ```
         | 
| 281 283 |  | 
| 282 284 | 
             
            ## Usage
         | 
| 283 285 |  | 
| @@ -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,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
         | 
    
        data/lib/js_routes/version.rb
    CHANGED
    
    
    
        data/lib/js_routes.rb
    CHANGED
    
    | @@ -132,7 +132,7 @@ class JsRoutes | |
| 132 132 | 
             
                end
         | 
| 133 133 |  | 
| 134 134 | 
             
                def definitions!(file_name = nil, **opts)
         | 
| 135 | 
            -
                  file_name ||= configuration.file&.sub | 
| 135 | 
            +
                  file_name ||= configuration.file&.sub(%r{(\.d)?\.(j|t)s\Z}, ".d.ts")
         | 
| 136 136 | 
             
                  generate!(file_name, module_type: 'DTS', **opts)
         | 
| 137 137 | 
             
                end
         | 
| 138 138 |  | 
| @@ -151,7 +151,7 @@ class JsRoutes | |
| 151 151 |  | 
| 152 152 | 
             
              def generate
         | 
| 153 153 | 
             
                # Ensure routes are loaded. If they're not, load them.
         | 
| 154 | 
            -
                if named_routes. | 
| 154 | 
            +
                if named_routes.empty? && application.respond_to?(:reload_routes!)
         | 
| 155 155 | 
             
                  application.reload_routes!
         | 
| 156 156 | 
             
                end
         | 
| 157 157 | 
             
                content = File.read(@configuration.source_file)
         | 
| @@ -273,12 +273,13 @@ export {}; | |
| 273 273 | 
             
              end
         | 
| 274 274 |  | 
| 275 275 | 
             
              def app_from_route(route)
         | 
| 276 | 
            +
                app = route.app
         | 
| 276 277 | 
             
                # rails engine in Rails 4.2 use additional
         | 
| 277 278 | 
             
                # ActionDispatch::Routing::Mapper::Constraints, which contain app
         | 
| 278 | 
            -
                if  | 
| 279 | 
            -
                   | 
| 279 | 
            +
                if app.respond_to?(:app) && app.respond_to?(:constraints)
         | 
| 280 | 
            +
                  app.app
         | 
| 280 281 | 
             
                else
         | 
| 281 | 
            -
                   | 
| 282 | 
            +
                  app
         | 
| 282 283 | 
             
                end
         | 
| 283 284 | 
             
              end
         | 
| 284 285 |  | 
| @@ -456,6 +457,10 @@ JS | |
| 456 457 | 
             
                  ].compact
         | 
| 457 458 | 
             
                end
         | 
| 458 459 | 
             
              end
         | 
| 460 | 
            +
              module Generators
         | 
| 461 | 
            +
              end
         | 
| 459 462 | 
             
            end
         | 
| 460 463 |  | 
| 464 | 
            +
            require "js_routes/middleware"
         | 
| 461 465 | 
             
            require "js_routes/generators/webpacker"
         | 
| 466 | 
            +
            require "js_routes/generators/middleware"
         | 
    
        data/lib/routes.js
    CHANGED
    
    | @@ -74,7 +74,7 @@ RubyVariables.WRAPPER((that) => { | |
| 74 74 | 
             
                            Utils.namespace(Root, RubyVariables.NAMESPACE, routes);
         | 
| 75 75 | 
             
                        },
         | 
| 76 76 | 
             
                        isSupported() {
         | 
| 77 | 
            -
                            return !!Root;
         | 
| 77 | 
            +
                            return !RubyVariables.NAMESPACE || !!Root;
         | 
| 78 78 | 
             
                        },
         | 
| 79 79 | 
             
                    },
         | 
| 80 80 | 
             
                    DTS: {
         | 
| @@ -205,7 +205,9 @@ RubyVariables.WRAPPER((that) => { | |
| 205 205 | 
             
                            throw new Error("Too many parameters provided for path");
         | 
| 206 206 | 
             
                        }
         | 
| 207 207 | 
             
                        let use_all_parts = args.length > required_params.length;
         | 
| 208 | 
            -
                        const parts_options = { | 
| 208 | 
            +
                        const parts_options = {
         | 
| 209 | 
            +
                            ...this.configuration.default_url_options,
         | 
| 210 | 
            +
                        };
         | 
| 209 211 | 
             
                        for (const key in options) {
         | 
| 210 212 | 
             
                            const value = options[key];
         | 
| 211 213 | 
             
                            if (!hasProp(options, key))
         | 
| @@ -446,7 +448,7 @@ RubyVariables.WRAPPER((that) => { | |
| 446 448 | 
             
                    namespace(object, namespace, routes) {
         | 
| 447 449 | 
             
                        const parts = (namespace === null || namespace === void 0 ? void 0 : namespace.split(".")) || [];
         | 
| 448 450 | 
             
                        if (parts.length === 0) {
         | 
| 449 | 
            -
                            return | 
| 451 | 
            +
                            return;
         | 
| 450 452 | 
             
                        }
         | 
| 451 453 | 
             
                        for (let index = 0; index < parts.length; index++) {
         | 
| 452 454 | 
             
                            const part = parts[index];
         | 
| @@ -454,7 +456,7 @@ RubyVariables.WRAPPER((that) => { | |
| 454 456 | 
             
                                object = object[part] || (object[part] = {});
         | 
| 455 457 | 
             
                            }
         | 
| 456 458 | 
             
                            else {
         | 
| 457 | 
            -
                                 | 
| 459 | 
            +
                                object[part] = routes;
         | 
| 458 460 | 
             
                            }
         | 
| 459 461 | 
             
                        }
         | 
| 460 462 | 
             
                    }
         | 
    
        data/lib/routes.ts
    CHANGED
    
    | @@ -190,7 +190,7 @@ RubyVariables.WRAPPER( | |
| 190 190 | 
             
                      Utils.namespace(Root, RubyVariables.NAMESPACE, routes);
         | 
| 191 191 | 
             
                    },
         | 
| 192 192 | 
             
                    isSupported() {
         | 
| 193 | 
            -
                      return !!Root;
         | 
| 193 | 
            +
                      return !RubyVariables.NAMESPACE || !!Root;
         | 
| 194 194 | 
             
                    },
         | 
| 195 195 | 
             
                  },
         | 
| 196 196 | 
             
                  DTS: {
         | 
| @@ -349,7 +349,9 @@ RubyVariables.WRAPPER( | |
| 349 349 | 
             
                      throw new Error("Too many parameters provided for path");
         | 
| 350 350 | 
             
                    }
         | 
| 351 351 | 
             
                    let use_all_parts = args.length > required_params.length;
         | 
| 352 | 
            -
                    const parts_options: RouteParameters = { | 
| 352 | 
            +
                    const parts_options: RouteParameters = {
         | 
| 353 | 
            +
                      ...this.configuration.default_url_options,
         | 
| 354 | 
            +
                    };
         | 
| 353 355 | 
             
                    for (const key in options) {
         | 
| 354 356 | 
             
                      const value = options[key];
         | 
| 355 357 | 
             
                      if (!hasProp(options, key)) continue;
         | 
| @@ -662,17 +664,17 @@ RubyVariables.WRAPPER( | |
| 662 664 | 
             
                    object: any,
         | 
| 663 665 | 
             
                    namespace: string | null | undefined,
         | 
| 664 666 | 
             
                    routes: unknown
         | 
| 665 | 
            -
                  ):  | 
| 667 | 
            +
                  ): void {
         | 
| 666 668 | 
             
                    const parts = namespace?.split(".") || [];
         | 
| 667 669 | 
             
                    if (parts.length === 0) {
         | 
| 668 | 
            -
                      return | 
| 670 | 
            +
                      return;
         | 
| 669 671 | 
             
                    }
         | 
| 670 672 | 
             
                    for (let index = 0; index < parts.length; index++) {
         | 
| 671 673 | 
             
                      const part = parts[index];
         | 
| 672 674 | 
             
                      if (index < parts.length - 1) {
         | 
| 673 675 | 
             
                        object = object[part] || (object[part] = {});
         | 
| 674 676 | 
             
                      } else {
         | 
| 675 | 
            -
                         | 
| 677 | 
            +
                        object[part] = routes;
         | 
| 676 678 | 
             
                      }
         | 
| 677 679 | 
             
                    }
         | 
| 678 680 | 
             
                  }
         | 
| @@ -3,11 +3,12 @@ require "spec_helper" | |
| 3 3 | 
             
            describe JsRoutes, "compatibility with AMD/require.js"  do
         | 
| 4 4 |  | 
| 5 5 | 
             
              before(:each) do
         | 
| 6 | 
            -
                evaljs(" | 
| 7 | 
            -
                evaljs(" | 
| 8 | 
            -
                evaljs(" | 
| 6 | 
            +
                evaljs("var global = this;", {force: true})
         | 
| 7 | 
            +
                evaljs("global.GlobalCheck = {};")
         | 
| 8 | 
            +
                evaljs("global.define = function (requirs, callback) { global.GlobalCheck['js-routes'] = callback.call(this); return global.GlobalCheck['js-routes']; };")
         | 
| 9 | 
            +
                evaljs("global.define.amd = { jQuery: true };")
         | 
| 9 10 | 
             
                strRequire =<<EOF
         | 
| 10 | 
            -
                 | 
| 11 | 
            +
                global.require = function (r, callback) {
         | 
| 11 12 | 
             
                  var allArgs, i;
         | 
| 12 13 |  | 
| 13 14 | 
             
                  allArgs = (function() {
         | 
| @@ -15,7 +16,7 @@ describe JsRoutes, "compatibility with AMD/require.js"  do | |
| 15 16 | 
             
                    _results = [];
         | 
| 16 17 | 
             
                    for (_i = 0, _len = r.length; _i < _len; _i++) {
         | 
| 17 18 | 
             
                      i = r[_i];
         | 
| 18 | 
            -
                      _results.push( | 
| 19 | 
            +
                      _results.push(global.GlobalCheck[i]);
         | 
| 19 20 | 
             
                    }
         | 
| 20 21 | 
             
                    return _results;
         | 
| 21 22 | 
             
                  })();
         | 
| @@ -0,0 +1,86 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe JsRoutes, "compatibility with NIL (legacy browser)" do
         | 
| 4 | 
            +
              let(:generated_js) do
         | 
| 5 | 
            +
                JsRoutes.generate(
         | 
| 6 | 
            +
                  module_type: nil,
         | 
| 7 | 
            +
                  include: /book|inboxes|inbox_message/,
         | 
| 8 | 
            +
                  **_options
         | 
| 9 | 
            +
                )
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              let(:_options) { {} }
         | 
| 13 | 
            +
              describe "generated js" do
         | 
| 14 | 
            +
                subject do
         | 
| 15 | 
            +
                  generated_js
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it "should call route function for each route" do
         | 
| 19 | 
            +
                  is_expected.to include("inboxes_path: __jsr.r(")
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                it "should have correct function without arguments signature" do
         | 
| 22 | 
            +
                  is_expected.to include('inboxes_path: __jsr.r({"format":{}}')
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                it "should have correct function with arguments signature" do
         | 
| 25 | 
            +
                  is_expected.to include('inbox_message_path: __jsr.r({"inbox_id":{"r":true},"id":{"r":true},"format":{}}')
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
                it "should have correct function signature with unordered hash" do
         | 
| 28 | 
            +
                  is_expected.to include('inbox_message_attachment_path: __jsr.r({"inbox_id":{"r":true},"message_id":{"r":true},"id":{"r":true},"format":{}}')
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe "inline generation" do
         | 
| 33 | 
            +
                let(:_options) { {namespace: nil} }
         | 
| 34 | 
            +
                before do
         | 
| 35 | 
            +
                  evaljs("const r = #{generated_js}")
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                it "should be possible" do
         | 
| 39 | 
            +
                  expect(evaljs("r.inboxes_path()")).to eq(test_routes.inboxes_path())
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              describe "namespace option" do
         | 
| 44 | 
            +
                let(:_options) { {namespace: "PHM"} }
         | 
| 45 | 
            +
                let(:_presetup) { "" }
         | 
| 46 | 
            +
                before do
         | 
| 47 | 
            +
                  evaljs("var window = this;")
         | 
| 48 | 
            +
                  evaljs(_presetup)
         | 
| 49 | 
            +
                  evaljs(generated_js)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
                it "should use this namespace for routing" do
         | 
| 52 | 
            +
                  expect(evaljs("window.Routes")).to be_nil
         | 
| 53 | 
            +
                  expect(evaljs("window.PHM.inboxes_path")).not_to be_nil
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                describe "is nested" do
         | 
| 57 | 
            +
                  context "and defined on client" do
         | 
| 58 | 
            +
                    let(:_presetup) { "window.PHM = {}" }
         | 
| 59 | 
            +
                    let(:_options) { {namespace: "PHM.Routes"} }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    it "should use this namespace for routing" do
         | 
| 62 | 
            +
                      expect(evaljs("PHM.Routes.inboxes_path")).not_to be_nil
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  context "but undefined on client" do
         | 
| 67 | 
            +
                    let(:_options) { {namespace: "PHM.Routes"} }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    it "should initialize namespace" do
         | 
| 70 | 
            +
                      expect(evaljs("window.PHM.Routes.inboxes_path")).not_to be_nil
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  context "and some parts are defined" do
         | 
| 75 | 
            +
                    let(:_presetup) { "window.PHM = { Utils: {} };" }
         | 
| 76 | 
            +
                    let(:_options) { {namespace: "PHM.Routes"} }
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    it "should not overwrite existing parts" do
         | 
| 79 | 
            +
                      expect(evaljs("window.PHM.Utils")).not_to be_nil
         | 
| 80 | 
            +
                      expect(evaljs("window.PHM.Routes.inboxes_path")).not_to be_nil
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
            end
         | 
| 86 | 
            +
             | 
| @@ -188,55 +188,19 @@ describe JsRoutes, "options" do | |
| 188 188 | 
             
                expect(evaljs("Routes.no_format_path({format: 'json'})")).to eq(test_routes.no_format_path(format: 'json'))
         | 
| 189 189 | 
             
              end
         | 
| 190 190 |  | 
| 191 | 
            -
              describe "namespace option" do
         | 
| 192 | 
            -
                let(:_options) { {:namespace => "PHM"} }
         | 
| 193 | 
            -
                it "should use this namespace for routing" do
         | 
| 194 | 
            -
                  expect(evaljs("window.Routes")).to be_nil
         | 
| 195 | 
            -
                  expect(evaljs("PHM.inbox_path")).not_to be_nil
         | 
| 196 | 
            -
                end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                context "is nil" do
         | 
| 199 | 
            -
                  let(:_options) { {:namespace => nil, include: /^inbox$/} }
         | 
| 200 | 
            -
                  it "should use this namespace for routing" do
         | 
| 201 | 
            -
                    evaljs("window.zz = #{generated_js}")
         | 
| 202 | 
            -
                    expect(evaljs("window.zz.inbox_path")).not_to be_nil
         | 
| 203 | 
            -
                  end
         | 
| 204 | 
            -
             | 
| 205 | 
            -
                end
         | 
| 206 | 
            -
             | 
| 207 | 
            -
                describe "is nested" do
         | 
| 208 | 
            -
                  context "and defined on client" do
         | 
| 209 | 
            -
                    let(:_presetup) { "window.PHM = {}" }
         | 
| 210 | 
            -
                    let(:_options) { {:namespace => "PHM.Routes"} }
         | 
| 211 | 
            -
                    it "should use this namespace for routing" do
         | 
| 212 | 
            -
                      expect(evaljs("PHM.Routes.inbox_path")).not_to be_nil
         | 
| 213 | 
            -
                    end
         | 
| 214 | 
            -
                  end
         | 
| 215 | 
            -
             | 
| 216 | 
            -
                  context "but undefined on client" do
         | 
| 217 | 
            -
                    let(:_options) { {:namespace => "PHM.Routes"} }
         | 
| 218 | 
            -
                    it "should initialize namespace" do
         | 
| 219 | 
            -
                      expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
         | 
| 220 | 
            -
                    end
         | 
| 221 | 
            -
                  end
         | 
| 222 | 
            -
             | 
| 223 | 
            -
                  context "and some parts are defined" do
         | 
| 224 | 
            -
                    let(:_presetup) { "window.PHM = { Utils: {} };" }
         | 
| 225 | 
            -
                    let(:_options) { {:namespace => "PHM.Routes"} }
         | 
| 226 | 
            -
                    it "should not overwrite existing parts" do
         | 
| 227 | 
            -
                      expect(evaljs("window.PHM.Utils")).not_to be_nil
         | 
| 228 | 
            -
                      expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
         | 
| 229 | 
            -
                    end
         | 
| 230 | 
            -
                  end
         | 
| 231 | 
            -
                end
         | 
| 232 | 
            -
              end
         | 
| 233 | 
            -
             | 
| 234 191 | 
             
              describe "default_url_options" do
         | 
| 235 192 | 
             
                context "with optional route parts" do
         | 
| 236 | 
            -
                  context "provided" do
         | 
| 193 | 
            +
                  context "provided by the default_url_options" do
         | 
| 237 194 | 
             
                    let(:_options) { { :default_url_options => { :optional_id => "12", :format => "json" } } }
         | 
| 238 | 
            -
                    it "should use this  | 
| 239 | 
            -
                      expect(evaljs("Routes.things_path()")).to eq(test_routes.things_path)
         | 
| 195 | 
            +
                    it "should use this options to fill optional parameters" do
         | 
| 196 | 
            +
                      expect(evaljs("Routes.things_path()")).to eq(test_routes.things_path(12))
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                  context "provided inline by the method parameters" do
         | 
| 201 | 
            +
                    let(:options) { { :default_url_options => { :optional_id => "12" } } }
         | 
| 202 | 
            +
                    it "should overwrite the default_url_options" do
         | 
| 203 | 
            +
                      expect(evaljs("Routes.things_path({ optional_id: 34 })")).to eq(test_routes.things_path(optional_id: 34))
         | 
| 240 204 | 
             
                    end
         | 
| 241 205 | 
             
                  end
         | 
| 242 206 |  | 
| @@ -249,12 +213,25 @@ describe JsRoutes, "options" do | |
| 249 213 | 
             
                end
         | 
| 250 214 |  | 
| 251 215 | 
             
                context "with required route parts" do
         | 
| 252 | 
            -
                  let(:_options) { {:default_url_options => {:inbox_id => "12"}} }
         | 
| 253 | 
            -
                  it "should use this  | 
| 216 | 
            +
                  let(:_options) { { :default_url_options => { :inbox_id => "12" } } }
         | 
| 217 | 
            +
                  it "should use this options to fill optional parameters" do
         | 
| 254 218 | 
             
                    expect(evaljs("Routes.inbox_messages_path()")).to eq(test_routes.inbox_messages_path)
         | 
| 255 219 | 
             
                  end
         | 
| 256 220 | 
             
                end
         | 
| 257 221 |  | 
| 222 | 
            +
                context "with optional and required route parts" do
         | 
| 223 | 
            +
                  let(:_options) { {:default_url_options => { :optional_id => "12" } } }
         | 
| 224 | 
            +
                  it "should use this options to fill the optional parameters" do
         | 
| 225 | 
            +
                    expect(evaljs("Routes.thing_path(1)")).to eq test_routes.thing_path(1, { optional_id: "12" })
         | 
| 226 | 
            +
                  end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                  context "when passing options that do not have defaults" do
         | 
| 229 | 
            +
                    it "should use this options to fill the optional parameters" do
         | 
| 230 | 
            +
                      expect(evaljs("Routes.thing_path(1, { format: 'json' })")).to eq test_routes.thing_path(1, { optional_id: "12", format: "json" } ) # test_routes.thing_path needs optional_id here to generate the correct route. Not sure why.
         | 
| 231 | 
            +
                    end
         | 
| 232 | 
            +
                  end
         | 
| 233 | 
            +
                end
         | 
| 234 | 
            +
             | 
| 258 235 | 
             
                context "when overwritten on JS level" do
         | 
| 259 236 | 
             
                    let(:_options) { { :default_url_options => { :format => "json" } } }
         | 
| 260 237 | 
             
                  it "uses JS defined value" do
         | 
| @@ -421,8 +398,14 @@ describe JsRoutes, "options" do | |
| 421 398 | 
             
                    host
         | 
| 422 399 | 
             
                  end
         | 
| 423 400 |  | 
| 424 | 
            -
                   | 
| 425 | 
            -
                     | 
| 401 | 
            +
                  let(:_presetup) do
         | 
| 402 | 
            +
                    window = {location: {
         | 
| 403 | 
            +
                      protocol: current_protocol,
         | 
| 404 | 
            +
                      hostname: current_hostname,
         | 
| 405 | 
            +
                      port: current_port,
         | 
| 406 | 
            +
                      host: current_host,
         | 
| 407 | 
            +
                    }}
         | 
| 408 | 
            +
                    "const window = #{ActiveSupport::JSON.encode(window)}"
         | 
| 426 409 | 
             
                  end
         | 
| 427 410 |  | 
| 428 411 | 
             
                  context "without specifying a default host" do
         | 
| @@ -434,7 +417,6 @@ describe JsRoutes, "options" do | |
| 434 417 | 
             
                      expect(evaljs("Routes.inbox_url(1)")).to eq("http://current.example.com#{test_routes.inbox_path(1)}")
         | 
| 435 418 | 
             
                      expect(evaljs("Routes.inbox_url(1, { test_key: \"test_val\" })")).to eq("http://current.example.com#{test_routes.inbox_path(1, :test_key => "test_val")}")
         | 
| 436 419 | 
             
                      expect(evaljs("Routes.new_session_url()")).to eq("https://current.example.com#{test_routes.new_session_path}")
         | 
| 437 | 
            -
             | 
| 438 420 | 
             
                    end
         | 
| 439 421 |  | 
| 440 422 | 
             
                    it "doesn't use current when specified in the route" do
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -108,11 +108,10 @@ RSpec.configure do |config| | |
| 108 108 | 
             
              end
         | 
| 109 109 |  | 
| 110 110 | 
             
              config.before :each do
         | 
| 111 | 
            -
                evaljs("var window = this;", {force: true})
         | 
| 112 | 
            -
             | 
| 113 111 | 
             
                log = proc do |*values|
         | 
| 114 112 | 
             
                  puts values.map(&:inspect).join(", ")
         | 
| 115 113 | 
             
                end
         | 
| 114 | 
            +
             | 
| 116 115 | 
             
                if defined?(JRUBY_VERSION)
         | 
| 117 116 | 
             
                  jscontext[:"console.log"] = lambda do |context, *values|
         | 
| 118 117 | 
             
                    log(*values)
         | 
    
        data/spec/support/routes.rb
    CHANGED
    
    | @@ -62,7 +62,7 @@ def draw_routes | |
| 62 62 |  | 
| 63 63 | 
             
                resources :portals, :port => 8080, only: [:index]
         | 
| 64 64 |  | 
| 65 | 
            -
                get '/with_defaults' => 'foo#foo', defaults: { bar: 'tested', format: :json }, format:  | 
| 65 | 
            +
                get '/with_defaults' => 'foo#foo', defaults: { bar: 'tested', format: :json }, format: true
         | 
| 66 66 |  | 
| 67 67 | 
             
                namespace :api, format: true, defaults: {format: 'json'} do
         | 
| 68 68 | 
             
                  get "/purchases" => "purchases#index"
         | 
    
        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. | 
| 4 | 
            +
              version: 2.2.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-12-21 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: railties
         | 
| @@ -171,7 +171,9 @@ files: | |
| 171 171 | 
             
            - lib/js-routes.rb
         | 
| 172 172 | 
             
            - lib/js_routes.rb
         | 
| 173 173 | 
             
            - lib/js_routes/engine.rb
         | 
| 174 | 
            +
            - lib/js_routes/generators/middleware.rb
         | 
| 174 175 | 
             
            - lib/js_routes/generators/webpacker.rb
         | 
| 176 | 
            +
            - lib/js_routes/middleware.rb
         | 
| 175 177 | 
             
            - lib/js_routes/version.rb
         | 
| 176 178 | 
             
            - lib/routes.d.ts
         | 
| 177 179 | 
             
            - lib/routes.js
         | 
| @@ -191,6 +193,7 @@ files: | |
| 191 193 | 
             
            - spec/js_routes/module_types/dts/test.spec.ts
         | 
| 192 194 | 
             
            - spec/js_routes/module_types/dts_spec.rb
         | 
| 193 195 | 
             
            - spec/js_routes/module_types/esm_spec.rb
         | 
| 196 | 
            +
            - spec/js_routes/module_types/nil_spec.rb
         | 
| 194 197 | 
             
            - spec/js_routes/module_types/umd_spec.rb
         | 
| 195 198 | 
             
            - spec/js_routes/options_spec.rb
         | 
| 196 199 | 
             
            - spec/js_routes/rails_routes_compatibility_spec.rb
         |