@sanity/workbench-cli 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/_exports/deploy.d.ts +13 -3
  2. package/dist/_exports/deploy.js +2 -1
  3. package/dist/_exports/deploy.js.map +1 -1
  4. package/dist/_exports/dev.d.ts +3 -2
  5. package/dist/_exports/index.d.ts +3 -2
  6. package/dist/_exports/undeploy.d.ts +248 -0
  7. package/dist/_exports/undeploy.js +3 -0
  8. package/dist/_exports/undeploy.js.map +1 -0
  9. package/dist/actions/build/vite/plugin.js +5 -0
  10. package/dist/actions/build/vite/plugin.js.map +1 -1
  11. package/dist/actions/build/vite/plugins/plugin-sanity-app-id.js +5 -3
  12. package/dist/actions/build/vite/plugins/plugin-sanity-app-id.js.map +1 -1
  13. package/dist/actions/build/vite/plugins/plugin-sanity-environment.js +26 -2
  14. package/dist/actions/build/vite/plugins/plugin-sanity-environment.js.map +1 -1
  15. package/dist/actions/deploy/buildExposes.js +5 -2
  16. package/dist/actions/deploy/buildExposes.js.map +1 -1
  17. package/dist/actions/deploy/checkBuiltOutput.js +4 -3
  18. package/dist/actions/deploy/checkBuiltOutput.js.map +1 -1
  19. package/dist/actions/deploy/deployConfig.js +11 -38
  20. package/dist/actions/deploy/deployConfig.js.map +1 -1
  21. package/dist/actions/deploy/deployWorkbenchApp.js +2 -79
  22. package/dist/actions/deploy/deployWorkbenchApp.js.map +1 -1
  23. package/dist/actions/deploy/getWorkbench.js.map +1 -1
  24. package/dist/actions/dev/deriveInterfaces.js +17 -20
  25. package/dist/actions/dev/deriveInterfaces.js.map +1 -1
  26. package/dist/actions/dev/exposesSetId.js +2 -2
  27. package/dist/actions/dev/exposesSetId.js.map +1 -1
  28. package/dist/actions/dev/registry.js +8 -7
  29. package/dist/actions/dev/registry.js.map +1 -1
  30. package/dist/actions/undeploy/workbenchUndeployAdapter.js +150 -0
  31. package/dist/actions/undeploy/workbenchUndeployAdapter.js.map +1 -0
  32. package/dist/defineView.js.map +1 -1
  33. package/dist/services/apiVersion.js.map +1 -0
  34. package/dist/services/applications.js +100 -0
  35. package/dist/services/applications.js.map +1 -0
  36. package/dist/services/installations.js +63 -0
  37. package/dist/services/installations.js.map +1 -0
  38. package/package.json +6 -2
  39. package/dist/actions/deploy/apiVersion.js.map +0 -1
  40. /package/dist/{actions/deploy → services}/apiVersion.js +0 -0
@@ -0,0 +1,150 @@
1
+ import { deleteApplication, getApplication, getApplicationUrl, getWorkbenchUrl } from '../../services/applications.js';
2
+ import { deleteConfig, listConfigs } from '../../services/installations.js';
3
+ import { summarizeExposes } from '../deploy/buildExposes.js';
4
+ import { resolveInstallationId, summarizeConfig } from '../deploy/deployConfig.js';
5
+ /**
6
+ * The undeploy adapter for workbench apps, mirroring what a workbench deploy
7
+ * creates: apps that expose interfaces delete their Brett application (the
8
+ * server soft-deletes its deployments and refuses singletons with active
9
+ * installations); a singleton without interfaces — the media library — deletes
10
+ * its installation's config snapshots instead.
11
+ */ export function createWorkbenchUndeployAdapter(options) {
12
+ const { appId, organizationId, type, workbench } = options;
13
+ // Keyed on singleton-ness, not on a locally declared config, so an undeploy
14
+ // still reaches the server's config snapshots after the fields are removed
15
+ // from sanity.cli.ts.
16
+ const configOnly = !!workbench.isSingleton && !workbench.hasInterfaces;
17
+ // Workbench-internal, so kept off the reported target; resolveTarget stashes it for the delete.
18
+ let installationId;
19
+ return {
20
+ resolveTarget: async ()=>{
21
+ if (!configOnly) return resolveApplicationTarget({
22
+ appId,
23
+ type,
24
+ workbench
25
+ });
26
+ const resolved = await resolveConfigTarget({
27
+ organizationId,
28
+ workbench
29
+ });
30
+ installationId = resolved.installationId;
31
+ return resolved.resolution;
32
+ },
33
+ type,
34
+ async undeploy (target) {
35
+ if (target.deletes === 'config') {
36
+ if (!installationId) throw new Error('No installation resolved for the config undeploy');
37
+ for (const snapshot of target.configs){
38
+ await deleteConfig(installationId, snapshot.id);
39
+ }
40
+ return;
41
+ }
42
+ await deleteApplication(target.id);
43
+ }
44
+ };
45
+ }
46
+ async function resolveApplicationTarget({ appId, type, workbench }) {
47
+ if (!appId) {
48
+ return {
49
+ message: 'No `deployment.appId` configured',
50
+ solution: 'Add `deployment.appId` to sanity.cli.ts',
51
+ type: 'none'
52
+ };
53
+ }
54
+ const application = await getApplication(appId);
55
+ if (!application) {
56
+ return {
57
+ message: 'Application with the given ID does not exist',
58
+ type: 'none'
59
+ };
60
+ }
61
+ const { exposes, lines } = summarizeExposes(workbench);
62
+ return {
63
+ target: {
64
+ activeDeployment: null,
65
+ appHost: application.slug,
66
+ createdAt: null,
67
+ deletes: 'application',
68
+ id: application.id,
69
+ interfaces: exposes,
70
+ organizationId: application.organizationId,
71
+ projectId: null,
72
+ summary: [
73
+ ...lines,
74
+ ...workbench.isSingleton === undefined ? [] : [
75
+ `Singleton: ${workbench.isSingleton}`
76
+ ]
77
+ ],
78
+ title: application.title,
79
+ type,
80
+ url: getApplicationUrl({
81
+ ...application,
82
+ type
83
+ })
84
+ },
85
+ type: 'found'
86
+ };
87
+ }
88
+ async function resolveConfigTarget({ organizationId, workbench }) {
89
+ const config = workbench.config;
90
+ const appType = config?.appType ?? workbench.applicationType;
91
+ if (!appType) throw new Error('The app declares no app type to resolve its installation');
92
+ if (!organizationId) {
93
+ throw new Error('sanity.cli.ts does not contain an organization identifier ("app.organizationId"), which is required to resolve the installation');
94
+ }
95
+ const installationId = await resolveInstallationId({
96
+ appType,
97
+ organizationId
98
+ });
99
+ if (!installationId) {
100
+ return {
101
+ resolution: {
102
+ message: `No active "${appType}" installation for organization "${organizationId}"`,
103
+ type: 'none'
104
+ }
105
+ };
106
+ }
107
+ const configs = await listConfigs(installationId);
108
+ if (configs.length === 0) {
109
+ return {
110
+ installationId,
111
+ resolution: {
112
+ message: `No deployed config for the "${appType}" installation`,
113
+ type: 'none'
114
+ }
115
+ };
116
+ }
117
+ // At most one snapshot is active (served); the rest are deactivated history.
118
+ const active = configs.find((snapshot)=>snapshot.isActive);
119
+ return {
120
+ installationId,
121
+ resolution: {
122
+ target: {
123
+ activeDeployment: active ? {
124
+ deployedAt: active.createdAt ?? '',
125
+ deployedBy: active.deployedBy ?? ''
126
+ } : null,
127
+ appHost: null,
128
+ configs: configs.map((snapshot)=>({
129
+ createdAt: snapshot.createdAt ?? null,
130
+ deployedBy: snapshot.deployedBy ?? null,
131
+ id: snapshot.id
132
+ })),
133
+ createdAt: configs.at(-1)?.createdAt ?? null,
134
+ deletes: 'config',
135
+ id: null,
136
+ organizationId,
137
+ projectId: null,
138
+ summary: config ? [
139
+ summarizeConfig(config)
140
+ ] : undefined,
141
+ title: workbench.name,
142
+ type: 'coreApp',
143
+ url: getWorkbenchUrl(organizationId)
144
+ },
145
+ type: 'found'
146
+ }
147
+ };
148
+ }
149
+
150
+ //# sourceMappingURL=workbenchUndeployAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/undeploy/workbenchUndeployAdapter.ts"],"sourcesContent":["import {\n type UndeployAdapter,\n type UndeployApplicationTarget,\n type UndeployConfigTarget,\n type UndeployTargetResolution,\n} from '@sanity/cli-core/undeploy'\n\nimport {\n deleteApplication,\n getApplication,\n getApplicationUrl,\n getWorkbenchUrl,\n} from '../../services/applications.js'\nimport {deleteConfig, listConfigs} from '../../services/installations.js'\nimport {type DeployedExpose, summarizeExposes} from '../deploy/buildExposes.js'\nimport {resolveInstallationId, summarizeConfig} from '../deploy/deployConfig.js'\nimport {type DeployableWorkbenchApp} from '../deploy/getWorkbench.js'\n\n/** The workbench extension of the shared target; serializes into `--json` as-is. */\nexport type WorkbenchUndeployTarget =\n | (UndeployApplicationTarget & {\n /** Interfaces (views and services) registered by the application. */\n interfaces: DeployedExpose[]\n })\n | (UndeployConfigTarget & {\n /** The deployed config snapshots an undeploy deletes. */\n configs: {\n createdAt: string | null\n deployedBy: string | null\n id: string\n }[]\n })\n\n/**\n * The undeploy adapter for workbench apps, mirroring what a workbench deploy\n * creates: apps that expose interfaces delete their Brett application (the\n * server soft-deletes its deployments and refuses singletons with active\n * installations); a singleton without interfaces — the media library — deletes\n * its installation's config snapshots instead.\n */\nexport function createWorkbenchUndeployAdapter(options: {\n appId: string | undefined\n organizationId: string | undefined\n type: 'coreApp' | 'studio'\n workbench: DeployableWorkbenchApp\n}): UndeployAdapter<WorkbenchUndeployTarget> {\n const {appId, organizationId, type, workbench} = options\n // Keyed on singleton-ness, not on a locally declared config, so an undeploy\n // still reaches the server's config snapshots after the fields are removed\n // from sanity.cli.ts.\n const configOnly = !!workbench.isSingleton && !workbench.hasInterfaces\n // Workbench-internal, so kept off the reported target; resolveTarget stashes it for the delete.\n let installationId: string | undefined\n\n return {\n resolveTarget: async () => {\n if (!configOnly) return resolveApplicationTarget({appId, type, workbench})\n const resolved = await resolveConfigTarget({organizationId, workbench})\n installationId = resolved.installationId\n return resolved.resolution\n },\n type,\n async undeploy(target) {\n if (target.deletes === 'config') {\n if (!installationId) throw new Error('No installation resolved for the config undeploy')\n for (const snapshot of target.configs) {\n await deleteConfig(installationId, snapshot.id)\n }\n return\n }\n await deleteApplication(target.id)\n },\n }\n}\n\nasync function resolveApplicationTarget({\n appId,\n type,\n workbench,\n}: {\n appId: string | undefined\n type: 'coreApp' | 'studio'\n workbench: DeployableWorkbenchApp\n}): Promise<UndeployTargetResolution<WorkbenchUndeployTarget>> {\n if (!appId) {\n return {\n message: 'No `deployment.appId` configured',\n solution: 'Add `deployment.appId` to sanity.cli.ts',\n type: 'none',\n }\n }\n\n const application = await getApplication(appId)\n if (!application) {\n return {message: 'Application with the given ID does not exist', type: 'none'}\n }\n\n const {exposes, lines} = summarizeExposes(workbench)\n return {\n target: {\n activeDeployment: null,\n appHost: application.slug,\n createdAt: null,\n deletes: 'application',\n id: application.id,\n interfaces: exposes,\n organizationId: application.organizationId,\n projectId: null,\n summary: [\n ...lines,\n ...(workbench.isSingleton === undefined ? [] : [`Singleton: ${workbench.isSingleton}`]),\n ],\n title: application.title,\n type,\n url: getApplicationUrl({...application, type}),\n },\n type: 'found',\n }\n}\n\nasync function resolveConfigTarget({\n organizationId,\n workbench,\n}: {\n organizationId: string | undefined\n workbench: DeployableWorkbenchApp\n}): Promise<{\n installationId?: string\n resolution: UndeployTargetResolution<WorkbenchUndeployTarget>\n}> {\n const config = workbench.config\n const appType = config?.appType ?? workbench.applicationType\n if (!appType) throw new Error('The app declares no app type to resolve its installation')\n if (!organizationId) {\n throw new Error(\n 'sanity.cli.ts does not contain an organization identifier (\"app.organizationId\"), which is required to resolve the installation',\n )\n }\n\n const installationId = await resolveInstallationId({appType, organizationId})\n if (!installationId) {\n return {\n resolution: {\n message: `No active \"${appType}\" installation for organization \"${organizationId}\"`,\n type: 'none',\n },\n }\n }\n\n const configs = await listConfigs(installationId)\n if (configs.length === 0) {\n return {\n installationId,\n resolution: {\n message: `No deployed config for the \"${appType}\" installation`,\n type: 'none',\n },\n }\n }\n\n // At most one snapshot is active (served); the rest are deactivated history.\n const active = configs.find((snapshot) => snapshot.isActive)\n return {\n installationId,\n resolution: {\n target: {\n activeDeployment: active\n ? {deployedAt: active.createdAt ?? '', deployedBy: active.deployedBy ?? ''}\n : null,\n appHost: null,\n configs: configs.map((snapshot) => ({\n createdAt: snapshot.createdAt ?? null,\n deployedBy: snapshot.deployedBy ?? null,\n id: snapshot.id,\n })),\n createdAt: configs.at(-1)?.createdAt ?? null,\n deletes: 'config',\n id: null,\n organizationId,\n projectId: null,\n summary: config ? [summarizeConfig(config)] : undefined,\n title: workbench.name,\n type: 'coreApp',\n url: getWorkbenchUrl(organizationId),\n },\n type: 'found',\n },\n }\n}\n"],"names":["deleteApplication","getApplication","getApplicationUrl","getWorkbenchUrl","deleteConfig","listConfigs","summarizeExposes","resolveInstallationId","summarizeConfig","createWorkbenchUndeployAdapter","options","appId","organizationId","type","workbench","configOnly","isSingleton","hasInterfaces","installationId","resolveTarget","resolveApplicationTarget","resolved","resolveConfigTarget","resolution","undeploy","target","deletes","Error","snapshot","configs","id","message","solution","application","exposes","lines","activeDeployment","appHost","slug","createdAt","interfaces","projectId","summary","undefined","title","url","config","appType","applicationType","length","active","find","isActive","deployedAt","deployedBy","map","at","name"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/defineView.ts"],"sourcesContent":["import {\n type InterfaceType,\n VIEW_CONTRACT_VERSION,\n type ViewComponent,\n type ViewComponentBaseProps,\n} from './contract.js'\n\n/**\n * Props a panel component receives: its interface record, minus the\n * service-assigned `id`/`deployment_id` a local dev server can't provide. Mirrors\n * the `panel` record the workbench host renders from (the wire format owned by\n * `@sanity/workbench`); drift is guarded by the stamped contract version.\n * @public\n */\nexport type PanelViewProps = ViewComponentBaseProps<{\n entry_point: string\n interface_type: 'panel'\n name: string\n}>\n\n/**\n * The component slots a `panel` view exposes — each its own module-federation\n * island, typed with the panel props.\n * @public\n */\nexport interface PanelViewComponents {\n panel: ViewComponent<PanelViewProps>\n title: ViewComponent<PanelViewProps>\n}\n\n/**\n * A panel's view-component slot — the module-federation expose for one island.\n * @public\n */\nexport type PanelComponent = keyof PanelViewComponents\n\n/**\n * The components each interface type exposes, keyed by type.\n * @public\n */\nexport interface ViewComponentsByType {\n panel: PanelViewComponents\n}\n\n/**\n * The result of `unstable_defineView`: the author's component(s), the view type,\n * and the internal contract version the build artifact targets.\n * @public\n */\nexport interface DefinedView<TType extends InterfaceType = InterfaceType> {\n readonly components: ViewComponentsByType[TType]\n readonly type: TType\n /** @internal */\n readonly version: typeof VIEW_CONTRACT_VERSION\n}\n\n/**\n * Define a Sanity Workbench view. The first argument narrows the component shape\n * and the props each component receives — `\"panel\"` yields a `{title, panel}`\n * record whose components are typed with the panel props.\n *\n * Returns the component(s) tagged with their type and the contract version, for\n * the CLI build to generate render artifacts from. Used as the default export of\n * a view's `src` file.\n * @public\n */\nexport function unstable_defineView<TType extends InterfaceType>(\n type: TType,\n components: ViewComponentsByType[TType],\n): DefinedView<TType> {\n return {components, type, version: VIEW_CONTRACT_VERSION}\n}\n"],"names":["VIEW_CONTRACT_VERSION","unstable_defineView","type","components","version"],"mappings":"AAAA,SAEEA,qBAAqB,QAGhB,gBAAe;AAmDtB;;;;;;;;;CASC,GACD,OAAO,SAASC,oBACdC,IAAW,EACXC,UAAuC;IAEvC,OAAO;QAACA;QAAYD;QAAME,SAASJ;IAAqB;AAC1D"}
1
+ {"version":3,"sources":["../src/defineView.ts"],"sourcesContent":["import {\n type InterfaceType,\n VIEW_CONTRACT_VERSION,\n type ViewComponent,\n type ViewComponentBaseProps,\n} from './contract.js'\n\n/**\n * Props a panel component receives: its interface record, minus the\n * service-assigned `id`/`deployment_id` a local dev server can't provide. Mirrors\n * the `panel` record the workbench host renders from (the wire format owned by\n * `@sanity/workbench`); drift is guarded by the stamped contract version.\n * @public\n */\nexport type PanelViewProps = ViewComponentBaseProps<{\n name: string\n src: string\n title: string\n type: 'panel'\n}>\n\n/**\n * The component slots a `panel` view exposes — each its own module-federation\n * island, typed with the panel props.\n * @public\n */\nexport interface PanelViewComponents {\n panel: ViewComponent<PanelViewProps>\n title: ViewComponent<PanelViewProps>\n}\n\n/**\n * A panel's view-component slot — the module-federation expose for one island.\n * @public\n */\nexport type PanelComponent = keyof PanelViewComponents\n\n/**\n * The components each interface type exposes, keyed by type.\n * @public\n */\nexport interface ViewComponentsByType {\n panel: PanelViewComponents\n}\n\n/**\n * The result of `unstable_defineView`: the author's component(s), the view type,\n * and the internal contract version the build artifact targets.\n * @public\n */\nexport interface DefinedView<TType extends InterfaceType = InterfaceType> {\n readonly components: ViewComponentsByType[TType]\n readonly type: TType\n /** @internal */\n readonly version: typeof VIEW_CONTRACT_VERSION\n}\n\n/**\n * Define a Sanity Workbench view. The first argument narrows the component shape\n * and the props each component receives — `\"panel\"` yields a `{title, panel}`\n * record whose components are typed with the panel props.\n *\n * Returns the component(s) tagged with their type and the contract version, for\n * the CLI build to generate render artifacts from. Used as the default export of\n * a view's `src` file.\n * @public\n */\nexport function unstable_defineView<TType extends InterfaceType>(\n type: TType,\n components: ViewComponentsByType[TType],\n): DefinedView<TType> {\n return {components, type, version: VIEW_CONTRACT_VERSION}\n}\n"],"names":["VIEW_CONTRACT_VERSION","unstable_defineView","type","components","version"],"mappings":"AAAA,SAEEA,qBAAqB,QAGhB,gBAAe;AAoDtB;;;;;;;;;CASC,GACD,OAAO,SAASC,oBACdC,IAAW,EACXC,UAAuC;IAEvC,OAAO;QAACA;QAAYD;QAAME,SAASJ;IAAqB;AAC1D"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/services/apiVersion.ts"],"sourcesContent":["// The app endpoints (applications + installations) live behind the\n// experimental `vX` version; a dated version returns 501.\nexport const APP_WORKBENCH_API_VERSION = 'vX'\n"],"names":["APP_WORKBENCH_API_VERSION"],"mappings":"AAAA,mEAAmE;AACnE,0DAA0D;AAC1D,OAAO,MAAMA,4BAA4B,KAAI"}
@@ -0,0 +1,100 @@
1
+ import { PassThrough } from 'node:stream';
2
+ import { getGlobalCliClient } from '@sanity/cli-core';
3
+ import { isStaging } from '@sanity/cli-core/util';
4
+ import FormData from 'form-data';
5
+ import { APP_WORKBENCH_API_VERSION } from './apiVersion.js';
6
+ export function getWorkbenchUrl(organizationId) {
7
+ return `https://${organizationId}.${isStaging() ? 'run.sanity.work' : 'sanity.run'}`;
8
+ }
9
+ /** Where a deployed application is served on its organization's workbench. */ export function getApplicationUrl(application) {
10
+ const segment = application.type === 'studio' ? 'studio' : 'application';
11
+ return `${getWorkbenchUrl(application.organizationId)}/${segment}/${application.id}`;
12
+ }
13
+ async function getClient() {
14
+ return getGlobalCliClient({
15
+ apiVersion: APP_WORKBENCH_API_VERSION,
16
+ requireUser: true
17
+ });
18
+ }
19
+ export async function getApplication(applicationId) {
20
+ const client = await getClient();
21
+ try {
22
+ return await client.request({
23
+ uri: `/applications/${applicationId}`
24
+ });
25
+ } catch (err) {
26
+ if (err?.statusCode === 404) return null;
27
+ throw err;
28
+ }
29
+ }
30
+ /** Create an application and its first deployment in one call. */ export async function createApplication(options) {
31
+ const { interfaces, isSingleton, organizationId, projectId, slug, tarball, title, type, version, workspaces } = options;
32
+ const formData = new FormData();
33
+ formData.append('type', type);
34
+ formData.append('title', title);
35
+ formData.append('organizationId', organizationId);
36
+ formData.append('slug', slug);
37
+ if (isSingleton !== undefined) formData.append('isSingleton', String(isSingleton));
38
+ // Studio config is set once, at create — it's immutable on redeploy.
39
+ if (projectId) appendJson(formData, 'config', {
40
+ studio: {
41
+ projectId
42
+ }
43
+ });
44
+ appendDeploymentParts(formData, {
45
+ interfaces,
46
+ tarball,
47
+ version,
48
+ workspaces
49
+ });
50
+ return request(`/applications`, formData);
51
+ }
52
+ /** Deploy a new active version to an existing application. */ export async function createDeployment(options) {
53
+ const { applicationId, interfaces, isAutoUpdating, tarball, version, workspaces } = options;
54
+ const formData = new FormData();
55
+ formData.append('isAutoUpdating', isAutoUpdating.toString());
56
+ appendDeploymentParts(formData, {
57
+ interfaces,
58
+ tarball,
59
+ version,
60
+ workspaces
61
+ });
62
+ return request(`/applications/${applicationId}/deployments`, formData);
63
+ }
64
+ /** Soft-deletes the application and all its deployments; already deleted counts as done. */ export async function deleteApplication(applicationId) {
65
+ const client = await getClient();
66
+ try {
67
+ await client.request({
68
+ method: 'DELETE',
69
+ uri: `/applications/${applicationId}`
70
+ });
71
+ } catch (err) {
72
+ if (err?.statusCode !== 404) throw err;
73
+ }
74
+ }
75
+ function appendDeploymentParts(formData, { interfaces, tarball, version, workspaces }) {
76
+ formData.append('version', version);
77
+ appendJson(formData, 'interfaces', interfaces);
78
+ // Studio-only — the server rejects a workspaces part on non-studio types.
79
+ if (workspaces?.length) appendJson(formData, 'workspaces', workspaces);
80
+ formData.append('tarball', tarball, {
81
+ contentType: 'application/gzip',
82
+ filename: 'app.tar.gz'
83
+ });
84
+ }
85
+ /** Structured parts must arrive as JSON so the server parses them. */ function appendJson(formData, name, value) {
86
+ formData.append(name, JSON.stringify(value), {
87
+ contentType: 'application/json'
88
+ });
89
+ }
90
+ async function request(uri, formData) {
91
+ const client = await getClient();
92
+ return client.request({
93
+ body: formData.pipe(new PassThrough()),
94
+ headers: formData.getHeaders(),
95
+ method: 'POST',
96
+ uri
97
+ });
98
+ }
99
+
100
+ //# sourceMappingURL=applications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/services/applications.ts"],"sourcesContent":["import {PassThrough} from 'node:stream'\nimport {type Gzip} from 'node:zlib'\n\nimport {getGlobalCliClient} from '@sanity/cli-core'\nimport {isStaging} from '@sanity/cli-core/util'\nimport FormData from 'form-data'\n\nimport {APP_WORKBENCH_API_VERSION} from './apiVersion.js'\n\nexport type ApplicationType = 'coreApp' | 'studio'\n\nexport interface Application {\n id: string\n organizationId: string\n slug: string | null\n title: string\n type: ApplicationType\n}\n\n/**\n * An interface as Brett stores it: the declared `type` (validated server-side,\n * not here) and the remote-relative `moduleId` the workbench loads it by — the\n * host prepends the app's own id.\n * @internal\n */\nexport interface BrettInterface {\n moduleId: string\n name: string\n title: string\n type: string\n version: string\n}\n\n/** A studio workspace as Brett stores it. */\nexport interface BrettWorkspace {\n dataset: string\n projectId: string\n\n basePath?: string\n icon?: string\n name?: string\n subtitle?: string\n title?: string\n}\n\nexport function getWorkbenchUrl(organizationId: string): string {\n return `https://${organizationId}.${isStaging() ? 'run.sanity.work' : 'sanity.run'}`\n}\n\n/** Where a deployed application is served on its organization's workbench. */\nexport function getApplicationUrl(\n application: Pick<Application, 'id' | 'organizationId' | 'type'>,\n): string {\n const segment = application.type === 'studio' ? 'studio' : 'application'\n return `${getWorkbenchUrl(application.organizationId)}/${segment}/${application.id}`\n}\n\nasync function getClient() {\n return getGlobalCliClient({apiVersion: APP_WORKBENCH_API_VERSION, requireUser: true})\n}\n\nexport async function getApplication(applicationId: string): Promise<Application | null> {\n const client = await getClient()\n try {\n return await client.request({uri: `/applications/${applicationId}`})\n } catch (err) {\n if ((err as {statusCode?: number})?.statusCode === 404) return null\n throw err\n }\n}\n\n/** Create an application and its first deployment in one call. */\nexport async function createApplication(options: {\n interfaces: readonly BrettInterface[]\n isSingleton?: boolean\n organizationId: string\n projectId?: string\n slug: string\n tarball: Gzip\n title: string\n type: ApplicationType\n version: string\n workspaces?: readonly BrettWorkspace[]\n}): Promise<Application> {\n const {\n interfaces,\n isSingleton,\n organizationId,\n projectId,\n slug,\n tarball,\n title,\n type,\n version,\n workspaces,\n } = options\n const formData = new FormData()\n formData.append('type', type)\n formData.append('title', title)\n formData.append('organizationId', organizationId)\n formData.append('slug', slug)\n if (isSingleton !== undefined) formData.append('isSingleton', String(isSingleton))\n // Studio config is set once, at create — it's immutable on redeploy.\n if (projectId) appendJson(formData, 'config', {studio: {projectId}})\n appendDeploymentParts(formData, {interfaces, tarball, version, workspaces})\n return request(`/applications`, formData)\n}\n\n/** Deploy a new active version to an existing application. */\nexport async function createDeployment(options: {\n applicationId: string\n interfaces: readonly BrettInterface[]\n isAutoUpdating: boolean\n tarball: Gzip\n version: string\n workspaces?: readonly BrettWorkspace[]\n}): Promise<{id: string}> {\n const {applicationId, interfaces, isAutoUpdating, tarball, version, workspaces} = options\n const formData = new FormData()\n formData.append('isAutoUpdating', isAutoUpdating.toString())\n appendDeploymentParts(formData, {interfaces, tarball, version, workspaces})\n return request(`/applications/${applicationId}/deployments`, formData)\n}\n\n/** Soft-deletes the application and all its deployments; already deleted counts as done. */\nexport async function deleteApplication(applicationId: string): Promise<void> {\n const client = await getClient()\n try {\n await client.request({method: 'DELETE', uri: `/applications/${applicationId}`})\n } catch (err) {\n if ((err as {statusCode?: number})?.statusCode !== 404) throw err\n }\n}\n\nfunction appendDeploymentParts(\n formData: FormData,\n {\n interfaces,\n tarball,\n version,\n workspaces,\n }: {\n interfaces: readonly BrettInterface[]\n tarball: Gzip\n version: string\n workspaces?: readonly BrettWorkspace[]\n },\n): void {\n formData.append('version', version)\n appendJson(formData, 'interfaces', interfaces)\n // Studio-only — the server rejects a workspaces part on non-studio types.\n if (workspaces?.length) appendJson(formData, 'workspaces', workspaces)\n formData.append('tarball', tarball, {contentType: 'application/gzip', filename: 'app.tar.gz'})\n}\n\n/** Structured parts must arrive as JSON so the server parses them. */\nfunction appendJson(formData: FormData, name: string, value: unknown): void {\n formData.append(name, JSON.stringify(value), {contentType: 'application/json'})\n}\n\nasync function request<T>(uri: string, formData: FormData): Promise<T> {\n const client = await getClient()\n return client.request({\n body: formData.pipe(new PassThrough()),\n headers: formData.getHeaders(),\n method: 'POST',\n uri,\n })\n}\n"],"names":["PassThrough","getGlobalCliClient","isStaging","FormData","APP_WORKBENCH_API_VERSION","getWorkbenchUrl","organizationId","getApplicationUrl","application","segment","type","id","getClient","apiVersion","requireUser","getApplication","applicationId","client","request","uri","err","statusCode","createApplication","options","interfaces","isSingleton","projectId","slug","tarball","title","version","workspaces","formData","append","undefined","String","appendJson","studio","appendDeploymentParts","createDeployment","isAutoUpdating","toString","deleteApplication","method","length","contentType","filename","name","value","JSON","stringify","body","pipe","headers","getHeaders"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { PassThrough } from 'node:stream';
2
+ import { getGlobalCliClient } from '@sanity/cli-core';
3
+ import FormData from 'form-data';
4
+ import { APP_WORKBENCH_API_VERSION } from './apiVersion.js';
5
+ async function getClient() {
6
+ return getGlobalCliClient({
7
+ apiVersion: APP_WORKBENCH_API_VERSION,
8
+ requireUser: true
9
+ });
10
+ }
11
+ /** The org's active singleton installation, matched on its slug. */ export async function resolveSingletonInstallationId(organizationId, slug) {
12
+ const client = await getClient();
13
+ // `limit=none` returns every installation in one response, no pagination.
14
+ const { data } = await client.request({
15
+ query: {
16
+ limit: 'none',
17
+ organizationId
18
+ },
19
+ uri: '/installations'
20
+ });
21
+ return data.find((item)=>item.application?.slug === slug)?.id;
22
+ }
23
+ /** Upload a config snapshot to the installation as a multipart tarball. */ export async function createConfig(installationId, { tarball, version }) {
24
+ const formData = new FormData();
25
+ formData.append('version', version);
26
+ formData.append('tarball', tarball, {
27
+ contentType: 'application/gzip',
28
+ filename: 'installation-config.tar.gz'
29
+ });
30
+ const client = await getClient();
31
+ await client.request({
32
+ body: formData.pipe(new PassThrough()),
33
+ headers: formData.getHeaders(),
34
+ method: 'POST',
35
+ uri: `/installations/${installationId}/configs`
36
+ });
37
+ }
38
+ /** The installation's deployed config snapshots, newest first. */ export async function listConfigs(installationId) {
39
+ const client = await getClient();
40
+ const { data } = await client.request({
41
+ query: {
42
+ limit: 'none'
43
+ },
44
+ uri: `/installations/${installationId}/configs`
45
+ });
46
+ return data;
47
+ }
48
+ /**
49
+ * Soft-deletes one config snapshot; its content is purged once superseded.
50
+ * Already deleted counts as done, so a partially-failed undeploy can re-run.
51
+ */ export async function deleteConfig(installationId, configId) {
52
+ const client = await getClient();
53
+ try {
54
+ await client.request({
55
+ method: 'DELETE',
56
+ uri: `/installations/${installationId}/configs/${configId}`
57
+ });
58
+ } catch (err) {
59
+ if (err?.statusCode !== 404) throw err;
60
+ }
61
+ }
62
+
63
+ //# sourceMappingURL=installations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/services/installations.ts"],"sourcesContent":["import {PassThrough} from 'node:stream'\nimport {type Gzip} from 'node:zlib'\n\nimport {getGlobalCliClient} from '@sanity/cli-core'\nimport FormData from 'form-data'\n\nimport {APP_WORKBENCH_API_VERSION} from './apiVersion.js'\n\nexport interface ConfigSnapshot {\n id: string\n\n createdAt?: string\n deployedBy?: string\n /** Whether this snapshot is the one being served; at most one per installation. */\n isActive?: boolean\n}\n\ninterface InstallationListItem {\n id: string\n\n application?: {slug?: string}\n}\n\nasync function getClient() {\n return getGlobalCliClient({apiVersion: APP_WORKBENCH_API_VERSION, requireUser: true})\n}\n\n/** The org's active singleton installation, matched on its slug. */\nexport async function resolveSingletonInstallationId(\n organizationId: string,\n slug: string,\n): Promise<string | undefined> {\n const client = await getClient()\n // `limit=none` returns every installation in one response, no pagination.\n const {data}: {data: InstallationListItem[]} = await client.request({\n query: {limit: 'none', organizationId},\n uri: '/installations',\n })\n return data.find((item) => item.application?.slug === slug)?.id\n}\n\n/** Upload a config snapshot to the installation as a multipart tarball. */\nexport async function createConfig(\n installationId: string,\n {tarball, version}: {tarball: Gzip; version: string},\n): Promise<void> {\n const formData = new FormData()\n formData.append('version', version)\n formData.append('tarball', tarball, {\n contentType: 'application/gzip',\n filename: 'installation-config.tar.gz',\n })\n\n const client = await getClient()\n await client.request({\n body: formData.pipe(new PassThrough()),\n headers: formData.getHeaders(),\n method: 'POST',\n uri: `/installations/${installationId}/configs`,\n })\n}\n\n/** The installation's deployed config snapshots, newest first. */\nexport async function listConfigs(installationId: string): Promise<ConfigSnapshot[]> {\n const client = await getClient()\n const {data}: {data: ConfigSnapshot[]} = await client.request({\n query: {limit: 'none'},\n uri: `/installations/${installationId}/configs`,\n })\n return data\n}\n\n/**\n * Soft-deletes one config snapshot; its content is purged once superseded.\n * Already deleted counts as done, so a partially-failed undeploy can re-run.\n */\nexport async function deleteConfig(installationId: string, configId: string): Promise<void> {\n const client = await getClient()\n try {\n await client.request({\n method: 'DELETE',\n uri: `/installations/${installationId}/configs/${configId}`,\n })\n } catch (err) {\n if ((err as {statusCode?: number})?.statusCode !== 404) throw err\n }\n}\n"],"names":["PassThrough","getGlobalCliClient","FormData","APP_WORKBENCH_API_VERSION","getClient","apiVersion","requireUser","resolveSingletonInstallationId","organizationId","slug","client","data","request","query","limit","uri","find","item","application","id","createConfig","installationId","tarball","version","formData","append","contentType","filename","body","pipe","headers","getHeaders","method","listConfigs","deleteConfig","configId","err","statusCode"],"mappings":"AAAA,SAAQA,WAAW,QAAO,cAAa;AAGvC,SAAQC,kBAAkB,QAAO,mBAAkB;AACnD,OAAOC,cAAc,YAAW;AAEhC,SAAQC,yBAAyB,QAAO,kBAAiB;AAiBzD,eAAeC;IACb,OAAOH,mBAAmB;QAACI,YAAYF;QAA2BG,aAAa;IAAI;AACrF;AAEA,kEAAkE,GAClE,OAAO,eAAeC,+BACpBC,cAAsB,EACtBC,IAAY;IAEZ,MAAMC,SAAS,MAAMN;IACrB,0EAA0E;IAC1E,MAAM,EAACO,IAAI,EAAC,GAAmC,MAAMD,OAAOE,OAAO,CAAC;QAClEC,OAAO;YAACC,OAAO;YAAQN;QAAc;QACrCO,KAAK;IACP;IACA,OAAOJ,KAAKK,IAAI,CAAC,CAACC,OAASA,KAAKC,WAAW,EAAET,SAASA,OAAOU;AAC/D;AAEA,yEAAyE,GACzE,OAAO,eAAeC,aACpBC,cAAsB,EACtB,EAACC,OAAO,EAAEC,OAAO,EAAmC;IAEpD,MAAMC,WAAW,IAAItB;IACrBsB,SAASC,MAAM,CAAC,WAAWF;IAC3BC,SAASC,MAAM,CAAC,WAAWH,SAAS;QAClCI,aAAa;QACbC,UAAU;IACZ;IAEA,MAAMjB,SAAS,MAAMN;IACrB,MAAMM,OAAOE,OAAO,CAAC;QACnBgB,MAAMJ,SAASK,IAAI,CAAC,IAAI7B;QACxB8B,SAASN,SAASO,UAAU;QAC5BC,QAAQ;QACRjB,KAAK,CAAC,eAAe,EAAEM,eAAe,QAAQ,CAAC;IACjD;AACF;AAEA,gEAAgE,GAChE,OAAO,eAAeY,YAAYZ,cAAsB;IACtD,MAAMX,SAAS,MAAMN;IACrB,MAAM,EAACO,IAAI,EAAC,GAA6B,MAAMD,OAAOE,OAAO,CAAC;QAC5DC,OAAO;YAACC,OAAO;QAAM;QACrBC,KAAK,CAAC,eAAe,EAAEM,eAAe,QAAQ,CAAC;IACjD;IACA,OAAOV;AACT;AAEA;;;CAGC,GACD,OAAO,eAAeuB,aAAab,cAAsB,EAAEc,QAAgB;IACzE,MAAMzB,SAAS,MAAMN;IACrB,IAAI;QACF,MAAMM,OAAOE,OAAO,CAAC;YACnBoB,QAAQ;YACRjB,KAAK,CAAC,eAAe,EAAEM,eAAe,SAAS,EAAEc,UAAU;QAC7D;IACF,EAAE,OAAOC,KAAK;QACZ,IAAI,AAACA,KAA+BC,eAAe,KAAK,MAAMD;IAChE;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/workbench-cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Internal implementation detail of the Sanity CLI's unstable workbench support. Not intended for direct use.",
5
5
  "homepage": "https://github.com/sanity-io/cli",
6
6
  "bugs": "https://github.com/sanity-io/cli/issues",
@@ -39,6 +39,10 @@
39
39
  "source": "./src/_exports/init.ts",
40
40
  "default": "./dist/_exports/init.js"
41
41
  },
42
+ "./undeploy": {
43
+ "source": "./src/_exports/undeploy.ts",
44
+ "default": "./dist/_exports/undeploy.js"
45
+ },
42
46
  "./package.json": "./package.json"
43
47
  },
44
48
  "publishConfig": {
@@ -51,7 +55,7 @@
51
55
  "tar-fs": "^3.1.2",
52
56
  "vite": "^8.1.3",
53
57
  "zod": "^4.4.3",
54
- "@sanity/cli-core": "^2.3.0"
58
+ "@sanity/cli-core": "^2.4.0"
55
59
  },
56
60
  "devDependencies": {
57
61
  "@eslint/compat": "^2.1.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/actions/deploy/apiVersion.ts"],"sourcesContent":["// The app endpoints (applications + installations) live behind the\n// experimental `vX` version; a dated version returns 501.\nexport const APP_WORKBENCH_API_VERSION = 'vX'\n"],"names":["APP_WORKBENCH_API_VERSION"],"mappings":"AAAA,mEAAmE;AACnE,0DAA0D;AAC1D,OAAO,MAAMA,4BAA4B,KAAI"}
File without changes