diff --git a/examples/ai-analyst/src/ai-config.d.ts b/examples/ai-analyst/src/ai-config.d.ts index 5fcb5be..9bbe760 100644 --- a/examples/ai-analyst/src/ai-config.d.ts +++ b/examples/ai-analyst/src/ai-config.d.ts @@ -1,4 +1,4 @@ -import type { Agent, NLQModelConfig, QueryTemplate } from '@objectstack/spec'; +import type { Agent, NLQModelConfig, QueryTemplate } from '@objectstack/spec/ai'; /** * AI Data Analyst Agent */ diff --git a/examples/ai-analyst/src/ai-config.ts b/examples/ai-analyst/src/ai-config.ts index 85ff549..d1337ad 100644 --- a/examples/ai-analyst/src/ai-config.ts +++ b/examples/ai-analyst/src/ai-config.ts @@ -1,4 +1,4 @@ -import type { Agent, NLQModelConfig, QueryTemplate } from '@objectstack/spec'; +import type { Agent, NLQModelConfig, QueryTemplate } from '@objectstack/spec/ai'; /** * AI Data Analyst Agent diff --git a/examples/ai-codegen/src/ai-config.d.ts b/examples/ai-codegen/src/ai-config.d.ts index a316695..0a29405 100644 --- a/examples/ai-codegen/src/ai-config.d.ts +++ b/examples/ai-codegen/src/ai-config.d.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec'; +import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec/ai'; /** * ObjectStack Code Generator Agent */ diff --git a/examples/ai-codegen/src/ai-config.ts b/examples/ai-codegen/src/ai-config.ts index 393d74f..0942c5a 100644 --- a/examples/ai-codegen/src/ai-config.ts +++ b/examples/ai-codegen/src/ai-config.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec'; +import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec/ai'; /** * ObjectStack Code Generator Agent diff --git a/examples/ai-sales/src/ai-config.d.ts b/examples/ai-sales/src/ai-config.d.ts index b6dcb56..eec98d7 100644 --- a/examples/ai-sales/src/ai-config.d.ts +++ b/examples/ai-sales/src/ai-config.d.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec'; +import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec/ai'; /** * AI Sales Assistant Agent */ diff --git a/examples/ai-sales/src/ai-config.ts b/examples/ai-sales/src/ai-config.ts index 096ae59..0478a91 100644 --- a/examples/ai-sales/src/ai-config.ts +++ b/examples/ai-sales/src/ai-config.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec'; +import type { Agent, ModelRegistry, RAGPipelineConfig } from '@objectstack/spec/ai'; /** * AI Sales Assistant Agent diff --git a/examples/ai-support/src/ai-config.d.ts b/examples/ai-support/src/ai-config.d.ts index 156d6ff..3c4ee47 100644 --- a/examples/ai-support/src/ai-config.d.ts +++ b/examples/ai-support/src/ai-config.d.ts @@ -1,4 +1,4 @@ -import type { Agent, ModelRegistry, RAGPipelineConfig, FieldSynonymConfig } from '@objectstack/spec'; +import type { Agent, ModelRegistry, RAGPipelineConfig, FieldSynonymConfig } from '@objectstack/spec/ai'; /** * AI Support Assistant - Agent Configuration */ diff --git a/examples/ai-support/src/ai-config.ts b/examples/ai-support/src/ai-config.ts index d2d2af6..1681f57 100644 --- a/examples/ai-support/src/ai-config.ts +++ b/examples/ai-support/src/ai-config.ts @@ -3,7 +3,7 @@ import type { ModelRegistry, RAGPipelineConfig, FieldSynonymConfig, -} from '@objectstack/spec'; +} from '@objectstack/spec/ai'; /** * AI Support Assistant - Agent Configuration diff --git a/examples/crm/objectstack.config.ts b/examples/crm/objectstack.config.ts index ecd5b06..a8cd5f9 100644 --- a/examples/crm/objectstack.config.ts +++ b/examples/crm/objectstack.config.ts @@ -1,4 +1,4 @@ -import { App } from '@objectstack/spec'; +import { App } from '@objectstack/spec/ui'; import { Account } from './src/domains/crm/account.object'; import { Contact } from './src/domains/crm/contact.object'; import { Opportunity } from './src/domains/crm/opportunity.object'; diff --git a/examples/crm/src/domains/crm/account.object.ts b/examples/crm/src/domains/crm/account.object.ts index 5e0f7a2..0a2e093 100644 --- a/examples/crm/src/domains/crm/account.object.ts +++ b/examples/crm/src/domains/crm/account.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Account = ObjectSchema.create({ name: 'account', diff --git a/examples/crm/src/domains/crm/case.object.ts b/examples/crm/src/domains/crm/case.object.ts index 8ca50b7..1823f8d 100644 --- a/examples/crm/src/domains/crm/case.object.ts +++ b/examples/crm/src/domains/crm/case.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Case = ObjectSchema.create({ name: 'case', diff --git a/examples/crm/src/domains/crm/contact.object.ts b/examples/crm/src/domains/crm/contact.object.ts index 1e52061..81b1c99 100644 --- a/examples/crm/src/domains/crm/contact.object.ts +++ b/examples/crm/src/domains/crm/contact.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Contact = ObjectSchema.create({ name: 'contact', diff --git a/examples/crm/src/domains/crm/lead.object.ts b/examples/crm/src/domains/crm/lead.object.ts index 3a6fde9..ef99b78 100644 --- a/examples/crm/src/domains/crm/lead.object.ts +++ b/examples/crm/src/domains/crm/lead.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Lead = ObjectSchema.create({ name: 'lead', diff --git a/examples/crm/src/domains/crm/opportunity.object.ts b/examples/crm/src/domains/crm/opportunity.object.ts index b766feb..e1b01bc 100644 --- a/examples/crm/src/domains/crm/opportunity.object.ts +++ b/examples/crm/src/domains/crm/opportunity.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Opportunity = ObjectSchema.create({ name: 'opportunity', diff --git a/examples/crm/src/domains/crm/task.object.ts b/examples/crm/src/domains/crm/task.object.ts index e59b133..a93a404 100644 --- a/examples/crm/src/domains/crm/task.object.ts +++ b/examples/crm/src/domains/crm/task.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const Task = ObjectSchema.create({ name: 'task', diff --git a/examples/crm/src/server/apis.ts b/examples/crm/src/server/apis.ts index 0d1b61b..2b8df33 100644 --- a/examples/crm/src/server/apis.ts +++ b/examples/crm/src/server/apis.ts @@ -1,4 +1,4 @@ -import { ApiEndpoint } from '@objectstack/spec'; +import { ApiEndpoint } from '@objectstack/spec/system'; /** * Custom API: Close Won Opportunities diff --git a/examples/crm/src/ui/actions.d.ts b/examples/crm/src/ui/actions.d.ts index 5648ef4..6e84924 100644 --- a/examples/crm/src/ui/actions.d.ts +++ b/examples/crm/src/ui/actions.d.ts @@ -1,4 +1,4 @@ -import type { Action } from '@objectstack/spec'; +import type { Action } from '@objectstack/spec/ui'; export declare const ConvertLeadAction: Action; export declare const CloneOpportunityAction: Action; export declare const MarkPrimaryContactAction: Action; diff --git a/examples/crm/src/ui/actions.ts b/examples/crm/src/ui/actions.ts index fb13308..1e595ac 100644 --- a/examples/crm/src/ui/actions.ts +++ b/examples/crm/src/ui/actions.ts @@ -1,4 +1,4 @@ -import type { Action } from '@objectstack/spec'; +import type { Action } from '@objectstack/spec/ui'; // Convert Lead to Account, Contact, and Opportunity export const ConvertLeadAction: Action = { diff --git a/examples/crm/src/ui/dashboards.d.ts b/examples/crm/src/ui/dashboards.d.ts index 9b57c4d..b936879 100644 --- a/examples/crm/src/ui/dashboards.d.ts +++ b/examples/crm/src/ui/dashboards.d.ts @@ -1,4 +1,4 @@ -import type { Dashboard } from '@objectstack/spec'; +import type { Dashboard } from '@objectstack/spec/ui'; export declare const SalesDashboard: Dashboard; export declare const ServiceDashboard: Dashboard; export declare const ExecutiveDashboard: Dashboard; diff --git a/examples/crm/src/ui/dashboards.ts b/examples/crm/src/ui/dashboards.ts index 78c594c..647c92c 100644 --- a/examples/crm/src/ui/dashboards.ts +++ b/examples/crm/src/ui/dashboards.ts @@ -1,4 +1,4 @@ -import type { Dashboard } from '@objectstack/spec'; +import type { Dashboard } from '@objectstack/spec/ui'; // Sales Performance Dashboard export const SalesDashboard: Dashboard = { diff --git a/examples/crm/src/ui/reports.d.ts b/examples/crm/src/ui/reports.d.ts index 7a14011..0888e31 100644 --- a/examples/crm/src/ui/reports.d.ts +++ b/examples/crm/src/ui/reports.d.ts @@ -1,4 +1,4 @@ -import type { Report } from '@objectstack/spec'; +import type { Report } from '@objectstack/spec/ui'; export declare const OpportunitiesByStageReport: Report; export declare const WonOpportunitiesByOwnerReport: Report; export declare const AccountsByIndustryTypeReport: Report; diff --git a/examples/crm/src/ui/reports.ts b/examples/crm/src/ui/reports.ts index b279577..dbf87d2 100644 --- a/examples/crm/src/ui/reports.ts +++ b/examples/crm/src/ui/reports.ts @@ -1,4 +1,4 @@ -import type { Report } from '@objectstack/spec'; +import type { Report } from '@objectstack/spec/ui'; // Sales Report - Opportunities by Stage export const OpportunitiesByStageReport: Report = { diff --git a/examples/plugin-bi/objectstack.config.d.ts b/examples/plugin-bi/objectstack.config.d.ts index f4b2baf..075d781 100644 --- a/examples/plugin-bi/objectstack.config.d.ts +++ b/examples/plugin-bi/objectstack.config.d.ts @@ -1,4 +1,4 @@ -import { ObjectStackManifest } from '@objectstack/spec'; +import { ObjectStackManifest } from '@objectstack/spec/system'; declare const BiPlugin: ObjectStackManifest; export default BiPlugin; //# sourceMappingURL=objectstack.config.d.ts.map \ No newline at end of file diff --git a/examples/plugin-bi/objectstack.config.ts b/examples/plugin-bi/objectstack.config.ts index 53d827d..0be1e50 100644 --- a/examples/plugin-bi/objectstack.config.ts +++ b/examples/plugin-bi/objectstack.config.ts @@ -1,4 +1,4 @@ -import { ObjectStackManifest } from '@objectstack/spec'; +import { ObjectStackManifest } from '@objectstack/spec/system'; const BiPlugin: ObjectStackManifest = { id: 'com.objectstack.bi', diff --git a/examples/plugin-bi/src/index.d.ts b/examples/plugin-bi/src/index.d.ts index 990dac3..cd0899c 100644 --- a/examples/plugin-bi/src/index.d.ts +++ b/examples/plugin-bi/src/index.d.ts @@ -1,4 +1,4 @@ -import { PluginDefinition } from '@objectstack/spec'; +import { PluginDefinition } from '@objectstack/spec/system'; export declare class BiEngine { constructor(); registerDataset(path: string): void; diff --git a/examples/plugin-bi/src/index.ts b/examples/plugin-bi/src/index.ts index 953c6f4..fee3010 100644 --- a/examples/plugin-bi/src/index.ts +++ b/examples/plugin-bi/src/index.ts @@ -1,4 +1,4 @@ -import { PluginDefinition, PluginContextData } from '@objectstack/spec'; +import { PluginDefinition, PluginContextData } from '@objectstack/spec/system'; export class BiEngine { constructor() { diff --git a/examples/todo/objectstack.config.ts b/examples/todo/objectstack.config.ts index 210fe86..6a22a47 100644 --- a/examples/todo/objectstack.config.ts +++ b/examples/todo/objectstack.config.ts @@ -1,4 +1,4 @@ -import { App } from '@objectstack/spec'; +import { App } from '@objectstack/spec/ui'; import { TodoTask } from './src/domains/todo/task.object'; export default App.create({ diff --git a/examples/todo/src/domains/todo/task.object.ts b/examples/todo/src/domains/todo/task.object.ts index 4463796..3e3cfc8 100644 --- a/examples/todo/src/domains/todo/task.object.ts +++ b/examples/todo/src/domains/todo/task.object.ts @@ -1,4 +1,4 @@ -import { ObjectSchema, Field } from '@objectstack/spec'; +import { ObjectSchema, Field } from '@objectstack/spec/data'; export const TodoTask = ObjectSchema.create({ name: 'todo_task', diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index dc010de..3c9bc17 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -1,4 +1,4 @@ -import { QueryAST, FilterNode, SortNode, AggregationNode, WindowFunctionNode } from '@objectstack/spec'; +import { QueryAST, FilterNode, SortNode, AggregationNode, WindowFunctionNode } from '@objectstack/spec/data'; export interface ClientConfig { baseUrl: string; diff --git a/packages/driver-memory/objectstack.config.ts b/packages/driver-memory/objectstack.config.ts index ab03e35..05df663 100644 --- a/packages/driver-memory/objectstack.config.ts +++ b/packages/driver-memory/objectstack.config.ts @@ -1,4 +1,4 @@ -import { ObjectStackManifest } from '@objectstack/spec'; +import { ObjectStackManifest } from '@objectstack/spec/system'; const MemoryDriverPlugin: ObjectStackManifest = { id: 'com.objectstack.driver.memory', diff --git a/packages/driver-memory/src/memory-driver.ts b/packages/driver-memory/src/memory-driver.ts index 4f8c75e..43fcedc 100644 --- a/packages/driver-memory/src/memory-driver.ts +++ b/packages/driver-memory/src/memory-driver.ts @@ -1,9 +1,5 @@ -import { - DriverInterface, - DriverOptions, - QueryAST, - QueryInput -} from '@objectstack/spec'; +import { QueryAST, QueryInput } from '@objectstack/spec/data'; +import { DriverInterface, DriverOptions } from '@objectstack/spec/system'; /** * Example: In-Memory Driver diff --git a/packages/objectql/src/index.ts b/packages/objectql/src/index.ts index 75d6365..cc47fed 100644 --- a/packages/objectql/src/index.ts +++ b/packages/objectql/src/index.ts @@ -1,4 +1,5 @@ -import { DriverInterface, DriverOptions, QueryAST, ObjectStackManifest } from '@objectstack/spec'; +import { QueryAST } from '@objectstack/spec/data'; +import { DriverInterface, DriverOptions, ObjectStackManifest } from '@objectstack/spec/system'; import { SchemaRegistry } from './registry'; // Export Registry for consumers diff --git a/packages/objectql/src/registry.ts b/packages/objectql/src/registry.ts index da828d9..099e4b3 100644 --- a/packages/objectql/src/registry.ts +++ b/packages/objectql/src/registry.ts @@ -1,4 +1,6 @@ -import { ServiceObject, App, ObjectStackManifest } from '@objectstack/spec'; +import { ServiceObject } from '@objectstack/spec/data'; +import { App } from '@objectstack/spec/ui'; +import { ObjectStackManifest } from '@objectstack/spec/system'; /** * Global Schema Registry diff --git a/packages/runtime/src/kernel.ts b/packages/runtime/src/kernel.ts index e8a202d..0d0b4ef 100644 --- a/packages/runtime/src/kernel.ts +++ b/packages/runtime/src/kernel.ts @@ -1,4 +1,4 @@ -import { ServiceObject } from '@objectstack/spec'; +import { ServiceObject } from '@objectstack/spec/data'; import { SchemaRegistry, ObjectQL } from '@objectstack/objectql'; /** diff --git a/packages/spec/README.md b/packages/spec/README.md index 28e4de1..d49b0a2 100644 --- a/packages/spec/README.md +++ b/packages/spec/README.md @@ -44,12 +44,115 @@ The specification is divided into three protocols: ## 📚 Usage +### Import Styles + +**Important:** This package does NOT export types at the root level to prevent naming conflicts. You must use one of the following import styles: + +#### 1. Namespace Imports from Root + +Import protocol namespaces from the package root: + +```typescript +import { Data, UI, System, AI, API } from '@objectstack/spec'; + +const field: Data.Field = { + name: 'task_name', + type: 'text', + label: 'Task Name', +}; + +const user: System.User = { + id: 'user_123', + email: 'user@example.com', + // ... +}; + +const agent: AI.Agent = { + name: 'sales_assistant', + // ... +}; +``` + +**Pros:** +- Single import line for multiple protocols +- Clear namespace boundaries +- No naming conflicts + +#### 2. Namespace Imports via Subpath + +Import protocol domains individually: + +```typescript +import * as Data from '@objectstack/spec/data'; +import * as UI from '@objectstack/spec/ui'; +import * as System from '@objectstack/spec/system'; +import * as AI from '@objectstack/spec/ai'; +import * as API from '@objectstack/spec/api'; + +const field: Data.Field = { + name: 'task_name', + type: 'text', + label: 'Task Name', +}; + +const user: System.User = { + id: 'user_123', + email: 'user@example.com', + // ... +}; +``` + +**Pros:** +- Explicit about which protocols are used +- Better tree-shaking (only imports needed protocols) +- Clear namespace boundaries + +#### 3. Direct Subpath Imports + +Import specific types from subpaths: + +```typescript +import { Field, FieldType, ObjectSchema } from '@objectstack/spec/data'; +import { User, Session } from '@objectstack/spec/system'; +import { App, View } from '@objectstack/spec/ui'; + +const field: Field = { + name: 'task_name', + type: 'text', + label: 'Task Name', +}; + +const user: User = { + id: 'user_123', + email: 'user@example.com', + // ... +}; +``` + +**Pros:** +- Most concise syntax +- Good for importing specific types +- No namespace prefix needed + +**Cons:** +- Need to know which subpath contains each type +- Multiple import statements for different protocols + ### Validation (Runtime) ```typescript -import { ObjectSchema } from '@objectstack/spec'; +// Style 1: Namespace from root +import { Data } from '@objectstack/spec'; +const result = Data.ObjectSchema.safeParse(userConfig); + +// Style 2: Namespace via subpath +import * as Data from '@objectstack/spec/data'; +const result = Data.ObjectSchema.safeParse(userConfig); +// Style 3: Direct subpath import +import { ObjectSchema } from '@objectstack/spec/data'; const result = ObjectSchema.safeParse(userConfig); + if (!result.success) { console.error("Invalid Object definition", result.error); } @@ -58,14 +161,33 @@ if (!result.success) { ### Type Definitions (Compile Time) ```typescript -import type { Object, Field } from '@objectstack/spec'; +// Style 1: Namespace from root +import type { Data } from '@objectstack/spec'; +const myField: Data.Field = { + name: "task_name", + type: "text", + label: "Task Name" +}; -const myObject: Object = { - name: "project_task", - fields: { ... } +// Style 2: Direct subpath import +import type { Field } from '@objectstack/spec/data'; +const myField: Field = { + name: "task_name", + type: "text", + label: "Task Name" }; ``` +Using namespace imports for multiple protocols: + +```typescript +import type * as Data from '@objectstack/spec/data'; +import type * as System from '@objectstack/spec/system'; + +const field: Data.Field = { /* ... */ }; +const user: System.User = { /* ... */ }; +``` + ### JSON Schema (Tooling) The package includes valid JSON Schemas in the `/json-schema` directory. These can be used with: diff --git a/packages/spec/examples/README.md b/packages/spec/examples/README.md new file mode 100644 index 0000000..1b358d6 --- /dev/null +++ b/packages/spec/examples/README.md @@ -0,0 +1,34 @@ +# Examples + +This directory contains example code demonstrating how to use the `@objectstack/spec` package. + +## Files + +- **namespaced-imports.example.ts** - Demonstrates both flat and namespaced import styles + +## Running Examples + +These examples are for reference only. They demonstrate the TypeScript API but are not executable as standalone files. + +To use these patterns in your own code: + +1. Install the package: + ```bash + npm install @objectstack/spec + ``` + +2. Import using your preferred style: + ```typescript + // Flat imports + import { Field, User } from '@objectstack/spec'; + + // Namespaced imports + import * as Data from '@objectstack/spec/data'; + import * as System from '@objectstack/spec/system'; + ``` + +3. See the main [README.md](../README.md) for more usage examples. + +## Contributing + +If you have useful examples to add, please submit a PR! diff --git a/packages/spec/examples/namespaced-imports.example.ts b/packages/spec/examples/namespaced-imports.example.ts new file mode 100644 index 0000000..f2cdfd6 --- /dev/null +++ b/packages/spec/examples/namespaced-imports.example.ts @@ -0,0 +1,180 @@ +/** + * Example: Using Namespaced Imports + * + * This example demonstrates the three import styles supported by @objectstack/spec. + * Note: Flat imports are NO LONGER SUPPORTED. Use one of the styles below. + */ + +// ============================================================================ +// STYLE 1: Namespace Imports from Root +// ============================================================================ + +import { Data, UI, System, AI } from '@objectstack/spec'; + +// Use with namespace prefix +const field1: Data.Field = { + name: 'employee_name', + label: 'Employee Name', + type: 'text' as Data.FieldType, + required: true, +}; + +// ============================================================================ +// STYLE 2: Namespace Imports via Subpath +// ============================================================================ + +import * as DataNS from '@objectstack/spec/data'; +import * as UINS from '@objectstack/spec/ui'; +import * as SystemNS from '@objectstack/spec/system'; +import * as AINS from '@objectstack/spec/ai'; + +// Use with namespace prefix for clarity +const field2: DataNS.Field = { + name: 'task_title', + label: 'Task Title', + type: 'text' as DataNS.FieldType, + required: true, +}; + +// ============================================================================ +// STYLE 3: Direct Subpath Imports +// ============================================================================ + +import { Field, FieldType, ObjectSchema, ServiceObject } from '@objectstack/spec/data'; +import { View } from '@objectstack/spec/ui'; +import { User } from '@objectstack/spec/system'; +import { Agent, ModelProvider } from '@objectstack/spec/ai'; + +// Use directly without namespace prefix +const field3: Field = { + name: 'task_description', + label: 'Task Description', + type: 'textarea' as FieldType, + required: false, +}; + +// Define an object using direct imports +const taskObject: ServiceObject = { + name: 'project_task', + label: 'Task', + fields: { + title: field3, + description: { + name: 'description', + label: 'Description', + type: 'textarea' as FieldType, + }, + status: { + name: 'status', + label: 'Status', + type: 'select' as FieldType, + options: [ + { value: 'todo', label: 'To Do' }, + { value: 'in_progress', label: 'In Progress' }, + { value: 'done', label: 'Done' }, + ], + }, + assignee: { + name: 'assignee', + label: 'Assignee', + type: 'lookup' as FieldType, + reference: 'system_user', + }, + }, +}; + +// Validate using direct import +const result = ObjectSchema.safeParse(taskObject); + +if (result.success) { + console.log('✓ Object definition is valid'); +} else { + console.error('✗ Validation errors:', result.error); +} + +// Define UI components using direct imports +const taskView: View = { + name: 'task_list', + label: 'Task List', + object: 'project_task', + type: 'list', + listView: { + type: 'grid', + columns: ['title', 'status', 'assignee'], + defaultSort: [{ field: 'created_at', direction: 'desc' }], + }, +}; + +// Define system configuration using direct imports +const adminUser: User = { + id: 'user_admin_001', + email: 'admin@example.com', + name: 'System Admin', + emailVerified: new Date(), + image: null, + createdAt: new Date(), + updatedAt: new Date(), +}; + +// Define AI agent using direct imports +const salesAgent: Agent = { + name: 'sales_assistant', + label: 'Sales Assistant', + description: 'AI agent to help with sales tasks', + model: { + provider: 'openai' as ModelProvider, + name: 'gpt-4', + }, + tools: [], + knowledge: [], + instructions: 'You are a helpful sales assistant.', +}; + +// ============================================================================ +// COMPARISON OF THE THREE STYLES +// ============================================================================ + +/** + * Style 1: Namespace from Root + * - Pro: Single import line for multiple protocols + * - Pro: Clear namespace boundaries + * - Con: Longer variable type declarations + * + * Style 2: Namespace via Subpath + * - Pro: Better tree-shaking + * - Pro: Explicit about which protocols are used + * - Con: Multiple import lines + * + * Style 3: Direct Subpath Imports + * - Pro: Most concise syntax + * - Pro: No namespace prefix needed + * - Con: Need to know which subpath contains each type + * + * BENEFITS ACROSS ALL STYLES: + * + * 1. Zero Naming Conflicts + * - Namespace boundaries completely eliminate collision risk + * - Safe to add new types without worrying about conflicts + * + * 2. Clear Domain Boundaries + * - Immediately obvious which protocol a type belongs to + * - Easier to navigate and understand the codebase + * + * 3. Better IDE Autocomplete + * - Type "Data." and see all data protocol types + * - Discover related types within a namespace + * + * 4. Self-Documenting Code + * - Reading "System.User" is clearer than just "User" + * - Helps new developers understand the architecture + */ + +export { + field1, + field2, + taskObject, + taskView, + adminUser, + salesAgent, + result, +}; diff --git a/packages/spec/package.json b/packages/spec/package.json index 1f8395e..1db0a5f 100644 --- a/packages/spec/package.json +++ b/packages/spec/package.json @@ -4,6 +4,32 @@ "description": "ObjectStack Protocol & Specification - TypeScript Interfaces, JSON Schemas, and Convention Configurations", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./data": { + "types": "./dist/data/index.d.ts", + "default": "./dist/data/index.js" + }, + "./ui": { + "types": "./dist/ui/index.d.ts", + "default": "./dist/ui/index.js" + }, + "./system": { + "types": "./dist/system/index.d.ts", + "default": "./dist/system/index.js" + }, + "./ai": { + "types": "./dist/ai/index.d.ts", + "default": "./dist/ai/index.js" + }, + "./api": { + "types": "./dist/api/index.d.ts", + "default": "./dist/api/index.js" + } + }, "files": [ "dist", "json-schema", diff --git a/packages/spec/scripts/build-schemas.ts b/packages/spec/scripts/build-schemas.ts index f345638..755beec 100644 --- a/packages/spec/scripts/build-schemas.ts +++ b/packages/spec/scripts/build-schemas.ts @@ -15,25 +15,30 @@ console.log(`Generating JSON Schemas to ${OUT_DIR}...`); let count = 0; -// Iterate over all exports in the protocol -for (const [key, value] of Object.entries(Protocol)) { - // Check if it looks like a Zod Schema - // Zod schemas usually have a parse method and safeParse method, or we can check instanceof - if (value instanceof z.ZodType) { - const schemaName = key.endsWith('Schema') ? key.replace('Schema', '') : key; - - // Convert to JSON Schema - const jsonSchema = zodToJsonSchema(value, { - name: schemaName, - $refStrategy: "none" // We want self-contained schemas for now, or use 'relative' if we handle refs - }); - - const fileName = `${schemaName}.json`; - const filePath = path.join(OUT_DIR, fileName); - - fs.writeFileSync(filePath, JSON.stringify(jsonSchema, null, 2)); - console.log(`✓ ${fileName}`); - count++; +// Protocol now exports namespaces (Data, UI, System, AI, API) +// We need to iterate through each namespace +for (const [_namespaceName, namespaceExports] of Object.entries(Protocol)) { + if (typeof namespaceExports === 'object' && namespaceExports !== null) { + // Iterate over all exports in each namespace + for (const [key, value] of Object.entries(namespaceExports)) { + // Check if it looks like a Zod Schema + if (value instanceof z.ZodType) { + const schemaName = key.endsWith('Schema') ? key.replace('Schema', '') : key; + + // Convert to JSON Schema + const jsonSchema = zodToJsonSchema(value, { + name: schemaName, + $refStrategy: "none" // We want self-contained schemas for now + }); + + const fileName = `${schemaName}.json`; + const filePath = path.join(OUT_DIR, fileName); + + fs.writeFileSync(filePath, JSON.stringify(jsonSchema, null, 2)); + console.log(`✓ ${fileName}`); + count++; + } + } } } diff --git a/packages/spec/src/ai/index.ts b/packages/spec/src/ai/index.ts new file mode 100644 index 0000000..6faa104 --- /dev/null +++ b/packages/spec/src/ai/index.ts @@ -0,0 +1,14 @@ +/** + * AI Protocol Exports + * + * AI/ML Capabilities + * - Agent Configuration + * - Model Registry & Selection + * - RAG Pipeline + * - Natural Language Query (NLQ) + */ + +export * from './agent.zod'; +export * from './model-registry.zod'; +export * from './rag-pipeline.zod'; +export * from './nlq.zod'; diff --git a/packages/spec/src/api/index.ts b/packages/spec/src/api/index.ts new file mode 100644 index 0000000..aa5b3c2 --- /dev/null +++ b/packages/spec/src/api/index.ts @@ -0,0 +1,9 @@ +/** + * API Protocol Exports + * + * API Contracts & Envelopes + * - Request/Response schemas + * - Error handling + */ + +export * from './contract.zod'; diff --git a/packages/spec/src/data/index.ts b/packages/spec/src/data/index.ts new file mode 100644 index 0000000..4fcc54f --- /dev/null +++ b/packages/spec/src/data/index.ts @@ -0,0 +1,21 @@ +/** + * Data Protocol Exports + * + * Core Business Logic & Data Modeling + * - Object, Field, Validation + * - Query (AST), Mapping (ETL) + * - Permission, Sharing, Flow + */ + +export * from './field.zod'; +export * from './object.zod'; +export * from './validation.zod'; +export * from './permission.zod'; +export * from './sharing.zod'; +export * from './workflow.zod'; +export * from './flow.zod'; +export * from './dataset.zod'; +export * from './query.zod'; +export * from './filter.zod'; +export * from './mapping.zod'; +export * from './trigger.zod'; diff --git a/packages/spec/src/index.ts b/packages/spec/src/index.ts index 8c0479c..8042653 100644 --- a/packages/spec/src/index.ts +++ b/packages/spec/src/index.ts @@ -3,61 +3,48 @@ * * ObjectStack Protocol & Specification * - * This package contains the core interfaces, schemas, and conventions for the ObjectStack ecosystem. - * All types and schemas are centralized here. + * This package does NOT export types at the root level to prevent naming conflicts. + * Please use namespaced imports or subpath imports. + * + * ## Import Styles + * + * ### Style 1: Namespace Imports from Root + * ```typescript + * import { Data, UI, System, AI, API } from '@objectstack/spec'; + * + * const field: Data.Field = { name: 'task_name', type: 'text' }; + * const user: System.User = { id: 'u1', email: 'user@example.com' }; + * ``` + * + * ### Style 2: Namespace Imports via Subpath + * ```typescript + * import * as Data from '@objectstack/spec/data'; + * import * as UI from '@objectstack/spec/ui'; + * import * as System from '@objectstack/spec/system'; + * + * const field: Data.Field = { name: 'task_name', type: 'text' }; + * const user: System.User = { id: 'u1', email: 'user@example.com' }; + * ``` + * + * ### Style 3: Direct Subpath Imports + * ```typescript + * import { Field, FieldType } from '@objectstack/spec/data'; + * import { User, Session } from '@objectstack/spec/system'; + * + * const field: Field = { name: 'task_name', type: 'text' }; + * const user: User = { id: 'u1', email: 'user@example.com' }; + * ``` */ -// Data Protocol (Schema, Validation, Logic) -export * from './data/field.zod'; -export * from './data/object.zod'; -export * from './data/validation.zod'; -export * from './data/permission.zod'; -export * from './data/sharing.zod'; -export * from './data/workflow.zod'; -export * from './data/flow.zod'; -export * from './data/dataset.zod'; -export * from './data/query.zod'; -export * from './data/filter.zod'; // Unified Query DSL -export * from './data/mapping.zod'; -export * from './data/trigger.zod'; - -// API Protocol (Envelopes, Contracts) -export * from './api/contract.zod'; - -// AI Protocol (Agent, RAG, Model Registry, NLQ) -export * from './ai/agent.zod'; -export * from './ai/model-registry.zod'; -export * from './ai/rag-pipeline.zod'; -export * from './ai/nlq.zod'; - -// UI Protocol (Layout, Navigation, Interaction) -export * from './ui/app.zod'; -export * from './ui/view.zod'; -export * from './ui/dashboard.zod'; -export * from './ui/report.zod'; -export * from './ui/action.zod'; -export * from './ui/page.zod'; -export * from './ui/widget.zod'; -export * from './ui/theme.zod'; +// ============================================================================ +// NAMESPACE EXPORTS +// ============================================================================ +// Export protocol domains as namespaces to prevent naming conflicts +// and establish clear boundaries between different protocol layers. -// System Protocol (Manifest, Runtime, Constants) -export * from './system/manifest.zod'; -export * from './system/datasource.zod'; -export * from './system/api.zod'; -export * from './system/identity.zod'; // User, Account, Session models -export * from './system/auth.zod'; // Authentication configuration -export * from './system/auth-protocol'; // Authentication wire protocol & constants -export * from './system/organization.zod'; // Organization, Member, Invitation models -export * from './system/policy.zod'; -export * from './system/role.zod'; -export * from './system/territory.zod'; -export * from './system/license.zod'; -export * from './system/webhook.zod'; -export * from './system/translation.zod'; -export * from './system/driver.zod'; // Export Driver Protocol -export * from './system/constants'; -export * from './system/types'; -export * from './system/discovery.zod'; -export * from './system/plugin.zod'; -export * from './system/driver.zod'; +export * as Data from './data'; +export * as UI from './ui'; +export * as System from './system'; +export * as AI from './ai'; +export * as API from './api'; diff --git a/packages/spec/src/system/index.ts b/packages/spec/src/system/index.ts new file mode 100644 index 0000000..ecd9de8 --- /dev/null +++ b/packages/spec/src/system/index.ts @@ -0,0 +1,28 @@ +/** + * System Protocol Exports + * + * Runtime Configuration & Security + * - Manifest (Config), Datasource + * - Role (Hierarchy), Identity (Auth) + * - Webhook (Integration), Policy (Compliance) + * - Plugin Architecture + */ + +export * from './manifest.zod'; +export * from './datasource.zod'; +export * from './api.zod'; +export * from './identity.zod'; +export * from './auth.zod'; +export * from './auth-protocol'; +export * from './organization.zod'; +export * from './policy.zod'; +export * from './role.zod'; +export * from './territory.zod'; +export * from './license.zod'; +export * from './webhook.zod'; +export * from './translation.zod'; +export * from './driver.zod'; +export * from './discovery.zod'; +export * from './plugin.zod'; +export * from './constants'; +export * from './types'; diff --git a/packages/spec/src/ui/index.ts b/packages/spec/src/ui/index.ts new file mode 100644 index 0000000..446da59 --- /dev/null +++ b/packages/spec/src/ui/index.ts @@ -0,0 +1,17 @@ +/** + * UI Protocol Exports + * + * Presentation & Interaction + * - App, Page, View (Grid/Kanban) + * - Dashboard (Widgets), Report + * - Action (Triggers) + */ + +export * from './app.zod'; +export * from './view.zod'; +export * from './dashboard.zod'; +export * from './report.zod'; +export * from './action.zod'; +export * from './page.zod'; +export * from './widget.zod'; +export * from './theme.zod';