quilt_rails 1.5.0 → 1.6.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/README.md +274 -46
- data/lib/quilt_rails/trusted_ui_server_csrf_strategy.rb +25 -0
- data/lib/quilt_rails/version.rb +1 -1
- data/lib/quilt_rails.rb +1 -0
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7cb007cf5708ce9cc49b8eea19e79e8922faeaddf91223348962242c1ce03a8f
         | 
| 4 | 
            +
              data.tar.gz: d351101e370001003ce4f75c613922c72263998fad1d449f29ac023584112284
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: dc19e93667fc50d44613cc76d6a63ede39cd7b855850ab9c6e3257637754b066969351d17421f244ac5c6ffe75ee33f9e9363ab546f89bf80269ad3ffecb2840
         | 
| 7 | 
            +
              data.tar.gz: 61c9d32098b159d7a0b940b96ba02eb274e53dae54e252a25a6ed430c9446cbda9859e9e7ca15808f464833f015a1e32c6bf6e23d5addcdcc0a9c70bb5c49b62
         | 
    
        data/README.md
    CHANGED
    
    | @@ -2,47 +2,79 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            A turn-key solution for integrating server-rendered react into your Rails app using Quilt libraries.
         | 
| 4 4 |  | 
| 5 | 
            -
            This document focuses on Rails integration. For details of `@shopify/react-server`'s configuration and usage, see the [react-server documentation](/packages/react-server/README.md).
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
            ## Table of Contents
         | 
| 8 6 |  | 
| 9 7 | 
             
            1. [Quick Start](#quick-start)
         | 
| 8 | 
            +
               1. [Generate Rails boilerplate](#generate-rails-boilerplate)
         | 
| 9 | 
            +
               1. [Add Ruby dependencies](#add-ruby-dependencies)
         | 
| 10 | 
            +
               1. [Generate Quilt boilerplate](#generate-quilt-boilerplate)
         | 
| 11 | 
            +
               1. [Try it out](#try-it-out)
         | 
| 12 | 
            +
            1. [Manual Install](#manual-installation)
         | 
| 13 | 
            +
               1. [Install Dependencies](#install-dependencies)
         | 
| 14 | 
            +
               1. [Setup the Rails app](#setup-the-rails-app)
         | 
| 15 | 
            +
               1. [Add JavaScript](#add-javascript)
         | 
| 16 | 
            +
               1. [Run the server](#run-the-server)
         | 
| 17 | 
            +
            1. [Application Layout](#application-layout)
         | 
| 18 | 
            +
            1. [API](#api)
         | 
| 19 | 
            +
               1. [ReactRenderable](#reactrenderable)
         | 
| 20 | 
            +
               1. [Engine](#engine)
         | 
| 21 | 
            +
               1. [Generators](#generators)
         | 
| 10 22 | 
             
            1. [Advanced Use](#advanced-use)
         | 
| 23 | 
            +
               1. [Testing](#testing)
         | 
| 24 | 
            +
               1. [Interacting with the request and response in React code](#interacting-with-the-request-and-response-in-react-code)
         | 
| 25 | 
            +
               1. [Dealing with isomorphic state](#dealing-with-isomorphic-state)
         | 
| 26 | 
            +
               1. [Customizing the node server](#customizing-the-node-server)
         | 
| 11 27 |  | 
| 12 28 | 
             
            ## Quick Start
         | 
| 13 29 |  | 
| 30 | 
            +
            Using the magic of generators, we can spin up a basic app with a few console commands.
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            ### Generate Rails boilerplate
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            `dev init`
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            When prompted, choose `rails`. This will generate a basic Rails application scaffold.
         | 
| 37 | 
            +
             | 
| 14 38 | 
             
            ### Add Ruby dependencies
         | 
| 15 39 |  | 
| 16 40 | 
             
            `bundle add sewing_kit quilt_rails`
         | 
| 17 41 |  | 
| 18 | 
            -
             | 
| 42 | 
            +
            This will install our ruby dependencies and update the project's gemfile.
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            ### Generate Quilt boilerplate
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            `rails generate quilt:install`
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            This will install the Node dependencies, provide a basic React app (in TypeScript) and mounts the Quilt engine inside of `config/routes.rb`.
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            ### Try it out
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            `dev server`
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            Will run the application, starting up both servers and compiling assets.
         | 
| 19 55 |  | 
| 20 56 | 
             
            ## Manual Installation
         | 
| 21 57 |  | 
| 22 | 
            -
             | 
| 58 | 
            +
            An application can also be setup manually using the following steps.
         | 
| 23 59 |  | 
| 24 60 | 
             
            ### Install Dependencies
         | 
| 25 61 |  | 
| 26 62 | 
             
            ```sh
         | 
| 27 | 
            -
            # Add Node dependencies
         | 
| 63 | 
            +
            # Add core Node dependencies
         | 
| 28 64 | 
             
            yarn add @shopify/sewing-kit @shopify/react-server
         | 
| 29 65 |  | 
| 30 | 
            -
            #  | 
| 31 | 
            -
            yarn add @shopify/polaris  | 
| 66 | 
            +
            # Add Polaris and React
         | 
| 67 | 
            +
            yarn add @shopify/polaris react react-dom
         | 
| 32 68 |  | 
| 33 69 | 
             
            yarn
         | 
| 34 70 | 
             
            dev up
         | 
| 35 71 | 
             
            ```
         | 
| 36 72 |  | 
| 37 | 
            -
            ###  | 
| 38 | 
            -
             | 
| 39 | 
            -
            sewing_kit looks for JavaScript in `app/ui/index.js`. The code in `index.js` (and any imported JS/CSS) will be built into a `main` bundle.
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            ### Rails Setup
         | 
| 73 | 
            +
            ### Setup the Rails app
         | 
| 42 74 |  | 
| 43 75 | 
             
            There are 2 ways to consume this package.
         | 
| 44 76 |  | 
| 45 | 
            -
             | 
| 77 | 
            +
            #### Option 1: Mount the Engine
         | 
| 46 78 |  | 
| 47 79 | 
             
            Add the engine to `routes.rb`.
         | 
| 48 80 |  | 
| @@ -54,7 +86,7 @@ Rails.application.routes.draw do | |
| 54 86 | 
             
            end
         | 
| 55 87 | 
             
            ```
         | 
| 56 88 |  | 
| 57 | 
            -
             | 
| 89 | 
            +
            If only a sub-section of routes should respond with the React App, it can be configured using the `at` parameter.
         | 
| 58 90 |  | 
| 59 91 | 
             
            ```ruby
         | 
| 60 92 | 
             
            # config/routes.rb
         | 
| @@ -64,7 +96,7 @@ Rails.application.routes.draw do | |
| 64 96 | 
             
            end
         | 
| 65 97 | 
             
            ```
         | 
| 66 98 |  | 
| 67 | 
            -
             | 
| 99 | 
            +
            #### Option 2: Add a React controller and routes
         | 
| 68 100 |  | 
| 69 101 | 
             
            Create a `ReactController` to handle react requests.
         | 
| 70 102 |  | 
| @@ -78,27 +110,18 @@ class ReactController < ApplicationController | |
| 78 110 | 
             
            end
         | 
| 79 111 | 
             
            ```
         | 
| 80 112 |  | 
| 81 | 
            -
             | 
| 113 | 
            +
            Add routes to default to the `ReactController`.
         | 
| 82 114 |  | 
| 83 115 | 
             
            ```ruby
         | 
| 84 116 | 
             
              get '/*path', to: 'react#index'
         | 
| 85 117 | 
             
              root 'react#index'
         | 
| 86 118 | 
             
            ```
         | 
| 87 119 |  | 
| 88 | 
            -
             | 
| 120 | 
            +
            ### Add JavaScript
         | 
| 89 121 |  | 
| 90 | 
            -
             | 
| 91 | 
            -
            ├── Gemfile (must contain "gem 'sewing_kit" and "gem 'quilt_rails'")
         | 
| 92 | 
            -
            ├── package.json (must specify '@shopify/sewing-kit' and `@shopify/react-server` as 'dependencies')
         | 
| 93 | 
            -
            │
         | 
| 94 | 
            -
            └── app
         | 
| 95 | 
            -
               └── ui
         | 
| 96 | 
            -
               │   └─- index.js
         | 
| 97 | 
            -
               └── controllers
         | 
| 98 | 
            -
                   └─- react_controller (see above)
         | 
| 99 | 
            -
            ```
         | 
| 122 | 
            +
            `sewing_kit` looks for the top level component of your React app in `app/ui/index`. The component exported from this component (and any imported JS/CSS) will be built into a `main` bundle, and used to render the initial server-rendered markup.
         | 
| 100 123 |  | 
| 101 | 
            -
             | 
| 124 | 
            +
            We will add a basic entrypoint using React with Polaris components.
         | 
| 102 125 |  | 
| 103 126 | 
             
            ```tsx
         | 
| 104 127 | 
             
            // app/ui/index.tsx
         | 
| @@ -119,21 +142,204 @@ function App() { | |
| 119 142 | 
             
            export default App;
         | 
| 120 143 | 
             
            ```
         | 
| 121 144 |  | 
| 122 | 
            -
             | 
| 145 | 
            +
            ### Run the server
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            `dev server`
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            Will run the application, starting up both servers and compiling assets.
         | 
| 150 | 
            +
             | 
| 151 | 
            +
            ## Application layout
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            ### Minimal
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            The basic layout for an app using `quilt_rails` and friends will have a `ui` folder nested inside the normal Rails `app` folder, containing at _least_ an index.js file exporting a React component.
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            ```
         | 
| 158 | 
            +
            ├── Gemfile (must contain "gem 'sewing_kit" and "gem 'quilt_rails'")
         | 
| 159 | 
            +
            ├── package.json (must specify '@shopify/sewing-kit' and `@shopify/react-server` as 'dependencies')
         | 
| 160 | 
            +
            │
         | 
| 161 | 
            +
            └── app
         | 
| 162 | 
            +
               └── ui
         | 
| 163 | 
            +
               │   └─- index.{js|ts} (exports a React component)
         | 
| 164 | 
            +
               └── controllers
         | 
| 165 | 
            +
                   └─- react_controller.rb (see above)
         | 
| 166 | 
            +
            ```
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ### Rails, Polaris, and React
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            A more complex application will want a more complex layout. The following shows scalable locations for:
         | 
| 171 | 
            +
             | 
| 172 | 
            +
            - Global SCSS settings
         | 
| 173 | 
            +
            - App sections (roughly analogous to Rails routes)
         | 
| 174 | 
            +
            - Components
         | 
| 175 | 
            +
            - Co-located CSS modules
         | 
| 176 | 
            +
            - Co-located unit tests
         | 
| 177 | 
            +
            - Test setup files
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            ```
         | 
| 180 | 
            +
            └── app
         | 
| 181 | 
            +
                └── ui
         | 
| 182 | 
            +
                    ├─- index.{js|ts} (exports a React component)
         | 
| 183 | 
            +
                    ├── styles (optional)
         | 
| 184 | 
            +
                    │   └── settings.scss (global vars and @polaris overrides)
         | 
| 185 | 
            +
                    │
         | 
| 186 | 
            +
                    └── tests (optional)
         | 
| 187 | 
            +
                    │   └── each-test.{js|ts}
         | 
| 188 | 
            +
                    │   └── setup.{js|ts}
         | 
| 189 | 
            +
                    └── features (optional)
         | 
| 190 | 
            +
                        ├── App
         | 
| 191 | 
            +
                        │   ├── index.{js|ts}
         | 
| 192 | 
            +
                        │   ├── App.{js|ts}x
         | 
| 193 | 
            +
                        │   └── tests
         | 
| 194 | 
            +
                        │       └── App.test.{js|ts}x
         | 
| 195 | 
            +
                        │
         | 
| 196 | 
            +
                        ├-─ MyComponent
         | 
| 197 | 
            +
                        │   ├-─ index.{js|ts}
         | 
| 198 | 
            +
                        │   ├-─ MyComponent.{js|ts}x
         | 
| 199 | 
            +
                        │   ├── MyComponent.scss (optional; component-scoped CSS styles, mixins, etc)
         | 
| 200 | 
            +
                        │   └── tests
         | 
| 201 | 
            +
                        │       └── MyComponent.test.{js|ts}x
         | 
| 202 | 
            +
                        │
         | 
| 203 | 
            +
                        └── sections (optional; container views that compose presentation components into UI blocks)
         | 
| 204 | 
            +
                            └── Home
         | 
| 205 | 
            +
                                ├-─ index.{js|ts}
         | 
| 206 | 
            +
                                └── Home.{js|ts}
         | 
| 207 | 
            +
            ```
         | 
| 208 | 
            +
             | 
| 209 | 
            +
            ## API
         | 
| 210 | 
            +
             | 
| 211 | 
            +
            ### ReactRenderable
         | 
| 212 | 
            +
             | 
| 213 | 
            +
            The `ReactRenderable` mixin is intended to be used in Rails controllers, and provides only the `render_react` method. This method handles proxying to a running `@shopify/react-server`.
         | 
| 214 | 
            +
             | 
| 215 | 
            +
            ```ruby
         | 
| 216 | 
            +
            class ReactController < ApplicationController
         | 
| 217 | 
            +
              include Quilt::ReactRenderable
         | 
| 218 | 
            +
             | 
| 219 | 
            +
              def index
         | 
| 220 | 
            +
                render_react
         | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
            end
         | 
| 223 | 
            +
            ```
         | 
| 224 | 
            +
             | 
| 225 | 
            +
            ### Engine
         | 
| 226 | 
            +
             | 
| 227 | 
            +
            `Quilt::Engine` provides a preconfigured controller which consumes `ReactRenderable` and provides an index route which uses it.
         | 
| 228 | 
            +
             | 
| 229 | 
            +
            ```ruby
         | 
| 230 | 
            +
            # config/routes.rb
         | 
| 231 | 
            +
            Rails.application.routes.draw do
         | 
| 232 | 
            +
              # ...
         | 
| 233 | 
            +
              mount Quilt::Engine, at: '/path/to/react'
         | 
| 234 | 
            +
            end
         | 
| 235 | 
            +
            ```
         | 
| 236 | 
            +
             | 
| 237 | 
            +
            ### Configuration
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            The `configure` method allows customization of the address the service will proxy to for UI rendering.
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            ```ruby
         | 
| 242 | 
            +
              # config/initializers/quilt.rb
         | 
| 243 | 
            +
              Quilt.configure do |config|
         | 
| 244 | 
            +
                config.react_server_host = "localhost:3000"
         | 
| 245 | 
            +
                config.react_server_protocol = 'https'
         | 
| 246 | 
            +
              end
         | 
| 247 | 
            +
            ```
         | 
| 248 | 
            +
             | 
| 249 | 
            +
            ### Generators
         | 
| 123 250 |  | 
| 124 | 
            -
             | 
| 251 | 
            +
            #### `quilt:install`
         | 
| 125 252 |  | 
| 126 | 
            -
            Installs the Node dependencies, provide a basic React app (in TypeScript) and mounts the Quilt engine  | 
| 253 | 
            +
            Installs the Node dependencies, provide a basic React app (in TypeScript) and mounts the Quilt engine in `config/routes.rb`.
         | 
| 127 254 |  | 
| 128 | 
            -
             | 
| 255 | 
            +
            #### `sewing_kit:install`
         | 
| 129 256 |  | 
| 130 257 | 
             
            Adds a basic `sewing-kit.config.ts` file.
         | 
| 131 258 |  | 
| 132 259 | 
             
            ## Advanced use
         | 
| 133 260 |  | 
| 134 | 
            -
            ###  | 
| 261 | 
            +
            ### Testing
         | 
| 262 | 
            +
             | 
| 263 | 
            +
            For fast tests with consistent results, test front-end components using the tools provided by sewing-kit instead of Rails integration tests.
         | 
| 264 | 
            +
             | 
| 265 | 
            +
            Use [`sewing-kit test`](https://github.com/Shopify/sewing-kit/blob/master/docs/commands/test.md#L3) to run all `.test.{js|ts}x` files in the `app/ui` directory. [Jest](https://jestjs.io/) is used as a test runner, with customization available via [its sewing-kit plugin](https://github.com/Shopify/sewing-kit/blob/master/docs/plugins/jest.md).
         | 
| 266 | 
            +
             | 
| 267 | 
            +
            For testing React applications we provide and support [`@shopify/react-testing`](https://github.com/Shopify/quilt/tree/master/packages/react-testing).
         | 
| 268 | 
            +
             | 
| 269 | 
            +
            #### Example
         | 
| 270 | 
            +
             | 
| 271 | 
            +
            Given a component `MyComponent.tsx`
         | 
| 272 | 
            +
             | 
| 273 | 
            +
            ```tsx
         | 
| 274 | 
            +
            // app/ui/components/MyComponent/MyComponent.tsx
         | 
| 275 | 
            +
            export function MyComponent({name}: {name: string}) {
         | 
| 276 | 
            +
              return <div>Hello, {name}!</div>;
         | 
| 277 | 
            +
            }
         | 
| 278 | 
            +
            ```
         | 
| 279 | 
            +
             | 
| 280 | 
            +
            A test would be written using Jest and `@shopify/react-testing`'s `mount` feature.
         | 
| 281 | 
            +
             | 
| 282 | 
            +
            ```tsx
         | 
| 283 | 
            +
            // app/ui/components/MyComponent/tests/MyComponent.test.tsx
         | 
| 284 | 
            +
            import {MyComponent} from '../MyComponent';
         | 
| 285 | 
            +
             | 
| 286 | 
            +
            describe('MyComponent', () => {
         | 
| 287 | 
            +
              it('greets the given named person', () => {
         | 
| 288 | 
            +
                const wrapper = mount(<MyComponent name="Kokusho" />);
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                // toContainReactText is a custom matcher provided by @shopify/react-testing/matchers
         | 
| 291 | 
            +
                expect(wrapper).toContainReactText('Hello, Kokusho');
         | 
| 292 | 
            +
              });
         | 
| 293 | 
            +
            });
         | 
| 294 | 
            +
            ```
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            ### Test setup files
         | 
| 297 | 
            +
             | 
| 298 | 
            +
            By default, the jest plugin will look for test setup files under `/app/ui/tests`.
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            `setup` can be used to add any custom polyfills needed for the testing environment.
         | 
| 301 | 
            +
             | 
| 302 | 
            +
            ```tsx
         | 
| 303 | 
            +
            // app/ui/tests/setup.ts
         | 
| 304 | 
            +
             | 
| 305 | 
            +
            import 'isomorphic-fetch';
         | 
| 306 | 
            +
            import 'raf/polyfill';
         | 
| 307 | 
            +
            import {URL, URLSearchParams} from 'url';
         | 
| 135 308 |  | 
| 136 | 
            -
             | 
| 309 | 
            +
            (global as any).URL = URL;
         | 
| 310 | 
            +
            (global as any).URLSearchParams = URLSearchParams;
         | 
| 311 | 
            +
            ```
         | 
| 312 | 
            +
             | 
| 313 | 
            +
            `each-test` can be used for any logic that needs to run for each individual test suite. Any setup logic that needs to happen with `jest` globals in scope, such as importing custom matchers, should also be done here.
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            ```tsx
         | 
| 316 | 
            +
            // app/ui/tests/each-test.ts
         | 
| 317 | 
            +
             | 
| 318 | 
            +
            // we cannot import these in `setup` because `expect` will not be defined
         | 
| 319 | 
            +
            import '@shopify/react-testing/matchers';
         | 
| 320 | 
            +
             | 
| 321 | 
            +
            beforeAll(() => {
         | 
| 322 | 
            +
              console.log('I will run before every test suite');
         | 
| 323 | 
            +
            });
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            beforeEach(() => {
         | 
| 326 | 
            +
              console.log('I will run before every test case');
         | 
| 327 | 
            +
            });
         | 
| 328 | 
            +
             | 
| 329 | 
            +
            afterEach(() => {
         | 
| 330 | 
            +
              console.log('I will run after every test case');
         | 
| 331 | 
            +
            });
         | 
| 332 | 
            +
             | 
| 333 | 
            +
            afterAll(() => {
         | 
| 334 | 
            +
              console.log('I will run after every test suite');
         | 
| 335 | 
            +
            });
         | 
| 336 | 
            +
            ```
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            For more complete documentation of the jest plugin see [it's documentation](https://github.com/Shopify/sewing-kit/tree/master/docs/plugins/jest.md).
         | 
| 339 | 
            +
             | 
| 340 | 
            +
            ### Interacting with the request and response in React code
         | 
| 341 | 
            +
             | 
| 342 | 
            +
            React-server sets up [@shopify/react-network](https://github.com/Shopify/quilt/blob/master/packages/react-network/src/hooks.ts#L25) automatically, so most interactions with the request or response can be done from inside the React app.
         | 
| 137 343 |  | 
| 138 344 | 
             
            #### Example: getting headers
         | 
| 139 345 |  | 
| @@ -186,16 +392,22 @@ function App() { | |
| 186 392 | 
             
            export default App;
         | 
| 187 393 | 
             
            ```
         | 
| 188 394 |  | 
| 395 | 
            +
            ### Isomorphic state
         | 
| 396 | 
            +
             | 
| 397 | 
            +
            With SSR enabled React apps, state must be serialized on the server and deserialized on the client to keep it consistent. When using `@shopify/react-server`, the best tool for this job is [`@shopify/react-html`](https://github.com/Shopify/quilt/tree/master/packages/react-html)'s [`useSerialized`](https://github.com/Shopify/quilt/tree/master/packages/react-html#in-your-application-code) hook.
         | 
| 398 | 
            +
             | 
| 399 | 
            +
            `useSerialized` can be used to implement [universal-providers](https://github.com/Shopify/quilt/tree/master/packages/react-universal-provider#what-is-a-universal-provider-), allowing application code to manage what is persisted between the server and client without adding any custom code to client or server entrypoints. We offer some for common use cases such as [CSRF](https://github.com/Shopify/quilt/tree/master/packages/react-csrf-universal-provider), [GraphQL](https://github.com/Shopify/quilt/tree/master/packages/react-graphql-universal-provider), [I18n](https://github.com/Shopify/quilt/tree/master/packages/react-i18n-universal-provider), and the [Shopify App Bridge](https://github.com/Shopify/quilt/tree/master/packages/react-app-bridge-universal-provider).
         | 
| 400 | 
            +
             | 
| 189 401 | 
             
            ### Customizing the node server
         | 
| 190 402 |  | 
| 191 | 
            -
            By default, sewing-kit bundles in `@shopify/react-server-webpack-plugin` for `quilt_rails` applications to get  | 
| 403 | 
            +
            By default, sewing-kit bundles in `@shopify/react-server-webpack-plugin` for `quilt_rails` applications to get apps up and running fast without needing to manually write any node server code. If what it provides is not sufficient, a custom server can be defined by adding a `server.js` or `server.ts` file to the app folder.
         | 
| 192 404 |  | 
| 193 405 | 
             
            ```
         | 
| 194 406 | 
             
            └── app
         | 
| 195 407 | 
             
               └── ui
         | 
| 196 | 
            -
                  └─- app.js
         | 
| 197 | 
            -
                  └─- index.js
         | 
| 198 | 
            -
                  └─- server.js
         | 
| 408 | 
            +
                  └─- app.{js|ts}x
         | 
| 409 | 
            +
                  └─- index.{js|ts}
         | 
| 410 | 
            +
                  └─- server.{js|ts}x
         | 
| 199 411 | 
             
            ```
         | 
| 200 412 |  | 
| 201 413 | 
             
            ```tsx
         | 
| @@ -207,17 +419,12 @@ import React from 'react'; | |
| 207 419 |  | 
| 208 420 | 
             
            import App from './app';
         | 
| 209 421 |  | 
| 210 | 
            -
            //  | 
| 422 | 
            +
            // The simplest way to build a custom server that will work with this library is to use the APIs provided by @shopify/react-server.
         | 
| 211 423 | 
             
            // https://github.com/Shopify/quilt/blob/master/packages/react-server/README.md#L8
         | 
| 212 424 | 
             
            const app = createServer({
         | 
| 213 425 | 
             
              port: process.env.PORT ? parseInt(process.env.PORT, 10) : 8081,
         | 
| 214 426 | 
             
              ip: process.env.IP,
         | 
| 215 427 | 
             
              assetPrefix: process.env.CDN_URL || 'localhost:8080/assets/webpack',
         | 
| 216 | 
            -
              serverMiddleware: [(ctx, next) => {
         | 
| 217 | 
            -
                // you can add your own middleware to extend the server's functionality.
         | 
| 218 | 
            -
                console.log('I am a custom middleware!');
         | 
| 219 | 
            -
                await next();
         | 
| 220 | 
            -
              }]
         | 
| 221 428 | 
             
              render: (ctx, {locale}) => {
         | 
| 222 429 | 
             
                const whatever = /* do something special with the koa context */;
         | 
| 223 430 | 
             
                // any special data we add to the incoming request in our rails controller we can access here to pass into our component
         | 
| @@ -228,6 +435,27 @@ const app = createServer({ | |
| 228 435 | 
             
            export default app;
         | 
| 229 436 | 
             
            ```
         | 
| 230 437 |  | 
| 231 | 
            -
            ###  | 
| 438 | 
            +
            ### Fixing rejected CSRF tokens for new user sessions
         | 
| 439 | 
            +
             | 
| 440 | 
            +
            If a React component calls back to a Rails endpoint (e.g., `/graphql`), Rails may throw a `Can't verify CSRF token authenticity` exception. This stems from the Rails CSRF tokens not persisting until after the first `UiController` call ends.
         | 
| 441 | 
            +
             | 
| 442 | 
            +
            To fix this:
         | 
| 232 443 |  | 
| 233 | 
            -
             | 
| 444 | 
            +
            - Add an `X-Shopify-Server-Side-Rendered: 1` header to all server-side GraphQL requests
         | 
| 445 | 
            +
            - Add a `protect_from_forgery with: Quilt::TrustedUiServerCsrfStrategy` override to Node-accessed controllers
         | 
| 446 | 
            +
             | 
| 447 | 
            +
            e.g.:
         | 
| 448 | 
            +
             | 
| 449 | 
            +
            ```rb
         | 
| 450 | 
            +
            class GraphqlController < ApplicationController
         | 
| 451 | 
            +
              protect_from_forgery with: Quilt::TrustedUiServerCsrfStrategy
         | 
| 452 | 
            +
             | 
| 453 | 
            +
              def execute
         | 
| 454 | 
            +
                # Get GraphQL query, etc
         | 
| 455 | 
            +
             | 
| 456 | 
            +
                result = MySchema.execute(query, operation_name: operation_name, variables: variables, context: context)
         | 
| 457 | 
            +
             | 
| 458 | 
            +
                render(json: result)
         | 
| 459 | 
            +
              end
         | 
| 460 | 
            +
            end
         | 
| 461 | 
            +
            ```
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Quilt
         | 
| 4 | 
            +
              class TrustedUiServerCsrfStrategy
         | 
| 5 | 
            +
                def initialize(controller)
         | 
| 6 | 
            +
                  @controller = controller
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def handle_unverified_request
         | 
| 10 | 
            +
                  return if node_server_side_render?
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  fallback_handler.handle_unverified_request
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                private
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def node_server_side_render?
         | 
| 18 | 
            +
                  @controller.request.headers['x-shopify-server-side-rendered'] == '1'
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def fallback_handler
         | 
| 22 | 
            +
                  ActionController::RequestForgeryProtection::ProtectionMethods::Exception.new(@controller)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
    
        data/lib/quilt_rails/version.rb
    CHANGED
    
    
    
        data/lib/quilt_rails.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: quilt_rails
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.6.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Mathew Allen
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019-09- | 
| 11 | 
            +
            date: 2019-09-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: railties
         | 
| @@ -90,6 +90,7 @@ files: | |
| 90 90 | 
             
            - lib/quilt_rails/engine.rb
         | 
| 91 91 | 
             
            - lib/quilt_rails/logger.rb
         | 
| 92 92 | 
             
            - lib/quilt_rails/react_renderable.rb
         | 
| 93 | 
            +
            - lib/quilt_rails/trusted_ui_server_csrf_strategy.rb
         | 
| 93 94 | 
             
            - lib/quilt_rails/version.rb
         | 
| 94 95 | 
             
            homepage: https://github.com/Shopify/quilt/tree/master/gems/quilt_rails
         | 
| 95 96 | 
             
            licenses:
         |