Skip to content

Commit 899056f

Browse files
committed
Merge origin/main into claude/project-thread-6qe56u (#25712)
Resolves packages/sdui-parser/package.json: main's publishing metadata (#26198, engines) and this branch's LICENSE-MIT `files` entry both kept. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6SEitNngAMugGbuJHWsDS
2 parents 930df7b + 81bba6c commit 899056f

383 files changed

Lines changed: 7330 additions & 4630 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@object-ui/components': patch
3+
'@object-ui/i18n': patch
4+
---
5+
6+
fix(components): a refused submit moves focus to the first invalid field and no longer toasts the field list over the dialog's title
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
- **Before.** A submit refused by field validation, on the client or by the server's `fields[]`, raised an error toast naming the fields ("Please check the highlighted fields: First name, Last name, Company…") on top of the message already written under each input. The toast cut its list after three names, and in a record create / edit dialog it was drawn over the title row.
12+
- **Now.** The form raises no toast for a refusal that every field carries inline. It scrolls to the first invalid field in form order and focuses it, and first activates that field's tab when it is on a background tab. The message under each input is the whole report.
13+
- **A field with nothing drawn to carry it.** When the server rejects a field that has no drawn input, for example one on a tab or section a `visibleWhen` predicate hides, the form shows the form-level banner and its toast with the server's sentence, the same path a rejection naming an unknown field already takes. The hidden tab is not activated.
14+
- **Earlier outcomes retire.** A refusal on the client now takes down the previous attempt's banner and toast, and a clear-on-hide notice, as an attempt that passes validation already did. Before, the refusal toast replaced them under the form's outcome id.
15+
- **`validation.formInvalid` removed.** The toast's sentence ("Please check the highlighted fields: {{fields}}") had no other reader, so it leaves the form's default map and all ten `@object-ui/i18n` locale packs. `validation.formInvalidJoiner` stays: the clear-on-hide notice, the faulted-`visibleWhen` refusal and the option-group hint still join field labels with it. A host bundle that overrides `validation.formInvalid` can drop the entry; nothing reads it.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
'@object-ui/react': patch
4+
'@object-ui/plugin-detail': patch
5+
---
6+
7+
fix(app-shell,react,plugin-detail): on a record under approval, an administrator who is not the approver sees one status line and one override menu instead of five buttons above the title, and Recall is drawn once
8+
9+
Clause-②: yes (widening)
10+
Metadata-protocol: none
11+
12+
- **`@object-ui/app-shell`:** for a viewer who holds no approver slot but may override, the record page's approval bar is now one line: the request's pending status and who the step waits on, the levers that have no override arm (Reply) as buttons, and one marked menu holding every lever the override flag admits (Override Approve, Override Reject, Override Reassign, and Recall). The approver's own bar is unchanged. Who may override, the override notice each lever shows, and the request each lever sends are unchanged. `DeclaredActionsBar` takes a new optional `foldOverrides` prop for this; a host that does not pass it renders as before.
13+
- **`@object-ui/react`:** `InlineEditProvider` and the `InlineEditContext` value gain an optional `approvalRecallDrawnByHost`. It is optional so every existing host keeps its behaviour: absent means `false`, and then the approval band draws its own Recall exactly as before. A host that draws the pending request's declared Recall itself sets it to `true`.
14+
- **`@object-ui/plugin-detail`:** the DetailView approval band leaves out its Recall button when the host says it draws one, and keeps its lock badge and tally. The record page sets the signal only while its approval bar actually draws the request's declared Recall, so Recall appears once on the page; before the bar can draw it (definition still loading, or a backend that sends no viewer block) the band keeps its own.
15+
16+
What to do: nothing.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
'@object-ui/console': patch
4+
'@object-ui/i18n': patch
5+
---
6+
7+
fix(app-shell,console): an invitee who opens the invitation link signed out is greeted for the invitation, offered "Create an account and join" first, and the accept page names the inviter
8+
9+
Clause-②: yes
10+
Metadata-protocol: none
11+
12+
- **Login page.** A signed-out visitor arriving at `/login?redirect=/accept-invitation/ID` used to see the returning-user card ("Welcome back · Sign in to continue your work") with a small "Sign up" link under the form. Both login pages (the console's own and `DefaultLoginPage`) now title the card "Accept your invitation · Use the email address the invitation was sent to." Where the server offers sign-up to this visitor, a full-width "Create an account and join" link (the new `InvitationSignUpPrompt` export) sits above the sign-in form in place of the small link. With sign-up switched off, the visitor gets the invitation header and the sign-in form only.
13+
- **Register page.** From an invitation redirect, both register pages title the form "Create an account to join" and ask for the address the invitation was sent to, because only that account can accept it.
14+
- **Accept page.** `DefaultAcceptInvitationPage` shows an "Invited by" row with the inviting member's email, which `GET /organization/get-invitation` already returns as `inviterEmail`. That route returns no inviter name.
15+
- **Not in this change.** The signed-out pages name no organization, inviter or invited address, and do not prefill the email. The only invitation read the server serves answers a signed-out caller `401`, so a preview for signed-out visitors needs a new server read first.
16+
- New locale keys in all ten packs: `auth.login.invitationTitle`, `auth.login.invitationDescription`, `auth.login.invitationSignUpButton`, `auth.login.invitationSignInDivider`, `auth.register.invitationTitle`, `auth.register.invitationDescription`, `organization.accept.invitedBy`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@object-ui/plugin-map': patch
3+
'@object-ui/i18n': patch
4+
---
5+
6+
fix(plugin-map): a map whose style or tiles fail to load shows the record list with a translated notice, instead of a grey canvas under an English alert
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
- **`@object-ui/plugin-map`:** when MapLibre reports a style or tile load failure (an intranet or proxied deployment that cannot reach the tile host, an unreachable style URL), the map view now removes the map and lists its records in its place, the same list a browser without WebGL2 already got: searchable, and each row opens the record the way its marker did. A "Try the map again" button brings the map back. The notice above the list keeps MapLibre's reason and names a remedy that exists: a view with its own map style is told to check that URL, and a view on the public default style is told to ask an administrator to set a map style for the view. It no longer says the markers are "listed in the search box" or asks for a "custom map style for production use" setting that does not exist. That notice, the WebGL2 notice, the list's label and empty text, and the "records excluded for missing or invalid coordinates" count now read the translation bundle, so a zh-CN console shows them in Chinese.
12+
- **`@object-ui/i18n`:** eight new `element.map.*` keys in all ten packs.
13+
14+
What to do: nothing. A deployment-wide map style setting is not part of this change.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
'@object-ui/i18n': patch
3+
---
4+
5+
chore(i18n): delete 92 message keys nothing reads from all ten locale packs
6+
7+
Clause-②: yes (TranslationKeys narrows by 92 unread members; patch per the #4730 retirement precedent)
8+
Metadata-protocol: none
9+
10+
`ui/scripts/check-i18n-dead-keys.mjs` listed 122 keys with no call site and no textual occurrence anywhere in the repository. 92 of them are deleted from `ar`, `de`, `en`, `es`, `fr`, `ja`, `ko`, `pt`, `ru` and `zh`; no key is renamed or added, and no screen changes, because no code asked for any of them. The largest groups are `appDesigner.*` (20 keys), `report.*` (9), `publicForm.*` (8), `table.*` (7) and `layout.appSwitcher.*` (7).
11+
12+
Two groups the script also listed stay:
13+
14+
- 28 `_one` / `_other` plural forms (`preview.changes.typeCount.*`, `notifications.arrivalMany` / `arrivalRepeats`, `fields.relativeDate.overdue`). Their base keys are called with `count`, and i18next reads the plural form, so they are in use.
15+
- `console.ai.agentLabels.dataChat` and `metadataAssistant`, which the pack keeps on purpose for external overrides.
16+
17+
`TranslationKeys` (`typeof en`) and the other pack objects' types lose the 92 members. A host that reads one of them by property gets a type error; nothing in this repository does, and no `t()` call anywhere asks for one.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/core': patch
3+
'@object-ui/plugin-form': patch
4+
'@object-ui/plugin-grid': patch
5+
---
6+
7+
feat(ui): an edit form's `state_machine` select offers only the moves the server accepts
8+
9+
Clause-②: yes
10+
Metadata-protocol: none
11+
12+
A record whose `status` is governed by an error-severity `state_machine` validation used to offer every option in the edit form, and the server refused the invalid ones only after submit, without naming the allowed next states. The form now offers the persisted value plus the states the machine declares as its next moves.
13+
14+
- **`@object-ui/core`:** new export `stateMachineNextValues(objectSchema, fieldName, currentValue)`. It returns the set of values a field may move to from its persisted value, or `null` for "don't constrain". It narrows only where the server refuses: rules with `severity: 'error'` (the default), `active` not `false`, and `events` covering `update` (the default covers it). A from-state the transition map does not declare stays unconstrained, and several applicable rules on one field intersect. It is a read of the declared transition map for choice controls, not a client-side rule engine.
15+
- **`@object-ui/plugin-form`:** `gateFormFields` takes an optional `previousValues` (the persisted record) and narrows each single-value select governed by such a machine, on both the entry's own `options` and its `field.options`. Every layout passes its persisted record: the simple, modal, drawer, tabbed, split and wizard forms. The from-state is the stored row, never the live form value. A create form is unconstrained, and the current value always stays offered. Options outside the reachable set are left out rather than drawn disabled.
16+
- **`@object-ui/plugin-grid`:** `stateMachineNextValues` is now re-exported from `@object-ui/core`. The grid's inline editor therefore stops narrowing on a `warning` / `info` machine, an inactive one, or one whose `events` leave out `update`. The server never refuses those moves, so the editor now offers every option for them.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@objectstack/types': patch
3+
'@objectstack/runtime': patch
4+
---
5+
6+
fix(runtime,types)!: a NOT NULL refusal on a column no field declares answers `RestServer`'s `400 VALIDATION_FAILED` body at the dispatcher `/data` and actions doors too
7+
8+
Since #24768 the engine refuses a NOT NULL violation on a field the object declares as its own `ValidationError`, which every door answers alike. A column no field declares (drift: the field left the metadata and its NOT NULL column stayed in the table) still leaves the engine as the driver threw it, and the doors answered that refusal three ways. `RestServer`'s `POST /data/:object` answered `mapDataError`'s NOT NULL arm: `400 VALIDATION_FAILED`, the column's sentence, its `required` field entry and the drift `hint`. The runtime dispatcher's `POST /data/:object` let it reach the Hono exits, which answered `500 INTERNAL_ERROR`. The actions door answered `400 VALIDATION_ERROR` with the driver's text (the physical table and column) as the message and the driver's code as `declaredCode`.
9+
10+
Clause-②: yes (widening: `@objectstack/types` adds the export `driverNotNullRefusalAnswer`)
11+
Metadata-protocol: none
12+
13+
<!-- adr-0087: not-required (no-migration-prescription) No metadata moves: no spec key, authorable spelling, object definition, stored row or stored shape is added, removed, renamed or re-shaped, and no exported declaration is removed or narrowed, so there is nothing for `objectstack migrate meta` to rewrite. What changes is the status, code and body two HTTP doors answer for one refusal, a driver NOT NULL refusal on an undeclared column: every write that was refused is still refused and every write that was served is still served. The remedy is on the consumer's side, reading `code` and `details`; never a rewrite of a package source or a stored row. The other categories are closed on facts: both packages publish (not unpublished); no ADR-0087 id is named or touched (not registered or already-registered); and nothing exported is removed or narrowed (not runtime-interface-only, type-surface-only or runtime-export-retired). -->
14+
15+
**BREAKING** (a wire-answer change), shipped as `patch`: no metadata protocol kind moves.
16+
17+
- **`@objectstack/types`.** New export `driverNotNullRefusalAnswer(error, object?)`: `mapDataError`'s NOT NULL arm answer (`{ status, body }`) when classification answers the error with that arm, `undefined` for every other answer. Every arm ahead of it (a declared status, a sandboxed body's throw, a unique violation, an unknown column, the record validator's `ValidationError`) still decides first. `mapDataError`'s own answers are unchanged.
18+
- **`@objectstack/runtime`.** The dispatcher's `/data/:object` routes answer that refusal themselves with `400`, `error.code: 'VALIDATION_FAILED'`, the column's sentence as `error.message`, and `fields`, `hint` and `object` in `error.details` (was a thrown `500 INTERNAL_ERROR`). The actions door answers the same body (was `400 VALIDATION_ERROR` with the driver's text and `declaredCode`). The driver's text and code no longer reach either wire.
19+
- A `PATCH` cannot reach such a column: naming it is refused before the driver as an undeclared field (`400 INVALID_FIELD`), on both `/data` doors alike, as before.
20+
- The answers for a field the object declares are unchanged.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
'@objectstack/account': patch
3+
'@objectstack/cli': patch
4+
'@objectstack/client': patch
5+
'@objectstack/client-react': patch
6+
'@objectstack/cloud-connection': patch
7+
'@objectstack/connector-imap': patch
8+
'@objectstack/connector-mcp': patch
9+
'@objectstack/connector-openapi': patch
10+
'@objectstack/connector-rest': patch
11+
'@objectstack/connector-slack': patch
12+
'@objectstack/console': patch
13+
'@objectstack/core': patch
14+
'@objectstack/driver-memory': patch
15+
'@objectstack/driver-mongodb': patch
16+
'@objectstack/driver-sql': patch
17+
'@objectstack/driver-sqlite-wasm': patch
18+
'@objectstack/driver-turso': patch
19+
'@objectstack/embedder-openai': patch
20+
'@objectstack/formula': patch
21+
'@objectstack/hono': patch
22+
'@objectstack/knowledge-memory': patch
23+
'@objectstack/knowledge-ragflow': patch
24+
'@objectstack/lint': patch
25+
'@objectstack/mcp': patch
26+
'@objectstack/metadata': patch
27+
'@objectstack/metadata-core': patch
28+
'@objectstack/metadata-fs': patch
29+
'@objectstack/metadata-protocol': patch
30+
'@objectstack/objectql': patch
31+
'@objectstack/observability': patch
32+
'@objectstack/organizations': patch
33+
'@objectstack/platform-objects': patch
34+
'@objectstack/plugin-approvals': patch
35+
'@objectstack/plugin-audit': patch
36+
'@objectstack/plugin-auth': patch
37+
'@objectstack/plugin-dev': patch
38+
'@objectstack/plugin-email': patch
39+
'@objectstack/plugin-hono-server': patch
40+
'@objectstack/plugin-pinyin-search': patch
41+
'@objectstack/plugin-security': patch
42+
'@objectstack/plugin-sharing': patch
43+
'@objectstack/plugin-webhooks': patch
44+
'@objectstack/rest': patch
45+
'@objectstack/runtime': patch
46+
'@objectstack/sdui-parser': patch
47+
'@objectstack/service-analytics': patch
48+
'@objectstack/service-automation': patch
49+
'@objectstack/service-cache': patch
50+
'@objectstack/service-cluster': patch
51+
'@objectstack/service-cluster-redis': patch
52+
'@objectstack/service-datasource': patch
53+
'@objectstack/service-i18n': patch
54+
'@objectstack/service-job': patch
55+
'@objectstack/service-knowledge': patch
56+
'@objectstack/service-mailbox': patch
57+
'@objectstack/service-messaging': patch
58+
'@objectstack/service-package': patch
59+
'@objectstack/service-print': patch
60+
'@objectstack/service-queue': patch
61+
'@objectstack/service-realtime': patch
62+
'@objectstack/service-settings': patch
63+
'@objectstack/service-sms': patch
64+
'@objectstack/service-storage': patch
65+
'@objectstack/setup': patch
66+
'@objectstack/skills': patch
67+
'@objectstack/spec': patch
68+
'@objectstack/studio': patch
69+
'@objectstack/trigger-api': patch
70+
'@objectstack/trigger-record-change': patch
71+
'@objectstack/trigger-schedule': patch
72+
'@objectstack/types': patch
73+
'@objectstack/verify': patch
74+
'create-objectstack': patch---
75+
76+
chore(packages): publishing metadata — per-format types in `exports`, declared `sideEffects`, and a README for the 18 published packages without one
77+
78+
Clause-②: no
79+
Metadata-protocol: none
80+
81+
Measured on a fresh `origin/main` build of all 73 published packages outside `ui/`, each staged as `npm pack` would ship it, with publint 0.3.25 and @arethetypeswrong/cli 0.18.5. Before: 73 of 73 packages carried at least one publint message and 48 carried an attw problem. After: 3 packages carry a publint message and 16 carry an attw problem, each remaining class needing a change this one deliberately does not make — an export-map shape change, or a dual-build fix in `@objectstack/core`.
82+
83+
- **Types per module format.** On 38 manifests one `types` entry served both formats, so a TypeScript consumer importing the ESM build was handed the CJS declarations — every one of attw's 38 `FalseCJS`. Each `{types, import, require}` entry becomes `{import: {types, default}, require: {types, default}}` pointing at the declaration file the same tsup run already emits for that format. No subpath is added or removed, and no JavaScript target moves. `@objectstack/core` keeps its single `types` entry: its `.d.ts` and `.d.cts` declare the same classes with private members, so serving them per format gives a consumer that reaches `core` through both resolution modes two incompatible `ObjectKernel` types, which is `@objectstack/plugin-dev`'s declaration build (it awaits `import('@objectstack/objectql')` inside a CommonJS build). Its `FalseESM` therefore stays, measured and unfixed here.
84+
- **`sideEffects` on the 72 manifests that declared none**, read per package rather than set in bulk: `@objectstack/service-cluster-redis` registers its `redis` cluster driver at module load and `create-objectstack`'s bin reaches its program through a bare import, so both declare their entry files side-effectful; everything else is `false`.
85+
- **`publishConfig: { access: 'public' }`** on the 17 that had none, the value the other 56 already declare.
86+
- **`type`** on the 39 that shipped `.js` without declaring a format — every `.js` under their `dist/` was read first and is CommonJS, which is what the absent field already meant — **`engines.node >= 22.0.0`** on the 22 that had no `engines`, and **`repository.url`** as the full `git+https://` git URL on 71.
87+
- **A README for 18 published packages that had none**: one paragraph, the first import a reader writes, and a link to the package's docs page. They are the pages npm renders, and for these 18 npm rendered nothing.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@object-ui/console': patch
3+
---
4+
5+
fix(console): the console's build-identity define no longer leaks into the other ui test projects
6+
7+
Clause-②: no (build/test configuration only; no exported type or runtime contract change; the console production build keeps its version stamp)
8+
Metadata-protocol: none
9+
10+
The console's Vite config bakes `import.meta.env.VITE_APP_VERSION` (the build's version, else the git short sha) as a `define`. The console's vitest project merges that config, and vitest moves every `import.meta.env.*` / `process.env.*` define into the main process's `process.env` while it resolves a project's config, so every other ui test project's workers inherited the console's git sha. App-shell's `getConsoleBuild()` then read that sha instead of `null`, and `buildIdentity-12970`'s "reads null" case went red in full ui runs. The console's vitest config now drops those keys from the merged Vite config. `vite build` still bakes the version exactly as before.

0 commit comments

Comments
 (0)