mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 09:57:48 +00:00
* 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.
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
// @vitest-environment happy-dom
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
exportedTypeShape,
|
|
runtimeShape,
|
|
type TypingsShape
|
|
} from '../authoring/plugin-author-typings.test-fixture'
|
|
import { buildPluginGuestShellHtml, buildPluginPanelShellHtml } from './plugin-panel-shell'
|
|
|
|
/** The `window.orca` a frame shell defines, read without leaving it on the test window. */
|
|
function frameOrca(html: string): unknown {
|
|
const script = html.match(/<script>\n([\s\S]*?)<\/script>/)?.[1] ?? ''
|
|
const transport = { send: () => {}, subscribe: () => {} }
|
|
Object.defineProperty(window, '__orcaPluginFrameTransport', {
|
|
value: transport,
|
|
configurable: true
|
|
})
|
|
window.eval(script.replaceAll('configurable: false', 'configurable: true'))
|
|
const orca: unknown = Object.getOwnPropertyDescriptor(window, 'orca')?.value
|
|
Reflect.deleteProperty(window, 'orca')
|
|
return orca
|
|
}
|
|
|
|
function without(shape: TypingsShape, keys: string[]): TypingsShape {
|
|
return typeof shape === 'string'
|
|
? shape
|
|
: Object.fromEntries(Object.entries(shape).filter(([key]) => !keys.includes(key)))
|
|
}
|
|
|
|
const typings = exportedTypeShape('orca/frame', 'OrcaFrameApi')
|
|
|
|
describe('orca-frame.d.ts matches window.orca', () => {
|
|
it('declares every member an isolated editor frame gets', () => {
|
|
expect(runtimeShape(frameOrca(buildPluginGuestShellHtml('', 'editor')))).toEqual(typings.shape)
|
|
})
|
|
|
|
it('marks optional exactly what an iframe panel lacks', () => {
|
|
const panel = runtimeShape(frameOrca(buildPluginPanelShellHtml('', 'panel')))
|
|
const absent = ['shell', 'files', 'document']
|
|
expect(typings.optional.filter((name) => !name.includes('.')).sort()).toEqual(absent.sort())
|
|
expect(panel).toEqual(without(typings.shape, absent))
|
|
})
|
|
})
|