openxiangda 1.0.36 → 1.0.38

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 (33) hide show
  1. package/README.md +10 -0
  2. package/lib/cli.js +43 -3
  3. package/lib/workspace-bootstrap.js +238 -0
  4. package/openxiangda-skills/SKILL.md +42 -3
  5. package/openxiangda-skills/references/pages/page-sdk.md +32 -0
  6. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +348 -0
  7. package/openxiangda-skills/skills/openxiangda-app/SKILL.md +18 -2
  8. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +37 -1
  9. package/openxiangda-skills/skills/openxiangda-form/SKILL.md +37 -2
  10. package/openxiangda-skills/skills/openxiangda-inspect/SKILL.md +26 -2
  11. package/openxiangda-skills/skills/openxiangda-page/SKILL.md +36 -2
  12. package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +19 -2
  13. package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +26 -2
  14. package/package.json +1 -1
  15. package/packages/sdk/dist/runtime/index.cjs +114 -0
  16. package/packages/sdk/dist/runtime/index.cjs.map +1 -1
  17. package/packages/sdk/dist/runtime/index.d.mts +14 -1
  18. package/packages/sdk/dist/runtime/index.d.ts +14 -1
  19. package/packages/sdk/dist/runtime/index.mjs +114 -0
  20. package/packages/sdk/dist/runtime/index.mjs.map +1 -1
  21. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-form.mdc +20 -0
  22. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-page.mdc +19 -0
  23. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +28 -0
  24. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-workflow-automation.mdc +21 -0
  25. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +47 -0
  26. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-form.md +34 -0
  27. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-page.md +37 -0
  28. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +46 -0
  29. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-workflow-automation.md +46 -0
  30. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +47 -0
  31. package/templates/sy-lowcode-app-workspace/AGENTS.md +92 -0
  32. package/templates/sy-lowcode-app-workspace/package.json +7 -0
  33. package/templates/sy-lowcode-app-workspace/scripts/guard-publish.mjs +29 -0
@@ -0,0 +1,28 @@
1
+ ---
2
+ description: src/resources/** — Resource manifests, use logical codes only
3
+ globs: src/resources/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Resource Manifests
8
+
9
+ Editing engineering-managed manifests under `src/resources/`. **All platform IDs are resolved by the CLI**; only logical `code` values go here.
10
+
11
+ | Path | Skill |
12
+ |---|---|
13
+ | `connectors/<code>.json` | `openxiangda-page` |
14
+ | `data-views/<code>.json` | `openxiangda-form` |
15
+ | `notifications/<code>.json` | `openxiangda-page` / `-workflow-automation` |
16
+ | `workflows/<code>/` | `openxiangda-workflow-automation` |
17
+ | `automations/<code>/` | `openxiangda-workflow-automation` |
18
+ | `roles/<code>.json` | `openxiangda-permission-settings` |
19
+ | `permissions/page-groups/<code>.json` | `openxiangda-permission-settings` |
20
+ | `permissions/form-groups/<formCode>/<code>.json` | `openxiangda-permission-settings` |
21
+ | `settings/forms/<formCode>.json` | `openxiangda-permission-settings` |
22
+ | `menus/<code>.json` | `openxiangda-app` |
23
+
24
+ See `references/resource-manifest-cheatsheet.md` for copy-paste skeletons.
25
+
26
+ Commands: `openxiangda resource validate|plan|publish|pull --profile <name>`.
27
+
28
+ Forbidden: 把 `formUuid` / `pageId` / `workflowId` 等平台 ID 写进 manifest;把 API key / token / secret / authorization 写进 manifest;data view 用作单表 CRUD / linkedForm / 写回 / 强实时;page 源里 hardcode 通知或 connector URL。
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: src/{workflows,automations,js-code-nodes}/** — Use openxiangda-workflow-automation skill
3
+ globs: src/{workflows,automations,js-code-nodes}/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Workflow / Automation / JS_CODE
8
+
9
+ Editing one of:
10
+ - `src/workflows/<code>/workflow.ts` # 代码优先工作流
11
+ - `src/automations/<code>/index.ts` # automation_code_ts (推荐)
12
+ - `src/js-code-nodes/<code>/index.ts` # JS_CODE V2 trusted_node
13
+
14
+ Use the **`openxiangda-workflow-automation`** skill.
15
+
16
+ Boundary: **大多数业务流转不是 workflow**。`pending → processing → resolved → closed` 用表单 `status` 字段 + 状态机 + automation。仅有真审批语义(审批人 / 任务 / 同意/驳回 / 节点权限 / 流程记录)才创建 workflow。
17
+
18
+ JS_CODE 适用:跨表查询、批量更新、终止流程、平台 API、外部 HTTP。**不适用**:UI 交互、普通校验、展示逻辑。
19
+
20
+ Build: `pnpm build-js-code --script <code>`(先 `tsc` 再打包)。
21
+ Publish: `openxiangda workflow|automation validate|create|publish --profile <name>`。
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: OpenXiangda workspace strong constraint — routing, commands, invariants, prohibitions
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # OpenXiangda Workspace Rule
7
+
8
+ This is a `sy-lowcode-app-workspace` managed by the `openxiangda` CLI. See [AGENTS.md](mdc:AGENTS.md) for full guidance.
9
+
10
+ ## Hard route — user intent → skill / command
11
+
12
+ | User says | Skill | Command |
13
+ |---|---|---|
14
+ | publish / deploy / 发布 / 上线 / 部署 | `openxiangda-core` | `openxiangda workspace publish --profile <name>` (+ `--changed` / `--page` / `--form` / `--only`) |
15
+ | create / scaffold app / 创建应用 / 初始化 | `openxiangda-app` | `openxiangda workspace init <dir> --profile <name> --app-name "..."` |
16
+ | bind existing app / 绑定已有应用 | `openxiangda-app` | `openxiangda workspace bind --profile <name> --app-type APP_XXX` |
17
+ | edit form / schema / 表单字段 / 表单页 | `openxiangda-form` | edit `src/forms/<code>/` → `workspace publish --form <code>` |
18
+ | edit code page / portal / dashboard / 代码页 | `openxiangda-page` | edit `src/pages/<code>/` → `workspace publish --page <code>` |
19
+ | approval workflow / 审批流程 / JS_CODE | `openxiangda-workflow-automation` | `openxiangda workflow ...` |
20
+ | automation / cron / 自动化 / 定时 | `openxiangda-workflow-automation` | `openxiangda automation ...` |
21
+ | role / permission / 公开访问 | `openxiangda-permission-settings` | `openxiangda permission ...` / `openxiangda settings ...` |
22
+ | diagnose / snapshot / 排查 / 报错 | `openxiangda-inspect` | `openxiangda app snapshot APP_XXX --profile <name> --json` |
23
+ | login / token / switch profile | `openxiangda-core` | `openxiangda env --profile <name>` / `openxiangda auth status` |
24
+
25
+ ## Always
26
+
27
+ - For routine edits, default to incremental publish: `workspace publish --profile <name> --changed --dry-run` then `--changed` or targeted `--page <code>` / `--form <code>`.
28
+ - Confirm current profile before any write: `openxiangda env --profile <name>`.
29
+ - `.openxiangda/state.json` is the authoritative profile → appType → resource-ID map; CLI maintains it, do not hand-edit.
30
+ - User tokens live in `~/.openxiangda/profiles.json`; shared env in `~/.openxiangda/.env`.
31
+ - Form fields need user-facing `placeholder`; use `SelectField` / `RadioField` for enums, `linkedForm` SelectField for cross-form sources.
32
+ - Pages default to `cssIsolation: "none"` + native Tailwind utilities; formal entries must be app-shell.
33
+
34
+ ## Never
35
+
36
+ - ❌ `pnpm publish:all` / `pnpm publish:oss` / `pnpm register` / `lowcode-workspace publish-*` directly. They are guarded by `_guard:publish` and will fail-fast without `OPENXIANGDA_PROFILE`.
37
+ - ❌ Ask for AK / SK / appKey / appSecret.
38
+ - ❌ Search the platform for similar app names when `.openxiangda/state.json` has no binding.
39
+ - ❌ Copy `formUuid` / `pageId` / `workflowId` / `automationId` across profiles.
40
+ - ❌ Run a full publish for a single-file edit.
41
+ - ❌ Use `openxiangda form create` / `form publish` / `page publish` as the normal page generation path.
42
+ - ❌ Store tokens / AK / SK / third-party secrets in project files.
43
+ - ❌ `npm publish` — this workspace is `"private": true`, not an npm package.
44
+
45
+ ## When unsure
46
+
47
+ Read [AGENTS.md](mdc:AGENTS.md) and the global skill: `~/.qoder/skills/openxiangda/SKILL.md`.
@@ -0,0 +1,34 @@
1
+ ---
2
+ description: src/forms/** glob — 精准引导到 openxiangda-form skill
3
+ glob: src/forms/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Form Files
8
+
9
+ You are editing files under `src/forms/<formCode>/`. Use the **`openxiangda-form`** skill.
10
+
11
+ ## Required structure
12
+
13
+ ```text
14
+ src/forms/<formCode>/
15
+ ├── schema.ts # defineFormSchema() default export — fields / options / rules / top-level FormEffect[]
16
+ └── page.tsx # presentation only
17
+ ```
18
+
19
+ ## Common pitfalls (high signal)
20
+
21
+ - 选项字段(Select / MultiSelect / Radio / Checkbox / Cascade)必须有 `options`,不要给空。
22
+ - 跨表数据 → `SelectField` + `optionSource.type: "linkedForm"`,**禁止** `AssociationFormField`。
23
+ - 顶层 `schema.rules` 仅用于 `FormEffect[]`(`when` / `then`),**不要**写成校验数组;校验放字段 `rules`。
24
+ - 平台系统字段(创建人 / 修改人 / 创建时间 / 修改时间 / 部门)由平台自动维护,**不要重复创建**。
25
+ - 隐式权限键 / 派生键 → `behavior: "HIDDEN"` + `valueSync`。
26
+
27
+ ## Publish
28
+
29
+ ```bash
30
+ openxiangda workspace publish --profile <name> --form <formCode> --dry-run
31
+ openxiangda workspace publish --profile <name> --form <formCode>
32
+ ```
33
+
34
+ 不要用 `openxiangda form create` / `form publish` 作为日常路径(仅底层修复)。
@@ -0,0 +1,37 @@
1
+ ---
2
+ description: src/pages/** glob — 精准引导到 openxiangda-page skill
3
+ glob: src/pages/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Page Files
8
+
9
+ You are editing files under `src/pages/<pageCode>/`. Use the **`openxiangda-page`** skill.
10
+
11
+ ## Required structure(复杂页面拆分)
12
+
13
+ ```text
14
+ src/pages/<pageCode>/
15
+ ├── page.config.ts # entry / route / navigation
16
+ ├── page.tsx # 薄视图层
17
+ ├── domain/ # 业务规则、状态机、查询构造器(可被 PC/移动复用)
18
+ ├── shared/{services,hooks}/ # 数据访问层、复用 hook
19
+ ├── components/ # 页面内组件
20
+ └── styles.css # 页面级样式
21
+ ```
22
+
23
+ ## Strong defaults
24
+
25
+ - 正式入口(管理后台 / PC 门户 / 移动门户)必须 `entry: { mode: "app-shell", hidePlatformNav: true, defaultRoute: "<home>" }`。
26
+ - 默认 `cssIsolation: "none"` + 原生 Tailwind utilities(`bg-white`, `border-slate-200`, `grid-cols-[240px_1fr]`),不要 `bg-card` / `text-muted-foreground` 这些未配置的 shadcn token。
27
+ - 列表页:用 `DataManagementList` 模式 + 分页 + 结构化 `filterGroup`,**不要** `pageSize=10000` 然后前端过滤。
28
+ - 外部接口:`src/resources/connectors/` + `sdk.connector.call()`;多表只读联表:`src/resources/data-views/` + `sdk.dataView.query()`;通知:`src/resources/notifications/` + `sdk.notification`。
29
+
30
+ ## Publish
31
+
32
+ ```bash
33
+ openxiangda workspace publish --profile <name> --page <pageCode> --dry-run
34
+ openxiangda workspace publish --profile <name> --page <pageCode>
35
+ ```
36
+
37
+ 不要用 `openxiangda page publish` 作为日常路径(仅底层修复)。
@@ -0,0 +1,46 @@
1
+ ---
2
+ description: src/resources/** glob — 精准引导到 connector / data-view / notification / role / permission / settings 资源 manifest
3
+ glob: src/resources/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Resource Manifests
8
+
9
+ You are editing engineering-managed resource manifests under `src/resources/`. **All平台资源 ID 由 CLI 解析**;本地只用逻辑 code。
10
+
11
+ ## 必看:复制即用速查
12
+
13
+ `references/resource-manifest-cheatsheet.md`(installed at `~/.qoder/skills/openxiangda/references/resource-manifest-cheatsheet.md`)— connector / data-view / notification / workflow / automation / JS_CODE / role / page-group / form-group / settings / menu 骨架。
14
+
15
+ ## 文件夹与对应 skill
16
+
17
+ | 路径 | 用途 | 主导 skill |
18
+ |---|---|---|
19
+ | `src/resources/connectors/<code>.json` | 第三方 / 自建系统 HTTP 连接器 | `openxiangda-page` |
20
+ | `src/resources/data-views/<code>.json` | 多表只读联表(materialized view) | `openxiangda-form` |
21
+ | `src/resources/notifications/<code>.json` | 通知模板 + typeConfigs | `openxiangda-page` / `-workflow-automation` |
22
+ | `src/resources/workflows/<code>/{workflow.json,definition.v3.json,preview.json}` | 工作流 manifest | `openxiangda-workflow-automation` |
23
+ | `src/resources/automations/<code>/{definition.code.json,preview.json}` | 自动化 manifest | `openxiangda-workflow-automation` |
24
+ | `src/resources/roles/<code>.json` | 角色 | `openxiangda-permission-settings` |
25
+ | `src/resources/permissions/page-groups/<code>.json` | 页面权限组 | `openxiangda-permission-settings` |
26
+ | `src/resources/permissions/form-groups/<formCode>/<code>.json` | 表单权限组 | `openxiangda-permission-settings` |
27
+ | `src/resources/settings/forms/<formCode>.json` | 表单设置 / 索引 / 数据管理页 / 公开访问 | `openxiangda-permission-settings` |
28
+ | `src/resources/menus/<code>.json` | 菜单 | `openxiangda-app` |
29
+
30
+ ## 命令
31
+
32
+ ```bash
33
+ openxiangda resource validate --profile <name> # 静态校验
34
+ openxiangda resource plan --profile <name> # diff 本地 vs. 平台
35
+ openxiangda resource publish --profile <name> # upsert(默认不 prune)
36
+ openxiangda resource publish --profile <name> --prune # 删除 manifest 未声明的平台资源(谨慎)
37
+ openxiangda resource pull --profile <name> # 平台 → 本地
38
+ ```
39
+
40
+ ## 严禁
41
+
42
+ - ❌ 把 `formUuid` / `pageId` / `workflowId` 等平台 ID 直接写进 manifest(CLI 解析逻辑 code)。
43
+ - ❌ 把 API key / token / secret / password / authorization / headers / credential 写进 manifest(平台后台配置)。
44
+ - ❌ data view 用作单表 CRUD、`linkedForm` 下拉、写回、强实时数据源。
45
+ - ❌ 在 page 源里 hardcode `/api/notification-config/*` 或 `/connectors/actions/invoke`(用 `sdk.notification` / `sdk.connector`)。
46
+ - ❌ 同时在 manifest 与平台后台编辑同一个资源(漂移源)。
@@ -0,0 +1,46 @@
1
+ ---
2
+ description: src/{workflows,automations,js-code-nodes}/** glob — 精准引导到 openxiangda-workflow-automation skill
3
+ glob: src/{workflows,automations,js-code-nodes}/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # OpenXiangda Workflow / Automation / JS_CODE Files
8
+
9
+ You are editing files under one of:
10
+
11
+ - `src/workflows/<code>/workflow.ts` # 代码优先工作流(推荐用于无需画布编辑的场景)
12
+ - `src/automations/<code>/index.ts` # 代码优先自动化(automation_code_ts,推荐)
13
+ - `src/js-code-nodes/<code>/index.ts` # JS_CODE V2 trusted_node 后端脚本
14
+
15
+ Use the **`openxiangda-workflow-automation`** skill.
16
+
17
+ ## Boundary — workflow vs. status field
18
+
19
+ **大多数业务流转不是工作流。** `pending → processing → resolved → closed` 用表单 + `status` 字段 + 状态机 + automation/JS_CODE。
20
+ 仅当存在**真正的审批语义**(审批人 / 审批任务 / 同意/驳回 / 意见 / 节点字段权限 / 流程记录 / 节点副作用)时创建 workflow。
21
+
22
+ ## JS_CODE 适用与不适用
23
+
24
+ - ✅ 跨表查询、批量更新、终止流程、平台 API、外部 HTTP、复杂编排。
25
+ - ✅ `ctx.logger.debug/info/warn/error(message, data?)` 在每个关键步骤埋点。
26
+ - ❌ 简单 UI 交互、普通表单校验、纯展示逻辑 → 应在 React 代码页里。
27
+
28
+ ## 构建与发布
29
+
30
+ ```bash
31
+ # JS_CODE V2 本地构建
32
+ pnpm build-js-code --script <scriptCode>
33
+
34
+ # workflow / automation 校验 + 发布
35
+ openxiangda workflow validate / create / publish --profile <name>
36
+ openxiangda automation validate / create / publish / enable --profile <name>
37
+
38
+ # 排查
39
+ openxiangda automation executions <code> --profile <name>
40
+ openxiangda automation logs <instanceId> --profile <name>
41
+ openxiangda automation diagnose <code> --profile <name>
42
+ ```
43
+
44
+ 不要把 `workflowId` / `automationId` 跨 profile 复制;每个 profile 独立维护。
45
+
46
+ 详见 `references/automation-v3.md` / `workflow-v3.md` / `resource-manifest-cheatsheet.md`。
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: OpenXiangda 工作区强约束 — 路由、命令、不变量、禁令
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # OpenXiangda Workspace Rule
7
+
8
+ This is a `sy-lowcode-app-workspace` managed by the `openxiangda` CLI. Read [AGENTS.md](AGENTS.md) for the full guidance. The summary below is auto-injected into every Qoder turn.
9
+
10
+ ## Hard route — 用户意图 → skill / 命令
11
+
12
+ | 用户说 | 必用 skill | 必用命令 |
13
+ |---|---|---|
14
+ | 发布 / 上线 / 部署 / publish / deploy | `openxiangda-core` | `openxiangda workspace publish --profile <name>` (+`--changed` / `--page` / `--form` / `--only`) |
15
+ | 创建 / 初始化应用 | `openxiangda-app` | `openxiangda workspace init <dir> --profile <name> --app-name "..."` |
16
+ | 绑定已有应用 | `openxiangda-app` | `openxiangda workspace bind --profile <name> --app-type APP_XXX` |
17
+ | 改表单字段 / schema / 表单页 | `openxiangda-form` | 编辑 `src/forms/<code>/` → `workspace publish --form <code>` |
18
+ | 改代码页 / portal / dashboard | `openxiangda-page` | 编辑 `src/pages/<code>/` → `workspace publish --page <code>` |
19
+ | 审批流程 / workflow / JS_CODE | `openxiangda-workflow-automation` | `openxiangda workflow ...` |
20
+ | 自动化 / 定时 / 提交触发 | `openxiangda-workflow-automation` | `openxiangda automation ...` |
21
+ | 角色 / 权限 / 公开访问 | `openxiangda-permission-settings` | `openxiangda permission ...` / `openxiangda settings ...` |
22
+ | 排查 / 快照 / 对比 / 报错 | `openxiangda-inspect` | `openxiangda app snapshot APP_XXX --profile <name> --json` |
23
+ | 登录 / token / 切平台 | `openxiangda-core` | `openxiangda env --profile <name>` / `openxiangda auth status` |
24
+
25
+ ## Always
26
+
27
+ - 单文件改动默认增量发布:先 `workspace publish --profile <name> --changed --dry-run`,再 `--changed` 或 `--page <code>` / `--form <code>`。
28
+ - 任何写操作前确认当前 profile:`openxiangda env --profile <name>`。
29
+ - `.openxiangda/state.json` 是 profile 到 appType / 资源 ID 的权威映射,由 CLI 维护,不要手改。
30
+ - 用户 token 在 `~/.openxiangda/profiles.json`;共享 env 在 `~/.openxiangda/.env`。
31
+ - 表单字段必须有 user-facing `placeholder`;选项使用 `SelectField` / `RadioField`,跨表用 `linkedForm` SelectField。
32
+ - 页面默认 `cssIsolation: "none"` + 原生 Tailwind utilities;正式入口必须是 app-shell。
33
+
34
+ ## Never
35
+
36
+ - ❌ `pnpm publish:all` / `pnpm publish:oss` / `pnpm register` / `lowcode-workspace publish-*` 直接调用。它们由 `_guard:publish` 拦截,缺少 `OPENXIANGDA_PROFILE` 时会 fail-fast。
37
+ - ❌ 询问 AK / SK / appKey / appSecret。
38
+ - ❌ 在没有本地 `.openxiangda/state.json` 绑定时,去平台搜索同名应用"复用"。
39
+ - ❌ 把 `formUuid` / `pageId` / `workflowId` / `automationId` 从 dev 复制到 prod。
40
+ - ❌ 改一处就全量发布。
41
+ - ❌ `openxiangda form create` / `form publish` / `page publish` 当作页面生成方式(仅底层修复)。
42
+ - ❌ 把 token / AK / SK / 第三方密钥写进项目文件。
43
+ - ❌ `npm publish` — 本工作区 `"private": true`,不发 npm 包。
44
+
45
+ ## When unsure
46
+
47
+ 读 [AGENTS.md](AGENTS.md) 与全局 skill:`~/.qoder/skills/openxiangda/SKILL.md`。
@@ -0,0 +1,92 @@
1
+ # AGENTS.md — OpenXiangda 工作区 AI 强约束
2
+
3
+ > 任何 AI(Qoder / Claude / Codex / Cursor / Copilot 等)在本工作区操作前 **必须先读完本文件**。
4
+ > 这是 `sy-lowcode-app-workspace`,由 `openxiangda` CLI 统一管理;普通 npm 习惯不适用于此工作区的发布与生命周期操作。
5
+
6
+ ## 一句话原则
7
+
8
+ **所有"发布 / 上线 / 部署 / publish / deploy / ship / release"请求,唯一正确入口是 `openxiangda workspace publish --profile <name>`,不要直接 `pnpm publish:all`。**
9
+
10
+ 工作区内的 npm scripts(`publish:all` / `publish:oss` / `register`)已加 `_guard:publish` 守卫;缺少 `OPENXIANGDA_PROFILE` 环境变量时会立即 fail,提示重新走 CLI 入口。
11
+
12
+ ## 路由表 — 用户意图 → 命令 / skill
13
+
14
+ | 用户说(中 / 英) | 用 skill | 第一条命令 |
15
+ |---|---|---|
16
+ | 发布 / 上线 / 部署 / publish / deploy | `openxiangda-core` | `openxiangda workspace publish --profile <name> --changed --dry-run` |
17
+ | 只发布改动 / 增量 / 单页 / 单表 | `openxiangda-core` | `... --changed` / `--page <code>` / `--form <code>` / `--only pages/a,forms/b` |
18
+ | 创建应用 / 新建 app / 初始化工作区 | `openxiangda-app` | `openxiangda workspace init <dir> --profile <name> --app-name "..."` |
19
+ | 绑定已有应用 | `openxiangda-app` | `openxiangda workspace bind --profile <name> --app-type APP_XXX` |
20
+ | 创建 / 改表单字段、schema、表单页 | `openxiangda-form` | 编辑 `src/forms/<code>/{schema.ts,page.tsx}` → `workspace publish --form <code>` |
21
+ | 创建 / 改自定义代码页、portal、看板 | `openxiangda-page` | 编辑 `src/pages/<code>/` → `workspace publish --page <code>` |
22
+ | 审批流程 / 流程节点 / JS_CODE | `openxiangda-workflow-automation` | `openxiangda workflow validate / create / publish` |
23
+ | 自动化 / 定时任务 / 提交触发 / cron | `openxiangda-workflow-automation` | `openxiangda automation validate / create / publish / enable` |
24
+ | 角色 / 权限组 / 字段权限 / 公开访问 | `openxiangda-permission-settings` | `openxiangda permission ...` / `openxiangda settings ...` |
25
+ | 查应用结构 / 快照 / 对比 / 排查 / 报错 | `openxiangda-inspect` | `openxiangda app snapshot <APP_XXX> --profile <name> --json` |
26
+ | 登录 / 切平台 / token / whoami | `openxiangda-core` | `openxiangda env --profile <name>` / `openxiangda auth status` |
27
+ | 多表只读联表查询 / 报表数据源 | `openxiangda-form`(data view) | 在 `src/resources/data-views/<code>.json` 声明 → `resource publish` |
28
+ | 调外部 / 第三方 API / 钉钉 / 自建系统 | `openxiangda-page`(connector) | 在 `src/resources/connectors/<code>.json` 声明 → `sdk.connector.invoke()` |
29
+
30
+ ## 必须遵守
31
+
32
+ - ✅ 先 preflight:`openxiangda env --profile <name>` + `openxiangda auth status --profile <name>` + `openxiangda update check --json`。
33
+ - ✅ 单文件改动默认增量发布:`workspace publish --profile <name> --changed --dry-run` → `--changed` / `--page` / `--form`。
34
+ - ✅ 用户 token 在 `~/.openxiangda/profiles.json`;项目 state 在 `.openxiangda/state.json`(只存 ID)。
35
+ - ✅ 共享环境(`APP_OSS_*`、反馈机器人等)在 `~/.openxiangda/.env`,项目 `.env` 仅做 per-workspace override。
36
+ - ✅ 多 profile(dev / prod / ...)资源 ID 互不复用;每个 profile 的 `appType` / `formUuid` / `pageId` / `workflowId` / `automationId` 独立维护。
37
+ - ✅ 改已有应用前先 `openxiangda app snapshot APP_XXX --profile <name> --json`。
38
+
39
+ ## 严禁
40
+
41
+ - ❌ 直接 `pnpm publish:all` / `pnpm publish:oss` / `pnpm register` / `lowcode-workspace publish-*`。它们是工作区内部脚本,不会注入 `OPENXIANGDA_PROFILE / BASE_URL / ACCESS_TOKEN / APP_TYPE`,发到错的环境也无人提醒。
42
+ - ❌ 询问 AK / SK / appKey / appSecret。整个流程基于普通用户登录 token。
43
+ - ❌ 在没有本地 `.openxiangda/state.json` 绑定时,去平台搜索同名应用尝试"复用"。空目录 / 无绑定 → 直接 `workspace init --app-name` 创建新应用。
44
+ - ❌ 把 `openxiangda form create` / `form publish` / `page publish` 当作日常页面生成方式。它们仅作底层修复 / 诊断。
45
+ - ❌ 改一个文件就 `workspace publish` 全量。
46
+ - ❌ 把 token、AK、SK、第三方密钥写进项目文件。
47
+ - ❌ `npm publish` —— 这个工作区是 `"private": true` 的应用工作区,不是要发到 npm 的 package。
48
+
49
+ ## 表单 / 页面写作约束(高频踩坑)
50
+
51
+ - 表单字段:可见字段必须有用户能看懂的 `placeholder`;`tips` 只用于特殊约束。
52
+ - 表单选项:用 `SelectField` / `RadioField` 表枚举;跨表数据用 `SelectField` + `optionSource.type: "linkedForm"`(数据量大时加 `remoteSearch: true` + `searchFieldId`)。**禁止**新建 `AssociationFormField`。
53
+ - 权限隐式键、计算字段、同步字段:在 schema 中保留 `behavior: "HIDDEN"`,由可见字段通过 `valueSync` 派生,不要让用户填裸 ID。
54
+ - 页面默认 `cssIsolation: "none"` + 原生 Tailwind utilities(`bg-white`、`border-slate-200`、`grid-cols-[240px_1fr]` 等),不要用 `bg-card` / `text-muted-foreground` 这类未配置的 shadcn token。
55
+ - 列表页用 `DataManagementList` 模式 + 分页 + 结构化 `filterGroup`,不要 `pageSize=10000` 然后前端过滤。
56
+ - 正式入口(管理后台 / PC 门户 / 移动门户)必须是 app-shell:`page.config.ts` 里 `entry: { mode: "app-shell", hidePlatformNav: true, defaultRoute: "<home>" }`。
57
+ - 对外接口走 `src/resources/connectors/`;多表只读联表走 `src/resources/data-views/`;通知模板走 `src/resources/notifications/`。
58
+
59
+ ## 工作区结构速查
60
+
61
+ ```text
62
+ sy-lowcode-app-workspace/
63
+ ├── AGENTS.md # 本文件
64
+ ├── .qoder/rules/openxiangda.md # Qoder always-on 项目规则
65
+ ├── .cursor/rules/openxiangda.mdc # Cursor always-on 项目规则
66
+ ├── .openxiangda/state.json # profile → appType → 资源 ID 的权威映射(CLI 维护)
67
+ ├── app-workspace.config.ts
68
+ ├── package.json # publish:all/publish:oss/register 都被 _guard:publish 守卫
69
+ ├── src/
70
+ │ ├── forms/<formCode>/{schema.ts,page.tsx} # 表单页源(openxiangda-form)
71
+ │ ├── pages/<pageCode>/ # 自定义代码页源(openxiangda-page)
72
+ │ ├── workflows/<code>/workflow.ts # 代码优先工作流(openxiangda-workflow-automation)
73
+ │ ├── automations/<code>/index.ts # 代码优先自动化
74
+ │ ├── js-code-nodes/<code>/index.ts # JS_CODE V2 trusted_node TS 源
75
+ │ └── resources/ # data-views / connectors / notifications / roles / ...
76
+ └── examples/best-practices/ # 仅参考;不发布
77
+ ```
78
+
79
+ ## 还想看更细的
80
+
81
+ - 全局 skill:`~/.qoder/skills/openxiangda/SKILL.md`(root 决策卡)+ 7 个子 skill。
82
+ - 资源 / 连接器 manifest:`docs/openxiangda-resources-and-connectors.md`(来自 openxiangda 仓库)。
83
+ - 平台数据模型:`references/platform-data-model.md`(option `{label, value}`、附件、成员字段等持久化形态)。
84
+ - 排错清单:`references/troubleshooting.md`。
85
+
86
+ ## 升级现有工作区
87
+
88
+ 如果这份文件是后加上来的,请确认下面三件事:
89
+
90
+ 1. `package.json` 的 `publish:all` / `publish:oss` / `register` 已加上 `pnpm _guard:publish && ...` 前缀。
91
+ 2. `.qoder/rules/openxiangda.md` 与 `.cursor/rules/openxiangda.mdc` 都存在。
92
+ 3. `openxiangda update check --json` 显示已是最新,并跑过 `openxiangda skill install --force`。
@@ -14,11 +14,18 @@
14
14
  "typecheck:js-code": "tsc -p tsconfig.js-code-nodes.json --noEmit",
15
15
  "examples:check": "tsc -p tsconfig.examples.json --noEmit",
16
16
  "sync-schema": "lowcode-workspace sync-schema",
17
+ "_guard:publish": "node scripts/guard-publish.mjs",
18
+ "prepublish:oss": "pnpm _guard:publish",
17
19
  "publish:oss": "lowcode-workspace publish-oss",
20
+ "preregister": "pnpm _guard:publish",
18
21
  "register": "lowcode-workspace register",
22
+ "preregister-bundle": "pnpm _guard:publish",
19
23
  "register-bundle": "lowcode-workspace register",
24
+ "prepublish:all": "pnpm _guard:publish",
20
25
  "publish:all": "lowcode-workspace publish-all",
26
+ "prepublish:changed": "pnpm _guard:publish",
21
27
  "publish:changed": "lowcode-workspace publish-all --changed",
28
+ "preopenxiangda:publish": "pnpm _guard:publish",
22
29
  "openxiangda:publish": "lowcode-workspace publish-all",
23
30
  "ai:update": "pnpm dlx openxiangda@latest lowcode-workspace update --channel latest",
24
31
  "ai:migrate": "pnpm dlx openxiangda@latest lowcode-workspace migrate",
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ // _guard:publish 守卫:拦截直接调用 publish:all / publish:oss / register 等内部 npm script 的尝试。
3
+ // 仅当通过 `openxiangda workspace publish --profile <name>` 入口发布时,CLI 会注入
4
+ // OPENXIANGDA_PROFILE / OPENXIANGDA_BASE_URL / OPENXIANGDA_ACCESS_TOKEN / OPENXIANGDA_APP_TYPE
5
+ // 等环境变量;本守卫据此放行内部脚本,否则 fail-fast 并提示正确入口。
6
+
7
+ if (!process.env.OPENXIANGDA_PROFILE) {
8
+ const lines = [
9
+ '',
10
+ '❌ 错误:请使用 openxiangda workspace publish --profile <name>',
11
+ '',
12
+ '此 npm script(publish:all / publish:oss / register / publish:changed / openxiangda:publish 等)',
13
+ '是工作区内部实现,直接调用会缺少 token / profile / appType / OSS 密钥的注入,',
14
+ '可能发到错误的环境,或彻底发不出去。',
15
+ '',
16
+ '正确入口:',
17
+ ' openxiangda workspace publish --profile <name> # 全量',
18
+ ' openxiangda workspace publish --profile <name> --changed # 增量(推荐)',
19
+ ' openxiangda workspace publish --profile <name> --page X # 单页',
20
+ ' openxiangda workspace publish --profile <name> --form Y # 单表',
21
+ '',
22
+ '更多说明详见工作区根目录的 AGENTS.md。',
23
+ '',
24
+ ];
25
+ for (const line of lines) {
26
+ console.error(line);
27
+ }
28
+ process.exit(1);
29
+ }