@notionhq/workers 0.0.85 → 0.0.86
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/builder.d.ts +9 -4
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +23 -18
- package/dist/builder.test.d.ts +2 -0
- package/dist/builder.test.d.ts.map +1 -0
- package/dist/capabilities/automation.js +2 -2
- package/dist/capabilities/sync.d.ts.map +1 -1
- package/dist/capabilities/sync.js +22 -6
- package/dist/capabilities/tool.d.ts +13 -6
- package/dist/capabilities/tool.d.ts.map +1 -1
- package/dist/capabilities/tool.js +28 -18
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/schema-builder.d.ts +79 -0
- package/dist/schema-builder.d.ts.map +1 -0
- package/dist/schema-builder.js +135 -0
- package/dist/schema-builder.test.d.ts +2 -0
- package/dist/schema-builder.test.d.ts.map +1 -0
- package/dist/worker.d.ts +3 -8
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +3 -8
- package/package.json +5 -1
- package/src/builder.test.ts +229 -0
- package/src/builder.ts +38 -25
- package/src/capabilities/automation.test.ts +8 -4
- package/src/capabilities/automation.ts +2 -2
- package/src/capabilities/sync.test.ts +70 -1
- package/src/capabilities/sync.ts +18 -6
- package/src/capabilities/tool.test.ts +32 -167
- package/src/capabilities/tool.ts +33 -26
- package/src/index.ts +2 -0
- package/src/schema-builder.test.ts +677 -0
- package/src/schema-builder.ts +203 -0
- package/src/worker.ts +3 -8
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod-like builder for JSONSchema objects.
|
|
3
|
+
*
|
|
4
|
+
* Guarantees output always complies with the model provider constraints
|
|
5
|
+
* enforced by `json-schema.ts` — all object properties in `required`,
|
|
6
|
+
* `additionalProperties: false`, no forbidden composition keywords, etc.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { j } from "@notionhq/workers/schema-builder";
|
|
11
|
+
*
|
|
12
|
+
* const schema = j.object({
|
|
13
|
+
* foo: j.enum("a", "b", "c").describe("The foo field"),
|
|
14
|
+
* bar: j.string(),
|
|
15
|
+
* count: j.number(),
|
|
16
|
+
* tags: j.array(j.string()),
|
|
17
|
+
* nickname: j.string().nullable(),
|
|
18
|
+
* createdAt: j.datetime(),
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { AnyJSONSchema, JSONSchema } from "./json-schema.js";
|
|
24
|
+
|
|
25
|
+
const SCHEMA: unique symbol = Symbol("schema");
|
|
26
|
+
|
|
27
|
+
export interface SchemaBuilder<T> {
|
|
28
|
+
readonly [SCHEMA]: AnyJSONSchema;
|
|
29
|
+
/** Set the JSONSchema description field. Chainable. */
|
|
30
|
+
describe(text: string): SchemaBuilder<T>;
|
|
31
|
+
/** Wrap in anyOf with null. Chainable. */
|
|
32
|
+
nullable(): SchemaBuilder<T | null>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Extracts `T` from `SchemaBuilder<T>` (type-level only). */
|
|
36
|
+
export type Infer<S> = S extends SchemaBuilder<infer T> ? T : never;
|
|
37
|
+
|
|
38
|
+
/** Extract the plain JSONSchema from a builder. */
|
|
39
|
+
export function getSchema<T>(builder: SchemaBuilder<T>): JSONSchema<T> {
|
|
40
|
+
return builder[SCHEMA] as JSONSchema<T>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function makeBuilder<T>(schema: AnyJSONSchema): SchemaBuilder<T> {
|
|
44
|
+
return {
|
|
45
|
+
[SCHEMA]: schema,
|
|
46
|
+
describe(text: string) {
|
|
47
|
+
return makeBuilder<T>({ ...schema, description: text });
|
|
48
|
+
},
|
|
49
|
+
nullable() {
|
|
50
|
+
const { description: desc, ...rest } = schema as unknown as Record<
|
|
51
|
+
string,
|
|
52
|
+
unknown
|
|
53
|
+
>;
|
|
54
|
+
const inner =
|
|
55
|
+
desc !== undefined ? (rest as unknown as AnyJSONSchema) : schema;
|
|
56
|
+
const wrapper: Record<string, unknown> = {
|
|
57
|
+
anyOf: [inner, { type: "null" }],
|
|
58
|
+
};
|
|
59
|
+
if (desc !== undefined) wrapper.description = desc;
|
|
60
|
+
return makeBuilder<T | null>(wrapper as unknown as AnyJSONSchema);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---- Primitives ----
|
|
66
|
+
|
|
67
|
+
export function string(): SchemaBuilder<string> {
|
|
68
|
+
return makeBuilder<string>({ type: "string" });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function number(): SchemaBuilder<number> {
|
|
72
|
+
return makeBuilder<number>({ type: "number" });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function integer(): SchemaBuilder<number> {
|
|
76
|
+
return makeBuilder<number>({ type: "integer" });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function boolean(): SchemaBuilder<boolean> {
|
|
80
|
+
return makeBuilder<boolean>({ type: "boolean" });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---- Enum ----
|
|
84
|
+
|
|
85
|
+
function enumBuilder<T extends string>(
|
|
86
|
+
...values: readonly T[]
|
|
87
|
+
): SchemaBuilder<T>;
|
|
88
|
+
function enumBuilder<T extends number>(
|
|
89
|
+
...values: readonly T[]
|
|
90
|
+
): SchemaBuilder<T>;
|
|
91
|
+
function enumBuilder(
|
|
92
|
+
...values: readonly (string | number)[]
|
|
93
|
+
): SchemaBuilder<unknown> {
|
|
94
|
+
const type = typeof values[0] === "string" ? "string" : "number";
|
|
95
|
+
return makeBuilder({ type, enum: values } as AnyJSONSchema);
|
|
96
|
+
}
|
|
97
|
+
export { enumBuilder as enum };
|
|
98
|
+
|
|
99
|
+
// ---- String format shorthands ----
|
|
100
|
+
|
|
101
|
+
export function datetime(): SchemaBuilder<string> {
|
|
102
|
+
return makeBuilder<string>({ type: "string", format: "date-time" });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function date(): SchemaBuilder<string> {
|
|
106
|
+
return makeBuilder<string>({ type: "string", format: "date" });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function time(): SchemaBuilder<string> {
|
|
110
|
+
return makeBuilder<string>({ type: "string", format: "time" });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function duration(): SchemaBuilder<string> {
|
|
114
|
+
return makeBuilder<string>({ type: "string", format: "duration" });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function email(): SchemaBuilder<string> {
|
|
118
|
+
return makeBuilder<string>({ type: "string", format: "email" });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function hostname(): SchemaBuilder<string> {
|
|
122
|
+
return makeBuilder<string>({ type: "string", format: "hostname" });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function ipv4(): SchemaBuilder<string> {
|
|
126
|
+
return makeBuilder<string>({ type: "string", format: "ipv4" });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function ipv6(): SchemaBuilder<string> {
|
|
130
|
+
return makeBuilder<string>({ type: "string", format: "ipv6" });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function uuid(): SchemaBuilder<string> {
|
|
134
|
+
return makeBuilder<string>({ type: "string", format: "uuid" });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ---- Composites ----
|
|
138
|
+
|
|
139
|
+
export function array<T>(
|
|
140
|
+
items: SchemaBuilder<T>,
|
|
141
|
+
options?: { minItems?: 0 | 1 },
|
|
142
|
+
): SchemaBuilder<T[]> {
|
|
143
|
+
const schema: Record<string, unknown> = {
|
|
144
|
+
type: "array",
|
|
145
|
+
items: getSchema(items),
|
|
146
|
+
};
|
|
147
|
+
if (options?.minItems !== undefined) schema.minItems = options.minItems;
|
|
148
|
+
return makeBuilder<T[]>(schema as unknown as AnyJSONSchema);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function object<P extends Record<string, SchemaBuilder<unknown>>>(
|
|
152
|
+
properties: P,
|
|
153
|
+
): SchemaBuilder<{ [K in keyof P]: Infer<P[K]> }> {
|
|
154
|
+
const schemaProps: Record<string, AnyJSONSchema> = {};
|
|
155
|
+
const keys = Object.keys(properties);
|
|
156
|
+
for (const key of keys) {
|
|
157
|
+
// biome-ignore lint/style/noNonNullAssertion: key comes from Object.keys(properties)
|
|
158
|
+
schemaProps[key] = getSchema(properties[key]!);
|
|
159
|
+
}
|
|
160
|
+
return makeBuilder({
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: schemaProps,
|
|
163
|
+
required: keys,
|
|
164
|
+
additionalProperties: false,
|
|
165
|
+
} as AnyJSONSchema);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function anyOf<S extends SchemaBuilder<unknown>[]>(
|
|
169
|
+
...schemas: S
|
|
170
|
+
): SchemaBuilder<Infer<S[number]>> {
|
|
171
|
+
return makeBuilder({
|
|
172
|
+
anyOf: schemas.map(getSchema),
|
|
173
|
+
} as AnyJSONSchema);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ---- Reference ----
|
|
177
|
+
|
|
178
|
+
export function ref(path: string): SchemaBuilder<unknown> {
|
|
179
|
+
return makeBuilder({ $ref: path });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---- Namespace export ----
|
|
183
|
+
|
|
184
|
+
export const j = {
|
|
185
|
+
string,
|
|
186
|
+
number,
|
|
187
|
+
integer,
|
|
188
|
+
boolean,
|
|
189
|
+
enum: enumBuilder,
|
|
190
|
+
datetime,
|
|
191
|
+
date,
|
|
192
|
+
time,
|
|
193
|
+
duration,
|
|
194
|
+
email,
|
|
195
|
+
hostname,
|
|
196
|
+
ipv4,
|
|
197
|
+
ipv6,
|
|
198
|
+
uuid,
|
|
199
|
+
array,
|
|
200
|
+
object,
|
|
201
|
+
anyOf,
|
|
202
|
+
ref,
|
|
203
|
+
};
|
package/src/worker.ts
CHANGED
|
@@ -112,23 +112,18 @@ export class Worker {
|
|
|
112
112
|
* Example:
|
|
113
113
|
*
|
|
114
114
|
* ```ts
|
|
115
|
+
* import { j } from "@notionhq/workers/schema-builder";
|
|
116
|
+
*
|
|
115
117
|
* worker.tool<{ name: string }, string>("sayHello", {
|
|
116
118
|
* title: "Say Hello",
|
|
117
119
|
* description: "Say hello to the user",
|
|
118
|
-
* schema: {
|
|
119
|
-
* type: "object",
|
|
120
|
-
* properties: {
|
|
121
|
-
* name: { type: "string" },
|
|
122
|
-
* },
|
|
123
|
-
* required: ["name"],
|
|
124
|
-
* },
|
|
120
|
+
* schema: j.object({ name: j.string() }),
|
|
125
121
|
* execute: ({ name }, { notion }) => {
|
|
126
122
|
* return `Hello, ${name}!`;
|
|
127
123
|
* },
|
|
128
124
|
* })
|
|
129
125
|
* ```
|
|
130
126
|
*
|
|
131
|
-
*
|
|
132
127
|
* @param key - The unique key for this capability.
|
|
133
128
|
* @param config - The tool configuration.
|
|
134
129
|
* @returns The capability object.
|