const {query} = require("../client") const {Tag} = require("./Tag") const {Chapter} = require("./Chapter") class Story { /** * Construct a story object. You should use the API instead of calling this. * * @param {string} id * @param {string} name * @param {string} author * @param {"Info"|"News"|"Document"|"Background"|"Story"} category Story's category * @param {boolean} listed * @param {boolean} open * @param {string} createdDate * @param {string} updatedDate * @param {string} fictionalDate * @param {{kind:string, name:string}[]} tags * @param {Chapter[]} chapters */ constructor(id, name, author, category, listed, open, createdDate, updatedDate, fictionalDate, tags, chapters) { this.id = id this.name = name this.author = author this.category = category this.listed = listed this.open = open this.createdDate = new Date(createdDate) this.updatedDate = new Date(updatedDate) this.fictionalDate = fictionalDate != null ? new Date(fictionalDate) : null this.tags = tags.map(dt => new Tag(dt.kind, dt.name)) this.chapters = chapters != null ? chapters.map(c => new Chapter(c.id, c.title, c.author, c.source, c.createdDate, c.fictionalDate, c.editedDate)) : null } } class StoryCategory { constructor(name, description) { this.name = name this.description = description } } const data = { categories: null } /** * storyApi contains the API queries */ const storyApi = { /** * Call `stories(filter)` query * * @param {{author:string, category:string, tags:Tag[]|Tag, unlisted: boolean, open: boolean, earliestFictionalDate:Date|string, latestFictionalDate:Date|string, limit:number}} filter * @returns {Promise} */ list(filter = {}, options = {}) { if (filter.earliestFictionalDate != null && typeof(filter.earliestFictionalDate) !== "string") { filter.earliestFictionalDate = filter.earliestFictionalDate.toISOString() } if (filter.latestFictionalDate != null && typeof(filter.latestFictionalDate) !== "string") { filter.latestFictionalDate = filter.latestFictionalDate.toISOString() } return query(` query ListStories($filter: StoriesFilter) { stories(filter: $filter) { id name author category tags { kind name } listed open createdDate fictionalDate updatedDate } } `, {filter}, options).then(({stories}) => { return stories.map(d => new Story(d.id, d.name, d.author, d.category, d.listed, d.open, d.createdDate, d.updatedDate, d.fictionalDate, d.tags)) }) }, /** * @param {string} id * @returns {Promise} */ find(id) { return query(` query FindStory($id: String!) { story(id: $id) { id name author category tags { kind name } listed open createdDate fictionalDate updatedDate chapters { id title author source createdDate fictionalDate editedDate } } } `, {id}).then(({story}) => { return new Story( story.id, story.name, story.author, story.category, story.listed, story.open, story.createdDate, story.updatedDate, story.fictionalDate, story.tags, story.chapters ) }) }, /** * Call `__type(name: "StoryCategory")` query and extracts the catogires from it * * @returns {Promise} */ categories() { if (data.categories !== null) { return data.categories } return query(` query ListStoryCategories { categoryType: __type(name: "StoryCategory") { enumValues { name description } } } `, {}).then(({categoryType}) => { data.categories = categoryType.enumValues.map(d => new StoryCategory(d.name, d.description)) return data.categories }) }, /** * Call `addStoryTag(input)` mutation, returns the new tag list. * * @param {{id:string, tag:Tag}} input * @returns {Promise<{tags: Tag[]}>} */ addTag(input) { return query(` mutation AddStoryTag($input: StoryTagAddInput!) { addStoryTag(input:$input) { tags { kind name } } } `, {input}, {permissions: ["member", "story.edit"]}).then(({addStoryTag}) => { return addStoryTag }) }, /** * Call `removeStoryTag(input)` mutation, returns the new tag list. * * @param {{id:string, tag:Tag}} input * @returns {Promise<{tags: Tag[]}>} */ removeTag(input) { return query(` mutation RemoveStoryTag($input: StoryTagRemoveInput!) { removeStoryTag(input:$input) { tags { kind name } } } `, {input}, {permissions: ["member", "story.edit"]}).then(({removeStoryTag}) => { return removeStoryTag }) }, /** * Call `addStory(input)` mutation, returns the ID. * * @param {{name:string, category:string, author:string, open:boolean, listed:boolean, fictionalDate:Date, tags:Tag[]}} input * @returns {Promise} */ add(input) { return query(` mutation AddStory($input: StoryAddInput!) { addStory(input:$input) { id name author category tags { kind name } listed open createdDate fictionalDate updatedDate chapters { id title author source createdDate fictionalDate editedDate } } } `, {input}, {permissions: ["member", "story.edit"]}).then(({addStory}) => { return new Story( addStory.id, addStory.name, addStory.author, addStory.category, addStory.listed, addStory.open, addStory.createdDate, addStory.updatedDate, addStory.fictionalDate, addStory.tags, addStory.chapters ) }) }, /** * Call `editStory(input)` mutation, returns the changable fields. * * @param {{id:string, name:string, category:string, author:string, open:boolean, listed:boolean, fictionalDate:Date, clearFictionalDate:boolean}} input * @returns {Promise<{id:string, name:string, category:string, author:string, open:boolean, listed:boolean, fictionalDate:Date}>} */ edit(input) { return query(` mutation EditStory($input: StoryEditInput!) { editStory(input:$input) { id name category author open listed fictionalDate } } `, {input}, {permissions: ["member", "story.edit"]}).then(({editStory}) => { return editStory }) }, /** * Call `removeStory(input)` mutation, returns the id. * * @param {{id:string}} input * @returns {Promise<{id:string}>} */ remove(input) { return query(` mutation RemoveStory($input: StoryRemoveInput!) { removeStory(input:$input) { id } } `, {input}, {permissions: ["member", "story.remove"]}).then(({removeStory}) => { return removeStory }) }, } module.exports = {storyApi, Story}