Initial Commit
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
const {query} = require("../client")
|
||||
|
||||
class Chapter {
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {string} title
|
||||
* @param {string} author
|
||||
* @param {string} source
|
||||
* @param {string | Date} createdDate
|
||||
* @param {string | Date} fictionalDate
|
||||
* @param {string | Date} editedDate
|
||||
*/
|
||||
constructor(id, title, author, source, createdDate, fictionalDate, editedDate) {
|
||||
this.id = id
|
||||
this.title = title
|
||||
this.author = author
|
||||
this.source = source
|
||||
this.createdDate = new Date(createdDate)
|
||||
this.fictionalDate = new Date(fictionalDate)
|
||||
this.editedDate = new Date(editedDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the chapter's editable fields and update this object. This promise returns a boolean
|
||||
* whether there has been a change.
|
||||
*
|
||||
* @returns {Promise<boolean>} `true` if the story was edited in the meantime
|
||||
*/
|
||||
update() {
|
||||
return query(`
|
||||
query UpdateChapter($id: String!) {
|
||||
update: chapter(id: $id) {
|
||||
title
|
||||
source
|
||||
fictionalDate
|
||||
editedDate
|
||||
}
|
||||
}
|
||||
`, {id: this.id}).then(({update}) => {
|
||||
const editedDate = new Date(udpate.editedDate)
|
||||
const wasEdited = editedDate.getTime() != this.editedDate.getTime()
|
||||
|
||||
this.title = update.title
|
||||
this.source = update.source
|
||||
this.fictionalDate = new Date(update.fictionalDate)
|
||||
this.editedDate = editedDate
|
||||
|
||||
return wasEdited
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {Chapter}
|
||||
@@ -0,0 +1,5 @@
|
||||
const {query} = require("../client")
|
||||
|
||||
class Character {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
const {query} = require("../client")
|
||||
|
||||
class LogHeader {
|
||||
/**
|
||||
* Construct a log header. You should probably use the logHeaderApi instead of doing
|
||||
* this manually, even for mutations.
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {Date|string} date
|
||||
* @param {string} channelName
|
||||
* @param {string} title
|
||||
* @param {string} description
|
||||
* @param {string} event
|
||||
* @param {boolean} open
|
||||
* @param {{id:string,name:string,shortName:string,author:string}[]} characters
|
||||
*/
|
||||
constructor(id, shortId, date, channelName, title, description, event, open, characters) {
|
||||
this.id = id
|
||||
this.shortId = shortId
|
||||
this.date = new Date(date)
|
||||
this.channelName = channelName
|
||||
this.title = title || null
|
||||
this.description = description || null
|
||||
this.event = event || null
|
||||
this.open = open
|
||||
this.characters = characters.map(ch => new LogHeaderCharacter(ch.id, ch.name, ch.shortName, ch.author))
|
||||
}
|
||||
}
|
||||
|
||||
class LogHeaderCharacter {
|
||||
/**
|
||||
* Construct a log header character list entry.
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {string} name
|
||||
* @param {string} shortName
|
||||
* @param {string} author
|
||||
*/
|
||||
constructor(id, name, shortName, author) {
|
||||
this.id = id
|
||||
this.name = name
|
||||
this.shortName = shortName
|
||||
this.author = author
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* logHeaderApi contains the API queries for the LogHeader frontend model, which is a subset of the
|
||||
* logs model.
|
||||
*/
|
||||
const logHeaderApi = {
|
||||
/**
|
||||
* Call `stories(filter)` query
|
||||
*
|
||||
* @param {{search:string, channels:string|string[], events:string|string[], open:boolean, characters:string|string[], limit:number}} filter
|
||||
* @returns {Promise<LogHeader[]>}
|
||||
*/
|
||||
list(filter = {}) {
|
||||
return query(`
|
||||
query LogHeaders($filter: LogsFilter) {
|
||||
headers: logs(filter:$filter) {
|
||||
id
|
||||
shortId
|
||||
date
|
||||
channelName
|
||||
title
|
||||
description
|
||||
event
|
||||
open
|
||||
characters {
|
||||
id
|
||||
name
|
||||
shortName
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`, {filter}).then(({headers}) => {
|
||||
return headers.map(h => new LogHeader(h.id, h.shortId, h.date, h.channelName, h.title, h.description, h.event, h.open, h.characters))
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = {LogHeader, LogHeaderCharacter, logHeaderApi}
|
||||
@@ -0,0 +1,147 @@
|
||||
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 {string} createdDate
|
||||
* @param {string} updatedDate
|
||||
* @param {string} fictionalDate
|
||||
* @param {{kind:string, name:string}[]} tags
|
||||
* @param {Chapter[]} chapters
|
||||
*/
|
||||
constructor(id, name, author, category, createdDate, updatedDate, fictionalDate, tags, chapters) {
|
||||
this.id = id
|
||||
this.name = name
|
||||
this.author = author
|
||||
this.category = category
|
||||
this.createdDate = new Date(createdDate)
|
||||
this.updatedDate = new Date(updatedDate)
|
||||
this.fictionalDate = new Date(fictionalDate)
|
||||
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<Story[]>}
|
||||
*/
|
||||
list(filter = {}) {
|
||||
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
|
||||
}
|
||||
createdDate
|
||||
fictionalDate
|
||||
updatedDate
|
||||
}
|
||||
}
|
||||
`, {filter}).then(({stories}) => {
|
||||
return stories.map(d => new Story(d.id, d.name, d.author, d.category, d.createdDate, d.updatedDate, d.fictionalDate, d.tags))
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {Promise<Story>}
|
||||
*/
|
||||
find(id) {
|
||||
return query(`
|
||||
query FindStory($id: String!) {
|
||||
story(id: $id) {
|
||||
id
|
||||
name
|
||||
author
|
||||
category
|
||||
tags {
|
||||
kind
|
||||
name
|
||||
}
|
||||
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.createdDate, story.updatedDate, story.fictionalDate,
|
||||
story.tags, story.chapters
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Call `__type(name: "StoryCategory")` query and extracts the catogires from it
|
||||
*
|
||||
* @returns {Promise<StoryCategory[]>}
|
||||
*/
|
||||
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
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = {storyApi, Story}
|
||||
@@ -0,0 +1,34 @@
|
||||
const {query} = require("../client")
|
||||
|
||||
class Tag {
|
||||
/**
|
||||
* @param {string} kind
|
||||
* @param {string} name
|
||||
*/
|
||||
constructor(kind, name) {
|
||||
this.kind = kind
|
||||
this.name = name
|
||||
}
|
||||
}
|
||||
|
||||
const tagApi = {
|
||||
/**
|
||||
* Call `tags` query
|
||||
*
|
||||
* @returns {Promise<Tag[]>}
|
||||
*/
|
||||
list() {
|
||||
return query(`
|
||||
query Tags {
|
||||
tags {
|
||||
kind
|
||||
name
|
||||
}
|
||||
}
|
||||
`, {}).then(({tags}) => {
|
||||
return tags.map(d => new Tag(d))
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = {Tag, tagApi}
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
...require("./LogHeader"),
|
||||
...require("./Chapter"),
|
||||
...require("./Story"),
|
||||
...require("./Tag"),
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
const fetch = require("isomorphic-fetch")
|
||||
const config = require("../config")
|
||||
const compressQuery = require("graphql-query-compress")
|
||||
|
||||
/**
|
||||
* Run a GraphQL query against the rpdata backend
|
||||
*
|
||||
* @param {string} query The query to run
|
||||
* @param {{[x:string]: any}} variables
|
||||
* @param {{operationName:string, token: string, permissions: string[]}} options
|
||||
*/
|
||||
function query(query, variables = {}, options = {}) {
|
||||
return fetch(config.graphqlEndpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": options.token ? `Bearer ${options.token}` : null,
|
||||
"X-Permissions": options.permissions ? options.permissions.join(",") : null,
|
||||
},
|
||||
body: JSON.stringify({query: query.length > 256 ? compressQuery(query || "") : query, variables, operationName: options.operationName}),
|
||||
credentials: "include",
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
return Promise.reject([{
|
||||
message: `HTTP: ${res.statusText}`,
|
||||
location: null,
|
||||
}])
|
||||
}
|
||||
|
||||
return res.json()
|
||||
}).then(json => {
|
||||
if (json.errors != null && json.errors.length > 0) {
|
||||
return Promise.reject(json.errors)
|
||||
}
|
||||
|
||||
return json.data
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { query }
|
||||
Reference in New Issue
Block a user