@supatype/cli 0.1.0-alpha.6 → 0.1.0-alpha.7

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 (309) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +203 -1
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/dist/app-config.d.ts +7 -0
  5. package/dist/app-config.d.ts.map +1 -0
  6. package/dist/app-config.js +113 -0
  7. package/dist/app-config.js.map +1 -0
  8. package/dist/augmentation-generator.d.ts +2 -0
  9. package/dist/augmentation-generator.d.ts.map +1 -0
  10. package/dist/augmentation-generator.js +111 -0
  11. package/dist/augmentation-generator.js.map +1 -0
  12. package/dist/binary-cache.d.ts +89 -0
  13. package/dist/binary-cache.d.ts.map +1 -0
  14. package/dist/binary-cache.js +656 -0
  15. package/dist/binary-cache.js.map +1 -0
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +13 -7
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/admin.d.ts.map +1 -1
  20. package/dist/commands/admin.js +4 -3
  21. package/dist/commands/admin.js.map +1 -1
  22. package/dist/commands/app.d.ts.map +1 -1
  23. package/dist/commands/app.js +56 -209
  24. package/dist/commands/app.js.map +1 -1
  25. package/dist/commands/cache.d.ts +6 -0
  26. package/dist/commands/cache.d.ts.map +1 -0
  27. package/dist/commands/cache.js +105 -0
  28. package/dist/commands/cache.js.map +1 -0
  29. package/dist/commands/cloud.d.ts +12 -0
  30. package/dist/commands/cloud.d.ts.map +1 -1
  31. package/dist/commands/cloud.js +36 -46
  32. package/dist/commands/cloud.js.map +1 -1
  33. package/dist/commands/db.d.ts.map +1 -1
  34. package/dist/commands/db.js +47 -54
  35. package/dist/commands/db.js.map +1 -1
  36. package/dist/commands/deploy.d.ts +2 -1
  37. package/dist/commands/deploy.d.ts.map +1 -1
  38. package/dist/commands/deploy.js +92 -51
  39. package/dist/commands/deploy.js.map +1 -1
  40. package/dist/commands/dev.d.ts +11 -0
  41. package/dist/commands/dev.d.ts.map +1 -1
  42. package/dist/commands/dev.js +751 -384
  43. package/dist/commands/dev.js.map +1 -1
  44. package/dist/commands/diff.d.ts.map +1 -1
  45. package/dist/commands/diff.js +20 -15
  46. package/dist/commands/diff.js.map +1 -1
  47. package/dist/commands/engine.d.ts +1 -3
  48. package/dist/commands/engine.d.ts.map +1 -1
  49. package/dist/commands/engine.js +13 -85
  50. package/dist/commands/engine.js.map +1 -1
  51. package/dist/commands/functions.d.ts.map +1 -1
  52. package/dist/commands/functions.js +92 -105
  53. package/dist/commands/functions.js.map +1 -1
  54. package/dist/commands/generate.d.ts.map +1 -1
  55. package/dist/commands/generate.js +22 -12
  56. package/dist/commands/generate.js.map +1 -1
  57. package/dist/commands/init.d.ts +1 -1
  58. package/dist/commands/init.d.ts.map +1 -1
  59. package/dist/commands/init.js +124 -410
  60. package/dist/commands/init.js.map +1 -1
  61. package/dist/commands/migrate-from-v1.d.ts +5 -0
  62. package/dist/commands/migrate-from-v1.d.ts.map +1 -0
  63. package/dist/commands/migrate-from-v1.js +125 -0
  64. package/dist/commands/migrate-from-v1.js.map +1 -0
  65. package/dist/commands/migrate.d.ts.map +1 -1
  66. package/dist/commands/migrate.js +27 -23
  67. package/dist/commands/migrate.js.map +1 -1
  68. package/dist/commands/pg.d.ts +8 -0
  69. package/dist/commands/pg.d.ts.map +1 -0
  70. package/dist/commands/pg.js +102 -0
  71. package/dist/commands/pg.js.map +1 -0
  72. package/dist/commands/pull.d.ts.map +1 -1
  73. package/dist/commands/pull.js +5 -66
  74. package/dist/commands/pull.js.map +1 -1
  75. package/dist/commands/push.d.ts.map +1 -1
  76. package/dist/commands/push.js +99 -39
  77. package/dist/commands/push.js.map +1 -1
  78. package/dist/commands/seed.d.ts +2 -0
  79. package/dist/commands/seed.d.ts.map +1 -1
  80. package/dist/commands/seed.js +44 -11
  81. package/dist/commands/seed.js.map +1 -1
  82. package/dist/commands/self-host.d.ts +7 -1
  83. package/dist/commands/self-host.d.ts.map +1 -1
  84. package/dist/commands/self-host.js +272 -758
  85. package/dist/commands/self-host.js.map +1 -1
  86. package/dist/commands/self-update.d.ts +9 -0
  87. package/dist/commands/self-update.d.ts.map +1 -0
  88. package/dist/commands/self-update.js +33 -0
  89. package/dist/commands/self-update.js.map +1 -0
  90. package/dist/commands/status.d.ts.map +1 -1
  91. package/dist/commands/status.js +4 -3
  92. package/dist/commands/status.js.map +1 -1
  93. package/dist/commands/types.d.ts +3 -0
  94. package/dist/commands/types.d.ts.map +1 -0
  95. package/dist/commands/types.js +62 -0
  96. package/dist/commands/types.js.map +1 -0
  97. package/dist/commands/update.d.ts +7 -0
  98. package/dist/commands/update.d.ts.map +1 -0
  99. package/dist/commands/update.js +77 -0
  100. package/dist/commands/update.js.map +1 -0
  101. package/dist/components.d.ts +5 -0
  102. package/dist/components.d.ts.map +1 -0
  103. package/dist/components.js +3 -0
  104. package/dist/components.js.map +1 -0
  105. package/dist/config.d.ts +10 -51
  106. package/dist/config.d.ts.map +1 -1
  107. package/dist/config.js +101 -33
  108. package/dist/config.js.map +1 -1
  109. package/dist/docker-postgres.d.ts +39 -0
  110. package/dist/docker-postgres.d.ts.map +1 -0
  111. package/dist/docker-postgres.js +96 -0
  112. package/dist/docker-postgres.js.map +1 -0
  113. package/dist/engine-client.d.ts +67 -0
  114. package/dist/engine-client.d.ts.map +1 -0
  115. package/dist/engine-client.js +156 -0
  116. package/dist/engine-client.js.map +1 -0
  117. package/dist/ensure-binary.d.ts +7 -0
  118. package/dist/ensure-binary.d.ts.map +1 -0
  119. package/dist/ensure-binary.js +17 -0
  120. package/dist/ensure-binary.js.map +1 -0
  121. package/dist/functions-router-gen.d.ts +14 -0
  122. package/dist/functions-router-gen.d.ts.map +1 -0
  123. package/dist/functions-router-gen.js +199 -0
  124. package/dist/functions-router-gen.js.map +1 -0
  125. package/dist/index.d.ts +4 -5
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +2 -3
  128. package/dist/index.js.map +1 -1
  129. package/dist/kong-config.d.ts +21 -0
  130. package/dist/kong-config.d.ts.map +1 -0
  131. package/dist/kong-config.js +60 -0
  132. package/dist/kong-config.js.map +1 -0
  133. package/dist/local-gateway.d.ts +7 -0
  134. package/dist/local-gateway.d.ts.map +1 -0
  135. package/dist/local-gateway.js +9 -0
  136. package/dist/local-gateway.js.map +1 -0
  137. package/dist/local-storage.d.ts +8 -0
  138. package/dist/local-storage.d.ts.map +1 -0
  139. package/dist/local-storage.js +14 -0
  140. package/dist/local-storage.js.map +1 -0
  141. package/dist/pgbouncer-userlist.d.ts +5 -0
  142. package/dist/pgbouncer-userlist.d.ts.map +1 -0
  143. package/dist/pgbouncer-userlist.js +14 -0
  144. package/dist/pgbouncer-userlist.js.map +1 -0
  145. package/dist/postgres-ctl.d.ts +44 -0
  146. package/dist/postgres-ctl.d.ts.map +1 -0
  147. package/dist/postgres-ctl.js +137 -0
  148. package/dist/postgres-ctl.js.map +1 -0
  149. package/dist/process-manager.d.ts +41 -0
  150. package/dist/process-manager.d.ts.map +1 -0
  151. package/dist/process-manager.js +120 -0
  152. package/dist/process-manager.js.map +1 -0
  153. package/dist/project-config.d.ts +215 -0
  154. package/dist/project-config.d.ts.map +1 -0
  155. package/dist/project-config.js +145 -0
  156. package/dist/project-config.js.map +1 -0
  157. package/dist/pull-utils.d.ts +15 -0
  158. package/dist/pull-utils.d.ts.map +1 -1
  159. package/dist/pull-utils.js +12 -0
  160. package/dist/pull-utils.js.map +1 -1
  161. package/dist/release-pins.d.ts +7 -0
  162. package/dist/release-pins.d.ts.map +1 -0
  163. package/dist/release-pins.js +27 -0
  164. package/dist/release-pins.js.map +1 -0
  165. package/dist/release-public-key.d.ts +8 -0
  166. package/dist/release-public-key.d.ts.map +1 -0
  167. package/dist/release-public-key.js +13 -0
  168. package/dist/release-public-key.js.map +1 -0
  169. package/dist/runtime-routes.d.ts +25 -0
  170. package/dist/runtime-routes.d.ts.map +1 -0
  171. package/dist/runtime-routes.js +189 -0
  172. package/dist/runtime-routes.js.map +1 -0
  173. package/dist/scripts/postinstall.d.ts +5 -6
  174. package/dist/scripts/postinstall.d.ts.map +1 -1
  175. package/dist/scripts/postinstall.js +36 -20
  176. package/dist/scripts/postinstall.js.map +1 -1
  177. package/dist/self-host-compose.d.ts +14 -0
  178. package/dist/self-host-compose.d.ts.map +1 -0
  179. package/dist/self-host-compose.js +236 -0
  180. package/dist/self-host-compose.js.map +1 -0
  181. package/dist/storage-provision.d.ts +24 -0
  182. package/dist/storage-provision.d.ts.map +1 -0
  183. package/dist/storage-provision.js +44 -0
  184. package/dist/storage-provision.js.map +1 -0
  185. package/dist/systemd.d.ts +26 -0
  186. package/dist/systemd.d.ts.map +1 -0
  187. package/dist/systemd.js +102 -0
  188. package/dist/systemd.js.map +1 -0
  189. package/dist/tsx-runner.d.ts.map +1 -1
  190. package/dist/tsx-runner.js +9 -2
  191. package/dist/tsx-runner.js.map +1 -1
  192. package/dist/type-extractor.d.ts +31 -0
  193. package/dist/type-extractor.d.ts.map +1 -0
  194. package/dist/type-extractor.js +876 -0
  195. package/dist/type-extractor.js.map +1 -0
  196. package/package.json +4 -3
  197. package/releases/deno/VERSION +1 -0
  198. package/scripts/mirror-deno-release.sh +76 -0
  199. package/src/app-config.ts +128 -0
  200. package/src/augmentation-generator.ts +126 -0
  201. package/src/binary-cache.ts +802 -0
  202. package/src/cli.ts +13 -8
  203. package/src/commands/admin.ts +4 -3
  204. package/src/commands/app.ts +67 -231
  205. package/src/commands/cache.ts +117 -0
  206. package/src/commands/cloud.ts +46 -57
  207. package/src/commands/db.ts +54 -63
  208. package/src/commands/deploy.ts +110 -61
  209. package/src/commands/dev.ts +930 -405
  210. package/src/commands/diff.ts +21 -29
  211. package/src/commands/engine.ts +13 -116
  212. package/src/commands/functions.ts +97 -115
  213. package/src/commands/generate.ts +23 -10
  214. package/src/commands/init.ts +136 -414
  215. package/src/commands/migrate-from-v1.ts +131 -0
  216. package/src/commands/migrate.ts +27 -23
  217. package/src/commands/pg.ts +133 -0
  218. package/src/commands/pull.ts +6 -85
  219. package/src/commands/push.ts +128 -59
  220. package/src/commands/seed.ts +54 -12
  221. package/src/commands/self-host.ts +312 -880
  222. package/src/commands/self-update.ts +45 -0
  223. package/src/commands/status.ts +4 -3
  224. package/src/commands/types.ts +76 -0
  225. package/src/commands/update.ts +92 -0
  226. package/src/components.ts +6 -0
  227. package/src/config.ts +127 -94
  228. package/src/docker-postgres.ts +138 -0
  229. package/src/engine-client.ts +231 -0
  230. package/src/ensure-binary.ts +28 -0
  231. package/src/functions-router-gen.ts +224 -0
  232. package/src/index.ts +4 -12
  233. package/src/kong-config.ts +78 -0
  234. package/src/local-gateway.ts +9 -0
  235. package/src/local-storage.ts +14 -0
  236. package/src/pgbouncer-userlist.ts +15 -0
  237. package/src/postgres-ctl.ts +171 -0
  238. package/src/process-manager.ts +151 -0
  239. package/src/project-config.ts +353 -0
  240. package/src/pull-utils.ts +24 -0
  241. package/src/release-pins.ts +31 -0
  242. package/src/release-public-key.ts +12 -0
  243. package/src/runtime-routes.ts +216 -0
  244. package/src/scripts/postinstall.ts +36 -25
  245. package/src/self-host-compose.ts +257 -0
  246. package/src/storage-provision.ts +58 -0
  247. package/src/systemd.ts +137 -0
  248. package/src/tsx-runner.ts +11 -1
  249. package/src/type-extractor.ts +1016 -0
  250. package/tests/app-command.test.ts +54 -0
  251. package/tests/augmentation-generator.test.ts +59 -0
  252. package/tests/binary-cache-cloud-overrides.test.ts +123 -0
  253. package/tests/cached-artifact-format.test.ts +84 -0
  254. package/tests/cli-help.test.ts +40 -14
  255. package/tests/config.test.ts +140 -37
  256. package/tests/engine-distribution.test.ts +3 -3
  257. package/tests/ensure-binary.test.ts +59 -0
  258. package/tests/init.test.ts +28 -86
  259. package/tests/migrate-from-v1.test.ts +29 -0
  260. package/tests/pg-spawn-env.test.ts +18 -0
  261. package/tests/postgres-archive-tag.test.ts +9 -0
  262. package/tests/pull-utils.test.ts +36 -1
  263. package/tests/release-pins.test.ts +28 -0
  264. package/tests/runtime-contract.test.ts +236 -0
  265. package/tests/seed-discover.test.ts +31 -0
  266. package/tests/tsconfig.json +9 -0
  267. package/tests/type-extractor.test.ts +401 -0
  268. package/tsconfig.tsbuildinfo +1 -1
  269. package/vitest.config.ts +12 -0
  270. package/dist/engine/cache.d.ts +0 -37
  271. package/dist/engine/cache.d.ts.map +0 -1
  272. package/dist/engine/cache.js +0 -121
  273. package/dist/engine/cache.js.map +0 -1
  274. package/dist/engine/download.d.ts +0 -19
  275. package/dist/engine/download.d.ts.map +0 -1
  276. package/dist/engine/download.js +0 -108
  277. package/dist/engine/download.js.map +0 -1
  278. package/dist/engine/platform.d.ts +0 -24
  279. package/dist/engine/platform.d.ts.map +0 -1
  280. package/dist/engine/platform.js +0 -50
  281. package/dist/engine/platform.js.map +0 -1
  282. package/dist/engine/resolve.d.ts +0 -37
  283. package/dist/engine/resolve.d.ts.map +0 -1
  284. package/dist/engine/resolve.js +0 -133
  285. package/dist/engine/resolve.js.map +0 -1
  286. package/dist/engine/update-notify.d.ts +0 -11
  287. package/dist/engine/update-notify.d.ts.map +0 -1
  288. package/dist/engine/update-notify.js +0 -43
  289. package/dist/engine/update-notify.js.map +0 -1
  290. package/dist/engine/verify.d.ts +0 -50
  291. package/dist/engine/verify.d.ts.map +0 -1
  292. package/dist/engine/verify.js +0 -161
  293. package/dist/engine/verify.js.map +0 -1
  294. package/dist/engine-version.d.ts +0 -35
  295. package/dist/engine-version.d.ts.map +0 -1
  296. package/dist/engine-version.js +0 -35
  297. package/dist/engine-version.js.map +0 -1
  298. package/dist/engine.d.ts +0 -34
  299. package/dist/engine.d.ts.map +0 -1
  300. package/dist/engine.js +0 -76
  301. package/dist/engine.js.map +0 -1
  302. package/src/engine/cache.ts +0 -135
  303. package/src/engine/download.ts +0 -143
  304. package/src/engine/platform.ts +0 -66
  305. package/src/engine/resolve.ts +0 -197
  306. package/src/engine/update-notify.ts +0 -50
  307. package/src/engine/verify.ts +0 -206
  308. package/src/engine-version.ts +0 -39
  309. package/src/engine.ts +0 -99
@@ -0,0 +1,131 @@
1
+ import type { Command } from "commander"
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs"
3
+ import { basename, dirname, extname, join, resolve } from "node:path"
4
+ import ts from "typescript"
5
+ import { loadConfig } from "../config.js"
6
+ import { schemaPathFromProject } from "../project-config.js"
7
+
8
+ export function registerMigrateFromV1(program: Command): void {
9
+ program
10
+ .command("migrate-from-v1")
11
+ .description("Codemod runtime model() schema DSL into RFC v2 Model<> type aliases")
12
+ .option("--schema <path>", "Path to v1 schema file (defaults to supatype.config.ts schema)")
13
+ .option("--write", "Overwrite source file instead of creating .v2.ts sibling")
14
+ .action((opts: { schema?: string; write?: boolean }) => {
15
+ const cwd = process.cwd()
16
+ const cfg = loadConfig(cwd)
17
+ const schemaPath = opts.schema !== undefined
18
+ ? resolve(cwd, opts.schema)
19
+ : schemaPathFromProject(cfg, cwd)
20
+ if (!existsSync(schemaPath)) {
21
+ throw new Error(`Schema file not found: ${schemaPath}`)
22
+ }
23
+
24
+ const src = readFileSync(schemaPath, "utf8")
25
+ const sf = ts.createSourceFile(schemaPath, src, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)
26
+ const output = codemodSource(sf)
27
+ const outPath = opts.write
28
+ ? schemaPath
29
+ : join(dirname(schemaPath), basename(schemaPath).replace(extname(schemaPath), ".v2.ts"))
30
+
31
+ writeFileSync(outPath, output, "utf8")
32
+ console.log(`v2 schema written to ${outPath}`)
33
+ if (!opts.write) {
34
+ console.log("Review TODO comments and replace unknown mappings before using this file in production.")
35
+ }
36
+ })
37
+ }
38
+
39
+ export function codemodSource(sf: ts.SourceFile): string {
40
+ const lines: string[] = []
41
+ lines.push('import type { Model, UUID, Optional } from "@supatype/types"')
42
+ lines.push("")
43
+ lines.push("// TODO(v2-migration): verify each mapped type and access rule below.")
44
+ lines.push("")
45
+
46
+ for (const stmt of sf.statements) {
47
+ if (!ts.isVariableStatement(stmt)) continue
48
+ if (!(ts.getModifiers(stmt)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false)) continue
49
+
50
+ for (const decl of stmt.declarationList.declarations) {
51
+ if (!ts.isIdentifier(decl.name) || !decl.initializer) continue
52
+ const modelCall = extractModelCall(decl.initializer)
53
+ if (!modelCall) continue
54
+ const fields = extractFields(modelCall.config)
55
+ const modelType = renderModelType(decl.name.text, fields)
56
+ lines.push(modelType)
57
+ lines.push("")
58
+ }
59
+ }
60
+
61
+ if (lines.length <= 4) {
62
+ lines.push("// TODO(v2-migration): no model() declarations were detected in this file.")
63
+ }
64
+
65
+ return lines.join("\n")
66
+ }
67
+
68
+ function extractModelCall(node: ts.Expression): { config: ts.ObjectLiteralExpression } | null {
69
+ if (!ts.isCallExpression(node)) return null
70
+ if (!ts.isIdentifier(node.expression) || node.expression.text !== "model") return null
71
+ const config = node.arguments[1]
72
+ if (!config || !ts.isObjectLiteralExpression(config)) return null
73
+ return { config }
74
+ }
75
+
76
+ function extractFields(config: ts.ObjectLiteralExpression): Array<{ name: string; type: string }> {
77
+ const fieldsProp = config.properties.find(
78
+ (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === "fields",
79
+ )
80
+ if (!fieldsProp || !ts.isPropertyAssignment(fieldsProp) || !ts.isObjectLiteralExpression(fieldsProp.initializer)) {
81
+ return []
82
+ }
83
+
84
+ const result: Array<{ name: string; type: string }> = []
85
+ for (const prop of fieldsProp.initializer.properties) {
86
+ if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue
87
+ result.push({
88
+ name: prop.name.text,
89
+ type: mapFieldInitializerToType(prop.initializer),
90
+ })
91
+ }
92
+ return result
93
+ }
94
+
95
+ function mapFieldInitializerToType(node: ts.Expression): string {
96
+ if (!ts.isCallExpression(node)) return "unknown // TODO(v2-migration): unsupported field expression"
97
+ if (!ts.isPropertyAccessExpression(node.expression)) return "unknown // TODO(v2-migration): unsupported field expression"
98
+ if (!ts.isIdentifier(node.expression.expression) || node.expression.expression.text !== "field") {
99
+ return "unknown // TODO(v2-migration): unsupported field expression"
100
+ }
101
+
102
+ const kind = node.expression.name.text
103
+ switch (kind) {
104
+ case "uuid":
105
+ return "UUID"
106
+ case "text":
107
+ case "slug":
108
+ case "email":
109
+ case "url":
110
+ return "string"
111
+ case "integer":
112
+ case "smallInt":
113
+ case "float":
114
+ case "decimal":
115
+ return "number"
116
+ case "boolean":
117
+ return "boolean"
118
+ case "richText":
119
+ case "json":
120
+ return "Record<string, unknown>"
121
+ default:
122
+ return "unknown // TODO(v2-migration): map field." + kind
123
+ }
124
+ }
125
+
126
+ function renderModelType(name: string, fields: Array<{ name: string; type: string }>): string {
127
+ const fieldsBlock = fields
128
+ .map((field) => ` ${field.name}: ${field.type}`)
129
+ .join("\n")
130
+ return `export type ${name} = Model<{\n${fieldsBlock}\n}>`
131
+ }
@@ -1,7 +1,8 @@
1
1
  import type { Command } from "commander"
2
2
  import { createInterface } from "node:readline"
3
- import { loadConfig } from "../config.js"
4
- import { ensureEngine, invokeEngine } from "../engine.js"
3
+ import { loadConfig, loadSchemaAst } from "../config.js"
4
+ import { connectionString, schemaPathFromProject } from "../project-config.js"
5
+ import { ensureEngine, engineRequest } from "../engine-client.js"
5
6
 
6
7
  export function registerMigrate(program: Command): void {
7
8
  // migrate — apply all pending migrations
@@ -11,15 +12,15 @@ export function registerMigrate(program: Command): void {
11
12
  .option("--connection <url>", "Database connection URL (overrides config)")
12
13
  .action(async (opts: { connection?: string }) => {
13
14
  const config = loadConfig()
14
- const connection = opts.connection ?? config.connection
15
+ const connection = opts.connection ?? connectionString(config)
15
16
 
16
17
  await ensureEngine()
17
- const result = invokeEngine(["migrate", "--pending", "--connection", connection])
18
- if (result.exitCode !== 0) {
19
- console.error(result.stderr || result.stdout)
20
- process.exit(1)
21
- }
22
- console.log(result.stdout || "Migrations applied.")
18
+ const result = await engineRequest<{ message?: string }>("/migrations", {
19
+ database_url: connection,
20
+ schema: "public",
21
+ action: "pending",
22
+ })
23
+ console.log(result.message ?? "Migrations applied.")
23
24
  })
24
25
 
25
26
  // rollback — undo the last applied migration
@@ -29,15 +30,15 @@ export function registerMigrate(program: Command): void {
29
30
  .option("--connection <url>", "Database connection URL (overrides config)")
30
31
  .action(async (opts: { connection?: string }) => {
31
32
  const config = loadConfig()
32
- const connection = opts.connection ?? config.connection
33
+ const connection = opts.connection ?? connectionString(config)
33
34
 
34
35
  await ensureEngine()
35
- const result = invokeEngine(["rollback", "--connection", connection])
36
- if (result.exitCode !== 0) {
37
- console.error(result.stderr || result.stdout)
38
- process.exit(1)
39
- }
40
- console.log(result.stdout || "Rolled back.")
36
+ const result = await engineRequest<{ message?: string }>("/migrations", {
37
+ database_url: connection,
38
+ schema: "public",
39
+ action: "rollback",
40
+ })
41
+ console.log(result.message ?? "Rolled back.")
41
42
  })
42
43
 
43
44
  // reset — drop all tables and re-apply from scratch
@@ -60,15 +61,18 @@ export function registerMigrate(program: Command): void {
60
61
  }
61
62
 
62
63
  const config = loadConfig()
63
- const connection = opts.connection ?? config.connection
64
+ const connection = opts.connection ?? connectionString(config)
65
+ const cwd = process.cwd()
64
66
 
65
67
  await ensureEngine()
66
- const result = invokeEngine(["reset", "--connection", connection])
67
- if (result.exitCode !== 0) {
68
- console.error(result.stderr || result.stdout)
69
- process.exit(1)
70
- }
71
- console.log(result.stdout || "Reset complete.")
68
+ const ast = loadSchemaAst(schemaPathFromProject(config, cwd), cwd)
69
+ const result = await engineRequest<{ message?: string }>("/push", {
70
+ ast,
71
+ database_url: connection,
72
+ schema: "public",
73
+ force: true,
74
+ })
75
+ console.log(result.message ?? "Reset complete.")
72
76
  })
73
77
  }
74
78
 
@@ -0,0 +1,133 @@
1
+ /**
2
+ * supatype pg — manage the native Postgres instance for a project.
3
+ *
4
+ * Commands: start, stop, reset, psql
5
+ */
6
+
7
+ import type { Command } from "commander"
8
+ import { spawnSync } from "node:child_process"
9
+ import { existsSync, mkdirSync, rmSync } from "node:fs"
10
+ import { homedir } from "node:os"
11
+ import { join } from "node:path"
12
+ import { loadConfig } from "../config.js"
13
+ import { resolveBinary } from "../binary-cache.js"
14
+ import {
15
+ initdb,
16
+ start as pgStart,
17
+ stop as pgStop,
18
+ waitReady,
19
+ } from "../postgres-ctl.js"
20
+
21
+ export function registerPg(program: Command): void {
22
+ const pg = program
23
+ .command("pg")
24
+ .description("Manage the native Postgres instance for the current project")
25
+
26
+ // ── start ────────────────────────────────────────────────────────────────
27
+ pg.command("start")
28
+ .description("Start Postgres for the current project")
29
+ .action(async () => {
30
+ const config = loadConfig()
31
+ const opts = await pgOpts(config)
32
+ initdb(opts)
33
+ pgStart(opts)
34
+ await waitReady(opts, 10_000)
35
+ console.log(
36
+ `[supatype] Postgres started on port ${opts.port} (data: ${opts.dataDir})`,
37
+ )
38
+ })
39
+
40
+ // ── stop ─────────────────────────────────────────────────────────────────
41
+ pg.command("stop")
42
+ .description("Stop Postgres for the current project")
43
+ .action(async () => {
44
+ const config = loadConfig()
45
+ const opts = await pgOpts(config)
46
+ pgStop(opts)
47
+ console.log("[supatype] Postgres stopped.")
48
+ })
49
+
50
+ // ── reset ─────────────────────────────────────────────────────────────────
51
+ pg.command("reset")
52
+ .description("Stop Postgres, wipe the data directory, and re-initialise")
53
+ .option("--force", "Skip confirmation prompt")
54
+ .action(async (opts: { force: boolean }) => {
55
+ const config = loadConfig()
56
+ const pgOpts_ = await pgOpts(config)
57
+
58
+ if (!opts.force) {
59
+ const readline = await import("node:readline")
60
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
61
+ const answer = await new Promise<string>((resolve) =>
62
+ rl.question(
63
+ `This will DELETE all data in ${pgOpts_.dataDir}. Continue? [y/N] `,
64
+ resolve,
65
+ ),
66
+ )
67
+ rl.close()
68
+ if (answer.toLowerCase() !== "y") {
69
+ console.log("Aborted.")
70
+ return
71
+ }
72
+ }
73
+
74
+ pgStop(pgOpts_)
75
+ if (existsSync(pgOpts_.dataDir)) {
76
+ rmSync(pgOpts_.dataDir, { recursive: true, force: true })
77
+ console.log(`[supatype] Data directory removed: ${pgOpts_.dataDir}`)
78
+ }
79
+ mkdirSync(pgOpts_.dataDir, { recursive: true })
80
+ initdb(pgOpts_)
81
+ pgStart(pgOpts_)
82
+ await waitReady(pgOpts_, 10_000)
83
+ console.log("[supatype] Postgres reset and started.")
84
+ })
85
+
86
+ // ── psql ─────────────────────────────────────────────────────────────────
87
+ pg.command("psql [dbname]")
88
+ .description("Open a psql shell connected to the project database")
89
+ .action(async (dbname?: string) => {
90
+ const config = loadConfig()
91
+ const opts = await pgOpts(config)
92
+ const db = dbname ?? config.project.name
93
+ const psql = join(opts.pgBinDir, "psql")
94
+
95
+ const result = spawnSync(
96
+ psql,
97
+ ["-h", "127.0.0.1", "-p", String(opts.port), "-U", "postgres", db],
98
+ { stdio: "inherit" },
99
+ )
100
+ process.exit(result.status ?? 0)
101
+ })
102
+ }
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Helper: build PgOptions from config
106
+ // ---------------------------------------------------------------------------
107
+
108
+ async function pgOpts(
109
+ config: ReturnType<typeof loadConfig>,
110
+ ): Promise<import("../postgres-ctl.js").PgOptions> {
111
+ const projectName = config.project.name
112
+ const stateRoot = join(homedir(), ".supatype", "projects", projectName)
113
+ const dataDir = config.database.data_dir ?? join(stateRoot, "data")
114
+ const logsDir = join(stateRoot, "logs")
115
+ mkdirSync(logsDir, { recursive: true })
116
+
117
+ // Resolve pg binary dir.
118
+ const pgCacheDir = await (async () => {
119
+ const override = config.overrides?.postgres_dir
120
+ if (override) return join(override, "bin")
121
+ const { cachePath, currentPlatform } = await import("../binary-cache.js")
122
+ const platform = currentPlatform()
123
+ const version = config.versions.postgres
124
+ return join(cachePath("postgres", version), `pg-${version}`, "bin")
125
+ })()
126
+
127
+ return {
128
+ pgBinDir: pgCacheDir,
129
+ dataDir,
130
+ port: 5432,
131
+ logPath: join(logsDir, "postgres.log"),
132
+ }
133
+ }
@@ -1,96 +1,17 @@
1
1
  import type { Command } from "commander"
2
- import { mkdirSync, writeFileSync } from "node:fs"
3
- import { resolve } from "node:path"
4
- import { loadConfig } from "../config.js"
5
- import { ensureEngine, invokeEngine } from "../engine.js"
6
- import { pgTypeToField, toCamelCase, type ColumnInfo } from "../pull-utils.js"
7
-
8
- interface IntrospectResult {
9
- models: Array<{
10
- name: string
11
- tableName: string
12
- columns: ColumnInfo[]
13
- }>
14
- }
2
+ import { ensureEngine } from "../engine-client.js"
15
3
 
16
4
  export function registerPull(program: Command): void {
17
5
  program
18
6
  .command("pull")
19
7
  .description(
20
- "Introspect an existing Postgres database and generate TypeScript schema files",
8
+ "Introspect an existing Postgres database (deprecated in type-first mode)",
21
9
  )
22
- .option("--connection <url>", "Database connection URL (overrides config)")
23
- .option("--output <path>", "Output directory for schema files", "./schema")
24
- .action(async (opts: { connection?: string; output: string }) => {
25
- const cwd = process.cwd()
26
- const connection = opts.connection ?? loadConfig(cwd).connection
27
-
10
+ .action(async () => {
28
11
  await ensureEngine()
29
- console.log("Introspecting database...")
30
- const result = invokeEngine([
31
- "introspect",
32
- "--connection",
33
- connection,
34
- "--format",
35
- "json",
36
- ])
37
- if (result.exitCode !== 0) {
38
- console.error(result.stderr || result.stdout)
39
- process.exit(1)
40
- }
41
-
42
- const introspected = JSON.parse(result.stdout) as IntrospectResult
43
- const models = introspected.models ?? []
44
-
45
- if (models.length === 0) {
46
- console.log("No tables found in the database.")
47
- return
48
- }
49
-
50
- const outputDir = resolve(cwd, opts.output)
51
- mkdirSync(outputDir, { recursive: true })
52
-
53
- for (const model of models) {
54
- const content = generateModelFile(model)
55
- writeFileSync(resolve(outputDir, `${model.name}.ts`), content, "utf8")
56
- console.log(` wrote ${opts.output}/${model.name}.ts`)
57
- }
58
-
59
- const indexContent = generateIndexFile(models.map((m) => m.name))
60
- writeFileSync(resolve(outputDir, "index.ts"), indexContent, "utf8")
61
- console.log(` wrote ${opts.output}/index.ts`)
62
-
63
- console.log(
64
- `\nPulled ${models.length} model(s). Review TODO comments before running supatype push.\n`,
12
+ throw new Error(
13
+ "The legacy `supatype pull` schema generator has been removed.\n" +
14
+ "Use type-based models with @supatype/types and run `supatype generate`.",
65
15
  )
66
16
  })
67
17
  }
68
-
69
- function generateModelFile(model: IntrospectResult["models"][number]): string {
70
- const fieldLines = model.columns
71
- .map((col) => ` ${col.name}: ${pgTypeToField(col)},`)
72
- .join("\n")
73
-
74
- return `import { model, field, access } from "@supatype/schema"
75
-
76
- // TODO: review access rules — all operations default to authenticated
77
- export const ${toCamelCase(model.name)} = model(${JSON.stringify(model.name)}, {
78
- tableName: ${JSON.stringify(model.tableName)},
79
- fields: {
80
- ${fieldLines}
81
- },
82
- access: {
83
- read: access.role("authenticated"),
84
- create: access.role("authenticated"),
85
- update: access.role("authenticated"),
86
- delete: access.role("authenticated"),
87
- },
88
- })
89
- `
90
- }
91
-
92
- function generateIndexFile(names: string[]): string {
93
- return names
94
- .map((n) => `export { ${toCamelCase(n)} } from "./${n}.js"`)
95
- .join("\n") + "\n"
96
- }