@mdxui/do 2.1.1 → 3.0.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.
- package/README.md +253 -266
- package/dist/{agents-xcIn2dUB.d.ts → agents-2_r9e9i7.d.ts} +213 -2
- package/dist/app/index.d.ts +347 -0
- package/dist/app/index.js +13 -0
- package/dist/app/index.js.map +1 -0
- package/dist/chunk-4KXVN3EQ.js +56 -0
- package/dist/chunk-4KXVN3EQ.js.map +1 -0
- package/dist/chunk-5AWTQDRF.js +76 -0
- package/dist/chunk-5AWTQDRF.js.map +1 -0
- package/dist/chunk-EQVOEEQO.js +95 -0
- package/dist/chunk-EQVOEEQO.js.map +1 -0
- package/dist/chunk-FO3N7SXV.js +469 -0
- package/dist/chunk-FO3N7SXV.js.map +1 -0
- package/dist/chunk-IESVTECE.js +536 -0
- package/dist/chunk-IESVTECE.js.map +1 -0
- package/dist/chunk-JWKIONEO.js +234 -0
- package/dist/chunk-JWKIONEO.js.map +1 -0
- package/dist/chunk-NTSEARBC.js +715 -0
- package/dist/chunk-NTSEARBC.js.map +1 -0
- package/dist/chunk-OWEAW4U6.js +116 -0
- package/dist/chunk-OWEAW4U6.js.map +1 -0
- package/dist/chunk-VRLUXCLD.js +31 -0
- package/dist/chunk-VRLUXCLD.js.map +1 -0
- package/dist/chunk-Y52IEYVM.js +131 -0
- package/dist/chunk-Y52IEYVM.js.map +1 -0
- package/dist/chunk-YGIBMNRH.js +1991 -0
- package/dist/chunk-YGIBMNRH.js.map +1 -0
- package/dist/components/index.d.ts +1 -738
- package/dist/components/index.js +2 -6
- package/dist/config-CmZBQQaT.d.ts +122 -0
- package/dist/{do-CaQVueZw.d.ts → do-C-t9UgjT.d.ts} +31 -33
- package/dist/errors-B4Oyyj4Z.d.ts +346 -0
- package/dist/hooks/index.d.ts +428 -696
- package/dist/hooks/index.js +6 -4
- package/dist/hooks/things/index.d.ts +298 -0
- package/dist/hooks/things/index.js +8 -0
- package/dist/hooks/things/index.js.map +1 -0
- package/dist/index.d.ts +21 -1010
- package/dist/index.js +11 -839
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +100 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/providers/index.d.ts +244 -32
- package/dist/providers/index.js +3 -2
- package/dist/query-keys-BC901wog.d.ts +153 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +2 -2
- package/dist/schemas/index.js.map +1 -1
- package/dist/{thing-DtI25yZh.d.ts → thing-BVhCTzOi.d.ts} +4 -4
- package/dist/types/index.d.ts +251 -216
- package/dist/types/index.js +1 -2
- package/dist/views/index.d.ts +131 -0
- package/dist/views/index.js +11 -0
- package/dist/views/index.js.map +1 -0
- package/package.json +39 -17
- package/dist/__test-utils__/index.d.ts +0 -399
- package/dist/__test-utils__/index.js +0 -34641
- package/dist/__test-utils__/index.js.map +0 -1
- package/dist/chunk-EEDMN7UF.js +0 -1351
- package/dist/chunk-EEDMN7UF.js.map +0 -1
- package/dist/chunk-G3PMV62Z.js +0 -33
- package/dist/chunk-G3PMV62Z.js.map +0 -1
- package/dist/chunk-NXPXL5NA.js +0 -3789
- package/dist/chunk-NXPXL5NA.js.map +0 -1
- package/dist/chunk-PC5FJY6M.js +0 -20
- package/dist/chunk-PC5FJY6M.js.map +0 -1
- package/dist/chunk-XF6LKY2M.js +0 -445
- package/dist/chunk-XF6LKY2M.js.map +0 -1
- package/dist/magic-string.es-J7BYFTTJ.js +0 -1307
- package/dist/magic-string.es-J7BYFTTJ.js.map +0 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/lib/errors.ts
|
|
2
|
+
var APIError = class _APIError extends Error {
|
|
3
|
+
constructor(code, message, status, details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "APIError";
|
|
9
|
+
Object.setPrototypeOf(this, _APIError.prototype);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create an APIError from a fetch Response
|
|
13
|
+
*
|
|
14
|
+
* @param response - The Response object from fetch
|
|
15
|
+
* @param body - Optional response body text (if already read)
|
|
16
|
+
* @returns An APIError with HTTP status information
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const response = await fetch('/api/things')
|
|
21
|
+
* if (!response.ok) {
|
|
22
|
+
* throw APIError.fromResponse(response, await response.text())
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
static fromResponse(response, body) {
|
|
27
|
+
return new _APIError(`HTTP_${response.status}`, body || response.statusText, response.status);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Type guard to check if an error is an APIError
|
|
31
|
+
*/
|
|
32
|
+
static isAPIError(error) {
|
|
33
|
+
return error instanceof _APIError;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var NetworkError = class _NetworkError extends Error {
|
|
37
|
+
constructor(message, cause) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.cause = cause;
|
|
40
|
+
this.name = "NetworkError";
|
|
41
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var ValidationError = class _ValidationError extends Error {
|
|
45
|
+
constructor(message, fields) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.fields = fields;
|
|
48
|
+
this.name = "ValidationError";
|
|
49
|
+
Object.setPrototypeOf(this, _ValidationError.prototype);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var SyncError = class _SyncError extends Error {
|
|
53
|
+
constructor(message, operation, recoverable) {
|
|
54
|
+
super(message);
|
|
55
|
+
this.operation = operation;
|
|
56
|
+
this.recoverable = recoverable;
|
|
57
|
+
this.name = "SyncError";
|
|
58
|
+
Object.setPrototypeOf(this, _SyncError.prototype);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function isAPIError(error) {
|
|
62
|
+
return error instanceof APIError;
|
|
63
|
+
}
|
|
64
|
+
function isNetworkError(error) {
|
|
65
|
+
return error instanceof NetworkError;
|
|
66
|
+
}
|
|
67
|
+
function isValidationError(error) {
|
|
68
|
+
return error instanceof ValidationError;
|
|
69
|
+
}
|
|
70
|
+
function isSyncError(error) {
|
|
71
|
+
return error instanceof SyncError;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { APIError, NetworkError, SyncError, ValidationError, isAPIError, isNetworkError, isSyncError, isValidationError };
|
|
75
|
+
//# sourceMappingURL=chunk-5AWTQDRF.js.map
|
|
76
|
+
//# sourceMappingURL=chunk-5AWTQDRF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/errors.ts"],"names":[],"mappings":";AAwCO,IAAM,QAAA,GAAN,MAAM,SAAA,SAAiB,KAAA,CAAM;AAAA,EAClC,WAAA,CACkB,IAAA,EAChB,OAAA,EACgB,MAAA,EACA,OAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AALG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AAEZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,SAAA,CAAS,SAAS,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,YAAA,CAAa,QAAA,EAAoB,IAAA,EAAyB;AAC/D,IAAA,OAAO,IAAI,SAAA,CAAS,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,IAAI,IAAA,IAAQ,QAAA,CAAS,UAAA,EAAY,QAAA,CAAS,MAAM,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAW,KAAA,EAAmC;AACnD,IAAA,OAAO,KAAA,YAAiB,SAAA;AAAA,EAC1B;AACF;AAWO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,KAAA,CAAM;AAAA,EACtC,WAAA,CACE,SACgB,KAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,aAAA,CAAa,SAAS,CAAA;AAAA,EACpD;AACF;AAgBO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,KAAA,CAAM;AAAA,EACzC,WAAA,CACE,SACgB,MAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,gBAAA,CAAgB,SAAS,CAAA;AAAA,EACvD;AACF;AAkBO,IAAM,SAAA,GAAN,MAAM,UAAA,SAAkB,KAAA,CAAM;AAAA,EACnC,WAAA,CACE,OAAA,EACgB,SAAA,EACA,WAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHG,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,UAAA,CAAU,SAAS,CAAA;AAAA,EACjD;AACF;AAKO,SAAS,WAAW,KAAA,EAAmC;AAC5D,EAAA,OAAO,KAAA,YAAiB,QAAA;AAC1B;AAKO,SAAS,eAAe,KAAA,EAAuC;AACpE,EAAA,OAAO,KAAA,YAAiB,YAAA;AAC1B;AAKO,SAAS,kBAAkB,KAAA,EAA0C;AAC1E,EAAA,OAAO,KAAA,YAAiB,eAAA;AAC1B;AAKO,SAAS,YAAY,KAAA,EAAoC;AAC9D,EAAA,OAAO,KAAA,YAAiB,SAAA;AAC1B","file":"chunk-5AWTQDRF.js","sourcesContent":["/**\n * Standardized error classes for @mdxui/do\n *\n * These classes provide consistent error handling across the package:\n * - APIError: HTTP/RPC errors from the backend\n * - NetworkError: Connection/fetch failures\n * - ValidationError: Input validation errors\n * - SyncError: Real-time sync errors\n *\n * @example\n * ```typescript\n * import { APIError, NetworkError, isAPIError } from '@mdxui/do'\n *\n * try {\n * const response = await fetch(url)\n * if (!response.ok) {\n * throw APIError.fromResponse(response)\n * }\n * } catch (error) {\n * if (isAPIError(error)) {\n * console.log(`API error ${error.code}: ${error.message}`)\n * if (error.status === 401) {\n * // Handle auth error\n * }\n * } else if (isNetworkError(error)) {\n * console.log('Network unavailable, will retry...')\n * }\n * }\n * ```\n */\n\n/**\n * API error from HTTP/RPC calls\n *\n * Provides structured error information including:\n * - code: Machine-readable error code (e.g., 'HTTP_404', 'VALIDATION_ERROR')\n * - message: Human-readable error message\n * - status: HTTP status code (when applicable)\n * - details: Additional error details from the server\n */\nexport class APIError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly status?: number,\n public readonly details?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'APIError'\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, APIError.prototype)\n }\n\n /**\n * Create an APIError from a fetch Response\n *\n * @param response - The Response object from fetch\n * @param body - Optional response body text (if already read)\n * @returns An APIError with HTTP status information\n *\n * @example\n * ```typescript\n * const response = await fetch('/api/things')\n * if (!response.ok) {\n * throw APIError.fromResponse(response, await response.text())\n * }\n * ```\n */\n static fromResponse(response: Response, body?: string): APIError {\n return new APIError(`HTTP_${response.status}`, body || response.statusText, response.status)\n }\n\n /**\n * Type guard to check if an error is an APIError\n */\n static isAPIError(error: unknown): error is APIError {\n return error instanceof APIError\n }\n}\n\n/**\n * Network-level error (connection failures, timeouts, etc.)\n *\n * Use for errors that occur before an HTTP response is received:\n * - DNS resolution failures\n * - Connection refused\n * - Request timeouts\n * - CORS errors\n */\nexport class NetworkError extends Error {\n constructor(\n message: string,\n public readonly cause?: Error\n ) {\n super(message)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n\n/**\n * Validation error with field-level details\n *\n * Use when input data fails validation checks.\n * The fields property maps field names to arrays of error messages.\n *\n * @example\n * ```typescript\n * throw new ValidationError('Invalid input', {\n * email: ['Invalid email format'],\n * name: ['Name is required', 'Name must be at least 2 characters'],\n * })\n * ```\n */\nexport class ValidationError extends Error {\n constructor(\n message: string,\n public readonly fields: Record<string, string[]>\n ) {\n super(message)\n this.name = 'ValidationError'\n Object.setPrototypeOf(this, ValidationError.prototype)\n }\n}\n\n/**\n * Real-time sync error\n *\n * Use for errors in the sync protocol (WebSocket, EventSource, etc.).\n * The operation property indicates what sync operation failed.\n * The recoverable property indicates whether the client should retry.\n *\n * @example\n * ```typescript\n * // Recoverable connection error - client should retry\n * throw new SyncError('WebSocket disconnected', 'connect', true)\n *\n * // Non-recoverable push error - user intervention needed\n * throw new SyncError('Conflict: record modified by another user', 'push', false)\n * ```\n */\nexport class SyncError extends Error {\n constructor(\n message: string,\n public readonly operation: 'push' | 'pull' | 'connect',\n public readonly recoverable: boolean\n ) {\n super(message)\n this.name = 'SyncError'\n Object.setPrototypeOf(this, SyncError.prototype)\n }\n}\n\n/**\n * Type guard to check if an error is an APIError\n */\nexport function isAPIError(error: unknown): error is APIError {\n return error instanceof APIError\n}\n\n/**\n * Type guard to check if an error is a NetworkError\n */\nexport function isNetworkError(error: unknown): error is NetworkError {\n return error instanceof NetworkError\n}\n\n/**\n * Type guard to check if an error is a ValidationError\n */\nexport function isValidationError(error: unknown): error is ValidationError {\n return error instanceof ValidationError\n}\n\n/**\n * Type guard to check if an error is a SyncError\n */\nexport function isSyncError(error: unknown): error is SyncError {\n return error instanceof SyncError\n}\n"]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { cn } from './chunk-Y52IEYVM.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var DOErrorBoundary = class extends React.Component {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
super(props);
|
|
8
|
+
this.state = { hasError: false, error: null };
|
|
9
|
+
}
|
|
10
|
+
static getDerivedStateFromError(error) {
|
|
11
|
+
return { hasError: true, error };
|
|
12
|
+
}
|
|
13
|
+
componentDidCatch(error, errorInfo) {
|
|
14
|
+
console.error("DOErrorBoundary caught error:", error, errorInfo);
|
|
15
|
+
if (this.props.onError) {
|
|
16
|
+
this.props.onError(error, errorInfo);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
componentDidUpdate(prevProps) {
|
|
20
|
+
if (this.state.hasError && prevProps.resetKey !== this.props.resetKey) {
|
|
21
|
+
this.reset();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
reset = () => {
|
|
25
|
+
this.setState({ hasError: false, error: null });
|
|
26
|
+
};
|
|
27
|
+
render() {
|
|
28
|
+
if (this.state.hasError) {
|
|
29
|
+
const { fallback, className } = this.props;
|
|
30
|
+
const error = this.state.error ?? new Error("Unknown error");
|
|
31
|
+
if (typeof fallback === "function") {
|
|
32
|
+
return fallback(error, this.reset);
|
|
33
|
+
}
|
|
34
|
+
if (fallback) {
|
|
35
|
+
return fallback;
|
|
36
|
+
}
|
|
37
|
+
return /* @__PURE__ */ jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
className: cn(
|
|
41
|
+
"p-6 rounded-lg bg-destructive/10 border border-destructive/20",
|
|
42
|
+
className
|
|
43
|
+
),
|
|
44
|
+
role: "alert",
|
|
45
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
46
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-0.5", children: /* @__PURE__ */ jsx(
|
|
47
|
+
"svg",
|
|
48
|
+
{
|
|
49
|
+
className: "h-5 w-5 text-destructive",
|
|
50
|
+
viewBox: "0 0 20 20",
|
|
51
|
+
fill: "currentColor",
|
|
52
|
+
"aria-hidden": "true",
|
|
53
|
+
children: /* @__PURE__ */ jsx(
|
|
54
|
+
"path",
|
|
55
|
+
{
|
|
56
|
+
fillRule: "evenodd",
|
|
57
|
+
d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z",
|
|
58
|
+
clipRule: "evenodd"
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
) }),
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
64
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-destructive", children: "Something went wrong" }),
|
|
65
|
+
error.message && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: error.message }),
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
onClick: this.reset,
|
|
71
|
+
className: "mt-4 inline-flex items-center rounded-md bg-destructive px-3 py-2 text-sm font-semibold text-destructive-foreground shadow-sm hover:bg-destructive/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-destructive",
|
|
72
|
+
children: "Try again"
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
] })
|
|
76
|
+
] })
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return this.props.children;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
function useErrorBoundary() {
|
|
84
|
+
const [error, setError] = React.useState(null);
|
|
85
|
+
if (error) {
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
showBoundary: setError
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { DOErrorBoundary, useErrorBoundary };
|
|
94
|
+
//# sourceMappingURL=chunk-EQVOEEQO.js.map
|
|
95
|
+
//# sourceMappingURL=chunk-EQVOEEQO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/error-boundary.tsx"],"names":[],"mappings":"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","file":"chunk-EQVOEEQO.js","sourcesContent":["'use client'\n\n/**\n * Error Boundary Component for @mdxui/do\n *\n * Catches JavaScript errors anywhere in the child component tree,\n * logs errors, and displays a fallback UI.\n *\n * @example\n * ```tsx\n * <DOErrorBoundary>\n * <ThingsList />\n * </DOErrorBoundary>\n *\n * // With custom fallback\n * <DOErrorBoundary fallback={<CustomErrorUI />}>\n * <Dashboard />\n * </DOErrorBoundary>\n *\n * // With fallback function\n * <DOErrorBoundary\n * fallback={(error, reset) => (\n * <div>\n * <p>Error: {error.message}</p>\n * <button onClick={reset}>Retry</button>\n * </div>\n * )}\n * >\n * <DataView />\n * </DOErrorBoundary>\n * ```\n */\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\n\nexport interface DOErrorBoundaryProps {\n /** Child components to render */\n children: React.ReactNode\n /** Custom fallback UI - can be ReactNode or render function */\n fallback?: React.ReactNode | ((error: Error, reset: () => void) => React.ReactNode)\n /** Callback when error is caught */\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void\n /** Key that triggers reset when changed (useful for route changes) */\n resetKey?: string | number\n /** Additional className for the error container */\n className?: string\n}\n\ninterface DOErrorBoundaryState {\n hasError: boolean\n error: Error | null\n}\n\n/**\n * DOErrorBoundary - Catches and handles errors in child components\n *\n * Features:\n * - Catches render errors in child tree\n * - Displays customizable error UI\n * - Provides retry functionality\n * - Supports error callbacks for logging\n * - Resets on resetKey change (e.g., route changes)\n */\nexport class DOErrorBoundary extends React.Component<\n DOErrorBoundaryProps,\n DOErrorBoundaryState\n> {\n constructor(props: DOErrorBoundaryProps) {\n super(props)\n this.state = { hasError: false, error: null }\n }\n\n static getDerivedStateFromError(error: Error): DOErrorBoundaryState {\n return { hasError: true, error }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n // Log error to console\n console.error('DOErrorBoundary caught error:', error, errorInfo)\n\n // Call optional error callback\n if (this.props.onError) {\n this.props.onError(error, errorInfo)\n }\n }\n\n componentDidUpdate(prevProps: DOErrorBoundaryProps): void {\n // Reset error state when resetKey changes\n if (\n this.state.hasError &&\n prevProps.resetKey !== this.props.resetKey\n ) {\n this.reset()\n }\n }\n\n reset = (): void => {\n this.setState({ hasError: false, error: null })\n }\n\n render(): React.ReactNode {\n if (this.state.hasError) {\n const { fallback, className } = this.props\n const error = this.state.error ?? new Error('Unknown error')\n\n // Render function fallback\n if (typeof fallback === 'function') {\n return fallback(error, this.reset)\n }\n\n // ReactNode fallback\n if (fallback) {\n return fallback\n }\n\n // Default error UI\n return (\n <div\n className={cn(\n 'p-6 rounded-lg bg-destructive/10 border border-destructive/20',\n className\n )}\n role=\"alert\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-shrink-0 mt-0.5\">\n <svg\n className=\"h-5 w-5 text-destructive\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n <div className=\"flex-1\">\n <h2 className=\"text-sm font-semibold text-destructive\">\n Something went wrong\n </h2>\n {error.message && (\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {error.message}\n </p>\n )}\n <button\n type=\"button\"\n onClick={this.reset}\n className=\"mt-4 inline-flex items-center rounded-md bg-destructive px-3 py-2 text-sm font-semibold text-destructive-foreground shadow-sm hover:bg-destructive/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-destructive\"\n >\n Try again\n </button>\n </div>\n </div>\n </div>\n )\n }\n\n return this.props.children\n }\n}\n\n/**\n * Hook to manually trigger error boundary\n * Useful for catching errors in async operations\n */\nexport function useErrorBoundary() {\n const [error, setError] = React.useState<Error | null>(null)\n\n if (error) {\n throw error\n }\n\n return {\n showBoundary: setError,\n }\n}\n\nexport default DOErrorBoundary\n"]}
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { deriveRpcUrl, useHealthCheck } from './chunk-OWEAW4U6.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
4
|
+
export { useQueryClient } from '@tanstack/react-query';
|
|
5
|
+
import { newHttpBatchRpcSession } from 'capnweb';
|
|
6
|
+
import { DataProviderContext } from '@mdxui/app';
|
|
7
|
+
import { jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
// src/lib/json-rpc-client.ts
|
|
10
|
+
var endpointCache = /* @__PURE__ */ new Map();
|
|
11
|
+
function createJsonRpcClient(baseUrl) {
|
|
12
|
+
const rpcUrl = baseUrl.replace(/\/$/, "").replace(/\/rpc$/, "");
|
|
13
|
+
async function rpcCall(method, args = []) {
|
|
14
|
+
const response = await fetch(`${rpcUrl}/rpc`, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: { "Content-Type": "application/json" },
|
|
17
|
+
body: JSON.stringify({ method, args })
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
21
|
+
}
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
if (data.error) {
|
|
24
|
+
throw new Error(data.error.message || data.error.code);
|
|
25
|
+
}
|
|
26
|
+
return data.result;
|
|
27
|
+
}
|
|
28
|
+
async function restCall(path, options) {
|
|
29
|
+
const response = await fetch(`${rpcUrl}${path}`, {
|
|
30
|
+
...options,
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
...options?.headers
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
const method = options?.method?.toUpperCase() ?? "GET";
|
|
38
|
+
if (response.status === 404 && method === "GET") {
|
|
39
|
+
return { data: [], count: 0 };
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
42
|
+
}
|
|
43
|
+
return response.json();
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
/**
|
|
47
|
+
* Namespace operations
|
|
48
|
+
*/
|
|
49
|
+
Namespace: {
|
|
50
|
+
async list(_params) {
|
|
51
|
+
return [{ id: "default", name: "default" }];
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Schema operations
|
|
56
|
+
*/
|
|
57
|
+
Schema: {
|
|
58
|
+
async discover(_params) {
|
|
59
|
+
const schemas = await rpcCall("schemas.list", []);
|
|
60
|
+
return {
|
|
61
|
+
namespaces: ["default"],
|
|
62
|
+
types: schemas,
|
|
63
|
+
schemas
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
async get(params) {
|
|
67
|
+
const result = await rpcCall("schemas.get", [params.type]);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Thing operations (maps to REST endpoints)
|
|
73
|
+
*/
|
|
74
|
+
Thing: {
|
|
75
|
+
async types(params) {
|
|
76
|
+
try {
|
|
77
|
+
const schemas = await rpcCall("schemas.list", []);
|
|
78
|
+
let validEndpoints = endpointCache.get(rpcUrl);
|
|
79
|
+
if (!validEndpoints) {
|
|
80
|
+
validEndpoints = /* @__PURE__ */ new Set();
|
|
81
|
+
const probeResults = await Promise.all(
|
|
82
|
+
schemas.map(async (type) => {
|
|
83
|
+
const endpoint = getEndpointForType(type);
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(`${rpcUrl}${endpoint}`, { method: "HEAD" });
|
|
86
|
+
return { type, exists: response.ok };
|
|
87
|
+
} catch {
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetch(`${rpcUrl}${endpoint}?limit=0`);
|
|
90
|
+
return { type, exists: response.ok };
|
|
91
|
+
} catch {
|
|
92
|
+
return { type, exists: false };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
for (const { type, exists } of probeResults) {
|
|
98
|
+
if (exists) {
|
|
99
|
+
validEndpoints.add(type);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
endpointCache.set(rpcUrl, validEndpoints);
|
|
103
|
+
}
|
|
104
|
+
return Array.from(validEndpoints).map((name) => ({
|
|
105
|
+
name,
|
|
106
|
+
ns: params.ns || "default"
|
|
107
|
+
}));
|
|
108
|
+
} catch {
|
|
109
|
+
return ["Noun", "Verb", "Action", "Function"].map((name) => ({
|
|
110
|
+
name,
|
|
111
|
+
ns: params.ns || "default"
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
async list(params) {
|
|
116
|
+
const endpoint = getEndpointForType(params.type || "Thing");
|
|
117
|
+
const response = await restCall(endpoint);
|
|
118
|
+
const items = response.data || response.items || response.result || [];
|
|
119
|
+
return {
|
|
120
|
+
data: items,
|
|
121
|
+
total: response.count ?? items.length
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
async get(params) {
|
|
125
|
+
const endpoint = getEndpointForType(params.type);
|
|
126
|
+
const response = await restCall(`${endpoint}/${params.id}`);
|
|
127
|
+
return response.data;
|
|
128
|
+
},
|
|
129
|
+
async create(params) {
|
|
130
|
+
const endpoint = getEndpointForType(params.type);
|
|
131
|
+
const response = await restCall(endpoint, {
|
|
132
|
+
method: "POST",
|
|
133
|
+
body: JSON.stringify(params.data)
|
|
134
|
+
});
|
|
135
|
+
return response.data;
|
|
136
|
+
},
|
|
137
|
+
async update(params) {
|
|
138
|
+
const endpoint = getEndpointForType(params.type);
|
|
139
|
+
const response = await restCall(`${endpoint}/${params.id}`, {
|
|
140
|
+
method: "PUT",
|
|
141
|
+
body: JSON.stringify(params.data)
|
|
142
|
+
});
|
|
143
|
+
return response.data;
|
|
144
|
+
},
|
|
145
|
+
async delete(params) {
|
|
146
|
+
const endpoint = getEndpointForType(params.type);
|
|
147
|
+
await restCall(`${endpoint}/${params.id}`, { method: "DELETE" });
|
|
148
|
+
return { success: true };
|
|
149
|
+
},
|
|
150
|
+
async versions(_params) {
|
|
151
|
+
return [];
|
|
152
|
+
},
|
|
153
|
+
async stats(_params) {
|
|
154
|
+
let validEndpoints = endpointCache.get(rpcUrl);
|
|
155
|
+
if (!validEndpoints) {
|
|
156
|
+
await this.types({ ns: _params.ns });
|
|
157
|
+
validEndpoints = endpointCache.get(rpcUrl) || /* @__PURE__ */ new Set();
|
|
158
|
+
}
|
|
159
|
+
const types = Array.from(validEndpoints);
|
|
160
|
+
const results = await Promise.all(
|
|
161
|
+
types.map(async (type) => {
|
|
162
|
+
const endpoint = getEndpointForType(type);
|
|
163
|
+
const response = await restCall(endpoint).catch(() => ({ count: 0 }));
|
|
164
|
+
return { type, count: response.count || 0 };
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
const byType = {};
|
|
168
|
+
let total = 0;
|
|
169
|
+
for (const { type, count } of results) {
|
|
170
|
+
byType[type] = count;
|
|
171
|
+
total += count;
|
|
172
|
+
}
|
|
173
|
+
return { total, byType };
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
/**
|
|
177
|
+
* SQL operations
|
|
178
|
+
*/
|
|
179
|
+
SQL: {
|
|
180
|
+
async execute(params) {
|
|
181
|
+
const startTime = Date.now();
|
|
182
|
+
try {
|
|
183
|
+
const result = await rpcCall("sql.execute", [params.query, params.params || []]);
|
|
184
|
+
return {
|
|
185
|
+
rows: result.rows ?? [],
|
|
186
|
+
columns: result.columns ?? [],
|
|
187
|
+
rowsAffected: result.rowsAffected,
|
|
188
|
+
executionTimeMs: result.executionTimeMs ?? Date.now() - startTime
|
|
189
|
+
};
|
|
190
|
+
} catch (rpcError) {
|
|
191
|
+
const errorMessage = rpcError instanceof Error ? rpcError.message : String(rpcError);
|
|
192
|
+
const isNotSupported = errorMessage.includes("not found") || errorMessage.includes("not supported") || errorMessage.includes("unknown method");
|
|
193
|
+
try {
|
|
194
|
+
const response = await restCall("/sql", {
|
|
195
|
+
method: "POST",
|
|
196
|
+
body: JSON.stringify({ query: params.query, params: params.params })
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
rows: response.rows ?? [],
|
|
200
|
+
columns: response.columns ?? [],
|
|
201
|
+
rowsAffected: response.rowsAffected,
|
|
202
|
+
executionTimeMs: Date.now() - startTime
|
|
203
|
+
};
|
|
204
|
+
} catch (restError) {
|
|
205
|
+
if (isNotSupported) {
|
|
206
|
+
throw new Error(
|
|
207
|
+
"SQL execution is not supported by this server. The server does not expose sql.execute RPC method or /sql REST endpoint."
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
throw restError;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
// Required for interface compatibility
|
|
216
|
+
dup: () => createJsonRpcClient(baseUrl),
|
|
217
|
+
onRpcBroken: (_callback) => {
|
|
218
|
+
},
|
|
219
|
+
[Symbol.dispose]: () => {
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function getEndpointForType(type) {
|
|
224
|
+
const typeMap = {
|
|
225
|
+
Noun: "/nouns",
|
|
226
|
+
Verb: "/verbs",
|
|
227
|
+
Action: "/actions",
|
|
228
|
+
Function: "/functions",
|
|
229
|
+
Event: "/events",
|
|
230
|
+
Relationship: "/relationships",
|
|
231
|
+
Thing: "/things",
|
|
232
|
+
Workflow: "/workflows"
|
|
233
|
+
};
|
|
234
|
+
return typeMap[type] || `/${type.toLowerCase()}s`;
|
|
235
|
+
}
|
|
236
|
+
function $JsonRpcContext(url) {
|
|
237
|
+
return createJsonRpcClient(url);
|
|
238
|
+
}
|
|
239
|
+
function createCapnwebClient(baseUrl) {
|
|
240
|
+
const rpcUrl = `${baseUrl.replace(/\/$/, "").replace(/\/rpc$/, "")}/rpc`;
|
|
241
|
+
const session = newHttpBatchRpcSession(rpcUrl);
|
|
242
|
+
const rpc = session;
|
|
243
|
+
return {
|
|
244
|
+
/**
|
|
245
|
+
* Namespace operations
|
|
246
|
+
*/
|
|
247
|
+
Namespace: {
|
|
248
|
+
async list(_params) {
|
|
249
|
+
return [{ id: "default", name: "default" }];
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
/**
|
|
253
|
+
* Schema operations
|
|
254
|
+
*/
|
|
255
|
+
Schema: {
|
|
256
|
+
async discover(_params) {
|
|
257
|
+
try {
|
|
258
|
+
const schemas = await rpc.getSchemas();
|
|
259
|
+
return {
|
|
260
|
+
namespaces: ["default"],
|
|
261
|
+
types: schemas ?? [],
|
|
262
|
+
schemas: schemas ?? []
|
|
263
|
+
};
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error("[@mdxui/do] Failed to get schemas:", error);
|
|
266
|
+
return { namespaces: ["default"], types: [], schemas: [] };
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
async get(params) {
|
|
270
|
+
try {
|
|
271
|
+
const result = await rpc.getSchema(params.type);
|
|
272
|
+
return result;
|
|
273
|
+
} catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
/**
|
|
279
|
+
* Thing operations
|
|
280
|
+
*/
|
|
281
|
+
Thing: {
|
|
282
|
+
async types(params) {
|
|
283
|
+
try {
|
|
284
|
+
const schemas = await rpc.getSchemas();
|
|
285
|
+
return (schemas ?? []).map((name) => ({
|
|
286
|
+
name,
|
|
287
|
+
ns: params.ns || "default"
|
|
288
|
+
}));
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error("[@mdxui/do] Failed to get types:", error);
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
async list(params) {
|
|
295
|
+
try {
|
|
296
|
+
const options = {};
|
|
297
|
+
if (params.type) options.type = params.type;
|
|
298
|
+
if (params.limit !== void 0) options.limit = params.limit;
|
|
299
|
+
if (params.offset !== void 0) options.offset = params.offset;
|
|
300
|
+
const result = await rpc.list(options);
|
|
301
|
+
if (Array.isArray(result)) {
|
|
302
|
+
return { data: result, total: result.length };
|
|
303
|
+
}
|
|
304
|
+
if (result) {
|
|
305
|
+
const items = result.data || result.items || result.result || [];
|
|
306
|
+
return { data: items, total: result.count ?? items.length };
|
|
307
|
+
}
|
|
308
|
+
return { data: [], total: 0 };
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.error("[@mdxui/do] Failed to list things:", error);
|
|
311
|
+
return { data: [], total: 0 };
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
async get(params) {
|
|
315
|
+
try {
|
|
316
|
+
const result = await rpc.get({ type: params.type, id: params.id });
|
|
317
|
+
return result;
|
|
318
|
+
} catch {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
async create(params) {
|
|
323
|
+
const result = await rpc.create({ type: params.type, data: params.data });
|
|
324
|
+
return result;
|
|
325
|
+
},
|
|
326
|
+
async update(params) {
|
|
327
|
+
const result = await rpc.update({ type: params.type, id: params.id, data: params.data });
|
|
328
|
+
return result;
|
|
329
|
+
},
|
|
330
|
+
async delete(params) {
|
|
331
|
+
await rpc.delete({ type: params.type, id: params.id });
|
|
332
|
+
return { success: true };
|
|
333
|
+
},
|
|
334
|
+
async versions(_params) {
|
|
335
|
+
return [];
|
|
336
|
+
},
|
|
337
|
+
async stats(_params) {
|
|
338
|
+
try {
|
|
339
|
+
const options = {};
|
|
340
|
+
if (_params.type) options.type = _params.type;
|
|
341
|
+
const result = await rpc.getStats(options);
|
|
342
|
+
return {
|
|
343
|
+
total: result?.total ?? 0,
|
|
344
|
+
byType: result?.byType ?? {}
|
|
345
|
+
};
|
|
346
|
+
} catch (error) {
|
|
347
|
+
console.error("[@mdxui/do] Failed to get stats:", error);
|
|
348
|
+
return { total: 0, byType: {} };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
/**
|
|
353
|
+
* SQL operations (not supported by capnweb servers)
|
|
354
|
+
*/
|
|
355
|
+
SQL: {
|
|
356
|
+
async execute(_params) {
|
|
357
|
+
throw new Error("SQL execution is not supported by this server");
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
// Required for interface compatibility
|
|
361
|
+
dup: () => createCapnwebClient(baseUrl),
|
|
362
|
+
onRpcBroken: (callback) => {
|
|
363
|
+
if ("onRpcBroken" in session && typeof session.onRpcBroken === "function") {
|
|
364
|
+
session.onRpcBroken(callback);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
[Symbol.dispose]: () => {
|
|
368
|
+
if (Symbol.dispose in session) {
|
|
369
|
+
session[Symbol.dispose]();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function $CapnwebContext(url) {
|
|
375
|
+
return createCapnwebClient(url);
|
|
376
|
+
}
|
|
377
|
+
function createQueryClient() {
|
|
378
|
+
return new QueryClient({
|
|
379
|
+
defaultOptions: {
|
|
380
|
+
queries: {
|
|
381
|
+
// Stale time: 30 seconds (data considered fresh)
|
|
382
|
+
staleTime: 30 * 1e3,
|
|
383
|
+
// Cache time: 5 minutes (keep in cache after unmount)
|
|
384
|
+
gcTime: 5 * 60 * 1e3,
|
|
385
|
+
// Retry failed requests 1 time
|
|
386
|
+
retry: 1,
|
|
387
|
+
// Refetch on window focus for fresh data
|
|
388
|
+
refetchOnWindowFocus: true
|
|
389
|
+
},
|
|
390
|
+
mutations: {
|
|
391
|
+
// Retry mutations once on failure
|
|
392
|
+
retry: 1
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
var DOContext = React.createContext(null);
|
|
398
|
+
function useDO() {
|
|
399
|
+
const context = React.useContext(DOContext);
|
|
400
|
+
if (!context) {
|
|
401
|
+
throw new Error("useDO must be used within a DOProvider");
|
|
402
|
+
}
|
|
403
|
+
return context;
|
|
404
|
+
}
|
|
405
|
+
function useDOClient() {
|
|
406
|
+
const { client } = useDO();
|
|
407
|
+
return client;
|
|
408
|
+
}
|
|
409
|
+
function useDOUrls() {
|
|
410
|
+
const { rpcUrl, config } = useDO();
|
|
411
|
+
return {
|
|
412
|
+
rpcUrl,
|
|
413
|
+
apiEndpoint: config.apiEndpoint
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function useSyncStatus() {
|
|
417
|
+
return "disconnected";
|
|
418
|
+
}
|
|
419
|
+
function DOProvider({
|
|
420
|
+
config,
|
|
421
|
+
initialNamespace = "default",
|
|
422
|
+
userId,
|
|
423
|
+
children,
|
|
424
|
+
queryClient: providedQueryClient
|
|
425
|
+
}) {
|
|
426
|
+
const [namespace, setNamespace] = React.useState(initialNamespace);
|
|
427
|
+
const rpcUrl = config.rpcUrl ?? deriveRpcUrl(config.apiEndpoint);
|
|
428
|
+
const client = React.useMemo(() => {
|
|
429
|
+
const clientType = config.clientType ?? "capnweb";
|
|
430
|
+
if (process.env.NODE_ENV === "development") {
|
|
431
|
+
const url = clientType === "json-rpc" ? config.apiEndpoint : rpcUrl;
|
|
432
|
+
console.log(`[@mdxui/do] Initializing ${clientType} client with URL: ${url}`);
|
|
433
|
+
}
|
|
434
|
+
if (clientType === "json-rpc") {
|
|
435
|
+
return $JsonRpcContext(config.apiEndpoint);
|
|
436
|
+
}
|
|
437
|
+
return $CapnwebContext(rpcUrl);
|
|
438
|
+
}, [rpcUrl, config.apiEndpoint, config.clientType]);
|
|
439
|
+
const healthCheckResult = useHealthCheck({
|
|
440
|
+
apiEndpoint: config.apiEndpoint,
|
|
441
|
+
authToken: config.authToken,
|
|
442
|
+
requestTimeout: config.requestTimeout,
|
|
443
|
+
healthCheckRetries: config.healthCheckRetries
|
|
444
|
+
});
|
|
445
|
+
const isConnected = config.skipHealthCheck ? true : healthCheckResult.isConnected;
|
|
446
|
+
const connectionError = config.skipHealthCheck ? void 0 : healthCheckResult.connectionError;
|
|
447
|
+
const [queryClient] = React.useState(() => providedQueryClient ?? createQueryClient());
|
|
448
|
+
const value = React.useMemo(
|
|
449
|
+
() => ({
|
|
450
|
+
config,
|
|
451
|
+
namespace,
|
|
452
|
+
setNamespace,
|
|
453
|
+
userId,
|
|
454
|
+
isConnected,
|
|
455
|
+
connectionError,
|
|
456
|
+
rpcUrl,
|
|
457
|
+
client
|
|
458
|
+
}),
|
|
459
|
+
[config, namespace, userId, isConnected, connectionError, rpcUrl, client]
|
|
460
|
+
);
|
|
461
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(DOContext.Provider, { value, children }) });
|
|
462
|
+
}
|
|
463
|
+
function useDataProviderSafe() {
|
|
464
|
+
return React.useContext(DataProviderContext);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export { DOProvider, useDO, useDOClient, useDOUrls, useDataProviderSafe, useSyncStatus };
|
|
468
|
+
//# sourceMappingURL=chunk-FO3N7SXV.js.map
|
|
469
|
+
//# sourceMappingURL=chunk-FO3N7SXV.js.map
|