Skip to content

docs(runner): 记录 api 查询参数这一真实的元数据加载配置面 (#3537) - #3581

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3537-runner-api-docs
Aug 7, 2026
Merged

docs(runner): 记录 api 查询参数这一真实的元数据加载配置面 (#3537)#3581
yinlianghui merged 1 commit into
mainfrom
claude/issue-3537-runner-api-docs

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#3537

纯文档单:runner 有一个真实可用的 API 基址配置面(URL 查询参数 api),但全仓文档零处记载 —— 在 #3533 / PR #3538 删掉那节「不存在的环境变量」之后,该页关于 API 基址的指引降为零。不涉及任何实现改动。

前提复核(rule 6:issue 正文是线索不是规格)

origin/main(b785a77b3)逐条复核,issue 的前提成立,行号也仍然准确:

  • packages/runner/src/App.tsx:44-57 —— const params = new URLSearchParams(window.location.search); const apiUrl = params.get('api');,有值 → new NetworkLoader(apiUrl),无值 → new LocalBundleLoader()
  • packages/runner/src/lib/MetadataLoader.ts:75-103 —— NetworkLoader,constructor(baseUrl: string = '/api'),取 ${this.baseUrl}/app.json${this.baseUrl}/pages${jsonPath}.json(path === '/' 先改写成 /index)。
  • PR docs: 删除 runner 不存在的环境变量配置面,修正前端示例的 process.env 读法 #3538 已落地(039d2d077),原 "Environment Variables" 一节确已删除。

改了什么

content/docs/utilities/runner.mdx —— 在 ## Configuration 下新增 ### Metadata Loading,放在 ### vite.config.ts之前(issue 的建议就是补在 Configuration 一节;而它是读者「我要把 runner 指向自己的后端」时第一眼扫的标题,排在 vite 配置前面比排在末尾更容易被找到)。内容:

  • 两种加载策略的分流表;params.get('api') 是真值判断,所以 ?api=(空值)仍然走本地加载器;控制台会打印命中了哪一种。
  • ?api= 走网络时后端要提供的四类请求(app.json + pages/index.json + pages/customers.json + pages/crm/accounts.json),嵌套路由直通。
  • 相对基址(同源)与绝对基址(需要后端开 CORS);fetch 无第二参数 ⇒ 不带 cookie / 自定义头,cookie 或 bearer 鉴权的后端直接用不了。
  • 失败静默:非 2xx 与网络/解析错误一律转成 null,页面显示 Page not found,app.json 失败则整个 app 外壳(头部/侧栏)消失,HTTP 状态码不进 UI。
  • 参数只在挂载时读一次;站内跳转 pushState 裸路径会把 ?api= 从地址栏抹掉(已另立单 runner 的站内导航把 ?api= 从地址栏抹掉:刷新/分享该 URL 会静默退回空的本地打包加载器 #3578)。
  • 缺省 LocalBundleLoader 的真实来源 src/app-data/(gitignore、新检出为空)与按序解析的文件顺序。

packages/runner/README.md —— 深度选择及理由:原 ## Schema Loading 一节讲的是 runner 并不具备的通用加载方式(await import('./my-schema.json') / fetch('/api/schema')),与本单要补的正是同一主题;若在它旁边另起一节,README 会自相矛盾(一节说「可以从各种地方加载」,紧邻一节说「只有两种,由查询参数决定」)。所以改写该节为 ## Metadata Loading,按 README 既有深度(每节 10–20 行 + 一个代码块 + 末尾指回文档)给出:分流表、后端要提供的请求清单、CORS/凭据/错误处理各一句,细节指回文档页的 #metadata-loading 锚点。README 里另外两处虚构能力(createRunner()runner.config.js)与本主题无关,未动,已另立单 #3576

实测(以及没有实测的部分)

这次没有在浏览器里跑通两种模式 —— 容器内没有安装 playwright 浏览器(~/.cache/ms-playwright 不存在),而且干净 worktree 里 runner 的 dev server 本身就因为别名缺口起不了页面(另立单 #3575)。按 #3524 的先例如实说明。以下是实际跑了的两项测量,文档里的 URL 形状与「缺目录时什么都加载不到」两条结论来自它们,不是读代码推断:

1. NetworkLoader 的请求 URL —— 用 esbuild 转译真实源文件packages/runner/src/lib/MetadataLoader.ts(与 Vite 相同的 TS→JS 步骤),桩掉 fetch 记录每一次请求:

--- explicit baseUrl: "https://backend.example.test/api" ---
loadAppConfig() -> https://backend.example.test/api/app.json
loadPage("/") -> https://backend.example.test/api/pages/index.json
loadPage("/customers") -> https://backend.example.test/api/pages/customers.json
loadPage("/crm/accounts")-> https://backend.example.test/api/pages/crm/accounts.json
--- default baseUrl (no argument) ---
/api/app.json , /api/pages/index.json
--- 404 handling (res.ok === false) ---
loadPage("/missing") -> null
--- network error handling (fetch throws) ---
loadAppConfig() -> null

2. LocalBundleLoader 的 glob 到底解析到什么 —— 起 runner 的 vite dev server(自选空闲端口 5387,用完按记下的 PID 收),直接取转译后的模块:

  • src/app-data/(= 仓库现状):

    appGlob=Object.assign({});pagesGlob=Object.assign({});rootGlob=Object.assign({});

    三个 glob 全空 ⇒ 每次加载都返回 null/ 落到内置的 No index page found.

  • 把一个 app.json + pages/index.json + pages/customers.json + pages/crm/accounts.json 的目录软链成 src/app-data/ 后重启:

    appGlob=Object.assign({"../app-data/app.json": ()=>import(...)});pagesGlob=Object.assign({"../app-data/pages/crm/accounts.json": ...,"../app-data/pages/customers.json": ...,"../app-data/pages/index.json": ...});

    即文档里写的键名与解析顺序确实是 Vite 编译期决定的。(该软链目录被 .gitignore 覆盖,git status 全程干净;测完已删除,dev server 已按 PID 停止,端口 5387 已释放。)

门禁(先预测后运行,均如预测)

命令预测实际
node scripts/check-doc-links.mjs0(新增内容不含站内链接)Links are valid across 3 scan roots. exit 0
pnpm exec vitest run scripts/ --maxWorkers=2(flock + 4G 堆上限)保持绿Test Files 16 passed (16) / Tests 275 passed (275)
node scripts/check-control-bytes.mjsOK✅ OK (scanned 3631 tracked text file(s));另自查 grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' 两文件均无命中

补充两项:

  • README 里的链接没有门禁覆盖,只能人工核 —— scripts/check-doc-links.mjsSCAN_ROOTScontent/docsexamples、根 README.md,packages/*/README.md 不在内。人工核了新增的那条 https://www.objectui.org/docs/utilities/runner#metadata-loading:页面文件 content/docs/utilities/runner.mdx 存在(路由与 package.jsonhomepage、README 底部 ## Links 一致),锚点来自本 PR 新增的 ### Metadata Loading 标题。(README 原有的 /docs/runner 那条是死链,不在本单范围,已另立单 packages/runner/README.md 记载了两个不存在的能力(createRunner() 程序化 API、runner.config.js),外加一条 404 的文档链接 #3576。)
  • MDX 能否解析:用仓库内的 @mdx-js/mdx@3.1.1 编译改后的 runner.mdx(去掉 frontmatter),compiled OK;新增内容里所有 < 都在行内代码或围栏代码里,不会被当作 JSX 标签。表格用 GFM 管道语法,与 content/docs 下已有的 43 个页面一致。

changeset:不加,依据如下

越界发现(全部另立单,本 PR 一处未改)

按 Prime Directive #10 逐条立单,均未指派:


🤖 Generated with Claude Code

https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt


Generated by Claude Code

runner 有一个真实可用的 API 基址配置面 —— URL 查询参数 `api` —— 但全仓
文档零处记载(#3533 删掉那节不存在的环境变量后,该页关于 API 基址的指引
降为零)。本 PR 只补文档,不动实现。
`content/docs/utilities/runner.mdx` —— `## Configuration` 下新增
`### Metadata Loading`:两种加载策略的分流表、`?api=<base>` 时后端需要提供
的四类请求(`app.json` + `pages{path}.json`)、相对/绝对基址与 CORS、
失败静默转 `null` 的表现、参数只在挂载时读取一次的注意事项,以及缺省
`LocalBundleLoader` 从 `src/app-data/`(gitignore、新检出为空)按序解析的
文件顺序。
`packages/runner/README.md` —— 原 `## Schema Loading` 一节讲的是 runner
并不具备的通用加载方式(`import('./my-schema.json')` / `fetch('/api/schema')`),
与本 PR 要补的正是同一主题;若在其旁另起一节,README 会自相矛盾。因此改写
该节为 `## Metadata Loading`,按 README 既有深度给出实测行为 + 指回文档页。
所有断言均对 origin/main 复核:分流见 `packages/runner/src/App.tsx:43-57`,
基址语义见 `packages/runner/src/lib/MetadataLoader.ts:75-103`。
Fixes#3537
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
@vercel

vercelBot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 7, 2026 2:18pm

Request Review

@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 7, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.1 KB350 KB
Entry fileindex-DpScGiC0.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.66KB3.13KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)7.57KB2.97KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)480.72KB105.64KB
core (index.js)2.96KB1.13KB
create-plugin (index.js)9.28KB2.98KB
data-objectstack (index.js)137.51KB35.11KB
fields (index.js)230.87KB56.83KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.65KB1.06KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)9.48KB3.27KB
i18n (useObjectLabel.js)26.14KB6.07KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.53KB10.71KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.05KB1.53KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)44.98KB12.37KB
plugin-charts (index.js)61.04KB17.31KB
plugin-chatbot (index.js)180.09KB42.72KB
plugin-dashboard (index.js)112.03KB28.88KB
plugin-designer (index.js)210.51KB42.51KB
plugin-detail (index.js)232.79KB57.42KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)112.10KB27.10KB
plugin-gantt (index.js)162.55KB39.57KB
plugin-grid (index.js)186.61KB49.34KB
plugin-kanban (index.js)48.30KB13.28KB
plugin-list (index.js)105.12KB25.48KB
plugin-map (index.js)16.81KB5.24KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.58KB10.58KB
plugin-timeline (index.js)25.76KB7.33KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)19.28KB6.38KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)2.46KB1.21KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)0.20KB0.18KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@yinlianghui
yinlianghui marked this pull request as ready for review August 7, 2026 14:20
@yinlianghui
yinlianghui added this pull request to the merge queueAug 7, 2026
Merged via the queue into main with commit 632c07cAug 7, 2026
7 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3537-runner-api-docs branch August 7, 2026 14:21
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 10, 2026
…ion (objectstack-ai#3577) (objectstack-ai#3616)
三类结构性虚构,均对 origin/main 逐条复核后处理。范围是整页 8 处锚点,
不是正文列的 3 处 —— 只修 Directory Structure 会让全页继续自相矛盾。
1. 幽灵目录。`packages/runner/src` 下实测只有 App.tsx / LayoutRenderer.tsx /
main.tsx / index.css / lib/ / 测试文件,没有 `schemas/`、没有 `components/`,
包根也没有 `public/`。按 objectstack-ai#3534/objectstack-ai#3539 先例(删手抄目录树,指真源)整块删掉
Directory Structure,换成一段实测过的 prose,并把承重信息落在唯一真实的
元数据目录 `src/app-data/` 上 —— 它由 `.gitignore` 排除、新检出下不存在,
布局与解析顺序由本页自己的 Metadata Loading 一节(objectstack-ai#3581 补)承接。
其余 5 处 `src/schemas/` 引用(Use Cases 两处、Add Custom Schemas、
Best Practices 目录树)一并按 Metadata Loading 的真实契约改写为
`src/app-data/pages/*.json`;页文档形状取 App.tsx 兜底页的
`{ type: 'page', title, body: [] }`,与本页 Metadata Loading 表格里
「the page document (PageNodeSchema)」一致。
2. 「内置示例 schema」。这个包一个 schema 文件都不带:承载它们的
`src/app-data/` 在 `packages/runner/.gitignore:1` 里,缺该目录时
LocalBundleLoader 三个 `import.meta.glob` 编译为 `{}`,`/` 渲染内置兜底
`No index page found.`。What's Included 下那节列七类「Runner 包含的示例
schema」整节改写为读者实际要做的事(往 `src/app-data/` 放 JSON,或用
`?api=` 指后端);下方 `## Example Schemas` 改题为 Schemas to Start From,
并说明这些例子活在文档里、不在包里。
3. Package Information。`Version: 0.3.1` 直接删除,不改成 17.3.0 ——
`@object-ui/runner` 在 `.changeset/config.json` 的 fixed 组里随 39 包同发,
手抄版本号必然再次漂移(分诊亦持此意见);当前版本改为指向 npm 页。
`Type: Application (not published to npm)` 与实测相反:package.json 是
`"private": false` + `publishConfig.access: "public"`,registry 上
`dist-tags.latest = 17.3.0`。改为不随版本漂移的措辞:已发布,但它是应用
不是库 —— package.json 不声明 main/module/exports/types,没有可 import 的
东西(与 PR objectstack-ai#3602 刚给 README 定下的说法一致)。
`src/components/` 保留一处 —— Add Custom Components 的 `// src/components/
MyComponent.tsx`。那是让读者自己建的文件(下方注册片段的相对 import 必须与它
对齐),已在上一句明写「包里不带组件,这个目录你自己加」,不再是「它存在」的
断言。
越界发现另行开单,不在本 PR 修:Features 的「All official plugins included」、
Best Practices 的环境变量小节(objectstack-ai#3538 删了 Environment Variables 整节却漏了它)、
Add Custom Routes 的 react-router-dom(runner 不依赖它,路由是手写
history.pushState)。objectstack-ai#3604 是 README 的另一件事,未触碰。
Fixesobjectstack-ai#3577
Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(runner): runner 真正的 API 基址配置面是 api 查询参数,但全仓文档零处记载

2 participants

@yinlianghui@claude