diff --git a/.changeset/nasty-llamas-refuse.md b/.changeset/nasty-llamas-refuse.md new file mode 100644 index 0000000000..e3c9b2b03d --- /dev/null +++ b/.changeset/nasty-llamas-refuse.md @@ -0,0 +1,5 @@ +--- +'houdini-svelte': patch +--- + +fix: queries will be sent once if they are defined in +(page|layout).gql diff --git a/packages/houdini-svelte/src/plugin/codegen/adapter.ts b/packages/houdini-svelte/src/plugin/codegen/adapter.ts deleted file mode 100644 index 826397e715..0000000000 --- a/packages/houdini-svelte/src/plugin/codegen/adapter.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { fs, path } from 'houdini' - -import { PluginGenerateInput } from '.' - -export default async function generateAdapter({ config, framework }: PluginGenerateInput) { - // we only need to generate an adapter for kit (the default one is fine for vanilla svelte) - if (framework !== 'kit') { - return - } - - // the location of the adapter - const adapterLocation = path.join(config.pluginRuntimeDirectory('houdini-svelte'), 'adapter.js') - - // figure out which adapter we need to lay down - const adapter = { - kit: sveltekitAdapter, - }[framework] - - // write the index file that exports the runtime - await fs.mkdirp(path.dirname(adapterLocation)) - await fs.writeFile(adapterLocation, adapter) -} - -const sveltekitAdapter = `import { goto as go } from '$app/navigation' -import { get } from 'svelte/store'; -import { browser, prerendering } from '$app/environment' -import { page } from '$app/stores' -import { error as svelteKitError } from '@sveltejs/kit' - -export function goTo(location, options) { - go(location, options) -} - -export const isBrowser = browser - -export let clientStarted = false; - -export function setClientStarted() { - clientStarted = true -} - -export const isPrerender = prerendering - -export const error = svelteKitError -` diff --git a/packages/houdini-svelte/src/plugin/codegen/index.ts b/packages/houdini-svelte/src/plugin/codegen/index.ts index 613b073402..ddb8efff98 100644 --- a/packages/houdini-svelte/src/plugin/codegen/index.ts +++ b/packages/houdini-svelte/src/plugin/codegen/index.ts @@ -1,7 +1,6 @@ import { GenerateHookInput, fs, Config } from 'houdini' import { stores_directory, type_route_dir } from '../kit' -import adapter from './adapter' import components from './components' import kit from './routes' import stores from './stores' @@ -15,7 +14,6 @@ export default async function (input: PluginGenerateInput) { // generate the files await Promise.all([ - adapter(input), kit(input.framework, input), stores(input), components(input.framework, input), diff --git a/packages/houdini-svelte/src/plugin/imports.ts b/packages/houdini-svelte/src/plugin/imports.ts deleted file mode 100644 index 6ba0f26c5e..0000000000 --- a/packages/houdini-svelte/src/plugin/imports.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Config, Script } from 'houdini' -import { ensure_imports } from 'houdini/vite' -import recast from 'recast' - -import { store_import_path } from './kit' - -type Identifier = recast.types.namedTypes.Identifier - -export function store_import({ - config, - script, - artifact, - local, -}: { - config: Config - script: Script - artifact: { name: string } - local?: string -}): { id: Identifier; added: number } { - const { ids, added } = ensure_imports({ - config, - script, - sourceModule: store_import_path({ config, name: artifact.name }), - import: `GQL_${artifact.name}`, - }) - - return { id: ids, added } -} diff --git a/packages/houdini-svelte/src/plugin/index.ts b/packages/houdini-svelte/src/plugin/index.ts index 67cc1a003d..94a7a65fb4 100644 --- a/packages/houdini-svelte/src/plugin/index.ts +++ b/packages/houdini-svelte/src/plugin/index.ts @@ -38,6 +38,34 @@ const HoudiniSveltePlugin: PluginFactory = async () => ({ return content.replace('HOUDINI_CLIENT_PATH', relativePath) }, + + 'adapter.js': ({ content }) => { + // dedicated sveltekit adapter. + const sveltekit_adapter = `import { goto as go } from '$app/navigation' +import { get } from 'svelte/store'; +import { browser, prerendering } from '$app/environment' +import { page } from '$app/stores' +import { error as svelteKitError } from '@sveltejs/kit' + +export function goTo(location, options) { + go(location, options) +} + +export const isBrowser = browser + +export let clientStarted = false; + +export function setClientStarted() { + clientStarted = true +} + +export const isPrerender = prerendering + +export const error = svelteKitError +` + + return framework === 'kit' ? sveltekit_adapter : content + }, }, // custom logic to pull a graphql document out of a svelte file diff --git a/packages/houdini-svelte/src/plugin/kit.ts b/packages/houdini-svelte/src/plugin/kit.ts index 5a20d56d68..a160645bb7 100644 --- a/packages/houdini-svelte/src/plugin/kit.ts +++ b/packages/houdini-svelte/src/plugin/kit.ts @@ -69,11 +69,12 @@ export function is_root_layout_script(config: Config, filename: string) { ) } -export function is_layout_component(config: Config, filename: string) { - return ( - resolve_relative(config, filename).replace(config.projectRoot, '').replace('.ts', '.js') === - path.sep + path.join('src', 'routes', '+layout.svelte') - ) +export function is_layout_component(framework: Framework, filename: string) { + return framework === 'kit' && filename.endsWith('+layout.svelte') +} + +export function is_layout(framework: Framework, filename: string) { + return is_layout_script(framework, filename) || is_layout_component(framework, filename) } export function is_component(config: Config, framework: Framework, filename: string) { @@ -203,7 +204,7 @@ export async function walk_routes( } // inline layout queries - else if (is_layout_component(config, child)) { + else if (is_layout_component(framework, child)) { // load the contents and parse it const contents = await fs.readFile(childPath) if (!contents) { diff --git a/packages/houdini-svelte/src/plugin/transforms/kit/load.test.ts b/packages/houdini-svelte/src/plugin/transforms/kit/load.test.ts index 49498108a6..9fe52171b7 100644 --- a/packages/houdini-svelte/src/plugin/transforms/kit/load.test.ts +++ b/packages/houdini-svelte/src/plugin/transforms/kit/load.test.ts @@ -369,10 +369,10 @@ describe('kit route processor', function () { `) expect(route.script).toMatchInlineSnapshot(` import GQL_MyQuery1 from "$houdini/plugins/houdini-svelte/stores/MyQuery1"; + import { load_TestQuery } from "$houdini/plugins/houdini-svelte/stores/TestQuery"; import GQL_MyQuery2 from "$houdini/plugins/houdini-svelte/stores/MyQuery2"; import { load_MyQuery2 } from "$houdini/plugins/houdini-svelte/stores/MyQuery2"; import { load_MyQuery1 } from "$houdini/plugins/houdini-svelte/stores/MyQuery1"; - import { load_TestQuery } from "$houdini/plugins/houdini-svelte/stores/TestQuery"; import { getCurrentConfig } from "$houdini/runtime/lib/config"; import { RequestContext } from "$houdini/plugins/houdini-svelte/runtime/session"; import GQL_TestQuery from "$houdini/plugins/houdini-svelte/stores/TestQuery"; @@ -386,14 +386,6 @@ describe('kit route processor', function () { const houdiniConfig = await getCurrentConfig(); const promises = []; const inputs = {}; - inputs["TestQuery"] = {}; - - promises.push(load_TestQuery({ - "variables": inputs["TestQuery"], - "event": context, - "blocking": false - })); - inputs["MyQuery1"] = {}; promises.push(load_MyQuery1({ @@ -414,6 +406,14 @@ describe('kit route processor', function () { "blocking": false })); + inputs["TestQuery"] = {}; + + promises.push(load_TestQuery({ + "variables": inputs["TestQuery"], + "event": context, + "blocking": false + })); + let result = {}; try { @@ -444,6 +444,7 @@ describe('kit route processor', function () { expect(route.component).toMatchInlineSnapshot( 'import GQL_TestPageQuery from "$houdini/plugins/houdini-svelte/stores/TestPageQuery";' ) + expect(route.script).toMatchInlineSnapshot(` import { load_TestPageQuery } from "$houdini/plugins/houdini-svelte/stores/TestPageQuery"; import { getCurrentConfig } from "$houdini/runtime/lib/config"; @@ -477,6 +478,32 @@ describe('kit route processor', function () { }; } `) + + expect(route.layout).toMatchInlineSnapshot(` + import { page } from "$app/stores"; + import { extractSession, setClientSession } from "$houdini/plugins/houdini-svelte/runtime/session"; + import { onMount } from "svelte"; + import { setClientStarted } from "$houdini/plugins/houdini-svelte/runtime/adapter"; + import GQL_TestPageQuery from "$houdini/plugins/houdini-svelte/stores/TestPageQuery"; + onMount(() => setClientStarted()); + + page.subscribe(val => { + setClientSession(extractSession(val.data)); + }); + `) + + expect(route.layout_script).toMatchInlineSnapshot(` + import GQL_TestPageQuery from "$houdini/plugins/houdini-svelte/stores/TestPageQuery"; + + export async function load(event) { + const __houdini__vite__plugin__return__value__ = {}; + + return { + ...event.data, + ...__houdini__vite__plugin__return__value__ + }; + } + `) }) test('route with +layout.gql query', async function () { @@ -493,6 +520,24 @@ describe('kit route processor', function () { expect(route.component).toMatchInlineSnapshot( 'import GQL_TestLayoutQuery from "$houdini/plugins/houdini-svelte/stores/TestLayoutQuery";' ) + + expect(route.script).toMatchInlineSnapshot( + 'import GQL_TestLayoutQuery from "$houdini/plugins/houdini-svelte/stores/TestLayoutQuery";' + ) + + expect(route.layout).toMatchInlineSnapshot(` + import { page } from "$app/stores"; + import { extractSession, setClientSession } from "$houdini/plugins/houdini-svelte/runtime/session"; + import { onMount } from "svelte"; + import { setClientStarted } from "$houdini/plugins/houdini-svelte/runtime/adapter"; + import GQL_TestLayoutQuery from "$houdini/plugins/houdini-svelte/stores/TestLayoutQuery"; + onMount(() => setClientStarted()); + + page.subscribe(val => { + setClientSession(extractSession(val.data)); + }); + `) + expect(route.layout_script).toMatchInlineSnapshot(` import { load_TestLayoutQuery } from "$houdini/plugins/houdini-svelte/stores/TestLayoutQuery"; import { getCurrentConfig } from "$houdini/runtime/lib/config"; diff --git a/packages/houdini-svelte/src/plugin/transforms/kit/load.ts b/packages/houdini-svelte/src/plugin/transforms/kit/load.ts index fa396ca01c..cb4ebbf01b 100644 --- a/packages/houdini-svelte/src/plugin/transforms/kit/load.ts +++ b/packages/houdini-svelte/src/plugin/transforms/kit/load.ts @@ -11,6 +11,7 @@ import { parseSvelte } from '../../extract' import { extract_load_function } from '../../extractLoadFunction' import { HoudiniRouteScript, + is_layout, is_route, is_route_script, layout_query_path, @@ -63,21 +64,30 @@ export default async function kit_load_generator(page: SvelteTransformPage) { find_page_info(page), ]) - const queries = inline_queries.concat(layout_query ?? []).concat(page_query ?? []) + const houdini_load_queries = [] for (const [i, target] of (page_info.houdini_load ?? []).entries()) { - queries.push({ + houdini_load_queries.push({ name: target.name!.value, variables: operation_requires_variables(target), store_id: AST.memberExpression(AST.identifier('houdini_load'), AST.literal(i)), }) } - // if we are processing a route config file (+page.ts) + // add the load functions if (script) { - // add the load function to the query file + const queries_that_needs_a_load = [...houdini_load_queries, ...inline_queries] + // Add special queries files to the list only if we are in the good context + const isLayout = is_layout(page.framework, page.filepath) + if (isLayout && layout_query) { + queries_that_needs_a_load.push(layout_query) + } + if (!isLayout && page_query) { + queries_that_needs_a_load.push(page_query) + } + add_load({ page, - queries, + queries: queries_that_needs_a_load, page_info, }) } diff --git a/packages/houdini/src/cmd/init.ts b/packages/houdini/src/cmd/init.ts index e776f3318e..a349dc4f63 100644 --- a/packages/houdini/src/cmd/init.ts +++ b/packages/houdini/src/cmd/init.ts @@ -298,9 +298,9 @@ async function tjsConfig(targetPath: string, framework: 'kit' | 'svelte') { // new rootDirs (will overwrite the one in "extends": "./.svelte-kit/tsconfig.json") if (framework === 'kit') { - tjsConfig.compilerOptions.rootDirs = ['.', './.svelte-kit/types', './.$houdini/types'] + tjsConfig.compilerOptions.rootDirs = ['.', './.svelte-kit/types', './$houdini/types'] } else { - tjsConfig.compilerOptions.rootDirs = ['.', './.$houdini/types'] + tjsConfig.compilerOptions.rootDirs = ['.', './$houdini/types'] } // In kit, no need to add manually the path. Why? Because: diff --git a/site/src/routes/guides/release-notes.svx b/site/src/routes/guides/release-notes.svx index 230c407eb8..127647f4b5 100644 --- a/site/src/routes/guides/release-notes.svx +++ b/site/src/routes/guides/release-notes.svx @@ -183,7 +183,7 @@ In order to make this work, you have to change your tsconfig file to look like t ```json { "compilerOptions": { - "rootDirs": [".", "./.svelte-kit/types", "./.$houdini/types"] + "rootDirs": [".", "./.svelte-kit/types", "./$houdini/types"] } } ``` diff --git a/site/src/routes/guides/typescript.svx b/site/src/routes/guides/typescript.svx index 65dda350bb..ac5210309c 100644 --- a/site/src/routes/guides/typescript.svx +++ b/site/src/routes/guides/typescript.svx @@ -15,7 +15,7 @@ In order to setup your project to take full advantage of Houdini's generated typ ```json { "compilerOptions": { - "rootDirs": [".", "./.svelte-kit/types", "./.$houdini/types"] + "rootDirs": [".", "./.svelte-kit/types", "./$houdini/types"] } } ```