diff --git a/content/docs/references/ai/feedback-loop.mdx b/content/docs/references/ai/feedback-loop.mdx index d87507aa3..b632a9237 100644 --- a/content/docs/references/ai/feedback-loop.mdx +++ b/content/docs/references/ai/feedback-loop.mdx @@ -12,27 +12,13 @@ description: Feedback Loop protocol schemas ## TypeScript Usage ```typescript -import { FeedbackLoop, Issue, Resolution } from '@objectstack/spec/ai'; -import type { FeedbackLoop, Issue, Resolution } from '@objectstack/spec/ai'; +import { Issue } from '@objectstack/spec/ai'; +import type { Issue } from '@objectstack/spec/ai'; // Validate data -const result = FeedbackLoop.parse(data); +const result = Issue.parse(data); ``` ---- - -## FeedbackLoop - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **issue** | `Object` | ✅ | | -| **analysis** | `string` | optional | AI analysis of the root cause | -| **resolutions** | `Object[]` | optional | | -| **status** | `Enum<'open' \| 'analyzing' \| 'resolved' \| 'ignored'>` | ✅ | | - - --- ## Issue @@ -53,17 +39,3 @@ const result = FeedbackLoop.parse(data); --- -## Resolution - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **issueId** | `string` | ✅ | | -| **reasoning** | `string` | ✅ | Explanation of why this fix is needed | -| **confidence** | `number` | ✅ | | -| **fix** | `Object \| Object` | ✅ | | - - ---- - diff --git a/content/docs/references/api/contract.mdx b/content/docs/references/api/contract.mdx index a24ff5807..f6e14d5e6 100644 --- a/content/docs/references/api/contract.mdx +++ b/content/docs/references/api/contract.mdx @@ -154,7 +154,7 @@ const result = ApiError.parse(data); | **having** | `[__schema2](./__schema2)` | optional | HAVING clause for aggregation filtering | | **windowFunctions** | `Object[]` | optional | Window functions with OVER clause | | **distinct** | `boolean` | optional | SELECT DISTINCT flag | -| **expand** | `Record` | optional | Recursive relation loading (nested queries) | +| **expand** | `Record` | optional | Recursive relation loading map. Keys are lookup/master_detail field names; values are nested QueryAST objects that control select, filter, sort, and further expansion on the related object. The engine resolves expand via batch $in queries (driver-agnostic) with a default max depth of 3. | --- diff --git a/content/docs/references/api/metadata.mdx b/content/docs/references/api/metadata.mdx index 8246ade1b..70588afef 100644 --- a/content/docs/references/api/metadata.mdx +++ b/content/docs/references/api/metadata.mdx @@ -50,8 +50,8 @@ the entire platform, including Hono, Next.js, and NestJS adapters. ## TypeScript Usage ```typescript -import { AppDefinitionResponse, ConceptListResponse, MetadataBulkResponse, MetadataBulkUnregisterRequest, MetadataDeleteResponse, MetadataDependenciesResponse, MetadataDependentsResponse, MetadataEffectiveResponse, MetadataExistsResponse, MetadataExportRequest, MetadataExportResponse, MetadataImportRequest, MetadataImportResponse, MetadataItemResponse, MetadataListResponse, MetadataNamesResponse, MetadataOverlayResponse, MetadataOverlaySaveRequest, MetadataQueryRequest, MetadataQueryResponse, MetadataRegisterRequest, MetadataTypeInfoResponse, MetadataTypesResponse, MetadataValidateRequest, MetadataValidateResponse, ObjectDefinitionResponse } from '@objectstack/spec/api'; -import type { AppDefinitionResponse, ConceptListResponse, MetadataBulkResponse, MetadataBulkUnregisterRequest, MetadataDeleteResponse, MetadataDependenciesResponse, MetadataDependentsResponse, MetadataEffectiveResponse, MetadataExistsResponse, MetadataExportRequest, MetadataExportResponse, MetadataImportRequest, MetadataImportResponse, MetadataItemResponse, MetadataListResponse, MetadataNamesResponse, MetadataOverlayResponse, MetadataOverlaySaveRequest, MetadataQueryRequest, MetadataQueryResponse, MetadataRegisterRequest, MetadataTypeInfoResponse, MetadataTypesResponse, MetadataValidateRequest, MetadataValidateResponse, ObjectDefinitionResponse } from '@objectstack/spec/api'; +import { AppDefinitionResponse, ConceptListResponse, MetadataBulkResponse, MetadataBulkUnregisterRequest, MetadataDeleteResponse, MetadataDependenciesResponse, MetadataDependentsResponse, MetadataEffectiveResponse, MetadataExistsResponse, MetadataExportRequest, MetadataExportResponse, MetadataImportRequest, MetadataImportResponse, MetadataItemResponse, MetadataListResponse, MetadataNamesResponse, MetadataOverlayResponse, MetadataOverlaySaveRequest, MetadataQueryRequest, MetadataQueryResponse, MetadataRegisterRequest, MetadataTypeInfoResponse, MetadataTypesResponse, MetadataValidateRequest, MetadataValidateResponse } from '@objectstack/spec/api'; +import type { AppDefinitionResponse, ConceptListResponse, MetadataBulkResponse, MetadataBulkUnregisterRequest, MetadataDeleteResponse, MetadataDependenciesResponse, MetadataDependentsResponse, MetadataEffectiveResponse, MetadataExistsResponse, MetadataExportRequest, MetadataExportResponse, MetadataImportRequest, MetadataImportResponse, MetadataItemResponse, MetadataListResponse, MetadataNamesResponse, MetadataOverlayResponse, MetadataOverlaySaveRequest, MetadataQueryRequest, MetadataQueryResponse, MetadataRegisterRequest, MetadataTypeInfoResponse, MetadataTypesResponse, MetadataValidateRequest, MetadataValidateResponse } from '@objectstack/spec/api'; // Validate data const result = AppDefinitionResponse.parse(data); @@ -425,17 +425,3 @@ Metadata query with filtering, sorting, and pagination --- -## ObjectDefinitionResponse - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **success** | `boolean` | ✅ | Operation success status | -| **error** | `Object` | optional | Error details if success is false | -| **meta** | `Object` | optional | Response metadata | -| **data** | `Object` | ✅ | Full Object Schema | - - ---- - diff --git a/content/docs/references/api/odata.mdx b/content/docs/references/api/odata.mdx index b2474082c..7a1da70a8 100644 --- a/content/docs/references/api/odata.mdx +++ b/content/docs/references/api/odata.mdx @@ -226,7 +226,7 @@ const result = ODataConfig.parse(data); | **$orderby** | `string \| string[]` | optional | Sort order | | **$top** | `integer` | optional | Max results to return | | **$skip** | `integer` | optional | Results to skip | -| **$expand** | `string \| string[]` | optional | Navigation properties to expand | +| **$expand** | `string \| string[]` | optional | Navigation properties to expand (lookup/master_detail fields) | | **$count** | `boolean` | optional | Include total count | | **$search** | `string` | optional | Search expression | | **$format** | `Enum<'json' \| 'xml' \| 'atom'>` | optional | Response format | diff --git a/content/docs/references/api/protocol.mdx b/content/docs/references/api/protocol.mdx index 15e69e2d7..1b15685b7 100644 --- a/content/docs/references/api/protocol.mdx +++ b/content/docs/references/api/protocol.mdx @@ -395,7 +395,7 @@ const result = AiChatRequest.parse(data); | **object** | `string` | ✅ | The object name. | | **id** | `string` | ✅ | The unique record identifier (primary key). | | **select** | `string[]` | optional | Fields to include in the response (allowlisted query param). | -| **expand** | `string[]` | optional | Relations to eager-load (allowlisted query param). | +| **expand** | `string[]` | optional | Lookup/master_detail field names to expand. The engine resolves these via batch $in queries, replacing foreign key IDs with full objects. | --- @@ -782,7 +782,7 @@ const result = AiChatRequest.parse(data); | **orderBy** | `string` | optional | Alias for sort (OData compatibility). | | **top** | `number` | optional | Max records to return (limit). | | **skip** | `number` | optional | Records to skip (offset). | -| **expand** | `string` | optional | Comma-separated list of relations to eager-load. | +| **expand** | `string` | optional | Comma-separated list of lookup/master_detail field names to expand. Resolved to populate array and passed to the engine for batch $in expansion. | | **search** | `string` | optional | Full-text search query. | | **distinct** | `boolean` | optional | SELECT DISTINCT flag. | | **count** | `boolean` | optional | Include total count in response. | diff --git a/content/docs/references/data/field.mdx b/content/docs/references/data/field.mdx index 08c7d347a..e5dceae72 100644 --- a/content/docs/references/data/field.mdx +++ b/content/docs/references/data/field.mdx @@ -115,7 +115,7 @@ const result = Address.parse(data); | **min** | `number` | optional | Minimum value | | **max** | `number` | optional | Maximum value | | **options** | `Object[]` | optional | Static options for select/multiselect | -| **reference** | `string` | optional | Target Object Name | +| **reference** | `string` | optional | Target object name (snake_case) for lookup/master_detail fields. Required for relationship types. Used by $expand to resolve foreign key IDs into full objects. | | **referenceFilters** | `string[]` | optional | Filters applied to lookup dialogs (e.g. "active = true") | | **writeRequiresMasterRead** | `boolean` | optional | If true, user needs read access to master record to edit this field | | **deleteBehavior** | `Enum<'set_null' \| 'cascade' \| 'restrict'>` | ✅ | What happens if referenced record is deleted | diff --git a/content/docs/references/data/object.mdx b/content/docs/references/data/object.mdx index 39b6017e9..5b8de28d7 100644 --- a/content/docs/references/data/object.mdx +++ b/content/docs/references/data/object.mdx @@ -14,8 +14,8 @@ API Operations Enum ## TypeScript Usage ```typescript -import { ApiMethod, CDCConfig, Index, Object, ObjectCapabilities, ObjectExtension, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; -import type { ApiMethod, CDCConfig, Index, Object, ObjectCapabilities, ObjectExtension, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import { ApiMethod, CDCConfig, Index, ObjectCapabilities, ObjectExtension, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; +import type { ApiMethod, CDCConfig, Index, ObjectCapabilities, ObjectExtension, ObjectOwnershipEnum, PartitioningConfig, SoftDeleteConfig, TenancyConfig, VersioningConfig } from '@objectstack/spec/data'; // Validate data const result = ApiMethod.parse(data); @@ -71,45 +71,6 @@ const result = ApiMethod.parse(data); | **partial** | `string` | optional | Partial index condition (SQL WHERE clause for conditional indexes) | ---- - -## Object - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **name** | `string` | ✅ | Machine unique key (snake_case). Immutable. | -| **label** | `string` | optional | Human readable singular label (e.g. "Account") | -| **pluralLabel** | `string` | optional | Human readable plural label (e.g. "Accounts") | -| **description** | `string` | optional | Developer documentation / description | -| **icon** | `string` | optional | Icon name (Lucide/Material) for UI representation | -| **tags** | `string[]` | optional | Categorization tags (e.g. "sales", "system", "reference") | -| **active** | `boolean` | ✅ | Is the object active and usable | -| **isSystem** | `boolean` | ✅ | Is system object (protected from deletion) | -| **abstract** | `boolean` | ✅ | Is abstract base object (cannot be instantiated) | -| **datasource** | `string` | ✅ | Target Datasource ID. "default" is the primary DB. | -| **tableName** | `string` | optional | Physical table/collection name in the target datasource | -| **fields** | `Record` | ✅ | Field definitions map. Keys must be snake_case identifiers. | -| **indexes** | `Object[]` | optional | Database performance indexes | -| **tenancy** | `Object` | optional | Multi-tenancy configuration for SaaS applications | -| **softDelete** | `Object` | optional | Soft delete (trash/recycle bin) configuration | -| **versioning** | `Object` | optional | Record versioning and history tracking configuration | -| **partitioning** | `Object` | optional | Table partitioning configuration for performance | -| **cdc** | `Object` | optional | Change Data Capture (CDC) configuration for real-time data streaming | -| **validations** | `[__schema0](./__schema0)[]` | optional | Object-level validation rules | -| **stateMachines** | `Record` | optional | Named state machines for parallel lifecycles (e.g., status, payment, approval) | -| **displayNameField** | `string` | optional | Field to use as the record display name (e.g., "name", "title"). Defaults to "name" if present. | -| **recordName** | `Object` | optional | Record name generation configuration (Salesforce pattern) | -| **titleFormat** | `string` | optional | Title expression (e.g. "`{name}` - `{code}`"). Overrides displayNameField. | -| **compactLayout** | `string[]` | optional | Primary fields for hover/cards/lookups | -| **search** | `Object` | optional | Search engine configuration | -| **enable** | `Object` | optional | Enabled system features modules | -| **recordTypes** | `string[]` | optional | Record type names for this object | -| **sharingModel** | `Enum<'private' \| 'read' \| 'read_write' \| 'full'>` | optional | Default sharing model | -| **keyPrefix** | `string` | optional | Short prefix for record IDs (e.g., "001" for Account) | - - --- ## ObjectCapabilities diff --git a/content/docs/references/data/query.mdx b/content/docs/references/data/query.mdx index a5400c1fd..19f3ca7ee 100644 --- a/content/docs/references/data/query.mdx +++ b/content/docs/references/data/query.mdx @@ -162,7 +162,7 @@ Type: `string` | **having** | `[__schema1](./__schema1)` | optional | HAVING clause for aggregation filtering | | **windowFunctions** | `Object[]` | optional | Window functions with OVER clause | | **distinct** | `boolean` | optional | SELECT DISTINCT flag | -| **expand** | `Record` | optional | Recursive relation loading (nested queries) | +| **expand** | `Record` | optional | Recursive relation loading map. Keys are lookup/master_detail field names; values are nested QueryAST objects that control select, filter, sort, and further expansion on the related object. The engine resolves expand via batch $in queries (driver-agnostic) with a default max depth of 3. | --- diff --git a/content/docs/references/integration/meta.json b/content/docs/references/integration/meta.json index 50987b859..fe5108d07 100644 --- a/content/docs/references/integration/meta.json +++ b/content/docs/references/integration/meta.json @@ -8,6 +8,7 @@ "misc", "object-storage", "offline", - "tenant" + "tenant", + "translation" ] } \ No newline at end of file diff --git a/content/docs/references/integration/misc.mdx b/content/docs/references/integration/misc.mdx index a5779c791..c1e3d344b 100644 --- a/content/docs/references/integration/misc.mdx +++ b/content/docs/references/integration/misc.mdx @@ -12,8 +12,8 @@ description: Misc protocol schemas ## TypeScript Usage ```typescript -import { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageFormat, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration'; -import type { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageFormat, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration'; +import { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration'; +import type { AckMode, ApiVersionConfig, BuildConfig, CdcConfig, DatabaseConnector, DatabasePoolConfig, DatabaseTable, DeliveryGuarantee, DeploymentConfig, DlqConfig, DomainConfig, EdgeFunctionConfig, EnvironmentVariables, FileAccessPattern, FileFilterConfig, FileMetadataConfig, FileStorageConnector, FileStorageProvider, FileVersioningConfig, GitHubActionsWorkflow, GitHubCommitConfig, GitHubConnector, GitHubIssueTracking, GitHubProvider, GitHubPullRequestConfig, GitHubReleaseConfig, GitHubRepository, GitRepositoryConfig, MessageQueueConnector, ProducerConfig, SaasConnector, SaasObjectType, SaasProvider, SslConfig, StorageBucket, TopicQueue, VercelConnector, VercelFramework, VercelMonitoring, VercelProject, VercelProvider, VercelTeam } from '@objectstack/spec/integration'; // Validate data const result = AckMode.parse(data); @@ -521,22 +521,6 @@ GitHub provider type | **autoDeployPreview** | `boolean` | ✅ | Auto-deploy preview branches | ---- - -## MessageFormat - -Message format/serialization - -### Allowed Values - -* `json` -* `xml` -* `protobuf` -* `avro` -* `text` -* `binary` - - --- ## MessageQueueConnector diff --git a/content/docs/references/integration/translation.mdx b/content/docs/references/integration/translation.mdx new file mode 100644 index 000000000..5fd774b91 --- /dev/null +++ b/content/docs/references/integration/translation.mdx @@ -0,0 +1,39 @@ +--- +title: Translation +description: Translation protocol schemas +--- + +{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */} + + +**Source:** `packages/spec/src/integration/translation.zod.ts` + + +## TypeScript Usage + +```typescript +import { MessageFormat } from '@objectstack/spec/integration'; +import type { MessageFormat } from '@objectstack/spec/integration'; + +// Validate data +const result = MessageFormat.parse(data); +``` + +--- + +## MessageFormat + +Message format/serialization + +### Allowed Values + +* `json` +* `xml` +* `protobuf` +* `avro` +* `text` +* `binary` + + +--- + diff --git a/content/docs/references/system/metadata-persistence.mdx b/content/docs/references/system/metadata-persistence.mdx index bdd758033..055a78206 100644 --- a/content/docs/references/system/metadata-persistence.mdx +++ b/content/docs/references/system/metadata-persistence.mdx @@ -16,8 +16,8 @@ Defines the lifecycle and mutability of a metadata item. ## TypeScript Usage ```typescript -import { MetadataCollectionInfo, MetadataExportOptions, MetadataFallbackStrategy, MetadataFormat, MetadataImportOptions, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataRecord, MetadataSaveOptions, MetadataSaveResult, MetadataScope, MetadataSource, MetadataState, MetadataStats, MetadataWatchEvent } from '@objectstack/spec/system'; -import type { MetadataCollectionInfo, MetadataExportOptions, MetadataFallbackStrategy, MetadataFormat, MetadataImportOptions, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataRecord, MetadataSaveOptions, MetadataSaveResult, MetadataScope, MetadataSource, MetadataState, MetadataStats, MetadataWatchEvent } from '@objectstack/spec/system'; +import { MetadataCollectionInfo, MetadataExportOptions, MetadataFallbackStrategy, MetadataFormat, MetadataImportOptions, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataRecord, MetadataSaveOptions, MetadataSaveResult, MetadataScope, MetadataSource, MetadataState, MetadataStats, MetadataWatchEvent, PackagePublishResult } from '@objectstack/spec/system'; +import type { MetadataCollectionInfo, MetadataExportOptions, MetadataFallbackStrategy, MetadataFormat, MetadataImportOptions, MetadataLoadOptions, MetadataLoadResult, MetadataLoaderContract, MetadataManagerConfig, MetadataRecord, MetadataSaveOptions, MetadataSaveResult, MetadataScope, MetadataSource, MetadataState, MetadataStats, MetadataWatchEvent, PackagePublishResult } from '@objectstack/spec/system'; // Validate data const result = MetadataCollectionInfo.parse(data); @@ -189,6 +189,9 @@ const result = MetadataCollectionInfo.parse(data); | **checksum** | `string` | optional | Content checksum for change detection | | **source** | `Enum<'filesystem' \| 'database' \| 'api' \| 'migration'>` | optional | Origin of this metadata record | | **tags** | `string[]` | optional | Classification tags for filtering and grouping | +| **publishedDefinition** | `any` | optional | Snapshot of the last published definition | +| **publishedAt** | `string` | optional | When this metadata was last published | +| **publishedBy** | `string` | optional | Who published this version | | **createdBy** | `string` | optional | | | **createdAt** | `string` | optional | Creation timestamp | | **updatedBy** | `string` | optional | | @@ -303,3 +306,19 @@ const result = MetadataCollectionInfo.parse(data); --- +## PackagePublishResult + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **success** | `boolean` | ✅ | Whether the publish succeeded | +| **packageId** | `string` | ✅ | The package ID that was published | +| **version** | `integer` | ✅ | New version number after publish | +| **publishedAt** | `string` | ✅ | Publish timestamp | +| **itemsPublished** | `integer` | ✅ | Total metadata items published | +| **validationErrors** | `Object[]` | optional | Validation errors if publish failed | + + +--- + diff --git a/content/docs/references/system/migration.mdx b/content/docs/references/system/migration.mdx index 4897e545a..e3b71c8ba 100644 --- a/content/docs/references/system/migration.mdx +++ b/content/docs/references/system/migration.mdx @@ -12,8 +12,8 @@ description: Migration protocol schemas ## TypeScript Usage ```typescript -import { AddFieldOperation, ChangeSet, CreateObjectOperation, DeleteObjectOperation, ExecuteSqlOperation, MigrationDependency, MigrationOperation, ModifyFieldOperation, RemoveFieldOperation, RenameObjectOperation } from '@objectstack/spec/system'; -import type { AddFieldOperation, ChangeSet, CreateObjectOperation, DeleteObjectOperation, ExecuteSqlOperation, MigrationDependency, MigrationOperation, ModifyFieldOperation, RemoveFieldOperation, RenameObjectOperation } from '@objectstack/spec/system'; +import { AddFieldOperation, DeleteObjectOperation, ExecuteSqlOperation, MigrationDependency, ModifyFieldOperation, RemoveFieldOperation, RenameObjectOperation } from '@objectstack/spec/system'; +import type { AddFieldOperation, DeleteObjectOperation, ExecuteSqlOperation, MigrationDependency, ModifyFieldOperation, RemoveFieldOperation, RenameObjectOperation } from '@objectstack/spec/system'; // Validate data const result = AddFieldOperation.parse(data); @@ -35,40 +35,6 @@ Add a new field to an existing object | **field** | `Object` | ✅ | Full field definition to add | ---- - -## ChangeSet - -A versioned set of atomic schema migration operations - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **id** | `string` | ✅ | Unique identifier for this change set | -| **name** | `string` | ✅ | Human readable name for the migration | -| **description** | `string` | optional | Detailed description of what this migration does | -| **author** | `string` | optional | Author who created this migration | -| **createdAt** | `string` | optional | ISO 8601 timestamp when the migration was created | -| **dependencies** | `Object[]` | optional | Migrations that must run before this one | -| **operations** | `Object \| Object \| Object \| Object \| Object \| Object \| Object[]` | ✅ | Ordered list of atomic migration operations | -| **rollback** | `Object \| Object \| Object \| Object \| Object \| Object \| Object[]` | optional | Operations to reverse this migration | - - ---- - -## CreateObjectOperation - -Create a new object - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **object** | `Object` | ✅ | Full object definition to create | - - --- ## DeleteObjectOperation @@ -112,127 +78,6 @@ Dependency reference to another migration that must run first | **package** | `string` | optional | Package that owns the dependency migration | ---- - -## MigrationOperation - -### Union Options - -This schema accepts one of the following structures: - -#### Option 1 - -Add a new field to an existing object - -**Type:** `add_field` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **objectName** | `string` | ✅ | Target object name | -| **fieldName** | `string` | ✅ | Name of the field to add | -| **field** | `Object` | ✅ | Full field definition to add | - ---- - -#### Option 2 - -Modify properties of an existing field - -**Type:** `modify_field` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **objectName** | `string` | ✅ | Target object name | -| **fieldName** | `string` | ✅ | Name of the field to modify | -| **changes** | `Record` | ✅ | Partial field definition updates | - ---- - -#### Option 3 - -Remove a field from an existing object - -**Type:** `remove_field` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **objectName** | `string` | ✅ | Target object name | -| **fieldName** | `string` | ✅ | Name of the field to remove | - ---- - -#### Option 4 - -Create a new object - -**Type:** `create_object` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **object** | `Object` | ✅ | Full object definition to create | - ---- - -#### Option 5 - -Rename an existing object - -**Type:** `rename_object` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **oldName** | `string` | ✅ | Current object name | -| **newName** | `string` | ✅ | New object name | - ---- - -#### Option 6 - -Delete an existing object - -**Type:** `delete_object` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **objectName** | `string` | ✅ | Name of the object to delete | - ---- - -#### Option 7 - -Execute a raw SQL statement - -**Type:** `execute_sql` - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **type** | `string` | ✅ | | -| **sql** | `string` | ✅ | Raw SQL statement to execute | -| **description** | `string` | optional | Human-readable description of the SQL | - ---- - - --- ## ModifyFieldOperation diff --git a/content/docs/references/system/translation.mdx b/content/docs/references/system/translation.mdx index e1c7aa0b7..ae72c397c 100644 --- a/content/docs/references/system/translation.mdx +++ b/content/docs/references/system/translation.mdx @@ -16,13 +16,54 @@ Translation data for a single field. ## TypeScript Usage ```typescript -import { FieldTranslation, Locale, ObjectTranslationData, TranslationBundle, TranslationConfig, TranslationData, TranslationFileOrganization } from '@objectstack/spec/system'; -import type { FieldTranslation, Locale, ObjectTranslationData, TranslationBundle, TranslationConfig, TranslationData, TranslationFileOrganization } from '@objectstack/spec/system'; +import { AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, MessageFormat, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus, TranslationFileOrganization } from '@objectstack/spec/system'; +import type { AppTranslationBundle, CoverageBreakdownEntry, FieldTranslation, Locale, MessageFormat, ObjectTranslationData, ObjectTranslationNode, TranslationBundle, TranslationConfig, TranslationCoverageResult, TranslationData, TranslationDiffItem, TranslationDiffStatus, TranslationFileOrganization } from '@objectstack/spec/system'; // Validate data -const result = FieldTranslation.parse(data); +const result = AppTranslationBundle.parse(data); ``` +--- + +## AppTranslationBundle + +Object-first application translation bundle for a single locale + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **_meta** | `Object` | optional | Bundle-level metadata (locale, bidi direction) | +| **namespace** | `string` | optional | Namespace for plugin isolation to avoid translation key collisions | +| **o** | `Record` | optional | Object-first translations keyed by object name | +| **_globalOptions** | `Record>` | optional | Global picklist option translations keyed by option set name | +| **app** | `Record` | optional | App translations keyed by app name | +| **nav** | `Record` | optional | Navigation item translations keyed by nav item name | +| **dashboard** | `Record` | optional | Dashboard translations keyed by dashboard name | +| **reports** | `Record` | optional | Report translations keyed by report name | +| **pages** | `Record` | optional | Page translations keyed by page name | +| **messages** | `Record` | optional | UI message translations keyed by message ID (supports ICU MessageFormat) | +| **validationMessages** | `Record` | optional | Validation error message translations keyed by rule name (supports ICU MessageFormat) | +| **notifications** | `Record` | optional | Global notification translations keyed by notification name | +| **errors** | `Record` | optional | Global error message translations keyed by error code | + + +--- + +## CoverageBreakdownEntry + +Coverage breakdown for a single translation group + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **group** | `string` | ✅ | Translation group category | +| **totalKeys** | `integer` | ✅ | Total keys in this group | +| **translatedKeys** | `integer` | ✅ | Translated keys in this group | +| **coveragePercent** | `number` | ✅ | Coverage percentage for this group | + + --- ## FieldTranslation @@ -35,12 +76,25 @@ Translation data for a single field | :--- | :--- | :--- | :--- | | **label** | `string` | optional | Translated field label | | **help** | `string` | optional | Translated help text | +| **placeholder** | `string` | optional | Translated placeholder text for form inputs | | **options** | `Record` | optional | Option value to translated label map | --- +--- + +## MessageFormat + +Message interpolation format: ICU MessageFormat or simple `{variable}` replacement + +### Allowed Values + +* `icu` +* `simple` + + --- ## ObjectTranslationData @@ -56,6 +110,29 @@ Translation data for a single object | **fields** | `Record` | optional | Field-level translations | +--- + +## ObjectTranslationNode + +Object-first aggregated translation node + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **label** | `string` | ✅ | Translated singular label | +| **pluralLabel** | `string` | optional | Translated plural label | +| **description** | `string` | optional | Translated object description | +| **helpText** | `string` | optional | Translated help text for the object | +| **fields** | `Record` | optional | Field translations keyed by field name | +| **_options** | `Record>` | optional | Object-scoped picklist option translations keyed by field name | +| **_views** | `Record` | optional | View translations keyed by view name | +| **_sections** | `Record` | optional | Section translations keyed by section name | +| **_actions** | `Record` | optional | Action translations keyed by action name | +| **_notifications** | `Record` | optional | Notification translations keyed by notification name | +| **_errors** | `Record` | optional | Error message translations keyed by error code | + + --- @@ -73,10 +150,33 @@ Internationalization configuration | **supportedLocales** | `string[]` | ✅ | Supported BCP-47 locale codes | | **fallbackLocale** | `string` | optional | Fallback locale code | | **fileOrganization** | `Enum<'bundled' \| 'per_locale' \| 'per_namespace'>` | ✅ | File organization strategy | +| **messageFormat** | `Enum<'icu' \| 'simple'>` | ✅ | Message interpolation format (ICU MessageFormat or simple) | | **lazyLoad** | `boolean` | ✅ | Load translations on demand | | **cache** | `boolean` | ✅ | Cache loaded translations | +--- + +## TranslationCoverageResult + +Aggregated translation coverage result + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **locale** | `string` | ✅ | BCP-47 locale code | +| **objectName** | `string` | optional | Object name scope (omit for full bundle) | +| **totalKeys** | `integer` | ✅ | Total translatable keys from metadata | +| **translatedKeys** | `integer` | ✅ | Number of translated keys | +| **missingKeys** | `integer` | ✅ | Number of missing translations | +| **redundantKeys** | `integer` | ✅ | Number of redundant translations | +| **staleKeys** | `integer` | ✅ | Number of stale translations | +| **coveragePercent** | `number` | ✅ | Translation coverage percentage | +| **items** | `Object[]` | ✅ | Detailed diff items | +| **breakdown** | `Object[]` | optional | Per-group coverage breakdown | + + --- ## TranslationData @@ -93,6 +193,38 @@ Translation data for objects, apps, and UI messages | **validationMessages** | `Record` | optional | Translatable validation error messages keyed by rule name (e.g., `{"discount_limit": "折扣不能超过40%"}`) | +--- + +## TranslationDiffItem + +A single translation diff item + +### Properties + +| Property | Type | Required | Description | +| :--- | :--- | :--- | :--- | +| **key** | `string` | ✅ | Dot-path translation key | +| **status** | `Enum<'missing' \| 'redundant' \| 'stale'>` | ✅ | Diff status of this translation key | +| **objectName** | `string` | optional | Associated object name (snake_case) | +| **locale** | `string` | ✅ | BCP-47 locale code | +| **sourceHash** | `string` | optional | Hash of source metadata for precise stale detection | +| **aiSuggested** | `string` | optional | AI-suggested translation for this key | +| **aiConfidence** | `number` | optional | AI suggestion confidence score (0–1) | + + +--- + +## TranslationDiffStatus + +Translation diff status: missing from bundle, redundant (no matching metadata), or stale (metadata changed) + +### Allowed Values + +* `missing` +* `redundant` +* `stale` + + --- ## TranslationFileOrganization diff --git a/content/docs/references/ui/action.mdx b/content/docs/references/ui/action.mdx index a2f6b5e65..0bb8be6e4 100644 --- a/content/docs/references/ui/action.mdx +++ b/content/docs/references/ui/action.mdx @@ -16,89 +16,15 @@ Defines inputs required before executing an action. ## TypeScript Usage ```typescript -import { Action, ActionParam } from '@objectstack/spec/ui'; -import type { Action, ActionParam } from '@objectstack/spec/ui'; +import { ActionParam, ActionType } from '@objectstack/spec/ui'; +import type { ActionParam, ActionType } from '@objectstack/spec/ui'; // Validate data -const result = Action.parse(data); +const result = ActionParam.parse(data); ``` --- -## Action - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **name** | `string` | ✅ | Machine name (lowercase snake_case) | -| **label** | `string \| Object` | ✅ | Display label | -| **icon** | `string` | optional | Icon name | -| **locations** | `Enum<'list_toolbar' \| 'list_item' \| 'record_header' \| 'record_more' \| 'record_related' \| 'global_nav'>[]` | optional | Locations where this action is visible | -| **component** | `Enum<'action:button' \| 'action:icon' \| 'action:menu' \| 'action:group'>` | optional | Visual component override | -| **type** | `Enum<'script' \| 'url' \| 'modal' \| 'flow' \| 'api'>` | ✅ | Action functionality type | -| **target** | `string` | conditional | URL, Script Name, Flow ID, Modal/Page Name, or API Endpoint. **Required** for `url`, `flow`, `modal`, and `api` types; recommended for `script`. | -| **execute** | `string` | optional | ⚠️ **Deprecated** — Use `target` instead. Auto-migrated to `target` during parsing. Will be removed in a future version. | -| **params** | `Object[]` | optional | Input parameters required from user | -| **variant** | `Enum<'primary' \| 'secondary' \| 'danger' \| 'ghost' \| 'link'>` | optional | Button visual variant for styling (primary = highlighted, danger = destructive, ghost = transparent) | -| **confirmText** | `string \| Object` | optional | Confirmation message before execution | -| **successMessage** | `string \| Object` | optional | Success message to show after execution | -| **refreshAfter** | `boolean` | ✅ | Refresh view after execution | -| **visible** | `string` | optional | Formula returning boolean | -| **disabled** | `boolean \| string` | optional | Whether the action is disabled, or a condition expression string | -| **shortcut** | `string` | optional | Keyboard shortcut to trigger this action (e.g., "Ctrl+S") | -| **bulkEnabled** | `boolean` | optional | Whether this action can be applied to multiple selected records | -| **timeout** | `number` | optional | Maximum execution time in milliseconds for the action | -| **aria** | `Object` | optional | ARIA accessibility attributes | - -### Target Binding Rules - -The `target` field is the canonical way to bind an action to its handler: - -| Action Type | target | Description | -| :--- | :--- | :--- | -| `script` | Recommended | Function name to invoke (e.g. `completeTask`) | -| `url` | **Required** | URL to navigate to | -| `flow` | **Required** | Flow name to invoke (validated against defined flows) | -| `modal` | **Required** | Page/modal name to open (validated against defined pages) | -| `api` | **Required** | API endpoint to call | - -### Examples - -```typescript -// Script action with handler target -const action: Action = { - name: 'complete_task', - label: 'Mark Complete', - type: 'script', - target: 'completeTask', // ← references a registered handler function - locations: ['record_header'], - refreshAfter: true, -}; - -// Flow action -const flowAction: Action = { - name: 'convert_lead', - label: 'Convert Lead', - type: 'flow', - target: 'lead_conversion', // ← must match a defined flow name -}; - -// Modal action -const modalAction: Action = { - name: 'defer_task', - label: 'Defer Task', - type: 'modal', - target: 'defer_task_modal', // ← must match a defined page name -}; -``` - - -**Migration Note:** The `execute` field is deprecated. If `execute` is provided without `target`, it is automatically migrated to `target` during schema parsing. Always use `target` in new code. - - ---- - ## ActionParam ### Properties @@ -114,25 +40,16 @@ const modalAction: Action = { --- -## Cross-Reference Validation +## ActionType -`defineStack()` validates action cross-references at build time: +### Allowed Values -- **`type: 'flow'`** — `target` is checked against the `flows[]` collection (when flows are defined). -- **`type: 'modal'`** — `target` is checked against the `pages[]` collection (when pages are defined). +* `script` +* `url` +* `modal` +* `flow` +* `api` -When the target collection is empty, validation is skipped because referenced items may come from plugins. --- -## Platform Comparison - -| Capability | ObjectStack | Salesforce | ServiceNow | Power Platform | -| :--- | :--- | :--- | :--- | :--- | -| **Declarative actions** | `ActionSchema` with `target` binding | Lightning Actions (Quick Actions) | UI Actions / Client Scripts | Power Fx `OnSelect` | -| **Action types** | `script`, `url`, `modal`, `flow`, `api` | URL, Flow, LWC, Visualforce | Client Script, UI Policy, Flow | Navigate, Patch, Launch | -| **Handler binding** | `target` string → `engine.registerAction()` | Apex Controller `@AuraEnabled` | Script Include + GlideAjax | Power Automate Cloud Flow | -| **Cross-ref validation** | Build-time (`defineStack`) | Deploy-time (Metadata API) | Update Set validation | Solution Checker | -| **Modal integration** | `type: 'modal'` + page name target | `lightning:overlayLibrary` | GlideModal / GlideDialogWindow | `Navigate(Screen)` | -| **Bulk operations** | `bulkEnabled` + `locations: ['list_toolbar']` | List Button + Mass Quick Action | List v3 Actions | Gallery `OnSelect` multi | - diff --git a/packages/plugins/plugin-msw/src/msw-plugin.ts b/packages/plugins/plugin-msw/src/msw-plugin.ts index fddb6efd5..083432865 100644 --- a/packages/plugins/plugin-msw/src/msw-plugin.ts +++ b/packages/plugins/plugin-msw/src/msw-plugin.ts @@ -372,7 +372,13 @@ export class ObjectStackServer { } static async getData(objectName: string, id: string, options?: { expand?: string | string[]; select?: string | string[] }) { - const body = await this.getProtocol().getData({ object: objectName, id, ...options }); + const normalize = (v?: string | string[]) => v == null ? undefined : Array.isArray(v) ? v : [v]; + const body = await this.getProtocol().getData({ + object: objectName, + id, + select: normalize(options?.select), + expand: normalize(options?.expand), + }); return { data: body, status: 200 }; } diff --git a/packages/spec/scripts/build-docs.ts b/packages/spec/scripts/build-docs.ts index 854a07007..15da6f233 100644 --- a/packages/spec/scripts/build-docs.ts +++ b/packages/spec/scripts/build-docs.ts @@ -160,7 +160,7 @@ function generateMarkdown(schemaName: string, schema: any, category: string, zod // Add description with better formatting if (mainDef.description) { - md += `${mainDef.description}\n\n`; + md += `${mainDef.description.replace(/\{[^}]*\}/g, (m: string) => `\`${m}\``)}\n\n`; } const renderProperties = (props: any, required: Set = new Set()) => {