ecosystem-packages.mjs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { readFile } from 'node:fs/promises'
  2. import { join, resolve } from 'node:path'
  3. export async function readJson(path) {
  4. return JSON.parse(await readFile(path, 'utf8'))
  5. }
  6. export function npmPackFilename(packageName, packageVersion) {
  7. return `${packageName.replace(/^@/, '').replace(/\//g, '-')}-${packageVersion}.tgz`
  8. }
  9. export function ecosystemPackageSpecs(wrapperManifest) {
  10. return [
  11. {
  12. id: 'core',
  13. kind: 'core',
  14. packageDir: 'packages/core',
  15. publicSource: true,
  16. corePackage: wrapperManifest.corePackage
  17. },
  18. ...(wrapperManifest.renderers || []).map(renderer => ({
  19. id: `renderer-${renderer.id}`,
  20. kind: 'renderer',
  21. packageDir: renderer.packageDir,
  22. renderer,
  23. publicSource: renderer.publicSource !== false
  24. })),
  25. ...(wrapperManifest.presets || []).map(preset => ({
  26. id: `preset-${preset.id}`,
  27. kind: 'preset',
  28. packageDir: preset.packageDir,
  29. preset,
  30. publicSource: preset.publicSource !== false
  31. })),
  32. ...(wrapperManifest.compatibilityPackages || []).map(compatibilityPackage => ({
  33. id: compatibilityPackage.id,
  34. kind: 'compatibility',
  35. packageDir: compatibilityPackage.packageDir,
  36. compatibilityPackage,
  37. publicSource: compatibilityPackage.publicSource === true,
  38. releaseArtifact: compatibilityPackage.releaseArtifact ?? {
  39. includeTarball: true
  40. }
  41. })),
  42. ...wrapperManifest.wrappers.map(wrapper => ({
  43. id: wrapper.id,
  44. kind: 'standard-wrapper',
  45. packageDir: wrapper.packageDir,
  46. wrapper,
  47. publicSource: true
  48. }))
  49. ]
  50. }
  51. export async function loadEcosystemPackageEntry(sourceRoot, spec) {
  52. const absoluteDir = resolve(sourceRoot, spec.packageDir)
  53. const packageJson = await readJson(join(absoluteDir, 'package.json'))
  54. return {
  55. ...spec,
  56. absoluteDir,
  57. packageJson,
  58. packageName: packageJson.name,
  59. version: packageJson.version,
  60. tarballName: npmPackFilename(packageJson.name, packageJson.version),
  61. releaseArtifact: spec.releaseArtifact ?? {
  62. includeTarball: true
  63. }
  64. }
  65. }
  66. export async function loadEcosystemReleaseContext(sourceRoot) {
  67. const rootPackage = await readJson(join(sourceRoot, 'package.json'))
  68. const wrapperManifest = await readJson(join(sourceRoot, 'ecosystem', 'wrappers.json'))
  69. const specs = ecosystemPackageSpecs(wrapperManifest)
  70. const entries = await Promise.all(specs.map(spec => loadEcosystemPackageEntry(sourceRoot, spec)))
  71. return {
  72. rootPackage,
  73. wrapperManifest,
  74. specs,
  75. entries
  76. }
  77. }
  78. export function collectExportEntrypoints(value, paths = new Set()) {
  79. if (!value) {
  80. return paths
  81. }
  82. if (typeof value === 'string') {
  83. paths.add(value)
  84. return paths
  85. }
  86. if (Array.isArray(value)) {
  87. for (const item of value) {
  88. collectExportEntrypoints(item, paths)
  89. }
  90. return paths
  91. }
  92. if (typeof value === 'object') {
  93. for (const item of Object.values(value)) {
  94. collectExportEntrypoints(item, paths)
  95. }
  96. }
  97. return paths
  98. }
  99. export function collectPackageEntrypoints(packageJson) {
  100. const entrypoints = new Set()
  101. for (const field of ['main', 'module', 'browser', 'types', 'svelte']) {
  102. if (typeof packageJson[field] === 'string') {
  103. entrypoints.add(packageJson[field])
  104. }
  105. }
  106. for (const item of collectExportEntrypoints(packageJson.exports)) {
  107. entrypoints.add(item)
  108. }
  109. for (const item of Object.values(packageJson.bin || {})) {
  110. if (typeof item === 'string') {
  111. entrypoints.add(item)
  112. }
  113. }
  114. return [...entrypoints].filter(entrypoint =>
  115. !entrypoint.startsWith('/') &&
  116. !entrypoint.includes(':') &&
  117. !entrypoint.includes('*') &&
  118. !entrypoint.startsWith('#') &&
  119. entrypoint !== './' &&
  120. entrypoint !== '.'
  121. )
  122. }
  123. export function ecosystemPackageManifestEntry(entry) {
  124. return {
  125. id: entry.id,
  126. kind: entry.kind,
  127. packageName: entry.packageName,
  128. version: entry.version,
  129. packageDir: entry.packageDir,
  130. tarball: entry.tarballName,
  131. publicSource: entry.publicSource,
  132. releaseArtifact: entry.releaseArtifact,
  133. targetPackage: entry.compatibilityPackage?.targetPackage ?? null,
  134. github: entry.wrapper?.github ?? entry.renderer?.github ?? entry.preset?.github ?? null,
  135. gitee: entry.wrapper?.gitee ?? entry.renderer?.gitee ?? entry.preset?.gitee ?? null,
  136. sourceRepository: entry.corePackage?.sourceRepository ?? null
  137. }
  138. }