termcast 1.3.30 ā 1.3.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apis/cache.d.ts.map +1 -1
- package/dist/apis/cache.js +4 -39
- package/dist/apis/cache.js.map +1 -1
- package/dist/apis/hud.d.ts.map +1 -1
- package/dist/apis/hud.js +13 -31
- package/dist/apis/hud.js.map +1 -1
- package/dist/apis/localstorage.d.ts.map +1 -1
- package/dist/apis/localstorage.js +3 -27
- package/dist/apis/localstorage.js.map +1 -1
- package/dist/apis/toast.d.ts +16 -43
- package/dist/apis/toast.d.ts.map +1 -1
- package/dist/apis/toast.js +78 -177
- package/dist/apis/toast.js.map +1 -1
- package/dist/build.d.ts +3 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +52 -2
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +206 -25
- package/dist/cli.js.map +1 -1
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +1 -0
- package/dist/colors.js.map +1 -1
- package/dist/compile.d.ts +0 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +18 -23
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.d.ts.map +1 -1
- package/dist/components/actions.js +30 -15
- package/dist/components/actions.js.map +1 -1
- package/dist/components/animation-tick.d.ts +12 -0
- package/dist/components/animation-tick.d.ts.map +1 -0
- package/dist/components/animation-tick.js +63 -0
- package/dist/components/animation-tick.js.map +1 -0
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +10 -13
- package/dist/components/detail.js.map +1 -1
- package/dist/components/dropdown.d.ts +1 -0
- package/dist/components/dropdown.d.ts.map +1 -1
- package/dist/components/dropdown.js +27 -26
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +15 -10
- package/dist/components/extension-preferences.js.map +1 -1
- package/dist/components/footer.d.ts +13 -0
- package/dist/components/footer.d.ts.map +1 -0
- package/dist/components/footer.js +106 -0
- package/dist/components/footer.js.map +1 -0
- package/dist/components/form/file-autocomplete.d.ts +19 -4
- package/dist/components/form/file-autocomplete.d.ts.map +1 -1
- package/dist/components/form/file-autocomplete.js +56 -55
- package/dist/components/form/file-autocomplete.js.map +1 -1
- package/dist/components/form/file-picker.d.ts.map +1 -1
- package/dist/components/form/file-picker.js +26 -15
- package/dist/components/form/file-picker.js.map +1 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +17 -15
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/form/with-left-border.d.ts.map +1 -1
- package/dist/components/form/with-left-border.js +4 -12
- package/dist/components/form/with-left-border.js.map +1 -1
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +126 -86
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.d.ts.map +1 -1
- package/dist/components/loading-bar.js +5 -22
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/loading-text.d.ts.map +1 -1
- package/dist/components/loading-text.js +3 -22
- package/dist/components/loading-text.js.map +1 -1
- package/dist/components/theme-picker.d.ts +2 -0
- package/dist/components/theme-picker.d.ts.map +1 -0
- package/dist/components/theme-picker.js +37 -0
- package/dist/components/theme-picker.js.map +1 -0
- package/dist/descendants.d.ts +6 -0
- package/dist/descendants.d.ts.map +1 -1
- package/dist/descendants.js +74 -8
- package/dist/descendants.js.map +1 -1
- package/dist/examples/internal/descendants-rerender.d.ts +14 -0
- package/dist/examples/internal/descendants-rerender.d.ts.map +1 -0
- package/dist/examples/internal/descendants-rerender.js +145 -0
- package/dist/examples/internal/descendants-rerender.js.map +1 -0
- package/dist/examples/internal/simple-dialog.js +4 -1
- package/dist/examples/internal/simple-dialog.js.map +1 -1
- package/dist/examples/internal/simple-scrollbox.js +1 -1
- package/dist/examples/internal/simple-scrollbox.js.map +1 -1
- package/dist/examples/list-with-dropdown.js +1 -1
- package/dist/examples/list-with-dropdown.js.map +1 -1
- package/dist/examples/miscellaneous.js +1 -1
- package/dist/examples/miscellaneous.js.map +1 -1
- package/dist/examples/toast-action.d.ts +2 -0
- package/dist/examples/toast-action.d.ts.map +1 -0
- package/dist/examples/toast-action.js +76 -0
- package/dist/examples/toast-action.js.map +1 -0
- package/dist/examples/toast-variations.js +38 -36
- package/dist/examples/toast-variations.js.map +1 -1
- package/dist/extensions/dev.d.ts +1 -1
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +62 -30
- package/dist/extensions/dev.js.map +1 -1
- package/dist/extensions/home.d.ts.map +1 -1
- package/dist/extensions/home.js +4 -3
- package/dist/extensions/home.js.map +1 -1
- package/dist/extensions/react-refresh-init.d.ts +5 -0
- package/dist/extensions/react-refresh-init.d.ts.map +1 -0
- package/dist/extensions/react-refresh-init.js +52 -0
- package/dist/extensions/react-refresh-init.js.map +1 -0
- package/dist/internal/date-picker-widget.js +1 -1
- package/dist/internal/date-picker-widget.js.map +1 -1
- package/dist/internal/dialog.d.ts +8 -3
- package/dist/internal/dialog.d.ts.map +1 -1
- package/dist/internal/dialog.js +37 -53
- package/dist/internal/dialog.js.map +1 -1
- package/dist/internal/navigation.d.ts +1 -0
- package/dist/internal/navigation.d.ts.map +1 -1
- package/dist/internal/navigation.js +25 -1
- package/dist/internal/navigation.js.map +1 -1
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +9 -197
- package/dist/internal/providers.js.map +1 -1
- package/dist/internal/scrollbox.d.ts.map +1 -1
- package/dist/internal/scrollbox.js +1 -0
- package/dist/internal/scrollbox.js.map +1 -1
- package/dist/release.d.ts +1 -0
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +16 -9
- package/dist/release.js.map +1 -1
- package/dist/state.d.ts +27 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +6 -0
- package/dist/state.js.map +1 -1
- package/dist/theme.d.ts +6 -19
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +76 -45
- package/dist/theme.js.map +1 -1
- package/dist/themes/aura.json +69 -0
- package/dist/themes/ayu.json +80 -0
- package/dist/themes/catppuccin-frappe.json +233 -0
- package/dist/themes/catppuccin-macchiato.json +233 -0
- package/dist/themes/catppuccin.json +112 -0
- package/dist/themes/cobalt2.json +228 -0
- package/dist/themes/cursor.json +249 -0
- package/dist/themes/dracula.json +219 -0
- package/dist/themes/everforest.json +241 -0
- package/dist/themes/flexoki.json +237 -0
- package/dist/themes/github-light.json +56 -0
- package/dist/themes/github.json +241 -0
- package/dist/themes/gruvbox.json +95 -0
- package/dist/themes/kanagawa.json +77 -0
- package/dist/themes/lucent-orng.json +227 -0
- package/dist/themes/material.json +235 -0
- package/dist/themes/matrix.json +77 -0
- package/dist/themes/mercury.json +245 -0
- package/dist/themes/monokai.json +221 -0
- package/dist/themes/nightowl.json +221 -0
- package/dist/themes/nord.json +223 -0
- package/dist/themes/one-dark.json +84 -0
- package/dist/themes/opencode-light.json +62 -0
- package/dist/themes/opencode.json +245 -0
- package/dist/themes/orng.json +245 -0
- package/dist/themes/palenight.json +222 -0
- package/dist/themes/rosepine.json +234 -0
- package/dist/themes/solarized.json +223 -0
- package/dist/themes/synthwave84.json +226 -0
- package/dist/themes/termcast.json +226 -0
- package/dist/themes/tokyonight.json +243 -0
- package/dist/themes/vercel.json +255 -0
- package/dist/themes/vesper.json +218 -0
- package/dist/themes/zenburn.json +223 -0
- package/dist/themes.d.ts +57 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +181 -0
- package/dist/themes.js.map +1 -0
- package/dist/utils/run-command.d.ts +2 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +20 -10
- package/dist/utils/run-command.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +90 -17
- package/dist/utils.js.map +1 -1
- package/dist/watcher.d.ts +3 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +16 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +16 -10
- package/src/apis/cache.tsx +5 -44
- package/src/apis/hud.tsx +17 -62
- package/src/apis/localstorage.tsx +3 -32
- package/src/apis/toast.tsx +91 -275
- package/src/build.test.tsx +10 -0
- package/src/build.tsx +61 -1
- package/src/cli.tsx +365 -103
- package/src/colors.tsx +1 -0
- package/src/compile.tsx +21 -29
- package/src/compile.vitest.tsx +300 -0
- package/src/components/actions.tsx +64 -45
- package/src/components/animation-tick.tsx +85 -0
- package/src/components/detail.tsx +31 -35
- package/src/components/dropdown.tsx +32 -21
- package/src/components/extension-preferences.tsx +14 -10
- package/src/components/footer.tsx +241 -0
- package/src/components/form/file-autocomplete.tsx +80 -60
- package/src/components/form/file-picker.tsx +37 -25
- package/src/components/form/index.tsx +45 -41
- package/src/components/form/with-left-border.tsx +4 -14
- package/src/components/list.tsx +181 -121
- package/src/components/loading-bar.tsx +5 -25
- package/src/components/loading-text.tsx +4 -23
- package/src/components/theme-picker.tsx +57 -0
- package/src/descendants.tsx +98 -9
- package/src/examples/actions-dialog-layout.vitest.tsx +112 -0
- package/src/examples/file-autocomplete.vitest.tsx +131 -122
- package/src/examples/form-basic.vitest.tsx +463 -644
- package/src/examples/form-dropdown.vitest.tsx +553 -571
- package/src/examples/form-scroll.vitest.tsx +112 -102
- package/src/examples/form-tagpicker.vitest.tsx +364 -338
- package/src/examples/internal/descendants-rerender.tsx +273 -0
- package/src/examples/internal/descendants-rerender.vitest.tsx +194 -0
- package/src/examples/internal/simple-dialog.tsx +4 -4
- package/src/examples/internal/simple-scrollbox.tsx +2 -2
- package/src/examples/internal/simple-scrollbox.vitest.tsx +43 -31
- package/src/examples/list-detail-metadata.vitest.tsx +34 -30
- package/src/examples/list-dropdown-default.vitest.tsx +84 -72
- package/src/examples/list-empty-view.vitest.tsx +93 -0
- package/src/examples/list-fetch-data.vitest.tsx +36 -30
- package/src/examples/list-scrollbox.vitest.tsx +59 -39
- package/src/examples/list-with-detail.vitest.tsx +339 -314
- package/src/examples/list-with-dropdown.tsx +1 -0
- package/src/examples/list-with-dropdown.vitest.tsx +176 -150
- package/src/examples/list-with-sections.vitest.tsx +289 -270
- package/src/examples/list-with-toast.vitest.tsx +44 -44
- package/src/examples/miscellaneous.tsx +10 -0
- package/src/examples/simple-file-picker.vitest.tsx +90 -86
- package/src/examples/simple-grid.vitest.tsx +275 -249
- package/src/examples/simple-navigation.vitest.tsx +192 -168
- package/src/examples/store.vitest.tsx +6 -4
- package/src/examples/swift-extension.vitest.tsx +31 -19
- package/src/examples/synonyms.vitest.tsx +93 -83
- package/src/examples/toast-action.tsx +160 -0
- package/src/examples/toast-action.vitest.tsx +404 -0
- package/src/examples/toast-variations.tsx +58 -57
- package/src/examples/toast-variations.vitest.tsx +186 -166
- package/src/extensions/dev.tsx +74 -33
- package/src/extensions/dev.vitest.tsx +162 -69
- package/src/extensions/home.tsx +5 -6
- package/src/extensions/react-refresh-init.tsx +59 -0
- package/src/internal/date-picker-widget.tsx +1 -1
- package/src/internal/dialog.tsx +59 -83
- package/src/internal/navigation.tsx +37 -4
- package/src/internal/providers.tsx +27 -315
- package/src/internal/scrollbox.tsx +1 -0
- package/src/release.tsx +16 -10
- package/src/state.tsx +36 -3
- package/src/theme.tsx +82 -51
- package/src/themes/aura.json +69 -0
- package/src/themes/ayu.json +80 -0
- package/src/themes/catppuccin-frappe.json +233 -0
- package/src/themes/catppuccin-macchiato.json +233 -0
- package/src/themes/catppuccin.json +112 -0
- package/src/themes/cobalt2.json +228 -0
- package/src/themes/cursor.json +249 -0
- package/src/themes/dracula.json +219 -0
- package/src/themes/everforest.json +241 -0
- package/src/themes/flexoki.json +237 -0
- package/src/themes/github-light.json +56 -0
- package/src/themes/github.json +241 -0
- package/src/themes/gruvbox.json +95 -0
- package/src/themes/kanagawa.json +77 -0
- package/src/themes/lucent-orng.json +227 -0
- package/src/themes/material.json +235 -0
- package/src/themes/matrix.json +77 -0
- package/src/themes/mercury.json +252 -0
- package/src/themes/monokai.json +221 -0
- package/src/themes/nightowl.json +221 -0
- package/src/themes/nord.json +223 -0
- package/src/themes/one-dark.json +84 -0
- package/src/themes/opencode-light.json +62 -0
- package/src/themes/opencode.json +245 -0
- package/src/themes/orng.json +245 -0
- package/src/themes/palenight.json +222 -0
- package/src/themes/rosepine.json +234 -0
- package/src/themes/solarized.json +223 -0
- package/src/themes/synthwave84.json +226 -0
- package/src/themes/termcast.json +227 -0
- package/src/themes/tokyonight.json +243 -0
- package/src/themes/vercel.json +255 -0
- package/src/themes/vesper.json +218 -0
- package/src/themes/zenburn.json +223 -0
- package/src/themes.ts +291 -0
- package/src/utils/run-command.tsx +23 -12
- package/src/utils.tsx +115 -18
- package/src/watcher.tsx +19 -0
package/src/cli.tsx
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
+
// CRITICAL: Import react-refresh-init FIRST before anything that imports @opentui/react
|
|
4
|
+
// This ensures the devtools hook exists before the reconciler calls injectIntoDevTools()
|
|
5
|
+
import './extensions/react-refresh-init'
|
|
6
|
+
|
|
3
7
|
import fs from 'node:fs'
|
|
4
8
|
import path from 'node:path'
|
|
5
9
|
import { execSync, spawn } from 'node:child_process'
|
|
6
10
|
import { cac } from 'cac'
|
|
7
|
-
import
|
|
11
|
+
import { getWatcher } from './watcher'
|
|
8
12
|
import { buildExtensionCommands } from './build'
|
|
9
13
|
import { logger } from './logger'
|
|
10
14
|
import { installExtension } from './utils'
|
|
@@ -32,7 +36,7 @@ async function checkForUpdates() {
|
|
|
32
36
|
return
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
const latestRelease = await response.json()
|
|
39
|
+
const latestRelease = (await response.json()) as { tag_name?: string }
|
|
36
40
|
const latestVersion =
|
|
37
41
|
latestRelease.tag_name?.replace('termcast@', '') ||
|
|
38
42
|
latestRelease.tag_name?.replace('v', '')
|
|
@@ -40,10 +44,14 @@ async function checkForUpdates() {
|
|
|
40
44
|
// Compare versions
|
|
41
45
|
if (latestVersion && latestVersion !== currentVersion) {
|
|
42
46
|
// Run the install script in background
|
|
43
|
-
const updateProcess = spawn(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
const updateProcess = spawn(
|
|
48
|
+
'bash',
|
|
49
|
+
['-c', 'curl -sf https://termcast.app/install | bash'],
|
|
50
|
+
{
|
|
51
|
+
detached: true,
|
|
52
|
+
stdio: 'ignore',
|
|
53
|
+
},
|
|
54
|
+
)
|
|
47
55
|
|
|
48
56
|
updateProcess.on('exit', async (code) => {
|
|
49
57
|
if (code === 0) {
|
|
@@ -64,20 +72,22 @@ async function checkForUpdates() {
|
|
|
64
72
|
}
|
|
65
73
|
}
|
|
66
74
|
|
|
67
|
-
//
|
|
68
|
-
checkForUpdates()
|
|
75
|
+
// TODO: re-enable auto-update check once install script temp dir issue is fixed
|
|
76
|
+
// checkForUpdates()
|
|
69
77
|
|
|
70
78
|
cli
|
|
71
79
|
.command('dev [path]', 'Run the extension in the current working directory')
|
|
72
80
|
.action(async (rawExtensionPath, options) => {
|
|
73
81
|
try {
|
|
74
82
|
// Check if the provided arg looks like a path (contains / or . or is existing dir)
|
|
75
|
-
const looksLikePath =
|
|
76
|
-
rawExtensionPath
|
|
77
|
-
rawExtensionPath.
|
|
78
|
-
|
|
83
|
+
const looksLikePath =
|
|
84
|
+
rawExtensionPath &&
|
|
85
|
+
(rawExtensionPath.includes('/') ||
|
|
86
|
+
rawExtensionPath.startsWith('.') ||
|
|
87
|
+
fs.existsSync(rawExtensionPath))
|
|
88
|
+
const extensionPath = path.resolve(
|
|
89
|
+
looksLikePath ? rawExtensionPath : process.cwd(),
|
|
79
90
|
)
|
|
80
|
-
const extensionPath = path.resolve(looksLikePath ? rawExtensionPath : process.cwd())
|
|
81
91
|
let isBuilding = false
|
|
82
92
|
|
|
83
93
|
// Start dev mode with initial render
|
|
@@ -96,16 +106,57 @@ cli
|
|
|
96
106
|
console.log('\nWatching for file changes...')
|
|
97
107
|
|
|
98
108
|
// Watch entire extension directory using @parcel/watcher
|
|
109
|
+
// Single source of truth for ignored patterns
|
|
110
|
+
const IGNORED_DIRS = [
|
|
111
|
+
'node_modules',
|
|
112
|
+
'.termcast-bundle',
|
|
113
|
+
'.git',
|
|
114
|
+
'.build', // Swift build output
|
|
115
|
+
'.cache',
|
|
116
|
+
'tmp',
|
|
117
|
+
'.tmp',
|
|
118
|
+
'dist',
|
|
119
|
+
'build',
|
|
120
|
+
]
|
|
121
|
+
const IGNORED_EXTENSIONS = ['.log', '.db', '.sqlite']
|
|
122
|
+
|
|
123
|
+
// Glob patterns for @parcel/watcher (matched against relative paths using micromatch)
|
|
99
124
|
const ignoredPatterns = [
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
'
|
|
104
|
-
'**/*.
|
|
105
|
-
'**/dist/**',
|
|
106
|
-
'**/build/**',
|
|
125
|
+
...IGNORED_DIRS.map((dir) => `**/${dir}/**`),
|
|
126
|
+
...IGNORED_EXTENSIONS.map((ext) => `**/*${ext}`),
|
|
127
|
+
// SQLite creates .db-wal and .db-shm alongside .db
|
|
128
|
+
'**/*.db-*',
|
|
129
|
+
'**/*.sqlite-*',
|
|
107
130
|
]
|
|
108
131
|
|
|
132
|
+
// Backup filter for files that should never trigger rebuild
|
|
133
|
+
// This catches cases where @parcel/watcher ignore doesn't work as expected
|
|
134
|
+
const shouldIgnoreFile = (filePath: string): boolean => {
|
|
135
|
+
const relativePath = path.relative(extensionPath, filePath)
|
|
136
|
+
// Ignore files outside the extension directory
|
|
137
|
+
if (relativePath.startsWith('..')) {
|
|
138
|
+
return true
|
|
139
|
+
}
|
|
140
|
+
// Check if path contains any ignored directory
|
|
141
|
+
const hasIgnoredDir = IGNORED_DIRS.some(
|
|
142
|
+
(dir) =>
|
|
143
|
+
relativePath.includes(`/${dir}/`) ||
|
|
144
|
+
relativePath.startsWith(`${dir}/`),
|
|
145
|
+
)
|
|
146
|
+
if (hasIgnoredDir) {
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
// Check if file has ignored extension
|
|
150
|
+
if (IGNORED_EXTENSIONS.some((ext) => relativePath.endsWith(ext))) {
|
|
151
|
+
return true
|
|
152
|
+
}
|
|
153
|
+
// Also catch .db-* and .sqlite-* patterns
|
|
154
|
+
if (/\.db-|\.sqlite-/.test(relativePath)) {
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
|
|
109
160
|
const rebuild = async (filePath: string) => {
|
|
110
161
|
if (isBuilding) {
|
|
111
162
|
logger.log('Build already in progress, skipping...')
|
|
@@ -125,19 +176,24 @@ cli
|
|
|
125
176
|
}
|
|
126
177
|
}
|
|
127
178
|
|
|
128
|
-
const subscription = await
|
|
179
|
+
const subscription = await getWatcher().subscribe(
|
|
129
180
|
extensionPath,
|
|
130
181
|
(err, events) => {
|
|
131
182
|
if (err) {
|
|
132
183
|
logger.error('Watcher error:', err)
|
|
133
184
|
return
|
|
134
185
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
186
|
+
|
|
187
|
+
// Filter out events for files that should be ignored
|
|
188
|
+
const relevantEvents = events.filter(
|
|
189
|
+
(event) => !shouldIgnoreFile(event.path),
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if (relevantEvents.length > 0) {
|
|
193
|
+
rebuild(relevantEvents[0].path)
|
|
138
194
|
}
|
|
139
195
|
},
|
|
140
|
-
{ ignore: ignoredPatterns }
|
|
196
|
+
{ ignore: ignoredPatterns },
|
|
141
197
|
)
|
|
142
198
|
|
|
143
199
|
// Clean up watcher on exit signals
|
|
@@ -182,6 +238,7 @@ cli
|
|
|
182
238
|
extensionSourcePath: extensionPath,
|
|
183
239
|
})
|
|
184
240
|
console.log(`\nExtension installed to store as '${extensionName}'`)
|
|
241
|
+
process.exit(0)
|
|
185
242
|
} catch (error: any) {
|
|
186
243
|
console.error('Build failed:', error.message)
|
|
187
244
|
process.exit(1)
|
|
@@ -205,6 +262,7 @@ cli
|
|
|
205
262
|
|
|
206
263
|
console.log(`\nExecutable created: ${result.outfile}`)
|
|
207
264
|
console.log(`Run it with: ${result.outfile}`)
|
|
265
|
+
process.exit(0)
|
|
208
266
|
} catch (error: any) {
|
|
209
267
|
console.error('Compile failed:', error.message)
|
|
210
268
|
process.exit(1)
|
|
@@ -234,7 +292,10 @@ cli
|
|
|
234
292
|
})
|
|
235
293
|
|
|
236
294
|
cli
|
|
237
|
-
.command(
|
|
295
|
+
.command(
|
|
296
|
+
'raycast-pr <prNumber>',
|
|
297
|
+
'Download extension from a GitHub PR in Raycast extensions repo. To test it with Termcast',
|
|
298
|
+
)
|
|
238
299
|
.action(async (prNumber: string) => {
|
|
239
300
|
try {
|
|
240
301
|
// Parse PR number from URL if provided
|
|
@@ -254,13 +315,34 @@ cli
|
|
|
254
315
|
)
|
|
255
316
|
|
|
256
317
|
if (!prResponse.ok) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
318
|
+
if (prResponse.status === 403) {
|
|
319
|
+
const rateLimitRemaining = prResponse.headers.get(
|
|
320
|
+
'x-ratelimit-remaining',
|
|
321
|
+
)
|
|
322
|
+
if (rateLimitRemaining === '0') {
|
|
323
|
+
const resetTime = prResponse.headers.get('x-ratelimit-reset')
|
|
324
|
+
const resetDate = resetTime
|
|
325
|
+
? new Date(parseInt(resetTime) * 1000).toLocaleTimeString()
|
|
326
|
+
: 'soon'
|
|
327
|
+
console.error(
|
|
328
|
+
`GitHub API rate limit exceeded. Resets at ${resetDate}`,
|
|
329
|
+
)
|
|
330
|
+
} else {
|
|
331
|
+
console.error(`Access forbidden for PR #${parsedPrNumber}`)
|
|
332
|
+
}
|
|
333
|
+
} else if (prResponse.status === 404) {
|
|
334
|
+
console.error(`PR #${parsedPrNumber} not found`)
|
|
335
|
+
} else {
|
|
336
|
+
console.error(
|
|
337
|
+
`Failed to fetch PR #${parsedPrNumber}: ${prResponse.status} ${prResponse.statusText}`,
|
|
338
|
+
)
|
|
339
|
+
}
|
|
260
340
|
process.exit(1)
|
|
261
341
|
}
|
|
262
342
|
|
|
263
|
-
const prData = await prResponse.json()
|
|
343
|
+
const prData = (await prResponse.json()) as {
|
|
344
|
+
head: { user: { login: string }; ref: string; repo: { clone_url: string } }
|
|
345
|
+
}
|
|
264
346
|
const prAuthor = prData.head.user.login
|
|
265
347
|
const branch = prData.head.ref
|
|
266
348
|
const forkUrl = prData.head.repo.clone_url
|
|
@@ -376,8 +458,76 @@ cli
|
|
|
376
458
|
})
|
|
377
459
|
|
|
378
460
|
cli
|
|
379
|
-
.command(
|
|
380
|
-
|
|
461
|
+
.command(
|
|
462
|
+
'raycast-pr-diff <prNumber>',
|
|
463
|
+
'Show the diff of a PR in Raycast extensions repo',
|
|
464
|
+
)
|
|
465
|
+
.action(async (prNumber: string) => {
|
|
466
|
+
try {
|
|
467
|
+
// Parse PR number from URL if provided
|
|
468
|
+
let parsedPrNumber = prNumber
|
|
469
|
+
const urlMatch = prNumber.match(
|
|
470
|
+
/github\.com\/raycast\/extensions\/pull\/(\d+)/,
|
|
471
|
+
)
|
|
472
|
+
if (urlMatch) {
|
|
473
|
+
parsedPrNumber = urlMatch[1]
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
console.error(`Fetching diff for PR #${parsedPrNumber}...`)
|
|
477
|
+
|
|
478
|
+
// Fetch diff directly from GitHub API
|
|
479
|
+
const response = await fetch(
|
|
480
|
+
`https://api.github.com/repos/raycast/extensions/pulls/${parsedPrNumber}`,
|
|
481
|
+
{
|
|
482
|
+
headers: {
|
|
483
|
+
Accept: 'application/vnd.github.v3.diff',
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
if (!response.ok) {
|
|
489
|
+
if (response.status === 403) {
|
|
490
|
+
const rateLimitRemaining = response.headers.get(
|
|
491
|
+
'x-ratelimit-remaining',
|
|
492
|
+
)
|
|
493
|
+
if (rateLimitRemaining === '0') {
|
|
494
|
+
const resetTime = response.headers.get('x-ratelimit-reset')
|
|
495
|
+
const resetDate = resetTime
|
|
496
|
+
? new Date(parseInt(resetTime) * 1000).toLocaleTimeString()
|
|
497
|
+
: 'soon'
|
|
498
|
+
console.error(
|
|
499
|
+
`GitHub API rate limit exceeded. Resets at ${resetDate}`,
|
|
500
|
+
)
|
|
501
|
+
} else {
|
|
502
|
+
console.error(`Access forbidden for PR #${parsedPrNumber}`)
|
|
503
|
+
}
|
|
504
|
+
} else if (response.status === 404) {
|
|
505
|
+
console.error(`PR #${parsedPrNumber} not found`)
|
|
506
|
+
} else {
|
|
507
|
+
console.error(
|
|
508
|
+
`Failed to fetch PR #${parsedPrNumber}: ${response.status} ${response.statusText}`,
|
|
509
|
+
)
|
|
510
|
+
}
|
|
511
|
+
process.exit(1)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const diff = await response.text()
|
|
515
|
+
console.log(diff)
|
|
516
|
+
process.exit(0)
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error('Error fetching PR diff:', error)
|
|
519
|
+
process.exit(1)
|
|
520
|
+
}
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
cli
|
|
524
|
+
.command(
|
|
525
|
+
'raycast-search <query>',
|
|
526
|
+
'Search for extensions in the Raycast store',
|
|
527
|
+
)
|
|
528
|
+
.option('-n, --limit <number>', 'Number of results to show', {
|
|
529
|
+
default: '10',
|
|
530
|
+
})
|
|
381
531
|
.action(async (query: string, options: { limit: string }) => {
|
|
382
532
|
try {
|
|
383
533
|
const limit = parseInt(options.limit, 10)
|
|
@@ -394,14 +544,18 @@ cli
|
|
|
394
544
|
const downloads = ext.download_count.toLocaleString()
|
|
395
545
|
const commands = ext.commands.map((c) => c.name).join(', ')
|
|
396
546
|
console.log(` ${ext.name}`)
|
|
397
|
-
console.log(
|
|
547
|
+
console.log(
|
|
548
|
+
` Path: extensions/${ext.relative_path.replace('extensions/', '')}`,
|
|
549
|
+
)
|
|
398
550
|
console.log(` Downloads: ${downloads}`)
|
|
399
551
|
console.log(` Commands: ${commands || 'none'}`)
|
|
400
|
-
console.log(
|
|
552
|
+
console.log(
|
|
553
|
+
` Description: ${ext.description.slice(0, 100)}${ext.description.length > 100 ? '...' : ''}`,
|
|
554
|
+
)
|
|
401
555
|
console.log()
|
|
402
556
|
}
|
|
403
557
|
|
|
404
|
-
console.log(`Download with: termcast download <extension-name>`)
|
|
558
|
+
console.log(`Download with: termcast raycast-download <extension-name>`)
|
|
405
559
|
process.exit(0)
|
|
406
560
|
} catch (error: any) {
|
|
407
561
|
console.error('Search failed:', error.message)
|
|
@@ -410,98 +564,206 @@ cli
|
|
|
410
564
|
})
|
|
411
565
|
|
|
412
566
|
cli
|
|
413
|
-
.command(
|
|
567
|
+
.command(
|
|
568
|
+
'raycast-download <extensionName>',
|
|
569
|
+
'Download extension from Raycast extensions repo',
|
|
570
|
+
)
|
|
414
571
|
.option('-o, --output <path>', 'Output directory', { default: '.' })
|
|
415
|
-
.option(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
572
|
+
.option(
|
|
573
|
+
'--no-dir',
|
|
574
|
+
'Put files directly in output directory instead of creating extension subdirectory',
|
|
575
|
+
)
|
|
576
|
+
.action(
|
|
577
|
+
async (
|
|
578
|
+
extensionName: string,
|
|
579
|
+
options: { output: string; dir: boolean },
|
|
580
|
+
) => {
|
|
581
|
+
try {
|
|
582
|
+
const destPath = path.resolve(options.output)
|
|
583
|
+
// When --no-dir is passed, dir is false; put files directly in destPath
|
|
584
|
+
const extensionDir = options.dir
|
|
585
|
+
? path.join(destPath, extensionName)
|
|
586
|
+
: destPath
|
|
587
|
+
const tempCloneDir = path.join(
|
|
588
|
+
destPath,
|
|
589
|
+
`.tmp-${extensionName}-${Date.now()}`,
|
|
590
|
+
)
|
|
422
591
|
|
|
423
|
-
|
|
592
|
+
console.log(
|
|
593
|
+
`Downloading extension '${extensionName}' from raycast/extensions...`,
|
|
594
|
+
)
|
|
424
595
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
596
|
+
if (options.dir && fs.existsSync(extensionDir)) {
|
|
597
|
+
console.log(`Removing existing directory: ${extensionDir}`)
|
|
598
|
+
fs.rmSync(extensionDir, { recursive: true, force: true })
|
|
599
|
+
}
|
|
429
600
|
|
|
430
|
-
|
|
601
|
+
fs.mkdirSync(destPath, { recursive: true })
|
|
431
602
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
603
|
+
const repoUrl = 'https://github.com/raycast/extensions.git'
|
|
604
|
+
const cloneDirName = path.basename(tempCloneDir)
|
|
605
|
+
const cloneCmd = `git clone -n --depth=1 --filter=tree:0 "${repoUrl}" "${cloneDirName}"`
|
|
606
|
+
console.log(`Running: ${cloneCmd}`)
|
|
607
|
+
try {
|
|
608
|
+
execSync(cloneCmd, {
|
|
609
|
+
cwd: destPath,
|
|
610
|
+
stdio: 'inherit',
|
|
611
|
+
})
|
|
612
|
+
} catch (error) {
|
|
613
|
+
console.error(`Failed to clone repository`)
|
|
614
|
+
process.exit(1)
|
|
615
|
+
}
|
|
445
616
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
617
|
+
const sparseCmd = `git sparse-checkout set --no-cone "extensions/${extensionName}"`
|
|
618
|
+
console.log(`Running: ${sparseCmd}`)
|
|
619
|
+
try {
|
|
620
|
+
execSync(sparseCmd, {
|
|
621
|
+
cwd: tempCloneDir,
|
|
622
|
+
stdio: 'inherit',
|
|
623
|
+
})
|
|
624
|
+
} catch (error) {
|
|
625
|
+
console.error(`Failed to set sparse-checkout`)
|
|
626
|
+
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
627
|
+
process.exit(1)
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const checkoutCmd = 'git checkout'
|
|
631
|
+
console.log(`Running: ${checkoutCmd}`)
|
|
632
|
+
try {
|
|
633
|
+
execSync(checkoutCmd, {
|
|
634
|
+
cwd: tempCloneDir,
|
|
635
|
+
stdio: 'inherit',
|
|
636
|
+
})
|
|
637
|
+
} catch (error) {
|
|
638
|
+
console.error(`Failed to checkout files`)
|
|
639
|
+
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
640
|
+
process.exit(1)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
const extensionPath = path.join(
|
|
644
|
+
tempCloneDir,
|
|
645
|
+
'extensions',
|
|
646
|
+
extensionName,
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
if (!fs.existsSync(extensionPath)) {
|
|
650
|
+
console.error(
|
|
651
|
+
`Extension '${extensionName}' not found in raycast/extensions repo`,
|
|
652
|
+
)
|
|
653
|
+
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
654
|
+
process.exit(1)
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Move files to final destination
|
|
658
|
+
if (options.dir) {
|
|
659
|
+
fs.mkdirSync(extensionDir, { recursive: true })
|
|
660
|
+
}
|
|
661
|
+
const filesToMove = fs.readdirSync(extensionPath)
|
|
662
|
+
for (const file of filesToMove) {
|
|
663
|
+
const src = path.join(extensionPath, file)
|
|
664
|
+
const dest = path.join(extensionDir, file)
|
|
665
|
+
fs.renameSync(src, dest)
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Clean up temp clone directory
|
|
455
669
|
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
456
|
-
process.exit(1)
|
|
457
|
-
}
|
|
458
670
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
execSync(checkoutCmd, {
|
|
463
|
-
cwd: tempCloneDir,
|
|
671
|
+
console.log(`\nInstalling dependencies...`)
|
|
672
|
+
execSync('npm install', {
|
|
673
|
+
cwd: extensionDir,
|
|
464
674
|
stdio: 'inherit',
|
|
465
675
|
})
|
|
676
|
+
|
|
677
|
+
console.log(`\nā
Extension downloaded successfully!`)
|
|
678
|
+
console.log(`š Path: ${extensionDir}`)
|
|
679
|
+
process.exit(0)
|
|
466
680
|
} catch (error) {
|
|
467
|
-
console.error(
|
|
468
|
-
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
681
|
+
console.error('Error downloading extension:', error)
|
|
469
682
|
process.exit(1)
|
|
470
683
|
}
|
|
684
|
+
},
|
|
685
|
+
)
|
|
471
686
|
|
|
472
|
-
|
|
687
|
+
cli
|
|
688
|
+
.command('new <name>', 'Create a new termcast extension')
|
|
689
|
+
.action(async (name: string) => {
|
|
690
|
+
try {
|
|
691
|
+
const targetDir = path.resolve(name)
|
|
473
692
|
|
|
474
|
-
if (
|
|
475
|
-
console.error(`
|
|
476
|
-
fs.rmSync(tempCloneDir, { recursive: true, force: true })
|
|
693
|
+
if (fs.existsSync(targetDir)) {
|
|
694
|
+
console.error(`Directory "${name}" already exists`)
|
|
477
695
|
process.exit(1)
|
|
478
696
|
}
|
|
479
697
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
698
|
+
console.log(`Creating new extension "${name}"...`)
|
|
699
|
+
|
|
700
|
+
// Download template from GitHub
|
|
701
|
+
const templateUrl =
|
|
702
|
+
'https://github.com/remorses/termcast/archive/refs/heads/main.zip'
|
|
703
|
+
|
|
704
|
+
console.log('Downloading template...')
|
|
705
|
+
const response = await fetch(templateUrl)
|
|
706
|
+
if (!response.ok) {
|
|
707
|
+
throw new Error(`Failed to download template: ${response.status}`)
|
|
483
708
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
709
|
+
|
|
710
|
+
console.log('Extracting...')
|
|
711
|
+
const JSZip = (await import('jszip')).default
|
|
712
|
+
const zip = await JSZip.loadAsync(await response.arrayBuffer())
|
|
713
|
+
|
|
714
|
+
// Find the template folder in the zip
|
|
715
|
+
const templatePrefix = 'termcast-main/termcast/template/'
|
|
716
|
+
const templateFiles = Object.keys(zip.files).filter((name) =>
|
|
717
|
+
name.startsWith(templatePrefix),
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
if (templateFiles.length === 0) {
|
|
721
|
+
throw new Error('Template not found in downloaded archive')
|
|
489
722
|
}
|
|
490
723
|
|
|
491
|
-
//
|
|
492
|
-
fs.
|
|
724
|
+
// Extract template files to target directory
|
|
725
|
+
fs.mkdirSync(targetDir, { recursive: true })
|
|
493
726
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
727
|
+
for (const filePath of templateFiles) {
|
|
728
|
+
const relativePath = filePath.slice(templatePrefix.length)
|
|
729
|
+
if (!relativePath) {
|
|
730
|
+
continue
|
|
731
|
+
}
|
|
499
732
|
|
|
500
|
-
|
|
501
|
-
|
|
733
|
+
const targetPath = path.join(targetDir, relativePath)
|
|
734
|
+
const zipEntry = zip.files[filePath]
|
|
735
|
+
|
|
736
|
+
if (zipEntry.dir) {
|
|
737
|
+
fs.mkdirSync(targetPath, { recursive: true })
|
|
738
|
+
} else {
|
|
739
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true })
|
|
740
|
+
const content = await zipEntry.async('nodebuffer')
|
|
741
|
+
fs.writeFileSync(targetPath, content)
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Replace placeholders in package.json
|
|
746
|
+
const packageJsonPath = path.join(targetDir, 'package.json')
|
|
747
|
+
let packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8')
|
|
748
|
+
const title = name
|
|
749
|
+
.split('-')
|
|
750
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
751
|
+
.join(' ')
|
|
752
|
+
packageJsonContent = packageJsonContent
|
|
753
|
+
.replace(/\{\{name\}\}/g, name)
|
|
754
|
+
.replace(/\{\{title\}\}/g, title)
|
|
755
|
+
fs.writeFileSync(packageJsonPath, packageJsonContent)
|
|
756
|
+
|
|
757
|
+
console.log('\nInstalling dependencies...')
|
|
758
|
+
execSync('bun install', { cwd: targetDir, stdio: 'inherit' })
|
|
759
|
+
|
|
760
|
+
console.log(`\nā
Created "${name}" successfully!`)
|
|
761
|
+
console.log(`\nNext steps:`)
|
|
762
|
+
console.log(` cd ${name}`)
|
|
763
|
+
console.log(` termcast dev`)
|
|
502
764
|
process.exit(0)
|
|
503
|
-
} catch (error) {
|
|
504
|
-
console.error('
|
|
765
|
+
} catch (error: any) {
|
|
766
|
+
console.error('Failed to create extension:', error.message)
|
|
505
767
|
process.exit(1)
|
|
506
768
|
}
|
|
507
769
|
})
|
package/src/colors.tsx
CHANGED
|
@@ -30,6 +30,7 @@ export function resolveColor(color: Color.ColorLike | undefined | null): string
|
|
|
30
30
|
return color
|
|
31
31
|
}
|
|
32
32
|
if (typeof color === 'object' && 'dark' in color) {
|
|
33
|
+
// Color.Dynamic - just use dark variant (light themes should use flat colors)
|
|
33
34
|
return color.dark
|
|
34
35
|
}
|
|
35
36
|
return undefined
|