@stacksjs/buddy 0.53.1 → 0.56.3

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.
@@ -0,0 +1,839 @@
1
+ import { ExitCode, Action } from '@stacksjs/types';
2
+ import { prompt, intro, log, outro, green, bold, runCommand, cyan, italic, dim } from '@stacksjs/cli';
3
+ import { runAction } from '@stacksjs/actions';
4
+ import { invoke } from '@stacksjs/actions/commit';
5
+ import { useOnline } from '@stacksjs/utils';
6
+ import * as storage from '@stacksjs/storage';
7
+ import { isFolder } from '@stacksjs/storage';
8
+ import { resolve, frameworkPath, projectPath } from '@stacksjs/path';
9
+ import { components, functions, pages, desktop } from '@stacksjs/actions/dev';
10
+ import { componentExample, webComponentExample, invoke as invoke$1 } from '@stacksjs/actions/examples';
11
+ import { invoke as invoke$2, types, libEntries, vueCompat, webTypes, vsCodeCustomData, ideHelpers, componentMeta, migrations } from '@stacksjs/actions/generate';
12
+ import { invoke as invoke$3, component, database, factory, page, fx, language, createNotification, stack, createModel } from '@stacksjs/actions/make';
13
+ import { invoke as invoke$4 } from '@stacksjs/actions/preinstall';
14
+ import { log as log$1 } from '@stacksjs/logging';
15
+
16
+ async function build(buddy) {
17
+ const descriptions = {
18
+ components: "Build your component library",
19
+ vueComponents: "Build your Vue component library",
20
+ webComponents: "Build your framework agnostic web component library",
21
+ elements: "An alias to the -w flag",
22
+ functions: "Build your function library",
23
+ pages: "Build your SSG views",
24
+ docs: "Build your documentation site",
25
+ stacks: "Build Stacks framework",
26
+ select: "What are you trying to build?",
27
+ verbose: "Enable verbose output"
28
+ };
29
+ buddy.command("build", "Automagically build any of your libraries/packages for production use. Select any of the following packages").option("-c, --components", descriptions.components).option("-v, --vue-components", descriptions.vueComponents).option("-w, --web-components", descriptions.webComponents).option("-e, --elements", descriptions.elements).option("-f, --functions", descriptions.functions).option("-p, --views", descriptions.pages).option("-d, --docs", descriptions.docs).option("-s, --stacks", descriptions.stacks, { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
30
+ if (hasNoOptions$4(options)) {
31
+ let answers = await prompt.require().multiselect(descriptions.select, {
32
+ options: [
33
+ { label: "Components", value: "components" },
34
+ // { label: 'Vue Components', value: 'vue-components' },
35
+ // { label: 'Web Components', value: 'web-components' },
36
+ { label: "Functions", value: "functions" },
37
+ { label: "Pages", value: "pages" },
38
+ { label: "Documentation", value: "docs" }
39
+ ]
40
+ });
41
+ if (answers !== null)
42
+ process.exit(ExitCode.InvalidArgument);
43
+ if (isString(answers))
44
+ answers = [answers];
45
+ options = answers.reduce((a, v) => ({ ...a, [v]: true }), {});
46
+ }
47
+ console.log("options", options);
48
+ await runAction(Action.BuildStacks, options);
49
+ process.exit(ExitCode.Success);
50
+ });
51
+ buddy.command("build:components", "Automagically build component libraries for production use & npm/CDN distribution").option("-c, --components", descriptions.components, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
52
+ await runAction(Action.BuildComponentLibs, options);
53
+ });
54
+ buddy.command("build:cli", "Automagically build the CLI").option("-c, --components", descriptions.components, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
55
+ await runAction(Action.BuildCli, options);
56
+ });
57
+ buddy.command("build:functions", "Automagically build function library for npm/CDN distribution").option("-f, --functions", descriptions.functions, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
58
+ await runAction(Action.BuildFunctionLib, options);
59
+ });
60
+ buddy.command("build:vue-components", "Automagically build Vue component library for npm/CDN distribution").option("-v, --vue-components", descriptions.vueComponents, { default: true }).option("--verbose", descriptions.verbose, { default: false }).alias("build:vue").action(async (options) => {
61
+ await runAction(Action.BuildVueComponentLib, options);
62
+ });
63
+ buddy.command("build:web-components", "Automagically build Web Component library for npm/CDN distribution").option("-w, --web-components", descriptions.webComponents, { default: true }).option("--verbose", descriptions.verbose, { default: false }).alias("build:elements").alias("build:wc").action(async (options) => {
64
+ await runAction(Action.BuildWebComponentLib, options);
65
+ });
66
+ buddy.command("build:docs", "Automagically build your documentation site.").option("-d, --docs", descriptions.docs, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
67
+ await runAction(Action.BuildDocs, options);
68
+ });
69
+ buddy.command("build:core", "Automagically build the Stacks core.").option("--verbose", descriptions.verbose, { default: true }).action(async (options) => {
70
+ const startTime = await intro("buddy build:core");
71
+ const result = await runAction(Action.BuildCore, options);
72
+ if (result.isErr()) {
73
+ log.error("Failed to build the Stacks core.", result.error);
74
+ process.exit();
75
+ }
76
+ outro("Stacks core built successfully", { startTime, useSeconds: true });
77
+ });
78
+ buddy.command("build:stacks", "Build the Stacks framework.").option("-s, --stacks", descriptions.stacks, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
79
+ const startTime = await intro("buddy build:stacks");
80
+ const result = await runAction(Action.BuildStacks, options);
81
+ if (result.isErr()) {
82
+ log.error("Failed to build Stacks.", result.error);
83
+ process.exit();
84
+ }
85
+ outro("Stacks built successfully", { startTime, useSeconds: true });
86
+ });
87
+ }
88
+ function hasNoOptions$4(options) {
89
+ return !options.components && !options.vueComponents && !options.webComponents && !options.elements && !options.functions && !options.pages && !options.docs && !options.stacks;
90
+ }
91
+
92
+ async function changelog(buddy) {
93
+ const descriptions = {
94
+ changelog: "Create a CHANGELOG.md file",
95
+ quiet: "Minimal output",
96
+ verbose: "Enable verbose output"
97
+ };
98
+ buddy.command("changelog", descriptions.changelog).option("--quiet", descriptions.quiet, { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
99
+ const perf = await intro("buddy changelog");
100
+ const result = await runAction(Action.Changelog, options);
101
+ if (result.isErr()) {
102
+ outro("While running the changelog command, there was an issue", { ...options, startTime: perf, useSeconds: true, isError: true }, result.error);
103
+ process.exit();
104
+ }
105
+ outro("Generated the CHANGELOG.md file", { ...options, startTime: perf, useSeconds: true, type: "info" });
106
+ process.exit(ExitCode.Success);
107
+ });
108
+ }
109
+
110
+ async function clean(buddy) {
111
+ const descriptions = {
112
+ clean: "Removes all node_modules & lock files",
113
+ verbose: "Enable verbose output"
114
+ };
115
+ buddy.command("clean", descriptions.clean).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
116
+ const perf = await intro("buddy clean");
117
+ const result = await runAction(Action.Clean, { ...options, verbose: true });
118
+ if (result.isErr()) {
119
+ outro("While running the clean command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
120
+ process.exit(ExitCode.FatalError);
121
+ }
122
+ outro("Cleaned up", { startTime: perf, useSeconds: true });
123
+ process.exit(ExitCode.Success);
124
+ });
125
+ }
126
+
127
+ async function commit(buddy) {
128
+ const descriptions = {
129
+ commit: "Commit your stashed changes",
130
+ verbose: "Enable verbose output"
131
+ };
132
+ buddy.command("commit", descriptions.commit).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
133
+ await invoke(options);
134
+ });
135
+ }
136
+
137
+ async function create(buddy) {
138
+ const descriptions = {
139
+ command: "Create a new Stacks project",
140
+ ui: "Are you building a UI?",
141
+ components: "Are you building UI components?",
142
+ webComponents: "Automagically built optimized custom elements/web components?",
143
+ vue: "Automagically built a Vue component library?",
144
+ pages: "How about views/views?",
145
+ functions: "Are you developing functions/composables?",
146
+ api: "Are you building an API?",
147
+ database: "Do you need a database?",
148
+ verbose: "Enable verbose output"
149
+ };
150
+ buddy.command("new <name>", descriptions.command).option("-u, --ui", descriptions.ui, { default: true }).option("-c, --components", descriptions.components, { default: true }).option("-w, --web-components", descriptions.webComponents, { default: true }).option("-v, --vue", descriptions.vue, { default: true }).option("-p, --views", descriptions.pages, { default: true }).option("-f, --functions", descriptions.functions, { default: true }).option("-a, --api", descriptions.api, { default: true }).option("-d, --database", descriptions.database, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
151
+ const startTime = await intro("stacks new");
152
+ const name = options.name;
153
+ const path = resolve(process.cwd(), name);
154
+ await isFolderCheck(path);
155
+ await onlineCheck();
156
+ const result = await download(name, path, options);
157
+ if (result.isErr()) {
158
+ log.error(result.error);
159
+ process.exit(ExitCode.FatalError);
160
+ }
161
+ await ensureEnv(path, options);
162
+ await install(path, options);
163
+ if (startTime) {
164
+ const time = performance.now() - startTime;
165
+ log.success(green(`Done in ${time}ms`));
166
+ }
167
+ log.info(bold("Welcome to the Stacks Framework! \u269B\uFE0F"));
168
+ log.info("To learn more, visit https://stacksjs.dev");
169
+ process.exit(ExitCode.Success);
170
+ });
171
+ }
172
+ async function isFolderCheck(path) {
173
+ if (await isFolder(path)) {
174
+ log.error(`Path ${path} already exists`);
175
+ process.exit(ExitCode.FatalError);
176
+ }
177
+ }
178
+ async function onlineCheck() {
179
+ const online = useOnline();
180
+ if (!online) {
181
+ log.info("It appears you are disconnected from the internet.");
182
+ log.info("The Stacks setup requires a brief internet connection for setup.");
183
+ log.info("For instance, it installs your dependencies from.");
184
+ process.exit(ExitCode.FatalError);
185
+ }
186
+ }
187
+ async function download(name, path, options) {
188
+ log.info("Setting up your stack.");
189
+ const result = await runCommand(`giget stacks ${name}`, options);
190
+ log.success(`Successfully scaffolded your project at ${cyan(path)}`);
191
+ return result;
192
+ }
193
+ async function ensureEnv(path, options) {
194
+ log.info("Ensuring your environment is ready...");
195
+ await runCommand("fnm use", { ...options, cwd: path });
196
+ log.success("Environment is ready");
197
+ }
198
+ async function install(path, options) {
199
+ log.info("Installing & setting up Stacks");
200
+ let result = await runCommand("pnpm install", { ...options, cwd: path });
201
+ if (result.isErr()) {
202
+ log.error(result.error);
203
+ process.exit();
204
+ }
205
+ result = await runCommand("cp .env.example .env", { ...options, cwd: path });
206
+ if (result.isErr()) {
207
+ log.error(result.error);
208
+ process.exit(ExitCode.FatalError);
209
+ }
210
+ await runAction(Action.KeyGenerate, { ...options, cwd: path });
211
+ result = await runCommand("git init", { ...options, cwd: path });
212
+ if (result.isErr()) {
213
+ log.error(result.error);
214
+ process.exit(ExitCode.FatalError);
215
+ }
216
+ log.success("Installed & set-up \u{1F680}");
217
+ }
218
+
219
+ async function dev(buddy) {
220
+ const descriptions = {
221
+ components: "Start the Components development server",
222
+ desktop: "Start the Desktop development server",
223
+ functions: "Start the Functions development server",
224
+ docs: "Start the Documentation development server",
225
+ pages: "Start the Pages development server",
226
+ select: "Which development server are you trying to start?",
227
+ verbose: "Enable verbose output"
228
+ };
229
+ buddy.command("dev", "Start the development server for any of the following").option("-c, --components", descriptions.components).option("-f, --functions", descriptions.functions).option("-d, --docs", descriptions.docs).option("-p, --views", descriptions.pages).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
230
+ if (hasNoOptions$3(options)) {
231
+ const answer = await prompt.require().select(descriptions.select, {
232
+ options: [
233
+ { value: "all", label: "All" },
234
+ { value: "pages", label: "Frontend" },
235
+ { value: "api", label: "Backend" },
236
+ { value: "desktop", label: "Desktop" },
237
+ { value: "components", label: "Components" },
238
+ { value: "functions", label: "Functions" },
239
+ { value: "docs", label: "Documentation" }
240
+ ]
241
+ });
242
+ if (answer === "components")
243
+ await components(options);
244
+ else if (answer === "functions")
245
+ await functions(options);
246
+ else if (answer === "pages")
247
+ await pages(options);
248
+ else
249
+ process.exit(ExitCode.InvalidArgument);
250
+ } else {
251
+ if (options.components)
252
+ await components(options);
253
+ else if (options.functions)
254
+ await functions(options);
255
+ else if (options.pages)
256
+ await pages(options);
257
+ }
258
+ process.exit(ExitCode.Success);
259
+ });
260
+ buddy.command("dev:components", descriptions.components).action(async (options) => {
261
+ const perf = await intro("buddy dev:components");
262
+ const result = await runAction(Action.DevComponents, { ...options, verbose: true });
263
+ if (options.verbose)
264
+ log.info("runAction result is", result);
265
+ if (result.isErr()) {
266
+ outro("While running the dev:components command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error ?? void 0);
267
+ process.exit();
268
+ }
269
+ console.log("");
270
+ outro("Exited", { startTime: perf, useSeconds: true });
271
+ process.exit(ExitCode.Success);
272
+ });
273
+ buddy.command("dev:docs", descriptions.docs).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
274
+ const perf = await intro("buddy dev:docs");
275
+ const result = await runAction(Action.DevDocs, { ...options, verbose: true });
276
+ if (Array.isArray(result)) ; else if (result.isErr()) {
277
+ outro("While running the dev:components command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error ?? void 0);
278
+ process.exit();
279
+ }
280
+ outro("Finished running dev:docs.", { startTime: perf, useSeconds: true });
281
+ process.exit(ExitCode.Success);
282
+ });
283
+ buddy.command("dev:desktop", descriptions.desktop).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
284
+ await desktop(options);
285
+ });
286
+ buddy.command("dev:functions", descriptions.functions).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
287
+ await functions(options);
288
+ });
289
+ buddy.command("dev:views", descriptions.pages).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
290
+ await pages(options);
291
+ });
292
+ }
293
+ function hasNoOptions$3(options) {
294
+ return !options.components && !options.all && !options.docs && !options.functions && !options.pages;
295
+ }
296
+
297
+ async function example(buddy) {
298
+ const descriptions = {
299
+ example: "Which example do you want to see?",
300
+ components: "Test your libraries against your built bundle",
301
+ vue: "Test your Vue component library",
302
+ webComponents: "Test your web component library",
303
+ select: "Which example are you trying to view?",
304
+ verbose: "Enable verbose output"
305
+ };
306
+ buddy.command("example", descriptions.example).option("-c, --components", descriptions.components).option("-v, --vue", descriptions.vue).option("-w, --web-components", descriptions.webComponents).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
307
+ const answer = await prompt.require().select(descriptions.select, {
308
+ options: [
309
+ { value: "components", label: "Vue Components" },
310
+ { value: "web-components", label: "Web Components" }
311
+ ]
312
+ });
313
+ if (answer === "components")
314
+ await componentExample(options);
315
+ else if (answer === "web-components")
316
+ await webComponentExample(options);
317
+ else
318
+ process.exit(ExitCode.InvalidArgument);
319
+ await invoke$1(options);
320
+ process.exit(ExitCode.Success);
321
+ });
322
+ buddy.command("example:vue", descriptions.vue).option("-v, --vue", descriptions.verbose, { default: true }).option("--verbose", descriptions.verbose, { default: false }).alias("example:components").action(async (options) => {
323
+ await invoke$1(options);
324
+ });
325
+ buddy.command("example:web-components", "Test your Web Component library.").option("-w, --web-components", descriptions.verbose, { default: true }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
326
+ await invoke$1(options);
327
+ });
328
+ }
329
+
330
+ async function fresh(buddy) {
331
+ const descriptions = {
332
+ fresh: "Reinstalls your npm dependencies",
333
+ verbose: "Enable verbose output"
334
+ };
335
+ buddy.command("fresh", descriptions.fresh).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
336
+ const perf = await intro("buddy fresh");
337
+ const result = await runAction(Action.Fresh, { ...options, verbose: true });
338
+ if (result.isErr()) {
339
+ outro("While running the `fresh` command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
340
+ process.exit(ExitCode.FatalError);
341
+ }
342
+ outro("Freshly reinstalled your dependencies", { startTime: perf, useSeconds: true });
343
+ process.exit(ExitCode.Success);
344
+ });
345
+ }
346
+
347
+ async function generate(buddy) {
348
+ const descriptions = {
349
+ command: "Automagically build any of your libraries/packages for production use. Select any of the following packages",
350
+ types: "Generate your TypeScript types",
351
+ entries: "Generate your function & component library entry points",
352
+ webTypes: "Generate web-types.json for IDEs",
353
+ customData: "Generate VS Code custom data (custom-elements.json) for IDEs",
354
+ ideHelpers: "Generate IDE helpers",
355
+ vueCompat: "Generate Vue 2 & 3 compatibility",
356
+ componentMeta: "Generate component meta information",
357
+ select: "What are you trying to generate?",
358
+ verbose: "Enable verbose output"
359
+ };
360
+ buddy.command("generate", descriptions.command).option("-t, --types", descriptions.types).option("-e, --entries", descriptions.entries).option("-w, --web-types", descriptions.webTypes).option("-c, --custom-data", descriptions.customData).option("-i, --ide-helpers", descriptions.ideHelpers).option("-v, --vue-compatibility", descriptions.vueCompat).option("-c, --component-meta", descriptions.componentMeta).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
361
+ if (hasNoOptions$2(options)) {
362
+ let answers = await prompt.require().multiselect(descriptions.select, {
363
+ options: [
364
+ { label: "1.) TypeScript Types", value: "types" },
365
+ { label: "2.) Library Entry Points", value: "entries" },
366
+ { label: "3.) Web Types", value: "web-types" },
367
+ { label: "4.) VS Code Custom Data", value: "custom-data" },
368
+ { label: "5.) IDE Helpers", value: "ide-helpers" },
369
+ { label: "6.) Vue 2 & 3 Compatibility", value: "vue-compatibility" },
370
+ { label: "7.) Component Meta", value: "component-meta" }
371
+ ]
372
+ });
373
+ if (isString(answers))
374
+ answers = [answers];
375
+ options = answers.reduce((a, v) => ({ ...a, [v]: true }), {});
376
+ }
377
+ await invoke$2(options);
378
+ process.exit(ExitCode.Success);
379
+ });
380
+ buddy.command("generate:types", descriptions.types).option("--verbose", descriptions.verbose, { default: false }).alias("types:generate").action(async (options) => {
381
+ await types(options);
382
+ });
383
+ buddy.command("generate:entries", descriptions.entries).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
384
+ await libEntries(options);
385
+ });
386
+ buddy.command("generate:vue-compatibility", descriptions.vueCompat).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
387
+ await vueCompat(options);
388
+ });
389
+ buddy.command("generate:web-types", descriptions.webTypes).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
390
+ await webTypes(options);
391
+ });
392
+ buddy.command("generate:vscode-custom-data", descriptions.customData).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
393
+ await vsCodeCustomData(options);
394
+ });
395
+ buddy.command("generate:ide-helpers", descriptions.ideHelpers).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
396
+ await ideHelpers(options);
397
+ });
398
+ buddy.command("generate:component-meta", descriptions.componentMeta).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
399
+ await componentMeta(options);
400
+ });
401
+ buddy.command("generate:migrations", "Generate Migrations").action(async () => {
402
+ await migrations();
403
+ });
404
+ }
405
+ function hasNoOptions$2(options) {
406
+ return !options.types && !options.entries && !options.webTypes && !options.customData && !options.ideHelpers && !options.vueCompatibility && !options.componentMeta;
407
+ }
408
+
409
+ async function lint(buddy) {
410
+ const descriptions = {
411
+ lint: "Automagically lints your project codebase",
412
+ lintFix: "Automagically fixes all lint errors",
413
+ verbose: "Enable verbose output"
414
+ };
415
+ buddy.command("lint", descriptions.lint).option("-f, --fix", descriptions.lintFix, { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
416
+ const startTime = await intro("buddy lint");
417
+ const result = await runAction(Action.Lint, { ...options, showSpinner: true, spinnerText: "Linting..." });
418
+ if (result.isErr()) {
419
+ outro("While running `buddy lint`, there was an issue", { startTime, useSeconds: true, isError: true }, result.error);
420
+ process.exit();
421
+ }
422
+ outro("Linted your project", { startTime, useSeconds: true });
423
+ });
424
+ buddy.command("lint:fix", descriptions.lintFix).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
425
+ log.info("Fixing lint errors...");
426
+ const result = await runAction(Action.LintFix, { ...options, showSpinner: true, spinnerText: "Linting..." });
427
+ if (result.isErr()) {
428
+ log.error("There was an error lint fixing your code.", result.error);
429
+ process.exit();
430
+ }
431
+ log.success("Fixed lint errors");
432
+ });
433
+ }
434
+
435
+ async function key(buddy) {
436
+ const descriptions = {
437
+ command: "Generate & set the application key.",
438
+ verbose: "Enable verbose output"
439
+ };
440
+ buddy.command("key:generate", descriptions.command).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
441
+ const startTime = await intro("buddy key:generate");
442
+ const result = await runAction(Action.KeyGenerate, options);
443
+ if (result.isErr()) {
444
+ log.error("Failed to set random application key.", result.error);
445
+ process.exit();
446
+ }
447
+ outro("Set random application key.", { startTime });
448
+ });
449
+ }
450
+
451
+ async function make(buddy) {
452
+ const descriptions = {
453
+ model: "Create a new model",
454
+ component: "Create a new component",
455
+ page: "Create a new page",
456
+ function: "Create a new function",
457
+ language: "Create a new language",
458
+ database: "Create a new database",
459
+ migration: "Create a new migration",
460
+ factory: "Create a new factory",
461
+ notification: "Create a new notification",
462
+ stack: "Create a new new stack",
463
+ select: "What are you trying to make?",
464
+ verbose: "Enable verbose output"
465
+ };
466
+ buddy.command("make", "The make command").option("-c, --component", descriptions.component, { default: false }).option("-p, --page", descriptions.page, { default: false }).option("-f, --function", descriptions.function, { default: false }).option("-l, --language", descriptions.language, { default: false }).option("-d, --database", descriptions.database, { default: false }).option("-m, --migration", descriptions.migration, { default: false }).option("-f, --factory", descriptions.factory, { default: false }).option("-n, --notification", descriptions.notification, { default: false }).option("-s, --stack", descriptions.stack, { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
467
+ const name = buddy.args[0];
468
+ if (!name) {
469
+ log.error("You need to specify a name. Read more about the documentation here.");
470
+ process.exit();
471
+ }
472
+ if (hasNoOptions$1(options)) {
473
+ let answers = await prompt.require().multiselect(descriptions.select, {
474
+ options: [
475
+ { label: "Page", value: "page" },
476
+ { label: "Function", value: "function" },
477
+ { label: "Component", value: "component" },
478
+ { label: "Notification", value: "notification" },
479
+ { label: "Language", value: "language" },
480
+ { label: "Database", value: "database" },
481
+ { label: "Migration", value: "migration" },
482
+ { label: "Factory", value: "factory" },
483
+ { label: "Stack", value: "stack" }
484
+ ]
485
+ });
486
+ if (answers !== null)
487
+ process.exit(ExitCode.InvalidArgument);
488
+ if (isString(answers))
489
+ answers = [answers];
490
+ options = answers.reduce((a, v) => ({ ...a, [v]: true }), {});
491
+ }
492
+ await invoke$3(options);
493
+ process.exit(ExitCode.Success);
494
+ });
495
+ buddy.command("make:component", descriptions.component).option("-n, --name", "The name of the component").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
496
+ const name = buddy.args[0] || options.name;
497
+ options.name = name;
498
+ if (!name) {
499
+ log.error("You need to specify a name. Read more about the documentation here.");
500
+ process.exit();
501
+ }
502
+ await component(options);
503
+ });
504
+ buddy.command("make:database", descriptions.database).option("-n, --name", "The name of the database").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
505
+ const name = buddy.args[0] || options.name;
506
+ options.name = name;
507
+ if (!name) {
508
+ log.error("You need to specify a name. Read more about the documentation here.");
509
+ process.exit();
510
+ }
511
+ await database(options);
512
+ });
513
+ buddy.command("make:factory", descriptions.factory).option("-n, --name", "The name of the factory").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
514
+ const name = buddy.args[0] || options.name;
515
+ options.name = name;
516
+ if (!name) {
517
+ log.error("You need to specify a name. Read more about the documentation here.");
518
+ process.exit();
519
+ }
520
+ await factory(options);
521
+ });
522
+ buddy.command("make:page", descriptions.page).option("-n, --name", "The name of the page").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
523
+ const name = buddy.args[0] || options.name;
524
+ options.name = name;
525
+ if (!name) {
526
+ log.error("You need to specify a name. Read more about the documentation here.");
527
+ process.exit();
528
+ }
529
+ await page(options);
530
+ });
531
+ buddy.command("make:function", descriptions.function).option("-n, --name", "The name of the function").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
532
+ await fx(options);
533
+ });
534
+ buddy.command("make:lang", descriptions.language).option("-n, --name", "The name of the language").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
535
+ const name = buddy.args[0] || options.name;
536
+ options.name = name;
537
+ if (!name) {
538
+ log.error("You need to specify a name. Read more about the documentation here.");
539
+ process.exit();
540
+ }
541
+ await language(options);
542
+ });
543
+ buddy.command("make:notification", descriptions.notification).option("-n, --name", "The name of the notification").option("-e, --email", "Is it an email notification?", { default: true }).option("-c, --chat", "Is it a chat notification?", { default: false }).option("-s, --sms", "Is it a SMS notification?", { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
544
+ const perf = await intro("buddy make:notification");
545
+ const name = buddy.args[0] || options.name;
546
+ options.name = name;
547
+ if (!name) {
548
+ log.error("You need to specify a name. Read more about the documentation here.");
549
+ process.exit();
550
+ }
551
+ const result = await createNotification(options);
552
+ if (!result) {
553
+ outro("While running the make:notification command, there was an issue", { startTime: perf, useSeconds: true, isError: true });
554
+ process.exit();
555
+ }
556
+ outro(`Created your ${italic(name)} notification.`, { startTime: perf, useSeconds: true });
557
+ process.exit(ExitCode.Success);
558
+ });
559
+ buddy.command("make:stack", descriptions.stack).option("-n, --name", "The name of the stack").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
560
+ const name = buddy.args[0] || options.name;
561
+ options.name = name;
562
+ if (!name) {
563
+ log.error("You need to specify a name. Read more about the documentation here.");
564
+ process.exit();
565
+ }
566
+ await stack(options);
567
+ });
568
+ buddy.command("make:model", descriptions.model).option("-n, --name", "The name of the model").action(async (options) => {
569
+ const name = buddy.args[0] || options.name;
570
+ options.name = name;
571
+ if (!name) {
572
+ log.error("You need to specify the model name");
573
+ process.exit();
574
+ }
575
+ await createModel(options);
576
+ });
577
+ buddy.command("make:migration", descriptions.migration).option("-n, --name", "The name of the migration").option("-e, --env", "The environment to run the migration in", { default: "dev" }).action(async (options) => {
578
+ const path = frameworkPath("database/schema.prisma");
579
+ const name = buddy.args[0] || options.name;
580
+ options.name = name;
581
+ if (!name) {
582
+ log.error("You need to specify the migration name");
583
+ process.exit();
584
+ }
585
+ await runCommand(`npx prisma migrate ${options.env} --name=${name} --schema=${path}`);
586
+ log.success(path, name);
587
+ });
588
+ }
589
+ function hasNoOptions$1(options) {
590
+ return !options.component && !options.page && !options.function && !options.language && !options.database && !options.migration && !options.factory && !options.notification && !options.stack;
591
+ }
592
+
593
+ async function migrate(buddy) {
594
+ const descriptions = {
595
+ migrate: "Migrates your database",
596
+ verbose: "Enable verbose output"
597
+ };
598
+ buddy.command("migrate", descriptions.migrate).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
599
+ const perf = await intro("buddy migrate");
600
+ const result = await runAction(Action.Migrate, { ...options, showSpinner: true, spinnerText: "Migrating..." });
601
+ if (result.isErr()) {
602
+ outro("While running the migrate command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
603
+ process.exit();
604
+ }
605
+ const APP_ENV = process.env.APP_ENV || "local";
606
+ outro(`Migrated your ${APP_ENV} database.`, { startTime: perf, useSeconds: true });
607
+ process.exit(ExitCode.Success);
608
+ });
609
+ }
610
+
611
+ async function prepublish(buddy) {
612
+ const descriptions = {
613
+ command: "Run your prepublish script",
614
+ verbose: "Enable verbose output"
615
+ };
616
+ buddy.command("prepublish", descriptions.command).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
617
+ await runAction(Action.Prepublish, options);
618
+ });
619
+ }
620
+
621
+ async function preinstall(buddy) {
622
+ const descriptions = {
623
+ command: "Run your preinstall script",
624
+ verbose: "Enable verbose output"
625
+ };
626
+ buddy.command("preinstall", descriptions.command).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
627
+ await invoke$4(options);
628
+ });
629
+ }
630
+
631
+ const descriptions = {
632
+ release: "Release a new version of your libraries/packages",
633
+ verbose: "Enable verbose output"
634
+ };
635
+ async function release(buddy) {
636
+ buddy.command("release", descriptions.release).option("--verbose", descriptions.verbose, { default: true }).action(async (options) => {
637
+ const startTime = await intro("buddy release");
638
+ const result = await runAction(Action.Release, { ...options, shell: true });
639
+ if (result.isErr()) {
640
+ log.error("Failed to release", result.error);
641
+ process.exit();
642
+ }
643
+ outro("Triggered your CI/CD release workflow", { startTime, useSeconds: true });
644
+ });
645
+ }
646
+
647
+ async function seed(buddy) {
648
+ const descriptions = {
649
+ seed: "Seed your database",
650
+ verbose: "Enable verbose output"
651
+ };
652
+ buddy.command("seed", descriptions.seed).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
653
+ const perf = await intro("buddy seed");
654
+ const result = await runAction(Action.Seed, { ...options, showSpinner: true, spinnerText: "Seeding..." });
655
+ if (result.isErr()) {
656
+ outro("While running the seed command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
657
+ process.exit(ExitCode.FatalError);
658
+ }
659
+ const APP_ENV = process.env.APP_ENV || "local";
660
+ outro(`Seeded your ${APP_ENV} database.`, { startTime: perf, useSeconds: true });
661
+ process.exit(ExitCode.Success);
662
+ });
663
+ }
664
+
665
+ async function setup(buddy) {
666
+ const descriptions = {
667
+ ensure: "This command checks whether Node is installed. pnpm is checked via `only-allow` preinstall hook",
668
+ setup: "This command installs Node & pnpm",
669
+ verbose: "Enable verbose output"
670
+ };
671
+ buddy.command("ensure", descriptions.ensure).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
672
+ await runCommand("pnpm install", options);
673
+ });
674
+ buddy.command("setup", descriptions.setup).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
675
+ await runCommand("pnpm env use", options);
676
+ });
677
+ }
678
+
679
+ async function test(buddy) {
680
+ const descriptions = {
681
+ command: "Runs your test suite",
682
+ types: "Typechecks your codebase",
683
+ coverage: "Generates a test coverage report",
684
+ ui: "Runs your test suite in the browser",
685
+ unit: "Runs your unit tests",
686
+ feature: "Runs your feature tests",
687
+ showReport: "Show the test report",
688
+ verbose: "Enable verbose output"
689
+ };
690
+ buddy.command("test", descriptions.command).option("--ui", descriptions.ui, { default: false }).option("--verbose", descriptions.verbose, { default: true }).action(async (options) => {
691
+ const perf = await intro("buddy test");
692
+ const result = await runAction(Action.Test, { ...options, cwd: projectPath() });
693
+ if (result.isErr()) {
694
+ outro("While running `buddy test`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
695
+ process.exit();
696
+ }
697
+ outro("Finished running tests", { startTime: perf, useSeconds: true });
698
+ });
699
+ buddy.command("test:unit", descriptions.unit).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
700
+ const perf = await intro("buddy test:unit");
701
+ const result = await runAction(Action.TestUnit, { ...options, verbose: true, cwd: projectPath() });
702
+ if (result.isErr()) {
703
+ outro("While running `buddy test:unit`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
704
+ process.exit();
705
+ }
706
+ outro("Finished running unit tests", { startTime: perf, useSeconds: true });
707
+ });
708
+ buddy.command("test:feature", descriptions.feature).option("--show-report", descriptions.showReport, { default: false }).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
709
+ const perf = await intro("buddy test:feature");
710
+ let result;
711
+ if (options.showReport)
712
+ result = await runAction(Action.ShowFeatureTestReport, { ...options, verbose: true, cwd: projectPath() });
713
+ else
714
+ result = await runAction(Action.TestFeature, { ...options, verbose: true, cwd: projectPath() });
715
+ if (result.isErr()) {
716
+ outro("While running `buddy test:feature`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
717
+ process.exit();
718
+ }
719
+ outro("Finished running feature tests", { startTime: perf, useSeconds: true });
720
+ });
721
+ buddy.command("test:ui", descriptions.command).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
722
+ const perf = await intro("buddy test:ui");
723
+ const result = await runAction(Action.TestUi, { ...options, verbose: true, cwd: projectPath() });
724
+ if (result.isErr()) {
725
+ outro("While running `buddy test:ui`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
726
+ process.exit();
727
+ }
728
+ outro("Finished running tests in the browser", { startTime: perf, useSeconds: true });
729
+ });
730
+ buddy.command("test:types", descriptions.types).alias("typecheck").option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
731
+ const perf = await intro("buddy test:types");
732
+ const result = await runAction(Action.Typecheck, { ...options, verbose: true, cwd: projectPath() });
733
+ if (result.isErr()) {
734
+ outro("While running `buddy test:types`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
735
+ process.exit();
736
+ }
737
+ outro("Finished running typecheck", { startTime: perf, useSeconds: true });
738
+ });
739
+ buddy.command("test:coverage", descriptions.coverage).action(async (options) => {
740
+ const perf = await intro("buddy test:coverage");
741
+ const result = await runAction(Action.TestCoverage, { ...options, cwd: projectPath(), verbose: true });
742
+ if (result.isErr()) {
743
+ outro("While running `buddy test:coverage`, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
744
+ process.exit();
745
+ }
746
+ outro("Generated the test coverage report", { startTime: perf, useSeconds: true });
747
+ process.exit();
748
+ });
749
+ }
750
+
751
+ async function upgrade(buddy) {
752
+ const descriptions = {
753
+ command: "Upgrade dependencies, framework, package manager, and/or Node.js",
754
+ framework: "Upgrade the Stacks framework",
755
+ dependencies: "Upgrade your dependencies",
756
+ packageManager: "Upgrade your package manager, i.e. pnpm",
757
+ node: "Upgrade Node to the version defined in ./node-version",
758
+ all: "Upgrade Node, package manager, project dependencies, and framework",
759
+ force: "Overwrite possible local updates with remote framework updates",
760
+ select: "What are you trying to upgrade?",
761
+ verbose: "Enable verbose output"
762
+ };
763
+ buddy.command("upgrade", descriptions.command).option("-c, --framework", descriptions.framework, { default: false }).option("-d, --dependencies", descriptions.dependencies, { default: false }).option("-p, --package-manager", descriptions.packageManager, { default: false }).option("-n, --node", descriptions.node, { default: false }).option("-a, --all", descriptions.all, { default: false }).option("-f, --force", descriptions.force, { default: false }).option("--verbose", descriptions.verbose, { default: false }).alias("update").example("buddy upgrade -a --verbose").action(async (options) => {
764
+ const perf = await intro("buddy upgrade");
765
+ if (hasNoOptions(options)) {
766
+ let answers = await prompt.require().multiselect(descriptions.select, {
767
+ options: [
768
+ { value: "dependencies", label: "Dependencies" },
769
+ { value: "framework", label: "Framework" },
770
+ { value: "node", label: "Node.js" },
771
+ { value: "package-manager", label: "Package Manager" }
772
+ ]
773
+ });
774
+ if (answers !== null)
775
+ process.exit(ExitCode.InvalidArgument);
776
+ if (isString(answers))
777
+ answers = [answers];
778
+ options = answers.reduce((a, v) => ({ ...a, [v]: true }), {});
779
+ }
780
+ const result = await runAction(Action.Upgrade, { ...options, shell: true });
781
+ if (result.isErr()) {
782
+ outro("While running the buddy:upgrade command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
783
+ process.exit();
784
+ }
785
+ outro("Upgrade complete.", { startTime: perf, useSeconds: true });
786
+ process.exit();
787
+ });
788
+ buddy.command("upgrade:framework", descriptions.framework).option("--verbose", descriptions.verbose, { default: false }).example("buddy upgrade:framework --verbose").action(async (options) => {
789
+ await runAction(Action.Upgrade, options);
790
+ });
791
+ buddy.command("upgrade:dependencies", descriptions.dependencies).option("--verbose", descriptions.verbose, { default: false }).alias("upgrade:deps").example("buddy upgrade:dependencies --verbose").action(async (options) => {
792
+ await runAction(Action.Upgrade, options);
793
+ });
794
+ buddy.command("upgrade:package-manager", descriptions.packageManager).option("--verbose", descriptions.verbose, { default: false }).alias("upgrade:pm").alias("upgrade:pnpm").example("buddy upgrade:package-manager 7.16.1 --verbose").example("buddy upgrade:package-manager latest").action(async (options) => {
795
+ options.version = "latest";
796
+ if (buddy.args[0])
797
+ options.version = buddy.args[0];
798
+ const perf = await intro("buddy upgrade:package-manager");
799
+ const result = await runAction(Action.UpgradePackageManager, options);
800
+ if (result.isErr()) {
801
+ outro("While running the buddy upgrade:package-manager command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
802
+ process.exit();
803
+ }
804
+ process.exit(ExitCode.Success);
805
+ });
806
+ buddy.command("upgrade:node", descriptions.node).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
807
+ const perf = await intro("buddy upgrade:node");
808
+ const result = await runAction(Action.UpgradeNode, options);
809
+ if (result.isErr()) {
810
+ outro("While running the buddy upgrade:node command, there was an issue", { startTime: perf, useSeconds: true, isError: true }, result.error);
811
+ process.exit();
812
+ }
813
+ process.exit(ExitCode.Success);
814
+ });
815
+ buddy.command("upgrade:all", descriptions.all).option("--verbose", descriptions.verbose, { default: false }).action(async (options) => {
816
+ await runAction(Action.Upgrade, options);
817
+ });
818
+ }
819
+ function hasNoOptions(options) {
820
+ return !options.framework && !options.dependencies && !options.packageManager && !options.node && !options.all;
821
+ }
822
+
823
+ async function version(buddy) {
824
+ const descriptions = {
825
+ version: "Retrieving Stacks build version"
826
+ };
827
+ buddy.command("version", descriptions.version).action(async () => {
828
+ await intro("buddy version");
829
+ const pkg = await storage.readPackageJson("./package.json");
830
+ const nodeVersion = pkg.engines.node.replace(">=v", "");
831
+ const pnpmVersion = pkg.engines.pnpm.replace(">=", "");
832
+ const stacksVersion = pkg.version;
833
+ log$1.info(green(bold("Stacks: ")) + dim(` ${stacksVersion}`));
834
+ log$1.info(green(bold("node: ")) + dim(` ${nodeVersion}`));
835
+ log$1.info(green(bold("pnpm: ")) + dim(` ${pnpmVersion}`));
836
+ });
837
+ }
838
+
839
+ export { clean as a, build as b, changelog as c, commit as d, create as e, dev as f, example as g, fresh as h, generate as i, migrate as j, key as k, lint as l, make as m, preinstall as n, setup as o, prepublish as p, release as r, seed as s, test as t, upgrade as u, version as v };