@hexclave/shared 1.0.3 → 1.0.6

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 (335) hide show
  1. package/dist/ai/unified-prompts/reminders.js +4 -3
  2. package/dist/ai/unified-prompts/reminders.js.map +1 -1
  3. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
  4. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
  5. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +216 -29
  6. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
  7. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
  8. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
  9. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
  10. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
  11. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
  12. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
  13. package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
  14. package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
  15. package/dist/config/schema.d.ts +1 -1
  16. package/dist/config/schema.d.ts.map +1 -1
  17. package/dist/config/schema.js +5 -5
  18. package/dist/config/schema.js.map +1 -1
  19. package/dist/config-authoring.d.ts +4 -4
  20. package/dist/config-authoring.d.ts.map +1 -1
  21. package/dist/config-authoring.js +2 -2
  22. package/dist/config-authoring.js.map +1 -1
  23. package/dist/config-rendering.d.ts +4 -4
  24. package/dist/config-rendering.d.ts.map +1 -1
  25. package/dist/config-rendering.js +19 -18
  26. package/dist/config-rendering.js.map +1 -1
  27. package/dist/esm/ai/unified-prompts/reminders.js +4 -3
  28. package/dist/esm/ai/unified-prompts/reminders.js.map +1 -1
  29. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
  30. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
  31. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +215 -30
  32. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
  33. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
  34. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
  35. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
  36. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
  37. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
  38. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
  39. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
  40. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
  41. package/dist/esm/config/schema.d.ts +1 -1
  42. package/dist/esm/config/schema.d.ts.map +1 -1
  43. package/dist/esm/config/schema.js +5 -5
  44. package/dist/esm/config/schema.js.map +1 -1
  45. package/dist/esm/config-authoring.d.ts +4 -4
  46. package/dist/esm/config-authoring.d.ts.map +1 -1
  47. package/dist/esm/config-authoring.js +2 -2
  48. package/dist/esm/config-authoring.js.map +1 -1
  49. package/dist/esm/config-rendering.d.ts +4 -4
  50. package/dist/esm/config-rendering.d.ts.map +1 -1
  51. package/dist/esm/config-rendering.js +15 -14
  52. package/dist/esm/config-rendering.js.map +1 -1
  53. package/dist/esm/helpers/vault/client-side.d.ts.map +1 -1
  54. package/dist/esm/helpers/vault/client-side.js.map +1 -1
  55. package/dist/esm/helpers/vault/server-side.d.ts.map +1 -1
  56. package/dist/esm/helpers/vault/server-side.js.map +1 -1
  57. package/dist/esm/hexclave-config-file.d.ts +15 -0
  58. package/dist/esm/hexclave-config-file.d.ts.map +1 -0
  59. package/dist/esm/{stack-config-file.js → hexclave-config-file.js} +7 -7
  60. package/dist/esm/hexclave-config-file.js.map +1 -0
  61. package/dist/esm/interface/admin-metrics.d.ts +2 -2
  62. package/dist/esm/interface/admin-metrics.js.map +1 -1
  63. package/dist/esm/interface/client-interface.js +2 -2
  64. package/dist/esm/interface/client-interface.js.map +1 -1
  65. package/dist/esm/interface/conversations.d.ts +32 -32
  66. package/dist/esm/interface/crud/current-user.d.ts +7 -7
  67. package/dist/esm/interface/crud/email-outbox.d.ts +42 -42
  68. package/dist/esm/interface/crud/project-permissions.js +5 -5
  69. package/dist/esm/interface/crud/project-permissions.js.map +1 -1
  70. package/dist/esm/interface/crud/team-member-profiles.d.ts +18 -18
  71. package/dist/esm/interface/crud/team-permissions.js +5 -5
  72. package/dist/esm/interface/crud/team-permissions.js.map +1 -1
  73. package/dist/esm/interface/crud/users.d.ts +10 -10
  74. package/dist/esm/interface/page-component-versions.js +107 -107
  75. package/dist/esm/interface/page-component-versions.js.map +1 -1
  76. package/dist/esm/interface/webhooks.d.ts +2 -2
  77. package/dist/esm/known-errors.d.ts +1 -1
  78. package/dist/esm/known-errors.d.ts.map +1 -1
  79. package/dist/esm/known-errors.js +9 -5
  80. package/dist/esm/known-errors.js.map +1 -1
  81. package/dist/esm/schema-fields.d.ts +15 -5
  82. package/dist/esm/schema-fields.d.ts.map +1 -1
  83. package/dist/esm/schema-fields.js +26 -16
  84. package/dist/esm/schema-fields.js.map +1 -1
  85. package/dist/esm/utils/crypto.d.ts.map +1 -1
  86. package/dist/esm/utils/crypto.js.map +1 -1
  87. package/dist/esm/utils/currency-constants.d.ts +6 -0
  88. package/dist/esm/utils/currency-constants.d.ts.map +1 -1
  89. package/dist/esm/utils/currency-constants.js.map +1 -1
  90. package/dist/esm/utils/dev-env-state-path.d.ts +3 -3
  91. package/dist/esm/utils/dev-env-state-path.d.ts.map +1 -1
  92. package/dist/esm/utils/dev-env-state-path.js +4 -4
  93. package/dist/esm/utils/dev-env-state-path.js.map +1 -1
  94. package/dist/esm/utils/errors.js +2 -2
  95. package/dist/esm/utils/errors.js.map +1 -1
  96. package/dist/esm/utils/esbuild.d.ts.map +1 -1
  97. package/dist/esm/utils/esbuild.js +0 -1
  98. package/dist/esm/utils/esbuild.js.map +1 -1
  99. package/dist/esm/utils/featurebase.d.ts +3 -3
  100. package/dist/esm/utils/featurebase.d.ts.map +1 -1
  101. package/dist/esm/utils/featurebase.js +15 -15
  102. package/dist/esm/utils/featurebase.js.map +1 -1
  103. package/dist/esm/utils/fs.js +6 -6
  104. package/dist/esm/utils/fs.js.map +1 -1
  105. package/dist/esm/utils/globals.d.ts.map +1 -1
  106. package/dist/esm/utils/globals.js +10 -10
  107. package/dist/esm/utils/globals.js.map +1 -1
  108. package/dist/esm/utils/jwt.d.ts.map +1 -1
  109. package/dist/esm/utils/jwt.js +3 -3
  110. package/dist/esm/utils/jwt.js.map +1 -1
  111. package/dist/esm/utils/redirect-urls.d.ts +3 -3
  112. package/dist/esm/utils/redirect-urls.d.ts.map +1 -1
  113. package/dist/esm/utils/redirect-urls.js +5 -5
  114. package/dist/esm/utils/redirect-urls.js.map +1 -1
  115. package/dist/esm/utils/urls.js.map +1 -1
  116. package/dist/helpers/vault/client-side.d.ts.map +1 -1
  117. package/dist/helpers/vault/client-side.js.map +1 -1
  118. package/dist/helpers/vault/server-side.d.ts.map +1 -1
  119. package/dist/helpers/vault/server-side.js.map +1 -1
  120. package/dist/hexclave-config-file.d.ts +15 -0
  121. package/dist/hexclave-config-file.d.ts.map +1 -0
  122. package/dist/{stack-config-file.js → hexclave-config-file.js} +8 -8
  123. package/dist/hexclave-config-file.js.map +1 -0
  124. package/dist/interface/admin-metrics.d.ts +12 -12
  125. package/dist/interface/admin-metrics.js.map +1 -1
  126. package/dist/interface/client-interface.js +2 -2
  127. package/dist/interface/client-interface.js.map +1 -1
  128. package/dist/interface/conversations.d.ts +32 -32
  129. package/dist/interface/crud/current-user.d.ts +7 -7
  130. package/dist/interface/crud/email-outbox.d.ts +42 -42
  131. package/dist/interface/crud/project-permissions.js +5 -5
  132. package/dist/interface/crud/project-permissions.js.map +1 -1
  133. package/dist/interface/crud/team-member-profiles.d.ts +18 -18
  134. package/dist/interface/crud/team-permissions.js +5 -5
  135. package/dist/interface/crud/team-permissions.js.map +1 -1
  136. package/dist/interface/crud/users.d.ts +10 -10
  137. package/dist/interface/page-component-versions.js +107 -107
  138. package/dist/interface/page-component-versions.js.map +1 -1
  139. package/dist/interface/webhooks.d.ts +2 -2
  140. package/dist/known-errors.d.ts +1 -1
  141. package/dist/known-errors.d.ts.map +1 -1
  142. package/dist/known-errors.js +9 -5
  143. package/dist/known-errors.js.map +1 -1
  144. package/dist/schema-fields.d.ts +15 -5
  145. package/dist/schema-fields.d.ts.map +1 -1
  146. package/dist/schema-fields.js +26 -16
  147. package/dist/schema-fields.js.map +1 -1
  148. package/dist/utils/crypto.d.ts.map +1 -1
  149. package/dist/utils/crypto.js.map +1 -1
  150. package/dist/utils/currency-constants.d.ts +6 -0
  151. package/dist/utils/currency-constants.d.ts.map +1 -1
  152. package/dist/utils/currency-constants.js.map +1 -1
  153. package/dist/utils/dev-env-state-path.d.ts +3 -3
  154. package/dist/utils/dev-env-state-path.d.ts.map +1 -1
  155. package/dist/utils/dev-env-state-path.js +5 -5
  156. package/dist/utils/dev-env-state-path.js.map +1 -1
  157. package/dist/utils/errors.js +2 -2
  158. package/dist/utils/errors.js.map +1 -1
  159. package/dist/utils/esbuild.d.ts.map +1 -1
  160. package/dist/utils/esbuild.js +0 -1
  161. package/dist/utils/esbuild.js.map +1 -1
  162. package/dist/utils/featurebase.d.ts +3 -3
  163. package/dist/utils/featurebase.d.ts.map +1 -1
  164. package/dist/utils/featurebase.js +15 -15
  165. package/dist/utils/featurebase.js.map +1 -1
  166. package/dist/utils/fs.js.map +1 -1
  167. package/dist/utils/globals.d.ts.map +1 -1
  168. package/dist/utils/globals.js +10 -10
  169. package/dist/utils/globals.js.map +1 -1
  170. package/dist/utils/jwt.d.ts.map +1 -1
  171. package/dist/utils/jwt.js +3 -3
  172. package/dist/utils/jwt.js.map +1 -1
  173. package/dist/utils/redirect-urls.d.ts +3 -3
  174. package/dist/utils/redirect-urls.d.ts.map +1 -1
  175. package/dist/utils/redirect-urls.js +5 -5
  176. package/dist/utils/redirect-urls.js.map +1 -1
  177. package/dist/utils/urls.js.map +1 -1
  178. package/package.json +2 -1
  179. package/src/ai/image-limits.ts +62 -0
  180. package/src/ai/llms/llms.ts +36 -0
  181. package/src/ai/unified-prompts/reminders.ts +27 -0
  182. package/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts +1047 -0
  183. package/src/ai/unified-prompts/skill-site-prompt-parts/brain.ts +5 -0
  184. package/src/ai/unified-prompts/skill-site-prompt-parts/cli-help.ts +5 -0
  185. package/src/ai/unified-prompts/skill-site-prompt-parts/config-docs.ts +5 -0
  186. package/src/ai/unified-prompts/skill-site-prompt-parts/custom-components-instructions.ts +5 -0
  187. package/src/ai/unified-prompts/skill-site-prompt-parts/dashboard-instructions.ts +5 -0
  188. package/src/ai/unified-prompts/skill-site-prompt-parts/docs-index.ts +80 -0
  189. package/src/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.ts +322 -0
  190. package/src/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.ts +5 -0
  191. package/src/ai/unified-prompts/skill-site-prompt-parts/sdk-interface-source.ts +5 -0
  192. package/src/ai/unified-prompts/skill-site-prompt.ts +72 -0
  193. package/src/apps/apps-config.ts +177 -0
  194. package/src/apps/apps-ui.tsx +112 -0
  195. package/src/config/README.md +154 -0
  196. package/src/config/db-sync-mappings.ts +2293 -0
  197. package/src/config/format.ts +388 -0
  198. package/src/config/migrate-catalogs-to-product-lines.ts +475 -0
  199. package/src/config/schema-fuzzer.test.ts +377 -0
  200. package/src/config/schema.ts +1507 -0
  201. package/src/config-authoring.test.ts +52 -0
  202. package/src/config-authoring.ts +37 -0
  203. package/src/config-rendering.ts +142 -0
  204. package/src/crud.tsx +275 -0
  205. package/src/global.d.ts +1 -0
  206. package/src/helpers/emails.ts +250 -0
  207. package/src/helpers/init-prompt.ts +39 -0
  208. package/src/helpers/password.ts +16 -0
  209. package/src/helpers/production-mode.ts +58 -0
  210. package/src/helpers/support-sla.test.ts +124 -0
  211. package/src/helpers/support-sla.ts +93 -0
  212. package/src/helpers/vault/client-side.ts +92 -0
  213. package/src/helpers/vault/server-side.ts +153 -0
  214. package/src/hexclave-config-file.ts +120 -0
  215. package/src/hooks/use-async-callback.tsx +43 -0
  216. package/src/hooks/use-async-external-store.tsx +24 -0
  217. package/src/hooks/use-hash.tsx +14 -0
  218. package/src/hooks/use-hover.tsx +88 -0
  219. package/src/hooks/use-strict-memo.tsx +157 -0
  220. package/src/index.ts +17 -0
  221. package/src/interface/admin-interface.ts +1043 -0
  222. package/src/interface/admin-metrics.ts +214 -0
  223. package/src/interface/client-interface.test.ts +765 -0
  224. package/src/interface/client-interface.ts +2586 -0
  225. package/src/interface/conversations.ts +109 -0
  226. package/src/interface/crud/analytics.ts +11 -0
  227. package/src/interface/crud/connected-accounts.ts +52 -0
  228. package/src/interface/crud/contact-channels.ts +74 -0
  229. package/src/interface/crud/current-user.ts +72 -0
  230. package/src/interface/crud/email-outbox.ts +263 -0
  231. package/src/interface/crud/email-templates.ts +50 -0
  232. package/src/interface/crud/emails.ts +22 -0
  233. package/src/interface/crud/internal-api-keys.ts +69 -0
  234. package/src/interface/crud/invoices.ts +36 -0
  235. package/src/interface/crud/items.ts +24 -0
  236. package/src/interface/crud/notification-preferences.ts +33 -0
  237. package/src/interface/crud/oauth-providers.ts +91 -0
  238. package/src/interface/crud/products.ts +42 -0
  239. package/src/interface/crud/project-api-keys.ts +100 -0
  240. package/src/interface/crud/project-permissions.ts +118 -0
  241. package/src/interface/crud/projects.ts +229 -0
  242. package/src/interface/crud/session-replays.ts +85 -0
  243. package/src/interface/crud/sessions.ts +66 -0
  244. package/src/interface/crud/sign-up-rules.ts +12 -0
  245. package/src/interface/crud/svix-token.ts +20 -0
  246. package/src/interface/crud/team-invitation-details.ts +22 -0
  247. package/src/interface/crud/team-invitation.ts +35 -0
  248. package/src/interface/crud/team-member-profiles.ts +61 -0
  249. package/src/interface/crud/team-memberships.ts +56 -0
  250. package/src/interface/crud/team-permissions.ts +119 -0
  251. package/src/interface/crud/teams.ts +142 -0
  252. package/src/interface/crud/transactions.ts +131 -0
  253. package/src/interface/crud/users.ts +185 -0
  254. package/src/interface/handler-urls.ts +74 -0
  255. package/src/interface/page-component-versions.ts +1702 -0
  256. package/src/interface/server-interface.ts +1146 -0
  257. package/src/interface/webhooks.ts +28 -0
  258. package/src/known-errors.tsx +2034 -0
  259. package/src/local-emulator.ts +5 -0
  260. package/src/payments/payment-methods.ts +167 -0
  261. package/src/payments/stripe-limits.ts +18 -0
  262. package/src/plans.ts +107 -0
  263. package/src/schema-fields.ts +944 -0
  264. package/src/sessions.ts +310 -0
  265. package/src/utils/api-keys.tsx +122 -0
  266. package/src/utils/arrays.tsx +248 -0
  267. package/src/utils/auth-methods.ts +8 -0
  268. package/src/utils/base64.tsx +24 -0
  269. package/src/utils/booleans.tsx +34 -0
  270. package/src/utils/browser-compat.tsx +17 -0
  271. package/src/utils/bytes.tsx +280 -0
  272. package/src/utils/caches.tsx +280 -0
  273. package/src/utils/cel-fields.ts +92 -0
  274. package/src/utils/cloud-hosts.tsx +92 -0
  275. package/src/utils/compile-time.tsx +11 -0
  276. package/src/utils/country-codes.ts +39 -0
  277. package/src/utils/crypto.tsx +174 -0
  278. package/src/utils/currencies.tsx +53 -0
  279. package/src/utils/currency-constants.tsx +51 -0
  280. package/src/utils/dates.tsx +246 -0
  281. package/src/utils/dev-env-state-path.ts +14 -0
  282. package/src/utils/dom.tsx +7 -0
  283. package/src/utils/env.tsx +117 -0
  284. package/src/utils/errors.tsx +284 -0
  285. package/src/utils/esbuild.tsx +235 -0
  286. package/src/utils/featurebase.tsx +247 -0
  287. package/src/utils/fs.tsx +33 -0
  288. package/src/utils/functions.tsx +22 -0
  289. package/src/utils/geo.tsx +16 -0
  290. package/src/utils/globals.tsx +48 -0
  291. package/src/utils/hashes.tsx +52 -0
  292. package/src/utils/html.tsx +60 -0
  293. package/src/utils/http.tsx +91 -0
  294. package/src/utils/ips.tsx +47 -0
  295. package/src/utils/json.tsx +200 -0
  296. package/src/utils/jsx-editable-transpiler.test.ts +156 -0
  297. package/src/utils/jsx-editable-transpiler.tsx +401 -0
  298. package/src/utils/jwt.tsx +170 -0
  299. package/src/utils/locks.tsx +71 -0
  300. package/src/utils/maps.tsx +407 -0
  301. package/src/utils/math.tsx +18 -0
  302. package/src/utils/monkey-patch.tsx +29 -0
  303. package/src/utils/node-http.tsx +47 -0
  304. package/src/utils/numbers.tsx +82 -0
  305. package/src/utils/oauth.tsx +9 -0
  306. package/src/utils/objects.tsx +581 -0
  307. package/src/utils/paginated-lists.test.ts +1039 -0
  308. package/src/utils/paginated-lists.tsx +479 -0
  309. package/src/utils/passkey.tsx +1 -0
  310. package/src/utils/promises.tsx +540 -0
  311. package/src/utils/proxies.tsx +212 -0
  312. package/src/utils/react.tsx +308 -0
  313. package/src/utils/redirect-urls.tsx +299 -0
  314. package/src/utils/regex.tsx +10 -0
  315. package/src/utils/results.tsx +411 -0
  316. package/src/utils/sentry.tsx +20 -0
  317. package/src/utils/stores.tsx +238 -0
  318. package/src/utils/strings.nicify.test.ts +253 -0
  319. package/src/utils/strings.tsx +723 -0
  320. package/src/utils/telemetry.tsx +37 -0
  321. package/src/utils/turnstile-browser.ts +106 -0
  322. package/src/utils/turnstile-flow.test.ts +101 -0
  323. package/src/utils/turnstile-flow.ts +266 -0
  324. package/src/utils/turnstile.ts +34 -0
  325. package/src/utils/typed-arrays.tsx +17 -0
  326. package/src/utils/types.tsx +208 -0
  327. package/src/utils/unicode.tsx +24 -0
  328. package/src/utils/urls.tsx +411 -0
  329. package/src/utils/uuids.tsx +47 -0
  330. package/dist/esm/stack-config-file.d.ts +0 -15
  331. package/dist/esm/stack-config-file.d.ts.map +0 -1
  332. package/dist/esm/stack-config-file.js.map +0 -1
  333. package/dist/stack-config-file.d.ts +0 -15
  334. package/dist/stack-config-file.d.ts.map +0 -1
  335. package/dist/stack-config-file.js.map +0 -1
@@ -0,0 +1,377 @@
1
+ import { ALL_APPS } from "../apps/apps-config";
2
+ import { SUPPORTED_CURRENCIES } from "../utils/currency-constants";
3
+ import { HexclaveAssertionError } from "../utils/errors";
4
+ import { getOrUndefined, isObjectLike, set, typedEntries, typedFromEntries } from "../utils/objects";
5
+ import { nicify } from "../utils/strings";
6
+ import { normalize, override } from "./format";
7
+ import { BranchConfigNormalizedOverride, EnvironmentConfigNormalizedOverride, OrganizationConfigNormalizedOverride, ProjectConfigNormalizedOverride, applyBranchDefaults, applyEnvironmentDefaults, applyOrganizationDefaults, applyProjectDefaults, assertNoConfigOverrideErrors, branchConfigSchema, environmentConfigSchema, migrateConfigOverride, organizationConfigSchema, projectConfigSchema, sanitizeBranchConfig, sanitizeEnvironmentConfig, sanitizeOrganizationConfig, sanitizeProjectConfig } from "./schema";
8
+
9
+ type FuzzerConfig<T> = ReadonlyArray<T extends object ? ([T] extends [any[]] ? { readonly [K in keyof T]: FuzzerConfig<T[K]> } : Required<{
10
+ [K in keyof T]: FuzzerConfig<T[K]>;
11
+ }> & Record<string, FuzzerConfig<any>>) : T>;
12
+
13
+ const projectSchemaFuzzerConfig = [{
14
+ sourceOfTruth: [{
15
+ type: ["hosted"],
16
+ }],
17
+ project: [{
18
+ requirePublishableClientKey: [true, false],
19
+ }],
20
+ }] satisfies FuzzerConfig<ProjectConfigNormalizedOverride>;
21
+
22
+ const branchSchemaFuzzerConfig = [{
23
+ apiKeys: [{
24
+ enabled: [{
25
+ team: [true, false],
26
+ user: [true, false],
27
+ }],
28
+ }],
29
+ auth: [{
30
+ allowSignUp: [true, false],
31
+ password: [{
32
+ allowSignIn: [true, false],
33
+ }],
34
+ otp: [{
35
+ allowSignIn: [true, false],
36
+ }],
37
+ passkey: [{
38
+ allowSignIn: [true, false],
39
+ }],
40
+ oauth: [{
41
+ accountMergeStrategy: ["link_method", "raise_error", "allow_duplicates"],
42
+ providers: [{
43
+ "google": [{
44
+ type: ["google", "github", "x"] as const,
45
+ allowSignIn: [true, false],
46
+ allowConnectedAccounts: [true, false],
47
+ }],
48
+ }],
49
+ }],
50
+ signUpRules: [{
51
+ "some-rule-id": [{
52
+ enabled: [true, false],
53
+ displayName: ["Block Test Emails", "Allow Only Company Domain"],
54
+ priority: [0, 1, 100],
55
+ condition: ['email.endsWith("@test.com")', 'emailDomain == "company.com"'],
56
+ action: [{
57
+ type: ["allow", "reject", "restrict", "log"] as const,
58
+ message: ["", "Sign up is not allowed for this email"],
59
+ }],
60
+ }],
61
+ }],
62
+ signUpRulesDefaultAction: ["allow", "reject"],
63
+ }],
64
+ dbSync: [{
65
+ externalDatabases: [{
66
+ "some-external-db-id": [{
67
+ type: ["postgres"] as const,
68
+ connectionString: [
69
+ "postgres://user:password@host:port/database",
70
+ "some-connection-string",
71
+ ],
72
+ }],
73
+ }],
74
+ }],
75
+ dataVault: [{
76
+ stores: [{
77
+ "some-store-id": [{
78
+ displayName: ["Some Store", "Some Other Store"],
79
+ }],
80
+ "some-other-store-id": [{
81
+ displayName: ["Some Store", "Some Other Store"],
82
+ }],
83
+ }],
84
+ }],
85
+ payments: [{
86
+ blockNewPurchases: [false, true],
87
+ autoPay: [{
88
+ interval: [[[0, 1, -3, 100, 0.333, Infinity], ["day", "week", "month", "year"]]] as const,
89
+ }],
90
+ productLines: [{
91
+ "some-product-line-id": [{
92
+ displayName: ["Some Product Line", "Some Other Product Line"],
93
+ customerType: ["user", "team", "custom"] as const,
94
+ }],
95
+ }],
96
+ catalogs: [{ // ensure migration works
97
+ "some-product-line-id": [{
98
+ displayName: ["Some Product Line", "Some Other Product Line"],
99
+ }],
100
+ }],
101
+ groups: [{ // ensure migration works
102
+ "some-product-line-id": [{
103
+ displayName: ["Some Product Line", "Some Other Product Line"],
104
+ }],
105
+ }],
106
+ items: [{
107
+ "some-item-id": [{
108
+ customerType: ["user", "team", "custom"] as const,
109
+ displayName: ["Some Item", "Some Other Item"],
110
+ }],
111
+ }],
112
+ products: [{
113
+ "some-product-id": [{
114
+ displayName: ["Some Product", "Some Other Product"],
115
+ customerType: ["user", "team", "custom"] as const,
116
+ freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], ["day", "week", "month", "year"]]] as const,
117
+ serverOnly: [true, false],
118
+ stackable: [true, false],
119
+ productLineId: ["some-product-line-id", "some-other-product-line-id"],
120
+ catalogId: ["some-product-line-id", "some-other-product-line-id"], // ensure migration works
121
+ groupId: ["some-product-line-id", "some-other-product-line-id"], // ensure migration works
122
+ isAddOnTo: [false, { "some-product-id": [true], "some-other-product-id": [true] }] as const,
123
+ prices: [{
124
+ "some-price-id": [{
125
+ ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, ["100_00", "not a number", "Infinity", "0"]])),
126
+ interval: [[[0, 1, -3, 100, 0.333, Infinity], ["day", "week", "month", "year"]]] as const,
127
+ serverOnly: [true, false],
128
+ freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], ["day", "week", "month", "year"]]] as const,
129
+ }],
130
+ }],
131
+ includedItems: [{
132
+ "some-item-id": [{
133
+ quantity: [0, 1, -3, 100, 0.333, Infinity],
134
+ repeat: ["never", [[0, 1, -3, 100, 0.333, Infinity], ["day", "week", "month", "year"]]] as const,
135
+ expires: ["never", "when-purchase-expires", "when-repeated"] as const,
136
+ }],
137
+ }],
138
+ }],
139
+ }],
140
+ }],
141
+ emails: [{
142
+ themes: [{
143
+ "12345678-1234-4234-9234-123456789012": [{
144
+ displayName: ["Some Theme", "Some Other Theme"],
145
+ tsxSource: ["", "some typescript source code"],
146
+ }],
147
+ }],
148
+ selectedThemeId: ["some-theme-id", "some-other-theme-id"],
149
+ templates: [{
150
+ "12345678-1234-4234-9234-123456789012": [{
151
+ themeId: ["some-theme-id", "some-other-theme-id"],
152
+ displayName: ["Some Template", "Some Other Template"],
153
+ tsxSource: ["", "some typescript source code"],
154
+ }],
155
+ }],
156
+ }],
157
+ teams: [{
158
+ createPersonalTeamOnSignUp: [true, false],
159
+ allowClientTeamCreation: [true, false],
160
+ }],
161
+ users: [{
162
+ allowClientUserDeletion: [true, false],
163
+ }],
164
+ rbac: [{
165
+ permissions: [{
166
+ "some_permission_id": [{
167
+ containedPermissionIds: [{
168
+ "some_permission_id": [true],
169
+ "$some_other_permission_id": [true],
170
+ }] as const,
171
+ description: ["Some Permission", "Some Other Permission"],
172
+ scope: ["team", "project"] as const,
173
+ }],
174
+ }],
175
+ defaultPermissions: [{
176
+ teamCreator: [{
177
+ "some_permission_id": [true],
178
+ "$some_other_permission_id": [true],
179
+ }] as const,
180
+ teamMember: [{
181
+ "some_permission_id": [true],
182
+ "$some_other_permission_id": [true],
183
+ }] as const,
184
+ signUp: [{
185
+ "some_permission_id": [true],
186
+ "$some_other_permission_id": [true],
187
+ }] as const,
188
+ }],
189
+ }],
190
+ domains: [{}],
191
+ apps: [{
192
+ installed: [typedFromEntries(typedEntries(ALL_APPS).map(([key, value]) => [key, [{
193
+ enabled: [true, false],
194
+ }]]))],
195
+ }],
196
+ onboarding: [{
197
+ requireEmailVerification: [true, false],
198
+ }],
199
+ }] satisfies FuzzerConfig<BranchConfigNormalizedOverride>;
200
+
201
+ const environmentSchemaFuzzerConfig = [{
202
+ ...branchSchemaFuzzerConfig[0],
203
+ auth: [{
204
+ ...branchSchemaFuzzerConfig[0].auth[0],
205
+ oauth: [{
206
+ ...branchSchemaFuzzerConfig[0].auth[0].oauth[0],
207
+ providers: [typedFromEntries(typedEntries(branchSchemaFuzzerConfig[0].auth[0].oauth[0].providers[0]).map(([key, value]) => [key, [{
208
+ ...value[0],
209
+ isShared: [true, false],
210
+ clientId: ["some-client-id"],
211
+ clientSecret: ["some-client-secret"],
212
+ // Kept undefined: the schema forbids customCallbackUrl when isShared is
213
+ // true, and the fuzzer randomizes each field independently so it cannot
214
+ // honor that coupling. The accept path is covered by an e2e test.
215
+ customCallbackUrl: [undefined] as (string | undefined)[],
216
+ facebookConfigId: ["some-facebook-config-id"],
217
+ microsoftTenantId: ["some-microsoft-tenant-id"],
218
+ appleBundles: [{ "some-bundle-id": [{ bundleId: ["com.example.app"] }] }],
219
+ }]]))] as const,
220
+ }],
221
+ }],
222
+ domains: [{
223
+ allowLocalhost: [true, false],
224
+ trustedDomains: [{
225
+ "some-domain-id": [{
226
+ baseUrl: ["https://example.com/something-here"],
227
+ handlerPath: ["/something-here"],
228
+ }],
229
+ }],
230
+ }],
231
+ emails: [{
232
+ ...branchSchemaFuzzerConfig[0].emails[0],
233
+ server: [{
234
+ isShared: [true, false],
235
+ provider: ["resend", "smtp", "managed"] as const,
236
+ host: ["example.com", "://super weird host that's not valid"],
237
+ port: [1234, 0.12543, -100, Infinity],
238
+ username: ["some-username", "some username with a space"],
239
+ password: ["some-password", "some password with a space"],
240
+ senderName: ["Some Sender"],
241
+ senderEmail: ["some-sender@example.com", "some invalid email"],
242
+ managedSubdomain: ["mail.example.com", "invalid subdomain"],
243
+ managedSenderLocalPart: ["noreply", "some invalid local part"],
244
+ }],
245
+ }],
246
+ payments: [{
247
+ ...branchSchemaFuzzerConfig[0].payments[0],
248
+ testMode: [false, true],
249
+ }],
250
+ analytics: [{
251
+ queryFolders: [{
252
+ "some-folder-id": [{
253
+ displayName: ["Some Folder", "Some Other Folder"],
254
+ sortOrder: [0, 1, 10, -5],
255
+ queries: [{
256
+ "some-query-id": [{
257
+ displayName: ["Some Query", "Some Other Query"],
258
+ sqlQuery: ["", "SELECT * FROM events", "SELECT * FROM users"],
259
+ description: ["", "A query description", "Another description"],
260
+ }],
261
+ }],
262
+ }],
263
+ }],
264
+ }],
265
+ customDashboards: [{
266
+ "12345678-1234-4234-9234-123456789012": [{
267
+ displayName: ["My Dashboard", "User Growth Dashboard"],
268
+ tsxSource: ["", "function Dashboard() { return <div>Hello</div>; }"],
269
+ }],
270
+ }],
271
+ }] satisfies FuzzerConfig<EnvironmentConfigNormalizedOverride>;
272
+
273
+ const organizationSchemaFuzzerConfig = environmentSchemaFuzzerConfig satisfies FuzzerConfig<OrganizationConfigNormalizedOverride>;
274
+
275
+ function setDeep<T>(obj: T, path: string[], value: any) {
276
+ if (!isObjectLike(obj)) return obj;
277
+
278
+ if (path.length === 0) {
279
+ throw new Error("Path is empty");
280
+ } else if (path.length === 1) {
281
+ set(obj as any, path[0], value);
282
+ } else {
283
+ const [key, ...rest] = path;
284
+ setDeep(getOrUndefined(obj as any, key), rest, value);
285
+ }
286
+ }
287
+
288
+ function createFuzzerInput<T>(config: FuzzerConfig<T>, progress: number): T {
289
+ progress = Math.min(1, 2 * progress);
290
+ const createShouldRandom = (strength: number) => {
291
+ const chance = Math.random() * strength * 1.2 - 0.1;
292
+ return () => Math.random() < chance;
293
+ };
294
+ const createShouldObjectDependent = (strength: number) => {
295
+ const objectChance = Math.random() * strength * 1.2 - 0.1;
296
+ const primitiveChance = Math.random() * strength * 1.2 - 0.1;
297
+ return (v: any) => Math.random() * Math.random() < (isObjectLike(v) ? objectChance : primitiveChance);
298
+ };
299
+
300
+ const shouldKeep = createShouldObjectDependent(progress * 1);
301
+ const shouldMakeNested = createShouldObjectDependent(1.25);
302
+ const shouldNull = createShouldRandom(0.25);
303
+
304
+ let res: any;
305
+ const recurse = <U>(outputPath: string[], config: FuzzerConfig<U>, forceNested: boolean, forceNonNull: boolean) => {
306
+ let subConfig: any = config[Math.floor(Math.random() * config.length)];
307
+ const originalValue = isObjectLike(subConfig) ? (Array.isArray(subConfig) ? [] : {}) : subConfig;
308
+
309
+ const newValue = forceNonNull || !shouldNull() ? originalValue : null;
310
+ const newOutputPath = forceNested || shouldMakeNested(originalValue) || outputPath.length === 0 ? outputPath : [outputPath.join(".")];
311
+ if (outputPath.length === 0) {
312
+ res = newValue;
313
+ } else {
314
+ if (forceNested || shouldKeep(originalValue)) {
315
+ setDeep(res, newOutputPath, newValue);
316
+ }
317
+ }
318
+ if (isObjectLike(subConfig)) {
319
+ for (const [key, newValue] of typedEntries(subConfig)) {
320
+ recurse([...newOutputPath, key], newValue, Array.isArray(subConfig), Array.isArray(subConfig));
321
+ }
322
+ }
323
+ };
324
+ recurse<T>([], config, false, true);
325
+ return res;
326
+ }
327
+
328
+ import.meta.vitest?.test("fuzz schemas", async ({ expect }) => {
329
+ const totalIterations = process.env.CI ? 1000 : 200;
330
+ for (let i = 0; i < totalIterations; i++) {
331
+ const projectInput = createFuzzerInput<ProjectConfigNormalizedOverride>(projectSchemaFuzzerConfig, i / totalIterations);
332
+ const branchInput = createFuzzerInput<BranchConfigNormalizedOverride>(branchSchemaFuzzerConfig, i / totalIterations);
333
+ const environmentInput = createFuzzerInput<EnvironmentConfigNormalizedOverride>(environmentSchemaFuzzerConfig, i / totalIterations);
334
+ const organizationInput = createFuzzerInput<OrganizationConfigNormalizedOverride>(organizationSchemaFuzzerConfig, i / totalIterations);
335
+
336
+ try {
337
+ const projectMigrated = migrateConfigOverride("project", projectInput);
338
+ await assertNoConfigOverrideErrors(projectConfigSchema, projectMigrated);
339
+ const projectOverridden = override({}, projectMigrated);
340
+ await sanitizeProjectConfig(normalize(applyProjectDefaults(projectOverridden), { onDotIntoNonObject: "ignore" }) as any);
341
+
342
+ const branchMigrated = migrateConfigOverride("branch", branchInput);
343
+ await assertNoConfigOverrideErrors(branchConfigSchema, branchMigrated);
344
+ const branchOverridden = override(projectOverridden, branchMigrated);
345
+ await sanitizeBranchConfig(normalize(applyBranchDefaults(branchOverridden), { onDotIntoNonObject: "ignore" }) as any);
346
+
347
+ const environmentMigrated = migrateConfigOverride("environment", environmentInput);
348
+ await assertNoConfigOverrideErrors(environmentConfigSchema, environmentMigrated);
349
+ const environmentOverridden = override(branchOverridden, environmentMigrated);
350
+ await sanitizeEnvironmentConfig(normalize(applyEnvironmentDefaults(environmentOverridden), { onDotIntoNonObject: "ignore" }) as any);
351
+
352
+ const organizationMigrated = migrateConfigOverride("organization", organizationInput);
353
+ await assertNoConfigOverrideErrors(organizationConfigSchema, organizationMigrated);
354
+ const organizationOverridden = override(environmentOverridden, organizationMigrated);
355
+ await sanitizeOrganizationConfig(normalize(applyOrganizationDefaults(organizationOverridden), { onDotIntoNonObject: "ignore" }) as any);
356
+
357
+ } catch (e) {
358
+ const data = {
359
+ cause: e,
360
+ inputs: {
361
+ projectInput,
362
+ branchInput,
363
+ environmentInput,
364
+ organizationInput,
365
+ },
366
+ } as const;
367
+ console.error("Failed to fuzz schema in iteration ${i}/${totalIterations}!", nicify(data));
368
+ throw new HexclaveAssertionError(`Error in iteration ${i}/${totalIterations} of schema fuzz: ${e}`, { cause: e });
369
+ }
370
+ }
371
+ });
372
+
373
+ import.meta.vitest?.test("rejects include-by-default product prices in config overrides", async ({ expect }) => {
374
+ await expect(assertNoConfigOverrideErrors(branchConfigSchema, {
375
+ "payments.products.free.prices": "include-by-default",
376
+ })).rejects.toThrow(/payments\.products\.free\.prices must not be one of the following values: include-by-default/);
377
+ });