@intlayer/api 9.2.0 → 9.3.1

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/README.md CHANGED
@@ -47,27 +47,27 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
47
47
 
48
48
  ## Keys benefits of Intlayer:
49
49
 
50
- | Feature | Description |
51
- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
53
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
54
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
55
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
56
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
57
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
58
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
59
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code) |
60
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
61
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
62
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
63
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
66
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
67
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
68
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
69
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) |
70
- | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
50
+ | Feature | Description |
51
+ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/frameworks.png?raw=true" alt="Feature" width="700"> | **Cross-Frameworks Support**<br><br>Intlayer is compatible with all major frameworks and libraries, including Next.js, React, Vite, Vue.js, Nuxt, Preact, Express, and more. |
53
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/javascript_content_management.jpg?raw=true" alt="Feature" width="700"> | **JavaScript-Powered Content Management**<br><br>Harness the flexibility of JavaScript to define and manage your content efficiently. <br><br> - [Content declaration](https://intlayer.org/doc/concept/content) |
54
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/per_locale_content_declaration_file.png?raw=true" alt="Feature" width="700"> | **Per-Locale Content Declaration File**<br><br>Speed up your development by declaring your content once, before auto generation.<br><br> - [Per-Locale Content Declaration File](https://intlayer.org/doc/concept/per-locale-file) |
55
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/compiler.jpg?raw=true" alt="Feature" width="700"> | **Compiler**<br><br>The Intlayer Compiler extract automatically the content from the components and generate the dictionary files.<br><br> - [Compiler](https://intlayer.org/doc/compiler) |
56
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true" alt="Feature" width="700"> | **Type-Safe Environment**<br><br>Leverage TypeScript to ensure your content definitions and code are error-free, while also benefiting from IDE autocompletion.<br><br> - [TypeScript configuration](https://intlayer.org/doc/environment/vite-and-react#configure-typescript) |
57
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/config_file.png?raw=true" alt="Feature" width="700"> | **Simplified Setup**<br><br>Get up and running quickly with minimal configuration. Adjust settings for internationalization, routing, AI, build, and content handling with ease. <br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
58
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/content_retrieval.png?raw=true" alt="Feature" width="700"> | **Simplified Content Retrieval**<br><br>No need to call your `t` function for each piece of content. Retrieve all your content directly using a single hook.<br><br> - [React integration](https://intlayer.org/doc/environment/create-react-app) |
59
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/server_component.png?raw=true" alt="Feature" width="700"> | **Consistent Server Component Implementation**<br><br>Perfectly suited for Next.js server components, use the same implementation for both client and server components, no need to pass your `t` function across each server component. <br><br> - [Server Components](https://intlayer.org/doc/environment/nextjs#step-7-utilize-content-in-your-code) |
60
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/file_tree.png?raw=true" alt="Feature" width="700"> | **Organized Codebase**<br><br>Keep your codebase more organized: 1 component = 1 dictionary in the same folder. Translations close to their respective components, enhance maintainability and clarity. <br><br> - [How Intlayer works](https://intlayer.org/doc/concept/how-works-intlayer) |
61
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/url_routing.png?raw=true" alt="Feature" width="700"> | **Enhanced Routing**<br><br>Full support of app routing, adapting seamlessly to complex application structures, for Next.js, React, Vite, Vue.js, etc.<br><br> - [Explore Next.js integration](https://intlayer.org/doc/environment/nextjs) |
62
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/markdown.png?raw=true" alt="Feature" width="700"> | **Markdown Support**<br><br>Import and interpret, locale files and remote Markdown for multilingual content like privacy policies, documentation, etc. Interpret and make Markdown metadata accessible in your code.<br><br> - [Content files](https://intlayer.org/doc/concept/content/file) |
63
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/visual_editor.png?raw=true" alt="Feature" width="700"> | **Free Visual Editor & CMS**<br><br>A free visual editor and CMS are available for content writers, removing the need for a localization platform. Keep your content synchronized using Git, or externalize it totally or partially with the CMS.<br><br> - [Intlayer Editor](https://intlayer.org/doc/concept/editor) <br> - [Intlayer CMS](https://intlayer.org/doc/concept/cms) |
64
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true" alt="Feature" width="700"> | **Tree-shakable Content**<br><br>Tree-shakable content, reducing the size of the final bundle. Loads content per component, excluding any unused content from your bundle. Supports lazy loading to enhance app loading efficiency. <br><br> - [App build optimization](https://intlayer.org/doc/concept/how-works-intlayer#app-build-optimization) |
65
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/static_rendering.png?raw=true" alt="Feature" width="700"> | **Static Rendering**<br><br>Doesn't block Static Rendering. <br><br> - [Next.js integration](https://intlayer.org/doc/environment/nextjs) |
66
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/AI_translation.png?raw=true" alt="Feature" width="700"> | **AI-Powered Translation**<br><br>Transform your website into 231 languages with just one click using Intlayer's advanced AI-powered translation tools using your own AI provider / API key. <br><br> - [CI/CD integration](https://intlayer.org/doc/concept/ci-cd) <br> - [Intlayer CLI](https://intlayer.org/doc/concept/cli) <br> - [Auto fill](https://intlayer.org/doc/concept/auto-fill) |
67
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/mcp.png?raw=true" alt="Feature" width="700"> | **MCP Server Integration**<br><br>Provides an MCP (Model Context Protocol) server for IDE automation, enabling seamless content management and i18n workflows directly within your development environment. <br><br> - [MCP Server](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/mcp_server.md) |
68
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/vscode_extension.png?raw=true" alt="Feature" width="700"> | **VSCode Extension**<br><br>Intlayer provides a VSCode extension to help you manage your content and translations, building your dictionaries, translating your content, and more. <br><br> - [VSCode Extension](https://intlayer.org/doc/vs-code-extension) |
69
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
70
+ | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
71
71
 
72
72
  ---
73
73
 
@@ -162,7 +162,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
162
162
  <li><a href="https://intlayer.org/doc/concept/cms" rel=''>Intlayer CMS</a></li>
163
163
  <li><a href="https://intlayer.org/doc/concept/content" rel=''>Dictionary</a>
164
164
  <ul>
165
- <li><a href="https://intlayer.org/doc/concept/content/per-locale-file" rel=''>Per-Locale Content Declaration File</a></li>
165
+ <li><a href="https://intlayer.org/doc/concept/per-locale-file" rel=''>Per-Locale Content Declaration File</a></li>
166
166
  <li><a href="https://intlayer.org/doc/concept/content/translation" rel=''>Translation</a></li>
167
167
  <li><a href="https://intlayer.org/doc/concept/content/enumeration" rel=''>Enumeration</a></li>
168
168
  <li><a href="https://intlayer.org/doc/concept/content/condition" rel=''>Condition</a></li>
@@ -183,7 +183,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
183
183
  <ul>
184
184
  <li><a href="https://intlayer.org/doc/environment/nextjs/15" rel=''>Next.js 15</a></li>
185
185
  <li><a href="https://intlayer.org/doc/environment/nextjs/14" rel=''>Next.js 14 (App Router)</a></li>
186
- <li><a href="https://intlayer.org/doc/environment/nextjs/next-with-Page-Router" rel=''>Next.js Page Router</a></li>
186
+ <li><a href="https://intlayer.org/doc/environment/nextjs/next-with-page-router" rel=''>Next.js Page Router</a></li>
187
187
  <li><a href="https://intlayer.org/doc/environment/nextjs/compiler" rel=''>Next.js using Compiler</a></li>
188
188
  </ul>
189
189
  </li>
@@ -212,7 +212,7 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
212
212
  <li><a href="https://intlayer.org/doc/environment/sveltekit" rel=''>SvelteKit</a></li>
213
213
  <li><a href="https://intlayer.org/doc/environment/vite-and-preact" rel=''>Vite + Preact</a></li>
214
214
  <li><a href="https://intlayer.org/doc/environment/vite-and-vue" rel=''>Vite + Vue</a></li>
215
- <li><a href="https://intlayer.org/doc/environment/vite-and-nuxt" rel=''>Vite + Nuxt</a></li>
215
+ <li><a href="https://intlayer.org/doc/environment/nuxt-and-vue" rel=''>Vite + Nuxt</a></li>
216
216
  <li><a href="https://intlayer.org/doc/environment/vite-and-solid" rel=''>Vite + Solid</a></li>
217
217
  <li><a href="https://intlayer.org/doc/environment/angular" rel=''>Angular</a></li>
218
218
  <li>
@@ -1 +1 @@
1
- {"version":3,"file":"createAuthManager.cjs","names":["getOAuthAPI"],"sources":["../../../src/cms/createAuthManager.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { defu } from 'defu';\nimport type { FetcherOptions } from '../fetcher';\nimport { getOAuthAPI } from '../getIntlayerAPI/oAuth';\n\n/**\n * Shape of the various OAuth2 token payloads the backend may return. Only the\n * fields used to derive the expiration timestamp are described here.\n */\ntype OAuthTokenLike = {\n accessToken?: string;\n accessTokenExpiresAt?: string | Date;\n expires_in?: number;\n expiresIn?: number;\n expiresAt?: string | Date;\n};\n\n/**\n * Any asynchronous API method exposed by a domain section\n * (e.g. `getDictionaries`, `pushDictionaries`).\n */\ntype AsyncMethod<Arguments extends unknown[], Result> = (\n ...args: Arguments\n) => Promise<Result>;\n\n/**\n * A domain section factory: builds a plain object of async methods from shared\n * fetcher options and the Intlayer configuration.\n */\ntype SectionFactory<Section extends Record<string, unknown>> = (\n fetcherOptions: FetcherOptions,\n intlayerConfig: IntlayerConfig\n) => Section;\n\nconst ONE_MINUTE_MS = 60_000;\n\n/**\n * Resolves the expiration timestamp (in ms since epoch) from an OAuth2\n * token-like payload, supporting both absolute dates and relative durations.\n */\nconst getExpiryTimestamp = (\n token: OAuthTokenLike | undefined\n): number | undefined => {\n if (!token) return undefined;\n\n const dateLike = (token.accessTokenExpiresAt ?? token.expiresAt) as\n | string\n | Date\n | undefined;\n\n if (dateLike) {\n const timestamp =\n typeof dateLike === 'string'\n ? Date.parse(dateLike)\n : dateLike.getTime?.();\n if (typeof timestamp === 'number' && Number.isFinite(timestamp)) {\n return timestamp;\n }\n }\n\n const seconds = token.expires_in ?? token.expiresIn;\n if (typeof seconds === 'number' && Number.isFinite(seconds)) {\n return Date.now() + seconds * 1000;\n }\n\n return undefined;\n};\n\n/**\n * Options accepted when creating an {@link AuthManager}.\n */\nexport type AuthManagerOptions = {\n /**\n * Base fetcher options merged into every request (e.g. custom headers).\n */\n baseFetcherOptions?: FetcherOptions;\n /**\n * A pre-issued CLI session token (prefixed with `clisession_`). When provided,\n * it is used directly as the Bearer token and the OAuth2 `client_credentials`\n * exchange is skipped entirely.\n */\n sessionToken?: string;\n};\n\n/**\n * Options accepted when binding a domain section to an {@link AuthManager}.\n */\nexport type BindSectionOptions = {\n /**\n * Forces auth injection on (`false`) or off (`true`). Defaults to enabled\n * whenever credentials are available.\n */\n skipAuth?: boolean;\n};\n\n/**\n * Manages CMS authentication for a set of API calls.\n *\n * The manager owns a single mutable {@link FetcherOptions} object\n * (`fetcherOptions`). Domain factories bound through it share the same\n * reference, so refreshing the token in place transparently authenticates every\n * call — without rebuilding the API clients.\n */\nexport type AuthManager = {\n /**\n * Mutable fetcher options carrying the `Authorization` header. Bound sections\n * share this reference so the injected token is reused everywhere.\n */\n fetcherOptions: FetcherOptions;\n /**\n * The resolved Intlayer configuration (merged with the build-time defaults).\n */\n intlayerConfig: IntlayerConfig;\n /**\n * `true` when credentials are available — either a session token or a\n * `clientId`/`clientSecret` pair in the configuration.\n */\n hasCredentials: boolean;\n /**\n * Ensures a valid access token is available and applies it to\n * `fetcherOptions`. Called automatically by {@link withAuth}.\n */\n ensureAuth: () => Promise<void>;\n /**\n * Forces a token refresh on the next call by clearing the cached token.\n */\n reset: () => void;\n /**\n * Wraps a single API method so it injects (and, on failure, refreshes) the\n * access token on every invocation while preserving the method's signature.\n */\n withAuth: <Arguments extends unknown[], Result>(\n method: AsyncMethod<Arguments, Result>,\n skipAuth?: boolean\n ) => AsyncMethod<Arguments, Result>;\n /**\n * Instantiates a domain factory with the managed fetcher options and config,\n * returning a section whose every method authenticates automatically.\n *\n * @example\n * ```ts\n * const dictionary = authManager.bindSection(getDictionaryAPI);\n * await dictionary.pushDictionaries(dictionaries);\n * ```\n */\n bindSection: <Section extends Record<string, unknown>>(\n factory: SectionFactory<Section>,\n options?: BindSectionOptions\n ) => Section;\n};\n\n/**\n * Creates an instance-scoped {@link AuthManager} handling the OAuth2\n * `client_credentials` flow (or a pre-issued CLI session token).\n *\n * Unlike a global token cache, each manager keeps its own token state, so\n * independent SDK instances never interfere with one another.\n *\n * @param intlayerConfig - Intlayer configuration carrying the `editor`\n * credentials. Defaults to the build-time configuration.\n * @param options - Optional session token and base fetcher options.\n */\nexport const createAuthManager = (\n intlayerConfig: Pick<IntlayerConfig, 'editor'> = { editor },\n options: AuthManagerOptions = {}\n): AuthManager => {\n const { baseFetcherOptions = {}, sessionToken } = options;\n\n const resolvedConfig = defu(intlayerConfig ?? {}, {\n editor,\n }) as IntlayerConfig;\n\n // `credentials: 'omit'` prevents the browser from attaching session cookies;\n // authentication is handled exclusively through the injected Bearer token.\n // This is required because the backend only allows credentialed requests for\n // whitelisted first-party origins.\n const fetcherOptions: FetcherOptions = {\n ...baseFetcherOptions,\n credentials: 'omit',\n };\n\n const hasCredentials =\n Boolean(sessionToken) ||\n Boolean(\n resolvedConfig?.editor?.clientId && resolvedConfig?.editor?.clientSecret\n );\n\n // A session token is used as-is and never expires within the SDK's concern,\n // so inject it once up-front and skip the OAuth2 exchange.\n if (sessionToken) {\n fetcherOptions.headers = {\n ...(fetcherOptions.headers ?? {}),\n Authorization: `Bearer ${sessionToken}`,\n } as HeadersInit;\n }\n\n let accessToken: string | undefined;\n let expiryTimestamp: number | undefined;\n let pendingRefresh: Promise<void> | undefined;\n\n const needsRefresh = (): boolean => {\n if (!accessToken) return true;\n if (!expiryTimestamp) return false; // Unknown expiry: assume usable until failure.\n\n // Refresh one minute before the actual expiry to avoid edge-of-expiry races.\n return Date.now() + ONE_MINUTE_MS >= expiryTimestamp;\n };\n\n const refreshToken = async (): Promise<void> => {\n const doRefresh = async (): Promise<void> => {\n const oAuthAPI = getOAuthAPI({}, resolvedConfig);\n const response = await oAuthAPI.getOAuth2AccessToken();\n const tokenData = response?.data as OAuthTokenLike | undefined;\n\n accessToken = tokenData?.accessToken;\n expiryTimestamp = getExpiryTimestamp(tokenData);\n };\n\n // De-duplicate concurrent refreshes so a burst of calls triggers one fetch.\n pendingRefresh ??= doRefresh().finally(() => {\n pendingRefresh = undefined;\n });\n\n await pendingRefresh;\n };\n\n const applyAuthHeader = (): void => {\n if (!accessToken) return;\n fetcherOptions.headers = {\n ...(fetcherOptions.headers ?? {}),\n Authorization: `Bearer ${accessToken}`,\n } as HeadersInit;\n };\n\n const ensureAuth = async (): Promise<void> => {\n if (sessionToken) return; // Already injected; nothing to refresh.\n if (needsRefresh()) {\n await refreshToken();\n }\n applyAuthHeader();\n };\n\n const reset = (): void => {\n accessToken = undefined;\n expiryTimestamp = undefined;\n };\n\n const withAuth = <Arguments extends unknown[], Result>(\n method: AsyncMethod<Arguments, Result>,\n skipAuth = !hasCredentials\n ): AsyncMethod<Arguments, Result> => {\n if (skipAuth) return method;\n\n return async (...args: Arguments): Promise<Result> => {\n await ensureAuth();\n\n try {\n return await method(...args);\n } catch (error) {\n // The token may have been revoked or expired early: refresh once and\n // retry before surfacing the error. A session token cannot be\n // refreshed, so re-throw immediately in that case.\n if (sessionToken) throw error;\n\n await refreshToken();\n applyAuthHeader();\n return await method(...args);\n }\n };\n };\n\n const bindSection = <Section extends Record<string, unknown>>(\n factory: SectionFactory<Section>,\n bindOptions: BindSectionOptions = {}\n ): Section => {\n const section = factory(fetcherOptions, resolvedConfig);\n const skipAuth = bindOptions.skipAuth ?? !hasCredentials;\n\n return new Proxy(section, {\n get(target, property, receiver) {\n const value = Reflect.get(target, property, receiver);\n\n if (typeof value !== 'function') return value;\n\n return withAuth(\n (value as AsyncMethod<unknown[], unknown>).bind(target),\n skipAuth\n );\n },\n });\n };\n\n return {\n fetcherOptions,\n intlayerConfig: resolvedConfig,\n hasCredentials,\n ensureAuth,\n reset,\n withAuth,\n bindSection,\n };\n};\n"],"mappings":";;;;;;AAmCA,MAAM,gBAAgB;;;;;AAMtB,MAAM,sBACJ,UACuB;CACvB,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,WAAY,MAAM,wBAAwB,MAAM;CAKtD,IAAI,UAAU;EACZ,MAAM,YACJ,OAAO,aAAa,WAChB,KAAK,MAAM,QAAQ,IACnB,SAAS,UAAU;EACzB,IAAI,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,GAC5D,OAAO;CAEX;CAEA,MAAM,UAAU,MAAM,cAAc,MAAM;CAC1C,IAAI,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,GACxD,OAAO,KAAK,IAAI,IAAI,UAAU;AAIlC;;;;;;;;;;;;AAgGA,MAAa,qBACX,iBAAiD,EAAE,sCAAO,GAC1D,UAA8B,CAAC,MACf;CAChB,MAAM,EAAE,qBAAqB,CAAC,GAAG,iBAAiB;CAElD,MAAM,gCAAsB,kBAAkB,CAAC,GAAG,EAChD,sCACF,CAAC;CAMD,MAAM,iBAAiC;EACrC,GAAG;EACH,aAAa;CACf;CAEA,MAAM,iBACJ,QAAQ,YAAY,KACpB,QACE,gBAAgB,QAAQ,YAAY,gBAAgB,QAAQ,YAC9D;CAIF,IAAI,cACF,eAAe,UAAU;EACvB,GAAI,eAAe,WAAW,CAAC;EAC/B,eAAe,UAAU;CAC3B;CAGF,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,qBAA8B;EAClC,IAAI,CAAC,aAAa,OAAO;EACzB,IAAI,CAAC,iBAAiB,OAAO;EAG7B,OAAO,KAAK,IAAI,IAAI,iBAAiB;CACvC;CAEA,MAAM,eAAe,YAA2B;EAC9C,MAAM,YAAY,YAA2B;GAG3C,MAAM,aAAY,MAFDA,yCAAY,CAAC,GAAG,cACH,CAAC,CAAC,qBAAqB,EAC3B,EAAE;GAE5B,cAAc,WAAW;GACzB,kBAAkB,mBAAmB,SAAS;EAChD;EAGA,mBAAmB,UAAU,CAAC,CAAC,cAAc;GAC3C,iBAAiB;EACnB,CAAC;EAED,MAAM;CACR;CAEA,MAAM,wBAA8B;EAClC,IAAI,CAAC,aAAa;EAClB,eAAe,UAAU;GACvB,GAAI,eAAe,WAAW,CAAC;GAC/B,eAAe,UAAU;EAC3B;CACF;CAEA,MAAM,aAAa,YAA2B;EAC5C,IAAI,cAAc;EAClB,IAAI,aAAa,GACf,MAAM,aAAa;EAErB,gBAAgB;CAClB;CAEA,MAAM,cAAoB;EACxB,cAAc;EACd,kBAAkB;CACpB;CAEA,MAAM,YACJ,QACA,WAAW,CAAC,mBACuB;EACnC,IAAI,UAAU,OAAO;EAErB,OAAO,OAAO,GAAG,SAAqC;GACpD,MAAM,WAAW;GAEjB,IAAI;IACF,OAAO,MAAM,OAAO,GAAG,IAAI;GAC7B,SAAS,OAAO;IAId,IAAI,cAAc,MAAM;IAExB,MAAM,aAAa;IACnB,gBAAgB;IAChB,OAAO,MAAM,OAAO,GAAG,IAAI;GAC7B;EACF;CACF;CAEA,MAAM,eACJ,SACA,cAAkC,CAAC,MACvB;EACZ,MAAM,UAAU,QAAQ,gBAAgB,cAAc;EACtD,MAAM,WAAW,YAAY,YAAY,CAAC;EAE1C,OAAO,IAAI,MAAM,SAAS,EACxB,IAAI,QAAQ,UAAU,UAAU;GAC9B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAEpD,IAAI,OAAO,UAAU,YAAY,OAAO;GAExC,OAAO,SACJ,MAA0C,KAAK,MAAM,GACtD,QACF;EACF,EACF,CAAC;CACH;CAEA,OAAO;EACL;EACA,gBAAgB;EAChB;EACA;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"createAuthManager.cjs","names":["getOAuthAPI"],"sources":["../../../src/cms/createAuthManager.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { defu } from 'defu';\nimport type { FetcherOptions } from '../fetcher';\nimport { getOAuthAPI } from '../getIntlayerAPI/oAuth';\n\n/**\n * Shape of the various OAuth2 token payloads the backend may return. Only the\n * fields used to derive the expiration timestamp are described here.\n */\ntype OAuthTokenLike = {\n accessToken?: string;\n accessTokenExpiresAt?: string | Date;\n expires_in?: number;\n expiresIn?: number;\n expiresAt?: string | Date;\n};\n\n/**\n * Any asynchronous API method exposed by a domain section\n * (e.g. `getDictionaries`, `pushDictionaries`).\n */\ntype AsyncMethod<Arguments extends unknown[], Result> = (\n ...args: Arguments\n) => Promise<Result>;\n\n/**\n * A domain section factory: builds a plain object of async methods from shared\n * fetcher options and the Intlayer configuration.\n */\ntype SectionFactory<Section extends Record<string, unknown>> = (\n fetcherOptions: FetcherOptions,\n intlayerConfig: IntlayerConfig\n) => Section;\n\nconst ONE_MINUTE_MS = 60_000;\n\n/**\n * Resolves the expiration timestamp (in ms since epoch) from an OAuth2\n * token-like payload, supporting both absolute dates and relative durations.\n */\nconst getExpiryTimestamp = (\n token: OAuthTokenLike | undefined\n): number | undefined => {\n if (!token) return undefined;\n\n const dateLike = (token.accessTokenExpiresAt ?? token.expiresAt) as\n | string\n | Date\n | undefined;\n\n if (dateLike) {\n const timestamp =\n typeof dateLike === 'string'\n ? Date.parse(dateLike)\n : dateLike.getTime?.();\n if (typeof timestamp === 'number' && Number.isFinite(timestamp)) {\n return timestamp;\n }\n }\n\n const seconds = token.expires_in ?? token.expiresIn;\n if (typeof seconds === 'number' && Number.isFinite(seconds)) {\n return Date.now() + seconds * 1000;\n }\n\n return undefined;\n};\n\n/**\n * Options accepted when creating an {@link AuthManager}.\n */\nexport type AuthManagerOptions = {\n /**\n * Base fetcher options merged into every request (e.g. custom headers).\n */\n baseFetcherOptions?: FetcherOptions;\n /**\n * A pre-issued CLI session token (prefixed with `clisession_`). When provided,\n * it is used directly as the Bearer token and the OAuth2 `client_credentials`\n * exchange is skipped entirely.\n */\n sessionToken?: string;\n};\n\n/**\n * Options accepted when binding a domain section to an {@link AuthManager}.\n */\nexport type BindSectionOptions = {\n /**\n * Forces auth injection on (`false`) or off (`true`). Defaults to enabled\n * whenever credentials are available.\n */\n skipAuth?: boolean;\n};\n\n/**\n * Manages CMS authentication for a set of API calls.\n *\n * The manager owns a single mutable {@link FetcherOptions} object\n * (`fetcherOptions`). Domain factories bound through it share the same\n * reference, so refreshing the token in place transparently authenticates every\n * call — without rebuilding the API clients.\n */\nexport type AuthManager = {\n /**\n * Mutable fetcher options carrying the `Authorization` header. Bound sections\n * share this reference so the injected token is reused everywhere.\n */\n fetcherOptions: FetcherOptions;\n /**\n * The resolved Intlayer configuration (merged with the build-time defaults).\n */\n intlayerConfig: IntlayerConfig;\n /**\n * `true` when credentials are available — either a session token or a\n * `clientId`/`clientSecret` pair in the configuration.\n */\n hasCredentials: boolean;\n /**\n * Ensures a valid access token is available and applies it to\n * `fetcherOptions`. Called automatically by {@link withAuth}.\n */\n ensureAuth: () => Promise<void>;\n /**\n * Forces a token refresh on the next call by clearing the cached token.\n */\n reset: () => void;\n /**\n * Wraps a single API method so it injects (and, on failure, refreshes) the\n * access token on every invocation while preserving the method's signature.\n */\n withAuth: <Arguments extends unknown[], Result>(\n method: AsyncMethod<Arguments, Result>,\n skipAuth?: boolean\n ) => AsyncMethod<Arguments, Result>;\n /**\n * Instantiates a domain factory with the managed fetcher options and config,\n * returning a section whose every method authenticates automatically.\n *\n * @example\n * ```ts\n * const dictionary = authManager.bindSection(getDictionaryAPI);\n * await dictionary.pushDictionaries(dictionaries);\n * ```\n */\n bindSection: <Section extends Record<string, unknown>>(\n factory: SectionFactory<Section>,\n options?: BindSectionOptions\n ) => Section;\n};\n\n/**\n * Creates an instance-scoped {@link AuthManager} handling the OAuth2\n * `client_credentials` flow (or a pre-issued CLI session token).\n *\n * Unlike a global token cache, each manager keeps its own token state, so\n * independent SDK instances never interfere with one another.\n *\n * @param intlayerConfig - Intlayer configuration carrying the `editor`\n * credentials. Defaults to the build-time configuration.\n * @param options - Optional session token and base fetcher options.\n */\nexport const createAuthManager = (\n intlayerConfig: Pick<IntlayerConfig, 'editor'> = { editor },\n options: AuthManagerOptions = {}\n): AuthManager => {\n const { baseFetcherOptions = {}, sessionToken } = options;\n\n const resolvedConfig = defu(intlayerConfig ?? {}, {\n editor,\n }) as IntlayerConfig;\n\n // `credentials: 'omit'` prevents the browser from attaching session cookies;\n // authentication is handled exclusively through the injected Bearer token.\n // This is required because the backend only allows credentialed requests for\n // whitelisted first-party origins.\n const fetcherOptions: FetcherOptions = {\n ...baseFetcherOptions,\n credentials: 'omit',\n };\n\n const hasCredentials =\n Boolean(sessionToken) ||\n Boolean(\n resolvedConfig?.editor?.clientId && resolvedConfig?.editor?.clientSecret\n );\n\n // A session token is used as-is and never expires within the SDK's concern,\n // so inject it once up-front and skip the OAuth2 exchange.\n if (sessionToken) {\n fetcherOptions.headers = {\n ...(fetcherOptions.headers ?? {}),\n Authorization: `Bearer ${sessionToken}`,\n } as HeadersInit;\n }\n\n let accessToken: string | undefined;\n let expiryTimestamp: number | undefined;\n let pendingRefresh: Promise<void> | undefined;\n\n const needsRefresh = (): boolean => {\n if (!accessToken) return true;\n if (!expiryTimestamp) return false; // Unknown expiry: assume usable until failure.\n\n // Refresh one minute before the actual expiry to avoid edge-of-expiry races.\n return Date.now() + ONE_MINUTE_MS >= expiryTimestamp;\n };\n\n const refreshToken = async (): Promise<void> => {\n const doRefresh = async (): Promise<void> => {\n const oAuthAPI = getOAuthAPI({}, resolvedConfig);\n const response = await oAuthAPI.getOAuth2AccessToken();\n const tokenData = response?.data as OAuthTokenLike | undefined;\n\n accessToken = tokenData?.accessToken;\n expiryTimestamp = getExpiryTimestamp(tokenData);\n };\n\n // De-duplicate concurrent refreshes so a burst of calls triggers one fetch.\n pendingRefresh ??= doRefresh().finally(() => {\n pendingRefresh = undefined;\n });\n\n await pendingRefresh;\n };\n\n const applyAuthHeader = (): void => {\n if (!accessToken) return;\n fetcherOptions.headers = {\n ...(fetcherOptions.headers ?? {}),\n Authorization: `Bearer ${accessToken}`,\n } as HeadersInit;\n };\n\n const ensureAuth = async (): Promise<void> => {\n if (sessionToken) return; // Already injected; nothing to refresh.\n if (needsRefresh()) {\n await refreshToken();\n }\n applyAuthHeader();\n };\n\n const reset = (): void => {\n accessToken = undefined;\n expiryTimestamp = undefined;\n };\n\n const withAuth = <Arguments extends unknown[], Result>(\n method: AsyncMethod<Arguments, Result>,\n skipAuth = !hasCredentials\n ): AsyncMethod<Arguments, Result> => {\n if (skipAuth) return method;\n\n return async (...args: Arguments): Promise<Result> => {\n await ensureAuth();\n\n try {\n return await method(...args);\n } catch (error) {\n // The token may have been revoked or expired early: refresh once and\n // retry before surfacing the error. A session token cannot be\n // refreshed, so re-throw immediately in that case.\n if (sessionToken) throw error;\n\n await refreshToken();\n applyAuthHeader();\n return await method(...args);\n }\n };\n };\n\n const bindSection = <Section extends Record<string, unknown>>(\n factory: SectionFactory<Section>,\n bindOptions: BindSectionOptions = {}\n ): Section => {\n const section = factory(fetcherOptions, resolvedConfig);\n const skipAuth = bindOptions.skipAuth ?? !hasCredentials;\n\n return new Proxy(section, {\n get(target, property, receiver) {\n const value = Reflect.get(target, property, receiver);\n\n if (typeof value !== 'function') return value;\n\n return withAuth(\n (value as AsyncMethod<unknown[], unknown>).bind(target),\n skipAuth\n );\n },\n });\n };\n\n return {\n fetcherOptions,\n intlayerConfig: resolvedConfig,\n hasCredentials,\n ensureAuth,\n reset,\n withAuth,\n bindSection,\n };\n};\n"],"mappings":";;;;;;AAmCA,MAAM,gBAAgB;;;;;AAMtB,MAAM,sBACJ,UACuB;CACvB,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,WAAY,MAAM,wBAAwB,MAAM;CAKtD,IAAI,UAAU;EACZ,MAAM,YACJ,OAAO,aAAa,WAChB,KAAK,MAAM,QAAQ,IACnB,SAAS,UAAU;EACzB,IAAI,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,GAC5D,OAAO;CAEX;CAEA,MAAM,UAAU,MAAM,cAAc,MAAM;CAC1C,IAAI,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,GACxD,OAAO,KAAK,IAAI,IAAI,UAAU;AAIlC;;;;;;;;;;;;AAgGA,MAAa,qBACX,iBAAiD,EAAE,sCAAO,GAC1D,UAA8B,CAAC,MACf;CAChB,MAAM,EAAE,qBAAqB,CAAC,GAAG,iBAAiB;CAElD,MAAM,qBAAiB,WAAK,kBAAkB,CAAC,GAAG,EAChD,sCACF,CAAC;CAMD,MAAM,iBAAiC;EACrC,GAAG;EACH,aAAa;CACf;CAEA,MAAM,iBACJ,QAAQ,YAAY,KACpB,QACE,gBAAgB,QAAQ,YAAY,gBAAgB,QAAQ,YAC9D;CAIF,IAAI,cACF,eAAe,UAAU;EACvB,GAAI,eAAe,WAAW,CAAC;EAC/B,eAAe,UAAU;CAC3B;CAGF,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,qBAA8B;EAClC,IAAI,CAAC,aAAa,OAAO;EACzB,IAAI,CAAC,iBAAiB,OAAO;EAG7B,OAAO,KAAK,IAAI,IAAI,iBAAiB;CACvC;CAEA,MAAM,eAAe,YAA2B;EAC9C,MAAM,YAAY,YAA2B;GAG3C,MAAM,aAAY,MAFDA,yCAAY,CAAC,GAAG,cACH,CAAC,CAAC,qBAAqB,EAC3B,EAAE;GAE5B,cAAc,WAAW;GACzB,kBAAkB,mBAAmB,SAAS;EAChD;EAGA,mBAAmB,UAAU,CAAC,CAAC,cAAc;GAC3C,iBAAiB;EACnB,CAAC;EAED,MAAM;CACR;CAEA,MAAM,wBAA8B;EAClC,IAAI,CAAC,aAAa;EAClB,eAAe,UAAU;GACvB,GAAI,eAAe,WAAW,CAAC;GAC/B,eAAe,UAAU;EAC3B;CACF;CAEA,MAAM,aAAa,YAA2B;EAC5C,IAAI,cAAc;EAClB,IAAI,aAAa,GACf,MAAM,aAAa;EAErB,gBAAgB;CAClB;CAEA,MAAM,cAAoB;EACxB,cAAc;EACd,kBAAkB;CACpB;CAEA,MAAM,YACJ,QACA,WAAW,CAAC,mBACuB;EACnC,IAAI,UAAU,OAAO;EAErB,OAAO,OAAO,GAAG,SAAqC;GACpD,MAAM,WAAW;GAEjB,IAAI;IACF,OAAO,MAAM,OAAO,GAAG,IAAI;GAC7B,SAAS,OAAO;IAId,IAAI,cAAc,MAAM;IAExB,MAAM,aAAa;IACnB,gBAAgB;IAChB,OAAO,MAAM,OAAO,GAAG,IAAI;GAC7B;EACF;CACF;CAEA,MAAM,eACJ,SACA,cAAkC,CAAC,MACvB;EACZ,MAAM,UAAU,QAAQ,gBAAgB,cAAc;EACtD,MAAM,WAAW,YAAY,YAAY,CAAC;EAE1C,OAAO,IAAI,MAAM,SAAS,EACxB,IAAI,QAAQ,UAAU,UAAU;GAC9B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAEpD,IAAI,OAAO,UAAU,YAAY,OAAO;GAExC,OAAO,SACJ,MAA0C,KAAK,MAAM,GACtD,QACF;EACF,EACF,CAAC;CACH;CAEA,OAAO;EACL;EACA,gBAAgB;EAChB;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -1,7 +1,28 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
-
3
2
  //#region src/fetcher.ts
4
3
  /**
4
+ * Error thrown when the backend answers with a non-ok response.
5
+ *
6
+ * Carries the HTTP status and the backend error code alongside the message, so
7
+ * callers can tell a transient failure (5xx, network) from a deterministic one
8
+ * (4xx) instead of blindly retrying.
9
+ */
10
+ var FetcherError = class extends Error {
11
+ /** HTTP status code of the response. */
12
+ status;
13
+ /** Error code returned by the backend, when available (ex: `DICTIONARY_NOT_FOUND`). */
14
+ code;
15
+ /** Raw error payload returned by the backend. */
16
+ data;
17
+ constructor(message, details) {
18
+ super(message);
19
+ this.name = "FetcherError";
20
+ this.status = details.status;
21
+ this.code = details.code;
22
+ this.data = details.data;
23
+ }
24
+ };
25
+ /**
5
26
  * Default options for the fetcher function.
6
27
  * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',
7
28
  * and includes credentials in the request.
@@ -112,13 +133,18 @@ const fetcher = async (url, ...options) => {
112
133
  const urlResult = `${url}${paramsString}`;
113
134
  const response = await fetch(urlResult, formattedOptions);
114
135
  if (!response.ok) {
115
- const result = await response.json();
116
- throw new Error(JSON.stringify(result.error) ?? "An error occurred");
136
+ const result = await response.json().catch(() => void 0);
137
+ throw new FetcherError(JSON.stringify(result?.error) ?? "An error occurred", {
138
+ status: response.status,
139
+ code: result?.error?.code,
140
+ data: result?.error
141
+ });
117
142
  }
118
143
  return await response.json();
119
144
  };
120
145
 
121
146
  //#endregion
147
+ exports.FetcherError = FetcherError;
122
148
  exports.fetcher = fetcher;
123
149
  exports.fetcherOptions = fetcherOptions;
124
150
  //# sourceMappingURL=fetcher.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.cjs","names":[],"sources":["../../src/fetcher.ts"],"sourcesContent":["/**\n * Type definition for options used in the fetcher function.\n * Extends the standard RequestInit interface (excluding 'body'),\n * and adds 'body' and 'params' properties for convenience.\n */\nexport type FetcherOptions = Omit<RequestInit, 'body'> & {\n /**\n * Body of the request. Should be a key-value pair object.\n */\n body?: Record<string, unknown>;\n /**\n * Query parameters to be appended to the URL.\n */\n params?:\n | Record<string, string | string[] | undefined>\n | string[]\n | URLSearchParams;\n};\n\n/**\n * Default options for the fetcher function.\n * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',\n * and includes credentials in the request.\n */\nexport const fetcherOptions: FetcherOptions = {\n method: 'GET', // Default HTTP method\n headers: {\n 'Content-Type': 'application/json', // Default content type\n },\n credentials: 'include',\n};\n\n/**\n * Utility function to remove properties with undefined values from an object.\n * This helps prevent sending undefined values in the request options.\n *\n * @param obj - The object to clean.\n * @returns The cleaned object without undefined values.\n */\nconst removeUndefined = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (obj[key as keyof typeof obj] === undefined) {\n delete obj[key as keyof typeof obj];\n }\n });\n return obj;\n};\n\n/**\n * Deeply merges an array of objects into a single object.\n * Later objects in the array overwrite properties of earlier ones.\n *\n * @template T - The type of objects being merged.\n * @param objects - An array of objects to merge.\n * @returns The merged object.\n */\nconst deepMerge = <T extends object>(objects: (T | undefined)[]): T =>\n objects.reduce((acc, obj) => {\n const acc1: T = (acc ?? {}) as T;\n const obj1: T = removeUndefined(obj ?? {}) as T;\n\n if (typeof acc1 === 'object' && typeof obj1 === 'object') {\n // Merge the two objects\n return { ...acc1, ...obj1 };\n }\n\n // If one of them is not an object, return the defined one\n return obj1 ?? acc1;\n }, {} as T)!;\n\n/**\n * Fetcher function to make HTTP requests.\n * It merges default options with user-provided options,\n * handles query parameters and request body,\n * and returns the parsed JSON response.\n *\n * @template T - The expected type of the response data.\n * @param url - The endpoint URL.\n * @param options - Additional options to customize the request.\n * @returns A promise that resolves with the response data of type T.\n *\n * @example\n * ```typescript\n * // Making a GET request with query parameters\n * const data = await fetcher<MyResponseType>('https://api.example.com/data', {\n * params: { search: 'query' },\n * });\n *\n * // Making a POST request with a JSON body\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * });\n *\n * // Merge body, headers, and params\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * headers: { 'Content-Type': 'application/json' },\n * params: { search: 'query' },\n * },\n * {\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1 },\n * });\n * ```\n *\n * Result:\n * ```typescript\n * {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1, search: 'query' },\n * body: { key: 'value' },\n * }\n * ```\n */\nexport const fetcher = async <T>(\n url: string,\n ...options: FetcherOptions[]\n): Promise<T> => {\n const { signal } = new AbortController();\n\n // Initialize query parameters string and request body string\n let paramsString = '';\n let bodyString: string | undefined;\n\n // Extract other options excluding 'body', 'params', and 'headers'\n const otherOptions = options.map(\n ({ body, params, headers, ...otherOptions }) => otherOptions\n );\n\n // Merge default options with user-provided options\n const mergedOptions = deepMerge([fetcherOptions, ...otherOptions]);\n\n // Merge default headers with user-provided headers\n const mergedHeaders = deepMerge([\n fetcherOptions.headers,\n ...options.map((option) => option.headers),\n ]);\n\n // Merge query parameters\n const params = deepMerge(options.map((option) => option.params));\n\n const method = mergedOptions.method;\n\n // If the request method is not 'GET' or 'HEAD', prepare the request body\n if (method !== 'GET' && method !== 'HEAD') {\n // Merge all 'body' options\n const body = deepMerge(options.map((option) => option.body));\n if (\n mergedHeaders?.['Content-Type' as keyof HeadersInit] ===\n 'application/x-www-form-urlencoded'\n ) {\n // If the content type is 'application/x-www-form-urlencoded', encode the body accordingly\n bodyString = new URLSearchParams(\n body as Record<string, string>\n ).toString();\n } else {\n // Otherwise, stringify the body as JSON\n bodyString = JSON.stringify(body);\n }\n }\n\n // If there are query parameters, append them to the URL\n if (Object.entries(params).length > 0) {\n paramsString = `?${new URLSearchParams(\n params as Record<string, string>\n ).toString()}`;\n }\n\n // Prepare the final request options\n const formattedOptions: RequestInit = {\n ...mergedOptions,\n headers: mergedHeaders,\n body: bodyString,\n signal,\n };\n\n // Construct the full URL with query parameters\n const urlResult = `${url}${paramsString}`;\n\n // Make the HTTP request using fetch\n const response = await fetch(urlResult, formattedOptions);\n\n if (!response.ok) {\n const result = await response.json();\n\n // You can customize the error message or include more details\n throw new Error(JSON.stringify(result.error) ?? 'An error occurred');\n }\n return await response.json();\n};\n"],"mappings":";;;;;;;;AAwBA,MAAa,iBAAiC;CAC5C,QAAQ;CACR,SAAS,EACP,gBAAgB,mBAClB;CACA,aAAa;AACf;;;;;;;;AASA,MAAM,mBAAmB,QAAgB;CACvC,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,QAAQ;EAChC,IAAI,IAAI,SAA6B,QACnC,OAAO,IAAI;CAEf,CAAC;CACD,OAAO;AACT;;;;;;;;;AAUA,MAAM,aAA+B,YACnC,QAAQ,QAAQ,KAAK,QAAQ;CAC3B,MAAM,OAAW,OAAO,CAAC;CACzB,MAAM,OAAU,gBAAgB,OAAO,CAAC,CAAC;CAEzC,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAE9C,OAAO;EAAE,GAAG;EAAM,GAAG;CAAK;CAI5B,OAAO,QAAQ;AACjB,GAAG,CAAC,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDZ,MAAa,UAAU,OACrB,KACA,GAAG,YACY;CACf,MAAM,EAAE,WAAW,IAAI,gBAAgB;CAGvC,IAAI,eAAe;CACnB,IAAI;CAGJ,MAAM,eAAe,QAAQ,KAC1B,EAAE,MAAM,QAAQ,SAAS,GAAG,mBAAmB,YAClD;CAGA,MAAM,gBAAgB,UAAU,CAAC,gBAAgB,GAAG,YAAY,CAAC;CAGjE,MAAM,gBAAgB,UAAU,CAC9B,eAAe,SACf,GAAG,QAAQ,KAAK,WAAW,OAAO,OAAO,CAC3C,CAAC;CAGD,MAAM,SAAS,UAAU,QAAQ,KAAK,WAAW,OAAO,MAAM,CAAC;CAE/D,MAAM,SAAS,cAAc;CAG7B,IAAI,WAAW,SAAS,WAAW,QAAQ;EAEzC,MAAM,OAAO,UAAU,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC;EAC3D,IACE,gBAAgB,oBAChB,qCAGA,aAAa,IAAI,gBACf,IACF,CAAC,CAAC,SAAS;OAGX,aAAa,KAAK,UAAU,IAAI;CAEpC;CAGA,IAAI,OAAO,QAAQ,MAAM,CAAC,CAAC,SAAS,GAClC,eAAe,IAAI,IAAI,gBACrB,MACF,CAAC,CAAC,SAAS;CAIb,MAAM,mBAAgC;EACpC,GAAG;EACH,SAAS;EACT,MAAM;EACN;CACF;CAGA,MAAM,YAAY,GAAG,MAAM;CAG3B,MAAM,WAAW,MAAM,MAAM,WAAW,gBAAgB;CAExD,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,SAAS,MAAM,SAAS,KAAK;EAGnC,MAAM,IAAI,MAAM,KAAK,UAAU,OAAO,KAAK,KAAK,mBAAmB;CACrE;CACA,OAAO,MAAM,SAAS,KAAK;AAC7B"}
1
+ {"version":3,"file":"fetcher.cjs","names":[],"sources":["../../src/fetcher.ts"],"sourcesContent":["/**\n * Error thrown when the backend answers with a non-ok response.\n *\n * Carries the HTTP status and the backend error code alongside the message, so\n * callers can tell a transient failure (5xx, network) from a deterministic one\n * (4xx) instead of blindly retrying.\n */\nexport class FetcherError extends Error {\n /** HTTP status code of the response. */\n public readonly status: number;\n /** Error code returned by the backend, when available (ex: `DICTIONARY_NOT_FOUND`). */\n public readonly code?: string;\n /** Raw error payload returned by the backend. */\n public readonly data?: unknown;\n\n constructor(\n message: string,\n details: { status: number; code?: string; data?: unknown }\n ) {\n super(message);\n\n this.name = 'FetcherError';\n this.status = details.status;\n this.code = details.code;\n this.data = details.data;\n }\n}\n\n/**\n * Type definition for options used in the fetcher function.\n * Extends the standard RequestInit interface (excluding 'body'),\n * and adds 'body' and 'params' properties for convenience.\n */\nexport type FetcherOptions = Omit<RequestInit, 'body'> & {\n /**\n * Body of the request. Should be a key-value pair object.\n */\n body?: Record<string, unknown>;\n /**\n * Query parameters to be appended to the URL.\n */\n params?:\n | Record<string, string | string[] | undefined>\n | string[]\n | URLSearchParams;\n};\n\n/**\n * Default options for the fetcher function.\n * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',\n * and includes credentials in the request.\n */\nexport const fetcherOptions: FetcherOptions = {\n method: 'GET', // Default HTTP method\n headers: {\n 'Content-Type': 'application/json', // Default content type\n },\n credentials: 'include',\n};\n\n/**\n * Utility function to remove properties with undefined values from an object.\n * This helps prevent sending undefined values in the request options.\n *\n * @param obj - The object to clean.\n * @returns The cleaned object without undefined values.\n */\nconst removeUndefined = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (obj[key as keyof typeof obj] === undefined) {\n delete obj[key as keyof typeof obj];\n }\n });\n return obj;\n};\n\n/**\n * Deeply merges an array of objects into a single object.\n * Later objects in the array overwrite properties of earlier ones.\n *\n * @template T - The type of objects being merged.\n * @param objects - An array of objects to merge.\n * @returns The merged object.\n */\nconst deepMerge = <T extends object>(objects: (T | undefined)[]): T =>\n objects.reduce((acc, obj) => {\n const acc1: T = (acc ?? {}) as T;\n const obj1: T = removeUndefined(obj ?? {}) as T;\n\n if (typeof acc1 === 'object' && typeof obj1 === 'object') {\n // Merge the two objects\n return { ...acc1, ...obj1 };\n }\n\n // If one of them is not an object, return the defined one\n return obj1 ?? acc1;\n }, {} as T)!;\n\n/**\n * Fetcher function to make HTTP requests.\n * It merges default options with user-provided options,\n * handles query parameters and request body,\n * and returns the parsed JSON response.\n *\n * @template T - The expected type of the response data.\n * @param url - The endpoint URL.\n * @param options - Additional options to customize the request.\n * @returns A promise that resolves with the response data of type T.\n *\n * @example\n * ```typescript\n * // Making a GET request with query parameters\n * const data = await fetcher<MyResponseType>('https://api.example.com/data', {\n * params: { search: 'query' },\n * });\n *\n * // Making a POST request with a JSON body\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * });\n *\n * // Merge body, headers, and params\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * headers: { 'Content-Type': 'application/json' },\n * params: { search: 'query' },\n * },\n * {\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1 },\n * });\n * ```\n *\n * Result:\n * ```typescript\n * {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1, search: 'query' },\n * body: { key: 'value' },\n * }\n * ```\n */\nexport const fetcher = async <T>(\n url: string,\n ...options: FetcherOptions[]\n): Promise<T> => {\n const { signal } = new AbortController();\n\n // Initialize query parameters string and request body string\n let paramsString = '';\n let bodyString: string | undefined;\n\n // Extract other options excluding 'body', 'params', and 'headers'\n const otherOptions = options.map(\n ({ body, params, headers, ...otherOptions }) => otherOptions\n );\n\n // Merge default options with user-provided options\n const mergedOptions = deepMerge([fetcherOptions, ...otherOptions]);\n\n // Merge default headers with user-provided headers\n const mergedHeaders = deepMerge([\n fetcherOptions.headers,\n ...options.map((option) => option.headers),\n ]);\n\n // Merge query parameters\n const params = deepMerge(options.map((option) => option.params));\n\n const method = mergedOptions.method;\n\n // If the request method is not 'GET' or 'HEAD', prepare the request body\n if (method !== 'GET' && method !== 'HEAD') {\n // Merge all 'body' options\n const body = deepMerge(options.map((option) => option.body));\n if (\n mergedHeaders?.['Content-Type' as keyof HeadersInit] ===\n 'application/x-www-form-urlencoded'\n ) {\n // If the content type is 'application/x-www-form-urlencoded', encode the body accordingly\n bodyString = new URLSearchParams(\n body as Record<string, string>\n ).toString();\n } else {\n // Otherwise, stringify the body as JSON\n bodyString = JSON.stringify(body);\n }\n }\n\n // If there are query parameters, append them to the URL\n if (Object.entries(params).length > 0) {\n paramsString = `?${new URLSearchParams(\n params as Record<string, string>\n ).toString()}`;\n }\n\n // Prepare the final request options\n const formattedOptions: RequestInit = {\n ...mergedOptions,\n headers: mergedHeaders,\n body: bodyString,\n signal,\n };\n\n // Construct the full URL with query parameters\n const urlResult = `${url}${paramsString}`;\n\n // Make the HTTP request using fetch\n const response = await fetch(urlResult, formattedOptions);\n\n if (!response.ok) {\n const result = await response.json().catch(() => undefined);\n\n // You can customize the error message or include more details\n throw new FetcherError(\n JSON.stringify(result?.error) ?? 'An error occurred',\n {\n status: response.status,\n code: result?.error?.code,\n data: result?.error,\n }\n );\n }\n return await response.json();\n};\n"],"mappings":";;;;;;;;;AAOA,IAAa,eAAb,cAAkC,MAAM;;CAEtC,AAAgB;;CAEhB,AAAgB;;CAEhB,AAAgB;CAEhB,YACE,SACA,SACA;EACA,MAAM,OAAO;EAEb,KAAK,OAAO;EACZ,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,QAAQ;EACpB,KAAK,OAAO,QAAQ;CACtB;AACF;;;;;;AA0BA,MAAa,iBAAiC;CAC5C,QAAQ;CACR,SAAS,EACP,gBAAgB,mBAClB;CACA,aAAa;AACf;;;;;;;;AASA,MAAM,mBAAmB,QAAgB;CACvC,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,QAAQ;EAChC,IAAI,IAAI,SAA6B,QACnC,OAAO,IAAI;CAEf,CAAC;CACD,OAAO;AACT;;;;;;;;;AAUA,MAAM,aAA+B,YACnC,QAAQ,QAAQ,KAAK,QAAQ;CAC3B,MAAM,OAAW,OAAO,CAAC;CACzB,MAAM,OAAU,gBAAgB,OAAO,CAAC,CAAC;CAEzC,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAE9C,OAAO;EAAE,GAAG;EAAM,GAAG;CAAK;CAI5B,OAAO,QAAQ;AACjB,GAAG,CAAC,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDZ,MAAa,UAAU,OACrB,KACA,GAAG,YACY;CACf,MAAM,EAAE,WAAW,IAAI,gBAAgB;CAGvC,IAAI,eAAe;CACnB,IAAI;CAGJ,MAAM,eAAe,QAAQ,KAC1B,EAAE,MAAM,QAAQ,SAAS,GAAG,mBAAmB,YAClD;CAGA,MAAM,gBAAgB,UAAU,CAAC,gBAAgB,GAAG,YAAY,CAAC;CAGjE,MAAM,gBAAgB,UAAU,CAC9B,eAAe,SACf,GAAG,QAAQ,KAAK,WAAW,OAAO,OAAO,CAC3C,CAAC;CAGD,MAAM,SAAS,UAAU,QAAQ,KAAK,WAAW,OAAO,MAAM,CAAC;CAE/D,MAAM,SAAS,cAAc;CAG7B,IAAI,WAAW,SAAS,WAAW,QAAQ;EAEzC,MAAM,OAAO,UAAU,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC;EAC3D,IACE,gBAAgB,oBAChB,qCAGA,aAAa,IAAI,gBACf,IACF,CAAC,CAAC,SAAS;OAGX,aAAa,KAAK,UAAU,IAAI;CAEpC;CAGA,IAAI,OAAO,QAAQ,MAAM,CAAC,CAAC,SAAS,GAClC,eAAe,IAAI,IAAI,gBACrB,MACF,CAAC,CAAC,SAAS;CAIb,MAAM,mBAAgC;EACpC,GAAG;EACH,SAAS;EACT,MAAM;EACN;CACF;CAGA,MAAM,YAAY,GAAG,MAAM;CAG3B,MAAM,WAAW,MAAM,MAAM,WAAW,gBAAgB;CAExD,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,SAAS,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,MAAS;EAG1D,MAAM,IAAI,aACR,KAAK,UAAU,QAAQ,KAAK,KAAK,qBACjC;GACE,QAAQ,SAAS;GACjB,MAAM,QAAQ,OAAO;GACrB,MAAM,QAAQ;EAChB,CACF;CACF;CACA,OAAO,MAAM,SAAS,KAAK;AAC7B"}
@@ -29,6 +29,21 @@ const getDictionaryAPI = (authAPIOptions = {}, intlayerConfig) => {
29
29
  */
30
30
  const getDictionary = async (dictionaryKey, version, otherOptions = {}) => await require_fetcher.fetcher(`${PROJECT_API_ROUTE}/${dictionaryKey}`, authAPIOptions, otherOptions, { params: version ? { version: version.toString() } : void 0 });
31
31
  /**
32
+ * Retrieves several dictionaries at once from their keys, in a single
33
+ * request. Keys matching no dictionary are absent from the result, so the
34
+ * caller should reconcile the response against the requested keys.
35
+ *
36
+ * @param dictionaryKeys - Dictionary keys to retrieve.
37
+ * @param version - Dictionary version of content.
38
+ */
39
+ const getDictionariesByKeys = async (dictionaryKeys, version, otherOptions = {}) => await require_fetcher.fetcher(`${PROJECT_API_ROUTE}/by-keys`, authAPIOptions, otherOptions, {
40
+ cache: "no-store",
41
+ params: {
42
+ keys: dictionaryKeys.join(","),
43
+ version: version?.toString()
44
+ }
45
+ });
46
+ /**
32
47
  * Adds a new dictionary to the database.
33
48
  * @param dictionary - Dictionary data.
34
49
  */
@@ -58,6 +73,7 @@ const getDictionaryAPI = (authAPIOptions = {}, intlayerConfig) => {
58
73
  getDictionariesKeys,
59
74
  getDictionariesUpdateTimestamp,
60
75
  getDictionary,
76
+ getDictionariesByKeys,
61
77
  pushDictionaries,
62
78
  addDictionary,
63
79
  updateDictionary,
@@ -1 +1 @@
1
- {"version":3,"file":"dictionary.cjs","names":["editor","fetcher","createEndpoint"],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"sourcesContent":["import type {\n AddDictionaryBody,\n AddDictionaryResult,\n DeleteDictionaryParam,\n DeleteDictionaryResult,\n GetDictionariesKeysResult,\n GetDictionariesParams,\n GetDictionariesResult,\n GetDictionariesUpdateTimestampResult,\n GetDictionaryParams,\n GetDictionaryQuery,\n GetDictionaryResult,\n PushDictionariesBody,\n PushDictionariesResult,\n UpdateDictionaryBody,\n UpdateDictionaryResult,\n} from '@intlayer/backend';\nimport { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { createEndpoint } from '../cms/createIntlayerCMS';\nimport { type FetcherOptions, fetcher } from '../fetcher';\n\nexport const getDictionaryAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: IntlayerConfig\n) => {\n const backendURL = intlayerConfig?.editor?.backendURL ?? editor.backendURL;\n\n const PROJECT_API_ROUTE = `${backendURL}/api/dictionary`;\n\n /**\n * Retrieves a list of dictionaries based on filters and pagination.\n * @param filters - Filters and pagination options.\n */\n const getDictionaries = async (\n filters?: GetDictionariesParams,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesResult>(\n PROJECT_API_ROUTE,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n // @ts-ignore Number of parameter will be stringified by the fetcher\n params: filters,\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesKeys = async (otherOptions: FetcherOptions = {}) =>\n await fetcher<GetDictionariesKeysResult>(\n `${PROJECT_API_ROUTE}/keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesUpdateTimestamp = async (\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesUpdateTimestampResult>(\n `${PROJECT_API_ROUTE}/update`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a dictionary by its key and version.\n * @param dictionaryKey - Dictionary key.\n * @param version - Dictionary version of content.\n */\n const getDictionary = async (\n dictionaryKey: GetDictionaryParams['dictionaryKey'],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionaryKey}`,\n authAPIOptions,\n otherOptions,\n {\n params: version ? { version: version.toString() } : undefined,\n }\n );\n\n /**\n * Adds a new dictionary to the database.\n * @param dictionary - Dictionary data.\n */\n const addDictionary = async (\n body: AddDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<AddDictionaryResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'POST',\n body,\n }\n );\n\n const pushDictionaries = async (\n dictionaries: PushDictionariesBody['dictionaries'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<PushDictionariesResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PATCH',\n body: { dictionaries },\n }\n );\n\n /**\n * Updates an existing dictionary in the database.\n * @param dictionary - Updated dictionary data.\n */\n const updateDictionary = async (\n dictionary: UpdateDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<UpdateDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionary.id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PUT',\n body: dictionary,\n }\n );\n\n /**\n * Deletes a dictionary from the database by its ID.\n * @param id - Dictionary ID.\n */\n const deleteDictionary = async (\n id: DeleteDictionaryParam['dictionaryId'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<DeleteDictionaryResult>(\n `${PROJECT_API_ROUTE}/${id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'DELETE',\n }\n );\n\n return {\n getDictionaries,\n getDictionariesKeys,\n getDictionariesUpdateTimestamp,\n getDictionary,\n pushDictionaries,\n addDictionary,\n updateDictionary,\n deleteDictionary,\n };\n};\n\n/**\n * Authenticated `dictionary` endpoint bound to an Intlayer CMS authenticator.\n *\n * Pass an authenticator created with `createIntlayerCMS`, or omit it to use\n * the build-time configuration (`@intlayer/config/built`).\n */\nexport const dictionaryEndpoint = createEndpoint(getDictionaryAPI);\n"],"mappings":";;;;;;AAsBA,MAAa,oBACX,iBAAiC,CAAC,GAClC,mBACG;CAGH,MAAM,oBAAoB,GAFP,gBAAgB,QAAQ,cAAcA,8BAAO,WAExB;;;;;CAMxC,MAAM,kBAAkB,OACtB,SACA,eAA+B,CAAC,MAEhC,MAAMC,wBACJ,mBACA,gBACA,cACA;EACE,OAAO;EAEP,QAAQ;CACV,CACF;;;;CAKF,MAAM,sBAAsB,OAAO,eAA+B,CAAC,MACjE,MAAMA,wBACJ,GAAG,kBAAkB,QACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;CAKF,MAAM,iCAAiC,OACrC,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,UACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;;;CAOF,MAAM,gBAAgB,OACpB,eACA,SACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,iBACxB,gBACA,cACA,EACE,QAAQ,UAAU,EAAE,SAAS,QAAQ,SAAS,EAAE,IAAI,OACtD,CACF;;;;;CAMF,MAAM,gBAAgB,OACpB,MACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR;CACF,CACF;CAEF,MAAM,mBAAmB,OACvB,cACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR,MAAM,EAAE,aAAa;CACvB,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,YACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,WAAW,MACnC,gBACA,cACA;EACE,QAAQ;EACR,MAAM;CACR,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,IACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,MACxB,gBACA,cACA,EACE,QAAQ,SACV,CACF;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;AAQA,MAAa,qBAAqBC,6CAAe,gBAAgB"}
1
+ {"version":3,"file":"dictionary.cjs","names":["editor","fetcher","createEndpoint"],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"sourcesContent":["import type {\n AddDictionaryBody,\n AddDictionaryResult,\n DeleteDictionaryParam,\n DeleteDictionaryResult,\n GetDictionariesByKeysResult,\n GetDictionariesKeysResult,\n GetDictionariesParams,\n GetDictionariesResult,\n GetDictionariesUpdateTimestampResult,\n GetDictionaryParams,\n GetDictionaryQuery,\n GetDictionaryResult,\n PushDictionariesBody,\n PushDictionariesResult,\n UpdateDictionaryBody,\n UpdateDictionaryResult,\n} from '@intlayer/backend';\nimport { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { createEndpoint } from '../cms/createIntlayerCMS';\nimport { type FetcherOptions, fetcher } from '../fetcher';\n\nexport const getDictionaryAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: IntlayerConfig\n) => {\n const backendURL = intlayerConfig?.editor?.backendURL ?? editor.backendURL;\n\n const PROJECT_API_ROUTE = `${backendURL}/api/dictionary`;\n\n /**\n * Retrieves a list of dictionaries based on filters and pagination.\n * @param filters - Filters and pagination options.\n */\n const getDictionaries = async (\n filters?: GetDictionariesParams,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesResult>(\n PROJECT_API_ROUTE,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n // @ts-ignore Number of parameter will be stringified by the fetcher\n params: filters,\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesKeys = async (otherOptions: FetcherOptions = {}) =>\n await fetcher<GetDictionariesKeysResult>(\n `${PROJECT_API_ROUTE}/keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesUpdateTimestamp = async (\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesUpdateTimestampResult>(\n `${PROJECT_API_ROUTE}/update`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a dictionary by its key and version.\n * @param dictionaryKey - Dictionary key.\n * @param version - Dictionary version of content.\n */\n const getDictionary = async (\n dictionaryKey: GetDictionaryParams['dictionaryKey'],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionaryKey}`,\n authAPIOptions,\n otherOptions,\n {\n params: version ? { version: version.toString() } : undefined,\n }\n );\n\n /**\n * Retrieves several dictionaries at once from their keys, in a single\n * request. Keys matching no dictionary are absent from the result, so the\n * caller should reconcile the response against the requested keys.\n *\n * @param dictionaryKeys - Dictionary keys to retrieve.\n * @param version - Dictionary version of content.\n */\n const getDictionariesByKeys = async (\n dictionaryKeys: string[],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesByKeysResult>(\n `${PROJECT_API_ROUTE}/by-keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n params: {\n keys: dictionaryKeys.join(','),\n version: version?.toString(),\n },\n }\n );\n\n /**\n * Adds a new dictionary to the database.\n * @param dictionary - Dictionary data.\n */\n const addDictionary = async (\n body: AddDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<AddDictionaryResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'POST',\n body,\n }\n );\n\n const pushDictionaries = async (\n dictionaries: PushDictionariesBody['dictionaries'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<PushDictionariesResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PATCH',\n body: { dictionaries },\n }\n );\n\n /**\n * Updates an existing dictionary in the database.\n * @param dictionary - Updated dictionary data.\n */\n const updateDictionary = async (\n dictionary: UpdateDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<UpdateDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionary.id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PUT',\n body: dictionary,\n }\n );\n\n /**\n * Deletes a dictionary from the database by its ID.\n * @param id - Dictionary ID.\n */\n const deleteDictionary = async (\n id: DeleteDictionaryParam['dictionaryId'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<DeleteDictionaryResult>(\n `${PROJECT_API_ROUTE}/${id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'DELETE',\n }\n );\n\n return {\n getDictionaries,\n getDictionariesKeys,\n getDictionariesUpdateTimestamp,\n getDictionary,\n getDictionariesByKeys,\n pushDictionaries,\n addDictionary,\n updateDictionary,\n deleteDictionary,\n };\n};\n\n/**\n * Authenticated `dictionary` endpoint bound to an Intlayer CMS authenticator.\n *\n * Pass an authenticator created with `createIntlayerCMS`, or omit it to use\n * the build-time configuration (`@intlayer/config/built`).\n */\nexport const dictionaryEndpoint = createEndpoint(getDictionaryAPI);\n"],"mappings":";;;;;;AAuBA,MAAa,oBACX,iBAAiC,CAAC,GAClC,mBACG;CAGH,MAAM,oBAAoB,GAFP,gBAAgB,QAAQ,cAAcA,8BAAO,WAExB;;;;;CAMxC,MAAM,kBAAkB,OACtB,SACA,eAA+B,CAAC,MAEhC,MAAMC,wBACJ,mBACA,gBACA,cACA;EACE,OAAO;EAEP,QAAQ;CACV,CACF;;;;CAKF,MAAM,sBAAsB,OAAO,eAA+B,CAAC,MACjE,MAAMA,wBACJ,GAAG,kBAAkB,QACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;CAKF,MAAM,iCAAiC,OACrC,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,UACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;;;CAOF,MAAM,gBAAgB,OACpB,eACA,SACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,iBACxB,gBACA,cACA,EACE,QAAQ,UAAU,EAAE,SAAS,QAAQ,SAAS,EAAE,IAAI,OACtD,CACF;;;;;;;;;CAUF,MAAM,wBAAwB,OAC5B,gBACA,SACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,WACrB,gBACA,cACA;EACE,OAAO;EACP,QAAQ;GACN,MAAM,eAAe,KAAK,GAAG;GAC7B,SAAS,SAAS,SAAS;EAC7B;CACF,CACF;;;;;CAMF,MAAM,gBAAgB,OACpB,MACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR;CACF,CACF;CAEF,MAAM,mBAAmB,OACvB,cACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR,MAAM,EAAE,aAAa;CACvB,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,YACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,WAAW,MACnC,gBACA,cACA;EACE,QAAQ;EACR,MAAM;CACR,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,IACA,eAA+B,CAAC,MAEhC,MAAMA,wBACJ,GAAG,kBAAkB,GAAG,MACxB,gBACA,cACA,EACE,QAAQ,SACV,CACF;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;AAQA,MAAa,qBAAqBC,6CAAe,gBAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["getAssetAPI","getOrganizationAPI","getProjectAPI","getEnvironmentAPI","getUserAPI","getOAuthAPI","getDictionaryAPI","getStripeAPI","getAiAPI","getAnalyticsAPI","getAuditAPI","getTagAPI","getSearchAPI","getEditorAPI","getNewsletterAPI","getGithubAPI","getGitlabAPI","getBitbucketAPI","getShowcaseProjectAPI","getTranslateAPI","getReviewerAPI","getStatusAPI"],"sources":["../../../src/getIntlayerAPI/index.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { defu } from 'defu';\nimport type { FetcherOptions } from '../fetcher';\nimport { getAiAPI } from './ai';\nimport { getAnalyticsAPI } from './analytics';\nimport { getAssetAPI } from './asset';\nimport { getAuditAPI } from './audit';\nimport { getBitbucketAPI } from './bitbucket';\nimport { getDictionaryAPI } from './dictionary';\nimport { getEditorAPI } from './editor';\nimport { getEnvironmentAPI } from './environment';\nimport { getGithubAPI } from './github';\nimport { getGitlabAPI } from './gitlab';\nimport { getNewsletterAPI } from './newsletter';\nimport { getOAuthAPI } from './oAuth';\nimport { getOrganizationAPI } from './organization';\nimport { getProjectAPI } from './project';\nimport { getReviewerAPI } from './reviewer';\nimport { getSearchAPI } from './search';\nimport { getShowcaseProjectAPI } from './showcaseProject';\nimport { getStatusAPI } from './status';\nimport { getStripeAPI } from './stripe';\nimport { getTagAPI } from './tag';\nimport { getTranslateAPI } from './translate';\nimport { getUserAPI } from './user';\n\ninterface IntlayerAPIReturn {\n asset: ReturnType<typeof getAssetAPI>;\n organization: ReturnType<typeof getOrganizationAPI>;\n project: ReturnType<typeof getProjectAPI>;\n environment: ReturnType<typeof getEnvironmentAPI>;\n user: ReturnType<typeof getUserAPI>;\n oAuth: ReturnType<typeof getOAuthAPI>;\n dictionary: ReturnType<typeof getDictionaryAPI>;\n stripe: ReturnType<typeof getStripeAPI>;\n ai: ReturnType<typeof getAiAPI>;\n analytics: ReturnType<typeof getAnalyticsAPI>;\n audit: ReturnType<typeof getAuditAPI>;\n tag: ReturnType<typeof getTagAPI>;\n search: ReturnType<typeof getSearchAPI>;\n editor: ReturnType<typeof getEditorAPI>;\n newsletter: ReturnType<typeof getNewsletterAPI>;\n github: ReturnType<typeof getGithubAPI>;\n gitlab: ReturnType<typeof getGitlabAPI>;\n bitbucket: ReturnType<typeof getBitbucketAPI>;\n showcaseProject: ReturnType<typeof getShowcaseProjectAPI>;\n translate: ReturnType<typeof getTranslateAPI>;\n reviewer: ReturnType<typeof getReviewerAPI>;\n status: ReturnType<typeof getStatusAPI>;\n}\n\nexport const getIntlayerAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: Pick<IntlayerConfig, 'editor'>\n): IntlayerAPIReturn => {\n const resolvedConfig = defu(intlayerConfig ?? {}, {\n editor,\n }) as IntlayerConfig;\n\n return {\n asset: getAssetAPI(authAPIOptions, resolvedConfig),\n organization: getOrganizationAPI(authAPIOptions, resolvedConfig),\n project: getProjectAPI(authAPIOptions, resolvedConfig),\n environment: getEnvironmentAPI(authAPIOptions, resolvedConfig),\n user: getUserAPI(authAPIOptions, resolvedConfig),\n oAuth: getOAuthAPI(authAPIOptions, resolvedConfig),\n dictionary: getDictionaryAPI(authAPIOptions, resolvedConfig),\n stripe: getStripeAPI(authAPIOptions, resolvedConfig),\n ai: getAiAPI(authAPIOptions, resolvedConfig),\n analytics: getAnalyticsAPI(authAPIOptions, resolvedConfig),\n audit: getAuditAPI(authAPIOptions, resolvedConfig),\n tag: getTagAPI(authAPIOptions, resolvedConfig),\n search: getSearchAPI(authAPIOptions, resolvedConfig),\n editor: getEditorAPI(authAPIOptions, resolvedConfig),\n newsletter: getNewsletterAPI(authAPIOptions, resolvedConfig),\n github: getGithubAPI(authAPIOptions, resolvedConfig),\n gitlab: getGitlabAPI(authAPIOptions, resolvedConfig),\n bitbucket: getBitbucketAPI(authAPIOptions, resolvedConfig),\n showcaseProject: getShowcaseProjectAPI(authAPIOptions, resolvedConfig),\n translate: getTranslateAPI(authAPIOptions, resolvedConfig),\n reviewer: getReviewerAPI(authAPIOptions, resolvedConfig),\n status: getStatusAPI(authAPIOptions, resolvedConfig),\n };\n};\n\nexport type IntlayerAPI = ReturnType<typeof getIntlayerAPI>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,kBACX,iBAAiC,CAAC,GAClC,mBACsB;CACtB,MAAM,gCAAsB,kBAAkB,CAAC,GAAG,EAChD,sCACF,CAAC;CAED,OAAO;EACL,OAAOA,yCAAY,gBAAgB,cAAc;EACjD,cAAcC,uDAAmB,gBAAgB,cAAc;EAC/D,SAASC,6CAAc,gBAAgB,cAAc;EACrD,aAAaC,qDAAkB,gBAAgB,cAAc;EAC7D,MAAMC,uCAAW,gBAAgB,cAAc;EAC/C,OAAOC,yCAAY,gBAAgB,cAAc;EACjD,YAAYC,mDAAiB,gBAAgB,cAAc;EAC3D,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,IAAIC,mCAAS,gBAAgB,cAAc;EAC3C,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,OAAOC,yCAAY,gBAAgB,cAAc;EACjD,KAAKC,qCAAU,gBAAgB,cAAc;EAC7C,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,YAAYC,mDAAiB,gBAAgB,cAAc;EAC3D,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,iBAAiBC,6DAAsB,gBAAgB,cAAc;EACrE,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,UAAUC,+CAAe,gBAAgB,cAAc;EACvD,QAAQC,2CAAa,gBAAgB,cAAc;CACrD;AACF"}
1
+ {"version":3,"file":"index.cjs","names":["getAssetAPI","getOrganizationAPI","getProjectAPI","getEnvironmentAPI","getUserAPI","getOAuthAPI","getDictionaryAPI","getStripeAPI","getAiAPI","getAnalyticsAPI","getAuditAPI","getTagAPI","getSearchAPI","getEditorAPI","getNewsletterAPI","getGithubAPI","getGitlabAPI","getBitbucketAPI","getShowcaseProjectAPI","getTranslateAPI","getReviewerAPI","getStatusAPI"],"sources":["../../../src/getIntlayerAPI/index.ts"],"sourcesContent":["import { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { defu } from 'defu';\nimport type { FetcherOptions } from '../fetcher';\nimport { getAiAPI } from './ai';\nimport { getAnalyticsAPI } from './analytics';\nimport { getAssetAPI } from './asset';\nimport { getAuditAPI } from './audit';\nimport { getBitbucketAPI } from './bitbucket';\nimport { getDictionaryAPI } from './dictionary';\nimport { getEditorAPI } from './editor';\nimport { getEnvironmentAPI } from './environment';\nimport { getGithubAPI } from './github';\nimport { getGitlabAPI } from './gitlab';\nimport { getNewsletterAPI } from './newsletter';\nimport { getOAuthAPI } from './oAuth';\nimport { getOrganizationAPI } from './organization';\nimport { getProjectAPI } from './project';\nimport { getReviewerAPI } from './reviewer';\nimport { getSearchAPI } from './search';\nimport { getShowcaseProjectAPI } from './showcaseProject';\nimport { getStatusAPI } from './status';\nimport { getStripeAPI } from './stripe';\nimport { getTagAPI } from './tag';\nimport { getTranslateAPI } from './translate';\nimport { getUserAPI } from './user';\n\ninterface IntlayerAPIReturn {\n asset: ReturnType<typeof getAssetAPI>;\n organization: ReturnType<typeof getOrganizationAPI>;\n project: ReturnType<typeof getProjectAPI>;\n environment: ReturnType<typeof getEnvironmentAPI>;\n user: ReturnType<typeof getUserAPI>;\n oAuth: ReturnType<typeof getOAuthAPI>;\n dictionary: ReturnType<typeof getDictionaryAPI>;\n stripe: ReturnType<typeof getStripeAPI>;\n ai: ReturnType<typeof getAiAPI>;\n analytics: ReturnType<typeof getAnalyticsAPI>;\n audit: ReturnType<typeof getAuditAPI>;\n tag: ReturnType<typeof getTagAPI>;\n search: ReturnType<typeof getSearchAPI>;\n editor: ReturnType<typeof getEditorAPI>;\n newsletter: ReturnType<typeof getNewsletterAPI>;\n github: ReturnType<typeof getGithubAPI>;\n gitlab: ReturnType<typeof getGitlabAPI>;\n bitbucket: ReturnType<typeof getBitbucketAPI>;\n showcaseProject: ReturnType<typeof getShowcaseProjectAPI>;\n translate: ReturnType<typeof getTranslateAPI>;\n reviewer: ReturnType<typeof getReviewerAPI>;\n status: ReturnType<typeof getStatusAPI>;\n}\n\nexport const getIntlayerAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: Pick<IntlayerConfig, 'editor'>\n): IntlayerAPIReturn => {\n const resolvedConfig = defu(intlayerConfig ?? {}, {\n editor,\n }) as IntlayerConfig;\n\n return {\n asset: getAssetAPI(authAPIOptions, resolvedConfig),\n organization: getOrganizationAPI(authAPIOptions, resolvedConfig),\n project: getProjectAPI(authAPIOptions, resolvedConfig),\n environment: getEnvironmentAPI(authAPIOptions, resolvedConfig),\n user: getUserAPI(authAPIOptions, resolvedConfig),\n oAuth: getOAuthAPI(authAPIOptions, resolvedConfig),\n dictionary: getDictionaryAPI(authAPIOptions, resolvedConfig),\n stripe: getStripeAPI(authAPIOptions, resolvedConfig),\n ai: getAiAPI(authAPIOptions, resolvedConfig),\n analytics: getAnalyticsAPI(authAPIOptions, resolvedConfig),\n audit: getAuditAPI(authAPIOptions, resolvedConfig),\n tag: getTagAPI(authAPIOptions, resolvedConfig),\n search: getSearchAPI(authAPIOptions, resolvedConfig),\n editor: getEditorAPI(authAPIOptions, resolvedConfig),\n newsletter: getNewsletterAPI(authAPIOptions, resolvedConfig),\n github: getGithubAPI(authAPIOptions, resolvedConfig),\n gitlab: getGitlabAPI(authAPIOptions, resolvedConfig),\n bitbucket: getBitbucketAPI(authAPIOptions, resolvedConfig),\n showcaseProject: getShowcaseProjectAPI(authAPIOptions, resolvedConfig),\n translate: getTranslateAPI(authAPIOptions, resolvedConfig),\n reviewer: getReviewerAPI(authAPIOptions, resolvedConfig),\n status: getStatusAPI(authAPIOptions, resolvedConfig),\n };\n};\n\nexport type IntlayerAPI = ReturnType<typeof getIntlayerAPI>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,kBACX,iBAAiC,CAAC,GAClC,mBACsB;CACtB,MAAM,qBAAiB,WAAK,kBAAkB,CAAC,GAAG,EAChD,sCACF,CAAC;CAED,OAAO;EACL,OAAOA,yCAAY,gBAAgB,cAAc;EACjD,cAAcC,uDAAmB,gBAAgB,cAAc;EAC/D,SAASC,6CAAc,gBAAgB,cAAc;EACrD,aAAaC,qDAAkB,gBAAgB,cAAc;EAC7D,MAAMC,uCAAW,gBAAgB,cAAc;EAC/C,OAAOC,yCAAY,gBAAgB,cAAc;EACjD,YAAYC,mDAAiB,gBAAgB,cAAc;EAC3D,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,IAAIC,mCAAS,gBAAgB,cAAc;EAC3C,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,OAAOC,yCAAY,gBAAgB,cAAc;EACjD,KAAKC,qCAAU,gBAAgB,cAAc;EAC7C,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,YAAYC,mDAAiB,gBAAgB,cAAc;EAC3D,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,QAAQC,2CAAa,gBAAgB,cAAc;EACnD,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,iBAAiBC,6DAAsB,gBAAgB,cAAc;EACrE,WAAWC,iDAAgB,gBAAgB,cAAc;EACzD,UAAUC,+CAAe,gBAAgB,cAAc;EACvD,QAAQC,2CAAa,gBAAgB,cAAc;CACrD;AACF"}
@@ -29,6 +29,7 @@ const require_distantDictionary_fetchDistantDictionaries = require('./distantDic
29
29
  const require_distantDictionary_fetchDistantDictionary = require('./distantDictionary/fetchDistantDictionary.cjs');
30
30
  const require_getIntlayerAPI_index = require('./getIntlayerAPI/index.cjs');
31
31
 
32
+ exports.FetcherError = require_fetcher.FetcherError;
32
33
  exports.aiEndpoint = require_getIntlayerAPI_ai.aiEndpoint;
33
34
  exports.analyticsEndpoint = require_getIntlayerAPI_analytics.analyticsEndpoint;
34
35
  exports.assetEndpoint = require_getIntlayerAPI_asset.assetEndpoint;
@@ -1,5 +1,27 @@
1
1
  //#region src/fetcher.ts
2
2
  /**
3
+ * Error thrown when the backend answers with a non-ok response.
4
+ *
5
+ * Carries the HTTP status and the backend error code alongside the message, so
6
+ * callers can tell a transient failure (5xx, network) from a deterministic one
7
+ * (4xx) instead of blindly retrying.
8
+ */
9
+ var FetcherError = class extends Error {
10
+ /** HTTP status code of the response. */
11
+ status;
12
+ /** Error code returned by the backend, when available (ex: `DICTIONARY_NOT_FOUND`). */
13
+ code;
14
+ /** Raw error payload returned by the backend. */
15
+ data;
16
+ constructor(message, details) {
17
+ super(message);
18
+ this.name = "FetcherError";
19
+ this.status = details.status;
20
+ this.code = details.code;
21
+ this.data = details.data;
22
+ }
23
+ };
24
+ /**
3
25
  * Default options for the fetcher function.
4
26
  * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',
5
27
  * and includes credentials in the request.
@@ -110,12 +132,16 @@ const fetcher = async (url, ...options) => {
110
132
  const urlResult = `${url}${paramsString}`;
111
133
  const response = await fetch(urlResult, formattedOptions);
112
134
  if (!response.ok) {
113
- const result = await response.json();
114
- throw new Error(JSON.stringify(result.error) ?? "An error occurred");
135
+ const result = await response.json().catch(() => void 0);
136
+ throw new FetcherError(JSON.stringify(result?.error) ?? "An error occurred", {
137
+ status: response.status,
138
+ code: result?.error?.code,
139
+ data: result?.error
140
+ });
115
141
  }
116
142
  return await response.json();
117
143
  };
118
144
 
119
145
  //#endregion
120
- export { fetcher, fetcherOptions };
146
+ export { FetcherError, fetcher, fetcherOptions };
121
147
  //# sourceMappingURL=fetcher.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.mjs","names":[],"sources":["../../src/fetcher.ts"],"sourcesContent":["/**\n * Type definition for options used in the fetcher function.\n * Extends the standard RequestInit interface (excluding 'body'),\n * and adds 'body' and 'params' properties for convenience.\n */\nexport type FetcherOptions = Omit<RequestInit, 'body'> & {\n /**\n * Body of the request. Should be a key-value pair object.\n */\n body?: Record<string, unknown>;\n /**\n * Query parameters to be appended to the URL.\n */\n params?:\n | Record<string, string | string[] | undefined>\n | string[]\n | URLSearchParams;\n};\n\n/**\n * Default options for the fetcher function.\n * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',\n * and includes credentials in the request.\n */\nexport const fetcherOptions: FetcherOptions = {\n method: 'GET', // Default HTTP method\n headers: {\n 'Content-Type': 'application/json', // Default content type\n },\n credentials: 'include',\n};\n\n/**\n * Utility function to remove properties with undefined values from an object.\n * This helps prevent sending undefined values in the request options.\n *\n * @param obj - The object to clean.\n * @returns The cleaned object without undefined values.\n */\nconst removeUndefined = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (obj[key as keyof typeof obj] === undefined) {\n delete obj[key as keyof typeof obj];\n }\n });\n return obj;\n};\n\n/**\n * Deeply merges an array of objects into a single object.\n * Later objects in the array overwrite properties of earlier ones.\n *\n * @template T - The type of objects being merged.\n * @param objects - An array of objects to merge.\n * @returns The merged object.\n */\nconst deepMerge = <T extends object>(objects: (T | undefined)[]): T =>\n objects.reduce((acc, obj) => {\n const acc1: T = (acc ?? {}) as T;\n const obj1: T = removeUndefined(obj ?? {}) as T;\n\n if (typeof acc1 === 'object' && typeof obj1 === 'object') {\n // Merge the two objects\n return { ...acc1, ...obj1 };\n }\n\n // If one of them is not an object, return the defined one\n return obj1 ?? acc1;\n }, {} as T)!;\n\n/**\n * Fetcher function to make HTTP requests.\n * It merges default options with user-provided options,\n * handles query parameters and request body,\n * and returns the parsed JSON response.\n *\n * @template T - The expected type of the response data.\n * @param url - The endpoint URL.\n * @param options - Additional options to customize the request.\n * @returns A promise that resolves with the response data of type T.\n *\n * @example\n * ```typescript\n * // Making a GET request with query parameters\n * const data = await fetcher<MyResponseType>('https://api.example.com/data', {\n * params: { search: 'query' },\n * });\n *\n * // Making a POST request with a JSON body\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * });\n *\n * // Merge body, headers, and params\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * headers: { 'Content-Type': 'application/json' },\n * params: { search: 'query' },\n * },\n * {\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1 },\n * });\n * ```\n *\n * Result:\n * ```typescript\n * {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1, search: 'query' },\n * body: { key: 'value' },\n * }\n * ```\n */\nexport const fetcher = async <T>(\n url: string,\n ...options: FetcherOptions[]\n): Promise<T> => {\n const { signal } = new AbortController();\n\n // Initialize query parameters string and request body string\n let paramsString = '';\n let bodyString: string | undefined;\n\n // Extract other options excluding 'body', 'params', and 'headers'\n const otherOptions = options.map(\n ({ body, params, headers, ...otherOptions }) => otherOptions\n );\n\n // Merge default options with user-provided options\n const mergedOptions = deepMerge([fetcherOptions, ...otherOptions]);\n\n // Merge default headers with user-provided headers\n const mergedHeaders = deepMerge([\n fetcherOptions.headers,\n ...options.map((option) => option.headers),\n ]);\n\n // Merge query parameters\n const params = deepMerge(options.map((option) => option.params));\n\n const method = mergedOptions.method;\n\n // If the request method is not 'GET' or 'HEAD', prepare the request body\n if (method !== 'GET' && method !== 'HEAD') {\n // Merge all 'body' options\n const body = deepMerge(options.map((option) => option.body));\n if (\n mergedHeaders?.['Content-Type' as keyof HeadersInit] ===\n 'application/x-www-form-urlencoded'\n ) {\n // If the content type is 'application/x-www-form-urlencoded', encode the body accordingly\n bodyString = new URLSearchParams(\n body as Record<string, string>\n ).toString();\n } else {\n // Otherwise, stringify the body as JSON\n bodyString = JSON.stringify(body);\n }\n }\n\n // If there are query parameters, append them to the URL\n if (Object.entries(params).length > 0) {\n paramsString = `?${new URLSearchParams(\n params as Record<string, string>\n ).toString()}`;\n }\n\n // Prepare the final request options\n const formattedOptions: RequestInit = {\n ...mergedOptions,\n headers: mergedHeaders,\n body: bodyString,\n signal,\n };\n\n // Construct the full URL with query parameters\n const urlResult = `${url}${paramsString}`;\n\n // Make the HTTP request using fetch\n const response = await fetch(urlResult, formattedOptions);\n\n if (!response.ok) {\n const result = await response.json();\n\n // You can customize the error message or include more details\n throw new Error(JSON.stringify(result.error) ?? 'An error occurred');\n }\n return await response.json();\n};\n"],"mappings":";;;;;;AAwBA,MAAa,iBAAiC;CAC5C,QAAQ;CACR,SAAS,EACP,gBAAgB,mBAClB;CACA,aAAa;AACf;;;;;;;;AASA,MAAM,mBAAmB,QAAgB;CACvC,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,QAAQ;EAChC,IAAI,IAAI,SAA6B,QACnC,OAAO,IAAI;CAEf,CAAC;CACD,OAAO;AACT;;;;;;;;;AAUA,MAAM,aAA+B,YACnC,QAAQ,QAAQ,KAAK,QAAQ;CAC3B,MAAM,OAAW,OAAO,CAAC;CACzB,MAAM,OAAU,gBAAgB,OAAO,CAAC,CAAC;CAEzC,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAE9C,OAAO;EAAE,GAAG;EAAM,GAAG;CAAK;CAI5B,OAAO,QAAQ;AACjB,GAAG,CAAC,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDZ,MAAa,UAAU,OACrB,KACA,GAAG,YACY;CACf,MAAM,EAAE,WAAW,IAAI,gBAAgB;CAGvC,IAAI,eAAe;CACnB,IAAI;CAGJ,MAAM,eAAe,QAAQ,KAC1B,EAAE,MAAM,QAAQ,SAAS,GAAG,mBAAmB,YAClD;CAGA,MAAM,gBAAgB,UAAU,CAAC,gBAAgB,GAAG,YAAY,CAAC;CAGjE,MAAM,gBAAgB,UAAU,CAC9B,eAAe,SACf,GAAG,QAAQ,KAAK,WAAW,OAAO,OAAO,CAC3C,CAAC;CAGD,MAAM,SAAS,UAAU,QAAQ,KAAK,WAAW,OAAO,MAAM,CAAC;CAE/D,MAAM,SAAS,cAAc;CAG7B,IAAI,WAAW,SAAS,WAAW,QAAQ;EAEzC,MAAM,OAAO,UAAU,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC;EAC3D,IACE,gBAAgB,oBAChB,qCAGA,aAAa,IAAI,gBACf,IACF,CAAC,CAAC,SAAS;OAGX,aAAa,KAAK,UAAU,IAAI;CAEpC;CAGA,IAAI,OAAO,QAAQ,MAAM,CAAC,CAAC,SAAS,GAClC,eAAe,IAAI,IAAI,gBACrB,MACF,CAAC,CAAC,SAAS;CAIb,MAAM,mBAAgC;EACpC,GAAG;EACH,SAAS;EACT,MAAM;EACN;CACF;CAGA,MAAM,YAAY,GAAG,MAAM;CAG3B,MAAM,WAAW,MAAM,MAAM,WAAW,gBAAgB;CAExD,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,SAAS,MAAM,SAAS,KAAK;EAGnC,MAAM,IAAI,MAAM,KAAK,UAAU,OAAO,KAAK,KAAK,mBAAmB;CACrE;CACA,OAAO,MAAM,SAAS,KAAK;AAC7B"}
1
+ {"version":3,"file":"fetcher.mjs","names":[],"sources":["../../src/fetcher.ts"],"sourcesContent":["/**\n * Error thrown when the backend answers with a non-ok response.\n *\n * Carries the HTTP status and the backend error code alongside the message, so\n * callers can tell a transient failure (5xx, network) from a deterministic one\n * (4xx) instead of blindly retrying.\n */\nexport class FetcherError extends Error {\n /** HTTP status code of the response. */\n public readonly status: number;\n /** Error code returned by the backend, when available (ex: `DICTIONARY_NOT_FOUND`). */\n public readonly code?: string;\n /** Raw error payload returned by the backend. */\n public readonly data?: unknown;\n\n constructor(\n message: string,\n details: { status: number; code?: string; data?: unknown }\n ) {\n super(message);\n\n this.name = 'FetcherError';\n this.status = details.status;\n this.code = details.code;\n this.data = details.data;\n }\n}\n\n/**\n * Type definition for options used in the fetcher function.\n * Extends the standard RequestInit interface (excluding 'body'),\n * and adds 'body' and 'params' properties for convenience.\n */\nexport type FetcherOptions = Omit<RequestInit, 'body'> & {\n /**\n * Body of the request. Should be a key-value pair object.\n */\n body?: Record<string, unknown>;\n /**\n * Query parameters to be appended to the URL.\n */\n params?:\n | Record<string, string | string[] | undefined>\n | string[]\n | URLSearchParams;\n};\n\n/**\n * Default options for the fetcher function.\n * Sets the default method to 'GET', the 'Content-Type' header to 'application/json',\n * and includes credentials in the request.\n */\nexport const fetcherOptions: FetcherOptions = {\n method: 'GET', // Default HTTP method\n headers: {\n 'Content-Type': 'application/json', // Default content type\n },\n credentials: 'include',\n};\n\n/**\n * Utility function to remove properties with undefined values from an object.\n * This helps prevent sending undefined values in the request options.\n *\n * @param obj - The object to clean.\n * @returns The cleaned object without undefined values.\n */\nconst removeUndefined = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (obj[key as keyof typeof obj] === undefined) {\n delete obj[key as keyof typeof obj];\n }\n });\n return obj;\n};\n\n/**\n * Deeply merges an array of objects into a single object.\n * Later objects in the array overwrite properties of earlier ones.\n *\n * @template T - The type of objects being merged.\n * @param objects - An array of objects to merge.\n * @returns The merged object.\n */\nconst deepMerge = <T extends object>(objects: (T | undefined)[]): T =>\n objects.reduce((acc, obj) => {\n const acc1: T = (acc ?? {}) as T;\n const obj1: T = removeUndefined(obj ?? {}) as T;\n\n if (typeof acc1 === 'object' && typeof obj1 === 'object') {\n // Merge the two objects\n return { ...acc1, ...obj1 };\n }\n\n // If one of them is not an object, return the defined one\n return obj1 ?? acc1;\n }, {} as T)!;\n\n/**\n * Fetcher function to make HTTP requests.\n * It merges default options with user-provided options,\n * handles query parameters and request body,\n * and returns the parsed JSON response.\n *\n * @template T - The expected type of the response data.\n * @param url - The endpoint URL.\n * @param options - Additional options to customize the request.\n * @returns A promise that resolves with the response data of type T.\n *\n * @example\n * ```typescript\n * // Making a GET request with query parameters\n * const data = await fetcher<MyResponseType>('https://api.example.com/data', {\n * params: { search: 'query' },\n * });\n *\n * // Making a POST request with a JSON body\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * });\n *\n * // Merge body, headers, and params\n * const result = await fetcher<AnotherResponseType>('https://api.example.com/submit', {\n * method: 'POST',\n * body: { key: 'value' },\n * headers: { 'Content-Type': 'application/json' },\n * params: { search: 'query' },\n * },\n * {\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1 },\n * });\n * ```\n *\n * Result:\n * ```typescript\n * {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n * params: { page: 1, search: 'query' },\n * body: { key: 'value' },\n * }\n * ```\n */\nexport const fetcher = async <T>(\n url: string,\n ...options: FetcherOptions[]\n): Promise<T> => {\n const { signal } = new AbortController();\n\n // Initialize query parameters string and request body string\n let paramsString = '';\n let bodyString: string | undefined;\n\n // Extract other options excluding 'body', 'params', and 'headers'\n const otherOptions = options.map(\n ({ body, params, headers, ...otherOptions }) => otherOptions\n );\n\n // Merge default options with user-provided options\n const mergedOptions = deepMerge([fetcherOptions, ...otherOptions]);\n\n // Merge default headers with user-provided headers\n const mergedHeaders = deepMerge([\n fetcherOptions.headers,\n ...options.map((option) => option.headers),\n ]);\n\n // Merge query parameters\n const params = deepMerge(options.map((option) => option.params));\n\n const method = mergedOptions.method;\n\n // If the request method is not 'GET' or 'HEAD', prepare the request body\n if (method !== 'GET' && method !== 'HEAD') {\n // Merge all 'body' options\n const body = deepMerge(options.map((option) => option.body));\n if (\n mergedHeaders?.['Content-Type' as keyof HeadersInit] ===\n 'application/x-www-form-urlencoded'\n ) {\n // If the content type is 'application/x-www-form-urlencoded', encode the body accordingly\n bodyString = new URLSearchParams(\n body as Record<string, string>\n ).toString();\n } else {\n // Otherwise, stringify the body as JSON\n bodyString = JSON.stringify(body);\n }\n }\n\n // If there are query parameters, append them to the URL\n if (Object.entries(params).length > 0) {\n paramsString = `?${new URLSearchParams(\n params as Record<string, string>\n ).toString()}`;\n }\n\n // Prepare the final request options\n const formattedOptions: RequestInit = {\n ...mergedOptions,\n headers: mergedHeaders,\n body: bodyString,\n signal,\n };\n\n // Construct the full URL with query parameters\n const urlResult = `${url}${paramsString}`;\n\n // Make the HTTP request using fetch\n const response = await fetch(urlResult, formattedOptions);\n\n if (!response.ok) {\n const result = await response.json().catch(() => undefined);\n\n // You can customize the error message or include more details\n throw new FetcherError(\n JSON.stringify(result?.error) ?? 'An error occurred',\n {\n status: response.status,\n code: result?.error?.code,\n data: result?.error,\n }\n );\n }\n return await response.json();\n};\n"],"mappings":";;;;;;;;AAOA,IAAa,eAAb,cAAkC,MAAM;;CAEtC,AAAgB;;CAEhB,AAAgB;;CAEhB,AAAgB;CAEhB,YACE,SACA,SACA;EACA,MAAM,OAAO;EAEb,KAAK,OAAO;EACZ,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,QAAQ;EACpB,KAAK,OAAO,QAAQ;CACtB;AACF;;;;;;AA0BA,MAAa,iBAAiC;CAC5C,QAAQ;CACR,SAAS,EACP,gBAAgB,mBAClB;CACA,aAAa;AACf;;;;;;;;AASA,MAAM,mBAAmB,QAAgB;CACvC,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,QAAQ;EAChC,IAAI,IAAI,SAA6B,QACnC,OAAO,IAAI;CAEf,CAAC;CACD,OAAO;AACT;;;;;;;;;AAUA,MAAM,aAA+B,YACnC,QAAQ,QAAQ,KAAK,QAAQ;CAC3B,MAAM,OAAW,OAAO,CAAC;CACzB,MAAM,OAAU,gBAAgB,OAAO,CAAC,CAAC;CAEzC,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAE9C,OAAO;EAAE,GAAG;EAAM,GAAG;CAAK;CAI5B,OAAO,QAAQ;AACjB,GAAG,CAAC,CAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDZ,MAAa,UAAU,OACrB,KACA,GAAG,YACY;CACf,MAAM,EAAE,WAAW,IAAI,gBAAgB;CAGvC,IAAI,eAAe;CACnB,IAAI;CAGJ,MAAM,eAAe,QAAQ,KAC1B,EAAE,MAAM,QAAQ,SAAS,GAAG,mBAAmB,YAClD;CAGA,MAAM,gBAAgB,UAAU,CAAC,gBAAgB,GAAG,YAAY,CAAC;CAGjE,MAAM,gBAAgB,UAAU,CAC9B,eAAe,SACf,GAAG,QAAQ,KAAK,WAAW,OAAO,OAAO,CAC3C,CAAC;CAGD,MAAM,SAAS,UAAU,QAAQ,KAAK,WAAW,OAAO,MAAM,CAAC;CAE/D,MAAM,SAAS,cAAc;CAG7B,IAAI,WAAW,SAAS,WAAW,QAAQ;EAEzC,MAAM,OAAO,UAAU,QAAQ,KAAK,WAAW,OAAO,IAAI,CAAC;EAC3D,IACE,gBAAgB,oBAChB,qCAGA,aAAa,IAAI,gBACf,IACF,CAAC,CAAC,SAAS;OAGX,aAAa,KAAK,UAAU,IAAI;CAEpC;CAGA,IAAI,OAAO,QAAQ,MAAM,CAAC,CAAC,SAAS,GAClC,eAAe,IAAI,IAAI,gBACrB,MACF,CAAC,CAAC,SAAS;CAIb,MAAM,mBAAgC;EACpC,GAAG;EACH,SAAS;EACT,MAAM;EACN;CACF;CAGA,MAAM,YAAY,GAAG,MAAM;CAG3B,MAAM,WAAW,MAAM,MAAM,WAAW,gBAAgB;CAExD,IAAI,CAAC,SAAS,IAAI;EAChB,MAAM,SAAS,MAAM,SAAS,KAAK,CAAC,CAAC,YAAY,MAAS;EAG1D,MAAM,IAAI,aACR,KAAK,UAAU,QAAQ,KAAK,KAAK,qBACjC;GACE,QAAQ,SAAS;GACjB,MAAM,QAAQ,OAAO;GACrB,MAAM,QAAQ;EAChB,CACF;CACF;CACA,OAAO,MAAM,SAAS,KAAK;AAC7B"}
@@ -28,6 +28,21 @@ const getDictionaryAPI = (authAPIOptions = {}, intlayerConfig) => {
28
28
  */
29
29
  const getDictionary = async (dictionaryKey, version, otherOptions = {}) => await fetcher(`${PROJECT_API_ROUTE}/${dictionaryKey}`, authAPIOptions, otherOptions, { params: version ? { version: version.toString() } : void 0 });
30
30
  /**
31
+ * Retrieves several dictionaries at once from their keys, in a single
32
+ * request. Keys matching no dictionary are absent from the result, so the
33
+ * caller should reconcile the response against the requested keys.
34
+ *
35
+ * @param dictionaryKeys - Dictionary keys to retrieve.
36
+ * @param version - Dictionary version of content.
37
+ */
38
+ const getDictionariesByKeys = async (dictionaryKeys, version, otherOptions = {}) => await fetcher(`${PROJECT_API_ROUTE}/by-keys`, authAPIOptions, otherOptions, {
39
+ cache: "no-store",
40
+ params: {
41
+ keys: dictionaryKeys.join(","),
42
+ version: version?.toString()
43
+ }
44
+ });
45
+ /**
31
46
  * Adds a new dictionary to the database.
32
47
  * @param dictionary - Dictionary data.
33
48
  */
@@ -57,6 +72,7 @@ const getDictionaryAPI = (authAPIOptions = {}, intlayerConfig) => {
57
72
  getDictionariesKeys,
58
73
  getDictionariesUpdateTimestamp,
59
74
  getDictionary,
75
+ getDictionariesByKeys,
60
76
  pushDictionaries,
61
77
  addDictionary,
62
78
  updateDictionary,
@@ -1 +1 @@
1
- {"version":3,"file":"dictionary.mjs","names":[],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"sourcesContent":["import type {\n AddDictionaryBody,\n AddDictionaryResult,\n DeleteDictionaryParam,\n DeleteDictionaryResult,\n GetDictionariesKeysResult,\n GetDictionariesParams,\n GetDictionariesResult,\n GetDictionariesUpdateTimestampResult,\n GetDictionaryParams,\n GetDictionaryQuery,\n GetDictionaryResult,\n PushDictionariesBody,\n PushDictionariesResult,\n UpdateDictionaryBody,\n UpdateDictionaryResult,\n} from '@intlayer/backend';\nimport { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { createEndpoint } from '../cms/createIntlayerCMS';\nimport { type FetcherOptions, fetcher } from '../fetcher';\n\nexport const getDictionaryAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: IntlayerConfig\n) => {\n const backendURL = intlayerConfig?.editor?.backendURL ?? editor.backendURL;\n\n const PROJECT_API_ROUTE = `${backendURL}/api/dictionary`;\n\n /**\n * Retrieves a list of dictionaries based on filters and pagination.\n * @param filters - Filters and pagination options.\n */\n const getDictionaries = async (\n filters?: GetDictionariesParams,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesResult>(\n PROJECT_API_ROUTE,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n // @ts-ignore Number of parameter will be stringified by the fetcher\n params: filters,\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesKeys = async (otherOptions: FetcherOptions = {}) =>\n await fetcher<GetDictionariesKeysResult>(\n `${PROJECT_API_ROUTE}/keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesUpdateTimestamp = async (\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesUpdateTimestampResult>(\n `${PROJECT_API_ROUTE}/update`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a dictionary by its key and version.\n * @param dictionaryKey - Dictionary key.\n * @param version - Dictionary version of content.\n */\n const getDictionary = async (\n dictionaryKey: GetDictionaryParams['dictionaryKey'],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionaryKey}`,\n authAPIOptions,\n otherOptions,\n {\n params: version ? { version: version.toString() } : undefined,\n }\n );\n\n /**\n * Adds a new dictionary to the database.\n * @param dictionary - Dictionary data.\n */\n const addDictionary = async (\n body: AddDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<AddDictionaryResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'POST',\n body,\n }\n );\n\n const pushDictionaries = async (\n dictionaries: PushDictionariesBody['dictionaries'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<PushDictionariesResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PATCH',\n body: { dictionaries },\n }\n );\n\n /**\n * Updates an existing dictionary in the database.\n * @param dictionary - Updated dictionary data.\n */\n const updateDictionary = async (\n dictionary: UpdateDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<UpdateDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionary.id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PUT',\n body: dictionary,\n }\n );\n\n /**\n * Deletes a dictionary from the database by its ID.\n * @param id - Dictionary ID.\n */\n const deleteDictionary = async (\n id: DeleteDictionaryParam['dictionaryId'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<DeleteDictionaryResult>(\n `${PROJECT_API_ROUTE}/${id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'DELETE',\n }\n );\n\n return {\n getDictionaries,\n getDictionariesKeys,\n getDictionariesUpdateTimestamp,\n getDictionary,\n pushDictionaries,\n addDictionary,\n updateDictionary,\n deleteDictionary,\n };\n};\n\n/**\n * Authenticated `dictionary` endpoint bound to an Intlayer CMS authenticator.\n *\n * Pass an authenticator created with `createIntlayerCMS`, or omit it to use\n * the build-time configuration (`@intlayer/config/built`).\n */\nexport const dictionaryEndpoint = createEndpoint(getDictionaryAPI);\n"],"mappings":";;;;;AAsBA,MAAa,oBACX,iBAAiC,CAAC,GAClC,mBACG;CAGH,MAAM,oBAAoB,GAFP,gBAAgB,QAAQ,cAAc,OAAO,WAExB;;;;;CAMxC,MAAM,kBAAkB,OACtB,SACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,mBACA,gBACA,cACA;EACE,OAAO;EAEP,QAAQ;CACV,CACF;;;;CAKF,MAAM,sBAAsB,OAAO,eAA+B,CAAC,MACjE,MAAM,QACJ,GAAG,kBAAkB,QACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;CAKF,MAAM,iCAAiC,OACrC,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,UACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;;;CAOF,MAAM,gBAAgB,OACpB,eACA,SACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,iBACxB,gBACA,cACA,EACE,QAAQ,UAAU,EAAE,SAAS,QAAQ,SAAS,EAAE,IAAI,OACtD,CACF;;;;;CAMF,MAAM,gBAAgB,OACpB,MACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR;CACF,CACF;CAEF,MAAM,mBAAmB,OACvB,cACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR,MAAM,EAAE,aAAa;CACvB,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,YACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,WAAW,MACnC,gBACA,cACA;EACE,QAAQ;EACR,MAAM;CACR,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,IACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,MACxB,gBACA,cACA,EACE,QAAQ,SACV,CACF;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;AAQA,MAAa,qBAAqB,eAAe,gBAAgB"}
1
+ {"version":3,"file":"dictionary.mjs","names":[],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"sourcesContent":["import type {\n AddDictionaryBody,\n AddDictionaryResult,\n DeleteDictionaryParam,\n DeleteDictionaryResult,\n GetDictionariesByKeysResult,\n GetDictionariesKeysResult,\n GetDictionariesParams,\n GetDictionariesResult,\n GetDictionariesUpdateTimestampResult,\n GetDictionaryParams,\n GetDictionaryQuery,\n GetDictionaryResult,\n PushDictionariesBody,\n PushDictionariesResult,\n UpdateDictionaryBody,\n UpdateDictionaryResult,\n} from '@intlayer/backend';\nimport { editor } from '@intlayer/config/built';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { createEndpoint } from '../cms/createIntlayerCMS';\nimport { type FetcherOptions, fetcher } from '../fetcher';\n\nexport const getDictionaryAPI = (\n authAPIOptions: FetcherOptions = {},\n intlayerConfig?: IntlayerConfig\n) => {\n const backendURL = intlayerConfig?.editor?.backendURL ?? editor.backendURL;\n\n const PROJECT_API_ROUTE = `${backendURL}/api/dictionary`;\n\n /**\n * Retrieves a list of dictionaries based on filters and pagination.\n * @param filters - Filters and pagination options.\n */\n const getDictionaries = async (\n filters?: GetDictionariesParams,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesResult>(\n PROJECT_API_ROUTE,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n // @ts-ignore Number of parameter will be stringified by the fetcher\n params: filters,\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesKeys = async (otherOptions: FetcherOptions = {}) =>\n await fetcher<GetDictionariesKeysResult>(\n `${PROJECT_API_ROUTE}/keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a list of dictionary keys related to the project.\n */\n const getDictionariesUpdateTimestamp = async (\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesUpdateTimestampResult>(\n `${PROJECT_API_ROUTE}/update`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n }\n );\n\n /**\n * Retrieves a dictionary by its key and version.\n * @param dictionaryKey - Dictionary key.\n * @param version - Dictionary version of content.\n */\n const getDictionary = async (\n dictionaryKey: GetDictionaryParams['dictionaryKey'],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionaryKey}`,\n authAPIOptions,\n otherOptions,\n {\n params: version ? { version: version.toString() } : undefined,\n }\n );\n\n /**\n * Retrieves several dictionaries at once from their keys, in a single\n * request. Keys matching no dictionary are absent from the result, so the\n * caller should reconcile the response against the requested keys.\n *\n * @param dictionaryKeys - Dictionary keys to retrieve.\n * @param version - Dictionary version of content.\n */\n const getDictionariesByKeys = async (\n dictionaryKeys: string[],\n version?: GetDictionaryQuery['version'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<GetDictionariesByKeysResult>(\n `${PROJECT_API_ROUTE}/by-keys`,\n authAPIOptions,\n otherOptions,\n {\n cache: 'no-store',\n params: {\n keys: dictionaryKeys.join(','),\n version: version?.toString(),\n },\n }\n );\n\n /**\n * Adds a new dictionary to the database.\n * @param dictionary - Dictionary data.\n */\n const addDictionary = async (\n body: AddDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<AddDictionaryResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'POST',\n body,\n }\n );\n\n const pushDictionaries = async (\n dictionaries: PushDictionariesBody['dictionaries'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<PushDictionariesResult>(\n `${PROJECT_API_ROUTE}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PATCH',\n body: { dictionaries },\n }\n );\n\n /**\n * Updates an existing dictionary in the database.\n * @param dictionary - Updated dictionary data.\n */\n const updateDictionary = async (\n dictionary: UpdateDictionaryBody,\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<UpdateDictionaryResult>(\n `${PROJECT_API_ROUTE}/${dictionary.id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'PUT',\n body: dictionary,\n }\n );\n\n /**\n * Deletes a dictionary from the database by its ID.\n * @param id - Dictionary ID.\n */\n const deleteDictionary = async (\n id: DeleteDictionaryParam['dictionaryId'],\n otherOptions: FetcherOptions = {}\n ) =>\n await fetcher<DeleteDictionaryResult>(\n `${PROJECT_API_ROUTE}/${id}`,\n authAPIOptions,\n otherOptions,\n {\n method: 'DELETE',\n }\n );\n\n return {\n getDictionaries,\n getDictionariesKeys,\n getDictionariesUpdateTimestamp,\n getDictionary,\n getDictionariesByKeys,\n pushDictionaries,\n addDictionary,\n updateDictionary,\n deleteDictionary,\n };\n};\n\n/**\n * Authenticated `dictionary` endpoint bound to an Intlayer CMS authenticator.\n *\n * Pass an authenticator created with `createIntlayerCMS`, or omit it to use\n * the build-time configuration (`@intlayer/config/built`).\n */\nexport const dictionaryEndpoint = createEndpoint(getDictionaryAPI);\n"],"mappings":";;;;;AAuBA,MAAa,oBACX,iBAAiC,CAAC,GAClC,mBACG;CAGH,MAAM,oBAAoB,GAFP,gBAAgB,QAAQ,cAAc,OAAO,WAExB;;;;;CAMxC,MAAM,kBAAkB,OACtB,SACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,mBACA,gBACA,cACA;EACE,OAAO;EAEP,QAAQ;CACV,CACF;;;;CAKF,MAAM,sBAAsB,OAAO,eAA+B,CAAC,MACjE,MAAM,QACJ,GAAG,kBAAkB,QACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;CAKF,MAAM,iCAAiC,OACrC,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,UACrB,gBACA,cACA,EACE,OAAO,WACT,CACF;;;;;;CAOF,MAAM,gBAAgB,OACpB,eACA,SACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,iBACxB,gBACA,cACA,EACE,QAAQ,UAAU,EAAE,SAAS,QAAQ,SAAS,EAAE,IAAI,OACtD,CACF;;;;;;;;;CAUF,MAAM,wBAAwB,OAC5B,gBACA,SACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,WACrB,gBACA,cACA;EACE,OAAO;EACP,QAAQ;GACN,MAAM,eAAe,KAAK,GAAG;GAC7B,SAAS,SAAS,SAAS;EAC7B;CACF,CACF;;;;;CAMF,MAAM,gBAAgB,OACpB,MACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR;CACF,CACF;CAEF,MAAM,mBAAmB,OACvB,cACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,qBACH,gBACA,cACA;EACE,QAAQ;EACR,MAAM,EAAE,aAAa;CACvB,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,YACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,WAAW,MACnC,gBACA,cACA;EACE,QAAQ;EACR,MAAM;CACR,CACF;;;;;CAMF,MAAM,mBAAmB,OACvB,IACA,eAA+B,CAAC,MAEhC,MAAM,QACJ,GAAG,kBAAkB,GAAG,MACxB,gBACA,cACA,EACE,QAAQ,SACV,CACF;CAEF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;AAQA,MAAa,qBAAqB,eAAe,gBAAgB"}
@@ -1,4 +1,4 @@
1
- import { fetcher, fetcherOptions } from "./fetcher.mjs";
1
+ import { FetcherError, fetcher, fetcherOptions } from "./fetcher.mjs";
2
2
  import { getOAuthAPI } from "./getIntlayerAPI/oAuth.mjs";
3
3
  import { createAuthManager } from "./cms/createAuthManager.mjs";
4
4
  import { createEndpoint, createIntlayerCMS } from "./cms/createIntlayerCMS.mjs";
@@ -28,4 +28,4 @@ import { fetchDistantDictionaries } from "./distantDictionary/fetchDistantDictio
28
28
  import { fetchDistantDictionary } from "./distantDictionary/fetchDistantDictionary.mjs";
29
29
  import { getIntlayerAPI } from "./getIntlayerAPI/index.mjs";
30
30
 
31
- export { aiEndpoint, analyticsEndpoint, assetEndpoint, auditEndpoint, bitbucketEndpoint, createAuthManager, createEndpoint, createIntlayerCMS, dictionaryEndpoint, editorEndpoint, environmentEndpoint, fetchDistantDictionaries, fetchDistantDictionary, fetcher, fetcherOptions, getAiAPI, getAnalyticsAPI, getAssetAPI, getAuditAPI, getBitbucketAPI, getDictionaryAPI, getEditorAPI, getEnvironmentAPI, getGithubAPI, getGitlabAPI, getIntlayerAPI, getIntlayerAPIProxy, getNewsletterAPI, getOAuthAPI, getOrganizationAPI, getProjectAPI, getReviewerAPI, getSearchAPI, getShowcaseProjectAPI, getStatusAPI, getStripeAPI, getTagAPI, getTranslateAPI, getUserAPI, githubEndpoint, gitlabEndpoint, newsletterEndpoint, organizationEndpoint, projectEndpoint, reviewerEndpoint, searchEndpoint, showcaseProjectEndpoint, statusEndpoint, stripeEndpoint, tagEndpoint, translateEndpoint, userEndpoint };
31
+ export { FetcherError, aiEndpoint, analyticsEndpoint, assetEndpoint, auditEndpoint, bitbucketEndpoint, createAuthManager, createEndpoint, createIntlayerCMS, dictionaryEndpoint, editorEndpoint, environmentEndpoint, fetchDistantDictionaries, fetchDistantDictionary, fetcher, fetcherOptions, getAiAPI, getAnalyticsAPI, getAssetAPI, getAuditAPI, getBitbucketAPI, getDictionaryAPI, getEditorAPI, getEnvironmentAPI, getGithubAPI, getGitlabAPI, getIntlayerAPI, getIntlayerAPIProxy, getNewsletterAPI, getOAuthAPI, getOrganizationAPI, getProjectAPI, getReviewerAPI, getSearchAPI, getShowcaseProjectAPI, getStatusAPI, getStripeAPI, getTagAPI, getTranslateAPI, getUserAPI, githubEndpoint, gitlabEndpoint, newsletterEndpoint, organizationEndpoint, projectEndpoint, reviewerEndpoint, searchEndpoint, showcaseProjectEndpoint, statusEndpoint, stripeEndpoint, tagEndpoint, translateEndpoint, userEndpoint };
@@ -1,4 +1,24 @@
1
1
  //#region src/fetcher.d.ts
2
+ /**
3
+ * Error thrown when the backend answers with a non-ok response.
4
+ *
5
+ * Carries the HTTP status and the backend error code alongside the message, so
6
+ * callers can tell a transient failure (5xx, network) from a deterministic one
7
+ * (4xx) instead of blindly retrying.
8
+ */
9
+ declare class FetcherError extends Error {
10
+ /** HTTP status code of the response. */
11
+ readonly status: number;
12
+ /** Error code returned by the backend, when available (ex: `DICTIONARY_NOT_FOUND`). */
13
+ readonly code?: string;
14
+ /** Raw error payload returned by the backend. */
15
+ readonly data?: unknown;
16
+ constructor(message: string, details: {
17
+ status: number;
18
+ code?: string;
19
+ data?: unknown;
20
+ });
21
+ }
2
22
  /**
3
23
  * Type definition for options used in the fetcher function.
4
24
  * Extends the standard RequestInit interface (excluding 'body'),
@@ -69,5 +89,5 @@ declare const fetcherOptions: FetcherOptions;
69
89
  */
70
90
  declare const fetcher: <T>(url: string, ...options: FetcherOptions[]) => Promise<T>;
71
91
  //#endregion
72
- export { FetcherOptions, fetcher, fetcherOptions };
92
+ export { FetcherError, FetcherOptions, fetcher, fetcherOptions };
73
93
  //# sourceMappingURL=fetcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","names":[],"sources":["../../src/fetcher.ts"],"mappings":";;;;;;KAKY,iBAAiB,KAAK;;;;EAIhC,OAAO;;;;EAIP,SACI,2DAEA;;;;;;;cAQO,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6FhB,UAAiB,GAAC,gBAClB,SACC,qBACX,QAAQ"}
1
+ {"version":3,"file":"fetcher.d.ts","names":[],"sources":["../../src/fetcher.ts"],"mappings":";;;;;;;;cAOa,qBAAqB;;WAEhB;;WAEA;;WAEA;EAEhB,YACE,iBACA;IAAW;IAAgB;IAAe;;;;;;;;KAgBlC,iBAAiB,KAAK;;;;EAIhC,OAAO;;;;EAIP,SACI,2DAEA;;;;;;;cAQO,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6FhB,UAAiB,GAAC,gBAClB,SACC,qBACX,QAAQ"}
@@ -9,6 +9,7 @@ declare const getDictionaryAPI: (authAPIOptions?: FetcherOptions, intlayerConfig
9
9
  getDictionariesKeys: (otherOptions?: FetcherOptions) => Promise<GetDictionariesKeysResult>;
10
10
  getDictionariesUpdateTimestamp: (otherOptions?: FetcherOptions) => Promise<GetDictionariesUpdateTimestampResult>;
11
11
  getDictionary: (dictionaryKey: GetDictionaryParams['dictionaryKey'], version?: GetDictionaryQuery['version'], otherOptions?: FetcherOptions) => Promise<GetDictionaryResult>;
12
+ getDictionariesByKeys: (dictionaryKeys: string[], version?: GetDictionaryQuery['version'], otherOptions?: FetcherOptions) => Promise<GetDictionariesByKeysResult>;
12
13
  pushDictionaries: (dictionaries: PushDictionariesBody['dictionaries'], otherOptions?: FetcherOptions) => Promise<PushDictionariesResult>;
13
14
  addDictionary: (body: AddDictionaryBody, otherOptions?: FetcherOptions) => Promise<AddDictionaryResult>;
14
15
  updateDictionary: (dictionary: UpdateDictionaryBody, otherOptions?: FetcherOptions) => Promise<UpdateDictionaryResult>;
@@ -25,6 +26,7 @@ declare const dictionaryEndpoint: CMSEndpoint<{
25
26
  getDictionariesKeys: (otherOptions?: FetcherOptions) => Promise<GetDictionariesKeysResult>;
26
27
  getDictionariesUpdateTimestamp: (otherOptions?: FetcherOptions) => Promise<GetDictionariesUpdateTimestampResult>;
27
28
  getDictionary: (dictionaryKey: GetDictionaryParams['dictionaryKey'], version?: GetDictionaryQuery['version'], otherOptions?: FetcherOptions) => Promise<GetDictionaryResult>;
29
+ getDictionariesByKeys: (dictionaryKeys: string[], version?: GetDictionaryQuery['version'], otherOptions?: FetcherOptions) => Promise<GetDictionariesByKeysResult>;
28
30
  pushDictionaries: (dictionaries: PushDictionariesBody['dictionaries'], otherOptions?: FetcherOptions) => Promise<PushDictionariesResult>;
29
31
  addDictionary: (body: AddDictionaryBody, otherOptions?: FetcherOptions) => Promise<AddDictionaryResult>;
30
32
  updateDictionary: (dictionary: UpdateDictionaryBody, otherOptions?: FetcherOptions) => Promise<UpdateDictionaryResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"dictionary.d.ts","names":[],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"mappings":";;;;;;cAsBa,mBAAgB,iBACX,gBAAc,iBACb;EAWL,kBAAA,UAAA,uBAAqB,eACjB,mBAAc,QAAA;EAgBmB,sBAAA,eAAA,mBAAc,QAAA;EAc/C,iCAAA,eAAA,mBAAc,QAAA;EAiBb,gBAAA,eAAA,sCAAoC,UACzC,+BAA6B,eACzB,mBAAc,QAAA;EA8Bd,mBAAA,cAAA,sCAAoC,eACpC,mBAAc,QAAA;EAftB,gBAAA,MAAA,mBAAiB,eACT,mBAAc,QAAA;EA+BhB,mBAAA,YAAA,sBAAoB,eAClB,mBAAc,QAAA;EAiBxB,mBAAA,IAAA,uCAAqC,eAC3B,mBAAc,QAAA;;;;;;;;cA6BnB,oBA7BmB;EArHlB,kBAAA,UAAA,uBAAqB,eACjB,mBAAc,QAAA;EAgBmB,sBAAA,eAAA,mBAAc,QAAA;EAc/C,iCAAA,eAAA,mBAAc,QAAA;EAiBb,gBAAA,eAAA,sCAAoC,UACzC,+BAA6B,eACzB,mBAAc,QAAA;EA8Bd,mBAAA,cAAA,sCAAoC,eACpC,mBAAc,QAAA;EAftB,gBAAA,MAAA,mBAAiB,eACT,mBAAc,QAAA;EA+BhB,mBAAA,YAAA,sBAAoB,eAClB,mBAAc,QAAA;EAiBxB,mBAAA,IAAA,uCAAqC,eAC3B,mBAAc,QAAA"}
1
+ {"version":3,"file":"dictionary.d.ts","names":[],"sources":["../../../src/getIntlayerAPI/dictionary.ts"],"mappings":";;;;;;cAuBa,mBAAgB,iBACX,gBAAc,iBACb;EAWL,kBAAA,UAAA,uBAAqB,eACjB,mBAAc,QAAA;EAgBmB,sBAAA,eAAA,mBAAc,QAAA;EAc/C,iCAAA,eAAA,mBAAc,QAAA;EAiBb,gBAAA,eAAA,sCAAoC,UACzC,+BAA6B,eACzB,mBAAc,QAAA;EAoBZ,wBAAA,0BAAQ,UACd,+BAA6B,eACzB,mBAAc,QAAA;EAkCd,mBAAA,cAAA,sCAAoC,eACpC,mBAAc,QAAA;EAftB,gBAAA,MAAA,mBAAiB,eACT,mBAAc,QAAA;EA+BhB,mBAAA,YAAA,sBAAoB,eAClB,mBAAc,QAAA;EAiBxB,mBAAA,IAAA,uCAAqC,eAC3B,mBAAc,QAAA;;;;;;;;cA8BnB,oBA9BmB;EA/IlB,kBAAA,UAAA,uBAAqB,eACjB,mBAAc,QAAA;EAgBmB,sBAAA,eAAA,mBAAc,QAAA;EAc/C,iCAAA,eAAA,mBAAc,QAAA;EAiBb,gBAAA,eAAA,sCAAoC,UACzC,+BAA6B,eACzB,mBAAc,QAAA;EAoBZ,wBAAA,0BAAQ,UACd,+BAA6B,eACzB,mBAAc,QAAA;EAkCd,mBAAA,cAAA,sCAAoC,eACpC,mBAAc,QAAA;EAftB,gBAAA,MAAA,mBAAiB,eACT,mBAAc,QAAA;EA+BhB,mBAAA,YAAA,sBAAoB,eAClB,mBAAc,QAAA;EAiBxB,mBAAA,IAAA,uCAAqC,eAC3B,mBAAc,QAAA"}
@@ -1,4 +1,4 @@
1
- import { FetcherOptions, fetcher, fetcherOptions } from "./fetcher.js";
1
+ import { FetcherError, FetcherOptions, fetcher, fetcherOptions } from "./fetcher.js";
2
2
  import { AuthManager, AuthManagerOptions, BindSectionOptions, createAuthManager } from "./cms/createAuthManager.js";
3
3
  import { CMSEndpoint, IntlayerCMS, IntlayerCMSOptions, createEndpoint, createIntlayerCMS } from "./cms/createIntlayerCMS.js";
4
4
  import "./cms/index.js";
@@ -30,4 +30,4 @@ import { IntlayerAPI, getIntlayerAPI } from "./getIntlayerAPI/index.js";
30
30
  import { IntlayerAPIProxy, getIntlayerAPIProxy } from "./proxy.js";
31
31
  import { AIOptions } from "./types.js";
32
32
  import { AskDocQuestionBody, AskDocQuestionResult, AutocompleteBody, ChatBody, ChatResult, ClientAction, aiEndpoint, getAiAPI } from "./getIntlayerAPI/ai.js";
33
- export { type AIOptions, AskDocQuestionBody, type AskDocQuestionResult, type AuditEvent, AuthManager, AuthManagerOptions, AutocompleteBody, BindSectionOptions, BitbucketAuthCallbackBody, BitbucketAuthCallbackResult, BitbucketCheckConfigBody, BitbucketCheckConfigResult, BitbucketGetAuthUrlResult, BitbucketGetConfigFileBody, BitbucketGetConfigFileResult, BitbucketListReposResult, BitbucketRepository, CMSEndpoint, ChatBody, type ChatResult, ClientAction, DiscoverUrlsParams, DiscoverUrlsResult, FetcherOptions, GetDemoSessionResult, GetRecursiveAuditStatusParams, type GetRecursiveAuditStatusResult, GitHubAuthCallbackBody, GitHubAuthCallbackResult, GitHubCheckConfigBody, GitHubCheckConfigResult, GitHubGetAuthUrlResult, GitHubGetConfigFileBody, GitHubGetConfigFileResult, GitHubGetTokenResult, GitHubListReposResult, GitHubRepository, GitLabAuthCallbackBody, GitLabAuthCallbackResult, GitLabCheckConfigBody, GitLabCheckConfigResult, GitLabGetAuthUrlResult, GitLabGetConfigFileBody, GitLabGetConfigFileResult, GitLabListProjectsResult, GitLabProject, IntlayerAPI, IntlayerAPIProxy, IntlayerCMS, IntlayerCMSOptions, OtherShowcaseProjectsQuery, RecursiveAuditJobParams, ScanUrlBody, ShowcaseProjectsQuery, StartRecursiveAuditBody, type StartRecursiveAuditResult, type TranslateDictionariesBody, type TranslateDictionariesResult, aiEndpoint, analyticsEndpoint, assetEndpoint, auditEndpoint, bitbucketEndpoint, createAuthManager, createEndpoint, createIntlayerCMS, dictionaryEndpoint, editorEndpoint, environmentEndpoint, fetchDistantDictionaries, fetchDistantDictionary, fetcher, fetcherOptions, getAiAPI, getAnalyticsAPI, getAssetAPI, getAuditAPI, getBitbucketAPI, getDictionaryAPI, getEditorAPI, getEnvironmentAPI, getGithubAPI, getGitlabAPI, getIntlayerAPI, getIntlayerAPIProxy, getNewsletterAPI, getOAuthAPI, getOrganizationAPI, getProjectAPI, getReviewerAPI, getSearchAPI, getShowcaseProjectAPI, getStatusAPI, getStripeAPI, getTagAPI, getTranslateAPI, getUserAPI, githubEndpoint, gitlabEndpoint, newsletterEndpoint, organizationEndpoint, projectEndpoint, reviewerEndpoint, searchEndpoint, showcaseProjectEndpoint, statusEndpoint, stripeEndpoint, tagEndpoint, translateEndpoint, userEndpoint };
33
+ export { type AIOptions, AskDocQuestionBody, type AskDocQuestionResult, type AuditEvent, AuthManager, AuthManagerOptions, AutocompleteBody, BindSectionOptions, BitbucketAuthCallbackBody, BitbucketAuthCallbackResult, BitbucketCheckConfigBody, BitbucketCheckConfigResult, BitbucketGetAuthUrlResult, BitbucketGetConfigFileBody, BitbucketGetConfigFileResult, BitbucketListReposResult, BitbucketRepository, CMSEndpoint, ChatBody, type ChatResult, ClientAction, DiscoverUrlsParams, DiscoverUrlsResult, FetcherError, FetcherOptions, GetDemoSessionResult, GetRecursiveAuditStatusParams, type GetRecursiveAuditStatusResult, GitHubAuthCallbackBody, GitHubAuthCallbackResult, GitHubCheckConfigBody, GitHubCheckConfigResult, GitHubGetAuthUrlResult, GitHubGetConfigFileBody, GitHubGetConfigFileResult, GitHubGetTokenResult, GitHubListReposResult, GitHubRepository, GitLabAuthCallbackBody, GitLabAuthCallbackResult, GitLabCheckConfigBody, GitLabCheckConfigResult, GitLabGetAuthUrlResult, GitLabGetConfigFileBody, GitLabGetConfigFileResult, GitLabListProjectsResult, GitLabProject, IntlayerAPI, IntlayerAPIProxy, IntlayerCMS, IntlayerCMSOptions, OtherShowcaseProjectsQuery, RecursiveAuditJobParams, ScanUrlBody, ShowcaseProjectsQuery, StartRecursiveAuditBody, type StartRecursiveAuditResult, type TranslateDictionariesBody, type TranslateDictionariesResult, aiEndpoint, analyticsEndpoint, assetEndpoint, auditEndpoint, bitbucketEndpoint, createAuthManager, createEndpoint, createIntlayerCMS, dictionaryEndpoint, editorEndpoint, environmentEndpoint, fetchDistantDictionaries, fetchDistantDictionary, fetcher, fetcherOptions, getAiAPI, getAnalyticsAPI, getAssetAPI, getAuditAPI, getBitbucketAPI, getDictionaryAPI, getEditorAPI, getEnvironmentAPI, getGithubAPI, getGitlabAPI, getIntlayerAPI, getIntlayerAPIProxy, getNewsletterAPI, getOAuthAPI, getOrganizationAPI, getProjectAPI, getReviewerAPI, getSearchAPI, getShowcaseProjectAPI, getStatusAPI, getStripeAPI, getTagAPI, getTranslateAPI, getUserAPI, githubEndpoint, gitlabEndpoint, newsletterEndpoint, organizationEndpoint, projectEndpoint, reviewerEndpoint, searchEndpoint, showcaseProjectEndpoint, statusEndpoint, stripeEndpoint, tagEndpoint, translateEndpoint, userEndpoint };
@@ -1,6 +1,6 @@
1
1
  import { ResponseData } from "../utils/responseData.js";
2
2
  import { IntlayerConfig } from "@intlayer/types/config";
3
- import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/fastify@5.11.2/node_modules/fastify/fastify.js";
3
+ import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/fastify@5.11.3/node_modules/fastify/fastify.js";
4
4
  //#region ../../intlayer-editor/server/dist/controllers/configuration.controller.d.ts
5
5
  //#region src/controllers/configuration.controller.d.ts
6
6
  type GetConfigurationResult = ResponseData<IntlayerConfig>;
@@ -1,6 +1,6 @@
1
1
  import { ResponseData } from "../utils/responseData.js";
2
2
  import { UnmergedDictionaries } from "../../../../@intlayer/unmerged-dictionaries-entry/dist/types/index.js";
3
- import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/fastify@5.11.2/node_modules/fastify/fastify.js";
3
+ import "/Users/aymericpineau/Documents/intlayer_/node_modules/.bun/fastify@5.11.3/node_modules/fastify/fastify.js";
4
4
  import { DictionaryStatus } from "@intlayer/engine/build";
5
5
  import { Dictionary } from "@intlayer/types/dictionary";
6
6
  //#region ../../intlayer-editor/server/dist/controllers/dictionary.controller.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/api",
3
- "version": "9.2.0",
3
+ "version": "9.3.1",
4
4
  "private": false,
5
5
  "description": "SDK for interacting with the Intlayer API, enabling content auditing, and managing organizations, projects, and users.",
6
6
  "keywords": [
@@ -256,12 +256,12 @@
256
256
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
257
257
  },
258
258
  "dependencies": {
259
- "@intlayer/config": "9.2.0",
260
- "@intlayer/types": "9.2.0",
259
+ "@intlayer/config": "9.3.1",
260
+ "@intlayer/types": "9.3.1",
261
261
  "defu": "6.1.7"
262
262
  },
263
263
  "devDependencies": {
264
- "@types/node": "26.1.2",
264
+ "@types/node": "26.2.0",
265
265
  "@utils/ts-config": "1.0.4",
266
266
  "@utils/ts-config-types": "1.0.4",
267
267
  "@utils/tsdown-config": "1.0.4",