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

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 (128) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +66 -61
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/dist/app/proxy-dev-app.d.ts +13 -0
  5. package/dist/app/proxy-dev-app.d.ts.map +1 -0
  6. package/dist/app/proxy-dev-app.js +53 -0
  7. package/dist/app/proxy-dev-app.js.map +1 -0
  8. package/dist/binary-cache.d.ts +5 -0
  9. package/dist/binary-cache.d.ts.map +1 -1
  10. package/dist/binary-cache.js +13 -0
  11. package/dist/binary-cache.js.map +1 -1
  12. package/dist/commands/cloud.d.ts +11 -3
  13. package/dist/commands/cloud.d.ts.map +1 -1
  14. package/dist/commands/cloud.js +33 -25
  15. package/dist/commands/cloud.js.map +1 -1
  16. package/dist/commands/deploy.d.ts.map +1 -1
  17. package/dist/commands/deploy.js +3 -17
  18. package/dist/commands/deploy.js.map +1 -1
  19. package/dist/commands/dev.d.ts +3 -3
  20. package/dist/commands/dev.d.ts.map +1 -1
  21. package/dist/commands/dev.js +66 -59
  22. package/dist/commands/dev.js.map +1 -1
  23. package/dist/commands/diff.d.ts.map +1 -1
  24. package/dist/commands/diff.js +11 -1
  25. package/dist/commands/diff.js.map +1 -1
  26. package/dist/commands/init.js +16 -3
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/push.d.ts.map +1 -1
  29. package/dist/commands/push.js +42 -12
  30. package/dist/commands/push.js.map +1 -1
  31. package/dist/commands/update.d.ts.map +1 -1
  32. package/dist/commands/update.js +16 -0
  33. package/dist/commands/update.js.map +1 -1
  34. package/dist/dev-compose.d.ts +17 -0
  35. package/dist/dev-compose.d.ts.map +1 -0
  36. package/dist/dev-compose.js +374 -0
  37. package/dist/dev-compose.js.map +1 -0
  38. package/dist/diff-output.d.ts +4 -0
  39. package/dist/diff-output.d.ts.map +1 -0
  40. package/dist/diff-output.js +12 -0
  41. package/dist/diff-output.js.map +1 -0
  42. package/dist/docker-postgres.d.ts +21 -3
  43. package/dist/docker-postgres.d.ts.map +1 -1
  44. package/dist/docker-postgres.js +130 -18
  45. package/dist/docker-postgres.js.map +1 -1
  46. package/dist/engine-client.d.ts +5 -3
  47. package/dist/engine-client.d.ts.map +1 -1
  48. package/dist/engine-client.js +2 -1
  49. package/dist/engine-client.js.map +1 -1
  50. package/dist/kong-config.d.ts +4 -0
  51. package/dist/kong-config.d.ts.map +1 -1
  52. package/dist/kong-config.js +12 -1
  53. package/dist/kong-config.js.map +1 -1
  54. package/dist/process-manager.d.ts +2 -0
  55. package/dist/process-manager.d.ts.map +1 -1
  56. package/dist/process-manager.js +16 -1
  57. package/dist/process-manager.js.map +1 -1
  58. package/dist/project-config.d.ts +21 -1
  59. package/dist/project-config.d.ts.map +1 -1
  60. package/dist/project-config.js +15 -0
  61. package/dist/project-config.js.map +1 -1
  62. package/dist/runtime-routes.d.ts +9 -0
  63. package/dist/runtime-routes.d.ts.map +1 -1
  64. package/dist/runtime-routes.js +75 -12
  65. package/dist/runtime-routes.js.map +1 -1
  66. package/dist/schema-ast-v2.d.ts +127 -0
  67. package/dist/schema-ast-v2.d.ts.map +1 -0
  68. package/dist/schema-ast-v2.js +226 -0
  69. package/dist/schema-ast-v2.js.map +1 -0
  70. package/dist/seed.d.ts +8 -0
  71. package/dist/seed.d.ts.map +1 -0
  72. package/dist/seed.js +32 -0
  73. package/dist/seed.js.map +1 -0
  74. package/dist/self-host-compose.d.ts +12 -4
  75. package/dist/self-host-compose.d.ts.map +1 -1
  76. package/dist/self-host-compose.js +146 -35
  77. package/dist/self-host-compose.js.map +1 -1
  78. package/dist/studio-admin-roles.d.ts +7 -0
  79. package/dist/studio-admin-roles.d.ts.map +1 -0
  80. package/dist/studio-admin-roles.js +14 -0
  81. package/dist/studio-admin-roles.js.map +1 -0
  82. package/dist/studio-dev-server.d.ts +22 -0
  83. package/dist/studio-dev-server.d.ts.map +1 -0
  84. package/dist/studio-dev-server.js +28 -0
  85. package/dist/studio-dev-server.js.map +1 -0
  86. package/dist/type-extractor.d.ts +3 -30
  87. package/dist/type-extractor.d.ts.map +1 -1
  88. package/dist/type-extractor.js +485 -148
  89. package/dist/type-extractor.js.map +1 -1
  90. package/dist/type-resolver.d.ts +33 -0
  91. package/dist/type-resolver.d.ts.map +1 -0
  92. package/dist/type-resolver.js +338 -0
  93. package/dist/type-resolver.js.map +1 -0
  94. package/package.json +7 -3
  95. package/src/TYPE-RESOLUTION.md +294 -0
  96. package/src/app/proxy-dev-app.ts +67 -0
  97. package/src/binary-cache.ts +20 -0
  98. package/src/commands/cloud.ts +40 -30
  99. package/src/commands/deploy.ts +3 -18
  100. package/src/commands/dev.ts +72 -69
  101. package/src/commands/diff.ts +11 -1
  102. package/src/commands/init.ts +16 -3
  103. package/src/commands/push.ts +49 -13
  104. package/src/commands/update.ts +17 -0
  105. package/src/dev-compose.ts +455 -0
  106. package/src/diff-output.ts +12 -0
  107. package/src/docker-postgres.ts +184 -27
  108. package/src/engine-client.ts +9 -4
  109. package/src/kong-config.ts +16 -1
  110. package/src/process-manager.ts +18 -1
  111. package/src/project-config.ts +34 -1
  112. package/src/runtime-routes.ts +87 -12
  113. package/src/schema-ast-v2.ts +324 -0
  114. package/src/seed.ts +43 -0
  115. package/src/self-host-compose.ts +168 -36
  116. package/src/studio-admin-roles.ts +16 -0
  117. package/src/studio-dev-server.ts +53 -0
  118. package/src/type-extractor.ts +649 -186
  119. package/src/type-resolver.ts +457 -0
  120. package/tests/config.test.ts +34 -3
  121. package/tests/docker-postgres.test.ts +39 -0
  122. package/tests/normalize-admin-config.test.ts +48 -0
  123. package/tests/proxy-dev-app.test.ts +33 -0
  124. package/tests/runtime-contract.test.ts +119 -4
  125. package/tests/studio-admin-roles.test.ts +27 -0
  126. package/tests/type-extractor.test.ts +607 -23
  127. package/tests/type-resolver.test.ts +59 -0
  128. package/tsconfig.tsbuildinfo +1 -1
@@ -25,7 +25,7 @@ const baseConfig: SupatypeProjectConfig = {
25
25
  describe("runtime contract", () => {
26
26
  it("includes core route families", () => {
27
27
  const paths = runtimeRouteSpec().flatMap((r) => r.paths)
28
- for (const path of ["/rest/v1/", "/auth/v1/", "/storage/v1/", "/realtime/v1/", "/functions/v1/"]) {
28
+ for (const path of ["/rest/v1/", "/auth/v1/", "/storage/v1/", "/realtime/v1/", "/functions/v1/", "/graphql/v1"]) {
29
29
  expect(paths).toContain(path)
30
30
  }
31
31
  })
@@ -48,10 +48,31 @@ describe("runtime contract", () => {
48
48
  expect(kong).toContain("/storage/v1/")
49
49
  expect(kong).toContain("/realtime/v1/")
50
50
  expect(kong).toContain("/functions/v1/")
51
- expect(kong).not.toContain("http://postgrest:3000")
51
+ expect(kong).toContain("http://postgrest:3000/rpc/graphql")
52
+ expect(kong).toContain("Content-Profile:graphql_public")
52
53
  expect(kong).not.toContain("http://storage:5000")
53
54
  })
54
55
 
56
+ it("self-host kong routes studio auth and proxy to supatype-server before static studio", () => {
57
+ const kong = buildKongDeclarative({ unifiedGateway: true })
58
+ const studioAuthIdx = kong.indexOf("/studio/auth/")
59
+ const studioProxyIdx = kong.indexOf("/studio/proxy/")
60
+ const studioStaticIdx = kong.lastIndexOf("/studio/")
61
+ expect(studioAuthIdx).toBeGreaterThan(-1)
62
+ expect(studioProxyIdx).toBeGreaterThan(-1)
63
+ expect(studioAuthIdx).toBeLessThan(studioStaticIdx)
64
+ expect(studioProxyIdx).toBeLessThan(studioStaticIdx)
65
+ expect(kong).toContain("name: supatype-server-studio-auth")
66
+ expect(kong).toContain("name: supatype-server-studio-proxy")
67
+ })
68
+
69
+ it("self-host kong proxies exact /studio to studio UI", () => {
70
+ const kong = buildKongDeclarative({ unifiedGateway: true })
71
+ expect(kong).toContain("name: studio-exact")
72
+ expect(kong).toContain("~/studio$")
73
+ expect(kong).not.toContain("name: redirect")
74
+ })
75
+
55
76
  it("kong declarative output contains route contract paths", () => {
56
77
  const kong = buildKongDeclarative({ appUpstream: "http://app:3000" })
57
78
  expect(kong).toContain("/rest/v1/")
@@ -81,6 +102,99 @@ describe("runtime contract", () => {
81
102
  expect(compose).not.toContain("static-app:")
82
103
  })
83
104
 
105
+ it("self-host compose includes schema-engine tools profile", () => {
106
+ const compose = renderSelfHostCompose(baseConfig)
107
+ expect(compose).toContain("\n schema-engine:\n")
108
+ expect(compose).toContain('profiles: ["tools"]')
109
+ expect(compose).toContain("supatype/schema-engine:latest")
110
+ })
111
+
112
+ it("self-host compose mounts project root at /project (project-directory relative)", () => {
113
+ const compose = renderSelfHostCompose(baseConfig)
114
+ expect(compose).toContain("- .:/project")
115
+ expect(compose).not.toMatch(/- \.\.\/\.\.:\/project/)
116
+ })
117
+
118
+ it("self-host compose mounts kong.yml from .supatype/self-host (project-directory relative)", () => {
119
+ const compose = renderSelfHostCompose(baseConfig)
120
+ expect(compose).toContain("- .supatype/self-host/kong.yml:/etc/kong/kong.yml:ro")
121
+ expect(compose).not.toContain("- ./kong.yml:/etc/kong/kong.yml:ro")
122
+ })
123
+
124
+ it("devLocal compose omits host-published db and server ports", () => {
125
+ const compose = renderSelfHostCompose(baseConfig, process.cwd(), { devLocal: true })
126
+ expect(compose).not.toContain('"5432:5432"')
127
+ expect(compose).not.toContain('"9999:9999"')
128
+ expect(compose).toContain("${SUPATYPE_KONG_PORT:-18473}:8000")
129
+ expect(compose).not.toContain("SUPATYPE_DEV_DB_PORT")
130
+ })
131
+
132
+ it("devLocal compose publishes db to host when overrides.engine is set", () => {
133
+ const compose = renderSelfHostCompose(
134
+ { ...baseConfig, overrides: { engine: "/tmp/supatype-engine" } },
135
+ process.cwd(),
136
+ { devLocal: true },
137
+ )
138
+ expect(compose).toContain("127.0.0.1:${SUPATYPE_DEV_DB_PORT:-54329}:5432")
139
+ expect(compose).not.toContain('"5432:5432"')
140
+ })
141
+
142
+ it("devLocal proxy upstream rewrites localhost to host.docker.internal", () => {
143
+ const compose = renderSelfHostCompose(
144
+ { ...baseConfig, app: { mode: "proxy", upstream: "http://127.0.0.1:4321" } },
145
+ process.cwd(),
146
+ { devLocal: true },
147
+ )
148
+ expect(compose).toContain("SUPATYPE_APP_UPSTREAM: http://host.docker.internal:4321")
149
+ })
150
+
151
+ it("devLocal compose omits studio container when overrides.studio is set", () => {
152
+ const compose = renderSelfHostCompose(
153
+ { ...baseConfig, overrides: { studio: "../supatype/packages/studio" } },
154
+ process.cwd(),
155
+ { devLocal: true },
156
+ )
157
+ expect(compose).not.toContain("\n studio:\n")
158
+ expect(compose).not.toContain("depends_on:\n - server\n - studio")
159
+ })
160
+
161
+ it("devLocal kong routes studio to host Vite when overrides.studio is set", () => {
162
+ const dir = mkdtempSync(join(tmpdir(), "supatype-studio-host-"))
163
+ try {
164
+ writeSelfHostCompose(
165
+ dir,
166
+ { ...baseConfig, overrides: { studio: "../supatype/packages/studio" } },
167
+ { devLocal: true },
168
+ )
169
+ const kong = readFileSync(join(dir, ".supatype", "self-host", "kong.yml"), "utf8")
170
+ expect(kong).toContain("http://host.docker.internal:3002")
171
+ expect(kong).not.toContain("http://studio:3002")
172
+ expect(kong).toContain("strip_path: false")
173
+ } finally {
174
+ rmSync(dir, { recursive: true, force: true })
175
+ }
176
+ })
177
+
178
+ it("devLocal compose enables STUDIO_OPEN_DEV on supatype-server", () => {
179
+ const compose = renderSelfHostCompose(baseConfig, process.cwd(), { devLocal: true })
180
+ expect(compose).toContain('STUDIO_OPEN_DEV: "1"')
181
+ })
182
+
183
+ it("production self-host compose does not enable STUDIO_OPEN_DEV", () => {
184
+ const compose = renderSelfHostCompose(baseConfig)
185
+ expect(compose).not.toContain("STUDIO_OPEN_DEV")
186
+ })
187
+
188
+ it("self-host studio SUPATYPE_CLOUD_JSON omits serviceRoleKey", () => {
189
+ const compose = renderSelfHostCompose(baseConfig)
190
+ const match = compose.match(/SUPATYPE_CLOUD_JSON: '([^']+)'/)
191
+ expect(match).not.toBeNull()
192
+ const parsed = JSON.parse(match![1]!) as Record<string, unknown>
193
+ expect(parsed).toHaveProperty("url")
194
+ expect(parsed).toHaveProperty("anonKey")
195
+ expect(parsed).not.toHaveProperty("serviceRoleKey")
196
+ })
197
+
84
198
  it("self-host compose runs per-project functions-worker and proxies via server", () => {
85
199
  const compose = renderSelfHostCompose(baseConfig)
86
200
  expect(compose).toContain("\n functions-worker:\n")
@@ -208,7 +322,7 @@ export default defineConfig({
208
322
  expect(readFileSync(out.composePath, "utf8")).toContain("services:")
209
323
  expect(readFileSync(out.kongPath, "utf8")).toContain("/rest/v1/")
210
324
  const compose = readFileSync(out.composePath, "utf8")
211
- expect(compose).toContain("${SUPATYPE_POSTGRES_IMAGE:-supatype/postgres:17-latest}")
325
+ expect(compose).toContain("${SUPATYPE_POSTGRES_IMAGE:-supatype/postgres:latest}")
212
326
  expect(compose).toContain("${SUPATYPE_SERVER_IMAGE:-${SUPATYPE_AUTH_IMAGE:-supatype/server:latest}}")
213
327
  expect(compose).toContain("${SUPATYPE_STORAGE_IMAGE:-supatype/storage:latest}")
214
328
  expect(compose).toContain("${SUPATYPE_STUDIO_IMAGE:-supatype/studio:latest}")
@@ -216,7 +330,8 @@ export default defineConfig({
216
330
  expect(compose).toContain("unified gateway")
217
331
  const kong = readFileSync(out.kongPath, "utf8")
218
332
  expect(kong).toContain("http://server:9999")
219
- expect(kong).not.toContain("http://postgrest:3000")
333
+ expect(kong).toContain("http://postgrest:3000/rpc/graphql")
334
+ expect(kong).toContain("Content-Profile:graphql_public")
220
335
  } finally {
221
336
  rmSync(dir, { recursive: true, force: true })
222
337
  }
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { DEFAULT_STUDIO_ADMIN_ROLES, studioAdminRoles, withAdminRoles } from "../src/studio-admin-roles.js"
3
+ import type { SupatypeProjectConfig } from "../src/project-config.js"
4
+
5
+ const baseConfig: SupatypeProjectConfig = {
6
+ project: { name: "acme" },
7
+ database: { provider: "docker" },
8
+ server: { mode: "dev" },
9
+ app: { mode: "none" },
10
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
11
+ }
12
+
13
+ describe("studioAdminRoles", () => {
14
+ it("returns defaults when admin.roles is omitted", () => {
15
+ expect(studioAdminRoles(baseConfig)).toEqual([...DEFAULT_STUDIO_ADMIN_ROLES])
16
+ })
17
+
18
+ it("uses admin.roles from config when set", () => {
19
+ const roles = studioAdminRoles({ ...baseConfig, admin: { roles: ["custom_admin"] } })
20
+ expect(roles).toEqual(["custom_admin"])
21
+ })
22
+
23
+ it("merges adminRoles into engine admin JSON", () => {
24
+ const merged = withAdminRoles({ models: [] }, { ...baseConfig, admin: { roles: ["ops"] } })
25
+ expect(merged).toEqual({ models: [], adminRoles: ["ops"] })
26
+ })
27
+ })