@storyblok/management-api-client 0.2.3 → 0.2.5
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/dist/index.cjs +2 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2 -7
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.cts +4 -4
- package/dist/types.d.mts +4 -4
- package/dist/utils/rate-limit.cjs +15 -74
- package/dist/utils/rate-limit.cjs.map +1 -1
- package/dist/utils/rate-limit.d.cts +5 -6
- package/dist/utils/rate-limit.d.mts +5 -6
- package/dist/utils/rate-limit.mjs +15 -74
- package/dist/utils/rate-limit.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -61,16 +61,11 @@ const createManagementApiClient = (config) => {
|
|
|
61
61
|
data: error
|
|
62
62
|
}));
|
|
63
63
|
/**
|
|
64
|
-
* Wraps an SDK call with throttling
|
|
65
|
-
* The throttle slot is held for the entire duration of the request.
|
|
64
|
+
* Wraps an SDK call with throttling.
|
|
66
65
|
* When throwOnError is true, errors throw and data is guaranteed non-null.
|
|
67
66
|
*/
|
|
68
67
|
function wrapRequest(fn, _throwOnError) {
|
|
69
|
-
return throttleManager.execute(
|
|
70
|
-
const result = await fn();
|
|
71
|
-
throttleManager.adaptToResponse(result.response);
|
|
72
|
-
return result;
|
|
73
|
-
});
|
|
68
|
+
return throttleManager.execute(() => fn());
|
|
74
69
|
}
|
|
75
70
|
const deps = {
|
|
76
71
|
client,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["createThrottleManager","createClient","createConfig","ClientError","createAssetFoldersResource","createAssetsResource","createComponentFoldersResource","createComponentsResource","createDatasourceEntriesResource","createDatasourcesResource","createInternalTagsResource","createPresetsResource","createSpacesResource","createStoriesResource","createUsersResource"],"sources":["../src/index.ts"],"sourcesContent":["import type { Client, ResolvedRequestOptions } from './generated/shared/client';\nimport type { Middleware } from './generated/shared/client/utils.gen';\nimport { createClient, createConfig } from './generated/shared/client';\nimport { getManagementBaseUrl } from '@storyblok/region-helper';\nimport { ClientError } from './error';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { createAssetFoldersResource } from './resources/asset-folders';\nimport { createAssetsResource } from './resources/assets';\nimport { createComponentFoldersResource } from './resources/component-folders';\nimport { createComponentsResource } from './resources/components';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createInternalTagsResource } from './resources/internal-tags';\nimport { createPresetsResource } from './resources/presets';\nimport { createSpacesResource } from './resources/spaces';\nimport { createStoriesResource } from './resources/stories';\nimport { createUsersResource } from './resources/users';\nimport type {\n ApiResponse,\n HttpRequestOptions,\n ManagementApiClientConfig,\n MapiResourceDeps,\n} from './types';\n\nexport { ClientError } from './error';\n\nfunction getAuthorizationHeader(config: ManagementApiClientConfig): string | undefined {\n if (config.personalAccessToken) {\n return config.personalAccessToken;\n }\n if (config.oauthToken) {\n return `Bearer ${config.oauthToken.replace(/^Bearer\\s+/i, '')}`;\n }\n return undefined;\n}\n\nexport const createManagementApiClient = (config: ManagementApiClientConfig) => {\n const {\n spaceId,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n retry = {\n limit: 12,\n backoffLimit: 20_000,\n methods: ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'],\n statusCodes: [429],\n },\n timeout = 30_000,\n rateLimit,\n } = config;\n\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const authHeader = getAuthorizationHeader(config);\n\n const client: Client = createClient(\n createConfig({\n baseUrl: baseUrl || getManagementBaseUrl(region),\n headers: {\n ...(authHeader ? { Authorization: authHeader } : {}),\n ...headers,\n },\n throwOnError,\n kyOptions: {\n throwHttpErrors: true,\n timeout,\n retry,\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n /**\n * Wraps an SDK call with throttling and response adaptation.\n * The throttle slot is held for the entire duration of the request.\n * When throwOnError is true, errors throw and data is guaranteed non-null.\n */\n function wrapRequest<TData, ThrowOnError extends boolean = false>(\n fn: () => Promise<unknown>,\n _throwOnError?: ThrowOnError,\n ): Promise<ApiResponse<TData, ThrowOnError>> {\n return throttleManager.execute(async () => {\n const result = await fn() as ApiResponse<TData, ThrowOnError>;\n throttleManager.adaptToResponse((result as { response: Response }).response);\n return result;\n }) as Promise<ApiResponse<TData, ThrowOnError>>;\n }\n\n const deps: MapiResourceDeps = { client, spaceId, wrapRequest };\n\n /**\n * Escape hatch: send a GET request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpGet = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.get({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a POST request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPost = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.post({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PUT request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPut = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.put({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PATCH request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPatch = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.patch({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a DELETE request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpDelete = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.delete({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n return {\n assetFolders: createAssetFoldersResource(deps),\n assets: createAssetsResource(deps),\n componentFolders: createComponentFoldersResource(deps),\n components: createComponentsResource(deps),\n datasourceEntries: createDatasourceEntriesResource(deps),\n datasources: createDatasourcesResource(deps),\n delete: httpDelete,\n get: httpGet,\n patch: httpPatch,\n interceptors: client.interceptors as Middleware<Request, Response, unknown, ResolvedRequestOptions>,\n internalTags: createInternalTagsResource(deps),\n post: httpPost,\n presets: createPresetsResource(deps),\n put: httpPut,\n spaces: createSpacesResource(deps),\n stories: createStoriesResource(deps),\n users: createUsersResource({ client, wrapRequest }),\n };\n};\n\nexport type ManagementApiClient = ReturnType<typeof createManagementApiClient>;\n\nexport type {\n ApiResponse,\n Asset,\n AssetCreate,\n AssetField,\n AssetFolder,\n AssetFolderCreate,\n AssetFolderUpdate,\n AssetListQuery,\n AssetSignRequest,\n AssetUpdate,\n AssetUpdateRequest,\n AssetUploadRequest,\n Component,\n ComponentCreate,\n ComponentFolder,\n ComponentSchemaField,\n ComponentUpdate,\n Datasource,\n DatasourceCreate,\n DatasourceEntry,\n DatasourceEntryCreate,\n DatasourceEntryUpdate,\n DatasourceUpdate,\n FetchOptions,\n HttpRequestOptions,\n InternalTag,\n ManagementApiClientConfig,\n MapiResourceDeps,\n MultilinkField,\n PluginField,\n Preset,\n RateLimitConfig,\n RequestConfigOverrides,\n RichtextField,\n SignedResponseObject,\n Space,\n SpaceCreate,\n SpaceUpdate,\n Story,\n StoryAlternate,\n StoryContent,\n StoryCreate,\n StoryListQuery,\n StoryLocalizedPath,\n StoryTranslatedSlug,\n StoryUpdate,\n TableField,\n User,\n} from './types';\nexport { normalizeAssetUrl } from './utils/normalize-asset-url';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["createThrottleManager","createClient","createConfig","ClientError","createAssetFoldersResource","createAssetsResource","createComponentFoldersResource","createComponentsResource","createDatasourceEntriesResource","createDatasourcesResource","createInternalTagsResource","createPresetsResource","createSpacesResource","createStoriesResource","createUsersResource"],"sources":["../src/index.ts"],"sourcesContent":["import type { Client, ResolvedRequestOptions } from './generated/shared/client';\nimport type { Middleware } from './generated/shared/client/utils.gen';\nimport { createClient, createConfig } from './generated/shared/client';\nimport { getManagementBaseUrl } from '@storyblok/region-helper';\nimport { ClientError } from './error';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { createAssetFoldersResource } from './resources/asset-folders';\nimport { createAssetsResource } from './resources/assets';\nimport { createComponentFoldersResource } from './resources/component-folders';\nimport { createComponentsResource } from './resources/components';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createInternalTagsResource } from './resources/internal-tags';\nimport { createPresetsResource } from './resources/presets';\nimport { createSpacesResource } from './resources/spaces';\nimport { createStoriesResource } from './resources/stories';\nimport { createUsersResource } from './resources/users';\nimport type {\n ApiResponse,\n HttpRequestOptions,\n ManagementApiClientConfig,\n MapiResourceDeps,\n} from './types';\n\nexport { ClientError } from './error';\n\nfunction getAuthorizationHeader(config: ManagementApiClientConfig): string | undefined {\n if (config.personalAccessToken) {\n return config.personalAccessToken;\n }\n if (config.oauthToken) {\n return `Bearer ${config.oauthToken.replace(/^Bearer\\s+/i, '')}`;\n }\n return undefined;\n}\n\nexport const createManagementApiClient = (config: ManagementApiClientConfig) => {\n const {\n spaceId,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n retry = {\n limit: 12,\n backoffLimit: 20_000,\n methods: ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'],\n statusCodes: [429],\n },\n timeout = 30_000,\n rateLimit,\n } = config;\n\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const authHeader = getAuthorizationHeader(config);\n\n const client: Client = createClient(\n createConfig({\n baseUrl: baseUrl || getManagementBaseUrl(region),\n headers: {\n ...(authHeader ? { Authorization: authHeader } : {}),\n ...headers,\n },\n throwOnError,\n kyOptions: {\n throwHttpErrors: true,\n timeout,\n retry,\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n /**\n * Wraps an SDK call with throttling.\n * When throwOnError is true, errors throw and data is guaranteed non-null.\n */\n function wrapRequest<TData, ThrowOnError extends boolean = false>(\n fn: () => Promise<unknown>,\n _throwOnError?: ThrowOnError,\n ): Promise<ApiResponse<TData, ThrowOnError>> {\n return throttleManager.execute(\n () => fn() as Promise<ApiResponse<TData, ThrowOnError>>,\n );\n }\n\n const deps: MapiResourceDeps = { client, spaceId, wrapRequest };\n\n /**\n * Escape hatch: send a GET request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpGet = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.get({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a POST request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPost = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.post({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PUT request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPut = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.put({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PATCH request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPatch = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.patch({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a DELETE request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpDelete = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.delete({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n return {\n assetFolders: createAssetFoldersResource(deps),\n assets: createAssetsResource(deps),\n componentFolders: createComponentFoldersResource(deps),\n components: createComponentsResource(deps),\n datasourceEntries: createDatasourceEntriesResource(deps),\n datasources: createDatasourcesResource(deps),\n delete: httpDelete,\n get: httpGet,\n patch: httpPatch,\n interceptors: client.interceptors as Middleware<Request, Response, unknown, ResolvedRequestOptions>,\n internalTags: createInternalTagsResource(deps),\n post: httpPost,\n presets: createPresetsResource(deps),\n put: httpPut,\n spaces: createSpacesResource(deps),\n stories: createStoriesResource(deps),\n users: createUsersResource({ client, wrapRequest }),\n };\n};\n\nexport type ManagementApiClient = ReturnType<typeof createManagementApiClient>;\n\nexport type {\n ApiResponse,\n Asset,\n AssetCreate,\n AssetField,\n AssetFolder,\n AssetFolderCreate,\n AssetFolderUpdate,\n AssetListQuery,\n AssetSignRequest,\n AssetUpdate,\n AssetUpdateRequest,\n AssetUploadRequest,\n Component,\n ComponentCreate,\n ComponentFolder,\n ComponentSchemaField,\n ComponentUpdate,\n Datasource,\n DatasourceCreate,\n DatasourceEntry,\n DatasourceEntryCreate,\n DatasourceEntryUpdate,\n DatasourceUpdate,\n FetchOptions,\n HttpRequestOptions,\n InternalTag,\n ManagementApiClientConfig,\n MapiResourceDeps,\n MultilinkField,\n PluginField,\n Preset,\n RateLimitConfig,\n RequestConfigOverrides,\n RichtextField,\n SignedResponseObject,\n Space,\n SpaceCreate,\n SpaceUpdate,\n Story,\n StoryAlternate,\n StoryContent,\n StoryCreate,\n StoryListQuery,\n StoryLocalizedPath,\n StoryTranslatedSlug,\n StoryUpdate,\n TableField,\n User,\n} from './types';\nexport { normalizeAssetUrl } from './utils/normalize-asset-url';\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -59,16 +59,11 @@ const createManagementApiClient = (config) => {
|
|
|
59
59
|
data: error
|
|
60
60
|
}));
|
|
61
61
|
/**
|
|
62
|
-
* Wraps an SDK call with throttling
|
|
63
|
-
* The throttle slot is held for the entire duration of the request.
|
|
62
|
+
* Wraps an SDK call with throttling.
|
|
64
63
|
* When throwOnError is true, errors throw and data is guaranteed non-null.
|
|
65
64
|
*/
|
|
66
65
|
function wrapRequest(fn, _throwOnError) {
|
|
67
|
-
return throttleManager.execute(
|
|
68
|
-
const result = await fn();
|
|
69
|
-
throttleManager.adaptToResponse(result.response);
|
|
70
|
-
return result;
|
|
71
|
-
});
|
|
66
|
+
return throttleManager.execute(() => fn());
|
|
72
67
|
}
|
|
73
68
|
const deps = {
|
|
74
69
|
client,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Client, ResolvedRequestOptions } from './generated/shared/client';\nimport type { Middleware } from './generated/shared/client/utils.gen';\nimport { createClient, createConfig } from './generated/shared/client';\nimport { getManagementBaseUrl } from '@storyblok/region-helper';\nimport { ClientError } from './error';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { createAssetFoldersResource } from './resources/asset-folders';\nimport { createAssetsResource } from './resources/assets';\nimport { createComponentFoldersResource } from './resources/component-folders';\nimport { createComponentsResource } from './resources/components';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createInternalTagsResource } from './resources/internal-tags';\nimport { createPresetsResource } from './resources/presets';\nimport { createSpacesResource } from './resources/spaces';\nimport { createStoriesResource } from './resources/stories';\nimport { createUsersResource } from './resources/users';\nimport type {\n ApiResponse,\n HttpRequestOptions,\n ManagementApiClientConfig,\n MapiResourceDeps,\n} from './types';\n\nexport { ClientError } from './error';\n\nfunction getAuthorizationHeader(config: ManagementApiClientConfig): string | undefined {\n if (config.personalAccessToken) {\n return config.personalAccessToken;\n }\n if (config.oauthToken) {\n return `Bearer ${config.oauthToken.replace(/^Bearer\\s+/i, '')}`;\n }\n return undefined;\n}\n\nexport const createManagementApiClient = (config: ManagementApiClientConfig) => {\n const {\n spaceId,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n retry = {\n limit: 12,\n backoffLimit: 20_000,\n methods: ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'],\n statusCodes: [429],\n },\n timeout = 30_000,\n rateLimit,\n } = config;\n\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const authHeader = getAuthorizationHeader(config);\n\n const client: Client = createClient(\n createConfig({\n baseUrl: baseUrl || getManagementBaseUrl(region),\n headers: {\n ...(authHeader ? { Authorization: authHeader } : {}),\n ...headers,\n },\n throwOnError,\n kyOptions: {\n throwHttpErrors: true,\n timeout,\n retry,\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n /**\n * Wraps an SDK call with throttling and response adaptation.\n * The throttle slot is held for the entire duration of the request.\n * When throwOnError is true, errors throw and data is guaranteed non-null.\n */\n function wrapRequest<TData, ThrowOnError extends boolean = false>(\n fn: () => Promise<unknown>,\n _throwOnError?: ThrowOnError,\n ): Promise<ApiResponse<TData, ThrowOnError>> {\n return throttleManager.execute(async () => {\n const result = await fn() as ApiResponse<TData, ThrowOnError>;\n throttleManager.adaptToResponse((result as { response: Response }).response);\n return result;\n }) as Promise<ApiResponse<TData, ThrowOnError>>;\n }\n\n const deps: MapiResourceDeps = { client, spaceId, wrapRequest };\n\n /**\n * Escape hatch: send a GET request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpGet = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.get({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a POST request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPost = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.post({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PUT request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPut = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.put({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PATCH request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPatch = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.patch({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a DELETE request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpDelete = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.delete({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n return {\n assetFolders: createAssetFoldersResource(deps),\n assets: createAssetsResource(deps),\n componentFolders: createComponentFoldersResource(deps),\n components: createComponentsResource(deps),\n datasourceEntries: createDatasourceEntriesResource(deps),\n datasources: createDatasourcesResource(deps),\n delete: httpDelete,\n get: httpGet,\n patch: httpPatch,\n interceptors: client.interceptors as Middleware<Request, Response, unknown, ResolvedRequestOptions>,\n internalTags: createInternalTagsResource(deps),\n post: httpPost,\n presets: createPresetsResource(deps),\n put: httpPut,\n spaces: createSpacesResource(deps),\n stories: createStoriesResource(deps),\n users: createUsersResource({ client, wrapRequest }),\n };\n};\n\nexport type ManagementApiClient = ReturnType<typeof createManagementApiClient>;\n\nexport type {\n ApiResponse,\n Asset,\n AssetCreate,\n AssetField,\n AssetFolder,\n AssetFolderCreate,\n AssetFolderUpdate,\n AssetListQuery,\n AssetSignRequest,\n AssetUpdate,\n AssetUpdateRequest,\n AssetUploadRequest,\n Component,\n ComponentCreate,\n ComponentFolder,\n ComponentSchemaField,\n ComponentUpdate,\n Datasource,\n DatasourceCreate,\n DatasourceEntry,\n DatasourceEntryCreate,\n DatasourceEntryUpdate,\n DatasourceUpdate,\n FetchOptions,\n HttpRequestOptions,\n InternalTag,\n ManagementApiClientConfig,\n MapiResourceDeps,\n MultilinkField,\n PluginField,\n Preset,\n RateLimitConfig,\n RequestConfigOverrides,\n RichtextField,\n SignedResponseObject,\n Space,\n SpaceCreate,\n SpaceUpdate,\n Story,\n StoryAlternate,\n StoryContent,\n StoryCreate,\n StoryListQuery,\n StoryLocalizedPath,\n StoryTranslatedSlug,\n StoryUpdate,\n TableField,\n User,\n} from './types';\nexport { normalizeAssetUrl } from './utils/normalize-asset-url';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Client, ResolvedRequestOptions } from './generated/shared/client';\nimport type { Middleware } from './generated/shared/client/utils.gen';\nimport { createClient, createConfig } from './generated/shared/client';\nimport { getManagementBaseUrl } from '@storyblok/region-helper';\nimport { ClientError } from './error';\nimport { createThrottleManager } from './utils/rate-limit';\nimport { createAssetFoldersResource } from './resources/asset-folders';\nimport { createAssetsResource } from './resources/assets';\nimport { createComponentFoldersResource } from './resources/component-folders';\nimport { createComponentsResource } from './resources/components';\nimport { createDatasourceEntriesResource } from './resources/datasource-entries';\nimport { createDatasourcesResource } from './resources/datasources';\nimport { createInternalTagsResource } from './resources/internal-tags';\nimport { createPresetsResource } from './resources/presets';\nimport { createSpacesResource } from './resources/spaces';\nimport { createStoriesResource } from './resources/stories';\nimport { createUsersResource } from './resources/users';\nimport type {\n ApiResponse,\n HttpRequestOptions,\n ManagementApiClientConfig,\n MapiResourceDeps,\n} from './types';\n\nexport { ClientError } from './error';\n\nfunction getAuthorizationHeader(config: ManagementApiClientConfig): string | undefined {\n if (config.personalAccessToken) {\n return config.personalAccessToken;\n }\n if (config.oauthToken) {\n return `Bearer ${config.oauthToken.replace(/^Bearer\\s+/i, '')}`;\n }\n return undefined;\n}\n\nexport const createManagementApiClient = (config: ManagementApiClientConfig) => {\n const {\n spaceId,\n region = 'eu',\n baseUrl,\n headers = {},\n throwOnError = false,\n retry = {\n limit: 12,\n backoffLimit: 20_000,\n methods: ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'],\n statusCodes: [429],\n },\n timeout = 30_000,\n rateLimit,\n } = config;\n\n const throttleManager = createThrottleManager(rateLimit ?? {});\n const authHeader = getAuthorizationHeader(config);\n\n const client: Client = createClient(\n createConfig({\n baseUrl: baseUrl || getManagementBaseUrl(region),\n headers: {\n ...(authHeader ? { Authorization: authHeader } : {}),\n ...headers,\n },\n throwOnError,\n kyOptions: {\n throwHttpErrors: true,\n timeout,\n retry,\n },\n }),\n );\n\n client.interceptors.error.use(\n (error: unknown, response: Response) =>\n new ClientError(response?.statusText || 'API request failed', {\n status: response?.status ?? 0,\n statusText: response?.statusText ?? '',\n data: error,\n }),\n );\n\n /**\n * Wraps an SDK call with throttling.\n * When throwOnError is true, errors throw and data is guaranteed non-null.\n */\n function wrapRequest<TData, ThrowOnError extends boolean = false>(\n fn: () => Promise<unknown>,\n _throwOnError?: ThrowOnError,\n ): Promise<ApiResponse<TData, ThrowOnError>> {\n return throttleManager.execute(\n () => fn() as Promise<ApiResponse<TData, ThrowOnError>>,\n );\n }\n\n const deps: MapiResourceDeps = { client, spaceId, wrapRequest };\n\n /**\n * Escape hatch: send a GET request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpGet = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.get({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a POST request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPost = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.post({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PUT request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPut = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.put({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a PATCH request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpPatch = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.patch({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n /**\n * Escape hatch: send a DELETE request to any MAPI endpoint not yet wrapped\n * in a dedicated resource method.\n */\n const httpDelete = <TData = unknown>(\n path: string,\n options: HttpRequestOptions = {},\n ): Promise<ApiResponse<TData>> => {\n const { fetchOptions, ...rest } = options;\n return wrapRequest<TData>(() =>\n client.delete({ url: path, ...rest, ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }),\n );\n };\n\n return {\n assetFolders: createAssetFoldersResource(deps),\n assets: createAssetsResource(deps),\n componentFolders: createComponentFoldersResource(deps),\n components: createComponentsResource(deps),\n datasourceEntries: createDatasourceEntriesResource(deps),\n datasources: createDatasourcesResource(deps),\n delete: httpDelete,\n get: httpGet,\n patch: httpPatch,\n interceptors: client.interceptors as Middleware<Request, Response, unknown, ResolvedRequestOptions>,\n internalTags: createInternalTagsResource(deps),\n post: httpPost,\n presets: createPresetsResource(deps),\n put: httpPut,\n spaces: createSpacesResource(deps),\n stories: createStoriesResource(deps),\n users: createUsersResource({ client, wrapRequest }),\n };\n};\n\nexport type ManagementApiClient = ReturnType<typeof createManagementApiClient>;\n\nexport type {\n ApiResponse,\n Asset,\n AssetCreate,\n AssetField,\n AssetFolder,\n AssetFolderCreate,\n AssetFolderUpdate,\n AssetListQuery,\n AssetSignRequest,\n AssetUpdate,\n AssetUpdateRequest,\n AssetUploadRequest,\n Component,\n ComponentCreate,\n ComponentFolder,\n ComponentSchemaField,\n ComponentUpdate,\n Datasource,\n DatasourceCreate,\n DatasourceEntry,\n DatasourceEntryCreate,\n DatasourceEntryUpdate,\n DatasourceUpdate,\n FetchOptions,\n HttpRequestOptions,\n InternalTag,\n ManagementApiClientConfig,\n MapiResourceDeps,\n MultilinkField,\n PluginField,\n Preset,\n RateLimitConfig,\n RequestConfigOverrides,\n RichtextField,\n SignedResponseObject,\n Space,\n SpaceCreate,\n SpaceUpdate,\n Story,\n StoryAlternate,\n StoryContent,\n StoryCreate,\n StoryListQuery,\n StoryLocalizedPath,\n StoryTranslatedSlug,\n StoryUpdate,\n TableField,\n User,\n} from './types';\nexport { normalizeAssetUrl } from './utils/normalize-asset-url';\n"],"mappings":"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"}
|
package/dist/types.d.cts
CHANGED
|
@@ -113,11 +113,11 @@ interface ManagementApiClientConfig {
|
|
|
113
113
|
*/
|
|
114
114
|
timeout?: number;
|
|
115
115
|
/**
|
|
116
|
-
*
|
|
116
|
+
* Rate limiting to avoid hitting the Storyblok Management API throttle (6 req/s paid, 3 req/s free).
|
|
117
117
|
*
|
|
118
|
-
* - `undefined` (default):
|
|
119
|
-
* - `number`:
|
|
120
|
-
* - `{
|
|
118
|
+
* - `undefined` (default): 6 requests per second.
|
|
119
|
+
* - `number`: N requests per second.
|
|
120
|
+
* - `{ requestsPerSecond?: number }`: full config object.
|
|
121
121
|
* - `false`: disable rate limiting entirely.
|
|
122
122
|
*/
|
|
123
123
|
rateLimit?: RateLimitConfig | number | false;
|
package/dist/types.d.mts
CHANGED
|
@@ -113,11 +113,11 @@ interface ManagementApiClientConfig {
|
|
|
113
113
|
*/
|
|
114
114
|
timeout?: number;
|
|
115
115
|
/**
|
|
116
|
-
*
|
|
116
|
+
* Rate limiting to avoid hitting the Storyblok Management API throttle (6 req/s paid, 3 req/s free).
|
|
117
117
|
*
|
|
118
|
-
* - `undefined` (default):
|
|
119
|
-
* - `number`:
|
|
120
|
-
* - `{
|
|
118
|
+
* - `undefined` (default): 6 requests per second.
|
|
119
|
+
* - `number`: N requests per second.
|
|
120
|
+
* - `{ requestsPerSecond?: number }`: full config object.
|
|
121
121
|
* - `false`: disable rate limiting entirely.
|
|
122
122
|
*/
|
|
123
123
|
rateLimit?: RateLimitConfig | number | false;
|
|
@@ -1,85 +1,26 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
let async_sema = require("async-sema");
|
|
1
3
|
|
|
2
4
|
//#region src/utils/rate-limit.ts
|
|
3
|
-
const
|
|
5
|
+
const DEFAULT_REQUESTS_PER_SECOND = 6;
|
|
4
6
|
const MAX_RATE_LIMIT = 1e3;
|
|
5
7
|
/**
|
|
6
|
-
* Concurrency limiter: allows up to `initialLimit` requests to be in-flight
|
|
7
|
-
* at the same time. A slot is freed as soon as the request's promise settles
|
|
8
|
-
* (resolves or rejects), so throughput scales with how quickly requests
|
|
9
|
-
* complete rather than being artificially capped at N per second.
|
|
10
|
-
*/
|
|
11
|
-
function createThrottle(initialLimit) {
|
|
12
|
-
let limit = initialLimit;
|
|
13
|
-
let activeCount = 0;
|
|
14
|
-
const queue = [];
|
|
15
|
-
const tryNext = () => {
|
|
16
|
-
while (queue.length > 0 && activeCount < limit) {
|
|
17
|
-
activeCount++;
|
|
18
|
-
queue.shift()();
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
const execute = (fn) => {
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
queue.push(() => {
|
|
24
|
-
fn().then((value) => {
|
|
25
|
-
activeCount--;
|
|
26
|
-
tryNext();
|
|
27
|
-
resolve(value);
|
|
28
|
-
}, (error) => {
|
|
29
|
-
activeCount--;
|
|
30
|
-
tryNext();
|
|
31
|
-
reject(error);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
tryNext();
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
const setLimit = (n) => {
|
|
38
|
-
limit = n;
|
|
39
|
-
tryNext();
|
|
40
|
-
};
|
|
41
|
-
return {
|
|
42
|
-
execute,
|
|
43
|
-
setLimit
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Extracts the quota (`q=`) value from the `X-RateLimit-Policy` response header.
|
|
48
|
-
* Returns `undefined` if the header is absent or unparseable.
|
|
49
|
-
*
|
|
50
|
-
* Example header: `"concurrent-requests";q=30`
|
|
51
|
-
*/
|
|
52
|
-
function parseRateLimitPolicyHeader(response) {
|
|
53
|
-
const policy = response.headers.get("x-ratelimit-policy");
|
|
54
|
-
if (!policy) return;
|
|
55
|
-
const match = policy.match(/q=(\d+)/);
|
|
56
|
-
if (!match) return;
|
|
57
|
-
return Math.min(Number.parseInt(match[1], 10), MAX_RATE_LIMIT);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
8
|
* Creates a `ThrottleManager` from the user-supplied `rateLimit` config.
|
|
61
9
|
*
|
|
62
|
-
* - `false`
|
|
63
|
-
* - `number`
|
|
64
|
-
* - `{
|
|
65
|
-
* - `{}` / `undefined` (default)->
|
|
10
|
+
* - `false` -> no throttling (passthrough)
|
|
11
|
+
* - `number` -> N requests per second
|
|
12
|
+
* - `{ requestsPerSecond: n }` -> N requests per second
|
|
13
|
+
* - `{}` / `undefined` (default) -> DEFAULT_REQUESTS_PER_SECOND per second
|
|
66
14
|
*/
|
|
67
15
|
function createThrottleManager(config) {
|
|
68
|
-
if (config === false) return {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
execute: (fn) => throttle.execute(fn),
|
|
77
|
-
adaptToResponse: (response) => {
|
|
78
|
-
if (!adaptToServerHeaders || response === void 0) return;
|
|
79
|
-
const serverLimit = parseRateLimitPolicyHeader(response);
|
|
80
|
-
if (serverLimit !== void 0) throttle.setLimit(Math.min(cappedLimit, serverLimit));
|
|
81
|
-
}
|
|
82
|
-
};
|
|
16
|
+
if (config === false) return { execute: (fn) => fn() };
|
|
17
|
+
const { requestsPerSecond, maxConcurrency } = typeof config === "number" ? { requestsPerSecond: config } : config;
|
|
18
|
+
const rps = requestsPerSecond ?? maxConcurrency ?? DEFAULT_REQUESTS_PER_SECOND;
|
|
19
|
+
const rl = (0, async_sema.RateLimit)(Math.min(rps, MAX_RATE_LIMIT));
|
|
20
|
+
return { execute: async (fn) => {
|
|
21
|
+
await rl();
|
|
22
|
+
return fn();
|
|
23
|
+
} };
|
|
83
24
|
}
|
|
84
25
|
|
|
85
26
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.cjs","names":[],"sources":["../../src/utils/rate-limit.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"rate-limit.cjs","names":[],"sources":["../../src/utils/rate-limit.ts"],"sourcesContent":["import { RateLimit } from 'async-sema';\n\nconst DEFAULT_REQUESTS_PER_SECOND = 6;\nconst MAX_RATE_LIMIT = 1_000;\n\nexport interface RateLimitConfig {\n /**\n * Maximum number of MAPI requests to start per second.\n * Defaults to 6. Capped at 1000.\n */\n requestsPerSecond?: number;\n /**\n * @deprecated Use `requestsPerSecond` instead.\n * @todo(next-major): Remove this field.\n */\n maxConcurrency?: number;\n}\n\nexport interface ThrottleManager {\n execute: <T>(fn: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Creates a `ThrottleManager` from the user-supplied `rateLimit` config.\n *\n * - `false` -> no throttling (passthrough)\n * - `number` -> N requests per second\n * - `{ requestsPerSecond: n }` -> N requests per second\n * - `{}` / `undefined` (default) -> DEFAULT_REQUESTS_PER_SECOND per second\n */\nexport function createThrottleManager(config: RateLimitConfig | number | false): ThrottleManager {\n if (config === false) {\n return { execute: fn => fn() };\n }\n\n const resolvedConfig: RateLimitConfig = typeof config === 'number' ? { requestsPerSecond: config } : config;\n const { requestsPerSecond, maxConcurrency } = resolvedConfig;\n const rps = requestsPerSecond ?? maxConcurrency ?? DEFAULT_REQUESTS_PER_SECOND;\n const rl = RateLimit(Math.min(rps, MAX_RATE_LIMIT));\n\n return {\n execute: async (fn) => {\n await rl();\n return fn();\n },\n };\n}\n"],"mappings":";;;;AAEA,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;;;;;;;;;AA2BvB,SAAgB,sBAAsB,QAA2D;AAC/F,KAAI,WAAW,MACb,QAAO,EAAE,UAAS,OAAM,IAAI,EAAE;CAIhC,MAAM,EAAE,mBAAmB,mBADa,OAAO,WAAW,WAAW,EAAE,mBAAmB,QAAQ,GAAG;CAErG,MAAM,MAAM,qBAAqB,kBAAkB;CACnD,MAAM,+BAAe,KAAK,IAAI,KAAK,eAAe,CAAC;AAEnD,QAAO,EACL,SAAS,OAAO,OAAO;AACrB,QAAM,IAAI;AACV,SAAO,IAAI;IAEd"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
//#region src/utils/rate-limit.d.ts
|
|
2
2
|
interface RateLimitConfig {
|
|
3
3
|
/**
|
|
4
|
-
* Maximum number of
|
|
4
|
+
* Maximum number of MAPI requests to start per second.
|
|
5
5
|
* Defaults to 6. Capped at 1000.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
requestsPerSecond?: number;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @default true
|
|
9
|
+
* @deprecated Use `requestsPerSecond` instead.
|
|
10
|
+
* @todo(next-major): Remove this field.
|
|
12
11
|
*/
|
|
13
|
-
|
|
12
|
+
maxConcurrency?: number;
|
|
14
13
|
}
|
|
15
14
|
//#endregion
|
|
16
15
|
export { RateLimitConfig };
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
//#region src/utils/rate-limit.d.ts
|
|
2
2
|
interface RateLimitConfig {
|
|
3
3
|
/**
|
|
4
|
-
* Maximum number of
|
|
4
|
+
* Maximum number of MAPI requests to start per second.
|
|
5
5
|
* Defaults to 6. Capped at 1000.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
requestsPerSecond?: number;
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @default true
|
|
9
|
+
* @deprecated Use `requestsPerSecond` instead.
|
|
10
|
+
* @todo(next-major): Remove this field.
|
|
12
11
|
*/
|
|
13
|
-
|
|
12
|
+
maxConcurrency?: number;
|
|
14
13
|
}
|
|
15
14
|
//#endregion
|
|
16
15
|
export { RateLimitConfig };
|
|
@@ -1,84 +1,25 @@
|
|
|
1
|
+
import { RateLimit } from "async-sema";
|
|
2
|
+
|
|
1
3
|
//#region src/utils/rate-limit.ts
|
|
2
|
-
const
|
|
4
|
+
const DEFAULT_REQUESTS_PER_SECOND = 6;
|
|
3
5
|
const MAX_RATE_LIMIT = 1e3;
|
|
4
6
|
/**
|
|
5
|
-
* Concurrency limiter: allows up to `initialLimit` requests to be in-flight
|
|
6
|
-
* at the same time. A slot is freed as soon as the request's promise settles
|
|
7
|
-
* (resolves or rejects), so throughput scales with how quickly requests
|
|
8
|
-
* complete rather than being artificially capped at N per second.
|
|
9
|
-
*/
|
|
10
|
-
function createThrottle(initialLimit) {
|
|
11
|
-
let limit = initialLimit;
|
|
12
|
-
let activeCount = 0;
|
|
13
|
-
const queue = [];
|
|
14
|
-
const tryNext = () => {
|
|
15
|
-
while (queue.length > 0 && activeCount < limit) {
|
|
16
|
-
activeCount++;
|
|
17
|
-
queue.shift()();
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
const execute = (fn) => {
|
|
21
|
-
return new Promise((resolve, reject) => {
|
|
22
|
-
queue.push(() => {
|
|
23
|
-
fn().then((value) => {
|
|
24
|
-
activeCount--;
|
|
25
|
-
tryNext();
|
|
26
|
-
resolve(value);
|
|
27
|
-
}, (error) => {
|
|
28
|
-
activeCount--;
|
|
29
|
-
tryNext();
|
|
30
|
-
reject(error);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
tryNext();
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
const setLimit = (n) => {
|
|
37
|
-
limit = n;
|
|
38
|
-
tryNext();
|
|
39
|
-
};
|
|
40
|
-
return {
|
|
41
|
-
execute,
|
|
42
|
-
setLimit
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Extracts the quota (`q=`) value from the `X-RateLimit-Policy` response header.
|
|
47
|
-
* Returns `undefined` if the header is absent or unparseable.
|
|
48
|
-
*
|
|
49
|
-
* Example header: `"concurrent-requests";q=30`
|
|
50
|
-
*/
|
|
51
|
-
function parseRateLimitPolicyHeader(response) {
|
|
52
|
-
const policy = response.headers.get("x-ratelimit-policy");
|
|
53
|
-
if (!policy) return;
|
|
54
|
-
const match = policy.match(/q=(\d+)/);
|
|
55
|
-
if (!match) return;
|
|
56
|
-
return Math.min(Number.parseInt(match[1], 10), MAX_RATE_LIMIT);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
7
|
* Creates a `ThrottleManager` from the user-supplied `rateLimit` config.
|
|
60
8
|
*
|
|
61
|
-
* - `false`
|
|
62
|
-
* - `number`
|
|
63
|
-
* - `{
|
|
64
|
-
* - `{}` / `undefined` (default)->
|
|
9
|
+
* - `false` -> no throttling (passthrough)
|
|
10
|
+
* - `number` -> N requests per second
|
|
11
|
+
* - `{ requestsPerSecond: n }` -> N requests per second
|
|
12
|
+
* - `{}` / `undefined` (default) -> DEFAULT_REQUESTS_PER_SECOND per second
|
|
65
13
|
*/
|
|
66
14
|
function createThrottleManager(config) {
|
|
67
|
-
if (config === false) return {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
execute: (fn) => throttle.execute(fn),
|
|
76
|
-
adaptToResponse: (response) => {
|
|
77
|
-
if (!adaptToServerHeaders || response === void 0) return;
|
|
78
|
-
const serverLimit = parseRateLimitPolicyHeader(response);
|
|
79
|
-
if (serverLimit !== void 0) throttle.setLimit(Math.min(cappedLimit, serverLimit));
|
|
80
|
-
}
|
|
81
|
-
};
|
|
15
|
+
if (config === false) return { execute: (fn) => fn() };
|
|
16
|
+
const { requestsPerSecond, maxConcurrency } = typeof config === "number" ? { requestsPerSecond: config } : config;
|
|
17
|
+
const rps = requestsPerSecond ?? maxConcurrency ?? DEFAULT_REQUESTS_PER_SECOND;
|
|
18
|
+
const rl = RateLimit(Math.min(rps, MAX_RATE_LIMIT));
|
|
19
|
+
return { execute: async (fn) => {
|
|
20
|
+
await rl();
|
|
21
|
+
return fn();
|
|
22
|
+
} };
|
|
82
23
|
}
|
|
83
24
|
|
|
84
25
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.mjs","names":[],"sources":["../../src/utils/rate-limit.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"rate-limit.mjs","names":[],"sources":["../../src/utils/rate-limit.ts"],"sourcesContent":["import { RateLimit } from 'async-sema';\n\nconst DEFAULT_REQUESTS_PER_SECOND = 6;\nconst MAX_RATE_LIMIT = 1_000;\n\nexport interface RateLimitConfig {\n /**\n * Maximum number of MAPI requests to start per second.\n * Defaults to 6. Capped at 1000.\n */\n requestsPerSecond?: number;\n /**\n * @deprecated Use `requestsPerSecond` instead.\n * @todo(next-major): Remove this field.\n */\n maxConcurrency?: number;\n}\n\nexport interface ThrottleManager {\n execute: <T>(fn: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Creates a `ThrottleManager` from the user-supplied `rateLimit` config.\n *\n * - `false` -> no throttling (passthrough)\n * - `number` -> N requests per second\n * - `{ requestsPerSecond: n }` -> N requests per second\n * - `{}` / `undefined` (default) -> DEFAULT_REQUESTS_PER_SECOND per second\n */\nexport function createThrottleManager(config: RateLimitConfig | number | false): ThrottleManager {\n if (config === false) {\n return { execute: fn => fn() };\n }\n\n const resolvedConfig: RateLimitConfig = typeof config === 'number' ? { requestsPerSecond: config } : config;\n const { requestsPerSecond, maxConcurrency } = resolvedConfig;\n const rps = requestsPerSecond ?? maxConcurrency ?? DEFAULT_REQUESTS_PER_SECOND;\n const rl = RateLimit(Math.min(rps, MAX_RATE_LIMIT));\n\n return {\n execute: async (fn) => {\n await rl();\n return fn();\n },\n };\n}\n"],"mappings":";;;AAEA,MAAM,8BAA8B;AACpC,MAAM,iBAAiB;;;;;;;;;AA2BvB,SAAgB,sBAAsB,QAA2D;AAC/F,KAAI,WAAW,MACb,QAAO,EAAE,UAAS,OAAM,IAAI,EAAE;CAIhC,MAAM,EAAE,mBAAmB,mBADa,OAAO,WAAW,WAAW,EAAE,mBAAmB,QAAQ,GAAG;CAErG,MAAM,MAAM,qBAAqB,kBAAkB;CACnD,MAAM,KAAK,UAAU,KAAK,IAAI,KAAK,eAAe,CAAC;AAEnD,QAAO,EACL,SAAS,OAAO,OAAO;AACrB,QAAM,IAAI;AACV,SAAO,IAAI;IAEd"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyblok/management-api-client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Storyblok Management API Client",
|
|
7
7
|
"author": "",
|
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"async-sema": "^3.1.1",
|
|
33
34
|
"ky": "^1.14.3",
|
|
34
|
-
"@storyblok/region-helper": "1.4.
|
|
35
|
+
"@storyblok/region-helper": "1.4.1"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@hey-api/openapi-ts": "^0.92.3",
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
"tsdown": "^0.20.3",
|
|
45
46
|
"tsx": "^4.20.3",
|
|
46
47
|
"vitest": "^3.1.3",
|
|
47
|
-
"@storyblok/eslint-config": "0.5.
|
|
48
|
-
"@storyblok/openapi": "2.0.
|
|
48
|
+
"@storyblok/eslint-config": "0.5.1",
|
|
49
|
+
"@storyblok/openapi": "2.0.1"
|
|
49
50
|
},
|
|
50
51
|
"nx": {
|
|
51
52
|
"targets": {
|