@proveanything/smartlinks 1.0.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,184 @@
1
+ # @smartlinks/sdk
2
+
3
+ An official JavaScript/TypeScript client SDK for the Smartlinks API. This package provides a simple wrapper around the Smartlinks REST endpoints, allowing you to fetch Collection, Product, and App Configuration data in both browser and Node.js environments.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @smartlinks/sdk
9
+ # or
10
+ yarn add @smartlinks/sdk
11
+ ```
12
+
13
+ ## Quickstart
14
+
15
+ ```ts
16
+ import { ApiClient, CollectionResponse, ProductResponse } from "@smartlinks/sdk";
17
+
18
+ async function main() {
19
+ // Instantiate the client (no apiKey needed for public endpoints, but shown here for reference)
20
+ const client = new ApiClient("https://smartlinks.app/api/v1", "YOUR_API_KEY_HERE");
21
+
22
+ try {
23
+ // Fetch a collection by ID
24
+ const collection: CollectionResponse = await client.getCollection("abc123");
25
+ console.log("Collection:", collection);
26
+
27
+ // Fetch a product item by collection ID & product ID
28
+ const product: ProductResponse = await client.getProductItem("abc123", "prod789");
29
+ console.log("Product Item:", product);
30
+ } catch (err) {
31
+ console.error("Error fetching data:", err);
32
+ }
33
+ }
34
+
35
+ main();
36
+ ```
37
+
38
+ ## API Reference
39
+
40
+ ### Class: `ApiClient`
41
+
42
+ ```ts
43
+ constructor(baseURL: string, apiKey?: string)
44
+ ```
45
+
46
+ - **Parameters:**
47
+ - `baseURL` (`string`, required): The root URL of the Smartlinks API, e.g. `https://smartlinks.app/api/v1`.
48
+ - `apiKey` (`string`, optional): Your Bearer token. If omitted, requests will be sent without an `Authorization` header.
49
+
50
+ ---
51
+
52
+ #### `getCollection(collectionId: string): Promise<CollectionResponse>`
53
+
54
+ Fetches a single collection by its ID.
55
+
56
+ - **Parameters:**
57
+ - `collectionId` (`string`, required): The unique identifier of the collection to fetch.
58
+ - **Returns:**
59
+ A `Promise` that resolves to a `CollectionResponse` object:
60
+
61
+ ```ts
62
+ export interface CollectionResponse {
63
+ id: string;
64
+ name: string;
65
+ title: string;
66
+ logoImage: string;
67
+ }
68
+ ```
69
+
70
+ - **Example:**
71
+ ```ts
72
+ const client = new ApiClient("https://smartlinks.app/api/v1", "YOUR_API_KEY");
73
+ const collection = await client.getCollection("abc123");
74
+ console.log("Fetched collection:", collection);
75
+ ```
76
+
77
+ ---
78
+
79
+ #### `getProductItem(collectionId: string, productId: string): Promise<ProductResponse>`
80
+
81
+ Fetches a single product item within a collection.
82
+
83
+ - **Parameters:**
84
+ - `collectionId` (`string`, required): The parent collection’s ID.
85
+ - `productId` (`string`, required): The product item’s ID.
86
+ - **Returns:**
87
+ A `Promise` that resolves to a `ProductResponse` object:
88
+
89
+ ```ts
90
+ export interface ProductResponse {
91
+ id: string;
92
+ name: string;
93
+ description: string;
94
+ heroImage: string;
95
+ }
96
+ ```
97
+
98
+ - **Example:**
99
+ ```ts
100
+ const client = new ApiClient("https://smartlinks.app/api/v1", "YOUR_API_KEY");
101
+ const product = await client.getProductItem("abc123", "prod789");
102
+ console.log("Fetched product:", product);
103
+ ```
104
+
105
+ ---
106
+
107
+ #### `getAppConfiguration(collectionId: string, appId: string): Promise<AppConfigurationResponse>`
108
+
109
+ Fetches a single app configuration within a collection.
110
+
111
+ - **Parameters:**
112
+ - `collectionId` (`string`, required): The parent collection’s ID.
113
+ - `appId` (`string`, required): The app configuration’s ID.
114
+ - **Returns:**
115
+ A `Promise` that resolves to an `AppConfigurationResponse` object:
116
+
117
+ ```ts
118
+ export interface AppConfigurationResponse {
119
+ id: string;
120
+ name: string;
121
+ settings?: Record<string, any>;
122
+ }
123
+ ```
124
+
125
+ - **Example:**
126
+ ```ts
127
+ const client = new ApiClient("https://smartlinks.app/api/v1", "YOUR_API_KEY");
128
+ const config = await client.getAppConfiguration("abc123", "app456");
129
+ console.log("Fetched app configuration:", config);
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Authentication
135
+
136
+ All endpoints require a Bearer token passed in the `AUTHORIZATION` header. When instantiating `ApiClient`, optionally supply your token:
137
+
138
+ ```ts
139
+ import { ApiClient } from "@smartlinks/sdk";
140
+
141
+ const apiKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
142
+ const client = new ApiClient("https://smartlinks.app/api/v1", apiKey);
143
+ ```
144
+
145
+ If `apiKey` is omitted, requests will be sent without an `Authorization` header, which may cause a `401 Unauthorized` for protected endpoints.
146
+
147
+ ## Error Handling
148
+
149
+ All methods throw an `Error` when the server responds with a non-2xx status. The thrown error message includes the numeric error code and message from the API. Example:
150
+
151
+ ```ts
152
+ import { ApiClient } from "@smartlinks/sdk";
153
+
154
+ async function fetchData() {
155
+ const client = new ApiClient("https://smartlinks.app/api/v1", "INVALID_KEY");
156
+
157
+ try {
158
+ await client.getCollection("nonexistent");
159
+ } catch (err) {
160
+ // err.message might be: "Error 401: Unauthorized" or "Error 404: Not Found"
161
+ console.error("Request failed:", err);
162
+ }
163
+ }
164
+
165
+ fetchData();
166
+ ```
167
+
168
+ ## Examples
169
+
170
+ See the **examples/** folder for complete, runnable samples:
171
+
172
+ - [`examples/node-demo.ts`](examples/node-demo.ts)
173
+ - [`examples/browser-demo.html`](examples/browser-demo.html)
174
+ - [`examples/react-demo.tsx`](examples/react-demo.tsx)
175
+
176
+ ## Changelog
177
+
178
+ ### 1.0.0
179
+
180
+ - Initial release:
181
+ - `ApiClient` class with `getCollection`, `getProductItem`, and `getAppConfiguration` methods.
182
+ - Full TypeScript typings and JSDoc.
183
+ - Browser/Node fetch support.
184
+ - Error handling via thrown `Error` objects.
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Represents a Collection object.
3
+ */
4
+ export interface CollectionResponse {
5
+ /** Unique identifier for the collection */
6
+ id: string;
7
+ /** Machine‐readable name of the collection */
8
+ name: string;
9
+ /** Human‐readable title of the collection */
10
+ title: string;
11
+ /** URL to the collection’s logo image */
12
+ logoImage: string;
13
+ }
14
+ /**
15
+ * Represents a Product Item object.
16
+ */
17
+ export interface ProductResponse {
18
+ /** Unique identifier for the product */
19
+ id: string;
20
+ /** Name of the product */
21
+ name: string;
22
+ /** Detailed description of the product */
23
+ description: string;
24
+ /** URL to the product’s hero image */
25
+ heroImage: string;
26
+ }
27
+ /**
28
+ * Represents an App Configuration object.
29
+ */
30
+ export interface AppConfigurationResponse {
31
+ /** Unique identifier for the app configuration */
32
+ id: string;
33
+ /** Name of the app configuration */
34
+ name: string;
35
+ /** Key‐value pairs representing configuration settings */
36
+ settings?: Record<string, any>;
37
+ }
38
+ /**
39
+ * Represents a standardized error response.
40
+ */
41
+ export interface ErrorResponse {
42
+ /** Numeric error code */
43
+ code: number;
44
+ /** Human‐readable error message */
45
+ message: string;
46
+ }
47
+ /**
48
+ * ApiClient for the Smartlinks API.
49
+ * Supports both browser (native fetch) and Node (using cross-fetch).
50
+ */
51
+ export declare class ApiClient {
52
+ private baseURL;
53
+ private apiKey?;
54
+ private bearerToken?;
55
+ /**
56
+ * Creates an instance of ApiClient.
57
+ * @param baseURL - The base URL of the Smartlinks API (e.g., https://smartlinks.app/api/v1)
58
+ * @param apiKey - (Optional) API key for X-API-Key header
59
+ * @param bearerToken - (Optional) Bearer token for AUTHORIZATION header
60
+ *
61
+ * @example
62
+ * // With both API key and bearer token
63
+ * const client = new ApiClient(
64
+ * 'https://smartlinks.app/api/v1',
65
+ * 'your-api-key',
66
+ * 'your-bearer-token'
67
+ * );
68
+ *
69
+ * // With only API key
70
+ * const client = new ApiClient(
71
+ * 'https://smartlinks.app/api/v1',
72
+ * 'your-api-key'
73
+ * );
74
+ *
75
+ * // With only bearer token
76
+ * const client = new ApiClient(
77
+ * 'https://smartlinks.app/api/v1',
78
+ * undefined,
79
+ * 'your-bearer-token'
80
+ * );
81
+ */
82
+ constructor(baseURL: string, apiKey?: string, bearerToken?: string);
83
+ /**
84
+ * Retrieves a single Collection by its ID.
85
+ * @param collectionId - Identifier of the collection
86
+ * @returns Promise resolving to a CollectionResponse object
87
+ * @throws ErrorResponse if the request fails
88
+ */
89
+ getCollection(collectionId: string): Promise<CollectionResponse>;
90
+ /**
91
+ * Retrieves a single Product Item by Collection ID and Product ID.
92
+ * @param collectionId - Identifier of the parent collection
93
+ * @param productId - Identifier of the product item
94
+ * @returns Promise resolving to a ProductResponse object
95
+ * @throws ErrorResponse if the request fails
96
+ */
97
+ getProductItem(collectionId: string, productId: string): Promise<ProductResponse>;
98
+ /**
99
+ * Retrieves a single App Configuration by Collection ID and App ID.
100
+ * @param collectionId - Identifier of the parent collection
101
+ * @param appId - Identifier of the app configuration
102
+ * @returns Promise resolving to an AppConfigurationResponse object
103
+ * @throws ErrorResponse if the request fails
104
+ */
105
+ getAppConfiguration(collectionId: string, appId: string): Promise<AppConfigurationResponse>;
106
+ /**
107
+ * Internal helper to perform a GET request and parse JSON.
108
+ * @param path - The path (relative to baseURL) to request
109
+ * @returns Promise resolving to the parsed JSON of type T
110
+ * @throws Error if network error or a non-2xx response is returned
111
+ */
112
+ private request;
113
+ }
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ import fetch from 'cross-fetch';
2
+ ///////////////////////////
3
+ // ApiClient Class
4
+ ///////////////////////////
5
+ /**
6
+ * ApiClient for the Smartlinks API.
7
+ * Supports both browser (native fetch) and Node (using cross-fetch).
8
+ */
9
+ export class ApiClient {
10
+ /**
11
+ * Creates an instance of ApiClient.
12
+ * @param baseURL - The base URL of the Smartlinks API (e.g., https://smartlinks.app/api/v1)
13
+ * @param apiKey - (Optional) API key for X-API-Key header
14
+ * @param bearerToken - (Optional) Bearer token for AUTHORIZATION header
15
+ *
16
+ * @example
17
+ * // With both API key and bearer token
18
+ * const client = new ApiClient(
19
+ * 'https://smartlinks.app/api/v1',
20
+ * 'your-api-key',
21
+ * 'your-bearer-token'
22
+ * );
23
+ *
24
+ * // With only API key
25
+ * const client = new ApiClient(
26
+ * 'https://smartlinks.app/api/v1',
27
+ * 'your-api-key'
28
+ * );
29
+ *
30
+ * // With only bearer token
31
+ * const client = new ApiClient(
32
+ * 'https://smartlinks.app/api/v1',
33
+ * undefined,
34
+ * 'your-bearer-token'
35
+ * );
36
+ */
37
+ constructor(baseURL, apiKey, bearerToken) {
38
+ this.baseURL = baseURL.replace(/\/+$/, ''); // Trim trailing slash
39
+ this.apiKey = apiKey;
40
+ this.bearerToken = bearerToken;
41
+ }
42
+ /**
43
+ * Retrieves a single Collection by its ID.
44
+ * @param collectionId - Identifier of the collection
45
+ * @returns Promise resolving to a CollectionResponse object
46
+ * @throws ErrorResponse if the request fails
47
+ */
48
+ async getCollection(collectionId) {
49
+ const path = `/public/collection/${encodeURIComponent(collectionId)}`;
50
+ return this.request(path);
51
+ }
52
+ /**
53
+ * Retrieves a single Product Item by Collection ID and Product ID.
54
+ * @param collectionId - Identifier of the parent collection
55
+ * @param productId - Identifier of the product item
56
+ * @returns Promise resolving to a ProductResponse object
57
+ * @throws ErrorResponse if the request fails
58
+ */
59
+ async getProductItem(collectionId, productId) {
60
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}`;
61
+ return this.request(path);
62
+ }
63
+ /**
64
+ * Retrieves a single App Configuration by Collection ID and App ID.
65
+ * @param collectionId - Identifier of the parent collection
66
+ * @param appId - Identifier of the app configuration
67
+ * @returns Promise resolving to an AppConfigurationResponse object
68
+ * @throws ErrorResponse if the request fails
69
+ */
70
+ async getAppConfiguration(collectionId, appId) {
71
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/app/${encodeURIComponent(appId)}`;
72
+ return this.request(path);
73
+ }
74
+ /**
75
+ * Internal helper to perform a GET request and parse JSON.
76
+ * @param path - The path (relative to baseURL) to request
77
+ * @returns Promise resolving to the parsed JSON of type T
78
+ * @throws Error if network error or a non-2xx response is returned
79
+ */
80
+ async request(path) {
81
+ const url = `${this.baseURL}${path}`;
82
+ const headers = {
83
+ 'Content-Type': 'application/json',
84
+ };
85
+ if (this.apiKey) {
86
+ headers['X-API-Key'] = this.apiKey;
87
+ }
88
+ if (this.bearerToken) {
89
+ headers['AUTHORIZATION'] = `Bearer ${this.bearerToken}`;
90
+ }
91
+ const response = await fetch(url, { method: 'GET', headers });
92
+ if (!response.ok) {
93
+ // Attempt to parse error body; if it fails, throw generic
94
+ let errorBody;
95
+ try {
96
+ errorBody = (await response.json());
97
+ }
98
+ catch (_a) {
99
+ throw new Error(`Request failed with status ${response.status}`);
100
+ }
101
+ throw new Error(`Error ${errorBody.code}: ${errorBody.message}`);
102
+ }
103
+ return (await response.json());
104
+ }
105
+ }
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Smartlinks SDK Browser Demo</title>
6
+ </head>
7
+ <body>
8
+ <h1>Smartlinks SDK Browser Demo</h1>
9
+ <pre id="output"></pre>
10
+ <script type="module">
11
+ import { ApiClient } from '../dist/index.js';
12
+
13
+ async function run() {
14
+ // You can provide either or both of these values:
15
+ const apiKey = 'YOUR_API_KEY'; // sent as X-API-Key header (optional)
16
+ const bearerToken = 'YOUR_BEARER_TOKEN'; // sent as AUTHORIZATION: Bearer ... (optional)
17
+
18
+ // Example: with both headers
19
+ const client = new ApiClient('https://smartlinks.app/api/v1', apiKey, bearerToken);
20
+
21
+ try {
22
+ const collection = await client.getCollection('abc123');
23
+ const product = await client.getProductItem('abc123', 'prod789');
24
+ document.getElementById('output').textContent = JSON.stringify({ collection, product }, null, 2);
25
+ } catch (err) {
26
+ document.getElementById('output').textContent = 'Error: ' + err.message;
27
+ }
28
+ }
29
+ run();
30
+ </script>
31
+ </body>
32
+ </html>
@@ -0,0 +1,22 @@
1
+ import { ApiClient, CollectionResponse, ProductResponse } from "../src/index";
2
+
3
+ async function main() {
4
+ // You can provide either or both of these values:
5
+ const apiKey = "YOUR_API_KEY"; // sent as X-API-Key header (optional)
6
+ const bearerToken = "YOUR_BEARER_TOKEN"; // sent as AUTHORIZATION: Bearer ... (optional)
7
+
8
+ // Example: with both headers
9
+ const client = new ApiClient("https://smartlinks.app/api/v1", apiKey, bearerToken);
10
+
11
+ try {
12
+ const collection: CollectionResponse = await client.getCollection("abc123");
13
+ console.log("Collection:", collection);
14
+
15
+ const product: ProductResponse = await client.getProductItem("abc123", "prod789");
16
+ console.log("Product Item:", product);
17
+ } catch (err) {
18
+ console.error("Error fetching data:", err);
19
+ }
20
+ }
21
+
22
+ main();
@@ -0,0 +1,44 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { ApiClient, CollectionResponse, ProductResponse } from '@smartlinks/sdk';
3
+
4
+ // You can provide either or both of these values:
5
+ const apiKey = 'YOUR_API_KEY'; // sent as X-API-Key header (optional)
6
+ const bearerToken = 'YOUR_BEARER_TOKEN'; // sent as AUTHORIZATION: Bearer ... (optional)
7
+
8
+ // Example: with both headers
9
+ const client = new ApiClient('https://smartlinks.app/api/v1', apiKey, bearerToken);
10
+
11
+ const ReactDemo: React.FC = () => {
12
+ const [collection, setCollection] = useState<CollectionResponse | null>(null);
13
+ const [product, setProduct] = useState<ProductResponse | null>(null);
14
+ const [error, setError] = useState<string | null>(null);
15
+
16
+ useEffect(() => {
17
+ async function fetchData() {
18
+ try {
19
+ const col = await client.getCollection('abc123');
20
+ const prod = await client.getProductItem('abc123', 'prod789');
21
+ setCollection(col);
22
+ setProduct(prod);
23
+ } catch (err) {
24
+ setError((err as Error).message);
25
+ }
26
+ }
27
+ fetchData();
28
+ }, []);
29
+
30
+ if (error) return <div>Error: {error}</div>;
31
+ if (!collection || !product) return <div>Loading...</div>;
32
+
33
+ return (
34
+ <div>
35
+ <h1>{collection.title}</h1>
36
+ <img src={collection.logoImage} alt={collection.title} width="100" />
37
+ <h2>{product.name}</h2>
38
+ <img src={product.heroImage} alt={product.name} width="100" />
39
+ <p>{product.description}</p>
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export default ReactDemo;
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@proveanything/smartlinks",
3
+ "version": "1.0.0",
4
+ "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc"
9
+ },
10
+ "author": "Glenn Shoosmith",
11
+ "license": "MIT",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "dependencies": {
16
+ "cross-fetch": "^3.1.5"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^4.9.0"
20
+ }
21
+ }
package/src/index.ts ADDED
@@ -0,0 +1,171 @@
1
+ import fetch from 'cross-fetch';
2
+
3
+ ///////////////////////////
4
+ // Schema Interfaces
5
+ ///////////////////////////
6
+
7
+ /**
8
+ * Represents a Collection object.
9
+ */
10
+ export interface CollectionResponse {
11
+ /** Unique identifier for the collection */
12
+ id: string;
13
+ /** Machine‐readable name of the collection */
14
+ name: string;
15
+ /** Human‐readable title of the collection */
16
+ title: string;
17
+ /** URL to the collection’s logo image */
18
+ logoImage: string;
19
+ }
20
+
21
+ /**
22
+ * Represents a Product Item object.
23
+ */
24
+ export interface ProductResponse {
25
+ /** Unique identifier for the product */
26
+ id: string;
27
+ /** Name of the product */
28
+ name: string;
29
+ /** Detailed description of the product */
30
+ description: string;
31
+ /** URL to the product’s hero image */
32
+ heroImage: string;
33
+ }
34
+
35
+ /**
36
+ * Represents an App Configuration object.
37
+ */
38
+ export interface AppConfigurationResponse {
39
+ /** Unique identifier for the app configuration */
40
+ id: string;
41
+ /** Name of the app configuration */
42
+ name: string;
43
+ /** Key‐value pairs representing configuration settings */
44
+ settings?: Record<string, any>;
45
+ }
46
+
47
+ /**
48
+ * Represents a standardized error response.
49
+ */
50
+ export interface ErrorResponse {
51
+ /** Numeric error code */
52
+ code: number;
53
+ /** Human‐readable error message */
54
+ message: string;
55
+ }
56
+
57
+ ///////////////////////////
58
+ // ApiClient Class
59
+ ///////////////////////////
60
+
61
+ /**
62
+ * ApiClient for the Smartlinks API.
63
+ * Supports both browser (native fetch) and Node (using cross-fetch).
64
+ */
65
+ export class ApiClient {
66
+ private baseURL: string;
67
+ private apiKey?: string;
68
+ private bearerToken?: string;
69
+
70
+ /**
71
+ * Creates an instance of ApiClient.
72
+ * @param baseURL - The base URL of the Smartlinks API (e.g., https://smartlinks.app/api/v1)
73
+ * @param apiKey - (Optional) API key for X-API-Key header
74
+ * @param bearerToken - (Optional) Bearer token for AUTHORIZATION header
75
+ *
76
+ * @example
77
+ * // With both API key and bearer token
78
+ * const client = new ApiClient(
79
+ * 'https://smartlinks.app/api/v1',
80
+ * 'your-api-key',
81
+ * 'your-bearer-token'
82
+ * );
83
+ *
84
+ * // With only API key
85
+ * const client = new ApiClient(
86
+ * 'https://smartlinks.app/api/v1',
87
+ * 'your-api-key'
88
+ * );
89
+ *
90
+ * // With only bearer token
91
+ * const client = new ApiClient(
92
+ * 'https://smartlinks.app/api/v1',
93
+ * undefined,
94
+ * 'your-bearer-token'
95
+ * );
96
+ */
97
+ constructor(baseURL: string, apiKey?: string, bearerToken?: string) {
98
+ this.baseURL = baseURL.replace(/\/+$/, ''); // Trim trailing slash
99
+ this.apiKey = apiKey;
100
+ this.bearerToken = bearerToken;
101
+ }
102
+
103
+ /**
104
+ * Retrieves a single Collection by its ID.
105
+ * @param collectionId - Identifier of the collection
106
+ * @returns Promise resolving to a CollectionResponse object
107
+ * @throws ErrorResponse if the request fails
108
+ */
109
+ public async getCollection(collectionId: string): Promise<CollectionResponse> {
110
+ const path = `/public/collection/${encodeURIComponent(collectionId)}`;
111
+ return this.request<CollectionResponse>(path);
112
+ }
113
+
114
+ /**
115
+ * Retrieves a single Product Item by Collection ID and Product ID.
116
+ * @param collectionId - Identifier of the parent collection
117
+ * @param productId - Identifier of the product item
118
+ * @returns Promise resolving to a ProductResponse object
119
+ * @throws ErrorResponse if the request fails
120
+ */
121
+ public async getProductItem(collectionId: string, productId: string): Promise<ProductResponse> {
122
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}`;
123
+ return this.request<ProductResponse>(path);
124
+ }
125
+
126
+ /**
127
+ * Retrieves a single App Configuration by Collection ID and App ID.
128
+ * @param collectionId - Identifier of the parent collection
129
+ * @param appId - Identifier of the app configuration
130
+ * @returns Promise resolving to an AppConfigurationResponse object
131
+ * @throws ErrorResponse if the request fails
132
+ */
133
+ public async getAppConfiguration(collectionId: string, appId: string): Promise<AppConfigurationResponse> {
134
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/app/${encodeURIComponent(appId)}`;
135
+ return this.request<AppConfigurationResponse>(path);
136
+ }
137
+
138
+ /**
139
+ * Internal helper to perform a GET request and parse JSON.
140
+ * @param path - The path (relative to baseURL) to request
141
+ * @returns Promise resolving to the parsed JSON of type T
142
+ * @throws Error if network error or a non-2xx response is returned
143
+ */
144
+ private async request<T>(path: string): Promise<T> {
145
+ const url = `${this.baseURL}${path}`;
146
+ const headers: Record<string, string> = {
147
+ 'Content-Type': 'application/json',
148
+ };
149
+ if (this.apiKey) {
150
+ headers['X-API-Key'] = this.apiKey;
151
+ }
152
+ if (this.bearerToken) {
153
+ headers['AUTHORIZATION'] = `Bearer ${this.bearerToken}`;
154
+ }
155
+
156
+ const response = await fetch(url, { method: 'GET', headers });
157
+
158
+ if (!response.ok) {
159
+ // Attempt to parse error body; if it fails, throw generic
160
+ let errorBody: ErrorResponse;
161
+ try {
162
+ errorBody = (await response.json()) as ErrorResponse;
163
+ } catch {
164
+ throw new Error(`Request failed with status ${response.status}`);
165
+ }
166
+ throw new Error(`Error ${errorBody.code}: ${errorBody.message}`);
167
+ }
168
+
169
+ return (await response.json()) as T;
170
+ }
171
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "module": "ES6",
5
+ "moduleResolution": "node",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "forceConsistentCasingInFileNames": true
11
+ },
12
+ "include": [
13
+ "src/**/*"
14
+ ]
15
+ }