@stacksjs/buddy 0.70.258 → 0.70.259

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
@@ -1,241 +1 @@
1
- const commandRegistry = {
2
- about: { path: "./commands/about.js", exportName: "about" },
3
- add: { path: "./commands/add.js", exportName: "add" },
4
- "ai:context": { path: "./commands/ai-context.js", exportName: "aiContext" },
5
- auth: { path: "./commands/auth.js", exportName: "auth" },
6
- build: { path: "./commands/build.js", exportName: "build" },
7
- cd: { path: "./commands/cd.js", exportName: "cd" },
8
- changelog: { path: "./commands/changelog.js", exportName: "changelog" },
9
- clean: { path: "./commands/clean.js", exportName: "clean" },
10
- cloud: { path: "./commands/cloud.js", exportName: "cloud" },
11
- commit: { path: "./commands/commit.js", exportName: "commit" },
12
- completion: { path: "./commands/completion.js", exportName: "completion" },
13
- "config:migrate": { path: "./commands/config-migrate.js", exportName: "configMigrate" },
14
- configure: { path: "./commands/configure.js", exportName: "configure" },
15
- create: { path: "./commands/create.js", exportName: "create" },
16
- new: { path: "./commands/create.js", exportName: "create" },
17
- deploy: { path: "./commands/deploy.js", exportName: "deploy" },
18
- dev: { path: "./commands/dev.js", exportName: "dev" },
19
- "desktop:apple:doctor": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
20
- "desktop:apple:csr": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
21
- "desktop:apple:init": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
22
- "desktop:apple:package": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
23
- "desktop:apple:provision": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
24
- "desktop:apple:publish": { path: "./commands/desktop-apple.js", exportName: "desktopApple" },
25
- dns: { path: "./commands/dns.js", exportName: "dns" },
26
- "dns:pull": { path: "./commands/dns.js", exportName: "dns" },
27
- "dns:diff": { path: "./commands/dns.js", exportName: "dns" },
28
- "dns:sync": { path: "./commands/dns.js", exportName: "dns" },
29
- doctor: { path: "./commands/doctor.js", exportName: "doctor" },
30
- domains: { path: "./commands/domains.js", exportName: "domains" },
31
- email: { path: "./commands/email.js", exportName: "email" },
32
- env: { path: "./commands/env.js", exportName: "env" },
33
- "extension:init": { path: "./commands/extension.js", exportName: "extension" },
34
- "extension:build": { path: "./commands/extension.js", exportName: "extension" },
35
- "extension:package": { path: "./commands/extension.js", exportName: "extension" },
36
- "extension:chrome:publish": { path: "./commands/extension.js", exportName: "extension" },
37
- "extension:chrome:status": { path: "./commands/extension.js", exportName: "extension" },
38
- "extension:firefox:publish": { path: "./commands/extension.js", exportName: "extension" },
39
- "extension:safari:init": { path: "./commands/extension.js", exportName: "extension" },
40
- "extension:safari:provision": { path: "./commands/extension.js", exportName: "extension" },
41
- "extension:safari:app": { path: "./commands/extension.js", exportName: "extension" },
42
- "extension:safari:publish": { path: "./commands/extension.js", exportName: "extension" },
43
- "dashboard:install": { path: "./commands/features.js", exportName: "features" },
44
- "dashboard:uninstall": { path: "./commands/features.js", exportName: "features" },
45
- "commerce:install": { path: "./commands/features.js", exportName: "features" },
46
- "commerce:uninstall": { path: "./commands/features.js", exportName: "features" },
47
- "cms:install": { path: "./commands/features.js", exportName: "features" },
48
- "cms:uninstall": { path: "./commands/features.js", exportName: "features" },
49
- "marketing:install": { path: "./commands/features.js", exportName: "features" },
50
- "marketing:uninstall": { path: "./commands/features.js", exportName: "features" },
51
- "monitoring:install": { path: "./commands/features.js", exportName: "features" },
52
- "monitoring:uninstall": { path: "./commands/features.js", exportName: "features" },
53
- "realtime:install": { path: "./commands/features.js", exportName: "features" },
54
- "realtime:uninstall": { path: "./commands/features.js", exportName: "features" },
55
- "queue:install": { path: "./commands/features.js", exportName: "features" },
56
- "queue:uninstall": { path: "./commands/features.js", exportName: "features" },
57
- fresh: { path: "./commands/fresh.js", exportName: "fresh" },
58
- generate: { path: "./commands/generate.js", exportName: "generate" },
59
- http: { path: "./commands/http.js", exportName: "http" },
60
- install: { path: "./commands/install.js", exportName: "install" },
61
- key: { path: "./commands/key.js", exportName: "key" },
62
- lint: { path: "./commands/lint.js", exportName: "lint" },
63
- format: { path: "./commands/lint.js", exportName: "lint" },
64
- "format:check": { path: "./commands/lint.js", exportName: "lint" },
65
- list: { path: "./commands/list.js", exportName: "list" },
66
- mail: { path: "./commands/mail.js", exportName: "mailCommands" },
67
- "mail:preview": { path: "./commands/mail.js", exportName: "mailCommands" },
68
- maintenance: { path: "./commands/maintenance.js", exportName: "maintenance" },
69
- down: { path: "./commands/maintenance.js", exportName: "maintenance" },
70
- up: { path: "./commands/maintenance.js", exportName: "maintenance" },
71
- status: { path: "./commands/maintenance.js", exportName: "maintenance" },
72
- "coming-soon": { path: "./commands/maintenance.js", exportName: "maintenance" },
73
- "coming-soon:status": { path: "./commands/maintenance.js", exportName: "maintenance" },
74
- launch: { path: "./commands/maintenance.js", exportName: "maintenance" },
75
- make: { path: "./commands/make.js", exportName: "make" },
76
- "scaffold:crud": { path: "./commands/make.js", exportName: "make" },
77
- migrate: { path: "./commands/migrate.js", exportName: "migrate" },
78
- "migrate:fresh": { path: "./commands/migrate.js", exportName: "migrate" },
79
- "migrate:switch": { path: "./commands/migrate.js", exportName: "migrate" },
80
- "migrate:dns": { path: "./commands/migrate.js", exportName: "migrate" },
81
- "migrate:project": { path: "./commands/migrate-project.js", exportName: "migrateProject" },
82
- outdated: { path: "./commands/outdated.js", exportName: "outdated" },
83
- package: { path: "./commands/package.js", exportName: "packageCommands" },
84
- phone: { path: "./commands/phone.js", exportName: "phone" },
85
- ports: { path: "./commands/ports.js", exportName: "ports" },
86
- "link:core": { path: "./commands/link.js", exportName: "link" },
87
- "user:add": { path: "./commands/user.js", exportName: "user" },
88
- "user:list": { path: "./commands/user.js", exportName: "user" },
89
- "unlink:core": { path: "./commands/link.js", exportName: "link" },
90
- prepublish: { path: "./commands/prepublish.js", exportName: "prepublish" },
91
- projects: { path: "./commands/projects.js", exportName: "projects" },
92
- publish: { path: "./commands/publish.js", exportName: "publish" },
93
- "publish:model": { path: "./commands/publish.js", exportName: "publish" },
94
- "publish:controller": { path: "./commands/publish.js", exportName: "publish" },
95
- "publish:middleware": { path: "./commands/publish.js", exportName: "publish" },
96
- "publish:action": { path: "./commands/publish.js", exportName: "publish" },
97
- "publish:core": { path: "./commands/publish.js", exportName: "publish" },
98
- "core:status": { path: "./commands/publish.js", exportName: "publish" },
99
- queue: { path: "./commands/queue.js", exportName: "queue" },
100
- release: { path: "./commands/release.js", exportName: "release" },
101
- route: { path: "./commands/route.js", exportName: "route" },
102
- saas: { path: "./commands/saas.js", exportName: "saas" },
103
- "stripe:setup": { path: "./commands/saas.js", exportName: "saas" },
104
- schedule: { path: "./commands/schedule.js", exportName: "schedule" },
105
- search: { path: "./commands/search.js", exportName: "search" },
106
- "search-engine:update": { path: "./commands/search.js", exportName: "search" },
107
- "search-engine:settings": { path: "./commands/search.js", exportName: "search" },
108
- seed: { path: "./commands/seed.js", exportName: "seed" },
109
- "seed:roles": { path: "./commands/seed.js", exportName: "seed" },
110
- "roles:seed": { path: "./commands/seed.js", exportName: "seed" },
111
- preview: { path: "./commands/serve.js", exportName: "preview" },
112
- serve: { path: "./commands/serve.js", exportName: "serve" },
113
- "serve:api": { path: "./commands/serve.js", exportName: "serveApi" },
114
- setup: { path: "./commands/setup.js", exportName: "setup" },
115
- "setup:ai": { path: "./commands/setup.js", exportName: "setup" },
116
- "setup:ssl": { path: "./commands/setup.js", exportName: "setup" },
117
- "setup:oh-my-zsh": { path: "./commands/setup.js", exportName: "setup" },
118
- "ai:setup": { path: "./commands/setup.js", exportName: "setup" },
119
- share: { path: "./commands/share.js", exportName: "share" },
120
- stack: { path: "./commands/stacks.js", exportName: "stacks" },
121
- sms: { path: "./commands/sms.js", exportName: "sms" },
122
- telemetry: { path: "./commands/telemetry.js", exportName: "telemetryCommand" },
123
- test: { path: "./commands/test.js", exportName: "test" },
124
- tinker: { path: "./commands/tinker.js", exportName: "tinker" },
125
- types: { path: "./commands/types.js", exportName: "types" },
126
- undeploy: { path: "./commands/cloud.js", exportName: "cloud" },
127
- upgrade: { path: "./commands/upgrade.js", exportName: "upgrade" },
128
- version: { path: "./commands/version.js", exportName: "version" },
129
- "protocol:conformance": { path: "./commands/protocol.js", exportName: "protocol" },
130
- "protocol:sync": { path: "./commands/protocol.js", exportName: "protocol" },
131
- "protocol:check": { path: "./commands/protocol.js", exportName: "protocol" },
132
- "protocol:manifest": { path: "./commands/protocol.js", exportName: "protocol" },
133
- "protocol:manifest:check": { path: "./commands/protocol.js", exportName: "protocol" },
134
- "protocol:release": { path: "./commands/protocol.js", exportName: "protocol" },
135
- "protocol:release:check": { path: "./commands/protocol.js", exportName: "protocol" },
136
- "protocol:drivers": { path: "./commands/protocol.js", exportName: "protocol" },
137
- "protocol:drivers:check": { path: "./commands/protocol.js", exportName: "protocol" },
138
- "protocol:drivers:test": { path: "./commands/protocol.js", exportName: "protocol" },
139
- "protocol:desktop": { path: "./commands/protocol.js", exportName: "protocol" },
140
- "protocol:desktop:check": { path: "./commands/protocol.js", exportName: "protocol" },
141
- "protocol:pantry": { path: "./commands/protocol.js", exportName: "protocol" },
142
- "protocol:pantry:check": { path: "./commands/protocol.js", exportName: "protocol" },
143
- "protocol:craft": { path: "./commands/protocol.js", exportName: "protocol" },
144
- "protocol:craft:check": { path: "./commands/protocol.js", exportName: "protocol" },
145
- "docs:buddy": { path: "./commands/docs.js", exportName: "docs" },
146
- "docs:buddy:check": { path: "./commands/docs.js", exportName: "docs" },
147
- "docs:artifacts": { path: "./commands/docs.js", exportName: "docs" },
148
- "docs:artifacts:check": { path: "./commands/docs.js", exportName: "docs" },
149
- "docs:links": { path: "./commands/docs.js", exportName: "docs" },
150
- "docs:links:check": { path: "./commands/docs.js", exportName: "docs" }
151
- }, commandGroups = {
152
- minimal: ["version", "help"],
153
- development: ["dev", "build", "test", "lint"],
154
- database: ["migrate", "seed", "fresh"],
155
- scaffolding: ["make", "generate"],
156
- deployment: ["deploy", "release", "cloud"],
157
- info: ["about", "doctor", "list"]
158
- }, loadedRegistrars = new WeakMap;
159
- function loaderKey(loader) {
160
- return `${loader.path}#${loader.exportName}`;
161
- }
162
- export function markLoaded(buddy, commandName) {
163
- const loader = commandRegistry[commandName];
164
- if (!loader)
165
- return;
166
- let set = loadedRegistrars.get(buddy);
167
- if (!set) {
168
- set = new Set;
169
- loadedRegistrars.set(buddy, set);
170
- }
171
- set.add(loaderKey(loader));
172
- }
173
- export async function loadCommand(commandName, buddy) {
174
- const loader = commandRegistry[commandName];
175
- if (!loader)
176
- return !1;
177
- let set = loadedRegistrars.get(buddy);
178
- if (!set) {
179
- set = new Set;
180
- loadedRegistrars.set(buddy, set);
181
- }
182
- const key = loaderKey(loader);
183
- if (set.has(key))
184
- return !0;
185
- set.add(key);
186
- try {
187
- const commandFunction = (await import(loader.path))[loader.exportName];
188
- if (typeof commandFunction === "function") {
189
- commandFunction(buddy);
190
- return !0;
191
- } else
192
- return !1;
193
- } catch {
194
- return !1;
195
- }
196
- }
197
- export async function loadCommands(commandNames, buddy) {
198
- const timeout = (ms) => new Promise((_, reject) => setTimeout(() => reject(Error("timeout")), ms)), seen = new Set, unique = [];
199
- for (const name of commandNames) {
200
- const loader = commandRegistry[name], key = loader ? `${loader.path}#${loader.exportName}` : `name:${name}`;
201
- if (seen.has(key))
202
- continue;
203
- seen.add(key);
204
- unique.push(name);
205
- }
206
- await Promise.all(unique.map(async (name) => {
207
- try {
208
- await Promise.race([
209
- loadCommand(name, buddy),
210
- timeout(5000)
211
- ]);
212
- } catch {}
213
- }));
214
- }
215
- export async function loadCommandGroup(groupName, buddy) {
216
- const commands = commandGroups[groupName];
217
- if (commands)
218
- await loadCommands(commands, buddy);
219
- }
220
- export async function loadAllCommands(buddy) {
221
- const allCommands = Object.keys(commandRegistry);
222
- await loadCommands(allCommands, buddy);
223
- }
224
- export function getCommandNames() {
225
- return Object.keys(commandRegistry);
226
- }
227
- export function getCommandsToLoad(args) {
228
- const requestedCommand = args[0], isVersionFlag = requestedCommand === "--version" || requestedCommand === "-v", isHelpFlag = requestedCommand === "--help" || requestedCommand === "-h", isHelpWord = requestedCommand === "help";
229
- if (isVersionFlag)
230
- return ["version"];
231
- if (!requestedCommand || isHelpFlag || isHelpWord)
232
- return Object.keys(commandRegistry);
233
- const baseCommand = requestedCommand.split(":")[0];
234
- if (baseCommand === "list")
235
- return ["list", ...Object.keys(commandRegistry).filter((k) => k !== "list")];
236
- if (commandRegistry[requestedCommand])
237
- return [requestedCommand];
238
- if (commandRegistry[baseCommand])
239
- return [baseCommand];
240
- return Object.keys(commandRegistry);
241
- }
1
+ const commandRegistry={about:{path:"./commands/about.js",exportName:"about"},add:{path:"./commands/add.js",exportName:"add"},"ai:context":{path:"./commands/ai-context.js",exportName:"aiContext"},auth:{path:"./commands/auth.js",exportName:"auth"},build:{path:"./commands/build.js",exportName:"build"},cd:{path:"./commands/cd.js",exportName:"cd"},changelog:{path:"./commands/changelog.js",exportName:"changelog"},clean:{path:"./commands/clean.js",exportName:"clean"},cloud:{path:"./commands/cloud.js",exportName:"cloud"},commit:{path:"./commands/commit.js",exportName:"commit"},completion:{path:"./commands/completion.js",exportName:"completion"},"config:migrate":{path:"./commands/config-migrate.js",exportName:"configMigrate"},configure:{path:"./commands/configure.js",exportName:"configure"},create:{path:"./commands/create.js",exportName:"create"},new:{path:"./commands/create.js",exportName:"create"},deploy:{path:"./commands/deploy.js",exportName:"deploy"},dev:{path:"./commands/dev.js",exportName:"dev"},"desktop:apple:doctor":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:csr":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:init":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:package":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:provision":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},"desktop:apple:publish":{path:"./commands/desktop-apple.js",exportName:"desktopApple"},dns:{path:"./commands/dns.js",exportName:"dns"},"dns:pull":{path:"./commands/dns.js",exportName:"dns"},"dns:diff":{path:"./commands/dns.js",exportName:"dns"},"dns:sync":{path:"./commands/dns.js",exportName:"dns"},doctor:{path:"./commands/doctor.js",exportName:"doctor"},domains:{path:"./commands/domains.js",exportName:"domains"},email:{path:"./commands/email.js",exportName:"email"},env:{path:"./commands/env.js",exportName:"env"},"extension:init":{path:"./commands/extension.js",exportName:"extension"},"extension:build":{path:"./commands/extension.js",exportName:"extension"},"extension:package":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:chrome:status":{path:"./commands/extension.js",exportName:"extension"},"extension:firefox:publish":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:init":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:provision":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:app":{path:"./commands/extension.js",exportName:"extension"},"extension:safari:publish":{path:"./commands/extension.js",exportName:"extension"},"dashboard:install":{path:"./commands/features.js",exportName:"features"},"dashboard:uninstall":{path:"./commands/features.js",exportName:"features"},"commerce:install":{path:"./commands/features.js",exportName:"features"},"commerce:uninstall":{path:"./commands/features.js",exportName:"features"},"cms:install":{path:"./commands/features.js",exportName:"features"},"cms:uninstall":{path:"./commands/features.js",exportName:"features"},"marketing:install":{path:"./commands/features.js",exportName:"features"},"marketing:uninstall":{path:"./commands/features.js",exportName:"features"},"monitoring:install":{path:"./commands/features.js",exportName:"features"},"monitoring:uninstall":{path:"./commands/features.js",exportName:"features"},"realtime:install":{path:"./commands/features.js",exportName:"features"},"realtime:uninstall":{path:"./commands/features.js",exportName:"features"},"queue:install":{path:"./commands/features.js",exportName:"features"},"queue:uninstall":{path:"./commands/features.js",exportName:"features"},fresh:{path:"./commands/fresh.js",exportName:"fresh"},generate:{path:"./commands/generate.js",exportName:"generate"},http:{path:"./commands/http.js",exportName:"http"},install:{path:"./commands/install.js",exportName:"install"},key:{path:"./commands/key.js",exportName:"key"},lint:{path:"./commands/lint.js",exportName:"lint"},format:{path:"./commands/lint.js",exportName:"lint"},"format:check":{path:"./commands/lint.js",exportName:"lint"},list:{path:"./commands/list.js",exportName:"list"},mail:{path:"./commands/mail.js",exportName:"mailCommands"},"mail:preview":{path:"./commands/mail.js",exportName:"mailCommands"},maintenance:{path:"./commands/maintenance.js",exportName:"maintenance"},down:{path:"./commands/maintenance.js",exportName:"maintenance"},up:{path:"./commands/maintenance.js",exportName:"maintenance"},status:{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon":{path:"./commands/maintenance.js",exportName:"maintenance"},"coming-soon:status":{path:"./commands/maintenance.js",exportName:"maintenance"},launch:{path:"./commands/maintenance.js",exportName:"maintenance"},make:{path:"./commands/make.js",exportName:"make"},"scaffold:crud":{path:"./commands/make.js",exportName:"make"},migrate:{path:"./commands/migrate.js",exportName:"migrate"},"migrate:fresh":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:switch":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:dns":{path:"./commands/migrate.js",exportName:"migrate"},"migrate:project":{path:"./commands/migrate-project.js",exportName:"migrateProject"},outdated:{path:"./commands/outdated.js",exportName:"outdated"},package:{path:"./commands/package.js",exportName:"packageCommands"},phone:{path:"./commands/phone.js",exportName:"phone"},ports:{path:"./commands/ports.js",exportName:"ports"},"link:core":{path:"./commands/link.js",exportName:"link"},"user:add":{path:"./commands/user.js",exportName:"user"},"user:list":{path:"./commands/user.js",exportName:"user"},"unlink:core":{path:"./commands/link.js",exportName:"link"},prepublish:{path:"./commands/prepublish.js",exportName:"prepublish"},projects:{path:"./commands/projects.js",exportName:"projects"},publish:{path:"./commands/publish.js",exportName:"publish"},"publish:model":{path:"./commands/publish.js",exportName:"publish"},"publish:controller":{path:"./commands/publish.js",exportName:"publish"},"publish:middleware":{path:"./commands/publish.js",exportName:"publish"},"publish:action":{path:"./commands/publish.js",exportName:"publish"},"publish:core":{path:"./commands/publish.js",exportName:"publish"},"core:status":{path:"./commands/publish.js",exportName:"publish"},queue:{path:"./commands/queue.js",exportName:"queue"},release:{path:"./commands/release.js",exportName:"release"},route:{path:"./commands/route.js",exportName:"route"},saas:{path:"./commands/saas.js",exportName:"saas"},"stripe:setup":{path:"./commands/saas.js",exportName:"saas"},schedule:{path:"./commands/schedule.js",exportName:"schedule"},search:{path:"./commands/search.js",exportName:"search"},"search-engine:update":{path:"./commands/search.js",exportName:"search"},"search-engine:settings":{path:"./commands/search.js",exportName:"search"},seed:{path:"./commands/seed.js",exportName:"seed"},"seed:roles":{path:"./commands/seed.js",exportName:"seed"},"roles:seed":{path:"./commands/seed.js",exportName:"seed"},preview:{path:"./commands/serve.js",exportName:"preview"},serve:{path:"./commands/serve.js",exportName:"serve"},"serve:api":{path:"./commands/serve.js",exportName:"serveApi"},setup:{path:"./commands/setup.js",exportName:"setup"},"setup:ai":{path:"./commands/setup.js",exportName:"setup"},"setup:ssl":{path:"./commands/setup.js",exportName:"setup"},"setup:oh-my-zsh":{path:"./commands/setup.js",exportName:"setup"},"ai:setup":{path:"./commands/setup.js",exportName:"setup"},share:{path:"./commands/share.js",exportName:"share"},stack:{path:"./commands/stacks.js",exportName:"stacks"},sms:{path:"./commands/sms.js",exportName:"sms"},telemetry:{path:"./commands/telemetry.js",exportName:"telemetryCommand"},test:{path:"./commands/test.js",exportName:"test"},tinker:{path:"./commands/tinker.js",exportName:"tinker"},types:{path:"./commands/types.js",exportName:"types"},undeploy:{path:"./commands/cloud.js",exportName:"cloud"},upgrade:{path:"./commands/upgrade.js",exportName:"upgrade"},version:{path:"./commands/version.js",exportName:"version"},"protocol:conformance":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:sync":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:manifest":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:manifest:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:release":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:release:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:drivers":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:drivers:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:drivers:test":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:desktop":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:desktop:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:pantry":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:pantry:check":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:craft":{path:"./commands/protocol.js",exportName:"protocol"},"protocol:craft:check":{path:"./commands/protocol.js",exportName:"protocol"},"docs:buddy":{path:"./commands/docs.js",exportName:"docs"},"docs:buddy:check":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts":{path:"./commands/docs.js",exportName:"docs"},"docs:artifacts:check":{path:"./commands/docs.js",exportName:"docs"},"docs:links":{path:"./commands/docs.js",exportName:"docs"},"docs:links:check":{path:"./commands/docs.js",exportName:"docs"}},commandGroups={minimal:["version","help"],development:["dev","build","test","lint"],database:["migrate","seed","fresh"],scaffolding:["make","generate"],deployment:["deploy","release","cloud"],info:["about","doctor","list"]},loadedRegistrars=new WeakMap;function loaderKey(loader){return`${loader.path}#${loader.exportName}`}export function markLoaded(buddy,commandName){const loader=commandRegistry[commandName];if(!loader)return;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}set.add(loaderKey(loader))}export async function loadCommand(commandName,buddy){const loader=commandRegistry[commandName];if(!loader)return!1;let set=loadedRegistrars.get(buddy);if(!set){set=new Set;loadedRegistrars.set(buddy,set)}const key=loaderKey(loader);if(set.has(key))return!0;set.add(key);try{const commandFunction=(await import(loader.path))[loader.exportName];if(typeof commandFunction==="function"){commandFunction(buddy);return!0}else return!1}catch{return!1}}export async function loadCommands(commandNames,buddy){const timeout=(ms)=>new Promise((_,reject)=>setTimeout(()=>reject(Error("timeout")),ms)),seen=new Set,unique=[];for(const name of commandNames){const loader=commandRegistry[name],key=loader?`${loader.path}#${loader.exportName}`:`name:${name}`;if(seen.has(key))continue;seen.add(key);unique.push(name)}await Promise.all(unique.map(async(name)=>{try{await Promise.race([loadCommand(name,buddy),timeout(5000)])}catch{}}))}export async function loadCommandGroup(groupName,buddy){const commands=commandGroups[groupName];if(commands)await loadCommands(commands,buddy)}export async function loadAllCommands(buddy){const allCommands=Object.keys(commandRegistry);await loadCommands(allCommands,buddy)}export function getCommandNames(){return Object.keys(commandRegistry)}export function getCommandsToLoad(args){const requestedCommand=args[0],isVersionFlag=requestedCommand==="--version"||requestedCommand==="-v",isHelpFlag=requestedCommand==="--help"||requestedCommand==="-h",isHelpWord=requestedCommand==="help";if(isVersionFlag)return["version"];if(!requestedCommand||isHelpFlag||isHelpWord)return Object.keys(commandRegistry);const baseCommand=requestedCommand.split(":")[0];if(baseCommand==="list")return["list",...Object.keys(commandRegistry).filter((k)=>k!=="list")];if(commandRegistry[requestedCommand])return[requestedCommand];if(commandRegistry[baseCommand])return[baseCommand];return Object.keys(commandRegistry)}
@@ -1,62 +1,2 @@
1
- import { laravelDriver } from "./laravel";
2
- import { railsDriver } from "./rails";
3
- export const DRIVERS = {
4
- laravel: laravelDriver,
5
- rails: railsDriver
6
- };
7
- export async function runMigrator(req) {
8
- const driver = DRIVERS[req.from];
9
- if (!driver)
10
- throw Error(`Unknown source framework: ${req.from}. Supported: ${Object.keys(DRIVERS).join(", ")}`);
11
- const startedAt = new Date().toISOString(), entries = await driver.migrate(req), finishedAt = new Date().toISOString();
12
- return {
13
- source: req.source,
14
- target: req.target,
15
- from: req.from,
16
- startedAt,
17
- finishedAt,
18
- entries
19
- };
20
- }
21
- export function renderReport(report) {
22
- const lines = [];
23
- lines.push(`# Migration report \u2014 ${report.from} \u2192 Stacks`);
24
- lines.push("");
25
- lines.push(`- **Source**: \`${report.source}\``);
26
- lines.push(`- **Target**: \`${report.target}\``);
27
- lines.push(`- **Started**: ${report.startedAt}`);
28
- lines.push(`- **Finished**: ${report.finishedAt}`);
29
- lines.push("");
30
- const groups = groupEntriesByStatus(report.entries);
31
- for (const [status, label] of [
32
- ["translated", "Translated"],
33
- ["copied", "Copied verbatim"],
34
- ["skipped", "Skipped (hand-port required)"],
35
- ["failed", "Failed"]
36
- ]) {
37
- const group = groups[status] ?? [];
38
- if (group.length === 0)
39
- continue;
40
- lines.push(`## ${label} (${group.length})`);
41
- lines.push("");
42
- for (const e of group) {
43
- const arrow = e.target ? ` \u2192 \`${e.target}\`` : "", note = e.note ? ` \u2014 ${e.note}` : "";
44
- lines.push(`- \`${e.source}\`${arrow}${note}`);
45
- }
46
- lines.push("");
47
- }
48
- lines.push("---");
49
- lines.push("");
50
- lines.push("Re-run `./buddy migrate:project <name> --from=" + report.from + "` after fixing the source project to refresh emitted files. Translated outputs are overwritten; skipped entries are not.");
51
- return lines.join(`
52
- `);
53
- }
54
- function groupEntriesByStatus(entries) {
55
- const out = {};
56
- for (const e of entries) {
57
- if (!out[e.status])
58
- out[e.status] = [];
59
- out[e.status].push(e);
60
- }
61
- return out;
62
- }
1
+ import{laravelDriver}from"./laravel";import{railsDriver}from"./rails";export const DRIVERS={laravel:laravelDriver,rails:railsDriver};export async function runMigrator(req){const driver=DRIVERS[req.from];if(!driver)throw Error(`Unknown source framework: ${req.from}. Supported: ${Object.keys(DRIVERS).join(", ")}`);const startedAt=new Date().toISOString(),entries=await driver.migrate(req),finishedAt=new Date().toISOString();return{source:req.source,target:req.target,from:req.from,startedAt,finishedAt,entries}}export function renderReport(report){const lines=[];lines.push(`# Migration report \u2014 ${report.from} \u2192 Stacks`);lines.push("");lines.push(`- **Source**: \`${report.source}\``);lines.push(`- **Target**: \`${report.target}\``);lines.push(`- **Started**: ${report.startedAt}`);lines.push(`- **Finished**: ${report.finishedAt}`);lines.push("");const groups=groupEntriesByStatus(report.entries);for(const[status,label]of[["translated","Translated"],["copied","Copied verbatim"],["skipped","Skipped (hand-port required)"],["failed","Failed"]]){const group=groups[status]??[];if(group.length===0)continue;lines.push(`## ${label} (${group.length})`);lines.push("");for(const e of group){const arrow=e.target?` \u2192 \`${e.target}\``:"",note=e.note?` \u2014 ${e.note}`:"";lines.push(`- \`${e.source}\`${arrow}${note}`)}lines.push("")}lines.push("---");lines.push("");lines.push("Re-run `./buddy migrate:project <name> --from="+report.from+"` after fixing the source project to refresh emitted files. Translated outputs are overwritten; skipped entries are not.");return lines.join(`
2
+ `)}function groupEntriesByStatus(entries){const out={};for(const e of entries){if(!out[e.status])out[e.status]=[];out[e.status].push(e)}return out}
@@ -1,148 +1 @@
1
- import { existsSync, readdirSync } from "node:fs";
2
- import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
3
- import { basename, join } from "node:path";
4
- import { laravelFilenameToStacks, parseLaravelMigration } from "./migrations";
5
- import { parseLaravelModel } from "./models";
6
- export const laravelDriver = {
7
- name: "laravel",
8
- async migrate(req) {
9
- const entries = [];
10
- entries.push(...await migrateEnv(req));
11
- entries.push(...await migrateMigrations(req));
12
- entries.push(...await migrateModels(req));
13
- entries.push(...summariseDeferred(req));
14
- return entries;
15
- }
16
- };
17
- async function migrateEnv(req) {
18
- const out = [];
19
- for (const file of [".env", ".env.example"]) {
20
- const sourcePath = join(req.source, file);
21
- if (!existsSync(sourcePath))
22
- continue;
23
- const targetPath = join(req.target, file);
24
- if (!req.dryRun) {
25
- await mkdir(req.target, { recursive: !0 });
26
- await copyFile(sourcePath, targetPath);
27
- }
28
- out.push({
29
- source: file,
30
- target: file,
31
- status: "copied",
32
- note: "Laravel-specific keys (BROADCAST_DRIVER, FILESYSTEM_DISK names) may need renaming; Stacks reads APP_*/DB_*/MAIL_* keys as-is."
33
- });
34
- }
35
- return out;
36
- }
37
- async function migrateMigrations(req) {
38
- const dir = join(req.source, "database", "migrations");
39
- if (!existsSync(dir))
40
- return [];
41
- const files = readdirSync(dir).filter((f) => f.endsWith(".php")).sort(), targetDir = join(req.target, "database", "migrations");
42
- if (!req.dryRun)
43
- await mkdir(targetDir, { recursive: !0 });
44
- const out = [];
45
- for (let i = 0;i < files.length; i++) {
46
- const file = files[i], rel = `database/migrations/${file}`;
47
- try {
48
- const body = await readFile(join(dir, file), "utf8"), parsed = parseLaravelMigration(body);
49
- if (!parsed) {
50
- out.push({
51
- source: rel,
52
- target: "",
53
- status: "skipped",
54
- note: "No `Schema::create(...)` block found (likely an alter / drop / data-only migration)."
55
- });
56
- continue;
57
- }
58
- const sequence = i + 1, outRel = `database/migrations/${laravelFilenameToStacks(file, sequence, parsed.table)}`;
59
- if (!req.dryRun)
60
- await writeFile(join(req.target, outRel), parsed.sql);
61
- const skippedNote = parsed.skipped.length > 0 ? ` Skipped ${parsed.skipped.length} line(s) inside the create block \u2014 hand-port from the source migration.` : "";
62
- out.push({
63
- source: rel,
64
- target: outRel,
65
- status: "translated",
66
- note: `CREATE TABLE \`${parsed.table}\` emitted.${skippedNote}`
67
- });
68
- } catch (err) {
69
- out.push({
70
- source: rel,
71
- target: "",
72
- status: "failed",
73
- note: `Parse error: ${err instanceof Error ? err.message : String(err)}`
74
- });
75
- }
76
- }
77
- return out;
78
- }
79
- async function migrateModels(req) {
80
- const dir = join(req.source, "app", "Models");
81
- if (!existsSync(dir))
82
- return [];
83
- const files = readdirSync(dir).filter((f) => f.endsWith(".php")), targetDir = join(req.target, "app", "Models");
84
- if (!req.dryRun)
85
- await mkdir(targetDir, { recursive: !0 });
86
- const out = [];
87
- for (const file of files) {
88
- const rel = `app/Models/${file}`;
89
- try {
90
- const body = await readFile(join(dir, file), "utf8"), parsed = parseLaravelModel(body);
91
- if (!parsed) {
92
- out.push({
93
- source: rel,
94
- target: "",
95
- status: "skipped",
96
- note: "No class declaration found."
97
- });
98
- continue;
99
- }
100
- const outRel = `app/Models/${`${parsed.className}.ts`}`;
101
- if (!req.dryRun)
102
- await writeFile(join(req.target, outRel), parsed.tsSource);
103
- const notes = [
104
- `Attributes: ${parsed.fillable.length} fillable, ${Object.keys(parsed.casts).length} cast`,
105
- parsed.relationships.length > 0 ? `Relationships: ${parsed.relationships.map((r) => `${r.name}(${r.kind})`).join(", ")}` : null,
106
- ...parsed.notes
107
- ].filter(Boolean).join(" | ");
108
- out.push({
109
- source: rel,
110
- target: outRel,
111
- status: "translated",
112
- note: notes || `Model ${parsed.className} emitted.`
113
- });
114
- } catch (err) {
115
- out.push({
116
- source: rel,
117
- target: "",
118
- status: "failed",
119
- note: `Parse error: ${err instanceof Error ? err.message : String(err)}`
120
- });
121
- }
122
- }
123
- return out;
124
- }
125
- const DEFERRED_SURFACES = [
126
- { path: "routes", note: "routes/web.php + routes/api.php \u2014 port to routes/web.ts + routes/api.ts using the Stacks router DSL." },
127
- { path: "app/Http/Controllers", note: "Controllers \u2192 Stacks Actions in app/Actions/. Each controller method maps to one Action file." },
128
- { path: "resources/views", note: "Blade templates \u2192 stx components in resources/views/." },
129
- { path: "database/seeders", note: "Seeders \u2192 database/seeders/*.ts using Stacks SeederContract." },
130
- { path: "app/Console/Commands", note: "Artisan commands \u2192 app/Commands/*.ts in your Stacks project." },
131
- { path: "app/Jobs", note: "Queue jobs \u2192 app/Jobs/*.ts; pair with config/queue.ts driver settings." },
132
- { path: "composer.json", note: "Dependency map \u2014 Laravel packages don't translate 1:1; the Stacks docs cover the closest @stacksjs/* equivalents." }
133
- ];
134
- function summariseDeferred(req) {
135
- const out = [];
136
- for (const surface of DEFERRED_SURFACES) {
137
- const sourcePath = join(req.source, surface.path);
138
- if (!existsSync(sourcePath))
139
- continue;
140
- out.push({
141
- source: surface.path,
142
- target: "",
143
- status: "skipped",
144
- note: surface.note
145
- });
146
- }
147
- return out;
148
- }
1
+ import{existsSync,readdirSync}from"node:fs";import{copyFile,mkdir,readFile,writeFile}from"node:fs/promises";import{basename,join}from"node:path";import{laravelFilenameToStacks,parseLaravelMigration}from"./migrations";import{parseLaravelModel}from"./models";export const laravelDriver={name:"laravel",async migrate(req){const entries=[];entries.push(...await migrateEnv(req));entries.push(...await migrateMigrations(req));entries.push(...await migrateModels(req));entries.push(...summariseDeferred(req));return entries}};async function migrateEnv(req){const out=[];for(const file of[".env",".env.example"]){const sourcePath=join(req.source,file);if(!existsSync(sourcePath))continue;const targetPath=join(req.target,file);if(!req.dryRun){await mkdir(req.target,{recursive:!0});await copyFile(sourcePath,targetPath)}out.push({source:file,target:file,status:"copied",note:"Laravel-specific keys (BROADCAST_DRIVER, FILESYSTEM_DISK names) may need renaming; Stacks reads APP_*/DB_*/MAIL_* keys as-is."})}return out}async function migrateMigrations(req){const dir=join(req.source,"database","migrations");if(!existsSync(dir))return[];const files=readdirSync(dir).filter((f)=>f.endsWith(".php")).sort(),targetDir=join(req.target,"database","migrations");if(!req.dryRun)await mkdir(targetDir,{recursive:!0});const out=[];for(let i=0;i<files.length;i++){const file=files[i],rel=`database/migrations/${file}`;try{const body=await readFile(join(dir,file),"utf8"),parsed=parseLaravelMigration(body);if(!parsed){out.push({source:rel,target:"",status:"skipped",note:"No `Schema::create(...)` block found (likely an alter / drop / data-only migration)."});continue}const sequence=i+1,outRel=`database/migrations/${laravelFilenameToStacks(file,sequence,parsed.table)}`;if(!req.dryRun)await writeFile(join(req.target,outRel),parsed.sql);const skippedNote=parsed.skipped.length>0?` Skipped ${parsed.skipped.length} line(s) inside the create block \u2014 hand-port from the source migration.`:"";out.push({source:rel,target:outRel,status:"translated",note:`CREATE TABLE \`${parsed.table}\` emitted.${skippedNote}`})}catch(err){out.push({source:rel,target:"",status:"failed",note:`Parse error: ${err instanceof Error?err.message:String(err)}`})}}return out}async function migrateModels(req){const dir=join(req.source,"app","Models");if(!existsSync(dir))return[];const files=readdirSync(dir).filter((f)=>f.endsWith(".php")),targetDir=join(req.target,"app","Models");if(!req.dryRun)await mkdir(targetDir,{recursive:!0});const out=[];for(const file of files){const rel=`app/Models/${file}`;try{const body=await readFile(join(dir,file),"utf8"),parsed=parseLaravelModel(body);if(!parsed){out.push({source:rel,target:"",status:"skipped",note:"No class declaration found."});continue}const outRel=`app/Models/${`${parsed.className}.ts`}`;if(!req.dryRun)await writeFile(join(req.target,outRel),parsed.tsSource);const notes=[`Attributes: ${parsed.fillable.length} fillable, ${Object.keys(parsed.casts).length} cast`,parsed.relationships.length>0?`Relationships: ${parsed.relationships.map((r)=>`${r.name}(${r.kind})`).join(", ")}`:null,...parsed.notes].filter(Boolean).join(" | ");out.push({source:rel,target:outRel,status:"translated",note:notes||`Model ${parsed.className} emitted.`})}catch(err){out.push({source:rel,target:"",status:"failed",note:`Parse error: ${err instanceof Error?err.message:String(err)}`})}}return out}const DEFERRED_SURFACES=[{path:"routes",note:"routes/web.php + routes/api.php \u2014 port to routes/web.ts + routes/api.ts using the Stacks router DSL."},{path:"app/Http/Controllers",note:"Controllers \u2192 Stacks Actions in app/Actions/. Each controller method maps to one Action file."},{path:"resources/views",note:"Blade templates \u2192 stx components in resources/views/."},{path:"database/seeders",note:"Seeders \u2192 database/seeders/*.ts using Stacks SeederContract."},{path:"app/Console/Commands",note:"Artisan commands \u2192 app/Commands/*.ts in your Stacks project."},{path:"app/Jobs",note:"Queue jobs \u2192 app/Jobs/*.ts; pair with config/queue.ts driver settings."},{path:"composer.json",note:"Dependency map \u2014 Laravel packages don't translate 1:1; the Stacks docs cover the closest @stacksjs/* equivalents."}];function summariseDeferred(req){const out=[];for(const surface of DEFERRED_SURFACES){const sourcePath=join(req.source,surface.path);if(!existsSync(sourcePath))continue;out.push({source:surface.path,target:"",status:"skipped",note:surface.note})}return out}