@usegraft/contracts 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anderson Joseph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,281 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Error codes + the GraftError shape.
5
+ *
6
+ * Every Graft error carries an agent-actionable `fix` — the next concrete step an
7
+ * agent (or human) can take to resolve it. This is part of the "self-teaching"
8
+ * pillar: failures explain how to recover, not just what went wrong.
9
+ */
10
+ declare const ErrorCodes: {
11
+ readonly SCHEMA_VALIDATION_FAILED: "SCHEMA_VALIDATION_FAILED";
12
+ readonly COLLECTION_NOT_FOUND: "COLLECTION_NOT_FOUND";
13
+ readonly CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND";
14
+ readonly CONFIG_INVALID: "CONFIG_INVALID";
15
+ readonly ALREADY_INITIALIZED: "ALREADY_INITIALIZED";
16
+ readonly ENV_VAR_MISSING: "ENV_VAR_MISSING";
17
+ readonly CONTENT_DIR_NOT_FOUND: "CONTENT_DIR_NOT_FOUND";
18
+ readonly CONTENT_REFERENCE_NOT_FOUND: "CONTENT_REFERENCE_NOT_FOUND";
19
+ readonly DOCUMENT_NOT_FOUND: "DOCUMENT_NOT_FOUND";
20
+ readonly FUNCTION_NOT_FOUND: "FUNCTION_NOT_FOUND";
21
+ readonly INPUT_VALIDATION_FAILED: "INPUT_VALIDATION_FAILED";
22
+ readonly FUNCTION_EXECUTION_FAILED: "FUNCTION_EXECUTION_FAILED";
23
+ readonly METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED";
24
+ readonly ROUTE_NOT_FOUND: "ROUTE_NOT_FOUND";
25
+ readonly AUTHORITY_MISMATCH: "AUTHORITY_MISMATCH";
26
+ readonly INDEX_OWNERSHIP: "INDEX_OWNERSHIP";
27
+ readonly SLUG_NOT_UNIQUE: "SLUG_NOT_UNIQUE";
28
+ readonly INVALID_SLUG: "INVALID_SLUG";
29
+ readonly MIGRATION_REQUIRED: "MIGRATION_REQUIRED";
30
+ readonly MIGRATION_FAILED: "MIGRATION_FAILED";
31
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
32
+ readonly TOKEN_INVALID: "TOKEN_INVALID";
33
+ readonly RATE_LIMITED: "RATE_LIMITED";
34
+ readonly DESTRUCTIVE_OP_REQUIRES_APPROVAL: "DESTRUCTIVE_OP_REQUIRES_APPROVAL";
35
+ readonly APPROVAL_INVALID: "APPROVAL_INVALID";
36
+ readonly APPROVAL_SELF_DECISION: "APPROVAL_SELF_DECISION";
37
+ readonly BRANCH_NOT_FOUND: "BRANCH_NOT_FOUND";
38
+ readonly BRANCH_EXISTS: "BRANCH_EXISTS";
39
+ readonly BRANCH_INVALID: "BRANCH_INVALID";
40
+ readonly BRANCH_BACKEND_FAILED: "BRANCH_BACKEND_FAILED";
41
+ readonly REGISTRY_ITEM_NOT_FOUND: "REGISTRY_ITEM_NOT_FOUND";
42
+ readonly REGISTRY_ITEM_INVALID: "REGISTRY_ITEM_INVALID";
43
+ readonly REGISTRY_FILE_EXISTS: "REGISTRY_FILE_EXISTS";
44
+ readonly ASSET_EXISTS: "ASSET_EXISTS";
45
+ readonly NEEDS_DATABASE: "NEEDS_DATABASE";
46
+ readonly CONTENT_TREE_READ_ONLY: "CONTENT_TREE_READ_ONLY";
47
+ readonly GIT_UNAVAILABLE: "GIT_UNAVAILABLE";
48
+ readonly COMMIT_FAILED: "COMMIT_FAILED";
49
+ readonly STATIC_INDEX_NOT_FOUND: "STATIC_INDEX_NOT_FOUND";
50
+ readonly STATIC_INDEX_UNSUPPORTED: "STATIC_INDEX_UNSUPPORTED";
51
+ readonly NOT_IMPLEMENTED: "NOT_IMPLEMENTED";
52
+ };
53
+ type ErrorCode = keyof typeof ErrorCodes;
54
+ interface GraftErrorJSON {
55
+ error: ErrorCode;
56
+ message: string;
57
+ fix?: string;
58
+ details?: Record<string, unknown>;
59
+ }
60
+ interface GraftErrorOptions {
61
+ code: ErrorCode;
62
+ message: string;
63
+ /** Agent-actionable next step, e.g. "create pages/about.mdx or fix the reference in nav.ts". */
64
+ fix?: string;
65
+ details?: Record<string, unknown>;
66
+ }
67
+ declare class GraftError extends Error {
68
+ readonly code: ErrorCode;
69
+ readonly fix?: string;
70
+ readonly details?: Record<string, unknown>;
71
+ constructor(options: GraftErrorOptions);
72
+ toJSON(): GraftErrorJSON;
73
+ }
74
+
75
+ /**
76
+ * Introspection contracts — the single source of truth for what the MCP
77
+ * `describe_schema` tool returns, so the MCP server, CLI, and core all agree on
78
+ * shape. Zod gives us runtime validation and the inferred TypeScript types from
79
+ * one definition (the "one Zod layer" principle).
80
+ */
81
+
82
+ declare const ContentAuthority: z.ZodEnum<{
83
+ "file-authoritative": "file-authoritative";
84
+ "db-authoritative": "db-authoritative";
85
+ "hybrid-with-drift-detection": "hybrid-with-drift-detection";
86
+ }>;
87
+ type ContentAuthority = z.infer<typeof ContentAuthority>;
88
+ /**
89
+ * Field introspection — recursive so object/array fields expose their shape
90
+ * to agents (describe_schema), not opaque "json" blobs.
91
+ */
92
+ type FieldDescriptor = {
93
+ name: string;
94
+ type: string;
95
+ optional: boolean;
96
+ description?: string;
97
+ /** Nested fields when type is `object`. */
98
+ fields?: FieldDescriptor[];
99
+ /** Item shape when type is `array` (name is conventionally `"item"`). */
100
+ items?: FieldDescriptor;
101
+ };
102
+ declare const FieldDescriptor: z.ZodType<FieldDescriptor>;
103
+ declare const CollectionDescriptor: z.ZodObject<{
104
+ name: z.ZodString;
105
+ authority: z.ZodEnum<{
106
+ "file-authoritative": "file-authoritative";
107
+ "db-authoritative": "db-authoritative";
108
+ "hybrid-with-drift-detection": "hybrid-with-drift-detection";
109
+ }>;
110
+ fields: z.ZodArray<z.ZodType<FieldDescriptor, unknown, z.core.$ZodTypeInternals<FieldDescriptor, unknown>>>;
111
+ description: z.ZodOptional<z.ZodString>;
112
+ sections: z.ZodOptional<z.ZodArray<z.ZodString>>;
113
+ }, z.core.$strip>;
114
+ type CollectionDescriptor = z.infer<typeof CollectionDescriptor>;
115
+ declare const FunctionDescriptor: z.ZodObject<{
116
+ name: z.ZodString;
117
+ kind: z.ZodEnum<{
118
+ query: "query";
119
+ mutation: "mutation";
120
+ }>;
121
+ args: z.ZodArray<z.ZodType<FieldDescriptor, unknown, z.core.$ZodTypeInternals<FieldDescriptor, unknown>>>;
122
+ returns: z.ZodOptional<z.ZodString>;
123
+ description: z.ZodOptional<z.ZodString>;
124
+ public: z.ZodOptional<z.ZodBoolean>;
125
+ destructive: z.ZodOptional<z.ZodBoolean>;
126
+ }, z.core.$strip>;
127
+ type FunctionDescriptor = z.infer<typeof FunctionDescriptor>;
128
+ declare const SchemaDescription: z.ZodObject<{
129
+ collections: z.ZodArray<z.ZodObject<{
130
+ name: z.ZodString;
131
+ authority: z.ZodEnum<{
132
+ "file-authoritative": "file-authoritative";
133
+ "db-authoritative": "db-authoritative";
134
+ "hybrid-with-drift-detection": "hybrid-with-drift-detection";
135
+ }>;
136
+ fields: z.ZodArray<z.ZodType<FieldDescriptor, unknown, z.core.$ZodTypeInternals<FieldDescriptor, unknown>>>;
137
+ description: z.ZodOptional<z.ZodString>;
138
+ sections: z.ZodOptional<z.ZodArray<z.ZodString>>;
139
+ }, z.core.$strip>>;
140
+ functions: z.ZodArray<z.ZodObject<{
141
+ name: z.ZodString;
142
+ kind: z.ZodEnum<{
143
+ query: "query";
144
+ mutation: "mutation";
145
+ }>;
146
+ args: z.ZodArray<z.ZodType<FieldDescriptor, unknown, z.core.$ZodTypeInternals<FieldDescriptor, unknown>>>;
147
+ returns: z.ZodOptional<z.ZodString>;
148
+ description: z.ZodOptional<z.ZodString>;
149
+ public: z.ZodOptional<z.ZodBoolean>;
150
+ destructive: z.ZodOptional<z.ZodBoolean>;
151
+ }, z.core.$strip>>;
152
+ }, z.core.$strip>;
153
+ type SchemaDescription = z.infer<typeof SchemaDescription>;
154
+ /**
155
+ * Registry introspection — the shape the MCP `list_registry` / `describe_item`
156
+ * tools return so agents can browse owned primitives before `graft add`.
157
+ *
158
+ * The vocabulary here mirrors @usegraft/registry's authoring manifest (ITEM_TYPES /
159
+ * FILE_ROLES); a drift test in @usegraft/registry keeps the two in lockstep so this
160
+ * stays the single introspection source of truth without contracts depending on
161
+ * registry.
162
+ */
163
+ declare const RegistryItemType: z.ZodEnum<{
164
+ block: "block";
165
+ field: "field";
166
+ access: "access";
167
+ bundle: "bundle";
168
+ }>;
169
+ type RegistryItemType = z.infer<typeof RegistryItemType>;
170
+ declare const RegistryFileRole: z.ZodEnum<{
171
+ module: "module";
172
+ component: "component";
173
+ content: "content";
174
+ env: "env";
175
+ editor: "editor";
176
+ }>;
177
+ type RegistryFileRole = z.infer<typeof RegistryFileRole>;
178
+ /**
179
+ * How a component presents in the Studio canvas — the editor's half of an
180
+ * owned primitive.
181
+ *
182
+ * Data, not code, and that is the load-bearing decision. The Studio ships as a
183
+ * prebuilt bundle with no bundler in the loop, so it cannot import a component
184
+ * from the project and render it; the only other way to let a third party
185
+ * control presentation would be to evaluate code they authored inside the
186
+ * editor, which is not a thing to ship. A declaration the editor interprets
187
+ * keeps the extension point open without that.
188
+ *
189
+ * It is copied into the project by `graft add`, exactly like the component it
190
+ * describes: owned, editable, no runtime dependency on the registry it came
191
+ * from. Renaming a prop means editing a file you already have.
192
+ *
193
+ * Everything is optional. A component with no declaration still renders — it
194
+ * gets the generic card, which is what every component got before this existed.
195
+ */
196
+ declare const EditorComponentSpec: z.ZodObject<{
197
+ component: z.ZodString;
198
+ label: z.ZodOptional<z.ZodString>;
199
+ titleProp: z.ZodOptional<z.ZodString>;
200
+ linkProp: z.ZodOptional<z.ZodString>;
201
+ tone: z.ZodOptional<z.ZodObject<{
202
+ prop: z.ZodString;
203
+ map: z.ZodRecord<z.ZodString, z.ZodEnum<{
204
+ success: "success";
205
+ info: "info";
206
+ warn: "warn";
207
+ danger: "danger";
208
+ neutral: "neutral";
209
+ }>>;
210
+ }, z.core.$strip>>;
211
+ hideProps: z.ZodDefault<z.ZodArray<z.ZodString>>;
212
+ children: z.ZodDefault<z.ZodArray<z.ZodString>>;
213
+ snippet: z.ZodOptional<z.ZodString>;
214
+ }, z.core.$strip>;
215
+ type EditorComponentSpec = z.infer<typeof EditorComponentSpec>;
216
+ /** What `GET /api/studio/v1/editor-components` returns: the project's own declarations. */
217
+ declare const EditorComponentList: z.ZodObject<{
218
+ components: z.ZodArray<z.ZodObject<{
219
+ component: z.ZodString;
220
+ label: z.ZodOptional<z.ZodString>;
221
+ titleProp: z.ZodOptional<z.ZodString>;
222
+ linkProp: z.ZodOptional<z.ZodString>;
223
+ tone: z.ZodOptional<z.ZodObject<{
224
+ prop: z.ZodString;
225
+ map: z.ZodRecord<z.ZodString, z.ZodEnum<{
226
+ success: "success";
227
+ info: "info";
228
+ warn: "warn";
229
+ danger: "danger";
230
+ neutral: "neutral";
231
+ }>>;
232
+ }, z.core.$strip>>;
233
+ hideProps: z.ZodDefault<z.ZodArray<z.ZodString>>;
234
+ children: z.ZodDefault<z.ZodArray<z.ZodString>>;
235
+ snippet: z.ZodOptional<z.ZodString>;
236
+ }, z.core.$strip>>;
237
+ }, z.core.$strip>;
238
+ type EditorComponentList = z.infer<typeof EditorComponentList>;
239
+ /** One file an item writes — the target path (relative to project root) and its role. */
240
+ declare const RegistryFileDescriptor: z.ZodObject<{
241
+ target: z.ZodString;
242
+ role: z.ZodEnum<{
243
+ module: "module";
244
+ component: "component";
245
+ content: "content";
246
+ env: "env";
247
+ editor: "editor";
248
+ }>;
249
+ }, z.core.$strip>;
250
+ type RegistryFileDescriptor = z.infer<typeof RegistryFileDescriptor>;
251
+ /**
252
+ * Agent-facing description of one owned primitive. Deliberately omits the
253
+ * machine-specific absolute `dir` a loaded item carries — this is the wire shape.
254
+ */
255
+ declare const RegistryItemDescriptor: z.ZodObject<{
256
+ name: z.ZodString;
257
+ type: z.ZodEnum<{
258
+ block: "block";
259
+ field: "field";
260
+ access: "access";
261
+ bundle: "bundle";
262
+ }>;
263
+ description: z.ZodString;
264
+ graftVersion: z.ZodString;
265
+ dependencies: z.ZodRecord<z.ZodString, z.ZodString>;
266
+ registryDependencies: z.ZodArray<z.ZodString>;
267
+ files: z.ZodArray<z.ZodObject<{
268
+ target: z.ZodString;
269
+ role: z.ZodEnum<{
270
+ module: "module";
271
+ component: "component";
272
+ content: "content";
273
+ env: "env";
274
+ editor: "editor";
275
+ }>;
276
+ }, z.core.$strip>>;
277
+ llms: z.ZodBoolean;
278
+ }, z.core.$strip>;
279
+ type RegistryItemDescriptor = z.infer<typeof RegistryItemDescriptor>;
280
+
281
+ export { CollectionDescriptor, ContentAuthority, EditorComponentList, EditorComponentSpec, type ErrorCode, ErrorCodes, FieldDescriptor, FunctionDescriptor, GraftError, type GraftErrorJSON, type GraftErrorOptions, RegistryFileDescriptor, RegistryFileRole, RegistryItemDescriptor, RegistryItemType, SchemaDescription };
package/dist/index.js ADDED
@@ -0,0 +1,189 @@
1
+ // src/errors.ts
2
+ var ErrorCodes = {
3
+ SCHEMA_VALIDATION_FAILED: "SCHEMA_VALIDATION_FAILED",
4
+ COLLECTION_NOT_FOUND: "COLLECTION_NOT_FOUND",
5
+ CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
6
+ CONFIG_INVALID: "CONFIG_INVALID",
7
+ ALREADY_INITIALIZED: "ALREADY_INITIALIZED",
8
+ ENV_VAR_MISSING: "ENV_VAR_MISSING",
9
+ CONTENT_DIR_NOT_FOUND: "CONTENT_DIR_NOT_FOUND",
10
+ CONTENT_REFERENCE_NOT_FOUND: "CONTENT_REFERENCE_NOT_FOUND",
11
+ DOCUMENT_NOT_FOUND: "DOCUMENT_NOT_FOUND",
12
+ FUNCTION_NOT_FOUND: "FUNCTION_NOT_FOUND",
13
+ INPUT_VALIDATION_FAILED: "INPUT_VALIDATION_FAILED",
14
+ FUNCTION_EXECUTION_FAILED: "FUNCTION_EXECUTION_FAILED",
15
+ METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED",
16
+ ROUTE_NOT_FOUND: "ROUTE_NOT_FOUND",
17
+ AUTHORITY_MISMATCH: "AUTHORITY_MISMATCH",
18
+ INDEX_OWNERSHIP: "INDEX_OWNERSHIP",
19
+ SLUG_NOT_UNIQUE: "SLUG_NOT_UNIQUE",
20
+ INVALID_SLUG: "INVALID_SLUG",
21
+ MIGRATION_REQUIRED: "MIGRATION_REQUIRED",
22
+ MIGRATION_FAILED: "MIGRATION_FAILED",
23
+ UNAUTHORIZED: "UNAUTHORIZED",
24
+ TOKEN_INVALID: "TOKEN_INVALID",
25
+ RATE_LIMITED: "RATE_LIMITED",
26
+ DESTRUCTIVE_OP_REQUIRES_APPROVAL: "DESTRUCTIVE_OP_REQUIRES_APPROVAL",
27
+ APPROVAL_INVALID: "APPROVAL_INVALID",
28
+ APPROVAL_SELF_DECISION: "APPROVAL_SELF_DECISION",
29
+ BRANCH_NOT_FOUND: "BRANCH_NOT_FOUND",
30
+ BRANCH_EXISTS: "BRANCH_EXISTS",
31
+ BRANCH_INVALID: "BRANCH_INVALID",
32
+ BRANCH_BACKEND_FAILED: "BRANCH_BACKEND_FAILED",
33
+ REGISTRY_ITEM_NOT_FOUND: "REGISTRY_ITEM_NOT_FOUND",
34
+ REGISTRY_ITEM_INVALID: "REGISTRY_ITEM_INVALID",
35
+ REGISTRY_FILE_EXISTS: "REGISTRY_FILE_EXISTS",
36
+ ASSET_EXISTS: "ASSET_EXISTS",
37
+ NEEDS_DATABASE: "NEEDS_DATABASE",
38
+ CONTENT_TREE_READ_ONLY: "CONTENT_TREE_READ_ONLY",
39
+ GIT_UNAVAILABLE: "GIT_UNAVAILABLE",
40
+ COMMIT_FAILED: "COMMIT_FAILED",
41
+ STATIC_INDEX_NOT_FOUND: "STATIC_INDEX_NOT_FOUND",
42
+ STATIC_INDEX_UNSUPPORTED: "STATIC_INDEX_UNSUPPORTED",
43
+ NOT_IMPLEMENTED: "NOT_IMPLEMENTED"
44
+ };
45
+ var GraftError = class extends Error {
46
+ code;
47
+ fix;
48
+ details;
49
+ constructor(options) {
50
+ super(options.message);
51
+ this.name = "GraftError";
52
+ this.code = options.code;
53
+ this.fix = options.fix;
54
+ this.details = options.details;
55
+ }
56
+ toJSON() {
57
+ return {
58
+ error: this.code,
59
+ message: this.message,
60
+ fix: this.fix,
61
+ details: this.details
62
+ };
63
+ }
64
+ };
65
+
66
+ // src/introspection.ts
67
+ import { z } from "zod";
68
+ var ContentAuthority = z.enum([
69
+ "file-authoritative",
70
+ "db-authoritative",
71
+ "hybrid-with-drift-detection"
72
+ ]);
73
+ var FieldDescriptor = z.lazy(
74
+ () => z.object({
75
+ name: z.string(),
76
+ type: z.string(),
77
+ optional: z.boolean().default(false),
78
+ description: z.string().optional(),
79
+ fields: z.array(FieldDescriptor).optional(),
80
+ items: FieldDescriptor.optional()
81
+ })
82
+ );
83
+ var CollectionDescriptor = z.object({
84
+ name: z.string(),
85
+ authority: ContentAuthority,
86
+ fields: z.array(FieldDescriptor),
87
+ description: z.string().optional(),
88
+ /**
89
+ * Reading order for the collection's `section` values, when it groups.
90
+ *
91
+ * Section order is editorial — "Start here" before "Reference" — and there
92
+ * is nothing in the content to infer it from, since `order` restarts within
93
+ * each section. Declaring it on the collection means the site nav and any
94
+ * tool that lists content (Studio, agents) sort identically instead of each
95
+ * inventing an order. Sections not listed sort last, so new content never
96
+ * disappears from a sidebar.
97
+ */
98
+ sections: z.array(z.string()).optional()
99
+ });
100
+ var FunctionDescriptor = z.object({
101
+ name: z.string(),
102
+ kind: z.enum(["query", "mutation"]),
103
+ args: z.array(FieldDescriptor),
104
+ returns: z.string().optional(),
105
+ description: z.string().optional(),
106
+ /** Anonymous callers allowed. Mutations default to false; queries to true. */
107
+ public: z.boolean().optional(),
108
+ /** Always human-gated: invoking it requires an approved, one-shot, input-bound approval. */
109
+ destructive: z.boolean().optional()
110
+ });
111
+ var SchemaDescription = z.object({
112
+ collections: z.array(CollectionDescriptor),
113
+ functions: z.array(FunctionDescriptor)
114
+ });
115
+ var RegistryItemType = z.enum(["block", "field", "access", "bundle"]);
116
+ var RegistryFileRole = z.enum(["module", "component", "content", "env", "editor"]);
117
+ var EditorComponentSpec = z.object({
118
+ /** The JSX name this describes, e.g. "Callout". */
119
+ component: z.string().min(1),
120
+ /** Display name for the card's chip. Defaults to `component`. */
121
+ label: z.string().min(1).optional(),
122
+ /** Prop to show as the card's heading instead of guessing. */
123
+ titleProp: z.string().optional(),
124
+ /** Prop holding a destination, shown as a chip. */
125
+ linkProp: z.string().optional(),
126
+ /**
127
+ * Colour the card by one of its props — `type="warning"` on a Callout should
128
+ * look like a warning. Values map to the editor's own tone roles, so a
129
+ * third-party component cannot introduce a colour the theme does not have.
130
+ */
131
+ tone: z.object({
132
+ prop: z.string().min(1),
133
+ map: z.record(z.string(), z.enum(["info", "warn", "danger", "success", "neutral"]))
134
+ }).optional(),
135
+ /** Props already implied by the card's shape, not worth listing again. */
136
+ hideProps: z.array(z.string()).default([]),
137
+ /** Declarations for the children this component expects, e.g. DocCard inside DocCards. */
138
+ children: z.array(z.string()).default([]),
139
+ /**
140
+ * The exact MDX inserted when the operator picks this component from the
141
+ * palette. Authored by whoever wrote the component, because only they know
142
+ * which props are required and what a sensible starting body is — a guess
143
+ * assembled from the other fields would produce blocks that do not compile.
144
+ * Without one the component is still rendered, just not offered for insert.
145
+ *
146
+ * **Put the opening tag on a line of its own.** Markdown only treats JSX as
147
+ * one HTML *block* when nothing else shares the opening tag's line; write
148
+ * `<Callout>text</Callout>` on a single line and remark splits it into an
149
+ * open tag, a text node and a close tag, which renders as three pieces of
150
+ * raw source rather than one card. Every authored component in this repo is
151
+ * written the block way for exactly this reason.
152
+ */
153
+ snippet: z.string().min(1).optional()
154
+ });
155
+ var EditorComponentList = z.object({ components: z.array(EditorComponentSpec) });
156
+ var RegistryFileDescriptor = z.object({
157
+ target: z.string(),
158
+ role: RegistryFileRole
159
+ });
160
+ var RegistryItemDescriptor = z.object({
161
+ name: z.string(),
162
+ type: RegistryItemType,
163
+ description: z.string(),
164
+ /** Semver range against @usegraft/core; "*" = any (pre-1.0 default). */
165
+ graftVersion: z.string(),
166
+ /** npm packages the target must install first (package → version range). */
167
+ dependencies: z.record(z.string(), z.string()),
168
+ /** Other registry items `graft add` pulls in first (transitive). */
169
+ registryDependencies: z.array(z.string()),
170
+ /** The files this item writes into the project. */
171
+ files: z.array(RegistryFileDescriptor),
172
+ /** Whether the item ships an llms.txt teaching fragment. */
173
+ llms: z.boolean()
174
+ });
175
+ export {
176
+ CollectionDescriptor,
177
+ ContentAuthority,
178
+ EditorComponentList,
179
+ EditorComponentSpec,
180
+ ErrorCodes,
181
+ FieldDescriptor,
182
+ FunctionDescriptor,
183
+ GraftError,
184
+ RegistryFileDescriptor,
185
+ RegistryFileRole,
186
+ RegistryItemDescriptor,
187
+ RegistryItemType,
188
+ SchemaDescription
189
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@usegraft/contracts",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/AndersonDesign1/graft.git",
8
+ "directory": "packages/contracts"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "dependencies": {
27
+ "zod": "^4.1.0"
28
+ },
29
+ "engines": {
30
+ "node": ">=22.16"
31
+ },
32
+ "scripts": {
33
+ "build": "tsup src/index.ts --format esm --dts --clean",
34
+ "dev": "tsup src/index.ts --format esm --watch",
35
+ "typecheck": "tsc --noEmit",
36
+ "test": "vitest run",
37
+ "lint": "oxlint ."
38
+ }
39
+ }