/* * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. * @generated-id: 7e457683073d */ import { CloudinaryAssetMgmtCore } from "../core.js"; import { encodeJSON, encodeSimple } from "../lib/encodings.js"; import { compactMap } from "../lib/primitives.js"; import { safeParse } from "../lib/schemas.js"; import { RequestOptions } from "../lib/sdks.js"; import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; import { pathToFunc } from "../lib/url.js"; import { APIError } from "../models/errors/apierror.js"; import { ConnectionError, InvalidRequestError, RequestAbortedError, RequestTimeoutError, UnexpectedClientError, } from "../models/errors/httpclienterrors.js"; import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; import { SearchParameters, SearchParameters$zodSchema, } from "../models/searchparameters.js"; import { APICall, APIPromise } from "../types/async.js"; import { Result } from "../types/fp.js"; /** * Provides a powerful query interface to filter and retrieve assets and their details * * @remarks * Returns a list of resources matching the specified search criteria. * * Uses a Lucene-like query language to filter assets by descriptive attributes (`public_id`, `asset_id`, `filename`, `display_name`, `folder` / `asset_folder`, `tags`, `context.`), file details (`resource_type`, `type`, `format`, `bytes`, `width`, `height`, `duration`, `pages`, `aspect_ratio`, `transparent`, `grayscale`), lifecycle dates (`uploaded_at`, `created_at`, `taken_at`, `updated_at`, `last_updated.`), moderation and lifecycle state (`status`, `moderation_status`, `moderation_kind`), embedded data (`image_metadata.*`), structured metadata (`metadata.`), and analysis fields (`face_count`, `colors`, `quality_score`, `illustration_score`, `accessibility_analysis.*`). Supports sorting, aggregate counts, and complex boolean expressions. See the `expression` parameter for the full field reference. * * ## Expression syntax * * - **Match**: `field:value` (token match) or `field=value` (exact match). Examples: `tags:shirt`, `tags=cotton`. * - **Comparisons**: `>`, `<`, `>=`, `<=` for numbers and dates. Example: `bytes>10000000`. * - **Ranges**: `field:[from TO to]` inclusive, `field:{from TO to}` exclusive. Example: `width:{200 TO 1028}`. * - **Booleans**: `AND`, `OR`, `NOT` (uppercase), or `+` (must), `-` (must not). `NOT` must appear between clauses — a bare leading `NOT` is a parse error; use `-field:value` to negate the first clause. Group with parentheses: `(shirt OR pants) AND clothes`. * - **Wildcards**: trailing `*` only, for prefix match (`public_id:shoes_*`, `format:jp*`, `tags:shirt*`). Not supported on `folder`, `asset_folder`, `resource_type`, or `type`. Leading `*`, middle `*`, `?`, and bare `*` (`folder:*`, `context.alt:*`) are all parse errors — wildcards cannot be used as a "field is present" probe. * - **Tokenized vs exact fields**: `tags`, `filename`, `display_name`, `context.`, and `metadata.` match on tokens split by whitespace and punctuation — `tags:analysis` matches the tag `full-analysis`. `public_id`, `folder`, `asset_folder`, and `format` match the whole value — `public_id:dog` will not match `dog_pldcwy`; use `public_id="dog_pldcwy"` (exact) or `public_id:dog*` (prefix). These exact-match fields still accept a trailing `*` for prefix match (except `folder` / `asset_folder`, where wildcards are ignored). * - **Dates**: ISO-8601 in quotes (`uploaded_at>"2024-01-15"`) or relative shorthand `Nh`, `Nd`, `Nw`, `Nm`, `Ny` (`uploaded_at>1d`, `created_at:[4w TO 1w]`). Send raw `<`/`>`, never HTML-escaped. * - **Quoting**: wrap any value containing a space, colon, or other reserved character (`! ( ) { } [ ] ^ ~ ? \ = & < > |`) in double quotes, or escape each character with `\`. Examples: `tags:"service:mantels"`, `aspect_ratio:"16:9"`, `folder:"My Folder"`. * * ## Common mistakes * * - Use `folder:` or `asset_folder:` (singular); `folders:`, `asset_folder_id:`, and other invented variants are not valid fields. Pass the exact folder name — wildcards do not apply here. * - There is no "has any value" / presence probe. `folder:*`, `metadata.alt:*`, `context.key:*`, `tags:*`, and `-tags:*` are all parse errors. See *"Which assets have any value for `metadata.`?"* under **Common tasks** for workarounds. * - `NOT foo AND bar` is a parse error. Write it as `bar AND NOT foo` or `-foo AND bar`, and keep every `NOT` between two clauses (`a AND NOT b AND NOT c` is fine; `NOT b AND NOT c …` is not). * - `public_id:dog` will not match `dog_pldcwy`. Use `public_id="dog_pldcwy"` (exact) or `public_id:dog*` (prefix). * - `tags=service:mantels` fails because the unquoted colon is parsed as a field separator. Use `tags="service:mantels"` or `tags=service\:mantels`. * - Do not HTML-escape operators. Send `uploaded_at<1h`, not `uploaded_at<1h`. * - Do not leave an operand empty (e.g. `tags: AND -tags:foo`). Omit the empty clause entirely. * * ## Tips * * - Set `max_results: 0` to return only `total_count` and `aggregations` without any resource payload — useful for counts and aggregation-only queries. * - `total_count` is always present in the response; prefer it over running an aggregation just to get a count. * - `aggregate` (both simple and range variants) and the `metadata`, `image_metadata`, `image_analysis` values of `with_field` require a Tier 2 search plan. * - Range aggregations require each range to include a `key` label (1–20 chars, `[a-zA-Z0-9_-]+`) and at least one of `from` / `to`. * * ## Common tasks * * - **Count matching assets** — put the filter in `expression` with `max_results: 0` and read `total_count` from the response. Works on every tier; no `aggregate` needed. * - **Preview one matching asset** — set `max_results: 1`; add `with_field: ["tags", "context"]` (or `metadata`, Tier 2) to inspect values. Prefer this over fetching and scanning a full page. * - **Distribution of values for a field** — Tier 2: `aggregate: [format|resource_type|type]` for enum counts, or range aggregations on `bytes`, `image_pixels`, `video_pixels`, or `duration`. Tier 1 fallback: run N small queries with `max_results: 0`, one per candidate value, and read `total_count` from each. * - **"Which assets have any value for `metadata.`?"** — not expressible directly (`metadata.X:*` is a parse error; there is no presence probe). Workarounds: (a) if the field has a known value set, enumerate — `metadata.region:(apac OR emea OR amer)`; (b) query broadly with `with_field: ["metadata"]` (Tier 2) and filter client-side for entries where the field is set; (c) at ingest time, attach a sentinel tag whenever the field is set, then search by that tag. * - **Newest / largest N** — keep the filter in `expression` and sort explicitly: `sort_by: [{uploaded_at: "desc"}]` with `max_results: 10`. * - **Filter by folder** — both `asset_folder:"parent/child"` and `folder:"parent/child"` match an exact folder path; there is no wildcard or "contains". To query across multiple folders, enumerate: `asset_folder:("campaigns/2024" OR "campaigns/2025")`. * - **Filter by metadata when you only know the label** — first call `list-metadata-fields` to resolve the label to an `external_id`, then query `metadata.:value`. * - **Multiple independent filters in one turn** — prefer one `expression` with `OR` / parentheses over firing many parallel calls: `metadata.region:apac OR metadata.region:emea` in a single request is faster and more reliable than two parallel requests. * * ## Examples * * - `tags:shirt AND uploaded_at>1d` * - `resource_type:image AND bytes>1000000 AND (format:png OR format:jpg)` * - `folder:products AND context.category:electronics` * - `tags:"service:mantels" AND -tags:discontinued` */ export function searchSearchAssets( client$: CloudinaryAssetMgmtCore, request: SearchParameters, options?: RequestOptions, ): APIPromise< Result< Response, | APIError | SDKValidationError | UnexpectedClientError | InvalidRequestError | RequestAbortedError | RequestTimeoutError | ConnectionError > > { return new APIPromise($do( client$, request, options, )); } async function $do( client$: CloudinaryAssetMgmtCore, request: SearchParameters, options?: RequestOptions, ): Promise< [ Result< Response, | APIError | SDKValidationError | UnexpectedClientError | InvalidRequestError | RequestAbortedError | RequestTimeoutError | ConnectionError >, APICall, ] > { const parsed$ = safeParse( request, (value$) => SearchParameters$zodSchema.parse(value$), "Input validation failed", ); if (!parsed$.ok) { return [parsed$, { status: "invalid" }]; } const payload$ = parsed$.value; const body$ = encodeJSON("body", payload$, { explode: true }); const pathParams$ = { cloud_name: encodeSimple("cloud_name", client$._options.cloud_name, { explode: false, charEncoding: "percent", }), }; const path$ = pathToFunc("/v1_1/{cloud_name}/resources/search")( pathParams$, ); const headers$ = new Headers(compactMap({ "Content-Type": "application/json", Accept: "application/json", })); const securityInput = await extractSecurity(client$._options.security); const requestSecurity = resolveGlobalSecurity(securityInput); const context = { options: client$._options, baseURL: options?.serverURL ?? client$._baseURL ?? "", operationID: "searchAssets", oAuth2Scopes: null, resolvedSecurity: requestSecurity, securitySource: client$._options.security, retryConfig: options?.retries || client$._options.retryConfig || { strategy: "none" }, retryCodes: options?.retryCodes || [ "429", "500", "502", "503", "504", ], }; const requestRes = client$._createRequest(context, { security: requestSecurity, method: "POST", baseURL: options?.serverURL, path: path$, headers: headers$, body: body$, userAgent: client$._options.userAgent, timeoutMs: options?.timeoutMs || client$._options.timeoutMs || -1, }, options); if (!requestRes.ok) { return [requestRes, { status: "invalid" }]; } const req$ = requestRes.value; const doResult = await client$._do(req$, { context, errorCodes: [], retryConfig: context.retryConfig, retryCodes: context.retryCodes, }); if (!doResult.ok) { return [doResult, { status: "request-error", request: req$ }]; } return [doResult, { status: "complete", "request": req$, response: doResult.value, }]; }