@hexclave/shared 1.0.23 → 1.0.25

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 (93) hide show
  1. package/dist/ai/unified-prompts/reminders.js +1 -0
  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.map +1 -1
  4. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +15 -0
  5. package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
  6. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +1 -46
  7. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +1 -62
  8. package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
  9. package/dist/config/schema.d.ts +30 -30
  10. package/dist/config-authoring.d.ts +2 -2
  11. package/dist/config-authoring.d.ts.map +1 -1
  12. package/dist/config-authoring.js.map +1 -1
  13. package/dist/esm/ai/unified-prompts/reminders.js +1 -0
  14. package/dist/esm/ai/unified-prompts/reminders.js.map +1 -1
  15. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
  16. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +15 -0
  17. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
  18. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +1 -46
  19. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +1 -62
  20. package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
  21. package/dist/esm/config/schema.d.ts +30 -30
  22. package/dist/esm/config-authoring.d.ts +2 -2
  23. package/dist/esm/config-authoring.d.ts.map +1 -1
  24. package/dist/esm/config-authoring.js.map +1 -1
  25. package/dist/esm/interface/admin-metrics.d.ts +10 -10
  26. package/dist/esm/interface/conversations.d.ts +11 -11
  27. package/dist/esm/interface/crud/current-user.d.ts +8 -8
  28. package/dist/esm/interface/crud/email-outbox.d.ts +184 -184
  29. package/dist/esm/interface/crud/invoices.d.ts +2 -2
  30. package/dist/esm/interface/crud/products.d.ts +15 -15
  31. package/dist/esm/interface/crud/products.d.ts.map +1 -1
  32. package/dist/esm/interface/crud/project-api-keys.d.ts +4 -4
  33. package/dist/esm/interface/crud/projects.d.ts +50 -0
  34. package/dist/esm/interface/crud/projects.d.ts.map +1 -1
  35. package/dist/esm/interface/crud/projects.js +6 -0
  36. package/dist/esm/interface/crud/projects.js.map +1 -1
  37. package/dist/esm/interface/crud/team-member-profiles.d.ts +12 -12
  38. package/dist/esm/interface/crud/transactions.d.ts +20 -20
  39. package/dist/esm/interface/crud/transactions.d.ts.map +1 -1
  40. package/dist/esm/interface/crud/users.d.ts +8 -8
  41. package/dist/esm/interface/webhooks.d.ts +2 -2
  42. package/dist/esm/known-errors.d.ts +1 -1
  43. package/dist/esm/schema-fields.d.ts +1 -1
  44. package/dist/esm/sessions.d.ts +7 -7
  45. package/dist/esm/utils/env.d.ts +2 -1
  46. package/dist/esm/utils/env.d.ts.map +1 -1
  47. package/dist/esm/utils/env.js +29 -17
  48. package/dist/esm/utils/env.js.map +1 -1
  49. package/dist/esm/utils/env.test.d.ts +1 -0
  50. package/dist/esm/utils/env.test.js +49 -0
  51. package/dist/esm/utils/env.test.js.map +1 -0
  52. package/dist/esm/utils/errors.d.ts.map +1 -1
  53. package/dist/esm/utils/errors.js +4 -1
  54. package/dist/esm/utils/errors.js.map +1 -1
  55. package/dist/interface/admin-metrics.d.ts +10 -10
  56. package/dist/interface/conversations.d.ts +11 -11
  57. package/dist/interface/crud/current-user.d.ts +8 -8
  58. package/dist/interface/crud/email-outbox.d.ts +184 -184
  59. package/dist/interface/crud/invoices.d.ts +2 -2
  60. package/dist/interface/crud/products.d.ts +15 -15
  61. package/dist/interface/crud/products.d.ts.map +1 -1
  62. package/dist/interface/crud/project-api-keys.d.ts +4 -4
  63. package/dist/interface/crud/projects.d.ts +50 -0
  64. package/dist/interface/crud/projects.d.ts.map +1 -1
  65. package/dist/interface/crud/projects.js +6 -0
  66. package/dist/interface/crud/projects.js.map +1 -1
  67. package/dist/interface/crud/team-member-profiles.d.ts +12 -12
  68. package/dist/interface/crud/transactions.d.ts +20 -20
  69. package/dist/interface/crud/transactions.d.ts.map +1 -1
  70. package/dist/interface/crud/users.d.ts +8 -8
  71. package/dist/interface/webhooks.d.ts +2 -2
  72. package/dist/known-errors.d.ts +1 -1
  73. package/dist/schema-fields.d.ts +1 -1
  74. package/dist/sessions.d.ts +7 -7
  75. package/dist/utils/env.d.ts +2 -1
  76. package/dist/utils/env.d.ts.map +1 -1
  77. package/dist/utils/env.js +29 -16
  78. package/dist/utils/env.js.map +1 -1
  79. package/dist/utils/env.test.d.ts +1 -0
  80. package/dist/utils/env.test.js +49 -0
  81. package/dist/utils/env.test.js.map +1 -0
  82. package/dist/utils/errors.d.ts.map +1 -1
  83. package/dist/utils/errors.js +4 -1
  84. package/dist/utils/errors.js.map +1 -1
  85. package/package.json +1 -1
  86. package/src/ai/unified-prompts/reminders.ts +1 -0
  87. package/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts +15 -0
  88. package/src/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.ts +1 -62
  89. package/src/config-authoring.ts +2 -2
  90. package/src/interface/crud/projects.ts +12 -0
  91. package/src/utils/env.test.tsx +58 -0
  92. package/src/utils/env.tsx +36 -20
  93. package/src/utils/errors.tsx +6 -1
@@ -82,8 +82,8 @@ declare const usersCrudServerReadSchema: yup$1.ObjectSchema<{
82
82
  server_metadata?: {} | null | undefined;
83
83
  display_name: string;
84
84
  id: string;
85
- created_at_millis: number;
86
85
  profile_image_url: string | null;
86
+ created_at_millis: number;
87
87
  } | null;
88
88
  selected_team_id: string | null;
89
89
  profile_image_url: string | null;
@@ -162,12 +162,12 @@ declare const usersCrudServerReadSchema: yup$1.ObjectSchema<{
162
162
  requires_totp_mfa: undefined;
163
163
  }, "">;
164
164
  declare const usersCrudServerCreateSchema: yup$1.ObjectSchema<{
165
- primary_email: string | null | undefined;
165
+ is_anonymous: boolean | undefined;
166
166
  display_name: string | null | undefined;
167
167
  client_metadata: {} | null | undefined;
168
168
  client_read_only_metadata: {} | null | undefined;
169
169
  server_metadata: {} | null | undefined;
170
- is_anonymous: boolean | undefined;
170
+ primary_email: string | null | undefined;
171
171
  password: string | null | undefined;
172
172
  primary_email_verified: boolean | undefined;
173
173
  primary_email_auth_enabled: boolean | undefined;
@@ -235,8 +235,8 @@ declare const usersCrud: CrudSchemaFromOptions<{
235
235
  server_metadata?: {} | null | undefined;
236
236
  display_name: string;
237
237
  id: string;
238
- created_at_millis: number;
239
238
  profile_image_url: string | null;
239
+ created_at_millis: number;
240
240
  } | null;
241
241
  selected_team_id: string | null;
242
242
  profile_image_url: string | null;
@@ -368,12 +368,12 @@ declare const usersCrud: CrudSchemaFromOptions<{
368
368
  };
369
369
  }, "">;
370
370
  serverCreateSchema: yup$1.ObjectSchema<{
371
- primary_email: string | null | undefined;
371
+ is_anonymous: boolean | undefined;
372
372
  display_name: string | null | undefined;
373
373
  client_metadata: {} | null | undefined;
374
374
  client_read_only_metadata: {} | null | undefined;
375
375
  server_metadata: {} | null | undefined;
376
- is_anonymous: boolean | undefined;
376
+ primary_email: string | null | undefined;
377
377
  password: string | null | undefined;
378
378
  primary_email_verified: boolean | undefined;
379
379
  primary_email_auth_enabled: boolean | undefined;
@@ -469,8 +469,8 @@ declare const userCreatedWebhookEvent: WebhookEvent<yup$1.ObjectSchema<{
469
469
  server_metadata?: {} | null | undefined;
470
470
  display_name: string;
471
471
  id: string;
472
- created_at_millis: number;
473
472
  profile_image_url: string | null;
473
+ created_at_millis: number;
474
474
  } | null;
475
475
  selected_team_id: string | null;
476
476
  profile_image_url: string | null;
@@ -560,8 +560,8 @@ declare const userUpdatedWebhookEvent: WebhookEvent<yup$1.ObjectSchema<{
560
560
  server_metadata?: {} | null | undefined;
561
561
  display_name: string;
562
562
  id: string;
563
- created_at_millis: number;
564
563
  profile_image_url: string | null;
564
+ created_at_millis: number;
565
565
  } | null;
566
566
  selected_team_id: string | null;
567
567
  profile_image_url: string | null;
@@ -22,8 +22,8 @@ declare const webhookEvents: readonly [WebhookEvent<yup$1.ObjectSchema<{
22
22
  server_metadata?: {} | null | undefined;
23
23
  display_name: string;
24
24
  id: string;
25
- created_at_millis: number;
26
25
  profile_image_url: string | null;
26
+ created_at_millis: number;
27
27
  } | null;
28
28
  selected_team_id: string | null;
29
29
  profile_image_url: string | null;
@@ -112,8 +112,8 @@ declare const webhookEvents: readonly [WebhookEvent<yup$1.ObjectSchema<{
112
112
  server_metadata?: {} | null | undefined;
113
113
  display_name: string;
114
114
  id: string;
115
- created_at_millis: number;
116
115
  profile_image_url: string | null;
116
+ created_at_millis: number;
117
117
  } | null;
118
118
  selected_team_id: string | null;
119
119
  profile_image_url: string | null;
@@ -518,7 +518,7 @@ declare const KnownErrors: {
518
518
  CustomerDoesNotExist: KnownErrorConstructor<KnownError & KnownErrorBrand<"CUSTOMER_DOES_NOT_EXIST">, [customerId: string]> & {
519
519
  errorCode: "CUSTOMER_DOES_NOT_EXIST";
520
520
  };
521
- ProductDoesNotExist: KnownErrorConstructor<KnownError & KnownErrorBrand<"PRODUCT_DOES_NOT_EXIST">, [productId: string, context: "item_exists" | "server_only" | null]> & {
521
+ ProductDoesNotExist: KnownErrorConstructor<KnownError & KnownErrorBrand<"PRODUCT_DOES_NOT_EXIST">, [productId: string, context: "server_only" | "item_exists" | null]> & {
522
522
  errorCode: "PRODUCT_DOES_NOT_EXIST";
523
523
  };
524
524
  ProductCustomerTypeDoesNotMatch: KnownErrorConstructor<KnownError & KnownErrorBrand<"PRODUCT_CUSTOMER_TYPE_DOES_NOT_MATCH">, [productId: string | undefined, customerId: string, productCustomerType: "team" | "user" | "custom" | undefined, actualCustomerType: "team" | "user" | "custom"]> & {
@@ -314,8 +314,8 @@ declare const inlineProductSchema: yup$1.ObjectSchema<{
314
314
  free_trial?: DayInterval | undefined;
315
315
  }>;
316
316
  included_items: Record<string, {
317
- quantity?: number | undefined;
318
317
  repeat?: "never" | DayInterval | undefined;
318
+ quantity?: number | undefined;
319
319
  expires?: "never" | "when-purchase-expires" | "when-repeated" | undefined;
320
320
  }>;
321
321
  client_metadata: {} | null | undefined;
@@ -9,24 +9,24 @@ declare class AccessToken {
9
9
  private constructor();
10
10
  get payload(): {
11
11
  exp?: number | undefined;
12
- project_id: string;
13
- refresh_token_id: string;
14
- email: string | null;
15
- restricted_reason: {
16
- type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
17
- } | null;
18
- branch_id: string;
19
12
  sub: string;
20
13
  iat: number;
21
14
  iss: string;
22
15
  aud: string;
16
+ project_id: string;
17
+ branch_id: string;
18
+ refresh_token_id: string;
23
19
  role: "authenticated";
24
20
  name: string | null;
21
+ email: string | null;
25
22
  email_verified: boolean;
26
23
  selected_team_id: string | null;
27
24
  signed_up_at: number;
28
25
  is_anonymous: boolean;
29
26
  is_restricted: boolean;
27
+ restricted_reason: {
28
+ type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
29
+ } | null;
30
30
  requires_totp_mfa: boolean;
31
31
  };
32
32
  get expiresAt(): Date;
@@ -1,5 +1,6 @@
1
1
  //#region src/utils/env.d.ts
2
2
  declare function isBrowserLike(): boolean;
3
+ declare function resolveHexclaveStackEnvVarValue(hexclaveName: string, stackName: string, hexclaveValue: string | undefined, stackValue: string | undefined): string | undefined;
3
4
  /**
4
5
  * Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.
5
6
  */
@@ -21,5 +22,5 @@ declare function getNodeEnvironment(): string;
21
22
  */
22
23
  declare function getProcessEnv(name: string): string | undefined;
23
24
  //#endregion
24
- export { getEnvBoolean, getEnvVariable, getNextRuntime, getNodeEnvironment, getProcessEnv, isBrowserLike };
25
+ export { getEnvBoolean, getEnvVariable, getNextRuntime, getNodeEnvironment, getProcessEnv, isBrowserLike, resolveHexclaveStackEnvVarValue };
25
26
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","names":[],"sources":["../../src/utils/env.tsx"],"mappings":";iBAGgB,aAAA,CAAA;AAAhB;;;AAAA,iBA0BgB,cAAA,CAAe,IAAA,UAAc,YAAA;AAAA,iBAgD7B,aAAA,CAAc,IAAA;AAAA,iBAWd,cAAA,CAAA;AAAA,iBAKA,kBAAA,CAAA;;;;AAhBhB;;;;;AAWA;;;;iBAqBgB,aAAA,CAAc,IAAA"}
1
+ {"version":3,"file":"env.d.ts","names":[],"sources":["../../src/utils/env.tsx"],"mappings":";iBAGgB,aAAA,CAAA;AAAA,iBASA,+BAAA,CAAgC,YAAA,UAAsB,SAAA,UAAmB,aAAA,sBAAmC,UAAA;;;;iBAgC5G,cAAA,CAAe,IAAA,UAAc,YAAA;AAAA,iBAgD7B,aAAA,CAAc,IAAA;AAAA,iBAWd,cAAA,CAAA;AAAA,iBAKA,kBAAA,CAAA;;;;;;;;AAhEhB;;;;;iBAgFgB,aAAA,CAAc,IAAA"}
package/dist/utils/env.js CHANGED
@@ -8,16 +8,30 @@ function isBrowserLike() {
8
8
  return typeof window !== "undefined" && typeof document !== "undefined" && typeof document.createElement !== "undefined";
9
9
  }
10
10
  const ENV_VAR_RENAME = { NEXT_PUBLIC_STACK_API_URL: ["STACK_BASE_URL", "NEXT_PUBLIC_STACK_URL"] };
11
+ function resolveHexclaveStackEnvVarValue(hexclaveName, stackName, hexclaveValue, stackValue) {
12
+ if (hexclaveValue && stackValue && hexclaveValue !== stackValue) throw new Error(`Environment variables ${hexclaveName} and ${stackName} are both set to different values. Remove one of them or set them to the same value.`);
13
+ return hexclaveValue || stackValue || void 0;
14
+ }
11
15
  /**
12
- * Hexclave rebrand: compute the `HEXCLAVE_*`-prefixed equivalent of a `STACK_*`
13
- * env var name by replacing the first `STACK_` occurrence with `HEXCLAVE_`.
14
- * Covers `STACK_FOO`, `NEXT_PUBLIC_STACK_FOO`, `NEXT_PUBLIC_BROWSER_STACK_FOO`,
15
- * `NEXT_PUBLIC_SERVER_STACK_FOO`, `VITE_STACK_FOO`. Returns `undefined` when the
16
- * name has no `STACK_` segment (caller should behave exactly as before).
16
+ * Hexclave rebrand: resolve an env var by reading both the `HEXCLAVE_*` and
17
+ * `STACK_*` spellings, preferring the canonical Hexclave value and falling back
18
+ * to the legacy Stack value (empty counts as unset). Works in BOTH directions —
19
+ * whether the caller passes the legacy `STACK_FOO` name or the canonical
20
+ * `HEXCLAVE_FOO` name, the other spelling is still honored. Covers `STACK_FOO`,
21
+ * `NEXT_PUBLIC_STACK_FOO`, `NEXT_PUBLIC_BROWSER_STACK_FOO`,
22
+ * `NEXT_PUBLIC_SERVER_STACK_FOO`, `VITE_STACK_FOO` and their HEXCLAVE_ twins.
23
+ * Names with neither segment behave exactly as before.
17
24
  */
18
- function getHexclaveEnvVarName(name) {
19
- if (!name.includes("STACK_")) return;
20
- return name.replace("STACK_", "HEXCLAVE_");
25
+ function getEnvVarWithHexclaveFallback(name) {
26
+ if (name.includes("STACK_")) {
27
+ const hexclaveName = name.replace("STACK_", "HEXCLAVE_");
28
+ return resolveHexclaveStackEnvVarValue(hexclaveName, name, process.env[hexclaveName], process.env[name]);
29
+ }
30
+ if (name.includes("HEXCLAVE_")) {
31
+ const stackName = name.replace("HEXCLAVE_", "STACK_");
32
+ return resolveHexclaveStackEnvVarValue(name, stackName, process.env[name], process.env[stackName]);
33
+ }
34
+ return process.env[name];
21
35
  }
22
36
  /**
23
37
  * Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.
@@ -33,12 +47,11 @@ function getEnvVariable(name, defaultValue) {
33
47
 
34
48
  Use getNextRuntime() instead.
35
49
  `);
36
- for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) if (oldNames.includes(name)) (0, __errors_js.throwErr)(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);
37
- const hexclaveName = getHexclaveEnvVarName(name);
38
- let value = (hexclaveName ? process.env[hexclaveName] : void 0) ?? process.env[name];
39
- if (!value && ENV_VAR_RENAME[name]) for (const oldName of ENV_VAR_RENAME[name]) {
40
- const hexclaveOldName = getHexclaveEnvVarName(oldName);
41
- value = (hexclaveOldName ? process.env[hexclaveOldName] : void 0) ?? process.env[oldName];
50
+ for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) if (oldNames?.includes(name)) (0, __errors_js.throwErr)(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);
51
+ let value = getEnvVarWithHexclaveFallback(name);
52
+ const renamedNames = ENV_VAR_RENAME[name];
53
+ if (!value && renamedNames != null) for (const oldName of renamedNames) {
54
+ value = getEnvVarWithHexclaveFallback(oldName);
42
55
  if (value) break;
43
56
  }
44
57
  if (!value) if (defaultValue !== void 0) value = defaultValue;
@@ -71,8 +84,7 @@ function getNodeEnvironment() {
71
84
  */
72
85
  function getProcessEnv(name) {
73
86
  if (typeof process === "undefined" || typeof process.env === "undefined") return;
74
- const hexclaveName = getHexclaveEnvVarName(name);
75
- return (hexclaveName ? process.env[hexclaveName] : void 0) ?? process.env[name];
87
+ return getEnvVarWithHexclaveFallback(name);
76
88
  }
77
89
 
78
90
  //#endregion
@@ -82,4 +94,5 @@ exports.getNextRuntime = getNextRuntime;
82
94
  exports.getNodeEnvironment = getNodeEnvironment;
83
95
  exports.getProcessEnv = getProcessEnv;
84
96
  exports.isBrowserLike = isBrowserLike;
97
+ exports.resolveHexclaveStackEnvVarValue = resolveHexclaveStackEnvVarValue;
85
98
  //# sourceMappingURL=env.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","names":["HexclaveAssertionError"],"sources":["../../src/utils/env.tsx"],"sourcesContent":["import { HexclaveAssertionError, throwErr } from \"./errors\";\nimport { deindent } from \"./strings\";\n\nexport function isBrowserLike() {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\" && typeof document.createElement !== \"undefined\";\n}\n\n// newName: oldName\nconst ENV_VAR_RENAME: Record<string, string[]> = {\n NEXT_PUBLIC_STACK_API_URL: ['STACK_BASE_URL', 'NEXT_PUBLIC_STACK_URL'],\n};\n\n/**\n * Hexclave rebrand: compute the `HEXCLAVE_*`-prefixed equivalent of a `STACK_*`\n * env var name by replacing the first `STACK_` occurrence with `HEXCLAVE_`.\n * Covers `STACK_FOO`, `NEXT_PUBLIC_STACK_FOO`, `NEXT_PUBLIC_BROWSER_STACK_FOO`,\n * `NEXT_PUBLIC_SERVER_STACK_FOO`, `VITE_STACK_FOO`. Returns `undefined` when the\n * name has no `STACK_` segment (caller should behave exactly as before).\n */\nfunction getHexclaveEnvVarName(name: string): string | undefined {\n if (!name.includes(\"STACK_\")) {\n return undefined;\n }\n return name.replace(\"STACK_\", \"HEXCLAVE_\");\n}\n\n/**\n * Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.\n */\nexport function getEnvVariable(name: string, defaultValue?: string | undefined): string {\n if (isBrowserLike()) {\n throw new Error(deindent`\n Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.\n \n Use process.env.XYZ directly instead.\n `);\n }\n if (name === \"NEXT_RUNTIME\") {\n throw new Error(deindent`\n Can't use getEnvVariable to access the NEXT_RUNTIME environment variable because it's compiled into the client bundle.\n \n Use getNextRuntime() instead.\n `);\n }\n\n // throw error if the old name is used as the retrieve key\n for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) {\n if (oldNames.includes(name)) {\n throwErr(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);\n }\n }\n\n // Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.\n const hexclaveName = getHexclaveEnvVarName(name);\n let value = (hexclaveName ? process.env[hexclaveName] : undefined) ?? process.env[name];\n\n // check the key under the old name if the new name is not found\n if (!value && ENV_VAR_RENAME[name] as any) {\n for (const oldName of ENV_VAR_RENAME[name]) {\n // Hexclave rebrand: also accept the HEXCLAVE_*-prefixed equivalent of each old alias.\n const hexclaveOldName = getHexclaveEnvVarName(oldName);\n value = (hexclaveOldName ? process.env[hexclaveOldName] : undefined) ?? process.env[oldName];\n if (value) break;\n }\n }\n\n if (!value) {\n if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throwErr(`Missing environment variable: ${name}`);\n }\n }\n\n return value;\n}\n\nexport function getEnvBoolean(name: string): boolean {\n const value = getEnvVariable(name, \"false\");\n if (value === \"true\") {\n return true;\n } else if (value === \"false\") {\n return false;\n } else {\n throw new HexclaveAssertionError(`Environment variable ${name} must be either \"true\" or \"false\": found ${JSON.stringify(value)}`);\n }\n}\n\nexport function getNextRuntime() {\n // This variable is compiled into the client bundle, so we can't use getEnvVariable here.\n return process.env.NEXT_RUNTIME || throwErr(\"Missing environment variable: NEXT_RUNTIME\");\n}\n\nexport function getNodeEnvironment() {\n return getEnvVariable(\"NODE_ENV\", \"\");\n}\n\n/**\n * Browser-safe access to `process.env` for server-only or genuinely dynamic\n * env-var lookups. Returns `undefined` when `process` is not defined (e.g. in\n * a Vite browser bundle without a `process` shim).\n *\n * Note: uses `process.env[name]` (bracket form), which is NOT recognized by\n * Next.js / webpack DefinePlugin for compile-time inlining. If you need\n * build-time inlining for a `NEXT_PUBLIC_*` var, use the literal dot-form at\n * the call site, guarded with `typeof process`:\n *\n * const value = (typeof process !== \"undefined\" ? process.env.NEXT_PUBLIC_FOO : undefined);\n */\nexport function getProcessEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || typeof process.env === \"undefined\") {\n return undefined;\n }\n // Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.\n const hexclaveName = getHexclaveEnvVarName(name);\n return (hexclaveName ? process.env[hexclaveName] : undefined) ?? process.env[name];\n}\n"],"mappings":";;;;;;AAGA,SAAgB,gBAAgB;AAC9B,QAAO,OAAO,WAAW,eAAe,OAAO,aAAa,eAAe,OAAO,SAAS,kBAAkB;;AAI/G,MAAM,iBAA2C,EAC/C,2BAA2B,CAAC,kBAAkB,wBAAwB,EACvE;;;;;;;;AASD,SAAS,sBAAsB,MAAkC;AAC/D,KAAI,CAAC,KAAK,SAAS,SAAS,CAC1B;AAEF,QAAO,KAAK,QAAQ,UAAU,YAAY;;;;;AAM5C,SAAgB,eAAe,MAAc,cAA2C;AACtF,KAAI,eAAe,CACjB,OAAM,IAAI,MAAM,qBAAQ;;;;MAItB;AAEJ,KAAI,SAAS,eACX,OAAM,IAAI,MAAM,qBAAQ;;;;MAItB;AAIJ,MAAK,MAAM,CAAC,SAAS,aAAa,OAAO,QAAQ,eAAe,CAC9D,KAAI,SAAS,SAAS,KAAK,CACzB,2BAAS,wBAAwB,KAAK,uBAAuB,QAAQ,yDAAyD;CAKlI,MAAM,eAAe,sBAAsB,KAAK;CAChD,IAAI,SAAS,eAAe,QAAQ,IAAI,gBAAgB,WAAc,QAAQ,IAAI;AAGlF,KAAI,CAAC,SAAS,eAAe,MAC3B,MAAK,MAAM,WAAW,eAAe,OAAO;EAE1C,MAAM,kBAAkB,sBAAsB,QAAQ;AACtD,WAAS,kBAAkB,QAAQ,IAAI,mBAAmB,WAAc,QAAQ,IAAI;AACpF,MAAI,MAAO;;AAIf,KAAI,CAAC,MACH,KAAI,iBAAiB,OACnB,SAAQ;KAER,2BAAS,iCAAiC,OAAO;AAIrD,QAAO;;AAGT,SAAgB,cAAc,MAAuB;CACnD,MAAM,QAAQ,eAAe,MAAM,QAAQ;AAC3C,KAAI,UAAU,OACZ,QAAO;UACE,UAAU,QACnB,QAAO;KAEP,OAAM,IAAIA,mCAAuB,wBAAwB,KAAK,2CAA2C,KAAK,UAAU,MAAM,GAAG;;AAIrI,SAAgB,iBAAiB;AAE/B,QAAO,QAAQ,IAAI,0CAAyB,6CAA6C;;AAG3F,SAAgB,qBAAqB;AACnC,QAAO,eAAe,YAAY,GAAG;;;;;;;;;;;;;;AAevC,SAAgB,cAAc,MAAkC;AAC9D,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,QAAQ,YAC3D;CAGF,MAAM,eAAe,sBAAsB,KAAK;AAChD,SAAQ,eAAe,QAAQ,IAAI,gBAAgB,WAAc,QAAQ,IAAI"}
1
+ {"version":3,"file":"env.js","names":["HexclaveAssertionError"],"sources":["../../src/utils/env.tsx"],"sourcesContent":["import { HexclaveAssertionError, throwErr } from \"./errors\";\nimport { deindent } from \"./strings\";\n\nexport function isBrowserLike() {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\" && typeof document.createElement !== \"undefined\";\n}\n\n// newName: oldName\nconst ENV_VAR_RENAME: Record<string, string[] | undefined> = {\n NEXT_PUBLIC_STACK_API_URL: ['STACK_BASE_URL', 'NEXT_PUBLIC_STACK_URL'],\n};\n\nexport function resolveHexclaveStackEnvVarValue(hexclaveName: string, stackName: string, hexclaveValue: string | undefined, stackValue: string | undefined): string | undefined {\n if (hexclaveValue && stackValue && hexclaveValue !== stackValue) {\n throw new Error(`Environment variables ${hexclaveName} and ${stackName} are both set to different values. Remove one of them or set them to the same value.`);\n }\n return hexclaveValue || stackValue || undefined;\n}\n\n/**\n * Hexclave rebrand: resolve an env var by reading both the `HEXCLAVE_*` and\n * `STACK_*` spellings, preferring the canonical Hexclave value and falling back\n * to the legacy Stack value (empty counts as unset). Works in BOTH directions —\n * whether the caller passes the legacy `STACK_FOO` name or the canonical\n * `HEXCLAVE_FOO` name, the other spelling is still honored. Covers `STACK_FOO`,\n * `NEXT_PUBLIC_STACK_FOO`, `NEXT_PUBLIC_BROWSER_STACK_FOO`,\n * `NEXT_PUBLIC_SERVER_STACK_FOO`, `VITE_STACK_FOO` and their HEXCLAVE_ twins.\n * Names with neither segment behave exactly as before.\n */\nfunction getEnvVarWithHexclaveFallback(name: string): string | undefined {\n if (name.includes(\"STACK_\")) {\n const hexclaveName = name.replace(\"STACK_\", \"HEXCLAVE_\");\n return resolveHexclaveStackEnvVarValue(hexclaveName, name, process.env[hexclaveName], process.env[name]);\n }\n if (name.includes(\"HEXCLAVE_\")) {\n const stackName = name.replace(\"HEXCLAVE_\", \"STACK_\");\n return resolveHexclaveStackEnvVarValue(name, stackName, process.env[name], process.env[stackName]);\n }\n return process.env[name];\n}\n\n/**\n * Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.\n */\nexport function getEnvVariable(name: string, defaultValue?: string | undefined): string {\n if (isBrowserLike()) {\n throw new Error(deindent`\n Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.\n \n Use process.env.XYZ directly instead.\n `);\n }\n if (name === \"NEXT_RUNTIME\") {\n throw new Error(deindent`\n Can't use getEnvVariable to access the NEXT_RUNTIME environment variable because it's compiled into the client bundle.\n \n Use getNextRuntime() instead.\n `);\n }\n\n // throw error if the old name is used as the retrieve key\n for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) {\n if (oldNames?.includes(name)) {\n throwErr(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);\n }\n }\n\n // Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.\n // Treat the empty string as unset the checked-in .env templates define empty\n // HEXCLAVE_* placeholders, which must not shadow a real value under the legacy name.\n let value = getEnvVarWithHexclaveFallback(name);\n\n // check the key under the old name if the new name is not found\n const renamedNames = ENV_VAR_RENAME[name];\n if (!value && renamedNames != null) {\n for (const oldName of renamedNames) {\n value = getEnvVarWithHexclaveFallback(oldName);\n if (value) break;\n }\n }\n\n if (!value) {\n if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throwErr(`Missing environment variable: ${name}`);\n }\n }\n\n return value;\n}\n\nexport function getEnvBoolean(name: string): boolean {\n const value = getEnvVariable(name, \"false\");\n if (value === \"true\") {\n return true;\n } else if (value === \"false\") {\n return false;\n } else {\n throw new HexclaveAssertionError(`Environment variable ${name} must be either \"true\" or \"false\": found ${JSON.stringify(value)}`);\n }\n}\n\nexport function getNextRuntime() {\n // This variable is compiled into the client bundle, so we can't use getEnvVariable here.\n return process.env.NEXT_RUNTIME || throwErr(\"Missing environment variable: NEXT_RUNTIME\");\n}\n\nexport function getNodeEnvironment() {\n return getEnvVariable(\"NODE_ENV\", \"\");\n}\n\n/**\n * Browser-safe access to `process.env` for server-only or genuinely dynamic\n * env-var lookups. Returns `undefined` when `process` is not defined (e.g. in\n * a Vite browser bundle without a `process` shim).\n *\n * Note: uses `process.env[name]` (bracket form), which is NOT recognized by\n * Next.js / webpack DefinePlugin for compile-time inlining. If you need\n * build-time inlining for a `NEXT_PUBLIC_*` var, use the literal dot-form at\n * the call site, guarded with `typeof process`:\n *\n * const value = (typeof process !== \"undefined\" ? process.env.NEXT_PUBLIC_FOO : undefined);\n */\nexport function getProcessEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || typeof process.env === \"undefined\") {\n return undefined;\n }\n // Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.\n // Empty counts as unset the checked-in .env templates define empty HEXCLAVE_* placeholders,\n // which must not shadow a real value under the legacy name.\n return getEnvVarWithHexclaveFallback(name);\n}\n"],"mappings":";;;;;;AAGA,SAAgB,gBAAgB;AAC9B,QAAO,OAAO,WAAW,eAAe,OAAO,aAAa,eAAe,OAAO,SAAS,kBAAkB;;AAI/G,MAAM,iBAAuD,EAC3D,2BAA2B,CAAC,kBAAkB,wBAAwB,EACvE;AAED,SAAgB,gCAAgC,cAAsB,WAAmB,eAAmC,YAAoD;AAC9K,KAAI,iBAAiB,cAAc,kBAAkB,WACnD,OAAM,IAAI,MAAM,yBAAyB,aAAa,OAAO,UAAU,sFAAsF;AAE/J,QAAO,iBAAiB,cAAc;;;;;;;;;;;;AAaxC,SAAS,8BAA8B,MAAkC;AACvE,KAAI,KAAK,SAAS,SAAS,EAAE;EAC3B,MAAM,eAAe,KAAK,QAAQ,UAAU,YAAY;AACxD,SAAO,gCAAgC,cAAc,MAAM,QAAQ,IAAI,eAAe,QAAQ,IAAI,MAAM;;AAE1G,KAAI,KAAK,SAAS,YAAY,EAAE;EAC9B,MAAM,YAAY,KAAK,QAAQ,aAAa,SAAS;AACrD,SAAO,gCAAgC,MAAM,WAAW,QAAQ,IAAI,OAAO,QAAQ,IAAI,WAAW;;AAEpG,QAAO,QAAQ,IAAI;;;;;AAMrB,SAAgB,eAAe,MAAc,cAA2C;AACtF,KAAI,eAAe,CACjB,OAAM,IAAI,MAAM,qBAAQ;;;;MAItB;AAEJ,KAAI,SAAS,eACX,OAAM,IAAI,MAAM,qBAAQ;;;;MAItB;AAIJ,MAAK,MAAM,CAAC,SAAS,aAAa,OAAO,QAAQ,eAAe,CAC9D,KAAI,UAAU,SAAS,KAAK,CAC1B,2BAAS,wBAAwB,KAAK,uBAAuB,QAAQ,yDAAyD;CAOlI,IAAI,QAAQ,8BAA8B,KAAK;CAG/C,MAAM,eAAe,eAAe;AACpC,KAAI,CAAC,SAAS,gBAAgB,KAC5B,MAAK,MAAM,WAAW,cAAc;AAClC,UAAQ,8BAA8B,QAAQ;AAC9C,MAAI,MAAO;;AAIf,KAAI,CAAC,MACH,KAAI,iBAAiB,OACnB,SAAQ;KAER,2BAAS,iCAAiC,OAAO;AAIrD,QAAO;;AAGT,SAAgB,cAAc,MAAuB;CACnD,MAAM,QAAQ,eAAe,MAAM,QAAQ;AAC3C,KAAI,UAAU,OACZ,QAAO;UACE,UAAU,QACnB,QAAO;KAEP,OAAM,IAAIA,mCAAuB,wBAAwB,KAAK,2CAA2C,KAAK,UAAU,MAAM,GAAG;;AAIrI,SAAgB,iBAAiB;AAE/B,QAAO,QAAQ,IAAI,0CAAyB,6CAA6C;;AAG3F,SAAgB,qBAAqB;AACnC,QAAO,eAAe,YAAY,GAAG;;;;;;;;;;;;;;AAevC,SAAgB,cAAc,MAAkC;AAC9D,KAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,QAAQ,YAC3D;AAKF,QAAO,8BAA8B,KAAK"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,49 @@
1
+ const require_chunk = require('../chunk-BE-pF4vm.js');
2
+ let vitest = require("vitest");
3
+ let __env_js = require("./env.js");
4
+
5
+ //#region src/utils/env.test.tsx
6
+ (0, vitest.afterEach)(() => {
7
+ vitest.vi.unstubAllEnvs();
8
+ });
9
+ (0, vitest.describe)("Hexclave/Stack env var dual-read", () => {
10
+ (0, vitest.it)("falls back to the legacy Stack name when the Hexclave value is empty", () => {
11
+ vitest.vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "");
12
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
13
+ (0, vitest.expect)((0, __env_js.getEnvVariable)("NEXT_PUBLIC_STACK_API_URL")).toBe("https://stack.example.test");
14
+ (0, vitest.expect)((0, __env_js.getProcessEnv)("NEXT_PUBLIC_STACK_API_URL")).toBe("https://stack.example.test");
15
+ });
16
+ (0, vitest.it)("allows both names when they have the same non-empty value", () => {
17
+ vitest.vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://api.example.test");
18
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://api.example.test");
19
+ (0, vitest.expect)((0, __env_js.getEnvVariable)("NEXT_PUBLIC_STACK_API_URL")).toBe("https://api.example.test");
20
+ (0, vitest.expect)((0, __env_js.getProcessEnv)("NEXT_PUBLIC_STACK_API_URL")).toBe("https://api.example.test");
21
+ });
22
+ (0, vitest.it)("throws when both names are non-empty and different", () => {
23
+ vitest.vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://hexclave.example.test");
24
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
25
+ (0, vitest.expect)(() => (0, __env_js.getEnvVariable)("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
26
+ (0, vitest.expect)(() => (0, __env_js.getProcessEnv)("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
27
+ });
28
+ (0, vitest.it)("checks renamed legacy aliases when falling back", () => {
29
+ vitest.vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_URL", "https://hexclave-url.example.test");
30
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_URL", "https://stack-url.example.test");
31
+ (0, vitest.expect)(() => (0, __env_js.getEnvVariable)("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_URL.*NEXT_PUBLIC_STACK_URL.*different values/);
32
+ });
33
+ (0, vitest.it)("returns undefined when both names are empty", () => {
34
+ (0, vitest.expect)((0, __env_js.resolveHexclaveStackEnvVarValue)("HEXCLAVE_FOO", "STACK_FOO", "", "")).toBeUndefined();
35
+ });
36
+ (0, vitest.it)("falls back to the legacy Stack name when a canonical Hexclave name is looked up", () => {
37
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
38
+ (0, vitest.expect)((0, __env_js.getEnvVariable)("NEXT_PUBLIC_HEXCLAVE_API_URL")).toBe("https://stack.example.test");
39
+ (0, vitest.expect)((0, __env_js.getProcessEnv)("NEXT_PUBLIC_HEXCLAVE_API_URL")).toBe("https://stack.example.test");
40
+ });
41
+ (0, vitest.it)("throws on a conflict when a canonical Hexclave name is looked up", () => {
42
+ vitest.vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://hexclave.example.test");
43
+ vitest.vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
44
+ (0, vitest.expect)(() => (0, __env_js.getEnvVariable)("NEXT_PUBLIC_HEXCLAVE_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
45
+ });
46
+ });
47
+
48
+ //#endregion
49
+ //# sourceMappingURL=env.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.test.js","names":[],"sources":["../../src/utils/env.test.tsx"],"sourcesContent":["import { afterEach, describe, expect, it, vi } from \"vitest\";\nimport { getEnvVariable, getProcessEnv, resolveHexclaveStackEnvVarValue } from \"./env\";\n\nafterEach(() => {\n vi.unstubAllEnvs();\n});\n\ndescribe(\"Hexclave/Stack env var dual-read\", () => {\n it(\"falls back to the legacy Stack name when the Hexclave value is empty\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_HEXCLAVE_API_URL\", \"\");\n vi.stubEnv(\"NEXT_PUBLIC_STACK_API_URL\", \"https://stack.example.test\");\n\n expect(getEnvVariable(\"NEXT_PUBLIC_STACK_API_URL\")).toBe(\"https://stack.example.test\");\n expect(getProcessEnv(\"NEXT_PUBLIC_STACK_API_URL\")).toBe(\"https://stack.example.test\");\n });\n\n it(\"allows both names when they have the same non-empty value\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_HEXCLAVE_API_URL\", \"https://api.example.test\");\n vi.stubEnv(\"NEXT_PUBLIC_STACK_API_URL\", \"https://api.example.test\");\n\n expect(getEnvVariable(\"NEXT_PUBLIC_STACK_API_URL\")).toBe(\"https://api.example.test\");\n expect(getProcessEnv(\"NEXT_PUBLIC_STACK_API_URL\")).toBe(\"https://api.example.test\");\n });\n\n it(\"throws when both names are non-empty and different\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_HEXCLAVE_API_URL\", \"https://hexclave.example.test\");\n vi.stubEnv(\"NEXT_PUBLIC_STACK_API_URL\", \"https://stack.example.test\");\n\n expect(() => getEnvVariable(\"NEXT_PUBLIC_STACK_API_URL\")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);\n expect(() => getProcessEnv(\"NEXT_PUBLIC_STACK_API_URL\")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);\n });\n\n it(\"checks renamed legacy aliases when falling back\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_HEXCLAVE_URL\", \"https://hexclave-url.example.test\");\n vi.stubEnv(\"NEXT_PUBLIC_STACK_URL\", \"https://stack-url.example.test\");\n\n expect(() => getEnvVariable(\"NEXT_PUBLIC_STACK_API_URL\")).toThrow(/NEXT_PUBLIC_HEXCLAVE_URL.*NEXT_PUBLIC_STACK_URL.*different values/);\n });\n\n it(\"returns undefined when both names are empty\", () => {\n expect(resolveHexclaveStackEnvVarValue(\"HEXCLAVE_FOO\", \"STACK_FOO\", \"\", \"\")).toBeUndefined();\n });\n\n it(\"falls back to the legacy Stack name when a canonical Hexclave name is looked up\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_STACK_API_URL\", \"https://stack.example.test\");\n\n // Caller passes the canonical HEXCLAVE_ name but only the legacy value is set.\n expect(getEnvVariable(\"NEXT_PUBLIC_HEXCLAVE_API_URL\")).toBe(\"https://stack.example.test\");\n expect(getProcessEnv(\"NEXT_PUBLIC_HEXCLAVE_API_URL\")).toBe(\"https://stack.example.test\");\n });\n\n it(\"throws on a conflict when a canonical Hexclave name is looked up\", () => {\n vi.stubEnv(\"NEXT_PUBLIC_HEXCLAVE_API_URL\", \"https://hexclave.example.test\");\n vi.stubEnv(\"NEXT_PUBLIC_STACK_API_URL\", \"https://stack.example.test\");\n\n expect(() => getEnvVariable(\"NEXT_PUBLIC_HEXCLAVE_API_URL\")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);\n });\n});\n"],"mappings":";;;;;4BAGgB;AACd,WAAG,eAAe;EAClB;qBAEO,0CAA0C;AACjD,gBAAG,8EAA8E;AAC/E,YAAG,QAAQ,gCAAgC,GAAG;AAC9C,YAAG,QAAQ,6BAA6B,6BAA6B;AAErE,kDAAsB,4BAA4B,CAAC,CAAC,KAAK,6BAA6B;AACtF,iDAAqB,4BAA4B,CAAC,CAAC,KAAK,6BAA6B;GACrF;AAEF,gBAAG,mEAAmE;AACpE,YAAG,QAAQ,gCAAgC,2BAA2B;AACtE,YAAG,QAAQ,6BAA6B,2BAA2B;AAEnE,kDAAsB,4BAA4B,CAAC,CAAC,KAAK,2BAA2B;AACpF,iDAAqB,4BAA4B,CAAC,CAAC,KAAK,2BAA2B;GACnF;AAEF,gBAAG,4DAA4D;AAC7D,YAAG,QAAQ,gCAAgC,gCAAgC;AAC3E,YAAG,QAAQ,6BAA6B,6BAA6B;AAErE,wDAA4B,4BAA4B,CAAC,CAAC,QAAQ,4EAA4E;AAC9I,uDAA2B,4BAA4B,CAAC,CAAC,QAAQ,4EAA4E;GAC7I;AAEF,gBAAG,yDAAyD;AAC1D,YAAG,QAAQ,4BAA4B,oCAAoC;AAC3E,YAAG,QAAQ,yBAAyB,iCAAiC;AAErE,wDAA4B,4BAA4B,CAAC,CAAC,QAAQ,oEAAoE;GACtI;AAEF,gBAAG,qDAAqD;AACtD,mEAAuC,gBAAgB,aAAa,IAAI,GAAG,CAAC,CAAC,eAAe;GAC5F;AAEF,gBAAG,yFAAyF;AAC1F,YAAG,QAAQ,6BAA6B,6BAA6B;AAGrE,kDAAsB,+BAA+B,CAAC,CAAC,KAAK,6BAA6B;AACzF,iDAAqB,+BAA+B,CAAC,CAAC,KAAK,6BAA6B;GACxF;AAEF,gBAAG,0EAA0E;AAC3E,YAAG,QAAQ,gCAAgC,gCAAgC;AAC3E,YAAG,QAAQ,6BAA6B,6BAA6B;AAErE,wDAA4B,+BAA+B,CAAC,CAAC,QAAQ,4EAA4E;GACjJ;EACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/utils/errors.tsx"],"mappings":";;;iBAMgB,QAAA,CAAS,YAAA,UAAsB,SAAA;AAAA,iBAC/B,QAAA,CAAS,KAAA,EAAO,KAAA;AAAA,iBAChB,QAAA,CAAA,GAAY,IAAA,EAAM,gCAAA;;;;;AADlC;;;;;AACA;;;;;AA0CA;;;;;;;;;iBAAgB,iBAAA,CAAkB,KAAA,EAAO,KAAA,KAAU,MAAA,EAAQ,KAAA;AAAA,cAkB9C,sBAAA,SAA+B,KAAA;EAAA,SACG,SAAA,IAAY,MAAA,gBAAsB,YAAA;cAAnE,OAAA,UAAiC,SAAA,IAAY,MAAA,gBAAsB,YAAA;AAAA;AAAA,iBAqBjE,iBAAA,CAAkB,KAAA;AAAA,KAMtB,YAAA;AAAA,KAEP,SAAA,IAAa,QAAA,UAAkB,KAAA,WAAgB,KAAA,EAAO,YAAA,KAAiB,SAAA;AAAA,iBAG5D,iBAAA,CAAkB,IAAA,EAAM,SAAA;;;;;;;;;;iBA4CxB,YAAA,CAAa,QAAA,UAAkB,KAAA;;;;AAvD/C;iBA+DgB,cAAA,CAAe,QAAA,UAAkB,KAAA;AAAA,KAK5C,MAAA;EACH,UAAA;EACA,OAAA;AAAA;AAAA,KAGG,gCAAA,IAEH,MAAA,EAAQ,MAAA,EACR,OAAA,cAGA,UAAA,WAAqB,MAAA,EACrB,OAAA;AAAA,cAGW,WAAA,SAAoB,KAAA;EAAA,iBACd,uBAAA;EACV,IAAA;EAAA,SACS,UAAA;EAAA,OAEF,UAAA;;;;SACA,YAAA;;;;SACA,eAAA;;;;SACA,SAAA;;;;SACA,QAAA;;;;SACA,gBAAA;;;;SACA,aAAA;;;;SACA,2BAAA;;;;SACA,cAAA;;;;SACA,QAAA;;;;SACA,IAAA;;;;SACA,cAAA;;;;SACA,kBAAA;;;;SACA,eAAA;;;;SACA,UAAA;;;;SACA,oBAAA;;;;SACA,mBAAA;;;;SACA,iBAAA;;;;SACA,SAAA;;;;SACA,kBAAA;;;;SACA,mBAAA;;;;SACA,MAAA;;;;SACA,gBAAA;;;;SACA,QAAA;;;;SACA,eAAA;;;;SACA,oBAAA;;;;SACA,eAAA;;;;SACA,2BAAA;;;;SACA,0BAAA;;;;SAEA,mBAAA;;;;SACA,cAAA;;;;SACA,UAAA;;;;SACA,kBAAA;;;;SACA,cAAA;;;;SACA,uBAAA;;;;SACA,qBAAA;;;;SACA,mBAAA;;;;SACA,YAAA;;;;SACA,WAAA;;;;SACA,6BAAA;;;;iBAGC,IAAA,EAAM,gCAAA;EAAA,OAgBP,aAAA,CAAc,KAAA,YAAiB,KAAA,IAAS,WAAA;EAK/C,aAAA,CAAA;EAIA,aAAA,CAAA;EAIA,aAAA,CAAA;EAIA,OAAA,CAAA,GAAW,UAAA;EAIX,UAAA,CAAA,GAAc,MAAA;EAMd,iBAAA,CAAA,GAAqB,IAAA;;;;EAWrB,UAAA,CAAA,GAAc,IAAA;AAAA"}
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/utils/errors.tsx"],"mappings":";;;iBAMgB,QAAA,CAAS,YAAA,UAAsB,SAAA;AAAA,iBAC/B,QAAA,CAAS,KAAA,EAAO,KAAA;AAAA,iBAChB,QAAA,CAAA,GAAY,IAAA,EAAM,gCAAA;;;;;AADlC;;;;;AACA;;;;;AA0CA;;;;;;;;;iBAAgB,iBAAA,CAAkB,KAAA,EAAO,KAAA,KAAU,MAAA,EAAQ,KAAA;AAAA,cAkB9C,sBAAA,SAA+B,KAAA;EAAA,SACG,SAAA,IAAY,MAAA,gBAAsB,YAAA;cAAnE,OAAA,UAAiC,SAAA,IAAY,MAAA,gBAAsB,YAAA;AAAA;AAAA,iBA0BjE,iBAAA,CAAkB,KAAA;AAAA,KAMtB,YAAA;AAAA,KAEP,SAAA,IAAa,QAAA,UAAkB,KAAA,WAAgB,KAAA,EAAO,YAAA,KAAiB,SAAA;AAAA,iBAG5D,iBAAA,CAAkB,IAAA,EAAM,SAAA;;;;;;;;;;iBA4CxB,YAAA,CAAa,QAAA,UAAkB,KAAA;;;;AAvD/C;iBA+DgB,cAAA,CAAe,QAAA,UAAkB,KAAA;AAAA,KAK5C,MAAA;EACH,UAAA;EACA,OAAA;AAAA;AAAA,KAGG,gCAAA,IAEH,MAAA,EAAQ,MAAA,EACR,OAAA,cAGA,UAAA,WAAqB,MAAA,EACrB,OAAA;AAAA,cAGW,WAAA,SAAoB,KAAA;EAAA,iBACd,uBAAA;EACV,IAAA;EAAA,SACS,UAAA;EAAA,OAEF,UAAA;;;;SACA,YAAA;;;;SACA,eAAA;;;;SACA,SAAA;;;;SACA,QAAA;;;;SACA,gBAAA;;;;SACA,aAAA;;;;SACA,2BAAA;;;;SACA,cAAA;;;;SACA,QAAA;;;;SACA,IAAA;;;;SACA,cAAA;;;;SACA,kBAAA;;;;SACA,eAAA;;;;SACA,UAAA;;;;SACA,oBAAA;;;;SACA,mBAAA;;;;SACA,iBAAA;;;;SACA,SAAA;;;;SACA,kBAAA;;;;SACA,mBAAA;;;;SACA,MAAA;;;;SACA,gBAAA;;;;SACA,QAAA;;;;SACA,eAAA;;;;SACA,oBAAA;;;;SACA,eAAA;;;;SACA,2BAAA;;;;SACA,0BAAA;;;;SAEA,mBAAA;;;;SACA,cAAA;;;;SACA,UAAA;;;;SACA,kBAAA;;;;SACA,cAAA;;;;SACA,uBAAA;;;;SACA,qBAAA;;;;SACA,mBAAA;;;;SACA,YAAA;;;;SACA,WAAA;;;;SACA,6BAAA;;;;iBAGC,IAAA,EAAM,gCAAA;EAAA,OAgBP,aAAA,CAAc,KAAA,YAAiB,KAAA,IAAS,WAAA;EAK/C,aAAA,CAAA;EAIA,aAAA,CAAA;EAIA,aAAA,CAAA;EAIA,OAAA,CAAA,GAAW,UAAA;EAIX,UAAA,CAAA,GAAc,MAAA;EAMd,iBAAA,CAAA,GAAqB,IAAA;;;;EAWrB,UAAA,CAAA,GAAc,IAAA;AAAA"}
@@ -56,7 +56,10 @@ var HexclaveAssertionError = class extends Error {
56
56
  },
57
57
  enumerable: false
58
58
  });
59
- if ((typeof process !== "undefined" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : void 0) === "true") debugger;
59
+ const hexclaveDebuggerValue = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR : void 0;
60
+ const stackDebuggerValue = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : void 0;
61
+ if (hexclaveDebuggerValue && stackDebuggerValue && hexclaveDebuggerValue !== stackDebuggerValue) throw new Error("Environment variables NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR and NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR are both set to different values. Remove one of them or set them to the same value.");
62
+ if ((hexclaveDebuggerValue || stackDebuggerValue) === "true") debugger;
60
63
  }
61
64
  };
62
65
  HexclaveAssertionError.prototype.name = "HexclaveAssertionError";
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":["globalVar"],"sources":["../../src/utils/errors.tsx"],"sourcesContent":["import { globalVar } from \"./globals\";\nimport { Json } from \"./json\";\nimport { pick } from \"./objects\";\nimport { nicify } from \"./strings\";\n\n\nexport function throwErr(errorMessage: string, extraData?: any): never;\nexport function throwErr(error: Error): never;\nexport function throwErr(...args: StatusErrorConstructorParameters): never;\nexport function throwErr(...args: any[]): never {\n if (typeof args[0] === \"string\") {\n throw new HexclaveAssertionError(args[0], args[1]);\n } else if (args[0] instanceof Error) {\n throw args[0];\n } else {\n // @ts-expect-error\n throw new StatusError(...args);\n }\n}\n\nfunction removeStacktraceNameLine(stack: string): string {\n // some browsers (eg. Chrome) prepend the stack with an extra line with the error name\n const addsNameLine = new Error().stack?.startsWith(\"Error\\n\");\n return stack.split(\"\\n\").slice(addsNameLine ? 1 : 0).join(\"\\n\");\n}\n\n\n/**\n * Concatenates the (original) stacktraces of the given errors onto the first.\n *\n * Note: Very often, the concatStacktracesIfRejected function in promises.tsx is an easier way to use this function.\n *\n * Useful when you invoke an async function to receive a promise without awaiting it immediately. Browsers are smart\n * enough to keep track of the call stack in async function calls when you invoke `.then` within the same async tick,\n * but if you don't, the stacktrace will be lost.\n *\n * Here's an example of the unwanted behavior:\n *\n * ```tsx\n * async function log() {\n * await wait(0); // put the task on the event loop\n * console.log(new Error().stack);\n * }\n *\n * async function main() {\n * await log(); // good; prints both \"log\" and \"main\" on the stacktrace\n * log(); // bad; prints only \"log\" on the stacktrace\n * }\n * ```\n */\nexport function concatStacktraces(first: Error, ...errors: Error[]): void {\n // some browsers (eg. Firefox) add an extra empty line at the end\n const addsEmptyLineAtEnd = first.stack?.endsWith(\"\\n\");\n\n\n // Add a reference to this function itself so that we know that stacktraces were concatenated\n // If you are coming here from a stacktrace, please know that the two parts before and after this line are different\n // stacktraces that were concatenated with concatStacktraces\n const separator = removeStacktraceNameLine(new Error().stack ?? \"\").split(\"\\n\")[0];\n\n\n for (const error of errors) {\n const toAppend = removeStacktraceNameLine(error.stack ?? \"\");\n first.stack += (addsEmptyLineAtEnd ? \"\" : \"\\n\") + separator + \"\\n\" + toAppend;\n }\n}\n\n\nexport class HexclaveAssertionError extends Error {\n constructor(message: string, public readonly extraData?: Record<string, any> & ErrorOptions) {\n const disclaimer = `\\n\\nThis is likely an error in Hexclave. Please make sure you are running the newest version and report it.`;\n super(`${message}${message.endsWith(disclaimer) ? \"\" : disclaimer}`, pick(extraData ?? {}, [\"cause\"]));\n\n Object.defineProperty(this, \"customCaptureExtraArgs\", {\n get() {\n return [this.extraData];\n },\n enumerable: false,\n });\n\n // Use literal dot-form (guarded with `typeof process`) so Next.js / webpack\n // DefinePlugin can inline the value at build time. See getProcessEnv in ./env.\n if ((typeof process !== \"undefined\" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : undefined) === \"true\") {\n debugger;\n }\n }\n}\nHexclaveAssertionError.prototype.name = \"HexclaveAssertionError\";\n\n\nexport function errorToNiceString(error: unknown): string {\n if (!(error instanceof Error)) return `${typeof error}<${nicify(error)}>`;\n return nicify(error, { maxDepth: 8 });\n}\n\n\nexport type CaptureLevel = \"error\" | \"warning\";\n\ntype ErrorSink = (location: string, error: unknown, level: CaptureLevel, ...extraArgs: unknown[]) => void;\n\nconst errorSinks = new Set<ErrorSink>();\nexport function registerErrorSink(sink: ErrorSink): void {\n if (errorSinks.has(sink)) {\n return;\n }\n errorSinks.add(sink);\n}\nregisterErrorSink((location, error, level, ...extraArgs) => {\n const logger = level === \"warning\" ? console.warn : console.error;\n const colorCode = level === \"warning\" ? \"\\x1b[43m\" : \"\\x1b[41m\";\n const label = level === \"warning\" ? \"warning\" : \"error\";\n logger(\n `${colorCode}Captured ${label} in ${location}:`,\n // HACK: Log a nicified version of the error to get around buggy Next.js pretty-printing\n // https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button\n errorToNiceString(error),\n ...extraArgs,\n \"\\x1b[0m\",\n );\n});\nregisterErrorSink((location, error, level, ...extraArgs) => {\n globalVar.hexclaveCapturedErrors = globalVar.hexclaveCapturedErrors ?? [];\n globalVar.hexclaveCapturedErrors.push({ location, error, level, extraArgs });\n});\n\nfunction dispatchToSinks(location: string, error: unknown, level: CaptureLevel): void {\n for (const sink of errorSinks) {\n sink(\n location,\n error,\n level,\n ...error && (typeof error === 'object' || typeof error === 'function') && \"customCaptureExtraArgs\" in error && Array.isArray(error.customCaptureExtraArgs) ? (error.customCaptureExtraArgs as any[]) : [],\n );\n }\n}\n\n/**\n * Captures an error and sends it to the error sinks (most notably, Sentry). Errors caught with captureError are\n * supposed to be seen by an engineer, so they should be actionable and important.\n *\n * The location string is a machine-readable ID, and should hence not contain spaces or anything like that. Good\n * examples are: \"api-route-handler\", \"renderPart()\", etc.\n *\n * Errors that bubble up to the top of runAsynchronously or a route handler are already captured with captureError.\n */\nexport function captureError(location: string, error: unknown): void {\n dispatchToSinks(location, error, \"error\");\n}\n\n/**\n * Like captureError, but logs at warning level. Use for issues that an engineer should know about but that aren't\n * severe enough to be treated as an error (e.g. recoverable failures in background tasks).\n */\nexport function captureWarning(location: string, error: unknown): void {\n dispatchToSinks(location, error, \"warning\");\n}\n\n\ntype Status = {\n statusCode: number,\n message: string,\n};\n\ntype StatusErrorConstructorParameters =\n| [\n status: Status,\n message?: string\n]\n| [\n statusCode: number | Status,\n message: string,\n];\n\nexport class StatusError extends Error {\n private readonly __stackStatusErrorBrand = \"stack-status-error-brand-sentinel\" as const;\n public name = \"StatusError\";\n public readonly statusCode: number;\n\n public static BadRequest = { statusCode: 400, message: \"Bad Request\" };\n public static Unauthorized = { statusCode: 401, message: \"Unauthorized\" };\n public static PaymentRequired = { statusCode: 402, message: \"Payment Required\" };\n public static Forbidden = { statusCode: 403, message: \"Forbidden\" };\n public static NotFound = { statusCode: 404, message: \"Not Found\" };\n public static MethodNotAllowed = { statusCode: 405, message: \"Method Not Allowed\" };\n public static NotAcceptable = { statusCode: 406, message: \"Not Acceptable\" };\n public static ProxyAuthenticationRequired = { statusCode: 407, message: \"Proxy Authentication Required\" };\n public static RequestTimeout = { statusCode: 408, message: \"Request Timeout\" };\n public static Conflict = { statusCode: 409, message: \"Conflict\" };\n public static Gone = { statusCode: 410, message: \"Gone\" };\n public static LengthRequired = { statusCode: 411, message: \"Length Required\" };\n public static PreconditionFailed = { statusCode: 412, message: \"Precondition Failed\" };\n public static PayloadTooLarge = { statusCode: 413, message: \"Payload Too Large\" };\n public static URITooLong = { statusCode: 414, message: \"URI Too Long\" };\n public static UnsupportedMediaType = { statusCode: 415, message: \"Unsupported Media Type\" };\n public static RangeNotSatisfiable = { statusCode: 416, message: \"Range Not Satisfiable\" };\n public static ExpectationFailed = { statusCode: 417, message: \"Expectation Failed\" };\n public static ImATeapot = { statusCode: 418, message: \"I'm a teapot\" };\n public static MisdirectedRequest = { statusCode: 421, message: \"Misdirected Request\" };\n public static UnprocessableEntity = { statusCode: 422, message: \"Unprocessable Entity\" };\n public static Locked = { statusCode: 423, message: \"Locked\" };\n public static FailedDependency = { statusCode: 424, message: \"Failed Dependency\" };\n public static TooEarly = { statusCode: 425, message: \"Too Early\" };\n public static UpgradeRequired = { statusCode: 426, message: \"Upgrade Required\" };\n public static PreconditionRequired = { statusCode: 428, message: \"Precondition Required\" };\n public static TooManyRequests = { statusCode: 429, message: \"Too Many Requests\" };\n public static RequestHeaderFieldsTooLarge = { statusCode: 431, message: \"Request Header Fields Too Large\" };\n public static UnavailableForLegalReasons = { statusCode: 451, message: \"Unavailable For Legal Reasons\" };\n\n public static InternalServerError = { statusCode: 500, message: \"Internal Server Error\" };\n public static NotImplemented = { statusCode: 501, message: \"Not Implemented\" };\n public static BadGateway = { statusCode: 502, message: \"Bad Gateway\" };\n public static ServiceUnavailable = { statusCode: 503, message: \"Service Unavailable\" };\n public static GatewayTimeout = { statusCode: 504, message: \"Gateway Timeout\" };\n public static HTTPVersionNotSupported = { statusCode: 505, message: \"HTTP Version Not Supported\" };\n public static VariantAlsoNegotiates = { statusCode: 506, message: \"Variant Also Negotiates\" };\n public static InsufficientStorage = { statusCode: 507, message: \"Insufficient Storage\" };\n public static LoopDetected = { statusCode: 508, message: \"Loop Detected\" };\n public static NotExtended = { statusCode: 510, message: \"Not Extended\" };\n public static NetworkAuthenticationRequired = { statusCode: 511, message: \"Network Authentication Required\" };\n\n\n constructor(...args: StatusErrorConstructorParameters);\n constructor(\n status: number | Status,\n message?: string,\n ) {\n if (typeof status === \"object\") {\n message ??= status.message;\n status = status.statusCode;\n }\n super(message);\n this.statusCode = status;\n if (!message) {\n throw new HexclaveAssertionError(\"StatusError always requires a message unless a Status object is passed\", { cause: this });\n }\n }\n\n public static isStatusError(error: unknown): error is StatusError {\n // like instanceof, but also works for errors thrown in other realms or by different versions of the same package\n return typeof error === \"object\" && error !== null && \"__stackStatusErrorBrand\" in error && error.__stackStatusErrorBrand === \"stack-status-error-brand-sentinel\";\n }\n\n public isClientError() {\n return this.statusCode >= 400 && this.statusCode < 500;\n }\n\n public isServerError() {\n return !this.isClientError();\n }\n\n public getStatusCode(): number {\n return this.statusCode;\n }\n\n public getBody(): Uint8Array {\n return new TextEncoder().encode(this.message);\n }\n\n public getHeaders(): Record<string, string[]> {\n return {\n \"Content-Type\": [\"text/plain; charset=utf-8\"],\n };\n }\n\n public toDescriptiveJson(): Json {\n return {\n status_code: this.getStatusCode(),\n message: this.message,\n headers: this.getHeaders(),\n };\n }\n\n /**\n * @deprecated this is not a good way to make status errors human-readable, use toDescriptiveJson instead\n */\n public toHttpJson(): Json {\n return {\n status_code: this.statusCode,\n body: this.message,\n headers: this.getHeaders(),\n };\n }\n}\nStatusError.prototype.name = \"StatusError\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","names":["globalVar"],"sources":["../../src/utils/errors.tsx"],"sourcesContent":["import { globalVar } from \"./globals\";\nimport { Json } from \"./json\";\nimport { pick } from \"./objects\";\nimport { nicify } from \"./strings\";\n\n\nexport function throwErr(errorMessage: string, extraData?: any): never;\nexport function throwErr(error: Error): never;\nexport function throwErr(...args: StatusErrorConstructorParameters): never;\nexport function throwErr(...args: any[]): never {\n if (typeof args[0] === \"string\") {\n throw new HexclaveAssertionError(args[0], args[1]);\n } else if (args[0] instanceof Error) {\n throw args[0];\n } else {\n // @ts-expect-error\n throw new StatusError(...args);\n }\n}\n\nfunction removeStacktraceNameLine(stack: string): string {\n // some browsers (eg. Chrome) prepend the stack with an extra line with the error name\n const addsNameLine = new Error().stack?.startsWith(\"Error\\n\");\n return stack.split(\"\\n\").slice(addsNameLine ? 1 : 0).join(\"\\n\");\n}\n\n\n/**\n * Concatenates the (original) stacktraces of the given errors onto the first.\n *\n * Note: Very often, the concatStacktracesIfRejected function in promises.tsx is an easier way to use this function.\n *\n * Useful when you invoke an async function to receive a promise without awaiting it immediately. Browsers are smart\n * enough to keep track of the call stack in async function calls when you invoke `.then` within the same async tick,\n * but if you don't, the stacktrace will be lost.\n *\n * Here's an example of the unwanted behavior:\n *\n * ```tsx\n * async function log() {\n * await wait(0); // put the task on the event loop\n * console.log(new Error().stack);\n * }\n *\n * async function main() {\n * await log(); // good; prints both \"log\" and \"main\" on the stacktrace\n * log(); // bad; prints only \"log\" on the stacktrace\n * }\n * ```\n */\nexport function concatStacktraces(first: Error, ...errors: Error[]): void {\n // some browsers (eg. Firefox) add an extra empty line at the end\n const addsEmptyLineAtEnd = first.stack?.endsWith(\"\\n\");\n\n\n // Add a reference to this function itself so that we know that stacktraces were concatenated\n // If you are coming here from a stacktrace, please know that the two parts before and after this line are different\n // stacktraces that were concatenated with concatStacktraces\n const separator = removeStacktraceNameLine(new Error().stack ?? \"\").split(\"\\n\")[0];\n\n\n for (const error of errors) {\n const toAppend = removeStacktraceNameLine(error.stack ?? \"\");\n first.stack += (addsEmptyLineAtEnd ? \"\" : \"\\n\") + separator + \"\\n\" + toAppend;\n }\n}\n\n\nexport class HexclaveAssertionError extends Error {\n constructor(message: string, public readonly extraData?: Record<string, any> & ErrorOptions) {\n const disclaimer = `\\n\\nThis is likely an error in Hexclave. Please make sure you are running the newest version and report it.`;\n super(`${message}${message.endsWith(disclaimer) ? \"\" : disclaimer}`, pick(extraData ?? {}, [\"cause\"]));\n\n Object.defineProperty(this, \"customCaptureExtraArgs\", {\n get() {\n return [this.extraData];\n },\n enumerable: false,\n });\n\n // Use literal dot-form (guarded with `typeof process`) so Next.js / webpack\n // DefinePlugin can inline the value at build time. See getProcessEnv in ./env.\n const hexclaveDebuggerValue = typeof process !== \"undefined\" ? process.env.NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR : undefined;\n const stackDebuggerValue = typeof process !== \"undefined\" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : undefined;\n if (hexclaveDebuggerValue && stackDebuggerValue && hexclaveDebuggerValue !== stackDebuggerValue) {\n throw new Error(\"Environment variables NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR and NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR are both set to different values. Remove one of them or set them to the same value.\");\n }\n if ((hexclaveDebuggerValue || stackDebuggerValue) === \"true\") {\n debugger;\n }\n }\n}\nHexclaveAssertionError.prototype.name = \"HexclaveAssertionError\";\n\n\nexport function errorToNiceString(error: unknown): string {\n if (!(error instanceof Error)) return `${typeof error}<${nicify(error)}>`;\n return nicify(error, { maxDepth: 8 });\n}\n\n\nexport type CaptureLevel = \"error\" | \"warning\";\n\ntype ErrorSink = (location: string, error: unknown, level: CaptureLevel, ...extraArgs: unknown[]) => void;\n\nconst errorSinks = new Set<ErrorSink>();\nexport function registerErrorSink(sink: ErrorSink): void {\n if (errorSinks.has(sink)) {\n return;\n }\n errorSinks.add(sink);\n}\nregisterErrorSink((location, error, level, ...extraArgs) => {\n const logger = level === \"warning\" ? console.warn : console.error;\n const colorCode = level === \"warning\" ? \"\\x1b[43m\" : \"\\x1b[41m\";\n const label = level === \"warning\" ? \"warning\" : \"error\";\n logger(\n `${colorCode}Captured ${label} in ${location}:`,\n // HACK: Log a nicified version of the error to get around buggy Next.js pretty-printing\n // https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button\n errorToNiceString(error),\n ...extraArgs,\n \"\\x1b[0m\",\n );\n});\nregisterErrorSink((location, error, level, ...extraArgs) => {\n globalVar.hexclaveCapturedErrors = globalVar.hexclaveCapturedErrors ?? [];\n globalVar.hexclaveCapturedErrors.push({ location, error, level, extraArgs });\n});\n\nfunction dispatchToSinks(location: string, error: unknown, level: CaptureLevel): void {\n for (const sink of errorSinks) {\n sink(\n location,\n error,\n level,\n ...error && (typeof error === 'object' || typeof error === 'function') && \"customCaptureExtraArgs\" in error && Array.isArray(error.customCaptureExtraArgs) ? (error.customCaptureExtraArgs as any[]) : [],\n );\n }\n}\n\n/**\n * Captures an error and sends it to the error sinks (most notably, Sentry). Errors caught with captureError are\n * supposed to be seen by an engineer, so they should be actionable and important.\n *\n * The location string is a machine-readable ID, and should hence not contain spaces or anything like that. Good\n * examples are: \"api-route-handler\", \"renderPart()\", etc.\n *\n * Errors that bubble up to the top of runAsynchronously or a route handler are already captured with captureError.\n */\nexport function captureError(location: string, error: unknown): void {\n dispatchToSinks(location, error, \"error\");\n}\n\n/**\n * Like captureError, but logs at warning level. Use for issues that an engineer should know about but that aren't\n * severe enough to be treated as an error (e.g. recoverable failures in background tasks).\n */\nexport function captureWarning(location: string, error: unknown): void {\n dispatchToSinks(location, error, \"warning\");\n}\n\n\ntype Status = {\n statusCode: number,\n message: string,\n};\n\ntype StatusErrorConstructorParameters =\n| [\n status: Status,\n message?: string\n]\n| [\n statusCode: number | Status,\n message: string,\n];\n\nexport class StatusError extends Error {\n private readonly __stackStatusErrorBrand = \"stack-status-error-brand-sentinel\" as const;\n public name = \"StatusError\";\n public readonly statusCode: number;\n\n public static BadRequest = { statusCode: 400, message: \"Bad Request\" };\n public static Unauthorized = { statusCode: 401, message: \"Unauthorized\" };\n public static PaymentRequired = { statusCode: 402, message: \"Payment Required\" };\n public static Forbidden = { statusCode: 403, message: \"Forbidden\" };\n public static NotFound = { statusCode: 404, message: \"Not Found\" };\n public static MethodNotAllowed = { statusCode: 405, message: \"Method Not Allowed\" };\n public static NotAcceptable = { statusCode: 406, message: \"Not Acceptable\" };\n public static ProxyAuthenticationRequired = { statusCode: 407, message: \"Proxy Authentication Required\" };\n public static RequestTimeout = { statusCode: 408, message: \"Request Timeout\" };\n public static Conflict = { statusCode: 409, message: \"Conflict\" };\n public static Gone = { statusCode: 410, message: \"Gone\" };\n public static LengthRequired = { statusCode: 411, message: \"Length Required\" };\n public static PreconditionFailed = { statusCode: 412, message: \"Precondition Failed\" };\n public static PayloadTooLarge = { statusCode: 413, message: \"Payload Too Large\" };\n public static URITooLong = { statusCode: 414, message: \"URI Too Long\" };\n public static UnsupportedMediaType = { statusCode: 415, message: \"Unsupported Media Type\" };\n public static RangeNotSatisfiable = { statusCode: 416, message: \"Range Not Satisfiable\" };\n public static ExpectationFailed = { statusCode: 417, message: \"Expectation Failed\" };\n public static ImATeapot = { statusCode: 418, message: \"I'm a teapot\" };\n public static MisdirectedRequest = { statusCode: 421, message: \"Misdirected Request\" };\n public static UnprocessableEntity = { statusCode: 422, message: \"Unprocessable Entity\" };\n public static Locked = { statusCode: 423, message: \"Locked\" };\n public static FailedDependency = { statusCode: 424, message: \"Failed Dependency\" };\n public static TooEarly = { statusCode: 425, message: \"Too Early\" };\n public static UpgradeRequired = { statusCode: 426, message: \"Upgrade Required\" };\n public static PreconditionRequired = { statusCode: 428, message: \"Precondition Required\" };\n public static TooManyRequests = { statusCode: 429, message: \"Too Many Requests\" };\n public static RequestHeaderFieldsTooLarge = { statusCode: 431, message: \"Request Header Fields Too Large\" };\n public static UnavailableForLegalReasons = { statusCode: 451, message: \"Unavailable For Legal Reasons\" };\n\n public static InternalServerError = { statusCode: 500, message: \"Internal Server Error\" };\n public static NotImplemented = { statusCode: 501, message: \"Not Implemented\" };\n public static BadGateway = { statusCode: 502, message: \"Bad Gateway\" };\n public static ServiceUnavailable = { statusCode: 503, message: \"Service Unavailable\" };\n public static GatewayTimeout = { statusCode: 504, message: \"Gateway Timeout\" };\n public static HTTPVersionNotSupported = { statusCode: 505, message: \"HTTP Version Not Supported\" };\n public static VariantAlsoNegotiates = { statusCode: 506, message: \"Variant Also Negotiates\" };\n public static InsufficientStorage = { statusCode: 507, message: \"Insufficient Storage\" };\n public static LoopDetected = { statusCode: 508, message: \"Loop Detected\" };\n public static NotExtended = { statusCode: 510, message: \"Not Extended\" };\n public static NetworkAuthenticationRequired = { statusCode: 511, message: \"Network Authentication Required\" };\n\n\n constructor(...args: StatusErrorConstructorParameters);\n constructor(\n status: number | Status,\n message?: string,\n ) {\n if (typeof status === \"object\") {\n message ??= status.message;\n status = status.statusCode;\n }\n super(message);\n this.statusCode = status;\n if (!message) {\n throw new HexclaveAssertionError(\"StatusError always requires a message unless a Status object is passed\", { cause: this });\n }\n }\n\n public static isStatusError(error: unknown): error is StatusError {\n // like instanceof, but also works for errors thrown in other realms or by different versions of the same package\n return typeof error === \"object\" && error !== null && \"__stackStatusErrorBrand\" in error && error.__stackStatusErrorBrand === \"stack-status-error-brand-sentinel\";\n }\n\n public isClientError() {\n return this.statusCode >= 400 && this.statusCode < 500;\n }\n\n public isServerError() {\n return !this.isClientError();\n }\n\n public getStatusCode(): number {\n return this.statusCode;\n }\n\n public getBody(): Uint8Array {\n return new TextEncoder().encode(this.message);\n }\n\n public getHeaders(): Record<string, string[]> {\n return {\n \"Content-Type\": [\"text/plain; charset=utf-8\"],\n };\n }\n\n public toDescriptiveJson(): Json {\n return {\n status_code: this.getStatusCode(),\n message: this.message,\n headers: this.getHeaders(),\n };\n }\n\n /**\n * @deprecated this is not a good way to make status errors human-readable, use toDescriptiveJson instead\n */\n public toHttpJson(): Json {\n return {\n status_code: this.statusCode,\n body: this.message,\n headers: this.getHeaders(),\n };\n }\n}\nStatusError.prototype.name = \"StatusError\";\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexclave/shared",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "repository": "https://github.com/hexclave/hexclave",
5
5
  "files": [
6
6
  "README.md",
@@ -26,6 +26,7 @@ export const remindersPrompt = deindent`
26
26
  - There is a \`useHexclaveApp()\` hook as a named export from the package itself that serves as a shortcut to get the current Hexclave App object from the React context. Similarly, the \`useUser(...args)\` named export is short for \`useHexclaveApp().useUser(...args)\`.
27
27
  - Other
28
28
  - Hexclave also has a REST API with near-full feature parity with the SDK. It can be used for both client and server-side code.
29
+ - If available, always prefer editing the \`hexclave.config.ts\` file directly over asking the user to make changes on the dashboard. When implementing new features, you can always update the config file, and then tell the user about the changes you've made.
29
30
  - Hexclave's config files allow dot notation for nested properties. For example, the config \`{ auth: { allowSignUp: true }, "auth.password": { allowSignIn: true } }\` is the same as \`{ auth: { allowSignUp: true, password: { allowSignIn: true } } }\`.
30
31
  - Hexclave was formerly known as Stack Auth. You may still see references to it as Stack Auth in some places.
31
32
  `;
@@ -1,6 +1,7 @@
1
1
  import { ALL_APPS, type AppId } from "../../../apps/apps-config";
2
2
  import { typedEntries } from "../../../utils/objects";
3
3
  import { deindent } from "../../../utils/strings";
4
+ import { remindersPrompt } from "../reminders";
4
5
 
5
6
  export const convexSetupPrompt = deindent`
6
7
  ## Convex Setup
@@ -593,6 +594,8 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
593
594
  Then wire the SDK setup above: create the Hexclave App object, wrap React apps in the provider, and add handler/auth pages where your framework needs them. OAuth client IDs/secrets and trusted domains are environment-specific, so leave placeholders or ask the user for those instead of inventing them. See [Auth providers](https://docs.hexclave.com/guides/apps/authentication/auth-providers) and [hexclave.config.ts: Auth](https://docs.hexclave.com/guides/going-further/hexclave-config#auth).
594
595
  `,
595
596
  "fraud-protection": deindent`
597
+ Key concepts: sign-up rules are ordered checks that decide whether a sign-up should be allowed, rejected, restricted, or logged; rule priority decides which matching rule wins when multiple rules apply.
598
+
596
599
  Start by writing the first sign-up rules in \`hexclave.config.ts\`. For a company-only product, default to reject and explicitly allow the company domain:
597
600
 
598
601
  \`\`\`ts title="hexclave.config.ts"
@@ -633,6 +636,8 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
633
636
  In the app, use team IDs in deep links wherever possible, then add a team switcher for navigation convenience. If team-specific authorization matters, configure RBAC next and enforce checks on the server. See [Teams](https://docs.hexclave.com/guides/apps/teams/overview), [Team Selection](https://docs.hexclave.com/guides/apps/teams/team-selection), and [hexclave.config.ts: Teams and Users](https://docs.hexclave.com/guides/going-further/hexclave-config#teams-and-users).
634
637
  `,
635
638
  "rbac": deindent`
639
+ Key concepts: permissions are stable IDs your app checks before protected actions; scopes decide whether a permission applies globally or within a team; contained permissions let one permission include other permissions recursively.
640
+
636
641
  Start with the permission IDs the product will check in code. For a basic team app, define reader/writer permissions and an admin-style composed permission:
637
642
 
638
643
  \`\`\`ts title="hexclave.config.ts"
@@ -663,6 +668,8 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
663
668
  Use \`scope: "project"\` only for global project-level actions. Client-side permission checks are UX only; always enforce the same permissions on the server. See [RBAC Permissions](https://docs.hexclave.com/guides/apps/rbac/overview) and [hexclave.config.ts: RBAC](https://docs.hexclave.com/guides/going-further/hexclave-config#rbac).
664
669
  `,
665
670
  "api-keys": deindent`
671
+ API keys allow you to programmatically create API keys for your own users. This is useful if you have an API yourself that you want to authenticate users against.
672
+
666
673
  Start by enabling only the owner types the product actually needs. For a platform with both personal and workspace APIs:
667
674
 
668
675
  \`\`\`ts title="hexclave.config.ts"
@@ -681,6 +688,8 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
681
688
  Then expose built-in account/team settings UI or build focused create/list/revoke screens. Always validate API keys on a trusted backend before serving protected requests. See [API Keys](https://docs.hexclave.com/guides/apps/api-keys/overview) and [hexclave.config.ts: API Keys](https://docs.hexclave.com/guides/going-further/hexclave-config#api-keys).
682
689
  `,
683
690
  "payments": deindent`
691
+ Key concepts: products are the sellable plans or one-time offers customers buy; product lines group mutually exclusive products such as pricing tiers; items are quantifiable entitlements such as credits, seats, or API calls granted by products; customers are the users, teams, or custom entities that own purchases and item balances.
692
+
684
693
  Start with a minimal catalog. For a user-plan SaaS with monthly credits:
685
694
 
686
695
  \`\`\`ts title="hexclave.config.ts"
@@ -691,6 +700,7 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
691
700
  },
692
701
  items: {
693
702
  credits: { displayName: "Credits", customerType: "user" },
703
+ access: { displayName: "Product Access", customerType: "user" },
694
704
  },
695
705
  products: {
696
706
  pro: {
@@ -702,6 +712,7 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
702
712
  },
703
713
  includedItems: {
704
714
  credits: { quantity: 1000, repeat: [1, "month"], expires: "when-repeated" },
715
+ access: { quantity: 1, expires: "when-purchase-expires" },
705
716
  },
706
717
  },
707
718
  },
@@ -714,6 +725,8 @@ const appSetupPrompt: Record<PublicAppSetupPromptId, string> =
714
725
  Keep purchases in test mode while building; Stripe connection and \`payments.testMode\` are environment-specific, so configure them in the dashboard/environment rather than hard-coding secrets. In code, generate checkout URLs and read products/items to gate access. See [Payments: Getting started](https://docs.hexclave.com/guides/apps/payments/overview#getting-started), [Defining products](https://docs.hexclave.com/guides/apps/payments/overview#defining-products), and [Checking item balances](https://docs.hexclave.com/guides/apps/payments/overview#checking-item-balances).
715
726
  `,
716
727
  "emails": deindent`
728
+ Key concepts: templates define reusable email content with variables; themes provide shared branding around templates; transactional emails are required product emails, while marketing emails must respect opt-out expectations.
729
+
717
730
  Start with delivery: shared delivery is fine for development, but production should use Managed, Resend, or custom SMTP from **Emails -> Email Settings**. Delivery credentials and sender settings are environment-specific, so do not put secrets in \`hexclave.config.ts\`.
718
731
 
719
732
  Use config for versioned content. For example, add a product-specific template once you have the copy:
@@ -1272,6 +1285,8 @@ export const aiSetupPrompt = deindent`
1272
1285
 
1273
1286
  To use it, you can use the sections below to set up Hexclave in the project. For example, if you are setting up a Svelte project, you would follow the SDK setup instructions for a frontend JS project.
1274
1287
 
1288
+ ${remindersPrompt}
1289
+
1275
1290
  ${getSdkSetupPrompt("ai-prompt")}
1276
1291
 
1277
1292
  ${convexSetupPrompt}
@@ -255,68 +255,7 @@ const docsJson = {
255
255
  "/code-language-labels.js"
256
256
  ]
257
257
  },
258
- "redirects": [
259
- {
260
- "source": "/sdk/objects/stack-app",
261
- "destination": "/sdk/objects/hexclave-app"
262
- },
263
- {
264
- "source": "/sdk/hooks/use-stack-app",
265
- "destination": "/sdk/hooks/use-hexclave-app"
266
- },
267
- {
268
- "source": "/rest-api/overview",
269
- "destination": "/api/overview"
270
- },
271
- {
272
- "source": "/getting-started/setup",
273
- "destination": "/guides/getting-started/setup"
274
- },
275
- {
276
- "source": "/docs/getting-started/setup",
277
- "destination": "/guides/getting-started/setup"
278
- },
279
- {
280
- "source": "/docs/next/getting-started/setup",
281
- "destination": "/guides/getting-started/setup"
282
- },
283
- {
284
- "source": "/docs/sdk",
285
- "destination": "/sdk/overview"
286
- },
287
- {
288
- "source": "/docs/apps/analytics",
289
- "destination": "/guides/apps/analytics/overview"
290
- },
291
- {
292
- "source": "/docs/apps/api-keys",
293
- "destination": "/guides/apps/api-keys/overview"
294
- },
295
- {
296
- "source": "/docs/others/convex",
297
- "destination": "/guides/integrations/convex/overview"
298
- },
299
- {
300
- "source": "/docs/concepts/teams",
301
- "destination": "/guides/apps/teams/overview"
302
- },
303
- {
304
- "source": "/docs/concepts/custom-user-data",
305
- "destination": "/guides/getting-started/user-fundamentals#custom-metadata"
306
- },
307
- {
308
- "source": "/guides/going-further/user-metadata",
309
- "destination": "/guides/getting-started/user-fundamentals#custom-metadata"
310
- },
311
- {
312
- "source": "/others/js-client",
313
- "destination": "/sdk/objects/hexclave-app"
314
- },
315
- {
316
- "source": "/guides/going-further/stack-app",
317
- "destination": "/sdk/objects/hexclave-app"
318
- }
319
- ]
258
+ "redirects": []
320
259
  } as const;
321
260
 
322
261
  export default docsJson;