@stacksjs/buddy 0.70.258 → 0.70.260
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/cli.d.ts +11 -1
- package/dist/cli.js +5 -164
- package/dist/commands/about.js +1 -35
- package/dist/commands/add.js +1 -25
- package/dist/commands/ai-context.js +4 -27
- package/dist/commands/auth.js +1 -68
- package/dist/commands/build.js +1 -221
- package/dist/commands/cd.js +8 -39
- package/dist/commands/changelog.js +1 -32
- package/dist/commands/clean.js +1 -44
- package/dist/commands/cloud.js +2 -519
- package/dist/commands/commit.js +1 -16
- package/dist/commands/completion.js +6 -42
- package/dist/commands/config-migrate.js +6 -94
- package/dist/commands/configure.js +2 -45
- package/dist/commands/create.js +1 -162
- package/dist/commands/deploy.js +13 -1676
- package/dist/commands/desktop-apple.js +12 -399
- package/dist/commands/dev.js +6 -1083
- package/dist/commands/dns.js +3 -103
- package/dist/commands/docs/buddy-commands.js +10 -132
- package/dist/commands/docs/buddy-commands.test.js +1 -38
- package/dist/commands/docs/framework-repo.js +1 -14
- package/dist/commands/docs/framework-repo.test.js +1 -68
- package/dist/commands/docs/generated-artifacts.js +3 -70
- package/dist/commands/docs/generated-artifacts.test.js +1 -19
- package/dist/commands/docs/links.js +2 -85
- package/dist/commands/docs/links.test.js +4 -66
- package/dist/commands/docs.js +1 -24
- package/dist/commands/doctor.js +2 -478
- package/dist/commands/domains.js +2 -152
- package/dist/commands/email.js +31 -503
- package/dist/commands/env.js +1 -312
- package/dist/commands/extension.js +1 -239
- package/dist/commands/features.js +9 -345
- package/dist/commands/fresh.js +1 -46
- package/dist/commands/generate.js +2 -152
- package/dist/commands/http.js +1 -33
- package/dist/commands/index.js +1 -57
- package/dist/commands/install.js +1 -22
- package/dist/commands/key.js +1 -23
- package/dist/commands/link.js +2 -147
- package/dist/commands/lint.js +2 -84
- package/dist/commands/list.js +1 -140
- package/dist/commands/mail.js +15 -1477
- package/dist/commands/maintenance.js +1 -141
- package/dist/commands/make.js +1 -392
- package/dist/commands/migrate-project.js +1 -49
- package/dist/commands/migrate.js +27 -625
- package/dist/commands/outdated.js +1 -19
- package/dist/commands/package.js +1 -17
- package/dist/commands/phone.js +17 -181
- package/dist/commands/ports.js +2 -118
- package/dist/commands/prepublish.js +1 -17
- package/dist/commands/projects.js +1 -29
- package/dist/commands/protocol/craft-evidence.js +4 -98
- package/dist/commands/protocol/craft-evidence.test.js +1 -20
- package/dist/commands/protocol/desktop-lifecycle-report.js +3 -57
- package/dist/commands/protocol/desktop-lifecycle-report.test.js +1 -32
- package/dist/commands/protocol/desktop-support.js +2 -32
- package/dist/commands/protocol/desktop-workflow.test.js +3 -35
- package/dist/commands/protocol/driver-registry.js +2 -71
- package/dist/commands/protocol/pantry-evidence.js +4 -144
- package/dist/commands/protocol/pantry-evidence.test.js +1 -29
- package/dist/commands/protocol/release-manifest.js +3 -102
- package/dist/commands/protocol/release-manifest.test.js +2 -34
- package/dist/commands/protocol/run-conformance.js +4 -346
- package/dist/commands/protocol/run-conformance.test.js +1 -52
- package/dist/commands/protocol/run-driver-contracts.js +4 -83
- package/dist/commands/protocol/run-driver-contracts.test.js +1 -18
- package/dist/commands/protocol/source-manifest.js +3 -113
- package/dist/commands/protocol/sync-suite.js +3 -136
- package/dist/commands/protocol/sync-suite.test.js +1 -44
- package/dist/commands/protocol.js +1 -60
- package/dist/commands/publish.js +8 -500
- package/dist/commands/queue.js +1 -248
- package/dist/commands/release.js +1 -42
- package/dist/commands/route.js +1 -21
- package/dist/commands/run-tool.js +1 -9
- package/dist/commands/saas.js +1 -25
- package/dist/commands/schedule.js +1 -61
- package/dist/commands/search.js +1 -84
- package/dist/commands/seed.js +1 -47
- package/dist/commands/serve.js +1 -55
- package/dist/commands/setup-ai.js +2 -121
- package/dist/commands/setup.js +2 -305
- package/dist/commands/share.js +1 -214
- package/dist/commands/sms.js +32 -319
- package/dist/commands/stacks.js +1 -72
- package/dist/commands/telemetry.js +1 -74
- package/dist/commands/test.js +1 -130
- package/dist/commands/tinker.js +1 -37
- package/dist/commands/types.js +1 -18
- package/dist/commands/upgrade.js +1 -98
- package/dist/commands/user.js +3 -84
- package/dist/commands/version.js +1 -14
- package/dist/config.js +1 -231
- package/dist/custom-cli.js +1 -23
- package/dist/database-preflight.js +1 -88
- package/dist/global-options.js +1 -4
- package/dist/index.js +1 -1
- package/dist/lazy-commands.js +1 -241
- package/dist/migrators/index.js +2 -62
- package/dist/migrators/laravel/index.js +1 -148
- package/dist/migrators/laravel/migrations.js +4 -231
- package/dist/migrators/laravel/models.js +8 -111
- package/dist/migrators/rails/index.js +1 -11
- package/dist/production-server.js +1 -257
- package/dist/project-setup.js +1 -36
- package/dist/serve-entry.js +1 -5
- package/dist/version-info.js +1 -5
- package/package.json +53 -46
|
@@ -1,33 +1,4 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import { log, onUnknownSubcommand } from "@stacksjs/cli";
|
|
3
|
-
export function completion(buddy) {
|
|
4
|
-
const descriptions = {
|
|
5
|
-
completion: "Generate shell completion scripts",
|
|
6
|
-
shell: "Shell type (bash, zsh, fish)"
|
|
7
|
-
};
|
|
8
|
-
buddy.command("completion [shell]", descriptions.completion).option("-s, --shell [shell]", descriptions.shell).example("buddy completion bash").example("buddy completion zsh").example("buddy completion fish").example("buddy completion bash > /usr/local/etc/bash_completion.d/buddy").action(async (shell, options) => {
|
|
9
|
-
log.debug("Running `buddy completion` ...", options);
|
|
10
|
-
const targetShell = shell || options.shell || "bash", commandNames = (buddy.commands || []).map((cmd) => cmd.name).filter((name) => Boolean(name));
|
|
11
|
-
switch (targetShell) {
|
|
12
|
-
case "bash":
|
|
13
|
-
console.log(generateBashCompletion(commandNames));
|
|
14
|
-
break;
|
|
15
|
-
case "zsh":
|
|
16
|
-
console.log(generateZshCompletion(commandNames));
|
|
17
|
-
break;
|
|
18
|
-
case "fish":
|
|
19
|
-
console.log(generateFishCompletion(commandNames));
|
|
20
|
-
break;
|
|
21
|
-
default:
|
|
22
|
-
console.error(`Unknown shell: ${targetShell}`);
|
|
23
|
-
console.error("Supported shells: bash, zsh, fish");
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
onUnknownSubcommand(buddy, "completion");
|
|
28
|
-
}
|
|
29
|
-
function generateBashCompletion(commands) {
|
|
30
|
-
return `# buddy completion for bash
|
|
1
|
+
import process from"node:process";import{log,onUnknownSubcommand}from"@stacksjs/cli";export function completion(buddy){const descriptions={completion:"Generate shell completion scripts",shell:"Shell type (bash, zsh, fish)"};buddy.command("completion [shell]",descriptions.completion).option("-s, --shell [shell]",descriptions.shell).example("buddy completion bash").example("buddy completion zsh").example("buddy completion fish").example("buddy completion bash > /usr/local/etc/bash_completion.d/buddy").action(async(shell,options)=>{log.debug("Running `buddy completion` ...",options);const targetShell=shell||options.shell||"bash",commandNames=(buddy.commands||[]).map((cmd)=>cmd.name).filter((name)=>Boolean(name));switch(targetShell){case"bash":console.log(generateBashCompletion(commandNames));break;case"zsh":console.log(generateZshCompletion(commandNames));break;case"fish":console.log(generateFishCompletion(commandNames));break;default:console.error(`Unknown shell: ${targetShell}`);console.error("Supported shells: bash, zsh, fish");process.exit(1)}});onUnknownSubcommand(buddy,"completion")}function generateBashCompletion(commands){return`# buddy completion for bash
|
|
31
2
|
|
|
32
3
|
_buddy_completion() {
|
|
33
4
|
local cur prev commands
|
|
@@ -60,17 +31,14 @@ complete -F _buddy_completion buddy
|
|
|
60
31
|
# - macOS: /usr/local/etc/bash_completion.d/buddy
|
|
61
32
|
#
|
|
62
33
|
# Then reload your shell or run: source ~/.bashrc
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
function generateZshCompletion(commands) {
|
|
66
|
-
return `#compdef buddy
|
|
34
|
+
`}function generateZshCompletion(commands){return`#compdef buddy
|
|
67
35
|
|
|
68
36
|
# buddy completion for zsh
|
|
69
37
|
|
|
70
38
|
_buddy() {
|
|
71
39
|
local -a commands
|
|
72
40
|
commands=(
|
|
73
|
-
${commands.map((cmd)
|
|
41
|
+
${commands.map((cmd)=>` '${cmd}:${cmd} command'`).join(`
|
|
74
42
|
`)}
|
|
75
43
|
)
|
|
76
44
|
|
|
@@ -111,16 +79,13 @@ _buddy "$@"
|
|
|
111
79
|
# Then add to your ~/.zshrc:
|
|
112
80
|
# fpath=(~/.zsh/completions $fpath)
|
|
113
81
|
# autoload -Uz compinit && compinit
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
function generateFishCompletion(commands) {
|
|
117
|
-
return `# buddy completion for fish
|
|
82
|
+
`}function generateFishCompletion(commands){return`# buddy completion for fish
|
|
118
83
|
|
|
119
84
|
# Remove old completions
|
|
120
85
|
complete -c buddy -e
|
|
121
86
|
|
|
122
87
|
# Command completions
|
|
123
|
-
${commands.map((cmd)
|
|
88
|
+
${commands.map((cmd)=>`complete -c buddy -n "__fish_use_subcommand" -a "${cmd}" -d "${cmd} command"`).join(`
|
|
124
89
|
`)}
|
|
125
90
|
|
|
126
91
|
# Global flag completions
|
|
@@ -139,5 +104,4 @@ complete -c buddy -s f -l force -d "Skip confirmation prompts"
|
|
|
139
104
|
# ~/.config/fish/completions/buddy.fish
|
|
140
105
|
#
|
|
141
106
|
# Fish will automatically load it on startup
|
|
142
|
-
|
|
143
|
-
}
|
|
107
|
+
`}
|
|
@@ -1,94 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
{
|
|
7
|
-
id: "0.65-cache-driver-rename",
|
|
8
|
-
description: "Rename `cache.driver` to `cache.default` (introduced in 0.65).",
|
|
9
|
-
files: ["cache.ts"],
|
|
10
|
-
shouldApply: (c) => /\bdriver\s*:/.test(c) && !c.includes("default:"),
|
|
11
|
-
apply: (c) => c.replace(/(\bcache\b[\s\S]*?)\bdriver(\s*:)/m, "$1default$2")
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
id: "0.68-search-engine-name",
|
|
15
|
-
description: "Rename `searchEngine.driver` to `searchEngine.default` (matches other configs).",
|
|
16
|
-
files: ["search-engine.ts"],
|
|
17
|
-
shouldApply: (c) => /\bdriver\s*:/.test(c),
|
|
18
|
-
apply: (c) => c.replace(/\bdriver(\s*:)/g, "default$1")
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
id: "0.70-ports-string-to-number",
|
|
22
|
-
description: 'Convert string port values like `"3000"` to numbers (TypeScript types now require number).',
|
|
23
|
-
files: ["ports.ts"],
|
|
24
|
-
shouldApply: (c) => /:\s*['"]\d+['"]/.test(c),
|
|
25
|
-
apply: (c) => c.replace(/:\s*['"](\d+)['"]/g, ": $1")
|
|
26
|
-
}
|
|
27
|
-
];
|
|
28
|
-
export async function runConfigMigrations(opts) {
|
|
29
|
-
const changed = [], skipped = [], codemods = opts.only ? CODEMODS.filter((m) => m.id === opts.only) : CODEMODS;
|
|
30
|
-
if (codemods.length === 0) {
|
|
31
|
-
log.warn(`No matching codemods. Available: ${CODEMODS.map((m) => m.id).join(", ")}`);
|
|
32
|
-
return { changed, skipped };
|
|
33
|
-
}
|
|
34
|
-
for (const cm of codemods) {
|
|
35
|
-
log.info(`Codemod ${italic(cm.id)} \u2014 ${cm.description}`);
|
|
36
|
-
for (const rel of cm.files) {
|
|
37
|
-
const full = projectPath(`config/${rel}`);
|
|
38
|
-
if (!existsSync(full)) {
|
|
39
|
-
skipped.push(`${full} (missing)`);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const before = readFileSync(full, "utf-8");
|
|
43
|
-
if (!cm.shouldApply(before)) {
|
|
44
|
-
skipped.push(`${full} (no changes)`);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
const after = cm.apply(before);
|
|
48
|
-
if (after === before) {
|
|
49
|
-
skipped.push(`${full} (no changes)`);
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (opts.dryRun) {
|
|
53
|
-
log.info(`[dry-run] would update ${full}`);
|
|
54
|
-
printDiff(before, after);
|
|
55
|
-
} else {
|
|
56
|
-
writeFileSync(full, after);
|
|
57
|
-
log.success(`updated ${full}`);
|
|
58
|
-
}
|
|
59
|
-
changed.push(full);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return { changed, skipped };
|
|
63
|
-
}
|
|
64
|
-
function printDiff(before, after) {
|
|
65
|
-
const beforeLines = before.split(`
|
|
66
|
-
`), afterLines = after.split(`
|
|
67
|
-
`), max = Math.max(beforeLines.length, afterLines.length);
|
|
68
|
-
for (let i = 0;i < max; i++) {
|
|
69
|
-
const b = beforeLines[i], a = afterLines[i];
|
|
70
|
-
if (b === a)
|
|
71
|
-
continue;
|
|
72
|
-
if (b !== void 0)
|
|
73
|
-
process.stdout.write(` - ${b}
|
|
74
|
-
`);
|
|
75
|
-
if (a !== void 0)
|
|
76
|
-
process.stdout.write(` + ${a}
|
|
77
|
-
`);
|
|
78
|
-
}
|
|
79
|
-
process.stdout.write(`
|
|
80
|
-
`);
|
|
81
|
-
}
|
|
82
|
-
export function configMigrate(buddy) {
|
|
83
|
-
buddy.command("config:migrate", "Apply config-shape codemods for the latest Stacks version").option("--dry-run", "Preview changes without writing", { default: !1 }).option("--only [id]", "Run a single codemod by id", { default: "" }).action(async (options) => {
|
|
84
|
-
log.info("Running `buddy config:migrate` ...");
|
|
85
|
-
const { changed, skipped } = await runConfigMigrations({
|
|
86
|
-
dryRun: Boolean(options.dryRun),
|
|
87
|
-
only: options.only?.length ? options.only : void 0
|
|
88
|
-
});
|
|
89
|
-
log.info(`Changed: ${changed.length}, Skipped: ${skipped.length}`);
|
|
90
|
-
if (skipped.length > 0)
|
|
91
|
-
for (const s of skipped)
|
|
92
|
-
log.debug(` skipped: ${s}`);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
1
|
+
import{existsSync,readFileSync,writeFileSync}from"node:fs";import process from"node:process";import{italic,log}from"@stacksjs/cli";import{projectPath}from"@stacksjs/path";const CODEMODS=[{id:"0.65-cache-driver-rename",description:"Rename `cache.driver` to `cache.default` (introduced in 0.65).",files:["cache.ts"],shouldApply:(c)=>/\bdriver\s*:/.test(c)&&!c.includes("default:"),apply:(c)=>c.replace(/(\bcache\b[\s\S]*?)\bdriver(\s*:)/m,"$1default$2")},{id:"0.68-search-engine-name",description:"Rename `searchEngine.driver` to `searchEngine.default` (matches other configs).",files:["search-engine.ts"],shouldApply:(c)=>/\bdriver\s*:/.test(c),apply:(c)=>c.replace(/\bdriver(\s*:)/g,"default$1")},{id:"0.70-ports-string-to-number",description:'Convert string port values like `"3000"` to numbers (TypeScript types now require number).',files:["ports.ts"],shouldApply:(c)=>/:\s*['"]\d+['"]/.test(c),apply:(c)=>c.replace(/:\s*['"](\d+)['"]/g,": $1")}];export async function runConfigMigrations(opts){const changed=[],skipped=[],codemods=opts.only?CODEMODS.filter((m)=>m.id===opts.only):CODEMODS;if(codemods.length===0){log.warn(`No matching codemods. Available: ${CODEMODS.map((m)=>m.id).join(", ")}`);return{changed,skipped}}for(const cm of codemods){log.info(`Codemod ${italic(cm.id)} \u2014 ${cm.description}`);for(const rel of cm.files){const full=projectPath(`config/${rel}`);if(!existsSync(full)){skipped.push(`${full} (missing)`);continue}const before=readFileSync(full,"utf-8");if(!cm.shouldApply(before)){skipped.push(`${full} (no changes)`);continue}const after=cm.apply(before);if(after===before){skipped.push(`${full} (no changes)`);continue}if(opts.dryRun){log.info(`[dry-run] would update ${full}`);printDiff(before,after)}else{writeFileSync(full,after);log.success(`updated ${full}`)}changed.push(full)}}return{changed,skipped}}function printDiff(before,after){const beforeLines=before.split(`
|
|
2
|
+
`),afterLines=after.split(`
|
|
3
|
+
`),max=Math.max(beforeLines.length,afterLines.length);for(let i=0;i<max;i++){const b=beforeLines[i],a=afterLines[i];if(b===a)continue;if(b!==void 0)process.stdout.write(` - ${b}
|
|
4
|
+
`);if(a!==void 0)process.stdout.write(` + ${a}
|
|
5
|
+
`)}process.stdout.write(`
|
|
6
|
+
`)}export function configMigrate(buddy){buddy.command("config:migrate","Apply config-shape codemods for the latest Stacks version").option("--dry-run","Preview changes without writing",{default:!1}).option("--only [id]","Run a single codemod by id",{default:""}).action(async(options)=>{log.info("Running `buddy config:migrate` ...");const{changed,skipped}=await runConfigMigrations({dryRun:Boolean(options.dryRun),only:options.only?.length?options.only:void 0});log.info(`Changed: ${changed.length}, Skipped: ${skipped.length}`);if(skipped.length>0)for(const s of skipped)log.debug(` skipped: ${s}`)})}
|
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import { log, onUnknownSubcommand, outro, runCommand } from "@stacksjs/cli";
|
|
3
|
-
import { path as p } from "@stacksjs/path";
|
|
4
|
-
import { ExitCode } from "@stacksjs/types";
|
|
5
|
-
export function configure(buddy) {
|
|
6
|
-
const descriptions = {
|
|
7
|
-
configure: "Configure options",
|
|
8
|
-
aws: "Configure the AWS connection",
|
|
9
|
-
project: "Target a specific project",
|
|
10
|
-
profile: "The AWS profile to use",
|
|
11
|
-
verbose: "Enable verbose output"
|
|
12
|
-
};
|
|
13
|
-
buddy.command("configure", descriptions.configure).option("--aws", descriptions.aws, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
14
|
-
log.debug("Running `buddy configure` ...", options);
|
|
15
|
-
if (options?.aws) {
|
|
16
|
-
await configureAws(options);
|
|
17
|
-
process.exit(ExitCode.Success);
|
|
18
|
-
}
|
|
19
|
-
log.info("Not implemented yet. Please use the --aws flag to configure AWS.");
|
|
20
|
-
process.exit(ExitCode.Success);
|
|
21
|
-
});
|
|
22
|
-
buddy.command("configure:aws", descriptions.aws).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--profile", descriptions.profile, {
|
|
23
|
-
default: process.env.AWS_PROFILE
|
|
24
|
-
}).option("--verbose", descriptions.verbose, { default: !1 }).option("--access-key-id", "The AWS access key").option("--secret-access-key", "The AWS secret access key").option("--region", "The AWS region").option("--output", "The AWS output format").option("--quiet", "Suppress output").action(async (options) => {
|
|
25
|
-
log.debug("Running `buddy configure:aws` ...", options);
|
|
26
|
-
await configureAws(options);
|
|
27
|
-
process.exit(ExitCode.Success);
|
|
28
|
-
});
|
|
29
|
-
onUnknownSubcommand(buddy, "configure");
|
|
30
|
-
}
|
|
31
|
-
async function configureAws(options) {
|
|
32
|
-
const startTime = performance.now(), awsAccessKeyId = options?.accessKeyId ?? process.env.AWS_ACCESS_KEY_ID, awsSecretAccessKey = options?.secretAccessKey ?? process.env.AWS_SECRET_ACCESS_KEY, defaultRegion = "us-east-1", defaultOutputFormat = options?.output ?? "json", profile = process.env.AWS_PROFILE ?? options?.profile, command = profile ? `aws configure --profile ${profile}` : "aws configure", input = `${awsAccessKeyId}
|
|
1
|
+
import process from"node:process";import{log,onUnknownSubcommand,outro,runCommand}from"@stacksjs/cli";import{path as p}from"@stacksjs/path";import{ExitCode}from"@stacksjs/types";export function configure(buddy){const descriptions={configure:"Configure options",aws:"Configure the AWS connection",project:"Target a specific project",profile:"The AWS profile to use",verbose:"Enable verbose output"};buddy.command("configure",descriptions.configure).option("--aws",descriptions.aws,{default:!1}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy configure` ...",options);if(options?.aws){await configureAws(options);process.exit(ExitCode.Success)}log.info("Not implemented yet. Please use the --aws flag to configure AWS.");process.exit(ExitCode.Success)});buddy.command("configure:aws",descriptions.aws).option("-p, --project [project]",descriptions.project,{default:!1}).option("--profile",descriptions.profile,{default:process.env.AWS_PROFILE}).option("--verbose",descriptions.verbose,{default:!1}).option("--access-key-id","The AWS access key").option("--secret-access-key","The AWS secret access key").option("--region","The AWS region").option("--output","The AWS output format").option("--quiet","Suppress output").action(async(options)=>{log.debug("Running `buddy configure:aws` ...",options);await configureAws(options);process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"configure")}async function configureAws(options){const startTime=performance.now(),awsAccessKeyId=options?.accessKeyId??process.env.AWS_ACCESS_KEY_ID,awsSecretAccessKey=options?.secretAccessKey??process.env.AWS_SECRET_ACCESS_KEY,defaultRegion="us-east-1",defaultOutputFormat=options?.output??"json",profile=process.env.AWS_PROFILE??options?.profile,command=profile?`aws configure --profile ${profile}`:"aws configure",input=`${awsAccessKeyId}
|
|
33
2
|
${awsSecretAccessKey}
|
|
34
3
|
${defaultRegion}
|
|
35
4
|
${defaultOutputFormat}
|
|
36
|
-
`,
|
|
37
|
-
cwd: p.projectPath(),
|
|
38
|
-
stdin: "pipe",
|
|
39
|
-
input
|
|
40
|
-
});
|
|
41
|
-
if (result.isErr) {
|
|
42
|
-
await outro("While running the cloud command, there was an issue", { startTime, useSeconds: !0 }, result.error);
|
|
43
|
-
process.exit(ExitCode.FatalError);
|
|
44
|
-
}
|
|
45
|
-
if (options?.quiet)
|
|
46
|
-
return;
|
|
47
|
-
await outro("Exited", { startTime, useSeconds: !0 });
|
|
48
|
-
}
|
|
5
|
+
`,result=await runCommand(command,{cwd:p.projectPath(),stdin:"pipe",input});if(result.isErr){await outro("While running the cloud command, there was an issue",{startTime,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}if(options?.quiet)return;await outro("Exited",{startTime,useSeconds:!0})}
|
package/dist/commands/create.js
CHANGED
|
@@ -1,162 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import process from "node:process";
|
|
3
|
-
import { runAction } from "@stacksjs/actions";
|
|
4
|
-
import { bold, cyan, dim, intro, log, onUnknownSubcommand, runCommand } from "@stacksjs/cli";
|
|
5
|
-
import { Action } from "@stacksjs/enums";
|
|
6
|
-
import { resolve } from "@stacksjs/path";
|
|
7
|
-
import { isFolder } from "@stacksjs/storage";
|
|
8
|
-
import { ExitCode } from "@stacksjs/types";
|
|
9
|
-
import { uninstallAllFeatures } from "./features";
|
|
10
|
-
import { ensurePantryDependencies, ensurePantryInstalled } from "./setup";
|
|
11
|
-
export function create(buddy) {
|
|
12
|
-
const descriptions = {
|
|
13
|
-
name: "The name of the project",
|
|
14
|
-
command: "Create a new Stacks project",
|
|
15
|
-
ui: "Are you building a UI?",
|
|
16
|
-
components: "Are you building UI components?",
|
|
17
|
-
webComponents: "Automagically built optimized custom elements/web components?",
|
|
18
|
-
views: "How about views?",
|
|
19
|
-
functions: "Are you developing functions/composables?",
|
|
20
|
-
api: "Are you building an API?",
|
|
21
|
-
database: "Do you need a database?",
|
|
22
|
-
notifications: "Do you need notifications? e.g. email, SMS, push or chat notifications",
|
|
23
|
-
cache: "Do you need caching?",
|
|
24
|
-
email: "Do you need email?",
|
|
25
|
-
project: "Target a specific project",
|
|
26
|
-
minimal: "Skip optional feature bundles (cms, commerce, dashboard, marketing, monitoring, realtime, queue) \u2014 bare-bones API/SPA starter that can re-add them later via `./buddy <feature>:install`.",
|
|
27
|
-
withCore: "Keep the framework vendored in `storage/framework/core` as a Bun workspace, for working ON Stacks. Apps that only work WITH Stacks want the default, which resolves every @stacksjs/* package from npm.",
|
|
28
|
-
verbose: "Enable verbose output"
|
|
29
|
-
};
|
|
30
|
-
buddy.command("new [name]", descriptions.command).alias("create [name]").option("-n, --name [name]", descriptions.name, { default: !1 }).option("-u, --ui", descriptions.ui, { default: !0 }).option("-c, --components", descriptions.components, { default: !0 }).option("-w, --web-components", descriptions.webComponents, { default: !0 }).option("-p, --views", descriptions.views, { default: !0 }).option("-f, --functions", descriptions.functions, { default: !0 }).option("-a, --api", descriptions.api, { default: !0 }).option("-d, --database", descriptions.database, { default: !0 }).option("-ca, --cache", descriptions.cache, { default: !1 }).option("-e, --email", descriptions.email, { default: !1 }).option("-P, --project [project]", descriptions.project, { default: !1 }).option("-m, --minimal", descriptions.minimal, { default: !1 }).option("--with-core", descriptions.withCore, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (name, options) => {
|
|
31
|
-
log.debug("Running `buddy new <name>` ...", options);
|
|
32
|
-
const startTime = await intro("buddy new");
|
|
33
|
-
name = name ?? options.name;
|
|
34
|
-
const path = resolve(process.cwd(), name);
|
|
35
|
-
isFolderCheck(path);
|
|
36
|
-
await onlineCheck();
|
|
37
|
-
const result = await download(name, path, options);
|
|
38
|
-
if (result.isErr) {
|
|
39
|
-
log.error(result.error);
|
|
40
|
-
process.exit(ExitCode.FatalError);
|
|
41
|
-
}
|
|
42
|
-
ensureExecutableScripts(path);
|
|
43
|
-
await ensureEnv(path, options);
|
|
44
|
-
await install(path, options);
|
|
45
|
-
if (!options.withCore)
|
|
46
|
-
await unvendorCore(path, options);
|
|
47
|
-
if (options.minimal)
|
|
48
|
-
await stripFeatures(path);
|
|
49
|
-
if (startTime) {
|
|
50
|
-
const time = performance.now() - startTime;
|
|
51
|
-
log.success(dim(`[${time.toFixed(2)}ms] Completed`));
|
|
52
|
-
}
|
|
53
|
-
log.info(bold("Welcome to the Stacks Framework! \u269B\uFE0F"));
|
|
54
|
-
log.info(`Get started: ${cyan(`cd ${name}`)} and then ${cyan("./buddy dev")}`);
|
|
55
|
-
log.info(`Run ${cyan("./buddy doctor")} anytime to check your setup`);
|
|
56
|
-
log.info("To learn more, visit https://stacksjs.com");
|
|
57
|
-
process.exit(ExitCode.Success);
|
|
58
|
-
});
|
|
59
|
-
onUnknownSubcommand(buddy, "new");
|
|
60
|
-
}
|
|
61
|
-
function isFolderCheck(path) {
|
|
62
|
-
if (!isFolder(path))
|
|
63
|
-
return;
|
|
64
|
-
if (readdirSync(path).filter((entry) => entry !== ".git").length === 0)
|
|
65
|
-
return;
|
|
66
|
-
log.error(`Path ${path} already exists`);
|
|
67
|
-
process.exit(ExitCode.FatalError);
|
|
68
|
-
}
|
|
69
|
-
async function onlineCheck() {
|
|
70
|
-
if (await isOnline())
|
|
71
|
-
return;
|
|
72
|
-
log.info("It appears you are disconnected from the internet.");
|
|
73
|
-
log.info("Creating a new project requires a brief internet connection to download the template and install dependencies.");
|
|
74
|
-
process.exit(ExitCode.FatalError);
|
|
75
|
-
}
|
|
76
|
-
async function isOnline() {
|
|
77
|
-
try {
|
|
78
|
-
return (await fetch("https://github.com", {
|
|
79
|
-
method: "HEAD",
|
|
80
|
-
signal: AbortSignal.timeout(3000)
|
|
81
|
-
})).ok;
|
|
82
|
-
} catch {
|
|
83
|
-
return !1;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async function download(name, path, _options) {
|
|
87
|
-
log.info("Setting up your stack.");
|
|
88
|
-
try {
|
|
89
|
-
const { downloadTemplate } = await import("@stacksjs/gitit");
|
|
90
|
-
await downloadTemplate("gh:stacksjs/stacks", { dir: name, force: !0 });
|
|
91
|
-
log.success(`Successfully scaffolded your project at ${cyan(path)}`);
|
|
92
|
-
return { isErr: !1 };
|
|
93
|
-
} catch (error) {
|
|
94
|
-
return { isErr: !0, error: error instanceof Error ? error.message : String(error) };
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function ensureExecutableScripts(path) {
|
|
98
|
-
for (const script of ["buddy", "bootstrap"])
|
|
99
|
-
try {
|
|
100
|
-
chmodSync(resolve(path, script), 493);
|
|
101
|
-
} catch {}
|
|
102
|
-
}
|
|
103
|
-
async function ensureEnv(path, _options) {
|
|
104
|
-
log.info("Ensuring your environment is ready...");
|
|
105
|
-
await ensurePantryInstalled();
|
|
106
|
-
await ensurePantryDependencies(path);
|
|
107
|
-
log.success("Environment is ready");
|
|
108
|
-
}
|
|
109
|
-
async function install(path, options) {
|
|
110
|
-
log.info("Installing & setting up Stacks");
|
|
111
|
-
log.info("Copying .env.example \u2192 .env");
|
|
112
|
-
let result = await runCommand("cp .env.example .env", { ...options, cwd: path });
|
|
113
|
-
if (result?.isErr) {
|
|
114
|
-
log.error(result.error);
|
|
115
|
-
process.exit(ExitCode.FatalError);
|
|
116
|
-
}
|
|
117
|
-
log.info("Removing template-encrypted env files...");
|
|
118
|
-
const { rm } = await import("node:fs/promises");
|
|
119
|
-
for (const stale of [".env.development", ".env.staging", ".env.production", ".env.keys"])
|
|
120
|
-
await rm(`${path}/${stale}`, { force: !0 });
|
|
121
|
-
log.info("Generating application key...");
|
|
122
|
-
const keyResult = await runAction(Action.KeyGenerate, { ...options, cwd: path });
|
|
123
|
-
if (keyResult.isErr) {
|
|
124
|
-
log.error(keyResult.error);
|
|
125
|
-
process.exit(ExitCode.FatalError);
|
|
126
|
-
}
|
|
127
|
-
if (existsSync(resolve(path, ".git")))
|
|
128
|
-
log.info("Existing git repository detected, skipping git init");
|
|
129
|
-
else {
|
|
130
|
-
log.info("Initializing git repository...");
|
|
131
|
-
result = await runCommand("git init", { ...options, cwd: path });
|
|
132
|
-
if (result.isErr) {
|
|
133
|
-
log.error(result.error);
|
|
134
|
-
process.exit(ExitCode.FatalError);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
log.success("Installed & set-up \uD83D\uDE80");
|
|
138
|
-
}
|
|
139
|
-
async function unvendorCore(path, options) {
|
|
140
|
-
log.info("Resolving the framework from npm (pass --with-core to keep it vendored)...");
|
|
141
|
-
const result = await runCommand("./buddy unpublish:core --all --force", { ...options, cwd: path });
|
|
142
|
-
if (result.isErr) {
|
|
143
|
-
log.error(result.error);
|
|
144
|
-
process.exit(ExitCode.FatalError);
|
|
145
|
-
}
|
|
146
|
-
log.success("Framework resolved from npm");
|
|
147
|
-
}
|
|
148
|
-
async function stripFeatures(path) {
|
|
149
|
-
log.info("Stripping optional feature bundles (--minimal)...");
|
|
150
|
-
const results = await uninstallAllFeatures({ root: path });
|
|
151
|
-
let strippedAny = !1;
|
|
152
|
-
for (const { feature, configOutcome, filesRemoved } of results)
|
|
153
|
-
if (configOutcome === "flipped" || filesRemoved.length > 0) {
|
|
154
|
-
strippedAny = !0;
|
|
155
|
-
const fileSummary = filesRemoved.length > 0 ? ` (${filesRemoved.length} path${filesRemoved.length === 1 ? "" : "s"})` : "";
|
|
156
|
-
log.info(` - ${feature}${fileSummary}`);
|
|
157
|
-
}
|
|
158
|
-
if (!strippedAny)
|
|
159
|
-
log.info(" \u2192 no feature scaffolding present; nothing to strip.");
|
|
160
|
-
else
|
|
161
|
-
log.success("Minimal skeleton ready \u2014 run `./buddy <feature>:install` to add features back.");
|
|
162
|
-
}
|
|
1
|
+
import{chmodSync,existsSync,readdirSync}from"node:fs";import process from"node:process";import{runAction}from"@stacksjs/actions";import{bold,cyan,dim,intro,log,onUnknownSubcommand,runCommand}from"@stacksjs/cli";import{Action}from"@stacksjs/enums";import{resolve}from"@stacksjs/path";import{isFolder}from"@stacksjs/storage";import{ExitCode}from"@stacksjs/types";import{uninstallAllFeatures}from"./features";import{ensurePantryDependencies,ensurePantryInstalled}from"./setup";export function create(buddy){const descriptions={name:"The name of the project",command:"Create a new Stacks project",ui:"Are you building a UI?",components:"Are you building UI components?",webComponents:"Automagically built optimized custom elements/web components?",views:"How about views?",functions:"Are you developing functions/composables?",api:"Are you building an API?",database:"Do you need a database?",notifications:"Do you need notifications? e.g. email, SMS, push or chat notifications",cache:"Do you need caching?",email:"Do you need email?",project:"Target a specific project",minimal:"Skip optional feature bundles (cms, commerce, dashboard, marketing, monitoring, realtime, queue) \u2014 bare-bones API/SPA starter that can re-add them later via `./buddy <feature>:install`.",withCore:"Keep the framework vendored in `storage/framework/core` as a Bun workspace, for working ON Stacks. Apps that only work WITH Stacks want the default, which resolves every @stacksjs/* package from npm.",verbose:"Enable verbose output"};buddy.command("new [name]",descriptions.command).alias("create [name]").option("-n, --name [name]",descriptions.name,{default:!1}).option("-u, --ui",descriptions.ui,{default:!0}).option("-c, --components",descriptions.components,{default:!0}).option("-w, --web-components",descriptions.webComponents,{default:!0}).option("-p, --views",descriptions.views,{default:!0}).option("-f, --functions",descriptions.functions,{default:!0}).option("-a, --api",descriptions.api,{default:!0}).option("-d, --database",descriptions.database,{default:!0}).option("-ca, --cache",descriptions.cache,{default:!1}).option("-e, --email",descriptions.email,{default:!1}).option("-P, --project [project]",descriptions.project,{default:!1}).option("-m, --minimal",descriptions.minimal,{default:!1}).option("--with-core",descriptions.withCore,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(name,options)=>{log.debug("Running `buddy new <name>` ...",options);const startTime=await intro("buddy new");name=name??options.name;const path=resolve(process.cwd(),name);isFolderCheck(path);await onlineCheck();const result=await download(name,path,options);if(result.isErr){log.error(result.error);process.exit(ExitCode.FatalError)}ensureExecutableScripts(path);await ensureEnv(path,options);await install(path,options);if(!options.withCore)await unvendorCore(path,options);if(options.minimal)await stripFeatures(path);if(startTime){const time=performance.now()-startTime;log.success(dim(`[${time.toFixed(2)}ms] Completed`))}log.info(bold("Welcome to the Stacks Framework! \u269B\uFE0F"));log.info(`Get started: ${cyan(`cd ${name}`)} and then ${cyan("./buddy dev")}`);log.info(`Run ${cyan("./buddy doctor")} anytime to check your setup`);log.info("To learn more, visit https://stacksjs.com");process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"new")}function isFolderCheck(path){if(!isFolder(path))return;if(readdirSync(path).filter((entry)=>entry!==".git").length===0)return;log.error(`Path ${path} already exists`);process.exit(ExitCode.FatalError)}async function onlineCheck(){if(await isOnline())return;log.info("It appears you are disconnected from the internet.");log.info("Creating a new project requires a brief internet connection to download the template and install dependencies.");process.exit(ExitCode.FatalError)}async function isOnline(){try{return(await fetch("https://github.com",{method:"HEAD",signal:AbortSignal.timeout(3000)})).ok}catch{return!1}}async function download(name,path,_options){log.info("Setting up your stack.");try{const{downloadTemplate}=await import("@stacksjs/gitit");await downloadTemplate("gh:stacksjs/stacks",{dir:name,force:!0});log.success(`Successfully scaffolded your project at ${cyan(path)}`);return{isErr:!1}}catch(error){return{isErr:!0,error:error instanceof Error?error.message:String(error)}}}function ensureExecutableScripts(path){for(const script of["buddy","bootstrap"])try{chmodSync(resolve(path,script),493)}catch{}}async function ensureEnv(path,_options){log.info("Ensuring your environment is ready...");await ensurePantryInstalled();await ensurePantryDependencies(path);log.success("Environment is ready")}async function install(path,options){log.info("Installing & setting up Stacks");log.info("Copying .env.example \u2192 .env");let result=await runCommand("cp .env.example .env",{...options,cwd:path});if(result?.isErr){log.error(result.error);process.exit(ExitCode.FatalError)}log.info("Removing template-encrypted env files...");const{rm}=await import("node:fs/promises");for(const stale of[".env.development",".env.staging",".env.production",".env.keys"])await rm(`${path}/${stale}`,{force:!0});log.info("Generating application key...");const keyResult=await runAction(Action.KeyGenerate,{...options,cwd:path});if(keyResult.isErr){log.error(keyResult.error);process.exit(ExitCode.FatalError)}if(existsSync(resolve(path,".git")))log.info("Existing git repository detected, skipping git init");else{log.info("Initializing git repository...");result=await runCommand("git init",{...options,cwd:path});if(result.isErr){log.error(result.error);process.exit(ExitCode.FatalError)}}log.success("Installed & set-up \uD83D\uDE80")}async function unvendorCore(path,options){log.info("Resolving the framework from npm (pass --with-core to keep it vendored)...");const result=await runCommand("./buddy unpublish:core --all --force",{...options,cwd:path});if(result.isErr){log.error(result.error);process.exit(ExitCode.FatalError)}log.success("Framework resolved from npm")}async function stripFeatures(path){log.info("Stripping optional feature bundles (--minimal)...");const results=await uninstallAllFeatures({root:path});let strippedAny=!1;for(const{feature,configOutcome,filesRemoved}of results)if(configOutcome==="flipped"||filesRemoved.length>0){strippedAny=!0;const fileSummary=filesRemoved.length>0?` (${filesRemoved.length} path${filesRemoved.length===1?"":"s"})`:"";log.info(` - ${feature}${fileSummary}`)}if(!strippedAny)log.info(" \u2192 no feature scaffolding present; nothing to strip.");else log.success("Minimal skeleton ready \u2014 run `./buddy <feature>:install` to add features back.")}
|