Skip to content

Commit ad649aa

Browse files
committed
Add flow, report, datasource, and API schemas
Introduced new Zod schemas for flow orchestration, analytics reports, external datasource connections, and API endpoint definitions. Updated the documentation and index exports to include these new modules, enhancing the protocol specification for business logic, analytics, integration, and system APIs.
1 parent a51efb5 commit ad649aa

File tree

6 files changed

+310
-1
lines changed

6 files changed

+310
-1
lines changed

.github/copilot-instructions.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
* **Props**: `name` (snake_case), `label`, `type`, `multiple` (Array support), `reference` (Target Object).
2626
* **Object (`src/data/object.zod.ts`)**:
2727
* **Props**: `name` (snake_case), `label`, `fields` (Map), `enable` (Capabilities: `trackHistory`, `apiEnabled`).
28-
* **Logic**: `validation.zod.ts` (Rules), `permission.zod.ts` (ACL), `workflow.zod.ts` (Automation).
28+
* **Flow (`src/data/flow.zod.ts`)**: Visual Logic Orchestration (`autolaunched`, `screen`, `schedule`).
29+
* **Logic**: `validation.zod.ts` (Rules), `permission.zod.ts` (ACL), `workflow.zod.ts` (State Machine).
2930

3031
### **B. UI PROTOCOL (`src/ui/*.zod.ts`)**
3132
*Presentation & Interaction*
@@ -37,12 +38,15 @@
3738
* **Navigation**: Structured Menu Tree (`ObjectNavItem`, `DashboardNavItem`).
3839
* **Branding**: Logo, Colors.
3940
* **Dashboard (`src/ui/dashboard.zod.ts`)**: Grid layout widgets.
41+
* **Report (`src/ui/report.zod.ts`)**: Analytics (`tabular`, `summary`, `matrix`, `chart`).
4042
* **Action (`src/ui/action.zod.ts`)**: Buttons, URL jumps, Screen Flows.
4143

4244
### **C. SYSTEM PROTOCOL (`src/system/*.zod.ts`)**
4345
*Runtime Configuration*
4446

4547
* **Manifest (`src/system/manifest.zod.ts`)**: Package definition (`objectstack.config.ts`).
48+
* **Datasource (`src/system/datasource.zod.ts`)**: External Data Connections (SQL, NoSQL, SaaS).
49+
* **API (`src/system/api.zod.ts`)**: REST/GraphQL Endpoint Definitions.
4650
* **Translation (`src/system/translation.zod.ts`)**: Internationalization (i18n).
4751

4852
---

packages/spec/src/data/flow.zod.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* Flow Node Types
5+
*/
6+
export const FlowNodeAction = z.enum([
7+
'start', // Trigger
8+
'end', // Return/Stop
9+
'decision', // If/Else logic
10+
'assignment', // Set Variable
11+
'loop', // For Each
12+
'create_record', // CRUD: Create
13+
'update_record', // CRUD: Update
14+
'delete_record', // CRUD: Delete
15+
'get_record', // CRUD: Get/Query
16+
'http_request', // Webhook/API Call
17+
'script', // Custom Script (JS/TS)
18+
'wait', // Delay/Sleep
19+
'subflow' // Call another flow
20+
]);
21+
22+
/**
23+
* Flow Variable Schema
24+
* Variables available within the flow execution context.
25+
*/
26+
export const FlowVariableSchema = z.object({
27+
name: z.string().describe('Variable name'),
28+
type: z.string().describe('Data type (text, number, boolean, object, list)'),
29+
isInput: z.boolean().default(false).describe('Is input parameter'),
30+
isOutput: z.boolean().default(false).describe('Is output parameter'),
31+
});
32+
33+
/**
34+
* Flow Node Schema
35+
* A single step in the visual logic graph.
36+
*/
37+
export const FlowNodeSchema = z.object({
38+
id: z.string().describe('Node unique ID'),
39+
type: FlowNodeAction.describe('Action type'),
40+
label: z.string().describe('Node label'),
41+
42+
/** Node Configuration Options (Specific to type) */
43+
config: z.record(z.any()).optional().describe('Node configuration'),
44+
45+
/** UI Position (for the canvas) */
46+
position: z.object({ x: z.number(), y: z.number() }).optional(),
47+
});
48+
49+
/**
50+
* Flow Edge Schema
51+
* Connections between nodes.
52+
*/
53+
export const FlowEdgeSchema = z.object({
54+
id: z.string().describe('Edge unique ID'),
55+
source: z.string().describe('Source Node ID'),
56+
target: z.string().describe('Target Node ID'),
57+
58+
/** Condition for this path (only for decision/branch nodes) */
59+
condition: z.string().optional().describe('Expression returning boolean used for branching'),
60+
61+
label: z.string().optional().describe('Label on the connector'),
62+
});
63+
64+
/**
65+
* Flow Schema
66+
* Visual Business Logic Orchestration.
67+
*/
68+
export const FlowSchema = z.object({
69+
/** Identity */
70+
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Machine name'),
71+
label: z.string().describe('Flow label'),
72+
description: z.string().optional(),
73+
74+
/** Trigger Type */
75+
type: z.enum(['autolaunched', 'record_change', 'schedule', 'screen', 'api']).describe('Flow type'),
76+
77+
/** Configuration Variables */
78+
variables: z.array(FlowVariableSchema).optional().describe('Flow variables'),
79+
80+
/** Graph Definition */
81+
nodes: z.array(FlowNodeSchema).describe('Flow nodes'),
82+
edges: z.array(FlowEdgeSchema).describe('Flow connections'),
83+
84+
/** Execution Config */
85+
active: z.boolean().default(false).describe('Is active'),
86+
runAs: z.enum(['system', 'user']).default('user').describe('Execution context'),
87+
});
88+
89+
export type Flow = z.infer<typeof FlowSchema>;
90+
export type FlowNode = z.infer<typeof FlowNodeSchema>;
91+
export type FlowEdge = z.infer<typeof FlowEdgeSchema>;

packages/spec/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@ export * from './data/object.zod';
1313
export * from './data/validation.zod';
1414
export * from './data/permission.zod';
1515
export * from './data/workflow.zod';
16+
export * from './data/flow.zod';
1617

1718
// UI Protocol (Layout, Navigation, Interaction)
1819
export * from './ui/app.zod';
1920
export * from './ui/view.zod';
2021
export * from './ui/dashboard.zod';
22+
export * from './ui/report.zod';
2123
export * from './ui/action.zod';
2224

2325
// System Protocol (Manifest, Runtime, Constants)
2426
export * from './system/manifest.zod';
27+
export * from './system/datasource.zod';
28+
export * from './system/api.zod';
2529
export * from './system/translation.zod';
2630
export * from './system/constants';
2731
export * from './system/types';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* HTTP Method Enum
5+
*/
6+
export const HttpMethod = z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']);
7+
8+
/**
9+
* Rate Limit Strategy
10+
*/
11+
export const RateLimitSchema = z.object({
12+
enabled: z.boolean().default(false),
13+
windowMs: z.number().default(60000).describe('Time window in milliseconds'),
14+
maxRequests: z.number().default(100).describe('Max requests per window'),
15+
});
16+
17+
/**
18+
* API Mapping Schema
19+
* Transform input/output data.
20+
*/
21+
export const ApiMappingSchema = z.object({
22+
source: z.string().describe('Source field/path'),
23+
target: z.string().describe('Target field/path'),
24+
transform: z.string().optional().describe('Transformation function name'),
25+
});
26+
27+
/**
28+
* API Endpoint Schema
29+
* Defines an external facing API contract.
30+
*/
31+
export const ApiEndpointSchema = z.object({
32+
/** Identity */
33+
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Unique endpoint ID'),
34+
path: z.string().regex(/^\//).describe('URL Path (e.g. /api/v1/customers)'),
35+
method: HttpMethod.describe('HTTP Method'),
36+
37+
/** Documentation */
38+
summary: z.string().optional(),
39+
description: z.string().optional(),
40+
41+
/** Execution Logic */
42+
type: z.enum(['flow', 'script', 'object_operation', 'proxy']).describe('Implementation type'),
43+
target: z.string().describe('Target Flow ID, Script Name, or Proxy URL'),
44+
45+
/** Logic Config */
46+
objectParams: z.object({
47+
object: z.string().optional(),
48+
operation: z.enum(['find', 'get', 'create', 'update', 'delete']).optional(),
49+
}).optional().describe('For object_operation type'),
50+
51+
/** Data Transformation */
52+
inputMapping: z.array(ApiMappingSchema).optional().describe('Map Request Body to Internal Params'),
53+
outputMapping: z.array(ApiMappingSchema).optional().describe('Map Internal Result to Response Body'),
54+
55+
/** Policies */
56+
authRequired: z.boolean().default(true).describe('Require authentication'),
57+
rateLimit: RateLimitSchema.optional().describe('Rate limiting policy'),
58+
cacheTtl: z.number().optional().describe('Response cache TTL in seconds'),
59+
});
60+
61+
export type ApiEndpoint = z.infer<typeof ApiEndpointSchema>;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* Driver Type Enum
5+
* Defines the underlying technology of the datasource.
6+
*/
7+
export const DriverType = z.enum([
8+
'postgres', 'mysql', 'sqlserver', 'oracle', 'sqlite', // SQL
9+
'mongo', 'redis', // NoSQL
10+
'excel', 'csv', 'airtable', // Spreadsheet / Low-code
11+
'rest_api', 'graphql', 'odata', // Web Services
12+
'salesforce', 'sap', 'workday' // Enterprise SaaS
13+
]);
14+
15+
/**
16+
* Datasource Capabilities Schema
17+
* Declares what this datasource naturally supports.
18+
* The ObjectQL engine uses this to determine what logic to push down
19+
* and what to compute in memory.
20+
*/
21+
export const DatasourceCapabilities = z.object({
22+
/** Can execute SQL-like joins natively? */
23+
joins: z.boolean().default(false),
24+
/** Can handle ACID transactions? */
25+
transactions: z.boolean().default(false),
26+
/** Can perform full-text search? */
27+
fullTextSearch: z.boolean().default(false),
28+
/** Can perform aggregation (group by, sum, avg)? */
29+
aggregation: z.boolean().default(false),
30+
/** Is scheme-less (needs schema inference)? */
31+
dynamicSchema: z.boolean().default(false),
32+
/** Is read-only? */
33+
readOnly: z.boolean().default(false),
34+
});
35+
36+
/**
37+
* Datasource Schema
38+
* Represents a connection to an external data store.
39+
*/
40+
export const DatasourceSchema = z.object({
41+
/** Machine Name */
42+
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Unique datasource identifier'),
43+
44+
/** Human Label */
45+
label: z.string().optional().describe('Display label'),
46+
47+
/** Driver */
48+
driver: DriverType.describe('Underlying driver type'),
49+
50+
/**
51+
* Connection Configuration
52+
* Specific to the driver (e.g., host, port, user, password, bucket, etc.)
53+
* Stored securely (passwords usually interpolated from ENV).
54+
*/
55+
config: z.record(z.any()).describe('Driver specific configuration'),
56+
57+
/**
58+
* Capability Overrides
59+
* Manually override what the driver claims to support.
60+
*/
61+
capabilities: DatasourceCapabilities.optional().describe('Capability overrides'),
62+
63+
/** Description */
64+
description: z.string().optional().describe('Internal description'),
65+
66+
/** Is enabled? */
67+
active: z.boolean().default(true).describe('Is datasource enabled'),
68+
});
69+
70+
export type Datasource = z.infer<typeof DatasourceSchema>;
71+
export type DatasourceConfig = z.infer<typeof DatasourceCapabilities>;

packages/spec/src/ui/report.zod.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* Report Type Enum
5+
*/
6+
export const ReportType = z.enum([
7+
'tabular', // Simple list
8+
'summary', // Grouped by row
9+
'matrix', // Grouped by row and column
10+
'joined' // Joined multiple blocks
11+
]);
12+
13+
/**
14+
* Report Column Schema
15+
*/
16+
export const ReportColumnSchema = z.object({
17+
field: z.string().describe('Field name'),
18+
label: z.string().optional().describe('Override label'),
19+
aggregate: z.enum(['sum', 'avg', 'max', 'min', 'count', 'unique']).optional().describe('Aggregation function'),
20+
});
21+
22+
/**
23+
* Report Grouping Schema
24+
*/
25+
export const ReportGroupingSchema = z.object({
26+
field: z.string().describe('Field to group by'),
27+
sortOrder: z.enum(['asc', 'desc']).default('asc'),
28+
dateGranularity: z.enum(['day', 'week', 'month', 'quarter', 'year']).optional().describe('For date fields'),
29+
});
30+
31+
/**
32+
* Report Chart Schema
33+
* Embedded visualization configuration.
34+
*/
35+
export const ReportChartSchema = z.object({
36+
type: z.enum(['bar', 'column', 'line', 'pie', 'donut', 'scatter', 'funnel']).describe('Chart type'),
37+
title: z.string().optional(),
38+
showLegend: z.boolean().default(true),
39+
xAxis: z.string().describe('Grouping field for X-Axis'),
40+
yAxis: z.string().describe('Summary field for Y-Axis'),
41+
});
42+
43+
/**
44+
* Report Schema
45+
* Deep data analysis definition.
46+
*/
47+
export const ReportSchema = z.object({
48+
/** Identity */
49+
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Report unique name'),
50+
label: z.string().describe('Report label'),
51+
description: z.string().optional(),
52+
53+
/** Data Source */
54+
objectName: z.string().describe('Primary object'),
55+
56+
/** Report Configuration */
57+
type: ReportType.default('tabular').describe('Report format type'),
58+
59+
columns: z.array(ReportColumnSchema).describe('Columns to display'),
60+
61+
/** Grouping (for Summary/Matrix) */
62+
groupingsDown: z.array(ReportGroupingSchema).optional().describe('Row groupings'),
63+
groupingsAcross: z.array(ReportGroupingSchema).optional().describe('Column groupings (Matrix only)'),
64+
65+
/** Filtering */
66+
filter: z.string().optional().describe('Filter logic (e.g. "1 AND (2 OR 3)")'),
67+
filterItems: z.array(z.object({
68+
id: z.number(),
69+
field: z.string(),
70+
operator: z.string(),
71+
value: z.any()
72+
})).optional().describe('Filter criteria lines'),
73+
74+
/** Visualization */
75+
chart: ReportChartSchema.optional().describe('Embedded chart configuration'),
76+
});
77+
78+
export type Report = z.infer<typeof ReportSchema>;

0 commit comments

Comments
 (0)