Skip to content

Commit

Permalink
exclude properties from partial responses (#1876)
Browse files Browse the repository at this point in the history
  • Loading branch information
lepikhinb authored May 17, 2024
1 parent ca7e7cb commit 680b2eb
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 10 deletions.
17 changes: 15 additions & 2 deletions packages/core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export class Router {
preserveScroll = false,
preserveState = false,
only = [],
except = [],
headers = {},
errorBag = '',
forceFormData = false,
Expand Down Expand Up @@ -294,6 +295,7 @@ export class Router {
preserveScroll,
preserveState,
only,
except,
headers,
errorBag,
forceFormData,
Expand Down Expand Up @@ -339,6 +341,8 @@ export class Router {
fireStartEvent(visit)
onStart(visit)

const isPartial = !!(only.length || except.length)

Axios({
method,
url: urlWithoutHash(url).href,
Expand All @@ -350,12 +354,21 @@ export class Router {
Accept: 'text/html, application/xhtml+xml',
'X-Requested-With': 'XMLHttpRequest',
'X-Inertia': true,
...(only.length
...(isPartial
? {
'X-Inertia-Partial-Component': this.page.component,
}
: {}),
...(only.length
? {
'X-Inertia-Partial-Data': only.join(','),
}
: {}),
...(except.length
? {
'X-Inertia-Partial-Except': except.join(','),
}
: {}),
...(errorBag && errorBag.length ? { 'X-Inertia-Error-Bag': errorBag } : {}),
...(this.page.version ? { 'X-Inertia-Version': this.page.version } : {}),
},
Expand All @@ -373,7 +386,7 @@ export class Router {
}

const pageResponse: Page = response.data
if (only.length && pageResponse.component === this.page.component) {
if (isPartial && pageResponse.component === this.page.component) {
pageResponse.props = { ...this.page.props, ...pageResponse.props }
}
preserveScroll = this.resolvePreserveOption(preserveScroll, pageResponse) as boolean
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export type Visit = {
preserveScroll: PreserveStateOption
preserveState: PreserveStateOption
only: Array<string>
except: Array<string>
headers: Record<string, string>
errorBag: string | null
forceFormData: boolean
Expand Down
4 changes: 4 additions & 0 deletions packages/react/src/Link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface BaseInertiaLinkProps {
preserveState?: PreserveStateOption
replace?: boolean
only?: string[]
except?: string[]
onCancelToken?: (cancelToken: import('axios').CancelTokenSource) => void
onBefore?: () => void
onStart?: () => void
Expand Down Expand Up @@ -49,6 +50,7 @@ const Link = forwardRef<unknown, InertiaLinkProps>(
preserveState = null,
replace = false,
only = [],
except = [],
headers = {},
queryStringArrayFormat = 'brackets',
onClick = noop,
Expand Down Expand Up @@ -78,6 +80,7 @@ const Link = forwardRef<unknown, InertiaLinkProps>(
preserveState: preserveState ?? method !== 'get',
replace,
only,
except,
headers,
onCancelToken,
onBefore,
Expand All @@ -98,6 +101,7 @@ const Link = forwardRef<unknown, InertiaLinkProps>(
preserveState,
replace,
only,
except,
headers,
onClick,
onCancelToken,
Expand Down
2 changes: 2 additions & 0 deletions packages/svelte/src/Link.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
export let preserveScroll = false
export let preserveState = null
export let only = []
export let except = []
export let headers = {}
export let queryStringArrayFormat = 'brackets'
Expand All @@ -33,6 +34,7 @@
preserveScroll,
preserveState: preserveState ?? method !== 'get',
only,
except,
headers,
queryStringArrayFormat,
}}
Expand Down
6 changes: 6 additions & 0 deletions packages/vue2/src/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface InertiaLinkProps {
preserveState?: PreserveStateOption
replace?: boolean
only?: string[]
except?: string[]
onCancelToken?: (cancelToken: import('axios').CancelTokenSource) => void
onBefore?: () => void
onStart?: () => void
Expand Down Expand Up @@ -66,6 +67,10 @@ const Link: InertiaLink = {
type: Array,
default: () => [],
},
except: {
type: Array,
default: () => [],
},
headers: {
type: Object,
default: () => ({}),
Expand Down Expand Up @@ -127,6 +132,7 @@ const Link: InertiaLink = {
preserveScroll: props.preserveScroll,
preserveState: props.preserveState ?? method !== 'get',
only: props.only,
except: props.except,
headers: props.headers,
// @ts-expect-error
onCancelToken: data.on.cancelToken,
Expand Down
6 changes: 6 additions & 0 deletions packages/vue2/tests/app/Pages/Links/PartialReloads.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
<inertia-link href="/links/partial-reloads" :only="['headers', 'baz']" :data="{ foo }" class="baz"
>'Only' baz</inertia-link
>
<inertia-link href="/links/partial-reloads" :except="['foo', 'bar']" :data="{ foo }" class="except-foo-bar"
>'Except' foo + bar</inertia-link
>
<inertia-link href="/links/partial-reloads" :except="['baz']" :data="{ foo }" class="except-baz"
>'Except' baz</inertia-link
>
</div>
</template>
<script>
Expand Down
38 changes: 38 additions & 0 deletions packages/vue2/tests/app/Pages/Visits/PartialReloads.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
<span @click="partialReloadVisit" class="visit">Update All (visit)</span>
<span @click="partialReloadVisitFooBar" class="visit-foo-bar">'Only' foo + bar (visit)</span>
<span @click="partialReloadVisitBaz" class="visit-baz">'Only' baz (visit)</span>
<span @click="partialReloadVisitExceptFooBar" class="visit-except-foo-bar">'Except' foo + bar (visit)</span>
<span @click="partialReloadVisitExceptBaz" class="visit-except-baz">'Except' baz (visit)</span>

<span @click="partialReloadGet" class="get">Update All (GET)</span>
<span @click="partialReloadGetFooBar" class="get-foo-bar">'Only' foo + bar (GET)</span>
<span @click="partialReloadGetBaz" class="get-baz">'Only' baz (GET)</span>
<span @click="partialReloadGetExceptFooBar" class="get-except-foo-bar">'Except' foo + bar (GET)</span>
<span @click="partialReloadGetExceptBaz" class="get-except-baz">'Except' baz (GET)</span>
</div>
</template>
<script>
Expand Down Expand Up @@ -47,6 +51,18 @@ export default {
only: ['headers', 'baz'],
})
},
partialReloadVisitExceptFooBar() {
this.$inertia.visit('/visits/partial-reloads', {
data: { foo: this.foo },
except: ['foo', 'bar'],
})
},
partialReloadVisitExceptBaz() {
this.$inertia.visit('/visits/partial-reloads', {
data: { foo: this.foo },
except: ['baz'],
})
},
partialReloadGet() {
this.$inertia.get('/visits/partial-reloads', {
foo: this.foo,
Expand Down Expand Up @@ -74,6 +90,28 @@ export default {
},
)
},
partialReloadGetExceptFooBar() {
this.$inertia.get(
'/visits/partial-reloads',
{
foo: this.foo,
},
{
except: ['foo', 'bar'],
},
)
},
partialReloadGetExceptBaz() {
this.$inertia.get(
'/visits/partial-reloads',
{
foo: this.foo,
},
{
except: ['baz'],
},
)
},
},
}
</script>
13 changes: 6 additions & 7 deletions packages/vue2/tests/app/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ module.exports = {
}

const partialDataHeader = req.headers['x-inertia-partial-data'] || ''
const partialExceptHeader = req.headers['x-inertia-partial-except'] || ''
const partialComponentHeader = req.headers['x-inertia-partial-component'] || ''

const isPartial = partialComponentHeader && partialComponentHeader === data.component

data.props = Object.keys(data.props)
.filter(
(key) =>
!partialComponentHeader ||
partialComponentHeader !== data.component ||
!partialDataHeader ||
partialDataHeader.split(',').indexOf(key) > -1,
)
.filter((key) => !isPartial || !partialDataHeader || partialDataHeader.split(',').indexOf(key) > -1)
.filter((key) => !isPartial || !partialExceptHeader || partialExceptHeader.split(',').indexOf(key) == -1)
.reduce((carry, key) => {
carry[key] = typeof data.props[key] === 'function' ? data.props[key](data.props) : data.props[key]

Expand Down
14 changes: 14 additions & 0 deletions packages/vue2/tests/cypress/integration/links.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,20 @@ describe('Links', () => {
cy.get('.bar-text').should('have.text', 'Bar is now 4')
cy.get('.baz-text').should('have.text', 'Baz is now 5')
})

it('it only updates props that are not passed through "except"', () => {
cy.get('.except-foo-bar').click()
cy.url().should('eq', Cypress.config().baseUrl + '/links/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 1')
cy.get('.bar-text').should('have.text', 'Bar is now 2')
cy.get('.baz-text').should('have.text', 'Baz is now 4')

cy.get('.except-baz').click()
cy.url().should('eq', Cypress.config().baseUrl + '/links/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 2')
cy.get('.bar-text').should('have.text', 'Bar is now 3')
cy.get('.baz-text').should('have.text', 'Baz is now 4')
})
})

describe('Redirects', () => {
Expand Down
53 changes: 52 additions & 1 deletion packages/vue2/tests/cypress/integration/manual-visits.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ describe('Manual Visits', () => {
})
})

it('has headers specific to partial reloads', () => {
it('has headers specific to "only" partial reloads', () => {
cy.get('.visit-foo-bar').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')

Expand All @@ -1314,6 +1314,29 @@ describe('Manual Visits', () => {
})
})

it('has headers specific to "except" partial reloads', () => {
cy.get('.visit-except-foo-bar').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')

cy.window().should('have.property', '_inertia_props')
cy.window()
.then((window) => window._inertia_props)
.then(({ headers }) => {
expect(headers).to.contain.keys([
'accept',
'x-requested-with',
'x-inertia',
'x-inertia-partial-component',
'x-inertia-partial-except',
])
expect(headers['accept']).to.eq('text/html, application/xhtml+xml')
expect(headers['x-requested-with']).to.eq('XMLHttpRequest')
expect(headers['x-inertia']).to.eq('true')
expect(headers['x-inertia-partial-except']).to.eq('foo,bar')
expect(headers['x-inertia-partial-component']).to.eq('Visits/PartialReloads')
})
})

it('it updates all props when the feature is not being used', () => {
cy.get('.visit').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')
Expand Down Expand Up @@ -1342,6 +1365,20 @@ describe('Manual Visits', () => {
cy.get('.bar-text').should('have.text', 'Bar is now 4')
cy.get('.baz-text').should('have.text', 'Baz is now 5')
})

it('it only updates props that are not passed through "except"', () => {
cy.get('.visit-except-foo-bar').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 1')
cy.get('.bar-text').should('have.text', 'Bar is now 2')
cy.get('.baz-text').should('have.text', 'Baz is now 4')

cy.get('.visit-except-baz').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 2')
cy.get('.bar-text').should('have.text', 'Bar is now 3')
cy.get('.baz-text').should('have.text', 'Baz is now 4')
})
})

describe('GET-method', () => {
Expand Down Expand Up @@ -1408,6 +1445,20 @@ describe('Manual Visits', () => {
cy.get('.bar-text').should('have.text', 'Bar is now 4')
cy.get('.baz-text').should('have.text', 'Baz is now 5')
})

it('it only updates props that are not passed through "except"', () => {
cy.get('.get-except-foo-bar').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 1')
cy.get('.bar-text').should('have.text', 'Bar is now 2')
cy.get('.baz-text').should('have.text', 'Baz is now 4')

cy.get('.get-except-baz').click()
cy.url().should('eq', Cypress.config().baseUrl + '/visits/partial-reloads')
cy.get('.foo-text').should('have.text', 'Foo is now 2')
cy.get('.bar-text').should('have.text', 'Bar is now 3')
cy.get('.baz-text').should('have.text', 'Baz is now 4')
})
})
})

Expand Down
6 changes: 6 additions & 0 deletions packages/vue3/src/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface InertiaLinkProps {
preserveState?: boolean | ((props: PageProps) => boolean) | null
replace?: boolean
only?: string[]
except?: string[]
onCancelToken?: (cancelToken: import('axios').CancelTokenSource) => void
onBefore?: () => void
onStart?: () => void
Expand Down Expand Up @@ -59,6 +60,10 @@ const Link: InertiaLink = defineComponent({
type: Array<string>,
default: () => [],
},
except: {
type: Array<string>,
default: () => [],
},
headers: {
type: Object,
default: () => ({}),
Expand Down Expand Up @@ -96,6 +101,7 @@ const Link: InertiaLink = defineComponent({
preserveScroll: props.preserveScroll,
preserveState: props.preserveState ?? method !== 'get',
only: props.only,
except: props.except,
headers: props.headers,
// @ts-expect-error
onCancelToken: attrs.onCancelToken || (() => ({})),
Expand Down

0 comments on commit 680b2eb

Please sign in to comment.