openyida 0.1.2 → 1.0.0-beta.0
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 +68 -38
- package/bin/yida.js +164 -761
- package/lib/babel-transform/index.js +244 -0
- package/lib/babel-transform/jsx-utils.js +89 -0
- package/lib/check-update.js +72 -0
- package/lib/copy.js +258 -0
- package/lib/create-app.js +174 -0
- package/lib/create-form.js +2244 -0
- package/lib/create-page.js +89 -0
- package/lib/env.js +164 -0
- package/lib/get-page-config.js +102 -0
- package/lib/get-schema.js +76 -0
- package/lib/login.js +323 -0
- package/lib/publish.js +610 -0
- package/lib/save-share-config.js +268 -0
- package/lib/update-form-config.js +237 -0
- package/lib/utils.js +443 -0
- package/lib/verify-short-url.js +279 -0
- package/package.json +20 -7
- package/project/.cache/demo-schema.json +2353 -0
- package/project/pages/src/demo-birthday-game.js +833 -0
- package/project/pages/src/demo-future-vision-2026.js +1102 -0
- package/project/pages/src/demo-salary-calculator.js +904 -0
- package/project/prd/demo-birthday-game.md +39 -0
- package/project/prd/demo-future-vision-2026.md +78 -0
- package/project/prd/demo-salary-calculator.md +101 -0
- package/scripts/postinstall.js +114 -0
- package/yida-skills/SKILL.md +273 -0
- package/yida-skills/reference/association-form-field.md +469 -0
- package/yida-skills/reference/employee-field.md +17 -0
- package/yida-skills/reference/model-api.md +73 -0
- package/yida-skills/reference/serial-number-field.md +132 -0
- package/yida-skills/reference/yida-api.md +1208 -0
- package/yida-skills/skills/yida-app/SKILL.md +394 -0
- package/yida-skills/skills/yida-create-app/SKILL.md +158 -0
- package/yida-skills/skills/yida-create-form-page/SKILL.md +598 -0
- package/yida-skills/skills/yida-create-page/SKILL.md +103 -0
- package/yida-skills/skills/yida-custom-page/SKILL.md +533 -0
- package/yida-skills/skills/yida-get-schema/SKILL.md +90 -0
- package/yida-skills/skills/yida-login/SKILL.md +200 -0
- package/yida-skills/skills/yida-logout/SKILL.md +58 -0
- package/yida-skills/skills/yida-page-config/SKILL.md +261 -0
- package/yida-skills/skills/yida-publish-page/SKILL.md +113 -0
- package/.eslintrc.json +0 -25
- package/.github/workflows/ci.yml +0 -123
- package/.github/workflows/publish.yml +0 -105
- package/.github/workflows/update-contributors.yml +0 -151
- package/.openclaw/skills/yida-issue/SKILL.md +0 -27
- package/.openclaw/skills/yida-issue/scripts/create-issue.js +0 -317
- package/CLAUDE.md +0 -168
- package/CONTRIBUTING.md +0 -59
- package/install-skills.ps1 +0 -162
- package/install-skills.sh +0 -175
- package/pages/dist/.gitkeep +0 -0
- package/pages/src/.gitkeep +0 -0
- package/prd/salary-calculator.md +0 -15
- package/tests/cli.test.js +0 -930
- package/tests/install.test.js +0 -277
- package/tests/yida-issue.test.js +0 -314
- /package/{config.json → project/config.json} +0 -0
- /package/{.cache → project/pages/dist}/.gitkeep +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* create-app.js - 宜搭应用创建命令
|
|
3
|
+
*
|
|
4
|
+
* 用法:yidacli create-app "<appName>" [description] [icon] [iconColor]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const querystring = require("querystring");
|
|
12
|
+
const {
|
|
13
|
+
findProjectRoot,
|
|
14
|
+
loadCookieData,
|
|
15
|
+
triggerLogin,
|
|
16
|
+
refreshCsrfToken,
|
|
17
|
+
resolveBaseUrl,
|
|
18
|
+
httpPost,
|
|
19
|
+
requestWithAutoLogin,
|
|
20
|
+
} = require("./utils");
|
|
21
|
+
|
|
22
|
+
// ── prd 文档更新 ──────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
function findPrdFile() {
|
|
25
|
+
let currentDir = process.cwd();
|
|
26
|
+
for (let i = 0; i < 5; i++) {
|
|
27
|
+
const prdDir = path.join(currentDir, "prd");
|
|
28
|
+
if (fs.existsSync(prdDir)) {
|
|
29
|
+
const files = fs.readdirSync(prdDir);
|
|
30
|
+
const mdFile = files.find((f) => f.endsWith(".md"));
|
|
31
|
+
if (mdFile) return path.join(prdDir, mdFile);
|
|
32
|
+
}
|
|
33
|
+
const parentDir = path.dirname(currentDir);
|
|
34
|
+
if (parentDir === currentDir) break;
|
|
35
|
+
currentDir = parentDir;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function updatePrdCorpId(prdFilePath, corpId, appType, baseUrl) {
|
|
41
|
+
if (!prdFilePath || !fs.existsSync(prdFilePath)) {
|
|
42
|
+
console.error(`\n ⚠️ 未找到 prd 文档,跳过 corpId 写入`);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
let content = fs.readFileSync(prdFilePath, "utf-8");
|
|
48
|
+
const hasAppConfig = content.includes("## 应用配置") || content.includes("| appType |");
|
|
49
|
+
|
|
50
|
+
if (hasAppConfig) {
|
|
51
|
+
const corpIdRegex = /\| corpId \| [^\|]*\|/;
|
|
52
|
+
if (corpIdRegex.test(content)) {
|
|
53
|
+
content = content.replace(corpIdRegex, `| corpId | ${corpId} |`);
|
|
54
|
+
} else {
|
|
55
|
+
content = content.replace(
|
|
56
|
+
/(\| appType \| [^\|]*\|)(\r?\n)/,
|
|
57
|
+
`$1$2| corpId | ${corpId} |$2`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
content = content.replace(/\| appType \| [^\|]*\|/, `| appType | ${appType} |`);
|
|
61
|
+
content = content.replace(/\| baseUrl \| [^\|]*\|/, `| baseUrl | ${baseUrl} |`);
|
|
62
|
+
} else {
|
|
63
|
+
const appConfigSection = `## 应用配置\n\n| 配置项 | 值 |\n| --- | --- |\n| appType | ${appType} |\n| corpId | ${corpId} |\n| baseUrl | ${baseUrl} |\n\n`;
|
|
64
|
+
if (content.startsWith("#")) {
|
|
65
|
+
content = content.replace(/^(# .*\r?\n)/, `$1\n${appConfigSection}`);
|
|
66
|
+
} else {
|
|
67
|
+
content = appConfigSection + content;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fs.writeFileSync(prdFilePath, content, "utf-8");
|
|
72
|
+
console.error(` ✅ 已更新 prd 文档: ${path.basename(prdFilePath)}`);
|
|
73
|
+
return true;
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error(` ⚠️ 更新 prd 文档失败: ${err.message}`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── 主逻辑 ────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
async function run(args) {
|
|
83
|
+
if (args.length < 1) {
|
|
84
|
+
console.error('用法: yidacli create-app "<appName>" [description] [icon] [iconColor]');
|
|
85
|
+
console.error('示例: yidacli create-app "考勤管理" "员工考勤打卡系统" "xian-daka" "#00B853"');
|
|
86
|
+
console.error("\n可用图标:");
|
|
87
|
+
console.error(" xian-xinwen, xian-zhengfu, xian-yingyong, xian-xueshimao, xian-qiye,");
|
|
88
|
+
console.error(" xian-danju, xian-shichang, xian-jingli, xian-falv, xian-baogao,");
|
|
89
|
+
console.error(" huoche, xian-shenbao, xian-diqiu, xian-qiche, xian-feiji,");
|
|
90
|
+
console.error(" xian-diannao, xian-gongzuozheng, xian-gouwuche, xian-xinyongka,");
|
|
91
|
+
console.error(" xian-huodong, xian-jiangbei, xian-liucheng, xian-chaxun, xian-daka");
|
|
92
|
+
console.error("\n可用颜色:");
|
|
93
|
+
console.error(" #0089FF #00B853 #FFA200 #FF7357 #5C72FF");
|
|
94
|
+
console.error(" #85C700 #FFC505 #FF6B7A #8F66FF #14A9FF");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const appName = args[0];
|
|
99
|
+
const description = args[1] || appName;
|
|
100
|
+
const icon = args[2] || "xian-yingyong";
|
|
101
|
+
const iconColor = args[3] || "#0089FF";
|
|
102
|
+
|
|
103
|
+
console.error("=".repeat(50));
|
|
104
|
+
console.error(" yidacli create-app - 宜搭应用创建工具");
|
|
105
|
+
console.error("=".repeat(50));
|
|
106
|
+
console.error(`\n 应用名称: ${appName}`);
|
|
107
|
+
console.error(` 应用描述: ${description}`);
|
|
108
|
+
console.error(` 图标: ${icon} (${iconColor})`);
|
|
109
|
+
|
|
110
|
+
// Step 1: 读取登录态
|
|
111
|
+
console.error("\n🔑 Step 1: 读取登录态");
|
|
112
|
+
let cookieData = loadCookieData();
|
|
113
|
+
if (!cookieData) {
|
|
114
|
+
console.error(" ⚠️ 未找到本地登录态,触发登录...");
|
|
115
|
+
cookieData = triggerLogin();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const authRef = {
|
|
119
|
+
csrfToken: cookieData.csrf_token,
|
|
120
|
+
cookies: cookieData.cookies,
|
|
121
|
+
baseUrl: resolveBaseUrl(cookieData),
|
|
122
|
+
cookieData,
|
|
123
|
+
};
|
|
124
|
+
console.error(` ✅ 登录态已就绪(${authRef.baseUrl})`);
|
|
125
|
+
|
|
126
|
+
// Step 2: 创建应用
|
|
127
|
+
console.error("\n📦 Step 2: 创建应用\n");
|
|
128
|
+
|
|
129
|
+
const iconValue = `${icon}%%${iconColor}`;
|
|
130
|
+
const response = await requestWithAutoLogin((auth) => {
|
|
131
|
+
const postData = querystring.stringify({
|
|
132
|
+
_csrf_token: auth.csrfToken,
|
|
133
|
+
appName: JSON.stringify({ zh_CN: appName, en_US: appName, type: "i18n" }),
|
|
134
|
+
description: JSON.stringify({ zh_CN: description, en_US: description, type: "i18n" }),
|
|
135
|
+
icon: iconValue,
|
|
136
|
+
iconUrl: iconValue,
|
|
137
|
+
colour: "blue",
|
|
138
|
+
defaultLanguage: "zh_CN",
|
|
139
|
+
openExclusive: "n",
|
|
140
|
+
openPhysicColumn: "n",
|
|
141
|
+
openIsolationDatabase: "n",
|
|
142
|
+
openExclusiveUnit: "n",
|
|
143
|
+
group: "全部应用",
|
|
144
|
+
});
|
|
145
|
+
return httpPost(auth.baseUrl, "/query/app/registerApp.json", postData, auth.cookies);
|
|
146
|
+
}, authRef);
|
|
147
|
+
|
|
148
|
+
// 输出结果
|
|
149
|
+
console.error("\n" + "=".repeat(50));
|
|
150
|
+
if (response && response.success && response.content) {
|
|
151
|
+
const appType = response.content;
|
|
152
|
+
const appUrl = `${authRef.baseUrl}/${appType}/admin`;
|
|
153
|
+
const corpId = authRef.cookieData.corp_id || "";
|
|
154
|
+
|
|
155
|
+
console.error(" ✅ 应用创建成功!");
|
|
156
|
+
console.error(` appType: ${appType}`);
|
|
157
|
+
console.error(` corpId: ${corpId || "未获取"}`);
|
|
158
|
+
console.error(` 访问地址: ${appUrl}`);
|
|
159
|
+
console.error("=".repeat(50));
|
|
160
|
+
|
|
161
|
+
const prdFile = findPrdFile();
|
|
162
|
+
if (prdFile) updatePrdCorpId(prdFile, corpId, appType, authRef.baseUrl);
|
|
163
|
+
|
|
164
|
+
console.log(JSON.stringify({ success: true, appType, appName, corpId, url: appUrl }));
|
|
165
|
+
} else {
|
|
166
|
+
const errorMsg = response ? response.errorMsg || "未知错误" : "请求失败";
|
|
167
|
+
console.error(` ❌ 创建失败: ${errorMsg}`);
|
|
168
|
+
console.error("=".repeat(50));
|
|
169
|
+
console.log(JSON.stringify({ success: false, error: errorMsg }));
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
module.exports = { run };
|