@sanity/cli 7.10.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.
Files changed (174) hide show
  1. package/README.md +31 -22
  2. package/dist/actions/auth/ensureAuthenticated.js +2 -0
  3. package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
  4. package/dist/actions/auth/login/loginInstructions.js +19 -0
  5. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  6. package/dist/actions/build/buildApp.js +10 -7
  7. package/dist/actions/build/buildApp.js.map +1 -1
  8. package/dist/actions/build/buildStudio.js +9 -6
  9. package/dist/actions/build/buildStudio.js.map +1 -1
  10. package/dist/actions/build/types.js.map +1 -1
  11. package/dist/actions/dataset/resolveDataset.js +7 -1
  12. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  13. package/dist/actions/deploy/deployApp.js +205 -157
  14. package/dist/actions/deploy/deployApp.js.map +1 -1
  15. package/dist/actions/deploy/deployChecks.js +1 -1
  16. package/dist/actions/deploy/deployChecks.js.map +1 -1
  17. package/dist/actions/deploy/deployStudio.js +127 -86
  18. package/dist/actions/deploy/deployStudio.js.map +1 -1
  19. package/dist/actions/deploy/resolveDeployTarget.js +5 -9
  20. package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
  21. package/dist/actions/dev/devAction.js +1 -2
  22. package/dist/actions/dev/devAction.js.map +1 -1
  23. package/dist/actions/dev/servers/getDevServerConfig.js +8 -2
  24. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  25. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  26. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  27. package/dist/actions/init/bootstrapLocalTemplate.js +18 -9
  28. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  29. package/dist/actions/init/createAppCliConfig.js.map +1 -1
  30. package/dist/actions/init/createCliConfig.js.map +1 -1
  31. package/dist/actions/init/initAction.js +23 -15
  32. package/dist/actions/init/initAction.js.map +1 -1
  33. package/dist/actions/manifest/extractCoreAppManifest.js +5 -3
  34. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  35. package/dist/actions/migration/constants.js +10 -0
  36. package/dist/actions/migration/constants.js.map +1 -0
  37. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  38. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  39. package/dist/actions/migration/fileExists.js +13 -0
  40. package/dist/actions/migration/fileExists.js.map +1 -0
  41. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  42. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  43. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  44. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  45. package/dist/actions/migration/resolveMigrations.js +50 -0
  46. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  47. package/dist/actions/migration/templates/index.js +7 -0
  48. package/dist/actions/migration/templates/index.js.map +1 -0
  49. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  50. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  51. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  52. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  53. package/dist/actions/migration/templates/renameField.js +20 -0
  54. package/dist/actions/migration/templates/renameField.js.map +1 -0
  55. package/dist/actions/migration/templates/renameType.js +19 -0
  56. package/dist/actions/migration/templates/renameType.js.map +1 -0
  57. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  58. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  59. package/dist/actions/migration/tree.js +111 -0
  60. package/dist/actions/migration/tree.js.map +1 -0
  61. package/dist/actions/preview/previewAction.js +33 -1
  62. package/dist/actions/preview/previewAction.js.map +1 -1
  63. package/dist/actions/schema/listSchemas.js +6 -4
  64. package/dist/actions/schema/listSchemas.js.map +1 -1
  65. package/dist/actions/tokens/validateRole.js +2 -1
  66. package/dist/actions/tokens/validateRole.js.map +1 -1
  67. package/dist/actions/undeploy/runUndeploy.js +13 -4
  68. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  69. package/dist/commands/backups/disable.js +5 -1
  70. package/dist/commands/backups/disable.js.map +1 -1
  71. package/dist/commands/backups/download.js +30 -6
  72. package/dist/commands/backups/download.js.map +1 -1
  73. package/dist/commands/backups/enable.js +5 -1
  74. package/dist/commands/backups/enable.js.map +1 -1
  75. package/dist/commands/backups/list.js +5 -1
  76. package/dist/commands/backups/list.js.map +1 -1
  77. package/dist/commands/cors/add.js +15 -7
  78. package/dist/commands/cors/add.js.map +1 -1
  79. package/dist/commands/cors/delete.js +6 -1
  80. package/dist/commands/cors/delete.js.map +1 -1
  81. package/dist/commands/datasets/alias/create.js +25 -18
  82. package/dist/commands/datasets/alias/create.js.map +1 -1
  83. package/dist/commands/datasets/alias/delete.js +15 -8
  84. package/dist/commands/datasets/alias/delete.js.map +1 -1
  85. package/dist/commands/datasets/alias/link.js +39 -17
  86. package/dist/commands/datasets/alias/link.js.map +1 -1
  87. package/dist/commands/datasets/alias/unlink.js +23 -2
  88. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  89. package/dist/commands/datasets/copy.js +18 -2
  90. package/dist/commands/datasets/copy.js.map +1 -1
  91. package/dist/commands/datasets/create.js +8 -2
  92. package/dist/commands/datasets/create.js.map +1 -1
  93. package/dist/commands/datasets/delete.js +14 -17
  94. package/dist/commands/datasets/delete.js.map +1 -1
  95. package/dist/commands/datasets/embeddings/disable.js +3 -0
  96. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  97. package/dist/commands/datasets/embeddings/enable.js +5 -2
  98. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  99. package/dist/commands/datasets/embeddings/status.js +3 -0
  100. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  101. package/dist/commands/datasets/export.js +27 -15
  102. package/dist/commands/datasets/export.js.map +1 -1
  103. package/dist/commands/datasets/import.js +3 -3
  104. package/dist/commands/datasets/import.js.map +1 -1
  105. package/dist/commands/datasets/visibility/get.js +2 -2
  106. package/dist/commands/datasets/visibility/get.js.map +1 -1
  107. package/dist/commands/datasets/visibility/set.js +2 -2
  108. package/dist/commands/datasets/visibility/set.js.map +1 -1
  109. package/dist/commands/docs/read.js +3 -3
  110. package/dist/commands/docs/read.js.map +1 -1
  111. package/dist/commands/documents/create.js +18 -13
  112. package/dist/commands/documents/create.js.map +1 -1
  113. package/dist/commands/documents/delete.js +3 -3
  114. package/dist/commands/documents/delete.js.map +1 -1
  115. package/dist/commands/documents/get.js +3 -3
  116. package/dist/commands/documents/get.js.map +1 -1
  117. package/dist/commands/documents/query.js +3 -3
  118. package/dist/commands/documents/query.js.map +1 -1
  119. package/dist/commands/documents/validate.js +29 -26
  120. package/dist/commands/documents/validate.js.map +1 -1
  121. package/dist/commands/graphql/deploy.js +20 -16
  122. package/dist/commands/graphql/deploy.js.map +1 -1
  123. package/dist/commands/graphql/undeploy.js +15 -18
  124. package/dist/commands/graphql/undeploy.js.map +1 -1
  125. package/dist/commands/hooks/delete.js +2 -2
  126. package/dist/commands/hooks/delete.js.map +1 -1
  127. package/dist/commands/hooks/logs.js +2 -2
  128. package/dist/commands/hooks/logs.js.map +1 -1
  129. package/dist/commands/login.js +2 -1
  130. package/dist/commands/login.js.map +1 -1
  131. package/dist/commands/media/create-aspect.js +20 -8
  132. package/dist/commands/media/create-aspect.js.map +1 -1
  133. package/dist/commands/media/delete-aspect.js +31 -16
  134. package/dist/commands/media/delete-aspect.js.map +1 -1
  135. package/dist/commands/media/deploy-aspect.js +10 -5
  136. package/dist/commands/media/deploy-aspect.js.map +1 -1
  137. package/dist/commands/media/export.js +9 -4
  138. package/dist/commands/media/export.js.map +1 -1
  139. package/dist/commands/media/import.js +6 -1
  140. package/dist/commands/media/import.js.map +1 -1
  141. package/dist/commands/migrations/create.js +150 -0
  142. package/dist/commands/migrations/create.js.map +1 -0
  143. package/dist/commands/migrations/list.js +64 -0
  144. package/dist/commands/migrations/list.js.map +1 -0
  145. package/dist/commands/migrations/run.js +306 -0
  146. package/dist/commands/migrations/run.js.map +1 -0
  147. package/dist/commands/preview.js +1 -0
  148. package/dist/commands/preview.js.map +1 -1
  149. package/dist/commands/projects/create.js +2 -1
  150. package/dist/commands/projects/create.js.map +1 -1
  151. package/dist/commands/schemas/delete.js +23 -2
  152. package/dist/commands/schemas/delete.js.map +1 -1
  153. package/dist/commands/schemas/deploy.js +6 -4
  154. package/dist/commands/schemas/deploy.js.map +1 -1
  155. package/dist/commands/schemas/extract.js +22 -1
  156. package/dist/commands/schemas/extract.js.map +1 -1
  157. package/dist/commands/schemas/list.js +8 -8
  158. package/dist/commands/schemas/list.js.map +1 -1
  159. package/dist/commands/tokens/{add.js → create.js} +25 -18
  160. package/dist/commands/tokens/create.js.map +1 -0
  161. package/dist/commands/tokens/delete.js +41 -23
  162. package/dist/commands/tokens/delete.js.map +1 -1
  163. package/dist/commands/undeploy.js +2 -7
  164. package/dist/commands/undeploy.js.map +1 -1
  165. package/dist/commands/users/invite.js +25 -3
  166. package/dist/commands/users/invite.js.map +1 -1
  167. package/dist/topicAliases.js +3 -0
  168. package/dist/topicAliases.js.map +1 -1
  169. package/dist/util/formatCliErrorMessages.js +5 -0
  170. package/dist/util/formatCliErrorMessages.js.map +1 -0
  171. package/oclif.config.js +5 -1
  172. package/oclif.manifest.json +579 -374
  173. package/package.json +7 -7
  174. package/dist/commands/tokens/add.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/dev/devAction.ts"],"sourcesContent":["import {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\nimport {type CliConfig} from '@sanity/cli-core'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {checkForDeprecatedAppId, getAppId} from '../../util/appId.js'\nimport {getSharedServerConfig} from '../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../util/resolveReactStrictMode.js'\nimport {extractCoreAppManifest} from '../manifest/extractCoreAppManifest.js'\nimport {extractStudioManifest} from '../manifest/extractStudioManifest.js'\nimport {startAppDevServer} from './servers/startAppDevServer.js'\nimport {startStudioDevServer} from './servers/startStudioDevServer.js'\nimport {type DevActionOptions} from './types.js'\n\nconst noop = async () => {}\n\n/**\n * Entry point for `sanity dev`. A plain studio/app starts a single dev server, as\n * before workbench existed. A workbench app (via `unstable_defineApp`) delegates to\n * `@sanity/workbench-cli`, injecting the CLI-domain pieces (app server, manifest\n * extraction, app id) and loading the package lazily so plain projects never do.\n */\nexport async function devAction(options: DevActionOptions): Promise<{close: () => Promise<void>}> {\n const {cliConfig, flags, isApp, output, workDir} = options\n\n const {httpHost, httpPort} = getSharedServerConfig({\n cliConfig,\n flags: {host: flags.host, port: flags.port},\n workDir,\n })\n\n // The app/studio server, parameterized per call; `announceUrl` is false when\n // the workbench announces the URL on its behalf.\n const startAppServer = (params: {announceUrl: boolean; cliConfig: CliConfig; httpPort: number}) =>\n (isApp ? startAppDevServer : startStudioDevServer)({\n ...options,\n announceUrl: params.announceUrl,\n cliConfig: params.cliConfig,\n httpPort: params.httpPort,\n })\n\n if (isWorkbenchApp(cliConfig?.app)) {\n // Lazy so a non-workbench `sanity dev` never loads the package. `doImport`\n // is path-based and doesn't apply to a bare specifier.\n // eslint-disable-next-line no-restricted-syntax\n const {startWorkbenchDev} = await import('@sanity/workbench-cli/dev')\n return startWorkbenchDev({\n appId: getAppId(cliConfig),\n cacheDir: `${SANITY_CACHE_DIR}/vite`,\n checkForDeprecatedAppId: () => checkForDeprecatedAppId({cliConfig, output}),\n cliConfig,\n extractManifest: isApp\n ? ({workDir: wd}) => extractCoreAppManifest({workDir: wd})\n : (params) => extractStudioManifest(params),\n httpHost,\n httpPort,\n isApp,\n output,\n // Runtime template needs a concrete boolean; collapse an unset config to off.\n reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,\n startAppServer,\n workDir,\n })\n }\n\n // Plain non-workbench studio/app: one dev server announcing its own URL.\n const result = await startAppServer({announceUrl: true, cliConfig, httpPort})\n return {close: result.started ? result.close : noop}\n}\n"],"names":["SANITY_CACHE_DIR","isWorkbenchApp","checkForDeprecatedAppId","getAppId","getSharedServerConfig","resolveReactStrictMode","extractCoreAppManifest","extractStudioManifest","startAppDevServer","startStudioDevServer","noop","devAction","options","cliConfig","flags","isApp","output","workDir","httpHost","httpPort","host","port","startAppServer","params","announceUrl","app","startWorkbenchDev","appId","cacheDir","extractManifest","wd","reactStrictMode","result","close","started"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,oCAAmC;AAElE,SAAQC,cAAc,QAAO,wBAAuB;AAEpD,SAAQC,uBAAuB,EAAEC,QAAQ,QAAO,sBAAqB;AACrE,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,sBAAsB,QAAO,uCAAsC;AAC3E,SAAQC,sBAAsB,QAAO,wCAAuC;AAC5E,SAAQC,qBAAqB,QAAO,uCAAsC;AAC1E,SAAQC,iBAAiB,QAAO,iCAAgC;AAChE,SAAQC,oBAAoB,QAAO,oCAAmC;AAGtE,MAAMC,OAAO,WAAa;AAE1B;;;;;CAKC,GACD,OAAO,eAAeC,UAAUC,OAAyB;IACvD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEnD,MAAM,EAACM,QAAQ,EAAEC,QAAQ,EAAC,GAAGf,sBAAsB;QACjDS;QACAC,OAAO;YAACM,MAAMN,MAAMM,IAAI;YAAEC,MAAMP,MAAMO,IAAI;QAAA;QAC1CJ;IACF;IAEA,6EAA6E;IAC7E,iDAAiD;IACjD,MAAMK,iBAAiB,CAACC,SACtB,AAACR,CAAAA,QAAQP,oBAAoBC,oBAAmB,EAAG;YACjD,GAAGG,OAAO;YACVY,aAAaD,OAAOC,WAAW;YAC/BX,WAAWU,OAAOV,SAAS;YAC3BM,UAAUI,OAAOJ,QAAQ;QAC3B;IAEF,IAAIlB,eAAeY,WAAWY,MAAM;QAClC,2EAA2E;QAC3E,uDAAuD;QACvD,gDAAgD;QAChD,MAAM,EAACC,iBAAiB,EAAC,GAAG,MAAM,MAAM,CAAC;QACzC,OAAOA,kBAAkB;YACvBC,OAAOxB,SAASU;YAChBe,UAAU,GAAG5B,iBAAiB,KAAK,CAAC;YACpCE,yBAAyB,IAAMA,wBAAwB;oBAACW;oBAAWG;gBAAM;YACzEH;YACAgB,iBAAiBd,QACb,CAAC,EAACE,SAASa,EAAE,EAAC,GAAKxB,uBAAuB;oBAACW,SAASa;gBAAE,KACtD,CAACP,SAAWhB,sBAAsBgB;YACtCL;YACAC;YACAJ;YACAC;YACA,8EAA8E;YAC9Ee,iBAAiB1B,uBAAuBQ,cAAc;YACtDS;YACAL;QACF;IACF;IAEA,yEAAyE;IACzE,MAAMe,SAAS,MAAMV,eAAe;QAACE,aAAa;QAAMX;QAAWM;IAAQ;IAC3E,OAAO;QAACc,OAAOD,OAAOE,OAAO,GAAGF,OAAOC,KAAK,GAAGvB;IAAI;AACrD"}
1
+ {"version":3,"sources":["../../../src/actions/dev/devAction.ts"],"sourcesContent":["import {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\nimport {type CliConfig} from '@sanity/cli-core'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {checkForDeprecatedAppId} from '../../util/appId.js'\nimport {getSharedServerConfig} from '../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../util/resolveReactStrictMode.js'\nimport {extractCoreAppManifest} from '../manifest/extractCoreAppManifest.js'\nimport {extractStudioManifest} from '../manifest/extractStudioManifest.js'\nimport {startAppDevServer} from './servers/startAppDevServer.js'\nimport {startStudioDevServer} from './servers/startStudioDevServer.js'\nimport {type DevActionOptions} from './types.js'\n\nconst noop = async () => {}\n\n/**\n * Entry point for `sanity dev`. A plain studio/app starts a single dev server, as\n * before workbench existed. A workbench app (via `unstable_defineApp`) delegates to\n * `@sanity/workbench-cli`, injecting the CLI-domain pieces (app server, manifest\n * extraction, app id) and loading the package lazily so plain projects never do.\n */\nexport async function devAction(options: DevActionOptions): Promise<{close: () => Promise<void>}> {\n const {cliConfig, flags, isApp, output, workDir} = options\n\n const {httpHost, httpPort} = getSharedServerConfig({\n cliConfig,\n flags: {host: flags.host, port: flags.port},\n workDir,\n })\n\n // The app/studio server, parameterized per call; `announceUrl` is false when\n // the workbench announces the URL on its behalf.\n const startAppServer = (params: {announceUrl: boolean; cliConfig: CliConfig; httpPort: number}) =>\n (isApp ? startAppDevServer : startStudioDevServer)({\n ...options,\n announceUrl: params.announceUrl,\n cliConfig: params.cliConfig,\n httpPort: params.httpPort,\n })\n\n if (isWorkbenchApp(cliConfig?.app)) {\n // Lazy so a non-workbench `sanity dev` never loads the package. `doImport`\n // is path-based and doesn't apply to a bare specifier.\n // eslint-disable-next-line no-restricted-syntax\n const {startWorkbenchDev} = await import('@sanity/workbench-cli/dev')\n return startWorkbenchDev({\n cacheDir: `${SANITY_CACHE_DIR}/vite`,\n checkForDeprecatedAppId: () => checkForDeprecatedAppId({cliConfig, output}),\n cliConfig,\n extractManifest: isApp\n ? ({workDir: wd}) => extractCoreAppManifest({workDir: wd})\n : (params) => extractStudioManifest(params),\n httpHost,\n httpPort,\n isApp,\n output,\n // Runtime template needs a concrete boolean; collapse an unset config to off.\n reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,\n startAppServer,\n workDir,\n })\n }\n\n // Plain non-workbench studio/app: one dev server announcing its own URL.\n const result = await startAppServer({announceUrl: true, cliConfig, httpPort})\n return {close: result.started ? result.close : noop}\n}\n"],"names":["SANITY_CACHE_DIR","isWorkbenchApp","checkForDeprecatedAppId","getSharedServerConfig","resolveReactStrictMode","extractCoreAppManifest","extractStudioManifest","startAppDevServer","startStudioDevServer","noop","devAction","options","cliConfig","flags","isApp","output","workDir","httpHost","httpPort","host","port","startAppServer","params","announceUrl","app","startWorkbenchDev","cacheDir","extractManifest","wd","reactStrictMode","result","close","started"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,oCAAmC;AAElE,SAAQC,cAAc,QAAO,wBAAuB;AAEpD,SAAQC,uBAAuB,QAAO,sBAAqB;AAC3D,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,sBAAsB,QAAO,uCAAsC;AAC3E,SAAQC,sBAAsB,QAAO,wCAAuC;AAC5E,SAAQC,qBAAqB,QAAO,uCAAsC;AAC1E,SAAQC,iBAAiB,QAAO,iCAAgC;AAChE,SAAQC,oBAAoB,QAAO,oCAAmC;AAGtE,MAAMC,OAAO,WAAa;AAE1B;;;;;CAKC,GACD,OAAO,eAAeC,UAAUC,OAAyB;IACvD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEnD,MAAM,EAACM,QAAQ,EAAEC,QAAQ,EAAC,GAAGf,sBAAsB;QACjDS;QACAC,OAAO;YAACM,MAAMN,MAAMM,IAAI;YAAEC,MAAMP,MAAMO,IAAI;QAAA;QAC1CJ;IACF;IAEA,6EAA6E;IAC7E,iDAAiD;IACjD,MAAMK,iBAAiB,CAACC,SACtB,AAACR,CAAAA,QAAQP,oBAAoBC,oBAAmB,EAAG;YACjD,GAAGG,OAAO;YACVY,aAAaD,OAAOC,WAAW;YAC/BX,WAAWU,OAAOV,SAAS;YAC3BM,UAAUI,OAAOJ,QAAQ;QAC3B;IAEF,IAAIjB,eAAeW,WAAWY,MAAM;QAClC,2EAA2E;QAC3E,uDAAuD;QACvD,gDAAgD;QAChD,MAAM,EAACC,iBAAiB,EAAC,GAAG,MAAM,MAAM,CAAC;QACzC,OAAOA,kBAAkB;YACvBC,UAAU,GAAG1B,iBAAiB,KAAK,CAAC;YACpCE,yBAAyB,IAAMA,wBAAwB;oBAACU;oBAAWG;gBAAM;YACzEH;YACAe,iBAAiBb,QACb,CAAC,EAACE,SAASY,EAAE,EAAC,GAAKvB,uBAAuB;oBAACW,SAASY;gBAAE,KACtD,CAACN,SAAWhB,sBAAsBgB;YACtCL;YACAC;YACAJ;YACAC;YACA,8EAA8E;YAC9Ec,iBAAiBzB,uBAAuBQ,cAAc;YACtDS;YACAL;QACF;IACF;IAEA,yEAAyE;IACzE,MAAMc,SAAS,MAAMT,eAAe;QAACE,aAAa;QAAMX;QAAWM;IAAQ;IAC3E,OAAO;QAACa,OAAOD,OAAOE,OAAO,GAAGF,OAAOC,KAAK,GAAGtB;IAAI;AACrD"}
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { getSanityEnvVar } from '@sanity/cli-core';
3
3
  import { logSymbols, spinner } from '@sanity/cli-core/ux';
4
- import { isWorkbenchApp } from '@sanity/workbench-cli';
4
+ import { isWorkbenchApp, resolveAppId } from '@sanity/workbench-cli';
5
5
  import { determineIsApp } from '../../../util/determineIsApp.js';
6
6
  import { getSharedServerConfig } from '../../../util/getSharedServerConfig.js';
7
7
  import { resolveReactStrictMode } from '../../../util/resolveReactStrictMode.js';
@@ -50,7 +50,13 @@ export function getDevServerConfig({ cliConfig, flags, httpPort, output, workDir
50
50
  reactStrictMode,
51
51
  staticPath: path.join(workDir, 'static'),
52
52
  typegen: cliConfig?.typegen,
53
- workbenchAppId: isWorkbenchApp(app) ? app.name : undefined
53
+ // Inline the same id the dev registry advertises so the app's bus identity
54
+ // matches how the workbench addresses it. The registry re-reads the bound
55
+ // port if a non-strict shift moves it.
56
+ workbenchAppId: isWorkbenchApp(app) ? resolveAppId({
57
+ host: baseConfig.httpHost,
58
+ port: httpPort ?? baseConfig.httpPort
59
+ }) : undefined
54
60
  };
55
61
  }
56
62
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, type Output} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views`/`services` are declared via `unstable_defineApp`, so read them off\n // the branded app result rather than the legacy `app` config type.\n const app = cliConfig?.app\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n // Unstable opt-in to Vite's experimental bundled dev mode, via\n // `unstable_bundledDev` in sanity.cli.ts. Defaults to off.\n const bundledDev = cliConfig?.unstable_bundledDev ?? false\n if (bundledDev) {\n output.log(`${logSymbols.info} Running dev server with experimental Vite bundled dev mode`)\n }\n\n return {\n ...baseConfig,\n bundledDev,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view: the runtime/federation skip the `./App` render path entirely.\n entry: app?.entry,\n exposes: isWorkbenchApp(app)\n ? {config: app.config, services: app.services, views: app.views}\n : undefined,\n // `devAction` passes an explicit port when a running workbench claimed the\n // configured one; otherwise the shared resolution stands.\n httpPort: httpPort ?? baseConfig.httpPort,\n isWorkbenchApp: isWorkbenchApp(app),\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n reactStrictMode,\n staticPath: path.join(workDir, 'static'),\n typegen: cliConfig?.typegen,\n workbenchAppId: isWorkbenchApp(app) ? app.name : undefined,\n }\n}\n"],"names":["path","getSanityEnvVar","logSymbols","spinner","isWorkbenchApp","determineIsApp","getSharedServerConfig","resolveReactStrictMode","getDevServerConfig","cliConfig","flags","httpPort","output","workDir","configSpinner","baseConfig","host","port","succeed","isApp","reactStrictMode","app","envBasePath","project","basePath","warn","bundledDev","unstable_bundledDev","log","info","entry","exposes","config","services","views","undefined","reactCompiler","staticPath","join","typegen","workbenchAppId","name"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAwBC,eAAe,QAAoB,mBAAkB;AAC7E,SAAQC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AACvD,SAAQC,cAAc,QAAO,wBAAuB;AAGpD,SAAQC,cAAc,QAAO,kCAAiC;AAC9D,SAAQC,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,sBAAsB,QAAO,0CAAyC;AAG9E,OAAO,SAASC,mBAAmB,EACjCC,SAAS,EACTC,KAAK,EACLC,QAAQ,EACRC,MAAM,EACNC,OAAO,EAOR;IACC,MAAMC,gBAAgBX,QAAQ;IAE9B,MAAMY,aAAaT,sBAAsB;QACvCG;QACAC,OAAO;YACLM,MAAMN,MAAMM,IAAI;YAChBC,MAAMP,MAAMO,IAAI;QAClB;QACAJ;IACF;IAEAC,cAAcI,OAAO;IAErB,MAAMC,QAAQV,YAAYJ,eAAeI,aAAa;IACtD,MAAMW,kBAAkBb,uBAAuBE;IAC/C,6EAA6E;IAC7E,mEAAmE;IACnE,MAAMY,MAAMZ,WAAWY;IAEvB,MAAMC,cAAcrB,gBAAgB,YAAYkB,SAAS;IACzD,IAAIG,eAAeb,WAAWc,SAASC,UAAU;QAC/CZ,OAAOa,IAAI,CACT,CAAC,iCAAiC,EAAEhB,UAAUc,OAAO,CAACC,QAAQ,CAAC,wCAAwC,EAAEF,YAAY,CAAC,CAAC;IAE3H;IAEA,+DAA+D;IAC/D,2DAA2D;IAC3D,MAAMI,aAAajB,WAAWkB,uBAAuB;IACrD,IAAID,YAAY;QACdd,OAAOgB,GAAG,CAAC,GAAG1B,WAAW2B,IAAI,CAAC,2DAA2D,CAAC;IAC5F;IAEA,OAAO;QACL,GAAGd,UAAU;QACbW;QACA,yEAAyE;QACzE,sEAAsE;QACtEI,OAAOT,KAAKS;QACZC,SAAS3B,eAAeiB,OACpB;YAACW,QAAQX,IAAIW,MAAM;YAAEC,UAAUZ,IAAIY,QAAQ;YAAEC,OAAOb,IAAIa,KAAK;QAAA,IAC7DC;QACJ,2EAA2E;QAC3E,0DAA0D;QAC1DxB,UAAUA,YAAYI,WAAWJ,QAAQ;QACzCP,gBAAgBA,eAAeiB;QAC/Be,eAAe3B,aAAa,mBAAmBA,YAAYA,UAAU2B,aAAa,GAAGD;QACrFf;QACAiB,YAAYrC,KAAKsC,IAAI,CAACzB,SAAS;QAC/B0B,SAAS9B,WAAW8B;QACpBC,gBAAgBpC,eAAeiB,OAAOA,IAAIoB,IAAI,GAAGN;IACnD;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, type Output} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp, resolveAppId} from '@sanity/workbench-cli'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views`/`services` are declared via `unstable_defineApp`, so read them off\n // the branded app result rather than the legacy `app` config type.\n const app = cliConfig?.app\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n // Unstable opt-in to Vite's experimental bundled dev mode, via\n // `unstable_bundledDev` in sanity.cli.ts. Defaults to off.\n const bundledDev = cliConfig?.unstable_bundledDev ?? false\n if (bundledDev) {\n output.log(`${logSymbols.info} Running dev server with experimental Vite bundled dev mode`)\n }\n\n return {\n ...baseConfig,\n bundledDev,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view: the runtime/federation skip the `./App` render path entirely.\n entry: app?.entry,\n exposes: isWorkbenchApp(app)\n ? {config: app.config, services: app.services, views: app.views}\n : undefined,\n // `devAction` passes an explicit port when a running workbench claimed the\n // configured one; otherwise the shared resolution stands.\n httpPort: httpPort ?? baseConfig.httpPort,\n isWorkbenchApp: isWorkbenchApp(app),\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n reactStrictMode,\n staticPath: path.join(workDir, 'static'),\n typegen: cliConfig?.typegen,\n // Inline the same id the dev registry advertises so the app's bus identity\n // matches how the workbench addresses it. The registry re-reads the bound\n // port if a non-strict shift moves it.\n workbenchAppId: isWorkbenchApp(app)\n ? resolveAppId({host: baseConfig.httpHost, port: httpPort ?? baseConfig.httpPort})\n : undefined,\n }\n}\n"],"names":["path","getSanityEnvVar","logSymbols","spinner","isWorkbenchApp","resolveAppId","determineIsApp","getSharedServerConfig","resolveReactStrictMode","getDevServerConfig","cliConfig","flags","httpPort","output","workDir","configSpinner","baseConfig","host","port","succeed","isApp","reactStrictMode","app","envBasePath","project","basePath","warn","bundledDev","unstable_bundledDev","log","info","entry","exposes","config","services","views","undefined","reactCompiler","staticPath","join","typegen","workbenchAppId","httpHost"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAwBC,eAAe,QAAoB,mBAAkB;AAC7E,SAAQC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AACvD,SAAQC,cAAc,EAAEC,YAAY,QAAO,wBAAuB;AAGlE,SAAQC,cAAc,QAAO,kCAAiC;AAC9D,SAAQC,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,sBAAsB,QAAO,0CAAyC;AAG9E,OAAO,SAASC,mBAAmB,EACjCC,SAAS,EACTC,KAAK,EACLC,QAAQ,EACRC,MAAM,EACNC,OAAO,EAOR;IACC,MAAMC,gBAAgBZ,QAAQ;IAE9B,MAAMa,aAAaT,sBAAsB;QACvCG;QACAC,OAAO;YACLM,MAAMN,MAAMM,IAAI;YAChBC,MAAMP,MAAMO,IAAI;QAClB;QACAJ;IACF;IAEAC,cAAcI,OAAO;IAErB,MAAMC,QAAQV,YAAYJ,eAAeI,aAAa;IACtD,MAAMW,kBAAkBb,uBAAuBE;IAC/C,6EAA6E;IAC7E,mEAAmE;IACnE,MAAMY,MAAMZ,WAAWY;IAEvB,MAAMC,cAActB,gBAAgB,YAAYmB,SAAS;IACzD,IAAIG,eAAeb,WAAWc,SAASC,UAAU;QAC/CZ,OAAOa,IAAI,CACT,CAAC,iCAAiC,EAAEhB,UAAUc,OAAO,CAACC,QAAQ,CAAC,wCAAwC,EAAEF,YAAY,CAAC,CAAC;IAE3H;IAEA,+DAA+D;IAC/D,2DAA2D;IAC3D,MAAMI,aAAajB,WAAWkB,uBAAuB;IACrD,IAAID,YAAY;QACdd,OAAOgB,GAAG,CAAC,GAAG3B,WAAW4B,IAAI,CAAC,2DAA2D,CAAC;IAC5F;IAEA,OAAO;QACL,GAAGd,UAAU;QACbW;QACA,yEAAyE;QACzE,sEAAsE;QACtEI,OAAOT,KAAKS;QACZC,SAAS5B,eAAekB,OACpB;YAACW,QAAQX,IAAIW,MAAM;YAAEC,UAAUZ,IAAIY,QAAQ;YAAEC,OAAOb,IAAIa,KAAK;QAAA,IAC7DC;QACJ,2EAA2E;QAC3E,0DAA0D;QAC1DxB,UAAUA,YAAYI,WAAWJ,QAAQ;QACzCR,gBAAgBA,eAAekB;QAC/Be,eAAe3B,aAAa,mBAAmBA,YAAYA,UAAU2B,aAAa,GAAGD;QACrFf;QACAiB,YAAYtC,KAAKuC,IAAI,CAACzB,SAAS;QAC/B0B,SAAS9B,WAAW8B;QACpB,2EAA2E;QAC3E,0EAA0E;QAC1E,uCAAuC;QACvCC,gBAAgBrC,eAAekB,OAC3BjB,aAAa;YAACY,MAAMD,WAAW0B,QAAQ;YAAExB,MAAMN,YAAYI,WAAWJ,QAAQ;QAAA,KAC9EwB;IACN;AACF"}
@@ -1,10 +1,10 @@
1
1
  import { CLIError } from '@oclif/core/errors';
2
- import { isInteractive } from '@sanity/cli-core';
2
+ import { exitCodes } from '@sanity/cli-core';
3
3
  import { confirm } from '@sanity/cli-core/ux';
4
4
  import { oneline } from 'oneline';
5
5
  import { graphqlDebug } from './graphqlDebug.js';
6
6
  const LATEST_GENERATION = 'gen3';
7
- export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration }) {
7
+ export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration, unattended }) {
8
8
  // a) If no API is currently deployed:
9
9
  // use the specificed one from config, or use whichever generation is the latest
10
10
  // b) If an API generation is specified explicitly:
@@ -17,12 +17,12 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
17
17
  return generation;
18
18
  }
19
19
  if (specifiedGeneration && specifiedGeneration !== currentGeneration) {
20
- if (!force && !isInteractive()) {
20
+ if (!force && unattended) {
21
21
  throw new CLIError(oneline`
22
22
  Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).
23
- Re-run the command with \`--force\` to force deployment.
23
+ Pass \`--force\` to continue.
24
24
  `, {
25
- exit: 1
25
+ exit: exitCodes.USAGE_ERROR
26
26
  });
27
27
  }
28
28
  output.warn(`Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`);
@@ -30,7 +30,10 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
30
30
  default: false,
31
31
  message: 'Are you sure you want to deploy?'
32
32
  });
33
- return confirmDeploy ? specifiedGeneration : undefined;
33
+ if (!confirmDeploy) {
34
+ return undefined;
35
+ }
36
+ return specifiedGeneration;
34
37
  }
35
38
  if (specifiedGeneration) {
36
39
  graphqlDebug('Using specified (%s) generation', specifiedGeneration);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {isInteractive, type Output} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {graphqlDebug} from './graphqlDebug.js'\n\nconst LATEST_GENERATION = 'gen3'\n\nexport async function resolveApiGeneration({\n currentGeneration,\n force,\n index,\n output,\n specifiedGeneration,\n}: {\n currentGeneration?: string\n force?: boolean\n index: number\n output: Output\n specifiedGeneration?: string\n}): Promise<string | undefined> {\n // a) If no API is currently deployed:\n // use the specificed one from config, or use whichever generation is the latest\n // b) If an API generation is specified explicitly:\n // use the given one, but _prompt_ if it differs from the current one\n // c) If no API generation is specified explicitly:\n // use whichever is already deployed, but warn if differs from latest\n if (!currentGeneration) {\n const generation = specifiedGeneration || LATEST_GENERATION\n graphqlDebug(\n 'There is no current generation deployed, using %s (%s)',\n generation,\n specifiedGeneration ? 'specified' : 'default',\n )\n return generation\n }\n\n if (specifiedGeneration && specifiedGeneration !== currentGeneration) {\n if (!force && !isInteractive()) {\n throw new CLIError(\n oneline`\n Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).\n Re-run the command with \\`--force\\` to force deployment.\n `,\n {exit: 1},\n )\n }\n\n output.warn(\n `Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`,\n )\n\n const confirmDeploy =\n force ||\n (await confirm({\n default: false,\n message: 'Are you sure you want to deploy?',\n }))\n\n return confirmDeploy ? specifiedGeneration : undefined\n }\n\n if (specifiedGeneration) {\n graphqlDebug('Using specified (%s) generation', specifiedGeneration)\n return specifiedGeneration\n }\n\n graphqlDebug('Using the currently deployed version (%s)', currentGeneration)\n return currentGeneration\n}\n"],"names":["CLIError","isInteractive","confirm","oneline","graphqlDebug","LATEST_GENERATION","resolveApiGeneration","currentGeneration","force","index","output","specifiedGeneration","generation","exit","warn","confirmDeploy","default","message","undefined"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,aAAa,QAAoB,mBAAkB;AAC3D,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,YAAY,QAAO,oBAAmB;AAE9C,MAAMC,oBAAoB;AAE1B,OAAO,eAAeC,qBAAqB,EACzCC,iBAAiB,EACjBC,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,mBAAmB,EAOpB;IACC,sCAAsC;IACtC,mFAAmF;IACnF,mDAAmD;IACnD,wEAAwE;IACxE,mDAAmD;IACnD,wEAAwE;IACxE,IAAI,CAACJ,mBAAmB;QACtB,MAAMK,aAAaD,uBAAuBN;QAC1CD,aACE,0DACAQ,YACAD,sBAAsB,cAAc;QAEtC,OAAOC;IACT;IAEA,IAAID,uBAAuBA,wBAAwBJ,mBAAmB;QACpE,IAAI,CAACC,SAAS,CAACP,iBAAiB;YAC9B,MAAM,IAAID,SACRG,OAAO,CAAC;8BACc,EAAEQ,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB;;MAEvI,CAAC,EACC;gBAACM,MAAM;YAAC;QAEZ;QAEAH,OAAOI,IAAI,CACT,CAAC,sBAAsB,EAAEH,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB,EAAE,CAAC;QAG3I,MAAMQ,gBACJP,SACC,MAAMN,QAAQ;YACbc,SAAS;YACTC,SAAS;QACX;QAEF,OAAOF,gBAAgBJ,sBAAsBO;IAC/C;IAEA,IAAIP,qBAAqB;QACvBP,aAAa,mCAAmCO;QAChD,OAAOA;IACT;IAEAP,aAAa,6CAA6CG;IAC1D,OAAOA;AACT"}
1
+ {"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {exitCodes, type Output} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {graphqlDebug} from './graphqlDebug.js'\n\nconst LATEST_GENERATION = 'gen3'\n\nexport async function resolveApiGeneration({\n currentGeneration,\n force,\n index,\n output,\n specifiedGeneration,\n unattended,\n}: {\n currentGeneration?: string\n force?: boolean\n index: number\n output: Output\n specifiedGeneration?: string\n unattended: boolean\n}): Promise<string | undefined> {\n // a) If no API is currently deployed:\n // use the specificed one from config, or use whichever generation is the latest\n // b) If an API generation is specified explicitly:\n // use the given one, but _prompt_ if it differs from the current one\n // c) If no API generation is specified explicitly:\n // use whichever is already deployed, but warn if differs from latest\n if (!currentGeneration) {\n const generation = specifiedGeneration || LATEST_GENERATION\n graphqlDebug(\n 'There is no current generation deployed, using %s (%s)',\n generation,\n specifiedGeneration ? 'specified' : 'default',\n )\n return generation\n }\n\n if (specifiedGeneration && specifiedGeneration !== currentGeneration) {\n if (!force && unattended) {\n throw new CLIError(\n oneline`\n Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).\n Pass \\`--force\\` to continue.\n `,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n output.warn(\n `Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`,\n )\n\n const confirmDeploy =\n force ||\n (await confirm({\n default: false,\n message: 'Are you sure you want to deploy?',\n }))\n\n if (!confirmDeploy) {\n return undefined\n }\n\n return specifiedGeneration\n }\n\n if (specifiedGeneration) {\n graphqlDebug('Using specified (%s) generation', specifiedGeneration)\n return specifiedGeneration\n }\n\n graphqlDebug('Using the currently deployed version (%s)', currentGeneration)\n return currentGeneration\n}\n"],"names":["CLIError","exitCodes","confirm","oneline","graphqlDebug","LATEST_GENERATION","resolveApiGeneration","currentGeneration","force","index","output","specifiedGeneration","unattended","generation","exit","USAGE_ERROR","warn","confirmDeploy","default","message","undefined"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,QAAoB,mBAAkB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,YAAY,QAAO,oBAAmB;AAE9C,MAAMC,oBAAoB;AAE1B,OAAO,eAAeC,qBAAqB,EACzCC,iBAAiB,EACjBC,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,mBAAmB,EACnBC,UAAU,EAQX;IACC,sCAAsC;IACtC,mFAAmF;IACnF,mDAAmD;IACnD,wEAAwE;IACxE,mDAAmD;IACnD,wEAAwE;IACxE,IAAI,CAACL,mBAAmB;QACtB,MAAMM,aAAaF,uBAAuBN;QAC1CD,aACE,0DACAS,YACAF,sBAAsB,cAAc;QAEtC,OAAOE;IACT;IAEA,IAAIF,uBAAuBA,wBAAwBJ,mBAAmB;QACpE,IAAI,CAACC,SAASI,YAAY;YACxB,MAAM,IAAIZ,SACRG,OAAO,CAAC;8BACc,EAAEQ,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB;;MAEvI,CAAC,EACC;gBAACO,MAAMb,UAAUc,WAAW;YAAA;QAEhC;QAEAL,OAAOM,IAAI,CACT,CAAC,sBAAsB,EAAEL,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB,EAAE,CAAC;QAG3I,MAAMU,gBACJT,SACC,MAAMN,QAAQ;YACbgB,SAAS;YACTC,SAAS;QACX;QAEF,IAAI,CAACF,eAAe;YAClB,OAAOG;QACT;QAEA,OAAOT;IACT;IAEA,IAAIA,qBAAqB;QACvBP,aAAa,mCAAmCO;QAChD,OAAOA;IACT;IAEAP,aAAa,6CAA6CG;IAC1D,OAAOA;AACT"}
@@ -64,12 +64,7 @@ export async function bootstrapLocalTemplate(opts) {
64
64
  ...isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies,
65
65
  ...isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies,
66
66
  ...template.dependencies,
67
- ...template.devDependencies,
68
- // `unstable_defineApp` (re-exported via `sanity/cli`) only exists on the
69
- // workbench dist-tag of `sanity`.
70
- ...variables.workbench && {
71
- sanity: 'workbench'
72
- }
67
+ ...template.devDependencies
73
68
  });
74
69
  spin.succeed();
75
70
  // Use the resolved version for the given dependency
@@ -91,8 +86,17 @@ export async function bootstrapLocalTemplate(opts) {
91
86
  /**
92
87
  * Currently app init doesn't ask for a name, so we use the last part of the path
93
88
  */ if (isAppTemplate) {
94
- packageJsonName = deburr(path.basename(outputPath).toLowerCase()).replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '');
89
+ packageJsonName = slugify(path.basename(outputPath));
95
90
  }
91
+ const title = variables.projectName || packageJsonName;
92
+ // Default the workbench app `slug` (the hostname the application is created
93
+ // at on deploy). App init never asks for a name (`variables.projectName` is
94
+ // just the cwd basename there), so apps follow their identity — the
95
+ // output-path basename (`packageJsonName`) — while studios slug the entered
96
+ // project name. Fall back to a constant when the source slugifies to
97
+ // nothing (e.g. a fully non-latin name): an empty `slug` fails app config
98
+ // validation, which is exactly what pre-filling it is meant to avoid.
99
+ const slug = (isAppTemplate ? packageJsonName : slugify(title)) || 'sanity-app';
96
100
  // Now create a package manifest (`package.json`) with the merged dependencies
97
101
  spin = spinner('Creating default project files').start();
98
102
  const packageManifest = createPackageManifest({
@@ -114,7 +118,8 @@ export async function bootstrapLocalTemplate(opts) {
114
118
  isWorkbenchApp: variables.workbench,
115
119
  name: packageJsonName,
116
120
  organizationId: variables.organizationId,
117
- title: variables.projectName || packageJsonName
121
+ slug,
122
+ title
118
123
  }) : createCliConfig({
119
124
  autoUpdates: variables.autoUpdates,
120
125
  dataset: variables.dataset,
@@ -122,7 +127,8 @@ export async function bootstrapLocalTemplate(opts) {
122
127
  name: packageJsonName,
123
128
  organizationId: variables.organizationId,
124
129
  projectId: variables.projectId,
125
- title: variables.projectName || packageJsonName
130
+ slug,
131
+ title
126
132
  });
127
133
  // Write non-template files to disc
128
134
  const codeExt = useTypeScript ? 'ts' : 'js';
@@ -162,5 +168,8 @@ export async function bootstrapLocalTemplate(opts) {
162
168
  function toTypeScriptPath(originalPath) {
163
169
  return originalPath.replace(/\.js$/, '.ts');
164
170
  }
171
+ /** Lowercase, deburred, spaces to hyphens, everything else stripped. */ function slugify(value) {
172
+ return deburr(value.toLowerCase()).replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '');
173
+ }
165
174
 
166
175
  //# sourceMappingURL=bootstrapLocalTemplate.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.dependencies,\n ...template.devDependencies,\n // `unstable_defineApp` (re-exported via `sanity/cli`) only exists on the\n // workbench dist-tag of `sanity`.\n ...(variables.workbench && {sanity: 'workbench'}),\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate) {\n packageJsonName = deburr(path.basename(outputPath).toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n }\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n isAppTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`)\n const studioConfig = createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n const cliConfig = isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n title: variables.projectName || packageJsonName,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n projectId: variables.projectId,\n title: variables.projectName || packageJsonName,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n isAppTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","template","Error","spin","start","rename","toTypeScriptPath","undefined","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependencies","devDependencies","workbench","sanity","dependency","Object","keys","packageJsonName","basename","toLowerCase","replaceAll","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","isWorkbenchApp","organizationId","title","projectName","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.dependencies,\n ...template.devDependencies,\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate) {\n packageJsonName = slugify(path.basename(outputPath))\n }\n\n const title = variables.projectName || packageJsonName\n // Default the workbench app `slug` (the hostname the application is created\n // at on deploy). App init never asks for a name (`variables.projectName` is\n // just the cwd basename there), so apps follow their identity — the\n // output-path basename (`packageJsonName`) — while studios slug the entered\n // project name. Fall back to a constant when the source slugifies to\n // nothing (e.g. a fully non-latin name): an empty `slug` fails app config\n // validation, which is exactly what pre-filling it is meant to avoid.\n const slug = (isAppTemplate ? packageJsonName : slugify(title)) || 'sanity-app'\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n isAppTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`)\n const studioConfig = createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n const cliConfig = isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n slug,\n title,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n projectId: variables.projectId,\n slug,\n title,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n isAppTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n\n/** Lowercase, deburred, spaces to hyphens, everything else stripped. */\nfunction slugify(value: string): string {\n return deburr(value.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","template","Error","spin","start","rename","toTypeScriptPath","undefined","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependencies","devDependencies","dependency","Object","keys","packageJsonName","slugify","basename","title","projectName","slug","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","isWorkbenchApp","workbench","organizationId","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace","value","toLowerCase","replaceAll"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/createAppCliConfig.ts"],"sourcesContent":["import {workbenchAppConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultAppTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n app: {\n organizationId: '%organizationId%',\n entry: '%entry%',\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n entry: string\n isWorkbenchApp: boolean\n name: string\n title: string\n\n organizationId?: string\n}\n\nexport function createAppCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchAppConfigTemplate : defaultAppTemplate,\n variables,\n })\n}\n"],"names":["workbenchAppConfigTemplate","processTemplate","defaultAppTemplate","createAppCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,6BAA4B;AAErE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,qBAAqB,CAAC;;;;;;;;;AAS5B,CAAC;AAWD,OAAO,SAASC,mBAAmBC,OAAiC;IAClE,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,6BAA6BE;QACxDI;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/init/createAppCliConfig.ts"],"sourcesContent":["import {workbenchAppConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultAppTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n app: {\n organizationId: '%organizationId%',\n entry: '%entry%',\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n entry: string\n isWorkbenchApp: boolean\n name: string\n slug: string\n title: string\n\n organizationId?: string\n}\n\nexport function createAppCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchAppConfigTemplate : defaultAppTemplate,\n variables,\n })\n}\n"],"names":["workbenchAppConfigTemplate","processTemplate","defaultAppTemplate","createAppCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,6BAA4B;AAErE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,qBAAqB,CAAC;;;;;;;;;AAS5B,CAAC;AAYD,OAAO,SAASC,mBAAmBC,OAAiC;IAClE,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,6BAA6BE;QACxDI;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/createCliConfig.ts"],"sourcesContent":["import {workbenchStudioConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '%projectId%',\n dataset: '%dataset%'\n },\n deployment: {\n /**\n * Enable auto-updates for studios.\n * Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56\n */\n autoUpdates: __BOOL__autoUpdates__,\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n autoUpdates: boolean\n dataset: string\n isWorkbenchApp: boolean\n name: string\n projectId: string\n title: string\n\n organizationId?: string\n}\n\nexport function createCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchStudioConfigTemplate : defaultTemplate,\n variables,\n })\n}\n"],"names":["workbenchStudioConfigTemplate","processTemplate","defaultTemplate","createCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,6BAA4B;AAExE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;;;;AAgBzB,CAAC;AAaD,OAAO,SAASC,gBAAgBC,OAAiC;IAC/D,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,gCAAgCE;QAC3DI;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/init/createCliConfig.ts"],"sourcesContent":["import {workbenchStudioConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '%projectId%',\n dataset: '%dataset%'\n },\n deployment: {\n /**\n * Enable auto-updates for studios.\n * Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56\n */\n autoUpdates: __BOOL__autoUpdates__,\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n autoUpdates: boolean\n dataset: string\n isWorkbenchApp: boolean\n name: string\n projectId: string\n slug: string\n title: string\n\n organizationId?: string\n}\n\nexport function createCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchStudioConfigTemplate : defaultTemplate,\n variables,\n })\n}\n"],"names":["workbenchStudioConfigTemplate","processTemplate","defaultTemplate","createCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,6BAA4B;AAExE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;;;;AAgBzB,CAAC;AAcD,OAAO,SAASC,gBAAgBC,OAAiC;IAC/D,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,gCAAgCE;QAC3DI;IACF;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { styleText } from 'node:util';
2
- import { subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, subdebug } from '@sanity/cli-core';
3
3
  import { logSymbols, spinner } from '@sanity/cli-core/ux';
4
4
  import { frameworks } from '@vercel/frameworks';
5
5
  import deburr from 'lodash-es/deburr.js';
@@ -7,10 +7,12 @@ import { promptForConfigFiles } from '../../prompts/init/nextjs.js';
7
7
  import { getCliUser } from '../../services/user.js';
8
8
  import { CLIInitStepCompleted } from '../../telemetry/init.telemetry.js';
9
9
  import { detectFrameworkRecord } from '../../util/detectFramework.js';
10
+ import { formatCliErrorMessages } from '../../util/formatCliErrorMessages.js';
10
11
  import { getProjectDefaults } from '../../util/getProjectDefaults.js';
11
12
  import { validateSession } from '../auth/ensureAuthenticated.js';
12
13
  import { getProviderName } from '../auth/getProviderName.js';
13
14
  import { login } from '../auth/login/login.js';
15
+ import { LOGIN_REQUIRED_MESSAGE } from '../auth/login/loginInstructions.js';
14
16
  import { detectAvailableEditors } from '../mcp/detectAvailableEditors.js';
15
17
  import { setupMCP } from '../mcp/setupMCP.js';
16
18
  import { setupSkills } from '../skills/setupSkills.js';
@@ -268,24 +270,29 @@ export async function initAction(options, context) {
268
270
  }
269
271
  function checkFlagsInUnattendedMode(options, { isAppTemplate, isNextJs }) {
270
272
  debug('Unattended mode, validating required options');
271
- if (options.projectName && !options.organization) {
272
- throw new InitError('`--project-name` requires `--organization <id>` in unattended mode', 1);
273
- }
273
+ const errors = [];
274
274
  if (isAppTemplate) {
275
275
  if (!options.outputPath) {
276
- throw new InitError('`--output-path` must be specified in unattended mode', 1);
276
+ errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
277
277
  }
278
- const hasProjectFlag = Boolean(options.project || options.projectName);
279
- if (!hasProjectFlag && !options.organization) {
280
- throw new InitError('The --organization flag is required for app templates in unattended mode. ' + 'Use --organization <id>, or pass --project <id> / --project-name <name>.', 1);
278
+ if (options.projectName && !options.organization) {
279
+ errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
280
+ } else if (!options.project && !options.organization) {
281
+ errors.push('Project or organization is required for app templates in unattended mode. ' + 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' + '`--project-name <name>` with `--organization <id>`.');
282
+ }
283
+ } else {
284
+ if (!isNextJs && !options.bare && !options.outputPath) {
285
+ errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
286
+ }
287
+ if (!options.project && !options.projectName) {
288
+ errors.push('Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.');
289
+ }
290
+ if (!options.project && !options.organization) {
291
+ errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
281
292
  }
282
- return;
283
- }
284
- if (!isNextJs && !options.bare && !options.outputPath) {
285
- throw new InitError('`--output-path` must be specified in unattended mode', 1);
286
293
  }
287
- if (!options.project && !options.projectName) {
288
- throw new InitError('`--project <id>` or `--project-name <name>` must be specified in unattended mode', 1);
294
+ if (errors.length > 0) {
295
+ throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR);
289
296
  }
290
297
  }
291
298
  async function ensureAuthenticated(options, output, trace) {
@@ -301,11 +308,12 @@ async function ensureAuthenticated(options, output, trace) {
301
308
  };
302
309
  }
303
310
  if (options.unattended) {
304
- throw new InitError('Must be logged in to run this command in unattended mode, run `sanity login`', 1);
311
+ throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR);
305
312
  }
306
313
  trace.log({
307
314
  step: 'login'
308
315
  });
316
+ output.warn(LOGIN_REQUIRED_MESSAGE);
309
317
  try {
310
318
  await login({
311
319
  output,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type SanityOrgUser, subdebug, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n if (options.project && options.organization) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template ? determineAppTemplate(options.template) : false\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n if (options.projectName) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({agents: mcpResult.skillsToInstall, output})\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n const sluggedName = deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // Workbench is opt-in (no prompt): the flag swaps the scaffolded\n // `sanity.cli.*` over to `unstable_defineApp` — the branded app is the sole\n // workbench opt-in.\n const workbench = flagOrDefault(options.unstableWorkbench, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {isAppTemplate, isNextJs}: {isAppTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n if (options.projectName && !options.organization) {\n throw new InitError('`--project-name` requires `--organization <id>` in unattended mode', 1)\n }\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n throw new InitError('`--output-path` must be specified in unattended mode', 1)\n }\n\n const hasProjectFlag = Boolean(options.project || options.projectName)\n\n if (!hasProjectFlag && !options.organization) {\n throw new InitError(\n 'The --organization flag is required for app templates in unattended mode. ' +\n 'Use --organization <id>, or pass --project <id> / --project-name <name>.',\n 1,\n )\n }\n\n return\n }\n\n if (!isNextJs && !options.bare && !options.outputPath) {\n throw new InitError('`--output-path` must be specified in unattended mode', 1)\n }\n\n if (!options.project && !options.projectName) {\n throw new InitError(\n '`--project <id>` or `--project-name <name>` must be specified in unattended mode',\n 1,\n )\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${user.email} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(\n 'Must be logged in to run this command in unattended mode, run `sanity login`',\n 1,\n )\n }\n\n trace.log({step: 'login'})\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${loggedInUser.email} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","getProjectDefaults","validateSession","getProviderName","login","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","template","templateToken","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","warn","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","unstableWorkbench","sharedParams","hasProjectFlag","alreadyLoggedIn","email","provider","newContext","loggedInUser"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n exitCodes,\n type SanityOrgUser,\n subdebug,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {LOGIN_REQUIRED_MESSAGE} from '../auth/login/loginInstructions.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n if (options.project && options.organization) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template ? determineAppTemplate(options.template) : false\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n if (options.projectName) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({\n agents: mcpResult.skillsToInstall,\n output,\n })\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n const sluggedName = deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // Workbench is opt-in (no prompt): the flag swaps the scaffolded\n // `sanity.cli.*` over to `unstable_defineApp` — the branded app is the sole\n // workbench opt-in.\n const workbench = flagOrDefault(options.unstableWorkbench, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {isAppTemplate, isNextJs}: {isAppTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n const errors: string[] = []\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (options.projectName && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n } else if (!options.project && !options.organization) {\n errors.push(\n 'Project or organization is required for app templates in unattended mode. ' +\n 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' +\n '`--project-name <name>` with `--organization <id>`.',\n )\n }\n } else {\n if (!isNextJs && !options.bare && !options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (!options.project && !options.projectName) {\n errors.push(\n 'Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.',\n )\n }\n\n if (!options.project && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n }\n }\n\n if (errors.length > 0) {\n throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR)\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${user.email} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR)\n }\n\n trace.log({step: 'login'})\n output.warn(LOGIN_REQUIRED_MESSAGE)\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${loggedInUser.email} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","exitCodes","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","formatCliErrorMessages","getProjectDefaults","validateSession","getProviderName","login","LOGIN_REQUIRED_MESSAGE","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","template","templateToken","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","warn","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","unstableWorkbench","sharedParams","errors","push","USAGE_ERROR","alreadyLoggedIn","email","provider","RUNTIME_ERROR","newContext","loggedInUser"],"mappings":"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"}
@@ -31,13 +31,15 @@ const sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href;
31
31
  return mod.sanitizeIcon;
32
32
  }
33
33
  /**
34
- * Resolves app.icon from config (a file path) to an SVG string for the manifest.
35
- * The manifest expects the SVG string inline, not a path.
34
+ * Resolves app.icon from config (a file path) to a sanitized SVG string. Used
35
+ * both for the manifest and, on deploy, for the icon shipped to Brett the
36
+ * manifest expects the SVG inline, not a path.
36
37
  *
37
38
  * The file is sanitized through the same allowlist as the studio manifest's
38
39
  * icon resolver (see {@link lazySanitizeIcon}) so both manifest paths inline the
39
40
  * same trusted subset of SVG markup.
40
- */ async function readIconFromPath(workDir, iconPath) {
41
+ * @internal
42
+ */ export async function readIconFromPath(workDir, iconPath) {
41
43
  const resolvedPath = resolve(workDir, iconPath);
42
44
  const pathRelativeToWorkDir = relative(workDir, resolvedPath);
43
45
  if (pathRelativeToWorkDir.startsWith('..')) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/manifest/extractCoreAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {doImport, getCliConfigUncached} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type sanitizeIcon as sanitizeIconFn} from './sanitizeIcon.js'\nimport {type CoreAppManifest, coreAppManifestSchema} from './types.js'\n\ninterface ExtractCoreAppManifestOptions {\n workDir: string\n}\n\n/**\n * The title change a deploy would sync from the manifest to the user\n * application, or null when the titles already match (or none is set).\n *\n * @internal\n */\nexport function resolveTitleUpdate(\n manifest: CoreAppManifest | undefined,\n application: {title: string | null},\n): {from: string | null; to: string} | null {\n if (manifest?.title === undefined || manifest.title === application.title) {\n return null\n }\n return {from: application.title, to: manifest.title}\n}\n\nconst sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href\n\n/**\n * Lazy-load {@link sanitizeIconFn} so `isomorphic-dompurify` (and its jsdom\n * dependency) stays out of the CLI's eager import graph. The studio manifest\n * resolver lazy-loads its icon machinery for the same reason; this path runs in\n * the main process (not the manifest worker), so only an app deploy that\n * actually has an icon pays the cost.\n */\nasync function lazySanitizeIcon(): Promise<typeof sanitizeIconFn> {\n const mod = await doImport(sanitizeIconPath)\n return mod.sanitizeIcon\n}\n\n/**\n * Resolves app.icon from config (a file path) to an SVG string for the manifest.\n * The manifest expects the SVG string inline, not a path.\n *\n * The file is sanitized through the same allowlist as the studio manifest's\n * icon resolver (see {@link lazySanitizeIcon}) so both manifest paths inline the\n * same trusted subset of SVG markup.\n */\nasync function readIconFromPath(workDir: string, iconPath: string): Promise<string> {\n const resolvedPath = resolve(workDir, iconPath)\n const pathRelativeToWorkDir = relative(workDir, resolvedPath)\n if (pathRelativeToWorkDir.startsWith('..')) {\n throw new Error(\n `Icon path \"${iconPath}\" resolves outside the project directory and is not allowed.`,\n )\n }\n\n let content: string\n try {\n content = await readFile(resolvedPath, 'utf8')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Could not read icon file at \"${iconPath}\" (resolved: ${resolvedPath}): ${message}`,\n {cause: err},\n )\n }\n\n const trimmed = content.trim()\n if (!/<svg[\\s>]/i.test(trimmed)) {\n throw new Error(\n `Icon file at \"${iconPath}\" does not contain an SVG element. App manifest icons must be SVG files.`,\n )\n }\n\n const sanitizeIcon = await lazySanitizeIcon()\n return sanitizeIcon(trimmed)\n}\n\n/**\n * Unlike studio manifest extraction, skips schema/tool parsing. The config's\n * `app.icon` is a file path; its content is read and inlined in the manifest.\n */\nexport async function extractCoreAppManifest(\n options: ExtractCoreAppManifestOptions,\n): Promise<CoreAppManifest | undefined> {\n const {workDir} = options\n const {app} = await getCliConfigUncached(workDir)\n if (!app) {\n return undefined\n }\n\n const spin = spinner('Extracting manifest').start()\n\n try {\n let icon: string | undefined\n if (app.icon) {\n icon = await readIconFromPath(workDir, app.icon)\n }\n\n if (!icon && !app.title) {\n spin.info('Manifest creation skipped: no icon or title found in app configuration')\n return undefined\n }\n\n const slug = isWorkbenchApp(app) ? app.slug : undefined\n\n const manifest: CoreAppManifest = coreAppManifestSchema.parse({\n version: '1',\n ...(icon ? {icon} : {}),\n ...(app.title ? {title: app.title} : {}),\n ...(app.group ? {group: app.group} : {}),\n ...(app.priority === undefined ? {} : {priority: app.priority}),\n ...(slug ? {slug} : {}),\n })\n\n spin.succeed(`Extracted manifest`)\n\n return manifest\n } catch (err) {\n const message = getErrorMessage(err)\n spin.fail(message)\n throw err\n }\n}\n"],"names":["readFile","relative","resolve","doImport","getCliConfigUncached","getErrorMessage","spinner","isWorkbenchApp","coreAppManifestSchema","resolveTitleUpdate","manifest","application","title","undefined","from","to","sanitizeIconPath","URL","url","href","lazySanitizeIcon","mod","sanitizeIcon","readIconFromPath","workDir","iconPath","resolvedPath","pathRelativeToWorkDir","startsWith","Error","content","err","message","String","cause","trimmed","trim","test","extractCoreAppManifest","options","app","spin","start","icon","info","slug","parse","version","group","priority","succeed","fail"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/manifest/extractCoreAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {doImport, getCliConfigUncached} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type sanitizeIcon as sanitizeIconFn} from './sanitizeIcon.js'\nimport {type CoreAppManifest, coreAppManifestSchema} from './types.js'\n\ninterface ExtractCoreAppManifestOptions {\n workDir: string\n}\n\n/**\n * The title change a deploy would sync from the manifest to the user\n * application, or null when the titles already match (or none is set).\n *\n * @internal\n */\nexport function resolveTitleUpdate(\n manifest: CoreAppManifest | undefined,\n application: {title: string | null},\n): {from: string | null; to: string} | null {\n if (manifest?.title === undefined || manifest.title === application.title) {\n return null\n }\n return {from: application.title, to: manifest.title}\n}\n\nconst sanitizeIconPath = new URL('sanitizeIcon.js', import.meta.url).href\n\n/**\n * Lazy-load {@link sanitizeIconFn} so `isomorphic-dompurify` (and its jsdom\n * dependency) stays out of the CLI's eager import graph. The studio manifest\n * resolver lazy-loads its icon machinery for the same reason; this path runs in\n * the main process (not the manifest worker), so only an app deploy that\n * actually has an icon pays the cost.\n */\nasync function lazySanitizeIcon(): Promise<typeof sanitizeIconFn> {\n const mod = await doImport(sanitizeIconPath)\n return mod.sanitizeIcon\n}\n\n/**\n * Resolves app.icon from config (a file path) to a sanitized SVG string. Used\n * both for the manifest and, on deploy, for the icon shipped to Brett — the\n * manifest expects the SVG inline, not a path.\n *\n * The file is sanitized through the same allowlist as the studio manifest's\n * icon resolver (see {@link lazySanitizeIcon}) so both manifest paths inline the\n * same trusted subset of SVG markup.\n * @internal\n */\nexport async function readIconFromPath(workDir: string, iconPath: string): Promise<string> {\n const resolvedPath = resolve(workDir, iconPath)\n const pathRelativeToWorkDir = relative(workDir, resolvedPath)\n if (pathRelativeToWorkDir.startsWith('..')) {\n throw new Error(\n `Icon path \"${iconPath}\" resolves outside the project directory and is not allowed.`,\n )\n }\n\n let content: string\n try {\n content = await readFile(resolvedPath, 'utf8')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Could not read icon file at \"${iconPath}\" (resolved: ${resolvedPath}): ${message}`,\n {cause: err},\n )\n }\n\n const trimmed = content.trim()\n if (!/<svg[\\s>]/i.test(trimmed)) {\n throw new Error(\n `Icon file at \"${iconPath}\" does not contain an SVG element. App manifest icons must be SVG files.`,\n )\n }\n\n const sanitizeIcon = await lazySanitizeIcon()\n return sanitizeIcon(trimmed)\n}\n\n/**\n * Unlike studio manifest extraction, skips schema/tool parsing. The config's\n * `app.icon` is a file path; its content is read and inlined in the manifest.\n */\nexport async function extractCoreAppManifest(\n options: ExtractCoreAppManifestOptions,\n): Promise<CoreAppManifest | undefined> {\n const {workDir} = options\n const {app} = await getCliConfigUncached(workDir)\n if (!app) {\n return undefined\n }\n\n const spin = spinner('Extracting manifest').start()\n\n try {\n let icon: string | undefined\n if (app.icon) {\n icon = await readIconFromPath(workDir, app.icon)\n }\n\n if (!icon && !app.title) {\n spin.info('Manifest creation skipped: no icon or title found in app configuration')\n return undefined\n }\n\n const slug = isWorkbenchApp(app) ? app.slug : undefined\n\n const manifest: CoreAppManifest = coreAppManifestSchema.parse({\n version: '1',\n ...(icon ? {icon} : {}),\n ...(app.title ? {title: app.title} : {}),\n ...(app.group ? {group: app.group} : {}),\n ...(app.priority === undefined ? {} : {priority: app.priority}),\n ...(slug ? {slug} : {}),\n })\n\n spin.succeed(`Extracted manifest`)\n\n return manifest\n } catch (err) {\n const message = getErrorMessage(err)\n spin.fail(message)\n throw err\n }\n}\n"],"names":["readFile","relative","resolve","doImport","getCliConfigUncached","getErrorMessage","spinner","isWorkbenchApp","coreAppManifestSchema","resolveTitleUpdate","manifest","application","title","undefined","from","to","sanitizeIconPath","URL","url","href","lazySanitizeIcon","mod","sanitizeIcon","readIconFromPath","workDir","iconPath","resolvedPath","pathRelativeToWorkDir","startsWith","Error","content","err","message","String","cause","trimmed","trim","test","extractCoreAppManifest","options","app","spin","start","icon","info","slug","parse","version","group","priority","succeed","fail"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export const MIGRATIONS_DIRECTORY = 'migrations';
2
+ export const MIGRATION_SCRIPT_EXTENSIONS = [
3
+ 'mjs',
4
+ 'js',
5
+ 'ts',
6
+ 'cjs'
7
+ ];
8
+ export const DEFAULT_API_VERSION = 'v2024-01-29';
9
+
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/migration/constants.ts"],"sourcesContent":["export const MIGRATIONS_DIRECTORY = 'migrations'\nexport const MIGRATION_SCRIPT_EXTENSIONS = ['mjs', 'js', 'ts', 'cjs']\nexport const DEFAULT_API_VERSION = 'v2024-01-29'\n"],"names":["MIGRATIONS_DIRECTORY","MIGRATION_SCRIPT_EXTENSIONS","DEFAULT_API_VERSION"],"mappings":"AAAA,OAAO,MAAMA,uBAAuB,aAAY;AAChD,OAAO,MAAMC,8BAA8B;IAAC;IAAO;IAAM;IAAM;CAAM,CAAA;AACrE,OAAO,MAAMC,sBAAsB,cAAa"}
@@ -0,0 +1,16 @@
1
+ const VERSION_PATTERN = /^v\d+-\d+-\d+$|^vX$/ // Matches version strings like vYYYY-MM-DD or vX
2
+ ;
3
+ /**
4
+ * Ensures that the provided API version string is in the correct format.
5
+ * If the version does not start with 'v', it will be prefixed with 'v'.
6
+ * If the version does not match the expected pattern, an error will be thrown.
7
+ */ export function ensureApiVersionFormat(version) {
8
+ const normalizedVersion = version.startsWith('v') ? version : `v${version}`;
9
+ // Check if the version matches the expected pattern
10
+ if (!VERSION_PATTERN.test(normalizedVersion)) {
11
+ throw new Error(`Invalid API version format: ${normalizedVersion}. Expected format: vYYYY-MM-DD or vX`);
12
+ }
13
+ return normalizedVersion;
14
+ }
15
+
16
+ //# sourceMappingURL=ensureApiVersionFormat.js.map