@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.
- package/dist/ai/unified-prompts/reminders.js +1 -0
- package/dist/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +15 -0
- package/dist/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +1 -46
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +1 -62
- package/dist/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/config/schema.d.ts +30 -30
- package/dist/config-authoring.d.ts +2 -2
- package/dist/config-authoring.d.ts.map +1 -1
- package/dist/config-authoring.js.map +1 -1
- package/dist/esm/ai/unified-prompts/reminders.js +1 -0
- package/dist/esm/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.d.ts.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js +15 -0
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.js.map +1 -1
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.d.ts +1 -46
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js +1 -62
- package/dist/esm/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.js.map +1 -1
- package/dist/esm/config/schema.d.ts +30 -30
- package/dist/esm/config-authoring.d.ts +2 -2
- package/dist/esm/config-authoring.d.ts.map +1 -1
- package/dist/esm/config-authoring.js.map +1 -1
- package/dist/esm/interface/admin-metrics.d.ts +10 -10
- package/dist/esm/interface/conversations.d.ts +11 -11
- package/dist/esm/interface/crud/current-user.d.ts +8 -8
- package/dist/esm/interface/crud/email-outbox.d.ts +184 -184
- package/dist/esm/interface/crud/invoices.d.ts +2 -2
- package/dist/esm/interface/crud/products.d.ts +15 -15
- package/dist/esm/interface/crud/products.d.ts.map +1 -1
- package/dist/esm/interface/crud/project-api-keys.d.ts +4 -4
- package/dist/esm/interface/crud/projects.d.ts +50 -0
- package/dist/esm/interface/crud/projects.d.ts.map +1 -1
- package/dist/esm/interface/crud/projects.js +6 -0
- package/dist/esm/interface/crud/projects.js.map +1 -1
- package/dist/esm/interface/crud/team-member-profiles.d.ts +12 -12
- package/dist/esm/interface/crud/transactions.d.ts +20 -20
- package/dist/esm/interface/crud/transactions.d.ts.map +1 -1
- package/dist/esm/interface/crud/users.d.ts +8 -8
- package/dist/esm/interface/webhooks.d.ts +2 -2
- package/dist/esm/known-errors.d.ts +1 -1
- package/dist/esm/schema-fields.d.ts +1 -1
- package/dist/esm/sessions.d.ts +7 -7
- package/dist/esm/utils/env.d.ts +2 -1
- package/dist/esm/utils/env.d.ts.map +1 -1
- package/dist/esm/utils/env.js +29 -17
- package/dist/esm/utils/env.js.map +1 -1
- package/dist/esm/utils/env.test.d.ts +1 -0
- package/dist/esm/utils/env.test.js +49 -0
- package/dist/esm/utils/env.test.js.map +1 -0
- package/dist/esm/utils/errors.d.ts.map +1 -1
- package/dist/esm/utils/errors.js +4 -1
- package/dist/esm/utils/errors.js.map +1 -1
- package/dist/interface/admin-metrics.d.ts +10 -10
- package/dist/interface/conversations.d.ts +11 -11
- package/dist/interface/crud/current-user.d.ts +8 -8
- package/dist/interface/crud/email-outbox.d.ts +184 -184
- package/dist/interface/crud/invoices.d.ts +2 -2
- package/dist/interface/crud/products.d.ts +15 -15
- package/dist/interface/crud/products.d.ts.map +1 -1
- package/dist/interface/crud/project-api-keys.d.ts +4 -4
- package/dist/interface/crud/projects.d.ts +50 -0
- package/dist/interface/crud/projects.d.ts.map +1 -1
- package/dist/interface/crud/projects.js +6 -0
- package/dist/interface/crud/projects.js.map +1 -1
- package/dist/interface/crud/team-member-profiles.d.ts +12 -12
- package/dist/interface/crud/transactions.d.ts +20 -20
- package/dist/interface/crud/transactions.d.ts.map +1 -1
- package/dist/interface/crud/users.d.ts +8 -8
- package/dist/interface/webhooks.d.ts +2 -2
- package/dist/known-errors.d.ts +1 -1
- package/dist/schema-fields.d.ts +1 -1
- package/dist/sessions.d.ts +7 -7
- package/dist/utils/env.d.ts +2 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js +29 -16
- package/dist/utils/env.js.map +1 -1
- package/dist/utils/env.test.d.ts +1 -0
- package/dist/utils/env.test.js +49 -0
- package/dist/utils/env.test.js.map +1 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +4 -1
- package/dist/utils/errors.js.map +1 -1
- package/package.json +1 -1
- package/src/ai/unified-prompts/reminders.ts +1 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts +15 -0
- package/src/ai/unified-prompts/skill-site-prompt-parts/docs-json.generated.ts +1 -62
- package/src/config-authoring.ts +2 -2
- package/src/interface/crud/projects.ts +12 -0
- package/src/utils/env.test.tsx +58 -0
- package/src/utils/env.tsx +36 -20
- package/src/utils/errors.tsx +6 -1
package/src/config-authoring.ts
CHANGED
|
@@ -27,11 +27,11 @@ type StrictStackConfig<T extends StackConfig> =
|
|
|
27
27
|
: T;
|
|
28
28
|
|
|
29
29
|
/** @deprecated Use `defineHexclaveConfig` from the `@hexclave/*` package instead — same symbol, new brand name. See https://docs.hexclave.com/migration. */
|
|
30
|
-
export function defineStackConfig
|
|
30
|
+
export function defineStackConfig(config: StrictStackConfig<StackConfig>): StackConfig {
|
|
31
31
|
return config;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Hexclave alias — separate function so it does not inherit the deprecation tag.
|
|
35
|
-
export function defineHexclaveConfig
|
|
35
|
+
export function defineHexclaveConfig(config: StrictStackConfig<HexclaveConfig>): HexclaveConfig {
|
|
36
36
|
return config;
|
|
37
37
|
}
|
|
@@ -32,6 +32,14 @@ const enabledOAuthProviderSchema = yupObject({
|
|
|
32
32
|
id: schemaFields.oauthIdSchema.defined(),
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
const pushedConfigErrorSchema = yupObject({
|
|
36
|
+
message: yupString().defined(),
|
|
37
|
+
}).defined();
|
|
38
|
+
|
|
39
|
+
const configWarningSchema = yupObject({
|
|
40
|
+
message: yupString().defined(),
|
|
41
|
+
}).defined();
|
|
42
|
+
|
|
35
43
|
const onboardingConfigChoiceValues = ["create-new", "link-existing"] as const;
|
|
36
44
|
const onboardingSignInMethodValues = ["credential", "magicLink", "passkey", "google", "github", "microsoft"] as const;
|
|
37
45
|
const onboardingPaymentsCountryValues = ["US", "OTHER"] as const;
|
|
@@ -89,6 +97,8 @@ export const projectsCrudAdminReadSchema = yupObject({
|
|
|
89
97
|
owner_team_id: schemaFields.yupString().nullable().defined(),
|
|
90
98
|
onboarding_status: schemaFields.projectOnboardingStatusSchema.defined(),
|
|
91
99
|
onboarding_state: projectOnboardingStateSchema.nullable().optional(),
|
|
100
|
+
pushed_config_error: pushedConfigErrorSchema.nullable().defined(),
|
|
101
|
+
config_warnings: yupArray(configWarningSchema).defined(),
|
|
92
102
|
/** @deprecated */
|
|
93
103
|
config: yupObject({
|
|
94
104
|
allow_localhost: schemaFields.projectAllowLocalhostSchema.defined(),
|
|
@@ -117,6 +127,8 @@ export const projectsCrudAdminReadSchema = yupObject({
|
|
|
117
127
|
export const projectsCrudClientReadSchema = yupObject({
|
|
118
128
|
id: schemaFields.projectIdSchema.defined(),
|
|
119
129
|
display_name: schemaFields.projectDisplayNameSchema.defined(),
|
|
130
|
+
pushed_config_error: pushedConfigErrorSchema.nullable().defined(),
|
|
131
|
+
config_warnings: yupArray(configWarningSchema).defined(),
|
|
120
132
|
config: yupObject({
|
|
121
133
|
sign_up_enabled: schemaFields.projectSignUpEnabledSchema.defined(),
|
|
122
134
|
credential_enabled: schemaFields.projectCredentialEnabledSchema.defined(),
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { getEnvVariable, getProcessEnv, resolveHexclaveStackEnvVarValue } from "./env";
|
|
3
|
+
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
vi.unstubAllEnvs();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
describe("Hexclave/Stack env var dual-read", () => {
|
|
9
|
+
it("falls back to the legacy Stack name when the Hexclave value is empty", () => {
|
|
10
|
+
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "");
|
|
11
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
|
|
12
|
+
|
|
13
|
+
expect(getEnvVariable("NEXT_PUBLIC_STACK_API_URL")).toBe("https://stack.example.test");
|
|
14
|
+
expect(getProcessEnv("NEXT_PUBLIC_STACK_API_URL")).toBe("https://stack.example.test");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("allows both names when they have the same non-empty value", () => {
|
|
18
|
+
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://api.example.test");
|
|
19
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://api.example.test");
|
|
20
|
+
|
|
21
|
+
expect(getEnvVariable("NEXT_PUBLIC_STACK_API_URL")).toBe("https://api.example.test");
|
|
22
|
+
expect(getProcessEnv("NEXT_PUBLIC_STACK_API_URL")).toBe("https://api.example.test");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("throws when both names are non-empty and different", () => {
|
|
26
|
+
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://hexclave.example.test");
|
|
27
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
|
|
28
|
+
|
|
29
|
+
expect(() => getEnvVariable("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
|
|
30
|
+
expect(() => getProcessEnv("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("checks renamed legacy aliases when falling back", () => {
|
|
34
|
+
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_URL", "https://hexclave-url.example.test");
|
|
35
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_URL", "https://stack-url.example.test");
|
|
36
|
+
|
|
37
|
+
expect(() => getEnvVariable("NEXT_PUBLIC_STACK_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_URL.*NEXT_PUBLIC_STACK_URL.*different values/);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("returns undefined when both names are empty", () => {
|
|
41
|
+
expect(resolveHexclaveStackEnvVarValue("HEXCLAVE_FOO", "STACK_FOO", "", "")).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("falls back to the legacy Stack name when a canonical Hexclave name is looked up", () => {
|
|
45
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
|
|
46
|
+
|
|
47
|
+
// Caller passes the canonical HEXCLAVE_ name but only the legacy value is set.
|
|
48
|
+
expect(getEnvVariable("NEXT_PUBLIC_HEXCLAVE_API_URL")).toBe("https://stack.example.test");
|
|
49
|
+
expect(getProcessEnv("NEXT_PUBLIC_HEXCLAVE_API_URL")).toBe("https://stack.example.test");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("throws on a conflict when a canonical Hexclave name is looked up", () => {
|
|
53
|
+
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_API_URL", "https://hexclave.example.test");
|
|
54
|
+
vi.stubEnv("NEXT_PUBLIC_STACK_API_URL", "https://stack.example.test");
|
|
55
|
+
|
|
56
|
+
expect(() => getEnvVariable("NEXT_PUBLIC_HEXCLAVE_API_URL")).toThrow(/NEXT_PUBLIC_HEXCLAVE_API_URL.*NEXT_PUBLIC_STACK_API_URL.*different values/);
|
|
57
|
+
});
|
|
58
|
+
});
|
package/src/utils/env.tsx
CHANGED
|
@@ -6,22 +6,37 @@ export function isBrowserLike() {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// newName: oldName
|
|
9
|
-
const ENV_VAR_RENAME: Record<string, string[]> = {
|
|
9
|
+
const ENV_VAR_RENAME: Record<string, string[] | undefined> = {
|
|
10
10
|
NEXT_PUBLIC_STACK_API_URL: ['STACK_BASE_URL', 'NEXT_PUBLIC_STACK_URL'],
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
export function resolveHexclaveStackEnvVarValue(hexclaveName: string, stackName: string, hexclaveValue: string | undefined, stackValue: string | undefined): string | undefined {
|
|
14
|
+
if (hexclaveValue && stackValue && hexclaveValue !== stackValue) {
|
|
15
|
+
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.`);
|
|
16
|
+
}
|
|
17
|
+
return hexclaveValue || stackValue || undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
/**
|
|
14
|
-
* Hexclave rebrand:
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
21
|
+
* Hexclave rebrand: resolve an env var by reading both the `HEXCLAVE_*` and
|
|
22
|
+
* `STACK_*` spellings, preferring the canonical Hexclave value and falling back
|
|
23
|
+
* to the legacy Stack value (empty counts as unset). Works in BOTH directions —
|
|
24
|
+
* whether the caller passes the legacy `STACK_FOO` name or the canonical
|
|
25
|
+
* `HEXCLAVE_FOO` name, the other spelling is still honored. Covers `STACK_FOO`,
|
|
26
|
+
* `NEXT_PUBLIC_STACK_FOO`, `NEXT_PUBLIC_BROWSER_STACK_FOO`,
|
|
27
|
+
* `NEXT_PUBLIC_SERVER_STACK_FOO`, `VITE_STACK_FOO` and their HEXCLAVE_ twins.
|
|
28
|
+
* Names with neither segment behave exactly as before.
|
|
19
29
|
*/
|
|
20
|
-
function
|
|
21
|
-
if (
|
|
22
|
-
|
|
30
|
+
function getEnvVarWithHexclaveFallback(name: string): string | undefined {
|
|
31
|
+
if (name.includes("STACK_")) {
|
|
32
|
+
const hexclaveName = name.replace("STACK_", "HEXCLAVE_");
|
|
33
|
+
return resolveHexclaveStackEnvVarValue(hexclaveName, name, process.env[hexclaveName], process.env[name]);
|
|
34
|
+
}
|
|
35
|
+
if (name.includes("HEXCLAVE_")) {
|
|
36
|
+
const stackName = name.replace("HEXCLAVE_", "STACK_");
|
|
37
|
+
return resolveHexclaveStackEnvVarValue(name, stackName, process.env[name], process.env[stackName]);
|
|
23
38
|
}
|
|
24
|
-
return name
|
|
39
|
+
return process.env[name];
|
|
25
40
|
}
|
|
26
41
|
|
|
27
42
|
/**
|
|
@@ -45,21 +60,21 @@ export function getEnvVariable(name: string, defaultValue?: string | undefined):
|
|
|
45
60
|
|
|
46
61
|
// throw error if the old name is used as the retrieve key
|
|
47
62
|
for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) {
|
|
48
|
-
if (oldNames
|
|
63
|
+
if (oldNames?.includes(name)) {
|
|
49
64
|
throwErr(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);
|
|
50
65
|
}
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
// Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
// Treat the empty string as unset — the checked-in .env templates define empty
|
|
70
|
+
// HEXCLAVE_* placeholders, which must not shadow a real value under the legacy name.
|
|
71
|
+
let value = getEnvVarWithHexclaveFallback(name);
|
|
56
72
|
|
|
57
73
|
// check the key under the old name if the new name is not found
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
value = (hexclaveOldName ? process.env[hexclaveOldName] : undefined) ?? process.env[oldName];
|
|
74
|
+
const renamedNames = ENV_VAR_RENAME[name];
|
|
75
|
+
if (!value && renamedNames != null) {
|
|
76
|
+
for (const oldName of renamedNames) {
|
|
77
|
+
value = getEnvVarWithHexclaveFallback(oldName);
|
|
63
78
|
if (value) break;
|
|
64
79
|
}
|
|
65
80
|
}
|
|
@@ -112,6 +127,7 @@ export function getProcessEnv(name: string): string | undefined {
|
|
|
112
127
|
return undefined;
|
|
113
128
|
}
|
|
114
129
|
// Hexclave rebrand: prefer the HEXCLAVE_*-prefixed equivalent, fall back to the STACK_* name.
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
// Empty counts as unset — the checked-in .env templates define empty HEXCLAVE_* placeholders,
|
|
131
|
+
// which must not shadow a real value under the legacy name.
|
|
132
|
+
return getEnvVarWithHexclaveFallback(name);
|
|
117
133
|
}
|
package/src/utils/errors.tsx
CHANGED
|
@@ -80,7 +80,12 @@ export class HexclaveAssertionError extends Error {
|
|
|
80
80
|
|
|
81
81
|
// Use literal dot-form (guarded with `typeof process`) so Next.js / webpack
|
|
82
82
|
// DefinePlugin can inline the value at build time. See getProcessEnv in ./env.
|
|
83
|
-
|
|
83
|
+
const hexclaveDebuggerValue = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_HEXCLAVE_DEBUGGER_ON_ASSERTION_ERROR : undefined;
|
|
84
|
+
const stackDebuggerValue = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_STACK_DEBUGGER_ON_ASSERTION_ERROR : undefined;
|
|
85
|
+
if (hexclaveDebuggerValue && stackDebuggerValue && hexclaveDebuggerValue !== stackDebuggerValue) {
|
|
86
|
+
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.");
|
|
87
|
+
}
|
|
88
|
+
if ((hexclaveDebuggerValue || stackDebuggerValue) === "true") {
|
|
84
89
|
debugger;
|
|
85
90
|
}
|
|
86
91
|
}
|