@polardbx/pxbaas 0.0.0-stage → 0.1.0-beta.2

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 (267) hide show
  1. package/README.md +107 -2
  2. package/bin/pxbaas.js +13 -0
  3. package/dist/app/preflight.d.ts +38 -0
  4. package/dist/app/preflight.d.ts.map +1 -0
  5. package/dist/app/preflight.js +79 -0
  6. package/dist/app/preflight.js.map +1 -0
  7. package/dist/app/spec-lint.d.ts +45 -0
  8. package/dist/app/spec-lint.d.ts.map +1 -0
  9. package/dist/app/spec-lint.js +407 -0
  10. package/dist/app/spec-lint.js.map +1 -0
  11. package/dist/app/templates.d.ts +143 -0
  12. package/dist/app/templates.d.ts.map +1 -0
  13. package/dist/app/templates.js +151 -0
  14. package/dist/app/templates.js.map +1 -0
  15. package/dist/cli/root.d.ts +3 -0
  16. package/dist/cli/root.d.ts.map +1 -0
  17. package/dist/cli/root.js +69 -0
  18. package/dist/cli/root.js.map +1 -0
  19. package/dist/commands/app/index.d.ts +8 -0
  20. package/dist/commands/app/index.d.ts.map +1 -0
  21. package/dist/commands/app/index.js +1476 -0
  22. package/dist/commands/app/index.js.map +1 -0
  23. package/dist/commands/auth/index.d.ts +3 -0
  24. package/dist/commands/auth/index.d.ts.map +1 -0
  25. package/dist/commands/auth/index.js +198 -0
  26. package/dist/commands/auth/index.js.map +1 -0
  27. package/dist/commands/completion/index.d.ts +3 -0
  28. package/dist/commands/completion/index.d.ts.map +1 -0
  29. package/dist/commands/completion/index.js +10 -0
  30. package/dist/commands/completion/index.js.map +1 -0
  31. package/dist/commands/data/index.d.ts +3 -0
  32. package/dist/commands/data/index.d.ts.map +1 -0
  33. package/dist/commands/data/index.js +245 -0
  34. package/dist/commands/data/index.js.map +1 -0
  35. package/dist/commands/db/index.d.ts +15 -0
  36. package/dist/commands/db/index.d.ts.map +1 -0
  37. package/dist/commands/db/index.js +389 -0
  38. package/dist/commands/db/index.js.map +1 -0
  39. package/dist/commands/doctor/index.d.ts +3 -0
  40. package/dist/commands/doctor/index.d.ts.map +1 -0
  41. package/dist/commands/doctor/index.js +305 -0
  42. package/dist/commands/doctor/index.js.map +1 -0
  43. package/dist/commands/functions/delete.d.ts +3 -0
  44. package/dist/commands/functions/delete.d.ts.map +1 -0
  45. package/dist/commands/functions/delete.js +55 -0
  46. package/dist/commands/functions/delete.js.map +1 -0
  47. package/dist/commands/functions/deploy.d.ts +3 -0
  48. package/dist/commands/functions/deploy.d.ts.map +1 -0
  49. package/dist/commands/functions/deploy.js +118 -0
  50. package/dist/commands/functions/deploy.js.map +1 -0
  51. package/dist/commands/functions/index.d.ts +3 -0
  52. package/dist/commands/functions/index.d.ts.map +1 -0
  53. package/dist/commands/functions/index.js +15 -0
  54. package/dist/commands/functions/index.js.map +1 -0
  55. package/dist/commands/functions/list.d.ts +6 -0
  56. package/dist/commands/functions/list.d.ts.map +1 -0
  57. package/dist/commands/functions/list.js +63 -0
  58. package/dist/commands/functions/list.js.map +1 -0
  59. package/dist/commands/functions/new.d.ts +3 -0
  60. package/dist/commands/functions/new.d.ts.map +1 -0
  61. package/dist/commands/functions/new.js +57 -0
  62. package/dist/commands/functions/new.js.map +1 -0
  63. package/dist/commands/gen/index.d.ts +3 -0
  64. package/dist/commands/gen/index.d.ts.map +1 -0
  65. package/dist/commands/gen/index.js +320 -0
  66. package/dist/commands/gen/index.js.map +1 -0
  67. package/dist/commands/instance/index.d.ts +8 -0
  68. package/dist/commands/instance/index.d.ts.map +1 -0
  69. package/dist/commands/instance/index.js +361 -0
  70. package/dist/commands/instance/index.js.map +1 -0
  71. package/dist/commands/login/index.d.ts +3 -0
  72. package/dist/commands/login/index.d.ts.map +1 -0
  73. package/dist/commands/login/index.js +160 -0
  74. package/dist/commands/login/index.js.map +1 -0
  75. package/dist/commands/login/login.d.ts +3 -0
  76. package/dist/commands/login/login.d.ts.map +1 -0
  77. package/dist/commands/login/login.js +185 -0
  78. package/dist/commands/login/login.js.map +1 -0
  79. package/dist/commands/logout/index.d.ts +3 -0
  80. package/dist/commands/logout/index.d.ts.map +1 -0
  81. package/dist/commands/logout/index.js +41 -0
  82. package/dist/commands/logout/index.js.map +1 -0
  83. package/dist/commands/profile/import-env.d.ts +13 -0
  84. package/dist/commands/profile/import-env.d.ts.map +1 -0
  85. package/dist/commands/profile/import-env.js +81 -0
  86. package/dist/commands/profile/import-env.js.map +1 -0
  87. package/dist/commands/profile/index.d.ts +3 -0
  88. package/dist/commands/profile/index.d.ts.map +1 -0
  89. package/dist/commands/profile/index.js +112 -0
  90. package/dist/commands/profile/index.js.map +1 -0
  91. package/dist/commands/rest/index.d.ts +3 -0
  92. package/dist/commands/rest/index.d.ts.map +1 -0
  93. package/dist/commands/rest/index.js +102 -0
  94. package/dist/commands/rest/index.js.map +1 -0
  95. package/dist/commands/skill/index.d.ts +11 -0
  96. package/dist/commands/skill/index.d.ts.map +1 -0
  97. package/dist/commands/skill/index.js +153 -0
  98. package/dist/commands/skill/index.js.map +1 -0
  99. package/dist/commands/status/index.d.ts +3 -0
  100. package/dist/commands/status/index.d.ts.map +1 -0
  101. package/dist/commands/status/index.js +59 -0
  102. package/dist/commands/status/index.js.map +1 -0
  103. package/dist/commands/storage/index.d.ts +3 -0
  104. package/dist/commands/storage/index.d.ts.map +1 -0
  105. package/dist/commands/storage/index.js +198 -0
  106. package/dist/commands/storage/index.js.map +1 -0
  107. package/dist/commands/whoami/index.d.ts +3 -0
  108. package/dist/commands/whoami/index.d.ts.map +1 -0
  109. package/dist/commands/whoami/index.js +82 -0
  110. package/dist/commands/whoami/index.js.map +1 -0
  111. package/dist/credentials/commit.d.ts +38 -0
  112. package/dist/credentials/commit.d.ts.map +1 -0
  113. package/dist/credentials/commit.js +57 -0
  114. package/dist/credentials/commit.js.map +1 -0
  115. package/dist/credentials/credential-store.d.ts +57 -0
  116. package/dist/credentials/credential-store.d.ts.map +1 -0
  117. package/dist/credentials/credential-store.js +180 -0
  118. package/dist/credentials/credential-store.js.map +1 -0
  119. package/dist/credentials/env-file.d.ts +44 -0
  120. package/dist/credentials/env-file.d.ts.map +1 -0
  121. package/dist/credentials/env-file.js +118 -0
  122. package/dist/credentials/env-file.js.map +1 -0
  123. package/dist/credentials/formatter.d.ts +39 -0
  124. package/dist/credentials/formatter.d.ts.map +1 -0
  125. package/dist/credentials/formatter.js +79 -0
  126. package/dist/credentials/formatter.js.map +1 -0
  127. package/dist/credentials/index.d.ts +13 -0
  128. package/dist/credentials/index.d.ts.map +1 -0
  129. package/dist/credentials/index.js +13 -0
  130. package/dist/credentials/index.js.map +1 -0
  131. package/dist/credentials/jwt-introspect.d.ts +32 -0
  132. package/dist/credentials/jwt-introspect.d.ts.map +1 -0
  133. package/dist/credentials/jwt-introspect.js +64 -0
  134. package/dist/credentials/jwt-introspect.js.map +1 -0
  135. package/dist/credentials/masker.d.ts +20 -0
  136. package/dist/credentials/masker.d.ts.map +1 -0
  137. package/dist/credentials/masker.js +37 -0
  138. package/dist/credentials/masker.js.map +1 -0
  139. package/dist/credentials/profile.d.ts +83 -0
  140. package/dist/credentials/profile.d.ts.map +1 -0
  141. package/dist/credentials/profile.js +184 -0
  142. package/dist/credentials/profile.js.map +1 -0
  143. package/dist/credentials/tenant-guard.d.ts +16 -0
  144. package/dist/credentials/tenant-guard.d.ts.map +1 -0
  145. package/dist/credentials/tenant-guard.js +53 -0
  146. package/dist/credentials/tenant-guard.js.map +1 -0
  147. package/dist/credentials/tty-guard.d.ts +19 -0
  148. package/dist/credentials/tty-guard.d.ts.map +1 -0
  149. package/dist/credentials/tty-guard.js +47 -0
  150. package/dist/credentials/tty-guard.js.map +1 -0
  151. package/dist/db/apply-schema.d.ts +144 -0
  152. package/dist/db/apply-schema.d.ts.map +1 -0
  153. package/dist/db/apply-schema.js +359 -0
  154. package/dist/db/apply-schema.js.map +1 -0
  155. package/dist/db/sql-file.d.ts +104 -0
  156. package/dist/db/sql-file.d.ts.map +1 -0
  157. package/dist/db/sql-file.js +584 -0
  158. package/dist/db/sql-file.js.map +1 -0
  159. package/dist/instance/provision.d.ts +89 -0
  160. package/dist/instance/provision.d.ts.map +1 -0
  161. package/dist/instance/provision.js +139 -0
  162. package/dist/instance/provision.js.map +1 -0
  163. package/dist/instance/zero-store.d.ts +47 -0
  164. package/dist/instance/zero-store.d.ts.map +1 -0
  165. package/dist/instance/zero-store.js +91 -0
  166. package/dist/instance/zero-store.js.map +1 -0
  167. package/dist/main.d.ts +3 -0
  168. package/dist/main.d.ts.map +1 -0
  169. package/dist/main.js +46 -0
  170. package/dist/main.js.map +1 -0
  171. package/dist/skill/assets.d.ts +38 -0
  172. package/dist/skill/assets.d.ts.map +1 -0
  173. package/dist/skill/assets.js +111 -0
  174. package/dist/skill/assets.js.map +1 -0
  175. package/dist/skill/hint.d.ts +39 -0
  176. package/dist/skill/hint.d.ts.map +1 -0
  177. package/dist/skill/hint.js +109 -0
  178. package/dist/skill/hint.js.map +1 -0
  179. package/dist/skill/hosts.d.ts +21 -0
  180. package/dist/skill/hosts.d.ts.map +1 -0
  181. package/dist/skill/hosts.js +38 -0
  182. package/dist/skill/hosts.js.map +1 -0
  183. package/dist/skill/installer.d.ts +88 -0
  184. package/dist/skill/installer.d.ts.map +1 -0
  185. package/dist/skill/installer.js +203 -0
  186. package/dist/skill/installer.js.map +1 -0
  187. package/dist/skill/ownership.d.ts +35 -0
  188. package/dist/skill/ownership.d.ts.map +1 -0
  189. package/dist/skill/ownership.js +52 -0
  190. package/dist/skill/ownership.js.map +1 -0
  191. package/package.json +63 -3
  192. package/skills/pxbaas-app-spec/SKILL.md +163 -0
  193. package/skills/pxbaas-app-spec/references/deploy-options.md +157 -0
  194. package/skills/pxbaas-app-spec/references/guardrails-pitfalls.md +89 -0
  195. package/skills/pxbaas-app-spec/references/runtime-contract.md +151 -0
  196. package/skills/pxbaas-app-spec/references/ssr-session.md +121 -0
  197. package/skills/pxbaas-app-spec/references/templates-examples.md +311 -0
  198. package/skills/pxbaas-cli/SKILL.md +171 -0
  199. package/skills/pxbaas-cli/references/api-reference.md +68 -0
  200. package/skills/pxbaas-cli/references/app-deploy.md +170 -0
  201. package/skills/pxbaas-cli/references/auth-and-credentials.md +100 -0
  202. package/skills/pxbaas-cli/references/data-postgrest.md +85 -0
  203. package/skills/pxbaas-cli/references/db-and-meta.md +97 -0
  204. package/skills/pxbaas-cli/references/edge-functions.md +71 -0
  205. package/skills/pxbaas-cli/references/multi-tenant-apps.md +138 -0
  206. package/skills/pxbaas-cli/references/provision.md +86 -0
  207. package/skills/pxbaas-cli/references/safety-and-two-phase.md +49 -0
  208. package/skills/pxbaas-cli/references/storage.md +61 -0
  209. package/skills/pxbaas-cli/references/troubleshooting.md +73 -0
  210. package/templates/webapp/api/index.ts +55 -0
  211. package/templates/webapp/csr-bff/README.md +81 -0
  212. package/templates/webapp/csr-bff/backend/index.ts +168 -0
  213. package/templates/webapp/csr-bff/db/rls.json +13 -0
  214. package/templates/webapp/csr-bff/db/schema.sql +49 -0
  215. package/templates/webapp/csr-bff/frontend/dist/admin.html +101 -0
  216. package/templates/webapp/csr-bff/frontend/dist/article.html +44 -0
  217. package/templates/webapp/csr-bff/frontend/dist/blog.js +206 -0
  218. package/templates/webapp/csr-bff/frontend/dist/blogger.html +53 -0
  219. package/templates/webapp/csr-bff/frontend/dist/index.html +70 -0
  220. package/templates/webapp/csr-bff/frontend/dist/login.html +56 -0
  221. package/templates/webapp/csr-bff/frontend/dist/profile.html +59 -0
  222. package/templates/webapp/csr-bff/frontend/dist/signup.html +78 -0
  223. package/templates/webapp/csr-bff/frontend/dist/style.css +27 -0
  224. package/templates/webapp/manifest.json +299 -0
  225. package/templates/webapp/mpa/about.html +29 -0
  226. package/templates/webapp/mpa/app.js +42 -0
  227. package/templates/webapp/mpa/index.html +42 -0
  228. package/templates/webapp/mpa/index.ts +60 -0
  229. package/templates/webapp/mpa/style.css +42 -0
  230. package/templates/webapp/react-vite/frontend/index.html +12 -0
  231. package/templates/webapp/react-vite/frontend/package-lock.json +1826 -0
  232. package/templates/webapp/react-vite/frontend/package.json +23 -0
  233. package/templates/webapp/react-vite/frontend/src/App.tsx +34 -0
  234. package/templates/webapp/react-vite/frontend/src/main.tsx +13 -0
  235. package/templates/webapp/react-vite/frontend/src/style.css +46 -0
  236. package/templates/webapp/react-vite/frontend/tsconfig.json +20 -0
  237. package/templates/webapp/react-vite/frontend/vite.config.ts +10 -0
  238. package/templates/webapp/react-vite-hono/backend/index.ts +21 -0
  239. package/templates/webapp/react-vite-hono/frontend/index.html +12 -0
  240. package/templates/webapp/react-vite-hono/frontend/package-lock.json +1826 -0
  241. package/templates/webapp/react-vite-hono/frontend/package.json +23 -0
  242. package/templates/webapp/react-vite-hono/frontend/src/App.tsx +47 -0
  243. package/templates/webapp/react-vite-hono/frontend/src/main.tsx +13 -0
  244. package/templates/webapp/react-vite-hono/frontend/src/style.css +66 -0
  245. package/templates/webapp/react-vite-hono/frontend/tsconfig.json +20 -0
  246. package/templates/webapp/react-vite-hono/frontend/vite.config.ts +10 -0
  247. package/templates/webapp/spa/index.ts +119 -0
  248. package/templates/webapp/ssr-auth/backend/index.ts +133 -0
  249. package/templates/webapp/ssr-auth/frontend/dist/index.html +15 -0
  250. package/templates/webapp/ssr-blog/README.md +111 -0
  251. package/templates/webapp/ssr-blog/backend/index.ts +764 -0
  252. package/templates/webapp/ssr-blog/db/rls.json +13 -0
  253. package/templates/webapp/ssr-blog/db/schema.sql +51 -0
  254. package/templates/webapp/ssr-blog/frontend/dist/index.html +39 -0
  255. package/templates/webapp/ssr-frameworks/README.md +64 -0
  256. package/templates/webapp/ssr-frameworks/backend/index.ts +241 -0
  257. package/templates/webapp/ssr-frameworks/frontend/dist/index.html +31 -0
  258. package/templates/webapp/ssr-hono/backend/index.ts +92 -0
  259. package/templates/webapp/ssr-hono/frontend/dist/index.html +12 -0
  260. package/templates/webapp/ssr-shop/README.md +80 -0
  261. package/templates/webapp/ssr-shop/backend/index.ts +491 -0
  262. package/templates/webapp/ssr-shop/db/rls.json +16 -0
  263. package/templates/webapp/ssr-shop/db/schema.sql +90 -0
  264. package/templates/webapp/ssr-shop/frontend/dist/index.html +12 -0
  265. package/templates/webapp/vanilla-static/frontend/app.js +6 -0
  266. package/templates/webapp/vanilla-static/frontend/index.html +19 -0
  267. package/templates/webapp/vanilla-static/frontend/style.css +43 -0
@@ -0,0 +1,299 @@
1
+ {
2
+ "version": 1,
3
+ "templates": [
4
+ {
5
+ "id": "spa",
6
+ "description": "Self-contained single-page webapp: inline HTML/CSS/JS + a built-in JSON API via ?action=. Best for shareable demos.",
7
+ "entrypoint": "index.ts"
8
+ },
9
+ {
10
+ "id": "api",
11
+ "description": "Headless JSON backend (Deno.serve) with ?action= routing and CORS. Best for webhooks / API-only demos.",
12
+ "entrypoint": "index.ts"
13
+ },
14
+ {
15
+ "id": "mpa",
16
+ "description": "Multi-page static webapp: real index.html/about.html/style.css/app.js served by path via the proxy static branch, plus a worker JSON API via ?action=. Best for traditional multi-page sites.",
17
+ "entrypoint": "index.ts",
18
+ "mode": "mpa",
19
+ "files": [
20
+ "index.ts",
21
+ "index.html",
22
+ "about.html",
23
+ "style.css",
24
+ "app.js"
25
+ ],
26
+ "pages": [
27
+ "index.html",
28
+ "about.html"
29
+ ],
30
+ "assets": [
31
+ "style.css",
32
+ "app.js"
33
+ ]
34
+ },
35
+ {
36
+ "id": "vanilla-static",
37
+ "description": "Minimal text-only static app for validating the /apps mount and release lifecycle.",
38
+ "entrypoint": "frontend/index.html",
39
+ "mode": "webapp",
40
+ "files": [
41
+ "frontend/index.html",
42
+ "frontend/style.css",
43
+ "frontend/app.js"
44
+ ],
45
+ "frontend": {
46
+ "root": "frontend/dist",
47
+ "routing": "files",
48
+ "index": "index.html",
49
+ "fallback": null
50
+ },
51
+ "backend": null
52
+ },
53
+ {
54
+ "id": "react-vite",
55
+ "description": "React + Vite static app with HashRouter, relative base, plain CSS, and exact dependency versions.",
56
+ "entrypoint": "frontend/src/App.tsx",
57
+ "mode": "webapp",
58
+ "files": [
59
+ "frontend/package.json",
60
+ "frontend/package-lock.json",
61
+ "frontend/index.html",
62
+ "frontend/tsconfig.json",
63
+ "frontend/vite.config.ts",
64
+ "frontend/src/main.tsx",
65
+ "frontend/src/App.tsx",
66
+ "frontend/src/style.css"
67
+ ],
68
+ "frontend": {
69
+ "root": "frontend/dist",
70
+ "routing": "files",
71
+ "index": "index.html",
72
+ "fallback": null
73
+ },
74
+ "backend": null
75
+ },
76
+ {
77
+ "id": "react-vite-hono",
78
+ "description": "React + Vite + HashRouter frontend with a Deno-served, platform-versioned Hono backend.",
79
+ "entrypoint": "backend/index.ts",
80
+ "mode": "webapp",
81
+ "files": [
82
+ "frontend/package.json",
83
+ "frontend/package-lock.json",
84
+ "frontend/index.html",
85
+ "frontend/tsconfig.json",
86
+ "frontend/vite.config.ts",
87
+ "frontend/src/main.tsx",
88
+ "frontend/src/App.tsx",
89
+ "frontend/src/style.css",
90
+ "backend/index.ts"
91
+ ],
92
+ "frontend": {
93
+ "root": "frontend/dist",
94
+ "routing": "files",
95
+ "index": "index.html",
96
+ "fallback": null
97
+ },
98
+ "backend": {
99
+ "entrypoint": "backend/index.ts",
100
+ "framework": "hono",
101
+ "pathMode": "strip-app-api-prefix",
102
+ "verifyJwt": false,
103
+ "secrets": [],
104
+ "egressPolicy": "deny"
105
+ }
106
+ },
107
+ {
108
+ "id": "ssr-hono",
109
+ "description": "SSR-shell webapp: Hono worker server-renders the page shell at /page (static-miss fallthrough, fallback=worker); browser hydrates and fetches data client-side. Single-file self-contained worker per D16.",
110
+ "entrypoint": "backend/index.ts",
111
+ "mode": "webapp",
112
+ "files": [
113
+ "backend/index.ts",
114
+ "frontend/dist/index.html"
115
+ ],
116
+ "frontend": {
117
+ "root": "frontend/dist",
118
+ "routing": "files",
119
+ "index": "index.html",
120
+ "fallback": "worker"
121
+ },
122
+ "backend": {
123
+ "entrypoint": "backend/index.ts",
124
+ "framework": "hono",
125
+ "pathMode": "strip-app-api-prefix",
126
+ "verifyJwt": false,
127
+ "secrets": [],
128
+ "egressPolicy": "deny"
129
+ },
130
+ "ssrProbePath": "/page"
131
+ },
132
+ {
133
+ "id": "ssr-auth",
134
+ "description": "SSR webapp with proxy-injected session (方案 C): the worker server-renders authenticated pages from trusted X-App-User-* headers; it never reads cookies, never sets Set-Cookie, and never puts tokens in URLs. Requires capabilities.sessionMode=proxy-injected-header.",
135
+ "entrypoint": "backend/index.ts",
136
+ "mode": "webapp",
137
+ "files": [
138
+ "backend/index.ts",
139
+ "frontend/dist/index.html"
140
+ ],
141
+ "frontend": {
142
+ "root": "frontend/dist",
143
+ "routing": "files",
144
+ "index": "index.html",
145
+ "fallback": null
146
+ },
147
+ "backend": {
148
+ "entrypoint": "backend/index.ts",
149
+ "framework": "deno",
150
+ "pathMode": "strip-app-api-prefix",
151
+ "verifyJwt": false,
152
+ "secrets": [],
153
+ "egressPolicy": "deny",
154
+ "session": "proxy-injected"
155
+ }
156
+ },
157
+ {
158
+ "id": "ssr-blog",
159
+ "description": "Full-site SSR blog (zero npm deps) with proxy-injected session: the worker renders every page server-side from the instance internal base and reads identity ONLY from X-App-User-* headers. Requires capabilities.sessionMode=proxy-injected-header.",
160
+ "entrypoint": "backend/index.ts",
161
+ "mode": "webapp",
162
+ "files": [
163
+ "README.md",
164
+ "backend/index.ts",
165
+ "db/schema.sql",
166
+ "db/rls.json",
167
+ "frontend/dist/index.html"
168
+ ],
169
+ "frontend": {
170
+ "root": "frontend/dist",
171
+ "routing": "files",
172
+ "index": "index.html",
173
+ "fallback": "worker"
174
+ },
175
+ "backend": {
176
+ "entrypoint": "backend/index.ts",
177
+ "framework": "deno",
178
+ "pathMode": "strip-app-api-prefix",
179
+ "verifyJwt": false,
180
+ "secrets": [],
181
+ "egressPolicy": "deny",
182
+ "session": "proxy-injected"
183
+ },
184
+ "ssrProbePath": "/posts",
185
+ "nextSteps": [
186
+ "Initialize the database BEFORE deploy: run `pxbaas app db-init <name> --dir <appsDir>`. It reads db/schema.sql (DDL + seed) and db/rls.json (RLS registry), shows the full plan, and applies it only after you authorize (--dry-run to preview, --yes for non-interactive). Works in single-tenant (/pg/query) AND multi-tenant (/api/tenant-ddl with your per-tenant service_role key); the CLI never auto-runs DDL.",
187
+ "Requires capabilities.sessionMode=proxy-injected-header.",
188
+ "Data-plane base and anon key come from the platform-in SUPABASE_INTERNAL_URL / SUPABASE_ANON_KEY (edge-runtime MR #30497903); no plaintext key editing is needed."
189
+ ]
190
+ },
191
+ {
192
+ "id": "csr-bff",
193
+ "description": "Front/back separated CSR blog: real static pages served by path plus a same-origin Deno BFF worker that proxies /api/* to the instance internal REST/Auth. Identity comes from proxy-injected X-App-User-Token (client Authorization is stripped on /apps).",
194
+ "entrypoint": "backend/index.ts",
195
+ "mode": "webapp",
196
+ "files": [
197
+ "README.md",
198
+ "backend/index.ts",
199
+ "db/schema.sql",
200
+ "db/rls.json",
201
+ "frontend/dist/admin.html",
202
+ "frontend/dist/article.html",
203
+ "frontend/dist/blog.js",
204
+ "frontend/dist/blogger.html",
205
+ "frontend/dist/index.html",
206
+ "frontend/dist/login.html",
207
+ "frontend/dist/profile.html",
208
+ "frontend/dist/signup.html",
209
+ "frontend/dist/style.css"
210
+ ],
211
+ "frontend": {
212
+ "root": "frontend/dist",
213
+ "routing": "files",
214
+ "index": "index.html",
215
+ "fallback": null
216
+ },
217
+ "backend": {
218
+ "entrypoint": "backend/index.ts",
219
+ "framework": "deno",
220
+ "pathMode": "strip-app-api-prefix",
221
+ "verifyJwt": false,
222
+ "secrets": [],
223
+ "egressPolicy": "deny",
224
+ "session": "proxy-injected"
225
+ },
226
+ "nextSteps": [
227
+ "Initialize the database BEFORE deploy: run `pxbaas app db-init <name> --dir <appsDir>`. It reads db/schema.sql (DDL + seed) and db/rls.json (RLS registry), shows the full plan, and applies it only after you authorize (--dry-run to preview, --yes for non-interactive). Works in single-tenant (/pg/query) AND multi-tenant (/api/tenant-ddl with your per-tenant service_role key); the CLI never auto-runs DDL.",
228
+ "Requires capabilities.sessionMode=proxy-injected-header.",
229
+ "The BFF forwards to the platform-injected SUPABASE_INTERNAL_URL with SUPABASE_ANON_KEY (edge-runtime MR #30497903); no plaintext key editing is needed."
230
+ ]
231
+ },
232
+ {
233
+ "id": "ssr-shop",
234
+ "description": "React 18 + Hono SSR shop: catalog/detail/search are fully server-rendered from MySQL; cart/checkout/orders hydrate in the browser. Browser-side session (localStorage + Authorization direct to /rest,/auth); order gating enforced by RLS.",
235
+ "entrypoint": "backend/index.ts",
236
+ "mode": "webapp",
237
+ "files": [
238
+ "README.md",
239
+ "backend/index.ts",
240
+ "db/schema.sql",
241
+ "db/rls.json",
242
+ "frontend/dist/index.html"
243
+ ],
244
+ "frontend": {
245
+ "root": "frontend/dist",
246
+ "routing": "files",
247
+ "index": "index.html",
248
+ "fallback": "worker"
249
+ },
250
+ "backend": {
251
+ "entrypoint": "backend/index.ts",
252
+ "framework": "hono",
253
+ "pathMode": "strip-app-api-prefix",
254
+ "verifyJwt": false,
255
+ "secrets": [],
256
+ "egressPolicy": "deny",
257
+ "session": "browser-side"
258
+ },
259
+ "ssrProbePath": "/shop",
260
+ "nextSteps": [
261
+ "Initialize the database BEFORE deploy: run `pxbaas app db-init <name> --dir <appsDir>`. It reads db/schema.sql (DDL + seed) and db/rls.json (RLS: products public-read; orders and order_items owner-gated by buyer_email = jwt.email), shows the full plan, and applies it only after you authorize (--dry-run to preview, --yes for non-interactive). Works in single-tenant (/pg/query) AND multi-tenant (/api/tenant-ddl with your per-tenant service_role key); the CLI never auto-runs DDL.",
262
+ "Create the admin account (admin@shop.demo) via GoTrue signup if the admin whitelist is needed.",
263
+ "Data-plane base and anon key come from the platform-injected SUPABASE_INTERNAL_URL / SUPABASE_ANON_KEY (edge-runtime MR #30497903); no plaintext key editing is needed. Requires the instance to report react/react-dom in capabilities.ssrLibs."
264
+ ]
265
+ },
266
+ {
267
+ "id": "ssr-frameworks",
268
+ "description": "Four-framework SSR showcase (React / Vue / Preact / Solid on Hono) rendering the same UI spec server-side, plus /compare. No data plane and no credentials; heaviest cold start of the set (~60s), so warm the tenant sandbox before publish.",
269
+ "entrypoint": "backend/index.ts",
270
+ "mode": "webapp",
271
+ "files": [
272
+ "README.md",
273
+ "backend/index.ts",
274
+ "frontend/dist/index.html"
275
+ ],
276
+ "frontend": {
277
+ "root": "frontend/dist",
278
+ "routing": "files",
279
+ "index": "index.html",
280
+ "fallback": "worker"
281
+ },
282
+ "backend": {
283
+ "entrypoint": "backend/index.ts",
284
+ "framework": "hono",
285
+ "pathMode": "strip-app-api-prefix",
286
+ "verifyJwt": false,
287
+ "secrets": [],
288
+ "egressPolicy": "deny",
289
+ "session": "none"
290
+ },
291
+ "ssrProbePath": "/react",
292
+ "nextSteps": [
293
+ "No data plane and no credentials are required.",
294
+ "Heaviest cold start of the set (~60s with four SSR renderers): warm the tenant sandbox before publish and retry APP_SSR_PROBE_FAILED 3-5 times.",
295
+ "Requires the instance to report react/react-dom, vue/@vue/server-renderer, preact/preact-render-to-string and solid-js in capabilities.ssrLibs, else deploy is blocked by no-remote-import / ssr-lib-not-allowed."
296
+ ]
297
+ }
298
+ ]
299
+ }
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{APP_NAME}} — About</title>
7
+ <link rel="stylesheet" href="style.css" />
8
+ </head>
9
+ <body>
10
+ <h1>About {{APP_NAME}}</h1>
11
+ <nav class="nav">
12
+ <a href="index.html">Home</a> · <a href="about.html">About</a>
13
+ </nav>
14
+
15
+ <div class="card">
16
+ <p>
17
+ This is a second static page (<code>about.html</code>). Navigating here from
18
+ the home page uses a plain relative link — no client-side router, no
19
+ single-file bundle. Each page is a real file served by path.
20
+ </p>
21
+ <p class="muted">
22
+ Add more pages by dropping new <code>.html</code> files into the app
23
+ directory and listing them under <code>pages</code> in <code>app.json</code>.
24
+ </p>
25
+ </div>
26
+
27
+ <script src="app.js"></script>
28
+ </body>
29
+ </html>
@@ -0,0 +1,42 @@
1
+ // {{APP_NAME}} — shared client script (MPA). Runs in the BROWSER on every page.
2
+ //
3
+ // Guardrails:
4
+ // - Asset links in the HTML are relative; here the API call uses a COMPUTED base
5
+ // (the function directory) + "?action=..." so the request returns through
6
+ // Kong -> proxy -> sandbox on the same /functions/v1/{{SLUG}}/ path and never
7
+ // escapes the prefix.
8
+ // - Defensive element lookups: the same script is included on every page, and
9
+ // not every page has every widget.
10
+ (function () {
11
+ // Directory of the current page, e.g. /functions/v1/{{SLUG}}/
12
+ var base = location.pathname.endsWith("/")
13
+ ? location.pathname
14
+ : location.pathname.replace(/\/[^/]*$/, "/");
15
+
16
+ var urlEl = document.getElementById("url");
17
+ if (urlEl) urlEl.textContent = location.origin + base;
18
+
19
+ var n = 0;
20
+ var countEl = document.getElementById("count");
21
+ var incBtn = document.getElementById("inc");
22
+ if (incBtn) {
23
+ incBtn.addEventListener("click", function () {
24
+ n++;
25
+ if (countEl) countEl.textContent = String(n);
26
+ });
27
+ }
28
+
29
+ var pingBtn = document.getElementById("ping");
30
+ var apiEl = document.getElementById("api");
31
+ if (pingBtn) {
32
+ pingBtn.addEventListener("click", async function () {
33
+ if (apiEl) apiEl.textContent = "loading…";
34
+ try {
35
+ var r = await fetch(base + "?action=time", { headers: { Accept: "application/json" } });
36
+ if (apiEl) apiEl.textContent = JSON.stringify(await r.json(), null, 2);
37
+ } catch (e) {
38
+ if (apiEl) apiEl.textContent = "error: " + e;
39
+ }
40
+ });
41
+ }
42
+ })();
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{APP_NAME}}</title>
7
+ <!-- RELATIVE asset link: resolves to /functions/v1/{{SLUG}}/style.css -->
8
+ <link rel="stylesheet" href="style.css" />
9
+ </head>
10
+ <body>
11
+ <h1>{{APP_NAME}}</h1>
12
+ <nav class="nav">
13
+ <a href="index.html">Home</a> · <a href="about.html">About</a>
14
+ </nav>
15
+
16
+ <p class="muted">
17
+ A multi-page webapp: <code>index.html</code>, <code>about.html</code>,
18
+ <code>style.css</code> and <code>app.js</code> are served as real static files
19
+ by the BaaS proxy, reverse-proxied via Kong <code>/functions/v1/</code>.
20
+ </p>
21
+
22
+ <div class="card">
23
+ <div class="muted">Share URL (opens directly in a browser)</div>
24
+ <code id="url">loading…</code>
25
+ </div>
26
+
27
+ <div class="card">
28
+ <div>① Client-side counter (from <code>app.js</code>)</div>
29
+ <div class="big" id="count">0</div>
30
+ <button id="inc">+1</button>
31
+ </div>
32
+
33
+ <div class="card">
34
+ <div>② Call the worker API (computed base + <code>?action=time</code>)</div>
35
+ <button id="ping">GET ?action=time</button>
36
+ <pre id="api" class="muted">Click to fetch server time</pre>
37
+ </div>
38
+
39
+ <!-- RELATIVE script src: resolves to /functions/v1/{{SLUG}}/app.js -->
40
+ <script src="app.js"></script>
41
+ </body>
42
+ </html>
@@ -0,0 +1,60 @@
1
+ // {{APP_NAME}} — multi-page webapp (MPA) Edge Function worker.
2
+ //
3
+ // Spec: follow the `pxbaas-app-spec` skill — `pxbaas app deploy` lints this app against it.
4
+ //
5
+ // Deploy with: pxbaas app deploy {{SLUG}}
6
+ // Share URL: {endpoint}/functions/v1/{{SLUG}}/ (serves static index.html)
7
+ // {endpoint}/functions/v1/{{SLUG}}/about.html (serves static about.html)
8
+ // {endpoint}/functions/v1/{{SLUG}}/style.css (static asset)
9
+ // Built-in API: {endpoint}/functions/v1/{{SLUG}}/?action=time
10
+ //
11
+ // How an MPA works here (Plan B):
12
+ // - The real static files (index.html / about.html / style.css / app.js) are
13
+ // served DIRECTLY by the BaaS proxy static branch — they never reach this
14
+ // worker. That is why they can be linked by relative path from the pages.
15
+ // - This worker only handles the JSON API (?action=...) and any non-asset path.
16
+ // - app.json declares `"mode": "mpa"` which is what turns the static branch on
17
+ // for this function; without it the proxy routes everything to this worker.
18
+ //
19
+ // Guardrails baked into this template (do NOT break them):
20
+ // - Pages reference assets with RELATIVE links (style.css, app.js, about.html),
21
+ // never root-absolute ("/style.css") which would escape the /functions/v1/ prefix.
22
+ // - API calls use a computed base + "?action=..." so they return through
23
+ // Kong -> proxy -> sandbox on the same path.
24
+ // - CORS headers are set for browser calls; reflected input is JSON-only here.
25
+
26
+ function corsHeaders(): Record<string, string> {
27
+ return {
28
+ "Access-Control-Allow-Origin": "*",
29
+ "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
30
+ "Access-Control-Allow-Headers": "Content-Type, Authorization, apikey, X-Tenant-Id",
31
+ };
32
+ }
33
+
34
+ function json(body: unknown, status = 200): Response {
35
+ return new Response(JSON.stringify(body), {
36
+ status,
37
+ headers: { "Content-Type": "application/json", ...corsHeaders() },
38
+ });
39
+ }
40
+
41
+ Deno.serve((req: Request) => {
42
+ const url = new URL(req.url);
43
+
44
+ if (req.method === "OPTIONS") {
45
+ return new Response(null, { status: 204, headers: corsHeaders() });
46
+ }
47
+
48
+ // Built-in JSON API — extend with your own actions here.
49
+ const action = url.searchParams.get("action");
50
+ if (action === "time") {
51
+ return json({ ok: true, now: new Date().toISOString() });
52
+ }
53
+ if (action) {
54
+ return json({ ok: false, error: `unknown action: ${action}` }, 400);
55
+ }
56
+
57
+ // No ?action: static pages/assets are served by the proxy before reaching here,
58
+ // so anything that lands on the worker is an unknown dynamic path.
59
+ return json({ ok: false, error: "not found" }, 404);
60
+ });
@@ -0,0 +1,42 @@
1
+ /* {{APP_NAME}} — shared stylesheet (MPA). Served as a real static .css file. */
2
+ :root { color-scheme: light dark; }
3
+
4
+ body {
5
+ font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
6
+ max-width: 720px;
7
+ margin: 40px auto;
8
+ padding: 0 20px;
9
+ line-height: 1.6;
10
+ }
11
+
12
+ h1 { margin-bottom: 4px; }
13
+
14
+ .nav { margin: 8px 0 20px; font-size: 15px; }
15
+ .nav a { text-decoration: none; color: #0a7; font-weight: 600; }
16
+ .nav a:hover { text-decoration: underline; }
17
+
18
+ .card {
19
+ border: 1px solid #ddd;
20
+ border-radius: 12px;
21
+ padding: 16px 20px;
22
+ margin: 16px 0;
23
+ }
24
+
25
+ code, pre {
26
+ background: #f4f4f5;
27
+ padding: 2px 6px;
28
+ border-radius: 4px;
29
+ word-break: break-all;
30
+ }
31
+ pre { padding: 12px; overflow: auto; }
32
+
33
+ button {
34
+ font-size: 15px;
35
+ padding: 8px 16px;
36
+ border-radius: 8px;
37
+ border: 1px solid #ccc;
38
+ cursor: pointer;
39
+ }
40
+
41
+ .big { font-size: 32px; font-weight: 700; }
42
+ .muted { color: #888; font-size: 13px; }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{APP_NAME}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="./src/main.tsx"></script>
11
+ </body>
12
+ </html>