npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ganwei-web/plugin-runtime

v0.0.14

Published

可视化平台自定义插件独立运行依赖包

Readme

@ganwei-web/plugin-runtime - 可视化平台插件独立运行依赖包

概述

@ganwei-web/plugin-runtime 是一个轻量级的运行时依赖包,用于支持可视化平台自定义插件�?独立开发和调试*。它提供了:

  • �?shared-lib 兼容�?BaseComponent 和服务接�?- 模拟�?Node/Topology 数据模型
  • 独立的开发调试服务器组件
  • 插件项目脚手架生成器

核心优势

  1. 无需完整项目:外部开发者只需获得此依赖包,无需访问核心框架代码
  2. 独立运行:插件可以脱离主项目独立开发、调试和预览
  3. 接口兼容:与主项目的 shared-lib 接口保持一致,接入时无需修改业务代码
  4. 模拟数据:内置数据源�?SignalR 模拟,支持完整的交互调试

安装

npm install @ganwei-web/plugin-runtime

使用方式

方式一:使�?Schematics 生成独立插件项目(推荐)

  1. 安装 Angular CLI �?Schematics�?```bash npm install -g @angular/[email protected]

2. 生成独立插件项目�?```bash
ng g @ganwei-web/plugin-runtime:standalone-plugin plugin-my-component
  1. 进入项目并安装依赖:
cd plugin-my-component
npm install
  1. 启动开发服务器�?```bash npm run dev

### 方式二:手动集成到现有插�?
1. 在现有插件项目中安装依赖�?```bash
npm install @ganwei-web/plugin-runtime
  1. 修改导入路径�?```typescript // 原导入(主项目运行时�?import { BaseComponent, StyleService } from 'shared-lib'; import { Node } from '@topology/core';

// 新导入(独立运行时) import { BaseComponent, StyleService } from '@ganwei-web/plugin-runtime'; import { Node } from '@ganwei-web/plugin-runtime';


3. �?`app.component.ts` 中使用开发服务器�?```typescript
import { Component } from '@angular/core';
import { PluginDevServerComponent } from '@ganwei-web/plugin-runtime';
import { MyPluginComponent } from './component/my-plugin.component';

@Component({
  selector: 'app-root',
  template: `
    <plugin-dev-server
      [pluginComponent]="pluginComponent"
      [initialPen]="initialPen"
      [mockData]="mockData">
    </plugin-dev-server>
  `
})
export class AppComponent {
  pluginComponent = MyPluginComponent;

  initialPen = {
    rect: { width: 400, height: 300 },
    datasourceId: 'test-datasource'
  };

  mockData = {
    value: 42,
    status: 'normal'
  };
}

API 参�?

BaseComponent

�?shared-lib 中的 BaseComponent 接口完全一致:

export abstract class BaseComponent {
  @Input() pen: Node;
  @Input() canvas: Topology;
  @Input() isWorkspace: boolean;
  @Input() visible: boolean;
  style: any;

  abstract getStyle(): void;
  abstract handleSignalrData(data: ISignalrData): void;
  abstract handleDatasource(data: any): void;
}

服务

StyleService

  • getBBox(node, canvas) - 获取元素边界框样�?- getFont(node) - 获取字体样式
  • getBackground(node) - 获取背景样式
  • getBorder(node) - 获取边框样式
  • getShadow(node) - 获取阴影样式

DatasourceService

  • sendInitialValue - BehaviorSubject,数据源初始�?- dataSourceDataMap - Map,数据源数据缓存
  • setMockData(guid, data) - 设置模拟数据

RefreshService

  • refreshNode - BehaviorSubject,刷新节点事�?- refresh(nodeId) - 触发节点刷新

SignalrDataService

  • signalrData - BehaviorSubject,SignalR数据
  • emit(data) - 发送模拟数�?

开发调试组�?

PluginDevServerComponent

独立开发服务器的核心组件,提供�?- 插件渲染区域

  • 刷新按钮
  • 模拟数据注入
  • SignalR数据模拟
  • 当前 Pen 属性查�? 输入属性:
  • pluginComponent - 要调试的插件组件�?- initialPen - 初始 Pen 属性(可选)
  • mockData - 初始模拟数据(可选)

项目结构

plugin-runtime/
├── src/
�?  ├── models/
�?  �?  ├── node.model.ts      # Node/Pen 数据模型
�?  �?  └── topology.model.ts  # Topology 接口
�?  ├── services/
�?  �?  ├── style.service.ts   # 样式服务
�?  �?  ├── datasource.service.ts  # 数据源服�?�?  �?  ├── refresh.service.ts     # 刷新服务
�?  �?  └── signalr-data.service.ts # SignalR服务
�?  ├── mock/
�?  �?  ├── pen.mock.ts        # Pen 模拟数据生成�?�?  �?  └── canvas.mock.ts     # Canvas 模拟�?�?  ├── dev-server/
�?  �?  └── plugin-dev-server.component.ts  # 开发调试服务器
�?  ├── base.component.ts      # 基础组件
�?  └── public-api.ts          # 公共导出
├── schematics/
�?  └── standalone-plugin/     # 独立插件脚手�?└── package.json

接入主项目流�?

  1. **独立开发阶�?*:使�?@ganwei-web/plugin-runtime 开发调�?2. 代码迁移:将 src/app/component/ 下的组件代码复制到主项目�?plugins/<plugin-name>/src/app/component/
  2. 导入替换:将 @ganwei-web/plugin-runtime 替换�?shared-lib
  3. 构建打包:使用主项目�?ng build <plugin-name> 命令打包

导入映射对照�?

| 独立运行�?| 主项目运行时 | |-----------|------------| | @ganwei-web/plugin-runtime | shared-lib | | @ganwei-web/plugin-runtime (Node) | @topology/core |

注意事项

  1. **不要修改运行时源�?@ganwei-web/plugin-runtime 是公共依赖,修改会影响所有插�?2. **保持接口一�?:独立运行时开发的插件,接入主项目时只需修改导入路径
  2. 模拟数据:独立运行时的数据源�?SignalR 都是模拟的,接入后会使用真实数据
  3. 样式兼容StyleService 提供的样式与主项目完全一�?

开发示�?

完整插件组件示例

import { Component, Input, ChangeDetectorRef, NgZone } from '@angular/core';
import { Node, BaseComponent, StyleService, RefreshService, SignalrDataService, DatasourceService } from '@ganwei-web/plugin-runtime';

interface IMyPluginExtendKeys {
  title?: string;
  showValue?: boolean;
}

@Component({
  selector: 'app-plugin-my',
  template: `
    <div [ngStyle]="style" class="my-plugin">
      <h3>{{ pen.title || '默认标题' }}</h3>
      <div *ngIf="pen.showValue" class="value">{{ dataValue }}</div>
    </div>
  `,
  styles: [`
    .my-plugin {
      padding: 10px;
      h3 { margin: 0 0 10px; }
      .value { font-size: 24px; color: #1890ff; }
    }
  `]
})
export class PluginMyComponent extends BaseComponent {
  @Input() pen: Node & IMyPluginExtendKeys;
  dataValue: any = '--';

  constructor(
    cdr: ChangeDetectorRef,
    refreshService: RefreshService,
    signalrDataService: SignalrDataService,
    styleService: StyleService,
    datasourceService: DatasourceService,
    ngZone: NgZone
  ) {
    super(cdr, styleService, refreshService, signalrDataService, datasourceService, ngZone);
  }

  getStyle() {
    this.style = {
      ...this.styleService.getBBox(this.pen, this.canvas),
      ...this.styleService.getFont(this.pen),
      ...this.styleService.getBackground(this.pen),
      ...this.styleService.getBorder(this.pen)
    };
  }

  handleSignalrData(data: any) {
    console.log('实时数据:', data);
  }

  handleDatasource(data: any) {
    this.dataValue = data?.value ?? '--';
    this.cdr.detectChanges();
  }
}

许可�?

MIT