@quilted/create 0.3.2 → 0.3.4
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 +111 -0
- package/build/esnext/_virtual/index7.esnext +2 -2
- package/build/esnext/_virtual/index8.esnext +2 -2
- package/build/esnext/node_modules/.pnpm/dir-glob@3.0.1/node_modules/dir-glob/index.esnext +1 -1
- package/build/esnext/node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/readers/stream.esnext +1 -1
- package/build/esnext/node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/utils/index.esnext +1 -1
- package/build/esnext/node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/utils/stream.esnext +1 -1
- package/package.json +1 -1
- package/templates/app-basic/App.tsx +8 -13
- package/templates/app-basic/browser.tsx +20 -39
- package/templates/app-basic/context/browser.ts +7 -3
- package/templates/app-basic/context/navigation.ts +6 -13
- package/templates/app-basic/context/preact.ts +9 -0
- package/templates/app-basic/context/server.ts +10 -3
- package/templates/app-basic/context/types.ts +20 -1
- package/templates/app-basic/package.json +1 -1
- package/templates/app-basic/tests/render/render.tsx +17 -22
- package/templates/app-basic/tests/render/types.ts +17 -13
- package/templates/app-basic/tests/render.ts +1 -1
- package/templates/app-empty/package.json +1 -1
- package/templates/app-graphql/App.tsx +10 -16
- package/templates/app-graphql/browser.tsx +20 -39
- package/templates/app-graphql/context/browser.ts +9 -13
- package/templates/app-graphql/context/navigation.ts +6 -13
- package/templates/app-graphql/context/preact.ts +9 -0
- package/templates/app-graphql/context/server.ts +13 -12
- package/templates/app-graphql/context/types.ts +23 -6
- package/templates/app-graphql/package.json +1 -1
- package/templates/app-graphql/tests/render/render.tsx +17 -37
- package/templates/app-graphql/tests/render/types.ts +20 -45
- package/templates/app-graphql/tests/render.ts +1 -1
- package/templates/app-trpc/App.tsx +15 -17
- package/templates/app-trpc/browser.tsx +20 -39
- package/templates/app-trpc/context/browser.ts +8 -4
- package/templates/app-trpc/context/navigation.ts +6 -13
- package/templates/app-trpc/context/preact.ts +9 -0
- package/templates/app-trpc/context/server.ts +11 -4
- package/templates/app-trpc/context/types.ts +27 -3
- package/templates/app-trpc/package.json +1 -1
- package/templates/app-trpc/tests/render/render.tsx +25 -29
- package/templates/app-trpc/tests/render/types.ts +17 -16
- package/templates/app-trpc/tests/render.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,116 @@
|
|
|
1
1
|
# @quilted/create
|
|
2
2
|
|
|
3
|
+
## 0.3.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e6fa47e`](https://github.com/lemonmade/quilt/commit/e6fa47e93981ce0eaebbe1546659aaa08cc22689) Thanks [@lemonmade](https://github.com/lemonmade)! - Update Preact and Signal dependencies
|
|
8
|
+
|
|
9
|
+
## 0.3.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#890](https://github.com/lemonmade/quilt/pull/890) [`b0f2334`](https://github.com/lemonmade/quilt/commit/b0f23340945280c951998bf77b3be8b8df13338c) Thanks [@lemonmade](https://github.com/lemonmade)! - Redesign asset loading APIs for better performance and clearer structure.
|
|
14
|
+
|
|
15
|
+
## Breaking changes
|
|
16
|
+
|
|
17
|
+
### `@quilted/assets`: `BrowserAssetsEntry` redesigned
|
|
18
|
+
|
|
19
|
+
The `BrowserAssetsEntry` type has been completely restructured. The previous flat `scripts` and `styles` arrays have been replaced with structured `script` and `style` objects that separate the entry asset from its dependencies:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// Before
|
|
23
|
+
interface BrowserAssetsEntry {
|
|
24
|
+
scripts: Asset[];
|
|
25
|
+
styles: Asset[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// After
|
|
29
|
+
interface BrowserAssetsEntry {
|
|
30
|
+
script?: {
|
|
31
|
+
asset: Asset;
|
|
32
|
+
syncDependencies: readonly Asset[];
|
|
33
|
+
asyncDependencies: readonly Asset[];
|
|
34
|
+
};
|
|
35
|
+
style?: {
|
|
36
|
+
asset: Asset;
|
|
37
|
+
syncDependencies: readonly Asset[];
|
|
38
|
+
asyncDependencies: readonly Asset[];
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This separation enables the renderer to treat the entry script, its preloadable sync dependencies, and its async dependencies differently in the HTML output.
|
|
44
|
+
|
|
45
|
+
### `@quilted/assets`: `BrowserAssets.modules()` return type changed
|
|
46
|
+
|
|
47
|
+
`modules()` now returns `readonly BrowserAssetsEntry[]` (one entry per module ID) instead of a single merged `BrowserAssetsEntry`:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// Before
|
|
51
|
+
modules(modules: Iterable<...>, options?): BrowserAssetsEntry;
|
|
52
|
+
|
|
53
|
+
// After
|
|
54
|
+
modules(modules: Iterable<string>, options?): readonly BrowserAssetsEntry[];
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `@quilted/assets`: `BrowserAssetModuleSelector` removed
|
|
58
|
+
|
|
59
|
+
The `BrowserAssetModuleSelector` interface and the `modules` field on `BrowserAssetSelector` have been removed. If you want to get the asset details for modules in addition to the entrypoints, use `BrowserAssets.modules()` instead.
|
|
60
|
+
|
|
61
|
+
### `@quilted/assets`: `AssetBuildManifest` module entry format changed
|
|
62
|
+
|
|
63
|
+
`AssetBuildManifest.modules` values changed from `number[]` to the new `AssetBuildModuleEntry` tuple type. The tuple uses positional slots for each asset category and is serialized in JSON as an object with numeric string keys (omitting empty positions):
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
type AssetBuildModuleEntry = [
|
|
67
|
+
script?: number, // [0] entry JS chunk
|
|
68
|
+
style?: number, // [1] entry CSS file
|
|
69
|
+
scriptSync?: number[], // [2] sync JS dependency indices
|
|
70
|
+
styleSync?: number[], // [3] CSS from sync JS dependencies
|
|
71
|
+
scriptAsync?: number[], // [4] dynamic JS dependency indices
|
|
72
|
+
styleAsync?: number[], // [5] CSS from dynamic JS dependencies
|
|
73
|
+
];
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `@quilted/browser`: `BrowserResponseAssets.get()` return type changed
|
|
77
|
+
|
|
78
|
+
`get()` now returns `string[]` (module IDs) instead of `BrowserAssetModuleSelector[]`.
|
|
79
|
+
|
|
80
|
+
## New features
|
|
81
|
+
|
|
82
|
+
### `@quilted/preact-browser`: `BrowserApp` class
|
|
83
|
+
|
|
84
|
+
A new `BrowserApp` class simplifies constructing and running a browser app. It handles waiting for the `#app` DOM element via `MutationObserver`, which is necessary now that the entry script runs with the `async` attribute:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import {BrowserApp} from '@quilted/quilt/browser';
|
|
88
|
+
import {BrowserAppContext} from '~/context/browser.ts';
|
|
89
|
+
import {App} from './App.tsx';
|
|
90
|
+
|
|
91
|
+
const context = new BrowserAppContext();
|
|
92
|
+
const app = new BrowserApp(<App context={context} />, {context});
|
|
93
|
+
await app.hydrate();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Render behavior changes
|
|
97
|
+
|
|
98
|
+
### Entry script rendered as `async` module
|
|
99
|
+
|
|
100
|
+
The browser entry script is now rendered as `<script type="module" async>` instead of a blocking `<script type="module">`. This means the script no longer blocks HTML parsing, and does not wait for DOMContentLoaded. This change is meant to allow streaming HTML responses to begin executing JavaScript earlier.
|
|
101
|
+
|
|
102
|
+
### Sync dependencies rendered as `modulepreload` links
|
|
103
|
+
|
|
104
|
+
Sync JS dependencies (previously rendered as additional `<script type="module">` tags) are now rendered as `<link rel="modulepreload">` hints. This tells the browser to fetch them eagerly without executing them, since the entry script will import them when it runs.
|
|
105
|
+
|
|
106
|
+
### Stylesheets rendered after all script references
|
|
107
|
+
|
|
108
|
+
Entry and async stylesheets are now emitted from the `<HTMLTemplate.Assets async />` placeholder, after all script and modulepreload tags. This ensures the stylesheet `<link>` elements appear after all JS references in the HTML.
|
|
109
|
+
|
|
110
|
+
### Asset deduplication across streamed chunks
|
|
111
|
+
|
|
112
|
+
Asset deduplication (preventing the same `src`/`href` from appearing more than once) now works across all streamed HTML chunks within a single response, not just within a single placeholder.
|
|
113
|
+
|
|
3
114
|
## 0.3.2
|
|
4
115
|
|
|
5
116
|
### Patch Changes
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var dirGlob = {exports: {}};
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { dirGlob as __module };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var utils = {};
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { utils as __exports };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __module as dirGlob } from '../../../../../_virtual/
|
|
1
|
+
import { __module as dirGlob } from '../../../../../_virtual/index7.esnext';
|
|
2
2
|
import path__default from 'node:path';
|
|
3
3
|
import { __require as requirePathType } from '../../../path-type@4.0.0/node_modules/path-type/index.esnext';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __exports as stream } from '../../../../../../../_virtual/
|
|
1
|
+
import { __exports as stream } from '../../../../../../../_virtual/stream2.esnext';
|
|
2
2
|
import require$$0 from 'node:stream';
|
|
3
3
|
import { __require as requireOut } from '../../../../../@nodelib_fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/index.esnext';
|
|
4
4
|
import { __require as requireOut$1 } from '../../../../../@nodelib_fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/index.esnext';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __exports as utils } from '../../../../../../../_virtual/
|
|
1
|
+
import { __exports as utils } from '../../../../../../../_virtual/index8.esnext';
|
|
2
2
|
import { __require as requireArray } from './array.esnext';
|
|
3
3
|
import { __require as requireErrno } from './errno.esnext';
|
|
4
4
|
import { __require as requireFs } from './fs.esnext';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __exports as stream } from '../../../../../../../_virtual/
|
|
1
|
+
import { __exports as stream } from '../../../../../../../_virtual/stream3.esnext';
|
|
2
2
|
import { __require as requireMerge2 } from '../../../../../merge2@1.4.1/node_modules/merge2/index.esnext';
|
|
3
3
|
|
|
4
4
|
var hasRequiredStream;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {NotFound} from '@quilted/quilt/server';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {Routes} from '@quilted/quilt/navigation';
|
|
3
|
+
import {QuiltFrameworkContext} from '@quilted/quilt/context';
|
|
4
4
|
|
|
5
5
|
import {Head} from './foundation/html.ts';
|
|
6
6
|
import {Frame} from './foundation/frame.ts';
|
|
@@ -15,8 +15,6 @@ export interface AppProps {
|
|
|
15
15
|
context: AppContext;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
// Define the routes for your application. If you have a lot of routes, you
|
|
19
|
-
// might want to split this into a separate file.
|
|
20
18
|
const routes = [
|
|
21
19
|
routeWithAppContext('*', {
|
|
22
20
|
render: (children) => <Frame>{children}</Frame>,
|
|
@@ -32,19 +30,16 @@ const routes = [
|
|
|
32
30
|
}),
|
|
33
31
|
];
|
|
34
32
|
|
|
35
|
-
// The root component for your application. You will typically render any
|
|
36
|
-
// app-wide context in this component.
|
|
37
33
|
export function App({context}: AppProps) {
|
|
38
34
|
return (
|
|
39
35
|
<AppContextPreact.Provider value={context}>
|
|
40
|
-
<
|
|
36
|
+
<QuiltFrameworkContext
|
|
37
|
+
navigation={context.navigation}
|
|
38
|
+
localization={context.localization}
|
|
39
|
+
>
|
|
41
40
|
<Head />
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
routes={routes}
|
|
45
|
-
context={context}
|
|
46
|
-
/>
|
|
47
|
-
</Localization>
|
|
41
|
+
<Routes list={routes} context={context} />
|
|
42
|
+
</QuiltFrameworkContext>
|
|
48
43
|
</AppContextPreact.Provider>
|
|
49
44
|
);
|
|
50
45
|
}
|
|
@@ -1,45 +1,26 @@
|
|
|
1
1
|
import './browser.css';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {hydrate} from '@quilted/quilt/browser';
|
|
3
|
+
import {BrowserApp} from '@quilted/quilt/browser';
|
|
5
4
|
|
|
6
5
|
import {BrowserAppContext} from '~/context/browser.ts';
|
|
7
6
|
import {App} from './App.tsx';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// // Log the current URL
|
|
29
|
-
// console.log(globalThis.app.context.router.currentRequest.url);
|
|
30
|
-
// ```
|
|
31
|
-
Object.defineProperty(globalThis, 'app', {
|
|
32
|
-
value: this,
|
|
33
|
-
enumerable: false,
|
|
34
|
-
configurable: true,
|
|
35
|
-
writable: true,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
hydrate() {
|
|
40
|
-
hydrate(this.rendered);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const app = new BrowserApp();
|
|
45
|
-
app.hydrate();
|
|
8
|
+
const context = new BrowserAppContext();
|
|
9
|
+
|
|
10
|
+
const app = new BrowserApp(<App context={context} />, {context});
|
|
11
|
+
|
|
12
|
+
// Makes key parts of the app available in the browser console.
|
|
13
|
+
//
|
|
14
|
+
// @example
|
|
15
|
+
// ```js
|
|
16
|
+
// // Log the current URL
|
|
17
|
+
// console.log(globalThis.app.context.navigation.currentRequest.url);
|
|
18
|
+
// ```
|
|
19
|
+
Object.defineProperty(globalThis, 'app', {
|
|
20
|
+
value: app,
|
|
21
|
+
enumerable: false,
|
|
22
|
+
configurable: true,
|
|
23
|
+
writable: true,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await app.hydrate();
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import {Navigation} from '@quilted/quilt/navigation';
|
|
2
|
+
import {Localization} from '@quilted/quilt/localize';
|
|
3
|
+
|
|
1
4
|
import type {AppContext} from './types.ts';
|
|
2
|
-
import {NavigationForApp} from './navigation.ts';
|
|
3
5
|
|
|
4
6
|
export class BrowserAppContext implements AppContext {
|
|
5
|
-
readonly navigation:
|
|
7
|
+
readonly navigation: Navigation;
|
|
8
|
+
readonly localization: Localization;
|
|
6
9
|
|
|
7
10
|
constructor() {
|
|
8
|
-
this.navigation = new
|
|
11
|
+
this.navigation = new Navigation();
|
|
12
|
+
this.localization = new Localization(navigator.language);
|
|
9
13
|
}
|
|
10
14
|
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createContextRouteFunction,
|
|
3
|
+
Navigation,
|
|
4
|
+
} from '@quilted/quilt/navigation';
|
|
2
5
|
|
|
3
6
|
import type {AppContext} from './types.ts';
|
|
4
7
|
|
|
5
|
-
export interface Navigation {
|
|
6
|
-
readonly router: Router;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class NavigationForApp implements Navigation {
|
|
10
|
-
readonly router: Router;
|
|
11
|
-
|
|
12
|
-
constructor(url?: string | URL) {
|
|
13
|
-
this.router = new Router(url);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
8
|
export const routeWithAppContext = createContextRouteFunction<AppContext>();
|
|
9
|
+
|
|
10
|
+
export {Navigation};
|
|
@@ -2,5 +2,14 @@ import {createOptionalContext} from '@quilted/quilt/context';
|
|
|
2
2
|
|
|
3
3
|
import type {AppContext} from './types.ts';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The Preact context object for this application's shared context.
|
|
7
|
+
* Provide it in `App.tsx` via `<AppContextPreact.Provider value={context}>`.
|
|
8
|
+
*/
|
|
5
9
|
export const AppContextPreact = createOptionalContext<AppContext>();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Returns the app's shared context. All fields in `AppContext` are required
|
|
13
|
+
* and will be available anywhere inside `<AppContextPreact.Provider>`.
|
|
14
|
+
*/
|
|
6
15
|
export const useAppContext = AppContextPreact.use;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import {Navigation} from '@quilted/quilt/navigation';
|
|
2
|
+
import {Localization, parseAcceptLanguageHeader} from '@quilted/quilt/localize';
|
|
3
|
+
|
|
1
4
|
import type {AppContext} from './types.ts';
|
|
2
|
-
import {NavigationForApp} from './navigation.ts';
|
|
3
5
|
|
|
4
6
|
export class ServerAppContext implements AppContext {
|
|
5
|
-
readonly navigation:
|
|
7
|
+
readonly navigation: Navigation;
|
|
8
|
+
readonly localization: Localization;
|
|
6
9
|
|
|
7
10
|
constructor(request: Request) {
|
|
8
|
-
this.navigation = new
|
|
11
|
+
this.navigation = new Navigation(request.url);
|
|
12
|
+
this.localization = new Localization(
|
|
13
|
+
parseAcceptLanguageHeader(request.headers.get('Accept-Language') ?? '') ??
|
|
14
|
+
'en',
|
|
15
|
+
);
|
|
9
16
|
}
|
|
10
17
|
}
|
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import type {Navigation} from '
|
|
1
|
+
import type {Navigation} from '@quilted/quilt/navigation';
|
|
2
|
+
import type {Localization} from '@quilted/quilt/localize';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The shared context for this application. Values in this object are
|
|
6
|
+
* available to all components in the app via `useQuiltContext()` hooks
|
|
7
|
+
* or the `useAppContext()` convenience hook.
|
|
8
|
+
*
|
|
9
|
+
* This interface extends a subset of `QuiltContext`, providing the
|
|
10
|
+
* navigation and localization fields as required (non-optional) values.
|
|
11
|
+
*/
|
|
3
12
|
export interface AppContext {
|
|
13
|
+
/**
|
|
14
|
+
* The navigation instance for this application. Manages the current URL,
|
|
15
|
+
* browser history, and programmatic navigation.
|
|
16
|
+
*/
|
|
4
17
|
readonly navigation: Navigation;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The localization instance for this application. Contains the active
|
|
21
|
+
* locale and formatting utilities for numbers, dates, currencies, and more.
|
|
22
|
+
*/
|
|
23
|
+
readonly localization: Localization;
|
|
5
24
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import {createRender} from '@quilted/quilt/testing';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
BrowserTestMock,
|
|
5
|
-
} from '@quilted/quilt/browser/testing';
|
|
6
|
-
import {Navigation, TestRouter} from '@quilted/quilt/navigation/testing';
|
|
2
|
+
import {TestBrowser} from '@quilted/quilt/browser/testing';
|
|
3
|
+
import {TestNavigation} from '@quilted/quilt/navigation/testing';
|
|
7
4
|
import {Localization} from '@quilted/quilt/localize';
|
|
8
|
-
|
|
9
|
-
import {AppContextPreact} from '~/context/preact.ts';
|
|
5
|
+
import {QuiltFrameworkTestContext} from '@quilted/quilt/context/testing';
|
|
10
6
|
|
|
11
7
|
import {RenderOptions, RenderContext, RenderActions} from './types.ts';
|
|
12
8
|
|
|
@@ -23,24 +19,23 @@ export const renderApp = createRender<
|
|
|
23
19
|
// Create context that can be used by the `render` function, and referenced by test
|
|
24
20
|
// authors on the `root.context` property. Context is used to share data between your
|
|
25
21
|
// React tree and your test code, and is ideal for mocking out global context providers.
|
|
26
|
-
context({
|
|
27
|
-
|
|
22
|
+
context({
|
|
23
|
+
navigation = new TestNavigation(),
|
|
24
|
+
browser = new TestBrowser(),
|
|
25
|
+
localization = new Localization('en'),
|
|
26
|
+
}) {
|
|
27
|
+
return {navigation, browser, localization};
|
|
28
28
|
},
|
|
29
29
|
// Render all of our app-wide context providers around each component under test.
|
|
30
|
-
render(element,
|
|
31
|
-
const {
|
|
32
|
-
navigation: {router},
|
|
33
|
-
browser,
|
|
34
|
-
} = context;
|
|
35
|
-
|
|
30
|
+
render(element, {navigation, browser, localization}) {
|
|
36
31
|
return (
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
</
|
|
32
|
+
<QuiltFrameworkTestContext
|
|
33
|
+
navigation={navigation}
|
|
34
|
+
browser={browser}
|
|
35
|
+
localization={localization}
|
|
36
|
+
>
|
|
37
|
+
{element}
|
|
38
|
+
</QuiltFrameworkTestContext>
|
|
44
39
|
);
|
|
45
40
|
},
|
|
46
41
|
async afterRender() {
|
|
@@ -1,38 +1,42 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
import type {AppContext} from '~/context/types.ts';
|
|
1
|
+
import type {TestNavigation} from '@quilted/quilt/navigation/testing';
|
|
2
|
+
import type {TestBrowser} from '@quilted/quilt/browser/testing';
|
|
3
|
+
import type {Localization} from '@quilted/quilt/localize';
|
|
5
4
|
|
|
6
5
|
export interface RenderOptions {
|
|
7
6
|
/**
|
|
8
|
-
* A custom
|
|
7
|
+
* A custom navigation to use for this component test. You can use a
|
|
9
8
|
* custom router to simulate a particular URL, and you can spy on
|
|
10
9
|
* its navigation method to check that components navigate as
|
|
11
10
|
* you expect.
|
|
12
11
|
*/
|
|
13
|
-
readonly
|
|
12
|
+
readonly navigation?: TestNavigation;
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* A custom environment for this component test.
|
|
17
16
|
*/
|
|
18
|
-
readonly browser?:
|
|
17
|
+
readonly browser?: TestBrowser;
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
|
-
* A custom
|
|
20
|
+
* A custom localization instance to use for this component test.
|
|
22
21
|
*/
|
|
23
|
-
readonly
|
|
22
|
+
readonly localization?: Localization;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
export interface RenderContext
|
|
25
|
+
export interface RenderContext {
|
|
27
26
|
/**
|
|
28
|
-
* The
|
|
27
|
+
* The navigation used for this component test.
|
|
29
28
|
*/
|
|
30
|
-
readonly navigation:
|
|
29
|
+
readonly navigation: TestNavigation;
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* The browser environment for this component test.
|
|
34
33
|
*/
|
|
35
|
-
readonly browser:
|
|
34
|
+
readonly browser: TestBrowser;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The localization used for this component test.
|
|
38
|
+
*/
|
|
39
|
+
readonly localization: Localization;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
export interface RenderActions extends Record<string, never> {}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {NotFound} from '@quilted/quilt/server';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {Localization} from '@quilted/quilt/localize';
|
|
2
|
+
import {Routes} from '@quilted/quilt/navigation';
|
|
3
|
+
import {QuiltFrameworkContext} from '@quilted/quilt/context';
|
|
5
4
|
|
|
6
5
|
import {Head} from './foundation/html.ts';
|
|
7
6
|
import {Frame} from './foundation/frame.ts';
|
|
@@ -24,7 +23,7 @@ const routes = [
|
|
|
24
23
|
children: [
|
|
25
24
|
routeWithAppContext('/', {
|
|
26
25
|
async load({context: {graphql}}) {
|
|
27
|
-
await Promise.all([Home.load(), graphql.cache
|
|
26
|
+
await Promise.all([Home.load(), graphql.cache?.query(homeQuery)]);
|
|
28
27
|
},
|
|
29
28
|
render: <Home />,
|
|
30
29
|
}),
|
|
@@ -38,19 +37,14 @@ const routes = [
|
|
|
38
37
|
export function App({context}: AppProps) {
|
|
39
38
|
return (
|
|
40
39
|
<AppContextPreact.Provider value={context}>
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
<QuiltFrameworkContext
|
|
41
|
+
navigation={context.navigation}
|
|
42
|
+
localization={context.localization}
|
|
43
|
+
graphql={context.graphql}
|
|
44
44
|
>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
router={context.navigation.router}
|
|
49
|
-
routes={routes}
|
|
50
|
-
context={context}
|
|
51
|
-
/>
|
|
52
|
-
</Localization>
|
|
53
|
-
</GraphQLContext>
|
|
45
|
+
<Head />
|
|
46
|
+
<Routes list={routes} context={context} />
|
|
47
|
+
</QuiltFrameworkContext>
|
|
54
48
|
</AppContextPreact.Provider>
|
|
55
49
|
);
|
|
56
50
|
}
|
|
@@ -1,46 +1,27 @@
|
|
|
1
1
|
import './browser.css';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {hydrate} from '@quilted/quilt/browser';
|
|
3
|
+
import {BrowserApp} from '@quilted/quilt/browser';
|
|
5
4
|
|
|
6
5
|
import {BrowserAppContext} from '~/context/browser.ts';
|
|
7
6
|
|
|
8
7
|
import {App} from './App.tsx';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// // Log the current URL
|
|
30
|
-
// console.log(globalThis.app.context.navigation.router.currentRequest.url);
|
|
31
|
-
// ```
|
|
32
|
-
Object.defineProperty(globalThis, 'app', {
|
|
33
|
-
value: this,
|
|
34
|
-
enumerable: false,
|
|
35
|
-
configurable: true,
|
|
36
|
-
writable: true,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
hydrate() {
|
|
41
|
-
hydrate(this.rendered);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const app = new BrowserApp();
|
|
46
|
-
app.hydrate();
|
|
9
|
+
const context = new BrowserAppContext();
|
|
10
|
+
|
|
11
|
+
const app = new BrowserApp(<App context={context} />, {context});
|
|
12
|
+
|
|
13
|
+
// Makes key parts of the app available in the browser console.
|
|
14
|
+
//
|
|
15
|
+
// @example
|
|
16
|
+
// ```js
|
|
17
|
+
// // Log the current URL
|
|
18
|
+
// console.log(globalThis.app.context.navigation.currentRequest.url);
|
|
19
|
+
// ```
|
|
20
|
+
Object.defineProperty(globalThis, 'app', {
|
|
21
|
+
value: app,
|
|
22
|
+
enumerable: false,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await app.hydrate();
|