{"version":3,"sources":["../src/narou.ts","../src/narou-search-results.ts"],"sourcesContent":["import type { NarouRankingResult } from \"./narou-ranking-results.js\";\nimport NarouSearchResults from \"./narou-search-results.js\";\nimport type {\n  NarouSearchResult,\n  UserSearchResult,\n} from \"./narou-search-results.js\";\nimport type {\n  RankingHistoryParams,\n  RankingParams,\n  SearchParams,\n  UserSearchParams,\n} from \"./params.js\";\nimport type { RankingHistoryRawResult } from \"./ranking-history.js\";\n\n/**\n * なろう小説APIへのリクエストパラメータ\n */\nexport type NarouParams =\n  | SearchParams\n  | RankingParams\n  | RankingHistoryParams\n  | UserSearchParams;\n\n/**\n * なろう小説APIへのリクエストを実行する\n * @class NarouNovel\n * @private\n */\nexport default abstract class NarouNovel {\n  /**\n   * なろうAPIへのAPIリクエストを実行する\n   * @param params クエリパラメータ\n   * @param endpoint APIエンドポイント\n   * @returns 実行結果\n   */\n  protected abstract execute<T>(\n    params: NarouParams,\n    endpoint: string\n  ): Promise<T>;\n\n  /**\n   * APIへの検索リクエストを実行する\n   * @param params クエリパラメータ\n   * @param endpoint APIエンドポイント\n   * @returns 検索結果\n   */\n  protected async executeSearch<T extends keyof NarouSearchResult>(\n    params: SearchParams,\n    endpoint = \"https://api.syosetu.com/novelapi/api/\"\n  ): Promise<NarouSearchResults<NarouSearchResult, T>> {\n    return new NarouSearchResults(await this.execute(params, endpoint), params);\n  }\n\n  /**\n   * 小説APIへの検索リクエストを実行する\n   * @param params クエリパラメータ\n   * @returns 検索結果\n   * @see https://dev.syosetu.com/man/api/\n   */\n  async executeNovel<T extends keyof NarouSearchResult>(\n    params: SearchParams\n  ): Promise<NarouSearchResults<NarouSearchResult, T>> {\n    return await this.executeSearch(\n      params,\n      \"https://api.syosetu.com/novelapi/api/\"\n    );\n  }\n\n  /**\n   * R18小説APIへの検索リクエストを実行する\n   * @param params クエリパラメータ\n   * @returns 検索結果\n   * @see https://dev.syosetu.com/xman/api/\n   */\n  async executeNovel18<T extends keyof NarouSearchResult>(\n    params: SearchParams\n  ): Promise<NarouSearchResults<NarouSearchResult, T>> {\n    return await this.executeSearch(\n      params,\n      \"https://api.syosetu.com/novel18api/api/\"\n    );\n  }\n\n  /**\n   * ランキングAPIへのリクエストを実行する\n   * @param params クエリパラメータ\n   * @returns ランキング結果\n   * @see https://dev.syosetu.com/man/rankapi/\n   */\n  async executeRanking(params: RankingParams): Promise<NarouRankingResult[]> {\n    return await this.execute(params, \"https://api.syosetu.com/rank/rankget/\");\n  }\n\n  /**\n   * 殿堂入りAPiへのリクエストを実行する\n   * @param params クエリパラメータ\n   * @returns ランキング履歴結果\n   * @see https://dev.syosetu.com/man/rankinapi/\n   */\n  async executeRankingHistory(\n    params: RankingHistoryParams\n  ): Promise<RankingHistoryRawResult[]> {\n    return await this.execute(params, \"https://api.syosetu.com/rank/rankin/\");\n  }\n\n  /**\n   * ユーザー検索APIへのリクエストを実行する\n   * @param params クエリパラメータ\n   * @returns 検索結果\n   * @see https://dev.syosetu.com/man/userapi/\n   */\n  async executeUserSearch<T extends keyof UserSearchResult>(\n    params: UserSearchParams\n  ): Promise<NarouSearchResults<UserSearchResult, T>> {\n    return new NarouSearchResults<UserSearchResult, T>(\n      await this.execute(params, \"https://api.syosetu.com/userapi/api/\"),\n      params\n    );\n  }\n}\n","import type {\n  BooleanNumber as BooleanNumber,\n  Genre,\n  R18Site,\n  SearchParams,\n  Fields,\n  BigGenre,\n  R18Fields,\n  OptionalFields,\n  UserFields,\n  UserSearchParams,\n} from \"./params.js\";\n\n/**\n * なろう小説API検索結果\n */\nexport default class NarouSearchResults<T, TKey extends keyof T> {\n  /**\n   * 検索結果数\n   */\n  allcount: number;\n  /**\n   * 結果表示上限数\n   */\n  limit: number;\n  /**\n   * 結果表示開始数\n   */\n  start: number;\n  /**\n   * 結果表示の現在ページ(=start/limit)\n   */\n  page: number;\n  /**\n   * 今回取得できた検索結果の数\n   */\n  length: number;\n  /**\n   * 検索結果\n   */\n  values: readonly Pick<T, TKey>[];\n\n  /**\n   * @constractor\n   * @private\n   */\n  constructor(\n    [header, ...result]: [{ allcount: number }, ...Pick<T, TKey>[]],\n    params: SearchParams | UserSearchParams\n  ) {\n    const count = header.allcount;\n    const limit = params.lim ?? 20;\n    const start = params.st ?? 0;\n\n    this.allcount = count;\n    this.limit = limit;\n    this.start = start;\n    this.page = start / limit;\n    this.length = result.length;\n    this.values = result;\n  }\n}\n\n/**\n * 小説情報\n * @see https://dev.syosetu.com/man/api/#output\n * @see https://dev.syosetu.com/xman/api/#output\n */\nexport interface NarouSearchResult {\n  /** 小説名 */\n  title: string;\n  /** Nコード */\n  ncode: string;\n  /** 作者のユーザID(数値) */\n  userid: number;\n  /** 作者名 */\n  writer: string;\n  /** 小説のあらすじ */\n  story: string;\n  /** 掲載サイト */\n  nocgenre: R18Site;\n  /** 大ジャンル */\n  biggenre: BigGenre;\n  /** ジャンル */\n  genre: Genre;\n  /** キーワード */\n  keyword: string;\n  /** 初回掲載日 YYYY-MM-DD HH:MM:SSの形式 */\n  general_firstup: string;\n  /** 最終掲載日 YYYY-MM-DD HH:MM:SSの形式 */\n  general_lastup: string;\n  /** 連載の場合は1、短編の場合は2 */\n  novel_type: NovelType;\n  /** 連載の場合は1、短編の場合は2 */\n  noveltype: NovelType;\n  /** 短編小説と完結済小説は0となっています。連載中は1です。 */\n  end: End;\n  /** 全掲載話数です。短編の場合は1です。 */\n  general_all_no: number;\n  /** 小説文字数です。スペースや改行は文字数としてカウントしません。 */\n  length: number;\n  /** 読了時間(分単位)です。読了時間は小説文字数÷500を切り上げした数値です。 */\n  time: number;\n  /** 長期連載中は1、それ以外は0です。 */\n  isstop: BooleanNumber;\n  /** 登録必須キーワードに「R15」が含まれる場合は1、それ以外は0です。 */\n  isr15: BooleanNumber;\n  /** 登録必須キーワードに「ボーイズラブ」が含まれる場合は1、それ以外は0です。 */\n  isbl: BooleanNumber;\n  /** 登録必須キーワードに「ガールズラブ」が含まれる場合は1、それ以外は0です。 */\n  isgl: BooleanNumber;\n  /** 登録必須キーワードに「残酷な描写あり」が含まれる場合は1、それ以外は0です。 */\n  iszankoku: BooleanNumber;\n  /** 登録必須キーワードに「異世界転生」が含まれる場合は1、それ以外は0です。 */\n  istensei: BooleanNumber;\n  /** 登録必須キーワードに「異世界転移」が含まれる場合は1、それ以外は0です。 */\n  istenni: BooleanNumber;\n  /** 総合得点(=(ブックマーク数×2)+評価点) */\n  global_point: number;\n  /**\n   * 日間ポイント\n   * ランキング集計時点から過去24時間以内で新たに登録されたブックマークや評価が対象\n   */\n  daily_point: number;\n  /**\n   * 週間ポイント\n   * ランキング集計時点から過去7日以内で新たに登録されたブックマークや評価が対象\n   */\n  weekly_point: number;\n  /**\n   * 月間ポイント\n   * ランキング集計時点から過去30日以内で新たに登録されたブックマークや評価が対象\n   */\n  monthly_point: number;\n  /**\n   * 四半期ポイント\n   * ランキング集計時点から過去90日以内で新たに登録されたブックマークや評価が対象\n   */\n  quarter_point: number;\n  /**\n   * 年間ポイント\n   * ランキング集計時点から過去365日以内で新たに登録されたブックマークや評価が対象\n   */\n  yearly_point: number;\n  /** ブックマーク数 */\n  fav_novel_cnt: number;\n  /** 感想数 */\n  impression_cnt: number;\n  /** レビュー数 */\n  review_cnt: number;\n  /** 評価ポイント */\n  all_point: number;\n  /** 評価者数 */\n  all_hyoka_cnt: number;\n  /** 挿絵の数 */\n  sasie_cnt: number;\n  /**\n   * 会話率\n   * @see https://dev.syosetu.com/man/kaiwa/\n   */\n  kaiwaritu: number;\n  /**\n   * 小説の更新日時\n   */\n  novelupdated_at: string;\n  /**\n   * 最終更新日時\n   * システム用で小説更新時とは関係ありません\n   */\n  updated_at: string;\n  /** 週間ユニークユーザー数 */\n  weekly_unique: number;\n}\n\n/**\n * ユーザ情報\n * @see https://dev.syosetu.com/man/userapi/#output\n */\nexport interface UserSearchResult {\n  /** ユーザID */\n  userid: number;\n  /** ユーザ名 */\n  name: string;\n  /** ユーザ名のフリガナ */\n  yomikata: string;\n  /**\n   * ユーザ名のフリガナの頭文字\n   * ひらがな以外の場合はnullまたは空文字となります。\n   */\n  name1st: string;\n  /** 小説投稿数 */\n  novel_cnt: number;\n  /** レビュー投稿数 */\n  review_cnt: number;\n  /**\n   * 小説累計文字数\n   * スペースや改行は文字数としてカウントしません。\n   */\n  novel_length: number;\n  /**\n   * 総合評価ポイントの合計\n   * 投稿済小説でそれぞれ獲得した総合評価ポイントの合計です。\n   */\n  sum_global_point: number;\n}\n\n/**\n * noveltype/novel_typeの値ヘルパー\n */\nexport const NovelType = {\n  /** 連載 */\n  Rensai: 1,\n  /** 短編 */\n  Tanpen: 2,\n} as const;\nexport type NovelType = typeof NovelType[keyof typeof NovelType];\n\n/**\n * endの値ヘルパー\n */\nexport const End = {\n  /** 短編小説と完結済小説 */\n  KanketsuOrTanpen: 0,\n  /** 連載中 */\n  Rensai: 1,\n} as const;\nexport type End = typeof End[keyof typeof End];\n\nexport type SearchResultFields<T extends Fields> = {\n  [K in keyof typeof Fields]: typeof Fields[K] extends T ? K : never;\n}[keyof typeof Fields];\n\nexport type SearchResultOptionalFields<T extends OptionalFields> = {\n  [K in keyof typeof OptionalFields]: typeof OptionalFields[K] extends T\n  ? K\n  : never;\n}[keyof typeof OptionalFields];\n\nexport type SearchResultR18Fields<T extends R18Fields> = {\n  [K in keyof typeof R18Fields]: typeof R18Fields[K] extends T ? K : never;\n}[keyof typeof R18Fields];\n\nexport type UserSearchResultFields<T extends UserFields> = {\n  [K in keyof typeof UserFields]: typeof UserFields[K] extends T ? K : never;\n}[keyof typeof UserFields];\n\nexport type PickedNarouSearchResult<T extends keyof NarouSearchResult> = Pick<\n  NarouSearchResult,\n  T\n>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgBA,IAAqB,qBAArB,MAAiE;AAAA;AAAA;AAAA;AAAA;AAAA,EA8B/D,YACE,CAAC,QAAQ,GAAG,MAAM,GAClB,QACA;AACA,UAAM,QAAQ,OAAO;AACrB,UAAM,QAAQ,OAAO,OAAO;AAC5B,UAAM,QAAQ,OAAO,MAAM;AAE3B,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,OAAO;AACrB,SAAK,SAAS;AAAA,EAChB;AACF;;;ADjCA,IAA8B,aAA9B,MAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBvC,MAAgB,cACd,QACA,WAAW,yCACwC;AACnD,WAAO,IAAI,mBAAmB,MAAM,KAAK,QAAQ,QAAQ,QAAQ,GAAG,MAAM;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aACJ,QACmD;AACnD,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eACJ,QACmD;AACnD,WAAO,MAAM,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,QAAsD;AACzE,WAAO,MAAM,KAAK,QAAQ,QAAQ,uCAAuC;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBACJ,QACoC;AACpC,WAAO,MAAM,KAAK,QAAQ,QAAQ,sCAAsC;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBACJ,QACkD;AAClD,WAAO,IAAI;AAAA,MACT,MAAM,KAAK,QAAQ,QAAQ,sCAAsC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AACF;","names":[]}