runtime-file-policy.spec.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
  2. import { tmpdir } from 'node:os'
  3. import { join, relative } from 'node:path'
  4. import { expect, it } from 'vitest'
  5. import { desktopRuntimeFileExclusion } from '../scripts/runtime-file-policy.ts'
  6. import { verifyDesktopRuntime, writeDesktopRuntime } from '../src/runtime-tree.ts'
  7. import { runtimeFixture } from './runtime-fixture.ts'
  8. const windows = { platform: 'win32' as const, arch: 'x64' }
  9. it('omits development artifacts while preserving executable modules, assets and license files', async () => {
  10. const root = mkdtempSync(join(tmpdir(), 'desktop-file-policy-'))
  11. const source = join(root, 'source')
  12. const output = join(root, 'output')
  13. const removed = [
  14. 'example/index.d.ts', 'example/index.d.mts', 'example/index.d.cts',
  15. 'example/index.js.map', 'example/index.mjs.map', 'example/index.cjs.map',
  16. 'example/style.css.map', 'example/index.d.ts.map', 'example/index.d.mts.map',
  17. 'example/index.d.cts.map', 'example/tsconfig.tsbuildinfo',
  18. 'fs-ext/build/Release/obj/fs_ext/native.obj', 'fs-ext/build/Release/fs_ext.pdb',
  19. 'fs-ext/build/Release/fs_ext.lib', 'fs-ext/build/Release/fs_ext.exp',
  20. 'fs-ext/build/Release/fs_ext.iobj', 'fs-ext/build/Release/fs_ext.ipdb',
  21. 'fs-ext/build/binding.sln', 'fs-ext/build/config.gypi',
  22. 'fs-ext/build/fs_ext.vcxproj', 'fs-ext/build/fs_ext.vcxproj.filters',
  23. 'node-pty/prebuilds/win32-arm64/conpty.node',
  24. 'node-pty/prebuilds/linux-x64/pty.node', 'node-pty/prebuilds/darwin-x64/pty.node',
  25. 'node-pty/prebuilds/win32-x64/conpty.pdb',
  26. '@koromix/koffi-win32-x64/win32_x64/koffi.lib',
  27. '@mixmark-io/domino/test/entities.html',
  28. '@deepseek-ai/libreoffice-kit-wasm/assets/soffice.data',
  29. '@deepseek-ai/libreoffice-kit-darwin-arm64/bin/libreoffice-kit',
  30. '.modules.yaml', '.pnpm-workspace-state-v1.json', '.bin/tool', '.pnpm/cache',
  31. ]
  32. const retained = [
  33. 'example/index.js', 'example/index.cjs', 'example/index.mjs', 'example/worker.js',
  34. 'example/source.ts', 'example/src/entry.ts', 'example/test/runtime-fixture.json',
  35. 'example/locale.json', 'example/data.map', 'example/module.wasm',
  36. 'example/package.json', 'example/LICENSE', 'example/NOTICE', 'example/README.md',
  37. 'example/native.lib', 'example/native.obj', 'example/symbols.pdb',
  38. 'fs-ext/build/Release/fs_ext.node', 'fs-ext/build/Release/runtime.dll',
  39. 'node-pty/prebuilds/win32-x64/conpty.node',
  40. 'node-pty/prebuilds/win32-x64/conpty_console_list.node',
  41. 'node-pty/prebuilds/win32-x64/conpty/conpty.dll',
  42. 'node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe',
  43. 'node-pty/third_party/conpty/win10-x64/OpenConsole.exe',
  44. '@koromix/koffi-win32-x64/win32_x64/koffi.node',
  45. '@mixmark-io/domino/lib/HTMLParser.js', '@mixmark-io/domino/lib/EntityParser.js',
  46. '@img/sharp-win32-x64/lib/libvips-42.dll',
  47. '@deepseek-ai/libreoffice-kit-win32-x64/bin/libreoffice-kit.exe',
  48. '@deepseek-ai/libreoffice-kit-win32-x64/sources/core-source.json',
  49. '@deepseek-ai/libreoffice-kit-win32-x64/licenses/MPL-2.0.txt',
  50. ]
  51. try {
  52. const runtime = runtimeFixture(source)
  53. const modules = join(source, 'node_modules')
  54. for (const path of [...removed, ...retained]) {
  55. mkdirSync(join(modules, path, '..'), { recursive: true })
  56. writeFileSync(join(modules, path), `payload:${path}`)
  57. }
  58. cpSync(modules, join(output, 'node_modules'), {
  59. recursive: true, dereference: true,
  60. filter: path => desktopRuntimeFileExclusion(relative(modules, path), windows, 'win32-x64') === undefined,
  61. })
  62. for (const path of removed) expect(existsSync(join(output, 'node_modules', path)), path).toBe(false)
  63. for (const path of retained) expect(readFileSync(join(output, 'node_modules', path), 'utf8'), path).toBe(`payload:${path}`)
  64. const sealed = writeDesktopRuntime(output, runtime.release, runtime.sharedPackages.map(entry => entry.name))
  65. expect(await verifyDesktopRuntime(output, runtime.release.version)).toEqual(sealed)
  66. expect(readFileSync(join(modules, removed[0]!), 'utf8')).toBe(`payload:${removed[0]}`)
  67. } finally {
  68. rmSync(root, { recursive: true, force: true })
  69. }
  70. })
  71. it('applies package-specific rules inside scoped and nested dependency containers', () => {
  72. expect(desktopRuntimeFileExclusion('outer/node_modules/@mixmark-io/domino/test/data.html', windows, 'win32-x64')).toBeDefined()
  73. expect(desktopRuntimeFileExclusion('outer\\node_modules\\node-pty\\prebuilds\\win32-arm64\\conpty.node', windows, 'win32-x64')).toBeDefined()
  74. expect(desktopRuntimeFileExclusion('outer/node_modules/unrelated/test/data.html', windows, 'win32-x64')).toBeUndefined()
  75. expect(desktopRuntimeFileExclusion('outer/fs-ext/build/Release/fs_ext.lib', windows, 'win32-x64')).toBeUndefined()
  76. })
  77. it('retains native prebuilds for the selected macOS architecture', () => {
  78. const mac = { platform: 'darwin' as const, arch: 'arm64' }
  79. expect(desktopRuntimeFileExclusion('node-pty/prebuilds/darwin-arm64/pty.node', mac, 'darwin-arm64')).toBeUndefined()
  80. expect(desktopRuntimeFileExclusion('node-pty/prebuilds/darwin-x64/pty.node', mac, 'darwin-arm64')).toBeDefined()
  81. expect(desktopRuntimeFileExclusion('node-pty/prebuilds/win32-x64/conpty.node', mac, 'darwin-arm64')).toBeDefined()
  82. })
  83. it.each([
  84. ['linux', 'x64', 'linux-x64'],
  85. ['linux', 'arm64', 'wasm'],
  86. ['freebsd', 'x64', 'wasm'],
  87. ] as const)('retains only the selected Office engine for %s/%s', (platform, arch, engine) => {
  88. for (const candidate of ['linux-x64', 'darwin-arm64', 'wasm']) {
  89. const omitted = desktopRuntimeFileExclusion(
  90. `@deepseek-ai/libreoffice-kit-${candidate}/prebuilds.json`, { platform, arch }, engine,
  91. )
  92. expect(omitted === undefined).toBe(candidate === engine)
  93. }
  94. })