@taisan11/zenn.js 0.1.0 → 0.1.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/index.cjs +2 -2
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -76,7 +76,7 @@ class ZennClient {
|
|
|
76
76
|
headers;
|
|
77
77
|
constructor(options = {}) {
|
|
78
78
|
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
79
|
-
this.fetcher = options.fetch ?? fetch;
|
|
79
|
+
this.fetcher = options.fetch ?? fetch.bind(globalThis);
|
|
80
80
|
this.headers = options.headers ?? {};
|
|
81
81
|
}
|
|
82
82
|
async request(path, params) {
|
|
@@ -169,4 +169,4 @@ class ZennClient {
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
//# debugId=
|
|
172
|
+
//# debugId=1EF2302271791DDE64756E2164756E21
|
package/dist/index.cjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/client.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {\n ArticleDetail,\n ArticleResponse,\n ArticlesResponse,\n BookResponse,\n BooksResponse,\n ChapterResponse,\n ClientOptions,\n ListArticlesOptions,\n ListBooksOptions,\n ListFollowersOptions,\n ListScrapsOptions,\n ListUsersCommentsOptions,\n PublicationMini,\n PublicationResponse,\n ScrapsResponse,\n ScrapResponse,\n SearchOptions,\n SearchResponse,\n SearchSource,\n TopicResponse,\n TopicsResponse,\n UserCommentsResponse,\n UserResponse,\n UsersResponse,\n Event,\n} from \"./types.ts\";\n\nconst DEFAULT_BASE_URL = \"https://zenn.dev\";\n\nexport class ZennApiError extends Error {\n status: number;\n body: unknown;\n\n constructor(status: number, body: unknown, message: string) {\n super(message);\n this.name = \"ZennApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface PublicationsMiniResponse {\n publications: PublicationMini[];\n next_page: number | null;\n}\n\nfunction buildQuery(params: object | undefined): string {\n if (!params) return \"\";\n const search = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null || v === \"\") continue;\n search.set(k, String(v));\n }\n const qs = search.toString();\n return qs.length > 0 ? `?${qs}` : \"\";\n}\n\nexport class ZennClient {\n private readonly baseUrl: string;\n private readonly fetcher: typeof fetch;\n private readonly headers: HeadersInit;\n\n constructor(options: ClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetcher = options.fetch ?? fetch;\n this.headers = options.headers ?? {};\n }\n\n private async request<T>(path: string, params?: object): Promise<T> {\n const url = `${this.baseUrl}${path}${buildQuery(params)}`;\n const res = await this.fetcher(url, {\n headers: {\n Accept: \"application/json\",\n ...this.headers,\n },\n });\n const text = await res.text();\n const data: unknown = text.length > 0 ? JSON.parse(text) : null;\n if (!res.ok) {\n throw new ZennApiError(res.status, data, `Zenn API request failed: ${res.status} ${res.statusText} (${url})`);\n }\n return data as T;\n }\n\n // ---------- Articles ----------\n\n listArticles(options: ListArticlesOptions = {}): Promise<ArticlesResponse> {\n return this.request<ArticlesResponse>(\"/api/articles\", options);\n }\n\n getArticle(slug: string): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(`/api/articles/${encodeURIComponent(slug)}`);\n }\n\n getArticleById(id: number): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(\"/api/articles\", { id });\n }\n\n async *iterArticles(options: Omit<ListArticlesOptions, \"page\"> = {}): AsyncGenerator<ArticleDetail, void, void> {\n let page = 1;\n while (true) {\n const res = await this.listArticles({ ...options, page });\n for (const item of res.articles) {\n const detail = await this.getArticle(item.slug);\n yield detail.article;\n }\n if (res.next_page === null || res.next_page === undefined) break;\n page = res.next_page;\n }\n }\n\n // ---------- Books ----------\n\n listBooks(options: ListBooksOptions = {}): Promise<BooksResponse> {\n return this.request<BooksResponse>(\"/api/books\", options);\n }\n\n getBook(slug: string): Promise<BookResponse> {\n return this.request<BookResponse>(`/api/books/${encodeURIComponent(slug)}`);\n }\n\n getChapter(id: number): Promise<ChapterResponse> {\n return this.request<ChapterResponse>(`/api/chapters/${id}`);\n }\n\n // ---------- Scraps ----------\n\n listScraps(options: ListScrapsOptions = {}): Promise<ScrapsResponse> {\n return this.request<ScrapsResponse>(\"/api/scraps\", options);\n }\n\n getScrap(slug: string): Promise<ScrapResponse> {\n return this.request<ScrapResponse>(`/api/scraps/${encodeURIComponent(slug)}`);\n }\n\n // ---------- Users ----------\n\n getUser(username: string): Promise<UserResponse> {\n return this.request<UserResponse>(`/api/users/${encodeURIComponent(username)}`);\n }\n\n getCurrentUser(): Promise<UserResponse> {\n return this.request<UserResponse>(\"/api/users/current\");\n }\n\n getUserFollowers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followers`, options);\n }\n\n getUserFollowingsUsers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followings/users`, options);\n }\n\n getUserFollowingsPublications(\n username: string,\n options: ListFollowersOptions = {},\n ): Promise<PublicationsMiniResponse> {\n return this.request<PublicationsMiniResponse>(\n `/api/users/${encodeURIComponent(username)}/followings/publications`,\n options,\n );\n }\n\n getUserComments(username: string, options: ListUsersCommentsOptions = {}): Promise<UserCommentsResponse> {\n return this.request<UserCommentsResponse>(`/api/users/${encodeURIComponent(username)}/comments`, options);\n }\n\n // ---------- Publications ----------\n\n getPublication(name: string): Promise<PublicationResponse> {\n return this.request<PublicationResponse>(`/api/publications/${encodeURIComponent(name)}`);\n }\n\n getPublicationFollowers(name: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/publications/${encodeURIComponent(name)}/followers`, options);\n }\n\n // ---------- Topics ----------\n\n listTopics(): Promise<TopicsResponse> {\n return this.request<TopicsResponse>(\"/api/topics\");\n }\n\n getTopic(name: string): Promise<TopicResponse> {\n return this.request<TopicResponse>(`/api/topics/${encodeURIComponent(name)}`);\n }\n\n // ---------- Search ----------\n\n search<TSource extends SearchSource>(\n options: SearchOptions & { source: TSource },\n ): Promise<SearchResponse<TSource>> {\n return this.request<SearchResponse<TSource>>(\"/api/search\", options);\n }\n\n // ---------- Events ----------\n\n listEvents(): Promise<Event[]> {\n return this.request<Event[]>(\"/api/events\");\n }\n}\n"
|
|
5
|
+
"import type {\n ArticleDetail,\n ArticleResponse,\n ArticlesResponse,\n BookResponse,\n BooksResponse,\n ChapterResponse,\n ClientOptions,\n ListArticlesOptions,\n ListBooksOptions,\n ListFollowersOptions,\n ListScrapsOptions,\n ListUsersCommentsOptions,\n PublicationMini,\n PublicationResponse,\n ScrapsResponse,\n ScrapResponse,\n SearchOptions,\n SearchResponse,\n SearchSource,\n TopicResponse,\n TopicsResponse,\n UserCommentsResponse,\n UserResponse,\n UsersResponse,\n Event,\n} from \"./types.ts\";\n\nconst DEFAULT_BASE_URL = \"https://zenn.dev\";\n\nexport class ZennApiError extends Error {\n status: number;\n body: unknown;\n\n constructor(status: number, body: unknown, message: string) {\n super(message);\n this.name = \"ZennApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface PublicationsMiniResponse {\n publications: PublicationMini[];\n next_page: number | null;\n}\n\nfunction buildQuery(params: object | undefined): string {\n if (!params) return \"\";\n const search = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null || v === \"\") continue;\n search.set(k, String(v));\n }\n const qs = search.toString();\n return qs.length > 0 ? `?${qs}` : \"\";\n}\n\nexport class ZennClient {\n private readonly baseUrl: string;\n private readonly fetcher: typeof fetch;\n private readonly headers: HeadersInit;\n\n constructor(options: ClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetcher = options.fetch ?? fetch.bind(globalThis);\n this.headers = options.headers ?? {};\n }\n\n private async request<T>(path: string, params?: object): Promise<T> {\n const url = `${this.baseUrl}${path}${buildQuery(params)}`;\n const res = await this.fetcher(url, {\n headers: {\n Accept: \"application/json\",\n ...this.headers,\n },\n });\n const text = await res.text();\n const data: unknown = text.length > 0 ? JSON.parse(text) : null;\n if (!res.ok) {\n throw new ZennApiError(res.status, data, `Zenn API request failed: ${res.status} ${res.statusText} (${url})`);\n }\n return data as T;\n }\n\n // ---------- Articles ----------\n\n listArticles(options: ListArticlesOptions = {}): Promise<ArticlesResponse> {\n return this.request<ArticlesResponse>(\"/api/articles\", options);\n }\n\n getArticle(slug: string): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(`/api/articles/${encodeURIComponent(slug)}`);\n }\n\n getArticleById(id: number): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(\"/api/articles\", { id });\n }\n\n async *iterArticles(options: Omit<ListArticlesOptions, \"page\"> = {}): AsyncGenerator<ArticleDetail, void, void> {\n let page = 1;\n while (true) {\n const res = await this.listArticles({ ...options, page });\n for (const item of res.articles) {\n const detail = await this.getArticle(item.slug);\n yield detail.article;\n }\n if (res.next_page === null || res.next_page === undefined) break;\n page = res.next_page;\n }\n }\n\n // ---------- Books ----------\n\n listBooks(options: ListBooksOptions = {}): Promise<BooksResponse> {\n return this.request<BooksResponse>(\"/api/books\", options);\n }\n\n getBook(slug: string): Promise<BookResponse> {\n return this.request<BookResponse>(`/api/books/${encodeURIComponent(slug)}`);\n }\n\n getChapter(id: number): Promise<ChapterResponse> {\n return this.request<ChapterResponse>(`/api/chapters/${id}`);\n }\n\n // ---------- Scraps ----------\n\n listScraps(options: ListScrapsOptions = {}): Promise<ScrapsResponse> {\n return this.request<ScrapsResponse>(\"/api/scraps\", options);\n }\n\n getScrap(slug: string): Promise<ScrapResponse> {\n return this.request<ScrapResponse>(`/api/scraps/${encodeURIComponent(slug)}`);\n }\n\n // ---------- Users ----------\n\n getUser(username: string): Promise<UserResponse> {\n return this.request<UserResponse>(`/api/users/${encodeURIComponent(username)}`);\n }\n\n getCurrentUser(): Promise<UserResponse> {\n return this.request<UserResponse>(\"/api/users/current\");\n }\n\n getUserFollowers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followers`, options);\n }\n\n getUserFollowingsUsers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followings/users`, options);\n }\n\n getUserFollowingsPublications(\n username: string,\n options: ListFollowersOptions = {},\n ): Promise<PublicationsMiniResponse> {\n return this.request<PublicationsMiniResponse>(\n `/api/users/${encodeURIComponent(username)}/followings/publications`,\n options,\n );\n }\n\n getUserComments(username: string, options: ListUsersCommentsOptions = {}): Promise<UserCommentsResponse> {\n return this.request<UserCommentsResponse>(`/api/users/${encodeURIComponent(username)}/comments`, options);\n }\n\n // ---------- Publications ----------\n\n getPublication(name: string): Promise<PublicationResponse> {\n return this.request<PublicationResponse>(`/api/publications/${encodeURIComponent(name)}`);\n }\n\n getPublicationFollowers(name: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/publications/${encodeURIComponent(name)}/followers`, options);\n }\n\n // ---------- Topics ----------\n\n listTopics(): Promise<TopicsResponse> {\n return this.request<TopicsResponse>(\"/api/topics\");\n }\n\n getTopic(name: string): Promise<TopicResponse> {\n return this.request<TopicResponse>(`/api/topics/${encodeURIComponent(name)}`);\n }\n\n // ---------- Search ----------\n\n search<TSource extends SearchSource>(\n options: SearchOptions & { source: TSource },\n ): Promise<SearchResponse<TSource>> {\n return this.request<SearchResponse<TSource>>(\"/api/search\", options);\n }\n\n // ---------- Events ----------\n\n listEvents(): Promise<Event[]> {\n return this.request<Event[]>(\"/api/events\");\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,IAAM,mBAAmB;AAAA;AAElB,MAAM,qBAAqB,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EAEA,WAAW,CAAC,QAAgB,MAAe,SAAiB;AAAA,IAC1D,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,SAAS;AAAA,IACd,KAAK,OAAO;AAAA;AAEhB;AAOA,SAAS,UAAU,CAAC,QAAoC;AAAA,EACtD,IAAI,CAAC;AAAA,IAAQ,OAAO;AAAA,EACpB,MAAM,SAAS,IAAI;AAAA,EACnB,YAAY,GAAG,MAAM,OAAO,QAAQ,MAAM,GAAG;AAAA,IAC3C,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM;AAAA,MAAI;AAAA,IAC/C,OAAO,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EACzB;AAAA,EACA,MAAM,KAAK,OAAO,SAAS;AAAA,EAC3B,OAAO,GAAG,SAAS,IAAI,IAAI,OAAO;AAAA;AAAA;AAG7B,MAAM,WAAW;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,UAAyB,CAAC,GAAG;AAAA,IACvC,KAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAAA,IACvE,KAAK,UAAU,QAAQ,SAAS;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "1EF2302271791DDE64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/index.js
CHANGED
|
@@ -30,7 +30,7 @@ class ZennClient {
|
|
|
30
30
|
headers;
|
|
31
31
|
constructor(options = {}) {
|
|
32
32
|
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
33
|
-
this.fetcher = options.fetch ?? fetch;
|
|
33
|
+
this.fetcher = options.fetch ?? fetch.bind(globalThis);
|
|
34
34
|
this.headers = options.headers ?? {};
|
|
35
35
|
}
|
|
36
36
|
async request(path, params) {
|
|
@@ -127,4 +127,4 @@ export {
|
|
|
127
127
|
ZennApiError
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
-
//# debugId=
|
|
130
|
+
//# debugId=7FEEDD2D6EB9174D64756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/client.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {\n ArticleDetail,\n ArticleResponse,\n ArticlesResponse,\n BookResponse,\n BooksResponse,\n ChapterResponse,\n ClientOptions,\n ListArticlesOptions,\n ListBooksOptions,\n ListFollowersOptions,\n ListScrapsOptions,\n ListUsersCommentsOptions,\n PublicationMini,\n PublicationResponse,\n ScrapsResponse,\n ScrapResponse,\n SearchOptions,\n SearchResponse,\n SearchSource,\n TopicResponse,\n TopicsResponse,\n UserCommentsResponse,\n UserResponse,\n UsersResponse,\n Event,\n} from \"./types.ts\";\n\nconst DEFAULT_BASE_URL = \"https://zenn.dev\";\n\nexport class ZennApiError extends Error {\n status: number;\n body: unknown;\n\n constructor(status: number, body: unknown, message: string) {\n super(message);\n this.name = \"ZennApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface PublicationsMiniResponse {\n publications: PublicationMini[];\n next_page: number | null;\n}\n\nfunction buildQuery(params: object | undefined): string {\n if (!params) return \"\";\n const search = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null || v === \"\") continue;\n search.set(k, String(v));\n }\n const qs = search.toString();\n return qs.length > 0 ? `?${qs}` : \"\";\n}\n\nexport class ZennClient {\n private readonly baseUrl: string;\n private readonly fetcher: typeof fetch;\n private readonly headers: HeadersInit;\n\n constructor(options: ClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetcher = options.fetch ?? fetch;\n this.headers = options.headers ?? {};\n }\n\n private async request<T>(path: string, params?: object): Promise<T> {\n const url = `${this.baseUrl}${path}${buildQuery(params)}`;\n const res = await this.fetcher(url, {\n headers: {\n Accept: \"application/json\",\n ...this.headers,\n },\n });\n const text = await res.text();\n const data: unknown = text.length > 0 ? JSON.parse(text) : null;\n if (!res.ok) {\n throw new ZennApiError(res.status, data, `Zenn API request failed: ${res.status} ${res.statusText} (${url})`);\n }\n return data as T;\n }\n\n // ---------- Articles ----------\n\n listArticles(options: ListArticlesOptions = {}): Promise<ArticlesResponse> {\n return this.request<ArticlesResponse>(\"/api/articles\", options);\n }\n\n getArticle(slug: string): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(`/api/articles/${encodeURIComponent(slug)}`);\n }\n\n getArticleById(id: number): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(\"/api/articles\", { id });\n }\n\n async *iterArticles(options: Omit<ListArticlesOptions, \"page\"> = {}): AsyncGenerator<ArticleDetail, void, void> {\n let page = 1;\n while (true) {\n const res = await this.listArticles({ ...options, page });\n for (const item of res.articles) {\n const detail = await this.getArticle(item.slug);\n yield detail.article;\n }\n if (res.next_page === null || res.next_page === undefined) break;\n page = res.next_page;\n }\n }\n\n // ---------- Books ----------\n\n listBooks(options: ListBooksOptions = {}): Promise<BooksResponse> {\n return this.request<BooksResponse>(\"/api/books\", options);\n }\n\n getBook(slug: string): Promise<BookResponse> {\n return this.request<BookResponse>(`/api/books/${encodeURIComponent(slug)}`);\n }\n\n getChapter(id: number): Promise<ChapterResponse> {\n return this.request<ChapterResponse>(`/api/chapters/${id}`);\n }\n\n // ---------- Scraps ----------\n\n listScraps(options: ListScrapsOptions = {}): Promise<ScrapsResponse> {\n return this.request<ScrapsResponse>(\"/api/scraps\", options);\n }\n\n getScrap(slug: string): Promise<ScrapResponse> {\n return this.request<ScrapResponse>(`/api/scraps/${encodeURIComponent(slug)}`);\n }\n\n // ---------- Users ----------\n\n getUser(username: string): Promise<UserResponse> {\n return this.request<UserResponse>(`/api/users/${encodeURIComponent(username)}`);\n }\n\n getCurrentUser(): Promise<UserResponse> {\n return this.request<UserResponse>(\"/api/users/current\");\n }\n\n getUserFollowers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followers`, options);\n }\n\n getUserFollowingsUsers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followings/users`, options);\n }\n\n getUserFollowingsPublications(\n username: string,\n options: ListFollowersOptions = {},\n ): Promise<PublicationsMiniResponse> {\n return this.request<PublicationsMiniResponse>(\n `/api/users/${encodeURIComponent(username)}/followings/publications`,\n options,\n );\n }\n\n getUserComments(username: string, options: ListUsersCommentsOptions = {}): Promise<UserCommentsResponse> {\n return this.request<UserCommentsResponse>(`/api/users/${encodeURIComponent(username)}/comments`, options);\n }\n\n // ---------- Publications ----------\n\n getPublication(name: string): Promise<PublicationResponse> {\n return this.request<PublicationResponse>(`/api/publications/${encodeURIComponent(name)}`);\n }\n\n getPublicationFollowers(name: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/publications/${encodeURIComponent(name)}/followers`, options);\n }\n\n // ---------- Topics ----------\n\n listTopics(): Promise<TopicsResponse> {\n return this.request<TopicsResponse>(\"/api/topics\");\n }\n\n getTopic(name: string): Promise<TopicResponse> {\n return this.request<TopicResponse>(`/api/topics/${encodeURIComponent(name)}`);\n }\n\n // ---------- Search ----------\n\n search<TSource extends SearchSource>(\n options: SearchOptions & { source: TSource },\n ): Promise<SearchResponse<TSource>> {\n return this.request<SearchResponse<TSource>>(\"/api/search\", options);\n }\n\n // ---------- Events ----------\n\n listEvents(): Promise<Event[]> {\n return this.request<Event[]>(\"/api/events\");\n }\n}\n"
|
|
5
|
+
"import type {\n ArticleDetail,\n ArticleResponse,\n ArticlesResponse,\n BookResponse,\n BooksResponse,\n ChapterResponse,\n ClientOptions,\n ListArticlesOptions,\n ListBooksOptions,\n ListFollowersOptions,\n ListScrapsOptions,\n ListUsersCommentsOptions,\n PublicationMini,\n PublicationResponse,\n ScrapsResponse,\n ScrapResponse,\n SearchOptions,\n SearchResponse,\n SearchSource,\n TopicResponse,\n TopicsResponse,\n UserCommentsResponse,\n UserResponse,\n UsersResponse,\n Event,\n} from \"./types.ts\";\n\nconst DEFAULT_BASE_URL = \"https://zenn.dev\";\n\nexport class ZennApiError extends Error {\n status: number;\n body: unknown;\n\n constructor(status: number, body: unknown, message: string) {\n super(message);\n this.name = \"ZennApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface PublicationsMiniResponse {\n publications: PublicationMini[];\n next_page: number | null;\n}\n\nfunction buildQuery(params: object | undefined): string {\n if (!params) return \"\";\n const search = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v === undefined || v === null || v === \"\") continue;\n search.set(k, String(v));\n }\n const qs = search.toString();\n return qs.length > 0 ? `?${qs}` : \"\";\n}\n\nexport class ZennClient {\n private readonly baseUrl: string;\n private readonly fetcher: typeof fetch;\n private readonly headers: HeadersInit;\n\n constructor(options: ClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.fetcher = options.fetch ?? fetch.bind(globalThis);\n this.headers = options.headers ?? {};\n }\n\n private async request<T>(path: string, params?: object): Promise<T> {\n const url = `${this.baseUrl}${path}${buildQuery(params)}`;\n const res = await this.fetcher(url, {\n headers: {\n Accept: \"application/json\",\n ...this.headers,\n },\n });\n const text = await res.text();\n const data: unknown = text.length > 0 ? JSON.parse(text) : null;\n if (!res.ok) {\n throw new ZennApiError(res.status, data, `Zenn API request failed: ${res.status} ${res.statusText} (${url})`);\n }\n return data as T;\n }\n\n // ---------- Articles ----------\n\n listArticles(options: ListArticlesOptions = {}): Promise<ArticlesResponse> {\n return this.request<ArticlesResponse>(\"/api/articles\", options);\n }\n\n getArticle(slug: string): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(`/api/articles/${encodeURIComponent(slug)}`);\n }\n\n getArticleById(id: number): Promise<ArticleResponse> {\n return this.request<ArticleResponse>(\"/api/articles\", { id });\n }\n\n async *iterArticles(options: Omit<ListArticlesOptions, \"page\"> = {}): AsyncGenerator<ArticleDetail, void, void> {\n let page = 1;\n while (true) {\n const res = await this.listArticles({ ...options, page });\n for (const item of res.articles) {\n const detail = await this.getArticle(item.slug);\n yield detail.article;\n }\n if (res.next_page === null || res.next_page === undefined) break;\n page = res.next_page;\n }\n }\n\n // ---------- Books ----------\n\n listBooks(options: ListBooksOptions = {}): Promise<BooksResponse> {\n return this.request<BooksResponse>(\"/api/books\", options);\n }\n\n getBook(slug: string): Promise<BookResponse> {\n return this.request<BookResponse>(`/api/books/${encodeURIComponent(slug)}`);\n }\n\n getChapter(id: number): Promise<ChapterResponse> {\n return this.request<ChapterResponse>(`/api/chapters/${id}`);\n }\n\n // ---------- Scraps ----------\n\n listScraps(options: ListScrapsOptions = {}): Promise<ScrapsResponse> {\n return this.request<ScrapsResponse>(\"/api/scraps\", options);\n }\n\n getScrap(slug: string): Promise<ScrapResponse> {\n return this.request<ScrapResponse>(`/api/scraps/${encodeURIComponent(slug)}`);\n }\n\n // ---------- Users ----------\n\n getUser(username: string): Promise<UserResponse> {\n return this.request<UserResponse>(`/api/users/${encodeURIComponent(username)}`);\n }\n\n getCurrentUser(): Promise<UserResponse> {\n return this.request<UserResponse>(\"/api/users/current\");\n }\n\n getUserFollowers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followers`, options);\n }\n\n getUserFollowingsUsers(username: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/users/${encodeURIComponent(username)}/followings/users`, options);\n }\n\n getUserFollowingsPublications(\n username: string,\n options: ListFollowersOptions = {},\n ): Promise<PublicationsMiniResponse> {\n return this.request<PublicationsMiniResponse>(\n `/api/users/${encodeURIComponent(username)}/followings/publications`,\n options,\n );\n }\n\n getUserComments(username: string, options: ListUsersCommentsOptions = {}): Promise<UserCommentsResponse> {\n return this.request<UserCommentsResponse>(`/api/users/${encodeURIComponent(username)}/comments`, options);\n }\n\n // ---------- Publications ----------\n\n getPublication(name: string): Promise<PublicationResponse> {\n return this.request<PublicationResponse>(`/api/publications/${encodeURIComponent(name)}`);\n }\n\n getPublicationFollowers(name: string, options: ListFollowersOptions = {}): Promise<UsersResponse> {\n return this.request<UsersResponse>(`/api/publications/${encodeURIComponent(name)}/followers`, options);\n }\n\n // ---------- Topics ----------\n\n listTopics(): Promise<TopicsResponse> {\n return this.request<TopicsResponse>(\"/api/topics\");\n }\n\n getTopic(name: string): Promise<TopicResponse> {\n return this.request<TopicResponse>(`/api/topics/${encodeURIComponent(name)}`);\n }\n\n // ---------- Search ----------\n\n search<TSource extends SearchSource>(\n options: SearchOptions & { source: TSource },\n ): Promise<SearchResponse<TSource>> {\n return this.request<SearchResponse<TSource>>(\"/api/search\", options);\n }\n\n // ---------- Events ----------\n\n listEvents(): Promise<Event[]> {\n return this.request<Event[]>(\"/api/events\");\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AA4BA,IAAM,mBAAmB;AAAA;AAElB,MAAM,qBAAqB,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EAEA,WAAW,CAAC,QAAgB,MAAe,SAAiB;AAAA,IAC1D,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,SAAS;AAAA,IACd,KAAK,OAAO;AAAA;AAEhB;AAOA,SAAS,UAAU,CAAC,QAAoC;AAAA,EACtD,IAAI,CAAC;AAAA,IAAQ,OAAO;AAAA,EACpB,MAAM,SAAS,IAAI;AAAA,EACnB,YAAY,GAAG,MAAM,OAAO,QAAQ,MAAM,GAAG;AAAA,IAC3C,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM;AAAA,MAAI;AAAA,IAC/C,OAAO,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EACzB;AAAA,EACA,MAAM,KAAK,OAAO,SAAS;AAAA,EAC3B,OAAO,GAAG,SAAS,IAAI,IAAI,OAAO;AAAA;AAAA;AAG7B,MAAM,WAAW;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,UAAyB,CAAC,GAAG;AAAA,IACvC,KAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAAA,IACvE,KAAK,UAAU,QAAQ,SAAS;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AA4BA,IAAM,mBAAmB;AAAA;AAElB,MAAM,qBAAqB,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EAEA,WAAW,CAAC,QAAgB,MAAe,SAAiB;AAAA,IAC1D,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,SAAS;AAAA,IACd,KAAK,OAAO;AAAA;AAEhB;AAOA,SAAS,UAAU,CAAC,QAAoC;AAAA,EACtD,IAAI,CAAC;AAAA,IAAQ,OAAO;AAAA,EACpB,MAAM,SAAS,IAAI;AAAA,EACnB,YAAY,GAAG,MAAM,OAAO,QAAQ,MAAM,GAAG;AAAA,IAC3C,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM;AAAA,MAAI;AAAA,IAC/C,OAAO,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,EACzB;AAAA,EACA,MAAM,KAAK,OAAO,SAAS;AAAA,EAC3B,OAAO,GAAG,SAAS,IAAI,IAAI,OAAO;AAAA;AAAA;AAG7B,MAAM,WAAW;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,UAAyB,CAAC,GAAG;AAAA,IACvC,KAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AAAA,IACvE,KAAK,UAAU,QAAQ,SAAS,MAAM,KAAK,UAAU;AAAA,IACrD,KAAK,UAAU,QAAQ,WAAW,CAAC;AAAA;AAAA,OAGvB,QAAU,CAAC,MAAc,QAA6B;AAAA,IAClE,MAAM,MAAM,GAAG,KAAK,UAAU,OAAO,WAAW,MAAM;AAAA,IACtD,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;AAAA,MAClC,SAAS;AAAA,QACP,QAAQ;AAAA,WACL,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AAAA,IACD,MAAM,OAAO,MAAM,IAAI,KAAK;AAAA,IAC5B,MAAM,OAAgB,KAAK,SAAS,IAAI,KAAK,MAAM,IAAI,IAAI;AAAA,IAC3D,IAAI,CAAC,IAAI,IAAI;AAAA,MACX,MAAM,IAAI,aAAa,IAAI,QAAQ,MAAM,4BAA4B,IAAI,UAAU,IAAI,eAAe,MAAM;AAAA,IAC9G;AAAA,IACA,OAAO;AAAA;AAAA,EAKT,YAAY,CAAC,UAA+B,CAAC,GAA8B;AAAA,IACzE,OAAO,KAAK,QAA0B,iBAAiB,OAAO;AAAA;AAAA,EAGhE,UAAU,CAAC,MAAwC;AAAA,IACjD,OAAO,KAAK,QAAyB,iBAAiB,mBAAmB,IAAI,GAAG;AAAA;AAAA,EAGlF,cAAc,CAAC,IAAsC;AAAA,IACnD,OAAO,KAAK,QAAyB,iBAAiB,EAAE,GAAG,CAAC;AAAA;AAAA,SAGvD,YAAY,CAAC,UAA6C,CAAC,GAA8C;AAAA,IAC9G,IAAI,OAAO;AAAA,IACX,OAAO,MAAM;AAAA,MACX,MAAM,MAAM,MAAM,KAAK,aAAa,KAAK,SAAS,KAAK,CAAC;AAAA,MACxD,WAAW,QAAQ,IAAI,UAAU;AAAA,QAC/B,MAAM,SAAS,MAAM,KAAK,WAAW,KAAK,IAAI;AAAA,QAC9C,MAAM,OAAO;AAAA,MACf;AAAA,MACA,IAAI,IAAI,cAAc,QAAQ,IAAI,cAAc;AAAA,QAAW;AAAA,MAC3D,OAAO,IAAI;AAAA,IACb;AAAA;AAAA,EAKF,SAAS,CAAC,UAA4B,CAAC,GAA2B;AAAA,IAChE,OAAO,KAAK,QAAuB,cAAc,OAAO;AAAA;AAAA,EAG1D,OAAO,CAAC,MAAqC;AAAA,IAC3C,OAAO,KAAK,QAAsB,cAAc,mBAAmB,IAAI,GAAG;AAAA;AAAA,EAG5E,UAAU,CAAC,IAAsC;AAAA,IAC/C,OAAO,KAAK,QAAyB,iBAAiB,IAAI;AAAA;AAAA,EAK5D,UAAU,CAAC,UAA6B,CAAC,GAA4B;AAAA,IACnE,OAAO,KAAK,QAAwB,eAAe,OAAO;AAAA;AAAA,EAG5D,QAAQ,CAAC,MAAsC;AAAA,IAC7C,OAAO,KAAK,QAAuB,eAAe,mBAAmB,IAAI,GAAG;AAAA;AAAA,EAK9E,OAAO,CAAC,UAAyC;AAAA,IAC/C,OAAO,KAAK,QAAsB,cAAc,mBAAmB,QAAQ,GAAG;AAAA;AAAA,EAGhF,cAAc,GAA0B;AAAA,IACtC,OAAO,KAAK,QAAsB,oBAAoB;AAAA;AAAA,EAGxD,gBAAgB,CAAC,UAAkB,UAAgC,CAAC,GAA2B;AAAA,IAC7F,OAAO,KAAK,QAAuB,cAAc,mBAAmB,QAAQ,eAAe,OAAO;AAAA;AAAA,EAGpG,sBAAsB,CAAC,UAAkB,UAAgC,CAAC,GAA2B;AAAA,IACnG,OAAO,KAAK,QAAuB,cAAc,mBAAmB,QAAQ,sBAAsB,OAAO;AAAA;AAAA,EAG3G,6BAA6B,CAC3B,UACA,UAAgC,CAAC,GACE;AAAA,IACnC,OAAO,KAAK,QACV,cAAc,mBAAmB,QAAQ,6BACzC,OACF;AAAA;AAAA,EAGF,eAAe,CAAC,UAAkB,UAAoC,CAAC,GAAkC;AAAA,IACvG,OAAO,KAAK,QAA8B,cAAc,mBAAmB,QAAQ,cAAc,OAAO;AAAA;AAAA,EAK1G,cAAc,CAAC,MAA4C;AAAA,IACzD,OAAO,KAAK,QAA6B,qBAAqB,mBAAmB,IAAI,GAAG;AAAA;AAAA,EAG1F,uBAAuB,CAAC,MAAc,UAAgC,CAAC,GAA2B;AAAA,IAChG,OAAO,KAAK,QAAuB,qBAAqB,mBAAmB,IAAI,eAAe,OAAO;AAAA;AAAA,EAKvG,UAAU,GAA4B;AAAA,IACpC,OAAO,KAAK,QAAwB,aAAa;AAAA;AAAA,EAGnD,QAAQ,CAAC,MAAsC;AAAA,IAC7C,OAAO,KAAK,QAAuB,eAAe,mBAAmB,IAAI,GAAG;AAAA;AAAA,EAK9E,MAAoC,CAClC,SACkC;AAAA,IAClC,OAAO,KAAK,QAAiC,eAAe,OAAO;AAAA;AAAA,EAKrE,UAAU,GAAqB;AAAA,IAC7B,OAAO,KAAK,QAAiB,aAAa;AAAA;AAE9C;",
|
|
8
|
+
"debugId": "7FEEDD2D6EB9174D64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|