chore: export basic types (#1692)

This commit is contained in:
chilingling 2025-11-03 10:10:27 +08:00 committed by GitHub
parent 67e613f399
commit ce6f4a7d46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 320 additions and 50 deletions

View File

@ -4,6 +4,7 @@
"description": "",
"main": "dist/index.mjs",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"type": "module",
"publishConfig": {
"access": "public"
@ -27,7 +28,8 @@
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"vite": "^5.4.2"
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4"
},
"peerDependencies": {
"@opentiny/vue": "^3.20.0",

View File

@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"include": ["./index.ts", "./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"]
}

View File

@ -14,9 +14,18 @@ import path from 'path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import vitePluginCssInjectedByJs from 'vite-plugin-css-injected-by-js'
import dts from 'vite-plugin-dts'
export default defineConfig({
plugins: [vue(), vueJsx(), vitePluginCssInjectedByJs()],
plugins: [
vue(),
vueJsx(),
vitePluginCssInjectedByJs(),
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
})
],
publicDir: false,
build: {
sourcemap: true,

View File

@ -15,6 +15,7 @@
"type": "module",
"main": "dist/lowcode-design-i18n-host.umd.js",
"module": "dist/lowcode-design-i18n-host.es.js",
"types": "dist/lowcode-design-i18n-host.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/opentiny/tiny-engine",
@ -28,7 +29,8 @@
"homepage": "https://opentiny.design/tiny-engine",
"devDependencies": {
"@vitejs/plugin-vue": "^5.1.2",
"vite": "^5.4.2"
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4"
},
"peerDependencies": {
"vue": "^3.4.15",

View File

@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.base.json",
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"],
"exclude": ["./src/test"]
}

View File

@ -12,9 +12,14 @@
import vue from '@vitejs/plugin-vue'
import path from 'path'
import dts from 'vite-plugin-dts'
export default {
plugins: [
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
}),
vue({
template: {
compilerOptions: {

View File

@ -5,6 +5,7 @@
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"author": "OpenTiny Team",
"license": "MIT",
"bugs": {
@ -32,6 +33,7 @@
},
"devDependencies": {
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^1.4.0"
},
"keywords": []

View File

@ -85,7 +85,7 @@ const registryApiAndOptionsMap = (id: string, value: any) => {
}
}
const genDefaultHashMap = (registry: any) => {
const genDefaultHashMap = (registry: Record<string, any>) => {
Object.entries(registry).forEach(([key, value]) => {
if (typeof value === 'object' && value && !isRef(value)) {
const { id } = value

View File

@ -0,0 +1,116 @@
/**
*
*
*
* TODO: 当这些包完成类型导出后
*
*
* - @opentiny/tiny-engine-canvas
* - @opentiny/tiny-engine-layout
* - @opentiny/tiny-engine-plugin-* (block, datasource, help, i18n, materials, page, robot)
* - @opentiny/tiny-engine-setting-props
* - @opentiny/tiny-engine-toolbar-* (breadcrumb, generate-code, redoundo)
* - @opentiny/tiny-engine-common
*/
// Canvas API - 导出一个返回 API 对象的函数
declare module '@opentiny/tiny-engine-canvas/DesignCanvas/src/api' {
const useCanvasApi: () => Record<string, any>
export default useCanvasApi
}
// Layout Service - 导出包含 apis 属性的服务对象
declare module '@opentiny/tiny-engine-layout' {
export const LayoutService: {
apis: Record<string, any>
}
}
// Plugin: Block - 区块管理服务
declare module '@opentiny/tiny-engine-plugin-block' {
export const BlockService: {
apis: Record<string, any>
}
}
// Plugin: DataSource - 数据源管理服务
declare module '@opentiny/tiny-engine-plugin-datasource' {
export const DataSourceService: {
apis: Record<string, any>
}
}
// Plugin: Help - 帮助服务
declare module '@opentiny/tiny-engine-plugin-help' {
export const HelpService: {
apis: Record<string, any>
}
}
// Plugin: I18n - 国际化翻译服务
declare module '@opentiny/tiny-engine-plugin-i18n' {
export const TranslateService: {
apis: Record<string, any>
}
}
// Plugin: Materials - 物料管理服务(包含两个服务)
declare module '@opentiny/tiny-engine-plugin-materials' {
export const MaterialService: {
apis: Record<string, any>
}
export const ResourceService: {
apis: Record<string, any>
}
}
// Plugin: Page - 页面管理服务
declare module '@opentiny/tiny-engine-plugin-page' {
export const PageService: {
apis: Record<string, any>
}
}
// Plugin: Robot - AI 机器人服务
declare module '@opentiny/tiny-engine-plugin-robot' {
export const RobotService: {
apis: Record<string, any>
}
}
// Setting: Props - 属性配置服务(包含两个服务)
declare module '@opentiny/tiny-engine-setting-props' {
export const PropertiesService: {
apis: Record<string, any>
}
export const PropertyService: {
apis: Record<string, any>
}
}
// Toolbar: Breadcrumb - 面包屑导航服务
declare module '@opentiny/tiny-engine-toolbar-breadcrumb' {
export const BreadcrumbService: {
apis: Record<string, any>
}
}
// Toolbar: Generate Code - 代码生成和本地保存服务
declare module '@opentiny/tiny-engine-toolbar-generate-code' {
export const SaveLocalService: {
apis: Record<string, any>
}
}
// Toolbar: Redo/Undo - 历史记录服务
declare module '@opentiny/tiny-engine-toolbar-redoundo' {
export const HistoryService: {
apis: Record<string, any>
}
}
// Common - 通用工具Modal 和 Notify
declare module '@opentiny/tiny-engine-common' {
export const Modal: Record<string, any>
export const Notify: (...args: any[]) => any
}

View File

@ -18,3 +18,5 @@ export { getConfigurator, addConfigurator } from './configurators'
export * from './hooks'
export { META_APP, META_SERVICE } from './constants'
export { defineService, initServices } from './service'
export type { ServiceOptions } from './service'

View File

@ -48,15 +48,18 @@ export const defineService = <T, K>(serviceOptions: ServiceOptions<T, K>): Servi
id,
type,
options,
apis: {}
// 使用类型断言,因为 getState 和 setState 会在后面添加
apis: {} as any
}
const state = reactive<any>(initialState || {})
// 使用对象展开运算符合并 apis避免直接赋值导致类型错误
if (typeof apis === 'object' && apis) {
resultService.apis = apis
resultService.apis = apis as any
} else if (typeof apis === 'function') {
resultService.apis = apis({ state })
// 传递完整的 context 对象,包含 state 和 options
resultService.apis = apis({ state, options }) as any
}
resultService.apis.setOptions = (kv) => {

View File

@ -10,8 +10,66 @@
*
*/
let lastMessage: any = null
const subscribers: Record<string, any> = { '': {} }
// 消息事件类型,用于存储消息数据
interface MessageEvent<T = unknown> {
data: T
}
// 消息回调函数类型
type MessageCallback<T = unknown> = (data: T) => void
// 带有 lastEvent 属性的回调数组类型
interface CallbacksWithLastEvent<T = unknown> extends Array<MessageCallback<T>> {
lastEvent?: MessageEvent<T>
}
// 监听器映射类型topic -> callbacks
type ListenersMap = Record<string, CallbacksWithLastEvent>
// 订阅者映射类型subscriber -> listeners
type SubscribersMap = Record<string, ListenersMap>
// subscribe 函数参数接口
interface SubscribeOptions<T = unknown> {
topic?: string
subscriber?: string
callback?: MessageCallback<T>
}
// unsubscribe 函数参数接口
interface UnsubscribeOptions {
topic?: string
subscriber?: string
}
// publish 函数参数接口
interface PublishOptions<T = unknown> {
topic?: string
data?: T
}
// broadcast 函数参数接口topic 和 data 为必需参数)
interface BroadcastOptions<T = unknown> {
topic: string
data: T
}
// 订阅消息返回的描述符
interface MessageDescriptor {
topic: string | undefined
subscriber: string | undefined
}
// useMessage 钩子的返回值类型
interface UseMessageReturn {
subscribe: <T = unknown>(options?: SubscribeOptions<T>) => MessageDescriptor
unsubscribe: (options?: UnsubscribeOptions) => void
publish: <T = unknown>(options?: PublishOptions<T>) => void
broadcast: <T = unknown>(options: BroadcastOptions<T>) => void
}
let lastMessage: PublishOptions | null = null
const subscribers: SubscribersMap = { '': {} }
/**
*
@ -23,9 +81,9 @@ const subscribers: Record<string, any> = { '': {} }
* @param {Object} object { topic: 消息名称, subscriber(): , callback: 接收到消息之后的回调用函数 }
* @return {Object} { topic: 消息名称, subscriber: 消息集合 }
*/
const subscribe = ({ topic, subscriber, callback } = {}) => {
const root = subscribers['']
let listeners = root
const subscribe = <T = unknown>({ topic, subscriber, callback }: SubscribeOptions<T> = {}): MessageDescriptor => {
const root: ListenersMap = subscribers['']
let listeners: ListenersMap = root
if (topic && typeof topic === 'string' && typeof callback === 'function') {
if (subscriber && typeof subscriber === 'string') {
@ -33,13 +91,13 @@ const subscribe = ({ topic, subscriber, callback } = {}) => {
subscribers[subscriber] = listeners
}
const callbacks = listeners[topic] || []
const callbacks: CallbacksWithLastEvent<T> = (listeners[topic] as CallbacksWithLastEvent<T>) || []
listeners[topic] = callbacks
callbacks.push(callback)
const lastEvent = callbacks.lastEvent || root[topic]?.lastEvent
if (lastEvent) {
callback(lastEvent.data)
callback(lastEvent.data as T)
}
}
@ -61,9 +119,9 @@ const subscribe = ({ topic, subscriber, callback } = {}) => {
* @member TinyEditor.message
* @param {Object} object { topic: 消息名称, subscriber(): }
*/
const unsubscribe = ({ topic, subscriber } = {}) => {
const unsubscribe = ({ topic, subscriber }: UnsubscribeOptions = {}): void => {
if (topic && typeof topic === 'string') {
const removeListener = (subscriber) => {
const removeListener = (subscriber: string): void => {
const listeners = subscribers[subscriber]
if (listeners) {
delete listeners[topic]
@ -94,23 +152,23 @@ const unsubscribe = ({ topic, subscriber } = {}) => {
* @member TinyEditor.message
* @param {Object} object { topic: 消息名称, data(string | object): }
*/
const publish = ({ topic, data } = {}) => {
const publish = <T = unknown>({ topic, data }: PublishOptions<T> = {}): void => {
if (!topic || typeof topic !== 'string') {
return
}
for (const value of Object.values(subscribers)) {
const callbacks = value[topic] || []
const callbacks: CallbacksWithLastEvent<T> = (value[topic] as CallbacksWithLastEvent<T>) || []
if (callbacks.length) {
for (const cb of callbacks) {
cb(data)
cb(data as T)
}
} else {
value[topic] = callbacks
}
callbacks.lastEvent = { data }
callbacks.lastEvent = { data: data as T }
}
}
@ -123,7 +181,7 @@ const publish = ({ topic, data } = {}) => {
* @member TinyEditor.message
* @param {Object} object { topic: 消息名称, data(string | object): }
*/
const broadcast = ({ topic, data }) => {
const broadcast = <T = unknown>({ topic, data }: BroadcastOptions<T>): void => {
if (topic && typeof topic === 'string') {
lastMessage = { topic, data }
@ -131,7 +189,7 @@ const broadcast = ({ topic, data }) => {
}
}
export default () => {
export default (): UseMessageReturn => {
// 新use的message自动广播上次的异步消息
if (lastMessage) {
publish(lastMessage)

1
packages/register/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"]
}

View File

@ -12,10 +12,15 @@
import { defineConfig } from 'vite'
import path from 'path'
import dts from 'vite-plugin-dts'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [],
plugins: [
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
})
],
publicDir: false,
resolve: {},
build: {

View File

@ -10,6 +10,7 @@
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
@ -28,7 +29,8 @@
"@opentiny/tiny-engine-vite-plugin-meta-comments": "workspace:*",
"@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"vite": "^5.4.2"
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4"
},
"peerDependencies": {
"@opentiny/vue": "^3.20.0",

View File

@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"include": ["./index.ts", "./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"]
}

View File

@ -15,10 +15,19 @@ import path from 'path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import generateComment from '@opentiny/tiny-engine-vite-plugin-meta-comments'
import dts from 'vite-plugin-dts'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [generateComment(), vue(), vueJsx()],
plugins: [
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
}),
generateComment(),
vue(),
vueJsx()
],
publicDir: false,
resolve: {},
build: {

View File

@ -9,6 +9,7 @@
},
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
@ -24,6 +25,7 @@
"license": "MIT",
"homepage": "https://opentiny.design/tiny-engine",
"devDependencies": {
"vite": "^5.4.2"
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4"
}
}

View File

@ -0,0 +1,4 @@
{
"extends": "../../../tsconfig.base.json",
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"]
}

View File

@ -12,10 +12,17 @@
import { defineConfig } from 'vite'
import path from 'path'
import dts from 'vite-plugin-dts'
// https://vitejs.dev/config/
export default defineConfig({
publicDir: false,
plugins: [
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
})
],
build: {
sourcemap: true,
lib: {

View File

@ -8,6 +8,7 @@
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
@ -28,7 +29,9 @@
"license": "MIT",
"homepage": "https://opentiny.design/tiny-engine",
"devDependencies": {
"@types/wicg-file-system-access": "^2023.10.6",
"vite": "^5.4.2",
"vite-plugin-dts": "^4.5.4",
"vitest": "^1.4.0"
},
"dependencies": {

View File

@ -20,11 +20,10 @@ export const isSupportFileSystemAccess =
/**
*
* @param {*} options
* mode: 授权模式 e.g. 'readwrite'
* @param {*} options - showDirectoryPicker
* @returns dirHandle
*/
export const getUserBaseDirHandle = async (options = {}) => {
export const getUserBaseDirHandle = async (options: DirectoryPickerOptions = {}) => {
if (!isSupportFileSystemAccess) {
return createZip()
}
@ -76,15 +75,16 @@ export async function getFileHandle(baseDirHandle: any, filePath: string, { crea
/**
*
* @param {*} options
* mode: 授权模式 e.g. 'readwrite'
* @param {*} options - showOpenFilePicker
* @returns fileHandle
*/
export const getUserFileHandle = async (options = {}) => {
export const getUserFileHandle = async (options: OpenFilePickerOptions & { multiple?: false } = {}) => {
if (!isSupportFileSystemAccess) {
throw new Error('不支持的浏览器或处于iframe中')
}
const [fileHandle] = await window.showOpenFilePicker({ mode: 'readwrite', ...options })
const [fileHandle] = await window.showOpenFilePicker(options)
// 请求读写权限
await fileHandle.requestPermission({ mode: 'readwrite' })
return fileHandle
}

View File

@ -341,8 +341,8 @@ export const objectToArray = (obj, { keyTo = 'id', orderKey = '_order' }) => {
const arr = Object.entries(obj)
// 过滤掉非对象的值,防止后面展开对象失败
.filter(([, value]) => typeof value === 'object' && obj !== null)
.map(([key, value]) => ({ ...value, [keyTo]: key }))
.filter(([, value]) => typeof value === 'object' && value !== null && !Array.isArray(value))
.map(([key, value]) => ({ ...(value as Record<string, any>), [keyTo]: key }))
.map(({ [orderKey]: order, ...rest }) => ({ ...rest, [orderKey]: order ?? Number.MAX_SAFE_INTEGER }))
.sort((a, b) => a[orderKey] - b[orderKey])

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["@types/wicg-file-system-access"]
},
"include": ["./src/**/*.ts", "./src/**/*.tsx", "./src/**/*.vue"]
}

View File

@ -12,11 +12,18 @@
import { defineConfig } from 'vite'
import path from 'path'
import dts from 'vite-plugin-dts'
// https://vitejs.dev/config/
export default defineConfig({
publicDir: false,
resolve: {},
plugins: [
dts({
tsconfigPath: path.resolve(__dirname, './tsconfig.json'),
rollupTypes: true
})
],
build: {
sourcemap: true,
lib: {

View File

@ -1,18 +1,14 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"extends": ["@vue/tsconfig/tsconfig.dom.json", "./tsconfig.base.json"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"allowJs": true,
"baseUrl": "./",
"jsx": "react-jsx",
"paths": {
"@/*": ["packages/*"],
"@opentiny/tiny-engine": ["packages/design-core/index.js"],

18
tsconfig.base.json Normal file
View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"module": "ESNext",
"target": "ESNext",
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"emitDeclarationOnly": true,
"jsx": "preserve",
"useDefineForClassFields": true
}
}

View File

@ -1,17 +1,10 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */