houdini-react 2.0.0-go.19 → 2.0.0-go.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "houdini-react",
3
- "version": "2.0.0-go.19",
3
+ "version": "2.0.0-go.20",
4
4
  "description": "The React plugin for houdini",
5
5
  "keywords": [
6
6
  "typescript",
@@ -36,7 +36,7 @@
36
36
  "graphql-yoga": "^4.0.4",
37
37
  "react": "^19.0.0",
38
38
  "react-dom": "^19.0.0",
39
- "react-streaming-compat": "^0.3.18",
39
+ "react-streaming": "^0.4.17",
40
40
  "recast": "^0.23.1",
41
41
  "rollup": "^4.28.1",
42
42
  "use-deep-compare-effect": "^1.8.1"
@@ -81,12 +81,12 @@
81
81
  }
82
82
  },
83
83
  "optionalDependencies": {
84
- "houdini-react-darwin-x64": "2.0.0-go.19",
85
- "houdini-react-darwin-arm64": "2.0.0-go.19",
86
- "houdini-react-linux-x64": "2.0.0-go.19",
87
- "houdini-react-linux-arm64": "2.0.0-go.19",
88
- "houdini-react-win32-x64": "2.0.0-go.19",
89
- "houdini-react-win32-arm64": "2.0.0-go.19"
84
+ "houdini-react-darwin-x64": "2.0.0-go.20",
85
+ "houdini-react-darwin-arm64": "2.0.0-go.20",
86
+ "houdini-react-linux-x64": "2.0.0-go.20",
87
+ "houdini-react-linux-arm64": "2.0.0-go.20",
88
+ "houdini-react-win32-x64": "2.0.0-go.20",
89
+ "houdini-react-win32-arm64": "2.0.0-go.20"
90
90
  },
91
91
  "bin": "bin/houdini-react",
92
92
  "scripts": {
package/postInstall.js CHANGED
@@ -5,7 +5,7 @@ const https = require('https')
5
5
  const child_process = require('child_process')
6
6
 
7
7
  // Adjust the version you want to install. You can also make this dynamic.
8
- const BINARY_DISTRIBUTION_VERSION = '2.0.0-go.19'
8
+ const BINARY_DISTRIBUTION_VERSION = '2.0.0-go.20'
9
9
 
10
10
  // Windows binaries end with .exe so we need to special case them.
11
11
  const binaryName = process.platform === 'win32' ? 'houdini-react.exe' : 'houdini-react'
package/runtime/client.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { HoudiniClient } from 'houdini/runtime/client'
1
+ import type { HoudiniClient } from '$houdini/runtime/client'
2
2
 
3
3
  // this file will be replaced by the code generation process
4
4
 
@@ -12,9 +12,9 @@ export function useFragment<
12
12
  _ReferenceType extends {},
13
13
  _Input extends GraphQLVariables = GraphQLVariables
14
14
  >(
15
- reference: _Data | { [fragmentKey]: _ReferenceType } | null,
15
+ reference: _Data | { ' $fragments': _ReferenceType } | null,
16
16
  document: { artifact: FragmentArtifact }
17
- ) {
17
+ ): _Data | null {
18
18
  const { cache } = useRouterContext()
19
19
 
20
20
  // get the fragment reference info
@@ -82,7 +82,7 @@ export function useFragment<
82
82
  }
83
83
 
84
84
  export function fragmentReference<_Data extends GraphQLObject, _Input, _ReferenceType extends {}>(
85
- reference: _Data | { [fragmentKey]: _ReferenceType } | null,
85
+ reference: _Data | { ' $fragments': _ReferenceType } | null,
86
86
  document: { artifact: FragmentArtifact }
87
87
  ): { variables: _Input; parent: string; loading: boolean } {
88
88
  // @ts-expect-error: typescript can't guarantee that the fragment key is defined
@@ -19,9 +19,9 @@ export function useFragmentHandle<
19
19
  _PaginationArtifact extends QueryArtifact,
20
20
  _Input extends GraphQLVariables = GraphQLVariables
21
21
  >(
22
- reference: _Data | { [fragmentKey]: _ReferenceType } | null,
22
+ reference: _Data | { ' $fragments': _ReferenceType } | null,
23
23
  document: { artifact: FragmentArtifact; refetchArtifact?: QueryArtifact }
24
- ): DocumentHandle<_PaginationArtifact, _Data, _Input> {
24
+ ): any {
25
25
  // get the fragment values
26
26
  const data = useFragment<_Data, _ReferenceType, _Input>(reference, document)
27
27
 
@@ -5,13 +5,8 @@ import { useQueryHandle } from './useQueryHandle'
5
5
 
6
6
  export function useQuery<
7
7
  _Artifact extends QueryArtifact,
8
- _Data extends GraphQLObject = GraphQLObject,
9
- _Input extends GraphQLVariables = GraphQLVariables
10
- >(
11
- document: { artifact: QueryArtifact },
12
- variables: any = null,
13
- config: UseQueryConfig = {}
14
- ): _Data {
15
- const { data } = useQueryHandle<_Artifact, _Data, _Input>(document, variables, config)
16
- return data
8
+ _Data extends GraphQLObject = GraphQLObject
9
+ >(document: { artifact: _Artifact }, variables: any = null, config: UseQueryConfig = {}): _Data {
10
+ const { data } = useQueryHandle<_Artifact, _Data>(document, variables, config)
11
+ return data as unknown as _Data
17
12
  }
@@ -33,7 +33,7 @@ export function useQueryHandle<
33
33
  { artifact }: { artifact: QueryArtifact },
34
34
  variables: any = null,
35
35
  config: UseQueryConfig = {}
36
- ): DocumentHandle<_Artifact, _Data, _Input> {
36
+ ): any {
37
37
  // figure out the identifier so we know what to look for
38
38
  const identifier = queryIdentifier({ artifact, variables, config })
39
39
 
@@ -0,0 +1,155 @@
1
+ import React from 'react'
2
+ import { hydrateRoot, createRoot } from 'react-dom/client'
3
+ import type { QueryArtifact, GraphQLVariables } from '$houdini/runtime'
4
+ import type { Cache } from '$houdini/runtime/cache'
5
+ import type { HoudiniClient } from '$houdini/runtime/client'
6
+ import cacheRef from '$houdini/runtime/cache'
7
+
8
+ import { injectComponents } from './componentFields'
9
+ import { router_cache, type RouterCache } from './routing'
10
+ import clientFactory from './client'
11
+
12
+ declare global {
13
+ interface Window {
14
+ __houdini__client__?: HoudiniClient
15
+ __houdini__pending_components__?: Record<string, any>
16
+ __houdini__cache__?: Cache
17
+ __houdini__hydration__layer__?: any
18
+ __houdini__initial__cache__?: any
19
+ __houdini__initial__session__?: any
20
+ __houdini__pending_artifacts__?: Record<string, QueryArtifact>
21
+ __houdini__pending_data__?: Record<string, any>
22
+ __houdini__pending_variables__?: Record<string, GraphQLVariables>
23
+ __houdini__nav_caches__?: RouterCache
24
+ }
25
+ }
26
+
27
+ export function hydrate_page(
28
+ App: React.ComponentType<any>,
29
+ Component: React.ComponentType<any>,
30
+ pageName: string,
31
+ pendingQueries: string[]
32
+ ) {
33
+ // set up the client using its internally-managed singleton cache (cacheRef).
34
+ // the client's cachePolicy and queryPlugin are closure-bound to cacheRef at
35
+ // construction time, so we must use that same instance as window.__houdini__cache__
36
+ // rather than creating a second cache and trying to wire them together afterward.
37
+ window.__houdini__client__ ??= clientFactory()
38
+ window.__houdini__cache__ ??= cacheRef
39
+
40
+ // configure the singleton for React component field support
41
+ if (window.__houdini__pending_components__) {
42
+ window.__houdini__client__.componentCache = window.__houdini__pending_components__
43
+ }
44
+ window.__houdini__cache__._internal_unstable.componentCache =
45
+ window.__houdini__client__.componentCache
46
+ window.__houdini__cache__._internal_unstable.createComponent = (
47
+ fn: React.ComponentType<any>,
48
+ props: any
49
+ ) => React.createElement(fn, props)
50
+
51
+ window.__houdini__hydration__layer__ ??=
52
+ window.__houdini__cache__._internal_unstable.storage.createLayer()
53
+
54
+ // rehydrate the cache from the server-serialized snapshot
55
+ window.__houdini__cache__?.hydrate(
56
+ window.__houdini__initial__cache__,
57
+ window.__houdini__hydration__layer__
58
+ )
59
+
60
+ // prime the data/artifact caches from anything the server streamed
61
+ const initialData: Record<string, any> = {}
62
+ const initialArtifacts: Record<string, QueryArtifact> = {}
63
+
64
+ for (const [artifactName, artifact] of Object.entries(
65
+ window.__houdini__pending_artifacts__ ?? {}
66
+ )) {
67
+ initialArtifacts[artifactName] = artifact
68
+
69
+ if (window.__houdini__pending_data__?.[artifactName]) {
70
+ const variables = window.__houdini__pending_variables__![artifactName]
71
+
72
+ if ((artifact as any).hasComponents) {
73
+ injectComponents({
74
+ cache: window.__houdini__cache__!,
75
+ selection: (artifact as any).selection,
76
+ data: window.__houdini__pending_data__[artifactName],
77
+ variables,
78
+ })
79
+ }
80
+
81
+ const observer = window.__houdini__client__!.observe({
82
+ artifact,
83
+ cache: window.__houdini__cache__,
84
+ initialValue: window.__houdini__cache__!.read({
85
+ selection: (artifact as any).selection,
86
+ variables,
87
+ }).data,
88
+ initialVariables: variables,
89
+ })
90
+
91
+ observer.send({
92
+ setup: true,
93
+ variables,
94
+ session: window.__houdini__initial__session__,
95
+ })
96
+
97
+ initialData[artifactName] = observer
98
+ }
99
+ }
100
+
101
+ if (!window.__houdini__nav_caches__) {
102
+ window.__houdini__nav_caches__ = router_cache({
103
+ pending_queries: pendingQueries,
104
+ initialData,
105
+ initialVariables: window.__houdini__pending_variables__,
106
+ initialArtifacts,
107
+ components: { [pageName]: Component },
108
+ })
109
+ _flush_pending_artifacts()
110
+ }
111
+
112
+ hydrateRoot(
113
+ document,
114
+ <App
115
+ initialURL={window.location.pathname}
116
+ cache={window.__houdini__cache__}
117
+ session={window.__houdini__initial__session__}
118
+ {...window.__houdini__nav_caches__}
119
+ />
120
+ )
121
+ }
122
+
123
+ const _pendingArtifacts: Array<[string, QueryArtifact]> = []
124
+
125
+ export function register_artifact(name: string, artifact: QueryArtifact) {
126
+ const caches = window.__houdini__nav_caches__
127
+ if (!caches?.artifact_cache) {
128
+ _pendingArtifacts.push([name, artifact])
129
+ return
130
+ }
131
+ if (!caches.artifact_cache.has(name)) {
132
+ caches.artifact_cache.set(name, artifact)
133
+ }
134
+ }
135
+
136
+ function _flush_pending_artifacts() {
137
+ while (_pendingArtifacts.length > 0) {
138
+ const [name, artifact] = _pendingArtifacts.shift()!
139
+ register_artifact(name, artifact)
140
+ }
141
+ }
142
+
143
+ export function mount_static_app(App: React.ComponentType<any>, manifest: any) {
144
+ const root = createRoot(document.getElementById('app')!)
145
+
146
+ root.render(
147
+ React.createElement(App, {
148
+ initialURL: window.location.pathname,
149
+ cache: cacheRef,
150
+ session: null,
151
+ manifest,
152
+ ...router_cache(),
153
+ })
154
+ )
155
+ }
@@ -246,7 +246,7 @@ function usePageData({
246
246
  injectToStream?.(`
247
247
  <script>
248
248
  {
249
- window.__houdini__cache__?.hydrate(${cache.serialize()}, window.__houdini__hydration__layer)
249
+ window.__houdini__cache__?.hydrate(${cache.serialize()}, window.__houdini__hydration__layer__)
250
250
 
251
251
  const artifactName = "${artifact.name}"
252
252
  const value = ${JSON.stringify(
@@ -403,11 +403,6 @@ function usePageData({
403
403
  // save the artifact in the cache
404
404
  artifact_cache.set(artifact_id, artifact)
405
405
 
406
- // add a script to load the artifact
407
- injectToStream?.(`
408
- <script type="module" src="${assetPrefix}/artifacts/${artifact.name}.js" async=""></script>
409
- `)
410
-
411
406
  // now that we have the artifact, we can load the query too
412
407
  load_query({ id: artifact.name, artifact, variables })
413
408
  })
package/server/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { renderToStream } from 'react-streaming-compat/server';
1
+ export { renderToStream } from 'react-streaming/server';
package/server/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { renderToStream } from "react-streaming-compat/server";
1
+ import { renderToStream } from "react-streaming/server";
2
2
  export {
3
3
  renderToStream
4
4
  };
package/vite/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import type { VitePluginContext } from 'houdini/vite';
2
- import type { PluginOption } from 'vite';
1
+ import { VitePluginContext } from 'houdini/vite';
2
+ import { PluginOption } from 'vite';
3
3
  export default function (ctx: VitePluginContext): PluginOption;
package/vite/index.js CHANGED
@@ -1,11 +1,284 @@
1
+ import { fs, path } from "houdini";
2
+ import {
3
+ app_component_path,
4
+ adapter_config_path,
5
+ plugin_dir,
6
+ client_build_directory
7
+ } from "houdini/router/conventions";
8
+ import { load_manifest } from "houdini/router/manifest";
9
+ import { createRequire } from "node:module";
10
+ import { build } from "vite";
11
+ import { transform_file } from "./transform.js";
12
+ const _require = createRequire(import.meta.url);
13
+ let reactStreamingServerPath = "";
14
+ try {
15
+ const main = _require.resolve("react-streaming");
16
+ const pkgDir = main.replace(/\/dist\/.*$/, "");
17
+ reactStreamingServerPath = path.join(pkgDir, "dist/server/index.node-and-web.js");
18
+ } catch {
19
+ }
1
20
  function vite_default(ctx) {
21
+ let manifest;
22
+ let viteEnv;
23
+ let devServer = false;
24
+ let isSSRBuild = false;
25
+ let cfCache = null;
2
26
  return {
3
27
  name: "houdini-react",
4
- configureServer(server) {
5
- console.log("greetings from react vite plugin");
28
+ configResolved(config) {
29
+ isSSRBuild = !!config.build.ssr;
30
+ },
31
+ async config(userConfig, env) {
32
+ viteEnv = env;
33
+ if (userConfig.build?.ssr) {
34
+ return reactStreamingServerPath ? { resolve: { alias: { "react-streaming/server": reactStreamingServerPath } } } : {};
35
+ }
36
+ try {
37
+ manifest = await load_manifest({ config: ctx.config });
38
+ } catch (e) {
39
+ console.log(
40
+ "something went wrong. please try again. \n error: " + e.message
41
+ );
42
+ manifest = {
43
+ pages: {},
44
+ layouts: {},
45
+ page_queries: {},
46
+ layout_queries: {},
47
+ artifacts: [],
48
+ local_schema: false,
49
+ local_yoga: false,
50
+ component_fields: {}
51
+ };
52
+ }
53
+ let conf = {
54
+ build: { rollupOptions: {} }
55
+ };
56
+ if (env.command === "build") {
57
+ conf.base = "/assets";
58
+ }
59
+ const compiledAssetsDir = client_build_directory(ctx.config);
60
+ await fs.mkdirp(compiledAssetsDir);
61
+ conf.build = {
62
+ outDir: compiledAssetsDir,
63
+ rollupOptions: {
64
+ output: {
65
+ assetFileNames: "assets/[name].js",
66
+ entryFileNames: "[name].js"
67
+ },
68
+ input: {
69
+ "entries/app": app_component_path(ctx.config),
70
+ ...ctx.adapter ? { "entries/adapter": adapter_config_path(ctx.config) } : {}
71
+ }
72
+ }
73
+ };
74
+ if (env.command === "build" && ctx.adapter && ctx.adapter.includePaths) {
75
+ const extra = typeof ctx.adapter.includePaths === "function" ? ctx.adapter.includePaths({ config: ctx.config }) : ctx.adapter.includePaths;
76
+ Object.assign(conf.build.rollupOptions.input, extra);
77
+ }
78
+ for (const [id, page] of Object.entries(manifest.pages)) {
79
+ ;
80
+ conf.build.rollupOptions.input[`pages/${id}`] = `virtual:houdini/pages/${page.id}.jsx`;
81
+ }
82
+ return reactStreamingServerPath ? {
83
+ ...conf,
84
+ resolve: { alias: { "react-streaming/server": reactStreamingServerPath } }
85
+ } : conf;
86
+ },
87
+ resolveId(id) {
88
+ if (!id.includes("virtual:houdini")) {
89
+ return;
90
+ }
91
+ return id.substring(id.indexOf("virtual:houdini"));
92
+ },
93
+ async transform(code, filepath) {
94
+ filepath = path.posixify(filepath);
95
+ if (filepath.startsWith("/src/")) {
96
+ filepath = path.join(process.cwd(), filepath);
97
+ }
98
+ if (!ctx.config.includeFile(filepath)) {
99
+ return;
100
+ }
101
+ if (cfCache === null) {
102
+ try {
103
+ cfCache = ctx.db.prepare("SELECT type, field, fragment FROM component_fields").all();
104
+ } catch {
105
+ cfCache = [];
106
+ }
107
+ }
108
+ return transform_file(
109
+ {
110
+ config: ctx.config,
111
+ content: code,
112
+ filepath: path.posixify(filepath),
113
+ watch_file: this.addWatchFile.bind(this)
114
+ },
115
+ cfCache
116
+ );
117
+ },
118
+ async closeBundle() {
119
+ if (viteEnv.mode !== "production" || devServer || isSSRBuild) {
120
+ return;
121
+ }
122
+ if (!ctx.adapter || ctx.adapter?.disableServer) {
123
+ return;
124
+ }
125
+ const compiledAssetsDir = client_build_directory(ctx.config);
126
+ await build({
127
+ build: {
128
+ ssr: true,
129
+ outDir: path.join(compiledAssetsDir, "ssr"),
130
+ rollupOptions: {
131
+ output: {
132
+ assetFileNames: "assets/[name].js",
133
+ entryFileNames: "[name].js"
134
+ },
135
+ input: {
136
+ "entries/adapter": adapter_config_path(ctx.config)
137
+ }
138
+ }
139
+ }
140
+ });
141
+ },
142
+ async load(id) {
143
+ if (!id.startsWith("virtual:houdini")) {
144
+ return;
145
+ }
146
+ if (!manifest) {
147
+ return;
148
+ }
149
+ let [, which, arg] = id.split("/");
150
+ const parsedPath = arg ? path.parse(arg) : "";
151
+ const pageName = parsedPath ? parsedPath.name : "";
152
+ if (which === "pages") {
153
+ const page = manifest.pages[pageName];
154
+ if (!page) {
155
+ throw new Error("unknown page" + pageName);
156
+ }
157
+ const pendingQueries = page.queries.filter((query) => {
158
+ const pg = Object.values(manifest.page_queries).find((q) => q.name === query);
159
+ if (pg) {
160
+ return pg.loading;
161
+ }
162
+ const layout = Object.values(manifest.layout_queries).find(
163
+ (q) => q.name === query
164
+ );
165
+ return layout?.loading;
166
+ });
167
+ return `
168
+ import App from '$houdini/plugins/houdini-react/units/render/App'
169
+ import Component from '$houdini/plugins/houdini-react/units/entries/${pageName}.jsx'
170
+ import { hydrate_page } from '$houdini/plugins/houdini-react/runtime/hydration'
171
+ hydrate_page(App, Component, '${pageName}', ${JSON.stringify(pendingQueries)})
172
+ `;
173
+ }
174
+ if (which === "artifacts") {
175
+ return `
176
+ import artifact from '$houdini/artifacts/${pageName}'
177
+ import { register_artifact } from '$houdini/plugins/houdini-react/runtime/hydration'
178
+ register_artifact('${pageName}', artifact)
179
+ `;
180
+ }
181
+ if (which === "static-entry") {
182
+ return `
183
+ import App from '$houdini/plugins/houdini-react/units/render/App'
184
+ import manifest from '$houdini/plugins/houdini-react/runtime/manifest'
185
+ import { mount_static_app } from '$houdini/plugins/houdini-react/runtime/hydration'
186
+ mount_static_app(App, manifest)
187
+ `;
188
+ }
189
+ },
190
+ async configureServer(server) {
191
+ devServer = true;
192
+ server.middlewares.use(async (req, res, next) => {
193
+ if (!req.url) {
194
+ next();
195
+ return;
196
+ }
197
+ const { default: router_manifest } = await server.ssrLoadModule(
198
+ path.join(plugin_dir(ctx.config, "houdini-react"), "runtime", "manifest.ts")
199
+ );
200
+ const { createServerAdapter } = await server.ssrLoadModule(
201
+ adapter_config_path(ctx.config)
202
+ );
203
+ const requestHeaders = new Headers();
204
+ for (const header of Object.entries(req.headers ?? {})) {
205
+ requestHeaders.set(header[0], header[1]);
206
+ }
207
+ const port = server.config.server.port ?? 5173;
208
+ const request = new Request(
209
+ `http://localhost:${port}` + req.url,
210
+ req.method === "POST" ? {
211
+ method: req.method,
212
+ headers: requestHeaders,
213
+ body: await getBody(req)
214
+ } : void 0
215
+ );
216
+ let documentPremable = `<script type="module" src="/@vite/client" async=""><\/script>`;
217
+ try {
218
+ const transformed = await server.transformIndexHtml(
219
+ req.url,
220
+ "<!DOCTYPE html><html><head></head><body></body></html>"
221
+ );
222
+ const headMatch = transformed.match(/<head>([\s\S]*?)<\/head>/);
223
+ if (headMatch?.[1]?.trim()) {
224
+ documentPremable = headMatch[1].trim();
225
+ }
226
+ } catch {
227
+ }
228
+ try {
229
+ const result = await createServerAdapter({
230
+ production: false,
231
+ manifest: router_manifest,
232
+ assetPrefix: "/virtual:houdini",
233
+ pipe: res,
234
+ documentPremable
235
+ })(request);
236
+ if (result && result.status === 404) {
237
+ return next();
238
+ }
239
+ if (result && typeof result !== "boolean") {
240
+ if (res.closed) {
241
+ return;
242
+ }
243
+ for (const header of result.headers ?? []) {
244
+ res.setHeader(header[0], header[1]);
245
+ }
246
+ if (result.status >= 300 && result.status < 400) {
247
+ res.writeHead(result.status, {
248
+ Location: result.headers.get("Location") ?? "",
249
+ ...[...result.headers].reduce(
250
+ (headers, [key, value]) => ({
251
+ ...headers,
252
+ [key]: value
253
+ }),
254
+ {}
255
+ )
256
+ });
257
+ } else {
258
+ res.write(await result.text());
259
+ }
260
+ res.end();
261
+ }
262
+ } catch (e) {
263
+ console.error(e);
264
+ res.end();
265
+ }
266
+ });
6
267
  }
7
268
  };
8
269
  }
270
+ function getBody(request) {
271
+ return new Promise((resolve) => {
272
+ const bodyParts = [];
273
+ let body;
274
+ request.on("data", (chunk) => {
275
+ bodyParts.push(chunk);
276
+ }).on("end", () => {
277
+ body = Buffer.concat(bodyParts).toString();
278
+ resolve(body);
279
+ });
280
+ });
281
+ }
9
282
  export {
10
283
  vite_default as default
11
284
  };
@@ -0,0 +1,11 @@
1
+ import type { TransformPage } from 'houdini';
2
+ import type { SourceMapInput } from 'rollup';
3
+ export type ComponentFieldRow = {
4
+ type: string;
5
+ field: string;
6
+ fragment: string;
7
+ };
8
+ export declare function transform_file(page: TransformPage, cfRows: ComponentFieldRow[]): Promise<{
9
+ code: string;
10
+ map?: SourceMapInput;
11
+ }>;
@@ -0,0 +1,92 @@
1
+ import * as graphql from "graphql";
2
+ import {
3
+ ArtifactKind,
4
+ artifact_import,
5
+ ensure_imports,
6
+ find_graphql,
7
+ parseJS,
8
+ path,
9
+ printJS
10
+ } from "houdini";
11
+ import { componentField_unit_path, houdini_root } from "houdini/router/conventions";
12
+ import * as recast from "recast";
13
+ const AST = recast.types.builders;
14
+ async function transform_file(page, cfRows) {
15
+ const isJSX = page.filepath.endsWith(".tsx") || page.filepath.endsWith(".jsx");
16
+ if (!isJSX && !page.filepath.endsWith(".ts") && !page.filepath.endsWith(".js")) {
17
+ return { code: page.content, map: page.map };
18
+ }
19
+ const script = parseJS(page.content, isJSX ? { plugins: ["jsx"] } : {});
20
+ const cfMap = {};
21
+ for (const row of cfRows) {
22
+ if (row.type && row.field && row.fragment) {
23
+ cfMap[row.type] ??= {};
24
+ cfMap[row.type][row.field] = row.fragment;
25
+ }
26
+ }
27
+ await find_graphql(page.config, script, {
28
+ skipGraphqlType: true,
29
+ tag({ node, artifact, parsedDocument }) {
30
+ const { id: artifactRef } = artifact_import({ page, script, artifact });
31
+ const properties = [AST.objectProperty(AST.stringLiteral("artifact"), artifactRef)];
32
+ if (is_paginated(parsedDocument)) {
33
+ if (artifact.kind !== ArtifactKind.Query) {
34
+ const refetchName = artifact.name + "_Pagination_Query";
35
+ const { id: refetchRef } = artifact_import({
36
+ page,
37
+ script,
38
+ artifact: { name: refetchName }
39
+ });
40
+ properties.push(
41
+ AST.objectProperty(AST.stringLiteral("refetchArtifact"), refetchRef)
42
+ );
43
+ } else {
44
+ properties.push(
45
+ AST.objectProperty(AST.stringLiteral("refetchArtifact"), artifactRef)
46
+ );
47
+ }
48
+ }
49
+ if (Object.keys(cfMap).length > 0) {
50
+ const typeInfo = new graphql.TypeInfo(page.config.schema);
51
+ graphql.visit(
52
+ parsedDocument,
53
+ graphql.visitWithTypeInfo(typeInfo, {
54
+ Field(fieldNode) {
55
+ const parentType = typeInfo.getParentType();
56
+ const typeName = parentType?.name;
57
+ if (!typeName)
58
+ return;
59
+ const fragmentName = cfMap[typeName]?.[fieldNode.name.value];
60
+ if (!fragmentName)
61
+ return;
62
+ const entryPointPath = componentField_unit_path(
63
+ page.config,
64
+ fragmentName
65
+ );
66
+ ensure_imports({
67
+ script,
68
+ sourceModule: "$houdini/" + path.relative(houdini_root(page.config), entryPointPath)
69
+ });
70
+ }
71
+ })
72
+ );
73
+ }
74
+ node.replaceWith(AST.objectExpression(properties));
75
+ }
76
+ });
77
+ return printJS(script);
78
+ }
79
+ function is_paginated(doc) {
80
+ let paginated = false;
81
+ graphql.visit(doc, {
82
+ Directive(node) {
83
+ if (node.name.value === "paginate") {
84
+ paginated = true;
85
+ }
86
+ }
87
+ });
88
+ return paginated;
89
+ }
90
+ export {
91
+ transform_file
92
+ };