@pmate/chat-sdk 0.12.0-next.72 → 0.12.0-next.74
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/lib/chatContract.d.ts +3 -0
- package/lib/chatTypes.d.ts +9 -3
- package/lib/internal/chatEngine.d.ts +16 -17
- package/lib/internal/chatEngine.js +3 -2
- package/lib/internal/createPublicChat.js +1 -1
- package/lib/messageView.js +1 -1
- package/lib/runtime/chatClient.d.ts +5 -0
- package/lib/runtime/chatClient.js +6 -0
- package/lib/runtime/chatSession.d.ts +3 -0
- package/lib/runtime/chatSession.js +13 -1
- package/lib/runtime/durableSender.js +1 -1
- package/lib/runtime/groupClient.d.ts +13 -1
- package/lib/runtime/groupClient.js +10 -3
- package/lib/runtime/messageStore.js +2 -1
- package/lib/runtime/outgoingContent.d.ts +5 -0
- package/lib/runtime/outgoingContent.js +6 -1
- package/lib/runtime/responseCache.js +1 -1
- package/lib/runtime/socialReadClient.d.ts +5 -2
- package/package.json +17 -16
package/lib/chatContract.d.ts
CHANGED
package/lib/chatTypes.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type ChatMessage = Readonly<{
|
|
|
52
52
|
mentions?: readonly ChatMention[];
|
|
53
53
|
recipientCount?: number;
|
|
54
54
|
system?: Readonly<{
|
|
55
|
-
type: "group-created" | "group-updated" | "contact-updated";
|
|
55
|
+
type: "group-created" | "group-updated" | "group-dissolved" | "contact-updated";
|
|
56
56
|
title?: string;
|
|
57
57
|
}>;
|
|
58
58
|
}>;
|
|
@@ -60,11 +60,17 @@ export type ChatGroup = Readonly<{
|
|
|
60
60
|
groupId: string;
|
|
61
61
|
teamId: string;
|
|
62
62
|
ownerId: string;
|
|
63
|
+
revision: string;
|
|
64
|
+
} & ({
|
|
65
|
+
status: "active";
|
|
63
66
|
title: string;
|
|
64
67
|
avatar?: string;
|
|
65
68
|
memberIds: readonly string[];
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
} | {
|
|
70
|
+
status: "dissolved";
|
|
71
|
+
dissolvedBy?: string;
|
|
72
|
+
dissolvedAt?: number;
|
|
73
|
+
})>;
|
|
68
74
|
export type ConversationInfo = Readonly<{
|
|
69
75
|
kind: "dm" | "group";
|
|
70
76
|
targetId: string;
|
|
@@ -11,8 +11,10 @@ export type OutgoingContent = Exclude<RuntimeContent, {
|
|
|
11
11
|
groupCreate: unknown;
|
|
12
12
|
} | {
|
|
13
13
|
groupUpdate: unknown;
|
|
14
|
+
} | {
|
|
15
|
+
groupDissolve: unknown;
|
|
14
16
|
}>;
|
|
15
|
-
import type { ChatThreadSnapshot, ChatSnapshot, ReadOptions } from "../chatTypes.js";
|
|
17
|
+
import type { ChatGroup, ChatThreadSnapshot, ChatSnapshot, ReadOptions } from "../chatTypes.js";
|
|
16
18
|
export type { ChatGroup, ConversationInfo, ChatThreadSnapshot, ChatSnapshot, ReadOptions } from "../chatTypes.js";
|
|
17
19
|
export type MessageQuery = {
|
|
18
20
|
earlier?: boolean;
|
|
@@ -94,15 +96,7 @@ export declare class ChatEngine {
|
|
|
94
96
|
getVoiceAttachment(threadId: string, messageId: string): Promise<import("../runtime/durableSender.js").VoiceAttachmentLease>;
|
|
95
97
|
getGroup(threadId: string, options?: {
|
|
96
98
|
refresh?: boolean;
|
|
97
|
-
}): Promise<
|
|
98
|
-
groupId: string;
|
|
99
|
-
teamId: string;
|
|
100
|
-
ownerId: string;
|
|
101
|
-
title: string;
|
|
102
|
-
avatar?: string;
|
|
103
|
-
memberIds: readonly string[];
|
|
104
|
-
revision: string;
|
|
105
|
-
}>>;
|
|
99
|
+
}): Promise<ChatGroup>;
|
|
106
100
|
createGroup(input: {
|
|
107
101
|
groupId?: string;
|
|
108
102
|
title: string;
|
|
@@ -112,20 +106,25 @@ export declare class ChatEngine {
|
|
|
112
106
|
groupId: string;
|
|
113
107
|
teamId: string;
|
|
114
108
|
ownerId: string;
|
|
109
|
+
revision: string;
|
|
110
|
+
status: "active";
|
|
115
111
|
title: string;
|
|
116
112
|
avatar?: string;
|
|
117
113
|
memberIds: readonly string[];
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
updateGroup(threadId: string, changes: GroupChanges): Promise<Readonly<{
|
|
114
|
+
} | {
|
|
115
|
+
threadId: string;
|
|
121
116
|
groupId: string;
|
|
122
117
|
teamId: string;
|
|
123
118
|
ownerId: string;
|
|
124
|
-
title: string;
|
|
125
|
-
avatar?: string;
|
|
126
|
-
memberIds: readonly string[];
|
|
127
119
|
revision: string;
|
|
128
|
-
|
|
120
|
+
status: "dissolved";
|
|
121
|
+
dissolvedBy?: string;
|
|
122
|
+
dissolvedAt?: number;
|
|
123
|
+
}>;
|
|
124
|
+
updateGroup(threadId: string, changes: GroupChanges): Promise<ChatGroup>;
|
|
125
|
+
dissolveGroup(threadId: string, options?: {
|
|
126
|
+
expectedRevision?: string;
|
|
127
|
+
}): Promise<ChatGroup>;
|
|
129
128
|
revokeAccess(): Promise<void>;
|
|
130
129
|
close(): Promise<void>;
|
|
131
130
|
}
|
|
@@ -201,8 +201,8 @@ export class ChatEngine {
|
|
|
201
201
|
}
|
|
202
202
|
sendMessage(threadId, content, options = {}) {
|
|
203
203
|
return this.threadOperation(threadId, async () => {
|
|
204
|
-
if (content && ("groupCreate" in content || "groupUpdate" in content))
|
|
205
|
-
throw new ChatError("invalid-input", "Use
|
|
204
|
+
if (content && ("groupCreate" in content || "groupUpdate" in content || "groupDissolve" in content))
|
|
205
|
+
throw new ChatError("invalid-input", "Use group lifecycle methods for group changes");
|
|
206
206
|
const result = await this.advanced.sendMessage(threadId, content, options);
|
|
207
207
|
return { id: result.hash, timestamp: result.t };
|
|
208
208
|
});
|
|
@@ -275,6 +275,7 @@ export class ChatEngine {
|
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
277
|
updateGroup(threadId, changes) { return this.threadOperation(threadId, async () => this.group(await this.advanced.updateGroup(threadId, changes))); }
|
|
278
|
+
dissolveGroup(threadId, options = {}) { return this.threadOperation(threadId, async () => this.group(await this.advanced.dissolveGroup(threadId, options))); }
|
|
278
279
|
revokeAccess() { return this.operation(() => this.advanced.revokeAccess()); }
|
|
279
280
|
close() { this.closed = true; return this.operation(() => this.advanced.close()).finally(() => { this.errors.clear(); this.targets.clear(); this.listeners.clear(); this.threadSubscribers.clear(); this.openQueue.clear(); this.views.clear(); this.summary = undefined; this.present = createMessagePresenter(); this.messageLists = new WeakMap(); this.groups = new WeakMap(); this.redactedQuotes = new WeakMap(); }); }
|
|
280
281
|
}
|
|
@@ -45,7 +45,7 @@ export function createPublicChat(options) {
|
|
|
45
45
|
},
|
|
46
46
|
getVoiceAttachment: (id, messageId, options = {}) => read(() => engine.getVoiceAttachment(id, messageId), options, lease => lease.release()),
|
|
47
47
|
getGroup: (id, options = {}) => read(() => engine.getGroup(id), options), refreshGroup: (id, options = {}) => read(() => engine.getGroup(id, { refresh: true }), options),
|
|
48
|
-
createGroup: input => engine.createGroup(input), updateGroup: (id, changes) => engine.updateGroup(id, changes),
|
|
48
|
+
createGroup: input => engine.createGroup(input), updateGroup: (id, changes) => engine.updateGroup(id, changes), dissolveGroup: (id, options) => engine.dissolveGroup(id, options),
|
|
49
49
|
});
|
|
50
50
|
registerChat(chat, engine);
|
|
51
51
|
return chat;
|
package/lib/messageView.js
CHANGED
|
@@ -51,7 +51,7 @@ function content(message) {
|
|
|
51
51
|
}
|
|
52
52
|
else if (body.kind === "group") {
|
|
53
53
|
result.kind = "system";
|
|
54
|
-
result.system = { type: body.action === "groupCreate" ? "group-created" : "group-updated", title: text(object(body.payload).title) || undefined };
|
|
54
|
+
result.system = { type: body.action === "groupCreate" ? "group-created" : body.action === "groupDissolve" ? "group-dissolved" : "group-updated", title: text(object(body.payload).title) || undefined };
|
|
55
55
|
}
|
|
56
56
|
else if (file) {
|
|
57
57
|
result.kind = "attachment";
|
|
@@ -123,6 +123,11 @@ export declare class ChatClient {
|
|
|
123
123
|
title?: string;
|
|
124
124
|
avatar?: string;
|
|
125
125
|
}): Promise<ChatRuntimeMessage>;
|
|
126
|
+
dissolveGroup(input: {
|
|
127
|
+
groupId: string;
|
|
128
|
+
teamId?: string;
|
|
129
|
+
expectedRevision: string;
|
|
130
|
+
}): Promise<ChatRuntimeMessage>;
|
|
126
131
|
sendGroup(input: {
|
|
127
132
|
groupId: string;
|
|
128
133
|
teamId?: string;
|
|
@@ -252,6 +252,12 @@ export class ChatClient {
|
|
|
252
252
|
addMembers: input.addMembers ?? [], removeMembers: input.removeMembers ?? [], ...(input.title !== undefined ? { title: input.title } : {}), ...(input.avatar !== undefined ? { avatar: input.avatar } : {}) },
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
|
+
async dissolveGroup(input) {
|
|
256
|
+
return this.sendChat(input.groupId, {
|
|
257
|
+
kind: "group", threadKind: "group", action: "groupDissolve",
|
|
258
|
+
payload: { appId: this.options.appId, groupId: input.groupId, ...(input.teamId !== undefined ? { teamId: input.teamId } : {}), expectedRevision: input.expectedRevision },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
255
261
|
async sendGroup(input) {
|
|
256
262
|
return this.sendChat(input.groupId, {
|
|
257
263
|
kind: "message",
|
|
@@ -149,6 +149,9 @@ export declare class ChatSession<T extends StoredMessage> {
|
|
|
149
149
|
title?: string;
|
|
150
150
|
avatar?: string;
|
|
151
151
|
}): Promise<ChatGroup>;
|
|
152
|
+
dissolveGroup(target: ChatConversation | string, options?: {
|
|
153
|
+
expectedRevision?: string;
|
|
154
|
+
}): Promise<ChatGroup>;
|
|
152
155
|
sendMessage(threadId: string, input: OutgoingContent, options?: {
|
|
153
156
|
waitFor?: "accepted" | "delivered";
|
|
154
157
|
}): Promise<ChatRuntimeMessage>;
|
|
@@ -403,6 +403,16 @@ export class ChatSession {
|
|
|
403
403
|
await this.sendMessage(thread, { groupUpdate: { ...changes, expectedRevision: changes.expectedRevision ?? previous.revision } }, { waitFor: "delivered" });
|
|
404
404
|
return this.groups.after(thread, previous.versionNumber + 1);
|
|
405
405
|
}
|
|
406
|
+
async dissolveGroup(target, options = {}) {
|
|
407
|
+
const thread = typeof target === "string" ? await this.resolveConversation(target) : target;
|
|
408
|
+
const previous = await this.getGroup(thread);
|
|
409
|
+
if (previous.status === "dissolved")
|
|
410
|
+
return previous;
|
|
411
|
+
if (previous.versionNumber >= Number.MAX_SAFE_INTEGER)
|
|
412
|
+
throw new Error("INVALID_GROUP_VERSION");
|
|
413
|
+
await this.sendMessage(thread, { groupDissolve: { expectedRevision: options.expectedRevision ?? previous.revision } }, { waitFor: "delivered" });
|
|
414
|
+
return this.groups.after(thread, previous.versionNumber + 1);
|
|
415
|
+
}
|
|
406
416
|
sendMessage(thread, input, options = {}) {
|
|
407
417
|
this.assertOpen();
|
|
408
418
|
if (options.waitFor !== undefined && !["accepted", "delivered"].includes(options.waitFor))
|
|
@@ -434,8 +444,10 @@ export class ChatSession {
|
|
|
434
444
|
await this.conversations.put(thread);
|
|
435
445
|
this.assertOpen();
|
|
436
446
|
// Recipients are SDK-owned metadata, never an App-supplied roster.
|
|
437
|
-
if (thread.kind === "group" && !input.groupCreate && !input.groupUpdate) {
|
|
447
|
+
if (thread.kind === "group" && !input.groupCreate && !input.groupUpdate && !input.groupDissolve) {
|
|
438
448
|
const group = await this.getGroup(thread);
|
|
449
|
+
if (group.status === "dissolved")
|
|
450
|
+
throw new Error("GROUP_DISSOLVED");
|
|
439
451
|
this.assertOpen();
|
|
440
452
|
thread = { ...thread, memberIds: group.memberIds };
|
|
441
453
|
}
|
|
@@ -876,7 +876,7 @@ export class DurableChatSender {
|
|
|
876
876
|
}
|
|
877
877
|
}
|
|
878
878
|
}
|
|
879
|
-
function statefulGroup(message) { const body = message.body; return body?.kind === "group" && (body.action === "groupCreate" || body.action === "groupUpdate"); }
|
|
879
|
+
function statefulGroup(message) { const body = message.body; return body?.kind === "group" && (body.action === "groupCreate" || body.action === "groupUpdate" || body.action === "groupDissolve"); }
|
|
880
880
|
function commandId(scope, version, threadId, message) {
|
|
881
881
|
return bytesToHex(blake3(new TextEncoder().encode(JSON.stringify(["chat-command:v1", scope, version, threadId, message.to, ordered(message.body)]))));
|
|
882
882
|
}
|
|
@@ -2,7 +2,7 @@ import { type ResponseCacheAccess } from "./responseCache.js";
|
|
|
2
2
|
import { type MessageScope } from "./messageStore.js";
|
|
3
3
|
import { type ChatConversation } from "./outgoingContent.js";
|
|
4
4
|
import type { SocialGroup } from "./socialReadClient.js";
|
|
5
|
-
export type
|
|
5
|
+
export type ActiveChatGroup = {
|
|
6
6
|
groupId: string;
|
|
7
7
|
teamId: string;
|
|
8
8
|
ownerId: string;
|
|
@@ -11,7 +11,19 @@ export type ChatGroup = {
|
|
|
11
11
|
memberIds: readonly string[];
|
|
12
12
|
revision: string;
|
|
13
13
|
versionNumber: number;
|
|
14
|
+
status: "active";
|
|
14
15
|
};
|
|
16
|
+
export type DissolvedChatGroup = {
|
|
17
|
+
groupId: string;
|
|
18
|
+
teamId: string;
|
|
19
|
+
ownerId: string;
|
|
20
|
+
revision: string;
|
|
21
|
+
versionNumber: number;
|
|
22
|
+
status: "dissolved";
|
|
23
|
+
dissolvedBy?: string;
|
|
24
|
+
dissolvedAt?: number;
|
|
25
|
+
};
|
|
26
|
+
export type ChatGroup = ActiveChatGroup | DissolvedChatGroup;
|
|
15
27
|
export type GroupSnapshot = {
|
|
16
28
|
data?: ChatGroup;
|
|
17
29
|
loading: boolean;
|
|
@@ -106,12 +106,19 @@ export class GroupClient {
|
|
|
106
106
|
}
|
|
107
107
|
normalize(value, entry) {
|
|
108
108
|
const scope = this.options.scope;
|
|
109
|
-
if (!value || value.appId !== scope.appId || value.groupId !== entry.thread.targetId || value.teamId !== scope.teamId || !validMessageIdentifier(value.ownerId) || !validMessageIdentifier(value.revision) || !Number.isSafeInteger(value.versionNumber) || value.versionNumber < 1
|
|
109
|
+
if (!value || value.appId !== scope.appId || value.groupId !== entry.thread.targetId || value.teamId !== scope.teamId || !validMessageIdentifier(value.ownerId) || !validMessageIdentifier(value.revision) || !Number.isSafeInteger(value.versionNumber) || value.versionNumber < 1)
|
|
110
110
|
throw new Error("INVALID_GROUP_METADATA");
|
|
111
|
-
|
|
111
|
+
if (value.status === "dissolved") {
|
|
112
|
+
if (value.dissolvedBy !== undefined && !validMessageIdentifier(value.dissolvedBy) || value.dissolvedAt !== undefined && (!Number.isSafeInteger(value.dissolvedAt) || value.dissolvedAt < 0))
|
|
113
|
+
throw new Error("INVALID_GROUP_METADATA");
|
|
114
|
+
return Object.freeze({ groupId: value.groupId, teamId: scope.teamId, ownerId: value.ownerId, revision: value.revision, versionNumber: value.versionNumber, status: "dissolved", ...(value.dissolvedBy ? { dissolvedBy: value.dissolvedBy } : {}), ...(value.dissolvedAt === undefined ? {} : { dissolvedAt: value.dissolvedAt }) });
|
|
115
|
+
}
|
|
116
|
+
if (value.status !== undefined && value.status !== "active" || !Array.isArray(value.members) || !value.members.length || value.members.length > 256 || !value.members.every(validMessageIdentifier) || !value.members.includes(value.ownerId) || !value.members.includes(scope.profileId) || typeof value.title !== "string" || value.avatar !== undefined && value.avatar !== null && typeof value.avatar !== "string")
|
|
117
|
+
throw new Error("INVALID_GROUP_METADATA");
|
|
118
|
+
return Object.freeze({ groupId: value.groupId, teamId: scope.teamId, ownerId: value.ownerId, title: value.title, ...(value.avatar ? { avatar: value.avatar } : {}), memberIds: Object.freeze([...new Set(value.members)].sort()), revision: value.revision, versionNumber: value.versionNumber, status: "active" });
|
|
112
119
|
}
|
|
113
120
|
cached(value, entry) {
|
|
114
|
-
return this.normalize({ appId: this.options.scope.appId,
|
|
121
|
+
return this.normalize(value.status === "dissolved" ? { appId: this.options.scope.appId, ...value } : { appId: this.options.scope.appId, ...value, members: value.memberIds }, entry);
|
|
115
122
|
}
|
|
116
123
|
local(entry) {
|
|
117
124
|
if (entry.loaded)
|
|
@@ -229,7 +229,8 @@ export class IndexedDbMessageStore {
|
|
|
229
229
|
});
|
|
230
230
|
}
|
|
231
231
|
async scopeAccess() {
|
|
232
|
-
const
|
|
232
|
+
const read = () => this.accessRows.get(this.key);
|
|
233
|
+
const access = (await (Dexie.currentTransaction?.db === this.db ? read() : this.transact("r", this.accessRows, read))) ?? { scope: this.key, version: 0, revoked: false };
|
|
233
234
|
if (!Number.isSafeInteger(access.version) || access.version < 0 || typeof access.revoked !== "boolean")
|
|
234
235
|
throw new Error("INVALID_MESSAGE_SCOPE_ACCESS");
|
|
235
236
|
return access;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseChatFile } from "../fileMetadata.js";
|
|
2
2
|
import { dmThreadId, groupThreadId } from "./thread.js";
|
|
3
|
-
const contentKeys = ["text", "file", "image", "voice", "recall", "reaction", "invitation", "groupCreate", "groupUpdate"];
|
|
3
|
+
const contentKeys = ["text", "file", "image", "voice", "recall", "reaction", "invitation", "groupCreate", "groupUpdate", "groupDissolve"];
|
|
4
4
|
export function validMessageIdentifier(value) { return typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).byteLength <= 256 && !/[\u0000-\u001f]/u.test(value); }
|
|
5
5
|
function members(value) {
|
|
6
6
|
if (!Array.isArray(value) || value.length > 256 || !value.every(validMessageIdentifier))
|
|
@@ -63,6 +63,11 @@ export function outgoingContent(scope, thread, input) {
|
|
|
63
63
|
throw new Error("INVALID_GROUP_AVATAR");
|
|
64
64
|
return { to: thread.targetId, body: { kind: "group", threadKind: "group", action: "groupUpdate", payload: { ...identity, groupId: thread.targetId, expectedRevision: update.expectedRevision, addMembers: add, removeMembers: remove, ...(update.title === undefined ? {} : { title: update.title.trim() }), ...(update.avatar === undefined ? {} : { avatar: update.avatar }) } } };
|
|
65
65
|
}
|
|
66
|
+
if (input.groupDissolve) {
|
|
67
|
+
if (thread.kind !== "group" || !validMessageIdentifier(input.groupDissolve.expectedRevision))
|
|
68
|
+
throw new Error("INVALID_GROUP_DISSOLVE");
|
|
69
|
+
return { to: thread.targetId, body: { kind: "group", threadKind: "group", action: "groupDissolve", payload: { ...identity, groupId: thread.targetId, expectedRevision: input.groupDissolve.expectedRevision } } };
|
|
70
|
+
}
|
|
66
71
|
if (thread.kind === "group" && !Array.isArray(thread.memberIds))
|
|
67
72
|
throw new Error("MESSAGE_GROUP_MEMBERS_UNAVAILABLE");
|
|
68
73
|
const recipients = thread.kind === "group" ? [...new Set(thread.memberIds)] : undefined;
|
|
@@ -48,7 +48,7 @@ export class IndexedDbResponseCache {
|
|
|
48
48
|
if (!this.options.access)
|
|
49
49
|
return;
|
|
50
50
|
const access = await this.options.access();
|
|
51
|
-
const stored = await this.epochs.get(this.scope);
|
|
51
|
+
const stored = await this.transact("r", this.epochs, () => this.epochs.get(this.scope));
|
|
52
52
|
const storedVersion = stored?.accessVersion ?? 0;
|
|
53
53
|
if (access.version < storedVersion)
|
|
54
54
|
throw new Error("RESPONSE_CACHE_SCOPE_CHANGED");
|
|
@@ -18,11 +18,14 @@ export type SocialGroup = {
|
|
|
18
18
|
groupId: string;
|
|
19
19
|
teamId?: string | null;
|
|
20
20
|
ownerId: string;
|
|
21
|
-
members
|
|
22
|
-
title
|
|
21
|
+
members?: readonly string[];
|
|
22
|
+
title?: string;
|
|
23
23
|
avatar?: string | null;
|
|
24
24
|
revision: string;
|
|
25
25
|
versionNumber?: number;
|
|
26
|
+
status?: "active" | "dissolved";
|
|
27
|
+
dissolvedBy?: string;
|
|
28
|
+
dissolvedAt?: number;
|
|
26
29
|
};
|
|
27
30
|
export type SocialRelationship = {
|
|
28
31
|
appId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pmate/chat-sdk",
|
|
3
|
-
"version": "0.12.0-next.
|
|
3
|
+
"version": "0.12.0-next.74",
|
|
4
4
|
"description": "Local-first chat SDK, message subscriptions, reading state, and shared chat UI primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -53,6 +53,15 @@
|
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"clean": "rimraf lib",
|
|
58
|
+
"build": "pnpm run clean && tsc -p tsconfig.build.json && cp src/voice/recorder-processor.js lib/voice/recorder-processor.js",
|
|
59
|
+
"prepack": "pnpm run build",
|
|
60
|
+
"npm:publish": "pnpm run build && npm publish --access public --registry https://registry.npmjs.org/",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"storybook": "storybook dev -p 6009",
|
|
63
|
+
"build-storybook": "storybook build --output-dir dist"
|
|
64
|
+
},
|
|
56
65
|
"dependencies": {
|
|
57
66
|
"@emoji-mart/data": "^1.2.1",
|
|
58
67
|
"@emoji-mart/react": "^1.1.1",
|
|
@@ -68,24 +77,16 @@
|
|
|
68
77
|
"devDependencies": {
|
|
69
78
|
"@storybook/addon-docs": "^9.0.17",
|
|
70
79
|
"@storybook/react-vite": "9.0.17",
|
|
71
|
-
"@tailwindcss/vite": "
|
|
72
|
-
"@types/react": "
|
|
73
|
-
"@types/react-dom": "
|
|
80
|
+
"@tailwindcss/vite": "catalog:",
|
|
81
|
+
"@types/react": "catalog:",
|
|
82
|
+
"@types/react-dom": "catalog:",
|
|
74
83
|
"fake-indexeddb": "^6.2.5",
|
|
75
|
-
"react": "
|
|
76
|
-
"react-dom": "
|
|
84
|
+
"react": "catalog:",
|
|
85
|
+
"react-dom": "catalog:",
|
|
77
86
|
"rimraf": "^6.1.2",
|
|
78
87
|
"storybook": "^9.0.17",
|
|
79
|
-
"tailwindcss": "
|
|
88
|
+
"tailwindcss": "catalog:",
|
|
80
89
|
"typescript": "5.9.2",
|
|
81
90
|
"vitest": "^4.0.17"
|
|
82
|
-
},
|
|
83
|
-
"scripts": {
|
|
84
|
-
"clean": "rimraf lib",
|
|
85
|
-
"build": "pnpm run clean && tsc -p tsconfig.build.json && cp src/voice/recorder-processor.js lib/voice/recorder-processor.js",
|
|
86
|
-
"npm:publish": "pnpm run build && npm publish --access public --registry https://registry.npmjs.org/",
|
|
87
|
-
"test": "vitest run",
|
|
88
|
-
"storybook": "storybook dev -p 6009",
|
|
89
|
-
"build-storybook": "storybook build --output-dir dist"
|
|
90
91
|
}
|
|
91
|
-
}
|
|
92
|
+
}
|