@stacksjs/defaults 0.70.206 → 0.70.208

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 (408) hide show
  1. package/TODO.md +21 -0
  2. package/ai/AGENTS.md +79 -0
  3. package/ai/README.md +45 -0
  4. package/ai/claude/launch.json +12 -0
  5. package/ai/skills/stacks-actions/SKILL.md +128 -0
  6. package/ai/skills/stacks-ai/SKILL.md +276 -0
  7. package/ai/skills/stacks-alias/SKILL.md +94 -0
  8. package/ai/skills/stacks-analytics/SKILL.md +91 -0
  9. package/ai/skills/stacks-api/SKILL.md +738 -0
  10. package/ai/skills/stacks-arrays/SKILL.md +277 -0
  11. package/ai/skills/stacks-auth/SKILL.md +422 -0
  12. package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
  13. package/ai/skills/stacks-brandkit/SKILL.md +811 -0
  14. package/ai/skills/stacks-browse/SKILL.md +127 -0
  15. package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
  16. package/ai/skills/stacks-browser/SKILL.md +145 -0
  17. package/ai/skills/stacks-buddy/SKILL.md +676 -0
  18. package/ai/skills/stacks-build/SKILL.md +163 -0
  19. package/ai/skills/stacks-cache/SKILL.md +125 -0
  20. package/ai/skills/stacks-calendar/SKILL.md +113 -0
  21. package/ai/skills/stacks-chat/SKILL.md +371 -0
  22. package/ai/skills/stacks-cli/SKILL.md +112 -0
  23. package/ai/skills/stacks-cloud/SKILL.md +192 -0
  24. package/ai/skills/stacks-cms/SKILL.md +217 -0
  25. package/ai/skills/stacks-collections/SKILL.md +82 -0
  26. package/ai/skills/stacks-commerce/SKILL.md +114 -0
  27. package/ai/skills/stacks-composables/SKILL.md +161 -0
  28. package/ai/skills/stacks-config/SKILL.md +144 -0
  29. package/ai/skills/stacks-configuration/SKILL.md +154 -0
  30. package/ai/skills/stacks-cron/SKILL.md +123 -0
  31. package/ai/skills/stacks-crosswind/SKILL.md +190 -0
  32. package/ai/skills/stacks-dashboard/SKILL.md +173 -0
  33. package/ai/skills/stacks-database/SKILL.md +286 -0
  34. package/ai/skills/stacks-datetime/SKILL.md +269 -0
  35. package/ai/skills/stacks-dependencies/SKILL.md +111 -0
  36. package/ai/skills/stacks-deploy/SKILL.md +102 -0
  37. package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
  38. package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
  39. package/ai/skills/stacks-design-output/SKILL.md +55 -0
  40. package/ai/skills/stacks-design-soft/SKILL.md +156 -0
  41. package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
  42. package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
  43. package/ai/skills/stacks-desktop/SKILL.md +78 -0
  44. package/ai/skills/stacks-development/SKILL.md +298 -0
  45. package/ai/skills/stacks-dns/SKILL.md +149 -0
  46. package/ai/skills/stacks-docs/SKILL.md +109 -0
  47. package/ai/skills/stacks-email/SKILL.md +236 -0
  48. package/ai/skills/stacks-enums/SKILL.md +100 -0
  49. package/ai/skills/stacks-env/SKILL.md +181 -0
  50. package/ai/skills/stacks-error-handling/SKILL.md +137 -0
  51. package/ai/skills/stacks-events/SKILL.md +228 -0
  52. package/ai/skills/stacks-faker/SKILL.md +158 -0
  53. package/ai/skills/stacks-git/SKILL.md +158 -0
  54. package/ai/skills/stacks-guard/SKILL.md +98 -0
  55. package/ai/skills/stacks-health/SKILL.md +75 -0
  56. package/ai/skills/stacks-http/SKILL.md +316 -0
  57. package/ai/skills/stacks-i18n/SKILL.md +198 -0
  58. package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
  59. package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
  60. package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
  61. package/ai/skills/stacks-investigate/SKILL.md +119 -0
  62. package/ai/skills/stacks-jobs/SKILL.md +136 -0
  63. package/ai/skills/stacks-lint/SKILL.md +184 -0
  64. package/ai/skills/stacks-listeners/SKILL.md +99 -0
  65. package/ai/skills/stacks-logging/SKILL.md +78 -0
  66. package/ai/skills/stacks-mail/SKILL.md +120 -0
  67. package/ai/skills/stacks-middleware/SKILL.md +249 -0
  68. package/ai/skills/stacks-migrations/SKILL.md +105 -0
  69. package/ai/skills/stacks-models/SKILL.md +267 -0
  70. package/ai/skills/stacks-new-feature/SKILL.md +206 -0
  71. package/ai/skills/stacks-notifications/SKILL.md +210 -0
  72. package/ai/skills/stacks-objects/SKILL.md +205 -0
  73. package/ai/skills/stacks-office-hours/SKILL.md +134 -0
  74. package/ai/skills/stacks-orm/SKILL.md +342 -0
  75. package/ai/skills/stacks-path/SKILL.md +118 -0
  76. package/ai/skills/stacks-payments/SKILL.md +373 -0
  77. package/ai/skills/stacks-plan-review/SKILL.md +152 -0
  78. package/ai/skills/stacks-plugins/SKILL.md +149 -0
  79. package/ai/skills/stacks-push/SKILL.md +376 -0
  80. package/ai/skills/stacks-query-builder/SKILL.md +128 -0
  81. package/ai/skills/stacks-queue/SKILL.md +559 -0
  82. package/ai/skills/stacks-realtime/SKILL.md +442 -0
  83. package/ai/skills/stacks-redesign/SKILL.md +182 -0
  84. package/ai/skills/stacks-registry/SKILL.md +58 -0
  85. package/ai/skills/stacks-repl/SKILL.md +80 -0
  86. package/ai/skills/stacks-retro/SKILL.md +122 -0
  87. package/ai/skills/stacks-review/SKILL.md +135 -0
  88. package/ai/skills/stacks-router/SKILL.md +231 -0
  89. package/ai/skills/stacks-routes/SKILL.md +105 -0
  90. package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
  91. package/ai/skills/stacks-scheduler/SKILL.md +363 -0
  92. package/ai/skills/stacks-search-engine/SKILL.md +112 -0
  93. package/ai/skills/stacks-security/SKILL.md +129 -0
  94. package/ai/skills/stacks-security-audit/SKILL.md +128 -0
  95. package/ai/skills/stacks-server/SKILL.md +458 -0
  96. package/ai/skills/stacks-shell/SKILL.md +62 -0
  97. package/ai/skills/stacks-slug/SKILL.md +87 -0
  98. package/ai/skills/stacks-sms/SKILL.md +385 -0
  99. package/ai/skills/stacks-socials/SKILL.md +303 -0
  100. package/ai/skills/stacks-storage/SKILL.md +576 -0
  101. package/ai/skills/stacks-strings/SKILL.md +416 -0
  102. package/ai/skills/stacks-stx/SKILL.md +176 -0
  103. package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
  104. package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
  105. package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
  106. package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
  107. package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
  108. package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
  109. package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
  110. package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
  111. package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
  112. package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
  113. package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
  114. package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
  115. package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
  116. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
  117. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
  118. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
  119. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
  120. package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
  121. package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
  122. package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
  123. package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
  124. package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
  125. package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
  126. package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
  127. package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
  128. package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
  129. package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
  130. package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
  131. package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
  132. package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
  133. package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
  134. package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
  135. package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
  136. package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
  137. package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
  138. package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
  139. package/ai/skills/stacks-testing/SKILL.md +129 -0
  140. package/ai/skills/stacks-tunnel/SKILL.md +125 -0
  141. package/ai/skills/stacks-types/SKILL.md +178 -0
  142. package/ai/skills/stacks-ui/SKILL.md +246 -0
  143. package/ai/skills/stacks-utils/SKILL.md +444 -0
  144. package/ai/skills/stacks-validation/SKILL.md +371 -0
  145. package/ai/skills/stacks-whois/SKILL.md +315 -0
  146. package/assets/world-map-data.ts +121 -0
  147. package/bootstrap.ts +114 -0
  148. package/docs/api-examples.md +46 -0
  149. package/docs/index.md +24 -0
  150. package/docs/markdown-examples.md +87 -0
  151. package/functions/analytics.ts +97 -0
  152. package/functions/api.ts +143 -0
  153. package/functions/auth.ts +208 -0
  154. package/functions/billing/payments.ts +149 -0
  155. package/functions/blog.ts +120 -0
  156. package/functions/cms/categorizables.ts +107 -0
  157. package/functions/cms/pages.ts +108 -0
  158. package/functions/cms/posts.ts +100 -0
  159. package/functions/cms/taggables.ts +102 -0
  160. package/functions/commerce/coupons.ts +128 -0
  161. package/functions/commerce/customers.ts +128 -0
  162. package/functions/commerce/gift-cards.ts +119 -0
  163. package/functions/commerce/orders.ts +112 -0
  164. package/functions/commerce/payments.ts +119 -0
  165. package/functions/commerce/products/categories.ts +123 -0
  166. package/functions/commerce/products/manufacturers.ts +123 -0
  167. package/functions/commerce/products/products.ts +123 -0
  168. package/functions/commerce/products/reviews.ts +123 -0
  169. package/functions/commerce/products/units.ts +123 -0
  170. package/functions/commerce/products/variants.ts +123 -0
  171. package/functions/commerce/shippings/delivery-routes.ts +123 -0
  172. package/functions/commerce/shippings/digital-deliveries.ts +119 -0
  173. package/functions/commerce/shippings/drivers.ts +123 -0
  174. package/functions/commerce/shippings/license-keys.ts +123 -0
  175. package/functions/commerce/shippings/shipping-methods.ts +123 -0
  176. package/functions/commerce/shippings/shipping-rates.ts +119 -0
  177. package/functions/commerce/shippings/shipping-zones.ts +119 -0
  178. package/functions/commerce/taxes.ts +119 -0
  179. package/functions/commerce/waitlist/products.ts +123 -0
  180. package/functions/commerce/waitlist/restaurants.ts +123 -0
  181. package/functions/craft.ts +107 -0
  182. package/functions/dashboard.ts +153 -0
  183. package/functions/inbox.ts +95 -0
  184. package/functions/jobs.ts +86 -0
  185. package/functions/monitoring/errors.ts +295 -0
  186. package/functions/queue.ts +111 -0
  187. package/functions/realtime/websockets.ts +96 -0
  188. package/functions/realtime.ts +52 -0
  189. package/functions/releases.ts +49 -0
  190. package/functions/search.ts +126 -0
  191. package/functions/toasts.ts +95 -0
  192. package/functions/uploads.ts +216 -0
  193. package/ide/.gitignore +4 -0
  194. package/ide/cursor/rules/auto-imports.mdc +574 -0
  195. package/ide/cursor/rules/code-style.mdc +12 -0
  196. package/ide/cursor/rules/documentation.mdc +9 -0
  197. package/ide/cursor/rules/error-handling-validation.mdc +11 -0
  198. package/ide/cursor/rules/key-conventions.mdc +11 -0
  199. package/ide/cursor/rules/project-structure.mdc +169 -0
  200. package/ide/cursor/rules/readme.mdc +318 -0
  201. package/ide/cursor/rules/syntax-formatting.mdc +9 -0
  202. package/ide/cursor/rules/testing.mdc +10 -0
  203. package/ide/cursor/rules/typescript.mdc +9 -0
  204. package/ide/cursor/rules/ui-styling.mdc +0 -0
  205. package/ide/dictionary.txt +397 -0
  206. package/ide/jetbrains/.fleet/settings.json +4 -0
  207. package/ide/jetbrains/.idea/.gitignore +5 -0
  208. package/ide/jetbrains/.idea/.name +1 -0
  209. package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
  210. package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
  211. package/ide/jetbrains/.idea/modules.xml +8 -0
  212. package/ide/jetbrains/.idea/stacks.iml +22 -0
  213. package/ide/jetbrains/.idea/vcs.xml +6 -0
  214. package/ide/jetbrains/.idea/webResources.xml +14 -0
  215. package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
  216. package/ide/jetbrains/installed.txt +4 -0
  217. package/ide/jetbrains/options/github-copilot.xml +5 -0
  218. package/ide/jetbrains/options/nodejs.xml +7 -0
  219. package/ide/jetbrains/options/templates.xml +124 -0
  220. package/ide/jetbrains/templates/JavaScript.xml +6 -0
  221. package/ide/jetbrains/templates/Stacks.xml +8 -0
  222. package/ide/vscode/.vscode/README.md +23 -0
  223. package/ide/vscode/.vscode/extensions.json +5 -0
  224. package/ide/vscode/.vscode/settings.json +176 -0
  225. package/ide/vscode/.vscode/stacks.code-snippets +181 -0
  226. package/ide/vscode/LICENSE.md +21 -0
  227. package/ide/vscode/README.md +36 -0
  228. package/ide/vscode/logo.png +0 -0
  229. package/ide/vscode/package.json +79 -0
  230. package/ide/zed/.zed/settings.json +139 -0
  231. package/lang/README.md +28 -0
  232. package/lang/de.yml +14 -0
  233. package/lang/en.yml +15 -0
  234. package/package.json +19 -3
  235. package/project/bootstrap +161 -0
  236. package/project/buddy +175 -0
  237. package/project/storage/framework/tsconfig.app.json +50 -0
  238. package/project/storage/framework/tsconfig.base.json +58 -0
  239. package/routes/core.ts +78 -0
  240. package/routes/dashboard-api.ts +233 -0
  241. package/routes/dashboard.ts +739 -0
  242. package/routes/email.ts +129 -0
  243. package/stores/[name].stx +16 -0
  244. package/stores/git.ts +71 -0
  245. package/stores/payment.ts +474 -0
  246. package/stores/queue.ts +43 -0
  247. package/stores/user.ts +29 -0
  248. package/stx-components-plugin.ts +25 -0
  249. package/styles/design-tokens.css +597 -0
  250. package/types/dashboard.ts +70 -0
  251. package/types/defaults.ts +438 -0
  252. package/vcs/github/CODE_OF_CONDUCT.md +83 -0
  253. package/vcs/github/CONTRIBUTING.md +187 -0
  254. package/vcs/github/EXPLANATIONS.md +41 -0
  255. package/vcs/github/FUNDING.yml +1 -0
  256. package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  257. package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
  258. package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  259. package/vcs/github/SECURITY.md +70 -0
  260. package/vcs/github/renovate.json +5 -0
  261. package/vcs/github/stale.yml +14 -0
  262. package/vcs/github/workflows/README.md +16 -0
  263. package/vcs/github/workflows/ci.yml +114 -0
  264. package/vcs/github/workflows/export-size.yml +25 -0
  265. package/vcs/github/workflows/labeler.yml +13 -0
  266. package/vcs/github/workflows/release.yml +219 -0
  267. package/views/[...all].stx +8 -0
  268. package/views/about.md +3 -0
  269. package/views/auth/login.stx +1 -0
  270. package/views/auth/signup.stx +85 -0
  271. package/views/dashboard/.discovered-models.json +542 -0
  272. package/views/dashboard/AUDIT.md +904 -0
  273. package/views/dashboard/[...all].stx +89 -0
  274. package/views/dashboard/access-tokens/index.stx +177 -0
  275. package/views/dashboard/actions/index.stx +129 -0
  276. package/views/dashboard/analytics/blog/index.stx +356 -0
  277. package/views/dashboard/analytics/browsers/index.stx +263 -0
  278. package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
  279. package/views/dashboard/analytics/commerce/web/index.stx +379 -0
  280. package/views/dashboard/analytics/countries/index.stx +289 -0
  281. package/views/dashboard/analytics/devices/index.stx +305 -0
  282. package/views/dashboard/analytics/events/index.stx +536 -0
  283. package/views/dashboard/analytics/index.stx +88 -0
  284. package/views/dashboard/analytics/marketing/index.stx +315 -0
  285. package/views/dashboard/analytics/pages/index.stx +271 -0
  286. package/views/dashboard/analytics/referrers/index.stx +319 -0
  287. package/views/dashboard/analytics/web/index.stx +356 -0
  288. package/views/dashboard/buddy/index.stx +198 -0
  289. package/views/dashboard/ci/index.stx +462 -0
  290. package/views/dashboard/cloud/index.stx +452 -0
  291. package/views/dashboard/commands/index.stx +295 -0
  292. package/views/dashboard/commerce/categories/index.stx +406 -0
  293. package/views/dashboard/commerce/coupons/index.stx +485 -0
  294. package/views/dashboard/commerce/customers/index.stx +410 -0
  295. package/views/dashboard/commerce/dashboard/index.stx +287 -0
  296. package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
  297. package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
  298. package/views/dashboard/commerce/delivery/drivers.stx +397 -0
  299. package/views/dashboard/commerce/delivery/index.stx +18 -0
  300. package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
  301. package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
  302. package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
  303. package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
  304. package/views/dashboard/commerce/delivery/tabs.ts +25 -0
  305. package/views/dashboard/commerce/gift-cards/index.stx +561 -0
  306. package/views/dashboard/commerce/manufacturers/index.stx +308 -0
  307. package/views/dashboard/commerce/orders/index.stx +247 -0
  308. package/views/dashboard/commerce/payments/index.stx +535 -0
  309. package/views/dashboard/commerce/pos/index.stx +653 -0
  310. package/views/dashboard/commerce/printers/devices/index.stx +273 -0
  311. package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
  312. package/views/dashboard/commerce/products/detail.stx +563 -0
  313. package/views/dashboard/commerce/products/index.stx +370 -0
  314. package/views/dashboard/commerce/reviews/index.stx +656 -0
  315. package/views/dashboard/commerce/reviews/index.ts +0 -0
  316. package/views/dashboard/commerce/taxes/index.stx +377 -0
  317. package/views/dashboard/commerce/units/index.stx +317 -0
  318. package/views/dashboard/commerce/variants/index.stx +319 -0
  319. package/views/dashboard/commerce/waitlist/products.stx +942 -0
  320. package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
  321. package/views/dashboard/components/index.stx +330 -0
  322. package/views/dashboard/composables/index.ts +19 -0
  323. package/views/dashboard/composables/useChart.ts +77 -0
  324. package/views/dashboard/composables/useNavigation.ts +99 -0
  325. package/views/dashboard/composables/useRole.ts +58 -0
  326. package/views/dashboard/composables/useTheme.ts +74 -0
  327. package/views/dashboard/content/authors/index.stx +171 -0
  328. package/views/dashboard/content/blog/index.stx +493 -0
  329. package/views/dashboard/content/categories/index.stx +169 -0
  330. package/views/dashboard/content/comments/index.stx +189 -0
  331. package/views/dashboard/content/dashboard.stx +383 -0
  332. package/views/dashboard/content/files/index.stx +706 -0
  333. package/views/dashboard/content/pages/index.stx +174 -0
  334. package/views/dashboard/content/posts/index.stx +269 -0
  335. package/views/dashboard/content/seo/index.stx +240 -0
  336. package/views/dashboard/content/tags/index.stx +167 -0
  337. package/views/dashboard/data/activity/index.stx +261 -0
  338. package/views/dashboard/data/dashboard/index.stx +116 -0
  339. package/views/dashboard/data/subscribers.stx +270 -0
  340. package/views/dashboard/data/teams.stx +275 -0
  341. package/views/dashboard/data/users.stx +279 -0
  342. package/views/dashboard/dependencies/index.stx +178 -0
  343. package/views/dashboard/deployments/[id].stx +234 -0
  344. package/views/dashboard/deployments/index.stx +9 -0
  345. package/views/dashboard/dns/index.stx +163 -0
  346. package/views/dashboard/environment/index.stx +283 -0
  347. package/views/dashboard/errors/index.stx +274 -0
  348. package/views/dashboard/forgot-password.stx +57 -0
  349. package/views/dashboard/functions/index.stx +159 -0
  350. package/views/dashboard/health/index.stx +248 -0
  351. package/views/dashboard/inbox/activity.stx +350 -0
  352. package/views/dashboard/inbox/index.stx +452 -0
  353. package/views/dashboard/inbox/settings.stx +290 -0
  354. package/views/dashboard/index.stx +252 -0
  355. package/views/dashboard/insights/index.stx +529 -0
  356. package/views/dashboard/jobs/[id].stx +430 -0
  357. package/views/dashboard/jobs/history.stx +222 -0
  358. package/views/dashboard/jobs/index.stx +214 -0
  359. package/views/dashboard/kanban/[id].stx +899 -0
  360. package/views/dashboard/kanban/index.stx +260 -0
  361. package/views/dashboard/layouts/default.stx +565 -0
  362. package/views/dashboard/layouts/guest.stx +10 -0
  363. package/views/dashboard/login.stx +48 -0
  364. package/views/dashboard/logs/index.stx +540 -0
  365. package/views/dashboard/mailboxes/index.stx +149 -0
  366. package/views/dashboard/management/permissions/index.stx +490 -0
  367. package/views/dashboard/marketing/campaigns/index.stx +604 -0
  368. package/views/dashboard/marketing/lists/index.stx +514 -0
  369. package/views/dashboard/marketing/reviews/index.stx +475 -0
  370. package/views/dashboard/marketing/social-posts/index.stx +560 -0
  371. package/views/dashboard/models/[model].stx +195 -0
  372. package/views/dashboard/models/index.stx +159 -0
  373. package/views/dashboard/monitoring/errors/index.stx +415 -0
  374. package/views/dashboard/notifications/dashboard.stx +383 -0
  375. package/views/dashboard/notifications/email.stx +336 -0
  376. package/views/dashboard/notifications/history.stx +373 -0
  377. package/views/dashboard/notifications/sms.stx +332 -0
  378. package/views/dashboard/packages/index.stx +195 -0
  379. package/views/dashboard/queries/[id].stx +381 -0
  380. package/views/dashboard/queries/history.stx +227 -0
  381. package/views/dashboard/queries/index.stx +335 -0
  382. package/views/dashboard/queries/slow.stx +318 -0
  383. package/views/dashboard/queue/index.stx +427 -0
  384. package/views/dashboard/realtime/index.stx +429 -0
  385. package/views/dashboard/register.stx +46 -0
  386. package/views/dashboard/releases/index.stx +389 -0
  387. package/views/dashboard/requests/index.stx +462 -0
  388. package/views/dashboard/serverless/index.stx +475 -0
  389. package/views/dashboard/servers/[id].stx +299 -0
  390. package/views/dashboard/servers/index.stx +483 -0
  391. package/views/dashboard/settings/billing.stx +50 -0
  392. package/views/dashboard/settings/index.stx +256 -0
  393. package/views/dashboard/settings/mail.stx +252 -0
  394. package/views/dashboard/stores/auth.ts +123 -0
  395. package/views/dashboard/stores/ci.ts +342 -0
  396. package/views/dashboard/stores/index.ts +129 -0
  397. package/views/dashboard/stores/kanban.ts +723 -0
  398. package/views/dashboard/stores/rbac.ts +350 -0
  399. package/views/dashboard/stx.config.ts +34 -0
  400. package/views/dashboard/teams/[id].stx +170 -0
  401. package/views/forum/category.stx +92 -0
  402. package/views/forum/index.stx +209 -0
  403. package/views/forum/new-topic.stx +113 -0
  404. package/views/forum/profile.stx +1 -0
  405. package/views/forum/topic.stx +143 -0
  406. package/views/hello-world/[name].stx +47 -0
  407. package/views/index.stx +21 -0
  408. package/views/system-tray/index.stx +147 -0
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: stacks-plugins
3
+ description: Use when working with the Stacks preload chain and Bun plugins — the env plugin, the framework preloader, how auto-imports get injected into globalThis, why a command does or does not see framework globals, the bun-plugin-stx static-serve plugin, or writing a Bun plugin. Covers bunfig.toml preload and storage/framework/defaults/resources/plugins/preloader.ts.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Stacks Plugins and the Preload Chain
10
+
11
+ Stacks has **no `@stacksjs/plugins` package**. "Plugins" here means Bun's native
12
+ plugin API plus the two modules `bunfig.toml` preloads before any Stacks code
13
+ runs. If you are chasing "why is `User` undefined in this command" or "why did
14
+ `.env` not decrypt", this is the skill.
15
+
16
+ ## Key Paths
17
+
18
+ - Preload declaration: `bunfig.toml` (`preload`, at the root and under `[test]`)
19
+ - Env plugin: `storage/framework/core/env/plugin.ts`
20
+ - Framework preloader: `storage/framework/defaults/resources/plugins/preloader.ts`
21
+ - Static-serve plugin: `bunfig.toml`, `[serve.static] plugins = ["bun-plugin-stx"]`
22
+
23
+ ## The preload chain
24
+
25
+ `bunfig.toml` preloads two modules, **in this order**:
26
+
27
+ ```toml
28
+ preload = [
29
+ "./storage/framework/core/env/plugin.ts",
30
+ "./storage/framework/defaults/resources/plugins/preloader.ts",
31
+ ]
32
+ ```
33
+
34
+ 1. **Env plugin** loads `.env` and decrypts dotenvx-style encrypted values, so
35
+ everything downstream reads plaintext from `process.env`.
36
+ 2. **Preloader** loads env files for the resolved environment, then injects the
37
+ framework's server auto-imports into `globalThis`.
38
+
39
+ Order is load-bearing: the preloader reads decrypted secrets, so it has to run
40
+ second.
41
+
42
+ Tests preload a different pair - the env plugin and `tests/setup.ts` - so the
43
+ suite gets production env semantics without the auto-import graph.
44
+
45
+ ## What the preloader does
46
+
47
+ ### 1. Resolves the environment
48
+
49
+ Before loading any `.env` file it works out `APP_ENV`, because that decides
50
+ *which* file gets decrypted:
51
+
52
+ - `deploy staging` and `deploy --staging` both resolve to `staging`. Both forms
53
+ are handled; CI uses the flag form.
54
+ - `cloud:remove`, `cloud:destroy`, `cloud:cleanup`, `undeploy` force `production`.
55
+ - Bare `deploy` defaults to `production`.
56
+
57
+ ### 2. Loads and decrypts env files
58
+
59
+ Gated on **`isRepl` / `isPostinstall` only** - never on the fast-command list
60
+ below. Fast commands (`migrate`, `build`, `seed`, ...) genuinely need decrypted
61
+ config; gating them here caused stacksjs/stacks#2048, where an encrypted
62
+ `.env.<env>` silently never decrypted even with the key present.
63
+
64
+ Postinstall skips because `@stacksjs/env` may not be linked yet mid-install.
65
+
66
+ ### 3. Injects auto-imports into `globalThis`
67
+
68
+ Loads ~24 framework packages plus everything in `app/Jobs/` and
69
+ `resources/functions/`, assigning every named export onto `globalThis`. That is
70
+ why `await User.find(1)` and `response.json(...)` work in an action with no
71
+ import statement. See `stacks-auto-imports` for the full manifest.
72
+
73
+ A `protectedGlobals` set guards the runtime: `process`, `fetch`, `Promise`,
74
+ `Bun`, `console` and friends are never overwritten, whatever a package exports.
75
+
76
+ ## The fast-command skip (the usual gotcha)
77
+
78
+ Auto-import injection is **skipped** when the first CLI argument matches:
79
+
80
+ ```
81
+ dev build test lint migrate fresh seed generate make
82
+ key:generate scaffold:crud version help --version -v --help -h
83
+ ```
84
+
85
+ Prefix matches count, so `generate:migrations` skips along with `generate`.
86
+
87
+ Two reasons: cold-start speed, and correctness. Codegen commands must not pull
88
+ the router and ORM graph in before `bun-query-builder` can diff schemas - a
89
+ broken `@stacksjs/bun-router` install used to make `generate:migrations` exit 1
90
+ with no output at all, because the preloader died loading `@stacksjs/router`.
91
+
92
+ **Consequence:** inside those commands, framework globals do not exist. Import
93
+ what you need explicitly.
94
+
95
+ The REPL skips too (`!process.argv[1]`), as does anything running under
96
+ `npm_lifecycle_event === 'postinstall'`.
97
+
98
+ ### Opting back in
99
+
100
+ The preloader exports `loadAutoImports()` so a server entrypoint can pull the
101
+ graph in deliberately:
102
+
103
+ ```ts
104
+ const { loadAutoImports } = await import('../../../defaults/resources/plugins/preloader.ts')
105
+ await loadAutoImports()
106
+ ```
107
+
108
+ `dev/api.ts` does exactly this. Bun consumes `--watch`, so a directly-run server
109
+ script sees an empty `argv.slice(2)` and would otherwise be indistinguishable
110
+ from a bare invocation.
111
+
112
+ ## Writing a Bun plugin
113
+
114
+ Use Bun's native API directly - there is no framework wrapper to import:
115
+
116
+ ```ts
117
+ import { plugin } from 'bun'
118
+
119
+ plugin({
120
+ name: 'my-loader',
121
+ setup(build) {
122
+ build.onLoad({ filter: /\.custom$/ }, async (args) => {
123
+ const contents = await Bun.file(args.path).text()
124
+ return { contents: transform(contents), loader: 'ts' }
125
+ })
126
+ },
127
+ })
128
+ ```
129
+
130
+ Register it by adding the module to `preload` in `bunfig.toml`. A plugin only
131
+ affects the process that preloaded it.
132
+
133
+ ## Gotchas
134
+
135
+ - **No `@stacksjs/plugins` package.** Import `plugin` from `bun`.
136
+ - **Preload order matters.** Env decryption has to precede the preloader.
137
+ - **Fast commands have no globals.** If a `make:*` or `generate:*` command needs
138
+ a framework symbol, import it - do not rely on auto-imports.
139
+ - **`bun-plugin-stx` is a static-serve plugin**, wired through
140
+ `[serve.static] plugins` in `bunfig.toml`. The preloader's own
141
+ `import 'bun-plugin-stx'` line is commented out; stx compilation in the dev
142
+ server runs through the stx package, not that import.
143
+ - **Preloader failures are silent per package.** Each import sits in its own
144
+ `try {} catch {}`, so a package that fails to build leaves its globals
145
+ undefined instead of crashing the process. A mysteriously undefined global is
146
+ usually an unbuilt package - check `storage/framework/core/<pkg>/dist`.
147
+ - **Adding a global?** Export it from a package already in the preloader's list,
148
+ or from `resources/functions/`, then run `buddy generate --types` so the
149
+ declarations match the runtime.
@@ -0,0 +1,376 @@
1
+ ---
2
+ name: stacks-push
3
+ description: Use when implementing push notifications in Stacks — sending via Expo Push Service or Firebase Cloud Messaging (FCM legacy and v1 APIs), configuring push drivers, batch sending, multicast, topic subscriptions, push notification payloads, token validation, or receipt checking. Covers @stacksjs/push.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Stacks Push Notifications
10
+
11
+ Push notification support with Expo Push Service and FCM (Firebase Cloud Messaging) drivers. FCM supports both the legacy server key API and the v1 service account API.
12
+
13
+ ## Key Paths
14
+ - Core package: `storage/framework/core/push/src/`
15
+ - Types: `storage/framework/core/types/src/push.ts`
16
+
17
+ ## Source Files
18
+ ```
19
+ push/src/
20
+ ├── index.ts # send(), configureFCM(), PushNotification type
21
+ └── drivers/
22
+ ├── index.ts # re-exports expo and fcm
23
+ ├── expo.ts # Expo Push Service driver
24
+ └── fcm.ts # FCM legacy + v1 API driver
25
+ ```
26
+
27
+ ## Main send() Function
28
+
29
+ ```typescript
30
+ async function send(
31
+ to: string | string[],
32
+ notification: PushNotification,
33
+ options?: SendOptions,
34
+ ): Promise<PushResult>
35
+ ```
36
+
37
+ Routes to the appropriate driver based on `options.driver` (default: `'expo'`).
38
+
39
+ - For **Expo**: Passes the notification directly to `expo.send()` with all fields mapped.
40
+ - For **FCM** with single token: Calls `fcm.send()` with notification mapped to `{ to, notification: { title, body }, data, priority }`.
41
+ - For **FCM** with multiple tokens: Calls `fcm.sendMulticast()` and returns an aggregated result with success count.
42
+ - FCM priority mapping: `'default'` is converted to `'normal'`; `'high'` and `'normal'` pass through.
43
+
44
+ ## PushNotification Interface (index.ts)
45
+
46
+ ```typescript
47
+ interface PushNotification {
48
+ title?: string
49
+ body: string // required
50
+ data?: Record<string, any>
51
+ badge?: number
52
+ sound?: 'default' | null
53
+ priority?: 'high' | 'normal' | 'default'
54
+ }
55
+ ```
56
+
57
+ ## PushResult Interface (from @stacksjs/types)
58
+
59
+ ```typescript
60
+ interface PushResult {
61
+ success: boolean
62
+ provider: string // 'expo' | 'fcm'
63
+ message: string
64
+ messageId?: string
65
+ data?: Record<string, any>
66
+ }
67
+ ```
68
+
69
+ ## Types
70
+
71
+ ```typescript
72
+ type PushDriver = 'expo' | 'fcm'
73
+
74
+ interface SendOptions {
75
+ driver?: PushDriver // default: 'expo'
76
+ }
77
+ ```
78
+
79
+ ## Expo Push Driver (expo.ts)
80
+
81
+ ### ExpoPushMessage
82
+ ```typescript
83
+ interface ExpoPushMessage {
84
+ to: string | string[]
85
+ title?: string
86
+ body: string
87
+ data?: Record<string, any>
88
+ sound?: 'default' | null
89
+ badge?: number
90
+ channelId?: string // Android notification channel
91
+ priority?: 'default' | 'normal' | 'high'
92
+ ttl?: number // time-to-live in seconds
93
+ }
94
+ ```
95
+
96
+ ### ExpoPushTicket
97
+ ```typescript
98
+ interface ExpoPushTicket {
99
+ id?: string
100
+ status: 'ok' | 'error'
101
+ message?: string
102
+ details?: {
103
+ error?: 'DeviceNotRegistered' | 'MessageTooBig' | 'MessageRateExceeded' | 'InvalidCredentials'
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### ExpoPushReceipt
109
+ ```typescript
110
+ interface ExpoPushReceipt {
111
+ status: 'ok' | 'error'
112
+ message?: string
113
+ details?: { error?: string }
114
+ }
115
+ ```
116
+
117
+ ### Functions
118
+
119
+ #### send()
120
+ ```typescript
121
+ async function send(message: ExpoPushMessage): Promise<PushResult>
122
+ ```
123
+
124
+ - Endpoint: `https://exp.host/--/api/v2/push/send`
125
+ - Validates tokens with `isExpoPushToken()` before sending
126
+ - Filters out invalid tokens and warns via `log.warn()`
127
+ - Returns early with failure if no valid tokens remain
128
+ - Creates one payload entry per token (fans out `to` array into individual messages)
129
+ - Default `sound: 'default'`, default `priority: 'high'`
130
+ - Returns `PushResult` with `data: { tickets }` containing the full ticket array
131
+ - `success` is `true` only if zero tickets have `status: 'error'`
132
+ - `messageId` is the first ticket's `id` (if any)
133
+
134
+ #### isExpoPushToken()
135
+ ```typescript
136
+ function isExpoPushToken(token: string): boolean
137
+ ```
138
+ Validates token format: matches `Expo(nent)?PushToken[...]` pattern OR alphanumeric with hyphens/underscores.
139
+
140
+ #### getReceipts()
141
+ ```typescript
142
+ async function getReceipts(ticketIds: string[]): Promise<Record<string, ExpoPushReceipt>>
143
+ ```
144
+ Endpoint: `https://exp.host/--/api/v2/push/getReceipts`. Checks delivery status for previously sent notifications.
145
+
146
+ #### sendBatch()
147
+ ```typescript
148
+ async function sendBatch(messages: ExpoPushMessage[], chunkSize?: number): Promise<PushResult[]>
149
+ ```
150
+ Sends multiple messages in chunks (default chunk size: 100, per Expo's recommendation). Processes chunks sequentially, messages within each chunk in parallel via `Promise.all`.
151
+
152
+ ### Exports
153
+ - `send`, `sendBatch`, `getReceipts`, `isExpoPushToken` functions
154
+ - `Send` alias for `send`
155
+
156
+ ## FCM Driver (fcm.ts)
157
+
158
+ Supports two APIs:
159
+ 1. **Legacy API** (`https://fcm.googleapis.com/fcm/send`) -- uses server key
160
+ 2. **v1 API** (`https://fcm.googleapis.com/v1/projects/{projectId}/messages:send`) -- uses service account with OAuth2 JWT
161
+
162
+ ### FCMConfig
163
+ ```typescript
164
+ interface FCMConfig {
165
+ serverKey?: string // for legacy API
166
+ projectId?: string // for v1 API
167
+ serviceAccount?: {
168
+ clientEmail: string
169
+ privateKey: string // PEM format
170
+ }
171
+ }
172
+ ```
173
+
174
+ ### FCMMessage
175
+ ```typescript
176
+ interface FCMMessage {
177
+ to?: string // single device token
178
+ registrationIds?: string[] // multiple device tokens (legacy only)
179
+ topic?: string // topic name (auto-prefixed with /topics/)
180
+ condition?: string // topic condition expression
181
+ notification?: {
182
+ title: string
183
+ body: string
184
+ icon?: string
185
+ image?: string
186
+ sound?: string
187
+ badge?: string
188
+ clickAction?: string
189
+ tag?: string
190
+ }
191
+ data?: Record<string, string> // NOTE: values must be strings for FCM
192
+ priority?: 'high' | 'normal'
193
+ ttl?: number
194
+ collapseKey?: string
195
+ }
196
+ ```
197
+
198
+ ### FCMResponse (legacy API)
199
+ ```typescript
200
+ interface FCMResponse {
201
+ multicastId?: number
202
+ success: number
203
+ failure: number
204
+ results?: Array<{
205
+ messageId?: string
206
+ error?: string
207
+ }>
208
+ }
209
+ ```
210
+
211
+ ### Functions
212
+
213
+ #### configure()
214
+ ```typescript
215
+ function configure(options: FCMConfig): void
216
+ ```
217
+ Sets module-level config. Called by `configureFCM()` from the main index.
218
+
219
+ #### send()
220
+ ```typescript
221
+ async function send(message: FCMMessage): Promise<PushResult>
222
+ ```
223
+ If `serviceAccount` and `projectId` are configured, uses the v1 API. Otherwise falls back to `sendLegacy()`.
224
+
225
+ **v1 API flow:**
226
+ 1. Generates JWT with RS256 signing using the service account private key
227
+ 2. Exchanges JWT for OAuth2 access token at `https://oauth2.googleapis.com/token`
228
+ 3. Sends to `https://fcm.googleapis.com/v1/projects/{projectId}/messages:send`
229
+ 4. Includes Android priority settings and APNS headers (`apns-priority: 10` for high, `5` for normal)
230
+ 5. Supports `to` (token), `topic`, or `condition` targeting
231
+
232
+ **JWT generation details:**
233
+ - Scope: `https://www.googleapis.com/auth/firebase.messaging`
234
+ - Algorithm: RS256 (RSASSA-PKCS1-v1_5 with SHA-256)
235
+ - Expiry: 1 hour
236
+ - Key imported via `crypto.subtle.importKey('pkcs8', ...)`
237
+
238
+ #### sendLegacy()
239
+ ```typescript
240
+ async function sendLegacy(message: FCMMessage): Promise<PushResult>
241
+ ```
242
+ Uses the legacy API with `Authorization: key=<serverKey>`. Supports:
243
+ - Single device via `to`
244
+ - Multiple devices via `registration_ids`
245
+ - Topics via `/topics/<topic>`
246
+ - Conditions via `condition`
247
+
248
+ #### sendMulticast()
249
+ ```typescript
250
+ async function sendMulticast(
251
+ tokens: string[],
252
+ message: Omit<FCMMessage, 'to' | 'registrationIds'>,
253
+ ): Promise<PushResult[]>
254
+ ```
255
+ - v1 API: sends individually to each token via `Promise.all` (v1 doesn't support multicast natively)
256
+ - Legacy API: uses `registrationIds` field for native multicast in a single request
257
+
258
+ #### sendToTopic()
259
+ ```typescript
260
+ async function sendToTopic(
261
+ topic: string,
262
+ message: Omit<FCMMessage, 'to' | 'registrationIds' | 'topic'>,
263
+ ): Promise<PushResult>
264
+ ```
265
+ Convenience wrapper that sets the `topic` field and calls `send()`.
266
+
267
+ #### subscribeToTopic()
268
+ ```typescript
269
+ async function subscribeToTopic(tokens: string[], topic: string): Promise<boolean>
270
+ ```
271
+ Uses `https://iid.googleapis.com/iid/v1:batchAdd` with legacy server key auth. Subscribes device tokens to a topic.
272
+
273
+ #### unsubscribeFromTopic()
274
+ ```typescript
275
+ async function unsubscribeFromTopic(tokens: string[], topic: string): Promise<boolean>
276
+ ```
277
+ Uses `https://iid.googleapis.com/iid/v1:batchRemove` with legacy server key auth.
278
+
279
+ ### Exports
280
+ - `send`, `sendLegacy`, `sendMulticast`, `sendToTopic`, `subscribeToTopic`, `unsubscribeFromTopic`, `configure` functions
281
+ - `Send` alias for `send`
282
+
283
+ ## Configuration
284
+
285
+ ```typescript
286
+ import { configureFCM } from '@stacksjs/push'
287
+
288
+ // FCM v1 API (recommended)
289
+ configureFCM({
290
+ projectId: 'my-firebase-project',
291
+ serviceAccount: {
292
+ clientEmail: 'firebase@project.iam.gserviceaccount.com',
293
+ privateKey: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----'
294
+ }
295
+ })
296
+
297
+ // FCM Legacy API (simpler setup)
298
+ configureFCM({
299
+ serverKey: 'your-fcm-server-key'
300
+ })
301
+
302
+ // Expo requires no configuration
303
+ ```
304
+
305
+ ## Usage Examples
306
+
307
+ ```typescript
308
+ import { send } from '@stacksjs/push'
309
+
310
+ // Expo (default driver)
311
+ await send('ExponentPushToken[xxxxxx]', {
312
+ title: 'New Order',
313
+ body: 'You have a new order #1234',
314
+ data: { orderId: 1234 },
315
+ badge: 1,
316
+ sound: 'default',
317
+ priority: 'high',
318
+ })
319
+
320
+ // Multiple Expo tokens
321
+ await send(
322
+ ['ExponentPushToken[aaa]', 'ExponentPushToken[bbb]'],
323
+ { title: 'Announcement', body: 'Maintenance at 3pm' },
324
+ )
325
+
326
+ // FCM single device
327
+ await send('fcm-device-token', notification, { driver: 'fcm' })
328
+
329
+ // FCM multiple devices
330
+ await send(
331
+ ['token1', 'token2', 'token3'],
332
+ { title: 'Alert', body: 'New message' },
333
+ { driver: 'fcm' },
334
+ )
335
+ ```
336
+
337
+ ### Direct driver access
338
+ ```typescript
339
+ import { expo, fcm } from '@stacksjs/push'
340
+
341
+ // Expo batch
342
+ await expo.sendBatch(messages, 100)
343
+
344
+ // Expo receipt check
345
+ const receipts = await expo.getReceipts(['ticket-id-1', 'ticket-id-2'])
346
+
347
+ // FCM topic
348
+ await fcm.sendToTopic('news', { notification: { title: 'Breaking', body: '...' } })
349
+
350
+ // FCM topic subscription
351
+ await fcm.subscribeToTopic(['token1', 'token2'], 'news')
352
+ await fcm.unsubscribeFromTopic(['token1'], 'news')
353
+ ```
354
+
355
+ ## Dependencies
356
+ - `@stacksjs/types` -- `PushResult`, `PushMessage`, `PushTicket`
357
+ - `@stacksjs/cli` -- `log` for info/warn/error logging
358
+ - Web Crypto API -- used by FCM for JWT signing (`crypto.subtle`)
359
+
360
+ ## Gotchas
361
+ - Default driver is `'expo'`, not FCM
362
+ - Expo token validation accepts both `ExponentPushToken[...]` format and plain alphanumeric strings
363
+ - Expo `send()` fans out array tokens into individual payload entries (one per token)
364
+ - Expo default `sound` is `'default'` and default `priority` is `'high'` (set in the driver, not the main send)
365
+ - FCM `data` values must be `Record<string, string>` (strings only, not arbitrary JSON)
366
+ - FCM `send()` auto-falls back to legacy API if no `serviceAccount`/`projectId` configured
367
+ - FCM v1 API does not support native multicast -- `sendMulticast()` sends individually via `Promise.all`
368
+ - FCM legacy API supports multicast via `registrationIds` in a single request
369
+ - FCM topic names are auto-prefixed with `/topics/` in the legacy API
370
+ - `subscribeToTopic()` and `unsubscribeFromTopic()` require the legacy `serverKey` (not service account)
371
+ - The main `send()` converts `priority: 'default'` to `'normal'` for FCM
372
+ - Expo `sendBatch()` processes chunks sequentially but messages within each chunk in parallel
373
+ - FCM v1 JWT tokens expire after 1 hour -- a new token is generated for each `send()` call (no caching)
374
+ - FCM v1 includes both Android and APNS-specific priority headers automatically
375
+ - `badge` only works on iOS -- Android uses notification channels (set via `channelId` on Expo)
376
+ - `sound: null` sends a silent notification
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: stacks-query-builder
3
+ description: Use when building database queries in a Stacks application — constructing SQL queries, using the fluent query API, or configuring the query builder. Covers @stacksjs/query-builder which wraps bun-query-builder, and config/query-builder.ts.
4
+ license: MIT
5
+ compatibility: Bun >= 1.3.0, TypeScript, SQLite >= 3.47.2
6
+ allowed-tools: Read Edit Write Bash Grep Glob
7
+ ---
8
+
9
+ # Stacks Query Builder
10
+
11
+ ## Key Paths
12
+ - Core package: `storage/framework/core/query-builder/src/`
13
+ - Configuration: `config/query-builder.ts`
14
+ - QB state: `.qb/`
15
+ - External library: `bun-query-builder`
16
+ - Package: `@stacksjs/query-builder`
17
+
18
+ ## API
19
+
20
+ The package re-exports everything from `bun-query-builder` plus a compatibility alias:
21
+
22
+ ```typescript
23
+ export * from 'bun-query-builder'
24
+ export { createQueryBuilder as QueryBuilder } from 'bun-query-builder'
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```typescript
30
+ import { db } from '@stacksjs/database'
31
+
32
+ // Select
33
+ const users = await db.selectFrom('users')
34
+ .where('active', '=', true)
35
+ .orderBy('name', 'asc')
36
+ .limit(10)
37
+ .get()
38
+
39
+ // Insert
40
+ await db.insertInto('users')
41
+ .values({ name: 'Alice', email: 'alice@example.com' })
42
+ .execute()
43
+
44
+ // Update
45
+ await db.update('users')
46
+ .set({ active: false })
47
+ .where('id', '=', 1)
48
+ .execute()
49
+
50
+ // Delete
51
+ await db.deleteFrom('users')
52
+ .where('id', '=', 1)
53
+ .execute()
54
+
55
+ // Joins
56
+ const posts = await db.selectFrom('posts')
57
+ .join('users', 'posts.user_id', '=', 'users.id')
58
+ .select(['posts.*', 'users.name as author_name'])
59
+ .get()
60
+
61
+ // Aggregates
62
+ const count = await db.selectFrom('users').count()
63
+ const total = await db.selectFrom('orders').sum('amount')
64
+ ```
65
+
66
+ ## Configuration (config/query-builder.ts)
67
+
68
+ ```typescript
69
+ {
70
+ verbose: true,
71
+ dialect: env.DB_CONNECTION || 'sqlite',
72
+ database: { database, username?, password?, host?, port? },
73
+
74
+ timestamps: {
75
+ createdAt: 'created_at',
76
+ updatedAt: 'updated_at',
77
+ defaultOrderColumn: 'created_at',
78
+ },
79
+
80
+ pagination: {
81
+ defaultPerPage: 25,
82
+ cursorColumn: 'id',
83
+ },
84
+
85
+ aliasing: {
86
+ relationColumnAliasFormat: 'table_column',
87
+ },
88
+
89
+ relations: {
90
+ foreignKeyFormat: 'singularParent_id',
91
+ maxDepth: 10,
92
+ maxEagerLoad: 50,
93
+ detectCycles: true,
94
+ },
95
+
96
+ transactionDefaults: {
97
+ retries: 2,
98
+ isolation: 'read committed',
99
+ sqlStates: ['40001', '40P01'],
100
+ backoff: { baseMs: 50, factor: 2, maxMs: 2000, jitter: true },
101
+ },
102
+
103
+ sql: {
104
+ randomFunction: 'RANDOM()',
105
+ sharedLockSyntax: 'FOR SHARE',
106
+ jsonContainsMode: 'operator',
107
+ },
108
+
109
+ features: { distinctOn: true },
110
+ debug: { captureText: true },
111
+
112
+ softDeletes: {
113
+ enabled: false,
114
+ column: 'deleted_at',
115
+ defaultFilter: true,
116
+ },
117
+ }
118
+ ```
119
+
120
+ ## Gotchas
121
+ - **Thin wrapper** — re-exports `bun-query-builder` with no additions
122
+ - **One config file** — `config/query-builder.ts`. Its `dialect` and connection details are derived from `DB_CONNECTION` and the other `DB_*` env vars, so switching databases is an env change, not a config edit
123
+ - **`.qb/` directory** — stores query builder state for migration diffing
124
+ - **Prefer ORM models** — query builder is the low-level interface; use models for most operations
125
+ - **`db` proxy** — the `db` export from `@stacksjs/database` is a lazy proxy that auto-initializes the query builder on first access
126
+ - **Soft deletes disabled by default** — must be explicitly enabled in config
127
+ - **Transaction retries** — defaults to 2 retries with exponential backoff + jitter
128
+ - **Dialect detection** — reads `DB_CONNECTION` env var, falls back to `sqlite`