Skip to content

Commit

Permalink
Allow user to specify custom stores (#676)
Browse files Browse the repository at this point in the history
* custom stores can be specified

* update snapshots

* changeset

* unused import
  • Loading branch information
AlecAivazis authored Nov 5, 2022
1 parent 8ba4c3e commit b7a07a3
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 98 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-seahorses-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini-svelte': patch
---

Add config for users to specify custom stores
22 changes: 22 additions & 0 deletions packages/houdini-svelte/src/plugin/codegen/stores/custom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Config } from 'houdini'

import type { HoudiniVitePluginConfig } from '../../'
import { plugin_config } from '../../kit'

export function store_import(
cfg: Config,
which: keyof Required<HoudiniVitePluginConfig>['customStores']
): { statement: string; store_class: string } {
// look up the import string for the store
const store_string = plugin_config(cfg).customStores[which]!

// the last separates the import path from the exported module
const parts = store_string.split('.')
const import_path = parts.slice(0, -1).join('.')
const store_class = parts[parts.length - 1]

return {
statement: `import { ${store_class} } from '${import_path}'`,
store_class,
}
}
23 changes: 13 additions & 10 deletions packages/houdini-svelte/src/plugin/codegen/stores/fragment.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { CollectedGraphQLDocument, fs, GenerateHookInput, path } from 'houdini'

import { HoudiniVitePluginConfig } from '../..'
import { global_store_name, stores_directory, store_name } from '../../kit'
import { store_import } from './custom'

export async function generateFragmentStore(
export async function fragmentStore(
{ config, plugin_root }: GenerateHookInput,
doc: CollectedGraphQLDocument
) {
Expand All @@ -14,18 +16,19 @@ export async function generateFragmentStore(
const paginationMethod = doc.refetch?.method

// in order to build the store, we need to know what class we're going to import from
let queryClass = 'FragmentStore'
let which: keyof Required<HoudiniVitePluginConfig>['customStores'] = 'fragment'
if (paginationMethod === 'cursor') {
queryClass =
which =
doc.refetch?.direction === 'forward'
? 'FragmentStoreForwardCursor'
: 'FragmentStoreBackwardCursor'
? 'fragmentForwardsCursor'
: 'fragmentBackwardsCursor'
} else if (paginationMethod === 'offset') {
queryClass = 'FragmentStoreOffset'
which = 'fragmentOffset'
}
const { statement, store_class } = store_import(config, which)

// store definition
const storeContent = `import { ${queryClass} } from '../runtime/stores'
const storeContent = `${statement}
import artifact from '$houdini/artifacts/${artifactName}'
${
paginationMethod
Expand All @@ -37,7 +40,7 @@ ${
// create the query store
export class ${storeName} extends ${queryClass} {
export class ${storeName} extends ${store_class} {
constructor() {
super({
artifact,
Expand All @@ -56,9 +59,9 @@ export default ${globalStoreName}
const _data = `${artifactName}$data`

// the type definitions for the store
const typeDefs = `import type { ${_data}, ${queryClass}, QueryStoreFetchParams} from '$houdini'
const typeDefs = `import type { ${_data}, ${store_class}, QueryStoreFetchParams} from '$houdini'
export declare class ${storeName} extends ${queryClass}<${_data}, {}> {
export declare class ${storeName} extends ${store_class}<${_data}, {}> {
constructor() {
// @ts-ignore
super({})
Expand Down
16 changes: 8 additions & 8 deletions packages/houdini-svelte/src/plugin/codegen/stores/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { cleanupFiles, fs, ArtifactKind, GenerateHookInput, path } from 'houdini'

import { stores_directory } from '../../kit'
import { generateFragmentStore } from './fragment'
import { generateIndividualStoreMutation } from './mutation'
import { generateIndividualStoreQuery } from './query'
import { generateSubscriptionStore } from './subscription'
import { fragmentStore } from './fragment'
import { mutationStore } from './mutation'
import { queryStore } from './query'
import { subscriptionStore } from './subscription'

export default async function storesGenerator(input: GenerateHookInput) {
const { config, documents } = input
Expand All @@ -19,13 +19,13 @@ export default async function storesGenerator(input: GenerateHookInput) {
}

if (doc.kind === ArtifactKind.Query) {
listOfStores.push(await generateIndividualStoreQuery(input, doc))
listOfStores.push(await queryStore(input, doc))
} else if (doc.kind === ArtifactKind.Mutation) {
listOfStores.push(await generateIndividualStoreMutation(input, doc))
listOfStores.push(await mutationStore(input, doc))
} else if (doc.kind === ArtifactKind.Subscription) {
listOfStores.push(await generateSubscriptionStore(input, doc))
listOfStores.push(await subscriptionStore(input, doc))
} else if (doc.kind === ArtifactKind.Fragment) {
listOfStores.push(await generateFragmentStore(input, doc))
listOfStores.push(await fragmentStore(input, doc))
}
})
)
Expand Down
12 changes: 7 additions & 5 deletions packages/houdini-svelte/src/plugin/codegen/stores/mutation.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { CollectedGraphQLDocument, fs, path, GenerateHookInput } from 'houdini'

import { global_store_name, stores_directory, store_name } from '../../kit'
import { store_import } from './custom'

export async function generateIndividualStoreMutation(
export async function mutationStore(
{ config, plugin_root }: GenerateHookInput,
doc: CollectedGraphQLDocument
) {
const fileName = doc.name
const storeName = store_name({ config, name: doc.name })
const globalStoreName = global_store_name({ config, name: doc.name })
const artifactName = `${doc.name}`
const { statement, store_class } = store_import(config, 'mutation')

// store content
const storeData = `import artifact from '$houdini/artifacts/${artifactName}'
import { MutationStore } from '../runtime/stores'
${statement}
export class ${storeName} extends MutationStore {
export class ${storeName} extends ${store_class} {
constructor() {
super({
artifact,
Expand All @@ -33,9 +35,9 @@ export default ${globalStoreName}
const _optimistic = `${artifactName}$optimistic`

// the type definitions for the store
const typeDefs = `import type { ${_input}, ${_data}, ${_optimistic}, MutationStore } from '$houdini'
const typeDefs = `import type { ${_input}, ${_data}, ${_optimistic}, ${store_class} } from '$houdini'
export declare class ${storeName} extends MutationStore<${_data} | undefined, ${_input}, ${_optimistic}>{
export declare class ${storeName} extends ${store_class}<${_data} | undefined, ${_input}, ${_optimistic}>{
constructor() {
// @ts-ignore
super({})
Expand Down
18 changes: 9 additions & 9 deletions packages/houdini-svelte/src/plugin/codegen/stores/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ test('basic store', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -97,7 +97,7 @@ test('change globalStorePrefix to "yop___"', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -149,7 +149,7 @@ test('change globalStorePrefix to ""', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -194,7 +194,7 @@ test('store with required variables', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -239,7 +239,7 @@ test('store with nullable variables', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -286,7 +286,7 @@ test('store with non-null variables with default value', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStore } from '../runtime/stores'
import { QueryStore } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -341,7 +341,7 @@ test('forward cursor pagination', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStoreForwardCursor } from '../runtime/stores'
import { QueryStoreForwardCursor } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -396,7 +396,7 @@ test('backwards cursor pagination', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStoreBackwardCursor } from '../runtime/stores'
import { QueryStoreBackwardCursor } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down Expand Up @@ -447,7 +447,7 @@ test('offset pagination', async function () {

// check the file contents
await expect(parsed).toMatchInlineSnapshot(`
import { QueryStoreOffset } from '../runtime/stores'
import { QueryStoreOffset } from '$houdini/plugins/houdini-svelte/runtime/stores'
import artifact from '$houdini/artifacts/TestQuery'
// create the query store
Expand Down
23 changes: 12 additions & 11 deletions packages/houdini-svelte/src/plugin/codegen/stores/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import * as graphql from 'graphql'
import { CollectedGraphQLDocument, GenerateHookInput, path } from 'houdini'
import { operation_requires_variables, fs } from 'houdini'

import type { HoudiniVitePluginConfig } from '../..'
import { global_store_name, stores_directory, store_name } from '../../kit'
import { store_import } from './custom'

export async function generateIndividualStoreQuery(
export async function queryStore(
{ config, plugin_root }: GenerateHookInput,
doc: CollectedGraphQLDocument
) {
Expand All @@ -27,23 +29,22 @@ export async function generateIndividualStoreQuery(
const paginationMethod = doc.refetch?.paginated && doc.refetch.method

// in order to build the store, we need to know what class we're going to import from
let queryClass = 'QueryStore'
let which: keyof Required<HoudiniVitePluginConfig>['customStores'] = 'query'
if (paginationMethod === 'cursor') {
queryClass =
doc.refetch?.direction === 'forward'
? 'QueryStoreForwardCursor'
: 'QueryStoreBackwardCursor'
which =
doc.refetch?.direction === 'forward' ? 'queryForwardsCursor' : 'queryBackwardsCursor'
} else if (paginationMethod === 'offset') {
queryClass = 'QueryStoreOffset'
which = 'queryOffset'
}

// store definition
const storeData = `import { ${queryClass} } from '../runtime/stores'
const { store_class, statement } = store_import(config, which)
const storeData = `${statement}
import artifact from '$houdini/artifacts/${artifactName}'
// create the query store
export class ${storeName} extends ${queryClass} {
export class ${storeName} extends ${store_class} {
constructor() {
super({
artifact,
Expand Down Expand Up @@ -72,9 +73,9 @@ export default ${globalStoreName}
const _data = `${artifactName}$result`

// the type definitions for the store
const typeDefs = `import type { ${_input}, ${_data}, ${queryClass}, QueryStoreFetchParams} from '$houdini'
const typeDefs = `import type { ${_input}, ${_data}, ${store_class}, QueryStoreFetchParams} from '$houdini'
export declare class ${storeName} extends ${queryClass}<${_data}, ${_input}> {
export declare class ${storeName} extends ${store_class}<${_data}, ${_input}> {
constructor() {
// @ts-ignore
super({})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { CollectedGraphQLDocument, fs, GenerateHookInput, path } from 'houdini'

import { global_store_name, stores_directory, store_name } from '../../kit'
import { store_import } from './custom'

export async function generateSubscriptionStore(
export async function subscriptionStore(
{ config, plugin_root }: GenerateHookInput,
doc: CollectedGraphQLDocument
) {
Expand All @@ -11,11 +12,14 @@ export async function generateSubscriptionStore(
const globalStoreName = global_store_name({ config, name: doc.name })
const artifactName = `${doc.name}`

// figure out which store to use
const { store_class, statement } = store_import(config, 'subscription')

// the content of the store
const storeContent = `import artifact from '$houdini/artifacts/${artifactName}'
const storeContent = `${statement}
import { SubscriptionStore } from '../runtime/stores'
export class ${storeName} extends SubscriptionStore {
export class ${storeName} extends ${store_class} {
constructor() {
super({
artifact,
Expand All @@ -32,9 +36,9 @@ export default ${globalStoreName}
const _data = `${artifactName}$result`

// the type definitions for the store
const typeDefs = `import type { ${_input}, ${_data}, SubscriptionStore } from '$houdini'
const typeDefs = `import type { ${_input}, ${_data}, ${store_class} } from '$houdini'
export declare class ${storeName} extends SubscriptionStore<${_data} | undefined, ${_input}> {
export declare class ${storeName} extends ${store_class}<${_data} | undefined, ${_input}> {
constructor() {
// @ts-ignore
super({})
Expand Down
17 changes: 17 additions & 0 deletions packages/houdini-svelte/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,21 @@ export type HoudiniVitePluginConfig = {
* A flag to treat every component as a non-route. This is useful for projects built with the static-adapter
*/
static?: boolean

/**
* Override the classes used when building stores for documents. Values should take the form package.export
* For example, if you have a store exported from $lib/stores you should set the value to "$lib/stores.CustomStore".
*/
customStores?: {
query?: string
mutation?: string
subscription?: string
fragment?: string
queryForwardsCursor?: string
queryBackwardsCursor?: string
queryOffset?: string
fragmentForwardsCursor?: string
fragmentBackwardsCursor?: string
fragmentOffset?: string
}
}
17 changes: 17 additions & 0 deletions packages/houdini-svelte/src/plugin/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,23 @@ export function plugin_config(config: Config): Required<HoudiniVitePluginConfig>
layoutQueryFilename: '+layout.gql',
quietQueryErrors: false,
static: false,
customStores: {
query: '$houdini/plugins/houdini-svelte/runtime/stores.QueryStore',
mutation: '$houdini/plugins/houdini-svelte/runtime/stores.MutationStore',
fragment: '$houdini/plugins/houdini-svelte/runtime/stores.FragmentStore',
subscription: '$houdini/plugins/houdini-svelte/runtime/stores.SubscriptionStore',
queryForwardsCursor:
'$houdini/plugins/houdini-svelte/runtime/stores.QueryStoreForwardCursor',
queryBackwardsCursor:
'$houdini/plugins/houdini-svelte/runtime/stores.QueryStoreBackwardCursor',
queryOffset: '$houdini/plugins/houdini-svelte/runtime/stores.QueryStoreOffset',
fragmentForwardsCursor:
'$houdini/plugins/houdini-svelte/runtime/stores.FragmentStoreForwardCursor',
fragmentBackwardsCursor:
'$houdini/plugins/houdini-svelte/runtime/stores.FragmentStoreBackwardCursor',
fragmentOffset: '$houdini/plugins/houdini-svelte/runtime/stores.FragmentStoreOffset',
...cfg?.customStores,
},
...cfg,
}
}
Expand Down
Loading

2 comments on commit b7a07a3

@vercel
Copy link

@vercel vercel bot commented on b7a07a3 Nov 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b7a07a3 Nov 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs-next – ./site

docs-next-houdinigraphql.vercel.app
docs-next-kohl.vercel.app
docs-next-git-main-houdinigraphql.vercel.app

Please sign in to comment.