Skip to content

Commit 9856e50

Browse files
committed
chore: wip
1 parent 2490f0f commit 9856e50

File tree

13 files changed

+798
-67
lines changed

13 files changed

+798
-67
lines changed

bun.lock

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"dependencies": {
5151
"bunfig": "^0.15.0",
5252
"cac": "^6.7.14",
53-
"ts-pkgx": "^0.4.72",
53+
"ts-pkgx": "link:ts-pkgx",
5454
},
5555
"devDependencies": {
5656
"bun-plugin-dtsx": "0.9.5",
@@ -1154,7 +1154,7 @@
11541154

11551155
"fs.realpath": ["[email protected]", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
11561156

1157-
"fsevents": ["[email protected].2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
1157+
"fsevents": ["[email protected].3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
11581158

11591159
"function-bind": ["[email protected]", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
11601160

@@ -1820,7 +1820,7 @@
18201820

18211821
"ts-declaration-location": ["[email protected]", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="],
18221822

1823-
"ts-pkgx": ["ts-pkgx@0.4.72", "", { "optionalDependencies": { "chromium-bidi": "^7.2.0", "electron": "^37.4.0", "js-yaml": "^4.1.0", "playwright": "^1.55.0" }, "bin": { "ts-pkgx": "dist/bin/cli.js" } }, "sha512-q/2BrHSHBOYlUaMkNYXg5x0M5oGact+FgIzgeqI0byPUlWlL2kAXPR7CtUfoWshfa4w4QrRh8fvKY1NjoGMmNg=="],
1823+
"ts-pkgx": ["ts-pkgx@link:ts-pkgx", { "bin": { "ts-pkgx": "./dist/bin/cli.js" } }],
18241824

18251825
"tslib": ["[email protected]", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
18261826

@@ -2088,8 +2088,6 @@
20882088

20892089
"buddy-bot/ts-pkgx": ["[email protected]", "", { "dependencies": { "chromium-bidi": "^7.2.0", "electron": "^37.4.0", "js-yaml": "^4.1.0", "playwright": "^1.55.0" }, "bin": { "ts-pkgx": "dist/bin/cli.js" } }, "sha512-YDuXweSXHXk3Me1Q/wI0mTpl4e0GQpiZfqAckPZ9d/PwLbFCQSjinSmTj6n8pnSj0XXs5/kw9z8aLZfSZtBzmw=="],
20902090

2091-
"chokidar/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2092-
20932091
"clean-regexp/escape-string-regexp": ["[email protected]", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
20942092

20952093
"clone-response/mimic-response": ["[email protected]", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
@@ -2138,12 +2136,12 @@
21382136

21392137
"parse-entities/@types/unist": ["@types/[email protected]", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
21402138

2139+
"playwright/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
2140+
21412141
"readdirp/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
21422142

21432143
"regjsparser/jsesc": ["[email protected]", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="],
21442144

2145-
"rollup/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2146-
21472145
"serialize-error/type-fest": ["[email protected]", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
21482146

21492147
"shiki/@shikijs/core": ["@shikijs/[email protected]", "", { "dependencies": { "@shikijs/types": "3.8.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-uTSXzUBQ/IgFcUa6gmGShCHr4tMdR3pxUiiWKDm8pd42UKJdYhkAYsAmHX5mTwybQ5VyGDgTjW4qKSsRvGSang=="],
@@ -2160,8 +2158,6 @@
21602158

21612159
"validate-npm-package-license/spdx-expression-parse": ["[email protected]", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="],
21622160

2163-
"vite/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2164-
21652161
"vitepress/shiki": ["[email protected]", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="],
21662162

21672163
"workbox-build/pretty-bytes": ["[email protected]", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="],
@@ -2184,12 +2180,6 @@
21842180

21852181
"@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/[email protected]", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="],
21862182

2187-
"@rollup/plugin-babel/rollup/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2188-
2189-
"@rollup/plugin-replace/rollup/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2190-
2191-
"@rollup/pluginutils/rollup/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2192-
21932183
"@shikijs/core/@shikijs/engine-javascript/oniguruma-to-es": ["[email protected]", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="],
21942184

21952185
"electron/@types/node/undici-types": ["[email protected]", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
@@ -2218,8 +2208,6 @@
22182208

22192209
"vitepress/shiki/@shikijs/themes": ["@shikijs/[email protected]", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw=="],
22202210

2221-
"workbox-build/rollup/fsevents": ["[email protected]", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
2222-
22232211
"vitepress/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["[email protected]", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="],
22242212
}
22252213
}

launchpad.config.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
1-
import type { LaunchpadConfig } from './packages/launchpad/src'
1+
import type { LaunchpadConfig } from '@stacksjs/launchpad'
22

3-
const config: Partial<LaunchpadConfig> = {
4-
verbose: false,
5-
showShellMessages: true,
3+
export const config: LaunchpadConfig = {
4+
dependencies: {
5+
'bun': '^1.2.199', // Bun runtime (alias)
6+
// 'bun.sh': '^1.2.19', // Bun runtime (domain)
7+
'redis': '^8.0.0', // Redis server (alias)
8+
'postgresql.org': '^17.0.0', // PostgreSQL database (domain)
9+
},
10+
11+
// Or as an array (uses latest versions)
12+
// dependencies: ['bun.com', 'redisio', 'postgresqlorg'],
13+
14+
// Or as a string (space-separated, uses latest versions)
15+
// dependencies: 'bun.com redisio postgresqlorg',
16+
17+
// Install globally (optional)
18+
global: false,
19+
20+
// Enable services to auto-start Redis and PostgreSQL
21+
services: {
22+
enabled: true,
23+
autoStart: true,
24+
database: {
25+
username: 'postgres',
26+
password: 'password',
27+
authMethod: 'trust',
28+
},
29+
},
30+
31+
verbose: true,
632
}
733

834
export default config

packages/launchpad/bin/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ cli
6161
.option('--verbose', 'Enable verbose output')
6262
.option('--path <path>', 'Custom installation path')
6363
.option('-g, --global', 'Install packages globally (or scan for all global dependencies if no packages specified)')
64+
.option('--global-deps', 'Scan for and install all global dependencies from dependency files')
6465
.option('--deps-only', 'Install only the dependencies of packages, not the packages themselves')
6566
.option('--dry-run', 'Show packages that would be installed without installing them')
6667
.option('--quiet', 'Suppress non-error output')
@@ -71,12 +72,14 @@ cli
7172
.example('launchpad install')
7273
.example('launchpad install ./my-project')
7374
.example('launchpad install -g')
75+
.example('launchpad install --global-deps')
7476
.example('launchpad install starship -g')
7577
.example('launchpad add node python')
7678
.action(async (packages: string[], options: {
7779
verbose?: boolean
7880
path?: string
7981
global?: boolean
82+
globalDeps?: boolean
8083
depsOnly?: boolean
8184
dryRun?: boolean
8285
quiet?: boolean
@@ -92,6 +95,8 @@ cli
9295
argv.push('--path', options.path)
9396
if (options.global)
9497
argv.push('--global')
98+
if (options.globalDeps)
99+
argv.push('--global-deps')
95100
if (options.depsOnly)
96101
argv.push('--deps-only')
97102
if (options.dryRun)

packages/launchpad/launchpad.config.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,42 @@ export const defaultConfig: LaunchpadConfig = {
6565
authMethod: 'trust',
6666
},
6767
},
68+
69+
// Package dependencies (similar to deps.yaml functionality)
70+
// Uncomment to declare dependencies directly in the config file
71+
// This eliminates the need for a separate deps.yaml file
72+
//
73+
// ✨ FULLY TYPED with ts-pkgx package names and versions!
74+
//
75+
// Option 1: Simple object format (works but limited type safety)
76+
// dependencies: {
77+
// 'bun.com': '^1.2.19',
78+
// 'redisio': '^8.0.0',
79+
// 'postgresqlorg': '^17.0.0',
80+
// },
81+
//
82+
// Option 2: Fully typed with helper function (RECOMMENDED)
83+
// import { defineDependencies, dep } from '@stacksjs/launchpad'
84+
// dependencies: defineDependencies({
85+
// 'bun.com': dep('^1.2.19'), // Full IntelliSense + precise error highlighting!
86+
// 'nodejsorg': dep('^22.0.0'), // Node.js (note: 'nodejsorg' not 'nodejs.org')
87+
// 'pythonorg': dep('^3.12.0'), // Python
88+
// 'redisio': {
89+
// version: '^8.0.0', // Object format also works
90+
// global: true, // Install this package globally
91+
// },
92+
// 'postgresqlorg': dep('^17.0.0'), // PostgreSQL
93+
// }),
94+
//
95+
// Option 3: Array format (uses latest versions) - fully typed!
96+
// import { definePackageList } from '@stacksjs/launchpad'
97+
// dependencies: definePackageList(['bun.com', 'nodejsorg', 'pythonorg']),
98+
//
99+
// Example 3: String format (space-separated, uses latest versions)
100+
// dependencies: 'bun.com nodejsorg pythonorg',
101+
//
102+
// Global flag (applies to all dependencies unless overridden individually)
103+
// global: false,
68104
}
69105

70106
/**

packages/launchpad/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"dependencies": {
6767
"bunfig": "^0.15.0",
6868
"cac": "^6.7.14",
69-
"ts-pkgx": "^0.4.72"
69+
"ts-pkgx": "link:ts-pkgx"
7070
},
7171
"devDependencies": {
7272
"bun-plugin-dtsx": "0.9.5"

packages/launchpad/src/commands/db/create.ts

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,110 @@ import fs from 'node:fs'
33
import path from 'node:path'
44
import process from 'node:process'
55

6+
/**
7+
* Parse environment variables from .env file
8+
*/
9+
function parseEnvFile(filePath: string): Record<string, string> {
10+
const envVars: Record<string, string> = {}
11+
12+
if (!fs.existsSync(filePath)) {
13+
return envVars
14+
}
15+
16+
const content = fs.readFileSync(filePath, 'utf-8')
17+
const lines = content.split('\n')
18+
19+
for (const line of lines) {
20+
const trimmed = line.trim()
21+
if (trimmed && !trimmed.startsWith('#')) {
22+
const [key, ...valueParts] = trimmed.split('=')
23+
if (key && valueParts.length > 0) {
24+
const value = valueParts.join('=').replace(/^["']|["']$/g, '') // Remove quotes
25+
envVars[key] = value
26+
}
27+
}
28+
}
29+
30+
return envVars
31+
}
32+
33+
/**
34+
* Read database configuration from deps.yaml if available
35+
*/
36+
function readDepsYamlConfig(): { type?: string, name?: string, username?: string, password?: string } {
37+
try {
38+
const depsPath = path.join(process.cwd(), 'deps.yaml')
39+
if (fs.existsSync(depsPath)) {
40+
const content = fs.readFileSync(depsPath, 'utf-8')
41+
const lines = content.split('\n')
42+
let inDatabase = false
43+
const config: { type?: string, name?: string, username?: string, password?: string } = {}
44+
45+
for (const line of lines) {
46+
const trimmed = line.trim()
47+
if (trimmed === 'database:') {
48+
inDatabase = true
49+
continue
50+
}
51+
if (inDatabase && trimmed.startsWith(' ')) {
52+
const [key, ...valueParts] = trimmed.replace(/^ /, '').split(':')
53+
if (key && valueParts.length > 0) {
54+
const value = valueParts.join(':').trim()
55+
if (key === 'type') config.type = value
56+
if (key === 'name') config.name = value
57+
if (key === 'username') config.username = value
58+
if (key === 'password') config.password = value
59+
}
60+
} else if (inDatabase && !trimmed.startsWith(' ')) {
61+
break // End of database section
62+
}
63+
}
64+
return config
65+
}
66+
} catch (error) {
67+
// Ignore errors reading deps.yaml
68+
}
69+
return {}
70+
}
71+
672
const command: Command = {
773
name: 'db:create',
874
description: 'Create a database for the current project',
975
async run({ options }) {
1076
const { createProjectDatabase, generateLaravelConfig } = await import('../../services/database')
11-
const typeRaw = options?.type as string | undefined
77+
78+
// Read environment variables from .env file
79+
const envVars = parseEnvFile('.env')
80+
81+
// Read configuration from deps.yaml
82+
const depsConfig = readDepsYamlConfig()
83+
84+
// Priority: command line options > .env file > deps.yaml > defaults
85+
const typeRaw = options?.type as string | undefined || envVars.DB_CONNECTION || depsConfig.type
1286
const type = (typeRaw && ['postgres', 'mysql', 'sqlite', 'auto'].includes(typeRaw)) ? typeRaw as 'postgres' | 'mysql' | 'sqlite' | 'auto' : undefined
13-
const port = typeof options?.port === 'string' ? Number.parseInt(options.port, 10) : (typeof options?.port === 'number' ? options.port : undefined)
14-
const name = typeof options?.name === 'string' ? options.name : undefined
15-
const host = typeof options?.host === 'string' ? options.host : undefined
16-
const user = typeof options?.user === 'string' ? options.user : undefined
17-
const password = typeof options?.password === 'string' ? options.password : undefined
87+
88+
const portRaw = options?.port || envVars.DB_PORT
89+
const port = portRaw ? (typeof portRaw === 'string' ? Number.parseInt(portRaw, 10) : portRaw) : undefined
90+
91+
const name = options?.name as string | undefined || envVars.DB_NAME || envVars.DB_DATABASE || depsConfig.name
92+
const host = options?.host as string | undefined || envVars.DB_HOST || '127.0.0.1'
93+
const user = options?.user as string | undefined || envVars.DB_USERNAME || depsConfig.username || 'root'
94+
const password = options?.password as string | undefined || envVars.DB_PASSWORD || depsConfig.password
1895

1996
const dbName = name || path.basename(process.cwd()).replace(/\W/g, '_')
2097

98+
// Show configuration source information
99+
const configSources: string[] = []
100+
if (envVars.DB_CONNECTION || envVars.DB_NAME || envVars.DB_HOST || envVars.DB_USERNAME || envVars.DB_PASSWORD) {
101+
configSources.push('.env file')
102+
}
103+
if (depsConfig.type || depsConfig.name || depsConfig.username || depsConfig.password) {
104+
configSources.push('deps.yaml')
105+
}
106+
if (configSources.length > 0) {
107+
console.warn(`📋 Using database configuration from: ${configSources.join(', ')}`)
108+
}
109+
21110
const dbOptions = {
22111
host,
23112
port,

packages/launchpad/src/commands/install.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ function parseArgs(argv: string[]): { pkgs: string[], opts: Record<string, strin
1717
opts.global = true
1818
continue
1919
}
20+
if (a === '--global-deps') {
21+
opts['global-deps'] = true
22+
continue
23+
}
2024
if (a === '-v') {
2125
opts.verbose = true
2226
continue
@@ -483,6 +487,12 @@ const command: Command = {
483487
// Dry run only prints plan if not combined with special modes handled below
484488
const dryRun = Boolean(opts['dry-run'])
485489

490+
// Handle global dependencies installation
491+
if (opts['global-deps']) {
492+
await installGlobalDependencies({ dryRun, quiet: Boolean(opts.quiet), verbose: Boolean(opts.verbose) })
493+
return 0
494+
}
495+
486496
// Handle global installation
487497
if (opts.global) {
488498
const list = pkgs

0 commit comments

Comments
 (0)