Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add seasons endpoint #208

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"operator-linebreak": ["error", "after"],

"import/extensions": "off",
"import/prefer-default-export": "off",

"jest/no-alias-methods": "off",

Expand Down
13,724 changes: 13,695 additions & 29 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"build": "npm run clean:dist && webpack",
"build:docs": "npm run clean:docs && jsdoc -c .jsdoc.json",
"clean": "npm run clean:dist && npm run clean:docs",
"clean:dist": "rm -rf web.js web.js.map node.js node.js.map web-dev.js web-dev.js.map node-dev.js node-dev.js.map",
"clean:docs": "rm -rf docs",
"clean:dist": "rimraf web.js web.js.map node.js node.js.map web-dev.js web-dev.js.map node-dev.js node-dev.js.map",
"clean:docs": "rimraf docs",
"ci": "npm run clean && npm run lint && npm run test && npm run build && npm run build:docs",
"lint": "eslint integration-tests/**/*.js src/**/*.js",
"prepublishOnly": "npm run build",
Expand Down Expand Up @@ -72,6 +72,7 @@
"jest": "26.4.2",
"jsdoc": "^3.6.6",
"q": "^1.5.1",
"rimraf": "^3.0.2",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
},
Expand Down
35 changes: 20 additions & 15 deletions src/base-classes/base-cacheable-object/base-cacheable-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ import BaseObject from '../base-object/base-object.js';
* from `getCacheId` is valid (see `_populateObject` for an example). Otherwise the cache will not
* be in the correct state.
*
* @extends {BaseObject}
* @augments {BaseObject}
*/
class BaseCacheableObject extends BaseObject {
static displayName = 'BaseCacheableObject';

/**
* Defers to `BaseObject._populateObject` and then caches the instance using the caching id from
* `getCacheId`.
*
* @override
*/
static _populateObject({
Expand All @@ -44,7 +45,8 @@ class BaseCacheableObject extends BaseObject {
* created. This implementation ensures each class has a unique cache of only instances of the
* BaseCacheableObject that does not overlap with other BaseCacheableObject classes. The keys of
* the cache should use the caching id implemented in `getCacheId`.
* @return {Object.<String, BaseCacheableObject>} The cache of BaseCacheableObjects.
*
* @returns {object.<string, BaseCacheableObject>} The cache of BaseCacheableObjects.
*/
static get cache() {
if (!this._cache) {
Expand All @@ -56,7 +58,8 @@ class BaseCacheableObject extends BaseObject {

/**
* Sets the cache object.
* @param {Object.<String, BaseCacheableObject>} cache
*
* @param {object.<string, BaseCacheableObject>} cache The cache object.
*/
static set cache(cache) {
this._cache = cache;
Expand All @@ -70,19 +73,19 @@ class BaseCacheableObject extends BaseObject {
}

/**
* Returns a cached instance matching the passed caching id if it exists. Otherwise, returns
* undefined.
* @param {Number} id This id must match the form of the caching id provided by `getCacheId`.
* @return {BaseCacheableObject|undefined}
*
* @param {number} id This id must match the form of the caching id provided by `getCacheId`.
* @returns {BaseCacheableObject|undefined} a cached instance matching the passed caching id if it
* exists. Otherwise, returns undefined.
*/
static get(id) {
return _.get(this.cache, id);
}

/**
* Should be overridden by each subclass. Returns an object containing all IDs used for API
* requests and caching.
* @return {Object}
* Should be overridden by each subclass.
*
* @returns {object} The object containing all IDs used for API requests and caching.
*/
static getIDParams() {
return {};
Expand All @@ -91,17 +94,18 @@ class BaseCacheableObject extends BaseObject {
/**
* Constructs and returns an id for the cache if possible from the passed params. If construction
* is not possible, returns undefined.
* @param {Object} idParams
* @return {string|undefined}
*
* @param {object} idParams The object containing all IDs used for API requests and caching.
* @returns {string|undefined} The id used for caching.
*/
static getCacheId(idParams) {
const cacheId = _.map(this.getIDParams(idParams), (value, key) => `${key}=${value};`).join('');
return _.isEmpty(cacheId) ? undefined : cacheId;
}

/**
* Returns an object containing all IDs used for API requests and caching for the instance.
* @return {Object}
*
* @returns {object} object containing all IDs used for API requests and caching for the instance.
*/
getIDParams() {
return this.constructor.getIDParams(this);
Expand All @@ -111,7 +115,8 @@ class BaseCacheableObject extends BaseObject {
* Returns the id used for caching. Important for classes that have multiple identifiers. Example:
* League is identified by its `leagueId` and its `seasonId`. This method prevents separate
* seasons from overriding each other's data.
* @return {String|undefined}
*
* @returns {string | undefined} The id used for caching.
*/
getCacheId() {
return this.constructor.getCacheId(this);
Expand Down
71 changes: 39 additions & 32 deletions src/base-classes/base-object/base-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { flattenObject } from '../../utils.js';
*/
class BaseObject {
/**
* @param {Object} options Properties to be assigned to the BaseObject. Must match the keys of the
* @param {object} options Properties to be assigned to the BaseObject. Must match the keys of the
* BaseObject's `responseMap` or valid options defined by the class's
* `constructor`.
*/
Expand All @@ -24,20 +24,23 @@ class BaseObject {
/**
* The class name. Minification will break `this.constructor.name`; this allows for readable
* logging even in minified code.
* @type {String}
*
* @type {string}
*/
static displayName = 'BaseObject';

/**
* Helper for processing items on `responseMap`s that are objects.
* @private
*
* @param {Object} options.data
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {Object} options.constructorParams Params to be passed to the instance's constructor.
* Useful for passing parent data, such as `leagueId`.
* @param {String} options.value The value of the responseMap entry being parsed.
* @return {*}
* @private
* @param {object} options The object containing the function parameters
* @param {object} options.data The data to be parsed onto the instance.
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {object} options.constructorParams Params to be passed to the instance's constructor.
* Useful for passing parent data, such as `leagueId`.
* @param {string} options.value The value of the responseMap entry being parsed.
* @returns {*} The result of the parsing. Will Throw an Error if the value does not have
* a manualParse function or BaseObject.
*/
static _processObjectValue({
data, constructorParams, instance, value
Expand Down Expand Up @@ -69,39 +72,40 @@ class BaseObject {
/**
* Helper method for `_populateObject` that houses the attribute mapping logic. Should never be
* used by other methods. See {@link ResponseMapValueObject} for `responseMap` documentation.
* @private
*
* @param {Object} options.data
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {Object} options.constructorParams Params to be passed to the instance's constructor.
* Useful for passing parent data, such as `leagueId`.
* @param {Boolean} options.isDataFromServer When true, the data came from the ESPN API over the
* wire. When false, the data came locally.
* @param {String} options.key The key of the responseMap entry being parsed.
* @param {String} options.value The value of the responseMap entry being parsed.
* @private
* @param {object} options The object containing the function parameters
* @param {object} options.data The data to be parsed onto the instance.
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {object} options.constructorParams Params to be passed to the instance's constructor.
* Useful for passing parent data, such as `leagueId`.
* @param {boolean} options.isDataFromServer When true, the data came from the ESPN API over the
* wire. When false, the data came locally.
* @param {string} options.key The key of the responseMap entry being parsed.
* @param {string} options.value The value of the responseMap entry being parsed.
*/
static _processResponseMapItem({
data, constructorParams, instance, isDataFromServer, key, value
}) {
/**
* @typedef {Object} BaseObject~ResponseMapValueObject
* @typedef {object} BaseObject~ResponseMapValueObject
*
* The `responseMap` can have two values: a string or a ResponseMapValueObject. When string, the
* data found on that response is directly mapped to the BaseObject without mutation. When
* ResponseMapValueObject, the data at the `key` will be used to create BaseObject(s) or
* manually parsed with a provided `manualParse function`. Either result is attached to the
* BaseObject being populated.
*
* @property {String} key The key on the response data where the data can be found. This must be
* @property {string} key The key on the response data where the data can be found. This must be
* defined.
* @property {BaseObject} BaseObject The BaseObject to create with the response data.
* @property {Boolean} isArray Whether or not the response data is an array. Useful for
* @property {boolean} isArray Whether or not the response data is an array. Useful for
* attributes such as "teams".
* @property {Boolean} defer Whether or not to wait to parse the entry until a second pass of
* @property {boolean} defer Whether or not to wait to parse the entry until a second pass of
* the map. This is useful for populating items with cached instances
* that are not guaranteed to be parsed/cached during initial parsing.
* Example: Using Team instances on League.
* @property {function} manualParse A function to manually apply logic to the response. This
* @property {Function} manualParse A function to manually apply logic to the response. This
* function must return its result to be attached to the
* populated BaseObject. The arguments to this function are:
* (data at the key), (the whole response), (the instance being
Expand Down Expand Up @@ -153,13 +157,15 @@ class BaseObject {
/**
* Returns the passed instance of the BaseObject populated with the passed data, mapping the
* attributes defined in the value of responseMap to the matching key.
* @private
*
* @param {Object} options.data The data to map onto the passed instance.
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {Boolean} options.isDataFromServer When true, the data came from ESPN. When false, the
* data came locally.
* @return {BaseObject} The mutated BaseObject instance.
* @private
* @param {object} options The object containing the function parameters
* @param {object} options.data The data to be parsed onto the instance.
* @param {BaseObject} options.instance The instance to populate. This instance will be mutated.
* @param {object} options.constructorParams Params to be passed to the instance's constructor.
* @param {boolean} options.isDataFromServer When true, the data came from ESPN. When false, the
* data came locally.
* @returns {BaseObject} The mutated BaseObject instance.
*/
static _populateObject({
data, constructorParams, instance, isDataFromServer
Expand Down Expand Up @@ -194,10 +200,11 @@ class BaseObject {
* Returns a new instance of the BaseObject populated with the passed data that came from ESPN,
* mapping the attributes defined in the value of responseMap to the matching key. Use this method
* when constructing BaseObjects with server responses.
* @param {Object} data Data originating from the server.
* @param {Object} constructorParams Params to be passed to the instance's constructor. Useful
*
* @param {object} data Data originating from the server.
* @param {object} constructorParams Params to be passed to the instance's constructor. Useful
* for passing parent data, such as `leagueId`.
* @return {BaseObject} A new instance of the BaseObject populated with the passed data.
* @returns {BaseObject} A new instance of the BaseObject populated with the passed data.
*/
static buildFromServer(data, constructorParams) {
const instance = new this(constructorParams);
Expand Down
1 change: 1 addition & 0 deletions src/base-classes/base-object/base-object.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// eslint-disable-next-line max-classes-per-file
import _ from 'lodash';

import { flattenObject } from '../../utils.js';
Expand Down
13 changes: 12 additions & 1 deletion src/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FreeAgentPlayer from '../free-agent-player/free-agent-player';
import League from '../league/league';
import NFLGame from '../nfl-game/nfl-game';
import Team from '../team/team';
import Season from '../season/season';

axios.defaults.baseURL = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/';

Expand Down Expand Up @@ -37,6 +38,16 @@ class Client {
}
}

/**
* Returns all seasons and the current scoring period for each.
*
* @returns {Season[]} All seasons and the current scoring period for each.
*/
getSeasons() {
return axios.get('', this._buildAxiosConfig())
.then((response) => _.map(response.data, (season) => Season.buildFromServer(season)));
}

/**
* Returns all boxscores for a week.
*
Expand Down Expand Up @@ -212,7 +223,7 @@ class Client {
* @returns {object} An axios config with cookies added if set on instance
* @private
*/
_buildAxiosConfig(config) {
_buildAxiosConfig(config = {}) {
if ((this.espnS2 && this.SWID)) {
const headers = { Cookie: `espn_s2=${this.espnS2}; SWID=${this.SWID};` };
return _.merge({}, config, { headers, withCredentials: true });
Expand Down
Loading