stack/packages/react/package.json
BilalG1 7f99f15b42
fix(rde): graceful config load errors + lightweight /config import path (#1557)
## Problem

A user hit `Failed to register development environment session (500)`
when running the RDE (`hexclave dev` / `stack dev`). Removing
`defineStackConfig` from their `stack.config.ts` made it go away.

**Root cause:** the local dashboard evaluates the project's config file
in a plain Node context via `jiti`
([config-file.ts](apps/dashboard/src/lib/remote-development-environment/config-file.ts)).
When the config imports a *value* (e.g. `defineStackConfig`) from a
framework package like `@stackframe/stack` / `@hexclave/next`, jiti
executes the entire SDK — React, `server-only`, Next internals — which
throws in that context. The exception propagated as a bare 500. Dropping
`defineStackConfig` removed the value import, so jiti no longer loaded
the framework.

## Changes

**1. Graceful error (Fix 3)**
`readConfigFile` now wraps the `jiti.import` in try/catch and rethrows a
message pointing at the lightweight import path, instead of a raw 500.

**2. Lightweight `/config` subpath (Fix 1)**
Added a side-effect-free `./config` entrypoint to the framework packages
— `@hexclave/{js,next,react,tanstack-start}/config` — that re-exports
`defineHexclaveConfig` / `defineStackConfig` + the `HexclaveConfig` type
from `@hexclave/shared/config`, with **no framework runtime**. Source of
truth:
[`packages/template/src/config.ts`](packages/template/src/config.ts) +
the export in
[`package-template.json`](packages/template/package-template.json),
propagated to the generated packages via `generate-sdks`.

> Why per-package and not `@hexclave/shared/config`: `@hexclave/shared`
is only a *transitive* dependency from a user's perspective, so
importing from it fails under pnpm strict mode. Users depend on the
framework package directly, so `@hexclave/next/config` always resolves.
This was confirmed empirically — the previous tests that imported
`@hexclave/shared/config` were red.

**3. Docs / prompts / renderer aligned to the new path**
-
[`ai-setup-prompt.ts`](packages/shared/src/ai/unified-prompts/skill-site-prompt-parts/ai-setup-prompt.ts)
+ regenerated `docs-mintlify` (setup.mdx, llms-full.txt, snippets).
- Hand-written
[`hexclave-config.mdx`](docs-mintlify/guides/going-further/hexclave-config.mdx)
and
[`local-vs-cloud-dashboard.mdx`](docs-mintlify/guides/going-further/local-vs-cloud-dashboard.mdx).
(`docs/**` left untouched — legacy.)
- `renderConfigFileContent` (the config file the dashboard/CLI
auto-writes) now emits `import type { HexclaveConfig } from
"<pkg>/config"`. Legacy `@stackframe/*` packages predate the subpath, so
they keep their root import (guarded).

## Behavioral note

Existing config files that import from a package root get their import
line upgraded to `/config` on their next dashboard/CLI sync — a
one-time, harmless rewrite that migrates them onto the safe path. The
github-config-push idempotence test was updated to use the current
`/config` format so it still genuinely verifies "no spurious commit."

## Testing

- 43 unit tests pass across `config-file`, `github-config-push`,
`config-rendering`, `config-authoring`, `local-emulator`. The two
previously-red RDE `define*` tests now pass through jiti via
`@hexclave/next/config` (the real code path), and were made
resolution-stable by rooting their temp dir at the test file instead of
`process.cwd()`.
- Typecheck green on all source-changed packages (shared, cli, js, next,
react, tanstack-start). Lint clean.
- ⚠️ The two e2e suites (`cli.test.ts`, `config-local-emulator.test.ts`)
need backend+DB infra; their snapshot updates are mechanical and
**confirmable only in CI**.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Prevents 500s when loading `hexclave.config.ts` by adding a lightweight
`<pkg>/config` entrypoint and showing a clear, actionable error without
leaking framework stacks. Import detection, rendering, CLI, tests, and
docs now default to `/config` (including `@hexclave/tanstack-start`) so
configs load in plain Node contexts.

- **New Features**
- Added `/config` subpaths in `@hexclave/js`, `@hexclave/next`,
`@hexclave/react`, `@hexclave/tanstack-start` (and template)
re-exporting `defineHexclaveConfig`, `defineStackConfig`, and
`HexclaveConfig` with no framework runtime.
- Renderer, CLI, and docs import `HexclaveConfig` from `<pkg>/config`;
legacy `@stackframe/*` keep root imports. Existing config files
auto-upgrade on next dashboard/CLI sync.

- **Bug Fixes**
- Wrapped `jiti` config load with try/catch; capture raw error for
diagnostics and show a concise message pointing to `<pkg>/config` (no
nested framework stack traces).
- Import detection accepts optional `/config` suffix; renderer always
appends `/config` for Hexclave packages and recognizes
`@hexclave/tanstack-start`.
- Tests stabilized by scoping temp dirs to the test file; CLI error
example now references `HexclaveConfig` from `<pkg>/config` for Hexclave
packages.

<sup>Written for commit dfe7d5fee4.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1557?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added lightweight "/config" subpath exports across SDK packages to
enable side-effect-free config authoring in plain Node contexts.

* **Documentation**
* Updated guides and snippets to recommend importing config types and
helpers from the "/config" entrypoint and added example usage.

* **Bug Fixes**
* Improved error messaging when dynamic config imports fail, with
guidance to use the "/config" entrypoint.

* **Tests**
* Adjusted tests and snapshots to expect normalized "/config" import
paths.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-10 11:40:19 -07:00

135 lines
4.2 KiB
JSON

{
"//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)",
"name": "@hexclave/react",
"version": "1.0.11",
"repository": "https://github.com/hexclave/hexclave",
"sideEffects": false,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": {
"default": "./dist/esm/index.js"
},
"require": {
"default": "./dist/index.js"
}
},
"./config": {
"types": "./dist/config.d.ts",
"import": {
"default": "./dist/esm/config.js"
},
"require": {
"default": "./dist/config.js"
}
},
"./convex.config": {
"types": "./dist/integrations/convex/component/convex.config.d.ts",
"import": {
"default": "./dist/esm/integrations/convex/component/convex.config.js"
},
"require": {
"default": "./dist/integrations/convex/component/convex.config.js"
}
},
"./convex-auth.config": {
"types": "./dist/integrations/convex.d.ts",
"import": {
"default": "./dist/esm/integrations/convex.js"
},
"require": {
"default": "./dist/integrations/convex.js"
}
}
},
"homepage": "https://hexclave.com",
"scripts": {
"typecheck": "tsc --noEmit",
"clean": "rimraf dist && rimraf node_modules",
"lint": "eslint --ext .tsx,.ts .",
"codegen": "pnpm run env && pnpm run css",
"codegen:watch": "concurrently -n \"env,css\" -k \"pnpm run env:watch\" \"pnpm run css:watch\"",
"build": "rimraf dist && pnpm run codegen && tsdown",
"dev": "concurrently -n \"build,codegen\" -k \"tsdown --watch\" \"pnpm run codegen:watch\"",
"env": "tsx ./scripts/generate-env.ts",
"env:watch": "chokidar --silent './scripts/generate-env.ts' -c 'pnpm run env' --throttle 2000",
"css": "pnpm run css-tw && pnpm run css-sc",
"css:watch": "concurrently -n \"tw,sc\" -k \"pnpm run css-tw:watch\" \"pnpm run css-sc:watch\"",
"css-tw:watch": "tailwindcss -i ./src/global.css -o ./src/generated/tailwind.css --watch",
"css-tw": "tailwindcss -i ./src/global.css -o ./src/generated/tailwind.css",
"css-sc": "tsx ./scripts/process-css.ts ./src/generated/tailwind.css ./src/generated/global-css.ts",
"css-sc:watch": "chokidar --silent './src/generated/tailwind.css' -c 'pnpm run css-sc' --throttle 2000"
},
"files": [
"README.md",
"dist",
"src",
"CHANGELOG.md",
"LICENSE"
],
"dependencies": {
"@ai-sdk/react": "^3.0.72",
"ai": "^6.0.0",
"@hookform/resolvers": "^5.2.2",
"@stripe/react-stripe-js": "^3.8.1",
"@stripe/stripe-js": "^7.7.0",
"@simplewebauthn/browser": "^13.2.2",
"@hexclave/shared": "workspace:*",
"@hexclave/ui": "workspace:*",
"@tanstack/react-table": "^8.21.3",
"browser-image-compression": "^2.0.2",
"color": "^5.0.3",
"cookie": "^1.1.1",
"jose": "^6.1.3",
"js-cookie": "^3.0.5",
"lucide-react": "^0.378.0",
"oauth4webapi": "^3.8.3",
"@oslojs/otp": "^1.1.0",
"qrcode": "^1.5.4",
"react-easy-crop": "^5.5.6",
"react-hook-form": "^7.70.0",
"tailwindcss-animate": "^1.0.7",
"rrweb": "^1.1.3",
"tsx": "^4.21.0",
"yup": "^1.7.1"
},
"peerDependencies": {
"@types/react": ">=18.0.0",
"@types/react-dom": ">=18.0.0",
"react-dom": ">=18.0.0",
"react": ">=18.0.0"
},
"peerDependenciesMeta": {
"@types/react-dom": {
"optional": true
},
"@types/react": {
"optional": true
}
},
"devDependencies": {
"@quetzallabs/i18n": "^0.1.19",
"@types/color": "^3.0.6",
"@types/cookie": "^0.6.0",
"@types/js-cookie": "^3.0.6",
"@types/qrcode": "^1.5.5",
"@types/react-avatar-editor": "^13.0.3",
"autoprefixer": "^10.4.17",
"chokidar-cli": "^3.0.0",
"esbuild": "^0.20.2",
"i18next": "^23.14.0",
"i18next-parser": "^9.0.2",
"postcss": "^8.4.38",
"postcss-nested": "^6.0.1",
"react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"react-dom": "^19.0.0",
"rimraf": "^6.1.2",
"tailwindcss": "^3.4.4",
"tsdown": "^0.20.3",
"convex": "^1.27.0"
}
}