@websolutespa/bom-next 4.0.0-next.2 → 4.0.0-next.3

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 (141) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +78 -28
  3. package/dist/client/client.d.ts +2 -2
  4. package/dist/client/extra.d.ts +3 -3
  5. package/dist/client/label.d.ts +3 -3
  6. package/dist/client/layout.d.ts +3 -3
  7. package/dist/client/layout.d.ts.map +1 -1
  8. package/dist/client/metadata.d.ts +13 -3
  9. package/dist/client/metadata.d.ts.map +1 -1
  10. package/dist/client/metadata.js +27 -46
  11. package/dist/client/metadata.js.map +1 -1
  12. package/dist/client/page.d.ts +4 -3
  13. package/dist/client/page.d.ts.map +1 -1
  14. package/dist/client/useApi.d.ts +7 -7
  15. package/dist/client/useCollectionApi.d.ts +6 -6
  16. package/dist/client/useCollectionApi.d.ts.map +1 -1
  17. package/dist/client/usePage.d.ts +1 -0
  18. package/dist/client/user.d.ts +15 -8
  19. package/dist/client/user.d.ts.map +1 -1
  20. package/dist/client/user.js +37 -14
  21. package/dist/client/user.js.map +1 -1
  22. package/dist/exports/client.d.ts +2 -2
  23. package/dist/exports/client.js +2 -2
  24. package/dist/exports/proxy.d.ts +3 -3
  25. package/dist/exports/proxy.js +3 -3
  26. package/dist/exports/server.d.ts +6 -4
  27. package/dist/exports/server.js +6 -4
  28. package/dist/lib/debug.js +14 -0
  29. package/dist/lib/debug.js.map +1 -0
  30. package/dist/lib/http.d.ts.map +1 -1
  31. package/dist/lib/http.js +2 -1
  32. package/dist/lib/http.js.map +1 -1
  33. package/dist/lib/meta-data.d.ts.map +1 -1
  34. package/dist/lib/page-metadata.d.ts +57 -0
  35. package/dist/lib/page-metadata.d.ts.map +1 -0
  36. package/dist/lib/page-metadata.js +205 -0
  37. package/dist/lib/page-metadata.js.map +1 -0
  38. package/dist/lib/ttl-cache.js +59 -0
  39. package/dist/lib/ttl-cache.js.map +1 -0
  40. package/dist/proxy/protected-route.d.ts.map +1 -1
  41. package/dist/proxy/protected-route.js +3 -2
  42. package/dist/proxy/protected-route.js.map +1 -1
  43. package/dist/proxy/route-auto-detection.d.ts +6 -1
  44. package/dist/proxy/route-auto-detection.d.ts.map +1 -1
  45. package/dist/proxy/route-auto-detection.js +61 -25
  46. package/dist/proxy/route-auto-detection.js.map +1 -1
  47. package/dist/proxy/route-proxy.d.ts +4 -1
  48. package/dist/proxy/route-proxy.d.ts.map +1 -1
  49. package/dist/proxy/route-proxy.js +96 -14
  50. package/dist/proxy/route-proxy.js.map +1 -1
  51. package/dist/server/handlers/registry.handler.d.ts.map +1 -1
  52. package/dist/server/handlers/registry.handler.js +77 -11
  53. package/dist/server/handlers/registry.handler.js.map +1 -1
  54. package/dist/server/handlers/route.handler.d.ts +12 -4
  55. package/dist/server/handlers/route.handler.d.ts.map +1 -1
  56. package/dist/server/handlers/route.handler.js +54 -39
  57. package/dist/server/handlers/route.handler.js.map +1 -1
  58. package/dist/server/helpers.d.ts +3 -5
  59. package/dist/server/helpers.d.ts.map +1 -1
  60. package/dist/server/json-ld.d.ts +33 -0
  61. package/dist/server/json-ld.d.ts.map +1 -0
  62. package/dist/server/json-ld.js +50 -0
  63. package/dist/server/json-ld.js.map +1 -0
  64. package/dist/server/layout.js +2 -1
  65. package/dist/server/layout.js.map +1 -1
  66. package/dist/server/lazy.js +8 -11
  67. package/dist/server/lazy.js.map +1 -1
  68. package/dist/server/metadata.d.ts +27 -11
  69. package/dist/server/metadata.d.ts.map +1 -1
  70. package/dist/server/metadata.js +29 -11
  71. package/dist/server/metadata.js.map +1 -1
  72. package/dist/server/mixer.d.ts +11 -4
  73. package/dist/server/mixer.d.ts.map +1 -1
  74. package/dist/server/mixer.js +93 -114
  75. package/dist/server/mixer.js.map +1 -1
  76. package/package.json +8 -5
  77. package/src/client/metadata.tsx +22 -57
  78. package/src/client/user.test.tsx +44 -0
  79. package/src/client/user.tsx +47 -14
  80. package/src/exports/server.ts +1 -0
  81. package/src/lib/debug.ts +11 -0
  82. package/src/lib/http.ts +2 -1
  83. package/src/lib/page-metadata.test.ts +126 -0
  84. package/src/lib/page-metadata.ts +231 -0
  85. package/src/lib/ttl-cache.ts +72 -0
  86. package/src/proxy/protected-route.ts +3 -2
  87. package/src/proxy/route-auto-detection.test.ts +50 -0
  88. package/src/proxy/route-auto-detection.ts +75 -24
  89. package/src/proxy/route-proxy.test.ts +93 -0
  90. package/src/proxy/route-proxy.ts +94 -18
  91. package/src/server/context.test.ts +64 -12
  92. package/src/server/handlers/registry.handler.test.ts +103 -11
  93. package/src/server/handlers/registry.handler.ts +98 -11
  94. package/src/server/handlers/route.handler.test.ts +39 -0
  95. package/src/server/handlers/route.handler.ts +61 -58
  96. package/src/server/json-ld.tsx +51 -0
  97. package/src/server/layout.ts +1 -0
  98. package/src/server/lazy.ts +6 -7
  99. package/src/server/metadata.ts +44 -78
  100. package/src/server/mixer.ts +101 -119
  101. package/dist/_virtual/rolldown_runtime.js +0 -27
  102. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js +0 -76
  103. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js.map +0 -1
  104. package/dist/node_modules/deepmerge/dist/cjs.js +0 -94
  105. package/dist/node_modules/deepmerge/dist/cjs.js.map +0 -1
  106. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js +0 -105
  107. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js.map +0 -1
  108. package/dist/node_modules/dom-serializer/lib/esm/index.js +0 -141
  109. package/dist/node_modules/dom-serializer/lib/esm/index.js.map +0 -1
  110. package/dist/node_modules/domelementtype/lib/esm/index.js +0 -53
  111. package/dist/node_modules/domelementtype/lib/esm/index.js.map +0 -1
  112. package/dist/node_modules/domhandler/lib/esm/index.js +0 -131
  113. package/dist/node_modules/domhandler/lib/esm/index.js.map +0 -1
  114. package/dist/node_modules/domhandler/lib/esm/node.js +0 -308
  115. package/dist/node_modules/domhandler/lib/esm/node.js.map +0 -1
  116. package/dist/node_modules/entities/lib/esm/decode.js +0 -364
  117. package/dist/node_modules/entities/lib/esm/decode.js.map +0 -1
  118. package/dist/node_modules/entities/lib/esm/decode_codepoint.js +0 -59
  119. package/dist/node_modules/entities/lib/esm/decode_codepoint.js.map +0 -1
  120. package/dist/node_modules/entities/lib/esm/escape.js +0 -93
  121. package/dist/node_modules/entities/lib/esm/escape.js.map +0 -1
  122. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js +0 -6
  123. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js.map +0 -1
  124. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js +0 -6
  125. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +0 -1
  126. package/dist/node_modules/html-to-text/lib/html-to-text.js +0 -1828
  127. package/dist/node_modules/html-to-text/lib/html-to-text.js.map +0 -1
  128. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js +0 -435
  129. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js.map +0 -1
  130. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js +0 -739
  131. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js.map +0 -1
  132. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js +0 -20
  133. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js.map +0 -1
  134. package/dist/node_modules/leac/lib/leac.js +0 -101
  135. package/dist/node_modules/leac/lib/leac.js.map +0 -1
  136. package/dist/node_modules/parseley/lib/parseley.js +0 -314
  137. package/dist/node_modules/parseley/lib/parseley.js.map +0 -1
  138. package/dist/node_modules/peberminta/lib/core.js +0 -149
  139. package/dist/node_modules/peberminta/lib/core.js.map +0 -1
  140. package/dist/node_modules/selderee/lib/selderee.js +0 -325
  141. package/dist/node_modules/selderee/lib/selderee.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @websolutespa/bom-next
2
2
 
3
+ ## 4.0.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Proxy: route resolutions are cached per instance (`BOM_ROUTE_CACHE_TTL` seconds, default 30; misses and redirects at most 10) with concurrent lookups shared. Draft requests and server errors are never cached.
8
+ - Proxy: the resolver query values (`pathname`, `href`, `hrefBeforeRedirect`) are now encoded, and CMS redirects go to the target and status returned by the resolver instead of always to `/`.
9
+ - `routeAutoDetection`: a valid `detectedRoute` cookie (relative paths only) redirects straight away without route, market or GeoIP lookups; GeoIP calls have a 2 s timeout and are cached per IP for one hour.
10
+ - Per-request diagnostics (proxy, local API calls, context cache) are logged in development only.
11
+ - Server context: `getRoutes` and `getMixerContext` read routes from the Bowl route store instead of re-reading every page collection and media document. Routes no longer depend on `market`, `locale` or `user`, and unpublished pages and category routes are not part of the public routes anymore.
12
+ - Server context: locale, market, category and route reads run in parallel; the result is cached per market, locale and user for `MEMORY_CACHE_DURATION` seconds and cleared as soon as the route store changes (also from other instances through Redis). Draft contexts are never cached, only shared within a request. The `_mixer` and `_route` globals are replaced by `_bomMixerContext`.
13
+ - `decorateLazyComponents` runs the lazy decorators in parallel, keeping the component order.
14
+ - Metadata: new `getPageMetadata`, `buildPageMetadata` and `inheritParentMetadata` build plain-text title and description, canonical (keeping `pagination[page]`), `alternates.languages` with `x-default`, robots, keywords, Open Graph and Twitter on the server. `getMetadata` is now a wrapper of `getPageMetadata`, so its result contains all of them instead of title and description only; Open Graph and Twitter fields left empty by the page are inherited from the parent metadata.
15
+ - Metadata: `JsonLd` and `buildPageStructuredData` render JSON-LD in Server Components.
16
+ - `MetaDataProvider` no longer uses `next/compat/router` (pass the query string through the new `search` prop), takes `brand.url` from `layout.homeHref`, reads `meta.robots` or `meta.robot`, converts HTML to text without bullets, link URLs or uppercased headings, and uses uppercase hreflang countries (`it-IT`).
17
+ - `layout.homeHref` exposes the root page href for the current market and locale.
18
+ - `html-to-text` and `schema-dts` are declared as dependencies.
19
+ - Registry: aliases are read from `components.json` (or `UI_REGISTRY_COMPONENTS_JSON` and `UI_REGISTRY_SOURCE_ALIAS`) and rewritten to registry imports; only import and export specifiers are rewritten. Items that import app code the registry cannot ship are reported in `meta.unresolvedImports`, or hidden with `UI_REGISTRY_SKIP_UNRESOLVED`.
20
+ - `UserProvider` reads `/auth/me` once per browser session and accepts `initialUser`; `invalidateUser()` forces a new read.
21
+ - Updated dependencies
22
+ - @websolutespa/payload-plugin-bowl@4.0.0-next.2
23
+ - @websolutespa/bom-core@4.0.0-next.1
24
+
3
25
  ## 4.0.0-next.2
4
26
 
5
27
  ### Patch Changes
package/README.md CHANGED
@@ -9,31 +9,81 @@ Next module of the [BOM Repository](https://github.com/websolutespa/bom) by [web
9
9
  ---
10
10
 
11
11
  ##### *this library is for internal usage and not production ready*
12
-
13
- ## Page context
14
-
15
- ```ts
16
- import { createPageContext, getMetadata } from '@websolutespa/bom-next/server';
17
-
18
- export const generateMetadata = getMetadata('post_detail', config);
19
-
20
- const { page, layout, label, link } = await createPageContext(market, locale, 'post_detail', id, {
21
- config,
22
- depth: 2, // default DEFAULT_PAGE_DEPTH
23
- select: { title: true, abstract: true, media: true, components: true },
24
- populate: { media: { url: true, alt: true, width: true, height: true, type: true } },
25
- });
26
-
27
- const { layout } = await createLayoutContext(market, locale, { config }); // depth: DEFAULT_LAYOUT_DEPTH (1)
28
- ```
29
-
30
- | option | default | |
31
- |---|---|---|
32
- | `depth` | `2` | `0` ids only, `1` direct relations/uploads (including those inside blocks), `2` relations of relations |
33
- | `select` | – | Payload select; envelope fields (`id`, `slug`, `title`, `category`, `markets`, `meta`, `template`) are always read |
34
- | `populate` | – | per-collection select for populated documents |
35
- | `draft` | `'auto'` | `true` / `false`, or `'auto'` to read Next `draftMode()` |
36
- | `layout` | `{ depth: 1 }` | layout options, or `false` to skip the layout |
37
-
38
- Page and layout reads are memoized per request, so `getMetadata` and the page component share them when called with the same options.
39
- To bind `config` once: `export const { createPageContext, createLayoutContext, getMetadata } = createContextHelpers({ config, defaults: { depth: 2 } });`
12
+
13
+ ## Page context
14
+
15
+ ```ts
16
+ import { createPageContext, getMetadata } from '@websolutespa/bom-next/server';
17
+
18
+ export const generateMetadata = getMetadata('post_detail', config);
19
+
20
+ const { page, layout, label, link } = await createPageContext(market, locale, 'post_detail', id, {
21
+ config,
22
+ depth: 2, // default DEFAULT_PAGE_DEPTH
23
+ select: { title: true, abstract: true, media: true, components: true },
24
+ populate: { media: { url: true, alt: true, width: true, height: true, type: true } },
25
+ });
26
+
27
+ const { layout } = await createLayoutContext(market, locale, { config }); // depth: DEFAULT_LAYOUT_DEPTH (1)
28
+ ```
29
+
30
+ | option | default | |
31
+ |---|---|---|
32
+ | `depth` | `2` | `0` ids only, `1` direct relations/uploads (including those inside blocks), `2` relations of relations |
33
+ | `select` | – | Payload select; envelope fields (`id`, `slug`, `title`, `category`, `markets`, `meta`, `template`) are always read |
34
+ | `populate` | – | per-collection select for populated documents |
35
+ | `draft` | `'auto'` | `true` / `false`, or `'auto'` to read Next `draftMode()` |
36
+ | `layout` | `{ depth: 1 }` | layout options, or `false` to skip the layout |
37
+
38
+ Page and layout reads are memoized per request, so `getMetadata` and the page component share them when called with the same options.
39
+ To bind `config` once: `export const { createPageContext, createLayoutContext, getMetadata } = createContextHelpers({ config, defaults: { depth: 2 } });`
40
+
41
+ ## Metadata
42
+
43
+ `getPageMetadata` (and `getMetadata`, its `config`-first form) returns a `generateMetadata` function that renders on the server: plain-text title and description, canonical (keeping `?pagination[page]=N` after the first page), `alternates.languages` with one `locale-COUNTRY` entry per market country plus `x-default`, robots, keywords, Open Graph and Twitter.
44
+
45
+ ```ts
46
+ import { getPageMetadata, JsonLd, buildPageStructuredData } from '@websolutespa/bom-next/server';
47
+
48
+ export const generateMetadata = getPageMetadata('post_detail', {
49
+ config,
50
+ metadata: {
51
+ brand: { name: 'Example', logo: '/logo.png', twitterName: '@example' },
52
+ extend: (metadata, { page }) => ({ ...metadata, title: `${metadata.title} | Example` }),
53
+ },
54
+ });
55
+
56
+ // JSON-LD in the page component
57
+ <JsonLd data={buildPageStructuredData(page, layout, { brand: { name: 'Example' } })} />
58
+ ```
59
+
60
+ `buildPageMetadata(page, layout, options)` is the same builder for custom routes. URLs are resolved against `NEXT_PUBLIC_URL` unless `baseUrl` is passed. Robots come from `meta.robots`, or `meta.robot` (the `@payloadcms/plugin-seo` field).
61
+
62
+ The client `MetaDataProvider` only computes values for `useMetaData`; the `next/head` based `Meta`, `OpenGraph` and `StructuredData` components of the mixer packages render nothing in the App Router.
63
+
64
+ `layout.homeHref` is the root page href for the current market and locale; prefer it to `layout.topLevelHrefs.<slug>`, which is keyed by collection slug or template.
65
+
66
+ ## Routing proxy
67
+
68
+ `createRouteProxy` resolves each request through `/api/-route` and caches the result per instance: found routes for `BOM_ROUTE_CACHE_TTL` seconds (default `30`, `0` disables), misses and redirects for at most 10 seconds. Draft requests and server errors are never cached. CMS redirects send the browser to the target returned by the resolver.
69
+
70
+ `routeAutoDetection` redirects `/` straight from the `detectedRoute` cookie when present; otherwise it detects the market (GeoIP, 2 s timeout, cached per IP for one hour) and the locale.
71
+
72
+ The server context (`getContext`) reads routes from the Bowl route store and caches the rest per market, locale and user for `MEMORY_CACHE_DURATION` seconds (default 300). Any route store change, local or from another instance through Redis, clears it. Draft contexts are never cached.
73
+
74
+ ## Environment
75
+
76
+ Per-request diagnostics (proxy, local API calls, context cache) are logged in development only (`NODE_ENV` unset or `development`).
77
+
78
+ | Variable | Default | |
79
+ |---|---|---|
80
+ | `BOM_ROUTE_CACHE_TTL` | `30` | proxy route cache lifetime in seconds, `0` disables it |
81
+ | `MEMORY_CACHE_DURATION` | `300` | server context cache lifetime in seconds |
82
+ | `UI_REGISTRY_SOURCE_DIR` | `packages/ui/src` | registry source directory |
83
+ | `UI_REGISTRY_COMPONENTS_JSON` | nearest `components.json` | shadcn config whose aliases (e.g. `@/ui/lib/utils`) are mapped to registry imports |
84
+ | `UI_REGISTRY_SOURCE_ALIAS` | – | extra import prefix pointing at the registry source, e.g. `@/ui/` |
85
+ | `UI_REGISTRY_SKIP_UNRESOLVED` | – | `1` hides registry items that import app code; otherwise they are listed with `meta.unresolvedImports` |
86
+
87
+ ## User
88
+
89
+ `UserProvider` reads `/api/auth/me` once per browser session, shared by every mount. Pass `initialUser` (a user or `null`) when the server already knows it to skip the request; `setUser` and `invalidateUser()` keep the cached value current after login or logout.
@@ -1,7 +1,7 @@
1
- import * as react8 from "react";
1
+ import * as react0 from "react";
2
2
 
3
3
  //#region src/client/client.d.ts
4
- declare function Client(): react8.JSX.Element;
4
+ declare function Client(): react0.JSX.Element;
5
5
  //# sourceMappingURL=client.d.ts.map
6
6
 
7
7
  //#endregion
@@ -1,15 +1,15 @@
1
- import * as react4 from "react";
1
+ import * as react1 from "react";
2
2
 
3
3
  //#region src/client/extra.d.ts
4
4
  type IExtraContext = Record<string, any>;
5
- declare const ExtraContext: react4.Context<IExtraContext | undefined>;
5
+ declare const ExtraContext: react1.Context<IExtraContext | undefined>;
6
6
  declare function ExtraProvider({
7
7
  extra,
8
8
  children
9
9
  }: {
10
10
  extra?: Record<string, any>;
11
11
  children?: React.ReactNode;
12
- }): react4.JSX.Element;
12
+ }): react1.JSX.Element;
13
13
  //# sourceMappingURL=extra.d.ts.map
14
14
 
15
15
  //#endregion
@@ -1,13 +1,13 @@
1
- import * as react9 from "react";
1
+ import * as react3 from "react";
2
2
 
3
3
  //#region src/client/label.d.ts
4
4
  type ILabelContext = (key: string, params?: Record<string, any>) => string;
5
- declare const LabelContext: react9.Context<ILabelContext | undefined>;
5
+ declare const LabelContext: react3.Context<ILabelContext | undefined>;
6
6
  declare function LabelProvider({
7
7
  children
8
8
  }: {
9
9
  children?: React.ReactNode;
10
- }): react9.JSX.Element;
10
+ }): react3.JSX.Element;
11
11
  //# sourceMappingURL=label.d.ts.map
12
12
 
13
13
  //#endregion
@@ -1,16 +1,16 @@
1
1
  import { ILayout } from "@websolutespa/bom-core";
2
- import * as react13 from "react";
2
+ import * as react9 from "react";
3
3
 
4
4
  //#region src/client/layout.d.ts
5
5
  type ILayoutContext = ILayout;
6
- declare const LayoutContext: react13.Context<ILayoutContext | undefined>;
6
+ declare const LayoutContext: react9.Context<ILayoutContext | undefined>;
7
7
  declare function LayoutProvider({
8
8
  layout,
9
9
  children
10
10
  }: {
11
11
  layout: ILayout;
12
12
  children?: React.ReactNode;
13
- }): react13.JSX.Element;
13
+ }): react9.JSX.Element;
14
14
  //# sourceMappingURL=layout.d.ts.map
15
15
 
16
16
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","names":[],"sources":["../../src/client/layout.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,cAAA,GAAiB;cAEhB,eAAa,OAAA,CAAA,QAAA;iBAEV,cAAA;;;;EAJJ,MAAA,EAQF,OARE;EAEC,QAAA,CAAA,EAOA,KAAA,CAAM,SAP8D;CAAA,CAAA,EAQhF,OAAA,CAAA,GAAA,CAAA,OARgF"}
1
+ {"version":3,"file":"layout.d.ts","names":[],"sources":["../../src/client/layout.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,cAAA,GAAiB;cAEhB,eAAa,MAAA,CAAA,QAAA;iBAEV,cAAA;;;;EAJJ,MAAA,EAQF,OARE;EAEC,QAAA,CAAA,EAOA,KAAA,CAAM,SAP8D;CAAA,CAAA,EAQhF,MAAA,CAAA,GAAA,CAAA,OARgF"}
@@ -2,7 +2,7 @@ import { OpenGraphType } from "../lib/open-graph.js";
2
2
  import { StructuredDataType } from "../lib/structured-data.js";
3
3
  import { TwitterCardType } from "../lib/twitter-card.js";
4
4
  import { IMetaData } from "../lib/meta-data.js";
5
- import * as react6 from "react";
5
+ import * as react5 from "react";
6
6
  import { ReactNode } from "react";
7
7
 
8
8
  //#region src/client/metadata.d.ts
@@ -29,14 +29,24 @@ type IMetaDataOptions = {
29
29
  twitterCard?: TwitterCardType;
30
30
  };
31
31
  type IMetaDataContext = IMetaData;
32
- declare const MetaDataContext: react6.Context<IMetaData | undefined>;
32
+ declare const MetaDataContext: react5.Context<IMetaData | undefined>;
33
+ /**
34
+ * Computes page metadata for client components (`useMetaData`). It renders
35
+ * nothing into `<head>`: in the App Router, export `generateMetadata` built
36
+ * with `getPageMetadata` from `@websolutespa/bom-next/server` instead.
37
+ *
38
+ * `search` is the current query string (e.g. `?pagination[page]=2`); pages
39
+ * after the first keep their pagination in the canonical URL.
40
+ */
33
41
  declare function MetaDataProvider({
34
42
  metaData,
43
+ search,
35
44
  children
36
45
  }: {
37
46
  metaData: IMetaDataOptions;
47
+ search?: string;
38
48
  children?: ReactNode;
39
- }): react6.JSX.Element;
49
+ }): react5.JSX.Element;
40
50
  //# sourceMappingURL=metadata.d.ts.map
41
51
  //#endregion
42
52
  export { IMetaDataContext, IMetaDataOptions, MetaDataContext, MetaDataProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","names":[],"sources":["../../src/client/metadata.tsx"],"sourcesContent":[],"mappings":";;;;;;;;KAeY,gBAAA;;;IAAA,IAAA,EAAA,MAAA;IAAgB,YAAA,CAAA,EAAA,MAAA;IAgBf,OAAA,CAAA,EAAA,MAAA;IAEM,GAAA,CAAA,EAAA,MAAA;IACL,KAAA,CAAA,EAAA,MAAA;IACE,SAAA,CAAA,EAAA,MAAA;IAAe,OAAA,CAAA,EAAA,MAAA;IAGnB,OAAA,CAAA,EAAA,MAAgB;IAEf,IAAA,CAAA,EAAA,MAAA;IAAwE,YAAA,CAAA,EAAA,MAAA;IAAzD,WAAA,CAAA,EAAA,MAAA;IAAA,WAAA,CAAA,EAAA,MAAA;IAAA,WAAA,CAAA,EAAA,MAAA;IAEZ,MAAA,CAAA,EAXH,MAWmB,CAAA,MAAA,EAAA,MAAA,CAAA;EAAA,CAAA;EAAA,cAC9B,CAAA,EAViB,kBAUjB;EAAQ,SACR,CAAA,EAVY,aAUZ;EAAQ,WAEE,CAAA,EAXI,eAWJ;CAAgB;AAE3B,KAVW,gBAAA,GAAmB,SAU9B;AAAA,cARY,eAQZ,EAR2B,MAAA,CAAA,OAQ3B,CAR2B,SAQ3B,GAAA,SAAA,CAAA;iBANe,gBAAA;;;;YAIJ;aACC;IACZ,MAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"metadata.d.ts","names":[],"sources":["../../src/client/metadata.tsx"],"sourcesContent":[],"mappings":";;;;;;;;KAcY,gBAAA;;;IAAA,IAAA,EAAA,MAAA;IAAgB,YAAA,CAAA,EAAA,MAAA;IAgBf,OAAA,CAAA,EAAA,MAAA;IAEM,GAAA,CAAA,EAAA,MAAA;IACL,KAAA,CAAA,EAAA,MAAA;IACE,SAAA,CAAA,EAAA,MAAA;IAAe,OAAA,CAAA,EAAA,MAAA;IAGnB,OAAA,CAAA,EAAA,MAAgB;IAEf,IAAA,CAAA,EAAA,MAAA;IAAwE,YAAA,CAAA,EAAA,MAAA;IAAzD,WAAA,CAAA,EAAA,MAAA;IAAA,WAAA,CAAA,EAAA,MAAA;IAAA,WAAA,CAAA,EAAA,MAAA;IAUZ,MAAA,CAAA,EAnBH,MAmBmB,CAAA,MAAA,EAAA,MAAA,CAAA;EAAA,CAAA;EAAA,cAC9B,CAAA,EAlBiB,kBAkBjB;EAAQ,SACR,CAAA,EAlBY,aAkBZ;EAAM,WACN,CAAA,EAlBc,eAkBd;CAAQ;AAIG,KAnBD,gBAAA,GAAmB,SAmBlB;AACZ,cAlBY,eAkBZ,EAlB2B,MAAA,CAAA,OAkB3B,CAlB2B,SAkB3B,GAAA,SAAA,CAAA;AAAA;;;;;;;;iBARe,gBAAA;;;;;YAKJ;;aAEC;IACZ,MAAA,CAAA,GAAA,CAAA"}
@@ -4,72 +4,53 @@
4
4
  import { getPublicUrl, resolveHref } from "../lib/utils.js";
5
5
  import { useLayout } from "./useLayout.js";
6
6
  import { usePage } from "./usePage.js";
7
- import { convert } from "../node_modules/html-to-text/lib/html-to-text.js";
8
- import { defaultLocale, defaultMarket } from "@websolutespa/bom-core";
7
+ import { getPageAlternates, getPageXDefault, getPaginationQuery, toPlainText } from "../lib/page-metadata.js";
8
+ import { getMetaRobots } from "@websolutespa/bom-core";
9
9
  import { createContext, useMemo } from "react";
10
10
  import { jsx } from "react/jsx-runtime";
11
- import { useRouter } from "next/compat/router";
12
11
 
13
12
  //#region src/client/metadata.tsx
14
13
  const MetaDataContext = createContext(void 0);
15
- function MetaDataProvider({ metaData, children }) {
16
- const router = useRouter();
14
+ /**
15
+
16
+ * Computes page metadata for client components (`useMetaData`). It renders
17
+
18
+ * nothing into `<head>`: in the App Router, export `generateMetadata` built
19
+
20
+ * with `getPageMetadata` from `@websolutespa/bom-next/server` instead.
21
+
22
+ *
23
+
24
+ * `search` is the current query string (e.g. `?pagination[page]=2`); pages
25
+
26
+ * after the first keep their pagination in the canonical URL.
27
+
28
+ */
29
+ function MetaDataProvider({ metaData, search, children }) {
17
30
  const layout = useLayout();
18
31
  const page = usePage();
32
+ const homeHref = layout.homeHref ?? layout.tree?.href;
19
33
  const brand = {
20
34
  ...metaData.brand,
21
35
  logo: resolveHref(metaData.brand.logo),
22
- url: getPublicUrl(),
36
+ url: metaData.brand.url || (homeHref ? resolveHref(homeHref) : getPublicUrl()),
23
37
  businessName: metaData.brand.businessName || metaData.brand.name,
24
38
  appName: metaData.brand.appName || metaData.brand.name
25
39
  };
26
- const title = convert(page.meta?.title || page.title || "");
27
- const description = convert(page.meta?.description || page.abstract || "");
40
+ const title = toPlainText(page.meta?.title || page.title || "");
41
+ const description = toPlainText(page.meta?.description || page.abstract || "");
28
42
  const media = page.meta?.image || page.media;
29
43
  const image = media ? resolveHref(media.src || media.url) : brand.logo;
30
- let canonical = resolveHref(page.href);
31
- const asPath = router?.asPath || "";
32
- const queryIndex = asPath.indexOf("?");
33
- const query = queryIndex !== -1 ? asPath.substring(queryIndex) : "";
34
- if (query.match(/^\?pagination\[page\]=(\d+)$/) && query !== "?pagination[page]=1") canonical = `${canonical}${query}`;
35
- const url = `${canonical}${query}`;
36
- const alternates = useMemo(() => {
37
- const alternates$1 = [];
38
- (page.alternates || []).forEach((alternate) => {
39
- const market = layout.markets.find((x) => x.id === alternate.market);
40
- if (market) if (market.countries && market.countries.length > 0) market.countries.forEach((country) => {
41
- const alpha2Code = typeof country === "string" ? country : country.alpha2Code;
42
- alternates$1.push({
43
- id: `${alternate.market}-${alternate.locale}-${alpha2Code}`,
44
- href: resolveHref(alternate.id),
45
- hrefLang: `${alternate.locale}-${alpha2Code}`
46
- });
47
- });
48
- else alternates$1.push({
49
- id: `${alternate.market}-${alternate.locale}`,
50
- href: resolveHref(alternate.id),
51
- hrefLang: alternate.locale
52
- });
53
- });
54
- return alternates$1;
55
- }, [layout, page]);
56
- const xDefault = useMemo(() => {
57
- const xDefaultMarket = layout.markets.find((x) => x.isDefault)?.id || defaultMarket;
58
- const xDefaultLocale = layout.locales.find((x) => x.isDefault)?.id || defaultLocale;
59
- const alternate = page.alternates.find((x) => x.market === xDefaultMarket && x.locale === xDefaultLocale);
60
- if (alternate) return {
61
- id: `${alternate.market}-${alternate.locale}`,
62
- href: resolveHref(alternate.id),
63
- hrefLang: alternate.locale
64
- };
65
- return void 0;
66
- }, [layout, page]);
44
+ const canonical = `${resolveHref(page.href)}${getPaginationQuery(new URLSearchParams(search || ""))}`;
45
+ const url = canonical;
46
+ const alternates = useMemo(() => getPageAlternates(page, layout, getPublicUrl()), [layout, page]);
47
+ const xDefault = useMemo(() => getPageXDefault(page, layout, getPublicUrl()), [layout, page]);
67
48
  const meta = {
68
49
  title,
69
50
  description,
70
51
  image,
71
52
  keywords: page.meta?.keywords,
72
- robots: page.meta?.robots,
53
+ robots: getMetaRobots(page.meta),
73
54
  slug: page.href,
74
55
  url,
75
56
  canonical,
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","names":["brand: IBrand","htmlToText","alternates: IAlternate[]","alternate: IRoute","country: any","alternates","meta: IMeta","contactPoint: ContactPoint","postalAddress: PostalAddress","organization: Organization","structuredData: StructuredDataType","openGraph: OpenGraphType","twitterCard: TwitterCardType | undefined","value: IMetaData"],"sources":["../../src/client/metadata.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { defaultLocale, defaultMarket, IMedia, IRoute } from '@websolutespa/bom-core';\r\nimport { convert as htmlToText } from 'html-to-text';\r\nimport { useRouter } from 'next/compat/router';\r\nimport { createContext, ReactNode, useMemo } from 'react';\r\nimport { ContactPoint, Organization, PostalAddress } from 'schema-dts';\r\nimport { IAlternate, IBrand, IMeta, IMetaData } from '../lib/meta-data';\r\nimport { OpenGraphType } from '../lib/open-graph';\r\nimport { StructuredDataType } from '../lib/structured-data';\r\nimport { TwitterCardType } from '../lib/twitter-card';\r\nimport { getPublicUrl, resolveHref } from '../lib/utils';\r\nimport { useLayout } from './useLayout';\r\nimport { usePage } from './usePage';\r\n\r\nexport type IMetaDataOptions = {\r\n brand: {\r\n name: string;\r\n logo: string;\r\n businessName?: string;\r\n appName?: string;\r\n url?: string;\r\n email?: string;\r\n telephone?: string;\r\n zipCode?: string;\r\n address?: string;\r\n city?: string;\r\n provinceCode?: string;\r\n countryName?: string;\r\n countryCode?: string;\r\n twitterName?: string;\r\n social?: Record<string, string>;\r\n },\r\n structuredData?: StructuredDataType;\r\n openGraph?: OpenGraphType;\r\n twitterCard?: TwitterCardType;\r\n};\r\n\r\nexport type IMetaDataContext = IMetaData;\r\n\r\nexport const MetaDataContext = createContext<IMetaDataContext | undefined>(undefined);\r\n\r\nexport function MetaDataProvider({\r\n metaData,\r\n children,\r\n}: {\r\n metaData: IMetaDataOptions,\r\n children?: ReactNode,\r\n}) {\r\n const router = useRouter();\r\n const layout = useLayout();\r\n const page = usePage();\r\n const brand: IBrand = {\r\n ...metaData.brand,\r\n logo: resolveHref(metaData.brand.logo),\r\n url: getPublicUrl(), // layout.topLevelHrefs.homepage,\r\n businessName: metaData.brand.businessName || metaData.brand.name,\r\n appName: metaData.brand.appName || metaData.brand.name,\r\n };\r\n const title = htmlToText(page.meta?.title || page.title || '');\r\n const description = htmlToText(page.meta?.description || page.abstract || '');\r\n const media = ((page.meta as { image: IMedia } | undefined)?.image || page.media);\r\n const image = media ? resolveHref(media.src || media.url) : brand.logo;\r\n let canonical = resolveHref(page.href);\r\n const asPath = router?.asPath || '';\r\n const queryIndex = asPath.indexOf('?');\r\n const query = queryIndex !== -1 ? asPath.substring(queryIndex) : '';\r\n if (query.match(/^\\?pagination\\[page\\]=(\\d+)$/) && query !== '?pagination[page]=1') {\r\n canonical = `${canonical}${query}`;\r\n // title = `${title} - ${query.replace('?pagination[page]=','')}`;\r\n }\r\n const url = `${canonical}${query}`;\r\n const alternates = useMemo(() => {\r\n const alternates: IAlternate[] = [];\r\n (page.alternates || []).forEach((alternate: IRoute) => {\r\n const market = layout.markets.find(x => x.id === alternate.market);\r\n if (market) {\r\n if (market.countries && market.countries.length > 0) {\r\n market.countries.forEach((country: any) => {\r\n // country: string | { alpha2Code: string };\r\n const alpha2Code = typeof country === 'string' ? country : country.alpha2Code;\r\n alternates.push({\r\n id: `${alternate.market}-${alternate.locale}-${alpha2Code}`,\r\n href: resolveHref(alternate.id),\r\n hrefLang: `${alternate.locale}-${alpha2Code}`,\r\n });\r\n });\r\n } else {\r\n alternates.push({\r\n id: `${alternate.market}-${alternate.locale}`,\r\n href: resolveHref(alternate.id),\r\n hrefLang: alternate.locale,\r\n });\r\n }\r\n }\r\n });\r\n return alternates;\r\n }, [layout, page]);\r\n const xDefault = useMemo(() => {\r\n const xDefaultMarket = layout.markets.find(x => x.isDefault)?.id || defaultMarket;\r\n const xDefaultLocale = layout.locales.find(x => x.isDefault)?.id || defaultLocale;\r\n const alternate = page.alternates.find(x => x.market === xDefaultMarket && x.locale === xDefaultLocale);\r\n if (alternate) {\r\n return {\r\n id: `${alternate.market}-${alternate.locale}`,\r\n href: resolveHref(alternate.id),\r\n hrefLang: alternate.locale,\r\n };\r\n }\r\n return undefined;\r\n }, [layout, page]);\r\n const meta: IMeta = {\r\n title: title,\r\n description: description,\r\n image: image,\r\n keywords: page.meta?.keywords,\r\n robots: page.meta?.robots,\r\n slug: page.href,\r\n url,\r\n canonical,\r\n alternates,\r\n xDefault,\r\n };\r\n const contactPoint: ContactPoint = {\r\n '@type': 'ContactPoint',\r\n telephone: brand.telephone,\r\n email: brand.email,\r\n contactType: 'customer service',\r\n areaServed: layout.locales.map(x => x.id),\r\n availableLanguage: layout.locales.map(x => x.id),\r\n };\r\n const postalAddress: PostalAddress = {\r\n '@type': 'PostalAddress',\r\n streetAddress: brand.address,\r\n addressLocality: brand.city,\r\n postalCode: brand.zipCode,\r\n addressRegion: brand.provinceCode,\r\n addressCountry: brand.countryCode,\r\n };\r\n const organization: Organization = {\r\n '@type': 'Organization',\r\n name: brand.businessName,\r\n logo: {\r\n '@type': 'ImageObject',\r\n url: brand.logo,\r\n },\r\n url: brand.url,\r\n /*\r\n description,\r\n founder,\r\n foundingDate,\r\n numberOfEmployees,\r\n */\r\n /*\r\n foundingDate: '2020-01-01',\r\n numberOfEmployees: {\r\n '@type': 'QuantitativeValue',\r\n value: 150,\r\n },\r\n */\r\n };\r\n const hasContact = Boolean(brand.email || brand.telephone);\r\n if (hasContact) {\r\n organization.contactPoint = contactPoint;\r\n }\r\n const hasAddress = Boolean(brand.address || brand.city || brand.zipCode || brand.provinceCode || brand.countryCode);\r\n if (hasAddress) {\r\n organization.address = postalAddress;\r\n }\r\n if (brand.social) {\r\n organization.sameAs = Object.values(brand.social);\r\n }\r\n const structuredData: StructuredDataType = metaData.structuredData || {\r\n '@type': 'WebPage',\r\n name: title,\r\n url: url,\r\n description: description,\r\n publisher: organization,\r\n };\r\n const openGraph: OpenGraphType = metaData.openGraph || {\r\n type: 'website',\r\n title: title,\r\n description: description,\r\n url: url,\r\n siteName: brand.name,\r\n image: image,\r\n locale: layout.locale,\r\n };\r\n const twitterCard: TwitterCardType | undefined = metaData.twitterCard || (\r\n brand.twitterName ? {\r\n card: 'summary_large_image',\r\n title: title,\r\n description: description,\r\n image: image,\r\n imageAlt: brand.businessName,\r\n site: brand.twitterName,\r\n creator: brand.twitterName,\r\n } : undefined\r\n );\r\n const value: IMetaData = {\r\n layout,\r\n page,\r\n brand,\r\n contactPoint,\r\n meta,\r\n openGraph,\r\n organization,\r\n postalAddress,\r\n structuredData,\r\n twitterCard,\r\n };\r\n return (\r\n <MetaDataContext.Provider value={value}>\r\n {children}\r\n </MetaDataContext.Provider>\r\n );\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","names":["brand: IBrand","meta: IMeta","contactPoint: ContactPoint","postalAddress: PostalAddress","organization: Organization","structuredData: StructuredDataType","openGraph: OpenGraphType","twitterCard: TwitterCardType | undefined","value: IMetaData"],"sources":["../../src/client/metadata.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { getMetaRobots, IMedia } from '@websolutespa/bom-core';\r\nimport { createContext, ReactNode, useMemo } from 'react';\r\nimport { ContactPoint, Organization, PostalAddress } from 'schema-dts';\r\nimport { IBrand, IMeta, IMetaData } from '../lib/meta-data';\r\nimport { OpenGraphType } from '../lib/open-graph';\r\nimport { StructuredDataType } from '../lib/structured-data';\r\nimport { TwitterCardType } from '../lib/twitter-card';\r\nimport { getPageAlternates, getPageXDefault, getPaginationQuery, toPlainText } from '../lib/page-metadata';\r\nimport { getPublicUrl, resolveHref } from '../lib/utils';\r\nimport { useLayout } from './useLayout';\r\nimport { usePage } from './usePage';\r\n\r\nexport type IMetaDataOptions = {\r\n brand: {\r\n name: string;\r\n logo: string;\r\n businessName?: string;\r\n appName?: string;\r\n url?: string;\r\n email?: string;\r\n telephone?: string;\r\n zipCode?: string;\r\n address?: string;\r\n city?: string;\r\n provinceCode?: string;\r\n countryName?: string;\r\n countryCode?: string;\r\n twitterName?: string;\r\n social?: Record<string, string>;\r\n },\r\n structuredData?: StructuredDataType;\r\n openGraph?: OpenGraphType;\r\n twitterCard?: TwitterCardType;\r\n};\r\n\r\nexport type IMetaDataContext = IMetaData;\r\n\r\nexport const MetaDataContext = createContext<IMetaDataContext | undefined>(undefined);\r\n\r\n/**\r\n * Computes page metadata for client components (`useMetaData`). It renders\r\n * nothing into `<head>`: in the App Router, export `generateMetadata` built\r\n * with `getPageMetadata` from `@websolutespa/bom-next/server` instead.\r\n *\r\n * `search` is the current query string (e.g. `?pagination[page]=2`); pages\r\n * after the first keep their pagination in the canonical URL.\r\n */\r\nexport function MetaDataProvider({\r\n metaData,\r\n search,\r\n children,\r\n}: {\r\n metaData: IMetaDataOptions,\r\n search?: string,\r\n children?: ReactNode,\r\n}) {\r\n const layout = useLayout();\r\n const page = usePage();\r\n const homeHref = layout.homeHref ?? layout.tree?.href;\r\n const brand: IBrand = {\r\n ...metaData.brand,\r\n logo: resolveHref(metaData.brand.logo),\r\n url: metaData.brand.url || (homeHref ? resolveHref(homeHref) : getPublicUrl()),\r\n businessName: metaData.brand.businessName || metaData.brand.name,\r\n appName: metaData.brand.appName || metaData.brand.name,\r\n };\r\n const title = toPlainText(page.meta?.title || page.title || '');\r\n const description = toPlainText(page.meta?.description || page.abstract || '');\r\n const media = ((page.meta as { image: IMedia } | undefined)?.image || page.media);\r\n const image = media ? resolveHref(media.src || media.url) : brand.logo;\r\n const canonical = `${resolveHref(page.href)}${getPaginationQuery(new URLSearchParams(search || ''))}`;\r\n const url = canonical;\r\n const alternates = useMemo(() => getPageAlternates(page, layout, getPublicUrl()), [layout, page]);\r\n const xDefault = useMemo(() => getPageXDefault(page, layout, getPublicUrl()), [layout, page]);\r\n const meta: IMeta = {\r\n title: title,\r\n description: description,\r\n image: image,\r\n keywords: page.meta?.keywords,\r\n robots: getMetaRobots(page.meta),\r\n slug: page.href,\r\n url,\r\n canonical,\r\n alternates,\r\n xDefault,\r\n };\r\n const contactPoint: ContactPoint = {\r\n '@type': 'ContactPoint',\r\n telephone: brand.telephone,\r\n email: brand.email,\r\n contactType: 'customer service',\r\n areaServed: layout.locales.map(x => x.id),\r\n availableLanguage: layout.locales.map(x => x.id),\r\n };\r\n const postalAddress: PostalAddress = {\r\n '@type': 'PostalAddress',\r\n streetAddress: brand.address,\r\n addressLocality: brand.city,\r\n postalCode: brand.zipCode,\r\n addressRegion: brand.provinceCode,\r\n addressCountry: brand.countryCode,\r\n };\r\n const organization: Organization = {\r\n '@type': 'Organization',\r\n name: brand.businessName,\r\n logo: {\r\n '@type': 'ImageObject',\r\n url: brand.logo,\r\n },\r\n url: brand.url,\r\n /*\r\n description,\r\n founder,\r\n foundingDate,\r\n numberOfEmployees,\r\n */\r\n /*\r\n foundingDate: '2020-01-01',\r\n numberOfEmployees: {\r\n '@type': 'QuantitativeValue',\r\n value: 150,\r\n },\r\n */\r\n };\r\n const hasContact = Boolean(brand.email || brand.telephone);\r\n if (hasContact) {\r\n organization.contactPoint = contactPoint;\r\n }\r\n const hasAddress = Boolean(brand.address || brand.city || brand.zipCode || brand.provinceCode || brand.countryCode);\r\n if (hasAddress) {\r\n organization.address = postalAddress;\r\n }\r\n if (brand.social) {\r\n organization.sameAs = Object.values(brand.social);\r\n }\r\n const structuredData: StructuredDataType = metaData.structuredData || {\r\n '@type': 'WebPage',\r\n name: title,\r\n url: url,\r\n description: description,\r\n publisher: organization,\r\n };\r\n const openGraph: OpenGraphType = metaData.openGraph || {\r\n type: 'website',\r\n title: title,\r\n description: description,\r\n url: url,\r\n siteName: brand.name,\r\n image: image,\r\n locale: layout.locale,\r\n };\r\n const twitterCard: TwitterCardType | undefined = metaData.twitterCard || (\r\n brand.twitterName ? {\r\n card: 'summary_large_image',\r\n title: title,\r\n description: description,\r\n image: image,\r\n imageAlt: brand.businessName,\r\n site: brand.twitterName,\r\n creator: brand.twitterName,\r\n } : undefined\r\n );\r\n const value: IMetaData = {\r\n layout,\r\n page,\r\n brand,\r\n contactPoint,\r\n meta,\r\n openGraph,\r\n organization,\r\n postalAddress,\r\n structuredData,\r\n twitterCard,\r\n };\r\n return (\r\n <MetaDataContext.Provider value={value}>\r\n {children}\r\n </MetaDataContext.Provider>\r\n );\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAuCA,MAAa,kBAAkB,cAA4C,OAAU;;;;;;;;;;;;;;;;AAUrF,SAAgB,iBAAiB,EAC/B,UACA,QACA,UAKD,EAAE;CACD,MAAM,SAAS,WAAW;CAC1B,MAAM,OAAO,SAAS;CACtB,MAAM,WAAW,OAAO,YAAY,OAAO,MAAM;CACjD,MAAMA,QAAgB;EACpB,GAAG,SAAS;EACZ,MAAM,YAAY,SAAS,MAAM,KAAK;EACtC,KAAK,SAAS,MAAM,QAAQ,WAAW,YAAY,SAAS,GAAG,cAAc;EAC7E,cAAc,SAAS,MAAM,gBAAgB,SAAS,MAAM;EAC5D,SAAS,SAAS,MAAM,WAAW,SAAS,MAAM;CACnD;CACD,MAAM,QAAQ,YAAY,KAAK,MAAM,SAAS,KAAK,SAAS,GAAG;CAC/D,MAAM,cAAc,YAAY,KAAK,MAAM,eAAe,KAAK,YAAY,GAAG;CAC9E,MAAM,QAAU,KAAK,MAAwC,SAAS,KAAK;CAC3E,MAAM,QAAQ,QAAQ,YAAY,MAAM,OAAO,MAAM,IAAI,GAAG,MAAM;CAClE,MAAM,YAAY,GAAG,YAAY,KAAK,KAAK,GAAG,mBAAmB,IAAI,gBAAgB,UAAU,IAAI,EAAE;CACrG,MAAM,MAAM;CACZ,MAAM,aAAa,QAAQ,MAAM,kBAAkB,MAAM,QAAQ,cAAc,CAAC,EAAE,CAAC,QAAQ,IAAK,EAAC;CACjG,MAAM,WAAW,QAAQ,MAAM,gBAAgB,MAAM,QAAQ,cAAc,CAAC,EAAE,CAAC,QAAQ,IAAK,EAAC;CAC7F,MAAMC,OAAc;EACX;EACM;EACN;EACP,UAAU,KAAK,MAAM;EACrB,QAAQ,cAAc,KAAK,KAAK;EAChC,MAAM,KAAK;EACX;EACA;EACA;EACA;CACD;CACD,MAAMC,eAA6B;EACjC,SAAS;EACT,WAAW,MAAM;EACjB,OAAO,MAAM;EACb,aAAa;EACb,YAAY,OAAO,QAAQ,IAAI,OAAK,EAAE,GAAG;EACzC,mBAAmB,OAAO,QAAQ,IAAI,OAAK,EAAE,GAAG;CACjD;CACD,MAAMC,gBAA+B;EACnC,SAAS;EACT,eAAe,MAAM;EACrB,iBAAiB,MAAM;EACvB,YAAY,MAAM;EAClB,eAAe,MAAM;EACrB,gBAAgB,MAAM;CACvB;CACD,MAAMC,eAA6B;EACjC,SAAS;EACT,MAAM,MAAM;EACZ,MAAM;GACJ,SAAS;GACT,KAAK,MAAM;EACZ;EACD,KAAK,MAAM;CAcZ;CACD,MAAM,aAAa,QAAQ,MAAM,SAAS,MAAM,UAAU;AAC1D,KAAI,YACF,aAAa,eAAe;CAE9B,MAAM,aAAa,QAAQ,MAAM,WAAW,MAAM,QAAQ,MAAM,WAAW,MAAM,gBAAgB,MAAM,YAAY;AACnH,KAAI,YACF,aAAa,UAAU;AAEzB,KAAI,MAAM,QACR,aAAa,SAAS,OAAO,OAAO,MAAM,OAAO;CAEnD,MAAMC,iBAAqC,SAAS,kBAAkB;EACpE,SAAS;EACT,MAAM;EACD;EACQ;EACb,WAAW;CACZ;CACD,MAAMC,YAA2B,SAAS,aAAa;EACrD,MAAM;EACC;EACM;EACR;EACL,UAAU,MAAM;EACT;EACP,QAAQ,OAAO;CAChB;CACD,MAAMC,cAA2C,SAAS,gBACxD,MAAM,cAAc;EAClB,MAAM;EACC;EACM;EACN;EACP,UAAU,MAAM;EAChB,MAAM,MAAM;EACZ,SAAS,MAAM;CAChB,IAAG;CAEN,MAAMC,QAAmB;EACvB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACD;AACD,4BACG,gBAAgB;EAAgB;EAC9B;GACwB;AAE9B"}
@@ -1,10 +1,10 @@
1
1
  import * as _websolutespa_bom_core0 from "@websolutespa/bom-core";
2
2
  import { ILocalized, IPage } from "@websolutespa/bom-core";
3
- import * as react11 from "react";
3
+ import * as react7 from "react";
4
4
 
5
5
  //#region src/client/page.d.ts
6
6
  type IPageContext = ILocalized<IPage>;
7
- declare const PageContext: react11.Context<{
7
+ declare const PageContext: react7.Context<{
8
8
  [x: string]: unknown;
9
9
  id: _websolutespa_bom_core0.IEquatable;
10
10
  schema: string;
@@ -324,6 +324,7 @@ declare const PageContext: react11.Context<{
324
324
  description?: string | undefined;
325
325
  keywords?: string | undefined;
326
326
  robots?: string | undefined;
327
+ robot?: string | undefined;
327
328
  image?: {
328
329
  [x: string]: unknown;
329
330
  id?: string | undefined;
@@ -397,7 +398,7 @@ declare function PageProvider({
397
398
  }: {
398
399
  page: ILocalized<IPage>;
399
400
  children?: React.ReactNode;
400
- }): react11.JSX.Element;
401
+ }): react7.JSX.Element;
401
402
  //# sourceMappingURL=page.d.ts.map
402
403
  //#endregion
403
404
  export { IPageContext, PageContext, PageProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","names":[],"sources":["../../src/client/page.tsx"],"sourcesContent":[],"mappings":";;;;;KAKY,YAAA,GAAe,WAAW;cAEzB,qBAAW;;MAAqD,uBAAA,CAAA;EAFjE,MAAA,EAAA,MAAA;EAAY,QAAA,EAAA;IAAc,UAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;IAAX,CAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAAU,QAAA,EAAA,GAAA,GAAA,MAAA;IAExB,MAAA,EAAA,CAAA,GAAgE,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,GAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAArD,GAAA,MAAA;IAAA,GAAA,EAAA,GAAA,GAAA,MAAA;IAER,QAAA,EAAA,CAAY,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAC1B,OAAA,EAAA,GAAA,GAAA,MAAA;IACA,SAAA,EAAA,GAAA,GAAA,MAAA;IAEiB,QAAA,EAAA,GAAA,GAAA,MAAA;IAAX,SAAA,EAAA,GAAA,GAAA,MAAA;IACK,QAAM,EAAA,CAAA,MAAA,QAAA,EAAA,uBAAA,gBAAA,CAAA;IAClB,UAAA,EAAA;MAAA,CAAA,WAAA,EAAA,MAAA,SAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBANe,YAAA;;;;QAIR,WAAW;aACN,KAAA,CAAM;IAClB,OAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"page.d.ts","names":[],"sources":["../../src/client/page.tsx"],"sourcesContent":[],"mappings":";;;;;KAKY,YAAA,GAAe,WAAW;cAEzB,oBAAW;;MAAqD,uBAAA,CAAA;EAFjE,MAAA,EAAA,MAAA;EAAY,QAAA,EAAA;IAAc,UAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;IAAX,CAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAAU,QAAA,EAAA,GAAA,GAAA,MAAA;IAExB,MAAA,EAAA,CAAA,GAAgE,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,GAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAArD,GAAA,MAAA;IAAA,GAAA,EAAA,GAAA,GAAA,MAAA;IAER,QAAA,EAAA,CAAY,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAC1B,OAAA,EAAA,GAAA,GAAA,MAAA;IACA,SAAA,EAAA,GAAA,GAAA,MAAA;IAEiB,QAAA,EAAA,GAAA,GAAA,MAAA;IAAX,SAAA,EAAA,GAAA,GAAA,MAAA;IACK,QAAM,EAAA,CAAA,MAAA,QAAA,EAAA,uBAAA,gBAAA,CAAA;IAClB,UAAA,EAAA;MAAA,CAAA,WAAA,EAAA,MAAA,SAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBANe,YAAA;;;;QAIR,WAAW;aACN,KAAA,CAAM;IAClB,MAAA,CAAA,GAAA,CAAA"}
@@ -1,13 +1,13 @@
1
1
  import { ApiRequestOptions } from "../lib/http.js";
2
- import * as react17 from "react";
2
+ import * as react11 from "react";
3
3
 
4
4
  //#region src/client/useApi.d.ts
5
- declare function useApiFetch<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
6
- declare function useApiGet<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
7
- declare function useApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
8
- declare function useApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
9
- declare function useApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
10
- declare function useApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
5
+ declare function useApiFetch<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
6
+ declare function useApiGet<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
7
+ declare function useApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
8
+ declare function useApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
9
+ declare function useApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
10
+ declare function useApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react11.Dispatch<any>];
11
11
  type Api = {
12
12
  get: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
13
13
  post: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
@@ -1,6 +1,6 @@
1
1
  import { ApiRequestOptions } from "../lib/http.js";
2
2
  import { QueryParams } from "@websolutespa/bom-core";
3
- import * as react0 from "react";
3
+ import * as react17 from "react";
4
4
 
5
5
  //#region src/client/useCollectionApi.d.ts
6
6
  type CollectionApi = {
@@ -11,11 +11,11 @@ type CollectionApi = {
11
11
  delete: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
12
12
  };
13
13
  declare function useCollectionApi(): CollectionApi;
14
- declare function useCollectionApiGet<T = unknown>(pathname: string, params?: QueryParams, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
15
- declare function useCollectionApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
16
- declare function useCollectionApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
17
- declare function useCollectionApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
18
- declare function useCollectionApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
14
+ declare function useCollectionApiGet<T = unknown>(pathname: string, params?: QueryParams, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
15
+ declare function useCollectionApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
16
+ declare function useCollectionApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
17
+ declare function useCollectionApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
18
+ declare function useCollectionApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
19
19
  //#endregion
20
20
  export { useCollectionApi, useCollectionApiDelete, useCollectionApiGet, useCollectionApiPatch, useCollectionApiPost, useCollectionApiPut };
21
21
  //# sourceMappingURL=useCollectionApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCollectionApi.d.ts","names":[],"sources":["../../src/client/useCollectionApi.ts"],"sourcesContent":[],"mappings":";;;;;KAMK,aAAA;gDAC2C,uBAAuB,sBAAsB,QAAQ;qEAChC,sBAAsB,QAAQ;EAF9F,GAAA,EAAA,CAAA,IAAA,OAAa,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAGkD,iBAHlD,EAAA,GAGwE,OAHxE,CAGgF,CAHhF,CAAA;EAAA,KAAA,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAIoD,iBAJpD,EAAA,GAI0E,OAJ1E,CAIkF,CAJlF,CAAA;EAAA,MAC8B,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAII,iBAJJ,EAAA,GAI0B,OAJ1B,CAIkC,CAJlC,CAAA;CAAW;AAA0C,iBAOrF,gBAAA,CAAA,CAPqF,EAOjE,aAPiE;AAAR,iBAuC7E,mBAvC6E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAuCjB,WAvCiB,EAAA,OAAA,CAAA,EAuCK,iBAvCL,CAAA,EAAA,CAuC2B,CAvC3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAuC2B,MAAA,CAAA,QAvC3B,CAAA,GAAA,CAAA,CAAA;AACxB,iBA2CrD,oBA3CqD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA2C0B,iBA3C1B,CAAA,EAAA,CA2CgD,CA3ChD,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA2CgD,MAAA,CAAA,QA3ChD,CAAA,GAAA,CAAA,CAAA;AAA8B,iBA+CnF,mBA/CmF,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA+CL,iBA/CK,CAAA,EAAA,CA+CiB,CA/CjB,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA+CiB,MAAA,CAAA,QA/CjB,CAAA,GAAA,CAAA,CAAA;AAAR,iBAmD3E,qBAnD2E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAmDK,iBAnDL,CAAA,EAAA,CAmD2B,CAnD3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAmD2B,MAAA,CAAA,QAnD3B,CAAA,GAAA,CAAA,CAAA;AACvB,iBAsDpD,sBAtDoD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAsDW,iBAtDX,CAAA,EAAA,CAsDiC,CAtDjC,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAsDiC,MAAA,CAAA,QAtDjC,CAAA,GAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"useCollectionApi.d.ts","names":[],"sources":["../../src/client/useCollectionApi.ts"],"sourcesContent":[],"mappings":";;;;;KAMK,aAAA;gDAC2C,uBAAuB,sBAAsB,QAAQ;qEAChC,sBAAsB,QAAQ;EAF9F,GAAA,EAAA,CAAA,IAAA,OAAa,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAGkD,iBAHlD,EAAA,GAGwE,OAHxE,CAGgF,CAHhF,CAAA;EAAA,KAAA,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAIoD,iBAJpD,EAAA,GAI0E,OAJ1E,CAIkF,CAJlF,CAAA;EAAA,MAC8B,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAII,iBAJJ,EAAA,GAI0B,OAJ1B,CAIkC,CAJlC,CAAA;CAAW;AAA0C,iBAOrF,gBAAA,CAAA,CAPqF,EAOjE,aAPiE;AAAR,iBAuC7E,mBAvC6E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAuCjB,WAvCiB,EAAA,OAAA,CAAA,EAuCK,iBAvCL,CAAA,EAAA,CAuC2B,CAvC3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAuC2B,OAAA,CAAA,QAvC3B,CAAA,GAAA,CAAA,CAAA;AACxB,iBA2CrD,oBA3CqD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA2C0B,iBA3C1B,CAAA,EAAA,CA2CgD,CA3ChD,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA2CgD,OAAA,CAAA,QA3ChD,CAAA,GAAA,CAAA,CAAA;AAA8B,iBA+CnF,mBA/CmF,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA+CL,iBA/CK,CAAA,EAAA,CA+CiB,CA/CjB,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA+CiB,OAAA,CAAA,QA/CjB,CAAA,GAAA,CAAA,CAAA;AAAR,iBAmD3E,qBAnD2E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAmDK,iBAnDL,CAAA,EAAA,CAmD2B,CAnD3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAmD2B,OAAA,CAAA,QAnD3B,CAAA,GAAA,CAAA,CAAA;AACvB,iBAsDpD,sBAtDoD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAsDW,iBAtDX,CAAA,EAAA,CAsDiC,CAtDjC,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAsDiC,OAAA,CAAA,QAtDjC,CAAA,GAAA,CAAA,CAAA"}
@@ -321,6 +321,7 @@ declare const usePage: () => {
321
321
  description?: string | undefined;
322
322
  keywords?: string | undefined;
323
323
  robots?: string | undefined;
324
+ robot?: string | undefined;
324
325
  image?: {
325
326
  [x: string]: unknown;
326
327
  id?: string | undefined;
@@ -1,20 +1,27 @@
1
1
  import { IEndUser, IUser } from "../types.js";
2
- import * as react15 from "react";
2
+ import * as react22 from "react";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/client/user.d.ts
6
+ type UserValue = IEndUser | IUser | null;
6
7
  type UserContextType = {
7
- user?: IEndUser | IUser | null;
8
- setUser: (user?: IEndUser | IUser | null) => void;
8
+ user?: UserValue;
9
+ setUser: (user?: UserValue) => void;
9
10
  };
10
- declare const UserContext: react15.Context<UserContextType>;
11
+ declare const UserContext: react22.Context<UserContextType>;
12
+ /** Forces the next UserProvider mount to read `/auth/me` again. */
13
+ declare function invalidateUser(): void;
14
+ /**
15
+ * Provides the current user. Pass `initialUser` (a user or `null`) when the
16
+ * server already knows it, to skip the `/auth/me` request entirely.
17
+ */
11
18
  declare function UserProvider({
19
+ initialUser,
12
20
  children
13
21
  }: {
22
+ initialUser?: UserValue;
14
23
  children: ReactNode;
15
- }): react15.JSX.Element;
16
- //# sourceMappingURL=user.d.ts.map
17
-
24
+ }): react22.JSX.Element;
18
25
  //#endregion
19
- export { UserContext, UserContextType, UserProvider };
26
+ export { UserContext, UserContextType, UserProvider, invalidateUser };
20
27
  //# sourceMappingURL=user.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","names":[],"sources":["../../src/client/user.tsx"],"sourcesContent":[],"mappings":";;;;;KAMY,eAAA;SACH,WAAW;mBACD,WAAW;AAF9B,CAAA;AAA2B,cAKd,WALc,EAKH,OAAA,CAAA,OALG,CAKH,eALG,CAAA;AAClB,iBAUO,YAAA,CAVP;EAAA;CAAA,EAAA;EAAQ,QAAG,EAaR,SAbQ;CAAK,CAAA,EAcxB,OAAA,CAAA,GAAA,CAAA,OAbkB"}
1
+ {"version":3,"file":"user.d.ts","names":[],"sources":["../../src/client/user.tsx"],"sourcesContent":[],"mappings":";;;;;KAMK,SAAA,GAAY,WAAW;KAEhB,eAAA;SACH;EAHJ,OAAA,EAAA,CAAA,IAAS,CAAA,EAIK,SAJL,EAAA,GAAA,IAAA;CAAA;AAAG,cAOJ,WAPI,EAOO,OAAA,CAAA,OAPP,CAOO,eAPP,CAAA;;AAAgB,iBA6BjB,cAAA,CAAA,CA7BiB,EAAA,IAAA;AAEjC;;;;AAE4B,iBAiCZ,YAAA,CAjCY;EAAA,WAAA;EAAA;CAAA,EAAA;EAGf,WAAA,CAAA,EAkCG,SA9Bd;EAAA,QAAA,EA+BU,SA/BV;CAAA,CAAA,EAgCD,OAAA,CAAA,GAAA,CAAA,OApCuB"}