import {z} from 'zod' export type DateStringFilter = 'now'; export type Source = 'MerchantCenter' | 'ImpEx' | 'ApiClient'; export type PlatformInitiatedChange = 'excludeAll' | 'addInheritedAssociate' | 'changeIncludedInStatistics' | 'changeInheritedAssociate' | 'changeLastVariantId' | 'changeLineItemName' | 'changeLineItemPublished' | 'changeReviewRatingStatistics' | 'changeTopLevelUnit' | 'removeInheritedAssociate' | 'setAncestors' | 'setApplicationVersion' | 'setInheritedAssociates' | 'setInheritedStores' | 'setIsValid' | 'setLineItemDeactivatedAt' | 'setProductCount' | 'setReservations' | 'setVariantAvailability'; export type GetApiProjectKeyResourceTypeArgs = {'date.from'?: (DateStringFilter | unknown | number) | undefined, 'date.to'?: (DateStringFilter | unknown | number) | undefined, limit?: number | undefined, offset?: number | undefined, userId?: string | undefined, userIds?: Array | undefined, resourceIds?: Array | undefined, clientId?: string | undefined, customerId?: string | undefined, associateId?: string | undefined, businessUnit?: string | undefined, type?: string | undefined, resourceKey?: string | undefined, source?: Source | undefined, changes?: Array | undefined, stores?: Array | undefined, excludePlatformInitiatedChanges?: Array | undefined, expand?: boolean | undefined, withTotal?: boolean | undefined}; export type GetApiProjectKeyResourceTypeOptions = {baseUrl?: string | undefined, oauth20?: string | undefined, fetch?: typeof fetch | undefined}; export const referenceTypeId = z.enum(["approval-flow", "approval-rule", "associate-role", "attribute-group", "business-unit", "cart", "cart-discount", "category", "channel", "customer", "customer-email-token", "customer-group", "customer-password-token", "direct-discount", "discount-code", "discount-group", "extension", "inventory-entry", "key-value-document", "order", "order-edit", "payment-method", "payment", "product", "product-discount", "product-price", "product-selection", "product-tailoring", "product-type", "quote", "quote-request", "recurrence-policy", "recurring-order", "review", "shipping-method", "shopping-list", "staged-quote", "standalone-price", "state", "store", "subscription", "tax-category", "type", "zone"]); export const reference = z.object({typeId: referenceTypeId, id: z.string()}); export const modifiedBy = z.object({isPlatformClient: z.boolean(), id: z.string().optional(), type: z.string(), clientId: z.string().optional(), anonymousId: z.string().optional(), customer: reference.optional(), associate: reference.optional()}); export const label = z.object({type: z.string()}); export const change = z.object({type: z.string(), change: z.string()}); export const resourceIdentifier = z.object({id: z.string().optional(), key: z.string().optional(), typeId: referenceTypeId}); export const keyReference = z.object({typeId: referenceTypeId, key: z.string()}); export const record = z.object({version: z.number().int(), previousVersion: z.number().int(), type: z.string(), modifiedBy: modifiedBy, modifiedAt: z.string(), label: label, previousLabel: label, changes: z.array(change), resource: resourceIdentifier, stores: z.array(keyReference), businessUnit: keyReference.optional(), withoutChanges: z.boolean()}); export const recordPagedQueryResponse = z.object({limit: z.number().int(), count: z.number().int(), total: z.number().int().optional(), offset: z.number().int(), results: z.array(record)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * The `view_audit_log:{projectKey}` scope is required, and depending on the [resource type](ctp:history:type:ChangeHistoryResourceType) queried, their respective scopes must be granted. * * GET /{projectKey}/{resourceType} */ export const getApiProjectKeyResourceType = async (args: GetApiProjectKeyResourceTypeArgs, options?: GetApiProjectKeyResourceTypeOptions) => { const {baseUrl = "https://history.europe-west1.gcp.commercetools.com", fetch: fetchFn = fetch, oauth20} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args['date.from'] != null) query.append("date.from", String(args['date.from'])) if (args['date.to'] != null) query.append("date.to", String(args['date.to'])) if (args.limit != null) query.append("limit", String(args.limit)) if (args.offset != null) query.append("offset", String(args.offset)) if (args.userId != null) query.append("userId", String(args.userId)) for (const item of args.userIds ?? []) query.append("userIds", String(item)) for (const item of args.resourceIds ?? []) query.append("resourceIds", String(item)) if (args.clientId != null) query.append("clientId", String(args.clientId)) if (args.customerId != null) query.append("customerId", String(args.customerId)) if (args.associateId != null) query.append("associateId", String(args.associateId)) if (args.businessUnit != null) query.append("businessUnit", String(args.businessUnit)) if (args.type != null) query.append("type", String(args.type)) if (args.resourceKey != null) query.append("resourceKey", String(args.resourceKey)) if (args.source != null) query.append("source", String(args.source)) for (const item of args.changes ?? []) query.append("changes", String(item)) for (const item of args.stores ?? []) query.append("stores", String(item)) for (const item of args.excludePlatformInitiatedChanges ?? []) query.append("excludePlatformInitiatedChanges", String(item)) if (args.expand != null) query.append("expand", String(args.expand)) if (args.withTotal != null) query.append("withTotal", String(args.withTotal)) if (oauth20 !== undefined) headers.set('authorization', `Bearer ${oauth20}`) const url = `${baseUrl.replace(/\/+$/, '')}/${encodeURIComponent(String(args.projectKey))}/${encodeURIComponent(String(args.resourceType))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(recordPagedQueryResponse, await res.json()) };