@iota-uz/sdk 0.1.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/LICENSE +201 -0
- package/README.MD +164 -0
- package/assets/fonts/Actay/Actay-Regular.otf +0 -0
- package/assets/fonts/Actay/Actay-RegularItalic.otf +0 -0
- package/assets/fonts/Actay/ActayCondensed-Thin.otf +0 -0
- package/assets/fonts/Actay/ActayCondensed-ThinItalic.otf +0 -0
- package/assets/fonts/Actay/ActayWide-Bold.otf +0 -0
- package/assets/fonts/Actay/ActayWide-BoldItalic.otf +0 -0
- package/assets/fonts/Gilroy/Gilroy-Black.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-BlackItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Bold.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-BoldItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Extrabold.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-ExtraboldItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Heavy.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-HeavyItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Light.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-LightItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Medium.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-MediumItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Regular.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-RegularItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Semibold.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-SemiboldItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-Thin.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-ThinItalic.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-UltraLight.woff2 +0 -0
- package/assets/fonts/Gilroy/Gilroy-UltraLightItalic.woff2 +0 -0
- package/assets/fonts/Inter.var.woff2 +0 -0
- package/dist/bichat/index.cjs +3033 -0
- package/dist/bichat/index.cjs.map +1 -0
- package/dist/bichat/index.css +139 -0
- package/dist/bichat/index.css.map +1 -0
- package/dist/bichat/index.d.cts +1081 -0
- package/dist/bichat/index.d.ts +1081 -0
- package/dist/bichat/index.mjs +2959 -0
- package/dist/bichat/index.mjs.map +1 -0
- package/dist/bichat/styles.css +160 -0
- package/dist/index.cjs +191 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +237 -0
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +178 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +70 -0
- package/tailwind/create-config.cjs +142 -0
- package/tailwind/iota.css +1106 -0
- package/tailwind/main.css +2 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TypeScript type definitions for IOTA SDK Applet Core
|
|
6
|
+
* Matches Go backend types from pkg/applet/types.go
|
|
7
|
+
*/
|
|
8
|
+
interface InitialContext {
|
|
9
|
+
user: UserContext;
|
|
10
|
+
tenant: TenantContext;
|
|
11
|
+
locale: LocaleContext;
|
|
12
|
+
config: AppConfig;
|
|
13
|
+
route: RouteContext;
|
|
14
|
+
session: SessionContext;
|
|
15
|
+
error: ErrorContext | null;
|
|
16
|
+
extensions?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
interface UserContext {
|
|
19
|
+
id: number;
|
|
20
|
+
email: string;
|
|
21
|
+
firstName: string;
|
|
22
|
+
lastName: string;
|
|
23
|
+
permissions: string[];
|
|
24
|
+
}
|
|
25
|
+
interface TenantContext {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
}
|
|
29
|
+
interface LocaleContext {
|
|
30
|
+
language: string;
|
|
31
|
+
translations: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
interface AppConfig {
|
|
34
|
+
graphQLEndpoint?: string;
|
|
35
|
+
streamEndpoint?: string;
|
|
36
|
+
restEndpoint?: string;
|
|
37
|
+
}
|
|
38
|
+
interface RouteContext {
|
|
39
|
+
path: string;
|
|
40
|
+
params: Record<string, string>;
|
|
41
|
+
query: Record<string, string>;
|
|
42
|
+
}
|
|
43
|
+
interface SessionContext {
|
|
44
|
+
expiresAt: number;
|
|
45
|
+
refreshURL: string;
|
|
46
|
+
csrfToken: string;
|
|
47
|
+
}
|
|
48
|
+
interface ErrorContext {
|
|
49
|
+
supportEmail?: string;
|
|
50
|
+
debugMode: boolean;
|
|
51
|
+
errorCodes?: Record<string, string>;
|
|
52
|
+
retryConfig?: RetryConfig;
|
|
53
|
+
}
|
|
54
|
+
interface RetryConfig {
|
|
55
|
+
maxAttempts: number;
|
|
56
|
+
backoffMs: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Hook return types
|
|
60
|
+
*/
|
|
61
|
+
interface TranslationHook {
|
|
62
|
+
t: (key: string, params?: Record<string, unknown>) => string;
|
|
63
|
+
language: string;
|
|
64
|
+
}
|
|
65
|
+
interface PermissionsHook {
|
|
66
|
+
hasPermission: (permission: string) => boolean;
|
|
67
|
+
hasAnyPermission: (...permissions: string[]) => boolean;
|
|
68
|
+
permissions: string[];
|
|
69
|
+
}
|
|
70
|
+
interface SessionHook {
|
|
71
|
+
isExpiringSoon: boolean;
|
|
72
|
+
refreshSession: () => Promise<void>;
|
|
73
|
+
csrfToken: string;
|
|
74
|
+
expiresAt: number;
|
|
75
|
+
}
|
|
76
|
+
interface StreamingHook {
|
|
77
|
+
isStreaming: boolean;
|
|
78
|
+
processStream: <T>(generator: AsyncGenerator<T>, onChunk: (chunk: T) => void, signal?: AbortSignal) => Promise<void>;
|
|
79
|
+
cancel: () => void;
|
|
80
|
+
reset: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface AppletProviderProps {
|
|
84
|
+
children: ReactNode;
|
|
85
|
+
windowKey: string;
|
|
86
|
+
context?: InitialContext;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* AppletProvider reads context from window global and provides it to hooks.
|
|
90
|
+
*
|
|
91
|
+
* Usage:
|
|
92
|
+
* <AppletProvider windowKey="__BICHAT_CONTEXT__">
|
|
93
|
+
* <App />
|
|
94
|
+
* </AppletProvider>
|
|
95
|
+
*/
|
|
96
|
+
declare function AppletProvider({ children, windowKey, context }: AppletProviderProps): react_jsx_runtime.JSX.Element;
|
|
97
|
+
/**
|
|
98
|
+
* useAppletContext provides access to the full applet context.
|
|
99
|
+
* Use specialized hooks (useUser, useConfig, etc.) for specific context parts.
|
|
100
|
+
*/
|
|
101
|
+
declare function useAppletContext$1<T = InitialContext>(): T;
|
|
102
|
+
|
|
103
|
+
interface ConfigProviderProps {
|
|
104
|
+
children: ReactNode;
|
|
105
|
+
config: InitialContext;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* ConfigProvider accepts context configuration via props.
|
|
109
|
+
*
|
|
110
|
+
* Usage:
|
|
111
|
+
* <ConfigProvider config={initialContext}>
|
|
112
|
+
* <App />
|
|
113
|
+
* </ConfigProvider>
|
|
114
|
+
*/
|
|
115
|
+
declare function ConfigProvider({ children, config }: ConfigProviderProps): react_jsx_runtime.JSX.Element;
|
|
116
|
+
/**
|
|
117
|
+
* useConfigContext provides access to the applet context when using ConfigProvider.
|
|
118
|
+
*/
|
|
119
|
+
declare function useConfigContext<T = InitialContext>(): T;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* useAppletContext provides direct access to the window global context.
|
|
123
|
+
* This is a standalone version that doesn't require AppletProvider.
|
|
124
|
+
*
|
|
125
|
+
* Usage:
|
|
126
|
+
* const context = useAppletContext('__BICHAT_CONTEXT__')
|
|
127
|
+
*
|
|
128
|
+
* Note: Prefer using AppletProvider + context hooks for better type safety
|
|
129
|
+
* and testability. Use this hook only when provider setup is not possible.
|
|
130
|
+
*/
|
|
131
|
+
declare function useAppletContext<T = InitialContext>(windowKey: string): T;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* useConfig provides access to applet configuration (endpoints, etc.)
|
|
135
|
+
*
|
|
136
|
+
* Usage:
|
|
137
|
+
* const { graphQLEndpoint, streamEndpoint } = useConfig()
|
|
138
|
+
*/
|
|
139
|
+
declare function useConfig(): AppConfig;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* useUser provides access to current user information.
|
|
143
|
+
*
|
|
144
|
+
* Usage:
|
|
145
|
+
* const { id, email, firstName, lastName, permissions } = useUser()
|
|
146
|
+
*/
|
|
147
|
+
declare function useUser(): UserContext;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* usePermissions provides permission checking utilities.
|
|
151
|
+
* All user permissions are automatically passed from backend.
|
|
152
|
+
*
|
|
153
|
+
* Usage:
|
|
154
|
+
* const { hasPermission, hasAnyPermission } = usePermissions()
|
|
155
|
+
*
|
|
156
|
+
* if (hasPermission('bichat.access')) {
|
|
157
|
+
* // User has bichat access
|
|
158
|
+
* }
|
|
159
|
+
*
|
|
160
|
+
* if (hasAnyPermission('finance.view', 'finance.edit')) {
|
|
161
|
+
* // User has at least one of these permissions
|
|
162
|
+
* }
|
|
163
|
+
*/
|
|
164
|
+
declare function usePermissions(): PermissionsHook;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* useTranslation provides i18n translation utilities.
|
|
168
|
+
* All translations are automatically passed from backend locale bundle.
|
|
169
|
+
*
|
|
170
|
+
* Usage:
|
|
171
|
+
* const { t, language } = useTranslation()
|
|
172
|
+
*
|
|
173
|
+
* // Simple translation
|
|
174
|
+
* t('BiChat.Title') // Returns translated text
|
|
175
|
+
*
|
|
176
|
+
* // Translation with interpolation
|
|
177
|
+
* t('Common.WelcomeMessage', { name: 'John' })
|
|
178
|
+
* // If translation is "Welcome {name}!" -> Returns "Welcome John!"
|
|
179
|
+
*
|
|
180
|
+
* React uses same keys as Go backend:
|
|
181
|
+
* Go: pageCtx.T("BiChat.Title")
|
|
182
|
+
* React: t("BiChat.Title")
|
|
183
|
+
*/
|
|
184
|
+
declare function useTranslation(): TranslationHook;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* useSession provides session and authentication handling utilities.
|
|
188
|
+
*
|
|
189
|
+
* Usage:
|
|
190
|
+
* const { isExpiringSoon, refreshSession, csrfToken } = useSession()
|
|
191
|
+
*
|
|
192
|
+
* // Check if session is expiring soon (5 min buffer)
|
|
193
|
+
* if (isExpiringSoon) {
|
|
194
|
+
* await refreshSession()
|
|
195
|
+
* }
|
|
196
|
+
*
|
|
197
|
+
* // Include CSRF token in requests
|
|
198
|
+
* fetch('/api/endpoint', {
|
|
199
|
+
* headers: { 'X-CSRF-Token': csrfToken }
|
|
200
|
+
* })
|
|
201
|
+
*/
|
|
202
|
+
declare function useSession(): SessionHook;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* useRoute provides access to the current route context.
|
|
206
|
+
* Route context is initialized from the backend and includes path, params, and query.
|
|
207
|
+
*
|
|
208
|
+
* Usage:
|
|
209
|
+
* const { path, params, query } = useRoute()
|
|
210
|
+
*
|
|
211
|
+
* // Example values:
|
|
212
|
+
* // path: "/sessions/123"
|
|
213
|
+
* // params: { id: "123" }
|
|
214
|
+
* // query: { tab: "history" }
|
|
215
|
+
*/
|
|
216
|
+
declare function useRoute(): RouteContext;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* useStreaming provides SSE (Server-Sent Events) streaming utilities with cancellation support.
|
|
220
|
+
*
|
|
221
|
+
* Usage:
|
|
222
|
+
* const { isStreaming, processStream, cancel, reset } = useStreaming()
|
|
223
|
+
*
|
|
224
|
+
* // Process async generator stream
|
|
225
|
+
* await processStream(messageStream, (chunk) => {
|
|
226
|
+
* console.log('Received:', chunk)
|
|
227
|
+
* })
|
|
228
|
+
*
|
|
229
|
+
* // Cancel ongoing stream
|
|
230
|
+
* cancel()
|
|
231
|
+
*
|
|
232
|
+
* // Reset state after stream completion
|
|
233
|
+
* reset()
|
|
234
|
+
*/
|
|
235
|
+
declare function useStreaming(): StreamingHook;
|
|
236
|
+
|
|
237
|
+
export { type AppConfig, AppletProvider, ConfigProvider, type InitialContext, type LocaleContext, type PermissionsHook, type RouteContext, type SessionContext, type SessionHook, type StreamingHook, type TenantContext, type TranslationHook, type UserContext, useAppletContext$1 as useAppletContext, useAppletContext as useAppletContextDirect, useConfig, useConfigContext, usePermissions, useRoute, useSession, useStreaming, useTranslation, useUser };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// ui/src/applet-core/context/AppletContext.tsx
|
|
5
|
+
var AppletContext = createContext(null);
|
|
6
|
+
function AppletProvider({ children, windowKey, context }) {
|
|
7
|
+
const initialContext = context ?? window[windowKey];
|
|
8
|
+
if (!initialContext) {
|
|
9
|
+
throw new Error(`${windowKey} not found on window. Ensure backend context injection is working.`);
|
|
10
|
+
}
|
|
11
|
+
return /* @__PURE__ */ jsx(AppletContext.Provider, { value: initialContext, children });
|
|
12
|
+
}
|
|
13
|
+
function useAppletContext() {
|
|
14
|
+
const context = useContext(AppletContext);
|
|
15
|
+
if (!context) {
|
|
16
|
+
throw new Error("useAppletContext must be used within AppletProvider");
|
|
17
|
+
}
|
|
18
|
+
return context;
|
|
19
|
+
}
|
|
20
|
+
var ConfigContext = createContext(null);
|
|
21
|
+
function ConfigProvider({ children, config }) {
|
|
22
|
+
return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: config, children });
|
|
23
|
+
}
|
|
24
|
+
function useConfigContext() {
|
|
25
|
+
const context = useContext(ConfigContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error("useConfigContext must be used within ConfigProvider");
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ui/src/applet-core/hooks/useAppletContext.ts
|
|
33
|
+
function useAppletContext2(windowKey) {
|
|
34
|
+
const context = window[windowKey];
|
|
35
|
+
if (!context) {
|
|
36
|
+
throw new Error(`${windowKey} not found on window. Ensure backend context injection is working.`);
|
|
37
|
+
}
|
|
38
|
+
return context;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ui/src/applet-core/hooks/useConfig.ts
|
|
42
|
+
function useConfig() {
|
|
43
|
+
const { config } = useAppletContext();
|
|
44
|
+
return config;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ui/src/applet-core/hooks/useUser.ts
|
|
48
|
+
function useUser() {
|
|
49
|
+
const { user } = useAppletContext();
|
|
50
|
+
return user;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ui/src/applet-core/hooks/usePermissions.ts
|
|
54
|
+
function usePermissions() {
|
|
55
|
+
const { user } = useAppletContext();
|
|
56
|
+
const hasPermission = (permission) => {
|
|
57
|
+
return user.permissions.includes(permission);
|
|
58
|
+
};
|
|
59
|
+
const hasAnyPermission = (...permissions) => {
|
|
60
|
+
return permissions.some((p) => user.permissions.includes(p));
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
hasPermission,
|
|
64
|
+
hasAnyPermission,
|
|
65
|
+
permissions: user.permissions
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ui/src/applet-core/hooks/useTranslation.ts
|
|
70
|
+
function useTranslation() {
|
|
71
|
+
const { locale } = useAppletContext();
|
|
72
|
+
const t = (key, params) => {
|
|
73
|
+
let text = locale.translations[key] || key;
|
|
74
|
+
if (params) {
|
|
75
|
+
Object.entries(params).forEach(([k, v]) => {
|
|
76
|
+
text = text.replace(new RegExp(`\\{${k}\\}`, "g"), String(v));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return text;
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
t,
|
|
83
|
+
language: locale.language
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function useSession() {
|
|
87
|
+
const { session } = useAppletContext();
|
|
88
|
+
const isExpiringSoon = useMemo(() => {
|
|
89
|
+
const bufferMs = 5 * 60 * 1e3;
|
|
90
|
+
return session.expiresAt - Date.now() < bufferMs;
|
|
91
|
+
}, [session.expiresAt]);
|
|
92
|
+
const refreshSession = async () => {
|
|
93
|
+
const response = await fetch(session.refreshURL, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
"X-CSRF-Token": session.csrfToken
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const returnUrl = encodeURIComponent(window.location.pathname);
|
|
101
|
+
window.location.href = `/login?redirect=${returnUrl}`;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const newToken = response.headers.get("X-CSRF-Token");
|
|
105
|
+
if (newToken) {
|
|
106
|
+
window.dispatchEvent(
|
|
107
|
+
new CustomEvent("iota:csrf-refresh", {
|
|
108
|
+
detail: { token: newToken }
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
isExpiringSoon,
|
|
115
|
+
refreshSession,
|
|
116
|
+
csrfToken: session.csrfToken,
|
|
117
|
+
expiresAt: session.expiresAt
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ui/src/applet-core/hooks/useRoute.ts
|
|
122
|
+
function useRoute() {
|
|
123
|
+
const { route } = useAppletContext();
|
|
124
|
+
return route;
|
|
125
|
+
}
|
|
126
|
+
function useStreaming() {
|
|
127
|
+
const [isStreaming, setIsStreaming] = useState(false);
|
|
128
|
+
const abortControllerRef = useRef(null);
|
|
129
|
+
const processStream = useCallback(
|
|
130
|
+
async (generator, onChunk, signal) => {
|
|
131
|
+
setIsStreaming(true);
|
|
132
|
+
const controller = new AbortController();
|
|
133
|
+
abortControllerRef.current = controller;
|
|
134
|
+
if (signal) {
|
|
135
|
+
signal.addEventListener("abort", () => {
|
|
136
|
+
controller.abort();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
for await (const chunk of generator) {
|
|
141
|
+
if (controller.signal.aborted) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
onChunk(chunk);
|
|
145
|
+
}
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (controller.signal.aborted) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
} finally {
|
|
152
|
+
setIsStreaming(false);
|
|
153
|
+
abortControllerRef.current = null;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
[]
|
|
157
|
+
);
|
|
158
|
+
const cancel = useCallback(() => {
|
|
159
|
+
if (abortControllerRef.current) {
|
|
160
|
+
abortControllerRef.current.abort();
|
|
161
|
+
}
|
|
162
|
+
setIsStreaming(false);
|
|
163
|
+
}, []);
|
|
164
|
+
const reset = useCallback(() => {
|
|
165
|
+
abortControllerRef.current = null;
|
|
166
|
+
setIsStreaming(false);
|
|
167
|
+
}, []);
|
|
168
|
+
return {
|
|
169
|
+
isStreaming,
|
|
170
|
+
processStream,
|
|
171
|
+
cancel,
|
|
172
|
+
reset
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export { AppletProvider, ConfigProvider, useAppletContext, useAppletContext2 as useAppletContextDirect, useConfig, useConfigContext, usePermissions, useRoute, useSession, useStreaming, useTranslation, useUser };
|
|
177
|
+
//# sourceMappingURL=index.mjs.map
|
|
178
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../ui/src/applet-core/context/AppletContext.tsx","../ui/src/applet-core/context/ConfigProvider.tsx","../ui/src/applet-core/hooks/useAppletContext.ts","../ui/src/applet-core/hooks/useConfig.ts","../ui/src/applet-core/hooks/useUser.ts","../ui/src/applet-core/hooks/usePermissions.ts","../ui/src/applet-core/hooks/useTranslation.ts","../ui/src/applet-core/hooks/useSession.ts","../ui/src/applet-core/hooks/useRoute.ts","../ui/src/applet-core/hooks/useStreaming.ts"],"names":["createContext","jsx","useContext","useAppletContext"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext, useContext, ReactNode } from 'react'\nimport type { InitialContext } from '../types'\n\n/**\n * AppletContext provides access to the global context injected by the backend.\n * The context is read from window.__*_CONTEXT__ (configured via windowKey).\n */\nconst AppletContext = createContext<InitialContext | null>(null)\n\nexport interface AppletProviderProps {\n children: ReactNode\n windowKey: string\n context?: InitialContext\n}\n\n/**\n * AppletProvider reads context from window global and provides it to hooks.\n *\n * Usage:\n * <AppletProvider windowKey=\"__BICHAT_CONTEXT__\">\n * <App />\n * </AppletProvider>\n */\nexport function AppletProvider({ children, windowKey, context }: AppletProviderProps) {\n // Use provided context or read from window global\n const initialContext = context ?? (window as any)[windowKey]\n\n if (!initialContext) {\n throw new Error(`${windowKey} not found on window. Ensure backend context injection is working.`)\n }\n\n return (\n <AppletContext.Provider value={initialContext}>\n {children}\n </AppletContext.Provider>\n )\n}\n\n/**\n * useAppletContext provides access to the full applet context.\n * Use specialized hooks (useUser, useConfig, etc.) for specific context parts.\n */\nexport function useAppletContext<T = InitialContext>(): T {\n const context = useContext(AppletContext)\n if (!context) {\n throw new Error('useAppletContext must be used within AppletProvider')\n }\n return context as T\n}\n","import { createContext, useContext, ReactNode } from 'react'\nimport type { InitialContext } from '../types'\n\n/**\n * ConfigProvider is an alternative to AppletProvider that accepts context via props\n * instead of reading from window global. Useful for testing and server-side rendering.\n */\n\nconst ConfigContext = createContext<InitialContext | null>(null)\n\nexport interface ConfigProviderProps {\n children: ReactNode\n config: InitialContext\n}\n\n/**\n * ConfigProvider accepts context configuration via props.\n *\n * Usage:\n * <ConfigProvider config={initialContext}>\n * <App />\n * </ConfigProvider>\n */\nexport function ConfigProvider({ children, config }: ConfigProviderProps) {\n return (\n <ConfigContext.Provider value={config}>\n {children}\n </ConfigContext.Provider>\n )\n}\n\n/**\n * useConfigContext provides access to the applet context when using ConfigProvider.\n */\nexport function useConfigContext<T = InitialContext>(): T {\n const context = useContext(ConfigContext)\n if (!context) {\n throw new Error('useConfigContext must be used within ConfigProvider')\n }\n return context as T\n}\n","import type { InitialContext } from '../types'\n\n/**\n * useAppletContext provides direct access to the window global context.\n * This is a standalone version that doesn't require AppletProvider.\n *\n * Usage:\n * const context = useAppletContext('__BICHAT_CONTEXT__')\n *\n * Note: Prefer using AppletProvider + context hooks for better type safety\n * and testability. Use this hook only when provider setup is not possible.\n */\nexport function useAppletContext<T = InitialContext>(windowKey: string): T {\n const context = (window as any)[windowKey]\n\n if (!context) {\n throw new Error(`${windowKey} not found on window. Ensure backend context injection is working.`)\n }\n\n return context as T\n}\n","import { useAppletContext } from '../context/AppletContext'\nimport type { AppConfig } from '../types'\n\n/**\n * useConfig provides access to applet configuration (endpoints, etc.)\n *\n * Usage:\n * const { graphQLEndpoint, streamEndpoint } = useConfig()\n */\nexport function useConfig(): AppConfig {\n const { config } = useAppletContext()\n return config\n}\n","import { useAppletContext } from '../context/AppletContext'\nimport type { UserContext } from '../types'\n\n/**\n * useUser provides access to current user information.\n *\n * Usage:\n * const { id, email, firstName, lastName, permissions } = useUser()\n */\nexport function useUser(): UserContext {\n const { user } = useAppletContext()\n return user\n}\n","import { useAppletContext } from '../context/AppletContext'\nimport type { PermissionsHook } from '../types'\n\n/**\n * usePermissions provides permission checking utilities.\n * All user permissions are automatically passed from backend.\n *\n * Usage:\n * const { hasPermission, hasAnyPermission } = usePermissions()\n *\n * if (hasPermission('bichat.access')) {\n * // User has bichat access\n * }\n *\n * if (hasAnyPermission('finance.view', 'finance.edit')) {\n * // User has at least one of these permissions\n * }\n */\nexport function usePermissions(): PermissionsHook {\n const { user } = useAppletContext()\n\n const hasPermission = (permission: string): boolean => {\n return user.permissions.includes(permission)\n }\n\n const hasAnyPermission = (...permissions: string[]): boolean => {\n return permissions.some(p => user.permissions.includes(p))\n }\n\n return {\n hasPermission,\n hasAnyPermission,\n permissions: user.permissions\n }\n}\n","import { useAppletContext } from '../context/AppletContext'\nimport type { TranslationHook } from '../types'\n\n/**\n * useTranslation provides i18n translation utilities.\n * All translations are automatically passed from backend locale bundle.\n *\n * Usage:\n * const { t, language } = useTranslation()\n *\n * // Simple translation\n * t('BiChat.Title') // Returns translated text\n *\n * // Translation with interpolation\n * t('Common.WelcomeMessage', { name: 'John' })\n * // If translation is \"Welcome {name}!\" -> Returns \"Welcome John!\"\n *\n * React uses same keys as Go backend:\n * Go: pageCtx.T(\"BiChat.Title\")\n * React: t(\"BiChat.Title\")\n */\nexport function useTranslation(): TranslationHook {\n const { locale } = useAppletContext()\n\n const t = (key: string, params?: Record<string, unknown>): string => {\n let text = locale.translations[key] || key\n\n // Simple interpolation: \"Hello {name}\" with {name: \"World\"}\n if (params) {\n Object.entries(params).forEach(([k, v]) => {\n text = text.replace(new RegExp(`\\\\{${k}\\\\}`, 'g'), String(v))\n })\n }\n\n return text\n }\n\n return {\n t,\n language: locale.language\n }\n}\n","import { useMemo } from 'react'\nimport { useAppletContext } from '../context/AppletContext'\nimport type { SessionHook } from '../types'\n\n/**\n * useSession provides session and authentication handling utilities.\n *\n * Usage:\n * const { isExpiringSoon, refreshSession, csrfToken } = useSession()\n *\n * // Check if session is expiring soon (5 min buffer)\n * if (isExpiringSoon) {\n * await refreshSession()\n * }\n *\n * // Include CSRF token in requests\n * fetch('/api/endpoint', {\n * headers: { 'X-CSRF-Token': csrfToken }\n * })\n */\nexport function useSession(): SessionHook {\n const { session } = useAppletContext()\n\n // Check if session is expiring soon (5 minute buffer)\n const isExpiringSoon = useMemo(() => {\n const bufferMs = 5 * 60 * 1000 // 5 minutes\n return session.expiresAt - Date.now() < bufferMs\n }, [session.expiresAt])\n\n const refreshSession = async (): Promise<void> => {\n const response = await fetch(session.refreshURL, {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': session.csrfToken\n }\n })\n\n if (!response.ok) {\n // Session refresh failed - redirect to login with return URL\n const returnUrl = encodeURIComponent(window.location.pathname)\n window.location.href = `/login?redirect=${returnUrl}`\n return\n }\n\n // Dispatch event for CSRF token update\n const newToken = response.headers.get('X-CSRF-Token')\n if (newToken) {\n window.dispatchEvent(\n new CustomEvent('iota:csrf-refresh', {\n detail: { token: newToken }\n })\n )\n }\n }\n\n return {\n isExpiringSoon,\n refreshSession,\n csrfToken: session.csrfToken,\n expiresAt: session.expiresAt\n }\n}\n","import { useAppletContext } from '../context/AppletContext'\nimport type { RouteContext } from '../types'\n\n/**\n * useRoute provides access to the current route context.\n * Route context is initialized from the backend and includes path, params, and query.\n *\n * Usage:\n * const { path, params, query } = useRoute()\n *\n * // Example values:\n * // path: \"/sessions/123\"\n * // params: { id: \"123\" }\n * // query: { tab: \"history\" }\n */\nexport function useRoute(): RouteContext {\n const { route } = useAppletContext()\n return route\n}\n","import { useState, useRef, useCallback } from 'react'\nimport type { StreamingHook } from '../types'\n\n/**\n * useStreaming provides SSE (Server-Sent Events) streaming utilities with cancellation support.\n *\n * Usage:\n * const { isStreaming, processStream, cancel, reset } = useStreaming()\n *\n * // Process async generator stream\n * await processStream(messageStream, (chunk) => {\n * console.log('Received:', chunk)\n * })\n *\n * // Cancel ongoing stream\n * cancel()\n *\n * // Reset state after stream completion\n * reset()\n */\nexport function useStreaming(): StreamingHook {\n const [isStreaming, setIsStreaming] = useState(false)\n const abortControllerRef = useRef<AbortController | null>(null)\n\n const processStream = useCallback(\n async <T,>(\n generator: AsyncGenerator<T>,\n onChunk: (chunk: T) => void,\n signal?: AbortSignal\n ): Promise<void> => {\n setIsStreaming(true)\n\n // Create abort controller if not provided\n const controller = new AbortController()\n abortControllerRef.current = controller\n\n // Listen to external signal if provided\n if (signal) {\n signal.addEventListener('abort', () => {\n controller.abort()\n })\n }\n\n try {\n for await (const chunk of generator) {\n // Check if stream was cancelled\n if (controller.signal.aborted) {\n break\n }\n\n onChunk(chunk)\n }\n } catch (error) {\n // Stream was cancelled or errored\n if (controller.signal.aborted) {\n // Cancellation is expected, don't throw\n return\n }\n throw error\n } finally {\n setIsStreaming(false)\n abortControllerRef.current = null\n }\n },\n []\n )\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort()\n }\n setIsStreaming(false)\n }, [])\n\n const reset = useCallback(() => {\n abortControllerRef.current = null\n setIsStreaming(false)\n }, [])\n\n return {\n isStreaming,\n processStream,\n cancel,\n reset\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@iota-uz/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "IOTA SDK UI utilities, Tailwind configuration, and React components for building IOTA SDK applets.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"tailwind",
|
|
17
|
+
"assets",
|
|
18
|
+
"README.MD",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.mjs",
|
|
25
|
+
"require": "./dist/index.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./bichat": {
|
|
28
|
+
"types": "./dist/bichat/index.d.ts",
|
|
29
|
+
"import": "./dist/bichat/index.mjs",
|
|
30
|
+
"require": "./dist/bichat/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./bichat/styles.css": "./dist/bichat/styles.css",
|
|
33
|
+
"./tailwind/main.css": "./tailwind/main.css",
|
|
34
|
+
"./tailwind/iota.css": "./tailwind/iota.css",
|
|
35
|
+
"./tailwind/create-config": "./tailwind/create-config.cjs",
|
|
36
|
+
"./assets/*": "./assets/*",
|
|
37
|
+
"./assets/fonts/*": "./assets/fonts/*"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
41
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@phosphor-icons/react": "^2.1.0",
|
|
45
|
+
"date-fns": "^3.0.0",
|
|
46
|
+
"framer-motion": "^11.0.0",
|
|
47
|
+
"react-markdown": "^9.0.1",
|
|
48
|
+
"react-syntax-highlighter": "^15.5.0",
|
|
49
|
+
"recharts": "^2.12.0",
|
|
50
|
+
"rehype-sanitize": "^6.0.0",
|
|
51
|
+
"remark-gfm": "^4.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@tailwindcss/cli": "4.1.18",
|
|
55
|
+
"@types/react": "^18.3.3",
|
|
56
|
+
"@types/react-dom": "^18.3.0",
|
|
57
|
+
"@types/react-syntax-highlighter": "^15.5.13",
|
|
58
|
+
"tailwindcss": "4.1.18",
|
|
59
|
+
"tsup": "^8.5.0",
|
|
60
|
+
"typescript": "^5.7.3"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "pnpm run build:js && pnpm run build:tailwind && pnpm run build:assets",
|
|
64
|
+
"build:js": "tsup",
|
|
65
|
+
"build:tailwind": "node ./scripts/build-tailwind-files.mjs",
|
|
66
|
+
"build:assets": "node ./scripts/build-assets.mjs",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"lint": "echo \"no lint\""
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const sdkThemeExtend = {
|
|
2
|
+
fontFamily: {
|
|
3
|
+
sans: ['Gilroy'],
|
|
4
|
+
},
|
|
5
|
+
backgroundColor: {
|
|
6
|
+
surface: {
|
|
7
|
+
100: 'oklch(var(--clr-surface-100))',
|
|
8
|
+
200: 'oklch(var(--clr-surface-200))',
|
|
9
|
+
300: 'oklch(var(--clr-surface-300))',
|
|
10
|
+
400: 'oklch(var(--clr-surface-400))',
|
|
11
|
+
500: 'oklch(var(--clr-surface-500))',
|
|
12
|
+
600: 'oklch(var(--clr-surface-600))',
|
|
13
|
+
},
|
|
14
|
+
avatar: 'oklch(var(--clr-avatar-bg))',
|
|
15
|
+
},
|
|
16
|
+
borderColor: {
|
|
17
|
+
primary: 'oklch(var(--clr-border-primary))',
|
|
18
|
+
secondary: 'oklch(var(--clr-border-secondary))',
|
|
19
|
+
green: 'oklch(var(--clr-border-green))',
|
|
20
|
+
pink: 'oklch(var(--clr-border-pink))',
|
|
21
|
+
yellow: 'oklch(var(--clr-border-yellow))',
|
|
22
|
+
blue: 'oklch(var(--clr-border-blue))',
|
|
23
|
+
purple: 'oklch(var(--clr-border-purple))',
|
|
24
|
+
},
|
|
25
|
+
textColor: {
|
|
26
|
+
100: 'oklch(var(--clr-text-100))',
|
|
27
|
+
200: 'oklch(var(--clr-text-200))',
|
|
28
|
+
300: 'oklch(var(--clr-text-300))',
|
|
29
|
+
green: 'oklch(var(--clr-text-green))',
|
|
30
|
+
pink: 'oklch(var(--clr-text-pink))',
|
|
31
|
+
yellow: 'oklch(var(--clr-text-yellow))',
|
|
32
|
+
blue: 'oklch(var(--clr-text-blue))',
|
|
33
|
+
purple: 'oklch(var(--clr-text-purple))',
|
|
34
|
+
avatar: 'oklch(var(--clr-avatar-text))',
|
|
35
|
+
},
|
|
36
|
+
colors: {
|
|
37
|
+
100: 'oklch(var(--clr-text-100))',
|
|
38
|
+
200: 'oklch(var(--clr-text-200))',
|
|
39
|
+
300: 'oklch(var(--clr-text-300))',
|
|
40
|
+
green: 'oklch(var(--clr-text-green))',
|
|
41
|
+
pink: 'oklch(var(--clr-text-pink))',
|
|
42
|
+
yellow: 'oklch(var(--clr-text-yellow))',
|
|
43
|
+
blue: 'oklch(var(--clr-text-blue))',
|
|
44
|
+
purple: 'oklch(var(--clr-text-purple))',
|
|
45
|
+
avatar: 'oklch(var(--clr-avatar-text))',
|
|
46
|
+
black: {
|
|
47
|
+
DEFAULT: 'oklch(var(--black))',
|
|
48
|
+
950: 'oklch(var(--black-950))',
|
|
49
|
+
},
|
|
50
|
+
brand: {
|
|
51
|
+
500: 'oklch(var(--primary-500) / <alpha-value>)',
|
|
52
|
+
600: 'oklch(var(--primary-600) / <alpha-value>)',
|
|
53
|
+
700: 'oklch(var(--primary-700) / <alpha-value>)',
|
|
54
|
+
},
|
|
55
|
+
gray: {
|
|
56
|
+
50: 'oklch(var(--gray-50) / <alpha-value>)',
|
|
57
|
+
100: 'oklch(var(--gray-100) / <alpha-value>)',
|
|
58
|
+
200: 'oklch(var(--gray-200) / <alpha-value>)',
|
|
59
|
+
300: 'oklch(var(--gray-300) / <alpha-value>)',
|
|
60
|
+
400: 'oklch(var(--gray-400) / <alpha-value>)',
|
|
61
|
+
500: 'oklch(var(--gray-500) / <alpha-value>)',
|
|
62
|
+
600: 'oklch(var(--gray-600) / <alpha-value>)',
|
|
63
|
+
700: 'oklch(var(--gray-700) / <alpha-value>)',
|
|
64
|
+
800: 'oklch(var(--gray-800) / <alpha-value>)',
|
|
65
|
+
900: 'oklch(var(--gray-900) / <alpha-value>)',
|
|
66
|
+
950: 'oklch(var(--gray-950) / <alpha-value>)',
|
|
67
|
+
},
|
|
68
|
+
green: {
|
|
69
|
+
50: 'oklch(var(--green-50) / <alpha-value>)',
|
|
70
|
+
100: 'oklch(var(--green-100) / <alpha-value>)',
|
|
71
|
+
200: 'oklch(var(--green-200) / <alpha-value>)',
|
|
72
|
+
500: 'oklch(var(--green-500) / <alpha-value>)',
|
|
73
|
+
600: 'oklch(var(--green-600) / <alpha-value>)',
|
|
74
|
+
},
|
|
75
|
+
red: {
|
|
76
|
+
100: 'oklch(var(--red-100))',
|
|
77
|
+
200: 'oklch(var(--red-200))',
|
|
78
|
+
500: 'oklch(var(--red-500) / <alpha-value>)',
|
|
79
|
+
600: 'oklch(var(--red-600) / <alpha-value>)',
|
|
80
|
+
700: 'oklch(var(--red-700) / <alpha-value>)',
|
|
81
|
+
},
|
|
82
|
+
badge: {
|
|
83
|
+
pink: 'oklch(var(--clr-badge-pink))',
|
|
84
|
+
yellow: 'oklch(var(--clr-badge-yellow))',
|
|
85
|
+
green: 'oklch(var(--clr-badge-green))',
|
|
86
|
+
blue: 'oklch(var(--clr-badge-blue))',
|
|
87
|
+
purple: 'oklch(var(--clr-badge-purple))',
|
|
88
|
+
gray: 'oklch(var(--clr-badge-gray))',
|
|
89
|
+
},
|
|
90
|
+
success: {
|
|
91
|
+
DEFAULT: 'oklch(var(--green-500) / <alpha-value>)',
|
|
92
|
+
},
|
|
93
|
+
on: {
|
|
94
|
+
success: 'oklch(var(--white))',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function isPlainObject(value) {
|
|
100
|
+
return (
|
|
101
|
+
value !== null &&
|
|
102
|
+
typeof value === 'object' &&
|
|
103
|
+
!Array.isArray(value) &&
|
|
104
|
+
Object.prototype.toString.call(value) === '[object Object]'
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function mergeDeep(base, extra) {
|
|
109
|
+
const out = { ...base }
|
|
110
|
+
for (const [key, value] of Object.entries(extra ?? {})) {
|
|
111
|
+
if (isPlainObject(out[key]) && isPlainObject(value)) {
|
|
112
|
+
out[key] = mergeDeep(out[key], value)
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
out[key] = value
|
|
116
|
+
}
|
|
117
|
+
return out
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizeContent(content) {
|
|
121
|
+
const list = Array.isArray(content) ? content.slice() : []
|
|
122
|
+
const sdkGlob = './node_modules/@iotauz/iota-sdk/dist/**/*.{js,mjs,cjs}'
|
|
123
|
+
if (!list.includes(sdkGlob)) list.push(sdkGlob)
|
|
124
|
+
return list
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function createIotaTailwindConfig(options = {}) {
|
|
128
|
+
const content = normalizeContent(options.content)
|
|
129
|
+
const extend = mergeDeep(sdkThemeExtend, options.extend ?? {})
|
|
130
|
+
const plugins = Array.isArray(options.plugins) ? options.plugins : []
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
darkMode: 'class',
|
|
134
|
+
content,
|
|
135
|
+
theme: { extend },
|
|
136
|
+
plugins,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = createIotaTailwindConfig
|
|
141
|
+
module.exports.createIotaTailwindConfig = createIotaTailwindConfig
|
|
142
|
+
|