[READ-ONLY] Mirror of https://github.com/danielroe/cross-origin-storage. Load shared dependencies from Cross-Origin Storage (COS).
cross-origin-storage experimental nuxt vite vite-plugin
0

Configure Feed

Select the types of activity you want to include in your feed.

1import { createHash } from 'node:crypto' 2import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync, globSync } from 'node:fs' 3import { fileURLToPath } from 'node:url' 4import { join } from 'node:path' 5import { afterAll, beforeAll, describe, expect, it } from 'vitest' 6import { build } from 'vite' 7import { cosPlugin } from '../src/vite' 8 9// Build inside the project tree so the fixture resolves `vue` from the project 10// node_modules rather than a detached temp dir. 11const scratchRoot = fileURLToPath(new URL('./.plugin-scratch', import.meta.url)) 12const nodeModules = fileURLToPath(new URL('../node_modules', import.meta.url)) 13const vueEntry = globSync('.pnpm/vue@*/node_modules/vue/dist/vue.runtime.esm-bundler.js', { cwd: nodeModules })[0]! 14 15describe('cosPlugin (standalone vite build)', () => { 16 let root: string 17 let outDir: string 18 let assetsDir: string 19 20 beforeAll(async () => { 21 mkdirSync(scratchRoot, { recursive: true }) 22 root = mkdtempSync(join(scratchRoot, 'app-')) 23 outDir = join(root, 'dist') 24 assetsDir = join(outDir, 'assets') 25 mkdirSync(join(root, 'src'), { recursive: true }) 26 writeFileSync( 27 join(root, 'index.html'), 28 '<!doctype html><html><head></head><body><script type="module" src="/src/main.js"></script></body></html>', 29 ) 30 writeFileSync(join(root, 'src/main.js'), 'import { ref } from "vue"\ndocument.body.dataset.count = String(ref(0).value)\n') 31 32 await build({ 33 root, 34 logLevel: 'error', 35 // The fixture lives in a scratch dir; point bare `vue` at the project copy. 36 resolve: { alias: { vue: join(nodeModules, vueEntry) } }, 37 plugins: [cosPlugin({ packages: [/^(?:vue$|@vue\/)/] })], 38 build: { outDir, emptyOutDir: true, rollupOptions: { input: join(root, 'index.html') } }, 39 }) 40 }, 120_000) 41 42 afterAll(() => { 43 rmSync(scratchRoot, { recursive: true, force: true }) 44 }) 45 46 function cosChunks(): string[] { 47 return readdirSync(assetsDir).filter(f => /^[a-f0-9]{64}\.js$/.test(f)) 48 } 49 50 it('emits content-addressed chunks whose names match their bytes', () => { 51 expect(cosChunks().length).toBeGreaterThanOrEqual(1) 52 for (const file of cosChunks()) { 53 const hash = createHash('sha256').update(readFileSync(join(assetsDir, file))).digest('hex') 54 expect(hash).toBe(file.replace('.js', '')) 55 } 56 }) 57 58 it('rewrites managed imports to content-addressed specifiers', () => { 59 for (const file of cosChunks()) { 60 const code = readFileSync(join(assetsDir, file), 'utf8') 61 const specifiers = [...code.matchAll(/(?:from|import)\s*["']([^"']+)["']/g)].map(m => m[1]!) 62 for (const specifier of specifiers) { 63 expect(specifier).toMatch(/^cos1:[a-f0-9]{64}$/) 64 } 65 } 66 }) 67 68 it('injects the loader into index.html and removes the default entry script', () => { 69 const html = readFileSync(join(outDir, 'index.html'), 'utf8') 70 expect(html).toContain('<script id="cos-loader">') 71 expect(html).toMatch(/cos1:[a-f0-9]{64}/) 72 expect(html).not.toMatch(/<script type="module"[^>]*src="[^"]*\.js"/) 73 }) 74 75 it('derives the base path from the vite config', () => { 76 const html = readFileSync(join(outDir, 'index.html'), 'utf8') 77 expect(html).toMatch(/"base":"\/assets\/"/) 78 }) 79})