@void/svelte 1.3.0 → 1.5.0
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/plugin.d.mts +0 -4
- package/dist/plugin.mjs +13 -84
- package/package.json +6 -6
- package/src/runtime/App.svelte +8 -7
- package/src/runtime/use-island-form.svelte.ts +8 -43
package/dist/plugin.d.mts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
2
2
|
import { Plugin } from "vite";
|
|
3
|
-
//#region src/plugin-pages.d.ts
|
|
4
3
|
type PrefetchConfig = {
|
|
5
4
|
hoverDelay?: number;
|
|
6
5
|
cacheFor?: number | string | [string, string];
|
|
7
6
|
};
|
|
8
|
-
//#endregion
|
|
9
|
-
//#region src/plugin.d.ts
|
|
10
7
|
export type VoidSvelteOptions = Readonly<{
|
|
11
8
|
svelte?: Parameters<typeof svelte>[0];
|
|
12
9
|
viewTransitions?: boolean;
|
|
13
10
|
prefetch?: PrefetchConfig;
|
|
14
11
|
}>;
|
|
15
12
|
export declare function voidSvelte(options?: VoidSvelteOptions): Array<Plugin>;
|
|
16
|
-
//#endregion
|
|
17
13
|
export {};
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
2
|
-
import { generateComponentManifest, resolveEffectiveLayoutChain, resolvePagesDir,
|
|
2
|
+
import { createPagesPlugin, generateComponentManifest, resolveEffectiveLayoutChain, resolvePagesDir, scanPages } from "void/pages";
|
|
3
3
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import nodePath from "node:path";
|
|
5
5
|
import { preprocess } from "svelte/compiler";
|
|
6
6
|
import { normalizePath } from "vite";
|
|
7
7
|
import { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, editIslandSource, findIslandImports, findStaticCssImports, hasIslandPages, islandStylesPlugin, recordIslandStyles, recordedIslandStyles, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan } from "void/pages-islands-plugin";
|
|
8
|
-
|
|
8
|
+
// ../../node_modules/.pnpm/pathslash@0.1.0/node_modules/pathslash/dist/index.mjs
|
|
9
9
|
const BACKSLASH_RE = /\\/g;
|
|
10
10
|
const isWindows = process.platform === "win32";
|
|
11
11
|
/**
|
|
@@ -43,8 +43,7 @@ const posix = { ...nodePath.posix };
|
|
|
43
43
|
posix.posix = win32.posix = posix;
|
|
44
44
|
posix.win32 = win32.win32 = win32;
|
|
45
45
|
const { basename, delimiter, dirname, extname, format, isAbsolute, join, matchesGlob, normalize, parse, relative, resolve, sep, toNamespacedPath } = isWindows ? win32 : posix;
|
|
46
|
-
|
|
47
|
-
//#region src/plugin-islands.ts
|
|
46
|
+
// src/plugin-islands.ts
|
|
48
47
|
const COMPONENT_EXTENSIONS = [
|
|
49
48
|
".svelte",
|
|
50
49
|
".ts",
|
|
@@ -327,9 +326,7 @@ initIslands(islands, hydrateIsland);
|
|
|
327
326
|
`);
|
|
328
327
|
return lines.join("\n");
|
|
329
328
|
}
|
|
330
|
-
|
|
331
|
-
//#region src/plugin-pages.ts
|
|
332
|
-
const RENDERER_ID = "virtual:void-pages-renderer";
|
|
329
|
+
// src/plugin-pages.ts
|
|
333
330
|
const CLIENT_ENTRY_ID = "virtual:void-pages-client";
|
|
334
331
|
const SVELTE_OPTIMIZE_DEPS = {
|
|
335
332
|
exclude: ["@void/svelte"],
|
|
@@ -356,82 +353,16 @@ function hasNonIslandPages(dir) {
|
|
|
356
353
|
return false;
|
|
357
354
|
}
|
|
358
355
|
function pagesPlugin(pagesDir, options) {
|
|
359
|
-
|
|
360
|
-
let isDev = false;
|
|
361
|
-
let viteConfig;
|
|
362
|
-
const root = options?.root ?? dirname(pagesDir);
|
|
363
|
-
const normalizedPagesDir = normalizePath(pagesDir);
|
|
364
|
-
let pendingRescan = null;
|
|
365
|
-
const rescanPages = async () => {
|
|
366
|
-
pageScan = existsSync(pagesDir) ? await scanPages(root, {
|
|
367
|
-
pagesDir,
|
|
368
|
-
environment: isDev ? "dev" : "prod"
|
|
369
|
-
}) : null;
|
|
370
|
-
};
|
|
371
|
-
const runRescan = () => {
|
|
372
|
-
pendingRescan ??= rescanPages().finally(() => {
|
|
373
|
-
pendingRescan = null;
|
|
374
|
-
});
|
|
375
|
-
return pendingRescan;
|
|
376
|
-
};
|
|
377
|
-
const invalidatePageModules = (server) => {
|
|
378
|
-
for (const env of Object.values(server.environments)) for (const id of ["\0" + RENDERER_ID, "\0" + CLIENT_ENTRY_ID]) {
|
|
379
|
-
const mod = env.moduleGraph.getModuleById(id);
|
|
380
|
-
if (mod) env.moduleGraph.invalidateModule(mod);
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
return {
|
|
356
|
+
return createPagesPlugin(pagesDir, {
|
|
384
357
|
name: "void-svelte:pages",
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
resolveId: {
|
|
389
|
-
filter: { id: /^virtual:void-pages-(renderer|client)$/ },
|
|
390
|
-
handler(id) {
|
|
391
|
-
return "\0" + id;
|
|
392
|
-
}
|
|
393
|
-
},
|
|
394
|
-
load: {
|
|
395
|
-
filter: { id: /^\0virtual:void-pages-(renderer|client)$/ },
|
|
396
|
-
async handler(id) {
|
|
397
|
-
if (isDev && pendingRescan) await pendingRescan;
|
|
398
|
-
if (!pageScan && existsSync(pagesDir)) await runRescan();
|
|
399
|
-
if (id === "\0" + RENDERER_ID) {
|
|
400
|
-
if (!pageScan) return "export function renderPage() { throw new Error('No pages found'); }";
|
|
401
|
-
return generateRendererModule(pageScan, pagesDir);
|
|
402
|
-
}
|
|
403
|
-
if (id === "\0" + CLIENT_ENTRY_ID) {
|
|
404
|
-
if (!pageScan) return "";
|
|
405
|
-
return generateClientEntry(pageScan, pagesDir, options?.viewTransitions, options?.prefetch, resolveStaticPageDataBuildOptions(root, { publicDir: viteConfig?.publicDir }));
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
},
|
|
409
|
-
configureServer(server) {
|
|
410
|
-
const handlePagesChange = async (path, event) => {
|
|
411
|
-
const normalizedPath = normalizePath(path);
|
|
412
|
-
if (normalizedPath !== normalizedPagesDir && !normalizedPath.startsWith(normalizedPagesDir + "/")) return;
|
|
413
|
-
if (event === "change" && !normalizedPath.endsWith(".md")) return;
|
|
414
|
-
try {
|
|
415
|
-
await runRescan();
|
|
416
|
-
} catch (error) {
|
|
417
|
-
server.config.logger.error(error instanceof Error ? error.message : String(error), {
|
|
418
|
-
error: error instanceof Error ? error : void 0,
|
|
419
|
-
timestamp: true
|
|
420
|
-
});
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
invalidatePageModules(server);
|
|
424
|
-
};
|
|
425
|
-
server.watcher.on("add", (path) => handlePagesChange(path, "add"));
|
|
426
|
-
server.watcher.on("change", (path) => handlePagesChange(path, "change"));
|
|
427
|
-
server.watcher.on("unlink", (path) => handlePagesChange(path, "unlink"));
|
|
358
|
+
root: options?.root,
|
|
359
|
+
generateRenderer(scan) {
|
|
360
|
+
return generateRendererModule(scan, pagesDir);
|
|
428
361
|
},
|
|
429
|
-
|
|
430
|
-
|
|
362
|
+
generateClient(scan, staticPageData) {
|
|
363
|
+
return generateClientEntry(scan, pagesDir, options?.viewTransitions, options?.prefetch, staticPageData);
|
|
431
364
|
},
|
|
432
|
-
config(
|
|
433
|
-
isDev = env.command === "serve";
|
|
434
|
-
if (!existsSync(pagesDir)) return;
|
|
365
|
+
config({ isDev }) {
|
|
435
366
|
if (isDev) return {
|
|
436
367
|
optimizeDeps: SVELTE_OPTIMIZE_DEPS,
|
|
437
368
|
environments: { void_worker: { optimizeDeps: { exclude: ["@void/svelte"] } } }
|
|
@@ -442,7 +373,7 @@ function pagesPlugin(pagesDir, options) {
|
|
|
442
373
|
rollupOptions: { input: { "pages-client": CLIENT_ENTRY_ID } }
|
|
443
374
|
} };
|
|
444
375
|
}
|
|
445
|
-
};
|
|
376
|
+
});
|
|
446
377
|
}
|
|
447
378
|
function generateRendererModule(scan, pagesDir) {
|
|
448
379
|
return `
|
|
@@ -595,8 +526,7 @@ commitInitialRender();
|
|
|
595
526
|
appEl.setAttribute("data-hydrated", "true");
|
|
596
527
|
`;
|
|
597
528
|
}
|
|
598
|
-
|
|
599
|
-
//#region src/plugin.ts
|
|
529
|
+
// src/plugin.ts
|
|
600
530
|
function voidSvelte(options) {
|
|
601
531
|
const root = process.cwd();
|
|
602
532
|
const pagesDir = resolvePagesDir(root);
|
|
@@ -610,5 +540,4 @@ function voidSvelte(options) {
|
|
|
610
540
|
...islandsPlugin(pagesDir, { root })
|
|
611
541
|
];
|
|
612
542
|
}
|
|
613
|
-
//#endregion
|
|
614
543
|
export { voidSvelte };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@void/svelte",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Svelte pages, server rendering, forms, and navigation for Void.",
|
|
5
5
|
"homepage": "https://void.cloud",
|
|
6
6
|
"bugs": {
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
"@sveltejs/vite-plugin-svelte": "^7.3.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^26.6.
|
|
41
|
+
"@types/node": "^26.6.6",
|
|
42
42
|
"pathslash": "^0.1.0",
|
|
43
43
|
"svelte": "^5.57.2",
|
|
44
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
45
|
-
"vite-plus": "1.
|
|
46
|
-
"void": "1.
|
|
44
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
45
|
+
"vite-plus": "1.4.0",
|
|
46
|
+
"void": "1.5.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"svelte": "^5.0.0",
|
|
50
50
|
"vite": "^8.0.0",
|
|
51
|
-
"void": "1.
|
|
51
|
+
"void": "1.5.0"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "vp pack",
|
package/src/runtime/App.svelte
CHANGED
|
@@ -30,12 +30,13 @@
|
|
|
30
30
|
let navigation = $state(init.navigation || idleNavigationState());
|
|
31
31
|
const router = createRouterFacade(init.router, () => routeUrl, () => params);
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
// Pages and layouts keep the objects returned by useShared() and useParams()
|
|
34
|
+
// across navigations, so update them in place.
|
|
35
|
+
function replaceInPlace(target, next) {
|
|
36
|
+
for (const key of Object.keys(target)) {
|
|
37
|
+
delete target[key];
|
|
37
38
|
}
|
|
38
|
-
Object.assign(
|
|
39
|
+
Object.assign(target, next || {});
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
// Capitalized alias for dynamic component rendering
|
|
@@ -65,8 +66,8 @@
|
|
|
65
66
|
init.stores.page.subscribe((v) => { currentPage = v; }),
|
|
66
67
|
init.stores.props.subscribe((v) => { currentPageProps = v; }),
|
|
67
68
|
init.stores.layouts.subscribe((v) => { currentLayouts = v; }),
|
|
68
|
-
init.stores.shared.subscribe(
|
|
69
|
-
init.stores.params.subscribe((v) =>
|
|
69
|
+
init.stores.shared.subscribe((v) => replaceInPlace(shared, v)),
|
|
70
|
+
init.stores.params.subscribe((v) => replaceInPlace(params, v)),
|
|
70
71
|
init.stores.route.subscribe((v) => { routeUrl = v; }),
|
|
71
72
|
init.stores.navigation.subscribe((v) => { navigation = v; }),
|
|
72
73
|
];
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
VoidActionError,
|
|
3
|
-
categorizeActionError,
|
|
4
|
-
getValidationErrors,
|
|
5
|
-
isEqualFormValue,
|
|
6
|
-
} from 'void/pages-client';
|
|
1
|
+
import { isEqualFormValue, submitIslandAction, type VoidActionError } from 'void/pages-client';
|
|
7
2
|
|
|
8
3
|
type UntypedIslandForm = {
|
|
9
4
|
readonly data: Record<string, unknown>;
|
|
@@ -23,19 +18,6 @@ type UntypedIslandForm = {
|
|
|
23
18
|
clearError(): void;
|
|
24
19
|
};
|
|
25
20
|
|
|
26
|
-
async function readActionErrorBody(response: Response): Promise<unknown> {
|
|
27
|
-
const contentType = response.headers.get('content-type') || '';
|
|
28
|
-
try {
|
|
29
|
-
if (contentType.includes('application/json')) {
|
|
30
|
-
return await response.json();
|
|
31
|
-
}
|
|
32
|
-
const text = await response.text();
|
|
33
|
-
return text || null;
|
|
34
|
-
} catch {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
21
|
/**
|
|
40
22
|
* Form composable for island pages. Uses fetch + page reload instead of the
|
|
41
23
|
* Void Router (which is not available in island mode).
|
|
@@ -90,18 +72,14 @@ export function useIslandForm(defaults: Record<string, unknown>): UntypedIslandF
|
|
|
90
72
|
clearError();
|
|
91
73
|
|
|
92
74
|
try {
|
|
93
|
-
const
|
|
94
|
-
method,
|
|
95
|
-
headers: { 'Content-Type': 'application/json' },
|
|
96
|
-
body: JSON.stringify(data),
|
|
97
|
-
});
|
|
75
|
+
const result = await submitIslandAction(url, method, data);
|
|
98
76
|
|
|
99
|
-
if (
|
|
100
|
-
window.location.href =
|
|
77
|
+
if (result.kind === 'redirect') {
|
|
78
|
+
window.location.href = result.url;
|
|
101
79
|
return;
|
|
102
80
|
}
|
|
103
81
|
|
|
104
|
-
if (
|
|
82
|
+
if (result.kind === 'success') {
|
|
105
83
|
wasSuccessful = true;
|
|
106
84
|
recentlySuccessful = true;
|
|
107
85
|
defaults_ = { ...data };
|
|
@@ -109,23 +87,10 @@ export function useIslandForm(defaults: Record<string, unknown>): UntypedIslandF
|
|
|
109
87
|
recentlySuccessful = false;
|
|
110
88
|
}, 2000);
|
|
111
89
|
window.location.reload();
|
|
90
|
+
} else if (result.kind === 'validation') {
|
|
91
|
+
Object.assign(errors, result.errors);
|
|
112
92
|
} else {
|
|
113
|
-
|
|
114
|
-
const actionError = new VoidActionError({
|
|
115
|
-
body,
|
|
116
|
-
status: response.status,
|
|
117
|
-
statusText: response.statusText,
|
|
118
|
-
url,
|
|
119
|
-
});
|
|
120
|
-
const validationErrors = response.status === 422 ? getValidationErrors(body) : null;
|
|
121
|
-
if (validationErrors) {
|
|
122
|
-
Object.assign(errors, validationErrors);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (categorizeActionError(response.status) === 'boundary') {
|
|
126
|
-
throw actionError;
|
|
127
|
-
}
|
|
128
|
-
error = actionError;
|
|
93
|
+
error = result.error;
|
|
129
94
|
}
|
|
130
95
|
} finally {
|
|
131
96
|
pending = false;
|