openxiangda 1.0.89 → 1.0.90
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 +16 -6
- package/openxiangda-skills/SKILL.md +3 -3
- package/openxiangda-skills/references/architecture-design.md +2 -1
- package/openxiangda-skills/references/openxiangda-api.md +1 -1
- package/openxiangda-skills/references/pages/page-sdk.md +17 -8
- package/openxiangda-skills/references/resource-manifest-cheatsheet.md +15 -5
- package/package.json +1 -1
- package/packages/sdk/dist/runtime/index.cjs +1495 -1371
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +1 -1
- package/packages/sdk/dist/runtime/index.d.ts +1 -1
- package/packages/sdk/dist/runtime/index.mjs +504 -380
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +311 -6
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +11 -1
- package/packages/sdk/dist/runtime/react.d.ts +11 -1
- package/packages/sdk/dist/runtime/react.mjs +311 -6
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
- package/templates/openxiangda-react-spa/src/app/router.tsx +4 -1
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ const affiliatedDepartmentExternalId = user?.affiliatedDepartment?.externalId
|
|
|
174
174
|
|
|
175
175
|
工程化资源放在工作区 `src/resources/` 下,由 `openxiangda resource validate|plan|publish|pull` 管理。`workspace publish` 会先构建并注册 workspace 表单/页面,再执行非破坏性资源 upsert,这样菜单、权限组、流程和表单设置可以解析最新的 profile-local ID。需要删除平台中 manifest 未声明的资源时,显式传 `--prune`。连接器页面运行时通过 `sdk.connector.invoke()` / `sdk.connector.call("connector.api")` 调用平台运行时接口,第三方密钥只保存在后端连接器配置中。
|
|
176
176
|
|
|
177
|
-
React SPA 新应用的无需登录访问统一使用 `/view/:appType/public/*`。应用在 `src/resources/routes/*.json` 声明公开路由,在 `src/resources/public-access/*.json` 声明公开策略、外部角色和可访问资源 grant,页面用 `PublicAccessGate` 或 `createPublicAccessClient` 创建 scoped public session。公开 guest 的 form、dataView、function、connector 默认全部拒绝,只有 policy `grants` 明确列出的资源可访问,并且仍受对应表单权限组、dataView 权限组等后端权限控制。
|
|
177
|
+
React SPA 新应用的无需登录访问统一使用 `/view/:appType/public/*`。应用在 `src/resources/routes/*.json` 声明公开路由,在 `src/resources/public-access/*.json` 声明公开策略、外部角色和可访问资源 grant,页面用 `PublicAccessGate` 或 `createPublicAccessClient` 创建 scoped public session。React SPA 路由树必须在 `OpenXiangdaProvider` 内再包一层 `OpenXiangdaPageProvider`;页面只要调用 `usePageSdk()`、`usePageContext()`、`useDataSource()` 等 Page SDK hooks,就依赖这层 provider。公开 guest 的 form、dataView、function、connector 默认全部拒绝,只有 policy `grants` 明确列出的资源可访问,并且仍受对应表单权限组、dataView 权限组等后端权限控制。
|
|
178
178
|
|
|
179
179
|
`mode: "ticket"` 的公开策略默认按单次 ticket 使用;只有明确配置 `ticketConfig.singleUse: false` 时才允许复用。新 public session 只返回 bearer token,SDK 会把 token 注入后续 runtime/bootstrap、dataView、function、connector 请求,不依赖认证 cookie。
|
|
180
180
|
|
|
@@ -199,13 +199,23 @@ React SPA 新应用的无需登录访问统一使用 `/view/:appType/public/*`
|
|
|
199
199
|
```
|
|
200
200
|
|
|
201
201
|
```tsx
|
|
202
|
-
import {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
202
|
+
import {
|
|
203
|
+
OpenXiangdaPageProvider,
|
|
204
|
+
OpenXiangdaProvider,
|
|
205
|
+
PublicAccessGate,
|
|
206
|
+
} from "openxiangda/runtime/react"
|
|
207
|
+
|
|
208
|
+
<OpenXiangdaProvider appType={appType} servicePrefix="/service">
|
|
209
|
+
<OpenXiangdaPageProvider>
|
|
210
|
+
<PublicAccessGate policyCode="public_register" routeCode="public.register">
|
|
211
|
+
<PublicRegisterPage />
|
|
212
|
+
</PublicAccessGate>
|
|
213
|
+
</OpenXiangdaPageProvider>
|
|
214
|
+
</OpenXiangdaProvider>
|
|
207
215
|
```
|
|
208
216
|
|
|
217
|
+
不要把 `PublicAccessGate` 单独放在没有 `OpenXiangdaProvider` / `OpenXiangdaPageProvider` 的页面树下;否则 public session 不能注入后续 SDK 请求,`usePageSdk()` 也会抛出 `usePageSdkStore 必须在 PageProvider 内使用`。
|
|
218
|
+
|
|
209
219
|
多表只读查询和固定口径统计优先声明 `src/resources/data-views/*.json` 数据视图,而不是在页面里手写多次单表查询再拼数据。默认 `storageMode: "materialized"` 会创建 PostgreSQL materialized view,适合读多写少和可接受刷新延迟的列表/报表;`storageMode: "live"` 每次查询实时编译逻辑视图,适合强实时但数据量可控的复杂查询。`viewType: "aggregate"` 是统计聚合视图,适合按客户、状态、月份等维度聚合 count/sum/avg/min/max。发布时 CLI 会把 `formCode` 解析为当前 profile 的 `formUuid`;页面通过 `sdk.dataView.query(code, params)` 查询行级视图,通过 `sdk.dataView.stats(code, params)` 查询聚合视图,也可以用 `sdk.dataSource.run()` 路由 `dataView.query` / `dataView.stats`。materialized 模式应为常用筛选、排序、统计维度和时间桶声明 `indexes`,并确认用户能接受的刷新延迟;live 模式忽略 `indexes`,不需要刷新。
|
|
210
220
|
|
|
211
221
|
后端业务逻辑优先声明为 App Function:源码放在 `src/functions/<functionCode>/index.ts`,资源 manifest 放在 `src/resources/functions/<functionCode>.json`。函数运行在 trusted_node 中,通过 `ctx.form`、`ctx.dataView`、`ctx.connector`、`ctx.notification`、`ctx.platform.api` 等受控 API 访问平台能力;自动化、流程和运行时接口都可以调用同一个 function。JS_CODE V2 仍兼容,但新逻辑建议写成 function,再由 `function_call` 节点、`sdk.function.invoke(code, { input })` 或 `/:appType/v1/functions/:code/invoke.json` 调用。当前 MVP 中直接运行时接口要求调用者具备应用自动化管理权限,自动化/流程内部调用走服务端受控上下文。
|
|
@@ -30,7 +30,7 @@ OpenXiangda supports two workspace modes. Classic `sy-lowcode-app-workspace` pub
|
|
|
30
30
|
| App Function / function_call / 可复用后端逻辑 | `openxiangda-workflow-automation` | declare `src/resources/functions/<code>.json` + `src/functions/<code>/index.ts` |
|
|
31
31
|
| 应用登录 / Auth SDK / 手机号验证码 / CAS / 钉钉免登 | `openxiangda-architecture-design` + `openxiangda-page` | design security gate first, then declare `src/resources/auth/<code>.json` and use `createAuthClient` / `LoginPage` |
|
|
32
32
|
| 角色 / 权限组 / 字段权限 / 数据范围 | `openxiangda-permission-settings` | `openxiangda permission ...` / `openxiangda settings ...` |
|
|
33
|
-
| 外部人员无需登录访问 / 公开报名 / 公开查询 / public page | `openxiangda-architecture-design` + `openxiangda-permission-settings` + `openxiangda-page` | 先确认公开范围、外部角色、ticket、grants;再声明 `routes` + `public-access`
|
|
33
|
+
| 外部人员无需登录访问 / 公开报名 / 公开查询 / public page | `openxiangda-architecture-design` + `openxiangda-permission-settings` + `openxiangda-page` | 先确认公开范围、外部角色、ticket、grants;再声明 `routes` + `public-access`,并用 `OpenXiangdaProvider` + `OpenXiangdaPageProvider` + `PublicAccessGate` |
|
|
34
34
|
| 看应用结构 / 快照 / 对比 / 诊断 / 排查 / 报错 | `openxiangda-inspect` | `openxiangda app snapshot <APP_XXX> --profile <name> --json` |
|
|
35
35
|
| 登录 / 切换平台 / profile / token / whoami | `openxiangda-core` | `openxiangda env --profile <name>` / `openxiangda auth status` |
|
|
36
36
|
| 多表只读联表 / 固定口径统计 / 强实时复杂查询 / 看板指标 | `openxiangda-form` (data view) | declare `src/resources/data-views/<code>.json` with `storageMode` → `resource publish` |
|
|
@@ -45,7 +45,7 @@ OpenXiangda supports two workspace modes. Classic `sy-lowcode-app-workspace` pub
|
|
|
45
45
|
- ✅ Run `openxiangda update check --json` at the start of substantial work; if `updateAvailable`, run `openxiangda update install` and `openxiangda skill install --force`.
|
|
46
46
|
- ✅ For non-trivial app requirements, run the architecture design gate first: forms, fields, pages, permissions, data views, status/workflow, automation, notifications, and development tasks must be decided before coding.
|
|
47
47
|
- ✅ For app login/auth requirements, run the auth security gate before coding: enabled methods, registration policy, identity matching keys, provider boundary, default roles, rate limits, audit fields, and third-party ownership must be confirmed.
|
|
48
|
-
- ✅ For public/no-login access requirements, run the public access design gate before coding: public routes, external role codes, guest vs ticket, form/dataView/function/connector grants, and backend permission groups must be confirmed. New React SPA apps use `/view/:appType/public/*`, `src/resources/routes/`, `src/resources/public-access/`, and `PublicAccessGate`.
|
|
48
|
+
- ✅ For public/no-login access requirements, run the public access design gate before coding: public routes, external role codes, guest vs ticket, form/dataView/function/connector grants, and backend permission groups must be confirmed. New React SPA apps use `/view/:appType/public/*`, `src/resources/routes/`, `src/resources/public-access/`, and `PublicAccessGate`; route children that use Page SDK hooks must be inside `OpenXiangdaProvider` + `OpenXiangdaPageProvider`.
|
|
49
49
|
- ✅ Public/no-login validation must inspect the JSON envelope, not only HTTP status. HTTP 200 with `code: "PUBLIC_GRANT_DENIED"` is a denied request; success requires `code` `200`, `"200"`, or compatible `0`, and no `success: false`.
|
|
50
50
|
- ✅ For form-entry UX, pick components in this order: OpenXiangda platform form components → `antd` / `antd-mobile` wrappers → custom component only when neither exists.
|
|
51
51
|
- ✅ List pages, linked options, remote selectors, and report drill-downs must use paginated server-side queries with explicit searchable fields. Do not fetch a large page and filter in local state.
|
|
@@ -149,7 +149,7 @@ When the user provides a root domain such as `https://yida.wisejob.cn/`, use it
|
|
|
149
149
|
- For external APIs, create a connector manifest in `src/resources/connectors/` and call it from pages through `sdk.connector`; never put third-party API keys in page source.
|
|
150
150
|
- For reusable backend logic shared by pages, automations, and workflows, create an App Function in `src/resources/functions/<functionCode>.json` plus `src/functions/<functionCode>/index.ts`. Call it from pages with `sdk.function.invoke`, from automation/workflow graphs with `function_call`, or from the runtime endpoint when the caller has app automation management permission. Current App Function MVP exposes controlled helpers such as `ctx.resources`, `ctx.form`, `ctx.dataView`, `ctx.connector`, `ctx.notification`, and `ctx.platform.api`; it does not expose raw SQL or Redis.
|
|
151
151
|
- For application login, declare auth resources in `src/resources/auth/<code>.json` and publish them with `openxiangda resource publish`. App Function auth providers may validate external credentials and return only an identity assertion; they must never issue tokens, set cookies, or write platform user/binding tables directly. The platform auth service decides create/bind/reject and issues tokens.
|
|
152
|
-
- For external/no-login pages in React SPA apps, declare `src/resources/routes/<code>.json` and `src/resources/public-access/<code>.json`, put the page under `/view/:appType/public/*`, and use `PublicAccessGate` or `createPublicAccessClient`. Public guest access to forms, dataViews, functions, and connectors is denied unless policy `grants` explicitly names the resource; backend permission groups still apply.
|
|
152
|
+
- For external/no-login pages in React SPA apps, declare `src/resources/routes/<code>.json` and `src/resources/public-access/<code>.json`, put the page under `/view/:appType/public/*`, and use `PublicAccessGate` or `createPublicAccessClient`. The route tree must also include `OpenXiangdaPageProvider` inside `OpenXiangdaProvider` before any `usePageSdk()` / `usePageContext()` / `useDataSource()` call; otherwise pages throw `usePageSdkStore 必须在 PageProvider 内使用`. Public guest access to forms, dataViews, functions, and connectors is denied unless policy `grants` explicitly names the resource; backend permission groups still apply.
|
|
153
153
|
- When verifying public access, parse the response body and reject string business errors such as `PUBLIC_GRANT_DENIED` even if the HTTP status is 200. Do not use `response.ok` alone as the success condition.
|
|
154
154
|
- Before scaffolding a real app, complex page, data management page, portal shell, status lifecycle, role governance, or automation, read `references/best-practices.md` and pick the architecture first. Prefer copying the relevant pattern from `examples/best-practices/` into `src/` instead of generating a single large page file.
|
|
155
155
|
- Before publishing to another platform, verify the workspace is bound for that profile. Resource IDs from one profile must not be reused for another profile.
|
|
@@ -264,8 +264,9 @@ For simple CRUD/admin lists, design can proceed with the appropriate OpenXiangda
|
|
|
264
264
|
- Public policies live under `src/resources/public-access/`.
|
|
265
265
|
- Policy `externalRoleCodes` are virtual role codes carried by the scoped public token; use the same codes in page/form/dataView permission groups.
|
|
266
266
|
- Policy `grants` must list every form/dataView/function/connector the public page can access. Do not rely on broad guest permissions.
|
|
267
|
-
- Use `PublicAccessGate` in React routes or `createPublicAccessClient` for custom bootstrapping.
|
|
267
|
+
- Use `PublicAccessGate` in React routes or `createPublicAccessClient` for custom bootstrapping. If the page uses Page SDK hooks, the route tree must have `OpenXiangdaProvider` plus `OpenXiangdaPageProvider`; `PublicAccessGate` alone is not enough.
|
|
268
268
|
- In validation scripts, success requires the JSON envelope success code (`200`, `"200"`, or compatible `0`). HTTP 200 with `code: "PUBLIC_GRANT_DENIED"` is a denied request, not a success.
|
|
269
|
+
- Validation must include at least one real browser render check for each public and private route, because API-only E2E can miss provider/runtime crashes such as `usePageSdkStore 必须在 PageProvider 内使用`.
|
|
269
270
|
- Old `?publicAccess=guest` and form `publicAccess` settings are legacy compatibility and should not appear in new-app designs.
|
|
270
271
|
|
|
271
272
|
## Final Document Template
|
|
@@ -289,7 +289,7 @@ Body:
|
|
|
289
289
|
}
|
|
290
290
|
```
|
|
291
291
|
|
|
292
|
-
The response returns a scoped bearer token. New React SPA apps must use `PublicAccessGate` or `createPublicAccessClient` so follow-up runtime/bootstrap, dataView, function, and connector calls include `Authorization: Bearer <token>`. Do not depend on auth cookies for public sessions.
|
|
292
|
+
The response returns a scoped bearer token. New React SPA apps must use `PublicAccessGate` or `createPublicAccessClient` so follow-up runtime/bootstrap, dataView, function, and connector calls include `Authorization: Bearer <token>`. React SPA route trees still need `OpenXiangdaProvider` plus `OpenXiangdaPageProvider` when pages use Page SDK hooks. Do not depend on auth cookies for public sessions.
|
|
293
293
|
|
|
294
294
|
Returns the normal guest token payload plus `extra.publicAccess`.
|
|
295
295
|
|
|
@@ -16,6 +16,7 @@ Guidelines:
|
|
|
16
16
|
- Use `sdk.notification.sendByType` and `batchSendByType` for reusable business messages. Custom notification types must be declared in `src/resources/notifications/` and published with `openxiangda resource publish`.
|
|
17
17
|
- Use `createAuthClient` from `openxiangda/runtime` or `LoginPage` / `useAuth` from `openxiangda/runtime/react` for application login pages. Auth provider App Functions return identity assertions only; platform auth owns create/bind/reject/token decisions.
|
|
18
18
|
- Use `PublicAccessGate` from `openxiangda/runtime/react` or `createPublicAccessClient` from `openxiangda/runtime` for React SPA public pages under `/view/:appType/public/*`. Do not append old `?publicAccess=guest` links in new apps.
|
|
19
|
+
- In React SPA apps, wrap route children with `OpenXiangdaPageProvider` inside `OpenXiangdaProvider` before using `usePageSdk()`, `usePageContext()`, `useDataSource()`, or `useFormViewPermissions()`. `OpenXiangdaProvider` alone is not enough and missing the page provider causes `usePageSdkStore 必须在 PageProvider 内使用`.
|
|
19
20
|
- For the current user's department hierarchy, use `sdk.department.getCurrentUserParentDepartments()`; do not hardcode `GET /department/:id/parentDepartments` in page code.
|
|
20
21
|
- Use `sdk.auth.logoutAndRedirect({ loginUrl })` for user logout when the page should return after login. It calls the platform logout endpoint, appends the current page URL as `callback`, and redirects to the login URL. Use `sdk.auth.logout()` only when the page wants to handle redirect itself.
|
|
21
22
|
- Use `sdk.role.getMyRoles()`, `sdk.role.getCurrentRole()`, and `sdk.role.switchAppRole()` for current-user app role switching. Pass `roleId: ""` to switch back to all app roles.
|
|
@@ -145,16 +146,24 @@ For phone-code auth, the App Function provider receives `event`, `appType`, `met
|
|
|
145
146
|
Public access route:
|
|
146
147
|
|
|
147
148
|
```tsx
|
|
148
|
-
import {
|
|
149
|
+
import {
|
|
150
|
+
OpenXiangdaPageProvider,
|
|
151
|
+
OpenXiangdaProvider,
|
|
152
|
+
PublicAccessGate,
|
|
153
|
+
} from "openxiangda/runtime/react";
|
|
149
154
|
|
|
150
155
|
export function PublicRegisterRoute() {
|
|
151
156
|
return (
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
157
|
+
<OpenXiangdaProvider appType={appType} servicePrefix="/service">
|
|
158
|
+
<OpenXiangdaPageProvider>
|
|
159
|
+
<PublicAccessGate
|
|
160
|
+
policyCode="public_register"
|
|
161
|
+
routeCode="public.register"
|
|
162
|
+
>
|
|
163
|
+
<PublicRegisterPage />
|
|
164
|
+
</PublicAccessGate>
|
|
165
|
+
</OpenXiangdaPageProvider>
|
|
166
|
+
</OpenXiangdaProvider>
|
|
158
167
|
);
|
|
159
168
|
}
|
|
160
169
|
```
|
|
@@ -174,7 +183,7 @@ await publicAccess.startSession({
|
|
|
174
183
|
});
|
|
175
184
|
```
|
|
176
185
|
|
|
177
|
-
`PublicAccessGate` stores the returned bearer token in the runtime provider and injects it into follow-up SDK requests. If you call `createPublicAccessClient` directly outside the provider, pass the returned `accessToken` as `Authorization: Bearer <token>` for follow-up APIs. The matching resources must exist under `src/resources/routes/` and `src/resources/public-access/`. Public guest access to forms, data views, functions, and connectors is denied unless the policy `grants` explicitly names that resource.
|
|
186
|
+
`PublicAccessGate` stores the returned bearer token in the runtime provider and injects it into follow-up SDK requests. It does not replace `OpenXiangdaPageProvider`. If you call `createPublicAccessClient` directly outside the provider, pass the returned `accessToken` as `Authorization: Bearer <token>` for follow-up APIs. The matching resources must exist under `src/resources/routes/` and `src/resources/public-access/`. Public guest access to forms, data views, functions, and connectors is denied unless the policy `grants` explicitly names that resource.
|
|
178
187
|
|
|
179
188
|
When testing public pages or writing direct fetch wrappers, check the JSON envelope, not only `response.ok`. Platform runtime APIs can return HTTP 200 with `code: "PUBLIC_GRANT_DENIED"`; this is a failed request. Treat only `code === 200`, `code === "200"`, or compatible success code `0` as success, and fail on `success: false`.
|
|
180
189
|
|
|
@@ -119,13 +119,23 @@ await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
|
|
|
119
119
|
React Router 中用 `PublicAccessGate` 创建 scoped public session:
|
|
120
120
|
|
|
121
121
|
```tsx
|
|
122
|
-
import {
|
|
122
|
+
import {
|
|
123
|
+
OpenXiangdaPageProvider,
|
|
124
|
+
OpenXiangdaProvider,
|
|
125
|
+
PublicAccessGate,
|
|
126
|
+
} from "openxiangda/runtime/react";
|
|
123
127
|
|
|
124
|
-
<
|
|
125
|
-
<
|
|
126
|
-
|
|
128
|
+
<OpenXiangdaProvider appType={appType} servicePrefix="/service">
|
|
129
|
+
<OpenXiangdaPageProvider>
|
|
130
|
+
<PublicAccessGate policyCode="public_register" routeCode="public.register">
|
|
131
|
+
<PublicRegisterPage />
|
|
132
|
+
</PublicAccessGate>
|
|
133
|
+
</OpenXiangdaPageProvider>
|
|
134
|
+
</OpenXiangdaProvider>
|
|
127
135
|
```
|
|
128
136
|
|
|
137
|
+
React SPA 中 `OpenXiangdaProvider` 负责 runtime/bootstrap 和 public token 注入,`OpenXiangdaPageProvider` 负责 `usePageSdk()` / `usePageContext()` 的 Page SDK 上下文。缺少 `OpenXiangdaPageProvider` 会抛出 `usePageSdkStore 必须在 PageProvider 内使用`。
|
|
138
|
+
|
|
129
139
|
公开访问验证必须检查 JSON envelope。HTTP 200 但 `code: "PUBLIC_GRANT_DENIED"` 代表后端已拒绝;只有 `code` 为 `200`、`"200"` 或兼容成功码 `0`,且没有 `success: false` 时才算成功。
|
|
130
140
|
|
|
131
141
|
## 2. Public Access Policy — `src/resources/public-access/<code>.json`
|
|
@@ -561,7 +571,7 @@ export default async function (ctx) {
|
|
|
561
571
|
}
|
|
562
572
|
```
|
|
563
573
|
|
|
564
|
-
`publicAccess` 表单 setting 只用于旧 `sy-lowcode-view` 兼容。新 React SPA 公开页面必须使用 `src/resources/routes/` + `src/resources/public-access/` + `PublicAccessGate`。
|
|
574
|
+
`publicAccess` 表单 setting 只用于旧 `sy-lowcode-view` 兼容。新 React SPA 公开页面必须使用 `src/resources/routes/` + `src/resources/public-access/` + `OpenXiangdaProvider` + `OpenXiangdaPageProvider` + `PublicAccessGate`。
|
|
565
575
|
|
|
566
576
|
## 12. Menu — `src/resources/menus/<code>.json`
|
|
567
577
|
|