diff --git a/.gitignore b/.gitignore index 46633af8..86e8027e 100644 --- a/.gitignore +++ b/.gitignore @@ -88,4 +88,4 @@ docs/cli.md /install.sh /.envrc -/config.json +/sunbeam.json diff --git a/.vscode/launch.json b/.vscode/launch.json index 38762e81..748642c7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,8 +6,7 @@ "type": "go", "request": "launch", "console": "integratedTerminal", - "program": "${workspaceFolder}", - "args": [] + "program": "${workspaceFolder}" }, ], } diff --git a/.vscode/settings.json b/.vscode/settings.json index 4c97998a..085c3d4d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,7 +6,7 @@ "yaml.validate": false, "deno.enablePaths": [ "./extensions", - "./cmd/templates", - "./scripts" + "./scripts", + "pkg/typescript" ] } diff --git a/cmd/custom.go b/cmd/custom.go index a71e107f..33dcf1b7 100644 --- a/cmd/custom.go +++ b/cmd/custom.go @@ -15,12 +15,12 @@ import ( "github.com/spf13/cobra" ) -func NewCmdCustom(alias string, extension extensions.Extension, preferences map[string]any) (*cobra.Command, error) { +func NewCmdCustom(alias string, extension extensions.Extension) (*cobra.Command, error) { rootCmd := &cobra.Command{ Use: alias, - Short: extension.Title, - Long: extension.Description, + Short: extension.Manifest.Title, + Long: extension.Manifest.Description, Args: cobra.NoArgs, GroupID: CommandGroupExtension, RunE: func(cmd *cobra.Command, args []string) error { @@ -39,13 +39,21 @@ func NewCmdCustom(alias string, extension extensions.Extension, preferences map[ return err } if input.Preferences == nil { - input.Preferences = preferences + input.Preferences = extension.Config.Preferences } return runExtension(extension, input) } - return cmd.Usage() + rootList := tui.NewRootList(extension.Manifest.Title, func() (extensions.ExtensionMap, []types.ListItem, error) { + extensionMap := map[string]extensions.Extension{ + alias: extension, + } + + return extensionMap, RootItems(nil, extensionMap), nil + }) + + return tui.Draw(rootList) }, } @@ -53,7 +61,7 @@ func NewCmdCustom(alias string, extension extensions.Extension, preferences map[ rootCmd.CompletionOptions.DisableDefaultCmd = true rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) - for _, command := range extension.Commands { + for _, command := range extension.Manifest.Commands { command := command parts := strings.Split(command.Name, ".") cmd := &cobra.Command{ @@ -91,9 +99,8 @@ func NewCmdCustom(alias string, extension extensions.Extension, preferences map[ } input := types.Payload{ - Command: command.Name, - Preferences: preferences, - Params: params, + Command: command.Name, + Params: params, } if !isatty.IsTerminal(os.Stdin.Fd()) { diff --git a/cmd/root.go b/cmd/root.go index c8d44151..607d2303 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -58,7 +58,7 @@ func NewRootCmd() (*cobra.Command, error) { return nil, cobra.ShellCompDirectiveDefault } - extension, err := ExtractManifest(entrypoint) + extension, err := extensions.ExtractManifest(entrypoint) if err != nil { return nil, cobra.ShellCompDirectiveDefault } @@ -80,25 +80,22 @@ See https://pomdtr.github.io/sunbeam for more information.`, } if len(args) == 0 { - rootList := tui.NewRootList("Sunbeam", func() (extensions.ExtensionMap, []types.ListItem, map[string]types.Preferences, error) { + rootList := tui.NewRootList("Sunbeam", func() (extensions.ExtensionMap, []types.ListItem, error) { cfg, err := config.Load() if err != nil { - return nil, nil, nil, err + return nil, nil, err } - preferences := make(map[string]types.Preferences) extensionMap := make(map[string]extensions.Extension) - for alias, ref := range cfg.Extensions { - preferences[alias] = ref.Preferences - - extension, err := LoadExtension(alias, ref.Origin) + for alias, extensionConfig := range cfg.Extensions { + extension, err := extensions.LoadExtension(extensionConfig) if err != nil { continue } extensionMap[alias] = extension } - return extensionMap, RootItems(cfg, extensionMap), preferences, nil + return extensionMap, RootItems(cfg.Oneliners, extensionMap), nil }) return tui.Draw(rootList) } @@ -164,12 +161,19 @@ See https://pomdtr.github.io/sunbeam for more information.`, scriptPath = s } - extension, err := ExtractManifest(scriptPath) + manifest, err := extensions.ExtractManifest(scriptPath) if err != nil { return fmt.Errorf("error loading extension: %w", err) } - rootCmd, err := NewCmdCustom(filepath.Base(scriptPath), extension, nil) + extension := extensions.Extension{ + Manifest: manifest, + Config: extensions.Config{ + Origin: scriptPath, + }, + } + + rootCmd, err := NewCmdCustom(filepath.Base(scriptPath), extension) if err != nil { return fmt.Errorf("error loading extension: %w", err) } @@ -247,18 +251,17 @@ See https://pomdtr.github.io/sunbeam for more information.`, Title: "Extension Commands:", }) - for alias, ref := range cfg.Extensions { - extension, err := LoadExtension(alias, ref.Origin) + for alias, extensionConfig := range cfg.Extensions { + extension, err := extensions.LoadExtension(extensionConfig) if err != nil { fmt.Fprintf(os.Stderr, "error loading extension %s: %s\n", alias, err) continue } - command, err := NewCmdCustom(alias, extension, ref.Preferences) + command, err := NewCmdCustom(alias, extension) if err != nil { return nil, err } - rootCmd.AddCommand(command) } @@ -300,15 +303,15 @@ func buildDoc(command *cobra.Command) (string, error) { return out.String(), nil } -func RootItems(cfg config.Config, extensionMap map[string]extensions.Extension) []types.ListItem { +func RootItems(oneliners map[string]config.Oneliner, extensionMap map[string]extensions.Extension) []types.ListItem { var items []types.ListItem - for _, oneliner := range cfg.Oneliners { + for title, oneliner := range oneliners { if strings.HasPrefix(oneliner.Cwd, "~") { oneliner.Cwd = strings.Replace(oneliner.Cwd, "~", os.Getenv("HOME"), 1) } item := types.ListItem{ - Id: fmt.Sprintf("root - %s", oneliner.Title), - Title: oneliner.Title, + Id: fmt.Sprintf("root - %s", title), + Title: title, Accessories: []string{"Oneliner"}, Actions: []types.Action{ { @@ -330,39 +333,6 @@ func RootItems(cfg config.Config, extensionMap map[string]extensions.Extension) items = append(items, item) } - for alias, ref := range cfg.Extensions { - extension, ok := extensionMap[alias] - if !ok { - continue - } - - for _, rootItem := range ref.Root { - items = append(items, types.ListItem{ - Id: fmt.Sprintf("%s - %s", alias, rootItem.Title), - Title: rootItem.Title, - Accessories: []string{extension.Title}, - Actions: []types.Action{ - { - Title: "Run", - Type: types.ActionTypeRun, - Extension: alias, - Command: rootItem.Command, - Params: rootItem.Params, - Exit: true, - }, - { - Title: "Copy Origin", - Key: "c", - Type: types.ActionTypeCopy, - Target: extension.Origin, - Exit: true, - }, - }, - }) - - } - } - for alias, extension := range extensionMap { items = append(items, ExtensionRootItems(alias, extension)...) } @@ -372,11 +342,11 @@ func RootItems(cfg config.Config, extensionMap map[string]extensions.Extension) func ExtensionRootItems(alias string, extension extensions.Extension) []types.ListItem { var items []types.ListItem - for _, rootItem := range extension.RootItems() { + for _, rootItem := range extension.Root() { listItem := types.ListItem{ Id: fmt.Sprintf("%s - %s", alias, rootItem.Title), Title: rootItem.Title, - Accessories: []string{extension.Title}, + Accessories: []string{extension.Manifest.Title}, Actions: []types.Action{ { Title: "Run", @@ -389,21 +359,11 @@ func ExtensionRootItems(alias string, extension extensions.Extension) []types.Li }, } - if extension.Type == extensions.ExtensionTypeLocal { - listItem.Actions = append(listItem.Actions, types.Action{ - Title: "Edit", - Key: "e", - Type: types.ActionTypeEdit, - Target: extension.Entrypoint, - Reload: true, - }) - } - listItem.Actions = append(listItem.Actions, types.Action{ Title: "Copy Origin", Key: "c", Type: types.ActionTypeCopy, - Target: extension.Origin, + Target: extension.Config.Origin, Exit: true, }) diff --git a/cmd/upgrade.go b/cmd/upgrade.go index b2c12613..56e34e6c 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -1,23 +1,12 @@ package cmd import ( - "crypto/sha1" - "encoding/hex" - "encoding/json" "fmt" - "io" - "net/http" - "os" "os/exec" "path/filepath" - "strings" - "github.com/acarl005/stripansi" "github.com/pomdtr/sunbeam/internal/config" "github.com/pomdtr/sunbeam/internal/extensions" - "github.com/pomdtr/sunbeam/internal/utils" - "github.com/pomdtr/sunbeam/pkg/schemas" - "github.com/pomdtr/sunbeam/pkg/types" "github.com/spf13/cobra" ) @@ -35,17 +24,16 @@ func NewCmdUpgrade(cfg config.Config) *cobra.Command { } } - for alias, ref := range cfg.Extensions { - if len(args) > 0 && alias != args[0] { - continue + for alias, extensionConfig := range cfg.Extensions { + if extensionConfig.Hooks.Upgrade != "" { + cmd := exec.Command("sh", "-c", extensionConfig.Hooks.Upgrade) + cmd.Dir = filepath.Dir(extensionConfig.Origin) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to run update hook: %s", err) + } } - extension, err := ExtractManifest(ref.Origin) - if err != nil { - return err - } - - if _, err := cacheExtension(alias, extension); err != nil { + if _, err := extensions.UpgradeExtension(extensionConfig); err != nil { return err } @@ -58,150 +46,3 @@ func NewCmdUpgrade(cfg config.Config) *cobra.Command { return cmd } - -func LoadExtension(alias string, origin string) (extensions.Extension, error) { - cacheDir := filepath.Join(utils.CacheHome(), "extensions") - if err := os.MkdirAll(cacheDir, 0755); err != nil { - return extensions.Extension{}, err - } - - cachePath := filepath.Join(cacheDir, alias+".json") - if _, err := os.Stat(cachePath); err == nil { - // check if cache is valid - var extension extensions.Extension - extensionBytes, err := os.ReadFile(cachePath) - if err != nil { - return extensions.Extension{}, err - } - - if err := json.Unmarshal(extensionBytes, &extension); err != nil { - return extensions.Extension{}, err - } - - entrypointInfo, err := os.Stat(extension.Metadata.Entrypoint) - if err != nil { - return extensions.Extension{}, err - } - - cacheInfo, err := os.Stat(cachePath) - if err != nil { - return extensions.Extension{}, err - } - - if extension.Metadata.Origin == origin && entrypointInfo.ModTime().Before(cacheInfo.ModTime()) { - return extension, nil - } - } - - extension, err := ExtractManifest(origin) - if err != nil { - return extensions.Extension{}, err - } - - return cacheExtension(alias, extension) -} - -func cacheExtension(alias string, extension extensions.Extension) (extensions.Extension, error) { - extensionBytes, err := json.MarshalIndent(extension, "", " ") - if err != nil { - return extensions.Extension{}, err - } - - cacheDir := filepath.Join(utils.CacheHome(), "extensions") - if err := os.MkdirAll(cacheDir, 0755); err != nil { - return extensions.Extension{}, err - } - - cachePath := filepath.Join(cacheDir, alias+".json") - - if err := os.WriteFile(cachePath, extensionBytes, 0644); err != nil { - return extensions.Extension{}, err - } - - return extension, nil -} - -func ExtractManifest(origin string) (extensions.Extension, error) { - var entrypoint string - var extensionType extensions.ExtensionType - if strings.HasPrefix(origin, "http://") || strings.HasPrefix(origin, "https://") { - extensionType = extensions.ExtensionTypeHttp - resp, err := http.Get(origin) - if err != nil { - return extensions.Extension{}, err - } - - h := sha1.New() - h.Write([]byte(origin)) - sha1_hash := hex.EncodeToString(h.Sum(nil)) - - cacheDir := filepath.Join(utils.CacheHome(), "scripts") - if err := os.MkdirAll(cacheDir, 0755); err != nil { - return extensions.Extension{}, err - } - - entrypoint = filepath.Join(utils.CacheHome(), "scripts", sha1_hash+filepath.Ext(origin)) - f, err := os.Create(entrypoint) - if err != nil { - return extensions.Extension{}, err - } - defer f.Close() - - if _, err := io.Copy(f, resp.Body); err != nil { - return extensions.Extension{}, err - } - - if err := f.Close(); err != nil { - return extensions.Extension{}, err - } - } else { - extensionType = extensions.ExtensionTypeLocal - entrypoint = origin - if strings.HasPrefix(entrypoint, "~") { - homedir, err := os.UserHomeDir() - if err != nil { - return extensions.Extension{}, err - } - - entrypoint = filepath.Join(homedir, entrypoint[1:]) - } - } - - if err := os.Chmod(entrypoint, 0755); err != nil { - return extensions.Extension{}, err - } - - cmd := exec.Command(entrypoint) - cmd.Dir = filepath.Dir(entrypoint) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "SUNBEAM=1") - - manifestBytes, err := cmd.Output() - if err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - return extensions.Extension{}, fmt.Errorf("command failed: %s", stripansi.Strip(string(exitErr.Stderr))) - } - - return extensions.Extension{}, err - } - - if err := schemas.ValidateManifest(manifestBytes); err != nil { - return extensions.Extension{}, err - } - - var manifest types.Manifest - if err := json.Unmarshal(manifestBytes, &manifest); err != nil { - return extensions.Extension{}, err - } - - extension := extensions.Extension{ - Manifest: manifest, - Metadata: extensions.Metadata{ - Type: extensionType, - Origin: origin, - Entrypoint: entrypoint, - }, - } - - return extension, nil -} diff --git a/docs/reference/config.md b/docs/reference/config.md index 0e8b34e7..1ba52828 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -11,18 +11,9 @@ If no config is found, sunbeam will create one. ```json { // additional items to show in the root list - "oneliners": [ - { - // title of the item shown in the list - "title": "Search Overreact Feed", - // command to run when the item is chosen - "command":\ "sunbeam rss show --url https://overreacted.io/rss.xml" - }, - { - "title": "View System Resources", - "command": "htop" - } - ], + "oneliners": { + "View System Resources": "htop" + }, "extensions": { "github": { "origin": "~/Developer/github.com/pomdtr/sunbeam/extensions/github.sh", @@ -31,7 +22,7 @@ If no config is found, sunbeam will create one. "token": "xxxx" }, // additional root items to show - "root": [ + "items": [ { "title": "List Sunbeam Issues", "command": "list-issues", diff --git a/docs/reference/schemas/manifest.md b/docs/reference/schemas/manifest.md index 5ce3ae64..149bd58a 100644 --- a/docs/reference/schemas/manifest.md +++ b/docs/reference/schemas/manifest.md @@ -9,8 +9,8 @@ It contains the title, description and the list of commands provided by the exte "title": "DevDocs", // the description of the extension, will be shown in usage string "description": "Search DevDocs.io", - // additional items to show in the root list (optional) - "root": [ + // items to show in the root list (optional) + "items": [ { "title": "Search Deno Docs", "command": "list-entries", diff --git a/extensions/bitwarden.sh b/extensions/bitwarden.sh index 445118b6..f408d0b0 100755 --- a/extensions/bitwarden.sh +++ b/extensions/bitwarden.sh @@ -4,19 +4,20 @@ if [ $# -eq 0 ]; then sunbeam query -n '{ title: "Bitwarden Vault", description: "Search your Bitwarden passwords", - root: [ + items: [ { command: "list-passwords" } ], - requirements: [ - { name: "bw", link: "https://bitwarden.com/help/article/cli/" } - ], commands: [ { name: "list-passwords", title: "List Passwords", mode: "list" } + ], + requirements: [ + { name: "bw", link: "https://bitwarden.com/help/article/cli/" } ] + }' exit 0 fi diff --git a/extensions/deno-deploy.ts b/extensions/deno-deploy.ts new file mode 100755 index 00000000..944650aa --- /dev/null +++ b/extensions/deno-deploy.ts @@ -0,0 +1,232 @@ +#!/usr/bin/env -S deno run -A + +import type * as sunbeam from "npm:sunbeam-types@0.25.1" +import * as dates from "npm:date-fns" + +if (Deno.args.length == 0) { + const manifest: sunbeam.Manifest = { + title: "Deno Deploy", + items: [ + { command: "projects" } + ], + commands: [ + { + name: "projects", + title: "List Projects", + mode: "list", + }, + { + name: "deployments", + title: "List Deployments", + mode: "list", + params: [ + { name: "project", title: "Project", required: true, type: "text" } + ] + }, + { + name: "playground", + title: "View Playground", + mode: "detail", + params: [ + { name: "project", title: "Project", required: true, type: "text" } + ] + } + ] + } + + console.log(JSON.stringify(manifest)); + Deno.exit(0); +} + +const payload = JSON.parse(Deno.args[0]) as sunbeam.Payload; +const deployToken = payload.preferences.token; +if (!deployToken) { + console.error("Missing deploy token"); + Deno.exit(1); +} + +try { + const res = await run(payload); + if (res) { + console.log(JSON.stringify(res)); + } +} catch (e) { + console.error(e); + Deno.exit(1); +} + +async function run(payload: sunbeam.Payload) { + switch (payload.command) { + case "projects": { + const resp = await fetchDeployAPI("/projects"); + if (resp.status != 200) { + throw new Error("Failed to fetch projects"); + } + const projects = await resp.json(); + + return { + items: projects.map((project: any) => { + const item: sunbeam.ListItem = { + title: project.name, + accessories: [project.type], + actions: [] + } + + if (project.type == "git") { + const repo = project.git.repository + item.actions?.push({ + title: "List Deployments", + type: "run", + command: "deployments", + params: { + project: project.name, + } + }, { + title: "Open Repository", + type: "open", + target: `https://github.com/${repo.owner}/${repo.name}`, + exit: true, + }) + } else if (project.type == "playground") { + item.actions?.push({ + title: "View Playground", + type: "run", + command: "view-playground", + params: { + project: project.name, + } + }, { + title: "Open Playground", + type: "open", + target: `https://dash.deno.com/playground/${project.id}`, + exit: true, + }) + } + + if (project.hasProductionDeployment) { + const domains = project.productionDeployment.deployment.domainMappings + const domain = domains.length ? domains[domains.length - 1].domain : "No domain" + item.subtitle = domain + item.actions?.push({ + title: "Open Production URL", + type: "open", + target: `https://${domain}`, + exit: true, + }) + } + + item.actions?.push({ + title: "Open Dashboard", + type: "open", + target: `https://dash.deno.com/projects/${project.id}`, + exit: true, + }, { + title: "Copy Dashboard URL", + type: "copy", + key: "c", + text: `https://dash.deno.com/projects/${project.id}`, + exit: true, + }) + + + return item + }) + } as sunbeam.List; + } + case "playground": { + const name = payload.params.project as string; + const resp = await fetchDeployAPI(`/projects/${name}`); + if (resp.status != 200) { + throw new Error("Failed to fetch project"); + } + + const project = await resp.json(); + if (project.type != "playground") { + throw new Error("Project is not a playground"); + } + + const snippet = project.playground.snippet; + const lang = project.playground.mediaType + return { + format: "markdown", + text: `\`\`\`${lang}\n${snippet}\n\`\`\``, + actions: [ + { + title: "Copy Snippet", + key: "c", + type: "copy", + text: snippet, + exit: true + }, + { + title: "Open in Browser", + type: "open", + target: `https://dash.deno.com/playground/${project.id}`, + exit: true + } + ], + } as sunbeam.Detail; + } + case "deployments": { + const project = payload.params.project as string; + + const resp = await fetchDeployAPI(`/projects/${project}/deployments`); + if (resp.status != 200) { + throw new Error("Failed to fetch deployments"); + } + + const [deployments] = await resp.json(); + return { + items: deployments.map(({ id, createdAt, deployment, relatedCommit }: any) => { + const item = { + title: id, + accessories: [dates.formatDistance(new Date(createdAt), new Date(), { + addSuffix: true, + })], + actions: [], + } as sunbeam.ListItem; + + if (deployment.domainMappings?.length) { + item.actions?.push({ + title: "Open URL", + type: "open", + target: `https://${deployment.domainMappings[0].domain}`, + exit: true, + }) + } + + if (relatedCommit) { + item.title = relatedCommit.message; + item.actions?.push({ + title: "Open Commit", + type: "open", + target: relatedCommit.url, + exit: true, + }) + } + + return item; + }) + } as sunbeam.List; + } + case "logs": { + const { project, deployment } = payload.params as { project: string, deployment: string }; + const resp = await fetchDeployAPI(`/projects/${project}/deployments/${deployment}`); + if (resp.status != 200) { + throw new Error("Failed to fetch deployment"); + } + + + } + } +} + +function fetchDeployAPI(endpoint: string, init?: RequestInit) { + return fetch(`https://dash.deno.com/api${endpoint}`, { + ...init, + headers: { + ...init?.headers, + "Authorization": `Bearer ${deployToken}`, + } + }) +} diff --git a/extensions/devdocs.sh b/extensions/devdocs.sh index d10fdd80..96f7166d 100755 --- a/extensions/devdocs.sh +++ b/extensions/devdocs.sh @@ -7,7 +7,7 @@ if [ $# -eq 0 ]; then sunbeam query -n '{ title: "DevDocs", description: "Search DevDocs.io", - root: [ + items: [ { command: "list-docsets" } ], commands: [ diff --git a/extensions/files.py b/extensions/files.py index 1e5b86b8..dac47634 100755 --- a/extensions/files.py +++ b/extensions/files.py @@ -11,7 +11,7 @@ "title": "File Browser", "description": "Browse files and folders", "requirements": [{"name": "python3", "link": "https://www.python.org/"}], - "root": [ + "items": [ { "title": "Browse Home Directory", "command": "ls", diff --git a/extensions/gists.ts b/extensions/gists.ts index 7cf466a8..1905a160 100755 --- a/extensions/gists.ts +++ b/extensions/gists.ts @@ -1,11 +1,15 @@ #!/usr/bin/env -S deno run -A -import type * as sunbeam from "npm:sunbeam-types@0.23.31" +import type * as sunbeam from "npm:sunbeam-types@0.25.1" import * as path from "https://deno.land/std/path/mod.ts"; if (Deno.args.length == 0) { const manifest: sunbeam.Manifest = { title: "Gists", + items: [ + { command: "search" }, + { command: "create" } + ], commands: [ { name: "search", diff --git a/extensions/github.ts b/extensions/github.ts index 01a23755..63eaf0b6 100755 --- a/extensions/github.ts +++ b/extensions/github.ts @@ -1,8 +1,9 @@ #!/usr/bin/env deno run -A -import type * as sunbeam from "npm:sunbeam-types@0.23.29"; +import * as sunbeam from "npm:sunbeam-types@0.25.1" import * as base64 from "https://deno.land/std@0.202.0/encoding/base64.ts"; + if (Deno.args.length == 0) { const manifest: sunbeam.Manifest = { title: "GitHub", @@ -13,7 +14,7 @@ if (Deno.args.length == 0) { link: "https://deno.com" } ], - root: [ + items: [ { command: "search-repos" } diff --git a/extensions/google.sh b/extensions/google.sh index 1e8a9052..4e51ee66 100755 --- a/extensions/google.sh +++ b/extensions/google.sh @@ -6,7 +6,7 @@ if [ $# -eq 0 ]; then sunbeam query -n '{ title: "Google Search", description: "Search Google", - root: [ + items: [ { command: "search" } ], commands: [ diff --git a/extensions/hackernews.ts b/extensions/hackernews.ts index a4588a9d..53e434c3 100755 --- a/extensions/hackernews.ts +++ b/extensions/hackernews.ts @@ -2,7 +2,7 @@ import Parser from "npm:rss-parser"; import { formatDistance } from "npm:date-fns"; -import * as sunbeam from "npm:sunbeam-types@0.23.28" +import * as sunbeam from "npm:sunbeam-types@0.25.1" if (Deno.args.length == 0) { const manifest: sunbeam.Manifest = { @@ -14,7 +14,7 @@ if (Deno.args.length == 0) { link: "https://deno.com" } ], - root: [ + items: [ { title: "Front Page", command: "browse", diff --git a/extensions/macapps.sh b/extensions/macapps.sh index d94885fd..b695e746 100755 --- a/extensions/macapps.sh +++ b/extensions/macapps.sh @@ -7,7 +7,7 @@ if [ $# -eq 0 ]; then title: "Mac Apps", platforms: ["macos"], description: "Open your favorite apps", - root: [ + items: [ { command: "list" } ], commands: [ diff --git a/extensions/manifest.json b/extensions/manifest.json new file mode 100644 index 00000000..0ca1ea5f --- /dev/null +++ b/extensions/manifest.json @@ -0,0 +1 @@ +{"title":"DevDocs","description":"Search DevDocs.io","items":[{"title":"","command":"list-docsets","params":null}],"commands":[{"name":"list-docsets","title":"List Docsets","mode":"list"},{"name":"list-entries","title":"List Entries from Docset","params":[{"type":"text","name":"slug","title":"Slug","required":true}],"mode":"list"}]} diff --git a/extensions/meteo.sh b/extensions/meteo.sh index f1fc2b42..281ac199 100755 --- a/extensions/meteo.sh +++ b/extensions/meteo.sh @@ -6,7 +6,7 @@ if [ $# -eq 0 ]; then sunbeam query -n '{ title: "Meteo", description: "Show Meteo", - root: [ + items: [ { command: "show" } ], commands: [ diff --git a/extensions/oneliners.sh b/extensions/oneliners.sh deleted file mode 100755 index f825f34a..00000000 --- a/extensions/oneliners.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/sh - -if [ $# -eq 0 ]; then - sunbeam query -n '{ - title: "Oneliners", - commands: [ - { - name: "list", - title: "Manage Oneliners", - mode: "list", - }, - { - name: "run", - title: "Run Oneliner", - mode: "tty", - hidden: true, - params: [ - { name: "index", title: "Index", type: "number", required: true } - ] - }, - { - name: "edit", - hidden: true, - title: "Edit Oneliner", - mode: "silent", - params: [ - { name: "index", title: "Index", type: "number", required: true }, - { title: "Title", name: "title", type: "text", required: true }, - { title: "Command", name: "command", type: "textarea", required: true }, - { title: "Directory", name: "cwd", placeholder: "~", type: "text", required: true }, - { title: "Exit", name: "exit", type: "checkbox", label: "Exit after running command", required: true } - ] - }, - { - name: "delete", - title: "Delete Oneliner", - hidden: true, - mode: "silent", - params: [ - { name: "index", title: "Index", type: "number", required: true } - ] - }, - { - name: "create", - title: "Create Oneliner", - mode: "silent", - params: [ - { name: "title", title: "Title", type: "text", placeholder: "Edit Bash Config", required: true }, - { name: "command", title: "Command", placeholder: "vim ~/.bashrc", type: "textarea", required: true }, - { name: "cwd", title: "Directory", type: "text", placeholder: "~", required: false }, - { name: "exit", title: "Exit", type: "checkbox", label: "Exit after running command", required: false } - ] - } - ] - }' - exit 0 -fi - -if [ -n "$SUNBEAM_CONFIG" ]; then - CONFIG_PATH="$SUNBEAM_CONFIG" -elif [ -n "$XDG_CONFIG_HOME" ]; then - CONFIG_PATH="$XDG_CONFIG_HOME/sunbeam/config.json" -else - CONFIG_PATH="$HOME/.config/sunbeam/config.json" -fi - - -COMMAND="$(echo "$1" | sunbeam query -r ".command")" -if [ "$COMMAND" = "list" ]; then - sunbeam query '.oneliners | to_entries | { - actions: [ - { title: "Create Oneliner", key: "n", type: "run", command: "create", reload: true } - ], - items: map({ - title: .value.title, - subtitle: .value.command, - actions: [ - { title: "Edit Oneliner", key: "e", type: "run", "command": "edit", params: { - index: .key, - title: { default: .value.title }, - command: { default: .value.command }, - exit: { default: (.value.exit // false) } - }, reload: true}, - { title: "Copy Command", key: "c", type: "copy", text: .value.command, exit: true }, - { title: "Run Oneliner", key: "r", type: "run", command: "run", params: { index: .key }, exit: (.value.exit // false) }, - { title: "Delete Oneliner", key: "d", type: "run", command: "delete", params: { index: .key }, reload: true }, - { title: "Create Oneliner", key: "n", type: "run", command: "create", reload: true } - ] - }) - }' "$CONFIG_PATH" -elif [ "$COMMAND" = "run" ]; then - INDEX=$(echo "$1" | sunbeam query -r ".params.index") - ONELINER_COMMAND=$(sunbeam query -r ".oneliners[$INDEX].command" "$CONFIG_PATH") - sh -c "$ONELINER_COMMAND" -elif [ "$COMMAND" = "delete" ]; then - INDEX=$(echo "$1" | sunbeam query -r ".params.index") - # shellcheck disable=SC2016 - sunbeam query --in-place --argjson idx="$INDEX" 'del( - .oneliners[$idx] - )' "$CONFIG_PATH" -elif [ "$COMMAND" = "edit" ]; then - PARAMS=$(echo "$1" | sunbeam query -r ".params") - - # shellcheck disable=SC2016 - sunbeam query --in-place --argjson params="$PARAMS" '.oneliners[$params.index] = { - title: $params.title, - command: $params.command, - cwd: $params.cwd, - exit: $params.exit - }' "$CONFIG_PATH" - -elif [ "$COMMAND" = "create" ]; then - PARAMS=$(echo "$1" | sunbeam query -r ".params") - - # shellcheck disable=SC2016 - sunbeam query --in-place --argjson params="$PARAMS" '.oneliners += [ - $params - ]' "$CONFIG_PATH" -fi diff --git a/extensions/pipe.ts b/extensions/pipe.ts index 350039e4..efcea620 100755 --- a/extensions/pipe.ts +++ b/extensions/pipe.ts @@ -1,5 +1,5 @@ #!/usr/bin/env deno run -A -import * as sunbeam from "npm:sunbeam-types@0.23.19" +import * as sunbeam from "npm:sunbeam-types@0.25.1" import * as clipboard from "https://deno.land/x/copy_paste@v1.1.3/mod.ts"; @@ -13,6 +13,14 @@ if (Deno.args.length == 0) { link: "https://deno.com" } ], + items: [ + { + command: "urldecode", + }, + { + command: "urlencode", + } + ], commands: [ { name: "urldecode", diff --git a/extensions/raindrop.ts b/extensions/raindrop.ts index 44eecd62..d7721264 100755 --- a/extensions/raindrop.ts +++ b/extensions/raindrop.ts @@ -1,5 +1,5 @@ #!/usr/bin/env -S deno run -A -import * as sunbeam from "npm:sunbeam-types@0.23.29" +import * as sunbeam from "npm:sunbeam-types@0.25.1" if (Deno.args.length === 0) { const manifest: sunbeam.Manifest = { @@ -11,7 +11,7 @@ if (Deno.args.length === 0) { link: "https://deno.com" } ], - root: [ + items: [ { command: "search-bookmarks" } ], commands: [ diff --git a/extensions/rss.ts b/extensions/rss.ts index a4638d8d..3c2a3fdd 100755 --- a/extensions/rss.ts +++ b/extensions/rss.ts @@ -2,13 +2,13 @@ import Parser from "npm:rss-parser"; import { formatDistance } from "npm:date-fns"; -import * as sunbeam from "npm:sunbeam-types@0.23.29" +import * as sunbeam from "npm:sunbeam-types@0.25.1" if (Deno.args.length == 0) { const manifest: sunbeam.Manifest = { title: "RSS", description: "Manage your RSS feeds", - root: [ + items: [ { command: "list" } ], requirements: [ diff --git a/extensions/system.sh b/extensions/system.sh deleted file mode 100755 index 003bcd2a..00000000 --- a/extensions/system.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -set -eu - -if [ $# -eq 0 ]; then - sunbeam query -n '{ - title: "System", - description: "Control your system", - platforms: ["macos"], - commands: [ - { - name: "toggle-dark-mode", - title: "Toggle Dark Mode", - mode: "silent" - }, - { - name: "lock-screen", - title: "Lock Screen", - mode: "silent" - }, - { - name: "empty-trash", - title: "Empty Trash", - mode: "silent" - }, - { - name: "open-trash", - title: "Open Trash", - mode: "silent" - } - ] - }' - exit 0 -fi - -COMMAND=$(echo "$1" | sunbeam query -r '.command') -if [ "$COMMAND" = "toggle-dark-mode" ]; then - osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to not dark mode' -elif [ "$COMMAND" = "lock-screen" ]; then - osascript -e 'tell application "System Events" to keystroke "q" using {command down,control down}' -elif [ "$COMMAND" = "empty-trash" ]; then - osascript -e 'tell application "Finder" to empty trash' -elif [ "$COMMAND" = "open-trash" ]; then - osascript -e 'tell application "Finder" to open trash' -fi diff --git a/extensions/tailscale.ts b/extensions/tailscale.ts index b43e2167..a5bf4a21 100755 --- a/extensions/tailscale.ts +++ b/extensions/tailscale.ts @@ -1,5 +1,5 @@ #!/usr/bin/env -S deno run -A -import type * as sunbeam from "npm:sunbeam-types@0.23.28"; +import type * as sunbeam from "npm:sunbeam-types@0.25.1"; if (Deno.args.length == 0) { const manifest: sunbeam.Manifest = { @@ -15,6 +15,9 @@ if (Deno.args.length == 0) { link: "https://tailscale.com" } ], + items: [ + { command: "list-devices", } + ], commands: [ { name: "list-devices", diff --git a/extensions/tldr.sh b/extensions/tldr.sh index a4037391..2bd3cc2a 100755 --- a/extensions/tldr.sh +++ b/extensions/tldr.sh @@ -10,7 +10,7 @@ if [ $# -eq 0 ]; then { title: "Browse TLDR Pages", description: "Browse TLDR Pages", - root: [{command: "list"}], + items: [{ command: "list"}], requirements: [ { name: "tldr", link: "https://dbrgn.github.io/tealdeer/installing.html" } ], diff --git a/extensions/vscode.ts b/extensions/vscode.ts index b63d2316..c6ec0f1a 100755 --- a/extensions/vscode.ts +++ b/extensions/vscode.ts @@ -2,7 +2,7 @@ import { DB } from "https://deno.land/x/sqlite@v3.8/mod.ts"; import * as fs from "https://deno.land/std@0.203.0/fs/mod.ts"; -import type * as sunbeam from "npm:sunbeam-types@0.23.24"; +import type * as sunbeam from "npm:sunbeam-types@0.25.1"; import * as path from "https://deno.land/std@0.186.0/path/mod.ts"; if (Deno.args.length == 0) { @@ -15,6 +15,7 @@ if (Deno.args.length == 0) { link: "https://deno.com", }, ], + items: [{ command: "list-projects" }], commands: [ { name: "list-projects", diff --git a/go.mod b/go.mod index 0b4f088b..79939d3a 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/spf13/cobra v1.8.0 + github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 56b6d003..e83be865 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= @@ -91,6 +93,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw= +github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= diff --git a/internal/config/config.go b/internal/config/config.go index fab5a744..b6f85c59 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,47 +7,19 @@ import ( "os" "path/filepath" + "github.com/pomdtr/sunbeam/internal/extensions" "github.com/pomdtr/sunbeam/internal/utils" "github.com/pomdtr/sunbeam/pkg/schemas" - "github.com/pomdtr/sunbeam/pkg/types" + "github.com/tailscale/hujson" ) -//go:embed config.json +//go:embed sunbeam.json var configBytes []byte type Config struct { - Schema string `json:"$schema,omitempty"` - Oneliners []Oneliner `json:"oneliners,omitempty"` - Extensions map[string]ExtensionConfig `json:"extensions,omitempty"` -} - -type ExtensionConfig struct { - Origin string `json:"origin,omitempty"` - Preferences types.Preferences `json:"preferences,omitempty"` - Root []types.RootItem `json:"root,omitempty"` -} - -func (e *ExtensionConfig) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err == nil { - e.Origin = s - return nil - } - - var extensionRef struct { - Origin string `json:"origin,omitempty"` - Preferences map[string]any `json:"preferences,omitempty"` - Root []types.RootItem - } - - if err := json.Unmarshal(b, &extensionRef); err == nil { - e.Origin = extensionRef.Origin - e.Preferences = extensionRef.Preferences - e.Root = extensionRef.Root - return nil - } - - return fmt.Errorf("invalid extension ref: %s", string(b)) + Schema string `json:"$schema,omitempty"` + Oneliners map[string]Oneliner `json:"oneliners,omitempty"` + Extensions map[string]extensions.Config `json:"extensions,omitempty"` } func (cfg Config) Aliases() []string { @@ -60,19 +32,40 @@ func (cfg Config) Aliases() []string { } type Oneliner struct { - Title string `json:"title"` Command string `json:"command"` Cwd string `json:"cwd"` Exit bool `json:"exit"` } +func (o *Oneliner) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err == nil { + o.Command = s + return nil + } + + type Alias Oneliner + var alias Alias + if err := json.Unmarshal(b, &alias); err == nil { + o.Command = alias.Command + o.Cwd = alias.Cwd + o.Exit = alias.Exit + return nil + } + + return fmt.Errorf("invalid oneliner: %s", string(b)) +} + func Path() string { if env, ok := os.LookupEnv("SUNBEAM_CONFIG"); ok { return env } - return filepath.Join(utils.ConfigHome(), "config.json") + if _, err := os.Stat(filepath.Join(utils.ConfigHome(), "config.jsonc")); err == nil { + return filepath.Join(utils.ConfigHome(), "sunbeam.jsonc") + } + return filepath.Join(utils.ConfigHome(), "sunbeam.json") } func Load() (Config, error) { @@ -100,12 +93,17 @@ func Load() (Config, error) { return Config{}, err } - if err := schemas.ValidateConfig(configBytes); err != nil { + jsonBytes, err := hujson.Standardize(configBytes) + if err != nil { + return Config{}, err + } + + if err := schemas.ValidateConfig(jsonBytes); err != nil { return Config{}, fmt.Errorf("invalid config: %w", err) } var config Config - if err := json.Unmarshal(configBytes, &config); err != nil { + if err := json.Unmarshal(jsonBytes, &config); err != nil { return Config{}, fmt.Errorf("failed to unmarshal config: %w", err) } diff --git a/internal/config/config.json b/internal/config/sunbeam.json similarity index 69% rename from internal/config/config.json rename to internal/config/sunbeam.json index f7eab898..34a5157d 100644 --- a/internal/config/config.json +++ b/internal/config/sunbeam.json @@ -2,7 +2,7 @@ "extensions": { "devdocs": { "origin": "https://raw.githubusercontent.com/pomdtr/sunbeam/main/extensions/devdocs.sh", - "root": [ + "items": [ { "title": "Search Bash Docs", "command": "list-entries", @@ -14,11 +14,7 @@ }, "google": "https://raw.githubusercontent.com/pomdtr/sunbeam/main/extensions/google.sh" }, - "oneliners": [ - { - "title": "Open Sunbeam Docs", - "command": "sunbeam open https://pomdtr.github.io/sunbeam/introduction", - "exit": true - } - ] + "oneliners": { + "Open Sunbeam Docs": "sunbeam open https://pomdtr.github.io/sunbeam/introduction" + } } diff --git a/internal/extensions/extensions.go b/internal/extensions/extensions.go index c45e8909..5ad462eb 100644 --- a/internal/extensions/extensions.go +++ b/internal/extensions/extensions.go @@ -2,14 +2,21 @@ package extensions import ( "context" + "crypto/sha1" + "encoding/hex" "encoding/json" "errors" "fmt" + "io" + "net/http" "os" "os/exec" "path/filepath" + "strings" "github.com/acarl005/stripansi" + "github.com/pomdtr/sunbeam/internal/utils" + "github.com/pomdtr/sunbeam/pkg/schemas" "github.com/pomdtr/sunbeam/pkg/types" ) @@ -24,8 +31,63 @@ func (e ExtensionMap) List() []Extension { } type Extension struct { - types.Manifest `json:"manifest"` - Metadata + Manifest types.Manifest + Entrypoint string `json:"entrypoint"` + Config Config `json:"config"` +} + +type Config struct { + Origin string `json:"origin,omitempty"` + Preferences types.Preferences `json:"preferences,omitempty"` + Items []types.RootItem `json:"items,omitempty"` + Hooks Hooks `json:"hooks,omitempty"` +} + +func (c Config) ExtensionDir() string { + return filepath.Join(utils.CacheHome(), "extensions", SHA1(c.Origin)) +} + +func (c Config) Entrypoint() (string, error) { + if IsRemoteExtension(c.Origin) { + return filepath.Join(c.ExtensionDir(), "entrypoint"), nil + } + + entrypoint := c.Origin + if strings.HasPrefix(entrypoint, "~") { + entrypoint = strings.Replace(entrypoint, "~", os.Getenv("HOME"), 1) + } + + entrypoint, err := filepath.Abs(entrypoint) + if err != nil { + return "", err + } + + return entrypoint, nil +} + +type Hooks struct { + Install string `json:"install,omitempty"` + Upgrade string `json:"upgrade,omitempty"` +} + +func (e *Config) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err == nil { + e.Origin = s + return nil + } + + type Alias Config + + var alias Alias + if err := json.Unmarshal(b, &alias); err == nil { + e.Origin = alias.Origin + e.Preferences = alias.Preferences + e.Items = alias.Items + return nil + } + + return fmt.Errorf("invalid extension ref: %s", string(b)) } type Preferences map[string]any @@ -44,7 +106,7 @@ const ( ) func (e Extension) Command(name string) (types.CommandSpec, bool) { - for _, command := range e.Commands { + for _, command := range e.Manifest.Commands { if command.Name == name { return command, true } @@ -52,32 +114,23 @@ func (e Extension) Command(name string) (types.CommandSpec, bool) { return types.CommandSpec{}, false } -func (e Extension) RootItems() []types.RootItem { +func (e Extension) Root() []types.RootItem { rootItems := make([]types.RootItem, 0) - if e.Root != nil { - for _, rootItem := range e.Root { - command, ok := e.Command(rootItem.Command) - if !ok { - continue - } - - if rootItem.Title == "" { - rootItem.Title = command.Title - } + var items []types.RootItem + items = append(items, e.Manifest.Items...) + items = append(items, e.Config.Items...) - rootItems = append(rootItems, rootItem) + for _, rootItem := range items { + command, ok := e.Command(rootItem.Command) + if !ok { + continue } - } else { - for _, command := range e.Commands { - if command.Hidden { - continue - } - rootItems = append(rootItems, types.RootItem{ - Title: command.Title, - Command: command.Name, - }) + if rootItem.Title == "" { + rootItem.Title = command.Title } + + rootItems = append(rootItems, rootItem) } return rootItems @@ -89,7 +142,7 @@ func (e Extension) Run(input types.Payload) error { } func (ext Extension) CheckRequirements() error { - for _, requirement := range ext.Require { + for _, requirement := range ext.Manifest.Requirements { if _, err := exec.LookPath(requirement.Name); err != nil { return fmt.Errorf("missing requirement %s", requirement.Name) } @@ -123,10 +176,7 @@ func (e Extension) CmdContext(ctx context.Context, input types.Payload) (*exec.C input.Params = make(map[string]any) } - if input.Preferences == nil { - input.Preferences = make(map[string]any) - } - + input.Preferences = e.Config.Preferences cwd, err := os.Getwd() if err != nil { return nil, err @@ -163,3 +213,233 @@ func (e Extension) CmdContext(ctx context.Context, input types.Payload) (*exec.C cmd.Env = append(cmd.Env, "SUNBEAM=1") return cmd, nil } + +func SHA1(input string) string { + h := sha1.New() + h.Write([]byte(input)) + return hex.EncodeToString(h.Sum(nil)) +} + +func IsRemoteExtension(origin string) bool { + return strings.HasPrefix(origin, "http://") || strings.HasPrefix(origin, "https://") +} + +func LoadExtension(config Config) (Extension, error) { + entrypoint, err := config.Entrypoint() + if err != nil { + return Extension{}, err + } + + entrypointInfo, err := os.Stat(entrypoint) + if err != nil { + return InstallExtension(config) + } + + manifestPath := filepath.Join(config.ExtensionDir(), "manifest.json") + manifestInfo, err := os.Stat(manifestPath) + if err != nil { + return InstallExtension(config) + } + + if entrypointInfo.ModTime().After(manifestInfo.ModTime()) { + manifest, err := ExtractManifest(entrypoint) + if err != nil { + return Extension{}, err + } + + f, err := os.Create(manifestPath) + if err != nil { + return Extension{}, err + } + defer f.Close() + + if err := json.NewEncoder(f).Encode(manifest); err != nil { + return Extension{}, err + } + + return Extension{ + Manifest: manifest, + Entrypoint: entrypoint, + Config: config, + }, nil + } + + var manifest types.Manifest + f, err := os.Open(manifestPath) + if err != nil { + return Extension{}, err + } + + if err := json.NewDecoder(f).Decode(&manifest); err != nil { + return Extension{}, err + } + + return Extension{ + Manifest: manifest, + Entrypoint: entrypoint, + Config: config, + }, nil +} + +func InstallExtension(config Config) (Extension, error) { + extensionDir := config.ExtensionDir() + if err := os.MkdirAll(extensionDir, 0755); err != nil { + return Extension{}, err + } + + entrypoint, err := config.Entrypoint() + if err != nil { + return Extension{}, err + } + + if config.Hooks.Install != "" { + cmd := exec.Command("sh", "-c", config.Hooks.Install) + cmd.Dir = filepath.Dir(entrypoint) + if err := cmd.Run(); err != nil { + return Extension{}, fmt.Errorf("failed to run install hook: %s", err) + } + } else if IsRemoteExtension(config.Origin) { + resp, err := http.Get(config.Origin) + if err != nil { + return Extension{}, err + } + + if resp.StatusCode != http.StatusOK { + return Extension{}, fmt.Errorf("error downloading extension: %s", resp.Status) + } + + f, err := os.Create(entrypoint) + if err != nil { + return Extension{}, err + } + + if _, err := io.Copy(f, resp.Body); err != nil { + return Extension{}, err + } + + if err := f.Close(); err != nil { + return Extension{}, err + } + + if err := os.Chmod(entrypoint, 0755); err != nil { + return Extension{}, err + } + } + + manifestPath := filepath.Join(config.ExtensionDir(), "manifest.json") + manifest, err := ExtractManifest(entrypoint) + if err != nil { + return Extension{}, err + } + + f, err := os.Create(manifestPath) + if err != nil { + return Extension{}, err + } + defer f.Close() + + if err := json.NewEncoder(f).Encode(manifest); err != nil { + return Extension{}, err + } + + if err := f.Close(); err != nil { + return Extension{}, err + } + + return Extension{ + Manifest: manifest, + Entrypoint: entrypoint, + Config: config, + }, nil +} + +func UpgradeExtension(config Config) (Extension, error) { + entrypoint, err := config.Entrypoint() + if err != nil { + return Extension{}, err + } + + if config.Hooks.Upgrade != "" { + cmd := exec.Command("sh", "-c", config.Hooks.Upgrade) + cmd.Dir = filepath.Dir(entrypoint) + if err := cmd.Run(); err != nil { + return Extension{}, fmt.Errorf("failed to run install hook: %s", err) + } + } else if IsRemoteExtension(config.Origin) { + resp, err := http.Get(config.Origin) + if err != nil { + return Extension{}, err + } + + if resp.StatusCode != http.StatusOK { + return Extension{}, fmt.Errorf("error downloading extension: %s", resp.Status) + } + + f, err := os.OpenFile(entrypoint, os.O_TRUNC|os.O_WRONLY, 0755) + if err != nil { + return Extension{}, err + } + + if _, err := io.Copy(f, resp.Body); err != nil { + return Extension{}, err + } + } + + manifest, err := ExtractManifest(entrypoint) + if err != nil { + return Extension{}, err + } + + manifestPath := filepath.Join(config.ExtensionDir(), "manifest.json") + f, err := os.OpenFile(manifestPath, os.O_TRUNC|os.O_WRONLY, 0755) + if err != nil { + return Extension{}, err + } + defer f.Close() + + if err := json.NewEncoder(f).Encode(manifest); err != nil { + return Extension{}, err + } + + if err := f.Close(); err != nil { + return Extension{}, err + } + + return Extension{ + Manifest: manifest, + Entrypoint: entrypoint, + Config: config, + }, nil + +} + +func ExtractManifest(entrypoint string) (types.Manifest, error) { + if err := os.Chmod(entrypoint, 0755); err != nil { + return types.Manifest{}, err + } + + cmd := exec.Command(entrypoint) + cmd.Dir = filepath.Dir(entrypoint) + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "SUNBEAM=1") + + manifestBytes, err := cmd.Output() + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + return types.Manifest{}, fmt.Errorf("command failed: %s", stripansi.Strip(string(exitErr.Stderr))) + } + + return types.Manifest{}, err + } + + if err := schemas.ValidateManifest(manifestBytes); err != nil { + return types.Manifest{}, err + } + + var manifest types.Manifest + if err := json.Unmarshal(manifestBytes, &manifest); err != nil { + return types.Manifest{}, err + } + + return manifest, nil +} diff --git a/internal/tui/root.go b/internal/tui/root.go index 3e92a997..8dcd5624 100644 --- a/internal/tui/root.go +++ b/internal/tui/root.go @@ -25,13 +25,11 @@ type RootList struct { list *List form *Form - extensions extensions.ExtensionMap - preferences map[string]types.Preferences - - generator func() (extensions.ExtensionMap, []types.ListItem, map[string]types.Preferences, error) + extensions extensions.ExtensionMap + generator func() (extensions.ExtensionMap, []types.ListItem, error) } -func NewRootList(title string, generator func() (extensions.ExtensionMap, []types.ListItem, map[string]types.Preferences, error)) *RootList { +func NewRootList(title string, generator func() (extensions.ExtensionMap, []types.ListItem, error)) *RootList { history, err := LoadHistory(filepath.Join(utils.CacheHome(), "history.json")) if err != nil { history = History{ @@ -54,15 +52,14 @@ func (c *RootList) Init() tea.Cmd { } func (c *RootList) Reload() tea.Msg { - extensionMap, rootItems, preferences, err := c.generator() + extensionMap, rootItems, err := c.generator() if err != nil { return err } c.extensions = extensionMap - c.preferences = preferences c.history.Sort(rootItems) - c.list.SetEmptyText("No item found, use ctrl+e to edit your config.") + c.list.SetEmptyText("No items") c.list.SetIsLoading(false) c.list.SetItems(rootItems...) return nil @@ -185,9 +182,8 @@ func (c *RootList) Update(msg tea.Msg) (Page, tea.Cmd) { } input := types.Payload{ - Command: command.Name, - Params: make(map[string]any), - Preferences: c.preferences[msg.Extension], + Command: command.Name, + Params: make(map[string]any), } for k, v := range msg.Params { diff --git a/internal/tui/runner.go b/internal/tui/runner.go index 903b72da..bae99900 100644 --- a/internal/tui/runner.go +++ b/internal/tui/runner.go @@ -76,7 +76,7 @@ func (c *Runner) Focus() tea.Cmd { if c.embed == nil { return nil } - termenv.DefaultOutput().SetWindowTitle(fmt.Sprintf("%s - %s", c.command.Title, c.extension.Title)) + termenv.DefaultOutput().SetWindowTitle(fmt.Sprintf("%s - %s", c.command.Title, c.extension.Manifest.Title)) return c.embed.Focus() } diff --git a/internal/tui/statusbar.go b/internal/tui/statusbar.go index c2ea0430..7a77feca 100644 --- a/internal/tui/statusbar.go +++ b/internal/tui/statusbar.go @@ -96,10 +96,35 @@ func (p StatusBar) Update(msg tea.Msg) (StatusBar, tea.Cmd) { return p, nil } +func ActionTitle(action types.Action) string { + if action.Title != "" { + return action.Title + } + + switch action.Type { + case types.ActionTypeRun: + return "Run" + case types.ActionTypeCopy: + return "Copy" + case types.ActionTypeOpen: + return "Open" + case types.ActionTypeEdit: + return "Edit" + case types.ActionTypeReload: + return "Reload" + case types.ActionTypeExec: + return "Exec" + case types.ActionTypeExit: + return "Exit" + default: + return string(action.Type) + } +} + func (c StatusBar) View() string { var accessory string if len(c.actions) == 1 { - accessory = renderAction(c.actions[0].Title, "enter", c.expanded) + accessory = renderAction(ActionTitle(c.actions[0]), "enter", c.expanded) } else if len(c.actions) > 1 { if c.expanded { accessories := make([]string, len(c.actions)) @@ -110,7 +135,7 @@ func (c StatusBar) View() string { } else if action.Key != "" { subtitle = fmt.Sprintf("alt+%s", action.Key) } - accessories[i] = renderAction(action.Title, subtitle, i == c.cursor) + accessories[i] = renderAction(ActionTitle(action), subtitle, i == c.cursor) } availableWidth := c.Width @@ -138,7 +163,7 @@ func (c StatusBar) View() string { } } else { - accessory = fmt.Sprintf("%s · Actions %s", renderAction(c.actions[0].Title, "enter", false), lipgloss.NewStyle().Faint(true).Render("tab")) + accessory = fmt.Sprintf("%s · Actions %s", renderAction(ActionTitle(c.actions[0]), "enter", false), lipgloss.NewStyle().Faint(true).Render("tab")) } } diff --git a/pkg/schemas/action.schema.json b/pkg/schemas/action.schema.json index f50c4e68..798666f4 100644 --- a/pkg/schemas/action.schema.json +++ b/pkg/schemas/action.schema.json @@ -30,7 +30,6 @@ }, "then": { "required": [ - "title", "type", "text" ], @@ -66,7 +65,6 @@ }, "then": { "required": [ - "title", "type", "target" ], @@ -115,7 +113,6 @@ }, "then": { "required": [ - "title", "type", "target" ], @@ -154,7 +151,6 @@ }, "then": { "required": [ - "title", "type", "command" ], @@ -197,7 +193,6 @@ "then": { "type": "object", "required": [ - "title", "type" ], "properties": { @@ -230,7 +225,6 @@ "then": { "type": "object", "required": [ - "title", "type" ], "properties": { diff --git a/pkg/schemas/config.schema.json b/pkg/schemas/config.schema.json index 028e7951..50ab9f36 100644 --- a/pkg/schemas/config.schema.json +++ b/pkg/schemas/config.schema.json @@ -6,31 +6,35 @@ "type": "string" }, "oneliners": { - "type": "array", + "type": "object", "description": "A list of commands that will be shown in the root list", - "items": { - "type": "object", - "required": [ - "title", - "command" - ], - "properties": { - "title": { - "type": "string", - "description": "An friendly title for the command" - }, - "command": { - "type": "string", - "description": "The command to run" - }, - "cwd": { - "type": "string", - "description": "The working directory to run the command in" - }, - "exit": { - "type": "boolean", - "description": "If true, sunbeam will close after running the command" - } + "patternProperties": { + ".+": { + "oneOf": [ + { + "type": "object", + "required": [ + "command" + ], + "properties": { + "command": { + "type": "string", + "description": "The command to run" + }, + "cwd": { + "type": "string", + "description": "The working directory to run the command in" + }, + "exit": { + "type": "boolean", + "description": "If true, sunbeam will close after running the command" + } + } + }, + { + "type": "string" + } + ] } } }, @@ -51,11 +55,12 @@ "origin": { "type": "string" }, - "root": { + "items": { "type": "array", "items": { "type": "object", "required": [ + "title", "command" ], "properties": { @@ -66,7 +71,7 @@ "type": "string" }, "params": { - "type": "object" + "$ref": "./params.schema.json" } } } diff --git a/pkg/schemas/manifest.schema.json b/pkg/schemas/manifest.schema.json index 90ed2304..576b9c8f 100644 --- a/pkg/schemas/manifest.schema.json +++ b/pkg/schemas/manifest.schema.json @@ -42,10 +42,24 @@ "description": { "type": "string" }, - "root": { + "items": { "type": "array", "items": { - "$ref": "#/definitions/commandref" + "type": "object", + "required": [ + "command" + ], + "properties": { + "title": { + "type": "string" + }, + "command": { + "type": "string" + }, + "params": { + "$ref": "./params.schema.json" + } + } } }, "commands": { @@ -56,27 +70,6 @@ } }, "definitions": { - "commandref": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "command": { - "type": "string" - }, - "params": { - "patternProperties": { - ".+": { - "type": [ - "string", - "boolean" - ] - } - } - } - } - }, "command": { "type": "object", "required": [ diff --git a/pkg/types/manifest.go b/pkg/types/manifest.go index dffe83a0..3e02bfa7 100644 --- a/pkg/types/manifest.go +++ b/pkg/types/manifest.go @@ -1,12 +1,18 @@ package types type Manifest struct { - Title string `json:"title"` - Platforms []Platfom `json:"platforms,omitempty"` - Description string `json:"description,omitempty"` - Require []Requirement `json:"requirements,omitempty"` - Root []RootItem `json:"root,omitempty"` - Commands []CommandSpec `json:"commands"` + Title string `json:"title"` + Platforms []Platfom `json:"platforms,omitempty"` + Description string `json:"description,omitempty"` + Requirements []Requirement `json:"requirements,omitempty"` + Items []RootItem `json:"items,omitempty"` + Commands []CommandSpec `json:"commands"` +} + +type RootItem struct { + Title string `json:"title"` + Command string `json:"command"` + Params map[string]Param `json:"params"` } type Platfom string @@ -21,12 +27,6 @@ type Requirement struct { Link string `json:"link,omitempty"` } -type RootItem struct { - Title string `json:"title"` - Command string `json:"command"` - Params map[string]Param `json:"params"` -} - type CommandSpec struct { Name string `json:"name"` Title string `json:"title"` diff --git a/pkg/typescript/build.ts b/pkg/typescript/build.ts new file mode 100755 index 00000000..8410ddf5 --- /dev/null +++ b/pkg/typescript/build.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env -S deno run -A +import { build, emptyDir } from "https://deno.land/x/dnt@0.39.0/mod.ts"; + +await emptyDir("./npm"); +await build({ + entryPoints: ["./src/mod.ts"], + outDir: "./npm", + shims: {}, + package: { + // package.json properties + name: "sunbeam-types", + version: Deno.readTextFileSync("./version.txt").trimEnd(), + description: "Sunbeam Types", + license: "MIT", + repository: { + type: "git", + url: "git+https://github.com/pomdtr/sunbeam.git", + }, + bugs: { + url: "https://github.com/pomdtr/sunbeam/issues", + }, + } +}); diff --git a/pkg/typescript/npm/.npmignore b/pkg/typescript/npm/.npmignore new file mode 100644 index 00000000..d54ff4ec --- /dev/null +++ b/pkg/typescript/npm/.npmignore @@ -0,0 +1,4 @@ +src/ +test_runner.js +yarn.lock +pnpm-lock.yaml diff --git a/pkg/typescript/npm/esm/action.d.ts b/pkg/typescript/npm/esm/action.d.ts new file mode 100644 index 00000000..323c2e1c --- /dev/null +++ b/pkg/typescript/npm/esm/action.d.ts @@ -0,0 +1,44 @@ +type ActionProps = { + title?: string; + key?: string; +}; +export type CopyAction = { + type: "copy"; + text: string; + exit?: boolean; +} & ActionProps; +export type OpenAction = { + type: "open"; + target: string; + app?: { + macos?: string; + linux?: string; + }; + exit?: boolean; +} & ActionProps; +export type EditAction = { + type: "edit"; + target: string; + exit?: boolean; +} & ActionProps; +export type RunAction = { + type: "run"; + command: string; + params?: Record; + reload?: boolean; + exit?: boolean; +} & ActionProps; +export type Param = string | number | boolean | { + default?: string | number | boolean; + required?: boolean; +}; +export type ReloadAction = { + type: "reload"; + command: string; + params?: Record; +} & ActionProps; +export type ExitAction = { + type: "exit"; +} & ActionProps; +export type Action = CopyAction | OpenAction | RunAction | ExitAction | EditAction | ReloadAction; +export {}; diff --git a/pkg/typescript/npm/esm/action.js b/pkg/typescript/npm/esm/action.js new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/pkg/typescript/npm/esm/action.js @@ -0,0 +1 @@ +export {}; diff --git a/pkg/typescript/npm/esm/manifest.d.ts b/pkg/typescript/npm/esm/manifest.d.ts new file mode 100644 index 00000000..10076d91 --- /dev/null +++ b/pkg/typescript/npm/esm/manifest.d.ts @@ -0,0 +1,71 @@ +import { Param } from "./action.js"; +export type Manifest = { + title: string; + platforms?: Platform[]; + description?: string; + requirements?: Requirement[]; + items?: RootItem[]; + commands: CommandSpec[]; +}; +type RootItem = { + command: string; + title?: string; + params?: Record; +}; +type Platform = "linux" | "macos"; +type Requirement = { + name: string; + link?: string; +}; +export type CommandSpec = { + name: string; + title: string; + mode: "list" | "detail" | "tty" | "silent"; + hidden?: boolean; + description?: string; + params?: Input[]; +}; +type PayloadParams = Record; +export type Payload = Record> = { + command: string; + params: T; + preferences: V; + query?: string; + cwd: string; +}; +type InputProps = { + name: string; + required: boolean; +}; +type TextField = InputProps & { + type: "text"; + title: string; + defaut?: string; + placeholder?: string; +}; +type NumberField = InputProps & { + type: "number"; + title: string; + default?: number; + placeholder?: string; +}; +type TextArea = InputProps & { + type: "textarea"; + title: string; + defaut?: string; + placeholder?: string; +}; +type Password = InputProps & { + type: "password"; + title: string; + defaut?: string; + placeholder?: string; +}; +type Checkbox = InputProps & { + type: "checkbox"; + label: string; + title?: string; + defaut?: boolean; +}; +export type Input = TextField | TextArea | Password | Checkbox | NumberField; +export {}; diff --git a/pkg/typescript/npm/esm/manifest.js b/pkg/typescript/npm/esm/manifest.js new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/pkg/typescript/npm/esm/manifest.js @@ -0,0 +1 @@ +export {}; diff --git a/pkg/typescript/npm/esm/mod.d.ts b/pkg/typescript/npm/esm/mod.d.ts new file mode 100644 index 00000000..e20e278e --- /dev/null +++ b/pkg/typescript/npm/esm/mod.d.ts @@ -0,0 +1,3 @@ +export type { List, Detail, ListItem } from "./page.js"; +export type { Manifest, Payload } from "./manifest.js"; +export type { Action } from "./action.js"; diff --git a/pkg/typescript/npm/esm/mod.js b/pkg/typescript/npm/esm/mod.js new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/pkg/typescript/npm/esm/mod.js @@ -0,0 +1 @@ +export {}; diff --git a/pkg/typescript/npm/esm/package.json b/pkg/typescript/npm/esm/package.json new file mode 100644 index 00000000..3dbc1ca5 --- /dev/null +++ b/pkg/typescript/npm/esm/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/pkg/typescript/npm/esm/page.d.ts b/pkg/typescript/npm/esm/page.d.ts new file mode 100644 index 00000000..048dd44d --- /dev/null +++ b/pkg/typescript/npm/esm/page.d.ts @@ -0,0 +1,18 @@ +import type { Action } from "./action.js"; +export type List = { + items?: ListItem[]; + actions?: Action[]; + emptyText?: string; + dynamic?: boolean; +}; +export type Detail = { + text: string; + format?: "markdown" | "ansi" | "template"; + actions?: Action[]; +}; +export type ListItem = { + title: string; + subtitle?: string; + accessories?: string[]; + actions?: Action[]; +}; diff --git a/pkg/typescript/npm/esm/page.js b/pkg/typescript/npm/esm/page.js new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/pkg/typescript/npm/esm/page.js @@ -0,0 +1 @@ +export {}; diff --git a/pkg/typescript/npm/package-lock.json b/pkg/typescript/npm/package-lock.json new file mode 100644 index 00000000..92fbc4ec --- /dev/null +++ b/pkg/typescript/npm/package-lock.json @@ -0,0 +1,22 @@ +{ + "name": "sunbeam-types", + "version": "0.25.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sunbeam-types", + "version": "0.25.1", + "license": "MIT", + "devDependencies": { + "picocolors": "^1.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + } + } +} diff --git a/pkg/typescript/npm/package.json b/pkg/typescript/npm/package.json new file mode 100644 index 00000000..3b0df5fa --- /dev/null +++ b/pkg/typescript/npm/package.json @@ -0,0 +1,28 @@ +{ + "name": "sunbeam-types", + "version": "0.25.1", + "description": "Sunbeam Types", + "repository": { + "type": "git", + "url": "git+https://github.com/pomdtr/sunbeam.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/pomdtr/sunbeam/issues" + }, + "main": "./script/mod.js", + "module": "./esm/mod.js", + "exports": { + ".": { + "import": "./esm/mod.js", + "require": "./script/mod.js" + } + }, + "scripts": { + "test": "node test_runner.js" + }, + "devDependencies": { + "picocolors": "^1.0.0" + }, + "_generatedBy": "dnt@0.39.0" +} \ No newline at end of file diff --git a/pkg/typescript/npm/script/action.d.ts b/pkg/typescript/npm/script/action.d.ts new file mode 100644 index 00000000..323c2e1c --- /dev/null +++ b/pkg/typescript/npm/script/action.d.ts @@ -0,0 +1,44 @@ +type ActionProps = { + title?: string; + key?: string; +}; +export type CopyAction = { + type: "copy"; + text: string; + exit?: boolean; +} & ActionProps; +export type OpenAction = { + type: "open"; + target: string; + app?: { + macos?: string; + linux?: string; + }; + exit?: boolean; +} & ActionProps; +export type EditAction = { + type: "edit"; + target: string; + exit?: boolean; +} & ActionProps; +export type RunAction = { + type: "run"; + command: string; + params?: Record; + reload?: boolean; + exit?: boolean; +} & ActionProps; +export type Param = string | number | boolean | { + default?: string | number | boolean; + required?: boolean; +}; +export type ReloadAction = { + type: "reload"; + command: string; + params?: Record; +} & ActionProps; +export type ExitAction = { + type: "exit"; +} & ActionProps; +export type Action = CopyAction | OpenAction | RunAction | ExitAction | EditAction | ReloadAction; +export {}; diff --git a/pkg/typescript/npm/script/action.js b/pkg/typescript/npm/script/action.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/pkg/typescript/npm/script/action.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/pkg/typescript/npm/script/manifest.d.ts b/pkg/typescript/npm/script/manifest.d.ts new file mode 100644 index 00000000..10076d91 --- /dev/null +++ b/pkg/typescript/npm/script/manifest.d.ts @@ -0,0 +1,71 @@ +import { Param } from "./action.js"; +export type Manifest = { + title: string; + platforms?: Platform[]; + description?: string; + requirements?: Requirement[]; + items?: RootItem[]; + commands: CommandSpec[]; +}; +type RootItem = { + command: string; + title?: string; + params?: Record; +}; +type Platform = "linux" | "macos"; +type Requirement = { + name: string; + link?: string; +}; +export type CommandSpec = { + name: string; + title: string; + mode: "list" | "detail" | "tty" | "silent"; + hidden?: boolean; + description?: string; + params?: Input[]; +}; +type PayloadParams = Record; +export type Payload = Record> = { + command: string; + params: T; + preferences: V; + query?: string; + cwd: string; +}; +type InputProps = { + name: string; + required: boolean; +}; +type TextField = InputProps & { + type: "text"; + title: string; + defaut?: string; + placeholder?: string; +}; +type NumberField = InputProps & { + type: "number"; + title: string; + default?: number; + placeholder?: string; +}; +type TextArea = InputProps & { + type: "textarea"; + title: string; + defaut?: string; + placeholder?: string; +}; +type Password = InputProps & { + type: "password"; + title: string; + defaut?: string; + placeholder?: string; +}; +type Checkbox = InputProps & { + type: "checkbox"; + label: string; + title?: string; + defaut?: boolean; +}; +export type Input = TextField | TextArea | Password | Checkbox | NumberField; +export {}; diff --git a/pkg/typescript/npm/script/manifest.js b/pkg/typescript/npm/script/manifest.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/pkg/typescript/npm/script/manifest.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/pkg/typescript/npm/script/mod.d.ts b/pkg/typescript/npm/script/mod.d.ts new file mode 100644 index 00000000..e20e278e --- /dev/null +++ b/pkg/typescript/npm/script/mod.d.ts @@ -0,0 +1,3 @@ +export type { List, Detail, ListItem } from "./page.js"; +export type { Manifest, Payload } from "./manifest.js"; +export type { Action } from "./action.js"; diff --git a/pkg/typescript/npm/script/mod.js b/pkg/typescript/npm/script/mod.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/pkg/typescript/npm/script/mod.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/pkg/typescript/npm/script/package.json b/pkg/typescript/npm/script/package.json new file mode 100644 index 00000000..5bbefffb --- /dev/null +++ b/pkg/typescript/npm/script/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/pkg/typescript/npm/script/page.d.ts b/pkg/typescript/npm/script/page.d.ts new file mode 100644 index 00000000..048dd44d --- /dev/null +++ b/pkg/typescript/npm/script/page.d.ts @@ -0,0 +1,18 @@ +import type { Action } from "./action.js"; +export type List = { + items?: ListItem[]; + actions?: Action[]; + emptyText?: string; + dynamic?: boolean; +}; +export type Detail = { + text: string; + format?: "markdown" | "ansi" | "template"; + actions?: Action[]; +}; +export type ListItem = { + title: string; + subtitle?: string; + accessories?: string[]; + actions?: Action[]; +}; diff --git a/pkg/typescript/npm/script/page.js b/pkg/typescript/npm/script/page.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/pkg/typescript/npm/script/page.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/pkg/typescript/npm/src/action.ts b/pkg/typescript/npm/src/action.ts new file mode 100644 index 00000000..87fa0deb --- /dev/null +++ b/pkg/typescript/npm/src/action.ts @@ -0,0 +1,50 @@ +type ActionProps = { + title?: string; + key?: string; +} + +export type CopyAction = { + type: "copy"; + text: string; + exit?: boolean; +} & ActionProps; + +export type OpenAction = { + type: "open"; + target: string; + app?: { + macos?: string; + linux?: string; + }; + exit?: boolean; +} & ActionProps; + +export type EditAction = { + type: "edit"; + target: string; + exit?: boolean; +} & ActionProps; + +export type RunAction = { + type: "run"; + command: string; + params?: Record; + reload?: boolean; + exit?: boolean; +} & ActionProps; + +export type Param = string | number | boolean | { default?: string | number | boolean, required?: boolean }; + + +export type ReloadAction = { + type: "reload"; + command: string; + params?: Record; +} & ActionProps; + + +export type ExitAction = { + type: "exit"; +} & ActionProps; + +export type Action = CopyAction | OpenAction | RunAction | ExitAction | EditAction | ReloadAction; diff --git a/pkg/typescript/npm/src/manifest.ts b/pkg/typescript/npm/src/manifest.ts new file mode 100644 index 00000000..27a6c818 --- /dev/null +++ b/pkg/typescript/npm/src/manifest.ts @@ -0,0 +1,82 @@ +import { Param } from "./action.js"; +export type Manifest = { + title: string; + platforms?: Platform[]; + description?: string; + requirements?: Requirement[]; + items?: RootItem[]; + commands: CommandSpec[]; +}; + +type RootItem = { + command: string; + title?: string; + params?: Record; +}; + +type Platform = "linux" | "macos" + +type Requirement = { + name: string; + link?: string; +}; + +export type CommandSpec = { + name: string; + title: string; + mode: "list" | "detail" | "tty" | "silent"; + hidden?: boolean; + description?: string; + params?: Input[]; +}; + +type PayloadParams = Record; +export type Payload = Record> = { + command: string; + params: T; + preferences: V; + query?: string; + cwd: string; +}; + +type InputProps = { + name: string; + required: boolean; +} + +type TextField = InputProps & { + type: "text"; + title: string; + defaut?: string; + placeholder?: string; +} + +type NumberField = InputProps & { + type: "number"; + title: string; + default?: number; + placeholder?: string; +} + +type TextArea = InputProps & { + type: "textarea"; + title: string; + defaut?: string; + placeholder?: string; +} + +type Password = InputProps & { + type: "password"; + title: string; + defaut?: string; + placeholder?: string; +} + +type Checkbox = InputProps & { + type: "checkbox"; + label: string; + title?: string; + defaut?: boolean; +} + +export type Input = TextField | TextArea | Password | Checkbox | NumberField; diff --git a/pkg/typescript/npm/src/mod.ts b/pkg/typescript/npm/src/mod.ts new file mode 100644 index 00000000..e20e278e --- /dev/null +++ b/pkg/typescript/npm/src/mod.ts @@ -0,0 +1,3 @@ +export type { List, Detail, ListItem } from "./page.js"; +export type { Manifest, Payload } from "./manifest.js"; +export type { Action } from "./action.js"; diff --git a/pkg/typescript/npm/src/page.ts b/pkg/typescript/npm/src/page.ts new file mode 100644 index 00000000..a56eee48 --- /dev/null +++ b/pkg/typescript/npm/src/page.ts @@ -0,0 +1,21 @@ +import type { Action } from "./action.js"; + +export type List = { + items?: ListItem[]; + actions?: Action[]; + emptyText?: string; + dynamic?: boolean; +}; + +export type Detail = { + text: string; + format?: "markdown" | "ansi" | "template"; + actions?: Action[]; +}; + +export type ListItem = { + title: string; + subtitle?: string; + accessories?: string[]; + actions?: Action[]; +}; diff --git a/pkg/typescript/npm/test_runner.js b/pkg/typescript/npm/test_runner.js new file mode 100644 index 00000000..c29e28dc --- /dev/null +++ b/pkg/typescript/npm/test_runner.js @@ -0,0 +1,25 @@ +const pc = require("picocolors"); +const process = require("process"); +const filePaths = []; +async function main() { + for (const [i, filePath] of filePaths.entries()) { + if (i > 0) { + console.log(""); + } + const scriptPath = "./script/" + filePath; + console.log("Running tests in " + pc.underline(scriptPath) + "...\n"); + process.chdir(__dirname + "/script"); + try { + require(scriptPath); + } + catch (err) { + console.error(err); + process.exit(1); + } + const esmPath = "./esm/" + filePath; + console.log("\nRunning tests in " + pc.underline(esmPath) + "...\n"); + process.chdir(__dirname + "/esm"); + await import(esmPath); + } +} +main(); diff --git a/pkg/typescript/package-lock.json b/pkg/typescript/package-lock.json deleted file mode 100644 index 3610e73b..00000000 --- a/pkg/typescript/package-lock.json +++ /dev/null @@ -1,1477 +0,0 @@ -{ - "name": "sunbeam-types", - "version": "0.23.32", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "sunbeam-types", - "version": "0.23.32", - "license": "MIT", - "devDependencies": { - "tsup": "^7.2.0", - "typescript": "^5.2.2" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/bundle-require": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz", - "integrity": "sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==", - "dev": true, - "dependencies": { - "load-tsconfig": "^0.2.3" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "esbuild": ">=0.17" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz", - "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^2.1.1" - }, - "engines": { - "node": ">= 14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dev": true, - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/sucrase": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", - "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "7.1.6", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "node_modules/tsup": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-7.2.0.tgz", - "integrity": "sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==", - "dev": true, - "dependencies": { - "bundle-require": "^4.0.0", - "cac": "^6.7.12", - "chokidar": "^3.5.1", - "debug": "^4.3.1", - "esbuild": "^0.18.2", - "execa": "^5.0.0", - "globby": "^11.0.3", - "joycon": "^3.0.1", - "postcss-load-config": "^4.0.1", - "resolve-from": "^5.0.0", - "rollup": "^3.2.5", - "source-map": "0.8.0-beta.0", - "sucrase": "^3.20.3", - "tree-kill": "^1.2.2" - }, - "bin": { - "tsup": "dist/cli-default.js", - "tsup-node": "dist/cli-node.js" - }, - "engines": { - "node": ">=16.14" - }, - "peerDependencies": { - "@swc/core": "^1", - "postcss": "^8.4.12", - "typescript": ">=4.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "postcss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", - "dev": true, - "engines": { - "node": ">= 14" - } - } - } -} diff --git a/pkg/typescript/package.json b/pkg/typescript/package.json deleted file mode 100644 index 81d414d8..00000000 --- a/pkg/typescript/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "sunbeam-types", - "version": "0.23.32", - "description": "Types for sunbeam", - "types": "dist/mod.d.ts", - "license": "MIT", - "files": [ - "dist" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/pomdtr/sunbeam.git" - }, - "scripts": { - "build": "npm run clean && tsup", - "clean": "rm -rf dist", - "release": "npm run build && npm publish" - }, - "devDependencies": { - "tsup": "^7.2.0", - "typescript": "^5.2.2" - } -} diff --git a/pkg/typescript/src/action.ts b/pkg/typescript/src/action.ts index 661a4238..87fa0deb 100644 --- a/pkg/typescript/src/action.ts +++ b/pkg/typescript/src/action.ts @@ -1,5 +1,5 @@ type ActionProps = { - title: string; + title?: string; key?: string; } @@ -33,7 +33,7 @@ export type RunAction = { exit?: boolean; } & ActionProps; -type Param = string | number | boolean | { default?: string | number | boolean, required?: boolean }; +export type Param = string | number | boolean | { default?: string | number | boolean, required?: boolean }; export type ReloadAction = { diff --git a/pkg/typescript/src/manifest.ts b/pkg/typescript/src/manifest.ts index 4e464cd8..4d05267d 100644 --- a/pkg/typescript/src/manifest.ts +++ b/pkg/typescript/src/manifest.ts @@ -1,12 +1,19 @@ +import { Param } from "./action.ts"; export type Manifest = { title: string; platforms?: Platform[]; description?: string; requirements?: Requirement[]; - root?: CommandRef[]; + items?: RootItem[]; commands: CommandSpec[]; }; +type RootItem = { + command: string; + title?: string; + params?: Record; +}; + type Platform = "linux" | "macos" type Requirement = { @@ -14,12 +21,6 @@ type Requirement = { link?: string; }; -type CommandRef = { - command: string; - title?: string; - params?: Record; -}; - export type CommandSpec = { name: string; title: string; diff --git a/pkg/typescript/src/mod.ts b/pkg/typescript/src/mod.ts index f0582ece..0e93805d 100644 --- a/pkg/typescript/src/mod.ts +++ b/pkg/typescript/src/mod.ts @@ -1,3 +1,3 @@ -export type * from "./page"; -export type * from "./manifest"; -export type * from "./action"; +export type { List, Detail, ListItem } from "./page.ts"; +export type { Manifest, Payload } from "./manifest.ts"; +export type { Action } from "./action.ts"; diff --git a/pkg/typescript/src/page.ts b/pkg/typescript/src/page.ts index 83010f1b..a6afa28c 100644 --- a/pkg/typescript/src/page.ts +++ b/pkg/typescript/src/page.ts @@ -1,4 +1,4 @@ -import type { Action } from "./action"; +import type { Action } from "./action.ts"; export type List = { items?: ListItem[]; diff --git a/pkg/typescript/tsup.config.ts b/pkg/typescript/tsup.config.ts deleted file mode 100644 index c6dbbd16..00000000 --- a/pkg/typescript/tsup.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - entry: ["src/*.ts"], - dts: { - only: true, - }, - clean: true, -}); diff --git a/pkg/typescript/version.txt b/pkg/typescript/version.txt new file mode 100644 index 00000000..af2dabf3 --- /dev/null +++ b/pkg/typescript/version.txt @@ -0,0 +1 @@ +0.25.1