@vieda/api-contract 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.
@@ -0,0 +1,653 @@
1
+ import { type AssetEntry, type AssetManifest, type ComponentDoc, type TokensDoc, type ViedaConfig } from '@vieda/ir';
2
+ import { z } from 'zod';
3
+ /**
4
+ * Maximum size of a single uploaded asset. Kept safely under Vercel's ~4.5MB
5
+ * serverless request/response body limit, since asset bytes flow through the
6
+ * cloud function in both directions. Enforced by the cloud upload route, the
7
+ * local editor server, and a `vd publish` pre-check so all three agree.
8
+ */
9
+ export declare const MAX_ASSET_BYTES: number;
10
+ /** An empty manifest — the "no assets" state, used as a parse/consumer default. */
11
+ export declare const EMPTY_ASSET_MANIFEST: AssetManifest;
12
+ /** MIME type by extension, for uploads that arrive without a content type. */
13
+ export declare const CONTENT_TYPE_BY_EXT: Record<string, string>;
14
+ /**
15
+ * Bare, lowercased file extension, or null when there isn't a usable one.
16
+ * Shared so the local and cloud upload handlers derive it identically.
17
+ */
18
+ export declare function assetExtOf(filename: string): string | null;
19
+ /** Stored content type: the provided one, else inferred from the extension. */
20
+ export declare function assetContentType(ext: string, provided?: string): string;
21
+ /**
22
+ * Deterministic JSON serialization: independent of object key order and (via
23
+ * codepoint key sorting, not localeCompare) of the machine's locale. Both
24
+ * sync-state checks build on it — the CLI hashes it into design/version.json,
25
+ * and the cloud compares Draft vs latest Version canonical strings directly.
26
+ * Array order is preserved: it's meaningful in documents (children).
27
+ */
28
+ export declare function canonicalJson(value: unknown): string;
29
+ /**
30
+ * Sync state of the editable design source against published Versions, as
31
+ * reported by GET /api/backend. Local backend: design/ vs design/version.json.
32
+ * Cloud backend: the Draft vs the latest published Version. Matches the
33
+ * compiler's `CompileProvenance` shape so the CLI can reuse it directly.
34
+ */
35
+ export interface DesignVersionState {
36
+ number: number;
37
+ label: string | null;
38
+ publishedAt: string;
39
+ /** True when the editable source has drifted from the published Version. */
40
+ modified: boolean;
41
+ }
42
+ /** What GET /api/project returns from both the local and cloud backends. */
43
+ export interface ProjectPayload {
44
+ config: ViedaConfig;
45
+ components: ComponentDoc[];
46
+ tokens: TokensDoc;
47
+ assets: AssetManifest;
48
+ }
49
+ /**
50
+ * What GET /api/backend returns. The editor probes this once to decide which
51
+ * shell to render and which actions (generate/publish/pull) to expose.
52
+ */
53
+ export interface BackendInfo {
54
+ mode: 'local' | 'cloud';
55
+ capabilities: {
56
+ generate: boolean;
57
+ publish: boolean;
58
+ pull: boolean;
59
+ /** Whether this backend accepts asset uploads (POST .../assets). */
60
+ upload: boolean;
61
+ /**
62
+ * Whether this backend can scan the project's source code for component
63
+ * references (GET .../components/:name/code-usage). Local only — the
64
+ * cloud stores design documents, never the repo.
65
+ */
66
+ codeUsage: boolean;
67
+ };
68
+ user?: {
69
+ email: string;
70
+ name?: string;
71
+ };
72
+ project?: {
73
+ id: string;
74
+ name: string;
75
+ };
76
+ /**
77
+ * Which published Version the editable design source corresponds to, and
78
+ * whether it has been modified since. Absent when the project has never
79
+ * been pulled/published (local) or has no published Versions (cloud).
80
+ */
81
+ designVersion?: DesignVersionState;
82
+ }
83
+ /** Immutable metadata for one published Version. */
84
+ export interface VersionMeta {
85
+ id: string;
86
+ number: number;
87
+ label: string | null;
88
+ createdAt: string;
89
+ createdBy: {
90
+ email: string;
91
+ name?: string;
92
+ };
93
+ basedOnVersionId: string | null;
94
+ }
95
+ /** A full Version: metadata plus the whole-project document snapshot. */
96
+ export interface VersionSnapshot {
97
+ meta: VersionMeta;
98
+ components: ComponentDoc[];
99
+ tokens: TokensDoc;
100
+ assets: AssetManifest;
101
+ }
102
+ export declare const versionMetaSchema: z.ZodObject<{
103
+ id: z.ZodString;
104
+ number: z.ZodNumber;
105
+ label: z.ZodNullable<z.ZodString>;
106
+ createdAt: z.ZodString;
107
+ createdBy: z.ZodObject<{
108
+ email: z.ZodString;
109
+ name: z.ZodOptional<z.ZodString>;
110
+ }, "strip", z.ZodTypeAny, {
111
+ email: string;
112
+ name?: string | undefined;
113
+ }, {
114
+ email: string;
115
+ name?: string | undefined;
116
+ }>;
117
+ basedOnVersionId: z.ZodNullable<z.ZodString>;
118
+ }, "strip", z.ZodTypeAny, {
119
+ number: number;
120
+ id: string;
121
+ label: string | null;
122
+ createdAt: string;
123
+ createdBy: {
124
+ email: string;
125
+ name?: string | undefined;
126
+ };
127
+ basedOnVersionId: string | null;
128
+ }, {
129
+ number: number;
130
+ id: string;
131
+ label: string | null;
132
+ createdAt: string;
133
+ createdBy: {
134
+ email: string;
135
+ name?: string | undefined;
136
+ };
137
+ basedOnVersionId: string | null;
138
+ }>;
139
+ /**
140
+ * Contents of `design/version.json` — written by `vd pull` and `vd publish`
141
+ * to record which published Version the local design files correspond to.
142
+ * `digest` is the CLI's canonical sha256 over the whole snapshot (components
143
+ * + tokens + assets manifest); `vd generate` recomputes it against the local
144
+ * files to detect modifications since the pull/publish and stamps generated
145
+ * headers accordingly.
146
+ */
147
+ export declare const designVersionFileSchema: z.ZodObject<{
148
+ schemaVersion: z.ZodLiteral<1>;
149
+ version: z.ZodObject<{
150
+ id: z.ZodString;
151
+ number: z.ZodNumber;
152
+ label: z.ZodNullable<z.ZodString>;
153
+ createdAt: z.ZodString;
154
+ createdBy: z.ZodObject<{
155
+ email: z.ZodString;
156
+ name: z.ZodOptional<z.ZodString>;
157
+ }, "strip", z.ZodTypeAny, {
158
+ email: string;
159
+ name?: string | undefined;
160
+ }, {
161
+ email: string;
162
+ name?: string | undefined;
163
+ }>;
164
+ basedOnVersionId: z.ZodNullable<z.ZodString>;
165
+ }, "strip", z.ZodTypeAny, {
166
+ number: number;
167
+ id: string;
168
+ label: string | null;
169
+ createdAt: string;
170
+ createdBy: {
171
+ email: string;
172
+ name?: string | undefined;
173
+ };
174
+ basedOnVersionId: string | null;
175
+ }, {
176
+ number: number;
177
+ id: string;
178
+ label: string | null;
179
+ createdAt: string;
180
+ createdBy: {
181
+ email: string;
182
+ name?: string | undefined;
183
+ };
184
+ basedOnVersionId: string | null;
185
+ }>;
186
+ digest: z.ZodString;
187
+ }, "strip", z.ZodTypeAny, {
188
+ schemaVersion: 1;
189
+ version: {
190
+ number: number;
191
+ id: string;
192
+ label: string | null;
193
+ createdAt: string;
194
+ createdBy: {
195
+ email: string;
196
+ name?: string | undefined;
197
+ };
198
+ basedOnVersionId: string | null;
199
+ };
200
+ digest: string;
201
+ }, {
202
+ schemaVersion: 1;
203
+ version: {
204
+ number: number;
205
+ id: string;
206
+ label: string | null;
207
+ createdAt: string;
208
+ createdBy: {
209
+ email: string;
210
+ name?: string | undefined;
211
+ };
212
+ basedOnVersionId: string | null;
213
+ };
214
+ digest: string;
215
+ }>;
216
+ export type DesignVersionFile = z.infer<typeof designVersionFileSchema>;
217
+ /**
218
+ * Validates a pulled snapshot with the exact document schemas the compiler
219
+ * uses locally, so a bad payload fails loudly before touching design files.
220
+ */
221
+ export declare const versionSnapshotSchema: z.ZodObject<{
222
+ meta: z.ZodObject<{
223
+ id: z.ZodString;
224
+ number: z.ZodNumber;
225
+ label: z.ZodNullable<z.ZodString>;
226
+ createdAt: z.ZodString;
227
+ createdBy: z.ZodObject<{
228
+ email: z.ZodString;
229
+ name: z.ZodOptional<z.ZodString>;
230
+ }, "strip", z.ZodTypeAny, {
231
+ email: string;
232
+ name?: string | undefined;
233
+ }, {
234
+ email: string;
235
+ name?: string | undefined;
236
+ }>;
237
+ basedOnVersionId: z.ZodNullable<z.ZodString>;
238
+ }, "strip", z.ZodTypeAny, {
239
+ number: number;
240
+ id: string;
241
+ label: string | null;
242
+ createdAt: string;
243
+ createdBy: {
244
+ email: string;
245
+ name?: string | undefined;
246
+ };
247
+ basedOnVersionId: string | null;
248
+ }, {
249
+ number: number;
250
+ id: string;
251
+ label: string | null;
252
+ createdAt: string;
253
+ createdBy: {
254
+ email: string;
255
+ name?: string | undefined;
256
+ };
257
+ basedOnVersionId: string | null;
258
+ }>;
259
+ components: z.ZodArray<z.ZodType<ComponentDoc, z.ZodTypeDef, ComponentDoc>, "many">;
260
+ tokens: z.ZodObject<{
261
+ schemaVersion: z.ZodNumber;
262
+ colors: z.ZodRecord<z.ZodString, z.ZodString>;
263
+ spacing: z.ZodRecord<z.ZodString, z.ZodNumber>;
264
+ radii: z.ZodRecord<z.ZodString, z.ZodNumber>;
265
+ textStyles: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
266
+ fontFamily: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
267
+ token: z.ZodString;
268
+ }, "strip", z.ZodTypeAny, {
269
+ token: string;
270
+ }, {
271
+ token: string;
272
+ }>]>>;
273
+ fontSize: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodType<import("@vieda/ir").UnitValue, z.ZodTypeDef, import("@vieda/ir").UnitValue>]>>;
274
+ fontWeight: z.ZodOptional<z.ZodNumber>;
275
+ fontStyle: z.ZodOptional<z.ZodEnum<["normal", "italic"]>>;
276
+ lineHeight: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodType<import("@vieda/ir").UnitValue, z.ZodTypeDef, import("@vieda/ir").UnitValue>]>>;
277
+ letterSpacing: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodType<import("@vieda/ir").UnitValue, z.ZodTypeDef, import("@vieda/ir").UnitValue>]>>;
278
+ color: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
279
+ token: z.ZodString;
280
+ }, "strip", z.ZodTypeAny, {
281
+ token: string;
282
+ }, {
283
+ token: string;
284
+ }>]>>;
285
+ textAlign: z.ZodOptional<z.ZodEnum<["left", "center", "right"]>>;
286
+ decoration: z.ZodOptional<z.ZodEnum<["underline", "strikethrough"]>>;
287
+ textCase: z.ZodOptional<z.ZodEnum<["uppercase", "lowercase", "capitalize"]>>;
288
+ }, "strip", z.ZodTypeAny, {
289
+ color
290
+ /** Recursively sort object keys (arrays keep their order). */
291
+ ?: string | {
292
+ token: string;
293
+ } | undefined;
294
+ fontFamily?: string | {
295
+ token: string;
296
+ } | undefined;
297
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
298
+ fontWeight?: number | undefined;
299
+ fontStyle?: "normal" | "italic" | undefined;
300
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
301
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
302
+ textAlign?: "left" | "center" | "right" | undefined;
303
+ decoration?: "underline" | "strikethrough" | undefined;
304
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
305
+ }, {
306
+ color?: string | {
307
+ token: string;
308
+ } | undefined;
309
+ fontFamily?: string | {
310
+ token: string;
311
+ } | undefined;
312
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
313
+ fontWeight?: number | undefined;
314
+ fontStyle?: "normal" | "italic" | undefined;
315
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
316
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
317
+ textAlign?: "left" | "center" | "right" | undefined;
318
+ decoration?: "underline" | "strikethrough" | undefined;
319
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
320
+ }>>>;
321
+ fonts: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
322
+ family: z.ZodString;
323
+ url: z.ZodString;
324
+ weights: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
325
+ fallback: z.ZodOptional<z.ZodString>;
326
+ }, "strip", z.ZodTypeAny, {
327
+ family: string;
328
+ url: string;
329
+ weights?: number[] | undefined;
330
+ fallback?: string | undefined;
331
+ }, {
332
+ family: string;
333
+ url: string;
334
+ weights?: number[] | undefined;
335
+ fallback?: string | undefined;
336
+ }>>>;
337
+ breakpoints: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodNumber>>;
338
+ resetDefaultStyles: z.ZodOptional<z.ZodBoolean>;
339
+ settings: z.ZodOptional<z.ZodObject<{
340
+ allowedUnits: z.ZodOptional<z.ZodArray<z.ZodEnum<["rem", "em", "%"]>, "many">>;
341
+ }, "strip", z.ZodTypeAny, {
342
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
343
+ }, {
344
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
345
+ }>>;
346
+ }, "strip", z.ZodTypeAny, {
347
+ schemaVersion: number;
348
+ breakpoints: Record<string, number>;
349
+ colors: Record<string, string>;
350
+ spacing: Record<string, number>;
351
+ radii: Record<string, number>;
352
+ textStyles: Record<string, {
353
+ color?: string | {
354
+ token: string;
355
+ } | undefined;
356
+ fontFamily?: string | {
357
+ token: string;
358
+ } | undefined;
359
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
360
+ fontWeight?: number | undefined;
361
+ fontStyle?: "normal" | "italic" | undefined;
362
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
363
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
364
+ textAlign?: "left" | "center" | "right" | undefined;
365
+ decoration?: "underline" | "strikethrough" | undefined;
366
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
367
+ }>;
368
+ fonts: Record<string, {
369
+ family: string;
370
+ url: string;
371
+ weights?: number[] | undefined;
372
+ fallback?: string | undefined;
373
+ }>;
374
+ resetDefaultStyles?: boolean | undefined;
375
+ settings?: {
376
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
377
+ } | undefined;
378
+ }, {
379
+ schemaVersion: number;
380
+ colors: Record<string, string>;
381
+ spacing: Record<string, number>;
382
+ radii: Record<string, number>;
383
+ breakpoints?: Record<string, number> | undefined;
384
+ textStyles?: Record<string, {
385
+ color?: string | {
386
+ token: string;
387
+ } | undefined;
388
+ fontFamily?: string | {
389
+ token: string;
390
+ } | undefined;
391
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
392
+ fontWeight?: number | undefined;
393
+ fontStyle?: "normal" | "italic" | undefined;
394
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
395
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
396
+ textAlign?: "left" | "center" | "right" | undefined;
397
+ decoration?: "underline" | "strikethrough" | undefined;
398
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
399
+ }> | undefined;
400
+ fonts?: Record<string, {
401
+ family: string;
402
+ url: string;
403
+ weights?: number[] | undefined;
404
+ fallback?: string | undefined;
405
+ }> | undefined;
406
+ resetDefaultStyles?: boolean | undefined;
407
+ settings?: {
408
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
409
+ } | undefined;
410
+ }>;
411
+ assets: z.ZodDefault<z.ZodObject<{
412
+ schemaVersion: z.ZodNumber;
413
+ assets: z.ZodDefault<z.ZodArray<z.ZodObject<{
414
+ name: z.ZodString;
415
+ digest: z.ZodString;
416
+ contentType: z.ZodString;
417
+ ext: z.ZodString;
418
+ }, "strip", z.ZodTypeAny, {
419
+ name: string;
420
+ digest: string;
421
+ contentType: string;
422
+ ext: string;
423
+ }, {
424
+ name: string;
425
+ digest: string;
426
+ contentType: string;
427
+ ext: string;
428
+ }>, "many">>;
429
+ }, "strip", z.ZodTypeAny, {
430
+ assets: {
431
+ name: string;
432
+ digest: string;
433
+ contentType: string;
434
+ ext: string;
435
+ }[];
436
+ schemaVersion: number;
437
+ }, {
438
+ schemaVersion: number;
439
+ assets?: {
440
+ name: string;
441
+ digest: string;
442
+ contentType: string;
443
+ ext: string;
444
+ }[] | undefined;
445
+ }>>;
446
+ }, "strip", z.ZodTypeAny, {
447
+ meta: {
448
+ number: number;
449
+ id: string;
450
+ label: string | null;
451
+ createdAt: string;
452
+ createdBy: {
453
+ email: string;
454
+ name?: string | undefined;
455
+ };
456
+ basedOnVersionId: string | null;
457
+ };
458
+ components: ComponentDoc[];
459
+ tokens: {
460
+ schemaVersion: number;
461
+ breakpoints: Record<string, number>;
462
+ colors: Record<string, string>;
463
+ spacing: Record<string, number>;
464
+ radii: Record<string, number>;
465
+ textStyles: Record<string, {
466
+ color?: string | {
467
+ token: string;
468
+ } | undefined;
469
+ fontFamily?: string | {
470
+ token: string;
471
+ } | undefined;
472
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
473
+ fontWeight?: number | undefined;
474
+ fontStyle?: "normal" | "italic" | undefined;
475
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
476
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
477
+ textAlign?: "left" | "center" | "right" | undefined;
478
+ decoration?: "underline" | "strikethrough" | undefined;
479
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
480
+ }>;
481
+ fonts: Record<string, {
482
+ family: string;
483
+ url: string;
484
+ weights?: number[] | undefined;
485
+ fallback?: string | undefined;
486
+ }>;
487
+ resetDefaultStyles?: boolean | undefined;
488
+ settings?: {
489
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
490
+ } | undefined;
491
+ };
492
+ assets: {
493
+ assets: {
494
+ name: string;
495
+ digest: string;
496
+ contentType: string;
497
+ ext: string;
498
+ }[];
499
+ schemaVersion: number;
500
+ };
501
+ }, {
502
+ meta: {
503
+ number: number;
504
+ id: string;
505
+ label: string | null;
506
+ createdAt: string;
507
+ createdBy: {
508
+ email: string;
509
+ name?: string | undefined;
510
+ };
511
+ basedOnVersionId: string | null;
512
+ };
513
+ components: ComponentDoc[];
514
+ tokens: {
515
+ schemaVersion: number;
516
+ colors: Record<string, string>;
517
+ spacing: Record<string, number>;
518
+ radii: Record<string, number>;
519
+ breakpoints?: Record<string, number> | undefined;
520
+ textStyles?: Record<string, {
521
+ color?: string | {
522
+ token: string;
523
+ } | undefined;
524
+ fontFamily?: string | {
525
+ token: string;
526
+ } | undefined;
527
+ fontSize?: number | import("@vieda/ir").UnitValue | undefined;
528
+ fontWeight?: number | undefined;
529
+ fontStyle?: "normal" | "italic" | undefined;
530
+ lineHeight?: number | import("@vieda/ir").UnitValue | undefined;
531
+ letterSpacing?: number | import("@vieda/ir").UnitValue | undefined;
532
+ textAlign?: "left" | "center" | "right" | undefined;
533
+ decoration?: "underline" | "strikethrough" | undefined;
534
+ textCase?: "uppercase" | "lowercase" | "capitalize" | undefined;
535
+ }> | undefined;
536
+ fonts?: Record<string, {
537
+ family: string;
538
+ url: string;
539
+ weights?: number[] | undefined;
540
+ fallback?: string | undefined;
541
+ }> | undefined;
542
+ resetDefaultStyles?: boolean | undefined;
543
+ settings?: {
544
+ allowedUnits?: ("rem" | "em" | "%")[] | undefined;
545
+ } | undefined;
546
+ };
547
+ assets?: {
548
+ schemaVersion: number;
549
+ assets?: {
550
+ name: string;
551
+ digest: string;
552
+ contentType: string;
553
+ ext: string;
554
+ }[] | undefined;
555
+ } | undefined;
556
+ }>;
557
+ /** One project as listed for the CLI and the cloud project picker. */
558
+ export interface ProjectSummary {
559
+ id: string;
560
+ name: string;
561
+ org: {
562
+ id: string;
563
+ name: string;
564
+ };
565
+ }
566
+ /** What a pull reports back: design files written and stale files removed. */
567
+ export interface PullResult {
568
+ written: string[];
569
+ deleted: string[];
570
+ /** Asset files written into assetsDir. */
571
+ assetsWritten: string[];
572
+ /** Stale asset files removed from assetsDir. */
573
+ assetsDeleted: string[];
574
+ version: VersionMeta;
575
+ }
576
+ /**
577
+ * What POST .../assets returns: the manifest entry for the uploaded file. The
578
+ * server derives `digest` (sha256) and `ext` from the bytes and original name,
579
+ * deduping identical content, so repeated uploads are cheap.
580
+ */
581
+ export type AssetUploadResult = AssetEntry;
582
+ export declare const assetUploadResultSchema: z.ZodObject<{
583
+ name: z.ZodString;
584
+ digest: z.ZodString;
585
+ contentType: z.ZodString;
586
+ ext: z.ZodString;
587
+ }, "strip", z.ZodTypeAny, {
588
+ name: string;
589
+ digest: string;
590
+ contentType: string;
591
+ ext: string;
592
+ }, {
593
+ name: string;
594
+ digest: string;
595
+ contentType: string;
596
+ ext: string;
597
+ }>;
598
+ /**
599
+ * What PATCH .../assets/:name returns: the manifest entry under its new name.
600
+ * The request body is JSON `{ name: string }`. Both backends implement the
601
+ * same contract: `200` with the updated entry (digest unchanged — the bytes
602
+ * don't move); `400` if the new name fails the asset-name regex; `404` if
603
+ * `:name` isn't in the manifest; `409` if the new name is already taken.
604
+ */
605
+ export type AssetRenameResult = AssetEntry;
606
+ export declare const assetRenameResultSchema: z.ZodObject<{
607
+ name: z.ZodString;
608
+ digest: z.ZodString;
609
+ contentType: z.ZodString;
610
+ ext: z.ZodString;
611
+ }, "strip", z.ZodTypeAny, {
612
+ name: string;
613
+ digest: string;
614
+ contentType: string;
615
+ ext: string;
616
+ }, {
617
+ name: string;
618
+ digest: string;
619
+ contentType: string;
620
+ ext: string;
621
+ }>;
622
+ /**
623
+ * What GET .../components/:name/code-usage returns: places in the project's
624
+ * own (non-generated) source files that mention the component, so the editor
625
+ * can warn before a delete that hand-written code still imports or renders
626
+ * it. Best-effort text search — `404` if `:name` isn't a component. Local
627
+ * backend only; gated by the `codeUsage` capability.
628
+ */
629
+ export interface CodeUsageResult {
630
+ matches: CodeUsageMatch[];
631
+ /** True when the scan stopped early because the match cap was hit. */
632
+ truncated: boolean;
633
+ }
634
+ export interface CodeUsageMatch {
635
+ /** Repo-relative POSIX path of the referencing file. */
636
+ file: string;
637
+ /** 1-based line number of the match. */
638
+ line: number;
639
+ /** The matching line, trimmed. */
640
+ text: string;
641
+ }
642
+ /**
643
+ * What PATCH .../components/:name returns: the renamed component document. The
644
+ * request body is JSON `{ name: string }` (the new PascalCase name). Both
645
+ * backends implement the same contract: `200` with the renamed doc (its
646
+ * internal `name`, and the root node's name when it still matched, updated to
647
+ * the new name); `400` if the new name isn't PascalCase; `404` if `:name`
648
+ * isn't a component; `409` if the new name is already taken. Cross-document
649
+ * instance references are the editor's responsibility, not the route's.
650
+ */
651
+ export type ComponentRenameResult = ComponentDoc;
652
+ export declare const componentRenameResultSchema: z.ZodType<ComponentDoc, z.ZodTypeDef, ComponentDoc>;
653
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ import { assetEntrySchema, assetManifestSchema, componentDocSchema, tokensDocSchema, } from '@vieda/ir';
2
+ import { z } from 'zod';
3
+ /**
4
+ * Maximum size of a single uploaded asset. Kept safely under Vercel's ~4.5MB
5
+ * serverless request/response body limit, since asset bytes flow through the
6
+ * cloud function in both directions. Enforced by the cloud upload route, the
7
+ * local editor server, and a `vd publish` pre-check so all three agree.
8
+ */
9
+ export const MAX_ASSET_BYTES = 4 * 1024 * 1024;
10
+ /** An empty manifest — the "no assets" state, used as a parse/consumer default. */
11
+ export const EMPTY_ASSET_MANIFEST = { schemaVersion: 1, assets: [] };
12
+ /** MIME type by extension, for uploads that arrive without a content type. */
13
+ export const CONTENT_TYPE_BY_EXT = {
14
+ png: 'image/png',
15
+ jpg: 'image/jpeg',
16
+ jpeg: 'image/jpeg',
17
+ gif: 'image/gif',
18
+ webp: 'image/webp',
19
+ avif: 'image/avif',
20
+ svg: 'image/svg+xml',
21
+ };
22
+ /**
23
+ * Bare, lowercased file extension, or null when there isn't a usable one.
24
+ * Shared so the local and cloud upload handlers derive it identically.
25
+ */
26
+ export function assetExtOf(filename) {
27
+ const dot = filename.lastIndexOf('.');
28
+ if (dot < 0 || dot === filename.length - 1)
29
+ return null;
30
+ const ext = filename.slice(dot + 1).toLowerCase();
31
+ return /^[a-z0-9]+$/.test(ext) ? ext : null;
32
+ }
33
+ /** Stored content type: the provided one, else inferred from the extension. */
34
+ export function assetContentType(ext, provided) {
35
+ return provided || CONTENT_TYPE_BY_EXT[ext] || 'application/octet-stream';
36
+ }
37
+ /** Recursively sort object keys (arrays keep their order). */
38
+ function canonical(value) {
39
+ if (Array.isArray(value))
40
+ return value.map(canonical);
41
+ if (value && typeof value === 'object') {
42
+ return Object.fromEntries(Object.entries(value)
43
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
44
+ .map(([k, v]) => [k, canonical(v)]));
45
+ }
46
+ return value;
47
+ }
48
+ /**
49
+ * Deterministic JSON serialization: independent of object key order and (via
50
+ * codepoint key sorting, not localeCompare) of the machine's locale. Both
51
+ * sync-state checks build on it — the CLI hashes it into design/version.json,
52
+ * and the cloud compares Draft vs latest Version canonical strings directly.
53
+ * Array order is preserved: it's meaningful in documents (children).
54
+ */
55
+ export function canonicalJson(value) {
56
+ return JSON.stringify(canonical(value));
57
+ }
58
+ export const versionMetaSchema = z.object({
59
+ id: z.string(),
60
+ number: z.number().int().positive(),
61
+ label: z.string().nullable(),
62
+ createdAt: z.string(),
63
+ createdBy: z.object({ email: z.string(), name: z.string().optional() }),
64
+ basedOnVersionId: z.string().nullable(),
65
+ });
66
+ /**
67
+ * Contents of `design/version.json` — written by `vd pull` and `vd publish`
68
+ * to record which published Version the local design files correspond to.
69
+ * `digest` is the CLI's canonical sha256 over the whole snapshot (components
70
+ * + tokens + assets manifest); `vd generate` recomputes it against the local
71
+ * files to detect modifications since the pull/publish and stamps generated
72
+ * headers accordingly.
73
+ */
74
+ export const designVersionFileSchema = z.object({
75
+ schemaVersion: z.literal(1),
76
+ version: versionMetaSchema,
77
+ digest: z.string(),
78
+ });
79
+ /**
80
+ * Validates a pulled snapshot with the exact document schemas the compiler
81
+ * uses locally, so a bad payload fails loudly before touching design files.
82
+ */
83
+ export const versionSnapshotSchema = z.object({
84
+ meta: versionMetaSchema,
85
+ components: z.array(componentDocSchema),
86
+ tokens: tokensDocSchema,
87
+ // Defaulted so Versions published before assets existed still validate.
88
+ assets: assetManifestSchema.default(EMPTY_ASSET_MANIFEST),
89
+ });
90
+ export const assetUploadResultSchema = assetEntrySchema;
91
+ export const assetRenameResultSchema = assetEntrySchema;
92
+ export const componentRenameResultSchema = componentDocSchema;
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@vieda/api-contract",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "dependencies": {
20
+ "zod": "^3.24.0",
21
+ "@vieda/ir": "0.1.0"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.6.0"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json",
28
+ "typecheck": "tsc -p tsconfig.json --noEmit"
29
+ }
30
+ }