@take-out/cli 0.0.39
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/LICENSE +21 -0
- package/README.md +274 -0
- package/cli.mjs +3 -0
- package/dist/cjs/cli.cjs +71 -0
- package/dist/cjs/cli.js +70 -0
- package/dist/cjs/cli.js.map +6 -0
- package/dist/cjs/cli.native.js +79 -0
- package/dist/cjs/cli.native.js.map +6 -0
- package/dist/cjs/commands/changed.cjs +212 -0
- package/dist/cjs/commands/changed.js +214 -0
- package/dist/cjs/commands/changed.js.map +6 -0
- package/dist/cjs/commands/changed.native.js +289 -0
- package/dist/cjs/commands/changed.native.js.map +6 -0
- package/dist/cjs/commands/docs.cjs +388 -0
- package/dist/cjs/commands/docs.js +313 -0
- package/dist/cjs/commands/docs.js.map +6 -0
- package/dist/cjs/commands/docs.native.js +476 -0
- package/dist/cjs/commands/docs.native.js.map +6 -0
- package/dist/cjs/commands/env-setup.cjs +90 -0
- package/dist/cjs/commands/env-setup.js +78 -0
- package/dist/cjs/commands/env-setup.js.map +6 -0
- package/dist/cjs/commands/env-setup.native.js +85 -0
- package/dist/cjs/commands/env-setup.native.js.map +6 -0
- package/dist/cjs/commands/onboard.cjs +479 -0
- package/dist/cjs/commands/onboard.js +631 -0
- package/dist/cjs/commands/onboard.js.map +6 -0
- package/dist/cjs/commands/onboard.native.js +608 -0
- package/dist/cjs/commands/onboard.native.js.map +6 -0
- package/dist/cjs/commands/run.cjs +148 -0
- package/dist/cjs/commands/run.js +116 -0
- package/dist/cjs/commands/run.js.map +6 -0
- package/dist/cjs/commands/run.native.js +140 -0
- package/dist/cjs/commands/run.native.js.map +6 -0
- package/dist/cjs/commands/script.cjs +379 -0
- package/dist/cjs/commands/script.js +339 -0
- package/dist/cjs/commands/script.js.map +6 -0
- package/dist/cjs/commands/script.native.js +449 -0
- package/dist/cjs/commands/script.native.js.map +6 -0
- package/dist/cjs/commands/sync.cjs +190 -0
- package/dist/cjs/commands/sync.js +168 -0
- package/dist/cjs/commands/sync.js.map +6 -0
- package/dist/cjs/commands/sync.native.js +211 -0
- package/dist/cjs/commands/sync.native.js.map +6 -0
- package/dist/cjs/constants/ascii.cjs +36 -0
- package/dist/cjs/constants/ascii.js +30 -0
- package/dist/cjs/constants/ascii.js.map +6 -0
- package/dist/cjs/constants/ascii.native.js +36 -0
- package/dist/cjs/constants/ascii.native.js.map +6 -0
- package/dist/cjs/index.cjs +64 -0
- package/dist/cjs/index.js +55 -0
- package/dist/cjs/index.js.map +6 -0
- package/dist/cjs/index.native.js +94 -0
- package/dist/cjs/index.native.js.map +6 -0
- package/dist/cjs/types.cjs +16 -0
- package/dist/cjs/types.js +14 -0
- package/dist/cjs/types.js.map +6 -0
- package/dist/cjs/types.native.js +15 -0
- package/dist/cjs/types.native.js.map +6 -0
- package/dist/cjs/utils/env-categories.cjs +272 -0
- package/dist/cjs/utils/env-categories.js +296 -0
- package/dist/cjs/utils/env-categories.js.map +6 -0
- package/dist/cjs/utils/env-categories.native.js +317 -0
- package/dist/cjs/utils/env-categories.native.js.map +6 -0
- package/dist/cjs/utils/env-setup.cjs +181 -0
- package/dist/cjs/utils/env-setup.js +190 -0
- package/dist/cjs/utils/env-setup.js.map +6 -0
- package/dist/cjs/utils/env-setup.native.js +264 -0
- package/dist/cjs/utils/env-setup.native.js.map +6 -0
- package/dist/cjs/utils/env.cjs +118 -0
- package/dist/cjs/utils/env.js +97 -0
- package/dist/cjs/utils/env.js.map +6 -0
- package/dist/cjs/utils/env.native.js +128 -0
- package/dist/cjs/utils/env.native.js.map +6 -0
- package/dist/cjs/utils/files.cjs +215 -0
- package/dist/cjs/utils/files.js +164 -0
- package/dist/cjs/utils/files.js.map +6 -0
- package/dist/cjs/utils/files.native.js +266 -0
- package/dist/cjs/utils/files.native.js.map +6 -0
- package/dist/cjs/utils/parallel-runner.cjs +99 -0
- package/dist/cjs/utils/parallel-runner.js +84 -0
- package/dist/cjs/utils/parallel-runner.js.map +6 -0
- package/dist/cjs/utils/parallel-runner.native.js +123 -0
- package/dist/cjs/utils/parallel-runner.native.js.map +6 -0
- package/dist/cjs/utils/ports.cjs +101 -0
- package/dist/cjs/utils/ports.js +81 -0
- package/dist/cjs/utils/ports.js.map +6 -0
- package/dist/cjs/utils/ports.native.js +130 -0
- package/dist/cjs/utils/ports.native.js.map +6 -0
- package/dist/cjs/utils/prerequisites.cjs +119 -0
- package/dist/cjs/utils/prerequisites.js +107 -0
- package/dist/cjs/utils/prerequisites.js.map +6 -0
- package/dist/cjs/utils/prerequisites.native.js +127 -0
- package/dist/cjs/utils/prerequisites.native.js.map +6 -0
- package/dist/cjs/utils/prompts.cjs +161 -0
- package/dist/cjs/utils/prompts.js +162 -0
- package/dist/cjs/utils/prompts.js.map +6 -0
- package/dist/cjs/utils/prompts.native.js +179 -0
- package/dist/cjs/utils/prompts.native.js.map +6 -0
- package/dist/cjs/utils/script-listing.cjs +113 -0
- package/dist/cjs/utils/script-listing.js +108 -0
- package/dist/cjs/utils/script-listing.js.map +6 -0
- package/dist/cjs/utils/script-listing.native.js +174 -0
- package/dist/cjs/utils/script-listing.native.js.map +6 -0
- package/dist/cjs/utils/sync.cjs +85 -0
- package/dist/cjs/utils/sync.js +70 -0
- package/dist/cjs/utils/sync.js.map +6 -0
- package/dist/cjs/utils/sync.native.js +84 -0
- package/dist/cjs/utils/sync.native.js.map +6 -0
- package/dist/cjs/utils/welcome.cjs +50 -0
- package/dist/cjs/utils/welcome.js +42 -0
- package/dist/cjs/utils/welcome.js.map +6 -0
- package/dist/cjs/utils/welcome.native.js +47 -0
- package/dist/cjs/utils/welcome.native.js.map +6 -0
- package/dist/esm/cli.js +79 -0
- package/dist/esm/cli.js.map +6 -0
- package/dist/esm/cli.mjs +71 -0
- package/dist/esm/cli.mjs.map +1 -0
- package/dist/esm/cli.native.js +69 -0
- package/dist/esm/cli.native.js.map +1 -0
- package/dist/esm/commands/changed.js +194 -0
- package/dist/esm/commands/changed.js.map +6 -0
- package/dist/esm/commands/changed.mjs +178 -0
- package/dist/esm/commands/changed.mjs.map +1 -0
- package/dist/esm/commands/changed.native.js +273 -0
- package/dist/esm/commands/changed.native.js.map +1 -0
- package/dist/esm/commands/docs.js +306 -0
- package/dist/esm/commands/docs.js.map +6 -0
- package/dist/esm/commands/docs.mjs +353 -0
- package/dist/esm/commands/docs.mjs.map +1 -0
- package/dist/esm/commands/docs.native.js +516 -0
- package/dist/esm/commands/docs.native.js.map +1 -0
- package/dist/esm/commands/env-setup.js +56 -0
- package/dist/esm/commands/env-setup.js.map +6 -0
- package/dist/esm/commands/env-setup.mjs +56 -0
- package/dist/esm/commands/env-setup.mjs.map +1 -0
- package/dist/esm/commands/env-setup.native.js +59 -0
- package/dist/esm/commands/env-setup.native.js.map +1 -0
- package/dist/esm/commands/onboard.js +645 -0
- package/dist/esm/commands/onboard.js.map +6 -0
- package/dist/esm/commands/onboard.mjs +445 -0
- package/dist/esm/commands/onboard.mjs.map +1 -0
- package/dist/esm/commands/onboard.native.js +584 -0
- package/dist/esm/commands/onboard.native.js.map +1 -0
- package/dist/esm/commands/run.js +95 -0
- package/dist/esm/commands/run.js.map +6 -0
- package/dist/esm/commands/run.mjs +114 -0
- package/dist/esm/commands/run.mjs.map +1 -0
- package/dist/esm/commands/run.native.js +133 -0
- package/dist/esm/commands/run.native.js.map +1 -0
- package/dist/esm/commands/script.js +338 -0
- package/dist/esm/commands/script.js.map +6 -0
- package/dist/esm/commands/script.mjs +336 -0
- package/dist/esm/commands/script.mjs.map +1 -0
- package/dist/esm/commands/script.native.js +445 -0
- package/dist/esm/commands/script.native.js.map +1 -0
- package/dist/esm/commands/sync.js +158 -0
- package/dist/esm/commands/sync.js.map +6 -0
- package/dist/esm/commands/sync.mjs +155 -0
- package/dist/esm/commands/sync.mjs.map +1 -0
- package/dist/esm/commands/sync.native.js +173 -0
- package/dist/esm/commands/sync.native.js.map +1 -0
- package/dist/esm/constants/ascii.js +14 -0
- package/dist/esm/constants/ascii.js.map +6 -0
- package/dist/esm/constants/ascii.mjs +12 -0
- package/dist/esm/constants/ascii.mjs.map +1 -0
- package/dist/esm/constants/ascii.native.js +12 -0
- package/dist/esm/constants/ascii.native.js.map +1 -0
- package/dist/esm/index.js +83 -0
- package/dist/esm/index.js.map +6 -0
- package/dist/esm/index.mjs +7 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +7 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/types.js.map +6 -0
- package/dist/esm/types.mjs +2 -0
- package/dist/esm/types.mjs.map +1 -0
- package/dist/esm/types.native.js +2 -0
- package/dist/esm/types.native.js.map +1 -0
- package/dist/esm/utils/env-categories.js +272 -0
- package/dist/esm/utils/env-categories.js.map +6 -0
- package/dist/esm/utils/env-categories.mjs +233 -0
- package/dist/esm/utils/env-categories.mjs.map +1 -0
- package/dist/esm/utils/env-categories.native.js +246 -0
- package/dist/esm/utils/env-categories.native.js.map +1 -0
- package/dist/esm/utils/env-setup.js +173 -0
- package/dist/esm/utils/env-setup.js.map +6 -0
- package/dist/esm/utils/env-setup.mjs +146 -0
- package/dist/esm/utils/env-setup.mjs.map +1 -0
- package/dist/esm/utils/env-setup.native.js +243 -0
- package/dist/esm/utils/env-setup.native.js.map +1 -0
- package/dist/esm/utils/env.js +83 -0
- package/dist/esm/utils/env.js.map +6 -0
- package/dist/esm/utils/env.mjs +90 -0
- package/dist/esm/utils/env.mjs.map +1 -0
- package/dist/esm/utils/env.native.js +99 -0
- package/dist/esm/utils/env.native.js.map +1 -0
- package/dist/esm/utils/files.js +150 -0
- package/dist/esm/utils/files.js.map +6 -0
- package/dist/esm/utils/files.mjs +187 -0
- package/dist/esm/utils/files.mjs.map +1 -0
- package/dist/esm/utils/files.native.js +247 -0
- package/dist/esm/utils/files.native.js.map +1 -0
- package/dist/esm/utils/parallel-runner.js +69 -0
- package/dist/esm/utils/parallel-runner.js.map +6 -0
- package/dist/esm/utils/parallel-runner.mjs +76 -0
- package/dist/esm/utils/parallel-runner.mjs.map +1 -0
- package/dist/esm/utils/parallel-runner.native.js +109 -0
- package/dist/esm/utils/parallel-runner.native.js.map +1 -0
- package/dist/esm/utils/ports.js +65 -0
- package/dist/esm/utils/ports.js.map +6 -0
- package/dist/esm/utils/ports.mjs +74 -0
- package/dist/esm/utils/ports.mjs.map +1 -0
- package/dist/esm/utils/ports.native.js +93 -0
- package/dist/esm/utils/ports.native.js.map +1 -0
- package/dist/esm/utils/prerequisites.js +91 -0
- package/dist/esm/utils/prerequisites.js.map +6 -0
- package/dist/esm/utils/prerequisites.mjs +91 -0
- package/dist/esm/utils/prerequisites.mjs.map +1 -0
- package/dist/esm/utils/prerequisites.native.js +97 -0
- package/dist/esm/utils/prerequisites.native.js.map +1 -0
- package/dist/esm/utils/prompts.js +139 -0
- package/dist/esm/utils/prompts.js.map +6 -0
- package/dist/esm/utils/prompts.mjs +112 -0
- package/dist/esm/utils/prompts.mjs.map +1 -0
- package/dist/esm/utils/prompts.native.js +115 -0
- package/dist/esm/utils/prompts.native.js.map +1 -0
- package/dist/esm/utils/script-listing.js +91 -0
- package/dist/esm/utils/script-listing.js.map +6 -0
- package/dist/esm/utils/script-listing.mjs +76 -0
- package/dist/esm/utils/script-listing.mjs.map +1 -0
- package/dist/esm/utils/script-listing.native.js +151 -0
- package/dist/esm/utils/script-listing.native.js.map +1 -0
- package/dist/esm/utils/sync.js +50 -0
- package/dist/esm/utils/sync.js.map +6 -0
- package/dist/esm/utils/sync.mjs +48 -0
- package/dist/esm/utils/sync.mjs.map +1 -0
- package/dist/esm/utils/sync.native.js +53 -0
- package/dist/esm/utils/sync.native.js.map +1 -0
- package/dist/esm/utils/welcome.js +21 -0
- package/dist/esm/utils/welcome.js.map +6 -0
- package/dist/esm/utils/welcome.mjs +15 -0
- package/dist/esm/utils/welcome.mjs.map +1 -0
- package/dist/esm/utils/welcome.native.js +18 -0
- package/dist/esm/utils/welcome.native.js.map +1 -0
- package/docs/aggregates.md +579 -0
- package/docs/cloudflare-dev-tunnel.md +41 -0
- package/docs/database.md +203 -0
- package/docs/docs.md +8 -0
- package/docs/emitters.md +562 -0
- package/docs/hot-updater.md +223 -0
- package/docs/native-hot-update.md +252 -0
- package/docs/one-components.md +234 -0
- package/docs/one-hooks.md +570 -0
- package/docs/one-routes.md +660 -0
- package/docs/package-json.md +115 -0
- package/docs/react-native-navigation-flow.md +184 -0
- package/docs/scripts.md +147 -0
- package/docs/sync-prompt.md +208 -0
- package/docs/tamagui.md +478 -0
- package/docs/testing-integration.md +564 -0
- package/docs/triggers.md +450 -0
- package/docs/zero.md +719 -0
- package/package.json +76 -0
- package/scripts/seed.ts +209 -0
- package/src/cli.ts +147 -0
- package/src/commands/changed.ts +313 -0
- package/src/commands/docs.ts +582 -0
- package/src/commands/env-setup.ts +69 -0
- package/src/commands/onboard.ts +1391 -0
- package/src/commands/run.ts +173 -0
- package/src/commands/script.ts +587 -0
- package/src/commands/sync.ts +305 -0
- package/src/constants/ascii.ts +17 -0
- package/src/index.ts +63 -0
- package/src/types.ts +59 -0
- package/src/utils/env-categories.ts +245 -0
- package/src/utils/env-setup.ts +338 -0
- package/src/utils/env.ts +127 -0
- package/src/utils/files.ts +302 -0
- package/src/utils/parallel-runner.ts +129 -0
- package/src/utils/ports.ts +77 -0
- package/src/utils/prerequisites.ts +137 -0
- package/src/utils/prompts.ts +197 -0
- package/src/utils/script-listing.ts +214 -0
- package/src/utils/sync.ts +101 -0
- package/src/withOpSqliteStatic.cjs +51 -0
- package/types/cli.d.ts +7 -0
- package/types/cli.d.ts.map +1 -0
- package/types/commands/changed.d.ts +14 -0
- package/types/commands/changed.d.ts.map +1 -0
- package/types/commands/docs.d.ts +5 -0
- package/types/commands/docs.d.ts.map +1 -0
- package/types/commands/env-setup.d.ts +25 -0
- package/types/commands/env-setup.d.ts.map +1 -0
- package/types/commands/onboard.d.ts +16 -0
- package/types/commands/onboard.d.ts.map +1 -0
- package/types/commands/run.d.ts +8 -0
- package/types/commands/run.d.ts.map +1 -0
- package/types/commands/script.d.ts +28 -0
- package/types/commands/script.d.ts.map +1 -0
- package/types/commands/sync.d.ts +5 -0
- package/types/commands/sync.d.ts.map +1 -0
- package/types/constants/ascii.d.ts +6 -0
- package/types/constants/ascii.d.ts.map +1 -0
- package/types/index.d.ts +12 -0
- package/types/index.d.ts.map +1 -0
- package/types/types.d.ts +54 -0
- package/types/types.d.ts.map +1 -0
- package/types/utils/env-categories.d.ts +8 -0
- package/types/utils/env-categories.d.ts.map +1 -0
- package/types/utils/env-setup.d.ts +10 -0
- package/types/utils/env-setup.d.ts.map +1 -0
- package/types/utils/env.d.ts +19 -0
- package/types/utils/env.d.ts.map +1 -0
- package/types/utils/files.d.ts +47 -0
- package/types/utils/files.d.ts.map +1 -0
- package/types/utils/parallel-runner.d.ts +15 -0
- package/types/utils/parallel-runner.d.ts.map +1 -0
- package/types/utils/ports.d.ts +16 -0
- package/types/utils/ports.d.ts.map +1 -0
- package/types/utils/prerequisites.d.ts +11 -0
- package/types/utils/prerequisites.d.ts.map +1 -0
- package/types/utils/prompts.d.ts +30 -0
- package/types/utils/prompts.d.ts.map +1 -0
- package/types/utils/script-listing.d.ts +7 -0
- package/types/utils/script-listing.d.ts.map +1 -0
- package/types/utils/sync.d.ts +16 -0
- package/types/utils/sync.d.ts.map +1 -0
- package/types/utils/welcome.d.ts +6 -0
- package/types/utils/welcome.d.ts.map +1 -0
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Script command - hybrid script runner with filesystem discovery
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
existsSync,
|
|
7
|
+
readdirSync,
|
|
8
|
+
statSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
mkdirSync,
|
|
12
|
+
} from 'node:fs'
|
|
13
|
+
import { homedir } from 'node:os'
|
|
14
|
+
import { join, relative, dirname, basename, extname } from 'node:path'
|
|
15
|
+
import { fileURLToPath } from 'node:url'
|
|
16
|
+
|
|
17
|
+
import { defineCommand } from 'citty'
|
|
18
|
+
import pc from 'picocolors'
|
|
19
|
+
|
|
20
|
+
import { listAllScripts, listCategoryScripts } from '../utils/script-listing'
|
|
21
|
+
import {
|
|
22
|
+
type FileToSync,
|
|
23
|
+
compareFiles,
|
|
24
|
+
getFileSize,
|
|
25
|
+
syncFileWithConfirmation,
|
|
26
|
+
} from '../utils/sync'
|
|
27
|
+
|
|
28
|
+
// cache configuration
|
|
29
|
+
const CACHE_DIR = join(homedir(), '.takeout')
|
|
30
|
+
const CACHE_FILE = join(CACHE_DIR, 'script-cache.json')
|
|
31
|
+
|
|
32
|
+
interface ScriptMetadata {
|
|
33
|
+
description?: string
|
|
34
|
+
args?: string[]
|
|
35
|
+
mtime?: number
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface ScriptCache {
|
|
39
|
+
[path: string]: ScriptMetadata
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// find scripts package root using import.meta.resolve
|
|
43
|
+
function findScriptsPackageRoot(): string | null {
|
|
44
|
+
try {
|
|
45
|
+
const resolved = import.meta.resolve('@take-out/scripts/package.json')
|
|
46
|
+
// use fileURLToPath for proper cross-platform handling
|
|
47
|
+
const packageJsonPath = fileURLToPath(new URL(resolved))
|
|
48
|
+
const packageRoot = join(packageJsonPath, '..')
|
|
49
|
+
const srcPath = join(packageRoot, 'src')
|
|
50
|
+
|
|
51
|
+
if (existsSync(srcPath)) {
|
|
52
|
+
return srcPath
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
// scripts package not found, that's ok for hybrid mode
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// get local scripts directory
|
|
62
|
+
export function getLocalScriptsDir(): string {
|
|
63
|
+
return join(process.cwd(), 'scripts')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// extract metadata from script file
|
|
67
|
+
function extractMetadata(filePath: string): ScriptMetadata {
|
|
68
|
+
try {
|
|
69
|
+
const content = readFileSync(filePath, 'utf-8')
|
|
70
|
+
const lines = content.split('\n').slice(0, 20) // check first 20 lines
|
|
71
|
+
|
|
72
|
+
const metadata: ScriptMetadata = {}
|
|
73
|
+
|
|
74
|
+
for (const line of lines) {
|
|
75
|
+
// look for @description comment
|
|
76
|
+
const descMatch = line.match(/@description\s+(.+)/)
|
|
77
|
+
if (descMatch && descMatch[1]) {
|
|
78
|
+
metadata.description = descMatch[1].trim()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// look for @args comment
|
|
82
|
+
const argsMatch = line.match(/@args\s+(.+)/)
|
|
83
|
+
if (argsMatch && argsMatch[1]) {
|
|
84
|
+
metadata.args = argsMatch[1].split(',').map((a) => a.trim())
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// add file modification time
|
|
89
|
+
const stat = statSync(filePath)
|
|
90
|
+
metadata.mtime = stat.mtimeMs
|
|
91
|
+
|
|
92
|
+
return metadata
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return {}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// load or create cache
|
|
99
|
+
function loadCache(): ScriptCache {
|
|
100
|
+
try {
|
|
101
|
+
if (existsSync(CACHE_FILE)) {
|
|
102
|
+
return JSON.parse(readFileSync(CACHE_FILE, 'utf-8'))
|
|
103
|
+
}
|
|
104
|
+
} catch (err) {
|
|
105
|
+
// ignore cache errors
|
|
106
|
+
}
|
|
107
|
+
return {}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// save cache
|
|
111
|
+
function saveCache(cache: ScriptCache) {
|
|
112
|
+
try {
|
|
113
|
+
if (!existsSync(CACHE_DIR)) {
|
|
114
|
+
mkdirSync(CACHE_DIR, { recursive: true })
|
|
115
|
+
}
|
|
116
|
+
writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2))
|
|
117
|
+
} catch (err) {
|
|
118
|
+
// ignore cache write errors
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// get metadata for a script (with caching)
|
|
123
|
+
export function getScriptMetadata(filePath: string): ScriptMetadata {
|
|
124
|
+
const cache = loadCache()
|
|
125
|
+
const stat = statSync(filePath)
|
|
126
|
+
|
|
127
|
+
// check if cache is valid
|
|
128
|
+
if (cache[filePath] && cache[filePath].mtime === stat.mtimeMs) {
|
|
129
|
+
return cache[filePath]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// extract fresh metadata
|
|
133
|
+
const metadata = extractMetadata(filePath)
|
|
134
|
+
|
|
135
|
+
// update cache
|
|
136
|
+
cache[filePath] = metadata
|
|
137
|
+
saveCache(cache)
|
|
138
|
+
|
|
139
|
+
return metadata
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// discover scripts in a directory
|
|
143
|
+
export function discoverScripts(
|
|
144
|
+
dir: string,
|
|
145
|
+
baseDir: string = dir,
|
|
146
|
+
depth: number = 0,
|
|
147
|
+
maxDepth: number = 1
|
|
148
|
+
): Map<string, string> {
|
|
149
|
+
const scripts = new Map<string, string>()
|
|
150
|
+
|
|
151
|
+
if (!existsSync(dir)) {
|
|
152
|
+
return scripts
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const entries = readdirSync(dir)
|
|
157
|
+
|
|
158
|
+
for (const entry of entries) {
|
|
159
|
+
const fullPath = join(dir, entry)
|
|
160
|
+
const stat = statSync(fullPath)
|
|
161
|
+
|
|
162
|
+
if (stat.isDirectory()) {
|
|
163
|
+
// skip helpers directories and limit depth to maxDepth
|
|
164
|
+
if (entry === 'helpers' || depth >= maxDepth) {
|
|
165
|
+
continue
|
|
166
|
+
}
|
|
167
|
+
// recursively discover in subdirectories
|
|
168
|
+
const subScripts = discoverScripts(fullPath, baseDir, depth + 1, maxDepth)
|
|
169
|
+
for (const [name, path] of subScripts) {
|
|
170
|
+
scripts.set(name, path)
|
|
171
|
+
}
|
|
172
|
+
} else if (entry.endsWith('.ts') || entry.endsWith('.js')) {
|
|
173
|
+
// create script name relative to base, normalize to forward slashes
|
|
174
|
+
const relativePath = relative(baseDir, fullPath).split('\\').join('/')
|
|
175
|
+
const scriptName = relativePath.replace(/\.(ts|js)$/, '')
|
|
176
|
+
scripts.set(scriptName, fullPath)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} catch (err) {
|
|
180
|
+
// ignore directory read errors
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return scripts
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// find a script by name (checks both built-in and local)
|
|
187
|
+
export function findScript(name: string): string | null {
|
|
188
|
+
// normalize name: convert colons to slashes for consistency
|
|
189
|
+
const normalizedName = name.replace(/:/g, '/')
|
|
190
|
+
|
|
191
|
+
// 1. check local scripts first (they override built-ins)
|
|
192
|
+
const localDir = getLocalScriptsDir()
|
|
193
|
+
|
|
194
|
+
// try direct file path with normalized name
|
|
195
|
+
for (const ext of ['.ts', '.js', '']) {
|
|
196
|
+
const localPath = join(localDir, `${normalizedName}${ext}`)
|
|
197
|
+
if (existsSync(localPath)) {
|
|
198
|
+
return localPath
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 2. check built-in scripts
|
|
203
|
+
const builtInDir = findScriptsPackageRoot()
|
|
204
|
+
if (builtInDir) {
|
|
205
|
+
for (const ext of ['.ts', '.js', '']) {
|
|
206
|
+
const builtInPath = join(builtInDir, `${normalizedName}${ext}`)
|
|
207
|
+
if (existsSync(builtInPath)) {
|
|
208
|
+
return builtInPath
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return null
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export {
|
|
217
|
+
formatScriptList,
|
|
218
|
+
listAllScripts,
|
|
219
|
+
listCategoryScripts,
|
|
220
|
+
} from '../utils/script-listing'
|
|
221
|
+
|
|
222
|
+
// run a script
|
|
223
|
+
async function runScript(scriptPath: string, args: string[]): Promise<void> {
|
|
224
|
+
console.info(pc.dim(`Running: ${relative(process.cwd(), scriptPath)}`))
|
|
225
|
+
console.info()
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const { $ } = await import('bun')
|
|
229
|
+
await $`bun ${scriptPath} ${args}`
|
|
230
|
+
} catch (err) {
|
|
231
|
+
console.error(pc.red(`✗ Error running script: ${err}`))
|
|
232
|
+
process.exit(1)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// new command for creating scripts
|
|
237
|
+
const newCommand = defineCommand({
|
|
238
|
+
meta: {
|
|
239
|
+
name: 'new',
|
|
240
|
+
description: 'Create a new script from template',
|
|
241
|
+
},
|
|
242
|
+
args: {
|
|
243
|
+
path: {
|
|
244
|
+
type: 'positional',
|
|
245
|
+
description: 'Path for the new script (e.g., ci/test)',
|
|
246
|
+
required: true,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
async run({ args }) {
|
|
250
|
+
const scriptPath = args.path
|
|
251
|
+
const localDir = getLocalScriptsDir()
|
|
252
|
+
|
|
253
|
+
// determine full path
|
|
254
|
+
const fullPath = join(localDir, `${scriptPath}.ts`)
|
|
255
|
+
const dir = dirname(fullPath)
|
|
256
|
+
|
|
257
|
+
// create directory if needed
|
|
258
|
+
if (!existsSync(dir)) {
|
|
259
|
+
mkdirSync(dir, { recursive: true })
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// check if file exists
|
|
263
|
+
if (existsSync(fullPath)) {
|
|
264
|
+
console.error(
|
|
265
|
+
pc.red(`✗ Script already exists: ${relative(process.cwd(), fullPath)}`)
|
|
266
|
+
)
|
|
267
|
+
process.exit(1)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// create template
|
|
271
|
+
const template = `#!/usr/bin/env bun
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* @description TODO: Add description
|
|
275
|
+
* @args --verbose, --dry-run
|
|
276
|
+
*/
|
|
277
|
+
|
|
278
|
+
import { parseArgs } from 'node:util'
|
|
279
|
+
|
|
280
|
+
const { values } = parseArgs({
|
|
281
|
+
args: process.argv.slice(2),
|
|
282
|
+
options: {
|
|
283
|
+
verbose: {
|
|
284
|
+
type: 'boolean',
|
|
285
|
+
short: 'v',
|
|
286
|
+
},
|
|
287
|
+
'dry-run': {
|
|
288
|
+
type: 'boolean',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
async function main() {
|
|
294
|
+
console.info('Running ${basename(scriptPath)}...')
|
|
295
|
+
|
|
296
|
+
if (values.verbose) {
|
|
297
|
+
console.info('Verbose mode enabled')
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (values['dry-run']) {
|
|
301
|
+
console.info('Dry run mode - no changes will be made')
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// TODO: Implement your script logic here
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
main().catch(console.error)
|
|
308
|
+
`
|
|
309
|
+
|
|
310
|
+
writeFileSync(fullPath, template)
|
|
311
|
+
console.info(pc.green(`✓ Created new script: ${relative(process.cwd(), fullPath)}`))
|
|
312
|
+
console.info()
|
|
313
|
+
console.info(pc.dim(`Edit the script and update the TODO sections`))
|
|
314
|
+
},
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// get all script files recursively
|
|
318
|
+
function getAllScriptFiles(dir: string, baseDir: string = dir): string[] {
|
|
319
|
+
const files: string[] = []
|
|
320
|
+
|
|
321
|
+
if (!existsSync(dir)) {
|
|
322
|
+
return files
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
const entries = readdirSync(dir)
|
|
327
|
+
|
|
328
|
+
for (const entry of entries) {
|
|
329
|
+
const fullPath = join(dir, entry)
|
|
330
|
+
const stat = statSync(fullPath)
|
|
331
|
+
|
|
332
|
+
if (stat.isDirectory()) {
|
|
333
|
+
files.push(...getAllScriptFiles(fullPath, baseDir))
|
|
334
|
+
} else if (
|
|
335
|
+
entry.endsWith('.ts') ||
|
|
336
|
+
entry.endsWith('.js') ||
|
|
337
|
+
entry.endsWith('.cjs')
|
|
338
|
+
) {
|
|
339
|
+
// normalize to forward slashes for consistent naming
|
|
340
|
+
files.push(relative(baseDir, fullPath).split('\\').join('/'))
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
} catch (err) {
|
|
344
|
+
// ignore directory read errors
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return files
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// eject command to copy built-in scripts to local directory
|
|
351
|
+
const ejectCommand = defineCommand({
|
|
352
|
+
meta: {
|
|
353
|
+
name: 'eject',
|
|
354
|
+
description: 'Eject built-in scripts into your project',
|
|
355
|
+
},
|
|
356
|
+
args: {
|
|
357
|
+
yes: {
|
|
358
|
+
type: 'boolean',
|
|
359
|
+
description: 'Skip confirmations and eject all files',
|
|
360
|
+
default: false,
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
async run({ args }) {
|
|
364
|
+
const cwd = process.cwd()
|
|
365
|
+
const targetScriptsDir = join(cwd, 'scripts')
|
|
366
|
+
const sourceScriptsDir = findScriptsPackageRoot()
|
|
367
|
+
|
|
368
|
+
console.info()
|
|
369
|
+
console.info(pc.bold(pc.cyan('⚙️ Eject Scripts')))
|
|
370
|
+
console.info()
|
|
371
|
+
|
|
372
|
+
if (!sourceScriptsDir) {
|
|
373
|
+
console.error(
|
|
374
|
+
pc.red(
|
|
375
|
+
'✗ Built-in scripts package (@take-out/scripts) not found or not installed'
|
|
376
|
+
)
|
|
377
|
+
)
|
|
378
|
+
console.info()
|
|
379
|
+
console.info(pc.dim('Install with: bun add -d @take-out/scripts'))
|
|
380
|
+
process.exit(1)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
console.info(pc.dim(`Source: ${sourceScriptsDir}`))
|
|
384
|
+
console.info(pc.dim(`Target: ${targetScriptsDir}`))
|
|
385
|
+
console.info()
|
|
386
|
+
|
|
387
|
+
// ensure target scripts directory exists
|
|
388
|
+
if (!existsSync(targetScriptsDir)) {
|
|
389
|
+
console.info(pc.yellow('⚠ Target scripts directory does not exist, will create it'))
|
|
390
|
+
mkdirSync(targetScriptsDir, { recursive: true })
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// get all script files from source (including subdirectories)
|
|
394
|
+
const sourceFiles = getAllScriptFiles(sourceScriptsDir)
|
|
395
|
+
|
|
396
|
+
if (sourceFiles.length === 0) {
|
|
397
|
+
console.info(pc.yellow('No script files found in built-in scripts package'))
|
|
398
|
+
return
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// analyze all files
|
|
402
|
+
const filesToSync: FileToSync[] = []
|
|
403
|
+
const stats = {
|
|
404
|
+
new: 0,
|
|
405
|
+
modified: 0,
|
|
406
|
+
identical: 0,
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
for (const file of sourceFiles) {
|
|
410
|
+
const sourcePath = join(sourceScriptsDir, file)
|
|
411
|
+
const targetPath = join(targetScriptsDir, file)
|
|
412
|
+
const status = compareFiles(sourcePath, targetPath)
|
|
413
|
+
|
|
414
|
+
stats[status]++
|
|
415
|
+
|
|
416
|
+
filesToSync.push({
|
|
417
|
+
name: file,
|
|
418
|
+
sourcePath,
|
|
419
|
+
targetPath,
|
|
420
|
+
status,
|
|
421
|
+
sourceSize: getFileSize(sourcePath),
|
|
422
|
+
targetSize: getFileSize(targetPath),
|
|
423
|
+
})
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
console.info(pc.bold('Summary:'))
|
|
427
|
+
console.info(` ${pc.green(`${stats.new} new`)}`)
|
|
428
|
+
console.info(` ${pc.yellow(`${stats.modified} modified`)}`)
|
|
429
|
+
console.info(` ${pc.dim(`${stats.identical} identical`)}`)
|
|
430
|
+
console.info()
|
|
431
|
+
|
|
432
|
+
if (stats.new === 0 && stats.modified === 0) {
|
|
433
|
+
console.info(pc.green('✓ All scripts are already up to date!'))
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// sort files: new first, then modified, then identical
|
|
438
|
+
const sortOrder = { new: 0, modified: 1, identical: 2 }
|
|
439
|
+
filesToSync.sort((a, b) => sortOrder[a.status] - sortOrder[b.status])
|
|
440
|
+
|
|
441
|
+
// sync files
|
|
442
|
+
let syncedCount = 0
|
|
443
|
+
|
|
444
|
+
for (const file of filesToSync) {
|
|
445
|
+
if (args.yes && file.status !== 'identical') {
|
|
446
|
+
// auto-sync without confirmation
|
|
447
|
+
const targetDir = dirname(file.targetPath)
|
|
448
|
+
if (!existsSync(targetDir)) {
|
|
449
|
+
mkdirSync(targetDir, { recursive: true })
|
|
450
|
+
}
|
|
451
|
+
const content = readFileSync(file.sourcePath)
|
|
452
|
+
writeFileSync(file.targetPath, content)
|
|
453
|
+
console.info(pc.green(` ✓ ${file.name}`))
|
|
454
|
+
syncedCount++
|
|
455
|
+
} else {
|
|
456
|
+
const wasSynced = await syncFileWithConfirmation(file)
|
|
457
|
+
if (wasSynced) {
|
|
458
|
+
syncedCount++
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
console.info()
|
|
464
|
+
console.info(pc.bold(pc.green(`✓ Complete: ${syncedCount} file(s) ejected`)))
|
|
465
|
+
console.info()
|
|
466
|
+
},
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
// run subcommand for backwards compatibility
|
|
470
|
+
const runSubCommand = defineCommand({
|
|
471
|
+
meta: {
|
|
472
|
+
name: 'run',
|
|
473
|
+
description: 'Run a script (for backwards compatibility)',
|
|
474
|
+
},
|
|
475
|
+
args: {
|
|
476
|
+
name: {
|
|
477
|
+
type: 'positional',
|
|
478
|
+
description: 'Script name',
|
|
479
|
+
required: true,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
async run({ args, rawArgs }) {
|
|
483
|
+
// Find and run the script
|
|
484
|
+
const scriptPath = findScript(args.name)
|
|
485
|
+
|
|
486
|
+
if (!scriptPath) {
|
|
487
|
+
console.error(pc.red(`✗ Script not found: ${args.name}`))
|
|
488
|
+
console.info()
|
|
489
|
+
console.info(pc.dim(`Run 'tko script' to see available scripts`))
|
|
490
|
+
process.exit(1)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Extract args after the script name
|
|
494
|
+
const scriptArgs = rawArgs.slice(rawArgs.indexOf(args.name) + 1)
|
|
495
|
+
|
|
496
|
+
await runScript(scriptPath, scriptArgs)
|
|
497
|
+
},
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
// main script command (handles both list and run)
|
|
501
|
+
export const scriptCommand = defineCommand({
|
|
502
|
+
meta: {
|
|
503
|
+
name: 'script',
|
|
504
|
+
description: 'Hybrid script runner with filesystem discovery',
|
|
505
|
+
},
|
|
506
|
+
args: {
|
|
507
|
+
name: {
|
|
508
|
+
type: 'positional',
|
|
509
|
+
description: 'Script name or category to run/list',
|
|
510
|
+
required: false,
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
subCommands: {
|
|
514
|
+
new: newCommand,
|
|
515
|
+
run: runSubCommand,
|
|
516
|
+
eject: ejectCommand,
|
|
517
|
+
},
|
|
518
|
+
async run({ args, rawArgs }) {
|
|
519
|
+
// citty doesn't handle args with hyphens well, so use rawArgs directly
|
|
520
|
+
// rawArgs[0] is 'script', rawArgs[1] is the actual script name
|
|
521
|
+
const scriptName = args.name || rawArgs[1]
|
|
522
|
+
|
|
523
|
+
// if no name provided, list all available scripts
|
|
524
|
+
if (!scriptName) {
|
|
525
|
+
listAllScripts(false) // don't show built-in commands in script listing
|
|
526
|
+
return
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// check if this is a category listing (e.g., "takeout script ci")
|
|
530
|
+
if (listCategoryScripts(scriptName)) {
|
|
531
|
+
return
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// find and run the script
|
|
535
|
+
const scriptPath = findScript(scriptName)
|
|
536
|
+
|
|
537
|
+
if (!scriptPath) {
|
|
538
|
+
console.error(pc.red(`✗ Script not found: ${scriptName}`))
|
|
539
|
+
console.info()
|
|
540
|
+
console.info(pc.dim(`Run 'tko script' to see available scripts`))
|
|
541
|
+
process.exit(1)
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// extract args after the script name
|
|
545
|
+
const scriptArgs = rawArgs.slice(rawArgs.indexOf(scriptName) + 1)
|
|
546
|
+
|
|
547
|
+
await runScript(scriptPath, scriptArgs)
|
|
548
|
+
},
|
|
549
|
+
})
|
|
550
|
+
|
|
551
|
+
// shorthand command that skips "script" subcommand
|
|
552
|
+
export function createShorthandCommand(name: string) {
|
|
553
|
+
return defineCommand({
|
|
554
|
+
meta: {
|
|
555
|
+
name,
|
|
556
|
+
description: 'Run script directly',
|
|
557
|
+
},
|
|
558
|
+
args: {
|
|
559
|
+
args: {
|
|
560
|
+
type: 'positional',
|
|
561
|
+
description: 'Script and arguments',
|
|
562
|
+
required: false,
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
async run({ rawArgs }) {
|
|
566
|
+
// if no args provided, list scripts in this category
|
|
567
|
+
const scriptName = rawArgs.length > 0 ? `${name}/${rawArgs[0]}` : name
|
|
568
|
+
const scriptArgs =
|
|
569
|
+
rawArgs.length > 0
|
|
570
|
+
? ['script', scriptName, ...rawArgs.slice(1)]
|
|
571
|
+
: ['script', name]
|
|
572
|
+
|
|
573
|
+
// delegate to script command
|
|
574
|
+
const { run } = scriptCommand
|
|
575
|
+
if (run) {
|
|
576
|
+
await run({
|
|
577
|
+
args: {
|
|
578
|
+
name: scriptName,
|
|
579
|
+
_: rawArgs.slice(1),
|
|
580
|
+
} as any,
|
|
581
|
+
rawArgs: scriptArgs,
|
|
582
|
+
cmd: scriptCommand,
|
|
583
|
+
} as any)
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
})
|
|
587
|
+
}
|