@bitvea/feedback-toolbar 0.0.1
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 +262 -0
- package/dist/FeedbackPanel.d.ts +117 -0
- package/dist/FeedbackPanel.d.ts.map +1 -0
- package/dist/FeedbackPanel.js +622 -0
- package/dist/FeedbackPanel.js.map +1 -0
- package/dist/FeedbackToolbar.d.ts +54 -0
- package/dist/FeedbackToolbar.d.ts.map +1 -0
- package/dist/FeedbackToolbar.js +1149 -0
- package/dist/FeedbackToolbar.js.map +1 -0
- package/dist/InboxSheet.d.ts +80 -0
- package/dist/InboxSheet.d.ts.map +1 -0
- package/dist/InboxSheet.js +580 -0
- package/dist/InboxSheet.js.map +1 -0
- package/dist/PinLayer.d.ts +59 -0
- package/dist/PinLayer.d.ts.map +1 -0
- package/dist/PinLayer.js +1702 -0
- package/dist/PinLayer.js.map +1 -0
- package/dist/RichText.d.ts +6 -0
- package/dist/RichText.d.ts.map +1 -0
- package/dist/RichText.js +135 -0
- package/dist/RichText.js.map +1 -0
- package/dist/browser/entry.d.ts +3 -0
- package/dist/browser/entry.d.ts.map +1 -0
- package/dist/browser/entry.js +13 -0
- package/dist/browser/entry.js.map +1 -0
- package/dist/browser/mount.d.ts +37 -0
- package/dist/browser/mount.d.ts.map +1 -0
- package/dist/browser/mount.js +150 -0
- package/dist/browser/mount.js.map +1 -0
- package/dist/browser/toolbar.js +38 -0
- package/dist/browser/toolbar.js.map +7 -0
- package/dist/capture.d.ts +58 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +98 -0
- package/dist/capture.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +196 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/fs.d.ts +16 -0
- package/dist/cli/fs.d.ts.map +1 -0
- package/dist/cli/fs.js +33 -0
- package/dist/cli/fs.js.map +1 -0
- package/dist/cli/init.d.ts +75 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +266 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/register.d.ts +55 -0
- package/dist/cli/register.d.ts.map +1 -0
- package/dist/cli/register.js +84 -0
- package/dist/cli/register.js.map +1 -0
- package/dist/cli/registration.d.ts +37 -0
- package/dist/cli/registration.d.ts.map +1 -0
- package/dist/cli/registration.js +69 -0
- package/dist/cli/registration.js.map +1 -0
- package/dist/cli/strategies.d.ts +98 -0
- package/dist/cli/strategies.d.ts.map +1 -0
- package/dist/cli/strategies.js +198 -0
- package/dist/cli/strategies.js.map +1 -0
- package/dist/client.d.ts +59 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +113 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +92 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +65 -0
- package/dist/config.js.map +1 -0
- package/dist/deepLink.d.ts +86 -0
- package/dist/deepLink.d.ts.map +1 -0
- package/dist/deepLink.js +185 -0
- package/dist/deepLink.js.map +1 -0
- package/dist/fontFace.d.ts +70 -0
- package/dist/fontFace.d.ts.map +1 -0
- package/dist/fontFace.js +88 -0
- package/dist/fontFace.js.map +1 -0
- package/dist/gating.d.ts +32 -0
- package/dist/gating.d.ts.map +1 -0
- package/dist/gating.js +49 -0
- package/dist/gating.js.map +1 -0
- package/dist/icons.d.ts +68 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +97 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +59 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +130 -0
- package/dist/markdown.js.map +1 -0
- package/dist/motion.d.ts +178 -0
- package/dist/motion.d.ts.map +1 -0
- package/dist/motion.js +302 -0
- package/dist/motion.js.map +1 -0
- package/dist/preferences.d.ts +71 -0
- package/dist/preferences.d.ts.map +1 -0
- package/dist/preferences.js +195 -0
- package/dist/preferences.js.map +1 -0
- package/dist/rasterise.d.ts +45 -0
- package/dist/rasterise.d.ts.map +1 -0
- package/dist/rasterise.js +490 -0
- package/dist/rasterise.js.map +1 -0
- package/dist/selector.d.ts +19 -0
- package/dist/selector.d.ts.map +1 -0
- package/dist/selector.js +142 -0
- package/dist/selector.js.map +1 -0
- package/dist/session.d.ts +19 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +36 -0
- package/dist/session.js.map +1 -0
- package/dist/shortcut.d.ts +88 -0
- package/dist/shortcut.d.ts.map +1 -0
- package/dist/shortcut.js +149 -0
- package/dist/shortcut.js.map +1 -0
- package/dist/tokens.d.ts +709 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +749 -0
- package/dist/tokens.js.map +1 -0
- package/dist/vendor/types/account.d.ts +26 -0
- package/dist/vendor/types/account.d.ts.map +1 -0
- package/dist/vendor/types/account.js +23 -0
- package/dist/vendor/types/account.js.map +1 -0
- package/dist/vendor/types/apiKey.d.ts +38 -0
- package/dist/vendor/types/apiKey.d.ts.map +1 -0
- package/dist/vendor/types/apiKey.js +36 -0
- package/dist/vendor/types/apiKey.js.map +1 -0
- package/dist/vendor/types/auth.d.ts +10 -0
- package/dist/vendor/types/auth.d.ts.map +1 -0
- package/dist/vendor/types/auth.js +15 -0
- package/dist/vendor/types/auth.js.map +1 -0
- package/dist/vendor/types/entity.d.ts +74 -0
- package/dist/vendor/types/entity.d.ts.map +1 -0
- package/dist/vendor/types/entity.js +111 -0
- package/dist/vendor/types/entity.js.map +1 -0
- package/dist/vendor/types/feedback.d.ts +285 -0
- package/dist/vendor/types/feedback.d.ts.map +1 -0
- package/dist/vendor/types/feedback.js +286 -0
- package/dist/vendor/types/feedback.js.map +1 -0
- package/dist/vendor/types/index.d.ts +14 -0
- package/dist/vendor/types/index.d.ts.map +1 -0
- package/dist/vendor/types/index.js +16 -0
- package/dist/vendor/types/index.js.map +1 -0
- package/dist/vendor/types/invite.d.ts +42 -0
- package/dist/vendor/types/invite.d.ts.map +1 -0
- package/dist/vendor/types/invite.js +30 -0
- package/dist/vendor/types/invite.js.map +1 -0
- package/dist/vendor/types/mcpToken.d.ts +38 -0
- package/dist/vendor/types/mcpToken.d.ts.map +1 -0
- package/dist/vendor/types/mcpToken.js +39 -0
- package/dist/vendor/types/mcpToken.js.map +1 -0
- package/dist/vendor/types/organization.d.ts +13 -0
- package/dist/vendor/types/organization.d.ts.map +1 -0
- package/dist/vendor/types/organization.js +12 -0
- package/dist/vendor/types/organization.js.map +1 -0
- package/dist/vendor/types/project.d.ts +73 -0
- package/dist/vendor/types/project.d.ts.map +1 -0
- package/dist/vendor/types/project.js +117 -0
- package/dist/vendor/types/project.js.map +1 -0
- package/dist/vendor/types/role.d.ts +12 -0
- package/dist/vendor/types/role.d.ts.map +1 -0
- package/dist/vendor/types/role.js +20 -0
- package/dist/vendor/types/role.js.map +1 -0
- package/dist/vendor/types/roleDefinition.d.ts +61 -0
- package/dist/vendor/types/roleDefinition.d.ts.map +1 -0
- package/dist/vendor/types/roleDefinition.js +45 -0
- package/dist/vendor/types/roleDefinition.js.map +1 -0
- package/dist/vendor/types/team.d.ts +25 -0
- package/dist/vendor/types/team.d.ts.map +1 -0
- package/dist/vendor/types/team.js +17 -0
- package/dist/vendor/types/team.js.map +1 -0
- package/dist/vendor/types/util.d.ts +39 -0
- package/dist/vendor/types/util.d.ts.map +1 -0
- package/dist/vendor/types/util.js +31 -0
- package/dist/vendor/types/util.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Anchored to a page element, or free text about the page as a whole. */
|
|
3
|
+
export declare const feedbackKindSchema: z.ZodEnum<{
|
|
4
|
+
GENERAL: "GENERAL";
|
|
5
|
+
PINNED: "PINNED";
|
|
6
|
+
}>;
|
|
7
|
+
export type FeedbackKind = z.infer<typeof feedbackKindSchema>;
|
|
8
|
+
/**
|
|
9
|
+
* The triage lane an item sits in. Moved from the dashboard or from the
|
|
10
|
+
* toolbar's own thread popover, by any member of the project.
|
|
11
|
+
*/
|
|
12
|
+
export declare const feedbackStatusSchema: z.ZodEnum<{
|
|
13
|
+
OPEN: "OPEN";
|
|
14
|
+
IN_REVIEW: "IN_REVIEW";
|
|
15
|
+
DONE: "DONE";
|
|
16
|
+
}>;
|
|
17
|
+
export type FeedbackStatus = z.infer<typeof feedbackStatusSchema>;
|
|
18
|
+
/** Stable display order for the dashboard's status filter. */
|
|
19
|
+
export declare const FEEDBACK_STATUSES: readonly FeedbackStatus[];
|
|
20
|
+
export declare const FEEDBACK_STATUS_LABELS: Record<FeedbackStatus, string>;
|
|
21
|
+
/** Longest body we accept, for a feedback item and for a reply alike. */
|
|
22
|
+
export declare const FEEDBACK_BODY_MAX = 5000;
|
|
23
|
+
/** Largest decoded screenshot we store, in bytes. A full-page PNG of a busy
|
|
24
|
+
* dashboard lands well under this; anything larger is a capture gone wrong. */
|
|
25
|
+
export declare const SCREENSHOT_MAX_BYTES: number;
|
|
26
|
+
/** The data URL carrying it is base64, so about 4/3 the size, plus the header. */
|
|
27
|
+
export declare const SCREENSHOT_DATA_URL_MAX: number;
|
|
28
|
+
/**
|
|
29
|
+
* Context the toolbar captures itself at submission time. None of it is typed
|
|
30
|
+
* by the reviewer, so a submission missing any required field is a toolbar bug
|
|
31
|
+
* and is rejected rather than stored half-blank.
|
|
32
|
+
*/
|
|
33
|
+
export declare const feedbackMetadataSchema: z.ZodObject<{
|
|
34
|
+
pageUrl: z.ZodString;
|
|
35
|
+
viewportWidth: z.ZodNumber;
|
|
36
|
+
viewportHeight: z.ZodNumber;
|
|
37
|
+
userAgent: z.ZodString;
|
|
38
|
+
gitBranch: z.ZodOptional<z.ZodString>;
|
|
39
|
+
gitCommit: z.ZodOptional<z.ZodString>;
|
|
40
|
+
environment: z.ZodString;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type FeedbackMetadata = z.infer<typeof feedbackMetadataSchema>;
|
|
43
|
+
/**
|
|
44
|
+
* Where a pinned item is anchored. `selector` finds the element again after a
|
|
45
|
+
* reload; the offsets are fractions of that element's box (0..1) so the dot
|
|
46
|
+
* stays in place when the element resizes.
|
|
47
|
+
*/
|
|
48
|
+
export declare const pinAnchorSchema: z.ZodObject<{
|
|
49
|
+
selector: z.ZodString;
|
|
50
|
+
offsetX: z.ZodNumber;
|
|
51
|
+
offsetY: z.ZodNumber;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
export type PinAnchor = z.infer<typeof pinAnchorSchema>;
|
|
54
|
+
/**
|
|
55
|
+
* A submission from the toolbar. `pin` is required exactly when `kind` is
|
|
56
|
+
* PINNED, which is what stops a pinned item being stored with nothing to
|
|
57
|
+
* anchor it to and a general item carrying a stray anchor.
|
|
58
|
+
*/
|
|
59
|
+
export declare const feedbackCreateSchema: z.ZodObject<{
|
|
60
|
+
organizationId: z.ZodString;
|
|
61
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
62
|
+
GENERAL: "GENERAL";
|
|
63
|
+
PINNED: "PINNED";
|
|
64
|
+
}>>;
|
|
65
|
+
body: z.ZodString;
|
|
66
|
+
metadata: z.ZodObject<{
|
|
67
|
+
pageUrl: z.ZodString;
|
|
68
|
+
viewportWidth: z.ZodNumber;
|
|
69
|
+
viewportHeight: z.ZodNumber;
|
|
70
|
+
userAgent: z.ZodString;
|
|
71
|
+
gitBranch: z.ZodOptional<z.ZodString>;
|
|
72
|
+
gitCommit: z.ZodOptional<z.ZodString>;
|
|
73
|
+
environment: z.ZodString;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
pin: z.ZodOptional<z.ZodObject<{
|
|
76
|
+
selector: z.ZodString;
|
|
77
|
+
offsetX: z.ZodNumber;
|
|
78
|
+
offsetY: z.ZodNumber;
|
|
79
|
+
}, z.core.$strip>>;
|
|
80
|
+
screenshot: z.ZodOptional<z.ZodString>;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
export type FeedbackCreateInput = z.infer<typeof feedbackCreateSchema>;
|
|
83
|
+
/**
|
|
84
|
+
* Moving one item between lanes. Only the target lane is on the wire: who did
|
|
85
|
+
* it comes from the caller's own session or token, never from the request, or
|
|
86
|
+
* the attribution columns would be a field a client could forge.
|
|
87
|
+
*/
|
|
88
|
+
export declare const feedbackStatusUpdateSchema: z.ZodObject<{
|
|
89
|
+
status: z.ZodEnum<{
|
|
90
|
+
OPEN: "OPEN";
|
|
91
|
+
IN_REVIEW: "IN_REVIEW";
|
|
92
|
+
DONE: "DONE";
|
|
93
|
+
}>;
|
|
94
|
+
}, z.core.$strip>;
|
|
95
|
+
export type FeedbackStatusUpdateInput = z.infer<typeof feedbackStatusUpdateSchema>;
|
|
96
|
+
export declare const replyCreateSchema: z.ZodObject<{
|
|
97
|
+
body: z.ZodString;
|
|
98
|
+
screenshot: z.ZodOptional<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
export type ReplyCreateInput = z.infer<typeof replyCreateSchema>;
|
|
101
|
+
/**
|
|
102
|
+
* How many items one list read answers with by default, and the ceiling a
|
|
103
|
+
* caller may raise it to.
|
|
104
|
+
*
|
|
105
|
+
* `FeedbackItem` is the one table in this schema that grows without bound, and
|
|
106
|
+
* every row it returns carries its whole reply thread. An unbounded read is
|
|
107
|
+
* therefore a response whose size is a project's entire review history - and
|
|
108
|
+
* the toolbar's inbox issues one on every open of the sheet, from a widget
|
|
109
|
+
* running on the customer's own deployment. So the bound lives in the schema
|
|
110
|
+
* rather than at each call site, and a caller that says nothing gets it.
|
|
111
|
+
*/
|
|
112
|
+
export declare const FEEDBACK_LIST_LIMIT_DEFAULT = 100;
|
|
113
|
+
export declare const FEEDBACK_LIST_LIMIT_MAX = 500;
|
|
114
|
+
/** Filter for the dashboard's feedback list. */
|
|
115
|
+
export declare const feedbackListQuerySchema: z.ZodObject<{
|
|
116
|
+
organizationId: z.ZodString;
|
|
117
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
118
|
+
OPEN: "OPEN";
|
|
119
|
+
IN_REVIEW: "IN_REVIEW";
|
|
120
|
+
DONE: "DONE";
|
|
121
|
+
}>>;
|
|
122
|
+
pageUrl: z.ZodOptional<z.ZodString>;
|
|
123
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
124
|
+
}, z.core.$strip>;
|
|
125
|
+
export type FeedbackListQuery = z.infer<typeof feedbackListQuerySchema>;
|
|
126
|
+
/**
|
|
127
|
+
* Item-scoped routes still have to name their project: membership is per
|
|
128
|
+
* project, and an id in the path is not proof of anything on its own.
|
|
129
|
+
*/
|
|
130
|
+
export declare const feedbackProjectQuerySchema: z.ZodObject<{
|
|
131
|
+
organizationId: z.ZodString;
|
|
132
|
+
}, z.core.$strip>;
|
|
133
|
+
export type FeedbackProjectQuery = z.infer<typeof feedbackProjectQuerySchema>;
|
|
134
|
+
/**
|
|
135
|
+
* Filter for `GET /api/v1/feedback/counts`.
|
|
136
|
+
*
|
|
137
|
+
* `organizationId` is OPTIONAL here and required everywhere else in this file,
|
|
138
|
+
* which is the whole point of the route: its subject is "every project the
|
|
139
|
+
* caller can reach", a fact about the person rather than about one project.
|
|
140
|
+
* Omitting it asks for that whole answer.
|
|
141
|
+
*
|
|
142
|
+
* What it is NOT is a list. A caller may narrow to one project they are a
|
|
143
|
+
* member of - the projects list and a single-project screen both want that -
|
|
144
|
+
* but the set of projects in the answer is always computed from the caller's
|
|
145
|
+
* own memberships per request, never taken from the request. A repeatable
|
|
146
|
+
* `organizationId[]` would look like a filter and read like an access-control
|
|
147
|
+
* decision the client gets to make, and the first time somebody passed a
|
|
148
|
+
* project id they had no membership in, the only thing standing between them
|
|
149
|
+
* and its counts would be a server-side intersection nobody had a reason to
|
|
150
|
+
* write. One id, checked the same way every other feedback read checks one.
|
|
151
|
+
*
|
|
152
|
+
* Still `.min(1)` when present: `?organizationId=` is a client that thinks it
|
|
153
|
+
* named a project, and silently answering with the install-wide total instead
|
|
154
|
+
* would be the wrong number reported with full confidence.
|
|
155
|
+
*/
|
|
156
|
+
export declare const feedbackCountsQuerySchema: z.ZodObject<{
|
|
157
|
+
organizationId: z.ZodOptional<z.ZodString>;
|
|
158
|
+
}, z.core.$strip>;
|
|
159
|
+
export type FeedbackCountsQuery = z.infer<typeof feedbackCountsQuerySchema>;
|
|
160
|
+
export declare const feedbackAuthorSchema: z.ZodObject<{
|
|
161
|
+
id: z.ZodString;
|
|
162
|
+
name: z.ZodString;
|
|
163
|
+
email: z.ZodString;
|
|
164
|
+
}, z.core.$strip>;
|
|
165
|
+
export type FeedbackAuthorDTO = z.infer<typeof feedbackAuthorSchema>;
|
|
166
|
+
export declare const replySchema: z.ZodObject<{
|
|
167
|
+
id: z.ZodString;
|
|
168
|
+
body: z.ZodString;
|
|
169
|
+
screenshotUrl: z.ZodNullable<z.ZodString>;
|
|
170
|
+
author: z.ZodObject<{
|
|
171
|
+
id: z.ZodString;
|
|
172
|
+
name: z.ZodString;
|
|
173
|
+
email: z.ZodString;
|
|
174
|
+
}, z.core.$strip>;
|
|
175
|
+
viaAgent: z.ZodBoolean;
|
|
176
|
+
createdAt: z.ZodString;
|
|
177
|
+
}, z.core.$strip>;
|
|
178
|
+
export type ReplyDTO = z.infer<typeof replySchema>;
|
|
179
|
+
export declare const pinSchema: z.ZodObject<{
|
|
180
|
+
selector: z.ZodString;
|
|
181
|
+
offsetX: z.ZodNumber;
|
|
182
|
+
offsetY: z.ZodNumber;
|
|
183
|
+
}, z.core.$strip>;
|
|
184
|
+
export type PinDTO = z.infer<typeof pinSchema>;
|
|
185
|
+
export declare const feedbackItemSchema: z.ZodObject<{
|
|
186
|
+
id: z.ZodString;
|
|
187
|
+
organizationId: z.ZodString;
|
|
188
|
+
kind: z.ZodEnum<{
|
|
189
|
+
GENERAL: "GENERAL";
|
|
190
|
+
PINNED: "PINNED";
|
|
191
|
+
}>;
|
|
192
|
+
status: z.ZodEnum<{
|
|
193
|
+
OPEN: "OPEN";
|
|
194
|
+
IN_REVIEW: "IN_REVIEW";
|
|
195
|
+
DONE: "DONE";
|
|
196
|
+
}>;
|
|
197
|
+
body: z.ZodString;
|
|
198
|
+
pageUrl: z.ZodString;
|
|
199
|
+
viewportWidth: z.ZodNumber;
|
|
200
|
+
viewportHeight: z.ZodNumber;
|
|
201
|
+
userAgent: z.ZodString;
|
|
202
|
+
gitBranch: z.ZodNullable<z.ZodString>;
|
|
203
|
+
gitCommit: z.ZodNullable<z.ZodString>;
|
|
204
|
+
environment: z.ZodString;
|
|
205
|
+
screenshotUrl: z.ZodNullable<z.ZodString>;
|
|
206
|
+
author: z.ZodObject<{
|
|
207
|
+
id: z.ZodString;
|
|
208
|
+
name: z.ZodString;
|
|
209
|
+
email: z.ZodString;
|
|
210
|
+
}, z.core.$strip>;
|
|
211
|
+
statusChangedBy: z.ZodNullable<z.ZodObject<{
|
|
212
|
+
id: z.ZodString;
|
|
213
|
+
name: z.ZodString;
|
|
214
|
+
email: z.ZodString;
|
|
215
|
+
}, z.core.$strip>>;
|
|
216
|
+
statusChangedAt: z.ZodNullable<z.ZodString>;
|
|
217
|
+
statusChangedViaAgent: z.ZodBoolean;
|
|
218
|
+
pin: z.ZodNullable<z.ZodObject<{
|
|
219
|
+
selector: z.ZodString;
|
|
220
|
+
offsetX: z.ZodNumber;
|
|
221
|
+
offsetY: z.ZodNumber;
|
|
222
|
+
}, z.core.$strip>>;
|
|
223
|
+
replies: z.ZodArray<z.ZodObject<{
|
|
224
|
+
id: z.ZodString;
|
|
225
|
+
body: z.ZodString;
|
|
226
|
+
screenshotUrl: z.ZodNullable<z.ZodString>;
|
|
227
|
+
author: z.ZodObject<{
|
|
228
|
+
id: z.ZodString;
|
|
229
|
+
name: z.ZodString;
|
|
230
|
+
email: z.ZodString;
|
|
231
|
+
}, z.core.$strip>;
|
|
232
|
+
viaAgent: z.ZodBoolean;
|
|
233
|
+
createdAt: z.ZodString;
|
|
234
|
+
}, z.core.$strip>>;
|
|
235
|
+
createdAt: z.ZodString;
|
|
236
|
+
}, z.core.$strip>;
|
|
237
|
+
export type FeedbackItemDTO = z.infer<typeof feedbackItemSchema>;
|
|
238
|
+
export declare const feedbackStatusCountsSchema: z.ZodObject<{
|
|
239
|
+
OPEN: z.ZodNumber;
|
|
240
|
+
IN_REVIEW: z.ZodNumber;
|
|
241
|
+
DONE: z.ZodNumber;
|
|
242
|
+
}, z.core.$strip>;
|
|
243
|
+
export type FeedbackStatusCounts = z.infer<typeof feedbackStatusCountsSchema>;
|
|
244
|
+
/** One project's lane totals. The project is named by id only: every consumer
|
|
245
|
+
* of this route already holds the project list, and re-sending names here
|
|
246
|
+
* would be a second copy of `ProjectDTO` that could disagree with the first. */
|
|
247
|
+
export declare const feedbackProjectCountsSchema: z.ZodObject<{
|
|
248
|
+
organizationId: z.ZodString;
|
|
249
|
+
counts: z.ZodObject<{
|
|
250
|
+
OPEN: z.ZodNumber;
|
|
251
|
+
IN_REVIEW: z.ZodNumber;
|
|
252
|
+
DONE: z.ZodNumber;
|
|
253
|
+
}, z.core.$strip>;
|
|
254
|
+
}, z.core.$strip>;
|
|
255
|
+
export type FeedbackProjectCountsDTO = z.infer<typeof feedbackProjectCountsSchema>;
|
|
256
|
+
/**
|
|
257
|
+
* The answer to `GET /api/v1/feedback/counts`.
|
|
258
|
+
*
|
|
259
|
+
* `projects` carries a row for every project the caller can reach, including
|
|
260
|
+
* the ones with no feedback at all - the breakdown a per-project screen wants.
|
|
261
|
+
* `totals` is the cross-project sum, and it is on the wire rather than left to
|
|
262
|
+
* the client on purpose: the install-wide open figure is the number this route
|
|
263
|
+
* exists to answer, and folding the array to get it would put the definition
|
|
264
|
+
* of "across every project the caller can reach" in the caller instead of in
|
|
265
|
+
* the one place that knows what the caller can reach. The sum is safe in a way
|
|
266
|
+
* `ProjectDTO.memberCount` is not - an item belongs to exactly one project, so
|
|
267
|
+
* nothing is counted twice.
|
|
268
|
+
*/
|
|
269
|
+
export declare const feedbackCountsSchema: z.ZodObject<{
|
|
270
|
+
projects: z.ZodArray<z.ZodObject<{
|
|
271
|
+
organizationId: z.ZodString;
|
|
272
|
+
counts: z.ZodObject<{
|
|
273
|
+
OPEN: z.ZodNumber;
|
|
274
|
+
IN_REVIEW: z.ZodNumber;
|
|
275
|
+
DONE: z.ZodNumber;
|
|
276
|
+
}, z.core.$strip>;
|
|
277
|
+
}, z.core.$strip>>;
|
|
278
|
+
totals: z.ZodObject<{
|
|
279
|
+
OPEN: z.ZodNumber;
|
|
280
|
+
IN_REVIEW: z.ZodNumber;
|
|
281
|
+
DONE: z.ZodNumber;
|
|
282
|
+
}, z.core.$strip>;
|
|
283
|
+
}, z.core.$strip>;
|
|
284
|
+
export type FeedbackCountsDTO = z.infer<typeof feedbackCountsSchema>;
|
|
285
|
+
//# sourceMappingURL=feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../../types/src/feedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// Feedback, Pin, and Reply schemas: the product's own domain, shared by the
|
|
2
|
+
// toolbar (which submits), the ingestion API (which validates), and the admin
|
|
3
|
+
// dashboard (which reads). Single source of truth for both runtime validation
|
|
4
|
+
// and the TypeScript types on either side of the wire.
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
/** Anchored to a page element, or free text about the page as a whole. */
|
|
7
|
+
export const feedbackKindSchema = z.enum(["GENERAL", "PINNED"]);
|
|
8
|
+
/**
|
|
9
|
+
* The triage lane an item sits in. Moved from the dashboard or from the
|
|
10
|
+
* toolbar's own thread popover, by any member of the project.
|
|
11
|
+
*/
|
|
12
|
+
export const feedbackStatusSchema = z.enum(["OPEN", "IN_REVIEW", "DONE"]);
|
|
13
|
+
/** Stable display order for the dashboard's status filter. */
|
|
14
|
+
export const FEEDBACK_STATUSES = [
|
|
15
|
+
"OPEN",
|
|
16
|
+
"IN_REVIEW",
|
|
17
|
+
"DONE",
|
|
18
|
+
];
|
|
19
|
+
export const FEEDBACK_STATUS_LABELS = {
|
|
20
|
+
OPEN: "Open",
|
|
21
|
+
IN_REVIEW: "In review",
|
|
22
|
+
DONE: "Done",
|
|
23
|
+
};
|
|
24
|
+
/** Longest body we accept, for a feedback item and for a reply alike. */
|
|
25
|
+
export const FEEDBACK_BODY_MAX = 5000;
|
|
26
|
+
/** Largest decoded screenshot we store, in bytes. A full-page PNG of a busy
|
|
27
|
+
* dashboard lands well under this; anything larger is a capture gone wrong. */
|
|
28
|
+
export const SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
|
|
29
|
+
/** The data URL carrying it is base64, so about 4/3 the size, plus the header. */
|
|
30
|
+
export const SCREENSHOT_DATA_URL_MAX = Math.ceil(SCREENSHOT_MAX_BYTES * 1.4);
|
|
31
|
+
/**
|
|
32
|
+
* Context the toolbar captures itself at submission time. None of it is typed
|
|
33
|
+
* by the reviewer, so a submission missing any required field is a toolbar bug
|
|
34
|
+
* and is rejected rather than stored half-blank.
|
|
35
|
+
*/
|
|
36
|
+
export const feedbackMetadataSchema = z.object({
|
|
37
|
+
pageUrl: z.string().url("A valid page URL is required."),
|
|
38
|
+
viewportWidth: z.number().int().positive().max(100_000),
|
|
39
|
+
viewportHeight: z.number().int().positive().max(100_000),
|
|
40
|
+
userAgent: z.string().trim().min(1).max(1000),
|
|
41
|
+
// Vercel populates these at build time; a local or non-Vercel build has
|
|
42
|
+
// neither, so both are optional rather than empty strings.
|
|
43
|
+
gitBranch: z.string().trim().max(255).optional(),
|
|
44
|
+
gitCommit: z.string().trim().max(255).optional(),
|
|
45
|
+
environment: z.string().trim().min(1).max(50),
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Where a pinned item is anchored. `selector` finds the element again after a
|
|
49
|
+
* reload; the offsets are fractions of that element's box (0..1) so the dot
|
|
50
|
+
* stays in place when the element resizes.
|
|
51
|
+
*/
|
|
52
|
+
export const pinAnchorSchema = z.object({
|
|
53
|
+
selector: z.string().trim().min(1).max(2000),
|
|
54
|
+
offsetX: z.number().min(0).max(1),
|
|
55
|
+
offsetY: z.number().min(0).max(1),
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* A submission from the toolbar. `pin` is required exactly when `kind` is
|
|
59
|
+
* PINNED, which is what stops a pinned item being stored with nothing to
|
|
60
|
+
* anchor it to and a general item carrying a stray anchor.
|
|
61
|
+
*/
|
|
62
|
+
export const feedbackCreateSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
// Which project the item belongs to. The route checks the caller is a
|
|
65
|
+
// member of it before anything is written.
|
|
66
|
+
organizationId: z.string().trim().min(1),
|
|
67
|
+
kind: feedbackKindSchema.default("GENERAL"),
|
|
68
|
+
body: z
|
|
69
|
+
.string()
|
|
70
|
+
.trim()
|
|
71
|
+
.min(1, "Feedback cannot be empty.")
|
|
72
|
+
.max(FEEDBACK_BODY_MAX, `Feedback must be at most ${FEEDBACK_BODY_MAX} characters.`),
|
|
73
|
+
metadata: feedbackMetadataSchema,
|
|
74
|
+
pin: pinAnchorSchema.optional(),
|
|
75
|
+
/**
|
|
76
|
+
* The captured screenshot as a data URL. Optional because capture can fail
|
|
77
|
+
* in a browser that blocks it, and losing the reviewer's words to a failed
|
|
78
|
+
* screenshot would be the worse trade.
|
|
79
|
+
*/
|
|
80
|
+
screenshot: z.string().max(SCREENSHOT_DATA_URL_MAX).optional(),
|
|
81
|
+
})
|
|
82
|
+
.refine((v) => (v.kind === "PINNED" ? v.pin !== undefined : true), {
|
|
83
|
+
message: "A pinned item must carry a pin anchor.",
|
|
84
|
+
path: ["pin"],
|
|
85
|
+
})
|
|
86
|
+
.refine((v) => (v.kind === "GENERAL" ? v.pin === undefined : true), {
|
|
87
|
+
message: "A general item must not carry a pin anchor.",
|
|
88
|
+
path: ["pin"],
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* Moving one item between lanes. Only the target lane is on the wire: who did
|
|
92
|
+
* it comes from the caller's own session or token, never from the request, or
|
|
93
|
+
* the attribution columns would be a field a client could forge.
|
|
94
|
+
*/
|
|
95
|
+
export const feedbackStatusUpdateSchema = z.object({
|
|
96
|
+
status: feedbackStatusSchema,
|
|
97
|
+
});
|
|
98
|
+
export const replyCreateSchema = z.object({
|
|
99
|
+
body: z
|
|
100
|
+
.string()
|
|
101
|
+
.trim()
|
|
102
|
+
.min(1, "A reply cannot be empty.")
|
|
103
|
+
.max(FEEDBACK_BODY_MAX, `A reply must be at most ${FEEDBACK_BODY_MAX} characters.`),
|
|
104
|
+
/**
|
|
105
|
+
* A `data:image/...;base64,` URL of ONE element the reviewer pointed at.
|
|
106
|
+
*
|
|
107
|
+
* Optional, and the reply is valid without it: the camera is a way to show
|
|
108
|
+
* what you mean, never a required field. Same wire shape the root report
|
|
109
|
+
* already uses, so both doors decode through `decodeScreenshotDataUrl` and
|
|
110
|
+
* neither invents its own size or content-type rule.
|
|
111
|
+
*/
|
|
112
|
+
screenshot: z.string().max(SCREENSHOT_DATA_URL_MAX).optional(),
|
|
113
|
+
});
|
|
114
|
+
/**
|
|
115
|
+
* How many items one list read answers with by default, and the ceiling a
|
|
116
|
+
* caller may raise it to.
|
|
117
|
+
*
|
|
118
|
+
* `FeedbackItem` is the one table in this schema that grows without bound, and
|
|
119
|
+
* every row it returns carries its whole reply thread. An unbounded read is
|
|
120
|
+
* therefore a response whose size is a project's entire review history - and
|
|
121
|
+
* the toolbar's inbox issues one on every open of the sheet, from a widget
|
|
122
|
+
* running on the customer's own deployment. So the bound lives in the schema
|
|
123
|
+
* rather than at each call site, and a caller that says nothing gets it.
|
|
124
|
+
*/
|
|
125
|
+
export const FEEDBACK_LIST_LIMIT_DEFAULT = 100;
|
|
126
|
+
export const FEEDBACK_LIST_LIMIT_MAX = 500;
|
|
127
|
+
/** Filter for the dashboard's feedback list. */
|
|
128
|
+
export const feedbackListQuerySchema = z.object({
|
|
129
|
+
organizationId: z.string().trim().min(1),
|
|
130
|
+
status: feedbackStatusSchema.optional(),
|
|
131
|
+
/** Restrict to one page, used by the toolbar to show the current page's pins. */
|
|
132
|
+
pageUrl: z.string().url().optional(),
|
|
133
|
+
/**
|
|
134
|
+
* Newest-first page size. Coerced because this arrives as a query string,
|
|
135
|
+
* and defaulted so the bound applies to callers that have not thought about
|
|
136
|
+
* it - which is every caller that predates it.
|
|
137
|
+
*/
|
|
138
|
+
limit: z.coerce
|
|
139
|
+
.number()
|
|
140
|
+
.int()
|
|
141
|
+
.min(1)
|
|
142
|
+
.max(FEEDBACK_LIST_LIMIT_MAX)
|
|
143
|
+
.default(FEEDBACK_LIST_LIMIT_DEFAULT),
|
|
144
|
+
});
|
|
145
|
+
/**
|
|
146
|
+
* Item-scoped routes still have to name their project: membership is per
|
|
147
|
+
* project, and an id in the path is not proof of anything on its own.
|
|
148
|
+
*/
|
|
149
|
+
export const feedbackProjectQuerySchema = z.object({
|
|
150
|
+
organizationId: z.string().trim().min(1, "A project is required."),
|
|
151
|
+
});
|
|
152
|
+
/**
|
|
153
|
+
* Filter for `GET /api/v1/feedback/counts`.
|
|
154
|
+
*
|
|
155
|
+
* `organizationId` is OPTIONAL here and required everywhere else in this file,
|
|
156
|
+
* which is the whole point of the route: its subject is "every project the
|
|
157
|
+
* caller can reach", a fact about the person rather than about one project.
|
|
158
|
+
* Omitting it asks for that whole answer.
|
|
159
|
+
*
|
|
160
|
+
* What it is NOT is a list. A caller may narrow to one project they are a
|
|
161
|
+
* member of - the projects list and a single-project screen both want that -
|
|
162
|
+
* but the set of projects in the answer is always computed from the caller's
|
|
163
|
+
* own memberships per request, never taken from the request. A repeatable
|
|
164
|
+
* `organizationId[]` would look like a filter and read like an access-control
|
|
165
|
+
* decision the client gets to make, and the first time somebody passed a
|
|
166
|
+
* project id they had no membership in, the only thing standing between them
|
|
167
|
+
* and its counts would be a server-side intersection nobody had a reason to
|
|
168
|
+
* write. One id, checked the same way every other feedback read checks one.
|
|
169
|
+
*
|
|
170
|
+
* Still `.min(1)` when present: `?organizationId=` is a client that thinks it
|
|
171
|
+
* named a project, and silently answering with the install-wide total instead
|
|
172
|
+
* would be the wrong number reported with full confidence.
|
|
173
|
+
*/
|
|
174
|
+
export const feedbackCountsQuerySchema = z.object({
|
|
175
|
+
organizationId: z.string().trim().min(1, "A project is required.").optional(),
|
|
176
|
+
});
|
|
177
|
+
/* ── Wire shapes ──────────────────────────────────────────────────────── */
|
|
178
|
+
export const feedbackAuthorSchema = z.object({
|
|
179
|
+
id: z.string(),
|
|
180
|
+
name: z.string(),
|
|
181
|
+
email: z.string(),
|
|
182
|
+
});
|
|
183
|
+
export const replySchema = z.object({
|
|
184
|
+
id: z.string(),
|
|
185
|
+
body: z.string(),
|
|
186
|
+
/**
|
|
187
|
+
* Where to fetch this reply's screenshot, or null. A URL rather than the
|
|
188
|
+
* handle, for the same reason the item's is: a reader needs somewhere to
|
|
189
|
+
* point an `<img>`, and the handle is the store's business.
|
|
190
|
+
*/
|
|
191
|
+
screenshotUrl: z.string().nullable(),
|
|
192
|
+
author: feedbackAuthorSchema,
|
|
193
|
+
/**
|
|
194
|
+
* True when an agent wrote this through the MCP server on the author's
|
|
195
|
+
* behalf. The author is still the person whose token was used - this says how
|
|
196
|
+
* the words arrived, so a thread never renders an agent as a human typing.
|
|
197
|
+
*
|
|
198
|
+
* Additive to the /v1 shape: existing consumers that ignore it keep working.
|
|
199
|
+
*/
|
|
200
|
+
viaAgent: z.boolean(),
|
|
201
|
+
createdAt: z.string(),
|
|
202
|
+
});
|
|
203
|
+
export const pinSchema = z.object({
|
|
204
|
+
selector: z.string(),
|
|
205
|
+
offsetX: z.number(),
|
|
206
|
+
offsetY: z.number(),
|
|
207
|
+
});
|
|
208
|
+
export const feedbackItemSchema = z.object({
|
|
209
|
+
id: z.string(),
|
|
210
|
+
organizationId: z.string(),
|
|
211
|
+
kind: feedbackKindSchema,
|
|
212
|
+
status: feedbackStatusSchema,
|
|
213
|
+
body: z.string(),
|
|
214
|
+
pageUrl: z.string(),
|
|
215
|
+
viewportWidth: z.number(),
|
|
216
|
+
viewportHeight: z.number(),
|
|
217
|
+
userAgent: z.string(),
|
|
218
|
+
gitBranch: z.string().nullable(),
|
|
219
|
+
gitCommit: z.string().nullable(),
|
|
220
|
+
environment: z.string(),
|
|
221
|
+
/** Path the screenshot is served from, or null when none was captured. */
|
|
222
|
+
screenshotUrl: z.string().nullable(),
|
|
223
|
+
author: feedbackAuthorSchema,
|
|
224
|
+
/**
|
|
225
|
+
* Who last moved `status`, and when, and whether an agent did the moving.
|
|
226
|
+
*
|
|
227
|
+
* Null until somebody moves it: an item sitting in OPEN because nobody has
|
|
228
|
+
* touched it is not the same fact as an item somebody deliberately reopened,
|
|
229
|
+
* and defaulting the reporter in here would erase that difference. The three
|
|
230
|
+
* travel together - `statusChangedAt` is null exactly when
|
|
231
|
+
* `statusChangedBy` is - so a consumer can branch on either.
|
|
232
|
+
*
|
|
233
|
+
* Additive to the /v1 shape: a consumer that ignores them keeps working.
|
|
234
|
+
*/
|
|
235
|
+
statusChangedBy: feedbackAuthorSchema.nullable(),
|
|
236
|
+
statusChangedAt: z.string().nullable(),
|
|
237
|
+
/** The `Reply.viaAgent` distinction, applied to a lane move. */
|
|
238
|
+
statusChangedViaAgent: z.boolean(),
|
|
239
|
+
pin: pinSchema.nullable(),
|
|
240
|
+
replies: z.array(replySchema),
|
|
241
|
+
createdAt: z.string(),
|
|
242
|
+
});
|
|
243
|
+
/* ── Cross-project counts ─────────────────────────────────────────────── */
|
|
244
|
+
/**
|
|
245
|
+
* How many items sit in each lane. One key per `FeedbackStatus`, always all
|
|
246
|
+
* three, and zero is an answer rather than an omission - a project whose
|
|
247
|
+
* DONE column is empty is a different fact from a response that did not count
|
|
248
|
+
* it, and a screen printing "0 open" needs to be sure which one it has.
|
|
249
|
+
*
|
|
250
|
+
* The shape is written out rather than derived from `FEEDBACK_STATUSES`
|
|
251
|
+
* because a derivation needs a cast to stay typed, and the `satisfies` below
|
|
252
|
+
* buys the same protection with none: adding a fourth status makes this line
|
|
253
|
+
* fail to compile until the new lane is given a key here, which is exactly
|
|
254
|
+
* when somebody should be thinking about it.
|
|
255
|
+
*/
|
|
256
|
+
const statusCount = z.number().int().nonnegative();
|
|
257
|
+
export const feedbackStatusCountsSchema = z.object({
|
|
258
|
+
OPEN: statusCount,
|
|
259
|
+
IN_REVIEW: statusCount,
|
|
260
|
+
DONE: statusCount,
|
|
261
|
+
});
|
|
262
|
+
/** One project's lane totals. The project is named by id only: every consumer
|
|
263
|
+
* of this route already holds the project list, and re-sending names here
|
|
264
|
+
* would be a second copy of `ProjectDTO` that could disagree with the first. */
|
|
265
|
+
export const feedbackProjectCountsSchema = z.object({
|
|
266
|
+
organizationId: z.string(),
|
|
267
|
+
counts: feedbackStatusCountsSchema,
|
|
268
|
+
});
|
|
269
|
+
/**
|
|
270
|
+
* The answer to `GET /api/v1/feedback/counts`.
|
|
271
|
+
*
|
|
272
|
+
* `projects` carries a row for every project the caller can reach, including
|
|
273
|
+
* the ones with no feedback at all - the breakdown a per-project screen wants.
|
|
274
|
+
* `totals` is the cross-project sum, and it is on the wire rather than left to
|
|
275
|
+
* the client on purpose: the install-wide open figure is the number this route
|
|
276
|
+
* exists to answer, and folding the array to get it would put the definition
|
|
277
|
+
* of "across every project the caller can reach" in the caller instead of in
|
|
278
|
+
* the one place that knows what the caller can reach. The sum is safe in a way
|
|
279
|
+
* `ProjectDTO.memberCount` is not - an item belongs to exactly one project, so
|
|
280
|
+
* nothing is counted twice.
|
|
281
|
+
*/
|
|
282
|
+
export const feedbackCountsSchema = z.object({
|
|
283
|
+
projects: z.array(feedbackProjectCountsSchema),
|
|
284
|
+
totals: feedbackStatusCountsSchema,
|
|
285
|
+
});
|
|
286
|
+
//# sourceMappingURL=feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../../../types/src/feedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./account.js";
|
|
2
|
+
export * from "./apiKey.js";
|
|
3
|
+
export * from "./auth.js";
|
|
4
|
+
export * from "./entity.js";
|
|
5
|
+
export * from "./feedback.js";
|
|
6
|
+
export * from "./invite.js";
|
|
7
|
+
export * from "./mcpToken.js";
|
|
8
|
+
export * from "./organization.js";
|
|
9
|
+
export * from "./project.js";
|
|
10
|
+
export * from "./role.js";
|
|
11
|
+
export * from "./roleDefinition.js";
|
|
12
|
+
export * from "./team.js";
|
|
13
|
+
export * from "./util.js";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../types/src/index.ts"],"names":[],"mappings":"AAGA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Shared Zod schemas, enums, and DTOs used across server and client packages.
|
|
2
|
+
// Single source of truth for runtime validation AND TypeScript types.
|
|
3
|
+
export * from "./account.js";
|
|
4
|
+
export * from "./apiKey.js";
|
|
5
|
+
export * from "./auth.js";
|
|
6
|
+
export * from "./entity.js";
|
|
7
|
+
export * from "./feedback.js";
|
|
8
|
+
export * from "./invite.js";
|
|
9
|
+
export * from "./mcpToken.js";
|
|
10
|
+
export * from "./organization.js";
|
|
11
|
+
export * from "./project.js";
|
|
12
|
+
export * from "./role.js";
|
|
13
|
+
export * from "./roleDefinition.js";
|
|
14
|
+
export * from "./team.js";
|
|
15
|
+
export * from "./util.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../types/src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,sEAAsE;AAEtE,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const inviteStatusSchema: z.ZodEnum<{
|
|
3
|
+
PENDING: "PENDING";
|
|
4
|
+
ACCEPTED: "ACCEPTED";
|
|
5
|
+
REVOKED: "REVOKED";
|
|
6
|
+
EXPIRED: "EXPIRED";
|
|
7
|
+
}>;
|
|
8
|
+
export type InviteStatus = z.infer<typeof inviteStatusSchema>;
|
|
9
|
+
export declare const inviteCreateSchema: z.ZodObject<{
|
|
10
|
+
email: z.ZodString;
|
|
11
|
+
role: z.ZodEnum<{
|
|
12
|
+
OWNER: "OWNER";
|
|
13
|
+
ADMIN: "ADMIN";
|
|
14
|
+
MEMBER: "MEMBER";
|
|
15
|
+
}>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type InviteCreateInput = z.infer<typeof inviteCreateSchema>;
|
|
18
|
+
export declare const inviteSchema: z.ZodObject<{
|
|
19
|
+
id: z.ZodString;
|
|
20
|
+
email: z.ZodString;
|
|
21
|
+
role: z.ZodEnum<{
|
|
22
|
+
OWNER: "OWNER";
|
|
23
|
+
ADMIN: "ADMIN";
|
|
24
|
+
MEMBER: "MEMBER";
|
|
25
|
+
}>;
|
|
26
|
+
status: z.ZodEnum<{
|
|
27
|
+
PENDING: "PENDING";
|
|
28
|
+
ACCEPTED: "ACCEPTED";
|
|
29
|
+
REVOKED: "REVOKED";
|
|
30
|
+
EXPIRED: "EXPIRED";
|
|
31
|
+
}>;
|
|
32
|
+
expiresAt: z.ZodCoercedDate<unknown>;
|
|
33
|
+
createdAt: z.ZodCoercedDate<unknown>;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
export type Invite = z.infer<typeof inviteSchema>;
|
|
36
|
+
export declare const acceptInviteSchema: z.ZodObject<{
|
|
37
|
+
token: z.ZodString;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
export type AcceptInviteInput = z.infer<typeof acceptInviteSchema>;
|
|
40
|
+
/** Invite TTL in days. 14 is generous but not indefinite. */
|
|
41
|
+
export declare const INVITE_TTL_DAYS = 14;
|
|
42
|
+
//# sourceMappingURL=invite.d.ts.map
|