Gro supports SvelteKit apps, Node libraries, and Node servers with minimal abstraction
with the help of an optional config file that lives at the root gro.config.ts
.
If a project does not define a config, Gro imports a default config from
src/lib/gro.config.default.ts
,
which looks at your project for the familiar patterns and tries to do the right thing.
The default config detects three types of projects that can coexist in one repo: SvelteKit frontends, Node libraries with
@sveltejs/package
, and Node servers.
See src/lib/config.ts
for the config types and implementation.
The default config
is used for projects that do not define gro.config.ts
.
It's also passed as the first argument to Create_Gro_Config
.
A simple config that does nothing:
// gro.config.ts
import type {Create_Gro_Config} from '@ryanatkn/gro';
const config: Create_Gro_Config = async (cfg) => {
// mutate `cfg` or return a new object
return cfg;
};
export default config;
The default export of a Gro config is Gro_Config | Create_Gro_Config
:
export interface Create_Gro_Config {
(base_config: Gro_Config): Gro_Config | Promise<Gro_Config>;
}
export interface Gro_Config {
plugins: Create_Config_Plugins;
map_package_json: Map_Package_Json | null;
}
To define a user config that overrides the default plugins:
import type {Create_Gro_Config} from '@ryanatkn/gro';
import {gro_plugin_sveltekit_app} from '@ryanatkn/gro/gro_plugin_sveltekit_app.js';
const config: Create_Gro_Config = async (cfg) => {
// example setting your own plugins:
cfg.plugins = async () => [
gro_plugin_sveltekit_app(),
(await import('./src/custom_plugin.js')).plugin(),
];
// example extending the default plugins:
const get_base_plugins = cfg.plugins;
cfg.plugins = async (ctx) => {
// replace a base plugin with `import {replace_plugin} from '@ryanatkn/gro';`:
const updated_plugins = replace_plugin(
await get_base_plugins(ctx),
gro_plugin_sveltekit_app({
// host_target?: Host_Target;
// well_known_package_json?: boolean | Map_Package_Json;
}),
// 'gro_plugin_sveltekit_app', // optional name if they don't match
);
return updated_plugins.concat(create_some_custom_plugin());
};
return cfg;
};
export default config;
See also Gro's own internal config.
The plugins
property is a function that returns an array of Plugin
instances.
Read more about plugins and the Plugin
in
plugin.md, dev.md, and build.md.
export interface Create_Config_Plugins<T_Plugin_Context extends Plugin_Context = Plugin_Context> {
(
ctx: T_Plugin_Context,
):
| (Plugin<T_Plugin_Context> | null | Array<Plugin<T_Plugin_Context> | null>)
| Promise<Plugin<T_Plugin_Context> | null | Array<Plugin<T_Plugin_Context> | null>>;
}
The Gro config option map_package_json
hooks into Gro's package.json
automations.
The gro sync
task, which is called during the dev and build tasks among others,
performs several steps to get a project's state ready,
including svelte-kit sync
and package.json
automations.
When the map_package_json
config value is truthy,
Gro outputs a mapped version of the root package.json
.
The
gro check
task integrates withmap_package_json
to ensure everything is synced.
The main purpose of map_package_json
is to automate
the "exports"
property of your root package.json
.
The motivation is to streamline package publishing by supplementing
@sveltejs/package
.
By default package_json.exports
includes everything from $lib/
except for some ignored files like tests and markdown,
and you can provide your own map_package_json
hook to
mutate the package_json
, return new data, or return null
to be a no-op.
Typical usage modifies package_json.exports
during this step to define the public API.
// gro.config.ts
const config: Gro_Config = {
// ...other config
// disable mapping `package.json` with automated `exports`:
map_package_json: null,
// mutate anything and return the final config (can be async):
map_package_json: (package_json) => {
// example setting `exports`:
package_json.exports = {
'.': {
default: './dist/index.js',
types: './dist/index.d.ts',
},
'./example.js': {
default: './dist/example.js',
types: './dist/example.d.ts',
},
'./Example.svelte': {
svelte: './dist/Example.svelte',
types: './dist/Example.svelte.d.ts',
},
};
// example filtering `exports`:
package_json.exports = Object.fromEntries(
Object.entries(package_json.exports).filter(/* ... */),
);
return package_json; // returning `null` is a no-op
},
};
export interface Map_Package_Json {
(package_json: Package_Json): Package_Json | null | Promise<Package_Json | null>;
}