@sanity/cli 6.0.0-alpha.19 → 6.0.0-alpha.21

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 (229) hide show
  1. package/README.md +713 -533
  2. package/dist/actions/auth/authServer.js +13 -11
  3. package/dist/actions/auth/authServer.js.map +1 -1
  4. package/dist/actions/auth/login/getProvider.js +43 -39
  5. package/dist/actions/auth/login/getProvider.js.map +1 -1
  6. package/dist/actions/auth/login/getSSOProvider.js +25 -19
  7. package/dist/actions/auth/login/getSSOProvider.js.map +1 -1
  8. package/dist/actions/auth/login/login.js +12 -33
  9. package/dist/actions/auth/login/login.js.map +1 -1
  10. package/dist/actions/auth/types.js.map +1 -1
  11. package/dist/actions/codemods/reactIconsV3.js +2 -2
  12. package/dist/actions/codemods/reactIconsV3.js.map +1 -1
  13. package/dist/actions/debug/formatters.js +22 -0
  14. package/dist/actions/debug/formatters.js.map +1 -0
  15. package/dist/actions/dev/getDashboardAppUrl.js +3 -3
  16. package/dist/actions/dev/getDashboardAppUrl.js.map +1 -1
  17. package/dist/actions/documents/validateDocuments.worker.js +2 -2
  18. package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
  19. package/dist/actions/documents/validation/reporters/prettyReporter/formatDocumentValidation.js +1 -1
  20. package/dist/actions/documents/validation/reporters/prettyReporter/formatDocumentValidation.js.map +1 -1
  21. package/dist/actions/documents/validation/reporters/prettyReporter/tree.js +108 -0
  22. package/dist/actions/documents/validation/reporters/prettyReporter/tree.js.map +1 -0
  23. package/dist/actions/graphql/SchemaError.js +4 -26
  24. package/dist/actions/graphql/SchemaError.js.map +1 -1
  25. package/dist/actions/graphql/extractFromSanitySchema.js +3 -4
  26. package/dist/actions/graphql/extractFromSanitySchema.js.map +1 -1
  27. package/dist/actions/graphql/extractGraphQLAPIs.js +150 -0
  28. package/dist/actions/graphql/extractGraphQLAPIs.js.map +1 -0
  29. package/dist/actions/graphql/extractGraphQLAPIs.worker.js +12 -0
  30. package/dist/actions/graphql/extractGraphQLAPIs.worker.js.map +1 -0
  31. package/dist/actions/graphql/gen1/index.js +5 -5
  32. package/dist/actions/graphql/gen1/index.js.map +1 -1
  33. package/dist/actions/graphql/gen2/index.js +6 -6
  34. package/dist/actions/graphql/gen2/index.js.map +1 -1
  35. package/dist/actions/graphql/gen3/generateTypeQueries.js +2 -3
  36. package/dist/actions/graphql/gen3/generateTypeQueries.js.map +1 -1
  37. package/dist/actions/graphql/gen3/index.js +6 -7
  38. package/dist/actions/graphql/gen3/index.js.map +1 -1
  39. package/dist/actions/graphql/getGraphQLAPIs.js +12 -35
  40. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  41. package/dist/actions/graphql/getGraphQLAPIs.worker.js +75 -106
  42. package/dist/actions/graphql/getGraphQLAPIs.worker.js.map +1 -1
  43. package/dist/actions/graphql/helpers.js +13 -0
  44. package/dist/actions/graphql/helpers.js.map +1 -1
  45. package/dist/actions/graphql/resolveGraphQLApisFromWorkspaces.js +187 -0
  46. package/dist/actions/graphql/resolveGraphQLApisFromWorkspaces.js.map +1 -0
  47. package/dist/actions/graphql/types.js +1 -1
  48. package/dist/actions/graphql/types.js.map +1 -1
  49. package/dist/actions/init/bootstrapLocalTemplate.js +2 -1
  50. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  51. package/dist/actions/init/bootstrapRemoteTemplate.js +6 -5
  52. package/dist/actions/init/bootstrapRemoteTemplate.js.map +1 -1
  53. package/dist/actions/init/createPackageManifest.js +5 -0
  54. package/dist/actions/init/createPackageManifest.js.map +1 -1
  55. package/dist/actions/init/templates/appQuickstart.js +2 -1
  56. package/dist/actions/init/templates/appQuickstart.js.map +1 -1
  57. package/dist/actions/init/templates/appSanityUi.js +2 -1
  58. package/dist/actions/init/templates/appSanityUi.js.map +1 -1
  59. package/dist/actions/init/types.js.map +1 -1
  60. package/dist/actions/media/importMedia.js +1 -2
  61. package/dist/actions/media/importMedia.js.map +1 -1
  62. package/dist/actions/projects/getManageUrl.js +1 -2
  63. package/dist/actions/projects/getManageUrl.js.map +1 -1
  64. package/dist/actions/schema/validateSchema.worker.js +1 -3
  65. package/dist/actions/schema/validateSchema.worker.js.map +1 -1
  66. package/dist/actions/telemetry/isTrueish.js +10 -0
  67. package/dist/actions/telemetry/isTrueish.js.map +1 -0
  68. package/dist/actions/telemetry/resolveConsent.js +2 -1
  69. package/dist/actions/telemetry/resolveConsent.js.map +1 -1
  70. package/dist/actions/telemetry/setConsent.js +2 -1
  71. package/dist/actions/telemetry/setConsent.js.map +1 -1
  72. package/dist/actions/versions/findSanityModulesVersions.js +1 -2
  73. package/dist/actions/versions/findSanityModulesVersions.js.map +1 -1
  74. package/dist/commands/backup/disable.js +21 -1
  75. package/dist/commands/backup/disable.js.map +1 -1
  76. package/dist/commands/backup/download.js +18 -4
  77. package/dist/commands/backup/download.js.map +1 -1
  78. package/dist/commands/backup/enable.js +21 -1
  79. package/dist/commands/backup/enable.js.map +1 -1
  80. package/dist/commands/backup/list.js +15 -1
  81. package/dist/commands/backup/list.js.map +1 -1
  82. package/dist/commands/cors/add.js +19 -1
  83. package/dist/commands/cors/add.js.map +1 -1
  84. package/dist/commands/cors/delete.js +21 -1
  85. package/dist/commands/cors/delete.js.map +1 -1
  86. package/dist/commands/cors/list.js +21 -1
  87. package/dist/commands/cors/list.js.map +1 -1
  88. package/dist/commands/dataset/alias/create.js +4 -2
  89. package/dist/commands/dataset/alias/create.js.map +1 -1
  90. package/dist/commands/dataset/alias/delete.js +4 -2
  91. package/dist/commands/dataset/alias/delete.js.map +1 -1
  92. package/dist/commands/dataset/alias/link.js +4 -2
  93. package/dist/commands/dataset/alias/link.js.map +1 -1
  94. package/dist/commands/dataset/alias/unlink.js +4 -2
  95. package/dist/commands/dataset/alias/unlink.js.map +1 -1
  96. package/dist/commands/dataset/copy.js +4 -2
  97. package/dist/commands/dataset/copy.js.map +1 -1
  98. package/dist/commands/dataset/create.js +4 -2
  99. package/dist/commands/dataset/create.js.map +1 -1
  100. package/dist/commands/dataset/delete.js +4 -2
  101. package/dist/commands/dataset/delete.js.map +1 -1
  102. package/dist/commands/dataset/embeddings/disable.js +4 -2
  103. package/dist/commands/dataset/embeddings/disable.js.map +1 -1
  104. package/dist/commands/dataset/embeddings/enable.js +6 -4
  105. package/dist/commands/dataset/embeddings/enable.js.map +1 -1
  106. package/dist/commands/dataset/embeddings/status.js +4 -2
  107. package/dist/commands/dataset/embeddings/status.js.map +1 -1
  108. package/dist/commands/dataset/export.js +7 -11
  109. package/dist/commands/dataset/export.js.map +1 -1
  110. package/dist/commands/dataset/list.js +4 -2
  111. package/dist/commands/dataset/list.js.map +1 -1
  112. package/dist/commands/dataset/visibility/get.js +4 -2
  113. package/dist/commands/dataset/visibility/get.js.map +1 -1
  114. package/dist/commands/dataset/visibility/set.js +4 -2
  115. package/dist/commands/dataset/visibility/set.js.map +1 -1
  116. package/dist/commands/debug.js +2 -1
  117. package/dist/commands/debug.js.map +1 -1
  118. package/dist/commands/documents/create.js +15 -5
  119. package/dist/commands/documents/create.js.map +1 -1
  120. package/dist/commands/documents/delete.js +17 -6
  121. package/dist/commands/documents/delete.js.map +1 -1
  122. package/dist/commands/documents/get.js +15 -6
  123. package/dist/commands/documents/get.js.map +1 -1
  124. package/dist/commands/documents/query.js +24 -12
  125. package/dist/commands/documents/query.js.map +1 -1
  126. package/dist/commands/documents/validate.js +29 -9
  127. package/dist/commands/documents/validate.js.map +1 -1
  128. package/dist/commands/graphql/deploy.js +55 -28
  129. package/dist/commands/graphql/deploy.js.map +1 -1
  130. package/dist/commands/graphql/list.js +14 -1
  131. package/dist/commands/graphql/list.js.map +1 -1
  132. package/dist/commands/graphql/undeploy.js +36 -14
  133. package/dist/commands/graphql/undeploy.js.map +1 -1
  134. package/dist/commands/hook/attempt.js +21 -1
  135. package/dist/commands/hook/attempt.js.map +1 -1
  136. package/dist/commands/hook/create.js +22 -2
  137. package/dist/commands/hook/create.js.map +1 -1
  138. package/dist/commands/hook/delete.js +21 -1
  139. package/dist/commands/hook/delete.js.map +1 -1
  140. package/dist/commands/hook/list.js +21 -1
  141. package/dist/commands/hook/list.js.map +1 -1
  142. package/dist/commands/hook/logs.js +19 -1
  143. package/dist/commands/hook/logs.js.map +1 -1
  144. package/dist/commands/init.js +13 -6
  145. package/dist/commands/init.js.map +1 -1
  146. package/dist/commands/login.js +13 -6
  147. package/dist/commands/login.js.map +1 -1
  148. package/dist/commands/logout.js +8 -6
  149. package/dist/commands/logout.js.map +1 -1
  150. package/dist/commands/media/create-aspect.js +3 -3
  151. package/dist/commands/media/create-aspect.js.map +1 -1
  152. package/dist/commands/media/delete-aspect.js +8 -1
  153. package/dist/commands/media/delete-aspect.js.map +1 -1
  154. package/dist/commands/media/deploy-aspect.js +20 -3
  155. package/dist/commands/media/deploy-aspect.js.map +1 -1
  156. package/dist/commands/media/export.js +8 -1
  157. package/dist/commands/media/export.js.map +1 -1
  158. package/dist/commands/media/import.js +9 -2
  159. package/dist/commands/media/import.js.map +1 -1
  160. package/dist/commands/schema/delete.js +19 -6
  161. package/dist/commands/schema/delete.js.map +1 -1
  162. package/dist/commands/schema/deploy.js +8 -2
  163. package/dist/commands/schema/deploy.js.map +1 -1
  164. package/dist/commands/tokens/add.js +23 -1
  165. package/dist/commands/tokens/add.js.map +1 -1
  166. package/dist/commands/tokens/delete.js +19 -1
  167. package/dist/commands/tokens/delete.js.map +1 -1
  168. package/dist/commands/tokens/list.js +19 -1
  169. package/dist/commands/tokens/list.js.map +1 -1
  170. package/dist/commands/users/invite.js +23 -1
  171. package/dist/commands/users/invite.js.map +1 -1
  172. package/dist/commands/users/list.js +23 -1
  173. package/dist/commands/users/list.js.map +1 -1
  174. package/dist/hooks/prerun/flushTelemetry.worker.js +1 -1
  175. package/dist/hooks/prerun/flushTelemetry.worker.js.map +1 -1
  176. package/dist/hooks/prerun/injectEnvVariables.js +9 -1
  177. package/dist/hooks/prerun/injectEnvVariables.js.map +1 -1
  178. package/dist/hooks/prerun/setupTelemetry.js +2 -1
  179. package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
  180. package/dist/prompts/promptForProject.js.map +1 -1
  181. package/dist/{actions/auth/login/promptProviders.js → prompts/promptForProviders.js} +3 -3
  182. package/dist/prompts/promptForProviders.js.map +1 -0
  183. package/dist/services/auth.js +36 -3
  184. package/dist/services/auth.js.map +1 -1
  185. package/dist/services/docs.js +2 -2
  186. package/dist/services/docs.js.map +1 -1
  187. package/dist/services/getUrlHeaders.js +0 -2
  188. package/dist/services/getUrlHeaders.js.map +1 -1
  189. package/dist/services/projects.js +4 -2
  190. package/dist/services/projects.js.map +1 -1
  191. package/dist/services/telemetry.js +2 -1
  192. package/dist/services/telemetry.js.map +1 -1
  193. package/dist/util/createExpiringConfig.js +64 -0
  194. package/dist/util/createExpiringConfig.js.map +1 -0
  195. package/dist/util/detectFramework.js +135 -0
  196. package/dist/util/detectFramework.js.map +1 -0
  197. package/dist/util/extractDocumentsFromNdjsonOrTarball.js +1 -2
  198. package/dist/util/extractDocumentsFromNdjsonOrTarball.js.map +1 -1
  199. package/dist/util/isSchemaError.js +11 -0
  200. package/dist/util/isSchemaError.js.map +1 -0
  201. package/dist/util/isTar.js +8 -0
  202. package/dist/util/isTar.js.map +1 -0
  203. package/dist/util/sharedFlags.js +44 -14
  204. package/dist/util/sharedFlags.js.map +1 -1
  205. package/dist/util/telemetry/cleanupOldTelemetryFiles.js +30 -0
  206. package/dist/util/telemetry/cleanupOldTelemetryFiles.js.map +1 -0
  207. package/dist/util/telemetry/createTelemetryStore.js +95 -0
  208. package/dist/util/telemetry/createTelemetryStore.js.map +1 -0
  209. package/dist/util/telemetry/createTraceId.js +10 -0
  210. package/dist/util/telemetry/createTraceId.js.map +1 -0
  211. package/dist/util/telemetry/findTelemetryFiles.js +35 -0
  212. package/dist/util/telemetry/findTelemetryFiles.js.map +1 -0
  213. package/dist/util/telemetry/flushTelemetryFiles.js +118 -0
  214. package/dist/util/telemetry/flushTelemetryFiles.js.map +1 -0
  215. package/dist/util/telemetry/generateTelemetryFilePath.js +30 -0
  216. package/dist/util/telemetry/generateTelemetryFilePath.js.map +1 -0
  217. package/dist/util/telemetry/logger.js +59 -0
  218. package/dist/util/telemetry/logger.js.map +1 -0
  219. package/dist/util/telemetry/readNDJSON.js +28 -0
  220. package/dist/util/telemetry/readNDJSON.js.map +1 -0
  221. package/dist/util/telemetry/telemetryStoreDebug.js +7 -0
  222. package/dist/util/telemetry/telemetryStoreDebug.js.map +1 -0
  223. package/dist/util/telemetry/trace.js +150 -0
  224. package/dist/util/telemetry/trace.js.map +1 -0
  225. package/dist/util/update/updateChecker.js +2 -1
  226. package/dist/util/update/updateChecker.js.map +1 -1
  227. package/oclif.manifest.json +1211 -774
  228. package/package.json +19 -22
  229. package/dist/actions/auth/login/promptProviders.js.map +0 -1
@@ -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 {studioDependencies} from '../../studioDependencies.js'\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 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 // 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 ? {} : studioDependencies.dependencies),\n ...(isAppTemplate ? {} : 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 ? {} : 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 ? {} : 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 })\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 organizationId: variables.organizationId,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n projectId: variables.projectId,\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 isAppTemplate\n ? Promise.resolve(null)\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 await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\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","studioDependencies","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","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","dependencyVersions","dependencies","devDependencies","dependency","Object","keys","packageJsonName","basename","toLowerCase","replaceAll","packageManifest","name","scripts","studioConfig","configTemplate","cliConfig","entry","organizationId","autoUpdates","dataset","projectId","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","writeFile","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 {studioDependencies} from '../../studioDependencies.js'\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 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 // 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 ? {} : studioDependencies.dependencies),\n ...(isAppTemplate ? {} : 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 ? {} : 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 ? {} : 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 organizationId: variables.organizationId,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n projectId: variables.projectId,\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 isAppTemplate\n ? Promise.resolve(null)\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 await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\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","studioDependencies","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","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","dependencyVersions","dependencies","devDependencies","dependency","Object","keys","packageJsonName","basename","toLowerCase","replaceAll","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","organizationId","autoUpdates","dataset","projectId","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","writeFile","flag","err","code","warn","originalPath","replace"],"mappings":"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"}
@@ -4,9 +4,9 @@ import { subdebug } from '@sanity/cli-core';
4
4
  import { logSymbols, spinner } from '@sanity/cli-core/ux';
5
5
  import { getMonoRepo, GitHubFileReader, validateTemplate } from '@sanity/template-validator';
6
6
  import { frameworks } from '@vercel/frameworks';
7
- import { detectFrameworkRecord, LocalFileSystemDetector } from '@vercel/fs-detectors';
8
7
  import { createCorsOrigin } from '../../services/cors.js';
9
8
  import { createToken } from '../../services/tokens.js';
9
+ import { detectFrameworkRecord } from '../../util/detectFramework.js';
10
10
  import { getDefaultPortForFramework } from '../../util/frameworkPort.js';
11
11
  import { tryGitInit } from './git.js';
12
12
  import { applyEnvVariables, checkIfNeedsApiToken, downloadAndExtractRepo, getGitHubRawContentUrl, tryApplyPackageName } from './remoteTemplate.js';
@@ -71,10 +71,10 @@ export async function bootstrapRemoteTemplate(opts) {
71
71
  const packagePath = join(outputPath, pkg);
72
72
  const packageFramework = await detectFrameworkRecord({
73
73
  frameworkList: frameworks,
74
- fs: new LocalFileSystemDetector(packagePath)
74
+ rootPath: packagePath
75
75
  });
76
76
  const port = getDefaultPortForFramework(packageFramework?.slug);
77
- if (corsAdded.includes(port)) {
77
+ if (!corsAdded.includes(port)) {
78
78
  debug('Setting CORS origin to http://localhost:%d', port);
79
79
  await createCorsOrigin({
80
80
  allowCredentials: true,
@@ -99,8 +99,9 @@ export async function bootstrapRemoteTemplate(opts) {
99
99
  debug('Updating initial template metadata');
100
100
  await updateInitialTemplateMetadata(variables.projectId, `external-${name}`);
101
101
  spin.succeed();
102
- if (corsAdded.length > 0) {
103
- output.log(`${logSymbols.success} CORS origins added (${corsAdded.map((p)=>`localhost:${p}`).join(', ')})`);
102
+ const newlyAddedPorts = corsAdded.slice(1);
103
+ if (newlyAddedPorts.length > 0) {
104
+ output.log(`${logSymbols.success} CORS origins added (${newlyAddedPorts.map((p)=>`localhost:${p}`).join(', ')})`);
104
105
  }
105
106
  if (readToken) output.log(`${logSymbols.success} API token generated (${READ_TOKEN_LABEL})`);
106
107
  if (writeToken) output.log(`${logSymbols.success} API token generated (${WRITE_TOKEN_LABEL})`);
@@ -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'\nimport {detectFrameworkRecord, LocalFileSystemDetector} from '@vercel/fs-detectors'\n\nimport {createCorsOrigin} from '../../services/cors.js'\nimport {createToken} from '../../services/tokens.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 fs: new LocalFileSystemDetector(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 if (corsAdded.length > 0) {\n output.log(\n `${logSymbols.success} CORS origins added (${corsAdded.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","detectFrameworkRecord","LocalFileSystemDetector","createCorsOrigin","createToken","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","fs","port","slug","includes","allowCredentials","origin","push","envName","succeed","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 ).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":"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,GAAG,GACLC;IACJ,MAAMC,aAAaP,kBACf,AACE,CAAA,MAAMnD,YAAY;QAChBqD,OAAOxC;QACPyC,WAAW9B,UAAU8B,SAAS;QAC9BC,UAAUvC;IACZ,EAAC,EACDwC,GAAG,GACLC;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"}
@@ -2,6 +2,7 @@ const manifestPropOrder = [
2
2
  'name',
3
3
  'private',
4
4
  'version',
5
+ 'type',
5
6
  'description',
6
7
  'main',
7
8
  'author',
@@ -28,12 +29,16 @@ export function createPackageManifest(data) {
28
29
  singleQuote: true
29
30
  }
30
31
  };
32
+ const type = data.type ? {
33
+ type: data.type
34
+ } : {};
31
35
  const pkg = {
32
36
  ...getCommonManifest(data),
33
37
  keywords: [
34
38
  'sanity'
35
39
  ],
36
40
  main: 'package.json',
41
+ ...type,
37
42
  scripts: data.scripts || {
38
43
  build: 'sanity build',
39
44
  deploy: 'sanity deploy',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/createPackageManifest.ts"],"sourcesContent":["import {type PackageJson, type SanityJson} from '../../types.js'\n\nconst manifestPropOrder = [\n 'name',\n 'private',\n 'version',\n 'description',\n 'main',\n 'author',\n 'license',\n 'scripts',\n 'keywords',\n 'dependencies',\n 'devDependencies',\n]\n\n// PackageJson has an index signature ([x: string]: unknown) from z.looseObject,\n// which causes Omit to collapse the type. Strip the index signature first, then Omit.\ntype RemoveIndex<T> = {\n [K in keyof T as string extends K ? never : K]: T[K]\n}\ntype PackageJsonWithoutVersion = Omit<RemoveIndex<PackageJson>, 'version'>\n\ninterface CreatePackageManifestOptions extends PackageJsonWithoutVersion {\n gitRemote?: string\n\n isAppTemplate?: boolean\n}\n\nexport function createPackageManifest(data: CreatePackageManifestOptions): string {\n const {isAppTemplate} = data\n\n const dependencies = data.dependencies ? {dependencies: sortKeys(data.dependencies)} : {}\n\n const devDependencies = data.devDependencies\n ? {devDependencies: sortKeys(data.devDependencies)}\n : {}\n\n // Don't write a prettier config for SDK apps; we want to allow developers to use their own\n const prettierConfig = isAppTemplate\n ? ({} as Record<string, never>)\n : {\n prettier: {\n bracketSpacing: false,\n printWidth: 100,\n semi: false,\n singleQuote: true,\n },\n }\n\n const pkg: PackageJson = {\n ...getCommonManifest(data),\n\n keywords: ['sanity'],\n main: 'package.json',\n scripts: data.scripts || {\n build: 'sanity build',\n deploy: 'sanity deploy',\n 'deploy-graphql': 'sanity graphql deploy',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n\n ...dependencies,\n ...devDependencies,\n ...prettierConfig,\n }\n\n return serializeManifest(pkg)\n}\n\nfunction getCommonManifest(data: PackageJsonWithoutVersion & {gitRemote?: string}) {\n const pkg: PackageJson = {\n name: data.name as string,\n version: '1.0.0',\n ...(data.author ? {author: data.author as string} : {}),\n ...(data.description ? {description: data.description as string} : {}),\n license: (data.license as string | undefined) || 'UNLICENSED',\n }\n\n if (pkg.license === 'UNLICENSED') {\n pkg.private = true\n }\n\n if (data.gitRemote) {\n pkg.repository = {\n type: 'git',\n url: data.gitRemote,\n }\n }\n\n return pkg\n}\n\nfunction sortKeys(obj: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(obj).toSorted(([a], [b]) => a.localeCompare(b)))\n}\n\nfunction serializeManifest(src: PackageJson | SanityJson): string {\n const props = [...manifestPropOrder, ...Object.keys(src)]\n const ordered: Record<string, unknown> = {}\n for (const prop of props) {\n const source = src as Record<string, unknown>\n if (source[prop] !== undefined && ordered[prop] === undefined) {\n ordered[prop] = source[prop]\n }\n }\n\n return `${JSON.stringify(ordered, null, 2)}\\n`\n}\n"],"names":["manifestPropOrder","createPackageManifest","data","isAppTemplate","dependencies","sortKeys","devDependencies","prettierConfig","prettier","bracketSpacing","printWidth","semi","singleQuote","pkg","getCommonManifest","keywords","main","scripts","build","deploy","dev","start","serializeManifest","name","version","author","description","license","private","gitRemote","repository","type","url","obj","Object","fromEntries","entries","toSorted","a","b","localeCompare","src","props","keys","ordered","prop","source","undefined","JSON","stringify"],"mappings":"AAEA,MAAMA,oBAAoB;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAeD,OAAO,SAASC,sBAAsBC,IAAkC;IACtE,MAAM,EAACC,aAAa,EAAC,GAAGD;IAExB,MAAME,eAAeF,KAAKE,YAAY,GAAG;QAACA,cAAcC,SAASH,KAAKE,YAAY;IAAC,IAAI,CAAC;IAExF,MAAME,kBAAkBJ,KAAKI,eAAe,GACxC;QAACA,iBAAiBD,SAASH,KAAKI,eAAe;IAAC,IAChD,CAAC;IAEL,2FAA2F;IAC3F,MAAMC,iBAAiBJ,gBAClB,CAAC,IACF;QACEK,UAAU;YACRC,gBAAgB;YAChBC,YAAY;YACZC,MAAM;YACNC,aAAa;QACf;IACF;IAEJ,MAAMC,MAAmB;QACvB,GAAGC,kBAAkBZ,KAAK;QAE1Ba,UAAU;YAAC;SAAS;QACpBC,MAAM;QACNC,SAASf,KAAKe,OAAO,IAAI;YACvBC,OAAO;YACPC,QAAQ;YACR,kBAAkB;YAClBC,KAAK;YACLC,OAAO;QACT;QAEA,GAAGjB,YAAY;QACf,GAAGE,eAAe;QAClB,GAAGC,cAAc;IACnB;IAEA,OAAOe,kBAAkBT;AAC3B;AAEA,SAASC,kBAAkBZ,IAAsD;IAC/E,MAAMW,MAAmB;QACvBU,MAAMrB,KAAKqB,IAAI;QACfC,SAAS;QACT,GAAItB,KAAKuB,MAAM,GAAG;YAACA,QAAQvB,KAAKuB,MAAM;QAAU,IAAI,CAAC,CAAC;QACtD,GAAIvB,KAAKwB,WAAW,GAAG;YAACA,aAAaxB,KAAKwB,WAAW;QAAU,IAAI,CAAC,CAAC;QACrEC,SAAS,AAACzB,KAAKyB,OAAO,IAA2B;IACnD;IAEA,IAAId,IAAIc,OAAO,KAAK,cAAc;QAChCd,IAAIe,OAAO,GAAG;IAChB;IAEA,IAAI1B,KAAK2B,SAAS,EAAE;QAClBhB,IAAIiB,UAAU,GAAG;YACfC,MAAM;YACNC,KAAK9B,KAAK2B,SAAS;QACrB;IACF;IAEA,OAAOhB;AACT;AAEA,SAASR,SAAS4B,GAA2B;IAC3C,OAAOC,OAAOC,WAAW,CAACD,OAAOE,OAAO,CAACH,KAAKI,QAAQ,CAAC,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKD,EAAEE,aAAa,CAACD;AACvF;AAEA,SAASjB,kBAAkBmB,GAA6B;IACtD,MAAMC,QAAQ;WAAI1C;WAAsBkC,OAAOS,IAAI,CAACF;KAAK;IACzD,MAAMG,UAAmC,CAAC;IAC1C,KAAK,MAAMC,QAAQH,MAAO;QACxB,MAAMI,SAASL;QACf,IAAIK,MAAM,CAACD,KAAK,KAAKE,aAAaH,OAAO,CAACC,KAAK,KAAKE,WAAW;YAC7DH,OAAO,CAACC,KAAK,GAAGC,MAAM,CAACD,KAAK;QAC9B;IACF;IAEA,OAAO,GAAGG,KAAKC,SAAS,CAACL,SAAS,MAAM,GAAG,EAAE,CAAC;AAChD"}
1
+ {"version":3,"sources":["../../../src/actions/init/createPackageManifest.ts"],"sourcesContent":["import {type PackageJson, type SanityJson} from '../../types.js'\n\nconst manifestPropOrder = [\n 'name',\n 'private',\n 'version',\n 'type',\n 'description',\n 'main',\n 'author',\n 'license',\n 'scripts',\n 'keywords',\n 'dependencies',\n 'devDependencies',\n]\n\n// PackageJson has an index signature ([x: string]: unknown) from z.looseObject,\n// which causes Omit to collapse the type. Strip the index signature first, then Omit.\ntype RemoveIndex<T> = {\n [K in keyof T as string extends K ? never : K]: T[K]\n}\ntype PackageJsonWithoutVersion = Omit<RemoveIndex<PackageJson>, 'version'>\n\ninterface CreatePackageManifestOptions extends PackageJsonWithoutVersion {\n gitRemote?: string\n\n isAppTemplate?: boolean\n}\n\nexport function createPackageManifest(data: CreatePackageManifestOptions): string {\n const {isAppTemplate} = data\n\n const dependencies = data.dependencies ? {dependencies: sortKeys(data.dependencies)} : {}\n\n const devDependencies = data.devDependencies\n ? {devDependencies: sortKeys(data.devDependencies)}\n : {}\n\n // Don't write a prettier config for SDK apps; we want to allow developers to use their own\n const prettierConfig = isAppTemplate\n ? ({} as Record<string, never>)\n : {\n prettier: {\n bracketSpacing: false,\n printWidth: 100,\n semi: false,\n singleQuote: true,\n },\n }\n\n const type = data.type\n ? {\n type: data.type,\n }\n : {}\n\n const pkg: PackageJson = {\n ...getCommonManifest(data),\n\n keywords: ['sanity'],\n main: 'package.json',\n ...type,\n scripts: data.scripts || {\n build: 'sanity build',\n deploy: 'sanity deploy',\n 'deploy-graphql': 'sanity graphql deploy',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n\n ...dependencies,\n ...devDependencies,\n ...prettierConfig,\n }\n\n return serializeManifest(pkg)\n}\n\nfunction getCommonManifest(data: PackageJsonWithoutVersion & {gitRemote?: string}) {\n const pkg: PackageJson = {\n name: data.name as string,\n version: '1.0.0',\n ...(data.author ? {author: data.author as string} : {}),\n ...(data.description ? {description: data.description as string} : {}),\n license: (data.license as string | undefined) || 'UNLICENSED',\n }\n\n if (pkg.license === 'UNLICENSED') {\n pkg.private = true\n }\n\n if (data.gitRemote) {\n pkg.repository = {\n type: 'git',\n url: data.gitRemote,\n }\n }\n\n return pkg\n}\n\nfunction sortKeys(obj: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(obj).toSorted(([a], [b]) => a.localeCompare(b)))\n}\n\nfunction serializeManifest(src: PackageJson | SanityJson): string {\n const props = [...manifestPropOrder, ...Object.keys(src)]\n const ordered: Record<string, unknown> = {}\n for (const prop of props) {\n const source = src as Record<string, unknown>\n if (source[prop] !== undefined && ordered[prop] === undefined) {\n ordered[prop] = source[prop]\n }\n }\n\n return `${JSON.stringify(ordered, null, 2)}\\n`\n}\n"],"names":["manifestPropOrder","createPackageManifest","data","isAppTemplate","dependencies","sortKeys","devDependencies","prettierConfig","prettier","bracketSpacing","printWidth","semi","singleQuote","type","pkg","getCommonManifest","keywords","main","scripts","build","deploy","dev","start","serializeManifest","name","version","author","description","license","private","gitRemote","repository","url","obj","Object","fromEntries","entries","toSorted","a","b","localeCompare","src","props","keys","ordered","prop","source","undefined","JSON","stringify"],"mappings":"AAEA,MAAMA,oBAAoB;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAeD,OAAO,SAASC,sBAAsBC,IAAkC;IACtE,MAAM,EAACC,aAAa,EAAC,GAAGD;IAExB,MAAME,eAAeF,KAAKE,YAAY,GAAG;QAACA,cAAcC,SAASH,KAAKE,YAAY;IAAC,IAAI,CAAC;IAExF,MAAME,kBAAkBJ,KAAKI,eAAe,GACxC;QAACA,iBAAiBD,SAASH,KAAKI,eAAe;IAAC,IAChD,CAAC;IAEL,2FAA2F;IAC3F,MAAMC,iBAAiBJ,gBAClB,CAAC,IACF;QACEK,UAAU;YACRC,gBAAgB;YAChBC,YAAY;YACZC,MAAM;YACNC,aAAa;QACf;IACF;IAEJ,MAAMC,OAAOX,KAAKW,IAAI,GAClB;QACEA,MAAMX,KAAKW,IAAI;IACjB,IACA,CAAC;IAEL,MAAMC,MAAmB;QACvB,GAAGC,kBAAkBb,KAAK;QAE1Bc,UAAU;YAAC;SAAS;QACpBC,MAAM;QACN,GAAGJ,IAAI;QACPK,SAAShB,KAAKgB,OAAO,IAAI;YACvBC,OAAO;YACPC,QAAQ;YACR,kBAAkB;YAClBC,KAAK;YACLC,OAAO;QACT;QAEA,GAAGlB,YAAY;QACf,GAAGE,eAAe;QAClB,GAAGC,cAAc;IACnB;IAEA,OAAOgB,kBAAkBT;AAC3B;AAEA,SAASC,kBAAkBb,IAAsD;IAC/E,MAAMY,MAAmB;QACvBU,MAAMtB,KAAKsB,IAAI;QACfC,SAAS;QACT,GAAIvB,KAAKwB,MAAM,GAAG;YAACA,QAAQxB,KAAKwB,MAAM;QAAU,IAAI,CAAC,CAAC;QACtD,GAAIxB,KAAKyB,WAAW,GAAG;YAACA,aAAazB,KAAKyB,WAAW;QAAU,IAAI,CAAC,CAAC;QACrEC,SAAS,AAAC1B,KAAK0B,OAAO,IAA2B;IACnD;IAEA,IAAId,IAAIc,OAAO,KAAK,cAAc;QAChCd,IAAIe,OAAO,GAAG;IAChB;IAEA,IAAI3B,KAAK4B,SAAS,EAAE;QAClBhB,IAAIiB,UAAU,GAAG;YACflB,MAAM;YACNmB,KAAK9B,KAAK4B,SAAS;QACrB;IACF;IAEA,OAAOhB;AACT;AAEA,SAAST,SAAS4B,GAA2B;IAC3C,OAAOC,OAAOC,WAAW,CAACD,OAAOE,OAAO,CAACH,KAAKI,QAAQ,CAAC,CAAC,CAACC,EAAE,EAAE,CAACC,EAAE,GAAKD,EAAEE,aAAa,CAACD;AACvF;AAEA,SAAShB,kBAAkBkB,GAA6B;IACtD,MAAMC,QAAQ;WAAI1C;WAAsBkC,OAAOS,IAAI,CAACF;KAAK;IACzD,MAAMG,UAAmC,CAAC;IAC1C,KAAK,MAAMC,QAAQH,MAAO;QACxB,MAAMI,SAASL;QACf,IAAIK,MAAM,CAACD,KAAK,KAAKE,aAAaH,OAAO,CAACC,KAAK,KAAKE,WAAW;YAC7DH,OAAO,CAACC,KAAK,GAAGC,MAAM,CAACD,KAAK;QAC9B;IACF;IAEA,OAAO,GAAGG,KAAKC,SAAS,CAACL,SAAS,MAAM,GAAG,EAAE,CAAC;AAChD"}
@@ -21,7 +21,8 @@ const appTemplate = {
21
21
  build: 'sanity build',
22
22
  dev: 'sanity dev',
23
23
  start: 'sanity start'
24
- }
24
+ },
25
+ type: 'module'
25
26
  };
26
27
  export default appTemplate;
27
28
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/init/templates/appQuickstart.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\n\nconst appTemplate: ProjectTemplate = {\n dependencies: {\n '@sanity/sdk': '^0.0.0-rc',\n '@sanity/sdk-react': '^0.0.0-rc',\n react: '^19',\n 'react-dom': '^19',\n },\n devDependencies: {\n /*\n * this will be changed to eslint-config sanity,\n * eslint.config generation will be a fast follow\n */\n '@sanity/eslint-config-studio': '^5.0.1',\n '@types/react': '^18.0.25',\n eslint: '^9.9.0',\n prettier: '^3.0.2',\n sanity: '^3',\n typescript: '^5.1.6',\n },\n entry: './src/App.tsx',\n scripts: {\n build: 'sanity build',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n}\n\nexport default appTemplate\n"],"names":["appTemplate","dependencies","react","devDependencies","eslint","prettier","sanity","typescript","entry","scripts","build","dev","start"],"mappings":"AAEA,MAAMA,cAA+B;IACnCC,cAAc;QACZ,eAAe;QACf,qBAAqB;QACrBC,OAAO;QACP,aAAa;IACf;IACAC,iBAAiB;QACf;;;KAGC,GACD,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;IACAC,OAAO;IACPC,SAAS;QACPC,OAAO;QACPC,KAAK;QACLC,OAAO;IACT;AACF;AAEA,eAAeZ,YAAW"}
1
+ {"version":3,"sources":["../../../../src/actions/init/templates/appQuickstart.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\n\nconst appTemplate: ProjectTemplate = {\n dependencies: {\n '@sanity/sdk': '^0.0.0-rc',\n '@sanity/sdk-react': '^0.0.0-rc',\n react: '^19',\n 'react-dom': '^19',\n },\n devDependencies: {\n /*\n * this will be changed to eslint-config sanity,\n * eslint.config generation will be a fast follow\n */\n '@sanity/eslint-config-studio': '^5.0.1',\n '@types/react': '^18.0.25',\n eslint: '^9.9.0',\n prettier: '^3.0.2',\n sanity: '^3',\n typescript: '^5.1.6',\n },\n entry: './src/App.tsx',\n scripts: {\n build: 'sanity build',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n type: 'module',\n}\n\nexport default appTemplate\n"],"names":["appTemplate","dependencies","react","devDependencies","eslint","prettier","sanity","typescript","entry","scripts","build","dev","start","type"],"mappings":"AAEA,MAAMA,cAA+B;IACnCC,cAAc;QACZ,eAAe;QACf,qBAAqB;QACrBC,OAAO;QACP,aAAa;IACf;IACAC,iBAAiB;QACf;;;KAGC,GACD,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;IACAC,OAAO;IACPC,SAAS;QACPC,OAAO;QACPC,KAAK;QACLC,OAAO;IACT;IACAC,MAAM;AACR;AAEA,eAAeb,YAAW"}
@@ -23,7 +23,8 @@ const appSanityUiTemplate = {
23
23
  build: 'sanity build',
24
24
  dev: 'sanity dev',
25
25
  start: 'sanity start'
26
- }
26
+ },
27
+ type: 'module'
27
28
  };
28
29
  export default appSanityUiTemplate;
29
30
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/init/templates/appSanityUi.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\n\nconst appSanityUiTemplate: ProjectTemplate = {\n dependencies: {\n '@sanity/sdk': '^0.0.0-rc',\n '@sanity/sdk-react': '^0.0.0-rc',\n '@sanity/ui': '^2',\n react: '^19',\n 'react-dom': '^19',\n 'styled-components': '^6.1.17',\n },\n devDependencies: {\n /*\n * this will be changed to eslint-config sanity,\n * eslint.config generation will be a fast follow\n */\n '@sanity/eslint-config-studio': '^5.0.1',\n '@types/react': '^18.0.25',\n eslint: '^9.9.0',\n prettier: '^3.0.2',\n sanity: '^3',\n typescript: '^5.1.6',\n },\n entry: './src/App.tsx',\n scripts: {\n build: 'sanity build',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n}\n\nexport default appSanityUiTemplate\n"],"names":["appSanityUiTemplate","dependencies","react","devDependencies","eslint","prettier","sanity","typescript","entry","scripts","build","dev","start"],"mappings":"AAEA,MAAMA,sBAAuC;IAC3CC,cAAc;QACZ,eAAe;QACf,qBAAqB;QACrB,cAAc;QACdC,OAAO;QACP,aAAa;QACb,qBAAqB;IACvB;IACAC,iBAAiB;QACf;;;KAGC,GACD,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;IACAC,OAAO;IACPC,SAAS;QACPC,OAAO;QACPC,KAAK;QACLC,OAAO;IACT;AACF;AAEA,eAAeZ,oBAAmB"}
1
+ {"version":3,"sources":["../../../../src/actions/init/templates/appSanityUi.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\n\nconst appSanityUiTemplate: ProjectTemplate = {\n dependencies: {\n '@sanity/sdk': '^0.0.0-rc',\n '@sanity/sdk-react': '^0.0.0-rc',\n '@sanity/ui': '^2',\n react: '^19',\n 'react-dom': '^19',\n 'styled-components': '^6.1.17',\n },\n devDependencies: {\n /*\n * this will be changed to eslint-config sanity,\n * eslint.config generation will be a fast follow\n */\n '@sanity/eslint-config-studio': '^5.0.1',\n '@types/react': '^18.0.25',\n eslint: '^9.9.0',\n prettier: '^3.0.2',\n sanity: '^3',\n typescript: '^5.1.6',\n },\n entry: './src/App.tsx',\n scripts: {\n build: 'sanity build',\n dev: 'sanity dev',\n start: 'sanity start',\n },\n type: 'module',\n}\n\nexport default appSanityUiTemplate\n"],"names":["appSanityUiTemplate","dependencies","react","devDependencies","eslint","prettier","sanity","typescript","entry","scripts","build","dev","start","type"],"mappings":"AAEA,MAAMA,sBAAuC;IAC3CC,cAAc;QACZ,eAAe;QACf,qBAAqB;QACrB,cAAc;QACdC,OAAO;QACP,aAAa;QACb,qBAAqB;IACvB;IACAC,iBAAiB;QACf;;;KAGC,GACD,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;IACAC,OAAO;IACPC,SAAS;QACPC,OAAO;QACPC,KAAK;QACLC,OAAO;IACT;IACAC,MAAM;AACR;AAEA,eAAeb,oBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/types.ts"],"sourcesContent":["import {Framework} from '@vercel/frameworks'\n\nimport {GenerateConfigOptions} from './createStudioConfig'\n\nexport type VersionedFramework = Framework & {\n detectedVersion?: string\n}\n\nexport interface ProjectTemplate {\n configTemplate?: ((variables: GenerateConfigOptions['variables']) => string) | string\n datasetUrl?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n entry?: string\n importPrompt?: string\n scripts?: Record<string, string>\n typescriptOnly?: boolean\n}\n"],"names":[],"mappings":"AAQA,WASC"}
1
+ {"version":3,"sources":["../../../src/actions/init/types.ts"],"sourcesContent":["import {Framework} from '@vercel/frameworks'\n\nimport {GenerateConfigOptions} from './createStudioConfig'\n\nexport type VersionedFramework = Framework & {\n detectedVersion?: string\n}\n\nexport interface ProjectTemplate {\n configTemplate?: ((variables: GenerateConfigOptions['variables']) => string) | string\n datasetUrl?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n entry?: string\n importPrompt?: string\n scripts?: Record<string, string>\n type?: 'commonjs' | 'module'\n typescriptOnly?: boolean\n}\n"],"names":[],"mappings":"AAQA,WAUC"}
@@ -8,13 +8,12 @@ import { pipeline } from 'node:stream/promises';
8
8
  import { styleText } from 'node:util';
9
9
  import gunzipMaybe from 'gunzip-maybe';
10
10
  // @ts-expect-error `peek-stream` module currently untyped
11
- import isTar from 'is-tar';
12
- // @ts-expect-error `peek-stream` module currently untyped
13
11
  import peek from 'peek-stream';
14
12
  import { catchError, EMPTY, filter, from, map, mergeMap, mergeWith, of, switchMap, tap, zip } from 'rxjs';
15
13
  import tar from 'tar-fs';
16
14
  import { glob } from 'tinyglobby';
17
15
  import { findNdjsonEntry } from '../../util/findNdjsonEntry.js';
16
+ import { isTar } from '../../util/isTar.js';
18
17
  import { importMediaDebug } from './importMediaDebug.js';
19
18
  const DEFAULT_CONCURRENCY = 6;
20
19
  export function importer(options) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/media/importMedia.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\nimport {createReadStream, type ReadStream} from 'node:fs'\nimport fs, {mkdtemp} from 'node:fs/promises'\nimport {tmpdir} from 'node:os'\nimport path from 'node:path'\nimport {text} from 'node:stream/consumers'\nimport {pipeline} from 'node:stream/promises'\nimport {styleText} from 'node:util'\n\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type SanityClient} from '@sanity/client'\nimport {type FileAsset, type ImageAsset, type SanityDocument} from '@sanity/types'\nimport gunzipMaybe from 'gunzip-maybe'\n// @ts-expect-error `peek-stream` module currently untyped\nimport isTar from 'is-tar'\n// @ts-expect-error `peek-stream` module currently untyped\nimport peek from 'peek-stream'\nimport {\n catchError,\n EMPTY,\n filter,\n from,\n map,\n mergeMap,\n mergeWith,\n type Observable,\n of,\n type OperatorFunction,\n switchMap,\n tap,\n zip,\n} from 'rxjs'\nimport tar from 'tar-fs'\nimport {glob} from 'tinyglobby'\n\nimport {findNdjsonEntry} from '../../util/findNdjsonEntry.js'\nimport {importMediaDebug} from './importMediaDebug.js'\n\nconst DEFAULT_CONCURRENCY = 6\n\ninterface MediaLibraryUploadResult {\n asset: SanityDocument & {\n _type: 'sanity.asset'\n aspects: unknown\n assetType: FileAsset['_type'] | ImageAsset['_type']\n }\n assetInstance: FileAsset | ImageAsset\n}\n\ninterface MediaLibraryUploadResponse {\n body: MediaLibraryUploadResult\n type: 'response'\n}\n\nexport interface State {\n /**\n * The last asset processed.\n */\n asset: AssetWithAspects\n /**\n * The count of input files.\n */\n fileCount: number\n}\n\ninterface ResolvedAsset {\n /**\n * The ids of the `sanity.asset` documents that currently refer to the asset.\n *\n * These documents contain aspects, and reference an asset instance document.\n */\n assetIds: string[]\n isExistingAsset: boolean\n /**\n * The original filename of the asset as it appears in the import source.\n *\n * Note: Currently includes `images/` or `files/` prefix.\n */\n originalFilename: string\n sha1Hash: string\n}\n\nexport type AssetWithAspects<Asset extends ResolvedAsset = ResolvedAsset> = Asset & {\n aspects: unknown | undefined\n}\n\ninterface Options {\n client: SanityClient\n replaceAspects: boolean\n sourcePath: string\n spinner: ReturnType<typeof spinner>\n}\n\ninterface Context extends Options {\n ndjson: () => ReadStream\n workingPath: string\n}\n\nexport function importer(options: Options): Observable<State> {\n return resolveSource(options).pipe(\n mergeMap(({aspectsNdjsonPath, files, images, workingPath}) => {\n const fileCount = files.length + images.length\n\n if (fileCount === 0) {\n throw new Error('No assets to import')\n }\n\n const context: Context = {\n ...options,\n ndjson: () => createReadStream(aspectsNdjsonPath),\n workingPath,\n }\n\n return from(files).pipe(\n switchMap((file) => zip(of<'file'>('file'), of(file))),\n mergeWith(from(images).pipe(switchMap((file) => zip(of<'image'>('image'), of(file))))),\n fetchExistingAssets(context),\n uploadAsset(context),\n resolveAspectData(context),\n setAspects(context),\n map((asset) => ({\n asset,\n fileCount,\n })),\n )\n }),\n )\n}\n\n/**\n * @internal\n */\nexport function resolveSource({sourcePath}: Pick<Context, 'sourcePath'>): Observable<{\n aspectsNdjsonPath: string\n files: string[]\n images: string[]\n workingPath: string\n}> {\n return from(fs.stat(sourcePath)).pipe(\n switchMap((stats) => {\n return stats.isDirectory()\n ? of(sourcePath)\n : from(mkdtemp(path.join(tmpdir(), 'sanity-media-library-import'))).pipe(\n switchMap((tempPath) => {\n return from(\n pipeline(createReadStream(sourcePath), gunzipMaybe(), untarMaybe(tempPath)),\n ).pipe(map(() => tempPath))\n }),\n )\n }),\n switchMap((importSourcePath) => {\n return from(\n glob(['**/data.ndjson'], {\n absolute: true,\n cwd: importSourcePath,\n deep: 2,\n }),\n ).pipe(\n map(([aspectsNdjsonPath]) => ({\n aspectsNdjsonPath,\n importSourcePath,\n workingPath:\n aspectsNdjsonPath === undefined ? importSourcePath : path.dirname(aspectsNdjsonPath),\n })),\n )\n }),\n tap(({aspectsNdjsonPath, importSourcePath}) => {\n if (aspectsNdjsonPath === undefined) {\n throw new Error(\n `No ${styleText('bold', 'data.ndjson')} file found in import source ${styleText('bold', importSourcePath)}`,\n )\n }\n importMediaDebug(`[Found NDJSON file] ${aspectsNdjsonPath}`)\n }),\n switchMap(({aspectsNdjsonPath, workingPath}) => {\n return from(\n Promise.all([\n glob(['files/*'], {\n cwd: workingPath,\n }),\n glob(['images/*'], {\n cwd: workingPath,\n }),\n ]),\n ).pipe(\n map(([files, images]) => ({\n aspectsNdjsonPath,\n files,\n images,\n workingPath,\n })),\n )\n }),\n )\n}\n\n/**\n * Untar the stream if its contents appear to be tarred.\n *\n * @internal\n */\nfunction untarMaybe(outputPath: string) {\n // @ts-expect-error `peek-stream` module currently untyped\n return peek({maxBuffer: 300, newline: false}, (data, swap) => {\n if (isTar(data)) {\n return swap(null, tar.extract(outputPath))\n }\n\n return swap(null)\n })\n}\n\n/**\n * Fetch the ids of all asset documents that reference the input asset.\n * The input asset is identified by its SHA-1 hash.\n *\n * @internal\n */\nfunction fetchAssetsByHash({\n client,\n type,\n}: {\n client: SanityClient\n type: 'file' | 'image'\n}): OperatorFunction<string, [hash: string, assetIds: string[]]> {\n return switchMap((hash) =>\n client.observable\n .fetch<string[]>(\n `*[\n _type == \"sanity.asset\" &&\n currentVersion._ref == *[\n _type == $type &&\n sha1hash == $hash\n ][0]._id\n ]._id`,\n {\n hash,\n type: ['sanity', `${type}Asset`].join('.'),\n },\n {\n tag: 'asset.getId',\n },\n )\n .pipe(switchMap((assetIds) => zip(of(hash), of(assetIds)))),\n )\n}\n\nfunction fetchExistingAssets({\n client,\n workingPath,\n}: Context): OperatorFunction<\n [type: 'file' | 'image', asset: string],\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset\n> {\n return mergeMap(([type, asset]) => {\n const createSha1Hash = createHash('sha1')\n\n const sha1hash = text(\n createReadStream(path.join(workingPath, asset)).pipe(createSha1Hash).setEncoding('hex'),\n )\n\n return from(sha1hash).pipe(\n tap((hash) =>\n importMediaDebug(`[Asset ${asset}] Checking for ${type} asset with hash ${hash}`),\n ),\n fetchAssetsByHash({client, type}),\n map<\n [string, string[]],\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset\n >(([hash, assetIds]) => {\n if (assetIds.length === 0) {\n return [type, asset, hash]\n }\n\n return {\n assetIds,\n isExistingAsset: true,\n originalFilename: asset,\n sha1Hash: hash,\n }\n }),\n )\n })\n}\n\n/**\n * Find the first matching entry in the provided NDJSON stream and attach it to the asset object.\n *\n * @internal\n */\nfunction resolveAspectData({ndjson}: Context): OperatorFunction<ResolvedAsset, AssetWithAspects> {\n return mergeMap((resolvedAsset) =>\n from(\n findNdjsonEntry<{aspects: unknown}>(\n ndjson(),\n (line) =>\n typeof line === 'object' &&\n line !== null &&\n 'filename' in line &&\n line.filename === resolvedAsset.originalFilename,\n ),\n ).pipe(\n map((aspectsFromImport) => ({\n ...resolvedAsset,\n aspects: aspectsFromImport?.aspects,\n })),\n ),\n )\n}\n\n// TODO: Batch mutations to reduce HTTP request count.\nexport function setAspects({\n client,\n replaceAspects,\n}: Pick<Context, 'client' | 'replaceAspects'>): OperatorFunction<\n AssetWithAspects,\n AssetWithAspects\n> {\n return mergeMap((asset) => {\n const {aspects, assetIds, isExistingAsset} = asset\n\n if (isExistingAsset && !replaceAspects) {\n importMediaDebug(`[Asset ${asset.originalFilename}] Skipping replacement of existing aspects`)\n return of(asset)\n }\n\n if (aspects === undefined) {\n importMediaDebug(`[Asset ${asset.originalFilename}] No aspects to import`)\n return of(asset)\n }\n\n const transaction = client.observable.transaction()\n for (const assetId of assetIds) {\n transaction.patch(assetId, {set: {aspects}})\n }\n\n importMediaDebug(\n `[Asset ${asset.originalFilename}] Setting aspects on asset documents ${JSON.stringify(assetIds)}`,\n )\n\n return transaction\n .commit({\n tag: 'asset.setAspects',\n visibility: 'async',\n })\n .pipe(map(() => asset))\n }, DEFAULT_CONCURRENCY)\n}\n\nfunction uploadAsset({\n client,\n workingPath,\n}: Context): OperatorFunction<\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset,\n ResolvedAsset\n> {\n return mergeMap((maybeResolvedAsset) => {\n if ('assetIds' in maybeResolvedAsset) {\n importMediaDebug(\n `[Asset ${maybeResolvedAsset.originalFilename}] Skipping upload of existing asset with hash ${maybeResolvedAsset.sha1Hash}`,\n )\n return of(maybeResolvedAsset)\n }\n\n const [type, asset, hash] = maybeResolvedAsset\n importMediaDebug(`[Asset ${asset}] Uploading new asset`)\n\n return client.observable.assets\n .upload(type, createReadStream(path.join(workingPath, asset)), {\n tag: 'asset.upload',\n })\n .pipe(\n catchError((error) => {\n // An asset matching the hash was not found during previous steps, but appears to exist upon upload.\n //\n // This may occur if:\n // - The asset was uploaded by another client since the check was performed.\n // - The asset instance document exists, but is not referenced by any asset document.\n if (error.statusCode === 409) {\n importMediaDebug(\n `[Asset ${asset}] Cannot overwrite existing ${type} asset with hash ${hash}`,\n )\n return EMPTY\n }\n return EMPTY\n }),\n filter((response) => response.type === 'response'),\n tap(() => importMediaDebug(`[Asset ${asset}] Finished uploading new asset`)),\n // TODO: The `client.assets.upload` method should return `MediaLibraryUploadResponse` when operating on Media Library resources. When that occurs, this type assertion can be removed.\n map((response) => (response as unknown as MediaLibraryUploadResponse).body),\n map<MediaLibraryUploadResult, ResolvedAsset>((result) => ({\n assetIds: [result.asset._id],\n isExistingAsset: false,\n originalFilename: asset,\n sha1Hash: hash,\n })),\n )\n }, DEFAULT_CONCURRENCY)\n}\n"],"names":["createHash","createReadStream","fs","mkdtemp","tmpdir","path","text","pipeline","styleText","gunzipMaybe","isTar","peek","catchError","EMPTY","filter","from","map","mergeMap","mergeWith","of","switchMap","tap","zip","tar","glob","findNdjsonEntry","importMediaDebug","DEFAULT_CONCURRENCY","importer","options","resolveSource","pipe","aspectsNdjsonPath","files","images","workingPath","fileCount","length","Error","context","ndjson","file","fetchExistingAssets","uploadAsset","resolveAspectData","setAspects","asset","sourcePath","stat","stats","isDirectory","join","tempPath","untarMaybe","importSourcePath","absolute","cwd","deep","undefined","dirname","Promise","all","outputPath","maxBuffer","newline","data","swap","extract","fetchAssetsByHash","client","type","hash","observable","fetch","tag","assetIds","createSha1Hash","sha1hash","setEncoding","isExistingAsset","originalFilename","sha1Hash","resolvedAsset","line","filename","aspectsFromImport","aspects","replaceAspects","transaction","assetId","patch","set","JSON","stringify","commit","visibility","maybeResolvedAsset","assets","upload","error","statusCode","response","body","result","_id"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/media/importMedia.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\nimport {createReadStream, type ReadStream} from 'node:fs'\nimport fs, {mkdtemp} from 'node:fs/promises'\nimport {tmpdir} from 'node:os'\nimport path from 'node:path'\nimport {text} from 'node:stream/consumers'\nimport {pipeline} from 'node:stream/promises'\nimport {styleText} from 'node:util'\n\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type SanityClient} from '@sanity/client'\nimport {type FileAsset, type ImageAsset, type SanityDocument} from '@sanity/types'\nimport gunzipMaybe from 'gunzip-maybe'\n// @ts-expect-error `peek-stream` module currently untyped\nimport peek from 'peek-stream'\nimport {\n catchError,\n EMPTY,\n filter,\n from,\n map,\n mergeMap,\n mergeWith,\n type Observable,\n of,\n type OperatorFunction,\n switchMap,\n tap,\n zip,\n} from 'rxjs'\nimport tar from 'tar-fs'\nimport {glob} from 'tinyglobby'\n\nimport {findNdjsonEntry} from '../../util/findNdjsonEntry.js'\nimport {isTar} from '../../util/isTar.js'\nimport {importMediaDebug} from './importMediaDebug.js'\n\nconst DEFAULT_CONCURRENCY = 6\n\ninterface MediaLibraryUploadResult {\n asset: SanityDocument & {\n _type: 'sanity.asset'\n aspects: unknown\n assetType: FileAsset['_type'] | ImageAsset['_type']\n }\n assetInstance: FileAsset | ImageAsset\n}\n\ninterface MediaLibraryUploadResponse {\n body: MediaLibraryUploadResult\n type: 'response'\n}\n\nexport interface State {\n /**\n * The last asset processed.\n */\n asset: AssetWithAspects\n /**\n * The count of input files.\n */\n fileCount: number\n}\n\ninterface ResolvedAsset {\n /**\n * The ids of the `sanity.asset` documents that currently refer to the asset.\n *\n * These documents contain aspects, and reference an asset instance document.\n */\n assetIds: string[]\n isExistingAsset: boolean\n /**\n * The original filename of the asset as it appears in the import source.\n *\n * Note: Currently includes `images/` or `files/` prefix.\n */\n originalFilename: string\n sha1Hash: string\n}\n\nexport type AssetWithAspects<Asset extends ResolvedAsset = ResolvedAsset> = Asset & {\n aspects: unknown | undefined\n}\n\ninterface Options {\n client: SanityClient\n replaceAspects: boolean\n sourcePath: string\n spinner: ReturnType<typeof spinner>\n}\n\ninterface Context extends Options {\n ndjson: () => ReadStream\n workingPath: string\n}\n\nexport function importer(options: Options): Observable<State> {\n return resolveSource(options).pipe(\n mergeMap(({aspectsNdjsonPath, files, images, workingPath}) => {\n const fileCount = files.length + images.length\n\n if (fileCount === 0) {\n throw new Error('No assets to import')\n }\n\n const context: Context = {\n ...options,\n ndjson: () => createReadStream(aspectsNdjsonPath),\n workingPath,\n }\n\n return from(files).pipe(\n switchMap((file) => zip(of<'file'>('file'), of(file))),\n mergeWith(from(images).pipe(switchMap((file) => zip(of<'image'>('image'), of(file))))),\n fetchExistingAssets(context),\n uploadAsset(context),\n resolveAspectData(context),\n setAspects(context),\n map((asset) => ({\n asset,\n fileCount,\n })),\n )\n }),\n )\n}\n\n/**\n * @internal\n */\nexport function resolveSource({sourcePath}: Pick<Context, 'sourcePath'>): Observable<{\n aspectsNdjsonPath: string\n files: string[]\n images: string[]\n workingPath: string\n}> {\n return from(fs.stat(sourcePath)).pipe(\n switchMap((stats) => {\n return stats.isDirectory()\n ? of(sourcePath)\n : from(mkdtemp(path.join(tmpdir(), 'sanity-media-library-import'))).pipe(\n switchMap((tempPath) => {\n return from(\n pipeline(createReadStream(sourcePath), gunzipMaybe(), untarMaybe(tempPath)),\n ).pipe(map(() => tempPath))\n }),\n )\n }),\n switchMap((importSourcePath) => {\n return from(\n glob(['**/data.ndjson'], {\n absolute: true,\n cwd: importSourcePath,\n deep: 2,\n }),\n ).pipe(\n map(([aspectsNdjsonPath]) => ({\n aspectsNdjsonPath,\n importSourcePath,\n workingPath:\n aspectsNdjsonPath === undefined ? importSourcePath : path.dirname(aspectsNdjsonPath),\n })),\n )\n }),\n tap(({aspectsNdjsonPath, importSourcePath}) => {\n if (aspectsNdjsonPath === undefined) {\n throw new Error(\n `No ${styleText('bold', 'data.ndjson')} file found in import source ${styleText('bold', importSourcePath)}`,\n )\n }\n importMediaDebug(`[Found NDJSON file] ${aspectsNdjsonPath}`)\n }),\n switchMap(({aspectsNdjsonPath, workingPath}) => {\n return from(\n Promise.all([\n glob(['files/*'], {\n cwd: workingPath,\n }),\n glob(['images/*'], {\n cwd: workingPath,\n }),\n ]),\n ).pipe(\n map(([files, images]) => ({\n aspectsNdjsonPath,\n files,\n images,\n workingPath,\n })),\n )\n }),\n )\n}\n\n/**\n * Untar the stream if its contents appear to be tarred.\n *\n * @internal\n */\nfunction untarMaybe(outputPath: string) {\n // @ts-expect-error `peek-stream` module currently untyped\n return peek({maxBuffer: 300, newline: false}, (data, swap) => {\n if (isTar(data)) {\n return swap(null, tar.extract(outputPath))\n }\n\n return swap(null)\n })\n}\n\n/**\n * Fetch the ids of all asset documents that reference the input asset.\n * The input asset is identified by its SHA-1 hash.\n *\n * @internal\n */\nfunction fetchAssetsByHash({\n client,\n type,\n}: {\n client: SanityClient\n type: 'file' | 'image'\n}): OperatorFunction<string, [hash: string, assetIds: string[]]> {\n return switchMap((hash) =>\n client.observable\n .fetch<string[]>(\n `*[\n _type == \"sanity.asset\" &&\n currentVersion._ref == *[\n _type == $type &&\n sha1hash == $hash\n ][0]._id\n ]._id`,\n {\n hash,\n type: ['sanity', `${type}Asset`].join('.'),\n },\n {\n tag: 'asset.getId',\n },\n )\n .pipe(switchMap((assetIds) => zip(of(hash), of(assetIds)))),\n )\n}\n\nfunction fetchExistingAssets({\n client,\n workingPath,\n}: Context): OperatorFunction<\n [type: 'file' | 'image', asset: string],\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset\n> {\n return mergeMap(([type, asset]) => {\n const createSha1Hash = createHash('sha1')\n\n const sha1hash = text(\n createReadStream(path.join(workingPath, asset)).pipe(createSha1Hash).setEncoding('hex'),\n )\n\n return from(sha1hash).pipe(\n tap((hash) =>\n importMediaDebug(`[Asset ${asset}] Checking for ${type} asset with hash ${hash}`),\n ),\n fetchAssetsByHash({client, type}),\n map<\n [string, string[]],\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset\n >(([hash, assetIds]) => {\n if (assetIds.length === 0) {\n return [type, asset, hash]\n }\n\n return {\n assetIds,\n isExistingAsset: true,\n originalFilename: asset,\n sha1Hash: hash,\n }\n }),\n )\n })\n}\n\n/**\n * Find the first matching entry in the provided NDJSON stream and attach it to the asset object.\n *\n * @internal\n */\nfunction resolveAspectData({ndjson}: Context): OperatorFunction<ResolvedAsset, AssetWithAspects> {\n return mergeMap((resolvedAsset) =>\n from(\n findNdjsonEntry<{aspects: unknown}>(\n ndjson(),\n (line) =>\n typeof line === 'object' &&\n line !== null &&\n 'filename' in line &&\n line.filename === resolvedAsset.originalFilename,\n ),\n ).pipe(\n map((aspectsFromImport) => ({\n ...resolvedAsset,\n aspects: aspectsFromImport?.aspects,\n })),\n ),\n )\n}\n\n// TODO: Batch mutations to reduce HTTP request count.\nexport function setAspects({\n client,\n replaceAspects,\n}: Pick<Context, 'client' | 'replaceAspects'>): OperatorFunction<\n AssetWithAspects,\n AssetWithAspects\n> {\n return mergeMap((asset) => {\n const {aspects, assetIds, isExistingAsset} = asset\n\n if (isExistingAsset && !replaceAspects) {\n importMediaDebug(`[Asset ${asset.originalFilename}] Skipping replacement of existing aspects`)\n return of(asset)\n }\n\n if (aspects === undefined) {\n importMediaDebug(`[Asset ${asset.originalFilename}] No aspects to import`)\n return of(asset)\n }\n\n const transaction = client.observable.transaction()\n for (const assetId of assetIds) {\n transaction.patch(assetId, {set: {aspects}})\n }\n\n importMediaDebug(\n `[Asset ${asset.originalFilename}] Setting aspects on asset documents ${JSON.stringify(assetIds)}`,\n )\n\n return transaction\n .commit({\n tag: 'asset.setAspects',\n visibility: 'async',\n })\n .pipe(map(() => asset))\n }, DEFAULT_CONCURRENCY)\n}\n\nfunction uploadAsset({\n client,\n workingPath,\n}: Context): OperatorFunction<\n [type: 'file' | 'image', asset: string, hash: string] | ResolvedAsset,\n ResolvedAsset\n> {\n return mergeMap((maybeResolvedAsset) => {\n if ('assetIds' in maybeResolvedAsset) {\n importMediaDebug(\n `[Asset ${maybeResolvedAsset.originalFilename}] Skipping upload of existing asset with hash ${maybeResolvedAsset.sha1Hash}`,\n )\n return of(maybeResolvedAsset)\n }\n\n const [type, asset, hash] = maybeResolvedAsset\n importMediaDebug(`[Asset ${asset}] Uploading new asset`)\n\n return client.observable.assets\n .upload(type, createReadStream(path.join(workingPath, asset)), {\n tag: 'asset.upload',\n })\n .pipe(\n catchError((error) => {\n // An asset matching the hash was not found during previous steps, but appears to exist upon upload.\n //\n // This may occur if:\n // - The asset was uploaded by another client since the check was performed.\n // - The asset instance document exists, but is not referenced by any asset document.\n if (error.statusCode === 409) {\n importMediaDebug(\n `[Asset ${asset}] Cannot overwrite existing ${type} asset with hash ${hash}`,\n )\n return EMPTY\n }\n return EMPTY\n }),\n filter((response) => response.type === 'response'),\n tap(() => importMediaDebug(`[Asset ${asset}] Finished uploading new asset`)),\n // TODO: The `client.assets.upload` method should return `MediaLibraryUploadResponse` when operating on Media Library resources. When that occurs, this type assertion can be removed.\n map((response) => (response as unknown as MediaLibraryUploadResponse).body),\n map<MediaLibraryUploadResult, ResolvedAsset>((result) => ({\n assetIds: [result.asset._id],\n isExistingAsset: false,\n originalFilename: asset,\n sha1Hash: hash,\n })),\n )\n }, DEFAULT_CONCURRENCY)\n}\n"],"names":["createHash","createReadStream","fs","mkdtemp","tmpdir","path","text","pipeline","styleText","gunzipMaybe","peek","catchError","EMPTY","filter","from","map","mergeMap","mergeWith","of","switchMap","tap","zip","tar","glob","findNdjsonEntry","isTar","importMediaDebug","DEFAULT_CONCURRENCY","importer","options","resolveSource","pipe","aspectsNdjsonPath","files","images","workingPath","fileCount","length","Error","context","ndjson","file","fetchExistingAssets","uploadAsset","resolveAspectData","setAspects","asset","sourcePath","stat","stats","isDirectory","join","tempPath","untarMaybe","importSourcePath","absolute","cwd","deep","undefined","dirname","Promise","all","outputPath","maxBuffer","newline","data","swap","extract","fetchAssetsByHash","client","type","hash","observable","fetch","tag","assetIds","createSha1Hash","sha1hash","setEncoding","isExistingAsset","originalFilename","sha1Hash","resolvedAsset","line","filename","aspectsFromImport","aspects","replaceAspects","transaction","assetId","patch","set","JSON","stringify","commit","visibility","maybeResolvedAsset","assets","upload","error","statusCode","response","body","result","_id"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { getSanityUrl } from '@sanity/cli-core';
2
2
  export function getManageUrl(projectId) {
3
- const sanityUrl = getSanityUrl();
4
- return projectId ? `${sanityUrl}/manage/project/${projectId}` : `${sanityUrl}/manage/`;
3
+ return projectId ? getSanityUrl(`/manage/project/${projectId}`) : getSanityUrl('/manage/');
5
4
  }
6
5
 
7
6
  //# sourceMappingURL=getManageUrl.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/projects/getManageUrl.ts"],"sourcesContent":["import {getSanityUrl} from '@sanity/cli-core'\n\nexport function getManageUrl(projectId: string | undefined): string {\n const sanityUrl = getSanityUrl()\n return projectId ? `${sanityUrl}/manage/project/${projectId}` : `${sanityUrl}/manage/`\n}\n"],"names":["getSanityUrl","getManageUrl","projectId","sanityUrl"],"mappings":"AAAA,SAAQA,YAAY,QAAO,mBAAkB;AAE7C,OAAO,SAASC,aAAaC,SAA6B;IACxD,MAAMC,YAAYH;IAClB,OAAOE,YAAY,GAAGC,UAAU,gBAAgB,EAAED,WAAW,GAAG,GAAGC,UAAU,QAAQ,CAAC;AACxF"}
1
+ {"version":3,"sources":["../../../src/actions/projects/getManageUrl.ts"],"sourcesContent":["import {getSanityUrl} from '@sanity/cli-core'\n\nexport function getManageUrl(projectId: string | undefined): string {\n return projectId ? getSanityUrl(`/manage/project/${projectId}`) : getSanityUrl('/manage/')\n}\n"],"names":["getSanityUrl","getManageUrl","projectId"],"mappings":"AAAA,SAAQA,YAAY,QAAO,mBAAkB;AAE7C,OAAO,SAASC,aAAaC,SAA6B;IACxD,OAAOA,YAAYF,aAAa,CAAC,gBAAgB,EAAEE,WAAW,IAAIF,aAAa;AACjF"}
@@ -2,6 +2,7 @@ import { isMainThread, parentPort, workerData } from 'node:worker_threads';
2
2
  import { findStudioConfigPath, getStudioWorkspaces } from '@sanity/cli-core';
3
3
  import { DescriptorConverter } from '@sanity/schema/_internal';
4
4
  import { getWorkspace } from '../../util/getWorkspace.js';
5
+ import { isSchemaError } from '../../util/isSchemaError.js';
5
6
  const { debugSerialize, level = 'warning', workDir, workspace: workspaceName } = workerData;
6
7
  async function main() {
7
8
  if (isMainThread || !parentPort) {
@@ -80,9 +81,6 @@ function getSerializedSchemaDebug(set) {
80
81
  function isEncodableObject(val) {
81
82
  return typeof val === 'object' && val !== null && !Array.isArray(val);
82
83
  }
83
- function isSchemaError(err) {
84
- return err !== null && typeof err === 'object' && 'schema' in err && err.schema !== null && typeof err.schema === 'object' && '_validation' in err.schema;
85
- }
86
84
  function getSerializedTypeDebug(typeDef) {
87
85
  const ext = typeof typeDef.extends === 'string' ? typeDef.extends : '<unknown>';
88
86
  let fields;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/schema/validateSchema.worker.ts"],"sourcesContent":["import {isMainThread, parentPort, workerData} from 'node:worker_threads'\n\nimport {findStudioConfigPath, getStudioWorkspaces} from '@sanity/cli-core'\nimport {\n type EncodableObject,\n type EncodableValue,\n type SetSynchronization,\n} from '@sanity/descriptors'\nimport {DescriptorConverter} from '@sanity/schema/_internal'\nimport {\n type Schema,\n type SchemaValidationProblem,\n type SchemaValidationProblemGroup,\n} from '@sanity/types'\n\nimport {getWorkspace} from '../../util/getWorkspace.js'\nimport {type SerializedSchemaDebug, type SerializedTypeDebug} from './types.js'\n\n/** @internal */\nexport interface ValidateSchemaWorkerData {\n workDir: string\n\n debugSerialize?: boolean\n level?: SchemaValidationProblem['severity']\n workspace?: string\n}\n\n/** @internal */\nexport interface ValidateSchemaWorkerResult {\n validation: SchemaValidationProblemGroup[]\n\n serializedDebug?: SerializedSchemaDebug\n}\n\nconst {\n debugSerialize,\n level = 'warning',\n workDir,\n workspace: workspaceName,\n} = workerData as ValidateSchemaWorkerData\n\nasync function main() {\n if (isMainThread || !parentPort) {\n throw new Error('This module must be run as a worker thread')\n }\n\n try {\n const configPath = await findStudioConfigPath(workDir)\n const workspaces = await getStudioWorkspaces(configPath)\n const workspace = getWorkspace(workspaces, workspaceName)\n const schema = workspace.schema\n parentPort?.postMessage(await resultFromSchema(schema))\n } catch (err: unknown) {\n if (isSchemaError(err)) {\n parentPort?.postMessage(await resultFromSchema(err.schema))\n return\n }\n\n throw err\n }\n}\n\nasync function resultFromSchema(schema: Schema): Promise<ValidateSchemaWorkerResult> {\n let serializedDebug: ValidateSchemaWorkerResult['serializedDebug']\n\n if (debugSerialize) {\n const conv = new DescriptorConverter()\n const set = await conv.get(schema)\n serializedDebug = getSerializedSchemaDebug(set)\n }\n\n const validation = schema._validation ?? []\n\n const result: ValidateSchemaWorkerResult = {\n serializedDebug,\n validation: validation\n .map((group) => ({\n ...group,\n problems: group.problems.filter((problem) =>\n level === 'error' ? problem.severity === 'error' : true,\n ),\n }))\n .filter((group) => group.problems.length),\n }\n\n return result\n}\n\nfunction getSerializedSchemaDebug(set: SetSynchronization<string>): SerializedSchemaDebug {\n let size = 0\n const types: Record<string, SerializedTypeDebug> = {}\n const hoisted: Record<string, SerializedTypeDebug> = {}\n\n for (const [id, value] of Object.entries(set.objectValues)) {\n const descType = typeof value.type === 'string' ? value.type : '<unknown>'\n switch (descType) {\n case 'sanity.schema.hoisted': {\n const key = typeof value.key === 'string' ? value.key : id\n // The `hoisted` can technically hoist _anything_,\n // but we detect the common case of field + array element.\n if (isEncodableObject(value.value) && isEncodableObject(value.value.typeDef)) {\n const debug = getSerializedTypeDebug(value.value.typeDef)\n hoisted[key] = debug\n size += debug.size\n }\n break\n }\n case 'sanity.schema.namedType': {\n const typeName = typeof value.name === 'string' ? value.name : id\n if (isEncodableObject(value.typeDef)) {\n const debug = getSerializedTypeDebug(value.typeDef)\n types[typeName] = debug\n size += debug.size\n }\n break\n }\n default:\n }\n size += JSON.stringify(value).length\n }\n\n return {\n hoisted,\n size,\n types,\n }\n}\n\nfunction isEncodableObject(val: EncodableValue | undefined): val is EncodableObject {\n return typeof val === 'object' && val !== null && !Array.isArray(val)\n}\n\nfunction isSchemaError(err: unknown): err is {schema: Schema} {\n return (\n err !== null &&\n typeof err === 'object' &&\n 'schema' in err &&\n err.schema !== null &&\n typeof err.schema === 'object' &&\n '_validation' in err.schema\n )\n}\n\nfunction getSerializedTypeDebug(typeDef: EncodableObject): SerializedTypeDebug {\n const ext = typeof typeDef.extends === 'string' ? typeDef.extends : '<unknown>'\n let fields: SerializedTypeDebug['fields']\n let of: SerializedTypeDebug['of']\n\n if (Array.isArray(typeDef.fields)) {\n fields = {}\n\n for (const field of typeDef.fields) {\n if (!isEncodableObject(field)) continue\n const name = field.name\n const fieldTypeDef = field.typeDef\n if (typeof name !== 'string' || !isEncodableObject(fieldTypeDef)) continue\n\n fields[name] = getSerializedTypeDebug(fieldTypeDef)\n }\n }\n\n if (Array.isArray(typeDef.of)) {\n of = {}\n\n for (const field of typeDef.of) {\n if (!isEncodableObject(field)) continue\n const name = field.name\n const arrayTypeDef = field.typeDef\n if (typeof name !== 'string' || !isEncodableObject(arrayTypeDef)) continue\n\n of[name] = getSerializedTypeDebug(arrayTypeDef)\n }\n }\n\n return {\n extends: ext,\n fields,\n of,\n size: JSON.stringify(typeDef).length,\n }\n}\n\nawait main()\n"],"names":["isMainThread","parentPort","workerData","findStudioConfigPath","getStudioWorkspaces","DescriptorConverter","getWorkspace","debugSerialize","level","workDir","workspace","workspaceName","main","Error","configPath","workspaces","schema","postMessage","resultFromSchema","err","isSchemaError","serializedDebug","conv","set","get","getSerializedSchemaDebug","validation","_validation","result","map","group","problems","filter","problem","severity","length","size","types","hoisted","id","value","Object","entries","objectValues","descType","type","key","isEncodableObject","typeDef","debug","getSerializedTypeDebug","typeName","name","JSON","stringify","val","Array","isArray","ext","extends","fields","of","field","fieldTypeDef","arrayTypeDef"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/schema/validateSchema.worker.ts"],"sourcesContent":["import {isMainThread, parentPort, workerData} from 'node:worker_threads'\n\nimport {findStudioConfigPath, getStudioWorkspaces} from '@sanity/cli-core'\nimport {\n type EncodableObject,\n type EncodableValue,\n type SetSynchronization,\n} from '@sanity/descriptors'\nimport {DescriptorConverter} from '@sanity/schema/_internal'\nimport {\n type Schema,\n type SchemaValidationProblem,\n type SchemaValidationProblemGroup,\n} from '@sanity/types'\n\nimport {getWorkspace} from '../../util/getWorkspace.js'\nimport {isSchemaError} from '../../util/isSchemaError.js'\nimport {type SerializedSchemaDebug, type SerializedTypeDebug} from './types.js'\n\n/** @internal */\nexport interface ValidateSchemaWorkerData {\n workDir: string\n\n debugSerialize?: boolean\n level?: SchemaValidationProblem['severity']\n workspace?: string\n}\n\n/** @internal */\nexport interface ValidateSchemaWorkerResult {\n validation: SchemaValidationProblemGroup[]\n\n serializedDebug?: SerializedSchemaDebug\n}\n\nconst {\n debugSerialize,\n level = 'warning',\n workDir,\n workspace: workspaceName,\n} = workerData as ValidateSchemaWorkerData\n\nasync function main() {\n if (isMainThread || !parentPort) {\n throw new Error('This module must be run as a worker thread')\n }\n\n try {\n const configPath = await findStudioConfigPath(workDir)\n const workspaces = await getStudioWorkspaces(configPath)\n const workspace = getWorkspace(workspaces, workspaceName)\n const schema = workspace.schema\n parentPort?.postMessage(await resultFromSchema(schema))\n } catch (err: unknown) {\n if (isSchemaError(err)) {\n parentPort?.postMessage(await resultFromSchema(err.schema))\n return\n }\n\n throw err\n }\n}\n\nasync function resultFromSchema(schema: Schema): Promise<ValidateSchemaWorkerResult> {\n let serializedDebug: ValidateSchemaWorkerResult['serializedDebug']\n\n if (debugSerialize) {\n const conv = new DescriptorConverter()\n const set = await conv.get(schema)\n serializedDebug = getSerializedSchemaDebug(set)\n }\n\n const validation = schema._validation ?? []\n\n const result: ValidateSchemaWorkerResult = {\n serializedDebug,\n validation: validation\n .map((group) => ({\n ...group,\n problems: group.problems.filter((problem) =>\n level === 'error' ? problem.severity === 'error' : true,\n ),\n }))\n .filter((group) => group.problems.length),\n }\n\n return result\n}\n\nfunction getSerializedSchemaDebug(set: SetSynchronization<string>): SerializedSchemaDebug {\n let size = 0\n const types: Record<string, SerializedTypeDebug> = {}\n const hoisted: Record<string, SerializedTypeDebug> = {}\n\n for (const [id, value] of Object.entries(set.objectValues)) {\n const descType = typeof value.type === 'string' ? value.type : '<unknown>'\n switch (descType) {\n case 'sanity.schema.hoisted': {\n const key = typeof value.key === 'string' ? value.key : id\n // The `hoisted` can technically hoist _anything_,\n // but we detect the common case of field + array element.\n if (isEncodableObject(value.value) && isEncodableObject(value.value.typeDef)) {\n const debug = getSerializedTypeDebug(value.value.typeDef)\n hoisted[key] = debug\n size += debug.size\n }\n break\n }\n case 'sanity.schema.namedType': {\n const typeName = typeof value.name === 'string' ? value.name : id\n if (isEncodableObject(value.typeDef)) {\n const debug = getSerializedTypeDebug(value.typeDef)\n types[typeName] = debug\n size += debug.size\n }\n break\n }\n default:\n }\n size += JSON.stringify(value).length\n }\n\n return {\n hoisted,\n size,\n types,\n }\n}\n\nfunction isEncodableObject(val: EncodableValue | undefined): val is EncodableObject {\n return typeof val === 'object' && val !== null && !Array.isArray(val)\n}\n\nfunction getSerializedTypeDebug(typeDef: EncodableObject): SerializedTypeDebug {\n const ext = typeof typeDef.extends === 'string' ? typeDef.extends : '<unknown>'\n let fields: SerializedTypeDebug['fields']\n let of: SerializedTypeDebug['of']\n\n if (Array.isArray(typeDef.fields)) {\n fields = {}\n\n for (const field of typeDef.fields) {\n if (!isEncodableObject(field)) continue\n const name = field.name\n const fieldTypeDef = field.typeDef\n if (typeof name !== 'string' || !isEncodableObject(fieldTypeDef)) continue\n\n fields[name] = getSerializedTypeDebug(fieldTypeDef)\n }\n }\n\n if (Array.isArray(typeDef.of)) {\n of = {}\n\n for (const field of typeDef.of) {\n if (!isEncodableObject(field)) continue\n const name = field.name\n const arrayTypeDef = field.typeDef\n if (typeof name !== 'string' || !isEncodableObject(arrayTypeDef)) continue\n\n of[name] = getSerializedTypeDebug(arrayTypeDef)\n }\n }\n\n return {\n extends: ext,\n fields,\n of,\n size: JSON.stringify(typeDef).length,\n }\n}\n\nawait main()\n"],"names":["isMainThread","parentPort","workerData","findStudioConfigPath","getStudioWorkspaces","DescriptorConverter","getWorkspace","isSchemaError","debugSerialize","level","workDir","workspace","workspaceName","main","Error","configPath","workspaces","schema","postMessage","resultFromSchema","err","serializedDebug","conv","set","get","getSerializedSchemaDebug","validation","_validation","result","map","group","problems","filter","problem","severity","length","size","types","hoisted","id","value","Object","entries","objectValues","descType","type","key","isEncodableObject","typeDef","debug","getSerializedTypeDebug","typeName","name","JSON","stringify","val","Array","isArray","ext","extends","fields","of","field","fieldTypeDef","arrayTypeDef"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export function isTrueish(value) {
2
+ if (value === undefined) return false;
3
+ if (value.toLowerCase() === 'true') return true;
4
+ if (value.toLowerCase() === 'false') return false;
5
+ const number = Number.parseInt(value, 10);
6
+ if (Number.isNaN(number)) return false;
7
+ return number > 0;
8
+ }
9
+
10
+ //# sourceMappingURL=isTrueish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/telemetry/isTrueish.ts"],"sourcesContent":["export function isTrueish(value: string | undefined) {\n if (value === undefined) return false\n if (value.toLowerCase() === 'true') return true\n if (value.toLowerCase() === 'false') return false\n const number = Number.parseInt(value, 10)\n if (Number.isNaN(number)) return false\n return number > 0\n}\n"],"names":["isTrueish","value","undefined","toLowerCase","number","Number","parseInt","isNaN"],"mappings":"AAAA,OAAO,SAASA,UAAUC,KAAyB;IACjD,IAAIA,UAAUC,WAAW,OAAO;IAChC,IAAID,MAAME,WAAW,OAAO,QAAQ,OAAO;IAC3C,IAAIF,MAAME,WAAW,OAAO,SAAS,OAAO;IAC5C,MAAMC,SAASC,OAAOC,QAAQ,CAACL,OAAO;IACtC,IAAII,OAAOE,KAAK,CAACH,SAAS,OAAO;IACjC,OAAOA,SAAS;AAClB"}
@@ -1,5 +1,6 @@
1
- import { getCliToken, isCi, isTrueish } from '@sanity/cli-core';
1
+ import { getCliToken, isCi } from '@sanity/cli-core';
2
2
  import { fetchTelemetryConsent, isValidApiConsentStatus, VALID_API_STATUSES } from '../../services/telemetry.js';
3
+ import { isTrueish } from './isTrueish.js';
3
4
  import { telemetryDebug } from './telemetryDebug.js';
4
5
  function parseApiConsentStatus(value) {
5
6
  if (typeof value === 'string' && isValidApiConsentStatus(value)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/telemetry/resolveConsent.ts"],"sourcesContent":["import {type ConsentInformation, getCliToken, isCi, isTrueish} from '@sanity/cli-core'\n\nimport {\n fetchTelemetryConsent,\n isValidApiConsentStatus,\n VALID_API_STATUSES,\n type ValidApiConsentStatus,\n} from '../../services/telemetry.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\nfunction parseApiConsentStatus(value: unknown): ValidApiConsentStatus {\n if (typeof value === 'string' && isValidApiConsentStatus(value)) {\n return value\n }\n throw new Error(`Invalid consent status. Must be one of: ${VALID_API_STATUSES.join(', ')}`)\n}\n\nexport async function resolveConsent(): Promise<ConsentInformation> {\n telemetryDebug('Resolving consent…')\n if (isCi()) {\n telemetryDebug('CI environment detected, treating telemetry consent as denied')\n return {status: 'denied'}\n }\n\n if (isTrueish(process.env.DO_NOT_TRACK)) {\n telemetryDebug('DO_NOT_TRACK is set, consent is denied')\n return {\n reason: 'localOverride',\n status: 'denied',\n }\n }\n\n const token = await getCliToken()\n if (!token) {\n telemetryDebug('User is not logged in, consent is undetermined')\n return {\n reason: 'unauthenticated',\n status: 'undetermined',\n }\n }\n\n try {\n const response = await fetchTelemetryConsent()\n\n telemetryDebug('User consent status is %s', response.status)\n return {status: parseApiConsentStatus(response.status)}\n } catch (err) {\n telemetryDebug('Failed to fetch user consent status, treating it as \"undetermined\": %s', err)\n return {\n reason: 'fetchError',\n status: 'undetermined',\n }\n }\n}\n"],"names":["getCliToken","isCi","isTrueish","fetchTelemetryConsent","isValidApiConsentStatus","VALID_API_STATUSES","telemetryDebug","parseApiConsentStatus","value","Error","join","resolveConsent","status","process","env","DO_NOT_TRACK","reason","token","response","err"],"mappings":"AAAA,SAAiCA,WAAW,EAAEC,IAAI,EAAEC,SAAS,QAAO,mBAAkB;AAEtF,SACEC,qBAAqB,EACrBC,uBAAuB,EACvBC,kBAAkB,QAEb,8BAA6B;AACpC,SAAQC,cAAc,QAAO,sBAAqB;AAElD,SAASC,sBAAsBC,KAAc;IAC3C,IAAI,OAAOA,UAAU,YAAYJ,wBAAwBI,QAAQ;QAC/D,OAAOA;IACT;IACA,MAAM,IAAIC,MAAM,CAAC,wCAAwC,EAAEJ,mBAAmBK,IAAI,CAAC,OAAO;AAC5F;AAEA,OAAO,eAAeC;IACpBL,eAAe;IACf,IAAIL,QAAQ;QACVK,eAAe;QACf,OAAO;YAACM,QAAQ;QAAQ;IAC1B;IAEA,IAAIV,UAAUW,QAAQC,GAAG,CAACC,YAAY,GAAG;QACvCT,eAAe;QACf,OAAO;YACLU,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,MAAMK,QAAQ,MAAMjB;IACpB,IAAI,CAACiB,OAAO;QACVX,eAAe;QACf,OAAO;YACLU,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,IAAI;QACF,MAAMM,WAAW,MAAMf;QAEvBG,eAAe,6BAA6BY,SAASN,MAAM;QAC3D,OAAO;YAACA,QAAQL,sBAAsBW,SAASN,MAAM;QAAC;IACxD,EAAE,OAAOO,KAAK;QACZb,eAAe,0EAA0Ea;QACzF,OAAO;YACLH,QAAQ;YACRJ,QAAQ;QACV;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/telemetry/resolveConsent.ts"],"sourcesContent":["import {type ConsentInformation, getCliToken, isCi} from '@sanity/cli-core'\n\nimport {\n fetchTelemetryConsent,\n isValidApiConsentStatus,\n VALID_API_STATUSES,\n type ValidApiConsentStatus,\n} from '../../services/telemetry.js'\nimport {isTrueish} from './isTrueish.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\nfunction parseApiConsentStatus(value: unknown): ValidApiConsentStatus {\n if (typeof value === 'string' && isValidApiConsentStatus(value)) {\n return value\n }\n throw new Error(`Invalid consent status. Must be one of: ${VALID_API_STATUSES.join(', ')}`)\n}\n\nexport async function resolveConsent(): Promise<ConsentInformation> {\n telemetryDebug('Resolving consent…')\n if (isCi()) {\n telemetryDebug('CI environment detected, treating telemetry consent as denied')\n return {status: 'denied'}\n }\n\n if (isTrueish(process.env.DO_NOT_TRACK)) {\n telemetryDebug('DO_NOT_TRACK is set, consent is denied')\n return {\n reason: 'localOverride',\n status: 'denied',\n }\n }\n\n const token = await getCliToken()\n if (!token) {\n telemetryDebug('User is not logged in, consent is undetermined')\n return {\n reason: 'unauthenticated',\n status: 'undetermined',\n }\n }\n\n try {\n const response = await fetchTelemetryConsent()\n\n telemetryDebug('User consent status is %s', response.status)\n return {status: parseApiConsentStatus(response.status)}\n } catch (err) {\n telemetryDebug('Failed to fetch user consent status, treating it as \"undetermined\": %s', err)\n return {\n reason: 'fetchError',\n status: 'undetermined',\n }\n }\n}\n"],"names":["getCliToken","isCi","fetchTelemetryConsent","isValidApiConsentStatus","VALID_API_STATUSES","isTrueish","telemetryDebug","parseApiConsentStatus","value","Error","join","resolveConsent","status","process","env","DO_NOT_TRACK","reason","token","response","err"],"mappings":"AAAA,SAAiCA,WAAW,EAAEC,IAAI,QAAO,mBAAkB;AAE3E,SACEC,qBAAqB,EACrBC,uBAAuB,EACvBC,kBAAkB,QAEb,8BAA6B;AACpC,SAAQC,SAAS,QAAO,iBAAgB;AACxC,SAAQC,cAAc,QAAO,sBAAqB;AAElD,SAASC,sBAAsBC,KAAc;IAC3C,IAAI,OAAOA,UAAU,YAAYL,wBAAwBK,QAAQ;QAC/D,OAAOA;IACT;IACA,MAAM,IAAIC,MAAM,CAAC,wCAAwC,EAAEL,mBAAmBM,IAAI,CAAC,OAAO;AAC5F;AAEA,OAAO,eAAeC;IACpBL,eAAe;IACf,IAAIL,QAAQ;QACVK,eAAe;QACf,OAAO;YAACM,QAAQ;QAAQ;IAC1B;IAEA,IAAIP,UAAUQ,QAAQC,GAAG,CAACC,YAAY,GAAG;QACvCT,eAAe;QACf,OAAO;YACLU,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,MAAMK,QAAQ,MAAMjB;IACpB,IAAI,CAACiB,OAAO;QACVX,eAAe;QACf,OAAO;YACLU,QAAQ;YACRJ,QAAQ;QACV;IACF;IAEA,IAAI;QACF,MAAMM,WAAW,MAAMhB;QAEvBI,eAAe,6BAA6BY,SAASN,MAAM;QAC3D,OAAO;YAACA,QAAQL,sBAAsBW,SAASN,MAAM;QAAC;IACxD,EAAE,OAAOO,KAAK;QACZb,eAAe,0EAA0Ea;QACzF,OAAO;YACLH,QAAQ;YACRJ,QAAQ;QACV;IACF;AACF"}
@@ -1,5 +1,6 @@
1
- import { getGlobalCliClient, getUserConfig, isCi, isTrueish } from '@sanity/cli-core';
1
+ import { getGlobalCliClient, getUserConfig, isCi } from '@sanity/cli-core';
2
2
  import { TELEMETRY_CONSENT_CONFIG_KEY } from '../../services/telemetry.js';
3
+ import { isTrueish } from './isTrueish.js';
3
4
  import { resolveConsent } from './resolveConsent.js';
4
5
  import { telemetryDebug } from './telemetryDebug.js';
5
6
  // Type guard for error objects with HTTP properties
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/telemetry/setConsent.ts"],"sourcesContent":["import {\n type ConsentInformation,\n getGlobalCliClient,\n getUserConfig,\n isCi,\n isTrueish,\n} from '@sanity/cli-core'\n\nimport {TELEMETRY_CONSENT_CONFIG_KEY, type ValidApiConsentStatus} from '../../services/telemetry.js'\nimport {resolveConsent} from './resolveConsent.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\ntype SettableConsentStatus = Extract<ValidApiConsentStatus, 'denied' | 'granted'>\n\n// Type guard for error objects with HTTP properties\nfunction isHttpError(error: unknown): error is {\n message: string\n response?: {body?: {message?: string}}\n statusCode: number\n} {\n return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error\n}\n\ninterface SetConsentOptions {\n status: SettableConsentStatus\n}\n\ninterface SetConsentResult {\n changed: boolean\n currentStatus: ConsentInformation\n message: string\n}\n\nexport async function setConsent({status}: SetConsentOptions): Promise<SetConsentResult> {\n telemetryDebug('Setting telemetry consent to \"%s\"', status)\n\n // Check current consent status first\n const currentConsent = await resolveConsent()\n\n // Handle various blocking conditions\n if (isCi()) {\n return {\n changed: false,\n currentStatus: currentConsent,\n message: 'Cannot set telemetry consent in CI environment',\n }\n }\n\n if (isTrueish(process.env.DO_NOT_TRACK) && status === 'granted') {\n return {\n changed: false,\n currentStatus: currentConsent,\n message:\n 'Cannot enable telemetry while DO_NOT_TRACK environment variable is set. Unset DO_NOT_TRACK to enable telemetry.',\n }\n }\n\n // Check if already at desired status\n if (currentConsent.status === status) {\n const message =\n status === 'granted'\n ? \"You've already enabled telemetry data collection to help us improve Sanity.\"\n : currentConsent.reason === 'localOverride'\n ? \"You've already opted out of telemetry data collection.\\nNo data is collected from your machine.\\n\\nUsing DO_NOT_TRACK environment variable.\"\n : \"You've already opted out of telemetry data collection.\\nNo data is collected from your Sanity account.\"\n\n return {\n changed: false,\n currentStatus: currentConsent,\n message,\n }\n }\n\n // User must be logged in to set consent\n if (currentConsent.status === 'undetermined' && currentConsent.reason === 'unauthenticated') {\n return {\n changed: false,\n currentStatus: currentConsent,\n message: 'You need to log in first to set telemetry preferences.',\n }\n }\n\n try {\n const client = await getGlobalCliClient({\n apiVersion: '2023-12-18',\n requireUser: true,\n })\n\n const uri = `/users/me/consents/telemetry/status/${status}`\n telemetryDebug('Sending telemetry consent status to %s', uri)\n\n await client.request({\n method: 'PUT',\n uri,\n })\n\n // Clear cached telemetry consent\n const userConfig = getUserConfig()\n userConfig.delete(TELEMETRY_CONSENT_CONFIG_KEY)\n\n const successMessage =\n status === 'granted'\n ? \"You've now enabled telemetry data collection to help us improve Sanity.\"\n : \"You've opted out of telemetry data collection.\\nNo data will be collected from your Sanity account.\"\n\n const newConsent = await resolveConsent()\n\n return {\n changed: true,\n currentStatus: newConsent,\n message: successMessage,\n }\n } catch (err: unknown) {\n const errorMessage = `Failed to ${status === 'granted' ? 'enable' : 'disable'} telemetry`\n\n if (isHttpError(err) && err.statusCode === 403) {\n // Create a new error without stack trace from original error\n const message = err.response?.body?.message\n ? `${errorMessage}: ${err.response.body.message}`\n : errorMessage\n throw new Error(message)\n }\n\n if (isHttpError(err)) {\n // For other errors, preserve the original error but update the message\n err.message = err.response?.body?.message\n ? `${errorMessage}: ${err.response.body.message}`\n : errorMessage\n throw err\n }\n\n // For non-HTTP errors, wrap in a new error\n throw new Error(errorMessage)\n }\n}\n"],"names":["getGlobalCliClient","getUserConfig","isCi","isTrueish","TELEMETRY_CONSENT_CONFIG_KEY","resolveConsent","telemetryDebug","isHttpError","error","setConsent","status","currentConsent","changed","currentStatus","message","process","env","DO_NOT_TRACK","reason","client","apiVersion","requireUser","uri","request","method","userConfig","delete","successMessage","newConsent","err","errorMessage","statusCode","response","body","Error"],"mappings":"AAAA,SAEEA,kBAAkB,EAClBC,aAAa,EACbC,IAAI,EACJC,SAAS,QACJ,mBAAkB;AAEzB,SAAQC,4BAA4B,QAAmC,8BAA6B;AACpG,SAAQC,cAAc,QAAO,sBAAqB;AAClD,SAAQC,cAAc,QAAO,sBAAqB;AAIlD,oDAAoD;AACpD,SAASC,YAAYC,KAAc;IAKjC,OAAO,OAAOA,UAAU,YAAYA,UAAU,QAAQ,gBAAgBA,SAAS,aAAaA;AAC9F;AAYA,OAAO,eAAeC,WAAW,EAACC,MAAM,EAAoB;IAC1DJ,eAAe,qCAAqCI;IAEpD,qCAAqC;IACrC,MAAMC,iBAAiB,MAAMN;IAE7B,qCAAqC;IACrC,IAAIH,QAAQ;QACV,OAAO;YACLU,SAAS;YACTC,eAAeF;YACfG,SAAS;QACX;IACF;IAEA,IAAIX,UAAUY,QAAQC,GAAG,CAACC,YAAY,KAAKP,WAAW,WAAW;QAC/D,OAAO;YACLE,SAAS;YACTC,eAAeF;YACfG,SACE;QACJ;IACF;IAEA,qCAAqC;IACrC,IAAIH,eAAeD,MAAM,KAAKA,QAAQ;QACpC,MAAMI,UACJJ,WAAW,YACP,gFACAC,eAAeO,MAAM,KAAK,kBACxB,gJACA;QAER,OAAO;YACLN,SAAS;YACTC,eAAeF;YACfG;QACF;IACF;IAEA,wCAAwC;IACxC,IAAIH,eAAeD,MAAM,KAAK,kBAAkBC,eAAeO,MAAM,KAAK,mBAAmB;QAC3F,OAAO;YACLN,SAAS;YACTC,eAAeF;YACfG,SAAS;QACX;IACF;IAEA,IAAI;QACF,MAAMK,SAAS,MAAMnB,mBAAmB;YACtCoB,YAAY;YACZC,aAAa;QACf;QAEA,MAAMC,MAAM,CAAC,oCAAoC,EAAEZ,QAAQ;QAC3DJ,eAAe,0CAA0CgB;QAEzD,MAAMH,OAAOI,OAAO,CAAC;YACnBC,QAAQ;YACRF;QACF;QAEA,iCAAiC;QACjC,MAAMG,aAAaxB;QACnBwB,WAAWC,MAAM,CAACtB;QAElB,MAAMuB,iBACJjB,WAAW,YACP,4EACA;QAEN,MAAMkB,aAAa,MAAMvB;QAEzB,OAAO;YACLO,SAAS;YACTC,eAAee;YACfd,SAASa;QACX;IACF,EAAE,OAAOE,KAAc;QACrB,MAAMC,eAAe,CAAC,UAAU,EAAEpB,WAAW,YAAY,WAAW,UAAU,UAAU,CAAC;QAEzF,IAAIH,YAAYsB,QAAQA,IAAIE,UAAU,KAAK,KAAK;YAC9C,6DAA6D;YAC7D,MAAMjB,UAAUe,IAAIG,QAAQ,EAAEC,MAAMnB,UAChC,GAAGgB,aAAa,EAAE,EAAED,IAAIG,QAAQ,CAACC,IAAI,CAACnB,OAAO,EAAE,GAC/CgB;YACJ,MAAM,IAAII,MAAMpB;QAClB;QAEA,IAAIP,YAAYsB,MAAM;YACpB,uEAAuE;YACvEA,IAAIf,OAAO,GAAGe,IAAIG,QAAQ,EAAEC,MAAMnB,UAC9B,GAAGgB,aAAa,EAAE,EAAED,IAAIG,QAAQ,CAACC,IAAI,CAACnB,OAAO,EAAE,GAC/CgB;YACJ,MAAMD;QACR;QAEA,2CAA2C;QAC3C,MAAM,IAAIK,MAAMJ;IAClB;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/telemetry/setConsent.ts"],"sourcesContent":["import {type ConsentInformation, getGlobalCliClient, getUserConfig, isCi} from '@sanity/cli-core'\n\nimport {TELEMETRY_CONSENT_CONFIG_KEY, type ValidApiConsentStatus} from '../../services/telemetry.js'\nimport {isTrueish} from './isTrueish.js'\nimport {resolveConsent} from './resolveConsent.js'\nimport {telemetryDebug} from './telemetryDebug.js'\n\ntype SettableConsentStatus = Extract<ValidApiConsentStatus, 'denied' | 'granted'>\n\n// Type guard for error objects with HTTP properties\nfunction isHttpError(error: unknown): error is {\n message: string\n response?: {body?: {message?: string}}\n statusCode: number\n} {\n return typeof error === 'object' && error !== null && 'statusCode' in error && 'message' in error\n}\n\ninterface SetConsentOptions {\n status: SettableConsentStatus\n}\n\ninterface SetConsentResult {\n changed: boolean\n currentStatus: ConsentInformation\n message: string\n}\n\nexport async function setConsent({status}: SetConsentOptions): Promise<SetConsentResult> {\n telemetryDebug('Setting telemetry consent to \"%s\"', status)\n\n // Check current consent status first\n const currentConsent = await resolveConsent()\n\n // Handle various blocking conditions\n if (isCi()) {\n return {\n changed: false,\n currentStatus: currentConsent,\n message: 'Cannot set telemetry consent in CI environment',\n }\n }\n\n if (isTrueish(process.env.DO_NOT_TRACK) && status === 'granted') {\n return {\n changed: false,\n currentStatus: currentConsent,\n message:\n 'Cannot enable telemetry while DO_NOT_TRACK environment variable is set. Unset DO_NOT_TRACK to enable telemetry.',\n }\n }\n\n // Check if already at desired status\n if (currentConsent.status === status) {\n const message =\n status === 'granted'\n ? \"You've already enabled telemetry data collection to help us improve Sanity.\"\n : currentConsent.reason === 'localOverride'\n ? \"You've already opted out of telemetry data collection.\\nNo data is collected from your machine.\\n\\nUsing DO_NOT_TRACK environment variable.\"\n : \"You've already opted out of telemetry data collection.\\nNo data is collected from your Sanity account.\"\n\n return {\n changed: false,\n currentStatus: currentConsent,\n message,\n }\n }\n\n // User must be logged in to set consent\n if (currentConsent.status === 'undetermined' && currentConsent.reason === 'unauthenticated') {\n return {\n changed: false,\n currentStatus: currentConsent,\n message: 'You need to log in first to set telemetry preferences.',\n }\n }\n\n try {\n const client = await getGlobalCliClient({\n apiVersion: '2023-12-18',\n requireUser: true,\n })\n\n const uri = `/users/me/consents/telemetry/status/${status}`\n telemetryDebug('Sending telemetry consent status to %s', uri)\n\n await client.request({\n method: 'PUT',\n uri,\n })\n\n // Clear cached telemetry consent\n const userConfig = getUserConfig()\n userConfig.delete(TELEMETRY_CONSENT_CONFIG_KEY)\n\n const successMessage =\n status === 'granted'\n ? \"You've now enabled telemetry data collection to help us improve Sanity.\"\n : \"You've opted out of telemetry data collection.\\nNo data will be collected from your Sanity account.\"\n\n const newConsent = await resolveConsent()\n\n return {\n changed: true,\n currentStatus: newConsent,\n message: successMessage,\n }\n } catch (err: unknown) {\n const errorMessage = `Failed to ${status === 'granted' ? 'enable' : 'disable'} telemetry`\n\n if (isHttpError(err) && err.statusCode === 403) {\n // Create a new error without stack trace from original error\n const message = err.response?.body?.message\n ? `${errorMessage}: ${err.response.body.message}`\n : errorMessage\n throw new Error(message)\n }\n\n if (isHttpError(err)) {\n // For other errors, preserve the original error but update the message\n err.message = err.response?.body?.message\n ? `${errorMessage}: ${err.response.body.message}`\n : errorMessage\n throw err\n }\n\n // For non-HTTP errors, wrap in a new error\n throw new Error(errorMessage)\n }\n}\n"],"names":["getGlobalCliClient","getUserConfig","isCi","TELEMETRY_CONSENT_CONFIG_KEY","isTrueish","resolveConsent","telemetryDebug","isHttpError","error","setConsent","status","currentConsent","changed","currentStatus","message","process","env","DO_NOT_TRACK","reason","client","apiVersion","requireUser","uri","request","method","userConfig","delete","successMessage","newConsent","err","errorMessage","statusCode","response","body","Error"],"mappings":"AAAA,SAAiCA,kBAAkB,EAAEC,aAAa,EAAEC,IAAI,QAAO,mBAAkB;AAEjG,SAAQC,4BAA4B,QAAmC,8BAA6B;AACpG,SAAQC,SAAS,QAAO,iBAAgB;AACxC,SAAQC,cAAc,QAAO,sBAAqB;AAClD,SAAQC,cAAc,QAAO,sBAAqB;AAIlD,oDAAoD;AACpD,SAASC,YAAYC,KAAc;IAKjC,OAAO,OAAOA,UAAU,YAAYA,UAAU,QAAQ,gBAAgBA,SAAS,aAAaA;AAC9F;AAYA,OAAO,eAAeC,WAAW,EAACC,MAAM,EAAoB;IAC1DJ,eAAe,qCAAqCI;IAEpD,qCAAqC;IACrC,MAAMC,iBAAiB,MAAMN;IAE7B,qCAAqC;IACrC,IAAIH,QAAQ;QACV,OAAO;YACLU,SAAS;YACTC,eAAeF;YACfG,SAAS;QACX;IACF;IAEA,IAAIV,UAAUW,QAAQC,GAAG,CAACC,YAAY,KAAKP,WAAW,WAAW;QAC/D,OAAO;YACLE,SAAS;YACTC,eAAeF;YACfG,SACE;QACJ;IACF;IAEA,qCAAqC;IACrC,IAAIH,eAAeD,MAAM,KAAKA,QAAQ;QACpC,MAAMI,UACJJ,WAAW,YACP,gFACAC,eAAeO,MAAM,KAAK,kBACxB,gJACA;QAER,OAAO;YACLN,SAAS;YACTC,eAAeF;YACfG;QACF;IACF;IAEA,wCAAwC;IACxC,IAAIH,eAAeD,MAAM,KAAK,kBAAkBC,eAAeO,MAAM,KAAK,mBAAmB;QAC3F,OAAO;YACLN,SAAS;YACTC,eAAeF;YACfG,SAAS;QACX;IACF;IAEA,IAAI;QACF,MAAMK,SAAS,MAAMnB,mBAAmB;YACtCoB,YAAY;YACZC,aAAa;QACf;QAEA,MAAMC,MAAM,CAAC,oCAAoC,EAAEZ,QAAQ;QAC3DJ,eAAe,0CAA0CgB;QAEzD,MAAMH,OAAOI,OAAO,CAAC;YACnBC,QAAQ;YACRF;QACF;QAEA,iCAAiC;QACjC,MAAMG,aAAaxB;QACnBwB,WAAWC,MAAM,CAACvB;QAElB,MAAMwB,iBACJjB,WAAW,YACP,4EACA;QAEN,MAAMkB,aAAa,MAAMvB;QAEzB,OAAO;YACLO,SAAS;YACTC,eAAee;YACfd,SAASa;QACX;IACF,EAAE,OAAOE,KAAc;QACrB,MAAMC,eAAe,CAAC,UAAU,EAAEpB,WAAW,YAAY,WAAW,UAAU,UAAU,CAAC;QAEzF,IAAIH,YAAYsB,QAAQA,IAAIE,UAAU,KAAK,KAAK;YAC9C,6DAA6D;YAC7D,MAAMjB,UAAUe,IAAIG,QAAQ,EAAEC,MAAMnB,UAChC,GAAGgB,aAAa,EAAE,EAAED,IAAIG,QAAQ,CAACC,IAAI,CAACnB,OAAO,EAAE,GAC/CgB;YACJ,MAAM,IAAII,MAAMpB;QAClB;QAEA,IAAIP,YAAYsB,MAAM;YACpB,uEAAuE;YACvEA,IAAIf,OAAO,GAAGe,IAAIG,QAAQ,EAAEC,MAAMnB,UAC9B,GAAGgB,aAAa,EAAE,EAAED,IAAIG,QAAQ,CAACC,IAAI,CAACnB,OAAO,EAAE,GAC/CgB;YACJ,MAAMD;QACR;QAEA,2CAA2C;QAC3C,MAAM,IAAIK,MAAMJ;IAClB;AACF"}
@@ -3,7 +3,6 @@ import { readPackageJson } from '@sanity/cli-core';
3
3
  import { spinner } from '@sanity/cli-core/ux';
4
4
  import promiseProps from 'promise-props-recursive';
5
5
  import semver from 'semver';
6
- import semverCompare from 'semver-compare';
7
6
  import { getCliVersion } from '../../util/getCliVersion.js';
8
7
  import { buildPackageArray } from './buildPackageArray.js';
9
8
  import { filterSanityModules } from './filterSanityModules.js';
@@ -30,7 +29,7 @@ import { versionsDebug } from './versionsDebug.js';
30
29
  versionsDebug('packages:', packages);
31
30
  return packages.map((mod)=>{
32
31
  const current = mod.installed || semver.minVersion(mod.declared)?.toString() || '';
33
- const needsUpdate = mod.latest ? semverCompare(current, mod.latest) === -1 : false;
32
+ const needsUpdate = mod.latest ? semver.compare(current, mod.latest) === -1 : false;
34
33
  return {
35
34
  ...mod,
36
35
  needsUpdate