featurebase-node 0.15.1 → 0.15.2

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/client.d.mts +2 -2
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +2 -2
  5. package/client.d.ts.map +1 -1
  6. package/client.js.map +1 -1
  7. package/client.mjs.map +1 -1
  8. package/package.json +1 -1
  9. package/resources/changelogs/changelogs.d.mts +1166 -6
  10. package/resources/changelogs/changelogs.d.mts.map +1 -1
  11. package/resources/changelogs/changelogs.d.ts +1166 -6
  12. package/resources/changelogs/changelogs.d.ts.map +1 -1
  13. package/resources/changelogs/changelogs.js +53 -3
  14. package/resources/changelogs/changelogs.js.map +1 -1
  15. package/resources/changelogs/changelogs.mjs +53 -3
  16. package/resources/changelogs/changelogs.mjs.map +1 -1
  17. package/resources/changelogs/index.d.mts +1 -1
  18. package/resources/changelogs/index.d.mts.map +1 -1
  19. package/resources/changelogs/index.d.ts +1 -1
  20. package/resources/changelogs/index.d.ts.map +1 -1
  21. package/resources/changelogs/index.js.map +1 -1
  22. package/resources/changelogs/index.mjs.map +1 -1
  23. package/resources/feedback/comments.d.mts +4 -2
  24. package/resources/feedback/comments.d.mts.map +1 -1
  25. package/resources/feedback/comments.d.ts +4 -2
  26. package/resources/feedback/comments.d.ts.map +1 -1
  27. package/resources/feedback/custom-fields.d.mts +12 -0
  28. package/resources/feedback/custom-fields.d.mts.map +1 -1
  29. package/resources/feedback/custom-fields.d.ts +12 -0
  30. package/resources/feedback/custom-fields.d.ts.map +1 -1
  31. package/resources/feedback/posts/index.d.mts +1 -0
  32. package/resources/feedback/posts/index.d.mts.map +1 -1
  33. package/resources/feedback/posts/index.d.ts +1 -0
  34. package/resources/feedback/posts/index.d.ts.map +1 -1
  35. package/resources/feedback/posts/index.js +3 -1
  36. package/resources/feedback/posts/index.js.map +1 -1
  37. package/resources/feedback/posts/index.mjs +1 -0
  38. package/resources/feedback/posts/index.mjs.map +1 -1
  39. package/resources/feedback/posts/insights.d.mts +254 -0
  40. package/resources/feedback/posts/insights.d.mts.map +1 -0
  41. package/resources/feedback/posts/insights.d.ts +254 -0
  42. package/resources/feedback/posts/insights.d.ts.map +1 -0
  43. package/resources/feedback/posts/insights.js +269 -0
  44. package/resources/feedback/posts/insights.js.map +1 -0
  45. package/resources/feedback/posts/insights.mjs +265 -0
  46. package/resources/feedback/posts/insights.mjs.map +1 -0
  47. package/resources/feedback/posts/posts.d.mts +647 -20
  48. package/resources/feedback/posts/posts.d.mts.map +1 -1
  49. package/resources/feedback/posts/posts.d.ts +647 -20
  50. package/resources/feedback/posts/posts.d.ts.map +1 -1
  51. package/resources/feedback/posts/posts.js +199 -7
  52. package/resources/feedback/posts/posts.js.map +1 -1
  53. package/resources/feedback/posts/posts.mjs +199 -7
  54. package/resources/feedback/posts/posts.mjs.map +1 -1
  55. package/resources/index.d.mts +1 -1
  56. package/resources/index.d.mts.map +1 -1
  57. package/resources/index.d.ts +1 -1
  58. package/resources/index.d.ts.map +1 -1
  59. package/resources/index.js.map +1 -1
  60. package/resources/index.mjs.map +1 -1
  61. package/resources/support/tickets/tickets.d.mts +9 -5
  62. package/resources/support/tickets/tickets.d.mts.map +1 -1
  63. package/resources/support/tickets/tickets.d.ts +9 -5
  64. package/resources/support/tickets/tickets.d.ts.map +1 -1
  65. package/resources/support/tickets/tickets.js.map +1 -1
  66. package/resources/support/tickets/tickets.mjs.map +1 -1
  67. package/src/client.ts +2 -0
  68. package/src/resources/changelogs/changelogs.ts +2003 -51
  69. package/src/resources/changelogs/index.ts +1 -0
  70. package/src/resources/feedback/comments.ts +4 -2
  71. package/src/resources/feedback/custom-fields.ts +15 -0
  72. package/src/resources/feedback/posts/index.ts +7 -0
  73. package/src/resources/feedback/posts/insights.ts +340 -0
  74. package/src/resources/feedback/posts/posts.ts +764 -20
  75. package/src/resources/index.ts +1 -0
  76. package/src/resources/support/tickets/tickets.ts +9 -5
  77. package/src/version.ts +1 -1
  78. package/version.d.mts +1 -1
  79. package/version.d.ts +1 -1
  80. package/version.js +1 -1
  81. package/version.mjs +1 -1
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Insights = void 0;
5
+ const resource_1 = require("../../../core/resource.js");
6
+ const pagination_1 = require("../../../core/pagination.js");
7
+ const headers_1 = require("../../../internal/headers.js");
8
+ const path_1 = require("../../../internal/utils/path.js");
9
+ /**
10
+ * User-submitted feedback and feature requests. Posts belong to boards and can be upvoted, commented on, and tracked through statuses.
11
+ */
12
+ class Insights extends resource_1.APIResource {
13
+ /**
14
+ * Returns the insights filed under the request `{id}` — the customer quotes kept
15
+ * as evidence for it. Newest first.
16
+ *
17
+ * Posts linked with `attachTo` are **not** listed here: they are posts, not
18
+ * insights, and they stay in `GET /v2/posts`. This endpoint lists exactly the rows
19
+ * that `POST /v2/posts/{insightId}/link-insight` filed under this request.
20
+ *
21
+ * ### Query parameters
22
+ *
23
+ * - `limit` — insights per page, 1–100. **Defaults to 100**, so most requests
24
+ * return their whole evidence set in one call.
25
+ * - `cursor` — opaque cursor from a previous response's `nextCursor`.
26
+ *
27
+ * ### Response format
28
+ *
29
+ * The standard post list envelope:
30
+ *
31
+ * - `object` — always `"list"`
32
+ * - `data` — the insights, each in the same shape as any other post object, with
33
+ * `kind: 'insight'` and `linkedIssueId` set to `{id}`
34
+ * - `nextCursor` — pass it back as `cursor` for the next page; `null` on the last
35
+ * page
36
+ *
37
+ * `pagination` is never returned by this endpoint — it is cursor-paginated only.
38
+ *
39
+ * ### Notes
40
+ *
41
+ * - Pass the **request's** id, not an insight's. An id that is not a request (an
42
+ * insight, or an unknown id in this workspace) is not an error: the list simply
43
+ * comes back empty.
44
+ * - The insights returned are not readable through `GET /v2/posts/{insightId}` —
45
+ * that endpoint serves work items only.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // Automatically fetches more pages as needed.
50
+ * for await (const post of client.feedback.posts.insights.list(
51
+ * '507f1f77bcf86cd799439011',
52
+ * )) {
53
+ * // ...
54
+ * }
55
+ * ```
56
+ */
57
+ list(id, params = {}, options) {
58
+ const { 'Featurebase-Version': featurebaseVersion, ...query } = params ?? {};
59
+ return this._client.getAPIList((0, path_1.path) `/v2/posts/${id}/insights`, (pagination_1.CursorPage), {
60
+ query,
61
+ ...options,
62
+ headers: (0, headers_1.buildHeaders)([
63
+ {
64
+ ...(featurebaseVersion?.toString() != null ?
65
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
66
+ : undefined),
67
+ },
68
+ options?.headers,
69
+ ]),
70
+ });
71
+ }
72
+ /**
73
+ * Promotes the insight `{id}` into a request of its own — the way back from
74
+ * `link-insight`.
75
+ *
76
+ * `kind` becomes `issue`, any link to another request is cleared (that request's
77
+ * `linkedInsightCount` is recounted), and the row is a post again:
78
+ * `GET /v2/posts/{id}` answers it, and `GET /v2/posts` lists it.
79
+ *
80
+ * The promoted request is given the workspace's default status if it had none, is
81
+ * filed on the internal board (its previous board is kept as the request's source
82
+ * category), and is created **hidden from the portal** — publish it with
83
+ * `PATCH /v2/posts/{id}` when you want customers to see it. It then announces
84
+ * itself like a freshly created request: the `post.created` webhook fires and the
85
+ * workspace's tracker integrations receive it, subject to the same rules as any
86
+ * other creation. Featurebase also looks for other existing insights that support
87
+ * the new request, in the background.
88
+ *
89
+ * Calling this on a post that is already a request is a no-op and returns it
90
+ * unchanged.
91
+ *
92
+ * ### Request
93
+ *
94
+ * No body. The insight is named by the path.
95
+ *
96
+ * ### Response
97
+ *
98
+ * The resulting request, in the standard post format.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const post =
103
+ * await client.feedback.posts.insights.convertToPost(
104
+ * '507f1f77bcf86cd799439011',
105
+ * );
106
+ * ```
107
+ */
108
+ convertToPost(id, params = {}, options) {
109
+ const { 'Featurebase-Version': featurebaseVersion } = params ?? {};
110
+ return this._client.post((0, path_1.path) `/v2/posts/${id}/convert-to-issue`, {
111
+ ...options,
112
+ headers: (0, headers_1.buildHeaders)([
113
+ {
114
+ ...(featurebaseVersion?.toString() != null ?
115
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
116
+ : undefined),
117
+ },
118
+ options?.headers,
119
+ ]),
120
+ });
121
+ }
122
+ /**
123
+ * An **insight** is a customer's own words kept as evidence under a request — a
124
+ * quote, not a request of its own, and never returned by `GET /v2/posts`.
125
+ *
126
+ * This endpoint turns the post `{id}` into an insight under the request `issueId`.
127
+ * Use it for the sentence a customer actually said; use `attachTo` on
128
+ * `POST /v2/posts` when the thing you are filing is a request in its own right and
129
+ * should stay one.
130
+ *
131
+ * ### What changes
132
+ *
133
+ * - The post becomes an insight: `kind` is `insight` and `linkedIssueId` is the
134
+ * request.
135
+ * - **It leaves the posts resource.** `GET /v2/posts/{id}` answers `404` from then
136
+ * on, and it no longer appears in `GET /v2/posts`. Read it back through
137
+ * `GET /v2/posts/{issueId}/insights`, which is where it now lives.
138
+ * - Its author counts as a supporter of the request: the insight's upvoters are
139
+ * rolled onto the request (deduped by user, so a customer who had already voted
140
+ * is not counted twice) and the insight's author is subscribed to the request's
141
+ * updates. The request's `upvotes` goes up accordingly.
142
+ * - The request's `linkedInsightCount` is recounted from the live set of insights
143
+ * pointing at it.
144
+ *
145
+ * Linking again to the same request is a no-op and returns the insight unchanged.
146
+ *
147
+ * An insight that is already filed under a DIFFERENT request is MOVED — but only
148
+ * if nobody has confirmed that first link by hand. The old link is dropped first,
149
+ * and the old request is remembered as "not a match" so automatic matching never
150
+ * puts it back there. An insight whose link was already confirmed by a person
151
+ * (every link made through this endpoint counts as confirmed) is refused with
152
+ * `400 Insight is already linked to another issue. Detach it first.` — call
153
+ * `POST /v2/posts/{id}/unlink-insight` first, then link it where you want it.
154
+ *
155
+ * ### Which targets are refused
156
+ *
157
+ * - `404` — no post with `{id}` in this workspace, or one the API key cannot see
158
+ * (`Insight not found.`); no request with `issueId`, or one the API key cannot
159
+ * see (`Issue not found.`).
160
+ * - `400` — `issueId` equals `{id}` (a post cannot be linked to itself); the
161
+ * target is not a request (it is itself an insight, or a record — convert or
162
+ * restore it first); the target is a processed submission (`atomizedAt` — link
163
+ * to the requests that came out of it); the post being linked is a record (link
164
+ * the record's extracted insights instead); the post is already filed under
165
+ * another request by hand (unlink it first).
166
+ * - `400 invalid_id` — `{id}` or `issueId` is not a valid object id.
167
+ *
168
+ * A merged, held-for-moderation, spam-held or closed target is **not** refused
169
+ * here: those guards apply to automatic (AI) attachment only, and a person linking
170
+ * by hand is trusted to mean it.
171
+ *
172
+ * ### Response
173
+ *
174
+ * The updated insight, in the standard post format (`kind: 'insight'`,
175
+ * `linkedIssueId` set). The request it was linked to is not returned — fetch it
176
+ * with `GET /v2/posts/{issueId}` if you need its new `upvotes` and
177
+ * `linkedInsightCount`.
178
+ *
179
+ * ### Body
180
+ *
181
+ * - `issueId` — the request to file this post under. Required.
182
+ * - `linkSource` — deprecated and ignored; a link made through the API is always a
183
+ * manual link.
184
+ *
185
+ * ### Errors
186
+ *
187
+ * Failures raised by the insight service (404 / 400 / 409) are returned as
188
+ * `{ "code": <status>, "message": "..." }` rather than in the Stripe-style
189
+ * envelope the rest of this resource uses. The status code is the contract; do not
190
+ * parse the body shape.
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * const post = await client.feedback.posts.insights.link(
195
+ * '507f1f77bcf86cd799439011',
196
+ * { issueId: '507f1f77bcf86cd799439011' },
197
+ * );
198
+ * ```
199
+ */
200
+ link(id, params, options) {
201
+ const { 'Featurebase-Version': featurebaseVersion, ...body } = params;
202
+ return this._client.post((0, path_1.path) `/v2/posts/${id}/link-insight`, {
203
+ body,
204
+ ...options,
205
+ headers: (0, headers_1.buildHeaders)([
206
+ {
207
+ ...(featurebaseVersion?.toString() != null ?
208
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
209
+ : undefined),
210
+ },
211
+ options?.headers,
212
+ ]),
213
+ });
214
+ }
215
+ /**
216
+ * Detaches the insight `{id}` from the request it was filed under.
217
+ *
218
+ * **The row stays an insight** — the customer's words do not disappear, they just
219
+ * return to the unlinked pool. `linkedIssueId` becomes `null`, and
220
+ * `GET /v2/posts/{id}` still answers `404`: an unlinked insight is still not a
221
+ * post. To get a post back, call `POST /v2/posts/{id}/convert-to-issue`.
222
+ *
223
+ * ### What does NOT change
224
+ *
225
+ * The votes this insight rolled onto the request are **not** taken back, and the
226
+ * author stays subscribed to it. They are real demand that was expressed, and the
227
+ * roll-up was deduplicated against votes the customer may have cast independently
228
+ * — unwinding it would remove votes it never created. The request's `upvotes`
229
+ * therefore stays where the link left it. Its `linkedInsightCount` IS recounted
230
+ * and goes down.
231
+ *
232
+ * The request that was just unlinked is remembered as "not a match" for this
233
+ * insight, so automatic matching never files it there again.
234
+ *
235
+ * Calling this on a post that is not an insight, or on an insight that is already
236
+ * unlinked, is a no-op and returns the row unchanged.
237
+ *
238
+ * ### Request
239
+ *
240
+ * No body. The insight is named by the path.
241
+ *
242
+ * ### Response
243
+ *
244
+ * The updated insight, in the standard post format.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * const post = await client.feedback.posts.insights.unlink(
249
+ * '507f1f77bcf86cd799439011',
250
+ * );
251
+ * ```
252
+ */
253
+ unlink(id, params = {}, options) {
254
+ const { 'Featurebase-Version': featurebaseVersion } = params ?? {};
255
+ return this._client.post((0, path_1.path) `/v2/posts/${id}/unlink-insight`, {
256
+ ...options,
257
+ headers: (0, headers_1.buildHeaders)([
258
+ {
259
+ ...(featurebaseVersion?.toString() != null ?
260
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
261
+ : undefined),
262
+ },
263
+ options?.headers,
264
+ ]),
265
+ });
266
+ }
267
+ }
268
+ exports.Insights = Insights;
269
+ //# sourceMappingURL=insights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../src/resources/feedback/posts/insights.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,265 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+ import { APIResource } from "../../../core/resource.mjs";
3
+ import { CursorPage } from "../../../core/pagination.mjs";
4
+ import { buildHeaders } from "../../../internal/headers.mjs";
5
+ import { path } from "../../../internal/utils/path.mjs";
6
+ /**
7
+ * User-submitted feedback and feature requests. Posts belong to boards and can be upvoted, commented on, and tracked through statuses.
8
+ */
9
+ export class Insights extends APIResource {
10
+ /**
11
+ * Returns the insights filed under the request `{id}` — the customer quotes kept
12
+ * as evidence for it. Newest first.
13
+ *
14
+ * Posts linked with `attachTo` are **not** listed here: they are posts, not
15
+ * insights, and they stay in `GET /v2/posts`. This endpoint lists exactly the rows
16
+ * that `POST /v2/posts/{insightId}/link-insight` filed under this request.
17
+ *
18
+ * ### Query parameters
19
+ *
20
+ * - `limit` — insights per page, 1–100. **Defaults to 100**, so most requests
21
+ * return their whole evidence set in one call.
22
+ * - `cursor` — opaque cursor from a previous response's `nextCursor`.
23
+ *
24
+ * ### Response format
25
+ *
26
+ * The standard post list envelope:
27
+ *
28
+ * - `object` — always `"list"`
29
+ * - `data` — the insights, each in the same shape as any other post object, with
30
+ * `kind: 'insight'` and `linkedIssueId` set to `{id}`
31
+ * - `nextCursor` — pass it back as `cursor` for the next page; `null` on the last
32
+ * page
33
+ *
34
+ * `pagination` is never returned by this endpoint — it is cursor-paginated only.
35
+ *
36
+ * ### Notes
37
+ *
38
+ * - Pass the **request's** id, not an insight's. An id that is not a request (an
39
+ * insight, or an unknown id in this workspace) is not an error: the list simply
40
+ * comes back empty.
41
+ * - The insights returned are not readable through `GET /v2/posts/{insightId}` —
42
+ * that endpoint serves work items only.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * // Automatically fetches more pages as needed.
47
+ * for await (const post of client.feedback.posts.insights.list(
48
+ * '507f1f77bcf86cd799439011',
49
+ * )) {
50
+ * // ...
51
+ * }
52
+ * ```
53
+ */
54
+ list(id, params = {}, options) {
55
+ const { 'Featurebase-Version': featurebaseVersion, ...query } = params ?? {};
56
+ return this._client.getAPIList(path `/v2/posts/${id}/insights`, (CursorPage), {
57
+ query,
58
+ ...options,
59
+ headers: buildHeaders([
60
+ {
61
+ ...(featurebaseVersion?.toString() != null ?
62
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
63
+ : undefined),
64
+ },
65
+ options?.headers,
66
+ ]),
67
+ });
68
+ }
69
+ /**
70
+ * Promotes the insight `{id}` into a request of its own — the way back from
71
+ * `link-insight`.
72
+ *
73
+ * `kind` becomes `issue`, any link to another request is cleared (that request's
74
+ * `linkedInsightCount` is recounted), and the row is a post again:
75
+ * `GET /v2/posts/{id}` answers it, and `GET /v2/posts` lists it.
76
+ *
77
+ * The promoted request is given the workspace's default status if it had none, is
78
+ * filed on the internal board (its previous board is kept as the request's source
79
+ * category), and is created **hidden from the portal** — publish it with
80
+ * `PATCH /v2/posts/{id}` when you want customers to see it. It then announces
81
+ * itself like a freshly created request: the `post.created` webhook fires and the
82
+ * workspace's tracker integrations receive it, subject to the same rules as any
83
+ * other creation. Featurebase also looks for other existing insights that support
84
+ * the new request, in the background.
85
+ *
86
+ * Calling this on a post that is already a request is a no-op and returns it
87
+ * unchanged.
88
+ *
89
+ * ### Request
90
+ *
91
+ * No body. The insight is named by the path.
92
+ *
93
+ * ### Response
94
+ *
95
+ * The resulting request, in the standard post format.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * const post =
100
+ * await client.feedback.posts.insights.convertToPost(
101
+ * '507f1f77bcf86cd799439011',
102
+ * );
103
+ * ```
104
+ */
105
+ convertToPost(id, params = {}, options) {
106
+ const { 'Featurebase-Version': featurebaseVersion } = params ?? {};
107
+ return this._client.post(path `/v2/posts/${id}/convert-to-issue`, {
108
+ ...options,
109
+ headers: buildHeaders([
110
+ {
111
+ ...(featurebaseVersion?.toString() != null ?
112
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
113
+ : undefined),
114
+ },
115
+ options?.headers,
116
+ ]),
117
+ });
118
+ }
119
+ /**
120
+ * An **insight** is a customer's own words kept as evidence under a request — a
121
+ * quote, not a request of its own, and never returned by `GET /v2/posts`.
122
+ *
123
+ * This endpoint turns the post `{id}` into an insight under the request `issueId`.
124
+ * Use it for the sentence a customer actually said; use `attachTo` on
125
+ * `POST /v2/posts` when the thing you are filing is a request in its own right and
126
+ * should stay one.
127
+ *
128
+ * ### What changes
129
+ *
130
+ * - The post becomes an insight: `kind` is `insight` and `linkedIssueId` is the
131
+ * request.
132
+ * - **It leaves the posts resource.** `GET /v2/posts/{id}` answers `404` from then
133
+ * on, and it no longer appears in `GET /v2/posts`. Read it back through
134
+ * `GET /v2/posts/{issueId}/insights`, which is where it now lives.
135
+ * - Its author counts as a supporter of the request: the insight's upvoters are
136
+ * rolled onto the request (deduped by user, so a customer who had already voted
137
+ * is not counted twice) and the insight's author is subscribed to the request's
138
+ * updates. The request's `upvotes` goes up accordingly.
139
+ * - The request's `linkedInsightCount` is recounted from the live set of insights
140
+ * pointing at it.
141
+ *
142
+ * Linking again to the same request is a no-op and returns the insight unchanged.
143
+ *
144
+ * An insight that is already filed under a DIFFERENT request is MOVED — but only
145
+ * if nobody has confirmed that first link by hand. The old link is dropped first,
146
+ * and the old request is remembered as "not a match" so automatic matching never
147
+ * puts it back there. An insight whose link was already confirmed by a person
148
+ * (every link made through this endpoint counts as confirmed) is refused with
149
+ * `400 Insight is already linked to another issue. Detach it first.` — call
150
+ * `POST /v2/posts/{id}/unlink-insight` first, then link it where you want it.
151
+ *
152
+ * ### Which targets are refused
153
+ *
154
+ * - `404` — no post with `{id}` in this workspace, or one the API key cannot see
155
+ * (`Insight not found.`); no request with `issueId`, or one the API key cannot
156
+ * see (`Issue not found.`).
157
+ * - `400` — `issueId` equals `{id}` (a post cannot be linked to itself); the
158
+ * target is not a request (it is itself an insight, or a record — convert or
159
+ * restore it first); the target is a processed submission (`atomizedAt` — link
160
+ * to the requests that came out of it); the post being linked is a record (link
161
+ * the record's extracted insights instead); the post is already filed under
162
+ * another request by hand (unlink it first).
163
+ * - `400 invalid_id` — `{id}` or `issueId` is not a valid object id.
164
+ *
165
+ * A merged, held-for-moderation, spam-held or closed target is **not** refused
166
+ * here: those guards apply to automatic (AI) attachment only, and a person linking
167
+ * by hand is trusted to mean it.
168
+ *
169
+ * ### Response
170
+ *
171
+ * The updated insight, in the standard post format (`kind: 'insight'`,
172
+ * `linkedIssueId` set). The request it was linked to is not returned — fetch it
173
+ * with `GET /v2/posts/{issueId}` if you need its new `upvotes` and
174
+ * `linkedInsightCount`.
175
+ *
176
+ * ### Body
177
+ *
178
+ * - `issueId` — the request to file this post under. Required.
179
+ * - `linkSource` — deprecated and ignored; a link made through the API is always a
180
+ * manual link.
181
+ *
182
+ * ### Errors
183
+ *
184
+ * Failures raised by the insight service (404 / 400 / 409) are returned as
185
+ * `{ "code": <status>, "message": "..." }` rather than in the Stripe-style
186
+ * envelope the rest of this resource uses. The status code is the contract; do not
187
+ * parse the body shape.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const post = await client.feedback.posts.insights.link(
192
+ * '507f1f77bcf86cd799439011',
193
+ * { issueId: '507f1f77bcf86cd799439011' },
194
+ * );
195
+ * ```
196
+ */
197
+ link(id, params, options) {
198
+ const { 'Featurebase-Version': featurebaseVersion, ...body } = params;
199
+ return this._client.post(path `/v2/posts/${id}/link-insight`, {
200
+ body,
201
+ ...options,
202
+ headers: buildHeaders([
203
+ {
204
+ ...(featurebaseVersion?.toString() != null ?
205
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
206
+ : undefined),
207
+ },
208
+ options?.headers,
209
+ ]),
210
+ });
211
+ }
212
+ /**
213
+ * Detaches the insight `{id}` from the request it was filed under.
214
+ *
215
+ * **The row stays an insight** — the customer's words do not disappear, they just
216
+ * return to the unlinked pool. `linkedIssueId` becomes `null`, and
217
+ * `GET /v2/posts/{id}` still answers `404`: an unlinked insight is still not a
218
+ * post. To get a post back, call `POST /v2/posts/{id}/convert-to-issue`.
219
+ *
220
+ * ### What does NOT change
221
+ *
222
+ * The votes this insight rolled onto the request are **not** taken back, and the
223
+ * author stays subscribed to it. They are real demand that was expressed, and the
224
+ * roll-up was deduplicated against votes the customer may have cast independently
225
+ * — unwinding it would remove votes it never created. The request's `upvotes`
226
+ * therefore stays where the link left it. Its `linkedInsightCount` IS recounted
227
+ * and goes down.
228
+ *
229
+ * The request that was just unlinked is remembered as "not a match" for this
230
+ * insight, so automatic matching never files it there again.
231
+ *
232
+ * Calling this on a post that is not an insight, or on an insight that is already
233
+ * unlinked, is a no-op and returns the row unchanged.
234
+ *
235
+ * ### Request
236
+ *
237
+ * No body. The insight is named by the path.
238
+ *
239
+ * ### Response
240
+ *
241
+ * The updated insight, in the standard post format.
242
+ *
243
+ * @example
244
+ * ```ts
245
+ * const post = await client.feedback.posts.insights.unlink(
246
+ * '507f1f77bcf86cd799439011',
247
+ * );
248
+ * ```
249
+ */
250
+ unlink(id, params = {}, options) {
251
+ const { 'Featurebase-Version': featurebaseVersion } = params ?? {};
252
+ return this._client.post(path `/v2/posts/${id}/unlink-insight`, {
253
+ ...options,
254
+ headers: buildHeaders([
255
+ {
256
+ ...(featurebaseVersion?.toString() != null ?
257
+ { 'Featurebase-Version': featurebaseVersion?.toString() }
258
+ : undefined),
259
+ },
260
+ options?.headers,
261
+ ]),
262
+ });
263
+ }
264
+ }
265
+ //# sourceMappingURL=insights.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.mjs","sourceRoot":"","sources":["../../../src/resources/feedback/posts/insights.ts"],"names":[],"mappings":"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"}