${filePath} copied to clipboard`
10 | )
11 | )
12 | await wait(2000, null)
13 |
14 | export {}
15 |
--------------------------------------------------------------------------------
/src/main/templates.ts:
--------------------------------------------------------------------------------
1 | // Description: Templates
2 | // Exclude: true
3 |
4 | import {
5 | escapeShortcut,
6 | closeShortcut,
7 | } from "../core/utils.js"
8 | setName(``)
9 |
10 | await arg({
11 | placeholder: "Reserved for future use",
12 | enter: "Exit",
13 | shortcuts: [escapeShortcut, closeShortcut],
14 | })
15 |
16 | export {}
17 |
--------------------------------------------------------------------------------
/src/cli/kenv-switch.ts:
--------------------------------------------------------------------------------
1 | import { Channel } from "../core/enum.js"
2 |
3 | let kitAppDb = await db<{ KENVS: string[] }>(kitPath("db", "app.json"))
4 |
5 | let kenv = await arg(
6 | {
7 | placeholder: "Select kenv",
8 | hint: `Current Kenv: ${process.env.KENV}`
9 | },
10 | kitAppDb.KENVS
11 | )
12 |
13 | global.send(Channel.SWITCH_KENV, kenv)
14 |
--------------------------------------------------------------------------------
/src/cli/open-script-log.ts:
--------------------------------------------------------------------------------
1 | import { getLogFromScriptPath } from "../core/utils.js"
2 |
3 | let { filePath } = await selectScript(
4 | `Open log for which script?`
5 | )
6 |
7 | let logPath = getLogFromScriptPath(filePath)
8 | log(`Opening log for ${filePath}: ${logPath}`)
9 | await ensureFile(logPath)
10 |
11 | await edit(logPath)
12 |
13 | export {}
14 |
--------------------------------------------------------------------------------
/src/hot/download-hot.ts:
--------------------------------------------------------------------------------
1 | // Description: Download latest hot
2 |
3 | try {
4 | await download(
5 | `https://www.scriptkit.com/api/hot`,
6 | kitPath("data"),
7 | {
8 | rejectUnauthorized: false,
9 | }
10 | )
11 | global.log(`🔥 Hot updated`)
12 | } catch {
13 | global.warn(`Hot failed to download`)
14 | }
15 |
16 | export {}
17 |
--------------------------------------------------------------------------------
/src/cli/new-from-clipboard.ts:
--------------------------------------------------------------------------------
1 | // Description: Creates a new empty script you can invoke from the terminal
2 |
3 | import { parseMetadata } from "../core/utils.js"
4 |
5 | let content = await paste()
6 |
7 | let { name } = parseMetadata(content)
8 | if (name) {
9 | arg.pass = name
10 | }
11 |
12 | arg.tip = content
13 | await cli("new")
14 |
15 | export {}
16 |
--------------------------------------------------------------------------------
/src/help/download-docs.ts:
--------------------------------------------------------------------------------
1 | // Description: Download latest docs
2 |
3 | try {
4 | await download(
5 | `https://www.scriptkit.com/api/docs`,
6 | kitPath("data"),
7 | {
8 | rejectUnauthorized: false,
9 | }
10 | )
11 |
12 | global.log(`📝 Docs updated`)
13 | } catch {
14 | global.warn(`Docs failed to download`)
15 | }
16 | export {}
17 |
--------------------------------------------------------------------------------
/src/cli/reveal-script.ts:
--------------------------------------------------------------------------------
1 | // Description: Reveal the selected script in Finder
2 |
3 | let filePath = ""
4 | if (typeof args[0] === "string") {
5 | filePath = args[0]
6 | } else {
7 | let script = await selectScript(
8 | `Which script do you want to reveal?`
9 | )
10 | filePath = script.filePath
11 | }
12 | await revealFile(filePath)
13 |
14 | export {}
15 |
--------------------------------------------------------------------------------
/src/emoji/download-emoji.ts:
--------------------------------------------------------------------------------
1 | // Description: Download latest hot
2 |
3 | try {
4 | await download(
5 | `https://www.scriptkit.com/api/emoji`,
6 | kitPath("data"),
7 | {
8 | rejectUnauthorized: false,
9 | }
10 | )
11 | global.log(`😘 Emoji updated`)
12 | } catch {
13 | global.warn(`Emoji failed to download`)
14 | }
15 |
16 | export {}
17 |
--------------------------------------------------------------------------------
/root/logos/vercel/symbol-light.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/root/logos/vercel/symbol-dark.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/setup/clone-sponsors.ts:
--------------------------------------------------------------------------------
1 | let sponsorsDir = kenvPath('kenvs', 'sponsors')
2 |
3 | if (await isDir(sponsorsDir)) {
4 | await exec('git pull --rebase --autostash --stat', {
5 | cwd: sponsorsDir
6 | })
7 | } else {
8 | await exec('git clone --depth 1 https://github.com/johnlindquist/kit-sponsors sponsors', {
9 | cwd: kenvPath('kenvs')
10 | })
11 | }
12 |
13 | export type {}
14 |
--------------------------------------------------------------------------------
/src/cli/open-script-database.ts:
--------------------------------------------------------------------------------
1 | let { filePath, command } = await selectScript(
2 | `Open database for which script?`
3 | )
4 |
5 | let scriptDb = path.resolve(
6 | path.dirname(path.dirname(filePath)),
7 | "db",
8 | `_${command}.json`
9 | )
10 |
11 | await ensureReadFile(
12 | scriptDb,
13 | JSON.stringify({ items: [] })
14 | )
15 |
16 | await edit(scriptDb)
17 |
18 | export {}
19 |
--------------------------------------------------------------------------------
/src/globals/execa.test.ts:
--------------------------------------------------------------------------------
1 | import ava from "ava"
2 | import "../core/utils.js"
3 |
4 | ava("$ works", async t => {
5 | const message = "Hello, world!"
6 | let { stdout } = await $`echo ${message}`
7 | t.is(stdout, message)
8 | })
9 |
10 |
11 | ava("exec works", async t => {
12 | const message = "Hello, world!"
13 | let { stdout } = await exec(`echo ${message}`)
14 | t.is(stdout, message)
15 | })
16 |
17 |
--------------------------------------------------------------------------------
/tsconfig-declaration.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "outDir": "./dist",
6 | "rootDir": "./src",
7 | "moduleResolution": "Node",
8 | "lib": ["esnext"],
9 | "allowSyntheticDefaultImports": true,
10 | "declaration": true,
11 | "emitDeclarationOnly": true,
12 | "skipLibCheck": true
13 | },
14 | "include": ["./src/core/*"]
15 | }
16 |
--------------------------------------------------------------------------------
/src/setup/switch-windows-kit-to-bat.ts:
--------------------------------------------------------------------------------
1 | // If windows, switch the package.json bin/kit to bin/kit.bat
2 |
3 | if (process.platform === "win32") {
4 | const packageJsonPath = kitPath("package.json")
5 | const packageJson = await readJson(packageJsonPath)
6 |
7 | packageJson.bin.kit = "bin/kit.bat"
8 |
9 | await writeFile(
10 | packageJsonPath,
11 | JSON.stringify(packageJson, null, 2)
12 | )
13 | }
14 |
15 | export {}
16 |
--------------------------------------------------------------------------------
/src/cli/create-bin.ts:
--------------------------------------------------------------------------------
1 | import { Bin } from "../core/enum.js"
2 | import type { Script } from "../types/core.ts"
3 | import { createBinFromScript } from "./lib/utils.js"
4 |
5 | let type = await arg${result}`
40 | },
41 | }
42 | })
43 | )
44 |
--------------------------------------------------------------------------------
/src/cli/new-quick.ts:
--------------------------------------------------------------------------------
1 | // Name: New Script
2 | // Description: Creates a new script
3 | import { default as generate } from "project-name-generator"
4 |
5 | let name = "quick-" + generate({ words: 2 }).dashed
6 |
7 | let scriptPath = path.join(
8 | kenvPath(),
9 | "scripts",
10 | name + ".js"
11 | )
12 |
13 | let contents = [arg?.npm]
14 | .flatMap(x => x)
15 | .filter(Boolean)
16 | .map(npm => `let {} = await npm("${npm}")`)
17 | .join("\n")
18 |
19 | let template = arg?.template || (await env("KIT_TEMPLATE"))
20 |
21 | let templateContent = await readFile(
22 | kenvPath("templates", template + ".js"),
23 | "utf8"
24 | )
25 |
26 | let templateCompiler = compile(templateContent)
27 | contents += templateCompiler({ name, ...env })
28 |
29 | if (arg?.url) {
30 | contents = (await get${name}
49 |
50 | \`${dbPath}\` not found
51 | `)
52 | )
53 | }
54 |
55 | await mainScript()
56 |
57 | export {}
58 |
--------------------------------------------------------------------------------
/src/cli/update-kit-package.ts:
--------------------------------------------------------------------------------
1 | import { KIT_FIRST_PATH } from "../core/utils.js"
2 | import { createPackageManagerCommand } from "./lib/install.js"
3 |
4 | let file = JSON.parse(
5 | await readFile(kenvPath("package.json"), {
6 | encoding: "utf8",
7 | })
8 | )
9 |
10 | let packages = (await arg(
11 | {
12 | placeholder: `Which package do you want to update to latest?`,
13 | enter: "Update",
14 | },
15 | [
16 | ...Object.keys(file?.dependencies || []),
17 | ...Object.keys(file?.devDependencies || []),
18 | ].filter(k => !k.startsWith("@johnlindquist/kit"))
19 | )) as string[]
20 |
21 | //grab all the args you used `kit un jquery react`
22 | if (typeof packages == "string") {
23 | packages = [packages, ...args]
24 | }
25 |
26 | packages = packages.map(p => `${p}@latest`)
27 |
28 | let command = await createPackageManagerCommand(
29 | "i",
30 | packages
31 | )
32 |
33 | let cwd = kenvPath()
34 |
35 | if (process.env.SCRIPTS_DIR) {
36 | cwd = kenvPath(process.env.SCRIPTS_DIR)
37 | }
38 |
39 | await term({
40 | command,
41 | env: {
42 | ...global.env,
43 | PATH: KIT_FIRST_PATH,
44 | },
45 | cwd,
46 | })
47 |
48 | export {}
49 |
--------------------------------------------------------------------------------
/src/cli/update-package.ts:
--------------------------------------------------------------------------------
1 | import { KIT_FIRST_PATH } from "../core/utils.js"
2 | import { createPackageManagerCommand } from "./lib/install.js"
3 |
4 | let file = JSON.parse(
5 | await readFile(kenvPath("package.json"), {
6 | encoding: "utf8",
7 | })
8 | )
9 |
10 | let packages = (await arg(
11 | {
12 | placeholder: `Which package do you want to update to latest?`,
13 | enter: "Update",
14 | },
15 | [
16 | ...Object.keys(file?.dependencies || []),
17 | ...Object.keys(file?.devDependencies || []),
18 | ].filter(k => !k.startsWith("@johnlindquist/kit"))
19 | )) as string[]
20 |
21 | //grab all the args you used `kit un jquery react`
22 | if (typeof packages == "string") {
23 | packages = [packages, ...args]
24 | }
25 |
26 | packages = packages.map(p => `${p}@latest`)
27 |
28 | let command = await createPackageManagerCommand(
29 | "i",
30 | packages
31 | )
32 |
33 | let cwd = kenvPath()
34 |
35 | if (process.env.SCRIPTS_DIR) {
36 | cwd = kenvPath(process.env.SCRIPTS_DIR)
37 | }
38 |
39 | await term({
40 | command,
41 | env: {
42 | ...global.env,
43 | PATH: KIT_FIRST_PATH,
44 | },
45 | cwd,
46 | })
47 |
48 | export {}
49 |
--------------------------------------------------------------------------------
/src/core/defaults.ts:
--------------------------------------------------------------------------------
1 | import { ProcessType } from "./enum.js"
2 | import type { Choice, Script } from "../types"
3 |
4 | export const DEFAULT_LIST_WIDTH = 300 // 256;
5 | export const DEFAULT_WIDTH = 300 // 256;
6 | export const DEFAULT_EXPANDED_WIDTH = 768
7 | export const DEFAULT_HEIGHT =
8 | process.env.KIT_TIKTOK === "development" ? 1040 : 480 // Math.round((DEFAULT_EXPANDED_WIDTH * 10) / 16); // 480;
9 | export const INPUT_HEIGHT = 32
10 | export const TOP_HEIGHT = 80
11 | export const MIN_HEIGHT = TOP_HEIGHT
12 | export const MIN_TEXTAREA_HEIGHT = MIN_HEIGHT * 3
13 | export const MIN_WIDTH = 256
14 | export const DROP_HEIGHT = 232
15 | export const BUTTON_HEIGHT = 56
16 | export const EMOJI_WIDTH = 278
17 | export const EMOJI_HEIGHT = 380
18 | export const ZOOM_LEVEL =
19 | process.env.KIT_TIKTOK === "development" ? 2 : 0
20 |
21 | export const SPLASH_PATH = `__app__/splash-screen`
22 |
23 | export const noScript: Script = {
24 | id: "",
25 | filePath: "__app__/no-script",
26 | command: "",
27 | name: "",
28 | type: ProcessType.App,
29 | kenv: "",
30 | }
31 |
32 | export const noChoice: Choice = {
33 | id: "",
34 | name: "__app__/no-choice",
35 | }
36 |
--------------------------------------------------------------------------------
/src/cli/log-widget.ts:
--------------------------------------------------------------------------------
1 | import "@johnlindquist/kit"
2 | import { getLogFromScriptPath } from "../core/utils.js"
3 |
4 | let scriptPath = await arg("Script Path")
5 |
6 | let Convert = await npm("ansi-to-html")
7 | let convert = new Convert()
8 |
9 | let logWidget = await widget(
10 | `
11 |
21 | Logging...
`, 31 | }, 32 | } 33 | ) 34 | 35 | let currentHtml = `` 36 | let handleLog = line => { 37 | let lineHtml = convert.toHtml(line) 38 | currentHtml += `${lineHtml}
` 39 | 40 | logWidget.setState({ 41 | log: currentHtml, 42 | }) 43 | } 44 | 45 | let logPath = getLogFromScriptPath(scriptPath) 46 | await execLog(`tail -f ${logPath}`, handleLog) 47 | -------------------------------------------------------------------------------- /src/cli/toggle-background.ts: -------------------------------------------------------------------------------- 1 | import { Channel } from "../core/enum.js" 2 | 3 | let { tasks } = await global.getBackgroundTasks() 4 | 5 | let scriptPath = await arg() 6 | 7 | let command = path.basename(scriptPath) 8 | 9 | let task = tasks.find(task => task.filePath === scriptPath) 10 | 11 | let toggleOrLog: "toggle" | "log" | "edit" = 12 | await global.arg( 13 | `${command} is ${task ? `running` : `stopped`}`, 14 | [ 15 | { 16 | name: `${task ? `Stop` : `Start`} ${command}`, 17 | value: `toggle`, 18 | id: uuid(), 19 | }, 20 | { 21 | name: `Edit ${command}`, 22 | value: `edit`, 23 | id: uuid(), 24 | }, 25 | { 26 | name: `View ${command}.log`, 27 | value: `log`, 28 | id: uuid(), 29 | }, 30 | ] 31 | ) 32 | 33 | if (toggleOrLog === "toggle") { 34 | global.send(Channel.TOGGLE_BACKGROUND, scriptPath) 35 | } 36 | 37 | if (toggleOrLog === "edit") { 38 | await global.edit(scriptPath, kenvPath()) 39 | } 40 | 41 | if (toggleOrLog === "log") { 42 | await global.edit( 43 | kenvPath("logs", `${command}.log`), 44 | kenvPath() 45 | ) 46 | } 47 | 48 | export {} 49 | -------------------------------------------------------------------------------- /src/cli/uninstall.ts: -------------------------------------------------------------------------------- 1 | import { KIT_FIRST_PATH } from "../core/utils.js" 2 | import { createPackageManagerCommand } from "./lib/install.js" 3 | 4 | let file = JSON.parse( 5 | await readFile(kenvPath("package.json"), { 6 | encoding: "utf8", 7 | }) 8 | ) 9 | 10 | let packageNames = (await arg( 11 | { 12 | placeholder: chalk`Which packages do you want to {red uninstall}`, 13 | enter: "Uninstall", 14 | }, 15 | [ 16 | ...Object.keys(file?.dependencies || []), 17 | ...Object.keys(file?.devDependencies || []), 18 | ].filter(k => !k.startsWith("@johnlindquist")) 19 | )) as string[] 20 | 21 | //grab all the args you used `kit un jquery react` 22 | if (typeof packageNames == "string") { 23 | packageNames = [packageNames, ...args] 24 | } 25 | let cwd = kenvPath() 26 | 27 | if (process.env.SCRIPTS_DIR) { 28 | cwd = kenvPath(process.env.SCRIPTS_DIR) 29 | } 30 | 31 | let command = await createPackageManagerCommand( 32 | "un", 33 | packageNames 34 | ) 35 | 36 | await term({ 37 | command, 38 | env: { 39 | ...global.env, 40 | PATH: KIT_FIRST_PATH, 41 | DISABLE_AUTO_UPDATE: "true", // Disable auto-update for zsh 42 | }, 43 | cwd, 44 | }) 45 | 46 | export {} 47 | -------------------------------------------------------------------------------- /src/cli/lib/install.ts: -------------------------------------------------------------------------------- 1 | import { kitPnpmPath } from "../../core/resolvers.js" 2 | import { existsSync } from "node:fs" 3 | export async function createPackageManagerCommand( 4 | command: "i" | "un", 5 | packageNames: string[] 6 | ) { 7 | let isYarn = await isFile(kenvPath("yarn.lock")) 8 | 9 | let packageManager = isYarn ? "yarn" : "pnpm" 10 | let toolCommand = command as 11 | | "add" 12 | | "i" 13 | | "remove" 14 | | "uninstall" 15 | 16 | if (isYarn) { 17 | if (command === "i") { 18 | toolCommand = "add" 19 | } 20 | } 21 | 22 | if (!isYarn) { 23 | // Check if the package manager exists with or without .exe extension 24 | const pm = packageManager + (global.isWin ? ".exe" : "") 25 | if (existsSync(kitPnpmPath(pm))) { 26 | // Use the full path to the package manager, but without the .exe extension 27 | packageManager = kitPnpmPath(packageManager) 28 | } 29 | } 30 | 31 | // Combine package manager and command 32 | let installCommand = `${packageManager} ${command}` 33 | 34 | let packages = packageNames.join(" ") 35 | let fullCommand = 36 | `${installCommand} -D ${packages}`.trim() 37 | 38 | return fullCommand 39 | } 40 | -------------------------------------------------------------------------------- /src/main/sticky.ts: -------------------------------------------------------------------------------- 1 | /* 2 | # Sticky Notes 3 | 4 | Opens a quick editor for taking notes. 5 | 6 | Notes are saved to `~/.kenv/sticky.md`. 7 | */ 8 | 9 | // Name: Sticky Pad 10 | // Description: Take Quick Notes 11 | // Cache: true 12 | // Trigger: , 13 | 14 | let stickyPath = kenvPath("sticky.md") 15 | let contents = await ensureReadFile( 16 | stickyPath, 17 | ` 18 | # Sticky Notes 19 | `.trim() 20 | ) 21 | 22 | let changed = false 23 | 24 | if (arg?.pass) { 25 | contents = `${contents} 26 | ${arg?.pass}` 27 | } 28 | 29 | contents = await editor({ 30 | value: contents, 31 | scrollTo: "bottom", 32 | // footer: `Escape to save to ${stickyPath}`, 33 | shortcuts: [ 34 | { 35 | name: "Save and Close", 36 | key: "escape", 37 | onPress: async (input, { inputChanged }) => { 38 | changed = inputChanged 39 | await hide() 40 | await submit(input) 41 | }, 42 | bar: "right" 43 | } 44 | ], 45 | onAbandon: async (input, { inputChanged }) => { 46 | changed = inputChanged 47 | submit(input) 48 | }, 49 | onInput: async () => { 50 | changed = true 51 | } 52 | }) 53 | 54 | if (changed || arg?.pass) { 55 | await writeFile(stickyPath, contents + "\n") 56 | } 57 | 58 | export {} 59 | -------------------------------------------------------------------------------- /src/core/shebang.ts: -------------------------------------------------------------------------------- 1 | import type { Script, Scriptlet } from "../types" 2 | import untildify from "untildify" 3 | import { kenvPath } from "./utils.js" 4 | import { slash } from "./resolvers.js" 5 | 6 | export type ShebangConfig = { 7 | command: string 8 | args: string[] 9 | shell: boolean | string 10 | cwd: string 11 | filePath: string 12 | } 13 | export function parseShebang(script: Script | Scriptlet): ShebangConfig { 14 | let command = "" 15 | let args: string[] = [] 16 | let shell: boolean | string = true 17 | let cwd = kenvPath() 18 | let filePath = script.filePath 19 | 20 | if ("scriptlet" in script) { 21 | ;[command, ...args] = script.scriptlet.split(" ") 22 | if (script?.shell === false || script?.shell === "false") { 23 | shell = false 24 | } 25 | if (typeof script?.shell === "string") { 26 | shell = script.shell 27 | } 28 | } else if ("shebang" in script) { 29 | command = script.shebang 30 | ;[command, ...args] = script.shebang.split(" ") 31 | args.push(filePath) 32 | } 33 | 34 | if ("cwd" in script) { 35 | cwd = path.resolve(slash(untildify(script.cwd))) 36 | } 37 | 38 | return { 39 | command, 40 | args, 41 | shell, 42 | cwd, 43 | filePath 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/run/github-workflow.ts: -------------------------------------------------------------------------------- 1 | process.env.KIT_TARGET = "github-workflow" 2 | 3 | import os from "node:os" 4 | import { randomUUID } from "node:crypto" 5 | import { pathToFileURL } from "node:url" 6 | 7 | process.env.KIT_CONTEXT = "workflow" 8 | 9 | import { 10 | configEnv, 11 | resolveToScriptPath, 12 | kitPath, 13 | } from "../core/utils.js" 14 | 15 | let kitImport = async (...pathParts: string[]) => 16 | await import( 17 | pathToFileURL(kitPath(...pathParts)).href + 18 | "?uuid=" + 19 | randomUUID() 20 | ) 21 | 22 | await kitImport("api", "global.js") 23 | await kitImport("api", "kit.js") 24 | await kitImport("api", "lib.js") 25 | await import("../platform/base.js") 26 | 27 | try { 28 | await attemptImport(kenvPath('globals.ts')) 29 | } catch (error) { 30 | log('No user-defined globals.ts') 31 | } 32 | 33 | 34 | let platform = process.env?.PLATFORM || os.platform() 35 | 36 | await kitImport("platform", `${platform}.js`) 37 | 38 | configEnv() 39 | 40 | await kitImport("target", "terminal.js") 41 | 42 | global.core = await npm("@actions/core") 43 | global.github = await npm("@actions/github") 44 | 45 | let scriptPath = resolveToScriptPath( 46 | await arg("Path to script") 47 | ) 48 | await run(scriptPath) 49 | -------------------------------------------------------------------------------- /src/cli/kenv-distrust.ts: -------------------------------------------------------------------------------- 1 | // Name: Testing Extreme Caution 2 | 3 | import { getTrustedKenvsKey } from "../core/utils.js" 4 | 5 | let trustedKenvsKey = getTrustedKenvsKey() 6 | 7 | let currentTrustedKenvs = process.env[trustedKenvsKey] 8 | ?.split(",") 9 | .filter(Boolean) 10 | 11 | let hasTrustedKenvs = currentTrustedKenvs?.length > 0 12 | 13 | let trustedKenvs: any[] = [ 14 | { 15 | info: true, 16 | name: hasTrustedKenvs 17 | ? "Select a kenv to distrust" 18 | : "No trusted kenvs", 19 | description: hasTrustedKenvs 20 | ? `Prevent scripts from this kenv from running automatically` 21 | : `Use "Trust Kenv" to manually trust a kenv`, 22 | }, 23 | ...currentTrustedKenvs, 24 | ] 25 | 26 | // Removes the kenv from the .env 27 | let kenv = await arg( 28 | { 29 | placeholder: "Distrust which kenv", 30 | }, 31 | trustedKenvs 32 | ) 33 | 34 | if (typeof process?.env?.[trustedKenvsKey] === "string") { 35 | let newValue = process.env[trustedKenvsKey] 36 | .split(",") 37 | .filter(Boolean) 38 | .filter(k => k !== kenv) 39 | .join(",") 40 | 41 | await global.cli("set-env-var", trustedKenvsKey, newValue) 42 | } 43 | 44 | if (process.env.KIT_CONTEXT === "app") { 45 | await mainScript() 46 | } 47 | -------------------------------------------------------------------------------- /src/cli/search-docs.ts: -------------------------------------------------------------------------------- 1 | // Name: Search Docs 2 | // Description: Type to Search Docs 3 | // Log: false 4 | 5 | let search = async input => { 6 | if (!input) return 7 | try { 8 | let { stdout } = 9 | await $`grep -ri --include='*.md' '^## .*${input}' ~/.kit/docs` 10 | 11 | let results = stdout.split("\n") 12 | let choices = Promise.all( 13 | results.filter(Boolean).map(async result => { 14 | let [filePath, ...found] = result.split(":") 15 | let preview = found.join(" ") 16 | // let { stdout: h1 } = 17 | // await $`grep '^# .*' ${filePath}` 18 | 19 | return { 20 | name: preview.split(`## `)[1], 21 | value: filePath, 22 | description: filePath, 23 | } 24 | }) 25 | ) 26 | 27 | return choices 28 | } catch { 29 | return [`${input} not found`] 30 | } 31 | } 32 | 33 | while (true) { 34 | let doc = await arg( 35 | { 36 | placeholder: `Search docs:`, 37 | }, 38 | search 39 | ) 40 | let value = md(await readFile(doc, "utf-8")) 41 | 42 | await arg( 43 | { 44 | placeholder: `Hit "enter" to start a new search:`, 45 | className: "kit-docs", 46 | }, 47 | value 48 | ) 49 | } 50 | 51 | export {} 52 | -------------------------------------------------------------------------------- /src/cli/kenv-visit.ts: -------------------------------------------------------------------------------- 1 | //Description: Visit a Kenv Repo 2 | import { getKenvs } from "../core/utils.js" 3 | let kenv = await arg( 4 | "Visit which kenv?", 5 | ( 6 | await getKenvs() 7 | ).map(value => ({ 8 | name: path.basename(value), 9 | value: path.basename(value), 10 | })) 11 | ) 12 | // find remote repo from .git dir 13 | let gitConfigPath = kenvPath( 14 | "kenvs", 15 | kenv, 16 | ".git", 17 | "config" 18 | ) 19 | try { 20 | let gitConfig = await readFile(gitConfigPath, "utf8") 21 | let remoteOriginRegex = 22 | /\[remote "origin"]\s+(?:fetch\s?=.*\s+)?url\s?=\s?(.+)(?:\s+fetch\s?=.*\s+)?/ 23 | let match = gitConfig.match(remoteOriginRegex) 24 | if (match) { 25 | let url = match[1] 26 | if (url.startsWith("git@")) { 27 | url = url 28 | .replace("git@", "https://") 29 | .replace(/(?<=\w|\d):(?=\w|\d)/, "/") 30 | .replace(/.git$/, "") 31 | } 32 | await open(url) 33 | } else { 34 | await div( 35 | md(`## Could not find remote origin in git config 36 | ~~~ 37 | ${gitConfig} 38 | ~~~ 39 | `) 40 | ) 41 | } 42 | } catch (error) { 43 | await div( 44 | md(`## Failed to read 45 | 46 | ${gitConfigPath}`) 47 | ) 48 | } 49 | //# sourceMappingURL=kenv-visit.js.map 50 | -------------------------------------------------------------------------------- /src/main/open-with.ts: -------------------------------------------------------------------------------- 1 | // Exclude: true 2 | // Description: Open with... 3 | 4 | import type { Open } from "../types/packages" 5 | import { createAppChoices } from "./common.js" 6 | 7 | let filePath = await path() 8 | setName(``) 9 | 10 | let appsDb = await db("apps", async () => { 11 | setChoices([]) 12 | clearTabs() 13 | setPlaceholder("One sec...") 14 | setPanel( 15 | md(`# First Run: Indexing Apps and Caching Icons... 16 | 17 | Please hold a few seconds while Script Kit creates icons for your apps and preferences for future use. 18 | `) 19 | ) 20 | let choices = await createAppChoices() 21 | setFooter(``) 22 | return { 23 | choices 24 | } 25 | }) 26 | let input = "" 27 | let app = await arg( 28 | { 29 | input: (flag?.input as string) || "", 30 | placeholder: "Open with...", 31 | onInput: (i) => { 32 | input = i 33 | } 34 | }, 35 | appsDb.choices 36 | ) 37 | 38 | log(`Opening ${input} with ${app} and ${flag?.cmd ? "cmd" : "open"}`) 39 | if (flag?.cmd) { 40 | await remove(kitPath("db", "apps.json")) 41 | await run(kitPath("main", "app-launcher.js"), "--input", input) 42 | } else { 43 | await Promise.all([ 44 | (open as unknown as Open)(filePath, { 45 | app: { 46 | name: app 47 | } 48 | }), 49 | await hide() 50 | ]) 51 | } 52 | -------------------------------------------------------------------------------- /src/main/system-commands.ts: -------------------------------------------------------------------------------- 1 | // Name: System Commands 2 | // Description: Run system commands 3 | // Keyword: - 4 | // Cache: true 5 | 6 | let command = await arg("Select System Command", [ 7 | { 8 | name: "Mute", 9 | description: "Mute the system volume", 10 | value: "mute", 11 | }, 12 | { 13 | name: "Unmute", 14 | description: "Unmute the system volume", 15 | value: "unmute", 16 | }, 17 | { 18 | name: "Adjust Volume", 19 | description: "Set the system volume", 20 | value: "adjustVolume", 21 | }, 22 | { 23 | name: "Lock", 24 | description: "Lock screen", 25 | value: "lock", 26 | }, 27 | { 28 | name: "Sleep Screens", 29 | description: "Sleep the screens", 30 | value: "sleepScreens", 31 | }, 32 | { 33 | name: "Sleep", 34 | description: "Put system to sleep", 35 | value: "sleep", 36 | }, 37 | { 38 | name: "Caffeinate", 39 | description: "Keep system awake", 40 | value: "caffeinate", 41 | }, 42 | { 43 | name: "Shutdown", 44 | description: "Shutdown system", 45 | value: "shutdown", 46 | }, 47 | { 48 | name: "Quit All Apps", 49 | description: "Quit all apps", 50 | value: "quitAllApps", 51 | }, 52 | ]) 53 | 54 | global[command]() 55 | export {} 56 | -------------------------------------------------------------------------------- /src/setup/clone-examples.ts: -------------------------------------------------------------------------------- 1 | import { KIT_FIRST_PATH } from '../core/utils.js' 2 | 3 | async function downloadAndSetupExamples() { 4 | let destination = kenvPath('tmp') 5 | await download('https://github.com/johnlindquist/kit-examples-ts/archive/main.zip', destination, { 6 | extract: true, 7 | rejectUnauthorized: false 8 | }) 9 | 10 | let source = path.join(destination, 'kit-examples-main') 11 | let newDestination = kenvPath('kenvs', 'examples') 12 | await rename(source, newDestination) 13 | } 14 | 15 | async function pnpmInstallExamples() { 16 | await exec('pnpm i', { 17 | cwd: kenvPath('kenvs', 'examples'), 18 | env: { 19 | ...global.env, 20 | PATH: KIT_FIRST_PATH 21 | } 22 | }).catch((error) => { 23 | console.error(error) 24 | }) 25 | } 26 | 27 | let examplesDir = kenvPath('kenvs', 'examples') 28 | 29 | if (await isDir(examplesDir)) { 30 | await exec('git pull --rebase --autostash --stat', { 31 | cwd: examplesDir 32 | }) 33 | } else { 34 | try { 35 | await exec('git clone --depth 1 https://github.com/johnlindquist/kit-examples-ts examples', { 36 | cwd: kenvPath('kenvs') 37 | }) 38 | } catch (error) { 39 | await downloadAndSetupExamples() 40 | } 41 | } 42 | 43 | await pnpmInstallExamples() 44 | -------------------------------------------------------------------------------- /src/cli/system-events.ts: -------------------------------------------------------------------------------- 1 | // Name: System Events Scripts 2 | // Description: Select a Script to Edit 3 | 4 | import { getScripts } from "../core/db.js" 5 | import { cliShortcuts } from "../core/utils.js" 6 | let scriptsCache = await getScripts() 7 | let filePath = await arg( 8 | { 9 | placeholder: "Select System Event Script to Edit", 10 | enter: "Edit", 11 | shortcuts: cliShortcuts, 12 | onNoChoices: async () => { 13 | setPanel( 14 | md(`# No System Event Scripts Found 15 | 16 | Create a script with// System: metadata to add it to this list.
17 |
18 | Available events:
19 |
20 | - suspend
21 | - resume
22 | - on-ac
23 | - on-battery
24 | - shutdown
25 | - lock-screen
26 | - unlock-screen
27 | - user-did-become-active
28 | - user-did-resign-active
29 | - Read about the available events [here](https://www.electronjs.org/docs/latest/api/power-monitor#events)
30 | `)
31 | )
32 | },
33 | },
34 | scriptsCache
35 | .filter(script => script?.system)
36 | .map(script => {
37 | return {
38 | name: script?.menu || script.command,
39 | description: `Runs on ${script.system}`,
40 | value: script.filePath,
41 | }
42 | })
43 | )
44 | await run(kitPath("cli", "edit-script.js"), filePath)
45 |
--------------------------------------------------------------------------------
/src/cli/kenv-pull.ts:
--------------------------------------------------------------------------------
1 | // Description: Git Pull Kenv Repo
2 |
3 | import { getKenvs } from "../core/utils.js"
4 |
5 | let kenvs = (await getKenvs()).map(value => ({
6 | name: path.basename(value),
7 | value,
8 | }))
9 |
10 | kenvs.unshift({
11 | name: "main",
12 | value: kenvPath(),
13 | })
14 |
15 | let dir = await arg("Pull which kenv", kenvs)
16 |
17 | cd(dir)
18 |
19 | await term({
20 | command: `git fetch`,
21 | preview: md(`# Pulling a Kenv
22 |
23 | > The terminal only ran "git fetch" to show you what changes are available.
24 |
25 | You still need to run "git merge" to apply the changes.
26 |
27 | `),
28 | cwd: dir,
29 | shortcuts: [
30 | {
31 | name: "Stash",
32 | key: `${cmd}+s`,
33 | bar: "right",
34 | onPress: async () => {
35 | term.write(`git stash`)
36 | },
37 | },
38 | {
39 | name: "Merge",
40 | key: `${cmd}+m`,
41 | bar: "right",
42 | onPress: async () => {
43 | term.write(`git merge`)
44 | },
45 | },
46 | {
47 | name: "Exit",
48 | key: `${cmd}+w`,
49 | bar: "right",
50 | onPress: async () => {
51 | submit("")
52 | },
53 | },
54 | ],
55 | })
56 |
57 | await getScripts(false)
58 |
59 | await mainScript()
60 |
61 | export {}
62 |
--------------------------------------------------------------------------------
/src/cli/new-from-url.ts:
--------------------------------------------------------------------------------
1 | // Description: Creates a script from an entered url
2 |
3 | import { highlightJavaScript } from "../api/kit.js"
4 | import {
5 | checkIfCommandExists,
6 | stripMetadata,
7 | } from "../core/utils.js"
8 | import { prependImport } from "./lib/utils.js"
9 |
10 | let url = await arg({
11 | placeholder: "Enter script url:",
12 | })
13 |
14 | if (url.includes("gist.github.com")) {
15 | url = `${url}/raw `
16 | }
17 |
18 | let contents = (await get