@adobe/aio-commerce-lib-admin-ui 0.1.0 → 0.2.0-alpha-20260722091448
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 +46 -0
- package/README.md +1 -1
- package/dist/cjs/acl-resource-id-DBlYU0DE.d.cts +39 -0
- package/dist/cjs/acl-resource-id-D_hCU1Qg.cjs +69 -0
- package/dist/cjs/api/index.cjs +252 -0
- package/dist/cjs/api/index.d.cts +126 -0
- package/dist/cjs/grid-columns/index.cjs +151 -0
- package/dist/cjs/grid-columns/index.d.cts +146 -0
- package/dist/cjs/mass-actions/index.cjs +188 -0
- package/dist/cjs/mass-actions/index.d.cts +160 -0
- package/dist/cjs/menu/index.cjs +91 -0
- package/dist/cjs/menu/index.d.cts +63 -0
- package/dist/cjs/order-view-buttons/index.cjs +126 -0
- package/dist/cjs/order-view-buttons/index.d.cts +113 -0
- package/dist/cjs/rolldown-runtime-Cx6hovH8.cjs +67 -0
- package/dist/cjs/schemas-Ce10uBzN.cjs +41 -0
- package/dist/cjs/utils-B59fjd_w.cjs +39 -0
- package/dist/cjs/web/index.cjs +872 -0
- package/dist/cjs/web/index.d.cts +206 -0
- package/dist/es/acl-resource-id-DBlYU0DE.d.mts +39 -0
- package/dist/es/acl-resource-id-pryVxI_c.mjs +57 -0
- package/dist/es/api/index.d.mts +126 -0
- package/dist/es/api/index.mjs +262 -0
- package/dist/es/grid-columns/index.d.mts +146 -0
- package/dist/es/grid-columns/index.mjs +143 -0
- package/dist/es/mass-actions/index.d.mts +160 -0
- package/dist/es/mass-actions/index.mjs +178 -0
- package/dist/es/menu/index.d.mts +63 -0
- package/dist/es/menu/index.mjs +80 -0
- package/dist/es/order-view-buttons/index.d.mts +113 -0
- package/dist/es/order-view-buttons/index.mjs +119 -0
- package/dist/es/schemas-BFT8ys8P.mjs +34 -0
- package/dist/es/utils-COPGW1HO.mjs +32 -0
- package/dist/es/web/index.d.mts +206 -0
- package/dist/es/web/index.mjs +861 -0
- package/package.json +87 -10
- package/dist/cjs/index.cjs +0 -139
- package/dist/cjs/index.d.cts +0 -56
- package/dist/es/index.d.mts +0 -56
- package/dist/es/index.mjs +0 -114
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
5
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
7
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
10
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
11
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
12
|
+
* governing permissions and limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { t as getAclResourceId } from "../acl-resource-id-pryVxI_c.mjs";
|
|
16
|
+
import { t as parseOrThrow } from "../utils-COPGW1HO.mjs";
|
|
17
|
+
import { CommerceSdkErrorBase } from "@adobe/aio-commerce-lib-core/error";
|
|
18
|
+
import { AdobeCommerceHttpClient, ApiClient } from "@adobe/aio-commerce-lib-api";
|
|
19
|
+
import * as v from "valibot";
|
|
20
|
+
import { HTTPError } from "ky";
|
|
21
|
+
|
|
22
|
+
//#region \0rolldown/runtime.js
|
|
23
|
+
var __defProp = Object.defineProperty;
|
|
24
|
+
var __exportAll = (all, no_symbols) => {
|
|
25
|
+
let target = {};
|
|
26
|
+
for (var name in all) {
|
|
27
|
+
__defProp(target, name, {
|
|
28
|
+
get: all[name],
|
|
29
|
+
enumerable: true
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (!no_symbols) {
|
|
33
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region source/errors.ts
|
|
40
|
+
/** Base error for Admin UI SDK permission helper failures. */
|
|
41
|
+
var AdminUiPermissionError = class extends CommerceSdkErrorBase {};
|
|
42
|
+
/** Error thrown when the current user is denied access to an Admin UI SDK ACL resource. */
|
|
43
|
+
var AdminUiPermissionDeniedError = class extends AdminUiPermissionError {
|
|
44
|
+
resource;
|
|
45
|
+
constructor(resource, options) {
|
|
46
|
+
super(`Admin UI SDK permission denied for resource: ${resource}`, options);
|
|
47
|
+
this.resource = resource;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region source/api/config/endpoints.ts
|
|
53
|
+
var endpoints_exports$1 = /* @__PURE__ */ __exportAll({ enableAdminUiSdk: () => enableAdminUiSdk });
|
|
54
|
+
/**
|
|
55
|
+
* Enables the Admin UI SDK in Commerce via PUT /V1/adminuisdk/config.
|
|
56
|
+
*
|
|
57
|
+
* This must be called before {@link registerExtension} so that Commerce accepts
|
|
58
|
+
* the extension registration; registering an extension while the SDK is disabled
|
|
59
|
+
* leaves the extension unavailable in the Admin UI.
|
|
60
|
+
*
|
|
61
|
+
* @param httpClient - The {@link AdobeCommerceHttpClient} to use to make the request.
|
|
62
|
+
* @param fetchOptions - Optional Ky fetch options.
|
|
63
|
+
*
|
|
64
|
+
* @throws An `HTTPError` if the status code is not 2XX.
|
|
65
|
+
*/
|
|
66
|
+
async function enableAdminUiSdk(httpClient, fetchOptions) {
|
|
67
|
+
return httpClient.put("adminuisdk/config", {
|
|
68
|
+
...fetchOptions,
|
|
69
|
+
json: { enableAdminUiSdk: true }
|
|
70
|
+
}).json();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region source/api/extensions/schema.ts
|
|
75
|
+
/** Parameters for POST /V1/adminuisdk/extension. */
|
|
76
|
+
const ExtensionRegistrationParamsSchema = v.object({
|
|
77
|
+
extensionName: v.pipe(v.string(), v.minLength(1)),
|
|
78
|
+
extensionTitle: v.pipe(v.string(), v.minLength(1)),
|
|
79
|
+
extensionWorkspace: v.pipe(v.string(), v.minLength(1))
|
|
80
|
+
});
|
|
81
|
+
/** Parameters for DELETE /V1/adminuisdk/extension/{workspaceName}/{extensionName}. */
|
|
82
|
+
const UnregisterExtensionParamsSchema = v.object({
|
|
83
|
+
extensionName: v.pipe(v.string(), v.minLength(1)),
|
|
84
|
+
workspaceName: v.pipe(v.string(), v.minLength(1))
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region source/api/extensions/endpoints.ts
|
|
89
|
+
var endpoints_exports = /* @__PURE__ */ __exportAll({
|
|
90
|
+
registerExtension: () => registerExtension,
|
|
91
|
+
unregisterExtension: () => unregisterExtension
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Registers an Admin UI extension with Commerce via POST /V1/adminuisdk/extension.
|
|
95
|
+
*
|
|
96
|
+
* @param httpClient - The {@link AdobeCommerceHttpClient} to use to make the request.
|
|
97
|
+
* @param params - The extension registration parameters.
|
|
98
|
+
* @param fetchOptions - Optional Ky fetch options.
|
|
99
|
+
*
|
|
100
|
+
* @throws A `CommerceSdkValidationError` if the parameters are invalid.
|
|
101
|
+
* @throws An `HTTPError` if the status code is not 2XX.
|
|
102
|
+
*/
|
|
103
|
+
async function registerExtension(httpClient, params, fetchOptions) {
|
|
104
|
+
const extension = parseOrThrow(ExtensionRegistrationParamsSchema, params);
|
|
105
|
+
return httpClient.post("adminuisdk/extension", {
|
|
106
|
+
...fetchOptions,
|
|
107
|
+
json: { extension }
|
|
108
|
+
}).json();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Unregisters an Admin UI extension from Commerce via DELETE /V1/adminuisdk/extension/{workspaceName}/{extensionName}.
|
|
112
|
+
*
|
|
113
|
+
* @param httpClient - The {@link AdobeCommerceHttpClient} to use to make the request.
|
|
114
|
+
* @param params - The workspace and extension names.
|
|
115
|
+
* @param fetchOptions - Optional Ky fetch options.
|
|
116
|
+
*
|
|
117
|
+
* @throws A `CommerceSdkValidationError` if the parameters are invalid.
|
|
118
|
+
* @throws An `HTTPError` if the status code is not 2XX.
|
|
119
|
+
*/
|
|
120
|
+
async function unregisterExtension(httpClient, params, fetchOptions) {
|
|
121
|
+
const { workspaceName, extensionName } = parseOrThrow(UnregisterExtensionParamsSchema, params);
|
|
122
|
+
return httpClient.delete(`adminuisdk/extension/${workspaceName}/${extensionName}`, fetchOptions).then((_res) => {});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region source/api/lib/api-client.ts
|
|
127
|
+
/**
|
|
128
|
+
* Creates a new API client for the Admin UI API with all available operations.
|
|
129
|
+
*
|
|
130
|
+
* @param params - The parameters to build the Commerce HTTP client.
|
|
131
|
+
*/
|
|
132
|
+
function createAdminUiApiClient(params) {
|
|
133
|
+
return ApiClient.create(new AdobeCommerceHttpClient(params), {
|
|
134
|
+
...endpoints_exports$1,
|
|
135
|
+
...endpoints_exports
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region source/api/permissions/schema.ts
|
|
141
|
+
/** Response shape returned by the Admin UI SDK permission check endpoint. */
|
|
142
|
+
const permissionCheckResponseSchema = v.object({ allowed: v.boolean() });
|
|
143
|
+
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region source/api/permissions/endpoints.ts
|
|
146
|
+
/**
|
|
147
|
+
* Checks whether the current user has the given ACL resource granted via POST /V1/adminuisdk/permission/check.
|
|
148
|
+
* This is the raw HTTP call — prefer {@link getAdminUiPermissionClient} for caching and deduplication.
|
|
149
|
+
*
|
|
150
|
+
* @param httpClient - The {@link AdobeCommerceHttpClient} to use to make the request.
|
|
151
|
+
* @param params - The resource to check.
|
|
152
|
+
*
|
|
153
|
+
* @throws {@link HTTPError} if the response status is not in the 2xx range.
|
|
154
|
+
*/
|
|
155
|
+
async function checkPermission(httpClient, params) {
|
|
156
|
+
return parseOrThrow(permissionCheckResponseSchema, await httpClient.post("adminuisdk/permission/check", { json: { resource: params.resource } }).json());
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region source/api/lib/permission-client.ts
|
|
161
|
+
const DEFAULT_CACHE_TTL_MS = 3e5;
|
|
162
|
+
/** Returns true when the error is an HTTP 401 Unauthorized response from ky. */
|
|
163
|
+
function isUnauthorizedError(error) {
|
|
164
|
+
return error instanceof HTTPError && error.response.status === 401;
|
|
165
|
+
}
|
|
166
|
+
/** Wraps an arbitrary thrown value in an `AdminUiPermissionError`, passing through instances that are already one. */
|
|
167
|
+
function toPermissionError(error) {
|
|
168
|
+
return error instanceof AdminUiPermissionError ? error : new AdminUiPermissionError("Permission check failed", { cause: error });
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Creates a client for checking Admin UI SDK ACL resources.
|
|
172
|
+
*
|
|
173
|
+
* @param options - Client configuration; see {@link AdminUiPermissionClientOptions}.
|
|
174
|
+
* @returns An {@link AdminUiPermissionClient} for checking and requiring ACL resources.
|
|
175
|
+
*/
|
|
176
|
+
function getAdminUiPermissionClient(options) {
|
|
177
|
+
const { httpClient, appId, cacheTtlMs = DEFAULT_CACHE_TTL_MS, denyOnError = true } = options;
|
|
178
|
+
const cache = /* @__PURE__ */ new Map();
|
|
179
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
180
|
+
/**
|
|
181
|
+
* Performs the network request for `resource` and maps the outcome to a `PermissionCheckResult`.
|
|
182
|
+
* Always throws `AdminUiPermissionError` on 401. On other errors, returns a non-cacheable error
|
|
183
|
+
* result when `denyOnError` is true, or re-throws otherwise.
|
|
184
|
+
*/
|
|
185
|
+
async function fetchCheck(resource) {
|
|
186
|
+
try {
|
|
187
|
+
return {
|
|
188
|
+
allowed: (await checkPermission(httpClient, { resource })).allowed,
|
|
189
|
+
cacheable: true
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (isUnauthorizedError(error)) throw new AdminUiPermissionError("Unauthorized", { cause: error });
|
|
193
|
+
if (denyOnError) return {
|
|
194
|
+
cacheable: false,
|
|
195
|
+
error: toPermissionError(error)
|
|
196
|
+
};
|
|
197
|
+
throw toPermissionError(error);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Returns a permission check result for `resource`, serving from the TTL cache or an
|
|
202
|
+
* in-flight request when available, and falling back to a fresh `fetchCheck` call otherwise.
|
|
203
|
+
* Successful cacheable results are written to the TTL cache once the in-flight promise settles.
|
|
204
|
+
*/
|
|
205
|
+
function resolveCheck(resource) {
|
|
206
|
+
if (cacheTtlMs > 0) {
|
|
207
|
+
const cached = cache.get(resource);
|
|
208
|
+
if (cached !== void 0 && cached.expiresAt > Date.now()) return {
|
|
209
|
+
allowed: cached.value,
|
|
210
|
+
cacheable: true
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const existing = inFlight.get(resource);
|
|
214
|
+
if (existing !== void 0) return existing;
|
|
215
|
+
const trackedPromise = fetchCheck(resource).then((result) => {
|
|
216
|
+
if (cacheTtlMs > 0 && result.cacheable && inFlight.get(resource) === trackedPromise) cache.set(resource, {
|
|
217
|
+
expiresAt: Date.now() + cacheTtlMs,
|
|
218
|
+
value: result.allowed
|
|
219
|
+
});
|
|
220
|
+
return result;
|
|
221
|
+
}).finally(() => {
|
|
222
|
+
if (inFlight.get(resource) === trackedPromise) inFlight.delete(resource);
|
|
223
|
+
});
|
|
224
|
+
inFlight.set(resource, trackedPromise);
|
|
225
|
+
return trackedPromise;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Resolves the ACL resource id for a call: uses the explicit argument when provided,
|
|
229
|
+
* otherwise derives it from `appId`. Returns an empty string when neither source yields a
|
|
230
|
+
* valid id, which callers interpret as "no resource available."
|
|
231
|
+
*/
|
|
232
|
+
function resolveResource(resource) {
|
|
233
|
+
return resource ?? getAclResourceId(appId ?? "");
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
async check(resource) {
|
|
237
|
+
const resolved = resolveResource(resource);
|
|
238
|
+
if (resolved === "") return false;
|
|
239
|
+
const result = await resolveCheck(resolved);
|
|
240
|
+
return "error" in result ? false : result.allowed;
|
|
241
|
+
},
|
|
242
|
+
invalidate(resource) {
|
|
243
|
+
if (resource === void 0) {
|
|
244
|
+
cache.clear();
|
|
245
|
+
inFlight.clear();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
cache.delete(resource);
|
|
249
|
+
inFlight.delete(resource);
|
|
250
|
+
},
|
|
251
|
+
async require(resource) {
|
|
252
|
+
const resolved = resolveResource(resource);
|
|
253
|
+
if (resolved === "") throw new AdminUiPermissionError("No ACL resource ID could be resolved: provide a resource argument or set appId in options");
|
|
254
|
+
const result = await resolveCheck(resolved);
|
|
255
|
+
if ("error" in result) throw result.error;
|
|
256
|
+
if (!result.allowed) throw new AdminUiPermissionDeniedError(resolved);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
//#endregion
|
|
262
|
+
export { AdminUiPermissionDeniedError, AdminUiPermissionError, createAdminUiApiClient, getAclResourceId, getAdminUiPermissionClient };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
5
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
7
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
10
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
11
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
12
|
+
* governing permissions and limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { t as AdminUiEntity } from "../acl-resource-id-DBlYU0DE.mjs";
|
|
16
|
+
import * as v from "valibot";
|
|
17
|
+
import { ErrorResponse, SuccessResponse } from "@adobe/aio-commerce-lib-core/responses";
|
|
18
|
+
|
|
19
|
+
//#region source/grid-columns/acl-resource-id.d.ts
|
|
20
|
+
/**
|
|
21
|
+
* Derives the deterministic Commerce ACL resource id for a grid column.
|
|
22
|
+
*
|
|
23
|
+
* The id is assembled as: `getAclResourceId(metadataId)` + `"_<entity>_gridcolumns_"` +
|
|
24
|
+
* sanitized `columnId`. The `entity` value is used verbatim (it is already `[a-z]`); the
|
|
25
|
+
* `columnId` is sanitized (trimmed, lowercased, non-`[a-z0-9_]` → `_`). `"Magento_CommerceBackendUix::adminuisdk_app_"`
|
|
26
|
+
* in the example is the fixed constant prefix (not a placeholder), and `"_gridcolumns_"` is the
|
|
27
|
+
* literal keyword separator for this component:
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```
|
|
31
|
+
* getGridColumnAclResourceId("approval-dashboard-app", "order", "order_status")
|
|
32
|
+
* // getAclResourceId("approval-dashboard-app") + "_order_gridcolumns_" + sanitize("order_status")
|
|
33
|
+
* // "Magento_CommerceBackendUix::adminuisdk_app_approval_dashboard_app" + "_order_gridcolumns_" + "order_status"
|
|
34
|
+
* // → "Magento_CommerceBackendUix::adminuisdk_app_approval_dashboard_app_order_gridcolumns_order_status"
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param metadataId - The application's `metadata.id` value (e.g. `"approval-dashboard-app"`).
|
|
38
|
+
* @param entity - The grid's Commerce entity (`"order"`, `"product"`, or `"customer"`).
|
|
39
|
+
* @param columnId - The column's `id` value from `adminUi.<entity>.gridColumns.columns[].id`.
|
|
40
|
+
* @returns The full Commerce ACL resource id for the grid-column leaf node, or an empty string
|
|
41
|
+
* when `metadataId` is blank.
|
|
42
|
+
*/
|
|
43
|
+
declare function getGridColumnAclResourceId(metadataId: string, entity: AdminUiEntity, columnId: string): string;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region source/grid-columns/requests/schema.d.ts
|
|
46
|
+
/**
|
|
47
|
+
* Grid identifier sent by Commerce on the `commerce/backend-ui/2` wire contract.
|
|
48
|
+
*
|
|
49
|
+
* @see {@link https://github.com/magento-commerce/adobe-commerce-backend-uix Magento module reference}
|
|
50
|
+
*/
|
|
51
|
+
declare const GridTypeSchema: v.PicklistSchema<["order", "product", "customer"], undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Schema for the JSON body Commerce POSTs to a grid column handler.
|
|
54
|
+
*
|
|
55
|
+
* Commerce sends one request per chunk of grid rows (currently up to 1000 IDs
|
|
56
|
+
* per request). The upper bound is the Commerce side's contract and is not
|
|
57
|
+
* enforced here.
|
|
58
|
+
*/
|
|
59
|
+
declare const GridRequestSchema: v.ObjectSchema<{
|
|
60
|
+
readonly gridType: v.PicklistSchema<["order", "product", "customer"], undefined>;
|
|
61
|
+
readonly ids: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>, undefined>, v.MinLengthAction<string[], 1, "The value of \"ids\" must contain at least one entry">]>;
|
|
62
|
+
readonly requestId: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
|
|
63
|
+
}, undefined>;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region source/grid-columns/requests/types.d.ts
|
|
66
|
+
/** Grid identifier sent on the wire. */
|
|
67
|
+
type GridType = v.InferOutput<typeof GridTypeSchema>;
|
|
68
|
+
/** Parsed request body sent by Commerce to a grid column handler. */
|
|
69
|
+
type GridRequest = v.InferOutput<typeof GridRequestSchema>;
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region source/grid-columns/requests/presets.d.ts
|
|
72
|
+
/**
|
|
73
|
+
* Parses and validates the JSON body Commerce POSTs to a grid column handler.
|
|
74
|
+
*
|
|
75
|
+
* Throws a `CommerceSdkValidationError` if the input is malformed.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* import { parseGridRequest } from "@adobe/aio-commerce-lib-admin-ui/grid-columns";
|
|
80
|
+
*
|
|
81
|
+
* export async function main(params: unknown) {
|
|
82
|
+
* const { requestId, gridType, ids } = parseGridRequest(params);
|
|
83
|
+
* // ...
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function parseGridRequest(input: unknown): GridRequest;
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region source/grid-columns/responses/types.d.ts
|
|
90
|
+
/** Cell values returned for a single row, keyed by `id`. */
|
|
91
|
+
type GridRow = Record<string, unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Success body returned to Commerce.
|
|
94
|
+
*
|
|
95
|
+
* The `"*"` entry supplies default cell values that Commerce applies to IDs
|
|
96
|
+
* missing from `data` and to cells whose returned value does not satisfy the
|
|
97
|
+
* declared `type` on the registration.
|
|
98
|
+
*/
|
|
99
|
+
type GridSuccessBody = {
|
|
100
|
+
data: Record<string, GridRow> & {
|
|
101
|
+
"*"?: GridRow;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
/** Failure body returned to Commerce. */
|
|
105
|
+
type GridErrorBody = {
|
|
106
|
+
message: string;
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region source/grid-columns/responses/presets.d.ts
|
|
110
|
+
/**
|
|
111
|
+
* Builds an HTTP 200 success response carrying the grid column data envelope
|
|
112
|
+
* Commerce expects on the `commerce/backend-ui/2` wire contract.
|
|
113
|
+
*
|
|
114
|
+
* @param data - Per-row cell values, keyed by entity ID.
|
|
115
|
+
* @param defaults - Default cell values applied by Commerce to IDs missing from
|
|
116
|
+
* `data` and to cells whose value does not satisfy the declared `type` on the
|
|
117
|
+
* registration.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* return okGridResponse(
|
|
122
|
+
* {
|
|
123
|
+
* "000000001": { fulfillment_status: "shipped", risk_score: 12 },
|
|
124
|
+
* "000000002": { fulfillment_status: "pending", risk_score: 47 },
|
|
125
|
+
* },
|
|
126
|
+
* { fulfillment_status: "unknown", risk_score: 0 },
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare function okGridResponse(data: Record<string, GridRow>, defaults?: GridRow): SuccessResponse<GridSuccessBody>;
|
|
131
|
+
/**
|
|
132
|
+
* Builds an error response for a grid column handler with the given HTTP status code.
|
|
133
|
+
*
|
|
134
|
+
* Commerce uses the HTTP status code to distinguish success from failure.
|
|
135
|
+
*
|
|
136
|
+
* @param statusCode - The HTTP status code to return.
|
|
137
|
+
* @param errorMessage - Error message included in the response body as `{ message }`.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* return errorGridResponse(500, "Could not reach inventory service");
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
declare function errorGridResponse(statusCode: number, errorMessage: string): ErrorResponse<GridErrorBody>;
|
|
145
|
+
//#endregion
|
|
146
|
+
export { type AdminUiEntity, type GridErrorBody, type GridRequest, GridRequestSchema, type GridRow, type GridSuccessBody, type GridType, GridTypeSchema, errorGridResponse, getGridColumnAclResourceId, okGridResponse, parseGridRequest };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
5
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
7
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
10
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
11
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
12
|
+
* governing permissions and limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { n as sanitizeSegment, t as getAclResourceId } from "../acl-resource-id-pryVxI_c.mjs";
|
|
16
|
+
import { t as nonEmptyStringValueSchema } from "../schemas-BFT8ys8P.mjs";
|
|
17
|
+
import { t as parseOrThrow } from "../utils-COPGW1HO.mjs";
|
|
18
|
+
import * as v from "valibot";
|
|
19
|
+
import { buildErrorResponse, ok } from "@adobe/aio-commerce-lib-core/responses";
|
|
20
|
+
|
|
21
|
+
//#region source/grid-columns/acl-resource-id.ts
|
|
22
|
+
/**
|
|
23
|
+
* Derives the deterministic Commerce ACL resource id for a grid column.
|
|
24
|
+
*
|
|
25
|
+
* The id is assembled as: `getAclResourceId(metadataId)` + `"_<entity>_gridcolumns_"` +
|
|
26
|
+
* sanitized `columnId`. The `entity` value is used verbatim (it is already `[a-z]`); the
|
|
27
|
+
* `columnId` is sanitized (trimmed, lowercased, non-`[a-z0-9_]` → `_`). `"Magento_CommerceBackendUix::adminuisdk_app_"`
|
|
28
|
+
* in the example is the fixed constant prefix (not a placeholder), and `"_gridcolumns_"` is the
|
|
29
|
+
* literal keyword separator for this component:
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```
|
|
33
|
+
* getGridColumnAclResourceId("approval-dashboard-app", "order", "order_status")
|
|
34
|
+
* // getAclResourceId("approval-dashboard-app") + "_order_gridcolumns_" + sanitize("order_status")
|
|
35
|
+
* // "Magento_CommerceBackendUix::adminuisdk_app_approval_dashboard_app" + "_order_gridcolumns_" + "order_status"
|
|
36
|
+
* // → "Magento_CommerceBackendUix::adminuisdk_app_approval_dashboard_app_order_gridcolumns_order_status"
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @param metadataId - The application's `metadata.id` value (e.g. `"approval-dashboard-app"`).
|
|
40
|
+
* @param entity - The grid's Commerce entity (`"order"`, `"product"`, or `"customer"`).
|
|
41
|
+
* @param columnId - The column's `id` value from `adminUi.<entity>.gridColumns.columns[].id`.
|
|
42
|
+
* @returns The full Commerce ACL resource id for the grid-column leaf node, or an empty string
|
|
43
|
+
* when `metadataId` is blank.
|
|
44
|
+
*/
|
|
45
|
+
function getGridColumnAclResourceId(metadataId, entity, columnId) {
|
|
46
|
+
const appRoot = getAclResourceId(metadataId);
|
|
47
|
+
if (appRoot === "") return "";
|
|
48
|
+
return `${appRoot}_${entity}_gridcolumns_${sanitizeSegment(columnId)}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region source/grid-columns/requests/schema.ts
|
|
53
|
+
/**
|
|
54
|
+
* Grid identifier sent by Commerce on the `commerce/backend-ui/2` wire contract.
|
|
55
|
+
*
|
|
56
|
+
* @see {@link https://github.com/magento-commerce/adobe-commerce-backend-uix Magento module reference}
|
|
57
|
+
*/
|
|
58
|
+
const GridTypeSchema = v.picklist([
|
|
59
|
+
"order",
|
|
60
|
+
"product",
|
|
61
|
+
"customer"
|
|
62
|
+
]);
|
|
63
|
+
/**
|
|
64
|
+
* Schema for the JSON body Commerce POSTs to a grid column handler.
|
|
65
|
+
*
|
|
66
|
+
* Commerce sends one request per chunk of grid rows (currently up to 1000 IDs
|
|
67
|
+
* per request). The upper bound is the Commerce side's contract and is not
|
|
68
|
+
* enforced here.
|
|
69
|
+
*/
|
|
70
|
+
const GridRequestSchema = v.object({
|
|
71
|
+
gridType: GridTypeSchema,
|
|
72
|
+
ids: v.pipe(v.array(nonEmptyStringValueSchema("id")), v.minLength(1, "The value of \"ids\" must contain at least one entry")),
|
|
73
|
+
requestId: nonEmptyStringValueSchema("requestId")
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region source/grid-columns/requests/presets.ts
|
|
78
|
+
/**
|
|
79
|
+
* Parses and validates the JSON body Commerce POSTs to a grid column handler.
|
|
80
|
+
*
|
|
81
|
+
* Throws a `CommerceSdkValidationError` if the input is malformed.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { parseGridRequest } from "@adobe/aio-commerce-lib-admin-ui/grid-columns";
|
|
86
|
+
*
|
|
87
|
+
* export async function main(params: unknown) {
|
|
88
|
+
* const { requestId, gridType, ids } = parseGridRequest(params);
|
|
89
|
+
* // ...
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
function parseGridRequest(input) {
|
|
94
|
+
return parseOrThrow(GridRequestSchema, input, "Invalid grid column request");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region source/grid-columns/responses/presets.ts
|
|
99
|
+
/**
|
|
100
|
+
* Builds an HTTP 200 success response carrying the grid column data envelope
|
|
101
|
+
* Commerce expects on the `commerce/backend-ui/2` wire contract.
|
|
102
|
+
*
|
|
103
|
+
* @param data - Per-row cell values, keyed by entity ID.
|
|
104
|
+
* @param defaults - Default cell values applied by Commerce to IDs missing from
|
|
105
|
+
* `data` and to cells whose value does not satisfy the declared `type` on the
|
|
106
|
+
* registration.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* return okGridResponse(
|
|
111
|
+
* {
|
|
112
|
+
* "000000001": { fulfillment_status: "shipped", risk_score: 12 },
|
|
113
|
+
* "000000002": { fulfillment_status: "pending", risk_score: 47 },
|
|
114
|
+
* },
|
|
115
|
+
* { fulfillment_status: "unknown", risk_score: 0 },
|
|
116
|
+
* );
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
function okGridResponse(data, defaults) {
|
|
120
|
+
return ok({ body: { data: defaults ? {
|
|
121
|
+
...data,
|
|
122
|
+
"*": defaults
|
|
123
|
+
} : data } });
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Builds an error response for a grid column handler with the given HTTP status code.
|
|
127
|
+
*
|
|
128
|
+
* Commerce uses the HTTP status code to distinguish success from failure.
|
|
129
|
+
*
|
|
130
|
+
* @param statusCode - The HTTP status code to return.
|
|
131
|
+
* @param errorMessage - Error message included in the response body as `{ message }`.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* return errorGridResponse(500, "Could not reach inventory service");
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
function errorGridResponse(statusCode, errorMessage) {
|
|
139
|
+
return buildErrorResponse(statusCode, { body: { message: errorMessage } });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { GridRequestSchema, GridTypeSchema, errorGridResponse, getGridColumnAclResourceId, okGridResponse, parseGridRequest };
|