UNPKG

@bachman-dev/wanikani-api-types

Version:

Regularly updated type definitions for the WaniKani API

1,468 lines (1,460 loc) 50.2 kB
import * as v2 from 'valibot'; // src/v20170710/lang/_internal.ts // @__NO_SIDE_EFFECTS__ function getLocale(issue) { if (typeof issue.lang === "string") { if (issue.lang === "en" || issue.lang.startsWith("en-")) { return "en"; } } return "en"; } // src/v20170710/lang/date-union.ts var en = "Expected either a valid ISO-8601 timestamp string or a JavaScript Date"; var dateUnion = /* @__NO_SIDE_EFFECTS__ */ (issue) => { const locale = getLocale(issue); switch (locale) { default: return en; } }; // src/v20170710/lang/review-payload-intersect.ts var en2 = "Failed to intersect Review Payload objects; this is usually caused when trying to merge a base object with key/value type conflicts."; var reviewPayloadIntersect = /* @__NO_SIDE_EFFECTS__ */ (issue) => { const locale = getLocale(issue); switch (locale) { default: return en2; } }; // src/v20170710/lang/review-payload-union.ts var en3 = "Review Payload must have one and only one of either an assignment_id or subject_id positive integer"; var reviewPayloadUnion = /* @__NO_SIDE_EFFECTS__ */ (issue) => { const locale = getLocale(issue); switch (locale) { default: return en3; } }; var ApiRevision = v2.literal("20170710"); var API_REVISION = "20170710"; // @__NO_SIDE_EFFECTS__ function isApiRevision(value) { return v2.is(ApiRevision, value); } var SafeInteger = v2.pipe(v2.number(), v2.safeInteger(), v2.minValue(0)); var DatableString = v2.pipe(v2.string(), v2.trim(), v2.isoTimestamp(), v2.brand("DatableString")); // @__NO_SIDE_EFFECTS__ function isDatableString(value) { return v2.is(DatableString, value); } var MIN_LEVEL = 1; var MAX_LEVEL = 60; var Level = v2.pipe(SafeInteger, v2.minValue(MIN_LEVEL), v2.maxValue(MAX_LEVEL)); // @__NO_SIDE_EFFECTS__ function isLevel(value) { return v2.is(Level, value); } var BaseResource = v2.object({ data_updated_at: DatableString, url: v2.string() }); var BaseCollection = v2.object({ data_updated_at: v2.union([DatableString, v2.null()]), object: v2.literal("collection"), pages: v2.object({ next_url: v2.union([v2.string(), v2.null()]), per_page: v2.number(), previous_url: v2.union([v2.string(), v2.null()]) }), total_count: v2.number(), url: v2.string() }); var CollectionParameters = v2.object({ ids: v2.optional(v2.array(SafeInteger)), page_after_id: v2.optional(SafeInteger), page_before_id: v2.optional(SafeInteger), updated_after: v2.optional(v2.union([DatableString, v2.date()], dateUnion)) }); function stringifyParameters(params) { v2.assert(CollectionParameters, params); if (Object.keys(params).length === 0) { return ""; } let isFirstItem = true; let queryString = ""; const emptyQueryParams = ["immediately_available_for_lessons", "immediately_available_for_review", "in_review"]; for (const [key, value] of Object.entries(params)) { if (emptyQueryParams.includes(key) && typeof value === "boolean") { if (value) { queryString += isFirstItem ? "?" : "&"; queryString += key; } } else { queryString += isFirstItem ? "?" : "&"; if (typeof value === "boolean") { queryString += value ? `${key}=true` : `${key}=false`; } else if (value instanceof Date && Object.prototype.toString.call(value) === "[object Date]") { queryString += `${key}=${value.toISOString()}`; } else if (Array.isArray(value) || typeof value === "number" || typeof value === "string") { queryString += `${key}=${value.toString()}`; } } isFirstItem = false; } return queryString; } var BaseReport = v2.object({ data_updated_at: DatableString, object: v2.literal("report"), url: v2.string() }); var ApiError = v2.object({ code: v2.number(), error: v2.string() }); // @__NO_SIDE_EFFECTS__ function isApiError(value) { return v2.is(ApiError, value); } var SubjectType = v2.picklist(["kana_vocabulary", "kanji", "radical", "vocabulary"]); // @__NO_SIDE_EFFECTS__ function isSubjectType(value) { return v2.is(SubjectType, value); } var SubjectTuple = v2.pipe( v2.tupleWithRest([SubjectType], SubjectType), v2.nonEmpty(), v2.checkItems( (item, index, array12) => array12.indexOf(item) === index, "Duplicate Subject Type detected in Subject Tuple" ) ); // @__NO_SIDE_EFFECTS__ function isSubjectTuple(value) { return v2.is(SubjectTuple, value); } var SubjectAuxiliaryMeaning = v2.object({ meaning: v2.string(), type: v2.picklist(["blacklist", "whitelist"]) }); var SubjectMeaning = v2.object({ accepted_answer: v2.boolean(), meaning: v2.string(), primary: v2.boolean() }); var SubjectBaseData = v2.object({ auxiliary_meanings: v2.array(SubjectAuxiliaryMeaning), created_at: DatableString, document_url: v2.string(), hidden_at: v2.union([DatableString, v2.null()]), lesson_position: v2.number(), level: Level, meaning_mnemonic: v2.string(), meanings: v2.array(SubjectMeaning), slug: v2.string(), spaced_repetition_system_id: v2.number() }); var RadicalCharacterImage = v2.intersect([ v2.object({ url: v2.string() }), v2.variant("content_type", [ v2.object({ content_type: v2.literal("image/svg+xml"), metadata: v2.object({ inline_styles: v2.boolean() }) }), v2.object({ content_type: v2.literal("image/png"), metadata: v2.object({ color: v2.string(), dimensions: v2.string(), style_name: v2.string() }) }) ]) ]); var RadicalData = v2.object( v2.entriesFromObjects([ SubjectBaseData, v2.object({ amalgamation_subject_ids: v2.array(v2.number()), character_images: v2.array(RadicalCharacterImage), characters: v2.union([v2.string(), v2.null()]) }) ]) ); var KanjiReading = v2.object({ accepted_answer: v2.boolean(), primary: v2.boolean(), reading: v2.string(), type: v2.picklist(["kunyomi", "nanori", "onyomi"]) }); var KanjiData = v2.object( v2.entriesFromObjects([ SubjectBaseData, v2.object({ amalgamation_subject_ids: v2.array(v2.number()), characters: v2.string(), component_subject_ids: v2.array(v2.number()), meaning_hint: v2.union([v2.string(), v2.null()]), reading_hint: v2.union([v2.string(), v2.null()]), reading_mnemonic: v2.string(), readings: v2.array(KanjiReading), visually_similar_subject_ids: v2.array(v2.number()) }) ]) ); var VocabularyContextSentence = v2.object({ en: v2.string(), ja: v2.string() }); var VocabularyPronunciationAudio = v2.object({ content_type: v2.picklist(["audio/mpeg", "audio/ogg", "audio/webm"]), metadata: v2.object({ gender: v2.picklist(["female", "male"]), pronunciation: v2.string(), source_id: v2.number(), voice_actor_id: v2.number(), voice_actor_name: v2.string(), voice_description: v2.string() }), url: v2.string() }); var VocabularyReading = v2.object({ accepted_answer: v2.boolean(), primary: v2.boolean(), reading: v2.string() }); var VocabularyData = v2.object( v2.entriesFromObjects([ SubjectBaseData, v2.object({ characters: v2.string(), component_subject_ids: v2.array(v2.number()), context_sentences: v2.array(VocabularyContextSentence), parts_of_speech: v2.array(v2.string()), pronunciation_audios: v2.array(VocabularyPronunciationAudio), reading_mnemonic: v2.string(), readings: v2.array(VocabularyReading) }) ]) ); var KanaVocabularyData = v2.object( v2.entriesFromObjects([ SubjectBaseData, v2.object({ characters: v2.string(), context_sentences: v2.array(VocabularyContextSentence), parts_of_speech: v2.array(v2.string()), pronunciation_audios: v2.array(VocabularyPronunciationAudio) }) ]) ); var Subject = v2.intersect([ BaseResource, v2.object({ id: v2.number() }), v2.variant("object", [ v2.object({ data: KanaVocabularyData, object: v2.literal("kana_vocabulary") }), v2.object({ data: KanjiData, object: v2.literal("kanji") }), v2.object({ data: RadicalData, object: v2.literal("radical") }), v2.object({ data: VocabularyData, object: v2.literal("vocabulary") }) ]) ]); // @__NO_SIDE_EFFECTS__ function isSubject(value) { return v2.is(Subject, value); } var SubjectCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(Subject) }) ]) ); // @__NO_SIDE_EFFECTS__ function isSubjectCollection(value) { return v2.is(SubjectCollection, value); } var SUBJECT_MARKUP_MATCHER = /<(?<tag>ja|kanji|meaning|radical|reading|vocabulary)>(?<innerText>.*?)<\/\1>/dgu; function parseSubjectMarkup(text) { if (!text) { return []; } const markupArray = []; let lastIdx = 0; for (const match of text.matchAll(SUBJECT_MARKUP_MATCHER)) { if (typeof match.indices?.[0] !== "undefined") { const beforeText = text.substring(lastIdx, match.indices[0][0]); if (beforeText) { markupArray.push({ text: beforeText }); } if (typeof match.groups?.innerText === "string" && (match.groups.tag === "ja" || match.groups.tag === "kanji" || match.groups.tag === "meaning" || match.groups.tag === "radical" || match.groups.tag === "reading" || match.groups.tag === "vocabulary")) { const tagNode = { tag: match.groups.tag, children: parseSubjectMarkup(match.groups.innerText) }; markupArray.push(tagNode); } lastIdx = match.indices[0][1]; } } const afterText = text.substring(lastIdx, text.length); if (afterText) { markupArray.push({ text: afterText }); } return markupArray; } var SubjectParameters = v2.object( v2.entriesFromObjects([ CollectionParameters, v2.object({ hidden: v2.optional(v2.boolean()), levels: v2.optional(v2.array(Level)), slugs: v2.optional(v2.array(v2.string())), types: v2.optional(SubjectTuple) }) ]) ); var MIN_SRS_STAGE = 0; var MAX_SRS_REVIEW_STAGE = 8; var MAX_SRS_STAGE = 9; var SpacedRepetitionSystemStageNumber = v2.pipe( SafeInteger, v2.minValue(MIN_SRS_STAGE), v2.maxValue(MAX_SRS_STAGE) ); // @__NO_SIDE_EFFECTS__ function isSpacedRepetitionSystemStageNumber(value) { return v2.is(SpacedRepetitionSystemStageNumber, value); } var SpacedRepetitionSystemStage = v2.object({ interval: v2.union([v2.number(), v2.null()]), interval_unit: v2.union([v2.picklist(["days", "hours", "milliseconds", "minutes", "seconds", "weeks"]), v2.null()]), position: SpacedRepetitionSystemStageNumber }); var SpacedRepetitionSystem = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ burning_stage_position: SpacedRepetitionSystemStageNumber, created_at: DatableString, description: v2.string(), name: v2.string(), passing_stage_position: SpacedRepetitionSystemStageNumber, stages: v2.array(SpacedRepetitionSystemStage), starting_stage_position: SpacedRepetitionSystemStageNumber, unlocking_stage_position: SpacedRepetitionSystemStageNumber }), id: v2.number(), object: v2.literal("spaced_repetition_system") }) ]) ); // @__NO_SIDE_EFFECTS__ function isSpacedRepetitionSystem(value) { return v2.is(SpacedRepetitionSystem, value); } var SpacedRepetitionSystemCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(SpacedRepetitionSystem) }) ]) ); // @__NO_SIDE_EFFECTS__ function isSpacedRepetitionSystemCollection(value) { return v2.is(SpacedRepetitionSystemCollection, value); } var SpacedRepetitionSystemParameters = CollectionParameters; // src/v20170710/assignments.ts var Assignment = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ available_at: v2.union([DatableString, v2.null()]), burned_at: v2.union([DatableString, v2.null()]), created_at: DatableString, hidden: v2.boolean(), passed_at: v2.union([DatableString, v2.null()]), resurrected_at: v2.union([DatableString, v2.null()]), srs_stage: SpacedRepetitionSystemStageNumber, started_at: v2.union([DatableString, v2.null()]), subject_id: v2.number(), subject_type: SubjectType, unlocked_at: v2.union([DatableString, v2.null()]) }), id: v2.number(), object: v2.literal("assignment") }) ]) ); // @__NO_SIDE_EFFECTS__ function isAssignment(value) { return v2.is(Assignment, value); } var AssignmentCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(Assignment) }) ]) ); // @__NO_SIDE_EFFECTS__ function isAssignmentCollection(value) { return v2.is(AssignmentCollection, value); } var AssignmentParameters = v2.object( v2.entriesFromObjects([ CollectionParameters, v2.object({ available_after: v2.optional(v2.union([DatableString, v2.date()], dateUnion)), available_before: v2.optional(v2.union([DatableString, v2.date()], dateUnion)), burned: v2.optional(v2.boolean()), hidden: v2.optional(v2.boolean()), immediately_available_for_lessons: v2.optional(v2.boolean()), immediately_available_for_review: v2.optional(v2.boolean()), in_review: v2.optional(v2.boolean()), levels: v2.optional(v2.array(Level)), srs_stages: v2.optional(v2.array(SpacedRepetitionSystemStageNumber)), started: v2.optional(v2.boolean()), subject_ids: v2.optional(v2.array(SafeInteger)), subject_types: v2.optional(SubjectTuple), unlocked: v2.optional(v2.boolean()) }) ]) ); var AssignmentPayload = v2.object({ assignment: v2.object({ started_at: v2.optional(v2.union([DatableString, v2.date()], dateUnion)) }) }); var LevelProgression = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ abandoned_at: v2.union([DatableString, v2.null()]), completed_at: v2.union([DatableString, v2.null()]), created_at: DatableString, level: Level, passed_at: v2.union([DatableString, v2.null()]), started_at: v2.union([DatableString, v2.null()]), unlocked_at: v2.union([DatableString, v2.null()]) }), id: v2.number(), object: v2.literal("level_progression") }) ]) ); // @__NO_SIDE_EFFECTS__ function isLevelProgression(value) { return v2.is(LevelProgression, value); } var LevelProgressionCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(LevelProgression) }) ]) ); // @__NO_SIDE_EFFECTS__ function isLevelProgressionCollection(value) { return v2.is(LevelProgressionCollection, value); } var LevelProgressionParameters = CollectionParameters; var ReviewStatistic = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ created_at: DatableString, hidden: v2.boolean(), meaning_correct: v2.number(), meaning_current_streak: v2.number(), meaning_incorrect: v2.number(), meaning_max_streak: v2.number(), percentage_correct: v2.number(), reading_correct: v2.number(), reading_current_streak: v2.number(), reading_incorrect: v2.number(), reading_max_streak: v2.number(), subject_id: v2.number(), subject_type: SubjectType }), id: v2.number(), object: v2.literal("review_statistic") }) ]) ); // @__NO_SIDE_EFFECTS__ function isReviewStatistic(value) { return v2.is(ReviewStatistic, value); } var ReviewStatisticCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(ReviewStatistic) }) ]) ); // @__NO_SIDE_EFFECTS__ function isReviewStatisticCollection(value) { return v2.is(ReviewStatisticCollection, value); } var ReviewStatisticParameters = v2.object( v2.entriesFromObjects([ CollectionParameters, v2.object({ hidden: v2.optional(v2.boolean()), percentages_greater_than: v2.optional(v2.number()), percentages_less_than: v2.optional(v2.number()), subject_ids: v2.optional(v2.array(SafeInteger)), subject_types: v2.optional(SubjectTuple) }) ]) ); // src/v20170710/reviews.ts var Review = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ assignment_id: v2.number(), created_at: DatableString, ending_srs_stage: SpacedRepetitionSystemStageNumber, incorrect_meaning_answers: v2.number(), incorrect_reading_answers: v2.number(), spaced_repetition_system_id: v2.number(), starting_srs_stage: SpacedRepetitionSystemStageNumber, subject_id: v2.number() }), id: v2.number(), object: v2.literal("review") }) ]) ); // @__NO_SIDE_EFFECTS__ function isReview(value) { return v2.is(Review, value); } var ReviewCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(Review) }) ]) ); // @__NO_SIDE_EFFECTS__ function isReviewCollection(value) { return v2.is(ReviewCollection, value); } var ReviewParameters = v2.object( v2.entriesFromObjects([ CollectionParameters, v2.object({ assignment_ids: v2.optional(v2.array(SafeInteger)), subject_ids: v2.optional(v2.array(SafeInteger)) }) ]) ); var ReviewPayload = v2.object({ review: v2.intersect( [ v2.object({ incorrect_meaning_answers: SafeInteger, incorrect_reading_answers: SafeInteger, created_at: v2.optional(v2.union([DatableString, v2.date()], dateUnion)) }), v2.union( [ v2.object({ assignment_id: SafeInteger, subject_id: v2.optional(v2.never()) }), v2.object({ subject_id: SafeInteger, assignment_id: v2.optional(v2.never()) }) ], reviewPayloadUnion ) ], reviewPayloadIntersect ) }); var CreatedReview = v2.object( v2.entriesFromObjects([ Review, v2.object({ resources_updated: v2.object({ assignment: Assignment, review_statistic: ReviewStatistic }) }) ]) ); // @__NO_SIDE_EFFECTS__ function isCreatedReview(value) { return v2.is(CreatedReview, value); } var StudyMaterialBaseData = v2.object({ meaning_note: v2.string(), meaning_synonyms: v2.array(v2.string()), reading_note: v2.string() }); var StudyMaterial = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.intersect([ StudyMaterialBaseData, v2.object({ created_at: DatableString, hidden: v2.boolean(), subject_id: v2.number(), subject_type: SubjectType }) ]), id: v2.number(), object: v2.literal("study_material") }) ]) ); // @__NO_SIDE_EFFECTS__ function isStudyMaterial(value) { return v2.is(StudyMaterial, value); } var StudyMaterialCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(StudyMaterial) }) ]) ); // @__NO_SIDE_EFFECTS__ function isStudyMaterialCollection(value) { return v2.is(StudyMaterialCollection, value); } var StudyMaterialParameters = v2.object( v2.entriesFromObjects([ CollectionParameters, v2.object({ hidden: v2.optional(v2.boolean()), subject_ids: v2.optional(v2.array(SafeInteger)), subject_types: v2.optional(SubjectTuple) }) ]) ); var StudyMaterialUpdatePayload = v2.partial(StudyMaterialBaseData); var StudyMaterialCreatePayload = v2.object( v2.entriesFromObjects([ StudyMaterialUpdatePayload, v2.object({ subject_id: SafeInteger }) ]) ); var Reset = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ confirmed_at: v2.union([DatableString, v2.null()]), created_at: DatableString, original_level: Level, target_level: Level }), id: v2.number(), object: v2.literal("reset") }) ]) ); // @__NO_SIDE_EFFECTS__ function isReset(value) { return v2.is(Reset, value); } var ResetCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(Reset) }) ]) ); // @__NO_SIDE_EFFECTS__ function isResetCollection(value) { return v2.is(ResetCollection, value); } var ResetParameters = CollectionParameters; var MIN_LESSON_BATCH_SIZE = 3; var MAX_LESSON_BATCH_SIZE = 10; var LessonBatchSizeNumber = v2.pipe( SafeInteger, v2.minValue(MIN_LESSON_BATCH_SIZE), v2.maxValue(MAX_LESSON_BATCH_SIZE) ); // @__NO_SIDE_EFFECTS__ function isLessonBatchSizeNumber(value) { return v2.is(LessonBatchSizeNumber, value); } var UserPreferences = v2.object({ default_voice_actor_id: SafeInteger, extra_study_autoplay_audio: v2.boolean(), lessons_autoplay_audio: v2.boolean(), lessons_batch_size: LessonBatchSizeNumber, lessons_presentation_order: v2.picklist(["ascending_level_then_shuffled", "ascending_level_then_subject", "shuffled"]), reviews_autoplay_audio: v2.boolean(), reviews_display_srs_indicator: v2.boolean(), reviews_presentation_order: v2.picklist(["lower_levels_first", "shuffled"]) }); var User = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ current_vacation_started_at: v2.union([DatableString, v2.null()]), id: v2.string(), level: Level, preferences: UserPreferences, profile_url: v2.string(), started_at: DatableString, subscription: v2.object({ active: v2.boolean(), max_level_granted: Level, period_ends_at: v2.union([DatableString, v2.null()]), type: v2.picklist(["free", "lifetime", "recurring", "unknown"]) }), username: v2.string() }), object: v2.literal("user") }) ]) ); // @__NO_SIDE_EFFECTS__ function isUser(value) { return v2.is(User, value); } var UserPreferencesPayload = v2.object({ user: v2.object({ preferences: v2.partial(UserPreferences) }) }); var VoiceActor = v2.object( v2.entriesFromObjects([ BaseResource, v2.object({ data: v2.object({ created_at: DatableString, description: v2.string(), gender: v2.picklist(["female", "male"]), name: v2.string() }), id: v2.number(), object: v2.literal("voice_actor") }) ]) ); // @__NO_SIDE_EFFECTS__ function isVoiceActor(value) { return v2.is(VoiceActor, value); } var VoiceActorCollection = v2.object( v2.entriesFromObjects([ BaseCollection, v2.object({ data: v2.array(VoiceActor) }) ]) ); // @__NO_SIDE_EFFECTS__ function isVoiceActorCollection(value) { return v2.is(VoiceActorCollection, value); } var VoiceActorParameters = CollectionParameters; // src/v20170710/requests.ts var ApiRequestFactory = class _ApiRequestFactory { /** * Types of Assignment Requests available in the WaniKani API. */ assignments = { /** * Get an Assignment or Assignment Collection from the WaniKani API. * @param idOrParams The Assignment ID for individual Assignments, or parameters for Assignment Collections. * @param options Options for making GET requests to the API. * @returns A Get Assignment(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/assignments` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(AssignmentParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; }, /** * Start an Assignment (i.e. move from Lessons to Reviews) via the WaniKani API. * @param assignmentId The Assignment ID to start. * @param payload The payload to send when starting the Assignment. * @param options Options for making PUT requests to the API. * @returns A Start Assignment Request usable in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or payload is invalid. */ start: (assignmentId, payload, options) => { v2.assert(SafeInteger, assignmentId); v2.assert(AssignmentPayload, payload); const headers = { ...this._postPutHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: JSON.stringify(payload), headers, method: "PUT", url: `${this.baseUrl}/assignments/${assignmentId}/start` }; return request; } }; /** The base URL of the WaniKani API */ baseUrl = "https://api.wanikani.com/v2"; /** * Types of Level Progression Requests available in the WaniKani API. */ levelProgressions = { /** * Get a Level Progression or Level Progression Collection from the WaniKani API. * @param idOrParams The Level Progression ID for individual Level Progressions, or parameters for Level * Progression Collections. * @param options Options for making GET requests to the API. * @returns A Get Level Progression(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/level_progressions` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(LevelProgressionParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * Types of Reset Requests available in the WaniKani API. */ resets = { /** * Get a Reset or Reset Collection from the WaniKani API. * @param idOrParams The Reset ID for individual Resets, or parameters for Reset Collections. * @param options Options for making GET requests to the API. * @returns A Get Reset(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/resets` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(ResetParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * Types of Review Statistic Requests available in the WaniKani API. */ reviewStatistics = { /** * Get a Review Statistic or Review Statistic Collection from the WaniKani API. * @param idOrParams The Review Statistic ID for individual Review Statistics, or parameters for Review Statistic * Collections. * @param options Options for making GET requests to the API. * @returns A Get Review Statistic(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/review_statistics` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(ReviewStatisticParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * Types of Review Requests available in the WaniKani API. */ reviews = { /** * Create a new Review via the WaniKani API. * @param payload The payload to send when creating the Review. * @param options Options for making POST requests to the API. * @returns A Create Review Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if payload is invalid. */ create: (payload, options) => { v2.assert(ReviewPayload, payload); const headers = { ...this._postPutHeaders }; if (typeof options !== "undefined") { if (typeof options.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } } const request = { body: JSON.stringify(payload), headers, method: "POST", url: `${this.baseUrl}/reviews` }; return request; }, /** * Get a Review or Review Collection from the WaniKani API. * @param idOrParams The Review ID for individual Reviews, or parameters for Review Collections. * @param options Options for making GET requests to the API. * @returns A Get Review(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/reviews` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(ReviewParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * Types of Spaced Repetition System (SRS) Requests available in the WaniKani API. */ spacedRepetitionSystems = { /** * Get a Spaced Repetition System (SRS) or Spaced Repetition System (SRS) Collection from the WaniKani API. * @param idOrParams The Spaced Repetition System (SRS) ID for individual Spaced Repetition Systems (SRS), or * parameters for Spaced Repetition System (SRS) Collections. * @param options Options for making GET requests to the API. * @returns A Get Spaced Repetition System(s) (SRS) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/spaced_repetition_systems` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(SpacedRepetitionSystemParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * An alias for Spaced Repetition System requests. */ srs = this.spacedRepetitionSystems; /** * Types of Study Material Requests available in the WaniKani API. */ studyMaterials = { /** * Get a Study Material or Study Material Collection from the WaniKani API. * @param idOrParams The Study Material ID for individual Study Materials, or parameters for Study Material * Collections. * @param options Options for making GET requests to the API. * @returns A Get Study Material(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/study_materials` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(StudyMaterialParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; }, /** * Create a new Study Material for a given Subject via the WaniKani API. * @param payload The payload to send when creating the new Study Material. * @param options Options for making POST requests to the API. * @returns A Create Study Material Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if payload is invalid. */ create: (payload, options) => { v2.assert(StudyMaterialCreatePayload, payload); const headers = { ...this._postPutHeaders }; if (typeof options !== "undefined") { if (typeof options.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } } const request = { body: JSON.stringify(payload), headers, method: "POST", url: `${this.baseUrl}/study_materials` }; return request; }, /** * Update a Study Material for a given Subject. * @param studyMaterialId The Study Material ID to update. * @param payload The payload to send when updating the Study Material. * @param options Options for making PUT requests to the API. * @returns An Update Study Material Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or payload is invalid. */ update: (studyMaterialId, payload, options) => { v2.assert(SafeInteger, studyMaterialId); v2.assert(StudyMaterialUpdatePayload, payload); const headers = { ...this._postPutHeaders }; if (typeof options !== "undefined") { if (typeof options.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } } const request = { body: JSON.stringify(payload), headers, method: "PUT", url: `${this.baseUrl}/study_materials/${studyMaterialId}` }; return request; } }; /** * Types of Subject Requests available in the WaniKani API. */ subjects = { /** * Get a Subject or Subject Collection from the WaniKani API. * @param idOrParams The Subject ID for individual Subjects, or parameters for Subject Collections. * @param options Options for making GET requests to the API. * @returns A Get Subject(s) Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/subjects` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(SubjectParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * Types of Summary Requests available in the WaniKani API. */ summary = { /** * Get a summary of a user's available and upcoming lessons/reviews from the WaniKani API. * * @param options Options for making GET requests to the API. * @returns A Get Summary Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. */ get: (options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/summary` }; return request; } }; /** * Types of User Requests available in the WaniKani API. */ user = { /** * Get a user's information from the WaniKani API. * * @param options Options for making GET requests to the API. * @returns A Get User Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. */ get: (options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/user` }; return request; }, /** * Update a User's Preferences via the WaniKani API. * * @param payload The payload containing changed Preferences to send for the update. * @param options Options for making PUT requests to the API. * @returns An Update User Preferences Request usabile in any HTTP API/Library. * @throws A `TypeError` if trying to set type-checked request headers. * @throws A {@link valibot!ValiError} if payload is invalid. */ updatePreferences: (payload, options) => { v2.assert(UserPreferencesPayload, payload); const headers = { ...this._postPutHeaders }; if (typeof options !== "undefined") { if (typeof options.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } } const request = { body: JSON.stringify(payload), headers, method: "PUT", url: `${this.baseUrl}/user` }; return request; } }; /** * Types of Voice Actor Requests available in the WaniKani API. */ voiceActors = { /** * Get a Voice Actor or Voice Actor Collection from the WaniKani API. * @param idOrParams The Voice Actor ID for individual Voice Actors, or parameters for Voice Actor Collections. * @param options Options for making GET requests to the API. * @returns A Get Voice Actor(s) Request usabile in any HTTP API/Library. * @throws A {@link valibot!ValiError} if ID or parameters are invalid. */ get: (idOrParams, options) => { const headers = { ...this._getHeaders }; if (typeof options?.customHeaders !== "undefined") { for (const [key, value] of Object.entries(options.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); headers[key] = value; } } const request = { body: null, headers, method: "GET", url: `${this.baseUrl}/voice_actors` }; if (typeof idOrParams === "number") { v2.assert(SafeInteger, idOrParams); request.url += `/${idOrParams}`; } else if (typeof idOrParams !== "undefined") { v2.assert(VoiceActorParameters, idOrParams); request.url += stringifyParameters(idOrParams); } return request; } }; /** * The headers set on factory initialization, excluding anything in the `customHeaders` property in * {@link ApiRequestFactoryInit}. */ _initHeaders; /** * The headers that will be added to any GET requests returned by the factory. */ _getHeaders; /** * The headers that will be added to any POST and PUT requests returned by the factory. */ _postPutHeaders; /** * Initialize the Request Factory. * @param init Initialization options for the factory. * @throws A `TypeError` if trying to set type-checked request headers. */ constructor(init) { this._initHeaders = { authorization: `Bearer ${init.apiToken}`, "wanikani-revision": init.revision ?? "20170710" }; this._getHeaders = { ...this._initHeaders }; this._postPutHeaders = { ...this._initHeaders }; if (typeof init.customHeaders !== "undefined") { for (const [key, value] of Object.entries(init.customHeaders)) { _ApiRequestFactory._validateHeader(key, value); this._getHeaders[key] = value; this._postPutHeaders[key] = value; } } this._postPutHeaders["content-type"] = "application/json"; } /** * Validates custom-set headers to make sure type checking isn't circumvented. * @param key The header key, e.g. `Accpet` or `X-Forwarded-For` * @param value The header value, e.g. `application/json` or `192.168.1.1` * @throws A `TypeError` if trying to set type-checked request headers. * @internal */ static _validateHeader(key, value) { if (key.toLowerCase() === "authorization") { throw new TypeError("WaniKani API Token should be set via setApiToken() method."); } else if (key.toLowerCase() === "wanikani-revision") { throw new TypeError("WaniKani API Revision should be set via setApiRevision() method."); } else if ((key.toLowerCase() === "accept" || key.toLowerCase() === "content-type") && value !== "application/json") { throw new TypeError(`The "${key}" header must be set to "application/json" .`); } } /** * Add additional custom headers to be used in all requests generated by the factory. * @param headers An object containing HTTP headers and their values. * @returns The factory, with the added custom headers. * @throws A `TypeError` if trying to set type-checked request headers. */ addCustomHeaders(headers) { for (const [key, value] of Object.entries(headers)) { _ApiRequestFactory._validateHeader(key, value); this._getHeaders[key] = value; this._postPutHeaders[key] = value; } return this; } /** * Sets a new WaniKani API Revision to use in requests returned by the factory. * @param revision The WaniKani API Revision to use. * @returns The factory, with the newly set WaniKani API Revision. * @throws A {@link valibot!ValiError} if the WaniKani API Revision is invalid. */ setApiRevision(revision) { const validRevision = v2.parse(ApiRevision, revision); this._initHeaders["wanikani-revision"] = validRevision; this._getHeaders["wanikani-revision"] = validRevision; this._postPutHeaders["wanikani-revision"] = validRevision; return this; } /** * Sets a new WaniKani API Token to use in requests returned by the factory. * @param token The new WaniKani API Token to use. * @returns The factory, with the newly set WaniKani API Token. */ setApiToken(token) { this._initHeaders.authorization = `Bearer ${token}`; this._getHeaders.authorization = `Bearer ${token}`; this._postPutHeaders.authorization = `Bearer ${token}`; return this; } /** * Sets the custom headers for all requests gerated by the factory to those passed to this function, removing any * previously set custom headers, and keeping API Revision and Token settings. * @param headers An object containing HTTP headers and their values. * @returns The factory, with the only custom headers being those passed to this function. * @throws A `TypeError` if trying to set type-checked request headers. */ setCustomHeaders(headers) { this._getHeaders = { ...this._initHeaders }; this._postPutHeaders = { ...this._initHeaders }; for (const [key, value] of Object.entries(headers)) { _ApiRequestFactory._validateHeader(key, value); this._getHeaders[key] = value; this._postPutHeaders[key] = value; } this._postPutHeaders["content-type"] = "application/json"; return this; } }; var SummaryInterval = v2.object({ available_at: DatableString, subject_ids: v2.array(v2.number()) }); var Summary = v2.object( v2.entriesFromObjects([ BaseReport, v2.object({ data: v2.object({ lessons: v2.array(SummaryInterval), next_reviews_at: v2.union([DatableString, v2.null()]), reviews: v2.array(SummaryInterval) }) }) ]) ); // @__NO_SIDE_EFFECTS__ function isSummary(value) { return v2.is(Summary, value); } export { API_REVISION, ApiError, ApiRequestFactory, ApiRevision, Assignment, AssignmentCollection, AssignmentParameters, AssignmentPayload, BaseCollection, BaseReport, BaseResource, CollectionParameters, CreatedReview, DatableString, KanaVocabularyData, KanjiData, KanjiReading, LessonBatchSizeNumber, Level, LevelProgression, LevelProgressionCollection, LevelProgressionParameters, MAX_LESSON_BATCH_SIZE, MAX_LEVEL, MAX_SRS_REVIEW_STAGE, MAX_SRS_STAGE, MIN_LESSON_BATCH_SIZE, MIN_LEVEL, MIN_SRS_STAGE, RadicalCharacterImage, RadicalData, Reset, ResetCollection, ResetParameters, Review, ReviewCollection, ReviewParameters, ReviewPayload, ReviewStatistic, ReviewStatisticCollection, ReviewStatisticParameters, SUBJECT_MARKUP_MATCHER, SafeInteger, SpacedRepetitionSystem, SpacedRepetitionSystemCollection, SpacedRepetitionSystemParameters, SpacedRepetitionSystemStage, SpacedRepetitionSystemStageNumber, StudyMaterial, StudyMaterialBaseData, StudyMaterialCollection, StudyMaterialCreatePayload, StudyMaterialParameters, StudyMaterialUpdatePayload, Subject, SubjectAuxiliaryMeaning, SubjectBaseData, SubjectCollection, SubjectMeaning, SubjectParameters, SubjectTuple, SubjectType, Summary, SummaryInterval, User, UserPreferences, UserPreferencesPayload, VocabularyContextSentence, VocabularyData, VocabularyPronunciationAudio, VocabularyReading, VoiceActor, VoiceActorCollection, VoiceActorParameters, isApiError, isApiRevision, isAssignment, isAssignmentCollection, isCreatedReview, isDatableString, isLessonBatchSizeNumber, isLevel, isLevelProgression, isLevelProgressionCollection, isReset, isResetCollection, isReview, isReviewCollection, isReviewStatistic, isReviewStatisticCollection, isSpacedRepetitionSystem, isSpacedRepetitionSystemCollection, isSpace