-
Notifications
You must be signed in to change notification settings - Fork 0
Add metadata-driven ObjectAgGrid with @objectstack/client integration #268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a metadata‑driven object-aggrid plugin that uses the shared DataSource abstraction (and @object-ui/data-objectstack) to auto-generate AG Grid columns from ObjectStack object schemas and load data without manual column configuration.
Changes:
- Introduces
ObjectAgGridImpland associated schema/prop types to fetch object metadata and data viaDataSource.getObjectSchema/find, generate AG GridcolumnDefsfromFieldMetadata, and wire up formatting and editing for many field types. - Extends the existing plugin registration in
index.tsxto lazily load the new implementation, expose anObjectAgGridRenderer, and register theobject-aggridcomponent with theComponentRegistryand design‑time inputs. - Adds docs (English and Chinese), Storybook stories, and an example demo to document and showcase the new metadata‑driven grid, along with wiring up the
@object-ui/data-objectstackworkspace dependency.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
pnpm-lock.yaml |
Adds the @object-ui/data-objectstack workspace package to the lockfile so the new adapter dependency resolves correctly. |
packages/plugin-aggrid/src/object-aggrid.types.ts |
Defines ObjectAgGridSchema and ObjectAgGridImplProps plus a field-type → AG Grid filter mapping; note that ColDef is imported but unused. |
packages/plugin-aggrid/src/object-aggrid.test.ts |
Adds basic Vitest tests ensuring ObjectAgGridRenderer is defined and can be invoked with required schema props without throwing. |
packages/plugin-aggrid/src/index.tsx |
Lazily loads ObjectAgGridImpl, defines ObjectAgGridRenderer, adds it to the aggridComponents export, and registers the object-aggrid component and its inputs in ComponentRegistry. |
packages/plugin-aggrid/src/ObjectAgGridImpl.tsx |
Core metadata-driven AG Grid implementation: fetches object schema and data via DataSource, generates columnDefs from FieldMetadata, configures filters, status bar, context menu, export, and inline editing with backend updates; contains a URL handling security issue and some unused imports/any casting. |
packages/plugin-aggrid/package.json |
Declares @object-ui/data-objectstack as a dependency so consumers can use ObjectStackAdapter with object-aggrid. |
packages/plugin-aggrid/README.md |
Adds a full “Object AgGrid” section documenting features, schema API, examples, and field-type formatting behavior. |
packages/plugin-aggrid/QUICKSTART.md |
New quick start for ObjectAgGrid including installation, schema examples, and backend requirements; currently shows SchemaRenderer imported from @object-ui/components, which is inconsistent with other docs that use @object-ui/react. |
packages/plugin-aggrid/OBJECT_AGGRID_CN.md |
Adds comprehensive Chinese-language documentation for ObjectAgGrid, matching the English README content and examples. |
packages/components/src/stories-json/object-aggrid.stories.tsx |
Storybook stories for ObjectAgGrid (contacts/products/basic/field selection/editable/export), using a local createMockDataSource; includes an unused ObjectStackAdapter import. |
examples/object-aggrid-demo.tsx |
Example React demo showing several ObjectAgGrid usage patterns with a mocked data source; imports ObjectStackAdapter but does not use it. |
IMPLEMENTATION_SUMMARY.md |
High-level implementation summary describing the new ObjectAgGrid component, field-type support, security considerations, testing status, and potential future enhancements. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| ### Step 4: Use in Your Component | ||
|
|
||
| ```typescript | ||
| import { SchemaRenderer } from '@object-ui/components'; |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Quick Start example imports SchemaRenderer from @object-ui/components, whereas other documentation (for example, the CLI app generator at packages/cli/src/utils/app-generator.ts:149) shows SchemaRenderer coming from @object-ui/react. For consistency with the rest of the docs and to match the recommended runtime entry point, consider updating this snippet to import SchemaRenderer from @object-ui/react.
| import { SchemaRenderer } from '@object-ui/components'; | |
| import { SchemaRenderer } from '@object-ui/react'; |
| case 'url': | ||
| colDef.cellRenderer = (params: any) => { | ||
| if (!params.value) return ''; | ||
| const escaped = escapeHtml(params.value); | ||
| return `<a href="${escaped}" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:underline">${escaped}</a>`; | ||
| }; |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The url cell renderer builds an <a> tag directly from params.value and only applies escapeHtml to it, which does not prevent javascript: or other dangerous URL schemes from being used in href; this means a malicious value like "javascript:alert(1)" would still produce a clickable XSS vector. To avoid this, validate and whitelist allowed protocols (e.g. http/https) before using the value in href, and fall back to rendering plain text or a safe placeholder when the URL scheme is not allowed.
| // Fetch object schema/metadata | ||
| const schema = await (dataSource as any).getObjectSchema(objectName); | ||
| setObjectSchema(schema); |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getObjectSchema is invoked via (dataSource as any) even though DataSource in @object-ui/types already declares this method, which unnecessarily discards type safety and deviates from how other components (e.g. packages/plugin-grid/src/ObjectGrid.tsx:166) call dataSource.getObjectSchema directly. You can rely on the typed DataSource interface here (or narrow the prop type if needed) instead of casting to any, so that incorrect data sources are caught at compile time rather than at runtime.
| MenuItemDef, | ||
| IServerSideDatasource, | ||
| IServerSideGetRowsParams |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IServerSideDatasource and IServerSideGetRowsParams are imported from ag-grid-community but never used, which adds noise and can cause linting issues. Please remove these unused imports or wire them into an actual server-side row model implementation if that work is planned.
| MenuItemDef, | |
| IServerSideDatasource, | |
| IServerSideGetRowsParams | |
| MenuItemDef |
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| import type { ColDef } from 'ag-grid-community'; |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ColDef is imported from ag-grid-community but not used in this file, which is unnecessary and can trigger lint warnings. Consider removing this unused import to keep the types module clean.
| import type { ColDef } from 'ag-grid-community'; |
| import type { Meta, StoryObj } from '@storybook/react'; | ||
| import { SchemaRenderer } from '../SchemaRenderer'; | ||
| import type { BaseSchema } from '@object-ui/types'; | ||
| import { ObjectStackAdapter } from '@object-ui/data-objectstack'; |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObjectStackAdapter is imported but never used in this Storybook file; the stories rely entirely on the local createMockDataSource helper instead. Dropping this unused import will avoid confusion about whether the stories exercise the real ObjectStack adapter and will keep the story code leaner.
| import { ObjectStackAdapter } from '@object-ui/data-objectstack'; |
| */ | ||
|
|
||
| import React from 'react'; | ||
| import { ObjectStackAdapter } from '@object-ui/data-objectstack'; |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObjectStackAdapter is imported at the top of this example but never actually used, since createExampleDataSource returns a hand-rolled mock data source. To reduce confusion for readers and keep the example code tidy, either remove this import or update the example to demonstrate constructing a real ObjectStackAdapter.
| import { ObjectStackAdapter } from '@object-ui/data-objectstack'; |
| const [error, setError] = useState<Error | null>(null); | ||
| const [objectSchema, setObjectSchema] = useState<ObjectSchemaMetadata | null>(null); | ||
| const [rowData, setRowData] = useState<any[]>([]); | ||
| const [totalCount, setTotalCount] = useState(0); |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable totalCount.
| ## Security Improvements | ||
|
|
||
| 1. **XSS Prevention**: All HTML cell renderers escape user input using `escapeHtml()` function | ||
| 2. **Date Validation**: Date parsing includes validation to prevent "Invalid Date" display | ||
| 3. **URL Sanitization**: All URL values are escaped before rendering | ||
| 4. **Error Handling**: Comprehensive error handling prevents crashes from malformed data |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation behind this section uses an escapeHtml() helper with document.createElement('div').textContent and then interpolates the escaped value directly into HTML attributes inside AG Grid cellRenderer strings (e.g., <a href="mailto:${escaped}">, <img src="${escapedUrl}">). This escaping is only safe for text nodes, not for attribute context; an attacker controlling a field value can inject quotes and additional attributes or javascript: URLs so that the constructed HTML becomes syntactically valid and executes arbitrary script in the browser. To address this, avoid building raw HTML strings for email/URL/phone/color/image/avatar cells (use React elements or framework components instead), or introduce attribute-context-safe encoding and strict URL/CSS whitelisting before inserting untrusted data into HTML attributes.
Extends existing AgGrid plugin with metadata-driven variant that auto-fetches object schemas and data from ObjectStack backend, eliminating manual column configuration.
Core Implementation
@objectstack/client, generates AG Grid column definitions from field metadata, handles data loading with pagination/filtering/sortingObjectAgGridSchemaand field-to-filter mappingsobject-aggridcomponent typeField Type Support
Implements renderers and formatters for all 30+ ObjectUI field types:
$1,234.56), percent (45.5%), number with precisionUsage
Security
Testing
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.