@book000/pixivts - v0.61.1
    Preparing search index...

    Migration Guide: ≤ 0.55.1 → ≥ 0.56.2

    Version 0.56.2 is a breaking rewrite. This guide maps patterns from 0.55.1 and earlier to the current API.

    The previous version was a single package. The current version is a pnpm monorepo with two packages:

    ≤ 0.55.1 ≥ 0.56.2
    @book000/pixivts (fetch-based, CJS) @book000/pixivts (fetch-based, ESM+CJS)
    saving-responses/ (TypeORM + MySQL built-in) @book000/pixivts-db-mysql (optional, Drizzle + MySQL)
    // ≤ 0.55.1
    import { Pixiv } from '@book000/pixivts'
    const pixiv = await Pixiv.of(refreshToken)

    // ≥ 0.56.2
    import { PixivClient } from '@book000/pixivts'
    const client = await PixivClient.of(refreshToken)

    The previous version threw errors on failure. The current version returns Result<T, PixivError> — no thrown exceptions.

    // ≤ 0.55.1
    try {
    const res = await pixiv.illustDetail({ illustId })
    console.log(res.data.illust.title)
    } catch (err) {
    console.error(err)
    }

    // ≥ 0.56.2
    const result = await client.illusts.detail({ illustId })
    if (result.isOk) {
    console.log(result.value.illust.title)
    } else {
    console.error(result.error.type)
    }
    ≤ 0.55.1 method ≥ 0.56.2 method
    pixiv.illustDetail({ illustId }) client.illusts.detail({ illustId })
    pixiv.illustRelated({ illustId }) client.illusts.related({ illustId })
    pixiv.searchIllust({ word }) client.illusts.search({ word })
    pixiv.illustRanking(opts) client.illusts.ranking(opts)
    pixiv.illustRecommended(opts) client.illusts.recommended(opts)
    pixiv.illustSeries({ illustSeriesId }) client.illusts.series({ illustSeriesId })
    pixiv.illustBookmarkAdd(opts) client.illusts.bookmarkAdd(opts)
    pixiv.illustBookmarkDelete(opts) client.illusts.bookmarkDelete(opts)
    pixiv.novelDetail({ novelId }) client.novels.detail({ novelId })
    pixiv.novelText({ novelId }) client.novels.text({ novelId })
    pixiv.novelRelated({ novelId }) client.novels.related({ novelId })
    pixiv.searchNovel({ word }) client.novels.search({ word })
    pixiv.novelRanking(opts) client.novels.ranking(opts)
    pixiv.novelRecommended(opts) client.novels.recommended(opts)
    pixiv.novelSeries({ seriesId }) client.novels.series({ seriesId })
    pixiv.novelBookmarkAdd(opts) client.novels.bookmarkAdd(opts)
    pixiv.novelBookmarkDelete(opts) client.novels.bookmarkDelete(opts)
    pixiv.userDetail({ userId }) client.users.detail({ userId })
    pixiv.userIllusts({ userId }) client.users.illusts({ userId })
    pixiv.userNovels({ userId }) client.users.novels({ userId })
    pixiv.userFollowing(opts) client.users.following(opts)
    pixiv.userFollowAdd(opts) client.users.followAdd(opts)
    pixiv.userFollowDelete(opts) client.users.followDelete(opts)
    pixiv.userBookmarksIllust(opts) client.users.bookmarks.illusts(opts)
    pixiv.userBookmarksNovel(opts) client.users.bookmarks.novels(opts)
    pixiv.mangaRecommended(opts) client.manga.recommended(opts)
    pixiv.ugoiraMetadata({ illustId }) client.ugoira.metadata({ illustId })
    pixiv.getImageStream(url) client.images.fetch(url)

    The previous version returned the raw API response including next_url. The current version provides a PaginatedResultAsync with async generators.

    // ≤ 0.55.1
    let offset = 0
    while (true) {
    const res = await pixiv.searchIllust({ word: 'hatsune miku', offset })
    // process res.data.illusts
    if (!res.data.next_url) break
    offset += res.data.illusts.length
    }

    // ≥ 0.56.2 — iterate pages
    for await (const page of client.illusts.search({ word: 'hatsune miku' }).pages()) {
    // process page.illusts
    }

    // ≥ 0.56.2 — iterate all items across pages (async generator — throws on fetch error)
    for await (const illust of client.illusts.search({ word: 'hatsune miku' }).items()) {
    console.log(illust) // IllustSimple
    }

    The previous version returned a custom PixivApiResponse<T> — you accessed the body via .data. The current version returns the unwrapped response body directly.

    // ≤ 0.55.1
    const res = await pixiv.illustDetail({ illustId })
    console.log(res.data.illust.title) // .data because it's PixivApiResponse<T>

    // ≥ 0.56.2
    const result = await client.illusts.detail({ illustId })
    if (result.isOk) {
    console.log(result.value.illust.title) // no .data — value is the response body
    }

    The previous version had response saving built into the core package via TypeORM. The current version moves this to the optional @book000/pixivts-db-mysql package using Drizzle ORM.

    // ≤ 0.55.1
    import { Pixiv } from '@book000/pixivts'
    const pixiv = await Pixiv.of(refreshToken, {
    responseDatabase: {
    host: 'localhost',
    username: 'pixiv',
    password: 'secret',
    database: 'pixivts',
    synchronize: true,
    },
    })

    // ≥ 0.56.2
    import { PixivClient } from '@book000/pixivts'
    import { createResponseRecorder } from '@book000/pixivts-db-mysql'

    const { interceptor, close } = await createResponseRecorder({
    host: 'localhost',
    user: 'pixiv',
    password: 'secret',
    database: 'pixivts',
    bootstrap: true,
    })
    const client = await PixivClient.of(refreshToken, { onResponse: interceptor })
    // ... use client ...
    await close()

    The following dependencies from ≤ 0.55.1 are no longer required:

    Removed Reason
    qs Replaced by URLSearchParams
    typeorm Moved to @book000/pixivts-db-mysql (Drizzle)
    typeorm-naming-strategies Same as above
    snake-camel-types Replaced by local type utilities

    Migration Guide: ≤ 0.57.x → ≥ 0.58.0

    All response field names have been renamed from snake_case to lowerCamelCase. This is a breaking change.

    The library continues to communicate with the pixiv API using snake_case internally, but all values returned to callers are now camelCase.

    ≤ 0.57.x ≥ 0.58.0
    illust.image_urls.square_medium illust.imageUrls.squareMedium
    illust.create_date illust.createDate
    illust.page_count illust.pageCount
    illust.x_restrict illust.xRestrict
    illust.meta_single_page illust.metaSinglePage
    illust.meta_pages illust.metaPages
    illust.total_view illust.totalView
    illust.total_bookmarks illust.totalBookmarks
    illust.is_bookmarked illust.isBookmarked
    illust.illust_ai_type illust.illustAiType
    novel.x_restrict novel.xRestrict
    novel.create_date novel.createDate
    novel.is_bookmarked novel.isBookmarked
    novel.novel_ai_type novel.novelAiType
    page.next_url page.nextUrl
    page.user_previews page.userPreviews
    page.ugoira_metadata page.ugoiraMetadata
    user.profile_image_urls user.profileImageUrls
    ugoira.zip_urls ugoira.zipUrls
    // ≤ 0.57.x
    const page = await client.users.bookmarks.illusts({ userId: client.userId })
    if (page.isOk && page.value.next_url) {
    const cursor = parseNextUrl(page.value.next_url)
    }

    // ≥ 0.58.0
    const page = await client.users.bookmarks.illusts({ userId: client.userId })
    if (page.isOk && page.value.nextUrl) {
    const cursor = parseNextUrl(page.value.nextUrl)
    }

    PixivClient now exposes getAccessToken() and getRefreshToken() methods:

    const client = await PixivClient.of(refreshToken)
    console.log(client.getAccessToken()) // current bearer token
    console.log(client.getRefreshToken()) // current refresh token

    The @book000/pixivts-db-mysql package continues to save raw snake_case response bodies to the database for archival fidelity. This behaviour is unchanged.