Add v1.0
This commit is contained in:
parent
6a5f642fb4
commit
48dffc112a
21 changed files with 1327 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
|
data/
|
||||||
|
config.toml
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|
|
||||||
126
docs/index.html
Normal file
126
docs/index.html
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Lurk Message Manager</title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
|
||||||
|
<link rel="stylesheet" href="./style.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
|
||||||
|
<script src="./script.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<div v-if="!authenticated" id="login">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input id="username" type="text" v-model="login.username">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input id="password" type="password" v-model="login.password">
|
||||||
|
<button
|
||||||
|
@click.stop="tryLogin"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-cloak v-else>
|
||||||
|
<div id="header">
|
||||||
|
<label for="channel-selector">
|
||||||
|
Select Channel
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
name="channel selector"
|
||||||
|
id="channel-selector"
|
||||||
|
v-model="channel"
|
||||||
|
@change="getMessages"
|
||||||
|
>
|
||||||
|
<option value="" selected disabled>Select a Channel</option>
|
||||||
|
<option
|
||||||
|
v-for="channel in channels"
|
||||||
|
:key="channel"
|
||||||
|
:value="channel"
|
||||||
|
>
|
||||||
|
{{channel}}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
:disabled="new_group"
|
||||||
|
@click.stop="addGroup"
|
||||||
|
>
|
||||||
|
Add Message Group
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="body">
|
||||||
|
<div
|
||||||
|
v-for="(group, i) in messages"
|
||||||
|
:key="group.id"
|
||||||
|
class="lurk-group"
|
||||||
|
>
|
||||||
|
<div class="flex-container">
|
||||||
|
<h3 style="flex-grow: 1;">Message Group {{i + 1}}</h3>
|
||||||
|
<button
|
||||||
|
v-if="group.id != 'new-group'"
|
||||||
|
@click.stop="deleteGroup(group)"
|
||||||
|
>
|
||||||
|
Delete Group
|
||||||
|
</button>
|
||||||
|
<div v-else>
|
||||||
|
<button
|
||||||
|
@click.stop="removeNewGroup"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
:disabled="group.lurk.length == 0 || group.unlurk.length == 0"
|
||||||
|
@click.stop="saveGroup(group)"
|
||||||
|
>
|
||||||
|
Save Group
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i>Group ID: {{group.id}}</i>
|
||||||
|
<hr>
|
||||||
|
<div class="lurk-messages group-messages">
|
||||||
|
<h4>Lurk Messages</h4>
|
||||||
|
<div v-for="msg in group.lurk" class="flex-container message">
|
||||||
|
<div style="flex-grow: 1">{{msg}}</div>
|
||||||
|
<button @click.stop="deleteLurk(group, msg)">Delete Message</button>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="flex-container">
|
||||||
|
<input type="text" class="message-input" v-model="group.new.lurk">
|
||||||
|
<button
|
||||||
|
:disabled="group.new.lurk.length == 0"
|
||||||
|
@click.stop="addLurk(group)"
|
||||||
|
>
|
||||||
|
Add Lurk Message
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="unlurk-messages group-messages">
|
||||||
|
<h4>Unlurk Messages</h4>
|
||||||
|
<div v-for="msg in group.unlurk" class="flex-container message">
|
||||||
|
<div style="flex-grow: 1">{{msg}}</div>
|
||||||
|
<button @click.stop="deleteUnlurk(group, msg)">Delete Message</button>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="flex-container">
|
||||||
|
<input type="text" class="message-input" v-model="group.new.unlurk">
|
||||||
|
<button
|
||||||
|
:disabled="group.new.unlurk.length == 0"
|
||||||
|
@click.stop="addUnlurk(group)"
|
||||||
|
>
|
||||||
|
Add Unlurk Message
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
182
docs/script.js
Normal file
182
docs/script.js
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
const app = new Vue({
|
||||||
|
el: `#app`,
|
||||||
|
data() {return {
|
||||||
|
url: `http://localhost:4000`,
|
||||||
|
authenticated: false,
|
||||||
|
channels: [],
|
||||||
|
channel: ``,
|
||||||
|
login: {
|
||||||
|
username: `alkali`,
|
||||||
|
password: `metal`,
|
||||||
|
},
|
||||||
|
api: null,
|
||||||
|
messages: [],
|
||||||
|
new_group: false,
|
||||||
|
}},
|
||||||
|
methods: {
|
||||||
|
async tryLogin() {
|
||||||
|
try {
|
||||||
|
let r = await axios.post(
|
||||||
|
`${this.url}/login`,
|
||||||
|
undefined,
|
||||||
|
{ auth: this.login }
|
||||||
|
);
|
||||||
|
this.api = axios.create({
|
||||||
|
baseURL: this.url,
|
||||||
|
validateStatus: null,
|
||||||
|
auth: this.login,
|
||||||
|
});
|
||||||
|
this.channels.push(...r.data.sort());
|
||||||
|
this.authenticated = true;
|
||||||
|
} catch (_) {};
|
||||||
|
},
|
||||||
|
async getMessages() {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let r = await this.api.get(`/manage/${this.channel}`);
|
||||||
|
if (r.status === 200) {
|
||||||
|
for (const m of r.data) {
|
||||||
|
m.new = {
|
||||||
|
lurk: ``,
|
||||||
|
unlurk: ``,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.messages = r.data;
|
||||||
|
} else {
|
||||||
|
this.messages = [];
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async addLurk(group) {
|
||||||
|
if (group.id === `new-group`) {
|
||||||
|
group.lurk.push(group.new.lurk);
|
||||||
|
} else {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let payload = {
|
||||||
|
lurk: [
|
||||||
|
...group.lurk,
|
||||||
|
group.new.lurk
|
||||||
|
],
|
||||||
|
unlurk: group.unlurk,
|
||||||
|
};
|
||||||
|
let r = await this.api.patch(
|
||||||
|
`/manage/${this.channel}/message/${group.id}`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
if (r.status != 200) {
|
||||||
|
alert(`Failed to update the group. Status: ${r.status}`);
|
||||||
|
} else {
|
||||||
|
group.lurk.push(group.new.lurk);
|
||||||
|
alert(`Added lurk message successfully.`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
group.new.lurk = ``;
|
||||||
|
},
|
||||||
|
async addUnlurk(group) {
|
||||||
|
if (group.id === `new-group`) {
|
||||||
|
group.unlurk.push(group.new.unlurk);
|
||||||
|
} else {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let payload = {
|
||||||
|
lurk: group.lurk,
|
||||||
|
unlurk: [
|
||||||
|
...group.unlurk,
|
||||||
|
group.new.unlurk
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let r = await this.api.patch(
|
||||||
|
`/manage/${this.channel}/message/${group.id}`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
if (r.status != 200) {
|
||||||
|
alert(`Failed to update the group. Status: ${r.status}`);
|
||||||
|
} else {
|
||||||
|
group.unlurk.push(group.new.unlurk);
|
||||||
|
alert(`Added unlurk message successfully.`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
group.new.unlurk = ``;
|
||||||
|
},
|
||||||
|
addGroup() {
|
||||||
|
this.new_group = true;
|
||||||
|
this.messages.unshift({
|
||||||
|
lurk: [],
|
||||||
|
unlurk: [],
|
||||||
|
id: "new-group",
|
||||||
|
new: {
|
||||||
|
lurk: ``,
|
||||||
|
unlurk: ``,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async saveGroup(group) {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let r = await this.api.post(`/manage/${this.channel}/message`, {
|
||||||
|
lurk: group.lurk,
|
||||||
|
unlurk: group.unlurk,
|
||||||
|
});
|
||||||
|
if (r.status === 200) {
|
||||||
|
this.messages.shift()
|
||||||
|
this.messages.push({
|
||||||
|
...r.data,
|
||||||
|
new: {
|
||||||
|
lurk: ``,
|
||||||
|
unlurk: ``,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
alert(`Group has been saved`);
|
||||||
|
};
|
||||||
|
this.new_group = false;
|
||||||
|
},
|
||||||
|
async deleteGroup(group) {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let r = await this.api.delete(`/manage/${this.channel}/message/${group.id}`);
|
||||||
|
if (r.status === 200) {
|
||||||
|
this.messages.splice(this.messages.indexOf(group, 1));
|
||||||
|
alert(`Group has been deleted`);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async deleteLurk(group, message) {
|
||||||
|
if (group.id == "new-group") {
|
||||||
|
group.lurk.splice(group.lurk.indexOf(message), 1);
|
||||||
|
} else {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let r = await this.api.patch(
|
||||||
|
`/manage/${this.channel}/message/${group.id}`,
|
||||||
|
{
|
||||||
|
lurk: group.lurk.filter(m => m != message),
|
||||||
|
unlurk: group.unlurk,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (r.status == 200) {
|
||||||
|
group.lurk.splice(group.lurk.indexOf(message), 1);
|
||||||
|
alert(`Deleted message successfully`);
|
||||||
|
} else {
|
||||||
|
alert(`Failed to delete the message. Status: ${r.status}`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async deleteUnlurk(group, message) {
|
||||||
|
if (group.id === `new-group`) {
|
||||||
|
group.unlurk.splice(group.unlurk.indexOf(message), 1);
|
||||||
|
} else {
|
||||||
|
if (!this.api) { return };
|
||||||
|
let r = await this.api.patch(
|
||||||
|
`/manage/${this.channel}/message/${group.id}`,
|
||||||
|
{
|
||||||
|
lurk: group.lurk,
|
||||||
|
unlurk: group.unlurk.filter(m => m != message),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (r.status == 200) {
|
||||||
|
group.unlurk.splice(group.unlurk.indexOf(message), 1);
|
||||||
|
alert(`Deleted message successfully`);
|
||||||
|
} else {
|
||||||
|
alert(`Failed to delete the message. Status: ${r.status}`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
},
|
||||||
|
removeNewGroup() {
|
||||||
|
this.messages.shift();
|
||||||
|
this.new_group = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
35
docs/style.css
Normal file
35
docs/style.css
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login > input {
|
||||||
|
margin: 5px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lurk-group {
|
||||||
|
background: #1a242f;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 7px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-input {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
8
makefile
Normal file
8
makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
.PHONY: dist dev prod
|
||||||
|
|
||||||
|
dist:
|
||||||
|
@rm -rf dist
|
||||||
|
tsc
|
||||||
|
|
||||||
|
dev: dist
|
||||||
|
NODE_ENV=development node dist/main.js
|
||||||
32
package.json
Normal file
32
package.json
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "twitch-lurk-message-api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Oliver Akins",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"dependencies": {
|
||||||
|
"@hapi/basic": "^6.0.0",
|
||||||
|
"@hapi/boom": "^10.0.0",
|
||||||
|
"@hapi/hapi": "^20.2.2",
|
||||||
|
"glob": "^8.0.3",
|
||||||
|
"joi": "^17.6.0",
|
||||||
|
"module-alias": "^2.2.2",
|
||||||
|
"toml": "^3.0.0",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/glob": "^7.2.0",
|
||||||
|
"@types/hapi__basic": "^5.1.2",
|
||||||
|
"@types/hapi__hapi": "^20.0.12",
|
||||||
|
"@types/node": "^18.0.6",
|
||||||
|
"@types/uuid": "^8.3.4"
|
||||||
|
},
|
||||||
|
"_moduleAliases": {
|
||||||
|
"@": "./dist"
|
||||||
|
}
|
||||||
|
}
|
||||||
417
pnpm-lock.yaml
generated
Normal file
417
pnpm-lock.yaml
generated
Normal file
|
|
@ -0,0 +1,417 @@
|
||||||
|
lockfileVersion: 5.4
|
||||||
|
|
||||||
|
specifiers:
|
||||||
|
'@hapi/basic': ^6.0.0
|
||||||
|
'@hapi/boom': ^10.0.0
|
||||||
|
'@hapi/hapi': ^20.2.2
|
||||||
|
'@types/glob': ^7.2.0
|
||||||
|
'@types/hapi__basic': ^5.1.2
|
||||||
|
'@types/hapi__hapi': ^20.0.12
|
||||||
|
'@types/node': ^18.0.6
|
||||||
|
'@types/uuid': ^8.3.4
|
||||||
|
glob: ^8.0.3
|
||||||
|
joi: ^17.6.0
|
||||||
|
module-alias: ^2.2.2
|
||||||
|
toml: ^3.0.0
|
||||||
|
uuid: ^8.3.2
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
'@hapi/basic': 6.0.0
|
||||||
|
'@hapi/boom': 10.0.0
|
||||||
|
'@hapi/hapi': 20.2.2
|
||||||
|
glob: 8.0.3
|
||||||
|
joi: 17.6.0
|
||||||
|
module-alias: 2.2.2
|
||||||
|
toml: 3.0.0
|
||||||
|
uuid: 8.3.2
|
||||||
|
|
||||||
|
devDependencies:
|
||||||
|
'@types/glob': 7.2.0
|
||||||
|
'@types/hapi__basic': 5.1.2
|
||||||
|
'@types/hapi__hapi': 20.0.12
|
||||||
|
'@types/node': 18.0.6
|
||||||
|
'@types/uuid': 8.3.4
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/@hapi/accept/5.0.2:
|
||||||
|
resolution: {integrity: sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/ammo/5.0.1:
|
||||||
|
resolution: {integrity: sha512-FbCNwcTbnQP4VYYhLNGZmA76xb2aHg9AMPiy18NZyWMG310P5KdFGyA9v2rm5ujrIny77dEEIkMOwl0Xv+fSSA==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/b64/5.0.0:
|
||||||
|
resolution: {integrity: sha512-ngu0tSEmrezoiIaNGG6rRvKOUkUuDdf4XTPnONHGYfSGRmDqPZX5oJL6HAdKTo1UQHECbdB4OzhWrfgVppjHUw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@hapi/basic/6.0.0:
|
||||||
|
resolution: {integrity: sha512-nWWSXNCq3WptnP3To2c8kfQiRFDUnd9FQOcMS0B85y1x/m12c0hhp+VdmK60BMe44k6WIog1n6g8f9gZOagqBg==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/boom/10.0.0:
|
||||||
|
resolution: {integrity: sha512-1YVs9tLHhypBqqinKQRqh7FUERIolarQApO37OWkzD+z6y6USi871Sv746zBPKcIOBuI6g6y4FrwX87mmJ90Gg==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 10.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/boom/9.1.4:
|
||||||
|
resolution: {integrity: sha512-Ls1oH8jaN1vNsqcaHVYJrKmgMcKsC1wcp8bujvXrHaAqD2iDYq3HoOwsxwo09Cuda5R5nC0o0IxlrlTuvPuzSw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@hapi/bounce/2.0.0:
|
||||||
|
resolution: {integrity: sha512-JesW92uyzOOyuzJKjoLHM1ThiOvHPOLDHw01YV8yh5nCso7sDwJho1h0Ad2N+E62bZyz46TG3xhAi/78Gsct6A==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/bourne/2.1.0:
|
||||||
|
resolution: {integrity: sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==}
|
||||||
|
|
||||||
|
/@hapi/call/8.0.1:
|
||||||
|
resolution: {integrity: sha512-bOff6GTdOnoe5b8oXRV3lwkQSb/LAWylvDMae6RgEWWntd0SHtkYbQukDHKlfaYtVnSAgIavJ0kqszF/AIBb6g==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/catbox-memory/5.0.1:
|
||||||
|
resolution: {integrity: sha512-QWw9nOYJq5PlvChLWV8i6hQHJYfvdqiXdvTupJFh0eqLZ64Xir7mKNi96d5/ZMUAqXPursfNDIDxjFgoEDUqeQ==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/catbox/11.1.1:
|
||||||
|
resolution: {integrity: sha512-u/8HvB7dD/6X8hsZIpskSDo4yMKpHxFd7NluoylhGrL6cUfYxdQPnvUp9YU2C6F9hsyBVLGulBd9vBN1ebfXOQ==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/podium': 4.1.3
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/content/5.0.2:
|
||||||
|
resolution: {integrity: sha512-mre4dl1ygd4ZyOH3tiYBrOUBzV7Pu/EOs8VLGf58vtOEECWed8Uuw6B4iR9AN/8uQt42tB04qpVaMyoMQh0oMw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/cryptiles/5.1.0:
|
||||||
|
resolution: {integrity: sha512-fo9+d1Ba5/FIoMySfMqPBR/7Pa29J2RsiPrl7bkwo5W5o+AN1dAYQRi4SPrPwwVxVGKjgLOEWrsvt1BonJSfLA==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
|
||||||
|
/@hapi/file/2.0.0:
|
||||||
|
resolution: {integrity: sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/hapi/20.2.2:
|
||||||
|
resolution: {integrity: sha512-crhU6TIKt7QsksWLYctDBAXogk9PYAm7UzdpETyuBHC2pCa6/+B5NykiOVLG/3FCIgHo/raPVtan8bYtByHORQ==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/accept': 5.0.2
|
||||||
|
'@hapi/ammo': 5.0.1
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/bounce': 2.0.0
|
||||||
|
'@hapi/call': 8.0.1
|
||||||
|
'@hapi/catbox': 11.1.1
|
||||||
|
'@hapi/catbox-memory': 5.0.1
|
||||||
|
'@hapi/heavy': 7.0.1
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/mimos': 6.0.0
|
||||||
|
'@hapi/podium': 4.1.3
|
||||||
|
'@hapi/shot': 5.0.5
|
||||||
|
'@hapi/somever': 3.0.1
|
||||||
|
'@hapi/statehood': 7.0.4
|
||||||
|
'@hapi/subtext': 7.0.4
|
||||||
|
'@hapi/teamwork': 5.1.1
|
||||||
|
'@hapi/topo': 5.1.0
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/heavy/7.0.1:
|
||||||
|
resolution: {integrity: sha512-vJ/vzRQ13MtRzz6Qd4zRHWS3FaUc/5uivV2TIuExGTM9Qk+7Zzqj0e2G7EpE6KztO9SalTbiIkTh7qFKj/33cA==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/hoek/10.0.0:
|
||||||
|
resolution: {integrity: sha512-CeNFz1JcLZ5xE8Vc9aau37cgHw9bxXqSDK/D55GF2GAOv0n0XjyyjSodHtKahB7A1tV3FlgCpijp3zkSITmBdA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/hoek/9.3.0:
|
||||||
|
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
||||||
|
|
||||||
|
/@hapi/iron/6.0.0:
|
||||||
|
resolution: {integrity: sha512-zvGvWDufiTGpTJPG1Y/McN8UqWBu0k/xs/7l++HVU535NLHXsHhy54cfEMdW7EjwKfbBfM9Xy25FmTiobb7Hvw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/b64': 5.0.0
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/bourne': 2.1.0
|
||||||
|
'@hapi/cryptiles': 5.1.0
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@hapi/mimos/6.0.0:
|
||||||
|
resolution: {integrity: sha512-Op/67tr1I+JafN3R3XN5DucVSxKRT/Tc+tUszDwENoNpolxeXkhrJ2Czt6B6AAqrespHoivhgZBWYSuANN9QXg==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
mime-db: 1.52.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/nigel/4.0.2:
|
||||||
|
resolution: {integrity: sha512-ht2KoEsDW22BxQOEkLEJaqfpoKPXxi7tvabXy7B/77eFtOyG5ZEstfZwxHQcqAiZhp58Ae5vkhEqI03kawkYNw==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/vise': 4.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/pez/5.0.3:
|
||||||
|
resolution: {integrity: sha512-mpikYRJjtrbJgdDHG/H9ySqYqwJ+QU/D7FXsYciS9P7NYBXE2ayKDAy3H0ou6CohOCaxPuTV4SZ0D936+VomHA==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/b64': 5.0.0
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/content': 5.0.2
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/nigel': 4.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/podium/4.1.3:
|
||||||
|
resolution: {integrity: sha512-ljsKGQzLkFqnQxE7qeanvgGj4dejnciErYd30dbrYzUOF/FyS/DOF97qcrT3bhoVwCYmxa6PEMhxfCPlnUcD2g==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/teamwork': 5.1.1
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
|
||||||
|
/@hapi/shot/5.0.5:
|
||||||
|
resolution: {integrity: sha512-x5AMSZ5+j+Paa8KdfCoKh+klB78otxF+vcJR/IoN91Vo2e5ulXIW6HUsFTCU+4W6P/Etaip9nmdAx2zWDimB2A==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/somever/3.0.1:
|
||||||
|
resolution: {integrity: sha512-4ZTSN3YAHtgpY/M4GOtHUXgi6uZtG9nEZfNI6QrArhK0XN/RDVgijlb9kOmXwCR5VclDSkBul9FBvhSuKXx9+w==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/bounce': 2.0.0
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/statehood/7.0.4:
|
||||||
|
resolution: {integrity: sha512-Fia6atroOVmc5+2bNOxF6Zv9vpbNAjEXNcUbWXavDqhnJDlchwUUwKS5LCi5mGtCTxRhUKKHwuxuBZJkmLZ7fw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/bounce': 2.0.0
|
||||||
|
'@hapi/bourne': 2.1.0
|
||||||
|
'@hapi/cryptiles': 5.1.0
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/iron': 6.0.0
|
||||||
|
'@hapi/validate': 1.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/subtext/7.0.4:
|
||||||
|
resolution: {integrity: sha512-Y72moHhbRuO8kwBHFEnCRw7oOnhNh4Pl+aonxAze18jkyMpE4Gwz4lNID7ei8vd3lpXC2rKdkxXJgtfY+WttRw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/bourne': 2.1.0
|
||||||
|
'@hapi/content': 5.0.2
|
||||||
|
'@hapi/file': 2.0.0
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/pez': 5.0.3
|
||||||
|
'@hapi/wreck': 17.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/teamwork/5.1.1:
|
||||||
|
resolution: {integrity: sha512-1oPx9AE5TIv+V6Ih54RP9lTZBso3rP8j4Xhb6iSVwPXtAM+sDopl5TFMv5Paw73UnpZJ9gjcrTE1BXrWt9eQrg==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
|
/@hapi/topo/5.1.0:
|
||||||
|
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@hapi/validate/1.1.3:
|
||||||
|
resolution: {integrity: sha512-/XMR0N0wjw0Twzq2pQOzPBZlDzkekGcoCtzO314BpIEsbXdYGthQUbxgkGDf4nhk1+IPDAsXqWjMohRQYO06UA==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/topo': 5.1.0
|
||||||
|
|
||||||
|
/@hapi/vise/4.0.0:
|
||||||
|
resolution: {integrity: sha512-eYyLkuUiFZTer59h+SGy7hUm+qE9p+UemePTHLlIWppEd+wExn3Df5jO04bFQTm7nleF5V8CtuYQYb+VFpZ6Sg==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@hapi/wreck/17.2.0:
|
||||||
|
resolution: {integrity: sha512-pJ5kjYoRPYDv+eIuiLQqhGon341fr2bNIYZjuotuPJG/3Ilzr/XtI+JAp0A86E2bYfsS3zBPABuS2ICkaXFT8g==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/bourne': 2.1.0
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@sideway/address/4.1.4:
|
||||||
|
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
/@sideway/formula/3.0.0:
|
||||||
|
resolution: {integrity: sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==}
|
||||||
|
|
||||||
|
/@sideway/pinpoint/2.0.0:
|
||||||
|
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
|
||||||
|
|
||||||
|
/@types/glob/7.2.0:
|
||||||
|
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/minimatch': 3.0.5
|
||||||
|
'@types/node': 18.0.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/hapi__basic/5.1.2:
|
||||||
|
resolution: {integrity: sha512-sqoQ34nwmRlNgQ5fdHHnghyVzs23aC2d30l9G1sKvdrh4PDV22bnQ+8fBCjoItT+0gGSuXIoG4qdoVZGBjH5EQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hapi__hapi': 20.0.12
|
||||||
|
joi: 17.6.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/hapi__catbox/10.2.4:
|
||||||
|
resolution: {integrity: sha512-A6ivRrXD5glmnJna1UAGw87QNZRp/vdFO9U4GS+WhOMWzHnw+oTGkMvg0g6y1930CbeheGOCm7A1qHsqH7AXqg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/hapi__hapi/20.0.12:
|
||||||
|
resolution: {integrity: sha512-B+0fceCzFvbIOVv5YWOZzbHtEff8BLlGH3etrkcOedyj7F0unC5FjzFfaaO5gwlhJDdX0cmmMeRg2pwRdMa2CQ==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 9.1.4
|
||||||
|
'@hapi/iron': 6.0.0
|
||||||
|
'@hapi/podium': 4.1.3
|
||||||
|
'@types/hapi__catbox': 10.2.4
|
||||||
|
'@types/hapi__mimos': 4.1.4
|
||||||
|
'@types/hapi__shot': 4.1.2
|
||||||
|
'@types/node': 18.0.6
|
||||||
|
joi: 17.6.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/hapi__mimos/4.1.4:
|
||||||
|
resolution: {integrity: sha512-i9hvJpFYTT/qzB5xKWvDYaSXrIiNqi4ephi+5Lo6+DoQdwqPXQgmVVOZR+s3MBiHoFqsCZCX9TmVWG3HczmTEQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mime-db': 1.43.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/hapi__shot/4.1.2:
|
||||||
|
resolution: {integrity: sha512-8wWgLVP1TeGqgzZtCdt+F+k15DWQvLG1Yv6ZzPfb3D5WIo5/S+GGKtJBVo2uNEcqabP5Ifc71QnJTDnTmw1axA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 18.0.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/mime-db/1.43.1:
|
||||||
|
resolution: {integrity: sha512-kGZJY+R+WnR5Rk+RPHUMERtb2qBRViIHCBdtUrY+NmwuGb8pQdfTqQiCKPrxpdoycl8KWm2DLdkpoSdt479XoQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/minimatch/3.0.5:
|
||||||
|
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/node/18.0.6:
|
||||||
|
resolution: {integrity: sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/uuid/8.3.4:
|
||||||
|
resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/balanced-match/1.0.2:
|
||||||
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/brace-expansion/2.0.1:
|
||||||
|
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
||||||
|
dependencies:
|
||||||
|
balanced-match: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/fs.realpath/1.0.0:
|
||||||
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/glob/8.0.3:
|
||||||
|
resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dependencies:
|
||||||
|
fs.realpath: 1.0.0
|
||||||
|
inflight: 1.0.6
|
||||||
|
inherits: 2.0.4
|
||||||
|
minimatch: 5.1.0
|
||||||
|
once: 1.4.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/inflight/1.0.6:
|
||||||
|
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||||
|
dependencies:
|
||||||
|
once: 1.4.0
|
||||||
|
wrappy: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/inherits/2.0.4:
|
||||||
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/joi/17.6.0:
|
||||||
|
resolution: {integrity: sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==}
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/topo': 5.1.0
|
||||||
|
'@sideway/address': 4.1.4
|
||||||
|
'@sideway/formula': 3.0.0
|
||||||
|
'@sideway/pinpoint': 2.0.0
|
||||||
|
|
||||||
|
/mime-db/1.52.0:
|
||||||
|
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/minimatch/5.1.0:
|
||||||
|
resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
brace-expansion: 2.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/module-alias/2.2.2:
|
||||||
|
resolution: {integrity: sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/once/1.4.0:
|
||||||
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
dependencies:
|
||||||
|
wrappy: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/toml/3.0.0:
|
||||||
|
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/uuid/8.3.2:
|
||||||
|
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/wrappy/1.0.2:
|
||||||
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
|
dev: false
|
||||||
17
src/endpoints/login.ts
Normal file
17
src/endpoints/login.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { db } from "@/main";
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `POST`, path: `/login`,
|
||||||
|
async handler(request, h) {
|
||||||
|
const { access } = request.auth.credentials as { username: string, access: string[] };
|
||||||
|
|
||||||
|
let channels = access.filter(x => x != "*");
|
||||||
|
if (access.includes(`*`)) {
|
||||||
|
channels.push(...Object.keys(db).filter(c => !channels.includes(c)));
|
||||||
|
};
|
||||||
|
|
||||||
|
return h.response(channels).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
27
src/endpoints/management/create_channel.ts
Normal file
27
src/endpoints/management/create_channel.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `POST`, path: `/manage`,
|
||||||
|
options: {
|
||||||
|
validate: {
|
||||||
|
payload: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
db[channel].lurkers = {};
|
||||||
|
|
||||||
|
return h.response().code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
38
src/endpoints/management/create_message.ts
Normal file
38
src/endpoints/management/create_message.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: [`POST`, `PUT`], path: `/manage/{channel}/message`,
|
||||||
|
options: {
|
||||||
|
validate: {
|
||||||
|
payload: Joi.object({
|
||||||
|
lurk: Joi.array().items(Joi.string().min(1)).min(1),
|
||||||
|
unlurk: Joi.array().items(Joi.string().min(1)).min(1),
|
||||||
|
}),
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
const data = request.payload as lurk_message;
|
||||||
|
const id = v4();
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
db[channel].messages[id] = data;
|
||||||
|
|
||||||
|
return h.response({
|
||||||
|
lurk: data.lurk,
|
||||||
|
unlurk: data.unlurk,
|
||||||
|
id,
|
||||||
|
}).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
33
src/endpoints/management/delete_message.ts
Normal file
33
src/endpoints/management/delete_message.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `DELETE`, path: `/manage/{channel}/message/{id}`,
|
||||||
|
options: {
|
||||||
|
validate: {
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
id: Joi.string().uuid(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel, id } = request.params;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!db[channel].messages[id]) {
|
||||||
|
throw boom.notFound(`Invalid ID`);
|
||||||
|
};
|
||||||
|
|
||||||
|
let message = db[channel].messages[id];
|
||||||
|
delete db[channel].messages[id];
|
||||||
|
|
||||||
|
return h.response(message).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
27
src/endpoints/management/list_messages.ts
Normal file
27
src/endpoints/management/list_messages.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `GET`, path: `/manage/{channel}`,
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
let messages = [];
|
||||||
|
for (const messageId in db[channel].messages) {
|
||||||
|
let message = db[channel].messages[messageId];
|
||||||
|
messages.push({
|
||||||
|
id: messageId,
|
||||||
|
lurk: message.lurk,
|
||||||
|
unlurk: message.unlurk,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return h.response(messages).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
27
src/endpoints/management/reset_lurkers.ts
Normal file
27
src/endpoints/management/reset_lurkers.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `DELETE`, path: `/manage/{channel}/lurkers`,
|
||||||
|
options: {
|
||||||
|
validate: {
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
db[channel].lurkers = {};
|
||||||
|
|
||||||
|
return h.response().code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
34
src/endpoints/management/update_message.ts
Normal file
34
src/endpoints/management/update_message.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `PATCH`, path: `/manage/{channel}/message/{id}`,
|
||||||
|
options: {
|
||||||
|
validate: {
|
||||||
|
payload: Joi.object({
|
||||||
|
lurk: Joi.array().items(Joi.string().min(1)).min(1),
|
||||||
|
unlurk: Joi.array().items(Joi.string().min(1)).min(1),
|
||||||
|
}),
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
id: Joi.string().uuid(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel, id } = request.params;
|
||||||
|
const data = request.payload as lurk_message;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
db[channel].messages[id] = data;
|
||||||
|
|
||||||
|
return h.response(`Updated message set with ID: ${id}`).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
46
src/endpoints/public/lurk.ts
Normal file
46
src/endpoints/public/lurk.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import { formatMessage } from "@/utils";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `GET`, path: `/{channel}/lurk`,
|
||||||
|
options: {
|
||||||
|
auth: false,
|
||||||
|
validate: {
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
}),
|
||||||
|
query: Joi.object({
|
||||||
|
user: Joi.string(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
const { user } = request.query;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const messages = db[channel].messages;
|
||||||
|
const messageIds = Object.keys(messages);
|
||||||
|
const messageId = messageIds[Math.floor(Math.random() * messageIds.length)];
|
||||||
|
const message = messages[messageId];
|
||||||
|
let lurkMessage = message.lurk[Math.floor(Math.random() * message.lurk.length)];
|
||||||
|
|
||||||
|
db[channel].lurkers[user] = messageId;
|
||||||
|
|
||||||
|
let twitchMessage = formatMessage(
|
||||||
|
lurkMessage,
|
||||||
|
{
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return h.response(twitchMessage).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
46
src/endpoints/public/unlurk.ts
Normal file
46
src/endpoints/public/unlurk.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { ServerRoute } from "@hapi/hapi";
|
||||||
|
import { formatMessage } from "@/utils";
|
||||||
|
import boom from "@hapi/boom";
|
||||||
|
import { db } from "@/main";
|
||||||
|
import Joi from "joi";
|
||||||
|
|
||||||
|
const data: ServerRoute = {
|
||||||
|
method: `GET`, path: `/{channel}/unlurk`,
|
||||||
|
options: {
|
||||||
|
auth: false,
|
||||||
|
validate: {
|
||||||
|
params: Joi.object({
|
||||||
|
channel: Joi.string().alphanum(),
|
||||||
|
}),
|
||||||
|
query: Joi.object({
|
||||||
|
user: Joi.string(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async handler(request, h) {
|
||||||
|
const { channel } = request.params;
|
||||||
|
const { user } = request.query;
|
||||||
|
|
||||||
|
if (!db[channel]) {
|
||||||
|
throw boom.notFound(`Invalid channel`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const messages = db[channel].messages;
|
||||||
|
const messageId = db[channel].lurkers[user];
|
||||||
|
const message = messages[messageId];
|
||||||
|
let lurkMessage = message.unlurk[Math.floor(Math.random() * message.unlurk.length)];
|
||||||
|
|
||||||
|
delete db[channel].lurkers[user];
|
||||||
|
|
||||||
|
let twitchMessage = formatMessage(
|
||||||
|
lurkMessage,
|
||||||
|
{
|
||||||
|
user,
|
||||||
|
channel,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return h.response(twitchMessage).code(200);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default data;
|
||||||
95
src/main.ts
Normal file
95
src/main.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
// Filepath alias resolution
|
||||||
|
import "module-alias/register";
|
||||||
|
|
||||||
|
// Begin personal code
|
||||||
|
import { Server, Request } from "@hapi/hapi";
|
||||||
|
import basic from "@hapi/basic";
|
||||||
|
import path from "path";
|
||||||
|
import glob from "glob";
|
||||||
|
import toml from "toml";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
const isDev = process.env.NODE_ENV?.startsWith(`dev`);
|
||||||
|
|
||||||
|
// load the config
|
||||||
|
if (!fs.existsSync(`config.toml`)) {
|
||||||
|
console.log(`Please fill out the config and then try starting the server again.`);
|
||||||
|
process.exit(1);
|
||||||
|
};
|
||||||
|
export const config: config = toml.parse(fs.readFileSync(`config.toml`, `utf-8`));
|
||||||
|
|
||||||
|
|
||||||
|
// Load the database
|
||||||
|
if (!fs.existsSync(`data/db.json`)) {
|
||||||
|
console.log(`Can't find database file, creating default`);
|
||||||
|
fs.writeFileSync(`data/db.json`, `{}`);
|
||||||
|
};
|
||||||
|
export var db: database = JSON.parse(fs.readFileSync(`data/db.json`, `utf-8`));
|
||||||
|
|
||||||
|
|
||||||
|
function saveDB() {
|
||||||
|
console.log(`Saving database`);
|
||||||
|
fs.writeFileSync(`data/db.json`, JSON.stringify(db, null, `\t`));
|
||||||
|
process.exit(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.on(`SIGINT`, saveDB);
|
||||||
|
process.on(`SIGTERM`, saveDB);
|
||||||
|
process.on(`uncaughtException`, saveDB);
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
|
||||||
|
const server = new Server({
|
||||||
|
port: config.server.port,
|
||||||
|
routes: {
|
||||||
|
cors: {
|
||||||
|
origin: [
|
||||||
|
isDev ? `*` : `oliver.akins.me/Twitch-Lurk-Message-API/`,
|
||||||
|
],
|
||||||
|
credentials: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.register(basic);
|
||||||
|
server.auth.strategy(`basic`, `basic`, {
|
||||||
|
async validate(request: Request, username: string, password: string) {
|
||||||
|
let isValid = false;
|
||||||
|
let user: account|undefined;
|
||||||
|
for (const account of config.accounts) {
|
||||||
|
if (username == account.username) {
|
||||||
|
user = account;
|
||||||
|
isValid = (
|
||||||
|
password == account.password
|
||||||
|
&& (
|
||||||
|
request.params?.channel == null
|
||||||
|
|| account.access.includes(`*`)
|
||||||
|
|| account.access.includes(request.params.channel)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return { isValid, credentials: { username, access: user?.access } };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
server.auth.default(`basic`);
|
||||||
|
|
||||||
|
// Register all the routes
|
||||||
|
let files = glob.sync(
|
||||||
|
`endpoints/**/!(*.map)`,
|
||||||
|
{ cwd: __dirname, nodir: true}
|
||||||
|
);
|
||||||
|
for (var file of files) {
|
||||||
|
let route = (await import(path.join(__dirname, file))).default;
|
||||||
|
console.log(`Registering route: ${route.method} ${route.path}`);
|
||||||
|
server.route(route);
|
||||||
|
};
|
||||||
|
|
||||||
|
server.start().then(() => {
|
||||||
|
console.log(`Server listening on ${config.server.host}:${config.server.port}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
init();
|
||||||
14
src/types/config.d.ts
vendored
Normal file
14
src/types/config.d.ts
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
interface account {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
access: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface config {
|
||||||
|
server: {
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
};
|
||||||
|
accounts: account[];
|
||||||
|
}
|
||||||
11
src/types/database.d.ts
vendored
Normal file
11
src/types/database.d.ts
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
interface lurk_message {
|
||||||
|
lurk: string[];
|
||||||
|
unlurk: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface database {
|
||||||
|
[index: string]: {
|
||||||
|
lurkers: {[index: string]: string}
|
||||||
|
messages: {[index: string]: lurk_message}
|
||||||
|
};
|
||||||
|
}
|
||||||
4
src/utils.ts
Normal file
4
src/utils.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export function formatMessage(message: string, meta: any): string {
|
||||||
|
return message
|
||||||
|
.replace(/\$\(user\)/, meta.user);
|
||||||
|
};
|
||||||
105
tsconfig.json
Normal file
105
tsconfig.json
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||||
|
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
|
||||||
|
/* Modules */
|
||||||
|
"module": "commonjs", /* Specify what module code is generated. */
|
||||||
|
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||||
|
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
"paths": {
|
||||||
|
"@/*": [ "./src/*" ]
|
||||||
|
}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||||
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
|
/* Emit */
|
||||||
|
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||||
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||||
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||||
|
|
||||||
|
/* Interop Constraints */
|
||||||
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue