@sanity/cli 7.11.0 → 7.12.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.
@@ -1,5 +1,5 @@
1
1
  import { compareDependencyVersions, buildApp as internalBuildApp } from '@sanity/cli-build/_internal/build';
2
- import { resolveWorkbenchApp } from '@sanity/workbench-cli/build';
2
+ import { buildAppId, resolveWorkbenchApp } from '@sanity/workbench-cli/build';
3
3
  import { getAppId } from '../../util/appId.js';
4
4
  import { warnAboutMissingAppId } from '../../util/warnAboutMissingAppId.js';
5
5
  import { determineBasePath } from './determineBasePath.js';
@@ -13,6 +13,11 @@ import { determineBasePath } from './determineBasePath.js';
13
13
  // `views`/`services` live on the branded `unstable_defineApp` result, not the
14
14
  // legacy `app` config object — resolve the workbench capability to read them.
15
15
  const workbench = resolveWorkbenchApp(cliConfig);
16
+ const exposes = workbench ? {
17
+ config: workbench.config,
18
+ services: workbench.services,
19
+ views: workbench.views
20
+ } : undefined;
16
21
  const appId = getAppId(cliConfig);
17
22
  await internalBuildApp({
18
23
  appId,
@@ -34,11 +39,7 @@ import { determineBasePath } from './determineBasePath.js';
34
39
  }),
35
40
  determineBasePath: ()=>determineBasePath(cliConfig, 'app', output),
36
41
  entry: app?.entry,
37
- exposes: workbench ? {
38
- config: workbench.config,
39
- services: workbench.services,
40
- views: workbench.views
41
- } : undefined,
42
+ exposes,
42
43
  isWorkbenchApp: !!workbench,
43
44
  minify: flags.minify,
44
45
  outDir,
@@ -49,7 +50,9 @@ import { determineBasePath } from './determineBasePath.js';
49
50
  stats: flags.stats,
50
51
  unattendedMode: flags.yes,
51
52
  vite: cliConfig.vite,
52
- workbenchAppId: workbench?.name,
53
+ // Shared with deploy: it passes the resolved application id (minted by the
54
+ // API on a first deploy) to inline; a plain build has none, so it hashes the shape.
55
+ workbenchAppId: workbench ? options.applicationId ?? buildAppId(workbench) : undefined,
53
56
  workDir
54
57
  });
55
58
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildApp as internalBuildApp,\n} from '@sanity/cli-build/_internal/build'\nimport {resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity app.\n *\n * @internal\n */\nexport async function buildApp(options: BuildOptions): Promise<void> {\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const app = cliConfig && 'app' in cliConfig ? cliConfig.app : undefined\n // `views`/`services` live on the branded `unstable_defineApp` result, not the\n // legacy `app` config object — resolve the workbench capability to read them.\n const workbench = resolveWorkbenchApp(cliConfig)\n\n const appId = getAppId(cliConfig)\n\n await internalBuildApp({\n appId,\n appTitle: app?.title,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'app', output})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'app', output),\n entry: app?.entry,\n exposes: workbench\n ? {\n config: workbench.config,\n services: workbench.services,\n views: workbench.views,\n }\n : undefined,\n isWorkbenchApp: !!workbench,\n minify: flags.minify,\n outDir,\n output,\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n schemaExtraction: cliConfig?.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: flags.yes,\n vite: cliConfig.vite,\n workbenchAppId: workbench?.name,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildApp","internalBuildApp","resolveWorkbenchApp","getAppId","warnAboutMissingAppId","determineBasePath","options","cliConfig","flags","outDir","output","workDir","app","undefined","workbench","appId","appTitle","title","autoUpdatesEnabled","checkAppId","calledFromDeploy","appType","packages","entry","exposes","config","services","views","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","Boolean","stats","unattendedMode","yes","vite","workbenchAppId","name"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,YAAYC,gBAAgB,QACvB,oCAAmC;AAC1C,SAAQC,mBAAmB,QAAO,8BAA6B;AAE/D,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeL,SAASM,OAAqB;IAClD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEpD,MAAMM,MAAML,aAAa,SAASA,YAAYA,UAAUK,GAAG,GAAGC;IAC9D,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMC,YAAYZ,oBAAoBK;IAEtC,MAAMQ,QAAQZ,SAASI;IAEvB,MAAMN,iBAAiB;QACrBc;QACAC,UAAUJ,KAAKK;QACfC,oBAAoBZ,QAAQY,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACT,QAAQc,gBAAgB,EAAE;gBACvChB,sBAAsB;oBAACiB,SAAS;oBAAOX;gBAAM;YAC/C;QACF;QACAX,2BAA2B,CAACuB,WAAavB,0BAA0BuB,UAAUX,SAAS;gBAACI;YAAK;QAC5FV,mBAAmB,IAAMA,kBAAkBE,WAAW,OAAOG;QAC7Da,OAAOX,KAAKW;QACZC,SAASV,YACL;YACEW,QAAQX,UAAUW,MAAM;YACxBC,UAAUZ,UAAUY,QAAQ;YAC5BC,OAAOb,UAAUa,KAAK;QACxB,IACAd;QACJe,gBAAgB,CAAC,CAACd;QAClBe,QAAQrB,MAAMqB,MAAM;QACpBpB;QACAC;QACAoB,eAAevB,aAAa,mBAAmBA,YAAYA,UAAUuB,aAAa,GAAGjB;QACrFkB,kBAAkBxB,WAAWwB;QAC7BC,WAAWC,QAAQzB,KAAK,CAAC,cAAc;QACvC0B,OAAO1B,MAAM0B,KAAK;QAClBC,gBAAgB3B,MAAM4B,GAAG;QACzBC,MAAM9B,UAAU8B,IAAI;QACpBC,gBAAgBxB,WAAWyB;QAC3B5B;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildApp as internalBuildApp,\n} from '@sanity/cli-build/_internal/build'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity app.\n *\n * @internal\n */\nexport async function buildApp(options: BuildOptions): Promise<void> {\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const app = cliConfig && 'app' in cliConfig ? cliConfig.app : undefined\n // `views`/`services` live on the branded `unstable_defineApp` result, not the\n // legacy `app` config object — resolve the workbench capability to read them.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench\n ? {config: workbench.config, services: workbench.services, views: workbench.views}\n : undefined\n\n const appId = getAppId(cliConfig)\n\n await internalBuildApp({\n appId,\n appTitle: app?.title,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'app', output})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'app', output),\n entry: app?.entry,\n exposes,\n isWorkbenchApp: !!workbench,\n minify: flags.minify,\n outDir,\n output,\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n schemaExtraction: cliConfig?.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: flags.yes,\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench ? (options.applicationId ?? buildAppId(workbench)) : undefined,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildApp","internalBuildApp","buildAppId","resolveWorkbenchApp","getAppId","warnAboutMissingAppId","determineBasePath","options","cliConfig","flags","outDir","output","workDir","app","undefined","workbench","exposes","config","services","views","appId","appTitle","title","autoUpdatesEnabled","checkAppId","calledFromDeploy","appType","packages","entry","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","Boolean","stats","unattendedMode","yes","vite","workbenchAppId","applicationId"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,YAAYC,gBAAgB,QACvB,oCAAmC;AAC1C,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeN,SAASO,OAAqB;IAClD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEpD,MAAMM,MAAML,aAAa,SAASA,YAAYA,UAAUK,GAAG,GAAGC;IAC9D,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMC,YAAYZ,oBAAoBK;IACtC,MAAMQ,UAAUD,YACZ;QAACE,QAAQF,UAAUE,MAAM;QAAEC,UAAUH,UAAUG,QAAQ;QAAEC,OAAOJ,UAAUI,KAAK;IAAA,IAC/EL;IAEJ,MAAMM,QAAQhB,SAASI;IAEvB,MAAMP,iBAAiB;QACrBmB;QACAC,UAAUR,KAAKS;QACfC,oBAAoBhB,QAAQgB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACb,QAAQkB,gBAAgB,EAAE;gBACvCpB,sBAAsB;oBAACqB,SAAS;oBAAOf;gBAAM;YAC/C;QACF;QACAZ,2BAA2B,CAAC4B,WAAa5B,0BAA0B4B,UAAUf,SAAS;gBAACQ;YAAK;QAC5Fd,mBAAmB,IAAMA,kBAAkBE,WAAW,OAAOG;QAC7DiB,OAAOf,KAAKe;QACZZ;QACAa,gBAAgB,CAAC,CAACd;QAClBe,QAAQrB,MAAMqB,MAAM;QACpBpB;QACAC;QACAoB,eAAevB,aAAa,mBAAmBA,YAAYA,UAAUuB,aAAa,GAAGjB;QACrFkB,kBAAkBxB,WAAWwB;QAC7BC,WAAWC,QAAQzB,KAAK,CAAC,cAAc;QACvC0B,OAAO1B,MAAM0B,KAAK;QAClBC,gBAAgB3B,MAAM4B,GAAG;QACzBC,MAAM9B,UAAU8B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgBxB,YAAaR,QAAQiC,aAAa,IAAItC,WAAWa,aAAcD;QAC/EF;IACF;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { compareDependencyVersions, buildStudio as internalBuildStudio } from '@sanity/cli-build/_internal/build';
2
- import { resolveWorkbenchApp } from '@sanity/workbench-cli/build';
2
+ import { buildAppId, resolveWorkbenchApp } from '@sanity/workbench-cli/build';
3
3
  import { getAppId } from '../../util/appId.js';
4
4
  import { determineIsApp } from '../../util/determineIsApp.js';
5
5
  import { getPackageManagerChoice } from '../../util/packageManager/packageManagerChoice.js';
@@ -15,6 +15,10 @@ import { determineBasePath } from './determineBasePath.js';
15
15
  // `views`/`services` live on the branded `unstable_defineApp` result — resolve
16
16
  // the workbench capability so it's gated on the brand, like the app build.
17
17
  const workbench = resolveWorkbenchApp(cliConfig);
18
+ const exposes = workbench ? {
19
+ services: workbench.services,
20
+ views: workbench.views
21
+ } : undefined;
18
22
  const appId = getAppId(cliConfig);
19
23
  const upgradePkgs = async (options)=>{
20
24
  await upgradePackages({
@@ -46,10 +50,7 @@ import { determineBasePath } from './determineBasePath.js';
46
50
  appId
47
51
  }),
48
52
  determineBasePath: ()=>determineBasePath(cliConfig, 'studio', output),
49
- exposes: workbench ? {
50
- services: workbench.services,
51
- views: workbench.views
52
- } : undefined,
53
+ exposes,
53
54
  isApp: determineIsApp(cliConfig),
54
55
  isWorkbenchApp: !!workbench,
55
56
  minify: Boolean(flags.minify),
@@ -62,7 +63,9 @@ import { determineBasePath } from './determineBasePath.js';
62
63
  unattendedMode: Boolean(flags.yes),
63
64
  upgradePackages: upgradePkgs,
64
65
  vite: cliConfig.vite,
65
- workbenchAppId: workbench?.name,
66
+ // Shared with deploy: it passes the resolved application id (minted by the
67
+ // API on a first deploy) to inline; a plain build has none, so it hashes the shape.
68
+ workbenchAppId: workbench ? options.applicationId ?? buildAppId(workbench) : undefined,
66
69
  workDir
67
70
  });
68
71
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildStudio as internalBuildStudio,\n} from '@sanity/cli-build/_internal/build'\nimport {resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {determineIsApp} from '../../util/determineIsApp.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const {calledFromDeploy, cliConfig, flags, outDir, output, workDir} = options\n\n // `views`/`services` live on the branded `unstable_defineApp` result — resolve\n // the workbench capability so it's gated on the brand, like the app build.\n const workbench = resolveWorkbenchApp(cliConfig)\n\n const appId = getAppId(cliConfig)\n\n const upgradePkgs = async (options: {\n packages: [name: string, version: string][]\n }): Promise<void> => {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: options.packages,\n },\n {output, workDir},\n )\n }\n\n await internalBuildStudio({\n appId,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId: cliConfig?.api?.projectId})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'studio', output),\n exposes: workbench ? {services: workbench.services, views: workbench.views} : undefined,\n isApp: determineIsApp(cliConfig),\n isWorkbenchApp: !!workbench,\n minify: Boolean(flags.minify),\n outDir,\n output,\n reactCompiler: cliConfig.reactCompiler,\n schemaExtraction: cliConfig.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: Boolean(flags.yes),\n upgradePackages: upgradePkgs,\n vite: cliConfig.vite,\n workbenchAppId: workbench?.name,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildStudio","internalBuildStudio","resolveWorkbenchApp","getAppId","determineIsApp","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","determineBasePath","options","calledFromDeploy","cliConfig","flags","outDir","output","workDir","workbench","appId","upgradePkgs","packageManager","interactive","chosen","packages","autoUpdatesEnabled","checkAppId","appType","projectId","api","exposes","services","views","undefined","isApp","isWorkbenchApp","minify","Boolean","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","yes","vite","workbenchAppId","name"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,eAAeC,mBAAmB,QAC7B,oCAAmC;AAC1C,SAAQC,mBAAmB,QAAO,8BAA6B;AAE/D,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,uBAAuB,QAAO,oDAAmD;AACzF,SAAQC,eAAe,QAAO,+CAA8C;AAC5E,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeR,YAAYS,OAAqB;IACrD,MAAM,EAACC,gBAAgB,EAAEC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAEtE,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAMO,YAAYd,oBAAoBS;IAEtC,MAAMM,QAAQd,SAASQ;IAEvB,MAAMO,cAAc,OAAOT;QAGzB,MAAMH,gBACJ;YACEa,gBAAgB,AAAC,CAAA,MAAMd,wBAAwBU,SAAS;gBAACK,aAAa;YAAK,EAAC,EAAGC,MAAM;YACrFC,UAAUb,QAAQa,QAAQ;QAC5B,GACA;YAACR;YAAQC;QAAO;IAEpB;IAEA,MAAMd,oBAAoB;QACxBgB;QACAM,oBAAoBd,QAAQc,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACP,SAAS,CAACP,kBAAkB;gBAC/BH,sBAAsB;oBAACkB,SAAS;oBAAUX;oBAAQY,WAAWf,WAAWgB,KAAKD;gBAAS;YACxF;QACF;QACA3B,2BAA2B,CAACuB,WAAavB,0BAA0BuB,UAAUP,SAAS;gBAACE;YAAK;QAC5FT,mBAAmB,IAAMA,kBAAkBG,WAAW,UAAUG;QAChEc,SAASZ,YAAY;YAACa,UAAUb,UAAUa,QAAQ;YAAEC,OAAOd,UAAUc,KAAK;QAAA,IAAIC;QAC9EC,OAAO5B,eAAeO;QACtBsB,gBAAgB,CAAC,CAACjB;QAClBkB,QAAQC,QAAQvB,MAAMsB,MAAM;QAC5BrB;QACAC;QACAsB,eAAezB,UAAUyB,aAAa;QACtCC,kBAAkB1B,UAAU0B,gBAAgB;QAC5CC,WAAWH,QAAQvB,KAAK,CAAC,cAAc;QACvC2B,OAAO3B,MAAM2B,KAAK;QAClBC,gBAAgBL,QAAQvB,MAAM6B,GAAG;QACjCnC,iBAAiBY;QACjBwB,MAAM/B,UAAU+B,IAAI;QACpBC,gBAAgB3B,WAAW4B;QAC3B7B;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildStudio as internalBuildStudio,\n} from '@sanity/cli-build/_internal/build'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {determineIsApp} from '../../util/determineIsApp.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const {calledFromDeploy, cliConfig, flags, outDir, output, workDir} = options\n\n // `views`/`services` live on the branded `unstable_defineApp` result — resolve\n // the workbench capability so it's gated on the brand, like the app build.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench ? {services: workbench.services, views: workbench.views} : undefined\n\n const appId = getAppId(cliConfig)\n\n const upgradePkgs = async (options: {\n packages: [name: string, version: string][]\n }): Promise<void> => {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: options.packages,\n },\n {output, workDir},\n )\n }\n\n await internalBuildStudio({\n appId,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId: cliConfig?.api?.projectId})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'studio', output),\n exposes,\n isApp: determineIsApp(cliConfig),\n isWorkbenchApp: !!workbench,\n minify: Boolean(flags.minify),\n outDir,\n output,\n reactCompiler: cliConfig.reactCompiler,\n schemaExtraction: cliConfig.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: Boolean(flags.yes),\n upgradePackages: upgradePkgs,\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench ? (options.applicationId ?? buildAppId(workbench)) : undefined,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildStudio","internalBuildStudio","buildAppId","resolveWorkbenchApp","getAppId","determineIsApp","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","determineBasePath","options","calledFromDeploy","cliConfig","flags","outDir","output","workDir","workbench","exposes","services","views","undefined","appId","upgradePkgs","packageManager","interactive","chosen","packages","autoUpdatesEnabled","checkAppId","appType","projectId","api","isApp","isWorkbenchApp","minify","Boolean","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","yes","vite","workbenchAppId","applicationId"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,eAAeC,mBAAmB,QAC7B,oCAAmC;AAC1C,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,uBAAuB,QAAO,oDAAmD;AACzF,SAAQC,eAAe,QAAO,+CAA8C;AAC5E,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeT,YAAYU,OAAqB;IACrD,MAAM,EAACC,gBAAgB,EAAEC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAEtE,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAMO,YAAYd,oBAAoBS;IACtC,MAAMM,UAAUD,YAAY;QAACE,UAAUF,UAAUE,QAAQ;QAAEC,OAAOH,UAAUG,KAAK;IAAA,IAAIC;IAErF,MAAMC,QAAQlB,SAASQ;IAEvB,MAAMW,cAAc,OAAOb;QAGzB,MAAMH,gBACJ;YACEiB,gBAAgB,AAAC,CAAA,MAAMlB,wBAAwBU,SAAS;gBAACS,aAAa;YAAK,EAAC,EAAGC,MAAM;YACrFC,UAAUjB,QAAQiB,QAAQ;QAC5B,GACA;YAACZ;YAAQC;QAAO;IAEpB;IAEA,MAAMf,oBAAoB;QACxBqB;QACAM,oBAAoBlB,QAAQkB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACP,SAAS,CAACX,kBAAkB;gBAC/BH,sBAAsB;oBAACsB,SAAS;oBAAUf;oBAAQgB,WAAWnB,WAAWoB,KAAKD;gBAAS;YACxF;QACF;QACAhC,2BAA2B,CAAC4B,WAAa5B,0BAA0B4B,UAAUX,SAAS;gBAACM;YAAK;QAC5Fb,mBAAmB,IAAMA,kBAAkBG,WAAW,UAAUG;QAChEG;QACAe,OAAO5B,eAAeO;QACtBsB,gBAAgB,CAAC,CAACjB;QAClBkB,QAAQC,QAAQvB,MAAMsB,MAAM;QAC5BrB;QACAC;QACAsB,eAAezB,UAAUyB,aAAa;QACtCC,kBAAkB1B,UAAU0B,gBAAgB;QAC5CC,WAAWH,QAAQvB,KAAK,CAAC,cAAc;QACvC2B,OAAO3B,MAAM2B,KAAK;QAClBC,gBAAgBL,QAAQvB,MAAM6B,GAAG;QACjCnC,iBAAiBgB;QACjBoB,MAAM/B,UAAU+B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgB3B,YAAaP,QAAQmC,aAAa,IAAI3C,WAAWe,aAAcI;QAC/EL;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/types.ts"],"sourcesContent":["import {type CliConfig, type Output} from '@sanity/cli-core'\n\nimport {BuildCommand} from '../../commands/build.js'\nimport {type DeployFlags} from '../deploy/types.js'\n\nexport type BuildFlags = BuildCommand['flags']\n\nexport interface BuildOptions {\n autoUpdatesEnabled: boolean\n cliConfig: CliConfig\n flags: BuildFlags | DeployFlags\n output: Output\n\n workDir: string\n\n calledFromDeploy?: boolean\n outDir?: string\n}\n"],"names":[],"mappings":"AAOA,WAUC"}
1
+ {"version":3,"sources":["../../../src/actions/build/types.ts"],"sourcesContent":["import {type CliConfig, type Output} from '@sanity/cli-core'\n\nimport {BuildCommand} from '../../commands/build.js'\nimport {type DeployFlags} from '../deploy/types.js'\n\nexport type BuildFlags = BuildCommand['flags']\n\nexport interface BuildOptions {\n autoUpdatesEnabled: boolean\n cliConfig: CliConfig\n flags: BuildFlags | DeployFlags\n output: Output\n\n workDir: string\n\n applicationId?: string\n calledFromDeploy?: boolean\n outDir?: string\n}\n"],"names":[],"mappings":"AAOA,WAWC"}
@@ -5,14 +5,14 @@ import { exitCodes } from '@sanity/cli-core';
5
5
  import { getErrorMessage } from '@sanity/cli-core/errors';
6
6
  import { getCoreAppUrl } from '@sanity/cli-core/util';
7
7
  import { spinner } from '@sanity/cli-core/ux';
8
- import { buildExposes, deployConfig, deployCoreApp as deployWorkbenchCoreApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
8
+ import { buildExposes, createCoreApp, deployConfig, deployWorkbenchApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
9
9
  import { pack } from 'tar-fs';
10
10
  import { createDeployment, updateUserApplication } from '../../services/userApplications.js';
11
11
  import { getAppId } from '../../util/appId.js';
12
12
  import { EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID } from '../../util/errorMessages.js';
13
13
  import { buildApp } from '../build/buildApp.js';
14
14
  import { extractCoreAppManifest, readIconFromPath, resolveTitleUpdate } from '../manifest/extractCoreAppManifest.js';
15
- import { createUserApplication, generateAppSlug } from './createUserApplication.js';
15
+ import { createUserApplication } from './createUserApplication.js';
16
16
  import { checkAppId, checkAppTarget, checkAutoUpdates, checkBuild, checkPackageVersion, verifyOutputDir } from './deployChecks.js';
17
17
  import { deployDebug } from './deployDebug.js';
18
18
  import { listDeploymentFiles, reportExposes } from './deploymentPlan.js';
@@ -103,193 +103,236 @@ export function deployApp(options) {
103
103
  reporter
104
104
  }));
105
105
  }
106
- await checkBuild(reporter, {
107
- build: ()=>buildApp({
108
- autoUpdatesEnabled: isAutoUpdating,
109
- calledFromDeploy: true,
110
- cliConfig,
111
- flags,
112
- outDir: sourceDir,
113
- output,
114
- workDir
115
- }),
116
- skipReason: flags.build ? undefined : 'Build skipped (--no-build) — validating existing output directory',
117
- successMessage: 'App built'
118
- });
119
- await verifyOutputDir({
120
- isWorkbenchApp: workbench !== null,
121
- reporter,
122
- sourceDir
123
- });
124
- // Workbench apps ship their icon straight to Brett (below) and don't read the
125
- // core-app manifest; only plain core-apps do. Manifests aren't strictly
126
- // essential, so a failure warns and continues.
127
- let manifest;
128
- if (!workbench) {
129
- try {
130
- manifest = await extractCoreAppManifest({
131
- workDir
132
- });
133
- } catch (err) {
134
- deployDebug('Error extracting app manifest', err);
135
- reporter.report({
136
- message: `Error extracting app manifest: ${getErrorMessage(err)}`,
137
- status: 'warn'
138
- });
139
- }
140
- }
141
- // Resolve the installation in both modes so the report — dry-run and real —
142
- // shows whether the config is deployable; a missing one fails the deploy here.
143
- let installationId;
144
- let config;
145
- const configAppType = workbench?.config?.appType;
146
- if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {
147
- installationId = await resolveInstallationId({
148
- appType: configAppType,
149
- organizationId
150
- });
151
- config = summarizeConfig(workbench.config);
152
- reporter.report(installationId ? {
153
- config,
154
- message: config,
155
- status: 'pass'
156
- } : {
106
+ // A first deploy mints the app id and the build inlines it; --no-build would
107
+ // ship an existing bundle carrying a different id, so it can't be a first deploy.
108
+ if (deployApplication && workbench && !appId && !flags.external && !flags.build) {
109
+ reporter.report({
157
110
  exitCode: exitCodes.USAGE_ERROR,
158
- message: `No active "${configAppType}" installation for organization "${organizationId}"`,
159
- solution: 'Install the Media Library for the organization before deploying its config',
111
+ message: 'A first deploy cannot skip the build (--no-build)',
112
+ solution: 'Drop --no-build so the new application id is inlined into the build',
160
113
  status: 'fail'
161
114
  });
162
115
  }
163
- // Report the exposes deploying with the application, both modes.
164
- const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : [];
165
- // Surface the app's explicit singleton flag when set, both modes.
166
- if (deployApplication && workbench?.isSingleton !== undefined) {
167
- reporter.report({
116
+ // Read up front so a bad icon path fails before we create or build.
117
+ const appIcon = !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined;
118
+ // Create the app before the build so the bundle carries its real id. A
119
+ // redeploy already has it from `deployment.appId`; a dry run skips creation.
120
+ let applicationId = appId;
121
+ let applicationCreated = false;
122
+ let rollbackApp;
123
+ if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {
124
+ ;
125
+ ({ applicationId, rollback: rollbackApp } = await createCoreApp({
168
126
  isSingleton: workbench.isSingleton,
169
- message: `Singleton: ${workbench.isSingleton}`,
170
- status: 'pass'
171
- });
172
- }
173
- // Dry run stops here — everything below mutates.
174
- if (dryRun) return;
175
- if (installationId && version && configAppType && organizationId) {
176
- await deployConfig({
177
- appType: configAppType,
178
- installationId,
179
127
  organizationId,
180
- output,
181
- sourceDir,
182
- version
183
- });
128
+ slug: workbench.slug,
129
+ title: appTitle,
130
+ visibility: workbench.visibility
131
+ }));
132
+ applicationCreated = true;
184
133
  }
185
- // A config-only singleton ships no application, only its config.
186
- if (!deployApplication) {
187
- if (installationId && version) {
134
+ // A record created above is stranded at its slug (and blocks retries) if any
135
+ // step before it fully deploys fails, so undo the creation on failure.
136
+ try {
137
+ await checkBuild(reporter, {
138
+ build: ()=>buildApp({
139
+ applicationId: workbench ? applicationId : undefined,
140
+ autoUpdatesEnabled: isAutoUpdating,
141
+ calledFromDeploy: true,
142
+ cliConfig,
143
+ flags,
144
+ outDir: sourceDir,
145
+ output,
146
+ workDir
147
+ }),
148
+ skipReason: flags.build ? undefined : 'Build skipped (--no-build) — validating existing output directory',
149
+ successMessage: 'App built'
150
+ });
151
+ await verifyOutputDir({
152
+ isWorkbenchApp: workbench !== null,
153
+ reporter,
154
+ sourceDir
155
+ });
156
+ // Workbench apps ship their icon straight to Brett (below) and don't read the
157
+ // core-app manifest; only plain core-apps do. Manifests aren't strictly
158
+ // essential, so a failure warns and continues.
159
+ let manifest;
160
+ if (!workbench) {
161
+ try {
162
+ manifest = await extractCoreAppManifest({
163
+ workDir
164
+ });
165
+ } catch (err) {
166
+ deployDebug('Error extracting app manifest', err);
167
+ reporter.report({
168
+ message: `Error extracting app manifest: ${getErrorMessage(err)}`,
169
+ status: 'warn'
170
+ });
171
+ }
172
+ }
173
+ // Resolve the installation in both modes so the report — dry-run and real —
174
+ // shows whether the config is deployable; a missing one fails the deploy here.
175
+ let installationId;
176
+ let config;
177
+ const configAppType = workbench?.config?.appType;
178
+ if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {
179
+ installationId = await resolveInstallationId({
180
+ appType: configAppType,
181
+ organizationId
182
+ });
183
+ config = summarizeConfig(workbench.config);
184
+ reporter.report(installationId ? {
185
+ config,
186
+ message: config,
187
+ status: 'pass'
188
+ } : {
189
+ exitCode: exitCodes.USAGE_ERROR,
190
+ message: `No active "${configAppType}" installation for organization "${organizationId}"`,
191
+ solution: 'Install the Media Library for the organization before deploying its config',
192
+ status: 'fail'
193
+ });
194
+ }
195
+ // Report the exposes deploying with the application, both modes.
196
+ const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : [];
197
+ // Surface the app's explicit singleton flag when set, both modes.
198
+ if (deployApplication && workbench?.isSingleton !== undefined) {
199
+ reporter.report({
200
+ isSingleton: workbench.isSingleton,
201
+ message: `Singleton: ${workbench.isSingleton}`,
202
+ status: 'pass'
203
+ });
204
+ }
205
+ // Applied after the app is live (see below) so a failed deploy never leaves
206
+ // the org's installation config without its application.
207
+ const deployApplicationConfig = async ()=>{
208
+ if (installationId && version && configAppType && organizationId) {
209
+ await deployConfig({
210
+ appType: configAppType,
211
+ installationId,
212
+ organizationId,
213
+ output,
214
+ sourceDir,
215
+ version
216
+ });
217
+ }
218
+ };
219
+ // Dry run stops here — everything below mutates.
220
+ if (dryRun) return;
221
+ // A config-only singleton ships no application, only its config.
222
+ if (!deployApplication) {
223
+ await deployApplicationConfig();
224
+ if (installationId && version) {
225
+ return {
226
+ applicationType: 'coreApp',
227
+ applicationVersion: version,
228
+ ...config ? {
229
+ config
230
+ } : {},
231
+ installationId,
232
+ target: null
233
+ };
234
+ }
235
+ return;
236
+ }
237
+ // A real deploy already exited on a version-resolution failure; this narrows the type.
238
+ if (!version) return;
239
+ // The app was created (or resolved from `deployment.appId`) before the build,
240
+ // so this only ships the deployment; plain coreApps use user-applications below.
241
+ if (workbench && organizationId && applicationId) {
242
+ await deployWorkbenchApp({
243
+ applicationId,
244
+ icon: appIcon,
245
+ interfaces: buildExposes(workbench, {
246
+ appName: workbench.name,
247
+ appTitle,
248
+ exposesAppView: workbench.entry !== undefined,
249
+ version
250
+ }),
251
+ isAutoUpdating,
252
+ // Once the deployment is live, a metadata-sync or later config failure
253
+ // must not delete the app.
254
+ onDeployed: ()=>{
255
+ rollbackApp = undefined;
256
+ },
257
+ sourceDir,
258
+ title: appTitle,
259
+ version,
260
+ visibility: workbench.visibility
261
+ });
262
+ await deployApplicationConfig();
263
+ const url = getApplicationUrl({
264
+ id: applicationId,
265
+ organizationId,
266
+ type: 'coreApp'
267
+ });
268
+ logAppDeployed({
269
+ applicationId,
270
+ cliConfig,
271
+ created: applicationCreated,
272
+ organizationId,
273
+ output,
274
+ title: appTitle,
275
+ url
276
+ });
188
277
  return {
189
278
  applicationType: 'coreApp',
190
279
  applicationVersion: version,
191
- ...config ? {
192
- config
280
+ ...exposes.length > 0 ? {
281
+ exposes
193
282
  } : {},
194
- installationId,
195
- target: null
283
+ ...workbench.isSingleton === undefined ? {} : {
284
+ isSingleton: workbench.isSingleton
285
+ },
286
+ target: {
287
+ action: applicationCreated ? 'create' : 'update',
288
+ applicationId,
289
+ // A redeploy targets an existing app; only a create reports the slug.
290
+ ...applicationCreated ? {
291
+ slug: workbench.slug
292
+ } : {},
293
+ title: appTitle,
294
+ url
295
+ }
196
296
  };
197
297
  }
198
- return;
199
- }
200
- // A real deploy already exited on a version-resolution failure; this narrows the type.
201
- if (!version) return;
202
- // Workbench apps deploy to Brett; plain coreApps use user-applications.
203
- if (workbench && organizationId) {
204
- const appId = getAppId(cliConfig);
205
- const slug = workbench.slug ?? generateAppSlug();
206
- const { applicationId } = await deployWorkbenchCoreApp({
207
- appId,
208
- icon: workbench.icon ? await readIconFromPath(workDir, workbench.icon) : undefined,
209
- interfaces: buildExposes(workbench, {
210
- appName: workbench.name,
211
- appTitle,
212
- exposesAppView: workbench.entry !== undefined,
213
- version
214
- }),
298
+ // A real deploy has already exited if anything failed; landing here without a
299
+ // resolved application means the deploy target was never resolved.
300
+ if (!application) return;
301
+ application = await syncApplicationMetadata({
302
+ application,
303
+ manifest,
304
+ output,
305
+ visibility: cliConfig.app?.visibility
306
+ });
307
+ await shipAppDeployment({
308
+ application,
215
309
  isAutoUpdating,
216
- isSingleton: workbench.isSingleton,
217
- organizationId,
218
- slug,
310
+ manifest,
219
311
  sourceDir,
220
- title: appTitle,
221
- version,
222
- visibility: workbench.visibility
223
- });
224
- const url = getApplicationUrl({
225
- id: applicationId,
226
- organizationId,
227
- type: 'coreApp'
312
+ version
228
313
  });
229
314
  logAppDeployed({
230
- applicationId,
315
+ applicationId: application.id,
231
316
  cliConfig,
232
- created: !appId,
233
- organizationId,
317
+ created: appCreated,
318
+ organizationId: application.organizationId,
234
319
  output,
235
- title: appTitle,
236
- url
320
+ title: application.title
237
321
  });
238
322
  return {
239
323
  applicationType: 'coreApp',
240
324
  applicationVersion: version,
241
- ...exposes.length > 0 ? {
242
- exposes
243
- } : {},
244
- ...workbench.isSingleton === undefined ? {} : {
245
- isSingleton: workbench.isSingleton
246
- },
247
325
  target: {
248
- action: appId ? 'update' : 'create',
249
- applicationId,
250
- // A redeploy ignores the slug, so only a create reports the one it used.
251
- ...appId ? {} : {
252
- slug
253
- },
254
- title: appTitle,
255
- url
326
+ action: appCreated ? 'create' : 'update',
327
+ applicationId: application.id,
328
+ title: application.title ?? null,
329
+ url: getCoreAppUrl(application.organizationId, application.id)
256
330
  }
257
331
  };
332
+ } catch (err) {
333
+ await rollbackApp?.();
334
+ throw err;
258
335
  }
259
- // A real deploy has already exited if anything failed; landing here without a
260
- // resolved application means the deploy target was never resolved.
261
- if (!application) return;
262
- application = await syncApplicationMetadata({
263
- application,
264
- manifest,
265
- output,
266
- visibility: cliConfig.app?.visibility
267
- });
268
- await shipAppDeployment({
269
- application,
270
- isAutoUpdating,
271
- manifest,
272
- sourceDir,
273
- version
274
- });
275
- logAppDeployed({
276
- applicationId: application.id,
277
- cliConfig,
278
- created: appCreated,
279
- organizationId: application.organizationId,
280
- output,
281
- title: application.title
282
- });
283
- return {
284
- applicationType: 'coreApp',
285
- applicationVersion: version,
286
- target: {
287
- action: appCreated ? 'create' : 'update',
288
- applicationId: application.id,
289
- title: application.title ?? null,
290
- url: getCoreAppUrl(application.organizationId, application.id)
291
- }
292
- };
293
336
  }
294
337
  /**
295
338
  * Finds the application a real deploy targets, creating one when none is