@stacksjs/actions 0.70.88 → 0.70.91

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 (261) hide show
  1. package/dist/action.d.ts +149 -0
  2. package/dist/action.js +78 -0
  3. package/dist/actions.d.ts +2 -0
  4. package/dist/actions.js +2 -0
  5. package/dist/add.d.ts +6 -0
  6. package/dist/add.js +20 -0
  7. package/dist/ai/request-model-access.d.ts +1 -0
  8. package/dist/ai/request-model-access.js +10 -0
  9. package/dist/auth/client.d.ts +1 -0
  10. package/dist/auth/client.js +44 -0
  11. package/dist/auth/prune.d.ts +1 -0
  12. package/dist/auth/prune.js +35 -0
  13. package/dist/auth/setup.d.ts +1 -0
  14. package/dist/auth/setup.js +322 -0
  15. package/dist/auth/token.d.ts +1 -0
  16. package/dist/auth/token.js +10 -0
  17. package/dist/blog-admin.d.ts +55 -0
  18. package/dist/blog-admin.js +156 -0
  19. package/dist/blog.d.ts +30 -0
  20. package/dist/blog.js +398 -0
  21. package/dist/build/cli.d.ts +1 -0
  22. package/dist/build/cli.js +6 -0
  23. package/dist/build/component-libs.d.ts +1 -0
  24. package/dist/build/component-libs.js +7 -0
  25. package/dist/build/core.d.ts +1 -0
  26. package/dist/build/core.js +55 -0
  27. package/dist/build/desktop.d.ts +1 -0
  28. package/dist/build/desktop.js +5 -0
  29. package/dist/build/docs.d.ts +1 -0
  30. package/dist/build/docs.js +5 -0
  31. package/dist/build/frontend-static.d.ts +16 -0
  32. package/dist/build/frontend-static.js +124 -0
  33. package/dist/build/server.d.ts +1 -0
  34. package/dist/build/server.js +6 -0
  35. package/dist/build/stacks.d.ts +1 -0
  36. package/dist/build/stacks.js +8 -0
  37. package/dist/build/views.d.ts +1 -0
  38. package/dist/build/views.js +11 -0
  39. package/dist/build.d.ts +9 -0
  40. package/dist/build.js +64 -0
  41. package/dist/bump.d.ts +1 -0
  42. package/dist/bump.js +163 -0
  43. package/dist/cdn/invalidate-cache.d.ts +1 -0
  44. package/dist/cdn/invalidate-cache.js +0 -0
  45. package/dist/changelog.d.ts +9 -0
  46. package/dist/changelog.js +27 -0
  47. package/dist/check/ports.d.ts +1 -0
  48. package/dist/check/ports.js +16 -0
  49. package/dist/clean.d.ts +1 -0
  50. package/dist/clean.js +4 -0
  51. package/dist/commit.d.ts +3 -0
  52. package/dist/commit.js +12 -0
  53. package/dist/copy-types.d.ts +1 -0
  54. package/dist/copy-types.js +10 -0
  55. package/dist/database/seed.d.ts +1 -0
  56. package/dist/database/seed.js +26 -0
  57. package/dist/deploy/create-receipt-rule.d.ts +1 -0
  58. package/dist/deploy/create-receipt-rule.js +36 -0
  59. package/dist/deploy/index.d.ts +1 -0
  60. package/dist/deploy/index.js +1574 -0
  61. package/dist/dev/api.d.ts +1 -0
  62. package/dist/dev/api.js +94 -0
  63. package/dist/dev/components.d.ts +1 -0
  64. package/dist/dev/components.js +7 -0
  65. package/dist/dev/dashboard-globals.d.ts +4 -0
  66. package/dist/dev/dashboard-globals.js +89 -0
  67. package/dist/dev/dashboard-utils.d.ts +150 -0
  68. package/dist/dev/dashboard-utils.js +380 -0
  69. package/dist/dev/dashboard.d.ts +22 -0
  70. package/dist/dev/dashboard.js +435 -0
  71. package/dist/dev/desktop.d.ts +1 -0
  72. package/dist/dev/desktop.js +5 -0
  73. package/dist/dev/docs.d.ts +1 -0
  74. package/dist/dev/docs.js +24 -0
  75. package/dist/dev/index.d.ts +10 -0
  76. package/dist/dev/index.js +29 -0
  77. package/dist/dev/migrate-watcher.d.ts +1 -0
  78. package/dist/dev/migrate-watcher.js +74 -0
  79. package/dist/dev/system-tray.d.ts +1 -0
  80. package/dist/dev/system-tray.js +5 -0
  81. package/dist/dev/views.d.ts +1 -0
  82. package/dist/dev/views.js +147 -0
  83. package/dist/discover-packages.d.ts +18 -0
  84. package/dist/discover-packages.js +32 -0
  85. package/dist/domains/add.d.ts +1 -0
  86. package/dist/domains/add.js +61 -0
  87. package/dist/domains/purchase.d.ts +1 -0
  88. package/dist/domains/purchase.js +66 -0
  89. package/dist/domains/remove.d.ts +1 -0
  90. package/dist/domains/remove.js +24 -0
  91. package/dist/examples.d.ts +5 -0
  92. package/dist/examples.js +34 -0
  93. package/dist/find-projects.d.ts +1 -0
  94. package/dist/find-projects.js +16 -0
  95. package/dist/fresh.d.ts +1 -0
  96. package/dist/fresh.js +17 -0
  97. package/dist/generate/action-types.d.ts +1 -0
  98. package/dist/generate/action-types.js +13 -0
  99. package/dist/generate/component-meta.d.ts +1 -0
  100. package/dist/generate/component-meta.js +9 -0
  101. package/dist/generate/custom-cli-file.d.ts +1 -0
  102. package/dist/generate/custom-cli-file.js +21 -0
  103. package/dist/generate/env-files.d.ts +1 -0
  104. package/dist/generate/env-files.js +66 -0
  105. package/dist/generate/ide-helpers.d.ts +1 -0
  106. package/dist/generate/ide-helpers.js +8 -0
  107. package/dist/generate/index.d.ts +36 -0
  108. package/dist/generate/index.js +158 -0
  109. package/dist/generate/lib-entries.d.ts +1 -0
  110. package/dist/generate/lib-entries.js +16 -0
  111. package/dist/generate/pantry-file.d.ts +1 -0
  112. package/dist/generate/pantry-file.js +46 -0
  113. package/dist/generate/symlink-core.d.ts +1 -0
  114. package/dist/generate/symlink-core.js +2 -0
  115. package/dist/generate/types.d.ts +1 -0
  116. package/dist/generate/types.js +3 -0
  117. package/dist/generate/vscode-custom-data.d.ts +1 -0
  118. package/dist/generate/vscode-custom-data.js +9 -0
  119. package/dist/generate/web-types.d.ts +1 -0
  120. package/dist/generate/web-types.js +0 -0
  121. package/dist/helpers/component-meta.d.ts +26 -0
  122. package/dist/helpers/component-meta.js +295 -0
  123. package/dist/helpers/index.d.ts +4 -0
  124. package/dist/helpers/index.js +1 -0
  125. package/dist/helpers/lib-entries.d.ts +12 -0
  126. package/dist/helpers/lib-entries.js +73 -0
  127. package/dist/helpers/package-json.d.ts +2 -0
  128. package/dist/helpers/package-json.js +74 -0
  129. package/dist/helpers/utils.d.ts +23 -0
  130. package/dist/helpers/utils.js +105 -0
  131. package/dist/helpers/vscode-custom-data.d.ts +3 -0
  132. package/dist/helpers/vscode-custom-data.js +30 -0
  133. package/dist/index.d.ts +62 -0
  134. package/dist/index.js +50 -0
  135. package/dist/key-generate.d.ts +1 -0
  136. package/dist/key-generate.js +24 -0
  137. package/dist/lint/fix.d.ts +1 -0
  138. package/dist/lint/fix.js +4 -0
  139. package/dist/lint/index.d.ts +1 -0
  140. package/dist/lint/index.js +4 -0
  141. package/dist/lint/lint.d.ts +14 -0
  142. package/dist/lint/lint.js +34 -0
  143. package/dist/make-command.d.ts +10 -0
  144. package/dist/make-command.js +95 -0
  145. package/dist/make-job.d.ts +5 -0
  146. package/dist/make-job.js +154 -0
  147. package/dist/make-policy.d.ts +10 -0
  148. package/dist/make-policy.js +142 -0
  149. package/dist/make-resource.d.ts +10 -0
  150. package/dist/make-resource.js +142 -0
  151. package/dist/make.d.ts +52 -0
  152. package/dist/make.js +328 -0
  153. package/dist/migrate/database.d.ts +1 -0
  154. package/dist/migrate/database.js +16 -0
  155. package/dist/migrate/fresh.d.ts +1 -0
  156. package/dist/migrate/fresh.js +31 -0
  157. package/dist/orm/base.d.ts +1 -0
  158. package/dist/orm/base.js +0 -0
  159. package/dist/orm/test.d.ts +1 -0
  160. package/dist/orm/test.js +0 -0
  161. package/dist/prepublish.d.ts +1 -0
  162. package/dist/prepublish.js +16 -0
  163. package/dist/queue/clear.d.ts +1 -0
  164. package/dist/queue/clear.js +42 -0
  165. package/dist/queue/dlq-purge.d.ts +1 -0
  166. package/dist/queue/dlq-purge.js +28 -0
  167. package/dist/queue/dlq-retry.d.ts +1 -0
  168. package/dist/queue/dlq-retry.js +35 -0
  169. package/dist/queue/dlq.d.ts +1 -0
  170. package/dist/queue/dlq.js +55 -0
  171. package/dist/queue/failed.d.ts +1 -0
  172. package/dist/queue/failed.js +69 -0
  173. package/dist/queue/flush.d.ts +1 -0
  174. package/dist/queue/flush.js +49 -0
  175. package/dist/queue/inspect.d.ts +1 -0
  176. package/dist/queue/inspect.js +154 -0
  177. package/dist/queue/list.d.ts +1 -0
  178. package/dist/queue/list.js +69 -0
  179. package/dist/queue/monitor.d.ts +1 -0
  180. package/dist/queue/monitor.js +95 -0
  181. package/dist/queue/pause.d.ts +1 -0
  182. package/dist/queue/pause.js +28 -0
  183. package/dist/queue/quarantine.d.ts +1 -0
  184. package/dist/queue/quarantine.js +42 -0
  185. package/dist/queue/resume.d.ts +1 -0
  186. package/dist/queue/resume.js +27 -0
  187. package/dist/queue/retry.d.ts +1 -0
  188. package/dist/queue/retry.js +41 -0
  189. package/dist/queue/schedule-list.d.ts +1 -0
  190. package/dist/queue/schedule-list.js +33 -0
  191. package/dist/queue/schedule.d.ts +1 -0
  192. package/dist/queue/schedule.js +12 -0
  193. package/dist/queue/status.d.ts +1 -0
  194. package/dist/queue/status.js +68 -0
  195. package/dist/queue/table.d.ts +1 -0
  196. package/dist/queue/table.js +10 -0
  197. package/dist/queue/unquarantine.d.ts +1 -0
  198. package/dist/queue/unquarantine.js +27 -0
  199. package/dist/queue/work.d.ts +1 -0
  200. package/dist/queue/work.js +57 -0
  201. package/dist/release.d.ts +1 -0
  202. package/dist/release.js +21 -0
  203. package/dist/route/list.d.ts +1 -0
  204. package/dist/route/list.js +78 -0
  205. package/dist/run-action.d.ts +2 -0
  206. package/dist/run-action.js +1 -0
  207. package/dist/saas/setup.d.ts +1 -0
  208. package/dist/saas/setup.js +9 -0
  209. package/dist/scaffold-crud.d.ts +25 -0
  210. package/dist/scaffold-crud.js +211 -0
  211. package/dist/schedule/run.d.ts +1 -0
  212. package/dist/schedule/run.js +7 -0
  213. package/dist/search/flush.d.ts +1 -0
  214. package/dist/search/flush.js +10 -0
  215. package/dist/search/import.d.ts +1 -0
  216. package/dist/search/import.js +10 -0
  217. package/dist/search/settings-list.d.ts +1 -0
  218. package/dist/search/settings-list.js +10 -0
  219. package/dist/search/settings.d.ts +1 -0
  220. package/dist/search/settings.js +9 -0
  221. package/dist/serve/api.d.ts +1 -0
  222. package/dist/serve/api.js +35 -0
  223. package/dist/setup/index.d.ts +1 -0
  224. package/dist/setup/index.js +1 -0
  225. package/dist/setup/ssl.d.ts +38 -0
  226. package/dist/setup/ssl.js +271 -0
  227. package/dist/stacks.d.ts +4 -0
  228. package/dist/stacks.js +265 -0
  229. package/dist/templates.d.ts +28 -0
  230. package/dist/templates.js +301 -0
  231. package/dist/test/feature.d.ts +1 -0
  232. package/dist/test/feature.js +11 -0
  233. package/dist/test/index.d.ts +1 -0
  234. package/dist/test/index.js +11 -0
  235. package/dist/test/ui.d.ts +1 -0
  236. package/dist/test/ui.js +4 -0
  237. package/dist/test/unit.d.ts +1 -0
  238. package/dist/test/unit.js +11 -0
  239. package/dist/typecheck.d.ts +1 -0
  240. package/dist/typecheck.js +4 -0
  241. package/dist/types.d.ts +3 -0
  242. package/dist/types.js +16 -0
  243. package/dist/upgrade/binary.d.ts +1 -0
  244. package/dist/upgrade/binary.js +29 -0
  245. package/dist/upgrade/bun.d.ts +1 -0
  246. package/dist/upgrade/bun.js +0 -0
  247. package/dist/upgrade/dependencies.d.ts +1 -0
  248. package/dist/upgrade/dependencies.js +0 -0
  249. package/dist/upgrade/framework-utils.d.ts +150 -0
  250. package/dist/upgrade/framework-utils.js +193 -0
  251. package/dist/upgrade/framework.d.ts +1 -0
  252. package/dist/upgrade/framework.js +310 -0
  253. package/dist/upgrade/index.d.ts +1 -0
  254. package/dist/upgrade/index.js +17 -0
  255. package/dist/upgrade/packages.d.ts +14 -0
  256. package/dist/upgrade/packages.js +99 -0
  257. package/dist/upgrade/shell.d.ts +1 -0
  258. package/dist/upgrade/shell.js +41 -0
  259. package/dist/upgrade.d.ts +7 -0
  260. package/dist/upgrade.js +38 -0
  261. package/package.json +16 -16
package/dist/make.js ADDED
@@ -0,0 +1,328 @@
1
+ import process from "node:process";
2
+ import { existsSync } from "node:fs";
3
+ import { italic, runCommand } from "@stacksjs/cli";
4
+ import { ExitCode } from "@stacksjs/types";
5
+ import { localUrl } from "@stacksjs/config";
6
+ import { Action } from "@stacksjs/enums";
7
+ import { handleError } from "@stacksjs/error-handling";
8
+ import { log } from "@stacksjs/logging";
9
+ import { frameworkPath, path as p, resolve } from "@stacksjs/path";
10
+ import { createFolder, doesFolderExist, writeTextFile } from "@stacksjs/storage";
11
+ import { kebabCase, pascalCase, template } from "@stacksjs/strings";
12
+ import { runAction } from "./helpers";
13
+ import { CODE_TEMPLATES } from "./templates";
14
+ let isDryRun = !1;
15
+ export function setDryRun(enabled) {
16
+ isDryRun = Boolean(enabled);
17
+ }
18
+ export function isDryRunActive() {
19
+ return isDryRun;
20
+ }
21
+ function generateCode(templateKey, ...args) {
22
+ return template(CODE_TEMPLATES[templateKey], ...args);
23
+ }
24
+ async function writeOrPreview(path, data) {
25
+ if (isDryRun) {
26
+ const lines = data.split(`
27
+ `), preview = lines.slice(0, 60).map((l) => ` ${l}`).join(`
28
+ `), truncated = lines.length > 60 ? `
29
+ ${italic(`\u2026 ${lines.length - 60} more lines elided`)}` : "";
30
+ log.info(`[dry-run] would write ${path} (${lines.length} lines)`);
31
+ process.stdout.write(`${preview}${truncated}
32
+
33
+ `);
34
+ return;
35
+ }
36
+ await writeTextFile({ path, data });
37
+ }
38
+ async function createFileWithTemplate(path, templateKey, ...args) {
39
+ await writeOrPreview(path, generateCode(templateKey, ...args));
40
+ }
41
+ export async function invoke(options) {
42
+ if (options.component)
43
+ await makeComponent(options);
44
+ if (options.database)
45
+ makeDatabase(options);
46
+ if (options.function)
47
+ await makeFunction(options);
48
+ if (options.language)
49
+ await makeLanguage(options);
50
+ if (options.middleware)
51
+ await createMiddleware(options);
52
+ if (options.notification)
53
+ await makeNotification(options);
54
+ if (options.page)
55
+ await makePage(options);
56
+ if (options.stack)
57
+ await makeStack(options);
58
+ }
59
+ export async function make(options) {
60
+ return await invoke(options);
61
+ }
62
+ export async function makeAction(options) {
63
+ try {
64
+ const name = options.name;
65
+ log.info("Creating your action...");
66
+ await createAction(options);
67
+ log.success(`Created ${italic(name)} action`);
68
+ } catch (error) {
69
+ log.error("There was an error creating your action", error);
70
+ process.exit(ExitCode.FatalError);
71
+ }
72
+ }
73
+ export async function makeComponent(options) {
74
+ try {
75
+ const name = options.name;
76
+ log.info("Creating your component...");
77
+ await createComponent(options);
78
+ log.success(`Created ${italic(name)} component`);
79
+ } catch (error) {
80
+ log.error("There was an error creating your component", error);
81
+ process.exit(ExitCode.FatalError);
82
+ }
83
+ }
84
+ export async function createAction(options) {
85
+ const name = options.name, opts = options, wantsValidation = Boolean(opts.withValidation || options["with-validation"]), wantsAuth = Boolean(opts.withAuth || options["with-auth"]), templateKey = wantsValidation && wantsAuth ? "actionWithBoth" : wantsValidation ? "actionWithValidation" : wantsAuth ? "actionWithAuth" : "action";
86
+ await createFileWithTemplate(p.userActionsPath(name), templateKey, name);
87
+ }
88
+ export async function createComponent(options) {
89
+ const name = options.name;
90
+ await createFileWithTemplate(p.userComponentsPath(`${name}.vue`), "component", name);
91
+ }
92
+ export function makeDatabase(options) {
93
+ try {
94
+ const name = options.name;
95
+ log.info(`Creating your ${italic(name)} database...`);
96
+ createDatabase(options);
97
+ log.success(`Created ${italic(name)} database`);
98
+ } catch (error) {
99
+ log.error("There was an error creating your database", error);
100
+ process.exit(ExitCode.FatalError);
101
+ }
102
+ }
103
+ export function createDatabase(options) {
104
+ log.debug("createDatabase options", options);
105
+ }
106
+ export function factory(options) {
107
+ try {
108
+ const name = options.name;
109
+ log.info(`Creating your ${italic(name)} factory...`);
110
+ createDatabase(options);
111
+ log.success(`Created ${italic(name)} factory`);
112
+ } catch (error) {
113
+ log.error("There was an error creating your factory", error);
114
+ process.exit(ExitCode.FatalError);
115
+ }
116
+ }
117
+ export async function createFactory(options) {
118
+ const name = options.name || "MyFactory", factoryName = name.endsWith("Factory") ? name : `${name}Factory`;
119
+ try {
120
+ const { path: p } = await import("@stacksjs/path"), factoryPath = `${p.userDatabasePath("factories")}/${factoryName}.ts`;
121
+ if (await Bun.file(factoryPath).exists()) {
122
+ log.warn(`Factory ${factoryName} already exists at ${factoryPath}`);
123
+ return;
124
+ }
125
+ const modelName = name.replace(/Factory$/, ""), content = `import type { ${modelName}Model } from '@stacksjs/orm'
126
+
127
+ export function ${factoryName}(): Partial<${modelName}Model> {
128
+ return {
129
+ // Define your factory attributes here
130
+ }
131
+ }
132
+
133
+ export default ${factoryName}
134
+ `;
135
+ await writeOrPreview(factoryPath, content);
136
+ log.success(`Created factory: ${factoryPath}`);
137
+ } catch (error) {
138
+ log.error(`Failed to create factory ${factoryName}`, error);
139
+ throw error;
140
+ }
141
+ }
142
+ export async function makeNotification(options) {
143
+ try {
144
+ const name = options.name;
145
+ log.info(`Creating your ${italic(name)} notification...`);
146
+ await createNotification(options);
147
+ log.success(`Created ${italic(name)} notification`);
148
+ } catch (error) {
149
+ log.error("There was an error creating your notification", error);
150
+ process.exit(ExitCode.FatalError);
151
+ }
152
+ }
153
+ export async function createMail(options) {
154
+ const rawName = String(options.name || "").trim();
155
+ if (!rawName) {
156
+ log.error("A mail name is required (e.g. `buddy make:mail OrderShipped`).");
157
+ return !1;
158
+ }
159
+ const className = pascalCase(rawName), kebabName = kebabCase(rawName), mailPath = p.userMailPath(`${className}.ts`), templatePath = p.userEmailsPath(`${kebabName}.stx`);
160
+ if (!options.force) {
161
+ if (existsSync(mailPath)) {
162
+ console.error(`${italic(mailPath)} already exists \u2014 re-run with --force to overwrite.`);
163
+ return !1;
164
+ }
165
+ if (existsSync(templatePath)) {
166
+ console.error(`${italic(templatePath)} already exists \u2014 re-run with --force to overwrite.`);
167
+ return !1;
168
+ }
169
+ }
170
+ if (!doesFolderExist(p.userMailPath()))
171
+ await createFolder(p.userMailPath());
172
+ if (!doesFolderExist(p.userEmailsPath()))
173
+ await createFolder(p.userEmailsPath());
174
+ try {
175
+ await createFileWithTemplate(mailPath, "mail", className, kebabName);
176
+ await createFileWithTemplate(templatePath, "mailTemplate", className, kebabName);
177
+ return !0;
178
+ } catch (error) {
179
+ handleError("Error creating mailable", error);
180
+ return !1;
181
+ }
182
+ }
183
+ export async function makeMail(options) {
184
+ try {
185
+ const name = options.name;
186
+ log.info(`Creating your ${italic(name)} mailable...`);
187
+ if (!await createMail(options))
188
+ process.exit(ExitCode.FatalError);
189
+ log.success(`Created ${italic(pascalCase(name))} mailable + ${italic(kebabCase(name))}.stx template`);
190
+ } catch (error) {
191
+ log.error("There was an error creating your mailable", error);
192
+ process.exit(ExitCode.FatalError);
193
+ }
194
+ }
195
+ export async function makePage(options) {
196
+ try {
197
+ const name = options.name;
198
+ log.info("Creating your page...");
199
+ await createPage(options);
200
+ log.success(`Created ${name} page`);
201
+ } catch (error) {
202
+ log.error("There was an error creating your page", error);
203
+ process.exit(ExitCode.FatalError);
204
+ }
205
+ }
206
+ export async function createPage(options) {
207
+ const name = options.name;
208
+ await createFileWithTemplate(p.userViewsPath(`${name}.vue`), "page", name);
209
+ }
210
+ export async function makeFunction(options) {
211
+ try {
212
+ const name = options.name;
213
+ log.info("Creating your function...");
214
+ await createFunction(options);
215
+ log.success(`Created ${name} function`);
216
+ } catch (error) {
217
+ log.error("There was an error creating your function", error);
218
+ process.exit(ExitCode.FatalError);
219
+ }
220
+ }
221
+ export async function createFunction(options) {
222
+ const name = options.name;
223
+ await createFileWithTemplate(p.userFunctionsPath(`${name}.ts`), "function", name);
224
+ }
225
+ export async function makeLanguage(options) {
226
+ try {
227
+ const name = options.name;
228
+ log.info("Creating your translation file...");
229
+ await createLanguage(options);
230
+ log.success(`Created ${name} translation file`);
231
+ } catch (error) {
232
+ log.error("There was an error creating your language.", error);
233
+ process.exit(ExitCode.FatalError);
234
+ }
235
+ }
236
+ export async function createLanguage(options) {
237
+ const name = options.name;
238
+ await createFileWithTemplate(p.resourcesPath(`lang/${name}.yml`), "language", name);
239
+ }
240
+ export async function makeStack(options) {
241
+ try {
242
+ const name = options.name;
243
+ log.info(`Creating your ${name} stack...`);
244
+ const stackDir = resolve(process.cwd(), name);
245
+ if (doesFolderExist(stackDir)) {
246
+ log.error(`Directory "${name}" already exists`);
247
+ process.exit(ExitCode.FatalError);
248
+ }
249
+ await createFolder(stackDir);
250
+ const dirs = ["app/Actions", "app/Models", "config", "database/migrations", "resources/views", "resources/components", "resources/functions", "routes", "public"];
251
+ for (const dir of dirs)
252
+ await createFolder(resolve(stackDir, dir));
253
+ const shortName = name.replace(/^@[^/]+\//, "").replace(/-stack$/, "");
254
+ await createFileWithTemplate(resolve(stackDir, "package.json"), "stackPackageJson", name, shortName);
255
+ log.success(`Successfully scaffolded your "${name}" stack`);
256
+ log.info("");
257
+ log.info(` cd ${name}`);
258
+ log.info(" # Add your models, actions, views, etc.");
259
+ log.info(" # Then publish: bun publish");
260
+ log.info("");
261
+ log.info(" Users install it with:");
262
+ log.info(` buddy stack:install ${name}`);
263
+ } catch (error) {
264
+ log.error("There was an error creating your stack", error);
265
+ process.exit(ExitCode.FatalError);
266
+ }
267
+ }
268
+ export async function createNotification(options) {
269
+ const name = options.name;
270
+ try {
271
+ let importOption = "EmailOptions";
272
+ if (!doesFolderExist("notifications"))
273
+ await createFolder("./notifications");
274
+ if (options.chat)
275
+ importOption = "ChatOptions";
276
+ if (options.sms)
277
+ importOption = "SMSOptions";
278
+ await createFileWithTemplate(p.userNotificationsPath(`${name}.ts`), "notification", importOption);
279
+ return !0;
280
+ } catch (error) {
281
+ handleError("Error creating notification", error);
282
+ return !1;
283
+ }
284
+ }
285
+ export async function createMigration(options) {
286
+ const optionName = options.name, table = "dummy-name";
287
+ if (!optionName[0])
288
+ throw Error("options.name is required and cannot be empty");
289
+ const name = optionName[0].toUpperCase() + optionName.slice(1), path = frameworkPath(`database/migrations/${name}.ts`);
290
+ try {
291
+ await createFileWithTemplate(path, "migration", table);
292
+ log.success(`Successfully created your migration file at stacks/database/migrations/${name}.ts`);
293
+ } catch (error) {
294
+ log.error(error);
295
+ }
296
+ }
297
+ export async function makeQueueTable() {
298
+ await runAction(Action.QueueTable);
299
+ }
300
+ export async function makeCertificate() {
301
+ const domain = await localUrl();
302
+ log.info("Creating SSL certificate...");
303
+ await runCommand(`tlsx ${domain}`, {
304
+ cwd: p.storagePath("keys")
305
+ });
306
+ log.success("Certificate created");
307
+ log.info("Installing SSL certificate...");
308
+ await runCommand("tlsx -install", {
309
+ cwd: p.storagePath("keys")
310
+ });
311
+ log.success("Certificate installed");
312
+ }
313
+ export async function createModel(options) {
314
+ const optionName = options.name;
315
+ if (!optionName[0])
316
+ throw Error("options.name is required and cannot be empty");
317
+ const name = optionName[0].toUpperCase() + optionName.slice(1), tableName = name.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "").replace(/([^s])$/, "$1s"), path = p.userModelsPath(`${name}.ts`);
318
+ try {
319
+ await createFileWithTemplate(path, "model", name, tableName);
320
+ log.success(`Model created: ${italic(`app/Models/${name}.ts`)}`);
321
+ } catch (error) {
322
+ log.error(error);
323
+ }
324
+ }
325
+ export async function createMiddleware(options) {
326
+ const name = options.name;
327
+ await createFileWithTemplate(p.userMiddlewarePath(`${name}.ts`), "middleware", name);
328
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import process from "node:process";
2
+ import { generateMigrations, runDatabaseMigration } from "@stacksjs/database";
3
+ import { log } from "@stacksjs/logging";
4
+ const result = await generateMigrations();
5
+ if (result?.isErr) {
6
+ console.error(result.error);
7
+ log.error("[stacks] generateMigrations failed", result.error);
8
+ process.exit(1);
9
+ }
10
+ const migrateResult = await runDatabaseMigration();
11
+ if (migrateResult.isErr) {
12
+ log.error("runDatabaseMigration failed");
13
+ log.error(migrateResult.error);
14
+ process.exit(1);
15
+ }
16
+ process.exit(0);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import process from "node:process";
2
+ import { generateMigrations, migrateAuthTables, migrateNotificationTables, migrateRbacTables, resetDatabase, runDatabaseMigration } from "@stacksjs/database";
3
+ import { log } from "@stacksjs/logging";
4
+ const resetResult = await resetDatabase();
5
+ if (resetResult?.isErr) {
6
+ console.error(resetResult.error);
7
+ log.error("resetDatabase failed", resetResult.error);
8
+ process.exit(1);
9
+ }
10
+ const genResult = await generateMigrations();
11
+ if (genResult?.isErr) {
12
+ console.error(genResult.error);
13
+ log.error("generateMigrations failed", genResult.error);
14
+ process.exit(1);
15
+ }
16
+ const authResult = await migrateAuthTables();
17
+ if (!authResult.success)
18
+ log.error(`Failed to migrate auth tables: ${authResult.error}`);
19
+ const notifResult = await migrateNotificationTables();
20
+ if (!notifResult.success)
21
+ log.error(`Failed to migrate notification tables: ${notifResult.error}`);
22
+ const rbacResult = await migrateRbacTables();
23
+ if (!rbacResult.success)
24
+ log.error(`Failed to migrate RBAC tables: ${rbacResult.error}`);
25
+ const migrateResult = await runDatabaseMigration();
26
+ if (migrateResult.isErr) {
27
+ log.error("runDatabaseMigration failed");
28
+ log.error(migrateResult.error);
29
+ process.exit(1);
30
+ }
31
+ process.exit(0);
@@ -0,0 +1 @@
1
+
File without changes
@@ -0,0 +1 @@
1
+
File without changes
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import process from "node:process";
2
+ import { NpmScript } from "@stacksjs/enums";
3
+ import { log } from "@stacksjs/logging";
4
+ import { runtimePath } from "@stacksjs/path";
5
+ import { ExitCode } from "@stacksjs/types";
6
+ import { runNpmScript } from "@stacksjs/utils";
7
+ log.info("Running prepublish command...");
8
+ const result = await runNpmScript(NpmScript.BuildStacks, {
9
+ verbose: !0,
10
+ cwd: runtimePath()
11
+ });
12
+ if (result.isErr) {
13
+ log.error(Error("There was an error while prepublishing your stack"), result.error);
14
+ process.exit(ExitCode.FatalError);
15
+ }
16
+ log.success("Prepublishing completed");
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { Job } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, force = options.force === "true";
5
+ try {
6
+ if (!force) {
7
+ log.warn("This will delete all jobs from the queue. Use --force to confirm.");
8
+ process.exit(1);
9
+ }
10
+ let deletedCount = 0;
11
+ if (queueName) {
12
+ log.info(`Clearing all jobs from queue "${queueName}"...`);
13
+ const jobs = await Job.where("queue", queueName).get();
14
+ deletedCount = jobs.length;
15
+ for (const job of jobs)
16
+ await job.delete();
17
+ } else {
18
+ log.info("Clearing all jobs from all queues...");
19
+ const jobs = await Job.all();
20
+ deletedCount = jobs.length;
21
+ for (const job of jobs)
22
+ await job.delete();
23
+ }
24
+ log.success(`Cleared ${deletedCount} job(s)`);
25
+ process.exit(0);
26
+ } catch (error) {
27
+ log.error("Failed to clear jobs", error);
28
+ process.exit(1);
29
+ }
30
+ function parseArgs() {
31
+ const args = {};
32
+ process.argv.forEach((arg) => {
33
+ if (arg.startsWith("--")) {
34
+ const [key, value] = arg.slice(2).split("=");
35
+ if (key && value)
36
+ args[key] = value;
37
+ else if (key)
38
+ args[key] = "true";
39
+ }
40
+ });
41
+ return args;
42
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { purgeDeadLetterJobs } from "@stacksjs/queue";
4
+ const options = parseArgs(), days = options.olderThanDays ? Number.parseInt(options.olderThanDays, 10) : options["older-than-days"] ? Number.parseInt(options["older-than-days"], 10) : 30;
5
+ if (!Number.isFinite(days) || days < 1) {
6
+ log.error(`Invalid --older-than-days value '${options.olderThanDays ?? options["older-than-days"]}'`);
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ log.info(`Pruning dead-letter rows older than ${days} day(s)...`);
11
+ const deleted = await purgeDeadLetterJobs(days);
12
+ log.success(`Deleted ${deleted} dead-letter row(s)`);
13
+ process.exit(0);
14
+ } catch (error) {
15
+ log.error("Failed to purge dead-letter jobs", error);
16
+ process.exit(1);
17
+ }
18
+ function parseArgs() {
19
+ const args = {};
20
+ process.argv.forEach((arg) => {
21
+ if (arg.startsWith("--")) {
22
+ const [key, value] = arg.slice(2).split("=");
23
+ if (key && value)
24
+ args[key] = value;
25
+ }
26
+ });
27
+ return args;
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { retryDeadLetterJob } from "@stacksjs/queue";
4
+ const options = parseArgs(), idArg = options.id;
5
+ if (!idArg) {
6
+ log.error("Usage: buddy queue:dlq:retry --id=<id>");
7
+ process.exit(1);
8
+ }
9
+ const id = Number.parseInt(idArg, 10);
10
+ if (Number.isNaN(id)) {
11
+ log.error("Invalid id provided");
12
+ process.exit(1);
13
+ }
14
+ try {
15
+ if (!await retryDeadLetterJob(id)) {
16
+ log.error(`Dead-letter job ${id} not found (or DLQ table missing)`);
17
+ process.exit(1);
18
+ }
19
+ log.success(`Re-enqueued dead-letter job ${id}`);
20
+ process.exit(0);
21
+ } catch (error) {
22
+ log.error("Failed to re-enqueue dead-letter job", error);
23
+ process.exit(1);
24
+ }
25
+ function parseArgs() {
26
+ const args = {};
27
+ process.argv.forEach((arg) => {
28
+ if (arg.startsWith("--")) {
29
+ const [key, value] = arg.slice(2).split("=");
30
+ if (key && value)
31
+ args[key] = value;
32
+ }
33
+ });
34
+ return args;
35
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,55 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { listDeadLetterJobs } from "@stacksjs/queue";
4
+ const options = parseArgs(), queueName = options.queue || void 0, reason = options.reason || void 0, sinceArg = options.since, limit = options.limit ? Number.parseInt(options.limit, 10) : 100;
5
+ try {
6
+ log.info(`Fetching dead-letter jobs...
7
+ `);
8
+ const sinceCutoffMs = sinceArg ? parseSinceDuration(sinceArg) ?? void 0 : void 0, rows = await listDeadLetterJobs({ queue: queueName, reason, sinceCutoffMs, limit });
9
+ if (rows.length === 0) {
10
+ console.log("\u2713 No dead-letter jobs found");
11
+ process.exit(0);
12
+ }
13
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
14
+ console.log("\u2502 ID \u2502 Queue \u2502 Reason \u2502 Failures \u2502 Dead-Lettered At \u2502");
15
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
16
+ for (const row of rows) {
17
+ const id = String(row.id).padEnd(3), q = (row.queue || "default").substring(0, 32).padEnd(32), r = (row.reason || "unknown").substring(0, 16).padEnd(16), f = String(row.total_failures ?? 1).padEnd(8), dt = (row.dead_lettered_at || "N/A").substring(0, 24).padEnd(24);
18
+ console.log(`\u2502 ${id} \u2502 ${q} \u2502 ${r} \u2502 ${f} \u2502 ${dt} \u2502`);
19
+ }
20
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
21
+ console.log(`
22
+ Showing ${rows.length} dead-letter job(s)`);
23
+ process.exit(0);
24
+ } catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ if (/no such table:\s*dead_letter_jobs\b/i.test(message)) {
27
+ process.stdout.write(`Dead-letter queue table is not set up yet.
28
+ `);
29
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
30
+ process.exit(0);
31
+ }
32
+ log.error("Failed to fetch dead-letter jobs", error);
33
+ process.exit(1);
34
+ }
35
+ function parseArgs() {
36
+ const args = {};
37
+ process.argv.forEach((arg) => {
38
+ if (arg.startsWith("--")) {
39
+ const [key, value] = arg.slice(2).split("=");
40
+ if (key && value)
41
+ args[key] = value;
42
+ }
43
+ });
44
+ return args;
45
+ }
46
+ function parseSinceDuration(input) {
47
+ const m = /^(\d+)([smhd])$/.exec(input.trim());
48
+ if (!m)
49
+ return null;
50
+ const n = Number(m[1]);
51
+ if (!Number.isFinite(n) || n <= 0)
52
+ return null;
53
+ const mult = m[2] === "s" ? 1000 : m[2] === "m" ? 60000 : m[2] === "h" ? 3600000 : 86400000;
54
+ return Date.now() - n * mult;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,69 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { FailedJob } from "@stacksjs/orm";
4
+ const options = parseArgs(), queueName = options.queue, sinceArg = options.since, sinceCutoff = sinceArg ? parseSinceDuration(sinceArg) : null;
5
+ try {
6
+ log.info(`Fetching failed jobs...
7
+ `);
8
+ let failedJobs;
9
+ if (queueName)
10
+ failedJobs = await FailedJob.where("queue", queueName).get();
11
+ else
12
+ failedJobs = await FailedJob.all();
13
+ if (sinceCutoff)
14
+ failedJobs = failedJobs.filter((j) => {
15
+ if (!j.failed_at)
16
+ return !1;
17
+ const ts = Date.parse(j.failed_at);
18
+ return Number.isFinite(ts) && ts >= sinceCutoff;
19
+ });
20
+ if (failedJobs.length === 0) {
21
+ if (sinceCutoff)
22
+ console.log(`\u2713 No failed jobs found since ${sinceArg}`);
23
+ else
24
+ console.log("\u2713 No failed jobs found");
25
+ process.exit(0);
26
+ }
27
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
28
+ console.log("\u2502 ID \u2502 Queue \u2502 Failed At \u2502 Exception \u2502");
29
+ console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
30
+ for (const job of failedJobs) {
31
+ const id = String(job.id).padEnd(3), queue = (job.queue || "default").substring(0, 48).padEnd(48), failedAt = (job.failed_at || "N/A").substring(0, 21).padEnd(21), exception = (job.exception || "Unknown error").substring(0, 31).padEnd(31);
32
+ console.log(`\u2502 ${id} \u2502 ${queue} \u2502 ${failedAt} \u2502 ${exception} \u2502`);
33
+ }
34
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
35
+ console.log(`
36
+ Total: ${failedJobs.length} failed job(s)`);
37
+ process.exit(0);
38
+ } catch (error) {
39
+ const message = error instanceof Error ? error.message : String(error);
40
+ if (/no such table:\s*(?:jobs|failed_jobs)\b/i.test(message)) {
41
+ process.stdout.write(`Queue tables are not set up yet.
42
+ `);
43
+ process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");
44
+ process.exit(0);
45
+ }
46
+ log.error("Failed to fetch failed jobs", error);
47
+ process.exit(1);
48
+ }
49
+ function parseArgs() {
50
+ const args = {};
51
+ process.argv.forEach((arg) => {
52
+ if (arg.startsWith("--")) {
53
+ const [key, value] = arg.slice(2).split("=");
54
+ if (key && value)
55
+ args[key] = value;
56
+ }
57
+ });
58
+ return args;
59
+ }
60
+ function parseSinceDuration(input) {
61
+ const m = /^(\d+)([smhd])$/.exec(input.trim());
62
+ if (!m)
63
+ return null;
64
+ const n = Number(m[1]);
65
+ if (!Number.isFinite(n) || n <= 0)
66
+ return null;
67
+ const mult = m[2] === "s" ? 1000 : m[2] === "m" ? 60000 : m[2] === "h" ? 3600000 : 86400000;
68
+ return Date.now() - n * mult;
69
+ }
@@ -0,0 +1 @@
1
+ export {};