Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] allow users to override IllegalModuleGuard default behaviour #7288

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fair-pumas-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[feat] allow users to override IllegalModuleGuard default behaviour
6 changes: 4 additions & 2 deletions packages/kit/src/exports/vite/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export async function dev(vite, vite_config, svelte_config) {
prevent_illegal_vite_imports(
module_node,
normalizePath(svelte_config.kit.files.lib),
extensions
extensions,
{ allow_server_import_from_client: svelte_config.kit.allowServerImportFromClient }
);

return module.default;
Expand All @@ -114,7 +115,8 @@ export async function dev(vite, vite_config, svelte_config) {
prevent_illegal_vite_imports(
module_node,
normalizePath(svelte_config.kit.files.lib),
extensions
extensions,
{ allow_server_import_from_client: svelte_config.kit.allowServerImportFromClient }
);
}

Expand Down
36 changes: 25 additions & 11 deletions packages/kit/src/exports/vite/graph_analysis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { normalizePath } from 'vite';
import { remove_query_from_id, get_module_types } from './utils.js';

/** @typedef {import('./types').ImportGraph} ImportGraph */
/** @typedef {import('./types').IllegalModuleGuardOptions} IllegalModuleGuardOptions */

const CWD_ID = normalizePath(process.cwd());
const NODE_MODULES_ID = normalizePath(path.resolve(process.cwd(), 'node_modules'));
Expand All @@ -24,12 +25,18 @@ export class IllegalModuleGuard {
/** @type {Array<ImportGraph>} */
#chain = [];

/** @type {(filepath: string) => boolean} */
#allow_server_import_from_client;

/**
* @param {string} lib_dir
* @param {IllegalModuleGuardOptions} [options]
*/
constructor(lib_dir) {
constructor(lib_dir, options) {
this.#lib_dir = normalizePath(lib_dir);
this.#server_dir = normalizePath(path.resolve(lib_dir, 'server'));
this.#allow_server_import_from_client =
options?.allow_server_import_from_client ?? (() => false);
}

/**
Expand All @@ -40,13 +47,18 @@ export class IllegalModuleGuard {
assert_legal(node) {
this.#chain.push(node);
for (const child of node.children) {
if (this.#is_illegal(child.id)) {
this.#chain.push(child);
const error = this.#format_illegal_import_chain(this.#chain);
this.#chain = []; // Reset the chain in case we want to reuse this guard
throw new Error(error);
if (this.#allow_server_import_from_client(child.id)) {
// Do not assert child nodes if module is allowed by user config
continue;
} else {
if (this.#is_illegal(child.id)) {
this.#chain.push(child);
const error = this.#format_illegal_import_chain(this.#chain);
this.#chain = []; // Reset the chain in case we want to reuse this guard
throw new Error(error);
}
this.assert_legal(child);
}
this.assert_legal(child);
}
this.#chain.pop();
}
Expand Down Expand Up @@ -255,11 +267,12 @@ export class ViteImportGraph {
* @param {(id: string) => import('rollup').ModuleInfo | null} node_getter
* @param {import('rollup').ModuleInfo} node
* @param {string} lib_dir
* @param {IllegalModuleGuardOptions} [options]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the rollup check is working and it's only the vite check that's broken, so I would remove this and have it only affect dev and not build

* @returns {void}
*/
export function prevent_illegal_rollup_imports(node_getter, node, lib_dir) {
export function prevent_illegal_rollup_imports(node_getter, node, lib_dir, options) {
const graph = new RollupImportGraph(node_getter, node);
const guard = new IllegalModuleGuard(lib_dir);
const guard = new IllegalModuleGuard(lib_dir, options);
guard.assert_legal(graph);
}

Expand All @@ -268,10 +281,11 @@ export function prevent_illegal_rollup_imports(node_getter, node, lib_dir) {
* @param {import('vite').ModuleNode} node
* @param {string} lib_dir
* @param {Iterable<string>} module_types File extensions to analyze in addition to the defaults: `.ts`, `.js`, etc.
* @param {IllegalModuleGuardOptions} [options]
* @returns {void}
*/
export function prevent_illegal_vite_imports(node, lib_dir, module_types) {
export function prevent_illegal_vite_imports(node, lib_dir, module_types, options) {
const graph = new ViteImportGraph(get_module_types(module_types), node);
const guard = new IllegalModuleGuard(lib_dir);
const guard = new IllegalModuleGuard(lib_dir, options);
guard.assert_legal(graph);
}
31 changes: 31 additions & 0 deletions packages/kit/src/exports/vite/graph_analysis/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,37 @@ describe('IllegalImportGuard', (test) => {

assert.not.throws(() => guard.assert_legal(module_graph));
});

test('assert ignores illegal server-only modules when allowed by user config', () => {
const guard = new IllegalModuleGuard(FAKE_LIB_DIR, {
allow_server_import_from_client: (moduleId) => moduleId.includes('.allowed.')
});

const module_graph = get_module_graph({
id: 'entry.svelte',
dynamic: false,
children: generator_from_array([
{
id: 'something.allowed.js',
dynamic: false,
children: generator_from_array([
{
id: PROD_VIRTUAL_STATIC_ID,
dynamic: false,
children: generator_from_array([])
},
{
id: USER_SERVER_FOLDER_ID,
dynamic: false,
children: generator_from_array([])
}
])
}
])
});

assert.not.throws(() => guard.assert_legal(module_graph));
});
});

/*
Expand Down
4 changes: 4 additions & 0 deletions packages/kit/src/exports/vite/graph_analysis/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ export interface ImportGraph {
readonly dynamic: boolean;
readonly children: Generator<ImportGraph>;
}

export interface IllegalModuleGuardOptions {
readonly allow_server_import_from_client?: (filepath: string) => boolean;
}
3 changes: 2 additions & 1 deletion packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ function kit() {
prevent_illegal_rollup_imports(
this.getModuleInfo.bind(this),
module_node,
vite.normalizePath(svelte_config.kit.files.lib)
vite.normalizePath(svelte_config.kit.files.lib),
{ allow_server_import_from_client: svelte_config.kit.allowServerImportFromClient }
);
}
});
Expand Down
1 change: 1 addition & 0 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export interface KitConfig {
name?: string;
pollInterval?: number;
};
allowServerImportFromClient?: (filepath: string) => boolean;
}

export interface Handle {
Expand Down