@proveanything/smartlinks 1.0.5 → 1.0.7

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 (49) hide show
  1. package/dist/api/asset.d.ts +21 -0
  2. package/dist/api/asset.js +100 -0
  3. package/dist/api/index.d.ts +1 -0
  4. package/dist/api/index.js +1 -0
  5. package/dist/http.d.ts +11 -0
  6. package/dist/http.js +47 -0
  7. package/dist/types/asset.d.ts +8 -0
  8. package/dist/types/asset.js +1 -0
  9. package/dist/types/index.d.ts +1 -0
  10. package/dist/types/index.js +1 -0
  11. package/docs/assets/navigation.js +1 -1
  12. package/docs/assets/search.js +1 -1
  13. package/docs/documentation.json +1395 -234
  14. package/docs/functions/appConfiguration.get.html +1 -1
  15. package/docs/functions/asset.getAllForCollection.html +1 -0
  16. package/docs/functions/asset.getAllForProduct.html +1 -0
  17. package/docs/functions/asset.getAllForProof.html +1 -0
  18. package/docs/functions/asset.getForCollection.html +1 -0
  19. package/docs/functions/asset.getForProduct.html +1 -0
  20. package/docs/functions/asset.getForProof.html +1 -0
  21. package/docs/functions/asset.uploadAsset.html +10 -0
  22. package/docs/functions/collection.get.html +1 -1
  23. package/docs/functions/initializeApi.html +1 -1
  24. package/docs/functions/product.get.html +1 -1
  25. package/docs/functions/product.getAll.html +1 -1
  26. package/docs/functions/proof.get.html +1 -1
  27. package/docs/functions/request.html +1 -1
  28. package/docs/index.html +50 -29
  29. package/docs/interfaces/AppConfigurationResponse.html +4 -4
  30. package/docs/interfaces/AssetResponse.html +5 -0
  31. package/docs/interfaces/CollectionResponse.html +5 -5
  32. package/docs/interfaces/ErrorResponse.html +3 -3
  33. package/docs/interfaces/ProductResponse.html +5 -5
  34. package/docs/interfaces/ProofResponse.html +8 -8
  35. package/docs/modules/appConfiguration.html +1 -1
  36. package/docs/modules/asset.html +8 -0
  37. package/docs/modules/collection.html +1 -1
  38. package/docs/modules/product.html +1 -1
  39. package/docs/modules/proof.html +1 -1
  40. package/docs/modules.html +2 -0
  41. package/examples/browser-demo.html +20 -9
  42. package/examples/node-demo.ts +18 -10
  43. package/examples/react-demo.tsx +29 -15
  44. package/package.json +1 -1
  45. package/src/api/asset.ts +133 -0
  46. package/src/api/index.ts +1 -0
  47. package/src/http.ts +54 -0
  48. package/src/types/asset.ts +9 -0
  49. package/src/types/index.ts +1 -0
@@ -1,25 +1,37 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { ApiClient, CollectionResponse, ProductResponse } from '@smartlinks/sdk';
2
+ import { initializeApi } from '../dist/index';
3
+ import { collection } from '../dist/api/collection';
4
+ import { product } from '../dist/api/product';
5
+ import { proof } from '../dist/api/proof';
6
+ import type { CollectionResponse } from '../dist/types/collection';
7
+ import type { ProductResponse } from '../dist/types/product';
8
+ import type { ProofResponse } from '../dist/types/proof';
3
9
 
4
10
  // 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)
11
+ const apiKey = 'YOUR_API_KEY'; // optional
12
+ const bearerToken = 'YOUR_BEARER_TOKEN'; // optional
7
13
 
8
- // Example: with both headers
9
- const client = new ApiClient('https://smartlinks.app/api/v1', apiKey, bearerToken);
14
+ initializeApi({
15
+ baseURL: 'https://smartlinks.app/api/v1',
16
+ apiKey,
17
+ bearerToken,
18
+ });
10
19
 
11
20
  const ReactDemo: React.FC = () => {
12
- const [collection, setCollection] = useState<CollectionResponse | null>(null);
13
- const [product, setProduct] = useState<ProductResponse | null>(null);
21
+ const [collectionData, setCollection] = useState<CollectionResponse | null>(null);
22
+ const [productData, setProduct] = useState<ProductResponse | null>(null);
23
+ const [proofData, setProof] = useState<ProofResponse | null>(null);
14
24
  const [error, setError] = useState<string | null>(null);
15
25
 
16
26
  useEffect(() => {
17
27
  async function fetchData() {
18
28
  try {
19
- const col = await client.getCollection('abc123');
20
- const prod = await client.getProductItem('abc123', 'prod789');
29
+ const col = await collection.get('abc123');
30
+ const prod = await product.get('abc123', 'prod789');
31
+ const prf = await proof.get('abc123', 'proof456');
21
32
  setCollection(col);
22
33
  setProduct(prod);
34
+ setProof(prf);
23
35
  } catch (err) {
24
36
  setError((err as Error).message);
25
37
  }
@@ -28,15 +40,17 @@ const ReactDemo: React.FC = () => {
28
40
  }, []);
29
41
 
30
42
  if (error) return <div>Error: {error}</div>;
31
- if (!collection || !product) return <div>Loading...</div>;
43
+ if (!collectionData || !productData || !proofData) return <div>Loading...</div>;
32
44
 
33
45
  return (
34
46
  <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>
47
+ <h1>{collectionData.title}</h1>
48
+ <img src={collectionData.logoImage} alt={collectionData.title} width="100" />
49
+ <h2>{productData.name}</h2>
50
+ <img src={productData.heroImage} alt={productData.name} width="100" />
51
+ <p>{productData.description}</p>
52
+ <h3>Proof</h3>
53
+ <pre>{JSON.stringify(proofData, null, 2)}</pre>
40
54
  </div>
41
55
  );
42
56
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,133 @@
1
+ import { request, post, getApiHeaders } from "../http"
2
+ import { AssetResponse } from "../types/asset"
3
+
4
+ export namespace asset {
5
+ // Collection-level
6
+ export async function getForCollection(
7
+ collectionId: string,
8
+ assetId: string
9
+ ): Promise<AssetResponse> {
10
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/asset/${encodeURIComponent(assetId)}`
11
+ return request<AssetResponse>(path)
12
+ }
13
+
14
+ export async function getAllForCollection(
15
+ collectionId: string
16
+ ): Promise<AssetResponse[]> {
17
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/asset`
18
+ return request<AssetResponse[]>(path)
19
+ }
20
+
21
+ // Product-level
22
+ export async function getForProduct(
23
+ collectionId: string,
24
+ productId: string,
25
+ assetId: string
26
+ ): Promise<AssetResponse> {
27
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/asset/${encodeURIComponent(assetId)}`
28
+ return request<AssetResponse>(path)
29
+ }
30
+
31
+ export async function getAllForProduct(
32
+ collectionId: string,
33
+ productId: string
34
+ ): Promise<AssetResponse[]> {
35
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/asset`
36
+ return request<AssetResponse[]>(path)
37
+ }
38
+
39
+ // Proof-level
40
+ export async function getForProof(
41
+ collectionId: string,
42
+ productId: string,
43
+ proofId: string,
44
+ assetId: string
45
+ ): Promise<AssetResponse> {
46
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/asset/${encodeURIComponent(assetId)}`
47
+ return request<AssetResponse>(path)
48
+ }
49
+
50
+ export async function getAllForProof(
51
+ collectionId: string,
52
+ productId: string,
53
+ proofId: string,
54
+ appId?: string
55
+ ): Promise<AssetResponse[]> {
56
+ let path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/asset`
57
+ if (appId) {
58
+ path += `?appId=${encodeURIComponent(appId)}`
59
+ }
60
+ return request<AssetResponse[]>(path)
61
+ }
62
+
63
+ /**
64
+ * Uploads an asset file to a proof, with optional extraData as JSON.
65
+ * Supports progress reporting via onProgress callback (browser only).
66
+ * @param collectionId - The collection ID
67
+ * @param productId - The product ID
68
+ * @param proofId - The proof ID
69
+ * @param file - The file to upload
70
+ * @param extraData - Arbitrary extra data to include (will be stringified as JSON)
71
+ * @param onProgress - Optional callback for upload progress (0-100)
72
+ * @returns Promise resolving to an AssetResponse object
73
+ */
74
+ export async function uploadAsset(
75
+ collectionId: string,
76
+ productId: string,
77
+ proofId: string,
78
+ file: File,
79
+ extraData?: Record<string, any>,
80
+ onProgress?: (percent: number) => void
81
+ ): Promise<AssetResponse> {
82
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/asset`
83
+ const url = (typeof window !== "undefined" && (window as any).SMARTLINKS_API_BASEURL)
84
+ ? (window as any).SMARTLINKS_API_BASEURL + path
85
+ : path // fallback for SSR or Node
86
+
87
+ const formData = new FormData()
88
+ formData.append("file", file)
89
+ if (extraData) {
90
+ formData.append("extraData", JSON.stringify(extraData))
91
+ }
92
+
93
+ // Use getApiHeaders from http module
94
+ const headers = getApiHeaders ? getApiHeaders() : {}
95
+
96
+ return new Promise<AssetResponse>((resolve, reject) => {
97
+ const xhr = new XMLHttpRequest()
98
+ xhr.open("POST", url)
99
+
100
+ // Set headers for API key and bearer token if available
101
+ for (const [key, value] of Object.entries(headers)) {
102
+ xhr.setRequestHeader(key, value)
103
+ }
104
+
105
+ xhr.upload.onprogress = (event) => {
106
+ if (onProgress && event.lengthComputable) {
107
+ const percent = Math.round((event.loaded / event.total) * 100)
108
+ onProgress(percent)
109
+ }
110
+ }
111
+
112
+ xhr.onload = () => {
113
+ if (xhr.status >= 200 && xhr.status < 300) {
114
+ try {
115
+ resolve(JSON.parse(xhr.responseText) as AssetResponse)
116
+ } catch (e) {
117
+ reject(new Error("Failed to parse server response"))
118
+ }
119
+ } else {
120
+ try {
121
+ const errBody = JSON.parse(xhr.responseText)
122
+ reject(new Error(`Error ${errBody.code}: ${errBody.message}`))
123
+ } catch {
124
+ reject(new Error(`Asset upload failed with status ${xhr.status}`))
125
+ }
126
+ }
127
+ }
128
+
129
+ xhr.onerror = () => reject(new Error("Network error during asset upload"))
130
+ xhr.send(formData)
131
+ })
132
+ }
133
+ }
package/src/api/index.ts CHANGED
@@ -4,3 +4,4 @@ export { collection } from "./collection"
4
4
  export { product } from "./product"
5
5
  export { proof } from "./proof"
6
6
  export { appConfiguration } from "./appConfiguration"
7
+ export { asset } from "./asset"
package/src/http.ts CHANGED
@@ -62,3 +62,57 @@ export async function request<T>(path: string): Promise<T> {
62
62
 
63
63
  return (await response.json()) as T
64
64
  }
65
+
66
+ /**
67
+ * Internal helper that performs a POST request to `${baseURL}${path}`,
68
+ * injecting headers for apiKey or bearerToken if present.
69
+ * If body is FormData, Content-Type is not set.
70
+ * Returns the parsed JSON as T, or throws an Error.
71
+ */
72
+ export async function post<T>(
73
+ path: string,
74
+ body: any,
75
+ extraHeaders?: Record<string, string>
76
+ ): Promise<T> {
77
+ if (!baseURL) {
78
+ throw new Error("HTTP client is not initialized. Call initializeApi(...) first.")
79
+ }
80
+
81
+ const url = `${baseURL}${path}`
82
+ const headers: Record<string, string> = extraHeaders ? { ...extraHeaders } : {}
83
+
84
+ if (apiKey) headers["X-API-Key"] = apiKey
85
+ if (bearerToken) headers["AUTHORIZATION"] = `Bearer ${bearerToken}`
86
+
87
+ // Only set Content-Type for non-FormData bodies
88
+ if (!(body instanceof FormData)) {
89
+ headers["Content-Type"] = "application/json"
90
+ }
91
+
92
+ const response = await fetch(url, {
93
+ method: "POST",
94
+ headers,
95
+ body: body instanceof FormData ? body : JSON.stringify(body),
96
+ })
97
+
98
+ if (!response.ok) {
99
+ try {
100
+ const errBody = (await response.json()) as import("./types/error").ErrorResponse
101
+ throw new Error(`Error ${errBody.code}: ${errBody.message}`)
102
+ } catch {
103
+ throw new Error(`Request to ${url} failed with status ${response.status}`)
104
+ }
105
+ }
106
+
107
+ return (await response.json()) as T
108
+ }
109
+
110
+ /**
111
+ * Returns the common headers used for API requests, including apiKey and bearerToken if set.
112
+ */
113
+ export function getApiHeaders(): Record<string, string> {
114
+ const headers: Record<string, string> = {}
115
+ if (apiKey) headers["X-API-Key"] = apiKey
116
+ if (bearerToken) headers["AUTHORIZATION"] = `Bearer ${bearerToken}`
117
+ return headers
118
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Represents an Asset object.
3
+ */
4
+ export interface AssetResponse {
5
+ id: string
6
+ name: string
7
+ url: string
8
+ // ...add more fields as needed...
9
+ }
@@ -6,3 +6,4 @@ export * from "./product"
6
6
  export * from "./proof"
7
7
  export * from "./appConfiguration"
8
8
  export * from "./error"
9
+ export * from "./asset"