Last active
April 21, 2022 06:43
-
-
Save deguchi/fcb0dc94682423cc7abb70b40d5e8385 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Unitrad UI APIライブラリ | |
Copyright (c) 2017 CALIL Inc. | |
This software is released under the MIT License. | |
http://opensource.org/licenses/mit-license.php | |
*/ | |
import queryString from 'query-string'; | |
interface UnitradQuery { | |
[key: string]: string | undefined, | |
free?: string, | |
title?: string, | |
author?: string, | |
publisher?: string, | |
isbn?: string, | |
ndc?: string, | |
year_start?: string, | |
year_end?: string, | |
region?: string | |
}; | |
interface UnitradPollingQuery { | |
uuid: string, | |
version: number, | |
diff: number, | |
timeout: number | |
}; | |
interface UnitradResult { | |
[key: string]: any, | |
uuid: string, | |
version: number, | |
running: boolean, | |
remains: Array<string>, | |
errors: Array<string>, | |
books: Array<UnitradBook>, | |
books_diff: { | |
update: Array<{ | |
[key: string]: any, | |
_idx: number, | |
holdings: Array<number>, | |
url: { | |
[key: number]: string, | |
} | |
}>, | |
insert: Array<UnitradBook> | |
} | |
}; | |
interface UnitradBook { | |
[key: string]: any, | |
url: string, | |
title: string, | |
volume: string, | |
author: string, | |
publisher: string, | |
_isbn: string, | |
isbn: string, | |
_pubdate: number, | |
pubdate: string, | |
id: string, | |
holdings: Array<number>, | |
_holdings: number, | |
_holding_key: number, | |
estimated_holdings: Array<number>, | |
}; | |
const ENDPOINT = 'https://unitrad.calil.jp/v1/'; | |
const FIELDS = ['free', 'title', 'author', 'publisher', 'isbn', 'ndc', 'year_start', 'year_end', 'region']; | |
/** | |
* Unitrad APIにアクセスするための共通関数 | |
* @param command APIのコマンド | |
* @param params 検索クエリ | |
* @returns {Object} | |
* @private | |
*/ | |
function _request(command: string, params: UnitradQuery | UnitradPollingQuery): Promise<UnitradResult> { | |
return fetch(ENDPOINT + command + '?' + queryString.stringify(params)).then(r => r.json()); | |
} | |
/** 横断検索APIクラス */ | |
export default class api { | |
/** | |
* 検索APIの起動 | |
* @param query - 検索クエリ | |
* @param callback - コールバック関数 | |
*/ | |
callback: (data: UnitradResult) => void; | |
killed: boolean; | |
data!: UnitradResult; | |
constructor(query: UnitradQuery, callback: (data: UnitradResult) => void) { | |
this.callback = callback; | |
this.killed = false; | |
this.search(query); | |
} | |
/** | |
* 検索の中止 | |
*/ | |
kill() { | |
this.killed = true; | |
} | |
search(query: UnitradQuery) { | |
if (!this.killed) { | |
_request('search', stripQuery(query)) | |
.then((r) => { | |
this.receive(r); | |
}).catch(() => { | |
setTimeout(() => this.search(query), 1000); | |
}) | |
} | |
} | |
polling() { | |
if (!this.killed) { | |
_request('polling', { | |
uuid: this.data.uuid, | |
version: this.data.version, | |
diff: 1, | |
timeout: 10 | |
}) | |
.then((r) => { | |
this.receive(r); | |
}).catch(() => { | |
setTimeout(() => this.polling(), 100); | |
}) | |
} | |
} | |
receive(data: UnitradResult) { | |
if (!this.killed) { | |
if (data.books_diff) { | |
Array.prototype.push.apply(this.data.books, data.books_diff.insert); | |
for (let key in data) { | |
if (data.hasOwnProperty(key) && key !== 'books_diff') { | |
this.data[key] = data[key]; | |
} | |
} | |
for (let d of data.books_diff.update) { | |
for (let key in d) { | |
if (d.hasOwnProperty(key) && key !== '_idx') { | |
if (Array.isArray(d[key]) === true) { | |
Array.prototype.push.apply(this.data.books[d._idx][key], d[key]); | |
} else if (d[key] instanceof Object) { | |
for (let k in d[key]) { | |
if (d[key].hasOwnProperty(k)) { | |
this.data.books[d._idx][key][k] = d[key][k]; | |
} | |
} | |
} else { | |
this.data.books[d._idx][key] = d[key]; | |
} | |
} | |
} | |
} | |
} else { | |
this.data = data; | |
} | |
this.callback(this.data); | |
if (data.running === true) { | |
console.log('[Unitrad] continue...'); | |
setTimeout(() => this.polling(), 500); | |
} else { | |
console.log('[Unitrad] complete.'); | |
} | |
} | |
} | |
} | |
/** | |
* クエリを共通形式にして返す | |
* @param query | |
* @returns {Object} | |
*/ | |
export function normalizeQuery(query: UnitradQuery): UnitradQuery { | |
let tmp: UnitradQuery = {}; | |
for (let k of FIELDS) { | |
tmp[k] = query[k] ? query[k] : ''; | |
} | |
return tmp | |
} | |
/** | |
* クエリが空かどうか判定する | |
* "region"のみの場合は空と判定する | |
* @param query | |
* @returns {boolean} | |
*/ | |
export function isEmptyQuery(query: UnitradQuery): boolean { | |
if (query) { | |
for (let k of FIELDS) { | |
if (k === 'region') continue; | |
if (query.hasOwnProperty(k) && query[k] !== '') return false | |
} | |
} | |
return true | |
} | |
/** | |
* クエリが同じかどうか判定する | |
* @param q1 比較元クエリ | |
* @param q2 比較先クエリ | |
* @returns {boolean} | |
*/ | |
export function isEqualQuery(q1: UnitradQuery, q2: UnitradQuery): boolean { | |
for (let k of FIELDS) { | |
if (k === 'region') continue; | |
if ((q1 && q1.hasOwnProperty(k) ? q1[k] : '') !== (q2 && q2.hasOwnProperty(k) ? q2[k] : '')) return false | |
} | |
return true | |
} | |
/** | |
* クエリを内容のあるプロパティだけにする | |
* @param query | |
* @returns {Object} query | |
*/ | |
export function stripQuery(query: UnitradQuery): UnitradQuery { | |
let tmp: UnitradQuery = {}; | |
for (let key of FIELDS) { | |
const k = key; | |
console.log(query[k]) | |
if (query.hasOwnProperty(k) && query[k] && query[k] !== '') { | |
tmp[k] = query[k]; | |
} | |
} | |
return tmp | |
} | |
/** | |
* マッピングデータを取得する | |
* @param region {String} リージョン | |
* @param callback(data) コールバック関数 | |
*/ | |
export function fetchMapping(region: string, callback: (data: any) => void): void { | |
_request('mapping', { | |
'region': region | |
}).then((r) => { | |
callback(r) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment