openxiangda 1.0.86 → 1.0.87

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 (31) hide show
  1. package/README.md +28 -0
  2. package/lib/cli.js +391 -0
  3. package/openxiangda-skills/SKILL.md +5 -1
  4. package/openxiangda-skills/references/architecture-design.md +29 -0
  5. package/openxiangda-skills/references/openxiangda-api.md +105 -3
  6. package/openxiangda-skills/references/pages/page-sdk.md +35 -0
  7. package/openxiangda-skills/references/permissions-settings.md +39 -2
  8. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +70 -4
  9. package/package.json +1 -1
  10. package/packages/sdk/dist/runtime/index.cjs +3590 -3388
  11. package/packages/sdk/dist/runtime/index.cjs.map +1 -1
  12. package/packages/sdk/dist/runtime/index.d.mts +4 -1001
  13. package/packages/sdk/dist/runtime/index.d.ts +4 -1001
  14. package/packages/sdk/dist/runtime/index.mjs +3049 -2849
  15. package/packages/sdk/dist/runtime/index.mjs.map +1 -1
  16. package/packages/sdk/dist/runtime/react.cjs +2793 -116
  17. package/packages/sdk/dist/runtime/react.cjs.map +1 -1
  18. package/packages/sdk/dist/runtime/react.d.mts +1394 -2
  19. package/packages/sdk/dist/runtime/react.d.ts +1394 -2
  20. package/packages/sdk/dist/runtime/react.mjs +2749 -84
  21. package/packages/sdk/dist/runtime/react.mjs.map +1 -1
  22. package/templates/openxiangda-react-spa/AGENTS.md +29 -0
  23. package/templates/openxiangda-react-spa/src/app/router.tsx +21 -1
  24. package/templates/openxiangda-react-spa/src/pages/public/PublicRegisterPage.tsx +15 -0
  25. package/templates/openxiangda-react-spa/src/resources/permissions/page-groups/public-visitor.json +8 -0
  26. package/templates/openxiangda-react-spa/src/resources/public-access/public-register.json +14 -0
  27. package/templates/openxiangda-react-spa/src/resources/routes/public-register.json +8 -0
  28. package/templates/openxiangda-react-spa/tsconfig.app.json +1 -1
  29. package/templates/openxiangda-react-spa/vite.config.ts +1 -1
  30. package/packages/sdk/dist/openxiangdaProvider-CaXMpsnK.d.mts +0 -328
  31. package/packages/sdk/dist/openxiangdaProvider-CaXMpsnK.d.ts +0 -328
@@ -166,11 +166,11 @@ Body:
166
166
 
167
167
  ### GET `/apps/:appType/forms/:formUuid/public-access`
168
168
 
169
- Requires Bearer token. Returns public/guest access config for the form.
169
+ Requires Bearer token. Returns legacy public/guest access config for the form. This endpoint is only for old `sy-lowcode-view` compatibility.
170
170
 
171
171
  ### PUT `/apps/:appType/forms/:formUuid/public-access`
172
172
 
173
- Requires Bearer token. Creates or updates public/guest access config.
173
+ Requires Bearer token. Creates or updates legacy public/guest access config.
174
174
 
175
175
  Body:
176
176
 
@@ -183,7 +183,109 @@ Body:
183
183
 
184
184
  ### DELETE `/apps/:appType/forms/:formUuid/public-access`
185
185
 
186
- Requires Bearer token. Deletes public/guest access config for the form.
186
+ Requires Bearer token. Deletes legacy public/guest access config for the form.
187
+
188
+ ## React SPA Public Access
189
+
190
+ New React SPA apps use `/view/:appType/public/*`, route resources, public access policies, and a scoped public session. Do not use `?publicAccess=guest` for new apps.
191
+
192
+ ### GET `/apps/:appType/routes`
193
+
194
+ Requires Bearer token. Lists route resources.
195
+
196
+ ### POST `/apps/:appType/routes`
197
+
198
+ Requires Bearer token. Creates a route resource.
199
+
200
+ Body:
201
+
202
+ ```json
203
+ {
204
+ "code": "public.register",
205
+ "title": "公开报名",
206
+ "kind": "page",
207
+ "pathPattern": "/view/:appType/public/register",
208
+ "publicAccess": "guest",
209
+ "publicPolicyCode": "public_register"
210
+ }
211
+ ```
212
+
213
+ ### PUT `/apps/:appType/routes/:code`
214
+
215
+ Requires Bearer token. Updates a route resource.
216
+
217
+ ### DELETE `/apps/:appType/routes/:code`
218
+
219
+ Requires Bearer token. Deletes a route resource.
220
+
221
+ ### GET `/apps/:appType/public-access/policies`
222
+
223
+ Requires Bearer token. Lists public access policies.
224
+
225
+ ### POST `/apps/:appType/public-access/policies`
226
+
227
+ Requires Bearer token. Creates a public access policy.
228
+
229
+ Body:
230
+
231
+ ```json
232
+ {
233
+ "code": "public_register",
234
+ "name": "公开报名入口",
235
+ "enabled": true,
236
+ "mode": "guest",
237
+ "routeCode": "public.register",
238
+ "pathPattern": "/view/:appType/public/register",
239
+ "externalRoleCodes": ["external_visitor"],
240
+ "grants": {
241
+ "forms": ["FORM_UUID"],
242
+ "dataViews": ["public_registration_lookup"],
243
+ "functions": ["submit_public_registration"],
244
+ "connectors": ["sms.sendCode"]
245
+ }
246
+ }
247
+ ```
248
+
249
+ ### PUT `/apps/:appType/public-access/policies/:code`
250
+
251
+ Requires Bearer token. Updates a public access policy.
252
+
253
+ ### DELETE `/apps/:appType/public-access/policies/:code`
254
+
255
+ Requires Bearer token. Deletes a public access policy.
256
+
257
+ ### POST `/apps/:appType/public-access/policies/:code/tickets`
258
+
259
+ Requires Bearer token. Creates a ticket for a `mode: "ticket"` policy.
260
+
261
+ Body:
262
+
263
+ ```json
264
+ {
265
+ "expiresAt": "2026-06-18T12:00:00.000Z",
266
+ "subject": { "usage": "single-use" }
267
+ }
268
+ ```
269
+
270
+ ### POST `/apps/:appType/public/session`
271
+
272
+ Does not require an existing login. Creates a scoped public guest session.
273
+
274
+ Body:
275
+
276
+ ```json
277
+ {
278
+ "policyCode": "public_register",
279
+ "routeCode": "public.register",
280
+ "path": "/view/APP_XXX/public/register",
281
+ "ticket": "optional-ticket",
282
+ "guestIdentifier": "public:APP_XXX:browser-id",
283
+ "domain": "example.com",
284
+ "userAgent": "browser"
285
+ }
286
+ ```
287
+
288
+ Returns the normal guest token payload plus `extra.publicAccess`.
187
289
 
188
290
  ### GET `/apps/:appType/menus`
189
291
 
@@ -15,6 +15,7 @@ Guidelines:
15
15
  - Use `sdk.connector.invoke`, `sdk.connector.call("connector.api")`, or `sdk.connector.download` for external services. The SDK calls the platform runtime connector endpoint; it must not call third-party domains directly.
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
+ - 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.
18
19
  - For the current user's department hierarchy, use `sdk.department.getCurrentUserParentDepartments()`; do not hardcode `GET /department/:id/parentDepartments` in page code.
19
20
  - 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.
20
21
  - 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.
@@ -141,6 +142,40 @@ const result = await auth.phoneCodeLogin({
141
142
 
142
143
  For phone-code auth, the App Function provider receives `event`, `appType`, `method`, `credential`, `requestId`, `request`, and `challenge`. It may return `{ ok, providerState }` for send and `{ ok, identity }` for verify. It must not return `token`, `accessToken`, `refreshToken`, cookies, or mutate platform account tables.
143
144
 
145
+ Public access route:
146
+
147
+ ```tsx
148
+ import { PublicAccessGate } from "openxiangda/runtime/react";
149
+
150
+ export function PublicRegisterRoute() {
151
+ return (
152
+ <PublicAccessGate
153
+ policyCode="public_register"
154
+ routeCode="public.register"
155
+ >
156
+ <PublicRegisterPage />
157
+ </PublicAccessGate>
158
+ );
159
+ }
160
+ ```
161
+
162
+ Standalone public session client:
163
+
164
+ ```ts
165
+ import { createPublicAccessClient } from "openxiangda/runtime";
166
+
167
+ const publicAccess = createPublicAccessClient({ appType, servicePrefix: "/service" });
168
+
169
+ await publicAccess.startSession({
170
+ policyCode: "public_register",
171
+ routeCode: "public.register",
172
+ path: window.location.pathname,
173
+ ticket: new URLSearchParams(window.location.search).get("ticket") || undefined,
174
+ });
175
+ ```
176
+
177
+ 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
+
144
179
  Logout and current-user role switching:
145
180
 
146
181
  ```ts
@@ -185,7 +185,44 @@ Data management config is stored as an opaque JSON object by the platform. Keep
185
185
  }
186
186
  ```
187
187
 
188
- Public access config:
188
+ ## Public Access
189
+
190
+ 新 React SPA 应用的公开访问使用应用路由和公开策略资源:
191
+
192
+ ```json
193
+ {
194
+ "code": "public.register",
195
+ "pathPattern": "/view/:appType/public/register",
196
+ "publicAccess": "guest",
197
+ "publicPolicyCode": "public_register"
198
+ }
199
+ ```
200
+
201
+ ```json
202
+ {
203
+ "code": "public_register",
204
+ "mode": "guest",
205
+ "routeCode": "public.register",
206
+ "externalRoleCodes": ["external_visitor"],
207
+ "grants": {
208
+ "forms": ["registration_form"],
209
+ "dataViews": ["public_registration_lookup"],
210
+ "functions": ["submit_public_registration"],
211
+ "connectors": ["sms.sendCode"]
212
+ }
213
+ }
214
+ ```
215
+
216
+ Rules:
217
+
218
+ - Public routes live under `/view/:appType/public/*`.
219
+ - Public users get a scoped `publicAccess` claim, not a normal app role assignment.
220
+ - Use virtual external role codes, such as `external_visitor`, in page/form/dataView permission groups.
221
+ - Form/dataView/function/connector access is denied unless the policy explicitly grants it.
222
+ - `mode: "ticket"` requires a valid ticket for sensitive links.
223
+ - Do not use `?publicAccess=guest` for new React SPA apps.
224
+
225
+ Legacy form public access config:
189
226
 
190
227
  ```json
191
228
  {
@@ -194,4 +231,4 @@ Public access config:
194
231
  }
195
232
  ```
196
233
 
197
- Public access is resolved by `appType + formUuid`; no local ID mapping is needed.
234
+ This old form-level setting is resolved by `appType + formUuid` and exists only for old `sy-lowcode-view` compatibility.
@@ -101,7 +101,72 @@ await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
101
101
 
102
102
  设计前必须确认启用方式、注册策略、身份匹配键、provider 边界、默认权限、安全参数、第三方配置归属。
103
103
 
104
- ## 1. Connector — `src/resources/connectors/<code>.json`
104
+ ## 1. Public Route — `src/resources/routes/<code>.json`
105
+
106
+ 新 React SPA 公开页使用 `/view/:appType/public/*`,不要再使用旧 `?publicAccess=guest`。
107
+
108
+ ```json
109
+ {
110
+ "code": "public.register",
111
+ "title": "公开报名",
112
+ "kind": "page",
113
+ "pathPattern": "/view/:appType/public/register",
114
+ "publicAccess": "guest",
115
+ "publicPolicyCode": "public_register"
116
+ }
117
+ ```
118
+
119
+ React Router 中用 `PublicAccessGate` 创建 scoped public session:
120
+
121
+ ```tsx
122
+ import { PublicAccessGate } from "openxiangda/runtime/react";
123
+
124
+ <PublicAccessGate policyCode="public_register" routeCode="public.register">
125
+ <PublicRegisterPage />
126
+ </PublicAccessGate>
127
+ ```
128
+
129
+ ## 2. Public Access Policy — `src/resources/public-access/<code>.json`
130
+
131
+ 公开策略声明外部角色和可访问资源。未显式 grant 的 form/dataView/function/connector 默认拒绝;grant 后仍受对应后端权限组控制。
132
+
133
+ ```json
134
+ {
135
+ "code": "public_register",
136
+ "name": "公开报名入口",
137
+ "mode": "guest",
138
+ "routeCode": "public.register",
139
+ "pathPattern": "/view/:appType/public/register",
140
+ "externalRoleCodes": ["external_visitor"],
141
+ "grants": {
142
+ "forms": ["registration_form"],
143
+ "dataViews": ["public_registration_lookup"],
144
+ "functions": ["submit_public_registration"],
145
+ "connectors": ["sms.sendCode"]
146
+ }
147
+ }
148
+ ```
149
+
150
+ Ticket 模式:
151
+
152
+ ```json
153
+ {
154
+ "code": "public_score_lookup",
155
+ "name": "公开成绩查询",
156
+ "mode": "ticket",
157
+ "routeCode": "public.scoreLookup",
158
+ "pathPattern": "/view/:appType/public/score",
159
+ "externalRoleCodes": ["external_ticket_holder"],
160
+ "ticketConfig": { "ttlSeconds": 1800 },
161
+ "grants": {
162
+ "dataViews": ["public_score_lookup"]
163
+ }
164
+ }
165
+ ```
166
+
167
+ `grants.forms` 可以写本地 `formCode`,CLI 发布时会解析为真实 `formUuid`。
168
+
169
+ ## 3. Connector — `src/resources/connectors/<code>.json`
105
170
 
106
171
  ```json
107
172
  {
@@ -140,7 +205,7 @@ const data = await sdk.connector.call("crm.getCustomer", { body: { keyword } });
140
205
 
141
206
  不要把 `authConfig` 里的真实 secret 写进 manifest;用 placeholder,由平台管理员在后台覆盖。完整字段见 [`connector-resources.md`](connector-resources.md)。
142
207
 
143
- ## 2. Data View — `src/resources/data-views/<code>.json`
208
+ ## 4. Data View — `src/resources/data-views/<code>.json`
144
209
 
145
210
  选择规则:
146
211
 
@@ -488,11 +553,12 @@ export default async function (ctx) {
488
553
  { "fields": ["customerCode"], "unique": true },
489
554
  { "fields": ["status", "ownerDept"] }
490
555
  ],
491
- "dataManagement": { "enabled": true, "default": "list" },
492
- "publicAccess": { "enabled": false }
556
+ "dataManagement": { "enabled": true, "default": "list" }
493
557
  }
494
558
  ```
495
559
 
560
+ `publicAccess` 表单 setting 只用于旧 `sy-lowcode-view` 兼容。新 React SPA 公开页面必须使用 `src/resources/routes/` + `src/resources/public-access/` + `PublicAccessGate`。
561
+
496
562
  ## 12. Menu — `src/resources/menus/<code>.json`
497
563
 
498
564
  ```json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.86",
3
+ "version": "1.0.87",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {