@sybilion/uilib 1.1.0 → 1.2.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 +8 -8
- package/assets/{mini-app-global.css → standalone-global.css} +1 -1
- package/dist/esm/components/ui/Sidebar/Sidebar.styl.js +2 -2
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.js +48 -0
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl.js +7 -0
- package/dist/esm/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.js +38 -0
- package/dist/esm/index.js +5 -5
- package/dist/esm/sybilion-auth/SybilionAuthProvider.js +185 -0
- package/dist/esm/sybilion-auth/authPaths.js +7 -0
- package/dist/esm/sybilion-auth/exchangeSybilionToken.js +40 -0
- package/dist/esm/types/src/components/ui/Input/Input.d.ts +1 -1
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.d.ts +11 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.d.ts +8 -0
- package/dist/esm/types/src/components/widgets/SidebarDatasetsItemsGrouped/index.d.ts +3 -0
- package/dist/esm/types/src/docs/pages/SidebarDatasetsItemsGroupedPage.d.ts +1 -0
- package/dist/esm/types/src/docs/pages/SybilionAuthProviderPage.d.ts +1 -0
- package/dist/esm/types/src/index.d.ts +3 -1
- package/dist/esm/types/src/sybilion-auth/SybilionAuthProvider.d.ts +39 -0
- package/dist/esm/types/src/sybilion-auth/authPaths.d.ts +3 -0
- package/dist/esm/types/src/sybilion-auth/exchangeSybilionToken.d.ts +2 -0
- package/dist/esm/types/src/sybilion-auth/index.d.ts +4 -0
- package/dist/esm/types/src/{mini-app/miniAppDataTypes.d.ts → types/sybilionDatasetSnapshots.d.ts} +5 -8
- package/docs/standalone-apps.md +65 -0
- package/package.json +10 -3
- package/src/components/ui/Sidebar/Sidebar.styl +0 -25
- package/src/components/ui/Sidebar/Sidebar.styl.d.ts +0 -1
- package/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl +29 -0
- package/src/{mini-app/MiniAppRoot.styl.d.ts → components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.styl.d.ts} +4 -2
- package/src/components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.tsx +128 -0
- package/src/components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.ts +51 -0
- package/src/components/widgets/SidebarDatasetsItemsGrouped/index.ts +10 -0
- package/src/docs/pages/SidebarDatasetsItemsGroupedPage.tsx +136 -0
- package/src/docs/pages/SybilionAuthProviderPage.tsx +37 -0
- package/src/docs/registry.ts +9 -3
- package/src/index.ts +3 -1
- package/src/sybilion-auth/SybilionAuthProvider.tsx +322 -0
- package/src/sybilion-auth/authPaths.ts +6 -0
- package/src/sybilion-auth/exchangeSybilionToken.ts +47 -0
- package/src/sybilion-auth/index.ts +16 -0
- package/src/{mini-app/miniAppDataTypes.ts → types/sybilionDatasetSnapshots.ts} +5 -8
- package/dist/esm/mini-app/MiniAppRoot.js +0 -82
- package/dist/esm/mini-app/MiniAppRoot.styl.js +0 -7
- package/dist/esm/mini-app/miniAppChatBridge.js +0 -45
- package/dist/esm/mini-app/miniAppDataClient.js +0 -98
- package/dist/esm/mini-app/miniAppProtocol.js +0 -153
- package/dist/esm/mini-app/miniAppThemeConfig.js +0 -40
- package/dist/esm/types/src/docs/pages/MiniAppRootPage.d.ts +0 -1
- package/dist/esm/types/src/mini-app/MiniAppRoot.d.ts +0 -18
- package/dist/esm/types/src/mini-app/index.d.ts +0 -10
- package/dist/esm/types/src/mini-app/miniAppChatBridge.d.ts +0 -6
- package/dist/esm/types/src/mini-app/miniAppDataClient.d.ts +0 -16
- package/dist/esm/types/src/mini-app/miniAppProtocol.d.ts +0 -89
- package/dist/esm/types/src/mini-app/miniAppThemeConfig.d.ts +0 -3
- package/docs/workspace-mini-apps.md +0 -51
- package/src/docs/pages/MiniAppRootPage.tsx +0 -58
- package/src/mini-app/MiniAppRoot.styl +0 -24
- package/src/mini-app/MiniAppRoot.tsx +0 -150
- package/src/mini-app/index.ts +0 -43
- package/src/mini-app/miniAppChatBridge.ts +0 -55
- package/src/mini-app/miniAppDataClient.ts +0 -165
- package/src/mini-app/miniAppProtocol.ts +0 -247
- package/src/mini-app/miniAppThemeConfig.ts +0 -45
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { ChatResponse } from '#uilib/types/chat-api.types';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
buildChatSendMessage,
|
|
5
|
-
isTrustedMiniAppParentMessage,
|
|
6
|
-
parseChatSendResultMessage,
|
|
7
|
-
resolveParentOriginFromReferrer,
|
|
8
|
-
} from './miniAppProtocol';
|
|
9
|
-
|
|
10
|
-
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Ask the Sybilion host to send a chat message with its auth token.
|
|
14
|
-
* Does not update host ChatSheet state — same session as `chatId` on the agent only.
|
|
15
|
-
*/
|
|
16
|
-
export async function sendChatMessage(
|
|
17
|
-
chatId: string,
|
|
18
|
-
message: string,
|
|
19
|
-
): Promise<ChatResponse> {
|
|
20
|
-
if (typeof window === 'undefined' || window.parent === window) {
|
|
21
|
-
throw new Error('sendChatMessage requires an embedded mini-app (iframe)');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const requestId = crypto.randomUUID();
|
|
25
|
-
const target = resolveParentOriginFromReferrer();
|
|
26
|
-
const payload = { requestId, chatId, message };
|
|
27
|
-
const msg = buildChatSendMessage(payload);
|
|
28
|
-
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
const onMessage = (event: MessageEvent) => {
|
|
31
|
-
if (!isTrustedMiniAppParentMessage(event)) return;
|
|
32
|
-
const parsed = parseChatSendResultMessage(event.data);
|
|
33
|
-
if (!parsed || parsed.requestId !== requestId) return;
|
|
34
|
-
window.removeEventListener('message', onMessage);
|
|
35
|
-
clearTimeout(timer);
|
|
36
|
-
if (parsed.ok === true) {
|
|
37
|
-
resolve(parsed.result);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
reject(new Error(parsed.error));
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
window.addEventListener('message', onMessage);
|
|
44
|
-
const timer = setTimeout(() => {
|
|
45
|
-
window.removeEventListener('message', onMessage);
|
|
46
|
-
reject(new Error('Mini-app chat request timed out'));
|
|
47
|
-
}, DEFAULT_TIMEOUT_MS);
|
|
48
|
-
|
|
49
|
-
if (target) {
|
|
50
|
-
window.parent.postMessage(msg, target);
|
|
51
|
-
} else {
|
|
52
|
-
window.parent.postMessage(msg, '*');
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
MiniAppDataset,
|
|
3
|
-
MiniAppDriversComparisonSnapshot,
|
|
4
|
-
MiniAppForecastMap,
|
|
5
|
-
MiniAppPerformanceBundle,
|
|
6
|
-
} from './miniAppDataTypes';
|
|
7
|
-
import {
|
|
8
|
-
type MiniAppDataOp,
|
|
9
|
-
type MiniAppDataRequestPayload,
|
|
10
|
-
buildDataRequestMessage,
|
|
11
|
-
isTrustedMiniAppParentMessage,
|
|
12
|
-
parseDataResponseMessage,
|
|
13
|
-
resolveParentOriginFromReferrer,
|
|
14
|
-
} from './miniAppProtocol';
|
|
15
|
-
|
|
16
|
-
export type MiniAppDataClientOptions = {
|
|
17
|
-
/** Default 10000 ms. */
|
|
18
|
-
timeoutMs?: number;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type MiniAppDataClient = {
|
|
22
|
-
getDatasets(): Promise<MiniAppDataset[]>;
|
|
23
|
-
getDataset(id: number): Promise<MiniAppDataset | null>;
|
|
24
|
-
getForecasts(datasetId: number): Promise<MiniAppForecastMap>;
|
|
25
|
-
getForecast(datasetId: number, analysisId: number): Promise<unknown | null>;
|
|
26
|
-
getDrivers(datasetId: number, analysisId: number): Promise<unknown[]>;
|
|
27
|
-
getPerformanceData(
|
|
28
|
-
datasetId: number,
|
|
29
|
-
analysisId: number,
|
|
30
|
-
): Promise<MiniAppPerformanceBundle>;
|
|
31
|
-
getDriversComparisonData(
|
|
32
|
-
datasetId: number,
|
|
33
|
-
analysisId: number,
|
|
34
|
-
): Promise<MiniAppDriversComparisonSnapshot>;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
38
|
-
|
|
39
|
-
type Pending = {
|
|
40
|
-
resolve: (value: unknown) => void;
|
|
41
|
-
reject: (err: Error) => void;
|
|
42
|
-
timer: ReturnType<typeof setTimeout>;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/** One listener per browsing context; tracks in-flight bridge requests by `requestId`. */
|
|
46
|
-
export function createMiniAppDataClient(
|
|
47
|
-
options?: MiniAppDataClientOptions,
|
|
48
|
-
): MiniAppDataClient {
|
|
49
|
-
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
50
|
-
const pending = new Map<string, Pending>();
|
|
51
|
-
let listening = false;
|
|
52
|
-
|
|
53
|
-
const settle = (rid: string, fn: (p: Pending) => void): void => {
|
|
54
|
-
const p = pending.get(rid);
|
|
55
|
-
if (!p) return;
|
|
56
|
-
clearTimeout(p.timer);
|
|
57
|
-
pending.delete(rid);
|
|
58
|
-
fn(p);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
function ensureListener(): void {
|
|
62
|
-
if (listening || typeof window === 'undefined') return;
|
|
63
|
-
listening = true;
|
|
64
|
-
window.addEventListener('message', (event: MessageEvent) => {
|
|
65
|
-
if (!isTrustedMiniAppParentMessage(event)) return;
|
|
66
|
-
const msg = parseDataResponseMessage(event.data);
|
|
67
|
-
if (!msg) return;
|
|
68
|
-
settle(msg.requestId, p => {
|
|
69
|
-
if (msg.ok) {
|
|
70
|
-
p.resolve(msg.result);
|
|
71
|
-
} else {
|
|
72
|
-
p.reject(
|
|
73
|
-
new Error(
|
|
74
|
-
typeof msg.error === 'string'
|
|
75
|
-
? msg.error
|
|
76
|
-
: 'Mini-app data request failed',
|
|
77
|
-
),
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function request(
|
|
85
|
-
payload: Omit<MiniAppDataRequestPayload, 'requestId'>,
|
|
86
|
-
): Promise<unknown> {
|
|
87
|
-
if (typeof window === 'undefined' || window.parent === window) {
|
|
88
|
-
throw new Error('MiniAppDataClient works only inside an iframe embed');
|
|
89
|
-
}
|
|
90
|
-
ensureListener();
|
|
91
|
-
|
|
92
|
-
const requestId =
|
|
93
|
-
typeof crypto !== 'undefined' && 'randomUUID' in crypto
|
|
94
|
-
? crypto.randomUUID()
|
|
95
|
-
: `miniapp-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
96
|
-
|
|
97
|
-
const envelope = buildDataRequestMessage({
|
|
98
|
-
...payload,
|
|
99
|
-
requestId,
|
|
100
|
-
});
|
|
101
|
-
const target = resolveParentOriginFromReferrer();
|
|
102
|
-
|
|
103
|
-
return new Promise((resolve, reject) => {
|
|
104
|
-
const timer = setTimeout(() => {
|
|
105
|
-
settle(requestId, p => {
|
|
106
|
-
p.reject(new Error('Mini-app data request timed out'));
|
|
107
|
-
});
|
|
108
|
-
}, timeoutMs);
|
|
109
|
-
|
|
110
|
-
pending.set(requestId, {
|
|
111
|
-
resolve,
|
|
112
|
-
reject,
|
|
113
|
-
timer,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
try {
|
|
117
|
-
if (target) {
|
|
118
|
-
window.parent.postMessage(envelope, target);
|
|
119
|
-
} else {
|
|
120
|
-
window.parent.postMessage(envelope, '*');
|
|
121
|
-
}
|
|
122
|
-
} catch (e) {
|
|
123
|
-
settle(requestId, p => {
|
|
124
|
-
p.reject(
|
|
125
|
-
e instanceof Error ? e : new Error('Mini-app postMessage failed'),
|
|
126
|
-
);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function rq<R>(
|
|
133
|
-
op: MiniAppDataOp,
|
|
134
|
-
params?: Record<string, number>,
|
|
135
|
-
): Promise<R> {
|
|
136
|
-
return request({ op, params }) as Promise<R>;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return {
|
|
140
|
-
getDatasets: () => rq<MiniAppDataset[]>('getDatasets'),
|
|
141
|
-
|
|
142
|
-
getDataset: id => rq<MiniAppDataset | null>('getDataset', { id }),
|
|
143
|
-
|
|
144
|
-
getForecasts: datasetId =>
|
|
145
|
-
rq<MiniAppForecastMap>('getForecasts', { datasetId }),
|
|
146
|
-
|
|
147
|
-
getForecast: (datasetId, analysisId) =>
|
|
148
|
-
rq<unknown | null>('getForecast', { datasetId, analysisId }),
|
|
149
|
-
|
|
150
|
-
getDrivers: (datasetId, analysisId) =>
|
|
151
|
-
rq<unknown[]>('getDrivers', { datasetId, analysisId }),
|
|
152
|
-
|
|
153
|
-
getPerformanceData: (datasetId, analysisId) =>
|
|
154
|
-
rq<MiniAppPerformanceBundle>('getPerformanceData', {
|
|
155
|
-
datasetId,
|
|
156
|
-
analysisId,
|
|
157
|
-
}),
|
|
158
|
-
|
|
159
|
-
getDriversComparisonData: (datasetId, analysisId) =>
|
|
160
|
-
rq<MiniAppDriversComparisonSnapshot>('getDriversComparisonData', {
|
|
161
|
-
datasetId,
|
|
162
|
-
analysisId,
|
|
163
|
-
}),
|
|
164
|
-
};
|
|
165
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* postMessage protocol for Sybilion workspace mini-apps (iframe child).
|
|
3
|
-
* Keep in sync with sybilion-client `src/workspace/miniAppBridge.ts` (channel, version, payloads).
|
|
4
|
-
*/
|
|
5
|
-
import type { ChatResponse } from '#uilib/types/chat-api.types';
|
|
6
|
-
|
|
7
|
-
export const MINIAPP_CHANNEL = 'sybilion.miniapp' as const;
|
|
8
|
-
export const MINIAPP_VERSION = 1 as const;
|
|
9
|
-
|
|
10
|
-
export type ThemeSyncPayload = {
|
|
11
|
-
mode: 'light' | 'dark';
|
|
12
|
-
isDarkMode: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type MiniAppMessageReady = {
|
|
16
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
17
|
-
version: typeof MINIAPP_VERSION;
|
|
18
|
-
type: 'READY';
|
|
19
|
-
payload: Record<string, unknown> | { appId?: string };
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type MiniAppMessageThemeSync = {
|
|
23
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
24
|
-
version: typeof MINIAPP_VERSION;
|
|
25
|
-
type: 'THEME_SYNC';
|
|
26
|
-
payload: ThemeSyncPayload;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type MiniAppDataOp =
|
|
30
|
-
| 'getDatasets'
|
|
31
|
-
| 'getDataset'
|
|
32
|
-
| 'getForecasts'
|
|
33
|
-
| 'getForecast'
|
|
34
|
-
| 'getDrivers'
|
|
35
|
-
| 'getPerformanceData'
|
|
36
|
-
| 'getDriversComparisonData';
|
|
37
|
-
|
|
38
|
-
export type MiniAppDataRequestPayload = {
|
|
39
|
-
requestId: string;
|
|
40
|
-
op: MiniAppDataOp;
|
|
41
|
-
params?: Record<string, number>;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export type MiniAppMessageDataRequest = {
|
|
45
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
46
|
-
version: typeof MINIAPP_VERSION;
|
|
47
|
-
type: 'DATA_REQUEST';
|
|
48
|
-
payload: MiniAppDataRequestPayload;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export type MiniAppDataResponsePayload = {
|
|
52
|
-
requestId: string;
|
|
53
|
-
ok: boolean;
|
|
54
|
-
result?: unknown;
|
|
55
|
-
error?: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export type MiniAppMessageDataResponse = {
|
|
59
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
60
|
-
version: typeof MINIAPP_VERSION;
|
|
61
|
-
type: 'DATA_RESPONSE';
|
|
62
|
-
payload: MiniAppDataResponsePayload;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export type MiniAppChatSendPayload = {
|
|
66
|
-
requestId: string;
|
|
67
|
-
chatId: string;
|
|
68
|
-
message: string;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export type MiniAppMessageChatSend = {
|
|
72
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
73
|
-
version: typeof MINIAPP_VERSION;
|
|
74
|
-
type: 'CHAT_SEND';
|
|
75
|
-
payload: MiniAppChatSendPayload;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export type MiniAppChatSendResultPayload =
|
|
79
|
-
| {
|
|
80
|
-
requestId: string;
|
|
81
|
-
ok: true;
|
|
82
|
-
result: ChatResponse;
|
|
83
|
-
}
|
|
84
|
-
| {
|
|
85
|
-
requestId: string;
|
|
86
|
-
ok: false;
|
|
87
|
-
error: string;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export type MiniAppMessageChatSendResult = {
|
|
91
|
-
channel: typeof MINIAPP_CHANNEL;
|
|
92
|
-
version: typeof MINIAPP_VERSION;
|
|
93
|
-
type: 'CHAT_SEND_RESULT';
|
|
94
|
-
payload: MiniAppChatSendResultPayload;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
function isRecord(v: unknown): v is Record<string, unknown> {
|
|
98
|
-
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** Parse parent → child THEME_SYNC (shell uses `buildThemeSyncMessage`). */
|
|
102
|
-
export function parseThemeSyncMessage(data: unknown): ThemeSyncPayload | null {
|
|
103
|
-
if (!isRecord(data)) return null;
|
|
104
|
-
if (data.channel !== MINIAPP_CHANNEL) return null;
|
|
105
|
-
if (data.version !== MINIAPP_VERSION) return null;
|
|
106
|
-
if (data.type !== 'THEME_SYNC') return null;
|
|
107
|
-
|
|
108
|
-
const payload = data.payload;
|
|
109
|
-
if (!isRecord(payload)) return null;
|
|
110
|
-
|
|
111
|
-
const mode = payload.mode === 'dark' ? 'dark' : 'light';
|
|
112
|
-
const isDarkMode =
|
|
113
|
-
typeof payload.isDarkMode === 'boolean'
|
|
114
|
-
? payload.isDarkMode
|
|
115
|
-
: mode === 'dark';
|
|
116
|
-
|
|
117
|
-
return { mode, isDarkMode };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Child → parent READY (optional `appId` for telemetry). */
|
|
121
|
-
export function buildReadyMessage(
|
|
122
|
-
payload: Record<string, unknown> = {},
|
|
123
|
-
): MiniAppMessageReady {
|
|
124
|
-
return {
|
|
125
|
-
channel: MINIAPP_CHANNEL,
|
|
126
|
-
version: MINIAPP_VERSION,
|
|
127
|
-
type: 'READY',
|
|
128
|
-
payload,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function resolveParentOriginFromReferrer(): string | null {
|
|
133
|
-
try {
|
|
134
|
-
if (typeof document !== 'undefined' && document.referrer) {
|
|
135
|
-
return new URL(document.referrer).origin;
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
/* invalid referrer */
|
|
139
|
-
}
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function applyThemeToDocument(mode: 'light' | 'dark'): void {
|
|
144
|
-
if (typeof document === 'undefined') return;
|
|
145
|
-
const root = document.documentElement;
|
|
146
|
-
root.classList.remove('light', 'dark');
|
|
147
|
-
root.classList.add(mode);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Only accept shell messages that appear to come from the real embedding parent. */
|
|
151
|
-
export function isTrustedMiniAppParentMessage(event: MessageEvent): boolean {
|
|
152
|
-
if (event.source !== window.parent) return false;
|
|
153
|
-
const fromReferrer = resolveParentOriginFromReferrer();
|
|
154
|
-
if (fromReferrer && event.origin !== fromReferrer) return false;
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function buildDataRequestMessage(
|
|
159
|
-
payload: MiniAppDataRequestPayload,
|
|
160
|
-
): MiniAppMessageDataRequest {
|
|
161
|
-
return {
|
|
162
|
-
channel: MINIAPP_CHANNEL,
|
|
163
|
-
version: MINIAPP_VERSION,
|
|
164
|
-
type: 'DATA_REQUEST',
|
|
165
|
-
payload,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function buildChatSendMessage(
|
|
170
|
-
payload: MiniAppChatSendPayload,
|
|
171
|
-
): MiniAppMessageChatSend {
|
|
172
|
-
return {
|
|
173
|
-
channel: MINIAPP_CHANNEL,
|
|
174
|
-
version: MINIAPP_VERSION,
|
|
175
|
-
type: 'CHAT_SEND',
|
|
176
|
-
payload,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/** Parse parent → child DATA_RESPONSE. */
|
|
181
|
-
export function parseDataResponseMessage(
|
|
182
|
-
data: unknown,
|
|
183
|
-
): MiniAppDataResponsePayload | null {
|
|
184
|
-
if (!isRecord(data)) return null;
|
|
185
|
-
if (data.channel !== MINIAPP_CHANNEL) return null;
|
|
186
|
-
if (data.version !== MINIAPP_VERSION) return null;
|
|
187
|
-
if (data.type !== 'DATA_RESPONSE') return null;
|
|
188
|
-
const payload = data.payload;
|
|
189
|
-
if (!isRecord(payload)) return null;
|
|
190
|
-
const requestId = payload.requestId;
|
|
191
|
-
if (typeof requestId !== 'string' || requestId.length === 0) return null;
|
|
192
|
-
const ok = payload.ok === true;
|
|
193
|
-
const errOk = payload.ok === false;
|
|
194
|
-
if (!ok && !errOk) return null;
|
|
195
|
-
|
|
196
|
-
const base: MiniAppDataResponsePayload = {
|
|
197
|
-
requestId,
|
|
198
|
-
ok,
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
if ('result' in payload) {
|
|
202
|
-
base.result = payload.result;
|
|
203
|
-
}
|
|
204
|
-
if (typeof payload.error === 'string') {
|
|
205
|
-
base.error = payload.error;
|
|
206
|
-
}
|
|
207
|
-
return base;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** Parse parent → child CHAT_SEND_RESULT (shell uses `buildChatSendResultMessage`). */
|
|
211
|
-
export function parseChatSendResultMessage(
|
|
212
|
-
data: unknown,
|
|
213
|
-
): MiniAppChatSendResultPayload | null {
|
|
214
|
-
if (!isRecord(data)) return null;
|
|
215
|
-
if (data.channel !== MINIAPP_CHANNEL) return null;
|
|
216
|
-
if (data.version !== MINIAPP_VERSION) return null;
|
|
217
|
-
if (data.type !== 'CHAT_SEND_RESULT') return null;
|
|
218
|
-
const payload = data.payload;
|
|
219
|
-
if (!isRecord(payload)) return null;
|
|
220
|
-
const requestId = payload.requestId;
|
|
221
|
-
if (typeof requestId !== 'string' || requestId.length === 0) return null;
|
|
222
|
-
|
|
223
|
-
if (payload.ok === true) {
|
|
224
|
-
const result = payload.result;
|
|
225
|
-
if (!isRecord(result)) return null;
|
|
226
|
-
const responseText = result.response;
|
|
227
|
-
if (typeof responseText !== 'string') return null;
|
|
228
|
-
const sidRaw = result.session_id;
|
|
229
|
-
if (sidRaw !== undefined && sidRaw !== null && typeof sidRaw !== 'string')
|
|
230
|
-
return null;
|
|
231
|
-
const session_id: string | null =
|
|
232
|
-
typeof sidRaw === 'string' ? sidRaw : null;
|
|
233
|
-
return {
|
|
234
|
-
requestId,
|
|
235
|
-
ok: true,
|
|
236
|
-
result: {
|
|
237
|
-
response: responseText,
|
|
238
|
-
session_id,
|
|
239
|
-
},
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
if (payload.ok === false) {
|
|
243
|
-
if (typeof payload.error !== 'string') return null;
|
|
244
|
-
return { requestId, ok: false, error: payload.error };
|
|
245
|
-
}
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ThemeDefaults, ThemeHelpers } from '@homecode/ui';
|
|
2
|
-
|
|
3
|
-
const { colors, getColors, getConfig } = ThemeDefaults;
|
|
4
|
-
|
|
5
|
-
const defaultPalette = getColors();
|
|
6
|
-
|
|
7
|
-
const colorsConfig = {
|
|
8
|
-
light: {
|
|
9
|
-
...ThemeHelpers.colorsConfigToVars({
|
|
10
|
-
...getColors({
|
|
11
|
-
accent: colors.dark,
|
|
12
|
-
decent: colors.light,
|
|
13
|
-
}),
|
|
14
|
-
}),
|
|
15
|
-
},
|
|
16
|
-
dark: {
|
|
17
|
-
...ThemeHelpers.colorsConfigToVars({
|
|
18
|
-
...getColors({
|
|
19
|
-
accent: colors.light,
|
|
20
|
-
decent: colors.dark,
|
|
21
|
-
}),
|
|
22
|
-
}),
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/** Homecode `<Theme config={...}>` shape for workspace mini-apps (generic palette). */
|
|
27
|
-
export function getDefaultMiniAppThemeConfig(isDarkMode: boolean) {
|
|
28
|
-
return {
|
|
29
|
-
...getConfig(),
|
|
30
|
-
...colorsConfig[isDarkMode ? 'dark' : 'light'],
|
|
31
|
-
...ThemeHelpers.colorsConfigToVars({
|
|
32
|
-
active: {
|
|
33
|
-
color: '#00a9c7',
|
|
34
|
-
mods: {
|
|
35
|
-
// @ts-ignore — extend defaults so --active-color-alpha-* variants match Homecode
|
|
36
|
-
alpha: [0, 50, 100, 200, ...defaultPalette.active.mods.alpha],
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
}),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export type MiniAppThemeConfig = ReturnType<
|
|
44
|
-
typeof getDefaultMiniAppThemeConfig
|
|
45
|
-
>;
|