ont-run 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/ont.js +173 -5424
- package/dist/index.js +16310 -7663
- package/dist/src/config/categorical.d.ts +1 -2
- package/dist/src/config/define.d.ts +1 -1
- package/dist/src/config/schema.d.ts +20 -116
- package/dist/src/config/zod-utils.d.ts +48 -0
- package/package.json +7 -7
- package/src/browser/transform.ts +40 -17
- package/src/cli/commands/init.ts +10 -5
- package/src/config/categorical.ts +9 -9
- package/src/config/define.ts +3 -1
- package/src/config/schema.ts +68 -38
- package/src/config/zod-utils.ts +133 -0
- package/src/lockfile/hasher.ts +46 -22
- package/src/server/mcp/tools.ts +45 -22
|
@@ -132,7 +132,6 @@ export declare function hasUserContextMetadata(schema: unknown): schema is UserC
|
|
|
132
132
|
/**
|
|
133
133
|
* Get all userContext field names from a Zod object schema
|
|
134
134
|
*
|
|
135
|
-
* Note: Uses
|
|
136
|
-
* module boundaries in bundled CLI.
|
|
135
|
+
* Note: Uses zod-utils for bundler compatibility (instanceof fails across module boundaries)
|
|
137
136
|
*/
|
|
138
137
|
export declare function getUserContextFields(schema: z.ZodType): string[];
|
|
@@ -38,7 +38,7 @@ import type { OntologyConfig, FunctionDefinition, AccessGroupConfig, Environment
|
|
|
38
38
|
* });
|
|
39
39
|
* ```
|
|
40
40
|
*/
|
|
41
|
-
export declare function defineOntology<TGroups extends string, TEntities extends string, TFunctions extends Record<string, FunctionDefinition<TGroups, TEntities>>>(config: {
|
|
41
|
+
export declare function defineOntology<TGroups extends string, TEntities extends string, TFunctions extends Record<string, FunctionDefinition<TGroups, TEntities, any, any>>>(config: {
|
|
42
42
|
name: string;
|
|
43
43
|
environments: Record<string, EnvironmentConfig>;
|
|
44
44
|
auth: AuthFunction;
|
|
@@ -5,60 +5,30 @@ import type { OntologyConfig } from "./types.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const EnvironmentConfigSchema: z.ZodObject<{
|
|
7
7
|
debug: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
-
},
|
|
9
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
11
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
-
}, z.ZodTypeAny, "passthrough">>;
|
|
8
|
+
}, z.core.$loose>;
|
|
13
9
|
/**
|
|
14
10
|
* Schema for access group configuration
|
|
15
11
|
*/
|
|
16
12
|
export declare const AccessGroupConfigSchema: z.ZodObject<{
|
|
17
13
|
description: z.ZodString;
|
|
18
|
-
},
|
|
19
|
-
description: string;
|
|
20
|
-
}, {
|
|
21
|
-
description: string;
|
|
22
|
-
}>;
|
|
14
|
+
}, z.core.$strip>;
|
|
23
15
|
/**
|
|
24
16
|
* Schema for entity definition
|
|
25
17
|
*/
|
|
26
18
|
export declare const EntityDefinitionSchema: z.ZodObject<{
|
|
27
19
|
description: z.ZodString;
|
|
28
|
-
},
|
|
29
|
-
description: string;
|
|
30
|
-
}, {
|
|
31
|
-
description: string;
|
|
32
|
-
}>;
|
|
20
|
+
}, z.core.$strip>;
|
|
33
21
|
/**
|
|
34
22
|
* Schema for function definition
|
|
35
23
|
*/
|
|
36
24
|
export declare const FunctionDefinitionSchema: z.ZodObject<{
|
|
37
25
|
description: z.ZodString;
|
|
38
|
-
access: z.ZodArray<z.ZodString
|
|
39
|
-
entities: z.ZodArray<z.ZodString
|
|
40
|
-
inputs: z.
|
|
41
|
-
outputs: z.ZodOptional<z.
|
|
42
|
-
resolver: z.
|
|
43
|
-
},
|
|
44
|
-
description: string;
|
|
45
|
-
access: string[];
|
|
46
|
-
entities: string[];
|
|
47
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
48
|
-
resolver: (...args: unknown[]) => unknown;
|
|
49
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
50
|
-
}, {
|
|
51
|
-
description: string;
|
|
52
|
-
access: string[];
|
|
53
|
-
entities: string[];
|
|
54
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
55
|
-
resolver: (...args: unknown[]) => unknown;
|
|
56
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
57
|
-
}>;
|
|
58
|
-
/**
|
|
59
|
-
* Schema for auth function
|
|
60
|
-
*/
|
|
61
|
-
export declare const AuthFunctionSchema: z.ZodFunction<z.ZodTuple<[z.ZodType<Request, z.ZodTypeDef, Request>], z.ZodUnknown>, z.ZodUnion<[z.ZodArray<z.ZodString, "many">, z.ZodPromise<z.ZodArray<z.ZodString, "many">>]>>;
|
|
26
|
+
access: z.ZodArray<z.ZodString>;
|
|
27
|
+
entities: z.ZodArray<z.ZodString>;
|
|
28
|
+
inputs: z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
29
|
+
outputs: z.ZodOptional<z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
30
|
+
resolver: z.ZodCustom<(...args: unknown[]) => unknown, (...args: unknown[]) => unknown>;
|
|
31
|
+
}, z.core.$strip>;
|
|
62
32
|
/**
|
|
63
33
|
* Schema for the full ontology configuration
|
|
64
34
|
*/
|
|
@@ -66,89 +36,23 @@ export declare const OntologyConfigSchema: z.ZodObject<{
|
|
|
66
36
|
name: z.ZodString;
|
|
67
37
|
environments: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
68
38
|
debug: z.ZodOptional<z.ZodBoolean>;
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
72
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
73
|
-
}, z.ZodTypeAny, "passthrough">>>;
|
|
74
|
-
auth: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>;
|
|
39
|
+
}, z.core.$loose>>;
|
|
40
|
+
auth: z.ZodCustom<(req: Request) => unknown, (req: Request) => unknown>;
|
|
75
41
|
accessGroups: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
76
42
|
description: z.ZodString;
|
|
77
|
-
},
|
|
78
|
-
description: string;
|
|
79
|
-
}, {
|
|
80
|
-
description: string;
|
|
81
|
-
}>>;
|
|
43
|
+
}, z.core.$strip>>;
|
|
82
44
|
entities: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
83
45
|
description: z.ZodString;
|
|
84
|
-
},
|
|
85
|
-
description: string;
|
|
86
|
-
}, {
|
|
87
|
-
description: string;
|
|
88
|
-
}>>>;
|
|
46
|
+
}, z.core.$strip>>>;
|
|
89
47
|
functions: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
90
48
|
description: z.ZodString;
|
|
91
|
-
access: z.ZodArray<z.ZodString
|
|
92
|
-
entities: z.ZodArray<z.ZodString
|
|
93
|
-
inputs: z.
|
|
94
|
-
outputs: z.ZodOptional<z.
|
|
95
|
-
resolver: z.
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
access: string[];
|
|
99
|
-
entities: string[];
|
|
100
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
101
|
-
resolver: (...args: unknown[]) => unknown;
|
|
102
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
103
|
-
}, {
|
|
104
|
-
description: string;
|
|
105
|
-
access: string[];
|
|
106
|
-
entities: string[];
|
|
107
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
108
|
-
resolver: (...args: unknown[]) => unknown;
|
|
109
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
110
|
-
}>>;
|
|
111
|
-
}, "strip", z.ZodTypeAny, {
|
|
112
|
-
name: string;
|
|
113
|
-
environments: Record<string, z.objectOutputType<{
|
|
114
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
115
|
-
}, z.ZodTypeAny, "passthrough">>;
|
|
116
|
-
auth: (...args: unknown[]) => unknown;
|
|
117
|
-
accessGroups: Record<string, {
|
|
118
|
-
description: string;
|
|
119
|
-
}>;
|
|
120
|
-
functions: Record<string, {
|
|
121
|
-
description: string;
|
|
122
|
-
access: string[];
|
|
123
|
-
entities: string[];
|
|
124
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
125
|
-
resolver: (...args: unknown[]) => unknown;
|
|
126
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
127
|
-
}>;
|
|
128
|
-
entities?: Record<string, {
|
|
129
|
-
description: string;
|
|
130
|
-
}> | undefined;
|
|
131
|
-
}, {
|
|
132
|
-
name: string;
|
|
133
|
-
environments: Record<string, z.objectInputType<{
|
|
134
|
-
debug: z.ZodOptional<z.ZodBoolean>;
|
|
135
|
-
}, z.ZodTypeAny, "passthrough">>;
|
|
136
|
-
auth: (...args: unknown[]) => unknown;
|
|
137
|
-
accessGroups: Record<string, {
|
|
138
|
-
description: string;
|
|
139
|
-
}>;
|
|
140
|
-
functions: Record<string, {
|
|
141
|
-
description: string;
|
|
142
|
-
access: string[];
|
|
143
|
-
entities: string[];
|
|
144
|
-
inputs: z.ZodType<any, z.ZodTypeDef, any>;
|
|
145
|
-
resolver: (...args: unknown[]) => unknown;
|
|
146
|
-
outputs?: z.ZodType<any, z.ZodTypeDef, any> | undefined;
|
|
147
|
-
}>;
|
|
148
|
-
entities?: Record<string, {
|
|
149
|
-
description: string;
|
|
150
|
-
}> | undefined;
|
|
151
|
-
}>;
|
|
49
|
+
access: z.ZodArray<z.ZodString>;
|
|
50
|
+
entities: z.ZodArray<z.ZodString>;
|
|
51
|
+
inputs: z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
52
|
+
outputs: z.ZodOptional<z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
|
|
53
|
+
resolver: z.ZodCustom<(...args: unknown[]) => unknown, (...args: unknown[]) => unknown>;
|
|
54
|
+
}, z.core.$strip>>;
|
|
55
|
+
}, z.core.$strip>;
|
|
152
56
|
/**
|
|
153
57
|
* Validate that all function access groups exist in accessGroups
|
|
154
58
|
*/
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for inspecting Zod 4 schemas.
|
|
3
|
+
* These use duck typing to work across bundle boundaries.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if a value is a Zod 3 schema (has _def but not _zod)
|
|
7
|
+
*/
|
|
8
|
+
export declare function isZod3Schema(val: unknown): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a value is a Zod schema (duck typing to work across bundle boundaries)
|
|
11
|
+
*/
|
|
12
|
+
export declare function isZodSchema(val: unknown): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Get the Zod type name from a schema
|
|
15
|
+
*/
|
|
16
|
+
export declare function getZodTypeName(schema: unknown): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Check if schema is a ZodObject
|
|
19
|
+
*/
|
|
20
|
+
export declare function isZodObject(schema: unknown): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Check if schema is a ZodOptional
|
|
23
|
+
*/
|
|
24
|
+
export declare function isZodOptional(schema: unknown): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if schema is a ZodNullable
|
|
27
|
+
*/
|
|
28
|
+
export declare function isZodNullable(schema: unknown): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Check if schema is a ZodArray
|
|
31
|
+
*/
|
|
32
|
+
export declare function isZodArray(schema: unknown): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Check if schema is a ZodDefault
|
|
35
|
+
*/
|
|
36
|
+
export declare function isZodDefault(schema: unknown): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Get the shape of a ZodObject schema
|
|
39
|
+
*/
|
|
40
|
+
export declare function getObjectShape(schema: unknown): Record<string, unknown> | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Get the inner schema from Optional/Nullable/Default
|
|
43
|
+
*/
|
|
44
|
+
export declare function getInnerSchema(schema: unknown): unknown;
|
|
45
|
+
/**
|
|
46
|
+
* Get the element schema from a ZodArray
|
|
47
|
+
*/
|
|
48
|
+
export declare function getArrayElement(schema: unknown): unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ont-run",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Ontology-enforced API framework for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"dev": "bun run bin/ont.ts",
|
|
23
23
|
"build": "bun build ./src/index.ts --outdir ./dist --target node",
|
|
24
|
-
"build:cli": "bun build ./bin/ont.ts --outfile ./dist/bin/ont.js --target node --external @modelcontextprotocol/sdk",
|
|
24
|
+
"build:cli": "bun build ./bin/ont.ts --outfile ./dist/bin/ont.js --target node --external @modelcontextprotocol/sdk --external zod",
|
|
25
25
|
"build:types": "tsc --declaration --emitDeclarationOnly",
|
|
26
26
|
"prepublishOnly": "bun run build && bun run build:cli && bun run build:types",
|
|
27
27
|
"docs": "cd docs && bun run dev",
|
|
@@ -34,16 +34,16 @@
|
|
|
34
34
|
"citty": "^0.1.6",
|
|
35
35
|
"consola": "^3.2.0",
|
|
36
36
|
"hono": "^4.6.0",
|
|
37
|
-
"open": "^10.0.0"
|
|
38
|
-
"zod": "^3.24.0",
|
|
39
|
-
"zod-to-json-schema": "^3.23.0"
|
|
37
|
+
"open": "^10.0.0"
|
|
40
38
|
},
|
|
41
39
|
"devDependencies": {
|
|
42
40
|
"@types/bun": "latest",
|
|
43
|
-
"typescript": "^5.5.0"
|
|
41
|
+
"typescript": "^5.5.0",
|
|
42
|
+
"zod": "^4.0.0"
|
|
44
43
|
},
|
|
45
44
|
"peerDependencies": {
|
|
46
|
-
"bun": ">=1.0.0"
|
|
45
|
+
"bun": ">=1.0.0",
|
|
46
|
+
"zod": ">=4"
|
|
47
47
|
},
|
|
48
48
|
"peerDependenciesMeta": {
|
|
49
49
|
"bun": {
|
package/src/browser/transform.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
2
|
import type { OntologyConfig } from "../config/types.js";
|
|
4
3
|
import type { OntologyDiff, FunctionChange } from "../lockfile/types.js";
|
|
5
4
|
import { getFieldFromMetadata, getUserContextFields } from "../config/categorical.js";
|
|
5
|
+
import {
|
|
6
|
+
isZodObject,
|
|
7
|
+
isZodOptional,
|
|
8
|
+
isZodNullable,
|
|
9
|
+
isZodArray,
|
|
10
|
+
isZodDefault,
|
|
11
|
+
getObjectShape,
|
|
12
|
+
getInnerSchema,
|
|
13
|
+
getArrayElement,
|
|
14
|
+
} from "../config/zod-utils.js";
|
|
6
15
|
|
|
7
16
|
export type NodeType = "entity" | "function" | "accessGroup";
|
|
8
17
|
export type EdgeType = "operates-on" | "requires-access" | "depends-on";
|
|
@@ -80,30 +89,44 @@ function extractFieldReferences(
|
|
|
80
89
|
});
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
if (schema
|
|
84
|
-
const shape = schema
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
if (isZodObject(schema)) {
|
|
93
|
+
const shape = getObjectShape(schema);
|
|
94
|
+
if (shape) {
|
|
95
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
96
|
+
const fieldPath = path ? `${path}.${key}` : key;
|
|
97
|
+
results.push(
|
|
98
|
+
...extractFieldReferences(value as z.ZodType<unknown>, fieldPath)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
103
|
|
|
93
|
-
if (schema
|
|
94
|
-
|
|
104
|
+
if (isZodOptional(schema)) {
|
|
105
|
+
const inner = getInnerSchema(schema);
|
|
106
|
+
if (inner) {
|
|
107
|
+
results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
|
|
108
|
+
}
|
|
95
109
|
}
|
|
96
110
|
|
|
97
|
-
if (schema
|
|
98
|
-
|
|
111
|
+
if (isZodNullable(schema)) {
|
|
112
|
+
const inner = getInnerSchema(schema);
|
|
113
|
+
if (inner) {
|
|
114
|
+
results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
|
|
115
|
+
}
|
|
99
116
|
}
|
|
100
117
|
|
|
101
|
-
if (schema
|
|
102
|
-
|
|
118
|
+
if (isZodArray(schema)) {
|
|
119
|
+
const element = getArrayElement(schema);
|
|
120
|
+
if (element) {
|
|
121
|
+
results.push(...extractFieldReferences(element as z.ZodType<unknown>, `${path}[]`));
|
|
122
|
+
}
|
|
103
123
|
}
|
|
104
124
|
|
|
105
|
-
if (schema
|
|
106
|
-
|
|
125
|
+
if (isZodDefault(schema)) {
|
|
126
|
+
const inner = getInnerSchema(schema);
|
|
127
|
+
if (inner) {
|
|
128
|
+
results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
|
|
129
|
+
}
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
return results;
|
|
@@ -114,7 +137,7 @@ function extractFieldReferences(
|
|
|
114
137
|
*/
|
|
115
138
|
function safeZodToJsonSchema(schema: z.ZodTypeAny): Record<string, unknown> | undefined {
|
|
116
139
|
try {
|
|
117
|
-
const result =
|
|
140
|
+
const result = z.toJSONSchema(schema, { reused: "inline", unrepresentable: "any" }) as Record<string, unknown>;
|
|
118
141
|
delete result.$schema;
|
|
119
142
|
return result;
|
|
120
143
|
} catch {
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -54,6 +54,11 @@ export const initCommand = defineCommand({
|
|
|
54
54
|
const configTemplate = `import { defineOntology, userContext } from 'ont-run';
|
|
55
55
|
import { z } from 'zod';
|
|
56
56
|
|
|
57
|
+
// Import resolver functions - TypeScript enforces return types match outputs
|
|
58
|
+
import healthCheck from './resolvers/healthCheck.js';
|
|
59
|
+
import getUser from './resolvers/getUser.js';
|
|
60
|
+
import deleteUser from './resolvers/deleteUser.js';
|
|
61
|
+
|
|
57
62
|
export default defineOntology({
|
|
58
63
|
name: 'my-api',
|
|
59
64
|
|
|
@@ -98,7 +103,7 @@ export default defineOntology({
|
|
|
98
103
|
access: ['public', 'support', 'admin'],
|
|
99
104
|
entities: [],
|
|
100
105
|
inputs: z.object({}),
|
|
101
|
-
resolver:
|
|
106
|
+
resolver: healthCheck,
|
|
102
107
|
},
|
|
103
108
|
|
|
104
109
|
// Example: Restricted function with row-level access
|
|
@@ -114,7 +119,7 @@ export default defineOntology({
|
|
|
114
119
|
email: z.string(),
|
|
115
120
|
})),
|
|
116
121
|
}),
|
|
117
|
-
resolver:
|
|
122
|
+
resolver: getUser,
|
|
118
123
|
},
|
|
119
124
|
|
|
120
125
|
// Example: Admin-only function
|
|
@@ -126,7 +131,7 @@ export default defineOntology({
|
|
|
126
131
|
userId: z.string().uuid(),
|
|
127
132
|
reason: z.string().optional(),
|
|
128
133
|
}),
|
|
129
|
-
resolver:
|
|
134
|
+
resolver: deleteUser,
|
|
130
135
|
},
|
|
131
136
|
},
|
|
132
137
|
});
|
|
@@ -138,7 +143,7 @@ export default defineOntology({
|
|
|
138
143
|
// Write example resolvers
|
|
139
144
|
const healthCheckResolver = `import type { ResolverContext } from 'ont-run';
|
|
140
145
|
|
|
141
|
-
export default async function healthCheck(ctx: ResolverContext
|
|
146
|
+
export default async function healthCheck(ctx: ResolverContext) {
|
|
142
147
|
ctx.logger.info('Health check called');
|
|
143
148
|
|
|
144
149
|
return {
|
|
@@ -237,7 +242,7 @@ await startOnt();
|
|
|
237
242
|
packageJson.dependencies = {
|
|
238
243
|
...(packageJson.dependencies as Record<string, string> || {}),
|
|
239
244
|
"ont-run": "latest",
|
|
240
|
-
zod: "^
|
|
245
|
+
zod: "^4.0.0",
|
|
241
246
|
};
|
|
242
247
|
|
|
243
248
|
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { isZodObject, getObjectShape } from "./zod-utils";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Symbol for storing fieldFrom metadata on Zod schemas
|
|
@@ -175,19 +176,18 @@ export function hasUserContextMetadata(
|
|
|
175
176
|
/**
|
|
176
177
|
* Get all userContext field names from a Zod object schema
|
|
177
178
|
*
|
|
178
|
-
* Note: Uses
|
|
179
|
-
* module boundaries in bundled CLI.
|
|
179
|
+
* Note: Uses zod-utils for bundler compatibility (instanceof fails across module boundaries)
|
|
180
180
|
*/
|
|
181
181
|
export function getUserContextFields(schema: z.ZodType): string[] {
|
|
182
182
|
const fields: string[] = [];
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
if (isZodObject(schema)) {
|
|
185
|
+
const shape = getObjectShape(schema);
|
|
186
|
+
if (shape) {
|
|
187
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
188
|
+
if (hasUserContextMetadata(value)) {
|
|
189
|
+
fields.push(key);
|
|
190
|
+
}
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
package/src/config/define.ts
CHANGED
|
@@ -56,7 +56,9 @@ import type {
|
|
|
56
56
|
export function defineOntology<
|
|
57
57
|
TGroups extends string,
|
|
58
58
|
TEntities extends string,
|
|
59
|
-
|
|
59
|
+
// Use `any` for input/output schema types to avoid contravariance issues with resolver functions.
|
|
60
|
+
// Without this, ResolverFunction<unknown, unknown> won't accept more specific resolver types.
|
|
61
|
+
TFunctions extends Record<string, FunctionDefinition<TGroups, TEntities, any, any>>,
|
|
60
62
|
>(config: {
|
|
61
63
|
name: string;
|
|
62
64
|
environments: Record<string, EnvironmentConfig>;
|
package/src/config/schema.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { getFieldFromMetadata, getUserContextFields } from "./categorical.js";
|
|
3
|
+
import {
|
|
4
|
+
isZodSchema,
|
|
5
|
+
isZod3Schema,
|
|
6
|
+
isZodObject,
|
|
7
|
+
isZodOptional,
|
|
8
|
+
isZodNullable,
|
|
9
|
+
isZodArray,
|
|
10
|
+
isZodDefault,
|
|
11
|
+
getObjectShape,
|
|
12
|
+
getInnerSchema,
|
|
13
|
+
getArrayElement,
|
|
14
|
+
} from "./zod-utils.js";
|
|
3
15
|
import type { OntologyConfig } from "./types.js";
|
|
4
16
|
|
|
5
17
|
/**
|
|
@@ -26,16 +38,24 @@ export const EntityDefinitionSchema = z.object({
|
|
|
26
38
|
});
|
|
27
39
|
|
|
28
40
|
/**
|
|
29
|
-
* Check if a value is a
|
|
41
|
+
* Check if a value is a function
|
|
30
42
|
*/
|
|
31
|
-
function
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
function isFunction(val: unknown): val is (...args: unknown[]) => unknown {
|
|
44
|
+
return typeof val === "function";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validate that a value is a Zod 4 schema, with helpful error for Zod 3
|
|
49
|
+
*/
|
|
50
|
+
function validateZodSchema(val: unknown, fieldName: string): boolean {
|
|
51
|
+
if (isZodSchema(val)) return true;
|
|
52
|
+
if (isZod3Schema(val)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`${fieldName} appears to be a Zod 3 schema. ont-run requires Zod 4.\n` +
|
|
55
|
+
`Please upgrade: bun add zod@4`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
/**
|
|
@@ -45,32 +65,28 @@ export const FunctionDefinitionSchema = z.object({
|
|
|
45
65
|
description: z.string(),
|
|
46
66
|
access: z.array(z.string()).min(1),
|
|
47
67
|
entities: z.array(z.string()),
|
|
48
|
-
inputs: z.custom<z.ZodType>(
|
|
49
|
-
message: "inputs must be a Zod schema",
|
|
68
|
+
inputs: z.custom<z.ZodType>((val) => validateZodSchema(val, "inputs"), {
|
|
69
|
+
message: "inputs must be a Zod 4 schema",
|
|
50
70
|
}),
|
|
51
71
|
outputs: z
|
|
52
|
-
.custom<z.ZodType>(
|
|
53
|
-
message: "outputs must be a Zod schema",
|
|
72
|
+
.custom<z.ZodType>((val) => validateZodSchema(val, "outputs"), {
|
|
73
|
+
message: "outputs must be a Zod 4 schema",
|
|
54
74
|
})
|
|
55
75
|
.optional(),
|
|
56
|
-
resolver: z.
|
|
76
|
+
resolver: z.custom<(...args: unknown[]) => unknown>(isFunction, {
|
|
77
|
+
message: "resolver must be a function",
|
|
78
|
+
}),
|
|
57
79
|
});
|
|
58
80
|
|
|
59
|
-
/**
|
|
60
|
-
* Schema for auth function
|
|
61
|
-
*/
|
|
62
|
-
export const AuthFunctionSchema = z
|
|
63
|
-
.function()
|
|
64
|
-
.args(z.custom<Request>())
|
|
65
|
-
.returns(z.union([z.array(z.string()), z.promise(z.array(z.string()))]));
|
|
66
|
-
|
|
67
81
|
/**
|
|
68
82
|
* Schema for the full ontology configuration
|
|
69
83
|
*/
|
|
70
84
|
export const OntologyConfigSchema = z.object({
|
|
71
85
|
name: z.string().min(1),
|
|
72
86
|
environments: z.record(z.string(), EnvironmentConfigSchema),
|
|
73
|
-
auth: z.
|
|
87
|
+
auth: z.custom<(req: Request) => unknown>(isFunction, {
|
|
88
|
+
message: "auth must be a function",
|
|
89
|
+
}),
|
|
74
90
|
accessGroups: z.record(z.string(), AccessGroupConfigSchema),
|
|
75
91
|
entities: z.record(z.string(), EntityDefinitionSchema).optional(),
|
|
76
92
|
functions: z.record(z.string(), FunctionDefinitionSchema),
|
|
@@ -141,34 +157,48 @@ function extractFieldFromRefs(
|
|
|
141
157
|
}
|
|
142
158
|
|
|
143
159
|
// Handle ZodObject - recurse into properties
|
|
144
|
-
if (schema
|
|
145
|
-
const shape = schema
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
160
|
+
if (isZodObject(schema)) {
|
|
161
|
+
const shape = getObjectShape(schema);
|
|
162
|
+
if (shape) {
|
|
163
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
164
|
+
const fieldPath = path ? `${path}.${key}` : key;
|
|
165
|
+
results.push(
|
|
166
|
+
...extractFieldFromRefs(value as z.ZodType<unknown>, fieldPath)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
151
169
|
}
|
|
152
170
|
}
|
|
153
171
|
|
|
154
172
|
// Handle ZodOptional - unwrap
|
|
155
|
-
if (schema
|
|
156
|
-
|
|
173
|
+
if (isZodOptional(schema)) {
|
|
174
|
+
const inner = getInnerSchema(schema);
|
|
175
|
+
if (inner) {
|
|
176
|
+
results.push(...extractFieldFromRefs(inner as z.ZodType<unknown>, path));
|
|
177
|
+
}
|
|
157
178
|
}
|
|
158
179
|
|
|
159
180
|
// Handle ZodNullable - unwrap
|
|
160
|
-
if (schema
|
|
161
|
-
|
|
181
|
+
if (isZodNullable(schema)) {
|
|
182
|
+
const inner = getInnerSchema(schema);
|
|
183
|
+
if (inner) {
|
|
184
|
+
results.push(...extractFieldFromRefs(inner as z.ZodType<unknown>, path));
|
|
185
|
+
}
|
|
162
186
|
}
|
|
163
187
|
|
|
164
188
|
// Handle ZodArray - recurse into element
|
|
165
|
-
if (schema
|
|
166
|
-
|
|
189
|
+
if (isZodArray(schema)) {
|
|
190
|
+
const element = getArrayElement(schema);
|
|
191
|
+
if (element) {
|
|
192
|
+
results.push(...extractFieldFromRefs(element as z.ZodType<unknown>, `${path}[]`));
|
|
193
|
+
}
|
|
167
194
|
}
|
|
168
195
|
|
|
169
196
|
// Handle ZodDefault - unwrap
|
|
170
|
-
if (schema
|
|
171
|
-
|
|
197
|
+
if (isZodDefault(schema)) {
|
|
198
|
+
const inner = getInnerSchema(schema);
|
|
199
|
+
if (inner) {
|
|
200
|
+
results.push(...extractFieldFromRefs(inner as z.ZodType<unknown>, path));
|
|
201
|
+
}
|
|
172
202
|
}
|
|
173
203
|
|
|
174
204
|
return results;
|