@toist/in 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@toist/in` are recorded here.
4
+
5
+ ## 0.2.0 — 2026-05-05
6
+
7
+ Initial release. Scaffold CLI for new toist instances.
8
+
9
+ - `bunx @toist/in <path>` writes a fresh instance directory at `<path>`
10
+ with `start.ts`, `kinds/custom.ts`, `pipelines/`, `resources/`, `data/`,
11
+ `README.md`, and a default `.gitignore`.
12
+ - Embedded templates ship with the package — no network calls during
13
+ scaffold.
14
+ - Prints a suggested `package.json` snippet to stdout for the host to merge.
15
+ - First release shipped together with `@toist/{spec,ui,run}@0.2.0` — the
16
+ rebrand from `@2121/*` (abandoned Gitea private registry) to `@toist/*`
17
+ on npmjs.com.
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@toist/in",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "description": "Scaffold a new toist instance: bunx @toist/in <path>",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "bin": {
9
+ "toist-in": "./src/index.ts"
10
+ },
11
+ "files": ["src/", "templates/", "CHANGELOG.md"]
12
+ }
package/src/index.ts ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bun
2
+ // 2121 toist
3
+ // @toist/in — scaffold a new toist instance.
4
+ //
5
+ // Usage: bunx @toist/in <path>
6
+ //
7
+ // Writes a fresh instance directory at <path> with start.ts, kinds/,
8
+ // pipelines/, resources/, data/, README.md, and .gitignore. Prints a
9
+ // suggested package.json snippet to stdout for the host to merge.
10
+
11
+ import { scaffold } from "./scaffold.ts"
12
+
13
+ const args = process.argv.slice(2)
14
+ const target = args[0]
15
+
16
+ if (!target || target === "--help" || target === "-h") {
17
+ console.log("bunx @toist/in <path> scaffold a new toist instance at <path>")
18
+ console.log("")
19
+ console.log("Full docs: https://toist.in")
20
+ process.exit(target ? 0 : 1)
21
+ }
22
+
23
+ await scaffold(target)
@@ -0,0 +1,68 @@
1
+ // 2121 toist
2
+ // Scaffold logic for @toist/in. Recursively copies templates/default/* into
3
+ // the target directory, with two special filename rules:
4
+ //
5
+ // - `_gitignore` -> `.gitignore` (npm strips real .gitignore files at publish
6
+ // time, so the templates ship them prefixed with an underscore)
7
+ // - `_package-snippet.json` is NOT copied — it is read and printed to stdout
8
+ // so the host can merge it into their existing package.json
9
+ //
10
+ // Templates live in `<package>/templates/default/`, relative to this file's
11
+ // runtime location. Works whether the package is consumed as a workspace
12
+ // link (in this repo) or from node_modules (in a host repo).
13
+
14
+ import { mkdir, copyFile, readdir, stat, readFile } from "node:fs/promises"
15
+ import { existsSync } from "node:fs"
16
+ import { dirname, join, resolve } from "node:path"
17
+ import { fileURLToPath } from "node:url"
18
+
19
+ const __dir = dirname(fileURLToPath(import.meta.url))
20
+ const TEMPLATE_DIR = resolve(__dir, "..", "templates", "default")
21
+ const SNIPPET_FILE = "_package-snippet.json"
22
+ const GITIGNORE_TPL = "_gitignore"
23
+
24
+ export async function scaffold(target: string): Promise<void> {
25
+ const dest = resolve(process.cwd(), target)
26
+
27
+ if (existsSync(dest)) {
28
+ const entries = await readdir(dest)
29
+ if (entries.length > 0) {
30
+ console.error(`Target directory '${dest}' is not empty. Aborting.`)
31
+ process.exit(1)
32
+ }
33
+ } else {
34
+ await mkdir(dest, { recursive: true })
35
+ }
36
+
37
+ await copyTree(TEMPLATE_DIR, dest)
38
+
39
+ const snippet = await readFile(join(TEMPLATE_DIR, SNIPPET_FILE), "utf8")
40
+
41
+ console.log(`\nScaffolded toist instance at ${dest}\n`)
42
+ console.log(`Add to your package.json (or create one at ${target}/package.json):`)
43
+ console.log("")
44
+ console.log(snippet)
45
+ console.log("Then:")
46
+ console.log(` cd ${target}`)
47
+ console.log(` bun install`)
48
+ console.log(` bun start.ts`)
49
+ console.log("")
50
+ console.log(`Full docs: https://toist.in`)
51
+ console.log("")
52
+ }
53
+
54
+ async function copyTree(src: string, dest: string): Promise<void> {
55
+ for (const entry of await readdir(src)) {
56
+ if (entry === SNIPPET_FILE) continue // printed, not copied
57
+ const srcPath = join(src, entry)
58
+ const destName = entry === GITIGNORE_TPL ? ".gitignore" : entry
59
+ const destPath = join(dest, destName)
60
+ const info = await stat(srcPath)
61
+ if (info.isDirectory()) {
62
+ await mkdir(destPath, { recursive: true })
63
+ await copyTree(srcPath, destPath)
64
+ } else {
65
+ await copyFile(srcPath, destPath)
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,23 @@
1
+ # my-toist-instance
2
+
3
+ Generated with [`bunx @toist/in`](https://toist.in).
4
+
5
+ ## First run
6
+
7
+ 1. Add the suggested deps to your `package.json` (printed by the scaffold output).
8
+ 2. `bun install`
9
+ 3. `bun start.ts` — runner boots on `http://localhost:3000`.
10
+
11
+ Open `http://localhost:3000` to use the UI.
12
+
13
+ ## Layout
14
+
15
+ - `start.ts` — bootstrap; calls `startRunner` from `@toist/run`
16
+ - `kinds/custom.ts` — register your domain-specific kinds here
17
+ - `pipelines/*.yaml` — pipeline definitions (per pipeline-spec)
18
+ - `resources/*.yaml` — resource definitions (per resource-spec)
19
+ - `data/` — runtime SQLite databases (gitignored)
20
+
21
+ ## More
22
+
23
+ Full quickstart and docs: https://toist.in
@@ -0,0 +1,7 @@
1
+ node_modules/
2
+ bun.lock
3
+ data/*.db
4
+ data/*.db-shm
5
+ data/*.db-wal
6
+ data/.lock/
7
+ .platform/
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "my-toist-instance",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "start": "bun start.ts",
7
+ "dev": "bun --watch start.ts"
8
+ },
9
+ "dependencies": {
10
+ "@toist/run": "^0.2.0",
11
+ "@toist/spec": "^0.2.0"
12
+ }
13
+ }
File without changes
@@ -0,0 +1,23 @@
1
+ // 2121 toist — register your domain-specific kinds here.
2
+ //
3
+ // Each export should be a NodeKind<P, I>. See the @toist/run built-ins for
4
+ // reference shapes, and pipeline-spec / kind-spec at https://toist.in for
5
+ // the full contract.
6
+ //
7
+ // Example:
8
+ //
9
+ // import type { NodeKind } from "@toist/spec"
10
+ //
11
+ // export const greet: NodeKind<{ name: string }, { msg: string }> = {
12
+ // id: "demo.greet",
13
+ // params: { name: { type: "string", required: true } },
14
+ // async execute(ctx) {
15
+ // return { msg: `Hello, ${ctx.params.name}!` }
16
+ // },
17
+ // }
18
+ //
19
+ // Then in start.ts:
20
+ // import * as customKinds from "./kinds/custom.ts"
21
+ // register(...Object.values(customKinds))
22
+
23
+ export {}
File without changes
File without changes
@@ -0,0 +1,14 @@
1
+ // 2121 toist instance bootstrap.
2
+ // See https://toist.in for the full quickstart.
3
+
4
+ import { startRunner } from "@toist/run"
5
+
6
+ // Uncomment to register domain-specific kinds:
7
+ // import { register } from "@toist/run"
8
+ // import * as customKinds from "./kinds/custom.ts"
9
+ // register(...Object.values(customKinds))
10
+
11
+ await startRunner({
12
+ port: Number(process.env.PORT ?? 3000),
13
+ rootDir: import.meta.dir,
14
+ })