houdini-react 2.0.0-next.4 → 2.0.0-next.40

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.
Files changed (176) hide show
  1. package/bin/houdini-react +173 -0
  2. package/package.json +63 -39
  3. package/postInstall.js +360 -0
  4. package/runtime/Link.tsx +81 -0
  5. package/runtime/client.ts +5 -0
  6. package/runtime/clientPlugin.ts +17 -0
  7. package/runtime/componentFields.ts +79 -0
  8. package/runtime/hooks/index.ts +9 -0
  9. package/runtime/hooks/recycleNodesInto.ts +60 -0
  10. package/runtime/hooks/useDeepCompareEffect.ts +93 -0
  11. package/runtime/hooks/useDocumentHandle.ts +238 -0
  12. package/runtime/hooks/useDocumentStore.ts +112 -0
  13. package/runtime/hooks/useDocumentSubscription.ts +65 -0
  14. package/runtime/hooks/useFragment.ts +101 -0
  15. package/runtime/hooks/useFragmentHandle.ts +191 -0
  16. package/runtime/hooks/useIsMounted.ts +14 -0
  17. package/runtime/hooks/useMutation.ts +70 -0
  18. package/runtime/hooks/useQuery.ts +12 -0
  19. package/runtime/hooks/useQueryHandle.ts +194 -0
  20. package/runtime/hooks/useSubscription.ts +12 -0
  21. package/runtime/hooks/useSubscriptionHandle.ts +38 -0
  22. package/runtime/hydration.tsx +155 -0
  23. package/runtime/index.tsx +66 -0
  24. package/runtime/manifest.ts +6 -0
  25. package/runtime/package.json +1 -0
  26. package/runtime/resolve-href.ts +14 -0
  27. package/runtime/routing/Router.tsx +959 -0
  28. package/runtime/routing/cache.ts +57 -0
  29. package/runtime/routing/errors.tsx +145 -0
  30. package/runtime/routing/index.ts +17 -0
  31. package/runtime/tsconfig.json +39 -0
  32. package/server/index.d.ts +1 -0
  33. package/server/index.js +4 -0
  34. package/server/react-streaming.d.js +0 -0
  35. package/vite/index.d.ts +3 -0
  36. package/vite/index.js +384 -0
  37. package/vite/transform.d.ts +11 -0
  38. package/vite/transform.js +90 -0
  39. package/README.md +0 -36
  40. package/build/plugin/codegen/entries/documentWrappers.d.ts +0 -6
  41. package/build/plugin/codegen/entries/fallbacks.d.ts +0 -5
  42. package/build/plugin/codegen/entries/index.d.ts +0 -16
  43. package/build/plugin/codegen/entries/pages.d.ts +0 -2
  44. package/build/plugin/codegen/index.d.ts +0 -17
  45. package/build/plugin/codegen/manifest.d.ts +0 -5
  46. package/build/plugin/codegen/render.d.ts +0 -7
  47. package/build/plugin/codegen/router.d.ts +0 -7
  48. package/build/plugin/codegen/typeRoot.d.ts +0 -5
  49. package/build/plugin/config.d.ts +0 -4
  50. package/build/plugin/dedent.d.ts +0 -1
  51. package/build/plugin/extract.d.ts +0 -6
  52. package/build/plugin/index.d.ts +0 -5
  53. package/build/plugin/state.d.ts +0 -3
  54. package/build/plugin/transform.d.ts +0 -6
  55. package/build/plugin/vite.d.ts +0 -27
  56. package/build/plugin-cjs/index.js +0 -90119
  57. package/build/plugin-cjs/package.json +0 -1
  58. package/build/plugin-esm/index.js +0 -90115
  59. package/build/runtime/client.d.ts +0 -3
  60. package/build/runtime/clientPlugin.d.ts +0 -3
  61. package/build/runtime/componentFields.d.ts +0 -9
  62. package/build/runtime/hooks/index.d.ts +0 -8
  63. package/build/runtime/hooks/useDeepCompareEffect.d.ts +0 -35
  64. package/build/runtime/hooks/useDocumentHandle.d.ts +0 -36
  65. package/build/runtime/hooks/useDocumentStore.d.ts +0 -11
  66. package/build/runtime/hooks/useDocumentSubscription.d.ts +0 -11
  67. package/build/runtime/hooks/useFragment.d.ts +0 -16
  68. package/build/runtime/hooks/useFragmentHandle.d.ts +0 -8
  69. package/build/runtime/hooks/useIsMounted.d.ts +0 -3
  70. package/build/runtime/hooks/useMutation.d.ts +0 -14
  71. package/build/runtime/hooks/useQuery.d.ts +0 -5
  72. package/build/runtime/hooks/useQueryHandle.d.ts +0 -10
  73. package/build/runtime/hooks/useSubscription.d.ts +0 -4
  74. package/build/runtime/hooks/useSubscriptionHandle.d.ts +0 -25
  75. package/build/runtime/index.d.ts +0 -14
  76. package/build/runtime/manifest.d.ts +0 -3
  77. package/build/runtime/routing/Router.d.ts +0 -62
  78. package/build/runtime/routing/cache.d.ts +0 -7
  79. package/build/runtime/routing/hooks.d.ts +0 -40
  80. package/build/runtime/routing/index.d.ts +0 -3
  81. package/build/runtime-cjs/client.d.ts +0 -3
  82. package/build/runtime-cjs/client.js +0 -25
  83. package/build/runtime-cjs/clientPlugin.d.ts +0 -3
  84. package/build/runtime-cjs/clientPlugin.js +0 -37
  85. package/build/runtime-cjs/componentFields.d.ts +0 -9
  86. package/build/runtime-cjs/componentFields.js +0 -83
  87. package/build/runtime-cjs/hooks/index.d.ts +0 -8
  88. package/build/runtime-cjs/hooks/index.js +0 -45
  89. package/build/runtime-cjs/hooks/useDeepCompareEffect.d.ts +0 -35
  90. package/build/runtime-cjs/hooks/useDeepCompareEffect.js +0 -76
  91. package/build/runtime-cjs/hooks/useDocumentHandle.d.ts +0 -36
  92. package/build/runtime-cjs/hooks/useDocumentHandle.js +0 -177
  93. package/build/runtime-cjs/hooks/useDocumentStore.d.ts +0 -11
  94. package/build/runtime-cjs/hooks/useDocumentStore.js +0 -76
  95. package/build/runtime-cjs/hooks/useDocumentSubscription.d.ts +0 -11
  96. package/build/runtime-cjs/hooks/useDocumentSubscription.js +0 -76
  97. package/build/runtime-cjs/hooks/useFragment.d.ts +0 -16
  98. package/build/runtime-cjs/hooks/useFragment.js +0 -102
  99. package/build/runtime-cjs/hooks/useFragmentHandle.d.ts +0 -8
  100. package/build/runtime-cjs/hooks/useFragmentHandle.js +0 -47
  101. package/build/runtime-cjs/hooks/useIsMounted.d.ts +0 -3
  102. package/build/runtime-cjs/hooks/useIsMounted.js +0 -38
  103. package/build/runtime-cjs/hooks/useMutation.d.ts +0 -14
  104. package/build/runtime-cjs/hooks/useMutation.js +0 -67
  105. package/build/runtime-cjs/hooks/useQuery.d.ts +0 -5
  106. package/build/runtime-cjs/hooks/useQuery.js +0 -32
  107. package/build/runtime-cjs/hooks/useQueryHandle.d.ts +0 -10
  108. package/build/runtime-cjs/hooks/useQueryHandle.js +0 -131
  109. package/build/runtime-cjs/hooks/useSubscription.d.ts +0 -4
  110. package/build/runtime-cjs/hooks/useSubscription.js +0 -32
  111. package/build/runtime-cjs/hooks/useSubscriptionHandle.d.ts +0 -25
  112. package/build/runtime-cjs/hooks/useSubscriptionHandle.js +0 -42
  113. package/build/runtime-cjs/index.d.ts +0 -14
  114. package/build/runtime-cjs/index.js +0 -88
  115. package/build/runtime-cjs/manifest.d.ts +0 -3
  116. package/build/runtime-cjs/manifest.js +0 -25
  117. package/build/runtime-cjs/package.json +0 -1
  118. package/build/runtime-cjs/routing/Router.d.ts +0 -62
  119. package/build/runtime-cjs/routing/Router.js +0 -540
  120. package/build/runtime-cjs/routing/cache.d.ts +0 -7
  121. package/build/runtime-cjs/routing/cache.js +0 -61
  122. package/build/runtime-cjs/routing/hooks.d.ts +0 -40
  123. package/build/runtime-cjs/routing/hooks.js +0 -93
  124. package/build/runtime-cjs/routing/index.d.ts +0 -3
  125. package/build/runtime-cjs/routing/index.js +0 -33
  126. package/build/runtime-esm/client.d.ts +0 -3
  127. package/build/runtime-esm/client.js +0 -5
  128. package/build/runtime-esm/clientPlugin.d.ts +0 -3
  129. package/build/runtime-esm/clientPlugin.js +0 -17
  130. package/build/runtime-esm/componentFields.d.ts +0 -9
  131. package/build/runtime-esm/componentFields.js +0 -59
  132. package/build/runtime-esm/hooks/index.d.ts +0 -8
  133. package/build/runtime-esm/hooks/index.js +0 -15
  134. package/build/runtime-esm/hooks/useDeepCompareEffect.d.ts +0 -35
  135. package/build/runtime-esm/hooks/useDeepCompareEffect.js +0 -41
  136. package/build/runtime-esm/hooks/useDocumentHandle.d.ts +0 -36
  137. package/build/runtime-esm/hooks/useDocumentHandle.js +0 -143
  138. package/build/runtime-esm/hooks/useDocumentStore.d.ts +0 -11
  139. package/build/runtime-esm/hooks/useDocumentStore.js +0 -42
  140. package/build/runtime-esm/hooks/useDocumentSubscription.d.ts +0 -11
  141. package/build/runtime-esm/hooks/useDocumentSubscription.js +0 -42
  142. package/build/runtime-esm/hooks/useFragment.d.ts +0 -16
  143. package/build/runtime-esm/hooks/useFragment.js +0 -67
  144. package/build/runtime-esm/hooks/useFragmentHandle.d.ts +0 -8
  145. package/build/runtime-esm/hooks/useFragmentHandle.js +0 -23
  146. package/build/runtime-esm/hooks/useIsMounted.d.ts +0 -3
  147. package/build/runtime-esm/hooks/useIsMounted.js +0 -14
  148. package/build/runtime-esm/hooks/useMutation.d.ts +0 -14
  149. package/build/runtime-esm/hooks/useMutation.js +0 -42
  150. package/build/runtime-esm/hooks/useQuery.d.ts +0 -5
  151. package/build/runtime-esm/hooks/useQuery.js +0 -8
  152. package/build/runtime-esm/hooks/useQueryHandle.d.ts +0 -10
  153. package/build/runtime-esm/hooks/useQueryHandle.js +0 -97
  154. package/build/runtime-esm/hooks/useSubscription.d.ts +0 -4
  155. package/build/runtime-esm/hooks/useSubscription.js +0 -8
  156. package/build/runtime-esm/hooks/useSubscriptionHandle.d.ts +0 -25
  157. package/build/runtime-esm/hooks/useSubscriptionHandle.js +0 -18
  158. package/build/runtime-esm/index.d.ts +0 -14
  159. package/build/runtime-esm/index.js +0 -48
  160. package/build/runtime-esm/manifest.d.ts +0 -3
  161. package/build/runtime-esm/manifest.js +0 -5
  162. package/build/runtime-esm/routing/Router.d.ts +0 -62
  163. package/build/runtime-esm/routing/Router.js +0 -499
  164. package/build/runtime-esm/routing/cache.d.ts +0 -7
  165. package/build/runtime-esm/routing/cache.js +0 -36
  166. package/build/runtime-esm/routing/hooks.d.ts +0 -40
  167. package/build/runtime-esm/routing/hooks.js +0 -53
  168. package/build/runtime-esm/routing/index.d.ts +0 -3
  169. package/build/runtime-esm/routing/index.js +0 -6
  170. package/build/server/index.d.ts +0 -1
  171. package/build/server-cjs/index.js +0 -28
  172. package/build/server-cjs/package.json +0 -1
  173. package/build/server-esm/index.js +0 -4
  174. package/build/server-esm/package.json +0 -1
  175. /package/{build/plugin-esm → server}/package.json +0 -0
  176. /package/{build/runtime-esm → vite}/package.json +0 -0
@@ -0,0 +1,57 @@
1
+ // a suspense cache is an object that maintains a key-value store of
2
+ // objects. If a value is missing when get() is called, a promise
3
+ // is thrown that resolves when a value is passed to set()
4
+ import { LRUCache } from 'houdini/runtime'
5
+
6
+ export function suspense_cache<T>(initialData?: Record<string, T>): SuspenseCache<T> {
7
+ const cache = new SuspenseCache<T>()
8
+
9
+ for (const [key, value] of Object.entries(initialData ?? {})) {
10
+ cache.set(key, value)
11
+ }
12
+
13
+ return cache
14
+ }
15
+
16
+ export class SuspenseCache<_Data> extends LRUCache<_Data> {
17
+ // if get is called before set, we need to invoke a callback.
18
+ // that means we need a place to put our callbacks
19
+ #callbacks: Map<string, { resolve: () => void; reject: () => void }[]> = new Map()
20
+
21
+ get(key: string): _Data {
22
+ // if there is a value, use that
23
+ if (super.has(key)) {
24
+ return super.get(key)!
25
+ }
26
+
27
+ // we don't have a value, so we need to throw a promise
28
+ // that resolves when a value is passed to set()
29
+ throw new Promise<void>((resolve, reject) => {
30
+ this.#subscribe(key, resolve, reject)
31
+ })
32
+ }
33
+
34
+ override clear() {
35
+ super.clear()
36
+ this.#callbacks.clear()
37
+ }
38
+
39
+ set(key: string, value: _Data) {
40
+ // perform the set like normal
41
+ super.set(key, value)
42
+
43
+ // if there are subscribers, resolve them
44
+ if (this.#callbacks.has(key)) {
45
+ // resolve all of the callbacks
46
+ this.#callbacks.get(key)?.forEach(({ resolve }) => {
47
+ resolve()
48
+ })
49
+ // delete the key
50
+ this.#callbacks.delete(key)
51
+ }
52
+ }
53
+
54
+ #subscribe(key: string, resolve: () => void, reject: () => void) {
55
+ this.#callbacks.set(key, [...(this.#callbacks.get(key) || []), { resolve, reject }])
56
+ }
57
+ }
@@ -0,0 +1,145 @@
1
+ import type { GraphQLError } from 'houdini/runtime'
2
+ import React from 'react'
3
+
4
+ export class GraphQLErrors extends Error {
5
+ graphqlErrors: GraphQLError[]
6
+
7
+ constructor(errors: GraphQLError[]) {
8
+ super(errors.map((e) => e.message).join('\n'))
9
+ this.name = 'GraphQLErrors'
10
+ this.graphqlErrors = errors
11
+ }
12
+ }
13
+
14
+ let _currentSegment: string | undefined
15
+
16
+ export function setCurrentSegment(id: string | undefined): void {
17
+ _currentSegment = id
18
+ }
19
+
20
+ function getCurrentSegment(): string | undefined {
21
+ return _currentSegment
22
+ }
23
+
24
+ export class RoutingError extends Error {
25
+ status: number
26
+ segment: string | undefined
27
+
28
+ constructor(status: number) {
29
+ super(`Routing error: ${status}`)
30
+ this.name = 'RoutingError'
31
+ this.status = status
32
+ this.segment = getCurrentSegment()
33
+ }
34
+ }
35
+
36
+ export class RedirectError extends Error {
37
+ status: number
38
+ location: string
39
+
40
+ constructor(status: number, location: string) {
41
+ super(`Redirect: ${status} ${location}`)
42
+ this.name = 'RedirectError'
43
+ this.status = status
44
+ this.location = location
45
+ }
46
+ }
47
+
48
+ export function isRoutingError(error: unknown): error is RoutingError {
49
+ return error instanceof RoutingError
50
+ }
51
+
52
+ export function isApiError(error: unknown): error is GraphQLErrors {
53
+ return error instanceof GraphQLErrors
54
+ }
55
+
56
+ export function notFound(): never {
57
+ throw new RoutingError(404)
58
+ }
59
+
60
+ export function unauthorized(): never {
61
+ throw new RoutingError(401)
62
+ }
63
+
64
+ export function forbidden(): never {
65
+ throw new RoutingError(403)
66
+ }
67
+
68
+ export function httpError(status: number): never {
69
+ throw new RoutingError(status)
70
+ }
71
+
72
+ export function redirect(status: 300 | 301 | 302 | 303 | 307 | 308, location: string): never {
73
+ throw new RedirectError(status, location)
74
+ }
75
+
76
+ // Mutable ref passed from the server renderer so that a synchronous RoutingError
77
+ // or redirect() can propagate the correct HTTP status/location before streaming.
78
+ export const StatusContext = React.createContext<{ status: number; location?: string } | null>(null)
79
+
80
+ type HoudiniErrorBoundaryProps = {
81
+ errorView: React.ComponentType<{
82
+ errors: Array<Error | GraphQLError>
83
+ children: React.ReactNode
84
+ }>
85
+ children: React.ReactNode
86
+ }
87
+
88
+ type HoudiniErrorBoundaryState = {
89
+ hasError: boolean
90
+ errors: Array<Error | GraphQLError>
91
+ }
92
+
93
+ export class HoudiniErrorBoundary extends React.Component<
94
+ HoudiniErrorBoundaryProps,
95
+ HoudiniErrorBoundaryState
96
+ > {
97
+ static contextType = StatusContext
98
+ declare context: React.ContextType<typeof StatusContext>
99
+
100
+ constructor(
101
+ props: HoudiniErrorBoundaryProps,
102
+ context: React.ContextType<typeof StatusContext>
103
+ ) {
104
+ super(props, context)
105
+ // Second-pass SSR: statusRef is pre-set to an error status by on_render after the first
106
+ // render threw. Start in error state immediately so children never render (and never throw).
107
+ if (typeof window === 'undefined' && context && context.status >= 400) {
108
+ this.state = {
109
+ hasError: true,
110
+ errors: [new RoutingError(context.status)],
111
+ }
112
+ } else {
113
+ this.state = { hasError: false, errors: [] }
114
+ }
115
+ }
116
+
117
+ static getDerivedStateFromError(error: unknown): HoudiniErrorBoundaryState {
118
+ if (error instanceof GraphQLErrors) {
119
+ return { hasError: true, errors: error.graphqlErrors }
120
+ }
121
+ return {
122
+ hasError: true,
123
+ errors: [error instanceof Error ? error : new Error(String(error))],
124
+ }
125
+ }
126
+
127
+ componentDidCatch(error: Error): void {
128
+ if (this.context) {
129
+ if (error instanceof RoutingError) {
130
+ this.context.status = error.status
131
+ } else if (error instanceof RedirectError) {
132
+ this.context.status = error.status
133
+ this.context.location = error.location
134
+ }
135
+ }
136
+ }
137
+
138
+ render() {
139
+ if (this.state.hasError) {
140
+ const ErrorView = this.props.errorView
141
+ return <ErrorView errors={this.state.errors}>{this.props.children}</ErrorView>
142
+ }
143
+ return this.props.children
144
+ }
145
+ }
@@ -0,0 +1,17 @@
1
+ export * from './Router.js'
2
+ export { type SuspenseCache, suspense_cache } from './cache.js'
3
+ export {
4
+ HoudiniErrorBoundary,
5
+ GraphQLErrors,
6
+ RoutingError,
7
+ RedirectError,
8
+ notFound,
9
+ unauthorized,
10
+ forbidden,
11
+ httpError,
12
+ redirect,
13
+ isRoutingError,
14
+ isApiError,
15
+ StatusContext,
16
+ setCurrentSegment,
17
+ } from './errors.js'
@@ -0,0 +1,39 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "$houdini": ["."],
6
+ "$houdini/*": ["./*"],
7
+ "~": ["../src"],
8
+ "~/*": ["../src/*"]
9
+ },
10
+ "rootDirs": ["..", "./types"],
11
+ "target": "ESNext",
12
+ "useDefineForClassFields": true,
13
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
14
+ "allowJs": true,
15
+ "skipLibCheck": true,
16
+ "esModuleInterop": false,
17
+ "allowSyntheticDefaultImports": true,
18
+ "strict": true,
19
+ "forceConsistentCasingInFileNames": true,
20
+ "module": "ESNext",
21
+ "moduleResolution": "Bundler",
22
+ "allowImportingTsExtensions": true,
23
+ "resolveJsonModule": true,
24
+ "isolatedModules": true,
25
+ "noEmit": true,
26
+ "jsx": "react-jsx"
27
+ },
28
+ "include": [
29
+ "ambient.d.ts",
30
+ "./types/**/$types.d.ts",
31
+ "../vite.config.ts",
32
+ "../src/**/*.js",
33
+ "../src/**/*.ts",
34
+ "../src/**/*.jsx",
35
+ "../src/**/*.tsx",
36
+ "../src/+app.d.ts"
37
+ ],
38
+ "exclude": ["../node_modules/**", "./[!ambient.d.ts]**"]
39
+ }
@@ -0,0 +1 @@
1
+ export { renderToStream } from 'react-streaming/server';
@@ -0,0 +1,4 @@
1
+ import { renderToStream } from "react-streaming/server";
2
+ export {
3
+ renderToStream
4
+ };
File without changes
@@ -0,0 +1,3 @@
1
+ import { VitePluginContext } from 'houdini/vite';
2
+ import { PluginOption } from 'vite';
3
+ export default function (ctx: VitePluginContext): PluginOption;
package/vite/index.js ADDED
@@ -0,0 +1,384 @@
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 { existsSync, mkdirSync, writeFileSync } from "node:fs";
10
+ import { createRequire } from "node:module";
11
+ import { build } from "vite";
12
+ import { transform_file } from "./transform.js";
13
+ const REACT_TSCONFIG_STUB = `{
14
+ "compilerOptions": {
15
+ "baseUrl": ".",
16
+ "paths": {
17
+ "$houdini": ["."],
18
+ "$houdini/*": ["./*"],
19
+ "~": ["../src"],
20
+ "~/*": ["../src/*"]
21
+ },
22
+ "rootDirs": ["..", "./types"],
23
+ "target": "ESNext",
24
+ "useDefineForClassFields": true,
25
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
26
+ "allowJs": true,
27
+ "skipLibCheck": true,
28
+ "esModuleInterop": false,
29
+ "allowSyntheticDefaultImports": true,
30
+ "strict": true,
31
+ "forceConsistentCasingInFileNames": true,
32
+ "module": "ESNext",
33
+ "moduleResolution": "Bundler",
34
+ "allowImportingTsExtensions": true,
35
+ "resolveJsonModule": true,
36
+ "isolatedModules": true,
37
+ "noEmit": true,
38
+ "jsx": "react-jsx"
39
+ },
40
+ "include": [
41
+ "ambient.d.ts",
42
+ "./types/**/$types.d.ts",
43
+ "../vite.config.ts",
44
+ "../src/**/*.js",
45
+ "../src/**/*.ts",
46
+ "../src/**/*.jsx",
47
+ "../src/**/*.tsx",
48
+ "../src/+app.d.ts"
49
+ ],
50
+ "exclude": ["../node_modules/**", "./[!ambient.d.ts]**"]
51
+ }
52
+ `;
53
+ const _require = createRequire(import.meta.url);
54
+ let reactStreamingServerPath = "";
55
+ try {
56
+ const main = _require.resolve("react-streaming");
57
+ const pkgDir = main.replace(/\/dist\/.*$/, "");
58
+ reactStreamingServerPath = path.join(pkgDir, "dist/server/index.node-and-web.js");
59
+ } catch {
60
+ }
61
+ function index_default(ctx) {
62
+ let manifest;
63
+ let viteEnv;
64
+ let devServer = false;
65
+ let isSSRBuild = false;
66
+ let cfCache = null;
67
+ return {
68
+ name: "houdini-react",
69
+ configResolved(config) {
70
+ isSSRBuild = !!config.build.ssr;
71
+ },
72
+ async config(userConfig, env) {
73
+ viteEnv = env;
74
+ const runtimeDir = path.join(
75
+ ctx.config.root_dir,
76
+ ctx.config.config_file.runtimeDir ?? ".houdini"
77
+ );
78
+ try {
79
+ mkdirSync(runtimeDir, { recursive: true });
80
+ const tsconfigPath = path.join(runtimeDir, "tsconfig.json");
81
+ if (!existsSync(tsconfigPath)) {
82
+ writeFileSync(tsconfigPath, REACT_TSCONFIG_STUB);
83
+ }
84
+ } catch {
85
+ }
86
+ if (userConfig.build?.ssr) {
87
+ return reactStreamingServerPath ? { resolve: { alias: { "react-streaming/server": reactStreamingServerPath } } } : {};
88
+ }
89
+ try {
90
+ manifest = await load_manifest({ config: ctx.config });
91
+ } catch (e) {
92
+ console.log(
93
+ "something went wrong. please try again. \n error: " + e.message
94
+ );
95
+ manifest = {
96
+ pages: {},
97
+ layouts: {},
98
+ page_queries: {},
99
+ layout_queries: {},
100
+ artifacts: [],
101
+ local_schema: false,
102
+ local_yoga: false,
103
+ component_fields: {}
104
+ };
105
+ }
106
+ let conf = {
107
+ build: { rollupOptions: {} }
108
+ };
109
+ if (env.command === "build") {
110
+ conf.base = "/assets";
111
+ }
112
+ const compiledAssetsDir = client_build_directory(ctx.config);
113
+ await fs.mkdirp(compiledAssetsDir);
114
+ conf.build = {
115
+ outDir: compiledAssetsDir,
116
+ rollupOptions: {
117
+ output: {
118
+ assetFileNames: "assets/[name].js",
119
+ entryFileNames: "[name].js"
120
+ },
121
+ input: {
122
+ "entries/app": app_component_path(ctx.config),
123
+ ...ctx.adapter ? { "entries/adapter": adapter_config_path(ctx.config) } : {}
124
+ }
125
+ }
126
+ };
127
+ if (env.command === "build" && ctx.adapter && ctx.adapter.includePaths) {
128
+ const extra = typeof ctx.adapter.includePaths === "function" ? ctx.adapter.includePaths({ config: ctx.config }) : ctx.adapter.includePaths;
129
+ Object.assign(conf.build.rollupOptions.input ?? {}, extra);
130
+ }
131
+ for (const [id, page] of Object.entries(manifest.pages)) {
132
+ ;
133
+ conf.build.rollupOptions.input[`pages/${id}`] = `virtual:houdini/pages/${page.id}.jsx`;
134
+ }
135
+ return reactStreamingServerPath ? {
136
+ ...conf,
137
+ resolve: { alias: { "react-streaming/server": reactStreamingServerPath } }
138
+ } : conf;
139
+ },
140
+ resolveId(id) {
141
+ if (id.includes("virtual:houdini")) {
142
+ return id.substring(id.indexOf("virtual:houdini"));
143
+ }
144
+ return null;
145
+ },
146
+ hotUpdate() {
147
+ cfCache = null;
148
+ },
149
+ async transform(code, filepath) {
150
+ filepath = path.posixify(filepath);
151
+ if (filepath.startsWith("/src/")) {
152
+ filepath = path.join(process.cwd(), filepath);
153
+ }
154
+ if (!ctx.config.includeFile(filepath)) {
155
+ return;
156
+ }
157
+ if (cfCache === null) {
158
+ try {
159
+ cfCache = ctx.db.all(
160
+ "SELECT type, field, fragment FROM component_fields"
161
+ );
162
+ } catch {
163
+ cfCache = [];
164
+ }
165
+ }
166
+ return transform_file(
167
+ {
168
+ config: ctx.config,
169
+ content: code,
170
+ filepath: path.posixify(filepath),
171
+ watch_file: this.addWatchFile.bind(this)
172
+ },
173
+ cfCache
174
+ );
175
+ },
176
+ async closeBundle() {
177
+ if (viteEnv.mode !== "production" || devServer || isSSRBuild) {
178
+ return;
179
+ }
180
+ if (!ctx.adapter || ctx.adapter?.disableServer) {
181
+ return;
182
+ }
183
+ const compiledAssetsDir = client_build_directory(ctx.config);
184
+ await build({
185
+ build: {
186
+ ssr: true,
187
+ outDir: path.join(compiledAssetsDir, "ssr"),
188
+ rollupOptions: {
189
+ output: {
190
+ assetFileNames: "assets/[name].js",
191
+ entryFileNames: "[name].js"
192
+ },
193
+ input: {
194
+ "entries/adapter": adapter_config_path(ctx.config)
195
+ }
196
+ }
197
+ }
198
+ });
199
+ },
200
+ async load(id) {
201
+ if (!id.startsWith("virtual:houdini")) {
202
+ return;
203
+ }
204
+ if (!manifest) {
205
+ return;
206
+ }
207
+ let [, which, arg] = id.split("/");
208
+ const parsedPath = arg ? path.parse(arg) : "";
209
+ const pageName = parsedPath ? parsedPath.name : "";
210
+ if (which === "pages") {
211
+ let page = manifest.pages[pageName];
212
+ if (!page) {
213
+ try {
214
+ manifest = await load_manifest({ config: ctx.config });
215
+ page = manifest.pages[pageName];
216
+ } catch {
217
+ }
218
+ }
219
+ if (!page) {
220
+ throw new Error("unknown page" + pageName);
221
+ }
222
+ const pendingQueries = page.queries.filter((query) => {
223
+ const pg = Object.values(manifest.page_queries).find((q) => q.name === query);
224
+ if (pg) {
225
+ return pg.loading;
226
+ }
227
+ const layout = Object.values(manifest.layout_queries).find(
228
+ (q) => q.name === query
229
+ );
230
+ return layout?.loading;
231
+ });
232
+ return `
233
+ import App from '$houdini/plugins/houdini-react/units/render/App'
234
+ import Component from '$houdini/plugins/houdini-react/units/entries/${pageName}.jsx'
235
+ import { hydrate_page } from '$houdini/plugins/houdini-react/runtime/hydration'
236
+ hydrate_page(App, Component, '${pageName}', ${JSON.stringify(pendingQueries)})
237
+ `;
238
+ }
239
+ if (which === "artifacts") {
240
+ return `
241
+ import artifact from '$houdini/artifacts/${pageName}'
242
+ import { register_artifact } from '$houdini/plugins/houdini-react/runtime/hydration'
243
+ register_artifact('${pageName}', artifact)
244
+ `;
245
+ }
246
+ if (which === "static-entry") {
247
+ return `
248
+ import App from '$houdini/plugins/houdini-react/units/render/App'
249
+ import manifest from '$houdini/plugins/houdini-react/runtime/manifest'
250
+ import { mount_static_app } from '$houdini/plugins/houdini-react/runtime/hydration'
251
+ mount_static_app(App, manifest)
252
+ `;
253
+ }
254
+ },
255
+ async configureServer(server) {
256
+ devServer = true;
257
+ const onUnhandledRejection = (err) => {
258
+ console.error("\n[houdini] dev server error (server still running):\n", err, "\n");
259
+ };
260
+ process.on("unhandledRejection", onUnhandledRejection);
261
+ server.httpServer?.once(
262
+ "close",
263
+ () => process.off("unhandledRejection", onUnhandledRejection)
264
+ );
265
+ server.httpServer?.once("listening", () => {
266
+ const addr = server.httpServer?.address();
267
+ if (addr && typeof addr === "object") {
268
+ process.env.HOUDINI_PORT = String(addr.port);
269
+ }
270
+ const root = ctx.config.root_dir;
271
+ const entry = ["+index.tsx", "+index.jsx"].map((f) => path.join(root, "src", f)).find((f) => existsSync(f));
272
+ if (entry) {
273
+ server.ssrLoadModule(entry).catch(() => {
274
+ });
275
+ }
276
+ });
277
+ server.middlewares.use(async (req, res, next) => {
278
+ if (!req.url) {
279
+ next();
280
+ return;
281
+ }
282
+ const url = req.url.split("?")[0];
283
+ if (url.startsWith("/@") || url.startsWith("/virtual:") || url.startsWith("/node_modules/") || /\.[a-z]+$/i.test(url)) {
284
+ next();
285
+ return;
286
+ }
287
+ const { default: router_manifest } = await server.ssrLoadModule(
288
+ path.join(plugin_dir(ctx.config, "houdini-react"), "runtime", "manifest.ts")
289
+ );
290
+ const { createServerAdapter } = await server.ssrLoadModule(
291
+ adapter_config_path(ctx.config)
292
+ );
293
+ const requestHeaders = new Headers();
294
+ for (const header of Object.entries(req.headers ?? {})) {
295
+ requestHeaders.set(header[0], header[1]);
296
+ }
297
+ const port = server.config.server.port ?? 5173;
298
+ const request = new Request(
299
+ `http://localhost:${port}` + req.url,
300
+ req.method === "POST" ? {
301
+ method: req.method,
302
+ headers: requestHeaders,
303
+ body: await getBody(req)
304
+ } : void 0
305
+ );
306
+ let documentPremable = `<script type="module" src="/@vite/client" async=""></script>`;
307
+ try {
308
+ const transformed = await server.transformIndexHtml(
309
+ req.url,
310
+ "<!DOCTYPE html><html><head></head><body></body></html>"
311
+ );
312
+ const headMatch = transformed.match(/<head>([\s\S]*?)<\/head>/);
313
+ if (headMatch?.[1]?.trim()) {
314
+ documentPremable = headMatch[1].trim();
315
+ }
316
+ } catch {
317
+ }
318
+ const cssLinkSet = /* @__PURE__ */ new Set();
319
+ for (const [url2] of server.moduleGraph.urlToModuleMap) {
320
+ const cleanUrl = url2.split("?")[0];
321
+ if (!cleanUrl.includes("node_modules") && cleanUrl.endsWith(".css") && !cleanUrl.endsWith(".module.css")) {
322
+ cssLinkSet.add(cleanUrl);
323
+ }
324
+ }
325
+ const cssLinks = [...cssLinkSet];
326
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
327
+ try {
328
+ const result = await createServerAdapter({
329
+ production: false,
330
+ manifest: router_manifest,
331
+ assetPrefix: "/virtual:houdini",
332
+ pipe: res,
333
+ documentPremable,
334
+ cssLinks
335
+ })(request);
336
+ if (result && result.status === 404) {
337
+ return next();
338
+ }
339
+ if (result && typeof result !== "boolean") {
340
+ if (res.closed) {
341
+ return;
342
+ }
343
+ for (const header of result.headers ?? []) {
344
+ res.setHeader(header[0], header[1]);
345
+ }
346
+ if (result.status >= 300 && result.status < 400) {
347
+ res.writeHead(result.status, {
348
+ Location: result.headers.get("Location") ?? "",
349
+ ...[...result.headers].reduce(
350
+ (headers, [key, value]) => ({
351
+ ...headers,
352
+ [key]: value
353
+ }),
354
+ {}
355
+ )
356
+ });
357
+ } else {
358
+ res.write(await result.text());
359
+ }
360
+ res.end();
361
+ }
362
+ } catch (e) {
363
+ console.error(e);
364
+ res.end();
365
+ }
366
+ });
367
+ }
368
+ };
369
+ }
370
+ function getBody(request) {
371
+ return new Promise((resolve) => {
372
+ const bodyParts = [];
373
+ let body;
374
+ request.on("data", (chunk) => {
375
+ bodyParts.push(chunk);
376
+ }).on("end", () => {
377
+ body = Buffer.concat(bodyParts).toString();
378
+ resolve(body);
379
+ });
380
+ });
381
+ }
382
+ export {
383
+ index_default as default
384
+ };
@@ -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
+ }>;