@quilted/create 0.1.77 → 0.1.79
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/CHANGELOG.md +12 -0
- package/build/cjs/app.cjs +20 -18
- package/build/cjs/module.cjs +15 -13
- package/build/cjs/package.cjs +10 -9
- package/build/cjs/service.cjs +8 -12
- package/build/esm/app.mjs +20 -18
- package/build/esm/module.mjs +15 -13
- package/build/esm/package.mjs +10 -9
- package/build/esm/service.mjs +8 -12
- package/build/esnext/app.esnext +20 -18
- package/build/esnext/module.esnext +15 -13
- package/build/esnext/package.esnext +10 -9
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/app.d.ts.map +1 -1
- package/build/typescript/module.d.ts.map +1 -1
- package/build/typescript/package.d.ts.map +1 -1
- package/build/typescript/service.d.ts.map +1 -1
- package/build/typescript/shared.d.ts +1 -1
- package/build/typescript/shared.d.ts.map +1 -1
- package/package.json +1 -1
- package/source/app.ts +35 -31
- package/source/module.ts +26 -22
- package/source/package.ts +20 -23
- package/source/service.ts +18 -23
- package/source/shared.ts +0 -2
- package/templates/app-basic/App.tsx +37 -13
- package/templates/app-basic/browser.tsx +2 -2
- package/templates/app-basic/features/start/Start/Start.tsx +5 -0
- package/templates/app-basic/features/start.ts +5 -0
- package/templates/app-basic/foundation/frame/Frame.module.css +14 -0
- package/templates/app-basic/foundation/frame/Frame.tsx +7 -0
- package/templates/app-basic/foundation/frame.ts +1 -0
- package/templates/app-basic/foundation/{Head → html}/Head.test.tsx +4 -4
- package/templates/app-basic/foundation/html.ts +1 -0
- package/templates/{app-trpc/foundation/Http/Http.test.tsx → app-basic/foundation/http/Headers.test.tsx} +8 -8
- package/templates/app-basic/foundation/{Http/Http.tsx → http/Headers.tsx} +3 -3
- package/templates/app-basic/foundation/http.ts +1 -0
- package/templates/app-basic/server.tsx +18 -15
- package/templates/app-basic/shared/context.ts +1 -6
- package/templates/app-basic/tests/render/render.tsx +12 -12
- package/templates/app-basic/tests/render/types.ts +3 -5
- package/templates/app-basic/tests/render.ts +2 -2
- package/templates/app-empty/App.tsx +1 -1
- package/templates/app-empty/browser.tsx +1 -1
- package/templates/app-empty/server.tsx +18 -14
- package/templates/app-graphql/App.tsx +36 -26
- package/templates/app-graphql/browser.tsx +1 -1
- package/templates/app-graphql/features/{Start → start/Start}/Start.test.tsx +3 -7
- package/templates/app-graphql/features/start/Start/Start.tsx +14 -0
- package/templates/app-graphql/features/start.ts +5 -0
- package/templates/app-graphql/foundation/frame/Frame.module.css +14 -0
- package/templates/app-graphql/foundation/frame/Frame.tsx +7 -0
- package/templates/app-graphql/foundation/frame.ts +1 -0
- package/templates/{app-trpc/foundation/Head → app-graphql/foundation/html}/Head.test.tsx +4 -4
- package/templates/app-graphql/foundation/html.ts +1 -0
- package/templates/{app-basic/foundation/Http/Http.test.tsx → app-graphql/foundation/http/Headers.test.tsx} +8 -8
- package/templates/app-graphql/foundation/{Http/Http.tsx → http/Headers.tsx} +3 -3
- package/templates/app-graphql/foundation/http.ts +1 -0
- package/templates/app-graphql/server/graphql.ts +1 -2
- package/templates/app-graphql/server.tsx +36 -33
- package/templates/app-graphql/shared/context.ts +1 -6
- package/templates/app-graphql/tests/graphql.ts +3 -4
- package/templates/app-graphql/tests/render/render.tsx +16 -15
- package/templates/app-graphql/tests/render/types.ts +3 -5
- package/templates/app-graphql/tests/render.ts +3 -3
- package/templates/app-trpc/App.tsx +39 -33
- package/templates/app-trpc/browser.tsx +1 -1
- package/templates/app-trpc/features/{Start → start/Start}/Start.test.tsx +2 -2
- package/templates/app-trpc/features/start/Start/Start.tsx +9 -0
- package/templates/app-trpc/features/start.ts +5 -0
- package/templates/app-trpc/foundation/frame/Frame.module.css +14 -0
- package/templates/app-trpc/foundation/frame/Frame.tsx +7 -0
- package/templates/app-trpc/foundation/frame.ts +1 -0
- package/templates/{app-graphql/foundation/Head → app-trpc/foundation/html}/Head.test.tsx +4 -4
- package/templates/app-trpc/foundation/html.ts +1 -0
- package/templates/{app-graphql/foundation/Http/Http.test.tsx → app-trpc/foundation/http/Headers.test.tsx} +8 -8
- package/templates/app-trpc/foundation/{Http/Http.tsx → http/Headers.tsx} +3 -3
- package/templates/app-trpc/foundation/http.ts +1 -0
- package/templates/app-trpc/server.tsx +1 -1
- package/templates/app-trpc/shared/context.ts +1 -6
- package/templates/app-trpc/tests/render/render.tsx +17 -16
- package/templates/service-basic/service.ts +2 -2
- package/templates/app-basic/features/Start/Start.tsx +0 -12
- package/templates/app-basic/features/Start.tsx +0 -3
- package/templates/app-basic/foundation/Head.tsx +0 -1
- package/templates/app-basic/foundation/Http.tsx +0 -1
- package/templates/app-basic/foundation/Metrics/Metrics.tsx +0 -23
- package/templates/app-basic/foundation/Metrics.tsx +0 -1
- package/templates/app-graphql/features/Start/Start.tsx +0 -20
- package/templates/app-graphql/features/Start.tsx +0 -3
- package/templates/app-graphql/foundation/Head.tsx +0 -1
- package/templates/app-graphql/foundation/Http.tsx +0 -1
- package/templates/app-graphql/foundation/Metrics/Metrics.tsx +0 -23
- package/templates/app-graphql/foundation/Metrics.tsx +0 -1
- package/templates/app-single-file/App.tsx +0 -199
- package/templates/app-single-file/package.json +0 -35
- package/templates/app-single-file/quilt.project.ts +0 -5
- package/templates/app-single-file/tsconfig.json +0 -9
- package/templates/app-trpc/features/Start/Start.tsx +0 -16
- package/templates/app-trpc/features/Start.tsx +0 -3
- package/templates/app-trpc/foundation/Head.tsx +0 -1
- package/templates/app-trpc/foundation/Http.tsx +0 -1
- package/templates/app-trpc/foundation/Metrics/Metrics.tsx +0 -23
- package/templates/app-trpc/foundation/Metrics.tsx +0 -1
- /package/templates/app-basic/features/{Start → start/Start}/Start.module.css +0 -0
- /package/templates/app-basic/features/{Start → start/Start}/Start.test.tsx +0 -0
- /package/templates/app-basic/foundation/{Head → html}/Head.tsx +0 -0
- /package/templates/app-graphql/features/{Start → start/Start}/Start.module.css +0 -0
- /package/templates/app-graphql/features/{Start → start/Start}/StartQuery.graphql +0 -0
- /package/templates/app-graphql/foundation/{Head → html}/Head.tsx +0 -0
- /package/templates/app-trpc/features/{Start → start/Start}/Start.module.css +0 -0
- /package/templates/app-trpc/foundation/{Head → html}/Head.tsx +0 -0
|
@@ -1,20 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {HTML} from '@quilted/quilt/html';
|
|
2
|
+
import {Routing, useRoutes} from '@quilted/quilt/navigate';
|
|
3
|
+
import {Localization, useLocaleFromEnvironment} from '@quilted/quilt/localize';
|
|
4
|
+
import {type PropsWithChildren} from '@quilted/quilt/react/tools';
|
|
2
5
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
+
import {Head} from './foundation/html.ts';
|
|
7
|
+
import {Headers} from './foundation/http.ts';
|
|
8
|
+
import {Frame} from './foundation/frame.ts';
|
|
6
9
|
|
|
7
|
-
import {Start} from './features/
|
|
10
|
+
import {Start} from './features/start.ts';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
AppContextReact,
|
|
14
|
+
type AppContext as AppContextType,
|
|
15
|
+
} from './shared/context.ts';
|
|
16
|
+
|
|
17
|
+
export interface AppProps extends AppContextType {}
|
|
8
18
|
|
|
9
19
|
// The root component for your application. You will typically render any
|
|
10
20
|
// app-wide context in this component.
|
|
11
|
-
export
|
|
21
|
+
export function App(props: AppProps) {
|
|
22
|
+
const locale = useLocaleFromEnvironment() ?? 'en';
|
|
23
|
+
|
|
12
24
|
return (
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
<HTML>
|
|
26
|
+
<Localization locale={locale}>
|
|
27
|
+
<Routing>
|
|
28
|
+
<AppContext {...props}>
|
|
29
|
+
<Headers />
|
|
30
|
+
<Head />
|
|
31
|
+
<Frame>
|
|
32
|
+
<Routes />
|
|
33
|
+
</Frame>
|
|
34
|
+
</AppContext>
|
|
35
|
+
</Routing>
|
|
36
|
+
</Localization>
|
|
37
|
+
</HTML>
|
|
18
38
|
);
|
|
19
39
|
}
|
|
20
40
|
|
|
@@ -27,6 +47,10 @@ function Routes() {
|
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
// This component renders any app-wide context.
|
|
30
|
-
function AppContext({children}: PropsWithChildren) {
|
|
31
|
-
return
|
|
50
|
+
function AppContext({children, ...context}: PropsWithChildren<AppProps>) {
|
|
51
|
+
return (
|
|
52
|
+
<AppContextReact.Provider value={context}>
|
|
53
|
+
{children}
|
|
54
|
+
</AppContextReact.Provider>
|
|
55
|
+
);
|
|
32
56
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {Frame} from './frame/Frame.tsx';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {Viewport, SearchRobots} from '@quilted/quilt/html';
|
|
2
1
|
import {describe, it, expect} from '@quilted/quilt/testing';
|
|
2
|
+
import {Viewport, SearchRobots} from '@quilted/quilt/html';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {renderApp} from '~/tests/render.tsx';
|
|
5
5
|
|
|
6
6
|
import {Head} from './Head.tsx';
|
|
7
7
|
|
|
8
8
|
describe('<Head />', () => {
|
|
9
9
|
it('includes a responsive viewport tag', async () => {
|
|
10
|
-
const head = await
|
|
10
|
+
const head = await renderApp(<Head />);
|
|
11
11
|
|
|
12
12
|
expect(head).toContainReactComponent(Viewport, {
|
|
13
13
|
cover: true,
|
|
@@ -15,7 +15,7 @@ describe('<Head />', () => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('prevents search robots from indexing the application', async () => {
|
|
18
|
-
const head = await
|
|
18
|
+
const head = await renderApp(<Head />);
|
|
19
19
|
|
|
20
20
|
expect(head).toContainReactComponent(SearchRobots, {
|
|
21
21
|
index: false,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {Head} from './html/Head.tsx';
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {CacheControl, ContentSecurityPolicy} from '@quilted/quilt/http';
|
|
2
1
|
import {describe, it, expect} from '@quilted/quilt/testing';
|
|
2
|
+
import {CacheControl, ContentSecurityPolicy} from '@quilted/quilt/http';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {renderApp} from '~/tests/render.tsx';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {Headers} from './Headers.tsx';
|
|
7
7
|
|
|
8
|
-
describe('<
|
|
8
|
+
describe('<Headers />', () => {
|
|
9
9
|
it('does not cache the response', async () => {
|
|
10
|
-
const
|
|
10
|
+
const headers = await renderApp(<Headers />);
|
|
11
11
|
|
|
12
|
-
expect(
|
|
12
|
+
expect(headers).toContainReactComponent(CacheControl, {
|
|
13
13
|
cache: false,
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('adds a content security policy with a strict default policy', async () => {
|
|
18
|
-
const
|
|
18
|
+
const headers = await renderApp(<Headers />);
|
|
19
19
|
|
|
20
|
-
expect(
|
|
20
|
+
expect(headers).toContainReactComponent(ContentSecurityPolicy, {
|
|
21
21
|
defaultSources: ["'self'"],
|
|
22
22
|
});
|
|
23
23
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Env from '@quilted/quilt/env';
|
|
2
|
-
import {
|
|
2
|
+
import {useInitialUrl} from '@quilted/quilt/navigate';
|
|
3
3
|
import {
|
|
4
4
|
CacheControl,
|
|
5
5
|
ResponseHeader,
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
// wherever in your application you can read that state.
|
|
15
15
|
//
|
|
16
16
|
// @see https://github.com/lemonmade/quilt/blob/main/documentation/features/http.md
|
|
17
|
-
export function
|
|
18
|
-
const isHttps =
|
|
17
|
+
export function Headers() {
|
|
18
|
+
const isHttps = useInitialUrl().protocol === 'https:';
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {Headers} from './http/Headers.tsx';
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import '@quilted/quilt/
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import '@quilted/quilt/globals';
|
|
2
|
+
import {RequestRouter} from '@quilted/quilt/request-router';
|
|
3
|
+
import {BrowserAssets} from '@quilted/quilt/magic/assets';
|
|
4
4
|
|
|
5
|
-
const router =
|
|
5
|
+
const router = new RequestRouter();
|
|
6
|
+
const assets = new BrowserAssets();
|
|
6
7
|
|
|
7
8
|
// For all GET requests, render our React application.
|
|
8
|
-
router.get(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)
|
|
18
|
-
|
|
9
|
+
router.get(async (request) => {
|
|
10
|
+
const [{App}, {renderToResponse}] = await Promise.all([
|
|
11
|
+
import('./App.tsx'),
|
|
12
|
+
import('@quilted/quilt/server'),
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const response = await renderToResponse(<App />, {
|
|
16
|
+
request,
|
|
17
|
+
assets,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return response;
|
|
21
|
+
});
|
|
19
22
|
|
|
20
23
|
export default router;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createOptionalContext,
|
|
3
3
|
createUseContextHook,
|
|
4
|
-
|
|
5
|
-
} from '@quilted/quilt';
|
|
4
|
+
} from '@quilted/quilt/react/tools';
|
|
6
5
|
|
|
7
6
|
export interface AppContext {}
|
|
8
7
|
|
|
9
8
|
export const AppContextReact = createOptionalContext<AppContext>();
|
|
10
9
|
export const useAppContext = createUseContextHook(AppContextReact);
|
|
11
|
-
|
|
12
|
-
export function createUseAppContextHook<T>(hook: (context: AppContext) => T) {
|
|
13
|
-
return createUseOptionalValueHook<T>(() => hook(useAppContext()));
|
|
14
|
-
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
createTestRouter,
|
|
5
|
-
} from '@quilted/quilt/testing';
|
|
1
|
+
import {createRender} from '@quilted/quilt/react/testing';
|
|
2
|
+
import {TestRouting, TestRouter} from '@quilted/quilt/navigate/testing';
|
|
3
|
+
import {Localization} from '@quilted/quilt/localize';
|
|
6
4
|
|
|
7
5
|
import {AppContextReact} from '~/shared/context.ts';
|
|
8
6
|
|
|
@@ -21,19 +19,21 @@ export const renderApp = createRender<
|
|
|
21
19
|
// Create context that can be used by the `render` function, and referenced by test
|
|
22
20
|
// authors on the `root.context` property. Context is used to share data between your
|
|
23
21
|
// React tree and your test code, and is ideal for mocking out global context providers.
|
|
24
|
-
context({router =
|
|
22
|
+
context({router = new TestRouter()}) {
|
|
25
23
|
return {router};
|
|
26
24
|
},
|
|
27
25
|
// Render all of our app-wide context providers around each component under test.
|
|
28
|
-
render(element, context, {locale}) {
|
|
26
|
+
render(element, context, {locale = 'en'}) {
|
|
29
27
|
const {router} = context;
|
|
30
28
|
|
|
31
29
|
return (
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
<Localization locale={locale}>
|
|
31
|
+
<TestRouting router={router}>
|
|
32
|
+
<AppContextReact.Provider value={context}>
|
|
33
|
+
{element}
|
|
34
|
+
</AppContextReact.Provider>
|
|
35
|
+
</TestRouting>
|
|
36
|
+
</Localization>
|
|
37
37
|
);
|
|
38
38
|
},
|
|
39
39
|
async afterRender() {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {TestRouter} from '@quilted/quilt/navigate/testing';
|
|
2
2
|
|
|
3
3
|
import type {AppContext} from '~/shared/context.ts';
|
|
4
4
|
|
|
5
|
-
type Router = ReturnType<typeof createTestRouter>;
|
|
6
|
-
|
|
7
5
|
export interface RenderOptions {
|
|
8
6
|
/**
|
|
9
7
|
* A custom router to use for this component test. You can use a
|
|
@@ -11,7 +9,7 @@ export interface RenderOptions {
|
|
|
11
9
|
* its navigation method to check that components navigate as
|
|
12
10
|
* you expect.
|
|
13
11
|
*/
|
|
14
|
-
readonly router?:
|
|
12
|
+
readonly router?: TestRouter;
|
|
15
13
|
|
|
16
14
|
/**
|
|
17
15
|
* A custom locale to use for this component test.
|
|
@@ -23,7 +21,7 @@ export interface RenderContext extends AppContext {
|
|
|
23
21
|
/**
|
|
24
22
|
* The router used for this component test.
|
|
25
23
|
*/
|
|
26
|
-
readonly router:
|
|
24
|
+
readonly router: TestRouter;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
export interface RenderActions extends Record<string, never> {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import '@quilted/quilt/
|
|
1
|
+
import '@quilted/quilt/react/testing';
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export {TestRouter} from '@quilted/quilt/navigate/testing';
|
|
4
4
|
|
|
5
5
|
export * from './render/types.ts';
|
|
6
6
|
export {renderApp} from './render/render.tsx';
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import '@quilted/quilt/globals';
|
|
2
|
+
import {RequestRouter} from '@quilted/quilt/request-router';
|
|
3
|
+
import {BrowserAssets} from '@quilted/quilt/magic/assets';
|
|
3
4
|
|
|
4
|
-
const router =
|
|
5
|
+
const router = new RequestRouter();
|
|
6
|
+
const assets = new BrowserAssets();
|
|
5
7
|
|
|
6
8
|
// For all GET requests, render our React application.
|
|
7
|
-
router.get(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
17
|
-
|
|
9
|
+
router.get(async (request) => {
|
|
10
|
+
const [{App}, {renderToResponse}] = await Promise.all([
|
|
11
|
+
import('./App.tsx'),
|
|
12
|
+
import('@quilted/quilt/server'),
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const response = await renderToResponse(<App />, {
|
|
16
|
+
request,
|
|
17
|
+
assets,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return response;
|
|
21
|
+
});
|
|
18
22
|
|
|
19
23
|
export default router;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import {useMemo} from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type PropsWithChildren,
|
|
8
|
-
} from '@quilted/quilt';
|
|
3
|
+
import {HTML} from '@quilted/quilt/html';
|
|
4
|
+
import {Routing, useRoutes} from '@quilted/quilt/navigate';
|
|
5
|
+
import {Localization, useLocaleFromEnvironment} from '@quilted/quilt/localize';
|
|
6
|
+
import {type PropsWithChildren} from '@quilted/quilt/react/tools';
|
|
9
7
|
import {
|
|
10
8
|
GraphQLContext,
|
|
11
9
|
createGraphQLHttpFetch,
|
|
@@ -15,27 +13,40 @@ import {
|
|
|
15
13
|
import {ReactQueryContext} from '@quilted/react-query';
|
|
16
14
|
import {QueryClient} from '@tanstack/react-query';
|
|
17
15
|
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
16
|
+
import {Head} from './foundation/html.ts';
|
|
17
|
+
import {Headers} from './foundation/http.ts';
|
|
18
|
+
import {Frame} from './foundation/frame.ts';
|
|
19
|
+
|
|
20
|
+
import {Start} from './features/start.ts';
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
AppContextReact,
|
|
24
|
+
type AppContext as AppContextType,
|
|
25
|
+
} from './shared/context.ts';
|
|
23
26
|
|
|
24
|
-
export interface
|
|
27
|
+
export interface AppProps extends AppContextType {
|
|
25
28
|
fetchGraphQL?: GraphQLFetch;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
// The root component for your application. You will typically render any
|
|
29
32
|
// app-wide context in this component.
|
|
30
|
-
export
|
|
33
|
+
export function App(props: AppProps) {
|
|
34
|
+
const locale = useLocaleFromEnvironment() ?? 'en';
|
|
35
|
+
|
|
31
36
|
return (
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
<HTML>
|
|
38
|
+
<Localization locale={locale}>
|
|
39
|
+
<Routing>
|
|
40
|
+
<AppContext {...props}>
|
|
41
|
+
<Headers />
|
|
42
|
+
<Head />
|
|
43
|
+
<Frame>
|
|
44
|
+
<Routes />
|
|
45
|
+
</Frame>
|
|
46
|
+
</AppContext>
|
|
47
|
+
</Routing>
|
|
48
|
+
</Localization>
|
|
49
|
+
</HTML>
|
|
39
50
|
);
|
|
40
51
|
}
|
|
41
52
|
|
|
@@ -43,11 +54,7 @@ export default function App(props: Props) {
|
|
|
43
54
|
// of routes, you may want to split this component into its own file.
|
|
44
55
|
function Routes() {
|
|
45
56
|
return useRoutes([
|
|
46
|
-
{
|
|
47
|
-
match: '/',
|
|
48
|
-
render: <Start />,
|
|
49
|
-
renderPreload: <Start.Preload />,
|
|
50
|
-
},
|
|
57
|
+
{match: '/', render: <Start />, renderPreload: <Start.Preload />},
|
|
51
58
|
]);
|
|
52
59
|
}
|
|
53
60
|
|
|
@@ -55,7 +62,8 @@ function Routes() {
|
|
|
55
62
|
function AppContext({
|
|
56
63
|
children,
|
|
57
64
|
fetchGraphQL: customFetchGraphQL,
|
|
58
|
-
|
|
65
|
+
...context
|
|
66
|
+
}: PropsWithChildren<AppProps>) {
|
|
59
67
|
const {fetchGraphQL, queryClient} = useMemo(() => {
|
|
60
68
|
return {
|
|
61
69
|
fetchGraphQL:
|
|
@@ -67,7 +75,9 @@ function AppContext({
|
|
|
67
75
|
return (
|
|
68
76
|
<GraphQLContext fetch={fetchGraphQL}>
|
|
69
77
|
<ReactQueryContext client={queryClient}>
|
|
70
|
-
<
|
|
78
|
+
<AppContextReact.Provider value={context}>
|
|
79
|
+
{children}
|
|
80
|
+
</AppContextReact.Provider>
|
|
71
81
|
</ReactQueryContext>
|
|
72
82
|
</GraphQLContext>
|
|
73
83
|
);
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import {describe, it, expect} from '@quilted/quilt/testing';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
renderApp,
|
|
5
|
-
fillGraphQL,
|
|
6
|
-
createGraphQLController,
|
|
7
|
-
} from '~/tests/render.tsx';
|
|
3
|
+
import {renderApp, fillGraphQL, GraphQLController} from '~/tests/render.ts';
|
|
8
4
|
|
|
9
5
|
import Start from './Start.tsx';
|
|
10
6
|
import startQuery from './StartQuery.graphql';
|
|
@@ -12,11 +8,11 @@ import startQuery from './StartQuery.graphql';
|
|
|
12
8
|
describe('<Start />', () => {
|
|
13
9
|
it('welcomes the user with their name', async () => {
|
|
14
10
|
const name = 'Winston';
|
|
15
|
-
const graphql =
|
|
11
|
+
const graphql = new GraphQLController([fillGraphQL(startQuery, {name})]);
|
|
16
12
|
|
|
17
13
|
const start = await renderApp(<Start />, {graphql});
|
|
18
14
|
|
|
19
|
-
expect(graphql).
|
|
15
|
+
expect(graphql).toHavePerformedGraphQLQuery(startQuery);
|
|
20
16
|
expect(start).toContainReactText(`Hello ${name}!`);
|
|
21
17
|
});
|
|
22
18
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {useGraphQLQuery} from '@quilted/react-query';
|
|
2
|
+
|
|
3
|
+
import styles from './Start.module.css';
|
|
4
|
+
import startQuery from './StartQuery.graphql';
|
|
5
|
+
|
|
6
|
+
export default function Start() {
|
|
7
|
+
const {data} = useGraphQLQuery(startQuery);
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<div className={styles.Start}>
|
|
11
|
+
{data ? `Hello ${data.name}!` : 'Hello!'}
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {Frame} from './frame/Frame.tsx';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {Viewport, SearchRobots} from '@quilted/quilt/html';
|
|
2
1
|
import {describe, it, expect} from '@quilted/quilt/testing';
|
|
2
|
+
import {Viewport, SearchRobots} from '@quilted/quilt/html';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {renderApp} from '~/tests/render.tsx';
|
|
5
5
|
|
|
6
6
|
import {Head} from './Head.tsx';
|
|
7
7
|
|
|
8
8
|
describe('<Head />', () => {
|
|
9
9
|
it('includes a responsive viewport tag', async () => {
|
|
10
|
-
const head = await
|
|
10
|
+
const head = await renderApp(<Head />);
|
|
11
11
|
|
|
12
12
|
expect(head).toContainReactComponent(Viewport, {
|
|
13
13
|
cover: true,
|
|
@@ -15,7 +15,7 @@ describe('<Head />', () => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('prevents search robots from indexing the application', async () => {
|
|
18
|
-
const head = await
|
|
18
|
+
const head = await renderApp(<Head />);
|
|
19
19
|
|
|
20
20
|
expect(head).toContainReactComponent(SearchRobots, {
|
|
21
21
|
index: false,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {Head} from './html/Head.tsx';
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {CacheControl, ContentSecurityPolicy} from '@quilted/quilt/http';
|
|
2
1
|
import {describe, it, expect} from '@quilted/quilt/testing';
|
|
2
|
+
import {CacheControl, ContentSecurityPolicy} from '@quilted/quilt/http';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {renderApp} from '~/tests/render.tsx';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {Headers} from './Headers.tsx';
|
|
7
7
|
|
|
8
|
-
describe('<
|
|
8
|
+
describe('<Headers />', () => {
|
|
9
9
|
it('does not cache the response', async () => {
|
|
10
|
-
const
|
|
10
|
+
const headers = await renderApp(<Headers />);
|
|
11
11
|
|
|
12
|
-
expect(
|
|
12
|
+
expect(headers).toContainReactComponent(CacheControl, {
|
|
13
13
|
cache: false,
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('adds a content security policy with a strict default policy', async () => {
|
|
18
|
-
const
|
|
18
|
+
const headers = await renderApp(<Headers />);
|
|
19
19
|
|
|
20
|
-
expect(
|
|
20
|
+
expect(headers).toContainReactComponent(ContentSecurityPolicy, {
|
|
21
21
|
defaultSources: ["'self'"],
|
|
22
22
|
});
|
|
23
23
|
});
|