Skip to content
This repository was archived by the owner on Oct 26, 2026. It is now read-only.

Commit 8b1f066

Browse files
refactor(types,components): retire the unimplemented async export-job path (objectui#10247) (#10264)
Fixes #10247 Clause-②: no ## What this does Retires the async export-job path on the objectui side, per ruling letter A on objectstack#17158 (director seat, batch #221 item 2; maintainer: 「同意」). The path is deleted, not kept alive with local copies of the spec's types. objectstack#17158 is the upstream this unblocks; it stays open and lands after this. - `@object-ui/components`: deletes `src/hooks/use-export-job.ts` (`useExportJob`, `UseExportJobOptions`, `UseExportJobReturn`) and `src/custom/export-progress-dialog.tsx` (`ExportProgressDialog`, `ExportProgressDialogProps`), with their barrel lines in `src/index.ts` (the two hook export statements) and `src/custom/index.ts` (one line, see the surface note below). - `@object-ui/types`: `src/data.ts` loses the optional `DataSource` members `createExportJob`, `getExportJobProgress`, `cancelExportJob` and `getExportJobDownloadUrl`; the types `ExportJobStatus`, `ExportJobFormat`, `CreateExportJobRequest`, `CreateExportJobResult` and `ExportJobProgressInfo`; and the spec imports behind them (`ExportJobStatus` and `ExportFormat` from `@objectstack/spec/api`, `CreateExportJobInput` and `CreateExportJobResult` from `@objectstack/spec/contracts`). `src/index.ts` drops the five re-exports. There was no zod mirror. The surviving `exportDownload` docblock no longer contrasts itself with the removed family. - Tests: the `ExportProgressDialog` case and its `job` fixture leave `displayLocale-9909.test.tsx`; the DebugPanel case stays. In `packages/types`, the three export-job rows in `page-nav-misc-spec-parity.test.ts` and the export-status covers row in `spec-derived-unions.test.ts` go with their types. The rows that pin surviving exports stay: `ImportRowResult` (`action` required), `ImportWriteMode`, `ImportJobStatus` and `ValidationError`. - `docs/ARCHITECTURE.md`: the compiled `MinimalDataSource` snippet's comment no longer lists an export job family among the optional `DataSource` members; it names `exportDownload` and the import-job family (round 2). - `.changeset/10247-retire-async-export-job-path.md`: `minor` for `@object-ui/types` and `@object-ui/components` (the repo's no-major convention), opening with a **BREAKING** banner. Out-of-repo implementers are NOT MEASURED, and the changeset says so. All four `DataSource` members go, not only the two the card names. The census pattern matches the `ExportJob` substring, so a zero requires `cancelExportJob` and `getExportJobDownloadUrl` to leave as well. They belong to the same family and `useExportJob` was their only reader. ## Surface note: one line outside the claimed file surface `packages/components/src/custom/index.ts` is not in the claim's file surface. It holds the only barrel line for the deleted dialog (`export * from './export-progress-dialog'`), so the component the card names cannot be deleted without it and still compile. The claim's surface was derived from the census, and the census pattern matches `ExportJob` tokens, not a module path, so it could not see this line. Before editing I re-read the fence over REST: 0 of the 12 open PRs touch that file. The release PR, objectui#5400, was paged in full: 1732 files, none under `src/`. The hunk is that one line. Round 2: the seat accepted this line and widened the surface by one comment line in `docs/ARCHITECTURE.md` (contract review `5816362049`). ## Premise checks - **Census, re-run.** At base `d7de5348` (origin/main had moved on from `6f96fca9` by the time the worktree was cut) it names the same 8 files the seat listed. The two `packages/types` spec-parity hits pinned the removed types, so their rows went. No assertion on a surviving export was removed. - **No `DataSource` implements the family.** The population is every non-markdown file under `packages/`, `apps/` and `examples/` that writes `implements DataSource`, `: DataSource =`, `as DataSource` or `satisfies DataSource`: 78 files at `d7de5348`. It covers the five implementing classes (`ApiDataSource` and `ValueDataSource` in core, `ObjectStackAdapter`, `MockDataSource` in runner, and the `RestDataSource` example) plus the test doubles. Files naming any of the four members: 1, `packages/types/src/data.ts`, which is the declaration. Lit control on the same population, the sync sibling `exportDownload`: 3 files (the `ObjectStackAdapter`, a `ListView` test double, the declaration). - **i18n.** The dialog and the hook made no translation calls (0 hits for `t(` / `useTranslation` / `useObjectTranslation` / `createSafeTranslation` in either file at base; the same pattern hits `RecordTitleChip.tsx`, `character-count.tsx` and others in the same directory). No key became orphaned and no locale file moves. ## Census with a lit control `git grep -l -E 'ExportJob|createExportJob|getExportJobProgress' REF -- packages apps ':!**/CHANGELOG.md'` | ref | files | |:--|:--| | base `d7de5348` | 8 | | main `4ab4f1ba` without this branch | 8 | | merged head `70770e74` (round 2, `origin/main` merged in, no rebase) | 0 | | control at `70770e74`, same roots and pathspec, `ImportJobStatus\|exportDownload` | 17 | **Ablation** (`scripts/ablation-replace.mjs` from the objectstack checkout, wrap mode, fix committed first, trap `git checkout HEAD -- ABS_PATH`). I re-planted `ExportJobStatus,` into the `packages/types/src/index.ts` re-export block (anchor 1 to 0, blob `0807e274` to `8794e110`). The census went red: 1 file, `packages/types/src/index.ts`. The restore was proven: blob after restore equals HEAD `0807e274`, and `git diff HEAD` is empty. The first attempt was a no-op that the tool refused, because the replacement still contained its anchor. The tool restored the file (blob equals HEAD) and the census did not run, so that attempt is not a measurement. ## Verification, all at HEAD `f618634c` - `pnpm turbo run type-check --filter=@object-ui/types --filter=@object-ui/components`: 10/10 tasks, exit 0. The test tsconfigs compile both parity tests and `displayLocale-9909.test.tsx`, counted with `--listFiles`. The first run caught a leftover `void` of the removed pin (TS2552), which the second commit fixes. - Consumers: `pnpm turbo run type-check` for `@object-ui/core`, `@object-ui/data-objectstack`, `@object-ui/runner`, `@object-ui/plugin-grid` and `@object-ui/plugin-list` (the in-repo `DataSource` implementers and the sync export path): 21/21 tasks, exit 0. - Reverse type probe against the rebuilt `dist` (a throwaway file in `plugin-grid`, deleted by trap): TS2724 for `ExportJobStatus`, TS2305 for `CreateExportJobRequest`, `useExportJob` and `ExportProgressDialog`, and TS2551 for `ds.createExportJob`. The control names `ImportJobStatus`, `ExportDownloadRequest`, `useIsMobile` and `ds.exportDownload` compiled. - From the repo root: `pnpm exec vitest run packages/types/` gave 213 files / 4916 tests passed. `pnpm exec vitest run packages/components/` gave 287 files / 2783 tests passed. The three touched test files, run verbosely, gave 3 files / 61 tests passed. - **The sync export still works** (grid CSV/Excel path): `plugin-grid` `exportGate.test.tsx`, `exportServer.test.tsx` and `ObjectGrid.exportOptionsKeys.test.ts`; `data-objectstack` `exportDownload.test.ts`; `plugin-list` `ListView.exportMatchesView.test.tsx`; `core` `export-filename.test.ts`. Result: 6 files / 55 tests passed. - Dist pins: `OBJECTUI_DIST_PINS=1 pnpm exec vitest run --project dist` gave 2 files / 8 tests passed. - Gates, all exit 0: `check:control-bytes`, `check:new-line-citations` (0 new), `check-changeset-presence.mjs`, `changeset:check` (fixed group, no major), `check:i18n-keys`, `check:i18n-drift` (0 en values changed), `check:i18n-dead-keys`, `check:pending-changeset-literals`, `check:changeset-claims`, `check:spec-symbols`, `check:unreferenced-sources`, `check:unused-deps`, `check:phantom-deps`, `check:side-effects-array`, `check:esm-specifiers`, `check:self-import`, `check:test-path-roots`, `check:component-surface-parity` (report-only), and `check-governed-queue-guard --test` (NOT GOVERNED, 10 paths). - `check:changeset-claims` pointed at four pending changesets that name a touched file (5213, 6051, 9309, i18nlabel-inverted-pin-5612). I read each paragraph against this diff and all four still hold: none cites a removed row or name. - Lint, narrowed: `eslint --format json` on the 7 changed ts/tsx files from their package directories (both packages lint with `eslint .` under the root flat config) found 7 files, 0 errors. The 27 warnings are all pre-existing `no-explicit-any` in `data.ts`, the same count as base `data.ts`. `--print-config` resolves a config for all 7 files with empty `parserOptions` (no `project` / `projectService`), and no enabled rule reads other files, so linting is not type-aware and this diff cannot move an untouched file's verdict. The only importers of the two deleted modules were in the linted set. ## Round 2 verification, all at HEAD `70770e74` - The changeset now states the real sequence: `@objectstack/spec` still exports the export-job contracts and `IExportService`, and objectstack#17158 (ruling A) retires them after this lands. The 「Why」 paragraph was re-tensed to match, and the import clause now names `@object-ui/types` / `@object-ui/components`. - `type-check` for types, components, core, data-objectstack, runner, plugin-grid and plugin-list: 23/23 tasks, exit 0. - From the repo root: types + components renderers/ui/notifications gave 332 files / 6050 tests passed; components `__tests__` gave 170 files (1 skipped) / 1656 tests (7 skipped). Sync export: 6 files / 55 passed. Dist pins: 2 / 8. - `check:doc-snippets`: 672 of 672 blocks judged, 0 failed. `check:readme-exports`: exit 0, 544 of 544 self-imports judged, all real. The remaining gates exit 0. ## NOT MEASURED - Type-check of the remaining consumers (app-shell, console, fields and the other plugins): not run locally. The census reads zero over `packages/` and `apps/`, so no file there spells a removed name. CI's Type Check runs all of them. - Out-of-repo `DataSource` implementers and importers: not measurable from here. ## Acceptance notes - The repo-root `ROADMAP.md` still names `ExportJobStatus` / `CreateExportJobRequest` in two table rows and in an unchecked item to integrate them for async streaming exports. It is outside the census roots and outside the claimed surface, so it is left as it is. Once objectstack#17158 lands, the protocol no longer carries what that item would integrate. Not filed. - The published `CHANGELOG.md` files keep their historical mentions. The census excludes them by design. - `origin/main` `4ab4f1ba` was merged into the branch as merge commit `70770e74` (no rebase). The census on the merged head is 0. - `docs/ARCHITECTURE.md` (Custom Data Source Interface, the compiled `MinimalDataSource` snippet): its comment listed the import/export job family among `DataSource`'s optional members. It now names `exportDownload` and the import-job family, which is what `DataSource` still declares: `createImportJob`, `getImportJobProgress`, `getImportJobResults`, `listImportJobs`, `cancelImportJob` and `undoImportJob`, all optional. It is one comment line; the seat widened the surface for it. <sub>Body refreshed by `domain:ui` seat #1 with the round-2 corrections the dev named · 2026-09-24T16:01Z</sub> --- _Generated by [Claude Code](https://claude.ai/code/session_01BA3nKVUwKQJf8DBxrSVtNC)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5ea623e commit 8b1f066

11 files changed

Lines changed: 72 additions & 698 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
'@object-ui/types': minor
3+
'@object-ui/components': minor
4+
---
5+
6+
**BREAKING: the unimplemented async export-job path is removed from `@object-ui/types` and `@object-ui/components`**
7+
8+
What left:
9+
10+
- `@object-ui/components`: the `useExportJob` hook with its `UseExportJobOptions`
11+
and `UseExportJobReturn` types, and the `ExportProgressDialog` component with
12+
its `ExportProgressDialogProps` type.
13+
- `@object-ui/types` (the root entry and the `./data` subpath): the optional
14+
`DataSource` members `createExportJob`, `getExportJobProgress`,
15+
`cancelExportJob` and `getExportJobDownloadUrl`, and the types
16+
`ExportJobStatus`, `ExportJobFormat`, `CreateExportJobRequest`,
17+
`CreateExportJobResult` and `ExportJobProgressInfo`. None of them had a zod
18+
mirror.
19+
20+
Why: ruling letter A on objectstack#17158 decided to retire the export-job API
21+
contract family from `@objectstack/spec`, because nothing serves it and
22+
`IExportService` has no provider. The ruling sequences the objectui side first:
23+
this change retires objectui's consumer side, rather than keeping it alive with
24+
local copies of the spec's types (objectui#10247). The spec-side retirement
25+
comes after this change; until it lands, `@objectstack/spec` still exports the
26+
export-job contracts.
27+
28+
No `DataSource` in this repository implemented any of the four methods. That
29+
was measured at `d7de5348` over every class that implements `DataSource` and
30+
every test double typed as one under `packages/`, `apps/` and `examples/`, with
31+
the synchronous `exportDownload` member as the control that did match. So
32+
`useExportJob` could only ever report `isSupported: false` here, and no runtime
33+
behaviour in this repository changes.
34+
35+
⚠️ Implementers and importers outside this repository are NOT MEASURED. Code
36+
that imports any name above from `@object-ui/types` or `@object-ui/components`
37+
no longer compiles, and a host `DataSource` that implements the four methods is
38+
no longer called by anything in objectui. There is no replacement API: nothing
39+
serves the spec's export-job contracts and `IExportService` has no provider;
40+
objectstack#17158 (ruling A) retires them from `@objectstack/spec` after this
41+
lands.
42+
43+
The synchronous export path is unchanged: `DataSource.exportDownload` and its
44+
`ExportDownloadRequest` (csv / json / xlsx), and the grid's client-side
45+
fallback.
46+
47+
Marked `minor`, not `major`, per the version-alignment convention in AGENTS.md;
48+
the break is real and is stated here.

‎docs/ARCHITECTURE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ type MinimalDataSource = Pick<
288288
>;
289289

290290
// And that those six SUFFICE. Every other member of `DataSource` — `searchAll`,
291-
// `bulk`, `getView`, `aggregate`, the import/export job family — is optional, so
291+
// `bulk`, `getView`, `aggregate`, `exportDownload`, the import-job family — is optional, so
292292
// a value with just the six is assignable to the whole interface. This line goes
293293
// red the moment a seventh member becomes required.
294294
declare const minimal: MinimalDataSource;

‎packages/components/src/__tests__/displayLocale-9909.test.tsx‎

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
*/
88

99
/**
10-
* The export dialog's record counts and the debug panel's event times read the
11-
* DECLARED session locale, never the machine's (objectui#9909).
10+
* The debug panel's event times read the DECLARED session locale, never the
11+
* machine's (objectui#9909).
1212
*
1313
* Each surface renders the same state twice — under a declared `de-DE` tenant
1414
* locale and a declared `en` one, the UI language `en` on both — and must read
1515
* differently: a literal expectation would measure the runner, on which a
1616
* broken surface and a repaired one print the same bytes. The runtime tripwire
1717
* then checks the argument every locale-taking call received.
18+
*
19+
* The export-progress dialog's record-count surface left this table with the
20+
* component itself: objectui#10247 retired the unimplemented async export path.
1821
*/
1922

2023
import { describe, it, expect, afterEach } from 'vitest';
@@ -23,9 +26,7 @@ import * as React from 'react';
2326
import { I18nProvider, LocalizationProvider } from '@object-ui/i18n';
2427
import { DebugCollector } from '@object-ui/core';
2528
import { isMachineLocale, recordLocaleArguments } from '@object-ui/test-support';
26-
import { ExportProgressDialog } from '../custom/export-progress-dialog';
2729
import { DebugPanel } from '../debug/DebugPanel';
28-
import type { UseExportJobReturn } from '../hooks/use-export-job';
2930

3031
afterEach(() => {
3132
cleanup();
@@ -48,18 +49,6 @@ function textUnder(locale: string, node: React.ReactNode, reveal?: () => void):
4849
return text.replace(/\s+/g, ' ').trim();
4950
}
5051

51-
const job: UseExportJobReturn = {
52-
isRunning: true,
53-
progress: { jobId: 'j1', status: 'processing', processedRecords: 12345, totalRecords: 67890 },
54-
error: null,
55-
isSupported: true,
56-
start: async () => 'j1',
57-
cancel: async () => {},
58-
getDownloadUrl: async () => null,
59-
download: async () => true,
60-
reset: () => {},
61-
};
62-
6352
/** 15:30:45 UTC — the suite runs in UTC; `de` is 24-hour, `en` is 12-hour. */
6453
const EVENT_AT = Date.UTC(2020, 2, 4, 15, 30, 45);
6554

@@ -83,12 +72,6 @@ interface Surface {
8372
}
8473

8574
const SURFACES: Surface[] = [
86-
{
87-
name: 'ExportProgressDialog — processed / total record counts',
88-
node: () => <ExportProgressDialog open onOpenChange={() => {}} job={job} />,
89-
de: /12\.345 \/ 67\.890 records/,
90-
en: /12,345 \/ 67,890 records/,
91-
},
9275
{
9376
name: 'DebugPanel — Events tab timestamp',
9477
node: () => {
@@ -101,7 +84,7 @@ const SURFACES: Surface[] = [
10184
},
10285
];
10386

104-
describe('component number and time faces follow the declared session locale (objectui#9909)', () => {
87+
describe('component time faces follow the declared session locale (objectui#9909)', () => {
10588
it.each(SURFACES)('$name — says the de-DE face under a de-DE session', ({ node, reveal, de }) => {
10689
const text = textUnder('de-DE', node(), reveal);
10790
expect(text, `got: ${text}`).toMatch(de);

‎packages/components/src/custom/export-progress-dialog.tsx‎

Lines changed: 0 additions & 220 deletions
This file was deleted.

‎packages/components/src/custom/index.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,3 @@ export * from './RecordTitleChip';
2525
export * from './refresh-indicator';
2626
export * from './view-states';
2727
export * from './mobile-dialog-content';
28-
export * from './export-progress-dialog';

0 commit comments

Comments
 (0)