{"version":3,"file":"client.cjs","names":["createThrottleManager","createClient","createConfig","getManagementBaseUrl","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> = ThrowOnError extends true\n  ? { data: T; error?: never; response: Response; request: Request }\n  :\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>(\n    fn: () => Promise<unknown>,\n    throwOnError?: ThrowOnError,\n  ) => 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<ThrowOnError extends boolean = false> = 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(() => fn() as Promise<ApiResponse<TData, CurrentThrowOnError>>);\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({\n        url: path,\n        ...rest,\n        ...(fetchOptions\n          ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } }\n          : {}),\n      }),\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({\n        url: path,\n        ...rest,\n        ...(fetchOptions\n          ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } }\n          : {}),\n      }),\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({\n        url: path,\n        ...rest,\n        ...(fetchOptions\n          ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } }\n          : {}),\n      }),\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({\n        url: path,\n        ...rest,\n        ...(fetchOptions\n          ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } }\n          : {}),\n      }),\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({\n        url: path,\n        ...rest,\n        ...(fetchOptions\n          ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } }\n          : {}),\n      }),\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<\n      Request,\n      Response,\n      unknown,\n      ResolvedRequestOptions\n    >,\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> = T extends {\n  components: infer C extends Block;\n}\n  ? C\n  : T extends { blocks: infer B extends Block }\n    ? 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<\n    ResolveComponents<T>,\n    ResolveFieldPlugins<T>,\n    DefaultThrowOnError\n  >;\n};\n\nexport const createManagementApiClient = <DefaultThrowOnError extends boolean = false>(\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<\n        ResolveComponents<T>,\n        ResolveFieldPlugins<T>,\n        DefaultThrowOnError\n      >;\n    },\n  };\n  return self;\n};\n"],"mappings":"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"}