@waline/vercel 1.26.3 → 1.26.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/404.html +39 -0
  2. package/dist/500.html +275 -0
  3. package/dist/index.js +58501 -0
  4. package/dist/package.json +54 -0
  5. package/dist/src/config/adapter.js +170 -0
  6. package/dist/src/config/config.js +134 -0
  7. package/dist/src/config/extend.js +38 -0
  8. package/dist/src/config/middleware.js +66 -0
  9. package/dist/src/config/router.js +1 -0
  10. package/dist/src/controller/article.js +91 -0
  11. package/dist/src/controller/comment.js +758 -0
  12. package/dist/src/controller/db.js +71 -0
  13. package/dist/src/controller/index.js +36 -0
  14. package/dist/src/controller/oauth.js +136 -0
  15. package/dist/src/controller/rest.js +60 -0
  16. package/dist/src/controller/token/2fa.js +66 -0
  17. package/dist/src/controller/token.js +75 -0
  18. package/dist/src/controller/user/password.js +52 -0
  19. package/dist/src/controller/user.js +289 -0
  20. package/dist/src/controller/verification.js +35 -0
  21. package/dist/src/extend/controller.js +25 -0
  22. package/dist/src/extend/think.js +84 -0
  23. package/dist/src/locales/en.json +19 -0
  24. package/dist/src/locales/index.js +12 -0
  25. package/dist/src/locales/zh-CN.json +19 -0
  26. package/dist/src/locales/zh-TW.json +19 -0
  27. package/dist/src/logic/article.js +27 -0
  28. package/dist/src/logic/base.js +164 -0
  29. package/dist/src/logic/comment.js +317 -0
  30. package/dist/src/logic/db.js +81 -0
  31. package/dist/src/logic/oauth.js +10 -0
  32. package/dist/src/logic/token/2fa.js +28 -0
  33. package/dist/src/logic/token.js +53 -0
  34. package/dist/src/logic/user/password.js +11 -0
  35. package/dist/src/logic/user.js +117 -0
  36. package/dist/src/middleware/dashboard.js +23 -0
  37. package/dist/src/middleware/version.js +6 -0
  38. package/dist/src/service/akismet.js +41 -0
  39. package/dist/src/service/avatar.js +35 -0
  40. package/dist/src/service/markdown/highlight.js +32 -0
  41. package/dist/src/service/markdown/index.js +63 -0
  42. package/dist/src/service/markdown/katex.js +49 -0
  43. package/dist/src/service/markdown/mathCommon.js +156 -0
  44. package/dist/src/service/markdown/mathjax.js +78 -0
  45. package/dist/src/service/markdown/utils.js +11 -0
  46. package/dist/src/service/markdown/xss.js +44 -0
  47. package/dist/src/service/notify.js +537 -0
  48. package/dist/src/service/storage/base.js +31 -0
  49. package/dist/src/service/storage/cloudbase.js +221 -0
  50. package/dist/src/service/storage/deta.js +307 -0
  51. package/dist/src/service/storage/github.js +377 -0
  52. package/dist/src/service/storage/leancloud.js +430 -0
  53. package/dist/src/service/storage/mongodb.js +179 -0
  54. package/dist/src/service/storage/mysql.js +123 -0
  55. package/dist/src/service/storage/postgresql.js +84 -0
  56. package/dist/src/service/storage/sqlite.js +11 -0
  57. package/dist/src/service/storage/tidb.js +3 -0
  58. package/package.json +1 -1
  59. package/src/controller/comment.js +1 -2
  60. package/src/extend/think.js +19 -0
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@waline/vercel",
3
+ "version": "1.26.3-deta-alpha.0",
4
+ "description": "vercel server for waline comment system",
5
+ "keywords": [
6
+ "waline",
7
+ "vercel",
8
+ "comment",
9
+ "blog"
10
+ ],
11
+ "repository": {
12
+ "url": "https://github.com/walinejs/waline",
13
+ "directory": "packages/server"
14
+ },
15
+ "license": "MIT",
16
+ "author": "lizheming <i@imnerd.org>",
17
+ "dependencies": {
18
+ "@cloudbase/node-sdk": "2.9.1",
19
+ "@koa/cors": "4.0.0",
20
+ "akismet": "2.0.7",
21
+ "deta": "1.1.0",
22
+ "dompurify": "3.0.0",
23
+ "dy-node-ip2region": "1.0.1",
24
+ "fast-csv": "4.3.6",
25
+ "form-data": "4.0.0",
26
+ "jsdom": "21.1.0",
27
+ "jsonwebtoken": "9.0.0",
28
+ "katex": "0.16.4",
29
+ "leancloud-storage": "4.14.0",
30
+ "markdown-it": "13.0.1",
31
+ "markdown-it-emoji": "2.0.2",
32
+ "markdown-it-sub": "1.0.0",
33
+ "markdown-it-sup": "1.0.0",
34
+ "mathjax-full": "3.2.2",
35
+ "node-fetch": "2.6.9",
36
+ "nodemailer": "6.9.1",
37
+ "nunjucks": "3.2.3",
38
+ "phpass": "0.1.1",
39
+ "prismjs": "1.29.0",
40
+ "speakeasy": "2.0.0",
41
+ "think-helper": "1.1.4",
42
+ "think-logger3": "1.3.1",
43
+ "think-model": "1.5.4",
44
+ "think-model-mysql": "1.1.7",
45
+ "think-model-mysql2": "^2.0.0",
46
+ "think-model-postgresql": "1.1.7",
47
+ "think-mongo": "2.2.1",
48
+ "think-router-rest": "1.0.5",
49
+ "ua-parser-js": "1.0.33"
50
+ },
51
+ "engines": {
52
+ "node": ">=14"
53
+ }
54
+ }
@@ -0,0 +1,170 @@
1
+ const { Console } = require('think-logger3');
2
+ const Mysql = require('think-model-mysql');
3
+ const Mysql2 = require('think-model-mysql2');
4
+ const Postgresql = require('think-model-postgresql');
5
+
6
+ let Sqlite = class {};
7
+
8
+ try {
9
+ Sqlite = require('think-model-sqlite');
10
+ } catch (err) {
11
+ console.log(err);
12
+ }
13
+
14
+ const {
15
+ MYSQL_HOST,
16
+ MYSQL_PORT,
17
+ MYSQL_DB,
18
+ MYSQL_USER,
19
+ MYSQL_PASSWORD,
20
+ MYSQL_PREFIX,
21
+ MYSQL_CHARSET,
22
+ MYSQL_SSL,
23
+ TIDB_HOST,
24
+ TIDB_PORT,
25
+ TIDB_DB,
26
+ TIDB_USER,
27
+ TIDB_PASSWORD,
28
+ TIDB_PREFIX,
29
+ TIDB_CHARSET,
30
+ SQLITE_PATH,
31
+ SQLITE_DB,
32
+ SQLITE_PREFIX,
33
+ PG_DB,
34
+ PG_HOST,
35
+ PG_PASSWORD,
36
+ PG_PORT,
37
+ PG_PREFIX,
38
+ PG_USER,
39
+ PG_SSL,
40
+ MONGO_AUTHSOURCE,
41
+ MONGO_DB,
42
+ MONGO_HOST,
43
+ MONGO_PASSWORD,
44
+ MONGO_PORT,
45
+ MONGO_REPLICASET,
46
+ MONGO_USER,
47
+ } = process.env;
48
+
49
+ let type = 'common';
50
+ const mongoOpt = {};
51
+
52
+ if (MONGO_REPLICASET) mongoOpt.replicaSet = MONGO_REPLICASET;
53
+ if (MONGO_AUTHSOURCE) mongoOpt.authSource = MONGO_AUTHSOURCE;
54
+
55
+ if (MONGO_DB) {
56
+ type = 'mongo';
57
+ for (const envKeys in process.env) {
58
+ if (/MONGO_OPT_/.test(envKeys)) {
59
+ const key = envKeys
60
+ .slice(10)
61
+ .toLocaleLowerCase()
62
+ .replace(/_([a-z])/g, (_, b) => b.toUpperCase());
63
+
64
+ mongoOpt[key] = process.env[envKeys];
65
+ }
66
+ }
67
+ } else if (PG_DB) {
68
+ type = 'postgresql';
69
+ } else if (SQLITE_PATH) {
70
+ type = 'sqlite';
71
+ } else if (MYSQL_DB) {
72
+ type = 'mysql';
73
+ } else if (TIDB_DB) {
74
+ type = 'tidb';
75
+ }
76
+
77
+ exports.model = {
78
+ type,
79
+ common: {
80
+ logSql: true,
81
+ logger: (msg) => think.logger.info(msg),
82
+ },
83
+
84
+ mongo: {
85
+ host: MONGO_HOST
86
+ ? MONGO_HOST.startsWith('[')
87
+ ? JSON.parse(MONGO_HOST)
88
+ : MONGO_HOST
89
+ : '127.0.0.1',
90
+ port: MONGO_PORT
91
+ ? MONGO_PORT.startsWith('[')
92
+ ? JSON.parse(MONGO_PORT)
93
+ : MONGO_PORT
94
+ : 27017,
95
+ user: MONGO_USER,
96
+ password: MONGO_PASSWORD,
97
+ database: MONGO_DB,
98
+ options: mongoOpt,
99
+ },
100
+
101
+ postgresql: {
102
+ handle: Postgresql,
103
+ user: PG_USER,
104
+ password: PG_PASSWORD,
105
+ database: PG_DB,
106
+ host: PG_HOST || '127.0.0.1',
107
+ port: PG_PORT || '3211',
108
+ connectionLimit: 1,
109
+ prefix: PG_PREFIX || 'wl_',
110
+ ssl:
111
+ PG_SSL == 'true'
112
+ ? {
113
+ rejectUnauthorized: false,
114
+ }
115
+ : null,
116
+ },
117
+
118
+ sqlite: {
119
+ handle: Sqlite,
120
+ path: SQLITE_PATH,
121
+ database: SQLITE_DB || 'waline',
122
+ connectionLimit: 1,
123
+ prefix: SQLITE_PREFIX || 'wl_',
124
+ },
125
+
126
+ mysql: {
127
+ handle: Mysql,
128
+ dateStrings: true,
129
+ host: MYSQL_HOST || '127.0.0.1',
130
+ port: MYSQL_PORT || '3306',
131
+ database: MYSQL_DB,
132
+ user: MYSQL_USER,
133
+ password: MYSQL_PASSWORD,
134
+ prefix: MYSQL_PREFIX || 'wl_',
135
+ charset: MYSQL_CHARSET || 'utf8mb4',
136
+ ssl:
137
+ MYSQL_SSL === 'true'
138
+ ? {
139
+ rejectUnauthorized: false,
140
+ }
141
+ : null,
142
+ },
143
+
144
+ tidb: {
145
+ handle: Mysql2,
146
+ dateStrings: true,
147
+ host: TIDB_HOST || '127.0.0.1',
148
+ port: TIDB_PORT || '4000',
149
+ database: TIDB_DB,
150
+ user: TIDB_USER,
151
+ password: TIDB_PASSWORD,
152
+ prefix: TIDB_PREFIX || 'wl_',
153
+ charset: TIDB_CHARSET || 'utf8mb4',
154
+ ssl: {
155
+ minVersion: 'TLSv1.2',
156
+ rejectUnauthorized: true,
157
+ },
158
+ },
159
+ };
160
+
161
+ /**
162
+ * logger adapter config
163
+ * @type {Object}
164
+ */
165
+ exports.logger = {
166
+ type: 'console',
167
+ console: {
168
+ handle: Console,
169
+ },
170
+ };
@@ -0,0 +1,134 @@
1
+ const {
2
+ JWT_TOKEN,
3
+ LEAN_KEY,
4
+ MYSQL_DB,
5
+ MYSQL_PASSWORD,
6
+ TIDB_DB,
7
+ TIDB_PASSWORD,
8
+ SQLITE_PATH,
9
+ PG_DB,
10
+ PG_PASSWORD,
11
+ MONGO_DB,
12
+ MONGO_PASSWORD,
13
+ FORBIDDEN_WORDS,
14
+ TCB_ENV,
15
+ TENCENTCLOUD_SECRETKEY,
16
+ TCB_KEY,
17
+ SECURE_DOMAINS,
18
+ DISABLE_USERAGENT,
19
+ DISABLE_REGION,
20
+ AVATAR_PROXY,
21
+ GITHUB_TOKEN,
22
+ DETA_PROJECT_KEY,
23
+ OAUTH_URL,
24
+
25
+ MARKDOWN_CONFIG = '{}',
26
+ MARKDOWN_HIGHLIGHT,
27
+ MARKDOWN_EMOJI,
28
+ MARKDOWN_SUB,
29
+ MARKDOWN_SUP,
30
+ // mathjax will be the default option for tex
31
+ MARKDOWN_TEX = 'mathjax',
32
+ MARKDOWN_MATHJAX = '{}',
33
+ MARKDOWN_KATEX = '{}',
34
+
35
+ MAIL_SUBJECT,
36
+ MAIL_TEMPLATE,
37
+ MAIL_SUBJECT_ADMIN,
38
+ MAIL_TEMPLATE_ADMIN,
39
+ QQ_TEMPLATE,
40
+ TG_TEMPLATE,
41
+ WX_TEMPLATE,
42
+ DISCORD_TEMPLATE,
43
+ LARK_TEMPLATE,
44
+
45
+ LEVELS,
46
+ } = process.env;
47
+
48
+ let storage = 'leancloud';
49
+ let jwtKey = JWT_TOKEN || LEAN_KEY;
50
+
51
+ if (LEAN_KEY) {
52
+ storage = 'leancloud';
53
+ } else if (MONGO_DB) {
54
+ storage = 'mongodb';
55
+ jwtKey = jwtKey || MONGO_PASSWORD;
56
+ } else if (PG_DB) {
57
+ storage = 'postgresql';
58
+ jwtKey = jwtKey || PG_PASSWORD;
59
+ } else if (SQLITE_PATH) {
60
+ storage = 'sqlite';
61
+ } else if (MYSQL_DB) {
62
+ storage = 'mysql';
63
+ jwtKey = jwtKey || MYSQL_PASSWORD;
64
+ } else if (TIDB_DB) {
65
+ storage = 'tidb';
66
+ jwtKey = jwtKey || TIDB_PASSWORD;
67
+ } else if (GITHUB_TOKEN) {
68
+ storage = 'github';
69
+ jwtKey = jwtKey || GITHUB_TOKEN;
70
+ } else if (think.env === 'cloudbase' || TCB_ENV) {
71
+ storage = 'cloudbase';
72
+ jwtKey = jwtKey || TENCENTCLOUD_SECRETKEY || TCB_KEY || TCB_ENV;
73
+ } else if (DETA_PROJECT_KEY) {
74
+ storage = 'deta';
75
+ jwtKey = jwtKey || DETA_PROJECT_KEY;
76
+ }
77
+
78
+ if (think.env === 'cloudbase' && storage === 'sqlite') {
79
+ throw new Error("You can't use SQLite in CloudBase platform.");
80
+ }
81
+
82
+ const forbiddenWords = FORBIDDEN_WORDS ? FORBIDDEN_WORDS.split(/\s*,\s*/) : [];
83
+
84
+ const isFalse = (content) =>
85
+ content && ['0', 'false'].includes(content.toLowerCase());
86
+
87
+ const markdown = {
88
+ config: JSON.parse(MARKDOWN_CONFIG),
89
+ plugin: {
90
+ emoji: !isFalse(MARKDOWN_EMOJI),
91
+ sub: !isFalse(MARKDOWN_SUB),
92
+ sup: !isFalse(MARKDOWN_SUP),
93
+ tex: isFalse(MARKDOWN_TEX) ? false : MARKDOWN_TEX,
94
+ mathjax: JSON.parse(MARKDOWN_MATHJAX),
95
+ katex: JSON.parse(MARKDOWN_KATEX),
96
+ },
97
+ };
98
+
99
+ if (isFalse(MARKDOWN_HIGHLIGHT)) markdown.config.highlight = false;
100
+
101
+ let avatarProxy = '';
102
+
103
+ if (AVATAR_PROXY) {
104
+ avatarProxy = !isFalse(AVATAR_PROXY) ? AVATAR_PROXY : '';
105
+ }
106
+
107
+ const oauthUrl = OAUTH_URL || 'https://oauth.lithub.cc';
108
+
109
+ module.exports = {
110
+ workers: 1,
111
+ storage,
112
+ jwtKey,
113
+ forbiddenWords,
114
+ disallowIPList: [],
115
+ secureDomains: SECURE_DOMAINS ? SECURE_DOMAINS.split(/\s*,\s*/) : undefined,
116
+ disableUserAgent: DISABLE_USERAGENT && !isFalse(DISABLE_USERAGENT),
117
+ disableRegion: DISABLE_REGION && !isFalse(DISABLE_REGION),
118
+ levels:
119
+ !LEVELS || isFalse(LEVELS)
120
+ ? false
121
+ : LEVELS.split(/\s*,\s*/).map((v) => Number(v)),
122
+ avatarProxy,
123
+ oauthUrl,
124
+ markdown,
125
+ mailSubject: MAIL_SUBJECT,
126
+ mailTemplate: MAIL_TEMPLATE,
127
+ mailSubjectAdmin: MAIL_SUBJECT_ADMIN,
128
+ mailTemplateAdmin: MAIL_TEMPLATE_ADMIN,
129
+ QQTemplate: QQ_TEMPLATE,
130
+ TGTemplate: TG_TEMPLATE,
131
+ WXTemplate: WX_TEMPLATE,
132
+ DiscordTemplate: DISCORD_TEMPLATE,
133
+ LarkTemplate: LARK_TEMPLATE,
134
+ };
@@ -0,0 +1,38 @@
1
+ const fetch = require('node-fetch');
2
+ const Model = require('think-model');
3
+ const Mongo = require('think-mongo');
4
+
5
+ module.exports = [
6
+ Model(think.app),
7
+ Mongo(think.app),
8
+ {
9
+ context: {
10
+ get serverURL() {
11
+ const { SERVER_URL } = process.env;
12
+
13
+ if (SERVER_URL) {
14
+ return SERVER_URL;
15
+ }
16
+
17
+ const { protocol, host } = this;
18
+
19
+ return `${protocol}://${host}`;
20
+ },
21
+ async webhook(type, data) {
22
+ const { WEBHOOK } = process.env;
23
+
24
+ if (!WEBHOOK) {
25
+ return;
26
+ }
27
+
28
+ return fetch(WEBHOOK, {
29
+ method: 'POST',
30
+ headers: {
31
+ 'content-type': 'application/json',
32
+ },
33
+ body: JSON.stringify({ type, data }),
34
+ }).then((resp) => resp.json());
35
+ },
36
+ },
37
+ },
38
+ ];
@@ -0,0 +1,66 @@
1
+ const cors = require('@koa/cors');
2
+ const routerREST = require('think-router-rest');
3
+ const isDev = think.env === 'development';
4
+ const isTcb = think.env === 'cloudbase';
5
+ const isDeta = think.env === 'deta' || process.env.DETA_RUNTIME === 'true';
6
+ const isAliyunFC =
7
+ think.env === 'aliyun-fc' || Boolean(process.env.FC_RUNTIME_VERSION);
8
+
9
+ module.exports = [
10
+ {
11
+ handle: 'dashboard',
12
+ match: /^\/ui/,
13
+ },
14
+
15
+ {
16
+ handle: 'meta',
17
+ options: {
18
+ logRequest: isDev,
19
+ sendResponseTime: isDev,
20
+ requestTimeoutCallback: isTcb || isDeta || isAliyunFC ? false : () => {},
21
+ },
22
+ },
23
+
24
+ {
25
+ handle: 'version',
26
+ },
27
+
28
+ { handle: cors },
29
+
30
+ {
31
+ handle: 'trace',
32
+ enable: !think.isCli,
33
+ options: {
34
+ debug: true,
35
+ contentType: () => 'json',
36
+ error(err, ctx) {
37
+ if (/favicon.ico$/.test(ctx.url)) {
38
+ return;
39
+ }
40
+ if (think.isPrevent(err)) {
41
+ return false;
42
+ }
43
+
44
+ console.error(err);
45
+ },
46
+ },
47
+ },
48
+
49
+ {
50
+ handle: 'payload',
51
+ options: {
52
+ keepExtensions: true,
53
+ limit: '5mb',
54
+ },
55
+ },
56
+
57
+ {
58
+ handle: 'router',
59
+ options: {},
60
+ },
61
+
62
+ { handle: routerREST },
63
+
64
+ 'logic',
65
+ 'controller',
66
+ ];
@@ -0,0 +1 @@
1
+ module.exports = [];
@@ -0,0 +1,91 @@
1
+ const BaseRest = require('./rest');
2
+
3
+ module.exports = class extends BaseRest {
4
+ constructor(ctx) {
5
+ super(ctx);
6
+ this.modelInstance = this.service(
7
+ `storage/${this.config('storage')}`,
8
+ 'Counter'
9
+ );
10
+ }
11
+
12
+ async getAction() {
13
+ const { path, type } = this.get();
14
+
15
+ // path is required
16
+ if (!Array.isArray(path) || !path.length) {
17
+ return this.json(0);
18
+ }
19
+
20
+ const resp = await this.modelInstance.select({ url: ['IN', path] });
21
+
22
+ if (think.isEmpty(resp)) {
23
+ const data = type.reduce((o, field) => {
24
+ o[field] = 0;
25
+
26
+ return o;
27
+ }, {});
28
+
29
+ return this.json(type.length === 1 ? data[type[0]] : data);
30
+ }
31
+
32
+ const respObj = resp.reduce((o, n) => {
33
+ o[n.url] = n;
34
+
35
+ return o;
36
+ }, {});
37
+
38
+ const data = [];
39
+
40
+ for (let i = 0; i < path.length; i++) {
41
+ const url = path[i];
42
+ let counters = {};
43
+
44
+ for (let j = 0; j < type.length; j++) {
45
+ const field = type[j];
46
+
47
+ counters[field] =
48
+ respObj[url] && respObj[url][field] ? respObj[url][field] : 0;
49
+ }
50
+
51
+ if (type.length === 1) {
52
+ counters = counters[type[0]];
53
+ }
54
+ data.push(counters);
55
+ }
56
+
57
+ return this.json(path.length === 1 ? data[0] : data);
58
+ }
59
+
60
+ async postAction() {
61
+ const { path, type, action } = this.post();
62
+ const resp = await this.modelInstance.select({ url: path });
63
+
64
+ if (think.isEmpty(resp)) {
65
+ if (action === 'desc') {
66
+ return this.json(0);
67
+ }
68
+
69
+ const count = 1;
70
+
71
+ await this.modelInstance.add(
72
+ { url: path, [type]: count },
73
+ { access: { read: true, write: true } }
74
+ );
75
+
76
+ return this.json(count);
77
+ }
78
+
79
+ const ret = await this.modelInstance.update(
80
+ (counter) => ({
81
+ [type]:
82
+ action === 'desc'
83
+ ? (counter[type] || 1) - 1
84
+ : (counter[type] || 0) + 1,
85
+ }),
86
+ { objectId: ['IN', resp.map(({ objectId }) => objectId)] }
87
+ );
88
+
89
+ return this.json(ret[0][type]);
90
+ }
91
+ };