fedincms-cli 0.0.1 → 0.0.3
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/README.md +6 -6
- package/dist/cli.js +57 -50
- package/package.json +1 -1
- package/templates/skill/SKILL.md +2 -2
- package/templates/skill/reference.md +5 -5
- package/templates/skill/scripts/fedin-cms-cli.js +2 -3
package/README.md
CHANGED
|
@@ -23,13 +23,13 @@ npm install -g @your-scope/fedin-cms-cli
|
|
|
23
23
|
cd /path/to/your-project
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
2.
|
|
26
|
+
2. 初始化:只需传入**站点密钥**(格式 `cms_<base64>`),会解密得到 websiteId 与 userId 并写入脚本:
|
|
27
27
|
```bash
|
|
28
|
-
fedincms init
|
|
29
|
-
#
|
|
30
|
-
fedincms init
|
|
31
|
-
#
|
|
32
|
-
fedincms init --website
|
|
28
|
+
fedincms init cms_website_key=你的站点密钥
|
|
29
|
+
# 或带可选 API 地址、密钥
|
|
30
|
+
fedincms init cms_website_key=你的站点密钥 apiUrl=https://... anonKey=你的密钥
|
|
31
|
+
# 长选项
|
|
32
|
+
fedincms init --cms-website-key=你的站点密钥 --api-url=... --anon-key=...
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
3. 在 Cursor 中打开该项目,AI 将根据 `.cursor/skills/fedin-cms/SKILL.md` 在需要时执行:
|
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,27 @@ const TEMPLATE_DIR = path.join(__dirname, '..', 'templates', 'skill');
|
|
|
8
8
|
const SKILL_DIR = '.cursor/skills/fedin-cms';
|
|
9
9
|
const SKILL_SCRIPTS_DIR = '.cursor/skills/fedin-cms/scripts';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* 解密站点密钥,得到 websiteId 和 userId
|
|
13
|
+
* @param {string} key - 格式为 cms_<base64url>
|
|
14
|
+
* @returns {{ websiteId: string, userId: string }}
|
|
15
|
+
*/
|
|
16
|
+
function decodeWebsiteKey(key) {
|
|
17
|
+
const PREFIX = 'cms_';
|
|
18
|
+
if (!key || typeof key !== 'string' || !key.startsWith(PREFIX)) {
|
|
19
|
+
throw new Error('Invalid website key format');
|
|
20
|
+
}
|
|
21
|
+
const base64 = key.slice(PREFIX.length).replace(/-/g, '+').replace(/_/g, '/');
|
|
22
|
+
const pad = base64.length % 4;
|
|
23
|
+
const padded = pad ? base64 + '='.repeat(4 - pad) : base64;
|
|
24
|
+
const json = Buffer.from(padded, 'base64').toString('utf8');
|
|
25
|
+
const out = JSON.parse(json);
|
|
26
|
+
if (typeof out?.userId !== 'string' || typeof out?.websiteId !== 'string') {
|
|
27
|
+
throw new Error('Invalid website key payload');
|
|
28
|
+
}
|
|
29
|
+
return { userId: out.userId, websiteId: out.websiteId };
|
|
30
|
+
}
|
|
31
|
+
|
|
11
32
|
function parseArgs(argv) {
|
|
12
33
|
const args = { _: [] };
|
|
13
34
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -25,17 +46,13 @@ function parseArgs(argv) {
|
|
|
25
46
|
if (eq > 0) {
|
|
26
47
|
const k = arg.slice(2, eq).replace(/-/g, '');
|
|
27
48
|
const v = arg.slice(eq + 1);
|
|
28
|
-
if (k === '
|
|
29
|
-
else if (k === 'apiurl') args.apiUrl = v;
|
|
30
|
-
else if (k === 'anonkey') args.anonKey = v;
|
|
49
|
+
if (k === 'cmswebsitekey' || k === 'cms_website_key') args.cmsWebsiteKey = v;
|
|
31
50
|
}
|
|
32
51
|
continue;
|
|
33
52
|
}
|
|
34
53
|
if (arg.includes('=')) {
|
|
35
54
|
const [k, v] = arg.split('=').map(s => s.trim());
|
|
36
|
-
if (k === '
|
|
37
|
-
else if (k === 'apiUrl') args.apiUrl = v;
|
|
38
|
-
else if (k === 'anonKey') args.anonKey = v;
|
|
55
|
+
if (k === 'cms_website_key' || k === 'cmsWebsiteKey') args.cmsWebsiteKey = v;
|
|
39
56
|
continue;
|
|
40
57
|
}
|
|
41
58
|
args._.push(arg);
|
|
@@ -57,24 +74,16 @@ function copyFile(src, dest, force) {
|
|
|
57
74
|
return true;
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (fs.existsSync(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
function appendEnv(lines) {
|
|
71
|
-
const { envPath, content } = readOrCreateEnv();
|
|
72
|
-
const toAdd = lines.filter(line => {
|
|
73
|
-
const key = line.split('=')[0].trim();
|
|
74
|
-
return !content.includes(key + '=');
|
|
75
|
-
});
|
|
76
|
-
if (toAdd.length === 0) return;
|
|
77
|
-
fs.writeFileSync(envPath, content + '\n# Fedin CMS (fedincms init)\n' + toAdd.join('\n') + '\n', 'utf8');
|
|
77
|
+
// 复制脚本并替换占位符 __FEDINCMS_WEBSITE_ID__、__FEDINCMS_USER_ID__
|
|
78
|
+
function copyScriptWithPlaceholders(srcPath, destRel, placeholders, force) {
|
|
79
|
+
const destFull = path.join(process.cwd(), destRel);
|
|
80
|
+
if (!force && fs.existsSync(destFull)) return false;
|
|
81
|
+
ensureDir(path.dirname(destFull));
|
|
82
|
+
let content = fs.readFileSync(srcPath, 'utf8');
|
|
83
|
+
content = content.replace(/__FEDINCMS_WEBSITE_ID__/g, placeholders.websiteId || '');
|
|
84
|
+
content = content.replace(/__FEDINCMS_USER_ID__/g, placeholders.userId || '');
|
|
85
|
+
fs.writeFileSync(destFull, content, 'utf8');
|
|
86
|
+
return true;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
function runInit(options) {
|
|
@@ -85,9 +94,20 @@ function runInit(options) {
|
|
|
85
94
|
process.exit(1);
|
|
86
95
|
}
|
|
87
96
|
|
|
88
|
-
const
|
|
89
|
-
if (!
|
|
90
|
-
console.error('fedincms init: 缺少必填参数
|
|
97
|
+
const key = options.cmsWebsiteKey;
|
|
98
|
+
if (!key) {
|
|
99
|
+
console.error('fedincms init: 缺少必填参数 cms_website_key。用法: fedincms init cms_website_key=xxxxx [apiUrl=...] [anonKey=...]');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let websiteId;
|
|
104
|
+
let userId;
|
|
105
|
+
try {
|
|
106
|
+
const decoded = decodeWebsiteKey(key);
|
|
107
|
+
websiteId = decoded.websiteId;
|
|
108
|
+
userId = decoded.userId;
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.error('fedincms init: 站点密钥解密失败:', e.message);
|
|
91
111
|
process.exit(1);
|
|
92
112
|
}
|
|
93
113
|
|
|
@@ -102,23 +122,11 @@ function runInit(options) {
|
|
|
102
122
|
const scriptJs = path.join(templateBase, 'scripts', 'fedin-cms-cli.js');
|
|
103
123
|
if (fs.existsSync(skillMd)) copyFile(skillMd, path.join(SKILL_DIR, 'SKILL.md'), options.force);
|
|
104
124
|
if (fs.existsSync(refMd)) copyFile(refMd, path.join(SKILL_DIR, 'reference.md'), options.force);
|
|
105
|
-
if (fs.existsSync(scriptJs))
|
|
125
|
+
if (fs.existsSync(scriptJs)) copyScriptWithPlaceholders(scriptJs, path.join(SKILL_DIR, 'scripts', 'fedin-cms-cli.js'), { websiteId, userId }, options.force);
|
|
106
126
|
}
|
|
107
127
|
|
|
108
|
-
const defaultContentTypeUrl = 'https://database.fedin.cn/functions/v1/cms_content-type-manager';
|
|
109
|
-
const defaultContentUrl = 'https://database.fedin.cn/functions/v1/cms_content-manager';
|
|
110
|
-
const envLines = [
|
|
111
|
-
`WEBSITE_ID=${website}`,
|
|
112
|
-
options.apiUrl ? `SUPABASE_CMS_API_URL=${options.apiUrl}` : `SUPABASE_CMS_API_URL=${defaultContentTypeUrl}`,
|
|
113
|
-
`SUPABASE_CONTENT_API_URL=${defaultContentUrl}`,
|
|
114
|
-
options.anonKey ? `SUPABASE_ANON_KEY=${options.anonKey}` : 'SUPABASE_ANON_KEY=',
|
|
115
|
-
].filter(Boolean);
|
|
116
|
-
appendEnv(envLines);
|
|
117
|
-
|
|
118
128
|
console.log('Skill 已安装到 .cursor/skills/fedin-cms/');
|
|
119
|
-
|
|
120
|
-
console.log('如未配置 API 地址或密钥,请在项目根 .env 中设置 SUPABASE_CMS_API_URL、SUPABASE_CONTENT_API_URL、SUPABASE_ANON_KEY。');
|
|
121
|
-
}
|
|
129
|
+
console.log('站点 ID 与用户 ID 已从密钥解密并写入脚本。');
|
|
122
130
|
console.log('脚本为单文件打包,无需在 scripts/ 下安装依赖。');
|
|
123
131
|
}
|
|
124
132
|
|
|
@@ -127,28 +135,27 @@ function printHelp() {
|
|
|
127
135
|
fedincms init - 将 Fedin CMS Skill 安装到当前项目
|
|
128
136
|
|
|
129
137
|
用法:
|
|
130
|
-
fedincms init
|
|
131
|
-
fedincms init --website
|
|
138
|
+
fedincms init cms_website_key=<站点密钥>
|
|
139
|
+
fedincms init --cms-website-key=<站点密钥>
|
|
132
140
|
|
|
133
141
|
参数:
|
|
134
|
-
|
|
135
|
-
apiUrl 可选。Fedin CMS API 根地址,对应 SUPABASE_CMS_API_URL。
|
|
136
|
-
anonKey 可选。API 密钥,对应 SUPABASE_ANON_KEY。
|
|
142
|
+
cms_website_key 必填。站点密钥(格式 cms_<base64>),解密后得到 websiteId 与 userId,并写入脚本占位符。
|
|
137
143
|
|
|
138
144
|
选项:
|
|
139
|
-
--force, -f 已存在 .cursor/skills/fedin-cms/
|
|
145
|
+
--force, -f 已存在 .cursor/skills/fedin-cms/ 时覆盖复制并重新替换占位符。
|
|
140
146
|
--help, -h 显示此帮助。
|
|
141
147
|
|
|
142
148
|
行为:
|
|
143
|
-
-
|
|
144
|
-
-
|
|
149
|
+
- 解密 cms_website_key 得到 websiteId、userId
|
|
150
|
+
- 创建 .cursor/skills/fedin-cms/ 并复制 SKILL.md、reference.md
|
|
151
|
+
- 复制 scripts/fedin-cms-cli.js 并将占位符 __FEDINCMS_WEBSITE_ID__、__FEDINCMS_USER_ID__ 替换为解密后的值
|
|
145
152
|
`);
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
function main() {
|
|
149
156
|
const argv = process.argv.slice(2);
|
|
150
157
|
if (argv.length === 0) {
|
|
151
|
-
console.log('用法: fedincms init
|
|
158
|
+
console.log('用法: fedincms init cms_website_key=xxxxx');
|
|
152
159
|
console.log('查看帮助: fedincms init --help');
|
|
153
160
|
process.exit(0);
|
|
154
161
|
}
|
package/package.json
CHANGED
package/templates/skill/SKILL.md
CHANGED
|
@@ -7,8 +7,8 @@ description: 通过 Fedin CMS 脚本管理内容类型与条目:列出/获取/
|
|
|
7
7
|
|
|
8
8
|
## 前提
|
|
9
9
|
|
|
10
|
-
- 项目已通过 `fedincms init
|
|
11
|
-
-
|
|
10
|
+
- 项目已通过 `fedincms init cms_website_key=xxxxx` 初始化,站点 ID 与用户 ID 已从密钥解密并写入脚本,无需再从环境变量读取。
|
|
11
|
+
- 若需调用 API,请在项目根 `.env` 中配置 `SUPABASE_CMS_API_URL`、`SUPABASE_CONTENT_API_URL`、`SUPABASE_ANON_KEY`。
|
|
12
12
|
- 脚本为单文件打包(依赖已内联),**无需**在 `scripts/` 下执行 `npm install`。
|
|
13
13
|
|
|
14
14
|
## 执行约定
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
## 环境
|
|
7
7
|
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
- `SUPABASE_CMS_API_URL`(内容类型 API
|
|
11
|
-
- `SUPABASE_CONTENT_API_URL`(条目 API
|
|
12
|
-
- `SUPABASE_ANON_KEY
|
|
8
|
+
- **站点 ID 与用户 ID**:由 `fedincms init cms_website_key=xxx` 解密密钥后写入脚本,**不从环境变量读取**。
|
|
9
|
+
- 脚本从项目根加载 `.env`,仅用于:
|
|
10
|
+
- `SUPABASE_CMS_API_URL`(内容类型 API)
|
|
11
|
+
- `SUPABASE_CONTENT_API_URL`(条目 API)
|
|
12
|
+
- `SUPABASE_ANON_KEY`(API 密钥)
|
|
13
13
|
- 成功时结果 JSON 输出到 stdout;失败时错误信息输出到 stderr 并以非 0 退出码退出。
|
|
14
14
|
|
|
15
15
|
---
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
#!/usr/bin/env node
|
|
3
2
|
"use strict";
|
|
4
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
4
|
var __commonJS = (cb, mod) => function __require() {
|
|
@@ -15397,11 +15396,11 @@ var fs = require("fs");
|
|
|
15397
15396
|
var dotenv = require_main();
|
|
15398
15397
|
var axios = require_axios();
|
|
15399
15398
|
dotenv.config({ path: path.join(process.cwd(), ".env") });
|
|
15400
|
-
var WEBSITE_ID =
|
|
15399
|
+
var WEBSITE_ID = "__FEDINCMS_WEBSITE_ID__";
|
|
15400
|
+
var USER_ID = "__FEDINCMS_USER_ID__";
|
|
15401
15401
|
var CONTENT_TYPE_BASE_URL = process.env.SUPABASE_CMS_API_URL || "https://database.fedin.cn/functions/v1/cms_content-type-manager";
|
|
15402
15402
|
var CONTENT_BASE_URL = process.env.SUPABASE_CONTENT_API_URL || "https://database.fedin.cn/functions/v1/cms_content-manager";
|
|
15403
15403
|
var ANON_KEY = process.env.SUPABASE_ANON_KEY || "";
|
|
15404
|
-
var USER_ID = process.env.USER_ID || "";
|
|
15405
15404
|
function err(msg) {
|
|
15406
15405
|
process.stderr.write(msg + "\n");
|
|
15407
15406
|
process.exit(1);
|