@sanity/workbench 0.1.0-alpha.7 → 0.1.0-alpha.8
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/index.js +6 -1
- package/dist/_chunks-es/index.js.map +1 -1
- package/dist/_internal.js +3 -8
- package/dist/_internal.js.map +1 -1
- package/dist/core.d.ts +582 -24
- package/dist/core.js +207 -105
- package/dist/core.js.map +1 -1
- package/package.json +3 -1
- package/src/_internal/render.test.ts +46 -14
- package/src/_internal/render.ts +4 -11
- package/src/core/__tests__/__fixtures__.ts +8 -11
- package/src/core/applications/application-list.test.ts +1 -1
- package/src/core/applications/application-list.ts +1 -1
- package/src/core/applications/local-application.test.ts +3 -3
- package/src/core/applications/local-application.ts +6 -2
- package/src/core/canvases.ts +1 -1
- package/src/core/index.ts +1 -1
- package/src/core/log/index.ts +12 -0
- package/src/core/media-libraries.ts +1 -1
- package/src/core/user-applications/core-app.test.ts +110 -25
- package/src/core/user-applications/core-app.ts +66 -10
- package/src/core/user-applications/studios/index.ts +3 -0
- package/src/core/user-applications/studios/schemas.test.ts +113 -0
- package/src/core/user-applications/studios/schemas.ts +106 -0
- package/src/core/user-applications/{studio.test.ts → studios/studio.test.ts} +106 -37
- package/src/core/user-applications/{studio.ts → studios/studio.ts} +56 -214
- package/src/core/user-applications/studios/workspace.ts +143 -0
- package/src/core/user-applications/user-application.test.ts +7 -8
- package/src/core/user-applications/user-application.ts +36 -5
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { StudioResource as ProtocolStudioResource } from "@sanity/message-protocol";
|
|
2
|
+
|
|
3
|
+
import { AbstractApplication } from "../../applications/application";
|
|
4
|
+
import type { Project } from "../../projects";
|
|
5
|
+
import { joinUrlPaths, normalizePath } from "../../shared/urls";
|
|
6
|
+
import type { UserApplicationId } from "../user-application";
|
|
7
|
+
import type { Workspace } from "./schemas";
|
|
8
|
+
import type { StudioApplication } from "./studio";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export class StudioWorkspace extends AbstractApplication<
|
|
14
|
+
"workspace",
|
|
15
|
+
ProtocolStudioResource
|
|
16
|
+
> {
|
|
17
|
+
/**
|
|
18
|
+
* Workspaces always belong to a studio application.
|
|
19
|
+
* They do not exist on their own & therefore can access
|
|
20
|
+
* information about the studio they're in via this property.
|
|
21
|
+
*/
|
|
22
|
+
private readonly studioApplication: StudioApplication;
|
|
23
|
+
private readonly workspace: Workspace;
|
|
24
|
+
readonly project: Project<false, false>;
|
|
25
|
+
private readonly isDefaultWorkspace: boolean;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
studioApplication: StudioApplication,
|
|
29
|
+
workspace: Workspace,
|
|
30
|
+
project: Project<false, false>,
|
|
31
|
+
isDefaultWorkspace: boolean,
|
|
32
|
+
) {
|
|
33
|
+
super("workspace");
|
|
34
|
+
|
|
35
|
+
this.studioApplication = studioApplication;
|
|
36
|
+
this.workspace = workspace;
|
|
37
|
+
this.project = project;
|
|
38
|
+
this.isDefaultWorkspace = isDefaultWorkspace;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The studio application that this workspace belongs to.
|
|
43
|
+
*/
|
|
44
|
+
get studio() {
|
|
45
|
+
return this.studioApplication;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get id() {
|
|
49
|
+
return StudioWorkspace.makeId(this.studio.id, this.workspace.name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get href() {
|
|
53
|
+
return joinUrlPaths(this.studio.href, this.workspace.name);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get title() {
|
|
57
|
+
/**
|
|
58
|
+
* If there's no manifest we will have created a single workspace for the application.
|
|
59
|
+
* In this circumstance we won't have a meaningful title, so instead we use the hostname of the appHost.
|
|
60
|
+
*/
|
|
61
|
+
if (this.isDefaultWorkspace) {
|
|
62
|
+
return this.project.displayName;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.workspace.title;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get subtitle() {
|
|
69
|
+
if (this.isDefaultWorkspace) {
|
|
70
|
+
const isValidAppHost = URL.canParse(this.studio.get("appHost"));
|
|
71
|
+
const url = isValidAppHost
|
|
72
|
+
? new URL(this.studio.get("appHost"))
|
|
73
|
+
: this.studio.url;
|
|
74
|
+
|
|
75
|
+
return url.hostname;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return this.get("subtitle");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get<TKey extends Exclude<keyof Workspace, "id" | "icon" | "title">>(
|
|
82
|
+
attr: TKey,
|
|
83
|
+
): Workspace[TKey] {
|
|
84
|
+
return this.workspace[attr];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* With comlink, studio-applications were not considered applications at all, only workspaces. This is partially why
|
|
89
|
+
* we create default workspaces when the application has no manifest or the manifest has no workspaces.
|
|
90
|
+
*
|
|
91
|
+
* Thereby, to create it we depend on a lot of information from the parent application even if it's duplicated across
|
|
92
|
+
* different workspaces.
|
|
93
|
+
*/
|
|
94
|
+
toProtocolResource(): ProtocolStudioResource {
|
|
95
|
+
return {
|
|
96
|
+
...this.workspace,
|
|
97
|
+
type: "studio",
|
|
98
|
+
userApplicationId: this.studio.id,
|
|
99
|
+
activeDeployment: this.studio.get("activeDeployment"),
|
|
100
|
+
autoUpdatingVersion: this.studio.get("autoUpdatingVersion"),
|
|
101
|
+
dashboardStatus: this.studio.get("dashboardStatus"),
|
|
102
|
+
url: this.studio.url.toString(),
|
|
103
|
+
href: this.href,
|
|
104
|
+
id: this.id,
|
|
105
|
+
hasManifest: true,
|
|
106
|
+
hasSchema: Boolean("schema" in this.workspace && this.workspace.schema),
|
|
107
|
+
manifest: (this.studio.get("manifestData")?.value ??
|
|
108
|
+
null) as ProtocolStudioResource["manifest"],
|
|
109
|
+
updatedAt: this.studio.get("updatedAt"),
|
|
110
|
+
version: this.studio.get("activeDeployment")?.version,
|
|
111
|
+
urlType: this.studio.get("urlType"),
|
|
112
|
+
config: this.studio.get("config"),
|
|
113
|
+
} satisfies ProtocolStudioResource;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @returns the URL to the workspace of a studio application.
|
|
118
|
+
*/
|
|
119
|
+
get url(): URL {
|
|
120
|
+
const studioUrl = new URL(this.studio.url);
|
|
121
|
+
const normalizedUrlPath = normalizePath(studioUrl.pathname);
|
|
122
|
+
|
|
123
|
+
let finalBasePath = normalizePath(this.get("basePath"));
|
|
124
|
+
|
|
125
|
+
// the appHost may already contain the basepath for externally hosted studios
|
|
126
|
+
// or embedded studios, so we deduplicate the segments
|
|
127
|
+
if (finalBasePath.startsWith(normalizedUrlPath)) {
|
|
128
|
+
finalBasePath = finalBasePath.slice(normalizedUrlPath.length);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
studioUrl.pathname = joinUrlPaths(normalizedUrlPath, finalBasePath);
|
|
132
|
+
|
|
133
|
+
return studioUrl;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static makeId(applicationId: UserApplicationId, workspaceName: string) {
|
|
137
|
+
return `${applicationId}-${workspaceName}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static splitId(id: string): [string, string] {
|
|
141
|
+
return id.split(new RegExp(/-(.*)/)).slice(0, 2) as [string, string];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
CoreApplication,
|
|
4
|
-
} from "@sanity/message-protocol";
|
|
1
|
+
// eslint-disable-next-line no-restricted-imports
|
|
2
|
+
import type { ApplicationResource as ProtocolApplicationResource } from "@sanity/message-protocol";
|
|
5
3
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
4
|
|
|
7
5
|
import { APPLICATION_DATA } from "../__tests__/__fixtures__";
|
|
6
|
+
import type { CoreAppUserApplication } from "./core-app";
|
|
8
7
|
import { UserApplication as AbstractUserApplication } from "./user-application";
|
|
9
8
|
|
|
10
9
|
class UserApplication extends AbstractUserApplication<
|
|
11
|
-
|
|
10
|
+
CoreAppUserApplication,
|
|
12
11
|
"coreApp",
|
|
13
12
|
ProtocolApplicationResource
|
|
14
13
|
> {
|
|
15
|
-
constructor(application:
|
|
14
|
+
constructor(application: CoreAppUserApplication) {
|
|
16
15
|
super(application, "coreApp");
|
|
17
16
|
}
|
|
18
17
|
|
|
@@ -37,11 +36,11 @@ class UserApplication extends AbstractUserApplication<
|
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
const setup = (overrides?: Partial<
|
|
39
|
+
const setup = (overrides?: Partial<CoreAppUserApplication>) =>
|
|
41
40
|
new UserApplication({
|
|
42
41
|
...APPLICATION_DATA,
|
|
43
42
|
...overrides,
|
|
44
|
-
} as
|
|
43
|
+
} as CoreAppUserApplication);
|
|
45
44
|
|
|
46
45
|
describe("UserApplication", () => {
|
|
47
46
|
afterEach(() => {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
UserApplication as UserApplicationData,
|
|
4
|
-
} from "@sanity/message-protocol";
|
|
1
|
+
// eslint-disable-next-line no-restricted-imports
|
|
2
|
+
import type { Resource as ProtocolResource } from "@sanity/message-protocol";
|
|
5
3
|
import { z } from "zod";
|
|
6
4
|
|
|
7
5
|
import {
|
|
@@ -32,11 +30,44 @@ export function brandUserApplicationId(id: string): UserApplicationId {
|
|
|
32
30
|
return UserApplicationId.parse(id);
|
|
33
31
|
}
|
|
34
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export const UserApplicationBase = z.object({
|
|
37
|
+
id: UserApplicationId,
|
|
38
|
+
appHost: z.string(),
|
|
39
|
+
urlType: z.enum(["internal", "external"]),
|
|
40
|
+
createdAt: z.string(),
|
|
41
|
+
updatedAt: z.string(),
|
|
42
|
+
dashboardStatus: z.enum(["default", "disabled"]),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export type UserApplicationBase = z.output<typeof UserApplicationBase>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
export const ActiveDeployment = z.object({
|
|
54
|
+
id: z.string(),
|
|
55
|
+
version: z.string(),
|
|
56
|
+
isActiveDeployment: z.boolean(),
|
|
57
|
+
userApplicationId: z.string(),
|
|
58
|
+
isAutoUpdating: z.boolean(),
|
|
59
|
+
size: z.number(),
|
|
60
|
+
deployedAt: z.string(),
|
|
61
|
+
deployedBy: z.string(),
|
|
62
|
+
createdAt: z.string(),
|
|
63
|
+
updatedAt: z.string(),
|
|
64
|
+
});
|
|
65
|
+
|
|
35
66
|
/**
|
|
36
67
|
* @internal
|
|
37
68
|
*/
|
|
38
69
|
export abstract class UserApplication<
|
|
39
|
-
TUserApplication extends
|
|
70
|
+
TUserApplication extends UserApplicationBase,
|
|
40
71
|
TType extends Extract<AbstractApplicationType, "coreApp" | "studio">,
|
|
41
72
|
TProtocolResource extends ProtocolResource = Extract<
|
|
42
73
|
ProtocolResource,
|