@sanity/workbench 0.1.0-alpha.19 → 0.1.0-alpha.20
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/_chunks-es/studio.js +57 -2
- package/dist/_chunks-es/studio.js.map +1 -1
- package/dist/core.d.ts +334 -2
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -1
- package/dist/system.d.ts +1107 -100
- package/dist/system.js +314 -110
- package/dist/system.js.map +1 -1
- package/package.json +2 -2
- package/src/core/applications/application.ts +80 -1
- package/src/core/user-applications/core-app.ts +5 -1
- package/src/core/user-applications/studios/schemas.ts +4 -0
- package/src/core/user-applications/user-application.ts +17 -0
- package/src/system/index.ts +5 -0
- package/src/system/load-federated-module.ts +54 -0
- package/src/system/remote.machine.ts +83 -37
- package/src/system/remotes.machine.ts +34 -28
- package/src/system/root.machine.ts +26 -0
- package/src/system/service.machine.ts +207 -0
- package/src/system/services.machine.ts +120 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { valid, coerce, gt, lt, gte, rsort } from "semver";
|
|
3
|
+
import { LocalInterfaceSchema } from "@sanity/federation";
|
|
3
4
|
class AbstractApplication {
|
|
4
5
|
type;
|
|
5
6
|
constructor(type) {
|
|
@@ -13,6 +14,38 @@ class AbstractApplication {
|
|
|
13
14
|
get isLocal() {
|
|
14
15
|
return !1;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Interfaces the application exposes (e.g. dock panels). Defaults to none;
|
|
19
|
+
* user applications surface what they declared via `unstable_defineApp`.
|
|
20
|
+
*/
|
|
21
|
+
get interfaces() {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Whether the application has a navigable full-page `app` view (US5). Defaults
|
|
26
|
+
* to `true` — studios, Canvas, and Media Library are always navigable. An SDK
|
|
27
|
+
* app overrides this to derive it from whether it declares an `app` interface.
|
|
28
|
+
*/
|
|
29
|
+
get hasAppView() {
|
|
30
|
+
return !0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Federation module id of the app's full-page view (`${id}/App`), or `null`
|
|
34
|
+
* when it can't be federation-loaded: the app isn't federated (Canvas, Media
|
|
35
|
+
* Library, deployed apps shown in an iframe) or has no app view. Only a
|
|
36
|
+
* non-null `moduleId` is fetched and rendered by the remotes machine.
|
|
37
|
+
*/
|
|
38
|
+
get moduleId() {
|
|
39
|
+
return this.isFederated && this.hasAppView ? `${this.id}/App` : null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Federation module id of one of this app's panel view components, or `null`
|
|
43
|
+
* when the app isn't federated (a non-federated app's panels can't be loaded
|
|
44
|
+
* as remotes).
|
|
45
|
+
*/
|
|
46
|
+
resolveViewModuleId(view, component) {
|
|
47
|
+
return this.isFederated ? `${this.id}/views/${view.name}/${component}` : null;
|
|
48
|
+
}
|
|
16
49
|
get initials() {
|
|
17
50
|
const SYMBOLS = /[^\p{Alpha}\p{N}\p{White_Space}]/gu, WHITESPACE = new RegExp("\\p{White_Space}+", "u"), ALPHANUMERIC_SEGMENTS = new RegExp("(\\p{N}+|\\p{Alpha}+)", "gu"), IS_NUMERIC = new RegExp("^\\p{N}+$", "u");
|
|
18
51
|
if (!this.title) return "";
|
|
@@ -227,6 +260,12 @@ function brandUserApplicationId(id) {
|
|
|
227
260
|
const LocalUserApplicationBase = z.object({
|
|
228
261
|
host: z.string(),
|
|
229
262
|
port: z.number(),
|
|
263
|
+
/**
|
|
264
|
+
* Interfaces the app exposes — dock panels (`interface_type: "panel"`) and
|
|
265
|
+
* background workers (`interface_type: "worker"`), forwarded from the dev
|
|
266
|
+
* server in one list.
|
|
267
|
+
*/
|
|
268
|
+
interfaces: z.array(LocalInterfaceSchema).optional(),
|
|
230
269
|
/** The `deployment.appId` from the application's `sanity.cli.ts`, when set. */
|
|
231
270
|
id: z.string().optional(),
|
|
232
271
|
/**
|
|
@@ -251,7 +290,12 @@ const LocalUserApplicationBase = z.object({
|
|
|
251
290
|
urlType: z.enum(["internal", "external"]),
|
|
252
291
|
createdAt: z.string(),
|
|
253
292
|
updatedAt: z.string(),
|
|
254
|
-
dashboardStatus: z.enum(["default", "disabled"])
|
|
293
|
+
dashboardStatus: z.enum(["default", "disabled"]),
|
|
294
|
+
/**
|
|
295
|
+
* Interfaces the app exposes (dock panels and background workers). Not part
|
|
296
|
+
* of the manifest.
|
|
297
|
+
*/
|
|
298
|
+
interfaces: z.array(LocalInterfaceSchema).optional()
|
|
255
299
|
}), ActiveDeployment = z.object({
|
|
256
300
|
id: z.string(),
|
|
257
301
|
version: z.string(),
|
|
@@ -287,6 +331,9 @@ class UserApplication extends AbstractApplication {
|
|
|
287
331
|
get isLocal() {
|
|
288
332
|
return this.#isLocal;
|
|
289
333
|
}
|
|
334
|
+
get interfaces() {
|
|
335
|
+
return this.application.interfaces ?? [];
|
|
336
|
+
}
|
|
290
337
|
/**
|
|
291
338
|
* @returns A fully resolved URL instance for the application.
|
|
292
339
|
* For internal applications, constructs a URL using the Sanity studio domain
|
|
@@ -303,7 +350,9 @@ class UserApplication extends AbstractApplication {
|
|
|
303
350
|
const CoreAppUserApplicationManifest = z.object({
|
|
304
351
|
version: z.string(),
|
|
305
352
|
icon: z.string().optional(),
|
|
306
|
-
title: z.string().optional()
|
|
353
|
+
title: z.string().optional(),
|
|
354
|
+
group: z.string().optional(),
|
|
355
|
+
priority: z.number().optional()
|
|
307
356
|
}), CoreAppUserApplicationBase = UserApplicationBase.extend({
|
|
308
357
|
title: z.string(),
|
|
309
358
|
organizationId: OrganizationId,
|
|
@@ -328,6 +377,8 @@ class CoreAppApplication extends UserApplication {
|
|
|
328
377
|
constructor(application, options = {}) {
|
|
329
378
|
super(application, "coreApp", options), this.activeDeployment = application.activeDeployment;
|
|
330
379
|
}
|
|
380
|
+
// Typed `string | null` so the UI-aware remote subclass can override it to
|
|
381
|
+
// `null` for a non-navigable app (US5); the core route itself is always set.
|
|
331
382
|
get href() {
|
|
332
383
|
return this.isLocal ? `/local/${this.id}` : `/application/${this.application.id}`;
|
|
333
384
|
}
|
|
@@ -375,6 +426,8 @@ const Workspace = z.object({
|
|
|
375
426
|
buildId: z.string().optional(),
|
|
376
427
|
bundleVersion: z.string().optional(),
|
|
377
428
|
version: z.string().optional(),
|
|
429
|
+
group: z.string().optional(),
|
|
430
|
+
priority: z.number().optional(),
|
|
378
431
|
workspaces: z.array(
|
|
379
432
|
Workspace.extend({
|
|
380
433
|
dataset: z.string(),
|
|
@@ -385,6 +438,8 @@ const Workspace = z.object({
|
|
|
385
438
|
version: z.number(),
|
|
386
439
|
createdAt: z.string(),
|
|
387
440
|
studioVersion: z.string().optional(),
|
|
441
|
+
group: z.string().optional(),
|
|
442
|
+
priority: z.number().optional(),
|
|
388
443
|
workspaces: z.array(
|
|
389
444
|
Workspace.extend({
|
|
390
445
|
schema: z.string(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"studio.js","sources":["../../src/core/applications/application.ts","../../src/core/env.ts","../../src/core/organizations.ts","../../src/core/canvases.ts","../../src/core/media-libraries.ts","../../src/core/projects.ts","../../src/core/shared/urls.ts","../../src/core/user-applications/user-application.ts","../../src/core/user-applications/core-app.ts","../../src/core/user-applications/studios/schemas.ts","../../src/core/user-applications/studios/workspace.ts","../../src/core/user-applications/studios/studio.ts"],"sourcesContent":["import type { Resource as ProtocolResource } from \"@sanity/message-protocol\";\n\n/**\n * @public\n */\nexport type AbstractApplicationType =\n | \"studio\"\n | \"coreApp\"\n | \"canvas\"\n | \"media-library\"\n | \"workspace\";\n\n/**\n * @public\n */\nexport abstract class AbstractApplication<\n TType extends AbstractApplicationType,\n TProtocolResource extends ProtocolResource = Extract<\n ProtocolResource,\n { type: TType }\n >,\n> {\n readonly type: TType;\n\n constructor(type: TType) {\n this.type = type;\n }\n\n abstract get href(): string;\n\n abstract get title(): string;\n\n abstract get id(): string;\n\n /**\n * Whether the application is federated or not. This is used to determine\n * if the application should be rendered in an iframe or not.\n */\n abstract get isFederated(): boolean;\n\n /**\n * Whether the application is served by a local CLI dev server rather than a\n * deployed remote. Defaults to `false`; user applications flip this when\n * constructed from a `LocalUserApplication` payload.\n */\n get isLocal(): boolean {\n return false;\n }\n\n abstract get url(): URL;\n\n get initials(): string {\n const SYMBOLS = /[^\\p{Alpha}\\p{N}\\p{White_Space}]/gu;\n const WHITESPACE = /\\p{White_Space}+/u;\n const ALPHANUMERIC_SEGMENTS = /(\\p{N}+|\\p{Alpha}+)/gu;\n const IS_NUMERIC = /^\\p{N}+$/u;\n\n if (!this.title) return \"\";\n\n const namesArray = this.title\n .replace(SYMBOLS, \"\")\n .split(WHITESPACE)\n .filter(Boolean);\n\n if (namesArray.length === 0) return \"\";\n\n if (namesArray.length === 1) {\n const word = namesArray[0];\n const segments = word.match(ALPHANUMERIC_SEGMENTS) || [];\n\n if (segments.length === 0) return \"\";\n if (segments.length === 1) {\n if (word.length === 1) {\n return word.toUpperCase();\n }\n\n if (IS_NUMERIC.test(word)) {\n return `${word.charAt(0)}${word.charAt(1)}`.toUpperCase();\n }\n\n return word.charAt(0).toUpperCase();\n }\n\n return `${segments[0]!.charAt(0)}${segments[1].charAt(0)}`.toUpperCase();\n }\n\n return `${namesArray[0].charAt(0)}${namesArray[namesArray.length - 1].charAt(0)}`.toUpperCase();\n }\n\n /**\n * Converts the resource to a protocol resource that comlink expects\n * for backwards compatibility with the old API format.\n */\n abstract toProtocolResource(): TProtocolResource;\n}\n","declare const __SANITY_STAGING__: boolean | undefined;\n\n/**\n * Returns the Sanity domain based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, the staging domain is returned.\n * Otherwise, the production domain is returned.\n *\n * @public\n */\nexport function getSanityDomain(): string {\n if (getSanityEnv() === \"staging\") {\n return \"sanity.work\";\n }\n return \"sanity.io\";\n}\n\n/**\n * Returns the API host based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, the staging API host is returned.\n * Otherwise, the production API host is returned.\n *\n * @public\n */\nexport function getApiHost(): string | undefined {\n return `https://api.${getSanityDomain()}`;\n}\n\n/**\n * Returns the current Sanity environment based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, \"staging\" is returned.\n * Otherwise, \"production\" is returned.\n *\n * @public\n */\nexport function getSanityEnv(): \"staging\" | \"production\" {\n if (\n typeof __SANITY_STAGING__ !== \"undefined\" &&\n __SANITY_STAGING__ === true\n ) {\n return \"staging\";\n }\n return \"production\";\n}\n","import { z } from \"zod\";\n\n/**\n * Organization ID schema, branded for type safety.\n * @public\n */\nexport const OrganizationId = z.string().nonempty().brand(\"OrganizationId\");\n\n/**\n * Organization ID type, branded for type safety.\n * @public\n */\nexport type OrganizationId = z.output<typeof OrganizationId>;\n\n/**\n * Validates and brands a string as an OrganizationId.\n * @public\n */\nexport function brandOrganizationId(id: string): OrganizationId {\n return OrganizationId.parse(id);\n}\n\nconst OrganizationMember = z.object({\n sanityUserId: z.string(),\n isCurrentUser: z.boolean(),\n user: z.object({\n id: z.string(),\n displayName: z.string(),\n familyName: z.string(),\n givenName: z.string(),\n middleName: z.string().nullable(),\n imageUrl: z.string().nullable(),\n email: z.string(),\n loginProvider: z.string(),\n }),\n roles: z.array(\n z.object({\n name: z.string(),\n title: z.string(),\n description: z.string().optional(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type OrganizationMember = z.output<typeof OrganizationMember>;\n\n/**\n * Organization schema — validates and brands API responses\n * from the `/organizations/:id` endpoint.\n * @public\n */\nexport const Organization = z.object({\n id: OrganizationId,\n name: z.string(),\n slug: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n dashboardStatus: z.enum([\"enabled\", \"disabled\"]),\n aiFeaturesStatus: z.enum([\"enabled\", \"disabled\"]),\n defaultRoleName: z.string().nullable(),\n});\n\n/**\n * Represents an organization with optional members and\n * features arrays depending on the generic parameters.\n * - `Organization` — base fields only (default)\n * - `Organization<true>` — includes `members`\n * - `Organization<true, true>` — includes both\n * @public\n */\nexport type Organization<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n> = z.output<typeof Organization> &\n (IncludeMembers extends true ? { members: OrganizationMember[] } : unknown) &\n (IncludeFeatures extends true ? { features: string[] } : unknown);\n\n/**\n * Validates and parses a raw API response into a branded\n * Organization. The options control which schema is used —\n * matching what the API returns based on query params.\n * @public\n */\nexport function parseOrganization<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n>(\n data: unknown,\n options?: {\n includeMembers?: IncludeMembers;\n includeFeatures?: IncludeFeatures;\n },\n): Organization<IncludeMembers, IncludeFeatures> {\n const includeMembers = options?.includeMembers ?? true;\n const includeFeatures = options?.includeFeatures ?? true;\n\n const extensions = {\n ...(includeMembers && {\n members: z.array(OrganizationMember),\n }),\n ...(includeFeatures && {\n features: z.array(z.string()),\n }),\n };\n\n const schema =\n Object.keys(extensions).length > 0\n ? Organization.extend(extensions)\n : Organization;\n\n return schema.parse(data) as Organization<IncludeMembers, IncludeFeatures>;\n}\n","import type { CanvasResource as ProtocolCanvasResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { AbstractApplication } from \"./applications/application\";\nimport { getSanityDomain } from \"./env\";\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Canvas ID schema, branded for type safety.\n * @public\n */\nconst CanvasId = z.string().nonempty().brand(\"CanvasId\");\n\n/**\n * Canvas ID type, branded for type safety.\n * @public\n */\nexport type CanvasId = z.output<typeof CanvasId>;\n\n/**\n * Validates and brands a string as a CanvasId.\n * @public\n */\nexport function brandCanvasId(id: string): CanvasId {\n return CanvasId.parse(id);\n}\n\nconst Canvas = z.object({\n id: CanvasId,\n organizationId: OrganizationId,\n status: z.enum([\"active\", \"provisioning\"]),\n});\n\n/**\n * Represents a Canvas resource as returned from the API.\n * @public\n */\nexport type Canvas = z.output<typeof Canvas>;\n\n/**\n * Validates and parses a raw API response into a branded\n * Canvas.\n * @public\n */\nexport function parseCanvas(data: unknown): Canvas {\n return Canvas.parse(data);\n}\n\n/**\n * Whilst the constructor takes an organization's canvas resource the existance\n * therefore implies the organization has access to the canvas application which\n * is what workbench most importantly wants to know.\n * @public\n */\nexport class CanvasApplication extends AbstractApplication<\"canvas\"> {\n readonly canvas: Canvas;\n\n constructor(canvas: Canvas) {\n super(\"canvas\");\n\n this.canvas = canvas;\n }\n\n get id(): CanvasId {\n return this.canvas.id;\n }\n\n get href(): string {\n return \"canvas\";\n }\n\n get title(): string {\n return \"Canvas\";\n }\n\n get url(): URL {\n return new URL(\n `https://canvas.${getSanityDomain()}/o/${this.canvas.organizationId}`,\n );\n }\n\n get isFederated(): boolean {\n return false;\n }\n\n toProtocolResource(): ProtocolCanvasResource {\n return {\n type: \"canvas\",\n id: this.id,\n } satisfies ProtocolCanvasResource;\n }\n}\n","import type { MediaResource as ProtocolMediaResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { AbstractApplication } from \"./applications/application\";\nimport { getSanityDomain } from \"./env\";\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Canvas ID schema, branded for type safety.\n * @public\n */\nconst MediaLibraryId = z.string().nonempty().brand(\"MediaLibraryId\");\n\n/**\n * MediaLibrary ID type, branded for type safety.\n * @public\n */\nexport type MediaLibraryId = z.output<typeof MediaLibraryId>;\n\n/**\n * Validates and brands a string as a MediaLibraryId.\n * @public\n */\nexport function brandMediaLibraryId(id: string): MediaLibraryId {\n return MediaLibraryId.parse(id);\n}\n\nconst MediaLibrary = z.object({\n id: MediaLibraryId,\n organizationId: OrganizationId,\n status: z.enum([\"active\", \"provisioning\"]),\n aclMode: z.enum([\"private\", \"public\"]),\n});\n\n/**\n * Represents a MediaLibrary resource as returned from the API.\n * @public\n */\nexport type MediaLibrary = z.output<typeof MediaLibrary>;\n\n/**\n * Validates and parses a raw API response into a branded\n * MediaLibrary.\n * @public\n */\nexport function parseMediaLibrary(data: unknown): MediaLibrary {\n return MediaLibrary.parse(data);\n}\n\n/**\n * Whilst the constructor takes an organization's media library resource the existance\n * therefore implies the organization has access to the media library application which\n * is what workbench most importantly wants to know.\n * @public\n */\nexport class MediaLibraryApplication extends AbstractApplication<\"media-library\"> {\n readonly library: MediaLibrary;\n\n constructor(library: MediaLibrary) {\n super(\"media-library\");\n\n this.library = library;\n }\n\n get id(): string {\n return this.library.id;\n }\n\n get href(): string {\n return \"media\";\n }\n\n get title(): string {\n return \"Media Library\";\n }\n\n get isFederated(): boolean {\n return false;\n }\n\n get url(): URL {\n return new URL(\n `https://media.${getSanityDomain()}/${this.library.organizationId}`,\n );\n }\n\n toProtocolResource(): ProtocolMediaResource {\n return {\n type: \"media-library\",\n id: this.id,\n } satisfies ProtocolMediaResource;\n }\n}\n","import { z } from \"zod\";\n\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Project ID schema, branded for type safety.\n * @public\n */\nexport const ProjectId = z.string().nonempty().brand(\"ProjectId\");\n\n/**\n * Project ID type, branded for type safety.\n * @public\n */\nexport type ProjectId = z.output<typeof ProjectId>;\n\n/**\n * Validates and brands a string as a ProjectId.\n * @public\n */\nexport function brandProjectId(id: string): ProjectId {\n return ProjectId.parse(id);\n}\n\nconst ProjectMember = z.object({\n id: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n isCurrentUser: z.boolean(),\n isRobot: z.boolean(),\n roles: z.array(\n z.object({\n name: z.string(),\n title: z.string(),\n description: z.string(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type ProjectMember = z.output<typeof ProjectMember>;\n\n/**\n * Project schema — validates and brands API responses\n * from the `/projects/:id` endpoint.\n * @public\n */\nexport const Project = z.object({\n id: ProjectId,\n displayName: z.string(),\n studioHost: z.string().nullable(),\n organizationId: OrganizationId,\n metadata: z.object({\n color: z.string().optional(),\n externalStudioHost: z.string().optional(),\n initialTemplate: z.string().optional(),\n cliInitializedAt: z.string().optional(),\n integration: z.string().optional(),\n }),\n isBlocked: z.boolean(),\n isDisabled: z.boolean(),\n isDisabledByUser: z.boolean(),\n activityFeedEnabled: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n/**\n * Represents a Sanity project with optional members and\n * features arrays depending on the generic parameters.\n * By default, neither members nor features are included.\n * - `Project` — base fields only (default)\n * - `Project<true>` — includes `members`\n * - `Project<true, true>` — includes both\n * @public\n */\nexport type Project<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n> = z.output<typeof Project> &\n (IncludeMembers extends true ? { members: ProjectMember[] } : unknown) &\n (IncludeFeatures extends true ? { features: string[] } : unknown);\n\n/**\n * Validates and parses a raw API response into a branded\n * Project. The options control which schema is used —\n * matching what the API returns based on query params.\n * @public\n */\nexport function parseProject<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n>(\n data: unknown,\n options?: {\n includeMembers?: IncludeMembers;\n includeFeatures?: IncludeFeatures;\n },\n): Project<IncludeMembers, IncludeFeatures> {\n const includeMembers = options?.includeMembers ?? true;\n const includeFeatures = options?.includeFeatures ?? true;\n\n const extensions = {\n ...(includeMembers && { members: z.array(ProjectMember) }),\n ...(includeFeatures && { features: z.array(z.string()) }),\n };\n\n const schema =\n Object.keys(extensions).length > 0 ? Project.extend(extensions) : Project;\n\n return schema.parse(data) as Project<IncludeMembers, IncludeFeatures>;\n}\n","/**\n * Joins multiple path segments into a single path string.\n * Handles null, undefined, and URL objects gracefully.\n *\n * @public\n * @param paths - An array of path segments to join.\n * @returns A single joined path string.\n */\nexport const joinUrlPaths = (\n ...paths: Array<string | URL | null | undefined>\n): string => {\n let nextPath = null;\n\n const safeJoinSegments = (\n segment1: string | null | undefined,\n segment2: string | null | undefined,\n ): string => {\n if (!segment1) {\n if (!segment2) {\n return \"\";\n }\n\n return segment2;\n }\n\n if (!segment2) {\n return segment1;\n }\n\n if (segment1.endsWith(\"/\") && segment2.startsWith(\"/\")) {\n return segment1 + segment2.slice(1);\n }\n\n if (segment1.endsWith(\"/\") || segment2.startsWith(\"/\")) {\n return segment1 + segment2;\n }\n\n return `${segment1}/${segment2}`;\n };\n\n const validPaths = paths.filter(\n (path) => path !== null && path !== undefined,\n );\n\n for (const path of validPaths) {\n nextPath = safeJoinSegments(\n nextPath,\n path instanceof URL ? path.pathname : path,\n );\n }\n\n return nextPath ?? \"\";\n};\n\n/**\n * Returns a normalized path by ensuring it starts with a single leading slash\n * and does not end with a trailing slash (unless it's the root path).\n */\nexport function normalizePath(pathname: string): string {\n if (!pathname.startsWith(\"/\")) {\n pathname = `/${pathname}`;\n }\n\n if (pathname !== \"/\" && pathname.endsWith(\"/\")) {\n pathname = pathname.slice(0, -1);\n }\n\n return pathname;\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\ninterface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial<Path> {\n let parsedPath: Partial<Path> = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substring(hashIndex);\n path = path.substring(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substring(searchIndex);\n path = path.substring(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial<Path>) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : `?${search}`;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : `#${hash}`;\n return pathname;\n}\n","// eslint-disable-next-line no-restricted-imports\nimport type { Resource as ProtocolResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport {\n AbstractApplication,\n type AbstractApplicationType,\n} from \"../applications/application\";\nimport { getSanityDomain, getSanityEnv } from \"../env\";\nimport type { CoreAppUserApplicationManifest } from \"./core-app\";\nimport type { ClientManifest, ServerManifest } from \"./studios/schemas\";\n\n/**\n * User application ID schema, branded for type safety.\n * @public\n */\nexport const UserApplicationId = z\n .string()\n .nonempty()\n .brand(\"UserApplicationId\");\n\n/**\n * User application ID type, branded for type safety.\n * @public\n */\nexport type UserApplicationId = z.output<typeof UserApplicationId>;\n\n/**\n * Validates and brands a string as a UserApplicationId.\n * @public\n */\nexport function brandUserApplicationId(id: string): UserApplicationId {\n return UserApplicationId.parse(id);\n}\n\nconst LocalUserApplicationBase = z.object({\n host: z.string(),\n port: z.number(),\n /** The `deployment.appId` from the application's `sanity.cli.ts`, when set. */\n id: z.string().optional(),\n /**\n * The `api.projectId` from the application's `sanity.cli.ts`. Available\n * synchronously at dev-server startup (no manifest extraction required), so\n * the studio's primary project is resolvable from the very first local\n * application event.\n */\n projectId: z.string().optional(),\n});\n\n/**\n * Raw data for a local application discovered by the CLI dev server.\n *\n * The CLI forwards the full studio or app manifest so the workbench can\n * derive icons, titles, workspaces and schema references the same way it\n * does for deployed applications. The manifest shape is discriminated on\n * `type`: studios receive a `ClientManifest`, core apps a `CoreAppUserApplicationManifest`.\n *\n * When set on a `UserApplication`, `isLocal` is `true` and `url`/`isFederated`\n * honour the local dev-server instead of the deployed application's host.\n *\n * @public\n */\nexport const LocalUserApplication = z.discriminatedUnion(\"type\", [\n LocalUserApplicationBase.extend({\n type: z.literal(\"studio\"),\n manifest: z.custom<ClientManifest>().optional(),\n }),\n LocalUserApplicationBase.extend({\n type: z.literal(\"coreApp\"),\n manifest: z.custom<CoreAppUserApplicationManifest>().optional(),\n }),\n]);\n\n/**\n * @public\n */\nexport type LocalUserApplication = z.output<typeof LocalUserApplication>;\n\n/**\n * @public\n */\nexport const UserApplicationBase = z.object({\n id: UserApplicationId,\n appHost: z.string(),\n urlType: z.enum([\"internal\", \"external\"]),\n createdAt: z.string(),\n updatedAt: z.string(),\n dashboardStatus: z.enum([\"default\", \"disabled\"]),\n});\n\n/**\n * @public\n */\nexport type UserApplicationBase = z.output<typeof UserApplicationBase>;\n\n/**\n * @public\n */\nexport const ActiveDeployment = z.object({\n id: z.string(),\n version: z.string(),\n isActiveDeployment: z.boolean(),\n userApplicationId: z.string(),\n isAutoUpdating: z.boolean(),\n size: z.number(),\n deployedAt: z.string(),\n deployedBy: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n/**\n * @public\n */\nexport abstract class UserApplication<\n TUserApplication extends UserApplicationBase,\n TType extends Extract<AbstractApplicationType, \"coreApp\" | \"studio\">,\n TProtocolResource extends ProtocolResource = Extract<\n ProtocolResource,\n { type: TType }\n >,\n> extends AbstractApplication<TType, TProtocolResource> {\n readonly application: TUserApplication;\n\n readonly id: UserApplicationId;\n\n /**\n * For local applications (`isLocal === true`), the deployed application\n * that shares the same `id` — if one was passed at construction. `null`\n * for deployed applications or when no remote twin was provided.\n */\n readonly remoteApplication: this | null;\n\n readonly #isLocal: boolean;\n\n constructor(\n application: TUserApplication,\n type: TType,\n options: {\n isLocal?: boolean;\n remoteApplication?: UserApplication<\n TUserApplication,\n TType,\n TProtocolResource\n > | null;\n } = {},\n ) {\n super(type);\n this.application = application;\n this.id = brandUserApplicationId(application.id);\n this.#isLocal = options.isLocal ?? false;\n this.remoteApplication =\n (options.remoteApplication as this | undefined) ?? null;\n }\n\n abstract get subtitle(): string | undefined;\n\n /**\n * Local dev servers are rendered as federated remotes; deployed applications\n * are rendered in an iframe.\n */\n get isFederated(): boolean {\n return this.isLocal;\n }\n\n override get isLocal(): boolean {\n return this.#isLocal;\n }\n\n /**\n * @returns A fully resolved URL instance for the application.\n * For internal applications, constructs a URL using the Sanity studio domain\n * pattern resolved from the environment at the consuming app's build time.\n * For external applications (including local dev servers), returns the\n * provided app host as a URL.\n */\n get url(): URL {\n if (this.application.urlType === \"internal\") {\n if (getSanityEnv() === \"production\") {\n return new URL(`https://${this.application.appHost}.sanity.studio`);\n }\n return new URL(\n `https://${this.application.appHost}.studio.${getSanityDomain()}`,\n );\n }\n\n return new URL(this.application.appHost);\n }\n\n /**\n * Unified manifest accessor for user applications. Resolves the most\n * authoritative manifest available for the application, preferring the\n * deployment manifest (`activeDeployment.manifest`) before falling back to\n * any client-side manifest. The returned shape depends on the application\n * type and source: studios may yield either a `ServerManifest` (deployment)\n * or a `ClientManifest` (fallback); core apps yield a\n * `CoreAppUserApplicationManifest`. Returns `null` when no manifest is\n * available.\n */\n abstract get manifest():\n | ClientManifest\n | ServerManifest\n | CoreAppUserApplicationManifest\n | null;\n}\n","// eslint-disable-next-line no-restricted-imports\nimport type { ApplicationResource as ProtocolApplicationResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { OrganizationId } from \"../organizations\";\nimport {\n UserApplication,\n UserApplicationBase,\n ActiveDeployment,\n} from \"./user-application\";\n\n/**\n * @public\n */\nexport const CoreAppUserApplicationManifest = z.object({\n version: z.string(),\n icon: z.string().optional(),\n title: z.string().optional(),\n});\n\n/**\n * @public\n */\nexport type CoreAppUserApplicationManifest = z.output<\n typeof CoreAppUserApplicationManifest\n>;\n\nconst CoreAppUserApplicationBase = UserApplicationBase.extend({\n title: z.string(),\n organizationId: OrganizationId,\n type: z.literal(\"coreApp\"),\n});\n\n// Core apps surface their manifest exclusively via `activeDeployment.manifest`\n// — they have no top-level `manifest` field and no `manifestData`.\nconst CoreAppActiveDeployment = ActiveDeployment.extend({\n manifest: CoreAppUserApplicationManifest.nullable(),\n}).nullable();\n\nconst InternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({\n urlType: z.literal(\"internal\"),\n activeDeployment: CoreAppActiveDeployment,\n});\n\nconst ExternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({\n urlType: z.literal(\"external\"),\n activeDeployment: CoreAppActiveDeployment,\n});\n\n/**\n * Core application schema — validates and brands API\n * responses from the `/user-applications?appType=coreApp`\n * endpoint. Uses a discriminated union on `urlType`.\n * @public\n */\nconst CoreAppUserApplication = z.discriminatedUnion(\"urlType\", [\n InternalCoreAppUserApplication,\n ExternalCoreAppUserApplication,\n]);\n\n/**\n * @public\n */\nexport type CoreAppUserApplication = z.output<typeof CoreAppUserApplication>;\n\n/**\n * Validates and parses a raw API response into a branded\n * CoreAppUserApplicationData.\n * @public\n */\nexport function parseCoreApplication(data: unknown): CoreAppUserApplication {\n return CoreAppUserApplication.parse(data);\n}\n\n/**\n * @public\n */\nexport class CoreAppApplication extends UserApplication<\n CoreAppUserApplication,\n \"coreApp\",\n ProtocolApplicationResource\n> {\n readonly activeDeployment: CoreAppUserApplication[\"activeDeployment\"];\n\n constructor(\n application: CoreAppUserApplication,\n options: {\n isLocal?: boolean;\n remoteApplication?: CoreAppApplication | null;\n } = {},\n ) {\n super(application, \"coreApp\", options);\n\n this.activeDeployment = application.activeDeployment;\n }\n\n get href() {\n return this.isLocal\n ? `/local/${this.id}`\n : `/application/${this.application.id}`;\n }\n\n get title() {\n return this.manifest?.title ?? this.application.title;\n }\n\n /**\n * Resolves the core app's manifest from `activeDeployment.manifest`. This\n * is the canonical (and only) slot for core app manifests — both for\n * Sanity-deployed apps and for local CLI dev-server apps, which synthesise\n * a deployment to surface the live manifest.\n */\n get manifest(): CoreAppUserApplicationManifest | null {\n return this.activeDeployment?.manifest ?? null;\n }\n\n get subtitle() {\n return undefined;\n }\n\n get updatedAt() {\n return this.application.updatedAt;\n }\n\n get<TKey extends keyof CoreAppUserApplication>(\n attr: TKey,\n ): CoreAppUserApplication[TKey] {\n if (!(attr in this.application)) {\n throw new Error(\n `Attribute ${attr.toString()} does not exist on application ${this.application.id}`,\n );\n }\n\n return this.application[attr];\n }\n\n toProtocolResource(): ProtocolApplicationResource {\n return {\n ...this.application,\n type: \"application\",\n url: this.url.toString(),\n } as ProtocolApplicationResource;\n }\n}\n","import { z } from \"zod\";\n\nimport { ProjectId } from \"../../projects\";\nimport { ActiveDeployment, UserApplicationBase } from \"../user-application\";\n\nconst Workspace = z.object({\n name: z.string(),\n title: z.string(),\n subtitle: z.string().optional(),\n basePath: z.string(),\n projectId: ProjectId,\n dataset: z.string().optional(),\n icon: z.string().nullable().optional(),\n});\n\n/**\n * @public\n */\nexport type Workspace = z.output<typeof Workspace>;\n\n/**\n * @public\n */\nexport const ServerManifest = z.object({\n buildId: z.string().optional(),\n bundleVersion: z.string().optional(),\n version: z.string().optional(),\n workspaces: z\n .array(\n Workspace.extend({\n dataset: z.string(),\n schemaDescriptorId: z.string(),\n }),\n )\n .optional(),\n});\n\n/**\n * @public\n */\nexport type ServerManifest = z.output<typeof ServerManifest>;\n\n/**\n * @public\n */\nexport const ClientManifest = z.object({\n version: z.number(),\n createdAt: z.string(),\n studioVersion: z.string().optional(),\n workspaces: z.array(\n Workspace.extend({\n schema: z.string(),\n tools: z.string().optional(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type ClientManifest = z.output<typeof ClientManifest>;\n\nconst StudioUserApplicationBase = UserApplicationBase.extend({\n title: z.string().nullable(),\n projectId: ProjectId,\n type: z.literal(\"studio\"),\n /**\n * @deprecated Use `manifestData` instead.\n */\n manifest: ClientManifest.nullable(),\n manifestData: z.object({ value: ClientManifest }).nullable(),\n autoUpdatingVersion: z.string().nullable(),\n config: z.object({\n \"live-manifest\": z\n .object({\n createdAt: z.string(),\n updatedAt: z.string(),\n updatedBy: z.string(),\n value: ServerManifest,\n })\n .optional(),\n }),\n});\n\nconst InternalStudioUserApplication = StudioUserApplicationBase.extend({\n urlType: z.literal(\"internal\"),\n activeDeployment: ActiveDeployment.extend({\n manifest: ServerManifest.nullable(),\n }).nullable(),\n});\n\nconst ExternalStudioUserApplication = StudioUserApplicationBase.extend({\n urlType: z.literal(\"external\"),\n activeDeployment: ActiveDeployment.extend({\n manifest: ServerManifest.nullable(),\n }).nullable(),\n});\n\n/**\n * Studio user application schema — validates and brands API\n * responses from the `/user-applications?appType=studio`\n * endpoint. Uses a discriminated union on `urlType`.\n * @public\n */\nexport const StudioUserApplication = z.discriminatedUnion(\"urlType\", [\n InternalStudioUserApplication,\n ExternalStudioUserApplication,\n]);\n\n/**\n * @public\n */\nexport type StudioUserApplication = z.output<typeof StudioUserApplication>;\n\n/**\n * Validates and parses a raw API response into a branded\n * StudioUserApplication.\n * @public\n */\nexport function parseStudioUserApplication(\n data: unknown,\n): StudioUserApplication {\n return StudioUserApplication.parse(data);\n}\n","import type { StudioResource as ProtocolStudioResource } from \"@sanity/message-protocol\";\n\nimport { AbstractApplication } from \"../../applications/application\";\nimport type { Project } from \"../../projects\";\nimport { joinUrlPaths, normalizePath } from \"../../shared/urls\";\nimport type { UserApplicationId } from \"../user-application\";\nimport type { Workspace } from \"./schemas\";\nimport type { StudioApplication } from \"./studio\";\n\n/**\n * @public\n */\nexport class StudioWorkspace extends AbstractApplication<\n \"workspace\",\n ProtocolStudioResource\n> {\n /**\n * Workspaces always belong to a studio application.\n * They do not exist on their own & therefore can access\n * information about the studio they're in via this property.\n */\n private readonly studioApplication: StudioApplication;\n private readonly workspace: Workspace;\n readonly project: Project<false, false>;\n private readonly isDefaultWorkspace: boolean;\n\n constructor(\n studioApplication: StudioApplication,\n workspace: Workspace,\n project: Project<false, false>,\n isDefaultWorkspace: boolean,\n ) {\n super(\"workspace\");\n\n this.studioApplication = studioApplication;\n this.workspace = workspace;\n this.project = project;\n this.isDefaultWorkspace = isDefaultWorkspace;\n }\n\n /**\n * The studio application that this workspace belongs to.\n */\n get studio() {\n return this.studioApplication;\n }\n\n get id() {\n return StudioWorkspace.makeId(this.studio.id, this.workspace.name);\n }\n\n get href() {\n return joinUrlPaths(this.studio.href, this.workspace.name);\n }\n\n get title() {\n /**\n * If there's no manifest we will have created a single workspace for the application.\n * In this circumstance we won't have a meaningful title, so instead we use the hostname of the appHost.\n */\n if (this.isDefaultWorkspace) {\n return this.project.displayName;\n }\n\n return this.workspace.title;\n }\n\n get subtitle() {\n if (this.isDefaultWorkspace) {\n const isValidAppHost = URL.canParse(this.studio.get(\"appHost\"));\n const url = isValidAppHost\n ? new URL(this.studio.get(\"appHost\"))\n : this.studio.url;\n\n return url.hostname;\n }\n\n return this.get(\"subtitle\");\n }\n\n get<TKey extends Exclude<keyof Workspace, \"id\" | \"icon\" | \"title\">>(\n attr: TKey,\n ): Workspace[TKey] {\n return this.workspace[attr];\n }\n\n get isFederated() {\n return this.studio.isFederated;\n }\n\n /**\n * With comlink, studio-applications were not considered applications at all, only workspaces. This is partially why\n * we create default workspaces when the application has no manifest or the manifest has no workspaces.\n *\n * Thereby, to create it we depend on a lot of information from the parent application even if it's duplicated across\n * different workspaces.\n */\n toProtocolResource(): ProtocolStudioResource {\n return {\n ...this.workspace,\n type: \"studio\",\n userApplicationId: this.studio.id,\n activeDeployment: this.studio.get(\"activeDeployment\"),\n autoUpdatingVersion: this.studio.get(\"autoUpdatingVersion\"),\n dashboardStatus: this.studio.get(\"dashboardStatus\"),\n url: this.studio.url.toString(),\n href: this.href,\n id: this.id,\n hasManifest: true,\n hasSchema: Boolean(\"schema\" in this.workspace && this.workspace.schema),\n // The protocol resource requires the client-shaped manifest (workspaces\n // with `schema`). Read those sources directly rather than the unified\n // `manifest` getter, which may return a `ServerManifest` for studios\n // with a deployment manifest.\n manifest: (this.studio.get(\"manifestData\")?.value ??\n this.studio.get(\"manifest\") ??\n null) as ProtocolStudioResource[\"manifest\"],\n updatedAt: this.studio.get(\"updatedAt\"),\n version: this.studio.get(\"activeDeployment\")?.version,\n urlType: this.studio.get(\"urlType\"),\n config: this.studio.get(\"config\"),\n } satisfies ProtocolStudioResource;\n }\n\n /**\n * @returns the URL to the workspace of a studio application.\n */\n get url(): URL {\n const studioUrl = new URL(this.studio.url);\n const normalizedUrlPath = normalizePath(studioUrl.pathname);\n\n let finalBasePath = normalizePath(this.get(\"basePath\"));\n\n // the appHost may already contain the basepath for externally hosted studios\n // or embedded studios, so we deduplicate the segments\n if (finalBasePath.startsWith(normalizedUrlPath)) {\n finalBasePath = finalBasePath.slice(normalizedUrlPath.length);\n }\n\n studioUrl.pathname = joinUrlPaths(normalizedUrlPath, finalBasePath);\n\n return studioUrl;\n }\n\n static makeId(applicationId: UserApplicationId, workspaceName: string) {\n return `${applicationId}-${workspaceName}`;\n }\n\n static splitId(id: string): [string, string] {\n return id.split(new RegExp(/-(.*)/)).slice(0, 2) as [string, string];\n }\n}\n","import type { SemVer } from \"semver\";\nimport { coerce, gt, gte, lt, rsort, valid } from \"semver\";\nimport { z } from \"zod\";\n\nimport type { Project } from \"../../projects\";\nimport { UserApplication } from \"../user-application\";\nimport {\n type ClientManifest as ClientManifestType,\n type ServerManifest as ServerManifestType,\n type Workspace,\n type StudioUserApplication,\n ClientManifest as ClientManifestSchema,\n ServerManifest as ServerManifestSchema,\n} from \"./schemas\";\nimport { StudioWorkspace } from \"./workspace\";\n\n/**\n * Validated manifest — accepts either a refined client manifest (with\n * version ≥ 2 and `studioVersion` set for v3+) or a server/deployment\n * manifest. Parsing fails when the input matches neither shape.\n */\nconst Manifest = z.union([\n ClientManifestSchema.superRefine((data, ctx) => {\n if (!data.version) {\n ctx.addIssue({\n code: \"invalid_type\",\n message: \"Manifest version is too old\",\n expected: \"number\",\n });\n }\n\n if (data.version < 2) {\n ctx.addIssue({\n code: \"invalid_value\",\n message: \"Manifest version is too old\",\n values: [2, 3],\n });\n }\n\n if (data.version >= 3 && !data.studioVersion) {\n ctx.addIssue({\n code: \"invalid_type\",\n message: \"Manifest version 3 or higher requires a `studioVersion`\",\n expected: \"string\",\n });\n }\n }),\n ServerManifestSchema,\n]);\n\nconst DEFAULT_WORKSPACE_DATA = {\n name: \"default\",\n title: \"Default\",\n basePath: \"/\",\n} as const satisfies Omit<Workspace, \"projectId\">;\n\n/**\n * @public\n */\nexport class StudioApplication extends UserApplication<\n StudioUserApplication,\n \"studio\",\n never\n> {\n /**\n * Returns a list of studio workspaces based on the application manifest.\n * If there is no manifest, or alternatively it is not valid, then we create a default workspace.\n */\n readonly workspaces: readonly StudioWorkspace[] = [];\n\n readonly project: Project<false, false>;\n\n /**\n * The projects actually referenced by this studio — the application's own\n * project plus any project used by a workspace. Preserved so the instance\n * can be re-constructed (e.g. by dock wrappers) without having to thread\n * the full organization project list through again.\n */\n readonly projects: Project<false, false>[];\n\n /**\n * @param application - The studio application to create a list of workspaces for\n * @param projects - The projects available in the organization. It's not enough to just pass\n * the project that associates with the application because that is the project the app is deployed in relation to.\n * The workspaces may have different projects completely.\n */\n constructor(\n application: StudioUserApplication,\n projects: Project<false, false>[],\n options: {\n isLocal?: boolean;\n remoteApplication?: StudioApplication | null;\n } = {},\n ) {\n super(application, \"studio\", options);\n\n /**\n * Derive workspaces from the application's most authoritative manifest.\n * `this.manifest` already prefers the deployment manifest over the\n * client manifest; the `Manifest` schema accepts either shape and\n * rejects malformed ones (e.g. a v3 client manifest missing\n * `studioVersion`). A parse failure logs a warning and falls through\n * to the default-workspace path rather than crashing.\n */\n let workspaces: Workspace[] = [];\n const manifest = this.manifest;\n if (manifest) {\n try {\n workspaces = Manifest.parse(manifest).workspaces ?? [];\n } catch (error) {\n console.warn(\n `Failed to parse manifest for application ${application.id}`,\n error,\n );\n }\n }\n\n /**\n * Filter all the workspaces that have a project the user does not have access to.\n */\n const workspacesWithProjectsMap = workspaces.reduce((acc, workspace) => {\n const project = projects.find((p) => p.id === workspace.projectId);\n\n if (project) {\n acc.set(workspace, project);\n } else {\n console.warn(\n `Project not found for application ${application.id} and workspace ${workspace.name}. This workspace has been omitted.`,\n );\n }\n\n return acc;\n }, new Map<Workspace, Project<false, false>>());\n\n const project = projects.find((p) => p.id === application.projectId);\n\n if (!project) {\n throw new Error(`Project not found for application ${application.id}`);\n }\n\n if (workspacesWithProjectsMap.size === 0) {\n /**\n * If there are still no workspaces, we create a default workspace.\n */\n workspacesWithProjectsMap.set(\n {\n ...DEFAULT_WORKSPACE_DATA,\n projectId: application.projectId,\n } satisfies Workspace,\n project,\n );\n }\n\n this.workspaces = Object.freeze(\n Array.from(workspacesWithProjectsMap.entries()).map(([workspace, p]) => {\n /**\n * A workspace is considered the default if the dashboard generated it OR because\n * the properties match that of the default workspace generated by the studio.\n * Which is why these values will match because dashboard generates an identical\n * workspace to the default studio one.\n */\n const isDefaultWorkspace =\n workspace.name === DEFAULT_WORKSPACE_DATA.name &&\n workspace.basePath === DEFAULT_WORKSPACE_DATA.basePath &&\n workspace.title === DEFAULT_WORKSPACE_DATA.title;\n\n return this.createWorkspace(workspace, p, isDefaultWorkspace);\n }),\n );\n\n this.project = project;\n\n // Collect only the projects actually referenced by this studio — the\n // application's own project plus any project used by a workspace.\n const usedProjects = new Set<Project<false, false>>([project]);\n for (const workspace of this.workspaces) {\n usedProjects.add(workspace.project);\n }\n this.projects = Array.from(usedProjects);\n }\n\n /**\n * Factory hook called for each workspace during construction. Subclasses\n * override this to substitute a `StudioWorkspace` subclass (e.g. a UI-aware\n * variant in a downstream package) without re-implementing the constructor's\n * workspace-derivation logic.\n */\n protected createWorkspace(\n workspace: Workspace,\n project: Project<false, false>,\n isDefaultWorkspace: boolean,\n ): StudioWorkspace {\n return new StudioWorkspace(this, workspace, project, isDefaultWorkspace);\n }\n\n get href() {\n return this.isLocal\n ? `/local/${this.id}`\n : `/studio/${this.application.id}`;\n }\n\n get title() {\n // Get the title from the user application, this has the highest precedence\n const title = this.get(\"title\");\n if (title) {\n return title;\n }\n\n // If there are multiple workspaces and the studio is internal, use the project display name\n if (this.workspaces.length > 1 && this.get(\"urlType\") === \"internal\") {\n return this.project.displayName;\n }\n\n // Otherwise use the title of the first workspace\n return this.workspaces[0].title;\n }\n\n get subtitle() {\n return new URL(this.url).hostname;\n }\n\n get<TKey extends keyof StudioUserApplication>(\n attr: TKey,\n ): StudioUserApplication[TKey] {\n if (!(attr in this.application)) {\n throw new Error(\n `Attribute ${attr.toString()} does not exist on studio ${this.application.id}`,\n );\n }\n\n return this.application[attr];\n }\n\n /**\n * Resolves the studio's most authoritative manifest. The lookup order is:\n *\n * 1. `activeDeployment.manifest` — deployment manifests are the new\n * primitive within Sanity and are preferred whenever available.\n * 2. `manifestData.value` — fallback to support older studios that\n * haven't produced a deployment manifest yet.\n * 3. `application.manifest` — last-resort legacy field.\n *\n * Returns `null` when no manifest is available. The return shape is a\n * union because the deployment and client manifests are not\n * interchangeable — consumers that depend on client-only fields (e.g.\n * `studioVersion`, workspace `schema`) must narrow or read the raw\n * field they need.\n */\n get manifest(): ClientManifestType | ServerManifestType | null {\n return (\n this.application.activeDeployment?.manifest ??\n this.application.manifestData?.value ??\n this.application.manifest ??\n null\n );\n }\n\n get hasManifest(): boolean {\n const manifest = this.manifest;\n if (!manifest) return false;\n\n // `manifest` is a union: server manifests encode `version` as an optional\n // string, client manifests as a required number. The typeof check doubles\n // as a discriminator — if it's not a number, we're looking at a server\n // manifest whose presence alone is authoritative.\n return typeof manifest.version !== \"number\" || manifest.version >= 2;\n }\n\n get hasSchema(): boolean {\n // A deployment manifest tracks a schema descriptor for every workspace,\n // so its presence is sufficient to short-circuit.\n if (this.application.activeDeployment?.manifest) return true;\n\n // Otherwise inspect the client manifest. We cannot look at\n // `this.workspaces` because it won't contain workspaces the user does\n // not have access to. The application has a schema even if the user\n // can't access any of the workspaces, otherwise it would be displayed\n // as not having a manifest in the setup guide and therefore considered\n // partially compatible.\n const clientManifest =\n this.application.manifestData?.value ?? this.application.manifest;\n const workspaces = clientManifest?.workspaces ?? [];\n\n if (workspaces.length === 0) return false;\n return workspaces.every((w) => Boolean(w.schema));\n }\n\n private resolveVersion() {\n // const growthbook = getGrowthbook()\n\n let version: string | undefined;\n\n if (this.get(\"urlType\") === \"internal\") {\n version = this.get(\"activeDeployment\")?.version;\n } else {\n const clientManifest =\n this.get(\"manifestData\")?.value ?? this.get(\"manifest\");\n // The property 'studioVersion' exists only on external studios,\n // starting from manifest.version 3\n version =\n clientManifest && \"studioVersion\" in clientManifest\n ? clientManifest.studioVersion\n : undefined;\n }\n\n /**\n * Self-hosted studios are often not publicly accessible, which means that\n * Brett often times cannot fetch the manifest to read the version. In this case\n * we try to read the version from the deployment manifest or 'live-manifest', if it exists, to do\n * everything we can to determine the version.\n *\n * Since the data of the live-maninfest can not be trusted, we also must validate\n * that the version is a valid semver version before returning it. It always represents\n * the last known version from when the studio was connected to Sanity's infrastructure,\n * which might not be the version this studio is currently running (e.g. because the version\n * has been downgraded).\n */\n const deploymentManifest = this.get(\"activeDeployment\")?.manifest;\n // const liveManifest = growthbook.isOn('dashboard-use-live-manifest')\n // ? this.get('config')?.['live-manifest']?.value\n // : null\n\n const serverManifest = deploymentManifest; /*?? liveManifest*/\n const bundleVersion = serverManifest?.bundleVersion;\n\n if (bundleVersion && valid(coerce(bundleVersion))) {\n if (!version || (version && gt(bundleVersion, version))) {\n version = bundleVersion;\n }\n }\n\n if (!version || !valid(coerce(version))) {\n return null;\n }\n\n return coerce(version);\n }\n\n get version() {\n const version = this.resolveVersion();\n return version ? version.toString() : null;\n }\n\n get compatibilityStatus(): CompatibilityStatus {\n return StudioApplication.resolveCompatibilityStatus(this);\n }\n\n /**\n * Used to calculate the compatibility status of a given studio application.\n * Optionally if you've resolved the version elsewhere provide that value to\n * get the new compatibility status without mutating the application.\n */\n static resolveCompatibilityStatus(\n application: StudioApplication,\n version: string | null = application.version,\n ): CompatibilityStatus {\n if (\n version === null ||\n lt(version, StudioApplication.MinimumStudioVersion)\n ) {\n return StudioApplication.CompatibilityStatuses.UNKNOWN;\n }\n\n if (\n !application.hasSchema ||\n !application.hasManifest ||\n StudioApplication.resolveIssues(application, version).length > 0\n ) {\n return StudioApplication.CompatibilityStatuses.PARTIALLY_COMPATIBLE;\n }\n\n return StudioApplication.CompatibilityStatuses.FULLY_COMPATIBLE;\n }\n\n get isAutoRedirecting(): boolean {\n return StudioApplication.resolveIsAutoRedirecting(this);\n }\n\n /**\n * Mirrors the `isRedirectable` function from Saison defined in\n * https://github.com/sanity-io/saison/blob/83556405d23e07f6d3a71c76249c67e33fe1101f/src/utils/applications.ts\n *\n * Returns whether a studio application is auto-redirecting, meaning it can only be accessed in the context of\n * Dashboard.\n */\n static resolveIsAutoRedirecting(\n application: StudioApplication,\n versionArg = application.version,\n ) {\n let version: string | SemVer | null = versionArg;\n\n if (application.get(\"urlType\") === \"external\" || !version) {\n return false;\n }\n\n if (!application.get(\"activeDeployment\")?.isAutoUpdating) {\n // If the studio is not auto-updating, we need to check if the version supports\n // workspace switcher (3.92.0+) otherwise it would not be redirected.\n return gt(version, \"3.92.0\");\n }\n\n const autoUpdatingVersion = application.get(\"autoUpdatingVersion\");\n\n if (autoUpdatingVersion) {\n if ([\"next\", \"stable\", \"latest\"].includes(autoUpdatingVersion)) {\n return true;\n }\n\n const autoUpdatingVersionPinnedVersion = coerce(autoUpdatingVersion);\n\n if (autoUpdatingVersionPinnedVersion) {\n version = autoUpdatingVersionPinnedVersion;\n }\n }\n\n return gt(version, StudioApplication.MinimumStudioVersion);\n }\n\n /**\n * Returns a list of issues that prevent the studio from functioning properly in the Dashboard.\n * This static value depends on the version of the studio that comes from the `activeDeployment` property.\n * As such, if the studio is auto-updating, this list will be incorrect & instead you should use\n * the static method `resolveIssues` to get the correct issues by passing the resolved version.\n */\n get issues(): StudioIssues {\n return StudioApplication.resolveIssues(this);\n }\n\n static resolveIssues(\n application: StudioApplication,\n version: string | null = application.version,\n ): StudioIssues {\n const issues: StudioIssues = StudioApplication.Features.filter(\n (feature) => {\n return !application.isFeatureSupported(feature.id, version);\n },\n );\n\n if (!application.hasManifest) {\n issues.push({\n id: StudioApplication.StudioIssues.ISSUE_MANIFEST,\n });\n }\n\n return issues;\n }\n\n protected isFeatureSupported(\n feature: StudioDashboardIssue,\n version = this.version,\n ) {\n const featureVersion = StudioApplication.Features.find(\n (_) => _.id === feature,\n )?.version;\n\n if (!featureVersion || !version) {\n return false;\n }\n\n return gte(version, featureVersion);\n }\n\n toProtocolResource(): never {\n throw new Error(\n \"Studio application resources cannot be converted to protocol resources\",\n );\n }\n\n static CompatibilityStatuses = {\n UNKNOWN: \"unknown\",\n PARTIALLY_COMPATIBLE: \"partially-compatible\",\n FULLY_COMPATIBLE: \"fully-compatible\",\n } as const;\n\n static StudioIssues = {\n ISSUE_ACTIVITY: \"ACTIVITY\",\n ISSUE_AGENT: \"AGENT\",\n ISSUE_FAVORITES: \"FAVORITES\",\n ISSUE_URL_SYNCING: \"URL_SYNCING\",\n ISSUE_UI_ADJUSTMENT: \"UI_ADJUSTMENT\",\n ISSUE_CONTENT_MAPPING: \"CONTENT_MAPPING\",\n ISSUE_LOGIN: \"LOGIN\",\n ISSUE_MANIFEST: \"MANIFEST\",\n } as const;\n\n static Features = [\n {\n id: StudioApplication.StudioIssues.ISSUE_AGENT,\n version: \"5.1.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_FAVORITES,\n version: \"3.88.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_ACTIVITY,\n version: \"3.88.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_URL_SYNCING,\n version: \"3.75.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_UI_ADJUSTMENT,\n version: \"3.78.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_CONTENT_MAPPING,\n version: \"3.68.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_LOGIN,\n version: \"2.28.0\",\n },\n ] satisfies StudioIssues;\n\n static MinimumStudioVersion = \"2.28.0\" as const;\n\n static MinimumStudioVersionWithNoIssues = rsort(\n StudioApplication.Features.map((feature) => feature.version),\n ).at(0);\n}\n\ntype CompatibilityStatus =\n (typeof StudioApplication.CompatibilityStatuses)[keyof typeof StudioApplication.CompatibilityStatuses];\n\ntype StudioDashboardIssue =\n (typeof StudioApplication.StudioIssues)[keyof typeof StudioApplication.StudioIssues];\n\ntype StudioIssues = Array<{\n id: StudioDashboardIssue;\n version?: string;\n}>;\n"],"names":["ClientManifestSchema","ServerManifestSchema","project"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"studio.js","sources":["../../src/core/applications/application.ts","../../src/core/env.ts","../../src/core/organizations.ts","../../src/core/canvases.ts","../../src/core/media-libraries.ts","../../src/core/projects.ts","../../src/core/shared/urls.ts","../../src/core/user-applications/user-application.ts","../../src/core/user-applications/core-app.ts","../../src/core/user-applications/studios/schemas.ts","../../src/core/user-applications/studios/workspace.ts","../../src/core/user-applications/studios/studio.ts"],"sourcesContent":["import {\n type App,\n type Interface,\n InterfaceSchema,\n type LocalApp,\n type LocalInterface,\n LocalInterfaceSchema,\n type LocalPanel,\n type LocalService,\n type Panel,\n type PanelComponent,\n type Service,\n} from \"@sanity/federation\";\nimport type { Resource as ProtocolResource } from \"@sanity/message-protocol\";\n\n// The interface model lives in @sanity/federation, which owns the\n// `unstable_defineView` / `unstable_defineService` contracts. Re-export it so it\n// stays part of the workbench app-model surface. `Panel`/`LocalPanel`,\n// `Service`/`LocalService`, and `App`/`LocalApp` are the panel-, worker-, and\n// app-typed subsets.\nexport {\n type App,\n type Interface,\n InterfaceSchema,\n type LocalApp,\n type LocalInterface,\n LocalInterfaceSchema,\n type LocalPanel,\n type LocalService,\n type Panel,\n type PanelComponent,\n type Service,\n};\n\n/**\n * @public\n */\nexport type AbstractApplicationType =\n | \"studio\"\n | \"coreApp\"\n | \"canvas\"\n | \"media-library\"\n | \"workspace\";\n\n/**\n * @public\n */\nexport abstract class AbstractApplication<\n TType extends AbstractApplicationType,\n TProtocolResource extends ProtocolResource = Extract<\n ProtocolResource,\n { type: TType }\n >,\n> {\n readonly type: TType;\n\n constructor(type: TType) {\n this.type = type;\n }\n\n /**\n * The in-app route this application navigates to, or `null` when it isn't\n * navigable as a full-page app (US5 — e.g. an SDK app with no `app` view).\n * The dock renders a navigable item only for a non-null `href`; the app\n * routes 404 a `null`-href app on direct visit.\n */\n abstract get href(): string | null;\n\n abstract get title(): string;\n\n abstract get id(): string;\n\n /**\n * Whether the application is federated or not. This is used to determine\n * if the application should be rendered in an iframe or not.\n */\n abstract get isFederated(): boolean;\n\n /**\n * Whether the application is served by a local CLI dev server rather than a\n * deployed remote. Defaults to `false`; user applications flip this when\n * constructed from a `LocalUserApplication` payload.\n */\n get isLocal(): boolean {\n return false;\n }\n\n abstract get url(): URL;\n\n /**\n * Interfaces the application exposes (e.g. dock panels). Defaults to none;\n * user applications surface what they declared via `unstable_defineApp`.\n */\n get interfaces(): readonly LocalInterface[] {\n return [];\n }\n\n /**\n * Whether the application has a navigable full-page `app` view (US5). Defaults\n * to `true` — studios, Canvas, and Media Library are always navigable. An SDK\n * app overrides this to derive it from whether it declares an `app` interface.\n */\n get hasAppView(): boolean {\n return true;\n }\n\n /**\n * Federation module id of the app's full-page view (`${id}/App`), or `null`\n * when it can't be federation-loaded: the app isn't federated (Canvas, Media\n * Library, deployed apps shown in an iframe) or has no app view. Only a\n * non-null `moduleId` is fetched and rendered by the remotes machine.\n */\n get moduleId(): string | null {\n return this.isFederated && this.hasAppView ? `${this.id}/App` : null;\n }\n\n /**\n * Federation module id of one of this app's panel view components, or `null`\n * when the app isn't federated (a non-federated app's panels can't be loaded\n * as remotes).\n */\n resolveViewModuleId(\n view: LocalPanel,\n component: PanelComponent,\n ): string | null {\n return this.isFederated\n ? `${this.id}/views/${view.name}/${component}`\n : null;\n }\n\n get initials(): string {\n const SYMBOLS = /[^\\p{Alpha}\\p{N}\\p{White_Space}]/gu;\n const WHITESPACE = /\\p{White_Space}+/u;\n const ALPHANUMERIC_SEGMENTS = /(\\p{N}+|\\p{Alpha}+)/gu;\n const IS_NUMERIC = /^\\p{N}+$/u;\n\n if (!this.title) return \"\";\n\n const namesArray = this.title\n .replace(SYMBOLS, \"\")\n .split(WHITESPACE)\n .filter(Boolean);\n\n if (namesArray.length === 0) return \"\";\n\n if (namesArray.length === 1) {\n const word = namesArray[0];\n const segments = word.match(ALPHANUMERIC_SEGMENTS) || [];\n\n if (segments.length === 0) return \"\";\n if (segments.length === 1) {\n if (word.length === 1) {\n return word.toUpperCase();\n }\n\n if (IS_NUMERIC.test(word)) {\n return `${word.charAt(0)}${word.charAt(1)}`.toUpperCase();\n }\n\n return word.charAt(0).toUpperCase();\n }\n\n return `${segments[0]!.charAt(0)}${segments[1].charAt(0)}`.toUpperCase();\n }\n\n return `${namesArray[0].charAt(0)}${namesArray[namesArray.length - 1].charAt(0)}`.toUpperCase();\n }\n\n /**\n * Converts the resource to a protocol resource that comlink expects\n * for backwards compatibility with the old API format.\n */\n abstract toProtocolResource(): TProtocolResource;\n}\n","declare const __SANITY_STAGING__: boolean | undefined;\n\n/**\n * Returns the Sanity domain based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, the staging domain is returned.\n * Otherwise, the production domain is returned.\n *\n * @public\n */\nexport function getSanityDomain(): string {\n if (getSanityEnv() === \"staging\") {\n return \"sanity.work\";\n }\n return \"sanity.io\";\n}\n\n/**\n * Returns the API host based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, the staging API host is returned.\n * Otherwise, the production API host is returned.\n *\n * @public\n */\nexport function getApiHost(): string | undefined {\n return `https://api.${getSanityDomain()}`;\n}\n\n/**\n * Returns the current Sanity environment based on the `__SANITY_STAGING__` runtime-time flag.\n * If the flag is set to `true`, \"staging\" is returned.\n * Otherwise, \"production\" is returned.\n *\n * @public\n */\nexport function getSanityEnv(): \"staging\" | \"production\" {\n if (\n typeof __SANITY_STAGING__ !== \"undefined\" &&\n __SANITY_STAGING__ === true\n ) {\n return \"staging\";\n }\n return \"production\";\n}\n","import { z } from \"zod\";\n\n/**\n * Organization ID schema, branded for type safety.\n * @public\n */\nexport const OrganizationId = z.string().nonempty().brand(\"OrganizationId\");\n\n/**\n * Organization ID type, branded for type safety.\n * @public\n */\nexport type OrganizationId = z.output<typeof OrganizationId>;\n\n/**\n * Validates and brands a string as an OrganizationId.\n * @public\n */\nexport function brandOrganizationId(id: string): OrganizationId {\n return OrganizationId.parse(id);\n}\n\nconst OrganizationMember = z.object({\n sanityUserId: z.string(),\n isCurrentUser: z.boolean(),\n user: z.object({\n id: z.string(),\n displayName: z.string(),\n familyName: z.string(),\n givenName: z.string(),\n middleName: z.string().nullable(),\n imageUrl: z.string().nullable(),\n email: z.string(),\n loginProvider: z.string(),\n }),\n roles: z.array(\n z.object({\n name: z.string(),\n title: z.string(),\n description: z.string().optional(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type OrganizationMember = z.output<typeof OrganizationMember>;\n\n/**\n * Organization schema — validates and brands API responses\n * from the `/organizations/:id` endpoint.\n * @public\n */\nexport const Organization = z.object({\n id: OrganizationId,\n name: z.string(),\n slug: z.string().nullable(),\n createdAt: z.string(),\n updatedAt: z.string(),\n dashboardStatus: z.enum([\"enabled\", \"disabled\"]),\n aiFeaturesStatus: z.enum([\"enabled\", \"disabled\"]),\n defaultRoleName: z.string().nullable(),\n});\n\n/**\n * Represents an organization with optional members and\n * features arrays depending on the generic parameters.\n * - `Organization` — base fields only (default)\n * - `Organization<true>` — includes `members`\n * - `Organization<true, true>` — includes both\n * @public\n */\nexport type Organization<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n> = z.output<typeof Organization> &\n (IncludeMembers extends true ? { members: OrganizationMember[] } : unknown) &\n (IncludeFeatures extends true ? { features: string[] } : unknown);\n\n/**\n * Validates and parses a raw API response into a branded\n * Organization. The options control which schema is used —\n * matching what the API returns based on query params.\n * @public\n */\nexport function parseOrganization<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n>(\n data: unknown,\n options?: {\n includeMembers?: IncludeMembers;\n includeFeatures?: IncludeFeatures;\n },\n): Organization<IncludeMembers, IncludeFeatures> {\n const includeMembers = options?.includeMembers ?? true;\n const includeFeatures = options?.includeFeatures ?? true;\n\n const extensions = {\n ...(includeMembers && {\n members: z.array(OrganizationMember),\n }),\n ...(includeFeatures && {\n features: z.array(z.string()),\n }),\n };\n\n const schema =\n Object.keys(extensions).length > 0\n ? Organization.extend(extensions)\n : Organization;\n\n return schema.parse(data) as Organization<IncludeMembers, IncludeFeatures>;\n}\n","import type { CanvasResource as ProtocolCanvasResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { AbstractApplication } from \"./applications/application\";\nimport { getSanityDomain } from \"./env\";\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Canvas ID schema, branded for type safety.\n * @public\n */\nconst CanvasId = z.string().nonempty().brand(\"CanvasId\");\n\n/**\n * Canvas ID type, branded for type safety.\n * @public\n */\nexport type CanvasId = z.output<typeof CanvasId>;\n\n/**\n * Validates and brands a string as a CanvasId.\n * @public\n */\nexport function brandCanvasId(id: string): CanvasId {\n return CanvasId.parse(id);\n}\n\nconst Canvas = z.object({\n id: CanvasId,\n organizationId: OrganizationId,\n status: z.enum([\"active\", \"provisioning\"]),\n});\n\n/**\n * Represents a Canvas resource as returned from the API.\n * @public\n */\nexport type Canvas = z.output<typeof Canvas>;\n\n/**\n * Validates and parses a raw API response into a branded\n * Canvas.\n * @public\n */\nexport function parseCanvas(data: unknown): Canvas {\n return Canvas.parse(data);\n}\n\n/**\n * Whilst the constructor takes an organization's canvas resource the existance\n * therefore implies the organization has access to the canvas application which\n * is what workbench most importantly wants to know.\n * @public\n */\nexport class CanvasApplication extends AbstractApplication<\"canvas\"> {\n readonly canvas: Canvas;\n\n constructor(canvas: Canvas) {\n super(\"canvas\");\n\n this.canvas = canvas;\n }\n\n get id(): CanvasId {\n return this.canvas.id;\n }\n\n get href(): string {\n return \"canvas\";\n }\n\n get title(): string {\n return \"Canvas\";\n }\n\n get url(): URL {\n return new URL(\n `https://canvas.${getSanityDomain()}/o/${this.canvas.organizationId}`,\n );\n }\n\n get isFederated(): boolean {\n return false;\n }\n\n toProtocolResource(): ProtocolCanvasResource {\n return {\n type: \"canvas\",\n id: this.id,\n } satisfies ProtocolCanvasResource;\n }\n}\n","import type { MediaResource as ProtocolMediaResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { AbstractApplication } from \"./applications/application\";\nimport { getSanityDomain } from \"./env\";\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Canvas ID schema, branded for type safety.\n * @public\n */\nconst MediaLibraryId = z.string().nonempty().brand(\"MediaLibraryId\");\n\n/**\n * MediaLibrary ID type, branded for type safety.\n * @public\n */\nexport type MediaLibraryId = z.output<typeof MediaLibraryId>;\n\n/**\n * Validates and brands a string as a MediaLibraryId.\n * @public\n */\nexport function brandMediaLibraryId(id: string): MediaLibraryId {\n return MediaLibraryId.parse(id);\n}\n\nconst MediaLibrary = z.object({\n id: MediaLibraryId,\n organizationId: OrganizationId,\n status: z.enum([\"active\", \"provisioning\"]),\n aclMode: z.enum([\"private\", \"public\"]),\n});\n\n/**\n * Represents a MediaLibrary resource as returned from the API.\n * @public\n */\nexport type MediaLibrary = z.output<typeof MediaLibrary>;\n\n/**\n * Validates and parses a raw API response into a branded\n * MediaLibrary.\n * @public\n */\nexport function parseMediaLibrary(data: unknown): MediaLibrary {\n return MediaLibrary.parse(data);\n}\n\n/**\n * Whilst the constructor takes an organization's media library resource the existance\n * therefore implies the organization has access to the media library application which\n * is what workbench most importantly wants to know.\n * @public\n */\nexport class MediaLibraryApplication extends AbstractApplication<\"media-library\"> {\n readonly library: MediaLibrary;\n\n constructor(library: MediaLibrary) {\n super(\"media-library\");\n\n this.library = library;\n }\n\n get id(): string {\n return this.library.id;\n }\n\n get href(): string {\n return \"media\";\n }\n\n get title(): string {\n return \"Media Library\";\n }\n\n get isFederated(): boolean {\n return false;\n }\n\n get url(): URL {\n return new URL(\n `https://media.${getSanityDomain()}/${this.library.organizationId}`,\n );\n }\n\n toProtocolResource(): ProtocolMediaResource {\n return {\n type: \"media-library\",\n id: this.id,\n } satisfies ProtocolMediaResource;\n }\n}\n","import { z } from \"zod\";\n\nimport { OrganizationId } from \"./organizations\";\n\n/**\n * Project ID schema, branded for type safety.\n * @public\n */\nexport const ProjectId = z.string().nonempty().brand(\"ProjectId\");\n\n/**\n * Project ID type, branded for type safety.\n * @public\n */\nexport type ProjectId = z.output<typeof ProjectId>;\n\n/**\n * Validates and brands a string as a ProjectId.\n * @public\n */\nexport function brandProjectId(id: string): ProjectId {\n return ProjectId.parse(id);\n}\n\nconst ProjectMember = z.object({\n id: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n isCurrentUser: z.boolean(),\n isRobot: z.boolean(),\n roles: z.array(\n z.object({\n name: z.string(),\n title: z.string(),\n description: z.string(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type ProjectMember = z.output<typeof ProjectMember>;\n\n/**\n * Project schema — validates and brands API responses\n * from the `/projects/:id` endpoint.\n * @public\n */\nexport const Project = z.object({\n id: ProjectId,\n displayName: z.string(),\n studioHost: z.string().nullable(),\n organizationId: OrganizationId,\n metadata: z.object({\n color: z.string().optional(),\n externalStudioHost: z.string().optional(),\n initialTemplate: z.string().optional(),\n cliInitializedAt: z.string().optional(),\n integration: z.string().optional(),\n }),\n isBlocked: z.boolean(),\n isDisabled: z.boolean(),\n isDisabledByUser: z.boolean(),\n activityFeedEnabled: z.boolean(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n/**\n * Represents a Sanity project with optional members and\n * features arrays depending on the generic parameters.\n * By default, neither members nor features are included.\n * - `Project` — base fields only (default)\n * - `Project<true>` — includes `members`\n * - `Project<true, true>` — includes both\n * @public\n */\nexport type Project<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n> = z.output<typeof Project> &\n (IncludeMembers extends true ? { members: ProjectMember[] } : unknown) &\n (IncludeFeatures extends true ? { features: string[] } : unknown);\n\n/**\n * Validates and parses a raw API response into a branded\n * Project. The options control which schema is used —\n * matching what the API returns based on query params.\n * @public\n */\nexport function parseProject<\n IncludeMembers extends boolean = true,\n IncludeFeatures extends boolean = true,\n>(\n data: unknown,\n options?: {\n includeMembers?: IncludeMembers;\n includeFeatures?: IncludeFeatures;\n },\n): Project<IncludeMembers, IncludeFeatures> {\n const includeMembers = options?.includeMembers ?? true;\n const includeFeatures = options?.includeFeatures ?? true;\n\n const extensions = {\n ...(includeMembers && { members: z.array(ProjectMember) }),\n ...(includeFeatures && { features: z.array(z.string()) }),\n };\n\n const schema =\n Object.keys(extensions).length > 0 ? Project.extend(extensions) : Project;\n\n return schema.parse(data) as Project<IncludeMembers, IncludeFeatures>;\n}\n","/**\n * Joins multiple path segments into a single path string.\n * Handles null, undefined, and URL objects gracefully.\n *\n * @public\n * @param paths - An array of path segments to join.\n * @returns A single joined path string.\n */\nexport const joinUrlPaths = (\n ...paths: Array<string | URL | null | undefined>\n): string => {\n let nextPath = null;\n\n const safeJoinSegments = (\n segment1: string | null | undefined,\n segment2: string | null | undefined,\n ): string => {\n if (!segment1) {\n if (!segment2) {\n return \"\";\n }\n\n return segment2;\n }\n\n if (!segment2) {\n return segment1;\n }\n\n if (segment1.endsWith(\"/\") && segment2.startsWith(\"/\")) {\n return segment1 + segment2.slice(1);\n }\n\n if (segment1.endsWith(\"/\") || segment2.startsWith(\"/\")) {\n return segment1 + segment2;\n }\n\n return `${segment1}/${segment2}`;\n };\n\n const validPaths = paths.filter(\n (path) => path !== null && path !== undefined,\n );\n\n for (const path of validPaths) {\n nextPath = safeJoinSegments(\n nextPath,\n path instanceof URL ? path.pathname : path,\n );\n }\n\n return nextPath ?? \"\";\n};\n\n/**\n * Returns a normalized path by ensuring it starts with a single leading slash\n * and does not end with a trailing slash (unless it's the root path).\n */\nexport function normalizePath(pathname: string): string {\n if (!pathname.startsWith(\"/\")) {\n pathname = `/${pathname}`;\n }\n\n if (pathname !== \"/\" && pathname.endsWith(\"/\")) {\n pathname = pathname.slice(0, -1);\n }\n\n return pathname;\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\ninterface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial<Path> {\n let parsedPath: Partial<Path> = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substring(hashIndex);\n path = path.substring(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substring(searchIndex);\n path = path.substring(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial<Path>) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : `?${search}`;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : `#${hash}`;\n return pathname;\n}\n","// eslint-disable-next-line no-restricted-imports\nimport type { Resource as ProtocolResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport {\n AbstractApplication,\n type AbstractApplicationType,\n type LocalInterface,\n LocalInterfaceSchema,\n} from \"../applications/application\";\nimport { getSanityDomain, getSanityEnv } from \"../env\";\nimport type { CoreAppUserApplicationManifest } from \"./core-app\";\nimport type { ClientManifest, ServerManifest } from \"./studios/schemas\";\n\n/**\n * User application ID schema, branded for type safety.\n * @public\n */\nexport const UserApplicationId = z\n .string()\n .nonempty()\n .brand(\"UserApplicationId\");\n\n/**\n * User application ID type, branded for type safety.\n * @public\n */\nexport type UserApplicationId = z.output<typeof UserApplicationId>;\n\n/**\n * Validates and brands a string as a UserApplicationId.\n * @public\n */\nexport function brandUserApplicationId(id: string): UserApplicationId {\n return UserApplicationId.parse(id);\n}\n\nconst LocalUserApplicationBase = z.object({\n host: z.string(),\n port: z.number(),\n /**\n * Interfaces the app exposes — dock panels (`interface_type: \"panel\"`) and\n * background workers (`interface_type: \"worker\"`), forwarded from the dev\n * server in one list.\n */\n interfaces: z.array(LocalInterfaceSchema).optional(),\n /** The `deployment.appId` from the application's `sanity.cli.ts`, when set. */\n id: z.string().optional(),\n /**\n * The `api.projectId` from the application's `sanity.cli.ts`. Available\n * synchronously at dev-server startup (no manifest extraction required), so\n * the studio's primary project is resolvable from the very first local\n * application event.\n */\n projectId: z.string().optional(),\n});\n\n/**\n * Raw data for a local application discovered by the CLI dev server.\n *\n * The CLI forwards the full studio or app manifest so the workbench can\n * derive icons, titles, workspaces and schema references the same way it\n * does for deployed applications. The manifest shape is discriminated on\n * `type`: studios receive a `ClientManifest`, core apps a `CoreAppUserApplicationManifest`.\n *\n * When set on a `UserApplication`, `isLocal` is `true` and `url`/`isFederated`\n * honour the local dev-server instead of the deployed application's host.\n *\n * @public\n */\nexport const LocalUserApplication = z.discriminatedUnion(\"type\", [\n LocalUserApplicationBase.extend({\n type: z.literal(\"studio\"),\n manifest: z.custom<ClientManifest>().optional(),\n }),\n LocalUserApplicationBase.extend({\n type: z.literal(\"coreApp\"),\n manifest: z.custom<CoreAppUserApplicationManifest>().optional(),\n }),\n]);\n\n/**\n * @public\n */\nexport type LocalUserApplication = z.output<typeof LocalUserApplication>;\n\n/**\n * @public\n */\nexport const UserApplicationBase = z.object({\n id: UserApplicationId,\n appHost: z.string(),\n urlType: z.enum([\"internal\", \"external\"]),\n createdAt: z.string(),\n updatedAt: z.string(),\n dashboardStatus: z.enum([\"default\", \"disabled\"]),\n /**\n * Interfaces the app exposes (dock panels and background workers). Not part\n * of the manifest.\n */\n interfaces: z.array(LocalInterfaceSchema).optional(),\n});\n\n/**\n * @public\n */\nexport type UserApplicationBase = z.output<typeof UserApplicationBase>;\n\n/**\n * @public\n */\nexport const ActiveDeployment = z.object({\n id: z.string(),\n version: z.string(),\n isActiveDeployment: z.boolean(),\n userApplicationId: z.string(),\n isAutoUpdating: z.boolean(),\n size: z.number(),\n deployedAt: z.string(),\n deployedBy: z.string(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\n/**\n * @public\n */\nexport abstract class UserApplication<\n TUserApplication extends UserApplicationBase,\n TType extends Extract<AbstractApplicationType, \"coreApp\" | \"studio\">,\n TProtocolResource extends ProtocolResource = Extract<\n ProtocolResource,\n { type: TType }\n >,\n> extends AbstractApplication<TType, TProtocolResource> {\n readonly application: TUserApplication;\n\n readonly id: UserApplicationId;\n\n /**\n * For local applications (`isLocal === true`), the deployed application\n * that shares the same `id` — if one was passed at construction. `null`\n * for deployed applications or when no remote twin was provided.\n */\n readonly remoteApplication: this | null;\n\n readonly #isLocal: boolean;\n\n constructor(\n application: TUserApplication,\n type: TType,\n options: {\n isLocal?: boolean;\n remoteApplication?: UserApplication<\n TUserApplication,\n TType,\n TProtocolResource\n > | null;\n } = {},\n ) {\n super(type);\n this.application = application;\n this.id = brandUserApplicationId(application.id);\n this.#isLocal = options.isLocal ?? false;\n this.remoteApplication =\n (options.remoteApplication as this | undefined) ?? null;\n }\n\n abstract get subtitle(): string | undefined;\n\n /**\n * Local dev servers are rendered as federated remotes; deployed applications\n * are rendered in an iframe.\n */\n get isFederated(): boolean {\n return this.isLocal;\n }\n\n override get isLocal(): boolean {\n return this.#isLocal;\n }\n\n override get interfaces(): readonly LocalInterface[] {\n return this.application.interfaces ?? [];\n }\n\n /**\n * @returns A fully resolved URL instance for the application.\n * For internal applications, constructs a URL using the Sanity studio domain\n * pattern resolved from the environment at the consuming app's build time.\n * For external applications (including local dev servers), returns the\n * provided app host as a URL.\n */\n get url(): URL {\n if (this.application.urlType === \"internal\") {\n if (getSanityEnv() === \"production\") {\n return new URL(`https://${this.application.appHost}.sanity.studio`);\n }\n return new URL(\n `https://${this.application.appHost}.studio.${getSanityDomain()}`,\n );\n }\n\n return new URL(this.application.appHost);\n }\n\n /**\n * Unified manifest accessor for user applications. Resolves the most\n * authoritative manifest available for the application, preferring the\n * deployment manifest (`activeDeployment.manifest`) before falling back to\n * any client-side manifest. The returned shape depends on the application\n * type and source: studios may yield either a `ServerManifest` (deployment)\n * or a `ClientManifest` (fallback); core apps yield a\n * `CoreAppUserApplicationManifest`. Returns `null` when no manifest is\n * available.\n */\n abstract get manifest():\n | ClientManifest\n | ServerManifest\n | CoreAppUserApplicationManifest\n | null;\n}\n","// eslint-disable-next-line no-restricted-imports\nimport type { ApplicationResource as ProtocolApplicationResource } from \"@sanity/message-protocol\";\nimport { z } from \"zod\";\n\nimport { OrganizationId } from \"../organizations\";\nimport {\n UserApplication,\n UserApplicationBase,\n ActiveDeployment,\n} from \"./user-application\";\n\n/**\n * @public\n */\nexport const CoreAppUserApplicationManifest = z.object({\n version: z.string(),\n icon: z.string().optional(),\n title: z.string().optional(),\n group: z.string().optional(),\n priority: z.number().optional(),\n});\n\n/**\n * @public\n */\nexport type CoreAppUserApplicationManifest = z.output<\n typeof CoreAppUserApplicationManifest\n>;\n\nconst CoreAppUserApplicationBase = UserApplicationBase.extend({\n title: z.string(),\n organizationId: OrganizationId,\n type: z.literal(\"coreApp\"),\n});\n\n// Core apps surface their manifest exclusively via `activeDeployment.manifest`\n// — they have no top-level `manifest` field and no `manifestData`.\nconst CoreAppActiveDeployment = ActiveDeployment.extend({\n manifest: CoreAppUserApplicationManifest.nullable(),\n}).nullable();\n\nconst InternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({\n urlType: z.literal(\"internal\"),\n activeDeployment: CoreAppActiveDeployment,\n});\n\nconst ExternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({\n urlType: z.literal(\"external\"),\n activeDeployment: CoreAppActiveDeployment,\n});\n\n/**\n * Core application schema — validates and brands API\n * responses from the `/user-applications?appType=coreApp`\n * endpoint. Uses a discriminated union on `urlType`.\n * @public\n */\nconst CoreAppUserApplication = z.discriminatedUnion(\"urlType\", [\n InternalCoreAppUserApplication,\n ExternalCoreAppUserApplication,\n]);\n\n/**\n * @public\n */\nexport type CoreAppUserApplication = z.output<typeof CoreAppUserApplication>;\n\n/**\n * Validates and parses a raw API response into a branded\n * CoreAppUserApplicationData.\n * @public\n */\nexport function parseCoreApplication(data: unknown): CoreAppUserApplication {\n return CoreAppUserApplication.parse(data);\n}\n\n/**\n * @public\n */\nexport class CoreAppApplication extends UserApplication<\n CoreAppUserApplication,\n \"coreApp\",\n ProtocolApplicationResource\n> {\n readonly activeDeployment: CoreAppUserApplication[\"activeDeployment\"];\n\n constructor(\n application: CoreAppUserApplication,\n options: {\n isLocal?: boolean;\n remoteApplication?: CoreAppApplication | null;\n } = {},\n ) {\n super(application, \"coreApp\", options);\n\n this.activeDeployment = application.activeDeployment;\n }\n\n // Typed `string | null` so the UI-aware remote subclass can override it to\n // `null` for a non-navigable app (US5); the core route itself is always set.\n get href(): string | null {\n return this.isLocal\n ? `/local/${this.id}`\n : `/application/${this.application.id}`;\n }\n\n get title() {\n return this.manifest?.title ?? this.application.title;\n }\n\n /**\n * Resolves the core app's manifest from `activeDeployment.manifest`. This\n * is the canonical (and only) slot for core app manifests — both for\n * Sanity-deployed apps and for local CLI dev-server apps, which synthesise\n * a deployment to surface the live manifest.\n */\n get manifest(): CoreAppUserApplicationManifest | null {\n return this.activeDeployment?.manifest ?? null;\n }\n\n get subtitle() {\n return undefined;\n }\n\n get updatedAt() {\n return this.application.updatedAt;\n }\n\n get<TKey extends keyof CoreAppUserApplication>(\n attr: TKey,\n ): CoreAppUserApplication[TKey] {\n if (!(attr in this.application)) {\n throw new Error(\n `Attribute ${attr.toString()} does not exist on application ${this.application.id}`,\n );\n }\n\n return this.application[attr];\n }\n\n toProtocolResource(): ProtocolApplicationResource {\n return {\n ...this.application,\n type: \"application\",\n url: this.url.toString(),\n } as ProtocolApplicationResource;\n }\n}\n","import { z } from \"zod\";\n\nimport { ProjectId } from \"../../projects\";\nimport { ActiveDeployment, UserApplicationBase } from \"../user-application\";\n\nconst Workspace = z.object({\n name: z.string(),\n title: z.string(),\n subtitle: z.string().optional(),\n basePath: z.string(),\n projectId: ProjectId,\n dataset: z.string().optional(),\n icon: z.string().nullable().optional(),\n});\n\n/**\n * @public\n */\nexport type Workspace = z.output<typeof Workspace>;\n\n/**\n * @public\n */\nexport const ServerManifest = z.object({\n buildId: z.string().optional(),\n bundleVersion: z.string().optional(),\n version: z.string().optional(),\n group: z.string().optional(),\n priority: z.number().optional(),\n workspaces: z\n .array(\n Workspace.extend({\n dataset: z.string(),\n schemaDescriptorId: z.string(),\n }),\n )\n .optional(),\n});\n\n/**\n * @public\n */\nexport type ServerManifest = z.output<typeof ServerManifest>;\n\n/**\n * @public\n */\nexport const ClientManifest = z.object({\n version: z.number(),\n createdAt: z.string(),\n studioVersion: z.string().optional(),\n group: z.string().optional(),\n priority: z.number().optional(),\n workspaces: z.array(\n Workspace.extend({\n schema: z.string(),\n tools: z.string().optional(),\n }),\n ),\n});\n\n/**\n * @public\n */\nexport type ClientManifest = z.output<typeof ClientManifest>;\n\nconst StudioUserApplicationBase = UserApplicationBase.extend({\n title: z.string().nullable(),\n projectId: ProjectId,\n type: z.literal(\"studio\"),\n /**\n * @deprecated Use `manifestData` instead.\n */\n manifest: ClientManifest.nullable(),\n manifestData: z.object({ value: ClientManifest }).nullable(),\n autoUpdatingVersion: z.string().nullable(),\n config: z.object({\n \"live-manifest\": z\n .object({\n createdAt: z.string(),\n updatedAt: z.string(),\n updatedBy: z.string(),\n value: ServerManifest,\n })\n .optional(),\n }),\n});\n\nconst InternalStudioUserApplication = StudioUserApplicationBase.extend({\n urlType: z.literal(\"internal\"),\n activeDeployment: ActiveDeployment.extend({\n manifest: ServerManifest.nullable(),\n }).nullable(),\n});\n\nconst ExternalStudioUserApplication = StudioUserApplicationBase.extend({\n urlType: z.literal(\"external\"),\n activeDeployment: ActiveDeployment.extend({\n manifest: ServerManifest.nullable(),\n }).nullable(),\n});\n\n/**\n * Studio user application schema — validates and brands API\n * responses from the `/user-applications?appType=studio`\n * endpoint. Uses a discriminated union on `urlType`.\n * @public\n */\nexport const StudioUserApplication = z.discriminatedUnion(\"urlType\", [\n InternalStudioUserApplication,\n ExternalStudioUserApplication,\n]);\n\n/**\n * @public\n */\nexport type StudioUserApplication = z.output<typeof StudioUserApplication>;\n\n/**\n * Validates and parses a raw API response into a branded\n * StudioUserApplication.\n * @public\n */\nexport function parseStudioUserApplication(\n data: unknown,\n): StudioUserApplication {\n return StudioUserApplication.parse(data);\n}\n","import type { StudioResource as ProtocolStudioResource } from \"@sanity/message-protocol\";\n\nimport { AbstractApplication } from \"../../applications/application\";\nimport type { Project } from \"../../projects\";\nimport { joinUrlPaths, normalizePath } from \"../../shared/urls\";\nimport type { UserApplicationId } from \"../user-application\";\nimport type { Workspace } from \"./schemas\";\nimport type { StudioApplication } from \"./studio\";\n\n/**\n * @public\n */\nexport class StudioWorkspace extends AbstractApplication<\n \"workspace\",\n ProtocolStudioResource\n> {\n /**\n * Workspaces always belong to a studio application.\n * They do not exist on their own & therefore can access\n * information about the studio they're in via this property.\n */\n private readonly studioApplication: StudioApplication;\n private readonly workspace: Workspace;\n readonly project: Project<false, false>;\n private readonly isDefaultWorkspace: boolean;\n\n constructor(\n studioApplication: StudioApplication,\n workspace: Workspace,\n project: Project<false, false>,\n isDefaultWorkspace: boolean,\n ) {\n super(\"workspace\");\n\n this.studioApplication = studioApplication;\n this.workspace = workspace;\n this.project = project;\n this.isDefaultWorkspace = isDefaultWorkspace;\n }\n\n /**\n * The studio application that this workspace belongs to.\n */\n get studio() {\n return this.studioApplication;\n }\n\n get id() {\n return StudioWorkspace.makeId(this.studio.id, this.workspace.name);\n }\n\n get href() {\n return joinUrlPaths(this.studio.href, this.workspace.name);\n }\n\n get title() {\n /**\n * If there's no manifest we will have created a single workspace for the application.\n * In this circumstance we won't have a meaningful title, so instead we use the hostname of the appHost.\n */\n if (this.isDefaultWorkspace) {\n return this.project.displayName;\n }\n\n return this.workspace.title;\n }\n\n get subtitle() {\n if (this.isDefaultWorkspace) {\n const isValidAppHost = URL.canParse(this.studio.get(\"appHost\"));\n const url = isValidAppHost\n ? new URL(this.studio.get(\"appHost\"))\n : this.studio.url;\n\n return url.hostname;\n }\n\n return this.get(\"subtitle\");\n }\n\n get<TKey extends Exclude<keyof Workspace, \"id\" | \"icon\" | \"title\">>(\n attr: TKey,\n ): Workspace[TKey] {\n return this.workspace[attr];\n }\n\n get isFederated() {\n return this.studio.isFederated;\n }\n\n /**\n * With comlink, studio-applications were not considered applications at all, only workspaces. This is partially why\n * we create default workspaces when the application has no manifest or the manifest has no workspaces.\n *\n * Thereby, to create it we depend on a lot of information from the parent application even if it's duplicated across\n * different workspaces.\n */\n toProtocolResource(): ProtocolStudioResource {\n return {\n ...this.workspace,\n type: \"studio\",\n userApplicationId: this.studio.id,\n activeDeployment: this.studio.get(\"activeDeployment\"),\n autoUpdatingVersion: this.studio.get(\"autoUpdatingVersion\"),\n dashboardStatus: this.studio.get(\"dashboardStatus\"),\n url: this.studio.url.toString(),\n href: this.href,\n id: this.id,\n hasManifest: true,\n hasSchema: Boolean(\"schema\" in this.workspace && this.workspace.schema),\n // The protocol resource requires the client-shaped manifest (workspaces\n // with `schema`). Read those sources directly rather than the unified\n // `manifest` getter, which may return a `ServerManifest` for studios\n // with a deployment manifest.\n manifest: (this.studio.get(\"manifestData\")?.value ??\n this.studio.get(\"manifest\") ??\n null) as ProtocolStudioResource[\"manifest\"],\n updatedAt: this.studio.get(\"updatedAt\"),\n version: this.studio.get(\"activeDeployment\")?.version,\n urlType: this.studio.get(\"urlType\"),\n config: this.studio.get(\"config\"),\n } satisfies ProtocolStudioResource;\n }\n\n /**\n * @returns the URL to the workspace of a studio application.\n */\n get url(): URL {\n const studioUrl = new URL(this.studio.url);\n const normalizedUrlPath = normalizePath(studioUrl.pathname);\n\n let finalBasePath = normalizePath(this.get(\"basePath\"));\n\n // the appHost may already contain the basepath for externally hosted studios\n // or embedded studios, so we deduplicate the segments\n if (finalBasePath.startsWith(normalizedUrlPath)) {\n finalBasePath = finalBasePath.slice(normalizedUrlPath.length);\n }\n\n studioUrl.pathname = joinUrlPaths(normalizedUrlPath, finalBasePath);\n\n return studioUrl;\n }\n\n static makeId(applicationId: UserApplicationId, workspaceName: string) {\n return `${applicationId}-${workspaceName}`;\n }\n\n static splitId(id: string): [string, string] {\n return id.split(new RegExp(/-(.*)/)).slice(0, 2) as [string, string];\n }\n}\n","import type { SemVer } from \"semver\";\nimport { coerce, gt, gte, lt, rsort, valid } from \"semver\";\nimport { z } from \"zod\";\n\nimport type { Project } from \"../../projects\";\nimport { UserApplication } from \"../user-application\";\nimport {\n type ClientManifest as ClientManifestType,\n type ServerManifest as ServerManifestType,\n type Workspace,\n type StudioUserApplication,\n ClientManifest as ClientManifestSchema,\n ServerManifest as ServerManifestSchema,\n} from \"./schemas\";\nimport { StudioWorkspace } from \"./workspace\";\n\n/**\n * Validated manifest — accepts either a refined client manifest (with\n * version ≥ 2 and `studioVersion` set for v3+) or a server/deployment\n * manifest. Parsing fails when the input matches neither shape.\n */\nconst Manifest = z.union([\n ClientManifestSchema.superRefine((data, ctx) => {\n if (!data.version) {\n ctx.addIssue({\n code: \"invalid_type\",\n message: \"Manifest version is too old\",\n expected: \"number\",\n });\n }\n\n if (data.version < 2) {\n ctx.addIssue({\n code: \"invalid_value\",\n message: \"Manifest version is too old\",\n values: [2, 3],\n });\n }\n\n if (data.version >= 3 && !data.studioVersion) {\n ctx.addIssue({\n code: \"invalid_type\",\n message: \"Manifest version 3 or higher requires a `studioVersion`\",\n expected: \"string\",\n });\n }\n }),\n ServerManifestSchema,\n]);\n\nconst DEFAULT_WORKSPACE_DATA = {\n name: \"default\",\n title: \"Default\",\n basePath: \"/\",\n} as const satisfies Omit<Workspace, \"projectId\">;\n\n/**\n * @public\n */\nexport class StudioApplication extends UserApplication<\n StudioUserApplication,\n \"studio\",\n never\n> {\n /**\n * Returns a list of studio workspaces based on the application manifest.\n * If there is no manifest, or alternatively it is not valid, then we create a default workspace.\n */\n readonly workspaces: readonly StudioWorkspace[] = [];\n\n readonly project: Project<false, false>;\n\n /**\n * The projects actually referenced by this studio — the application's own\n * project plus any project used by a workspace. Preserved so the instance\n * can be re-constructed (e.g. by dock wrappers) without having to thread\n * the full organization project list through again.\n */\n readonly projects: Project<false, false>[];\n\n /**\n * @param application - The studio application to create a list of workspaces for\n * @param projects - The projects available in the organization. It's not enough to just pass\n * the project that associates with the application because that is the project the app is deployed in relation to.\n * The workspaces may have different projects completely.\n */\n constructor(\n application: StudioUserApplication,\n projects: Project<false, false>[],\n options: {\n isLocal?: boolean;\n remoteApplication?: StudioApplication | null;\n } = {},\n ) {\n super(application, \"studio\", options);\n\n /**\n * Derive workspaces from the application's most authoritative manifest.\n * `this.manifest` already prefers the deployment manifest over the\n * client manifest; the `Manifest` schema accepts either shape and\n * rejects malformed ones (e.g. a v3 client manifest missing\n * `studioVersion`). A parse failure logs a warning and falls through\n * to the default-workspace path rather than crashing.\n */\n let workspaces: Workspace[] = [];\n const manifest = this.manifest;\n if (manifest) {\n try {\n workspaces = Manifest.parse(manifest).workspaces ?? [];\n } catch (error) {\n console.warn(\n `Failed to parse manifest for application ${application.id}`,\n error,\n );\n }\n }\n\n /**\n * Filter all the workspaces that have a project the user does not have access to.\n */\n const workspacesWithProjectsMap = workspaces.reduce((acc, workspace) => {\n const project = projects.find((p) => p.id === workspace.projectId);\n\n if (project) {\n acc.set(workspace, project);\n } else {\n console.warn(\n `Project not found for application ${application.id} and workspace ${workspace.name}. This workspace has been omitted.`,\n );\n }\n\n return acc;\n }, new Map<Workspace, Project<false, false>>());\n\n const project = projects.find((p) => p.id === application.projectId);\n\n if (!project) {\n throw new Error(`Project not found for application ${application.id}`);\n }\n\n if (workspacesWithProjectsMap.size === 0) {\n /**\n * If there are still no workspaces, we create a default workspace.\n */\n workspacesWithProjectsMap.set(\n {\n ...DEFAULT_WORKSPACE_DATA,\n projectId: application.projectId,\n } satisfies Workspace,\n project,\n );\n }\n\n this.workspaces = Object.freeze(\n Array.from(workspacesWithProjectsMap.entries()).map(([workspace, p]) => {\n /**\n * A workspace is considered the default if the dashboard generated it OR because\n * the properties match that of the default workspace generated by the studio.\n * Which is why these values will match because dashboard generates an identical\n * workspace to the default studio one.\n */\n const isDefaultWorkspace =\n workspace.name === DEFAULT_WORKSPACE_DATA.name &&\n workspace.basePath === DEFAULT_WORKSPACE_DATA.basePath &&\n workspace.title === DEFAULT_WORKSPACE_DATA.title;\n\n return this.createWorkspace(workspace, p, isDefaultWorkspace);\n }),\n );\n\n this.project = project;\n\n // Collect only the projects actually referenced by this studio — the\n // application's own project plus any project used by a workspace.\n const usedProjects = new Set<Project<false, false>>([project]);\n for (const workspace of this.workspaces) {\n usedProjects.add(workspace.project);\n }\n this.projects = Array.from(usedProjects);\n }\n\n /**\n * Factory hook called for each workspace during construction. Subclasses\n * override this to substitute a `StudioWorkspace` subclass (e.g. a UI-aware\n * variant in a downstream package) without re-implementing the constructor's\n * workspace-derivation logic.\n */\n protected createWorkspace(\n workspace: Workspace,\n project: Project<false, false>,\n isDefaultWorkspace: boolean,\n ): StudioWorkspace {\n return new StudioWorkspace(this, workspace, project, isDefaultWorkspace);\n }\n\n get href() {\n return this.isLocal\n ? `/local/${this.id}`\n : `/studio/${this.application.id}`;\n }\n\n get title() {\n // Get the title from the user application, this has the highest precedence\n const title = this.get(\"title\");\n if (title) {\n return title;\n }\n\n // If there are multiple workspaces and the studio is internal, use the project display name\n if (this.workspaces.length > 1 && this.get(\"urlType\") === \"internal\") {\n return this.project.displayName;\n }\n\n // Otherwise use the title of the first workspace\n return this.workspaces[0].title;\n }\n\n get subtitle() {\n return new URL(this.url).hostname;\n }\n\n get<TKey extends keyof StudioUserApplication>(\n attr: TKey,\n ): StudioUserApplication[TKey] {\n if (!(attr in this.application)) {\n throw new Error(\n `Attribute ${attr.toString()} does not exist on studio ${this.application.id}`,\n );\n }\n\n return this.application[attr];\n }\n\n /**\n * Resolves the studio's most authoritative manifest. The lookup order is:\n *\n * 1. `activeDeployment.manifest` — deployment manifests are the new\n * primitive within Sanity and are preferred whenever available.\n * 2. `manifestData.value` — fallback to support older studios that\n * haven't produced a deployment manifest yet.\n * 3. `application.manifest` — last-resort legacy field.\n *\n * Returns `null` when no manifest is available. The return shape is a\n * union because the deployment and client manifests are not\n * interchangeable — consumers that depend on client-only fields (e.g.\n * `studioVersion`, workspace `schema`) must narrow or read the raw\n * field they need.\n */\n get manifest(): ClientManifestType | ServerManifestType | null {\n return (\n this.application.activeDeployment?.manifest ??\n this.application.manifestData?.value ??\n this.application.manifest ??\n null\n );\n }\n\n get hasManifest(): boolean {\n const manifest = this.manifest;\n if (!manifest) return false;\n\n // `manifest` is a union: server manifests encode `version` as an optional\n // string, client manifests as a required number. The typeof check doubles\n // as a discriminator — if it's not a number, we're looking at a server\n // manifest whose presence alone is authoritative.\n return typeof manifest.version !== \"number\" || manifest.version >= 2;\n }\n\n get hasSchema(): boolean {\n // A deployment manifest tracks a schema descriptor for every workspace,\n // so its presence is sufficient to short-circuit.\n if (this.application.activeDeployment?.manifest) return true;\n\n // Otherwise inspect the client manifest. We cannot look at\n // `this.workspaces` because it won't contain workspaces the user does\n // not have access to. The application has a schema even if the user\n // can't access any of the workspaces, otherwise it would be displayed\n // as not having a manifest in the setup guide and therefore considered\n // partially compatible.\n const clientManifest =\n this.application.manifestData?.value ?? this.application.manifest;\n const workspaces = clientManifest?.workspaces ?? [];\n\n if (workspaces.length === 0) return false;\n return workspaces.every((w) => Boolean(w.schema));\n }\n\n private resolveVersion() {\n // const growthbook = getGrowthbook()\n\n let version: string | undefined;\n\n if (this.get(\"urlType\") === \"internal\") {\n version = this.get(\"activeDeployment\")?.version;\n } else {\n const clientManifest =\n this.get(\"manifestData\")?.value ?? this.get(\"manifest\");\n // The property 'studioVersion' exists only on external studios,\n // starting from manifest.version 3\n version =\n clientManifest && \"studioVersion\" in clientManifest\n ? clientManifest.studioVersion\n : undefined;\n }\n\n /**\n * Self-hosted studios are often not publicly accessible, which means that\n * Brett often times cannot fetch the manifest to read the version. In this case\n * we try to read the version from the deployment manifest or 'live-manifest', if it exists, to do\n * everything we can to determine the version.\n *\n * Since the data of the live-maninfest can not be trusted, we also must validate\n * that the version is a valid semver version before returning it. It always represents\n * the last known version from when the studio was connected to Sanity's infrastructure,\n * which might not be the version this studio is currently running (e.g. because the version\n * has been downgraded).\n */\n const deploymentManifest = this.get(\"activeDeployment\")?.manifest;\n // const liveManifest = growthbook.isOn('dashboard-use-live-manifest')\n // ? this.get('config')?.['live-manifest']?.value\n // : null\n\n const serverManifest = deploymentManifest; /*?? liveManifest*/\n const bundleVersion = serverManifest?.bundleVersion;\n\n if (bundleVersion && valid(coerce(bundleVersion))) {\n if (!version || (version && gt(bundleVersion, version))) {\n version = bundleVersion;\n }\n }\n\n if (!version || !valid(coerce(version))) {\n return null;\n }\n\n return coerce(version);\n }\n\n get version() {\n const version = this.resolveVersion();\n return version ? version.toString() : null;\n }\n\n get compatibilityStatus(): CompatibilityStatus {\n return StudioApplication.resolveCompatibilityStatus(this);\n }\n\n /**\n * Used to calculate the compatibility status of a given studio application.\n * Optionally if you've resolved the version elsewhere provide that value to\n * get the new compatibility status without mutating the application.\n */\n static resolveCompatibilityStatus(\n application: StudioApplication,\n version: string | null = application.version,\n ): CompatibilityStatus {\n if (\n version === null ||\n lt(version, StudioApplication.MinimumStudioVersion)\n ) {\n return StudioApplication.CompatibilityStatuses.UNKNOWN;\n }\n\n if (\n !application.hasSchema ||\n !application.hasManifest ||\n StudioApplication.resolveIssues(application, version).length > 0\n ) {\n return StudioApplication.CompatibilityStatuses.PARTIALLY_COMPATIBLE;\n }\n\n return StudioApplication.CompatibilityStatuses.FULLY_COMPATIBLE;\n }\n\n get isAutoRedirecting(): boolean {\n return StudioApplication.resolveIsAutoRedirecting(this);\n }\n\n /**\n * Mirrors the `isRedirectable` function from Saison defined in\n * https://github.com/sanity-io/saison/blob/83556405d23e07f6d3a71c76249c67e33fe1101f/src/utils/applications.ts\n *\n * Returns whether a studio application is auto-redirecting, meaning it can only be accessed in the context of\n * Dashboard.\n */\n static resolveIsAutoRedirecting(\n application: StudioApplication,\n versionArg = application.version,\n ) {\n let version: string | SemVer | null = versionArg;\n\n if (application.get(\"urlType\") === \"external\" || !version) {\n return false;\n }\n\n if (!application.get(\"activeDeployment\")?.isAutoUpdating) {\n // If the studio is not auto-updating, we need to check if the version supports\n // workspace switcher (3.92.0+) otherwise it would not be redirected.\n return gt(version, \"3.92.0\");\n }\n\n const autoUpdatingVersion = application.get(\"autoUpdatingVersion\");\n\n if (autoUpdatingVersion) {\n if ([\"next\", \"stable\", \"latest\"].includes(autoUpdatingVersion)) {\n return true;\n }\n\n const autoUpdatingVersionPinnedVersion = coerce(autoUpdatingVersion);\n\n if (autoUpdatingVersionPinnedVersion) {\n version = autoUpdatingVersionPinnedVersion;\n }\n }\n\n return gt(version, StudioApplication.MinimumStudioVersion);\n }\n\n /**\n * Returns a list of issues that prevent the studio from functioning properly in the Dashboard.\n * This static value depends on the version of the studio that comes from the `activeDeployment` property.\n * As such, if the studio is auto-updating, this list will be incorrect & instead you should use\n * the static method `resolveIssues` to get the correct issues by passing the resolved version.\n */\n get issues(): StudioIssues {\n return StudioApplication.resolveIssues(this);\n }\n\n static resolveIssues(\n application: StudioApplication,\n version: string | null = application.version,\n ): StudioIssues {\n const issues: StudioIssues = StudioApplication.Features.filter(\n (feature) => {\n return !application.isFeatureSupported(feature.id, version);\n },\n );\n\n if (!application.hasManifest) {\n issues.push({\n id: StudioApplication.StudioIssues.ISSUE_MANIFEST,\n });\n }\n\n return issues;\n }\n\n protected isFeatureSupported(\n feature: StudioDashboardIssue,\n version = this.version,\n ) {\n const featureVersion = StudioApplication.Features.find(\n (_) => _.id === feature,\n )?.version;\n\n if (!featureVersion || !version) {\n return false;\n }\n\n return gte(version, featureVersion);\n }\n\n toProtocolResource(): never {\n throw new Error(\n \"Studio application resources cannot be converted to protocol resources\",\n );\n }\n\n static CompatibilityStatuses = {\n UNKNOWN: \"unknown\",\n PARTIALLY_COMPATIBLE: \"partially-compatible\",\n FULLY_COMPATIBLE: \"fully-compatible\",\n } as const;\n\n static StudioIssues = {\n ISSUE_ACTIVITY: \"ACTIVITY\",\n ISSUE_AGENT: \"AGENT\",\n ISSUE_FAVORITES: \"FAVORITES\",\n ISSUE_URL_SYNCING: \"URL_SYNCING\",\n ISSUE_UI_ADJUSTMENT: \"UI_ADJUSTMENT\",\n ISSUE_CONTENT_MAPPING: \"CONTENT_MAPPING\",\n ISSUE_LOGIN: \"LOGIN\",\n ISSUE_MANIFEST: \"MANIFEST\",\n } as const;\n\n static Features = [\n {\n id: StudioApplication.StudioIssues.ISSUE_AGENT,\n version: \"5.1.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_FAVORITES,\n version: \"3.88.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_ACTIVITY,\n version: \"3.88.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_URL_SYNCING,\n version: \"3.75.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_UI_ADJUSTMENT,\n version: \"3.78.1\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_CONTENT_MAPPING,\n version: \"3.68.0\",\n },\n {\n id: StudioApplication.StudioIssues.ISSUE_LOGIN,\n version: \"2.28.0\",\n },\n ] satisfies StudioIssues;\n\n static MinimumStudioVersion = \"2.28.0\" as const;\n\n static MinimumStudioVersionWithNoIssues = rsort(\n StudioApplication.Features.map((feature) => feature.version),\n ).at(0);\n}\n\ntype CompatibilityStatus =\n (typeof StudioApplication.CompatibilityStatuses)[keyof typeof StudioApplication.CompatibilityStatuses];\n\ntype StudioDashboardIssue =\n (typeof StudioApplication.StudioIssues)[keyof typeof StudioApplication.StudioIssues];\n\ntype StudioIssues = Array<{\n id: StudioDashboardIssue;\n version?: string;\n}>;\n"],"names":["ClientManifestSchema","ServerManifestSchema","project"],"mappings":"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"}
|