openxiangda 1.0.88 → 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 CHANGED
@@ -174,10 +174,12 @@ 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
 
181
+ 公开访问和测试脚本不能只判断 HTTP 状态。平台部分运行时接口可能返回 HTTP 200,同时在 JSON envelope 中返回业务错误码,例如 `code: "PUBLIC_GRANT_DENIED"`。只有 `code` 为 `200`、`"200"` 或兼容成功码 `0` 时才算成功;字符串错误码、`success: false` 或非 2xx HTTP 都必须当作失败。
182
+
181
183
  旧 `?publicAccess=guest` 和表单 `settings/forms/*.json` 里的 `publicAccess` 只用于旧 `sy-lowcode-view` 兼容。新 React SPA 应用不要再设计或生成这种链接。
182
184
 
183
185
  ```json
@@ -197,13 +199,23 @@ React SPA 新应用的无需登录访问统一使用 `/view/:appType/public/*`
197
199
  ```
198
200
 
199
201
  ```tsx
200
- import { PublicAccessGate } from "openxiangda/runtime/react"
201
-
202
- <PublicAccessGate policyCode="public_register" routeCode="public.register">
203
- <PublicRegisterPage />
204
- </PublicAccessGate>
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>
205
215
  ```
206
216
 
217
+ 不要把 `PublicAccessGate` 单独放在没有 `OpenXiangdaProvider` / `OpenXiangdaPageProvider` 的页面树下;否则 public session 不能注入后续 SDK 请求,`usePageSdk()` 也会抛出 `usePageSdkStore 必须在 PageProvider 内使用`。
218
+
207
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`,不需要刷新。
208
220
 
209
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` 并用 `PublicAccessGate` |
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,8 @@ 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
+ - ✅ 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`.
49
50
  - ✅ For form-entry UX, pick components in this order: OpenXiangda platform form components → `antd` / `antd-mobile` wrappers → custom component only when neither exists.
50
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.
51
52
  - ✅ Treat workflow forms as an exception. Ordinary ticket/order/task/asset lifecycles use status fields, state machines, action logs, permissions, and automations; workflows are for real approval tasks.
@@ -148,7 +149,8 @@ When the user provides a root domain such as `https://yida.wisejob.cn/`, use it
148
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.
149
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.
150
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.
151
- - 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
+ - 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.
152
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.
153
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.
154
156
  - Use `openxiangda app snapshot <APP_XXX> --profile <name> --json` for diagnosis before changing an existing app.
@@ -264,7 +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
+ - 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 内使用`.
268
270
  - Old `?publicAccess=guest` and form `publicAccess` settings are legacy compatibility and should not appear in new-app designs.
269
271
 
270
272
  ## Final Document Template
@@ -189,6 +189,8 @@ Requires Bearer token. Deletes legacy public/guest access config for the form.
189
189
 
190
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
191
 
192
+ Runtime APIs use a JSON envelope. Do not treat HTTP 200 alone as success: `code: "PUBLIC_GRANT_DENIED"` and any other string error code is a failure even when the HTTP status is 200. Validation scripts should require `code === 200`, `code === "200"`, or compatible success code `0`, and should also fail on `success: false`.
193
+
192
194
  ### GET `/apps/:appType/routes`
193
195
 
194
196
  Requires Bearer token. Lists route resources.
@@ -287,7 +289,7 @@ Body:
287
289
  }
288
290
  ```
289
291
 
290
- 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.
291
293
 
292
294
  Returns the normal guest token payload plus `extra.publicAccess`.
293
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 { PublicAccessGate } from "openxiangda/runtime/react";
149
+ import {
150
+ OpenXiangdaPageProvider,
151
+ OpenXiangdaProvider,
152
+ PublicAccessGate,
153
+ } from "openxiangda/runtime/react";
149
154
 
150
155
  export function PublicRegisterRoute() {
151
156
  return (
152
- <PublicAccessGate
153
- policyCode="public_register"
154
- routeCode="public.register"
155
- >
156
- <PublicRegisterPage />
157
- </PublicAccessGate>
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,9 @@ 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.
187
+
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`.
178
189
 
179
190
  Logout and current-user role switching:
180
191
 
@@ -119,13 +119,25 @@ await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
119
119
  React Router 中用 `PublicAccessGate` 创建 scoped public session:
120
120
 
121
121
  ```tsx
122
- import { PublicAccessGate } from "openxiangda/runtime/react";
122
+ import {
123
+ OpenXiangdaPageProvider,
124
+ OpenXiangdaProvider,
125
+ PublicAccessGate,
126
+ } from "openxiangda/runtime/react";
123
127
 
124
- <PublicAccessGate policyCode="public_register" routeCode="public.register">
125
- <PublicRegisterPage />
126
- </PublicAccessGate>
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
+
139
+ 公开访问验证必须检查 JSON envelope。HTTP 200 但 `code: "PUBLIC_GRANT_DENIED"` 代表后端已拒绝;只有 `code` 为 `200`、`"200"` 或兼容成功码 `0`,且没有 `success: false` 时才算成功。
140
+
129
141
  ## 2. Public Access Policy — `src/resources/public-access/<code>.json`
130
142
 
131
143
  公开策略声明外部角色和可访问资源。未显式 grant 的 form/dataView/function/connector 默认拒绝;grant 后仍受对应后端权限组控制。
@@ -559,7 +571,7 @@ export default async function (ctx) {
559
571
  }
560
572
  ```
561
573
 
562
- `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`。
563
575
 
564
576
  ## 12. Menu — `src/resources/menus/<code>.json`
565
577
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.88",
3
+ "version": "1.0.90",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -39151,6 +39151,11 @@ var joinUrl = (baseUrl, url2) => {
39151
39151
  if (/^https?:\/\//i.test(url2)) return url2;
39152
39152
  return `${trimTrailingSlash(baseUrl)}${url2.startsWith("/") ? url2 : `/${url2}`}`;
39153
39153
  };
39154
+ var isSuccessCode = (value) => {
39155
+ if (value === void 0 || value === null || value === "") return true;
39156
+ const code = Number(value);
39157
+ return Number.isFinite(code) ? code === 0 || code >= 200 && code < 300 : false;
39158
+ };
39154
39159
  var normalizeRuntimeFileUrl = (baseUrl, value) => {
39155
39160
  if (typeof value !== "string" || !value) return value;
39156
39161
  if (/^(https?:)?\/\//i.test(value) || /^(blob|data):/i.test(value)) return value;
@@ -39177,6 +39182,12 @@ var parseResponse = async (response) => {
39177
39182
  const message6 = typeof payload === "object" && payload ? payload.message || payload.error || response.statusText : response.statusText;
39178
39183
  throw new Error(message6 || "\u8BF7\u6C42\u5931\u8D25");
39179
39184
  }
39185
+ if (typeof payload === "object" && payload) {
39186
+ const hasCode = Object.prototype.hasOwnProperty.call(payload, "code");
39187
+ if (payload.success === false || hasCode && !isSuccessCode(payload.code)) {
39188
+ throw new Error(payload.message || payload.error || "\u8BF7\u6C42\u5931\u8D25");
39189
+ }
39190
+ }
39180
39191
  if (typeof payload === "object" && payload) {
39181
39192
  return payload;
39182
39193
  }
@@ -40920,14 +40931,14 @@ var TASK_STATUS_META = {
40920
40931
  init_cjs_shims();
40921
40932
  var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
40922
40933
  var isRuntimeEnvelope = (value) => !!value && typeof value === "object" && !Array.isArray(value) && (hasOwn(value, "code") || hasOwn(value, "success") || hasOwn(value, "data") || hasOwn(value, "result") || hasOwn(value, "message") || hasOwn(value, "error"));
40923
- var isSuccessCode = (code) => {
40934
+ var isSuccessCode2 = (code) => {
40924
40935
  if (code === void 0 || code === null || code === "") return true;
40925
40936
  const normalized = Number(code);
40926
40937
  return Number.isFinite(normalized) ? normalized === 0 || normalized === 200 : false;
40927
40938
  };
40928
40939
  var unwrapRuntimeResponse = (response) => {
40929
40940
  if (!isRuntimeEnvelope(response)) return response;
40930
- if (response.success === false || !isSuccessCode(response.code)) {
40941
+ if (response.success === false || !isSuccessCode2(response.code)) {
40931
40942
  throw new Error(response.message || response.error || "\u8BF7\u6C42\u5931\u8D25");
40932
40943
  }
40933
40944
  if (hasOwn(response, "data")) return response.data;