@fluxfast/react 0.0.0-oidc-bootstrap.0

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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -0
  3. package/dist/client.d.ts +10 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +41 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/config.d.ts +17 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +3 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/document.d.ts +7 -0
  12. package/dist/document.d.ts.map +1 -0
  13. package/dist/document.js +10 -0
  14. package/dist/document.js.map +1 -0
  15. package/dist/esm/client.js +35 -0
  16. package/dist/esm/client.js.map +1 -0
  17. package/dist/esm/config.js +2 -0
  18. package/dist/esm/config.js.map +1 -0
  19. package/dist/esm/document.js +7 -0
  20. package/dist/esm/document.js.map +1 -0
  21. package/dist/esm/form.js +204 -0
  22. package/dist/esm/form.js.map +1 -0
  23. package/dist/esm/hooks.js +50 -0
  24. package/dist/esm/hooks.js.map +1 -0
  25. package/dist/esm/hydration.js +40 -0
  26. package/dist/esm/hydration.js.map +1 -0
  27. package/dist/esm/index.js +11 -0
  28. package/dist/esm/index.js.map +1 -0
  29. package/dist/esm/link.js +61 -0
  30. package/dist/esm/link.js.map +1 -0
  31. package/dist/esm/live.js +17 -0
  32. package/dist/esm/live.js.map +1 -0
  33. package/dist/esm/package.json +3 -0
  34. package/dist/esm/provider.js +77 -0
  35. package/dist/esm/provider.js.map +1 -0
  36. package/dist/esm/resolver.js +31 -0
  37. package/dist/esm/resolver.js.map +1 -0
  38. package/dist/esm/root.js +40 -0
  39. package/dist/esm/root.js.map +1 -0
  40. package/dist/esm/server/handler.js +115 -0
  41. package/dist/esm/server/handler.js.map +1 -0
  42. package/dist/esm/server/index.js +4 -0
  43. package/dist/esm/server/index.js.map +1 -0
  44. package/dist/esm/server/render.js +70 -0
  45. package/dist/esm/server/render.js.map +1 -0
  46. package/dist/form.d.ts +31 -0
  47. package/dist/form.d.ts.map +1 -0
  48. package/dist/form.js +207 -0
  49. package/dist/form.js.map +1 -0
  50. package/dist/hooks.d.ts +20 -0
  51. package/dist/hooks.d.ts.map +1 -0
  52. package/dist/hooks.js +58 -0
  53. package/dist/hooks.js.map +1 -0
  54. package/dist/hydration.d.ts +5 -0
  55. package/dist/hydration.d.ts.map +1 -0
  56. package/dist/hydration.js +44 -0
  57. package/dist/hydration.js.map +1 -0
  58. package/dist/index.d.ts +10 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +27 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/link.d.ts +10 -0
  63. package/dist/link.d.ts.map +1 -0
  64. package/dist/link.js +65 -0
  65. package/dist/link.js.map +1 -0
  66. package/dist/live.d.ts +5 -0
  67. package/dist/live.d.ts.map +1 -0
  68. package/dist/live.js +20 -0
  69. package/dist/live.js.map +1 -0
  70. package/dist/provider.d.ts +22 -0
  71. package/dist/provider.d.ts.map +1 -0
  72. package/dist/provider.js +82 -0
  73. package/dist/provider.js.map +1 -0
  74. package/dist/resolver.d.ts +13 -0
  75. package/dist/resolver.d.ts.map +1 -0
  76. package/dist/resolver.js +39 -0
  77. package/dist/resolver.js.map +1 -0
  78. package/dist/root.d.ts +15 -0
  79. package/dist/root.d.ts.map +1 -0
  80. package/dist/root.js +43 -0
  81. package/dist/root.js.map +1 -0
  82. package/dist/server/handler.d.ts +20 -0
  83. package/dist/server/handler.d.ts.map +1 -0
  84. package/dist/server/handler.js +118 -0
  85. package/dist/server/handler.js.map +1 -0
  86. package/dist/server/index.d.ts +6 -0
  87. package/dist/server/index.d.ts.map +1 -0
  88. package/dist/server/index.js +9 -0
  89. package/dist/server/index.js.map +1 -0
  90. package/dist/server/render.d.ts +11 -0
  91. package/dist/server/render.d.ts.map +1 -0
  92. package/dist/server/render.js +77 -0
  93. package/dist/server/render.js.map +1 -0
  94. package/package.json +72 -0
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useRouter } from "./hooks.js";
4
+ export function resolveInternalDestination(href, currentUrl) {
5
+ if (href.startsWith("#"))
6
+ return null;
7
+ const base = currentUrl ?? (typeof window !== "undefined" ? window.location.href : undefined);
8
+ if (!base)
9
+ return href.startsWith("/") ? href : null;
10
+ try {
11
+ const destination = new URL(href, base);
12
+ if (destination.origin !== new URL(base).origin)
13
+ return null;
14
+ return `${destination.pathname}${destination.search}${destination.hash}`;
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ export function Link({ href, prefetch = "hover", replace = false, preserveScroll = false, onClick, onMouseEnter, children, ...props }) {
21
+ const router = useRouter();
22
+ const getInternalDestination = () => {
23
+ return resolveInternalDestination(href);
24
+ };
25
+ const handleClick = (e) => {
26
+ if (onClick) {
27
+ onClick(e);
28
+ }
29
+ // Allow browser default for external links or modified clicks (ctrl/cmd/shift/middle click)
30
+ if (e.defaultPrevented ||
31
+ e.button !== 0 ||
32
+ e.metaKey ||
33
+ e.ctrlKey ||
34
+ e.altKey ||
35
+ e.shiftKey ||
36
+ props.download !== undefined ||
37
+ (props.target !== undefined && props.target !== "_self")) {
38
+ return;
39
+ }
40
+ const destination = getInternalDestination();
41
+ if (!destination)
42
+ return;
43
+ e.preventDefault();
44
+ router.visit(destination, { replace, preserveScroll }).catch(err => {
45
+ console.error("[fluxfast] Link navigation failed:", err);
46
+ });
47
+ };
48
+ const handleMouseEnter = (e) => {
49
+ if (onMouseEnter) {
50
+ onMouseEnter(e);
51
+ }
52
+ const destination = getInternalDestination();
53
+ if (prefetch === "hover" && destination) {
54
+ router.prefetch(destination).catch(err => {
55
+ console.debug("[fluxfast] Prefetch failed:", err);
56
+ });
57
+ }
58
+ };
59
+ return (_jsx("a", { href: href, onClick: handleClick, onMouseEnter: handleMouseEnter, ...props, children: children }));
60
+ }
61
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/link.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { useCallback, useSyncExternalStore } from "react";
3
+ import { useRouter } from "./hooks.js";
4
+ const SERVER_LIVE_STATUS = Object.freeze({
5
+ status: "idle",
6
+ connected: false,
7
+ reconnectAttempt: 0,
8
+ lastEventAt: null,
9
+ });
10
+ /** Observe the current Live Resource connection without affecting its lifecycle. */
11
+ export function useLiveStatus() {
12
+ const router = useRouter();
13
+ const subscribe = useCallback((callback) => router.liveManager.subscribe(callback), [router]);
14
+ const getSnapshot = useCallback(() => router.liveManager.getSnapshot(), [router]);
15
+ return useSyncExternalStore(subscribe, getSnapshot, () => SERVER_LIVE_STATUS);
16
+ }
17
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/live.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAOvC,MAAM,kBAAkB,GAAuB,MAAM,CAAC,MAAM,CAAC;IAC3D,MAAM,EAAE,MAAM;IACd,SAAS,EAAE,KAAK;IAChB,gBAAgB,EAAE,CAAC;IACnB,WAAW,EAAE,IAAI;CAClB,CAAC,CAAC;AAEH,oFAAoF;AACpF,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,QAAoB,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,EAChE,CAAC,MAAM,CAAC,CACT,CAAC;IACF,MAAM,WAAW,GAAG,WAAW,CAC7B,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,EACtC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext, useEffect, useMemo, useRef } from "react";
4
+ import { createFetchTransport, FluxRouter } from "@fluxfast/core";
5
+ export const FluxContext = createContext(null);
6
+ export function FluxProvider({ initialEnvelope, development, registry, router: customRouter, clientUrl, cache, children, }) {
7
+ const didBootstrapDiagnostics = useRef(false);
8
+ const router = useMemo(() => {
9
+ if (customRouter) {
10
+ return customRouter;
11
+ }
12
+ return new FluxRouter({
13
+ initialEnvelope,
14
+ transport: createFetchTransport(clientUrl),
15
+ maxResources: cache?.maxResources,
16
+ maxPages: cache?.maxPages,
17
+ deferHistory: true,
18
+ });
19
+ }, [customRouter, initialEnvelope, clientUrl, cache?.maxPages, cache?.maxResources]);
20
+ const value = useMemo(() => ({ router, registry: registry ?? {} }), [router, registry]);
21
+ useEffect(() => {
22
+ if ((typeof process !== "undefined" && process.env?.NODE_ENV === "production") ||
23
+ development === undefined ||
24
+ didBootstrapDiagnostics.current) {
25
+ return;
26
+ }
27
+ didBootstrapDiagnostics.current = true;
28
+ const requestId = typeof development.initialServerTrace.requestId === "string"
29
+ ? development.initialServerTrace.requestId
30
+ : "ssr";
31
+ const hydratedAt = Date.now();
32
+ const durationMs = typeof development.initialServerTrace.durationMs === "number"
33
+ ? development.initialServerTrace.durationMs
34
+ : 0;
35
+ router.diagnostics.bootstrap([
36
+ {
37
+ id: `ssr_server_trace_${requestId}`,
38
+ timestamp: Math.max(0, hydratedAt - durationMs),
39
+ type: "server-trace",
40
+ correlationId: requestId,
41
+ data: {
42
+ ...development.initialServerTrace,
43
+ path: development.initialPath,
44
+ source: "ssr",
45
+ },
46
+ },
47
+ {
48
+ id: `ssr_hydrated_${requestId}`,
49
+ timestamp: hydratedAt,
50
+ type: "lifecycle",
51
+ correlationId: requestId,
52
+ data: { phase: "hydrated", path: development.initialPath },
53
+ },
54
+ ]);
55
+ }, [development, router]);
56
+ useEffect(() => {
57
+ if (!customRouter) {
58
+ router.startHistory();
59
+ void router.startInitialDeferred().catch(() => undefined);
60
+ }
61
+ router.startLive();
62
+ return () => {
63
+ router.stopLive();
64
+ if (!customRouter)
65
+ router.stopHistory();
66
+ };
67
+ }, [customRouter, router]);
68
+ return (_jsx(FluxContext.Provider, { value: value, children: children }));
69
+ }
70
+ export function useFluxContext() {
71
+ const ctx = useContext(FluxContext);
72
+ if (!ctx) {
73
+ throw new Error("useFluxContext must be used within a <FluxProvider> or <FluxRoot>");
74
+ }
75
+ return ctx;
76
+ }
77
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ import { ComponentResolutionError } from "@fluxfast/core";
3
+ let globalRegistry = {};
4
+ const lazyComponents = new WeakMap();
5
+ export function setComponentRegistry(registry) {
6
+ globalRegistry = registry;
7
+ }
8
+ export function getComponentRegistry() {
9
+ return globalRegistry;
10
+ }
11
+ function isLazyEntry(entry) {
12
+ return typeof entry === "object" && entry !== null && "load" in entry;
13
+ }
14
+ export function resolveComponent(identifier, registry = globalRegistry) {
15
+ const entry = Object.prototype.hasOwnProperty.call(registry, identifier)
16
+ ? registry[identifier]
17
+ : undefined;
18
+ if (!entry) {
19
+ const known = Object.keys(registry).sort().map(key => `- ${key}`).join("\n");
20
+ throw new ComponentResolutionError(`FluxFast Component Resolution Error:\n\nComponent "${identifier}" was requested by the backend, but was not found in the component registry.\n\nRegistered components:\n${known || "(none)"}`);
21
+ }
22
+ if (!isLazyEntry(entry))
23
+ return entry;
24
+ let component = lazyComponents.get(entry);
25
+ if (!component) {
26
+ component = React.lazy(entry.load);
27
+ lazyComponents.set(entry, component);
28
+ }
29
+ return component;
30
+ }
31
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAS1D,IAAI,cAAc,GAAsB,EAAE,CAAC;AAC3C,MAAM,cAAc,GAAG,IAAI,OAAO,EAA2E,CAAC;AAE9G,MAAM,UAAU,oBAAoB,CAAC,QAA2B;IAC9D,cAAc,GAAG,QAAQ,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,SAAS,WAAW,CAAC,KAA6B;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,UAAkB,EAClB,QAAQ,GAAsB,cAAc;IAE5C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC;QACtE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;QACtB,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,IAAI,wBAAwB,CAChC,sDAAsD,UAAU,2GAA2G,KAAK,IAAI,QAAQ,EAAE,CAC/L,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Component, Suspense } from "react";
4
+ import { FluxProvider, useFluxContext } from "./provider.js";
5
+ import { usePage } from "./hooks.js";
6
+ import { resolveComponent } from "./resolver.js";
7
+ class ErrorBoundary extends Component {
8
+ state = { error: null };
9
+ static getDerivedStateFromError(error) {
10
+ return { error };
11
+ }
12
+ componentDidUpdate(previous) {
13
+ if (previous.resetKey !== this.props.resetKey && this.state.error) {
14
+ this.setState({ error: null });
15
+ }
16
+ }
17
+ render() {
18
+ if (this.state.error) {
19
+ if (this.props.fallback)
20
+ return this.props.fallback(this.state.error);
21
+ return (_jsxs("div", { role: "alert", style: { padding: "2rem", fontFamily: "monospace", color: "#b91c1c" }, children: [_jsx("h2", { children: "FluxFast Error" }), _jsx("pre", { style: { whiteSpace: "pre-wrap" }, children: this.state.error.message })] }));
22
+ }
23
+ return this.props.children;
24
+ }
25
+ }
26
+ function ResolvedPage({ component }) {
27
+ const { registry } = useFluxContext();
28
+ const PageComponent = resolveComponent(component, registry);
29
+ return _jsx(PageComponent, {});
30
+ }
31
+ function PageRenderer({ fallback }) {
32
+ const page = usePage();
33
+ if (!page.component)
34
+ return null;
35
+ return (_jsx(ErrorBoundary, { resetKey: page.component, fallback: fallback, children: _jsx(Suspense, { fallback: null, children: _jsx(ResolvedPage, { component: page.component }) }) }));
36
+ }
37
+ export function FluxRoot({ initialEnvelope, development, registry, clientUrl, cache, errorFallback, }) {
38
+ return (_jsx(FluxProvider, { initialEnvelope: initialEnvelope, development: development, registry: registry, clientUrl: clientUrl, cache: cache, children: _jsx(PageRenderer, { fallback: errorFallback }) }));
39
+ }
40
+ //# sourceMappingURL=root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/root.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EAAE,SAAS,EAAa,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAqB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAcpE,MAAM,aAAc,SAAQ,SAAiD;IAClE,KAAK,GAAuB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAErD,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAEQ,kBAAkB,CAAC,QAA4B;QACtD,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YAClE,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAEQ,MAAM;QACb,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtE,OAAO,CACL,eAAK,IAAI,EAAC,OAAO,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,aACrF,0CAAuB,EACvB,cAAK,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,YAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAO,IACpE,CACP,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF;AAED,SAAS,YAAY,CAAC,EAAE,SAAS,EAAyB;IACxD,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,CAAC;IACtC,MAAM,aAAa,GAAG,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,OAAO,KAAC,aAAa,KAAG,CAAC;AAC3B,CAAC;AAED,SAAS,YAAY,CAAC,EAAE,QAAQ,EAA8C;IAC5E,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAEjC,OAAO,CACL,KAAC,aAAa,IAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,YACzD,KAAC,QAAQ,IAAC,QAAQ,EAAE,IAAI,YACtB,KAAC,YAAY,IAAC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAI,GAClC,GACG,CACjB,CAAC;AACJ,CAAC;AAWD,MAAM,UAAU,QAAQ,CAAC,EACvB,eAAe,EACf,WAAW,EACX,QAAQ,EACR,SAAS,EACT,KAAK,EACL,aAAa,GACC;IACd,OAAO,CACL,KAAC,YAAY,IACX,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,YAEZ,KAAC,YAAY,IAAC,QAAQ,EAAE,aAAa,GAAI,GAC5B,CAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,115 @@
1
+ import { TransportError } from "@fluxfast/core";
2
+ import { createFluxTransportProxy, fetchFluxInitialPage, selectFluxForwardHeaders } from "@fluxfast/core/server";
3
+ import { PAYLOAD_ID, PAYLOAD_MARKER, SSR_MARKER } from "../document.js";
4
+ import { validateRenderTimeout } from "./render.js";
5
+ import { readFluxCacheConfig } from "../hydration.js";
6
+ function htmlResponse(body, status) {
7
+ return new Response(body, { status, headers: {
8
+ "content-type": "text/html; charset=utf-8", "cache-control": "no-store",
9
+ } });
10
+ }
11
+ function failureDocument(status) {
12
+ const title = status === 404 ? "Page not found" : status === 401 || status === 403
13
+ ? "Access denied" : "Page unavailable";
14
+ return `<!doctype html><html><head><meta charset="utf-8"><title>${title}</title></head><body><h1>${title}</h1></body></html>`;
15
+ }
16
+ function safePayload(props) {
17
+ // Even non-executable JSON script text must not contain an HTML closing tag.
18
+ return JSON.stringify(props).replace(/[<>&\u2028\u2029]/g, character => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
19
+ }
20
+ function renderDocument(template, markup, props) {
21
+ for (const marker of [SSR_MARKER, PAYLOAD_MARKER]) {
22
+ if (template.split(marker).length !== 2) {
23
+ throw new TypeError("FluxFast template requires exactly one SSR and payload marker");
24
+ }
25
+ }
26
+ // Do not run a second replace over inserted application markup: user text
27
+ // can legitimately contain the other marker. Split the template first.
28
+ const payload = `<script id="${PAYLOAD_ID}" type="application/json">${safePayload(props)}</script>`;
29
+ return template.split(/(<!--fluxfast:ssr-->|<!--fluxfast:payload-->)/g)
30
+ .map(part => part === SSR_MARKER ? markup : part === PAYLOAD_MARKER ? payload : part).join("");
31
+ }
32
+ function untilAbort(operation, signal) {
33
+ return new Promise((resolve, reject) => {
34
+ const abort = () => reject(new Error("FluxFast initial request aborted"));
35
+ if (signal.aborted)
36
+ abort();
37
+ else
38
+ signal.addEventListener("abort", abort, { once: true });
39
+ operation.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
40
+ });
41
+ }
42
+ /** Web Request/Response boundary reused by SSR hosts; no socket or asset server. */
43
+ export function createFluxReactHandler(options) {
44
+ const timeoutMs = options.timeoutMs ?? 30_000;
45
+ validateRenderTimeout(timeoutMs);
46
+ const cache = options.cache === undefined ? undefined : readFluxCacheConfig(options.cache);
47
+ let backend;
48
+ try {
49
+ backend = new URL(options.backendUrl);
50
+ }
51
+ catch {
52
+ throw new TypeError("FluxFast backendUrl must be a trusted HTTP(S) URL");
53
+ }
54
+ if (!["http:", "https:"].includes(backend.protocol) || backend.username || backend.password || backend.search || backend.hash) {
55
+ throw new TypeError("FluxFast backendUrl must be a trusted HTTP(S) URL without credentials, query, or fragment");
56
+ }
57
+ const fetchImplementation = options.fetch ?? globalThis.fetch;
58
+ return async (request) => {
59
+ const development = options.development === true && process.env.NODE_ENV !== "production";
60
+ const url = new URL(request.url);
61
+ if (request.headers.get("x-fluxfast") === "1") {
62
+ const headers = new Headers(request.headers);
63
+ if (!development)
64
+ headers.delete("x-fluxfast-devtools");
65
+ const proxy = createFluxTransportProxy({ backendUrl: options.backendUrl, fetch: fetchImplementation });
66
+ const result = await proxy(new Request(request, { headers }), url.pathname);
67
+ if (development)
68
+ return result;
69
+ const responseHeaders = new Headers(result.headers);
70
+ responseHeaders.delete("x-fluxfast-devtools-trace");
71
+ return new Response(result.body, { status: result.status, statusText: result.statusText, headers: responseHeaders });
72
+ }
73
+ if (request.method !== "GET" && request.method !== "HEAD") {
74
+ return new Response(null, { status: 405, headers: { allow: "GET, HEAD", "cache-control": "no-store" } });
75
+ }
76
+ const controller = new AbortController();
77
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
78
+ const signal = AbortSignal.any([request.signal, controller.signal]);
79
+ try {
80
+ if (signal.aborted)
81
+ throw new Error("FluxFast initial request aborted");
82
+ const initial = await untilAbort(fetchFluxInitialPage({
83
+ backendUrl: options.backendUrl, path: url.pathname + url.search,
84
+ headers: selectFluxForwardHeaders(request.headers, options.forwardHeaders),
85
+ diagnostics: development,
86
+ fetch: (input, init) => fetchImplementation(input, { ...init, signal }),
87
+ }), signal);
88
+ if (initial.type === "not-found") {
89
+ return htmlResponse(request.method === "HEAD" ? null : failureDocument(404), 404);
90
+ }
91
+ const props = {
92
+ initialEnvelope: initial.envelope,
93
+ ...(cache === undefined ? {} : { cache }),
94
+ ...(initial.development === undefined ? {} : { development: initial.development }),
95
+ };
96
+ const template = typeof options.template === "string" ? options.template : await untilAbort(Promise.resolve(options.template(request)), signal);
97
+ const markup = await untilAbort(options.render(props, { signal, timeoutMs }), signal);
98
+ if (signal.aborted)
99
+ throw new Error("FluxFast initial request aborted");
100
+ const html = renderDocument(template, markup, props);
101
+ return htmlResponse(request.method === "HEAD" ? null : html, 200);
102
+ }
103
+ catch (error) {
104
+ const status = error instanceof TransportError && (error.status === 401 || error.status === 403)
105
+ ? error.status : signal.aborted ? 503 : 500;
106
+ // No native exception, backend address, response body or credentials cross
107
+ // into this public error document. Never invent a valid page envelope.
108
+ return htmlResponse(request.method === "HEAD" ? null : failureDocument(status), status);
109
+ }
110
+ finally {
111
+ clearTimeout(timer);
112
+ }
113
+ };
114
+ }
115
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/server/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Node-only React SSR boundary. Never import this entry into a browser graph. */
2
+ export { renderFluxApplication } from "./render.js";
3
+ export { createFluxReactHandler } from "./handler.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,70 @@
1
+ import React from "react";
2
+ import { renderToPipeableStream } from "react-dom/server";
3
+ import { Writable } from "node:stream";
4
+ import { IDENTIFIER_PREFIX } from "../document.js";
5
+ export function validateRenderTimeout(value) {
6
+ if (!Number.isSafeInteger(value) || value <= 0 || value > 2_147_483_647) {
7
+ throw new TypeError("FluxFast render timeoutMs must be a positive bounded integer");
8
+ }
9
+ }
10
+ /** Render meaningful HTML, including lazy pages, without a client-only bailout. */
11
+ export function renderFluxApplication(application, props, options = {}) {
12
+ const timeoutMs = options.timeoutMs ?? 30_000;
13
+ validateRenderTimeout(timeoutMs);
14
+ if (options.signal !== undefined && (typeof options.signal?.aborted !== "boolean" ||
15
+ typeof options.signal.addEventListener !== "function" || typeof options.signal.removeEventListener !== "function")) {
16
+ throw new TypeError("FluxFast render signal must be an AbortSignal");
17
+ }
18
+ if (options.signal?.aborted)
19
+ return Promise.reject(new Error("FluxFast rendering aborted"));
20
+ return new Promise((resolve, reject) => {
21
+ let settled = false;
22
+ let stream;
23
+ const chunks = [];
24
+ const destination = new Writable({
25
+ write(chunk, _encoding, callback) {
26
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
27
+ callback();
28
+ },
29
+ });
30
+ const cleanup = () => {
31
+ clearTimeout(timer);
32
+ options.signal?.removeEventListener("abort", abort);
33
+ };
34
+ const fail = (error) => {
35
+ if (settled)
36
+ return;
37
+ settled = true;
38
+ cleanup();
39
+ reject(error);
40
+ stream?.abort();
41
+ destination.destroy();
42
+ };
43
+ const abort = () => fail(new Error("FluxFast rendering aborted"));
44
+ const timer = setTimeout(() => fail(new Error("FluxFast rendering timed out")), timeoutMs);
45
+ options.signal?.addEventListener("abort", abort, { once: true });
46
+ destination.on("error", fail);
47
+ destination.on("finish", () => {
48
+ if (settled)
49
+ return;
50
+ settled = true;
51
+ cleanup();
52
+ resolve(Buffer.concat(chunks).toString("utf8"));
53
+ });
54
+ try {
55
+ stream = renderToPipeableStream(React.createElement(application, props), {
56
+ identifierPrefix: IDENTIFIER_PREFIX,
57
+ // Lazy registry modules are part of the blocking page, not a deferred
58
+ // resource. Waiting here avoids an empty fallback in the initial HTML.
59
+ onAllReady() { if (!settled)
60
+ stream.pipe(destination); },
61
+ onShellError: fail,
62
+ onError: fail,
63
+ });
64
+ }
65
+ catch (error) {
66
+ fail(error);
67
+ }
68
+ });
69
+ }
70
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/server/render.ts"],"names":[],"mappings":"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"}
package/dist/form.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { type FormEvent } from "react";
2
+ import { type FluxValidator, type ValidationIssue } from "@fluxfast/core";
3
+ export interface FormOptions {
4
+ method?: string;
5
+ onSuccess?: () => void;
6
+ onError?: (errors: Record<string, string>) => void;
7
+ preserveScroll?: boolean;
8
+ }
9
+ export interface UseFormOptions<T extends Record<string, any>> {
10
+ validator?: FluxValidator<T>;
11
+ }
12
+ export interface UseFormReturn<T extends Record<string, any>> {
13
+ data: T;
14
+ errors: Partial<Record<keyof T, string>>;
15
+ issues: readonly ValidationIssue[];
16
+ errorMap: Readonly<Record<string, string>>;
17
+ processing: boolean;
18
+ wasSuccessful: boolean;
19
+ recentlySuccessful: boolean;
20
+ setData: {
21
+ <K extends keyof T>(key: K, value: T[K]): void;
22
+ (values: Partial<T> | ((prev: T) => T)): void;
23
+ };
24
+ setError: (key: keyof T, message: string) => void;
25
+ clearErrors: (...keys: (keyof T)[]) => void;
26
+ reset: (...keys: (keyof T)[]) => void;
27
+ validate: () => boolean;
28
+ submit: (url: string, options?: FormOptions) => (e?: FormEvent<HTMLFormElement>) => Promise<void>;
29
+ }
30
+ export declare function useForm<T extends Record<string, any>>(initialValues: T, formOptions?: UseFormOptions<T>): UseFormReturn<T>;
31
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAQxB,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC1D,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IACnC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,OAAO,EAAE;QACP,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAC/C,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;KAC/C,CAAC;IACF,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;IAC5C,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,MAAM,EAAE,CACN,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,WAAW,KAClB,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAgCD,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACnD,aAAa,EAAE,CAAC,EAChB,WAAW,GAAE,cAAc,CAAC,CAAC,CAAM,GAClC,aAAa,CAAC,CAAC,CAAC,CA0LlB"}