@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.
Files changed (112) hide show
  1. package/dist/cli.d.ts +11 -1
  2. package/dist/cli.js +5 -164
  3. package/dist/commands/about.js +1 -35
  4. package/dist/commands/add.js +1 -25
  5. package/dist/commands/ai-context.js +4 -27
  6. package/dist/commands/auth.js +1 -68
  7. package/dist/commands/build.js +1 -221
  8. package/dist/commands/cd.js +8 -39
  9. package/dist/commands/changelog.js +1 -32
  10. package/dist/commands/clean.js +1 -44
  11. package/dist/commands/cloud.js +2 -519
  12. package/dist/commands/commit.js +1 -16
  13. package/dist/commands/completion.js +6 -42
  14. package/dist/commands/config-migrate.js +6 -94
  15. package/dist/commands/configure.js +2 -45
  16. package/dist/commands/create.js +1 -162
  17. package/dist/commands/deploy.js +13 -1676
  18. package/dist/commands/desktop-apple.js +12 -399
  19. package/dist/commands/dev.js +6 -1083
  20. package/dist/commands/dns.js +3 -103
  21. package/dist/commands/docs/buddy-commands.js +10 -132
  22. package/dist/commands/docs/buddy-commands.test.js +1 -38
  23. package/dist/commands/docs/framework-repo.js +1 -14
  24. package/dist/commands/docs/framework-repo.test.js +1 -68
  25. package/dist/commands/docs/generated-artifacts.js +3 -70
  26. package/dist/commands/docs/generated-artifacts.test.js +1 -19
  27. package/dist/commands/docs/links.js +2 -85
  28. package/dist/commands/docs/links.test.js +4 -66
  29. package/dist/commands/docs.js +1 -24
  30. package/dist/commands/doctor.js +2 -478
  31. package/dist/commands/domains.js +2 -152
  32. package/dist/commands/email.js +31 -503
  33. package/dist/commands/env.js +1 -312
  34. package/dist/commands/extension.js +1 -239
  35. package/dist/commands/features.js +9 -345
  36. package/dist/commands/fresh.js +1 -46
  37. package/dist/commands/generate.js +2 -152
  38. package/dist/commands/http.js +1 -33
  39. package/dist/commands/index.js +1 -57
  40. package/dist/commands/install.js +1 -22
  41. package/dist/commands/key.js +1 -23
  42. package/dist/commands/link.js +2 -147
  43. package/dist/commands/lint.js +2 -84
  44. package/dist/commands/list.js +1 -140
  45. package/dist/commands/mail.js +15 -1477
  46. package/dist/commands/maintenance.js +1 -141
  47. package/dist/commands/make.js +1 -392
  48. package/dist/commands/migrate-project.js +1 -49
  49. package/dist/commands/migrate.js +27 -625
  50. package/dist/commands/outdated.js +1 -19
  51. package/dist/commands/package.js +1 -17
  52. package/dist/commands/phone.js +17 -181
  53. package/dist/commands/ports.js +2 -118
  54. package/dist/commands/prepublish.js +1 -17
  55. package/dist/commands/projects.js +1 -29
  56. package/dist/commands/protocol/craft-evidence.js +4 -98
  57. package/dist/commands/protocol/craft-evidence.test.js +1 -20
  58. package/dist/commands/protocol/desktop-lifecycle-report.js +3 -57
  59. package/dist/commands/protocol/desktop-lifecycle-report.test.js +1 -32
  60. package/dist/commands/protocol/desktop-support.js +2 -32
  61. package/dist/commands/protocol/desktop-workflow.test.js +3 -35
  62. package/dist/commands/protocol/driver-registry.js +2 -71
  63. package/dist/commands/protocol/pantry-evidence.js +4 -144
  64. package/dist/commands/protocol/pantry-evidence.test.js +1 -29
  65. package/dist/commands/protocol/release-manifest.js +3 -102
  66. package/dist/commands/protocol/release-manifest.test.js +2 -34
  67. package/dist/commands/protocol/run-conformance.js +4 -346
  68. package/dist/commands/protocol/run-conformance.test.js +1 -52
  69. package/dist/commands/protocol/run-driver-contracts.js +4 -83
  70. package/dist/commands/protocol/run-driver-contracts.test.js +1 -18
  71. package/dist/commands/protocol/source-manifest.js +3 -113
  72. package/dist/commands/protocol/sync-suite.js +3 -136
  73. package/dist/commands/protocol/sync-suite.test.js +1 -44
  74. package/dist/commands/protocol.js +1 -60
  75. package/dist/commands/publish.js +8 -500
  76. package/dist/commands/queue.js +1 -248
  77. package/dist/commands/release.js +1 -42
  78. package/dist/commands/route.js +1 -21
  79. package/dist/commands/run-tool.js +1 -9
  80. package/dist/commands/saas.js +1 -25
  81. package/dist/commands/schedule.js +1 -61
  82. package/dist/commands/search.js +1 -84
  83. package/dist/commands/seed.js +1 -47
  84. package/dist/commands/serve.js +1 -55
  85. package/dist/commands/setup-ai.js +2 -121
  86. package/dist/commands/setup.js +2 -305
  87. package/dist/commands/share.js +1 -214
  88. package/dist/commands/sms.js +32 -319
  89. package/dist/commands/stacks.js +1 -72
  90. package/dist/commands/telemetry.js +1 -74
  91. package/dist/commands/test.js +1 -130
  92. package/dist/commands/tinker.js +1 -37
  93. package/dist/commands/types.js +1 -18
  94. package/dist/commands/upgrade.js +1 -98
  95. package/dist/commands/user.js +3 -84
  96. package/dist/commands/version.js +1 -14
  97. package/dist/config.js +1 -231
  98. package/dist/custom-cli.js +1 -23
  99. package/dist/database-preflight.js +1 -88
  100. package/dist/global-options.js +1 -4
  101. package/dist/index.js +1 -1
  102. package/dist/lazy-commands.js +1 -241
  103. package/dist/migrators/index.js +2 -62
  104. package/dist/migrators/laravel/index.js +1 -148
  105. package/dist/migrators/laravel/migrations.js +4 -231
  106. package/dist/migrators/laravel/models.js +8 -111
  107. package/dist/migrators/rails/index.js +1 -11
  108. package/dist/production-server.js +1 -257
  109. package/dist/project-setup.js +1 -36
  110. package/dist/serve-entry.js +1 -5
  111. package/dist/version-info.js +1 -5
  112. package/package.json +53 -46
package/dist/config.js CHANGED
@@ -1,231 +1 @@
1
- import { existsSync } from "node:fs";
2
- import { pathToFileURL } from "node:url";
3
- import { log } from "@stacksjs/cli";
4
- import { path as p } from "@stacksjs/path";
5
- export async function loadProjectDnsConfig(fallback) {
6
- const configPath = p.projectConfigPath("dns.ts");
7
- if (!existsSync(configPath))
8
- return fallback;
9
- const loaded = await import(`${pathToFileURL(configPath).href}?updated=${Date.now()}`);
10
- return loaded.default ?? loaded.dns ?? fallback;
11
- }
12
- export function validateConfig(config) {
13
- const errors = [];
14
- if (typeof config !== "object" || config === null) {
15
- errors.push({
16
- path: "config",
17
- message: "Config must be an object",
18
- value: config
19
- });
20
- return errors;
21
- }
22
- if (config.theme !== void 0) {
23
- const validThemes = ["default", "dracula", "nord", "solarized", "monokai"];
24
- if (typeof config.theme !== "string" || !validThemes.includes(config.theme))
25
- errors.push({
26
- path: "theme",
27
- message: `Theme must be one of: ${validThemes.join(", ")}`,
28
- value: config.theme
29
- });
30
- }
31
- if (config.emoji !== void 0 && typeof config.emoji !== "boolean")
32
- errors.push({
33
- path: "emoji",
34
- message: "Emoji must be a boolean",
35
- value: config.emoji
36
- });
37
- if (config.commands !== void 0)
38
- if (!Array.isArray(config.commands))
39
- errors.push({
40
- path: "commands",
41
- message: "Commands must be an array",
42
- value: config.commands
43
- });
44
- else
45
- config.commands.forEach((cmd, index) => {
46
- if (typeof cmd !== "function")
47
- errors.push({
48
- path: `commands[${index}]`,
49
- message: "Each command must be a function",
50
- value: cmd
51
- });
52
- });
53
- if (config.defaultFlags !== void 0)
54
- if (typeof config.defaultFlags !== "object" || config.defaultFlags === null)
55
- errors.push({
56
- path: "defaultFlags",
57
- message: "Default flags must be an object",
58
- value: config.defaultFlags
59
- });
60
- else {
61
- const flagKeys = ["verbose", "quiet", "debug"];
62
- for (const key of Object.keys(config.defaultFlags))
63
- if (!flagKeys.includes(key))
64
- errors.push({
65
- path: `defaultFlags.${key}`,
66
- message: `Unknown flag. Valid flags are: ${flagKeys.join(", ")}`,
67
- value: config.defaultFlags[key]
68
- });
69
- else if (typeof config.defaultFlags[key] !== "boolean")
70
- errors.push({
71
- path: `defaultFlags.${key}`,
72
- message: "Flag value must be a boolean",
73
- value: config.defaultFlags[key]
74
- });
75
- }
76
- if (config.aliases !== void 0) {
77
- if (typeof config.aliases !== "object" || config.aliases === null || Array.isArray(config.aliases))
78
- errors.push({
79
- path: "aliases",
80
- message: "Aliases must be an object mapping alias names to command names",
81
- value: config.aliases
82
- });
83
- else
84
- for (const [alias, command] of Object.entries(config.aliases))
85
- if (typeof command !== "string")
86
- errors.push({
87
- path: `aliases.${alias}`,
88
- message: "Alias target must be a string",
89
- value: command
90
- });
91
- }
92
- if (config.plugins !== void 0)
93
- if (!Array.isArray(config.plugins))
94
- errors.push({
95
- path: "plugins",
96
- message: "Plugins must be an array",
97
- value: config.plugins
98
- });
99
- else
100
- config.plugins.forEach((plugin, index) => {
101
- if (typeof plugin === "string")
102
- return;
103
- if (typeof plugin !== "object" || plugin === null) {
104
- errors.push({
105
- path: `plugins[${index}]`,
106
- message: "Each plugin must be an object or a string (module path)",
107
- value: plugin
108
- });
109
- return;
110
- }
111
- if (!plugin.name || typeof plugin.name !== "string")
112
- errors.push({
113
- path: `plugins[${index}].name`,
114
- message: "Plugin must have a name property of type string",
115
- value: plugin.name
116
- });
117
- if (!plugin.setup || typeof plugin.setup !== "function")
118
- errors.push({
119
- path: `plugins[${index}].setup`,
120
- message: "Plugin must have a setup function",
121
- value: plugin.setup
122
- });
123
- if (plugin.hooks !== void 0) {
124
- if (typeof plugin.hooks !== "object" || plugin.hooks === null)
125
- errors.push({
126
- path: `plugins[${index}].hooks`,
127
- message: "Plugin hooks must be an object",
128
- value: plugin.hooks
129
- });
130
- }
131
- });
132
- const validKeys = ["theme", "emoji", "commands", "defaultFlags", "aliases", "plugins"];
133
- for (const key of Object.keys(config))
134
- if (!validKeys.includes(key))
135
- errors.push({
136
- path: key,
137
- message: `Unknown configuration key. Valid keys are: ${validKeys.join(", ")}`,
138
- value: config[key]
139
- });
140
- return errors;
141
- }
142
- let cachedConfig = null;
143
- export async function loadBuddyConfig() {
144
- if (cachedConfig)
145
- return cachedConfig;
146
- const configPaths = [
147
- p.projectPath("buddy.config.ts"),
148
- p.projectPath("buddy.config.js"),
149
- p.projectPath(".buddy.config.ts"),
150
- p.projectPath(".buddy.config.js")
151
- ];
152
- for (const configPath of configPaths)
153
- if (existsSync(configPath))
154
- try {
155
- log.debug(`Loading buddy config from ${configPath}`);
156
- const configModule = await import(configPath), config = configModule.default || configModule, validationErrors = validateConfig(config);
157
- if (validationErrors.length > 0) {
158
- log.error("Invalid buddy.config.ts:");
159
- for (const error of validationErrors)
160
- log.error(` - ${error.path}: ${error.message}`);
161
- throw Error("Configuration validation failed");
162
- }
163
- cachedConfig = config;
164
- return config;
165
- } catch (error) {
166
- log.warn(`Failed to load buddy config from ${configPath}:`, error);
167
- }
168
- cachedConfig = {};
169
- return cachedConfig;
170
- }
171
- export async function loadPlugins(cli, config) {
172
- if (!config.plugins || config.plugins.length === 0)
173
- return;
174
- log.debug(`Loading ${config.plugins.length} plugin(s)`);
175
- for (const pluginConfig of config.plugins) {
176
- let plugin;
177
- if (typeof pluginConfig === "string")
178
- try {
179
- const pluginModule = await import(pluginConfig);
180
- plugin = pluginModule.default || pluginModule;
181
- } catch (error) {
182
- log.error(`Failed to load plugin from ${pluginConfig}:`, error);
183
- continue;
184
- }
185
- else
186
- plugin = pluginConfig;
187
- try {
188
- log.debug(`Initializing plugin: ${plugin.name}${plugin.version ? ` v${plugin.version}` : ""}`);
189
- await plugin.setup(cli);
190
- if (plugin.hooks) {
191
- if (plugin.hooks.beforeCommand)
192
- cli.on("command:*", async (command) => {
193
- if (plugin.hooks?.beforeCommand)
194
- await plugin.hooks.beforeCommand({ command });
195
- });
196
- if (plugin.hooks.afterCommand)
197
- cli.on("command:*", async (command) => {
198
- if (plugin.hooks?.afterCommand)
199
- await plugin.hooks.afterCommand({ command });
200
- });
201
- }
202
- log.debug(`Plugin ${plugin.name} initialized successfully`);
203
- } catch (error) {
204
- log.error(`Failed to initialize plugin ${plugin.name}:`, error);
205
- }
206
- }
207
- }
208
- export async function applyBuddyConfig(buddy) {
209
- const config = await loadBuddyConfig();
210
- if (config.emoji !== void 0 && buddy.options.noEmoji === void 0)
211
- buddy.useEmoji = config.emoji;
212
- if (config.defaultFlags) {
213
- if (config.defaultFlags.verbose && !buddy.isVerbose)
214
- buddy.isVerbose = !0;
215
- if (config.defaultFlags.quiet && !buddy.isQuiet)
216
- buddy.isQuiet = !0;
217
- if (config.defaultFlags.debug && !buddy.isDebug)
218
- buddy.isDebug = !0;
219
- }
220
- if (config.commands && Array.isArray(config.commands)) {
221
- for (const registerCommand of config.commands)
222
- if (typeof registerCommand === "function")
223
- registerCommand(buddy);
224
- }
225
- if (config.aliases)
226
- for (const [alias, command] of Object.entries(config.aliases)) {
227
- const targetCommand = buddy.commands.find((cmd) => cmd.name === command);
228
- if (targetCommand && !targetCommand.aliasNames.includes(alias))
229
- targetCommand.aliasNames.push(alias);
230
- }
231
- }
1
+ import{existsSync}from"node:fs";import{pathToFileURL}from"node:url";import{log}from"@stacksjs/cli";import{path as p}from"@stacksjs/path";export async function loadProjectDnsConfig(fallback){const configPath=p.projectConfigPath("dns.ts");if(!existsSync(configPath))return fallback;const loaded=await import(`${pathToFileURL(configPath).href}?updated=${Date.now()}`);return loaded.default??loaded.dns??fallback}export function validateConfig(config){const errors=[];if(typeof config!=="object"||config===null){errors.push({path:"config",message:"Config must be an object",value:config});return errors}if(config.theme!==void 0){const validThemes=["default","dracula","nord","solarized","monokai"];if(typeof config.theme!=="string"||!validThemes.includes(config.theme))errors.push({path:"theme",message:`Theme must be one of: ${validThemes.join(", ")}`,value:config.theme})}if(config.emoji!==void 0&&typeof config.emoji!=="boolean")errors.push({path:"emoji",message:"Emoji must be a boolean",value:config.emoji});if(config.commands!==void 0)if(!Array.isArray(config.commands))errors.push({path:"commands",message:"Commands must be an array",value:config.commands});else config.commands.forEach((cmd,index)=>{if(typeof cmd!=="function")errors.push({path:`commands[${index}]`,message:"Each command must be a function",value:cmd})});if(config.defaultFlags!==void 0)if(typeof config.defaultFlags!=="object"||config.defaultFlags===null)errors.push({path:"defaultFlags",message:"Default flags must be an object",value:config.defaultFlags});else{const flagKeys=["verbose","quiet","debug"];for(const key of Object.keys(config.defaultFlags))if(!flagKeys.includes(key))errors.push({path:`defaultFlags.${key}`,message:`Unknown flag. Valid flags are: ${flagKeys.join(", ")}`,value:config.defaultFlags[key]});else if(typeof config.defaultFlags[key]!=="boolean")errors.push({path:`defaultFlags.${key}`,message:"Flag value must be a boolean",value:config.defaultFlags[key]})}if(config.aliases!==void 0){if(typeof config.aliases!=="object"||config.aliases===null||Array.isArray(config.aliases))errors.push({path:"aliases",message:"Aliases must be an object mapping alias names to command names",value:config.aliases});else for(const[alias,command]of Object.entries(config.aliases))if(typeof command!=="string")errors.push({path:`aliases.${alias}`,message:"Alias target must be a string",value:command})}if(config.plugins!==void 0)if(!Array.isArray(config.plugins))errors.push({path:"plugins",message:"Plugins must be an array",value:config.plugins});else config.plugins.forEach((plugin,index)=>{if(typeof plugin==="string")return;if(typeof plugin!=="object"||plugin===null){errors.push({path:`plugins[${index}]`,message:"Each plugin must be an object or a string (module path)",value:plugin});return}if(!plugin.name||typeof plugin.name!=="string")errors.push({path:`plugins[${index}].name`,message:"Plugin must have a name property of type string",value:plugin.name});if(!plugin.setup||typeof plugin.setup!=="function")errors.push({path:`plugins[${index}].setup`,message:"Plugin must have a setup function",value:plugin.setup});if(plugin.hooks!==void 0){if(typeof plugin.hooks!=="object"||plugin.hooks===null)errors.push({path:`plugins[${index}].hooks`,message:"Plugin hooks must be an object",value:plugin.hooks})}});const validKeys=["theme","emoji","commands","defaultFlags","aliases","plugins"];for(const key of Object.keys(config))if(!validKeys.includes(key))errors.push({path:key,message:`Unknown configuration key. Valid keys are: ${validKeys.join(", ")}`,value:config[key]});return errors}let cachedConfig=null;export async function loadBuddyConfig(){if(cachedConfig)return cachedConfig;const configPaths=[p.projectPath("buddy.config.ts"),p.projectPath("buddy.config.js"),p.projectPath(".buddy.config.ts"),p.projectPath(".buddy.config.js")];for(const configPath of configPaths)if(existsSync(configPath))try{log.debug(`Loading buddy config from ${configPath}`);const configModule=await import(configPath),config=configModule.default||configModule,validationErrors=validateConfig(config);if(validationErrors.length>0){log.error("Invalid buddy.config.ts:");for(const error of validationErrors)log.error(` - ${error.path}: ${error.message}`);throw Error("Configuration validation failed")}cachedConfig=config;return config}catch(error){log.warn(`Failed to load buddy config from ${configPath}:`,error)}cachedConfig={};return cachedConfig}export async function loadPlugins(cli,config){if(!config.plugins||config.plugins.length===0)return;log.debug(`Loading ${config.plugins.length} plugin(s)`);for(const pluginConfig of config.plugins){let plugin;if(typeof pluginConfig==="string")try{const pluginModule=await import(pluginConfig);plugin=pluginModule.default||pluginModule}catch(error){log.error(`Failed to load plugin from ${pluginConfig}:`,error);continue}else plugin=pluginConfig;try{log.debug(`Initializing plugin: ${plugin.name}${plugin.version?` v${plugin.version}`:""}`);await plugin.setup(cli);if(plugin.hooks){if(plugin.hooks.beforeCommand)cli.on("command:*",async(command)=>{if(plugin.hooks?.beforeCommand)await plugin.hooks.beforeCommand({command})});if(plugin.hooks.afterCommand)cli.on("command:*",async(command)=>{if(plugin.hooks?.afterCommand)await plugin.hooks.afterCommand({command})})}log.debug(`Plugin ${plugin.name} initialized successfully`)}catch(error){log.error(`Failed to initialize plugin ${plugin.name}:`,error)}}}export async function applyBuddyConfig(buddy){const config=await loadBuddyConfig();if(config.emoji!==void 0&&buddy.options.noEmoji===void 0)buddy.useEmoji=config.emoji;if(config.defaultFlags){if(config.defaultFlags.verbose&&!buddy.isVerbose)buddy.isVerbose=!0;if(config.defaultFlags.quiet&&!buddy.isQuiet)buddy.isQuiet=!0;if(config.defaultFlags.debug&&!buddy.isDebug)buddy.isDebug=!0}if(config.commands&&Array.isArray(config.commands)){for(const registerCommand of config.commands)if(typeof registerCommand==="function")registerCommand(buddy)}if(config.aliases)for(const[alias,command]of Object.entries(config.aliases)){const targetCommand=buddy.commands.find((cmd)=>cmd.name===command);if(targetCommand&&!targetCommand.aliasNames.includes(alias))targetCommand.aliasNames.push(alias)}}
@@ -1,23 +1 @@
1
- import process from "node:process";
2
- import { cli } from "@stacksjs/cli";
3
- import { config } from "@stacksjs/config";
4
- import { handleError } from "@stacksjs/error-handling";
5
- import { path as p } from "@stacksjs/path";
6
- import { fs } from "@stacksjs/storage";
7
- process.on("uncaughtException", handleError);
8
- process.on("unhandledRejection", handleError);
9
- async function main() {
10
- const buddy = cli(config.cli.name);
11
- if (!fs.existsSync(p.projectPath(config.cli.command)))
12
- fs.writeFileSync(p.projectPath(config.cli.command), "import('./storage/framework/core/buddy/src/custom-cli')");
13
- const commandsDir = p.appPath("Commands"), commandFiles = fs.readdirSync(commandsDir).filter((file) => file.endsWith(".ts"));
14
- for (const file of commandFiles) {
15
- const dynamicImport = await import(`${commandsDir}/${file}`);
16
- if (typeof dynamicImport.default === "function")
17
- dynamicImport.default(buddy);
18
- else
19
- console.error(`Expected a default export function in ${file}, but got:`, dynamicImport.default);
20
- }
21
- buddy.parse();
22
- }
23
- await main();
1
+ import process from"node:process";import{cli}from"@stacksjs/cli";import{config}from"@stacksjs/config";import{handleError}from"@stacksjs/error-handling";import{path as p}from"@stacksjs/path";import{fs}from"@stacksjs/storage";process.on("uncaughtException",handleError);process.on("unhandledRejection",handleError);async function main(){const buddy=cli(config.cli.name);if(!fs.existsSync(p.projectPath(config.cli.command)))fs.writeFileSync(p.projectPath(config.cli.command),"import('./storage/framework/core/buddy/src/custom-cli')");const commandsDir=p.appPath("Commands"),commandFiles=fs.readdirSync(commandsDir).filter((file)=>file.endsWith(".ts"));for(const file of commandFiles){const dynamicImport=await import(`${commandsDir}/${file}`);if(typeof dynamicImport.default==="function")dynamicImport.default(buddy);else console.error(`Expected a default export function in ${file}, but got:`,dynamicImport.default)}buddy.parse()}await main();
@@ -1,88 +1 @@
1
- import process from "node:process";
2
- import { confirmOrNull, log } from "@stacksjs/cli";
3
- import { ExitCode } from "@stacksjs/types";
4
- export function canPromptInteractively() {
5
- if (process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.BUILD_NUMBER || process.env.RUN_ID)
6
- return !1;
7
- return Boolean(process.stdin.isTTY && process.stdout.isTTY);
8
- }
9
- export function resolveCreatePolicy() {
10
- const value = String(process.env.DB_CREATE_DATABASE || "").toLowerCase();
11
- if (value === "always" || value === "true" || value === "1")
12
- return "always";
13
- if (value === "never" || value === "false" || value === "0")
14
- return "never";
15
- return "prompt";
16
- }
17
- function decide(create) {
18
- process.env.STACKS_CREATE_DATABASE = create ? "1" : "0";
19
- }
20
- const UNANSWERED = Symbol("unanswered");
21
- async function confirmWithTimeout(message, timeoutMs) {
22
- let timer;
23
- try {
24
- return await Promise.race([
25
- confirmOrNull({ message, initial: !0 }).then((v) => v === null ? UNANSWERED : v),
26
- new Promise((resolve) => {
27
- timer = setTimeout(() => resolve(UNANSWERED), timeoutMs);
28
- })
29
- ]);
30
- } finally {
31
- if (timer)
32
- clearTimeout(timer);
33
- }
34
- }
35
- export async function preflightDatabase(options = {}) {
36
- const commandName = options.command || "migrate", {
37
- canCreateDatabases,
38
- describeTarget,
39
- manualCreateHint,
40
- probeTargetDatabase,
41
- resolveConnectionTarget
42
- } = await import("@stacksjs/database"), target = resolveConnectionTarget();
43
- if (!target)
44
- return;
45
- const probe = await probeTargetDatabase(target);
46
- if (probe.ok || probe.kind !== "missing-database")
47
- return;
48
- const where = describeTarget(target), standing = resolveCreatePolicy();
49
- if (standing === "never") {
50
- decide(!1);
51
- return;
52
- }
53
- if (options.createDatabase || standing === "always") {
54
- decide(!0);
55
- return;
56
- }
57
- if (!canPromptInteractively()) {
58
- log.syncError(`The database "${target.database}" does not exist on ${where}.`);
59
- log.syncError("Refusing to create it in a non-interactive shell.");
60
- log.syncError(" Create it ahead of time, re-run with --create-database, or set DB_CREATE_DATABASE=always.");
61
- log.syncError(` ${manualCreateHint(target)}`);
62
- process.exit(ExitCode.FatalError);
63
- }
64
- if (await canCreateDatabases(target) === !1) {
65
- log.syncError(`The database "${target.database}" does not exist on ${where}.`);
66
- log.syncError(`The user "${target.username}" is not allowed to create databases, so I cannot create it for you.`);
67
- log.syncError(` Grant it with: ALTER ROLE "${target.username}" CREATEDB;`);
68
- log.syncError(` Or create the database yourself with: ${manualCreateHint(target)}`);
69
- process.exit(ExitCode.FatalError);
70
- }
71
- log.warn(`The database "${target.database}" does not exist on ${where}.`);
72
- await log.flush();
73
- const timeoutMs = Number(process.env.DB_CREATE_DATABASE_TIMEOUT_MS || 120000), answer = await confirmWithTimeout("Would you like to create it?", timeoutMs);
74
- if (answer === UNANSWERED) {
75
- log.syncError(`No answer after ${Math.round(timeoutMs / 1000)}s, so nothing was created.`);
76
- log.syncError(" Re-run with --create-database, or set DB_CREATE_DATABASE=always, to skip this question.");
77
- log.syncError(` ${manualCreateHint(target)}`);
78
- process.exit(ExitCode.FatalError);
79
- }
80
- if (!answer) {
81
- decide(!1);
82
- log.info("Nothing was changed. Create it yourself with:");
83
- log.info(` ${manualCreateHint(target)}`);
84
- log.info(`Then re-run \`buddy ${commandName}\`, or re-run with --create-database to skip this question.`);
85
- process.exit(ExitCode.Success);
86
- }
87
- decide(!0);
88
- }
1
+ import process from"node:process";import{confirmOrNull,log}from"@stacksjs/cli";import{ExitCode}from"@stacksjs/types";export function canPromptInteractively(){if(process.env.CI||process.env.CONTINUOUS_INTEGRATION||process.env.BUILD_NUMBER||process.env.RUN_ID)return!1;return Boolean(process.stdin.isTTY&&process.stdout.isTTY)}export function resolveCreatePolicy(){const value=String(process.env.DB_CREATE_DATABASE||"").toLowerCase();if(value==="always"||value==="true"||value==="1")return"always";if(value==="never"||value==="false"||value==="0")return"never";return"prompt"}function decide(create){process.env.STACKS_CREATE_DATABASE=create?"1":"0"}const UNANSWERED=Symbol("unanswered");async function confirmWithTimeout(message,timeoutMs){let timer;try{return await Promise.race([confirmOrNull({message,initial:!0}).then((v)=>v===null?UNANSWERED:v),new Promise((resolve)=>{timer=setTimeout(()=>resolve(UNANSWERED),timeoutMs)})])}finally{if(timer)clearTimeout(timer)}}export async function preflightDatabase(options={}){const commandName=options.command||"migrate",{canCreateDatabases,describeTarget,manualCreateHint,probeTargetDatabase,resolveConnectionTarget}=await import("@stacksjs/database"),target=resolveConnectionTarget();if(!target)return;const probe=await probeTargetDatabase(target);if(probe.ok||probe.kind!=="missing-database")return;const where=describeTarget(target),standing=resolveCreatePolicy();if(standing==="never"){decide(!1);return}if(options.createDatabase||standing==="always"){decide(!0);return}if(!canPromptInteractively()){log.syncError(`The database "${target.database}" does not exist on ${where}.`);log.syncError("Refusing to create it in a non-interactive shell.");log.syncError(" Create it ahead of time, re-run with --create-database, or set DB_CREATE_DATABASE=always.");log.syncError(` ${manualCreateHint(target)}`);process.exit(ExitCode.FatalError)}if(await canCreateDatabases(target)===!1){log.syncError(`The database "${target.database}" does not exist on ${where}.`);log.syncError(`The user "${target.username}" is not allowed to create databases, so I cannot create it for you.`);log.syncError(` Grant it with: ALTER ROLE "${target.username}" CREATEDB;`);log.syncError(` Or create the database yourself with: ${manualCreateHint(target)}`);process.exit(ExitCode.FatalError)}log.warn(`The database "${target.database}" does not exist on ${where}.`);await log.flush();const timeoutMs=Number(process.env.DB_CREATE_DATABASE_TIMEOUT_MS||120000),answer=await confirmWithTimeout("Would you like to create it?",timeoutMs);if(answer===UNANSWERED){log.syncError(`No answer after ${Math.round(timeoutMs/1000)}s, so nothing was created.`);log.syncError(" Re-run with --create-database, or set DB_CREATE_DATABASE=always, to skip this question.");log.syncError(` ${manualCreateHint(target)}`);process.exit(ExitCode.FatalError)}if(!answer){decide(!1);log.info("Nothing was changed. Create it yourself with:");log.info(` ${manualCreateHint(target)}`);log.info(`Then re-run \`buddy ${commandName}\`, or re-run with --create-database to skip this question.`);process.exit(ExitCode.Success)}decide(!0)}
@@ -1,4 +1 @@
1
- import { versionDescriptor } from "./version-info";
2
- export function registerGlobalOptions(buddy, options = {}) {
3
- (options.version === !1 ? buddy : buddy.version(versionDescriptor, "-V, --version")).option("-v, --verbose", "Enable verbose output").option("-q, --quiet", "Suppress non-essential output").option("--debug", "Enable debug output and stack traces").option("--no-interaction", "Do not ask interactive questions").option("--env <environment>", "Target an environment").option("--dry-run", "Preview actions without making changes").option("--force", "Skip confirmation prompts").option("--no-emoji", "Disable emoji in output").option("--no-cache", "Disable command metadata caching");
4
- }
1
+ import{versionDescriptor}from"./version-info";export function registerGlobalOptions(buddy,options={}){(options.version===!1?buddy:buddy.version(versionDescriptor,"-V, --version")).option("-v, --verbose","Enable verbose output").option("-q, --quiet","Suppress non-essential output").option("--debug","Enable debug output and stack traces").option("--no-interaction","Do not ask interactive questions").option("--env <environment>","Target an environment").option("--dry-run","Preview actions without making changes").option("--force","Skip confirmation prompts").option("--no-emoji","Disable emoji in output").option("--no-cache","Disable command metadata caching")}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export * from "./commands";
1
+ export*from"./commands";