@sanity/cli 7.18.0 → 8.0.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 (131) hide show
  1. package/README.md +74 -4
  2. package/dist/SanityHelp.js +1 -35
  3. package/dist/SanityHelp.js.map +1 -1
  4. package/dist/actions/assets/assetFileError.js +9 -0
  5. package/dist/actions/assets/assetFileError.js.map +1 -0
  6. package/dist/actions/assets/uploadAssetFromFile.js +40 -0
  7. package/dist/actions/assets/uploadAssetFromFile.js.map +1 -0
  8. package/dist/actions/assets/uploadAssetWithProgress.js +76 -0
  9. package/dist/actions/assets/uploadAssetWithProgress.js.map +1 -0
  10. package/dist/actions/deploy/deployApp.js +39 -44
  11. package/dist/actions/deploy/deployApp.js.map +1 -1
  12. package/dist/actions/deploy/deployChecks.js +21 -13
  13. package/dist/actions/deploy/deployChecks.js.map +1 -1
  14. package/dist/actions/deploy/deployRunner.js +8 -7
  15. package/dist/actions/deploy/deployRunner.js.map +1 -1
  16. package/dist/actions/deploy/deployStudio.js +55 -35
  17. package/dist/actions/deploy/deployStudio.js.map +1 -1
  18. package/dist/actions/deploy/deploymentPlan.js +17 -29
  19. package/dist/actions/deploy/deploymentPlan.js.map +1 -1
  20. package/dist/actions/deploy/resolveDeployTarget.js +2 -8
  21. package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
  22. package/dist/actions/dev/servers/getDevServerConfig.js +2 -8
  23. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  24. package/dist/actions/dev/servers/startStudioDevServer.js +7 -1
  25. package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
  26. package/dist/actions/init/bootstrapRemoteTemplate.js +2 -2
  27. package/dist/actions/init/bootstrapRemoteTemplate.js.map +1 -1
  28. package/dist/actions/schema/listSchemas.js +1 -1
  29. package/dist/actions/schema/listSchemas.js.map +1 -1
  30. package/dist/actions/tokens/constants.js +2 -2
  31. package/dist/actions/tokens/constants.js.map +1 -1
  32. package/dist/actions/tokens/expiry.js +35 -0
  33. package/dist/actions/tokens/expiry.js.map +1 -0
  34. package/dist/actions/tokens/types.js.map +1 -1
  35. package/dist/actions/tokens/validateRole.js +5 -2
  36. package/dist/actions/tokens/validateRole.js.map +1 -1
  37. package/dist/actions/typegen/count.js +6 -0
  38. package/dist/actions/typegen/count.js.map +1 -0
  39. package/dist/actions/typegen/formatPath.js +5 -0
  40. package/dist/actions/typegen/formatPath.js.map +1 -0
  41. package/dist/actions/typegen/percent.js +8 -0
  42. package/dist/actions/typegen/percent.js.map +1 -0
  43. package/dist/actions/typegen/renderTypegenProgress.js +88 -0
  44. package/dist/actions/typegen/renderTypegenProgress.js.map +1 -0
  45. package/dist/actions/undeploy/adapters.js +6 -9
  46. package/dist/actions/undeploy/adapters.js.map +1 -1
  47. package/dist/actions/undeploy/runUndeploy.js +12 -4
  48. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  49. package/dist/actions/undeploy/undeployPlan.js +6 -14
  50. package/dist/actions/undeploy/undeployPlan.js.map +1 -1
  51. package/dist/commands/assets/upload.js +126 -0
  52. package/dist/commands/assets/upload.js.map +1 -0
  53. package/dist/commands/backups/list.js +1 -1
  54. package/dist/commands/backups/list.js.map +1 -1
  55. package/dist/commands/datasets/copy.js +1 -1
  56. package/dist/commands/datasets/copy.js.map +1 -1
  57. package/dist/commands/login.js +2 -8
  58. package/dist/commands/login.js.map +1 -1
  59. package/dist/commands/mcp/configure.js.map +1 -1
  60. package/dist/commands/migrations/list.js +1 -1
  61. package/dist/commands/migrations/list.js.map +1 -1
  62. package/dist/commands/migrations/run.js +67 -3
  63. package/dist/commands/migrations/run.js.map +1 -1
  64. package/dist/commands/new.js +4 -3
  65. package/dist/commands/new.js.map +1 -1
  66. package/dist/commands/organizations/list.js +1 -1
  67. package/dist/commands/organizations/list.js.map +1 -1
  68. package/dist/commands/projects/list.js +39 -12
  69. package/dist/commands/projects/list.js.map +1 -1
  70. package/dist/commands/projects/unclaimed.js +39 -33
  71. package/dist/commands/projects/unclaimed.js.map +1 -1
  72. package/dist/commands/tokens/create.js +92 -7
  73. package/dist/commands/tokens/create.js.map +1 -1
  74. package/dist/commands/tokens/delete.js +2 -2
  75. package/dist/commands/tokens/delete.js.map +1 -1
  76. package/dist/commands/tokens/list.js +12 -11
  77. package/dist/commands/tokens/list.js.map +1 -1
  78. package/dist/commands/tokens/rotate.js +95 -0
  79. package/dist/commands/tokens/rotate.js.map +1 -0
  80. package/dist/commands/typegen/generate.js +222 -0
  81. package/dist/commands/typegen/generate.js.map +1 -0
  82. package/dist/commands/users/list.js +8 -8
  83. package/dist/commands/users/list.js.map +1 -1
  84. package/dist/exports/_internal.d.ts +29 -0
  85. package/dist/exports/_internal.js +1 -0
  86. package/dist/exports/_internal.js.map +1 -1
  87. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +6 -0
  88. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  89. package/dist/exports/invokeSanityCli/help.js +4 -0
  90. package/dist/exports/invokeSanityCli/help.js.map +1 -1
  91. package/dist/exports/invokeSanityCli/index.js +2 -0
  92. package/dist/exports/invokeSanityCli/index.js.map +1 -1
  93. package/dist/hooks/commandNotFound/topicAliases.js +13 -40
  94. package/dist/hooks/commandNotFound/topicAliases.js.map +1 -1
  95. package/dist/hooks/prerun/setupTelemetry.js +3 -2
  96. package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
  97. package/dist/server/vite/plugin-typegen.js +4 -16
  98. package/dist/server/vite/plugin-typegen.js.map +1 -1
  99. package/dist/services/assets.js +46 -0
  100. package/dist/services/assets.js.map +1 -0
  101. package/dist/services/tokens.js +81 -31
  102. package/dist/services/tokens.js.map +1 -1
  103. package/dist/topicAliases.js +43 -0
  104. package/dist/topicAliases.js.map +1 -1
  105. package/dist/util/parseArguments.js +7 -2
  106. package/dist/util/parseArguments.js.map +1 -1
  107. package/dist/util/readTokenFromStdin.js +17 -0
  108. package/dist/util/readTokenFromStdin.js.map +1 -0
  109. package/dist/util/responsiveTable.js +97 -0
  110. package/dist/util/responsiveTable.js.map +1 -0
  111. package/dist/util/telemetry/commandTelemetry.js +34 -0
  112. package/dist/util/telemetry/commandTelemetry.js.map +1 -0
  113. package/dist/util/unclaimedProjects.js +10 -0
  114. package/dist/util/unclaimedProjects.js.map +1 -1
  115. package/oclif.config.js +2 -4
  116. package/oclif.manifest.json +213 -1
  117. package/package.json +12 -10
  118. package/templates/shopify/components/inputs/ShopifyMetafield.tsx +20 -0
  119. package/templates/shopify/docs/features.md +24 -0
  120. package/templates/shopify/schemaTypes/index.ts +2 -0
  121. package/templates/shopify/schemaTypes/objects/shopify/shopifyCollectionType.ts +18 -1
  122. package/templates/shopify/schemaTypes/objects/shopify/shopifyMetafieldType.ts +47 -0
  123. package/templates/shopify/schemaTypes/objects/shopify/shopifyProductType.ts +17 -0
  124. package/templates/shopify/utils/formatMetafieldValue.ts +30 -0
  125. package/templates/shopify-online-storefront/components/inputs/ShopifyMetafield.tsx +22 -0
  126. package/templates/shopify-online-storefront/schemaTypes/index.ts +4 -0
  127. package/templates/shopify-online-storefront/schemaTypes/objects/shop.ts +16 -0
  128. package/templates/shopify-online-storefront/schemaTypes/objects/shopifyCollection.ts +19 -0
  129. package/templates/shopify-online-storefront/schemaTypes/objects/shopifyMetafield.ts +53 -0
  130. package/templates/shopify-online-storefront/schemaTypes/objects/shopifyProduct.ts +19 -0
  131. package/templates/shopify-online-storefront/utils/formatMetafieldValue.ts +30 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {checkDependenciesEventListenerFactory} from '../../build/eventListenerFactory.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies({\n ...options,\n ...checkDependenciesEventListenerFactory(output),\n })\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","checkDependenciesEventListenerFactory","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","basePath","appType","viteVersion","Math","ceil","started"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SACEC,yBAAyB,EACzBC,6BAA6B,EAC7BC,yBAAyB,QACpB,oCAAmC;AAC1C,SAAQC,sBAAsB,EAAEC,aAAa,QAAO,mBAAkB;AACtE,SAAQC,OAAO,EAAEC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AAChE,SAAQC,cAAc,QAAO,wBAAuB;AACpD,SAAQC,SAASC,WAAW,QAAO,SAAQ;AAE3C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,cAAc,QAAO,gCAA+B;AAC5D,SAAQC,QAAQ,QAAO,yBAAwB;AAC/C,SAAQC,uBAAuB,QAAO,uDAAsD;AAC5F,SAAQC,eAAe,QAAO,kDAAiD;AAC/E,SAAQC,qCAAqC,QAAO,sCAAqC;AACzF,SAAQC,gBAAgB,QAAO,kCAAiC;AAChE,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,OAAO,eAAeC,qBACpBC,OAAyB;IAEzB,MAAM,EAACC,cAAc,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAC1E,MAAMO,YAAYL,WAAWM,KAAKD;IAClC,IAAIE;IAEJ,sEAAsE;IACtE,mCAAmC;IACnC,MAAMC,kBAAkBP,KAAK,CAAC,oBAAoB,IAAI,CAAClB,eAAeiB,WAAWS;IAEjF,mCAAmC;IACnC,MAAMjC,8BAA8B4B,SAASD;IAE7C,MAAM,EAACO,sBAAsB,EAAC,GAAG,MAAMnC,0BAA0B;QAC/D,GAAGuB,OAAO;QACV,GAAGN,sCAAsCW,OAAO;IAClD;IAEA,oCAAoC;IACpC,MAAMQ,qBAAqBlB,iBAAiB;QAACO;QAAWC;QAAOE;IAAM;IAErE,IAAIQ,oBAAoB;QACtB,iFAAiF;QACjF,MAAMC,qBAAqB3B,YAAYyB,yBAAyBG;QAChE,IAAI,CAACD,oBAAoB;YACvB,MAAM,IAAIE,MAAM,CAAC,0CAA0C,EAAEJ,wBAAwB;QACvF;QAEA,MAAMK,qBAAqB;YACzB;gBAACC,MAAM;gBAAUH,SAASD;YAAkB;YAC5C;gBAACI,MAAM;gBAAkBH,SAASD;YAAkB;SACrD;QAEDT,OAAOc,GAAG,CAAC,GAAGpC,WAAWqC,IAAI,CAAC,kCAAkC,CAAC;QAEjE,iDAAiD;QACjD,IAAIC;QAEJ,MAAMC,QAAQ/B,SAASW;QAEvB,IAAI;YACFmB,SAAS,MAAM1C,0BAA0BsC,oBAAoBX,SAAS;gBAACgB;YAAK;QAC9E,EAAE,OAAOC,KAAK;YACZlB,OAAOmB,IAAI,CAAC,CAAC,iEAAiE,EAAED,KAAK;QACvF;QAEA,IAAIF,QAAQI,qBAAqBC,QAAQ;YACvC,KAAK,MAAMC,OAAON,OAAOI,oBAAoB,CAAE;gBAC7CpB,OAAOmB,IAAI,CACT,CAAC,sBAAsB,EAAEG,IAAIC,GAAG,CAAC,EAAE,EAAED,IAAIZ,OAAO,CAAC,oGAAoG,CAAC;YAE1J;QACF;QAEA,wDAAwD;QACxD,IAAIM,QAAQQ,WAAWH,QAAQ;YAC7B,MAAMI,UACJ,CAAC,mGAAmG,CAAC,GACrG,CAAC,qHAAqH,CAAC,GACvH,GAAGT,OAAOQ,UAAU,CAACE,GAAG,CAAC,CAACJ,MAAQ,CAAC,GAAG,EAAEA,IAAIC,GAAG,CAAC,iBAAiB,EAAED,IAAIK,SAAS,CAAC,mBAAmB,EAAEL,IAAIM,MAAM,CAAC,CAAC,CAAC,EAAEC,IAAI,CAAC,MAAM,IAAI,CAAC;YAEvI,IAAIrD,iBAAiB;gBACnB,MAAMsD,gBAAgB,MAAMrD,QAAQ;oBAClCsD,SAAS;oBACTN,SAAStD,UAAU,UAAU,GAAGsD,QAAQ,sCAAsC,CAAC;gBACjF;gBACA,IAAIK,eAAe;oBACjB,MAAM1C,gBACJ;wBACE4C,gBAAgB,AAAC,CAAA,MAAM7C,wBAAwBc,SAAS;4BAACgC,aAAa;wBAAK,EAAC,EAAGC,MAAM;wBACrFC,UAAUnB,OAAOQ,UAAU,CAACE,GAAG,CAAC,CAACU,MAAQ;gCAACA,IAAIb,GAAG;gCAAEa,IAAIR,MAAM;6BAAC;oBAChE,GACA;wBAAC5B;wBAAQC;oBAAO;gBAEpB;YACF,OAAO;gBACL,4GAA4G;gBAC5GD,OAAOc,GAAG,CAAC3C,UAAU,UAAUsD;YACjC;QACF;IACF;IAEA,IAAI5B,WAAWwC,kBAAkBC,SAAS;QACxCtC,OAAOc,GAAG,CAAC,GAAGpC,WAAWqC,IAAI,CAAC,kDAAkD,CAAC;IACnF;IAEA,MAAMwB,SAAS9C,mBAAmB;QAACI;QAAWC;QAAOC;QAAUC;QAAQC;IAAO;IAE9E,IAAII,iBAAiB;QACnB,IAAI,CAACH,WAAW;YACdF,OAAOwC,KAAK,CAAC,+CAA+C;gBAACC,MAAM;YAAC;QACtE;QAEA,IAAI;YACF,MAAMC,UAAU,MAAMzD,eAAeiB;YACrCE,iBAAiBsC,QAAQtC,cAAc;QACzC,EAAE,OAAOoC,OAAO;YACdjD,SAAS,iDAAiDiD;YAC1DxC,OAAOwC,KAAK,CAAC,iDAAiD;gBAACC,MAAM;YAAC;QACxE;IACF;IAEA,IAAI;QACF,MAAME,YAAYC,KAAKC,GAAG;QAC1B,MAAMC,OAAOnE,QAAQ,uBAAuBoE,KAAK;QACjD,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAMlE,eAAewD;QAE7C,MAAM,EAACxB,MAAMmC,UAAU,EAAC,GAAGD,OAAOV,MAAM,CAACY,MAAM;QAC/C,MAAM,EAACC,IAAI,EAAC,GAAGH,OAAOV,MAAM,CAACU,MAAM;QACnC,MAAMI,WAAWd,OAAOc,QAAQ,IAAI;QAEpC,IAAIhD,iBAAiB;YACnByC,KAAKQ,OAAO;YAEZtD,OAAOc,GAAG,CAAC,CAAC,2BAA2B,EAAEsC,MAAM;YAC/CpD,OAAOc,GAAG,CAAC,CAAC,8CAA8C,CAAC;YAC3Dd,OAAOc,GAAG,CACR3C,UACE;gBAAC;gBAAQ;aAAY,EACrB,MAAMqB,mBAAmB;gBACvB6D;gBACAtD,UAAUqD;gBACVhD,gBAAgBA;YAClB;QAGN,OAAO;YACL,MAAMmD,kBAAkBX,KAAKC,GAAG,KAAKF;YACrC,MAAMa,MAAM,CAAC,OAAO,EAAEH,YAAY,YAAY,CAAC,EAAED,OAAOb,OAAOkB,QAAQ,EAAE;YACzE,MAAMC,UAAU;YAEhB,MAAMC,cAAc,MAAMpF,uBAAuB,QAAQ,YAAYiF,GAAG;YACxEV,KAAKQ,OAAO;YAEZJ,WACE,GAAGQ,QAAQ,CAAC,CAAC,GACX,CAAC,MAAM,EAAEvF,UAAU,QAAQ,CAAC,KAAK,EAAEwF,aAAa,EAAE,CAAC,CAAC,GACpD,CAAC,SAAS,EAAExF,UAAU,QAAQ,GAAGyF,KAAKC,IAAI,CAACN,iBAAiB,EAAE,CAAC,GAAG,GACjE3D,CAAAA,cAAc,CAAC,gBAAgB,EAAEzB,UAAU,QAAQqF,MAAM,GAAG,EAAC;QAEpE;QAEA,OAAO;YAACR;YAAOC;YAAQa,SAAS;QAAI;IACtC,EAAE,OAAO5C,KAAK;QACZ3B,SAAS,oCAAoC2B;QAC7C,MAAMlC,oBAAoB,OAAOuD,OAAOc,QAAQ,EAAEd,OAAOxC,QAAQ,EAAEmB;IACrE;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {hasLocalUnclaimedProject} from '../../../util/unclaimedProjects.js'\nimport {checkDependenciesEventListenerFactory} from '../../build/eventListenerFactory.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies({\n ...options,\n ...checkDependenciesEventListenerFactory(output),\n })\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = withUnclaimedSignInHash(\n `http://${httpHost || 'localhost'}:${port}${config.basePath}`,\n projectId,\n )\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n\nfunction withUnclaimedSignInHash(url: string, projectId: string | undefined): string {\n const token = process.env.SANITY_AUTH_TOKEN\n if (!token || !projectId || !hasLocalUnclaimedProject(projectId)) return url\n return `${url}#token=${encodeURIComponent(token)}`\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","hasLocalUnclaimedProject","checkDependenciesEventListenerFactory","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","withUnclaimedSignInHash","basePath","appType","viteVersion","Math","ceil","started","token","process","env","SANITY_AUTH_TOKEN","encodeURIComponent"],"mappings":"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"}
@@ -59,12 +59,12 @@ export async function bootstrapRemoteTemplate(opts) {
59
59
  label: READ_TOKEN_LABEL,
60
60
  projectId: variables.projectId,
61
61
  roleName: API_READ_TOKEN_ROLE
62
- })).key : undefined;
62
+ })).token : undefined;
63
63
  const writeToken = needsWriteToken ? (await createToken({
64
64
  label: WRITE_TOKEN_LABEL,
65
65
  projectId: variables.projectId,
66
66
  roleName: API_WRITE_TOKEN_ROLE
67
- })).key : undefined;
67
+ })).token : undefined;
68
68
  for (const pkg of packages ?? [
69
69
  ''
70
70
  ]){
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/bootstrapRemoteTemplate.ts"],"sourcesContent":["import {mkdir} from 'node:fs/promises'\nimport {join} from 'node:path'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {getMonoRepo, GitHubFileReader, validateTemplate} from '@sanity/template-validator'\nimport {type Framework, frameworks} from '@vercel/frameworks'\n\nimport {createCorsOrigin} from '../../services/cors.js'\nimport {createToken} from '../../services/tokens.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {getDefaultPortForFramework} from '../../util/frameworkPort.js'\nimport {type GenerateConfigOptions} from './createStudioConfig.js'\nimport {tryGitInit} from './git.js'\nimport {\n applyEnvVariables,\n checkIfNeedsApiToken,\n downloadAndExtractRepo,\n getGitHubRawContentUrl,\n type RepoInfo,\n tryApplyPackageName,\n} from './remoteTemplate.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapRemoteOptions {\n output: Output\n outputPath: string\n packageName: string\n repoInfo: RepoInfo\n variables: GenerateConfigOptions['variables']\n\n bearerToken?: string\n}\n\nconst SANITY_DEFAULT_PORT = 3333\nconst READ_TOKEN_LABEL = 'Live Preview API'\nconst WRITE_TOKEN_LABEL = 'App Write Token'\nconst INITIAL_COMMIT_MESSAGE = 'Initial commit from Sanity CLI'\nconst API_READ_TOKEN_ROLE = 'viewer'\nconst API_WRITE_TOKEN_ROLE = 'editor'\n\nexport async function bootstrapRemoteTemplate(opts: BootstrapRemoteOptions): Promise<void> {\n const {bearerToken, output, outputPath, packageName, repoInfo, variables} = opts\n const name = [repoInfo.username, repoInfo.name, repoInfo.filePath].filter(Boolean).join('/')\n const contentsUrl = getGitHubRawContentUrl(repoInfo)\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n const spin = spinner(`Bootstrapping files from template \"${name}\"`).start()\n const corsAdded: number[] = [SANITY_DEFAULT_PORT]\n\n debug('Validating remote template')\n const fileReader = new GitHubFileReader(contentsUrl, headers)\n const packages = await getMonoRepo(fileReader)\n const validation = await validateTemplate(fileReader, packages)\n if (!validation.isValid) {\n throw new Error(validation.errors.join('\\n'))\n }\n\n debug('Create new directory \"%s\"', outputPath)\n await mkdir(outputPath, {recursive: true})\n\n debug('Downloading and extracting repo to %s', outputPath)\n await downloadAndExtractRepo(outputPath, repoInfo, bearerToken)\n\n debug('Checking if template needs read token')\n const needsReadToken = await Promise.all(\n (packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'read')),\n ).then((results) => results.some(Boolean))\n const needsWriteToken = await Promise.all(\n (packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'write')),\n ).then((results) => results.some(Boolean))\n\n debug('Applying environment variables')\n const readToken = needsReadToken\n ? (\n await createToken({\n label: READ_TOKEN_LABEL,\n projectId: variables.projectId,\n roleName: API_READ_TOKEN_ROLE,\n })\n ).key\n : undefined\n const writeToken = needsWriteToken\n ? (\n await createToken({\n label: WRITE_TOKEN_LABEL,\n projectId: variables.projectId,\n roleName: API_WRITE_TOKEN_ROLE,\n })\n ).key\n : undefined\n\n for (const pkg of packages ?? ['']) {\n const packagePath = join(outputPath, pkg)\n const packageFramework: Framework | null = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: packagePath,\n })\n\n const port = getDefaultPortForFramework(packageFramework?.slug)\n if (!corsAdded.includes(port)) {\n debug('Setting CORS origin to http://localhost:%d', port)\n await createCorsOrigin({\n allowCredentials: true,\n origin: `http://localhost:${port}`,\n projectId: variables.projectId,\n })\n corsAdded.push(port)\n }\n\n debug('Applying environment variables to %s', pkg)\n // Next.js uses `.env.local` for local environment variables\n const envName = packageFramework?.slug === 'nextjs' ? '.env.local' : '.env'\n await applyEnvVariables(packagePath, {...variables, readToken, writeToken}, envName)\n }\n\n debug('Setting package name to %s', packageName)\n await tryApplyPackageName(outputPath, packageName)\n\n debug('Initializing git repository')\n tryGitInit(outputPath, INITIAL_COMMIT_MESSAGE)\n\n debug('Updating initial template metadata')\n await updateInitialTemplateMetadata(variables.projectId, `external-${name}`)\n\n spin.succeed()\n const newlyAddedPorts = corsAdded.slice(1)\n if (newlyAddedPorts.length > 0) {\n output.log(\n `${logSymbols.success} CORS origins added (${newlyAddedPorts.map((p) => `localhost:${p}`).join(', ')})`,\n )\n }\n if (readToken) output.log(`${logSymbols.success} API token generated (${READ_TOKEN_LABEL})`)\n if (writeToken) output.log(`${logSymbols.success} API token generated (${WRITE_TOKEN_LABEL})`)\n}\n"],"names":["mkdir","join","subdebug","logSymbols","spinner","getMonoRepo","GitHubFileReader","validateTemplate","frameworks","createCorsOrigin","createToken","detectFrameworkRecord","getDefaultPortForFramework","tryGitInit","applyEnvVariables","checkIfNeedsApiToken","downloadAndExtractRepo","getGitHubRawContentUrl","tryApplyPackageName","updateInitialTemplateMetadata","debug","SANITY_DEFAULT_PORT","READ_TOKEN_LABEL","WRITE_TOKEN_LABEL","INITIAL_COMMIT_MESSAGE","API_READ_TOKEN_ROLE","API_WRITE_TOKEN_ROLE","bootstrapRemoteTemplate","opts","bearerToken","output","outputPath","packageName","repoInfo","variables","name","username","filePath","filter","Boolean","contentsUrl","headers","Authorization","spin","start","corsAdded","fileReader","packages","validation","isValid","Error","errors","recursive","needsReadToken","Promise","all","map","pkg","then","results","some","needsWriteToken","readToken","label","projectId","roleName","key","undefined","writeToken","packagePath","packageFramework","frameworkList","rootPath","port","slug","includes","allowCredentials","origin","push","envName","succeed","newlyAddedPorts","slice","length","log","success","p"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/init/bootstrapRemoteTemplate.ts"],"sourcesContent":["import {mkdir} from 'node:fs/promises'\nimport {join} from 'node:path'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {getMonoRepo, GitHubFileReader, validateTemplate} from '@sanity/template-validator'\nimport {type Framework, frameworks} from '@vercel/frameworks'\n\nimport {createCorsOrigin} from '../../services/cors.js'\nimport {createToken} from '../../services/tokens.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {getDefaultPortForFramework} from '../../util/frameworkPort.js'\nimport {type GenerateConfigOptions} from './createStudioConfig.js'\nimport {tryGitInit} from './git.js'\nimport {\n applyEnvVariables,\n checkIfNeedsApiToken,\n downloadAndExtractRepo,\n getGitHubRawContentUrl,\n type RepoInfo,\n tryApplyPackageName,\n} from './remoteTemplate.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapRemoteOptions {\n output: Output\n outputPath: string\n packageName: string\n repoInfo: RepoInfo\n variables: GenerateConfigOptions['variables']\n\n bearerToken?: string\n}\n\nconst SANITY_DEFAULT_PORT = 3333\nconst READ_TOKEN_LABEL = 'Live Preview API'\nconst WRITE_TOKEN_LABEL = 'App Write Token'\nconst INITIAL_COMMIT_MESSAGE = 'Initial commit from Sanity CLI'\nconst API_READ_TOKEN_ROLE = 'viewer'\nconst API_WRITE_TOKEN_ROLE = 'editor'\n\nexport async function bootstrapRemoteTemplate(opts: BootstrapRemoteOptions): Promise<void> {\n const {bearerToken, output, outputPath, packageName, repoInfo, variables} = opts\n const name = [repoInfo.username, repoInfo.name, repoInfo.filePath].filter(Boolean).join('/')\n const contentsUrl = getGitHubRawContentUrl(repoInfo)\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n const spin = spinner(`Bootstrapping files from template \"${name}\"`).start()\n const corsAdded: number[] = [SANITY_DEFAULT_PORT]\n\n debug('Validating remote template')\n const fileReader = new GitHubFileReader(contentsUrl, headers)\n const packages = await getMonoRepo(fileReader)\n const validation = await validateTemplate(fileReader, packages)\n if (!validation.isValid) {\n throw new Error(validation.errors.join('\\n'))\n }\n\n debug('Create new directory \"%s\"', outputPath)\n await mkdir(outputPath, {recursive: true})\n\n debug('Downloading and extracting repo to %s', outputPath)\n await downloadAndExtractRepo(outputPath, repoInfo, bearerToken)\n\n debug('Checking if template needs read token')\n const needsReadToken = await Promise.all(\n (packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'read')),\n ).then((results) => results.some(Boolean))\n const needsWriteToken = await Promise.all(\n (packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'write')),\n ).then((results) => results.some(Boolean))\n\n debug('Applying environment variables')\n const readToken = needsReadToken\n ? (\n await createToken({\n label: READ_TOKEN_LABEL,\n projectId: variables.projectId,\n roleName: API_READ_TOKEN_ROLE,\n })\n ).token\n : undefined\n const writeToken = needsWriteToken\n ? (\n await createToken({\n label: WRITE_TOKEN_LABEL,\n projectId: variables.projectId,\n roleName: API_WRITE_TOKEN_ROLE,\n })\n ).token\n : undefined\n\n for (const pkg of packages ?? ['']) {\n const packagePath = join(outputPath, pkg)\n const packageFramework: Framework | null = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: packagePath,\n })\n\n const port = getDefaultPortForFramework(packageFramework?.slug)\n if (!corsAdded.includes(port)) {\n debug('Setting CORS origin to http://localhost:%d', port)\n await createCorsOrigin({\n allowCredentials: true,\n origin: `http://localhost:${port}`,\n projectId: variables.projectId,\n })\n corsAdded.push(port)\n }\n\n debug('Applying environment variables to %s', pkg)\n // Next.js uses `.env.local` for local environment variables\n const envName = packageFramework?.slug === 'nextjs' ? '.env.local' : '.env'\n await applyEnvVariables(packagePath, {...variables, readToken, writeToken}, envName)\n }\n\n debug('Setting package name to %s', packageName)\n await tryApplyPackageName(outputPath, packageName)\n\n debug('Initializing git repository')\n tryGitInit(outputPath, INITIAL_COMMIT_MESSAGE)\n\n debug('Updating initial template metadata')\n await updateInitialTemplateMetadata(variables.projectId, `external-${name}`)\n\n spin.succeed()\n const newlyAddedPorts = corsAdded.slice(1)\n if (newlyAddedPorts.length > 0) {\n output.log(\n `${logSymbols.success} CORS origins added (${newlyAddedPorts.map((p) => `localhost:${p}`).join(', ')})`,\n )\n }\n if (readToken) output.log(`${logSymbols.success} API token generated (${READ_TOKEN_LABEL})`)\n if (writeToken) output.log(`${logSymbols.success} API token generated (${WRITE_TOKEN_LABEL})`)\n}\n"],"names":["mkdir","join","subdebug","logSymbols","spinner","getMonoRepo","GitHubFileReader","validateTemplate","frameworks","createCorsOrigin","createToken","detectFrameworkRecord","getDefaultPortForFramework","tryGitInit","applyEnvVariables","checkIfNeedsApiToken","downloadAndExtractRepo","getGitHubRawContentUrl","tryApplyPackageName","updateInitialTemplateMetadata","debug","SANITY_DEFAULT_PORT","READ_TOKEN_LABEL","WRITE_TOKEN_LABEL","INITIAL_COMMIT_MESSAGE","API_READ_TOKEN_ROLE","API_WRITE_TOKEN_ROLE","bootstrapRemoteTemplate","opts","bearerToken","output","outputPath","packageName","repoInfo","variables","name","username","filePath","filter","Boolean","contentsUrl","headers","Authorization","spin","start","corsAdded","fileReader","packages","validation","isValid","Error","errors","recursive","needsReadToken","Promise","all","map","pkg","then","results","some","needsWriteToken","readToken","label","projectId","roleName","token","undefined","writeToken","packagePath","packageFramework","frameworkList","rootPath","port","slug","includes","allowCredentials","origin","push","envName","succeed","newlyAddedPorts","slice","length","log","success","p"],"mappings":"AAAA,SAAQA,KAAK,QAAO,mBAAkB;AACtC,SAAQC,IAAI,QAAO,YAAW;AAE9B,SAAgBC,QAAQ,QAAO,mBAAkB;AACjD,SAAQC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AACvD,SAAQC,WAAW,EAAEC,gBAAgB,EAAEC,gBAAgB,QAAO,6BAA4B;AAC1F,SAAwBC,UAAU,QAAO,qBAAoB;AAE7D,SAAQC,gBAAgB,QAAO,yBAAwB;AACvD,SAAQC,WAAW,QAAO,2BAA0B;AACpD,SAAQC,qBAAqB,QAAO,gCAA+B;AACnE,SAAQC,0BAA0B,QAAO,8BAA6B;AAEtE,SAAQC,UAAU,QAAO,WAAU;AACnC,SACEC,iBAAiB,EACjBC,oBAAoB,EACpBC,sBAAsB,EACtBC,sBAAsB,EAEtBC,mBAAmB,QACd,sBAAqB;AAC5B,SAAQC,6BAA6B,QAAO,qCAAoC;AAEhF,MAAMC,QAAQlB,SAAS;AAYvB,MAAMmB,sBAAsB;AAC5B,MAAMC,mBAAmB;AACzB,MAAMC,oBAAoB;AAC1B,MAAMC,yBAAyB;AAC/B,MAAMC,sBAAsB;AAC5B,MAAMC,uBAAuB;AAE7B,OAAO,eAAeC,wBAAwBC,IAA4B;IACxE,MAAM,EAACC,WAAW,EAAEC,MAAM,EAAEC,UAAU,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,SAAS,EAAC,GAAGN;IAC5E,MAAMO,OAAO;QAACF,SAASG,QAAQ;QAAEH,SAASE,IAAI;QAAEF,SAASI,QAAQ;KAAC,CAACC,MAAM,CAACC,SAAStC,IAAI,CAAC;IACxF,MAAMuC,cAAcvB,uBAAuBgB;IAC3C,MAAMQ,UAAkC,CAAC;IACzC,IAAIZ,aAAa;QACfY,QAAQC,aAAa,GAAG,CAAC,OAAO,EAAEb,aAAa;IACjD;IACA,MAAMc,OAAOvC,QAAQ,CAAC,mCAAmC,EAAE+B,KAAK,CAAC,CAAC,EAAES,KAAK;IACzE,MAAMC,YAAsB;QAACxB;KAAoB;IAEjDD,MAAM;IACN,MAAM0B,aAAa,IAAIxC,iBAAiBkC,aAAaC;IACrD,MAAMM,WAAW,MAAM1C,YAAYyC;IACnC,MAAME,aAAa,MAAMzC,iBAAiBuC,YAAYC;IACtD,IAAI,CAACC,WAAWC,OAAO,EAAE;QACvB,MAAM,IAAIC,MAAMF,WAAWG,MAAM,CAAClD,IAAI,CAAC;IACzC;IAEAmB,MAAM,6BAA6BW;IACnC,MAAM/B,MAAM+B,YAAY;QAACqB,WAAW;IAAI;IAExChC,MAAM,yCAAyCW;IAC/C,MAAMf,uBAAuBe,YAAYE,UAAUJ;IAEnDT,MAAM;IACN,MAAMiC,iBAAiB,MAAMC,QAAQC,GAAG,CACtC,AAACR,CAAAA,YAAY;QAAC;KAAG,AAAD,EAAGS,GAAG,CAAC,CAACC,MAAQ1C,qBAAqBd,KAAK8B,YAAY0B,MAAM,UAC5EC,IAAI,CAAC,CAACC,UAAYA,QAAQC,IAAI,CAACrB;IACjC,MAAMsB,kBAAkB,MAAMP,QAAQC,GAAG,CACvC,AAACR,CAAAA,YAAY;QAAC;KAAG,AAAD,EAAGS,GAAG,CAAC,CAACC,MAAQ1C,qBAAqBd,KAAK8B,YAAY0B,MAAM,WAC5EC,IAAI,CAAC,CAACC,UAAYA,QAAQC,IAAI,CAACrB;IAEjCnB,MAAM;IACN,MAAM0C,YAAYT,iBACd,AACE,CAAA,MAAM3C,YAAY;QAChBqD,OAAOzC;QACP0C,WAAW9B,UAAU8B,SAAS;QAC9BC,UAAUxC;IACZ,EAAC,EACDyC,KAAK,GACPC;IACJ,MAAMC,aAAaP,kBACf,AACE,CAAA,MAAMnD,YAAY;QAChBqD,OAAOxC;QACPyC,WAAW9B,UAAU8B,SAAS;QAC9BC,UAAUvC;IACZ,EAAC,EACDwC,KAAK,GACPC;IAEJ,KAAK,MAAMV,OAAOV,YAAY;QAAC;KAAG,CAAE;QAClC,MAAMsB,cAAcpE,KAAK8B,YAAY0B;QACrC,MAAMa,mBAAqC,MAAM3D,sBAAsB;YACrE4D,eAAe/D;YACfgE,UAAUH;QACZ;QAEA,MAAMI,OAAO7D,2BAA2B0D,kBAAkBI;QAC1D,IAAI,CAAC7B,UAAU8B,QAAQ,CAACF,OAAO;YAC7BrD,MAAM,8CAA8CqD;YACpD,MAAMhE,iBAAiB;gBACrBmE,kBAAkB;gBAClBC,QAAQ,CAAC,iBAAiB,EAAEJ,MAAM;gBAClCT,WAAW9B,UAAU8B,SAAS;YAChC;YACAnB,UAAUiC,IAAI,CAACL;QACjB;QAEArD,MAAM,wCAAwCqC;QAC9C,4DAA4D;QAC5D,MAAMsB,UAAUT,kBAAkBI,SAAS,WAAW,eAAe;QACrE,MAAM5D,kBAAkBuD,aAAa;YAAC,GAAGnC,SAAS;YAAE4B;YAAWM;QAAU,GAAGW;IAC9E;IAEA3D,MAAM,8BAA8BY;IACpC,MAAMd,oBAAoBa,YAAYC;IAEtCZ,MAAM;IACNP,WAAWkB,YAAYP;IAEvBJ,MAAM;IACN,MAAMD,8BAA8Be,UAAU8B,SAAS,EAAE,CAAC,SAAS,EAAE7B,MAAM;IAE3EQ,KAAKqC,OAAO;IACZ,MAAMC,kBAAkBpC,UAAUqC,KAAK,CAAC;IACxC,IAAID,gBAAgBE,MAAM,GAAG,GAAG;QAC9BrD,OAAOsD,GAAG,CACR,GAAGjF,WAAWkF,OAAO,CAAC,qBAAqB,EAAEJ,gBAAgBzB,GAAG,CAAC,CAAC8B,IAAM,CAAC,UAAU,EAAEA,GAAG,EAAErF,IAAI,CAAC,MAAM,CAAC,CAAC;IAE3G;IACA,IAAI6D,WAAWhC,OAAOsD,GAAG,CAAC,GAAGjF,WAAWkF,OAAO,CAAC,sBAAsB,EAAE/D,iBAAiB,CAAC,CAAC;IAC3F,IAAI8C,YAAYtC,OAAOsD,GAAG,CAAC,GAAGjF,WAAWkF,OAAO,CAAC,sBAAsB,EAAE9D,kBAAkB,CAAC,CAAC;AAC/F"}
@@ -1,8 +1,8 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { studioWorkerTask } from '@sanity/cli-core';
3
3
  import { logSymbols } from '@sanity/cli-core/ux';
4
- import { Table } from 'console-table-printer';
5
4
  import { getSchemas } from '../../services/schemas.js';
5
+ import { Table } from '../../util/responsiveTable.js';
6
6
  import { isDefined } from '../manifest/schemaTypeHelpers.js';
7
7
  import { getDatasetsOutString } from './utils/schemaStoreOutStrings.js';
8
8
  import { SCHEMA_PERMISSION_HELP_TEXT } from './utils/schemaStoreValidation.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/schema/listSchemas.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, studioWorkerTask} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {type Workspace} from 'sanity'\n\nimport {getSchemas} from '../../services/schemas.js'\nimport {isDefined} from '../manifest/schemaTypeHelpers.js'\nimport {type StoredWorkspaceSchema} from '../manifest/types.js'\nimport {type UniqWorkspaceWorkerData} from './types.js'\nimport {getDatasetsOutString} from './utils/schemaStoreOutStrings.js'\nimport {SCHEMA_PERMISSION_HELP_TEXT} from './utils/schemaStoreValidation.js'\n\ninterface ListSchemasOptions {\n configPath: string\n json: boolean\n output: Output\n workDir: string\n\n id?: string\n}\n\nclass DatasetError extends Error {\n public dataset: string\n public projectId: string\n constructor(args: {dataset: string; options?: ErrorOptions; projectId: string}) {\n super((args.options?.cause as {message?: string})?.message, args.options)\n this.projectId = args.projectId\n this.dataset = args.dataset\n this.name = 'DatasetError'\n }\n}\n\nexport async function listSchemas(options: ListSchemasOptions): Promise<void> {\n const {configPath, id, json, output, workDir} = options\n\n const projectDatasets = await studioWorkerTask<(Workspace & {key: string})[]>(\n new URL('uniqueWorkspaces.worker.js', import.meta.url),\n {\n name: 'uniqueWorkspaces',\n studioRootPath: workDir,\n workerData: {configPath} satisfies UniqWorkspaceWorkerData,\n },\n )\n\n const schemas = await getDatasetSchemas(projectDatasets, id)\n const parsedSchemas = parseSchemas(schemas, output, json)\n\n if (parsedSchemas.length === 0) {\n const datasetString = getDatasetsOutString(projectDatasets.map((dataset) => dataset.dataset))\n\n throw new Error(\n id\n ? `Schema for id \"${id}\" not found in ${datasetString}`\n : `No schemas found in ${datasetString}`,\n )\n }\n\n if (json) {\n output.log(JSON.stringify(id ? parsedSchemas[0] : parsedSchemas, null, 2))\n } else {\n printSchemas({output, schemas: parsedSchemas, workspaces: projectDatasets})\n }\n}\n\nasync function getDatasetSchemas(projectDatasets: Workspace[], id?: string) {\n return Promise.allSettled(\n projectDatasets.map(async ({dataset, projectId}) => {\n try {\n return await getSchemas(dataset, projectId, id)\n } catch (error) {\n throw new DatasetError({dataset, options: {cause: error}, projectId})\n }\n }),\n )\n}\n\nfunction parseSchemas(\n schemas: PromiseSettledResult<StoredWorkspaceSchema[]>[],\n output: Output,\n json: boolean,\n) {\n return schemas\n .map((schema) => {\n if (schema.status === 'fulfilled') return schema.value\n\n const error = schema.reason\n\n if (error instanceof DatasetError) {\n if (\n 'cause' in error &&\n error.cause &&\n typeof error.cause === 'object' &&\n 'statusCode' in error.cause &&\n error.cause.statusCode === 401\n ) {\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText(\n 'yellow',\n `${logSymbols.warning} ↳ No permissions to read schema from \"${error.dataset}\". ${\n SCHEMA_PERMISSION_HELP_TEXT\n }:\\n ${styleText('red', `${error.message}`)}`,\n ),\n )\n return []\n }\n\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText('red', `↳ Failed to fetch schema from \"${error.dataset}\":\\n ${error.message}`),\n )\n return []\n } else {\n //hubris inc: given the try-catch wrapping all the full promise \"this should never happen\"\n throw error\n }\n })\n .filter((schema) => isDefined(schema))\n .flat()\n}\n\nfunction printSchemas({\n output,\n schemas,\n workspaces,\n}: {\n output: Output\n schemas: StoredWorkspaceSchema[]\n workspaces: Workspace[]\n}) {\n const rows = schemas\n .toSorted((a, b) => -(a._createdAt || '').localeCompare(b._createdAt || ''))\n .map(({_createdAt: createdAt, _id: id, workspace}) => {\n const workspaceData = workspaces.find((w) => w.name === workspace.name)\n if (!workspaceData) return\n\n return {\n CreatedAt: createdAt,\n Dataset: workspaceData.dataset,\n Id: id,\n ProjectId: workspaceData.projectId,\n Workspace: workspace.name,\n }\n })\n .filter((schema) => isDefined(schema))\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'Id'},\n {alignment: 'left', name: 'Workspace'},\n {alignment: 'left', name: 'Dataset'},\n {alignment: 'left', name: 'ProjectId'},\n {alignment: 'left', name: 'CreatedAt'},\n ],\n })\n\n table.addRows(rows)\n output.log(table.render())\n}\n"],"names":["styleText","studioWorkerTask","logSymbols","Table","getSchemas","isDefined","getDatasetsOutString","SCHEMA_PERMISSION_HELP_TEXT","DatasetError","Error","dataset","projectId","args","options","cause","message","name","listSchemas","configPath","id","json","output","workDir","projectDatasets","URL","url","studioRootPath","workerData","schemas","getDatasetSchemas","parsedSchemas","parseSchemas","length","datasetString","map","log","JSON","stringify","printSchemas","workspaces","Promise","allSettled","error","schema","status","value","reason","statusCode","logDiagnostic","warn","bind","warning","filter","flat","rows","toSorted","a","b","_createdAt","localeCompare","createdAt","_id","workspace","workspaceData","find","w","CreatedAt","Dataset","Id","ProjectId","Workspace","table","columns","alignment","addRows","render"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/schema/listSchemas.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, studioWorkerTask} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {type Workspace} from 'sanity'\n\nimport {getSchemas} from '../../services/schemas.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {isDefined} from '../manifest/schemaTypeHelpers.js'\nimport {type StoredWorkspaceSchema} from '../manifest/types.js'\nimport {type UniqWorkspaceWorkerData} from './types.js'\nimport {getDatasetsOutString} from './utils/schemaStoreOutStrings.js'\nimport {SCHEMA_PERMISSION_HELP_TEXT} from './utils/schemaStoreValidation.js'\n\ninterface ListSchemasOptions {\n configPath: string\n json: boolean\n output: Output\n workDir: string\n\n id?: string\n}\n\nclass DatasetError extends Error {\n public dataset: string\n public projectId: string\n constructor(args: {dataset: string; options?: ErrorOptions; projectId: string}) {\n super((args.options?.cause as {message?: string})?.message, args.options)\n this.projectId = args.projectId\n this.dataset = args.dataset\n this.name = 'DatasetError'\n }\n}\n\nexport async function listSchemas(options: ListSchemasOptions): Promise<void> {\n const {configPath, id, json, output, workDir} = options\n\n const projectDatasets = await studioWorkerTask<(Workspace & {key: string})[]>(\n new URL('uniqueWorkspaces.worker.js', import.meta.url),\n {\n name: 'uniqueWorkspaces',\n studioRootPath: workDir,\n workerData: {configPath} satisfies UniqWorkspaceWorkerData,\n },\n )\n\n const schemas = await getDatasetSchemas(projectDatasets, id)\n const parsedSchemas = parseSchemas(schemas, output, json)\n\n if (parsedSchemas.length === 0) {\n const datasetString = getDatasetsOutString(projectDatasets.map((dataset) => dataset.dataset))\n\n throw new Error(\n id\n ? `Schema for id \"${id}\" not found in ${datasetString}`\n : `No schemas found in ${datasetString}`,\n )\n }\n\n if (json) {\n output.log(JSON.stringify(id ? parsedSchemas[0] : parsedSchemas, null, 2))\n } else {\n printSchemas({output, schemas: parsedSchemas, workspaces: projectDatasets})\n }\n}\n\nasync function getDatasetSchemas(projectDatasets: Workspace[], id?: string) {\n return Promise.allSettled(\n projectDatasets.map(async ({dataset, projectId}) => {\n try {\n return await getSchemas(dataset, projectId, id)\n } catch (error) {\n throw new DatasetError({dataset, options: {cause: error}, projectId})\n }\n }),\n )\n}\n\nfunction parseSchemas(\n schemas: PromiseSettledResult<StoredWorkspaceSchema[]>[],\n output: Output,\n json: boolean,\n) {\n return schemas\n .map((schema) => {\n if (schema.status === 'fulfilled') return schema.value\n\n const error = schema.reason\n\n if (error instanceof DatasetError) {\n if (\n 'cause' in error &&\n error.cause &&\n typeof error.cause === 'object' &&\n 'statusCode' in error.cause &&\n error.cause.statusCode === 401\n ) {\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText(\n 'yellow',\n `${logSymbols.warning} ↳ No permissions to read schema from \"${error.dataset}\". ${\n SCHEMA_PERMISSION_HELP_TEXT\n }:\\n ${styleText('red', `${error.message}`)}`,\n ),\n )\n return []\n }\n\n const logDiagnostic = json ? output.warn.bind(output) : output.log.bind(output)\n logDiagnostic(\n styleText('red', `↳ Failed to fetch schema from \"${error.dataset}\":\\n ${error.message}`),\n )\n return []\n } else {\n //hubris inc: given the try-catch wrapping all the full promise \"this should never happen\"\n throw error\n }\n })\n .filter((schema) => isDefined(schema))\n .flat()\n}\n\nfunction printSchemas({\n output,\n schemas,\n workspaces,\n}: {\n output: Output\n schemas: StoredWorkspaceSchema[]\n workspaces: Workspace[]\n}) {\n const rows = schemas\n .toSorted((a, b) => -(a._createdAt || '').localeCompare(b._createdAt || ''))\n .map(({_createdAt: createdAt, _id: id, workspace}) => {\n const workspaceData = workspaces.find((w) => w.name === workspace.name)\n if (!workspaceData) return\n\n return {\n CreatedAt: createdAt,\n Dataset: workspaceData.dataset,\n Id: id,\n ProjectId: workspaceData.projectId,\n Workspace: workspace.name,\n }\n })\n .filter((schema) => isDefined(schema))\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'Id'},\n {alignment: 'left', name: 'Workspace'},\n {alignment: 'left', name: 'Dataset'},\n {alignment: 'left', name: 'ProjectId'},\n {alignment: 'left', name: 'CreatedAt'},\n ],\n })\n\n table.addRows(rows)\n output.log(table.render())\n}\n"],"names":["styleText","studioWorkerTask","logSymbols","getSchemas","Table","isDefined","getDatasetsOutString","SCHEMA_PERMISSION_HELP_TEXT","DatasetError","Error","dataset","projectId","args","options","cause","message","name","listSchemas","configPath","id","json","output","workDir","projectDatasets","URL","url","studioRootPath","workerData","schemas","getDatasetSchemas","parsedSchemas","parseSchemas","length","datasetString","map","log","JSON","stringify","printSchemas","workspaces","Promise","allSettled","error","schema","status","value","reason","statusCode","logDiagnostic","warn","bind","warning","filter","flat","rows","toSorted","a","b","_createdAt","localeCompare","createdAt","_id","workspace","workspaceData","find","w","CreatedAt","Dataset","Id","ProjectId","Workspace","table","columns","alignment","addRows","render"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * API version for tokens endpoints
3
- */ export const TOKENS_API_VERSION = 'v2025-08-18';
2
+ * API version for the Access API endpoints backing the tokens commands
3
+ */ export const TOKENS_API_VERSION = 'v2025-07-11';
4
4
 
5
5
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/tokens/constants.ts"],"sourcesContent":["/**\n * API version for tokens endpoints\n */\nexport const TOKENS_API_VERSION = 'v2025-08-18'\n"],"names":["TOKENS_API_VERSION"],"mappings":"AAAA;;CAEC,GACD,OAAO,MAAMA,qBAAqB,cAAa"}
1
+ {"version":3,"sources":["../../../src/actions/tokens/constants.ts"],"sourcesContent":["/**\n * API version for the Access API endpoints backing the tokens commands\n */\nexport const TOKENS_API_VERSION = 'v2025-07-11'\n"],"names":["TOKENS_API_VERSION"],"mappings":"AAAA;;CAEC,GACD,OAAO,MAAMA,qBAAqB,cAAa"}
@@ -0,0 +1,35 @@
1
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
2
+ /**
3
+ * Parse a user-supplied expiry date or timestamp into an ISO 8601 timestamp
4
+ * @param value - The raw flag or prompt input
5
+ * @returns The normalized timestamp, or an error message describing why the
6
+ * input was rejected
7
+ *
8
+ * @internal
9
+ */ export function parseExpiryDate(value) {
10
+ const date = new Date(value);
11
+ if (Number.isNaN(date.getTime())) {
12
+ return {
13
+ error: `Invalid expiry date "${value}". Pass an ISO 8601 date or timestamp, for example 2027-01-01 or 2027-01-01T12:00:00Z.`
14
+ };
15
+ }
16
+ if (date.getTime() <= Date.now()) {
17
+ return {
18
+ error: `Expiry date "${value}" must be in the future.`
19
+ };
20
+ }
21
+ return {
22
+ expiresAt: date.toISOString()
23
+ };
24
+ }
25
+ /**
26
+ * Get the expiry timestamp a number of days from now
27
+ * @param days - The number of days until expiry
28
+ * @returns An ISO 8601 timestamp
29
+ *
30
+ * @internal
31
+ */ export function expiryInDays(days) {
32
+ return new Date(Date.now() + days * MS_PER_DAY).toISOString();
33
+ }
34
+
35
+ //# sourceMappingURL=expiry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/tokens/expiry.ts"],"sourcesContent":["const MS_PER_DAY = 24 * 60 * 60 * 1000\n\n/**\n * Parse a user-supplied expiry date or timestamp into an ISO 8601 timestamp\n * @param value - The raw flag or prompt input\n * @returns The normalized timestamp, or an error message describing why the\n * input was rejected\n *\n * @internal\n */\nexport function parseExpiryDate(value: string): {error: string} | {expiresAt: string} {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) {\n return {\n error: `Invalid expiry date \"${value}\". Pass an ISO 8601 date or timestamp, for example 2027-01-01 or 2027-01-01T12:00:00Z.`,\n }\n }\n if (date.getTime() <= Date.now()) {\n return {error: `Expiry date \"${value}\" must be in the future.`}\n }\n return {expiresAt: date.toISOString()}\n}\n\n/**\n * Get the expiry timestamp a number of days from now\n * @param days - The number of days until expiry\n * @returns An ISO 8601 timestamp\n *\n * @internal\n */\nexport function expiryInDays(days: number): string {\n return new Date(Date.now() + days * MS_PER_DAY).toISOString()\n}\n"],"names":["MS_PER_DAY","parseExpiryDate","value","date","Date","Number","isNaN","getTime","error","now","expiresAt","toISOString","expiryInDays","days"],"mappings":"AAAA,MAAMA,aAAa,KAAK,KAAK,KAAK;AAElC;;;;;;;CAOC,GACD,OAAO,SAASC,gBAAgBC,KAAa;IAC3C,MAAMC,OAAO,IAAIC,KAAKF;IACtB,IAAIG,OAAOC,KAAK,CAACH,KAAKI,OAAO,KAAK;QAChC,OAAO;YACLC,OAAO,CAAC,qBAAqB,EAAEN,MAAM,sFAAsF,CAAC;QAC9H;IACF;IACA,IAAIC,KAAKI,OAAO,MAAMH,KAAKK,GAAG,IAAI;QAChC,OAAO;YAACD,OAAO,CAAC,aAAa,EAAEN,MAAM,wBAAwB,CAAC;QAAA;IAChE;IACA,OAAO;QAACQ,WAAWP,KAAKQ,WAAW;IAAE;AACvC;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,aAAaC,IAAY;IACvC,OAAO,IAAIT,KAAKA,KAAKK,GAAG,KAAKI,OAAOb,YAAYW,WAAW;AAC7D"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/tokens/types.ts"],"sourcesContent":["interface TokenRole {\n name: string\n title: string\n}\n\nexport interface Token {\n createdAt: string\n createdBy: string\n id: string\n label: string\n lastUsedAt: string | null\n permissions: string[]\n projectId: string\n projectUserId: string\n roles: TokenRole[]\n}\n\nexport interface TokenResponse {\n id: string\n key: string\n label: string\n projectUserId: string\n roles: TokenRole[]\n}\n\nexport interface ProjectRole {\n appliesToRobots: boolean\n appliesToUsers: boolean\n description: string\n isCustom: boolean\n name: string\n projectId: string\n title: string\n}\n"],"names":[],"mappings":"AAyBA,WAQC"}
1
+ {"version":3,"sources":["../../../src/actions/tokens/types.ts"],"sourcesContent":["export interface Role {\n appliesToRobots: boolean\n appliesToUsers: boolean\n description: string\n isCustom: boolean\n name: string\n resourceId: string\n resourceType: string\n title: string\n}\n\nexport type SelectedTokenRole = Pick<Role, 'name' | 'title'>\n\nexport interface Membership {\n resourceId: string\n resourceType: string\n roleNames: string[]\n\n addedAt?: string\n lastSeenAt?: string | null\n resourceUserId?: string | null\n}\n\nexport interface Robot {\n createdAt: string\n id: string\n label: string\n memberships: Membership[]\n\n expiresAt?: string | null\n managedBy?: {\n resourceId: string\n resourceType: string\n }\n tokenId?: string\n}\n\nexport interface RobotWithToken extends Robot {\n token: string\n}\n"],"names":[],"mappings":"AAqCA,WAEC"}
@@ -5,7 +5,7 @@ import { getTokenRoles } from '../../services/tokens.js';
5
5
  * @param roleName - The role name to validate
6
6
  * @param projectId - The project ID
7
7
  * @param output - Output to raise the error through the calling command
8
- * @returns A promise that resolves to the validated role name
8
+ * @returns A promise that resolves to the validated role
9
9
  *
10
10
  * @internal
11
11
  */ export async function validateRole(roleName, projectId, output) {
@@ -13,7 +13,10 @@ import { getTokenRoles } from '../../services/tokens.js';
13
13
  const robotRoles = roles.filter((role)=>role.appliesToRobots);
14
14
  const role = robotRoles.find((r)=>r.name === roleName);
15
15
  if (role) {
16
- return roleName;
16
+ return {
17
+ name: role.name,
18
+ title: role.title
19
+ };
17
20
  }
18
21
  const availableRoles = robotRoles.map((r)=>r.name).join(', ');
19
22
  return output.error(`Invalid role "${roleName}". Available roles: ${availableRoles}`, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/tokens/validateRole.ts"],"sourcesContent":["import {exitCodes, type Output} from '@sanity/cli-core'\n\nimport {getTokenRoles} from '../../services/tokens.js'\n\n/**\n * Validate a role name\n * @param roleName - The role name to validate\n * @param projectId - The project ID\n * @param output - Output to raise the error through the calling command\n * @returns A promise that resolves to the validated role name\n *\n * @internal\n */\nexport async function validateRole(\n roleName: string,\n projectId: string,\n output: Output,\n): Promise<string> {\n const roles = await getTokenRoles(projectId)\n const robotRoles = roles.filter((role) => role.appliesToRobots)\n\n const role = robotRoles.find((r) => r.name === roleName)\n if (role) {\n return roleName\n }\n\n const availableRoles = robotRoles.map((r) => r.name).join(', ')\n return output.error(`Invalid role \"${roleName}\". Available roles: ${availableRoles}`, {\n exit: exitCodes.USAGE_ERROR,\n })\n}\n"],"names":["exitCodes","getTokenRoles","validateRole","roleName","projectId","output","roles","robotRoles","filter","role","appliesToRobots","find","r","name","availableRoles","map","join","error","exit","USAGE_ERROR"],"mappings":"AAAA,SAAQA,SAAS,QAAoB,mBAAkB;AAEvD,SAAQC,aAAa,QAAO,2BAA0B;AAEtD;;;;;;;;CAQC,GACD,OAAO,eAAeC,aACpBC,QAAgB,EAChBC,SAAiB,EACjBC,MAAc;IAEd,MAAMC,QAAQ,MAAML,cAAcG;IAClC,MAAMG,aAAaD,MAAME,MAAM,CAAC,CAACC,OAASA,KAAKC,eAAe;IAE9D,MAAMD,OAAOF,WAAWI,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKV;IAC/C,IAAIM,MAAM;QACR,OAAON;IACT;IAEA,MAAMW,iBAAiBP,WAAWQ,GAAG,CAAC,CAACH,IAAMA,EAAEC,IAAI,EAAEG,IAAI,CAAC;IAC1D,OAAOX,OAAOY,KAAK,CAAC,CAAC,cAAc,EAAEd,SAAS,oBAAoB,EAAEW,gBAAgB,EAAE;QACpFI,MAAMlB,UAAUmB,WAAW;IAC7B;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/tokens/validateRole.ts"],"sourcesContent":["import {exitCodes, type Output} from '@sanity/cli-core'\n\nimport {getTokenRoles} from '../../services/tokens.js'\nimport {type SelectedTokenRole} from './types.js'\n\n/**\n * Validate a role name\n * @param roleName - The role name to validate\n * @param projectId - The project ID\n * @param output - Output to raise the error through the calling command\n * @returns A promise that resolves to the validated role\n *\n * @internal\n */\nexport async function validateRole(\n roleName: string,\n projectId: string,\n output: Output,\n): Promise<SelectedTokenRole> {\n const roles = await getTokenRoles(projectId)\n const robotRoles = roles.filter((role) => role.appliesToRobots)\n\n const role = robotRoles.find((r) => r.name === roleName)\n if (role) {\n return {name: role.name, title: role.title}\n }\n\n const availableRoles = robotRoles.map((r) => r.name).join(', ')\n return output.error(`Invalid role \"${roleName}\". Available roles: ${availableRoles}`, {\n exit: exitCodes.USAGE_ERROR,\n })\n}\n"],"names":["exitCodes","getTokenRoles","validateRole","roleName","projectId","output","roles","robotRoles","filter","role","appliesToRobots","find","r","name","title","availableRoles","map","join","error","exit","USAGE_ERROR"],"mappings":"AAAA,SAAQA,SAAS,QAAoB,mBAAkB;AAEvD,SAAQC,aAAa,QAAO,2BAA0B;AAGtD;;;;;;;;CAQC,GACD,OAAO,eAAeC,aACpBC,QAAgB,EAChBC,SAAiB,EACjBC,MAAc;IAEd,MAAMC,QAAQ,MAAML,cAAcG;IAClC,MAAMG,aAAaD,MAAME,MAAM,CAAC,CAACC,OAASA,KAAKC,eAAe;IAE9D,MAAMD,OAAOF,WAAWI,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKV;IAC/C,IAAIM,MAAM;QACR,OAAO;YAACI,MAAMJ,KAAKI,IAAI;YAAEC,OAAOL,KAAKK,KAAK;QAAA;IAC5C;IAEA,MAAMC,iBAAiBR,WAAWS,GAAG,CAAC,CAACJ,IAAMA,EAAEC,IAAI,EAAEI,IAAI,CAAC;IAC1D,OAAOZ,OAAOa,KAAK,CAAC,CAAC,cAAc,EAAEf,SAAS,oBAAoB,EAAEY,gBAAgB,EAAE;QACpFI,MAAMnB,UAAUoB,WAAW;IAC7B;AACF"}
@@ -0,0 +1,6 @@
1
+ export const count = (amount, plural = '', singular = plural.slice(0, Math.max(0, plural.length - 1)))=>[
2
+ amount.toLocaleString('en-US'),
3
+ amount === 1 ? singular : plural
4
+ ].filter(Boolean).join(' ');
5
+
6
+ //# sourceMappingURL=count.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/count.ts"],"sourcesContent":["export const count = (\n amount: number,\n plural: string = '',\n singular: string = plural.slice(0, Math.max(0, plural.length - 1)),\n): string =>\n [amount.toLocaleString('en-US'), amount === 1 ? singular : plural].filter(Boolean).join(' ')\n"],"names":["count","amount","plural","singular","slice","Math","max","length","toLocaleString","filter","Boolean","join"],"mappings":"AAAA,OAAO,MAAMA,QAAQ,CACnBC,QACAC,SAAiB,EAAE,EACnBC,WAAmBD,OAAOE,KAAK,CAAC,GAAGC,KAAKC,GAAG,CAAC,GAAGJ,OAAOK,MAAM,GAAG,GAAG,GAElE;QAACN,OAAOO,cAAc,CAAC;QAAUP,WAAW,IAAIE,WAAWD;KAAO,CAACO,MAAM,CAACC,SAASC,IAAI,CAAC,KAAI"}
@@ -0,0 +1,5 @@
1
+ /** Formats a path so it is the same in Windows and Unix. */ export function formatPath(path) {
2
+ return path.replaceAll('\\', '/');
3
+ }
4
+
5
+ //# sourceMappingURL=formatPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/formatPath.ts"],"sourcesContent":["/** Formats a path so it is the same in Windows and Unix. */\nexport function formatPath(path: string): string {\n return path.replaceAll('\\\\', '/')\n}\n"],"names":["formatPath","path","replaceAll"],"mappings":"AAAA,0DAA0D,GAC1D,OAAO,SAASA,WAAWC,IAAY;IACrC,OAAOA,KAAKC,UAAU,CAAC,MAAM;AAC/B"}
@@ -0,0 +1,8 @@
1
+ const formatter = new Intl.NumberFormat('en-US', {
2
+ maximumFractionDigits: 1,
3
+ minimumFractionDigits: 1,
4
+ style: 'percent'
5
+ });
6
+ export const percent = (value)=>formatter.format(Math.min(value, 1));
7
+
8
+ //# sourceMappingURL=percent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/percent.ts"],"sourcesContent":["const formatter = new Intl.NumberFormat('en-US', {\n maximumFractionDigits: 1,\n minimumFractionDigits: 1,\n style: 'percent',\n})\n\nexport const percent = (value: number): string => formatter.format(Math.min(value, 1))\n"],"names":["formatter","Intl","NumberFormat","maximumFractionDigits","minimumFractionDigits","style","percent","value","format","Math","min"],"mappings":"AAAA,MAAMA,YAAY,IAAIC,KAAKC,YAAY,CAAC,SAAS;IAC/CC,uBAAuB;IACvBC,uBAAuB;IACvBC,OAAO;AACT;AAEA,OAAO,MAAMC,UAAU,CAACC,QAA0BP,UAAUQ,MAAM,CAACC,KAAKC,GAAG,CAACH,OAAO,IAAG"}
@@ -0,0 +1,88 @@
1
+ import { count } from './count.js';
2
+ import { formatPath } from './formatPath.js';
3
+ import { percent } from './percent.js';
4
+ /**
5
+ * Builds an onProgress handler that renders typegen progress to a spinner,
6
+ * matching the output the command produced before the library was decoupled.
7
+ */ export function createTypegenProgressRenderer(spin, context) {
8
+ const { formatGeneratedCode, generates, schema } = context;
9
+ // Track cross-event data needed for the final success message.
10
+ let evaluatedFiles = 0;
11
+ let queriesCount = 0;
12
+ let queryFilesCount = 0;
13
+ let schemaTypesCount = 0;
14
+ let formatterName;
15
+ let formattingError = false;
16
+ return (event)=>{
17
+ switch(event.type){
18
+ case 'complete':
19
+ {
20
+ const { result } = event;
21
+ if (result.filesWithErrors > 0) {
22
+ spin.warn(`Encountered errors in ${count(result.filesWithErrors, 'files')} while generating types`);
23
+ }
24
+ let successText = `Successfully generated types to ${formatPath(generates)} in ${Number(result.duration).toFixed(0)}ms` + `\n └─ ${count(queriesCount, 'queries', 'query')} and ${count(schemaTypesCount, 'schema types', 'schema type')}` + `\n └─ found queries in ${count(queryFilesCount, 'files', 'file')} after evaluating ${count(evaluatedFiles, 'files', 'file')}`;
25
+ // formatGeneratedCode !== false means a formatter was attempted.
26
+ if (formatGeneratedCode !== false && formatterName) {
27
+ successText += `\n └─ ${formattingError ? 'an error occurred during formatting' : `formatted the generated code with ${formatterName}`}`;
28
+ }
29
+ spin.succeed(successText);
30
+ return;
31
+ }
32
+ case 'formatFailed':
33
+ {
34
+ formatterName = event.formatterName;
35
+ formattingError = true;
36
+ spin.warn(`Failed to format generated types with ${event.formatterName}: ${event.message}`);
37
+ return;
38
+ }
39
+ case 'formatting':
40
+ {
41
+ formatterName = event.formatterName;
42
+ spin.text = `Formatting generated types with ${event.formatterName}…`;
43
+ return;
44
+ }
45
+ case 'moduleEvaluated':
46
+ {
47
+ evaluatedFiles = event.evaluatedFiles;
48
+ queriesCount = event.queriesCount;
49
+ queryFilesCount = event.queryFilesCount;
50
+ // `fail` stops the spinner, so it has to be restarted to keep rendering
51
+ // progress. Restarting only after a failure (rather than whenever the
52
+ // spinner reports it is not spinning) keeps non-interactive output
53
+ // quiet: a disabled spinner never reports itself as spinning, and each
54
+ // `start` writes a line, which would emit progress once per source file.
55
+ for (const message of event.errors){
56
+ spin.fail(message);
57
+ }
58
+ if (event.errors.length > 0) {
59
+ spin.start();
60
+ }
61
+ spin.text = `Generating query types… (${percent(event.evaluatedFiles / event.expectedFileCount)})\n` + ` └─ Processed ${count(event.evaluatedFiles)} of ${count(event.expectedFileCount, 'files')}. ` + `Found ${count(event.queriesCount, 'queries', 'query')} from ${count(event.queryFilesCount, 'files')}.`;
62
+ return;
63
+ }
64
+ case 'schemaLoaded':
65
+ {
66
+ spin.succeed(`Schema loaded from ${formatPath(schema)}`);
67
+ spin.start('Generating schema types…');
68
+ return;
69
+ }
70
+ case 'schemaTypesGenerated':
71
+ {
72
+ schemaTypesCount = event.schemaTypesCount;
73
+ spin.text = 'Generating query types…';
74
+ return;
75
+ }
76
+ case 'typegenStarted':
77
+ {
78
+ return;
79
+ }
80
+ default:
81
+ {
82
+ return;
83
+ }
84
+ }
85
+ };
86
+ }
87
+
88
+ //# sourceMappingURL=renderTypegenProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/renderTypegenProgress.ts"],"sourcesContent":["import {type TypeGenConfig, type TypegenProgressEvent} from '@sanity/codegen'\n\nimport {count} from './count.js'\nimport {formatPath} from './formatPath.js'\nimport {percent} from './percent.js'\n\n/**\n * Minimal structural shape of the spinner the renderer depends on.\n *\n * The `@sanity/cli-core/ux` `spinner` factory returns an instance whose\n * methods return `this` (for chaining), which is assignable to this\n * `void`-returning interface. This is deliberately narrower than the real\n * spinner type so that test doubles (plain object literals) can satisfy it\n * structurally without a type assertion.\n */\nexport interface TypegenSpinner {\n fail(text?: string): void\n start(text?: string): void\n succeed(text?: string): void\n text: string\n warn(text?: string): void\n}\n\ninterface RendererContext {\n // Indexed access avoids needing a dedicated FormatGeneratedCode export from @sanity/codegen.\n formatGeneratedCode: TypeGenConfig['formatGeneratedCode']\n generates: string\n schema: string\n}\n\n/**\n * Builds an onProgress handler that renders typegen progress to a spinner,\n * matching the output the command produced before the library was decoupled.\n */\nexport function createTypegenProgressRenderer(\n spin: TypegenSpinner,\n context: RendererContext,\n): (event: TypegenProgressEvent) => void {\n const {formatGeneratedCode, generates, schema} = context\n\n // Track cross-event data needed for the final success message.\n let evaluatedFiles = 0\n let queriesCount = 0\n let queryFilesCount = 0\n let schemaTypesCount = 0\n let formatterName: string | undefined\n let formattingError = false\n\n return (event) => {\n switch (event.type) {\n case 'complete': {\n const {result} = event\n if (result.filesWithErrors > 0) {\n spin.warn(\n `Encountered errors in ${count(result.filesWithErrors, 'files')} while generating types`,\n )\n }\n\n let successText =\n `Successfully generated types to ${formatPath(generates)} in ${Number(result.duration).toFixed(0)}ms` +\n `\\n └─ ${count(queriesCount, 'queries', 'query')} and ${count(schemaTypesCount, 'schema types', 'schema type')}` +\n `\\n └─ found queries in ${count(queryFilesCount, 'files', 'file')} after evaluating ${count(evaluatedFiles, 'files', 'file')}`\n\n // formatGeneratedCode !== false means a formatter was attempted.\n if (formatGeneratedCode !== false && formatterName) {\n successText += `\\n └─ ${formattingError ? 'an error occurred during formatting' : `formatted the generated code with ${formatterName}`}`\n }\n\n spin.succeed(successText)\n return\n }\n case 'formatFailed': {\n formatterName = event.formatterName\n formattingError = true\n spin.warn(`Failed to format generated types with ${event.formatterName}: ${event.message}`)\n return\n }\n case 'formatting': {\n formatterName = event.formatterName\n spin.text = `Formatting generated types with ${event.formatterName}…`\n return\n }\n case 'moduleEvaluated': {\n evaluatedFiles = event.evaluatedFiles\n queriesCount = event.queriesCount\n queryFilesCount = event.queryFilesCount\n\n // `fail` stops the spinner, so it has to be restarted to keep rendering\n // progress. Restarting only after a failure (rather than whenever the\n // spinner reports it is not spinning) keeps non-interactive output\n // quiet: a disabled spinner never reports itself as spinning, and each\n // `start` writes a line, which would emit progress once per source file.\n for (const message of event.errors) {\n spin.fail(message)\n }\n if (event.errors.length > 0) {\n spin.start()\n }\n\n spin.text =\n `Generating query types… (${percent(event.evaluatedFiles / event.expectedFileCount)})\\n` +\n ` └─ Processed ${count(event.evaluatedFiles)} of ${count(event.expectedFileCount, 'files')}. ` +\n `Found ${count(event.queriesCount, 'queries', 'query')} from ${count(event.queryFilesCount, 'files')}.`\n return\n }\n case 'schemaLoaded': {\n spin.succeed(`Schema loaded from ${formatPath(schema)}`)\n spin.start('Generating schema types…')\n return\n }\n case 'schemaTypesGenerated': {\n schemaTypesCount = event.schemaTypesCount\n spin.text = 'Generating query types…'\n return\n }\n case 'typegenStarted': {\n return\n }\n default: {\n return\n }\n }\n }\n}\n"],"names":["count","formatPath","percent","createTypegenProgressRenderer","spin","context","formatGeneratedCode","generates","schema","evaluatedFiles","queriesCount","queryFilesCount","schemaTypesCount","formatterName","formattingError","event","type","result","filesWithErrors","warn","successText","Number","duration","toFixed","succeed","message","text","errors","fail","length","start","expectedFileCount"],"mappings":"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"}
@@ -75,17 +75,14 @@ export function createStudioUndeployAdapter(cliConfig) {
75
75
  }
76
76
  function toUndeployTarget(application, type) {
77
77
  return {
78
- activeDeployment: application.activeDeployment ? {
79
- deployedAt: application.activeDeployment.deployedAt,
80
- deployedBy: application.activeDeployment.deployedBy
81
- } : null,
82
- appHost: application.appHost ?? null,
83
- createdAt: application.createdAt ?? null,
78
+ application,
84
79
  deletes: 'application',
85
80
  id: application.id,
86
- organizationId: application.organizationId ?? null,
87
- projectId: application.projectId ?? null,
88
- title: application.title ?? null,
81
+ payload: {
82
+ appId: application.id,
83
+ type
84
+ },
85
+ title: application.title,
89
86
  type,
90
87
  url: resolveTargetUrl(application, type)
91
88
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/undeploy/adapters.ts"],"sourcesContent":["import {type CliConfig} from '@sanity/cli-core'\nimport {\n type UndeployAdapter,\n type UndeployApplicationTarget,\n type UndeployTarget,\n} from '@sanity/cli-core/undeploy'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\n\nimport {\n deleteUserApplication,\n getUserApplication,\n type UserApplication,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nexport function createAppUndeployAdapter(\n cliConfig: CliConfig,\n): UndeployAdapter<UndeployApplicationTarget> {\n return {\n async resolveTarget() {\n const appId = getAppId(cliConfig)\n if (!appId) {\n return {\n message: 'No `deployment.appId` configured',\n solution: 'Add `deployment.appId` to sanity.cli.ts',\n type: 'none',\n }\n }\n\n const application = await getUserApplication({appId, isSdkApp: true})\n if (!application) {\n return {message: 'Application with the given ID does not exist', type: 'none'}\n }\n\n return {target: toUndeployTarget(application, 'coreApp'), type: 'found'}\n },\n type: 'coreApp',\n undeploy: ({id}) => deleteUserApplication({applicationId: id, appType: 'coreApp'}),\n }\n}\n\nexport function createStudioUndeployAdapter(\n cliConfig: CliConfig,\n): UndeployAdapter<UndeployApplicationTarget> {\n return {\n async resolveTarget() {\n const appId = cliConfig.deployment?.appId\n const studioHost = cliConfig.studioHost\n if (!appId && !studioHost) {\n return {\n message: 'No studio hostname configured',\n solution: 'Set `studioHost` in sanity.cli.ts',\n type: 'none',\n }\n }\n\n const projectId = cliConfig.api?.projectId\n if (!projectId) throw new Error(NO_PROJECT_ID)\n\n const application = await getUserApplication({\n appHost: studioHost,\n appId,\n isSdkApp: false,\n projectId,\n })\n if (!application) {\n return {\n message:\n 'Your project has not been assigned an app ID or a studio hostname, or the `appId` or `studioHost` provided does not exist',\n type: 'none',\n }\n }\n\n return {target: toUndeployTarget(application, 'studio'), type: 'found'}\n },\n type: 'studio',\n undeploy: ({id}) => deleteUserApplication({applicationId: id, appType: 'studio'}),\n }\n}\n\nfunction toUndeployTarget(\n application: UserApplication,\n type: UndeployTarget['type'],\n): UndeployApplicationTarget {\n return {\n activeDeployment: application.activeDeployment\n ? {\n deployedAt: application.activeDeployment.deployedAt,\n deployedBy: application.activeDeployment.deployedBy,\n }\n : null,\n appHost: application.appHost ?? null,\n createdAt: application.createdAt ?? null,\n deletes: 'application',\n id: application.id,\n organizationId: application.organizationId ?? null,\n projectId: application.projectId ?? null,\n title: application.title ?? null,\n type,\n url: resolveTargetUrl(application, type),\n }\n}\n\nfunction resolveTargetUrl(\n application: UserApplication,\n type: UndeployTarget['type'],\n): string | null {\n if (type === 'coreApp') {\n return application.organizationId\n ? getCoreAppUrl(application.organizationId, application.id)\n : null\n }\n if (!application.appHost) return null\n return application.urlType === 'external'\n ? application.appHost\n : `https://${application.appHost}.sanity.studio`\n}\n"],"names":["getCoreAppUrl","deleteUserApplication","getUserApplication","getAppId","NO_PROJECT_ID","createAppUndeployAdapter","cliConfig","resolveTarget","appId","message","solution","type","application","isSdkApp","target","toUndeployTarget","undeploy","id","applicationId","appType","createStudioUndeployAdapter","deployment","studioHost","projectId","api","Error","appHost","activeDeployment","deployedAt","deployedBy","createdAt","deletes","organizationId","title","url","resolveTargetUrl","urlType"],"mappings":"AAMA,SAAQA,aAAa,QAAO,wBAAuB;AAEnD,SACEC,qBAAqB,EACrBC,kBAAkB,QAEb,qCAAoC;AAC3C,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,OAAO,SAASC,yBACdC,SAAoB;IAEpB,OAAO;QACL,MAAMC;YACJ,MAAMC,QAAQL,SAASG;YACvB,IAAI,CAACE,OAAO;gBACV,OAAO;oBACLC,SAAS;oBACTC,UAAU;oBACVC,MAAM;gBACR;YACF;YAEA,MAAMC,cAAc,MAAMV,mBAAmB;gBAACM;gBAAOK,UAAU;YAAI;YACnE,IAAI,CAACD,aAAa;gBAChB,OAAO;oBAACH,SAAS;oBAAgDE,MAAM;gBAAM;YAC/E;YAEA,OAAO;gBAACG,QAAQC,iBAAiBH,aAAa;gBAAYD,MAAM;YAAO;QACzE;QACAA,MAAM;QACNK,UAAU,CAAC,EAACC,EAAE,EAAC,GAAKhB,sBAAsB;gBAACiB,eAAeD;gBAAIE,SAAS;YAAS;IAClF;AACF;AAEA,OAAO,SAASC,4BACdd,SAAoB;IAEpB,OAAO;QACL,MAAMC;YACJ,MAAMC,QAAQF,UAAUe,UAAU,EAAEb;YACpC,MAAMc,aAAahB,UAAUgB,UAAU;YACvC,IAAI,CAACd,SAAS,CAACc,YAAY;gBACzB,OAAO;oBACLb,SAAS;oBACTC,UAAU;oBACVC,MAAM;gBACR;YACF;YAEA,MAAMY,YAAYjB,UAAUkB,GAAG,EAAED;YACjC,IAAI,CAACA,WAAW,MAAM,IAAIE,MAAMrB;YAEhC,MAAMQ,cAAc,MAAMV,mBAAmB;gBAC3CwB,SAASJ;gBACTd;gBACAK,UAAU;gBACVU;YACF;YACA,IAAI,CAACX,aAAa;gBAChB,OAAO;oBACLH,SACE;oBACFE,MAAM;gBACR;YACF;YAEA,OAAO;gBAACG,QAAQC,iBAAiBH,aAAa;gBAAWD,MAAM;YAAO;QACxE;QACAA,MAAM;QACNK,UAAU,CAAC,EAACC,EAAE,EAAC,GAAKhB,sBAAsB;gBAACiB,eAAeD;gBAAIE,SAAS;YAAQ;IACjF;AACF;AAEA,SAASJ,iBACPH,WAA4B,EAC5BD,IAA4B;IAE5B,OAAO;QACLgB,kBAAkBf,YAAYe,gBAAgB,GAC1C;YACEC,YAAYhB,YAAYe,gBAAgB,CAACC,UAAU;YACnDC,YAAYjB,YAAYe,gBAAgB,CAACE,UAAU;QACrD,IACA;QACJH,SAASd,YAAYc,OAAO,IAAI;QAChCI,WAAWlB,YAAYkB,SAAS,IAAI;QACpCC,SAAS;QACTd,IAAIL,YAAYK,EAAE;QAClBe,gBAAgBpB,YAAYoB,cAAc,IAAI;QAC9CT,WAAWX,YAAYW,SAAS,IAAI;QACpCU,OAAOrB,YAAYqB,KAAK,IAAI;QAC5BtB;QACAuB,KAAKC,iBAAiBvB,aAAaD;IACrC;AACF;AAEA,SAASwB,iBACPvB,WAA4B,EAC5BD,IAA4B;IAE5B,IAAIA,SAAS,WAAW;QACtB,OAAOC,YAAYoB,cAAc,GAC7BhC,cAAcY,YAAYoB,cAAc,EAAEpB,YAAYK,EAAE,IACxD;IACN;IACA,IAAI,CAACL,YAAYc,OAAO,EAAE,OAAO;IACjC,OAAOd,YAAYwB,OAAO,KAAK,aAC3BxB,YAAYc,OAAO,GACnB,CAAC,QAAQ,EAAEd,YAAYc,OAAO,CAAC,cAAc,CAAC;AACpD"}
1
+ {"version":3,"sources":["../../../src/actions/undeploy/adapters.ts"],"sourcesContent":["import {type CliConfig} from '@sanity/cli-core'\nimport {type UndeployAdapter, type UndeployApplicationTarget} from '@sanity/cli-core/undeploy'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\n\nimport {\n deleteUserApplication,\n getUserApplication,\n type UserApplication,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nexport function createAppUndeployAdapter(\n cliConfig: CliConfig,\n): UndeployAdapter<UndeployApplicationTarget> {\n return {\n async resolveTarget() {\n const appId = getAppId(cliConfig)\n if (!appId) {\n return {\n message: 'No `deployment.appId` configured',\n solution: 'Add `deployment.appId` to sanity.cli.ts',\n type: 'none',\n }\n }\n\n const application = await getUserApplication({appId, isSdkApp: true})\n if (!application) {\n return {message: 'Application with the given ID does not exist', type: 'none'}\n }\n\n return {target: toUndeployTarget(application, 'coreApp'), type: 'found'}\n },\n type: 'coreApp',\n undeploy: ({id}) => deleteUserApplication({applicationId: id, appType: 'coreApp'}),\n }\n}\n\nexport function createStudioUndeployAdapter(\n cliConfig: CliConfig,\n): UndeployAdapter<UndeployApplicationTarget> {\n return {\n async resolveTarget() {\n const appId = cliConfig.deployment?.appId\n const studioHost = cliConfig.studioHost\n if (!appId && !studioHost) {\n return {\n message: 'No studio hostname configured',\n solution: 'Set `studioHost` in sanity.cli.ts',\n type: 'none',\n }\n }\n\n const projectId = cliConfig.api?.projectId\n if (!projectId) throw new Error(NO_PROJECT_ID)\n\n const application = await getUserApplication({\n appHost: studioHost,\n appId,\n isSdkApp: false,\n projectId,\n })\n if (!application) {\n return {\n message:\n 'Your project has not been assigned an app ID or a studio hostname, or the `appId` or `studioHost` provided does not exist',\n type: 'none',\n }\n }\n\n return {target: toUndeployTarget(application, 'studio'), type: 'found'}\n },\n type: 'studio',\n undeploy: ({id}) => deleteUserApplication({applicationId: id, appType: 'studio'}),\n }\n}\n\nfunction toUndeployTarget(\n application: UserApplication,\n type: UndeployApplicationTarget['type'],\n): UndeployApplicationTarget {\n return {\n application,\n deletes: 'application',\n id: application.id,\n payload: {appId: application.id, type},\n title: application.title,\n type,\n url: resolveTargetUrl(application, type),\n }\n}\n\nfunction resolveTargetUrl(\n application: UserApplication,\n type: UndeployApplicationTarget['type'],\n): string | null {\n if (type === 'coreApp') {\n return application.organizationId\n ? getCoreAppUrl(application.organizationId, application.id)\n : null\n }\n if (!application.appHost) return null\n return application.urlType === 'external'\n ? application.appHost\n : `https://${application.appHost}.sanity.studio`\n}\n"],"names":["getCoreAppUrl","deleteUserApplication","getUserApplication","getAppId","NO_PROJECT_ID","createAppUndeployAdapter","cliConfig","resolveTarget","appId","message","solution","type","application","isSdkApp","target","toUndeployTarget","undeploy","id","applicationId","appType","createStudioUndeployAdapter","deployment","studioHost","projectId","api","Error","appHost","deletes","payload","title","url","resolveTargetUrl","organizationId","urlType"],"mappings":"AAEA,SAAQA,aAAa,QAAO,wBAAuB;AAEnD,SACEC,qBAAqB,EACrBC,kBAAkB,QAEb,qCAAoC;AAC3C,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,OAAO,SAASC,yBACdC,SAAoB;IAEpB,OAAO;QACL,MAAMC;YACJ,MAAMC,QAAQL,SAASG;YACvB,IAAI,CAACE,OAAO;gBACV,OAAO;oBACLC,SAAS;oBACTC,UAAU;oBACVC,MAAM;gBACR;YACF;YAEA,MAAMC,cAAc,MAAMV,mBAAmB;gBAACM;gBAAOK,UAAU;YAAI;YACnE,IAAI,CAACD,aAAa;gBAChB,OAAO;oBAACH,SAAS;oBAAgDE,MAAM;gBAAM;YAC/E;YAEA,OAAO;gBAACG,QAAQC,iBAAiBH,aAAa;gBAAYD,MAAM;YAAO;QACzE;QACAA,MAAM;QACNK,UAAU,CAAC,EAACC,EAAE,EAAC,GAAKhB,sBAAsB;gBAACiB,eAAeD;gBAAIE,SAAS;YAAS;IAClF;AACF;AAEA,OAAO,SAASC,4BACdd,SAAoB;IAEpB,OAAO;QACL,MAAMC;YACJ,MAAMC,QAAQF,UAAUe,UAAU,EAAEb;YACpC,MAAMc,aAAahB,UAAUgB,UAAU;YACvC,IAAI,CAACd,SAAS,CAACc,YAAY;gBACzB,OAAO;oBACLb,SAAS;oBACTC,UAAU;oBACVC,MAAM;gBACR;YACF;YAEA,MAAMY,YAAYjB,UAAUkB,GAAG,EAAED;YACjC,IAAI,CAACA,WAAW,MAAM,IAAIE,MAAMrB;YAEhC,MAAMQ,cAAc,MAAMV,mBAAmB;gBAC3CwB,SAASJ;gBACTd;gBACAK,UAAU;gBACVU;YACF;YACA,IAAI,CAACX,aAAa;gBAChB,OAAO;oBACLH,SACE;oBACFE,MAAM;gBACR;YACF;YAEA,OAAO;gBAACG,QAAQC,iBAAiBH,aAAa;gBAAWD,MAAM;YAAO;QACxE;QACAA,MAAM;QACNK,UAAU,CAAC,EAACC,EAAE,EAAC,GAAKhB,sBAAsB;gBAACiB,eAAeD;gBAAIE,SAAS;YAAQ;IACjF;AACF;AAEA,SAASJ,iBACPH,WAA4B,EAC5BD,IAAuC;IAEvC,OAAO;QACLC;QACAe,SAAS;QACTV,IAAIL,YAAYK,EAAE;QAClBW,SAAS;YAACpB,OAAOI,YAAYK,EAAE;YAAEN;QAAI;QACrCkB,OAAOjB,YAAYiB,KAAK;QACxBlB;QACAmB,KAAKC,iBAAiBnB,aAAaD;IACrC;AACF;AAEA,SAASoB,iBACPnB,WAA4B,EAC5BD,IAAuC;IAEvC,IAAIA,SAAS,WAAW;QACtB,OAAOC,YAAYoB,cAAc,GAC7BhC,cAAcY,YAAYoB,cAAc,EAAEpB,YAAYK,EAAE,IACxD;IACN;IACA,IAAI,CAACL,YAAYc,OAAO,EAAE,OAAO;IACjC,OAAOd,YAAYqB,OAAO,KAAK,aAC3BrB,YAAYc,OAAO,GACnB,CAAC,QAAQ,EAAEd,YAAYc,OAAO,CAAC,cAAc,CAAC;AACpD"}
@@ -15,8 +15,7 @@ const undeployDebug = subdebug('undeploy');
15
15
  */ export async function runUndeploy(options, adapter) {
16
16
  const { flags, output } = options;
17
17
  const json = !!flags.json;
18
- // The report-only `summary` lines never enter the payload
19
- const emitJson = (payload)=>output.log(JSON.stringify(payload, (key, value)=>key === 'summary' ? undefined : value, 2));
18
+ const emitJson = (payload)=>output.log(JSON.stringify(payload, null, 2));
20
19
  // The JSON payload owns stdout, so the run's progress logs go to stderr; only
21
20
  // the final JSON.stringify writes to stdout.
22
21
  const runOptions = json ? {
@@ -50,9 +49,12 @@ const undeployDebug = subdebug('undeploy');
50
49
  // printed its plan, so only a real undeploy adds the {undeployed: false} envelope.
51
50
  if (json && !flags['dry-run']) {
52
51
  emitJson({
52
+ application: null,
53
53
  error: {
54
54
  message: failure.message
55
55
  },
56
+ payload: null,
57
+ reason: failure.message,
56
58
  undeployed: false
57
59
  });
58
60
  }
@@ -71,6 +73,8 @@ const undeployDebug = subdebug('undeploy');
71
73
  if (resolution.solution) output.log(`${resolution.solution}.`);
72
74
  output.log('Nothing to undeploy.');
73
75
  return {
76
+ application: null,
77
+ payload: null,
74
78
  reason: resolution.message,
75
79
  undeployed: false
76
80
  };
@@ -107,8 +111,12 @@ const undeployDebug = subdebug('undeploy');
107
111
  spin.succeed();
108
112
  printUndeployed(target, output);
109
113
  return {
110
- application: target,
111
- undeployed: true
114
+ application: target.application ?? null,
115
+ deletes: target.deletes,
116
+ payload: target.payload,
117
+ reason: null,
118
+ undeployed: true,
119
+ url: target.url
112
120
  };
113
121
  }
114
122
  /**