@happyvertical/smrt-comments 0.0.0-stage → 0.55.10
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/AGENTS.md +17 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +58 -2
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/collections/CommentCollection.d.ts +7 -0
- package/dist/collections/CommentCollection.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +184 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +474 -0
- package/dist/models/Comment.d.ts +13 -0
- package/dist/models/Comment.d.ts.map +1 -0
- package/dist/recipes.d.ts +27 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/services/CommentService.d.ts +16 -0
- package/dist/services/CommentService.d.ts.map +1 -0
- package/dist/services/mentionNotifications.d.ts +18 -0
- package/dist/services/mentionNotifications.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +269 -0
- package/dist/svelte/RecordComments.svelte +71 -0
- package/dist/svelte/RecordComments.svelte.d.ts +16 -0
- package/dist/svelte/RecordComments.svelte.d.ts.map +1 -0
- package/dist/svelte/RecordCommentsPlayground.svelte +20 -0
- package/dist/svelte/RecordCommentsPlayground.svelte.d.ts +4 -0
- package/dist/svelte/RecordCommentsPlayground.svelte.d.ts.map +1 -0
- package/dist/svelte/demo.d.ts +4 -0
- package/dist/svelte/demo.d.ts.map +1 -0
- package/dist/svelte/demo.js +13 -0
- package/dist/svelte/index.d.ts +6 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +4 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/package.json +62 -3
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"sensitiveFieldsExcluded": true,
|
|
4
|
+
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
|
+
"packageName": "@happyvertical/smrt-comments",
|
|
6
|
+
"packageVersion": "0.55.10",
|
|
7
|
+
"sourceManifestPath": "dist/manifest.json",
|
|
8
|
+
"agentDocPath": "AGENTS.md",
|
|
9
|
+
"sourceHashes": {
|
|
10
|
+
"manifest": "1518972bb1a556c8edc32a947d1f20a1c53cd98cca73bec7a0763208f457b25b",
|
|
11
|
+
"packageJson": "5c32ef54ad66abe3246ca039016de7d2120eae960b0fa14b45ae69354a981c70",
|
|
12
|
+
"agents": "06a1eb0f4777eea60f0ea72d08f5af82e5045f686b5197ddeaa2079e446852cd",
|
|
13
|
+
"moduleDoc:agents/test-design.md": "fd111b1db0a648accd4b144cea42711239cf9bbb5a0f3186302c624a80d10107"
|
|
14
|
+
},
|
|
15
|
+
"exports": [
|
|
16
|
+
".",
|
|
17
|
+
"./manifest",
|
|
18
|
+
"./manifest.json",
|
|
19
|
+
"./svelte"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@happyvertical/smrt-core": "workspace:*",
|
|
23
|
+
"@happyvertical/smrt-tenancy": "workspace:*",
|
|
24
|
+
"@happyvertical/smrt-vitest": "workspace:*",
|
|
25
|
+
"@sveltejs/package": "^2.5.8",
|
|
26
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
27
|
+
"@testing-library/svelte": "^5.4.2",
|
|
28
|
+
"@types/node": "24.13.6",
|
|
29
|
+
"svelte": "^5.57.0",
|
|
30
|
+
"svelte-check": "^4.7.6",
|
|
31
|
+
"typescript": "6.0.3",
|
|
32
|
+
"vite": "8.1.4",
|
|
33
|
+
"vitest": "4.1.10",
|
|
34
|
+
"@happyvertical/smrt-messages": "workspace:*"
|
|
35
|
+
},
|
|
36
|
+
"smrtDependencies": [
|
|
37
|
+
"@happyvertical/smrt-core",
|
|
38
|
+
"@happyvertical/smrt-messages",
|
|
39
|
+
"@happyvertical/smrt-tenancy",
|
|
40
|
+
"@happyvertical/smrt-vitest"
|
|
41
|
+
],
|
|
42
|
+
"sdkDependencies": [],
|
|
43
|
+
"tags": [
|
|
44
|
+
"cross-package"
|
|
45
|
+
],
|
|
46
|
+
"risks": [
|
|
47
|
+
"cross-package-refs:1",
|
|
48
|
+
"polymorphic-associations:1",
|
|
49
|
+
"sensitive-fields-excluded"
|
|
50
|
+
],
|
|
51
|
+
"objects": [
|
|
52
|
+
{
|
|
53
|
+
"name": "CommentCollection",
|
|
54
|
+
"qualifiedName": "@happyvertical/smrt-comments:CommentCollection",
|
|
55
|
+
"collection": "comments",
|
|
56
|
+
"tableName": "record_comments",
|
|
57
|
+
"packageName": "@happyvertical/smrt-comments",
|
|
58
|
+
"extends": "SmrtCollection",
|
|
59
|
+
"fields": [],
|
|
60
|
+
"relationships": [],
|
|
61
|
+
"methods": [
|
|
62
|
+
"listForRecord"
|
|
63
|
+
],
|
|
64
|
+
"methodSignatures": [
|
|
65
|
+
{
|
|
66
|
+
"name": "listForRecord",
|
|
67
|
+
"async": true,
|
|
68
|
+
"params": [
|
|
69
|
+
"recordType: string",
|
|
70
|
+
"recordId: string"
|
|
71
|
+
],
|
|
72
|
+
"returns": "Promise<Comment[]>"
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"surfaces": [],
|
|
76
|
+
"withheldSurfaces": [
|
|
77
|
+
{
|
|
78
|
+
"kind": "api",
|
|
79
|
+
"operation": "listForRecord",
|
|
80
|
+
"code": "api-disabled",
|
|
81
|
+
"reason": "api is disabled",
|
|
82
|
+
"objectName": "@happyvertical/smrt-comments:CommentCollection"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"relationshipFeatures": [
|
|
86
|
+
"uuidColumns"
|
|
87
|
+
],
|
|
88
|
+
"tags": [],
|
|
89
|
+
"risks": []
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "Comment",
|
|
93
|
+
"qualifiedName": "@happyvertical/smrt-comments:Comment",
|
|
94
|
+
"collection": "comments",
|
|
95
|
+
"tableName": "record_comments",
|
|
96
|
+
"packageName": "@happyvertical/smrt-comments",
|
|
97
|
+
"extends": "SmrtPolymorphicAssociation",
|
|
98
|
+
"fields": [
|
|
99
|
+
{
|
|
100
|
+
"name": "metaType",
|
|
101
|
+
"type": "text",
|
|
102
|
+
"required": true,
|
|
103
|
+
"columnType": "TEXT"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "metaId",
|
|
107
|
+
"type": "text",
|
|
108
|
+
"required": true,
|
|
109
|
+
"columnType": "TEXT"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "role",
|
|
113
|
+
"type": "text",
|
|
114
|
+
"required": true,
|
|
115
|
+
"columnType": "TEXT"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"name": "sortOrder",
|
|
119
|
+
"type": "integer",
|
|
120
|
+
"required": false,
|
|
121
|
+
"columnType": "INTEGER",
|
|
122
|
+
"default": 0
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "tenantId",
|
|
126
|
+
"type": "text",
|
|
127
|
+
"required": true,
|
|
128
|
+
"columnType": "UUID"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "authorUserId",
|
|
132
|
+
"type": "crossPackageRef",
|
|
133
|
+
"required": true,
|
|
134
|
+
"related": "@happyvertical/smrt-users:User",
|
|
135
|
+
"columnType": "UUID"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "body",
|
|
139
|
+
"type": "text",
|
|
140
|
+
"required": true,
|
|
141
|
+
"columnType": "TEXT"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "mentions",
|
|
145
|
+
"type": "text",
|
|
146
|
+
"required": false,
|
|
147
|
+
"columnType": "TEXT"
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
"relationships": [
|
|
151
|
+
{
|
|
152
|
+
"name": "authorUserId",
|
|
153
|
+
"type": "crossPackageRef",
|
|
154
|
+
"required": true,
|
|
155
|
+
"related": "@happyvertical/smrt-users:User",
|
|
156
|
+
"columnType": "UUID"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"methods": [
|
|
160
|
+
"hydrate"
|
|
161
|
+
],
|
|
162
|
+
"methodSignatures": [
|
|
163
|
+
{
|
|
164
|
+
"name": "hydrate",
|
|
165
|
+
"async": true,
|
|
166
|
+
"returns": "Promise<T | null>"
|
|
167
|
+
}
|
|
168
|
+
],
|
|
169
|
+
"tenant": {
|
|
170
|
+
"scoped": true,
|
|
171
|
+
"mode": "required",
|
|
172
|
+
"field": "tenantId"
|
|
173
|
+
},
|
|
174
|
+
"conflictColumns": [
|
|
175
|
+
"tenant_id",
|
|
176
|
+
"slug",
|
|
177
|
+
"context"
|
|
178
|
+
],
|
|
179
|
+
"surfaces": [],
|
|
180
|
+
"withheldSurfaces": [
|
|
181
|
+
{
|
|
182
|
+
"kind": "api",
|
|
183
|
+
"operation": "hydrate",
|
|
184
|
+
"code": "api-disabled",
|
|
185
|
+
"reason": "api is disabled",
|
|
186
|
+
"objectName": "@happyvertical/smrt-comments:Comment"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"relationshipFeatures": [
|
|
190
|
+
"SmrtPolymorphicAssociation",
|
|
191
|
+
"crossPackageRef",
|
|
192
|
+
"uuidColumns"
|
|
193
|
+
],
|
|
194
|
+
"tags": [],
|
|
195
|
+
"risks": []
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"surfaces": [],
|
|
199
|
+
"prompts": [],
|
|
200
|
+
"relationshipsV2": {
|
|
201
|
+
"foreignKeyFields": 0,
|
|
202
|
+
"crossPackageRefFields": 1,
|
|
203
|
+
"junctionCollections": 0,
|
|
204
|
+
"hierarchicalObjects": 0,
|
|
205
|
+
"polymorphicAssociations": 1,
|
|
206
|
+
"uuidColumns": 6
|
|
207
|
+
},
|
|
208
|
+
"agentDoc": "# @happyvertical/smrt-comments\n\nRecord discussions attach to arbitrary records through `Comment`'s inherited\n`metaType` and `metaId`; preserve these as a qualified polymorphic pair and\nnever replace them with a text foreign key. `CommentService` owns persistence\nand invokes the optional mention adapter only after the comment is saved.\n\nThe package must not depend on `smrt-messages`: hosts compose\n`CommentMentionNotificationAdapter` with `UserNotificationService` and retain\ntheir own notification delivery policy. The Svelte surface receives authorized\ncomment projections and callbacks; it does not fetch or authorize records.\n`CommentService` requires a trusted actor and host record authorization callback.\n`RecordComments.contextKey` includes tenant, actor and record identity.\nSee [test design](agents/test-design.md) for the behavior matrix.\n\nRun `pnpm --filter @happyvertical/smrt-comments test`, `test:postgres`, `typecheck`, `check`, and\n`npx --yes @biomejs/biome@2.5.2 check packages/comments` after changes.\n",
|
|
209
|
+
"moduleDocs": [
|
|
210
|
+
{
|
|
211
|
+
"path": "agents/test-design.md",
|
|
212
|
+
"module": "test-design",
|
|
213
|
+
"content": "# Comments behavior evidence (#3714)\n\n| Behavior / trigger | Positive / failure | Actor / executor | Runtime / edge | Level / command |\n| --- | --- | --- | --- | --- |\n| Create/read a comment | Persist and reload; deny missing record permission, forged author or tenant | Trusted session actor; same supplied DB handle under tenant context | Node, SQLite/DuckDB/PostgreSQL; polymorphic record authorization callback | Integration, `test` / `test:postgres` |\n| Shared record identity in different tenants | Tenant A sees A; never B | Two tenant contexts, same actor and DB | All three SQL dialects; explicit tenant filter | Integration, `test` / `test:postgres` |\n| Mention creation | Deduplicate and exclude author; malformed UUID rejected | Authorized author, recipient access callback | All three SQL dialects; missing adapter is supported | Integration, `test` / `test:postgres` |\n| Mention delivery | Real UserNotificationService row; denied recipient gets none; replay deduplicates | Supplied notification service/DB | All three SQL dialects; upstream failure leaves saved comment | Integration, `test` / `test:postgres` |\n| UI submission | Trim/post; empty body and rejected callback keep actionable feedback | Host authorized projections | Browser Svelte; async callback | Component, `test` |\n| Actor/record switch during submission | Reset draft; stale success/error cannot mutate new draft | Changed composite contextKey | Browser Svelte; async completion | Component, `test` |\n| Recipe/schema | Recipe includes Comment; generated schema used by real persistence | Registry/test migrator | All three SQL dialects | Integration, `test` / `test:postgres`; `build` |\n\nNew feature, so a base-regression comparison is N/A. Comment insertion is one\nsave on the provided executor, with validation/authorization before mutation.\nNotification delivery intentionally occurs after save and is not atomic with it;\nthe failure test asserts the saved-row contract. No comment retry/idempotency\ncontract is promised: clients must not blindly retry create after delivery error.\nThe fixture-only playground does not replace the authenticated record surface.\n\nRecipe metadata follow-up (#3604): the comments catalog group, embedded-only\nnavigation and help are checked in the generated manifest and knowledge artifact\nafter building with refreshed scanner/core artifacts. Model exposure stays off.\nThis change does not affect persistence or delivery; prior three-dialect evidence\nremains applicable. Full package tests, typecheck, Svelte and Biome are rerun.\n\n#3708 follow-up: the browser-only playground renders fixture projections and\naccepts local posts without storage or notification access. Component tests\nverify display, posting, instance isolation and reset on remount. Build assertions\nverify runtime, playground and demo exports in manifest and knowledge artifacts.\nPersistence and authorization are unchanged; existing three-dialect evidence\napplies. Route/settings/shell/provider contracts are N/A because they cannot\nprovide the parent record authorization context.\n\n## Accepted review6084422109 round 1 regressions\n\n- Invalid UUID and 51 distinct mentions: authorized actor, each SQL dialect,\n failed create must leave zero rows for the record. Baseline failed on SQLite,\n DuckDB and PostgreSQL; public model setter now validates before the one insert.\n- Actual SQLite CommentService notification rejection composed with the Svelte\n submit callback: saved row remains, draft remains, alert instructs refresh and\n checking the discussion before reposting. Baseline produced “Try again”.\n- Commands: full comments `test`, `test:postgres`, `typecheck`, `check`, `build`,\n and Biome; evidence under `/private/tmp/smrt-track-b-evidence/3714-r1-*`.\n"
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
"recipes": [
|
|
217
|
+
{
|
|
218
|
+
"id": "comments.records",
|
|
219
|
+
"className": "RecordCommentsRecipe",
|
|
220
|
+
"label": "Record comments",
|
|
221
|
+
"summary": "Discuss work directly on the records it concerns.",
|
|
222
|
+
"synonyms": [
|
|
223
|
+
"comments",
|
|
224
|
+
"mentions",
|
|
225
|
+
"discussion"
|
|
226
|
+
],
|
|
227
|
+
"models": [
|
|
228
|
+
"@happyvertical/smrt-comments:Comment"
|
|
229
|
+
],
|
|
230
|
+
"nav": [],
|
|
231
|
+
"requires": [],
|
|
232
|
+
"group": {
|
|
233
|
+
"id": "comments",
|
|
234
|
+
"label": "Comments",
|
|
235
|
+
"summary": "Keep discussions alongside the records your team works on."
|
|
236
|
+
},
|
|
237
|
+
"help": {
|
|
238
|
+
"markdown": "## Overview\n\nRecord comments keep a discussion next to the work it concerns. Open a record\nyou can access to read its discussion or add a comment. Comments are part of\nthe record page, rather than a separate list of every discussion.\n\n## Tasks\n\n### Add a comment\n\nOpen the record, find Comments, write your message and choose Post comment.\nYour app controls who can read the record and who can contribute to its discussion.\n\n### Mention someone\n\nIf your app provides mention selection, choose a teammate who can access the\nrecord. When mention notifications are connected, that person receives a\nnotification. Typing a name alone does not select a recipient.\n\n### Check a failed post\n\nIf posting reports an error, refresh the discussion before trying again. A\ncomment may have been saved even when its mention notification could not be\ndelivered. If it appears in the discussion, do not post it a second time.\n",
|
|
239
|
+
"fieldRefs": []
|
|
240
|
+
},
|
|
241
|
+
"surfaces": [
|
|
242
|
+
{
|
|
243
|
+
"kind": "playground",
|
|
244
|
+
"export": "@happyvertical/smrt-comments/svelte#RecordCommentsPlayground",
|
|
245
|
+
"label": "Record discussion preview"
|
|
246
|
+
}
|
|
247
|
+
],
|
|
248
|
+
"runtime": "both",
|
|
249
|
+
"demoSeed": {
|
|
250
|
+
"export": "@happyvertical/smrt-comments/svelte#recordCommentsDemo"
|
|
251
|
+
},
|
|
252
|
+
"demo": {
|
|
253
|
+
"mode": "server",
|
|
254
|
+
"reasons": [
|
|
255
|
+
"Needs a server because its package depends on @happyvertical/smrt-tenancy, which do not build for a browser (#3624)."
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
"browser": {
|
|
261
|
+
"status": "server-only",
|
|
262
|
+
"issues": [
|
|
263
|
+
"#3624"
|
|
264
|
+
],
|
|
265
|
+
"via": [
|
|
266
|
+
"@happyvertical/smrt-tenancy"
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export interface RecordCommentView {
|
|
3
|
+
id: string;
|
|
4
|
+
body: string;
|
|
5
|
+
authorLabel: string;
|
|
6
|
+
createdAtLabel?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Props {
|
|
9
|
+
contextKey: string;
|
|
10
|
+
comments: readonly RecordCommentView[];
|
|
11
|
+
onsubmit?: (body: string) => void | Promise<void>;
|
|
12
|
+
heading?: string;
|
|
13
|
+
}
|
|
14
|
+
let { contextKey, comments, onsubmit, heading = 'Comments' }: Props = $props();
|
|
15
|
+
const inputId = $props.id();
|
|
16
|
+
let generation = 0;
|
|
17
|
+
$effect(() => {
|
|
18
|
+
void contextKey;
|
|
19
|
+
generation += 1;
|
|
20
|
+
body = '';
|
|
21
|
+
pending = false;
|
|
22
|
+
error = '';
|
|
23
|
+
return () => {
|
|
24
|
+
generation += 1;
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
let body = $state('');
|
|
28
|
+
let pending = $state(false);
|
|
29
|
+
let error = $state('');
|
|
30
|
+
async function submit() {
|
|
31
|
+
if (pending) return;
|
|
32
|
+
const submittedGeneration = generation;
|
|
33
|
+
const value = body.trim();
|
|
34
|
+
if (!value) {
|
|
35
|
+
error = 'Write a comment before posting.';
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!onsubmit) return;
|
|
39
|
+
pending = true;
|
|
40
|
+
error = '';
|
|
41
|
+
try {
|
|
42
|
+
await onsubmit(value);
|
|
43
|
+
if (generation === submittedGeneration) body = '';
|
|
44
|
+
} catch {
|
|
45
|
+
if (generation === submittedGeneration)
|
|
46
|
+
error =
|
|
47
|
+
'Could not confirm your comment was posted. Refresh and check the discussion before posting again.';
|
|
48
|
+
} finally {
|
|
49
|
+
if (generation === submittedGeneration) pending = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<section aria-label={heading} class="record-comments">
|
|
55
|
+
<h2>{heading}</h2>
|
|
56
|
+
<ol aria-live="polite">
|
|
57
|
+
{#each comments as comment (comment.id)}
|
|
58
|
+
<li><strong>{comment.authorLabel}</strong><p>{comment.body}</p>{#if comment.createdAtLabel}<small>{comment.createdAtLabel}</small>{/if}</li>
|
|
59
|
+
{/each}
|
|
60
|
+
</ol>
|
|
61
|
+
{#if onsubmit}
|
|
62
|
+
<form onsubmit={(event) => { event.preventDefault(); void submit(); }}>
|
|
63
|
+
<label for={inputId}>Add a comment</label>
|
|
64
|
+
<textarea id={inputId} bind:value={body} disabled={pending}></textarea>
|
|
65
|
+
{#if error}<p role="alert">{error}</p>{/if}
|
|
66
|
+
<button disabled={pending} type="submit">{pending ? 'Posting…' : 'Post comment'}</button>
|
|
67
|
+
</form>
|
|
68
|
+
{/if}
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
<style>.record-comments { display: grid; gap: var(--smrt-spacing-3, 0.75rem); } ol { display: grid; gap: var(--smrt-spacing-3, 0.75rem); list-style: none; margin: 0; padding: 0; } li { border-block-end: 1px solid var(--smrt-color-on-surface-variant); } textarea { display: block; min-height: 5rem; width: 100%; }</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface RecordCommentView {
|
|
2
|
+
id: string;
|
|
3
|
+
body: string;
|
|
4
|
+
authorLabel: string;
|
|
5
|
+
createdAtLabel?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Props {
|
|
8
|
+
contextKey: string;
|
|
9
|
+
comments: readonly RecordCommentView[];
|
|
10
|
+
onsubmit?: (body: string) => void | Promise<void>;
|
|
11
|
+
heading?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const RecordComments: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type RecordComments = ReturnType<typeof RecordComments>;
|
|
15
|
+
export default RecordComments;
|
|
16
|
+
//# sourceMappingURL=RecordComments.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordComments.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/RecordComments.svelte.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAiED,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { recordCommentsDemo } from './demo.js';
|
|
3
|
+
import RecordComments, {
|
|
4
|
+
type RecordCommentView,
|
|
5
|
+
} from './RecordComments.svelte';
|
|
6
|
+
|
|
7
|
+
let comments = $state<RecordCommentView[]>(
|
|
8
|
+
recordCommentsDemo.map((comment) => ({ ...comment })),
|
|
9
|
+
);
|
|
10
|
+
let nextId = 3;
|
|
11
|
+
function addComment(body: string) {
|
|
12
|
+
comments = [
|
|
13
|
+
...comments,
|
|
14
|
+
{ id: `demo-comment-${nextId++}`, authorLabel: 'You', body },
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<p>Sample record discussion. Comments stay in this preview and do not send notifications.</p>
|
|
20
|
+
<RecordComments contextKey="playground:sample-record" {comments} onsubmit={addComment} />
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
declare const RecordCommentsPlayground: import("svelte").Component<Record<string, never>, {}, "">;
|
|
2
|
+
type RecordCommentsPlayground = ReturnType<typeof RecordCommentsPlayground>;
|
|
3
|
+
export default RecordCommentsPlayground;
|
|
4
|
+
//# sourceMappingURL=RecordCommentsPlayground.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordCommentsPlayground.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/RecordCommentsPlayground.svelte.ts"],"names":[],"mappings":"AA6BA,QAAA,MAAM,wBAAwB,2DAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/svelte/demo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,EAAE,SAAS,iBAAiB,EAW1D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Browser-only sample projections, never persisted or sent as notifications. */
|
|
2
|
+
export const recordCommentsDemo = [
|
|
3
|
+
{
|
|
4
|
+
id: 'demo-comment-1',
|
|
5
|
+
authorLabel: 'Alex',
|
|
6
|
+
body: 'The draft is ready for review.',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: 'demo-comment-2',
|
|
10
|
+
authorLabel: 'Sam',
|
|
11
|
+
body: 'I will check it this afternoon.',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import RecordComments from './RecordComments.svelte';
|
|
2
|
+
export { recordCommentsDemo } from './demo.js';
|
|
3
|
+
export type { Props as RecordCommentsProps, RecordCommentView, } from './RecordComments.svelte';
|
|
4
|
+
export { default as RecordCommentsPlayground } from './RecordCommentsPlayground.svelte';
|
|
5
|
+
export { RecordComments };
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EACV,KAAK,IAAI,mBAAmB,EAC5B,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SmrtPolymorphicAssociationOptions } from '@happyvertical/smrt-core';
|
|
2
|
+
export interface CommentOptions extends SmrtPolymorphicAssociationOptions {
|
|
3
|
+
tenantId?: string;
|
|
4
|
+
authorUserId?: string;
|
|
5
|
+
body?: string;
|
|
6
|
+
mentions?: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export interface CommentMention {
|
|
9
|
+
commentId: string;
|
|
10
|
+
tenantId: string;
|
|
11
|
+
authorUserId: string;
|
|
12
|
+
recipientUserId: string;
|
|
13
|
+
recordType: string;
|
|
14
|
+
recordId: string;
|
|
15
|
+
body: string;
|
|
16
|
+
}
|
|
17
|
+
/** Composition seam for a host or the smrt-messages notification adapter. */
|
|
18
|
+
export interface CommentMentionNotificationAdapter {
|
|
19
|
+
notifyMention(mention: CommentMention): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/** Trusted server context; never populate from the comment request body. */
|
|
22
|
+
export interface CommentActorContext {
|
|
23
|
+
tenantId: string;
|
|
24
|
+
userId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface CommentRecordAccess extends CommentActorContext {
|
|
27
|
+
recordType: string;
|
|
28
|
+
recordId: string;
|
|
29
|
+
action: 'read' | 'comment';
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,0BAA0B,CAAC;AAElF,MAAM,WAAW,cAAe,SAAQ,iCAAiC;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6EAA6E;AAC7E,MAAM,WAAW,iCAAiC;IAChD,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B"}
|
package/dist/types.js
ADDED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-comments",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.55.10",
|
|
4
|
+
"description": "Record comments and mention hooks for SMRT applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"CLAUDE.md",
|
|
11
|
+
"AGENTS.md"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./svelte": {
|
|
19
|
+
"types": "./dist/svelte/index.d.ts",
|
|
20
|
+
"svelte": "./dist/svelte/index.js",
|
|
21
|
+
"import": "./dist/svelte/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./manifest": "./dist/manifest.json",
|
|
24
|
+
"./manifest.json": "./dist/manifest.json"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@happyvertical/smrt-core": "0.55.10",
|
|
28
|
+
"@happyvertical/smrt-tenancy": "0.55.10"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"svelte": "^5.57.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"svelte": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"author": "HappyVertical",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/happyvertical/smrt.git",
|
|
43
|
+
"directory": "packages/comments"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@happyvertical/smrt-vitest": "0.55.10",
|
|
47
|
+
"@sveltejs/package": "^2.5.8",
|
|
48
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
49
|
+
"@testing-library/svelte": "^5.4.2",
|
|
50
|
+
"@types/node": "24.13.6",
|
|
51
|
+
"svelte": "^5.57.1",
|
|
52
|
+
"svelte-check": "^4.7.6",
|
|
53
|
+
"typescript": "6.0.3",
|
|
54
|
+
"vite": "8.1.4",
|
|
55
|
+
"vitest": "4.1.10",
|
|
56
|
+
"@happyvertical/smrt-messages": "0.55.10"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "vite build --mode library && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json && node ../../scripts/prune-svelte-package-artifacts.js dist",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"check": "svelte-check --tsconfig ./tsconfig.svelte.json",
|
|
62
|
+
"typecheck": "tsc --noEmit -p tsconfig.json && tsc -p tsconfig.test.json && node ../../scripts/svelte-check-a11y.mjs --tsconfig ./tsconfig.svelte-test.json",
|
|
63
|
+
"test:postgres": "node ../../scripts/run-with-ci-postgres.mjs -- pnpm exec vitest run src/comments.test.ts"
|
|
64
|
+
}
|
|
6
65
|
}
|