Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the meta tag used for token or state #121

Merged
merged 5 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .containers.example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
organization:
name: turbo_boost

app:
name: turbo_boost-commands
directory: /path/to/turbo_boost-commands

docker:
directory: /path/to/turbo_boost-commands
compose_files:
- /path/to/turbo_boost-commands/docker-compose.yml
default_service: web
10 changes: 7 additions & 3 deletions .github/workflows/prettier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Enable Corepack
run: corepack enable

- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
version: '20.x'
cache: 'yarn'

- name: Yarn install
run: yarn install --frozen-lockfile
run: 'yarn install --frozen-lockfile'

- name: Run Prettier
run: yarn run prettier --check package.json prettier.config.js bin/build.mjs app/javascript/**/*.js test/dummy/app/javascript/**/*.js test/dummy/app/assets/stylesheets/**/*.css test/dummy/app/views/**/*.css
run: 'yarn run prettier --check --fail-on-errors .'

6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ jobs:

steps:
- uses: actions/checkout@v3

- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true

- name: Enable Corepack
run: corepack enable

- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'yarn'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
*.gem
*.key
*.metafile.json
.containers.yml
.yarn
/.bundle/
/doc/
/log/*.log
Expand Down
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.md
*.yml
builds
1 change: 0 additions & 1 deletion .standard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ parallel: true

ignore:
- test/dummy/bin/*
- test/dummy/config/initializers/inspect_helpers.rb
- test/dummy/db/schema.rb

Lint/RescueException:
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ tzdata

RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
RUN apt-get -y --no-install-recommends install nodejs && \
npm install -g npm@latest yarn
corepack enable && \
yarn set version stable

RUN apt-get clean
RUN gem update --system
Expand Down
32 changes: 14 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,6 @@ rails app:template LOCATION='https://railsbytes.com/script/xkjsbB'
+import '@turbo-boost/commands'
```

3. Add TurboBoost to your Rails app

```diff
# app/views/layouts/application.html.erb
<html>
<head>
+ <%= turbo_boost.meta_tag %>
</head>
<body>
</body>
</html>
```

## Usage

This example illustrates how to use TurboBoost Commands to manage upvotes on a Post.
Expand Down Expand Up @@ -556,14 +543,23 @@ fly deploy

## Releasing

1. Run `yarn` and `bundle` to pick up the latest
> [!TIP]
> Run these commands on the host machine _(i.e. not inside the dev container)_

> [!TIP]
> Ensure you're using the latest stable version of `yarn`
> `corepack enable && yarn set version stable`

1. Run `yarn upgrade-interactive` and `bundle update` to pick up the latest dependencies
1. Bump version number at `lib/turbo_boost-streams/version.rb`. Pre-release versions use `.preN`
1. Bump version number at `package.json` _(make sure it matches)_. Pre-release versions use `-preN`
1. Run `yarn build` and `rake build`
1. Commit and push changes to GitHub
1. Run `bin/standardize`
1. Run `rake build`
1. Run `yarn build`
1. Commit and push any changes to GitHub
1. Run `rake release`
1. Run `yarn publish --no-git-tag-version --access public --new-version X.X.X` _(use same version number)_
1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_boost-streams/releases)) and generate the changelog for the stable release for it
1. Run `yarn npm publish --access public`
1. Create a new release on GitHub ([here](https://github.com/hopsoft/turbo_boost-commands/releases)) and generate the changelog for the stable release for it

## About TurboBoost

Expand Down
2 changes: 1 addition & 1 deletion app/assets/builds/@turbo-boost/commands.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions app/assets/builds/@turbo-boost/commands.js.map

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion app/assets/builds/@turbo-boost/commands.metafile.json

This file was deleted.

3 changes: 0 additions & 3 deletions app/javascript/drivers/form.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import meta from '../meta'

function invokeCommand(form, payload = {}, event = {}) {
payload.token = meta.token
const input = form.querySelector('input[name="turbo_boost_command"]') || document.createElement('input')
input.type = 'hidden'
input.name = 'turbo_boost_command'
Expand Down
1 change: 0 additions & 1 deletion app/javascript/drivers/window.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import meta from '../meta'
import state from '../state'
import { dispatch } from '../events'
import lifecycle from '../lifecycle'
Expand Down
57 changes: 24 additions & 33 deletions app/javascript/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
import './turbo'
import schema from './schema'
import { dispatch, commandEvents, stateEvents } from './events'
import { dispatch, commandEvents } from './events'
import activity from './activity'
import confirmation from './confirmation'
import delegates from './delegates'
import drivers from './drivers'
import meta from './meta'
import elements from './elements'
import lifecycle from './lifecycle'
import logger from './logger'
import state from './state'
import urls from './urls'
import uuids from './uuids'

const TurboBoost = self.TurboBoost || {}

const Commands = {
busy: false,
confirmation,
logger,
schema,
events: commandEvents,
registerEventDelegate: delegates.register,
get eventDelegates() {
return delegates.events
}
}

function buildCommandPayload(id, element) {
return {
id, // uniquely identifies the command
name: element.getAttribute(schema.commandAttribute),
elementId: element.id.length > 0 ? element.id : null,
elementAttributes: elements.buildAttributePayload(element),
startedAt: Date.now(),
token: meta.token, // authenticity token
signedState: meta.signedState, // server side state
state: state.changed // client side state (optimistic updates)
token: Commands.token, // command token (used for CSRF protection)
signedState: state.signed, // server side state
clientState: state.changed // client side state (optimistic updates)
}
}

Expand Down Expand Up @@ -70,8 +83,8 @@ async function invokeCommand(event) {

if (['frame', 'window'].includes(driver.name)) event.preventDefault()

meta.busy = true
setTimeout(() => (meta.busy = false), 10)
Commands.busy = true
setTimeout(() => (Commands.busy = false), 10)

switch (driver.name) {
case 'method':
Expand All @@ -90,21 +103,7 @@ async function invokeCommand(event) {
}
}

self.TurboBoost = self.TurboBoost || {}

self.TurboBoost = {
...self.TurboBoost,

stateEvents,

get state() {
return state.current
},

get stateChanges() {
return state.changed
}
}
self.TurboBoost = { ...TurboBoost }

if (!self.TurboBoost.Commands) {
// wire things up and setup defaults for event delegation
Expand All @@ -117,16 +116,8 @@ if (!self.TurboBoost.Commands) {
`textarea[${schema.commandAttribute}]`
])

self.TurboBoost.Commands = {
confirmation,
logger,
schema,
events: commandEvents,
registerEventDelegate: delegates.register,
get eventDelegates() {
return delegates.events
}
}
self.TurboBoost.Commands = Commands
self.TurboBoost.State = state
}

export default self.TurboBoost.Commands
export default Commands
31 changes: 0 additions & 31 deletions app/javascript/meta.js

This file was deleted.

35 changes: 13 additions & 22 deletions app/javascript/state/index.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
import meta from '../meta'
// TODO: Consider moving State to its own library
import observable from './observable'
import { dispatch, commandEvents, stateEvents } from '../events'

let initialState, currentState, changedState
let loadStateTimeout
let initialState, currentState, changedState, signedState

function loadState() {
if (!meta.element) return loadStateLater()
const json = JSON.parse(meta.element.dataset.state)
function initialize(initial, signed) {
const json = JSON.parse(initial)
initialState = { ...json }
signedState = signed
currentState = observable(json)
changedState = {}
setTimeout(() =>
dispatch(stateEvents.stateLoad, meta.element, {
dispatch(stateEvents.stateLoad, document, {
detail: { state: currentState }
})
)
}

function loadStateLater() {
clearTimeout(loadStateTimeout)
loadStateTimeout = setTimeout(loadState, 10)
}

if (!initialState) loadState()

addEventListener('DOMContentLoaded', loadStateLater)
addEventListener('load', loadStateLater)
addEventListener('turbo:load', loadStateLater)
addEventListener('turbo:frame-load', loadStateLater)
addEventListener(commandEvents.success, loadStateLater)

addEventListener(stateEvents.stateChange, event => {
for (const [key, value] of Object.entries(currentState))
if (initialState[key] !== value) changedState[key] = value
})

export default {
initialize,
events: stateEvents,

get initial() {
return { ...initialState }
return initialState
},

get current() {
return currentState
},

get changed() {
return { ...changedState }
return changedState
},

get signed() {
return signedState
}
}
5 changes: 2 additions & 3 deletions app/javascript/state/observable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import meta from '../meta'
import { dispatch, stateEvents as events } from '../events'

let head
Expand All @@ -9,13 +8,13 @@ function observable(object, parent = null) {
const proxy = new Proxy(object, {
deleteProperty(target, key) {
delete target[key]
dispatch(events.stateChange, meta.element, { detail: { state: head } })
dispatch(events.stateChange, document, { detail: { state: head } })
return true
},

set(target, key, value, receiver) {
target[key] = observable(value, this)
dispatch(events.stateChange, meta.element, { detail: { state: head } })
dispatch(events.stateChange, document, { detail: { state: head } })
return true
}
})
Expand Down
3 changes: 1 addition & 2 deletions app/javascript/turbo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import meta from './meta'
import state from './state'
import renderer from './renderer'
import { dispatch } from './events'
Expand All @@ -12,7 +11,7 @@ addEventListener('turbo:before-fetch-request', event => {
const { fetchOptions } = event.detail

// command invoked and busy
if (meta.busy) {
if (self.TurboBoost?.Commands?.busy) {
let acceptHeaders = ['text/vnd.turbo-boost.html', fetchOptions.headers['Accept']]
acceptHeaders = acceptHeaders.filter(entry => entry && entry.trim().length > 0).join(', ')
fetchOptions.headers['Accept'] = acceptHeaders
Expand Down
Loading