@drawcall/design 0.5.0 → 0.5.2

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.
@@ -1,6 +1,7 @@
1
1
  import { oc } from "@orpc/contract";
2
2
  import { z } from "zod";
3
- import { createFrameSchema, createProjectFromBriefSchema, designIdSchema, fileListSchema, fileMutationSchema, fileSchema, fileTextSchema, frameNameSchema, frameSchema, generateImageFrameSchema, projectDirectoryPathSchema, projectNameSchema, projectPathSchema, projectSchema, screenshotSchema, userSchema, } from "./schemas.js";
3
+ import { projectFrameLayoutSchema } from "../project-state.js";
4
+ import { cameraPoseSchema, createFrameSchema, createProjectFromBriefSchema, designIdSchema, fileListSchema, fileMutationSchema, fileSchema, fileTextSchema, frameExportSchema, frameNameSchema, frameSchema, generateImageFrameSchema, projectDirectoryPathSchema, projectNameSchema, projectPathSchema, projectSchema, screenshotSchema, userSchema, } from "./schemas.js";
4
5
  const projectInputSchema = z.object({ project: designIdSchema });
5
6
  const frameInputSchema = projectInputSchema.extend({ frame: designIdSchema });
6
7
  const fileInputSchema = projectInputSchema.extend({ path: projectPathSchema });
@@ -57,6 +58,24 @@ export const contract = {
57
58
  .route({ method: "PATCH", path: "/projects/{project}/frames/{frame}" })
58
59
  .input(frameInputSchema.extend({ name: frameNameSchema }))
59
60
  .output(frameSchema),
61
+ setCamera: oc
62
+ .route({
63
+ method: "PUT",
64
+ path: "/projects/{project}/frames/{frame}/camera",
65
+ })
66
+ .input(frameInputSchema.extend({
67
+ camera: cameraPoseSchema,
68
+ expectedContentRevision: z.number().int().nonnegative(),
69
+ expectedUpdatedAt: z.string().datetime(),
70
+ }))
71
+ .output(frameSchema),
72
+ setLayout: oc
73
+ .route({
74
+ method: "PUT",
75
+ path: "/projects/{project}/frames/{frame}/layout",
76
+ })
77
+ .input(frameInputSchema.extend(projectFrameLayoutSchema.shape))
78
+ .output(frameSchema),
60
79
  delete: oc
61
80
  .route({ method: "DELETE", path: "/projects/{project}/frames/{frame}" })
62
81
  .input(frameInputSchema)
@@ -68,6 +87,13 @@ export const contract = {
68
87
  })
69
88
  .input(frameInputSchema)
70
89
  .output(screenshotSchema),
90
+ prepareExport: oc
91
+ .route({
92
+ method: "POST",
93
+ path: "/projects/{project}/frames/{frame}/exports",
94
+ })
95
+ .input(frameInputSchema)
96
+ .output(frameExportSchema),
71
97
  },
72
98
  filesystem: {
73
99
  list: oc
@@ -16,6 +16,19 @@ export declare const projectDerivationStatusSchema: z.ZodEnum<{
16
16
  export declare const frameNameSchema: z.ZodString;
17
17
  export declare const frameSizeSchema: z.ZodNumber;
18
18
  export declare const framePositionSchema: z.ZodNumber;
19
+ export declare const cameraPoseSchema: z.ZodObject<{
20
+ position: z.ZodObject<{
21
+ x: z.ZodNumber;
22
+ y: z.ZodNumber;
23
+ z: z.ZodNumber;
24
+ }, z.core.$strict>;
25
+ quaternion: z.ZodObject<{
26
+ x: z.ZodNumber;
27
+ y: z.ZodNumber;
28
+ z: z.ZodNumber;
29
+ w: z.ZodNumber;
30
+ }, z.core.$strict>;
31
+ }, z.core.$strict>;
19
32
  export declare const httpUrlSchema: z.ZodString;
20
33
  export declare const imageUrlSchema: z.ZodString;
21
34
  /** An absolute path in the hosted project filesystem. */
@@ -63,6 +76,20 @@ export declare const gltsFrameSchema: z.ZodObject<{
63
76
  createdAt: z.ZodString;
64
77
  updatedAt: z.ZodString;
65
78
  type: z.ZodLiteral<"glts">;
79
+ camera: z.ZodOptional<z.ZodObject<{
80
+ position: z.ZodObject<{
81
+ x: z.ZodNumber;
82
+ y: z.ZodNumber;
83
+ z: z.ZodNumber;
84
+ }, z.core.$strict>;
85
+ quaternion: z.ZodObject<{
86
+ x: z.ZodNumber;
87
+ y: z.ZodNumber;
88
+ z: z.ZodNumber;
89
+ w: z.ZodNumber;
90
+ }, z.core.$strict>;
91
+ }, z.core.$strict>>;
92
+ contentRevision: z.ZodNumber;
66
93
  }, z.core.$strip>;
67
94
  export declare const imageGenerationOperationSchema: z.ZodEnum<{
68
95
  generate: "generate";
@@ -190,6 +217,20 @@ export declare const frameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
190
217
  createdAt: z.ZodString;
191
218
  updatedAt: z.ZodString;
192
219
  type: z.ZodLiteral<"glts">;
220
+ camera: z.ZodOptional<z.ZodObject<{
221
+ position: z.ZodObject<{
222
+ x: z.ZodNumber;
223
+ y: z.ZodNumber;
224
+ z: z.ZodNumber;
225
+ }, z.core.$strict>;
226
+ quaternion: z.ZodObject<{
227
+ x: z.ZodNumber;
228
+ y: z.ZodNumber;
229
+ z: z.ZodNumber;
230
+ w: z.ZodNumber;
231
+ }, z.core.$strict>;
232
+ }, z.core.$strict>>;
233
+ contentRevision: z.ZodNumber;
193
234
  }, z.core.$strip>, z.ZodObject<{
194
235
  id: z.ZodString;
195
236
  projectId: z.ZodString;
@@ -352,10 +393,101 @@ export declare const screenshotSchema: z.ZodObject<{
352
393
  height: z.ZodNumber;
353
394
  mediaType: z.ZodLiteral<"image/png">;
354
395
  }, z.core.$strip>;
396
+ export declare const gltsFrameExportSchema: z.ZodObject<{
397
+ frameId: z.ZodString;
398
+ frameName: z.ZodString;
399
+ projectId: z.ZodString;
400
+ type: z.ZodLiteral<"glts">;
401
+ runtime: z.ZodObject<{
402
+ gltf: z.ZodObject<{
403
+ filename: z.ZodString;
404
+ }, z.core.$strip>;
405
+ stl: z.ZodObject<{
406
+ filename: z.ZodString;
407
+ }, z.core.$strip>;
408
+ }, z.core.$strip>;
409
+ sourceArchive: z.ZodNullable<z.ZodObject<{
410
+ filename: z.ZodString;
411
+ url: z.ZodString;
412
+ mediaType: z.ZodLiteral<"application/zip">;
413
+ }, z.core.$strict>>;
414
+ }, z.core.$strip>;
415
+ export declare const imageFrameExportSchema: z.ZodObject<{
416
+ frameId: z.ZodString;
417
+ frameName: z.ZodString;
418
+ projectId: z.ZodString;
419
+ type: z.ZodLiteral<"image">;
420
+ download: z.ZodObject<{
421
+ filename: z.ZodString;
422
+ url: z.ZodString;
423
+ mediaType: z.ZodEnum<{
424
+ "image/png": "image/png";
425
+ "image/jpeg": "image/jpeg";
426
+ "image/webp": "image/webp";
427
+ }>;
428
+ }, z.core.$strict>;
429
+ }, z.core.$strip>;
430
+ export declare const marketFrameExportSchema: z.ZodObject<{
431
+ frameId: z.ZodString;
432
+ frameName: z.ZodString;
433
+ projectId: z.ZodString;
434
+ type: z.ZodLiteral<"market">;
435
+ asset: z.ZodString;
436
+ download: z.ZodObject<{
437
+ filename: z.ZodString;
438
+ url: z.ZodString;
439
+ mediaType: z.ZodLiteral<"application/zip">;
440
+ }, z.core.$strict>;
441
+ }, z.core.$strip>;
442
+ export declare const frameExportSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
443
+ frameId: z.ZodString;
444
+ frameName: z.ZodString;
445
+ projectId: z.ZodString;
446
+ type: z.ZodLiteral<"glts">;
447
+ runtime: z.ZodObject<{
448
+ gltf: z.ZodObject<{
449
+ filename: z.ZodString;
450
+ }, z.core.$strip>;
451
+ stl: z.ZodObject<{
452
+ filename: z.ZodString;
453
+ }, z.core.$strip>;
454
+ }, z.core.$strip>;
455
+ sourceArchive: z.ZodNullable<z.ZodObject<{
456
+ filename: z.ZodString;
457
+ url: z.ZodString;
458
+ mediaType: z.ZodLiteral<"application/zip">;
459
+ }, z.core.$strict>>;
460
+ }, z.core.$strip>, z.ZodObject<{
461
+ frameId: z.ZodString;
462
+ frameName: z.ZodString;
463
+ projectId: z.ZodString;
464
+ type: z.ZodLiteral<"image">;
465
+ download: z.ZodObject<{
466
+ filename: z.ZodString;
467
+ url: z.ZodString;
468
+ mediaType: z.ZodEnum<{
469
+ "image/png": "image/png";
470
+ "image/jpeg": "image/jpeg";
471
+ "image/webp": "image/webp";
472
+ }>;
473
+ }, z.core.$strict>;
474
+ }, z.core.$strip>, z.ZodObject<{
475
+ frameId: z.ZodString;
476
+ frameName: z.ZodString;
477
+ projectId: z.ZodString;
478
+ type: z.ZodLiteral<"market">;
479
+ asset: z.ZodString;
480
+ download: z.ZodObject<{
481
+ filename: z.ZodString;
482
+ url: z.ZodString;
483
+ mediaType: z.ZodLiteral<"application/zip">;
484
+ }, z.core.$strict>;
485
+ }, z.core.$strip>], "type">;
355
486
  export type User = z.infer<typeof userSchema>;
356
487
  export type Project = z.infer<typeof projectSchema>;
357
488
  export type CreateProjectFromBrief = z.infer<typeof createProjectFromBriefSchema>;
358
489
  export type ProjectDerivationStatus = z.infer<typeof projectDerivationStatusSchema>;
490
+ export type CameraPose = z.infer<typeof cameraPoseSchema>;
359
491
  export type GltsFrame = z.infer<typeof gltsFrameSchema>;
360
492
  export type ImageFrame = z.infer<typeof imageFrameSchema>;
361
493
  export type ImageGenerationOperation = z.infer<typeof imageGenerationOperationSchema>;
@@ -374,3 +506,7 @@ export type BinaryFile = z.infer<typeof binaryFileSchema>;
374
506
  export type DesignFile = z.infer<typeof fileSchema>;
375
507
  export type FileMutation = z.infer<typeof fileMutationSchema>;
376
508
  export type Screenshot = z.infer<typeof screenshotSchema>;
509
+ export type GltsFrameExport = z.infer<typeof gltsFrameExportSchema>;
510
+ export type ImageFrameExport = z.infer<typeof imageFrameExportSchema>;
511
+ export type MarketFrameExport = z.infer<typeof marketFrameExportSchema>;
512
+ export type FrameExport = z.infer<typeof frameExportSchema>;
@@ -31,6 +31,28 @@ export const frameNameSchema = z
31
31
  .refine((name) => !name.includes("/"), "Frame names cannot contain /");
32
32
  export const frameSizeSchema = z.number().int().min(1).max(MAX_FRAME_DIMENSION);
33
33
  export const framePositionSchema = z.number().finite();
34
+ const cameraPositionSchema = z
35
+ .object({
36
+ x: framePositionSchema,
37
+ y: framePositionSchema,
38
+ z: framePositionSchema,
39
+ })
40
+ .strict();
41
+ const cameraQuaternionSchema = z
42
+ .object({
43
+ x: framePositionSchema,
44
+ y: framePositionSchema,
45
+ z: framePositionSchema,
46
+ w: framePositionSchema,
47
+ })
48
+ .strict()
49
+ .refine(isNormalizedQuaternion, "Camera quaternion must be normalized");
50
+ export const cameraPoseSchema = z
51
+ .object({
52
+ position: cameraPositionSchema,
53
+ quaternion: cameraQuaternionSchema,
54
+ })
55
+ .strict();
34
56
  export const httpUrlSchema = z
35
57
  .string()
36
58
  .url()
@@ -92,6 +114,8 @@ const frameBaseSchema = z.object({
92
114
  });
93
115
  export const gltsFrameSchema = frameBaseSchema.extend({
94
116
  type: z.literal("glts"),
117
+ camera: cameraPoseSchema.optional(),
118
+ contentRevision: z.number().int().nonnegative(),
95
119
  });
96
120
  export const imageGenerationOperationSchema = z.enum(["generate", "edit"]);
97
121
  export const imageGenerationResultSchema = z.enum(["new", "replace"]);
@@ -274,6 +298,56 @@ export const screenshotSchema = z.object({
274
298
  height: frameSizeSchema,
275
299
  mediaType: z.literal("image/png"),
276
300
  });
301
+ const frameExportFilenameSchema = z.object({
302
+ filename: z
303
+ .string()
304
+ .regex(/^[a-z0-9][a-z0-9._-]{0,159}$/, "Export filenames must be safe ASCII"),
305
+ });
306
+ const frameDownloadSchema = z
307
+ .object({
308
+ url: httpUrlSchema,
309
+ mediaType: z.string().min(1),
310
+ ...frameExportFilenameSchema.shape,
311
+ })
312
+ .strict();
313
+ const marketDownloadSchema = frameDownloadSchema.extend({
314
+ url: z
315
+ .string()
316
+ .url()
317
+ .refine(isCredentialFreeHttpsUrl, "Market downloads must use credential-free HTTPS"),
318
+ mediaType: z.literal("application/zip"),
319
+ });
320
+ const frameExportBaseSchema = z.object({
321
+ frameId: designIdSchema,
322
+ frameName: frameNameSchema,
323
+ projectId: designIdSchema,
324
+ });
325
+ export const gltsFrameExportSchema = frameExportBaseSchema.extend({
326
+ type: z.literal("glts"),
327
+ runtime: z.object({
328
+ gltf: frameExportFilenameSchema,
329
+ stl: frameExportFilenameSchema,
330
+ }),
331
+ sourceArchive: frameDownloadSchema
332
+ .extend({ mediaType: z.literal("application/zip") })
333
+ .nullable(),
334
+ });
335
+ export const imageFrameExportSchema = frameExportBaseSchema.extend({
336
+ type: z.literal("image"),
337
+ download: frameDownloadSchema.extend({
338
+ mediaType: z.enum(["image/png", "image/jpeg", "image/webp"]),
339
+ }),
340
+ });
341
+ export const marketFrameExportSchema = frameExportBaseSchema.extend({
342
+ type: z.literal("market"),
343
+ asset: marketAssetSchema,
344
+ download: marketDownloadSchema,
345
+ });
346
+ export const frameExportSchema = z.discriminatedUnion("type", [
347
+ gltsFrameExportSchema,
348
+ imageFrameExportSchema,
349
+ marketFrameExportSchema,
350
+ ]);
277
351
  function isProjectPath(path) {
278
352
  if (!path.startsWith("/") || path === "/" || path.endsWith("/"))
279
353
  return false;
@@ -297,3 +371,16 @@ function isHttpUrl(value) {
297
371
  const protocol = new URL(value).protocol;
298
372
  return protocol === "http:" || protocol === "https:";
299
373
  }
374
+ function isCredentialFreeHttpsUrl(value) {
375
+ if (!URL.canParse(value))
376
+ return false;
377
+ const url = new URL(value);
378
+ return url.protocol === "https:" && !url.username && !url.password;
379
+ }
380
+ function isNormalizedQuaternion(value) {
381
+ const squaredLength = value.x * value.x +
382
+ value.y * value.y +
383
+ value.z * value.z +
384
+ value.w * value.w;
385
+ return Math.abs(squaredLength - 1) <= 1e-6;
386
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/design",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Typed API and remote CLI for Drawcall Design",
5
5
  "repository": {
6
6
  "type": "git",