enhance(libs): types

This commit is contained in:
charlie
2025-01-09 14:22:30 +08:00
parent e83cb0ff86
commit 72c09e5c30
2 changed files with 83 additions and 67 deletions

View File

@@ -687,6 +687,8 @@ export interface IEditorProxy extends Record<string, any> {
*/
newBlockUUID: () => Promise<string>
isPageBlock: (block: BlockEntity | PageEntity) => Boolean
/**
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-reddit-hot-news
*

View File

@@ -37,6 +37,7 @@ import {
IAssetsProxy,
AppInfo,
IPluginSearchServiceHooks,
PageEntity,
} from './LSPlugin'
import Debug from 'debug'
import * as CSS from 'csstype'
@@ -64,7 +65,7 @@ const logger = new PluginLogger('', { console: true })
* @param opts
* @param action
*/
function registerSimpleCommand (
function registerSimpleCommand(
this: LSPluginUser,
type: string,
opts: {
@@ -109,7 +110,7 @@ function registerSimpleCommand (
})
}
function shouldValidUUID (uuid: string) {
function shouldValidUUID(uuid: string) {
if (!isValidUUID(uuid)) {
logger.error(`#${uuid} is not a valid UUID string.`)
return false
@@ -118,7 +119,7 @@ function shouldValidUUID (uuid: string) {
return true
}
function checkEffect (p: LSPluginUser) {
function checkEffect(p: LSPluginUser) {
return p && (p.baseInfo?.effect || !p.baseInfo?.iir)
}
@@ -126,7 +127,7 @@ let _appBaseInfo: AppInfo = null
let _searchServices: Map<string, LSPluginSearchService> = new Map()
const app: Partial<IAppProxy> = {
async getInfo (this: LSPluginUser, key) {
async getInfo(this: LSPluginUser, key) {
if (!_appBaseInfo) {
_appBaseInfo = await this._execCallableAPIAsync('get-app-info')
}
@@ -135,7 +136,7 @@ const app: Partial<IAppProxy> = {
registerCommand: registerSimpleCommand,
registerSearchService<T extends IPluginSearchServiceHooks> (
registerSearchService<T extends IPluginSearchServiceHooks>(
this: LSPluginUser,
s: T
) {
@@ -146,7 +147,7 @@ const app: Partial<IAppProxy> = {
_searchServices.set(s.name, new LSPluginSearchService(this, s))
},
registerCommandPalette (
registerCommandPalette(
opts: { key: string; label: string; keybinding?: SimpleCommandKeybinding },
action: SimpleCommandCallback
) {
@@ -161,7 +162,7 @@ const app: Partial<IAppProxy> = {
)
},
registerCommandShortcut (
registerCommandShortcut(
keybinding: SimpleCommandKeybinding | string,
action: SimpleCommandCallback,
opts: Partial<{
@@ -190,7 +191,7 @@ const app: Partial<IAppProxy> = {
)
},
registerUIItem (
registerUIItem(
type: 'toolbar' | 'pagebar',
opts: { key: string; template: string }
) {
@@ -203,7 +204,7 @@ const app: Partial<IAppProxy> = {
})
},
registerPageMenuItem (
registerPageMenuItem(
this: LSPluginUser,
tag: string,
action: (e: IHookEvent & { page: string }) => void
@@ -227,7 +228,7 @@ const app: Partial<IAppProxy> = {
)
},
onBlockRendererSlotted (uuid, callback: (payload: any) => void) {
onBlockRendererSlotted(uuid, callback: (payload: any) => void) {
if (!shouldValidUUID(uuid)) return
const pid = this.baseInfo.id
@@ -242,7 +243,7 @@ const app: Partial<IAppProxy> = {
}
},
invokeExternalPlugin (this: LSPluginUser, type: string, ...args: Array<any>) {
invokeExternalPlugin(this: LSPluginUser, type: string, ...args: Array<any>) {
type = type?.trim()
if (!type) return
let [pid, group] = type.split('.')
@@ -263,7 +264,7 @@ const app: Partial<IAppProxy> = {
)
},
setFullScreen (flag) {
setFullScreen(flag) {
const sf = (...args) => this._callWin('setFullScreen', ...args)
if (flag === 'toggle') {
@@ -279,11 +280,18 @@ const app: Partial<IAppProxy> = {
let registeredCmdUid = 0
const editor: Partial<IEditorProxy> = {
newBlockUUID (this: LSPluginUser): Promise<string> {
newBlockUUID(this: LSPluginUser): Promise<string> {
return this._execCallableAPIAsync('new_block_uuid')
},
registerSlashCommand (
isPageBlock(
this: LSPluginUser,
block: BlockEntity | PageEntity
): Boolean {
return block.uuid && block.hasOwnProperty('name')
},
registerSlashCommand(
this: LSPluginUser,
tag: string,
actions: BlockCommandCallback | Array<SlashCommandAction>
@@ -331,7 +339,7 @@ const editor: Partial<IEditorProxy> = {
})
},
registerBlockContextMenuItem (
registerBlockContextMenuItem(
this: LSPluginUser,
label: string,
action: BlockCommandCallback
@@ -354,7 +362,7 @@ const editor: Partial<IEditorProxy> = {
)
},
registerHighlightContextMenuItem (
registerHighlightContextMenuItem(
this: LSPluginUser,
label: string,
action: SimpleCommandCallback,
@@ -379,7 +387,7 @@ const editor: Partial<IEditorProxy> = {
)
},
scrollToBlockInPage (
scrollToBlockInPage(
this: LSPluginUser,
pageName: BlockPageName,
blockId: BlockIdentity,
@@ -395,7 +403,7 @@ const editor: Partial<IEditorProxy> = {
}
const db: Partial<IDBProxy> = {
onBlockChanged (
onBlockChanged(
this: LSPluginUser,
uuid: BlockUUID,
callback: (
@@ -425,7 +433,7 @@ const db: Partial<IDBProxy> = {
}
},
datascriptQuery<T = any> (
datascriptQuery<T = any>(
this: LSPluginUser,
query: string,
...inputs: Array<any>
@@ -447,7 +455,7 @@ const git: Partial<IGitProxy> = {}
const ui: Partial<IUIProxy> = {}
const assets: Partial<IAssetsProxy> = {
makeSandboxStorage (this: LSPluginUser): IAsyncStorage {
makeSandboxStorage(this: LSPluginUser): IAsyncStorage {
return new LSPluginFileStorage(this, { assets: true })
},
}
@@ -496,7 +504,7 @@ export class LSPluginUser
* @param _baseInfo
* @param _caller
*/
constructor (
constructor(
private _baseInfo: LSPluginBaseInfo,
private _caller: LSPluginCaller
) {
@@ -529,7 +537,7 @@ export class LSPluginUser
}
// Life related
async ready (model?: any, callback?: any) {
async ready(model?: any, callback?: any) {
if (this._connected) return
try {
@@ -576,39 +584,39 @@ export class LSPluginUser
}
}
ensureConnected () {
ensureConnected() {
if (!this._connected) {
throw new Error('not connected')
}
}
beforeunload (callback: (e: any) => Promise<void>): void {
beforeunload(callback: (e: any) => Promise<void>): void {
if (typeof callback !== 'function') return
this._beforeunloadCallback = callback
}
provideModel (model: Record<string, any>) {
provideModel(model: Record<string, any>) {
this.caller._extendUserModel(model)
return this
}
provideTheme (theme: Theme) {
provideTheme(theme: Theme) {
this.caller.call('provider:theme', theme)
return this
}
provideStyle (style: StyleString) {
provideStyle(style: StyleString) {
this.caller.call('provider:style', style)
return this
}
provideUI (ui: UIOptions) {
provideUI(ui: UIOptions) {
this.caller.call('provider:ui', ui)
return this
}
// Settings related
useSettingsSchema (schema: Array<SettingSchemaDesc>) {
useSettingsSchema(schema: Array<SettingSchemaDesc>) {
if (this.connected) {
this.caller.call('settings:schema', {
schema,
@@ -620,35 +628,35 @@ export class LSPluginUser
return this
}
updateSettings (attrs: Record<string, any>) {
updateSettings(attrs: Record<string, any>) {
this.caller.call('settings:update', attrs)
// TODO: update associated baseInfo settings
}
onSettingsChanged<T = any> (cb: (a: T, b: T) => void): IUserOffHook {
onSettingsChanged<T = any>(cb: (a: T, b: T) => void): IUserOffHook {
const type = 'settings:changed'
this.on(type, cb)
return () => this.off(type, cb)
}
showSettingsUI () {
showSettingsUI() {
this.caller.call('settings:visible:changed', { visible: true })
}
hideSettingsUI () {
hideSettingsUI() {
this.caller.call('settings:visible:changed', { visible: false })
}
// UI related
setMainUIAttrs (attrs: Partial<UIContainerAttrs>): void {
setMainUIAttrs(attrs: Partial<UIContainerAttrs>): void {
this.caller.call('main-ui:attrs', attrs)
}
setMainUIInlineStyle (style: CSS.Properties): void {
setMainUIInlineStyle(style: CSS.Properties): void {
this.caller.call('main-ui:style', style)
}
hideMainUI (opts?: { restoreEditingCursor: boolean }): void {
hideMainUI(opts?: { restoreEditingCursor: boolean }): void {
const payload = {
key: KEY_MAIN_UI,
visible: false,
@@ -659,7 +667,7 @@ export class LSPluginUser
this._ui.set(payload.key, payload)
}
showMainUI (opts?: { autoFocus: boolean }): void {
showMainUI(opts?: { autoFocus: boolean }): void {
const payload = {
key: KEY_MAIN_UI,
visible: true,
@@ -670,7 +678,7 @@ export class LSPluginUser
this._ui.set(payload.key, payload)
}
toggleMainUI (): void {
toggleMainUI(): void {
const payload = { key: KEY_MAIN_UI, toggle: true }
const state = this._ui.get(payload.key)
if (state && state.visible) {
@@ -681,40 +689,40 @@ export class LSPluginUser
}
// Getters
get version (): string {
get version(): string {
return this._version
}
get isMainUIVisible (): boolean {
get isMainUIVisible(): boolean {
const state = this._ui.get(KEY_MAIN_UI)
return Boolean(state && state.visible)
}
get connected (): boolean {
get connected(): boolean {
return this._connected
}
get baseInfo (): LSPluginBaseInfo {
get baseInfo(): LSPluginBaseInfo {
return this._baseInfo
}
get effect (): Boolean {
get effect(): Boolean {
return checkEffect(this)
}
get logger () {
get logger() {
return logger
}
get settings () {
get settings() {
return this.baseInfo?.settings
}
get caller (): LSPluginCaller {
get caller(): LSPluginCaller {
return this._caller
}
resolveResourceFullUrl (filePath: string) {
resolveResourceFullUrl(filePath: string) {
this.ensureConnected()
if (!filePath) return
filePath = filePath.replace(/^[.\\/]+/, '')
@@ -724,12 +732,12 @@ export class LSPluginUser
/**
* @internal
*/
_makeUserProxy (target: any, tag?: UserProxyTags) {
_makeUserProxy(target: any, tag?: UserProxyTags) {
const that = this
const caller = this.caller
return new Proxy(target, {
get (target: any, propKey, receiver) {
get(target: any, propKey, _receiver) {
const origMethod = target[propKey]
return function (this: any, ...args: any) {
@@ -800,68 +808,74 @@ export class LSPluginUser
})
}
_execCallableAPIAsync (method: callableMethods, ...args) {
_execCallableAPIAsync(method: callableMethods, ...args) {
return this._caller.callAsync(`api:call`, {
method,
args,
})
}
_execCallableAPI (method: callableMethods, ...args) {
_execCallableAPI(method: callableMethods, ...args) {
this._caller.call(`api:call`, {
method,
args,
})
}
_callWin (...args) {
_callWin(...args) {
return this._execCallableAPIAsync(`_callMainWin`, ...args)
}
// User Proxies
#appProxy: IAppProxy
#editorProxy: IEditorProxy
#dbProxy: IDBProxy
#uiProxy: IUIProxy
/**
* The interface methods of {@link IAppProxy}
*/
get App (): IAppProxy {
get App(): IAppProxy {
if (this.#appProxy) return this.#appProxy
return (this.#appProxy = this._makeUserProxy(app, 'app'))
}
get Editor (): IEditorProxy {
return this._makeUserProxy(editor, 'editor')
get Editor(): IEditorProxy {
if (this.#editorProxy) return this.#editorProxy
return (this.#editorProxy = this._makeUserProxy(editor, 'editor'))
}
get DB (): IDBProxy {
return this._makeUserProxy(db, 'db')
get DB(): IDBProxy {
if (this.#dbProxy) return this.#dbProxy
return (this.#dbProxy = this._makeUserProxy(db, 'db'))
}
get Git (): IGitProxy {
get UI(): IUIProxy {
if (this.#uiProxy) return this.#uiProxy
return (this.#uiProxy = this._makeUserProxy(ui, 'ui'))
}
get Git(): IGitProxy {
return this._makeUserProxy(git, 'git')
}
get UI (): IUIProxy {
return this._makeUserProxy(ui, 'ui')
}
get Assets (): IAssetsProxy {
get Assets(): IAssetsProxy {
return this._makeUserProxy(assets, 'assets')
}
get FileStorage (): LSPluginFileStorage {
get FileStorage(): LSPluginFileStorage {
let m = this._mFileStorage
if (!m) m = this._mFileStorage = new LSPluginFileStorage(this)
return m
}
get Request (): LSPluginRequest {
get Request(): LSPluginRequest {
let m = this._mRequest
if (!m) m = this._mRequest = new LSPluginRequest(this)
return m
}
get Experiments (): LSPluginExperiments {
get Experiments(): LSPluginExperiments {
let m = this._mExperiments
if (!m) m = this._mExperiments = new LSPluginExperiments(this)
return m
@@ -873,7 +887,7 @@ export * from './LSPlugin'
/**
* @internal
*/
export function setupPluginUserInstance (
export function setupPluginUserInstance(
pluginBaseInfo: LSPluginBaseInfo,
pluginCaller: LSPluginCaller
) {