@stacksjs/buddy 0.70.86 → 0.70.88

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 (143) hide show
  1. package/package.json +2 -2
  2. package/dist/cli.d.ts +0 -1
  3. package/dist/cli.js +0 -165
  4. package/dist/commands/about.d.ts +0 -2
  5. package/dist/commands/about.js +0 -35
  6. package/dist/commands/add.d.ts +0 -2
  7. package/dist/commands/add.js +0 -33
  8. package/dist/commands/auth.d.ts +0 -2
  9. package/dist/commands/auth.js +0 -68
  10. package/dist/commands/build.d.ts +0 -2
  11. package/dist/commands/build.js +0 -153
  12. package/dist/commands/cd.d.ts +0 -20
  13. package/dist/commands/cd.js +0 -39
  14. package/dist/commands/changelog.d.ts +0 -2
  15. package/dist/commands/changelog.js +0 -32
  16. package/dist/commands/clean.d.ts +0 -2
  17. package/dist/commands/clean.js +0 -37
  18. package/dist/commands/cloud.d.ts +0 -2
  19. package/dist/commands/cloud.js +0 -503
  20. package/dist/commands/commit.d.ts +0 -2
  21. package/dist/commands/commit.js +0 -16
  22. package/dist/commands/completion.d.ts +0 -2
  23. package/dist/commands/completion.js +0 -143
  24. package/dist/commands/config-migrate.d.ts +0 -26
  25. package/dist/commands/config-migrate.js +0 -94
  26. package/dist/commands/configure.d.ts +0 -2
  27. package/dist/commands/configure.js +0 -48
  28. package/dist/commands/create.d.ts +0 -2
  29. package/dist/commands/create.js +0 -141
  30. package/dist/commands/deploy.d.ts +0 -107
  31. package/dist/commands/deploy.js +0 -1439
  32. package/dist/commands/dev.d.ts +0 -10
  33. package/dist/commands/dev.js +0 -907
  34. package/dist/commands/dns.d.ts +0 -2
  35. package/dist/commands/dns.js +0 -102
  36. package/dist/commands/doctor.d.ts +0 -2
  37. package/dist/commands/doctor.js +0 -285
  38. package/dist/commands/domains.d.ts +0 -2
  39. package/dist/commands/domains.js +0 -159
  40. package/dist/commands/email.d.ts +0 -2
  41. package/dist/commands/email.js +0 -524
  42. package/dist/commands/env.d.ts +0 -2
  43. package/dist/commands/env.js +0 -246
  44. package/dist/commands/extension.d.ts +0 -8
  45. package/dist/commands/extension.js +0 -78
  46. package/dist/commands/features.d.ts +0 -180
  47. package/dist/commands/features.js +0 -422
  48. package/dist/commands/fresh.d.ts +0 -2
  49. package/dist/commands/fresh.js +0 -39
  50. package/dist/commands/generate.d.ts +0 -2
  51. package/dist/commands/generate.js +0 -104
  52. package/dist/commands/http.d.ts +0 -2
  53. package/dist/commands/http.js +0 -33
  54. package/dist/commands/index.d.ts +0 -53
  55. package/dist/commands/index.js +0 -53
  56. package/dist/commands/install.d.ts +0 -2
  57. package/dist/commands/install.js +0 -22
  58. package/dist/commands/key.d.ts +0 -2
  59. package/dist/commands/key.js +0 -23
  60. package/dist/commands/lint.d.ts +0 -2
  61. package/dist/commands/lint.js +0 -46
  62. package/dist/commands/list.d.ts +0 -2
  63. package/dist/commands/list.js +0 -108
  64. package/dist/commands/mail.d.ts +0 -2
  65. package/dist/commands/mail.js +0 -693
  66. package/dist/commands/maintenance.d.ts +0 -2
  67. package/dist/commands/maintenance.js +0 -141
  68. package/dist/commands/make.d.ts +0 -2
  69. package/dist/commands/make.js +0 -375
  70. package/dist/commands/migrate-project.d.ts +0 -2
  71. package/dist/commands/migrate-project.js +0 -49
  72. package/dist/commands/migrate.d.ts +0 -4
  73. package/dist/commands/migrate.js +0 -455
  74. package/dist/commands/outdated.d.ts +0 -2
  75. package/dist/commands/outdated.js +0 -19
  76. package/dist/commands/package.d.ts +0 -2
  77. package/dist/commands/package.js +0 -17
  78. package/dist/commands/phone.d.ts +0 -2
  79. package/dist/commands/phone.js +0 -188
  80. package/dist/commands/ports.d.ts +0 -2
  81. package/dist/commands/ports.js +0 -118
  82. package/dist/commands/prepublish.d.ts +0 -2
  83. package/dist/commands/prepublish.js +0 -17
  84. package/dist/commands/projects.d.ts +0 -2
  85. package/dist/commands/projects.js +0 -29
  86. package/dist/commands/publish.d.ts +0 -2
  87. package/dist/commands/publish.js +0 -172
  88. package/dist/commands/queue.d.ts +0 -2
  89. package/dist/commands/queue.js +0 -248
  90. package/dist/commands/release.d.ts +0 -2
  91. package/dist/commands/release.js +0 -30
  92. package/dist/commands/route.d.ts +0 -2
  93. package/dist/commands/route.js +0 -21
  94. package/dist/commands/saas.d.ts +0 -2
  95. package/dist/commands/saas.js +0 -25
  96. package/dist/commands/schedule.d.ts +0 -2
  97. package/dist/commands/schedule.js +0 -61
  98. package/dist/commands/search.d.ts +0 -2
  99. package/dist/commands/search.js +0 -84
  100. package/dist/commands/seed.d.ts +0 -2
  101. package/dist/commands/seed.js +0 -71
  102. package/dist/commands/serve.d.ts +0 -25
  103. package/dist/commands/serve.js +0 -182
  104. package/dist/commands/setup.d.ts +0 -12
  105. package/dist/commands/setup.js +0 -215
  106. package/dist/commands/share.d.ts +0 -2
  107. package/dist/commands/share.js +0 -214
  108. package/dist/commands/sms.d.ts +0 -2
  109. package/dist/commands/sms.js +0 -328
  110. package/dist/commands/stacks.d.ts +0 -2
  111. package/dist/commands/stacks.js +0 -69
  112. package/dist/commands/telemetry.d.ts +0 -2
  113. package/dist/commands/telemetry.js +0 -74
  114. package/dist/commands/test.d.ts +0 -2
  115. package/dist/commands/test.js +0 -130
  116. package/dist/commands/tinker.d.ts +0 -2
  117. package/dist/commands/tinker.js +0 -37
  118. package/dist/commands/types.d.ts +0 -2
  119. package/dist/commands/types.js +0 -18
  120. package/dist/commands/upgrade.d.ts +0 -2
  121. package/dist/commands/upgrade.js +0 -98
  122. package/dist/commands/version.d.ts +0 -2
  123. package/dist/commands/version.js +0 -16
  124. package/dist/config.d.ts +0 -43
  125. package/dist/config.js +0 -223
  126. package/dist/custom-cli.d.ts +0 -1
  127. package/dist/custom-cli.js +0 -23
  128. package/dist/index.d.ts +0 -1
  129. package/dist/index.js +0 -1
  130. package/dist/lazy-commands.d.ts +0 -61
  131. package/dist/lazy-commands.js +0 -188
  132. package/dist/migrators/index.d.ts +0 -9
  133. package/dist/migrators/index.js +0 -62
  134. package/dist/migrators/laravel/index.d.ts +0 -2
  135. package/dist/migrators/laravel/index.js +0 -148
  136. package/dist/migrators/laravel/migrations.d.ts +0 -52
  137. package/dist/migrators/laravel/migrations.js +0 -232
  138. package/dist/migrators/laravel/models.d.ts +0 -34
  139. package/dist/migrators/laravel/models.js +0 -134
  140. package/dist/migrators/rails/index.d.ts +0 -2
  141. package/dist/migrators/rails/index.js +0 -11
  142. package/dist/migrators/types.d.ts +0 -44
  143. package/dist/migrators/types.js +0 -0
@@ -1,188 +0,0 @@
1
- const commandRegistry = {
2
- about: { path: "./commands/about.js", exportName: "about" },
3
- add: { path: "./commands/add.js", exportName: "add" },
4
- auth: { path: "./commands/auth.js", exportName: "auth" },
5
- build: { path: "./commands/build.js", exportName: "build" },
6
- cd: { path: "./commands/cd.js", exportName: "cd" },
7
- changelog: { path: "./commands/changelog.js", exportName: "changelog" },
8
- clean: { path: "./commands/clean.js", exportName: "clean" },
9
- cloud: { path: "./commands/cloud.js", exportName: "cloud" },
10
- commit: { path: "./commands/commit.js", exportName: "commit" },
11
- completion: { path: "./commands/completion.js", exportName: "completion" },
12
- "config:migrate": { path: "./commands/config-migrate.js", exportName: "configMigrate" },
13
- configure: { path: "./commands/configure.js", exportName: "configure" },
14
- create: { path: "./commands/create.js", exportName: "create" },
15
- deploy: { path: "./commands/deploy.js", exportName: "deploy" },
16
- dev: { path: "./commands/dev.js", exportName: "dev" },
17
- dns: { path: "./commands/dns.js", exportName: "dns" },
18
- "dns:pull": { path: "./commands/dns.js", exportName: "dns" },
19
- "dns:diff": { path: "./commands/dns.js", exportName: "dns" },
20
- "dns:sync": { path: "./commands/dns.js", exportName: "dns" },
21
- doctor: { path: "./commands/doctor.js", exportName: "doctor" },
22
- domains: { path: "./commands/domains.js", exportName: "domains" },
23
- email: { path: "./commands/email.js", exportName: "email" },
24
- env: { path: "./commands/env.js", exportName: "env" },
25
- "extension:init": { path: "./commands/extension.js", exportName: "extension" },
26
- "extension:build": { path: "./commands/extension.js", exportName: "extension" },
27
- "extension:package": { path: "./commands/extension.js", exportName: "extension" },
28
- "dashboard:install": { path: "./commands/features.js", exportName: "features" },
29
- "dashboard:uninstall": { path: "./commands/features.js", exportName: "features" },
30
- "commerce:install": { path: "./commands/features.js", exportName: "features" },
31
- "commerce:uninstall": { path: "./commands/features.js", exportName: "features" },
32
- "cms:install": { path: "./commands/features.js", exportName: "features" },
33
- "cms:uninstall": { path: "./commands/features.js", exportName: "features" },
34
- "marketing:install": { path: "./commands/features.js", exportName: "features" },
35
- "marketing:uninstall": { path: "./commands/features.js", exportName: "features" },
36
- "monitoring:install": { path: "./commands/features.js", exportName: "features" },
37
- "monitoring:uninstall": { path: "./commands/features.js", exportName: "features" },
38
- "realtime:install": { path: "./commands/features.js", exportName: "features" },
39
- "realtime:uninstall": { path: "./commands/features.js", exportName: "features" },
40
- "queue:install": { path: "./commands/features.js", exportName: "features" },
41
- "queue:uninstall": { path: "./commands/features.js", exportName: "features" },
42
- fresh: { path: "./commands/fresh.js", exportName: "fresh" },
43
- generate: { path: "./commands/generate.js", exportName: "generate" },
44
- http: { path: "./commands/http.js", exportName: "http" },
45
- install: { path: "./commands/install.js", exportName: "install" },
46
- key: { path: "./commands/key.js", exportName: "key" },
47
- lint: { path: "./commands/lint.js", exportName: "lint" },
48
- list: { path: "./commands/list.js", exportName: "list" },
49
- mail: { path: "./commands/mail.js", exportName: "mailCommands" },
50
- "mail:preview": { path: "./commands/mail.js", exportName: "mailCommands" },
51
- maintenance: { path: "./commands/maintenance.js", exportName: "maintenance" },
52
- down: { path: "./commands/maintenance.js", exportName: "maintenance" },
53
- up: { path: "./commands/maintenance.js", exportName: "maintenance" },
54
- status: { path: "./commands/maintenance.js", exportName: "maintenance" },
55
- make: { path: "./commands/make.js", exportName: "make" },
56
- migrate: { path: "./commands/migrate.js", exportName: "migrate" },
57
- "migrate:fresh": { path: "./commands/migrate.js", exportName: "migrate" },
58
- "migrate:switch": { path: "./commands/migrate.js", exportName: "migrate" },
59
- "migrate:dns": { path: "./commands/migrate.js", exportName: "migrate" },
60
- "migrate:project": { path: "./commands/migrate-project.js", exportName: "migrateProject" },
61
- outdated: { path: "./commands/outdated.js", exportName: "outdated" },
62
- package: { path: "./commands/package.js", exportName: "packageCommands" },
63
- phone: { path: "./commands/phone.js", exportName: "phone" },
64
- ports: { path: "./commands/ports.js", exportName: "ports" },
65
- prepublish: { path: "./commands/prepublish.js", exportName: "prepublish" },
66
- projects: { path: "./commands/projects.js", exportName: "projects" },
67
- publish: { path: "./commands/publish.js", exportName: "publish" },
68
- "publish:model": { path: "./commands/publish.js", exportName: "publish" },
69
- "publish:controller": { path: "./commands/publish.js", exportName: "publish" },
70
- "publish:middleware": { path: "./commands/publish.js", exportName: "publish" },
71
- "publish:action": { path: "./commands/publish.js", exportName: "publish" },
72
- "publish:core": { path: "./commands/publish.js", exportName: "publish" },
73
- queue: { path: "./commands/queue.js", exportName: "queue" },
74
- release: { path: "./commands/release.js", exportName: "release" },
75
- route: { path: "./commands/route.js", exportName: "route" },
76
- saas: { path: "./commands/saas.js", exportName: "saas" },
77
- schedule: { path: "./commands/schedule.js", exportName: "schedule" },
78
- search: { path: "./commands/search.js", exportName: "search" },
79
- seed: { path: "./commands/seed.js", exportName: "seed" },
80
- "seed:roles": { path: "./commands/seed.js", exportName: "seed" },
81
- "roles:seed": { path: "./commands/seed.js", exportName: "seed" },
82
- serve: { path: "./commands/serve.js", exportName: "serve" },
83
- "serve:api": { path: "./commands/serve.js", exportName: "serveApi" },
84
- setup: { path: "./commands/setup.js", exportName: "setup" },
85
- share: { path: "./commands/share.js", exportName: "share" },
86
- stack: { path: "./commands/stacks.js", exportName: "stacks" },
87
- sms: { path: "./commands/sms.js", exportName: "sms" },
88
- telemetry: { path: "./commands/telemetry.js", exportName: "telemetryCommand" },
89
- test: { path: "./commands/test.js", exportName: "test" },
90
- tinker: { path: "./commands/tinker.js", exportName: "tinker" },
91
- types: { path: "./commands/types.js", exportName: "types" },
92
- undeploy: { path: "./commands/cloud.js", exportName: "cloud" },
93
- upgrade: { path: "./commands/upgrade.js", exportName: "upgrade" },
94
- version: { path: "./commands/version.js", exportName: "version" }
95
- }, commandGroups = {
96
- minimal: ["version", "help"],
97
- development: ["dev", "build", "test", "lint"],
98
- database: ["migrate", "seed", "fresh"],
99
- scaffolding: ["make", "generate"],
100
- deployment: ["deploy", "release", "cloud"],
101
- info: ["about", "doctor", "list"]
102
- }, loadedRegistrars = new WeakMap;
103
- function loaderKey(loader) {
104
- return `${loader.path}#${loader.exportName}`;
105
- }
106
- export function markLoaded(buddy, commandName) {
107
- const loader = commandRegistry[commandName];
108
- if (!loader)
109
- return;
110
- let set = loadedRegistrars.get(buddy);
111
- if (!set) {
112
- set = new Set;
113
- loadedRegistrars.set(buddy, set);
114
- }
115
- set.add(loaderKey(loader));
116
- }
117
- export async function loadCommand(commandName, buddy) {
118
- const loader = commandRegistry[commandName];
119
- if (!loader)
120
- return !1;
121
- let set = loadedRegistrars.get(buddy);
122
- if (!set) {
123
- set = new Set;
124
- loadedRegistrars.set(buddy, set);
125
- }
126
- const key = loaderKey(loader);
127
- if (set.has(key))
128
- return !0;
129
- set.add(key);
130
- try {
131
- const commandFunction = (await import(loader.path))[loader.exportName];
132
- if (typeof commandFunction === "function") {
133
- commandFunction(buddy);
134
- return !0;
135
- } else
136
- return !1;
137
- } catch {
138
- return !1;
139
- }
140
- }
141
- export async function loadCommands(commandNames, buddy) {
142
- const timeout = (ms) => new Promise((_, reject) => setTimeout(() => reject(Error("timeout")), ms)), seen = new Set, unique = [];
143
- for (const name of commandNames) {
144
- const loader = commandRegistry[name], key = loader ? `${loader.path}#${loader.exportName}` : `name:${name}`;
145
- if (seen.has(key))
146
- continue;
147
- seen.add(key);
148
- unique.push(name);
149
- }
150
- await Promise.all(unique.map(async (name) => {
151
- try {
152
- await Promise.race([
153
- loadCommand(name, buddy),
154
- timeout(5000)
155
- ]);
156
- } catch {}
157
- }));
158
- }
159
- export async function loadCommandGroup(groupName, buddy) {
160
- const commands = commandGroups[groupName];
161
- if (commands)
162
- await loadCommands(commands, buddy);
163
- }
164
- export async function loadAllCommands(buddy) {
165
- const allCommands = Object.keys(commandRegistry);
166
- await loadCommands(allCommands, buddy);
167
- }
168
- export function getCommandNames() {
169
- return Object.keys(commandRegistry);
170
- }
171
- export function getCommandsToLoad(args) {
172
- const requestedCommand = args[0], isVersionFlag = requestedCommand === "--version" || requestedCommand === "-v", isHelpFlag = requestedCommand === "--help" || requestedCommand === "-h", isHelpWord = requestedCommand === "help";
173
- if (isVersionFlag)
174
- return ["version"];
175
- if (!requestedCommand || isHelpFlag || isHelpWord)
176
- return Object.keys(commandRegistry);
177
- const baseCommand = requestedCommand.split(":")[0];
178
- if (baseCommand === "list")
179
- return ["list", ...Object.keys(commandRegistry).filter((k) => k !== "list")];
180
- if (commandRegistry[baseCommand])
181
- return [baseCommand];
182
- if (requestedCommand.includes(":")) {
183
- const namespace = baseCommand;
184
- if (commandRegistry[namespace])
185
- return [namespace];
186
- }
187
- return Object.keys(commandRegistry);
188
- }
@@ -1,9 +0,0 @@
1
- import type { Driver, MigrationReport, MigrateProjectRequest } from './types';
2
- export type { MigrateProjectRequest, MigrationReport, ReportEntry } from './types';
3
- export declare function runMigrator(req: MigrateProjectRequest): Promise<MigrationReport>;
4
- /**
5
- * Render a migration report as a Markdown checklist suitable for
6
- * writing to `MIGRATION_REPORT.md` in the target project.
7
- */
8
- export declare function renderReport(report: MigrationReport): string;
9
- export declare const DRIVERS: Record<string, Driver>;
@@ -1,62 +0,0 @@
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,2 +0,0 @@
1
- import type { Driver } from '../types';
2
- export declare const laravelDriver: Driver;
@@ -1,148 +0,0 @@
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,52 +0,0 @@
1
- /**
2
- * Parse a Laravel migration file. Returns `null` when no
3
- * `Schema::create(...)` block is found (e.g. drop migrations,
4
- * data-only migrations, alter-table migrations — those are deferred
5
- * to a separate emitter once the create paths land).
6
- */
7
- export declare function parseLaravelMigration(source: string): ParsedMigration | null;
8
- /**
9
- * Lift Laravel's `YYYY_MM_DD_HHMMSS_create_<table>_table.php` filename
10
- * into the `0000000NNN-create-<table>-table.sql` form the Stacks
11
- * migration runner expects. The numeric prefix preserves ordering
12
- * across the existing Stacks migrations directory — callers should
13
- * pass a `sequence` that starts above whatever's already there.
14
- */
15
- export declare function laravelFilenameToStacks(filename: string, sequence: number, table: string): string;
16
- /**
17
- * Laravel migration → Stacks SQL translator.
18
- *
19
- * Laravel migrations are PHP classes whose `up()` calls
20
- * `Schema::create(table, fn (Blueprint $t) => { ... })`. We don't
21
- * parse arbitrary PHP — we recognise the common Blueprint DSL by
22
- * regex and emit a CREATE TABLE statement that the Stacks runner can
23
- * consume.
24
- *
25
- * Strategy:
26
- * 1. Find the `Schema::create('table', function (...) { BODY })` block.
27
- * 2. Tokenise BODY line-by-line, each line a `$table->method(args)->modifier()...;` chain.
28
- * 3. Map the leading method to a SQLite column type.
29
- * 4. Translate modifiers (`->nullable()`, `->unique()`, `->default(...)`, `->index()`)
30
- * into column constraints (or post-table CREATE INDEX statements).
31
- *
32
- * Anything unrecognised gets logged in the report as `// SKIPPED:` and
33
- * the user can hand-port it.
34
- */
35
- export declare interface ParsedMigration {
36
- table: string
37
- sql: string
38
- skipped: string[]
39
- }
40
- declare interface Column {
41
- name: string
42
- type: string
43
- nullable: boolean
44
- unique: boolean
45
- primaryKey: boolean
46
- autoIncrement: boolean
47
- defaultValue: string | null
48
- index: boolean
49
- }
50
- declare type ParsedLine = | { kind: 'columns', columns: Column[], indexes?: { name: string, columns: string[], unique: boolean }[] }
51
- | { kind: 'index', index: { name: string, columns: string[], unique: boolean } }
52
- | { kind: 'skip' }