Files
orca/config/scripts/validate-plugin-files.test.mjs
T
Neil 4ee788a725 Build-less TS/TSX plugins, typings and authoring tools (#36918)
* feat(plugins): build-less TS/TSX plugins, typings and authoring tools

- Plugin frames transpile .ts/.tsx/.mts/.jsx on load (sucrase on a shared worker thread with a
  2 s budget, cached in main), resolve relative imports to exact files, and refuse bare
  package imports by name. Components and html panel/editor entries may be .ts/.tsx.
- orca plugin types writes typings for the components orca module, window.orca, worker
  activate(orca), host.call and events into .orca/types, from one host-typings generator.
- orca plugin create --template components; templates omit publisher and target 1.4.246.
- orca plugin release-entry, dev inspect and restart; validate:plugin checks named files.
- Guest console errors reach orca plugin logs; dev workers restart on edits; the dev watcher
  ignores .git, .orca and node_modules; Git and folder installs cannot replace catalog installs.
- examples/plugins/hello-tsx, docs, and the plugin-buildless-tsx e2e spec.

* ci: run the Windows parity probes with one tsgo checker

tsconfig.node peaks near 22 GB with tsgo's default four checkers (each holds its own types)
and about 16 GB with one; the 16 GB Windows runner paged the native probe past its 900 s
timeout once this branch's package.json change triggered the job. One checker gives the
same diagnostics (verified locally with --parity-only); the timing benchmark is unchanged.
2026-11-01 01:28:35 -08:00

55 lines
1.9 KiB
JavaScript

import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import process from 'node:process'
import { runProcess } from '@orca/process-host'
import { afterEach, describe, expect, it } from 'vitest'
import { createPluginFromTemplate } from '../../src/cli/plugin-authoring/plugin-create'
const SCRIPT = path.join(import.meta.dirname, 'validate-plugin-files.mjs')
const roots = []
async function tempRoot() {
const root = await mkdtemp(path.join(tmpdir(), 'orca-validate-plugin-files-'))
roots.push(root)
return root
}
afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })))
})
function validate(...targets) {
return runProcess({
program: process.execPath,
args: [SCRIPT, ...targets],
timeoutMs: 60_000
})
}
describe('validate-plugin-files', () => {
it('fails with exit 1 when a file the manifest names is missing', async () => {
const dir = path.join(await tempRoot(), 'panel')
await createPluginFromTemplate({ dir, template: 'panel', publisher: 'acme' })
await rm(path.join(dir, 'panel', 'index.html'))
const result = await validate(dir)
expect(result.code).toBe(1)
expect(result.stderr).toContain('panel/index.html')
}, 60_000)
it('passes a scaffolded plugin, explaining why there is no release entry outside Git', async () => {
const dir = path.join(await tempRoot(), 'dusk')
await createPluginFromTemplate({ dir, template: 'theme', publisher: 'acme' })
const result = await validate(dir)
expect(result.code, result.stderr).toBe(0)
expect(result.stdout).toContain('not in a Git repository')
}, 60_000)
it('exits 1 for a missing path and 2 without arguments', async () => {
const missing = await validate(path.join(await tempRoot(), 'nope'))
expect(missing.code).toBe(1)
expect(missing.stderr).toContain('does not exist')
expect((await validate()).code).toBe(2)
}, 60_000)
})