Writing a package
A package is just a project whose entry gets imported instead of run. There is no special format and no name field: the project that uses it picks the import name.
The layout
text
mathx/
thicket.json
src/
index.tks
easing.tksjson5
// mathx/thicket.json
{
entry: "src/index.tks",
}ts
// mathx/src/index.tks
export function lerp(a: float, b: float, t: float): float {
return a + (b - a) * t;
}
export function clamp01(t: float): float {
if (t < 0) {
return 0;
}
if (t > 1) {
return 1;
}
return t;
}Importing the package loads the entry's exports. It never calls main. A consumer reaches other files by path, relative to the package root: import { easeIn } from "mathx/src/easing";.
A package cannot import anything outside its own folder.
Using it
ts
// game/app.tks, with packages: { mathx: "../mathx" }
import { clamp01, lerp } from "mathx";
console.log(lerp(0, 10, clamp01(0.25)));Tests are a sub-project
Put the tests in a folder with its own thicket.json that lists the package by a relative path. They import it exactly as a real consumer would:
json5
// mathx/tests/thicket.json
{ entry: "all.tks", packages: { mathx: ".." } }There is no thicket test command yet. Run the tests with thicket run.
Declare what you need
List what the package uses. These are requirements, not grants:
json5
{
entry: "src/index.tks",
systems: ["willow"],
permissions: { fs: true },
}A project that uses your package has to list the same systems and turn on the same permissions. It gets a clear error naming the fix if it does not.
A package whose code uses engine makes its consumer a window app. Code that only needs the scene can read Scene.main instead, which is null in a console program and imposes no window.
Reach your own files with moduleDir
A relative path given to fs resolves against the working directory, which is the game's folder, not yours. To load your own fonts, images or data, build the path from moduleDir, the folder the current source file lives in:
ts
import { Files } from "fs";
export async function loadTheme(): Promise<string> {
return await Files.readText(Files.join(moduleDir, "theme.json"));
}moduleDir needs no import. It is right for a local folder, a package in thicket_packages/ and a built program alike. Reading through it is an ordinary file read, so the package declares fs and the consuming project grants it.
In a built program, a consumer ships your files by listing them as "<package>:<path>" in its assets.
Offer tools
A package can offer script tools to the projects that use it. Map a tool name to a script in tools:
json5
{
entry: "src/index.tks",
tools: { themec: "tools/themec.tks" },
}A project that lists the package runs it with thicket tool themec, and thicket tool lists every tool available.
Share it
Publish the folder as a git repository and tag a version. Users add it with a URL pinned to that tag, like "https://github.com/you/mathx-tks#v1.0.0". There is no package registry.