ECMAScript Modules
- kosko v3.0.0
Kosko supports ECMAScript modules (ESM). You can write components and environments in native ESM files.
Enabling
You don't have to modify any config in kosko.toml
at all. To start using ESM, you can either set type
in package.json
as below.
{
"type": "module"
}
Or rename file extension as .mjs
. See Node.js documentation for more information.
Environments
When @kosko/env
is imported in ESM, it returns a Promise
instead. This is because import()
is asynchronous. You MUST add await
when retrieving environment variables as below.
import env from "@kosko/env";
const globalParams = await env.global();
const componentParams = await env.component("demo");
Programmatical Usage
You can use @kosko/env
and @kosko/generate
package directly. The following is a basic example.
import env from "@kosko/env";
import { generate, print, PrintFormat } from "@kosko/generate";
import { fileURLToPath } from "node:url";
import { join } from "node:path";
// Set environment
env.env = "dev";
// Set CWD (optional)
env.cwd = fileURLToPath(new URL("./", import.meta.url));
// Generate manifests
const result = await generate({
path: join(env.cwd, "components"),
components: ["*"]
});
// Print manifests to stdout
print(result, {
format: PrintFormat.YAML,
writer: process.stdout
});
There's no much difference between CommonJS and ESM when using Kosko programmatically. However, it could be troublesome if you are going to use both CommonJS and ESM at the same time. In Node.js, ESM has its own separate cache, which means there are two isolated instances of Environment
in CommonJS and ESM and both must be initialized separately.
It's recommended to use only one module type. If you really need to use both, here's an example of how to initialize them.
function setupEnv(env) {
env.env = "dev";
env.cwd = __dirname;
}
// CommonJS
setupEnv(require("@kosko/env"));
// ESM
setupEnv((await import("@kosko/env")).default);
TypeScript
Set compilerOptions.module
to esnext
to allow TypeScript compile your code into ESM instead of CommonJS.
{
"compilerOptions": {
"module": "esnext"
}
}
Then add loaders
option to kosko.toml
.
loaders = ["ts-node/esm"]
extensions = ["ts", "mts", "cjs", "mjs", "js", "json"]
Or run kosko generate
with --loader
option.
kosko generate --loader ts-node/esm
Because @kosko/env
is asynchronous in ESM, it's recommended to modify environment types in order to better reflect actual types.
declare module "@kosko/env" {
interface Environment {
global(): Promise<GlobalEnvironment>;
component<K extends string>(
name: K
): Promise<GlobalEnvironment & ComponentEnvironment[K]>;
}
}
When loaders are specified, Kosko will run Node.js with --experimental-loader
option. You might see the following ExperimentalWarning
message in console and it is totally fine. To hide such warning message, run Kosko with NODE_NO_WARNINGS=1
environment variable.
(node:26303) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Related
📄️ Programmatic Usage
Kosko provides a programmatic API. You can generate manifests directly from Node.js.
📄️ @kosko/env
@kosko/env package