Merge branch 'develop' into remove-supabase

This commit is contained in:
Huakun Shen 2025-03-26 01:53:24 -04:00
commit e25f28b97f
No known key found for this signature in database
9 changed files with 71 additions and 29 deletions

View File

@ -1,9 +1,15 @@
import { expect, test } from "bun:test"
import { parseGitHubRepoFromUri } from "../github"
import { getGitHubRepoMetadata, parseGitHubRepoFromUri } from "../github"
test("parse github repo from uri", () => {
expect(parseGitHubRepoFromUri("https://github.com/huakunshen/kunkun-ext-ossinsight")).toEqual({
owner: "huakunshen",
expect(parseGitHubRepoFromUri("https://github.com/kunkunsh/kunkun-ext-ossinsight")).toEqual({
owner: "kunkunsh",
repo: "kunkun-ext-ossinsight"
})
expect(() => parseGitHubRepoFromUri("invalid-uri")).toThrow("Invalid GitHub repository URI")
})
test("get github repo metadata", async () => {
const metadata = await getGitHubRepoMetadata("kunkunsh", "kunkun-ext-ossinsight")
expect(metadata).toBeDefined()
})

View File

@ -33,6 +33,12 @@ export function authenticatedUserIsMemberOfGitHubOrg(
})
}
/**
* Parse a GitHub repository URI into owner and repo
* If not a valid GitHub repository URI, throw an error
* @param uri
* @returns owner and repo
*/
export function parseGitHubRepoFromUri(uri: string): {
owner: string
repo: string
@ -46,3 +52,15 @@ export function parseGitHubRepoFromUri(uri: string): {
const [, owner, repo] = match
return { owner, repo }
}
/**
* Get GitHub repository metadata
* @param owner
* @param repo
* @param githubToken - Optional GitHub token to prevent rate limiting
* @returns repository metadata
*/
export function getGitHubRepoMetadata(owner: string, repo: string, githubToken?: string) {
const octokit = new Octokit({ auth: githubToken })
return octokit.rest.repos.get({ owner, repo }).then((res) => res.data)
}

View File

@ -7,7 +7,11 @@ import {
} from "@huakunshen/jsr-client/hey-api-client"
import { ExtPackageJson, License } from "@kksh/api/models"
import * as v from "valibot"
import { authenticatedUserIsMemberOfGitHubOrg, userIsPublicMemberOfGitHubOrg } from "../github"
import {
authenticatedUserIsMemberOfGitHubOrg,
getGitHubRepoMetadata,
userIsPublicMemberOfGitHubOrg
} from "../github"
import type { ExtensionPublishValidationData } from "../models"
import type { NpmPkgMetadata } from "../npm/models"
import { getInfoFromRekorLog } from "../sigstore"
@ -205,6 +209,7 @@ export function jsrPackageExists(scope: string, name: string, version?: string):
/**
* Validate a Jsr package as a Kunkun extension
* !This function will also run in frontend, so if there is any verification logic that must be run in backend, do not add it here
* - check if jsr pkg is linked to a github repo
* - check if jsr pkg is signed with github action
* - check if user's github username is the same as repo's owner name
@ -368,6 +373,7 @@ export async function validateJsrPackageAsKunkunExtension(payload: {
}
}
const rekorInfo = await getInfoFromRekorLog(rekorLogId)
return {
data: {
pkgJson: parseResult.output,

View File

@ -2,6 +2,7 @@ import { ExtPackageJson, License } from "@kksh/api/models"
import * as v from "valibot"
import {
authenticatedUserIsMemberOfGitHubOrg,
getGitHubRepoMetadata,
parseGitHubRepoFromUri,
userIsPublicMemberOfGitHubOrg
} from "../github"
@ -237,6 +238,7 @@ export async function validateNpmPackageAsKunkunExtension(payload: {
provenance.summary.sourceRepositoryDigest,
parseResult.output.readme ?? "README.md"
)
return {
data: {
pkgJson: parseResult.output,

View File

@ -20,7 +20,10 @@ export const ExtPublishMetadata = v.object({
repo: v.string("GitHub repo of the extension"),
owner: v.string("GitHub owner of the extension"),
commit: v.string("Commit hash of the extension"),
workflowPath: v.string("Workflow path of the extension")
workflowPath: v.string("Workflow path of the extension"),
repoNodeId: v.optional(
v.string("GitHub repo node ID of the extension (a string, not the number id)")
)
})
)
})

View File

@ -12,8 +12,7 @@
// let className = ""
// export { className as class }
let { locations = [], class: className }: { class?: string; locations?: [number, number][] } =
$props()
let { locations, class: className }: { class?: string; locations?: [number, number][] } = $props()
let pointerInteracting: number | null = null
let pointerInteractionMovement = 0
let canvas: HTMLCanvasElement
@ -54,24 +53,25 @@
baseColor: [0.3, 0.3, 0.3],
markerColor: [251 / 255, 100 / 255, 21 / 255],
glowColor: [1, 1, 1],
markers: locations.map((location) => {
markers: locations
? locations.map((location) => {
return {
location: location,
size: 0.03
}
}),
// [
// { location: [14.5995, 120.9842], size: 0.03 },
// { location: [19.076, 72.8777], size: 0.03 },
// { location: [23.8103, 90.4125], size: 0.05 },
// { location: [30.0444, 31.2357], size: 0.07 },
// { location: [39.9042, 116.4074], size: 0.08 },
// { location: [-23.5505, -46.6333], size: 0.05 },
// { location: [19.4326, -99.1332], size: 0.04 },
// { location: [40.7128, -74.006], size: 0.1 },
// { location: [34.6937, 135.5022], size: 0.05 },
// { location: [41.0082, 28.9784], size: 0.06 }
// ],
})
: [
{ location: [14.5995, 120.9842], size: 0.03 },
{ location: [19.076, 72.8777], size: 0.03 },
{ location: [23.8103, 90.4125], size: 0.05 },
{ location: [30.0444, 31.2357], size: 0.07 },
{ location: [39.9042, 116.4074], size: 0.08 },
{ location: [-23.5505, -46.6333], size: 0.05 },
{ location: [19.4326, -99.1332], size: 0.04 },
{ location: [40.7128, -74.006], size: 0.1 },
{ location: [34.6937, 135.5022], size: 0.05 },
{ location: [41.0082, 28.9784], size: 0.06 }
],
// onRender: (state) => {
// if (!pointerInteracting) {
// // Called on every animation frame.

View File

@ -16,7 +16,7 @@
style?: HTMLAttributes<HTMLAnchorElement>["style"]
class?: HTMLAttributes<HTMLAnchorElement>["class"]
children: Snippet
ref: HTMLAnchorElement | HTMLButtonElement | null
ref?: HTMLAnchorElement | HTMLButtonElement | null
} = $props()
// @ts-expect-error window.__TAURI_INTERNALS__ is not defined in the browser

View File

@ -19,6 +19,7 @@
} = $props()
const workflowRunId = githubActionInvocationId.split("/").at(-3)
const workflowRunUrl = `https://github.com/${repoOwner}/${repoName}/actions/runs/${workflowRunId}/workflow`
const giteaMirrorUrl = `https://gitea.kunkun.sh/kunkun-extensions-mirror/${repoOwner}-${repoName}`
</script>
<Card.Root>
@ -60,6 +61,12 @@
class="underline">Transparentcy log entry</a
>
</p>
<p class="flex flex-col text-sm sm:flex-row">
<strong class="mt-2 inline-block w-28 md:mt-0">Mirror</strong>
<a href={giteaMirrorUrl} target="_blank" rel="noreferrer" class="underline">
Mirror Repo
</a>
</p>
</div>
</Card.Content>
</Card.Root>

View File

@ -4,7 +4,7 @@
import { ExtPackageJson, IconEnum, KunkunExtManifest } from "@kksh/api/models"
import { ExtPublishMetadata, ExtPublishSourceTypeEnum } from "@kksh/supabase/models"
import { type Tables } from "@kksh/supabase/types"
import { Badge, Button, ScrollArea, Separator } from "@kksh/svelte5"
import { Badge, Button, ScrollArea, Separator, Tooltip } from "@kksh/svelte5"
import { Constants, IconMultiplexer } from "@kksh/ui"
import { cn } from "@kksh/ui/utils"
import { CircleCheckBigIcon, MoveRightIcon, Trash2Icon } from "lucide-svelte"
@ -186,7 +186,7 @@
<Button onclick={onInstallSelected}>Install</Button>
{/if}
</div>
<div class="mt-2 flex gap-2">
<div class="mt-2 flex flex-col gap-2 md:flex-row">
{#if metadata && metadata.sourceType === ExtPublishSourceTypeEnum.jsr}
<a href={metadata.source} target="_blank">
<Icon class="h-10 w-10" icon="vscode-icons:file-type-jsr" />
@ -201,7 +201,7 @@
href={`https://github.com/${metadata.git.owner}/${metadata.git.repo}/tree/${metadata.git.commit}`}
target="_blank"
>
<Badge class="h-8 space-x-2" variant="secondary">
<Badge class="min-h-8 space-x-2" variant="secondary">
<Icon class="h-6 w-6" icon="mdi:github" />
<span>{metadata.git.owner}/{metadata.git.repo}</span>
</Badge>