@sanity/cli 6.0.0-alpha.11 → 6.0.0-alpha.13

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 (135) hide show
  1. package/README.md +100 -112
  2. package/dist/actions/build/buildApp.js +15 -6
  3. package/dist/actions/build/buildApp.js.map +1 -1
  4. package/dist/actions/build/buildStudio.js +9 -3
  5. package/dist/actions/build/buildStudio.js.map +1 -1
  6. package/dist/actions/build/checkRequiredDependencies.js +6 -3
  7. package/dist/actions/build/checkRequiredDependencies.js.map +1 -1
  8. package/dist/actions/build/checkStudioDependencyVersions.js +6 -4
  9. package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
  10. package/dist/actions/build/types.js.map +1 -1
  11. package/dist/actions/deploy/deployApp.js +1 -2
  12. package/dist/actions/deploy/deployApp.js.map +1 -1
  13. package/dist/actions/deploy/deployStudio.js +1 -2
  14. package/dist/actions/deploy/deployStudio.js.map +1 -1
  15. package/dist/actions/deploy/types.js.map +1 -1
  16. package/dist/actions/init/checkNextJsReactCompatibility.js +1 -1
  17. package/dist/actions/init/checkNextJsReactCompatibility.js.map +1 -1
  18. package/dist/actions/init/createPackageManifest.js +13 -8
  19. package/dist/actions/init/createPackageManifest.js.map +1 -1
  20. package/dist/actions/init/remoteTemplate.js +1 -2
  21. package/dist/actions/init/remoteTemplate.js.map +1 -1
  22. package/dist/actions/manifest/SchemaIcon.js +6 -4
  23. package/dist/actions/manifest/SchemaIcon.js.map +1 -1
  24. package/dist/actions/manifest/blockTypeTransformer.js +67 -0
  25. package/dist/actions/manifest/blockTypeTransformer.js.map +1 -0
  26. package/dist/actions/manifest/debug.js +4 -0
  27. package/dist/actions/manifest/debug.js.map +1 -0
  28. package/dist/actions/manifest/extractManifest.js +26 -41
  29. package/dist/actions/manifest/extractManifest.js.map +1 -1
  30. package/dist/actions/manifest/extractManifest.worker.js +31 -0
  31. package/dist/actions/manifest/extractManifest.worker.js.map +1 -0
  32. package/dist/actions/manifest/extractWorkspaceManifest.js +31 -372
  33. package/dist/actions/manifest/extractWorkspaceManifest.js.map +1 -1
  34. package/dist/actions/manifest/iconResolver.js +30 -0
  35. package/dist/actions/manifest/iconResolver.js.map +1 -0
  36. package/dist/actions/manifest/referenceTransformer.js +51 -0
  37. package/dist/actions/manifest/referenceTransformer.js.map +1 -0
  38. package/dist/actions/manifest/schemaTypeHelpers.js +2 -2
  39. package/dist/actions/manifest/schemaTypeHelpers.js.map +1 -1
  40. package/dist/actions/manifest/schemaTypeTransformer.js +168 -0
  41. package/dist/actions/manifest/schemaTypeTransformer.js.map +1 -0
  42. package/dist/actions/manifest/transformerUtils.js +40 -0
  43. package/dist/actions/manifest/transformerUtils.js.map +1 -0
  44. package/dist/actions/manifest/types.js +5 -0
  45. package/dist/actions/manifest/types.js.map +1 -1
  46. package/dist/actions/manifest/validationTransformer.js +84 -0
  47. package/dist/actions/manifest/validationTransformer.js.map +1 -0
  48. package/dist/actions/manifest/writeWorkspaceFiles.js +30 -0
  49. package/dist/actions/manifest/writeWorkspaceFiles.js.map +1 -0
  50. package/dist/actions/schema/deleteSchemaAction.js +14 -30
  51. package/dist/actions/schema/deleteSchemaAction.js.map +1 -1
  52. package/dist/actions/schema/extractSchema.js +1 -8
  53. package/dist/actions/schema/extractSchema.js.map +1 -1
  54. package/dist/actions/schema/listSchemas.js +53 -56
  55. package/dist/actions/schema/listSchemas.js.map +1 -1
  56. package/dist/actions/schema/types.js +4 -0
  57. package/dist/actions/schema/types.js.map +1 -1
  58. package/dist/actions/schema/uniqueWorkspaces.worker.js +22 -0
  59. package/dist/actions/schema/uniqueWorkspaces.worker.js.map +1 -0
  60. package/dist/actions/schema/utils/SchemaExtractionError.js +10 -0
  61. package/dist/actions/schema/utils/SchemaExtractionError.js.map +1 -0
  62. package/dist/actions/schema/utils/manifestExtractor.js +3 -7
  63. package/dist/actions/schema/utils/manifestExtractor.js.map +1 -1
  64. package/dist/actions/schema/utils/schemaStoreValidation.js +1 -9
  65. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  66. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +1 -1
  67. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -1
  68. package/dist/actions/versions/filterSanityModules.js.map +1 -1
  69. package/dist/actions/versions/findSanityModulesVersions.js +1 -1
  70. package/dist/actions/versions/findSanityModulesVersions.js.map +1 -1
  71. package/dist/commands/build.js +2 -5
  72. package/dist/commands/build.js.map +1 -1
  73. package/dist/commands/deploy.js +1 -4
  74. package/dist/commands/deploy.js.map +1 -1
  75. package/dist/commands/manifest/extract.js +13 -9
  76. package/dist/commands/manifest/extract.js.map +1 -1
  77. package/dist/commands/schema/delete.js +15 -25
  78. package/dist/commands/schema/delete.js.map +1 -1
  79. package/dist/commands/schema/list.js +10 -31
  80. package/dist/commands/schema/list.js.map +1 -1
  81. package/dist/config/createCliConfig.js +1 -2
  82. package/dist/config/createCliConfig.js.map +1 -1
  83. package/dist/exports/_internal.d.ts +132 -0
  84. package/dist/exports/_internal.js +4 -0
  85. package/dist/exports/_internal.js.map +1 -0
  86. package/dist/exports/index.d.ts +51 -0
  87. package/dist/exports/index.js +6 -0
  88. package/dist/exports/index.js.map +1 -0
  89. package/dist/hooks/init/checkForUpdates.js +14 -0
  90. package/dist/hooks/init/checkForUpdates.js.map +1 -0
  91. package/dist/hooks/prerun/setupTelemetry.js +7 -2
  92. package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
  93. package/dist/services/schemas.js.map +1 -1
  94. package/dist/types.js +3 -0
  95. package/dist/types.js.map +1 -1
  96. package/dist/util/cliClient.js +5 -3
  97. package/dist/util/cliClient.js.map +1 -1
  98. package/dist/util/compareDependencyVersions.js +9 -5
  99. package/dist/util/compareDependencyVersions.js.map +1 -1
  100. package/dist/util/getCliVersion.js +1 -1
  101. package/dist/util/getCliVersion.js.map +1 -1
  102. package/dist/util/getLocalPackageVersion.js +1 -1
  103. package/dist/util/getLocalPackageVersion.js.map +1 -1
  104. package/dist/util/promiseRaceWithTimeout.js +28 -0
  105. package/dist/util/promiseRaceWithTimeout.js.map +1 -0
  106. package/dist/util/readModuleVersion.js +11 -5
  107. package/dist/util/readModuleVersion.js.map +1 -1
  108. package/dist/util/update/fetchLatestVersion.js +21 -0
  109. package/dist/util/update/fetchLatestVersion.js.map +1 -0
  110. package/dist/util/update/getUpdateCommand.js +15 -0
  111. package/dist/util/update/getUpdateCommand.js.map +1 -0
  112. package/dist/util/update/isInstalledUsingYarn.js +17 -0
  113. package/dist/util/update/isInstalledUsingYarn.js.map +1 -0
  114. package/dist/util/update/showNotificationUpdate.js +31 -0
  115. package/dist/util/update/showNotificationUpdate.js.map +1 -0
  116. package/dist/util/update/updateChecker.js +59 -0
  117. package/dist/util/update/updateChecker.js.map +1 -0
  118. package/dist/util/update/updateCheckerDebug.js +4 -0
  119. package/dist/util/update/updateCheckerDebug.js.map +1 -0
  120. package/oclif.config.js +1 -0
  121. package/oclif.manifest.json +299 -303
  122. package/package.json +26 -22
  123. package/dist/index.d.ts +0 -2326
  124. package/dist/index.js +0 -6
  125. package/dist/index.js.map +0 -1
  126. package/dist/typings/deepSortObject.d.js +0 -2
  127. package/dist/typings/deepSortObject.d.js.map +0 -1
  128. package/dist/util/importStudioConfig.js +0 -40
  129. package/dist/util/importStudioConfig.js.map +0 -1
  130. package/dist/util/readPackageJson.js +0 -44
  131. package/dist/util/readPackageJson.js.map +0 -1
  132. package/dist/util/readPackageManifest.js +0 -46
  133. package/dist/util/readPackageManifest.js.map +0 -1
  134. package/dist/util/uniqBy.js +0 -14
  135. package/dist/util/uniqBy.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/createPackageManifest.ts"],"sourcesContent":["import sortObject from 'deep-sort-object'\n\nimport {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\nexport function createPackageManifest(\n data: Omit<PackageJson, 'version'> & {gitRemote?: string} & {isAppTemplate?: boolean},\n): string {\n const {isAppTemplate} = data\n\n const dependencies = data.dependencies\n ? {dependencies: sortObject(data.dependencies) as Record<string, string>}\n : {}\n\n const devDependencies = data.devDependencies\n ? {devDependencies: sortObject(data.devDependencies) as Record<string, string>}\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 ? {}\n : {\n prettier: {\n bracketSpacing: false,\n printWidth: 100,\n semi: false,\n singleQuote: true,\n },\n }\n\n const pkg = {\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: Omit<PackageJson, 'version'> & {gitRemote?: string}) {\n const pkg: PackageJson = {\n author: data.author,\n description: data.description,\n devDependencies: {},\n license: data.license || 'UNLICENSED',\n name: data.name,\n version: '1.0.0',\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 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":["sortObject","manifestPropOrder","createPackageManifest","data","isAppTemplate","dependencies","devDependencies","prettierConfig","prettier","bracketSpacing","printWidth","semi","singleQuote","pkg","getCommonManifest","keywords","main","scripts","build","deploy","dev","start","serializeManifest","author","description","license","name","version","private","gitRemote","repository","type","url","src","props","Object","keys","ordered","prop","source","undefined","JSON","stringify"],"mappings":"AAAA,OAAOA,gBAAgB,mBAAkB;AAIzC,MAAMC,oBAAoB;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,OAAO,SAASC,sBACdC,IAAqF;IAErF,MAAM,EAACC,aAAa,EAAC,GAAGD;IAExB,MAAME,eAAeF,KAAKE,YAAY,GAClC;QAACA,cAAcL,WAAWG,KAAKE,YAAY;IAA2B,IACtE,CAAC;IAEL,MAAMC,kBAAkBH,KAAKG,eAAe,GACxC;QAACA,iBAAiBN,WAAWG,KAAKG,eAAe;IAA2B,IAC5E,CAAC;IAEL,2FAA2F;IAC3F,MAAMC,iBAAiBH,gBACnB,CAAC,IACD;QACEI,UAAU;YACRC,gBAAgB;YAChBC,YAAY;YACZC,MAAM;YACNC,aAAa;QACf;IACF;IAEJ,MAAMC,MAAM;QACV,GAAGC,kBAAkBX,KAAK;QAE1BY,UAAU;YAAC;SAAS;QACpBC,MAAM;QACNC,SAASd,KAAKc,OAAO,IAAI;YACvBC,OAAO;YACPC,QAAQ;YACR,kBAAkB;YAClBC,KAAK;YACLC,OAAO;QACT;QAEA,GAAGhB,YAAY;QACf,GAAGC,eAAe;QAClB,GAAGC,cAAc;IACnB;IAEA,OAAOe,kBAAkBT;AAC3B;AAEA,SAASC,kBAAkBX,IAAyD;IAClF,MAAMU,MAAmB;QACvBU,QAAQpB,KAAKoB,MAAM;QACnBC,aAAarB,KAAKqB,WAAW;QAC7BlB,iBAAiB,CAAC;QAClBmB,SAAStB,KAAKsB,OAAO,IAAI;QACzBC,MAAMvB,KAAKuB,IAAI;QACfC,SAAS;IACX;IAEA,IAAId,IAAIY,OAAO,KAAK,cAAc;QAChCZ,IAAIe,OAAO,GAAG;IAChB;IAEA,IAAIzB,KAAK0B,SAAS,EAAE;QAClBhB,IAAIiB,UAAU,GAAG;YACfC,MAAM;YACNC,KAAK7B,KAAK0B,SAAS;QACrB;IACF;IAEA,OAAOhB;AACT;AAEA,SAASS,kBAAkBW,GAA6B;IACtD,MAAMC,QAAQ;WAAIjC;WAAsBkC,OAAOC,IAAI,CAACH;KAAK;IACzD,MAAMI,UAAmC,CAAC;IAC1C,KAAK,MAAMC,QAAQJ,MAAO;QACxB,MAAMK,SAASN;QACf,IAAIM,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 '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"}
@@ -2,10 +2,9 @@ import { access, readFile, writeFile } from 'node:fs/promises';
2
2
  import { join, posix, sep } from 'node:path';
3
3
  import { Readable } from 'node:stream';
4
4
  import { pipeline } from 'node:stream/promises';
5
- import { subdebug } from '@sanity/cli-core';
5
+ import { readPackageJson, subdebug } from '@sanity/cli-core';
6
6
  import { ENV_TEMPLATE_FILES, REQUIRED_ENV_VAR } from '@sanity/template-validator';
7
7
  import { x } from 'tar';
8
- import { readPackageJson } from '../../util/readPackageJson.js';
9
8
  const debug = subdebug('remoteTemplate');
10
9
  const DISALLOWED_PATHS = [
11
10
  // Prevent security risks from unknown GitHub Actions
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/remoteTemplate.ts"],"sourcesContent":["import {access, readFile, writeFile} from 'node:fs/promises'\nimport {join, posix, sep} from 'node:path'\nimport {Readable} from 'node:stream'\nimport {pipeline} from 'node:stream/promises'\n\nimport {subdebug} from '@sanity/cli-core'\nimport {ENV_TEMPLATE_FILES, REQUIRED_ENV_VAR} from '@sanity/template-validator'\nimport {x} from 'tar'\n\nimport {readPackageJson} from '../../util/readPackageJson.js'\n\nconst debug = subdebug('remoteTemplate')\n\nconst DISALLOWED_PATHS = [\n // Prevent security risks from unknown GitHub Actions\n '/.github/',\n]\n\nconst ENV_VAR = {\n ...REQUIRED_ENV_VAR,\n READ_TOKEN: 'SANITY_API_READ_TOKEN',\n WRITE_TOKEN: 'SANITY_API_WRITE_TOKEN',\n} as const\n\ntype EnvData = {\n dataset: string\n projectId: string\n readToken?: string\n writeToken?: string\n}\n\ntype GitHubUrlString =\n | `https://github.com/${string}/${string}`\n | `https://www.github.com/${string}/${string}`\n\nexport type RepoInfo = {\n branch: string\n filePath: string\n name: string\n username: string\n}\n\nexport function getGitHubRawContentUrl(repoInfo: RepoInfo): string {\n const {branch, filePath, name, username} = repoInfo\n return `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`\n}\n\nfunction isGitHubRepoShorthand(value: string): boolean {\n if (URL.canParse(value)) {\n return false\n }\n // This supports :owner/:repo and :owner/:repo/nested/path, e.g.\n // sanity-io/sanity\n // sanity-io/sanity/templates/next-js\n // sanity-io/templates/live-content-api\n // sanity-io/sanity/packages/@sanity/cli/test/test-template\n return /^[\\w-]+\\/[\\w-.]+(\\/[@\\w-.]+)*$/.test(value)\n}\n\nfunction isGitHubRepoUrl(value: string | URL): value is GitHubUrlString | URL {\n if (!URL.canParse(value)) {\n return false\n }\n const url = new URL(value)\n const pathSegments = url.pathname.slice(1).split('/')\n\n return (\n url.protocol === 'https:' &&\n url.hostname === 'github.com' &&\n // The pathname must have at least 2 segments. If it has more than 2, the\n // third must be \"tree\" and it must have at least 4 segments.\n // https://github.com/:owner/:repo\n // https://github.com/:owner/:repo/tree/:ref\n pathSegments.length >= 2 &&\n (pathSegments.length > 2 ? pathSegments[2] === 'tree' && pathSegments.length >= 4 : true)\n )\n}\n\nasync function downloadTarStream(url: string, bearerToken?: string): Promise<Readable> {\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n\n const res = await fetch(url, {headers})\n\n if (!res.body) {\n throw new Error(`Failed to download: ${url}`)\n }\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n return Readable.fromWeb(res.body as Parameters<typeof Readable.fromWeb>[0])\n}\n\nexport function checkIsRemoteTemplate(templateName?: string): boolean {\n return templateName?.includes('/') ?? false\n}\n\nexport async function getGitHubRepoInfo(value: string, bearerToken?: string): Promise<RepoInfo> {\n let username = ''\n let name = ''\n let branch = ''\n let filePath = ''\n\n if (isGitHubRepoShorthand(value)) {\n const parts = value.split('/')\n username = parts[0]\n name = parts[1]\n // If there are more segments after owner/repo, they form the file path\n if (parts.length > 2) {\n filePath = parts.slice(2).join('/')\n }\n }\n\n if (isGitHubRepoUrl(value)) {\n const url = new URL(value)\n const pathSegments = url.pathname.slice(1).split('/')\n username = pathSegments[0]\n name = pathSegments[1]\n\n // If we have a \"tree\" segment, everything after branch is the file path\n if (pathSegments[2] === 'tree') {\n branch = pathSegments[3]\n if (pathSegments.length > 4) {\n filePath = pathSegments.slice(4).join('/')\n }\n }\n }\n\n if (!username || !name) {\n throw new Error('Invalid GitHub repository format')\n }\n\n const tokenMessage =\n 'GitHub repository not found. For private repositories, use --template-token to provide an access token.\\n\\n' +\n 'You can generate a new token at https://github.com/settings/personal-access-tokens/new\\n' +\n 'Set the token to \"read-only\" with repository access and a short expiry (e.g. 7 days) for security.'\n\n try {\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n\n const infoResponse = await fetch(`https://api.github.com/repos/${username}/${name}`, {\n headers,\n })\n\n if (infoResponse.status !== 200) {\n if (infoResponse.status === 404) {\n throw new Error(tokenMessage)\n }\n throw new Error('GitHub repository not found')\n }\n\n const info = await infoResponse.json()\n\n return {\n branch: branch || info.default_branch,\n filePath,\n name,\n username,\n }\n } catch {\n throw new Error(tokenMessage)\n }\n}\n\nexport async function downloadAndExtractRepo(\n root: string,\n {branch, filePath, name, username}: RepoInfo,\n bearerToken?: string,\n): Promise<void> {\n let rootPath: string | null = null\n await pipeline(\n await downloadTarStream(\n `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`,\n bearerToken,\n ),\n x({\n cwd: root,\n filter: (p: string) => {\n const posixPath = p.split(sep).join(posix.sep)\n if (rootPath === null) {\n const pathSegments = posixPath.split(posix.sep)\n rootPath = pathSegments.length > 0 ? pathSegments[0] : null\n }\n for (const disallowedPath of DISALLOWED_PATHS) {\n if (posixPath.includes(disallowedPath)) return false\n }\n return posixPath.startsWith(`${rootPath}${filePath ? `/${filePath}/` : '/'}`)\n },\n strip: filePath ? filePath.split('/').length + 1 : 1,\n }),\n )\n}\n\nexport async function checkIfNeedsApiToken(root: string, type: 'read' | 'write'): Promise<boolean> {\n try {\n const templatePath = await Promise.any(\n ENV_TEMPLATE_FILES.map(async (file) => {\n await access(join(root, file))\n return file\n }),\n )\n const templateContent = await readFile(join(root, templatePath), 'utf8')\n return templateContent.includes(type === 'read' ? ENV_VAR.READ_TOKEN : ENV_VAR.WRITE_TOKEN)\n } catch {\n return false\n }\n}\n\nexport async function applyEnvVariables(\n root: string,\n envData: EnvData,\n targetName = '.env',\n): Promise<void> {\n const templatePath = await Promise.any(\n ENV_TEMPLATE_FILES.map(async (file) => {\n await access(join(root, file))\n return file\n }),\n ).catch(() => {})\n\n if (!templatePath) {\n return // No template .env file found, skip\n }\n\n try {\n const templateContent = await readFile(join(root, templatePath), 'utf8')\n const {dataset, projectId, readToken = '', writeToken = ''} = envData\n\n const findAndReplaceVariable = (\n content: string,\n varRegex: RegExp | string,\n value: string,\n useQuotes: boolean,\n ) => {\n const varPattern = typeof varRegex === 'string' ? varRegex : varRegex.source\n const pattern = new RegExp(`.*${varPattern}=.*$`, 'gm')\n const matches = content.matchAll(pattern)\n\n let result = content\n for (const match of matches) {\n if (!match[0]) continue\n const varName = match[0].split('=')[0].trim()\n result = result.replaceAll(\n new RegExp(`${varName}=.*$`, 'gm'),\n `${varName}=${useQuotes ? `\"${value}\"` : value}`,\n )\n }\n\n return result\n }\n\n let envContent = templateContent\n const vars = [\n {pattern: ENV_VAR.PROJECT_ID, value: projectId},\n {pattern: ENV_VAR.DATASET, value: dataset},\n {pattern: ENV_VAR.READ_TOKEN, value: readToken},\n {pattern: ENV_VAR.WRITE_TOKEN, value: writeToken},\n ]\n const useQuotes = templateContent.includes('=\"')\n\n for (const {pattern, value} of vars) {\n envContent = findAndReplaceVariable(envContent, pattern, value, useQuotes)\n }\n\n await writeFile(join(root, targetName), envContent)\n } catch (err) {\n debug(`Error setting environment variables: ${err}`)\n throw new Error(\n 'Failed to set environment variables. This could be due to file permissions or the .env file format. See https://www.sanity.io/docs/environment-variables for details on environment variable setup.',\n )\n }\n}\n\nexport async function tryApplyPackageName(root: string, name: string): Promise<void> {\n try {\n const pkg = await readPackageJson(join(root, 'package.json'))\n pkg.name = name\n\n await writeFile(join(root, 'package.json'), JSON.stringify(pkg, null, 2))\n } catch {\n // noop\n }\n}\n"],"names":["access","readFile","writeFile","join","posix","sep","Readable","pipeline","subdebug","ENV_TEMPLATE_FILES","REQUIRED_ENV_VAR","x","readPackageJson","debug","DISALLOWED_PATHS","ENV_VAR","READ_TOKEN","WRITE_TOKEN","getGitHubRawContentUrl","repoInfo","branch","filePath","name","username","isGitHubRepoShorthand","value","URL","canParse","test","isGitHubRepoUrl","url","pathSegments","pathname","slice","split","protocol","hostname","length","downloadTarStream","bearerToken","headers","Authorization","res","fetch","body","Error","fromWeb","checkIsRemoteTemplate","templateName","includes","getGitHubRepoInfo","parts","tokenMessage","infoResponse","status","info","json","default_branch","downloadAndExtractRepo","root","rootPath","cwd","filter","p","posixPath","disallowedPath","startsWith","strip","checkIfNeedsApiToken","type","templatePath","Promise","any","map","file","templateContent","applyEnvVariables","envData","targetName","catch","dataset","projectId","readToken","writeToken","findAndReplaceVariable","content","varRegex","useQuotes","varPattern","source","pattern","RegExp","matches","matchAll","result","match","varName","trim","replaceAll","envContent","vars","PROJECT_ID","DATASET","err","tryApplyPackageName","pkg","JSON","stringify"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/init/remoteTemplate.ts"],"sourcesContent":["import {access, readFile, writeFile} from 'node:fs/promises'\nimport {join, posix, sep} from 'node:path'\nimport {Readable} from 'node:stream'\nimport {pipeline} from 'node:stream/promises'\n\nimport {readPackageJson, subdebug} from '@sanity/cli-core'\nimport {ENV_TEMPLATE_FILES, REQUIRED_ENV_VAR} from '@sanity/template-validator'\nimport {x} from 'tar'\n\nconst debug = subdebug('remoteTemplate')\n\nconst DISALLOWED_PATHS = [\n // Prevent security risks from unknown GitHub Actions\n '/.github/',\n]\n\nconst ENV_VAR = {\n ...REQUIRED_ENV_VAR,\n READ_TOKEN: 'SANITY_API_READ_TOKEN',\n WRITE_TOKEN: 'SANITY_API_WRITE_TOKEN',\n} as const\n\ntype EnvData = {\n dataset: string\n projectId: string\n readToken?: string\n writeToken?: string\n}\n\ntype GitHubUrlString =\n | `https://github.com/${string}/${string}`\n | `https://www.github.com/${string}/${string}`\n\nexport type RepoInfo = {\n branch: string\n filePath: string\n name: string\n username: string\n}\n\nexport function getGitHubRawContentUrl(repoInfo: RepoInfo): string {\n const {branch, filePath, name, username} = repoInfo\n return `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`\n}\n\nfunction isGitHubRepoShorthand(value: string): boolean {\n if (URL.canParse(value)) {\n return false\n }\n // This supports :owner/:repo and :owner/:repo/nested/path, e.g.\n // sanity-io/sanity\n // sanity-io/sanity/templates/next-js\n // sanity-io/templates/live-content-api\n // sanity-io/sanity/packages/@sanity/cli/test/test-template\n return /^[\\w-]+\\/[\\w-.]+(\\/[@\\w-.]+)*$/.test(value)\n}\n\nfunction isGitHubRepoUrl(value: string | URL): value is GitHubUrlString | URL {\n if (!URL.canParse(value)) {\n return false\n }\n const url = new URL(value)\n const pathSegments = url.pathname.slice(1).split('/')\n\n return (\n url.protocol === 'https:' &&\n url.hostname === 'github.com' &&\n // The pathname must have at least 2 segments. If it has more than 2, the\n // third must be \"tree\" and it must have at least 4 segments.\n // https://github.com/:owner/:repo\n // https://github.com/:owner/:repo/tree/:ref\n pathSegments.length >= 2 &&\n (pathSegments.length > 2 ? pathSegments[2] === 'tree' && pathSegments.length >= 4 : true)\n )\n}\n\nasync function downloadTarStream(url: string, bearerToken?: string): Promise<Readable> {\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n\n const res = await fetch(url, {headers})\n\n if (!res.body) {\n throw new Error(`Failed to download: ${url}`)\n }\n\n // eslint-disable-next-line n/no-unsupported-features/node-builtins\n return Readable.fromWeb(res.body as Parameters<typeof Readable.fromWeb>[0])\n}\n\nexport function checkIsRemoteTemplate(templateName?: string): boolean {\n return templateName?.includes('/') ?? false\n}\n\nexport async function getGitHubRepoInfo(value: string, bearerToken?: string): Promise<RepoInfo> {\n let username = ''\n let name = ''\n let branch = ''\n let filePath = ''\n\n if (isGitHubRepoShorthand(value)) {\n const parts = value.split('/')\n username = parts[0]\n name = parts[1]\n // If there are more segments after owner/repo, they form the file path\n if (parts.length > 2) {\n filePath = parts.slice(2).join('/')\n }\n }\n\n if (isGitHubRepoUrl(value)) {\n const url = new URL(value)\n const pathSegments = url.pathname.slice(1).split('/')\n username = pathSegments[0]\n name = pathSegments[1]\n\n // If we have a \"tree\" segment, everything after branch is the file path\n if (pathSegments[2] === 'tree') {\n branch = pathSegments[3]\n if (pathSegments.length > 4) {\n filePath = pathSegments.slice(4).join('/')\n }\n }\n }\n\n if (!username || !name) {\n throw new Error('Invalid GitHub repository format')\n }\n\n const tokenMessage =\n 'GitHub repository not found. For private repositories, use --template-token to provide an access token.\\n\\n' +\n 'You can generate a new token at https://github.com/settings/personal-access-tokens/new\\n' +\n 'Set the token to \"read-only\" with repository access and a short expiry (e.g. 7 days) for security.'\n\n try {\n const headers: Record<string, string> = {}\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`\n }\n\n const infoResponse = await fetch(`https://api.github.com/repos/${username}/${name}`, {\n headers,\n })\n\n if (infoResponse.status !== 200) {\n if (infoResponse.status === 404) {\n throw new Error(tokenMessage)\n }\n throw new Error('GitHub repository not found')\n }\n\n const info = await infoResponse.json()\n\n return {\n branch: branch || info.default_branch,\n filePath,\n name,\n username,\n }\n } catch {\n throw new Error(tokenMessage)\n }\n}\n\nexport async function downloadAndExtractRepo(\n root: string,\n {branch, filePath, name, username}: RepoInfo,\n bearerToken?: string,\n): Promise<void> {\n let rootPath: string | null = null\n await pipeline(\n await downloadTarStream(\n `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`,\n bearerToken,\n ),\n x({\n cwd: root,\n filter: (p: string) => {\n const posixPath = p.split(sep).join(posix.sep)\n if (rootPath === null) {\n const pathSegments = posixPath.split(posix.sep)\n rootPath = pathSegments.length > 0 ? pathSegments[0] : null\n }\n for (const disallowedPath of DISALLOWED_PATHS) {\n if (posixPath.includes(disallowedPath)) return false\n }\n return posixPath.startsWith(`${rootPath}${filePath ? `/${filePath}/` : '/'}`)\n },\n strip: filePath ? filePath.split('/').length + 1 : 1,\n }),\n )\n}\n\nexport async function checkIfNeedsApiToken(root: string, type: 'read' | 'write'): Promise<boolean> {\n try {\n const templatePath = await Promise.any(\n ENV_TEMPLATE_FILES.map(async (file) => {\n await access(join(root, file))\n return file\n }),\n )\n const templateContent = await readFile(join(root, templatePath), 'utf8')\n return templateContent.includes(type === 'read' ? ENV_VAR.READ_TOKEN : ENV_VAR.WRITE_TOKEN)\n } catch {\n return false\n }\n}\n\nexport async function applyEnvVariables(\n root: string,\n envData: EnvData,\n targetName = '.env',\n): Promise<void> {\n const templatePath = await Promise.any(\n ENV_TEMPLATE_FILES.map(async (file) => {\n await access(join(root, file))\n return file\n }),\n ).catch(() => {})\n\n if (!templatePath) {\n return // No template .env file found, skip\n }\n\n try {\n const templateContent = await readFile(join(root, templatePath), 'utf8')\n const {dataset, projectId, readToken = '', writeToken = ''} = envData\n\n const findAndReplaceVariable = (\n content: string,\n varRegex: RegExp | string,\n value: string,\n useQuotes: boolean,\n ) => {\n const varPattern = typeof varRegex === 'string' ? varRegex : varRegex.source\n const pattern = new RegExp(`.*${varPattern}=.*$`, 'gm')\n const matches = content.matchAll(pattern)\n\n let result = content\n for (const match of matches) {\n if (!match[0]) continue\n const varName = match[0].split('=')[0].trim()\n result = result.replaceAll(\n new RegExp(`${varName}=.*$`, 'gm'),\n `${varName}=${useQuotes ? `\"${value}\"` : value}`,\n )\n }\n\n return result\n }\n\n let envContent = templateContent\n const vars = [\n {pattern: ENV_VAR.PROJECT_ID, value: projectId},\n {pattern: ENV_VAR.DATASET, value: dataset},\n {pattern: ENV_VAR.READ_TOKEN, value: readToken},\n {pattern: ENV_VAR.WRITE_TOKEN, value: writeToken},\n ]\n const useQuotes = templateContent.includes('=\"')\n\n for (const {pattern, value} of vars) {\n envContent = findAndReplaceVariable(envContent, pattern, value, useQuotes)\n }\n\n await writeFile(join(root, targetName), envContent)\n } catch (err) {\n debug(`Error setting environment variables: ${err}`)\n throw new Error(\n 'Failed to set environment variables. This could be due to file permissions or the .env file format. See https://www.sanity.io/docs/environment-variables for details on environment variable setup.',\n )\n }\n}\n\nexport async function tryApplyPackageName(root: string, name: string): Promise<void> {\n try {\n const pkg = await readPackageJson(join(root, 'package.json'))\n pkg.name = name\n\n await writeFile(join(root, 'package.json'), JSON.stringify(pkg, null, 2))\n } catch {\n // noop\n }\n}\n"],"names":["access","readFile","writeFile","join","posix","sep","Readable","pipeline","readPackageJson","subdebug","ENV_TEMPLATE_FILES","REQUIRED_ENV_VAR","x","debug","DISALLOWED_PATHS","ENV_VAR","READ_TOKEN","WRITE_TOKEN","getGitHubRawContentUrl","repoInfo","branch","filePath","name","username","isGitHubRepoShorthand","value","URL","canParse","test","isGitHubRepoUrl","url","pathSegments","pathname","slice","split","protocol","hostname","length","downloadTarStream","bearerToken","headers","Authorization","res","fetch","body","Error","fromWeb","checkIsRemoteTemplate","templateName","includes","getGitHubRepoInfo","parts","tokenMessage","infoResponse","status","info","json","default_branch","downloadAndExtractRepo","root","rootPath","cwd","filter","p","posixPath","disallowedPath","startsWith","strip","checkIfNeedsApiToken","type","templatePath","Promise","any","map","file","templateContent","applyEnvVariables","envData","targetName","catch","dataset","projectId","readToken","writeToken","findAndReplaceVariable","content","varRegex","useQuotes","varPattern","source","pattern","RegExp","matches","matchAll","result","match","varName","trim","replaceAll","envContent","vars","PROJECT_ID","DATASET","err","tryApplyPackageName","pkg","JSON","stringify"],"mappings":"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"}
@@ -1,19 +1,21 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { resolveLocalPackage } from '@sanity/cli-core';
2
3
  import { ThemeProvider } from '@sanity/ui';
3
4
  import { buildTheme } from '@sanity/ui/theme';
4
5
  import { isValidElement } from 'react';
5
6
  import { isValidElementType } from 'react-is';
6
- import { createDefaultIcon } from 'sanity';
7
7
  const theme = buildTheme();
8
- const SchemaIcon = ({ icon, subtitle, title })=>{
8
+ const SchemaIcon = async ({ icon, subtitle, title, workDir })=>{
9
+ const normalizedIcon = await normalizeIcon(icon, title, subtitle, workDir);
9
10
  return /*#__PURE__*/ _jsx(ThemeProvider, {
10
11
  theme: theme,
11
- children: normalizeIcon(icon, title, subtitle)
12
+ children: normalizedIcon
12
13
  });
13
14
  };
14
- function normalizeIcon(Icon, title, subtitle = '') {
15
+ async function normalizeIcon(Icon, title, subtitle = '', workDir) {
15
16
  if (isValidElementType(Icon)) return /*#__PURE__*/ _jsx(Icon, {});
16
17
  if (/*#__PURE__*/ isValidElement(Icon)) return Icon;
18
+ const { createDefaultIcon } = await resolveLocalPackage('sanity', workDir);
17
19
  return createDefaultIcon(title, subtitle);
18
20
  }
19
21
  export { SchemaIcon };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/manifest/SchemaIcon.tsx"],"sourcesContent":["import {ThemeProvider} from '@sanity/ui'\nimport {buildTheme} from '@sanity/ui/theme'\nimport {type ComponentType, isValidElement, type ReactNode} from 'react'\nimport {isValidElementType} from 'react-is'\nimport {createDefaultIcon} from 'sanity'\n\nconst theme = buildTheme()\n\ninterface SchemaIconProps {\n title: string\n\n icon?: ComponentType | ReactNode\n subtitle?: string\n}\n\nconst SchemaIcon = ({icon, subtitle, title}: SchemaIconProps): React.JSX.Element => {\n return <ThemeProvider theme={theme}>{normalizeIcon(icon, title, subtitle)}</ThemeProvider>\n}\n\nfunction normalizeIcon(\n Icon: ComponentType | ReactNode | undefined,\n title: string,\n subtitle = '',\n): React.JSX.Element {\n if (isValidElementType(Icon)) return <Icon />\n if (isValidElement(Icon)) return Icon\n return createDefaultIcon(title, subtitle)\n}\n\nexport {SchemaIcon}\nexport type {SchemaIconProps}\n"],"names":["ThemeProvider","buildTheme","isValidElement","isValidElementType","createDefaultIcon","theme","SchemaIcon","icon","subtitle","title","normalizeIcon","Icon"],"mappings":";AAAA,SAAQA,aAAa,QAAO,aAAY;AACxC,SAAQC,UAAU,QAAO,mBAAkB;AAC3C,SAA4BC,cAAc,QAAuB,QAAO;AACxE,SAAQC,kBAAkB,QAAO,WAAU;AAC3C,SAAQC,iBAAiB,QAAO,SAAQ;AAExC,MAAMC,QAAQJ;AASd,MAAMK,aAAa,CAAC,EAACC,IAAI,EAAEC,QAAQ,EAAEC,KAAK,EAAkB;IAC1D,qBAAO,KAACT;QAAcK,OAAOA;kBAAQK,cAAcH,MAAME,OAAOD;;AAClE;AAEA,SAASE,cACPC,IAA2C,EAC3CF,KAAa,EACbD,WAAW,EAAE;IAEb,IAAIL,mBAAmBQ,OAAO,qBAAO,KAACA;IACtC,kBAAIT,eAAeS,OAAO,OAAOA;IACjC,OAAOP,kBAAkBK,OAAOD;AAClC;AAEA,SAAQF,UAAU,GAAC"}
1
+ {"version":3,"sources":["../../../src/actions/manifest/SchemaIcon.tsx"],"sourcesContent":["import {resolveLocalPackage} from '@sanity/cli-core'\nimport {ThemeProvider} from '@sanity/ui'\nimport {buildTheme} from '@sanity/ui/theme'\nimport {type ComponentType, isValidElement, type ReactNode} from 'react'\nimport {isValidElementType} from 'react-is'\n\nconst theme = buildTheme()\n\ninterface SchemaIconProps {\n title: string\n workDir: string\n\n icon?: ComponentType | ReactNode\n subtitle?: string\n}\n\nconst SchemaIcon = async ({\n icon,\n subtitle,\n title,\n workDir,\n}: SchemaIconProps): Promise<React.JSX.Element> => {\n const normalizedIcon = await normalizeIcon(icon, title, subtitle, workDir)\n\n return <ThemeProvider theme={theme}>{normalizedIcon}</ThemeProvider>\n}\n\nasync function normalizeIcon(\n Icon: ComponentType | ReactNode | undefined,\n title: string,\n subtitle = '',\n workDir: string,\n): Promise<React.JSX.Element> {\n if (isValidElementType(Icon)) return <Icon />\n if (isValidElement(Icon)) return Icon\n\n const {createDefaultIcon} = await resolveLocalPackage<typeof import('sanity')>('sanity', workDir)\n\n return createDefaultIcon(title, subtitle)\n}\n\nexport {SchemaIcon}\nexport type {SchemaIconProps}\n"],"names":["resolveLocalPackage","ThemeProvider","buildTheme","isValidElement","isValidElementType","theme","SchemaIcon","icon","subtitle","title","workDir","normalizedIcon","normalizeIcon","Icon","createDefaultIcon"],"mappings":";AAAA,SAAQA,mBAAmB,QAAO,mBAAkB;AACpD,SAAQC,aAAa,QAAO,aAAY;AACxC,SAAQC,UAAU,QAAO,mBAAkB;AAC3C,SAA4BC,cAAc,QAAuB,QAAO;AACxE,SAAQC,kBAAkB,QAAO,WAAU;AAE3C,MAAMC,QAAQH;AAUd,MAAMI,aAAa,OAAO,EACxBC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACLC,OAAO,EACS;IAChB,MAAMC,iBAAiB,MAAMC,cAAcL,MAAME,OAAOD,UAAUE;IAElE,qBAAO,KAACT;QAAcI,OAAOA;kBAAQM;;AACvC;AAEA,eAAeC,cACbC,IAA2C,EAC3CJ,KAAa,EACbD,WAAW,EAAE,EACbE,OAAe;IAEf,IAAIN,mBAAmBS,OAAO,qBAAO,KAACA;IACtC,kBAAIV,eAAeU,OAAO,OAAOA;IAEjC,MAAM,EAACC,iBAAiB,EAAC,GAAG,MAAMd,oBAA6C,UAAUU;IAEzF,OAAOI,kBAAkBL,OAAOD;AAClC;AAEA,SAAQF,UAAU,GAAC"}
@@ -0,0 +1,67 @@
1
+ import { isRecord, isString, isType } from './schemaTypeHelpers.js';
2
+ import { ensureString } from './transformerUtils.js';
3
+ /**
4
+ * Transforms a block schema type (Portable Text) to its manifest representation
5
+ */ export function transformBlockType(blockType, context, transformType) {
6
+ if (blockType.jsonType !== 'object' || !isType(blockType, 'block')) {
7
+ return {};
8
+ }
9
+ const childrenField = blockType.fields?.find((field)=>field.name === 'children');
10
+ if (!childrenField) {
11
+ return {};
12
+ }
13
+ const ofType = childrenField.type.of;
14
+ if (!ofType) {
15
+ return {};
16
+ }
17
+ const spanType = ofType.find((memberType)=>memberType.name === 'span');
18
+ if (!spanType) {
19
+ return {};
20
+ }
21
+ const inlineObjectTypes = ofType.filter((memberType)=>memberType.name !== 'span') || [];
22
+ return {
23
+ lists: resolveEnabledListItems(blockType),
24
+ marks: {
25
+ annotations: spanType.annotations.map((t)=>transformType(t, context)),
26
+ decorators: resolveEnabledDecorators(spanType)
27
+ },
28
+ of: inlineObjectTypes.map((t)=>transformType(t, context)),
29
+ styles: resolveEnabledStyles(blockType)
30
+ };
31
+ }
32
+ /**
33
+ * Resolves enabled styles from a block type
34
+ */ function resolveEnabledStyles(blockType) {
35
+ const styleField = blockType.fields?.find((btField)=>btField.name === 'style');
36
+ return resolveTitleValueArray(styleField?.type?.options?.list);
37
+ }
38
+ /**
39
+ * Resolves enabled decorators from a span type
40
+ */ function resolveEnabledDecorators(spanType) {
41
+ return 'decorators' in spanType ? resolveTitleValueArray(spanType.decorators) : undefined;
42
+ }
43
+ /**
44
+ * Resolves enabled list items from a block type
45
+ */ function resolveEnabledListItems(blockType) {
46
+ const listField = blockType.fields?.find((btField)=>btField.name === 'listItem');
47
+ return resolveTitleValueArray(listField?.type?.options?.list);
48
+ }
49
+ /**
50
+ * Resolves an array of title/value objects
51
+ */ function resolveTitleValueArray(possibleArray) {
52
+ if (!possibleArray || !Array.isArray(possibleArray)) {
53
+ return undefined;
54
+ }
55
+ const titledValues = possibleArray.filter((d)=>isRecord(d) && !!d.value && isString(d.value)).map((item)=>{
56
+ return {
57
+ value: item.value,
58
+ ...ensureString('title', item.title)
59
+ };
60
+ });
61
+ if (!titledValues?.length) {
62
+ return undefined;
63
+ }
64
+ return titledValues;
65
+ }
66
+
67
+ //# sourceMappingURL=blockTypeTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/manifest/blockTypeTransformer.ts"],"sourcesContent":["import {\n type ArraySchemaType,\n type ObjectSchemaType,\n type SchemaType,\n type SpanSchemaType,\n} from '@sanity/types'\n\nimport {isRecord, isString, isType} from './schemaTypeHelpers.js'\nimport {type Context, ensureString} from './transformerUtils.js'\nimport {type ManifestSchemaType, type ManifestTitledValue} from './types.js'\n\ntype TransformTypeFn = (type: SchemaType, context: Context) => ManifestSchemaType\n\n/**\n * Transforms a block schema type (Portable Text) to its manifest representation\n */\nexport function transformBlockType(\n blockType: SchemaType,\n context: Context,\n transformType: TransformTypeFn,\n): Pick<ManifestSchemaType, 'lists' | 'marks' | 'of' | 'styles'> | Record<string, never> {\n if (blockType.jsonType !== 'object' || !isType(blockType, 'block')) {\n return {}\n }\n\n const childrenField = blockType.fields?.find((field) => field.name === 'children') as\n | {type: ArraySchemaType}\n | undefined\n\n if (!childrenField) {\n return {}\n }\n const ofType = childrenField.type.of\n if (!ofType) {\n return {}\n }\n const spanType = ofType.find((memberType) => memberType.name === 'span') as\n | ObjectSchemaType\n | undefined\n if (!spanType) {\n return {}\n }\n const inlineObjectTypes = (ofType.filter((memberType) => memberType.name !== 'span') ||\n []) as ObjectSchemaType[]\n\n return {\n lists: resolveEnabledListItems(blockType),\n marks: {\n annotations: (spanType as SpanSchemaType).annotations.map((t) => transformType(t, context)),\n decorators: resolveEnabledDecorators(spanType),\n },\n of: inlineObjectTypes.map((t) => transformType(t, context)),\n styles: resolveEnabledStyles(blockType),\n }\n}\n\n/**\n * Resolves enabled styles from a block type\n */\nfunction resolveEnabledStyles(blockType: ObjectSchemaType): ManifestTitledValue[] | undefined {\n const styleField = blockType.fields?.find((btField) => btField.name === 'style')\n return resolveTitleValueArray(styleField?.type?.options?.list)\n}\n\n/**\n * Resolves enabled decorators from a span type\n */\nfunction resolveEnabledDecorators(spanType: ObjectSchemaType): ManifestTitledValue[] | undefined {\n return 'decorators' in spanType ? resolveTitleValueArray(spanType.decorators) : undefined\n}\n\n/**\n * Resolves enabled list items from a block type\n */\nfunction resolveEnabledListItems(blockType: ObjectSchemaType): ManifestTitledValue[] | undefined {\n const listField = blockType.fields?.find((btField) => btField.name === 'listItem')\n return resolveTitleValueArray(listField?.type?.options?.list)\n}\n\n/**\n * Resolves an array of title/value objects\n */\nfunction resolveTitleValueArray(possibleArray: unknown): ManifestTitledValue[] | undefined {\n if (!possibleArray || !Array.isArray(possibleArray)) {\n return undefined\n }\n const titledValues = possibleArray\n .filter(\n (d): d is {title?: string; value: string} => isRecord(d) && !!d.value && isString(d.value),\n )\n .map((item) => {\n return {\n value: item.value,\n ...ensureString('title', item.title),\n } satisfies ManifestTitledValue\n })\n if (!titledValues?.length) {\n return undefined\n }\n\n return titledValues\n}\n"],"names":["isRecord","isString","isType","ensureString","transformBlockType","blockType","context","transformType","jsonType","childrenField","fields","find","field","name","ofType","type","of","spanType","memberType","inlineObjectTypes","filter","lists","resolveEnabledListItems","marks","annotations","map","t","decorators","resolveEnabledDecorators","styles","resolveEnabledStyles","styleField","btField","resolveTitleValueArray","options","list","undefined","listField","possibleArray","Array","isArray","titledValues","d","value","item","title","length"],"mappings":"AAOA,SAAQA,QAAQ,EAAEC,QAAQ,EAAEC,MAAM,QAAO,yBAAwB;AACjE,SAAsBC,YAAY,QAAO,wBAAuB;AAKhE;;CAEC,GACD,OAAO,SAASC,mBACdC,SAAqB,EACrBC,OAAgB,EAChBC,aAA8B;IAE9B,IAAIF,UAAUG,QAAQ,KAAK,YAAY,CAACN,OAAOG,WAAW,UAAU;QAClE,OAAO,CAAC;IACV;IAEA,MAAMI,gBAAgBJ,UAAUK,MAAM,EAAEC,KAAK,CAACC,QAAUA,MAAMC,IAAI,KAAK;IAIvE,IAAI,CAACJ,eAAe;QAClB,OAAO,CAAC;IACV;IACA,MAAMK,SAASL,cAAcM,IAAI,CAACC,EAAE;IACpC,IAAI,CAACF,QAAQ;QACX,OAAO,CAAC;IACV;IACA,MAAMG,WAAWH,OAAOH,IAAI,CAAC,CAACO,aAAeA,WAAWL,IAAI,KAAK;IAGjE,IAAI,CAACI,UAAU;QACb,OAAO,CAAC;IACV;IACA,MAAME,oBAAqBL,OAAOM,MAAM,CAAC,CAACF,aAAeA,WAAWL,IAAI,KAAK,WAC3E,EAAE;IAEJ,OAAO;QACLQ,OAAOC,wBAAwBjB;QAC/BkB,OAAO;YACLC,aAAa,AAACP,SAA4BO,WAAW,CAACC,GAAG,CAAC,CAACC,IAAMnB,cAAcmB,GAAGpB;YAClFqB,YAAYC,yBAAyBX;QACvC;QACAD,IAAIG,kBAAkBM,GAAG,CAAC,CAACC,IAAMnB,cAAcmB,GAAGpB;QAClDuB,QAAQC,qBAAqBzB;IAC/B;AACF;AAEA;;CAEC,GACD,SAASyB,qBAAqBzB,SAA2B;IACvD,MAAM0B,aAAa1B,UAAUK,MAAM,EAAEC,KAAK,CAACqB,UAAYA,QAAQnB,IAAI,KAAK;IACxE,OAAOoB,uBAAuBF,YAAYhB,MAAMmB,SAASC;AAC3D;AAEA;;CAEC,GACD,SAASP,yBAAyBX,QAA0B;IAC1D,OAAO,gBAAgBA,WAAWgB,uBAAuBhB,SAASU,UAAU,IAAIS;AAClF;AAEA;;CAEC,GACD,SAASd,wBAAwBjB,SAA2B;IAC1D,MAAMgC,YAAYhC,UAAUK,MAAM,EAAEC,KAAK,CAACqB,UAAYA,QAAQnB,IAAI,KAAK;IACvE,OAAOoB,uBAAuBI,WAAWtB,MAAMmB,SAASC;AAC1D;AAEA;;CAEC,GACD,SAASF,uBAAuBK,aAAsB;IACpD,IAAI,CAACA,iBAAiB,CAACC,MAAMC,OAAO,CAACF,gBAAgB;QACnD,OAAOF;IACT;IACA,MAAMK,eAAeH,cAClBlB,MAAM,CACL,CAACsB,IAA4C1C,SAAS0C,MAAM,CAAC,CAACA,EAAEC,KAAK,IAAI1C,SAASyC,EAAEC,KAAK,GAE1FlB,GAAG,CAAC,CAACmB;QACJ,OAAO;YACLD,OAAOC,KAAKD,KAAK;YACjB,GAAGxC,aAAa,SAASyC,KAAKC,KAAK,CAAC;QACtC;IACF;IACF,IAAI,CAACJ,cAAcK,QAAQ;QACzB,OAAOV;IACT;IAEA,OAAOK;AACT"}
@@ -0,0 +1,4 @@
1
+ import { subdebug } from '@sanity/cli-core';
2
+ export const manifestDebug = subdebug('manifest');
3
+
4
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/manifest/debug.ts"],"sourcesContent":["import {subdebug} from '@sanity/cli-core'\n\nexport const manifestDebug = subdebug('manifest')\n"],"names":["subdebug","manifestDebug"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AAEzC,OAAO,MAAMC,gBAAgBD,SAAS,YAAW"}
@@ -1,14 +1,12 @@
1
- import { createHash } from 'node:crypto';
2
1
  import { mkdir, writeFile } from 'node:fs/promises';
3
2
  import { join, resolve } from 'node:path';
4
- import { getTimer } from '@sanity/cli-core';
3
+ import { findProjectRoot, getTimer, studioWorkerTask } from '@sanity/cli-core';
5
4
  import { spinner } from '@sanity/cli-core/ux';
6
- import { importStudioConfig } from '../../util/importStudioConfig.js';
7
5
  import { readModuleVersion } from '../../util/readModuleVersion.js';
8
- import { extractWorkspaceManifest } from './extractWorkspaceManifest.js';
6
+ import { SchemaExtractionError } from '../schema/utils/SchemaExtractionError.js';
7
+ import { manifestDebug } from './debug.js';
8
+ import { writeWorkspaceFiles } from './writeWorkspaceFiles.js';
9
9
  export const MANIFEST_FILENAME = 'create-manifest.json';
10
- const SCHEMA_FILENAME_SUFFIX = '.create-schema.json';
11
- const TOOLS_FILENAME_SUFFIX = '.create-tools.json';
12
10
  /** Escape-hatch env flags to change action behavior */ const FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_EXTRACT_MANIFEST_ENABLED';
13
11
  const EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== 'false';
14
12
  const EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === 'true';
@@ -17,32 +15,45 @@ const CREATE_TIMER = 'create-manifest';
17
15
  * This function will never throw.
18
16
  * @returns `undefined` if extract succeeded - caught error if it failed
19
17
  */ export async function extractManifestSafe(options) {
18
+ const { outPath, output } = options;
20
19
  if (!EXTRACT_MANIFEST_ENABLED) {
21
20
  return undefined;
22
21
  }
23
22
  try {
24
- await extractManifest(options);
23
+ await extractManifest(outPath);
25
24
  return undefined;
26
25
  } catch (err) {
27
26
  if (EXTRACT_MANIFEST_LOG_ERRORS) {
28
- options.output.error(err);
27
+ output.error(err);
29
28
  }
30
29
  return err;
31
30
  }
32
31
  }
33
- async function extractManifest(options) {
34
- const { flags, workDir } = options;
35
- const staticPath = resolve(join(workDir, flags.path));
32
+ export async function extractManifest(outPath) {
33
+ const projectRoot = await findProjectRoot(process.cwd());
34
+ const workDir = projectRoot.directory;
35
+ const configPath = projectRoot.path;
36
+ const staticPath = resolve(join(workDir, outPath));
36
37
  const path = join(staticPath, MANIFEST_FILENAME);
37
38
  const timer = getTimer();
38
39
  timer.start(CREATE_TIMER);
39
40
  const spin = spinner('Extracting manifest').start();
40
41
  try {
41
- const workspaceManifests = await getWorkspaceManifests(workDir);
42
+ const result = await studioWorkerTask(new URL('extractManifest.worker.js', import.meta.url), {
43
+ name: 'extractManifest',
44
+ studioRootPath: workDir,
45
+ workerData: {
46
+ configPath,
47
+ workDir
48
+ }
49
+ });
50
+ if (result.type === 'error') {
51
+ throw new SchemaExtractionError(result.error, result.validation);
52
+ }
42
53
  await mkdir(staticPath, {
43
54
  recursive: true
44
55
  });
45
- const workspaceFiles = await writeWorkspaceFiles(workspaceManifests, staticPath);
56
+ const workspaceFiles = await writeWorkspaceFiles(result.workspaceManifests, staticPath);
46
57
  const manifest = {
47
58
  /**
48
59
  * Version history:
@@ -58,36 +69,10 @@ async function extractManifest(options) {
58
69
  const manifestDuration = timer.end(CREATE_TIMER);
59
70
  spin.succeed(`Extracted manifest (${manifestDuration.toFixed(0)}ms)`);
60
71
  } catch (err) {
61
- spin.fail(err.message);
72
+ manifestDebug('Error extracting manifest', err);
73
+ spin.fail();
62
74
  throw err;
63
75
  }
64
76
  }
65
- async function getWorkspaceManifests(workDir) {
66
- const workspaces = await importStudioConfig(workDir);
67
- return await extractWorkspaceManifest(workspaces);
68
- }
69
- function writeWorkspaceFiles(manifestWorkspaces, staticPath) {
70
- const output = manifestWorkspaces.map((workspace)=>writeWorkspaceFile(workspace, staticPath));
71
- return Promise.all(output);
72
- }
73
- async function writeWorkspaceFile(workspace, staticPath) {
74
- const [schemaFilename, toolsFilename] = await Promise.all([
75
- createFile(staticPath, workspace.schema, SCHEMA_FILENAME_SUFFIX),
76
- createFile(staticPath, workspace.tools, TOOLS_FILENAME_SUFFIX)
77
- ]);
78
- return {
79
- ...workspace,
80
- schema: schemaFilename,
81
- tools: toolsFilename
82
- };
83
- }
84
- const createFile = async (path, content, filenameSuffix)=>{
85
- const stringifiedContent = JSON.stringify(content, null, 2);
86
- const hash = createHash('sha1').update(stringifiedContent).digest('hex');
87
- const filename = `${hash.slice(0, 8)}${filenameSuffix}`;
88
- // workspaces with identical data will overwrite each others file. This is ok, since they are identical and can be shared
89
- await writeFile(join(path, filename), stringifiedContent);
90
- return filename;
91
- };
92
77
 
93
78
  //# sourceMappingURL=extractManifest.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/manifest/extractManifest.ts"],"sourcesContent":["import {createHash} from 'node:crypto'\nimport {mkdir, writeFile} from 'node:fs/promises'\nimport {join, resolve} from 'node:path'\n\nimport {getTimer, Output} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type Workspace} from 'sanity'\n\nimport {type ExtractManifestCommand} from '../../commands/manifest/extract'\nimport {importStudioConfig} from '../../util/importStudioConfig.js'\nimport {readModuleVersion} from '../../util/readModuleVersion.js'\nimport {extractWorkspaceManifest} from './extractWorkspaceManifest.js'\nimport {\n type CreateManifest,\n type CreateWorkspaceManifest,\n type ManifestWorkspaceFile,\n} from './types'\n\nexport const MANIFEST_FILENAME = 'create-manifest.json'\nconst SCHEMA_FILENAME_SUFFIX = '.create-schema.json'\nconst TOOLS_FILENAME_SUFFIX = '.create-tools.json'\n\n/** Escape-hatch env flags to change action behavior */\nconst FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_EXTRACT_MANIFEST_ENABLED'\nconst EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== 'false'\nconst EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === 'true'\n\nconst CREATE_TIMER = 'create-manifest'\n\ninterface ExtractManifestOptions {\n flags: ExtractManifestCommand['flags']\n output: Output\n workDir: string\n}\n\n/**\n * This function will never throw.\n * @returns `undefined` if extract succeeded - caught error if it failed\n */\nexport async function extractManifestSafe(\n options: ExtractManifestOptions,\n): Promise<Error | undefined> {\n if (!EXTRACT_MANIFEST_ENABLED) {\n return undefined\n }\n\n try {\n await extractManifest(options)\n return undefined\n } catch (err) {\n if (EXTRACT_MANIFEST_LOG_ERRORS) {\n options.output.error(err)\n }\n return err\n }\n}\n\nasync function extractManifest(options: ExtractManifestOptions): Promise<void> {\n const {flags, workDir} = options\n const staticPath = resolve(join(workDir, flags.path))\n const path = join(staticPath, MANIFEST_FILENAME)\n\n const timer = getTimer()\n timer.start(CREATE_TIMER)\n const spin = spinner('Extracting manifest').start()\n\n try {\n const workspaceManifests = await getWorkspaceManifests(workDir)\n await mkdir(staticPath, {recursive: true})\n\n const workspaceFiles = await writeWorkspaceFiles(workspaceManifests, staticPath)\n\n const manifest: CreateManifest = {\n /**\n * Version history:\n * 1: Initial release.\n * 2: Added tools file.\n * 3. Added studioVersion field.\n */\n createdAt: new Date().toISOString(),\n studioVersion: await readModuleVersion(workDir, 'sanity'),\n version: 3,\n workspaces: workspaceFiles,\n }\n\n await writeFile(path, JSON.stringify(manifest, null, 2))\n const manifestDuration = timer.end(CREATE_TIMER)\n\n spin.succeed(`Extracted manifest (${manifestDuration.toFixed(0)}ms)`)\n } catch (err) {\n spin.fail(err.message)\n throw err\n }\n}\n\nasync function getWorkspaceManifests(workDir: string): Promise<CreateWorkspaceManifest[]> {\n const workspaces = await importStudioConfig(workDir)\n return await extractWorkspaceManifest(workspaces as unknown as Workspace[])\n}\n\nfunction writeWorkspaceFiles(\n manifestWorkspaces: CreateWorkspaceManifest[],\n staticPath: string,\n): Promise<ManifestWorkspaceFile[]> {\n const output = manifestWorkspaces.map((workspace) => writeWorkspaceFile(workspace, staticPath))\n\n return Promise.all(output)\n}\n\nasync function writeWorkspaceFile(\n workspace: CreateWorkspaceManifest,\n staticPath: string,\n): Promise<ManifestWorkspaceFile> {\n const [schemaFilename, toolsFilename] = await Promise.all([\n createFile(staticPath, workspace.schema, SCHEMA_FILENAME_SUFFIX),\n createFile(staticPath, workspace.tools, TOOLS_FILENAME_SUFFIX),\n ])\n\n return {\n ...workspace,\n schema: schemaFilename,\n tools: toolsFilename,\n }\n}\n\nconst createFile = async (path: string, content: unknown, filenameSuffix: string) => {\n const stringifiedContent = JSON.stringify(content, null, 2)\n const hash = createHash('sha1').update(stringifiedContent).digest('hex')\n const filename = `${hash.slice(0, 8)}${filenameSuffix}`\n\n // workspaces with identical data will overwrite each others file. This is ok, since they are identical and can be shared\n await writeFile(join(path, filename), stringifiedContent)\n\n return filename\n}\n"],"names":["createHash","mkdir","writeFile","join","resolve","getTimer","spinner","importStudioConfig","readModuleVersion","extractWorkspaceManifest","MANIFEST_FILENAME","SCHEMA_FILENAME_SUFFIX","TOOLS_FILENAME_SUFFIX","FEATURE_ENABLED_ENV_NAME","EXTRACT_MANIFEST_ENABLED","process","env","EXTRACT_MANIFEST_LOG_ERRORS","SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS","CREATE_TIMER","extractManifestSafe","options","undefined","extractManifest","err","output","error","flags","workDir","staticPath","path","timer","start","spin","workspaceManifests","getWorkspaceManifests","recursive","workspaceFiles","writeWorkspaceFiles","manifest","createdAt","Date","toISOString","studioVersion","version","workspaces","JSON","stringify","manifestDuration","end","succeed","toFixed","fail","message","manifestWorkspaces","map","workspace","writeWorkspaceFile","Promise","all","schemaFilename","toolsFilename","createFile","schema","tools","content","filenameSuffix","stringifiedContent","hash","update","digest","filename","slice"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/manifest/extractManifest.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport {join, resolve} from 'node:path'\n\nimport {findProjectRoot, getTimer, Output, studioWorkerTask} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {readModuleVersion} from '../../util/readModuleVersion.js'\nimport {type ExtractSchemaWorkerError} from '../schema/types.js'\nimport {SchemaExtractionError} from '../schema/utils/SchemaExtractionError.js'\nimport {manifestDebug} from './debug.js'\nimport {\n type CreateManifest,\n type CreateWorkspaceManifest,\n type ExtractManifestWorkerData,\n} from './types'\nimport {writeWorkspaceFiles} from './writeWorkspaceFiles.js'\n\nexport const MANIFEST_FILENAME = 'create-manifest.json'\n\n/** Escape-hatch env flags to change action behavior */\nconst FEATURE_ENABLED_ENV_NAME = 'SANITY_CLI_EXTRACT_MANIFEST_ENABLED'\nconst EXTRACT_MANIFEST_ENABLED = process.env[FEATURE_ENABLED_ENV_NAME] !== 'false'\nconst EXTRACT_MANIFEST_LOG_ERRORS = process.env.SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS === 'true'\n\nconst CREATE_TIMER = 'create-manifest'\n\ninterface ExtractManifestOptions {\n outPath: string\n output: Output\n}\n\n/**\n * This function will never throw.\n * @returns `undefined` if extract succeeded - caught error if it failed\n */\nexport async function extractManifestSafe(\n options: ExtractManifestOptions,\n): Promise<Error | undefined> {\n const {outPath, output} = options\n if (!EXTRACT_MANIFEST_ENABLED) {\n return undefined\n }\n\n try {\n await extractManifest(outPath)\n return undefined\n } catch (err) {\n if (EXTRACT_MANIFEST_LOG_ERRORS) {\n output.error(err)\n }\n return err\n }\n}\n\ninterface ExtractManifestWorkerResult {\n type: 'success'\n workspaceManifests: CreateWorkspaceManifest[]\n}\n\ntype ExtractManifestWorkerMessage = ExtractManifestWorkerResult | ExtractSchemaWorkerError\n\nexport async function extractManifest(outPath: string): Promise<void> {\n const projectRoot = await findProjectRoot(process.cwd())\n\n const workDir = projectRoot.directory\n const configPath = projectRoot.path\n const staticPath = resolve(join(workDir, outPath))\n const path = join(staticPath, MANIFEST_FILENAME)\n\n const timer = getTimer()\n timer.start(CREATE_TIMER)\n const spin = spinner('Extracting manifest').start()\n\n try {\n const result = await studioWorkerTask<ExtractManifestWorkerMessage>(\n new URL('extractManifest.worker.js', import.meta.url),\n {\n name: 'extractManifest',\n studioRootPath: workDir,\n workerData: {configPath, workDir} satisfies ExtractManifestWorkerData,\n },\n )\n\n if (result.type === 'error') {\n throw new SchemaExtractionError(result.error, result.validation)\n }\n\n await mkdir(staticPath, {recursive: true})\n\n const workspaceFiles = await writeWorkspaceFiles(result.workspaceManifests, staticPath)\n\n const manifest: CreateManifest = {\n /**\n * Version history:\n * 1: Initial release.\n * 2: Added tools file.\n * 3. Added studioVersion field.\n */\n createdAt: new Date().toISOString(),\n studioVersion: await readModuleVersion(workDir, 'sanity'),\n version: 3,\n workspaces: workspaceFiles,\n }\n\n await writeFile(path, JSON.stringify(manifest, null, 2))\n const manifestDuration = timer.end(CREATE_TIMER)\n\n spin.succeed(`Extracted manifest (${manifestDuration.toFixed(0)}ms)`)\n } catch (err) {\n manifestDebug('Error extracting manifest', err)\n spin.fail()\n\n throw err\n }\n}\n"],"names":["mkdir","writeFile","join","resolve","findProjectRoot","getTimer","studioWorkerTask","spinner","readModuleVersion","SchemaExtractionError","manifestDebug","writeWorkspaceFiles","MANIFEST_FILENAME","FEATURE_ENABLED_ENV_NAME","EXTRACT_MANIFEST_ENABLED","process","env","EXTRACT_MANIFEST_LOG_ERRORS","SANITY_CLI_EXTRACT_MANIFEST_LOG_ERRORS","CREATE_TIMER","extractManifestSafe","options","outPath","output","undefined","extractManifest","err","error","projectRoot","cwd","workDir","directory","configPath","path","staticPath","timer","start","spin","result","URL","url","name","studioRootPath","workerData","type","validation","recursive","workspaceFiles","workspaceManifests","manifest","createdAt","Date","toISOString","studioVersion","version","workspaces","JSON","stringify","manifestDuration","end","succeed","toFixed","fail"],"mappings":"AAAA,SAAQA,KAAK,EAAEC,SAAS,QAAO,mBAAkB;AACjD,SAAQC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAEvC,SAAQC,eAAe,EAAEC,QAAQ,EAAUC,gBAAgB,QAAO,mBAAkB;AACpF,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,iBAAiB,QAAO,kCAAiC;AAEjE,SAAQC,qBAAqB,QAAO,2CAA0C;AAC9E,SAAQC,aAAa,QAAO,aAAY;AAMxC,SAAQC,mBAAmB,QAAO,2BAA0B;AAE5D,OAAO,MAAMC,oBAAoB,uBAAsB;AAEvD,qDAAqD,GACrD,MAAMC,2BAA2B;AACjC,MAAMC,2BAA2BC,QAAQC,GAAG,CAACH,yBAAyB,KAAK;AAC3E,MAAMI,8BAA8BF,QAAQC,GAAG,CAACE,sCAAsC,KAAK;AAE3F,MAAMC,eAAe;AAOrB;;;CAGC,GACD,OAAO,eAAeC,oBACpBC,OAA+B;IAE/B,MAAM,EAACC,OAAO,EAAEC,MAAM,EAAC,GAAGF;IAC1B,IAAI,CAACP,0BAA0B;QAC7B,OAAOU;IACT;IAEA,IAAI;QACF,MAAMC,gBAAgBH;QACtB,OAAOE;IACT,EAAE,OAAOE,KAAK;QACZ,IAAIT,6BAA6B;YAC/BM,OAAOI,KAAK,CAACD;QACf;QACA,OAAOA;IACT;AACF;AASA,OAAO,eAAeD,gBAAgBH,OAAe;IACnD,MAAMM,cAAc,MAAMxB,gBAAgBW,QAAQc,GAAG;IAErD,MAAMC,UAAUF,YAAYG,SAAS;IACrC,MAAMC,aAAaJ,YAAYK,IAAI;IACnC,MAAMC,aAAa/B,QAAQD,KAAK4B,SAASR;IACzC,MAAMW,OAAO/B,KAAKgC,YAAYtB;IAE9B,MAAMuB,QAAQ9B;IACd8B,MAAMC,KAAK,CAACjB;IACZ,MAAMkB,OAAO9B,QAAQ,uBAAuB6B,KAAK;IAEjD,IAAI;QACF,MAAME,SAAS,MAAMhC,iBACnB,IAAIiC,IAAI,6BAA6B,YAAYC,GAAG,GACpD;YACEC,MAAM;YACNC,gBAAgBZ;YAChBa,YAAY;gBAACX;gBAAYF;YAAO;QAClC;QAGF,IAAIQ,OAAOM,IAAI,KAAK,SAAS;YAC3B,MAAM,IAAInC,sBAAsB6B,OAAOX,KAAK,EAAEW,OAAOO,UAAU;QACjE;QAEA,MAAM7C,MAAMkC,YAAY;YAACY,WAAW;QAAI;QAExC,MAAMC,iBAAiB,MAAMpC,oBAAoB2B,OAAOU,kBAAkB,EAAEd;QAE5E,MAAMe,WAA2B;YAC/B;;;;;OAKC,GACDC,WAAW,IAAIC,OAAOC,WAAW;YACjCC,eAAe,MAAM7C,kBAAkBsB,SAAS;YAChDwB,SAAS;YACTC,YAAYR;QACd;QAEA,MAAM9C,UAAUgC,MAAMuB,KAAKC,SAAS,CAACR,UAAU,MAAM;QACrD,MAAMS,mBAAmBvB,MAAMwB,GAAG,CAACxC;QAEnCkB,KAAKuB,OAAO,CAAC,CAAC,oBAAoB,EAAEF,iBAAiBG,OAAO,CAAC,GAAG,GAAG,CAAC;IACtE,EAAE,OAAOnC,KAAK;QACZhB,cAAc,6BAA6BgB;QAC3CW,KAAKyB,IAAI;QAET,MAAMpC;IACR;AACF"}
@@ -0,0 +1,31 @@
1
+ import { isMainThread, parentPort, workerData } from 'node:worker_threads';
2
+ import { getStudioWorkspaces } from '@sanity/cli-core';
3
+ import { extractValidationFromSchemaError } from '../schema/utils/extractValidationFromSchemaError.js';
4
+ import { extractWorkspaceManifest } from './extractWorkspaceManifest.js';
5
+ import { extractManifestWorkerData } from './types.js';
6
+ if (isMainThread || !parentPort) {
7
+ throw new Error('Should only be run in a worker!');
8
+ }
9
+ const { configPath, workDir } = extractManifestWorkerData.parse(workerData);
10
+ try {
11
+ const workspaces = await getStudioWorkspaces(configPath);
12
+ const workspaceManifests = await extractWorkspaceManifest(workspaces, workDir);
13
+ parentPort.postMessage({
14
+ type: 'success',
15
+ workspaceManifests
16
+ });
17
+ } catch (error) {
18
+ const validation = await extractValidationFromSchemaError(error, workDir);
19
+ parentPort.postMessage({
20
+ error: error instanceof Error ? error.message : String(error),
21
+ type: 'error',
22
+ validation
23
+ });
24
+ }
25
+ // Explicitly exit the process to avoid any dangling references from keeping
26
+ // the process alive after resolving it's main task
27
+ setImmediate(()=>{
28
+ process.exit(1);
29
+ });
30
+
31
+ //# sourceMappingURL=extractManifest.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/manifest/extractManifest.worker.ts"],"sourcesContent":["import {isMainThread, parentPort, workerData} from 'node:worker_threads'\n\nimport {getStudioWorkspaces} from '@sanity/cli-core'\n\nimport {extractValidationFromSchemaError} from '../schema/utils/extractValidationFromSchemaError.js'\nimport {extractWorkspaceManifest} from './extractWorkspaceManifest.js'\nimport {extractManifestWorkerData} from './types.js'\n\nif (isMainThread || !parentPort) {\n throw new Error('Should only be run in a worker!')\n}\n\nconst {configPath, workDir} = extractManifestWorkerData.parse(workerData)\n\ntry {\n const workspaces = await getStudioWorkspaces(configPath)\n const workspaceManifests = await extractWorkspaceManifest(workspaces, workDir)\n\n parentPort.postMessage({\n type: 'success',\n workspaceManifests,\n })\n} catch (error) {\n const validation = await extractValidationFromSchemaError(error, workDir)\n parentPort.postMessage({\n error: error instanceof Error ? error.message : String(error),\n type: 'error',\n validation,\n })\n}\n\n// Explicitly exit the process to avoid any dangling references from keeping\n// the process alive after resolving it's main task\nsetImmediate(() => {\n process.exit(1)\n})\n"],"names":["isMainThread","parentPort","workerData","getStudioWorkspaces","extractValidationFromSchemaError","extractWorkspaceManifest","extractManifestWorkerData","Error","configPath","workDir","parse","workspaces","workspaceManifests","postMessage","type","error","validation","message","String","setImmediate","process","exit"],"mappings":"AAAA,SAAQA,YAAY,EAAEC,UAAU,EAAEC,UAAU,QAAO,sBAAqB;AAExE,SAAQC,mBAAmB,QAAO,mBAAkB;AAEpD,SAAQC,gCAAgC,QAAO,sDAAqD;AACpG,SAAQC,wBAAwB,QAAO,gCAA+B;AACtE,SAAQC,yBAAyB,QAAO,aAAY;AAEpD,IAAIN,gBAAgB,CAACC,YAAY;IAC/B,MAAM,IAAIM,MAAM;AAClB;AAEA,MAAM,EAACC,UAAU,EAAEC,OAAO,EAAC,GAAGH,0BAA0BI,KAAK,CAACR;AAE9D,IAAI;IACF,MAAMS,aAAa,MAAMR,oBAAoBK;IAC7C,MAAMI,qBAAqB,MAAMP,yBAAyBM,YAAYF;IAEtER,WAAWY,WAAW,CAAC;QACrBC,MAAM;QACNF;IACF;AACF,EAAE,OAAOG,OAAO;IACd,MAAMC,aAAa,MAAMZ,iCAAiCW,OAAON;IACjER,WAAWY,WAAW,CAAC;QACrBE,OAAOA,iBAAiBR,QAAQQ,MAAME,OAAO,GAAGC,OAAOH;QACvDD,MAAM;QACNE;IACF;AACF;AAEA,4EAA4E;AAC5E,mDAAmD;AACnDG,aAAa;IACXC,QAAQC,IAAI,CAAC;AACf"}