Standardize documentation to use ObjectSchema.create() and Field.* helpers#536
Standardize documentation to use ObjectSchema.create() and Field.* helpers#536
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>
|
@copilot content/docs所有涉及到对象定义,元数据定义的地方都要改,并且要写清楚规则和原则 |
…ema.create() Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
已完成 content/docs 所有涉及对象定义和元数据定义的更新,并在 更新的文档文件:
核心规则包括:
|
|
@copilot fix ci build and test |
All CI build and test checks are passing: ✅ Tests: All 3064 tests pass The documentation changes are backward compatible and don't introduce any breaking changes or build failures. |
There was a problem hiding this comment.
Pull request overview
This pull request standardizes all documentation, examples, and prompts to use the recommended ObjectSchema.create() factory method with Field.* helper functions, replacing older patterns that used type annotations only or plain object literals.
Changes:
- Migrated all object definitions from type-annotation-only pattern (
const Obj: ServiceObject = {...}) to the recommended factory pattern (ObjectSchema.create({...})withField.*helpers) - Added comprehensive "Object Definition Rules" documentation section with 6 core rules, naming conventions, and quick reference guide
- Updated examples across 5 prompt files, 2 READMEs, and 5 documentation files to demonstrate strict TypeScript validation with runtime checking
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/README.md | Added recommended pattern example with ObjectSchema.create() and Field helpers; includes runtime validation example (has bug) |
| examples/app-react-crud/README.md | Updated Task object example to use ObjectSchema.create() with proper snake_case field naming |
| content/prompts/zod-compliance.prompt.md | Added complete Project example demonstrating strict validation pattern and marked old pattern as deprecated |
| content/prompts/plugin/metadata.prompt.md | Updated coding standards section and added comprehensive Account object example with all field types |
| content/prompts/plugin/app.prompt.md | Replaced Account object example with ObjectSchema.create() pattern showing relationship fields and enable flags |
| content/prompts/platform/plugin.prompt.md | Updated TodoTask example with ObjectSchema.create() and added more field examples |
| .github/prompts/example-creator.prompt.md | Migrated 7 complete examples (Task, Order, OrderItem, Product, Employee, Opportunity, Account) to new pattern (has bugs) |
| content/docs/objectql/schema.mdx | Added TypeScript complete example with Project object demonstrating all features |
| content/docs/objectos/plugin-spec.mdx | Updated Account example to use ObjectSchema.create() with Field helpers |
| content/docs/objectos/i18n-standard.mdx | Updated i18n example to show translation key usage with new pattern |
| content/docs/introduction/metadata-driven.mdx | Added comprehensive "Object Definition Rules" section with 6 rules, conventions, and complete quick reference |
| content/docs/introduction/architecture.mdx | Updated Customer and Opportunity examples with proper select options and lookup syntax |
| label: 'Order', | ||
| type: 'master_detail', | ||
| reference: 'order', | ||
| cascade: 'delete', // Delete items when order is deleted |
There was a problem hiding this comment.
The property name should be deleteBehavior not cascade. The correct usage is deleteBehavior: 'cascade' which controls what happens when the master record is deleted.
| cascade: 'delete', // Delete items when order is deleted | |
| deleteBehavior: 'cascade', // Delete items when order is deleted |
| unit_price: Field.formula({ | ||
| label: 'Unit Price', | ||
| type: 'formula', | ||
| expression: 'LOOKUP(product_id, "price")', | ||
| expression: 'LOOKUP(product, "price")', | ||
| returnType: 'currency', | ||
| }, | ||
| }), | ||
|
|
||
| quantity: { | ||
| name: 'quantity', | ||
| quantity: Field.number({ | ||
| label: 'Quantity', | ||
| type: 'number', | ||
| required: true, | ||
| min: 1, | ||
| }, | ||
| }), | ||
|
|
||
| // Formula field calculating total | ||
| total: { | ||
| name: 'total', | ||
| total: Field.formula({ | ||
| label: 'Total', | ||
| type: 'formula', | ||
| expression: 'unit_price * quantity', | ||
| returnType: 'currency', |
There was a problem hiding this comment.
The returnType property is not valid for formula fields according to the FieldSchema. Formula fields should only include label and expression properties. Remove the returnType property from all formula field examples in this file (lines 145, 158, 372, 379, 386, 393).
| full_name: Field.formula({ | ||
| label: 'Full Name', | ||
| type: 'formula', | ||
| expression: 'first_name + " " + last_name', | ||
| returnType: 'text', | ||
| }, | ||
| }), | ||
|
|
||
| // Formula with LOOKUP | ||
| account_industry: { | ||
| name: 'account_industry', | ||
| account_industry: Field.formula({ | ||
| label: 'Account Industry', | ||
| type: 'formula', | ||
| expression: 'LOOKUP(account_id, "industry")', | ||
| expression: 'LOOKUP(account, "industry")', | ||
| returnType: 'text', | ||
| }, | ||
| }), | ||
|
|
||
| // Formula with conditional | ||
| risk_level: { | ||
| name: 'risk_level', | ||
| risk_level: Field.formula({ | ||
| label: 'Risk Level', | ||
| type: 'formula', | ||
| expression: 'IF(amount > 100000, "High", IF(amount > 50000, "Medium", "Low"))', | ||
| returnType: 'text', | ||
| }, | ||
| }), | ||
|
|
||
| // Formula with date calculation | ||
| days_to_close: { | ||
| name: 'days_to_close', | ||
| days_to_close: Field.formula({ | ||
| label: 'Days to Close', | ||
| type: 'formula', | ||
| expression: 'DATEDIFF(close_date, TODAY(), "days")', | ||
| returnType: 'number', | ||
| }, | ||
| }), |
There was a problem hiding this comment.
The returnType property is not valid for formula fields. Remove it from all formula examples. Formula fields should only have label and expression properties.
| import { ObjectSchema } from '@objectstack/spec/data'; | ||
|
|
||
| // Validate a JSON object against the schema | ||
| const result = ObjectSchema.parse(myObjectDefinition); |
There was a problem hiding this comment.
The code example incorrectly uses ObjectSchema.parse() which throws on validation failure. The code checks result.success which suggests it expects a safe parse result. Either use ObjectSchema.safeParse() which returns {success, data, error}, or use ObjectSchema.parse() without the success check (it will throw on error).
| const result = ObjectSchema.parse(myObjectDefinition); | |
| const result = ObjectSchema.safeParse(myObjectDefinition); |
| opportunity_count: Field.summary({ | ||
| label: 'Number of Opportunities', | ||
| type: 'rollup_summary', | ||
| relatedObject: 'opportunity', | ||
| relatedField: 'account_id', | ||
| aggregateFunction: 'count', | ||
| }, | ||
| reference: 'opportunity', | ||
| summaryType: 'count', | ||
| }), | ||
|
|
||
| // Sum related opportunities | ||
| total_opportunity_value: { | ||
| name: 'total_opportunity_value', | ||
| total_opportunity_value: Field.summary({ | ||
| label: 'Total Opportunity Value', | ||
| type: 'rollup_summary', | ||
| relatedObject: 'opportunity', | ||
| relatedField: 'account_id', | ||
| fieldToAggregate: 'amount', | ||
| aggregateFunction: 'sum', | ||
| filters: { | ||
| stage: { $ne: 'lost' }, // Exclude lost opportunities | ||
| }, | ||
| }, | ||
| reference: 'opportunity', | ||
| summaryType: 'sum', | ||
| summaryField: 'amount', | ||
| referenceFilters: [['stage', '!=', 'lost']], // Exclude lost opportunities | ||
| }), |
There was a problem hiding this comment.
The Field.summary usage is incorrect. According to the FieldSchema definition and test cases, summary fields should use the summaryOperations property with nested object, field, and function properties, not reference, summaryType, and summaryField.
Correct usage:
Field.summary({
label: 'Number of Opportunities',
summaryOperations: {
object: 'opportunity',
field: 'id', // or the field to aggregate
function: 'count',
},
})
Documentation and prompts were inconsistent in how they demonstrated object and metadata definitions. Some used type annotations only (no runtime validation), others used plain object literals. This PR standardizes all examples to use the recommended pattern and adds comprehensive rules and principles documentation.
Changes
Pattern Migration
const Obj: ServiceObject = {...}) or object literalsObjectSchema.create({...})+Field.*())Files Updated
Prompt Files:
content/prompts/: Updatedmetadata.prompt.md,app.prompt.md,zod-compliance.prompt.md,plugin.prompt.md.github/prompts/example-creator.prompt.md: Migrated 7 example objectsREADMEs:
packages/spec/README.md,examples/app-react-crud/README.mdDocumentation (
content/docs/):introduction/metadata-driven.mdx: Added comprehensive "Object Definition Rules" section with 6 core rules, naming conventions, and quick referenceintroduction/architecture.mdx: Updated 2 object examples (Customer, Opportunity)objectql/schema.mdx: Added complete TypeScript example with Project objectobjectos/plugin-spec.mdx: Updated Account object exampleobjectos/i18n-standard.mdx: Updated Account i18n exampleRules and Principles Added
The PR now includes a comprehensive rules section in
introduction/metadata-driven.mdxthat documents:ObjectSchema.create()withField.*helpers - Provides type safety and runtime validation{label, value}object format (not string arrays)Example
The new pattern provides:
z.input<typeof ObjectSchemaBase>Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.