@alepha/react 0.13.1 → 0.13.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.
- package/dist/auth/index.browser.js +10 -5
- package/dist/auth/index.browser.js.map +1 -1
- package/dist/auth/index.d.ts +401 -330
- package/dist/auth/index.js +12 -7
- package/dist/auth/index.js.map +1 -1
- package/dist/core/index.browser.js +50 -28
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +382 -344
- package/dist/core/index.js +65 -37
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +381 -0
- package/dist/core/index.native.js.map +1 -0
- package/dist/form/index.d.ts +2 -2
- package/dist/head/index.browser.js +28 -17
- package/dist/head/index.browser.js.map +1 -1
- package/dist/head/index.d.ts +270 -267
- package/dist/head/index.js +29 -17
- package/dist/head/index.js.map +1 -1
- package/dist/i18n/index.d.ts +20 -20
- package/dist/i18n/index.js +12 -12
- package/dist/i18n/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/dist/websocket/index.js.map +1 -1
- package/package.json +21 -12
- package/src/auth/index.ts +1 -1
- package/src/auth/providers/ReactAuthProvider.ts +1 -1
- package/src/auth/services/ReactAuth.ts +15 -5
- package/src/core/components/NestedView.tsx +6 -2
- package/src/core/components/NotFound.tsx +10 -6
- package/src/core/hooks/useStore.ts +4 -4
- package/src/core/index.browser.ts +2 -2
- package/src/core/index.native.ts +1 -1
- package/src/core/index.shared-router.ts +1 -1
- package/src/core/index.ts +3 -3
- package/src/core/{descriptors → primitives}/$page.ts +20 -20
- package/src/core/providers/ReactBrowserProvider.ts +2 -2
- package/src/core/providers/ReactBrowserRouterProvider.ts +3 -2
- package/src/core/providers/ReactPageProvider.ts +28 -11
- package/src/core/providers/ReactServerProvider.ts +34 -23
- package/src/core/services/ReactPageServerService.ts +6 -6
- package/src/core/services/ReactPageService.ts +6 -6
- package/src/core/services/ReactRouter.ts +19 -3
- package/src/head/index.browser.ts +3 -3
- package/src/head/index.ts +4 -4
- package/src/head/interfaces/Head.ts +1 -0
- package/src/head/{descriptors → primitives}/$head.ts +10 -7
- package/src/head/providers/BrowserHeadProvider.ts +13 -0
- package/src/head/providers/HeadProvider.ts +11 -9
- package/src/head/providers/ServerHeadProvider.ts +6 -0
- package/src/i18n/hooks/useI18n.ts +2 -2
- package/src/i18n/index.ts +3 -3
- package/src/i18n/{descriptors → primitives}/$dictionary.ts +8 -8
- package/src/i18n/providers/I18nProvider.ts +5 -5
- package/src/websocket/hooks/useRoom.tsx +3 -3
|
@@ -23,9 +23,9 @@ import { ServerStaticProvider } from "alepha/server/static";
|
|
|
23
23
|
import { renderToString } from "react-dom/server";
|
|
24
24
|
import {
|
|
25
25
|
$page,
|
|
26
|
-
type
|
|
27
|
-
type
|
|
28
|
-
} from "../
|
|
26
|
+
type PagePrimitiveRenderOptions,
|
|
27
|
+
type PagePrimitiveRenderResult,
|
|
28
|
+
} from "../primitives/$page.ts";
|
|
29
29
|
import { Redirection } from "../errors/Redirection.ts";
|
|
30
30
|
import type { ReactHydrationState } from "./ReactBrowserProvider.ts";
|
|
31
31
|
import {
|
|
@@ -112,12 +112,12 @@ export class ReactServerProvider {
|
|
|
112
112
|
public readonly onConfigure = $hook({
|
|
113
113
|
on: "configure",
|
|
114
114
|
handler: async () => {
|
|
115
|
-
const pages = this.alepha.
|
|
115
|
+
const pages = this.alepha.primitives($page);
|
|
116
116
|
|
|
117
117
|
const ssrEnabled =
|
|
118
118
|
pages.length > 0 && this.env.REACT_SSR_ENABLED !== false;
|
|
119
119
|
|
|
120
|
-
this.alepha.
|
|
120
|
+
this.alepha.store.set("alepha.react.server.ssr", ssrEnabled);
|
|
121
121
|
|
|
122
122
|
// development mode
|
|
123
123
|
if (this.alepha.isViteDev()) {
|
|
@@ -184,19 +184,17 @@ export class ReactServerProvider {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
for (const page of this.pageApi.getPages()) {
|
|
187
|
-
if (page.
|
|
188
|
-
|
|
187
|
+
if (page.component || page.lazy) {
|
|
188
|
+
this.log.debug(`+ ${page.match} -> ${page.name}`);
|
|
189
|
+
|
|
190
|
+
this.serverRouterProvider.createRoute({
|
|
191
|
+
...page,
|
|
192
|
+
schema: undefined, // schema is handled by the page primitive provider for now (shared by browser and server)
|
|
193
|
+
method: "GET",
|
|
194
|
+
path: page.match,
|
|
195
|
+
handler: this.createHandler(page, templateLoader),
|
|
196
|
+
});
|
|
189
197
|
}
|
|
190
|
-
|
|
191
|
-
this.log.debug(`+ ${page.match} -> ${page.name}`);
|
|
192
|
-
|
|
193
|
-
this.serverRouterProvider.createRoute({
|
|
194
|
-
...page,
|
|
195
|
-
schema: undefined, // schema is handled by the page descriptor provider for now (shared by browser and server)
|
|
196
|
-
method: "GET",
|
|
197
|
-
path: page.match,
|
|
198
|
-
handler: this.createHandler(page, templateLoader),
|
|
199
|
-
});
|
|
200
198
|
}
|
|
201
199
|
}
|
|
202
200
|
|
|
@@ -257,8 +255,8 @@ export class ReactServerProvider {
|
|
|
257
255
|
*/
|
|
258
256
|
public async render(
|
|
259
257
|
name: string,
|
|
260
|
-
options:
|
|
261
|
-
): Promise<
|
|
258
|
+
options: PagePrimitiveRenderOptions = {},
|
|
259
|
+
): Promise<PagePrimitiveRenderResult> {
|
|
262
260
|
const page = this.pageApi.page(name);
|
|
263
261
|
const url = new URL(this.pageApi.url(name, options));
|
|
264
262
|
const entry: Partial<ReactRouterState> = {
|
|
@@ -289,7 +287,7 @@ export class ReactServerProvider {
|
|
|
289
287
|
}
|
|
290
288
|
|
|
291
289
|
if (!options.html) {
|
|
292
|
-
this.alepha.
|
|
290
|
+
this.alepha.store.set("alepha.react.router.state", state);
|
|
293
291
|
|
|
294
292
|
return {
|
|
295
293
|
state,
|
|
@@ -339,8 +337,10 @@ export class ReactServerProvider {
|
|
|
339
337
|
|
|
340
338
|
const state = entry as ReactRouterState;
|
|
341
339
|
|
|
340
|
+
state.name = route.name;
|
|
341
|
+
|
|
342
342
|
if (this.alepha.has(ServerLinksProvider)) {
|
|
343
|
-
this.alepha.
|
|
343
|
+
this.alepha.store.set(
|
|
344
344
|
"alepha.server.request.apiLinks",
|
|
345
345
|
await this.alepha.inject(ServerLinksProvider).getUserApiLinks({
|
|
346
346
|
user: (serverRequest as any).user, // TODO: fix type
|
|
@@ -349,9 +349,12 @@ export class ReactServerProvider {
|
|
|
349
349
|
);
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
let target: PageRoute | undefined = route; // TODO: move to
|
|
352
|
+
let target: PageRoute | undefined = route; // TODO: move to PagePrimitiveProvider
|
|
353
353
|
while (target) {
|
|
354
354
|
if (route.can && !route.can()) {
|
|
355
|
+
this.log.warn(
|
|
356
|
+
`Access to page '${route.name}' is forbidden by can() check`,
|
|
357
|
+
)
|
|
355
358
|
// if the page is not accessible, return 403
|
|
356
359
|
reply.status = 403;
|
|
357
360
|
reply.headers["content-type"] = "text/plain";
|
|
@@ -383,6 +386,9 @@ export class ReactServerProvider {
|
|
|
383
386
|
this.serverTimingProvider.endTiming("createLayers");
|
|
384
387
|
|
|
385
388
|
if (redirect) {
|
|
389
|
+
this.log.debug("Resolver resulted in redirection", {
|
|
390
|
+
redirect,
|
|
391
|
+
});
|
|
386
392
|
return reply.redirect(redirect);
|
|
387
393
|
}
|
|
388
394
|
|
|
@@ -402,9 +408,14 @@ export class ReactServerProvider {
|
|
|
402
408
|
? html.redirect
|
|
403
409
|
: this.pageApi.href(html.redirect),
|
|
404
410
|
);
|
|
411
|
+
this.log.debug("Rendering resulted in redirection", {
|
|
412
|
+
redirect: html.redirect,
|
|
413
|
+
});
|
|
405
414
|
return;
|
|
406
415
|
}
|
|
407
416
|
|
|
417
|
+
this.log.trace("Page rendered to HTML successfully");
|
|
418
|
+
|
|
408
419
|
const event = {
|
|
409
420
|
request: serverRequest,
|
|
410
421
|
state,
|
|
@@ -431,7 +442,7 @@ export class ReactServerProvider {
|
|
|
431
442
|
const element = this.pageApi.root(state);
|
|
432
443
|
|
|
433
444
|
// attach react router state to the http request context
|
|
434
|
-
this.alepha.
|
|
445
|
+
this.alepha.store.set("alepha.react.router.state", state);
|
|
435
446
|
|
|
436
447
|
this.serverTimingProvider.beginTiming("renderToString");
|
|
437
448
|
let app = "";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { $inject, AlephaError } from "alepha";
|
|
2
2
|
import { ServerProvider } from "alepha/server";
|
|
3
3
|
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "../
|
|
4
|
+
PagePrimitiveRenderOptions,
|
|
5
|
+
PagePrimitiveRenderResult,
|
|
6
|
+
} from "../primitives/$page.ts";
|
|
7
7
|
import { ReactServerProvider } from "../providers/ReactServerProvider.ts";
|
|
8
8
|
import { ReactPageService } from "./ReactPageService.ts";
|
|
9
9
|
|
|
@@ -13,14 +13,14 @@ export class ReactPageServerService extends ReactPageService {
|
|
|
13
13
|
|
|
14
14
|
public async render(
|
|
15
15
|
name: string,
|
|
16
|
-
options:
|
|
17
|
-
): Promise<
|
|
16
|
+
options: PagePrimitiveRenderOptions = {},
|
|
17
|
+
): Promise<PagePrimitiveRenderResult> {
|
|
18
18
|
return this.reactServerProvider.render(name, options);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
public async fetch(
|
|
22
22
|
pathname: string,
|
|
23
|
-
options:
|
|
23
|
+
options: PagePrimitiveRenderOptions = {},
|
|
24
24
|
): Promise<{
|
|
25
25
|
html: string;
|
|
26
26
|
response: Response;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { AlephaError } from "alepha";
|
|
2
2
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "../
|
|
3
|
+
PagePrimitiveRenderOptions,
|
|
4
|
+
PagePrimitiveRenderResult,
|
|
5
|
+
} from "../primitives/$page.ts";
|
|
6
6
|
|
|
7
7
|
export class ReactPageService {
|
|
8
8
|
public fetch(
|
|
9
9
|
pathname: string,
|
|
10
|
-
options:
|
|
10
|
+
options: PagePrimitiveRenderOptions = {},
|
|
11
11
|
): Promise<{
|
|
12
12
|
html: string;
|
|
13
13
|
response: Response;
|
|
@@ -17,8 +17,8 @@ export class ReactPageService {
|
|
|
17
17
|
|
|
18
18
|
public render(
|
|
19
19
|
name: string,
|
|
20
|
-
options:
|
|
21
|
-
): Promise<
|
|
20
|
+
options: PagePrimitiveRenderOptions = {},
|
|
21
|
+
): Promise<PagePrimitiveRenderResult> {
|
|
22
22
|
throw new AlephaError("Render is not available for this environment.");
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $inject, Alepha } from "alepha";
|
|
2
|
-
import type {
|
|
2
|
+
import type { PagePrimitive } from "../primitives/$page.ts";
|
|
3
3
|
import {
|
|
4
4
|
ReactBrowserProvider,
|
|
5
5
|
type RouterGoOptions,
|
|
@@ -15,7 +15,7 @@ export class ReactRouter<T extends object> {
|
|
|
15
15
|
protected readonly pageApi = $inject(ReactPageProvider);
|
|
16
16
|
|
|
17
17
|
public get state(): ReactRouterState {
|
|
18
|
-
return this.alepha.
|
|
18
|
+
return this.alepha.store.get("alepha.react.router.state")!;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
public get pages() {
|
|
@@ -51,6 +51,22 @@ export class ReactRouter<T extends object> {
|
|
|
51
51
|
return isActive;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
public node(
|
|
55
|
+
name: keyof VirtualRouter<T> | string,
|
|
56
|
+
config: {
|
|
57
|
+
params?: Record<string, any>;
|
|
58
|
+
query?: Record<string, any>;
|
|
59
|
+
} = {},
|
|
60
|
+
) {
|
|
61
|
+
const page = this.pageApi.page(name as string);
|
|
62
|
+
return {
|
|
63
|
+
...page,
|
|
64
|
+
label: page.label ?? page.name,
|
|
65
|
+
href: this.path(name, config),
|
|
66
|
+
children: undefined,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
public path(
|
|
55
71
|
name: keyof VirtualRouter<T> | string,
|
|
56
72
|
config: {
|
|
@@ -220,5 +236,5 @@ export class ReactRouter<T extends object> {
|
|
|
220
236
|
}
|
|
221
237
|
|
|
222
238
|
export type VirtualRouter<T> = {
|
|
223
|
-
[K in keyof T as T[K] extends
|
|
239
|
+
[K in keyof T as T[K] extends PagePrimitive ? K : never]: T[K];
|
|
224
240
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { AlephaReact } from "@alepha/react";
|
|
2
2
|
import { $module } from "alepha";
|
|
3
|
-
import { $head } from "./
|
|
3
|
+
import { $head } from "./primitives/$head.ts";
|
|
4
4
|
import { BrowserHeadProvider } from "./providers/BrowserHeadProvider.ts";
|
|
5
5
|
|
|
6
6
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
7
7
|
|
|
8
|
-
export * from "./
|
|
8
|
+
export * from "./primitives/$head.ts";
|
|
9
9
|
export * from "./hooks/useHead.ts";
|
|
10
10
|
export * from "./interfaces/Head.ts";
|
|
11
11
|
export * from "./providers/BrowserHeadProvider.ts";
|
|
@@ -20,6 +20,6 @@ export * from "./providers/BrowserHeadProvider.ts";
|
|
|
20
20
|
*/
|
|
21
21
|
export const AlephaReactHead = $module({
|
|
22
22
|
name: "alepha.react.head",
|
|
23
|
-
|
|
23
|
+
primitives: [$head],
|
|
24
24
|
services: [AlephaReact, BrowserHeadProvider],
|
|
25
25
|
});
|
package/src/head/index.ts
CHANGED
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
type TPropsParentDefault,
|
|
6
6
|
} from "@alepha/react";
|
|
7
7
|
import { $module } from "alepha";
|
|
8
|
-
import { $head } from "./
|
|
8
|
+
import { $head } from "./primitives/$head.ts";
|
|
9
9
|
import type { Head } from "./interfaces/Head.ts";
|
|
10
10
|
import { ServerHeadProvider } from "./providers/ServerHeadProvider.ts";
|
|
11
11
|
|
|
12
12
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
13
13
|
|
|
14
|
-
export * from "./
|
|
14
|
+
export * from "./primitives/$head.ts";
|
|
15
15
|
export * from "./hooks/useHead.ts";
|
|
16
16
|
export * from "./interfaces/Head.ts";
|
|
17
17
|
export * from "./providers/ServerHeadProvider.ts";
|
|
@@ -19,7 +19,7 @@ export * from "./providers/ServerHeadProvider.ts";
|
|
|
19
19
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
20
20
|
|
|
21
21
|
declare module "@alepha/react" {
|
|
22
|
-
interface
|
|
22
|
+
interface PagePrimitiveOptions<
|
|
23
23
|
TConfig extends PageConfigSchema = PageConfigSchema,
|
|
24
24
|
TProps extends object = TPropsDefault,
|
|
25
25
|
TPropsParent extends object = TPropsParentDefault,
|
|
@@ -42,6 +42,6 @@ declare module "@alepha/react" {
|
|
|
42
42
|
*/
|
|
43
43
|
export const AlephaReactHead = $module({
|
|
44
44
|
name: "alepha.react.head",
|
|
45
|
-
|
|
45
|
+
primitives: [$head],
|
|
46
46
|
services: [AlephaReact, ServerHeadProvider],
|
|
47
47
|
});
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
import { $inject,
|
|
1
|
+
import { $inject, createPrimitive, Primitive, KIND } from "alepha";
|
|
2
2
|
import type { Head } from "../interfaces/Head.ts";
|
|
3
3
|
import { HeadProvider } from "../providers/HeadProvider.ts";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Set global `<head>` options for the application.
|
|
7
7
|
*/
|
|
8
|
-
export const $head = (options:
|
|
9
|
-
return
|
|
8
|
+
export const $head = (options: HeadPrimitiveOptions) => {
|
|
9
|
+
return createPrimitive(HeadPrimitive, options);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
13
13
|
|
|
14
|
-
export type
|
|
14
|
+
export type HeadPrimitiveOptions = Head | (() => Head);
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
17
17
|
|
|
18
|
-
export class
|
|
18
|
+
export class HeadPrimitive extends Primitive<HeadPrimitiveOptions> {
|
|
19
19
|
protected readonly provider = $inject(HeadProvider);
|
|
20
20
|
protected onInit() {
|
|
21
|
-
this.provider.global =
|
|
21
|
+
this.provider.global = [
|
|
22
|
+
...(this.provider.global ?? []),
|
|
23
|
+
this.options,
|
|
24
|
+
];
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
$head[KIND] =
|
|
28
|
+
$head[KIND] = HeadPrimitive;
|
|
@@ -101,5 +101,18 @@ export class BrowserHeadProvider {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
if (head.link) {
|
|
106
|
+
for (const it of head.link) {
|
|
107
|
+
const { rel, href } = it;
|
|
108
|
+
let link = document.querySelector(`link[rel="${rel}"][href="${href}"]`);
|
|
109
|
+
if (!link) {
|
|
110
|
+
link = document.createElement("link");
|
|
111
|
+
link.setAttribute("rel", rel);
|
|
112
|
+
link.setAttribute("href", href);
|
|
113
|
+
document.head.appendChild(link);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
104
117
|
}
|
|
105
118
|
}
|
|
@@ -2,21 +2,23 @@ import type { PageRoute, ReactRouterState } from "@alepha/react";
|
|
|
2
2
|
import type { Head } from "../interfaces/Head.ts";
|
|
3
3
|
|
|
4
4
|
export class HeadProvider {
|
|
5
|
-
public global?: Head | (() => Head);
|
|
6
|
-
|
|
7
|
-
protected getGlobalHead(): Head | undefined {
|
|
8
|
-
if (typeof this.global === "function") {
|
|
9
|
-
return this.global();
|
|
10
|
-
}
|
|
11
|
-
return this.global;
|
|
12
|
-
}
|
|
5
|
+
public global?: Array<Head | (() => Head)> = [];
|
|
13
6
|
|
|
14
7
|
public fillHead(state: ReactRouterState) {
|
|
15
8
|
state.head = {
|
|
16
9
|
...state.head,
|
|
17
|
-
...this.getGlobalHead(),
|
|
18
10
|
};
|
|
19
11
|
|
|
12
|
+
for (const h of this.global ?? []) {
|
|
13
|
+
const head =
|
|
14
|
+
typeof h === "function" ? h() : h;
|
|
15
|
+
state.head = {
|
|
16
|
+
...state.head,
|
|
17
|
+
...head,
|
|
18
|
+
meta: [...(state.head.meta ?? []), ...(head.meta ?? [])],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
20
22
|
for (const layer of state.layers) {
|
|
21
23
|
if (layer.route?.head && !layer.error) {
|
|
22
24
|
this.fillHeadByPage(layer.route, state, layer.props ?? {});
|
|
@@ -62,6 +62,12 @@ export class ServerHeadProvider {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
if (head.link) {
|
|
66
|
+
for (const link of head.link) {
|
|
67
|
+
headContent += `<link rel="${this.escapeHtml(link.rel)}" href="${this.escapeHtml(link.href)}">\n`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
65
71
|
// Inject into <head>...</head>
|
|
66
72
|
result = result.replace(
|
|
67
73
|
/<head([^>]*)>(.*?)<\/head>/is,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useInject, useStore } from "@alepha/react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { DictionaryPrimitive } from "../primitives/$dictionary.ts";
|
|
3
3
|
import { I18nProvider } from "../providers/I18nProvider.ts";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -14,5 +14,5 @@ export const useI18n = <
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export type ServiceDictionary<T extends object> = {
|
|
17
|
-
[K in keyof T]: T[K] extends
|
|
17
|
+
[K in keyof T]: T[K] extends DictionaryPrimitive<infer U> ? U : never;
|
|
18
18
|
};
|
package/src/i18n/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
|
-
import { $dictionary } from "./
|
|
2
|
+
import { $dictionary } from "./primitives/$dictionary.ts";
|
|
3
3
|
import { I18nProvider } from "./providers/I18nProvider.ts";
|
|
4
4
|
|
|
5
5
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
6
6
|
|
|
7
7
|
export type { LocalizeProps } from "./components/Localize.tsx";
|
|
8
8
|
export { default as Localize } from "./components/Localize.tsx";
|
|
9
|
-
export * from "./
|
|
9
|
+
export * from "./primitives/$dictionary.ts";
|
|
10
10
|
export * from "./hooks/useI18n.ts";
|
|
11
11
|
export * from "./providers/I18nProvider.ts";
|
|
12
12
|
|
|
@@ -29,6 +29,6 @@ declare module "alepha" {
|
|
|
29
29
|
*/
|
|
30
30
|
export const AlephaReactI18n = $module({
|
|
31
31
|
name: "alepha.react.i18n",
|
|
32
|
-
|
|
32
|
+
primitives: [$dictionary],
|
|
33
33
|
services: [I18nProvider],
|
|
34
34
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $inject, type Async,
|
|
1
|
+
import { $inject, type Async, createPrimitive, Primitive, KIND } from "alepha";
|
|
2
2
|
import { I18nProvider } from "../providers/I18nProvider.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -33,14 +33,14 @@ import { I18nProvider } from "../providers/I18nProvider.ts";
|
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
35
|
export const $dictionary = <T extends Record<string, string>>(
|
|
36
|
-
options:
|
|
37
|
-
):
|
|
38
|
-
return
|
|
36
|
+
options: DictionaryPrimitiveOptions<T>,
|
|
37
|
+
): DictionaryPrimitive<T> => {
|
|
38
|
+
return createPrimitive(DictionaryPrimitive<T>, options);
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
42
42
|
|
|
43
|
-
export interface
|
|
43
|
+
export interface DictionaryPrimitiveOptions<T extends Record<string, string>> {
|
|
44
44
|
lang?: string;
|
|
45
45
|
name?: string;
|
|
46
46
|
lazy: () => Async<{ default: T }>;
|
|
@@ -48,9 +48,9 @@ export interface DictionaryDescriptorOptions<T extends Record<string, string>> {
|
|
|
48
48
|
|
|
49
49
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
50
50
|
|
|
51
|
-
export class
|
|
51
|
+
export class DictionaryPrimitive<
|
|
52
52
|
T extends Record<string, string>,
|
|
53
|
-
> extends
|
|
53
|
+
> extends Primitive<DictionaryPrimitiveOptions<T>> {
|
|
54
54
|
protected provider = $inject(I18nProvider);
|
|
55
55
|
protected onInit() {
|
|
56
56
|
this.provider.registry.push({
|
|
@@ -66,4 +66,4 @@ export class DictionaryDescriptor<
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
$dictionary[KIND] =
|
|
69
|
+
$dictionary[KIND] = DictionaryPrimitive;
|
|
@@ -54,7 +54,7 @@ export class I18nProvider<
|
|
|
54
54
|
on: "server:onRequest",
|
|
55
55
|
priority: "last",
|
|
56
56
|
handler: async ({ request }) => {
|
|
57
|
-
this.alepha.
|
|
57
|
+
this.alepha.store.set("alepha.react.i18n.lang", this.cookie.get(request));
|
|
58
58
|
},
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -65,7 +65,7 @@ export class I18nProvider<
|
|
|
65
65
|
// get cookie lang
|
|
66
66
|
const cookieLang = this.cookie.get();
|
|
67
67
|
if (cookieLang) {
|
|
68
|
-
this.alepha.
|
|
68
|
+
this.alepha.store.set("alepha.react.i18n.lang", cookieLang);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
for (const item of this.registry) {
|
|
@@ -110,7 +110,7 @@ export class I18nProvider<
|
|
|
110
110
|
this.cookie.set(lang);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
this.alepha.
|
|
113
|
+
this.alepha.store.set("alepha.react.i18n.lang", lang);
|
|
114
114
|
this.refreshLocale();
|
|
115
115
|
};
|
|
116
116
|
|
|
@@ -132,7 +132,7 @@ export class I18nProvider<
|
|
|
132
132
|
this.refreshLocale();
|
|
133
133
|
|
|
134
134
|
if (hasChanged) {
|
|
135
|
-
this.alepha.
|
|
135
|
+
this.alepha.store.set("alepha.react.i18n.lang", value);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
},
|
|
@@ -140,7 +140,7 @@ export class I18nProvider<
|
|
|
140
140
|
|
|
141
141
|
public get lang(): string {
|
|
142
142
|
return (
|
|
143
|
-
this.alepha.
|
|
143
|
+
this.alepha.store.get("alepha.react.i18n.lang") ||
|
|
144
144
|
this.options.fallbackLang
|
|
145
145
|
);
|
|
146
146
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useAlepha, useInject } from "@alepha/react";
|
|
2
2
|
import type { Static } from "alepha";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ChannelPrimitive, TWSObject } from "alepha/websocket";
|
|
4
4
|
import { WebSocketClient } from "alepha/websocket";
|
|
5
5
|
import { useEffect, useRef, useState } from "react";
|
|
6
6
|
|
|
@@ -17,9 +17,9 @@ export interface UseRoomOptions<
|
|
|
17
17
|
roomId: string;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Channel
|
|
20
|
+
* Channel primitive defining the schemas
|
|
21
21
|
*/
|
|
22
|
-
channel:
|
|
22
|
+
channel: ChannelPrimitive<TClient, TServer>;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Handler for incoming messages from the server
|