[add] first

This commit is contained in:
建喵 2023-06-02 09:39:43 +08:00
commit 94be48a1d0
20 changed files with 1059 additions and 0 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
npm-debug.log

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
node_modules
.env
package-lock.json
*.pem
.foreverignore
.vscode

25
Dockerfile Normal file
View File

@ -0,0 +1,25 @@
# sudo docker build -t line_catan_groupbuy_ts .
# sudo docker exec -it 2e8e3995aa52 /bin/bash
# 選擇node
FROM node:19.4.0
# 指定NODE_ENV為production
ENV NODE_ENV=production
# 指定預設/工作資料夾
WORKDIR /app
# 只copy package.json檔案
COPY ["package.json", "./"]
# 安裝dependencies
# If you are building your code for production
# RUN npm ci --only=production
RUN npm install
# copy其餘目錄及檔案
COPY . .
# 指定啟動container後執行命令
CMD [ "npm", "start" ]

35
package.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": "line_catan_groupbuy_ts",
"version": "1.0.0",
"description": "",
"main": "src/app.ts",
"scripts": {
"start": "nodemon src/app.ts",
"test": "nodemon src/app.ts",
"dev": "nodemon --exec \"node --require ts-node/register --inspect=192.168.1.15:9229 src/app.ts\"",
"build": "tsc --project ./"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/dateformat": "^5.0.0",
"@types/express": "^4.17.15",
"@types/mysql": "^2.15.21",
"@types/node": "^18.11.18",
"typescript": "^4.9.4"
},
"dependencies": {
"@line/bot-sdk": "^7.5.2",
"dateformat": "^4.5.1",
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"fs": "^0.0.1-security",
"linebot": "^1.6.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.20",
"openai": "^3.1.0",
"ts-node": "^10.9.1",
"xmlhttprequest": "^1.8.0"
}
}

44
src/DBTools.ts Normal file
View File

@ -0,0 +1,44 @@
import mysql from "mysql";
import Tools from "./Tools";
/**
* DBTools
*/
export default class DBTools {
//#region Custom
public static async Query(query: string): Promise<any> {
const conn: mysql.Connection = this.connect();
let resp: any = null;
let run: boolean = true;
conn.query(query, function (err: mysql.MysqlError, rows: any, fields: mysql.FieldInfo[]): void {
if (err) {
console.error(`${query} Error: \n${err.message}`);
run = false;
}
resp = rows;
run = false;
});
while (run) {
await Tools.Sleep(100);
}
conn.end();
return resp;
}
private static connect(): mysql.Connection {
const conn: mysql.Connection = mysql.createConnection({
host: process.env.DB_HOST,
port: +process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE
});
conn.connect();
return conn;
}
//#endregion
}

View File

@ -0,0 +1,116 @@
declare interface Array<T> {
/**
*
* @param index
*/
ExRemoveAt(index: number): T;
/**
* (. )
* @example
*
* let bar: number[] = [1, 2, 3];
* let bar2: number[] = bar;
* bar.Clear();
* console.log(bar, bar2);
*
* // {
* // "bar": [],
* // "bar2": []
* // }
*/
Clear(): void;
/**
* asc&key陣列長度請一樣
* PS. boolean false是先true在false
* @link JavaScript Object http://www.eion.com.tw/Blogger/?Pid=1170#:~:text=JavaScript%20Object%20排序
* @param asc ()
* @param key key()()
*/
ObjectSort(asc?: boolean[], key?: string[]): any[];
/**
* Array<cc.Component.EventHandler>forHoldButton使用
* Add a non persistent listener to the UnityEvent.
* @param call Callback function.
*/
AddListener(call: Function): void;
}
Array.prototype.ExRemoveAt || Object.defineProperty(Array.prototype, "ExRemoveAt", {
enumerable: false,
value: function (index: number): any {
let item: any = this.splice(index, 1);
return item[0];
}
});
Array.prototype.Clear || Object.defineProperty(Array.prototype, "Clear", {
enumerable: false,
value: function (): void {
this.length = 0;
// let foo: number[] = [1, 2, 3];
// let bar: number[] = [1, 2, 3];
// let foo2: number[] = foo;
// let bar2: number[] = bar;
// foo = [];
// bar.length = 0;
// console.log(foo, bar, foo2, bar2);
// {
// "foo": [],
// "bar": [],
// "foo2": [
// 1,
// 2,
// 3
// ],
// "bar2": []
// }
}
});
Array.prototype.ObjectSort || Object.defineProperty(Array.prototype, "ObjectSort", {
enumerable: false,
/**
* @param asc ()
* @param key key()()
*/
value: function (asc: boolean[] = [true], key?: string[]): any[] {
if (this.length === 0) {
return this;
} else if (!key || key.length === 0) {
console.error(`ObjectSort key error`);
return this;
} else if (asc.length !== key.length) {
console.error(`ObjectSort key asc error asc.length: ${asc.length}, key.length: ${key.length}`);
return this;
}
for (let i: number = 0; i < key.length; i++) {
const keyname: string = key[i];
if (this[0][keyname] === undefined) {
console.error(`ObjectSort has not key[${i}]: ${keyname}`);
return this;
}
}
let count: number = key ? key.length : 1;
let arr: any[];
for (let i: number = count - 1; i >= 0; i--) {
arr = this.sort(function (a: any, b: any): 1 | -1 {
let mya: any = a;
let myb: any = b;
if (key) {
mya = a[key[i]];
myb = b[key[i]];
}
// 加個等於數字相同不要再去排序到
if (asc[i]) {
return mya >= myb ? 1 : -1;
} else {
return mya <= myb ? 1 : -1;
}
});
}
return arr;
}
});

View File

@ -0,0 +1,10 @@
{
"ver": "1.1.0",
"uuid": "b373f805-9297-4af5-8ea6-0a250649b5b0",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@ -0,0 +1,189 @@
declare interface Number {
/**
* (), 2
* 41,038,560.00
* @param precision
* @param isPadZero
* */
ExFormatNumberWithComma(precision?: number, isPadZero?: boolean): string;
/**
* 4(9,999-999B-T)
* */
ExTransferToBMK(precision?: number,offset?: number): string;
/**
* , 0
* @param size
*/
Pad(size: number): string;
/**
* X位 (server計算規則)
* @param precision
*/
ExToNumRoundDecimal(precision: number): number;
/**
* X位
* @param precision
*/
ExToNumFloorDecimal(precision: number): number;
/**
* X位小數2200.2.00
* @param precision
* @param isPadZero
*/
ExToStringFloorDecimal(precision: number, isPadZero?: boolean): string;
/**
* )
*/
ExToInt():number;
/**
* ()
*/
Float2Fixed():number;
/**
* ()
*/
DigitLength():number;
target: number;
}
Number.prototype.ExFormatNumberWithComma || Object.defineProperty(Number.prototype, 'ExFormatNumberWithComma', {
enumerable: false,
value: function (precision: number = 2, isPadZero: boolean = true) {
// let arr = String(this).split('.');
let arr = this.ExToStringFloorDecimal(precision, isPadZero).split('.');
let num = arr[0], result = '';
while (num.length > 3) {
result = ',' + num.slice(-3) + result;
num = num.slice(0, num.length - 3);
}
if (num.length > 0) result = num + result;
return arr[1] ? result + '.' + arr[1] : result;
}
})
Number.prototype.ExTransferToBMK || Object.defineProperty(Number.prototype, 'ExTransferToBMK', {
enumerable: false,
value: function (precision: number=2,offset: number = 0) {
/**千 */
let MONEY_1K: number = 1000;
/**萬 */
// let MONEY_10K: number = 10000;
/**十萬 */
// let MONEY_100K: number = 100000;
/**百萬 */
let MONEY_1M: number = 1000000;
/**千萬 */
// let MONEY_10M: number = 10000000;
/**億 */
// let MONEY_100M: number = 100000000;
/**十億 */
let MONEY_1B: number = 1000000000;
/**百億 */
// let MONEY_10B: number = 10000000000;
/**千億 */
// let MONEY_100B: number = 100000000000;
/**兆 */
// let MONEY_1T: number = 1000000000000;
offset = Math.pow(10, offset);
// if (this >= MONEY_1T * offset) {
// //(3)1,000T
// //1T~
// return (~~(this / MONEY_1T)).ExFormatNumberWithComma(0) + "T";
// }
if (this >= MONEY_1B * offset) {
//1,000B~900,000B
//1B~900B
return (this / MONEY_1B).ExFormatNumberWithComma(3, false) + "B";
}
else if (this >= MONEY_1M * offset) {
//1,000M~900,000M
//1M~900M
return (this / MONEY_1M).ExFormatNumberWithComma(3, false) + "M";
}
else if (this >= MONEY_1K * offset) {
//1,000K~900,000K
//1K~90K
return (this / MONEY_1K).ExFormatNumberWithComma(3, false) + "K";
}
else {
//0~9,000,000
//0~9,000
return this.ExFormatNumberWithComma(precision);
}
}
})
Number.prototype.Pad || Object.defineProperty(Number.prototype, 'Pad', {
enumerable: false,
value: function (size: number) {
let s = this + "";
while (s.length < size) s = "0" + s;
return s;
}
})
Number.prototype.ExToNumRoundDecimal || Object.defineProperty(Number.prototype, 'ExToNumRoundDecimal', {
enumerable: false,
value: function (precision: number) {
return Math.round(Math.round(this * Math.pow(10, (precision || 0) + 1)) / 10) / Math.pow(10, (precision || 0));
}
})
Number.prototype.ExToInt || Object.defineProperty(Number.prototype, 'ExToInt',{
enumerable: false,
value: function (){
return ~~this;
}
})
Number.prototype.ExToNumFloorDecimal || Object.defineProperty(Number.prototype, 'ExToNumFloorDecimal', {
enumerable: false,
value: function (precision: number) {
let str = this.toPrecision(12);
let dotPos = str.indexOf('.');
return dotPos == -1 ? this : +`${str.substr(0, dotPos + 1 + precision)}`;
}
})
Number.prototype.ExToStringFloorDecimal || Object.defineProperty(Number.prototype, 'ExToStringFloorDecimal', {
enumerable: false,
value: function (precision: number, isPadZero: boolean = true) {
// 取小數點第X位
let f = this.ExToNumFloorDecimal(precision);
let s = f.toString();
// 補0
if (isPadZero) {
let rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + precision) {
s += '0';
}
}
return s;
}
})
Number.prototype.Float2Fixed || Object.defineProperty(Number.prototype, 'Float2Fixed', {
enumerable: false,
value: function () {
if (this.toString().indexOf('e') === -1) {
return Number(this.toString().replace('.', ''));
}
const dLen = this.DigitLength();
return dLen > 0 ? +parseFloat((this * Math.pow(10, dLen)).toPrecision(12)) : this;
}
})
Number.prototype.DigitLength || Object.defineProperty(Number.prototype, 'DigitLength', {
enumerable: false,
value: function () {
const eSplit = this.toString().split(/[eE]/);
const len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));
return len > 0 ? len : 0;
}
})

View File

@ -0,0 +1,84 @@
export module NumberEx {
/**
*
* @param {*number} num
*/
function checkBoundary(num: number) {
if (_boundaryCheckingState) {
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
}
}
}
/**
*
*/
export function times(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return times(times(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = num1.Float2Fixed();
const num2Changed = num2.Float2Fixed();
const baseNum = num1.DigitLength() + num2.DigitLength();
const leftValue = num1Changed * num2Changed;
checkBoundary(leftValue);
return leftValue / Math.pow(10, baseNum);
}
/**
*
*/
export function plus(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return plus(plus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
}
/**
*
*/
export function minus(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return minus(minus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
}
/**
*
*/
export function divide(num1: number, num2: number, ...others: number[]): number {
if (others.length > 0) {
return divide(divide(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = num1.Float2Fixed();
const num2Changed = num2.Float2Fixed();
checkBoundary(num1Changed);
checkBoundary(num2Changed);
return times((num1Changed / num2Changed), Math.pow(10, num2.DigitLength() - num1.DigitLength()));
}
/**
*
*/
export function round(num: number, ratio: number): number {
const base = Math.pow(10, ratio);
return divide(Math.round(times(num, base)), base);
}
let _boundaryCheckingState = false;
/**
*
* @param flag true false
*/
function enableBoundaryChecking(flag = true) {
_boundaryCheckingState = flag;
}
}

View File

@ -0,0 +1,90 @@
export module RandomEx {
/**
*
*/
export function GetBool() {
return GetInt() >= 0;
}
/**
* (min ~ max - 1)
* @param min
* @param max
*/
export function GetInt(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
return Math.floor(Math.random() * (max - min)) + min;
}
/**
*
* @param min
* @param max
*/
export function GetFloat(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
return Math.random() * (max - min) + min;
}
/**
*
* @param num
* @param items
*/
export function GetMultiNoRepeat(num: number, items: any[]): any[] {
let result: any[] = [];
for (let i: number = 0; i < num; i++) {
let ran: number = Math.floor(Math.random() * items.length);
let item = items.splice(ran, 1)[0];
if (result.indexOf(item) == -1) {
result.push(item);
}
};
return result;
}
/**
*
* @param prize
* @param weights
* @param count
*/
export function GetMultiNoRepeatByWeight(prize: any[], weights: number[] = null, count: number = 1): any[] {
if (weights === null) {
weights = [];
for (let i: number = 0; i < prize.length; i++) {
weights.push(1);
}
}
let target: any[] = [];
for (let i: number = 0; i < count; i++) {
let results: number[] = RandomEx.GetPrizeByWeight(prize, weights);
prize.splice(results[0], 1);
weights.splice(results[0], 1);
target.push(results[1]);
}
return target;
}
/**
*
* @param prize
* @param weights
*/
export function GetPrizeByWeight(prize: any[], weights: number[]): any[] {
if (prize.length !== weights.length) {
console.error(`GetWeight error -> prize.length:${prize.length} !== weights.length:${weights.length}`);
return null;
}
let totalWeight: number = 0;
for (let i: number = 0; i < weights.length; i++) {
totalWeight += weights[i];
}
let random: number = RandomEx.GetInt(0, totalWeight) + 1;
let nowWeight: number = weights[0];
for (let i: number = 0; i < weights.length; i++) {
if (nowWeight >= random) {
return [i, prize[i]];
}
nowWeight += weights[i + 1];
}
}
}

16
src/Engine/String.ts Normal file
View File

@ -0,0 +1,16 @@
interface StringConstructor {
IsNullOrEmpty: (value: string) => boolean;
Format: (format: string, ...args: any[]) => string;
}
String.IsNullOrEmpty = function (value: string): boolean {
return value === undefined || value === null || value.trim() === "";
};
String.Format = function (format: string, ...args: any[]): string {
return format.replace(/{(\d+)}/g, (match, index) => {
let value: any = args[index];
if (value === null || value === undefined) { return ""; }
return "" + value;
});
};

37
src/LineNotify.ts Normal file
View File

@ -0,0 +1,37 @@
/**
* LineNotify
*/
export default class LineNotify {
//#region Custom
public static Send(message: string): void {
const data: string = `message=\n${message}`;
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function (): void {
if (this.readyState === 4) {
// console.log(this.responseText);
}
});
xhr.open("POST", "https://notify-api.line.me/api/notify");
xhr.setRequestHeader("Authorization", "Bearer Dkv8Yh1Li3XsKFqZkmFMNP5o0JDSvan7qfcDmSv9GJr");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
}
public static SendBadmintonNotify(): void {
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function (): void {
if (this.readyState === 4) {
// console.log(this.responseText);
}
});
xhr.open("POST", "http://jianmiau.tk:1880/BadmintonNotify");
xhr.send();
}
//#endregion
}

55
src/MemberJoinedClass.ts Normal file
View File

@ -0,0 +1,55 @@
import * as line from "@line/bot-sdk";
import LineNotify from "./LineNotify";
/**
* MemberJoined
*/
export default class MemberJoinedClass {
//#region private
private bot: line.Client = null;
//#endregion
//#region Lifecycle
constructor(bot: line.Client) {
this.bot = bot;
}
//#endregion
//#region Custom
public async MemberJoined(event: any): Promise<void> {
switch (event.source.groupId) {
case process.env.toBadminton: {
this.badminton_MemberJoin(event);
break;
}
default:
break;
}
}
private async badminton_MemberJoin(event: any): Promise<void> {
const members: any[] = event.joined.members;
for (let i: number = 0; i < members.length; i++) {
const userId: string = members[i].userId;
this.sendBadminton_Welcome(event, event.source.groupId, userId);
}
}
private async sendBadminton_Welcome(event: any, groupId: string, userId: string): Promise<void> {
const userdata: line.Profile = await this.bot.getGroupMemberProfile(groupId, userId);
if (userdata && userdata.displayName) {
const message: string = `歡迎尊貴的 ${userdata.displayName} 降臨羽球團`;
event.reply(message);
LineNotify.SendBadmintonNotify();
}
}
//#endregion
}

87
src/MessageClass.ts Normal file
View File

@ -0,0 +1,87 @@
import * as line from "@line/bot-sdk";
import GroupBuy from "./GroupBuy";
/**
* Message
*/
export default class MessageClass {
//#region private
private bot: line.Client = null;
//#endregion
//#region Lifecycle
constructor(bot: line.Client) {
this.bot = bot;
}
//#endregion
//#region Custom
public async Message(event: any): Promise<void> {
switch (event.message.type) {
case "text": {
return await this.Text(event);
}
default:
break;
}
}
public async Text(event: any): Promise<void> {
switch (event.source.type) {
case "group": {
return await this.Group(event);
}
default:
break;
}
}
public async Group(event: any): Promise<any> {
let groupId: string = event.source.groupId;
// 團購 特別功能
if ([process.env.toGroupBuy].includes(groupId)) {
/** 訊息 */
let msg: string[] = event.message.text.split(" ");
/** 指令 */
let instruction: string = msg[0];
switch (instruction) {
case "團購": {
const messages: line.Message | line.Message[] = await GroupBuy.Run(event, msg, this.bot);
if (messages) {
return this.bot.replyMessage(event.replyToken, messages);
}
}
default: {
break;
}
}
}
}
// Group(event) {
// switch (event.source.groupId) {
// case process.env.toYoutube: {
// let messagereplace = event.message.text;
// messagereplace.replace("【IFTTT】 \n", "");
// let replyMsg = messagereplace;
// let res_toUniversity = this.bot.pushMessage(process.env.toUniversity, replyMsg);
// let res_toApex = this.bot.pushMessage(process.env.toApex, replyMsg);
// break;
// }
// default:
// break;
// }
// }
//#endregion
}

35
src/OpenAI.ts Normal file
View File

@ -0,0 +1,35 @@
import { Configuration, CreateCompletionResponseChoicesInner, OpenAIApi } from "openai";
/**
* OpenAI
*/
export default class OpenAI {
//#region Custom
public static async RunOpenAI(msg: string): Promise<string> {
const configuration: Configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai: OpenAIApi = new OpenAIApi(configuration);
// tslint:disable-next-line:typedef
const response = await openai.createCompletion({
model: "text-davinci-003",
prompt: "你:" + msg,
temperature: 0.7,
max_tokens: 256,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
});
let resptext: string = msg;
const choices: CreateCompletionResponseChoicesInner[] = response.data.choices;
for (let i: number = 0; i < choices.length; i++) {
const choice: CreateCompletionResponseChoicesInner = choices[i];
resptext += choice.text;
}
return resptext;
}
//#endregion
}

76
src/PostbackClass.ts Normal file
View File

@ -0,0 +1,76 @@
import * as line from "@line/bot-sdk";
import GroupBuy from "./GroupBuy";
/**
* Postback
*/
export default class PostbackClass {
//#region private
private bot: line.Client = null;
//#endregion
//#region Lifecycle
constructor(bot: line.Client) {
this.bot = bot;
}
//#endregion
//#region Custom
public async Postback(event: any): Promise<void> {
switch (event.source.type) {
case "group": {
return await this.Group(event);
}
default:
break;
}
}
public async Group(event: any): Promise<any> {
let groupId: string = event.source.groupId;
// 團購 特別功能
if ([process.env.toGroupBuy].includes(groupId)) {
/** 訊息 */
let msg: string[] = event.postback.data.split(" ");
/** 指令 */
let instruction: string = msg[0];
switch (instruction) {
case "團購": {
const messages: line.Message | line.Message[] = await GroupBuy.Run(event, msg, this.bot);
if (messages) {
return this.bot.replyMessage(event.replyToken, messages);
}
}
default: {
break;
}
}
}
}
// Group(event) {
// switch (event.source.groupId) {
// case process.env.toYoutube: {
// let messagereplace = event.message.text;
// messagereplace.replace("【IFTTT】 \n", "");
// let replyMsg = messagereplace;
// let res_toUniversity = this.bot.pushMessage(process.env.toUniversity, replyMsg);
// let res_toApex = this.bot.pushMessage(process.env.toApex, replyMsg);
// break;
// }
// default:
// break;
// }
// }
//#endregion
}

13
src/Tools.ts Normal file
View File

@ -0,0 +1,13 @@
/**
* Tools
*/
export default class Tools {
//#region Custom
public static Sleep(ms: number): Promise<any> {
return new Promise(resolve => setTimeout(resolve, ms));
}
//#endregion
}

16
src/app.ts Normal file
View File

@ -0,0 +1,16 @@
// 背景執行 forever start -c ts-node -a -l line-bot-ts.log src/app.ts
// 重新背景執行 forever restart -a -l line-bot-ts.log src/app.ts
// 監聽檔案變化 "npm start"
// 連線Debug "npm run dev"
import dayjs from "dayjs";
import "dayjs/locale/zh-tw";
import dotenv from "dotenv";
import "./Engine/CCExtensions/ArrayExtension";
import "./Engine/CCExtensions/NumberExtension";
import "./Engine/String";
import LineBotClass from "./LineBotClass";
dayjs.locale("zh-tw");
dotenv.config();
new LineBotClass();

16
tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "commonjs", /* Specify what module code is generated. */
"lib": [
"es2015",
"es2017",
"dom"
],
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": false, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */,
"outDir": "dist" // jsdist
}
}

107
tslint.json Normal file
View File

@ -0,0 +1,107 @@
{
"defaultSeverity": "warning",
"rules": {
"ban": [
true,
[
"_",
"extend"
],
[
"_",
"isNull"
],
[
"_",
"isDefined"
]
],
"class-name": false,
"comment-format": [
false,
"check-space"
],
"curly": true,
"eofline": false,
"forin": false,
"indent": [
true,
4
],
"interface-name": [
false,
"never-prefix"
],
"jsdoc-format": false,
"label-position": true,
"max-line-length": [
false,
140
],
"no-arg": true,
"no-bitwise": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": true,
// "no-eval": true,
"no-string-literal": false,
"no-trailing-whitespace": true,
"no-unused-expression": false,
"no-unused-variable": true,
"no-use-before-declare": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"quotemark": [
true,
"double"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef": [
true,
"call-signature",
"parameter",
"property-declaration",
"variable-declaration"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace"
},
{
"index-signature": "space"
}
],
"variable-name": false,
"whitespace": [
false,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}