@solidjs/start 2.0.0-beta.0 → 2.0.0-beta.2

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 (91) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/config/dev-server.js +3 -1
  3. package/dist/config/fs-router.d.ts +1 -1
  4. package/dist/http/index.d.ts +4 -4
  5. package/package.json +11 -5
  6. package/scripts/build.js +0 -15
  7. package/scripts/validate-imports.js +0 -316
  8. package/src/client/StartClient.tsx +0 -34
  9. package/src/client/index.tsx +0 -2
  10. package/src/client/mount.ts +0 -1
  11. package/src/client/spa/index.tsx +0 -9
  12. package/src/config/constants.ts +0 -19
  13. package/src/config/dev-server.ts +0 -157
  14. package/src/config/env.ts +0 -105
  15. package/src/config/fs-router.ts +0 -162
  16. package/src/config/fs-routes/fs-watcher.ts +0 -66
  17. package/src/config/fs-routes/index.ts +0 -136
  18. package/src/config/fs-routes/router.ts +0 -184
  19. package/src/config/fs-routes/tree-shake.ts +0 -324
  20. package/src/config/index.ts +0 -239
  21. package/src/config/lazy.ts +0 -132
  22. package/src/config/manifest.ts +0 -120
  23. package/src/config/utils.ts +0 -5
  24. package/src/config/vite-utils.ts +0 -113
  25. package/src/directives/bubble-function-declaration.ts +0 -33
  26. package/src/directives/compile.ts +0 -54
  27. package/src/directives/generate-unique-name.ts +0 -22
  28. package/src/directives/get-descriptive-name.ts +0 -39
  29. package/src/directives/get-import-identifier.ts +0 -34
  30. package/src/directives/get-root-statement-path.ts +0 -14
  31. package/src/directives/index.ts +0 -233
  32. package/src/directives/is-statement-top-level.ts +0 -13
  33. package/src/directives/paths.ts +0 -63
  34. package/src/directives/plugin.ts +0 -389
  35. package/src/directives/remove-unused-variables.ts +0 -70
  36. package/src/directives/types.ts +0 -12
  37. package/src/directives/xxhash32.ts +0 -214
  38. package/src/env.d.ts +0 -17
  39. package/src/fns/client.ts +0 -141
  40. package/src/fns/handler.spec.ts +0 -85
  41. package/src/fns/handler.ts +0 -287
  42. package/src/fns/registration.ts +0 -19
  43. package/src/fns/serialization.ts +0 -250
  44. package/src/fns/server.ts +0 -46
  45. package/src/fns/shared.ts +0 -116
  46. package/src/http/index.ts +0 -216
  47. package/src/index.tsx +0 -7
  48. package/src/internal.d.ts +0 -14
  49. package/src/middleware/index.ts +0 -92
  50. package/src/router.tsx +0 -37
  51. package/src/server/StartServer.tsx +0 -58
  52. package/src/server/assets/PatchVirtualDevStyles.tsx +0 -31
  53. package/src/server/assets/index.ts +0 -70
  54. package/src/server/assets/render.tsx +0 -46
  55. package/src/server/collect-styles.ts +0 -70
  56. package/src/server/fetchEvent.spec.ts +0 -85
  57. package/src/server/fetchEvent.ts +0 -36
  58. package/src/server/handler.ts +0 -261
  59. package/src/server/index.tsx +0 -29
  60. package/src/server/manifest/client-manifest.ts +0 -8
  61. package/src/server/manifest/dev-client-manifest.ts +0 -21
  62. package/src/server/manifest/dev-ssr-manifest.ts +0 -23
  63. package/src/server/manifest/prod-client-manifest.ts +0 -21
  64. package/src/server/manifest/prod-ssr-manifest.ts +0 -109
  65. package/src/server/manifest/ssr-manifest.ts +0 -10
  66. package/src/server/routes.ts +0 -126
  67. package/src/server/spa/StartServer.tsx +0 -42
  68. package/src/server/spa/handler.ts +0 -29
  69. package/src/server/spa/index.tsx +0 -5
  70. package/src/server/types.ts +0 -82
  71. package/src/server/util.ts +0 -12
  72. package/src/shared/ErrorBoundary.tsx +0 -52
  73. package/src/shared/GET.ts +0 -8
  74. package/src/shared/HttpHeader.tsx +0 -42
  75. package/src/shared/HttpStatusCode.ts +0 -27
  76. package/src/shared/clientOnly.ts +0 -44
  77. package/src/shared/dev-overlay/CodeView.tsx +0 -90
  78. package/src/shared/dev-overlay/DevOverlayDialog.tsx +0 -316
  79. package/src/shared/dev-overlay/createStackFrame.ts +0 -74
  80. package/src/shared/dev-overlay/download.ts +0 -6
  81. package/src/shared/dev-overlay/env.d.ts +0 -4
  82. package/src/shared/dev-overlay/get-source-map.ts +0 -33
  83. package/src/shared/dev-overlay/icons.tsx +0 -456
  84. package/src/shared/dev-overlay/index.tsx +0 -63
  85. package/src/shared/dev-overlay/styles.css +0 -292
  86. package/src/shared/lazy.ts +0 -52
  87. package/src/shared/serverFunction.ts +0 -10
  88. package/src/utils/debounce.ts +0 -10
  89. package/src/virtual.d.ts +0 -27
  90. package/tsconfig.json +0 -24
  91. package/vitest.config.ts +0 -9
@@ -1,126 +0,0 @@
1
- // @ts-expect-error
2
- import fileRoutes from "solid-start:routes";
3
- import { createRouter } from "radix3";
4
-
5
- import type { FetchEvent } from "./types.ts";
6
-
7
- interface Route {
8
- path: string;
9
- id: string;
10
- children?: Route[];
11
- page?: boolean;
12
- $component?: any;
13
- $HEAD?: any;
14
- $GET?: any;
15
- $POST?: any;
16
- $PUT?: any;
17
- $PATCH?: any;
18
- $DELETE?: any;
19
- }
20
-
21
- export const pageRoutes = defineRoutes((fileRoutes as unknown as Route[]).filter(o => o.page));
22
-
23
- function defineRoutes(fileRoutes: Route[]) {
24
- function processRoute(routes: Route[], route: Route, id: string, full: string) {
25
- const parentRoute = Object.values(routes).find(o => {
26
- return id.startsWith(o.id + "/");
27
- });
28
-
29
- if (!parentRoute) {
30
- routes.push({
31
- ...route,
32
- id,
33
- path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/"),
34
- });
35
- return routes;
36
- }
37
- processRoute(
38
- parentRoute.children || (parentRoute.children = []),
39
- route,
40
- id.slice(parentRoute.id.length),
41
- full,
42
- );
43
-
44
- return routes;
45
- }
46
-
47
- return fileRoutes
48
- .sort((a, b) => a.path.length - b.path.length)
49
- .reduce((prevRoutes: Route[], route) => {
50
- return processRoute(prevRoutes, route, route.path, route.path);
51
- }, []);
52
- }
53
-
54
- const router = createRouter({
55
- routes: (fileRoutes as unknown as Route[]).reduce(
56
- (memo, route) => {
57
- if (!containsHTTP(route)) return memo;
58
- const path = route.path
59
- .replace(/\([^)/]+\)/g, "")
60
- .replace(/\/+/g, "/")
61
- .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
62
- .split("/")
63
- .map(s => (s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s)))
64
- .join("/");
65
- if (/:[^/]*\?/g.test(path)) {
66
- throw new Error(`Optional parameters are not supported in API routes: ${path}`);
67
- }
68
- if (memo[path]) {
69
- throw new Error(
70
- `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${
71
- route.path
72
- }"`,
73
- );
74
- }
75
- memo[path] = { route };
76
- return memo;
77
- },
78
- {} as Record<string, { route: Route }>,
79
- ),
80
- });
81
-
82
- function containsHTTP(route: Route) {
83
- return (
84
- route["$HEAD"] ||
85
- route["$GET"] ||
86
- route["$POST"] ||
87
- route["$PUT"] ||
88
- route["$PATCH"] ||
89
- route["$DELETE"]
90
- );
91
- }
92
-
93
- export function matchAPIRoute(
94
- path: string,
95
- method: string,
96
- ):
97
- | {
98
- params?: Record<string, any>;
99
- handler: {
100
- import: () => Promise<Record<string, (e: FetchEvent) => Promise<any>>>;
101
- };
102
- isPage: boolean;
103
- }
104
- | undefined {
105
- const match = router.lookup(path);
106
- if (match && match.route) {
107
- const route = match.route;
108
-
109
- // Find the appropriate handler for the HTTP method
110
- const handler = method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
111
-
112
- if (handler === undefined) return;
113
-
114
- // Check if this is a page route
115
- const isPage = route.page === true && route.$component !== undefined;
116
-
117
- // Return comprehensive route information
118
- return {
119
- handler,
120
- params: match.params,
121
- isPage,
122
- };
123
- }
124
-
125
- return undefined;
126
- }
@@ -1,42 +0,0 @@
1
- // @refresh skip
2
- // @ts-ignore
3
- import type { Component } from "solid-js";
4
- import { NoHydration, getRequestEvent, ssr } from "solid-js/web";
5
- import { getSsrManifest } from "../manifest/ssr-manifest.ts";
6
-
7
- import { TopErrorBoundary } from "../../shared/ErrorBoundary.tsx";
8
- import { useAssets } from "../assets/index.ts";
9
- import PatchVirtualDevStyles from "../assets/PatchVirtualDevStyles.tsx";
10
- import type { DocumentComponentProps, PageEvent } from "../types.ts";
11
-
12
- const docType = ssr("<!DOCTYPE html>");
13
-
14
- /**
15
- *
16
- * Read more: https://docs.solidjs.com/solid-start/reference/server/start-server
17
- */
18
- export function StartServer(props: { document: Component<DocumentComponentProps> }) {
19
- const context = getRequestEvent() as PageEvent;
20
- // @ts-ignore
21
- const nonce = context.nonce;
22
- useAssets(context.assets, nonce);
23
-
24
- return (
25
- <NoHydration>
26
- {docType as unknown as any}
27
- <TopErrorBoundary>
28
- <props.document
29
- scripts={
30
- <>
31
- <PatchVirtualDevStyles nonce={nonce} />
32
- <script
33
- type="module"
34
- src={getSsrManifest("client").path(import.meta.env.START_CLIENT_ENTRY)}
35
- />
36
- </>
37
- }
38
- />
39
- </TopErrorBoundary>
40
- </NoHydration>
41
- );
42
- }
@@ -1,29 +0,0 @@
1
- import type { JSX } from "solid-js";
2
-
3
- import { createBaseHandler } from "../handler.ts";
4
- import { getSsrManifest } from "../manifest/ssr-manifest.ts";
5
- import type { FetchEvent, HandlerOptions, PageEvent } from "../types.ts";
6
-
7
- /**
8
- *
9
- * Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
10
- */
11
- export function createHandler(
12
- fn: (context: PageEvent) => JSX.Element,
13
- options?: HandlerOptions | ((context: PageEvent) => HandlerOptions),
14
- ) {
15
- return createBaseHandler(createPageEvent, fn, options);
16
- }
17
-
18
- async function createPageEvent(ctx: FetchEvent) {
19
- const manifest = getSsrManifest("ssr");
20
- const pageEvent: PageEvent = Object.assign(ctx, {
21
- manifest: "json" in manifest ? await manifest.json() : {},
22
- assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
23
- routes: [],
24
- complete: false,
25
- $islands: new Set<string>(),
26
- });
27
-
28
- return pageEvent;
29
- }
@@ -1,5 +0,0 @@
1
- // @refresh skip
2
- export { default as lazy } from "../../shared/lazy.ts";
3
- export * from "../types.ts";
4
- export { StartServer } from "./StartServer.tsx";
5
- export { createHandler } from "./handler.ts";
@@ -1,82 +0,0 @@
1
- import type { H3Event } from "h3";
2
- import type { JSX } from "solid-js";
3
- import type { RequestEvent } from "solid-js/web";
4
-
5
- // export const FETCH_EVENT = "$FETCH";
6
-
7
- export type DocumentComponentProps = {
8
- assets?: JSX.Element;
9
- scripts: JSX.Element;
10
- children?: JSX.Element;
11
- };
12
-
13
- export type Asset =
14
- | {
15
- tag: "style";
16
- attrs: JSX.StyleHTMLAttributes<HTMLStyleElement> & { key?: string };
17
- children?: JSX.Element;
18
- }
19
- | {
20
- tag: "script";
21
- attrs: JSX.ScriptHTMLAttributes<HTMLScriptElement> & { key?: string };
22
- }
23
- | {
24
- tag: "link";
25
- attrs: JSX.LinkHTMLAttributes<HTMLLinkElement> & { key?: string };
26
- };
27
-
28
- export type HandlerOptions = {
29
- mode?: "sync" | "async" | "stream";
30
- nonce?: string;
31
- renderId?: string;
32
- onCompleteAll?: (options: { write: (v: any) => void }) => void;
33
- onCompleteShell?: (options: { write: (v: any) => void }) => void;
34
- };
35
-
36
- export type ContextMatches = {
37
- originalPath: string;
38
- pattern: string;
39
- path: string;
40
- params: unknown;
41
- };
42
-
43
- export interface ResponseStub {
44
- status?: number;
45
- statusText?: string;
46
- headers: Headers;
47
- }
48
-
49
- export interface FetchEvent {
50
- request: Request;
51
- response: ResponseStub;
52
- clientAddress?: string;
53
- locals: App.RequestEventLocals;
54
- nativeEvent: H3Event;
55
- }
56
-
57
- export interface PageEvent extends RequestEvent {
58
- assets: any[];
59
- routes: any[];
60
- // prevUrl: string | null;
61
- // $type: typeof FETCH_EVENT;
62
- $islands: Set<string>;
63
- complete: boolean;
64
- nonce?: string;
65
- // mutation: boolean;
66
- }
67
-
68
- export interface APIEvent extends FetchEvent {
69
- params: { [key: string]: string };
70
- }
71
-
72
- export type APIHandler = (event: APIEvent) => any;
73
-
74
- export interface ServerFunctionMeta {
75
- id: string;
76
- }
77
-
78
- declare module "solid-js/web" {
79
- interface RequestEvent extends FetchEvent {
80
- serverOnly?: boolean;
81
- }
82
- }
@@ -1,12 +0,0 @@
1
- import type { ResponseStub } from "./types.ts";
2
-
3
- // according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages
4
- const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
5
-
6
- export function getExpectedRedirectStatus(response: ResponseStub): number {
7
- if (response.status && validRedirectStatuses.has(response.status)) {
8
- return response.status;
9
- }
10
-
11
- return 302;
12
- }
@@ -1,52 +0,0 @@
1
- // @refresh skip
2
- import { ErrorBoundary as DefaultErrorBoundary, catchError, type ParentProps } from "solid-js";
3
- import { isServer } from "solid-js/web";
4
- import { HttpStatusCode } from "./HttpStatusCode.ts";
5
- import { DevOverlay } from "./dev-overlay/index.tsx";
6
-
7
- export const ErrorBoundary =
8
- import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY
9
- ? (props: ParentProps) => <DevOverlay>{props.children}</DevOverlay>
10
- : (props: ParentProps) => {
11
- const message = isServer
12
- ? "500 | Internal Server Error"
13
- : "Error | Uncaught Client Exception";
14
- return (
15
- <DefaultErrorBoundary
16
- fallback={error => {
17
- console.error(error);
18
- return (
19
- <>
20
- <span style="font-size:1.5em;text-align:center;position:fixed;left:0px;bottom:55%;width:100%;">
21
- {message}
22
- </span>
23
- <HttpStatusCode code={500} />
24
- </>
25
- );
26
- }}
27
- >
28
- {props.children}
29
- </DefaultErrorBoundary>
30
- );
31
- };
32
-
33
- export const TopErrorBoundary = (props: ParentProps) => {
34
- let isError = false;
35
- const res = catchError(
36
- () => props.children,
37
- err => {
38
- console.error(err);
39
- isError = !!err;
40
- },
41
- );
42
- return isError ? (
43
- <>
44
- <span style="font-size:1.5em;text-align:center;position:fixed;left:0px;bottom:55%;width:100%;">
45
- 500 | Internal Server Error
46
- </span>
47
- <HttpStatusCode code={500} />
48
- </>
49
- ) : (
50
- res
51
- );
52
- };
package/src/shared/GET.ts DELETED
@@ -1,8 +0,0 @@
1
- // @refresh skip
2
- /**
3
- *
4
- * Read more: https://docs.solidjs.com/solid-start/reference/server/get
5
- */
6
- export function GET<T extends (...args: any[]) => any>(fn: T) {
7
- return (fn as any).GET as (...args: Parameters<T>) => ReturnType<T>;
8
- }
@@ -1,42 +0,0 @@
1
- // @refresh skip
2
- import { onCleanup } from "solid-js";
3
- import { getRequestEvent, isServer } from "solid-js/web";
4
-
5
- import type { PageEvent } from "../server/types.ts";
6
- import { appendHeader, setHeader } from "../http/index.ts";
7
-
8
- export interface HttpHeaderProps {
9
- name: string;
10
- value: string;
11
- append?: boolean;
12
- }
13
-
14
- /**
15
- *
16
- * Read more: https://docs.solidjs.com/solid-start/reference/server/http-header
17
- */
18
- export const HttpHeader = isServer
19
- ? (props: HttpHeaderProps) => {
20
- const event = getRequestEvent() as PageEvent;
21
-
22
- if (props.append) appendHeader(props.name, props.value);
23
- else setHeader(props.name, props.value);
24
-
25
- onCleanup(() => {
26
- // @ts-expect-error
27
- if (event.nativeEvent.handled || event.complete) return;
28
- const value = event.response.headers.get(props.name);
29
- if (!value) return;
30
- if (!value.includes(", ")) {
31
- if (value === props.value) event.response.headers.delete(props.name);
32
- return;
33
- }
34
- const values = value.split(", ");
35
- const index = values.indexOf(props.value);
36
- index !== -1 && values.splice(index, 1);
37
- if (values.length) event.response.headers.set(props.name, values.join(","));
38
- else event.response.headers.delete(props.name);
39
- });
40
- return null;
41
- }
42
- : (_props: HttpHeaderProps) => null;
@@ -1,27 +0,0 @@
1
- // @refresh skip
2
- import { onCleanup } from "solid-js";
3
- import { getRequestEvent, isServer } from "solid-js/web";
4
- import type { PageEvent } from "../server/types.ts";
5
-
6
- export interface HttpStatusCodeProps {
7
- code: number;
8
- text?: string;
9
- }
10
-
11
- /**
12
- *
13
- * Read more: https://docs.solidjs.com/solid-start/reference/server/http-status-code
14
- */
15
- export const HttpStatusCode = isServer
16
- ? (props: HttpStatusCodeProps) => {
17
- const event = getRequestEvent() as PageEvent;
18
- event.response.status = props.code;
19
- event.response.statusText = props.text;
20
- onCleanup(
21
- () =>
22
- // !event.nativeEvent.handled &&
23
- !event.complete && (event.response.status = 200),
24
- );
25
- return null;
26
- }
27
- : (_props: HttpStatusCodeProps) => null;
@@ -1,44 +0,0 @@
1
- // @refresh skip
2
- import type { Component, ComponentProps, JSX, Setter } from "solid-js";
3
- import { createMemo, createSignal, onMount, sharedConfig, splitProps, untrack } from "solid-js";
4
- import { isServer } from "solid-js/web";
5
-
6
- /**
7
- *
8
- * Read more: https://docs.solidjs.com/solid-start/reference/client/client-only
9
- */
10
- // not using Suspense
11
- export default function clientOnly<T extends Component<any>>(
12
- fn: () => Promise<{
13
- default: T;
14
- }>,
15
- options: { lazy?: boolean } = {},
16
- ) {
17
- if (isServer) return (props: ComponentProps<T> & { fallback?: JSX.Element }) => props.fallback;
18
-
19
- const [comp, setComp] = createSignal<T>();
20
- !options.lazy && load(fn, setComp);
21
- return (props: ComponentProps<T>) => {
22
- let Comp: T | undefined;
23
- let m: boolean;
24
- const [, rest] = splitProps(props, ["fallback"]);
25
- options.lazy && load(fn, setComp);
26
- if ((Comp = comp()) && !sharedConfig.context) return Comp(rest);
27
- const [mounted, setMounted] = createSignal(!sharedConfig.context);
28
- onMount(() => setMounted(true));
29
- return createMemo(
30
- () => (
31
- (Comp = comp()), (m = mounted()), untrack(() => (Comp && m ? Comp(rest) : props.fallback))
32
- ),
33
- );
34
- };
35
- }
36
-
37
- function load<T>(
38
- fn: () => Promise<{
39
- default: T;
40
- }>,
41
- setComp: Setter<T>,
42
- ) {
43
- fn().then(m => setComp(() => m.default));
44
- }
@@ -1,90 +0,0 @@
1
- // @refresh skip
2
- import { type BuiltinLanguage, getSingletonHighlighter, type Highlighter } from "shiki";
3
- import { loadWasm } from "shiki/engine/oniguruma";
4
- import langJS from "shiki/langs/javascript.mjs";
5
- import langJSX from "shiki/langs/jsx.mjs";
6
- import langTSX from "shiki/langs/tsx.mjs";
7
- import langTS from "shiki/langs/typescript.mjs";
8
- import url from "shiki/onig.wasm?url";
9
- import darkPlus from "shiki/themes/dark-plus.mjs";
10
- import { createEffect, createResource, type JSX } from "solid-js";
11
-
12
- let HIGHLIGHTER: Highlighter;
13
-
14
- async function loadHighlighter() {
15
- if (!HIGHLIGHTER) {
16
- await loadWasm(await fetch(url));
17
- HIGHLIGHTER = await getSingletonHighlighter({
18
- themes: [darkPlus],
19
- langs: [langJS, langJSX, langTS, langTSX],
20
- });
21
- }
22
- return HIGHLIGHTER;
23
- }
24
-
25
- export interface CodeViewProps {
26
- fileName: string;
27
- content: string;
28
- line: number;
29
- }
30
-
31
- const RANGE = 8;
32
-
33
- export function CodeView(props: CodeViewProps): JSX.Element | null {
34
- const lines = () =>
35
- props.content.split("\n").map((item, index) => ({
36
- index: index + 1,
37
- line: item,
38
- }));
39
-
40
- const minLine = () => Math.max(props.line - (1 + RANGE), 0);
41
- const maxLine = () => Math.min(props.line + RANGE, lines().length - 1);
42
-
43
- let ref: HTMLDivElement | undefined;
44
-
45
- const [data] = createResource(
46
- () =>
47
- lines()
48
- .slice(minLine(), maxLine())
49
- .map(item => item.line)
50
- .join("\n"),
51
- async value => {
52
- const highlighter = await loadHighlighter();
53
- const fileExtension = props.fileName.split(/[#?]/)[0]!.split(".").pop()?.trim();
54
- let lang = fileExtension as BuiltinLanguage;
55
- if (fileExtension === "mjs" || fileExtension === "cjs") {
56
- lang = "js";
57
- }
58
- return highlighter.codeToHtml(value, {
59
- theme: "dark-plus",
60
- lang,
61
- });
62
- },
63
- );
64
-
65
- createEffect(() => {
66
- const result = data();
67
- if (ref && result) {
68
- ref.innerHTML = result;
69
-
70
- const lines = ref.querySelectorAll('span[class="line"]');
71
-
72
- for (let i = 0, len = lines.length; i < len; i++) {
73
- const el = lines[i] as HTMLElement;
74
- if (props.line - minLine() - 1 === i) {
75
- el.dataset.startDevOverlayErrorLine = '';
76
- }
77
- }
78
- }
79
- });
80
-
81
- return (
82
- <div
83
- ref={ref}
84
- data-start-dev-overlay-code-view
85
- style={{
86
- "--dev-overlay-code-view-start": minLine() + 1,
87
- }}
88
- />
89
- );
90
- }