Skip to content

Commit

Permalink
Add event to mutate (#847)
Browse files Browse the repository at this point in the history
* enter prerelease mode

* HoudiniClient Plugins (#834)

* create e2e project

* init houdini

* use env var for token

* update lock

* update

* accept liveQuery handler as 3rd argument for now

* clean up deprecation warnings

* persist live flag in artifact

* add live to artifact type

* add liveQuery to store

* close EventSource when unsubscribing

* liveQueryHandler takes an updater instead of just returning a raw value

* use third party apply_patch for grafbase test

* pass session to LiveQueryHandler

* remove logs

* handle errors

* start document observer

* failing test and start store implementation

* fixed all tests except lists

* all tests pass

* map subs to spec in one place

* update snapshots

* remove live from artifact

* another failing test

* first pass at middleware iterator

* remove unused import

* temporary names for phases

* fix error when invoking first terminate

* tweak docs

* exception handling

* cleanup phase

* tweak

* move client logic to special directory

* add skeleton for rest of middlewares

* fetch gives full payload

* rename file

* rename document observer stages ; track loading state

* naming tweaks

* naming and comments

* plugins can specify client plugins

* passing null to client_plugins prevents function invocation

* accept url and fetchParams functions

* users can't provide plugins and pipelines together

* rework fetch plugin

* start implementating plugins

* implement input and mutation plugin ; fix fetching state tracking

* update tests

* random tidyness

* failing test

* query plugin includes last used variables in outbound requests

* update variables before subscribing in query

* move variable tracking into document observer

* marshalVariables and variablesChanged from handlers

* can check if variables changed right after assigning it

* mutation clears layer if there is a network error

* quietErrors happens at the network level now

* first pass at subscriptions

* typos

* tests pass

* tidy up type names

* strengthen test

* clean up typedefs

* improved idempotency

* rename plugin.error to plugin.throw

* query plugin uses marshaled variables

* start implementation query store

* implement query, subscription, and mutation

* query pagination

* unused imports

* make import logic synchronous

* everything builds!!

* fix import tests

* move injected plugins into plugins directory

* use getCurrentClient in houdini-react

* fix imports

* subscribe on the way out

* better hook wrapping

* update snapshot

* test cache policy

* add loading state checks to tests

* dont specify pipeline on client

* remove App.Sessions

* query pagination works!

* fix component queries

* more tests passing

* fix fragment cursor pagination

* fragment offset and metadata tests

* mutation initial state

* more tests

* fixed more tests

* remove logging

* ⚡ UPDATE: App Metadata & Session

* 🚀 UPDATE: libReporter config

* update snapshots

* move client retrieval into houdini-svelte

* plugin client_plugins can be specified as a function of config file and plugin config

* add throwOnError config

* can update store state from handle

* setup test

* flatten client plugin hook names

* update init and release notes

* update documentPlugin wrapper for new keywords

* update release notes and subscription setup

* remove index from doc frontmatter

* add doc page for client

* flesh out client docs more

* @manual_load directive & fetching default. (#831)

* ✨ NEW: info in artifact

* ✨ NEW: default init value

* 🐛 FIX: the test to be coherent!

* ✏️ UPDATE: changeset

* 🐛 FIX: lint

* ⚡ IMPROVE: serializeValue to have keys quoted

* ✨ NEW: artifact.pluginsData

* 🚧 UPDATE: all artifacts + check 1 test + docs to doc

* 🐛 FIX: defautl default is false

* 👌 FIX: lint

* 🚸 UPDATE: having the right default for core and the right tests for core

* 💡 IMPROVE: with libReporter (to comment if any config change)

* 👌 FIX: lint

* 👌 FIX: linting

* start on client plugin section

* flesh out plugin overview

* start on your first plugin

* add second plugin example

* add type definition to plugin docs

* add enter and exit phase sections

* more doc updates

* pull out data sources section

* reorder subsections

* add beforeNetwork phase

* tweak sizing and spacing of diagram

* note change of quietQueryErrors in release notes

* add $houdini/plugins export

* add section on Choosing a Phase

* update example

* subscription handler is now a function of the ClientPlugin context

* add changeset

* remove unused import

* linter

* more type imports

* make sure that the plugin root directory exists

* fix graphql return type generator

* enter prerelease mode

* start from 1.0.0-next.1 to cover last mistake

* 🎨 UPDATE: zoomable component (first use: Workflow)

* ✏️ FIX: link & mini typo

* 🎨 IMPROVE: colors

* feedback

* remove grafbase e2e test

* move pipeline config to deep dive

* comment tweak

* grammar

* add links to source of truth for typedefs

* start on fetchParams specifying body

* fetchParams can specify body

* update automatic persisted queries

* better comments

* document App.Stuff

* tweak comment

* detect spread values

* rename file

* remove unused config value

* add fragments to home page

* remove test

* rename DocumentObserver to DocumentStore

* better subscription auth logic

* client-plugin review

* add typedefs for throwOnError and fetchParams

* tweak words

* punctuation

* fix build errors

* start single step document store

* forgot to commit something

* fix document store

* add test for error throw

* remove log

* consolidate error handling

* update docs

* remove log

* fix build errors

* choosing a phase after enter vs exit

* wether -> whether

* punctuation

* small tweaks

* more tweaks

* add caption

* one word

Co-authored-by: jycouet <[email protected]>

* remove log

* 📦 v1.0.0-next.2 (next) (#838)

* 📦 v{VERSION} (next)

* fix changesets

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Alec Aivazis <[email protected]>

* tidy up changelogs

* Restructure programatic cache api (#841)

* fragment stores need to provide an artifact

* first pass at Record.write

* unused import

* update snapshot

* list handlers work

* move FragmentValue utility type to types file

* changeset

* linter

* start on docs and add cache.read and cache.write

* nest fragment under fragment key when writing to records

* document cache.read and cache.write

* sketch out query type

* add query type definitions to CacheDef

* query variables in imperative type def

* generate query definitions

* unused imports

* unused import

* fixed tests

* fragment inputs are persisted in artifacts

* generate input type definitions and wire up variable marhsaling

* read and write variables with arguments

* update docs

* add links to fragment args docs

* replace @manual_load with @load

* changeset

* update docs

* update release notes

* update api welcome page cache section

* fix import type

* update tests

* typo in docs

* simpler second step

* soften second step

* cleanup

* cleanup cleanup

* graphql tag should return never in default case since that means the query wasn't recognized

* make imperative types more responsive when saving

* cleanup

* fix e2e test type

* e2e check

* grammar

* explicitly mention that manual_load is gone

* remove log

* Consolidate schema polling config (#842)

* move all schema polling things into config.watchSchema

* update docs

* fix documented watchSchema params

* update init command

* more doc updates

* clean up examples

* changeset

* 📦 v1.0.0-next.3 (next) (#843)

* 📦 v{VERSION} (next)

* tidy up changelogs

* more cleanup

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Alec Aivazis <[email protected]>

* pass session to mutation

* changeset

Co-authored-by: jycouet <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
4 people committed Feb 10, 2023
1 parent 7e4e27e commit cc85c88
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-yaks-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini-svelte': patch
---

Add event argument to mutation for server-side operations
3 changes: 3 additions & 0 deletions e2e/sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"api": "cross-env TZ=utc e2e-api",
"dev": "concurrently \"pnpm run web\" \"pnpm run api\" -n \"web,api\" -c \"green,magenta\"",
"build": "vite build",
"build:": "cd ../../ && run build && cd -",
"build:dev": "pnpm build: && pnpm dev",
"build:test": "pnpm build: && pnpm test",
"package": "svelte-kit package",
"previewWeb": "vite preview --port 3007",
"preview": "concurrently \"pnpm run previewWeb\" \"pnpm run api\" -n \"web,api\" -c \"green,magenta\"",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ export const actions = {
}
`);

return await actionMutation.mutate({ name });
return await actionMutation.mutate({ name }, { event });
}
};
15 changes: 12 additions & 3 deletions packages/houdini-svelte/src/runtime/stores/mutation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { DocumentStore } from '$houdini/runtime/client'
import type { MutationArtifact } from '$houdini/runtime/lib/types'
import type { GraphQLObject } from '$houdini/runtime/lib/types'
import type { RequestEvent } from '@sveltejs/kit'

import { getClient } from '../client'
import { getSession } from '../session'
import { fetchParams } from './query'

export class MutationStore<
_Data extends GraphQLObject,
Expand All @@ -25,19 +26,27 @@ export class MutationStore<
{
metadata,
fetch,
event,
...mutationConfig
}: {
// @ts-ignore
metadata?: App.Metadata
fetch?: typeof globalThis.fetch
event?: RequestEvent
} & MutationConfig<_Data, _Input, _Optimistic> = {}
): Promise<_Data> {
const { context } = await fetchParams(this.artifact, this.artifact.name, {
fetch,
metadata,
event,
})

return (
await this.store.send({
variables,
fetch,
fetch: context.fetch,
metadata,
session: await getSession(),
session: context.session,
stuff: {
...mutationConfig,
},
Expand Down
12 changes: 9 additions & 3 deletions packages/houdini-svelte/src/runtime/stores/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import type { FetchContext } from '$houdini/runtime/client/plugins/fetch'
import * as log from '$houdini/runtime/lib/log'
import type {
QueryArtifact,
MutationArtifact,
GraphQLObject,
HoudiniFetchContext,
QueryResult,
} from '$houdini/runtime/lib/types'
import { ArtifactKind } from '$houdini/runtime/lib/types'
// internals
import { CachePolicy, CompiledQueryKind } from '$houdini/runtime/lib/types'
import type { LoadEvent, RequestEvent } from '@sveltejs/kit'
Expand Down Expand Up @@ -183,17 +185,17 @@ export type StoreConfig<_Data extends GraphQLObject, _Input, _Artifact> = {
}

export async function fetchParams<_Data extends GraphQLObject, _Input>(
artifact: QueryArtifact,
artifact: QueryArtifact | MutationArtifact,
storeName: string,
params?: QueryStoreFetchParams<_Data, _Input>
): Promise<{
context: FetchContext
policy: CachePolicy
policy: CachePolicy | undefined
params: QueryStoreFetchParams<_Data, _Input>
}> {
// figure out the right policy
let policy = params?.policy
if (!policy) {
if (!policy && artifact.kind === ArtifactKind.Query) {
// use the artifact policy as the default, otherwise prefer the cache over the network
policy = artifact.policy ?? CachePolicy.CacheOrNetwork
}
Expand Down Expand Up @@ -244,11 +246,15 @@ Please remember to pass event to fetch like so:
import type { LoadEvent } from '@sveltejs/kit';
// in a load function...
export async function load(${log.yellow('event')}: LoadEvent) {
return {
...load_${storeName}({ ${log.yellow('event')}, variables: { ... } })
};
}
// in a server-side mutation:
await mutation.mutate({ ... }, ${log.yellow('{ event }')})
`

type FetchGlobalParams<_Data extends GraphQLObject, _Input> = {
Expand Down
11 changes: 9 additions & 2 deletions packages/houdini/src/runtime/client/plugins/fetchParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ export const fetchParamsPlugin: (fn?: FetchParamFn) => ClientPlugin =
next({
...ctx,
fetchParams: fn({
...ctx,
// most of the stuff comes straight from the context
config: ctx.config,
policy: ctx.policy,
metadata: ctx.metadata,
session: ctx.session,
stuff: ctx.stuff,
// a few fields are renamed or modified
document: ctx.artifact,
variables: marshalVariables(ctx),
text: ctx.artifact.raw,
hash: ctx.artifact.hash,
Expand All @@ -25,5 +32,5 @@ export type FetchParamsInput = Pick<
> & {
text: string
hash: string
artifact: DocumentArtifact
document: DocumentArtifact
}
2 changes: 1 addition & 1 deletion site/src/routes/api/mutation/+page.svx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const actions: Actions = {
}
`)

return await actionMutation.mutate({ name }, event)
return await actionMutation.mutate({ name }, { event })
}
}
```
Expand Down
22 changes: 22 additions & 0 deletions site/src/routes/guides/release-notes/+page.svx
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,28 @@ has become mostly used for "lazy" stores that don't fetch automatically. On top
new imperative cache api relies heavily on `graphql` documents which would mean a lot of accidental
loading. At least this way everything is very explicit.

### Server-side Mutations Need an Event

In order to simplify the mental model for sessions and fetching, server-side mutations
need their event passed explicitly.

```diff
import { Actions } from './$types'

const actionMutation = graphql(...)

export const actions: Actions = {
addUser: async (event) => {
const data = await event.request.formData();

const name = data.get('name')?.toString();

- return await actionMutation.mutate({ name }, { fetch: event.fetch });
+ return await actionMutation.mutate({ name }, { event });
}
}
```

## 0.20.0

This release was originally planned to be `1.0` but we have some exciting stuff planned
Expand Down

0 comments on commit cc85c88

Please sign in to comment.