twikoo-netlify 2.0.0-beta.2 → 2.0.0-beta.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.
- package/dist/index.js +29 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -62,6 +62,9 @@ async dispatch(comment, ctx) {
|
|
|
62
62
|
*
|
|
63
63
|
* 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以
|
|
64
64
|
* HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。
|
|
65
|
+
*
|
|
66
|
+
* **异常不外抛**(1.x 语义):请求处理中的任何异常都转成 HTTP 200 + `code: 1000`。
|
|
67
|
+
* 1.x 的 Netlify 函数是复用 vercel 核心的薄壳,而核心函数从不外抛。
|
|
65
68
|
*/
|
|
66
69
|
/** Netlify 平台能力:全能力*/
|
|
67
70
|
const netlifyCapabilities = _twikoojs_common.FULL_CAPABILITIES;
|
|
@@ -113,25 +116,38 @@ function fromTkResponse(tkRes) {
|
|
|
113
116
|
*/
|
|
114
117
|
function createNetlifyFunc(options = {}) {
|
|
115
118
|
let database = options.database ?? null;
|
|
116
|
-
/**
|
|
117
|
-
|
|
119
|
+
/**
|
|
120
|
+
* 懒建数据库实例(inject 优先)。**不在这里 init**:pipeline 自己会 init 且在同一处 catch 内,
|
|
121
|
+
* 提前 init 会让「连不上数据库」在 pipeline 之外抛错(1.x 连不上也是 200 + code 1000)。
|
|
122
|
+
*/
|
|
123
|
+
const getDatabase = () => {
|
|
118
124
|
database ??= new _twikoojs_common.MongoDatabase({ uri: options.mongoUri ?? process.env.MONGODB_URI ?? "" });
|
|
119
|
-
await database.init();
|
|
120
125
|
return database;
|
|
121
126
|
};
|
|
122
127
|
return async (event) => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
try {
|
|
129
|
+
const request = toTkRequest(event);
|
|
130
|
+
return fromTkResponse(await (0, _twikoojs_common.createHandler)((0, _twikoojs_common.scaffoldAdapters)({
|
|
131
|
+
request: {
|
|
132
|
+
/** 请求恒等透传(归一化见 toTkRequest) */
|
|
127
133
|
toTkRequest: () => request },
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
response: {
|
|
135
|
+
/** TkResponse 恒等透传(序列化见 fromTkResponse) */
|
|
130
136
|
fromTkResponse: (r) => r },
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
database: getDatabase(),
|
|
138
|
+
capabilities: netlifyCapabilities,
|
|
139
|
+
postSubmit: netlifyPostSubmitDispatcher
|
|
140
|
+
}))(request));
|
|
141
|
+
} catch (e) {
|
|
142
|
+
return {
|
|
143
|
+
statusCode: 200,
|
|
144
|
+
headers: { "Content-Type": "application/json" },
|
|
145
|
+
body: JSON.stringify({
|
|
146
|
+
code: _twikoojs_common.RES_CODE.FAIL,
|
|
147
|
+
message: e instanceof Error ? e.message : String(e)
|
|
148
|
+
})
|
|
149
|
+
};
|
|
150
|
+
}
|
|
135
151
|
};
|
|
136
152
|
}
|
|
137
153
|
/** 装配缓存(handler 懒加载语义) */
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["getAxios","RECURSION_HEADER","getRecursionToken","FULL_CAPABILITIES","MongoDatabase","createHandler","scaffoldAdapters"],"sources":["../src/dispatch.ts","../src/main.ts"],"sourcesContent":["/**\n * Netlify 的 POST_SUBMIT 派发实现(规范「后置副作用异步语义」)。\n *\n * **与 1.x 的差异(修正)**:1.x 的 Netlify 适配器是 `require('twikoo-vercel')`\n * 纯转发壳,于是继承了 vercel 的 HTTP 递归——而 vercel 取的是 `VERCEL_URL`,\n * 在 Netlify 上并不存在,自调用实际发不出去(副作用静默丢失)。2.0 独立实现,\n * 改用 Netlify 运行时可用的 `URL`(见下)。\n *\n * **平台事实**(docs.netlify.com「Environment variables and serverless functions」,\n * 查阅 2026-09-18):Netlify Functions **运行时**可用的只读变量只有 `URL` /\n * `SITE_NAME` / `SITE_ID`;`DEPLOY_URL` / `DEPLOY_PRIME_URL` 仅构建期可用。\n * 函数调用路径为 `/.netlify/functions/<函数名>`。\n *\n * 副作用链本身仍在 common 的 postSubmit 服务里。\n */\nimport {\n RECURSION_HEADER,\n getAxios,\n getRecursionToken,\n type PostSubmitDispatcher,\n} from \"@twikoojs/common\";\n\n/** 派发等待上限(毫秒),语义同 Vercel 实现(超时只表示本请求不再等) */\nconst DISPATCH_TIMEOUT_MS = 5000;\n\n/** Netlify Functions 的标准调用路径前缀(函数名为 twikoo) */\nconst FUNCTION_PATH = \"/.netlify/functions/twikoo\";\n\n/**\n * 解析自身函数地址:`TWIKOO_SELF_URL`(完整地址,显式覆写)→\n * `${URL}/.netlify/functions/twikoo`(运行时只读变量)。\n * @returns 绝对地址;URL 缺失时为空串\n */\nfunction resolveSelfUrl(): string {\n const explicit = process.env.TWIKOO_SELF_URL;\n if (explicit) return explicit;\n const siteUrl = process.env.URL;\n return siteUrl ? `${siteUrl.replace(/\\/$/, \"\")}${FUNCTION_PATH}` : \"\";\n}\n\n/** Netlify 的 POST_SUBMIT 派发实现(HTTP 递归自调用) */\nexport const netlifyPostSubmitDispatcher: PostSubmitDispatcher = {\n /**\n * 自调用本函数执行 POST_SUBMIT(不等待副作用完成,只等有界竞速)。\n * @param comment 已入库的评论\n * @param ctx 当前请求上下文(用于取递归令牌与记录日志)\n */\n async dispatch(comment, ctx): Promise<void> {\n const url = resolveSelfUrl();\n if (!url) {\n ctx.logger.warn(\"POST_SUBMIT 派发跳过:未取到自身地址(TWIKOO_SELF_URL / URL)\");\n return;\n }\n const axios = await getAxios();\n await Promise.race([\n axios.post(\n url,\n { event: \"POST_SUBMIT\", comment },\n { headers: { [RECURSION_HEADER]: getRecursionToken(ctx.config) } },\n ),\n new Promise((resolve) => setTimeout(resolve, DISPATCH_TIMEOUT_MS)),\n ]);\n },\n};\n","/**\n * twikoo-netlify 主逻辑(Netlify 独立薄适配器——不再依赖 twikoo-vercel)。\n * 业务逻辑全部在 @twikoojs/common;数据库 MONGODB_URI→Mongo。\n * 平台核对:Functions v1 handler = async (event, context) =>\n * { statusCode, headers, body(string) };IP 头 x-nf-client-connection-ip——\n * docs.netlify.com/functions(查阅 2026-09-17)。1.x 的 TWIKOO_IP_HEADERS\n * 环境变量机制由本适配器消化(公共库不感知该变量)。\n *\n * 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以\n * HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。\n */\nimport {\n FULL_CAPABILITIES,\n MongoDatabase,\n createHandler,\n scaffoldAdapters,\n type Database,\n type TkRequest,\n type TkResponse,\n} from \"@twikoojs/common\";\nimport { netlifyPostSubmitDispatcher } from \"./dispatch\";\n\n/** Netlify 平台能力:全能力*/\nconst netlifyCapabilities = FULL_CAPABILITIES;\n\n/** Netlify Functions v1 事件的最小结构面 */\nexport interface NetlifyEventLike {\n httpMethod: string;\n headers: Record<string, string | string[] | undefined>;\n /** 请求体(Netlify 交付为字符串) */\n body: string | null;\n rawUrl?: string;\n}\n\n/** Netlify 返回体(v1 形态:body 必须为字符串) */\nexport interface NetlifyResult {\n statusCode: number;\n headers: Record<string, string>;\n /** 返回体(isBase64Encoded 缺省 false,JSON 直接字符串化) */\n body: string;\n}\n\n/**\n * Netlify 事件 → 内部统一请求(IP 优先 x-nf-client-connection-ip,1.x 对齐)。\n * @param event Netlify 事件\n * @returns 内部统一请求\n */\nexport function toTkRequest(event: NetlifyEventLike): TkRequest {\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(event.headers ?? {})) {\n if (value !== undefined) headers[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;\n }\n const forwarded = headers[\"x-forwarded-for\"];\n const ip =\n headers[\"x-nf-client-connection-ip\"] ??\n headers[\"x-real-ip\"] ??\n (forwarded ? forwarded.split(\",\")[0].trim() : \"\") ??\n \"\";\n let body = {} as TkRequest[\"body\"];\n try {\n const parsed = event.body ? JSON.parse(event.body) : {};\n if (parsed && typeof parsed === \"object\") body = parsed as TkRequest[\"body\"];\n } catch {\n // 非法 JSON 按空体处理(1.x try/catch 对齐)\n }\n return {\n method: event.httpMethod.toUpperCase(),\n path: \"/\",\n query: {},\n body,\n headers,\n ip,\n raw: event,\n };\n}\n\n/** 内部统一响应 → Netlify 返回体(204 无体;业务体字符串化)。 */\nexport function fromTkResponse(tkRes: TkResponse): NetlifyResult {\n if (tkRes.status === 204) {\n return { statusCode: 204, headers: {}, body: \"\" };\n }\n return {\n statusCode: tkRes.status,\n headers: { ...tkRes.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(tkRes.body),\n };\n}\n\n/**\n * 创建 Netlify 请求处理器(database 可注入;缺省按 MONGODB_URI 懒建连)。\n * @param options 注入项(database:Database 实现;mongoUri:连接串覆写)\n * @returns 逐事件处理器\n */\nexport function createNetlifyFunc(\n options: { database?: Database; mongoUri?: string } = {},\n): (event: NetlifyEventLike) => Promise<NetlifyResult> {\n let database: Database | null = options.database ?? null;\n
|
|
1
|
+
{"version":3,"file":"index.js","names":["getAxios","RECURSION_HEADER","getRecursionToken","FULL_CAPABILITIES","MongoDatabase","createHandler","scaffoldAdapters","RES_CODE"],"sources":["../src/dispatch.ts","../src/main.ts"],"sourcesContent":["/**\n * Netlify 的 POST_SUBMIT 派发实现(规范「后置副作用异步语义」)。\n *\n * **与 1.x 的差异(修正)**:1.x 的 Netlify 适配器是 `require('twikoo-vercel')`\n * 纯转发壳,于是继承了 vercel 的 HTTP 递归——而 vercel 取的是 `VERCEL_URL`,\n * 在 Netlify 上并不存在,自调用实际发不出去(副作用静默丢失)。2.0 独立实现,\n * 改用 Netlify 运行时可用的 `URL`(见下)。\n *\n * **平台事实**(docs.netlify.com「Environment variables and serverless functions」,\n * 查阅 2026-09-18):Netlify Functions **运行时**可用的只读变量只有 `URL` /\n * `SITE_NAME` / `SITE_ID`;`DEPLOY_URL` / `DEPLOY_PRIME_URL` 仅构建期可用。\n * 函数调用路径为 `/.netlify/functions/<函数名>`。\n *\n * 副作用链本身仍在 common 的 postSubmit 服务里。\n */\nimport {\n RECURSION_HEADER,\n getAxios,\n getRecursionToken,\n type PostSubmitDispatcher,\n} from \"@twikoojs/common\";\n\n/** 派发等待上限(毫秒),语义同 Vercel 实现(超时只表示本请求不再等) */\nconst DISPATCH_TIMEOUT_MS = 5000;\n\n/** Netlify Functions 的标准调用路径前缀(函数名为 twikoo) */\nconst FUNCTION_PATH = \"/.netlify/functions/twikoo\";\n\n/**\n * 解析自身函数地址:`TWIKOO_SELF_URL`(完整地址,显式覆写)→\n * `${URL}/.netlify/functions/twikoo`(运行时只读变量)。\n * @returns 绝对地址;URL 缺失时为空串\n */\nfunction resolveSelfUrl(): string {\n const explicit = process.env.TWIKOO_SELF_URL;\n if (explicit) return explicit;\n const siteUrl = process.env.URL;\n return siteUrl ? `${siteUrl.replace(/\\/$/, \"\")}${FUNCTION_PATH}` : \"\";\n}\n\n/** Netlify 的 POST_SUBMIT 派发实现(HTTP 递归自调用) */\nexport const netlifyPostSubmitDispatcher: PostSubmitDispatcher = {\n /**\n * 自调用本函数执行 POST_SUBMIT(不等待副作用完成,只等有界竞速)。\n * @param comment 已入库的评论\n * @param ctx 当前请求上下文(用于取递归令牌与记录日志)\n */\n async dispatch(comment, ctx): Promise<void> {\n const url = resolveSelfUrl();\n if (!url) {\n ctx.logger.warn(\"POST_SUBMIT 派发跳过:未取到自身地址(TWIKOO_SELF_URL / URL)\");\n return;\n }\n const axios = await getAxios();\n await Promise.race([\n axios.post(\n url,\n { event: \"POST_SUBMIT\", comment },\n { headers: { [RECURSION_HEADER]: getRecursionToken(ctx.config) } },\n ),\n new Promise((resolve) => setTimeout(resolve, DISPATCH_TIMEOUT_MS)),\n ]);\n },\n};\n","/**\n * twikoo-netlify 主逻辑(Netlify 独立薄适配器——不再依赖 twikoo-vercel)。\n * 业务逻辑全部在 @twikoojs/common;数据库 MONGODB_URI→Mongo。\n * 平台核对:Functions v1 handler = async (event, context) =>\n * { statusCode, headers, body(string) };IP 头 x-nf-client-connection-ip——\n * docs.netlify.com/functions(查阅 2026-09-17)。1.x 的 TWIKOO_IP_HEADERS\n * 环境变量机制由本适配器消化(公共库不感知该变量)。\n *\n * 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以\n * HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。\n *\n * **异常不外抛**(1.x 语义):请求处理中的任何异常都转成 HTTP 200 + `code: 1000`。\n * 1.x 的 Netlify 函数是复用 vercel 核心的薄壳,而核心函数从不外抛。\n */\nimport {\n FULL_CAPABILITIES,\n MongoDatabase,\n RES_CODE,\n createHandler,\n scaffoldAdapters,\n type Database,\n type TkRequest,\n type TkResponse,\n} from \"@twikoojs/common\";\nimport { netlifyPostSubmitDispatcher } from \"./dispatch\";\n\n/** Netlify 平台能力:全能力*/\nconst netlifyCapabilities = FULL_CAPABILITIES;\n\n/** Netlify Functions v1 事件的最小结构面 */\nexport interface NetlifyEventLike {\n httpMethod: string;\n headers: Record<string, string | string[] | undefined>;\n /** 请求体(Netlify 交付为字符串) */\n body: string | null;\n rawUrl?: string;\n}\n\n/** Netlify 返回体(v1 形态:body 必须为字符串) */\nexport interface NetlifyResult {\n statusCode: number;\n headers: Record<string, string>;\n /** 返回体(isBase64Encoded 缺省 false,JSON 直接字符串化) */\n body: string;\n}\n\n/**\n * Netlify 事件 → 内部统一请求(IP 优先 x-nf-client-connection-ip,1.x 对齐)。\n * @param event Netlify 事件\n * @returns 内部统一请求\n */\nexport function toTkRequest(event: NetlifyEventLike): TkRequest {\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(event.headers ?? {})) {\n if (value !== undefined) headers[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;\n }\n const forwarded = headers[\"x-forwarded-for\"];\n const ip =\n headers[\"x-nf-client-connection-ip\"] ??\n headers[\"x-real-ip\"] ??\n (forwarded ? forwarded.split(\",\")[0].trim() : \"\") ??\n \"\";\n let body = {} as TkRequest[\"body\"];\n try {\n const parsed = event.body ? JSON.parse(event.body) : {};\n if (parsed && typeof parsed === \"object\") body = parsed as TkRequest[\"body\"];\n } catch {\n // 非法 JSON 按空体处理(1.x try/catch 对齐)\n }\n return {\n method: event.httpMethod.toUpperCase(),\n path: \"/\",\n query: {},\n body,\n headers,\n ip,\n raw: event,\n };\n}\n\n/** 内部统一响应 → Netlify 返回体(204 无体;业务体字符串化)。 */\nexport function fromTkResponse(tkRes: TkResponse): NetlifyResult {\n if (tkRes.status === 204) {\n return { statusCode: 204, headers: {}, body: \"\" };\n }\n return {\n statusCode: tkRes.status,\n headers: { ...tkRes.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(tkRes.body),\n };\n}\n\n/**\n * 创建 Netlify 请求处理器(database 可注入;缺省按 MONGODB_URI 懒建连)。\n * @param options 注入项(database:Database 实现;mongoUri:连接串覆写)\n * @returns 逐事件处理器\n */\nexport function createNetlifyFunc(\n options: { database?: Database; mongoUri?: string } = {},\n): (event: NetlifyEventLike) => Promise<NetlifyResult> {\n let database: Database | null = options.database ?? null;\n /**\n * 懒建数据库实例(inject 优先)。**不在这里 init**:pipeline 自己会 init 且在同一处 catch 内,\n * 提前 init 会让「连不上数据库」在 pipeline 之外抛错(1.x 连不上也是 200 + code 1000)。\n */\n const getDatabase = (): Database => {\n database ??= new MongoDatabase({ uri: options.mongoUri ?? process.env.MONGODB_URI ?? \"\" });\n return database;\n };\n return async (event) => {\n try {\n const request = toTkRequest(event);\n const handler = createHandler(\n scaffoldAdapters({\n request: {\n /** 请求恒等透传(归一化见 toTkRequest) */\n toTkRequest: () => request,\n },\n response: {\n /** TkResponse 恒等透传(序列化见 fromTkResponse) */\n fromTkResponse: (r: TkResponse) => r,\n },\n database: getDatabase(),\n capabilities: netlifyCapabilities,\n postSubmit: netlifyPostSubmitDispatcher,\n }),\n );\n return fromTkResponse(await handler(request));\n } catch (e) {\n // 1.x 语义:不外抛(外抛 Netlify 回 502,前端拿不到 code/message)\n return {\n statusCode: 200,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n code: RES_CODE.FAIL,\n message: e instanceof Error ? e.message : String(e),\n }),\n };\n }\n };\n}\n\n/** 装配缓存(handler 懒加载语义) */\nlet handlerFn: ((event: NetlifyEventLike) => Promise<NetlifyResult>) | null = null;\n\n/**\n * Netlify Function 入口(exports.handler 形态,v1 CJS)。\n * @param event Netlify 事件\n * @returns Netlify 返回体\n */\nexport async function handler(event: NetlifyEventLike): Promise<NetlifyResult> {\n handlerFn ??= createNetlifyFunc();\n return handlerFn(event);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuBA,MAAM,sBAAsB;;AAG5B,MAAM,gBAAgB;;;;;;AAOtB,SAAS,iBAAyB;CAChC,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,UAAU,OAAO;CACrB,MAAM,UAAU,QAAQ,IAAI;CAC5B,OAAO,UAAU,GAAG,QAAQ,QAAQ,OAAO,EAAE,IAAI,kBAAkB;AACrE;;AAGA,MAAa,8BAAoD;;;;;;AAM/D,MAAM,SAAS,SAAS,KAAoB;CAC1C,MAAM,MAAM,eAAe;CAC3B,IAAI,CAAC,KAAK;EACR,IAAI,OAAO,KAAK,iDAAiD;EACjE;CACF;CACA,MAAM,QAAQ,OAAA,GAAMA,iBAAAA,SAAAA,CAAS;CAC7B,MAAM,QAAQ,KAAK,CACjB,MAAM,KACJ,KACA;EAAE,OAAO;EAAe;CAAQ,GAChC,EAAE,SAAS,GAAGC,iBAAAA,oBAAAA,GAAmBC,iBAAAA,kBAAAA,CAAkB,IAAI,MAAM,EAAE,EAAE,CACnE,GACA,IAAI,SAAS,YAAY,WAAW,SAAS,mBAAmB,CAAC,CACnE,CAAC;AACH,EACF;;;;;;;;;;;;;;;;;;ACpCA,MAAM,sBAAsBC,iBAAAA;;;;;;AAwB5B,SAAgB,YAAY,OAAoC;CAC9D,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC,GAC3D,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,YAAY,KAAK,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK;CAE1F,MAAM,YAAY,QAAQ;CAC1B,MAAM,KACJ,QAAQ,gCACR,QAAQ,iBACP,YAAY,UAAU,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,OAC9C;CACF,IAAI,OAAO,CAAC;CACZ,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC;EACtD,IAAI,UAAU,OAAO,WAAW,UAAU,OAAO;CACnD,QAAQ,CAER;CACA,OAAO;EACL,QAAQ,MAAM,WAAW,YAAY;EACrC,MAAM;EACN,OAAO,CAAC;EACR;EACA;EACA;EACA,KAAK;CACP;AACF;;AAGA,SAAgB,eAAe,OAAkC;CAC/D,IAAI,MAAM,WAAW,KACnB,OAAO;EAAE,YAAY;EAAK,SAAS,CAAC;EAAG,MAAM;CAAG;CAElD,OAAO;EACL,YAAY,MAAM;EAClB,SAAS;GAAE,GAAG,MAAM;GAAS,gBAAgB;EAAmB;EAChE,MAAM,KAAK,UAAU,MAAM,IAAI;CACjC;AACF;;;;;;AAOA,SAAgB,kBACd,UAAsD,CAAC,GACF;CACrD,IAAI,WAA4B,QAAQ,YAAY;;;;;CAKpD,MAAM,oBAA8B;EAClC,aAAa,IAAIC,iBAAAA,cAAc,EAAE,KAAK,QAAQ,YAAY,QAAQ,IAAI,eAAe,GAAG,CAAC;EACzF,OAAO;CACT;CACA,OAAO,OAAO,UAAU;EACtB,IAAI;GACF,MAAM,UAAU,YAAY,KAAK;GAgBjC,OAAO,eAAe,OAAA,GAfNC,iBAAAA,cAAAA,EAAAA,GACdC,iBAAAA,iBAAAA,CAAiB;IACf,SAAS;;AAEP,mBAAmB,QACrB;IACA,UAAU;;AAER,iBAAiB,MAAkB,EACrC;IACA,UAAU,YAAY;IACtB,cAAc;IACd,YAAY;GACd,CAAC,CAE+B,CAAC,CAAC,OAAO,CAAC;EAC9C,SAAS,GAAG;GAEV,OAAO;IACL,YAAY;IACZ,SAAS,EAAE,gBAAgB,mBAAmB;IAC9C,MAAM,KAAK,UAAU;KACnB,MAAMC,iBAAAA,SAAS;KACf,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;IACpD,CAAC;GACH;EACF;CACF;AACF;;AAGA,IAAI,YAA0E;;;;;;AAO9E,eAAsB,QAAQ,OAAiD;CAC7E,cAAc,kBAAkB;CAChC,OAAO,UAAU,KAAK;AACxB"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FULL_CAPABILITIES, MongoDatabase, RECURSION_HEADER, createHandler, getAxios, getRecursionToken, scaffoldAdapters } from "@twikoojs/common";
|
|
1
|
+
import { FULL_CAPABILITIES, MongoDatabase, RECURSION_HEADER, RES_CODE, createHandler, getAxios, getRecursionToken, scaffoldAdapters } from "@twikoojs/common";
|
|
2
2
|
//#region src/dispatch.ts
|
|
3
3
|
/**
|
|
4
4
|
* Netlify 的 POST_SUBMIT 派发实现(规范「后置副作用异步语义」)。
|
|
@@ -61,6 +61,9 @@ async dispatch(comment, ctx) {
|
|
|
61
61
|
*
|
|
62
62
|
* 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以
|
|
63
63
|
* HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。
|
|
64
|
+
*
|
|
65
|
+
* **异常不外抛**(1.x 语义):请求处理中的任何异常都转成 HTTP 200 + `code: 1000`。
|
|
66
|
+
* 1.x 的 Netlify 函数是复用 vercel 核心的薄壳,而核心函数从不外抛。
|
|
64
67
|
*/
|
|
65
68
|
/** Netlify 平台能力:全能力*/
|
|
66
69
|
const netlifyCapabilities = FULL_CAPABILITIES;
|
|
@@ -112,25 +115,38 @@ function fromTkResponse(tkRes) {
|
|
|
112
115
|
*/
|
|
113
116
|
function createNetlifyFunc(options = {}) {
|
|
114
117
|
let database = options.database ?? null;
|
|
115
|
-
/**
|
|
116
|
-
|
|
118
|
+
/**
|
|
119
|
+
* 懒建数据库实例(inject 优先)。**不在这里 init**:pipeline 自己会 init 且在同一处 catch 内,
|
|
120
|
+
* 提前 init 会让「连不上数据库」在 pipeline 之外抛错(1.x 连不上也是 200 + code 1000)。
|
|
121
|
+
*/
|
|
122
|
+
const getDatabase = () => {
|
|
117
123
|
database ??= new MongoDatabase({ uri: options.mongoUri ?? process.env.MONGODB_URI ?? "" });
|
|
118
|
-
await database.init();
|
|
119
124
|
return database;
|
|
120
125
|
};
|
|
121
126
|
return async (event) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
try {
|
|
128
|
+
const request = toTkRequest(event);
|
|
129
|
+
return fromTkResponse(await createHandler(scaffoldAdapters({
|
|
130
|
+
request: {
|
|
131
|
+
/** 请求恒等透传(归一化见 toTkRequest) */
|
|
126
132
|
toTkRequest: () => request },
|
|
127
|
-
|
|
128
|
-
|
|
133
|
+
response: {
|
|
134
|
+
/** TkResponse 恒等透传(序列化见 fromTkResponse) */
|
|
129
135
|
fromTkResponse: (r) => r },
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
database: getDatabase(),
|
|
137
|
+
capabilities: netlifyCapabilities,
|
|
138
|
+
postSubmit: netlifyPostSubmitDispatcher
|
|
139
|
+
}))(request));
|
|
140
|
+
} catch (e) {
|
|
141
|
+
return {
|
|
142
|
+
statusCode: 200,
|
|
143
|
+
headers: { "Content-Type": "application/json" },
|
|
144
|
+
body: JSON.stringify({
|
|
145
|
+
code: RES_CODE.FAIL,
|
|
146
|
+
message: e instanceof Error ? e.message : String(e)
|
|
147
|
+
})
|
|
148
|
+
};
|
|
149
|
+
}
|
|
134
150
|
};
|
|
135
151
|
}
|
|
136
152
|
/** 装配缓存(handler 懒加载语义) */
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/dispatch.ts","../src/main.ts"],"sourcesContent":["/**\n * Netlify 的 POST_SUBMIT 派发实现(规范「后置副作用异步语义」)。\n *\n * **与 1.x 的差异(修正)**:1.x 的 Netlify 适配器是 `require('twikoo-vercel')`\n * 纯转发壳,于是继承了 vercel 的 HTTP 递归——而 vercel 取的是 `VERCEL_URL`,\n * 在 Netlify 上并不存在,自调用实际发不出去(副作用静默丢失)。2.0 独立实现,\n * 改用 Netlify 运行时可用的 `URL`(见下)。\n *\n * **平台事实**(docs.netlify.com「Environment variables and serverless functions」,\n * 查阅 2026-09-18):Netlify Functions **运行时**可用的只读变量只有 `URL` /\n * `SITE_NAME` / `SITE_ID`;`DEPLOY_URL` / `DEPLOY_PRIME_URL` 仅构建期可用。\n * 函数调用路径为 `/.netlify/functions/<函数名>`。\n *\n * 副作用链本身仍在 common 的 postSubmit 服务里。\n */\nimport {\n RECURSION_HEADER,\n getAxios,\n getRecursionToken,\n type PostSubmitDispatcher,\n} from \"@twikoojs/common\";\n\n/** 派发等待上限(毫秒),语义同 Vercel 实现(超时只表示本请求不再等) */\nconst DISPATCH_TIMEOUT_MS = 5000;\n\n/** Netlify Functions 的标准调用路径前缀(函数名为 twikoo) */\nconst FUNCTION_PATH = \"/.netlify/functions/twikoo\";\n\n/**\n * 解析自身函数地址:`TWIKOO_SELF_URL`(完整地址,显式覆写)→\n * `${URL}/.netlify/functions/twikoo`(运行时只读变量)。\n * @returns 绝对地址;URL 缺失时为空串\n */\nfunction resolveSelfUrl(): string {\n const explicit = process.env.TWIKOO_SELF_URL;\n if (explicit) return explicit;\n const siteUrl = process.env.URL;\n return siteUrl ? `${siteUrl.replace(/\\/$/, \"\")}${FUNCTION_PATH}` : \"\";\n}\n\n/** Netlify 的 POST_SUBMIT 派发实现(HTTP 递归自调用) */\nexport const netlifyPostSubmitDispatcher: PostSubmitDispatcher = {\n /**\n * 自调用本函数执行 POST_SUBMIT(不等待副作用完成,只等有界竞速)。\n * @param comment 已入库的评论\n * @param ctx 当前请求上下文(用于取递归令牌与记录日志)\n */\n async dispatch(comment, ctx): Promise<void> {\n const url = resolveSelfUrl();\n if (!url) {\n ctx.logger.warn(\"POST_SUBMIT 派发跳过:未取到自身地址(TWIKOO_SELF_URL / URL)\");\n return;\n }\n const axios = await getAxios();\n await Promise.race([\n axios.post(\n url,\n { event: \"POST_SUBMIT\", comment },\n { headers: { [RECURSION_HEADER]: getRecursionToken(ctx.config) } },\n ),\n new Promise((resolve) => setTimeout(resolve, DISPATCH_TIMEOUT_MS)),\n ]);\n },\n};\n","/**\n * twikoo-netlify 主逻辑(Netlify 独立薄适配器——不再依赖 twikoo-vercel)。\n * 业务逻辑全部在 @twikoojs/common;数据库 MONGODB_URI→Mongo。\n * 平台核对:Functions v1 handler = async (event, context) =>\n * { statusCode, headers, body(string) };IP 头 x-nf-client-connection-ip——\n * docs.netlify.com/functions(查阅 2026-09-17)。1.x 的 TWIKOO_IP_HEADERS\n * 环境变量机制由本适配器消化(公共库不感知该变量)。\n *\n * 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以\n * HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。\n */\nimport {\n FULL_CAPABILITIES,\n MongoDatabase,\n createHandler,\n scaffoldAdapters,\n type Database,\n type TkRequest,\n type TkResponse,\n} from \"@twikoojs/common\";\nimport { netlifyPostSubmitDispatcher } from \"./dispatch\";\n\n/** Netlify 平台能力:全能力*/\nconst netlifyCapabilities = FULL_CAPABILITIES;\n\n/** Netlify Functions v1 事件的最小结构面 */\nexport interface NetlifyEventLike {\n httpMethod: string;\n headers: Record<string, string | string[] | undefined>;\n /** 请求体(Netlify 交付为字符串) */\n body: string | null;\n rawUrl?: string;\n}\n\n/** Netlify 返回体(v1 形态:body 必须为字符串) */\nexport interface NetlifyResult {\n statusCode: number;\n headers: Record<string, string>;\n /** 返回体(isBase64Encoded 缺省 false,JSON 直接字符串化) */\n body: string;\n}\n\n/**\n * Netlify 事件 → 内部统一请求(IP 优先 x-nf-client-connection-ip,1.x 对齐)。\n * @param event Netlify 事件\n * @returns 内部统一请求\n */\nexport function toTkRequest(event: NetlifyEventLike): TkRequest {\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(event.headers ?? {})) {\n if (value !== undefined) headers[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;\n }\n const forwarded = headers[\"x-forwarded-for\"];\n const ip =\n headers[\"x-nf-client-connection-ip\"] ??\n headers[\"x-real-ip\"] ??\n (forwarded ? forwarded.split(\",\")[0].trim() : \"\") ??\n \"\";\n let body = {} as TkRequest[\"body\"];\n try {\n const parsed = event.body ? JSON.parse(event.body) : {};\n if (parsed && typeof parsed === \"object\") body = parsed as TkRequest[\"body\"];\n } catch {\n // 非法 JSON 按空体处理(1.x try/catch 对齐)\n }\n return {\n method: event.httpMethod.toUpperCase(),\n path: \"/\",\n query: {},\n body,\n headers,\n ip,\n raw: event,\n };\n}\n\n/** 内部统一响应 → Netlify 返回体(204 无体;业务体字符串化)。 */\nexport function fromTkResponse(tkRes: TkResponse): NetlifyResult {\n if (tkRes.status === 204) {\n return { statusCode: 204, headers: {}, body: \"\" };\n }\n return {\n statusCode: tkRes.status,\n headers: { ...tkRes.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(tkRes.body),\n };\n}\n\n/**\n * 创建 Netlify 请求处理器(database 可注入;缺省按 MONGODB_URI 懒建连)。\n * @param options 注入项(database:Database 实现;mongoUri:连接串覆写)\n * @returns 逐事件处理器\n */\nexport function createNetlifyFunc(\n options: { database?: Database; mongoUri?: string } = {},\n): (event: NetlifyEventLike) => Promise<NetlifyResult> {\n let database: Database | null = options.database ?? null;\n
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/dispatch.ts","../src/main.ts"],"sourcesContent":["/**\n * Netlify 的 POST_SUBMIT 派发实现(规范「后置副作用异步语义」)。\n *\n * **与 1.x 的差异(修正)**:1.x 的 Netlify 适配器是 `require('twikoo-vercel')`\n * 纯转发壳,于是继承了 vercel 的 HTTP 递归——而 vercel 取的是 `VERCEL_URL`,\n * 在 Netlify 上并不存在,自调用实际发不出去(副作用静默丢失)。2.0 独立实现,\n * 改用 Netlify 运行时可用的 `URL`(见下)。\n *\n * **平台事实**(docs.netlify.com「Environment variables and serverless functions」,\n * 查阅 2026-09-18):Netlify Functions **运行时**可用的只读变量只有 `URL` /\n * `SITE_NAME` / `SITE_ID`;`DEPLOY_URL` / `DEPLOY_PRIME_URL` 仅构建期可用。\n * 函数调用路径为 `/.netlify/functions/<函数名>`。\n *\n * 副作用链本身仍在 common 的 postSubmit 服务里。\n */\nimport {\n RECURSION_HEADER,\n getAxios,\n getRecursionToken,\n type PostSubmitDispatcher,\n} from \"@twikoojs/common\";\n\n/** 派发等待上限(毫秒),语义同 Vercel 实现(超时只表示本请求不再等) */\nconst DISPATCH_TIMEOUT_MS = 5000;\n\n/** Netlify Functions 的标准调用路径前缀(函数名为 twikoo) */\nconst FUNCTION_PATH = \"/.netlify/functions/twikoo\";\n\n/**\n * 解析自身函数地址:`TWIKOO_SELF_URL`(完整地址,显式覆写)→\n * `${URL}/.netlify/functions/twikoo`(运行时只读变量)。\n * @returns 绝对地址;URL 缺失时为空串\n */\nfunction resolveSelfUrl(): string {\n const explicit = process.env.TWIKOO_SELF_URL;\n if (explicit) return explicit;\n const siteUrl = process.env.URL;\n return siteUrl ? `${siteUrl.replace(/\\/$/, \"\")}${FUNCTION_PATH}` : \"\";\n}\n\n/** Netlify 的 POST_SUBMIT 派发实现(HTTP 递归自调用) */\nexport const netlifyPostSubmitDispatcher: PostSubmitDispatcher = {\n /**\n * 自调用本函数执行 POST_SUBMIT(不等待副作用完成,只等有界竞速)。\n * @param comment 已入库的评论\n * @param ctx 当前请求上下文(用于取递归令牌与记录日志)\n */\n async dispatch(comment, ctx): Promise<void> {\n const url = resolveSelfUrl();\n if (!url) {\n ctx.logger.warn(\"POST_SUBMIT 派发跳过:未取到自身地址(TWIKOO_SELF_URL / URL)\");\n return;\n }\n const axios = await getAxios();\n await Promise.race([\n axios.post(\n url,\n { event: \"POST_SUBMIT\", comment },\n { headers: { [RECURSION_HEADER]: getRecursionToken(ctx.config) } },\n ),\n new Promise((resolve) => setTimeout(resolve, DISPATCH_TIMEOUT_MS)),\n ]);\n },\n};\n","/**\n * twikoo-netlify 主逻辑(Netlify 独立薄适配器——不再依赖 twikoo-vercel)。\n * 业务逻辑全部在 @twikoojs/common;数据库 MONGODB_URI→Mongo。\n * 平台核对:Functions v1 handler = async (event, context) =>\n * { statusCode, headers, body(string) };IP 头 x-nf-client-connection-ip——\n * docs.netlify.com/functions(查阅 2026-09-17)。1.x 的 TWIKOO_IP_HEADERS\n * 环境变量机制由本适配器消化(公共库不感知该变量)。\n *\n * 后置副作用(垃圾检测 + 通知)经 {@link netlifyPostSubmitDispatcher} 以\n * HTTP 递归自调用派发到独立执行单元,见 `./dispatch.ts`。\n *\n * **异常不外抛**(1.x 语义):请求处理中的任何异常都转成 HTTP 200 + `code: 1000`。\n * 1.x 的 Netlify 函数是复用 vercel 核心的薄壳,而核心函数从不外抛。\n */\nimport {\n FULL_CAPABILITIES,\n MongoDatabase,\n RES_CODE,\n createHandler,\n scaffoldAdapters,\n type Database,\n type TkRequest,\n type TkResponse,\n} from \"@twikoojs/common\";\nimport { netlifyPostSubmitDispatcher } from \"./dispatch\";\n\n/** Netlify 平台能力:全能力*/\nconst netlifyCapabilities = FULL_CAPABILITIES;\n\n/** Netlify Functions v1 事件的最小结构面 */\nexport interface NetlifyEventLike {\n httpMethod: string;\n headers: Record<string, string | string[] | undefined>;\n /** 请求体(Netlify 交付为字符串) */\n body: string | null;\n rawUrl?: string;\n}\n\n/** Netlify 返回体(v1 形态:body 必须为字符串) */\nexport interface NetlifyResult {\n statusCode: number;\n headers: Record<string, string>;\n /** 返回体(isBase64Encoded 缺省 false,JSON 直接字符串化) */\n body: string;\n}\n\n/**\n * Netlify 事件 → 内部统一请求(IP 优先 x-nf-client-connection-ip,1.x 对齐)。\n * @param event Netlify 事件\n * @returns 内部统一请求\n */\nexport function toTkRequest(event: NetlifyEventLike): TkRequest {\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(event.headers ?? {})) {\n if (value !== undefined) headers[key.toLowerCase()] = Array.isArray(value) ? value[0] : value;\n }\n const forwarded = headers[\"x-forwarded-for\"];\n const ip =\n headers[\"x-nf-client-connection-ip\"] ??\n headers[\"x-real-ip\"] ??\n (forwarded ? forwarded.split(\",\")[0].trim() : \"\") ??\n \"\";\n let body = {} as TkRequest[\"body\"];\n try {\n const parsed = event.body ? JSON.parse(event.body) : {};\n if (parsed && typeof parsed === \"object\") body = parsed as TkRequest[\"body\"];\n } catch {\n // 非法 JSON 按空体处理(1.x try/catch 对齐)\n }\n return {\n method: event.httpMethod.toUpperCase(),\n path: \"/\",\n query: {},\n body,\n headers,\n ip,\n raw: event,\n };\n}\n\n/** 内部统一响应 → Netlify 返回体(204 无体;业务体字符串化)。 */\nexport function fromTkResponse(tkRes: TkResponse): NetlifyResult {\n if (tkRes.status === 204) {\n return { statusCode: 204, headers: {}, body: \"\" };\n }\n return {\n statusCode: tkRes.status,\n headers: { ...tkRes.headers, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(tkRes.body),\n };\n}\n\n/**\n * 创建 Netlify 请求处理器(database 可注入;缺省按 MONGODB_URI 懒建连)。\n * @param options 注入项(database:Database 实现;mongoUri:连接串覆写)\n * @returns 逐事件处理器\n */\nexport function createNetlifyFunc(\n options: { database?: Database; mongoUri?: string } = {},\n): (event: NetlifyEventLike) => Promise<NetlifyResult> {\n let database: Database | null = options.database ?? null;\n /**\n * 懒建数据库实例(inject 优先)。**不在这里 init**:pipeline 自己会 init 且在同一处 catch 内,\n * 提前 init 会让「连不上数据库」在 pipeline 之外抛错(1.x 连不上也是 200 + code 1000)。\n */\n const getDatabase = (): Database => {\n database ??= new MongoDatabase({ uri: options.mongoUri ?? process.env.MONGODB_URI ?? \"\" });\n return database;\n };\n return async (event) => {\n try {\n const request = toTkRequest(event);\n const handler = createHandler(\n scaffoldAdapters({\n request: {\n /** 请求恒等透传(归一化见 toTkRequest) */\n toTkRequest: () => request,\n },\n response: {\n /** TkResponse 恒等透传(序列化见 fromTkResponse) */\n fromTkResponse: (r: TkResponse) => r,\n },\n database: getDatabase(),\n capabilities: netlifyCapabilities,\n postSubmit: netlifyPostSubmitDispatcher,\n }),\n );\n return fromTkResponse(await handler(request));\n } catch (e) {\n // 1.x 语义:不外抛(外抛 Netlify 回 502,前端拿不到 code/message)\n return {\n statusCode: 200,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n code: RES_CODE.FAIL,\n message: e instanceof Error ? e.message : String(e),\n }),\n };\n }\n };\n}\n\n/** 装配缓存(handler 懒加载语义) */\nlet handlerFn: ((event: NetlifyEventLike) => Promise<NetlifyResult>) | null = null;\n\n/**\n * Netlify Function 入口(exports.handler 形态,v1 CJS)。\n * @param event Netlify 事件\n * @returns Netlify 返回体\n */\nexport async function handler(event: NetlifyEventLike): Promise<NetlifyResult> {\n handlerFn ??= createNetlifyFunc();\n return handlerFn(event);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuBA,MAAM,sBAAsB;;AAG5B,MAAM,gBAAgB;;;;;;AAOtB,SAAS,iBAAyB;CAChC,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,UAAU,OAAO;CACrB,MAAM,UAAU,QAAQ,IAAI;CAC5B,OAAO,UAAU,GAAG,QAAQ,QAAQ,OAAO,EAAE,IAAI,kBAAkB;AACrE;;AAGA,MAAa,8BAAoD;;;;;;AAM/D,MAAM,SAAS,SAAS,KAAoB;CAC1C,MAAM,MAAM,eAAe;CAC3B,IAAI,CAAC,KAAK;EACR,IAAI,OAAO,KAAK,iDAAiD;EACjE;CACF;CACA,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,QAAQ,KAAK,CACjB,MAAM,KACJ,KACA;EAAE,OAAO;EAAe;CAAQ,GAChC,EAAE,SAAS,GAAG,mBAAmB,kBAAkB,IAAI,MAAM,EAAE,EAAE,CACnE,GACA,IAAI,SAAS,YAAY,WAAW,SAAS,mBAAmB,CAAC,CACnE,CAAC;AACH,EACF;;;;;;;;;;;;;;;;;;ACpCA,MAAM,sBAAsB;;;;;;AAwB5B,SAAgB,YAAY,OAAoC;CAC9D,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC,GAC3D,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,YAAY,KAAK,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK;CAE1F,MAAM,YAAY,QAAQ;CAC1B,MAAM,KACJ,QAAQ,gCACR,QAAQ,iBACP,YAAY,UAAU,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,OAC9C;CACF,IAAI,OAAO,CAAC;CACZ,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC;EACtD,IAAI,UAAU,OAAO,WAAW,UAAU,OAAO;CACnD,QAAQ,CAER;CACA,OAAO;EACL,QAAQ,MAAM,WAAW,YAAY;EACrC,MAAM;EACN,OAAO,CAAC;EACR;EACA;EACA;EACA,KAAK;CACP;AACF;;AAGA,SAAgB,eAAe,OAAkC;CAC/D,IAAI,MAAM,WAAW,KACnB,OAAO;EAAE,YAAY;EAAK,SAAS,CAAC;EAAG,MAAM;CAAG;CAElD,OAAO;EACL,YAAY,MAAM;EAClB,SAAS;GAAE,GAAG,MAAM;GAAS,gBAAgB;EAAmB;EAChE,MAAM,KAAK,UAAU,MAAM,IAAI;CACjC;AACF;;;;;;AAOA,SAAgB,kBACd,UAAsD,CAAC,GACF;CACrD,IAAI,WAA4B,QAAQ,YAAY;;;;;CAKpD,MAAM,oBAA8B;EAClC,aAAa,IAAI,cAAc,EAAE,KAAK,QAAQ,YAAY,QAAQ,IAAI,eAAe,GAAG,CAAC;EACzF,OAAO;CACT;CACA,OAAO,OAAO,UAAU;EACtB,IAAI;GACF,MAAM,UAAU,YAAY,KAAK;GAgBjC,OAAO,eAAe,MAfN,cACd,iBAAiB;IACf,SAAS;;AAEP,mBAAmB,QACrB;IACA,UAAU;;AAER,iBAAiB,MAAkB,EACrC;IACA,UAAU,YAAY;IACtB,cAAc;IACd,YAAY;GACd,CAAC,CAE+B,CAAC,CAAC,OAAO,CAAC;EAC9C,SAAS,GAAG;GAEV,OAAO;IACL,YAAY;IACZ,SAAS,EAAE,gBAAgB,mBAAmB;IAC9C,MAAM,KAAK,UAAU;KACnB,MAAM,SAAS;KACf,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;IACpD,CAAC;GACH;EACF;CACF;AACF;;AAGA,IAAI,YAA0E;;;;;;AAO9E,eAAsB,QAAQ,OAAiD;CAC7E,cAAc,kBAAkB;CAChC,OAAO,UAAU,KAAK;AACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "twikoo-netlify",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.4",
|
|
4
4
|
"description": "Twikoo comment system backend for Netlify",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@cap.js/server": "^4.0.5",
|
|
25
25
|
"@imaegoo/node-ip2region": "^2.1.1",
|
|
26
|
-
"@twikoojs/common": "2.0.0-beta.
|
|
27
|
-
"@twikoojs/shared": "2.0.0-beta.
|
|
26
|
+
"@twikoojs/common": "2.0.0-beta.4",
|
|
27
|
+
"@twikoojs/shared": "2.0.0-beta.4",
|
|
28
28
|
"@xsai/generate-text": "^0.5.0",
|
|
29
29
|
"akismet-api": "^6.0.0",
|
|
30
30
|
"axios": "^1.20.0",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"marked": "^18.0.13",
|
|
37
37
|
"mongodb": "^7.6.0",
|
|
38
38
|
"nodemailer": "^10.0.10",
|
|
39
|
-
"pushoo": "^2.0.0-beta.
|
|
39
|
+
"pushoo": "^2.0.0-beta.4",
|
|
40
40
|
"tencentcloud-sdk-nodejs-tms": "^4.1.311",
|
|
41
41
|
"xml2js": "^0.6.2"
|
|
42
42
|
},
|