@hexclave/shared 1.0.3 → 1.0.5
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.
- package/dist/ai/unified-prompts/reminders.js +4 -3
- package/dist/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +216 -29
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
- package/dist/config/schema.d.ts +71 -71
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +5 -5
- package/dist/config/schema.js.map +1 -1
- package/dist/config-authoring.d.ts +4 -4
- package/dist/config-authoring.d.ts.map +1 -1
- package/dist/config-authoring.js +2 -2
- package/dist/config-authoring.js.map +1 -1
- package/dist/config-rendering.d.ts +4 -4
- package/dist/config-rendering.d.ts.map +1 -1
- package/dist/config-rendering.js +19 -18
- package/dist/config-rendering.js.map +1 -1
- package/dist/esm/ai/unified-prompts/reminders.js +4 -3
- package/dist/esm/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts +3 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +215 -30
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.d.ts.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js +1 -0
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-index.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +18 -6
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +23 -8
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.js.map +1 -1
- package/dist/esm/config/schema.d.ts +71 -71
- package/dist/esm/config/schema.d.ts.map +1 -1
- package/dist/esm/config/schema.js +5 -5
- package/dist/esm/config/schema.js.map +1 -1
- package/dist/esm/config-authoring.d.ts +4 -4
- package/dist/esm/config-authoring.d.ts.map +1 -1
- package/dist/esm/config-authoring.js +2 -2
- package/dist/esm/config-authoring.js.map +1 -1
- package/dist/esm/config-rendering.d.ts +4 -4
- package/dist/esm/config-rendering.d.ts.map +1 -1
- package/dist/esm/config-rendering.js +15 -14
- package/dist/esm/config-rendering.js.map +1 -1
- package/dist/esm/helpers/vault/client-side.d.ts.map +1 -1
- package/dist/esm/helpers/vault/client-side.js.map +1 -1
- package/dist/esm/helpers/vault/server-side.d.ts.map +1 -1
- package/dist/esm/helpers/vault/server-side.js.map +1 -1
- package/dist/esm/hexclave-config-file.d.ts +15 -0
- package/dist/esm/hexclave-config-file.d.ts.map +1 -0
- package/dist/esm/{stack-config-file.js → hexclave-config-file.js} +7 -7
- package/dist/esm/hexclave-config-file.js.map +1 -0
- package/dist/esm/hooks/use-async-callback.js +1 -1
- package/dist/esm/hooks/use-async-external-store.js +1 -1
- package/dist/esm/hooks/use-strict-memo.js +1 -1
- package/dist/esm/interface/admin-metrics.d.ts +4 -4
- package/dist/esm/interface/admin-metrics.js.map +1 -1
- package/dist/esm/interface/client-interface.js +2 -2
- package/dist/esm/interface/client-interface.js.map +1 -1
- package/dist/esm/interface/conversations.d.ts +13 -13
- package/dist/esm/interface/crud/current-user.d.ts +9 -9
- package/dist/esm/interface/crud/email-outbox.d.ts +112 -112
- package/dist/esm/interface/crud/products.d.ts +1 -1
- package/dist/esm/interface/crud/project-api-keys.d.ts +2 -2
- package/dist/esm/interface/crud/project-permissions.js +5 -5
- package/dist/esm/interface/crud/project-permissions.js.map +1 -1
- package/dist/esm/interface/crud/projects.d.ts +28 -28
- package/dist/esm/interface/crud/team-member-profiles.d.ts +22 -22
- package/dist/esm/interface/crud/team-permissions.js +5 -5
- package/dist/esm/interface/crud/team-permissions.js.map +1 -1
- package/dist/esm/interface/crud/users.d.ts +14 -14
- package/dist/esm/interface/page-component-versions.js +107 -107
- package/dist/esm/interface/page-component-versions.js.map +1 -1
- package/dist/esm/interface/webhooks.d.ts +4 -4
- package/dist/esm/known-errors.js +4 -4
- package/dist/esm/known-errors.js.map +1 -1
- package/dist/esm/schema-fields.d.ts +15 -5
- package/dist/esm/schema-fields.d.ts.map +1 -1
- package/dist/esm/schema-fields.js +26 -16
- package/dist/esm/schema-fields.js.map +1 -1
- package/dist/esm/utils/crypto.d.ts.map +1 -1
- package/dist/esm/utils/crypto.js.map +1 -1
- package/dist/esm/utils/currency-constants.d.ts +6 -0
- package/dist/esm/utils/currency-constants.d.ts.map +1 -1
- package/dist/esm/utils/currency-constants.js.map +1 -1
- package/dist/esm/utils/dev-env-state-path.d.ts +3 -3
- package/dist/esm/utils/dev-env-state-path.d.ts.map +1 -1
- package/dist/esm/utils/dev-env-state-path.js +4 -4
- package/dist/esm/utils/dev-env-state-path.js.map +1 -1
- package/dist/esm/utils/errors.js +2 -2
- package/dist/esm/utils/errors.js.map +1 -1
- package/dist/esm/utils/esbuild.d.ts.map +1 -1
- package/dist/esm/utils/esbuild.js +0 -1
- package/dist/esm/utils/esbuild.js.map +1 -1
- package/dist/esm/utils/featurebase.d.ts +3 -3
- package/dist/esm/utils/featurebase.d.ts.map +1 -1
- package/dist/esm/utils/featurebase.js +15 -15
- package/dist/esm/utils/featurebase.js.map +1 -1
- package/dist/esm/utils/fs.js +6 -6
- package/dist/esm/utils/fs.js.map +1 -1
- package/dist/esm/utils/globals.d.ts.map +1 -1
- package/dist/esm/utils/globals.js +10 -10
- package/dist/esm/utils/globals.js.map +1 -1
- package/dist/esm/utils/jwt.d.ts.map +1 -1
- package/dist/esm/utils/jwt.js +3 -3
- package/dist/esm/utils/jwt.js.map +1 -1
- package/dist/esm/utils/redirect-urls.d.ts +3 -3
- package/dist/esm/utils/redirect-urls.d.ts.map +1 -1
- package/dist/esm/utils/redirect-urls.js +5 -5
- package/dist/esm/utils/redirect-urls.js.map +1 -1
- package/dist/esm/utils/urls.js.map +1 -1
- package/dist/helpers/vault/client-side.d.ts.map +1 -1
- package/dist/helpers/vault/client-side.js.map +1 -1
- package/dist/helpers/vault/server-side.d.ts.map +1 -1
- package/dist/helpers/vault/server-side.js.map +1 -1
- package/dist/hexclave-config-file.d.ts +15 -0
- package/dist/hexclave-config-file.d.ts.map +1 -0
- package/dist/{stack-config-file.js → hexclave-config-file.js} +8 -8
- package/dist/hexclave-config-file.js.map +1 -0
- package/dist/hooks/use-async-callback.js +1 -1
- package/dist/hooks/use-async-external-store.js +1 -1
- package/dist/hooks/use-strict-memo.js +1 -1
- package/dist/interface/admin-metrics.d.ts +4 -4
- package/dist/interface/admin-metrics.js.map +1 -1
- package/dist/interface/client-interface.js +2 -2
- package/dist/interface/client-interface.js.map +1 -1
- package/dist/interface/conversations.d.ts +13 -13
- package/dist/interface/crud/current-user.d.ts +9 -9
- package/dist/interface/crud/email-outbox.d.ts +112 -112
- package/dist/interface/crud/products.d.ts +1 -1
- package/dist/interface/crud/project-api-keys.d.ts +2 -2
- package/dist/interface/crud/project-permissions.js +5 -5
- package/dist/interface/crud/project-permissions.js.map +1 -1
- package/dist/interface/crud/projects.d.ts +28 -28
- package/dist/interface/crud/team-member-profiles.d.ts +22 -22
- package/dist/interface/crud/team-permissions.js +5 -5
- package/dist/interface/crud/team-permissions.js.map +1 -1
- package/dist/interface/crud/users.d.ts +14 -14
- package/dist/interface/page-component-versions.js +107 -107
- package/dist/interface/page-component-versions.js.map +1 -1
- package/dist/interface/webhooks.d.ts +4 -4
- package/dist/known-errors.js +4 -4
- package/dist/known-errors.js.map +1 -1
- package/dist/schema-fields.d.ts +15 -5
- package/dist/schema-fields.d.ts.map +1 -1
- package/dist/schema-fields.js +26 -16
- package/dist/schema-fields.js.map +1 -1
- package/dist/utils/crypto.d.ts.map +1 -1
- package/dist/utils/crypto.js.map +1 -1
- package/dist/utils/currency-constants.d.ts +6 -0
- package/dist/utils/currency-constants.d.ts.map +1 -1
- package/dist/utils/currency-constants.js.map +1 -1
- package/dist/utils/dev-env-state-path.d.ts +3 -3
- package/dist/utils/dev-env-state-path.d.ts.map +1 -1
- package/dist/utils/dev-env-state-path.js +5 -5
- package/dist/utils/dev-env-state-path.js.map +1 -1
- package/dist/utils/errors.js +2 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/esbuild.d.ts.map +1 -1
- package/dist/utils/esbuild.js +0 -1
- package/dist/utils/esbuild.js.map +1 -1
- package/dist/utils/featurebase.d.ts +3 -3
- package/dist/utils/featurebase.d.ts.map +1 -1
- package/dist/utils/featurebase.js +15 -15
- package/dist/utils/featurebase.js.map +1 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/globals.d.ts.map +1 -1
- package/dist/utils/globals.js +10 -10
- package/dist/utils/globals.js.map +1 -1
- package/dist/utils/jwt.d.ts.map +1 -1
- package/dist/utils/jwt.js +3 -3
- package/dist/utils/jwt.js.map +1 -1
- package/dist/utils/redirect-urls.d.ts +3 -3
- package/dist/utils/redirect-urls.d.ts.map +1 -1
- package/dist/utils/redirect-urls.js +5 -5
- package/dist/utils/redirect-urls.js.map +1 -1
- package/dist/utils/urls.js.map +1 -1
- package/package.json +2 -1
- package/src/ai/image-limits.ts +62 -0
- package/src/ai/llms/llms.ts +36 -0
- package/src/ai/unified-prompts/reminders.ts +27 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts +1047 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/brain.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/cli-help.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/config-docs.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/custom-components-instructions.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/dashboard-instructions.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/docs-index.ts +80 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.ts +322 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/openapi-specs.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/sdk-interface-source.ts +5 -0
- package/src/ai/unified-prompts/skill-site-prompt.ts +72 -0
- package/src/apps/apps-config.ts +177 -0
- package/src/apps/apps-ui.tsx +112 -0
- package/src/config/README.md +154 -0
- package/src/config/db-sync-mappings.ts +2293 -0
- package/src/config/format.ts +388 -0
- package/src/config/migrate-catalogs-to-product-lines.ts +475 -0
- package/src/config/schema-fuzzer.test.ts +377 -0
- package/src/config/schema.ts +1507 -0
- package/src/config-authoring.test.ts +52 -0
- package/src/config-authoring.ts +37 -0
- package/src/config-rendering.ts +142 -0
- package/src/crud.tsx +275 -0
- package/src/global.d.ts +1 -0
- package/src/helpers/emails.ts +250 -0
- package/src/helpers/init-prompt.ts +39 -0
- package/src/helpers/password.ts +16 -0
- package/src/helpers/production-mode.ts +58 -0
- package/src/helpers/support-sla.test.ts +124 -0
- package/src/helpers/support-sla.ts +93 -0
- package/src/helpers/vault/client-side.ts +92 -0
- package/src/helpers/vault/server-side.ts +153 -0
- package/src/hexclave-config-file.ts +120 -0
- package/src/hooks/use-async-callback.tsx +43 -0
- package/src/hooks/use-async-external-store.tsx +24 -0
- package/src/hooks/use-hash.tsx +14 -0
- package/src/hooks/use-hover.tsx +88 -0
- package/src/hooks/use-strict-memo.tsx +157 -0
- package/src/index.ts +17 -0
- package/src/interface/admin-interface.ts +1043 -0
- package/src/interface/admin-metrics.ts +214 -0
- package/src/interface/client-interface.test.ts +765 -0
- package/src/interface/client-interface.ts +2586 -0
- package/src/interface/conversations.ts +109 -0
- package/src/interface/crud/analytics.ts +11 -0
- package/src/interface/crud/connected-accounts.ts +52 -0
- package/src/interface/crud/contact-channels.ts +74 -0
- package/src/interface/crud/current-user.ts +72 -0
- package/src/interface/crud/email-outbox.ts +263 -0
- package/src/interface/crud/email-templates.ts +50 -0
- package/src/interface/crud/emails.ts +22 -0
- package/src/interface/crud/internal-api-keys.ts +69 -0
- package/src/interface/crud/invoices.ts +36 -0
- package/src/interface/crud/items.ts +24 -0
- package/src/interface/crud/notification-preferences.ts +33 -0
- package/src/interface/crud/oauth-providers.ts +91 -0
- package/src/interface/crud/products.ts +42 -0
- package/src/interface/crud/project-api-keys.ts +100 -0
- package/src/interface/crud/project-permissions.ts +118 -0
- package/src/interface/crud/projects.ts +229 -0
- package/src/interface/crud/session-replays.ts +85 -0
- package/src/interface/crud/sessions.ts +66 -0
- package/src/interface/crud/sign-up-rules.ts +12 -0
- package/src/interface/crud/svix-token.ts +20 -0
- package/src/interface/crud/team-invitation-details.ts +22 -0
- package/src/interface/crud/team-invitation.ts +35 -0
- package/src/interface/crud/team-member-profiles.ts +61 -0
- package/src/interface/crud/team-memberships.ts +56 -0
- package/src/interface/crud/team-permissions.ts +119 -0
- package/src/interface/crud/teams.ts +142 -0
- package/src/interface/crud/transactions.ts +131 -0
- package/src/interface/crud/users.ts +185 -0
- package/src/interface/handler-urls.ts +74 -0
- package/src/interface/page-component-versions.ts +1702 -0
- package/src/interface/server-interface.ts +1146 -0
- package/src/interface/webhooks.ts +28 -0
- package/src/known-errors.tsx +2031 -0
- package/src/local-emulator.ts +5 -0
- package/src/payments/payment-methods.ts +167 -0
- package/src/payments/stripe-limits.ts +18 -0
- package/src/plans.ts +107 -0
- package/src/schema-fields.ts +944 -0
- package/src/sessions.ts +310 -0
- package/src/utils/api-keys.tsx +122 -0
- package/src/utils/arrays.tsx +248 -0
- package/src/utils/auth-methods.ts +8 -0
- package/src/utils/base64.tsx +24 -0
- package/src/utils/booleans.tsx +34 -0
- package/src/utils/browser-compat.tsx +17 -0
- package/src/utils/bytes.tsx +280 -0
- package/src/utils/caches.tsx +280 -0
- package/src/utils/cel-fields.ts +92 -0
- package/src/utils/cloud-hosts.tsx +92 -0
- package/src/utils/compile-time.tsx +11 -0
- package/src/utils/country-codes.ts +39 -0
- package/src/utils/crypto.tsx +174 -0
- package/src/utils/currencies.tsx +53 -0
- package/src/utils/currency-constants.tsx +51 -0
- package/src/utils/dates.tsx +246 -0
- package/src/utils/dev-env-state-path.ts +14 -0
- package/src/utils/dom.tsx +7 -0
- package/src/utils/env.tsx +117 -0
- package/src/utils/errors.tsx +284 -0
- package/src/utils/esbuild.tsx +235 -0
- package/src/utils/featurebase.tsx +247 -0
- package/src/utils/fs.tsx +33 -0
- package/src/utils/functions.tsx +22 -0
- package/src/utils/geo.tsx +16 -0
- package/src/utils/globals.tsx +48 -0
- package/src/utils/hashes.tsx +52 -0
- package/src/utils/html.tsx +60 -0
- package/src/utils/http.tsx +91 -0
- package/src/utils/ips.tsx +47 -0
- package/src/utils/json.tsx +200 -0
- package/src/utils/jsx-editable-transpiler.test.ts +156 -0
- package/src/utils/jsx-editable-transpiler.tsx +401 -0
- package/src/utils/jwt.tsx +170 -0
- package/src/utils/locks.tsx +71 -0
- package/src/utils/maps.tsx +407 -0
- package/src/utils/math.tsx +18 -0
- package/src/utils/monkey-patch.tsx +29 -0
- package/src/utils/node-http.tsx +47 -0
- package/src/utils/numbers.tsx +82 -0
- package/src/utils/oauth.tsx +9 -0
- package/src/utils/objects.tsx +581 -0
- package/src/utils/paginated-lists.test.ts +1039 -0
- package/src/utils/paginated-lists.tsx +479 -0
- package/src/utils/passkey.tsx +1 -0
- package/src/utils/promises.tsx +540 -0
- package/src/utils/proxies.tsx +212 -0
- package/src/utils/react.tsx +308 -0
- package/src/utils/redirect-urls.tsx +299 -0
- package/src/utils/regex.tsx +10 -0
- package/src/utils/results.tsx +411 -0
- package/src/utils/sentry.tsx +20 -0
- package/src/utils/stores.tsx +238 -0
- package/src/utils/strings.nicify.test.ts +253 -0
- package/src/utils/strings.tsx +723 -0
- package/src/utils/telemetry.tsx +37 -0
- package/src/utils/turnstile-browser.ts +106 -0
- package/src/utils/turnstile-flow.test.ts +101 -0
- package/src/utils/turnstile-flow.ts +266 -0
- package/src/utils/turnstile.ts +34 -0
- package/src/utils/typed-arrays.tsx +17 -0
- package/src/utils/types.tsx +208 -0
- package/src/utils/unicode.tsx +24 -0
- package/src/utils/urls.tsx +411 -0
- package/src/utils/uuids.tsx +47 -0
- package/dist/esm/stack-config-file.d.ts +0 -15
- package/dist/esm/stack-config-file.d.ts.map +0 -1
- package/dist/esm/stack-config-file.js.map +0 -1
- package/dist/stack-config-file.d.ts +0 -15
- package/dist/stack-config-file.d.ts.map +0 -1
- 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
|
+
});
|