Skip to content

Plugins ​

Plugins allow you to extend and customize Crelte's functionality. Plugins hook into Crelte mainly through plugin functions and events provided by crelte.events.

Adding a plugin ​

By convention, each plugin should provide a createMyPlugin function that accepts an optional configuration parameter. This function then needs to return a PluginCreator function, which in turn will return a Plugin object.

The plugin can then be added to App.svelte:

svelte
<script module>
	import { createMyPlugin } from './myPlugin.ts';

	export const plugins = [createMyPlugin()];
</script>

Example ​

ts
import { PluginCreator, Plugin } from 'crelte/plugins';

export function createMyPlugin(): PluginCreator {
	return crelte => new MyPlugin(crelte);
}

export function getMyPlugin(crelte?: Crelte): MyPlugin {
	crelte = crelte ?? getCrelte();
	return crelte.getPlugin('myPlugin') as MyPlugin;
}

export class MyPlugin implements Plugin {
	constructor(_crelte: Crelte) {}

	get name(): string {
		return 'myPlugin';
	}

	loadData(cr: CrelteRequest) {
		console.log('loadData');
	}
}

Using a plugin ​

By convention each plugin has a getMyPlugin function which accepts an optional Crelte instance and returns the plugin instance.

In a component or a template you then can use the plugin like this:

svelte
<script module>
	import { getMyPlugin } from './myPlugin.ts';

	/** @type {import('crelte').LoadData} */
	export const loadData = {
		// in loadData you need to provide crelte because
		pluginName: cr => getMyPlugin(cr).name
	};
</script>

<script>
	// in the component initialization you can omit the crelte instance
	const myPlugin = getMyPlugin();
</script>

Functions ​

toRequest ​

If your plugin loads data, it may make sense to make it stateful. With toRequest you can return a new plugin instance for each request, allowing request-specific data to be stored on that instance.

loadGlobalData ​

Gets called in the loadGlobalData phase.

loadData ​

Gets called in the loadData phase.

render ​

Gets called right before the DOM gets updated. In this function you should transition back from a stateful plugin (toRequest). Example

Events ​

For exact details when each request is fired, see data flow.

beforeRequest ​

Prefer to only return a promise if async work is needed, otherwise return without waiting. This allows a push request to be done without a microtask, allowing for a better dev experience.

ts
type Fn = (cr: CrelteRequest) => Promise<void> | void;

loadGlobalData ​

ts
type Fn = (cr: CrelteRequest) => Promise<any>;

loadEntry ​

This will execute all listeners in sequence and stop on the first one which returns an entry.
loadEntry is executed in preload as well.

ts
type Fn = (cr: CrelteRequest) => Promise<Entry | null> | Entry | null;

beforeQueryEntry ​

This allows to modify the entry query variables before the entry query is executed.
beforeQueryEntry executed in preload as well.

ts
type Fn = (cr: CrelteRequest, vars: EntryQueryVars) => Promise<void> | void;

afterLoadEntry ​

This will be executed in preload as well.

ts
type Fn = (cr: CrelteRequest) => Promise<any>;

loadData ​

ts
type Fn = (cr: CrelteRequest, entry: Entry) => Promise<any>;

beforeRender ​

ts
type Fn = (cr: CrelteRequest, route: Route) => void;

afterRender ​

Gets executed after a render. This can be used to scroll to a specific location or similar.

ts
type Fn = (cr: CrelteRequest, route: Route) => void;

Inside App.svelte ​

If you need to access some event but a fullblown plugin is overkill you can export the init function from App.svelte.

svelte
<script module>
	/** @type {import('crelte').Init} */
	export function init(crelte) {
		crelte.events.on('beforeRequest', () => console.log('beforeRequest'));
	}
</script>