{"version":3,"file":"client.cjs","names":["createThrottleManager","createClient","createConfig","ClientError","createAssetFoldersResource","createAssetsResource","createComponentFoldersResource","createDatasourceEntriesResource","createDatasourcesResource","createExperimentsResource","createInternalTagsResource","createPresetsResource","createSharedAssetFoldersResource","createSharedAssetsResource","createSharedInternalTagsResource","createSpacesResource","createUsersResource","createComponentsResource","createStoriesResource"],"sources":["../src/client.ts"],"sourcesContent":["import type { Client, ResolvedRequestOptions, RetryOptions } from './generated/mapi/client';\nimport type { Middleware } from './generated/mapi/client/utils.gen';\nimport { createClient, createConfig } from './generated/mapi/client';\nimport { getManagementBaseUrl } from '@storyblok/region-helper';\nimport type { Region } from '@storyblok/region-helper';\nimport type { Block } from './generated/types/block';\nimport { ClientError } from './error';\nimport type { RateLimitConfig } from './utils/rate-limit';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { querySerializer } from './utils/query-serializer';\nimport { createAssetFoldersResource } from './resources/asset-folders';\nimport { createAssetsResource } from './resources/assets';\nimport { createComponentFoldersResource } from './resources/component-folders';\nimport { createComponentsResource } from './resources/components';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createExperimentsResource } from './resources/experiments';\nimport { createInternalTagsResource } from './resources/internal-tags';\nimport { createPresetsResource } from './resources/presets';\nimport { createSharedAssetFoldersResource } from './resources/shared-asset-folders';\nimport { createSharedAssetsResource } from './resources/shared-assets';\nimport { createSharedInternalTagsResource } from './resources/shared-internal-tags';\nimport { createSpacesResource } from './resources/spaces';\nimport { createStoriesResource } from './resources/stories';\nimport { createUsersResource } from './resources/users';\n\n// ---------------------------------------------------------------------------\n// Client types (co-located with runtime)\n// ---------------------------------------------------------------------------\n\nexport type ApiResponse<T, ThrowOnError extends boolean = false> =\n  ThrowOnError extends true\n    ? { data: T; error?: never; response: Response; request: Request }\n    : | { data: T; error: undefined; response: Response; request: Request }\n      | { data: undefined; error: ClientError; response: Response; request: Request };\n\nexport interface RequestConfigOverrides {\n  throwOnError?: boolean;\n}\n\n/**\n * Arbitrary options forwarded to the underlying `fetch()` call.\n *\n * Standard `RequestInit` properties (`cache`, `credentials`, `mode`, …) and\n * non-standard, vendor-specific properties (Next.js `next`, Cloudflare `cf`, …)\n * are both supported.\n *\n * @example\n * ```ts\n * client.stories.get(123, {\n *   fetchOptions: {\n *     cache: 'no-store',\n *     next: { revalidate: 60 },\n *   },\n * })\n * ```\n */\nexport type FetchOptions = Record<string, unknown>;\n\nexport interface HttpRequestOptions {\n  query?: Record<string, unknown>;\n  body?: unknown;\n  headers?: Record<string, string>;\n  signal?: AbortSignal;\n  throwOnError?: RequestConfigOverrides['throwOnError'];\n  fetchOptions?: FetchOptions;\n}\n\n/**\n * Dependencies injected into every resource factory.\n */\nexport interface MapiResourceDeps<DefaultThrowOnError extends boolean = false> {\n  client: Client;\n  spaceId?: number;\n  wrapRequest: <TData, ThrowOnError extends boolean = DefaultThrowOnError>(fn: () => Promise<unknown>, throwOnError?: ThrowOnError) => Promise<ApiResponse<TData, ThrowOnError>>;\n}\n\ntype TokenConfig =\n  | {\n    /** Personal access token for authentication. */\n    personalAccessToken: string;\n    oauthToken?: never;\n  }\n  | {\n    personalAccessToken?: never;\n    /** OAuth bearer token for authentication. */\n    oauthToken: string;\n  }\n  | {\n    personalAccessToken?: undefined;\n    oauthToken?: undefined;\n  };\n\nexport type ManagementApiClientConfig<\n  ThrowOnError extends boolean = false,\n> = TokenConfig & {\n  /**\n   * The Storyblok space ID. Used as the default for space-scoped endpoints.\n   * You can also override it per request via `path.space_id`.\n   */\n  spaceId?: number;\n  /**\n   * Storyblok region. Determines the base URL.\n   * @default 'eu'\n   */\n  region?: Region;\n  /**\n   * Override the base URL entirely (e.g. for testing).\n   */\n  baseUrl?: string;\n  /**\n   * Additional request headers.\n   */\n  headers?: Record<string, string>;\n  /**\n   * Throw on HTTP errors instead of returning them.\n   * @default false\n   */\n  throwOnError?: ThrowOnError;\n  /**\n   * Retry configuration for failed requests.\n   */\n  retry?: RetryOptions;\n  /**\n   * Request timeout in milliseconds.\n   * @default 30_000\n   */\n  timeout?: number;\n  /**\n   * Preventive rate limiting to avoid hitting the Storyblok Management API rate limits.\n   *\n   * - `undefined` (default): single bucket at 6 requests per second.\n   * - `number`: fixed requests per second.\n   * - `{ requestsPerSecond?: number }`: full config.\n   * - `false`: disable rate limiting entirely.\n   */\n  rateLimit?: RateLimitConfig | number | false;\n};\n\n// ---------------------------------------------------------------------------\n// Client factory\n// ---------------------------------------------------------------------------\n\nfunction getAuthorizationHeader(config: ManagementApiClientConfig<boolean>): string | undefined {\n  if (config.personalAccessToken) {\n    return config.personalAccessToken;\n  }\n  if (config.oauthToken) {\n    return config.oauthToken.startsWith('Bearer ')\n      ? config.oauthToken\n      : `Bearer ${config.oauthToken}`;\n  }\n  return undefined;\n}\n\nconst createManagementApiClientBase = <DefaultThrowOnError extends boolean = false>(\n  config: ManagementApiClientConfig<DefaultThrowOnError>,\n): {\n  deps: MapiResourceDeps<DefaultThrowOnError>;\n  resources: Omit<ReturnType<typeof buildResources<DefaultThrowOnError>>, never>;\n} => {\n  const {\n    spaceId,\n    region = 'eu',\n    baseUrl,\n    headers = {},\n    throwOnError = false,\n    retry = {\n      limit: 12,\n      backoffLimit: 20_000,\n      methods: ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'],\n      statusCodes: [429],\n    },\n    timeout = 30_000,\n    rateLimit,\n  } = config;\n\n  const throttleManager = createThrottleManager(rateLimit ?? {});\n  const authHeader = getAuthorizationHeader(config);\n\n  const client: Client = createClient(\n    createConfig({\n      baseUrl: baseUrl || getManagementBaseUrl(region),\n      headers: {\n        ...(authHeader ? { Authorization: authHeader } : {}),\n        ...headers,\n      },\n      // Default serializer throws on nested objects; MAPI needs `filter_query`\n      // serialized as a nested hash (`filter_query[field][op]=value`).\n      querySerializer,\n      throwOnError,\n      kyOptions: {\n        throwHttpErrors: true,\n        timeout,\n        retry,\n      },\n    }),\n  );\n\n  client.interceptors.error.use(\n    (error: unknown, response: Response) =>\n      new ClientError(response?.statusText || 'API request failed', {\n        status: response?.status ?? 0,\n        statusText: response?.statusText ?? '',\n        data: error,\n      }),\n  );\n\n  function wrapRequest<TData, CurrentThrowOnError extends boolean = DefaultThrowOnError>(\n    fn: () => Promise<unknown>,\n    _throwOnError?: CurrentThrowOnError,\n  ): Promise<ApiResponse<TData, CurrentThrowOnError>> {\n    return throttleManager.execute(\n      () => fn() as Promise<ApiResponse<TData, CurrentThrowOnError>>,\n    );\n  }\n\n  const deps: MapiResourceDeps<DefaultThrowOnError> = { client, spaceId, wrapRequest };\n  return { deps, resources: buildResources(deps, client) };\n};\n\nfunction buildResources<DefaultThrowOnError extends boolean = false>(\n  deps: MapiResourceDeps<DefaultThrowOnError>,\n  client: Client,\n) {\n  /**\n   * Escape hatch: send a GET request to any MAPI endpoint not yet wrapped\n   * in a dedicated resource method.\n   */\n  const httpGet = <TData = unknown>(\n    path: string,\n    options: HttpRequestOptions = {},\n  ): Promise<ApiResponse<TData, DefaultThrowOnError>> => {\n    const { fetchOptions, ...rest } = options;\n    return deps.wrapRequest<TData>(() =>\n      client.get({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n    );\n  };\n\n  /**\n   * Escape hatch: send a POST request to any MAPI endpoint not yet wrapped\n   * in a dedicated resource method.\n   */\n  const httpPost = <TData = unknown>(\n    path: string,\n    options: HttpRequestOptions = {},\n  ): Promise<ApiResponse<TData, DefaultThrowOnError>> => {\n    const { fetchOptions, ...rest } = options;\n    return deps.wrapRequest<TData>(() =>\n      client.post({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n    );\n  };\n\n  /**\n   * Escape hatch: send a PUT request to any MAPI endpoint not yet wrapped\n   * in a dedicated resource method.\n   */\n  const httpPut = <TData = unknown>(\n    path: string,\n    options: HttpRequestOptions = {},\n  ): Promise<ApiResponse<TData, DefaultThrowOnError>> => {\n    const { fetchOptions, ...rest } = options;\n    return deps.wrapRequest<TData>(() =>\n      client.put({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n    );\n  };\n\n  /**\n   * Escape hatch: send a PATCH request to any MAPI endpoint not yet wrapped\n   * in a dedicated resource method.\n   */\n  const httpPatch = <TData = unknown>(\n    path: string,\n    options: HttpRequestOptions = {},\n  ): Promise<ApiResponse<TData, DefaultThrowOnError>> => {\n    const { fetchOptions, ...rest } = options;\n    return deps.wrapRequest<TData>(() =>\n      client.patch({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n    );\n  };\n\n  /**\n   * Escape hatch: send a DELETE request to any MAPI endpoint not yet wrapped\n   * in a dedicated resource method.\n   */\n  const httpDelete = <TData = unknown>(\n    path: string,\n    options: HttpRequestOptions = {},\n  ): Promise<ApiResponse<TData, DefaultThrowOnError>> => {\n    const { fetchOptions, ...rest } = options;\n    return deps.wrapRequest<TData>(() =>\n      client.delete({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n    );\n  };\n\n  return {\n    assetFolders: createAssetFoldersResource(deps),\n    assets: createAssetsResource(deps),\n    componentFolders: createComponentFoldersResource(deps),\n    datasourceEntries: createDatasourceEntriesResource(deps),\n    datasources: createDatasourcesResource(deps),\n    experiments: createExperimentsResource(deps),\n    delete: httpDelete,\n    get: httpGet,\n    patch: httpPatch,\n    interceptors: client.interceptors as Middleware<Request, Response, unknown, ResolvedRequestOptions>,\n    internalTags: createInternalTagsResource(deps),\n    post: httpPost,\n    presets: createPresetsResource(deps),\n    put: httpPut,\n    sharedAssetFolders: createSharedAssetFoldersResource(deps),\n    sharedAssets: createSharedAssetsResource(deps),\n    sharedInternalTags: createSharedInternalTagsResource(deps),\n    spaces: createSpacesResource(deps),\n    users: createUsersResource<DefaultThrowOnError>({ client, wrapRequest: deps.wrapRequest }),\n  };\n}\n\ntype StoryblokTypesConfig = { components: Block } | { blocks: Block };\n\ntype ResolveComponents<T extends StoryblokTypesConfig> =\n  T extends { components: infer C extends Block } ? C\n    : T extends { blocks: infer B extends Block } ? B\n      : never;\n\n/** Extracts the `fieldType → value` plugin map from a Schema, defaulting to an empty map. */\ntype ResolveFieldPlugins<T> = T extends { fieldPlugins: infer P } ? P : Record<never, never>;\n\n/**\n * The return type of `createManagementApiClient`, parameterised by `TBlocks` so that\n * `.stories` methods can narrow story content types without touching the runtime object.\n * Component *definitions* (`.components`) are wire-shaped and not narrowed by `TBlocks`.\n */\nexport type ManagementApiClient<\n  TBlocks extends Block = Block,\n  TFieldPlugins = Record<never, never>,\n  DefaultThrowOnError extends boolean = false,\n> = ReturnType<typeof buildResources<DefaultThrowOnError>> & {\n  components: ReturnType<typeof createComponentsResource<DefaultThrowOnError>>;\n  stories: ReturnType<typeof createStoriesResource<TBlocks, TFieldPlugins, DefaultThrowOnError>>;\n  /**\n   * Returns the same client instance cast to a version that narrows story content\n   * to the provided component types. No runtime cost — type parameter is erased.\n   *\n   * Accepts either `{ components: ... }` or `{ blocks: ... }` — the latter matches the\n   * `Schema` type produced by `@storyblok/schema`'s `InferSchema`.\n   *\n   * @example\n   * ```ts\n   * import type { Schema } from './schema';\n   *\n   * const client = createManagementApiClient({ personalAccessToken: '...' })\n   *   .withTypes<Schema>();\n   * ```\n   */\n  withTypes: <T extends StoryblokTypesConfig>() => ManagementApiClient<ResolveComponents<T>, ResolveFieldPlugins<T>, DefaultThrowOnError>;\n};\n\nexport const createManagementApiClient = <\n  DefaultThrowOnError extends boolean = false,\n>(\n  config: ManagementApiClientConfig<DefaultThrowOnError>,\n): ManagementApiClient<Block, Record<never, never>, DefaultThrowOnError> => {\n  const { deps, resources } = createManagementApiClientBase(config);\n  const self: ManagementApiClient<Block, Record<never, never>, DefaultThrowOnError> = {\n    ...resources,\n    components: createComponentsResource<DefaultThrowOnError>(deps),\n    stories: createStoriesResource<Block, Record<never, never>, DefaultThrowOnError>(deps),\n    withTypes<T extends StoryblokTypesConfig>() {\n      return self as unknown as ManagementApiClient<ResolveComponents<T>, ResolveFieldPlugins<T>, DefaultThrowOnError>;\n    },\n  };\n  return self;\n};\n"],"mappings":"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"}