@theaiplatform/miniapp-sdk 0.1.0-dev.5264044 → 0.1.0-dev.e198ea6
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 +58 -2
- package/THIRD_PARTY_NOTICES.md +40 -14
- package/dist/index.d.ts +74 -0
- package/dist/rspack/index.js +119 -0
- package/dist/sdk.d.ts +74 -0
- package/dist/ui/styles.css +3694 -0
- package/dist/ui/tailwind.css +112 -0
- package/dist/ui/theme.css +335 -0
- package/dist/ui.d.ts +826 -0
- package/dist/ui.js +1852 -0
- package/dist/web.d.ts +93 -0
- package/dist/web.js +37 -1
- package/package.json +44 -3
- package/ui-components.json +59 -0
package/README.md
CHANGED
|
@@ -8,8 +8,9 @@ pnpm add @theaiplatform/miniapp-sdk
|
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
The package provides the host-injected SDK API, isolated surface lifecycle
|
|
11
|
-
types, browser helpers, manifest schema, and the
|
|
12
|
-
to produce descriptor-backed Module Federation
|
|
11
|
+
types, browser helpers, portable React UI components, manifest schema, and the
|
|
12
|
+
Rspack/Rslib integration used to produce descriptor-backed Module Federation
|
|
13
|
+
targets.
|
|
13
14
|
|
|
14
15
|
Start with the [Miniapp SDK documentation](https://docs.theaiplatform.app/miniapps/).
|
|
15
16
|
|
|
@@ -18,6 +19,10 @@ Start with the [Miniapp SDK documentation](https://docs.theaiplatform.app/miniap
|
|
|
18
19
|
- `@theaiplatform/miniapp-sdk`
|
|
19
20
|
- `@theaiplatform/miniapp-sdk/sdk`
|
|
20
21
|
- `@theaiplatform/miniapp-sdk/web`
|
|
22
|
+
- `@theaiplatform/miniapp-sdk/ui`
|
|
23
|
+
- `@theaiplatform/miniapp-sdk/ui/styles.css`
|
|
24
|
+
- `@theaiplatform/miniapp-sdk/ui/tailwind.css`
|
|
25
|
+
- `@theaiplatform/miniapp-sdk/ui-components.json`
|
|
21
26
|
- `@theaiplatform/miniapp-sdk/surface`
|
|
22
27
|
- `@theaiplatform/miniapp-sdk/config`
|
|
23
28
|
- `@theaiplatform/miniapp-sdk/rspack`
|
|
@@ -25,6 +30,57 @@ Start with the [Miniapp SDK documentation](https://docs.theaiplatform.app/miniap
|
|
|
25
30
|
|
|
26
31
|
The host API is injected at runtime. Importing an entry point is safe in build
|
|
27
32
|
tools and tests; host-backed calls fail when used outside a supported runtime.
|
|
33
|
+
`sdk.storage` provides revisioned non-secret JSON scoped by the host to the
|
|
34
|
+
active workspace and exact package. `sdk.presence` provides host-stamped,
|
|
35
|
+
ephemeral room membership and state; package code never supplies participant
|
|
36
|
+
identity.
|
|
37
|
+
|
|
38
|
+
## Portable UI
|
|
39
|
+
|
|
40
|
+
Import the precompiled stylesheet once at the miniapp entry point, then use
|
|
41
|
+
components from the public UI entry. React 19 is a peer dependency.
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import '@theaiplatform/miniapp-sdk/ui/styles.css';
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
Button,
|
|
48
|
+
Card,
|
|
49
|
+
CardContent,
|
|
50
|
+
CardHeader,
|
|
51
|
+
CardTitle,
|
|
52
|
+
} from '@theaiplatform/miniapp-sdk/ui';
|
|
53
|
+
|
|
54
|
+
export function WelcomeCard() {
|
|
55
|
+
return (
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle>Ready to build</CardTitle>
|
|
59
|
+
</CardHeader>
|
|
60
|
+
<CardContent>
|
|
61
|
+
<Button>Continue</Button>
|
|
62
|
+
</CardContent>
|
|
63
|
+
</Card>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Tailwind v4 miniapps can instead import the source integration after
|
|
69
|
+
`tailwindcss` and `tw-animate-css`; it supplies the platform theme and scans the
|
|
70
|
+
SDK's UI bundle for component classes.
|
|
71
|
+
|
|
72
|
+
```css
|
|
73
|
+
@import 'tailwindcss' source(none);
|
|
74
|
+
@import 'tw-animate-css';
|
|
75
|
+
@import '@theaiplatform/miniapp-sdk/ui/tailwind.css';
|
|
76
|
+
|
|
77
|
+
@source './src';
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `installMiniAppAppearanceSync()` from the `/web` entry to apply the host's
|
|
81
|
+
light/dark theme and bounded UI scale. Tools and agents can read the exported
|
|
82
|
+
`ui-components.json` catalog to discover the supported component families and
|
|
83
|
+
style entry points without importing application-private packages.
|
|
28
84
|
|
|
29
85
|
## License and public policies
|
|
30
86
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -2,26 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
## Scope
|
|
4
4
|
|
|
5
|
-
The `@theaiplatform/miniapp-sdk`
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
The `@theaiplatform/miniapp-sdk` JavaScript entries import separately installed
|
|
6
|
+
runtime dependencies. Its precompiled UI stylesheet is generated with
|
|
7
|
+
Tailwind CSS and `tw-animate-css`; the Tailwind integration stylesheet is
|
|
8
|
+
distributed as source. Optional peer dependencies are not distributed with
|
|
9
|
+
this package and remain subject to their own licenses.
|
|
9
10
|
|
|
10
11
|
The inventory below records the direct and transitive runtime dependency
|
|
11
|
-
versions resolved by the release workspace lockfile on July
|
|
12
|
+
versions resolved by the release workspace lockfile on July 16, 2026. A
|
|
12
13
|
downstream application may resolve a different compatible transitive version
|
|
13
14
|
and is responsible for reviewing the notices required by its own lockfile and
|
|
14
15
|
distribution artifact.
|
|
15
16
|
|
|
16
|
-
| Relationship | Package
|
|
17
|
-
| ---------------- |
|
|
18
|
-
| Direct
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
| Direct
|
|
24
|
-
|
|
|
17
|
+
| Relationship | Package | Version | License |
|
|
18
|
+
| ---------------- | ------------------------------ | ------: | ------------ |
|
|
19
|
+
| Direct UI | `@radix-ui/react-alert-dialog` | 1.1.15 | MIT |
|
|
20
|
+
| Direct UI | `@radix-ui/react-checkbox` | 1.3.3 | MIT |
|
|
21
|
+
| Direct UI | `@radix-ui/react-compose-refs` | 1.1.2 | MIT |
|
|
22
|
+
| Direct UI | `@radix-ui/react-dialog` | 1.1.15 | MIT |
|
|
23
|
+
| Direct UI | `@radix-ui/react-label` | 2.1.8 | MIT |
|
|
24
|
+
| Direct UI | `@radix-ui/react-progress` | 1.1.8 | MIT |
|
|
25
|
+
| Direct UI | `@radix-ui/react-radio-group` | 1.3.8 | MIT |
|
|
26
|
+
| Direct UI | `@radix-ui/react-scroll-area` | 1.2.10 | MIT |
|
|
27
|
+
| Direct UI | `@radix-ui/react-select` | 2.2.6 | MIT |
|
|
28
|
+
| Direct UI | `@radix-ui/react-separator` | 1.1.8 | MIT |
|
|
29
|
+
| Direct UI | `@radix-ui/react-slider` | 1.3.6 | MIT |
|
|
30
|
+
| Direct UI | `@radix-ui/react-slot` | 1.2.4 | MIT |
|
|
31
|
+
| Direct UI | `@radix-ui/react-tabs` | 1.1.13 | MIT |
|
|
32
|
+
| Direct UI | `@radix-ui/react-toggle` | 1.1.10 | MIT |
|
|
33
|
+
| Direct UI | `@radix-ui/react-toggle-group` | 1.1.11 | MIT |
|
|
34
|
+
| Direct UI | `@radix-ui/react-tooltip` | 1.2.8 | MIT |
|
|
35
|
+
| Direct UI | `class-variance-authority` | 0.7.1 | Apache-2.0 |
|
|
36
|
+
| Direct UI | `clsx` | 2.1.1 | MIT |
|
|
37
|
+
| Direct UI | `lucide-react` | 1.20.0 | ISC |
|
|
38
|
+
| Direct UI | `prism-react-renderer` | 2.4.1 | MIT |
|
|
39
|
+
| Direct UI | `react-resizable-panels` | 4.11.1 | MIT |
|
|
40
|
+
| Direct UI | `tailwind-merge` | 3.6.0 | MIT |
|
|
41
|
+
| Styles build | `@tailwindcss/postcss` | 4.3.0 | MIT |
|
|
42
|
+
| Styles build | `tailwindcss` | 4.3.0 | MIT |
|
|
43
|
+
| Styles build | `tw-animate-css` | 1.4.0 | MIT |
|
|
44
|
+
| Direct | `ajv` | 8.20.0 | MIT |
|
|
45
|
+
| Ajv transitive | `fast-deep-equal` | 3.1.3 | MIT |
|
|
46
|
+
| Ajv transitive | `fast-uri` | 3.1.2 | BSD-3-Clause |
|
|
47
|
+
| Ajv transitive | `json-schema-traverse` | 1.0.0 | MIT |
|
|
48
|
+
| Ajv transitive | `require-from-string` | 2.0.2 | MIT |
|
|
49
|
+
| Direct | `saxes` | 6.0.0 | ISC |
|
|
50
|
+
| Saxes transitive | `xmlchars` | 2.2.0 | MIT |
|
|
25
51
|
|
|
26
52
|
## License texts
|
|
27
53
|
|
package/dist/index.d.ts
CHANGED
|
@@ -245,6 +245,8 @@ export declare type MiniAppPlatformApi = {
|
|
|
245
245
|
open(options: OpenNavigationOptions): void | Promise<void>;
|
|
246
246
|
};
|
|
247
247
|
chat: MiniAppChatApi;
|
|
248
|
+
storage: MiniAppStorageApi;
|
|
249
|
+
presence: MiniAppPresenceApi;
|
|
248
250
|
/** Browser capabilities appear only when the selected target supports them. */
|
|
249
251
|
auth?: MiniAppAuthApi;
|
|
250
252
|
vfs?: MiniAppVfsApi;
|
|
@@ -253,6 +255,41 @@ export declare type MiniAppPlatformApi = {
|
|
|
253
255
|
hasHostHttpRequest?: boolean;
|
|
254
256
|
};
|
|
255
257
|
|
|
258
|
+
export declare type MiniAppPresenceAddress = {
|
|
259
|
+
namespace: string;
|
|
260
|
+
room: string;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Ephemeral realtime presence scoped by the host to the active workspace and
|
|
265
|
+
* exact package. Participant identity is stamped by the host, not the app.
|
|
266
|
+
*/
|
|
267
|
+
export declare type MiniAppPresenceApi = {
|
|
268
|
+
join(options: MiniAppPresenceUpdateOptions): MiniAppMaybePromise<MiniAppPresenceSnapshot>;
|
|
269
|
+
update(options: MiniAppPresenceUpdateOptions): MiniAppMaybePromise<MiniAppPresenceSnapshot>;
|
|
270
|
+
leave(options: MiniAppPresenceAddress): MiniAppMaybePromise<void>;
|
|
271
|
+
subscribe(options: MiniAppPresenceAddress, listener: MiniAppPresenceListener): () => void;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export declare type MiniAppPresenceListener = (snapshot: MiniAppPresenceSnapshot) => void;
|
|
275
|
+
|
|
276
|
+
export declare type MiniAppPresenceParticipant = {
|
|
277
|
+
/** Host-derived, ephemeral participant identity. */
|
|
278
|
+
participantId: string;
|
|
279
|
+
displayName: string;
|
|
280
|
+
state: MiniAppJsonValue;
|
|
281
|
+
updatedAtMs: number;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export declare type MiniAppPresenceSnapshot = MiniAppPresenceAddress & {
|
|
285
|
+
selfParticipantId: string;
|
|
286
|
+
participants: MiniAppPresenceParticipant[];
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
export declare type MiniAppPresenceUpdateOptions = MiniAppPresenceAddress & {
|
|
290
|
+
state: MiniAppJsonValue;
|
|
291
|
+
};
|
|
292
|
+
|
|
256
293
|
export declare type MiniAppProject = {
|
|
257
294
|
id: string;
|
|
258
295
|
name: string;
|
|
@@ -352,6 +389,43 @@ export declare type MiniAppSpecialistTurnResult = {
|
|
|
352
389
|
};
|
|
353
390
|
};
|
|
354
391
|
|
|
392
|
+
/** Caller-selected partition inside the host-derived workspace/package scope. */
|
|
393
|
+
export declare type MiniAppStorageAddress = {
|
|
394
|
+
namespace: string;
|
|
395
|
+
key: string;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Durable, non-secret JSON storage. The host derives workspace and package
|
|
400
|
+
* identity from the authenticated frame; apps control only the namespace and
|
|
401
|
+
* key inside that scope.
|
|
402
|
+
*/
|
|
403
|
+
export declare type MiniAppStorageApi = {
|
|
404
|
+
get(options: MiniAppStorageAddress): MiniAppMaybePromise<MiniAppStorageEntry>;
|
|
405
|
+
set(options: MiniAppStorageSetOptions): MiniAppMaybePromise<MiniAppStorageMutationResult>;
|
|
406
|
+
delete(options: MiniAppStorageDeleteOptions): MiniAppMaybePromise<void>;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
export declare type MiniAppStorageDeleteOptions = MiniAppStorageAddress & {
|
|
410
|
+
expectedRevision: number;
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
export declare type MiniAppStorageEntry = {
|
|
414
|
+
value: MiniAppJsonValue | null;
|
|
415
|
+
/** Null means that no value currently exists at this address. */
|
|
416
|
+
revision: number | null;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
export declare type MiniAppStorageMutationResult = {
|
|
420
|
+
revision: number;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
export declare type MiniAppStorageSetOptions = MiniAppStorageAddress & {
|
|
424
|
+
value: MiniAppJsonValue;
|
|
425
|
+
/** Optimistic concurrency token returned by `get`; null creates a missing key. */
|
|
426
|
+
expectedRevision: number | null;
|
|
427
|
+
};
|
|
428
|
+
|
|
355
429
|
export declare type MiniAppUserProfile = {
|
|
356
430
|
sub: string;
|
|
357
431
|
name?: string | null;
|
package/dist/rspack/index.js
CHANGED
|
@@ -444,8 +444,15 @@ const HOST_ACTION_RESPONSE = 'tap-miniapp-host-action-response';
|
|
|
444
444
|
const MAX_PENDING_HOST_ACTIONS = 32;
|
|
445
445
|
const MAX_CHECKPOINT_REFERENCE_CHARS = 512;
|
|
446
446
|
const MAX_CHECKPOINT_JSON_BYTES = 32 * 1024;
|
|
447
|
+
const MAX_STORAGE_NAMESPACE_CHARS = 128;
|
|
448
|
+
const MAX_STORAGE_KEY_CHARS = 512;
|
|
449
|
+
const MAX_STORAGE_JSON_BYTES = 5 * 1024 * 1024;
|
|
450
|
+
const MAX_PRESENCE_ROOM_CHARS = 256;
|
|
451
|
+
const MAX_PRESENCE_JSON_BYTES = 16 * 1024;
|
|
452
|
+
const PRESENCE_EVENT = 'tap-miniapp-presence-event';
|
|
447
453
|
const HOST_ACTION_TIMEOUT_MS = 4000;
|
|
448
454
|
const pendingHostActions = new Map();
|
|
455
|
+
const presenceListeners = new Map();
|
|
449
456
|
let hostActionSequence = 0;
|
|
450
457
|
const validCheckpointReference = (reference) =>
|
|
451
458
|
typeof reference === 'string' &&
|
|
@@ -465,6 +472,24 @@ const checkedCheckpointValue = (value) => {
|
|
|
465
472
|
}
|
|
466
473
|
return value;
|
|
467
474
|
};
|
|
475
|
+
const validPlatformPartition = (value, maximumLength) =>
|
|
476
|
+
typeof value === 'string' &&
|
|
477
|
+
value.length > 0 &&
|
|
478
|
+
value.trim() === value &&
|
|
479
|
+
Array.from(value).length <= maximumLength &&
|
|
480
|
+
!/[\u0000-\u001f\u007f-\u009f]/u.test(value);
|
|
481
|
+
const checkedPlatformJson = (value, maximumBytes, label) => {
|
|
482
|
+
let encoded;
|
|
483
|
+
try {
|
|
484
|
+
encoded = JSON.stringify(value);
|
|
485
|
+
} catch {
|
|
486
|
+
throw new Error(label + ' must be JSON serializable.');
|
|
487
|
+
}
|
|
488
|
+
if (encoded === undefined || new TextEncoder().encode(encoded).byteLength > maximumBytes) {
|
|
489
|
+
throw new Error(label + ' exceeds the allowed size.');
|
|
490
|
+
}
|
|
491
|
+
return value;
|
|
492
|
+
};
|
|
468
493
|
const requestHostAction = (action, payload, timeoutMs = HOST_ACTION_TIMEOUT_MS) => {
|
|
469
494
|
if (pendingHostActions.size >= MAX_PENDING_HOST_ACTIONS) {
|
|
470
495
|
return Promise.reject(new Error('Too many miniapp host actions are pending.'));
|
|
@@ -619,6 +644,79 @@ const invokeSdkHostAction = (action, options, label, timeoutMs = HOST_ACTION_TIM
|
|
|
619
644
|
requestHostAction(action, {
|
|
620
645
|
options: requireOptionsObject(options, label),
|
|
621
646
|
}, timeoutMs);
|
|
647
|
+
const checkedStorageAddress = (options, label) => {
|
|
648
|
+
requireOptionsObject(options, label);
|
|
649
|
+
if (!validPlatformPartition(options.namespace, MAX_STORAGE_NAMESPACE_CHARS)) {
|
|
650
|
+
throw new Error(label + ' requires a valid namespace.');
|
|
651
|
+
}
|
|
652
|
+
if (!validPlatformPartition(options.key, MAX_STORAGE_KEY_CHARS)) {
|
|
653
|
+
throw new Error(label + ' requires a valid key.');
|
|
654
|
+
}
|
|
655
|
+
return options;
|
|
656
|
+
};
|
|
657
|
+
const storage = Object.freeze({
|
|
658
|
+
get(options) {
|
|
659
|
+
checkedStorageAddress(options, 'app.storage.get');
|
|
660
|
+
return invokeSdkHostAction('tap.platform.storage.get', options, 'app.storage.get');
|
|
661
|
+
},
|
|
662
|
+
set(options) {
|
|
663
|
+
checkedStorageAddress(options, 'app.storage.set');
|
|
664
|
+
if (options.expectedRevision !== null &&
|
|
665
|
+
(!Number.isInteger(options.expectedRevision) || options.expectedRevision < 1)) {
|
|
666
|
+
throw new Error('app.storage.set expectedRevision must be null or a positive integer.');
|
|
667
|
+
}
|
|
668
|
+
checkedPlatformJson(options.value, MAX_STORAGE_JSON_BYTES, 'app.storage.set value');
|
|
669
|
+
return invokeSdkHostAction('tap.platform.storage.set', options, 'app.storage.set', 12000);
|
|
670
|
+
},
|
|
671
|
+
delete(options) {
|
|
672
|
+
checkedStorageAddress(options, 'app.storage.delete');
|
|
673
|
+
if (!Number.isInteger(options.expectedRevision) || options.expectedRevision < 1) {
|
|
674
|
+
throw new Error('app.storage.delete expectedRevision must be a positive integer.');
|
|
675
|
+
}
|
|
676
|
+
return invokeSdkHostAction('tap.platform.storage.delete', options, 'app.storage.delete');
|
|
677
|
+
},
|
|
678
|
+
});
|
|
679
|
+
const checkedPresenceAddress = (options, label) => {
|
|
680
|
+
requireOptionsObject(options, label);
|
|
681
|
+
if (!validPlatformPartition(options.namespace, MAX_STORAGE_NAMESPACE_CHARS)) {
|
|
682
|
+
throw new Error(label + ' requires a valid namespace.');
|
|
683
|
+
}
|
|
684
|
+
if (!validPlatformPartition(options.room, MAX_PRESENCE_ROOM_CHARS)) {
|
|
685
|
+
throw new Error(label + ' requires a valid room.');
|
|
686
|
+
}
|
|
687
|
+
return options;
|
|
688
|
+
};
|
|
689
|
+
const presenceKey = (options) => options.namespace + '\u0000' + options.room;
|
|
690
|
+
const presence = Object.freeze({
|
|
691
|
+
join(options) {
|
|
692
|
+
checkedPresenceAddress(options, 'app.presence.join');
|
|
693
|
+
checkedPlatformJson(options.state, MAX_PRESENCE_JSON_BYTES, 'app.presence.join state');
|
|
694
|
+
return invokeSdkHostAction('tap.platform.presence.join', options, 'app.presence.join');
|
|
695
|
+
},
|
|
696
|
+
update(options) {
|
|
697
|
+
checkedPresenceAddress(options, 'app.presence.update');
|
|
698
|
+
checkedPlatformJson(options.state, MAX_PRESENCE_JSON_BYTES, 'app.presence.update state');
|
|
699
|
+
return invokeSdkHostAction('tap.platform.presence.update', options, 'app.presence.update');
|
|
700
|
+
},
|
|
701
|
+
leave(options) {
|
|
702
|
+
checkedPresenceAddress(options, 'app.presence.leave');
|
|
703
|
+
return invokeSdkHostAction('tap.platform.presence.leave', options, 'app.presence.leave');
|
|
704
|
+
},
|
|
705
|
+
subscribe(options, listener) {
|
|
706
|
+
checkedPresenceAddress(options, 'app.presence.subscribe');
|
|
707
|
+
if (typeof listener !== 'function') {
|
|
708
|
+
throw new Error('app.presence.subscribe requires a listener.');
|
|
709
|
+
}
|
|
710
|
+
const key = presenceKey(options);
|
|
711
|
+
const listeners = presenceListeners.get(key) ?? new Set();
|
|
712
|
+
listeners.add(listener);
|
|
713
|
+
presenceListeners.set(key, listeners);
|
|
714
|
+
return () => {
|
|
715
|
+
listeners.delete(listener);
|
|
716
|
+
if (listeners.size === 0) presenceListeners.delete(key);
|
|
717
|
+
};
|
|
718
|
+
},
|
|
719
|
+
});
|
|
622
720
|
const channels = Object.freeze({
|
|
623
721
|
create(options) {
|
|
624
722
|
requireOptionString(options?.name, 'app.channels.create name');
|
|
@@ -893,6 +991,8 @@ const miniappSdk = Object.freeze({
|
|
|
893
991
|
workflows,
|
|
894
992
|
navigation,
|
|
895
993
|
chat: miniappChat,
|
|
994
|
+
storage,
|
|
995
|
+
presence,
|
|
896
996
|
auth: platformAuth,
|
|
897
997
|
vfs: platformVfs,
|
|
898
998
|
specialist: platformSpecialist,
|
|
@@ -1021,6 +1121,24 @@ const onHostMessage = async (event) => {
|
|
|
1021
1121
|
}
|
|
1022
1122
|
return;
|
|
1023
1123
|
}
|
|
1124
|
+
if (
|
|
1125
|
+
message.type === PRESENCE_EVENT &&
|
|
1126
|
+
validPlatformPartition(message.namespace, MAX_STORAGE_NAMESPACE_CHARS) &&
|
|
1127
|
+
validPlatformPartition(message.room, MAX_PRESENCE_ROOM_CHARS) &&
|
|
1128
|
+
typeof message.selfParticipantId === 'string' &&
|
|
1129
|
+
Array.isArray(message.participants)
|
|
1130
|
+
) {
|
|
1131
|
+
const snapshot = Object.freeze({
|
|
1132
|
+
namespace: message.namespace,
|
|
1133
|
+
room: message.room,
|
|
1134
|
+
selfParticipantId: message.selfParticipantId,
|
|
1135
|
+
participants: message.participants,
|
|
1136
|
+
});
|
|
1137
|
+
for (const listener of presenceListeners.get(presenceKey(snapshot)) ?? []) {
|
|
1138
|
+
try { await listener(snapshot); } catch { /* isolate observer failures */ }
|
|
1139
|
+
}
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1024
1142
|
if (message.type === HOST_ACTION_RESPONSE) {
|
|
1025
1143
|
const requestId = typeof message.id === 'string' ? message.id : '';
|
|
1026
1144
|
const pending = pendingHostActions.get(requestId);
|
|
@@ -1141,6 +1259,7 @@ window.addEventListener('pagehide', () => {
|
|
|
1141
1259
|
window.removeEventListener('message', onHostMessage);
|
|
1142
1260
|
eventListeners.clear();
|
|
1143
1261
|
hostAuthorityListeners.clear();
|
|
1262
|
+
presenceListeners.clear();
|
|
1144
1263
|
for (const pending of pendingHostActions.values()) {
|
|
1145
1264
|
clearTimeout(pending.timeout);
|
|
1146
1265
|
pending.reject(new Error('The mini app document was removed.'));
|
package/dist/sdk.d.ts
CHANGED
|
@@ -234,6 +234,8 @@ export declare type MiniAppPlatformApi = {
|
|
|
234
234
|
open(options: OpenNavigationOptions): void | Promise<void>;
|
|
235
235
|
};
|
|
236
236
|
chat: MiniAppChatApi;
|
|
237
|
+
storage: MiniAppStorageApi;
|
|
238
|
+
presence: MiniAppPresenceApi;
|
|
237
239
|
/** Browser capabilities appear only when the selected target supports them. */
|
|
238
240
|
auth?: MiniAppAuthApi;
|
|
239
241
|
vfs?: MiniAppVfsApi;
|
|
@@ -242,6 +244,41 @@ export declare type MiniAppPlatformApi = {
|
|
|
242
244
|
hasHostHttpRequest?: boolean;
|
|
243
245
|
};
|
|
244
246
|
|
|
247
|
+
export declare type MiniAppPresenceAddress = {
|
|
248
|
+
namespace: string;
|
|
249
|
+
room: string;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Ephemeral realtime presence scoped by the host to the active workspace and
|
|
254
|
+
* exact package. Participant identity is stamped by the host, not the app.
|
|
255
|
+
*/
|
|
256
|
+
export declare type MiniAppPresenceApi = {
|
|
257
|
+
join(options: MiniAppPresenceUpdateOptions): MiniAppMaybePromise<MiniAppPresenceSnapshot>;
|
|
258
|
+
update(options: MiniAppPresenceUpdateOptions): MiniAppMaybePromise<MiniAppPresenceSnapshot>;
|
|
259
|
+
leave(options: MiniAppPresenceAddress): MiniAppMaybePromise<void>;
|
|
260
|
+
subscribe(options: MiniAppPresenceAddress, listener: MiniAppPresenceListener): () => void;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
export declare type MiniAppPresenceListener = (snapshot: MiniAppPresenceSnapshot) => void;
|
|
264
|
+
|
|
265
|
+
export declare type MiniAppPresenceParticipant = {
|
|
266
|
+
/** Host-derived, ephemeral participant identity. */
|
|
267
|
+
participantId: string;
|
|
268
|
+
displayName: string;
|
|
269
|
+
state: MiniAppJsonValue;
|
|
270
|
+
updatedAtMs: number;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
export declare type MiniAppPresenceSnapshot = MiniAppPresenceAddress & {
|
|
274
|
+
selfParticipantId: string;
|
|
275
|
+
participants: MiniAppPresenceParticipant[];
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
export declare type MiniAppPresenceUpdateOptions = MiniAppPresenceAddress & {
|
|
279
|
+
state: MiniAppJsonValue;
|
|
280
|
+
};
|
|
281
|
+
|
|
245
282
|
export declare type MiniAppProject = {
|
|
246
283
|
id: string;
|
|
247
284
|
name: string;
|
|
@@ -341,6 +378,43 @@ export declare type MiniAppSpecialistTurnResult = {
|
|
|
341
378
|
};
|
|
342
379
|
};
|
|
343
380
|
|
|
381
|
+
/** Caller-selected partition inside the host-derived workspace/package scope. */
|
|
382
|
+
export declare type MiniAppStorageAddress = {
|
|
383
|
+
namespace: string;
|
|
384
|
+
key: string;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Durable, non-secret JSON storage. The host derives workspace and package
|
|
389
|
+
* identity from the authenticated frame; apps control only the namespace and
|
|
390
|
+
* key inside that scope.
|
|
391
|
+
*/
|
|
392
|
+
export declare type MiniAppStorageApi = {
|
|
393
|
+
get(options: MiniAppStorageAddress): MiniAppMaybePromise<MiniAppStorageEntry>;
|
|
394
|
+
set(options: MiniAppStorageSetOptions): MiniAppMaybePromise<MiniAppStorageMutationResult>;
|
|
395
|
+
delete(options: MiniAppStorageDeleteOptions): MiniAppMaybePromise<void>;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
export declare type MiniAppStorageDeleteOptions = MiniAppStorageAddress & {
|
|
399
|
+
expectedRevision: number;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
export declare type MiniAppStorageEntry = {
|
|
403
|
+
value: MiniAppJsonValue | null;
|
|
404
|
+
/** Null means that no value currently exists at this address. */
|
|
405
|
+
revision: number | null;
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
export declare type MiniAppStorageMutationResult = {
|
|
409
|
+
revision: number;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
export declare type MiniAppStorageSetOptions = MiniAppStorageAddress & {
|
|
413
|
+
value: MiniAppJsonValue;
|
|
414
|
+
/** Optimistic concurrency token returned by `get`; null creates a missing key. */
|
|
415
|
+
expectedRevision: number | null;
|
|
416
|
+
};
|
|
417
|
+
|
|
344
418
|
export declare type MiniAppUserProfile = {
|
|
345
419
|
sub: string;
|
|
346
420
|
name?: string | null;
|