Files
class/scripts/create-typesense-search-key.mjs
T
2026-07-18 10:58:33 +08:00

79 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFile, writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
const collectionName = process.env.PUBLIC_TYPESENSE_COLLECTION || "class_memories";
const host = process.env.PUBLIC_TYPESENSE_HOST?.replace(/^https?:\/\//, "").replace(/\/$/, "");
const port = process.env.PUBLIC_TYPESENSE_PORT || "443";
const protocol = process.env.PUBLIC_TYPESENSE_PROTOCOL || "https";
const adminKey = process.env.TYPESENSE_ADMIN_API_KEY;
const existingSearchKey = process.env.PUBLIC_TYPESENSE_SEARCH_API_KEY;
const force = process.argv.includes("--force");
if (!host || !adminKey) {
throw new Error(
"缺少 Typesense 配置。请在 .env 或 .env.local 中设置 PUBLIC_TYPESENSE_HOST 和 TYPESENSE_ADMIN_API_KEY。"
);
}
const isPlaceholder = (value) =>
!value || /replace|example|your|请填写|只读密钥/i.test(value);
if (!isPlaceholder(existingSearchKey) && !force) {
throw new Error(
"PUBLIC_TYPESENSE_SEARCH_API_KEY 已存在。如需轮换密钥,请执行 npm run search:key -- --force。"
);
}
const origin = `${protocol}://${host}${
(protocol === "https" && port === "443") || (protocol === "http" && port === "80")
? ""
: `:${port}`
}`;
const response = await fetch(`${origin}/keys`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-TYPESENSE-API-KEY": adminKey
},
body: JSON.stringify({
description: `Search-only key for ${collectionName}`,
actions: ["documents:search"],
collections: [collectionName]
})
});
const responseText = await response.text();
if (!response.ok) {
throw new Error(`创建只读密钥失败:${response.status} ${responseText}`);
}
const result = JSON.parse(responseText);
if (!result.value) {
throw new Error("Typesense 没有返回完整密钥,无法保存配置。请检查服务端响应。" );
}
const envLocalPath = fileURLToPath(new URL("../.env.local", import.meta.url));
let envLocal = "";
try {
envLocal = await readFile(envLocalPath, "utf8");
} catch (error) {
if (error.code !== "ENOENT") throw error;
}
const lineEnding = envLocal.includes("\r\n") ? "\r\n" : "\n";
const assignment = `PUBLIC_TYPESENSE_SEARCH_API_KEY=${JSON.stringify(result.value)}`;
if (/^PUBLIC_TYPESENSE_SEARCH_API_KEY=.*$/m.test(envLocal)) {
envLocal = envLocal.replace(/^PUBLIC_TYPESENSE_SEARCH_API_KEY=.*$/m, assignment);
} else {
const separator = envLocal.length === 0 || envLocal.endsWith("\n") ? "" : lineEnding;
envLocal = `${envLocal}${separator}${assignment}${lineEnding}`;
}
await writeFile(envLocalPath, envLocal, "utf8");
console.log(`已创建仅限 ${collectionName} 的 documents:search 密钥。`);
console.log(`密钥 ID${result.id},已写入 .env.local。`);
console.log("现在可以执行 npm run search:sync 和 npm run build。");