import Database from 'better-sqlite3'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; import { newFixture, type Fixture } from '../helpers/fixture.js'; import { migrateVersionLayout } from '../../src/lib/server/db/version-layout.js'; let fixture: Fixture; beforeEach(async () => { vi.resetModules(); fixture = await newFixture([]); }); afterEach(async () => { vi.restoreAllMocks(); await fixture.cleanup(); }); it('returns metadata without plugin bytes and lists many artifacts in two queries', async () => { const { createScript, getVersion, getVersionContent, getLatestVersion, listVersions } = await import('../../src/lib/server/fleet/scripts.js'); const { scriptCatalog, betaScriptMetadata } = await import('../../src/lib/server/fleet/library-metadata.js'); const { db } = await import('../../src/lib/server/db/index.js'); const content = Buffer.alloc(1024 * 1024, 77); let id = 0; for (let i = 0; i < 20; i++) id = createScript({ name: `plugin-${i}`, kind: 'plugin', targetRelPath: 'plugin.dll', content }).version.id; expect(getVersionContent(id)).toEqual(content); expect(getVersion(id)).not.toHaveProperty('content'); expect(getLatestVersion(getVersion(id)!.script_id)).not.toHaveProperty('content'); expect(listVersions(getVersion(id)!.script_id)[0]).not.toHaveProperty('content'); const prepare = vi.spyOn(db(), 'prepare'); expect(scriptCatalog('plugin')).toHaveLength(20); expect(prepare).toHaveBeenCalledTimes(2); betaScriptMetadata([]); expect(prepare.mock.calls.every(([sql]) => !/\bcontent\b/.test(sql))).toBe(true); }); it('moves legacy content last without losing bytes, IDs, indexes, triggers or references', () => { const handle = new Database(':memory:'); try { handle.exec(`PRAGMA foreign_keys=ON; CREATE TABLE script_versions(id INTEGER PRIMARY KEY AUTOINCREMENT, script_id INTEGER, version INTEGER, content BLOB NOT NULL, state TEXT, release_version TEXT, UNIQUE(script_id,version)); CREATE INDEX version_state ON script_versions(state); CREATE TABLE child(version INTEGER REFERENCES script_versions(id)); CREATE TABLE updates(n INTEGER); INSERT INTO updates VALUES(0); CREATE TRIGGER version_update AFTER UPDATE ON script_versions BEGIN UPDATE updates SET n=n+1; END; INSERT INTO script_versions VALUES(7,1,1,x'00ff','tested','v1'); INSERT INTO child VALUES(7); INSERT INTO script_versions VALUES(100,1,2,x'aa','untested',NULL); DELETE FROM script_versions WHERE id=100;`); const before = handle.prepare('SELECT * FROM script_versions').all(); migrateVersionLayout(handle); migrateVersionLayout(handle); expect(handle.prepare('SELECT * FROM script_versions').all()).toEqual(before); expect( (handle.pragma('table_info(script_versions)') as { name: string }[]).at(-1)?.name ).toBe('content'); expect(handle.pragma('foreign_key_check')).toEqual([]); expect( handle .prepare("INSERT INTO script_versions(script_id,version,content) VALUES(1,3,x'01')") .run().lastInsertRowid ).toBe(101); handle.prepare("UPDATE script_versions SET state='tested' WHERE id=101").run(); expect(handle.prepare('SELECT n FROM updates').get()).toEqual({ n: 1 }); expect( (handle.pragma('index_list(script_versions)') as { name: string }[]).some( (index) => index.name === 'version_state' ) ).toBe(true); } finally { handle.close(); } });