@solidjs/vite-plugin 3.0.0-next.33 → 3.0.0-next.35
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/README.md +9 -9
- package/dist/cjs/index.cjs +297 -45
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +297 -45
- package/dist/esm/index.mjs.map +1 -1
- package/dist/types/src/diagnostics/index.d.ts +5 -0
- package/dist/types/src/index.d.ts +17 -5
- package/dist/types/src/server-functions/compile.d.ts +1 -1
- package/dist/types/src/ssr/index.d.ts +1 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -693,8 +693,8 @@ your entry files instead. See `examples/start-ssr` for a complete page.
|
|
|
693
693
|
- Default: `"native"`
|
|
694
694
|
|
|
695
695
|
Choose the JSX compiler backend. The default `"native"` compiles JSX through
|
|
696
|
-
the native compiler from `@
|
|
697
|
-
|
|
696
|
+
the native compiler from `@solidjs/compiler`. `"babel"` runs
|
|
697
|
+
`@solidjs/babel-plugin` instead and only switches the JSX transform — every
|
|
698
698
|
other pass (the `lazy()` module-URL transform and the solid-refresh HMR
|
|
699
699
|
transform) is native in both modes.
|
|
700
700
|
|
|
@@ -702,7 +702,7 @@ transform) is native in both modes.
|
|
|
702
702
|
you expect, set `compiler: 'babel'` and file an issue — the behavioral diff
|
|
703
703
|
between the two modes is the bug report. Platforms without a prebuilt native
|
|
704
704
|
binary (for example StackBlitz WebContainers) automatically fall back to the
|
|
705
|
-
`@
|
|
705
|
+
`@solidjs/compiler-wasm32-wasi` build, so no configuration is needed
|
|
706
706
|
there.
|
|
707
707
|
|
|
708
708
|
```ts
|
|
@@ -723,13 +723,13 @@ Pass any additional [babel transform options](https://babeljs.io/docs/en/options
|
|
|
723
723
|
|
|
724
724
|
#### options.solid
|
|
725
725
|
|
|
726
|
-
- Type: [@
|
|
726
|
+
- Type: [@solidjs/compiler](https://github.com/solidjs/solid/tree/main/packages/compiler) / [@solidjs/babel-plugin](https://github.com/solidjs/solid/tree/main/packages/babel-plugin)
|
|
727
727
|
- Default: {}
|
|
728
728
|
|
|
729
|
-
Pass additional
|
|
730
|
-
|
|
731
|
-
context, and conditional wrapping)
|
|
732
|
-
selected.
|
|
729
|
+
Pass additional Solid JSX compiler options. Both backends carry the Solid
|
|
730
|
+
defaults (`moduleName: "@solidjs/web"`, the control-flow built-ins,
|
|
731
|
+
custom-element context, and conditional wrapping) internally; anything set
|
|
732
|
+
here is merged over them and applied to whichever backend is selected.
|
|
733
733
|
|
|
734
734
|
#### options.typescript
|
|
735
735
|
|
|
@@ -778,7 +778,7 @@ plugin's errors are prefixed `[@solidjs/vite-plugin]`.
|
|
|
778
778
|
## Note on HMR
|
|
779
779
|
|
|
780
780
|
Starting from version `1.1.0`, this plugin handles automatic HMR. The refresh
|
|
781
|
-
transform is compiled natively by `@
|
|
781
|
+
transform is compiled natively by `@solidjs/compiler` and drives the
|
|
782
782
|
dev-only `solid-js/refresh` runtime entry that ships with Solid (the
|
|
783
783
|
standalone [solid-refresh](https://github.com/solidjs/solid-refresh) package
|
|
784
784
|
is no longer used).
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var babel = require('@babel/core');
|
|
6
6
|
var remapping = require('@ampproject/remapping');
|
|
7
|
-
var solid = require('babel-
|
|
7
|
+
var solid = require('@solidjs/babel-plugin');
|
|
8
8
|
var fs = require('fs');
|
|
9
9
|
var mergeAnything = require('merge-anything');
|
|
10
10
|
var module$1 = require('module');
|
|
@@ -501,6 +501,27 @@ function createDevAssetResolver(server, filter = defaultStyleFilter) {
|
|
|
501
501
|
};
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Cross-instance-safe stand-in for vite's `isRunnableDevEnvironment`.
|
|
506
|
+
*
|
|
507
|
+
* Vite's helper is an `instanceof RunnableDevEnvironment` check against the
|
|
508
|
+
* class of whichever `vite` module the CALLER imported. When this plugin is
|
|
509
|
+
* consumed through a workspace/`link:` install, its own `vite` import can
|
|
510
|
+
* resolve to a different physical copy than the one running the dev server —
|
|
511
|
+
* and then the `instanceof` is false for every environment, silently standing
|
|
512
|
+
* the SSR/dev middlewares down. The `runner` accessor is the type's defining
|
|
513
|
+
* member (`RunnableDevEnvironment` is exactly "a DevEnvironment with a
|
|
514
|
+
* runner"), so presence-check it instead of trusting class identity.
|
|
515
|
+
*/
|
|
516
|
+
function isRunnableEnvironment(environment) {
|
|
517
|
+
return !!environment && typeof environment === 'object' && 'runner' in environment;
|
|
518
|
+
}
|
|
519
|
+
function getEnvironmentConsumer(environment, options) {
|
|
520
|
+
const consumer = environment?.config?.consumer;
|
|
521
|
+
if (consumer === 'client' || consumer === 'server') return consumer;
|
|
522
|
+
return options?.ssr ? 'server' : 'client';
|
|
523
|
+
}
|
|
524
|
+
|
|
504
525
|
const VIRTUAL_ID = '\0@solidjs/vite-plugin:boundary-modules';
|
|
505
526
|
|
|
506
527
|
/**
|
|
@@ -535,7 +556,7 @@ function boundaryModules() {
|
|
|
535
556
|
// scan all the same. Real dev/build module graphs resolve without
|
|
536
557
|
// the flag and stay fully guarded.
|
|
537
558
|
const scan = !!options?.scan;
|
|
538
|
-
const server = this.environment
|
|
559
|
+
const server = getEnvironmentConsumer(this.environment, options) === 'server';
|
|
539
560
|
if (id === 'server-only') {
|
|
540
561
|
if (!server && !scan) this.error(`[@solidjs/vite-plugin] Attempt to import 'server-only' in a client module: ${importer}. ` + `Code that uses this module must run only on the server — make sure it is only ` + `imported by server code (e.g. a server entry, a "use server" module, or code ` + `reached exclusively from them).`);
|
|
541
562
|
} else if (id === 'client-only') {
|
|
@@ -552,31 +573,216 @@ function boundaryModules() {
|
|
|
552
573
|
}
|
|
553
574
|
|
|
554
575
|
/**
|
|
555
|
-
*
|
|
576
|
+
* Agent diagnostics surface (`diagnostics: true`, dev serve only).
|
|
556
577
|
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
578
|
+
* Three pieces:
|
|
579
|
+
* - an injected client module (virtual, imported by index.html or the
|
|
580
|
+
* start-mode client entry) that installs the in-page bridge from the
|
|
581
|
+
* app's own `@solidjs/diagnostics` and answers requests over Vite's
|
|
582
|
+
* WebSocket custom events;
|
|
583
|
+
* - a collector that forwards requests to the page and correlates
|
|
584
|
+
* responses by id;
|
|
585
|
+
* - an HTTP endpoint (`/__solid/diagnostics`) fronting that round-trip so
|
|
586
|
+
* any out-of-process consumer (agent, MCP tool, curl) can drive capture
|
|
587
|
+
* sessions without holding a WebSocket.
|
|
588
|
+
*
|
|
589
|
+
* `@solidjs/diagnostics` is deliberately a type-only dependency of this
|
|
590
|
+
* plugin: the runtime bridge always comes from the app's own installed
|
|
591
|
+
* copy, so plugin releases and diagnostics releases stay uncoupled. The
|
|
592
|
+
* wire constants are re-declared here with types imported from the
|
|
593
|
+
* package, so drift fails the plugin's own compile.
|
|
565
594
|
*/
|
|
566
|
-
|
|
567
|
-
|
|
595
|
+
const DIAGNOSTICS_ENDPOINT = '/__solid/diagnostics';
|
|
596
|
+
const REQUEST_EVENT = 'solid:diagnostics:request';
|
|
597
|
+
const RESPONSE_EVENT = 'solid:diagnostics:response';
|
|
598
|
+
const DIAGNOSTICS_PACKAGE = '@solidjs/diagnostics';
|
|
599
|
+
const DIAGNOSTICS_CLIENT_ID = 'virtual:solid-diagnostics/client';
|
|
600
|
+
const METHODS = ['begin', 'end', 'active', 'whyDidRun', 'costs'];
|
|
601
|
+
|
|
602
|
+
/** How long the endpoint waits for a page to answer before failing the call. */
|
|
603
|
+
const RESPONSE_TIMEOUT_MS = 10_000;
|
|
604
|
+
function diagnosticsClientModuleCode() {
|
|
605
|
+
// Runtime imports resolve to the APP's diagnostics package (see the
|
|
606
|
+
// resolveId assist below) — the page speaks its own package's protocol.
|
|
607
|
+
return [`import { installDiagnosticsBridge } from '${DIAGNOSTICS_PACKAGE}/browser';`, `import {`, ` DIAGNOSTICS_REQUEST_EVENT,`, ` DIAGNOSTICS_RESPONSE_EVENT,`, `} from '${DIAGNOSTICS_PACKAGE}/protocol';`, ``, `const bridge = installDiagnosticsBridge();`, ``, `async function dispatch(request) {`, ` switch (request.method) {`, ` case 'begin': bridge.begin(request.params); return true;`, ` case 'end': return bridge.end();`, ` case 'active': return bridge.active();`, ` case 'whyDidRun': return bridge.whyDidRun(request.params.name);`, ` case 'costs': return bridge.costs();`, ` default: throw new Error('Unknown diagnostics method: ' + request.method);`, ` }`, `}`, ``, `if (import.meta.hot) {`, ` import.meta.hot.on(DIAGNOSTICS_REQUEST_EVENT, async (request) => {`, ` let response;`, ` try {`, ` response = { id: request.id, result: await dispatch(request) };`, ` } catch (error) {`, ` response = {`, ` id: request.id,`, ` error: error instanceof Error ? error.message : String(error),`, ` };`, ` }`, ` import.meta.hot.send(DIAGNOSTICS_RESPONSE_EVENT, response);`, ` });`, `}`].join('\n');
|
|
568
608
|
}
|
|
569
|
-
function
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
609
|
+
function sendJson(res, status, body) {
|
|
610
|
+
res.statusCode = status;
|
|
611
|
+
res.setHeader('Content-Type', 'application/json');
|
|
612
|
+
res.end(JSON.stringify(body));
|
|
613
|
+
}
|
|
614
|
+
function readJsonBody(req) {
|
|
615
|
+
return new Promise((resolve, reject) => {
|
|
616
|
+
const chunks = [];
|
|
617
|
+
req.on('data', chunk => chunks.push(chunk));
|
|
618
|
+
req.on('end', () => {
|
|
619
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
620
|
+
if (!text) return resolve({});
|
|
621
|
+
try {
|
|
622
|
+
resolve(JSON.parse(text));
|
|
623
|
+
} catch {
|
|
624
|
+
reject(new Error('Request body is not valid JSON'));
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
req.on('error', reject);
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
function solidDiagnostics() {
|
|
631
|
+
let root = process.cwd();
|
|
632
|
+
let base = '/';
|
|
633
|
+
return {
|
|
634
|
+
name: 'solid:diagnostics',
|
|
635
|
+
// Dev-serve only: the channels this fronts exist in dev builds only.
|
|
636
|
+
apply(_config, env) {
|
|
637
|
+
return env.command === 'serve' && !env.isPreview;
|
|
638
|
+
},
|
|
639
|
+
configResolved(config) {
|
|
640
|
+
root = config.root;
|
|
641
|
+
base = config.base;
|
|
642
|
+
},
|
|
643
|
+
async resolveId(source, importer) {
|
|
644
|
+
if (source === DIAGNOSTICS_CLIENT_ID) {
|
|
645
|
+
return {
|
|
646
|
+
id: DIAGNOSTICS_CLIENT_ID,
|
|
647
|
+
moduleSideEffects: true
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
// The virtual module has no directory to resolve bare imports from;
|
|
651
|
+
// resolve the app's diagnostics package from the project root.
|
|
652
|
+
if (importer === DIAGNOSTICS_CLIENT_ID && source.startsWith(DIAGNOSTICS_PACKAGE)) {
|
|
653
|
+
const resolved = await this.resolve(source, path.resolve(root, 'index.html'), {
|
|
654
|
+
skipSelf: true
|
|
655
|
+
});
|
|
656
|
+
if (!resolved || resolved.id.startsWith('__vite-optional-peer-dep:')) {
|
|
657
|
+
this.error(`[@solidjs/vite-plugin] the diagnostics option requires ${DIAGNOSTICS_PACKAGE} ` + 'installed in the app (it provides the in-page bridge). Install it as a ' + 'development dependency or remove `diagnostics: true`.');
|
|
658
|
+
}
|
|
659
|
+
return resolved;
|
|
660
|
+
}
|
|
661
|
+
return null;
|
|
662
|
+
},
|
|
663
|
+
load(id) {
|
|
664
|
+
if (id === DIAGNOSTICS_CLIENT_ID) return diagnosticsClientModuleCode();
|
|
665
|
+
return null;
|
|
666
|
+
},
|
|
667
|
+
// Plain (index.html) apps get the client module injected here;
|
|
668
|
+
// start-mode apps import it from the generated client entry instead.
|
|
669
|
+
transformIndexHtml() {
|
|
670
|
+
return [{
|
|
671
|
+
tag: 'script',
|
|
672
|
+
attrs: {
|
|
673
|
+
type: 'module',
|
|
674
|
+
src: joinBase(base, '/@id/' + DIAGNOSTICS_CLIENT_ID)
|
|
675
|
+
},
|
|
676
|
+
injectTo: 'head'
|
|
677
|
+
}];
|
|
678
|
+
},
|
|
679
|
+
configureServer(server) {
|
|
680
|
+
// Announce the surface in the startup block. This is a discovery
|
|
681
|
+
// channel: agents watching dev-server output learn the endpoint and
|
|
682
|
+
// the skill documents without any project-level pointer (AGENTS.md).
|
|
683
|
+
const originalPrintUrls = server.printUrls.bind(server);
|
|
684
|
+
server.printUrls = () => {
|
|
685
|
+
originalPrintUrls();
|
|
686
|
+
const local = server.resolvedUrls?.local[0];
|
|
687
|
+
const endpoint = local ? new URL(DIAGNOSTICS_ENDPOINT, local).href : DIAGNOSTICS_ENDPOINT;
|
|
688
|
+
server.config.logger.info(` ➜ Solid diagnostics: ${endpoint} ` + `(GET status; POST {"method":"begin"|"end"|"whyDidRun"|"costs"})\n` + ` ➜ Agent skills: node_modules/${DIAGNOSTICS_PACKAGE}/skills/agent-loops/SKILL.md, ` + `node_modules/solid-js/skills/reactivity-diagnostics/SKILL.md`);
|
|
689
|
+
};
|
|
690
|
+
const pending = new Map();
|
|
691
|
+
let nextId = 1;
|
|
692
|
+
server.ws.on(RESPONSE_EVENT, data => {
|
|
693
|
+
const entry = pending.get(data?.id);
|
|
694
|
+
if (!entry) return;
|
|
695
|
+
pending.delete(data.id);
|
|
696
|
+
clearTimeout(entry.timer);
|
|
697
|
+
entry.resolve(data);
|
|
698
|
+
});
|
|
699
|
+
server.middlewares.use(DIAGNOSTICS_ENDPOINT, async (req, res) => {
|
|
700
|
+
// The middleware mounts on the exact path; anything deeper is 404.
|
|
701
|
+
if (req.url && req.url !== '/' && req.url !== '') {
|
|
702
|
+
sendJson(res, 404, {
|
|
703
|
+
error: `Unknown diagnostics path ${req.url}`
|
|
704
|
+
});
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
if (req.method === 'GET') {
|
|
708
|
+
sendJson(res, 200, {
|
|
709
|
+
ok: true,
|
|
710
|
+
methods: METHODS,
|
|
711
|
+
clients: server.ws.clients.size
|
|
712
|
+
});
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (req.method !== 'POST') {
|
|
716
|
+
sendJson(res, 405, {
|
|
717
|
+
error: 'Use GET for status or POST { method, params }'
|
|
718
|
+
});
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
let body;
|
|
722
|
+
try {
|
|
723
|
+
body = await readJsonBody(req);
|
|
724
|
+
} catch (error) {
|
|
725
|
+
sendJson(res, 400, {
|
|
726
|
+
error: error.message
|
|
727
|
+
});
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (!body.method || !METHODS.includes(body.method)) {
|
|
731
|
+
sendJson(res, 400, {
|
|
732
|
+
error: `Unknown method ${JSON.stringify(body.method)}; expected one of: ${METHODS.join(', ')}`
|
|
733
|
+
});
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
if (server.ws.clients.size === 0) {
|
|
737
|
+
sendJson(res, 503, {
|
|
738
|
+
error: 'No connected page. Open the app in a browser (dev server) so the ' + 'diagnostics bridge can answer.'
|
|
739
|
+
});
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const id = nextId++;
|
|
743
|
+
// Broadcast; with several open tabs the first responder wins. Good
|
|
744
|
+
// enough for the agent loop (one page under test); revisit with
|
|
745
|
+
// client targeting if multi-page capture ever matters.
|
|
746
|
+
const response = await new Promise(resolve => {
|
|
747
|
+
const timer = setTimeout(() => {
|
|
748
|
+
pending.delete(id);
|
|
749
|
+
resolve({
|
|
750
|
+
timeout: `No page answered within ${RESPONSE_TIMEOUT_MS}ms. The connected page ` + 'may predate `diagnostics: true` — reload it.'
|
|
751
|
+
});
|
|
752
|
+
}, RESPONSE_TIMEOUT_MS);
|
|
753
|
+
pending.set(id, {
|
|
754
|
+
resolve,
|
|
755
|
+
timer
|
|
756
|
+
});
|
|
757
|
+
server.ws.send(REQUEST_EVENT, {
|
|
758
|
+
id,
|
|
759
|
+
method: body.method,
|
|
760
|
+
params: body.params
|
|
761
|
+
});
|
|
762
|
+
});
|
|
763
|
+
if ('timeout' in response) {
|
|
764
|
+
sendJson(res, 504, {
|
|
765
|
+
error: response.timeout
|
|
766
|
+
});
|
|
767
|
+
} else if (response.error !== undefined) {
|
|
768
|
+
sendJson(res, 400, {
|
|
769
|
+
error: response.error
|
|
770
|
+
});
|
|
771
|
+
} else {
|
|
772
|
+
sendJson(res, 200, {
|
|
773
|
+
result: response.result
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
};
|
|
573
779
|
}
|
|
574
780
|
|
|
575
781
|
// The `"use server"` directive compiler. This wraps the native
|
|
576
|
-
// `transformDirectives` pass from @
|
|
782
|
+
// `transformDirectives` pass from @solidjs/compiler (Rust/Oxc); the
|
|
577
783
|
// original Babel implementation (hoisted from solid-start) lived in this
|
|
578
784
|
// directory through vite-plugin-solid@c052963e and remains the frozen
|
|
579
|
-
// reference for the native pass's fixture suite
|
|
785
|
+
// reference for the native pass's fixture suite.
|
|
580
786
|
|
|
581
787
|
let compilerPromise;
|
|
582
788
|
|
|
@@ -585,11 +791,11 @@ let compilerPromise;
|
|
|
585
791
|
// compiler's opt-in loader in index.ts).
|
|
586
792
|
async function loadCompiler() {
|
|
587
793
|
try {
|
|
588
|
-
return await (compilerPromise ??= import('@
|
|
794
|
+
return await (compilerPromise ??= import('@solidjs/compiler'));
|
|
589
795
|
} catch (error) {
|
|
590
796
|
compilerPromise = undefined;
|
|
591
797
|
const reason = error instanceof Error ? `\n\nCause: ${error.message}` : '';
|
|
592
|
-
throw new Error('@solidjs/vite-plugin: failed to load @
|
|
798
|
+
throw new Error('@solidjs/vite-plugin: failed to load @solidjs/compiler (the "use server" ' + 'transform). Your platform should get a prebuilt native binary or the ' + '@solidjs/compiler-wasm32-wasi fallback — check that optional ' + 'dependencies were installed.' + reason);
|
|
593
799
|
}
|
|
594
800
|
}
|
|
595
801
|
|
|
@@ -1037,24 +1243,47 @@ function serverFunctions(options = {}, internal = {}) {
|
|
|
1037
1243
|
if (internal.externalDevServer || !isRunnableEnvironment(ssrEnvironment)) {
|
|
1038
1244
|
return;
|
|
1039
1245
|
}
|
|
1246
|
+
// A call's address is `<endpoint>/<id>` (solidjs/solid#3076) — the
|
|
1247
|
+
// mount plus exactly one path segment. Bare-mount requests still
|
|
1248
|
+
// reach the runtime handler (it answers 404), so misdirected posts
|
|
1249
|
+
// fail through the endpoint rather than falling through to SSR.
|
|
1250
|
+
const underMount = (pathname, mount) => pathname === mount || pathname.startsWith(mount + '/');
|
|
1040
1251
|
server.middlewares.use((req, res, next) => {
|
|
1041
1252
|
const url = new URL(req.url || '/', 'http://localhost');
|
|
1042
1253
|
// Match with and without `base` — middleware-mode hosts may mount
|
|
1043
1254
|
// vite.middlewares below the base themselves.
|
|
1044
|
-
if (url.pathname
|
|
1255
|
+
if (!underMount(url.pathname, resolvedEndpoint) && !underMount(url.pathname, endpoint)) {
|
|
1045
1256
|
return next();
|
|
1046
1257
|
}
|
|
1258
|
+
const basePrefixed = underMount(url.pathname, resolvedEndpoint);
|
|
1047
1259
|
// When the stripped form matched, restore the base for dispatch:
|
|
1048
1260
|
// the generated handler compares the request pathname against the
|
|
1049
1261
|
// base-prefixed endpoint, and production handlers only ever see
|
|
1050
1262
|
// base-prefixed URLs.
|
|
1051
|
-
const dispatchUrl =
|
|
1263
|
+
const dispatchUrl = basePrefixed ? undefined : joinBase(base, req.url || '/');
|
|
1052
1264
|
(async () => {
|
|
1053
1265
|
// Make sure the referenced module has been evaluated in the SSR
|
|
1054
1266
|
// environment so its registration exists — functions only client
|
|
1055
1267
|
// code references are never loaded by the SSR render itself.
|
|
1056
|
-
|
|
1057
|
-
const
|
|
1268
|
+
// The id lives in the path segment after the mount.
|
|
1269
|
+
const mount = basePrefixed ? resolvedEndpoint : endpoint;
|
|
1270
|
+
const segment = url.pathname.slice(mount.length + 1);
|
|
1271
|
+
let functionId = null;
|
|
1272
|
+
if (segment && !segment.includes('/')) {
|
|
1273
|
+
try {
|
|
1274
|
+
functionId = decodeURIComponent(segment);
|
|
1275
|
+
} catch {
|
|
1276
|
+
// not an address; the runtime handler answers the 404
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
if (!functionId) {
|
|
1280
|
+
// TRANSITIONAL (remove before 3.0 stable): the retired header
|
|
1281
|
+
// and `?id=` addressing, kept only for the RC window where this
|
|
1282
|
+
// plugin meets a @solidjs/web older than the path-addressing
|
|
1283
|
+
// change (solidjs/solid#3076).
|
|
1284
|
+
const headerId = req.headers['x-server-function-id'];
|
|
1285
|
+
functionId = (typeof headerId === 'string' ? headerId.split('#')[0] : undefined) || url.searchParams.get('id');
|
|
1286
|
+
}
|
|
1058
1287
|
if (functionId) {
|
|
1059
1288
|
const entry = moduleForFunctionId(functionId);
|
|
1060
1289
|
if (entry) await ssrEnvironment.runner.import(moduleDevUrl(entry));
|
|
@@ -1401,6 +1630,7 @@ function startServe(options, internal = {}) {
|
|
|
1401
1630
|
const serverComponents = !!internal.serverComponents;
|
|
1402
1631
|
const errorBoundary = options.errorBoundary !== false;
|
|
1403
1632
|
const styleFilter = internal.styleFilter;
|
|
1633
|
+
const diagnostics = !!internal.diagnostics;
|
|
1404
1634
|
let devtoolsEnabled = false;
|
|
1405
1635
|
let devtoolsResolutions = {};
|
|
1406
1636
|
let devtoolsIds = {};
|
|
@@ -1565,15 +1795,18 @@ function startServe(options, internal = {}) {
|
|
|
1565
1795
|
const {
|
|
1566
1796
|
app
|
|
1567
1797
|
} = requireEntries();
|
|
1798
|
+
// Dev-only: the diagnostics bridge fronts dev-mode channels, so builds
|
|
1799
|
+
// never see this import (mirrors the plugin's own serve-only `apply`).
|
|
1800
|
+
const diagnosticsImport = diagnostics && !isBuild ? [`import ${JSON.stringify(DIAGNOSTICS_CLIENT_ID)};`] : [];
|
|
1568
1801
|
if (clientMode) {
|
|
1569
1802
|
// render(), not hydrate(): the shell's body is empty, the app mounts
|
|
1570
1803
|
// fresh. Client code compiles non-hydratable in client mode, so the
|
|
1571
1804
|
// app cannot claim server DOM anyway. The entry script is injected
|
|
1572
1805
|
// without `async` (plain module = deferred), so document.body is
|
|
1573
1806
|
// complete when this runs.
|
|
1574
|
-
return [`import { render } from '@solidjs/web';`, ...errorBoundaryImport(), ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), `import App from ${JSON.stringify(app)};`, ``, `render(() => ${isBuild && errorBoundary ? '<DefaultErrorBoundary><App /></DefaultErrorBoundary>' : toolbar ? '<DevToolbar><App /></DevToolbar>' : '<App />'}, document.body);`].join('\n');
|
|
1807
|
+
return [...diagnosticsImport, `import { render } from '@solidjs/web';`, ...errorBoundaryImport(), ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), `import App from ${JSON.stringify(app)};`, ``, `render(() => ${isBuild && errorBoundary ? '<DefaultErrorBoundary><App /></DefaultErrorBoundary>' : toolbar ? '<DevToolbar><App /></DevToolbar>' : '<App />'}, document.body);`].join('\n');
|
|
1575
1808
|
}
|
|
1576
|
-
return [`import { hydrate } from '@solidjs/web';`, ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), ...(serverComponents ? [`import { installServerComponents } from '@solidjs/web/frames';`] : []), ...errorBoundaryImport(), `import Document from ${JSON.stringify(documentSpec())};`, `import App from ${JSON.stringify(app)};`, ``, ...(serverComponents ? [
|
|
1809
|
+
return [...diagnosticsImport, `import { hydrate } from '@solidjs/web';`, ...(toolbar ? [`import { DevToolbar } from ${JSON.stringify(DEVTOOLS_PACKAGE)};`] : []), ...(serverComponents ? [`import { installServerComponents } from '@solidjs/web/frames';`] : []), ...errorBoundaryImport(), `import Document from ${JSON.stringify(documentSpec())};`, `import App from ${JSON.stringify(app)};`, ``, ...(serverComponents ? [
|
|
1577
1810
|
// Installs the t=0 document-adoption registry and the transport
|
|
1578
1811
|
// policy (component responses morph their boundary instead of
|
|
1579
1812
|
// decoding as data). Must run before hydrate().
|
|
@@ -1688,7 +1921,11 @@ function startServe(options, internal = {}) {
|
|
|
1688
1921
|
// through untouched, so the edge applies it unconditionally.
|
|
1689
1922
|
lines.push(``, `async function dispatchRequest(request, event, options) {`);
|
|
1690
1923
|
if (composeServerFunctions) {
|
|
1691
|
-
lines.push(
|
|
1924
|
+
lines.push(
|
|
1925
|
+
// A call's address is `<endpoint>/<id>` (solidjs/solid#3076); the
|
|
1926
|
+
// bare mount still routes so a misaddressed request 404s through the
|
|
1927
|
+
// runtime handler instead of rendering a page at it.
|
|
1928
|
+
` const requestPath = new URL(request.url).pathname;`, ` if (requestPath === endpoint || requestPath.startsWith(endpoint + '/')) {`,
|
|
1692
1929
|
// The call shares the middleware chain's event (locals decoration,
|
|
1693
1930
|
// the response stub); an explicit host-provided createEvent wins.
|
|
1694
1931
|
// No fold here: the runtime's server-function handler runs the
|
|
@@ -1985,7 +2222,7 @@ function startServe(options, internal = {}) {
|
|
|
1985
2222
|
return null;
|
|
1986
2223
|
},
|
|
1987
2224
|
async transform(code, id, opts) {
|
|
1988
|
-
if (isBuild || !devtoolsEnabled) return null;
|
|
2225
|
+
if (isBuild || !devtoolsEnabled && !diagnostics) return null;
|
|
1989
2226
|
const current = requireEntries();
|
|
1990
2227
|
if (current.generated || getEnvironmentConsumer(this.environment, opts) !== 'client') {
|
|
1991
2228
|
return null;
|
|
@@ -1995,12 +2232,17 @@ function startServe(options, internal = {}) {
|
|
|
1995
2232
|
if (vite.normalizePath(id.split('?')[0]) !== vite.normalizePath(path.resolve(root, current.entryClient))) {
|
|
1996
2233
|
return null;
|
|
1997
2234
|
}
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2235
|
+
const injected = [];
|
|
2236
|
+
if (diagnostics) injected.push(`import ${JSON.stringify(DIAGNOSTICS_CLIENT_ID)};`);
|
|
2237
|
+
if (devtoolsEnabled) {
|
|
2238
|
+
const toolbar = await resolveDevtools((source, importer) => this.resolve(source, importer, {
|
|
2239
|
+
skipSelf: true
|
|
2240
|
+
}), id, 'client');
|
|
2241
|
+
if (toolbar) injected.push(`import ${JSON.stringify(DEVTOOLS_MOUNT_ID)};`);
|
|
2242
|
+
}
|
|
2243
|
+
if (injected.length === 0) return null;
|
|
2002
2244
|
return {
|
|
2003
|
-
code:
|
|
2245
|
+
code: `${injected.join('\n')}\n${code}`,
|
|
2004
2246
|
map: null
|
|
2005
2247
|
};
|
|
2006
2248
|
},
|
|
@@ -2734,7 +2976,7 @@ const require$1 = module$1.createRequire((typeof document === 'undefined' ? requ
|
|
|
2734
2976
|
* second string-literal argument of the form
|
|
2735
2977
|
* `"__SOLID_LAZY_MODULE__:" + spec`, which `resolveLazyModuleUrls` swaps for
|
|
2736
2978
|
* the project-relative resolved module path. The prefix and shape are FROZEN
|
|
2737
|
-
* — the emitting side lives in @
|
|
2979
|
+
* — the emitting side lives in @solidjs/compiler and must match.
|
|
2738
2980
|
*/
|
|
2739
2981
|
const LAZY_PLACEHOLDER_PREFIX = '__SOLID_LAZY_MODULE__:';
|
|
2740
2982
|
|
|
@@ -2852,18 +3094,17 @@ async function fetchAssets(key) {
|
|
|
2852
3094
|
}
|
|
2853
3095
|
export default (registry && registry[${JSON.stringify(root)}]) ||
|
|
2854
3096
|
(bridgeUrl ? createBridgeResolver() : { resolve: jsOnly, resolveSync: jsOnly });`;
|
|
2855
|
-
const SOLID_BUILT_INS = ['For', 'Show', 'Switch', 'Match', 'Loading', 'Reveal', 'Portal', 'Repeat', 'Dynamic', 'Errored'];
|
|
2856
3097
|
|
|
2857
3098
|
/** Possible options for the extensions property */
|
|
2858
3099
|
|
|
2859
3100
|
let nativeCompilerPromise;
|
|
2860
3101
|
async function loadNativeCompiler() {
|
|
2861
3102
|
try {
|
|
2862
|
-
return await (nativeCompilerPromise ??= import('@
|
|
3103
|
+
return await (nativeCompilerPromise ??= import('@solidjs/compiler'));
|
|
2863
3104
|
} catch (error) {
|
|
2864
3105
|
nativeCompilerPromise = undefined;
|
|
2865
3106
|
const reason = error instanceof Error ? `\n\nCause: ${error.message}` : '';
|
|
2866
|
-
throw new Error('@solidjs/vite-plugin: failed to load @
|
|
3107
|
+
throw new Error('@solidjs/vite-plugin: failed to load @solidjs/compiler, which is required ' + 'in every mode (it drives the lazy, refresh, and server-function transforms; ' + 'compiler: "babel" only switches the JSX transform). Your platform should get ' + 'a prebuilt native binary or the @solidjs/compiler-wasm32-wasi fallback ' + '— check that optional dependencies were installed.' + reason);
|
|
2867
3108
|
}
|
|
2868
3109
|
}
|
|
2869
3110
|
|
|
@@ -2940,11 +3181,12 @@ function getSolidOptions(options, isSsr, dev, isTestMode = false) {
|
|
|
2940
3181
|
// by construction (the dom generate ignores the flag), and apps without
|
|
2941
3182
|
// the flag compile byte-for-byte as before.
|
|
2942
3183
|
const serverComponents = typeof options.serverFunctions === 'object' && !!options.serverFunctions.components;
|
|
3184
|
+
|
|
3185
|
+
// Solid-specific defaults (moduleName "@solidjs/web", the control-flow
|
|
3186
|
+
// builtIns, contextToCustomElements, wrapConditionals) are baked into both
|
|
3187
|
+
// backends — @solidjs/compiler and @solidjs/babel-plugin — so only the
|
|
3188
|
+
// posture this plugin actually decides is passed.
|
|
2943
3189
|
return {
|
|
2944
|
-
moduleName: '@solidjs/web',
|
|
2945
|
-
builtIns: SOLID_BUILT_INS,
|
|
2946
|
-
contextToCustomElements: true,
|
|
2947
|
-
wrapConditionals: true,
|
|
2948
3190
|
...solidOptions,
|
|
2949
3191
|
...(serverComponents && solidOptions.generate === 'ssr' ? {
|
|
2950
3192
|
serverComponents: true
|
|
@@ -3538,10 +3780,13 @@ function solidPlugin(options = {}) {
|
|
|
3538
3780
|
}
|
|
3539
3781
|
|
|
3540
3782
|
// Babel JSX backend: one babel.transformAsync hosting the user's
|
|
3541
|
-
// options plus babel-
|
|
3783
|
+
// options plus @solidjs/babel-plugin. Appended to `plugins` (was the
|
|
3784
|
+
// sole preset pre-rename): user plugins still run before it, user
|
|
3785
|
+
// presets still run after — babel runs plugins before presets and
|
|
3786
|
+
// presets in reverse order, so the pass order is unchanged.
|
|
3542
3787
|
const babelOptions = mergeAnything.mergeAndConcat(babelUserOptions, {
|
|
3543
3788
|
...babelBaseOptions,
|
|
3544
|
-
|
|
3789
|
+
plugins: [[solid, solidOptions]]
|
|
3545
3790
|
});
|
|
3546
3791
|
const result = await babel__namespace.transformAsync(code, babelOptions);
|
|
3547
3792
|
if (!result) {
|
|
@@ -3583,10 +3828,17 @@ function solidPlugin(options = {}) {
|
|
|
3583
3828
|
serverFunctions: !!options.serverFunctions,
|
|
3584
3829
|
serverComponents,
|
|
3585
3830
|
ssr: !!options.ssr,
|
|
3586
|
-
styleFilter: filterDevStyles
|
|
3831
|
+
styleFilter: filterDevStyles,
|
|
3832
|
+
diagnostics: !!options.diagnostics
|
|
3587
3833
|
}));
|
|
3588
3834
|
}
|
|
3589
3835
|
|
|
3836
|
+
// Agent diagnostics endpoint + injected bridge (dev serve only — the
|
|
3837
|
+
// plugin no-ops itself for builds and preview via `apply`).
|
|
3838
|
+
if (options.diagnostics) {
|
|
3839
|
+
plugins.push(solidDiagnostics());
|
|
3840
|
+
}
|
|
3841
|
+
|
|
3590
3842
|
// Builder-mode (environments API) client-before-server build ordering.
|
|
3591
3843
|
// Server builds read the client manifest — `virtual:solid-manifest` bakes
|
|
3592
3844
|
// dist/client/.vite/manifest.json in, and the persisted server-function
|