openxiangda 1.0.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.
Files changed (121) hide show
  1. package/README.md +58 -0
  2. package/bin/openxiangda.js +11 -0
  3. package/lib/cli.js +2423 -0
  4. package/lib/config.js +121 -0
  5. package/lib/http.js +47 -0
  6. package/lib/skills.js +371 -0
  7. package/lib/utils.js +87 -0
  8. package/lib/workspace-init.js +139 -0
  9. package/openxiangda-skills/SKILL.md +128 -0
  10. package/openxiangda-skills/references/architecture-patterns.md +242 -0
  11. package/openxiangda-skills/references/automation-v3.md +129 -0
  12. package/openxiangda-skills/references/component-guide.md +198 -0
  13. package/openxiangda-skills/references/forms/component-registry.md +53 -0
  14. package/openxiangda-skills/references/forms/form-schema.md +109 -0
  15. package/openxiangda-skills/references/forms/layout-and-rules.md +24 -0
  16. package/openxiangda-skills/references/openxiangda-api.md +466 -0
  17. package/openxiangda-skills/references/pages/page-sdk.md +13 -0
  18. package/openxiangda-skills/references/pages/publish-flow.md +36 -0
  19. package/openxiangda-skills/references/pages/workspace-structure.md +38 -0
  20. package/openxiangda-skills/references/permissions-settings.md +147 -0
  21. package/openxiangda-skills/references/platform-data-model.md +305 -0
  22. package/openxiangda-skills/references/style-system.md +492 -0
  23. package/openxiangda-skills/references/troubleshooting.md +246 -0
  24. package/openxiangda-skills/references/workflow-v3.md +105 -0
  25. package/openxiangda-skills/references/workspace-state.md +45 -0
  26. package/openxiangda-skills/skills/openxiangda-app/SKILL.md +64 -0
  27. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +143 -0
  28. package/openxiangda-skills/skills/openxiangda-form/SKILL.md +76 -0
  29. package/openxiangda-skills/skills/openxiangda-inspect/SKILL.md +40 -0
  30. package/openxiangda-skills/skills/openxiangda-page/SKILL.md +62 -0
  31. package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +95 -0
  32. package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +97 -0
  33. package/package.json +126 -0
  34. package/packages/sdk/bin/lowcode-workspace.mjs +4 -0
  35. package/packages/sdk/dist/build/index.cjs +33 -0
  36. package/packages/sdk/dist/build/index.cjs.map +1 -0
  37. package/packages/sdk/dist/build/index.d.mts +40 -0
  38. package/packages/sdk/dist/build/index.d.ts +40 -0
  39. package/packages/sdk/dist/build/index.mjs +8 -0
  40. package/packages/sdk/dist/build/index.mjs.map +1 -0
  41. package/packages/sdk/dist/components/index.cjs +18700 -0
  42. package/packages/sdk/dist/components/index.cjs.map +1 -0
  43. package/packages/sdk/dist/components/index.d.mts +2094 -0
  44. package/packages/sdk/dist/components/index.d.ts +2094 -0
  45. package/packages/sdk/dist/components/index.mjs +18649 -0
  46. package/packages/sdk/dist/components/index.mjs.map +1 -0
  47. package/packages/sdk/dist/runtime/index.cjs +1469 -0
  48. package/packages/sdk/dist/runtime/index.cjs.map +1 -0
  49. package/packages/sdk/dist/runtime/index.d.mts +831 -0
  50. package/packages/sdk/dist/runtime/index.d.ts +831 -0
  51. package/packages/sdk/dist/runtime/index.mjs +1420 -0
  52. package/packages/sdk/dist/runtime/index.mjs.map +1 -0
  53. package/packages/sdk/dist/styles/antd-theme.cjs +60 -0
  54. package/packages/sdk/dist/styles/antd-theme.cjs.map +1 -0
  55. package/packages/sdk/dist/styles/antd-theme.d.mts +5 -0
  56. package/packages/sdk/dist/styles/antd-theme.d.ts +5 -0
  57. package/packages/sdk/dist/styles/antd-theme.mjs +35 -0
  58. package/packages/sdk/dist/styles/antd-theme.mjs.map +1 -0
  59. package/packages/sdk/dist/styles/tailwind-preset.cjs +2641 -0
  60. package/packages/sdk/dist/styles/tailwind-preset.cjs.map +1 -0
  61. package/packages/sdk/dist/styles/tailwind-preset.d.mts +75 -0
  62. package/packages/sdk/dist/styles/tailwind-preset.d.ts +75 -0
  63. package/packages/sdk/dist/styles/tailwind-preset.mjs +2618 -0
  64. package/packages/sdk/dist/styles/tailwind-preset.mjs.map +1 -0
  65. package/packages/sdk/dist/styles/tokens.css +73 -0
  66. package/packages/sdk/src/build-source/README.md +9 -0
  67. package/packages/sdk/src/build-source/bin/lowcode-workspace.mjs +7 -0
  68. package/packages/sdk/src/build-source/package.json +34 -0
  69. package/packages/sdk/src/build-source/scripts/build-forms.mjs +824 -0
  70. package/packages/sdk/src/build-source/scripts/build-forms.runtime-entry.test.ts +18 -0
  71. package/packages/sdk/src/build-source/scripts/build-pages.mjs +793 -0
  72. package/packages/sdk/src/build-source/scripts/build-workspace.mjs +64 -0
  73. package/packages/sdk/src/build-source/scripts/publish-all.mjs +127 -0
  74. package/packages/sdk/src/build-source/scripts/publish-oss.mjs +149 -0
  75. package/packages/sdk/src/build-source/scripts/register-bundle.mjs +1 -0
  76. package/packages/sdk/src/build-source/scripts/register.mjs +329 -0
  77. package/packages/sdk/src/build-source/scripts/sync-schema.mjs +301 -0
  78. package/packages/sdk/src/build-source/scripts/utils/form-api.mjs +639 -0
  79. package/packages/sdk/src/build-source/scripts/utils/form-api.test.ts +244 -0
  80. package/packages/sdk/src/build-source/scripts/utils/form-runtime-assets.mjs +57 -0
  81. package/packages/sdk/src/build-source/scripts/utils/form-runtime-assets.test.ts +135 -0
  82. package/packages/sdk/src/build-source/scripts/utils/incremental.mjs +210 -0
  83. package/packages/sdk/src/build-source/scripts/utils/load-config.mjs +257 -0
  84. package/packages/sdk/src/build-source/scripts/utils/load-config.test.ts +44 -0
  85. package/packages/sdk/src/build-source/scripts/utils/mime-types.mjs +70 -0
  86. package/packages/sdk/src/build-source/scripts/utils/namespace-css.mjs +61 -0
  87. package/packages/sdk/src/build-source/scripts/utils/oss-client.mjs +128 -0
  88. package/packages/sdk/src/build-source/scripts/utils/pages.mjs +80 -0
  89. package/packages/sdk/src/build-source/scripts/utils/progress.mjs +57 -0
  90. package/packages/sdk/src/build-source/scripts/utils/register-payload.mjs +89 -0
  91. package/packages/sdk/src/build-source/scripts/utils/register-payload.test.ts +76 -0
  92. package/packages/sdk/src/build-source/scripts/utils/runtime-css-check.mjs +44 -0
  93. package/packages/sdk/src/build-source/scripts/utils/runtime-css-check.test.ts +54 -0
  94. package/packages/sdk/src/build-source/scripts/utils/schema-transform.mjs +130 -0
  95. package/packages/sdk/src/build-source/scripts/utils/schema-transform.test.ts +141 -0
  96. package/packages/sdk/src/build-source/scripts/utils/tailwind-config.mjs +227 -0
  97. package/packages/sdk/src/build-source/scripts/utils/tailwind-config.test.ts +187 -0
  98. package/packages/sdk/src/build-source/src/cli.mjs +679 -0
  99. package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +34 -0
  100. package/templates/sy-lowcode-app-workspace/examples/forms/customer/page.tsx +1 -0
  101. package/templates/sy-lowcode-app-workspace/examples/forms/customer/schema.ts +35 -0
  102. package/templates/sy-lowcode-app-workspace/index.html +12 -0
  103. package/templates/sy-lowcode-app-workspace/package.json +49 -0
  104. package/templates/sy-lowcode-app-workspace/postcss.config.cjs +6 -0
  105. package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +100 -0
  106. package/templates/sy-lowcode-app-workspace/src/dev/App.tsx +26 -0
  107. package/templates/sy-lowcode-app-workspace/src/forms/.gitkeep +1 -0
  108. package/templates/sy-lowcode-app-workspace/src/forms/README.md +48 -0
  109. package/templates/sy-lowcode-app-workspace/src/index.css +28 -0
  110. package/templates/sy-lowcode-app-workspace/src/js-code-nodes/.gitkeep +1 -0
  111. package/templates/sy-lowcode-app-workspace/src/js-code-nodes/types.d.ts +3 -0
  112. package/templates/sy-lowcode-app-workspace/src/main.tsx +36 -0
  113. package/templates/sy-lowcode-app-workspace/src/pages/.gitkeep +1 -0
  114. package/templates/sy-lowcode-app-workspace/src/shared/form-schema.ts +128 -0
  115. package/templates/sy-lowcode-app-workspace/src/types/app-workspace.types.ts +31 -0
  116. package/templates/sy-lowcode-app-workspace/tailwind.config.cjs +30 -0
  117. package/templates/sy-lowcode-app-workspace/tsconfig.app.json +24 -0
  118. package/templates/sy-lowcode-app-workspace/tsconfig.js-code-nodes.json +15 -0
  119. package/templates/sy-lowcode-app-workspace/tsconfig.json +7 -0
  120. package/templates/sy-lowcode-app-workspace/tsconfig.node.json +10 -0
  121. package/templates/sy-lowcode-app-workspace/vite.config.ts +32 -0
@@ -0,0 +1,246 @@
1
+ # OpenXiangda 常见问题排查指南
2
+
3
+ > 本文档面向 AI Agent,收录在实际低代码项目(如 zjnu-dxyq-lowcode)开发中遇到的典型问题及解决方案。遇到报错或异常现象时,请优先在此查找匹配项;若无匹配,再结合源码与日志分析。
4
+
5
+ ## 快速索引
6
+
7
+ | # | 问题 | 关键报错 / 现象 |
8
+ | --- | --- | --- |
9
+ | 1 | antd/antd-mobile 弹层样式丢失 | Select/Modal 弹层无样式或跑到屏幕外 |
10
+ | 2 | SelectField options 为 undefined 导致 .map 报错 | `Cannot read properties of undefined (reading 'map')` |
11
+ | 3 | ESM 模块动态导入路径错误 | `ERR_UNSUPPORTED_ESM_URL_SCHEME` / `Cannot find module` |
12
+ | 4 | Windows 环境 OSS 上传路径错误 | 发布后资源 404,URL 含 `\` |
13
+ | 5 | 构建时表单 API 常量替换失败 | formApi.ts 中环境变量未替换 |
14
+ | 6 | Tailwind 样式被清除(PurgeCSS) | 生产构建后样式丢失 |
15
+ | 7 | React 多实例冲突 | `Invalid hook call` |
16
+ | 8 | 移动端 antd-mobile 组件样式不生效 | 组件渲染但无样式 |
17
+ | 9 | 数据格式理解错误导致展示异常 | 页面显示 `[object Object]` |
18
+ | 10 | workspace publish 环境变量缺失 | `OPENXIANGDA_ACCESS_TOKEN is not set` |
19
+
20
+ ---
21
+
22
+ ## 问题:antd/antd-mobile 弹层样式丢失
23
+
24
+ **症状**:Select / Dropdown / Popup / Modal 等组件的弹出层没有样式,直接跑到屏幕外,或呈现为无样式的裸 HTML。
25
+
26
+ **根因**:当页面启用了 Shadow DOM 样式隔离(`cssIsolation: "shadow"`)时,antd 组件的弹出层默认会渲染到 `document.body`,从而脱离 Shadow DOM 的样式作用域;即使未使用 Shadow DOM,如果没有正确配置弹层容器,antd-mobile 的 Popup 也可能因 namespace 未被继承而失去样式。
27
+
28
+ **解决方案**:
29
+ 1. 推荐使用 CSS Namespace 隔离(`cssIsolation: "namespace"`)替代 Shadow DOM。
30
+ 2. 为 antd `ConfigProvider` 配置 `getPopupContainer` 指向页面根容器。
31
+ 3. 对于 antd-mobile,确保 `Popup` / `Modal` 的 `getContainer` 指向正确容器。
32
+ 4. 确保弹层的 `className` 中包含 namespace class(如 `sy-app-workspace`)。
33
+
34
+ **示例**:
35
+ ```tsx
36
+ import { useRef } from 'react';
37
+ import { ConfigProvider } from 'antd';
38
+
39
+ const rootRef = useRef<HTMLDivElement>(null);
40
+
41
+ <div ref={rootRef} className="sy-app-workspace">
42
+ <ConfigProvider getPopupContainer={() => rootRef.current!}>
43
+ <App />
44
+ </ConfigProvider>
45
+ </div>
46
+ ```
47
+
48
+ **预防措施**:在 workspace 初始化阶段就统一约定弹层容器策略,避免后续逐个组件修复。
49
+
50
+ ---
51
+
52
+ ## 问题:SelectField options 为 undefined 导致 .map 报错
53
+
54
+ **症状**:渲染 `SelectField` / `RadioField` / `CheckboxField` 时抛出 `Cannot read properties of undefined (reading 'map')`。
55
+
56
+ **根因**:这些需要枚举值的字段组件在 schema 中未提供 `options` 属性,组件内部直接调用 `options.map(...)`。
57
+
58
+ **解决方案**:
59
+ - 确保所有选择类字段在 schema 中至少包含 `options: []`。
60
+ - 使用 `createFormSchema` 工厂函数,它会自动为缺失的 options 字段补齐空数组。
61
+
62
+ **预防措施**:
63
+ ```typescript
64
+ // form-schema.ts 中的保护逻辑
65
+ const NEEDS_OPTIONS = ['SelectField', 'RadioField', 'CheckboxField'];
66
+
67
+ for (const field of schema.fields) {
68
+ if (NEEDS_OPTIONS.includes(field.componentName) && !Array.isArray(field.options)) {
69
+ field.options = [];
70
+ }
71
+ }
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 问题:ESM 模块动态导入路径错误
77
+
78
+ **症状**:执行 `sync-schema` 等脚本时报 `ERR_UNSUPPORTED_ESM_URL_SCHEME` 或 `Cannot find module`。
79
+
80
+ **根因**:Node.js 的 `import()` 在部分环境下(尤其是 Windows)不接受纯文件路径,必须使用 `file://` URL 形式。
81
+
82
+ **解决方案**:
83
+ ```javascript
84
+ import { pathToFileURL } from 'url';
85
+
86
+ // 错误写法(可能在 Windows 下报错)
87
+ const module = await import(tmpFile);
88
+
89
+ // 正确写法
90
+ const module = await import(pathToFileURL(tmpFile).href);
91
+ ```
92
+
93
+ **预防措施**:所有动态 `import()` 文件路径统一通过 `pathToFileURL().href` 转换,CI 中加入 Windows 平台冒烟测试。
94
+
95
+ ---
96
+
97
+ ## 问题:Windows 环境 OSS 上传路径错误
98
+
99
+ **症状**:发布完成后访问页面,CSS / JS 资源返回 404,浏览器 Network 面板中可见 URL 内出现反斜杠 `\`。
100
+
101
+ **根因**:Windows 文件系统使用 `\` 作为路径分隔符,而 OSS 对象 key 必须使用 `/`,未做归一化时直接拼接路径会导致非法 key。
102
+
103
+ **解决方案**:
104
+ ```javascript
105
+ function toOssKeyPath(file) {
106
+ return String(file).replace(/\\/g, '/');
107
+ }
108
+
109
+ const ossKey = toOssKeyPath(path.relative(distDir, absFile));
110
+ await ossClient.put(ossKey, absFile);
111
+ ```
112
+
113
+ **预防措施**:在上传函数入口处统一调用 `toOssKeyPath`,禁止直接拼接原始路径。
114
+
115
+ ---
116
+
117
+ ## 问题:构建时表单 API 常量替换失败
118
+
119
+ **症状**:生成的 `formApi.ts` 中,环境变量(如 `APP_ID`、`BASE_URL`)等常量值没有被正确替换为目标 profile 的真实值。
120
+
121
+ **根因**:旧的替换正则只覆盖了简单字符串字面量,无法匹配对象字面量、函数调用、模板字符串等复杂初始化表达式。
122
+
123
+ **解决方案**:使用更宽松的正则匹配 `=` 到 `;` 之间的任意表达式:
124
+ ```javascript
125
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
126
+ const regex = new RegExp(
127
+ `((?:export\\s+)?const\\s+${escaped}\\s*=\\s*)([^;]+);`
128
+ );
129
+ source = source.replace(regex, (_, prefix) => `${prefix}${JSON.stringify(value)};`);
130
+ ```
131
+
132
+ **预防措施**:替换后立即写一个 sanity check,比较替换前后的 AST 是否仅常量值发生变化。
133
+
134
+ ---
135
+
136
+ ## 问题:Tailwind 样式被清除(PurgeCSS 问题)
137
+
138
+ **症状**:开发环境(`vite dev`)下页面样式正常,但 `vite build` 生产产物中部分组件样式丢失。
139
+
140
+ **根因**:Tailwind v3+ 的 `content` 配置未包含来自 SDK / 组件库的源文件,组件库内使用的类名在编译期被 PurgeCSS 误删。
141
+
142
+ **解决方案**:
143
+ ```javascript
144
+ // tailwind.config.cjs
145
+ module.exports = {
146
+ content: [
147
+ './src/**/*.{ts,tsx}',
148
+ './node_modules/openxiangda/packages/sdk/dist/**/*.{mjs,cjs}', // 关键:包含 SDK 分发文件
149
+ ],
150
+ presets: [require('openxiangda/tailwind-preset')],
151
+ };
152
+ ```
153
+
154
+ **预防措施**:每次新增第三方组件库时,同步将其分发产物路径加入 `content` 数组;将 `pnpm build` 纳入 CI,对比构建产物体积异常增减。
155
+
156
+ ---
157
+
158
+ ## 问题:React 多实例冲突
159
+
160
+ **症状**:运行时抛出 `Invalid hook call. Hooks can only be called inside of the body of a function component.`,组件中所有 hooks 失效。
161
+
162
+ **根因**:项目最终打包产物中存在多个 React 实例,通常是因为组件库与宿主项目各自引入了不同版本的 `react` / `react-dom`。
163
+
164
+ **解决方案**:
165
+ ```typescript
166
+ // vite.config.ts
167
+ import { defineConfig } from 'vite';
168
+
169
+ export default defineConfig({
170
+ resolve: {
171
+ dedupe: ['react', 'react-dom', 'antd'],
172
+ },
173
+ });
174
+ ```
175
+
176
+ **预防措施**:
177
+ - 在 `package.json` 中将 `react` / `react-dom` 设为 SDK 的 `peerDependencies`。
178
+ - 使用 `pnpm why react` 排查重复依赖。
179
+
180
+ ---
181
+
182
+ ## 问题:移动端 antd-mobile 组件样式不生效
183
+
184
+ **症状**:antd-mobile 组件 DOM 已渲染,但样式全部丢失,呈现裸 HTML。
185
+
186
+ **根因**:antd-mobile 使用 CSS-in-JS / 预编译样式,可能被 Tailwind 的 preflight 重置覆盖,或受 namespace 隔离影响。
187
+
188
+ **解决方案**:
189
+ 1. 在 `vite.config.ts` 的 `optimizeDeps.include` 中显式添加 `antd-mobile`,避免运行时多次预构建。
190
+ 2. 调整 Tailwind preflight 策略,确保不会覆盖 antd-mobile 的基础样式(必要时关闭 preflight 或使用 `important` 选择器)。
191
+ 3. 确保 antd-mobile 组件渲染在 `sy-app-workspace` namespace 容器内,弹层 `getContainer` 指向该容器。
192
+
193
+ **示例**:
194
+ ```typescript
195
+ // vite.config.ts
196
+ export default defineConfig({
197
+ optimizeDeps: {
198
+ include: ['antd-mobile', 'antd-mobile/es/locales/zh-CN'],
199
+ },
200
+ });
201
+ ```
202
+
203
+ **预防措施**:移动端项目模板中预置好 antd-mobile 的 vite 与 Tailwind 配置,禁止业务方随意修改 preflight。
204
+
205
+ ---
206
+
207
+ ## 问题:数据格式理解错误导致展示异常
208
+
209
+ **症状**:页面显示 `[object Object]`、空白,或筛选条件无法命中数据。
210
+
211
+ **根因**:AI 将平台返回的 `{label, value}` 结构字段当作纯字符串处理,直接渲染对象到 JSX。
212
+
213
+ **解决方案**:参考 `platform-data-model.md`,选择类字段在平台中存储为对象(单选为对象,多选为对象数组),渲染时需取 `label` 字段:
214
+ ```tsx
215
+ // 错误:直接展示对象
216
+ <span>{record.department}</span> // 显示 [object Object]
217
+
218
+ // 正确:取 label
219
+ <span>{record.department?.label}</span>
220
+
221
+ // 多选字段
222
+ <span>{record.tags?.map(t => t.label).join(', ')}</span>
223
+ ```
224
+
225
+ **预防措施**:
226
+ - 编辑器中为选择类字段统一定义 `OptionValue = { label: string; value: string }` 类型。
227
+ - 列表 / 详情页渲染前,封装 `formatOption(value)` 工具函数。
228
+
229
+ ---
230
+
231
+ ## 问题:workspace publish 环境变量缺失
232
+
233
+ **症状**:执行发布命令时报错 `OPENXIANGDA_ACCESS_TOKEN is not set` 或类似缺少配置项的错误。
234
+
235
+ **根因**:没有通过 `openxiangda` CLI 触发发布,CLI 负责从安全存储读取 profile 配置并注入到子进程的环境变量中;直接运行 `pnpm` 脚本会绕过这一步骤。
236
+
237
+ **解决方案**:
238
+ - 始终通过 CLI 发布:
239
+ ```bash
240
+ openxiangda workspace publish --profile <profile-name>
241
+ ```
242
+ - **不要**直接执行 `pnpm run publish:all` / `node scripts/publish.js`,这些命令缺少 token 注入。
243
+
244
+ **预防措施**:
245
+ - 在 workspace 的 `package.json` 中将真正的发布脚本设为内部脚本(前缀 `_`),README 与 SKILL 文档统一引导走 CLI 入口。
246
+ - 必要时在脚本入口处增加守卫,检测到 `OPENXIANGDA_ACCESS_TOKEN` 缺失时输出明确指引:`请通过 openxiangda workspace publish 发布`。
@@ -0,0 +1,105 @@
1
+ # Workflow V3 Reference
2
+
3
+ Workflow definitions are JSON objects saved by `openxiangda workflow create`.
4
+
5
+ Minimum shape:
6
+
7
+ ```json
8
+ {
9
+ "version": "v3",
10
+ "nodes": [
11
+ { "id": "start", "type": "start", "data": { "label": "开始" } },
12
+ { "id": "approve", "type": "approval", "data": { "label": "审批" } },
13
+ { "id": "end", "type": "end", "data": { "label": "结束" } }
14
+ ],
15
+ "edges": [
16
+ { "id": "e1", "source": "start", "target": "approve" },
17
+ { "id": "e2", "source": "approve", "target": "end" }
18
+ ],
19
+ "flowConfig": {}
20
+ }
21
+ ```
22
+
23
+ Rules:
24
+
25
+ - `nodes` and `edges` must be arrays.
26
+ - `version` must be `v3`.
27
+ - Publishing requires one `start` node and at least one `end` node.
28
+ - Each node needs `id`, `type`, and object `data`.
29
+ - Edges must reference existing node IDs.
30
+ - Keep live platform IDs out of the JSON when possible. Resolve `formUuid` and `workflowId` through CLI state.
31
+ - JS_CODE V2 supports trusted Node execution. For AI/admin logic use `runtimeMode: "trusted_node"`.
32
+
33
+ Supported node types:
34
+
35
+ - `start`
36
+ - `approval`
37
+ - `condition`
38
+ - `condition_branch`
39
+ - `end`
40
+ - `copy`
41
+ - `js_code`
42
+ - `branch`
43
+ - `data_retrieve_single`
44
+ - `data_retrieve_batch`
45
+ - `data_create`
46
+ - `data_update`
47
+ - `loop_container`
48
+ - `connector_call`
49
+ - `callback_wait`
50
+ - `work_notification`
51
+ - `dingtalk_card`
52
+
53
+ ## JS_CODE V2
54
+
55
+ Inline:
56
+
57
+ ```json
58
+ {
59
+ "id": "calc",
60
+ "type": "js_code",
61
+ "data": {
62
+ "label": "计算",
63
+ "runtimeMode": "trusted_node",
64
+ "sourceType": "inline",
65
+ "code": "const crypto = require('crypto'); variables.hash = crypto.createHash('sha256').update('x').digest('hex'); return variables.hash;",
66
+ "timeout": 30000
67
+ }
68
+ }
69
+ ```
70
+
71
+ File snapshot:
72
+
73
+ ```json
74
+ {
75
+ "id": "sync_customer",
76
+ "type": "js_code",
77
+ "data": {
78
+ "label": "同步客户",
79
+ "runtimeMode": "trusted_node",
80
+ "sourceType": "file_snapshot",
81
+ "scriptCode": "sync_customer",
82
+ "sourceFile": {
83
+ "localPath": "src/js-code-nodes/sync_customer/index.ts"
84
+ },
85
+ "timeout": 30000
86
+ }
87
+ }
88
+ ```
89
+
90
+ AI-authored JS_CODE source must be TypeScript under `sy-lowcode-app-workspace/src/js-code-nodes/<scriptCode>/index.ts`. When validating or creating, the CLI runs `pnpm build-js-code --script <scriptCode>`, which runs TypeScript validation first, bundles to `dist/js-code-nodes/<scriptCode>/index.cjs`, uploads the bundle, and replaces `sourceFile.localPath` with immutable snapshot metadata. Scripts can export `export default async function (ctx) {}` or `module.exports = async (ctx) => {}` and call `ctx.platform.api` or global `platform.api`; the default API namespace is `/openxiangda-api/v1`.
91
+
92
+ Field permission config lives in `flowConfig` by node ID:
93
+
94
+ ```json
95
+ {
96
+ "flowConfig": {
97
+ "approve": [
98
+ { "fieldId": "amount", "fieldBehavior": "READONLY" },
99
+ { "fieldId": "remark", "fieldBehavior": "NORMAL" }
100
+ ]
101
+ }
102
+ }
103
+ ```
104
+
105
+ Allowed `fieldBehavior` values: `NORMAL`, `READONLY`, `HIDDEN`.
@@ -0,0 +1,45 @@
1
+ # Workspace State
2
+
3
+ OpenXiangda project state lives in `.openxiangda/state.json`.
4
+
5
+ Tokens never belong in the project. User tokens live in `~/.openxiangda/profiles.json`.
6
+
7
+ ## Shape
8
+
9
+ ```json
10
+ {
11
+ "version": 1,
12
+ "profiles": {
13
+ "dev": {
14
+ "baseUrl": "https://dev-lowcode.example.com/service",
15
+ "appType": "APP_DEV",
16
+ "resources": {
17
+ "forms": {
18
+ "customer": {
19
+ "formUuid": "FORM_XXX"
20
+ }
21
+ },
22
+ "pages": {
23
+ "dashboard": {
24
+ "pageId": "PAGE_XXX",
25
+ "routeKey": "dashboard",
26
+ "legacyFormUuid": "FORM_LEGACY_PAGE"
27
+ }
28
+ },
29
+ "workflows": {},
30
+ "automations": {},
31
+ "menus": {}
32
+ }
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ## Rules
39
+
40
+ - Profile is the deployment boundary.
41
+ - `baseUrl` is the backend API base. On standard private deployments it is `<origin>/service`; management pages use `/platform`, and app runtime pages use `/view`.
42
+ - Local resource keys are logical codes.
43
+ - Live IDs are nested under the profile that produced them.
44
+ - A prod publish must not read dev IDs.
45
+ - Before publishing to another platform, run `openxiangda workspace bind --profile <name> --app-type <APP_XXX>`.
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: openxiangda-app
3
+ description: Manage OpenXiangda low-code apps, profiles, workspace initialization, workspace binding, app snapshots, menus, and profile-isolated resource state through the openxiangda CLI.
4
+ ---
5
+
6
+ # OpenXiangda App
7
+
8
+ Use this when the user needs to create, bind, inspect, or publish an app on a private OpenXiangda platform.
9
+
10
+ ## Required Context
11
+
12
+ Always start from the current profile and workspace binding:
13
+
14
+ ```bash
15
+ openxiangda env --profile <name>
16
+ openxiangda auth status --profile <name>
17
+ ```
18
+
19
+ If the workspace is not bound:
20
+
21
+ ```bash
22
+ openxiangda app list --profile <name>
23
+ openxiangda workspace bind --profile <name> --app-type APP_XXX
24
+ ```
25
+
26
+ If there is no local app workspace yet:
27
+
28
+ ```bash
29
+ openxiangda workspace init ./my-app-workspace --profile <name> --app-type APP_XXX
30
+ cd ./my-app-workspace
31
+ pnpm install
32
+ ```
33
+
34
+ For menu work:
35
+
36
+ ```bash
37
+ openxiangda menu list --profile <name>
38
+ openxiangda menu create main --name "主菜单" --type nav --profile <name>
39
+ openxiangda menu create customer-entry --name "客户信息" --type receipt --form-code customer --profile <name>
40
+ ```
41
+
42
+ If the app does not exist:
43
+
44
+ ```bash
45
+ openxiangda app create "应用名称" --profile <name>
46
+ openxiangda workspace bind --profile <name> --app-type APP_XXX
47
+ ```
48
+
49
+ ## Rules
50
+
51
+ - Never ask for AK/SK.
52
+ - Always pass `--profile` for publish or cross-platform operations.
53
+ - Use `openxiangda workspace init <dir>` before page/form work when the user starts from a new empty directory.
54
+ - Store platform-specific IDs only in `.openxiangda/state.json`.
55
+ - Use logical local codes for forms, pages, workflows, automations, and menus.
56
+ - Use `openxiangda app snapshot <APP_XXX> --profile <name> --json` before changing an existing app.
57
+
58
+ ## Resource State
59
+
60
+ Read `../../references/workspace-state.md` when changing `.openxiangda/state.json`.
61
+
62
+ Read `../../references/openxiangda-api.md` when exact endpoint fields are needed.
63
+
64
+ Read `../../references/architecture-patterns.md` to understand the overall app structure (how forms, pages, menus, workflows, and permissions compose into an app, and the recommended `src/forms` / `src/pages` layout) before scaffolding or restructuring an app workspace.
@@ -0,0 +1,143 @@
1
+ ---
2
+ name: openxiangda-core
3
+ description: Core OpenXiangda CLI workflow for normal-user token login, platform profiles, workspace initialization, workspace binding, multi-platform publishing, and lightweight app inspection.
4
+ ---
5
+
6
+ # OpenXiangda Core
7
+
8
+ ## Login
9
+
10
+ Use ordinary platform login:
11
+
12
+ ```bash
13
+ openxiangda login https://lowcode.example.com --profile dev
14
+ ```
15
+
16
+ The CLI creates a one-time login session, opens the platform authorization page, polls the backend, and stores the returned `accessToken` and `refreshToken` in `~/.openxiangda/profiles.json` with file mode `0600`.
17
+
18
+ Do not request or generate AK/SK credentials.
19
+
20
+ ## Private Routing
21
+
22
+ OpenXiangda private deployments use fixed public paths:
23
+
24
+ - `/service` for backend APIs.
25
+ - `/platform` for platform management pages and login redirects.
26
+ - `/view` for app runtime pages.
27
+
28
+ The CLI profile stores the API base. If the user enters a root domain, `/platform` URL, or `/view` URL, normalize it to `<origin>/service` before calling OpenXiangda APIs. Never call `/openxiangda-api/v1` directly at the root domain.
29
+
30
+ ## Profiles
31
+
32
+ ```bash
33
+ openxiangda platform add dev https://dev-lowcode.example.com
34
+ openxiangda platform add prod https://lowcode.example.com/platform
35
+ openxiangda platform list
36
+ openxiangda platform use dev
37
+ ```
38
+
39
+ Use `--profile` for every destructive or publishing action. Treat the profile as the deployment boundary.
40
+
41
+ Run write commands sequentially in the same workspace because they update `.openxiangda/state.json`. Read-only commands such as list, pull, snapshot, and inspect may run in parallel.
42
+
43
+ ## Workspace State
44
+
45
+ Create a workspace when the current project does not already contain a `sy-lowcode-app-workspace`:
46
+
47
+ ```bash
48
+ openxiangda workspace init ./my-app-workspace --profile dev --app-type APP_DEV
49
+ cd ./my-app-workspace
50
+ pnpm install
51
+ openxiangda env --profile dev
52
+ ```
53
+
54
+ If the workspace already exists, bind each platform to its own app, then publish from `sy-lowcode-app-workspace`:
55
+
56
+ ```bash
57
+ openxiangda app list --profile dev
58
+ openxiangda app create "测试应用" --profile dev
59
+ openxiangda workspace bind --profile dev --app-type APP_DEV
60
+ openxiangda workspace bind --profile prod --app-type APP_PROD
61
+ cd /path/to/sy-lowcode-app-workspace
62
+ openxiangda workspace publish --profile dev
63
+ ```
64
+
65
+ Read-only diagnosis can use resource commands:
66
+
67
+ ```bash
68
+ openxiangda form list --profile dev
69
+ openxiangda form pull customer --profile dev
70
+ openxiangda page list --profile dev
71
+ openxiangda workflow list --form-code customer --profile dev
72
+ openxiangda automation list --form-code customer --profile dev
73
+ openxiangda permission role-list --profile dev
74
+ openxiangda settings get customer --profile dev
75
+ openxiangda inspect app --profile dev --json
76
+ ```
77
+
78
+ `openxiangda form create`, `form publish`, and `page publish` are low-level repair commands. Do not use them as the normal AI page generation path.
79
+
80
+ Project state is stored in `.openxiangda/state.json`:
81
+
82
+ ```json
83
+ {
84
+ "version": 1,
85
+ "profiles": {
86
+ "dev": {
87
+ "baseUrl": "https://dev-lowcode.example.com/service",
88
+ "appType": "APP_DEV",
89
+ "resources": {
90
+ "forms": {},
91
+ "pages": {},
92
+ "workflows": {},
93
+ "automations": {},
94
+ "menus": {},
95
+ "roles": {},
96
+ "pagePermissionGroups": {},
97
+ "formPermissionGroups": {}
98
+ }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ The CLI reads `.openxiangda/state.json` from the current working directory. Run workspace commands from the workspace root unless the CLI has explicit parent-directory discovery in the current version.
105
+
106
+ ## Inspection
107
+
108
+ Use snapshots to understand an app before editing:
109
+
110
+ ```bash
111
+ openxiangda app snapshot APP_XXX --profile dev --json
112
+ ```
113
+
114
+ The snapshot endpoint aggregates app metadata, forms, menus, code pages, release summaries, and permission hints using the logged-in user's permissions.
115
+
116
+ ## Publishing
117
+
118
+ ```bash
119
+ openxiangda workspace publish --profile prod
120
+ ```
121
+
122
+ The CLI checks that the target profile is logged in and bound to an app. It then runs the workspace publish script with these environment variables:
123
+
124
+ - `OPENXIANGDA_PROFILE`
125
+ - `OPENXIANGDA_BASE_URL`
126
+ - `OPENXIANGDA_ACCESS_TOKEN`
127
+ - `OPENXIANGDA_APP_TYPE`
128
+
129
+ Publishing scripts must read these values instead of AK/SK.
130
+
131
+ The publish script is responsible for:
132
+
133
+ 1. Scanning `src/forms/*/schema.ts` and `page.tsx` for normal and workflow form pages.
134
+ 2. Creating or binding platform form shells only as needed.
135
+ 3. Building form runtime, form bundles, and code page bundles.
136
+ 4. Uploading assets to OSS.
137
+ 5. Registering bundles through `/openxiangda-api/v1` with `OPENXIANGDA_ACCESS_TOKEN`.
138
+
139
+ ## References
140
+
141
+ - `../../references/openxiangda-api.md` — exact endpoint contracts.
142
+ - `../../references/workspace-state.md` — `.openxiangda/state.json` shape and profile-scoped resource maps.
143
+ - `../../references/architecture-patterns.md` — overall architecture of an OpenXiangda app workspace (CRUD data flow, page/form layering, recommended directory organization). Read this when you need to understand how forms, pages, workflows, and platform state fit together end-to-end.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: openxiangda-form
3
+ description: Create, bind, generate, sync, and publish OpenXiangda normal form pages and workflow form pages through sy-lowcode-app-workspace bundles, profile state, and token-based workspace publish.
4
+ ---
5
+
6
+ # OpenXiangda Form
7
+
8
+ Use this when the user asks to create or update normal forms, workflow forms, form page source, form bundles, or form runtime publishing.
9
+
10
+ ## Required Workspace Flow
11
+
12
+ ```bash
13
+ openxiangda env --profile <name>
14
+ openxiangda form list --profile <name>
15
+ cd /path/to/sy-lowcode-app-workspace
16
+ ```
17
+
18
+ If the workspace does not exist yet, create it before writing form source:
19
+
20
+ ```bash
21
+ openxiangda workspace init ./my-app-workspace --profile <name> --app-type APP_XXX
22
+ cd ./my-app-workspace
23
+ pnpm install
24
+ ```
25
+
26
+ Create or edit workspace source:
27
+
28
+ ```text
29
+ src/forms/<formCode>/
30
+ ├── schema.ts
31
+ └── page.tsx
32
+ ```
33
+
34
+ Then publish:
35
+
36
+ ```bash
37
+ openxiangda workspace publish --profile <name>
38
+ ```
39
+
40
+ The workspace publish script receives `OPENXIANGDA_BASE_URL`, `OPENXIANGDA_ACCESS_TOKEN`, and `OPENXIANGDA_APP_TYPE` from the CLI. It creates/binds the platform form shell only when needed, syncs form metadata, builds the React form page bundle, uploads assets, and registers the bundle.
41
+
42
+ ## Low-level Commands
43
+
44
+ Use these only for diagnosis, binding existing resources, or repairing a broken publish state:
45
+
46
+ ```bash
47
+ openxiangda form bind customer --form-uuid FORM_XXX --profile <name>
48
+ openxiangda form pull customer --profile <name> --json
49
+ openxiangda form create customer --name "客户信息" --profile <name>
50
+ openxiangda form publish customer --bundle-url <url> --profile <name>
51
+ ```
52
+
53
+ Do not use `openxiangda form create` as the normal way to generate a user-facing page. It creates the old platform form shell and will show the legacy default schema until a workspace bundle is published.
54
+
55
+ ## Workspace Form Rules
56
+
57
+ Read these references only when writing or reviewing schema:
58
+
59
+ - `../../references/forms/form-schema.md`
60
+ - `../../references/forms/component-registry.md`
61
+ - `../../references/forms/layout-and-rules.md`
62
+ - `../../references/platform-data-model.md` — how each field type is persisted (JSONB, `{label, value}` for option fields, attachment shape). Consult before designing schema or wiring values.
63
+ - `../../references/component-guide.md` — when to pick platform form components vs. custom widgets, and the option-component rules.
64
+
65
+ ## Rules
66
+
67
+ - Prefer deterministic `formCode` as local key; bind live `formUuid` under the active profile.
68
+ - For multi-platform publishing, create or bind the form separately for each profile.
69
+ - Do not copy `formUuid` from dev to prod unless the target platform explicitly already uses that ID.
70
+ - Keep `schema.ts` and `page.tsx` as the source for fields/layout/rules and presentation; generated build output is not the source of truth.
71
+ - In `schema.ts`, import `defineFormSchema` from `openxiangda` and default-export the schema.
72
+ - Put validation on field-level `rules`; never generate old top-level validation arrays under `schema.rules`. Top-level `rules` is only for `FormEffect[]` with `when` and `then`.
73
+ - Always provide `options` for option components. `SelectField`, `MultiSelectField`, `RadioField`, `CheckboxField`, and `CascadeSelectField` must not be emitted with `options` undefined. See `../../references/component-guide.md` for the full list and `../../references/platform-data-model.md` for the `{label, value}` storage contract.
74
+ - Workflow form pages use the same workspace form structure plus workflow v3 configuration; publish the form page bundle through workspace publish before treating it as complete.
75
+ - Use `openxiangda form pull` or app snapshot before overwriting an existing form.
76
+ - Before assuming a value shape (e.g. dates, attachments, member fields, option fields), verify against `../../references/platform-data-model.md` instead of guessing.