@sanity/workbench 0.1.0-alpha.7 → 0.1.0-alpha.9

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.
Files changed (34) hide show
  1. package/dist/_chunks-es/index.js +6 -1
  2. package/dist/_chunks-es/index.js.map +1 -1
  3. package/dist/_internal.js +3 -8
  4. package/dist/_internal.js.map +1 -1
  5. package/dist/core.d.ts +582 -24
  6. package/dist/core.js +207 -105
  7. package/dist/core.js.map +1 -1
  8. package/package.json +9 -3
  9. package/src/_internal/render.ts +4 -11
  10. package/src/core/applications/application-list.ts +1 -1
  11. package/src/core/applications/local-application.ts +6 -2
  12. package/src/core/canvases.ts +1 -1
  13. package/src/core/index.ts +1 -1
  14. package/src/core/log/index.ts +12 -0
  15. package/src/core/media-libraries.ts +1 -1
  16. package/src/core/user-applications/core-app.ts +66 -10
  17. package/src/core/user-applications/studios/index.ts +3 -0
  18. package/src/core/user-applications/studios/schemas.ts +106 -0
  19. package/src/core/user-applications/{studio.ts → studios/studio.ts} +56 -214
  20. package/src/core/user-applications/studios/workspace.ts +143 -0
  21. package/src/core/user-applications/user-application.ts +36 -5
  22. package/src/_internal/render.test.ts +0 -73
  23. package/src/core/__tests__/__fixtures__.ts +0 -248
  24. package/src/core/applications/application-list.test.ts +0 -222
  25. package/src/core/applications/local-application.test.ts +0 -93
  26. package/src/core/canvases.test.ts +0 -38
  27. package/src/core/log/index.test.ts +0 -133
  28. package/src/core/media-libraries.test.ts +0 -38
  29. package/src/core/organizations.test.ts +0 -134
  30. package/src/core/projects.test.ts +0 -248
  31. package/src/core/shared/urls.test.ts +0 -182
  32. package/src/core/user-applications/core-app.test.ts +0 -151
  33. package/src/core/user-applications/studio.test.ts +0 -928
  34. package/src/core/user-applications/user-application.test.ts +0 -126
package/dist/core.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { createLogger } from "./_chunks-es/index.js";
2
+ import { createLogger, logger } from "./_chunks-es/index.js";
3
3
  import { valid, coerce, gt, lt, gte, rsort } from "semver";
4
4
  class AbstractApplication {
5
5
  type;
@@ -25,15 +25,18 @@ class LocalApplication extends AbstractApplication {
25
25
  }
26
26
  get id() {
27
27
  const { host, port } = this.localApplication;
28
- return `local-${host}-${port}`;
28
+ return `${host}-${port}`;
29
29
  }
30
30
  get title() {
31
31
  const { host, port } = this.localApplication;
32
32
  return `${host}:${port}`;
33
33
  }
34
34
  get href() {
35
+ return `/local/${this.id}`;
36
+ }
37
+ get url() {
35
38
  const { host, port } = this.localApplication;
36
- return `/local/${host}:${port}`;
39
+ return new URL(`http://${host}:${port}`);
37
40
  }
38
41
  toProtocolResource() {
39
42
  throw new Error(
@@ -230,6 +233,25 @@ const UserApplicationId = z.string().nonempty().brand("UserApplicationId");
230
233
  function brandUserApplicationId(id) {
231
234
  return UserApplicationId.parse(id);
232
235
  }
236
+ const UserApplicationBase = z.object({
237
+ id: UserApplicationId,
238
+ appHost: z.string(),
239
+ urlType: z.enum(["internal", "external"]),
240
+ createdAt: z.string(),
241
+ updatedAt: z.string(),
242
+ dashboardStatus: z.enum(["default", "disabled"])
243
+ }), ActiveDeployment = z.object({
244
+ id: z.string(),
245
+ version: z.string(),
246
+ isActiveDeployment: z.boolean(),
247
+ userApplicationId: z.string(),
248
+ isAutoUpdating: z.boolean(),
249
+ size: z.number(),
250
+ deployedAt: z.string(),
251
+ deployedBy: z.string(),
252
+ createdAt: z.string(),
253
+ updatedAt: z.string()
254
+ });
233
255
  class UserApplication extends AbstractApplication {
234
256
  application;
235
257
  id;
@@ -248,6 +270,30 @@ class UserApplication extends AbstractApplication {
248
270
  ) : new URL(this.application.appHost);
249
271
  }
250
272
  }
273
+ const CoreAppUserApplicationManifest = z.object({
274
+ version: z.string(),
275
+ icon: z.string().optional(),
276
+ title: z.string().optional()
277
+ }), CoreAppUserApplicationBase = UserApplicationBase.extend({
278
+ title: z.string(),
279
+ organizationId: OrganizationId,
280
+ type: z.literal("coreApp"),
281
+ manifest: CoreAppUserApplicationManifest.nullable().optional()
282
+ }), InternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({
283
+ urlType: z.literal("internal"),
284
+ activeDeployment: ActiveDeployment.extend({
285
+ manifest: CoreAppUserApplicationManifest.nullable().optional()
286
+ })
287
+ }), ExternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({
288
+ urlType: z.literal("external"),
289
+ activeDeployment: z.null()
290
+ }), CoreAppUserApplication = z.discriminatedUnion("urlType", [
291
+ InternalCoreAppUserApplication,
292
+ ExternalCoreAppUserApplication
293
+ ]);
294
+ function parseCoreApplication(data) {
295
+ return CoreAppUserApplication.parse(data);
296
+ }
251
297
  class CoreAppApplication extends UserApplication {
252
298
  activeDeployment;
253
299
  constructor(application) {
@@ -279,6 +325,64 @@ class CoreAppApplication extends UserApplication {
279
325
  };
280
326
  }
281
327
  }
328
+ const Workspace = z.object({
329
+ name: z.string(),
330
+ title: z.string(),
331
+ subtitle: z.string().optional(),
332
+ basePath: z.string(),
333
+ projectId: ProjectId,
334
+ dataset: z.string().optional(),
335
+ icon: z.string().nullable().optional()
336
+ }), ServerManifest = z.object({
337
+ buildId: z.string().optional(),
338
+ bundleVersion: z.string().optional(),
339
+ version: z.string().optional(),
340
+ workspaces: z.array(
341
+ Workspace.extend({
342
+ dataset: z.string(),
343
+ schemaDescriptorId: z.string()
344
+ })
345
+ ).optional()
346
+ }), ClientManifest$1 = z.object({
347
+ version: z.number(),
348
+ createdAt: z.string(),
349
+ studioVersion: z.string().optional(),
350
+ workspaces: z.array(
351
+ Workspace.extend({
352
+ schema: z.string(),
353
+ tools: z.string().optional()
354
+ })
355
+ )
356
+ }), StudioUserApplicationBase = UserApplicationBase.extend({
357
+ title: z.string().nullable(),
358
+ projectId: ProjectId,
359
+ type: z.literal("studio"),
360
+ manifest: ClientManifest$1.nullable(),
361
+ manifestData: z.object({ value: ClientManifest$1 }).nullable(),
362
+ autoUpdatingVersion: z.string().nullable(),
363
+ config: z.object({
364
+ "live-manifest": z.object({
365
+ createdAt: z.string(),
366
+ updatedAt: z.string(),
367
+ updatedBy: z.string(),
368
+ value: ServerManifest
369
+ }).optional()
370
+ })
371
+ }), InternalStudioUserApplication = StudioUserApplicationBase.extend({
372
+ urlType: z.literal("internal"),
373
+ activeDeployment: ActiveDeployment.extend({
374
+ manifest: ServerManifest.nullable()
375
+ })
376
+ }), ExternalStudioUserApplication = StudioUserApplicationBase.extend({
377
+ urlType: z.literal("external"),
378
+ activeDeployment: z.null()
379
+ }), StudioUserApplication = z.discriminatedUnion("urlType", [
380
+ InternalStudioUserApplication,
381
+ ExternalStudioUserApplication
382
+ ]);
383
+ function parseStudioUserApplication(data) {
384
+ return StudioUserApplication.parse(data);
385
+ }
282
386
  const joinUrlPaths = (...paths) => {
283
387
  let nextPath = null;
284
388
  const safeJoinSegments = (segment1, segment2) => segment1 ? segment2 ? segment1.endsWith("/") && segment2.startsWith("/") ? segment1 + segment2.slice(1) : segment1.endsWith("/") || segment2.startsWith("/") ? segment1 + segment2 : `${segment1}/${segment2}` : segment1 : segment2 || "", validPaths = paths.filter(
@@ -294,24 +398,83 @@ const joinUrlPaths = (...paths) => {
294
398
  function normalizePath(pathname) {
295
399
  return pathname.startsWith("/") || (pathname = `/${pathname}`), pathname !== "/" && pathname.endsWith("/") && (pathname = pathname.slice(0, -1)), pathname;
296
400
  }
297
- const WORKSPACE_MANIFEST_SCHEMA = z.object({
298
- name: z.string(),
299
- title: z.string(),
300
- subtitle: z.string().nullable().optional(),
301
- basePath: z.string(),
302
- projectId: ProjectId,
303
- dataset: z.string(),
304
- icon: z.string().optional().nullable(),
305
- schema: z.string(),
306
- tools: z.string().optional()
307
- }), STUDIO_MANIFEST_SCHEMA = z.object({
308
- // data from manifest
309
- version: z.number(),
310
- createdAt: z.string(),
311
- studioVersion: z.string().nullable().optional(),
312
- // data from workspace object
313
- workspaces: z.array(WORKSPACE_MANIFEST_SCHEMA)
314
- }).superRefine((data, ctx) => {
401
+ class StudioWorkspace extends AbstractApplication {
402
+ /**
403
+ * Workspaces always belong to a studio application.
404
+ * They do not exist on their own & therefore can access
405
+ * information about the studio they're in via this property.
406
+ */
407
+ studioApplication;
408
+ workspace;
409
+ project;
410
+ isDefaultWorkspace;
411
+ constructor(studioApplication, workspace, project, isDefaultWorkspace) {
412
+ super("workspace"), this.studioApplication = studioApplication, this.workspace = workspace, this.project = project, this.isDefaultWorkspace = isDefaultWorkspace;
413
+ }
414
+ /**
415
+ * The studio application that this workspace belongs to.
416
+ */
417
+ get studio() {
418
+ return this.studioApplication;
419
+ }
420
+ get id() {
421
+ return StudioWorkspace.makeId(this.studio.id, this.workspace.name);
422
+ }
423
+ get href() {
424
+ return joinUrlPaths(this.studio.href, this.workspace.name);
425
+ }
426
+ get title() {
427
+ return this.isDefaultWorkspace ? this.project.displayName : this.workspace.title;
428
+ }
429
+ get subtitle() {
430
+ return this.isDefaultWorkspace ? (URL.canParse(this.studio.get("appHost")) ? new URL(this.studio.get("appHost")) : this.studio.url).hostname : this.get("subtitle");
431
+ }
432
+ get(attr) {
433
+ return this.workspace[attr];
434
+ }
435
+ /**
436
+ * With comlink, studio-applications were not considered applications at all, only workspaces. This is partially why
437
+ * we create default workspaces when the application has no manifest or the manifest has no workspaces.
438
+ *
439
+ * Thereby, to create it we depend on a lot of information from the parent application even if it's duplicated across
440
+ * different workspaces.
441
+ */
442
+ toProtocolResource() {
443
+ return {
444
+ ...this.workspace,
445
+ type: "studio",
446
+ userApplicationId: this.studio.id,
447
+ activeDeployment: this.studio.get("activeDeployment"),
448
+ autoUpdatingVersion: this.studio.get("autoUpdatingVersion"),
449
+ dashboardStatus: this.studio.get("dashboardStatus"),
450
+ url: this.studio.url.toString(),
451
+ href: this.href,
452
+ id: this.id,
453
+ hasManifest: !0,
454
+ hasSchema: !!("schema" in this.workspace && this.workspace.schema),
455
+ manifest: this.studio.get("manifestData")?.value ?? null,
456
+ updatedAt: this.studio.get("updatedAt"),
457
+ version: this.studio.get("activeDeployment")?.version,
458
+ urlType: this.studio.get("urlType"),
459
+ config: this.studio.get("config")
460
+ };
461
+ }
462
+ /**
463
+ * @returns the URL to the workspace of a studio application.
464
+ */
465
+ get url() {
466
+ const studioUrl = new URL(this.studio.url), normalizedUrlPath = normalizePath(studioUrl.pathname);
467
+ let finalBasePath = normalizePath(this.get("basePath"));
468
+ return finalBasePath.startsWith(normalizedUrlPath) && (finalBasePath = finalBasePath.slice(normalizedUrlPath.length)), studioUrl.pathname = joinUrlPaths(normalizedUrlPath, finalBasePath), studioUrl;
469
+ }
470
+ static makeId(applicationId, workspaceName) {
471
+ return `${applicationId}-${workspaceName}`;
472
+ }
473
+ static splitId(id) {
474
+ return id.split(new RegExp(/-(.*)/)).slice(0, 2);
475
+ }
476
+ }
477
+ const ClientManifest = ClientManifest$1.superRefine((data, ctx) => {
315
478
  data.version || ctx.addIssue({
316
479
  code: "invalid_type",
317
480
  message: "Manifest version is too old",
@@ -337,6 +500,13 @@ class StudioApplication extends UserApplication {
337
500
  */
338
501
  workspaces = [];
339
502
  project;
503
+ /**
504
+ * The projects actually referenced by this studio — the application's own
505
+ * project plus any project used by a workspace. Preserved so the instance
506
+ * can be re-constructed (e.g. by dock wrappers) without having to thread
507
+ * the full organization project list through again.
508
+ */
509
+ projects;
340
510
  /**
341
511
  * @param application - The studio application to create a list of workspaces for
342
512
  * @param projects - The projects available in the organization. It's not enough to just pass
@@ -348,7 +518,7 @@ class StudioApplication extends UserApplication {
348
518
  let workspaces = [];
349
519
  if (this.hasManifest)
350
520
  try {
351
- workspaces = STUDIO_MANIFEST_SCHEMA.parse(
521
+ workspaces = ClientManifest.parse(
352
522
  application.manifestData?.value
353
523
  ).workspaces;
354
524
  } catch (error) {
@@ -359,23 +529,20 @@ class StudioApplication extends UserApplication {
359
529
  }
360
530
  if (workspaces.length === 0) {
361
531
  const serverManifestWorkspaces = application.activeDeployment?.manifest?.workspaces;
362
- Array.isArray(serverManifestWorkspaces) && serverManifestWorkspaces.length && (workspaces = serverManifestWorkspaces.map((w) => ({
363
- ...w,
364
- projectId: brandProjectId(w.projectId)
365
- })));
532
+ Array.isArray(serverManifestWorkspaces) && serverManifestWorkspaces.length && (workspaces = serverManifestWorkspaces);
366
533
  }
367
534
  const workspacesWithProjectsMap = workspaces.reduce((acc, workspace) => {
368
535
  const project2 = projects.find((p) => p.id === workspace.projectId);
369
536
  return project2 ? acc.set(workspace, project2) : console.warn(
370
537
  `Project not found for application ${application.id} and workspace ${workspace.name}. This workspace has been omitted.`
371
538
  ), acc;
372
- }, /* @__PURE__ */ new Map()), brandedProjectId = brandProjectId(application.projectId), project = projects.find((p) => p.id === brandedProjectId);
539
+ }, /* @__PURE__ */ new Map()), project = projects.find((p) => p.id === application.projectId);
373
540
  if (!project)
374
541
  throw new Error(`Project not found for application ${application.id}`);
375
542
  workspacesWithProjectsMap.size === 0 && workspacesWithProjectsMap.set(
376
543
  {
377
544
  ...DEFAULT_WORKSPACE_DATA,
378
- projectId: brandedProjectId
545
+ projectId: application.projectId
379
546
  },
380
547
  project
381
548
  ), this.workspaces = Object.freeze(
@@ -384,6 +551,10 @@ class StudioApplication extends UserApplication {
384
551
  return new StudioWorkspace(this, workspace, p, isDefaultWorkspace);
385
552
  })
386
553
  ), this.project = project;
554
+ const usedProjects = /* @__PURE__ */ new Set([project]);
555
+ for (const workspace of this.workspaces)
556
+ usedProjects.add(workspace.project);
557
+ this.projects = Array.from(usedProjects);
387
558
  }
388
559
  get href() {
389
560
  return `/studio/${this.application.id}`;
@@ -537,86 +708,12 @@ class StudioApplication extends UserApplication {
537
708
  StudioApplication.Features.map((feature) => feature.version)
538
709
  ).at(0);
539
710
  }
540
- class StudioWorkspace extends AbstractApplication {
541
- /**
542
- * Workspaces always belong to a studio application.
543
- * They do not exist on their own & therefore can access
544
- * information about the studio they're in via this property.
545
- */
546
- studioApplication;
547
- workspace;
548
- project;
549
- isDefaultWorkspace;
550
- constructor(studioApplication, workspace, project, isDefaultWorkspace) {
551
- super("workspace"), this.studioApplication = studioApplication, this.workspace = workspace, this.project = project, this.isDefaultWorkspace = isDefaultWorkspace;
552
- }
553
- /**
554
- * The studio application that this workspace belongs to.
555
- */
556
- get studio() {
557
- return this.studioApplication;
558
- }
559
- get id() {
560
- return StudioWorkspace.makeId(this.studio.id, this.workspace.name);
561
- }
562
- get href() {
563
- return joinUrlPaths(this.studio.href, this.workspace.name);
564
- }
565
- get title() {
566
- return this.isDefaultWorkspace ? this.project.displayName : this.workspace.title;
567
- }
568
- get subtitle() {
569
- return this.isDefaultWorkspace ? (URL.canParse(this.studio.get("appHost")) ? new URL(this.studio.get("appHost")) : this.studio.url).hostname : this.get("subtitle");
570
- }
571
- get(attr) {
572
- return this.workspace[attr];
573
- }
574
- /**
575
- * With comlink, studio-applications were not considered applications at all, only workspaces. This is partially why
576
- * we create default workspaces when the application has no manifest or the manifest has no workspaces.
577
- *
578
- * Thereby, to create it we depend on a lot of information from the parent application even if it's duplicated across
579
- * different workspaces.
580
- */
581
- toProtocolResource() {
582
- return {
583
- ...this.workspace,
584
- type: "studio",
585
- userApplicationId: this.studio.id,
586
- activeDeployment: this.studio.get("activeDeployment"),
587
- autoUpdatingVersion: this.studio.get("autoUpdatingVersion"),
588
- dashboardStatus: this.studio.get("dashboardStatus"),
589
- url: this.studio.url.toString(),
590
- href: this.href,
591
- id: this.id,
592
- hasManifest: !0,
593
- hasSchema: !!this.workspace.schema,
594
- manifest: this.studio.get("manifestData")?.value ?? null,
595
- updatedAt: this.studio.get("updatedAt"),
596
- version: this.studio.get("activeDeployment")?.version,
597
- urlType: this.studio.get("urlType"),
598
- config: this.studio.get("config")
599
- };
600
- }
601
- /**
602
- * @returns the URL to the workspace of a studio application.
603
- */
604
- get url() {
605
- const studioUrl = new URL(this.studio.url), normalizedUrlPath = normalizePath(studioUrl.pathname);
606
- let finalBasePath = normalizePath(this.get("basePath"));
607
- return finalBasePath.startsWith(normalizedUrlPath) && (finalBasePath = finalBasePath.slice(normalizedUrlPath.length)), studioUrl.pathname = joinUrlPaths(normalizedUrlPath, finalBasePath), studioUrl;
608
- }
609
- static makeId(applicationId, workspaceName) {
610
- return `${applicationId}-${workspaceName}`;
611
- }
612
- static splitId(id) {
613
- return id.split(new RegExp(/-(.*)/)).slice(0, 2);
614
- }
615
- }
616
711
  export {
617
712
  AbstractApplication,
713
+ ActiveDeployment,
618
714
  ApplicationList,
619
715
  CanvasApplication,
716
+ ClientManifest$1 as ClientManifest,
620
717
  CoreAppApplication,
621
718
  LocalApplication,
622
719
  MediaLibraryApplication,
@@ -625,8 +722,10 @@ export {
625
722
  Project,
626
723
  ProjectId,
627
724
  StudioApplication,
725
+ StudioUserApplication,
628
726
  StudioWorkspace,
629
727
  UserApplication,
728
+ UserApplicationBase,
630
729
  UserApplicationId,
631
730
  brandCanvasId,
632
731
  brandMediaLibraryId,
@@ -634,9 +733,12 @@ export {
634
733
  brandProjectId,
635
734
  brandUserApplicationId,
636
735
  createLogger,
736
+ logger,
637
737
  parseCanvas,
738
+ parseCoreApplication,
638
739
  parseMediaLibrary,
639
740
  parseOrganization,
640
- parseProject
741
+ parseProject,
742
+ parseStudioUserApplication
641
743
  };
642
744
  //# sourceMappingURL=core.js.map