@stackframe/stack-shared 2.8.64 → 2.8.66

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 (65) hide show
  1. package/dist/config/db-sync-mappings.d.mts +17 -0
  2. package/dist/config/db-sync-mappings.d.ts +17 -0
  3. package/dist/config/db-sync-mappings.js +195 -0
  4. package/dist/config/db-sync-mappings.js.map +1 -0
  5. package/dist/config/schema-fuzzer.test.js +24 -0
  6. package/dist/config/schema-fuzzer.test.js.map +1 -1
  7. package/dist/config/schema.d.mts +198 -24
  8. package/dist/config/schema.d.ts +198 -24
  9. package/dist/config/schema.js +56 -3
  10. package/dist/config/schema.js.map +1 -1
  11. package/dist/esm/config/db-sync-mappings.js +170 -0
  12. package/dist/esm/config/db-sync-mappings.js.map +1 -0
  13. package/dist/esm/config/schema-fuzzer.test.js +24 -0
  14. package/dist/esm/config/schema-fuzzer.test.js.map +1 -1
  15. package/dist/esm/config/schema.js +56 -3
  16. package/dist/esm/config/schema.js.map +1 -1
  17. package/dist/esm/interface/admin-interface.js.map +1 -1
  18. package/dist/esm/interface/client-interface.js.map +1 -1
  19. package/dist/esm/interface/crud/current-user.js +3 -1
  20. package/dist/esm/interface/crud/current-user.js.map +1 -1
  21. package/dist/esm/interface/crud/sign-up-rules.js +1 -0
  22. package/dist/esm/interface/crud/sign-up-rules.js.map +1 -0
  23. package/dist/esm/interface/crud/users.js +40 -6
  24. package/dist/esm/interface/crud/users.js.map +1 -1
  25. package/dist/esm/known-errors.js +13 -0
  26. package/dist/esm/known-errors.js.map +1 -1
  27. package/dist/esm/schema-fields.js +6 -4
  28. package/dist/esm/schema-fields.js.map +1 -1
  29. package/dist/esm/utils/types.js.map +1 -1
  30. package/dist/interface/admin-interface.d.mts +2 -4
  31. package/dist/interface/admin-interface.d.ts +2 -4
  32. package/dist/interface/admin-interface.js.map +1 -1
  33. package/dist/interface/client-interface.js.map +1 -1
  34. package/dist/interface/crud/current-user.d.mts +22 -2
  35. package/dist/interface/crud/current-user.d.ts +22 -2
  36. package/dist/interface/crud/current-user.js +3 -1
  37. package/dist/interface/crud/current-user.js.map +1 -1
  38. package/dist/interface/crud/project-api-keys.d.mts +2 -2
  39. package/dist/interface/crud/project-api-keys.d.ts +2 -2
  40. package/dist/interface/crud/sign-up-rules.d.mts +13 -0
  41. package/dist/interface/crud/sign-up-rules.d.ts +13 -0
  42. package/dist/interface/crud/sign-up-rules.js +19 -0
  43. package/dist/interface/crud/sign-up-rules.js.map +1 -0
  44. package/dist/interface/crud/team-member-profiles.d.mts +14 -2
  45. package/dist/interface/crud/team-member-profiles.d.ts +14 -2
  46. package/dist/interface/crud/users.d.mts +52 -4
  47. package/dist/interface/crud/users.d.ts +52 -4
  48. package/dist/interface/crud/users.js +40 -6
  49. package/dist/interface/crud/users.js.map +1 -1
  50. package/dist/interface/webhooks.d.mts +14 -2
  51. package/dist/interface/webhooks.d.ts +14 -2
  52. package/dist/known-errors.d.mts +5 -2
  53. package/dist/known-errors.d.ts +5 -2
  54. package/dist/known-errors.js +13 -0
  55. package/dist/known-errors.js.map +1 -1
  56. package/dist/schema-fields.d.mts +9 -3
  57. package/dist/schema-fields.d.ts +9 -3
  58. package/dist/schema-fields.js +7 -4
  59. package/dist/schema-fields.js.map +1 -1
  60. package/dist/sessions.d.mts +2 -2
  61. package/dist/sessions.d.ts +2 -2
  62. package/dist/utils/types.d.mts +2 -2
  63. package/dist/utils/types.d.ts +2 -2
  64. package/dist/utils/types.js.map +1 -1
  65. package/package.json +1 -1
@@ -0,0 +1,170 @@
1
+ // src/config/db-sync-mappings.ts
2
+ var DEFAULT_DB_SYNC_MAPPINGS = {
3
+ "users": {
4
+ sourceTables: { "ProjectUser": "ProjectUser" },
5
+ targetTable: "users",
6
+ targetTableSchemas: {
7
+ postgres: `
8
+ CREATE TABLE IF NOT EXISTS "users" (
9
+ "id" uuid PRIMARY KEY NOT NULL,
10
+ "display_name" text,
11
+ "profile_image_url" text,
12
+ "primary_email" text,
13
+ "primary_email_verified" boolean NOT NULL DEFAULT false,
14
+ "signed_up_at" timestamp without time zone NOT NULL,
15
+ "client_metadata" jsonb NOT NULL DEFAULT '{}'::jsonb,
16
+ "client_read_only_metadata" jsonb NOT NULL DEFAULT '{}'::jsonb,
17
+ "server_metadata" jsonb NOT NULL DEFAULT '{}'::jsonb,
18
+ "is_anonymous" boolean NOT NULL DEFAULT false
19
+ );
20
+ REVOKE ALL ON "users" FROM PUBLIC;
21
+ GRANT SELECT ON "users" TO PUBLIC;
22
+
23
+ CREATE TABLE IF NOT EXISTS "_stack_sync_metadata" (
24
+ "mapping_name" text PRIMARY KEY NOT NULL,
25
+ "last_synced_sequence_id" bigint NOT NULL DEFAULT -1,
26
+ "updated_at" timestamp without time zone NOT NULL DEFAULT now()
27
+ );
28
+ `.trim()
29
+ },
30
+ internalDbFetchQuery: `
31
+ SELECT *
32
+ FROM (
33
+ SELECT
34
+ "ProjectUser"."projectUserId" AS "id",
35
+ "ProjectUser"."displayName" AS "display_name",
36
+ "ProjectUser"."profileImageUrl" AS "profile_image_url",
37
+ (
38
+ SELECT "ContactChannel"."value"
39
+ FROM "ContactChannel"
40
+ WHERE "ContactChannel"."projectUserId" = "ProjectUser"."projectUserId"
41
+ AND "ContactChannel"."tenancyId" = "ProjectUser"."tenancyId"
42
+ AND "ContactChannel"."type" = 'EMAIL'
43
+ AND "ContactChannel"."isPrimary" = 'TRUE'
44
+ LIMIT 1
45
+ ) AS "primary_email",
46
+ COALESCE(
47
+ (
48
+ SELECT "ContactChannel"."isVerified"
49
+ FROM "ContactChannel"
50
+ WHERE "ContactChannel"."projectUserId" = "ProjectUser"."projectUserId"
51
+ AND "ContactChannel"."tenancyId" = "ProjectUser"."tenancyId"
52
+ AND "ContactChannel"."type" = 'EMAIL'
53
+ AND "ContactChannel"."isPrimary" = 'TRUE'
54
+ LIMIT 1
55
+ ),
56
+ false
57
+ ) AS "primary_email_verified",
58
+ "ProjectUser"."createdAt" AS "signed_up_at",
59
+ COALESCE("ProjectUser"."clientMetadata", '{}'::jsonb) AS "client_metadata",
60
+ COALESCE("ProjectUser"."clientReadOnlyMetadata", '{}'::jsonb) AS "client_read_only_metadata",
61
+ COALESCE("ProjectUser"."serverMetadata", '{}'::jsonb) AS "server_metadata",
62
+ "ProjectUser"."isAnonymous" AS "is_anonymous",
63
+ "ProjectUser"."sequenceId" AS "sequence_id",
64
+ "ProjectUser"."tenancyId",
65
+ false AS "is_deleted"
66
+ FROM "ProjectUser"
67
+ WHERE "ProjectUser"."tenancyId" = $1::uuid
68
+
69
+ UNION ALL
70
+
71
+ SELECT
72
+ ("DeletedRow"."primaryKey"->>'projectUserId')::uuid AS "id",
73
+ NULL::text AS "display_name",
74
+ NULL::text AS "profile_image_url",
75
+ NULL::text AS "primary_email",
76
+ false AS "primary_email_verified",
77
+ "DeletedRow"."deletedAt"::timestamp without time zone AS "signed_up_at",
78
+ '{}'::jsonb AS "client_metadata",
79
+ '{}'::jsonb AS "client_read_only_metadata",
80
+ '{}'::jsonb AS "server_metadata",
81
+ false AS "is_anonymous",
82
+ "DeletedRow"."sequenceId" AS "sequence_id",
83
+ "DeletedRow"."tenancyId",
84
+ true AS "is_deleted"
85
+ FROM "DeletedRow"
86
+ WHERE
87
+ "DeletedRow"."tenancyId" = $1::uuid
88
+ AND "DeletedRow"."tableName" = 'ProjectUser'
89
+ ) AS "_src"
90
+ WHERE "sequence_id" IS NOT NULL
91
+ AND "sequence_id" > $2::bigint
92
+ ORDER BY "sequence_id" ASC
93
+ LIMIT 1000
94
+ `.trim(),
95
+ // Last parameter = mapping_name (for metadata tracking)
96
+ externalDbUpdateQueries: {
97
+ postgres: `
98
+ WITH params AS (
99
+ SELECT
100
+ $1::uuid AS "id",
101
+ $2::text AS "display_name",
102
+ $3::text AS "profile_image_url",
103
+ $4::text AS "primary_email",
104
+ $5::boolean AS "primary_email_verified",
105
+ $6::timestamp without time zone AS "signed_up_at",
106
+ $7::jsonb AS "client_metadata",
107
+ $8::jsonb AS "client_read_only_metadata",
108
+ $9::jsonb AS "server_metadata",
109
+ $10::boolean AS "is_anonymous",
110
+ $11::bigint AS "sequence_id",
111
+ $12::boolean AS "is_deleted",
112
+ $13::text AS "mapping_name"
113
+ ),
114
+ deleted AS (
115
+ DELETE FROM "users" u
116
+ USING params p
117
+ WHERE p."is_deleted" = true AND u."id" = p."id"
118
+ RETURNING 1
119
+ ),
120
+ upserted AS (
121
+ INSERT INTO "users" (
122
+ "id",
123
+ "display_name",
124
+ "profile_image_url",
125
+ "primary_email",
126
+ "primary_email_verified",
127
+ "signed_up_at",
128
+ "client_metadata",
129
+ "client_read_only_metadata",
130
+ "server_metadata",
131
+ "is_anonymous"
132
+ )
133
+ SELECT
134
+ p."id",
135
+ p."display_name",
136
+ p."profile_image_url",
137
+ p."primary_email",
138
+ p."primary_email_verified",
139
+ p."signed_up_at",
140
+ p."client_metadata",
141
+ p."client_read_only_metadata",
142
+ p."server_metadata",
143
+ p."is_anonymous"
144
+ FROM params p
145
+ WHERE p."is_deleted" = false
146
+ ON CONFLICT ("id") DO UPDATE SET
147
+ "display_name" = EXCLUDED."display_name",
148
+ "profile_image_url" = EXCLUDED."profile_image_url",
149
+ "primary_email" = EXCLUDED."primary_email",
150
+ "primary_email_verified" = EXCLUDED."primary_email_verified",
151
+ "signed_up_at" = EXCLUDED."signed_up_at",
152
+ "client_metadata" = EXCLUDED."client_metadata",
153
+ "client_read_only_metadata" = EXCLUDED."client_read_only_metadata",
154
+ "server_metadata" = EXCLUDED."server_metadata",
155
+ "is_anonymous" = EXCLUDED."is_anonymous"
156
+ RETURNING 1
157
+ )
158
+ INSERT INTO "_stack_sync_metadata" ("mapping_name", "last_synced_sequence_id", "updated_at")
159
+ SELECT p."mapping_name", p."sequence_id", now() FROM params p
160
+ ON CONFLICT ("mapping_name") DO UPDATE SET
161
+ "last_synced_sequence_id" = GREATEST("_stack_sync_metadata"."last_synced_sequence_id", EXCLUDED."last_synced_sequence_id"),
162
+ "updated_at" = now();
163
+ `.trim()
164
+ }
165
+ }
166
+ };
167
+ export {
168
+ DEFAULT_DB_SYNC_MAPPINGS
169
+ };
170
+ //# sourceMappingURL=db-sync-mappings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/config/db-sync-mappings.ts"],"sourcesContent":["export const DEFAULT_DB_SYNC_MAPPINGS = {\n \"users\": {\n sourceTables: { \"ProjectUser\": \"ProjectUser\" },\n targetTable: \"users\",\n targetTableSchemas: {\n postgres: `\n CREATE TABLE IF NOT EXISTS \"users\" (\n \"id\" uuid PRIMARY KEY NOT NULL,\n \"display_name\" text,\n \"profile_image_url\" text,\n \"primary_email\" text,\n \"primary_email_verified\" boolean NOT NULL DEFAULT false,\n \"signed_up_at\" timestamp without time zone NOT NULL,\n \"client_metadata\" jsonb NOT NULL DEFAULT '{}'::jsonb,\n \"client_read_only_metadata\" jsonb NOT NULL DEFAULT '{}'::jsonb,\n \"server_metadata\" jsonb NOT NULL DEFAULT '{}'::jsonb,\n \"is_anonymous\" boolean NOT NULL DEFAULT false\n );\n REVOKE ALL ON \"users\" FROM PUBLIC;\n GRANT SELECT ON \"users\" TO PUBLIC;\n\n CREATE TABLE IF NOT EXISTS \"_stack_sync_metadata\" (\n \"mapping_name\" text PRIMARY KEY NOT NULL,\n \"last_synced_sequence_id\" bigint NOT NULL DEFAULT -1,\n \"updated_at\" timestamp without time zone NOT NULL DEFAULT now()\n );\n `.trim(),\n },\n internalDbFetchQuery: `\n SELECT *\n FROM (\n SELECT\n \"ProjectUser\".\"projectUserId\" AS \"id\",\n \"ProjectUser\".\"displayName\" AS \"display_name\",\n \"ProjectUser\".\"profileImageUrl\" AS \"profile_image_url\",\n (\n SELECT \"ContactChannel\".\"value\"\n FROM \"ContactChannel\"\n WHERE \"ContactChannel\".\"projectUserId\" = \"ProjectUser\".\"projectUserId\"\n AND \"ContactChannel\".\"tenancyId\" = \"ProjectUser\".\"tenancyId\"\n AND \"ContactChannel\".\"type\" = 'EMAIL'\n AND \"ContactChannel\".\"isPrimary\" = 'TRUE'\n LIMIT 1\n ) AS \"primary_email\",\n COALESCE(\n (\n SELECT \"ContactChannel\".\"isVerified\"\n FROM \"ContactChannel\"\n WHERE \"ContactChannel\".\"projectUserId\" = \"ProjectUser\".\"projectUserId\"\n AND \"ContactChannel\".\"tenancyId\" = \"ProjectUser\".\"tenancyId\"\n AND \"ContactChannel\".\"type\" = 'EMAIL'\n AND \"ContactChannel\".\"isPrimary\" = 'TRUE'\n LIMIT 1\n ),\n false\n ) AS \"primary_email_verified\",\n \"ProjectUser\".\"createdAt\" AS \"signed_up_at\",\n COALESCE(\"ProjectUser\".\"clientMetadata\", '{}'::jsonb) AS \"client_metadata\",\n COALESCE(\"ProjectUser\".\"clientReadOnlyMetadata\", '{}'::jsonb) AS \"client_read_only_metadata\",\n COALESCE(\"ProjectUser\".\"serverMetadata\", '{}'::jsonb) AS \"server_metadata\",\n \"ProjectUser\".\"isAnonymous\" AS \"is_anonymous\",\n \"ProjectUser\".\"sequenceId\" AS \"sequence_id\",\n \"ProjectUser\".\"tenancyId\",\n false AS \"is_deleted\"\n FROM \"ProjectUser\"\n WHERE \"ProjectUser\".\"tenancyId\" = $1::uuid\n\n UNION ALL\n\n SELECT\n (\"DeletedRow\".\"primaryKey\"->>'projectUserId')::uuid AS \"id\",\n NULL::text AS \"display_name\",\n NULL::text AS \"profile_image_url\",\n NULL::text AS \"primary_email\",\n false AS \"primary_email_verified\",\n \"DeletedRow\".\"deletedAt\"::timestamp without time zone AS \"signed_up_at\",\n '{}'::jsonb AS \"client_metadata\",\n '{}'::jsonb AS \"client_read_only_metadata\",\n '{}'::jsonb AS \"server_metadata\",\n false AS \"is_anonymous\",\n \"DeletedRow\".\"sequenceId\" AS \"sequence_id\",\n \"DeletedRow\".\"tenancyId\",\n true AS \"is_deleted\"\n FROM \"DeletedRow\"\n WHERE\n \"DeletedRow\".\"tenancyId\" = $1::uuid\n AND \"DeletedRow\".\"tableName\" = 'ProjectUser'\n ) AS \"_src\"\n WHERE \"sequence_id\" IS NOT NULL\n AND \"sequence_id\" > $2::bigint\n ORDER BY \"sequence_id\" ASC\n LIMIT 1000\n `.trim(),\n // Last parameter = mapping_name (for metadata tracking)\n externalDbUpdateQueries: {\n postgres: `\n WITH params AS (\n SELECT\n $1::uuid AS \"id\",\n $2::text AS \"display_name\",\n $3::text AS \"profile_image_url\",\n $4::text AS \"primary_email\",\n $5::boolean AS \"primary_email_verified\",\n $6::timestamp without time zone AS \"signed_up_at\",\n $7::jsonb AS \"client_metadata\",\n $8::jsonb AS \"client_read_only_metadata\",\n $9::jsonb AS \"server_metadata\",\n $10::boolean AS \"is_anonymous\",\n $11::bigint AS \"sequence_id\",\n $12::boolean AS \"is_deleted\",\n $13::text AS \"mapping_name\"\n ),\n deleted AS (\n DELETE FROM \"users\" u\n USING params p\n WHERE p.\"is_deleted\" = true AND u.\"id\" = p.\"id\"\n RETURNING 1\n ),\n upserted AS (\n INSERT INTO \"users\" (\n \"id\",\n \"display_name\",\n \"profile_image_url\",\n \"primary_email\",\n \"primary_email_verified\",\n \"signed_up_at\",\n \"client_metadata\",\n \"client_read_only_metadata\",\n \"server_metadata\",\n \"is_anonymous\"\n )\n SELECT\n p.\"id\",\n p.\"display_name\",\n p.\"profile_image_url\",\n p.\"primary_email\",\n p.\"primary_email_verified\",\n p.\"signed_up_at\",\n p.\"client_metadata\",\n p.\"client_read_only_metadata\",\n p.\"server_metadata\",\n p.\"is_anonymous\"\n FROM params p\n WHERE p.\"is_deleted\" = false\n ON CONFLICT (\"id\") DO UPDATE SET\n \"display_name\" = EXCLUDED.\"display_name\",\n \"profile_image_url\" = EXCLUDED.\"profile_image_url\",\n \"primary_email\" = EXCLUDED.\"primary_email\",\n \"primary_email_verified\" = EXCLUDED.\"primary_email_verified\",\n \"signed_up_at\" = EXCLUDED.\"signed_up_at\",\n \"client_metadata\" = EXCLUDED.\"client_metadata\",\n \"client_read_only_metadata\" = EXCLUDED.\"client_read_only_metadata\",\n \"server_metadata\" = EXCLUDED.\"server_metadata\",\n \"is_anonymous\" = EXCLUDED.\"is_anonymous\"\n RETURNING 1\n )\n INSERT INTO \"_stack_sync_metadata\" (\"mapping_name\", \"last_synced_sequence_id\", \"updated_at\")\n SELECT p.\"mapping_name\", p.\"sequence_id\", now() FROM params p\n ON CONFLICT (\"mapping_name\") DO UPDATE SET\n \"last_synced_sequence_id\" = GREATEST(\"_stack_sync_metadata\".\"last_synced_sequence_id\", EXCLUDED.\"last_synced_sequence_id\"),\n \"updated_at\" = now();\n `.trim(),\n },\n },\n} as const;\n"],"mappings":";AAAO,IAAM,2BAA2B;AAAA,EACtC,SAAS;AAAA,IACP,cAAc,EAAE,eAAe,cAAc;AAAA,IAC7C,aAAa;AAAA,IACb,oBAAoB;AAAA,MAClB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAqBR,KAAK;AAAA,IACT;AAAA,IACA,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEpB,KAAK;AAAA;AAAA,IAEP,yBAAyB;AAAA,MACvB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkER,KAAK;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -33,6 +33,30 @@ var branchSchemaFuzzerConfig = [{
33
33
  allowConnectedAccounts: [true, false]
34
34
  }]
35
35
  }]
36
+ }],
37
+ signUpRules: [{
38
+ "some-rule-id": [{
39
+ enabled: [true, false],
40
+ displayName: ["Block Test Emails", "Allow Only Company Domain"],
41
+ priority: [0, 1, 100],
42
+ condition: ['email.endsWith("@test.com")', 'emailDomain == "company.com"'],
43
+ action: [{
44
+ type: ["allow", "reject", "restrict", "log"],
45
+ message: ["", "Sign up is not allowed for this email"]
46
+ }]
47
+ }]
48
+ }],
49
+ signUpRulesDefaultAction: ["allow", "reject"]
50
+ }],
51
+ dbSync: [{
52
+ externalDatabases: [{
53
+ "some-external-db-id": [{
54
+ type: ["postgres"],
55
+ connectionString: [
56
+ "postgres://user:password@host:port/database",
57
+ "some-connection-string"
58
+ ]
59
+ }]
36
60
  }]
37
61
  }],
38
62
  dataVault: [{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/config/schema-fuzzer.test.ts"],"sourcesContent":["import { ALL_APPS } from \"../apps/apps-config\";\nimport { SUPPORTED_CURRENCIES } from \"../utils/currency-constants\";\nimport { StackAssertionError } from \"../utils/errors\";\nimport { getOrUndefined, isObjectLike, set, typedEntries, typedFromEntries } from \"../utils/objects\";\nimport { nicify } from \"../utils/strings\";\nimport { normalize, override } from \"./format\";\nimport { BranchConfigNormalizedOverride, EnvironmentConfigNormalizedOverride, OrganizationConfigNormalizedOverride, ProjectConfigNormalizedOverride, applyBranchDefaults, applyEnvironmentDefaults, applyOrganizationDefaults, applyProjectDefaults, assertNoConfigOverrideErrors, branchConfigSchema, environmentConfigSchema, migrateConfigOverride, organizationConfigSchema, projectConfigSchema, sanitizeBranchConfig, sanitizeEnvironmentConfig, sanitizeOrganizationConfig, sanitizeProjectConfig } from \"./schema\";\n\ntype FuzzerConfig<T> = ReadonlyArray<T extends object ? ([T] extends [any[]] ? { readonly [K in keyof T]: FuzzerConfig<T[K]> } : Required<{\n [K in keyof T]: FuzzerConfig<T[K]>;\n}> & Record<string, FuzzerConfig<any>>) : T>;\n\nconst projectSchemaFuzzerConfig = [{\n sourceOfTruth: [{\n type: [\"hosted\", \"neon\", \"postgres\"],\n connectionString: [\"\", \"postgres://user:password@host:port/database\", \"THIS IS A STRING LOLOL\"],\n connectionStrings: [{\n \"123-some-branch-id\": [\"\", \"THIS IS A CONNECTION STRING OR SO\"],\n }],\n }],\n}] satisfies FuzzerConfig<ProjectConfigNormalizedOverride>;\n\nconst branchSchemaFuzzerConfig = [{\n apiKeys: [{\n enabled: [{\n team: [true, false],\n user: [true, false],\n }],\n }],\n auth: [{\n allowSignUp: [true, false],\n password: [{\n allowSignIn: [true, false],\n }],\n otp: [{\n allowSignIn: [true, false],\n }],\n passkey: [{\n allowSignIn: [true, false],\n }],\n oauth: [{\n accountMergeStrategy: [\"link_method\", \"raise_error\", \"allow_duplicates\"],\n providers: [{\n \"google\": [{\n type: [\"google\", \"github\", \"x\"] as const,\n allowSignIn: [true, false],\n allowConnectedAccounts: [true, false],\n }],\n }],\n }],\n }],\n dataVault: [{\n stores: [{\n \"some-store-id\": [{\n displayName: [\"Some Store\", \"Some Other Store\"],\n }],\n \"some-other-store-id\": [{\n displayName: [\"Some Store\", \"Some Other Store\"],\n }],\n }],\n }],\n payments: [{\n blockNewPurchases: [false, true],\n autoPay: [{\n interval: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n }],\n productLines: [{\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n customerType: [\"user\", \"team\", \"custom\"] as const,\n }],\n }],\n catalogs: [{ // ensure migration works\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n }],\n }],\n groups: [{ // ensure migration works\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n }],\n }],\n items: [{\n \"some-item-id\": [{\n customerType: [\"user\", \"team\", \"custom\"] as const,\n displayName: [\"Some Item\", \"Some Other Item\"],\n }],\n }],\n products: [{\n \"some-product-id\": [{\n displayName: [\"Some Product\", \"Some Other Product\"],\n customerType: [\"user\", \"team\", \"custom\"] as const,\n freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n serverOnly: [true, false],\n stackable: [true, false],\n productLineId: [\"some-product-line-id\", \"some-other-product-line-id\"],\n catalogId: [\"some-product-line-id\", \"some-other-product-line-id\"], // ensure migration works\n groupId: [\"some-product-line-id\", \"some-other-product-line-id\"], // ensure migration works\n isAddOnTo: [false, { \"some-product-id\": [true], \"some-other-product-id\": [true] }] as const,\n prices: [\"include-by-default\" as \"include-by-default\", {\n \"some-price-id\": [{\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, [\"100_00\", \"not a number\", \"Infinity\", \"0\"]])),\n interval: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n serverOnly: [true, false],\n freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n }],\n }],\n includedItems: [{\n \"some-item-id\": [{\n quantity: [0, 1, -3, 100, 0.333, Infinity],\n repeat: [\"never\", [[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n expires: [\"never\", \"when-purchase-expires\", \"when-repeated\"] as const,\n }],\n }],\n }],\n }],\n }],\n emails: [{\n themes: [{\n \"12345678-1234-4234-9234-123456789012\": [{\n displayName: [\"Some Theme\", \"Some Other Theme\"],\n tsxSource: [\"\", \"some typescript source code\"],\n }],\n }],\n selectedThemeId: [\"some-theme-id\", \"some-other-theme-id\"],\n templates: [{\n \"12345678-1234-4234-9234-123456789012\": [{\n themeId: [\"some-theme-id\", \"some-other-theme-id\"],\n displayName: [\"Some Template\", \"Some Other Template\"],\n tsxSource: [\"\", \"some typescript source code\"],\n }],\n }],\n }],\n teams: [{\n createPersonalTeamOnSignUp: [true, false],\n allowClientTeamCreation: [true, false],\n }],\n users: [{\n allowClientUserDeletion: [true, false],\n }],\n rbac: [{\n permissions: [{\n \"some_permission_id\": [{\n containedPermissionIds: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n description: [\"Some Permission\", \"Some Other Permission\"],\n scope: [\"team\", \"project\"] as const,\n }],\n }],\n defaultPermissions: [{\n teamCreator: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n teamMember: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n signUp: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n }],\n }],\n domains: [{}],\n apps: [{\n installed: [typedFromEntries(typedEntries(ALL_APPS).map(([key, value]) => [key, [{\n enabled: [true, false],\n }]]))],\n }],\n onboarding: [{\n requireEmailVerification: [true, false],\n }],\n}] satisfies FuzzerConfig<BranchConfigNormalizedOverride>;\n\nconst environmentSchemaFuzzerConfig = [{\n ...branchSchemaFuzzerConfig[0],\n auth: [{\n ...branchSchemaFuzzerConfig[0].auth[0],\n oauth: [{\n ...branchSchemaFuzzerConfig[0].auth[0].oauth[0],\n providers: [typedFromEntries(typedEntries(branchSchemaFuzzerConfig[0].auth[0].oauth[0].providers[0]).map(([key, value]) => [key, [{\n ...value[0],\n isShared: [true, false],\n clientId: [\"some-client-id\"],\n clientSecret: [\"some-client-secret\"],\n facebookConfigId: [\"some-facebook-config-id\"],\n microsoftTenantId: [\"some-microsoft-tenant-id\"],\n appleBundles: [{ \"some-bundle-id\": [{ bundleId: [\"com.example.app\"] }] }],\n }]]))] as const,\n }],\n }],\n domains: [{\n allowLocalhost: [true, false],\n trustedDomains: [{\n \"some-domain-id\": [{\n baseUrl: [\"https://example.com/something-here\"],\n handlerPath: [\"/something-here\"],\n }],\n }],\n }],\n emails: [{\n ...branchSchemaFuzzerConfig[0].emails[0],\n server: [{\n isShared: [true, false],\n provider: [\"resend\", \"smtp\"] as const,\n host: [\"example.com\", \"://super weird host that's not valid\"],\n port: [1234, 0.12543, -100, Infinity],\n username: [\"some-username\", \"some username with a space\"],\n password: [\"some-password\", \"some password with a space\"],\n senderName: [\"Some Sender\"],\n senderEmail: [\"some-sender@example.com\", \"some invalid email\"],\n }],\n }],\n payments: [{\n ...branchSchemaFuzzerConfig[0].payments[0],\n testMode: [false, true],\n }],\n}] satisfies FuzzerConfig<EnvironmentConfigNormalizedOverride>;\n\nconst organizationSchemaFuzzerConfig = environmentSchemaFuzzerConfig satisfies FuzzerConfig<OrganizationConfigNormalizedOverride>;\n\nfunction setDeep<T>(obj: T, path: string[], value: any) {\n if (!isObjectLike(obj)) return obj;\n\n if (path.length === 0) {\n throw new Error(\"Path is empty\");\n } else if (path.length === 1) {\n set(obj as any, path[0], value);\n } else {\n const [key, ...rest] = path;\n setDeep(getOrUndefined(obj as any, key), rest, value);\n }\n}\n\nfunction createFuzzerInput<T>(config: FuzzerConfig<T>, progress: number): T {\n progress = Math.min(1, 2 * progress);\n const createShouldRandom = (strength: number) => {\n const chance = Math.random() * strength * 1.2 - 0.1;\n return () => Math.random() < chance;\n };\n const createShouldObjectDependent = (strength: number) => {\n const objectChance = Math.random() * strength * 1.2 - 0.1;\n const primitiveChance = Math.random() * strength * 1.2 - 0.1;\n return (v: any) => Math.random() * Math.random() < (isObjectLike(v) ? objectChance : primitiveChance);\n };\n\n const shouldKeep = createShouldObjectDependent(progress * 1);\n const shouldMakeNested = createShouldObjectDependent(1.25);\n const shouldNull = createShouldRandom(0.25);\n\n let res: any;\n const recurse = <U>(outputPath: string[], config: FuzzerConfig<U>, forceNested: boolean, forceNonNull: boolean) => {\n let subConfig: any = config[Math.floor(Math.random() * config.length)];\n const originalValue = isObjectLike(subConfig) ? (Array.isArray(subConfig) ? [] : {}) : subConfig;\n\n const newValue = forceNonNull || !shouldNull() ? originalValue : null;\n const newOutputPath = forceNested || shouldMakeNested(originalValue) || outputPath.length === 0 ? outputPath : [outputPath.join(\".\")];\n if (outputPath.length === 0) {\n res = newValue;\n } else {\n if (forceNested || shouldKeep(originalValue)) {\n setDeep(res, newOutputPath, newValue);\n }\n }\n if (isObjectLike(subConfig)) {\n for (const [key, newValue] of typedEntries(subConfig)) {\n recurse([...newOutputPath, key], newValue, Array.isArray(subConfig), Array.isArray(subConfig));\n }\n }\n };\n recurse<T>([], config, false, true);\n return res;\n}\n\nundefined?.test(\"fuzz schemas\", async ({ expect }) => {\n const totalIterations = process.env.CI ? 1000 : 200;\n for (let i = 0; i < totalIterations; i++) {\n const projectInput = createFuzzerInput<ProjectConfigNormalizedOverride>(projectSchemaFuzzerConfig, i / totalIterations);\n const branchInput = createFuzzerInput<BranchConfigNormalizedOverride>(branchSchemaFuzzerConfig, i / totalIterations);\n const environmentInput = createFuzzerInput<EnvironmentConfigNormalizedOverride>(environmentSchemaFuzzerConfig, i / totalIterations);\n const organizationInput = createFuzzerInput<OrganizationConfigNormalizedOverride>(organizationSchemaFuzzerConfig, i / totalIterations);\n\n try {\n const projectMigrated = migrateConfigOverride(\"project\", projectInput);\n await assertNoConfigOverrideErrors(projectConfigSchema, projectMigrated);\n const projectOverridden = override({}, projectMigrated);\n await sanitizeProjectConfig(normalize(applyProjectDefaults(projectOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const branchMigrated = migrateConfigOverride(\"branch\", branchInput);\n await assertNoConfigOverrideErrors(branchConfigSchema, branchMigrated);\n const branchOverridden = override(projectOverridden, branchMigrated);\n await sanitizeBranchConfig(normalize(applyBranchDefaults(branchOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const environmentMigrated = migrateConfigOverride(\"environment\", environmentInput);\n await assertNoConfigOverrideErrors(environmentConfigSchema, environmentMigrated);\n const environmentOverridden = override(branchOverridden, environmentMigrated);\n await sanitizeEnvironmentConfig(normalize(applyEnvironmentDefaults(environmentOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const organizationMigrated = migrateConfigOverride(\"organization\", organizationInput);\n await assertNoConfigOverrideErrors(organizationConfigSchema, organizationMigrated);\n const organizationOverridden = override(environmentOverridden, organizationMigrated);\n await sanitizeOrganizationConfig(normalize(applyOrganizationDefaults(organizationOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n } catch (e) {\n const data = {\n cause: e,\n inputs: {\n projectInput,\n branchInput,\n environmentInput,\n organizationInput,\n },\n } as const;\n console.error(\"Failed to fuzz schema in iteration ${i}/${totalIterations}!\", nicify(data));\n throw new StackAssertionError(`Error in iteration ${i}/${totalIterations} of schema fuzz: ${e}`, { cause: e });\n }\n }\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/config/schema-fuzzer.test.ts"],"sourcesContent":["import { ALL_APPS } from \"../apps/apps-config\";\nimport { SUPPORTED_CURRENCIES } from \"../utils/currency-constants\";\nimport { StackAssertionError } from \"../utils/errors\";\nimport { getOrUndefined, isObjectLike, set, typedEntries, typedFromEntries } from \"../utils/objects\";\nimport { nicify } from \"../utils/strings\";\nimport { normalize, override } from \"./format\";\nimport { BranchConfigNormalizedOverride, EnvironmentConfigNormalizedOverride, OrganizationConfigNormalizedOverride, ProjectConfigNormalizedOverride, applyBranchDefaults, applyEnvironmentDefaults, applyOrganizationDefaults, applyProjectDefaults, assertNoConfigOverrideErrors, branchConfigSchema, environmentConfigSchema, migrateConfigOverride, organizationConfigSchema, projectConfigSchema, sanitizeBranchConfig, sanitizeEnvironmentConfig, sanitizeOrganizationConfig, sanitizeProjectConfig } from \"./schema\";\n\ntype FuzzerConfig<T> = ReadonlyArray<T extends object ? ([T] extends [any[]] ? { readonly [K in keyof T]: FuzzerConfig<T[K]> } : Required<{\n [K in keyof T]: FuzzerConfig<T[K]>;\n}> & Record<string, FuzzerConfig<any>>) : T>;\n\nconst projectSchemaFuzzerConfig = [{\n sourceOfTruth: [{\n type: [\"hosted\", \"neon\", \"postgres\"],\n connectionString: [\"\", \"postgres://user:password@host:port/database\", \"THIS IS A STRING LOLOL\"],\n connectionStrings: [{\n \"123-some-branch-id\": [\"\", \"THIS IS A CONNECTION STRING OR SO\"],\n }],\n }],\n}] satisfies FuzzerConfig<ProjectConfigNormalizedOverride>;\n\nconst branchSchemaFuzzerConfig = [{\n apiKeys: [{\n enabled: [{\n team: [true, false],\n user: [true, false],\n }],\n }],\n auth: [{\n allowSignUp: [true, false],\n password: [{\n allowSignIn: [true, false],\n }],\n otp: [{\n allowSignIn: [true, false],\n }],\n passkey: [{\n allowSignIn: [true, false],\n }],\n oauth: [{\n accountMergeStrategy: [\"link_method\", \"raise_error\", \"allow_duplicates\"],\n providers: [{\n \"google\": [{\n type: [\"google\", \"github\", \"x\"] as const,\n allowSignIn: [true, false],\n allowConnectedAccounts: [true, false],\n }],\n }],\n }],\n signUpRules: [{\n \"some-rule-id\": [{\n enabled: [true, false],\n displayName: [\"Block Test Emails\", \"Allow Only Company Domain\"],\n priority: [0, 1, 100],\n condition: ['email.endsWith(\"@test.com\")', 'emailDomain == \"company.com\"'],\n action: [{\n type: [\"allow\", \"reject\", \"restrict\", \"log\"] as const,\n message: [\"\", \"Sign up is not allowed for this email\"],\n }],\n }],\n }],\n signUpRulesDefaultAction: [\"allow\", \"reject\"],\n }],\n dbSync: [{\n externalDatabases: [{\n \"some-external-db-id\": [{\n type: [\"postgres\"] as const,\n connectionString: [\n \"postgres://user:password@host:port/database\",\n \"some-connection-string\",\n ],\n }],\n }],\n }],\n dataVault: [{\n stores: [{\n \"some-store-id\": [{\n displayName: [\"Some Store\", \"Some Other Store\"],\n }],\n \"some-other-store-id\": [{\n displayName: [\"Some Store\", \"Some Other Store\"],\n }],\n }],\n }],\n payments: [{\n blockNewPurchases: [false, true],\n autoPay: [{\n interval: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n }],\n productLines: [{\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n customerType: [\"user\", \"team\", \"custom\"] as const,\n }],\n }],\n catalogs: [{ // ensure migration works\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n }],\n }],\n groups: [{ // ensure migration works\n \"some-product-line-id\": [{\n displayName: [\"Some Product Line\", \"Some Other Product Line\"],\n }],\n }],\n items: [{\n \"some-item-id\": [{\n customerType: [\"user\", \"team\", \"custom\"] as const,\n displayName: [\"Some Item\", \"Some Other Item\"],\n }],\n }],\n products: [{\n \"some-product-id\": [{\n displayName: [\"Some Product\", \"Some Other Product\"],\n customerType: [\"user\", \"team\", \"custom\"] as const,\n freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n serverOnly: [true, false],\n stackable: [true, false],\n productLineId: [\"some-product-line-id\", \"some-other-product-line-id\"],\n catalogId: [\"some-product-line-id\", \"some-other-product-line-id\"], // ensure migration works\n groupId: [\"some-product-line-id\", \"some-other-product-line-id\"], // ensure migration works\n isAddOnTo: [false, { \"some-product-id\": [true], \"some-other-product-id\": [true] }] as const,\n prices: [\"include-by-default\" as \"include-by-default\", {\n \"some-price-id\": [{\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, [\"100_00\", \"not a number\", \"Infinity\", \"0\"]])),\n interval: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n serverOnly: [true, false],\n freeTrial: [[[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n }],\n }],\n includedItems: [{\n \"some-item-id\": [{\n quantity: [0, 1, -3, 100, 0.333, Infinity],\n repeat: [\"never\", [[0, 1, -3, 100, 0.333, Infinity], [\"day\", \"week\", \"month\", \"year\"]]] as const,\n expires: [\"never\", \"when-purchase-expires\", \"when-repeated\"] as const,\n }],\n }],\n }],\n }],\n }],\n emails: [{\n themes: [{\n \"12345678-1234-4234-9234-123456789012\": [{\n displayName: [\"Some Theme\", \"Some Other Theme\"],\n tsxSource: [\"\", \"some typescript source code\"],\n }],\n }],\n selectedThemeId: [\"some-theme-id\", \"some-other-theme-id\"],\n templates: [{\n \"12345678-1234-4234-9234-123456789012\": [{\n themeId: [\"some-theme-id\", \"some-other-theme-id\"],\n displayName: [\"Some Template\", \"Some Other Template\"],\n tsxSource: [\"\", \"some typescript source code\"],\n }],\n }],\n }],\n teams: [{\n createPersonalTeamOnSignUp: [true, false],\n allowClientTeamCreation: [true, false],\n }],\n users: [{\n allowClientUserDeletion: [true, false],\n }],\n rbac: [{\n permissions: [{\n \"some_permission_id\": [{\n containedPermissionIds: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n description: [\"Some Permission\", \"Some Other Permission\"],\n scope: [\"team\", \"project\"] as const,\n }],\n }],\n defaultPermissions: [{\n teamCreator: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n teamMember: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n signUp: [{\n \"some_permission_id\": [true],\n \"$some_other_permission_id\": [true],\n }] as const,\n }],\n }],\n domains: [{}],\n apps: [{\n installed: [typedFromEntries(typedEntries(ALL_APPS).map(([key, value]) => [key, [{\n enabled: [true, false],\n }]]))],\n }],\n onboarding: [{\n requireEmailVerification: [true, false],\n }],\n}] satisfies FuzzerConfig<BranchConfigNormalizedOverride>;\n\nconst environmentSchemaFuzzerConfig = [{\n ...branchSchemaFuzzerConfig[0],\n auth: [{\n ...branchSchemaFuzzerConfig[0].auth[0],\n oauth: [{\n ...branchSchemaFuzzerConfig[0].auth[0].oauth[0],\n providers: [typedFromEntries(typedEntries(branchSchemaFuzzerConfig[0].auth[0].oauth[0].providers[0]).map(([key, value]) => [key, [{\n ...value[0],\n isShared: [true, false],\n clientId: [\"some-client-id\"],\n clientSecret: [\"some-client-secret\"],\n facebookConfigId: [\"some-facebook-config-id\"],\n microsoftTenantId: [\"some-microsoft-tenant-id\"],\n appleBundles: [{ \"some-bundle-id\": [{ bundleId: [\"com.example.app\"] }] }],\n }]]))] as const,\n }],\n }],\n domains: [{\n allowLocalhost: [true, false],\n trustedDomains: [{\n \"some-domain-id\": [{\n baseUrl: [\"https://example.com/something-here\"],\n handlerPath: [\"/something-here\"],\n }],\n }],\n }],\n emails: [{\n ...branchSchemaFuzzerConfig[0].emails[0],\n server: [{\n isShared: [true, false],\n provider: [\"resend\", \"smtp\"] as const,\n host: [\"example.com\", \"://super weird host that's not valid\"],\n port: [1234, 0.12543, -100, Infinity],\n username: [\"some-username\", \"some username with a space\"],\n password: [\"some-password\", \"some password with a space\"],\n senderName: [\"Some Sender\"],\n senderEmail: [\"some-sender@example.com\", \"some invalid email\"],\n }],\n }],\n payments: [{\n ...branchSchemaFuzzerConfig[0].payments[0],\n testMode: [false, true],\n }],\n}] satisfies FuzzerConfig<EnvironmentConfigNormalizedOverride>;\n\nconst organizationSchemaFuzzerConfig = environmentSchemaFuzzerConfig satisfies FuzzerConfig<OrganizationConfigNormalizedOverride>;\n\nfunction setDeep<T>(obj: T, path: string[], value: any) {\n if (!isObjectLike(obj)) return obj;\n\n if (path.length === 0) {\n throw new Error(\"Path is empty\");\n } else if (path.length === 1) {\n set(obj as any, path[0], value);\n } else {\n const [key, ...rest] = path;\n setDeep(getOrUndefined(obj as any, key), rest, value);\n }\n}\n\nfunction createFuzzerInput<T>(config: FuzzerConfig<T>, progress: number): T {\n progress = Math.min(1, 2 * progress);\n const createShouldRandom = (strength: number) => {\n const chance = Math.random() * strength * 1.2 - 0.1;\n return () => Math.random() < chance;\n };\n const createShouldObjectDependent = (strength: number) => {\n const objectChance = Math.random() * strength * 1.2 - 0.1;\n const primitiveChance = Math.random() * strength * 1.2 - 0.1;\n return (v: any) => Math.random() * Math.random() < (isObjectLike(v) ? objectChance : primitiveChance);\n };\n\n const shouldKeep = createShouldObjectDependent(progress * 1);\n const shouldMakeNested = createShouldObjectDependent(1.25);\n const shouldNull = createShouldRandom(0.25);\n\n let res: any;\n const recurse = <U>(outputPath: string[], config: FuzzerConfig<U>, forceNested: boolean, forceNonNull: boolean) => {\n let subConfig: any = config[Math.floor(Math.random() * config.length)];\n const originalValue = isObjectLike(subConfig) ? (Array.isArray(subConfig) ? [] : {}) : subConfig;\n\n const newValue = forceNonNull || !shouldNull() ? originalValue : null;\n const newOutputPath = forceNested || shouldMakeNested(originalValue) || outputPath.length === 0 ? outputPath : [outputPath.join(\".\")];\n if (outputPath.length === 0) {\n res = newValue;\n } else {\n if (forceNested || shouldKeep(originalValue)) {\n setDeep(res, newOutputPath, newValue);\n }\n }\n if (isObjectLike(subConfig)) {\n for (const [key, newValue] of typedEntries(subConfig)) {\n recurse([...newOutputPath, key], newValue, Array.isArray(subConfig), Array.isArray(subConfig));\n }\n }\n };\n recurse<T>([], config, false, true);\n return res;\n}\n\nundefined?.test(\"fuzz schemas\", async ({ expect }) => {\n const totalIterations = process.env.CI ? 1000 : 200;\n for (let i = 0; i < totalIterations; i++) {\n const projectInput = createFuzzerInput<ProjectConfigNormalizedOverride>(projectSchemaFuzzerConfig, i / totalIterations);\n const branchInput = createFuzzerInput<BranchConfigNormalizedOverride>(branchSchemaFuzzerConfig, i / totalIterations);\n const environmentInput = createFuzzerInput<EnvironmentConfigNormalizedOverride>(environmentSchemaFuzzerConfig, i / totalIterations);\n const organizationInput = createFuzzerInput<OrganizationConfigNormalizedOverride>(organizationSchemaFuzzerConfig, i / totalIterations);\n\n try {\n const projectMigrated = migrateConfigOverride(\"project\", projectInput);\n await assertNoConfigOverrideErrors(projectConfigSchema, projectMigrated);\n const projectOverridden = override({}, projectMigrated);\n await sanitizeProjectConfig(normalize(applyProjectDefaults(projectOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const branchMigrated = migrateConfigOverride(\"branch\", branchInput);\n await assertNoConfigOverrideErrors(branchConfigSchema, branchMigrated);\n const branchOverridden = override(projectOverridden, branchMigrated);\n await sanitizeBranchConfig(normalize(applyBranchDefaults(branchOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const environmentMigrated = migrateConfigOverride(\"environment\", environmentInput);\n await assertNoConfigOverrideErrors(environmentConfigSchema, environmentMigrated);\n const environmentOverridden = override(branchOverridden, environmentMigrated);\n await sanitizeEnvironmentConfig(normalize(applyEnvironmentDefaults(environmentOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n const organizationMigrated = migrateConfigOverride(\"organization\", organizationInput);\n await assertNoConfigOverrideErrors(organizationConfigSchema, organizationMigrated);\n const organizationOverridden = override(environmentOverridden, organizationMigrated);\n await sanitizeOrganizationConfig(normalize(applyOrganizationDefaults(organizationOverridden), { onDotIntoNonObject: \"ignore\" }) as any);\n\n } catch (e) {\n const data = {\n cause: e,\n inputs: {\n projectInput,\n branchInput,\n environmentInput,\n organizationInput,\n },\n } as const;\n console.error(\"Failed to fuzz schema in iteration ${i}/${totalIterations}!\", nicify(data));\n throw new StackAssertionError(`Error in iteration ${i}/${totalIterations} of schema fuzz: ${e}`, { cause: e });\n }\n }\n});\n"],"mappings":"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","names":[]}
@@ -9,6 +9,7 @@ import { StackAssertionError } from "../utils/errors.js";
9
9
  import { allProviders } from "../utils/oauth.js";
10
10
  import { filterUndefined, get, getOrUndefined, has, isObjectLike, mapValues, set, typedAssign, typedEntries, typedFromEntries } from "../utils/objects.js";
11
11
  import { Result } from "../utils/results.js";
12
+ import { stringCompare } from "../utils/strings.js";
12
13
  import { typeAssert, typeAssertExtends, typeAssertIs } from "../utils/types.js";
13
14
  import { NormalizationError, assertNormalized, getInvalidConfigReason, normalize } from "./format.js";
14
15
  import { migrateCatalogsToProductLines } from "./migrate-catalogs-to-product-lines.js";
@@ -97,7 +98,26 @@ var branchAuthSchema = yupObject({
97
98
  allowConnectedAccounts: yupBoolean()
98
99
  })
99
100
  )
100
- })
101
+ }),
102
+ signUpRules: yupRecord(
103
+ userSpecifiedIdSchema("signUpRuleId"),
104
+ yupObject({
105
+ enabled: yupBoolean(),
106
+ displayName: yupString(),
107
+ // Priority for rule ordering (higher number = higher priority, evaluated first)
108
+ // Rules with same priority are sorted alphabetically by ID
109
+ priority: yupNumber().integer().min(0),
110
+ // CEL expression string - evaluated against signup context
111
+ // Example: 'email.endsWith("@gmail.com") && authMethod == "password"'
112
+ condition: yupString(),
113
+ action: yupObject({
114
+ type: yupString().oneOf(["allow", "reject", "restrict", "log"]).defined(),
115
+ message: yupString().optional()
116
+ // for reject action custom message (internal use, not shown to user)
117
+ })
118
+ })
119
+ ),
120
+ signUpRulesDefaultAction: yupString().oneOf(["allow", "reject"])
101
121
  });
102
122
  var branchPaymentsSchema = yupObject({
103
123
  blockNewPurchases: yupBoolean(),
@@ -170,6 +190,15 @@ var branchConfigSchema = canNoLongerBeOverridden(projectConfigSchema, ["sourceOf
170
190
  templates: schemaFields.emailTemplateListSchema
171
191
  }),
172
192
  payments: branchPaymentsSchema,
193
+ dbSync: yupObject({
194
+ externalDatabases: yupRecord(
195
+ userSpecifiedIdSchema("externalDatabaseId"),
196
+ yupObject({
197
+ type: yupString().oneOf(["postgres"]).defined(),
198
+ connectionString: yupString().defined()
199
+ })
200
+ )
201
+ }),
173
202
  dataVault: yupObject({
174
203
  stores: yupRecord(
175
204
  userSpecifiedIdSchema("storeId"),
@@ -390,7 +419,18 @@ var organizationConfigDefaults = {
390
419
  microsoftTenantId: void 0,
391
420
  appleBundles: void 0
392
421
  })
393
- }
422
+ },
423
+ signUpRules: (key) => ({
424
+ enabled: false,
425
+ displayName: void 0,
426
+ priority: 0,
427
+ condition: void 0,
428
+ action: {
429
+ type: "allow",
430
+ message: void 0
431
+ }
432
+ }),
433
+ signUpRulesDefaultAction: "allow"
394
434
  },
395
435
  emails: {
396
436
  server: {
@@ -447,6 +487,12 @@ var organizationConfigDefaults = {
447
487
  customerType: "user"
448
488
  })
449
489
  },
490
+ dbSync: {
491
+ externalDatabases: (key) => ({
492
+ type: void 0,
493
+ connectionString: void 0
494
+ })
495
+ },
450
496
  dataVault: {
451
497
  stores: (key) => ({
452
498
  displayName: "Unnamed Vault"
@@ -581,6 +627,12 @@ async function sanitizeOrganizationConfig(config) {
581
627
  }];
582
628
  }));
583
629
  const appSortIndices = new Map(Object.keys(ALL_APPS).map((appId, index) => [appId, index]));
630
+ const sortedRuleEntries = typedEntries(prepared.auth.signUpRules).sort((a, b) => {
631
+ const priorityA = a[1].priority;
632
+ const priorityB = b[1].priority;
633
+ if (priorityA !== priorityB) return priorityB - priorityA;
634
+ return stringCompare(a[0], b[0]);
635
+ });
584
636
  return {
585
637
  ...prepared,
586
638
  auth: {
@@ -588,7 +640,8 @@ async function sanitizeOrganizationConfig(config) {
588
640
  oauth: {
589
641
  ...prepared.auth.oauth,
590
642
  providers: typedFromEntries(typedEntries(prepared.auth.oauth.providers).filter(([key, value]) => value.type !== void 0))
591
- }
643
+ },
644
+ signUpRules: typedFromEntries(sortedRuleEntries)
592
645
  },
593
646
  emails: {
594
647
  ...prepared.emails,