fix(plugin-sdk,server-*): type mismatch
This commit is contained in:
@@ -38,6 +38,7 @@ export default defineConfig({
|
||||
// Thanks to [@Maqsyo](https://github.com/Maqsyo)
|
||||
// https://github.com/alex8088/electron-vite/issues/99#issuecomment-1862671727
|
||||
base: './',
|
||||
|
||||
build: {
|
||||
rolldownOptions: {
|
||||
input: {
|
||||
@@ -46,6 +47,7 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
optimizeDeps: {
|
||||
exclude: [
|
||||
// Internal Packages
|
||||
@@ -74,6 +76,7 @@ export default defineConfig({
|
||||
'@framework/model/cubismmoc',
|
||||
],
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'@proj-airi/server-sdk': resolve(join(import.meta.dirname, '..', '..', 'packages', 'server-sdk', 'src')),
|
||||
@@ -83,6 +86,7 @@ export default defineConfig({
|
||||
'@proj-airi/stage-shared': resolve(join(import.meta.dirname, '..', '..', 'packages', 'stage-shared', 'src')),
|
||||
},
|
||||
},
|
||||
|
||||
server: {
|
||||
warmup: {
|
||||
clientFiles: [
|
||||
@@ -91,6 +95,7 @@ export default defineConfig({
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
worker: {
|
||||
format: 'es',
|
||||
rollupOptions: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ContextInit } from '../../apis/plugin/shared'
|
||||
import type { ContextInit } from '../../plugin/shared'
|
||||
|
||||
export async function init(_initContext: ContextInit) {
|
||||
return false
|
||||
|
||||
@@ -23,16 +23,19 @@ import {
|
||||
matchesDestinations,
|
||||
} from './middlewares'
|
||||
|
||||
function createServerEventMetadata(serverInstanceId: string, parentId?: string) {
|
||||
function createServerEventMetadata(serverInstanceId: string, parentId?: string): { source: MetadataEventSource, event: { id: string, parentId?: string } } {
|
||||
return {
|
||||
event: {
|
||||
id: nanoid(),
|
||||
parentId,
|
||||
},
|
||||
source: {
|
||||
plugin: WebSocketEventSource.Server,
|
||||
instanceId: serverInstanceId,
|
||||
version: packageJSON.version,
|
||||
kind: 'plugin',
|
||||
plugin: {
|
||||
id: WebSocketEventSource.Server,
|
||||
version: packageJSON.version,
|
||||
},
|
||||
id: serverInstanceId,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -160,6 +163,24 @@ export function setupApp(options?: {
|
||||
}
|
||||
}
|
||||
|
||||
function listKnownModules() {
|
||||
return Array.from(peers.values())
|
||||
.filter(peerInfo => peerInfo.name && peerInfo.identity)
|
||||
.map(peerInfo => ({
|
||||
name: peerInfo.name,
|
||||
index: peerInfo.index,
|
||||
identity: peerInfo.identity!,
|
||||
}))
|
||||
}
|
||||
|
||||
function sendRegistrySync(peer: Peer, parentId?: string) {
|
||||
send(peer, {
|
||||
type: 'registry:modules:sync',
|
||||
data: { modules: listKnownModules() },
|
||||
metadata: createServerEventMetadata(instanceId, parentId),
|
||||
})
|
||||
}
|
||||
|
||||
app.get('/ws', defineWebSocketHandler({
|
||||
open: (peer) => {
|
||||
if (authToken) {
|
||||
@@ -168,6 +189,7 @@ export function setupApp(options?: {
|
||||
else {
|
||||
peer.send(RESPONSES.authenticated)
|
||||
peers.set(peer.id, { peer, authenticated: true, name: '', lastHeartbeatAt: Date.now() })
|
||||
sendRegistrySync(peer)
|
||||
}
|
||||
|
||||
logger.withFields({ peer: peer.id, activePeers: peers.size }).log('connected')
|
||||
@@ -228,6 +250,8 @@ export function setupApp(options?: {
|
||||
p.authenticated = true
|
||||
}
|
||||
|
||||
sendRegistrySync(peer, event.metadata?.event.id)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -253,6 +277,11 @@ export function setupApp(options?: {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!identity || identity.kind !== 'plugin' || !identity.plugin?.id) {
|
||||
send(peer, RESPONSES.error('module identity must include kind=plugin and a plugin id for event \'module:announce\'', instanceId))
|
||||
|
||||
return
|
||||
}
|
||||
if (authToken && !p.authenticated) {
|
||||
send(peer, RESPONSES.error('must authenticate before announcing', instanceId))
|
||||
|
||||
@@ -271,7 +300,15 @@ export function setupApp(options?: {
|
||||
}
|
||||
|
||||
case 'ui:configure': {
|
||||
const { moduleName, moduleIndex, config } = event.data
|
||||
const data = event.data as {
|
||||
moduleName?: string
|
||||
moduleIndex?: number
|
||||
identity?: MetadataEventSource
|
||||
config?: Record<string, unknown>
|
||||
}
|
||||
const moduleName = data.moduleName ?? data.identity?.plugin?.id ?? ''
|
||||
const moduleIndex = data.moduleIndex
|
||||
const config = data.config
|
||||
|
||||
if (moduleName === '') {
|
||||
send(peer, RESPONSES.error('the field \'moduleName\' can\'t be empty for event \'ui:configure\'', instanceId))
|
||||
|
||||
@@ -19,7 +19,7 @@ function createPeer(options: {
|
||||
authenticated: true,
|
||||
name: options.name,
|
||||
identity: options.plugin && options.instanceId
|
||||
? { plugin: options.plugin, instanceId: options.instanceId, labels: options.labels }
|
||||
? { kind: 'plugin', plugin: { id: options.plugin }, id: options.instanceId, labels: options.labels }
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ function createSparkNotifyEvent(overrides: Partial<WebSocketEventOf<'spark:notif
|
||||
type: 'spark:notify',
|
||||
data,
|
||||
metadata: overrides.metadata ?? {
|
||||
source: { plugin: 'server-runtime', instanceId: 'test' },
|
||||
source: { kind: 'plugin', plugin: { id: 'server-runtime' }, id: 'test' },
|
||||
event: { id: data.id },
|
||||
},
|
||||
route: overrides.route,
|
||||
|
||||
@@ -25,22 +25,31 @@ export interface RouteContext {
|
||||
|
||||
export type RouteMiddleware = (context: RouteContext) => RouteDecision | void
|
||||
|
||||
function getPeerLabels(peer: AuthenticatedPeer) {
|
||||
return {
|
||||
...peer.identity?.plugin?.labels,
|
||||
...peer.identity?.labels,
|
||||
}
|
||||
}
|
||||
|
||||
export function isDevtoolsPeer(peer: AuthenticatedPeer) {
|
||||
const devtoolsLabel = peer.identity?.labels?.devtools
|
||||
const devtoolsLabel = getPeerLabels(peer).devtools
|
||||
const isDevtoolsLabel = devtoolsLabel === 'true' || devtoolsLabel === '1'
|
||||
return Boolean(isDevtoolsLabel || peer.name.includes('devtools'))
|
||||
}
|
||||
|
||||
export function peerMatchesPolicy(peer: AuthenticatedPeer, policy: RoutingPolicy) {
|
||||
if (policy.allowPlugins?.length && !policy.allowPlugins.includes(peer.identity?.plugin ?? '')) {
|
||||
const pluginId = peer.identity?.plugin?.id ?? ''
|
||||
|
||||
if (policy.allowPlugins?.length && !policy.allowPlugins.includes(pluginId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (policy.denyPlugins?.length && policy.denyPlugins.includes(peer.identity?.plugin ?? '')) {
|
||||
if (policy.denyPlugins?.length && policy.denyPlugins.includes(pluginId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const labels = peer.identity?.labels ?? {}
|
||||
const labels = getPeerLabels(peer)
|
||||
if (policy.allowLabels?.length && !matchesLabelSelectors(policy.allowLabels, labels)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@ export function matchesLabelSelectors(selectors: string[], labels: Record<string
|
||||
return selectors.every(selector => matchesLabelSelector(selector, labels))
|
||||
}
|
||||
|
||||
function getPeerLabels(peer: AuthenticatedPeer) {
|
||||
return {
|
||||
...peer.identity?.plugin?.labels,
|
||||
...peer.identity?.labels,
|
||||
}
|
||||
}
|
||||
|
||||
export function matchesRouteExpression(expression: RouteTargetExpression, peer: AuthenticatedPeer) {
|
||||
switch (expression.type) {
|
||||
case 'and':
|
||||
@@ -40,9 +47,10 @@ export function matchesRouteExpression(expression: RouteTargetExpression, peer:
|
||||
case 'or':
|
||||
return expression.any.some(expr => matchesRouteExpression(expr, peer))
|
||||
case 'glob': {
|
||||
const pluginId = peer.identity?.plugin?.id
|
||||
const matched = matchesGlob(expression.glob, peer.name)
|
||||
|| matchesGlob(expression.glob, peer.identity?.plugin)
|
||||
|| matchesGlob(expression.glob, peer.identity?.instanceId)
|
||||
|| matchesGlob(expression.glob, pluginId)
|
||||
|| matchesGlob(expression.glob, peer.identity?.id)
|
||||
|
||||
return expression.inverted ? !matched : matched
|
||||
}
|
||||
@@ -51,15 +59,15 @@ export function matchesRouteExpression(expression: RouteTargetExpression, peer:
|
||||
return expression.inverted ? !matched : matched
|
||||
}
|
||||
case 'plugin': {
|
||||
const matched = expression.plugins.includes(peer.identity?.plugin ?? '')
|
||||
const matched = expression.plugins.includes(peer.identity?.plugin?.id ?? '')
|
||||
return expression.inverted ? !matched : matched
|
||||
}
|
||||
case 'instance': {
|
||||
const matched = expression.instances.includes(peer.identity?.instanceId ?? '')
|
||||
const matched = expression.instances.includes(peer.identity?.id ?? '')
|
||||
return expression.inverted ? !matched : matched
|
||||
}
|
||||
case 'label': {
|
||||
const matched = matchesLabelSelectors(expression.selectors, peer.identity?.labels ?? {})
|
||||
const matched = matchesLabelSelectors(expression.selectors, getPeerLabels(peer))
|
||||
return expression.inverted ? !matched : matched
|
||||
}
|
||||
case 'module': {
|
||||
@@ -89,21 +97,23 @@ export function matchesDestination(destination: string | RouteTargetExpression,
|
||||
|
||||
switch (prefix) {
|
||||
case 'plugin':
|
||||
return peer.identity?.plugin === value
|
||||
return peer.identity?.plugin?.id === value
|
||||
case 'instance':
|
||||
return peer.identity?.instanceId === value
|
||||
return peer.identity?.id === value
|
||||
case 'label':
|
||||
return matchesLabelSelectors([value], peer.identity?.labels ?? {})
|
||||
return matchesLabelSelectors([value], getPeerLabels(peer))
|
||||
case 'peer':
|
||||
return peer.peer.id === value
|
||||
case 'module':
|
||||
return peer.name === value
|
||||
case 'source':
|
||||
return peer.name === value
|
||||
default:
|
||||
default: {
|
||||
const pluginId = peer.identity?.plugin?.id
|
||||
return matchesGlob(destination, peer.name)
|
||||
|| matchesGlob(destination, peer.identity?.plugin)
|
||||
|| matchesGlob(destination, peer.identity?.instanceId)
|
||||
|| matchesGlob(destination, pluginId)
|
||||
|| matchesGlob(destination, peer.identity?.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,8 @@ export class Client<C = undefined> {
|
||||
onAnyMessage: () => {},
|
||||
onAnySend: () => {},
|
||||
possibleEvents: [],
|
||||
dependencies: [],
|
||||
configSchema: undefined,
|
||||
onError: () => {},
|
||||
onClose: () => {},
|
||||
autoConnect: true,
|
||||
|
||||
@@ -708,6 +708,10 @@ interface ModuleStatusChangeEvent {
|
||||
details?: Record<string, unknown>
|
||||
}
|
||||
|
||||
interface ModuleConfigureEvent<C = undefined> {
|
||||
config: C | Record<string, unknown>
|
||||
}
|
||||
|
||||
interface UiConfigureEvent<C = undefined> {
|
||||
moduleName: string
|
||||
moduleIndex?: number
|
||||
@@ -845,6 +849,8 @@ export const moduleContributeCapabilityActivated = defineEventa<ModuleContribute
|
||||
|
||||
export const moduleStatusChange = defineEventa<ModuleStatusChangeEvent>('module:status:change')
|
||||
|
||||
export const moduleConfigure = defineEventa<ModuleConfigureEvent>('module:configure')
|
||||
|
||||
export const uiConfigure = defineEventa<UiConfigureEvent>('ui:configure')
|
||||
|
||||
export const inputText = defineEventa<WebSocketEventInputText>('input:text')
|
||||
@@ -953,6 +959,10 @@ export interface WebSocketEvents<C = undefined> {
|
||||
* Request a phase transition (module → host).
|
||||
*/
|
||||
'module:status:change': ModuleStatusChangeEvent
|
||||
/**
|
||||
* Push configuration down to module (host → module).
|
||||
*/
|
||||
'module:configure': ModuleConfigureEvent<C>
|
||||
|
||||
'ui:configure': UiConfigureEvent<C>
|
||||
|
||||
|
||||
@@ -10,7 +10,10 @@ function formatMetadataSource(source?: MetadataEventSource) {
|
||||
if (!source?.plugin)
|
||||
return undefined
|
||||
|
||||
return source.instanceId ? `${source.plugin}:${source.instanceId}` : source.plugin
|
||||
const pluginId = source.plugin.id
|
||||
const instanceId = source.id
|
||||
|
||||
return instanceId ? `${pluginId}:${instanceId}` : pluginId
|
||||
}
|
||||
|
||||
export function getEventSourceKey(event: EventSourcePayload, fallback = 'unknown') {
|
||||
|
||||
@@ -28,9 +28,12 @@ export function createClientState(): ClientState {
|
||||
|
||||
function createIdentity() {
|
||||
return {
|
||||
plugin: PLUGIN_NAME,
|
||||
instanceId: nanoid(),
|
||||
version: typeof packageJSON.version === 'string' ? packageJSON.version : undefined,
|
||||
kind: 'plugin',
|
||||
plugin: {
|
||||
id: PLUGIN_NAME,
|
||||
version: typeof packageJSON.version === 'string' ? packageJSON.version : undefined,
|
||||
},
|
||||
id: nanoid(),
|
||||
labels: {
|
||||
runtime: 'web-extension',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user