@viu/emporix-sdk 1.0.0 → 2.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/CHANGELOG.md +38 -0
- package/README.md +13 -0
- package/dist/cart.d.cts +1 -1
- package/dist/cart.d.ts +1 -1
- package/dist/category.d.cts +1 -1
- package/dist/category.d.ts +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/chunk-WSXRUYBE.js +248 -0
- package/dist/chunk-WSXRUYBE.js.map +1 -0
- package/dist/companies.d.cts +1 -1
- package/dist/companies.d.ts +1 -1
- package/dist/contacts.d.cts +1 -1
- package/dist/contacts.d.ts +1 -1
- package/dist/{context-vKgzZ-5f.d.cts → context-mMTqsW1Z.d.cts} +15 -0
- package/dist/{context-vKgzZ-5f.d.ts → context-mMTqsW1Z.d.ts} +15 -0
- package/dist/customer-groups.d.cts +1 -1
- package/dist/customer-groups.d.ts +1 -1
- package/dist/customer.d.cts +1 -1
- package/dist/customer.d.ts +1 -1
- package/dist/index.cjs +186 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +53 -2
- package/dist/index.js.map +1 -1
- package/dist/locations.d.cts +1 -1
- package/dist/locations.d.ts +1 -1
- package/dist/media.cjs +218 -9
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +103 -7
- package/dist/media.d.ts +103 -7
- package/dist/media.js +2 -1
- package/dist/orders.d.cts +1 -1
- package/dist/orders.d.ts +1 -1
- package/dist/payment.d.cts +1 -1
- package/dist/payment.d.ts +1 -1
- package/dist/price.d.cts +1 -1
- package/dist/price.d.ts +1 -1
- package/dist/product.d.cts +1 -1
- package/dist/product.d.ts +1 -1
- package/dist/segment.d.cts +1 -1
- package/dist/segment.d.ts +1 -1
- package/package.json +2 -2
- package/dist/chunk-F3WAQH2E.js +0 -120
- package/dist/chunk-F3WAQH2E.js.map +0 -1
package/dist/media.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.js';
|
|
2
2
|
|
|
3
3
|
type MetadataUpdate = {
|
|
4
4
|
/**
|
|
@@ -156,9 +156,44 @@ type AssetUpdateBlob = Asset$1 & {
|
|
|
156
156
|
/** Generated media types (caller sends the exact wire shape). */
|
|
157
157
|
type AssetCreateBlobInput = AssetCreateBlob;
|
|
158
158
|
type AssetCreateLinkInput = AssetCreateLink;
|
|
159
|
+
type AssetUpdateBlobInput = AssetUpdateBlob;
|
|
160
|
+
type AssetUpdateLinkInput = AssetUpdateLink;
|
|
159
161
|
type AssetUpdateInput = AssetUpdateBlob | AssetUpdateLink;
|
|
160
162
|
type Asset = GetAsset;
|
|
161
163
|
type AssetRefId = RefId;
|
|
164
|
+
/**
|
|
165
|
+
* Filter / pagination options for {@link MediaService.list}. The explicit
|
|
166
|
+
* fields are typed for autocomplete; the index signature stays open so
|
|
167
|
+
* Emporix `q`-syntax filters like `"refIds.id"` can be passed verbatim.
|
|
168
|
+
*/
|
|
169
|
+
interface ListAssetsQuery {
|
|
170
|
+
pageNumber?: number;
|
|
171
|
+
pageSize?: number;
|
|
172
|
+
/** Emporix sort syntax, e.g. `"name,metadata.createdAt:desc"`. */
|
|
173
|
+
sort?: string;
|
|
174
|
+
/** Emporix `q`-syntax filter, e.g. `"name:hero"`. */
|
|
175
|
+
q?: string;
|
|
176
|
+
[key: string]: string | number | undefined;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Result of {@link MediaService.download}. The endpoint's behaviour depends
|
|
180
|
+
* on the asset's `access`:
|
|
181
|
+
* - `PUBLIC` assets respond with a 30x redirect whose `Location` header
|
|
182
|
+
* carries the externally-cacheable storage URL — useful when the
|
|
183
|
+
* storefront wants to send the user there directly.
|
|
184
|
+
* - `PRIVATE` assets respond with the raw bytes (plus an `ETag` header
|
|
185
|
+
* for caching). The asset is delivered through Cloudinary behind the
|
|
186
|
+
* server-side service token, never publicly addressable.
|
|
187
|
+
*/
|
|
188
|
+
type DownloadResult = {
|
|
189
|
+
kind: "redirect";
|
|
190
|
+
url: string;
|
|
191
|
+
} | {
|
|
192
|
+
kind: "bytes";
|
|
193
|
+
data: ArrayBuffer;
|
|
194
|
+
etag?: string;
|
|
195
|
+
contentType?: string;
|
|
196
|
+
};
|
|
162
197
|
declare function isProductRef(r: AssetRefId, productId: string): boolean;
|
|
163
198
|
/**
|
|
164
199
|
* Media assets (BLOB/LINK). All endpoints require a backend-only scope
|
|
@@ -179,14 +214,61 @@ declare class MediaService {
|
|
|
179
214
|
}, auth?: AuthContext): Promise<{
|
|
180
215
|
id: string;
|
|
181
216
|
}>;
|
|
182
|
-
/**
|
|
183
|
-
|
|
217
|
+
/**
|
|
218
|
+
* List assets, wrapped in the shared {@link PaginatedItems} envelope so
|
|
219
|
+
* callers can iterate over pages consistently with the rest of the SDK.
|
|
220
|
+
* `hasNextPage` is the standard SDK heuristic: `true` when the returned
|
|
221
|
+
* page is full (`items.length === requested pageSize`). Pagination
|
|
222
|
+
* defaults match Emporix's server defaults (`pageNumber: 1`,
|
|
223
|
+
* `pageSize: 60`) so an empty `query` produces stable expectations.
|
|
224
|
+
*/
|
|
225
|
+
list(query?: ListAssetsQuery, auth?: AuthContext): Promise<PaginatedItems<Asset>>;
|
|
184
226
|
/** Fetch an asset by id. */
|
|
185
227
|
get(assetId: string, auth?: AuthContext): Promise<Asset>;
|
|
186
|
-
/**
|
|
187
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Update an asset. The input is a discriminated union mirroring
|
|
230
|
+
* {@link create}:
|
|
231
|
+
* - `{ kind: "json", body }` — metadata-only patch (BLOB or LINK).
|
|
232
|
+
* Sends `application/json`. Used for `refIds`, `details`, `metadata`,
|
|
233
|
+
* or `url` changes.
|
|
234
|
+
* - `{ kind: "blob", file, body }` — replaces the BLOB file content
|
|
235
|
+
* (max 10MB) AND patches metadata in the same request. Sends
|
|
236
|
+
* `multipart/form-data`.
|
|
237
|
+
*
|
|
238
|
+
* `type` and `access` are immutable per Emporix — they must match the
|
|
239
|
+
* existing asset's values. Optimistic-locking is via `body.metadata.version`;
|
|
240
|
+
* the server returns 409 Conflict on a stale version.
|
|
241
|
+
*/
|
|
242
|
+
update(assetId: string, input: {
|
|
243
|
+
kind: "json";
|
|
244
|
+
body: AssetUpdateInput;
|
|
245
|
+
} | {
|
|
246
|
+
kind: "blob";
|
|
247
|
+
file: Blob;
|
|
248
|
+
body: AssetUpdateBlobInput;
|
|
249
|
+
}, auth?: AuthContext): Promise<Asset>;
|
|
188
250
|
/** Remove an asset. */
|
|
189
251
|
remove(assetId: string, auth?: AuthContext): Promise<void>;
|
|
252
|
+
/**
|
|
253
|
+
* Download an asset by id. Returns a discriminated union:
|
|
254
|
+
* - `{ kind: "redirect", url }` for `PUBLIC` assets (server-side 30x with
|
|
255
|
+
* the storage URL in `Location`).
|
|
256
|
+
* - `{ kind: "bytes", data }` for `PRIVATE` assets (server-side 200 with
|
|
257
|
+
* the asset bytes; `etag` + `contentType` headers are exposed for
|
|
258
|
+
* caching). When the server reports `text/plain` Content-Type (the
|
|
259
|
+
* OpenAPI-documented format), the SDK decodes the base64 stream into
|
|
260
|
+
* an `ArrayBuffer` transparently; binary Content-Types are passed
|
|
261
|
+
* through verbatim.
|
|
262
|
+
*
|
|
263
|
+
* Implementation note: uses `redirect: "manual"` so the redirect-location
|
|
264
|
+
* is observable. In Node.js this works; in a browser the redirect Location
|
|
265
|
+
* is intentionally hidden by fetch — there, `PUBLIC` downloads will
|
|
266
|
+
* surface as an opaque-redirect and the SDK throws. Browser code should
|
|
267
|
+
* use the asset's `url` field from `get()` for `LINK` assets, or the
|
|
268
|
+
* direct storage URL for `PUBLIC` `BLOB` assets (typically delivered via
|
|
269
|
+
* an `<img>` tag rather than `download()`).
|
|
270
|
+
*/
|
|
271
|
+
download(assetId: string, auth?: AuthContext): Promise<DownloadResult>;
|
|
190
272
|
/** Multipart upload sugar: builds `AssetCreateBlob` from input. */
|
|
191
273
|
uploadFile(input: {
|
|
192
274
|
file: Blob;
|
|
@@ -197,6 +279,20 @@ declare class MediaService {
|
|
|
197
279
|
}, auth?: AuthContext): Promise<{
|
|
198
280
|
id: string;
|
|
199
281
|
}>;
|
|
282
|
+
/**
|
|
283
|
+
* Replace the file content of an existing BLOB asset. Sugar over
|
|
284
|
+
* {@link update} with `kind: "blob"`. `access` is required because the
|
|
285
|
+
* field is immutable and the server validates that the patch matches.
|
|
286
|
+
* Pass `version` from `asset.metadata.version` if you want optimistic
|
|
287
|
+
* locking (recommended when concurrent writers are possible).
|
|
288
|
+
*/
|
|
289
|
+
replaceFile(assetId: string, input: {
|
|
290
|
+
file: Blob;
|
|
291
|
+
access: "PUBLIC" | "PRIVATE";
|
|
292
|
+
filename?: string;
|
|
293
|
+
mimeType?: string;
|
|
294
|
+
version?: number;
|
|
295
|
+
}, auth?: AuthContext): Promise<Asset>;
|
|
200
296
|
/** External-URL sugar: builds `AssetCreateLink`. */
|
|
201
297
|
link(input: {
|
|
202
298
|
url: string;
|
|
@@ -210,10 +306,10 @@ declare class MediaService {
|
|
|
210
306
|
/** Remove a PRODUCT refId from an asset (no-op if absent). */
|
|
211
307
|
detachFromProduct(assetId: string, productId: string, auth?: AuthContext): Promise<Asset>;
|
|
212
308
|
/** Convenience: list assets attached to a product (server-side filter). */
|
|
213
|
-
listForProduct(productId: string, auth?: AuthContext): Promise<Asset
|
|
309
|
+
listForProduct(productId: string, auth?: AuthContext): Promise<PaginatedItems<Asset>>;
|
|
214
310
|
}
|
|
215
311
|
declare const _internalMedia: {
|
|
216
312
|
isProductRef: typeof isProductRef;
|
|
217
313
|
};
|
|
218
314
|
|
|
219
|
-
export { type Asset, type AssetCreateBlobInput, type AssetCreateLinkInput, type AssetRefId, type AssetUpdateInput, MediaService, _internalMedia };
|
|
315
|
+
export { type Asset, type AssetCreateBlobInput, type AssetCreateLinkInput, type AssetRefId, type AssetUpdateBlobInput, type AssetUpdateInput, type AssetUpdateLinkInput, type DownloadResult, type ListAssetsQuery, MediaService, _internalMedia };
|
package/dist/media.js
CHANGED
package/dist/orders.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Hand-written mirror of the Emporix Order-v2 schemas (storefront-relevant
|
package/dist/orders.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Hand-written mirror of the Emporix Order-v2 schemas (storefront-relevant
|
package/dist/payment.d.cts
CHANGED
package/dist/payment.d.ts
CHANGED
package/dist/price.d.cts
CHANGED
package/dist/price.d.ts
CHANGED
package/dist/product.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Localized value which can have different structure which depends on provided `Content-Language` header.
|
package/dist/product.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Localized value which can have different structure which depends on provided `Content-Language` header.
|
package/dist/segment.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.cjs';
|
|
2
2
|
import { ProductService } from './product.cjs';
|
|
3
3
|
import { CategoryService } from './category.cjs';
|
|
4
4
|
|
package/dist/segment.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-
|
|
1
|
+
import { C as ClientContext, b as AuthContext, P as PaginatedItems } from './context-mMTqsW1Z.js';
|
|
2
2
|
import { ProductService } from './product.js';
|
|
3
3
|
import { CategoryService } from './category.js';
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viu/emporix-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "TypeScript SDK for the Emporix Commerce Engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
},
|
|
115
115
|
"publishConfig": {
|
|
116
116
|
"access": "public",
|
|
117
|
-
"provenance":
|
|
117
|
+
"provenance": true
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
120
|
"@hey-api/openapi-ts": "^0.64.0",
|
package/dist/chunk-F3WAQH2E.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// src/services/media.ts
|
|
2
|
-
var SERVICE = { kind: "service" };
|
|
3
|
-
function isProductRef(r, productId) {
|
|
4
|
-
return r.type === "PRODUCT" && r.id === productId;
|
|
5
|
-
}
|
|
6
|
-
var MediaService = class {
|
|
7
|
-
constructor(ctx) {
|
|
8
|
-
this.ctx = ctx;
|
|
9
|
-
}
|
|
10
|
-
ctx;
|
|
11
|
-
base() {
|
|
12
|
-
return `/media/${this.ctx.tenant}/assets`;
|
|
13
|
-
}
|
|
14
|
-
/** Create an asset. BLOB uploads via multipart; LINK via JSON. */
|
|
15
|
-
async create(input, auth = SERVICE) {
|
|
16
|
-
if (input.kind === "blob") {
|
|
17
|
-
const fd = new FormData();
|
|
18
|
-
fd.set("file", input.file);
|
|
19
|
-
fd.set("body", JSON.stringify(input.body));
|
|
20
|
-
return this.ctx.http.request({
|
|
21
|
-
method: "POST",
|
|
22
|
-
path: this.base(),
|
|
23
|
-
auth,
|
|
24
|
-
body: fd
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
return this.ctx.http.request({
|
|
28
|
-
method: "POST",
|
|
29
|
-
path: this.base(),
|
|
30
|
-
auth,
|
|
31
|
-
body: input.body
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
/** List assets. Optional `query` is passed through to Emporix verbatim. */
|
|
35
|
-
async list(query, auth = SERVICE) {
|
|
36
|
-
return this.ctx.http.request({
|
|
37
|
-
method: "GET",
|
|
38
|
-
path: this.base(),
|
|
39
|
-
auth,
|
|
40
|
-
...query ? { query } : {}
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
/** Fetch an asset by id. */
|
|
44
|
-
async get(assetId, auth = SERVICE) {
|
|
45
|
-
return this.ctx.http.request({
|
|
46
|
-
method: "GET",
|
|
47
|
-
path: `${this.base()}/${assetId}`,
|
|
48
|
-
auth
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
/** Update an asset (e.g. swap `refIds` or `access`). */
|
|
52
|
-
async update(assetId, patch, auth = SERVICE) {
|
|
53
|
-
return this.ctx.http.request({
|
|
54
|
-
method: "PUT",
|
|
55
|
-
path: `${this.base()}/${assetId}`,
|
|
56
|
-
auth,
|
|
57
|
-
body: patch
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
/** Remove an asset. */
|
|
61
|
-
async remove(assetId, auth = SERVICE) {
|
|
62
|
-
await this.ctx.http.request({
|
|
63
|
-
method: "DELETE",
|
|
64
|
-
path: `${this.base()}/${assetId}`,
|
|
65
|
-
auth
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
/** Multipart upload sugar: builds `AssetCreateBlob` from input. */
|
|
69
|
-
async uploadFile(input, auth = SERVICE) {
|
|
70
|
-
const body = {
|
|
71
|
-
type: "BLOB",
|
|
72
|
-
access: input.access ?? "PUBLIC",
|
|
73
|
-
...input.productId ? { refIds: [{ type: "PRODUCT", id: input.productId }] } : {},
|
|
74
|
-
...input.filename || input.mimeType ? {
|
|
75
|
-
details: {
|
|
76
|
-
...input.filename ? { filename: input.filename } : {},
|
|
77
|
-
...input.mimeType ? { mimeType: input.mimeType } : {}
|
|
78
|
-
}
|
|
79
|
-
} : {}
|
|
80
|
-
};
|
|
81
|
-
return this.create({ kind: "blob", file: input.file, body }, auth);
|
|
82
|
-
}
|
|
83
|
-
/** External-URL sugar: builds `AssetCreateLink`. */
|
|
84
|
-
async link(input, auth = SERVICE) {
|
|
85
|
-
const body = {
|
|
86
|
-
type: "LINK",
|
|
87
|
-
access: input.access ?? "PUBLIC",
|
|
88
|
-
url: input.url,
|
|
89
|
-
...input.productId ? { refIds: [{ type: "PRODUCT", id: input.productId }] } : {}
|
|
90
|
-
};
|
|
91
|
-
return this.create({ kind: "link", body }, auth);
|
|
92
|
-
}
|
|
93
|
-
/** Idempotently add a PRODUCT refId to an asset. */
|
|
94
|
-
async attachToProduct(assetId, productId, auth = SERVICE) {
|
|
95
|
-
const a = await this.get(assetId, auth);
|
|
96
|
-
const refIds = a.refIds ?? [];
|
|
97
|
-
if (refIds.some((r) => isProductRef(r, productId))) return a;
|
|
98
|
-
const next = [...refIds, { type: "PRODUCT", id: productId }];
|
|
99
|
-
const patch = { type: a.type, refIds: next };
|
|
100
|
-
return this.update(assetId, patch, auth);
|
|
101
|
-
}
|
|
102
|
-
/** Remove a PRODUCT refId from an asset (no-op if absent). */
|
|
103
|
-
async detachFromProduct(assetId, productId, auth = SERVICE) {
|
|
104
|
-
const a = await this.get(assetId, auth);
|
|
105
|
-
const refIds = a.refIds ?? [];
|
|
106
|
-
const next = refIds.filter((r) => !isProductRef(r, productId));
|
|
107
|
-
if (next.length === refIds.length) return a;
|
|
108
|
-
const patch = { type: a.type, refIds: next };
|
|
109
|
-
return this.update(assetId, patch, auth);
|
|
110
|
-
}
|
|
111
|
-
/** Convenience: list assets attached to a product (server-side filter). */
|
|
112
|
-
async listForProduct(productId, auth = SERVICE) {
|
|
113
|
-
return this.list({ "refIds.id": productId }, auth);
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
var _internalMedia = { isProductRef };
|
|
117
|
-
|
|
118
|
-
export { MediaService, _internalMedia };
|
|
119
|
-
//# sourceMappingURL=chunk-F3WAQH2E.js.map
|
|
120
|
-
//# sourceMappingURL=chunk-F3WAQH2E.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/media.ts"],"names":[],"mappings":"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","file":"chunk-F3WAQH2E.js","sourcesContent":["import type { ClientContext } from \"../core/context\";\nimport type { AuthContext } from \"../core/auth\";\nimport type {\n AssetCreateBlob,\n AssetCreateLink,\n AssetUpdateBlob,\n AssetUpdateLink,\n GetAsset,\n RefId,\n} from \"../generated/media\";\n\n/** Generated media types (caller sends the exact wire shape). */\nexport type AssetCreateBlobInput = AssetCreateBlob;\nexport type AssetCreateLinkInput = AssetCreateLink;\nexport type AssetUpdateInput = AssetUpdateBlob | AssetUpdateLink;\nexport type Asset = GetAsset;\nexport type AssetRefId = RefId;\n\nconst SERVICE: AuthContext = { kind: \"service\" };\n\nfunction isProductRef(r: AssetRefId, productId: string): boolean {\n return r.type === \"PRODUCT\" && r.id === productId;\n}\n\n/**\n * Media assets (BLOB/LINK). All endpoints require a backend-only scope\n * (`media.asset_manage` / `media.asset_read`) — default auth: service.\n */\nexport class MediaService {\n constructor(private readonly ctx: ClientContext) {}\n\n private base(): string {\n return `/media/${this.ctx.tenant}/assets`;\n }\n\n /** Create an asset. BLOB uploads via multipart; LINK via JSON. */\n async create(\n input:\n | { kind: \"blob\"; file: Blob; body: AssetCreateBlobInput }\n | { kind: \"link\"; body: AssetCreateLinkInput },\n auth: AuthContext = SERVICE,\n ): Promise<{ id: string }> {\n if (input.kind === \"blob\") {\n const fd = new FormData();\n fd.set(\"file\", input.file);\n fd.set(\"body\", JSON.stringify(input.body));\n return this.ctx.http.request<{ id: string }>({\n method: \"POST\",\n path: this.base(),\n auth,\n body: fd,\n });\n }\n return this.ctx.http.request<{ id: string }>({\n method: \"POST\",\n path: this.base(),\n auth,\n body: input.body,\n });\n }\n\n /** List assets. Optional `query` is passed through to Emporix verbatim. */\n async list(\n query?: Record<string, string | number | undefined>,\n auth: AuthContext = SERVICE,\n ): Promise<Asset[]> {\n return this.ctx.http.request<Asset[]>({\n method: \"GET\",\n path: this.base(),\n auth,\n ...(query ? { query } : {}),\n });\n }\n\n /** Fetch an asset by id. */\n async get(assetId: string, auth: AuthContext = SERVICE): Promise<Asset> {\n return this.ctx.http.request<Asset>({\n method: \"GET\",\n path: `${this.base()}/${assetId}`,\n auth,\n });\n }\n\n /** Update an asset (e.g. swap `refIds` or `access`). */\n async update(\n assetId: string,\n patch: AssetUpdateInput,\n auth: AuthContext = SERVICE,\n ): Promise<Asset> {\n return this.ctx.http.request<Asset>({\n method: \"PUT\",\n path: `${this.base()}/${assetId}`,\n auth,\n body: patch,\n });\n }\n\n /** Remove an asset. */\n async remove(assetId: string, auth: AuthContext = SERVICE): Promise<void> {\n await this.ctx.http.request<void>({\n method: \"DELETE\",\n path: `${this.base()}/${assetId}`,\n auth,\n });\n }\n\n /** Multipart upload sugar: builds `AssetCreateBlob` from input. */\n async uploadFile(\n input: {\n file: Blob;\n productId?: string;\n filename?: string;\n mimeType?: string;\n access?: \"PUBLIC\" | \"PRIVATE\";\n },\n auth: AuthContext = SERVICE,\n ): Promise<{ id: string }> {\n const body: AssetCreateBlobInput = {\n type: \"BLOB\",\n access: input.access ?? \"PUBLIC\",\n ...(input.productId\n ? { refIds: [{ type: \"PRODUCT\", id: input.productId }] }\n : {}),\n ...(input.filename || input.mimeType\n ? {\n details: {\n ...(input.filename ? { filename: input.filename } : {}),\n ...(input.mimeType ? { mimeType: input.mimeType } : {}),\n },\n }\n : {}),\n };\n return this.create({ kind: \"blob\", file: input.file, body }, auth);\n }\n\n /** External-URL sugar: builds `AssetCreateLink`. */\n async link(\n input: { url: string; productId?: string; access?: \"PUBLIC\" | \"PRIVATE\" },\n auth: AuthContext = SERVICE,\n ): Promise<{ id: string }> {\n const body: AssetCreateLinkInput = {\n type: \"LINK\",\n access: input.access ?? \"PUBLIC\",\n url: input.url,\n ...(input.productId\n ? { refIds: [{ type: \"PRODUCT\", id: input.productId }] }\n : {}),\n };\n return this.create({ kind: \"link\", body }, auth);\n }\n\n /** Idempotently add a PRODUCT refId to an asset. */\n async attachToProduct(\n assetId: string,\n productId: string,\n auth: AuthContext = SERVICE,\n ): Promise<Asset> {\n const a = await this.get(assetId, auth);\n const refIds: AssetRefId[] = a.refIds ?? [];\n if (refIds.some((r) => isProductRef(r, productId))) return a;\n const next: AssetRefId[] = [...refIds, { type: \"PRODUCT\", id: productId }];\n // Preserve the asset's type discriminator so the update body satisfies\n // the AssetUpdateBlob | AssetUpdateLink union.\n const patch = { type: a.type, refIds: next } as unknown as AssetUpdateInput;\n return this.update(assetId, patch, auth);\n }\n\n /** Remove a PRODUCT refId from an asset (no-op if absent). */\n async detachFromProduct(\n assetId: string,\n productId: string,\n auth: AuthContext = SERVICE,\n ): Promise<Asset> {\n const a = await this.get(assetId, auth);\n const refIds: AssetRefId[] = a.refIds ?? [];\n const next = refIds.filter((r) => !isProductRef(r, productId));\n if (next.length === refIds.length) return a;\n const patch = { type: a.type, refIds: next } as unknown as AssetUpdateInput;\n return this.update(assetId, patch, auth);\n }\n\n /** Convenience: list assets attached to a product (server-side filter). */\n async listForProduct(productId: string, auth: AuthContext = SERVICE): Promise<Asset[]> {\n return this.list({ \"refIds.id\": productId }, auth);\n }\n}\n\n// Re-export so consumers can `import { isProductRef } from \"@viu/emporix-sdk/media\"`?\n// Internal helper — kept module-private; convenience methods in Task 4 use it.\nexport const _internalMedia = { isProductRef };\n"]}
|