@sparkvault/sdk-mobile 4.3.2 → 4.5.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/dist/client.d.ts +2 -2
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/notify.d.ts +84 -0
- package/dist/notify.js +49 -0
- package/dist/notify.js.map +1 -0
- package/dist/types.d.ts +9 -5
- package/package.json +1 -1
- package/src/client.ts +3 -3
- package/src/index.ts +12 -4
- package/src/notify.ts +132 -0
- package/src/types.ts +9 -5
- package/dist/push-tokens.d.ts +0 -12
- package/dist/push-tokens.js +0 -15
- package/dist/push-tokens.js.map +0 -1
- package/src/push-tokens.ts +0 -26
package/dist/client.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { MobileFoldersClient } from './folders.js';
|
|
|
6
6
|
import { MobileHealthClient } from './health.js';
|
|
7
7
|
import { type AuthEventListener } from './http.js';
|
|
8
8
|
import { MobileIngotsClient } from './ingots.js';
|
|
9
|
+
import { MobileNotifyClient } from './notify.js';
|
|
9
10
|
import { MobileProductsClient } from './products/index.js';
|
|
10
|
-
import { MobilePushTokensClient } from './push-tokens.js';
|
|
11
11
|
import { MobileSparksClient } from './sparks.js';
|
|
12
12
|
import { MobileUsersClient } from './users.js';
|
|
13
13
|
import { MobileVaultsClient } from './vaults.js';
|
|
@@ -21,7 +21,7 @@ export declare class SparkVaultMobile {
|
|
|
21
21
|
readonly health: MobileHealthClient;
|
|
22
22
|
readonly sparks: MobileSparksClient;
|
|
23
23
|
readonly entropy: MobileEntropyClient;
|
|
24
|
-
readonly
|
|
24
|
+
readonly notify: MobileNotifyClient;
|
|
25
25
|
readonly billing: MobileBillingClient;
|
|
26
26
|
readonly users: MobileUsersClient;
|
|
27
27
|
private readonly http;
|
package/dist/client.js
CHANGED
|
@@ -6,8 +6,8 @@ import { MobileFoldersClient } from './folders.js';
|
|
|
6
6
|
import { MobileHealthClient } from './health.js';
|
|
7
7
|
import { MobileHttpClient } from './http.js';
|
|
8
8
|
import { MobileIngotsClient } from './ingots.js';
|
|
9
|
+
import { MobileNotifyClient } from './notify.js';
|
|
9
10
|
import { MobileProductsClient } from './products/index.js';
|
|
10
|
-
import { MobilePushTokensClient } from './push-tokens.js';
|
|
11
11
|
import { MobileSparksClient } from './sparks.js';
|
|
12
12
|
import { MobileUsersClient } from './users.js';
|
|
13
13
|
import { MobileVaultsClient } from './vaults.js';
|
|
@@ -23,7 +23,7 @@ export class SparkVaultMobile {
|
|
|
23
23
|
this.health = new MobileHealthClient(this.config);
|
|
24
24
|
this.sparks = new MobileSparksClient(this.http);
|
|
25
25
|
this.entropy = new MobileEntropyClient(this.http);
|
|
26
|
-
this.
|
|
26
|
+
this.notify = new MobileNotifyClient(this.http);
|
|
27
27
|
this.billing = new MobileBillingClient(this.http);
|
|
28
28
|
this.users = new MobileUsersClient(this.http);
|
|
29
29
|
if (this.config.preloadIdentityConfig) {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAA0D,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAA0B,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAA0D,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAA0B,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,OAAO,gBAAgB;IAe3B,YAAY,MAA8B;QACxC,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE9C,IAAI,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,WAAW,CAAC,QAA2B;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,4BAA4B,CAAC,MAA8B;IACzE,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export { MobileSparksClient, } from './sparks.js';
|
|
|
13
13
|
export type { CreateSparkOptions, CreateSparkResponse, ListSparksOptions, ListSparksResponse, ShareSparkOptions, Spark, SparkResponse, } from './sparks.js';
|
|
14
14
|
export { MobileEntropyClient, } from './entropy.js';
|
|
15
15
|
export type { EntropyFormat, EntropyResponse, GenerateEntropyOptions, } from './entropy.js';
|
|
16
|
-
export {
|
|
17
|
-
export type {
|
|
16
|
+
export { MobileNotifyClient, } from './notify.js';
|
|
17
|
+
export type { NotificationInboxState, NotificationMarkState, NotificationRow, ListNotificationsOptions, ListNotificationsResponse, UnreadCountResponse, MarkNotificationStateOptions, MarkNotificationStateResponse, RegisterDeviceResponse, } from './notify.js';
|
|
18
18
|
export { MobileBillingClient, } from './billing.js';
|
|
19
19
|
export type { PortalSession, } from './billing.js';
|
|
20
20
|
export { MobileUsersClient, } from './users.js';
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { MobileIngotsClient, } from './ingots.js';
|
|
|
7
7
|
export { MobileHealthClient, } from './health.js';
|
|
8
8
|
export { MobileSparksClient, } from './sparks.js';
|
|
9
9
|
export { MobileEntropyClient, } from './entropy.js';
|
|
10
|
-
export {
|
|
10
|
+
export { MobileNotifyClient, } from './notify.js';
|
|
11
11
|
export { MobileBillingClient, } from './billing.js';
|
|
12
12
|
export { MobileUsersClient, } from './users.js';
|
|
13
13
|
export { MobileTusUploader, parseForgeUrl, } from './tus.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AASrB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAYrB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAUrB,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAMtB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AASrB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAYrB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAUrB,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAMtB,OAAO,EACL,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAYrB,OAAO,EACL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAItB,OAAO,EACL,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,aAAa,GACd,MAAM,UAAU,CAAC;AAKlB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,6BAA6B,EAC7B,4BAA4B,EAC5B,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
|
package/dist/notify.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { MobileHttpClient } from './http.js';
|
|
2
|
+
/** Inbox views the feed can be filtered to. `all` excludes archived rows. */
|
|
3
|
+
export type NotificationInboxState = 'all' | 'unseen' | 'unread' | 'archived';
|
|
4
|
+
/** Terminal display states the recipient can apply to one of their rows. */
|
|
5
|
+
export type NotificationMarkState = 'seen' | 'read' | 'archived';
|
|
6
|
+
/**
|
|
7
|
+
* A metadata-only inbox row. Rows are LOCKED pointers: the content lives behind
|
|
8
|
+
* the SparkLink (`sparklink_code`) and is never carried here — open the SparkLink
|
|
9
|
+
* to unseal it. Timestamps are epoch SECONDS.
|
|
10
|
+
*/
|
|
11
|
+
export interface NotificationRow {
|
|
12
|
+
notification_id: string;
|
|
13
|
+
send_id: string;
|
|
14
|
+
created_at: number;
|
|
15
|
+
title: string;
|
|
16
|
+
category: string;
|
|
17
|
+
type: string;
|
|
18
|
+
seen_at: number | null;
|
|
19
|
+
read_at: number | null;
|
|
20
|
+
archived_at: number | null;
|
|
21
|
+
sparklink_code: string;
|
|
22
|
+
locked: true;
|
|
23
|
+
thread_id?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ListNotificationsOptions {
|
|
26
|
+
state?: NotificationInboxState;
|
|
27
|
+
/** Page size, 1-100 (server default 50). */
|
|
28
|
+
limit?: number;
|
|
29
|
+
/** Opaque cursor from a prior response. */
|
|
30
|
+
cursor?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ListNotificationsResponse {
|
|
33
|
+
notifications: NotificationRow[];
|
|
34
|
+
/**
|
|
35
|
+
* Next-page cursor, or null on the last page. A page can be SHORT of `limit`
|
|
36
|
+
* yet still carry a non-null cursor (the state/sender filter is applied after
|
|
37
|
+
* the key query) — follow the cursor; never treat a short page as the end.
|
|
38
|
+
*/
|
|
39
|
+
cursor: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface UnreadCountResponse {
|
|
42
|
+
unread_count: number;
|
|
43
|
+
/** True when the true count is at/beyond the badge ceiling (render "N+"). */
|
|
44
|
+
capped: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface MarkNotificationStateOptions {
|
|
47
|
+
/** The row's `created_at` (epoch seconds), round-tripped from the list row. Required. */
|
|
48
|
+
createdAt: number;
|
|
49
|
+
state: NotificationMarkState;
|
|
50
|
+
}
|
|
51
|
+
export interface MarkNotificationStateResponse {
|
|
52
|
+
notification_id: string;
|
|
53
|
+
state: NotificationMarkState;
|
|
54
|
+
updated_at: number;
|
|
55
|
+
}
|
|
56
|
+
/** Response to registering/refreshing this device's push token. */
|
|
57
|
+
export interface RegisterDeviceResponse {
|
|
58
|
+
success: boolean;
|
|
59
|
+
created: boolean;
|
|
60
|
+
refreshed: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The signed-in user's first-party Notify surface: their own metadata-only inbox
|
|
64
|
+
* plus this device's push registration. The recipient is ALWAYS derived from the
|
|
65
|
+
* session on the server — no method takes a `recipient_id`, and any account/
|
|
66
|
+
* recipient a caller might try to supply is ignored.
|
|
67
|
+
*/
|
|
68
|
+
export declare class MobileNotifyClient {
|
|
69
|
+
private readonly http;
|
|
70
|
+
constructor(http: MobileHttpClient);
|
|
71
|
+
/** The caller's own inbox feed (newest first). */
|
|
72
|
+
getInbox(options?: ListNotificationsOptions): Promise<ListNotificationsResponse>;
|
|
73
|
+
/** Bounded unseen badge count for the caller's own inbox. */
|
|
74
|
+
getUnreadCount(): Promise<UnreadCountResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* Apply a terminal display state to one of the caller's own rows (idempotent).
|
|
77
|
+
* `createdAt` MUST be the row's own `created_at` — the id alone is insufficient.
|
|
78
|
+
*/
|
|
79
|
+
markState(notificationId: string, options: MarkNotificationStateOptions): Promise<MarkNotificationStateResponse>;
|
|
80
|
+
/** Register/refresh this device's Expo push token under the session user. */
|
|
81
|
+
registerDevice(pushToken: string): Promise<RegisterDeviceResponse>;
|
|
82
|
+
/** Deregister a device token (logout / disable notifications). */
|
|
83
|
+
unregisterDevice(tokenHash: string): Promise<void>;
|
|
84
|
+
}
|
package/dist/notify.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed-in user's first-party Notify surface: their own metadata-only inbox
|
|
3
|
+
* plus this device's push registration. The recipient is ALWAYS derived from the
|
|
4
|
+
* session on the server — no method takes a `recipient_id`, and any account/
|
|
5
|
+
* recipient a caller might try to supply is ignored.
|
|
6
|
+
*/
|
|
7
|
+
export class MobileNotifyClient {
|
|
8
|
+
constructor(http) {
|
|
9
|
+
this.http = http;
|
|
10
|
+
}
|
|
11
|
+
/** The caller's own inbox feed (newest first). */
|
|
12
|
+
async getInbox(options = {}) {
|
|
13
|
+
const params = new URLSearchParams();
|
|
14
|
+
if (options.state)
|
|
15
|
+
params.set('state', options.state);
|
|
16
|
+
if (options.limit)
|
|
17
|
+
params.set('limit', String(options.limit));
|
|
18
|
+
if (options.cursor)
|
|
19
|
+
params.set('cursor', options.cursor);
|
|
20
|
+
const query = params.toString();
|
|
21
|
+
const response = await this.http.get(query ? `/me/notifications?${query}` : '/me/notifications');
|
|
22
|
+
return response.data;
|
|
23
|
+
}
|
|
24
|
+
/** Bounded unseen badge count for the caller's own inbox. */
|
|
25
|
+
async getUnreadCount() {
|
|
26
|
+
const response = await this.http.get('/me/notifications/unread-count');
|
|
27
|
+
return response.data;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Apply a terminal display state to one of the caller's own rows (idempotent).
|
|
31
|
+
* `createdAt` MUST be the row's own `created_at` — the id alone is insufficient.
|
|
32
|
+
*/
|
|
33
|
+
async markState(notificationId, options) {
|
|
34
|
+
const response = await this.http.post(`/me/notifications/${encodeURIComponent(notificationId)}/state`, { created_at: options.createdAt, state: options.state });
|
|
35
|
+
return response.data;
|
|
36
|
+
}
|
|
37
|
+
/** Register/refresh this device's Expo push token under the session user. */
|
|
38
|
+
async registerDevice(pushToken) {
|
|
39
|
+
const response = await this.http.post('/me/notifications/devices', {
|
|
40
|
+
push_token: pushToken,
|
|
41
|
+
});
|
|
42
|
+
return response.data;
|
|
43
|
+
}
|
|
44
|
+
/** Deregister a device token (logout / disable notifications). */
|
|
45
|
+
async unregisterDevice(tokenHash) {
|
|
46
|
+
await this.http.delete(`/me/notifications/devices/${encodeURIComponent(tokenHash)}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"AAuEA;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IAG7B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,QAAQ,CAAC,UAAoC,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAEzD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAClC,KAAK,CAAC,CAAC,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAC3D,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,cAAc;QAClB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAsB,gCAAgC,CAAC,CAAC;QAC5F,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CACb,cAAsB,EACtB,OAAqC;QAErC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CACnC,qBAAqB,kBAAkB,CAAC,cAAc,CAAC,QAAQ,EAC/D,EAAE,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CACxD,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,cAAc,CAAC,SAAiB;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAyB,2BAA2B,EAAE;YACzF,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACtC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,6BAA6B,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACvF,CAAC;CACF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -135,13 +135,17 @@ export interface SubscriptionIdentityStatus {
|
|
|
135
135
|
state: PoolState;
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
|
-
* GET /v1/billing/subscription — the account's
|
|
139
|
-
* seats, capacity blocks, live pool usage, and Identity
|
|
140
|
-
* subscription / usage view. `
|
|
141
|
-
* `
|
|
138
|
+
* GET /v1/billing/subscription — the account's derived billing lifecycle,
|
|
139
|
+
* licensed vs. used seats, capacity blocks, live pool usage, and Identity
|
|
140
|
+
* attempts. Drives the subscription / usage view. `status` is the derived
|
|
141
|
+
* lifecycle label; `is_paying`/`is_entitled` are the booleans the UI gates on
|
|
142
|
+
* (paying vs merely entitled). `renewal_amount_usd` is a formatted dollars
|
|
143
|
+
* string; `renewal_date` is an epoch (seconds) or null when there is no plan.
|
|
142
144
|
*/
|
|
143
145
|
export interface SparkVaultSubscription {
|
|
144
|
-
|
|
146
|
+
status: 'free' | 'customer' | 'churned' | 'suspended';
|
|
147
|
+
is_paying: boolean;
|
|
148
|
+
is_entitled: boolean;
|
|
145
149
|
unlimited: boolean;
|
|
146
150
|
subscription_status: string | null;
|
|
147
151
|
past_due: boolean;
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -6,8 +6,8 @@ import { MobileFoldersClient } from './folders.js';
|
|
|
6
6
|
import { MobileHealthClient } from './health.js';
|
|
7
7
|
import { MobileHttpClient, type AuthEventListener } from './http.js';
|
|
8
8
|
import { MobileIngotsClient } from './ingots.js';
|
|
9
|
+
import { MobileNotifyClient } from './notify.js';
|
|
9
10
|
import { MobileProductsClient } from './products/index.js';
|
|
10
|
-
import { MobilePushTokensClient } from './push-tokens.js';
|
|
11
11
|
import { MobileSparksClient } from './sparks.js';
|
|
12
12
|
import { MobileUsersClient } from './users.js';
|
|
13
13
|
import { MobileVaultsClient } from './vaults.js';
|
|
@@ -22,7 +22,7 @@ export class SparkVaultMobile {
|
|
|
22
22
|
readonly health: MobileHealthClient;
|
|
23
23
|
readonly sparks: MobileSparksClient;
|
|
24
24
|
readonly entropy: MobileEntropyClient;
|
|
25
|
-
readonly
|
|
25
|
+
readonly notify: MobileNotifyClient;
|
|
26
26
|
readonly billing: MobileBillingClient;
|
|
27
27
|
readonly users: MobileUsersClient;
|
|
28
28
|
private readonly http: MobileHttpClient;
|
|
@@ -38,7 +38,7 @@ export class SparkVaultMobile {
|
|
|
38
38
|
this.health = new MobileHealthClient(this.config);
|
|
39
39
|
this.sparks = new MobileSparksClient(this.http);
|
|
40
40
|
this.entropy = new MobileEntropyClient(this.http);
|
|
41
|
-
this.
|
|
41
|
+
this.notify = new MobileNotifyClient(this.http);
|
|
42
42
|
this.billing = new MobileBillingClient(this.http);
|
|
43
43
|
this.users = new MobileUsersClient(this.http);
|
|
44
44
|
|
package/src/index.ts
CHANGED
|
@@ -65,11 +65,19 @@ export type {
|
|
|
65
65
|
GenerateEntropyOptions,
|
|
66
66
|
} from './entropy.js';
|
|
67
67
|
export {
|
|
68
|
-
|
|
69
|
-
} from './
|
|
68
|
+
MobileNotifyClient,
|
|
69
|
+
} from './notify.js';
|
|
70
70
|
export type {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
NotificationInboxState,
|
|
72
|
+
NotificationMarkState,
|
|
73
|
+
NotificationRow,
|
|
74
|
+
ListNotificationsOptions,
|
|
75
|
+
ListNotificationsResponse,
|
|
76
|
+
UnreadCountResponse,
|
|
77
|
+
MarkNotificationStateOptions,
|
|
78
|
+
MarkNotificationStateResponse,
|
|
79
|
+
RegisterDeviceResponse,
|
|
80
|
+
} from './notify.js';
|
|
73
81
|
export {
|
|
74
82
|
MobileBillingClient,
|
|
75
83
|
} from './billing.js';
|
package/src/notify.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { MobileHttpClient } from './http.js';
|
|
2
|
+
|
|
3
|
+
/** Inbox views the feed can be filtered to. `all` excludes archived rows. */
|
|
4
|
+
export type NotificationInboxState = 'all' | 'unseen' | 'unread' | 'archived';
|
|
5
|
+
|
|
6
|
+
/** Terminal display states the recipient can apply to one of their rows. */
|
|
7
|
+
export type NotificationMarkState = 'seen' | 'read' | 'archived';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A metadata-only inbox row. Rows are LOCKED pointers: the content lives behind
|
|
11
|
+
* the SparkLink (`sparklink_code`) and is never carried here — open the SparkLink
|
|
12
|
+
* to unseal it. Timestamps are epoch SECONDS.
|
|
13
|
+
*/
|
|
14
|
+
export interface NotificationRow {
|
|
15
|
+
notification_id: string;
|
|
16
|
+
send_id: string;
|
|
17
|
+
created_at: number;
|
|
18
|
+
title: string;
|
|
19
|
+
category: string;
|
|
20
|
+
type: string;
|
|
21
|
+
seen_at: number | null;
|
|
22
|
+
read_at: number | null;
|
|
23
|
+
archived_at: number | null;
|
|
24
|
+
sparklink_code: string;
|
|
25
|
+
locked: true;
|
|
26
|
+
thread_id?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ListNotificationsOptions {
|
|
30
|
+
state?: NotificationInboxState;
|
|
31
|
+
/** Page size, 1-100 (server default 50). */
|
|
32
|
+
limit?: number;
|
|
33
|
+
/** Opaque cursor from a prior response. */
|
|
34
|
+
cursor?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ListNotificationsResponse {
|
|
38
|
+
notifications: NotificationRow[];
|
|
39
|
+
/**
|
|
40
|
+
* Next-page cursor, or null on the last page. A page can be SHORT of `limit`
|
|
41
|
+
* yet still carry a non-null cursor (the state/sender filter is applied after
|
|
42
|
+
* the key query) — follow the cursor; never treat a short page as the end.
|
|
43
|
+
*/
|
|
44
|
+
cursor: string | null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface UnreadCountResponse {
|
|
48
|
+
unread_count: number;
|
|
49
|
+
/** True when the true count is at/beyond the badge ceiling (render "N+"). */
|
|
50
|
+
capped: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface MarkNotificationStateOptions {
|
|
54
|
+
/** The row's `created_at` (epoch seconds), round-tripped from the list row. Required. */
|
|
55
|
+
createdAt: number;
|
|
56
|
+
state: NotificationMarkState;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface MarkNotificationStateResponse {
|
|
60
|
+
notification_id: string;
|
|
61
|
+
state: NotificationMarkState;
|
|
62
|
+
updated_at: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Response to registering/refreshing this device's push token. */
|
|
66
|
+
export interface RegisterDeviceResponse {
|
|
67
|
+
success: boolean;
|
|
68
|
+
created: boolean;
|
|
69
|
+
refreshed: boolean;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The signed-in user's first-party Notify surface: their own metadata-only inbox
|
|
74
|
+
* plus this device's push registration. The recipient is ALWAYS derived from the
|
|
75
|
+
* session on the server — no method takes a `recipient_id`, and any account/
|
|
76
|
+
* recipient a caller might try to supply is ignored.
|
|
77
|
+
*/
|
|
78
|
+
export class MobileNotifyClient {
|
|
79
|
+
private readonly http: MobileHttpClient;
|
|
80
|
+
|
|
81
|
+
constructor(http: MobileHttpClient) {
|
|
82
|
+
this.http = http;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The caller's own inbox feed (newest first). */
|
|
86
|
+
async getInbox(options: ListNotificationsOptions = {}): Promise<ListNotificationsResponse> {
|
|
87
|
+
const params = new URLSearchParams();
|
|
88
|
+
if (options.state) params.set('state', options.state);
|
|
89
|
+
if (options.limit) params.set('limit', String(options.limit));
|
|
90
|
+
if (options.cursor) params.set('cursor', options.cursor);
|
|
91
|
+
|
|
92
|
+
const query = params.toString();
|
|
93
|
+
const response = await this.http.get<ListNotificationsResponse>(
|
|
94
|
+
query ? `/me/notifications?${query}` : '/me/notifications'
|
|
95
|
+
);
|
|
96
|
+
return response.data;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Bounded unseen badge count for the caller's own inbox. */
|
|
100
|
+
async getUnreadCount(): Promise<UnreadCountResponse> {
|
|
101
|
+
const response = await this.http.get<UnreadCountResponse>('/me/notifications/unread-count');
|
|
102
|
+
return response.data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Apply a terminal display state to one of the caller's own rows (idempotent).
|
|
107
|
+
* `createdAt` MUST be the row's own `created_at` — the id alone is insufficient.
|
|
108
|
+
*/
|
|
109
|
+
async markState(
|
|
110
|
+
notificationId: string,
|
|
111
|
+
options: MarkNotificationStateOptions
|
|
112
|
+
): Promise<MarkNotificationStateResponse> {
|
|
113
|
+
const response = await this.http.post<MarkNotificationStateResponse>(
|
|
114
|
+
`/me/notifications/${encodeURIComponent(notificationId)}/state`,
|
|
115
|
+
{ created_at: options.createdAt, state: options.state }
|
|
116
|
+
);
|
|
117
|
+
return response.data;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Register/refresh this device's Expo push token under the session user. */
|
|
121
|
+
async registerDevice(pushToken: string): Promise<RegisterDeviceResponse> {
|
|
122
|
+
const response = await this.http.post<RegisterDeviceResponse>('/me/notifications/devices', {
|
|
123
|
+
push_token: pushToken,
|
|
124
|
+
});
|
|
125
|
+
return response.data;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Deregister a device token (logout / disable notifications). */
|
|
129
|
+
async unregisterDevice(tokenHash: string): Promise<void> {
|
|
130
|
+
await this.http.delete(`/me/notifications/devices/${encodeURIComponent(tokenHash)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -157,13 +157,17 @@ export interface SubscriptionIdentityStatus {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
* GET /v1/billing/subscription — the account's
|
|
161
|
-
* seats, capacity blocks, live pool usage, and Identity
|
|
162
|
-
* subscription / usage view. `
|
|
163
|
-
* `
|
|
160
|
+
* GET /v1/billing/subscription — the account's derived billing lifecycle,
|
|
161
|
+
* licensed vs. used seats, capacity blocks, live pool usage, and Identity
|
|
162
|
+
* attempts. Drives the subscription / usage view. `status` is the derived
|
|
163
|
+
* lifecycle label; `is_paying`/`is_entitled` are the booleans the UI gates on
|
|
164
|
+
* (paying vs merely entitled). `renewal_amount_usd` is a formatted dollars
|
|
165
|
+
* string; `renewal_date` is an epoch (seconds) or null when there is no plan.
|
|
164
166
|
*/
|
|
165
167
|
export interface SparkVaultSubscription {
|
|
166
|
-
|
|
168
|
+
status: 'free' | 'customer' | 'churned' | 'suspended';
|
|
169
|
+
is_paying: boolean;
|
|
170
|
+
is_entitled: boolean;
|
|
167
171
|
unlimited: boolean;
|
|
168
172
|
subscription_status: string | null;
|
|
169
173
|
past_due: boolean;
|
package/dist/push-tokens.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { MobileHttpClient } from './http.js';
|
|
2
|
-
export interface RegisterPushTokenResponse {
|
|
3
|
-
success: boolean;
|
|
4
|
-
created: boolean;
|
|
5
|
-
refreshed: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare class MobilePushTokensClient {
|
|
8
|
-
private readonly http;
|
|
9
|
-
constructor(http: MobileHttpClient);
|
|
10
|
-
register(pushToken: string): Promise<RegisterPushTokenResponse>;
|
|
11
|
-
unregister(tokenHash: string): Promise<void>;
|
|
12
|
-
}
|
package/dist/push-tokens.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export class MobilePushTokensClient {
|
|
2
|
-
constructor(http) {
|
|
3
|
-
this.http = http;
|
|
4
|
-
}
|
|
5
|
-
async register(pushToken) {
|
|
6
|
-
const response = await this.http.post('/push-tokens', {
|
|
7
|
-
push_token: pushToken,
|
|
8
|
-
});
|
|
9
|
-
return response.data;
|
|
10
|
-
}
|
|
11
|
-
async unregister(tokenHash) {
|
|
12
|
-
await this.http.delete(`/push-tokens/${encodeURIComponent(tokenHash)}`);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=push-tokens.js.map
|
package/dist/push-tokens.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-tokens.js","sourceRoot":"","sources":["../src/push-tokens.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,sBAAsB;IAGjC,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB;QAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAA4B,cAAc,EAAE;YAC/E,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
package/src/push-tokens.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { MobileHttpClient } from './http.js';
|
|
2
|
-
|
|
3
|
-
export interface RegisterPushTokenResponse {
|
|
4
|
-
success: boolean;
|
|
5
|
-
created: boolean;
|
|
6
|
-
refreshed: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class MobilePushTokensClient {
|
|
10
|
-
private readonly http: MobileHttpClient;
|
|
11
|
-
|
|
12
|
-
constructor(http: MobileHttpClient) {
|
|
13
|
-
this.http = http;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async register(pushToken: string): Promise<RegisterPushTokenResponse> {
|
|
17
|
-
const response = await this.http.post<RegisterPushTokenResponse>('/push-tokens', {
|
|
18
|
-
push_token: pushToken,
|
|
19
|
-
});
|
|
20
|
-
return response.data;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async unregister(tokenHash: string): Promise<void> {
|
|
24
|
-
await this.http.delete(`/push-tokens/${encodeURIComponent(tokenHash)}`);
|
|
25
|
-
}
|
|
26
|
-
}
|