From 469c2987536c490762efe82ef6dfa5e6dfbb8d21 Mon Sep 17 00:00:00 2001 From: Anthony Correa Date: Thu, 17 Aug 2023 06:51:08 -0500 Subject: [PATCH] first commit --- .env.sample | 2 + .github/FUNDING.yml | 1 + .gitignore | 174 + README.md | 3 + app.js | 86 + bin/www | 92 + certs/.gitkeep | 0 package-lock.json | 3566 +++++++++++ package.json | 50 + public/css/gamecard.css | 661 ++ public/css/paper.css | 71 + public/css/project.css | 57 + public/fonts/futura-now/stylesheet.css | 6 + public/fonts/helvetica-now/stylesheet.css | 7 + public/fonts/inconsolata/stylesheet.css | 4 + public/fonts/m+1m/m+1m.css | 38 + public/fonts/vera/bitstreamvera.css | 68 + public/fonts/verdana/verdanapro.css | 123 + public/js/load_from_teamsnap.js | 115 + public/js/teamsnap.js | 6810 +++++++++++++++++++++ public/media/baseball-diamond.svg | 10 + public/media/benchcoach.svg | 23 + routes/auth.js | 128 + routes/index.js | 390 ++ views/error.pug | 8 + views/event.pug | 46 + views/events.pug | 37 + views/gamecard.pug | 409 ++ views/home.pug | 29 + views/lineup.pug | 139 + views/login.pug | 19 + views/team.pug | 17 + views/teams.pug | 14 + 33 files changed, 13203 insertions(+) create mode 100644 .env.sample create mode 100644 .github/FUNDING.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app.js create mode 100755 bin/www create mode 100644 certs/.gitkeep create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/css/gamecard.css create mode 100644 public/css/paper.css create mode 100644 public/css/project.css create mode 100644 public/fonts/futura-now/stylesheet.css create mode 100644 public/fonts/helvetica-now/stylesheet.css create mode 100644 public/fonts/inconsolata/stylesheet.css create mode 100644 public/fonts/m+1m/m+1m.css create mode 100644 public/fonts/vera/bitstreamvera.css create mode 100644 public/fonts/verdana/verdanapro.css create mode 100644 public/js/load_from_teamsnap.js create mode 100644 public/js/teamsnap.js create mode 100644 public/media/baseball-diamond.svg create mode 100644 public/media/benchcoach.svg create mode 100644 routes/auth.js create mode 100644 routes/index.js create mode 100644 views/error.pug create mode 100644 views/event.pug create mode 100644 views/events.pug create mode 100644 views/gamecard.pug create mode 100644 views/home.pug create mode 100644 views/lineup.pug create mode 100644 views/login.pug create mode 100644 views/team.pug create mode 100644 views/teams.pug diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..326f811 --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +TEAMSNAP_CLIENT_ID= +TEAMSNAP_CLIENT_SECRET= \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..4d380a7 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: anthonyscorrea diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5a96aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,174 @@ +.env +var + +#ide +/.nova + +# certs +certs/*.pem + +# fonts +*.ttf +*.woff + +# Node.js +https://github.com/github/gitignore/blob/main/Node.gitignore +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# MacOS +# https://github.com/github/gitignore/blob/main/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ba165e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# teamsnap-benchcoach + +"An assistant for TeamSnap" diff --git a/app.js b/app.js new file mode 100644 index 0000000..d1a2e5c --- /dev/null +++ b/app.js @@ -0,0 +1,86 @@ +require("dotenv").config(); + +var createError = require("http-errors"); +var express = require("express"); +var path = require("path"); +var cookieParser = require("cookie-parser"); +var session = require("express-session"); +var csrf = require("csurf"); +var passport = require("passport"); +var logger = require("morgan"); +global.XMLHttpRequest = require("xhr2"); +var teamsnap = require("teamsnap.js"); + +var indexRouter = require("./routes/index"); +var authRouter = require("./routes/auth"); + +var app = express(); + +// view engine setup +app.set("views", path.join(__dirname, "views")); +app.set("view engine", "pug"); + +app.locals.pluralize = require("pluralize"); + +app.use(logger("dev")); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, "public"))); +app.use( + "/css", + express.static(path.join(__dirname, "node_modules/bootstrap/dist/css")) +); +app.use( + "/css", + express.static( + path.join(__dirname, "node_modules/@teamsnap/teamsnap-ui/dist/css") + ) +); +app.use( + "/font", + express.static(path.join(__dirname, "node_modules/bootstrap-icons/font")) +); +app.use( + session({ + teamsnap_token: "", + current_team: "", + secret: "keyboard cat", + resave: false, // don't save session if unmodified + saveUninitialized: false, // don't create session until something stored + }) +); +app.use(csrf()); +app.use(passport.authenticate("session")); +app.use(function (req, res, next) { + var msgs = req.session.messages || []; + res.locals.messages = msgs; + res.locals.hasMessages = !!msgs.length; + req.session.messages = []; + next(); +}); +app.use(function (req, res, next) { + res.locals.csrfToken = req.csrfToken(); + next(); +}); + +app.use("/", authRouter); +app.use("/", indexRouter); + +// catch 404 and forward to error handler +app.use(function (req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function (err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get("env") === "development" ? err : {}; + console.log("error:", err); + // render the error page + res.status(err.status || 500); + res.render("error", { message: err.message }); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..f940195 --- /dev/null +++ b/bin/www @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require("../app"); +var http = require("http"); +var https = require("https"); +var fs = require("fs"); +var debug = require("debug")("https"); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || "3000"); +app.set("port", port); + +/** + * Create HTTPS server. + */ +const https_options = { + key: fs.readFileSync("certs/key.pem"), + cert: fs.readFileSync("certs/cert.pem"), +}; + +var server = https.createServer(https_options, app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on("error", onError); +server.on("listening", onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== "listen") { + throw error; + } + + var bind = typeof port === "string" ? "Pipe " + port : "Port " + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case "EACCES": + console.error(bind + " requires elevated privileges"); + process.exit(1); + break; + case "EADDRINUSE": + console.error(bind + " is already in use"); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; + debug("Listening on " + bind); +} diff --git a/certs/.gitkeep b/certs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d321046 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3566 @@ +{ + "name": "teamsnap-benchcoach", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "teamsnap-benchcoach", + "version": "0.0.0", + "license": "Unlicense", + "dependencies": { + "@teamsnap/teamsnap-ui": "^3.12.3", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "connect-ensure-login": "^0.1.1", + "cookie-parser": "~1.4.4", + "csurf": "^1.11.0", + "debug": "~2.6.9", + "dotenv": "^8.6.0", + "express": "^4.18.2", + "express-session": "^1.17.2", + "http-errors": "~1.6.3", + "mkdirp": "^1.0.4", + "morgan": "~1.9.1", + "papaparse": "^5.4.1", + "passport": "^0.6.0", + "passport-teamsnap": "^1.1.1", + "pluralize": "^8.0.0", + "pug": "^3.0.2", + "teamsnap.js": "^1.62.1", + "xhr2": "^0.2.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/anthonyscorrea" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "peer": true, + "dependencies": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "peer": true + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "peer": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "peer": true, + "dependencies": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "peer": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "peer": true, + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "peer": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "peer": true, + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "peer": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/node": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.22.10.tgz", + "integrity": "sha512-FpSgdjIPabpEetDxtKYAcXCs0qRh12S2D40rhpRoo0w5h7/7Tu2ZroaX99cbKFNDODiSs484sZ1q0kutJbZ2iQ==", + "dependencies": { + "@babel/register": "^7.22.5", + "commander": "^4.0.1", + "core-js": "^3.30.2", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.14.0", + "v8flags": "^3.1.1" + }, + "bin": { + "babel-node": "bin/babel-node.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/register": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.22.5.tgz", + "integrity": "sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ==", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/runtime": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", + "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "peer": true + }, + "node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@teamsnap/teamsnap-ui": { + "version": "3.12.3", + "resolved": "https://registry.npmjs.org/@teamsnap/teamsnap-ui/-/teamsnap-ui-3.12.3.tgz", + "integrity": "sha512-LS7f4hTMyNRo70eGQDvKLig5Op9FFCZClEqSsdDodzIYnsAtkUDNOCk2wrL1fSLlgH2xOygVAkDkpPq4zlgZNg==", + "dependencies": { + "@babel/node": "^7.5.5", + "@babel/runtime": "^7.5.5", + "core-js": "^3.1.4", + "lodash": "^4.17.15" + }, + "engines": { + "node": ">=14.7.0" + }, + "peerDependencies": { + "react": "^17.0.1" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/assert-never": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", + "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "dependencies": { + "@babel/types": "^7.9.6" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bootstrap": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.1.tgz", + "integrity": "sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.5.tgz", + "integrity": "sha512-oSX26F37V7QV7NCE53PPEL45d7EGXmBgHG3pDpZvcRaKVzWMqIRL9wcqJUyEha1esFtM3NJzvmxFXDxjJYD0jQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001521", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", + "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha512-QjQ1T4BqyHv19k6XSfdhy/QLlIOhywz0ekBUCa9h71zYMJlfDTGan/Z1JXzYkZ6v8R+GhvL/p4FZPbPW8WNXlg==", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/collection-json": { + "version": "0.4.0", + "resolved": "git+ssh://git@github.com/7elephants/collection-json.js.git#e74485c5fcf610409ac14bc3049676de8ebf5352", + "license": "MIT", + "dependencies": { + "coffee-script": "~1.3.3", + "passport": "~0.4.0", + "passport-oauth2": "~1.4.0", + "request": "~2.11.4", + "underscore": "~1.4.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/collection-json/node_modules/passport": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", + "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/collection-json/node_modules/passport-oauth2": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz", + "integrity": "sha512-aFrjWoTSFLob+JNvmPxCc+zyv/W7VpBx8WS4vZ8Snm6sm25BbRgobIcmSjpaRt4ciyS5ldEIdC+WFbd8zP8ggA==", + "dependencies": { + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/connect-ensure-login": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-ensure-login/-/connect-ensure-login-0.1.1.tgz", + "integrity": "sha512-u0LGY/YXgkqdD4uVz8Gkri0adby5SBPYIFQvIa4FjBIaZUN0yuZPVHsjAA2bUiprGyjh8NlqxPUcIzzfTiXhQQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "peer": true + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-js": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.0.tgz", + "integrity": "sha512-rd4rYZNlF3WuoYuRIDEmbR/ga9CeuWX9U05umAvgrrZoHY4Z++cp/xwPQMvUpBB4Ag6J8KfD80G0zwCyaSxDww==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/csrf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", + "dependencies": { + "rndm": "1.2.0", + "tsscmp": "1.0.6", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csurf": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", + "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", + "deprecated": "Please use another csrf package", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "csrf": "3.1.0", + "http-errors": "~1.7.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/csurf/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/csurf/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/csurf/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==" + }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.492", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.492.tgz", + "integrity": "sha512-36K9b/6skMVwAIEsC7GiQ8I8N3soCALVSHqWHzNDtGemAcI9Xu8hP02cywWM0A794rTHm0b0zHPeLJHtgFVamQ==", + "peer": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "1.0.0-rc3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", + "integrity": "sha512-Z5JWXWsFDI8x73Rt/Dc7SK/EvKBzudhqIVBtEhcAhtoevCTqO3YJmctGBLzT0Ggg39xFcefkXt00t1TYLz6D0w==", + "dependencies": { + "async": "^1.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/form-data/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "dependencies": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "peer": true + }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", + "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", + "dependencies": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/papaparse": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", + "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-teamsnap": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/passport-teamsnap/-/passport-teamsnap-1.1.1.tgz", + "integrity": "sha512-OUGHHDnyUyIYzdyUQ0nNqMU//ui0wPiLrZ52iJ075sw2FFG2DAv/McMT1eLqDybJFCJr4ymB3bgxuxbu7bgMhQ==", + "dependencies": { + "collection-json": "github:7elephants/collection-json.js", + "debug": "~2.2.0", + "passport-oauth2": "^1.4.0", + "pkginfo": "^0.2.3" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-teamsnap/node_modules/debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha512-X0rGvJcskG1c3TgSCPqHJ0XJgwlcvOC7elJ5Y0hYuKBZoVqWpAMfLOeIh2UI/DCQ5ruodIjvsugZtjUYUw2pUw==", + "dependencies": { + "ms": "0.7.1" + } + }, + "node_modules/passport-teamsnap/node_modules/ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha512-lRLiIR9fSNpnP6TC4v8+4OU7oStC01esuNowdQ34L+Gk8e5Puoc88IqJ+XAY/B3Mn2ZKis8l8HX90oU8ivzUHg==" + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "peer": true + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkginfo": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz", + "integrity": "sha512-7W7wTrE/NsY8xv/DTGjwNIyNah81EQH0MWcTzrHL6pOpMocOGZc0Mbdz9aXxSrp+U0mSmkU8jrNCDCfUs3sOBg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pug": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", + "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "dependencies": { + "pug-code-gen": "^3.0.2", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", + "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.0.0", + "pug-runtime": "^3.0.0", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", + "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/raw-body/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/request": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/request/-/request-2.11.4.tgz", + "integrity": "sha512-lL+DgCpVn4b8scEhyGGel3kAipjMyHHfIEcP1SCbdJq9jCuaJLSBELJ7pel5RhK3oXl/xTI9HecR4NnHSV+Hrg==", + "bundleDependencies": [ + "form-data", + "mime" + ], + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "engines": [ + "node >= 0.3.6" + ], + "dependencies": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "0.0.3", + "inBundle": true, + "dependencies": { + "async": "~0.1.9", + "combined-stream": "0.0.3", + "mime": "~1.2.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/async": { + "version": "0.1.9", + "inBundle": true, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/combined-stream": { + "version": "0.0.3", + "inBundle": true, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "engines": { + "node": "*" + } + }, + "node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream": { + "version": "0.0.5", + "inBundle": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/request/node_modules/mime": { + "version": "1.2.7", + "inBundle": true, + "engines": { + "node": "*" + } + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/teamsnap.js": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/teamsnap.js/-/teamsnap.js-1.62.1.tgz", + "integrity": "sha512-CivGwesQSxklXSQjZbKNnfvqFW/hDOgC/F+DipUkM8tiks6DNuM5FsmzLcl2HgmJMrpuuhGrwkKdPZbmSus5Cg==", + "dependencies": { + "form-data": "1.0.0-rc3", + "xmlhttprequest": "1.8.0" + }, + "engines": { + "node": ">=7.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha512-ZqGrAgaqqZM7LGRzNjLnw5elevWb5M8LEoDMadxIW3OWbcv72wMMgKdwOKpd5Fqxe8choLD8HN3iSj3TUh/giQ==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/xhr2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz", + "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "engines": { + "node": ">=0.4.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4ef188f --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "teamsnap-benchcoach", + "version": "0.0.0", + "private": true, + "description": "An assistant for teamsnap", + "keywords": [ + "teamsnap" + ], + "author": { + "name": "Tony Correa", + "email": "a@correa.co" + }, + "homepage": "https://benchcoach.ascorrea.com", + "repository": { + "type": "git", + "url": "git://github.com/anthonyscorrea/teamsnap-benchcoach.git" + }, + "bugs": { + "url": "https://github.com/anthonyscorrea/teamsnap-benchcoach/issues" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/anthonyscorrea" + }, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "@teamsnap/teamsnap-ui": "^3.12.3", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "connect-ensure-login": "^0.1.1", + "cookie-parser": "~1.4.4", + "csurf": "^1.11.0", + "debug": "~2.6.9", + "dotenv": "^8.6.0", + "express": "^4.18.2", + "express-session": "^1.17.2", + "http-errors": "~1.6.3", + "mkdirp": "^1.0.4", + "morgan": "~1.9.1", + "papaparse": "^5.4.1", + "passport": "^0.6.0", + "passport-teamsnap": "^1.1.1", + "pluralize": "^8.0.0", + "pug": "^3.0.2", + "teamsnap.js": "^1.62.1", + "xhr2": "^0.2.1" + } +} diff --git a/public/css/gamecard.css b/public/css/gamecard.css new file mode 100644 index 0000000..cb11ee9 --- /dev/null +++ b/public/css/gamecard.css @@ -0,0 +1,661 @@ +@import url("../css/paper.css"); +@import url("../fonts/vera/bitstreamvera.css"); +@import url("../fonts/verdana/verdanapro.css"); +@import url("../fonts/m+1m/m+1m.css"); +@import url("../fonts/helvetica-now/stylesheet.css"); +@import url("../fonts/futura-now/stylesheet.css"); +@import url("../fonts/inconsolata/stylesheet.css"); + +:root { + --color-success: #b7e1cd; + --color-danger: #f4c7c3; + --color-neutral: #acc9fe; + --color-warning: rgb(249, 228, 180); + --color-grey-100: #f8f9fa; + --color-grey-200: #e9ecef; + --color-grey-300: #dee2e6; + --color-grey-400: #ced4da; + --color-grey-500: #adb5bd; + --color-grey-600: #6c757d; + --color-grey-700: #495057; + --color-grey-800: #343a40; + --color-grey-900: #212529; + --row-height: 14px; + --monospace-font: "Inconsolata"; +} + +body { + font-family: "Helvetica Now"; + position: relative; + font-size: 11px; +} + +table { + position: inherit; + font-size: inherit; + border-collapse: collapse; + empty-cells: show; + white-space: nowrap; + text-overflow: ellipsis; + overflow-x: hidden; + overflow-y: hidden; + width: 100%; + border: 0.5px solid black; + display: inline-table; +} + +.bar-right { + float: right; +} + +.bar-left { + float: left; +} + +th, +td { + /* vertical-align: middle; */ + /* line-height: 1.3em; */ + overflow: hidden; + padding: 0 2px 0 2px; /* top right bottom left */ +} + +tr { + border-bottom-width: 0.5px; + border-color: grey; + border-bottom-style: solid; +} + +tr:last-child { + border-bottom-color: black; +} + +tr:first-child { + border-top-color: black; +} + +tr:nth-child(odd) { + background-color: rgb(242, 242, 242, 0.85); +} + +tr:nth-child(even) { + background-color: rgb(256, 256, 256, 0.85); +} + +td:not(:first-child) { + border-left: 0.5px solid grey; +} + +th { + font-stretch: extra-condensed; + width: 1em; + text-align: center; + text-transform: uppercase; +} + +td:empty::after, +th:empty::after { + content: "\00a0"; +} + +td.player-name { + text-transform: uppercase; + font-stretch: 80%; + /* font-family: var(--monospace-font); */ +} + +td.position, +td.jersey-number { + font-family: var(--monospace-font); + width: 2ch; + text-align: right; + overflow: hidden; +} + +.index-card .gamecard { + position: relative; +} + +.B5 > .gamecard { + /* height: auto; */ + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr 1fr; + /* padding: 0.15in; */ + /* grid-gap: 0.25in 0.15in; */ + + /* background-image: url("../2023-G08-0523.png"); */ + background-size: 100%; +} + +.gamecard > section { + /* margin: 0.07in; */ + box-sizing: content-box; + /* border: 4px solid var(--color-grey-200); */ + /* border-radius: 4px; */ + overflow: hidden; + outline: 0.5px dashed lightgrey; + /* border-right: 1px dotted black; */ + display: flex; + align-items: stretch; +} + +.gamecard > section > div { + margin: 0.15in; + outline: 0.5px solid black; + display: flex; + flex: 1; /* consumes all free space (taking full height) */ + align-items: stretch; + height: auto; +} + +#lineup-card-dugout div.grid-container, +#lineup-card-dugout-empty div.grid-container { + display: grid; + grid-template-columns: 60% auto; + grid-template-rows: fit-content(16px) auto; + grid-template-areas: + "header header" + "sarting-lineup-table substitution-table"; +} + +#lineup-card-exchange div.grid-container, +#lineup-card-exchange-empty div.grid-container { + display: grid; + grid-template-columns: auto; + grid-template-rows: fit-content(16px) auto; + grid-template-areas: + "header" + "sarting-lineup-table"; +} + +.lineup-card div.grid-container > .section-header { + grid-area: "header"; + font-size: 14px; + font-weight: bold; +} + +.lineup-card div.grid-container > .section-header:empty::after { + content: "\00a0"; +} + +div.grid-container > .starting-lineup-table { + grid-area: "starting-lineup-table"; +} + +div.grid-container > .substitution-table { + grid-area: "substitution-table"; +} + +.lineup-card thead th { + color: var(--color-grey-600); + font-size: 0.7em; +} + +.lineup-card th.sequence { + color: var(--color-grey-600); + font-size: inherit; +} + +.lineup-card table { + font-size: 22px; +} + +.lineup-card td { + height: 33.5px; +} + +#lineup-card-exchange tr, +#lineup-card-exchange-empty tr, +#lineup-card-dugout .starting-lineup-table tr, +#lineup-card-dugout .substitution-table tr:nth-child(odd) { + border-top: 1px solid black; +} + +#lineup-card-exchange tr, +#lineup-card-exchange-empty tr, +#lineup-card-dugout .starting-lineup-table tr, +#lineup-card-dugout .substitution-table tr:nth-child(even) { + border-bottom: 1px solid black; +} + +#lineup-card-exchange td.player-name { + font-stretch: 100%; +} + +#lineup-card-dugout td.player-name { + width: 10ch; +} + +#lineup-card-dugout td.substitution, +#lineup-card-dugout-empty td.substitution { + font-size: 11px; + height: 15px; +} + +.lineup-card .position, +.lineup-card .jersey-number { + width: 2ch; +} + +#lineup-card-dugout .position, +#lineup-card-dugout .jersey-number { + font-stretch: 75%; + padding-left: 2.5px; + padding-right: 2.5px; +} + +.lineup-card .section-header { + padding-left: 1px; + padding-right: 1px; + font-size: inherit; + text-transform: uppercase; + font-stretch: 85%; +} + +#todays-game > div { + display: grid; + /* gap: 0.5px; */ + grid-template-columns: 110px auto; + grid-template-rows: calc(var(--row-height) * 1) auto auto; + grid-template-areas: + "header header" + "offense defense" + "footer footer"; +} + +#defense-pane { + position: relative; + /* box-sizing: border-box; */ + padding: 4px 4px 0px 4px; /* top right bottom left */ + display: flex; + grid-area: defense; + border-left: 0.5px solid black; + border-bottom: 0.5px solid black; +} + +#offense-pane { + position: relative; + /* box-sizing: border-box; */ + height: 100%; + grid-area: offense; + border-bottom: 0.5px solid black; + /* outline: 0.5px solid black; */ +} + +#offense-pane table { + height: 100%; + border: none; +} + +#defense-pane .container { + width: 100%; + display: grid; + grid-template-rows: auto; +} + +#defense-pane .pitching-container { + margin: auto 0 0 0; /* top right bottom left */ +} + +#defense-pane .field-container { + display: grid; + grid-template-rows: auto; + /* margin: top; */ + width: 100%; + /* background: url("../baseball-diamond.svg"); */ + background-size: 100%; + background-position: center 10px; + background-repeat: no-repeat; + gap: 6px; + z-index: 2; +} + +#defense-pane img { + position: absolute; + z-index: -1; +} + +.defense-slot-set { + width: 77px; +} + +.index-card .defense-slot-set { + width: 65px; +} + +.index-card .defense-slot-set .player-name { + font-stretch: 70%; +} + +.pitching-container .defense-slot-set { + width: 100%; +} + +.container .row { + width: 100%; + display: flex; + align-items: center; +} + +.section-header { + background-color: #cadcf9; + font-size: 8.8px; + /* outline: 1px solid black; */ + /* height: var(--row-height); */ + width: auto; + grid-area: header; + text-align: center; + padding-left: 10px; + padding-right: 10px; + border-bottom: 0.5px solid black; + z-index: 1; +} + +.footer { + /* height:var(--row-height); */ + position: relative; + box-sizing: border-box; + grid-area: footer; + /* border: 1px solid black; */ + height: 100%; +} + +.footer table { + height: 100%; + outline: none; + border-style: none; +} + +.footer tr { + background-color: white; + outline: none; + border-bottom: 0.5px solid var(--color-grey-500); +} + +.footer tr :last-child { + background-color: white; + outline: none; + border-bottom-style: none; +} +.footer th { + text-align: left; + color: var(--color-grey-600); +} +.footer td { + height: var(--row-height); + + border: none; +} + +.footer td:empty::after { + content: ""; +} + +.cell-checkbox { + font-size: 0.75em; +} + +.in-starting-lineup { + font-weight: bold; +} + +.gametitle { + font-weight: bold; + text-transform: uppercase; + font-stretch: semi-condensed; +} + +.homeaway { + text-transform: uppercase; + font-stretch: normal; + font-weight: bolder; + float: right; + text-transform: uppercase; +} + +.cell-smalltext { + font-stretch: condensed; + font-size: 10px; +} + +.statscell { + font-family: "m+1m"; + text-align: center; + font-stretch: extra-condensed; + font-size: 9px; + width: 60px; +} + + { + text-transform: uppercase; +} + +.condensedNameCell { + width: 70px; + text-transform: uppercase; + font-stretch: condensed; +} + +.cell-square { + height: var(--row-height); + width: 14px; + text-align: center; +} + +.cell-square.narrow { + width: 10px; +} +.cell-mono { + font-family: "m+1m"; +} + +.cell-condensed { + font-stretch: condensed; +} + +.available-status-code-1 { + color: rgb(0, 85, 0); + background-color: #b7e1cd; +} + +.available-status-code-0 { + color: rgb(170, 0, 0); + background-color: #f4c7c3; +} + +.past.available-status-code-0, +.past.available-status-code-null { + color: var(--color-grey-600); + background-color: inherit; +} + +.past.available-status-code-1 { + color: inherit; + background-color: var(--color-warning); +} + +.past.available-status-code-1.started { + color: inherit; + background-color: inherit; +} + +.available-status-code-2 { + color: blue; + background-color: #acc9fe; +} + +#roster-and-history .player-name, +#roster-and-history .jersey-number { + color: black; +} + +#roster-and-history .player-name { + font-stretch: normal; +} + +.starting { + font-weight: bold; +} + +#roster-and-history > div > table { + /* font-size: 10.5px; */ + padding: 0; + line-height: 1em; + /* outline: 0.5px black; */ +} + +#roster-and-history td, +#roster-and-history th { + border-left: none; + border-right: none; + padding: 0.2em 0.1em 0.2em 0.1em; /* top right bottom left */ +} + +#roster-and-history td.player-name { + text-align: left; +} + +#roster-and-history th { + background-color: #cadcf9; + color: black; + border: none; +} + +#roster-and-history thead > tr, +#roster-and-history tfoot > tr { + border-bottom: solid black 1px; +} + +#roster-and-history tbody { + border-bottom: solid black 1px; +} + +#roster-and-history td[id^="avail"][id$="today-plus-1"], +#roster-and-history .pitcher, +#roster-and-history .player-stats, +#roster-and-history td[id^="avail"][id$="today-minus-1"] { + border-left-width: 1px; + border-left-style: solid; + border-left-color: black; +} + +#roster-and-history td.jersey-number { + border-left: 0.5px solid lightgrey; +} + +#roster-and-history td.today-minus-4 { + border-right: 1px solid black; +} + +#roster-and-history tr.border-top { + border-top: 1px solid black; +} + +#roster-and-history #today-availability { + font-stretch: normal; + text-transform: uppercase; + font-size: 0.8em; +} + +.player-stats { + font-family: var(--monospace-font); + font-size: 1em; + font-stretch: 60%; + font-weight: 300; +} + +#roster-and-history td.position-capability, +th.position-capability { + font-size: 8px; + font-stretch: 50%; + width: 5px; + text-align: center; + padding: 0; +} + +#roster-and-history th.position-capability { + font-size: inherit; +} + +td.position-capability:not(:empty) { + color: var(--color-grey-700); + background-color: var(--color-grey-200); +} + +td.is-present-checkbox { + font-size: 0.5em; + text-align: center; + color: white; + /* text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, + 1px 1px 0 #000; */ +} + +td.is-present-checkbox.available-status-code-0 > span { + display: none; +} + +td.is-present-checkbox.available-status-code-None > span { + display: none; +} + +td.availability { + font-family: var(--monospace-font); + font-stretch: condensed; + text-align: center; + max-width: 0.8em; + min-width: 0.8em; +} + +.availability.future, +.availability.past { + font-family: var(--monospace-font); + font-stretch: condensed; + font-weight: normal; + font-size: 0.8em; + padding: 0.1em; + text-transform: uppercase; +} + +#roster-test .player-name { + font-weight: bold; + text-transform: uppercase; + grid-area: player-name; +} + +#roster-test .jersey-number { + font-weight: bolder; + font-stretch: extra-condensed; + grid-area: jersey-number; +} + +#roster-test .player-stats { + grid-area: player-stats; +} + +#roster-test .diamond { + grid-area: diamond; + overflow: hidden; + display: inline-block; + height: 10px; + /* height:10px; */ +} + +.rotate { + transform: rotate(270deg); +} + +.delimiter, +.decimal-point { + font-family: Helvetica Now; + font-stretch: expanded; + color: var(--color-grey-500); +} + +th .decimal-point { + color: rgb(0, 0, 0, 0); +} + +th .delimiter { + color: var(--color-grey-500); +} diff --git a/public/css/paper.css b/public/css/paper.css new file mode 100644 index 0000000..7d04cd9 --- /dev/null +++ b/public/css/paper.css @@ -0,0 +1,71 @@ +@page { + margin: 0; + size: B5; +} +body { + margin: 0; +} +.sheet { + margin: 0; + overflow: hidden; + position: relative; + box-sizing: border-box; + page-break-after: always; +} + +/** Paper sizes **/ +body.B5 .sheet { + width: 182mm; + height: 257mm; +} + +body.index-card .sheet { + width: 3.5in; + height: 5in; +} + +/** For screen preview **/ +@media screen { + body { + background: #e0e0e0; + } + .sheet { + background: white; + box-shadow: 0 0.5mm 2mm rgba(0, 0, 0, 0.3); + margin: 5mm auto; + } +} + +/** Fix for Chrome issue #273306 **/ +@media print { + body.A3.landscape { + width: 420mm; + } + body.A3, + body.A4.landscape { + width: 297mm; + } + body.A4, + body.A5.landscape { + width: 210mm; + } + body.A5 { + width: 148mm; + } + body.B5 { + width: 182mm; + } + body.B5.landscape { + width: 257mm; + } + body.letter, + body.legal { + width: 216mm; + } + body.letter.landscape { + width: 280mm; + } + body.legal.landscape { + width: 357mm; + } +} diff --git a/public/css/project.css b/public/css/project.css new file mode 100644 index 0000000..c132114 --- /dev/null +++ b/public/css/project.css @@ -0,0 +1,57 @@ +/* These styles are generated from project.scss. */ +@import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"); +.alert-debug { + color: black; + background-color: white; + border-color: #d6e9c6; +} + +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.navbar-brand { + text-transform: uppercase; + font-weight: bolder; +} + +.bg-navbar { + background: #212529; +} + +.btn-teamsnap { + background-color: #ff8f00; + border-color: #cc7200; + color: #ffffff; + border-bottom-width: 2px; + border-radius: 4px; + cursor: pointer; + display: inline-block; + font-family: "Open Sans", Helvetica, sans-serif; + font-size: 13px; + font-weight: 600; + height: 32px; + line-height: 29px; + margin: 0; + padding: 0 16px; + text-decoration: none; + transition: all 250ms ease-in-out; + vertical-align: middle; + white-space: nowrap; +} + +.btn-teamsnap:hover, +.btn-teamsnap:active, +.btn-teamsnap:focus { + background-color: #e68100; + border-color: #b86700; + color: #ffffff; +} + +.btn-gamechanger { + color: #fff; + border-color: #1b73bc; + background-color: #1b73bc; +} diff --git a/public/fonts/futura-now/stylesheet.css b/public/fonts/futura-now/stylesheet.css new file mode 100644 index 0000000..4fdee7c --- /dev/null +++ b/public/fonts/futura-now/stylesheet.css @@ -0,0 +1,6 @@ +@font-face { + font-family: "Futura Now"; + src: url('futura-now.ttf') format('truetype'); + font-style: normal; + font-weight: 100 900; +} diff --git a/public/fonts/helvetica-now/stylesheet.css b/public/fonts/helvetica-now/stylesheet.css new file mode 100644 index 0000000..c512683 --- /dev/null +++ b/public/fonts/helvetica-now/stylesheet.css @@ -0,0 +1,7 @@ +@font-face { + font-family: "Helvetica Now"; + src: url('helvetica-now.ttf') format('truetype'); + font-weight: 125 900; + font-stretch: 50% 150%; + font-style: normal; +} \ No newline at end of file diff --git a/public/fonts/inconsolata/stylesheet.css b/public/fonts/inconsolata/stylesheet.css new file mode 100644 index 0000000..76a3a5f --- /dev/null +++ b/public/fonts/inconsolata/stylesheet.css @@ -0,0 +1,4 @@ +@font-face { + font-family: "Inconsolata"; + src: url("inconsolata-vf.ttf") format("truetype"); +} diff --git a/public/fonts/m+1m/m+1m.css b/public/fonts/m+1m/m+1m.css new file mode 100644 index 0000000..c8f1fb9 --- /dev/null +++ b/public/fonts/m+1m/m+1m.css @@ -0,0 +1,38 @@ +@font-face { + font-family: 'm+1m'; + src: url('mplus-1m-bold-webfont.woff') format('woff'); + font-weight: bold; + font-style: normal; + +} + +@font-face { + font-family: 'm+1m'; + src: url('mplus-1m-light-webfont.woff') format('woff'); + font-weight: 300; + font-style: normal; + +} + +@font-face { + font-family: 'm+1m'; + src: url('mplus-1m-medium-webfont.woff') format('woff'); + font-weight: 500; + font-style: normal; + +} + +@font-face { + font-family: 'm+1m'; + src: url('mplus-1m-regular-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} + +@font-face { + font-family: 'm+1m'; + src: url('mplus-1m-thin-webfont.woff') format('woff'); + font-weight: 100; + font-style: normal; +} diff --git a/public/fonts/vera/bitstreamvera.css b/public/fonts/vera/bitstreamvera.css new file mode 100644 index 0000000..3672c63 --- /dev/null +++ b/public/fonts/vera/bitstreamvera.css @@ -0,0 +1,68 @@ +@font-face { + font-family: 'Bitstream Vera Sans'; + src: url('Vera-Bold-webfont.woff') format('woff'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Bitstream Vera Sans'; + src: url('Vera-Bold-Italic-webfont.woff') format('woff'); + font-weight: bold; + font-style: oblique; + +} + +@font-face { + font-family: 'Bitstream Vera Sans'; + src: url('Vera-Italic-webfont.woff') format('woff'); + font-weight: normal; + font-style: oblique; + +} + +@font-face { + font-family: 'Bitstream Vera Sans'; + src: url('Vera-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; + +} + +@font-face { + font-family: 'Bitstream Vera Sans Mono'; + src: url('VeraMono-Bold-webfont.woff') format('woff'); + font-weight: bold; + font-style: normal; + +} + +@font-face { + font-family: 'Bitstream Vera Sans Mono'; + src: url('VeraMono-Bold-Italic-webfont.woff') format('woff'); + font-weight: bold; + font-style: italic; + +} + +@font-face { + font-family: 'Bitstream Vera Sans Mono'; + src: url('VeraMono-Italic-webfont.woff') format('woff'); + font-weight: normal; + font-style: italic; + +} + +@font-face { + font-family: 'Bitstream Vera Sans Mono'; + src: url('VeraMono-webfont.woff') format('woff'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Bitstream Vera Sans Mono'; + src: url('VeraMono-webfont.woff') format('woff'); + font-weight: 800; + font-style: normal; +} diff --git a/public/fonts/verdana/verdanapro.css b/public/fonts/verdana/verdanapro.css new file mode 100644 index 0000000..2dccbc7 --- /dev/null +++ b/public/fonts/verdana/verdanapro.css @@ -0,0 +1,123 @@ +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-Black.ttf') format('truetype'); + font-weight: 800; + font-style: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-BlackItalic.ttf') format('truetype'); + font-weight: 800; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-Bold.ttf') format('truetype'); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-BoldItalic.ttf') format('truetype'); + font-weight: bold; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondBlack.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 800; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondBlackItalic.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 800; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondBold.ttf') format('truetype'); + font-stretch: condensed; + font-weight: bold; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondBoldItalic.ttf') format('truetype'); + font-stretch: condensed; + font-weight: bold; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondItalic.ttf') format('truetype'); + font-stretch: condensed; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondLight.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 300; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondLightItalic.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 300; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondRegular.ttf') format('truetype'); + font-stretch: condensed; + font-style: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondSemiBold.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 600; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-CondSemiBoldItalic.ttf') format('truetype'); + font-stretch: condensed; + font-weight: 600; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-Italic.ttf') format('truetype'); + font-style: italic; + font-weight: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-Light.ttf') format('truetype'); + font-weight: 300; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-LightItalic.ttf') format('truetype'); + font-weight: 300; + font-style: italic; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-Regular.ttf') format('truetype'); + font-style: normal; + font-weight: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-SemiBold.ttf') format('truetype'); + font-weight: 600; + font-style: normal; +} +@font-face { + font-family: 'VerdanaPro'; + src: url('VerdanaPro-SemiBoldItalic.ttf') format('truetype'); + font-weight: 600; + font-style: italic; +} diff --git a/public/js/load_from_teamsnap.js b/public/js/load_from_teamsnap.js new file mode 100644 index 0000000..1b26347 --- /dev/null +++ b/public/js/load_from_teamsnap.js @@ -0,0 +1,115 @@ +event_id = "292333461"; +event_id_2 = "292333462"; +team_id = "6882652"; + +function format_stat(number) { + const zeroPad = (num, places) => String(num).padStart(3, "0"); + return zeroPad(Math.round(number * 1000), 3); +} + +async function load_data_xxx() { + const event_id = document.querySelector('input[name="event_id"]').value; + const team_id = document.querySelector('input[name="team_id"]').value; + update_card(team_id, event_id); +} + +async function update_card(team_id, event_id) { + fetch(`/${team_id}/event/${event_id}/gamecard/data`, { + method: "GET", + headers: { + Accept: "application/json", + }, + }) + .then((response) => response.json()) + .then(function (items) { + console.log(items); + events = items.filter(function (item) { + return item.type == "event"; + }); + event_index = events.findIndex(function (e) { + return e.id == event_id; + }); + event = events[event_index]; + document.title = event.formattedTitle; + + document.querySelectorAll(".event-title").forEach(function (element) { + element.innerText = event.formattedTitle; + }); + + document.querySelectorAll(".event-label").forEach(function (element) { + element.innerText = event.label; + }); + + document + .querySelectorAll(".event-location-name") + .forEach(function (element) { + element.innerText = event.locationName; + }); + + document.querySelectorAll(".opponent").forEach(function (element) { + element.innerText = event.opponentName; + }); + + document.querySelectorAll(".homeaway").forEach(function (element) { + element.innerText = event.gameType; + }); + + document.querySelectorAll(".event-date").forEach(function (element) { + element.innerText = new Date(event.startDate).toLocaleDateString( + "en-us", + { + weekday: "short", + day: "numeric", + // year: "numeric", + month: "short", + } + ); + }); + + document.querySelectorAll(".event-time").forEach(function (element) { + element.innerText = new Date(event.startDate).toLocaleTimeString( + "en-us", + { + hour: "numeric", + minute: "2-digit", + } + ); + }); + + document.getElementById("todays-game-header").innerText = + event.formattedTitle + + " - " + + new Date(event.startDate).toLocaleDateString("en-us", { + weekday: "short", + day: "numeric", + // year: "numeric", + month: "short", + }) + + " " + + new Date(event.startDate).toLocaleTimeString("en-us", { + hour: "numeric", + minute: "2-digit", + }); + + for (let j = -4; j < 5; j++) { + if (j < 0) { + plus_minus = "minus"; + } else if (j > 0) { + plus_minus = "plus"; + } else { + continue; + } + document.querySelector( + `th.today-${plus_minus}-${Math.abs(j)} div` + ).textContent = new Date( + events[event_index + j].startDate + ).toLocaleDateString("en-us", { + weekday: "short", + }); + } + console.log({ + 0: events[event_index], + 1: events[event_index + 1], + }); + }); +} diff --git a/public/js/teamsnap.js b/public/js/teamsnap.js new file mode 100644 index 0000000..a483c72 --- /dev/null +++ b/public/js/teamsnap.js @@ -0,0 +1,6810 @@ +(function() { +var window, global = {}; +(function() { + 'use strict'; + + var globals = typeof window === 'undefined' ? global : window; + if (typeof globals.require === 'function') return; + + var modules = {}; + var cache = {}; + var aliases = {}; + var has = ({}).hasOwnProperty; + + var expRe = /^\.\.?(\/|$)/; + var expand = function(root, name) { + var results = [], part; + var parts = (expRe.test(name) ? root + '/' + name : name).split('/'); + for (var i = 0, length = parts.length; i < length; i++) { + part = parts[i]; + if (part === '..') { + results.pop(); + } else if (part !== '.' && part !== '') { + results.push(part); + } + } + return results.join('/'); + }; + + var dirname = function(path) { + return path.split('/').slice(0, -1).join('/'); + }; + + var localRequire = function(path) { + return function expanded(name) { + var absolute = expand(dirname(path), name); + return globals.require(absolute, path); + }; + }; + + var initModule = function(name, definition) { + var hot = null; + hot = hmr && hmr.createHot(name); + var module = {id: name, exports: {}, hot: hot}; + cache[name] = module; + definition(module.exports, localRequire(name), module); + return module.exports; + }; + + var expandAlias = function(name) { + return aliases[name] ? expandAlias(aliases[name]) : name; + }; + + var _resolve = function(name, dep) { + return expandAlias(expand(dirname(name), dep)); + }; + + var require = function(name, loaderPath) { + if (loaderPath == null) loaderPath = '/'; + var path = expandAlias(name); + + if (has.call(cache, path)) return cache[path].exports; + if (has.call(modules, path)) return initModule(path, modules[path]); + + throw new Error("Cannot find module '" + name + "' from '" + loaderPath + "'"); + }; + + require.alias = function(from, to) { + aliases[to] = from; + }; + + var extRe = /\.[^.\/]+$/; + var indexRe = /\/index(\.[^\/]+)?$/; + var addExtensions = function(bundle) { + if (extRe.test(bundle)) { + var alias = bundle.replace(extRe, ''); + if (!has.call(aliases, alias) || aliases[alias].replace(extRe, '') === alias + '/index') { + aliases[alias] = bundle; + } + } + + if (indexRe.test(bundle)) { + var iAlias = bundle.replace(indexRe, ''); + if (!has.call(aliases, iAlias)) { + aliases[iAlias] = bundle; + } + } + }; + + require.register = require.define = function(bundle, fn) { + if (typeof bundle === 'object') { + for (var key in bundle) { + if (has.call(bundle, key)) { + require.register(key, bundle[key]); + } + } + } else { + modules[bundle] = fn; + delete cache[bundle]; + addExtensions(bundle); + } + }; + + require.list = function() { + var list = []; + for (var item in modules) { + if (has.call(modules, item)) { + list.push(item); + } + } + return list; + }; + + var hmr = globals._hmr && new globals._hmr(_resolve, require, modules, cache); + require._cache = cache; + require.hmr = hmr && hmr.wrap; + require.brunch = true; + globals.require = require; +})(); +var require = global.require; +global = this; +if (global.window) window = this; +require.register("auth.coffee", function(exports, require, module) { +var TeamSnap, authRequest, browserStorageName, browserStore, collectionJSONMime, createAuthDialog, generateUrl, jsonMime, multipartMime, promises, request, sdkRequest; + +TeamSnap = require('./teamsnap').TeamSnap; + +promises = require('./promises'); + +request = require('./request'); + +jsonMime = 'application/json'; + +collectionJSONMime = 'application/vnd.collection+json'; + +multipartMime = 'multipart/form-data'; + +browserStorageName = 'teamsnap.authToken'; + +authRequest = request.create().hook(function(xhr, data) { + xhr.setRequestHeader('Accept', jsonMime); + if (data) { + xhr.setRequestHeader('Content-Type', jsonMime); + } + return xhr.withCredentials = true; +}); + +sdkRequest = request.create().hook(function(xhr, data) { + xhr.setRequestHeader('Accept', collectionJSONMime); + if (data && !(data instanceof FormData)) { + xhr.setRequestHeader('Content-Type', collectionJSONMime); + } + return xhr.withCredentials = true; +}); + +generateUrl = function(endpoint, params) { + var key, queries, url, value; + queries = []; + for (key in params) { + value = params[key]; + if (value) { + queries.push(key + '=' + encodeURIComponent(value)); + } + } + url = teamsnap.authUrl + '/oauth/' + endpoint; + if (queries.length) { + url = url + '?' + queries.join('&'); + } + return url.replace(/%20/g, '+'); +}; + +TeamSnap.prototype.auth = function(token) { + var cachedCollections, callback; + if (typeof token === 'function') { + callback = token; + token = null; + } else if (typeof token === 'object') { + callback = cachedCollections; + cachedCollections = token; + token = null; + } + if (typeof cachedCollections === 'function') { + callback = cachedCollections; + cachedCollections = null; + } + this.request = sdkRequest.clone(); + if (typeof token === 'number' && teamsnap.apiUrl.indexOf(':3000') !== -1) { + this.request.hook(function(xhr) { + return xhr.setRequestHeader('X-Teamsnap-User-ID', token); + }); + return this; + } + if (!token) { + token = browserStore(); + } + if (!token) { + throw new TSArgsError('teamsnap.auth', 'A token is required to auth unless in the browser it has been cached'); + } + this.request.hook(function(xhr) { + return xhr.setRequestHeader('Authorization', 'Bearer ' + token); + }); + return this; +}; + +TeamSnap.prototype.deleteAuth = function() { + return this.request = null; +}; + +TeamSnap.prototype.isAuthed = function() { + return !!this.request; +}; + +TeamSnap.prototype.hasSession = function() { + return !!browserStore(); +}; + +TeamSnap.prototype.browserLogout = function() { + createAuthDialog(teamsnap.authUrl + '/logout'); + if (this.isAuthed) { + return this.deleteAuth(); + } +}; + +TeamSnap.prototype.init = function(clientId, secret) { + var generateAuthUrl, generatePasswordUrl, generateTokenUrl; + generateAuthUrl = function(type, redirect, scopes) { + scopes = Array.isArray(scopes) ? scopes.join(' ') : scopes; + return generateUrl('authorize', { + response_type: type, + client_id: clientId, + redirect_uri: redirect, + scope: scopes + }); + }; + generateTokenUrl = function(code) { + return generateUrl('token', { + grant_type: 'authorization_code', + code: code, + client_id: clientId, + client_secret: secret + }); + }; + generatePasswordUrl = function(username, password) { + return generateUrl('token', { + grant_type: 'password', + username: username, + password: password, + client_id: clientId, + client_secret: secret + }); + }; + this.getServerAuthUrl = function(redirect, scopes) { + return generateAuthUrl('code', redirect, scopes); + }; + this.getServerTokenUrl = function(code) { + return generateTokenUrl(code); + }; + this.getBrowserAuthUrl = function(redirect, scopes) { + return generateAuthUrl('token', redirect, scopes); + }; + this.getPasswordAuthUrl = function(username, password) { + return generatePasswordUrl(username, password); + }; + this.createDialog = function(url, callback) { + return createAuthDialog(url, callback); + }; + this.finishServerAuth = function(code, callback) { + return authRequest.post(this.getServerTokenUrl(code), callback); + }; + this.startBrowserAuth = function(redirect, scopes, callback) { + if (location.protocol === 'file:') { + throw new TSError('TeamSnap.js cannot auth from the file system'); + } + return this.createDialog(this.getBrowserAuthUrl(redirect, scopes)).then((function(_this) { + return function(response) { + var token; + token = response.access_token; + browserStore(token); + return _this.auth(token); + }; + })(this)).callback(callback); + }; + return this.startPasswordAuth = function(username, password, callback) { + return authRequest.post(this.getPasswordAuthUrl(username, password), callback); + }; +}; + +browserStore = function(token) { + if (!global.sessionStorage) { + return; + } + if (arguments.length === 0) { + return sessionStorage.getItem(browserStorageName); + } else { + sessionStorage.setItem(browserStorageName, token); + } +}; + +createAuthDialog = function(url, callback) { + var deferred, dialog, height, interval, left, top, width, windowHeight, windowWidth, x, y; + width = 860; + height = 720; + deferred = promises.defer(); + x = window.screenLeft || window.screenX; + y = window.screenTop || window.screenY; + windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + left = x + (windowWidth - width) / 2; + top = y + (windowHeight - height) / 2; + dialog = window.open(url, 'oauth', 'menubar=no,scrollbars=no,status=no,toolbar=no,' + 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top); + interval = setInterval(function() { + var e, params, response; + try { + if (dialog.closed) { + clearInterval(interval); + deferred.reject({ + error: 'access_denied', + error_description: 'The resource owner denied the request.' + }); + } + if (dialog.location.host !== location.host) { + return; + } + params = dialog.location.hash.replace(/^#/, '') || dialog.location.search.replace(/^\?/, ''); + } catch (error) { + e = error; + return; + } + clearInterval(interval); + dialog.close(); + response = {}; + params.split('&').forEach(function(param) { + var key, ref, value; + ref = param.split('='), key = ref[0], value = ref[1]; + return response[decodeURIComponent(key)] = decodeURIComponent(value.replace(/\+/g, ' ')); + }); + if (response.error) { + return deferred.reject(response); + } else { + return deferred.resolve(response); + } + }, 50); + return deferred.promise.callback(callback); +}; + +}); + +require.register("collections/assignments.coffee", function(exports, require, module) { +exports.EVENT_SETS = ['future_games_and_events', 'future_games', 'future_events']; + +exports.loadAssignments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadAssignments', 'must provide a teamId or query parameters'); + } + return this.loadItems('assignment', params, callback); +}; + +exports.createAssignment = function(data) { + return this.createItem(data, { + type: 'assignment', + description: '' + }); +}; + +exports.saveAssignment = function(assignment, callback) { + var ref; + if (!assignment) { + throw new TSArgsError('teamsnap.saveAssignment', "`assignment` must be provided"); + } + if (!this.isItem(assignment, 'assignment')) { + throw new TSArgsError('teamsnap.saveAssignment', "`assignment.type` must be 'assignment'"); + } + if (!assignment.eventId) { + return this.reject('You must choose an event.', 'eventId', callback); + } + if (!((ref = assignment.description) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a description for the assignment.', 'name', callback); + } + return this.saveItem(assignment, callback); +}; + +exports.deleteAssignment = function(assignment, callback) { + if (!assignment) { + throw new TSArgsError('teamsnap.deleteAssignment', '`assignment` must be provided'); + } + return this.deleteItem(assignment, callback); +}; + +exports.getAssignmentSort = function(reverse) { + return (function(_this) { + return function(itemA, itemB) { + var valueA, valueB; + if (!_this.isItem(itemA, 'assignment') || !_this.isItem(itemB, 'assignment')) { + valueA = itemA.type; + valueB = itemB.type; + } else { + valueA = _this.memberName(itemA.member, reverse).toLowerCase(); + valueB = _this.memberName(itemB.member, reverse).toLowerCase(); + } + if (typeof (valueA != null ? valueA.localeCompare : void 0) === 'function') { + return valueA.localeCompare(valueB); + } else { + if (valueA === valueB) { + return 0; + } else if (!valueA && valueB) { + return 1; + } else if (valueA && !valueB) { + return -1; + } else if (valueA > valueB) { + return 1; + } else if (valueA < valueB) { + return -1; + } else { + return 0; + } + } + }; + })(this); +}; + +exports.sendAssignmentEmails = function(teamId, eventIds, message, sendingMemberId, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.sendAssignmentEmails', "must provide a `teamId`"); + } + if (!eventIds) { + throw new TSArgsError('teamsnap.sendAssignmentEmails', "must provide `eventIds`"); + } + if (this.isItem(eventIds)) { + eventIds = eventIds.id; + } + if (!this.isId(sendingMemberId)) { + throw new TSArgsError('teamsnap.sendAssignmentEmails', "must provide a `sendingMemberId`"); + } + params = { + teamId: teamId, + eventIds: eventIds, + message: message, + sendingMemberId: sendingMemberId + }; + return this.collections.assignments.exec('sendAssignmentEmails', params, callback); +}; + +exports.reorderAssignments = function(eventId, assignmentIds, callback) { + var params; + if (!this.isId(eventId)) { + throw new TSArgsError('teamsnap.reorderAssignments', '`eventId` must be provided'); + } + if (!(assignmentIds && Array.isArray(assignmentIds))) { + throw new TSArgsError('teamsnap.reorderAssignments', 'You must provide an array of ordered Assignments IDs'); + } + params = { + eventId: eventId, + sortedIds: assignmentIds + }; + return this.collections.assignments.exec('reorderAssignments', params).callback(callback); +}; + +exports.createBulkAssignments = function(eventSet, description, teamId, createAsMemberId, callback) { + var params; + if (!(this.EVENT_SETS.indexOf(eventSet) > -1)) { + throw new TSArgsError('teamsnap.createBulkAssignments', " `eventSet` must be one of the following: " + this.EVENT_SETS.toString() + "."); + } + if (!description.trim()) { + return this.reject('You must provide a description for the assignments.', 'description', callback); + } + if (!teamId) { + throw new TSArgsError('teamsnap.createBulkAssignments', '`teamId` must be provided.'); + } + if (this.isItem(teamId, 'team')) { + ({ + teamId: teamId.id + }); + } + if (!createAsMemberId) { + throw new TSArgsError('teamsnap.createBulkAssignments', '`createAsMemberId` must be provided.'); + } + if (this.isItem(createAsMemberId, 'member')) { + ({ + createAsMemberId: createAsMemberId.id + }); + } + params = { + eventSet: eventSet, + description: description, + teamId: teamId, + createAsMemberId: createAsMemberId + }; + return this.collections.assignments.exec('createBulkAssignments', params, callback); +}; + +}); + +require.register("collections/availabilities.coffee", function(exports, require, module) { +var key, ref, statuses, value; + +exports.AVAILABILITIES = { + NONE: null, + NO: 0, + YES: 1, + MAYBE: 2 +}; + +statuses = {}; + +ref = exports.AVAILABILITIES; +for (key in ref) { + value = ref[key]; + statuses[value] = true; +} + +exports.loadAvailabilities = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadAvailabilities', 'must provide a teamId or query parameters'); + } + return this.loadItems('availability', params, callback); +}; + +exports.saveAvailability = function(availability, callback) { + if (!availability) { + throw new TSArgsError('teamsnap.saveAvailability', "`availability` must be provided"); + } + if (!this.isItem(availability, 'availability')) { + throw new TSArgsError('teamsnap.saveAvailability', "`type` must be 'availability'"); + } + if (availability.statusCode !== null && !statuses[availability.statusCode]) { + return this.reject('You must select a valid status or null', 'statusCode', callback); + } + return this.saveItem(availability, callback); +}; + +exports.bulkMarkUnsetAvailabilities = function(memberId, statusCode, callback) { + var params; + if (!this.isId(memberId)) { + throw new TSArgsError('teamsnap.bulkMarkUnsetAvailabilities', "must provide a `memberId`"); + } + if (!((statusCode != null) && statuses[statusCode])) { + return this.reject('You must select a valid status', 'statusCode', callback); + } + params = { + memberId: memberId, + statusCode: statusCode + }; + return this.collections.availabilities.exec('bulkMarkUnsetAvailabilities', params).pop().callback(callback); +}; + +}); + +require.register("collections/broadcastAlerts.coffee", function(exports, require, module) { +exports.loadBroadcastAlerts = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadBroadcastAlerts', 'must provide a teamId or query parameters'); + } + return this.loadItems('broadcastAlert', params, callback); +}; + +exports.createBroadcastAlert = function(data) { + return this.createItem(data, { + type: 'broadcastAlert' + }); +}; + +exports.saveBroadcastAlert = function(broadcastAlert, callback) { + var ref; + if (!broadcastAlert) { + throw new TSArgsError('teamsnap.saveBroadcastAlert', "`broadcastAlert` must be provided"); + } + if (!this.isItem(broadcastAlert, 'broadcastAlert')) { + throw new TSArgsError('teamsnap.saveBroadcastAlert', "`type` must be 'broadcastAlert'"); + } + if (!broadcastAlert.teamId) { + return this.reject('You must provide a team id.', 'teamId', callback); + } + if (!broadcastAlert.memberId) { + return this.reject('You must provide a member id.', 'memberId', callback); + } + if (!((ref = broadcastAlert.body) != null ? ref.trim() : void 0)) { + return this.reject('You must provide the text alert body.', 'body', callback); + } + return this.saveItem(broadcastAlert, callback); +}; + +exports.deleteBroadcastAlert = function(broadcastAlert, callback) { + if (!broadcastAlert) { + throw new TSArgsError('teamsnap.deleteBroadcastAlert', '`broadcastAlert` must be provided'); + } + return this.deleteItem(broadcastAlert, callback); +}; + +}); + +require.register("collections/broadcastEmailAttachments.coffee", function(exports, require, module) { +exports.loadBroadcastEmailAttachments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadBroadcastEmailAttachments', 'must provide a teamId or query parameters'); + } + return this.loadItems('broadcastEmailAttachment', params, callback); +}; + +exports.deleteBroadcastEmailAttachment = function(broadcastEmailAttachment, callback) { + if (!broadcastEmailAttachment) { + throw new TSArgsError('teamsnap.deleteBroadcastEmailAttachment', '`broadcastEmailAttachment` must be provided'); + } + return this.deleteItem(broadcastEmailAttachment, callback); +}; + +exports.uploadBroadcastEmailAttachment = function(broadcastEmailId, memberId, file, progressCallback, callback) { + var params; + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!broadcastEmailId) { + throw new TSArgsError('teamsnap.uploadBroadcastEmailAttachment', 'broadcastEmailId is required'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadBroadcastEmailAttachment', 'must include `file` as type File', 'file is required'); + } + if (!memberId) { + throw new TSArgsError('teamsnap.uploadBroadcastEmailAttachment', 'memberId is required'); + } + params = { + broadcastEmailId: broadcastEmailId, + file: file, + memberId: memberId + }; + return this.collections.broadcastEmailAttachments.file('uploadBroadcastEmailAttachment', params, progressCallback, callback); +}; + +}); + +require.register("collections/broadcastEmails.coffee", function(exports, require, module) { +exports.loadBroadcastEmails = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadBroadcastEmails', 'must provide a teamId or query parameters'); + } + return this.loadItems('broadcastEmail', params, callback); +}; + +exports.createBroadcastEmail = function(data) { + return this.createItem(data, { + type: 'broadcastEmail' + }); +}; + +exports.saveBroadcastEmail = function(broadcastEmail, callback) { + var ref; + if (!broadcastEmail) { + throw new TSArgsError('teamsnap.saveBroadcastEmail', "`broadcastEmail` must be provided"); + } + if (!this.isItem(broadcastEmail, 'broadcastEmail')) { + throw new TSArgsError('teamsnap.saveBroadcastEmail', "`type` must be 'broadcastEmail'"); + } + if (broadcastEmail.isLeague) { + if (!broadcastEmail.divisionId) { + return reject('You must provide a division id.', 'divisionId', callback); + } + } else { + if (!broadcastEmail.teamId) { + return this.reject('You must provide a team id.', 'teamId', callback); + } + } + if (!broadcastEmail.memberId) { + return this.reject('You must provide a member id.', 'memberId', callback); + } + if (!((ref = broadcastEmail.body) != null ? ref.trim() : void 0)) { + return this.reject('You must provide the text alert body.', 'body', callback); + } + if (!broadcastEmail.isDraft) { + if (!broadcastEmail.isLeague) { + if (!(Array.isArray(broadcastEmail.recipientIds) && broadcastEmail.recipientIds.length > 0)) { + return this.reject('You must provide at least one recipient.', 'recipientIds'); + } + } + } + return this.saveItem(broadcastEmail, callback); +}; + +exports.deleteBroadcastEmail = function(broadcastEmail, callback) { + if (!broadcastEmail) { + throw new TSArgsError('teamsnap.deleteBroadcastEmail', '`broadcastEmail` must be provided'); + } + return this.deleteItem(broadcastEmail, callback); +}; + +exports.bulkDeleteBroadcastEmails = function(broadcastEmailIds, callback) { + if (!(Array.isArray(broadcastEmailIds))) { + throw new TSArgsError('teamsnap.broadcastEmailIds', 'You must provide an array of broadcastEmail IDs'); + } + return this.collections.broadcastEmails.exec('bulkDelete', { + id: broadcastEmailIds + }, callback); +}; + +}); + +require.register("collections/contactEmailAddresses.coffee", function(exports, require, module) { +exports.loadContactEmailAddresses = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadContactEmailAddresses', 'must provide a teamId or query parameters'); + } + return this.loadItems('contactEmailAddress', params, callback); +}; + +exports.createContactEmailAddress = function(data) { + return this.createItem(data, { + type: 'contactEmailAddress', + receivesTeamEmails: true + }); +}; + +exports.saveContactEmailAddress = function(contactEmailAddress, callback) { + if (!contactEmailAddress) { + throw new TSArgsError('teamsnap.saveContactEmailAddress', '`contactEmailAddress` must be provided'); + } + if (!this.isItem(contactEmailAddress, 'contactEmailAddress')) { + throw new TSArgsError('teamsnap.saveContactEmailAddress', "`contactEmailAddress.type` must be 'contactEmailAddress'"); + } + if (!contactEmailAddress.contactId) { + return this.reject('You must choose a contact.', 'contactId', callback); + } + return this.saveItem(contactEmailAddress, callback); +}; + +exports.deleteContactEmailAddress = function(contactEmailAddress, callback) { + if (!contactEmailAddress) { + throw new TSArgsError('teamsnap.deleteContactEmailAddress', '`contactEmailAddress` must be provided'); + } + return this.deleteItem(contactEmailAddress, callback); +}; + +}); + +require.register("collections/contactPhoneNumbers.coffee", function(exports, require, module) { +exports.loadContactPhoneNumbers = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadContactPhoneNumbers', 'must provide a teamId or query parameters'); + } + return this.loadItems('contactPhoneNumber', params, callback); +}; + +exports.createContactPhoneNumber = function(data) { + return this.createItem(data, { + type: 'contactPhoneNumber' + }); +}; + +exports.saveContactPhoneNumber = function(contactPhoneNumber, callback) { + if (!contactPhoneNumber) { + throw new TSArgsError('teamsnap.saveContactPhoneNumber', '`contactPhoneNumber` must be provided'); + } + if (!this.isItem(contactPhoneNumber, 'contactPhoneNumber')) { + throw new TSArgsError('teamsnap.saveContactPhoneNumber', "`contactPhoneNumber.type` must be 'contactPhoneNumber'"); + } + if (!contactPhoneNumber.contactId) { + return this.reject('You must choose a contact.', 'contactId', callback); + } + return this.saveItem(contactPhoneNumber, callback); +}; + +exports.deleteContactPhoneNumber = function(contactPhoneNumber, callback) { + if (!contactPhoneNumber) { + throw new TSArgsError('teamsnap.deleteContactPhoneNumber', '`contactPhoneNumber` must be provided'); + } + return this.deleteItem(contactPhoneNumber, callback); +}; + +}); + +require.register("collections/contacts.coffee", function(exports, require, module) { +exports.loadContacts = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadContacts', 'must provide a teamId or query parameters'); + } + return this.loadItems('contact', params, callback); +}; + +exports.createContact = function(data) { + return this.createItem(data, { + type: 'contact' + }); +}; + +exports.saveContact = function(contact, callback) { + var ref; + if (!contact) { + throw new TSArgsError('teamsnap.saveContact', "`contact` must be provided"); + } + if (!this.isItem(contact, 'contact')) { + throw new TSArgsError('teamsnap.saveContact', "`contact.type` must be 'contact'"); + } + if (!contact.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + if (!((ref = contact.firstName) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a firstName for the contact.', 'name', callback); + } + return this.saveItem(contact, callback); +}; + +exports.deleteContact = function(contact, callback) { + if (!contact) { + throw new TSArgsError('teamsnap.deleteContact', '`contact` must be provided'); + } + return this.deleteItem(contact, callback); +}; + +}); + +require.register("collections/customData.coffee", function(exports, require, module) { +exports.loadCustomData = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadCustomData', 'must provide a teamId or query parameters'); + } + return this.loadItems('customDatum', params, callback); +}; + +exports.createCustomDatum = function(data, field) { + return this.createItem(data, { + type: 'customDatum', + customFieldId: field.id, + kind: field.kind, + name: field.name, + isPrivate: false, + value: null + }); +}; + +exports.saveCustomDatum = function(customDatum, callback) { + if (!customDatum) { + throw new TSArgsError('teamsnap.saveCustomField', '`customDatum` must be provided'); + } + if (!this.isItem(customDatum, 'customDatum')) { + throw new TSArgsError('teamsnap.saveCustomField', "`customDatum.type` must be 'customDatum'"); + } + return this.saveItem(customDatum, callback); +}; + +}); + +require.register("collections/customFields.coffee", function(exports, require, module) { +exports.loadCustomFields = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadCustomFields', 'must provide a teamId or query parameters'); + } + return this.loadItems('customField', params, callback); +}; + +exports.createCustomField = function(data) { + return this.createItem(data, { + type: 'customField' + }); +}; + +exports.saveCustomField = function(customField, callback) { + if (!customField) { + throw new TSArgsError('teamsnap.saveCustomField', '`customField` must be provided'); + } + if (!this.isItem(customField, 'customField')) { + throw new TSArgsError('teamsnap.saveCustomField', "`customField.type` must be 'customField'"); + } + if (!customField.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!customField.name) { + return this.reject('You must enter a name.', 'name', callback); + } + if (!customField.kind) { + return this.reject('You must choose a type.', 'kind', callback); + } + return this.saveItem(customField, callback); +}; + +exports.deleteCustomField = function(customField, callback) { + if (!customField) { + throw new TSArgsError('teamsnap.deleteCustomField', '`customField` must be provided'); + } + return this.deleteItem(customField, callback); +}; + +}); + +require.register("collections/divisionEvents.coffee", function(exports, require, module) { +exports.loadDivisionEvents = function(params, callback) { + if (this.isId(params)) { + params = { + divisionId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionEvents', 'must provide a divisionId or query parameters'); + } + return this.loadItems('divisionEvent', params, callback); +}; + +}); + +require.register("collections/divisionLocations.coffee", function(exports, require, module) { +exports.loadDivisionLocations = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionLocations', 'must provide a teamId or query parameters'); + } + return this.loadItems('divisionLocation', params, callback); +}; + +}); + +require.register("collections/divisionMembers.coffee", function(exports, require, module) { +exports.loadDivisionMembers = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionMembers', 'must provide a teamId or query parameters'); + } + return this.loadItems('divisionMember', params, callback); +}; + +}); + +require.register("collections/divisionMembersPreferences.coffee", function(exports, require, module) { +exports.PREFS = { + SCHEDULE_SHOW: { + ALL: 1, + GAMES: 2, + EVENTS: 3 + } +}; + +exports.loadDivisionMembersPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionMembersPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItems('divisionMemberPreferences', params, callback); +}; + +exports.loadDivisionMemberPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionMemberPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItem('divisionMemberPreferences', params, callback); +}; + +exports.saveDivisionMemberPreferences = function(divisionMemberPreferences, callback) { + if (!divisionMemberPreferences) { + throw new TSArgsError('teamsnap.saveDivisionMemberPreferences', "`divisionMemberPreferences` must be provided"); + } + if (!this.isItem(divisionMemberPreferences, 'divisionMemberPreferences')) { + throw new TSArgsError('teamsnap.saveDivisionMemberPreferences', "`divisionMemberPreferences.type` must be 'divisionMemberPreferences'"); + } + return this.saveItem(divisionMemberPreferences, callback); +}; + +}); + +require.register("collections/divisionTeamStandings.coffee", function(exports, require, module) { +exports.loadDivisionTeamStandings = function(teamId, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.loadDivisionTeamStandings', 'must provide a teamId'); + } + params = { + teamId: teamId + }; + return this.loadItems('divisionTeamStanding', params, callback); +}; + +}); + +require.register("collections/divisions.coffee", function(exports, require, module) { +exports.loadDivisions = function(params, callback) { + if (params == null) { + params = {}; + } + if (typeof params === 'function') { + callback = params; + params = {}; + } + if (Object.keys(params).length) { + return this.loadItems('division', params, callback); + } else { + return this.loadMe().then((function(_this) { + return function(me) { + params.userId = me.id; + return _this.loadItems('division', params, callback); + }; + })(this)); + } +}; + +exports.loadDivision = function(divisionId, callback) { + if (!this.isId(divisionId)) { + throw new TSArgsError('teamsnap.loadDivision', 'divisionId must be provided'); + } + return this.loadItem('division', { + id: divisionId + }, callback); +}; + +exports.createDivision = function(data) { + return this.createItem(data, { + type: 'division', + name: '' + }); +}; + +exports.saveDivision = function(division, callback) { + var ref; + if (!division) { + throw new TSArgsError('teamsnap.saveDivision', "`division` must be provided"); + } + if (!this.isItem(division, 'division')) { + throw new TSArgsError('teamsnap.saveDivision', "`type` must be 'division'"); + } + if (!((ref = division.name) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a name for the division.', 'name', callback); + } + return this.saveItem(division, callback); +}; + +exports.deleteDivision = function(division, callback) { + if (!division) { + throw new TSArgsError('teamsnap.deleteDivision', '`division` must be provided'); + } + return this.deleteItem(division, callback); +}; + +exports.loadAncestorDivisions = function(divisionId, callback) { + if (!this.isId(divisionId)) { + throw new TSArgsError('teamsnap.loadAncestorDivisions', 'divisionId must be provided'); + } + return this.collections.divisions.queryItems('ancestors', { + id: divisionId + }, callback); +}; + +exports.loadDescendantDivisions = function(divisionId, callback) { + if (!this.isId(divisionId)) { + throw new TSArgsError('teamsnap.loadDescendantDivisions', 'divisionId must be provided'); + } + return this.collections.divisions.queryItems('descendants', { + id: divisionId + }, callback); +}; + +exports.loadChildDivisions = function(divisionId, callback) { + if (!this.isId(divisionId)) { + throw new TSArgsError('teamsnap.loadChildDivisions', 'divisionId must be provided'); + } + return this.collections.divisions.queryItems('children', { + id: divisionId + }, callback); +}; + +exports.loadActiveTrialDivisions = function(userId, callback) { + if (!this.isId(userId)) { + throw new TSArgsError('teamsnap.loadActiveTrialsDivisions', 'userId must be provided'); + } + return this.collections.divisions.queryItems('activeTrials', { + userId: userId + }, callback); +}; + +}); + +require.register("collections/divisionsPreferences.coffee", function(exports, require, module) { +exports.loadDivisionsPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + divisionId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionsPreferences', 'must provide a divisionId or query parameters'); + } + return this.loadItems('divisionPreferences', params, callback); +}; + +exports.loadDivisionPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + divisionId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadDivisionPreferences', 'must provide a divisionId or query parameters'); + } + return this.loadItem('divisionPreferences', params, callback); +}; + +exports.saveDivisionPreferences = function(divisionPreferences, callback) { + if (!divisionPreferences) { + throw new TSArgsError('teamsnap.saveDivisionPreferences', "`divisionPreferences` must be provided"); + } + if (!this.isItem(divisionPreferences, 'divisionPreferences')) { + throw new TSArgsError('teamsnap.saveDivisionPreferences', "`divisionPreferences.type` must be 'divisionPreferences'"); + } + return this.saveItem(divisionPreferences, callback); +}; + +}); + +require.register("collections/eventStatistics.coffee", function(exports, require, module) { +exports.loadEventStatistics = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadEventStatistics', 'must provide a teamId or query parameters'); + } + return this.loadItems('eventStatistic', params, callback); +}; + +}); + +require.register("collections/events.coffee", function(exports, require, module) { +var includes, key, ref, value; + +exports.EVENTS = { + NONE: 'none', + FUTURE: 'future', + ALL: 'all' +}; + +exports.REMINDERS = { + ALL: 'all', + UNSET: 'unset' +}; + +includes = {}; + +ref = exports.EVENTS; +for (key in ref) { + value = ref[key]; + includes[value] = true; +} + +exports.loadEvents = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadEvents', 'must provide a teamId or query parameters'); + } + return this.loadItems('event', params, callback); +}; + +exports.createEvent = function(data) { + return this.createItem(data, { + type: 'event', + isGame: false, + tracksAvailability: true + }); +}; + +exports.saveEvent = function(event, callback) { + var ref1, ref2; + if (!event) { + throw new TSArgsError('teamsnap.saveEvent', "`event` must be provided"); + } + if (!this.isItem(event, 'event')) { + throw new TSArgsError('teamsnap.saveEvent', "`event.type` must be 'event'"); + } + if (!(event.isGame || ((ref1 = event.name) != null ? ref1.trim() : void 0))) { + return this.reject('You must provide a name.', 'name', callback); + } + if (!event.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!(event.locationId || event.divisionLocationId)) { + return this.reject('You must choose a location.', 'locationId', callback); + } + if (event.isGame && !event.opponentId) { + return this.reject('You must choose an opponent.', 'opponentId', callback); + } + if (isNaN((ref2 = event.startDate) != null ? ref2.getTime() : void 0)) { + return this.reject('You must provide a valid start date.', 'startDate', callback); + } + if (event.notifyTeam && !event.notifyTeamAsMemberId) { + return this.reject('You must provide the current member\'s id.', 'notifyTeamAsMemberId', callback); + } + return this.saveItem(event, callback); +}; + +exports.deleteEvent = function(event, include, notify, notifyAs, callback) { + var params; + params = {}; + if (!event) { + throw new TSArgsError('teamsnap.deleteEvent', '`event` must be provided'); + } + if (typeof include === 'function') { + callback = include; + include = null; + } + if (!include && event.repeatingUuid) { + include = this.EVENTS.NONE; + } + if (include) { + if (!includes[include]) { + throw new TSArgsError('teamsnap.deleteEvent', "`include` must be one of " + (Object.keys(includes).join(', '))); + } + params.repeatingInclude = include; + } + if (notify) { + params.notifyTeam = notify; + if (!notifyAs) { + throw new TSArgsError('teamsnap.deleteEvent', '`notifyTeamAsMemberId` must be provided'); + } + params.notifyTeamAsMemberId = notifyAs; + } + return this.deleteItem(event, params, callback); +}; + +exports.sendAvailabilityReminders = function(eventId, sendingMemberId, include) { + var options; + if (!include) { + include = []; + } + if (this.isItem(eventId, 'event')) { + eventId = eventId.id; + } + if (this.isItem(sendingMemberId, 'member')) { + sendingMemberId = sendingMemberId.id; + } else if (this.isItem(sendingMemberId, 'divisionMember')) { + sendingMemberId = sendingMemberId.id; + } + if (!this.isId(eventId)) { + throw new TSArgsError('teamsnap.sendAvailabilityReminders', 'must include id `eventId`'); + } + if (!this.isId(sendingMemberId)) { + throw new TSArgsError('teamsnap.sendAvailabilityReminders', 'must include id `sendingMemberId`'); + } + if (!Array.isArray(include)) { + throw new TSArgsError('teamsnap.sendAvailabilityReminders', "`include` must be an array of member ids"); + } + if ((include == null) || include.length === 0) { + throw new TSArgsError('teamsnap.sendAvailabilityReminders', "`include` must be an array of member ids"); + } + options = { + id: eventId, + membersToNotify: include, + notifyTeamAsMemberId: sendingMemberId + }; + return this.collections.events.exec('sendAvailabilityReminders', options); +}; + +exports.getEventSort = function() { + return (function(_this) { + return function(itemA, itemB) { + var valueA, valueB; + if (!_this.isItem(itemA, 'event') || !_this.isItem(itemB, 'event')) { + valueA = itemA.type; + valueB = itemB.type; + } else { + valueA = itemA.startDate; + valueB = itemB.startDate; + } + if (valueA > valueB) { + return 1; + } else if (valueA < valueB) { + return -1; + } else { + return 0; + } + }; + })(this); +}; + +exports.bulkCreateEvents = function(params, callback) { + var options; + if (!params.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!Array.isArray(params.events)) { + throw new TSArgsError('teamsnap.bulkCreateEvents', "`events` must be an array of events"); + } + options = { + templates: params.events, + teamId: params.teamId, + notifyTeamAsMemberId: params.sendingMemberId, + notifyTeam: params.notifyTeam + }; + return this.collections.events.exec('bulkCreate', options, callback); +}; + +}); + +require.register("collections/facebookPages.coffee", function(exports, require, module) { +exports.loadFacebookPages = function(callback) { + var params; + params = {}; + return this.loadItems('facebookPage', params, callback); +}; + +}); + +require.register("collections/forumPosts.coffee", function(exports, require, module) { +exports.loadForumPosts = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadForumPosts', 'must provide a teamId or query parameters'); + } + return this.loadItems('forumPost', params, callback); +}; + +exports.createForumPost = function(data) { + return this.createItem(data, { + type: 'forumPost' + }); +}; + +exports.saveForumPost = function(forumPost, callback) { + var ref; + if (!forumPost) { + throw new TSArgsError('teamsnap.saveForumPost', "`forumPost` must be provided"); + } + if (!this.isItem(forumPost, 'forumPost')) { + throw new TSArgsError('teamsnap.saveForumPost', "`type` must be 'forumPost'"); + } + if (!forumPost.forumTopicId) { + return this.reject('You must provide a forum topic id.', 'forumTopicId', callback); + } + if (!forumPost.memberId) { + return this.reject('You must provide a member id.', 'memberId', callback); + } + if (!((ref = forumPost.message) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a message for the forum post.', 'message', callback); + } + return this.saveItem(forumPost, callback); +}; + +exports.deleteForumPost = function(forumPost, callback) { + if (!forumPost) { + throw new TSArgsError('teamsnap.deleteForumPost', '`forumPost` must be provided'); + } + return this.deleteItem(forumPost, callback); +}; + +}); + +require.register("collections/forumSubscriptions.coffee", function(exports, require, module) { +exports.loadForumSubscriptions = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadForumSubscriptions', 'must provide a teamId or query parameters'); + } + return this.loadItems('forumSubscription', params, callback); +}; + +exports.createForumSubscription = function(data) { + return this.createItem(data, { + type: 'forumSubscription' + }); +}; + +exports.saveForumSubscription = function(forumSubscription, callback) { + if (!forumSubscription) { + throw new TSArgsError('teamsnap.saveForumSubscription', "`forumSubscription` must be provided"); + } + if (!this.isItem(forumSubscription, 'forumSubscription')) { + throw new TSArgsError('teamsnap.saveForumSubscription', "`type` must be 'forumSubscription'"); + } + if (!forumSubscription.forumTopicId) { + return this.reject('You must provide a forum topic id.', 'forumTopicId', callback); + } + if (!forumSubscription.memberId) { + return this.reject('You must provide a member id.', 'memberId', callback); + } + return this.saveItem(forumSubscription, callback); +}; + +exports.deleteForumSubscription = function(forumSubscription, callback) { + if (!forumSubscription) { + throw new TSArgsError('teamsnap.deleteForumSubscription', '`forumSubscription` must be provided'); + } + return this.deleteItem(forumSubscription, callback); +}; + +}); + +require.register("collections/forumTopics.coffee", function(exports, require, module) { +exports.loadForumTopics = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadForumTopics', 'must provide a teamId or query parameters'); + } + return this.loadItems('forumTopic', params, callback); +}; + +exports.createForumTopic = function(data) { + return this.createItem(data, { + type: 'forumTopic' + }); +}; + +exports.saveForumTopic = function(forumTopic, callback) { + var ref; + if (!forumTopic) { + throw new TSArgsError('teamsnap.saveForumTopic', "`forumTopic` must be provided"); + } + if (!this.isItem(forumTopic, 'forumTopic')) { + throw new TSArgsError('teamsnap.saveForumTopic', "`type` must be 'forumTopic'"); + } + if (!forumTopic.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!((ref = forumTopic.title) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a title for the forum topic.', 'title', callback); + } + return this.saveItem(forumTopic, callback); +}; + +exports.deleteForumTopic = function(forumTopic, callback) { + if (!forumTopic) { + throw new TSArgsError('teamsnap.deleteForumTopic', '`forumTopic` must be provided'); + } + return this.deleteItem(forumTopic, callback); +}; + +}); + +require.register("collections/leagueCustomData.coffee", function(exports, require, module) { +exports.loadLeagueCustomData = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadLeagueCustomData', 'must provide a teamId or query parameters'); + } + return this.loadItems('leagueCustomDatum', params, callback); +}; + +exports.createLeagueCustomDatum = function(data, field) { + return this.createItem(data, { + type: 'leagueCustomDatum', + leagueCustomFieldId: field.id, + kind: field.kind, + name: field.name, + isPrivate: false, + value: null + }); +}; + +exports.saveLeagueCustomDatum = function(leagueCustomDatum, callback) { + if (!leagueCustomDatum) { + throw new TSArgsError('teamsnap.saveLeagueCustomDatum', '`leagueCustomDatum` must be provided'); + } + if (!this.isItem(leagueCustomDatum, 'leagueCustomDatum')) { + throw new TSArgsError('teamsnap.saveLeagueCustomDatum', "`leagueCustomDatum.type` must be 'leagueCustomDatum'"); + } + return this.saveItem(leagueCustomDatum, callback); +}; + +}); + +require.register("collections/leagueCustomFields.coffee", function(exports, require, module) { +exports.loadLeagueCustomFields = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadLeagueCustomFields', 'must provide a teamId or query parameters'); + } + return this.loadItems('leagueCustomField', params, callback); +}; + +}); + +require.register("collections/leagueRegistrantDocuments.coffee", function(exports, require, module) { +exports.loadLeagueRegistrantDocuments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadLeagueRegistrantDocuments', 'must provide a teamId or query parameters'); + } + return this.loadItems('leagueRegistrantDocument', params, callback); +}; + +}); + +require.register("collections/locations.coffee", function(exports, require, module) { +exports.loadLocations = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadLocations', 'must provide a teamId or query parameters'); + } + return this.loadItems('location', params, callback); +}; + +exports.createLocation = function(data) { + return this.createItem(data, { + type: 'location', + name: '' + }); +}; + +exports.saveLocation = function(location, callback) { + var ref; + if (!location) { + throw new TSArgsError('teamsnap.saveLocation', "`location` must be provided"); + } + if (!this.isItem(location, 'location')) { + throw new TSArgsError('teamsnap.saveLocation', "`location.type` must be 'location'"); + } + if (!location.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!((ref = location.name) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a name for the location.', 'name', callback); + } + return this.saveItem(location, callback); +}; + +exports.deleteLocation = function(location, callback) { + if (!location) { + throw new TSArgsError('teamsnap.deleteLocation', '`location` must be provided'); + } + return this.deleteItem(location, callback); +}; + +}); + +require.register("collections/memberAssignments.coffee", function(exports, require, module) { +exports.loadMemberAssignments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberAssignments', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberAssignment', params, callback); +}; + +exports.createMemberAssignment = function(data) { + return this.createItem(data, { + type: 'memberAssignment' + }); +}; + +exports.saveMemberAssignment = function(memberAssignment, callback) { + if (!memberAssignment) { + throw new TSArgsError('teamsnap.saveMemberAssignment', "`memberAssignment` must be provided"); + } + if (!this.isItem(memberAssignment, 'memberAssignment')) { + throw new TSArgsError('teamsnap.saveMemberAssignment', "`memberAssignment.type` must be 'memberAssignment'"); + } + return this.saveItem(memberAssignment, callback); +}; + +exports.deleteMemberAssignment = function(memberAssignment, callback) { + if (!memberAssignment) { + throw new TSArgsError('teamsnap.deleteMemberAssignment', '`memberAssignment` must be provided'); + } + return this.deleteItem(memberAssignment, callback); +}; + +}); + +require.register("collections/memberBalances.coffee", function(exports, require, module) { +exports.loadMemberBalances = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberBalances', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberBalance', params, callback); +}; + +}); + +require.register("collections/memberEmailAddresses.coffee", function(exports, require, module) { +exports.INVITED_STATES = ["new", "new_user", "existing_user"]; + +exports.loadMemberEmailAddresses = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberEmailAddresses', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberEmailAddress', params, callback); +}; + +exports.createMemberEmailAddress = function(data) { + return this.createItem(data, { + type: 'memberEmailAddress', + receivesTeamEmails: true + }); +}; + +exports.inviteMemberEmailAddresses = function(options, callback) { + if (!options.memberEmailAddressIds) { + throw new TSArgsError('teamsnap.inviteMemberEmailAddresses', 'options.memberEmailAddressIds is required.'); + } + if (!options.memberId) { + throw new TSArgsError('teamsnap.inviteMemberEmailAddresses', 'options.memberId is required.'); + } + if (!options.teamId) { + throw new TSArgsError('teamsnap.inviteMemberEmailAddresses', 'options.teamId is required.'); + } + if (!options.notifyAsMemberId) { + throw new TSArgsError('teamsnap.inviteMemberEmailAddresses', 'options.notifyAsMemberId is required.'); + } + return this.collections.memberEmailAddresses.exec('invite', options).pop().callback(callback); +}; + +exports.saveMemberEmailAddress = function(memberEmailAddress, callback) { + if (!memberEmailAddress) { + throw new TSArgsError('teamsnap.saveMemberEmailAddress', '`memberEmailAddress` must be provided'); + } + if (!this.isItem(memberEmailAddress, 'memberEmailAddress')) { + throw new TSArgsError('teamsnap.saveMemberEmailAddress', "`memberEmailAddress.type` must be 'memberEmailAddress'"); + } + if (!memberEmailAddress.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + return this.saveItem(memberEmailAddress, callback); +}; + +exports.deleteMemberEmailAddress = function(memberEmailAddress, callback) { + if (!memberEmailAddress) { + throw new TSArgsError('teamsnap.deleteMemberEmailAddress', '`memberEmailAddress` must be provided'); + } + return this.deleteItem(memberEmailAddress, callback); +}; + +}); + +require.register("collections/memberFiles.coffee", function(exports, require, module) { +exports.loadMemberFiles = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberFiles', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberFile', params, callback); +}; + +exports.createMemberFile = function(data) { + return this.createItem(data, { + type: 'memberFile' + }); +}; + +exports.saveMemberFile = function(memberFile, callback) { + if (!memberFile) { + throw new TSArgsError('teamsnap.saveMemberFile', '`memberFile` must be provided'); + } + if (!this.isItem(memberFile, 'memberFile')) { + throw new TSArgsError('teamsnap.saveMemberFile', "`memberFile.type` must be 'memberFile'"); + } + if (!memberFile.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + return this.saveItem(memberFile, callback); +}; + +exports.deleteMemberFile = function(memberFile, callback) { + if (!memberFile) { + throw new TSArgsError('teamsnap.deleteMemberFile', '`memberFile` must be provided'); + } + return this.deleteItem(memberFile, callback); +}; + +exports.uploadMemberFile = function(memberFileId, file, callback) { + var params; + if (this.isItem(memberFileId, 'memberFile')) { + memberFileId = memberFileId.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(memberFileId)) { + throw new TSArgsError('teamsnap.uploadMemberFile', 'must include `memberFileId`'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadMemberFile', 'must include `file` as type File'); + } + params = { + memberFileId: memberFileId, + file: file + }; + return this.collections.memberFiles.exec('uploadMemberFile', params).pop().callback(callback); +}; + +}); + +require.register("collections/memberLinks.coffee", function(exports, require, module) { +exports.loadMemberLinks = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberLinks', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberLink', params, callback); +}; + +exports.createMemberLink = function(data) { + return this.createItem(data, { + type: 'memberLink' + }); +}; + +exports.saveMemberLink = function(memberLink, callback) { + if (!memberLink) { + throw new TSArgsError('teamsnap.saveMemberLink', '`memberLink` must be provided'); + } + if (!this.isItem(memberLink, 'memberLink')) { + throw new TSArgsError('teamsnap.saveMemberLink', "`memberLink.type` must be 'memberLink'"); + } + if (!memberLink.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + return this.saveItem(memberLink, callback); +}; + +exports.deleteMemberLink = function(memberLink, callback) { + if (!memberLink) { + throw new TSArgsError('teamsnap.deleteMemberLink', '`memberLink` must be provided'); + } + return this.deleteItem(memberLink, callback); +}; + +}); + +require.register("collections/memberPayments.coffee", function(exports, require, module) { +exports.loadMemberPayments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberPayments', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberPayment', params, callback); +}; + +exports.saveMemberPayment = function(memberPayment, callback) { + if (!memberPayment) { + throw new TSArgsError('teamsnap.saveMemberPayment', '`memberPayment` must be provided'); + } + if (!this.isItem(memberPayment, 'memberPayment')) { + throw new TSArgsError('teamsnap.saveMemberPayment', "`memberPayment.type` must be 'memberPayment'"); + } + if (!memberPayment.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + return this.saveItem(memberPayment, callback); +}; + +exports.memberPaymentTransaction = function(memberPaymentId, amount, note, callback) { + var params; + if (!this.isItem(memberPaymentId)) { + throw new TSArgsError('teamsnap.memberPaymentTransaction', "must provide a `memberPaymentId`"); + } + if (this.isItem(memberPaymentId)) { + memberPaymentId = memberPaymentId.id; + } + if (!amount) { + return this.reject('You must add an amount.', 'amount', callback); + } + if (typeof note === 'function') { + callback = note; + } + params = { + memberPaymentId: memberPaymentId, + amount: amount, + note: note + }; + return this.collections.memberPayments.exec('transaction', params).pop().callback(callback); +}; + +}); + +require.register("collections/memberPhoneNumbers.coffee", function(exports, require, module) { +exports.loadMemberPhoneNumbers = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberPhoneNumbers', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberPhoneNumber', params, callback); +}; + +exports.createMemberPhoneNumber = function(data) { + return this.createItem(data, { + type: 'memberPhoneNumber' + }); +}; + +exports.saveMemberPhoneNumber = function(memberPhoneNumber, callback) { + if (!memberPhoneNumber) { + throw new TSArgsError('teamsnap.saveMemberPhoneNumber', '`memberPhoneNumber` must be provided'); + } + if (!this.isItem(memberPhoneNumber, 'memberPhoneNumber')) { + throw new TSArgsError('teamsnap.saveMemberPhoneNumber', "`memberPhoneNumber.type` must be 'memberPhoneNumber'"); + } + if (!memberPhoneNumber.memberId) { + return this.reject('You must choose a member.', 'memberId', callback); + } + return this.saveItem(memberPhoneNumber, callback); +}; + +exports.deleteMemberPhoneNumber = function(memberPhoneNumber, callback) { + if (!memberPhoneNumber) { + throw new TSArgsError('teamsnap.deleteMemberPhoneNumber', '`memberPhoneNumber` must be provided'); + } + return this.deleteItem(memberPhoneNumber, callback); +}; + +}); + +require.register("collections/memberPhotos.coffee", function(exports, require, module) { +exports.loadMemberPhotos = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberPhotos', 'must provide a `teamId` or query parameters'); + } + return this.loadItems('memberPhoto', params, callback); +}; + +exports.loadMemberPhoto = function(params, callback) { + if (this.isId(params)) { + params = { + id: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberPhoto', 'must provide an `id` or query parameters'); + } + return this.loadItem('memberPhoto', params, callback); +}; + +}); + +require.register("collections/memberRegistrationSignups.coffee", function(exports, require, module) { +exports.loadMemberRegistrationSignups = function(params, callback) { + if (this.isId(params)) { + params = { + id: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberRegistrationSignups', 'must provide a id or query parameters'); + } + return this.loadItems('memberRegistrationSignup', params, callback); +}; + +}); + +require.register("collections/memberStatistics.coffee", function(exports, require, module) { +exports.loadMemberStatistics = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberStatistics', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberStatistic', params, callback); +}; + +}); + +require.register("collections/members.coffee", function(exports, require, module) { +exports.loadMembers = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMembers', 'must provide a teamId or query parameters'); + } + return this.loadItems('member', params, callback); +}; + +exports.createMember = function(data) { + return this.createItem(data, { + type: 'member' + }); +}; + +exports.saveMember = function(member, callback) { + var ref; + if (!member) { + throw new TSArgsError('teamsnap.saveMember', "`member` must be provided"); + } + if (!this.isItem(member, 'member')) { + throw new TSArgsError('teamsnap.saveMember', "`type` must be 'member'"); + } + if (!member.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!((ref = member.firstName) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a first name for the member.', 'name', callback); + } + return this.saveItem(member, callback); +}; + +exports.deleteMember = function(member, callback) { + if (!member) { + throw new TSArgsError('teamsnap.deleteMember', '`member` must be provided'); + } + return this.deleteItem(member, callback); +}; + +exports.uploadMemberPhoto = function(memberId, file, callback) { + var params; + if (this.isItem(memberId, 'member')) { + memberId = memberId.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(memberId)) { + throw new TSArgsError('teamsnap.deleteMemberPhoto', "`memberId` must be a valid id"); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadMemberFile', 'must include `file` as type File'); + } + params = { + memberId: memberId, + file: file + }; + return this.collections.members.exec('uploadMemberPhoto', params).pop().callback(callback); +}; + +exports.removeMemberPhoto = function(memberId, callback) { + var params; + if (this.isItem(memberId, 'member')) { + memberId = memberId.id; + } + if (!this.isId(memberId)) { + throw new TSArgsError('teamsnap.deleteMemberPhoto', "`memberId` must be a valid id"); + } + params = { + memberId: memberId + }; + return this.collections.members.exec('removeMemberPhoto', params).pop().callback(callback); +}; + +exports.generateMemberThumbnail = function(memberId, x, y, width, height, callback) { + var params; + if (this.isItem(memberId, 'member')) { + memberId = memberId.id; + } + if (!((memberId != null) && (x != null) && (y != null) && (width != null) && (height != null))) { + throw new TSArgsError('teamsnap.generateThumbnail', "`memberId`, `x`, `y`, `width`, and `height` are all required"); + } + if (!this.isId(memberId)) { + throw new TSArgsError('teamsnap.generateMemberThumbnail', "`memberId` must be a valid id"); + } + params = { + memberId: memberId, + x: x, + y: y, + width: width, + height: height + }; + return this.collections.members.exec('generateMemberThumbnail', params).pop().callback(callback); +}; + +exports.disableMember = function(memberId, callback) { + var params; + if (this.isItem(memberId, 'member')) { + memberId = memberId.id; + } + if (!this.isId(memberId)) { + throw new TSArgsError('teamsnap.disableMember', "`memberId` must be a valid id"); + } + params = { + memberId: memberId + }; + return this.collections.members.exec('disableMember', params).pop().callback(callback); +}; + +exports.divisionLoadMembers = function(params, callback) { + if (!params.divisionId) { + throw new TSArgsError('teamsnap.divisionLoadMembers', "`divisionId` must be provided"); + } + return this.collections.members.queryItems('divisionSearch', params, callback); +}; + +exports.divisionAdvancedLoadMembers = function(params, callback) { + if (!params.divisionId) { + throw new TSArgsError('teamsnap.divisionAdvancedLoadMembers', "`divisionId` must be provided"); + } + return this.collections.members.queryItems('advancedDivisionSearch', params, callback); +}; + +exports.memberName = function(member, reverse, forSort) { + if (!member) { + return ''; + } + if (reverse && (member.firstName && member.lastName || forSort)) { + return member.lastName + ', ' + member.firstName; + } + return [member.firstName || '', member.lastName || ''].join(' ').trim(); +}; + +exports.getMemberSort = function(reverse) { + return (function(_this) { + return function(itemA, itemB) { + var valueA, valueB; + if (!_this.isItem(itemA, 'member') || !_this.isItem(itemB, 'member')) { + valueA = itemA.type; + valueB = itemB.type; + } else { + valueA = _this.memberName(itemA, reverse, true).toLowerCase(); + valueB = _this.memberName(itemB, reverse, true).toLowerCase(); + } + if (typeof (valueA != null ? valueA.localeCompare : void 0) === 'function') { + return valueA.localeCompare(valueB); + } else { + if (valueA === valueB) { + return 0; + } else if (!valueA && valueB) { + return 1; + } else if (valueA && !valueB) { + return -1; + } else if (valueA > valueB) { + return 1; + } else if (valueA < valueB) { + return -1; + } else { + return 0; + } + } + }; + })(this); +}; + +exports.canEditTeam = function(member, team) { + if (!(member && team)) { + return false; + } + return (member.isManager || member.isOwner) && (!team.isArchivedSeason || member.isOwner); +}; + +exports.canEditItem = function(member, team, item) { + if (!(member && team && this.isItem(item))) { + return false; + } + if (item.readOnly) { + return false; + } + if (item.type === 'member' && item.isOwner && !member.isOwner) { + return false; + } + if (teamsnap.canEditTeam(member, team)) { + return true; + } + if (team.isArchivedSeason) { + return false; + } + if (this.isItem(item, 'member')) { + return item.href === member.href; + } else { + return item.links.member.href === member.href; + } +}; + +exports.importMembersFromTeam = function(memberIds, teamId, sendInvites, callback) { + var params; + if (!memberIds) { + throw new TSArgsError('teamsnap.importMembersFromTeam', 'must include `memberIds`'); + } + if (!this.isItem(teamId)) { + throw new TSArgsError('teamsnap.importMembersFromTeam', "must provide a teamId"); + } + if (this.isItem(teamId)) { + teamId = teamId.id; + } + if (typeof sendInvites === 'function') { + callback = sendInvites; + } + params = { + sourceMemberIds: memberIds, + destinationTeamId: teamId, + sendInvites: sendInvites + }; + return this.collections.members.exec('importFromTeam', params, callback); +}; + +exports.loadImportableMembers = function(userId, includeArchivedTeams, callback) { + var params; + if (!userId) { + throw new TSArgsError('teamsnap.loadImportableMembers', "must provide a userId"); + } + if (typeof includeArchivedTeams === 'function') { + callback = includeArchivedTeams; + } + params = { + userId: userId, + includeArchivedTeams: includeArchivedTeams + }; + return this.collections.members.queryItems('importableMembers', params, callback); +}; + +exports.bulkDeleteMembers = function(members, callback) { + if (Array.isArray(members)) { + if (members.length === 0) { + throw new TSArgsError('teamsnap.bulkDeleteMembers', 'The array of members to be deleted is empty.'); + } else if (members.every((function(_this) { + return function(member) { + return _this.isItem(member, 'member'); + }; + })(this))) { + members = { + memberId: members.map(function(member) { + return member.id; + }) + }; + } else { + throw new TSArgsError('teamsnap.bulkDeleteMembers', 'Must provide an `array` of member `ids` or `member` objects'); + } + } else if (typeof members === 'object' && this.isItem(members, 'member')) { + members = { + memberId: members.id + }; + } else { + throw new TSArgsError('teamsnap.bulkDeleteMembers', 'Must provide an `array` of members, or a `member` object'); + } + return this.collections.members.exec('bulkDelete', members).callback(callback); +}; + +exports.moveMemberToTeam = function(params, callback) { + if (!params.member) { + throw new TSArgsError('teamsnap.moveMemberToTeam', 'params must include `member`'); + } + if (!params.divisionId) { + throw new TSArgsError('teamsnap.moveMemberToTeam', 'params must include `divisionId`'); + } + if (Array.isArray(params.member)) { + if (params.member.length === 0) { + throw new TSArgsError('teamsnap.moveMemberToTeam', 'member in params is empty.'); + } else if (params.member.every((function(_this) { + return function(member) { + return _this.isItem(member, 'member'); + }; + })(this))) { + params.memberId = params.member.map(function(member) { + return member.id; + }); + } else { + throw new TSArgsError('teamsnap.moveMemberToTeam', 'Must provide an `array` of member objects or a `member` object for member'); + } + } else if (this.isItem(params.member, 'member')) { + params.memberId = params.member.id; + } else { + throw new TSArgsError('teamsnap.moveMemberToTeam', 'Must provide an `array` of member objects or `member` objects for member'); + } + if (this.isItem(params.divisionId, 'division')) { + params.divisionId = params.divisionId.id; + } + if (this.isItem(params.teamId, 'team')) { + params.teamId = params.teamId.id; + } + return this.collections.members.exec('moveMember', params).callback(callback); +}; + +}); + +require.register("collections/membersPreferences.coffee", function(exports, require, module) { +exports.PREFS = { + SCHEDULE_SHOW: { + ALL: 1, + GAMES: 2, + EVENTS: 3 + } +}; + +exports.loadMembersPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMembersPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItems('memberPreferences', params, callback); +}; + +exports.loadMemberPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMemberPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItem('memberPreferences', params, callback); +}; + +exports.saveMemberPreferences = function(memberPreferences, callback) { + if (!memberPreferences) { + throw new TSArgsError('teamsnap.saveMemberPreferences', "`memberPreferences` must be provided"); + } + if (!this.isItem(memberPreferences, 'memberPreferences')) { + throw new TSArgsError('teamsnap.saveMemberPreferences', "`memberPreferences.type` must be 'memberPreferences'"); + } + return this.saveItem(memberPreferences, callback); +}; + +}); + +require.register("collections/messageData.coffee", function(exports, require, module) { +exports.loadMessageData = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMessageData', 'must provide a teamId or query parameters'); + } + return this.loadItems('messageDatum', params, callback); +}; + +}); + +require.register("collections/messages.coffee", function(exports, require, module) { +exports.loadMessages = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadMessages', 'must provide a teamId or query parameters'); + } + return this.loadItems('message', params, callback); +}; + +exports.markMessageAsRead = function(params, callback) { + if (typeof params === 'object') { + params = { + id: params.id + }; + } else if (this.isId(params)) { + params = { + id: params + }; + } else { + throw new TSArgsError('teamsnap.markMessageAsRead', 'a message `id` or `message` object must be provided'); + } + return this.collections.messages.exec('markMessageAsRead', params).pop().callback(callback); +}; + +exports.bulkDeleteMessages = function(messages, callback) { + if (Array.isArray(messages)) { + if (messages.length === 0) { + throw new TSArgsError('teamsnap.bulkDeleteMessages', 'The array of messages to be deleted is empty.'); + } else if (this.isItem(messages[0], 'message')) { + messages = { + id: messages.map(function(message) { + return message.id; + }) + }; + } else if (this.isId(messages[0])) { + messages = { + id: messages + }; + } else { + throw new TSArgsError('teamsnap.bulkDeleteMessages', 'Must provide an `array` of message `ids` or `message` objects'); + } + } else if (typeof messages === 'object' && this.isItem(messages, 'message')) { + messages = { + id: messages.id + }; + } else if (this.isId(messages)) { + messages = { + id: messages + }; + } else { + throw new TSArgsError('teamsnap.bulkDeleteMessages', 'Must provide an `array` of message `ids`, an `id` or a `message` object'); + } + return this.collections.messages.exec('bulkDelete', messages).callback(callback); +}; + +}); + +require.register("collections/opponents.coffee", function(exports, require, module) { +exports.loadOpponents = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadOpponents', 'must provide a teamId or query parameters'); + } + return this.loadItems('opponent', params, callback); +}; + +exports.createOpponent = function(data) { + return this.createItem(data, { + type: 'opponent', + name: '' + }); +}; + +exports.saveOpponent = function(opponent, callback) { + var ref; + if (!opponent) { + throw new TSArgsError('teamsnap.saveOpponent', "`opponent` must be provided"); + } + if (!this.isItem(opponent, 'opponent')) { + throw new TSArgsError('teamsnap.saveOpponent', "`opponent.type` must be 'opponent'"); + } + if (!opponent.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!((ref = opponent.name) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a name for the opponent.', 'name', callback); + } + return this.saveItem(opponent, callback); +}; + +exports.deleteOpponent = function(opponent, callback) { + if (!opponent) { + throw new TSArgsError('teamsnap.deleteOpponent', '`opponent` must be provided'); + } + return this.deleteItem(opponent, callback); +}; + +}); + +require.register("collections/opponentsResults.coffee", function(exports, require, module) { +exports.loadOpponentsResults = function(params, callback) { + if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadOpponentsResults', 'must provide query parameters'); + } + return this.loadItems('opponentResults', params, callback); +}; + +exports.loadOpponentResults = function(opponentId, callback) { + var params; + if (!this.isId(opponentId)) { + throw new TSArgsError('teamsnap.loadOpponentResults', 'must provide an opponentId'); + } + params = { + id: opponentId + }; + return this.loadItem('opponentResults', params, callback); +}; + +}); + +require.register("collections/paymentNotes.coffee", function(exports, require, module) { +exports.loadPaymentNotes = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadPaymentNotes', 'must provide a teamId or query parameters'); + } + return this.loadItems('paymentNote', params, callback); +}; + +exports.createPaymentNote = function(data) { + return this.createItem(data, { + type: 'paymentNote' + }); +}; + +exports.savePaymentNote = function(paymentNote, callback) { + if (!paymentNote) { + throw new TSArgsError('teamsnap.savePaymentNote', '`paymentNote` must be provided'); + } + if (!this.isItem(paymentNote, 'paymentNote')) { + throw new TSArgsError('teamsnap.savePaymentNote', "`paymentNote.type` must be 'paymentNote'"); + } + if (!paymentNote.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!paymentNote.memberPaymentId) { + return this.reject('You must specify a memberPaymentId.', 'memberPaymentId', callback); + } + if (!paymentNote.note) { + return this.reject('You must provide a note.', 'note', callback); + } + return this.saveItem(paymentNote, callback); +}; + +}); + +require.register("collections/plans.coffee", function(exports, require, module) { +exports.loadPlans = function(params, callback) { + if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadPlans', 'must provide query parameters'); + } + return this.loadItems('plan', params, callback); +}; + +exports.loadPlan = function(teamId, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.loadPlan', 'must provide a teamId'); + } + params = { + teamId: teamId + }; + return this.loadItem('plan', params, callback); +}; + +}); + +require.register("collections/registrationForms.coffee", function(exports, require, module) { +exports.loadRegistrationForms = function(params, callback) { + if (this.isId(params)) { + params = { + id: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadRegistrationForms', 'must provide a id or query parameters'); + } + return this.loadItems('registrationForm', params, callback); +}; + +}); + +require.register("collections/sponsors.coffee", function(exports, require, module) { +exports.loadSponsors = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadSponsors', 'must provide a teamId or query parameters'); + } + return this.loadItems('sponsor', params, callback); +}; + +exports.createSponsor = function(data) { + return this.createItem(data, { + type: 'sponsor', + name: '' + }); +}; + +exports.saveSponsor = function(sponsor, callback) { + if (!sponsor) { + throw new TSArgsError('teamsnap.saveSponsor', "`sponsor` must be provided"); + } + if (!this.isItem(sponsor, 'sponsor')) { + throw new TSArgsError('teamsnap.saveSponsor', "`sponsor.type` must be 'sponsor'"); + } + return this.saveItem(sponsor, callback); +}; + +exports.deleteSponsor = function(sponsor, callback) { + if (!sponsor) { + throw new TSArgsError('teamsnap.deleteSponsor', "`sponsor` must be provided"); + } + return this.deleteItem(sponsor, callback); +}; + +exports.uploadSponsorLogo = function(sponsorId, file, callback) { + var params; + if (this.isItem(sponsorId, 'sponsor')) { + sponsorId = sponsorId.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(sponsorId)) { + throw new TSArgsError('teamsnap.uploadSponsorLogo', 'must include `sponsorId`'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadSponsorLogo', 'must include `file` as type File'); + } + params = { + sponsorId: sponsorId, + file: file + }; + return this.collections.sponsors.exec('uploadSponsorLogo', params).pop().callback(callback); +}; + +exports.deleteSponsorLogo = function(sponsorId, callback) { + var params; + if (!sponsorId) { + throw new TSArgsError('teamsnap.deleteSponsorLogo', "`sponsorId` must be provided"); + } + if (this.isItem(sponsorId, 'sponsor')) { + sponsorId = sponsorId.id; + } + if (!this.isId(sponsorId)) { + throw new TSArgsError('teamsnap.deleteSponsorLogo', "`sponsorId` must be a valid id"); + } + params = { + sponsorId: sponsorId + }; + return this.collections.sponsors.exec('removeSponsorLogo', params).callback(callback); +}; + +}); + +require.register("collections/sports.coffee", function(exports, require, module) { +exports.loadSports = function(params, callback) { + if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadSports', 'must provide query parameters'); + } + return this.loadItems('sport', params, callback); +}; + +exports.loadSport = function(teamId, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.loadSport', 'must provide a teamId'); + } + params = { + teamId: teamId + }; + return this.loadItem('sport', params, callback); +}; + +}); + +require.register("collections/statisticAggregates.coffee", function(exports, require, module) { +exports.loadStatisticAggregates = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadStatisticAggregates', 'must provide a teamId or query parameters'); + } + return this.loadItems('statisticAggregate', params, callback); +}; + +}); + +require.register("collections/statisticData.coffee", function(exports, require, module) { +exports.loadStatisticData = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadStatisticData', 'must provide a teamId or query parameters'); + } + return this.loadItems('statisticDatum', params, callback); +}; + +exports.createStatisticDatum = function(data) { + return this.createItem(data, { + type: 'statisticDatum' + }); +}; + +exports.saveStatisticDatum = function(statisticDatum, callback) { + if (!statisticDatum) { + throw new TSArgsError('teamsnap.saveStatisticDatum', '`statisticDatum` must be provided'); + } + if (!this.isItem(statisticDatum, 'statisticDatum')) { + throw new TSArgsError('teamsnap.saveStatisticDatum', "`statisticDatum.type` must be 'statisticDatum'"); + } + if (!statisticDatum.eventId) { + return this.reject('You must specify an event.', 'eventId', callback); + } + if (!statisticDatum.statisticId) { + return this.reject('You must specify a statistic.', 'statisticId', callback); + } + if (!statisticDatum.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + return this.saveItem(statisticDatum, callback); +}; + +exports.deleteStatisticDatum = function(statisticDatum, callback) { + if (!statisticDatum) { + throw new TSArgsError('teamsnap.deleteStatisticDatum', '`statisticDatum` must be provided'); + } + return this.deleteItem(statisticDatum, callback); +}; + +exports.bulkSaveStatisticData = function(templates, callback) { + var params; + if (!templates) { + throw new TSArgsError('teamsnap.bulkSaveStatisticData', "`templates` must be provided"); + } + params = { + templates: templates + }; + return this.collections.statisticData.exec('bulkUpdateStatisticData', params).callback(callback); +}; + +exports.bulkDeleteStatisticData = function(member, event, callback) { + var params; + if (!member) { + throw new TSArgsError('teamsnap.bulkDeleteStatisticData', "`member` must be provided"); + } + if (!this.isItem(member, 'member')) { + throw new TSArgsError('teamsnap.bulkDeleteStatisticData', "`member.type` must be 'member'"); + } + if (!event) { + throw new TSArgsError('teamsnap.bulkDeleteStatisticData', "`event` must be provided"); + } + if (!this.isItem(event, 'event')) { + throw new TSArgsError('teamsnap.bulkDeleteStatisticData', "`event.type` must be 'event'"); + } + params = { + memberId: member.id, + eventId: event.id + }; + return this.collections.statisticData.exec('bulkDeleteStatisticData', params).callback(callback); +}; + +}); + +require.register("collections/statisticGroups.coffee", function(exports, require, module) { +exports.loadStatisticGroups = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadStatisticGroups', 'you must provide a a teamId or query parameters'); + } + return this.loadItems('statisticGroup', params, callback); +}; + +exports.createStatisticGroup = function(data) { + return this.createItem(data, { + type: 'statisticGroup' + }); +}; + +exports.saveStatisticGroup = function(statisticGroup, callback) { + if (!statisticGroup) { + throw new TSArgsError('teamsnap.saveStatisticGroup', '`statisticGroup` must be provided'); + } + if (!this.isItem(statisticGroup, 'statisticGroup')) { + throw new TSArgsError('teamsnap.saveStatisticGroup', "`statisticGroup.type` must be 'statisticGroup'"); + } + if (!statisticGroup.name) { + return this.reject('You must specify a name', 'name', callback); + } + if (!statisticGroup.teamId) { + return this.reject('You must specify a team', 'teamId', callback); + } + return this.saveItem(statisticGroup, callback); +}; + +exports.deleteStatisticGroup = function(statisticGroup, callback) { + if (!statisticGroup) { + throw new TSArgsError('teamsnap.deleteStatisticGroup', '`statisticGroup` must be provided'); + } + return this.deleteItem(statisticGroup, callback); +}; + +exports.reorderStatisticGroups = function(teamId, statisticGroupIds, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.reorderStatisticGroups', '`teamId` must be provided'); + } + if (!(statisticGroupIds && Array.isArray(statisticGroupIds))) { + throw new TSArgsError('teamsnap.reorderStatisticGroups', 'You must provide an array of ordered Statistic Group IDs'); + } + params = { + teamId: teamId, + sortedIds: statisticGroupIds + }; + return this.collections.statisticGroups.exec('reorderStatisticGroups', params).callback(callback); +}; + +}); + +require.register("collections/statistics.coffee", function(exports, require, module) { +exports.loadStatistics = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadStatistics', 'must provide a teamId or query parameters'); + } + return this.loadItems('statistic', params, callback); +}; + +exports.createStatistic = function(data) { + return this.createItem(data, { + type: 'statistic' + }); +}; + +exports.saveStatistic = function(statistic, callback) { + if (!statistic) { + throw new TSArgsError('teamsnap.saveStatistic', '`statistic` must be provided'); + } + if (!this.isItem(statistic, 'statistic')) { + throw new TSArgsError('teamsnap.saveStatistic', "`statistic.type` must be 'statistic'"); + } + if (!statistic.name) { + return this.reject('You must specify a name.', 'name', callback); + } + if (!statistic.acronym) { + return this.reject('You must specify an acronym.', 'acronym', callback); + } + if (!statistic.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + return this.saveItem(statistic, callback); +}; + +exports.deleteStatistic = function(statistic, callback) { + if (!statistic) { + throw new TSArgsError('teamsnap.deleteStatistic', '`statistic` must be provided'); + } + return this.deleteItem(statistic, callback); +}; + +exports.reorderStatistics = function(teamId, statisticIds, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.reorderStatistics', '`teamId` must be provided'); + } + if (!(statisticIds && Array.isArray(statisticIds))) { + throw new TSArgsError('teamsnap.reorderStatistics', 'You must provide an array of ordered Statistic IDs'); + } + params = { + teamId: teamId, + sortedIds: statisticIds + }; + return this.collections.statistics.exec('reorderStatistics', params).callback(callback); +}; + +}); + +require.register("collections/teamFees.coffee", function(exports, require, module) { +exports.loadTeamFees = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamFees', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamFee', params, callback); +}; + +exports.createTeamFee = function(data) { + return this.createItem(data, { + type: 'teamFee' + }); +}; + +exports.saveTeamFee = function(teamFee, callback) { + if (!teamFee) { + throw new TSArgsError('teamsnap.saveTeamFee', '`teamFee` must be provided'); + } + if (!this.isItem(teamFee, 'teamFee')) { + throw new TSArgsError('teamsnap.saveTeamFee', "`teamFee.type` must be 'teamFee'"); + } + if (!teamFee.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!teamFee.description) { + return this.reject('You must provide a team fee description.', 'description', callback); + } + if (!teamFee.amount) { + return this.reject('You must provide a fee amount.', 'description', callback); + } + return this.saveItem(teamFee, callback); +}; + +exports.deleteTeamFee = function(teamFee, callback) { + if (!teamFee) { + throw new TSArgsError('teamsnap.deleteTeamFee', '`teamFee` must be provided'); + } + return this.deleteItem(teamFee, callback); +}; + +}); + +require.register("collections/teamMedia.coffee", function(exports, require, module) { +exports.ROTATION_DIRECTIONS = { + CLOCKWISE: 'clockwise', + COUNTERCLOCKWISE: 'counterclockwise' +}; + +exports.loadTeamMedia = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamMedia', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamMedium', params, callback); +}; + +exports.createTeamMedium = function(data) { + return this.createItem(data, { + type: 'teamMedium' + }); +}; + +exports.uploadTeamMedium = function(teamMedium, progressCallback, callback) { + if (!teamMedium) { + throw new TSArgsError('teamsnap.uploadTeamMedium', "`teamMedium` must be provided"); + } + if (!this.isItem(teamMedium, 'teamMedium')) { + throw new TSArgsError('teamsnap.uploadTeamMedium', "`type` must be 'teamMedium'"); + } + if (!this.isId(teamMedium.teamId)) { + throw new TSArgsError('teamsnap.uploadTeamMedium', 'must include `teamId`'); + } + if (!this.isId(teamMedium.teamMediaGroupId)) { + throw new TSArgsError('teamsnap.uploadTeamMedium', 'must include `teamMediaGroupId`'); + } + if (!(teamMedium.file instanceof File)) { + throw new TSArgsError('teamsnap.uploadTeamMedium', 'must include `file` as type File'); + } + return this.collections.teamMedia.file('uploadTeamMedium', teamMedium, progressCallback).pop().callback(callback); +}; + +exports.deleteTeamMedium = function(teamMedium, callback) { + if (!teamMedium) { + throw new TSArgsError('teamsnap.deleteTeamMedium', '`teamMedium` must be provided'); + } + return this.deleteItem(teamMedium, callback); +}; + +exports.saveTeamMedium = function(teamMedium, callback) { + if (!teamMedium) { + throw new TSArgsError('teamsnap.saveTeamMedium', "`teamMedium` must be provided"); + } + if (!this.isItem(teamMedium, 'teamMedium')) { + throw new TSArgsError('teamsnap.saveTeamMedium', "`type` must be 'teamMedium'"); + } + if (!this.isId(teamMedium.teamId)) { + throw new TSArgsError('teamsnap.saveTeamMedium', 'must include `teamId`'); + } + if (!this.isId(teamMedium.memberId)) { + throw new TSArgsError('teamsnap.saveTeamMedium', 'must include `memberId`'); + } + if (!this.isId(teamMedium.teamMediaGroupId)) { + throw new TSArgsError('teamsnap.saveTeamMedium', 'must include `teamMediaGroupId`'); + } + return this.saveItem(teamMedium, callback); +}; + +exports.saveTeamVideoLink = function(teamMedium, callback) { + if (!teamMedium) { + throw new TSArgsError('teamsnap.createVideoLink', "`teamMedium` must be provided"); + } + if (!this.isItem(teamMedium, 'teamMedium')) { + throw new TSArgsError('teamsnap.createVideoLink', "`type` must be 'teamMedium'"); + } + if (!this.isId(teamMedium.teamId)) { + throw new TSArgsError('teamsnap.createVideoLink', 'must include `teamId`'); + } + if (!this.isId(teamMedium.teamMediaGroupId)) { + throw new TSArgsError('teamsnap.createVideoLink', 'must include `teamMediaGroupId`'); + } + return this.collections.teamMedia.exec('createTeamVideoLink', teamMedium).pop().callback(callback); +}; + +exports.bulkDeleteTeamMedia = function(teamMediumIds, callback) { + var params; + if (!teamMediumIds) { + throw new TSArgsError('teamsnap.bulkDeleteTeamMedia', "`teamMediumIds` must be provided"); + } + params = { + teamMediumIds: teamMediumIds + }; + return this.collections.teamMedia.exec('bulkDeleteTeamMedia', params).callback(callback); +}; + +exports.assignMediaToGroup = function(teamMediumIds, teamMediaGroupId, callback) { + var params; + if (!teamMediumIds) { + throw new TSArgsError('teamsnap.assignMediaToGroup', 'must provide teamMediumIds'); + } + if (this.isItem(teamMediaGroupId, 'teamMediaGroup')) { + teamMediaGroupId = teamMediaGroupId.id; + } + if (!(teamMediaGroupId && this.isId(teamMediaGroupId))) { + throw new TSArgsError('teamsnap.assignMediaToGroup', 'must provide a teamMediaGroupId'); + } + params = { + teamMediumIds: teamMediumIds, + teamMediaGroupId: teamMediaGroupId + }; + return this.collections.teamMedia.exec('assignMediaToGroup', params).callback(callback); +}; + +exports.rotateTeamMediumImage = function(teamMediumId, rotateDirection, callback) { + var params; + if (this.isItem(teamMediumId, 'teamMedium')) { + teamMediumId = teamMediumId.id; + } + if (!(teamMediumId && this.isId(teamMediumId))) { + throw new TSArgsError('teamsnap.rotateTeamMediumImage', 'must provide a teamMediumId'); + } + if (!rotateDirection) { + throw new TSArgsError('teamsnap.rotateTeamMediumImage', 'must provide a rotateDirection'); + } + params = { + teamMediumId: teamMediumId, + rotateDirection: rotateDirection + }; + return this.collections.teamMedia.exec('rotateTeamMediumImage', params).pop().callback(callback); +}; + +exports.setMediumAsTeamPhoto = function(teamMediumId, callback) { + var params; + if (this.isItem(teamMediumId, 'teamMedium')) { + teamMediumId = teamMediumId.id; + } + if (!(teamMediumId && this.isId(teamMediumId))) { + throw new TSArgsError('teamsnap.setMediumAsTeamPhoto', 'must include a teamMediumId'); + } + params = { + teamMediumId: teamMediumId + }; + return this.collections.teamMedia.exec('setMediumAsTeamPhoto', params).pop().callback(callback); +}; + +exports.setMediumAsMemberPhoto = function(teamMediumId, memberId, callback) { + var params; + if (this.isItem(teamMediumId, 'teamMedium')) { + teamMediumId = teamMediumId.id; + } + if (this.isItem(memberId, 'member')) { + memberId = memberId.id; + } + if (!(teamMediumId && this.isId(teamMediumId))) { + throw new TSArgsError('teamsnap.setMediumAsMemberPhoto', 'must include a teamMediumId'); + } + if (!(memberId && this.isId(memberId))) { + throw new TSArgsError('teamsnap.setMediumAsMemberPhoto', 'must include a memberId'); + } + params = { + teamMediumId: teamMediumId, + memberId: memberId + }; + return this.collections.teamMedia.exec('setMediumAsMemberPhoto', params).pop().callback(callback); +}; + +exports.reorderTeamMedia = function(teamId, teamMediaIds, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.reorderTeamMedia', '`teamId` must be provided'); + } + if (!(teamMediaIds && Array.isArray(teamMediaIds))) { + throw new TSArgsError('teamsnap.reorderTeamMedia', 'You must provide an array of ordered Team Medium IDs'); + } + params = { + teamId: teamId, + sortedIds: teamMediaIds + }; + return this.collections.teamMedia.exec('reorderTeamMedia', params).callback(callback); +}; + +exports.facebookShareTeamMedium = function(teamMediumId, facebookPageId, isSuppressedFromFeed, caption, callback) { + var params; + if (typeof facebookPageId === 'boolean') { + callback = caption; + caption = isSuppressedFromFeed; + isSuppressedFromFeed = facebookPageId; + facebookPageId = null; + } + if (typeof caption === 'function') { + callback = caption; + } + if (facebookPageId != null) { + facebookPageId = parseInt(facebookPageId); + } + if (this.isItem(teamMediumId, 'teamMedium')) { + teamMediumId = teamMediumId.id; + } + if (!((isSuppressedFromFeed != null) && typeof isSuppressedFromFeed === 'boolean')) { + throw new TSArgsError('teamsnap.facebookShareMedium', 'must include boolean isSuppressedFromFeed'); + } + params = { + teamMediumId: teamMediumId, + facebookPageId: facebookPageId, + caption: caption, + isSuppressedFromFeed: isSuppressedFromFeed + }; + return this.collections.teamMedia.exec('facebookShareTeamMedium', params).pop().callback(callback); +}; + +}); + +require.register("collections/teamMediaGroups.coffee", function(exports, require, module) { +exports.loadTeamMediaGroups = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamMediaGroups', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamMediaGroup', params, callback); +}; + +exports.createTeamMediaGroup = function(data) { + return this.createItem(data, { + type: 'teamMediaGroup' + }); +}; + +exports.saveTeamMediaGroup = function(teamMediaGroup, callback) { + if (!teamMediaGroup) { + throw new TSArgsError('teamsnap.saveTeamMediaGroup', "`teamMediaGroup` must be provided"); + } + if (!this.isItem(teamMediaGroup, 'teamMediaGroup')) { + throw new TSArgsError('teamsnap.saveTeamMediaGroup', "`teamMediaGroup.type` must be 'teamMediaGroup'"); + } + return this.saveItem(teamMediaGroup, callback); +}; + +exports.deleteTeamMediaGroup = function(teamMediaGroup, callback) { + if (!teamMediaGroup) { + throw new TSArgsError('teamsnap.deleteTeamMediaGroup', '`teamMediaGroup` must be provided'); + } + return this.deleteItem(teamMediaGroup, callback); +}; + +exports.reorderTeamMediaGroups = function(teamId, teamMediaGroupIds, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.reorderTeamMediaGroups', '`teamId` must be provided'); + } + if (!(teamMediaGroupIds && Array.isArray(teamMediaGroupIds))) { + throw new TSArgsError('teamsnap.reorderTeamMediaGroups', 'You must provide an array of ordered Team Media Group IDs'); + } + params = { + teamId: teamId, + sortedIds: teamMediaGroupIds + }; + return this.collections.teamMediaGroups.exec('reorderTeamMediaGroups', params).callback(callback); +}; + +exports.facebookShareTeamMediaGroup = function(teamMediaGroupId, facebookPageId, isSuppressedFromFeed, albumName, callback) { + var params; + if (typeof facebookPageId === 'boolean') { + callback = albumName; + albumName = isSuppressedFromFeed; + isSuppressedFromFeed = facebookPageId; + facebookPageId = null; + } + if (typeof albumName === 'function') { + callback = albumName; + } + if (facebookPageId != null) { + facebookPageId = parseInt(facebookPageId); + } + if (this.isItem(teamMediaGroupId, 'teamMedium')) { + teamMediaGroupId = teamMediaGroup.id; + } + if (!((isSuppressedFromFeed != null) && typeof isSuppressedFromFeed === 'boolean')) { + throw new TSArgsError('teamsnap.facebookShareMediaGroup', 'must include boolean isSuppressedFromFeed'); + } + params = { + teamMediaGroupId: teamMediaGroupId, + facebookPageId: facebookPageId, + albumName: albumName, + isSuppressedFromFeed: isSuppressedFromFeed + }; + return this.collections.teamMediaGroups.exec('facebookShareTeamMediaGroup', params).pop().callback(callback); +}; + +}); + +require.register("collections/teamMediumComments.coffee", function(exports, require, module) { +exports.loadTeamMediumComments = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamMediumComments', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamMediumComment', params, callback); +}; + +exports.createTeamMediumComment = function(data) { + return this.createItem(data, { + type: 'teamMediumComment' + }); +}; + +exports.saveTeamMediumComment = function(teamMediumComment, callback) { + if (!teamMediumComment) { + throw new TSArgsError('teamsnap.saveTeamMediumComment', '`teamMediumComment` must be provided'); + } + if (!this.isItem(teamMediumComment, 'teamMediumComment')) { + throw new TSArgsError('teamsnap.saveTeamMediumComment', "`teamMediumComment.type` must be 'teamMediumComment'"); + } + return this.saveItem(teamMediumComment, callback); +}; + +exports.deleteTeamMediumComment = function(teamMediumComment, callback) { + if (!teamMediumComment) { + throw new TSArgsError('teamsnap.deleteTeamMediumComment', '`teamMediumComment` must be provided'); + } + return this.deleteItem(teamMediumComment, callback); +}; + +}); + +require.register("collections/teamPhotos.coffee", function(exports, require, module) { +exports.loadTeamPhotos = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPhotos', 'must provide a `teamId` or query parameters'); + } + return this.loadItems('teamPhoto', params, callback); +}; + +exports.loadTeamPhoto = function(params, callback) { + if (this.isId(params)) { + params = { + id: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPhoto', 'must provide an `id` or query parameters'); + } + return this.loadItem('teamPhoto', params, callback); +}; + +}); + +require.register("collections/teamPublicSites.coffee", function(exports, require, module) { +exports.loadTeamPublicSites = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPublicSites', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamPublicSite', params, callback); +}; + +exports.loadTeamPublicSite = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPublicSite', 'must provide a teamId or query parameters'); + } + return this.loadItem('teamPublicSite', params, callback); +}; + +exports.saveTeamPublicSite = function(teamPublicSite, callback) { + if (!teamPublicSite) { + throw new TSArgsError('teamsnap.saveTeamPublicSite', "`teamPublicSite` must be provided"); + } + if (!this.isItem(teamPublicSite, 'teamPublicSite')) { + throw new TSArgsError('teamsnap.saveTeamPublicSite', "`teamPublicSite.type` must be 'teamPublicSite'"); + } + return this.saveItem(teamPublicSite, callback); +}; + +exports.uploadTeamPublicPhoto = function(teamPublicSiteId, file, callback) { + var params; + if (this.isItem(teamPublicSiteId, 'teamPublicSite')) { + teamPublicSiteId = teamPublicSite.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(teamPublicSiteId)) { + throw new TSArgsError('teamsnap.uploadTeamPublicPhoto', 'must include `teamPublicSiteId`'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadTeamPublicPhoto', 'must include `file` as type File'); + } + params = { + teamPublicSiteId: teamPublicSiteId, + file: file + }; + return this.collections.teamPublicSites.exec('uploadTeamPublicPhoto', params).pop().callback(callback); +}; + +exports.deleteTeamPublicPhoto = function(teamPublicSiteId, callback) { + var params; + if (!teamPublicSiteId) { + throw new TSArgsError('teamsnap.deleteTeamPublicPhoto', "`teamPublicSiteId` must be provided"); + } + if (this.isItem(teamPublicSiteId, 'teamPublicSite')) { + teamPublicSiteId = teamPublicSite.id; + } + if (!this.isId(teamPublicSiteId)) { + throw new TSArgsError('teamsnap.deleteTeamPublicPhoto', "`teamPublicSiteId` must be a valid id"); + } + params = { + teamPublicSiteId: teamPublicSiteId + }; + return this.collections.teamPublicSites.exec('removeTeamPublicPhoto', params).callback(callback); +}; + +exports.validateSubdomain = function(subdomain, callback) { + var params; + if (!subdomain) { + throw new TSArgsError('teamsnap.validateSubdomain', "`subdomain` must be provided"); + } + params = { + subdomain: subdomain + }; + return this.collections.teamPublicSites.exec('validateSubdomain', params).callback(callback); +}; + +}); + +require.register("collections/teamStatistics.coffee", function(exports, require, module) { +exports.loadTeamStatistics = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamStatistics', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamStatistic', params, callback); +}; + +}); + +require.register("collections/teams.coffee", function(exports, require, module) { +var cleanArray; + +exports.loadTeams = function(params, callback) { + if (params == null) { + params = {}; + } + if (typeof params === 'function') { + callback = params; + params = {}; + } + if (Object.keys(params).length) { + return this.loadItems('team', params, callback); + } else { + return this.loadMe().then((function(_this) { + return function(me) { + params.userId = me.id; + return _this.loadItems('team', params, callback); + }; + })(this)); + } +}; + +exports.loadTeam = function(teamId, callback) { + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.loadTeam', 'teamId must be provided'); + } + return this.loadItem('team', { + teamId: teamId + }, callback); +}; + +exports.createTeam = function(data) { + return this.createItem(data, { + type: 'team', + name: '' + }); +}; + +exports.saveTeam = function(team, callback) { + var ref; + if (!team) { + throw new TSArgsError('teamsnap.saveTeam', "`team` must be provided"); + } + if (!this.isItem(team, 'team')) { + throw new TSArgsError('teamsnap.saveTeam', "`type` must be 'team'"); + } + if (!((ref = team.name) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a name for the team.', 'name', callback); + } + return this.saveItem(team, callback); +}; + +exports.deleteTeam = function(team, callback) { + if (!team) { + throw new TSArgsError('teamsnap.deleteTeam', '`team` must be provided'); + } + return this.deleteItem(team, callback); +}; + +exports.bulkLoad = function(teamId, types, callback) { + var key, loadParams, params, value; + if (typeof teamId === 'object' && !Array.isArray(teamId)) { + loadParams = teamId; + teamId = loadParams.teamId; + types = loadParams.types; + } + if (!(this.isId(teamId) || (Array.isArray(teamId) && this.isId(teamId[0])))) { + throw new TSArgsError('teamsnap.bulkLoad', 'teamId must be provided'); + if (typeof types === 'function') { + callback = types; + types = null; + } + } + if (!Array.isArray(types)) { + types = this.getTeamTypes(); + types.splice(types.indexOf('availability'), 1); + } + params = { + teamId: teamId, + types: types.map(this.underscoreType).join(',') + }; + if (loadParams != null) { + if (loadParams.scopeTo != null) { + params.scopeTo = this.underscoreType(loadParams.scopeTo); + } + for (key in loadParams) { + value = loadParams[key]; + if (key.indexOf('__') !== -1) { + params[key] = value; + } + } + } + return this.collections.root.queryItems('bulkLoad', params, callback); +}; + +exports.invite = function(options) { + if (options == null) { + options = {}; + } + cleanArray(options, 'memberId'); + cleanArray(options, 'contactId'); + if (!(options.memberId || options.contactId)) { + throw new TSArgsError('teamsnap.invite', 'options.memberId or options.contactId is required.'); + } + if (!options.teamId) { + throw new TSArgsError('teamsnap.invite', 'options.teamId is required.'); + } + if (!options.notifyAsMemberId) { + throw new TSArgsError('teamsnap.invite', 'options.notifyAsMemberId is required.'); + } + return this.collections.teams.exec('invite', options); +}; + +exports.updateTimeZone = function(options) { + if (options == null) { + options = {}; + } + if (!options.timeZone) { + throw new TSArgsError('teamsnap.updateTimeZone', 'options.timeZone is required.'); + } + if (!options.teamId) { + throw new TSArgsError('teamsnap.updateTimeZone', 'options.teamId is required.'); + } + if (!options.offsetTeamTimes) { + throw new TSArgsError('teamsnap.updateTimeZone', 'options.offsetTeamTimes is required'); + } + return this.collections.teams.exec('updateTimeZone', options); +}; + +exports.resetStatistics = function(teamId, callback) { + var params; + if (!teamId) { + throw new TSArgsError('teamsnap.resetStatistics', "`teamId` must be provided"); + } + if (this.isItem(teamId, 'teamId')) { + teamId = teamId.id; + } + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.resetStatistics', "`teamId` must be a valid id"); + } + params = { + teamId: teamId + }; + return this.collections.teams.exec('resetStatistics', params).callback(callback); +}; + +exports.divisionLoadTeams = function(params, callback) { + if (!params.divisionId) { + throw new TSArgsError('teamsnap.divisionLoadTeams', "`divisionId` must be provided"); + } + return this.collections.teams.queryItems('divisionSearch', params, callback); +}; + +cleanArray = function(obj, prop) { + var plural; + plural = prop + 's'; + if (obj[plural]) { + obj[prop] = obj[plural]; + delete obj[plural]; + } + if ((obj[prop] != null) && !Array.isArray(obj[prop])) { + obj[prop] = [obj[prop]]; + } + return obj; +}; + +}); + +require.register("collections/teamsPaypalPreferences.coffee", function(exports, require, module) { +exports.loadTeamsPaypalPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamsPaypalPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamPaypalPreferences', params, callback); +}; + +exports.loadTeamPaypalPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPaypalPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItem('teamPaypalPreferences', params, callback); +}; + +exports.saveTeamPaypalPreferences = function(teamPaypalPreferences, callback) { + if (!teamPaypalPreferences) { + throw new TSArgsError('teamsnap.saveTeamPaypalPreferences', "`teamPaypalPreferences` must be provided"); + } + if (!this.isItem(teamPaypalPreferences, 'teamPaypalPreferences')) { + throw new TSArgsError('teamsnap.saveTeamPaypalPreferences', "`teamPaypalPreferences.type` must be 'teamPaypalPreferences'"); + } + return this.saveItem(teamPaypalPreferences, callback); +}; + +}); + +require.register("collections/teamsPreferences.coffee", function(exports, require, module) { +exports.ASSIGNMENTS_ENABLED_FOR_CODE = { + GamesAndEvents: 0, + Games: 1, + Events: 2 +}; + +exports.loadTeamsPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItems('teamPreferences', params, callback); +}; + +exports.loadTeamPreferences = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamPreferences', 'must provide a teamId or query parameters'); + } + return this.loadItem('teamPreferences', params, callback); +}; + +exports.saveTeamPreferences = function(teamPreferences, callback) { + if (!teamPreferences) { + throw new TSArgsError('teamsnap.saveTeamPreferences', "`teamPreferences` must be provided"); + } + if (!this.isItem(teamPreferences, 'teamPreferences')) { + throw new TSArgsError('teamsnap.saveTeamPreferences', "`teamPreferences.type` must be 'teamPreferences'"); + } + return this.saveItem(teamPreferences, callback); +}; + +exports.uploadTeamPhoto = function(teamPreferencesId, file, callback) { + var params; + if (this.isItem(teamPreferencesId, 'teamPreferences')) { + teamPreferencesId = teamPreferencesId.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(teamPreferencesId)) { + throw new TSArgsError('teamsnap.uploadTeamPhoto', 'must include `teamPreferencesId`'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadTeamPhoto', 'must include `file` as type File'); + } + params = { + teamPreferencesId: teamPreferencesId, + file: file + }; + return this.collections.teamsPreferences.exec('uploadTeamPhoto', params).pop().callback(callback); +}; + +exports.deleteTeamPhoto = function(teamPreferencesId, callback) { + var params; + if (!teamPreferencesId) { + throw new TSArgsError('teamsnap.deleteTeamPhoto', "`teamPreferencesId` must be provided"); + } + if (this.isItem(teamPreferencesId, 'teamPreferences')) { + teamPreferencesId = teamPreferences.id; + } + if (!this.isId(teamPreferencesId)) { + throw new TSArgsError('teamsnap.deleteTeamPhoto', "`teamPreferencesId` must be a valid id"); + } + params = { + teamPreferencesId: teamPreferencesId + }; + return this.collections.teamsPreferences.exec('removeTeamPhoto', params).callback(callback); +}; + +exports.uploadTeamLogo = function(teamPreferencesId, file, callback) { + var params; + if (this.isItem(teamPreferencesId, 'teamPreferences')) { + teamPreferencesId = teamPreferences.id; + } + if (typeof FormData === 'undefined') { + this.reject('Your browser does not support the new file upload APIs.', 'file', callback); + } + if (!this.isId(teamPreferencesId)) { + throw new TSArgsError('teamsnap.uploadTeamLogo', 'must include `teamPreferencesId`'); + } + if (!(file instanceof File)) { + throw new TSArgsError('teamsnap.uploadTeamLogo', 'must include `file` as type File'); + } + params = { + teamPreferencesId: teamPreferencesId, + file: file + }; + return this.collections.teamsPreferences.exec('uploadTeamLogo', params).pop().callback(callback); +}; + +exports.deleteTeamLogo = function(teamPreferencesId, callback) { + var params; + if (!teamPreferencesId) { + throw new TSArgsError('teamsnap.deleteTeamLogo', "`teamPreferencesId` must be provided"); + } + if (this.isItem(teamPreferencesId, 'teamPreferences')) { + teamPreferencesId = teamPreferences.id; + } + if (!this.isId(teamPreferencesId)) { + throw new TSArgsError('teamsnap.deleteTeamLogo', "`teamPreferencesId` must be a valid id"); + } + params = { + teamPreferencesId: teamPreferencesId + }; + return this.collections.teamsPreferences.exec('removeTeamLogo', params).callback(callback); +}; + +}); + +require.register("collections/teamsResults.coffee", function(exports, require, module) { +exports.loadTeamsResults = function(params, callback) { + if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTeamsResults', 'must provide query parameters'); + } + return this.loadItems('teamResults', params, callback); +}; + +exports.loadTeamResults = function(teamId, callback) { + var params; + if (!this.isId(teamId)) { + throw new TSArgsError('teamsnap.loadTeamResults', 'must provide a teamId'); + } + params = { + teamId: teamId + }; + return this.loadItem('teamResults', params, callback); +}; + +}); + +require.register("collections/trackedItemStatuses.coffee", function(exports, require, module) { +var key, ref, statuses, value; + +exports.TRACKING = { + NONE: 0, + CHECK: 1, + X: 2 +}; + +statuses = {}; + +ref = exports.TRACKING; +for (key in ref) { + value = ref[key]; + statuses[value] = true; +} + +exports.loadTrackedItemStatuses = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTrackedItemStatuses', 'must provide a teamId or query parameters'); + } + return this.loadItems('trackedItemStatus', params, callback); +}; + +exports.saveTrackedItemStatus = function(trackedItemStatus, callback) { + if (!trackedItemStatus) { + throw new TSArgsError('teamsnap.saveTrackedItemStatus', "`trackedItemStatus` must be provided"); + } + if (!this.isItem(trackedItemStatus, 'trackedItemStatus')) { + throw new TSArgsError('teamsnap.saveTrackedItemStatus', "`trackedItemStatus.type` must be 'trackedItemStatus'"); + } + if (!statuses[trackedItemStatus.statusCode]) { + return this.reject('You must select a valid status', 'statusCode', callback); + } + return this.saveItem(trackedItemStatus, callback); +}; + +}); + +require.register("collections/trackedItems.coffee", function(exports, require, module) { +exports.loadTrackedItems = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadTrackedItems', 'must provide a teamId or query parameters'); + } + return this.loadItems('trackedItem', params, callback); +}; + +exports.createTrackedItem = function(data) { + return this.createItem(data, { + type: 'trackedItem', + name: '' + }); +}; + +exports.saveTrackedItem = function(trackedItem, callback) { + var ref; + if (!trackedItem) { + throw new TSArgsError('teamsnap.saveTrackedItem', "`trackedItem` must be provided"); + } + if (!this.isItem(trackedItem, 'trackedItem')) { + throw new TSArgsError('teamsnap.saveTrackedItem', "`trackedItem.type` must be 'trackedItem'"); + } + if (!trackedItem.teamId) { + return this.reject('You must choose a team.', 'teamId', callback); + } + if (!((ref = trackedItem.name) != null ? ref.trim() : void 0)) { + return this.reject('You must provide a name for the tracked item.', 'name', callback); + } + return this.saveItem(trackedItem, callback); +}; + +exports.deleteTrackedItem = function(trackedItem, callback) { + if (!trackedItem) { + throw new TSArgsError('teamsnap.deleteTrackedItem', '`trackedItem` must be provided'); + } + return this.deleteItem(trackedItem, callback); +}; + +}); + +require.register("collections/users.coffee", function(exports, require, module) { +exports.loadUsers = function(params, callback) { + if (this.isId(params)) { + params = { + teamId: params + }; + } else if (!(params && typeof params === 'object')) { + throw new TSArgsError('teamsnap.loadUsers', 'must provide a teamId or query parameters'); + } + return this.loadItems('user', params, callback); +}; + +exports.loadMe = function(callback) { + return this.collections.root.queryItem('me', callback); +}; + +exports.saveUser = function(user, callback) { + var ref; + if (!user) { + throw new TSArgsError('teamsnap.saveUser', "`user` must be provided"); + } + if (!this.isItem(user, 'user')) { + throw new TSArgsError('teamsnap.saveUser', "`user.type` must be 'user'"); + } + if (!((ref = user.email) != null ? ref.trim() : void 0)) { + return this.reject('You must provide an email for the user.', 'email', callback); + } + return this.saveItem(user, callback); +}; + +}); + +require.register("errors.coffee", function(exports, require, module) { +var TSArgsError, TSError, TSServerError, TSValidationError, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + +TSError = (function(superClass) { + extend(TSError, superClass); + + function TSError(message) { + TSError.__super__.constructor.call(this); + this.name = 'TeamSnapError'; + this.message = message; + } + + return TSError; + +})(Error); + +TSArgsError = (function(superClass) { + extend(TSArgsError, superClass); + + function TSArgsError(method, msg) { + TSArgsError.__super__.constructor.call(this); + this.name = 'TeamSnapArgumentError'; + this.message = "Failed to execute `" + method + "`: " + msg + "."; + } + + return TSArgsError; + +})(TypeError); + +TSValidationError = (function(superClass) { + extend(TSValidationError, superClass); + + function TSValidationError(message, field) { + TSValidationError.__super__.constructor.call(this); + this.name = 'TeamSnapValidationError'; + this.message = message; + this.field = field; + } + + return TSValidationError; + +})(RangeError); + +TSServerError = (function(superClass) { + extend(TSServerError, superClass); + + function TSServerError(message) { + TSServerError.__super__.constructor.call(this); + this.name = 'TeamSnapServerError'; + this.message = message || 'An unknown error occurred on TeamSnap\'s server.'; + } + + TSServerError.create = function(message, jqxhr) { + return new TSServerError(message, jqxhr); + }; + + return TSServerError; + +})(Error); + +global.TSError = TSError; + +global.TSArgsError = TSArgsError; + +global.TSValidationError = TSValidationError; + +global.TSServerError = TSServerError; + +}); + +require.register("linking.coffee", function(exports, require, module) { +var linkItem, linkItemWith, linkItems, types, unlinkItem, unlinkItemFrom, unlinkItems, unlinkItemsFrom; + +types = require('./types'); + +linkItems = function(items, lookup) { + if (lookup == null) { + lookup = {}; + } + if (!items) { + return; + } + if (Array.isArray(items)) { + items.forEach(function(item) { + if (item.href) { + return lookup[item.href] = item; + } + }); + items.forEach(function(item) { + return linkItem(item, lookup); + }); + } else { + if (items.href) { + lookup[items.href] = items; + } + linkItem(items, lookup); + } + return items; +}; + +unlinkItems = function(items, lookup) { + if (lookup == null) { + lookup = {}; + } + if (!items) { + return; + } + if (Array.isArray(items)) { + items.forEach(function(item) { + return unlinkItem(item, lookup); + }); + } else { + unlinkItem(items, lookup); + } + return items; +}; + +linkItem = function(item, lookup) { + if (!lookup) { + throw new TSArgsError('linkItem', 'lookup must be provided'); + } + if (item.href) { + lookup[item.href] = item; + } + return item.links.each(function(rel, href) { + var related; + if (types.isPluralType(rel)) { + if (!item[rel]) { + return item[rel] = []; + } + } else { + if (!(related = lookup[href])) { + return; + } + item[rel] = related; + return linkItemWith(item, related); + } + }); +}; + +linkItemWith = function(item, other) { + var plural; + plural = types.getPluralType(item.type); + if (plural && other.links.has(plural)) { + if (!other[plural]) { + other[plural] = []; + } + if (other[plural].indexOf(item) === -1) { + return other[plural].push(item); + } + } else { + return other.links.each(function(rel, href) { + if (href === item.href) { + return other[rel] = item; + } + }); + } +}; + +unlinkItem = function(item, lookup) { + if (!item.href) { + return; + } + if (lookup[item.href] === item) { + delete lookup[item.href]; + } + return item.links.each(function(rel, href) { + if (!item[rel]) { + return; + } + if (types.isPluralType(rel)) { + unlinkItemsFrom(item[rel], item); + } else { + unlinkItemFrom(item, item[rel]); + } + return delete item[rel]; + }); +}; + +unlinkItemFrom = function(item, other) { + var index, plural; + plural = types.getPluralType(item.type); + if (plural && other.links.has(plural) && other[plural]) { + index = other[plural].indexOf(item); + if (index !== -1) { + return other[plural].splice(index, 1); + } + } else { + return other.links.each(function(rel, href) { + if (other[rel] === item) { + return delete other[rel]; + } + }); + } +}; + +unlinkItemsFrom = function(items, from) { + return items.forEach(function(item) { + return item.links.each(function(rel, href) { + if (item[rel] === from) { + return delete item[rel]; + } + }); + }); +}; + +exports.linkItems = linkItems; + +exports.unlinkItems = unlinkItems; + +exports.linkItem = linkItem; + +exports.linkItemWith = linkItemWith; + +exports.unlinkItem = unlinkItem; + +exports.unlinkItemFrom = unlinkItemFrom; + +exports.unlinkItemsFrom = unlinkItemsFrom; + +}); + +require.register("loadCollections.coffee", function(exports, require, module) { +var Collection, collectionsPromise, promises, types, + hasProp = {}.hasOwnProperty; + +promises = require('./promises'); + +types = require('./types'); + +Collection = require('./model').Collection; + +collectionsPromise = null; + +module.exports = function(request, cachedCollections) { + if (!collectionsPromise || collectionsPromise.getStatus() === 'reject') { + collectionsPromise = request.get(teamsnap.apiUrl).then(function(xhr) { + var collections, key, loads, ref, ref1, ref2, ref3, root, rootTypeToRels, value; + collections = {}; + collections.root = root = Collection.fromData(xhr.data); + if (cachedCollections && cachedCollections.root.version === root.version) { + collections = {}; + for (key in cachedCollections) { + value = cachedCollections[key]; + collections[key] = new Collection(value); + } + return collectionsPromise = promises.resolve(collections); + } else { + rootTypeToRels = {}; + loads = []; + ref = collections.root.links; + for (key in ref) { + if (!hasProp.call(ref, key)) continue; + value = ref[key]; + rootTypeToRels[value.href] = key; + } + if ((ref1 = collections.root) != null ? (ref2 = ref1.links) != null ? (ref3 = ref2.schemas) != null ? ref3.href : void 0 : void 0 : void 0) { + loads.push(request.get(collections.root.links.schemas.href).then(function(xhr) { + return xhr.data.forEach(function(collection) { + var rel; + rel = rootTypeToRels[collection.collection.href]; + if (rel && rel !== "root") { + return collections[rel] = Collection.fromData(collection); + } + }); + })); + } else { + types.getTypes().forEach(function(type) { + var rel; + rel = types.getPluralType(type); + if (root.links.has(rel)) { + return loads.push(request.get(root.links.href(rel)).then(function(xhr) { + return collections[rel] = Collection.fromData(xhr.data); + })); + } + }); + } + return promises.when.apply(promises, loads).then(function() { + return collections; + }); + } + }); + } + return collectionsPromise; +}; + +module.exports.clear = function() { + return collectionsPromise = null; +}; + +}); + +require.register("model.coffee", function(exports, require, module) { +var Collection, File, Item, MetaList, ScopedCollection, camelize, copy, dateField, dateValue, promises, underscore, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + +promises = require('./promises'); + +File = global.File || function() {}; + +Collection = (function() { + Collection.fromData = function(data) { + return new Collection().deserialize(data); + }; + + function Collection(data) { + if (data == null) { + data = {}; + } + this.href = data.href; + this.links = new MetaList(data.links); + this.queries = new MetaList(data.queries); + this.commands = new MetaList(data.commands); + this.template = data.template || []; + if (data.version) { + this.version = data.version; + } + if (data.items) { + this.items = data.items; + } + } + + Collection.prototype.deserialize = function(data) { + var ref, ref1; + if (data.collection) { + data = data.collection; + } + if (!data) { + return; + } + this.href = data.href; + this.links.deserialize(data.links); + this.queries.deserialize(data.queries); + this.commands.deserialize(data.commands); + if (data.version) { + this.version = data.version; + } + this.template = ((ref = data.template) != null ? ref.data : void 0) || []; + if ((ref1 = data.items) != null ? ref1.length : void 0) { + this.items = data.items; + } + return this; + }; + + return Collection; + +})(); + +ScopedCollection = (function(superClass) { + extend(ScopedCollection, superClass); + + ScopedCollection.fromData = function(request, data) { + return new ScopedCollection(request, new Collection().deserialize(data)); + }; + + function ScopedCollection(_request, collection) { + this._request = _request; + this.href = collection.href; + this.links = collection.links; + this.queries = collection.queries; + this.commands = collection.commands; + this.template = collection.template; + this.version = collection.version; + if (collection.items) { + this.items = Item.fromArray(this._request, collection.items); + } + } + + ScopedCollection.prototype.save = function(item, callback) { + var data, method; + if (!(item instanceof Item)) { + item = Item.create(this._request, item); + } + method = item.href ? 'put' : 'post'; + data = item.serialize(this.template); + if (data.template.data.length === 0) { + return promises.resolve(item).callback(callback); + } + return this._request(method, item.href || this.href, data).then((function(_this) { + return function(xhr) { + var all, items, ref, ref1; + if ((items = (ref = xhr.data) != null ? (ref1 = ref.collection) != null ? ref1.items : void 0 : void 0)) { + if (items.length > 1) { + item.deserialize(items.shift()); + all = Item.fromArray(_this._request, items); + all.unshift(item); + return all; + } else if (items.length) { + return item.deserialize(xhr.data); + } + } + }; + })(this)).callback(callback); + }; + + ScopedCollection.prototype.loadItems = function(linkName, callback) { + return this.links.loadItems(this._request, linkName, callback); + }; + + ScopedCollection.prototype.loadItem = function(linkName, callback) { + return this.links.loadItem(this._request, linkName, callback); + }; + + ScopedCollection.prototype.queryItems = function(queryName, params, callback) { + return this.queries.loadItems(this._request, queryName, params, callback); + }; + + ScopedCollection.prototype.queryItem = function(queryName, params, callback) { + return this.queries.loadItem(this._request, queryName, params, callback); + }; + + ScopedCollection.prototype.exec = function(commandName, params, callback) { + return this.commands.exec(this._request, commandName, params, callback); + }; + + ScopedCollection.prototype.file = function(commandName, params, progress, callback) { + return this.commands.fileExec(this._request, commandName, params, progress, callback); + }; + + return ScopedCollection; + +})(Collection); + +Item = (function() { + Item.create = function(request, data) { + return new Item(request, data); + }; + + Item.fromArray = function(request, array) { + if (Array.isArray(array)) { + return array.map(function(data) { + return Item.fromData(request, data); + }); + } else { + return array; + } + }; + + Item.fromData = function(request, data) { + if (data.collection || data.data) { + return this.create(request).deserialize(data); + } else { + return this.create(request, data); + } + }; + + function Item(_request, data) { + this._request = _request; + if (typeof data === 'string') { + this.href = data; + } else if (data && typeof data === 'object') { + copy(data, this); + } + if (!(this.links instanceof MetaList)) { + this.links = new MetaList(data != null ? data.links : void 0); + } + } + + Item.prototype.deserialize = function(data) { + var i, len, prop, ref, ref1, value; + if (data != null ? data.collection : void 0) { + data = (ref = data.collection.items) != null ? ref[0] : void 0; + } + if (!data) { + return; + } + this.href = data.href; + this.links.deserialize(data.links); + ref1 = data.data; + for (i = 0, len = ref1.length; i < len; i++) { + prop = ref1[i]; + value = prop.value; + if (prop.type === 'DateTime' && value) { + value = new Date(value); + } + if (prop.name === 'type') { + value = camelize(value); + } + this[camelize(prop.name)] = value; + } + return this; + }; + + Item.prototype.serialize = function(template) { + var fields, item; + if (!(template != null ? template.length : void 0)) { + throw new TSError('You must provide the collection\'s template'); + } + fields = []; + item = this; + template.forEach(function(prop) { + var value; + value = item[camelize(prop.name)]; + if (prop.name === 'type') { + value = underscore(value); + } + if (value !== void 0) { + return fields.push({ + name: prop.name, + value: value + }); + } + }); + return { + template: { + data: fields + } + }; + }; + + Item.prototype.loadItems = function(linkName, callback) { + return this.links.loadItems(this._request, linkName, callback); + }; + + Item.prototype.loadItem = function(linkName, callback) { + return this.links.loadItem(this._request, linkName, callback); + }; + + Item.prototype["delete"] = function(params, callback) { + var data, fields, key, value; + if (typeof params === 'function') { + callback = params; + params = null; + } + if (params) { + fields = []; + for (key in params) { + if (!hasProp.call(params, key)) continue; + value = params[key]; + fields.push({ + name: underscore(key), + value: value + }); + } + data = { + template: { + data: fields + } + }; + } + return this._request["delete"](this.href, data).callback(callback); + }; + + Item.prototype.copy = function(template) { + var obj; + obj = {}; + if (template) { + template.forEach((function(_this) { + return function(prop) { + var camel; + camel = camelize(prop.name); + return obj[camel] = _this[camel]; + }; + })(this)); + } else { + copy(this, obj); + } + delete obj.id; + delete obj.href; + obj.type = this.type; + obj.links = this.links.cloneEmpty(); + return new Item(this._request, obj); + }; + + Item.prototype.toJSON = function() { + var obj; + obj = {}; + Object.keys(this).forEach((function(_this) { + return function(key) { + var value; + value = _this[key]; + if (typeof value === 'function' || key.charAt(0) === '_' || _this.links.has(key)) { + return; + } + return obj[key] = _this[key]; + }; + })(this)); + return obj; + }; + + return Item; + +})(); + +MetaList = (function() { + function MetaList(data) { + if (data) { + copy(data, this); + } + } + + MetaList.prototype.deserialize = function(data) { + var entry, i, j, len, len1, link, linksToRemove, param, params, propName, ref, results; + if (!Array.isArray(data)) { + return; + } + linksToRemove = {}; + Object.keys(this).forEach(function(link) { + return linksToRemove[link] = true; + }); + for (i = 0, len = data.length; i < len; i++) { + entry = data[i]; + params = {}; + if (Array.isArray(entry.data)) { + ref = entry.data; + for (j = 0, len1 = ref.length; j < len1; j++) { + param = ref[j]; + params[camelize(param.name)] = param.value; + } + } + propName = camelize(entry.rel); + this[propName] = { + href: entry.href, + params: params + }; + delete linksToRemove[propName]; + } + results = []; + for (link in linksToRemove) { + results.push(delete this[link]); + } + return results; + }; + + MetaList.prototype.has = function(rel) { + return this.hasOwnProperty(rel); + }; + + MetaList.prototype.href = function(rel) { + var ref; + return (ref = this[rel]) != null ? ref.href : void 0; + }; + + MetaList.prototype.each = function(iterator) { + var entry, ref, rel, results; + ref = this; + results = []; + for (rel in ref) { + if (!hasProp.call(ref, rel)) continue; + entry = ref[rel]; + results.push(iterator(rel, entry.href, entry.params)); + } + return results; + }; + + MetaList.prototype.loadItems = function(request, rel, params, callback) { + if (typeof params === 'function') { + callback = params; + params = void 0; + } + return this._request(request, 'get', rel, params, 'items').callback(callback); + }; + + MetaList.prototype.loadItem = function(request, rel, params, callback) { + if (typeof params === 'function') { + callback = params; + params = void 0; + } + return this._request(request, 'get', rel, params, 'item').callback(callback); + }; + + MetaList.prototype["delete"] = function(request, rel, callback) { + return this._request(request, 'delete', rel, void 0, 'item').callback(callback); + }; + + MetaList.prototype.exec = function(request, rel, params, callback) { + if (typeof params === 'function') { + callback = params; + params = void 0; + } + return this._request(request, 'post', rel, params, 'items').callback(callback); + }; + + MetaList.prototype.fileExec = function(request, rel, params, progress, callback) { + var progressHook; + if (typeof params === 'function') { + callback = progress; + progress = params; + params = void 0; + } + progressHook = function(xhr, data) { + if (data instanceof FormData) { + return xhr.upload.onprogress = function(e) { + if (e.lengthComputable) { + return progress({ + loaded: e.loaded, + total: e.total + }); + } + }; + } + }; + request.hook(progressHook); + return this._request(request, 'post', rel, params, 'items').callback(callback); + }; + + MetaList.prototype.cloneEmpty = function() { + var clone, entry, ref, rel; + clone = new MetaList(); + ref = this; + for (rel in ref) { + if (!hasProp.call(ref, rel)) continue; + entry = ref[rel]; + if (entry.href) { + clone[rel] = { + href: '' + }; + } + } + return clone; + }; + + MetaList.prototype._request = function(request, method, rel, params, type) { + var data, entry, filteredOn, itemCollection, key, value; + if (!(entry = this[rel])) { + throw new TSError("Unable to find rel '" + rel + "'"); + } + if (params) { + data = {}; + for (key in params) { + if (!hasProp.call(params, key)) continue; + value = params[key]; + if (value instanceof File) { + data = new FormData(); + for (key in params) { + if (!hasProp.call(params, key)) continue; + value = params[key]; + data.append(underscore(key), value); + } + break; + } + if (entry.params.hasOwnProperty(key)) { + data[underscore(key)] = value; + } else if (key.indexOf('__') !== -1) { + filteredOn = key.split('__'); + itemCollection = teamsnap.getCollectionForItem(filteredOn[0]); + if (itemCollection.queries.search.params.hasOwnProperty(filteredOn[1])) { + data[underscore(key)] = value; + } + } + } + } + return request(method, entry.href, data).then(function(xhr) { + var items, ref, ref1; + items = ((ref = xhr.data) != null ? (ref1 = ref.collection) != null ? ref1.items : void 0 : void 0) ? Item.fromArray(request, xhr.data.collection.items) : []; + if (type === 'item') { + return items.pop(); + } else { + return items; + } + }); + }; + + return MetaList; + +})(); + +dateField = /(At|Date)$/; + +dateValue = /^\d{4}-/; + +copy = function(from, to) { + Object.keys(from).forEach(function(key) { + var value; + value = from[key]; + if (typeof value === 'function' || key.charAt(0) === '_') { + return; + } + if (dateField.test(key) && dateValue.test(value)) { + value = new Date(value); + } + return to[key] = value; + }); + return to; +}; + +camelize = function(str) { + return str.replace(/[-_]+(\w)/g, function(_, char) { + return char.toUpperCase(); + }); +}; + +underscore = function(str) { + return str.replace(/[A-Z]/g, function(char) { + return '_' + char.toLowerCase(); + }); +}; + +exports.Collection = Collection; + +exports.ScopedCollection = ScopedCollection; + +exports.Item = Item; + +exports.MetaList = MetaList; + +}); + +require.register("persistence.coffee", function(exports, require, module) { +var Item, MetaList, ScopedCollection, camelize, copy, linking, lookup, modifyModel, modifySDK, promises, ref, revertModel, revertSDK, revertWrapMethod, types, wrapMethod, wrapSave, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + +promises = require('./promises'); + +linking = require('./linking'); + +types = require('./types'); + +Item = require('./model').Item; + +ref = require('./model'), ScopedCollection = ref.ScopedCollection, Item = ref.Item, MetaList = ref.MetaList; + +lookup = null; + +exports.enablePersistence = function(cachedItemData) { + var initialItems; + if (lookup) { + return; + } + if (!this.collections) { + throw new TSError('You must auth() and loadCollections() before enabling persistence.'); + } + this.persistenceEnabled = true; + lookup = {}; + modifyModel(); + modifySDK(this); + initialItems = []; + initialItems.push.apply(initialItems, this.plans); + initialItems.push.apply(initialItems, this.smsGateways); + initialItems.push.apply(initialItems, this.sports); + initialItems.push.apply(initialItems, this.timeZones); + linking.linkItems(this.plans.concat(this.sports), lookup); + if (cachedItemData) { + return Item.fromArray(this.request, cachedItemData); + } +}; + +exports.disablePersistence = function() { + if (!lookup) { + return; + } + this.persistenceEnabled = false; + linking.unlinkItems(Object.keys(lookup).map(function(href) { + return lookup[href]; + }), lookup); + lookup = null; + revertModel(); + revertSDK(this); + return this; +}; + +exports.findItem = function(href) { + return lookup != null ? lookup[href] : void 0; +}; + +exports.getAllItems = function() { + return Object.keys(lookup).map(function(href) { + return lookup[href]; + }); +}; + +exports.unlinkTeam = function(team) { + var i, items, len, plural, ref1, ref2, teamType, users, value; + items = [team]; + users = (ref1 = team.members) != null ? ref1.filter(function(member) { + return member.user; + }).map(function(member) { + return member.user; + }) : void 0; + ref2 = this.getTeamTypes(); + for (i = 0, len = ref2.length; i < len; i++) { + teamType = ref2[i]; + plural = this.getPluralType(teamType); + if ((value = team[plural]) && value.length) { + items.push.apply(items, value); + } else if ((value = team[teamType])) { + items.push(value); + } + } + return unlinkItems(items); +}; + +modifyModel = function() { + wrapMethod(Item, 'fromArray', function(fromArray) { + return function(request, array) { + var items; + items = fromArray.call(this, request, array); + return linking.linkItems(items, lookup).map(function(item) { + return item.saveState(); + }); + }; + }); + wrapMethod(ScopedCollection.prototype, 'save', function(save) { + return function(item, callback) { + return save.call(this, item).then(function(item) { + if (Array.isArray(item)) { + return item.map(function(item) { + linking.linkItem(item, lookup); + return item.saveState(); + }); + } else { + linking.linkItem(item, lookup); + return item.saveState(); + } + }).callback(callback); + }; + }); + wrapMethod(Item.prototype, 'delete', function(deleteItem) { + return function(params, callback) { + var item; + item = this; + linking.unlinkItem(item, lookup); + return deleteItem.call(this, params).fail(function(err) { + linking.linkItem(item, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(Item, 'create', function(create) { + return function(request, data) { + var item; + item = create.call(this, request, data); + linking.linkItem(item, lookup); + return item; + }; + }); + wrapMethod(Item.prototype, 'deserialize', function(deserialize) { + return function(data) { + var item, ref1; + if (data != null ? data.collection : void 0) { + data = (ref1 = data.collection.items) != null ? ref1[0] : void 0; + } + item = lookup[data.href] || this; + return deserialize.call(item, data); + }; + }); + wrapMethod(Item.prototype, 'serialize', function(serialize) { + return function(template) { + var body, state; + body = serialize.call(this, template); + if ((state = this._state)) { + body.template.data = body.template.data.filter(function(field) { + var isSame, oldValue, value; + oldValue = state[camelize(field.name)]; + value = field.value; + if (field.name === 'type') { + value = camelize(value); + } + isSame = value === oldValue || (value && oldValue && value.valueOf() === oldValue.valueOf()); + return !isSame; + }); + } + return body; + }; + }); + Item.prototype.saveState = function() { + this._state = { + _undos: [] + }; + if (this.href) { + copy(this, this._state); + } + return this; + }; + Item.prototype.rollback = function() { + this._state._undos.reverse().forEach(function(undo) { + return undo(); + }); + this._state._undos.length = 0; + return copy(this._state, this); + }; + return Item.prototype.link = function(rel, item) { + var related, undos; + if (!this._state) { + this.saveState(); + } + undos = this._state._undos; + if (this[rel]) { + related = this[rel]; + linking.unlinkItemFrom(this, this[rel]); + undos.push((function(_this) { + return function() { + _this[rel] = related; + _this.links[rel].href = related.href; + _this[rel + 'Id'] = related.id; + return linking.linkItemWith(_this, related); + }; + })(this)); + } + this[rel] = item; + if (item) { + this[rel + 'Id'] = item.id; + this.links[rel].href = item.href; + linking.linkItemWith(this, item); + undos.push((function(_this) { + return function() { + delete _this[rel]; + delete _this[rel + 'Id']; + return linking.unlinkItemFrom(_this, item); + }; + })(this)); + } + return this; + }; +}; + +revertModel = function() { + revertWrapMethod(MetaList.prototype, '_request'); + revertWrapMethod(ScopedCollection.prototype, 'save'); + revertWrapMethod(Item.prototype, 'delete'); + revertWrapMethod(Item, 'create'); + revertWrapMethod(Item.prototype, 'deserialize'); + revertWrapMethod(Item.prototype, 'serialize'); + delete Item.prototype.saveState; + delete Item.prototype.rollback; + return delete Item.prototype.link; +}; + +modifySDK = function(sdk) { + wrapSave(sdk, 'saveMember', function(member) { + return promises.when(sdk.loadAvailabilities({ + memberId: member.id + }), sdk.loadTrackedItemStatuses({ + memberId: member.id + }), sdk.loadCustomData({ + memberId: member.id + }), sdk.loadLeagueCustomData({ + memberId: member.id + }), sdk.loadMemberPayments({ + memberId: member.id + }), sdk.loadMemberBalances({ + memberId: member.id + }), sdk.loadTeamFees({ + teamId: member.teamId + })); + }); + wrapMethod(sdk, 'deleteMember', function(deleteMember) { + return function(member, callback) { + var toRemove; + toRemove = []; + toRemove.push.apply(toRemove, member.assignments); + toRemove.push.apply(toRemove, member.availabilities); + member.contacts.forEach(function(contact) { + toRemove.push.apply(toRemove, contact.contactEmailAddresses); + toRemove.push.apply(toRemove, contact.contactPhoneNumbers); + return toRemove.push(contact); + }); + toRemove.push.apply(toRemove, member.trackedItemStatuses); + toRemove.push.apply(toRemove, member.memberPayments); + toRemove.push.apply(toRemove, member.memberStatistics); + toRemove.push.apply(toRemove, member.statisticData); + toRemove.push.apply(toRemove, member.memberAssignments); + linking.unlinkItems(toRemove, lookup); + return deleteMember.call(this, member, callback).then(function(result) { + sdk.loadTeamFees(member.teamId); + sdk.loadStatisticAggregates(member.teamId); + return result; + }).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteContact', function(deleteContact) { + return function(contact, callback) { + var toRemove; + toRemove = []; + toRemove.push.apply(toRemove, contact.contactEmailAddresses); + toRemove.push.apply(toRemove, contact.contactPhoneNumbers); + linking.unlinkItems(toRemove, lookup); + return deleteContact.call(this, contact, callback).then(function(result) { + return sdk.loadMembers({ + memberId: contact.memberId + }).then(function() { + return result; + }); + }).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveMemberEmailAddress', function(saveMemberEmailAddress) { + return function(emailAddress, callback) { + return saveMemberEmailAddress.call(this, emailAddress, callback).then(function(result) { + return sdk.loadMembers({ + id: emailAddress.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteMemberEmailAddress', function(deleteMemberEmailAddress) { + return function(emailAddress, callback) { + return deleteMemberEmailAddress.call(this, emailAddress, callback).then(function(result) { + return sdk.loadMembers({ + id: emailAddress.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveMemberPhoneNumber', function(saveMemberPhoneNumber) { + return function(phoneNumber, callback) { + return saveMemberPhoneNumber.call(this, phoneNumber, callback).then(function(result) { + return sdk.loadMembers({ + id: phoneNumber.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteMemberPhoneNumber', function(deleteMemberPhoneNumber) { + return function(phoneNumber, callback) { + return deleteMemberPhoneNumber.call(this, phoneNumber, callback).then(function(result) { + return sdk.loadMembers({ + id: phoneNumber.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveContactEmailAddress', function(saveContactEmailAddress) { + return function(emailAddress, callback) { + return saveContactEmailAddress.call(this, emailAddress, callback).then(function(result) { + return sdk.loadMembers({ + id: emailAddress.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteContactEmailAddress', function(deleteContactEmailAddress) { + return function(emailAddress, callback) { + return deleteContactEmailAddress.call(this, emailAddress, callback).then(function(result) { + return sdk.loadMembers({ + id: emailAddress.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveContactPhoneNumber', function(saveContactPhoneNumber) { + return function(phoneNumber, callback) { + return saveContactPhoneNumber.call(this, phoneNumber, callback).then(function(result) { + return sdk.loadMembers({ + id: phoneNumber.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteContactPhoneNumber', function(deleteContactPhoneNumber) { + return function(phoneNumber, callback) { + return deleteContactPhoneNumber.call(this, phoneNumber, callback).then(function(result) { + return sdk.loadMembers({ + id: phoneNumber.memberId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapSave(sdk, 'saveEvent', function(event) { + var ids; + ids = Array.isArray(event) ? (event.map(function(event) { + return event.id; + })).join(',') : event.id; + return sdk.loadAvailabilities({ + eventId: ids + }); + }, function(event) { + var e, firstEvent, ref1, ref2, repeatingEventIds, toRemove; + if (event.isGame) { + return promises.when(sdk.loadTeamResults(event.teamId), sdk.loadOpponentResults(event.opponentId), sdk.loadEventStatistics({ + eventId: event.id + })); + } else if (Array.isArray(event)) { + repeatingEventIds = (function() { + var i, len, results; + results = []; + for (i = 0, len = event.length; i < len; i++) { + e = event[i]; + results.push(e.id); + } + return results; + })(); + firstEvent = event.shift(); + toRemove = []; + if ((ref1 = firstEvent.team) != null) { + if ((ref2 = ref1.events) != null) { + ref2.forEach(function(e) { + if (e.repeatingUuid === firstEvent.repeatingUuid) { + return toRemove.push(e); + } + }); + } + } + toRemove = toRemove.filter(function(e) { + var ref3; + return ref3 = e.id, indexOf.call(repeatingEventIds, ref3) < 0; + }); + return linking.unlinkItems(toRemove, lookup); + } + }); + wrapMethod(sdk, 'deleteEvent', function(deleteEvent) { + return function(event, include, notify, notifyAs, callback) { + var events, ref1, ref2, startDate, toRemove, uuid; + events = []; + if (typeof include === 'string' && include !== sdk.EVENTS.NONE) { + uuid = event.repeatingUuid; + startDate = event.startDate; + if ((ref1 = event.team) != null) { + if ((ref2 = ref1.events) != null) { + ref2.forEach(function(event) { + if (event.repeatingUuid === uuid) { + return events.push(event); + } + }); + } + } + if (include === sdk.EVENTS.FUTURE) { + events = events.filter(function(event) { + return event.startDate >= startDate; + }); + } + } else { + events.push(event); + } + toRemove = events.slice(); + events.forEach(function(event) { + toRemove.push.apply(toRemove, event.assignments); + toRemove.push.apply(toRemove, event.availabilities); + return toRemove.push.apply(toRemove, event.eventStatistics); + }); + event.assignments.forEach(function(assignment) { + if (assignment.memberAssignments.length) { + return assignment.memberAssignments.forEach(function(memberAssignment) { + return toRemove.push.apply(toRemove, memberAssignment); + }); + } + }); + linking.unlinkItems(toRemove, lookup); + return deleteEvent.call(this, event, include, notify, notifyAs, callback).then(function(result) { + if (event.isGame) { + return promises.when(sdk.loadTeamResults(event.teamId), sdk.loadOpponentResults(event.opponentId)).then(function() { + return result; + }); + } else { + return result; + } + }, function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapSave(sdk, 'saveTrackedItem', function(trackedItem) { + return sdk.loadTrackedItemStatuses({ + trackedItemId: trackedItem.id + }); + }); + wrapMethod(sdk, 'deleteTrackedItem', function(deleteTrackedItem) { + return function(trackedItem, callback) { + var toRemove; + toRemove = trackedItem.trackedItemStatuses.slice(); + linking.unlinkItems(toRemove, lookup); + return deleteTrackedItem.call(this, trackedItem).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteStatistic', function(deleteStatistic) { + return function(statistic, callback) { + var toRemove; + toRemove = statistic.statisticData.slice(); + toRemove.push.apply(toRemove, statistic.eventStatistics); + toRemove.push.apply(toRemove, statistic.memberStatistics); + toRemove.push.apply(toRemove, statistic.teamStatistics); + toRemove.push.apply(toRemove, statistic.statisticAggregates); + linking.unlinkItems(toRemove, lookup); + return deleteStatistic.call(this, statistic).then(function(result) { + var bulkLoadTypes, statisticId, teamId; + teamId = statistic.teamId; + statisticId = result.id; + bulkLoadTypes = ['memberStatistic', 'teamStatistic', 'statisticAggregate', 'eventStatistic']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + }).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveStatistic', function(saveStatistic) { + return function(statistic, callback) { + if ((statistic.statisticGroupId == null) && (statistic.statisticGroup != null)) { + linking.unlinkItems(statistic.statisticGroup, statistic); + } + return saveStatistic.call(this, statistic, callback).then(function(result) { + var bulkLoadTypes, statisticId, teamId; + teamId = statistic.teamId; + statisticId = result.id; + bulkLoadTypes = ['memberStatistic', 'teamStatistic', 'statisticAggregate', 'statistic', 'statisticGroup', 'eventStatistic']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'bulkSaveStatisticData', function(bulkSaveStatisticData) { + return function(templates, callback) { + return bulkSaveStatisticData.call(this, templates, callback).then(function(result) { + var bulkLoadTypes, teamId; + if ((result[0] != null) && (result[0].teamId != null)) { + teamId = result[0].teamId; + bulkLoadTypes = ['memberStatistic', 'statisticAggregate', 'eventStatistic']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + } + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveStatisticDatum', function(saveStatisticDatum) { + return function(statisticDatum, callback) { + return saveStatisticDatum.call(this, statisticDatum, callback).then(function(result) { + var bulkLoadTypes, statisticId, teamId; + teamId = result.teamId; + statisticId = result.statisticId; + bulkLoadTypes = ['memberStatistic', 'statisticAggregate', 'eventStatistic']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'bulkDeleteStatisticData', function(bulkDeleteStatisticData) { + return function(member, event, callback) { + var ref1, toRemove; + toRemove = []; + toRemove.push(event.eventStatistics); + if ((ref1 = member.statisticData) != null) { + ref1.forEach(function(statisticDatum) { + if (statisticDatum.event === event) { + return toRemove.push(statisticDatum); + } + }); + } + linking.unlinkItems(toRemove, lookup); + return bulkDeleteStatisticData.call(this, member, event).then(function(result) { + var bulkLoadTypes, teamId; + teamId = member.teamId; + bulkLoadTypes = ['memberStatistic', 'statisticAggregate', 'eventStatistic']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + }).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveMemberPayment', function(saveMemberPayment) { + return function(memberPayment, callback) { + return saveMemberPayment.call(this, memberPayment).then(function(result) { + var memberId, teamFeeId; + memberId = result.memberId; + teamFeeId = result.teamFeeId; + return promises.when(sdk.loadMemberBalances({ + memberId: memberId + }), sdk.loadTeamFees({ + id: teamFeeId + }), sdk.loadPaymentNotes({ + memberPaymentId: memberPayment.id + })).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveTeamFee', function(saveTeamFee) { + return function(teamFee, callback) { + return saveTeamFee.call(this, teamFee).then(function(result) { + var teamId; + teamId = result.teamId; + return sdk.loadMemberBalances({ + teamId: teamId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteTeamFee', function(deleteTeamFee) { + return function(teamFee, callback) { + return deleteTeamFee.call(this, teamFee).then(function(result) { + var teamId; + teamId = teamFee.teamId; + return sdk.loadMemberBalances({ + teamId: teamId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'assignMediaToGroup', function(assignMediaToGroup) { + return function(teamMediumIds, teamMediaGroup, callback) { + return assignMediaToGroup.call(this, teamMediumIds, teamMediaGroup).then(function(result) { + var bulkLoadTypes, teamId; + teamId = result[0].teamId; + bulkLoadTypes = ['teamMediaGroup', 'teamMedium']; + return sdk.bulkLoad(teamId, bulkLoadTypes).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'setMediumAsTeamPhoto', function(setMediumAsTeamPhoto) { + return function(teamMedium, callback) { + return setMediumAsTeamPhoto.call(this, teamMedium).then(function(result) { + var teamId; + teamId = result.teamId; + return sdk.loadTeamPreferences(teamId).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'setMediumAsMemberPhoto', function(setMediumAsMemberPhoto) { + return function(teamMedium, member, callback) { + return setMediumAsMemberPhoto.call(this, teamMedium, member).then(function(result) { + if (member.id != null) { + return sdk.loadMembers({ + id: member.id + }).then(function() { + return result; + }); + } + }).callback(callback); + }; + }); + wrapMethod(sdk, 'uploadTeamMedium', function(uploadTeamMedium) { + return function(teamMedium, progressCallback, callback) { + return uploadTeamMedium.call(this, teamMedium, progressCallback).then(function(result) { + return promises.when(sdk.loadTeam(teamMedium.teamId), sdk.loadTeamMediaGroups({ + id: teamMedium.teamMediaGroupId + })).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveTeamMedium', function(saveTeamMedium) { + return function(teamMedium, callback) { + var ref1, teamMediaGroupIds; + teamMediaGroupIds = [teamMedium.teamMediaGroupId]; + if ((((ref1 = teamMedium._state) != null ? ref1.teamMediaGroupId : void 0) != null) !== teamMedium.teamMediaGroupId) { + teamMediaGroupIds.push(teamMedium._state.teamMediaGroupId); + } + return saveTeamMedium.call(this, teamMedium).then(function(result) { + var teamId; + teamId = teamMedium.teamId; + return sdk.loadTeamMediaGroups({ + id: teamMediaGroupIds + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveTeamVideoLink', function(saveTeamVideoLink) { + return function(teamMedium, callback) { + return saveTeamVideoLink.call(this, teamMedium).then(function(result) { + return sdk.loadTeamMediaGroups({ + id: teamMedium.teamMediaGroupId + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteTeamMedium', function(deleteTeamMedium) { + return function(teamMedium, callback) { + var toRemove; + toRemove = teamMedium.teamMediumComments.slice(); + linking.unlinkItems(toRemove, lookup); + return deleteTeamMedium.call(this, teamMedium).then(function(result) { + return promises.when(sdk.loadTeam(teamMedium.teamId), sdk.loadTeamMediaGroups({ + id: teamMedium.teamMediaGroupId + })).then(function() { + return result; + }); + }, function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'bulkDeleteTeamMedia', function(bulkDeleteTeamMedia) { + return function(teamMediumIds, teamId, callback) { + if (typeof teamId === 'function') { + callback = teamId; + } + return bulkDeleteTeamMedia.call(this, teamMediumIds, callback).then(function(result) { + if (typeof teamId === 'string' || typeof teamId === 'number') { + return promises.when(sdk.loadTeam(teamId), sdk.loadTeamMediaGroups({ + teamId: teamId + })).then(function() { + return result; + }); + } else { + return result; + } + }).callback(callback); + }; + }); + wrapMethod(sdk, 'reorderTeamMedia', function(reorderTeamMedia) { + return function(teamId, teamMediaIds, teamMediaGroupId, callback) { + var params; + params = { + teamId: teamId + }; + if (typeof teamMediaGroupId === 'function') { + callback = teamMediaGroupId; + } + if (typeof teamMediaGroupId === 'string' || typeof teamMediaGroupId === 'number') { + params = { + id: teamMediaGroupId + }; + } + return reorderTeamMedia.call(this, teamId, teamMediaIds).then(function(result) { + return sdk.loadTeamMediaGroups(params).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteTeam', function(deleteTeam) { + return function(team, callback) { + var toRemove; + toRemove = []; + team.links.each(function(rel) { + var value; + value = team[name]; + if (types.getType(rel) && rel !== 'sport' && rel !== 'plan') { + if (Array.isArray(value)) { + return toRemove.push.apply(toRemove, value); + } else { + return toRemove.push(value); + } + } + }); + return deleteTeam.call(this, team).then(function(result) { + linking.unlinkItems(toRemove, lookup); + return result; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteForumTopic', function(deleteForumTopic) { + return function(topic, callback) { + var toRemove; + toRemove = []; + toRemove.push.apply(toRemove, topic.forumPosts); + linking.unlinkItems(toRemove, lookup); + return deleteForumTopic.call(this, topic, callback).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'invite', function(invite) { + return function(options, callback) { + return invite.call(this, options).then(function(result) { + var contactId, memberId; + if (options.hasOwnProperty('memberId')) { + memberId = options.memberId; + return sdk.loadMemberEmailAddresses({ + memberId: memberId + }).then(function() { + return result; + }); + } else if (options.hasOwnProperty('contactId')) { + contactId = options.contactId; + return sdk.loadContactEmailAddresses({ + contactId: contactId + }).then(function() { + return result; + }); + } + }).callback(callback); + }; + }); + wrapMethod(sdk, 'memberPaymentTransaction', function(memberPaymentTransaction) { + return function(memberPaymentId, amount, note, callback) { + return memberPaymentTransaction.call(this, memberPaymentId, amount, note).then(function(result) { + var memberId, teamFeeId; + memberId = result.memberId; + teamFeeId = result.teamFeeId; + return promises.when(sdk.loadMemberBalances({ + memberId: memberId + }), sdk.loadTeamFees({ + id: teamFeeId + }), sdk.loadPaymentNotes({ + memberPaymentId: memberPaymentId + })).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'importMembersFromTeam', function(importMembersFromTeam) { + return function(memberIds, teamId, sendInvites, callback) { + return importMembersFromTeam.call(this, memberIds, teamId, sendInvites).then(function(result) { + memberIds = result.map(function(member) { + return member.id; + }); + return promises.when(sdk.loadMembers({ + id: memberIds + }), sdk.loadContacts({ + memberId: memberIds + }), sdk.loadMemberEmailAddresses({ + memberId: memberIds + }), sdk.loadContactEmailAddresses({ + memberId: memberIds + }), sdk.loadMemberPhoneNumbers({ + memberId: memberIds + }), sdk.loadContactPhoneNumbers({ + memberId: memberIds + })).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveBroadcastAlert', function(saveBroadcastAlert) { + return function(broadcastAlert, callback) { + return saveBroadcastAlert.call(this, broadcastAlert).then(function(result) { + var params; + if ((result.member != null) || (result.divisionMember != null)) { + params = { + memberId: result.memberId + }; + } else { + params = { + contactId: result.contactId + }; + } + sdk.loadMessageData(params); + return sdk.loadMessages({ + messageSourceId: result.id + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveBroadcastEmail', function(saveBroadcastEmail) { + return function(broadcastEmail, callback) { + return saveBroadcastEmail.call(this, broadcastEmail).then(function(result) { + var params; + if ((result.member != null) || (result.divisionMember != null)) { + params = { + memberId: result.memberId + }; + } else { + params = { + contactId: result.contactId + }; + } + sdk.loadMessageData(params); + return sdk.loadMessages({ + messageSourceId: result.id + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveAssignment', function(saveAssignment) { + return function(assignment, callback) { + return saveAssignment.call(this, assignment, callback).then(function(result) { + return sdk.loadMemberAssignments({ + assignmentId: result.id + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteAssignment', function(deleteAssignment) { + return function(assignment, callback) { + var toRemove; + if (assignment.memberAssignments.length) { + toRemove = assignment.memberAssignments; + linking.unlinkItems(toRemove, lookup); + } + return deleteAssignment.call(this, assignment).then(function(result) { + return sdk.loadEvents({ + eventId: assignment.eventId + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'saveMemberAssignment', function(saveMemberAssignment) { + return function(memberAssignment, callback) { + return saveMemberAssignment.call(this, memberAssignment).then(function(result) { + return sdk.loadAssignments({ + id: result.assignmentId + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'deleteMemberAssignment', function(deleteMemberAssignment) { + return function(memberAssignment, callback) { + return deleteMemberAssignment.call(this, memberAssignment, callback).then(function(result) { + return sdk.loadAssignments({ + id: memberAssignment.assignmentId + }).then(function(assignment) { + assignment[0].member = null; + return result; + }); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'markMessageAsRead', function(markMessageAsRead) { + return function(messageId, callback) { + return markMessageAsRead.call(this, messageId, callback).then(function(result) { + var params; + if ((result.member != null) || (result.divisionMember != null)) { + params = { + memberId: result.memberId + }; + } else { + params = { + contactId: result.contactId + }; + } + params.messageType = 'alert,email'; + sdk.loadMessages({ + id: result.messageId + }); + return sdk.loadMessageData(params); + }).callback(callback); + }; + }); + wrapMethod(sdk, 'bulkDeleteMessages', function(bulkDeleteMessages) { + return function(messages, callback) { + var contactId, memberId, teamId, toRemove; + if (Array.isArray(messages) && messages.length && this.isItem(messages[0], 'message')) { + toRemove = messages; + } else if (typeof messages === 'object' && this.isItem(messages, 'message')) { + toRemove = [messages]; + } + if (toRemove != null) { + if (toRemove[0].contactId != null) { + contactId = toRemove[0].contactId; + } else if (toRemove[0].memberId != null) { + memberId = toRemove[0].memberId; + } + teamId = toRemove[0].teamId; + linking.unlinkItems(toRemove, lookup); + } + return bulkDeleteMessages.call(this, messages).then(function(result) { + var params; + if (toRemove != null) { + params = {}; + if (contactId != null) { + params.contactId = contactId; + } else if (memberId != null) { + params.memberId = memberId; + } + params.messageType = 'alert,email'; + params.teamId = teamId; + return sdk.loadMessageData(params).then(function(result) { + return result; + }).fail(function(err) { + return err; + }); + } else { + return result; + } + }).fail(function(err) { + if (toRemove != null) { + linking.linkItems(toRemove, lookup); + } + return err; + }).callback(callback); + }; + }); + wrapMethod(sdk, 'createBulkAssignments', function(createBulkAssignments) { + return function(eventSet, description, teamId, createAsMemberId, callback) { + return createBulkAssignments.call(this, eventSet, description, teamId, createAsMemberId, callback).then(function(result) { + var assignmentIds; + assignmentIds = result.map(function(assignment) { + return assignment.id; + }); + return sdk.loadAssignments({ + id: assignmentIds + }).then(function() { + return result; + }); + }).callback(callback); + }; + }); + return wrapMethod(sdk, 'bulkDeleteMembers', function(bulkDeleteMembers) { + return function(members, callback) { + var toRemove; + toRemove = []; + members.forEach(function(member) { + toRemove.push.apply(toRemove, member.assignments); + toRemove.push.apply(toRemove, member.availabilities); + member.contacts.forEach(function(contact) { + toRemove.push.apply(toRemove, contact.contactEmailAddresses); + toRemove.push.apply(toRemove, contact.contactPhoneNumbers); + return toRemove.push(contact); + }); + toRemove.push.apply(toRemove, member.trackedItemStatuses); + toRemove.push.apply(toRemove, member.memberPayments); + toRemove.push.apply(toRemove, member.memberStatistics); + toRemove.push.apply(toRemove, member.statisticData); + return toRemove.push.apply(toRemove, member.memberAssignments); + }); + linking.unlinkItems(toRemove, lookup); + return bulkDeleteMembers.call(this, members, callback).then(function(result) { + return result; + }).fail(function(err) { + linking.linkItems(toRemove, lookup); + return err; + }).callback(callback); + }; + }); +}; + +revertSDK = function(sdk) { + revertWrapMethod(sdk, 'saveMember'); + revertWrapMethod(sdk, 'deleteMember'); + revertWrapMethod(sdk, 'deleteContact'); + revertWrapMethod(sdk, 'saveEvent'); + revertWrapMethod(sdk, 'deleteEvent'); + revertWrapMethod(sdk, 'saveTrackedItem'); + revertWrapMethod(sdk, 'deleteTrackedItem'); + return revertWrapMethod(sdk, 'deleteTeam'); +}; + +wrapMethod = function(obj, methodName, newMethodProvider) { + var oldMethod; + oldMethod = obj[methodName]; + obj[methodName] = newMethodProvider(oldMethod); + obj[methodName].oldMethod = oldMethod; + return obj; +}; + +revertWrapMethod = function(obj, methodName) { + var oldMethod; + oldMethod = obj[methodName].oldMethod; + return obj[methodName] = oldMethod; +}; + +wrapSave = function(sdk, saveMethodName, onSaveNew, onSaveEdit) { + return wrapMethod(sdk, saveMethodName, function(save) { + return function(item, callback) { + var savedItem; + if (item.id && onSaveEdit) { + savedItem = null; + return save.call(this, item).then(function(item) { + return savedItem = item; + }).then(onSaveEdit).then(function() { + return savedItem; + }).callback(callback); + } else if (!item.id && onSaveNew) { + savedItem = null; + return save.call(this, item).then(function(item) { + return savedItem = item; + }).then(onSaveNew).then(function() { + return savedItem; + }).callback(callback); + } else { + return save.call(this, item, callback); + } + }; + }); +}; + +copy = function(from, to) { + Object.keys(from).forEach(function(key) { + if (typeof value === 'function' || key.charAt(0) === '_') { + return; + } + return to[key] = from[key]; + }); + return to; +}; + +camelize = function(str) { + return str.replace(/[-_]+(\w)/g, function(_, char) { + return char.toUpperCase(); + }); +}; + +}); + +require.register("promises.coffee", function(exports, require, module) { +var Deferred, Promise, args, promises, + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + slice = [].slice, + hasProp = {}.hasOwnProperty; + +promises = typeof exports !== 'undefined' ? exports : this; + +Promise = (function() { + function Promise() { + this.call = bind(this.call, this); + } + + Promise.prototype.then = function(resolvedHandler, rejectedHandler, progressHandler, cancelHandler) { + throw new TypeError('The Promise base class is abstract, this function is overwritten by the promise\'s deferred object'); + }; + + Promise.prototype.callback = function(callback) { + if (callback && typeof callback === 'function') { + this.then(function() { + var results; + results = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return callback.apply(null, [null].concat(slice.call(results))); + }, function(err) { + return callback(err); + }); + } + return this; + }; + + Promise.prototype.resolved = function(handler) { + return this.then(handler); + }; + + Promise.prototype.done = function(handler) { + return this.then(handler); + }; + + Promise.prototype.rejected = function(handler) { + return this.then(null, handler); + }; + + Promise.prototype.fail = function(handler) { + return this.then(null, handler); + }; + + Promise.prototype.always = function(handler) { + var rejectedHandler, resolvedHandler; + resolvedHandler = function(res) { + return handler(null, res); + }; + rejectedHandler = function(err) { + return handler(err); + }; + return this.then(resolvedHandler, rejectedHandler); + }; + + Promise.prototype.progress = function(handler) { + return this.then(null, null, handler); + }; + + Promise.prototype.canceled = function(handler) { + return this.then(null, null, null, handler); + }; + + Promise.prototype.apply = function(handler, context) { + return this.then(function(result) { + if ((result instanceof Array)(handler.apply(context || this, result))) { + + } else { + return handler.call(context || this, result); + } + }); + }; + + Promise.prototype.cancel = function() { + throw new TypeError('The Promise base class is abstract, this function is overwritten by the promise\'s deferred object'); + }; + + Promise.prototype.get = function(propertyName) { + return this.then(function(object) { + return object != null ? object[propertyName] : void 0; + }); + }; + + Promise.prototype.set = function(propertyName, value) { + return this.then(function(object) { + if (object != null) { + object[propertyName] = value; + } + return object; + }); + }; + + Promise.prototype.put = function(propertyName, value) { + return this.then(function(object) { + return object != null ? object[propertyName] = value : void 0; + }); + }; + + Promise.prototype.run = function() { + var functionName, params; + functionName = arguments[0], params = 2 <= arguments.length ? slice.call(arguments, 1) : []; + return this.then(function(object) { + if (object != null) { + object[functionName].apply(object, params); + } + return object; + }); + }; + + Promise.prototype.call = function() { + var functionName, params; + functionName = arguments[0], params = 2 <= arguments.length ? slice.call(arguments, 1) : []; + return this.then(function(object) { + return object[functionName].apply(object, params); + }); + }; + + return Promise; + +})(); + +['pop', 'shift', 'splice', 'filter', 'every', 'map', 'some'].forEach(function(method) { + return Promise.prototype[method] = function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return this.then(function(object) { + return object != null ? typeof object[method] === "function" ? object[method].apply(object, args) : void 0 : void 0; + }); + }; +}); + +['push', 'reverse', 'sort', 'unshift', 'forEach'].forEach(function(method) { + return Promise.prototype[method] = function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return this.then(function(object) { + if (object instanceof Array) { + object[method].apply(object, args); + } + return object; + }); + }; +}); + +Promise.extend = function(methods) { + var SubPromise, name, value; + SubPromise = function() {}; + SubPromise.extend = this.extend; + SubPromise.prototype = new this(); + if (methods) { + for (name in methods) { + if (!hasProp.call(methods, name)) continue; + value = methods[name]; + SubPromise.prototype[name] = value; + } + } + return SubPromise; +}; + +promises.when = function() { + var alwaysCallback, count, createCallback, deferred, i, len, name, obj, params, rejected, rejectedCallback, resolvedCallback; + params = 1 <= arguments.length ? slice.call(arguments, 0) : []; + deferred = promises.defer(); + count = params.length; + rejected = false; + resolvedCallback = function() {}; + rejectedCallback = function(value) { + rejected = true; + return value; + }; + createCallback = function(index) { + return function() { + var results; + results = 1 <= arguments.length ? slice.call(arguments, 0) : []; + params[index] = results.length > 1 ? results : results[0]; + if (--count === 0) { + if (rejected) { + return deferred.reject.apply(deferred, params); + } else { + return deferred.resolve.apply(deferred, params); + } + } + }; + }; + for (name = i = 0, len = params.length; i < len; name = ++i) { + obj = params[name]; + if (obj && typeof obj.then === 'function') { + alwaysCallback = createCallback(name); + obj.then(resolvedCallback, rejectedCallback); + obj.then(alwaysCallback, alwaysCallback); + } else { + --count; + } + } + if (count === 0) { + deferred.resolve.apply(deferred, params); + } + return deferred.promise; +}; + +args = function() { + var params; + params = 1 <= arguments.length ? slice.call(arguments, 0) : []; + params.isArgs = true; + return params; +}; + +Deferred = (function() { + function Deferred(promise) { + if (promise == null) { + promise = new promises.Promise; + } + this.progress = bind(this.progress, this); + this.cancel = bind(this.cancel, this); + this.reject = bind(this.reject, this); + this.resolve = bind(this.resolve, this); + this.finished = bind(this.finished, this); + this.then = bind(this.then, this); + this.promise = promise; + this.status = 'pending'; + this.progressHandlers = []; + this.handlers = []; + promise.then = this.then; + promise.cancel = this.cancel; + promise.getStatus = (function(_this) { + return function() { + return _this.status; + }; + })(this); + } + + Deferred.prototype.then = function(resolvedHandler, rejectedHandler, progressHandler, canceledHandler) { + var deferred, handler, i, len, method, nextDeferred, nextResult; + for (i = 0, len = arguments.length; i < len; i++) { + handler = arguments[i]; + if ((handler != null) && typeof handler !== 'function') { + throw new Error('Promise handlers must be functions'); + } + } + if (progressHandler) { + this.progressHandlers.push(progressHandler); + } + nextDeferred = promises.defer(); + nextDeferred.promise.prev = this.promise; + this._addHandler(resolvedHandler, rejectedHandler, canceledHandler).nextDeferred = nextDeferred; + if (this.finished()) { + handler = this.handlers.pop(); + method = handler[this.status]; + deferred = handler.nextDeferred; + if (!method) { + deferred[this.status].apply(deferred, this.results); + } else { + nextResult = method.apply(null, this.results); + if (nextResult && typeof nextResult.then === 'function') { + nextResult.then(deferred.resolve, deferred.reject); + } else { + deferred[this.status](nextResult); + } + } + } + return nextDeferred.promise; + }; + + Deferred.prototype.finished = function() { + return this.status !== 'pending'; + }; + + Deferred.prototype.resolve = function() { + var deferred, handler, method, nextResult, ref, results; + results = 1 <= arguments.length ? slice.call(arguments, 0) : []; + if (this.status !== 'pending') { + return; + } + if ((ref = results[0]) != null ? ref.isArgs : void 0) { + results = results[0]; + } + clearTimeout(this._timeout); + this.status = 'resolve'; + this.results = results; + while ((handler = this.handlers.shift())) { + method = handler[this.status]; + deferred = handler.nextDeferred; + if (!method) { + deferred[this.status].apply(deferred, this.results); + } else { + nextResult = method.apply(null, this.results); + if (nextResult && typeof nextResult.then === 'function') { + nextResult.then(deferred.resolve, deferred.reject); + } else { + deferred[this.status](nextResult); + } + } + } + }; + + Deferred.prototype.reject = function() { + var deferred, handler, method, nextResult, ref, results; + results = 1 <= arguments.length ? slice.call(arguments, 0) : []; + if (this.status !== 'pending') { + return; + } + if ((ref = results[0]) != null ? ref.isArgs : void 0) { + results = results[0]; + } + clearTimeout(this._timeout); + this.status = 'reject'; + this.results = results; + while ((handler = this.handlers.shift())) { + method = handler[this.status]; + deferred = handler.nextDeferred; + if (!method) { + deferred[this.status].apply(deferred, this.results); + } else { + nextResult = method.apply(null, this.results); + if (nextResult && typeof nextResult.then === 'function') { + nextResult.then(deferred.resolve, deferred.reject); + } else { + deferred[this.status](nextResult); + } + } + } + }; + + Deferred.prototype.cancel = function() { + var deferred, handler, method, nextResult, ref, ref1, results; + results = 1 <= arguments.length ? slice.call(arguments, 0) : []; + if (this.status !== 'pending') { + return; + } + if ((ref = results[0]) != null ? ref.isArgs : void 0) { + results = results[0]; + } + clearTimeout(this._timeout); + this.status = 'cancel'; + this.results = results; + while ((handler = this.handlers.shift())) { + method = handler[this.status]; + deferred = handler.nextDeferred; + if (!method) { + deferred[this.status].apply(deferred, this.results); + } else { + nextResult = method.apply(null, this.results); + if (nextResult && typeof nextResult.then === 'function') { + nextResult.then(deferred.resolve, deferred.reject); + } else { + deferred[this.status](nextResult); + } + } + } + if ((ref1 = this.promise.prev) != null) { + ref1.cancel(); + } + }; + + Deferred.prototype.progress = function() { + var i, len, params, progress, ref, results1; + params = 1 <= arguments.length ? slice.call(arguments, 0) : []; + ref = this.progressHandlers; + results1 = []; + for (i = 0, len = ref.length; i < len; i++) { + progress = ref[i]; + results1.push(progress.apply(null, params)); + } + return results1; + }; + + Deferred.prototype.timeout = function(milliseconds, error) { + clearTimeout(this._timeout); + return this._timeout = setTimeout((function(_this) { + return function() { + return _this.reject(error != null ? error : new Error('Operation timed out')); + }; + })(this), milliseconds); + }; + + Deferred.prototype.reset = function() { + this.status = 'pending'; + this.progressHandlers = []; + return this.handlers = []; + }; + + Deferred.prototype._addHandler = function(resolvedHandler, rejectedHandler, canceledHandler) { + var handler; + handler = { + resolve: resolvedHandler, + reject: rejectedHandler, + cancel: canceledHandler + }; + this.handlers.push(handler); + return handler; + }; + + return Deferred; + +})(); + +promises.Deferred = Deferred; + +promises.Promise = Promise; + +promises.args = args; + +promises.defer = function(promise) { + return new promises.Deferred(promise); +}; + +promises.wrap = function(method, PromiseClass) { + return function() { + var args, callback, deferred, promise; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + promise = PromiseClass ? new PromiseClass() : void 0; + deferred = promises.defer(promise); + if (typeof args[args.length - 1] === 'function') { + callback = args.pop(); + } + args.push(function(err, result) { + var extras; + extras = Array.prototype.slice.call(arguments, 2); + if (callback) { + callback.apply(null, [err, result].concat(slice.call(extras))); + } + if (err) { + return deferred.reject(err); + } else { + return deferred.resolve.apply(deferred, [result].concat(slice.call(extras))); + } + }); + method.apply(this, args); + return deferred.promise; + }; +}; + +promises.resolve = function() { + var args, deferred; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + deferred = promises.defer(); + deferred.resolve.apply(deferred, args); + return deferred.promise; +}; + +promises.reject = function() { + var args, deferred; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + deferred = promises.defer(); + deferred.reject.apply(deferred, args); + return deferred.promise; +}; + +}); + +require.register("request.coffee", function(exports, require, module) { +var FormData, RequestError, createRequest, promises, sendRequest, unloading, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + +if (typeof XMLHttpRequest === 'undefined') { + global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; +} + +FormData = global.FormData || function() {}; + +promises = require('./promises'); + +sendRequest = function(method, url, data, hooks, callback) { + var deferred, hook, i, key, len, query, value, xhr; + if (data && method.toUpperCase() === 'GET') { + query = []; + for (key in data) { + value = data[key]; + query.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + } + if (query.length) { + url += url.indexOf('?') === -1 ? '?' : '&'; + url += query.join('&'); + } + } else if (typeof data === 'object' && !(data instanceof FormData)) { + data = JSON.stringify(data); + } + xhr = new XMLHttpRequest(); + xhr.open(method.toUpperCase(), url); + if (hooks) { + for (i = 0, len = hooks.length; i < len; i++) { + hook = hooks[i]; + hook(xhr, data); + } + } + deferred = promises.defer(); + xhr.onreadystatechange = function() { + var errorMsg, ref, ref1, ref2; + switch (xhr.readyState) { + case 3: + return deferred.progress(xhr); + case 4: + try { + xhr.data = JSON.parse(xhr.responseText); + } catch (error) { + xhr.data = null; + } + if (xhr.status >= 400) { + errorMsg = ((ref = xhr.data) != null ? (ref1 = ref.collection) != null ? (ref2 = ref1.error) != null ? ref2.message : void 0 : void 0 : void 0) || ''; + } + if (xhr.status === 0) { + if (unloading) { + return promises.defer().promise; + } + return deferred.reject(new RequestError(RequestError.CONNECTION_ERROR, 'Could not connect to the server'), xhr, errorMsg); + } else if (xhr.status >= 500) { + if (global.console) { + console.error("TeamSnap API error: " + errorMsg); + } + return deferred.reject(new RequestError(RequestError.SERVER_ERROR, 'Error with the server'), xhr, errorMsg); + } else if (xhr.status > 400) { + return deferred.reject(new RequestError(RequestError.CLIENT_ERROR, 'There was an error with the request'), xhr, errorMsg); + } else if (xhr.status === 400) { + return deferred.reject(new RequestError(RequestError.VALIDATION_ERROR, errorMsg || 'The data was invalid'), xhr); + } else { + return deferred.resolve(xhr); + } + } + }; + xhr.send(data || null); + return deferred.promise.callback(callback); +}; + +createRequest = function(hooks) { + var request; + if (hooks == null) { + hooks = []; + } + request = function(method, url, data, callback) { + if (typeof data === 'function') { + callback = data; + data = null; + } + return sendRequest(method, url, data, hooks, callback); + }; + request.get = function(url, params, callback) { + return request('get', url, params, callback); + }; + request.post = function(url, params, callback) { + return request('post', url, params, callback); + }; + request.put = function(url, params, callback) { + return request('put', url, params, callback); + }; + request["delete"] = function(url, params, callback) { + return request('delete', url, params, callback); + }; + request.create = function() { + return createRequest(); + }; + request.clone = function() { + return createRequest(hooks.slice()); + }; + request.reset = function() { + hooks = []; + return this; + }; + request.hook = function(hook) { + hooks.push(hook); + return this; + }; + request.removeHook = function(hook) { + var index; + index = hooks.indexOf(hook); + if (index !== -1) { + hooks.splice(index, 1); + } + return this; + }; + return request; +}; + +module.exports = createRequest(); + +RequestError = (function(superClass) { + extend(RequestError, superClass); + + RequestError.CONNECTION_ERROR = 1; + + RequestError.SERVER_ERROR = 2; + + RequestError.CLIENT_ERROR = 3; + + RequestError.VALIDATION_ERROR = 4; + + function RequestError(code, message) { + this.code = code; + this.message = message; + RequestError.__super__.constructor.call(this); + this.name = 'RequestError'; + } + + return RequestError; + +})(Error); + +if (typeof window !== 'undefined') { + unloading = false; + window.addEventListener('beforeunload', function() { + unloading = true; + }); +} + +}); + +;require.register("sdk.coffee", function(exports, require, module) { +var Item, ScopedCollection, TeamSnap, add, linking, loadCollections, mergeDefaults, promises, ref, urlExp, + hasProp = {}.hasOwnProperty; + +TeamSnap = require('./teamsnap').TeamSnap; + +promises = require('./promises'); + +loadCollections = require('./loadCollections'); + +ref = require('./model'), Item = ref.Item, ScopedCollection = ref.ScopedCollection; + +urlExp = /^https?:\/\//; + +TeamSnap.prototype.loadCollections = function(cachedCollections, callback) { + if (typeof cachedCollections === 'function') { + callback = cachedCollections; + cachedCollections = null; + } + return loadCollections(this.request, cachedCollections).then((function(_this) { + return function(colls) { + var ref1, ref2, ref3, ref4; + _this.collections = {}; + Object.keys(colls).forEach(function(name) { + return _this.collections[name] = new ScopedCollection(_this.request, colls[name]); + }); + _this.apiVersion = colls.root.version; + _this.plans = Item.fromArray(_this.request, ((ref1 = colls.plans.items) != null ? ref1.slice() : void 0) || []); + _this.smsGateways = Item.fromArray(_this.request, ((ref2 = colls.smsGateways.items) != null ? ref2.slice() : void 0) || []); + _this.sports = Item.fromArray(_this.request, ((ref3 = colls.sports.items) != null ? ref3.slice() : void 0) || []); + _this.timeZones = Item.fromArray(_this.request, ((ref4 = colls.timeZones.items) != null ? ref4.slice() : void 0) || []); + return _this; + }; + })(this)).callback(callback); +}; + +TeamSnap.prototype.reloadCollections = function(callback) { + loadCollections.clear(); + return this.loadCollections(callback); +}; + +TeamSnap.prototype.loadItems = function(type, params, callback) { + var collection; + if (!this.hasType(type)) { + throw new TSArgsError('teamsnap.load*', 'must provide a valid `type`'); + } + collection = this.getCollectionForItem(type); + return collection.queryItems('search', params, callback); +}; + +TeamSnap.prototype.loadItem = function(type, params, callback) { + var collection; + if (!this.hasType(type)) { + throw new TSArgsError('teamsnap.load*', 'must provide a valid `type`'); + } + collection = this.getCollectionForItem(type); + return collection.queryItem('search', params, callback); +}; + +TeamSnap.prototype.createItem = function(properties, defaults) { + var collection; + if (!properties) { + properties = defaults; + defaults = null; + } + if (defaults) { + properties = mergeDefaults(properties, defaults); + } + if (!this.isItem(properties)) { + throw new TSArgsError('teamsnap.create*', 'must include a valid `type`'); + } + if (!properties.links) { + collection = this.getCollectionForItem(properties.type); + properties.links = collection.links.cloneEmpty(); + } + return Item.create(this.request, properties); +}; + +TeamSnap.prototype.saveItem = function(item, callback) { + var collection; + if (!this.isItem(item)) { + throw new TSArgsError('teamsnap.save*', 'must include a valid `type`'); + } + collection = this.getCollectionForItem(item); + return collection.save(item, callback); +}; + +TeamSnap.prototype.deleteItem = function(item, params, callback) { + if (typeof item === 'string' && urlExp.test(item)) { + item = { + href: item + }; + } + if (!(typeof (item != null ? item.href : void 0) === 'string' && urlExp.test(item.href))) { + throw new TSArgsError('teamsnap.delete*', 'item must have a valid href to delete'); + } + if (!(item instanceof Item)) { + item = Item.create(this.request, item); + } + return item["delete"](params, callback); +}; + +TeamSnap.prototype.copyItem = function(item) { + var collection; + collection = this.getCollectionForItem(item); + return item.copy(collection.template); +}; + +TeamSnap.prototype.getNameSort = function() { + return function(itemA, itemB) { + var valueA, valueB; + if (itemA.type !== itemB.type) { + valueA = itemA.type; + valueB = itemB.type; + } else if (typeof itemA.name === 'string' && typeof itemB.name === 'string') { + valueA = itemA.name.toLowerCase(); + valueB = itemB.name.toLowerCase(); + } else { + if (itemA.createdAt && itemB.createdAt) { + valueA = itemA.createdAt; + valueB = itemB.createdAt; + } else { + valueA = itemA.id; + valueB = itemB.id; + } + } + if (typeof (valueA != null ? valueA.localeCompare : void 0) === 'function') { + return valueA.localeCompare(valueB); + } else { + if (valueA === valueB) { + return 0; + } else if (!valueA && valueB) { + return 1; + } else if (valueA && !valueB) { + return -1; + } else if (valueA > valueB) { + return 1; + } else if (valueA < valueB) { + return -1; + } else { + return 0; + } + } + }; +}; + +TeamSnap.prototype.getDefaultSort = function() { + return function(itemA, itemB) { + var valueA, valueB; + if (itemA.type !== itemB.type) { + valueA = itemA.type; + valueB = itemB.type; + } else { + if (itemA.createdAt && itemB.createdAt) { + valueA = itemA.createdAt; + valueB = itemB.createdAt; + } else { + valueA = itemA.id; + valueB = itemB.id; + } + } + if (typeof (valueA != null ? valueA.localeCompare : void 0) === 'function') { + return valueA.localeCompare(valueB); + } else { + if (valueA === valueB) { + return 0; + } else if (!valueA && valueB) { + return 1; + } else if (valueA && !valueB) { + return -1; + } else if (valueA > valueB) { + return 1; + } else if (valueA < valueB) { + return -1; + } else { + return 0; + } + } + }; +}; + +TeamSnap.prototype.getCollectionForItem = function(item) { + var collectionName, type; + if (!this.collections) { + throw new TSError('You must auth() and loadCollections() before using any load*, save*, create*, or delete* methods.'); + } + type = typeof item === 'string' ? item : item.type; + collectionName = this.getPluralType(type); + return this.collections[collectionName]; +}; + +TeamSnap.prototype.isId = function(value) { + return typeof value === 'string' || typeof value === 'number'; +}; + +TeamSnap.prototype.isItem = function(value, type) { + return this.hasType(value != null ? value.type : void 0) && (!type || value.type === type); +}; + +TeamSnap.prototype.reject = function(msg, field, callback) { + return promises.reject(new TSValidationError(msg, field)).callback(callback); +}; + +add = function(module) { + var key, results, value; + results = []; + for (key in module) { + value = module[key]; + results.push(TeamSnap.prototype[key] = value); + } + return results; +}; + +add(require('./types')); + +linking = require('./linking'); + +TeamSnap.prototype.linkItems = linking.linkItems; + +TeamSnap.prototype.unlinkItems = linking.unlinkItems; + +add(require('./persistence')); + +add(require('./collections/teams')); + +add(require('./collections/assignments')); + +add(require('./collections/availabilities')); + +add(require('./collections/broadcastAlerts')); + +add(require('./collections/broadcastEmails')); + +add(require('./collections/broadcastEmailAttachments')); + +add(require('./collections/contactEmailAddresses')); + +add(require('./collections/contactPhoneNumbers')); + +add(require('./collections/contacts')); + +add(require('./collections/customData')); + +add(require('./collections/customFields')); + +add(require('./collections/leagueCustomData')); + +add(require('./collections/leagueCustomFields')); + +add(require('./collections/divisionEvents')); + +add(require('./collections/divisionLocations')); + +add(require('./collections/divisionMembers')); + +add(require('./collections/divisionMembersPreferences')); + +add(require('./collections/divisionTeamStandings')); + +add(require('./collections/divisions')); + +add(require('./collections/divisionsPreferences')); + +add(require('./collections/events')); + +add(require('./collections/eventStatistics')); + +add(require('./collections/facebookPages')); + +add(require('./collections/forumPosts')); + +add(require('./collections/forumSubscriptions')); + +add(require('./collections/forumTopics')); + +add(require('./collections/leagueRegistrantDocuments')); + +add(require('./collections/locations')); + +add(require('./collections/memberAssignments')); + +add(require('./collections/memberBalances')); + +add(require('./collections/memberEmailAddresses')); + +add(require('./collections/memberFiles')); + +add(require('./collections/memberLinks')); + +add(require('./collections/memberPayments')); + +add(require('./collections/memberPhoneNumbers')); + +add(require('./collections/memberPhotos')); + +add(require('./collections/membersPreferences')); + +add(require('./collections/memberStatistics')); + +add(require('./collections/memberRegistrationSignups')); + +add(require('./collections/members')); + +add(require('./collections/messageData')); + +add(require('./collections/messages')); + +add(require('./collections/opponents')); + +add(require('./collections/opponentsResults')); + +add(require('./collections/paymentNotes')); + +add(require('./collections/plans')); + +add(require('./collections/sponsors')); + +add(require('./collections/sports')); + +add(require('./collections/registrationForms')); + +add(require('./collections/statisticAggregates')); + +add(require('./collections/statistics')); + +add(require('./collections/statisticData')); + +add(require('./collections/statisticGroups')); + +add(require('./collections/teamFees')); + +add(require('./collections/teamMedia')); + +add(require('./collections/teamMediumComments')); + +add(require('./collections/teamMediaGroups')); + +add(require('./collections/teamPublicSites')); + +add(require('./collections/teamsPaypalPreferences')); + +add(require('./collections/teamPhotos')); + +add(require('./collections/teamsPreferences')); + +add(require('./collections/teamsResults')); + +add(require('./collections/teamStatistics')); + +add(require('./collections/trackedItems')); + +add(require('./collections/trackedItemStatuses')); + +add(require('./collections/users')); + +mergeDefaults = function(properties, defaults) { + var key, obj, value; + obj = {}; + for (key in properties) { + if (!hasProp.call(properties, key)) continue; + value = properties[key]; + if (!(typeof value === 'function' || key.charAt(0) === '_')) { + obj[key] = value; + } + } + for (key in defaults) { + if (!hasProp.call(defaults, key)) continue; + value = defaults[key]; + if (!(typeof value === 'function' || properties.hasOwnProperty(key))) { + obj[key] = value; + } + } + return obj; +}; + +}); + +require.register("teamsnap.coffee", function(exports, require, module) { +var Collection, Item, TeamSnap, promises, ref; + +promises = require('./promises'); + +ref = require('./model'), Collection = ref.Collection, Item = ref.Item; + +require('./errors'); + +TeamSnap = (function() { + TeamSnap.prototype.version = '1.24.0'; + + TeamSnap.prototype.promises = promises; + + TeamSnap.prototype.when = promises.when; + + TeamSnap.prototype.TeamSnap = TeamSnap; + + TeamSnap.prototype.Collection = Collection; + + TeamSnap.prototype.Item = Item; + + function TeamSnap(apiUrl, authUrl) { + this.apiUrl = apiUrl != null ? apiUrl : 'https://apiv3.teamsnap.com'; + this.authUrl = authUrl != null ? authUrl : 'https://auth.teamsnap.com'; + } + + return TeamSnap; + +})(); + +module.exports = new TeamSnap(); + +require('./auth'); + +require('./sdk'); + +if (!String.prototype.trim) { + String.prototype.trim = function() { + return this.replace(/^\s+|\s+$/g, ''); + }; +} + +}); + +;require.register("types.coffee", function(exports, require, module) { +var i, len, plural, pluralLookup, singularLookup, teamTypes, teamsnap, type, typeLookup, types; + +teamsnap = exports; + +types = ['user', 'assignment', 'availability', 'broadcastAlert', 'broadcastEmail', 'broadcastEmailAttachment', 'contact', 'contactEmailAddress', 'contactPhoneNumber', 'customDatum', 'customField', 'leagueCustomDatum', 'leagueCustomField', 'divisionContact', 'divisionContactEmailAddress', 'divisionContactPhoneNumber', 'divisionEvent', 'divisionLocation', 'divisionMember', 'divisionMemberEmailAddress', 'divisionMemberPhoneNumber', 'divisionMemberPreferences', 'divisionTeamStanding', 'divisionPreferences', 'division', 'event', 'eventStatistic', 'facebookPage', 'forumPost', 'forumSubscription', 'forumTopic', 'leagueRegistrantDocument', 'location', 'member', 'memberAssignment', 'memberBalance', 'memberEmailAddress', 'memberFile', 'memberLink', 'memberPayment', 'memberPhoneNumber', 'memberPhoto', 'memberPreferences', 'memberStatistic', 'memberRegistrationSignup', 'message', 'messageDatum', 'opponent', 'opponentResults', 'paymentNote', 'plan', 'registrationForm', 'smsGateway', 'sponsor', 'statistic', 'statisticAggregate', 'statisticDatum', 'statisticGroup', 'sport', 'team', 'teamFee', 'teamMedium', 'teamMediumComment', 'teamMediaGroup', 'teamPaypalPreferences', 'teamPhoto', 'teamPreferences', 'teamPublicSite', 'teamResults', 'teamStatistic', 'timeZone', 'trackedItem', 'trackedItemStatus']; + +teamTypes = types.slice(); + +teamTypes.remove = function(type) { + var index; + index = this.indexOf(type); + if (index !== -1) { + this.splice(index, 1); + } + return this; +}; + +teamTypes.remove('user').remove('plan').remove('smsGateway').remove('sport').remove('timeZone'); + +typeLookup = {}; + +singularLookup = {}; + +pluralLookup = { + memberPreferences: 'membersPreferences', + divisionMemberPreferences: 'divisionMembersPreferences', + divisionPreferences: 'divisionsPreferences', + opponentResults: 'opponentsResults', + statisticDatum: 'statisticData', + messageDatum: 'messageData', + teamMedium: 'teamMedia', + teamPaypalPreferences: 'teamsPaypalPreferences', + teamPreferences: 'teamsPreferences', + teamResults: 'teamsResults', + customDatum: 'customData', + leagueCustomDatum: 'leagueCustomData', + smsGateway: 'smsGateways' +}; + +for (i = 0, len = types.length; i < len; i++) { + type = types[i]; + plural = pluralLookup[type] || (function() { + switch (type.slice(-1)) { + case 'y': + return type.slice(0, -1) + 'ies'; + case 's': + return type + 'es'; + default: + return type + 's'; + } + })(); + typeLookup[type] = type; + typeLookup[plural] = type; + singularLookup[plural] = type; + pluralLookup[type] = plural; +} + +teamsnap.isPluralType = function(name) { + return singularLookup.hasOwnProperty(name); +}; + +teamsnap.isSingularType = function(name) { + return pluralLookup.hasOwnProperty(name); +}; + +teamsnap.hasType = function(type) { + return typeLookup[type] !== void 0; +}; + +teamsnap.getTypes = function() { + return types.slice(); +}; + +teamsnap.getTeamTypes = function() { + return teamTypes.slice(); +}; + +teamsnap.getPluralType = function(name) { + return pluralLookup[name]; +}; + +teamsnap.getSingularType = function(name) { + return singularLookup[name]; +}; + +teamsnap.getType = function(name) { + return typeLookup[name]; +}; + +teamsnap.camelcaseType = function(type) { + return type.replace(/[-_]+(\w)/g, function(_, char) { + return char.toUpperCase(); + }); +}; + +teamsnap.underscoreType = function(type) { + return type.replace(/[A-Z]/g, function(char) { + return '_' + char.toLowerCase(); + }); +}; + +}); + + +global['teamsnap'] = require('teamsnap'); +})(); \ No newline at end of file diff --git a/public/media/baseball-diamond.svg b/public/media/baseball-diamond.svg new file mode 100644 index 0000000..0b523a9 --- /dev/null +++ b/public/media/baseball-diamond.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/media/benchcoach.svg b/public/media/benchcoach.svg new file mode 100644 index 0000000..858d545 --- /dev/null +++ b/public/media/benchcoach.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 0000000..7fbbf0f --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,128 @@ +var express = require("express"); +var passport = require("passport"); +var TeamsnapStrategy = require("passport-teamsnap"); + +// Configure the TeamSnap strategy for use by Passport. +// +// OAuth 2.0-based strategies require a `verify` function which receives the +// credential (`accessToken`) for accessing the Facebook API on the user's +// behalf, along with the user's profile. The function must invoke `cb` +// with a user object, which will be set at `req.user` in route handlers after +// authentication. +passport.use( + new TeamsnapStrategy( + { + apiVersion: "3", + clientID: process.env["TEAMSNAP_CLIENT_ID"], + clientSecret: process.env["TEAMSNAP_CLIENT_SECRET"], + callbackURL: "/auth/teamsnap/callback", + passReqToCallback: true, + }, + function (req, accessToken, refreshToken, profile, done) { + json = JSON.parse(profile._raw); + new_profile = { access_token: accessToken }; + new_profile["id"] = json.collection.items[0].data.filter( + (e) => e.name == "id" + )[0].value; + new_profile["email"] = json.collection.items[0].data.filter( + (e) => e.name == "email" + )[0].value; + new_profile["first_name"] = json.collection.items[0].data.filter( + (e) => e.name == "first_name" + )[0].value; + console.log("LI#35 session is ", req.session); + console.log("LI#35 session id is ", req.session.id); + req.session.teamsnap_access_token = accessToken; + teamsnap.init(process.env["TEAMSNAP_CLIENT_ID"]); + teamsnap.auth(accessToken); + // teamsnap.enablePersistence(); + return done(null, new_profile); + } + ) +); + +// Configure Passport authenticated session persistence. +// +// In order to restore authentication state across HTTP requests, Passport needs +// to serialize users into and deserialize users out of the session. In a +// production-quality application, this would typically be as simple as +// supplying the user ID when serializing, and querying the user record by ID +// from the database when deserializing. However, due to the fact that this +// example does not have a database, the complete Facebook profile is serialized +// and deserialized. +passport.serializeUser(function (user, cb) { + process.nextTick(function () { + console.log("L#51 serializing user id", user.id); + cb(null, { + id: user.id, + username: user.email, + name: user.firstName, + accessToken: user.access_token, + }); + }); +}); + +passport.deserializeUser(function (user, cb) { + process.nextTick(function () { + return cb(null, user); + }); +}); + +var router = express.Router(); + +/* GET /login + * + * This route prompts the user to log in. + * + * The 'login' view renders an HTML page, which contain a button prompting the + * user to sign in with TeamSnap. When the user clicks this button, a request + * will be sent to the `GET /login/federated/teamsnap` route. + */ +router.get("/login", function (req, res, next) { + res.render("login"); +}); + +/* GET /login/federated/teamsnap + * + * This route redirects the user to TeamSnap, where they will authenticate. + * + * Signing in with TeamSnap is implemented using OAuth 2.0. This route initiates + * an OAuth 2.0 flow by redirecting the user to TeamSnap's identity server. + * Once there, TeamSnap will authenticate the user + * and obtain their consent to release identity information to this app. + * + * Once TeamSnap has completed their interaction with the user, the user will be + * redirected back to the app. + */ +router.get("/login/federated/teamsnap", passport.authenticate("teamsnap")); + +/* + This route completes the authentication sequence when TeamSnap redirects the + user back to the application. When a new user signs in, a user account is + automatically created and their TeamSnap account is linked. When an existing + user returns, they are signed in to their linked account. +*/ +router.get( + "/auth/teamsnap", + passport.authenticate("teamsnap", function (err, user, info, status) {}) +); + +router.get("/auth/teamsnap/callback", function (req, res, next) { + passport.authenticate("teamsnap", function (err, user, info, status) { + if (err) { + // do something with the error + console.error("error: ", err); + } + // success + console.log("L#105 user is ", user); + req.logIn(user, function (err) { + if (err) { + return next(err); + } + + return res.redirect("/"); + }); + })(req, res, next); +}); + +module.exports = router; diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..0bb96e9 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,390 @@ +var express = require("express"); +var ensureLogIn = require("connect-ensure-login").ensureLoggedIn; +var papaparse = require("papaparse"); + +var ensureLoggedIn = ensureLogIn(); + +var router = express.Router(); + +function authTeamsnap(user) { + if (!teamsnap.isAuthed()) { + teamsnap.init(process.env["TEAMSNAP_CLIENT_ID"]); + teamsnap.auth(user.accessToken); + } +} + +function availabilitiesSort(a, b) { + status_code_sort = [ + teamsnap.AVAILABILITIES.YES, + teamsnap.AVAILABILITIES.MAYBE, + teamsnap.AVAILABILITIES.NO, + teamsnap.AVAILABILITIES.NONE, + ]; + a_sort = status_code_sort.indexOf(a.statusCode); + b_sort = status_code_sort.indexOf(b.statusCode); + if (a_sort > b_sort) { + return 1; + } + if (a_sort < b_sort) { + return -1; + } + if (a_sort == b_sort) { + if (a.member.lastName < b.member.lastName) { + return -1; + } + if (a.member.lastName > b.member.lastName) { + return 1; + } + } +} + +async function fetch_stats(resolve, reject) { + url = + "https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv&gid={tab_id}"; + papaparse.Papa.parse(url, { + download: true, + complete: function (results) { + results.data.forEach((row, i) => { + if (i == 0 || row[2] == "Totals" || row[2] == "") { + return; + } + d = { + first_name: row[3], + last_name: row[2], + jersey_number: row[1], + pa: row[5], + ab: row[6], + avg: row[20], + obp: row[21], + slg: row[22], + }; + }); + resolve(d); + }, + }); +} + +/* GET home page. */ +router.get("/", ensureLoggedIn, function (req, res, next) { + if (req.user) { + authTeamsnap(req.user); + teamsnap.loadCollections(function (err) { + if (err) { + alert("Error loading TeamSnap SDK"); + return; + } + teamsnap.loadTeams(function onTeamsLoad(err, teams) { + teams = teams.sort((a, b) => b.seasonName - a.seasonName); + res.render("home", { req: req, teams: teams }); + }); + }); + } else { + res.render("home", { req: req }); + } +}); + +router.get( + "/teams", + ensureLoggedIn, + function (req, res, next) { + console.log("teamsnap authed?: ", teamsnap.isAuthed()); + console.log("user is", req.user); + + authTeamsnap(req.user); + teamsnap.loadCollections(function (err) { + if (err) { + alert("Error loading TeamSnap SDK"); + return; + } + teamsnap.loadTeams(function onTeamsLoad(err, teams) { + teams = teams.sort((a, b) => b.seasonName - a.seasonName); + res.render("teams", { teams: teams }); + }); + }); + + next(); + }, + function (req, res, next) { + // res.send(`${me.firstName} ${me.lastName}`); + } +); + +router.get("/:team_id([0-9]+)", ensureLoggedIn, function (req, res, next) { + authTeamsnap(req.user); + team_id = req.params.team_id; + console.log("team_id", team_id); + teamsnap.loadCollections(function (err) { + if (err) { + alert("Error loading TeamSnap SDK"); + return; + } + teamsnap.enablePersistence(); + + teamsnap.bulkLoad( + team_id, + ["team", "member", "event", "opponent", "availability_summary"], + function onBulkLoad(err, items) { + team = items.find((i) => (i.type == "team") & (i.id == team_id)); + console.log(team); + res.set("Content-Type", "text/html"); + res.render("team", { team: team }); + } + ); + }); +}); + +router.get( + "/:team_id/event/:event_id", + ensureLoggedIn, + function (req, res, next) { + authTeamsnap(req.user); + var team_id = req.params.team_id; + var event_id = req.params.event_id; + teamsnap.loadCollections(function (err) { + console.log(); + teamsnap.enablePersistence(); + + teamsnap.bulkLoad( + team_id, + ["team", "event", "availabilitySummary"], + function (err, items) { + if (err) { + res.code = 500; + res.send(err); + } + + availabilitySummaries = items.filter( + (i) => i.type == "availabilitySummary" && i.id == event_id + ); + events = items.filter((i) => i.type == "event" && i.id == event_id); + + if (events) { + event = events[0]; + availabilitySummary = availabilitySummaries[0]; + console.log("A_S", availabilitySummaries); + res.render("event", { + event: event, + team_id: team_id, + team: items.find((i) => i.type == "team" && i.id == team_id), + availabilitySummary: availabilitySummary, + }); + } else { + res.code = 500; + res.send("error"); + } + } + ); + }); + } +); + +router.get( + "/:team_id/event/:event_id/gamecard", + ensureLoggedIn, + function (req, res, next) { + authTeamsnap(req.user); + team_id = req.params.team_id; + event_id = req.params.event_id; + teamsnap.loadCollections((err) => { + teamsnap.enablePersistence(); + var events; + teamsnap + .bulkLoad(team_id, [ + "team", + "member", + // "member_photos", + "event", + "opponent", + "availability_summary", + ]) + .then((items) => { + events = items + .filter((i) => i.type == "event") + .sort((a, b) => a.startDate - b.startDate); + event = events.find((i) => i.id == event_id); + events_past = events.slice( + events.findIndex((e) => e == event) - 4, + events.findIndex((e) => e == event) + ); + events_future = events.slice( + events.findIndex((e) => e == event) + 1, + events.findIndex((e) => e == event) + 5 + ); + events = events_past.concat(event).concat(events_future); + }) + .then((items) => { + return teamsnap.loadAvailabilities({ + eventId: events.map((e) => e.id), + }); + }) + .then(() => { + return teamsnap.collections["eventLineups"] + .queryItems("search", { + eventId: events.map((e) => e.id), + }) + .then((event_lineups) => { + return Promise.all( + event_lineups.map((elu) => elu.loadItem("eventLineupEntries")) + ); + }); + }) + .then(() => { + items = teamsnap.getAllItems(); + events = items.filter((i) => i.type == "event"); + current_event_index = events.findIndex((e) => e.id == event_id); + + context = { + team_id: req.params.team_id, + event_id: req.params.event_id, + current_event_index: current_event_index, + events: items.filter((a) => a.type == "event"), + availabilitySummaries: items.filter( + (i) => i.type == "availabilitySummary" + ), + event: items.find((e) => e.type == "event" && e.id == event_id), + events_past: events_past, + events_future: events_future, + members: items.filter((a) => a.type == "member"), + availabilities: items + .filter((i) => i.type == "availability") + .sort(availabilitiesSort), + all_lineup_entries: items.filter( + (i) => i.type == "eventLineupEntry" + ), + event_lineup_entries_offense: items + .filter( + (i) => + i.type == "eventLineupEntry" && + i.eventId == event_id && + !i.label.includes("[PO]") + ) + .sort((a, b) => a.sequence - b.sequence), + event_lineup_entries: items + .filter( + (i) => i.type == "eventLineupEntry" && i.eventId == event_id + ) + .sort((a, b) => a.sequence - b.sequence), + }; + + res.render("gamecard", context); + }); + }); + } +); + +router.get( + "/:team_id/event/:event_id/lineup", + ensureLoggedIn, + function (req, res, next) { + authTeamsnap(req.user); + team_id = req.params.team_id; + event_id = req.params.event_id; + teamsnap.loadCollections((err) => { + teamsnap.enablePersistence(); + var events; + teamsnap + .bulkLoad(team_id, [ + "team", + "member", + // "member_photos", + "event", + "opponent", + "availability_summary", + ]) + .then((items) => { + events = items + .filter((i) => i.type == "event") + .sort((a, b) => a.startDate - b.startDate); + event = events.find((i) => i.id == event_id); + events_past = events.slice( + events.findIndex((e) => e == event) - 4, + events.findIndex((e) => e == event) + ); + events_future = events.slice( + events.findIndex((e) => e == event) + 1, + events.findIndex((e) => e == event) + 5 + ); + events = events_past.concat(event).concat(events_future); + }) + .then((items) => { + return teamsnap.loadAvailabilities({ + eventId: events.map((e) => e.id), + }); + }) + .then(() => { + return teamsnap.collections["eventLineups"] + .queryItems("search", { + eventId: events.map((e) => e.id), + }) + .then((event_lineups) => { + return Promise.all( + event_lineups.map((elu) => elu.loadItem("eventLineupEntries")) + ); + }); + }) + .then(() => { + items = teamsnap.getAllItems(); + events = items.filter((i) => i.type == "event"); + current_event_index = events.findIndex((e) => e.id == event_id); + + context = { + team_id: req.params.team_id, + event_id: req.params.event_id, + current_event_index: current_event_index, + events: items.filter((a) => a.type == "event"), + availabilitySummaries: items.filter( + (i) => i.type == "availabilitySummary" + ), + event: items.find((e) => e.type == "event" && e.id == event_id), + events_past: events_past, + events_future: events_future, + members: items.filter((a) => a.type == "member"), + availabilities: items + .filter((i) => i.type == "availability") + .sort(availabilitiesSort), + all_lineup_entries: items.filter( + (i) => i.type == "eventLineupEntry" + ), + event_lineup_entries_offense: items + .filter( + (i) => + i.type == "eventLineupEntry" && + i.eventId == event_id && + !i.label.includes("[PO]") + ) + .sort((a, b) => a.sequence - b.sequence), + event_lineup_entries: items + .filter( + (i) => i.type == "eventLineupEntry" && i.eventId == event_id + ) + .sort((a, b) => a.sequence - b.sequence), + }; + + res.render("lineup", context); + }); + }); + } +); + +router.get("/:team_id/events", ensureLoggedIn, function (req, res, next) { + authTeamsnap(req.user); + team_id = req.params.team_id; + event_id = req.params.event_id; + teamsnap.loadCollections(function (err) { + teamsnap + .bulkLoad(team_id, ["team", "event", "availability_summary"]) + .then((items) => { + res.set("Content-Type", "text/html"); + res.render("events", { + team: items.find((i) => i.type == "team" && i.id == team_id), + events: items.filter((i) => i.type == "event"), + availabilitySummaries: items.filter( + (i) => i.type == "availabilitySummary" + ), + team_id: team_id, + }); + }); + }); +}); + +module.exports = router; diff --git a/views/error.pug b/views/error.pug new file mode 100644 index 0000000..329d5b9 --- /dev/null +++ b/views/error.pug @@ -0,0 +1,8 @@ +html + head + body + h1 error + h2 + error.status + pre + message #{message} diff --git a/views/event.pug b/views/event.pug new file mode 100644 index 0000000..93d9dec --- /dev/null +++ b/views/event.pug @@ -0,0 +1,46 @@ +html + head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title #{event.formattedTitle} + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/font/bootstrap-icons.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + body + .container + .Panel + .Panel-header + h3.Panel-title #{event.formattedTitle} + .Panel-body + .Panel-row + h6.card-text.text-muted.mb-2 + |#{event.startDate} + br + |#{event.locationName} + .Panel-row + h4 Availability + .progress + div(class="progress-bar bg-success fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerGoingCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerGoingCount} + div(class="progress-bar bg-info fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerMaybeCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerMaybeCount} + div(class="progress-bar bg-danger fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerNotGoingCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerNotGoingCount} + div(class="progress-bar text-secondary fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerUnknownCount/team.playerMemberCount)*100).toString() + "%"}; + background-color: var(--bs-gray-200)`) + |#{availabilitySummary.playerUnknownCount} + hr + div.d-flex + a(class="Button m-auto" href=`/${team_id}/event/${event.id}/lineup`) + i(class="bi bi-clipboard") + span.mx-1 Lineup + a(class="Button m-auto" href=`/${team_id}/event/${event.id}/gamecard`) + i(class="bi bi-book") + span.mx-1 Game Card + a(class="Button m-auto" href=`https://go.teamsnap.com/${team_id}/schedule/view_game/${event.id}`) + i(class="bi bi-asterisk") + span.mx-1 TeamSnap \ No newline at end of file diff --git a/views/events.pug b/views/events.pug new file mode 100644 index 0000000..fda04df --- /dev/null +++ b/views/events.pug @@ -0,0 +1,37 @@ +html + head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title BenchCoach - Teams + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + body + .container + .Panel + .Panel-header + .Panel-title Schedule + .Panel-body + each event in events + - var availabilitySummary = availabilitySummaries.find((a)=>a.eventId==event.id) + .Panel-row + a(class="event list-group-item" href=`/${team_id}/event/${event.id}`) + h4 #{event.formattedTitle} + p.small + | #{event.startDate.toLocaleDateString("en-us",{weekday: "short", day: "numeric",month: "short"})} + | #{event.startDate.toLocaleTimeString("en-us",{hour: "numeric", minute: "2-digit"})} + p #{event.locationName} + .progress + div(class="progress-bar bg-success fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerGoingCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerGoingCount} + div(class="progress-bar bg-info fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerMaybeCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerMaybeCount} + div(class="progress-bar bg-danger fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerNotGoingCount/team.playerMemberCount)*100).toString() + "%"}`) + |#{availabilitySummary.playerNotGoingCount} + div(class="progress-bar text-secondary fw-bold" role="progressbar" style=` + width: ${((availabilitySummary.playerUnknownCount/team.playerMemberCount)*100).toString() + "%"}; + background-color: var(--bs-gray-200)`) + |#{availabilitySummary.playerUnknownCount} + diff --git a/views/gamecard.pug b/views/gamecard.pug new file mode 100644 index 0000000..9f98da7 --- /dev/null +++ b/views/gamecard.pug @@ -0,0 +1,409 @@ +html + head + meta(charset='utf-8') + title #{event.formattedTitle} + link(rel='stylesheet' href='/css/gamecard.css') + + body(class="B5") + input(name="team_id", type="hidden" value=`${team_id}`) + input(name="event_id", type="hidden" value=`${event_id}`) + #page-1.sheet.gamecard + section#todays-game + .grid-container + .section-header + #todays-game-header.bar-left.event-title + | #{event.formattedTitle} + | #{event.startDate.toLocaleDateString("en-us",{weekday: "short", day: "numeric",month: "short"})} + | #{event.startDate.toLocaleTimeString("en-us",{hour: "numeric", minute: "2-digit"})} + .bar-right.homeaway #{event.gameType} + .bar-span.gametitle + #offense-pane.left + table#starting-lineup-offense + tbody + each _, i in Array(11) + - if (typeof(event_lineup_entries_offense[i]) !== 'undefined'){ + tr + th(rowspan='2') #{i+1} + td(id=`offense-slot-${i}-name` class="player-name") #{event_lineup_entries_offense[i].member.lastName} + td(id=`offense-slot-${i}-jersey-number` class="jersey-number") #{event_lineup_entries_offense[i].member.jerseyNumber} + td(id=`offense-slot-${i}-position` class="position") #{event_lineup_entries_offense[i].label} + tr.substitute + td + td + td + - } else { + tr + th(rowspan='2') + td(id=`offense-slot-${i}-name` class="player-name") + td(id=`offense-slot-${i}-jersey-number` class="jersey-number") + td(id=`offense-slot-${i}-position` class="position") + tr.substitute + td + td + td + - } + + #defense-pane.right + .container + .field-container + image(src='/media/baseball-diamond.svg') + .row(style='justify-content: center') + .defense-slot-set + table + tr + th.position CF + td#defense-slot-CF-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("CF")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .row(style='justify-content: space-between') + .defense-slot-set + table + tr + th.position LF + td#defense-slot-LF-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("LF")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .defense-slot-set + table + tr + th.position RF + td#defense-slot-RF-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("RF")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .row(style='justify-content: space-around') + .defense-slot-set + table + tr + th.position SS + td#defense-slot-SS-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("SS")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .defense-slot-set + table + tr + th.position 2B + td#defense-slot-2B-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("2B")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .row(style='justify-content: space-between') + .defense-slot-set + table + tr + th.position 3B + td#defense-slot-3B-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("3B")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .defense-slot-set + table + tr + th.position 1B + td#defense-slot-1B-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("1B")) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .row(style='justify-content: center') + .defense-slot-set + table + tr + th.position C + td#defense-slot-C-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("C") && !lue.label.startsWith("CF") ) || {"member":{}}).member.lastName} + tr + td(colspan='2') + tr + td(colspan='2') + .pitching-container + .defense-slot-set + table + tr + th.position P + td#defense-slot-P-name.player-name + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("P")) || {"member":{}}).member.lastName} + td.jersey-number + | #{(event_lineup_entries.find((lue)=>lue.label.startsWith("P")) || {"member":{}}).member.jerseyNumber} + td.position + tr + th.position RP + td#defense-slot-RP1-name.player-name + td + td + tr + th.position RP + td#defense-slot-RP2-name.player-name + td + td + .footer + table + tr + th Notes + td + tr + td + tr + td + section#roster-and-history + div + table + thead + tr + th#today-availability(colspan='3') Available ( + | #{availabilitySummaries.find((e)=>e.id==event_id).playerGoingCount}| + | #{availabilitySummaries.find((e)=>e.id==event_id).playerMaybeCount} + | ) + th.player-stats + span.decimal-point . + | AVG + span.delimiter / + span.decimal-point . + | OBP + span.delimiter / + span.decimal-point . + | SLG + span.delimiter : + | PA + th.position-capability.pitcher P + th.position-capability.catcher C + th.position-capability.infield I + th.position-capability.outfield O + each event_future, i in events_future + th(id=`avail-header-today-plus-${i+1}` class="availability future") + .rotate #{event_future.startDate.toLocaleDateString("en-us", {weekday: "short"})} + each event_past, i in events_past + th(id=`avail-header-today-minus-${i+1}` class="availability past") + .rotate #{event_past.startDate.toLocaleDateString("en-us", {weekday: "short"})} + tbody + each row, index in availabilities.filter((e)=>e.event.id==event_id && !e.member.isNonPlayer) + tr(id=`roster-history-slot-${index+1}` class=``) + td(class=`is-present-checkbox available-status-code-${row.statusCode}`) + span ■ + td( + class=` + jersey-number + border-left + available-status-code-${row.statusCode} + ${event_lineup_entries.find((lue)=>lue.member.id==row.member.id) !== undefined ? "starting" : ""} + `) + | #{row.member.jerseyNumber} + td( + class=` + player-name + available-status-code-${row.statusCode} + ${event_lineup_entries.find((lue)=>lue.member.id==row.member.id) !== undefined ? "starting" : ""} + `) + | #{row.member.lastName} + td.player-stats.border-left.border-right + span.decimal-point . + span.avg 000 + span.delimiter / + span.decimal-point . + span.obp 000 + span.delimiter / + span.decimal-point . + span.slg 000 + span.delimiter : + span.pa 00 + td.position-capability.pitcher #{row.member.position.includes("P") ? "\u2713" : ""} + td.position-capability.catcher #{row.member.position.includes("C") ? "\u2713" : ""} + td.position-capability.infield #{row.member.position.includes("IF") ? "\u2713" : ""} + td.position-capability.outfield #{row.member.position.includes("OF") ? "\u2713" : ""} + - var future_availability + - var future_lineupEntry + each future_event, i in events_future + - future_availability = availabilities.find((el)=>el.eventId ==future_event.id && el.memberId==row.member.id) + - future_lineupEntry = all_lineup_entries.find((el)=>el.eventId ==future_event.id && el.member.id==row.member.id) + - console.log(future_availability) + td(id=`avail-${row.member}-today-plus-${i+1}` class=` + row + future + availability + available-status-code-${future_availability.statusCode} + `) + if future_lineupEntry + |#{future_lineupEntry.label.slice(0,2)} + else + |#{future_availability.status[0]} + - var past_availability + - var past_lineupEntry + each past_event, i in events_past + - past_availability = availabilities.find((el)=>el.eventId==past_event.id && el.memberId==row.memberId) + - past_lineupEntry = all_lineup_entries.find((el)=>el.event.id==past_event.id && el.member.id==row.member.id) + td(id=`avail-${row.member}-today-minus-${i+1}` class=` + row + past + availability + available-status-code-${past_availability.statusCode} + ${past_lineupEntry ? "started" : ""} + `) + if past_lineupEntry + |#{past_lineupEntry.label.slice(0,2)} + else + |#{past_availability.status[0]} + tfoot + tr + th(colspan='3') + th + th(colspan='4') + each event_future, i in events_future + th(class=`availability future`) + .rotate #{availabilitySummaries.find((el)=>el.eventId == event_future.id).playerGoingCount} + th.today-minus-1 + .rotate + th.today-minus-2 + .rotate + th.today-minus-3 + .rotate + th.today-minus-4 + .rotate + section#lineup-card-dugout.lineup-card + .grid-container + .section-header + .bar-left.event-title + | #{event.formattedTitle} + .bar-right.homeaway #{event.gameType} + .starting-lineup-table + table + thead + tr + th(colspan='4') Starting + tbody + each i in [0,1,2,3,4,5,6,7,8,9,10] + - if (typeof(event_lineup_entries_offense[i]) !== 'undefined'){ + tr + th.sequence.label #{event_lineup_entries_offense[i].sequence +1} + td.player-name #{event_lineup_entries_offense[i].member.lastName} + td.jersey-number #{event_lineup_entries_offense[i].member.jerseyNumber} + td.position #{event_lineup_entries_offense[i].label} + - } else { + tr + th.sequence.label + td.player-name + td.jersey-number + td.position + tr + td + td + td + td + - } + + .substitution-table + table(style='width: 100%') + thead + tr + th Substitution + tbody + each i in [0,1,2,3,4,5,6,7,8,9,10,11] + tr + td.substitution + tr + td.substitution + section#lineup-card-exchange.lineup-card + .grid-container + .section-header.event-title #{event.formattedTitleForMultiTeam} + .starting-lineup-table + table.starting-lineup-table + thead + tr + th + th.player-name Name + th.jersey-number Num + th.position Pos + tbody + each _,i in Array(10) + - if (typeof(event_lineup_entries_offense[i]) !== 'undefined'){ + tr + th.sequence.label #{event_lineup_entries_offense[i].sequence+1} + td.player-name #{event_lineup_entries_offense[i].member.lastName} + td.jersey-number #{event_lineup_entries_offense[i].member.jerseyNumber} + td.position #{event_lineup_entries_offense[i].label} + - } else { + tr + th.sequence.label + td.player-name + td.jersey-number + td.position + tr + td + td + td + td + - } + #page-2.sheet.gamecard + section#back-cover + section#front-cover + div.grid-container + .section-header + .bar-right.homeaway #{event.gameType} + .event-title + | #{event.startDate.toLocaleDateString("en-us",{weekday: "long", day: "numeric",month: "short"})}, + | #{event.startDate.toLocaleTimeString("en-us",{hour: "numeric", minute: "2-digit"})} + br + | #{event.locationName} + div.team + |#{event.team.name} + div.opponent + |#{event.opponent.name} + section#lineup-card-dugout-empty.lineup-card + .grid-container + .section-header + .starting-lineup-table + table + thead + tr + th(colspan='4') Starting + tbody + each _ in Array(12) + tr + th.sequence.label + td.player-name + td.jersey-number + td.position + .substitution-table + table(style='width: 100%') + thead + tr + th Substitution + tbody + each _ in Array(11) + tr + td.substitution + tr + td.substitution + section#lineup-card-exchange-empty.lineup-card + .grid-container + .section-header + .starting-lineup-table + table.starting-lineup-table + thead + tr + th + th.player-name Name + th.jersey-number Num + th.position Pos + tbody + each _ in Array(12) + tr + th.sequence.label + td.player-name + td.jersey-number + td.position diff --git a/views/home.pug b/views/home.pug new file mode 100644 index 0000000..e002492 --- /dev/null +++ b/views/home.pug @@ -0,0 +1,29 @@ +head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title BenchCoach - Home + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/css/project.css') +body.bg-light + .container + .row + .text-center.my-2 + .row + h1 + img.mx-auto(src="media/benchcoach.svg" style="width: 2.5em;") + .row + h1 + strong + | Welcome to + span.text-nowrap BenchCoach + .text-center.lead.fst-italic.fw-light + | An assistant coach for TeamSnap + .row + .col.text-center + if req.user + ul.list-group + each team in teams + a(class='team list-group-item' href=`/${team.id}`) #{team.name} [#{team.seasonName}] + else + a.btn.btn-outline-primary(href="login") + | Login \ No newline at end of file diff --git a/views/lineup.pug b/views/lineup.pug new file mode 100644 index 0000000..861e4d2 --- /dev/null +++ b/views/lineup.pug @@ -0,0 +1,139 @@ +html + head + meta(charset='utf-8') + title #{event.formattedTitle} + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/font/bootstrap-icons.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + + body.bg-light + .container + div(style="max-width: 455px") + .Panel + .panel-header + .Panel-title #{event.formattedTitle} + .Panel-body + .Panel-row + p.text-muted.mb-2 #{event.startDate} + p #{event.locationName} + .Panel + .Panel-body + .Panel-row.Panel-title.u-padXs + i.bi.bi-clipboard-check.me-1 + span Starting Lineup + .Panel-row.Grid.Grid--fit.fw-bold.text-center.u-padXs + each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"] + if event_lineup_entries.map((lue)=>lue.label).includes(pos) + .Grid-cell.text-success + |#{pos} + else + .Grid-cell.text-danger + |#{pos} + each lineup_entry, i in event_lineup_entries_offense + .Panel-row.Panel-row--withCells + .Panel-cell.Panel-cell--header.u-padXs.u-size1of12 + .u-flexAlignSelfCenter + |#{i+1} + .Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase + if lineup_entry.availabilityStatusCode == 2 + i.bi.bi-question-circle-fill.text-info.u-spaceRightXs + else if lineup_entry.availabilityStatusCode == 1 + i.bi.bi-check-circle-fill.text-success.u-spaceRightXs + else if lineup_entry.availabilityStatusCode == 0 + i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs + else + i.bi.bi-question-circle.u-spaceRightXs + |#{lineup_entry.member.lastName} + .Panel-cell.u-padXs.u-size2of12 + .SelectBox + select.SelectBox-options + each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"] + option(selected=lineup_entry.label==pos) #{pos} + .Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12 + .drag-handle + i.bi.bi-grip-vertical.text-secondary + .Panel + .Panel-body + .Panel-row.Panel-title.u-padXs + i.bi.bi-clipboard-minus.me-1 + span Starting Lineup (Position Only) + each lineup_entry, i in event_lineup_entries + if lineup_entry.label.includes("[PO]") + .Panel-row.Panel-row--withCells + .Panel-cell.Panel-cell--header.u-padXs.u-size1of12 + .u-flexAlignSelfCenter + |#{i+1} + .Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase + if lineup_entry.availabilityStatusCode == 2 + i.bi.bi-question-circle-fill.text-info.u-spaceRightXs + else if lineup_entry.availabilityStatusCode == 1 + i.bi.bi-check-circle-fill.text-success.u-spaceRightXs + else if lineup_entry.availabilityStatusCode == 0 + i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs + else + i.bi.bi-question-circle.u-spaceRightXs + |#{lineup_entry.member.lastName} + .Panel-cell.u-padXs.u-size2of12 + .SelectBox + select.SelectBox-options + each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"] + option(selected=lineup_entry.label==pos) #{pos} + .Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12 + .drag-handle + i.bi.bi-grip-vertical.text-secondary + .Panel + .Panel-body + .Panel-row.Panel-title.u-padXs + i.bi.bi-clipboard.me-1 + span Bench + each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && a.statusCode!=0 && a.statusCode!==null) + .Panel-row.Panel-row--withCells + .Panel-cell.Panel-cell--header.u-padXs.u-size1of12 + .u-flexAlignSelfCenter + .Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase + if availability.statusCode == 2 + i.bi.bi-question-circle-fill.text-info.u-spaceRightXs + else if availability.statusCode == 1 + i.bi.bi-check-circle-fill.text-success.u-spaceRightXs + else if availability.statusCode == 0 + i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs + else + i.bi.bi-question-circle.u-spaceRightXs + |#{availability.member.lastName} + .Panel-cell.u-padXs.u-size2of12 + .SelectBox + select.SelectBox-options + each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"] + option #{pos} + .Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12 + .drag-handle + i.bi.bi-grip-vertical.text-secondary + + .Panel + .Panel-body + .Panel-row.Panel-title.u-padXs + i.bi.bi-clipboard-x.me-1 + span Out + each availability, i in availabilities.filter((a)=>a.eventId==event_id && !context.event_lineup_entries.map((lue)=>lue.memberId).includes(a.memberId) && !a.member.isNonPlayer && (a.statusCode==0 || a.statusCode===null)) + .Panel-row.Panel-row--withCells + .Panel-cell.Panel-cell--header.u-padXs.u-size1of12 + .u-flexAlignSelfCenter + .Panel-cell.u-padXs.u-size8of12.fw-bold.text-uppercase + if availability.statusCode == 2 + i.bi.bi-question-circle-fill.text-info.u-spaceRightXs + else if availability.statusCode == 1 + i.bi.bi-check-circle-fill.text-success.u-spaceRightXs + else if availability.statusCode == 0 + i.bi.bi-x-circle-fill.text-danger.u-spaceRightXs + else + i.bi.bi-question-circle.u-spaceRightXs + |#{availability.member.lastName} + .Panel-cell.u-padXs.u-size2of12 + .SelectBox + select.SelectBox-options + each pos in ["P", "C", "1B", "2B", "3B", "SS", "LF", "CF", "RF", "EH", "DH"] + option #{pos} + .Panel-cell.u-padXs.u-flexAlignSelfCenter.u-size1of12 + .drag-handle + i.bi.bi-grip-vertical.text-secondary + diff --git a/views/login.pug b/views/login.pug new file mode 100644 index 0000000..8f48814 --- /dev/null +++ b/views/login.pug @@ -0,0 +1,19 @@ +html + head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title BenchCoach - Login + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/font/bootstrap-icons.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + body + .u-padSidesMd.u-xs-padSidesLg + .Panel.u-padLg + h3 BenchCoach + p Sign in + + a(class="Button Button--large Button--orange" href="/login/federated/teamsnap") + i(class="bi bi-asterisk")/ + span Sign in with TeamSnap + + diff --git a/views/team.pug b/views/team.pug new file mode 100644 index 0000000..d8ed89c --- /dev/null +++ b/views/team.pug @@ -0,0 +1,17 @@ +html + head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title BenchCoach - #{team.name} + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/font/bootstrap-icons.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + + body + .container + h2 #{team.name} + p #{team.seasonName} + hr + ul.list-group + a(class="list-group-item" href=`${team.id}/events`) Events + a(class="list-group-item" href=`${team.id}/roster`) Roster \ No newline at end of file diff --git a/views/teams.pug b/views/teams.pug new file mode 100644 index 0000000..29811b1 --- /dev/null +++ b/views/teams.pug @@ -0,0 +1,14 @@ +html + head + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1') + title BenchCoach - Teams + link(rel='stylesheet' href='/css/bootstrap.min.css') + link(rel='stylesheet' href='/font/bootstrap-icons.min.css') + link(rel='stylesheet' href='/css/teamsnap-ui.css') + + body + ul + each team in teams + li + a(class='team' href=`/${team.id}`) #{team.name} [#{team.seasonName}]