From 2d40fee3186fb543e5f3d7c12f0942585386a10c Mon Sep 17 00:00:00 2001 From: ByteAtATime Date: Wed, 25 Jun 2025 21:45:00 -0700 Subject: [PATCH] refactor(protocol): extract protocol into multiple files --- packages/protocol/src/api.ts | 174 ++++++++++++ packages/protocol/src/command.ts | 63 +++++ packages/protocol/src/common.ts | 6 + packages/protocol/src/hud.ts | 10 + packages/protocol/src/index.ts | 390 +-------------------------- packages/protocol/src/main.ts | 67 +++++ packages/protocol/src/plugin.ts | 37 +++ packages/protocol/src/preferences.ts | 28 ++ packages/protocol/src/toast.ts | 30 +++ 9 files changed, 423 insertions(+), 382 deletions(-) create mode 100644 packages/protocol/src/api.ts create mode 100644 packages/protocol/src/command.ts create mode 100644 packages/protocol/src/common.ts create mode 100644 packages/protocol/src/hud.ts create mode 100644 packages/protocol/src/main.ts create mode 100644 packages/protocol/src/plugin.ts create mode 100644 packages/protocol/src/preferences.ts create mode 100644 packages/protocol/src/toast.ts diff --git a/packages/protocol/src/api.ts b/packages/protocol/src/api.ts new file mode 100644 index 0000000..25cba21 --- /dev/null +++ b/packages/protocol/src/api.ts @@ -0,0 +1,174 @@ +import { z } from 'zod/v4'; + +export const OpenPayloadSchema = z.object({ + target: z.string(), + application: z.string().optional() +}); +export const OpenMessageSchema = z.object({ + type: z.literal('open'), + payload: OpenPayloadSchema +}); + +export const GetSelectedTextPayloadSchema = z.object({ + requestId: z.string() +}); +export const GetSelectedTextMessageSchema = z.object({ + type: z.literal('get-selected-text'), + payload: GetSelectedTextPayloadSchema +}); + +export const GetSelectedFinderItemsPayloadSchema = z.object({ + requestId: z.string() +}); +export const GetSelectedFinderItemsMessageSchema = z.object({ + type: z.literal('get-selected-finder-items'), + payload: GetSelectedFinderItemsPayloadSchema +}); + +export const BrowserExtensionRequestPayloadSchema = z.object({ + requestId: z.string(), + method: z.string(), + params: z.unknown() +}); +export const BrowserExtensionRequestMessageSchema = z.object({ + type: z.literal('browser-extension-request'), + payload: BrowserExtensionRequestPayloadSchema +}); + +export const ClipboardContentSchema = z.object({ + text: z.string().optional(), + html: z.string().optional(), + file: z.string().optional() +}); + +export const CopyOptionsSchema = z.object({ + concealed: z.boolean().optional() +}); + +export const ClipboardCopyPayloadSchema = z.object({ + requestId: z.string(), + content: ClipboardContentSchema, + options: CopyOptionsSchema.optional() +}); +export const ClipboardCopyMessageSchema = z.object({ + type: z.literal('clipboard-copy'), + payload: ClipboardCopyPayloadSchema +}); + +export const ClipboardPastePayloadSchema = z.object({ + requestId: z.string(), + content: ClipboardContentSchema +}); +export const ClipboardPasteMessageSchema = z.object({ + type: z.literal('clipboard-paste'), + payload: ClipboardPastePayloadSchema +}); + +export const ClipboardReadPayloadSchema = z.object({ + requestId: z.string(), + offset: z.number().optional() +}); +export const ClipboardReadMessageSchema = z.object({ + type: z.literal('clipboard-read'), + payload: ClipboardReadPayloadSchema +}); + +export const ClipboardReadTextPayloadSchema = z.object({ + requestId: z.string(), + offset: z.number().optional() +}); +export const ClipboardReadTextMessageSchema = z.object({ + type: z.literal('clipboard-read-text'), + payload: ClipboardReadTextPayloadSchema +}); + +export const ClipboardClearPayloadSchema = z.object({ + requestId: z.string() +}); +export const ClipboardClearMessageSchema = z.object({ + type: z.literal('clipboard-clear'), + payload: ClipboardClearPayloadSchema +}); + +export const OauthAuthorizePayloadSchema = z.object({ + url: z.string(), + providerName: z.string(), + providerIcon: z.string().optional(), + description: z.string().optional() +}); +export const OauthAuthorizeMessageSchema = z.object({ + type: z.literal('oauth-authorize'), + payload: OauthAuthorizePayloadSchema +}); + +export const OauthGetTokensPayloadSchema = z.object({ + requestId: z.string(), + providerId: z.string() +}); +export const OauthGetTokensMessageSchema = z.object({ + type: z.literal('oauth-get-tokens'), + payload: OauthGetTokensPayloadSchema +}); + +export const OauthSetTokensPayloadSchema = z.object({ + requestId: z.string(), + providerId: z.string(), + tokens: z.record(z.string(), z.unknown()) +}); +export const OauthSetTokensMessageSchema = z.object({ + type: z.literal('oauth-set-tokens'), + payload: OauthSetTokensPayloadSchema +}); + +export const OauthRemoveTokensPayloadSchema = z.object({ + requestId: z.string(), + providerId: z.string() +}); +export const OauthRemoveTokensMessageSchema = z.object({ + type: z.literal('oauth-remove-tokens'), + payload: OauthRemoveTokensPayloadSchema +}); + +export const SystemGetApplicationsPayloadSchema = z.object({ + requestId: z.string(), + path: z.string().optional() +}); +export const SystemGetApplicationsMessageSchema = z.object({ + type: z.literal('system-get-applications'), + payload: SystemGetApplicationsPayloadSchema +}); + +export const SystemGetDefaultApplicationPayloadSchema = z.object({ + requestId: z.string(), + path: z.string() +}); +export const SystemGetDefaultApplicationMessageSchema = z.object({ + type: z.literal('system-get-default-application'), + payload: SystemGetDefaultApplicationPayloadSchema +}); + +export const SystemGetFrontmostApplicationPayloadSchema = z.object({ + requestId: z.string() +}); +export const SystemGetFrontmostApplicationMessageSchema = z.object({ + type: z.literal('system-get-frontmost-application'), + payload: SystemGetFrontmostApplicationPayloadSchema +}); + +export const SystemShowInFinderPayloadSchema = z.object({ + requestId: z.string(), + path: z.string() +}); +export const SystemShowInFinderMessageSchema = z.object({ + type: z.literal('system-show-in-finder'), + payload: SystemShowInFinderPayloadSchema +}); + +export const SystemTrashPayloadSchema = z.object({ + requestId: z.string(), + paths: z.array(z.string()) +}); +export const SystemTrashMessageSchema = z.object({ + type: z.literal('system-trash'), + payload: SystemTrashPayloadSchema +}); diff --git a/packages/protocol/src/command.ts b/packages/protocol/src/command.ts new file mode 100644 index 0000000..e5921a2 --- /dev/null +++ b/packages/protocol/src/command.ts @@ -0,0 +1,63 @@ +import { z } from 'zod/v4'; +import { ShowToastPayloadSchema, UpdateToastPayloadSchema, HideToastPayloadSchema } from './toast'; + +const CreateInstancePayloadSchema = z.object({ + id: z.number(), + type: z.string(), + props: z.record(z.string(), z.unknown()), + children: z.array(z.number()).optional(), + namedChildren: z.record(z.string(), z.number()).optional() +}); + +const CreateTextInstancePayloadSchema = z.object({ + id: z.number(), + type: z.literal('TEXT'), + text: z.string() +}); + +const ParentChildPayloadSchema = z.object({ + parentId: z.union([z.literal('root'), z.number()]), + childId: z.number() +}); + +const InsertBeforePayloadSchema = z.object({ + parentId: z.union([z.literal('root'), z.number()]), + childId: z.number(), + beforeId: z.number() +}); + +const UpdatePropsPayloadSchema = z.object({ + id: z.number(), + props: z.record(z.string(), z.unknown()), + namedChildren: z.record(z.string(), z.number()).optional() +}); + +const UpdateTextPayloadSchema = z.object({ + id: z.number(), + text: z.string() +}); + +const ReplaceChildrenPayloadSchema = z.object({ + parentId: z.union([z.string(), z.number()]), + childrenIds: z.array(z.number()) +}); + +const ClearContainerPayloadSchema = z.object({ + containerId: z.string() +}); + +export const CommandSchema = z.discriminatedUnion('type', [ + z.object({ type: z.literal('CREATE_INSTANCE'), payload: CreateInstancePayloadSchema }), + z.object({ type: z.literal('CREATE_TEXT_INSTANCE'), payload: CreateTextInstancePayloadSchema }), + z.object({ type: z.literal('APPEND_CHILD'), payload: ParentChildPayloadSchema }), + z.object({ type: z.literal('INSERT_BEFORE'), payload: InsertBeforePayloadSchema }), + z.object({ type: z.literal('REMOVE_CHILD'), payload: ParentChildPayloadSchema }), + z.object({ type: z.literal('UPDATE_PROPS'), payload: UpdatePropsPayloadSchema }), + z.object({ type: z.literal('UPDATE_TEXT'), payload: UpdateTextPayloadSchema }), + z.object({ type: z.literal('REPLACE_CHILDREN'), payload: ReplaceChildrenPayloadSchema }), + z.object({ type: z.literal('CLEAR_CONTAINER'), payload: ClearContainerPayloadSchema }), + z.object({ type: z.literal('SHOW_TOAST'), payload: ShowToastPayloadSchema }), + z.object({ type: z.literal('UPDATE_TOAST'), payload: UpdateToastPayloadSchema }), + z.object({ type: z.literal('HIDE_TOAST'), payload: HideToastPayloadSchema }) +]); +export type Command = z.infer; diff --git a/packages/protocol/src/common.ts b/packages/protocol/src/common.ts new file mode 100644 index 0000000..c00a90d --- /dev/null +++ b/packages/protocol/src/common.ts @@ -0,0 +1,6 @@ +import { z } from 'zod/v4'; + +export const KeyboardShortcutSchema = z.object({ + modifiers: z.array(z.enum(['cmd', 'ctrl', 'opt', 'shift'])), + key: z.string() +}); diff --git a/packages/protocol/src/hud.ts b/packages/protocol/src/hud.ts new file mode 100644 index 0000000..a49ad27 --- /dev/null +++ b/packages/protocol/src/hud.ts @@ -0,0 +1,10 @@ +import { z } from 'zod/v4'; + +export const ShowHudPayloadSchema = z.object({ + title: z.string() +}); + +export const ShowHudMessageSchema = z.object({ + type: z.literal('SHOW_HUD'), + payload: ShowHudPayloadSchema +}); diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts index d13fbc2..047a1c0 100644 --- a/packages/protocol/src/index.ts +++ b/packages/protocol/src/index.ts @@ -1,382 +1,8 @@ -import { z } from 'zod/v4'; - -const CreateInstancePayloadSchema = z.object({ - id: z.number(), - type: z.string(), - props: z.record(z.string(), z.unknown()), - children: z.array(z.number()).optional(), - namedChildren: z.record(z.string(), z.number()).optional() -}); - -const CreateTextInstancePayloadSchema = z.object({ - id: z.number(), - type: z.literal('TEXT'), - text: z.string() -}); - -const ParentChildPayloadSchema = z.object({ - parentId: z.union([z.literal('root'), z.number()]), - childId: z.number() -}); - -const InsertBeforePayloadSchema = z.object({ - parentId: z.union([z.literal('root'), z.number()]), - childId: z.number(), - beforeId: z.number() -}); - -const UpdatePropsPayloadSchema = z.object({ - id: z.number(), - props: z.record(z.string(), z.unknown()), - namedChildren: z.record(z.string(), z.number()).optional() -}); - -const UpdateTextPayloadSchema = z.object({ - id: z.number(), - text: z.string() -}); - -const ReplaceChildrenPayloadSchema = z.object({ - parentId: z.union([z.string(), z.number()]), - childrenIds: z.array(z.number()) -}); - -const ClearContainerPayloadSchema = z.object({ - containerId: z.string() -}); - -const KeyboardShortcutSchema = z.object({ - modifiers: z.array(z.enum(['cmd', 'ctrl', 'opt', 'shift'])), - key: z.string() -}); - -const ToastActionOptionsSchema = z.object({ - title: z.string(), - onAction: z.boolean(), - shortcut: KeyboardShortcutSchema.optional() -}); - -const ToastStyleSchema = z.enum(['SUCCESS', 'FAILURE', 'ANIMATED']); - -const ShowToastPayloadSchema = z.object({ - id: z.number(), - title: z.string(), - message: z.string().optional(), - style: ToastStyleSchema.optional(), - primaryAction: ToastActionOptionsSchema.optional(), - secondaryAction: ToastActionOptionsSchema.optional() -}); - -const UpdateToastPayloadSchema = z.object({ - id: z.number(), - title: z.string().optional(), - message: z.string().optional(), - style: ToastStyleSchema.optional() -}); - -const HideToastPayloadSchema = z.object({ - id: z.number() -}); - -const ShowHudPayloadSchema = z.object({ - title: z.string() -}); - -const ShowHudMessageSchema = z.object({ - type: z.literal('SHOW_HUD'), - payload: ShowHudPayloadSchema -}); - -export const CommandSchema = z.discriminatedUnion('type', [ - z.object({ type: z.literal('CREATE_INSTANCE'), payload: CreateInstancePayloadSchema }), - z.object({ type: z.literal('CREATE_TEXT_INSTANCE'), payload: CreateTextInstancePayloadSchema }), - z.object({ type: z.literal('APPEND_CHILD'), payload: ParentChildPayloadSchema }), - z.object({ type: z.literal('INSERT_BEFORE'), payload: InsertBeforePayloadSchema }), - z.object({ type: z.literal('REMOVE_CHILD'), payload: ParentChildPayloadSchema }), - z.object({ type: z.literal('UPDATE_PROPS'), payload: UpdatePropsPayloadSchema }), - z.object({ type: z.literal('UPDATE_TEXT'), payload: UpdateTextPayloadSchema }), - z.object({ type: z.literal('REPLACE_CHILDREN'), payload: ReplaceChildrenPayloadSchema }), - z.object({ type: z.literal('CLEAR_CONTAINER'), payload: ClearContainerPayloadSchema }), - z.object({ type: z.literal('SHOW_TOAST'), payload: ShowToastPayloadSchema }), - z.object({ type: z.literal('UPDATE_TOAST'), payload: UpdateToastPayloadSchema }), - z.object({ type: z.literal('HIDE_TOAST'), payload: HideToastPayloadSchema }) -]); -export type Command = z.infer; - -export const BatchUpdateSchema = z.object({ - type: z.literal('BATCH_UPDATE'), - payload: z.array(CommandSchema) -}); -export type BatchUpdate = z.infer; - -const LogMessageSchema = z.object({ - type: z.literal('log'), - payload: z.unknown() -}); - -export const SidecarMessageSchema = z.union([BatchUpdateSchema, CommandSchema, LogMessageSchema]); -export type SidecarMessage = z.infer; - -const BasePreferenceSchema = z.object({ - name: z.string(), - title: z.string().optional(), - description: z.string().optional(), - required: z.boolean().optional(), - default: z.union([z.string(), z.boolean()]).optional(), - data: z - .array( - z.object({ - title: z.string(), - value: z.string() - }) - ) - .optional() -}); - -export const PreferenceSchema = z.discriminatedUnion('type', [ - BasePreferenceSchema.extend({ - type: z.literal('checkbox'), - label: z.string() - }), - BasePreferenceSchema.extend({ - type: z.enum(['textfield', 'password', 'dropdown', 'appPicker', 'file', 'directory']) - }) -]); -export type Preference = z.infer; - -export const PluginInfoSchema = z.object({ - title: z.string(), - description: z.string().optional(), - pluginTitle: z.string(), - pluginName: z.string(), - commandName: z.string(), - pluginPath: z.string(), - icon: z.string().optional(), - preferences: z.array(PreferenceSchema).optional(), - commandPreferences: z.array(PreferenceSchema).optional(), - mode: z.enum(['view', 'no-view', 'menu-bar']).optional() -}); -export type PluginInfo = z.infer; - -export const PluginListSchema = z.object({ - type: z.literal('plugin-list'), - payload: z.array(PluginInfoSchema) -}); -export type PluginList = z.infer; - -export const PreferenceValuesSchema = z.object({ - type: z.literal('preference-values'), - payload: z.object({ - pluginName: z.string(), - values: z.record(z.string(), z.unknown()) - }) -}); -export type PreferenceValues = z.infer; - -export const GoBackToPluginListSchema = z.object({ - type: z.literal('go-back-to-plugin-list'), - payload: z.object({}) -}); -export type GoBackToPluginList = z.infer; - -const OpenPayloadSchema = z.object({ - target: z.string(), - application: z.string().optional() -}); -const OpenMessageSchema = z.object({ - type: z.literal('open'), - payload: OpenPayloadSchema -}); - -const GetSelectedTextPayloadSchema = z.object({ - requestId: z.string() -}); -const GetSelectedTextMessageSchema = z.object({ - type: z.literal('get-selected-text'), - payload: GetSelectedTextPayloadSchema -}); - -const GetSelectedFinderItemsPayloadSchema = z.object({ - requestId: z.string() -}); -const GetSelectedFinderItemsMessageSchema = z.object({ - type: z.literal('get-selected-finder-items'), - payload: GetSelectedFinderItemsPayloadSchema -}); - -const BrowserExtensionRequestPayloadSchema = z.object({ - requestId: z.string(), - method: z.string(), - params: z.unknown() -}); -const BrowserExtensionRequestMessageSchema = z.object({ - type: z.literal('browser-extension-request'), - payload: BrowserExtensionRequestPayloadSchema -}); - -const ClipboardContentSchema = z.object({ - text: z.string().optional(), - html: z.string().optional(), - file: z.string().optional() -}); - -const CopyOptionsSchema = z.object({ - concealed: z.boolean().optional() -}); - -const ClipboardCopyPayloadSchema = z.object({ - requestId: z.string(), - content: ClipboardContentSchema, - options: CopyOptionsSchema.optional() -}); -const ClipboardCopyMessageSchema = z.object({ - type: z.literal('clipboard-copy'), - payload: ClipboardCopyPayloadSchema -}); - -const ClipboardPastePayloadSchema = z.object({ - requestId: z.string(), - content: ClipboardContentSchema -}); -const ClipboardPasteMessageSchema = z.object({ - type: z.literal('clipboard-paste'), - payload: ClipboardPastePayloadSchema -}); - -const ClipboardReadPayloadSchema = z.object({ - requestId: z.string(), - offset: z.number().optional() -}); -const ClipboardReadMessageSchema = z.object({ - type: z.literal('clipboard-read'), - payload: ClipboardReadPayloadSchema -}); - -const ClipboardReadTextPayloadSchema = z.object({ - requestId: z.string(), - offset: z.number().optional() -}); -const ClipboardReadTextMessageSchema = z.object({ - type: z.literal('clipboard-read-text'), - payload: ClipboardReadTextPayloadSchema -}); - -const ClipboardClearPayloadSchema = z.object({ - requestId: z.string() -}); -const ClipboardClearMessageSchema = z.object({ - type: z.literal('clipboard-clear'), - payload: ClipboardClearPayloadSchema -}); - -const OauthAuthorizePayloadSchema = z.object({ - url: z.string(), - providerName: z.string(), - providerIcon: z.string().optional(), - description: z.string().optional() -}); -const OauthAuthorizeMessageSchema = z.object({ - type: z.literal('oauth-authorize'), - payload: OauthAuthorizePayloadSchema -}); - -const OauthGetTokensPayloadSchema = z.object({ - requestId: z.string(), - providerId: z.string() -}); -const OauthGetTokensMessageSchema = z.object({ - type: z.literal('oauth-get-tokens'), - payload: OauthGetTokensPayloadSchema -}); - -const OauthSetTokensPayloadSchema = z.object({ - requestId: z.string(), - providerId: z.string(), - tokens: z.record(z.string(), z.unknown()) -}); -const OauthSetTokensMessageSchema = z.object({ - type: z.literal('oauth-set-tokens'), - payload: OauthSetTokensPayloadSchema -}); - -const OauthRemoveTokensPayloadSchema = z.object({ - requestId: z.string(), - providerId: z.string() -}); -const OauthRemoveTokensMessageSchema = z.object({ - type: z.literal('oauth-remove-tokens'), - payload: OauthRemoveTokensPayloadSchema -}); - -const SystemGetApplicationsPayloadSchema = z.object({ - requestId: z.string(), - path: z.string().optional() -}); -const SystemGetApplicationsMessageSchema = z.object({ - type: z.literal('system-get-applications'), - payload: SystemGetApplicationsPayloadSchema -}); - -const SystemGetDefaultApplicationPayloadSchema = z.object({ - requestId: z.string(), - path: z.string() -}); -const SystemGetDefaultApplicationMessageSchema = z.object({ - type: z.literal('system-get-default-application'), - payload: SystemGetDefaultApplicationPayloadSchema -}); - -const SystemGetFrontmostApplicationPayloadSchema = z.object({ - requestId: z.string() -}); -const SystemGetFrontmostApplicationMessageSchema = z.object({ - type: z.literal('system-get-frontmost-application'), - payload: SystemGetFrontmostApplicationPayloadSchema -}); - -const SystemShowInFinderPayloadSchema = z.object({ - requestId: z.string(), - path: z.string() -}); -const SystemShowInFinderMessageSchema = z.object({ - type: z.literal('system-show-in-finder'), - payload: SystemShowInFinderPayloadSchema -}); - -const SystemTrashPayloadSchema = z.object({ - requestId: z.string(), - paths: z.array(z.string()) -}); -const SystemTrashMessageSchema = z.object({ - type: z.literal('system-trash'), - payload: SystemTrashPayloadSchema -}); - -export const SidecarMessageWithPluginsSchema = z.union([ - BatchUpdateSchema, - CommandSchema, - ShowHudMessageSchema, - LogMessageSchema, - PluginListSchema, - PreferenceValuesSchema, - GoBackToPluginListSchema, - OpenMessageSchema, - GetSelectedTextMessageSchema, - GetSelectedFinderItemsMessageSchema, - BrowserExtensionRequestMessageSchema, - ClipboardCopyMessageSchema, - ClipboardPasteMessageSchema, - ClipboardReadMessageSchema, - ClipboardReadTextMessageSchema, - ClipboardClearMessageSchema, - OauthAuthorizeMessageSchema, - OauthGetTokensMessageSchema, - OauthSetTokensMessageSchema, - OauthRemoveTokensMessageSchema, - SystemGetApplicationsMessageSchema, - SystemGetDefaultApplicationMessageSchema, - SystemGetFrontmostApplicationMessageSchema, - SystemShowInFinderMessageSchema, - SystemTrashMessageSchema -]); -export type SidecarMessageWithPlugins = z.infer; +export * from './api'; +export * from './command'; +export * from './common'; +export * from './hud'; +export * from './main'; +export * from './plugin'; +export * from './preferences'; +export * from './toast'; diff --git a/packages/protocol/src/main.ts b/packages/protocol/src/main.ts new file mode 100644 index 0000000..02cc674 --- /dev/null +++ b/packages/protocol/src/main.ts @@ -0,0 +1,67 @@ +import { z } from 'zod/v4'; +import { + BrowserExtensionRequestMessageSchema, + ClipboardClearMessageSchema, + ClipboardCopyMessageSchema, + ClipboardPasteMessageSchema, + ClipboardReadMessageSchema, + ClipboardReadTextMessageSchema, + GetSelectedFinderItemsMessageSchema, + GetSelectedTextMessageSchema, + OauthAuthorizeMessageSchema, + OauthGetTokensMessageSchema, + OauthRemoveTokensMessageSchema, + OauthSetTokensMessageSchema, + OpenMessageSchema, + SystemGetApplicationsMessageSchema, + SystemGetDefaultApplicationMessageSchema, + SystemGetFrontmostApplicationMessageSchema, + SystemShowInFinderMessageSchema, + SystemTrashMessageSchema +} from './api'; +import { CommandSchema } from './command'; +import { ShowHudMessageSchema } from './hud'; +import { GoBackToPluginListSchema, PluginListSchema, PreferenceValuesSchema } from './plugin'; + +export const BatchUpdateSchema = z.object({ + type: z.literal('BATCH_UPDATE'), + payload: z.array(CommandSchema) +}); +export type BatchUpdate = z.infer; + +const LogMessageSchema = z.object({ + type: z.literal('log'), + payload: z.unknown() +}); + +export const SidecarMessageSchema = z.union([BatchUpdateSchema, CommandSchema, LogMessageSchema]); +export type SidecarMessage = z.infer; + +export const SidecarMessageWithPluginsSchema = z.union([ + BatchUpdateSchema, + CommandSchema, + ShowHudMessageSchema, + LogMessageSchema, + PluginListSchema, + PreferenceValuesSchema, + GoBackToPluginListSchema, + OpenMessageSchema, + GetSelectedTextMessageSchema, + GetSelectedFinderItemsMessageSchema, + BrowserExtensionRequestMessageSchema, + ClipboardCopyMessageSchema, + ClipboardPasteMessageSchema, + ClipboardReadMessageSchema, + ClipboardReadTextMessageSchema, + ClipboardClearMessageSchema, + OauthAuthorizeMessageSchema, + OauthGetTokensMessageSchema, + OauthSetTokensMessageSchema, + OauthRemoveTokensMessageSchema, + SystemGetApplicationsMessageSchema, + SystemGetDefaultApplicationMessageSchema, + SystemGetFrontmostApplicationMessageSchema, + SystemShowInFinderMessageSchema, + SystemTrashMessageSchema +]); +export type SidecarMessageWithPlugins = z.infer; diff --git a/packages/protocol/src/plugin.ts b/packages/protocol/src/plugin.ts new file mode 100644 index 0000000..ea513bf --- /dev/null +++ b/packages/protocol/src/plugin.ts @@ -0,0 +1,37 @@ +import { z } from 'zod/v4'; +import { PreferenceSchema } from './preferences'; + +export const PluginInfoSchema = z.object({ + title: z.string(), + description: z.string().optional(), + pluginTitle: z.string(), + pluginName: z.string(), + commandName: z.string(), + pluginPath: z.string(), + icon: z.string().optional(), + preferences: z.array(PreferenceSchema).optional(), + commandPreferences: z.array(PreferenceSchema).optional(), + mode: z.enum(['view', 'no-view', 'menu-bar']).optional() +}); +export type PluginInfo = z.infer; + +export const PluginListSchema = z.object({ + type: z.literal('plugin-list'), + payload: z.array(PluginInfoSchema) +}); +export type PluginList = z.infer; + +export const PreferenceValuesSchema = z.object({ + type: z.literal('preference-values'), + payload: z.object({ + pluginName: z.string(), + values: z.record(z.string(), z.unknown()) + }) +}); +export type PreferenceValues = z.infer; + +export const GoBackToPluginListSchema = z.object({ + type: z.literal('go-back-to-plugin-list'), + payload: z.object({}) +}); +export type GoBackToPluginList = z.infer; diff --git a/packages/protocol/src/preferences.ts b/packages/protocol/src/preferences.ts new file mode 100644 index 0000000..aa85e1a --- /dev/null +++ b/packages/protocol/src/preferences.ts @@ -0,0 +1,28 @@ +import { z } from 'zod/v4'; + +const BasePreferenceSchema = z.object({ + name: z.string(), + title: z.string().optional(), + description: z.string().optional(), + required: z.boolean().optional(), + default: z.union([z.string(), z.boolean()]).optional(), + data: z + .array( + z.object({ + title: z.string(), + value: z.string() + }) + ) + .optional() +}); + +export const PreferenceSchema = z.discriminatedUnion('type', [ + BasePreferenceSchema.extend({ + type: z.literal('checkbox'), + label: z.string() + }), + BasePreferenceSchema.extend({ + type: z.enum(['textfield', 'password', 'dropdown', 'appPicker', 'file', 'directory']) + }) +]); +export type Preference = z.infer; diff --git a/packages/protocol/src/toast.ts b/packages/protocol/src/toast.ts new file mode 100644 index 0000000..7bc0bb8 --- /dev/null +++ b/packages/protocol/src/toast.ts @@ -0,0 +1,30 @@ +import { z } from 'zod/v4'; +import { KeyboardShortcutSchema } from './common'; + +export const ToastActionOptionsSchema = z.object({ + title: z.string(), + onAction: z.boolean(), + shortcut: KeyboardShortcutSchema.optional() +}); + +export const ToastStyleSchema = z.enum(['SUCCESS', 'FAILURE', 'ANIMATED']); + +export const ShowToastPayloadSchema = z.object({ + id: z.number(), + title: z.string(), + message: z.string().optional(), + style: ToastStyleSchema.optional(), + primaryAction: ToastActionOptionsSchema.optional(), + secondaryAction: ToastActionOptionsSchema.optional() +}); + +export const UpdateToastPayloadSchema = z.object({ + id: z.number(), + title: z.string().optional(), + message: z.string().optional(), + style: ToastStyleSchema.optional() +}); + +export const HideToastPayloadSchema = z.object({ + id: z.number() +});