publication-payload.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /** Publication payload policy shared by static manifests and packed tarballs. */
  2. /** Publication exceptions required for TypeRT declaration-map navigation. */
  3. export interface PublicationPayloadPolicy {
  4. readonly typeRTRemoteNavigation?: boolean
  5. }
  6. /** Whether a package manifest exports generated Host-for-Client metadata with source navigation. */
  7. export function hasTypeRTRemoteNavigation(manifest: unknown): boolean {
  8. if (manifest === null || typeof manifest !== 'object' || Array.isArray(manifest)) return false
  9. const exportsField = (manifest as Record<string, unknown>).exports
  10. if (exportsField === null || typeof exportsField !== 'object' || Array.isArray(exportsField)) return false
  11. const remote = (exportsField as Record<string, unknown>)['./remote']
  12. if (remote === null || typeof remote !== 'object' || Array.isArray(remote)) return false
  13. const entry = remote as Record<string, unknown>
  14. return entry.types === './lib/typert.remote-client.d.ts'
  15. && entry.default === './lib/typert.remote-client.js'
  16. }
  17. /** Normalize a package manifest path or npm tarball member to its payload-relative path. */
  18. function payloadPath(file: string): string {
  19. const normalized = file.replaceAll('\\', '/').replace(/^\.\/+/, '').replace(/\/+$/, '')
  20. return normalized.startsWith('package/') ? normalized.slice('package/'.length) : normalized
  21. }
  22. /** Whether a package payload path exposes source or declaration-map intermediates. */
  23. export function isForbiddenPublicationFile(
  24. file: string,
  25. policy: PublicationPayloadPolicy = {},
  26. ): boolean {
  27. const normalized = payloadPath(file)
  28. if (policy.typeRTRemoteNavigation === true
  29. && (normalized === 'src'
  30. || normalized.startsWith('src/')
  31. || normalized === 'lib/typert.remote-client.d.ts.map')) {
  32. return false
  33. }
  34. return normalized === 'src'
  35. || normalized.startsWith('src/')
  36. || normalized.endsWith('.d.ts.map')
  37. }
  38. /** Reject source and declaration-map members in a packed npm tarball. */
  39. export function validateTarballPayload(
  40. files: readonly string[],
  41. context: string,
  42. policy: PublicationPayloadPolicy = {},
  43. ): void {
  44. for (const file of files) {
  45. if (!isForbiddenPublicationFile(file, policy)) continue
  46. const normalized = payloadPath(file)
  47. if (normalized === 'src' || normalized.startsWith('src/')) {
  48. throw new Error(`${context} publishes source file ${file}`)
  49. }
  50. throw new Error(`${context} publishes declaration map ${file}`)
  51. }
  52. }