@proveanything/smartlinks 1.0.6 → 1.0.8

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 (52) hide show
  1. package/debug.log +6 -0
  2. package/dist/api/asset.d.ts +14 -2
  3. package/dist/api/asset.js +65 -5
  4. package/dist/api/attestation.d.ts +23 -0
  5. package/dist/api/attestation.js +44 -0
  6. package/dist/api/index.d.ts +1 -0
  7. package/dist/api/index.js +1 -0
  8. package/dist/http.d.ts +30 -0
  9. package/dist/http.js +156 -0
  10. package/dist/types/attestation.d.ts +16 -0
  11. package/dist/types/attestation.js +1 -0
  12. package/docs/assets/navigation.js +1 -1
  13. package/docs/assets/search.js +1 -1
  14. package/docs/documentation.json +1240 -211
  15. package/docs/functions/appConfiguration.get.html +1 -1
  16. package/docs/functions/asset.getAllForCollection.html +1 -1
  17. package/docs/functions/asset.getAllForProduct.html +1 -1
  18. package/docs/functions/asset.getAllForProof.html +1 -1
  19. package/docs/functions/asset.getForCollection.html +1 -1
  20. package/docs/functions/asset.getForProduct.html +1 -1
  21. package/docs/functions/asset.getForProof.html +1 -1
  22. package/docs/functions/asset.uploadAsset.html +10 -0
  23. package/docs/functions/attestation.create.html +2 -0
  24. package/docs/functions/attestation.get.html +2 -0
  25. package/docs/functions/attestation.getAll.html +2 -0
  26. package/docs/functions/attestation.remove.html +2 -0
  27. package/docs/functions/attestation.update.html +2 -0
  28. package/docs/functions/collection.get.html +1 -1
  29. package/docs/functions/initializeApi.html +1 -1
  30. package/docs/functions/product.get.html +1 -1
  31. package/docs/functions/product.getAll.html +1 -1
  32. package/docs/functions/proof.get.html +1 -1
  33. package/docs/functions/request.html +1 -1
  34. package/docs/interfaces/AppConfigurationResponse.html +4 -4
  35. package/docs/interfaces/AssetResponse.html +2 -2
  36. package/docs/interfaces/CollectionResponse.html +5 -5
  37. package/docs/interfaces/ErrorResponse.html +3 -3
  38. package/docs/interfaces/ProductResponse.html +5 -5
  39. package/docs/interfaces/ProofResponse.html +8 -8
  40. package/docs/modules/appConfiguration.html +1 -1
  41. package/docs/modules/asset.html +2 -1
  42. package/docs/modules/attestation.html +6 -0
  43. package/docs/modules/collection.html +1 -1
  44. package/docs/modules/product.html +1 -1
  45. package/docs/modules/proof.html +1 -1
  46. package/docs/modules.html +1 -0
  47. package/package.json +1 -1
  48. package/src/api/asset.ts +76 -3
  49. package/src/api/attestation.ts +69 -0
  50. package/src/api/index.ts +1 -0
  51. package/src/http.ts +190 -0
  52. package/src/types/attestation.ts +18 -0
package/src/api/asset.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { request } from "../http"
1
+ import { request, post, getApiHeaders } from "../http"
2
2
  import { AssetResponse } from "../types/asset"
3
3
 
4
4
  export namespace asset {
@@ -39,22 +39,95 @@ export namespace asset {
39
39
  // Proof-level
40
40
  export async function getForProof(
41
41
  collectionId: string,
42
+ productId: string,
42
43
  proofId: string,
43
44
  assetId: string
44
45
  ): Promise<AssetResponse> {
45
- const path = `/public/collection/${encodeURIComponent(collectionId)}/proof/${encodeURIComponent(proofId)}/asset/${encodeURIComponent(assetId)}`
46
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/asset/${encodeURIComponent(assetId)}`
46
47
  return request<AssetResponse>(path)
47
48
  }
48
49
 
49
50
  export async function getAllForProof(
50
51
  collectionId: string,
52
+ productId: string,
51
53
  proofId: string,
52
54
  appId?: string
53
55
  ): Promise<AssetResponse[]> {
54
- let path = `/public/collection/${encodeURIComponent(collectionId)}/proof/${encodeURIComponent(proofId)}/asset`
56
+ let path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/asset`
55
57
  if (appId) {
56
58
  path += `?appId=${encodeURIComponent(appId)}`
57
59
  }
58
60
  return request<AssetResponse[]>(path)
59
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
+ }
60
133
  }
@@ -0,0 +1,69 @@
1
+ import { request, post, put, del } from "../http"
2
+ import type { AttestationResponse, AttestationCreateRequest, AttestationUpdateRequest } from "../types/attestation"
3
+
4
+ export namespace attestation {
5
+ /**
6
+ * Get all attestations for a proof.
7
+ */
8
+ export async function getAll(
9
+ collectionId: string,
10
+ productId: string,
11
+ proofId: string
12
+ ): Promise<AttestationResponse[]> {
13
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/attestation`
14
+ return request<AttestationResponse[]>(path)
15
+ }
16
+
17
+ /**
18
+ * Get a single attestation by ID.
19
+ */
20
+ export async function get(
21
+ collectionId: string,
22
+ productId: string,
23
+ proofId: string,
24
+ attestationId: string
25
+ ): Promise<AttestationResponse> {
26
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/attestation/${encodeURIComponent(attestationId)}`
27
+ return request<AttestationResponse>(path)
28
+ }
29
+
30
+ /**
31
+ * Create a new attestation for a proof.
32
+ */
33
+ export async function create(
34
+ collectionId: string,
35
+ productId: string,
36
+ proofId: string,
37
+ data: AttestationCreateRequest
38
+ ): Promise<AttestationResponse> {
39
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/attestation`
40
+ return post<AttestationResponse>(path, data)
41
+ }
42
+
43
+ /**
44
+ * Update an attestation.
45
+ */
46
+ export async function update(
47
+ collectionId: string,
48
+ productId: string,
49
+ proofId: string,
50
+ attestationId: string,
51
+ data: AttestationUpdateRequest
52
+ ): Promise<AttestationResponse> {
53
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/attestation/${encodeURIComponent(attestationId)}`
54
+ return put<AttestationResponse>(path, data)
55
+ }
56
+
57
+ /**
58
+ * Delete an attestation.
59
+ */
60
+ export async function remove(
61
+ collectionId: string,
62
+ productId: string,
63
+ proofId: string,
64
+ attestationId: string
65
+ ): Promise<void> {
66
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/product/${encodeURIComponent(productId)}/proof/${encodeURIComponent(proofId)}/attestation/${encodeURIComponent(attestationId)}`
67
+ return del<void>(path)
68
+ }
69
+ }
package/src/api/index.ts CHANGED
@@ -5,3 +5,4 @@ export { product } from "./product"
5
5
  export { proof } from "./proof"
6
6
  export { appConfiguration } from "./appConfiguration"
7
7
  export { asset } from "./asset"
8
+ export { attestation } from "./attestation"
package/src/http.ts CHANGED
@@ -62,3 +62,193 @@ 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
+ * Internal helper that performs a PUT request to `${baseURL}${path}`,
112
+ * injecting headers for apiKey or bearerToken if present.
113
+ * If body is FormData, Content-Type is not set.
114
+ * Returns the parsed JSON as T, or throws an Error.
115
+ */
116
+ export async function put<T>(
117
+ path: string,
118
+ body: any,
119
+ extraHeaders?: Record<string, string>
120
+ ): Promise<T> {
121
+ if (!baseURL) {
122
+ throw new Error("HTTP client is not initialized. Call initializeApi(...) first.")
123
+ }
124
+
125
+ const url = `${baseURL}${path}`
126
+ const headers: Record<string, string> = extraHeaders ? { ...extraHeaders } : {}
127
+
128
+ if (apiKey) headers["X-API-Key"] = apiKey
129
+ if (bearerToken) headers["AUTHORIZATION"] = `Bearer ${bearerToken}`
130
+
131
+ // Only set Content-Type for non-FormData bodies
132
+ if (!(body instanceof FormData)) {
133
+ headers["Content-Type"] = "application/json"
134
+ }
135
+
136
+ const response = await fetch(url, {
137
+ method: "PUT",
138
+ headers,
139
+ body: body instanceof FormData ? body : JSON.stringify(body),
140
+ })
141
+
142
+ if (!response.ok) {
143
+ try {
144
+ const errBody = (await response.json()) as import("./types/error").ErrorResponse
145
+ throw new Error(`Error ${errBody.code}: ${errBody.message}`)
146
+ } catch {
147
+ throw new Error(`Request to ${url} failed with status ${response.status}`)
148
+ }
149
+ }
150
+
151
+ return (await response.json()) as T
152
+ }
153
+
154
+ /**
155
+ * Internal helper that performs a request to `${baseURL}${path}` with custom options,
156
+ * injecting headers for apiKey or bearerToken if present.
157
+ * Returns the parsed JSON as T, or throws an Error.
158
+ */
159
+ export async function requestWithOptions<T>(
160
+ path: string,
161
+ options: RequestInit
162
+ ): Promise<T> {
163
+ if (!baseURL) {
164
+ throw new Error("HTTP client is not initialized. Call initializeApi(...) first.")
165
+ }
166
+ const url = `${baseURL}${path}`
167
+
168
+ // Safely merge headers, converting Headers/init to Record<string, string>
169
+ let extraHeaders: Record<string, string> = {}
170
+ if (options.headers) {
171
+ if (options.headers instanceof Headers) {
172
+ options.headers.forEach((value, key) => {
173
+ extraHeaders[key] = value
174
+ })
175
+ } else if (Array.isArray(options.headers)) {
176
+ for (const [key, value] of options.headers) {
177
+ extraHeaders[key] = value
178
+ }
179
+ } else {
180
+ extraHeaders = { ...(options.headers as Record<string, string>) }
181
+ }
182
+ }
183
+
184
+ const headers: Record<string, string> = {
185
+ "Content-Type": "application/json",
186
+ ...(apiKey ? { "X-API-Key": apiKey } : {}),
187
+ ...(bearerToken ? { "AUTHORIZATION": `Bearer ${bearerToken}` } : {}),
188
+ ...extraHeaders,
189
+ }
190
+
191
+ const response = await fetch(url, {
192
+ ...options,
193
+ headers,
194
+ })
195
+
196
+ if (!response.ok) {
197
+ try {
198
+ const errBody = (await response.json()) as import("./types/error").ErrorResponse
199
+ throw new Error(`Error ${errBody.code}: ${errBody.message}`)
200
+ } catch {
201
+ throw new Error(`Request to ${url} failed with status ${response.status}`)
202
+ }
203
+ }
204
+
205
+ return (await response.json()) as T
206
+ }
207
+
208
+ /**
209
+ * Internal helper that performs a DELETE request to `${baseURL}${path}`,
210
+ * injecting headers for apiKey or bearerToken if present.
211
+ * Returns the parsed JSON as T, or throws an Error.
212
+ */
213
+ export async function del<T>(
214
+ path: string,
215
+ extraHeaders?: Record<string, string>
216
+ ): Promise<T> {
217
+ if (!baseURL) {
218
+ throw new Error("HTTP client is not initialized. Call initializeApi(...) first.")
219
+ }
220
+
221
+ const url = `${baseURL}${path}`
222
+ const headers: Record<string, string> = extraHeaders ? { ...extraHeaders } : {}
223
+
224
+ if (apiKey) headers["X-API-Key"] = apiKey
225
+ if (bearerToken) headers["AUTHORIZATION"] = `Bearer ${bearerToken}`
226
+
227
+ const response = await fetch(url, {
228
+ method: "DELETE",
229
+ headers,
230
+ })
231
+
232
+ if (!response.ok) {
233
+ try {
234
+ const errBody = (await response.json()) as import("./types/error").ErrorResponse
235
+ throw new Error(`Error ${errBody.code}: ${errBody.message}`)
236
+ } catch {
237
+ throw new Error(`Request to ${url} failed with status ${response.status}`)
238
+ }
239
+ }
240
+
241
+ // If the response is empty, just return undefined
242
+ if (response.status === 204) return undefined as T
243
+ return (await response.json()) as T
244
+ }
245
+
246
+ /**
247
+ * Returns the common headers used for API requests, including apiKey and bearerToken if set.
248
+ */
249
+ export function getApiHeaders(): Record<string, string> {
250
+ const headers: Record<string, string> = {}
251
+ if (apiKey) headers["X-API-Key"] = apiKey
252
+ if (bearerToken) headers["AUTHORIZATION"] = `Bearer ${bearerToken}`
253
+ return headers
254
+ }
@@ -0,0 +1,18 @@
1
+ export interface AttestationResponse {
2
+ id: string
3
+ proofId: string
4
+ createdAt: string
5
+ updatedAt: string
6
+ type: string
7
+ data: Record<string, any>
8
+ }
9
+
10
+ export interface AttestationCreateRequest {
11
+ type: string
12
+ data: Record<string, any>
13
+ }
14
+
15
+ export interface AttestationUpdateRequest {
16
+ type?: string
17
+ data?: Record<string, any>
18
+ }