From 7a3b6f3983186fbed9afd1465cc7444bfe14b8fc Mon Sep 17 00:00:00 2001 From: Huakun Shen Date: Sat, 18 Jan 2025 02:26:23 -0500 Subject: [PATCH] fix: listview action menu (#64) * refactor: add a valibot schema for package registry validation * fix: list view action menu * chore: bump version to 0.1.16 in package.json * refactor: extract supabase package from api * ci: remove NODE_OPTIONS from build step and improve error handling in getLatestNpmPkgVersion function --- .github/workflows/ci.yml | 2 - apps/create-kunkun/src/utils.ts | 8 +- apps/desktop/package.json | 2 +- apps/desktop/src/lib/stores/appState.ts | 4 +- apps/desktop/src/lib/stores/keys.ts | 26 +++++++ apps/desktop/src/lib/utils/key.ts | 6 ++ apps/desktop/src/routes/app/+layout.svelte | 4 +- .../routes/app/extension/store/+page.svelte | 3 +- .../src/routes/app/extension/store/+page.ts | 2 +- .../extension/store/[identifier]/+page.svelte | 2 +- .../app/extension/store/[identifier]/+page.ts | 2 +- .../extension/store/[identifier]/helper.ts | 2 +- .../app/extension/ui-worker/+page.svelte | 76 +++++++++++++++++-- packages/api/package.json | 2 - packages/api/src/supabase/index.ts | 2 - packages/api/src/supabase/model.ts | 19 ----- packages/package-registry/package.json | 3 +- packages/package-registry/src/jsr/index.ts | 17 +---- packages/package-registry/src/models.ts | 17 +++++ packages/package-registry/src/npm/index.ts | 17 +---- packages/supabase/package.json | 3 +- packages/supabase/src/api.ts | 4 +- .../src}/database.types.ts | 0 packages/supabase/src/index.ts | 6 +- packages/supabase/src/models.ts | 18 +++++ .../permissions/autogenerated/reference.md | 2 - packages/types/src/appState.ts | 2 +- .../components/extension/ExtListItem.svelte | 2 +- .../extension/StoreExtDetail.svelte | 4 +- .../extension/templates/form.svelte | 14 +++- .../extension/templates/list-view.svelte | 2 +- .../ui/src/components/main/ActionPanel.svelte | 24 ++++-- .../main/GlobalCommandPaletteFooter.svelte | 15 +++- 33 files changed, 209 insertions(+), 103 deletions(-) create mode 100644 apps/desktop/src/lib/stores/keys.ts delete mode 100644 packages/api/src/supabase/index.ts delete mode 100644 packages/api/src/supabase/model.ts rename packages/{api/src/supabase => supabase/src}/database.types.ts (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a244d5a..5721d05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,8 +51,6 @@ jobs: - name: Setup run: pnpm prepare - name: Build - env: - NODE_OPTIONS: --max-old-space-size=4096 run: pnpm build - name: JS Test if: matrix.os == 'ubuntu-24.04' diff --git a/apps/create-kunkun/src/utils.ts b/apps/create-kunkun/src/utils.ts index 702431b..7031328 100644 --- a/apps/create-kunkun/src/utils.ts +++ b/apps/create-kunkun/src/utils.ts @@ -11,9 +11,11 @@ export function getLatestNpmPkgInfo(pkgName: string): Promise { - return getLatestNpmPkgInfo(pkgName).then( - (data) => v.parse(v.object({ version: v.string() }), data).version - ) + return getLatestNpmPkgInfo(pkgName) + .then((data) => v.parse(v.object({ version: v.string() }), data).version) + .catch((err) => { + throw new Error(`Failed to get latest version of ${pkgName}: ${err.message}`) + }) } /** diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 921f01c..0b5c89c 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@kksh/desktop", - "version": "0.1.15", + "version": "0.1.16", "description": "", "type": "module", "scripts": { diff --git a/apps/desktop/src/lib/stores/appState.ts b/apps/desktop/src/lib/stores/appState.ts index d45c87a..1ea43b2 100644 --- a/apps/desktop/src/lib/stores/appState.ts +++ b/apps/desktop/src/lib/stores/appState.ts @@ -16,7 +16,7 @@ interface AppStateAPI { clearSearchTerm: () => void get: () => AppState setLoadingBar: (loadingBar: boolean) => void - setDefaultAction: (defaultAction: string) => void + setDefaultAction: (defaultAction: string | null) => void setActionPanel: (actionPanel?: ActionSchema.ActionPanel) => void } @@ -32,7 +32,7 @@ function createAppState(): Writable & AppStateAPI { setLoadingBar: (loadingBar: boolean) => { store.update((state) => ({ ...state, loadingBar })) }, - setDefaultAction: (defaultAction: string) => { + setDefaultAction: (defaultAction: string | null) => { store.update((state) => ({ ...state, defaultAction })) }, setActionPanel: (actionPanel?: ActionSchema.ActionPanel) => { diff --git a/apps/desktop/src/lib/stores/keys.ts b/apps/desktop/src/lib/stores/keys.ts new file mode 100644 index 0000000..84edc0a --- /dev/null +++ b/apps/desktop/src/lib/stores/keys.ts @@ -0,0 +1,26 @@ +import { get, writable, type Writable } from "svelte/store" + +export interface KeyStoreAPI { + get: () => string[] + getSet: () => Set + keydown: (key: string) => void + keyup: (key: string) => void +} + +function createKeysStore(): Writable & KeyStoreAPI { + const store = writable([]) + + return { + ...store, + get: () => get(store), + getSet: () => new Set(get(store)), + keydown: (key: string) => { + store.update((state) => [...state, key]) + }, + keyup: (key: string) => { + store.update((state) => state.filter((k) => k !== key)) + } + } +} + +export const keys = createKeysStore() diff --git a/apps/desktop/src/lib/utils/key.ts b/apps/desktop/src/lib/utils/key.ts index a285935..6558a9c 100644 --- a/apps/desktop/src/lib/utils/key.ts +++ b/apps/desktop/src/lib/utils/key.ts @@ -1,4 +1,5 @@ import { appState } from "@/stores" +import { keys } from "@/stores/keys" import { toggleDevTools } from "@kksh/api/commands" import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow" import { getCurrentWindow } from "@tauri-apps/api/window" @@ -72,6 +73,7 @@ export function goHomeOrCloseOnEscapeWithInput(e: KeyboardEvent) { } export async function globalKeyDownHandler(e: KeyboardEvent) { + keys.keydown(e.key) const _platform = platform() if ((_platform === "macos" && e.metaKey) || (_platform === "windows" && e.ctrlKey)) { if (e.key === ",") { @@ -96,6 +98,10 @@ export async function globalKeyDownHandler(e: KeyboardEvent) { } } +export function globalKeyUpHandler(e: KeyboardEvent) { + keys.keyup(e.key) +} + export function isLetter(letter: string): boolean { if (letter.length != 1) return false return letter.match(/[a-zA-Z]/) ? true : false diff --git a/apps/desktop/src/routes/app/+layout.svelte b/apps/desktop/src/routes/app/+layout.svelte index 4914c9a..263819b 100644 --- a/apps/desktop/src/routes/app/+layout.svelte +++ b/apps/desktop/src/routes/app/+layout.svelte @@ -3,7 +3,7 @@ import { appConfig, appState, extensions, quickLinks, winExtMap } from "@/stores" import { initDeeplink } from "@/utils/deeplink" import { updateAppHotkey } from "@/utils/hotkey" - import { globalKeyDownHandler, goBackOrCloseOnEscape } from "@/utils/key" + import { globalKeyDownHandler, globalKeyUpHandler, goBackOrCloseOnEscape } from "@/utils/key" import { listenToWindowBlur } from "@/utils/tauri-events" import { isInMainWindow } from "@/utils/window" import { listenToKillProcessEvent, listenToRecordExtensionProcessEvent } from "@kksh/api/events" @@ -97,7 +97,7 @@ }) - + {@render children()} diff --git a/apps/desktop/src/routes/app/extension/store/+page.svelte b/apps/desktop/src/routes/app/extension/store/+page.svelte index 3a1711d..fb8e2a7 100644 --- a/apps/desktop/src/routes/app/extension/store/+page.svelte +++ b/apps/desktop/src/routes/app/extension/store/+page.svelte @@ -4,8 +4,7 @@ import { supabaseAPI } from "@/supabase" import { goBackOnEscapeClearSearchTerm, goHomeOnEscapeClearSearchTerm } from "@/utils/key" import { goBack, goHome } from "@/utils/route" - import { SBExt, type Tables } from "@kksh/api/supabase" - import { isUpgradable } from "@kksh/extension" + import { SBExt, type Tables } from "@kksh/supabase" import type { ExtPublishMetadata } from "@kksh/supabase/models" import { Button, Command } from "@kksh/svelte5" import { Constants } from "@kksh/ui" diff --git a/apps/desktop/src/routes/app/extension/store/+page.ts b/apps/desktop/src/routes/app/extension/store/+page.ts index e0dc5af..41e0ff3 100644 --- a/apps/desktop/src/routes/app/extension/store/+page.ts +++ b/apps/desktop/src/routes/app/extension/store/+page.ts @@ -1,8 +1,8 @@ import { appConfig, extensions, installedStoreExts } from "@/stores" import { supabaseAPI } from "@/supabase" import type { ExtPackageJsonExtra } from "@kksh/api/models" -import { SBExt } from "@kksh/api/supabase" import { isExtPathInDev, isUpgradable } from "@kksh/extension" +import { SBExt } from "@kksh/supabase" import { error } from "@sveltejs/kit" import { derived, get, type Readable } from "svelte/store" import type { PageLoad } from "./$types" diff --git a/apps/desktop/src/routes/app/extension/store/[identifier]/+page.svelte b/apps/desktop/src/routes/app/extension/store/[identifier]/+page.svelte index 20c2bfe..60fc9f4 100644 --- a/apps/desktop/src/routes/app/extension/store/[identifier]/+page.svelte +++ b/apps/desktop/src/routes/app/extension/store/[identifier]/+page.svelte @@ -3,8 +3,8 @@ import { extensions, installedStoreExts } from "@/stores/extensions.js" import { supabaseAPI } from "@/supabase" import { goBack } from "@/utils/route.js" - import type { Tables } from "@kksh/api/supabase/types" import { ExtPublishMetadata } from "@kksh/supabase/models" + import type { Tables } from "@kksh/supabase/types" import { Button } from "@kksh/svelte5" import { cn } from "@kksh/svelte5/utils" import { Constants } from "@kksh/ui" diff --git a/apps/desktop/src/routes/app/extension/store/[identifier]/+page.ts b/apps/desktop/src/routes/app/extension/store/[identifier]/+page.ts index 081a0af..817c222 100644 --- a/apps/desktop/src/routes/app/extension/store/[identifier]/+page.ts +++ b/apps/desktop/src/routes/app/extension/store/[identifier]/+page.ts @@ -1,8 +1,8 @@ import { extensions } from "@/stores" import { supabaseAPI } from "@/supabase" import { KunkunExtManifest, type ExtPackageJsonExtra } from "@kksh/api/models" -import type { Tables } from "@kksh/api/supabase/types" import { ExtPublishMetadata } from "@kksh/supabase/models" +import type { Tables } from "@kksh/supabase/types" import { error } from "@sveltejs/kit" import { toast } from "svelte-sonner" import * as v from "valibot" diff --git a/apps/desktop/src/routes/app/extension/store/[identifier]/helper.ts b/apps/desktop/src/routes/app/extension/store/[identifier]/helper.ts index 2ba49a9..7ac604a 100644 --- a/apps/desktop/src/routes/app/extension/store/[identifier]/helper.ts +++ b/apps/desktop/src/routes/app/extension/store/[identifier]/helper.ts @@ -1,5 +1,5 @@ -import type { Tables } from "@kksh/api/supabase/types" import type { ExtPublishMetadata } from "@kksh/supabase/models" +import type { Tables } from "@kksh/supabase/types" export async function getInstallExtras( ext: Tables<"ext_publish"> & { metadata?: ExtPublishMetadata } diff --git a/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte b/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte index ebad6b0..6995147 100644 --- a/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte +++ b/apps/desktop/src/routes/app/extension/ui-worker/+page.svelte @@ -1,5 +1,6 @@ + {#if loadingBar} {/if} {#if loaded && listViewContent !== undefined} { - workerAPI?.onHighlightedListItemChanged(value) - if (listViewContent?.defaultAction) { - appState.setDefaultAction(listViewContent.defaultAction) - } - if (listViewContent?.actions) { - appState.setActionPanel(listViewContent.actions) + // workerAPI?.onHighlightedListItemChanged(value) + // if (listViewContent?.defaultAction) { + // appState.setDefaultAction(listViewContent.defaultAction) + // } + // if (listViewContent?.actions) { + // appState.setActionPanel(listViewContent.actions) + // } + try { + const parsedItem = v.parse(ListSchema.Item, JSON.parse(value)) + if (parsedItem.defaultAction) { + appState.setDefaultAction(parsedItem.defaultAction) + } + if (parsedItem.actions) { + appState.setActionPanel(parsedItem.actions) + } + workerAPI?.onHighlightedListItemChanged(parsedItem.value) + } catch (error) { + console.error(error) } }} > {#snippet footer()} { workerAPI?.onEnterPressedOnSearchBar() }} diff --git a/packages/api/package.json b/packages/api/package.json index 56cb48c..3ed7a4b 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -14,8 +14,6 @@ "./permissions": "./src/permissions/index.ts", "./dev": "./src/dev/index.ts", "./events": "./src/events.ts", - "./supabase": "./src/supabase/index.ts", - "./supabase/types": "./src/supabase/database.types.ts", "./package.json": "./package.json" }, "license": "MIT", diff --git a/packages/api/src/supabase/index.ts b/packages/api/src/supabase/index.ts deleted file mode 100644 index c2b5335..0000000 --- a/packages/api/src/supabase/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./model" -export * from "./database.types" diff --git a/packages/api/src/supabase/model.ts b/packages/api/src/supabase/model.ts deleted file mode 100644 index 3c85e0b..0000000 --- a/packages/api/src/supabase/model.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Icon } from "@kksh/api/models" -import * as v from "valibot" - -/*** - * Correspond to `extensions` table in supabase - */ -export const SBExt = v.object({ - identifier: v.string(), - name: v.string(), - created_at: v.string(), - downloads: v.number(), - short_description: v.string(), - long_description: v.string(), - version: v.string(), - api_version: v.optional(v.string()), - icon: Icon -}) - -export type SBExt = v.InferOutput diff --git a/packages/package-registry/package.json b/packages/package-registry/package.json index 780eafe..7904e6a 100644 --- a/packages/package-registry/package.json +++ b/packages/package-registry/package.json @@ -8,7 +8,8 @@ "exports": { "./jsr": "./src/jsr/index.ts", "./npm": "./src/npm/index.ts", - "./github": "./src/github.ts" + "./github": "./src/github.ts", + "./models": "./src/models.ts" }, "devDependencies": { "@types/bun": "latest", diff --git a/packages/package-registry/src/jsr/index.ts b/packages/package-registry/src/jsr/index.ts index fd65519..8f2d0e8 100644 --- a/packages/package-registry/src/jsr/index.ts +++ b/packages/package-registry/src/jsr/index.ts @@ -7,6 +7,7 @@ import { import { ExtPackageJson } from "@kksh/api/models" import * as v from "valibot" import { authenticatedUserIsMemberOfGitHubOrg, userIsPublicMemberOfGitHubOrg } from "../github" +import type { ExtensionPublishValidationData } from "../models" import type { NpmPkgMetadata } from "../npm/models" import { getInfoFromRekorLog } from "../sigstore" import { getTarballSize } from "../utils" @@ -220,21 +221,7 @@ export async function validateJsrPackageAsKunkunExtension(payload: { githubToken?: string }): Promise<{ error?: string - data?: { - pkgJson: ExtPackageJson - tarballUrl: string - shasum: string - apiVersion: string - tarballSize: number - rekorLogIndex: string - github: { - githubActionInvocationId: string - commit: string - repo: string - owner: string - workflowPath: string - } - } + data?: ExtensionPublishValidationData }> { /* -------------------------------------------------------------------------- */ /* check if jsr package exists */ diff --git a/packages/package-registry/src/models.ts b/packages/package-registry/src/models.ts index 32bccc4..17fb69e 100644 --- a/packages/package-registry/src/models.ts +++ b/packages/package-registry/src/models.ts @@ -1,3 +1,4 @@ +import { ExtPackageJson } from "@kksh/api/models" import * as v from "valibot" export const RawRekorLogEntry = v.object({ @@ -58,3 +59,19 @@ export const SigstoreAttestation = v.object({ }) }) export type SigstoreAttestation = v.InferOutput +export const ExtensionPublishValidationData = v.object({ + pkgJson: ExtPackageJson, + tarballUrl: v.string(), + shasum: v.string(), + apiVersion: v.string(), + rekorLogIndex: v.string(), + tarballSize: v.number(), + github: v.object({ + githubActionInvocationId: v.string(), + commit: v.string(), + repo: v.string(), + owner: v.string(), + workflowPath: v.string() + }) +}) +export type ExtensionPublishValidationData = v.InferOutput diff --git a/packages/package-registry/src/npm/index.ts b/packages/package-registry/src/npm/index.ts index 097f742..94c5dcb 100644 --- a/packages/package-registry/src/npm/index.ts +++ b/packages/package-registry/src/npm/index.ts @@ -5,6 +5,7 @@ import { parseGitHubRepoFromUri, userIsPublicMemberOfGitHubOrg } from "../github" +import type { ExtensionPublishValidationData } from "../models" import { getInfoFromRekorLog } from "../sigstore" import { NpmPkgMetadata, @@ -116,21 +117,7 @@ export async function validateNpmPackageAsKunkunExtension(payload: { provenance?: Provenance // provenance API has cors policy, when we run this validation on client side, a provenance should be passed in }): Promise<{ error?: string - data?: { - pkgJson: ExtPackageJson - tarballUrl: string - shasum: string - apiVersion: string - rekorLogIndex: string - tarballSize: number - github: { - githubActionInvocationId: string - commit: string - repo: string - owner: string - workflowPath: string - } - } + data?: ExtensionPublishValidationData }> { /* -------------------------------------------------------------------------- */ /* check if npm package exist */ diff --git a/packages/supabase/package.json b/packages/supabase/package.json index 50e0453..a474856 100644 --- a/packages/supabase/package.json +++ b/packages/supabase/package.json @@ -6,7 +6,8 @@ }, "exports": { ".": "./src/index.ts", - "./models": "./src/models.ts" + "./models": "./src/models.ts", + "./types": "./src/database.types.ts" }, "dependencies": { "@kksh/api": "workspace:*", diff --git a/packages/supabase/src/api.ts b/packages/supabase/src/api.ts index 6dc7d3e..68e0ecb 100644 --- a/packages/supabase/src/api.ts +++ b/packages/supabase/src/api.ts @@ -1,7 +1,7 @@ -import { SBExt } from "@kksh/api/supabase" -import type { Database, Tables } from "@kksh/api/supabase/types" import type { PostgrestSingleResponse, SupabaseClient } from "@supabase/supabase-js" import * as v from "valibot" +import type { Database, Tables } from "./database.types" +import { SBExt } from "./models" export class SupabaseAPI { constructor(private supabase: SupabaseClient) {} diff --git a/packages/api/src/supabase/database.types.ts b/packages/supabase/src/database.types.ts similarity index 100% rename from packages/api/src/supabase/database.types.ts rename to packages/supabase/src/database.types.ts diff --git a/packages/supabase/src/index.ts b/packages/supabase/src/index.ts index 09aae5e..75bdcf2 100644 --- a/packages/supabase/src/index.ts +++ b/packages/supabase/src/index.ts @@ -1,5 +1,5 @@ -import type { Database } from "@kksh/api/supabase/types" import { createClient } from "@supabase/supabase-js" +import type { Database } from "./database.types" export function createSB(supabaseUrl: string, supabaseAnonKey: string) { return createClient(supabaseUrl, supabaseAnonKey, { @@ -10,5 +10,5 @@ export function createSB(supabaseUrl: string, supabaseAnonKey: string) { } export { SupabaseAPI } from "./api" -export type { Database, Tables } from "@kksh/api/supabase/types" -export { SBExt } from "@kksh/api/supabase" +export type { Database, Tables } from "./database.types" +export { SBExt } from "./models" diff --git a/packages/supabase/src/models.ts b/packages/supabase/src/models.ts index 679907b..85535a7 100644 --- a/packages/supabase/src/models.ts +++ b/packages/supabase/src/models.ts @@ -2,6 +2,7 @@ * @module @kksh/supabase/models * This module contains some models for supabase database that cannot be code generated, such as JSON fields. */ +import { Icon } from "@kksh/api/models" import * as v from "valibot" export enum ExtPublishSourceTypeEnum { @@ -24,3 +25,20 @@ export const ExtPublishMetadata = v.object({ ) }) export type ExtPublishMetadata = v.InferOutput + +/*** + * Correspond to `extensions` table in supabase + */ +export const SBExt = v.object({ + identifier: v.string(), + name: v.string(), + created_at: v.string(), + downloads: v.number(), + short_description: v.string(), + long_description: v.string(), + version: v.string(), + api_version: v.optional(v.string()), + icon: Icon +}) + +export type SBExt = v.InferOutput diff --git a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md index 19f9805..7020b75 100644 --- a/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md +++ b/packages/tauri-plugins/jarvis/permissions/autogenerated/reference.md @@ -1,4 +1,3 @@ - ## Permission Table @@ -7,7 +6,6 @@ -
Description
diff --git a/packages/types/src/appState.ts b/packages/types/src/appState.ts index 4a0539c..b014327 100644 --- a/packages/types/src/appState.ts +++ b/packages/types/src/appState.ts @@ -4,6 +4,6 @@ export interface AppState { searchTerm: string highlightedCmd: string loadingBar: boolean - defaultAction: string + defaultAction: string | null actionPanel?: ActionSchema.ActionPanel } diff --git a/packages/ui/src/components/extension/ExtListItem.svelte b/packages/ui/src/components/extension/ExtListItem.svelte index 091c4c0..f5952d2 100644 --- a/packages/ui/src/components/extension/ExtListItem.svelte +++ b/packages/ui/src/components/extension/ExtListItem.svelte @@ -1,7 +1,7 @@ - {#snippet child({ props })} + + {#snippet child({ props }: { props: any })} {/if} {#if actionPanel} - + {/if}