@elytracms/cli 0.0.82 → 0.0.83
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/package.json +3 -3
- package/src/config-harness.js +65 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elytracms/cli",
|
|
3
3
|
"author": "finaldream <hi@finaldream.de>",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.83",
|
|
5
5
|
"description": "The Elytra CLI — run a consuming repo's studio, frontend, and Convex backend under one command.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=22.18.0"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@elytracms/core": "^0.0.
|
|
20
|
+
"@elytracms/core": "^0.0.83"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"vitest": "^4.1.10"
|
package/src/config-harness.js
CHANGED
|
@@ -75,6 +75,66 @@ export function virtualModulesPlugin(name, modules) {
|
|
|
75
75
|
* because the studio `vite.config.ts` is never loaded), and automatic JSX so
|
|
76
76
|
* `.tsx` component barrels transform without the app's React plugin.
|
|
77
77
|
*/
|
|
78
|
+
/**
|
|
79
|
+
* React specifiers the automatic-JSX transform injects, aliased to the STUDIO's
|
|
80
|
+
* own copies (EC-537).
|
|
81
|
+
*
|
|
82
|
+
* `jsx: 'automatic'` below rewrites every transformed `.tsx` to import
|
|
83
|
+
* `react/jsx-dev-runtime`, and Vite resolves a bare specifier from the
|
|
84
|
+
* IMPORTER's directory. A consumer's page-builder components live at their repo
|
|
85
|
+
* root, outside `studioDir` — so on a repo whose root `package.json` does not
|
|
86
|
+
* declare react, every one of them fails to resolve and `config-valid` reports
|
|
87
|
+
* a config that "could not be executed", taking `asset-collection` and
|
|
88
|
+
* `presentation-targets` down with it.
|
|
89
|
+
*
|
|
90
|
+
* Measured 2026-08-02 on a real `create-elytra@0.0.82` scaffold, both
|
|
91
|
+
* directions: with react at the root `✓ config-valid` (11 ok); with react
|
|
92
|
+
* removed, `✗ Cannot find module 'react/jsx-dev-runtime' imported from
|
|
93
|
+
* components/marketing/hero.tsx` and three checks lost. Both production
|
|
94
|
+
* consumers hit exactly this on upgrading and both added react to their root.
|
|
95
|
+
*
|
|
96
|
+
* That was a workaround for a requirement the HARNESS invented: automatic JSX is
|
|
97
|
+
* our transform setting, chosen for our convenience, in a boot whose only job is
|
|
98
|
+
* to *evaluate* a config — nothing here mounts or renders. So the package that
|
|
99
|
+
* mandated React supplies it. The studio always has react (it is a React app),
|
|
100
|
+
* and resolving from `studioDir` is what this harness already does for `vite`
|
|
101
|
+
* itself, one line above.
|
|
102
|
+
*
|
|
103
|
+
* Opportunistic by contract, like everything else in this file: a specifier that
|
|
104
|
+
* cannot be resolved is simply left unaliased rather than throwing, so a partial
|
|
105
|
+
* install degrades to the previous behaviour instead of crashing the CLI.
|
|
106
|
+
*/
|
|
107
|
+
export function reactRuntimeFromStudioPlugin(studioDir) {
|
|
108
|
+
// Resolve THROUGH VITE, from a studio-side importer — never to a raw path.
|
|
109
|
+
//
|
|
110
|
+
// The obvious implementation is `resolve.alias` to
|
|
111
|
+
// `createRequire(studioDir).resolve('react/jsx-dev-runtime')`. That was tried
|
|
112
|
+
// first and is wrong twice over (both measured 2026-08-02): `createRequire`
|
|
113
|
+
// returns the **CJS** entry, and an absolute-path alias bypasses Vite's
|
|
114
|
+
// exports-map/condition/interop handling entirely, so its SSR runner
|
|
115
|
+
// evaluates CommonJS as ESM — `elytra previews` died with
|
|
116
|
+
// `ReferenceError: module is not defined` at `react/index.js:9`, then at
|
|
117
|
+
// `react/jsx-dev-runtime.js:9` when the alias was narrowed.
|
|
118
|
+
//
|
|
119
|
+
// Handing Vite a studio-side *importer* instead lets its own resolver do the
|
|
120
|
+
// work — right conditions, right ESM build — while only changing WHERE the
|
|
121
|
+
// lookup starts. That is the whole intent: not a different React, just one
|
|
122
|
+
// that can be found.
|
|
123
|
+
const importer = join(studioDir, '__elytra-harness__.js')
|
|
124
|
+
return {
|
|
125
|
+
name: 'elytra:react-runtime-from-studio',
|
|
126
|
+
async resolveId(id, from) {
|
|
127
|
+
if (id !== 'react/jsx-runtime' && id !== 'react/jsx-dev-runtime') return null
|
|
128
|
+
// Only rescue importers OUTSIDE the studio (the consumer's root-level
|
|
129
|
+
// components). Anything already inside studio/ resolves on its own, and
|
|
130
|
+
// intercepting it would be a silent no-op at best.
|
|
131
|
+
if (from === undefined || from.startsWith(studioDir)) return null
|
|
132
|
+
const resolved = await this.resolve(id, importer, { skipSelf: true })
|
|
133
|
+
return resolved ?? null
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
78
138
|
export async function startConsumerVite({ root, studioDir, port, plugins }) {
|
|
79
139
|
const vite = await import(pathToFileURL(resolveFromDir(studioDir, 'vite')).href)
|
|
80
140
|
const server = await vite.createServer({
|
|
@@ -83,7 +143,11 @@ export async function startConsumerVite({ root, studioDir, port, plugins }) {
|
|
|
83
143
|
mode: 'development',
|
|
84
144
|
appType: 'custom',
|
|
85
145
|
logLevel: 'warn',
|
|
86
|
-
plugins
|
|
146
|
+
// EC-537 — the rescue runs BEFORE the caller's plugins so nothing downstream
|
|
147
|
+
// has to know about it. `dedupe` rides along: once the consumer's components
|
|
148
|
+
// and the studio can both resolve React, they must agree on ONE copy.
|
|
149
|
+
plugins: [reactRuntimeFromStudioPlugin(studioDir), ...(plugins ?? [])],
|
|
150
|
+
resolve: { dedupe: ['react', 'react-dom'] },
|
|
87
151
|
server: {
|
|
88
152
|
port,
|
|
89
153
|
strictPort: true,
|