@storyblok/management-api-client 0.2.3 → 1.0.0-alpha.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/dist/client.cjs +190 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +624 -0
- package/dist/client.d.mts +624 -0
- package/dist/client.mjs +189 -0
- package/dist/client.mjs.map +1 -0
- package/dist/error.cjs.map +1 -1
- package/dist/error.d.cts +12 -2
- package/dist/error.d.mts +12 -2
- package/dist/error.mjs.map +1 -1
- package/dist/generated/asset_folders/types.gen.d.cts +5 -31
- package/dist/generated/asset_folders/types.gen.d.mts +5 -31
- package/dist/generated/assets/types.gen.d.cts +1 -73
- package/dist/generated/assets/types.gen.d.mts +1 -73
- package/dist/generated/component_folders/types.gen.d.cts +29 -45
- package/dist/generated/component_folders/types.gen.d.mts +29 -45
- package/dist/generated/components/types.gen.d.cts +636 -465
- package/dist/generated/components/types.gen.d.mts +636 -465
- package/dist/generated/datasource_entries/types.gen.d.cts +6 -32
- package/dist/generated/datasource_entries/types.gen.d.mts +6 -32
- package/dist/generated/datasources/types.gen.d.cts +18 -39
- package/dist/generated/datasources/types.gen.d.mts +18 -39
- package/dist/generated/internal_tags/types.gen.d.cts +28 -32
- package/dist/generated/internal_tags/types.gen.d.mts +28 -32
- package/dist/generated/presets/types.gen.d.cts +53 -58
- package/dist/generated/presets/types.gen.d.mts +53 -58
- package/dist/generated/spaces/types.gen.d.cts +1 -41
- package/dist/generated/spaces/types.gen.d.mts +1 -41
- package/dist/generated/stories/types.gen.d.cts +206 -198
- package/dist/generated/stories/types.gen.d.mts +206 -198
- package/dist/generated/users/types.gen.d.cts +13 -112
- package/dist/generated/users/types.gen.d.mts +13 -112
- package/dist/index.cjs +3 -178
- package/dist/index.d.cts +8 -425
- package/dist/index.d.mts +8 -425
- package/dist/index.mjs +2 -176
- package/dist/resources/asset-folders.cjs.map +1 -1
- package/dist/resources/asset-folders.mjs.map +1 -1
- package/dist/resources/assets.cjs +11 -2
- package/dist/resources/assets.cjs.map +1 -1
- package/dist/resources/assets.d.cts +3 -2
- package/dist/resources/assets.d.mts +3 -2
- package/dist/resources/assets.mjs +11 -2
- package/dist/resources/assets.mjs.map +1 -1
- package/dist/resources/component-folders.cjs.map +1 -1
- package/dist/resources/component-folders.mjs.map +1 -1
- package/dist/resources/components.cjs.map +1 -1
- package/dist/resources/components.mjs.map +1 -1
- package/dist/resources/datasource-entries.cjs.map +1 -1
- package/dist/resources/datasource-entries.mjs.map +1 -1
- package/dist/resources/datasources.cjs.map +1 -1
- package/dist/resources/datasources.mjs.map +1 -1
- package/dist/resources/internal-tags.cjs.map +1 -1
- package/dist/resources/internal-tags.mjs.map +1 -1
- package/dist/resources/presets.cjs.map +1 -1
- package/dist/resources/presets.mjs.map +1 -1
- package/dist/resources/spaces.cjs.map +1 -1
- package/dist/resources/spaces.mjs.map +1 -1
- package/dist/resources/stories.cjs.map +1 -1
- package/dist/resources/stories.d.cts +105 -0
- package/dist/resources/stories.d.mts +105 -0
- package/dist/resources/stories.mjs.map +1 -1
- package/dist/resources/users.cjs.map +1 -1
- package/dist/resources/users.mjs.map +1 -1
- package/package.json +13 -10
- package/test/GUIDE.md +59 -0
- package/test/setup.e2e.ts +11 -0
- package/test/specs/mapi-round-trip.spec.e2e.ts +520 -0
- package/vitest.config.e2e.ts +26 -0
- package/vitest.config.ts +3 -0
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/types.d.cts +0 -130
- package/dist/types.d.mts +0 -130
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stories.mjs","names":["storiesApi.list","storiesApi.get","storiesApi.create","storiesApi.update","storiesApi.delete_","storiesApi.duplicate","storiesApi.publish","storiesApi.versions"],"sources":["../../src/resources/stories.ts"],"sourcesContent":["import * as storiesApi from '../generated/stories/sdk.gen';\nimport type {\n CreateData,\n CreateResponses,\n DeleteResponses,\n DuplicateData,\n DuplicateResponses,\n GetData,\n GetResponses,\n ListData,\n ListResponses,\n PublishData,\n PublishResponses,\n UpdateData,\n UpdateResponses,\n VersionsData,\n VersionsResponses,\n} from '../generated/stories/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../index';\nimport { resolveSpaceId, type SpaceIdPathOverride } from './shared';\n\nexport function createStoriesResource(deps: MapiResourceDeps) {\n const { client, spaceId, wrapRequest } = deps;\n const getSpaceId = (path?: SpaceIdPathOverride['path']) => resolveSpaceId(spaceId, path);\n\n return {\n list<ThrowOnError extends boolean = false>(options: { query?: ListData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<ListResponses[200], ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<ListResponses[200], ThrowOnError>(() =>\n storiesApi.list({ client, path: { space_id: resolvedSpaceId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n get<ThrowOnError extends boolean = false>(storyId: number | string, options: { query?: GetData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<GetResponses[200], ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<GetResponses[200], ThrowOnError>(() =>\n storiesApi.get({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n create<ThrowOnError extends boolean = false>(options: { body: CreateData['body']; query?: CreateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride): Promise<ApiResponse<CreateResponses[201], ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<CreateResponses[201], ThrowOnError>(() =>\n storiesApi.create({ client, path: { space_id: resolvedSpaceId }, body, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n update<ThrowOnError extends boolean = false>(\n storyId: number | string,\n options: { body: UpdateData['body']; query?: UpdateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride,\n ): Promise<ApiResponse<UpdateResponses[200], ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<UpdateResponses[200], ThrowOnError>(() =>\n storiesApi.update({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, body, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n delete<ThrowOnError extends boolean = false>(storyId: number | string, options: { signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<DeleteResponses[200], ThrowOnError>> {\n const { signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<DeleteResponses[200], ThrowOnError>(() =>\n storiesApi.delete_({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n duplicate<ThrowOnError extends boolean = false>(\n storyId: number | string,\n options: { body: DuplicateData['body']; query?: DuplicateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride,\n ): Promise<ApiResponse<DuplicateResponses[200], ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<DuplicateResponses[200], ThrowOnError>(() =>\n storiesApi.duplicate({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, body, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n publish<ThrowOnError extends boolean = false>(\n storyId: number | string,\n options: { query?: PublishData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {},\n ): Promise<ApiResponse<PublishResponses[200], ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<PublishResponses[200], ThrowOnError>(() =>\n storiesApi.publish({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n versions<ThrowOnError extends boolean = false>(\n options: { query?: VersionsData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {},\n ): Promise<ApiResponse<VersionsResponses[200], ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<VersionsResponses[200], ThrowOnError>(() =>\n storiesApi.versions({ client, path: { space_id: resolvedSpaceId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stories.mjs","names":["storiesApi.list","storiesApi.get","storiesApi.create","storiesApi.update","storiesApi.delete_","storiesApi.duplicate","storiesApi.publish","storiesApi.versions"],"sources":["../../src/resources/stories.ts"],"sourcesContent":["import * as storiesApi from '../generated/stories/sdk.gen';\nimport type {\n CreateData,\n CreateResponses,\n DeleteResponses,\n DuplicateData,\n DuplicateResponses,\n GetData,\n GetResponses,\n ListData,\n ListResponses,\n PublishData,\n PublishResponses,\n StoryCreateRequest,\n StoryMapi,\n StoryUpdateRequest,\n UpdateData,\n UpdateResponses,\n VersionsData,\n VersionsResponses,\n} from '../generated/stories/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../client';\nimport { resolveSpaceId, type SpaceIdPathOverride } from './shared';\nimport type { Block as Component, MapiStory, StoryCreate as MapiStoryCreate, StoryUpdate as MapiStoryUpdate } from '@storyblok/schema';\n\nexport type StoryListQuery = NonNullable<ListData['query']>;\n\n/**\n * Resolves to a component-narrowed story type when `TComponents` is a specific\n * Component union, or falls back to the generated `StoryMapi` when no components\n * are provided (i.e. `TComponents` is the default base `Component` type).\n *\n * Delegates to `MapiStory<TComponents>` single-generic mode which internally\n * handles the `RootComponents` filtering and discriminated union construction.\n */\ntype StoryResult<TComponents extends Component> =\n Component extends TComponents\n ? StoryMapi // fallback: no components provided\n : MapiStory<TComponents>;\n\ntype GetResponse<TComponents extends Component> =\n Omit<GetResponses[200], 'story'> & { story?: StoryResult<TComponents> };\n\ntype ListResponse<TComponents extends Component> =\n Omit<ListResponses[200], 'stories'> & { stories?: Array<StoryResult<TComponents>> };\n\ntype CreateResponse<TComponents extends Component> =\n Omit<CreateResponses[201], 'story'> & { story?: StoryResult<TComponents> };\n\ntype UpdateResponse<TComponents extends Component> =\n Omit<UpdateResponses[200], 'story'> & { story?: StoryResult<TComponents> };\n\ntype DuplicateResponse<TComponents extends Component> =\n Omit<DuplicateResponses[200], 'story'> & { story?: StoryResult<TComponents> };\n\ntype PublishResponse<TComponents extends Component> =\n Omit<PublishResponses[200], 'story'> & { story?: StoryResult<TComponents> };\n\n/**\n * Component-narrowed body for story creation. When `TComponents` is provided,\n * `body.story.content` is typed to the narrowed union of root component content types.\n * Falls back to the generated `StoryCreateRequest` when no components are provided.\n */\ntype CreateBody<TComponents extends Component> =\n Component extends TComponents\n ? CreateData['body']\n : Omit<StoryCreateRequest, 'story'> & {\n story: MapiStoryCreate<TComponents>;\n };\n\n/**\n * Component-narrowed body for story updates. When `TComponents` is provided,\n * `body.story.content` is typed to the narrowed union of root component content types.\n * Falls back to the generated `StoryUpdateRequest` when no components are provided.\n */\ntype UpdateBody<TComponents extends Component> =\n Component extends TComponents\n ? UpdateData['body']\n : Omit<StoryUpdateRequest, 'story'> & {\n story: MapiStoryUpdate<TComponents>;\n };\n\nexport function createStoriesResource<\n TComponents extends Component = Component,\n DefaultThrowOnError extends boolean = false,\n>(deps: MapiResourceDeps<DefaultThrowOnError>) {\n const { client, spaceId, wrapRequest } = deps;\n const getSpaceId = (path?: SpaceIdPathOverride['path']) => resolveSpaceId(spaceId, path);\n\n return {\n list<ThrowOnError extends boolean = DefaultThrowOnError>(options: { query?: ListData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<ListResponse<TComponents>, ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<ListResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.list({ client, path: { space_id: resolvedSpaceId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n get<ThrowOnError extends boolean = DefaultThrowOnError>(storyId: number | string, options: { query?: GetData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<GetResponse<TComponents>, ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<GetResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.get({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n create<ThrowOnError extends boolean = DefaultThrowOnError>(options: { body: CreateBody<TComponents>; query?: CreateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride): Promise<ApiResponse<CreateResponse<TComponents>, ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<CreateResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.create({ client, path: { space_id: resolvedSpaceId }, body: body as CreateData['body'], query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n update<ThrowOnError extends boolean = DefaultThrowOnError>(\n storyId: number | string,\n options: { body: UpdateBody<TComponents>; query?: UpdateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride,\n ): Promise<ApiResponse<UpdateResponse<TComponents>, ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<UpdateResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.update({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, body: body as UpdateData['body'], query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n delete<ThrowOnError extends boolean = DefaultThrowOnError>(storyId: number | string, options: { signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {}): Promise<ApiResponse<DeleteResponses[200], ThrowOnError>> {\n const { signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<DeleteResponses[200], ThrowOnError>(() =>\n storiesApi.delete_({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n duplicate<ThrowOnError extends boolean = DefaultThrowOnError>(\n storyId: number | string,\n options: { body: DuplicateData['body']; query?: DuplicateData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride,\n ): Promise<ApiResponse<DuplicateResponse<TComponents>, ThrowOnError>> {\n const { body, query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<DuplicateResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.duplicate({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, body, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n publish<ThrowOnError extends boolean = DefaultThrowOnError>(\n storyId: number | string,\n options: { query?: PublishData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {},\n ): Promise<ApiResponse<PublishResponse<TComponents>, ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<PublishResponse<TComponents>, ThrowOnError>(() =>\n storiesApi.publish({ client, path: { space_id: resolvedSpaceId, story_id: storyId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n versions<ThrowOnError extends boolean = DefaultThrowOnError>(\n options: { query?: VersionsData['query']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } & SpaceIdPathOverride = {},\n ): Promise<ApiResponse<VersionsResponses[200], ThrowOnError>> {\n const { query, signal, path, throwOnError, fetchOptions } = options;\n const resolvedSpaceId = getSpaceId(path);\n return wrapRequest<VersionsResponses[200], ThrowOnError>(() =>\n storiesApi.versions({ client, path: { space_id: resolvedSpaceId }, query, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.cjs","names":[],"sources":["../../src/resources/users.ts"],"sourcesContent":["import * as usersApi from '../generated/users/sdk.gen';\nimport type {\n MeResponses,\n UpdateMeData,\n UpdateMeResponses,\n} from '../generated/users/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../
|
|
1
|
+
{"version":3,"file":"users.cjs","names":[],"sources":["../../src/resources/users.ts"],"sourcesContent":["import * as usersApi from '../generated/users/sdk.gen';\nimport type {\n MeResponses,\n UpdateMeData,\n UpdateMeResponses,\n} from '../generated/users/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../client';\n\nexport function createUsersResource<DefaultThrowOnError extends boolean = false>(deps: Omit<MapiResourceDeps<DefaultThrowOnError>, 'spaceId'>) {\n const { client, wrapRequest } = deps;\n\n return {\n me<ThrowOnError extends boolean = DefaultThrowOnError>(options: { signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } = {}): Promise<ApiResponse<MeResponses[200], ThrowOnError>> {\n const { signal, throwOnError, fetchOptions } = options;\n return wrapRequest<MeResponses[200], ThrowOnError>(() =>\n usersApi.me({ client, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n updateMe<ThrowOnError extends boolean = DefaultThrowOnError>(options: { body: UpdateMeData['body']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions }): Promise<ApiResponse<UpdateMeResponses[200], ThrowOnError>> {\n const { body, signal, throwOnError, fetchOptions } = options;\n return wrapRequest<UpdateMeResponses[200], ThrowOnError>(() =>\n usersApi.updateMe({ client, body, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n };\n}\n"],"mappings":";;;AAQA,SAAgB,oBAAiE,MAA8D;CAC7I,MAAM,EAAE,QAAQ,gBAAgB;AAEhC,QAAO;EACL,GAAuD,UAA8F,EAAE,EAAwD;GAC7M,MAAM,EAAE,QAAQ,cAAc,iBAAiB;AAC/C,UAAO,qCACO;IAAE;IAAQ;IAAQ,GAAI,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc;IAAG,GAAI,eAAe,EAAE,WAAW;KAAE,GAAG,OAAO,WAAW,CAAC;KAAW,GAAG;KAAc,EAAE,GAAG,EAAE;IAAG,CAAC,EAAE,aAAa;;EAEzM,SAA6D,SAAqL;GAChP,MAAM,EAAE,MAAM,QAAQ,cAAc,iBAAiB;AACrD,UAAO,2CACa;IAAE;IAAQ;IAAM;IAAQ,GAAI,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc;IAAG,GAAI,eAAe,EAAE,WAAW;KAAE,GAAG,OAAO,WAAW,CAAC;KAAW,GAAG;KAAc,EAAE,GAAG,EAAE;IAAG,CAAC,EAAE,aAAa;;EAEtN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.mjs","names":["usersApi.me","usersApi.updateMe"],"sources":["../../src/resources/users.ts"],"sourcesContent":["import * as usersApi from '../generated/users/sdk.gen';\nimport type {\n MeResponses,\n UpdateMeData,\n UpdateMeResponses,\n} from '../generated/users/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../
|
|
1
|
+
{"version":3,"file":"users.mjs","names":["usersApi.me","usersApi.updateMe"],"sources":["../../src/resources/users.ts"],"sourcesContent":["import * as usersApi from '../generated/users/sdk.gen';\nimport type {\n MeResponses,\n UpdateMeData,\n UpdateMeResponses,\n} from '../generated/users/types.gen';\nimport type { ApiResponse, FetchOptions, MapiResourceDeps } from '../client';\n\nexport function createUsersResource<DefaultThrowOnError extends boolean = false>(deps: Omit<MapiResourceDeps<DefaultThrowOnError>, 'spaceId'>) {\n const { client, wrapRequest } = deps;\n\n return {\n me<ThrowOnError extends boolean = DefaultThrowOnError>(options: { signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions } = {}): Promise<ApiResponse<MeResponses[200], ThrowOnError>> {\n const { signal, throwOnError, fetchOptions } = options;\n return wrapRequest<MeResponses[200], ThrowOnError>(() =>\n usersApi.me({ client, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n updateMe<ThrowOnError extends boolean = DefaultThrowOnError>(options: { body: UpdateMeData['body']; signal?: AbortSignal; throwOnError?: ThrowOnError; fetchOptions?: FetchOptions }): Promise<ApiResponse<UpdateMeResponses[200], ThrowOnError>> {\n const { body, signal, throwOnError, fetchOptions } = options;\n return wrapRequest<UpdateMeResponses[200], ThrowOnError>(() =>\n usersApi.updateMe({ client, body, signal, ...(throwOnError === undefined ? {} : { throwOnError }), ...(fetchOptions ? { kyOptions: { ...client.getConfig().kyOptions, ...fetchOptions } } : {}) }), throwOnError);\n },\n };\n}\n"],"mappings":";;;AAQA,SAAgB,oBAAiE,MAA8D;CAC7I,MAAM,EAAE,QAAQ,gBAAgB;AAEhC,QAAO;EACL,GAAuD,UAA8F,EAAE,EAAwD;GAC7M,MAAM,EAAE,QAAQ,cAAc,iBAAiB;AAC/C,UAAO,kBACLA,GAAY;IAAE;IAAQ;IAAQ,GAAI,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc;IAAG,GAAI,eAAe,EAAE,WAAW;KAAE,GAAG,OAAO,WAAW,CAAC;KAAW,GAAG;KAAc,EAAE,GAAG,EAAE;IAAG,CAAC,EAAE,aAAa;;EAEzM,SAA6D,SAAqL;GAChP,MAAM,EAAE,MAAM,QAAQ,cAAc,iBAAiB;AACrD,UAAO,kBACLC,SAAkB;IAAE;IAAQ;IAAM;IAAQ,GAAI,iBAAiB,SAAY,EAAE,GAAG,EAAE,cAAc;IAAG,GAAI,eAAe,EAAE,WAAW;KAAE,GAAG,OAAO,WAAW,CAAC;KAAW,GAAG;KAAc,EAAE,GAAG,EAAE;IAAG,CAAC,EAAE,aAAa;;EAEtN"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyblok/management-api-client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0-alpha.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Storyblok Management API Client",
|
|
7
7
|
"author": "",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"homepage": "https://github.com/storyblok/monoblok/tree/main/packages/mapi-client#readme",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/storyblok/monoblok.git",
|
|
12
|
+
"url": "git+https://github.com/storyblok/monoblok.git",
|
|
13
13
|
"directory": "packages/mapi-client"
|
|
14
14
|
},
|
|
15
15
|
"bugs": {
|
|
@@ -31,21 +31,23 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"ky": "^1.14.3",
|
|
34
|
-
"@storyblok/region-helper": "1.4.0"
|
|
34
|
+
"@storyblok/region-helper": "1.4.0",
|
|
35
|
+
"@storyblok/schema": "1.0.0-alpha.0"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@hey-api/openapi-ts": "^0.92.3",
|
|
38
39
|
"@msw/source": "^0.6.1",
|
|
39
40
|
"@types/node": "^24.1.0",
|
|
41
|
+
"dotenv": "^17.3.1",
|
|
40
42
|
"eslint": "^9.39.2",
|
|
41
43
|
"glob": "^13.0.6",
|
|
42
44
|
"msw": "^2.12.9",
|
|
43
45
|
"pathe": "^2.0.3",
|
|
44
46
|
"tsdown": "^0.20.3",
|
|
45
47
|
"tsx": "^4.20.3",
|
|
46
|
-
"vitest": "^
|
|
47
|
-
"@storyblok/
|
|
48
|
-
"@storyblok/
|
|
48
|
+
"vitest": "^4.1.3",
|
|
49
|
+
"@storyblok/openapi": "2.1.0-alpha.0",
|
|
50
|
+
"@storyblok/eslint-config": "0.5.0"
|
|
49
51
|
},
|
|
50
52
|
"nx": {
|
|
51
53
|
"targets": {
|
|
@@ -71,10 +73,11 @@
|
|
|
71
73
|
"scripts": {
|
|
72
74
|
"generate": "tsx scripts/generate.ts",
|
|
73
75
|
"build": "tsdown",
|
|
74
|
-
"test": "vitest",
|
|
75
|
-
"test:
|
|
76
|
+
"test": "vitest run",
|
|
77
|
+
"test:types": "tsc --noEmit --skipLibCheck",
|
|
78
|
+
"test:e2e": "vitest run -c vitest.config.e2e.ts",
|
|
79
|
+
"coverage": "vitest run --coverage",
|
|
76
80
|
"lint": "eslint .",
|
|
77
|
-
"lint:fix": "eslint . --fix"
|
|
78
|
-
"typecheck": "tsc --noEmit"
|
|
81
|
+
"lint:fix": "eslint . --fix"
|
|
79
82
|
}
|
|
80
83
|
}
|
package/test/GUIDE.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Manually Test the @storyblok/management-api-client Package
|
|
2
|
+
|
|
3
|
+
`@storyblok/management-api-client` is the Management API (MAPI) client. The key things to validate manually are that the schema-aware `.withTypes()` integration correctly narrows story content, that every define helper produces a valid creation payload, and that Zod schemas accept real API responses.
|
|
4
|
+
|
|
5
|
+
## Automated e2e tests
|
|
6
|
+
|
|
7
|
+
`test/specs/mapi-round-trip.spec.e2e.ts` covers the full round-trip against a real Storyblok space:
|
|
8
|
+
|
|
9
|
+
- Seeds components, datasources, internal tags, presets, and stories via the MAPI.
|
|
10
|
+
- Validates runtime values, type narrowing, nested bloks (two- and three-level), unwhitelisted bloks, and update round-trips.
|
|
11
|
+
- Validates MAPI Zod schemas (`componentSchema`, `storySchema`, `datasourceSchema`, `datasourceEntrySchema`) against real API responses.
|
|
12
|
+
|
|
13
|
+
Run manually:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm --filter @storyblok/management-api-client test:e2e
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
- A `.env.qa-engineer-manual` file at the repo root with `STORYBLOK_TOKEN` and `STORYBLOK_SPACE_ID`.
|
|
22
|
+
- `@storyblok/management-api-client` must be built first.
|
|
23
|
+
|
|
24
|
+
## Fetch via MAPI client and check content types
|
|
25
|
+
|
|
26
|
+
`stories.get(storyId)` takes a numeric/string ID as its first positional argument — there is no `getBySlug`. Fetch the ID from `stories.list` first:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createManagementApiClient } from '@storyblok/management-api-client';
|
|
30
|
+
|
|
31
|
+
const client = createManagementApiClient({ personalAccessToken: process.env.STORYBLOK_TOKEN, spaceId });
|
|
32
|
+
const list = await client.stories.list({ query: { per_page: 100 } });
|
|
33
|
+
const story = list.data?.stories?.find(s => s.slug === 'home');
|
|
34
|
+
const result = await client.stories.get(story.id);
|
|
35
|
+
console.info(result.data?.story?.content);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Push component JSONs via the CLI
|
|
39
|
+
|
|
40
|
+
To push `defineComponent` components, serialize the component objects to JSON and stage them under `.storyblok/components/<space_id>/`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
node packages/cli/dist/index.mjs components push \
|
|
44
|
+
--from qa-test \
|
|
45
|
+
--space $STORYBLOK_SPACE_ID \
|
|
46
|
+
--separate-files
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Always push components before stories.** The CLI validates that each story's `content.component` (and any nested block components) exist in the space. Pushing stories first fails if the referenced components are not yet present.
|
|
50
|
+
|
|
51
|
+
You can do the same with stories and `defineStory`. **Story filename convention:** the CLI requires files named `{slug}_{uuid}.json` where the part after the last `_` exactly matches `story.uuid` in the JSON. Use hyphens (not underscores) in UUIDs. A mismatch causes Pass 2 of the push (reference mapping + content update) to silently skip all stories.
|
|
52
|
+
|
|
53
|
+
## Known quirks
|
|
54
|
+
|
|
55
|
+
- **Stories require a content type component (`is_root: true`).** The MAPI rejects story creation with `"please select a content type component as your root component"` if the component used as the story root does not have `is_root: true`.
|
|
56
|
+
- **MAPI `stories.get` takes a positional ID, not an options object:** `client.stories.get(id)` — there is no `getBySlug`. The `list` response does not include `content`; call `get(id)` for full content.
|
|
57
|
+
- **MAPI client constructor uses `personalAccessToken`:** `createManagementApiClient({ personalAccessToken: '...', spaceId: ... })`.
|
|
58
|
+
- **Delete methods are `delete`:** Use `client.RESOURCE.delete(id)`.
|
|
59
|
+
- **Each story JSON must have a unique `id`.** `defineStory` defaults `id` to `1`. If multiple story files share the same `id`, the CLI's manifest maps all of them to the same `old_id` entry, causing "slug already taken" errors.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
config({ path: resolve(import.meta.dirname, '../../../.env.qa-engineer-manual') });
|
|
5
|
+
|
|
6
|
+
if (!process.env.STORYBLOK_TOKEN || !process.env.STORYBLOK_SPACE_ID) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
'E2E tests require STORYBLOK_TOKEN and STORYBLOK_SPACE_ID.\n'
|
|
9
|
+
+ 'Create a .env.qa-engineer-manual file at the repo root with these variables.',
|
|
10
|
+
);
|
|
11
|
+
}
|