@kyrofeedback/sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +242 -2
- package/dist/client.d.ts +21 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +210 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KyroFeedback
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,243 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @kyrofeedback/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A TypeScript-first, server-side client for the KyroFeedback v1 REST API. It uses the existing API and does not connect to a database or depend on Next.js.
|
|
4
|
+
|
|
5
|
+
The API currently supports feedback listing, retrieval, and creation; comment listing and creation; and vote state, vote, and unvote. Feedback editing/deletion and comment deletion are not available through v1 and are intentionally not exposed here.
|
|
6
|
+
|
|
7
|
+
## Requirements and installation
|
|
8
|
+
|
|
9
|
+
- Node.js 20 or newer (native `fetch` and `AbortController`)
|
|
10
|
+
- A KyroFeedback API key for one project
|
|
11
|
+
|
|
12
|
+
When the package is published, install it with:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install @kyrofeedback/sdk
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This repository does not publish automatically. Until release, build the package and install its packed tarball from a local path.
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
cd packages/sdk
|
|
22
|
+
npm install
|
|
23
|
+
npm test
|
|
24
|
+
npm pack
|
|
25
|
+
# From the consuming application:
|
|
26
|
+
npm install /path/to/kyrofeedback-sdk-0.1.0.tgz
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Keep keys on the server
|
|
30
|
+
|
|
31
|
+
The SDK can use either `sk_live_` or `pk_live_` keys because both are accepted by these API endpoints. Current keys have the prefix followed by 43 base64url characters. For a server integration, use a secret `sk_live_` key and keep it in a server-only environment variable. In Next.js, use `KYROFEEDBACK_API_KEY`, never `NEXT_PUBLIC_KYROFEEDBACK_API_KEY`. The client rejects initialization in a browser runtime; do not import it into browser components or send a secret key to a browser. The browser widget continues to use its publishable key and `widget.js`.
|
|
32
|
+
|
|
33
|
+
Keys are project-scoped. The API enforces project settings, project isolation, and a current limit of 120 requests per minute per key. Feedback, comment, and vote creation can return `403` when the corresponding anonymous activity setting is disabled. The SDK does not bypass those checks.
|
|
34
|
+
|
|
35
|
+
## Initialize
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { KyroFeedback } from "@kyrofeedback/sdk";
|
|
39
|
+
|
|
40
|
+
const kyro = new KyroFeedback({
|
|
41
|
+
apiKey: process.env.KYROFEEDBACK_API_KEY!,
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The default host is `https://feedback.kyrocms.com`; requests go to its `/api/v1` API. For a local or self-hosted instance, set `baseUrl` to its origin (or an origin with a path prefix):
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const kyro = new KyroFeedback({
|
|
49
|
+
apiKey: process.env.KYROFEEDBACK_API_KEY!,
|
|
50
|
+
baseUrl: "http://localhost:3000",
|
|
51
|
+
timeout: 5_000,
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`baseUrl` must be an absolute HTTP or HTTPS URL without credentials, query, or fragment. Plain HTTP is accepted only for localhost and loopback development URLs; remote hosts must use HTTPS. A trailing `/api/v1` is normalized. The default timeout is 10 seconds. Pass a compatible Fetch API implementation with `fetch` when needed.
|
|
56
|
+
|
|
57
|
+
## Feedback
|
|
58
|
+
|
|
59
|
+
### List and paginate
|
|
60
|
+
|
|
61
|
+
The list endpoint returns newest feedback first and supports `limit` (API range 1–50, default 20), `cursor`, `q`, `status`, and `type`. The page object preserves `meta.nextCursor`; request subsequent pages only when needed.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const page = await kyro.feedback.list({
|
|
65
|
+
limit: 20,
|
|
66
|
+
status: "OPEN",
|
|
67
|
+
type: "FEATURE",
|
|
68
|
+
q: "dark mode",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
for (const item of page.data) {
|
|
72
|
+
console.log(item.title, item.votesCount, item.commentsCount);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (page.meta.nextCursor) {
|
|
76
|
+
const nextPage = await kyro.feedback.list({
|
|
77
|
+
limit: 20,
|
|
78
|
+
cursor: page.meta.nextCursor,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Supported status values are `OPEN`, `PLANNED`, `IN_PROGRESS`, `COMPLETED`, and `CLOSED`. Supported type values are `FEATURE`, `BUG`, `QUESTION`, and `INTEGRATION`.
|
|
84
|
+
|
|
85
|
+
### Get and create
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
const item = await kyro.feedback.get("feedback-id");
|
|
89
|
+
|
|
90
|
+
const created = await kyro.feedback.create({
|
|
91
|
+
title: "Add dark mode",
|
|
92
|
+
description: "A dark theme would make the dashboard easier to use at night.",
|
|
93
|
+
type: "FEATURE",
|
|
94
|
+
authorName: "Alex", // optional; 100 characters maximum in the API
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The API requires a title of 3–200 characters and a description of 3–10,000 characters. Feedback creation is anonymous and requires the project’s anonymous feedback setting to be enabled. The response fields are `id`, `title`, `description`, `type`, `status`, `votesCount`, `commentsCount`, `createdAt`, and `updatedAt`.
|
|
99
|
+
|
|
100
|
+
The v1 API does not support feedback updates or deletion. Those methods are not included.
|
|
101
|
+
|
|
102
|
+
## Comments and replies
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
const comments = await kyro.comments.list("feedback-id");
|
|
106
|
+
|
|
107
|
+
const rootComment = await kyro.comments.create("feedback-id", {
|
|
108
|
+
content: "This would help our team too.",
|
|
109
|
+
authorName: "Alex",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await kyro.comments.create("feedback-id", {
|
|
113
|
+
content: "Thanks for the detail!",
|
|
114
|
+
parentId: rootComment.id,
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Comments are returned as a flat, creation-ordered array. Group `parentId: null` comments as roots and attach replies to their parent ID. The API accepts comment content up to 5,000 characters, requires anonymous comments to be enabled, and validates that a reply’s parent belongs to the same feedback item. Comment deletion is not supported by the v1 API.
|
|
119
|
+
|
|
120
|
+
## Votes and visitor identity
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const state = await kyro.votes.get("feedback-id");
|
|
124
|
+
const updated = state.voted
|
|
125
|
+
? await kyro.votes.unvote("feedback-id")
|
|
126
|
+
: await kyro.votes.vote("feedback-id");
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The API identifies votes with its `kyro_anonymous_id` cookie; it does not accept a user ID. The SDK never stores cookies between requests because a long-lived server client may be shared by many visitors. To preserve a particular visitor’s identity in a server route, forward that visitor’s Kyro cookie on each request:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const cookie = request.headers.get("cookie") ?? undefined;
|
|
133
|
+
const voteState = await kyro.votes.get("feedback-id", { cookie });
|
|
134
|
+
const responseHeaders = new Headers();
|
|
135
|
+
const updated = await kyro.votes.vote("feedback-id", {
|
|
136
|
+
cookie,
|
|
137
|
+
onResponse(response) {
|
|
138
|
+
// In a server route, relay Set-Cookie to that same visitor when present.
|
|
139
|
+
const setCookie = response.headers.get("set-cookie");
|
|
140
|
+
if (setCookie) responseHeaders.append("set-cookie", setCookie);
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
return Response.json(updated, { headers: responseHeaders });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`RequestOptions` also accepts an `AbortSignal`. Vote state and counts come from the API response; the SDK does not synthesize them.
|
|
147
|
+
|
|
148
|
+
## Request controls
|
|
149
|
+
|
|
150
|
+
All resource methods accept an optional final `RequestOptions` argument with `signal`, `cookie`, and `onResponse`. Cookies are opt-in and never persisted. Mutations are not automatically retried.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
const controller = new AbortController();
|
|
154
|
+
const result = await kyro.feedback.list({ limit: 10 }, { signal: controller.signal });
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Errors
|
|
158
|
+
|
|
159
|
+
All API, transport, and malformed-response failures are `KyroFeedbackError` instances. `status` is populated for HTTP responses, and `kind` categorizes failures as `authentication`, `permission`, `validation`, `not_found`, `rate_limit`, `server`, `http`, `network`, `timeout`, or `invalid_response`.
|
|
160
|
+
|
|
161
|
+
The API currently returns errors as `{ error: { message, status } }`; it does not return a stable error code or request ID, so the SDK does not fabricate either.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { KyroFeedbackError } from "@kyrofeedback/sdk";
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
await kyro.feedback.create({ title: "Add dark mode", description: "Please add a dark theme.", type: "FEATURE" });
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (error instanceof KyroFeedbackError) {
|
|
170
|
+
if (error.kind === "permission") console.error("Check anonymous feedback settings.");
|
|
171
|
+
else console.error(error.kind, error.status, error.message);
|
|
172
|
+
}
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Next.js server-side usage
|
|
178
|
+
|
|
179
|
+
Keep SDK use in a route handler or server component. A client component should call your route, not import the SDK or receive the secret key.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
// app/api/feedback/route.ts
|
|
183
|
+
import { KyroFeedback, KyroFeedbackError } from "@kyrofeedback/sdk";
|
|
184
|
+
|
|
185
|
+
const kyro = new KyroFeedback({ apiKey: process.env.KYROFEEDBACK_API_KEY! });
|
|
186
|
+
|
|
187
|
+
export async function GET() {
|
|
188
|
+
try {
|
|
189
|
+
const page = await kyro.feedback.list({ limit: 20 });
|
|
190
|
+
return Response.json(page);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (error instanceof KyroFeedbackError) {
|
|
193
|
+
return Response.json({ error: error.message }, { status: error.status ?? 502 });
|
|
194
|
+
}
|
|
195
|
+
return Response.json({ error: "Unexpected error" }, { status: 500 });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
An end-to-end example is in [`examples/nextjs`](./examples/nextjs).
|
|
201
|
+
|
|
202
|
+
## Node.js usage
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
import { KyroFeedback } from "@kyrofeedback/sdk";
|
|
206
|
+
|
|
207
|
+
const kyro = new KyroFeedback({ apiKey: process.env.KYROFEEDBACK_API_KEY });
|
|
208
|
+
const page = await kyro.feedback.list({ limit: 10, type: "BUG" });
|
|
209
|
+
console.log(page.data);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Development, tests, and package verification
|
|
213
|
+
|
|
214
|
+
From this directory:
|
|
215
|
+
|
|
216
|
+
```sh
|
|
217
|
+
npm install
|
|
218
|
+
npm run typecheck
|
|
219
|
+
npm test
|
|
220
|
+
npm run pack:check
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`npm test` compiles the package and runs mocked-fetch tests with Node’s built-in test runner. It does not contact a live service.
|
|
224
|
+
|
|
225
|
+
### Live integration checks
|
|
226
|
+
|
|
227
|
+
`npm run test:integration` runs an opt-in suite against a dedicated local or test deployment. It creates feedback and comments and changes a vote; it cannot delete those records. Use two disposable projects with separate keys, enable anonymous feedback, comments, and voting on the first project, and use a third disposable key that you have revoked if you want the revoked-key case. Never use a production project, key, or user data.
|
|
228
|
+
|
|
229
|
+
Set these server-side variables without printing or committing them:
|
|
230
|
+
|
|
231
|
+
```sh
|
|
232
|
+
export KYROFEEDBACK_BASE_URL=http://localhost:3000
|
|
233
|
+
export KYROFEEDBACK_TEST_API_KEY=sk_live_REPLACE_WITH_FULL_TEST_PROJECT_ONE_KEY
|
|
234
|
+
export KYROFEEDBACK_SECOND_PROJECT_API_KEY=sk_live_REPLACE_WITH_FULL_TEST_PROJECT_TWO_KEY
|
|
235
|
+
export KYROFEEDBACK_REVOKED_API_KEY=sk_live_REPLACE_WITH_FULL_REVOKED_TEST_KEY
|
|
236
|
+
npm run test:integration
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Replace each placeholder with the complete raw disposable key copied from the dashboard; these sample values are intentionally not valid keys.
|
|
240
|
+
|
|
241
|
+
For a remote dedicated test host, use HTTPS and explicitly set `KYROFEEDBACK_ALLOW_REMOTE_TEST_INSTANCE=true` after confirming the deployment is isolated. The script refuses `feedback.kyrocms.com` and refuses remote hosts without that opt-in. It checks authentication, list/create/get, cursor pagination, comments/replies, vote/unvote, a second-project 404, invalid credentials, and (when provided) revoked credentials. The test records are marked with a random ID and remain in the disposable project because v1 has no delete methods.
|
|
242
|
+
|
|
243
|
+
Build output and declaration files are generated under `dist/`. To publish after review, update the version, run the checks above, inspect `npm pack --dry-run`, then publish explicitly from this directory with `npm publish --access public`. No package has been published by this repository change.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Comment, CreateCommentInput, CreateFeedbackInput, Feedback, FeedbackPage, KyroFeedbackConfig, ListFeedbackOptions, RequestOptions, VoteState } from "./types.js";
|
|
2
|
+
/** Server-side client for the supported KyroFeedback v1 REST API. */
|
|
3
|
+
export declare class KyroFeedback {
|
|
4
|
+
private readonly http;
|
|
5
|
+
readonly feedback: {
|
|
6
|
+
list: (options?: ListFeedbackOptions, request?: RequestOptions) => Promise<FeedbackPage>;
|
|
7
|
+
get: (id: string, request?: RequestOptions) => Promise<Feedback>;
|
|
8
|
+
create: (input: CreateFeedbackInput, request?: RequestOptions) => Promise<Feedback>;
|
|
9
|
+
};
|
|
10
|
+
readonly comments: {
|
|
11
|
+
list: (feedbackId: string, request?: RequestOptions) => Promise<Comment[]>;
|
|
12
|
+
create: (feedbackId: string, input: CreateCommentInput, request?: RequestOptions) => Promise<Comment>;
|
|
13
|
+
};
|
|
14
|
+
readonly votes: {
|
|
15
|
+
get: (feedbackId: string, request?: RequestOptions) => Promise<VoteState>;
|
|
16
|
+
vote: (feedbackId: string, request?: RequestOptions) => Promise<VoteState>;
|
|
17
|
+
unvote: (feedbackId: string, request?: RequestOptions) => Promise<VoteState>;
|
|
18
|
+
};
|
|
19
|
+
constructor(config: KyroFeedbackConfig);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,kBAAkB,EAClB,mBAAmB,EACnB,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,SAAS,EACV,MAAM,YAAY,CAAC;AA4LpB,qEAAqE;AACrE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAElC,QAAQ,CAAC,QAAQ,EAAE;QACjB,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACzF,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;KACrF,CAAC;IAEF,QAAQ,CAAC,QAAQ,EAAE;QACjB,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KACvG,CAAC;IAEF,QAAQ,CAAC,KAAK,EAAE;QACd,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QAC3E,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;KAC9E,CAAC;gBAEU,MAAM,EAAE,kBAAkB;CAiBvC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { KyroFeedbackError } from "./errors.js";
|
|
2
|
+
const DEFAULT_BASE_URL = "https://feedback.kyrocms.com";
|
|
3
|
+
const DEFAULT_TIMEOUT = 10_000;
|
|
4
|
+
const API_PATH = "/api/v1";
|
|
5
|
+
function normalizeBaseUrl(value) {
|
|
6
|
+
const candidate = value ?? DEFAULT_BASE_URL;
|
|
7
|
+
let url;
|
|
8
|
+
try {
|
|
9
|
+
url = new URL(candidate);
|
|
10
|
+
}
|
|
11
|
+
catch (cause) {
|
|
12
|
+
throw new TypeError("baseUrl must be an absolute HTTP or HTTPS URL", { cause });
|
|
13
|
+
}
|
|
14
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
15
|
+
throw new TypeError("baseUrl must use HTTP or HTTPS");
|
|
16
|
+
}
|
|
17
|
+
const hostname = url.hostname.toLowerCase();
|
|
18
|
+
const isLoopback = hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "[::1]"
|
|
19
|
+
|| /^127(?:\.\d{1,3}){3}$/.test(hostname);
|
|
20
|
+
if (url.protocol === "http:" && !isLoopback) {
|
|
21
|
+
throw new TypeError("baseUrl must use HTTPS unless it targets localhost or a loopback IP");
|
|
22
|
+
}
|
|
23
|
+
if (url.username || url.password || url.search || url.hash) {
|
|
24
|
+
throw new TypeError("baseUrl must not contain credentials, a query, or a fragment");
|
|
25
|
+
}
|
|
26
|
+
const path = url.pathname.replace(/\/+$/, "");
|
|
27
|
+
if (path.endsWith(API_PATH)) {
|
|
28
|
+
url.pathname = path.slice(0, -API_PATH.length) || "/";
|
|
29
|
+
}
|
|
30
|
+
return url.toString().replace(/\/+$/, "");
|
|
31
|
+
}
|
|
32
|
+
function errorKind(status) {
|
|
33
|
+
if (status === 401)
|
|
34
|
+
return "authentication";
|
|
35
|
+
if (status === 403)
|
|
36
|
+
return "permission";
|
|
37
|
+
if (status === 404)
|
|
38
|
+
return "not_found";
|
|
39
|
+
if (status === 400 || status === 422)
|
|
40
|
+
return "validation";
|
|
41
|
+
if (status === 429)
|
|
42
|
+
return "rate_limit";
|
|
43
|
+
if (status >= 500)
|
|
44
|
+
return "server";
|
|
45
|
+
return "http";
|
|
46
|
+
}
|
|
47
|
+
function isRecord(value) {
|
|
48
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
function sanitizeCause(cause, secret) {
|
|
51
|
+
if (typeof cause === "string" && cause.includes(secret)) {
|
|
52
|
+
return cause.split(secret).join("[redacted]");
|
|
53
|
+
}
|
|
54
|
+
if (cause instanceof Error && cause.message.includes(secret)) {
|
|
55
|
+
return new Error(cause.message.split(secret).join("[redacted]"));
|
|
56
|
+
}
|
|
57
|
+
return cause;
|
|
58
|
+
}
|
|
59
|
+
function buildQuery(options = {}) {
|
|
60
|
+
const params = new URLSearchParams();
|
|
61
|
+
if (options.limit !== undefined)
|
|
62
|
+
params.set("limit", String(options.limit));
|
|
63
|
+
if (options.cursor !== undefined)
|
|
64
|
+
params.set("cursor", options.cursor);
|
|
65
|
+
if (options.q !== undefined)
|
|
66
|
+
params.set("q", options.q);
|
|
67
|
+
if (options.status !== undefined)
|
|
68
|
+
params.set("status", options.status);
|
|
69
|
+
if (options.type !== undefined)
|
|
70
|
+
params.set("type", options.type);
|
|
71
|
+
const query = params.toString();
|
|
72
|
+
return query ? `?${query}` : "";
|
|
73
|
+
}
|
|
74
|
+
class HttpClient {
|
|
75
|
+
baseUrl;
|
|
76
|
+
#apiKey;
|
|
77
|
+
timeout;
|
|
78
|
+
fetcher;
|
|
79
|
+
constructor(config) {
|
|
80
|
+
if (typeof window !== "undefined") {
|
|
81
|
+
throw new TypeError("@kyrofeedback/sdk is server-side only; use widget.js for browser feedback");
|
|
82
|
+
}
|
|
83
|
+
if (typeof config.apiKey !== "string" || !config.apiKey.trim()) {
|
|
84
|
+
throw new TypeError("apiKey is required");
|
|
85
|
+
}
|
|
86
|
+
if (!/^(?:sk|pk)_live_[A-Za-z0-9_-]{43}$/.test(config.apiKey)) {
|
|
87
|
+
throw new TypeError("apiKey must be a 32-byte KyroFeedback key beginning with sk_live_ or pk_live_");
|
|
88
|
+
}
|
|
89
|
+
if (config.timeout !== undefined && (!Number.isFinite(config.timeout) || config.timeout <= 0)) {
|
|
90
|
+
throw new TypeError("timeout must be a positive finite number of milliseconds");
|
|
91
|
+
}
|
|
92
|
+
this.#apiKey = config.apiKey;
|
|
93
|
+
this.baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
94
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
95
|
+
this.fetcher = config.fetch ?? globalThis.fetch;
|
|
96
|
+
if (typeof this.fetcher !== "function") {
|
|
97
|
+
throw new TypeError("A Fetch API implementation is required; pass it with the fetch option");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async request(path, init = {}, options = {}, preserveEnvelope = false) {
|
|
101
|
+
if (options.signal?.aborted) {
|
|
102
|
+
throw new KyroFeedbackError("KyroFeedback request was aborted", { kind: "network", cause: sanitizeCause(options.signal.reason, this.#apiKey) });
|
|
103
|
+
}
|
|
104
|
+
const controller = new AbortController();
|
|
105
|
+
let timedOut = false;
|
|
106
|
+
const timeoutId = setTimeout(() => {
|
|
107
|
+
timedOut = true;
|
|
108
|
+
controller.abort(new Error("KyroFeedback request timed out"));
|
|
109
|
+
}, this.timeout);
|
|
110
|
+
const abortFromCaller = () => controller.abort(options.signal?.reason);
|
|
111
|
+
if (options.signal?.aborted)
|
|
112
|
+
abortFromCaller();
|
|
113
|
+
else
|
|
114
|
+
options.signal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
115
|
+
const headers = new Headers({
|
|
116
|
+
Authorization: `Bearer ${this.#apiKey}`,
|
|
117
|
+
Accept: "application/json",
|
|
118
|
+
});
|
|
119
|
+
if (init.body !== undefined)
|
|
120
|
+
headers.set("Content-Type", "application/json");
|
|
121
|
+
if (options.cookie)
|
|
122
|
+
headers.set("Cookie", options.cookie);
|
|
123
|
+
let response;
|
|
124
|
+
try {
|
|
125
|
+
response = await this.fetcher(`${this.baseUrl}${API_PATH}${path}`, {
|
|
126
|
+
method: init.method ?? "GET",
|
|
127
|
+
headers,
|
|
128
|
+
...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),
|
|
129
|
+
signal: controller.signal,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (cause) {
|
|
133
|
+
clearTimeout(timeoutId);
|
|
134
|
+
options.signal?.removeEventListener("abort", abortFromCaller);
|
|
135
|
+
if (timedOut) {
|
|
136
|
+
throw new KyroFeedbackError(`KyroFeedback request timed out after ${this.timeout} ms`, { kind: "timeout", cause: sanitizeCause(cause, this.#apiKey) });
|
|
137
|
+
}
|
|
138
|
+
if (options.signal?.aborted) {
|
|
139
|
+
throw new KyroFeedbackError("KyroFeedback request was aborted", { kind: "network", cause: sanitizeCause(cause, this.#apiKey) });
|
|
140
|
+
}
|
|
141
|
+
throw new KyroFeedbackError("Unable to reach the KyroFeedback API", { kind: "network", cause: sanitizeCause(cause, this.#apiKey) });
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
options.onResponse?.(response);
|
|
145
|
+
let payload = null;
|
|
146
|
+
const text = await response.text().catch((cause) => {
|
|
147
|
+
if (timedOut) {
|
|
148
|
+
throw new KyroFeedbackError(`KyroFeedback request timed out after ${this.timeout} ms`, { kind: "timeout", cause });
|
|
149
|
+
}
|
|
150
|
+
if (options.signal?.aborted) {
|
|
151
|
+
throw new KyroFeedbackError("KyroFeedback request was aborted", { kind: "network", cause });
|
|
152
|
+
}
|
|
153
|
+
throw new KyroFeedbackError("Could not read the KyroFeedback API response", { kind: "invalid_response", cause });
|
|
154
|
+
});
|
|
155
|
+
if (text) {
|
|
156
|
+
try {
|
|
157
|
+
payload = JSON.parse(text);
|
|
158
|
+
}
|
|
159
|
+
catch (cause) {
|
|
160
|
+
if (response.ok) {
|
|
161
|
+
throw new KyroFeedbackError("KyroFeedback returned a malformed JSON response", { status: response.status, kind: "invalid_response", cause });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (!response.ok) {
|
|
166
|
+
const error = isRecord(payload) && isRecord(payload.error) ? payload.error : undefined;
|
|
167
|
+
const message = typeof error?.message === "string" ? error.message : `KyroFeedback request failed with HTTP ${response.status}`;
|
|
168
|
+
const safeMessage = message.split(this.#apiKey).join("[redacted]");
|
|
169
|
+
throw new KyroFeedbackError(safeMessage, { status: response.status, kind: errorKind(response.status) });
|
|
170
|
+
}
|
|
171
|
+
if (!isRecord(payload) || !Object.hasOwn(payload, "data")) {
|
|
172
|
+
throw new KyroFeedbackError("KyroFeedback returned an unexpected response format", { status: response.status, kind: "invalid_response" });
|
|
173
|
+
}
|
|
174
|
+
if (preserveEnvelope && (!isRecord(payload.meta)
|
|
175
|
+
|| !(payload.meta.nextCursor === null || typeof payload.meta.nextCursor === "string"))) {
|
|
176
|
+
throw new KyroFeedbackError("KyroFeedback returned an unexpected pagination format", { status: response.status, kind: "invalid_response" });
|
|
177
|
+
}
|
|
178
|
+
return preserveEnvelope ? payload : payload.data;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
clearTimeout(timeoutId);
|
|
182
|
+
options.signal?.removeEventListener("abort", abortFromCaller);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Server-side client for the supported KyroFeedback v1 REST API. */
|
|
187
|
+
export class KyroFeedback {
|
|
188
|
+
http;
|
|
189
|
+
feedback;
|
|
190
|
+
comments;
|
|
191
|
+
votes;
|
|
192
|
+
constructor(config) {
|
|
193
|
+
this.http = new HttpClient(config);
|
|
194
|
+
this.feedback = {
|
|
195
|
+
list: (options = {}, request) => this.http.request(`/feedback${buildQuery(options)}`, {}, request, true),
|
|
196
|
+
get: (id, request) => this.http.request(`/feedback/${encodeURIComponent(id)}`, {}, request),
|
|
197
|
+
create: (input, request) => this.http.request("/feedback", { method: "POST", body: input }, request),
|
|
198
|
+
};
|
|
199
|
+
this.comments = {
|
|
200
|
+
list: (feedbackId, request) => this.http.request(`/feedback/${encodeURIComponent(feedbackId)}/comments`, {}, request),
|
|
201
|
+
create: (feedbackId, input, request) => this.http.request(`/feedback/${encodeURIComponent(feedbackId)}/comments`, { method: "POST", body: input }, request),
|
|
202
|
+
};
|
|
203
|
+
this.votes = {
|
|
204
|
+
get: (feedbackId, request) => this.http.request(`/feedback/${encodeURIComponent(feedbackId)}/votes`, {}, request),
|
|
205
|
+
vote: (feedbackId, request) => this.http.request(`/feedback/${encodeURIComponent(feedbackId)}/votes`, { method: "POST" }, request),
|
|
206
|
+
unvote: (feedbackId, request) => this.http.request(`/feedback/${encodeURIComponent(feedbackId)}/votes`, { method: "DELETE" }, request),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type KyroFeedbackErrorKind = "authentication" | "permission" | "validation" | "not_found" | "rate_limit" | "server" | "http" | "network" | "timeout" | "invalid_response";
|
|
2
|
+
export interface KyroFeedbackErrorOptions {
|
|
3
|
+
status?: number;
|
|
4
|
+
kind: KyroFeedbackErrorKind;
|
|
5
|
+
cause?: unknown;
|
|
6
|
+
}
|
|
7
|
+
/** Error raised for API failures, network failures, and invalid API responses. */
|
|
8
|
+
export declare class KyroFeedbackError extends Error {
|
|
9
|
+
readonly status?: number;
|
|
10
|
+
readonly kind: KyroFeedbackErrorKind;
|
|
11
|
+
constructor(message: string, options: KyroFeedbackErrorOptions);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAC7B,gBAAgB,GAChB,YAAY,GACZ,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,QAAQ,GACR,MAAM,GACN,SAAS,GACT,SAAS,GACT,kBAAkB,CAAC;AAEvB,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,kFAAkF;AAClF,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB;CAM/D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Error raised for API failures, network failures, and invalid API responses. */
|
|
2
|
+
export class KyroFeedbackError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
kind;
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
7
|
+
this.name = "KyroFeedbackError";
|
|
8
|
+
this.status = options.status;
|
|
9
|
+
this.kind = options.kind;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAkBA,kFAAkF;AAClF,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,MAAM,CAAU;IAChB,IAAI,CAAwB;IAErC,YAAY,OAAe,EAAE,OAAiC;QAC5D,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { KyroFeedback } from "./client.js";
|
|
2
|
+
export { KyroFeedbackError } from "./errors.js";
|
|
3
|
+
export type { KyroFeedbackErrorKind, KyroFeedbackErrorOptions } from "./errors.js";
|
|
4
|
+
export type { Comment, CreateCommentInput, CreateFeedbackInput, Feedback, FeedbackPage, FeedbackStatus, FeedbackType, KyroFeedbackConfig, ListFeedbackOptions, RequestOptions, VoteState, } from "./types.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACnF,YAAY,EACV,OAAO,EACP,kBAAkB,EAClB,mBAAmB,EACnB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type FeedbackStatus = "OPEN" | "PLANNED" | "IN_PROGRESS" | "COMPLETED" | "CLOSED";
|
|
2
|
+
export type FeedbackType = "FEATURE" | "BUG" | "QUESTION" | "INTEGRATION";
|
|
3
|
+
/** A feedback object returned by the public v1 API. Dates are ISO 8601 strings. */
|
|
4
|
+
export interface Feedback {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
type: FeedbackType;
|
|
9
|
+
status: FeedbackStatus;
|
|
10
|
+
votesCount: number;
|
|
11
|
+
commentsCount: number;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CreateFeedbackInput {
|
|
16
|
+
title: string;
|
|
17
|
+
description: string;
|
|
18
|
+
type: FeedbackType;
|
|
19
|
+
authorName?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ListFeedbackOptions {
|
|
22
|
+
/** API range is 1–50; omitted values use the API default of 20. */
|
|
23
|
+
limit?: number;
|
|
24
|
+
/** Cursor returned as `meta.nextCursor` by the preceding page. */
|
|
25
|
+
cursor?: string;
|
|
26
|
+
/** Case-insensitive search across title and description. */
|
|
27
|
+
q?: string;
|
|
28
|
+
status?: FeedbackStatus;
|
|
29
|
+
type?: FeedbackType;
|
|
30
|
+
}
|
|
31
|
+
export interface FeedbackPage {
|
|
32
|
+
data: Feedback[];
|
|
33
|
+
meta: {
|
|
34
|
+
nextCursor: string | null;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface Comment {
|
|
38
|
+
id: string;
|
|
39
|
+
parentId: string | null;
|
|
40
|
+
content: string;
|
|
41
|
+
anonymous: boolean;
|
|
42
|
+
authorName: string | null;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
}
|
|
46
|
+
export interface CreateCommentInput {
|
|
47
|
+
content: string;
|
|
48
|
+
/** Set to a comment on this same feedback item to create a threaded reply. */
|
|
49
|
+
parentId?: string | null;
|
|
50
|
+
authorName?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface VoteState {
|
|
53
|
+
voted: boolean;
|
|
54
|
+
count: number;
|
|
55
|
+
}
|
|
56
|
+
export interface KyroFeedbackConfig {
|
|
57
|
+
/** A project-scoped `sk_live_` or `pk_live_` key. Prefer `sk_live_` on servers. */
|
|
58
|
+
apiKey: string;
|
|
59
|
+
/** KyroFeedback origin. Defaults to https://feedback.kyrocms.com. */
|
|
60
|
+
baseUrl?: string;
|
|
61
|
+
/** Request timeout in milliseconds. Defaults to 10 seconds. */
|
|
62
|
+
timeout?: number;
|
|
63
|
+
/** Custom Fetch API implementation, useful for runtimes and tests. */
|
|
64
|
+
fetch?: typeof fetch;
|
|
65
|
+
}
|
|
66
|
+
/** Per-request transport controls. Cookies are never stored by the SDK. */
|
|
67
|
+
export interface RequestOptions {
|
|
68
|
+
signal?: AbortSignal;
|
|
69
|
+
/** Forward a visitor's `kyro_anonymous_id` cookie when preserving vote identity. */
|
|
70
|
+
cookie?: string;
|
|
71
|
+
/** Inspect response headers, for example to relay Set-Cookie from your server route. */
|
|
72
|
+
onResponse?: (response: Response) => void;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;AACzF,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,aAAa,CAAC;AAE1E,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACrC;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC3C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kyrofeedback/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Typed server-side client for the KyroFeedback REST API",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/kasimthecoder/kyrofeedback.git",
|
|
9
|
+
"directory": "packages/sdk"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/kasimthecoder/kyrofeedback/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/kasimthecoder/kyrofeedback/tree/main/packages/sdk#readme",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc -p tsconfig.json",
|
|
34
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
35
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
36
|
+
"test:integration": "npm run build && node test/integration.mjs",
|
|
37
|
+
"pack:check": "npm pack --dry-run"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
}
|
|
42
|
+
}
|