@classytic/commerce-client 0.1.0 → 0.1.1
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 +10 -0
- package/dist/management-types.d.ts +5 -0
- package/dist/management.d.ts +6 -0
- package/dist/management.js +6 -2
- package/dist/platform.d.ts +36 -0
- package/dist/platform.js +29 -0
- package/management.md +12 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 — 2026-10-20
|
|
4
|
+
|
|
5
|
+
Add tenant-scoped media removal through the guarded media resource, and type media folder, size and display metadata for Fluid library bindings. Report unsupported source formats and browser decoding failures before starting storage writes.
|
|
6
|
+
|
|
7
|
+
Add `@classytic/commerce-client/platform`: `createPlatformClient({ apiUrl, token })` for platform administration with a bearer token and no merchant organization. `organizations.list` pages organizations and `organizations.decide(id, { action, expectedStatus, note })` applies an approve, reject, suspend or reactivate decision (matches `@spinekit/auth` 0.17.0 `./organizations`).
|
|
8
|
+
|
|
9
|
+
Dependencies are already at the latest published (`arc-next` 0.18.0, `media-transform` 0.3.0, `primitives` 0.34.0).
|
|
10
|
+
|
|
3
11
|
## 0.1.0 — 2026-10-20
|
|
4
12
|
|
|
5
13
|
First publish.
|
|
@@ -19,3 +27,5 @@ Typed store profiles, catalog reads, guest checkout with explicit retry keys, an
|
|
|
19
27
|
The isolated `/management` entry supports merchant catalog/media, order commands
|
|
20
28
|
and cash collection, store settings, Telegram connections and delivery history,
|
|
21
29
|
plus API-key options, creation, rotation and revocation.
|
|
30
|
+
|
|
31
|
+
Platform administration: `./platform` exposes bearer-only organization lists and guarded status decisions without requiring a merchant organization.
|
|
@@ -98,6 +98,11 @@ export interface StoreSettings {
|
|
|
98
98
|
}
|
|
99
99
|
export interface MerchantMedia {
|
|
100
100
|
_id: string;
|
|
101
|
+
folder: string;
|
|
102
|
+
size: number;
|
|
103
|
+
title?: string;
|
|
104
|
+
alt?: string;
|
|
105
|
+
createdAt?: string;
|
|
101
106
|
url: string;
|
|
102
107
|
filename: string;
|
|
103
108
|
mimeType?: string;
|
package/dist/management.d.ts
CHANGED
|
@@ -86,6 +86,12 @@ export declare function createMerchantClient(options: MerchantClientOptions): {
|
|
|
86
86
|
params?: import("@classytic/arc-next/api").QueryParams;
|
|
87
87
|
options?: Omit<import("@classytic/arc-next/api").RequestOptions, "token" | "organizationId">;
|
|
88
88
|
}) => Promise<import("@classytic/repo-core/pagination").PaginatedResult<MerchantMedia>>;
|
|
89
|
+
remove: ({ token, organizationId, id, options }: {
|
|
90
|
+
token?: string | null;
|
|
91
|
+
organizationId?: string | null;
|
|
92
|
+
id: string;
|
|
93
|
+
options?: Omit<import("@classytic/arc-next/api").RequestOptions, "token" | "organizationId">;
|
|
94
|
+
}) => Promise<import("@classytic/repo-core/repository").DeleteResult>;
|
|
89
95
|
upload: (file: File, folder?: 'products' | 'categories') => Promise<MerchantMedia>;
|
|
90
96
|
uploadImage(file: File, folder?: 'products' | 'categories'): Promise<MerchantMedia>;
|
|
91
97
|
};
|
package/dist/management.js
CHANGED
|
@@ -124,10 +124,12 @@ function createMerchantMedia(client, fetcher) {
|
|
|
124
124
|
}
|
|
125
125
|
return {
|
|
126
126
|
list: media.getAll.bind(media),
|
|
127
|
+
remove: media.delete.bind(media),
|
|
127
128
|
upload: (file, folder = "products") => upload(file, folder),
|
|
128
129
|
async uploadImage(file, folder = "products") {
|
|
129
130
|
const policy = await media.request("GET", `${media.baseUrl}/transform-policy`);
|
|
130
|
-
const { resolveTransformPlan } = await import("@classytic/media-transform/policy");
|
|
131
|
+
const { resolveTransformPlan, isTransformableImage } = await import("@classytic/media-transform/policy");
|
|
132
|
+
if (!isTransformableImage(file.type)) throw new Error("Choose a JPEG, PNG, WebP, AVIF or BMP image that your browser can open.");
|
|
131
133
|
const plan = resolveTransformPlan({
|
|
132
134
|
folder,
|
|
133
135
|
mimeType: file.type,
|
|
@@ -142,7 +144,9 @@ function createMerchantMedia(client, fetcher) {
|
|
|
142
144
|
import("@classytic/media-transform/image/compressImageSet"),
|
|
143
145
|
import("@classytic/media-transform/image/uploadHints")
|
|
144
146
|
]);
|
|
145
|
-
const result = await compressImageSet(await createBrowserImageAdapter(), file, plan.options)
|
|
147
|
+
const result = await compressImageSet(await createBrowserImageAdapter(), file, plan.options).catch(() => {
|
|
148
|
+
throw new Error("Your browser could not process this image. Try a JPEG or PNG copy.");
|
|
149
|
+
});
|
|
146
150
|
return upload(new File([result.blob], storedFilename(file.name, result.format), { type: result.blob.type }), folder, result, file.name);
|
|
147
151
|
}
|
|
148
152
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/platform.d.ts
|
|
2
|
+
export type OrganizationStatus = 'pending' | 'active' | 'rejected' | 'suspended';
|
|
3
|
+
export type OrganizationAction = 'approve' | 'reject' | 'suspend' | 'reactivate';
|
|
4
|
+
export interface PlatformOrganization {
|
|
5
|
+
_id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
status: OrganizationStatus;
|
|
9
|
+
createdAt?: string;
|
|
10
|
+
statusHistory?: Array<{
|
|
11
|
+
status: OrganizationStatus;
|
|
12
|
+
occurredAt: string;
|
|
13
|
+
by?: string;
|
|
14
|
+
note?: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
/** Platform administration uses a bearer identity without selecting a merchant organization. */
|
|
18
|
+
export declare function createPlatformClient({ apiUrl, token }: {
|
|
19
|
+
apiUrl: string;
|
|
20
|
+
token: string;
|
|
21
|
+
}): {
|
|
22
|
+
organizations: {
|
|
23
|
+
list: ({ token, organizationId, params, options }?: {
|
|
24
|
+
token?: string | null;
|
|
25
|
+
organizationId?: string | null;
|
|
26
|
+
params?: import("@classytic/arc-next/api").QueryParams;
|
|
27
|
+
options?: Omit<import("@classytic/arc-next/api").RequestOptions, "token" | "organizationId">;
|
|
28
|
+
}) => Promise<import("@classytic/repo-core/pagination").PaginatedResult<PlatformOrganization>>;
|
|
29
|
+
decide(id: string, data: {
|
|
30
|
+
action: OrganizationAction;
|
|
31
|
+
expectedStatus: OrganizationStatus;
|
|
32
|
+
note: string;
|
|
33
|
+
}): Promise<PlatformOrganization>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseApi } from "@classytic/arc-next/api";
|
|
2
|
+
import { createClient } from "@classytic/arc-next/client";
|
|
3
|
+
//#region src/platform.ts
|
|
4
|
+
/** Platform administration uses a bearer identity without selecting a merchant organization. */
|
|
5
|
+
function createPlatformClient({ apiUrl, token }) {
|
|
6
|
+
if (!token.trim()) throw new Error("A platform bearer token is required.");
|
|
7
|
+
const url = new URL(apiUrl);
|
|
8
|
+
if (url.username || url.password || url.search || url.hash) throw new Error("Use a plain API URL.");
|
|
9
|
+
const client = createClient({
|
|
10
|
+
baseUrl: url.href.replace(/\/+$/, ""),
|
|
11
|
+
getToken: () => token,
|
|
12
|
+
credentials: "omit",
|
|
13
|
+
autoIdempotency: false,
|
|
14
|
+
timeoutMs: 15e3
|
|
15
|
+
});
|
|
16
|
+
const organizations = new BaseApi("admin/organizations", {
|
|
17
|
+
client,
|
|
18
|
+
basePath: "",
|
|
19
|
+
cache: "no-store"
|
|
20
|
+
});
|
|
21
|
+
return { organizations: {
|
|
22
|
+
list: organizations.getAll.bind(organizations),
|
|
23
|
+
decide(id, data) {
|
|
24
|
+
return organizations.request("POST", `${organizations.baseUrl}/${encodeURIComponent(id)}/action`, { data });
|
|
25
|
+
}
|
|
26
|
+
} };
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { createPlatformClient };
|
package/management.md
CHANGED
|
@@ -86,3 +86,15 @@ Product writes also accept `tags`, `collections` and
|
|
|
86
86
|
`defaultMonetization.pricing.compareAtPrice`. The catalog derives `onSale`; clients
|
|
87
87
|
never set it. Tags and collections use the existing catalog arrays, with no
|
|
88
88
|
additional collection-management service.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Media library
|
|
92
|
+
|
|
93
|
+
`client.media.list({ params: { page: 1, limit: 20, folder: 'products' } })`
|
|
94
|
+
returns tenant-scoped media and pagination. `client.media.remove({ id })` uses
|
|
95
|
+
the media resource's guarded delete; an in-use image is refused by the server.
|
|
96
|
+
|
|
97
|
+
`client.media.uploadImage(file, folder)` resolves the server's transform policy
|
|
98
|
+
through media-transform before requesting storage writes. The server must accept
|
|
99
|
+
every output format in its policy, including the browser encoder's fallback.
|
|
100
|
+
Passthrough thresholds and dimensions belong to that policy, rather than the UI.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/commerce-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Typed storefront and merchant clients for the Classytic Commerce API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"./category-tree": {
|
|
31
31
|
"types": "./dist/category-tree.d.ts",
|
|
32
32
|
"default": "./dist/category-tree.js"
|
|
33
|
+
},
|
|
34
|
+
"./platform": {
|
|
35
|
+
"types": "./dist/platform.d.ts",
|
|
36
|
+
"default": "./dist/platform.js"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"files": [
|