Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/index.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export {

export * from "./ranking-history.js";
export * from "./params.js";
export type { NarouParams } from "./narou.js";
export type { ExecuteOptions, NarouParams } from "./narou.js";
export * from "./narou-search-results.js";
export type * from "./narou-ranking-results.js";
export * from "./search-builder.js";
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export async function rankingHistory(
if (Array.isArray(result)) {
return result.map(formatRankingHistory);
} else {
throw new Error(result);
throw result;
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/narou-fetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { unzipp } from "./util/unzipp.js";
import NarouNovel from "./narou.js";
import type { NarouParams } from "./narou.js";
import type { ExecuteOptions, NarouParams } from "./narou.js";

type Fetch = typeof fetch;

Expand All @@ -18,7 +18,8 @@ export default class NarouNovelFetch extends NarouNovel {

protected async execute<T>(
params: NarouParams,
endpoint: string
endpoint: string,
options?: ExecuteOptions
): Promise<T> {
const query = { ...params, out: "json" };

Expand All @@ -36,7 +37,7 @@ export default class NarouNovelFetch extends NarouNovel {
}
});

const res = await (this.fetch ?? fetch)(url);
const res = await (this.fetch ?? fetch)(url, options?.fetchOptions);

if (!query.gzip) {
return (await res.json()) as T;
Expand Down
5 changes: 3 additions & 2 deletions src/narou-jsonp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import NarouNovel from "./narou.js";
import type { NarouParams } from "./narou.js";
import type { ExecuteOptions, NarouParams } from "./narou.js";
import { jsonp } from "./util/jsonp.js";

/**
Expand All @@ -8,7 +8,8 @@ import { jsonp } from "./util/jsonp.js";
export default class NarouNovelJsonp extends NarouNovel {
protected async execute<T>(
params: NarouParams,
endpoint: string
endpoint: string,
_options?: ExecuteOptions
): Promise<T> {
const query = { ...params, out: "jsonp" };
query.gzip = 0;
Expand Down
56 changes: 43 additions & 13 deletions src/narou.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export type NarouParams =
| RankingHistoryParams
| UserSearchParams;

export type ExecuteOptions = {
Comment on lines 23 to +24
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc documentation for the ExecuteOptions type. As a public API type that's exported in index.common.ts, it should have documentation explaining its purpose and usage.

Add JSDoc:

/**
 * なろう小説APIの実行オプション
 */
export type ExecuteOptions = {
  /**
   * fetch APIに渡すオプション (Node.js環境でのみ使用可能)
   */
  fetchOptions?: RequestInit;
};
Suggested change
export type ExecuteOptions = {
/**
* なろう小説APIの実行オプション
*/
export type ExecuteOptions = {
/**
* fetch APIに渡すオプション (Node.js環境でのみ使用可能)
*/

Copilot uses AI. Check for mistakes.
fetchOptions?: RequestInit;
};

/**
* なろう小説APIへのリクエストを実行する
* @class NarouNovel
Expand All @@ -35,7 +39,8 @@ export default abstract class NarouNovel {
*/
protected abstract execute<T>(
params: NarouParams,
endpoint: string
endpoint: string,
options?: ExecuteOptions
): Promise<T>;
Comment on lines 40 to 44
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add:

/**
 * なろうAPIへのAPIリクエストを実行する
 * @param params クエリパラメータ
 * @param endpoint APIエンドポイント
 * @param options 実行オプション(fetchオプションなど)
 * @returns 実行結果
 */

Copilot uses AI. Check for mistakes.

/**
Expand All @@ -46,9 +51,13 @@ export default abstract class NarouNovel {
*/
protected async executeSearch<T extends keyof NarouSearchResult>(
params: SearchParams,
endpoint = "https://api.syosetu.com/novelapi/api/"
endpoint = "https://api.syosetu.com/novelapi/api/",
options?: ExecuteOptions
): Promise<NarouSearchResults<NarouSearchResult, T>> {
Comment on lines 52 to 56
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add:

/**
 * APIへの検索リクエストを実行する
 * @param params クエリパラメータ
 * @param endpoint APIエンドポイント
 * @param options 実行オプション(fetchオプションなど)
 * @returns 検索結果
 */

Copilot uses AI. Check for mistakes.
return new NarouSearchResults(await this.execute(params, endpoint), params);
return new NarouSearchResults(
await this.execute(params, endpoint, options),
params
);
}

/**
Expand All @@ -58,11 +67,13 @@ export default abstract class NarouNovel {
* @see https://dev.syosetu.com/man/api/
*/
async executeNovel<T extends keyof NarouSearchResult>(
params: SearchParams
params: SearchParams,
options?: ExecuteOptions
): Promise<NarouSearchResults<NarouSearchResult, T>> {
Comment on lines 69 to 72
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add after the @param params line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
return await this.executeSearch(
params,
"https://api.syosetu.com/novelapi/api/"
"https://api.syosetu.com/novelapi/api/",
options
);
}

Expand All @@ -73,11 +84,13 @@ export default abstract class NarouNovel {
* @see https://dev.syosetu.com/xman/api/
*/
async executeNovel18<T extends keyof NarouSearchResult>(
params: SearchParams
params: SearchParams,
options?: ExecuteOptions
): Promise<NarouSearchResults<NarouSearchResult, T>> {
Comment on lines 86 to 89
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add after the @param params line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
return await this.executeSearch(
params,
"https://api.syosetu.com/novel18api/api/"
"https://api.syosetu.com/novel18api/api/",
options
);
}

Expand All @@ -87,8 +100,15 @@ export default abstract class NarouNovel {
* @returns ランキング結果
* @see https://dev.syosetu.com/man/rankapi/
*/
async executeRanking(params: RankingParams): Promise<NarouRankingResult[]> {
return await this.execute(params, "https://api.syosetu.com/rank/rankget/");
async executeRanking(
params: RankingParams,
options?: ExecuteOptions
): Promise<NarouRankingResult[]> {
Comment on lines +103 to +106
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add after the @param params line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
return await this.execute(
params,
"https://api.syosetu.com/rank/rankget/",
options
);
}

/**
Expand All @@ -98,9 +118,14 @@ export default abstract class NarouNovel {
* @see https://dev.syosetu.com/man/rankinapi/
*/
async executeRankingHistory(
params: RankingHistoryParams
params: RankingHistoryParams,
options?: ExecuteOptions
): Promise<RankingHistoryRawResult[]> {
Comment on lines 120 to 123
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add after the @param params line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
return await this.execute(params, "https://api.syosetu.com/rank/rankin/");
return await this.execute(
params,
"https://api.syosetu.com/rank/rankin/",
options
);
}

/**
Expand All @@ -110,10 +135,15 @@ export default abstract class NarouNovel {
* @see https://dev.syosetu.com/man/userapi/
*/
async executeUserSearch<T extends keyof UserSearchResult>(
params: UserSearchParams
params: UserSearchParams,
options?: ExecuteOptions
): Promise<NarouSearchResults<UserSearchResult, T>> {
Comment on lines 137 to 140
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add after the @param params line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
return new NarouSearchResults<UserSearchResult, T>(
await this.execute(params, "https://api.syosetu.com/userapi/api/"),
await this.execute(
params,
"https://api.syosetu.com/userapi/api/",
options
),
params
);
}
Expand Down
24 changes: 14 additions & 10 deletions src/ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Fields,
} from "./params.js";
import type NarouNovel from "./narou.js";
import type { ExecuteOptions } from "./narou.js";
import type { SearchResultFields } from "./narou-search-results.js";
import { addDays, formatDate } from "./util/date.js";

Expand Down Expand Up @@ -111,18 +112,18 @@ export default class RankingBuilder {
* @returns {Promise<NarouRankingResult[]>} ランキング結果の配列
* @see https://dev.syosetu.com/man/rankapi/#output
*/
execute(): Promise<NarouRankingResult[]> {
execute(options?: ExecuteOptions): Promise<NarouRankingResult[]> {
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Update the JSDoc to:

/**
 * 設定されたパラメータに基づき、なろう小説ランキングAPIへのリクエストを実行します。
 *
 * 返される結果には、Nコード、ポイント、順位が含まれます。
 * @param options 実行オプション(fetchオプションなど)
 * @returns {Promise<NarouRankingResult[]>} ランキング結果の配列
 * @see https://dev.syosetu.com/man/rankapi/#output
 */

Copilot uses AI. Check for mistakes.
const date = formatDate(this.date$);
this.set({ rtype: `${date}-${this.type$}` });
return this.api.executeRanking(this.params as RankingParams);
return this.api.executeRanking(this.params as RankingParams, options);
}

/**
* ランキングAPIを実行し、取得したNコードを元になろう小説APIで詳細情報を取得して結合します。
*/
async executeWithFields(): Promise<
RankingResult<DefaultSearchResultFields>[]
>;
async executeWithFields(
options?: ExecuteOptions
): Promise<RankingResult<DefaultSearchResultFields>[]>;
Comment on lines +124 to +126
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. While this is an overload signature without a body, it should still document the parameter for API consumers.

Add @param documentation:

/**
 * ランキングAPIを実行し、取得したNコードを元になろう小説APIで詳細情報を取得して結合します。
 * @param options 実行オプション(fetchオプションなど)
 */

Copilot uses AI. Check for mistakes.
/**
* ランキングAPIを実行し、取得したNコードを元になろう小説APIで詳細情報を取得して結合します。
*
Expand All @@ -131,7 +132,8 @@ export default class RankingBuilder {
* @returns {Promise<RankingResult<SearchResultFields<TFields>>[]>} 詳細情報を含むランキング結果の配列
*/
async executeWithFields<TFields extends Fields>(
fields: TFields | TFields[]
fields: TFields | TFields[],
options?: ExecuteOptions
): Promise<RankingResult<SearchResultFields<TFields>>[]>;
Comment on lines 134 to 137
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add @param documentation after the @param fields line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
/**
* ランキングAPIを実行し、取得したNコードを元になろう小説APIで詳細情報を取得して結合します。
Expand All @@ -141,7 +143,8 @@ export default class RankingBuilder {
*/
async executeWithFields(
fields: never[],
opt: OptionalFields | OptionalFields[]
opt: OptionalFields | OptionalFields[],
options?: ExecuteOptions
): Promise<RankingResult<DefaultSearchResultFields | "weekly_unique">[]>;
Comment on lines 144 to 148
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Add @param documentation after the @param opt line:

 * @param options 実行オプション(fetchオプションなど)

Copilot uses AI. Check for mistakes.
/**
* ランキングAPIを実行し、取得したNコードを元になろう小説APIで詳細情報を取得して結合します。
Expand Down Expand Up @@ -169,9 +172,10 @@ export default class RankingBuilder {
TOpt extends OptionalFields | undefined = undefined
>(
fields: TFields | TFields[] = [],
opt?: TOpt
opt?: TOpt,
options?: ExecuteOptions
): Promise<RankingResult<SearchResultFields<TFields>>[]> {
const ranking = await this.execute();
const ranking = await this.execute(options);
Comment on lines 174 to +178

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge executeWithFields drops ExecuteOptions

executeWithFields advertises overloads that accept an ExecuteOptions bag either as the only argument or as the second argument, but the implementation still treats the second parameter as opt and only forwards the third parameter to execute. If a caller passes ExecuteOptions (with fetchOptions) to rank-with-fields—e.g., executeWithFields(options) or executeWithFields(fields, options)—the options object is instead consumed as fields/opt (polluting the query) and never reaches execute or builder.execute, so the new fetch options support is broken for this helper.

Useful? React with 👍 / 👎.

const fields$ = Array.isArray(fields)
? fields.length == 0
? []
Expand All @@ -186,7 +190,7 @@ export default class RankingBuilder {
}
builder.ncode(rankingNcodes);
builder.limit(ranking.length);
const result = await builder.execute();
const result = await builder.execute(options);

return ranking.map<
RankingResult<
Expand Down
7 changes: 5 additions & 2 deletions src/search-builder-r18.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
SearchResultR18Fields,
SearchResultOptionalFields,
} from "./narou-search-results.js";
import type { ExecuteOptions } from "./narou.js";
import type {
R18Site,
SearchResultFieldNames,
Expand All @@ -30,8 +31,10 @@ export default class SearchBuilderR18<
* @override
* @returns {Promise<NarouSearchResults>} 検索結果
*/
execute(): Promise<NarouSearchResults<NarouSearchResult, T | TOpt>> {
return this.api.executeNovel18(this.params);
execute(
options?: ExecuteOptions
): Promise<NarouSearchResults<NarouSearchResult, T | TOpt>> {
Comment on lines +34 to +36
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Update the JSDoc to:

/**
 * なろう小説APIへの検索リクエストを実行する
 * @override
 * @param options 実行オプション(fetchオプションなど)
 * @returns {Promise<NarouSearchResults>} 検索結果
 */

Copilot uses AI. Check for mistakes.
return this.api.executeNovel18(this.params, options);
}

/**
Expand Down
7 changes: 5 additions & 2 deletions src/search-builder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type NarouNovel from "./narou.js";
import type { ExecuteOptions } from "./narou.js";
import type {
NarouSearchResult,
SearchResultFields,
Expand Down Expand Up @@ -474,8 +475,10 @@ export abstract class NovelSearchBuilderBase<
* なろう小説APIへの検索リクエストを実行する
* @returns {Promise<NarouSearchResults>} 検索結果
*/
execute(): Promise<NarouSearchResults<NarouSearchResult, T>> {
return this.api.executeNovel(this.params);
execute(options?: ExecuteOptions): Promise<
NarouSearchResults<NarouSearchResult, T>
> {
Comment on lines +478 to +480
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Update the JSDoc to:

/**
 * なろう小説APIへの検索リクエストを実行する
 * @param options 実行オプション(fetchオプションなど)
 * @returns {Promise<NarouSearchResults>} 検索結果
 */

Copilot uses AI. Check for mistakes.
return this.api.executeNovel(this.params, options);
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/user-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
} from "./narou-search-results.js";
import type { UserFields, UserOrder, UserSearchParams } from "./params.js";
import { SearchBuilderBase } from "./search-builder.js";
import type { ExecuteOptions } from "./narou.js";

/**
* なろうユーザ検索API
Expand Down Expand Up @@ -104,7 +105,12 @@ export default class UserSearchBuilder<
* なろう小説APIへのリクエストを実行する
* @returns ランキング
*/
execute(): Promise<NarouSearchResults<UserSearchResult, TField>> {
return this.api.executeUserSearch(this.params as UserSearchParams);
execute(
options?: ExecuteOptions
): Promise<NarouSearchResults<UserSearchResult, TField>> {
Comment on lines +108 to +110
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing JSDoc @param documentation for the new options parameter. The JSDoc should be updated to document this parameter.

Update the JSDoc to:

/**
 * なろう小説APIへのリクエストを実行する
 * @param options 実行オプション(fetchオプションなど)
 * @returns ランキング
 */

Copilot uses AI. Check for mistakes.
return this.api.executeUserSearch(
this.params as UserSearchParams,
options
);
}
}
20 changes: 20 additions & 0 deletions test/narou-fetch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,26 @@ describe('NarouNovelFetch', () => {
expect(result).toEqual(mockData);
});

it('should pass fetch options to fetch implementation', async () => {
const customFetchMock = vi.fn().mockResolvedValue({
json: vi.fn().mockResolvedValue(mockData)
});

const narouFetch = new NarouNovelFetch(customFetchMock);

// @ts-expect-error - Accessing protected method for testing
await narouFetch.execute(
{ gzip: 0 },
'https://api.example.com',
{ fetchOptions: { method: 'POST', headers: { 'X-Test': '1' } } }
);

expect(customFetchMock).toHaveBeenCalledWith(
new URL('https://api.example.com/?out=json'),
{ method: 'POST', headers: { 'X-Test': '1' } }
);
});

it('should set gzip to 5 when undefined', async () => {
// URLパラメータをキャプチャするモック
const requestSpy = vi.fn();
Expand Down
Loading