Skip to content

fix(plugin-grid): type ObjectGrid's column emit against the TableColumn[] slot it fills - #6461

Merged
os-support-ai merged 2 commits into
mainfrom
claude/issue-6004-generatecolumns-typed
Aug 26, 2026
Merged

fix(plugin-grid): type ObjectGrid's column emit against the TableColumn[] slot it fills#6461
os-support-ai merged 2 commits into
mainfrom
claude/issue-6004-generatecolumns-typed

Conversation

@claude

@claudeclaudeBot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Fixes#6004

Verified at 356d0d93a (the final commit; every gate below was run on that tree).

The finding this PR paid for

The obvious remedy is inert, and at this seam it is more inert than at #6373's. Measured on this program before choosing a shape, each leg restored byte-identically afterwards:

proberesult
generateColumns(): TableColumn[], nothing else changedtsc --noEmitexit 0, zero diagnostics
same, plus an undeclared key written out longhand in the emit literalexit 0, zero diagnostics
same, plus a wrong-typed declared key (sortable: 'NOT_A_BOOLEAN')exit 0, zero diagnostics

#6373 found that spread properties escape excess-property checking. Here freshness is gone entirely: every emit literal is a .map() callback's return value, so it is inferred into the callback's return type first and reaches the annotation as a non-fresh X[]. Written-out keys escape too.

⭐ The greens above are real inertness, not a dead compiler: the control probe (return 'DEFINITELY_NOT_AN_ARRAY' inside the same annotated function) raised TS2322, so the annotation was being honoured.

And underneath that, the reason no annotation could bite at all

objectSchema is useState<any> (:692), so the field type read off it is any — and an any spread into an object literal collapses the entire literal to any, silently un-checking every other key in it. That is why the third probe stayed green on a declared key. Measured directly: with the return annotated but the locals untouched, path A's emit expression is any[].

So the fix has three parts, and the first is load-bearing rather than cosmetic:

  1. Name the four inference locals (baseInferredType, inferredType, resolvedType ×2, plus fieldType) so any stops at that boundary.
  2. Tombstones, derived& { [K in Exclude<keyof ListColumn, keyof TableColumn | 'wrap' | 'pinned'>]?: never }. Derived from the authored input type, never hand-listed, so a key added to the spec's ListColumn tomorrow is refused by default. Tombstones bite by assignability, which never depended on freshness.
  3. Every any cast at the call sites gone.

The census was wider than the card's

The card named three call sites. There are fiveanys defeating the emit type:

sitewhat it was
:2108:2176:2227the three the card named
:3398a fourth — the mobile card-view filter((c: any) => …)
generatedColumns: any[]a fifth, insidegenerateColumns(); it left the schema-derived emit path unchecked even after the return was annotated

Adjudication — every key, with the read-count behind it

Read sets measured from source, comments stripped. Two consumers, because the array is read twice before it reaches the slot.

keyreadsverdict
headerIcondata-table.tsx ×2 (renders it into the header cell)HELD — live. Whether TableColumn should declare it is #6424's call; declared at the seam meanwhile so the hold is visible instead of anonymous.
pinnedObjectGrid.tsx ×5 (the left/right reorder + the frozen-column verdict); data-table ×0HELD — live, and consumed before the slot: the reorder re-expresses it as the sticky classNamedata-table actually reads.
wrap0 anywhereHELD, deliberately not retired. This card's rule would retire it, but #5453 owns that key and is pm:blocked on #5415, whose outcome decides implement-vs-remove. Retiring it here would settle a blocked card from outside its own thread. Byte-for-byte unchanged.
options0data-table has no column-level options read; its select/boolean editors come from the host via renderCellEditor, and this component's renderCellEditor rebuilds the field from objectSchema.fields[accessorKey], not from the columnRETIRED
typeliveNOT MINE#5853's; its fold stands unchanged
nameNOT MINE#5120's, and not emitted by this producer at all

Second road proven before retiring options (the check is part of the rule, not an aside): cell renderers read translated options off the fieldMeta built inside generateColumns(), and the inline editor reads them off the object schema. Neither ever consulted col.options. No rendering change.

⚠️ Overlap reported, not folded

Census correction to the card

The card's suggested key list named essential. It is not on the emit surface at all: it is read off the authored column and turned into a className, and it is not a ListColumn member. Recorded on #6458.

Review items from the second pass

1. Null guards restored (356d0d93a)

The first pass narrowed away if (!col || …) in the enrichment map and the fold, reasoning the emit is now typed non-nullable. Put back, with a comment naming why they survive a non-nullable type — otherwise the next reader correctly identifies them as unreachable-by-type and deletes them, losing the protection a second time for a good reason.

The argument is this PR's own census: five separate any leaks defeated this boundary, one of them inside generateColumns() itself, where it left a whole emit path unchecked even after the return was annotated. Each was invisible until measured. Defence in depth behind the typing — the tombstones and the removed casts still stand.

Verified the guards are not stripped. TypeScript narrows col to never in those branches, which is exactly the condition under which one might expect a bundler to drop them. Checked in the built artifact:

// packages/plugin-grid/dist/index.jsif(!e||e.accessorKey==="_actions")returne;// enrichment mapif(!e)returne;// fold pass

Both present. A guard the bundler deletes would be no guard at all.

2. Renamed off an exported-name collision (356d0d93a)

GridColumn collided with the pre-existing packages/fields/src/widgets/GridField.tsx:82, failing scripts/__tests__/one-authority-per-exported-name-6273.test.ts. The two are genuinely different shapes — a fields-widget column config vs this producer's emit type — so they are renamed apart rather than re-pointed at one authority:

beforeafter
GridColumnObjectGridColumn
GridColumnDraftObjectGridColumnDraft
GridColumnHoldsObjectGridColumnHolds

Matching this file's own precedent, ObjectGridColumnState (:257), rather than the aliased-import pattern the gate cites generically. RetiredListColumnKey is unique and keeps its name — it describes ListColumn's keys, so an ObjectGrid prefix would misname it.

KNOWN_COLLISIONS is untouched. It is a shrink-only baseline, so the entry the failure message offers would have weakened the gate rather than satisfied it. scripts/ carries no diff in this PR (git diff --quiet <base> -- scripts/ → clean).

Tests — the defect is type-level, so the pins are compile-time

packages/plugin-grid/src/__tests__/columnEmitBoundary-6004.test.ts. A test that merely renders the grid is blind to this: it stays green with the whole emit type deleted.

Coverage measured, not assumedtsconfig.json excludes **/__tests__/**, so only the test project checks this file:

tsc -p tsconfig.test.json --noEmit --listFiles → 1751 inputs, including
src/__tests__/columnEmitBoundary-6004.test.ts
src/ObjectGrid.tsx

Each @ts-expect-error is written to be refused for exactly one reason — a directive refused for two pins neither, because it stays "used" when one is deleted (#6373's lesson). Where freshness would be a second reason, the fixture is routed through a non-fresh value first, which is also how the real emit reaches the type.

Ablation — tombstone deleted from both emit types, re-run on the final tree:

ON-DISK CHECK: tombstone lines before=2 after=0
ablated blob=35835c37… head blob=4116bcfb…
ABLATED_TSC_TEST_EXIT=2
columnEmitBoundary-6004.test.ts(105,5): error TS2578: Unused '@ts-expect-error' directive.
columnEmitBoundary-6004.test.ts(116,5): error TS2578: Unused '@ts-expect-error' directive.
columnEmitBoundary-6004.test.ts(130,58): error TS2339: Property 'field' does not exist on type 'ObjectGridColumnDraft'.
… (link / action / prefix / hidden)
RESTORED byte-identical: 4116bcfbf4b97c7a79a9c6f4a9a42fde6e653ffc

Predicted before running, and the isolation held: the options pin and the type-fold pin stayed green, proving they are refused by their own independent machinery rather than riding on the tombstone.

Forward reverse-verification — all five emit paths bite (predicted red before each run; every leg confirmed on disk and restored byte-identically):

legmutationresult
1wrong-typed declared key in path ATS2322 naming sortable
2tombstoned key via spread in path ATS2322 naming summary
3tombstoned key written out in path BTS2322 naming label
4tombstoned key in path C (inline data)TS2322 naming link
5tombstoned key in path D (schema-derived push)TS2322 Type 'true' is not assignable to type 'undefined'

The test also pins the two mechanisms as executable claims, since nothing else in the repo states them: that an any in a conditional spread collapses the literal, and that a bare TableColumn[] annotation accepts the undeclared key. If TypeScript tightens either, these go red and the docblock gets re-measured — a useful red.

Gates run (all on 356d0d93a)

gateresult
pnpm --filter @object-ui/plugin-grid type-check (tsc --noEmit && tsc -p tsconfig.test.json)exit 0
pnpm exec vitest run packages/plugin-grid/ scripts/__tests__/one-authority-per-exported-name-6273.test.tsTest Files 93 passed (93) · Tests 872 passed (872)
the collision gate alone11/11 passed
node scripts/check-changeset-presence.mjs✅ 1 changeset declared
pnpm --filter @object-ui/plugin-grid lint0 errors, 679 warnings (680 before this change — the removed any casts)
downstream type-checkapp-shell, plugin-view, plugin-report, plugin-designer (downstream/prefix direction)all Done, exit 0
control-byte scan over all changed filesno matches

Repo-wide lint is CI's run, not attempted here. The narrowing is measured: eslint's population for this package is 129 files (from its own config, counted via --format json), my diff touches 3 files all inside it, and eslint.config.js sets no parserOptions.project / projectServicetype-aware linting is not enabled, so my diff cannot move the verdict of any file it does not contain.

Out-of-scope findings filed (unassigned, not fixed here)


Generated by Claude Code


Generated by Claude Code

…mn[] slot it fills
`generateColumns()` had no return annotation and every call site cast to `any`,
so nothing checked what this producer wrote into
`DataTableSchema.columns: TableColumn[]`.
Annotating it would have changed nothing, and that measurement is the substance
of this change. On this program `generateColumns(): TableColumn[]` raises ZERO
diagnostics — the emit literals reach the annotation through `.map()`, which
strips the freshness excess-property checking depends on, so even an undeclared
key written out longhand is accepted. objectui#6373 found spreads exempt at its
seam; here freshness is gone entirely.
Underneath that sat the reason no annotation could bite: `objectSchema` is
`useState<any>`, and an `any` spread into an object literal collapses the WHOLE
literal to `any`. Naming the four inference locals stops it at that boundary.
The emit type then carries ADR-0049 `?: never` tombstones DERIVED from
`keyof ListColumn` — never hand-listed — so a future spec key is refused by
default and has to be adjudicated to escape. Tombstones bite by assignability,
which never depended on freshness.
Casts dropped at all four call sites (the card's census named three) plus a
fifth inside the producer, `const generatedColumns: any[]`, which had left one
emit path unchecked even after the return was annotated.
Verdicts: `headerIcon` and `pinned` are HELD — both have measured live readers
(`data-table`'s header cell; this file's own pin-reorder pass) — and are now
declared at the seam instead of arriving anonymously. `wrap` is HELD too and
deliberately NOT retired: nothing reads it, but objectui#5453 owns that key and
is blocked on objectui#5415. `options` is RETIRED: no reader on either side of
the seam, and every value it carried still reaches its consumer through the
field metadata the cell closure captures and the object schema the inline
editor reads. `type` stays objectui#5853's; `name` is not emitted here.
No rendering change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3233.7 KB3266.6 KB
Main entry chunk (gzip)157.4 KB350 KB
Entry fileindex-C8utwOhB.js
StatusPASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)11.30KB4.28KB
app-shell (runtime-config.js)18.10KB6.51KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.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)505.99KB114.64KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)173.10KB47.96KB
fields (index.js)238.89KB60.02KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.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.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.66KB12.84KB
plugin-charts (index.js)64.66KB18.32KB
plugin-chatbot (index.js)188.60KB44.82KB
plugin-dashboard (index.js)133.48KB34.49KB
plugin-designer (index.js)211.90KB42.74KB
plugin-detail (index.js)245.10KB62.31KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)131.78KB32.19KB
plugin-gantt (index.js)164.14KB39.87KB
plugin-grid (index.js)201.64KB54.57KB
plugin-kanban (index.js)53.16KB14.65KB
plugin-list (index.js)112.63KB27.45KB
plugin-map (index.js)20.09KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)26.72KB7.71KB
plugin-tree (index.js)9.26KB3.13KB
plugin-view (index.js)84.55KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)56.69KB19.03KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)2.05KB1.04KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)7.54KB2.63KB
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)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.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-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
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 (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
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

…mit type off a collision
Two review items from the PM on objectui#6004.
1. NULL GUARDS RESTORED. The first pass narrowed `if (!col || …)` away in the
enrichment map and the fold, on the grounds that the emit is now typed
non-nullable. Put back, with a comment naming why they survive a
non-nullable type: this producer had FIVE separate `any` leaks defeating
this very boundary — one of them (`const generatedColumns: any[]`) inside
`generateColumns()` itself, where it left a whole emit path unchecked even
after the return was annotated. A file with that history is where a cheap
runtime guard earns its place. Defence in depth BEHIND the typing, not a
substitute for it: the tombstones and the removed casts still stand.
Verified the guards survive minification into `dist/index.js` rather than
being stripped by the `never` narrowing that makes them unreachable by type
— a guard the bundler deletes would be no guard at all.
2. RENAMED off a collision. `GridColumn` collided with the pre-existing
`packages/fields/src/widgets/GridField.tsx:82`, failing
`scripts/__tests__/one-authority-per-exported-name-6273.test.ts`. The two
are genuinely different shapes (a fields-widget column config vs this
producer's emit type), so they are renamed apart rather than re-pointed at
one authority:
GridColumn -> ObjectGridColumn
GridColumnDraft -> ObjectGridColumnDraft
GridColumnHolds -> ObjectGridColumnHolds
Matching this file's own precedent, `ObjectGridColumnState` (:257), rather
than the aliased-import pattern the gate cites generically.
`RetiredListColumnKey` is unique and keeps its name — it describes
`ListColumn`'s keys, so an `ObjectGrid` prefix would misname it.
⛔ `KNOWN_COLLISIONS` is untouched. It is a SHRINK-ONLY baseline, so the
entry the failure message offers would have weakened the gate rather than
satisfied it; `scripts/` carries no diff in this PR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3233.8 KB3266.6 KB
Main entry chunk (gzip)157.4 KB350 KB
Entry fileindex-OLtSmMjd.js
StatusPASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)11.30KB4.28KB
app-shell (runtime-config.js)18.10KB6.51KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)40.18KB10.59KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.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)505.99KB114.64KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)173.10KB47.96KB
fields (index.js)238.89KB60.02KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.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.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.66KB12.84KB
plugin-charts (index.js)64.66KB18.32KB
plugin-chatbot (index.js)188.60KB44.82KB
plugin-dashboard (index.js)133.48KB34.49KB
plugin-designer (index.js)211.90KB42.74KB
plugin-detail (index.js)245.26KB62.38KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)131.78KB32.19KB
plugin-gantt (index.js)164.14KB39.87KB
plugin-grid (index.js)201.66KB54.57KB
plugin-kanban (index.js)53.16KB14.65KB
plugin-list (index.js)112.74KB27.50KB
plugin-map (index.js)20.09KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.51KB11.94KB
plugin-timeline (index.js)26.72KB7.71KB
plugin-tree (index.js)9.26KB3.13KB
plugin-view (index.js)84.55KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)4.47KB1.63KB
react (SchemaRenderer.js)56.69KB19.03KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)2.05KB1.04KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)7.54KB2.63KB
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)2.74KB1.41KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)3.75KB1.85KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.85KB0.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-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.72KB2.24KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
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 (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)6.28KB2.87KB
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

@os-support-ai
os-support-ai marked this pull request as ready for review August 26, 2026 02:04
@os-support-ai
os-support-ai added this pull request to the merge queueAug 26, 2026
Merged via the queue into main with commit beccf1cAug 26, 2026
30 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-6004-generatecolumns-typed branch August 26, 2026 02:16
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants

@os-support-ai@claude