@stacksjs/buddy 0.70.161 → 0.70.162

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/README.md CHANGED
@@ -35,7 +35,7 @@ curl -Ssf stacksjs.com/install | sh # wip
35
35
 
36
36
  # alternatively, if Bun >= v1.1.11 is installed already
37
37
  # you may also get started via
38
- bunx stacks new my-project
38
+ panx @stacksjs/buddy new my-project
39
39
  ```
40
40
 
41
41
  ## Usage
@@ -79,7 +79,7 @@ buddy --help # view help menu
79
79
  # `command --help` flag to review the help menu
80
80
 
81
81
  buddy install # installs dependencies
82
- buddy add # adds a stack or dependency
82
+ buddy add calendar # pulls a registered project-shaped stack into this project
83
83
  buddy fresh # fresh reinstall of all deps
84
84
  buddy clean # removes all deps
85
85
  buddy setup # sets up the project initially
@@ -154,7 +154,7 @@ buddy make:factory cars # creates a Car factory file
154
154
  buddy make:table cars # bootstraps a cars data table
155
155
  buddy make:notification welcome-email # bootstraps a welcome-email notification
156
156
  buddy make:lang de # bootstraps a lang/de.yml language file
157
- buddy make:stack my-project # shares logic with `bunx stacks new my-project`
157
+ buddy make:stack my-project # scaffolds a project-shaped registry stack
158
158
 
159
159
  buddy migrate # runs database migrations
160
160
  buddy migrate:dns # sets the ./config/dns.ts file
@@ -1,33 +1,25 @@
1
1
  import process from "node:process";
2
- import { runAdd } from "@stacksjs/actions";
3
- import { log } from "@stacksjs/logging";
2
+ import { installStack } from "@stacksjs/actions";
3
+ import { intro, italic, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
4
4
  import { ExitCode } from "@stacksjs/types";
5
- import { onUnknownSubcommand } from "@stacksjs/cli";
6
5
  export function add(buddy) {
7
- const descriptions = {
8
- add: "Add a stack to your project (table and calendar available, more coming soon)",
9
- table: "Add the Table Stack to your project",
10
- calendar: "Add the Calendar Stack to your project",
11
- all: "Add all stacks",
12
- select: "Which stack/s are you trying to add?",
13
- project: "Target a specific project",
14
- verbose: "Enable verbose output"
15
- };
16
- buddy.command("add", descriptions.add).option("-t, --table", descriptions.table, { default: !1 }).option("-c, --calendar", descriptions.calendar, { default: !1 }).option("-a, --all", descriptions.all, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
17
- log.debug("Running `buddy add`...", options);
18
- if (hasNoOptions(options))
19
- ;
20
- await runAdd(options);
6
+ buddy.command("add <stack>", "Pull a registered stack and merge its project files into this Stacks application").option("--force", "Overwrite existing files", { default: !1 }).option("--dry-run", "Show which files would be installed without changing the project", { default: !1 }).option("--conflict <strategy>", "Resolve existing files with skip, overwrite, or backup", { default: "skip" }).option("-p, --project <path>", "Target a specific Stacks project").option("--verbose", "Show every file copied or skipped", { default: !1 }).example("buddy add calendar").example("buddy add table --dry-run").example("buddy add calendar --conflict backup").action(async (stack, options) => {
7
+ const perf = await intro("buddy add");
8
+ if (!await installStack({
9
+ name: stack,
10
+ force: options.force,
11
+ dryRun: options.dryRun,
12
+ conflict: options.conflict,
13
+ project: options.project,
14
+ verbose: options.verbose
15
+ })) {
16
+ await outro(`Could not add stack ${italic(stack)}.`, { startTime: perf, useSeconds: !0 });
17
+ process.exit(ExitCode.FatalError);
18
+ }
19
+ if (options.dryRun)
20
+ log.info("Dry run complete. No project files were changed.");
21
+ await outro(`Stack ${italic(stack)} added.`, { startTime: perf, useSeconds: !0 });
21
22
  process.exit(ExitCode.Success);
22
23
  });
23
- buddy.command("add:table", descriptions.table).option("-t, --table", descriptions.table, { default: !0 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
24
- await runAdd(options);
25
- });
26
- buddy.command("add:calendar", descriptions.calendar).option("-t, --calendar", descriptions.calendar, { default: !0 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
27
- await runAdd(options);
28
- });
29
24
  onUnknownSubcommand(buddy, "add");
30
25
  }
31
- function hasNoOptions(options) {
32
- return !options.all && !options.table && !options.calendar;
33
- }
@@ -103,14 +103,8 @@ async function ensureEnv(path, _options) {
103
103
  }
104
104
  async function install(path, options) {
105
105
  log.info("Installing & setting up Stacks");
106
- log.info("Running bun install...");
107
- let result = await runCommand("bun install", { ...options, cwd: path });
108
- if (result?.isErr) {
109
- log.error(result.error);
110
- process.exit(ExitCode.FatalError);
111
- }
112
106
  log.info("Copying .env.example \u2192 .env");
113
- result = await runCommand("cp .env.example .env", { ...options, cwd: path });
107
+ let result = await runCommand("cp .env.example .env", { ...options, cwd: path });
114
108
  if (result?.isErr) {
115
109
  log.error(result.error);
116
110
  process.exit(ExitCode.FatalError);
@@ -17,7 +17,7 @@ export function sanitizeLineCount(value) {
17
17
  const count = Number.parseInt(value || "50", 10);
18
18
  return String(Number.isFinite(count) ? Math.min(5000, Math.max(1, count)) : 50);
19
19
  }
20
- function shellQuote(value) {
20
+ function shellQuote(_value) {
21
21
  return `'${value.replace(/'/g, "'\\''")}'`;
22
22
  }
23
23
  async function resolveOperationalMailHost() {
@@ -2,7 +2,6 @@ import type { CLI, CliOptions } from '@stacksjs/types';
2
2
  export declare function setup(buddy: CLI): void;
3
3
  export declare function ensurePantryInstalled(): Promise<void>;
4
4
  export declare function ensurePantryDependencies(cwd: string): Promise<void>;
5
- export declare function ensureNodeDependencies(cwd: string): Promise<void>;
6
5
  export declare function ensureAppKey(cwd: string): Promise<void>;
7
6
  export declare function ensureIdeSettings(cwd: string): void;
8
7
  export declare function pantryDatabasePackage(connection: string): DatabasePackage | undefined;
@@ -1,4 +1,5 @@
1
1
  import { cpSync, existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
2
3
  import { join } from "node:path";
3
4
  import process from "node:process";
4
5
  import { runAction } from "@stacksjs/actions";
@@ -15,7 +16,7 @@ function getTimeoutMs(envVar, fallbackMs) {
15
16
  return value;
16
17
  return fallbackMs;
17
18
  }
18
- const PANTRY_CHECK_TIMEOUT_MS = getTimeoutMs("PANTRY_CHECK_TIMEOUT_MS", 15000), PANTRY_INSTALL_TIMEOUT_MS = getTimeoutMs("PANTRY_INSTALL_TIMEOUT_MS", 600000), PANTRY_DEPENDENCIES_TIMEOUT_MS = getTimeoutMs("PANTRY_DEPENDENCIES_TIMEOUT_MS", 1200000), BUN_INSTALL_TIMEOUT_MS = getTimeoutMs("BUN_INSTALL_TIMEOUT_MS", 600000), KEYGEN_TIMEOUT_MS = getTimeoutMs("KEYGEN_TIMEOUT_MS", 120000), AWS_CONFIG_TIMEOUT_MS = getTimeoutMs("AWS_CONFIG_TIMEOUT_MS", 900000);
19
+ const PANTRY_CHECK_TIMEOUT_MS = getTimeoutMs("PANTRY_CHECK_TIMEOUT_MS", 15000), PANTRY_INSTALL_TIMEOUT_MS = getTimeoutMs("PANTRY_INSTALL_TIMEOUT_MS", 600000), PANTRY_DEPENDENCIES_TIMEOUT_MS = getTimeoutMs("PANTRY_DEPENDENCIES_TIMEOUT_MS", 1200000), KEYGEN_TIMEOUT_MS = getTimeoutMs("KEYGEN_TIMEOUT_MS", 120000), AWS_CONFIG_TIMEOUT_MS = getTimeoutMs("AWS_CONFIG_TIMEOUT_MS", 900000);
19
20
  export function setup(buddy) {
20
21
  const descriptions = {
21
22
  setup: "This command ensures your project is setup correctly",
@@ -69,59 +70,41 @@ async function isPantryInstalled() {
69
70
  }
70
71
  }
71
72
  async function installPantry() {
72
- const result = await runCommand(p.frameworkPath("scripts/pantry-install"), {
73
+ const bundledInstaller = p.frameworkPath("scripts/pantry-install"), command = existsSync(bundledInstaller) ? [bundledInstaller] : ["sh", "-c", "curl -fsSL https://pantry.dev | bash"], result = await runCommand(command, {
73
74
  timeoutMs: PANTRY_INSTALL_TIMEOUT_MS
74
- });
75
- if (result.isOk)
75
+ }), localBin = join(homedir(), ".local", "bin");
76
+ if (!process.env.PATH?.split(":").includes(localBin))
77
+ process.env.PATH = `${localBin}:${process.env.PATH || ""}`;
78
+ if (result.isOk && await isPantryInstalled())
76
79
  return;
77
- handleError(result.error);
80
+ if (result.isErr)
81
+ handleError(result.error);
82
+ else
83
+ log.error("Pantry installed but is not available on PATH. Open a new shell and run `buddy setup` again.");
78
84
  process.exit(ExitCode.FatalError);
79
85
  }
80
86
  export async function ensurePantryInstalled() {
81
87
  if (await isPantryInstalled())
82
88
  return;
83
- const installer = p.frameworkPath("scripts/pantry-install");
84
- if (!existsSync(installer)) {
85
- log.debug("Pantry is not installed and no bundled installer is present; continuing without it.");
86
- return;
87
- }
89
+ log.info("Pantry is required. Installing it from https://pantry.dev...");
88
90
  await installPantry();
89
91
  }
90
92
  export async function ensurePantryDependencies(cwd) {
91
- if (!await isPantryInstalled()) {
92
- log.debug("Pantry not installed; skipping pantry dependency install (deps come from node_modules).");
93
- return;
94
- }
95
- log.info("Installing Pantry dependencies...");
93
+ await ensurePantryInstalled();
94
+ log.info("Installing project dependencies with Pantry...");
96
95
  const result = await runCommand("pantry install", {
97
96
  cwd,
98
97
  timeoutMs: PANTRY_DEPENDENCIES_TIMEOUT_MS
99
98
  });
100
- if (result.isOk) {
101
- log.success("Installed Pantry dependencies");
102
- return;
103
- }
104
- handleError(result.error);
105
- process.exit(ExitCode.FatalError);
106
- }
107
- export async function ensureNodeDependencies(cwd) {
108
- if (existsSync(join(cwd, "node_modules"))) {
109
- log.success("node_modules existed, skipping bun install");
110
- return;
111
- }
112
- log.info("Running bun install...");
113
- const result = await runCommand("bun install", {
114
- cwd,
115
- timeoutMs: BUN_INSTALL_TIMEOUT_MS
116
- }).catch((error) => {
117
- handleError(error);
118
- process.exit(ExitCode.FatalError);
119
- });
120
99
  if (result.isErr) {
121
100
  handleError(result.error);
122
101
  process.exit(ExitCode.FatalError);
123
102
  }
124
- log.success("Installed node dependencies");
103
+ if (existsSync(join(cwd, "package.json")) && !existsSync(join(cwd, "node_modules"))) {
104
+ log.error("Pantry completed without installing the project JavaScript dependencies.");
105
+ process.exit(ExitCode.FatalError);
106
+ }
107
+ log.success("Installed project dependencies with Pantry");
125
108
  }
126
109
  function hasAppKey(cwd) {
127
110
  const envPath = join(cwd, ".env");
@@ -167,7 +150,6 @@ async function runInitialMigration(cwd) {
167
150
  async function initializeProject(options) {
168
151
  const cwd = options.cwd || p.projectPath();
169
152
  await ensurePantryDependencies(cwd);
170
- await ensureNodeDependencies(cwd);
171
153
  await ensureEnvIsSet(options);
172
154
  if (!options.skipKeygen)
173
155
  await ensureAppKey(cwd);
@@ -11,13 +11,14 @@ export function stacks(buddy) {
11
11
  force: "Force overwrite existing files",
12
12
  dryRun: "Show what would be installed without making changes",
13
13
  conflict: "Conflict resolution strategy: skip, overwrite, or backup",
14
- verbose: "Enable verbose output"
14
+ verbose: "Enable verbose output",
15
+ project: "Target a specific Stacks project"
15
16
  };
16
- buddy.command("stack:install <name>", descriptions.install).option("--force", descriptions.force, { default: !1 }).option("--dry-run", descriptions.dryRun, { default: !1 }).option("--conflict <strategy>", descriptions.conflict, { default: "skip" }).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy stack:install @stacksjs/blog").example("buddy stack:install blog --force").example("buddy stack:install blog --conflict backup --verbose").example("buddy stack:install blog --dry-run").action(async (name, options) => {
17
+ buddy.command("stack:install <name>", descriptions.install).option("--force", descriptions.force, { default: !1 }).option("--dry-run", descriptions.dryRun, { default: !1 }).option("--conflict <strategy>", descriptions.conflict, { default: "skip" }).option("-p, --project <path>", descriptions.project).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy add calendar").example("buddy add table --force").example("buddy add calendar --conflict backup --verbose").example("buddy add table --dry-run").action(async (name, options) => {
17
18
  const perf = await intro("buddy stack:install");
18
19
  if (!name) {
19
20
  log.error("You need to specify a stack name.");
20
- log.info("Example: buddy stack:install @stacksjs/blog");
21
+ log.info("Example: buddy add calendar");
21
22
  process.exit(ExitCode.FatalError);
22
23
  }
23
24
  if (!await installStack({
@@ -25,6 +26,7 @@ export function stacks(buddy) {
25
26
  force: options.force,
26
27
  dryRun: options.dryRun,
27
28
  conflict: options.conflict || "skip",
29
+ project: options.project,
28
30
  verbose: options.verbose
29
31
  }) && !options.dryRun) {
30
32
  await outro("Failed to install stack", { startTime: perf, useSeconds: !0 });
@@ -33,7 +35,7 @@ export function stacks(buddy) {
33
35
  await outro(`Stack ${italic(name)} installed.`, { startTime: perf, useSeconds: !0 });
34
36
  process.exit(ExitCode.Success);
35
37
  });
36
- buddy.command("stack:uninstall <name>", descriptions.uninstall).option("--force", descriptions.force, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy stack:uninstall blog").example("buddy stack:uninstall blog --force").action(async (name, options) => {
38
+ buddy.command("stack:uninstall <name>", descriptions.uninstall).option("--force", descriptions.force, { default: !1 }).option("-p, --project <path>", descriptions.project).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy stack:uninstall blog").example("buddy stack:uninstall blog --force").action(async (name, options) => {
37
39
  const perf = await intro("buddy stack:uninstall");
38
40
  if (!name) {
39
41
  log.error("You need to specify a stack name.");
@@ -42,6 +44,7 @@ export function stacks(buddy) {
42
44
  if (!await uninstallStack({
43
45
  name,
44
46
  force: options.force,
47
+ project: options.project,
45
48
  verbose: options.verbose
46
49
  })) {
47
50
  await outro("Failed to uninstall stack", { startTime: perf, useSeconds: !0 });
@@ -50,10 +53,10 @@ export function stacks(buddy) {
50
53
  await outro(`Stack ${italic(name)} uninstalled.`, { startTime: perf, useSeconds: !0 });
51
54
  process.exit(ExitCode.Success);
52
55
  });
53
- buddy.command("stack:list", descriptions.list).alias("stack:ls").example("buddy stack:list").action(async () => {
54
- const perf = await intro("buddy stack:list"), entries = await listStacks();
56
+ buddy.command("stack:list", descriptions.list).alias("stack:ls").option("-p, --project <path>", descriptions.project).example("buddy stack:list").action(async (options) => {
57
+ const perf = await intro("buddy stack:list"), entries = await listStacks(options.project);
55
58
  if (entries.length === 0)
56
- log.info("No stacks found. Install one with: buddy stack:install <name>");
59
+ log.info("No stacks found. Install one with: buddy add <name>");
57
60
  else {
58
61
  log.info(`Found ${entries.length} stack(s):`);
59
62
  log.info("");
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.161",
5
+ "version": "0.70.162",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -92,52 +92,52 @@
92
92
  "prepublishOnly": "bun run build"
93
93
  },
94
94
  "dependencies": {
95
- "@stacksjs/actions": "^0.70.161",
96
- "@stacksjs/ai": "^0.70.161",
97
- "@stacksjs/alias": "^0.70.161",
98
- "@stacksjs/arrays": "^0.70.161",
99
- "@stacksjs/auth": "^0.70.161",
100
- "@stacksjs/build": "^0.70.161",
101
- "@stacksjs/cache": "^0.70.161",
102
- "@stacksjs/cli": "^0.70.161",
95
+ "@stacksjs/actions": "^0.70.162",
96
+ "@stacksjs/ai": "^0.70.162",
97
+ "@stacksjs/alias": "^0.70.162",
98
+ "@stacksjs/arrays": "^0.70.162",
99
+ "@stacksjs/auth": "^0.70.162",
100
+ "@stacksjs/build": "^0.70.162",
101
+ "@stacksjs/cache": "^0.70.162",
102
+ "@stacksjs/cli": "^0.70.162",
103
103
  "@stacksjs/clapp": "^0.2.12",
104
- "@stacksjs/cloud": "^0.70.161",
105
- "@stacksjs/collections": "^0.70.161",
106
- "@stacksjs/config": "^0.70.161",
107
- "@stacksjs/database": "^0.70.161",
108
- "@stacksjs/desktop": "^0.70.161",
109
- "@stacksjs/dns": "^0.70.161",
110
- "@stacksjs/email": "^0.70.161",
111
- "@stacksjs/enums": "^0.70.161",
112
- "@stacksjs/error-handling": "^0.70.161",
113
- "@stacksjs/events": "^0.70.161",
114
- "@stacksjs/git": "^0.70.161",
104
+ "@stacksjs/cloud": "^0.70.162",
105
+ "@stacksjs/collections": "^0.70.162",
106
+ "@stacksjs/config": "^0.70.162",
107
+ "@stacksjs/database": "^0.70.162",
108
+ "@stacksjs/desktop": "^0.70.162",
109
+ "@stacksjs/dns": "^0.70.162",
110
+ "@stacksjs/email": "^0.70.162",
111
+ "@stacksjs/enums": "^0.70.162",
112
+ "@stacksjs/error-handling": "^0.70.162",
113
+ "@stacksjs/events": "^0.70.162",
114
+ "@stacksjs/git": "^0.70.162",
115
115
  "@stacksjs/gitit": "^0.2.5",
116
- "@stacksjs/health": "^0.70.161",
116
+ "@stacksjs/health": "^0.70.162",
117
117
  "@stacksjs/dnsx": "^0.2.3",
118
118
  "@stacksjs/httx": "^0.1.10",
119
- "@stacksjs/lint": "^0.70.161",
120
- "@stacksjs/logging": "^0.70.161",
121
- "@stacksjs/notifications": "^0.70.161",
122
- "@stacksjs/objects": "^0.70.161",
123
- "@stacksjs/orm": "^0.70.161",
124
- "@stacksjs/path": "^0.70.161",
125
- "@stacksjs/payments": "^0.70.161",
126
- "@stacksjs/realtime": "^0.70.161",
127
- "@stacksjs/router": "^0.70.161",
119
+ "@stacksjs/lint": "^0.70.162",
120
+ "@stacksjs/logging": "^0.70.162",
121
+ "@stacksjs/notifications": "^0.70.162",
122
+ "@stacksjs/objects": "^0.70.162",
123
+ "@stacksjs/orm": "^0.70.162",
124
+ "@stacksjs/path": "^0.70.162",
125
+ "@stacksjs/payments": "^0.70.162",
126
+ "@stacksjs/realtime": "^0.70.162",
127
+ "@stacksjs/router": "^0.70.162",
128
128
  "@stacksjs/rpx": "^0.11.31",
129
- "@stacksjs/search-engine": "^0.70.161",
130
- "@stacksjs/security": "^0.70.161",
131
- "@stacksjs/server": "^0.70.161",
132
- "@stacksjs/storage": "^0.70.161",
133
- "@stacksjs/strings": "^0.70.161",
134
- "@stacksjs/testing": "^0.70.161",
135
- "@stacksjs/tunnel": "^0.70.161",
136
- "@stacksjs/types": "^0.70.161",
137
- "@stacksjs/ui": "^0.70.161",
138
- "@stacksjs/utils": "^0.70.161",
139
- "@stacksjs/validation": "^0.70.161",
140
- "@stacksjs/ts-cloud": "^0.7.49"
129
+ "@stacksjs/search-engine": "^0.70.162",
130
+ "@stacksjs/security": "^0.70.162",
131
+ "@stacksjs/server": "^0.70.162",
132
+ "@stacksjs/storage": "^0.70.162",
133
+ "@stacksjs/strings": "^0.70.162",
134
+ "@stacksjs/testing": "^0.70.162",
135
+ "@stacksjs/tunnel": "^0.70.162",
136
+ "@stacksjs/types": "^0.70.162",
137
+ "@stacksjs/ui": "^0.70.162",
138
+ "@stacksjs/utils": "^0.70.162",
139
+ "@stacksjs/validation": "^0.70.162",
140
+ "@stacksjs/ts-cloud": "^0.7.56"
141
141
  },
142
142
  "devDependencies": {
143
143
  "better-dx": "^0.2.17"