@bangkeut-technology/supportdock-sdk 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/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @bangkeut-technology/supportdock-sdk
2
+
3
+ Official SDK for [SupportDock](https://supportdock.io) — submit feedback and manage FAQs from your React Native / Expo app.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @bangkeut-technology/supportdock-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ import { SupportDockClient } from '@bangkeut-technology/supportdock-sdk';
15
+
16
+ const sdk = new SupportDockClient({
17
+ apiKey: 'sdk_your_api_key',
18
+ });
19
+
20
+ // Submit feedback
21
+ await sdk.sendFeedback({
22
+ type: 'bug',
23
+ message: 'App crashes when opening settings',
24
+ email: 'user@example.com',
25
+ metadata: { appVersion: '2.1.0', platform: 'ios' },
26
+ });
27
+
28
+ // List FAQs
29
+ const faqs = await sdk.listFAQs();
30
+ ```
31
+
32
+ ## React Hook (Expo / React Native)
33
+
34
+ ```tsx
35
+ import { useSupportDock } from '@bangkeut-technology/supportdock-sdk';
36
+ import { Platform } from 'react-native';
37
+
38
+ function FeedbackScreen() {
39
+ const { sendFeedback, loading, error, success } = useSupportDock({
40
+ apiKey: 'sdk_your_api_key',
41
+ defaultMetadata: {
42
+ appVersion: '2.1.0',
43
+ platform: Platform.OS,
44
+ },
45
+ });
46
+
47
+ const handleSubmit = async () => {
48
+ await sendFeedback({
49
+ type: 'bug',
50
+ message: 'Something went wrong',
51
+ email: userEmail,
52
+ });
53
+ };
54
+
55
+ if (success) return <Text>Thanks for your feedback!</Text>;
56
+
57
+ return (
58
+ <View>
59
+ <Button onPress={handleSubmit} disabled={loading} title="Send Feedback" />
60
+ {error && <Text style={{ color: 'red' }}>{error}</Text>}
61
+ </View>
62
+ );
63
+ }
64
+ ```
65
+
66
+ ## API
67
+
68
+ ### `SupportDockClient`
69
+
70
+ ```ts
71
+ const sdk = new SupportDockClient({
72
+ apiKey: string; // Required — your app's API key (starts with sdk_)
73
+ baseUrl?: string; // Default: 'https://supportdock.io'
74
+ defaultMetadata?: Record<string, string>; // Merged into every feedback submission
75
+ timeout?: number; // Request timeout in ms (default: 10000)
76
+ });
77
+ ```
78
+
79
+ ### Feedback
80
+
81
+ ```ts
82
+ // Submit feedback
83
+ await sdk.sendFeedback({
84
+ type: 'bug' | 'feature' | 'question' | 'general', // default: 'general'
85
+ message: string, // required
86
+ email?: string,
87
+ name?: string,
88
+ subject?: string, // auto-generated from type if omitted
89
+ metadata?: Record<string, string>,
90
+ source?: string, // default: 'mobile-app'
91
+ });
92
+ ```
93
+
94
+ ### FAQs
95
+
96
+ ```ts
97
+ // List all FAQs
98
+ const faqs = await sdk.listFAQs();
99
+
100
+ // Create FAQ
101
+ const faq = await sdk.createFAQ({ question: '...', answer: '...', sortOrder: 0 });
102
+
103
+ // Update FAQ
104
+ await sdk.updateFAQ(faqId, { answer: 'Updated answer' });
105
+
106
+ // Delete FAQ
107
+ await sdk.deleteFAQ(faqId);
108
+ ```
109
+
110
+ ### Error Handling
111
+
112
+ ```ts
113
+ import { SupportDockError } from '@bangkeut-technology/supportdock-sdk';
114
+
115
+ try {
116
+ await sdk.sendFeedback({ message: '...' });
117
+ } catch (err) {
118
+ if (err instanceof SupportDockError) {
119
+ console.log(err.message); // Error message from API
120
+ console.log(err.status); // HTTP status code (401, 429, etc.)
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## Get Your API Key
126
+
127
+ 1. Go to your app dashboard on [supportdock.io](https://supportdock.io)
128
+ 2. Click **Generate API key**
129
+ 3. Copy the key (starts with `sdk_`)
130
+
131
+ Requires a Pro plan.
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,31 @@
1
+ import type { SupportDockConfig, FeedbackOptions, FeedbackResult, FAQ, CreateFAQOptions, UpdateFAQOptions } from './types';
2
+ export declare class SupportDockClient {
3
+ private apiKey;
4
+ private baseUrl;
5
+ private defaultMetadata;
6
+ private timeout;
7
+ constructor(config: SupportDockConfig);
8
+ private request;
9
+ /**
10
+ * Submit feedback from your app.
11
+ *
12
+ * ```ts
13
+ * await sdk.sendFeedback({ type: 'bug', message: 'App crashes on launch' });
14
+ * ```
15
+ */
16
+ sendFeedback(options: FeedbackOptions): Promise<FeedbackResult>;
17
+ /** List all FAQ entries for this app. */
18
+ listFAQs(): Promise<FAQ[]>;
19
+ /** Create a new FAQ entry. */
20
+ createFAQ(options: CreateFAQOptions): Promise<FAQ>;
21
+ /** Update an existing FAQ entry. */
22
+ updateFAQ(faqId: string, options: UpdateFAQOptions): Promise<FAQ>;
23
+ /** Delete a FAQ entry. */
24
+ deleteFAQ(faqId: string): Promise<{
25
+ success: boolean;
26
+ }>;
27
+ }
28
+ export declare class SupportDockError extends Error {
29
+ status: number;
30
+ constructor(message: string, status: number);
31
+ }
package/dist/client.js ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SupportDockError = exports.SupportDockClient = void 0;
4
+ const DEFAULT_BASE_URL = 'https://supportdock.io';
5
+ const DEFAULT_TIMEOUT = 10000;
6
+ class SupportDockClient {
7
+ constructor(config) {
8
+ if (!config.apiKey)
9
+ throw new Error('SupportDock: apiKey is required');
10
+ this.apiKey = config.apiKey;
11
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, '');
12
+ this.defaultMetadata = config.defaultMetadata ?? {};
13
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
14
+ }
15
+ async request(path, options = {}) {
16
+ const controller = new AbortController();
17
+ const timer = setTimeout(() => controller.abort(), this.timeout);
18
+ try {
19
+ const res = await fetch(`${this.baseUrl}${path}`, {
20
+ ...options,
21
+ signal: controller.signal,
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ 'x-api-key': this.apiKey,
25
+ ...options.headers,
26
+ },
27
+ });
28
+ const data = await res.json();
29
+ if (!res.ok) {
30
+ throw new SupportDockError(data.error ?? `Request failed with status ${res.status}`, res.status);
31
+ }
32
+ return data;
33
+ }
34
+ finally {
35
+ clearTimeout(timer);
36
+ }
37
+ }
38
+ // ─── Feedback ────────────────────────────────────────────────
39
+ /**
40
+ * Submit feedback from your app.
41
+ *
42
+ * ```ts
43
+ * await sdk.sendFeedback({ type: 'bug', message: 'App crashes on launch' });
44
+ * ```
45
+ */
46
+ async sendFeedback(options) {
47
+ const metadata = { ...this.defaultMetadata, ...options.metadata };
48
+ return this.request('/api/feedback/remote', {
49
+ method: 'POST',
50
+ body: JSON.stringify({
51
+ type: options.type ?? 'general',
52
+ message: options.message,
53
+ email: options.email,
54
+ name: options.name,
55
+ subject: options.subject,
56
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
57
+ source: options.source ?? 'mobile-app',
58
+ }),
59
+ });
60
+ }
61
+ // ─── FAQ ─────────────────────────────────────────────────────
62
+ /** List all FAQ entries for this app. */
63
+ async listFAQs() {
64
+ return this.request('/api/faqs/remote');
65
+ }
66
+ /** Create a new FAQ entry. */
67
+ async createFAQ(options) {
68
+ return this.request('/api/faqs/remote', {
69
+ method: 'POST',
70
+ body: JSON.stringify(options),
71
+ });
72
+ }
73
+ /** Update an existing FAQ entry. */
74
+ async updateFAQ(faqId, options) {
75
+ return this.request(`/api/faqs/remote/${faqId}`, {
76
+ method: 'PATCH',
77
+ body: JSON.stringify(options),
78
+ });
79
+ }
80
+ /** Delete a FAQ entry. */
81
+ async deleteFAQ(faqId) {
82
+ return this.request(`/api/faqs/remote/${faqId}`, {
83
+ method: 'DELETE',
84
+ });
85
+ }
86
+ }
87
+ exports.SupportDockClient = SupportDockClient;
88
+ class SupportDockError extends Error {
89
+ constructor(message, status) {
90
+ super(message);
91
+ this.name = 'SupportDockError';
92
+ this.status = status;
93
+ }
94
+ }
95
+ exports.SupportDockError = SupportDockError;
@@ -0,0 +1,3 @@
1
+ export { SupportDockClient, SupportDockError } from './client';
2
+ export { useSupportDock } from './react';
3
+ export type { SupportDockConfig, FeedbackOptions, FeedbackResult, FeedbackType, FAQ, CreateFAQOptions, UpdateFAQOptions, } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSupportDock = exports.SupportDockError = exports.SupportDockClient = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "SupportDockClient", { enumerable: true, get: function () { return client_1.SupportDockClient; } });
6
+ Object.defineProperty(exports, "SupportDockError", { enumerable: true, get: function () { return client_1.SupportDockError; } });
7
+ var react_1 = require("./react");
8
+ Object.defineProperty(exports, "useSupportDock", { enumerable: true, get: function () { return react_1.useSupportDock; } });
@@ -0,0 +1,22 @@
1
+ import { SupportDockClient } from './client';
2
+ import type { SupportDockConfig, FeedbackOptions, FeedbackResult } from './types';
3
+ /**
4
+ * React hook for submitting feedback from your Expo / React Native app.
5
+ *
6
+ * ```tsx
7
+ * const { sendFeedback, loading, error, success } = useSupportDock({
8
+ * apiKey: 'sdk_your_key',
9
+ * defaultMetadata: { appVersion: '2.0.0', platform: Platform.OS },
10
+ * });
11
+ *
12
+ * await sendFeedback({ type: 'bug', message: 'Something went wrong' });
13
+ * ```
14
+ */
15
+ export declare function useSupportDock(config: SupportDockConfig): {
16
+ sendFeedback: (options: FeedbackOptions) => Promise<FeedbackResult>;
17
+ loading: boolean;
18
+ error: string | null;
19
+ success: boolean;
20
+ reset: () => void;
21
+ client: SupportDockClient;
22
+ };
package/dist/react.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSupportDock = useSupportDock;
4
+ const react_1 = require("react");
5
+ const client_1 = require("./client");
6
+ /**
7
+ * React hook for submitting feedback from your Expo / React Native app.
8
+ *
9
+ * ```tsx
10
+ * const { sendFeedback, loading, error, success } = useSupportDock({
11
+ * apiKey: 'sdk_your_key',
12
+ * defaultMetadata: { appVersion: '2.0.0', platform: Platform.OS },
13
+ * });
14
+ *
15
+ * await sendFeedback({ type: 'bug', message: 'Something went wrong' });
16
+ * ```
17
+ */
18
+ function useSupportDock(config) {
19
+ const clientRef = (0, react_1.useRef)(null);
20
+ if (!clientRef.current) {
21
+ clientRef.current = new client_1.SupportDockClient(config);
22
+ }
23
+ const [loading, setLoading] = (0, react_1.useState)(false);
24
+ const [error, setError] = (0, react_1.useState)(null);
25
+ const [success, setSuccess] = (0, react_1.useState)(false);
26
+ const sendFeedback = (0, react_1.useCallback)(async (options) => {
27
+ setLoading(true);
28
+ setError(null);
29
+ setSuccess(false);
30
+ try {
31
+ const result = await clientRef.current.sendFeedback(options);
32
+ setSuccess(true);
33
+ return result;
34
+ }
35
+ catch (err) {
36
+ const message = err instanceof Error ? err.message : 'Failed to send feedback';
37
+ setError(message);
38
+ return { success: false, error: message };
39
+ }
40
+ finally {
41
+ setLoading(false);
42
+ }
43
+ }, []);
44
+ const reset = (0, react_1.useCallback)(() => {
45
+ setError(null);
46
+ setSuccess(false);
47
+ }, []);
48
+ return { sendFeedback, loading, error, success, reset, client: clientRef.current };
49
+ }
@@ -0,0 +1,49 @@
1
+ export type FeedbackType = 'bug' | 'feature' | 'question' | 'general';
2
+ export interface FeedbackOptions {
3
+ /** Feedback type. Defaults to 'general'. */
4
+ type?: FeedbackType;
5
+ /** The feedback message (required). */
6
+ message: string;
7
+ /** Sender email (optional). */
8
+ email?: string;
9
+ /** Sender name (optional). */
10
+ name?: string;
11
+ /** Subject line (optional — auto-generated from type if omitted). */
12
+ subject?: string;
13
+ /** Arbitrary metadata (e.g. appVersion, platform, deviceModel). */
14
+ metadata?: Record<string, string>;
15
+ /** Source identifier (defaults to 'mobile-app'). */
16
+ source?: string;
17
+ }
18
+ export interface FeedbackResult {
19
+ success: boolean;
20
+ error?: string;
21
+ }
22
+ export interface FAQ {
23
+ id: string;
24
+ question: string;
25
+ answer: string;
26
+ sortOrder: number;
27
+ createdAt: string;
28
+ updatedAt: string;
29
+ }
30
+ export interface CreateFAQOptions {
31
+ question: string;
32
+ answer: string;
33
+ sortOrder?: number;
34
+ }
35
+ export interface UpdateFAQOptions {
36
+ question?: string;
37
+ answer?: string;
38
+ sortOrder?: number;
39
+ }
40
+ export interface SupportDockConfig {
41
+ /** Your app's API key (starts with sdk_). */
42
+ apiKey: string;
43
+ /** Base URL. Defaults to https://supportdock.io. */
44
+ baseUrl?: string;
45
+ /** Default metadata merged into every feedback submission. */
46
+ defaultMetadata?: Record<string, string>;
47
+ /** Request timeout in ms. Defaults to 10000. */
48
+ timeout?: number;
49
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@bangkeut-technology/supportdock-sdk",
3
+ "version": "0.1.0",
4
+ "description": "SupportDock SDK — submit feedback and manage FAQs from your React Native / Expo app",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist"],
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build"
11
+ },
12
+ "keywords": ["supportdock", "feedback", "faq", "react-native", "expo", "sdk"],
13
+ "license": "MIT",
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "peerDependencies": {
18
+ "react": ">=18.0.0"
19
+ },
20
+ "peerDependenciesMeta": {
21
+ "react": {
22
+ "optional": true
23
+ }
24
+ },
25
+ "devDependencies": {
26
+ "@types/react": "^19.0.0",
27
+ "typescript": "^5.0.0"
28
+ }
29
+ }