initial commit

This commit is contained in:
CaramelKat
2020-11-20 12:11:39 -06:00
parent 1a74f6cc5f
commit e8cc92ff96
48 changed files with 9966 additions and 0 deletions

906
package-lock.json generated Normal file
View File

@@ -0,0 +1,906 @@
{
"name": "juxt-web",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@oozcitak/dom": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.8.tgz",
"integrity": "sha512-MoOnLBNsF+ok0HjpAvxYxR4piUhRDCEWK0ot3upwOOHYudJd30j6M+LNcE8RKpwfnclAX9T66nXXzkytd29XSw==",
"requires": {
"@oozcitak/infra": "1.0.8",
"@oozcitak/url": "1.0.4",
"@oozcitak/util": "8.3.8"
}
},
"@oozcitak/infra": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
"integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
"requires": {
"@oozcitak/util": "8.3.8"
}
},
"@oozcitak/url": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
"integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
"requires": {
"@oozcitak/infra": "1.0.8",
"@oozcitak/util": "8.3.8"
}
},
"@oozcitak/util": {
"version": "8.3.8",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
"integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ=="
},
"@types/node": {
"version": "14.6.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz",
"integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A=="
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"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==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"async": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
"dev": true
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"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==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"bl": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
"requires": {
"bytes": "3.1.0",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"on-finished": "~2.3.0",
"qs": "6.7.0",
"raw-body": "2.4.0",
"type-is": "~1.6.17"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"bson": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz",
"integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg=="
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"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==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"dank-each": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dank-each/-/dank-each-1.0.0.tgz",
"integrity": "sha1-qGE0Okso02IgPUBcd4ZNyaZANzA=",
"dev": true
},
"dank-map": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dank-map/-/dank-map-0.1.0.tgz",
"integrity": "sha1-6Z5384LGjy5asrPzqCuAMZV1Kag=",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"denque": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"ejs": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
"integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
"dev": true,
"requires": {
"jake": "^10.6.1"
}
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
"requires": {
"accepts": "~1.3.7",
"array-flatten": "1.1.1",
"body-parser": "1.19.0",
"content-disposition": "0.5.3",
"content-type": "~1.0.4",
"cookie": "0.4.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.1.2",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.5",
"qs": "6.7.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.1.2",
"send": "0.17.1",
"serve-static": "1.14.1",
"setprototypeof": "1.1.1",
"statuses": "~1.5.0",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
}
},
"express-subdomain": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz",
"integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s=",
"dev": true
},
"filelist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
"dev": true,
"requires": {
"minimatch": "^3.0.4"
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
}
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs-extra": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"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=="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"jake": {
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
"dev": true,
"requires": {
"async": "0.9.x",
"chalk": "^2.4.2",
"filelist": "^1.0.1",
"minimatch": "^3.0.4"
}
},
"js-yaml": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
},
"dependencies": {
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
}
}
},
"kareem": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz",
"integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw=="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memory-cache": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"mongodb": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
"integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==",
"requires": {
"bl": "^2.2.1",
"bson": "^1.1.4",
"denque": "^1.4.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
},
"mongoose": {
"version": "5.10.14",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.14.tgz",
"integrity": "sha512-lG7TCyjGjVPM4R1HWCyWZbdK7hC4MdWRG7P95hDENXSvaLkGLiP7WZbGT83KzLY8+400x1p6C53UALD3MqpsCA==",
"requires": {
"bson": "^1.1.4",
"kareem": "2.3.1",
"mongodb": "3.6.3",
"mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.7.0",
"mquery": "3.2.2",
"ms": "2.1.2",
"regexp-clone": "1.0.0",
"safe-buffer": "5.2.1",
"sift": "7.0.1",
"sliced": "1.0.1"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"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=="
}
}
},
"mongoose-legacy-pluralize": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
},
"morgan": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
"integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
"requires": {
"basic-auth": "~2.0.1",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-finished": "~2.3.0",
"on-headers": "~1.0.2"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"mpath": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz",
"integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg=="
},
"mquery": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz",
"integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==",
"requires": {
"bluebird": "3.5.1",
"debug": "3.1.0",
"regexp-clone": "^1.0.0",
"safe-buffer": "5.1.2",
"sliced": "1.0.1"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"object-to-xml": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/object-to-xml/-/object-to-xml-2.0.0.tgz",
"integrity": "sha512-bArXy7WCF1V9R88/zF9adSZSeFQnFmmKhMqNuNLAxqrbkvzcWP8HgnaRCcVJsfvIgvpdHiYd0qzJi7LM7QFfcQ==",
"dev": true,
"requires": {
"dank-each": "^1.0.0",
"dank-map": "~0.1.0",
"sanitizer": "0.1.3"
}
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"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=="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
"requires": {
"forwarded": "~0.1.2",
"ipaddr.js": "1.9.1"
}
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"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=="
},
"raw-body": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
"integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
},
"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=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sanitizer": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/sanitizer/-/sanitizer-0.1.3.tgz",
"integrity": "sha1-1PCvdHXZp7ryqeWmEXGLqheKOeE=",
"dev": true
},
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
"requires": {
"debug": "2.6.9",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "~1.7.2",
"mime": "1.6.0",
"ms": "2.1.1",
"on-finished": "~2.3.0",
"range-parser": "~1.2.1",
"statuses": "~1.5.0"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"serve-static": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
"requires": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.17.1"
}
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"sift": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
"integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g=="
},
"sliced": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"xmlbuilder": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
"integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="
},
"xmlbuilder2": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.4.0.tgz",
"integrity": "sha512-KrOVUGD65xTQ7ZA+GMQGdBSpe1Ufu5ylCQSYVk6QostySDkxPmAQ0WWIu7dR3JjLfVbF22RFQX7KyrZ6VTLcQg==",
"requires": {
"@oozcitak/dom": "1.15.8",
"@oozcitak/infra": "1.0.8",
"@oozcitak/util": "8.3.8",
"@types/node": "14.6.2",
"js-yaml": "3.14.0"
}
}
}
}

20
package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "juxt-web",
"version": "1.0.0",
"dependencies": {
"colors": "^1.4.0",
"express": "^4.17.1",
"fs-extra": "^9.0.1",
"memory-cache": "^0.2.0",
"moment": "^2.29.1",
"mongoose": "^5.10.14",
"morgan": "^1.10.0",
"xmlbuilder": "^15.1.1",
"xmlbuilder2": "^2.4.0"
},
"devDependencies": {
"ejs": "^3.1.5",
"express-subdomain": "^1.0.5",
"object-to-xml": "^2.0.0"
}
}

14
src/config.example.json Normal file
View File

@@ -0,0 +1,14 @@
{
"http": {
"port": 80
},
"secret": "[Database Secret Key]",
"mongoose": {
"uri": "mongodb://localhost:27017",
"database": "[Database Name]",
"options": {
"useNewUrlParser": true,
"useUnifiedTopology": true
}
}
}

175
src/database.js Normal file
View File

@@ -0,0 +1,175 @@
const mongoose = require('mongoose');
const { mongoose: mongooseConfig } = require('./config.json');
const { TOPIC } = require('./models/topic');
const { ENDPOINT } = require('./models/endpoint');
const { COMMUNITY } = require('./models/communities');
const { POST } = require('./models/post');
const { USER } = require('./models/user');
const { uri, database, options } = mongooseConfig;
let connection;
async function connect() {
await mongoose.connect(`${uri}/${database}`, options);
connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error:'));
}
function verifyConnected() {
if (!connection) {
throw new Error('Cannot make database requets without being connected');
}
}
async function getTopicByName(topicName) {
verifyConnected();
if (typeof topicName !== 'string') {
return null;
}
return TOPIC.findOne({
name: topicName
});
}
async function getTopicByCommunityID(communityID) {
verifyConnected();
if (typeof communityID !== 'string') {
return null;
}
return TOPIC.findOne({
community_id: communityID
});
}
async function getCommunities(numberOfCommunities) {
verifyConnected();
return COMMUNITY.find({}).limit(numberOfCommunities);
}
async function getMostPopularCommunities(numberOfCommunities) {
verifyConnected();
return COMMUNITY.find({}).sort({followers: -1}).limit(numberOfCommunities);
}
async function getNewCommunities(numberOfCommunities) {
verifyConnected();
return COMMUNITY.find({}).sort([['created_at', -1]]).limit(numberOfCommunities);
}
async function getCommunityByTitleID(title_id) {
verifyConnected();
return COMMUNITY.findOne({
title_id: title_id
});
}
async function getCommunityByID(community_id) {
verifyConnected();
return COMMUNITY.findOne({
id: community_id
});
}
async function getNumberPostsByCommunity(community) {
verifyConnected();
return POST.find({
title_id: community.title_id
}).countDocuments();
}
async function getPostByID(postID) {
verifyConnected();
return POST.findOne({
id: postID
});
}
async function getPostsByUserID(userID) {
verifyConnected();
return POST.find({
pid: userID
});
}
async function getNumberPostsByUserID(userID) {
verifyConnected();
return POST.find({
pid: userID
}).countDocuments();
}
async function getHotPostsByCommunity(community, numberOfPosts) {
verifyConnected();
return POST.find({
title_id: community.title_id
}).sort({empathy_count: -1}).limit(numberOfPosts);
}
async function getPostsByCommunity(community, numberOfPosts) {
verifyConnected();
return POST.find({
title_id: community.title_id
}).limit(numberOfPosts);
}
async function getPostsByCommunityKey(community, numberOfPosts, search_key) {
verifyConnected();
return POST.find({
title_id: community.title_id,
search_key: search_key
}).limit(numberOfPosts);
}
async function getNewPostsByCommunity(community, numberOfPosts) {
verifyConnected();
return POST.find({
title_id: community.title_id
}).sort({ created_at: -1 }).limit(numberOfPosts);
}
async function getDiscoveryHosts() {
verifyConnected();
return ENDPOINT.findOne({
version: 1
});
}
async function getUserByPID(PID) {
verifyConnected();
return USER.findOne({
pid: PID
});
}
async function getServerConfig() {
verifyConnected();
return ENDPOINT.findOne({
type: "config"
});
}
module.exports = {
connect,
getCommunities,
getMostPopularCommunities,
getNewCommunities,
getCommunityByTitleID,
getCommunityByID,
getNumberPostsByCommunity,
getDiscoveryHosts,
getPostsByCommunity,
getHotPostsByCommunity,
getNewPostsByCommunity,
getPostsByCommunityKey,
getPostsByUserID,
getNumberPostsByUserID,
getPostByID,
getUserByPID,
};

52
src/logger.js Normal file
View File

@@ -0,0 +1,52 @@
const fs = require('fs-extra');
require('colors');
const root = __dirname;
fs.ensureDirSync(`${root}/logs`);
const streams = {
latest: fs.createWriteStream(`${root}/logs/latest.log`),
success: fs.createWriteStream(`${root}/logs/success.log`),
error: fs.createWriteStream(`${root}/logs/error.log`),
warn: fs.createWriteStream(`${root}/logs/warn.log`),
info: fs.createWriteStream(`${root}/logs/info.log`)
};
function success(input) {
const time = new Date();
input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [SUCCESS]: ${input}`;
streams.success.write(`${input}\n`);
console.log(`${input}`.green.bold);
}
function error(input) {
const time = new Date();
input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [ERROR]: ${input}`;
streams.error.write(`${input}\n`);
console.log(`${input}`.red.bold);
}
function warn(input) {
const time = new Date();
input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [WARN]: ${input}`;
streams.warn.write(`${input}\n`);
console.log(`${input}`.yellow.bold);
}
function info(input) {
const time = new Date();
input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [INFO]: ${input}`;
streams.info.write(`${input}\n`);
console.log(`${input}`.cyan.bold);
}
module.exports = {
success,
error,
warn,
info
};

View File

@@ -0,0 +1,38 @@
const xmlbuilder = require('xmlbuilder');
const VALID_CLIENT_ID_SECRET_PAIRS = {
// 'Key' is the client ID, 'Value' is the client secret
'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // Possibly WiiU exclusive?
'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0', // Possibly 3DS exclusive?
'ea25c66c26b403376b4c5ed94ab9cdea': 'd137be62cb6a2b831cad8c013b92fb55', // Possibly 3DS exclusive?
};
function nintendoClientHeaderCheck(request, response, next) {
response.set('Content-Type', 'text/xml');
response.set('Server', 'Nintendo 3DS (http)');
response.set('X-Nintendo-Date', new Date().getTime());
const {headers} = request;
if (
!headers['x-nintendo-client-id'] ||
!headers['x-nintendo-client-secret'] ||
!VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] ||
headers['x-nintendo-client-secret'] !== VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']]
) {
return response.send(xmlbuilder.create({
errors: {
error: {
cause: 'client_id',
code: '0004',
message: 'API application invalid or incorrect application credentials'
}
}
}).end());
}
return next();
}
module.exports = nintendoClientHeaderCheck;

50
src/middleware/pnid.js Normal file
View File

@@ -0,0 +1,50 @@
const xmlbuilder = require('xmlbuilder');
const database = require('../database');
async function PNIDMiddleware(request, response, next) {
const { headers } = request;
if (!headers.authorization || !(headers.authorization.startsWith('Bearer') || headers.authorization.startsWith('Basic'))) {
return next();
}
const [type, token] = headers.authorization.split(' ');
let user;
if (type === 'Basic') {
user = await database.getUserBasic(token);
} else {
user = await database.getUserBearer(token);
}
if (!user) {
response.status(401);
if (type === 'Bearer') {
return response.send(xmlbuilder.create({
errors: {
error: {
cause: 'access_token',
code: '0005',
message: 'Invalid access token'
}
}
}).end());
}
return response.send(xmlbuilder.create({
errors: {
error: {
code: '1105',
message: 'Email address, username, or password, is not valid'
}
}
}).end());
}
request.pnid = user;
return next();
}
module.exports = PNIDMiddleware;

23
src/middleware/session.js Normal file
View File

@@ -0,0 +1,23 @@
// super basic and there's probably a much better way to do this
// this will only be used during the registration process, to track the progress of the user
// express-session uses cookies which the WiiU does not support during the registration process
// temp, in-memory session storage
const sessionStore = {};
function sessionMiddlware(request, response, next) {
const ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
if (!sessionStore[ip]) {
sessionStore[ip] = {};
}
const session = sessionStore[ip];
request.session = session;
return next();
}
module.exports = sessionMiddlware;

View File

@@ -0,0 +1,35 @@
const { document: xmlParser } = require('xmlbuilder2');
function XMLMiddleware(request, response, next) {
if (request.method == 'POST' || request.method == 'PUT') {
const headers = request.headers;
let body = '';
if (
!headers['content-type'] ||
!headers['content-type'].toLowerCase().includes('xml')
) {
return next();
}
request.setEncoding('utf-8');
request.on('data', (chunk) => {
body += chunk;
});
request.on('end', () => {
try {
request.body = xmlParser(body);
request.body = request.body.toObject();
} catch (error) {
return next();
}
next();
});
} else {
next();
}
}
module.exports = XMLMiddleware;

64
src/models/communities.js Normal file
View File

@@ -0,0 +1,64 @@
const { Schema, model } = require('mongoose');
const CommunitySchema = new Schema({
created_at: {
type: Date,
},
empathy_count: {
type: Number,
default: 0
},
followers: {
type: Number,
default: 0
},
id: {
type: Number,
default: 0
},
has_shop_page: {
type: Number,
default: 0
},
icon: String,
title_ids: {
type: [String],
default: undefined
},
title_id: {
type: [String],
default: undefined
},
community_id: String,
is_recommended: {
type: Number,
default: 0
},
platform_id: Number,
name: String,
browser_icon: String,
CTR_browser_header: String,
WiiU_browser_header: String,
description: String,
});
CommunitySchema.methods.upEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy + 1);
await this.save();
};
CommunitySchema.methods.downEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy - 1);
await this.save();
};
const COMMUNITY = model('COMMUNITY', CommunitySchema);
module.exports = {
CommunitySchema,
COMMUNITY
};

27
src/models/endpoint.js Normal file
View File

@@ -0,0 +1,27 @@
const { Schema, model } = require('mongoose');
const endpointSchema = new Schema({
has_error: Number,
version: Number,
endpoint: {
host: String,
api_host: String,
portal_host: String,
n3ds_host: String
}
});
endpointSchema.methods.updateHosts = async function({host, api_host, portal_host, n3ds_host}) {
this.set('endpoint.host', host);
this.set('endpoint.api_host', api_host);
this.set('endpoint.portal_host', portal_host);
this.set('endpoint.n3ds_host', n3ds_host);
await this.save();
};
const ENDPOINT = model('ENDPOINT', endpointSchema);
module.exports = {
endpointSchema,
ENDPOINT
};

103
src/models/post.js Normal file
View File

@@ -0,0 +1,103 @@
const { Schema, model } = require('mongoose');
//just testing pull requests
const PostSchema = new Schema({
title_id: String,
screen_name: String,
body: String,
app_data: String,
painting: String,
painting_uri: String,
screenshot: String,
url: String,
search_key: {
type: [String],
default: undefined
},
topic_tag: {
type: [String],
default: undefined
},
community_id: String,
country_id: Number,
created_at: String,
feeling_id: Number,
id: Number,
is_autopost: {
type: Number,
default: 0
},
is_community_private_autopost: {
type: Number,
default: 0
},
is_spoiler: {
type: Number,
default: 0
},
is_app_jumpable: {
type: Number,
default: 0
},
empathy_count: {
type: Number,
default: 0
},
language_id: {
type: Number,
default: 1
},
mii: String,
mii_face_url: String,
number: {
type: Number,
default: 1
},
pid: Number,
platform_id: Number,
region_id: Number,
parent_post: Number,
reply_count: {
type: Number,
default: 0
},
verified: {
type: Boolean,
default: false
}
});
PostSchema.methods.upEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy + 1);
await this.save();
};
PostSchema.methods.downEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy - 1);
await this.save();
};
PostSchema.methods.upReply = async function() {
const replyCount = this.get('reply_count');
this.set('reply_count', replyCount + 1);
await this.save();
};
PostSchema.methods.downReply = async function() {
const replyCount = this.get('reply_count');
this.set('reply_count', replyCount - 1);
await this.save();
};
const POST = model('POST', PostSchema);
module.exports = {
PostSchema,
POST
};

79
src/models/topic.js Normal file
View File

@@ -0,0 +1,79 @@
const { Schema, model } = require('mongoose');
const { PostSchema } = require('./post');
const titleIdsSchema = new Schema({
title_id: String,
});
const personSchema = new Schema({
posts: {
type: [PostSchema],
default: undefined
}
});
const TopicSchema = new Schema({
empathy_count: {
type: Number,
default: 0
},
has_shop_page: {
type: Number,
default: 0
},
icon: String,
title_ids: {
type: [titleIdsSchema],
default: undefined
},
title_id: String,
community_id: String,
is_recommended: {
type: Number,
default: 0
},
name: String,
people: {
type: [personSchema],
default: undefined
},
});
TopicSchema.methods.upEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy + 1);
await this.save();
};
TopicSchema.methods.downEmpathy = async function() {
const empathy = this.get('empathy_count');
this.set('empathy_count', empathy - 1);
await this.save();
};
TopicSchema.pre('save', async function(next) {
if (!this.isModified('password')) {
return next();
}
this.set('usernameLower', this.get('username').toLowerCase());
await this.generatePID();
await this.generateNEXPassword();
await this.generateEmailValidationCode();
await this.generateEmailValidationToken();
const primaryHash = util.nintendoPasswordHash(this.get('password'), this.get('pid'));
const hash = bcrypt.hashSync(primaryHash, 10);
this.set('password', hash);
next();
});
const MiiverseTopic = model('MiiverseTopic', PostSchema);
module.exports = {
TopicSchema,
MiiverseTopic
};

152
src/models/user.js Normal file
View File

@@ -0,0 +1,152 @@
const { Schema, model } = require('mongoose');
const UserSchema = new Schema({
pid: Number,
created_at: String,
user_id: String,
birthday: Date,
country: String,
pfp_uri: String,
mii: String,
/**
* Account Status
* 0 - Fine
* 1 - Limited from Posting
* 2 - Temporary Ban
* 3 - Forever Ban
*/
account_status: {
type: Number,
default: 0
},
ban_lift_date: Date,
official: {
type: Boolean,
default: false
},
favorite_communities: {
type: [String],
default: undefined
},
profile_comment: {
type: String,
default: undefined
},
/**
* Game Skill Level
* 1 - Beginner
* 2 - Intermediate
* 3 - Expert
*/
game_skill: {
type: Number,
default: 0
},
/**
* Profile Visibility settings
* 1 - Everyone
* 2 - Friends Only
* 3 - Private
*/
game_skill_visibility: {
type: Number,
default: 1
},
profile_comment_visibility: {
type: Number,
default: 1
},
birthday_visibility: {
type: Number,
default: 3
},
relationship_visibility: {
type: Number,
default: 2
},
profile_favorite_community_visibility: {
type: Number,
default: 1
}
});
UserSchema.methods.getAccountStatus = async function() {
return this.get('account_status');
};
UserSchema.methods.setAccountStatus = async function(accountStatus) {
this.set('account_status', accountStatus);
await this.save();
};
UserSchema.methods.getBanDate = async function() {
return this.get('ban_lift_date');
};
UserSchema.methods.setBanData = async function(banDate) {
this.set('ban_lift_date', banDate);
await this.save();
};
UserSchema.methods.getProfileComment = async function() {
return this.get('profile_comment');
};
UserSchema.methods.setProfileComment = async function(profileComment) {
this.set('profile_comment', profileComment);
await this.save();
};
UserSchema.methods.getGameSkill = async function() {
return this.get('game_skill');
};
UserSchema.methods.setGameSkill = async function(gameSkill) {
this.set('game_skill', gameSkill);
await this.save();
};
UserSchema.methods.getGameSkillVisibility = async function() {
return this.get('game_skill_visibility');
};
UserSchema.methods.setGameSkillVisibility = async function(gameSkillVisibility) {
this.set('game_skill_visibility', gameSkillVisibility);
await this.save();
};
UserSchema.methods.getProfileCommentVisibility = async function() {
return this.get('profile_comment_visibility');
};
UserSchema.methods.setProfileCommentVisibility = async function(profileCommentVisibility) {
this.set('profile_comment_visibility', profileCommentVisibility);
await this.save();
};
UserSchema.methods.getBirthdayVisibility = async function() {
return this.get('birthday_visibility');
};
UserSchema.methods.setBirthdayVisibility = async function(birthdayVisibility) {
this.set('birthday_visibility', birthdayVisibility);
await this.save();
};
UserSchema.methods.getRelationshipVisibility = async function() {
return this.get('relationship_visibility');
};
UserSchema.methods.setRelationshipVisibility = async function(accountStatus) {
this.set('relationship_visibility', accountStatus);
await this.save();
};
UserSchema.methods.getFavoriteCommunityVisibility = async function() {
return this.get('profile_favorite_community_visibility');
};
UserSchema.methods.setFavoriteCommunityVisibility = async function(favoriteCommunityVisibility) {
this.set('profile_favorite_community_visibility', favoriteCommunityVisibility);
await this.save();
};
const USER = model('USER', UserSchema);
module.exports = {
UserSchema,
USER
};

64
src/server.js Normal file
View File

@@ -0,0 +1,64 @@
process.title = 'Pretendo - Miiverse';
const express = require('express');
const morgan = require('morgan');
const ejs = require('ejs');
const xmlparser = require('./middleware/xml-parser');
const database = require('./database');
const logger = require('./logger');
const config = require('./config.json');
const { http: { port } } = config;
const app = express();
const juxt_web = require('./services/juxt-web');
app.set('etag', false);
app.disable('x-powered-by');
app.set('view engine', 'ejs');
app.set('views', __dirname + '\\views');
// Create router
logger.info('Setting up Middleware');
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: true,
limit: '5mb',
parameterLimit: 100000
}));
app.use(xmlparser);
// import the servers into one
app.use(juxt_web);
// 404 handler
logger.info('Creating 404 status handler');
app.use((request, response) => {
//logger.warn(request.protocol + '://' + request.get('host') + request.originalUrl);
response.status(404);
response.send();
});
// non-404 error handler
logger.info('Creating non-404 status handler');
app.use((error, request, response) => {
const status = error.status || 500;
response.status(status);
response.json({
app: 'api',
status,
error: error.message
});
});
// Starts the server
logger.info('Starting server');
database.connect().then(() => {
app.listen(port, () => {
logger.success(`Server started on port ${port}`);
});
});

View File

@@ -0,0 +1,27 @@
const express = require('express');
const subdomain = require('express-subdomain');
const logger = require('../../logger');
const routes = require('./routes');
const router = express.Router();
const portal = express.Router();
const ctr = express.Router();
// Create subdomains
logger.info('[JUXT-WEB] Creating \'Wii U\' subdomain');
router.use(subdomain('portal.olv', portal));
logger.info('[JUXT-WEB] Creating \'3DS\' subdomain');
router.use(subdomain('ctr.olv', ctr));
// Setup routes
portal.use('/titles/show', routes.PORTAL_SHOW);
portal.use('/communities', routes.PORTAL_COMMUNITIES);
portal.use('/', routes.PORTAL_WEB);
ctr.use('/titles/show', routes.CTR_SHOW);
ctr.use('/communities', routes.CTR_COMMUNITIES);
ctr.use('/', routes.CTR_WEB);
module.exports = router;

View File

@@ -0,0 +1,62 @@
var express = require('express');
var xml = require('object-to-xml');
const database = require('../../../../database');
//const util = require('../../../../util/authentication');
const ejs = require('ejs');
var router = express.Router();
/* GET discovery server. */
router.get('/', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
database.connect().then(async e => {
let popularCommunities = await database.getMostPopularCommunities(9);
let newCommunities = await database.getNewCommunities(6);
res.render('ctr_communities.ejs', {
// EJS variable and server-side variable
popularCommunities: popularCommunities,
newCommunities: newCommunities
});
}).catch(error => {
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
router.get('/*/new', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
let community_id = req.originalUrl.replace('/communities/', '').replace('/new','').trim();
database.connect().then(async e => {
let community = await database.getCommunityByID(community_id);
let newPosts = await database.getPostsByCommunity(community, 25);
res.render('ctr_community.ejs', {
// EJS variable and server-side variable
community: community,
newPosts: newPosts
});
}).catch(error => {
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
module.exports = router;

View File

@@ -0,0 +1,35 @@
var express = require('express');
var xml = require('object-to-xml');
const database = require('../../../../database');
//const util = require('../../../../util/authentication');
const ejs = require('ejs');
var router = express.Router();
/* GET discovery server. */
router.get('/', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
database.connect().then(async e => {
let popularCommunities = await database.getMostPopularCommunities(9);
let newCommunities = await database.getNewCommunities(6);
res.render('ctr_show.ejs', {
// EJS variable and server-side variable
popularCommunities: popularCommunities,
newCommunities: newCommunities
});
}).catch(error => {
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
module.exports = router;

View File

@@ -0,0 +1,22 @@
var express = require('express');
var router = express.Router();
var path = require('path');
/* GET discovery server. */
router.get('/css/juxt.css', function (req, res) {
res.sendFile('css/juxt.css', {root: path.join(__dirname, '../../../../webfiles/ctr/')});
});
router.get('/js/juxt.js', function (req, res) {
res.sendFile('js/juxt.js', {root: path.join(__dirname, '../../../../webfiles/ctr/')});
});
router.get('/icons/Icon-feather-search.svg', function (req, res) {
res.sendFile('icons/Icon-feather-search.svg', {root: path.join(__dirname, '../../../../webfiles/ctr/')})
});
router.get('/icons/mario-kart.jpg', function (req, res) {
res.sendFile('icons/mario-kart.jpg', {root: path.join(__dirname, '../../../../webfiles/ctr/')});
});
module.exports = router;

View File

@@ -0,0 +1,8 @@
module.exports = {
PORTAL_SHOW: require('./portal/show'),
PORTAL_WEB: require('./portal/web'),
PORTAL_COMMUNITIES: require('./portal/communities'),
CTR_SHOW: require('./ctr/show'),
CTR_WEB: require('./ctr/web'),
CTR_COMMUNITIES: require('./ctr/communities'),
};

View File

@@ -0,0 +1,89 @@
var express = require('express');
var xml = require('object-to-xml');
const database = require('../../../../database');
//const util = require('../../../../util/authentication');
const ejs = require('ejs');
var router = express.Router();
/* GET discovery server. */
router.get('/', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
var isAJAX = ((req.query.ajax+'').toLowerCase() === 'true')
database.connect().then(async e => {
let popularCommunities = await database.getMostPopularCommunities(9);
let newCommunities = await database.getNewCommunities(6);
if(isAJAX) {
res.render('portal_communities_ajax.ejs', {
// EJS variable and server-side variable
popularCommunities: popularCommunities,
newCommunities: newCommunities
});
}
else {
res.render('portal_communities.ejs', {
// EJS variable and server-side variable
popularCommunities: popularCommunities,
newCommunities: newCommunities
});
}
}).catch(error => {
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
router.get('/*/new', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
let community_id = req.originalUrl.replace('/communities/', '').replace('/new','').trim();
var isAJAX = ((req.query.ajax+'').toLowerCase() === 'true')
if(isAJAX)
community_id = community_id.substring(0, community_id.indexOf('?'));
database.connect().then(async e => {
let community = await database.getCommunityByID(community_id.substring(0, community_id));
let newPosts = await database.getNewPostsByCommunity(community, 100);
let totalNumPosts = await database.getNumberPostsByCommunity(community);
if(isAJAX) {
res.render('portal_community_ajax.ejs', {
// EJS variable and server-side variable
community: community,
newPosts: newPosts,
totalNumPosts: totalNumPosts
});
}
else {
res.render('portal_community.ejs', {
// EJS variable and server-side variable
community: community,
newPosts: newPosts,
totalNumPosts: totalNumPosts
});
}
}).catch(error => {
console.error(error);
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
module.exports = router;

View File

@@ -0,0 +1,35 @@
var express = require('express');
var xml = require('object-to-xml');
const database = require('../../../../database');
//const util = require('../../../../util/authentication');
const ejs = require('ejs');
var router = express.Router();
/* GET discovery server. */
router.get('/', function (req, res) {
res.header('X-Nintendo-WhiteList','1|http,youtube.com,,2|https,youtube.com,,2|http,.youtube.com,,2|https,.youtube.com,,2|http,.ytimg.com,,2|https,.ytimg.com,,2|http,.googlevideo.com,,2|https,.googlevideo.com,,2|https,youtube.com,/embed/,6|https,youtube.com,/e/,6|https,youtube.com,/v/,6|https,www.youtube.com,/embed/,6|https,www.youtube.com,/e/,6|https,www.youtube.com,/v/,6|https,youtube.googleapis.com,/e/,6|https,youtube.googleapis.com,/v/,6|http,maps.googleapis.com,/maps/api/streetview,2|https,maps.googleapis.com,/maps/api/streetview,2|http,cbk0.google.com,/cbk,2|https,cbk0.google.com,/cbk,2|http,cbk1.google.com,/cbk,2|https,cbk1.google.com,/cbk,2|http,cbk2.google.com,/cbk,2|https,cbk2.google.com,/cbk,2|http,cbk3.google.com,/cbk,2|https,cbk3.google.com,/cbk,2|https,.cloudfront.net,,2|https,www.google-analytics.com,/,2|https,stats.g.doubleclick.net,,2|https,www.google.com,/ads/,2|https,ssl.google-analytics.com,,2|http,fonts.googleapis.com,,2||fonts.googleapis.com,,2');
database.connect().then(async e => {
let popularCommunities = await database.getMostPopularCommunities(9);
let newCommunities = await database.getNewCommunities(6);
res.render('portal_show.ejs', {
// EJS variable and server-side variable
popularCommunities: popularCommunities,
newCommunities: newCommunities
});
}).catch(error => {
res.set("Content-Type", "application/xml");
res.statusCode = 400;
response = {
result: {
has_error: 1,
version: 1,
code: 400,
error_code: 15,
message: "SERVER_ERROR"
}
};
res.send("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml(response));
});
});
module.exports = router;

View File

@@ -0,0 +1,22 @@
var express = require('express');
var router = express.Router();
var path = require('path');
/* GET discovery server. */
router.get('/css/juxt.css', function (req, res) {
res.sendFile('css/juxt.css', {root: path.join(__dirname, '../../../../webfiles/portal/')});
});
router.get('/js/juxt.js', function (req, res) {
res.sendFile('js/juxt.js', {root: path.join(__dirname, '../../../../webfiles/portal/')});
});
router.get('/icons/Icon-feather-search.svg', function (req, res) {
res.sendFile('icons/Icon-feather-search.svg', {root: path.join(__dirname, '../../../../webfiles/portal/')})
});
router.get('/icons/mario-kart.jpg', function (req, res) {
res.sendFile('icons/mario-kart.jpg', {root: path.join(__dirname, '../../../../webfiles/portal/')});
});
module.exports = router;

View File

@@ -0,0 +1,74 @@
<div class="top-screen">
<div class="header-description">
<p>
Check out the communities for the games that you play or games that you're curious about!
</p>
</div>
<div id="headers-communities-icon" class="header-icon"></div>
<h2 class="header-title">Communities</h2>
</div>
<div class="bottom-screen">
<div class="search-container">
<div id="search-icon"></div>
<input id="search-bar" type="text" placeholder="Search communities..." name="search" onclick="searchCommunities(this)" readonly>
</div>
<div class="communities-wrapper" id="popular-communities">
<h1 class="communities-header">Popular Places</h1>
<table>
<tbody>
<% for(var i = 0; i < popularCommunities.length; i++) {%>
<% if(i === popularCommunities.length - 1) { %>
<tr>
<td>
<div class="community-wrapper bottom" id="<%= popularCommunities[i].id %>">
<img class="community-icon bottom" src="<%= popularCommunities[i].browser_icon %>">
<h2 class="community-title"><%= popularCommunities[i].name %></h2>
<h4><%= popularCommunities[i].followers %> followers</h4>
</div>
</td>
</tr>
<% } else { %>
<tr>
<td>
<div class="community-wrapper" id="<%= popularCommunities[i].id %>">
<img class="community-icon" src="<%= popularCommunities[i].browser_icon %>">
<h2 class="community-title"><%= popularCommunities[i].name %></h2>
<h4><%= popularCommunities[i].followers %> followers</h4>
</div>
</td>
</tr>
<% }} %>
</tbody>
</table>
</div>
<div class="communities-wrapper" id="new-communities">
<h1 class="communities-header">New Communities</h1>
<table>
<tbody>
<% for(var j = 0; j < newCommunities.length; j++) {%>
<% if(j === newCommunities.length - 1) { %>
<tr>
<td>
<div class="community-wrapper bottom" id="<%= popularCommunities[i].id %>">
<img class="community-icon bottom" src="<%= newCommunities[j].browser_icon %>">
<h2 class="community-title"><%= newCommunities[j].name %></h2>
<h4><%= newCommunities[j].followers %> followers</h4>
</div>
</td>
</tr>
<% } else { %>
<tr>
<td>
<div class="community-wrapper" id="<%= popularCommunities[i].id %>">
<img class="community-icon" src="<%= newCommunities[j].browser_icon %>">
<h2 class="community-title"><%= newCommunities[j].name %></h2>
<h4><%= newCommunities[j].followers %> followers</h4>
</div>
</td>
</tr>
<% }} %>
</tbody>
</table>
</div>
<div class="toolbar-padding"></div>
</div>

16
src/views/ctr_show.ejs Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3DS Testing</title>
<script src="/js/juxt.js"></script>
<link rel="stylesheet" type="text/css" href="/css/juxt.css">
<link href="https://fonts.googleapis.com/css2?family=Poppins&amp;display=swap" rel="stylesheet">
</head>
<body>
<div id="main">
</div>
<body onload="onStart()"></body>
</body>
</html>

12
src/views/index.ejs Normal file
View File

@@ -0,0 +1,12 @@
<html lang="en">
<body>
<h2>Testing dynamic stuff</h2>
<% listnames.forEach(function(person) { %>
<% if(person.alive) { %>
<p><%= person.name %></p>
<p><%= person.age %></p>
<br>
<% } %>
<% }); %>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/juxt.css">
<script src="/js/juxt.js"></script>
</head>
<body>
<menu id="nav-bar" class="">
<li id="nav-bar-profile" class="" onclick="loadTab('nav-bar-profile')"><a>User Page</a></li>
<li id="nav-bar-activity-feed" class="" onclick="loadTab('nav-bar-activity-feed')"><a>Activity Feed</a></li>
<li id="nav-bar-communities" class="selected" onclick="loadTab('nav-bar-communities')"><a>Communities</a></li>
<li id="nav-bar-messages" class="" onclick="loadMessagesTab();"><a>Messages<span id="messages-badge" class="badge" style=""></span></a></li>
<li id="nav-bar-news" class="" onclick="loadTab('nav-bar-news')"><a>Notifications<span id="news-badge" class="badge" style=""></span></a></li >
<li id="nav-bar-exit" class="" onclick="exit()"><a href="">Close</a></li>
<li id="nav-bar-back" class="none"><a href="">Back</a></li>
</menu>
<div id="main">
<h1 class="page-header">Communities</h1>
<div class="search-container">
<form action="/action_page.php">
<img id="search-icon" src="/icons/Icon-feather-search.svg"></img>
<input id="search-bar" type="text" placeholder="Search communities..." name="search">
</form>
</div>
<div id="popular" class="communities-wrapper">
<h1 class="communities-header">Popular Places</h1>
<table>
<tbody>
<tr>
<% for(var i = 0; i < popularCommunities.length; i++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= popularCommunities[i].id %>')">
<img class="community-list-icon" src="<%= popularCommunities[i].browser_icon %>">
<h2 class="community-list-title"><%= popularCommunities[i].name %></h2>
<h4 class="community-list-followers"><%= popularCommunities[i].followers %> followers</h4>
</div>
</td>
<% if( (i + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
<div id="new" class="communities-wrapper">
<h1 class="communities-header">New communities</h1>
<table>
<tbody>
<tr>
<% for(var j = 0; j < newCommunities.length; j++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= newCommunities[j].id %>')">
<img class="community-list-icon" src="<%= newCommunities[j].browser_icon %>">
<h2 class="community-list-title"><%= newCommunities[j].name %></h2>
<h4 class="community-list-followers"><%= newCommunities[j].followers %> followers</h4>
</div>
</td>
<% if( (j + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
</div>
<body onload="stopLoading()">
</body>
</html>

View File

@@ -0,0 +1,52 @@
<h1 class="page-header">Communities</h1>
<div class="search-container">
<form action="/action_page.php">
<img id="search-icon" src="/icons/Icon-feather-search.svg"></img>
<input id="search-bar" type="text" placeholder="Search communities..." name="search">
</form>
</div>
<div id="popular" class="communities-wrapper">
<h1 class="communities-header">Popular Places</h1>
<table>
<tbody>
<tr>
<% for(var i = 0; i < popularCommunities.length; i++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= popularCommunities[i].id %>')">
<img class="community-list-icon" src="<%= popularCommunities[i].browser_icon %>">
<h2 class="community-list-title"><%= popularCommunities[i].name %></h2>
<h4 class="community-list-followers"><%= popularCommunities[i].followers %> followers</h4>
</div>
</td>
<% if( (i + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
<div id="new" class="communities-wrapper">
<h1 class="communities-header">New communities</h1>
<table>
<tbody>
<tr>
<% for(var j = 0; j < newCommunities.length; j++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= newCommunities[j].id %>')">
<img class="community-list-icon" src="<%= newCommunities[j].browser_icon %>">
<h2 class="community-list-title"><%= newCommunities[j].name %></h2>
<h4 class="community-list-followers"><%= newCommunities[j].followers %> followers</h4>
</div>
</td>
<% if( (j + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
<img src="" onerror="wiiuBrowser.showLoadingIcon(!1)">

View File

@@ -0,0 +1,133 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/juxt.css">
<script src="/js/juxt.js"></script>
</head>
<body>
<menu id="nav-bar" class="">
<li id="nav-bar-profile" class="" onclick="loadTab('nav-bar-profile')"><a>User Page</a></li>
<li id="nav-bar-activity-feed" class="" onclick="loadTab('nav-bar-activity-feed')"><a>Activity Feed</a></li>
<li id="nav-bar-communities" class="selected" onclick="loadTab('nav-bar-communities')"><a>Communities</a></li>
<li id="nav-bar-messages" class="" onclick="loadMessagesTab();"><a>Messages<span id="messages-badge" class="badge" style=""></span></a></li>
<li id="nav-bar-news" class="" onclick="loadTab('nav-bar-news')"><a>Notifications<span id="news-badge" class="badge" style=""></span></a></li >
<li id="nav-bar-exit" class="" onclick="exit()"><a href="">Close</a></li>
<li id="nav-bar-back" class="none"><a href="">Back</a></li>
</menu>
<div id="main">
<div class="community-page-header" style="background-image: <%= community.WiiU_browser_header %>"></div>
<div class="community-page-header-overlay"></div>
<div class="community-page-back-button" onclick="loadTab('nav-bar-communities')"></div>
<div class="community-page-info-container">
<div class="community-page-follow-button-wrapper" onclick="window.location.reload(false)"></div>
<img class="community-page-info-icon" src="<%= community.browser_icon %>">
<h2 class="community-page-title"><%= community.name %></h2>
<h4 class="community-page-description"><%= community.description %></h4>
<div class="community-page-margin-line"></div>
<table class="community-page-table-wrapper">
<tbody>
<tr>
<td>
<div class="community-page-shaded-info-container">
<h4 class="community-page-table-label">Followers</h4>
<h4 class="community-page-table-text"><%= community.followers %></h4>
</div>
</td>
<td>
<div class="community-page-shaded-info-container">
<h4 class="community-page-table-label">Posts</h4>
<h4 class="community-page-table-text"><%=totalNumPosts%></h4>
</div>
</td>
<td>
<div class="community-page-shaded-info-container" style="width: 500px;">
<h4 class="community-page-table-label">Tags</h4>
<h4 class="community-page-table-text">N/A</h4>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="community-page-posts-wrapper">
<table class="community-page-posts-header">
<tbody>
<tr>
<td>
<h4 id="recent-tab" onclick="loadPosts(0)" class="community-page-posts-header-tab active">Recent posts</h4>
</td>
<td>
<h4 id="popular-tab" onclick="loadPosts(1)" class="community-page-posts-header-tab">Popular posts</h4>
</td>
<td>
<h4 id="verified-tab" onclick="loadPosts(2)" class="community-page-posts-header-tab">Verified posts</h4>
</td>
</tr>
</tbody>
</table>
<% newPosts.forEach(function(post) { %>
<div class="post-user-info-wrapper">
<%if(post.verified) {%>
<img class="community-page-post-user-icon verified" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style=""></span>
<%} else {%>
<img class="community-page-post-user-icon" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style="display: none;"></span>
<%}%>
<h2 class="community-page-post-username"><%= post.screen_name %></h2>
<h4 class="community-page-post-time-stamp"><%= post.created_at %></h4>
<div class="community-page-post-yeah-button-wrapper">
<div class="community-page-post-yeah-button" onclick="yeah(this.parentNode, <%= post.id %>)"></div>
</div>
<div id="yeah-<%= post.id %>" class="community-page-post-yeah-count"><%= post.empathy_count %> Yeahs</div>
</div>
<%if(post.screenshot !== '' && post.painting === '' && post.url === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
</div>
<% } else if(post.painting !== '' && post.screenshot === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.screenshot === '' && post.painting === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<% } else if(post.body !== '' && post.screenshot === '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<h3><%= post.body %></h3>
</div>
<% } else if(post.screenshot !== '' && post.body !== '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.screenshot !== '' && post.painting !== '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.body !== '' && post.screenshot === '' && post.painting === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.url !== '' && post.painting !== '' && post.screenshot === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<%}%>
<br>
<br>
<% }); %>
</div>
</div>
<br>
<body onload="stopLoading(); wiiuBrowser.showLoadingIcon(!1)">
</body>
</html>

View File

@@ -0,0 +1,114 @@
<div class="community-page-header" style="background-image: url('<%= community.WiiU_browser_header %>')"></div>
<div class="community-page-header-overlay"></div>
<div class="community-page-back-button" onclick="loadTab('nav-bar-communities')"></div>
<div class="community-page-info-container">
<div class="community-page-follow-button-wrapper"></div>
<img class="community-page-info-icon" src="<%= community.browser_icon %>">
<h2 class="community-page-title"><%= community.name %></h2>
<h4 class="community-page-description"><%= community.description %></h4>
<div class="community-page-margin-line"></div>
<table class="community-page-table-wrapper">
<tbody>
<tr>
<td>
<div class="community-page-shaded-info-container">
<h4 class="community-page-table-label">Followers</h4>
<h4 class="community-page-table-text"><%= community.followers %></h4>
</div>
</td>
<td>
<div class="community-page-shaded-info-container">
<h4 class="community-page-table-label">Posts</h4>
<h4 class="community-page-table-text"><%=totalNumPosts%></h4>
</div>
</td>
<td>
<div class="community-page-shaded-info-container" style="width: 500px;">
<h4 class="community-page-table-label">Tags</h4>
<h4 class="community-page-table-text">N/A</h4>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="community-page-posts-wrapper">
<table class="community-page-posts-header">
<tbody>
<tr>
<td>
<h4 id="recent-tab" onclick="loadPosts(0)" class="community-page-posts-header-tab active">Recent posts</h4>
</td>
<td>
<h4 id="popular-tab" onclick="loadPosts(1)" class="community-page-posts-header-tab">Popular posts</h4>
</td>
<td>
<h4 id="verified-tab" onclick="loadPosts(2)" class="community-page-posts-header-tab">Verified posts</h4>
</td>
</tr>
</tbody>
</table>
<% newPosts.forEach(function(post) { %>
<div class="post-user-info-wrapper">
<%if(post.verified) {%>
<img class="community-page-post-user-icon verified" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style=""></span>
<%} else {%>
<img class="community-page-post-user-icon" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style="display: none;"></span>
<%}%>
<h2 class="community-page-post-username"><%= post.screen_name %></h2>
<h4 class="community-page-post-time-stamp"><%= post.created_at %></h4>
<div class="community-page-post-yeah-button-wrapper">
<div class="community-page-post-yeah-button" onclick="yeah(this.parentNode, <%= post.id %>)"></div>
</div>
<div id="yeah-<%= post.id %>" class="community-page-post-yeah-count"><%= post.empathy_count %> Yeahs</div>
</div>
<%if(post.screenshot !== '' && post.painting === '' && post.url === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
</div>
<% } else if(post.painting !== '' && post.screenshot === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.screenshot === '' && post.painting === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<% } else if(post.body !== '' && post.screenshot === '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<h3><%= post.body %></h3>
</div>
<% } else if(post.screenshot !== '' && post.body !== '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.screenshot !== '' && post.painting !== '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.body !== '' && post.screenshot === '' && post.painting === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.url !== '' && post.painting !== '' && post.screenshot === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<%}%>
<br>
<br>
<% }); %>
</div>
<br>
<img src="" onerror="wiiuBrowser.showLoadingIcon(!1)">

View File

@@ -0,0 +1,85 @@
<table class="community-page-posts-header">
<tbody>
<tr>
<td>
<h4 id="recent-tab" onclick="loadPosts(0)" class="community-page-posts-header-tab active">Recent posts</h4>
</td>
<td>
<h4 id="popular-tab" onclick="loadPosts(1)" class="community-page-posts-header-tab">Popular posts</h4>
</td>
<td>
<h4 id="verified-tab" onclick="loadPosts(2)" class="community-page-posts-header-tab">Verified posts</h4>
</td>
</tr>
</tbody>
</table>
<% newPosts.forEach(function(post) { %>
<div class="post-user-info-wrapper">
<%if(post.verified) {%>
<img class="community-page-post-user-icon verified" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style=""></span>
<%} else {%>
<img class="community-page-post-user-icon" src="<%= post.mii_face_url %>">
<span class="community-page-verified-user-badge community-page-verified" style="display: none;"></span>
<%}%>
<h2 class="community-page-post-username"><%= post.screen_name %></h2>
<h4 class="community-page-post-time-stamp"><%= post.created_at %></h4>
<div class="community-page-post-yeah-button-wrapper">
<div class="community-page-post-yeah-button" onclick="yeah(this.parentNode, <%= post.id %>)"></div>
</div>
<div id="yeah-<%= post.id %>" class="community-page-post-yeah-count"><%= post.empathy_count %> Yeahs</div>
</div>
<%if(post.screenshot !== '' && post.painting === '' && post.url === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<p>Screenshot Only:</p>
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
</div>
<% } else if(post.painting !== '' && post.screenshot === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<p>Painting Only:</p>
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.screenshot === '' && post.painting === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<p>Video Only:</p>
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<% } else if(post.body !== '' && post.screenshot === '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<p>Text Only:</p>
<h3><%= post.body %></h3>
</div>
<% } else if(post.screenshot !== '' && post.body !== '' && post.painting === '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<p>Screenshot and Body:</p>
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.screenshot !== '' && post.painting !== '' && post.url === '') {%>
<div class="community-page-post-wrapper">
<p>Screenshot and Painting:</p>
<img id="<%= post.id %>" class="community-page-post-screenshot" src="data:image/png;base64,<%= post.screenshot %>">
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<% } else if(post.url !== '' && post.body !== '' && post.screenshot === '' && post.painting === '') {%>
<div class="community-page-post-wrapper">
<p>Video and Body:</p>
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<div class="community-page-post-text-overlay">
<h3><%= post.body %></h3>
</div>
</div>
<% } else if(post.url !== '' && post.painting !== '' && post.screenshot === '' && post.body === '') {%>
<div class="community-page-post-wrapper">
<p>Video and Painting:</p>
<iframe width="760" height="427.5" src="<%= post.url %>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<img id="<%= post.id%>" class="community-page-post-painting" src="<%= post.painting_uri %>">
</div>
<%}%>
<br>
<br>
<% }); %>
<img src="" onerror="wiiuBrowser.showLoadingIcon(!1)">

72
src/views/portal_show.ejs Normal file
View File

@@ -0,0 +1,72 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/juxt.css">
<script src="/js/juxt.js"></script>
</head>
<body>
<menu id="nav-bar" class="">
<li id="nav-bar-profile" class="" onclick="loadTab('nav-bar-profile')"><a>User Page</a></li>
<li id="nav-bar-activity-feed" class="" onclick="loadTab('nav-bar-activity-feed')"><a>Activity Feed</a></li>
<li id="nav-bar-communities" class="selected" onclick="loadTab('nav-bar-communities')"><a>Communities</a></li>
<li id="nav-bar-messages" class="" onclick="loadMessagesTab();"><a>Messages<span id="messages-badge" class="badge" style=""></span></a></li>
<li id="nav-bar-news" class="" onclick="loadTab('nav-bar-news')"><a>Notifications<span id="news-badge" class="badge" style=""></span></a></li >
<li id="nav-bar-exit" class="" onclick="exit()"><a href="">Close</a></li>
<li id="nav-bar-back" class="none"><a href="">Back</a></li>
</menu>
<div id="main">
<h1 class="page-header">Communities</h1>
<div class="search-container">
<form action="/action_page.php">
<img id="search-icon" src="/icons/Icon-feather-search.svg"></img>
<input id="search-bar" type="text" placeholder="Search communities..." name="search">
</form>
</div>
<div id="popular" class="communities-wrapper">
<h1 class="communities-header">Popular Places</h1>
<table>
<tbody>
<tr>
<% for(var i = 0; i < popularCommunities.length; i++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= popularCommunities[i].id %>')">
<img class="community-list-icon" src="<%= popularCommunities[i].browser_icon %>">
<h2 class="community-list-title"><%= popularCommunities[i].name %></h2>
<h4 class="community-list-followers"><%= popularCommunities[i].followers %> followers</h4>
</div>
</td>
<% if( (i + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
<div id="new" class="communities-wrapper">
<h1 class="communities-header">New communities</h1>
<table>
<tbody>
<tr>
<% for(var j = 0; j < newCommunities.length; j++) {%>
<td>
<div class="community-list-wrapper" onclick="loadCommunityPage('<%= newCommunities[j].id %>')">
<img class="community-list-icon" src="<%= newCommunities[j].browser_icon %>">
<h2 class="community-list-title"><%= newCommunities[j].name %></h2>
<h4 class="community-list-followers"><%= newCommunities[j].followers %> followers</h4>
</div>
</td>
<% if( (j + 1) % 3 === 0) { %>
</tr>
<tr>
<% } %>
<% } %>
</tr>
</tbody>
</table>
</div>
</div>
<body onload="stopLoading()">
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="15.111" height="15.111" viewBox="0 0 15.111 15.111">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #673db6;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2px;
}
</style>
</defs>
<path id="Path_52" data-name="Path 52" class="cls-1" d="M15.611,10.056A5.556,5.556,0,1,1,10.056,4.5,5.556,5.556,0,0,1,15.611,10.056Z" transform="translate(-3.5 -3.5)"/>
<path id="Path_53" data-name="Path 53" class="cls-1" d="M28,28l-3.021-3.021" transform="translate(-14.561 -14.561)"/>
</svg>

After

Width:  |  Height:  |  Size: 600 B

View File

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="5.849" height="5.849" viewBox="0 0 5.849 5.849">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #673db6;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2px;
}
</style>
</defs>
<path id="Path_53" data-name="Path 53" class="cls-1" d="M28,28l-3.021-3.021" transform="translate(-23.561 -23.561)"/>
</svg>

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 KiB

228
src/webfiles/ctr/js/juxt.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="15.111" height="15.111" viewBox="0 0 15.111 15.111">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #673db6;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2px;
}
</style>
</defs>
<path id="Path_52" data-name="Path 52" class="cls-1" d="M15.611,10.056A5.556,5.556,0,1,1,10.056,4.5,5.556,5.556,0,0,1,15.611,10.056Z" transform="translate(-3.5 -3.5)"/>
<path id="Path_53" data-name="Path 53" class="cls-1" d="M28,28l-3.021-3.021" transform="translate(-14.561 -14.561)"/>
</svg>

After

Width:  |  Height:  |  Size: 600 B

View File

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="5.849" height="5.849" viewBox="0 0 5.849 5.849">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #673db6;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2px;
}
</style>
</defs>
<path id="Path_53" data-name="Path 53" class="cls-1" d="M28,28l-3.021-3.021" transform="translate(-23.561 -23.561)"/>
</svg>

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

File diff suppressed because one or more lines are too long