swallowkit 1.0.0-beta.6 → 1.0.0-beta.60

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 (296) hide show
  1. package/README.ja.md +86 -177
  2. package/README.md +86 -178
  3. package/dist/__tests__/fixtures.d.ts +12 -0
  4. package/dist/__tests__/fixtures.d.ts.map +1 -1
  5. package/dist/__tests__/fixtures.js +101 -0
  6. package/dist/__tests__/fixtures.js.map +1 -1
  7. package/dist/cli/commands/add-auth.d.ts +15 -0
  8. package/dist/cli/commands/add-auth.d.ts.map +1 -0
  9. package/dist/cli/commands/add-auth.js +790 -0
  10. package/dist/cli/commands/add-auth.js.map +1 -0
  11. package/dist/cli/commands/add-connector.d.ts +20 -0
  12. package/dist/cli/commands/add-connector.d.ts.map +1 -0
  13. package/dist/cli/commands/add-connector.js +163 -0
  14. package/dist/cli/commands/add-connector.js.map +1 -0
  15. package/dist/cli/commands/cosmos-worktree-isolation.d.ts +25 -0
  16. package/dist/cli/commands/cosmos-worktree-isolation.d.ts.map +1 -0
  17. package/dist/cli/commands/cosmos-worktree-isolation.js +124 -0
  18. package/dist/cli/commands/cosmos-worktree-isolation.js.map +1 -0
  19. package/dist/cli/commands/create-model.d.ts +1 -4
  20. package/dist/cli/commands/create-model.d.ts.map +1 -1
  21. package/dist/cli/commands/create-model.js +19 -81
  22. package/dist/cli/commands/create-model.js.map +1 -1
  23. package/dist/cli/commands/dev-seeds.d.ts +62 -0
  24. package/dist/cli/commands/dev-seeds.d.ts.map +1 -0
  25. package/dist/cli/commands/dev-seeds.js +474 -0
  26. package/dist/cli/commands/dev-seeds.js.map +1 -0
  27. package/dist/cli/commands/dev.d.ts +38 -0
  28. package/dist/cli/commands/dev.d.ts.map +1 -1
  29. package/dist/cli/commands/dev.js +733 -155
  30. package/dist/cli/commands/dev.js.map +1 -1
  31. package/dist/cli/commands/index.d.ts +1 -0
  32. package/dist/cli/commands/index.d.ts.map +1 -1
  33. package/dist/cli/commands/index.js +3 -1
  34. package/dist/cli/commands/index.js.map +1 -1
  35. package/dist/cli/commands/init.d.ts +78 -0
  36. package/dist/cli/commands/init.d.ts.map +1 -1
  37. package/dist/cli/commands/init.js +1453 -898
  38. package/dist/cli/commands/init.js.map +1 -1
  39. package/dist/cli/commands/scaffold.d.ts +24 -0
  40. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  41. package/dist/cli/commands/scaffold.js +473 -90
  42. package/dist/cli/commands/scaffold.js.map +1 -1
  43. package/dist/cli/index.d.ts +5 -1
  44. package/dist/cli/index.d.ts.map +1 -1
  45. package/dist/cli/index.js +333 -55
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/core/config.d.ts +14 -3
  48. package/dist/core/config.d.ts.map +1 -1
  49. package/dist/core/config.js +179 -8
  50. package/dist/core/config.js.map +1 -1
  51. package/dist/core/mock/connector-mock-server.d.ts +101 -0
  52. package/dist/core/mock/connector-mock-server.d.ts.map +1 -0
  53. package/dist/core/mock/connector-mock-server.js +480 -0
  54. package/dist/core/mock/connector-mock-server.js.map +1 -0
  55. package/dist/core/mock/zod-mock-generator.d.ts +14 -0
  56. package/dist/core/mock/zod-mock-generator.d.ts.map +1 -0
  57. package/dist/core/mock/zod-mock-generator.js +163 -0
  58. package/dist/core/mock/zod-mock-generator.js.map +1 -0
  59. package/dist/core/operations/auth-operations.d.ts +61 -0
  60. package/dist/core/operations/auth-operations.d.ts.map +1 -0
  61. package/dist/core/operations/auth-operations.js +272 -0
  62. package/dist/core/operations/auth-operations.js.map +1 -0
  63. package/dist/core/operations/create-model.d.ts +15 -0
  64. package/dist/core/operations/create-model.d.ts.map +1 -0
  65. package/dist/core/operations/create-model.js +185 -0
  66. package/dist/core/operations/create-model.js.map +1 -0
  67. package/dist/core/operations/file-session.d.ts +56 -0
  68. package/dist/core/operations/file-session.d.ts.map +1 -0
  69. package/dist/core/operations/file-session.js +203 -0
  70. package/dist/core/operations/file-session.js.map +1 -0
  71. package/dist/core/operations/provision-operations.d.ts +52 -0
  72. package/dist/core/operations/provision-operations.d.ts.map +1 -0
  73. package/dist/core/operations/provision-operations.js +211 -0
  74. package/dist/core/operations/provision-operations.js.map +1 -0
  75. package/dist/core/operations/runtime.d.ts +37 -0
  76. package/dist/core/operations/runtime.d.ts.map +1 -0
  77. package/dist/core/operations/runtime.js +248 -0
  78. package/dist/core/operations/runtime.js.map +1 -0
  79. package/dist/core/operations/scaffold-apply.d.ts +21 -0
  80. package/dist/core/operations/scaffold-apply.d.ts.map +1 -0
  81. package/dist/core/operations/scaffold-apply.js +57 -0
  82. package/dist/core/operations/scaffold-apply.js.map +1 -0
  83. package/dist/core/operations/scaffold-machine.d.ts +16 -0
  84. package/dist/core/operations/scaffold-machine.d.ts.map +1 -0
  85. package/dist/core/operations/scaffold-machine.js +51 -0
  86. package/dist/core/operations/scaffold-machine.js.map +1 -0
  87. package/dist/core/operations/scaffold-plan.d.ts +43 -0
  88. package/dist/core/operations/scaffold-plan.d.ts.map +1 -0
  89. package/dist/core/operations/scaffold-plan.js +187 -0
  90. package/dist/core/operations/scaffold-plan.js.map +1 -0
  91. package/dist/core/project/agent-instructions.d.ts +29 -0
  92. package/dist/core/project/agent-instructions.d.ts.map +1 -0
  93. package/dist/core/project/agent-instructions.js +159 -0
  94. package/dist/core/project/agent-instructions.js.map +1 -0
  95. package/dist/core/project/artifacts.d.ts +58 -0
  96. package/dist/core/project/artifacts.d.ts.map +1 -0
  97. package/dist/core/project/artifacts.js +179 -0
  98. package/dist/core/project/artifacts.js.map +1 -0
  99. package/dist/core/project/boundaries.d.ts +50 -0
  100. package/dist/core/project/boundaries.d.ts.map +1 -0
  101. package/dist/core/project/boundaries.js +117 -0
  102. package/dist/core/project/boundaries.js.map +1 -0
  103. package/dist/core/project/capabilities.d.ts +58 -0
  104. package/dist/core/project/capabilities.d.ts.map +1 -0
  105. package/dist/core/project/capabilities.js +135 -0
  106. package/dist/core/project/capabilities.js.map +1 -0
  107. package/dist/core/project/drift.d.ts +29 -0
  108. package/dist/core/project/drift.d.ts.map +1 -0
  109. package/dist/core/project/drift.js +188 -0
  110. package/dist/core/project/drift.js.map +1 -0
  111. package/dist/core/project/infra.d.ts +49 -0
  112. package/dist/core/project/infra.d.ts.map +1 -0
  113. package/dist/core/project/infra.js +167 -0
  114. package/dist/core/project/infra.js.map +1 -0
  115. package/dist/core/project/manifest.d.ts +92 -0
  116. package/dist/core/project/manifest.d.ts.map +1 -0
  117. package/dist/core/project/manifest.js +321 -0
  118. package/dist/core/project/manifest.js.map +1 -0
  119. package/dist/core/project/state.d.ts +15 -0
  120. package/dist/core/project/state.d.ts.map +1 -0
  121. package/dist/core/project/state.js +106 -0
  122. package/dist/core/project/state.js.map +1 -0
  123. package/dist/core/project/validation.d.ts +20 -0
  124. package/dist/core/project/validation.d.ts.map +1 -0
  125. package/dist/core/project/validation.js +274 -0
  126. package/dist/core/project/validation.js.map +1 -0
  127. package/dist/core/project/workflows.d.ts +43 -0
  128. package/dist/core/project/workflows.d.ts.map +1 -0
  129. package/dist/core/project/workflows.js +299 -0
  130. package/dist/core/project/workflows.js.map +1 -0
  131. package/dist/core/scaffold/auth-generator.d.ts +63 -0
  132. package/dist/core/scaffold/auth-generator.d.ts.map +1 -0
  133. package/dist/core/scaffold/auth-generator.js +1774 -0
  134. package/dist/core/scaffold/auth-generator.js.map +1 -0
  135. package/dist/core/scaffold/connector-functions-generator.d.ts +41 -0
  136. package/dist/core/scaffold/connector-functions-generator.d.ts.map +1 -0
  137. package/dist/core/scaffold/connector-functions-generator.js +1029 -0
  138. package/dist/core/scaffold/connector-functions-generator.js.map +1 -0
  139. package/dist/core/scaffold/functions-generator.d.ts +7 -1
  140. package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
  141. package/dist/core/scaffold/functions-generator.js +771 -69
  142. package/dist/core/scaffold/functions-generator.js.map +1 -1
  143. package/dist/core/scaffold/model-parser.d.ts +21 -1
  144. package/dist/core/scaffold/model-parser.d.ts.map +1 -1
  145. package/dist/core/scaffold/model-parser.js +243 -43
  146. package/dist/core/scaffold/model-parser.js.map +1 -1
  147. package/dist/core/scaffold/native-schema-generator.d.ts +19 -0
  148. package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -0
  149. package/dist/core/scaffold/native-schema-generator.js +753 -0
  150. package/dist/core/scaffold/native-schema-generator.js.map +1 -0
  151. package/dist/core/scaffold/nextjs-generator.d.ts +8 -0
  152. package/dist/core/scaffold/nextjs-generator.d.ts.map +1 -1
  153. package/dist/core/scaffold/nextjs-generator.js +153 -9
  154. package/dist/core/scaffold/nextjs-generator.js.map +1 -1
  155. package/dist/core/scaffold/openapi-generator.d.ts +3 -0
  156. package/dist/core/scaffold/openapi-generator.d.ts.map +1 -0
  157. package/dist/core/scaffold/openapi-generator.js +190 -0
  158. package/dist/core/scaffold/openapi-generator.js.map +1 -0
  159. package/dist/core/scaffold/ui-generator.d.ts +17 -4
  160. package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
  161. package/dist/core/scaffold/ui-generator.js +174 -34
  162. package/dist/core/scaffold/ui-generator.js.map +1 -1
  163. package/dist/core/verify/index.d.ts +69 -0
  164. package/dist/core/verify/index.d.ts.map +1 -0
  165. package/dist/core/verify/index.js +412 -0
  166. package/dist/core/verify/index.js.map +1 -0
  167. package/dist/database/base-model.d.ts +3 -3
  168. package/dist/database/base-model.js +3 -3
  169. package/dist/index.d.ts +2 -2
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +2 -1
  172. package/dist/index.js.map +1 -1
  173. package/dist/machine/contracts.d.ts +24 -0
  174. package/dist/machine/contracts.d.ts.map +1 -0
  175. package/dist/machine/contracts.js +3 -0
  176. package/dist/machine/contracts.js.map +1 -0
  177. package/dist/machine/errors.d.ts +14 -0
  178. package/dist/machine/errors.d.ts.map +1 -0
  179. package/dist/machine/errors.js +42 -0
  180. package/dist/machine/errors.js.map +1 -0
  181. package/dist/machine/index.d.ts +3 -0
  182. package/dist/machine/index.d.ts.map +1 -0
  183. package/dist/machine/index.js +566 -0
  184. package/dist/machine/index.js.map +1 -0
  185. package/dist/mcp/index.d.ts +25 -0
  186. package/dist/mcp/index.d.ts.map +1 -0
  187. package/dist/mcp/index.js +425 -0
  188. package/dist/mcp/index.js.map +1 -0
  189. package/dist/types/index.d.ts +109 -0
  190. package/dist/types/index.d.ts.map +1 -1
  191. package/dist/utils/package-manager.d.ts +5 -2
  192. package/dist/utils/package-manager.d.ts.map +1 -1
  193. package/dist/utils/package-manager.js +30 -9
  194. package/dist/utils/package-manager.js.map +1 -1
  195. package/dist/utils/python-uv.d.ts +21 -0
  196. package/dist/utils/python-uv.d.ts.map +1 -0
  197. package/dist/utils/python-uv.js +111 -0
  198. package/dist/utils/python-uv.js.map +1 -0
  199. package/dist/version.d.ts +2 -0
  200. package/dist/version.d.ts.map +1 -0
  201. package/dist/version.js +49 -0
  202. package/dist/version.js.map +1 -0
  203. package/package.json +9 -5
  204. package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +1139 -0
  205. package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +206 -0
  206. package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +532 -0
  207. package/src/__tests__/agent-instructions.test.ts +237 -0
  208. package/src/__tests__/agent-loop-phase34.test.ts +513 -0
  209. package/src/__tests__/auth.test.ts +770 -0
  210. package/src/__tests__/bff-swa-auth.test.ts +275 -0
  211. package/src/__tests__/config.test.ts +295 -0
  212. package/src/__tests__/connector-functions-generator.test.ts +288 -0
  213. package/src/__tests__/connector-mock-server.test.ts +439 -0
  214. package/src/__tests__/connector-model-bff.test.ts +162 -0
  215. package/src/__tests__/cosmos-worktree-isolation.test.ts +149 -0
  216. package/src/__tests__/dev-seeds.test.ts +236 -0
  217. package/src/__tests__/dev.test.ts +296 -0
  218. package/src/__tests__/file-session.test.ts +98 -0
  219. package/src/__tests__/fixtures.ts +184 -0
  220. package/src/__tests__/functions-generator.test.ts +237 -0
  221. package/src/__tests__/init.test.ts +411 -0
  222. package/src/__tests__/jest-globals.d.ts +8 -0
  223. package/src/__tests__/machine.test.ts +371 -0
  224. package/src/__tests__/mcp.test.ts +253 -0
  225. package/src/__tests__/model-parser.test.ts +81 -0
  226. package/src/__tests__/multi-auth.test.ts +160 -0
  227. package/src/__tests__/nextjs-generator.test.ts +105 -0
  228. package/src/__tests__/openapi-generator.test.ts +43 -0
  229. package/src/__tests__/package-manager.test.ts +227 -0
  230. package/src/__tests__/plan-apply.test.ts +499 -0
  231. package/src/__tests__/python-uv.test.ts +48 -0
  232. package/src/__tests__/scaffold.test.ts +302 -0
  233. package/src/__tests__/string-utils.test.ts +75 -0
  234. package/src/__tests__/tsconfig.json +15 -0
  235. package/src/__tests__/ui-generator.test.ts +248 -0
  236. package/src/__tests__/zod-mock-generator.test.ts +132 -0
  237. package/src/cli/commands/add-auth.ts +853 -0
  238. package/src/cli/commands/add-connector.ts +158 -0
  239. package/src/cli/commands/cosmos-worktree-isolation.ts +130 -0
  240. package/src/cli/commands/create-model.ts +62 -0
  241. package/src/cli/commands/dev-seeds.ts +629 -0
  242. package/src/cli/commands/dev.ts +1252 -0
  243. package/src/cli/commands/index.ts +9 -0
  244. package/src/cli/commands/init.ts +3541 -0
  245. package/src/cli/commands/provision.ts +193 -0
  246. package/src/cli/commands/scaffold.ts +1081 -0
  247. package/src/cli/index.ts +350 -0
  248. package/src/core/config.ts +380 -0
  249. package/src/core/mock/connector-mock-server.ts +555 -0
  250. package/src/core/mock/zod-mock-generator.ts +205 -0
  251. package/src/core/operations/auth-operations.ts +360 -0
  252. package/src/core/operations/create-model.ts +191 -0
  253. package/src/core/operations/file-session.ts +222 -0
  254. package/src/core/operations/provision-operations.ts +297 -0
  255. package/src/core/operations/runtime.ts +258 -0
  256. package/src/core/operations/scaffold-apply.ts +106 -0
  257. package/src/core/operations/scaffold-machine.ts +77 -0
  258. package/src/core/operations/scaffold-plan.ts +215 -0
  259. package/src/core/project/agent-instructions.ts +167 -0
  260. package/src/core/project/agent-templates/AGENTS.md +502 -0
  261. package/src/core/project/agent-templates/CLAUDE.md +31 -0
  262. package/src/core/project/agent-templates/azure-functions.instructions.md +22 -0
  263. package/src/core/project/agent-templates/bff-routes.instructions.md +18 -0
  264. package/src/core/project/agent-templates/copilot-instructions.md +27 -0
  265. package/src/core/project/agent-templates/shared-models.instructions.md +72 -0
  266. package/src/core/project/artifacts.ts +205 -0
  267. package/src/core/project/boundaries.ts +170 -0
  268. package/src/core/project/capabilities.ts +193 -0
  269. package/src/core/project/drift.ts +202 -0
  270. package/src/core/project/infra.ts +196 -0
  271. package/src/core/project/manifest.ts +402 -0
  272. package/src/core/project/state.ts +77 -0
  273. package/src/core/project/validation.ts +295 -0
  274. package/src/core/project/workflows.ts +295 -0
  275. package/src/core/scaffold/auth-generator.ts +1824 -0
  276. package/src/core/scaffold/connector-functions-generator.ts +1133 -0
  277. package/src/core/scaffold/functions-generator.ts +972 -0
  278. package/src/core/scaffold/model-parser.ts +854 -0
  279. package/src/core/scaffold/native-schema-generator.ts +904 -0
  280. package/src/core/scaffold/nextjs-generator.ts +382 -0
  281. package/src/core/scaffold/openapi-generator.ts +212 -0
  282. package/src/core/scaffold/ui-generator.ts +1100 -0
  283. package/src/core/verify/index.ts +468 -0
  284. package/src/database/base-model.ts +184 -0
  285. package/src/database/client.ts +140 -0
  286. package/src/database/repository.ts +104 -0
  287. package/src/database/runtime-check.ts +25 -0
  288. package/src/index.ts +27 -0
  289. package/src/machine/contracts.ts +33 -0
  290. package/src/machine/errors.ts +45 -0
  291. package/src/machine/index.ts +690 -0
  292. package/src/mcp/index.ts +423 -0
  293. package/src/types/index.ts +182 -0
  294. package/src/utils/package-manager.ts +246 -0
  295. package/src/utils/python-uv.ts +96 -0
  296. package/src/version.ts +13 -0
@@ -0,0 +1,350 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync } from "child_process";
4
+ import { readFileSync } from "fs";
5
+ import * as path from "path";
6
+ import { Command } from "commander";
7
+ import { initCommand, devCommand, devSeedsCommand, scaffoldCommand, createModelCommand } from "./commands";
8
+ import { provisionCommand } from "./commands/provision";
9
+ import { addConnectorCommand } from "./commands/add-connector";
10
+ import { addAuthCommand } from "./commands/add-auth";
11
+ import { planScaffoldOperation } from "../core/operations/scaffold-plan";
12
+ import { inspectArtifacts } from "../core/project/artifacts";
13
+ import { detectDrift } from "../core/project/drift";
14
+ import { runVerify } from "../core/verify";
15
+ import { isMachineCommand, runMachineCli } from "../machine";
16
+
17
+ const packageJsonPath = path.resolve(__dirname, "../../package.json");
18
+ export const CLI_VERSION = JSON.parse(readFileSync(packageJsonPath, "utf8")).version as string;
19
+
20
+ const DEV_OPTION_ARITY = new Map<string, 0 | 1>([
21
+ ["-p", 1],
22
+ ["--port", 1],
23
+ ["-f", 1],
24
+ ["--functions-port", 1],
25
+ ["--host", 1],
26
+ ["--seed-env", 1],
27
+ ["-o", 0],
28
+ ["--open", 0],
29
+ ["-v", 0],
30
+ ["--verbose", 0],
31
+ ["--no-functions", 0],
32
+ ["--mock-connectors", 0],
33
+ ["--swa-port", 1],
34
+ ["--no-swa", 0],
35
+ ]);
36
+
37
+ function ensureUtf8ConsoleOnWindows(): void {
38
+ if (process.platform === 'win32') {
39
+ try {
40
+ execSync('chcp 65001', { stdio: 'ignore' });
41
+ } catch {
42
+ // ignore — non-critical
43
+ }
44
+ }
45
+ }
46
+
47
+ function isDevOptionSequence(tokens: string[]): boolean {
48
+ if (tokens.length === 0) {
49
+ return false;
50
+ }
51
+
52
+ for (let index = 0; index < tokens.length; index += 1) {
53
+ const token = tokens[index];
54
+ const arity = DEV_OPTION_ARITY.get(token);
55
+
56
+ if (arity === undefined) {
57
+ return false;
58
+ }
59
+
60
+ if (arity === 1) {
61
+ const value = tokens[index + 1];
62
+ if (value === undefined || value === "dev") {
63
+ return false;
64
+ }
65
+ index += 1;
66
+ }
67
+ }
68
+
69
+ return true;
70
+ }
71
+
72
+ export function normalizeDevCommandArgv(argv: string[]): string[] {
73
+ if (argv.length <= 3) {
74
+ return argv;
75
+ }
76
+
77
+ const prefix = argv.slice(0, 2);
78
+ const args = argv.slice(2);
79
+ const devIndex = args.indexOf("dev");
80
+
81
+ if (devIndex <= 0) {
82
+ return argv;
83
+ }
84
+
85
+ const leadingTokens = args.slice(0, devIndex);
86
+ if (!isDevOptionSequence(leadingTokens)) {
87
+ return argv;
88
+ }
89
+
90
+ return [
91
+ ...prefix,
92
+ "dev",
93
+ ...leadingTokens,
94
+ ...args.slice(devIndex + 1),
95
+ ];
96
+ }
97
+
98
+ export function createProgram(devCommandOverride: Command = devCommand): Command {
99
+ const program = new Command();
100
+
101
+ program
102
+ .name("swallowkit")
103
+ .description("Next.js framework optimized for Azure deployment - Automatically splits SSR into individual Azure Functions")
104
+ .version(CLI_VERSION);
105
+
106
+ // Register commands
107
+ program
108
+ .command("init [project-name]")
109
+ .description("Initialize a new SwallowKit project")
110
+ .option("--template <template>", "Template to use", "default")
111
+ .option("--next-version <version>", "Next.js version to install (e.g., 16.0.7, latest)", "latest")
112
+ .option("--cicd <provider>", "CI/CD provider: github | azure | skip")
113
+ .option("--backend-language <language>", "Azure Functions backend language: typescript | csharp | python")
114
+ .option("--cosmos-db-mode <mode>", "Cosmos DB mode: freetier | serverless")
115
+ .option("--vnet <option>", "Network security: outbound | none")
116
+ .option("--swa-plan <plan>", "Azure Static Web Apps plan: free | standard")
117
+ .action((projectName, options) => {
118
+ initCommand({
119
+ name: projectName || "swallowkit-app",
120
+ template: options.template,
121
+ nextVersion: options.nextVersion,
122
+ cicd: options.cicd,
123
+ backendLanguage: options.backendLanguage,
124
+ cosmosDbMode: options.cosmosDbMode,
125
+ vnet: options.vnet,
126
+ swaPlan: options.swaPlan,
127
+ });
128
+ });
129
+
130
+ program.addCommand(devCommandOverride);
131
+ program.addCommand(devSeedsCommand);
132
+
133
+ program.addCommand(provisionCommand);
134
+
135
+ program
136
+ .command("create-model <names...>")
137
+ .description("Create model template files with id, createdAt, and updatedAt fields")
138
+ .option("--models-dir <dir>", "Models directory", "shared/models")
139
+ .option("--connector <name>", "Associate model with a connector defined in swallowkit.config.js")
140
+ .action((names, options) => {
141
+ createModelCommand({
142
+ names,
143
+ modelsDir: options.modelsDir,
144
+ connector: options.connector,
145
+ });
146
+ });
147
+
148
+ program
149
+ .command("scaffold <model>")
150
+ .description("Generate CRUD code for Azure Functions and Next.js BFF from Zod models")
151
+ .option("--functions-dir <dir>", "Azure Functions directory", "functions")
152
+ .option("--api-dir <dir>", "Next.js API routes directory", "app/api")
153
+ .option("--api-only", "Skip UI components; still update Functions, BFF routes, OpenAPI, and native schema assets", false)
154
+ .option("--dry-run", "Show planned file changes without writing anything", false)
155
+ .action(async (model, options) => {
156
+ if (options.dryRun) {
157
+ await runScaffoldDryRun({
158
+ model,
159
+ functionsDir: options.functionsDir,
160
+ apiDir: options.apiDir,
161
+ apiOnly: options.apiOnly,
162
+ });
163
+ return;
164
+ }
165
+
166
+ await scaffoldCommand({
167
+ model,
168
+ functionsDir: options.functionsDir,
169
+ apiDir: options.apiDir,
170
+ apiOnly: options.apiOnly,
171
+ });
172
+ });
173
+
174
+ program
175
+ .command("add-connector <name>")
176
+ .description("Add an external data source connector configuration")
177
+ .requiredOption("--type <type>", "Connector type: rdb | api")
178
+ .option("--provider <provider>", "RDB provider: mysql | postgres | sqlserver", "mysql")
179
+ .action((name, options) => {
180
+ addConnectorCommand({
181
+ name,
182
+ type: options.type,
183
+ provider: options.provider,
184
+ });
185
+ });
186
+
187
+ program
188
+ .command("add-auth")
189
+ .description("Add authentication and authorization to the project")
190
+ .option("--provider <provider>", "Auth provider: custom-jwt | swa | external-token | swa-custom | none", "custom-jwt")
191
+ .option("--scheme <name>", "Add a named authentication scheme")
192
+ .option("--allowed-providers <list>", "Comma-separated SWA identity providers to allow (e.g. github,aad); defaults to aad")
193
+ .action((options) => {
194
+ addAuthCommand({
195
+ provider: options.provider,
196
+ scheme: options.scheme,
197
+ allowedProviders: options.allowedProviders ? String(options.allowedProviders).split(",") : undefined,
198
+ });
199
+ });
200
+
201
+ program
202
+ .command("status")
203
+ .description("Show generated artifact status and drift against the current project state")
204
+ .option("--artifacts", "List all tracked artifacts with ownership", false)
205
+ .action(async (options) => {
206
+ await runStatusCommand({ artifacts: options.artifacts });
207
+ });
208
+
209
+ program
210
+ .command("verify")
211
+ .description("Run verification checks (structure, drift, typecheck)")
212
+ .option("--checks <ids>", "Comma-separated check ids to run (structure,drift,typecheck)")
213
+ .action(async (options) => {
214
+ await runVerifyCommand({ checks: options.checks });
215
+ });
216
+
217
+ return program;
218
+ }
219
+
220
+ async function runScaffoldDryRun(options: { model: string; functionsDir?: string; apiDir?: string; apiOnly?: boolean }): Promise<void> {
221
+ console.log("šŸ” Scaffold dry-run — no files will be written.\n");
222
+
223
+ const plan = await planScaffoldOperation(options);
224
+
225
+ const actionIcons: Record<string, string> = {
226
+ create: "āž•",
227
+ update: "ā™»ļø ",
228
+ overwrite: "āš ļø ",
229
+ append: "šŸ”—",
230
+ delete: "šŸ—‘ļø ",
231
+ skip: "ā­ļø ",
232
+ };
233
+
234
+ for (const operation of plan.operations) {
235
+ if (operation.action === "skip") continue;
236
+ const icon = actionIcons[operation.action] ?? "•";
237
+ const conflictNote = operation.conflict ? ` (conflict: ${operation.conflictReason})` : "";
238
+ console.log(` ${icon} ${operation.action.padEnd(9)} ${operation.path} [${operation.ownership}]${conflictNote}`);
239
+ }
240
+
241
+ const skipped = plan.operations.filter((operation) => operation.action === "skip").length;
242
+ if (skipped > 0) {
243
+ console.log(` ā­ļø ${skipped} file(s) unchanged (skipped)`);
244
+ }
245
+
246
+ if (plan.warnings.length > 0) {
247
+ console.log("\nāš ļø Warnings:");
248
+ for (const warning of plan.warnings) {
249
+ console.log(` - ${warning}`);
250
+ }
251
+ }
252
+
253
+ console.log(`\nšŸ“‹ Plan ${plan.planId} saved.`);
254
+ if (plan.requiresApproval) {
255
+ console.log(`āš ļø ${plan.conflicts.length} file(s) were modified after generation and would be overwritten.`);
256
+ console.log(` Review the conflicts, then run: swallowkit scaffold ${options.model} (or machine apply scaffold --plan ${plan.planId} --approve)`);
257
+ } else {
258
+ console.log(` Run without --dry-run to apply: swallowkit scaffold ${options.model}`);
259
+ }
260
+ }
261
+
262
+ async function runStatusCommand(options: { artifacts?: boolean }): Promise<void> {
263
+ const inspection = inspectArtifacts();
264
+ const drift = await detectDrift();
265
+
266
+ console.log("šŸ“¦ SwallowKit project status\n");
267
+
268
+ if (!inspection.ledgerFound) {
269
+ console.log("ā„¹ļø No artifact ledger (.swallowkit/artifacts.json) found yet.");
270
+ console.log(" Run scaffold once with this SwallowKit version to start tracking artifacts.\n");
271
+ } else {
272
+ const total = inspection.artifacts.length;
273
+ const missing = inspection.artifacts.filter((artifact) => !artifact.exists).length;
274
+ const modified = inspection.artifacts.filter((artifact) => artifact.modified).length;
275
+ console.log(` Tracked artifacts: ${total}`);
276
+ console.log(` Modified after generation: ${modified}`);
277
+ console.log(` Missing: ${missing}\n`);
278
+
279
+ if (options.artifacts) {
280
+ for (const artifact of inspection.artifacts) {
281
+ const flags = [
282
+ artifact.modified ? "modified" : null,
283
+ !artifact.exists ? "missing" : null,
284
+ ].filter(Boolean);
285
+ const suffix = flags.length > 0 ? ` (${flags.join(", ")})` : "";
286
+ console.log(` - ${artifact.path} [${artifact.ownership}]${suffix}`);
287
+ }
288
+ console.log("");
289
+ }
290
+ }
291
+
292
+ if (drift.findings.length === 0) {
293
+ console.log("āœ… No drift detected.");
294
+ return;
295
+ }
296
+
297
+ console.log(`āš ļø Drift findings (${drift.findings.length}):`);
298
+ for (const finding of drift.findings) {
299
+ console.log(` [${finding.severity}] ${finding.kind}: ${finding.message}`);
300
+ console.log(` → ${finding.repairAction}`);
301
+ }
302
+ }
303
+
304
+ async function runVerifyCommand(options: { checks?: string }): Promise<void> {
305
+ console.log("šŸ”Ž Running verification checks...\n");
306
+
307
+ const result = await runVerify(options.checks ? options.checks.split(",") : undefined);
308
+
309
+ const statusIcons: Record<string, string> = {
310
+ pass: "āœ…",
311
+ fail: "āŒ",
312
+ skip: "ā­ļø ",
313
+ error: "šŸ’„",
314
+ };
315
+
316
+ for (const check of result.checks) {
317
+ console.log(` ${statusIcons[check.status]} ${check.id.padEnd(10)} ${check.title} (${check.durationMs}ms)`);
318
+ if (check.status === "fail" || check.status === "error") {
319
+ for (const action of check.suggestedActions) {
320
+ console.log(` → ${action}`);
321
+ }
322
+ }
323
+ }
324
+
325
+ console.log(
326
+ `\n${result.summary.done ? "āœ…" : "āŒ"} ${result.summary.passed} passed, ${result.summary.failed} failed, ${result.summary.skipped} skipped, ${result.summary.errors} error(s)`
327
+ );
328
+
329
+ if (!result.summary.done) {
330
+ console.log(' Details: swallowkit machine explain failure');
331
+ process.exitCode = 1;
332
+ }
333
+ }
334
+
335
+ export async function runCli(argv: string[] = process.argv): Promise<void> {
336
+ ensureUtf8ConsoleOnWindows();
337
+ if (isMachineCommand(argv)) {
338
+ await runMachineCli(argv);
339
+ return;
340
+ }
341
+
342
+ await createProgram().parseAsync(normalizeDevCommandArgv(argv));
343
+ }
344
+
345
+ if (require.main === module) {
346
+ void runCli().catch((error) => {
347
+ console.error(error);
348
+ process.exitCode = 1;
349
+ });
350
+ }