@silvermoon-work/task-builder-cli 0.0.0 → 0.1.0-canary-261109-1
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/LICENSE +21 -0
- package/README.md +138 -1
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +23 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +191 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +148 -0
- package/dist/node.js.map +1 -0
- package/dist/project.d.ts +10 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +81 -0
- package/dist/project.js.map +1 -0
- package/package.json +50 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 silvermoon-work contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,140 @@
|
|
|
1
1
|
# @silvermoon-work/task-builder-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Independent Commander 14 CLI and reusable command runner for
|
|
4
|
+
[@silvermoon-work/task-builder](../task-builder/README.md).
|
|
5
|
+
The core owns read-only tree transformations; this package owns argument parsing,
|
|
6
|
+
help, version, output rendering, host paths, file writes and executable signals.
|
|
7
|
+
It does not implement bundling or CAR encoding itself.
|
|
8
|
+
|
|
9
|
+
This package and the extracted core APIs are **not yet published**. The old
|
|
10
|
+
`task-builder@0.1.0-canary-261109-1` binary is not this CLI. Use the
|
|
11
|
+
[two-tarball development workflow](../../docs/end-to-end-verification.md) until
|
|
12
|
+
explicitly authorized releases are available.
|
|
13
|
+
|
|
14
|
+
## Commands
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
task-builder init <new-directory> [--name <name>] [--cli-version <specifier>] [--builder-version <specifier>]
|
|
18
|
+
task-builder build <task.build.yaml> [--root <directory>] [--trusted-contract]
|
|
19
|
+
task-builder car <bundle-directory> <output.car> [--cid-file <output.cid>]
|
|
20
|
+
task-builder check <bundle.car> [--expected-cid <cid>]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The original `task-builder <task.build.yaml> [build options]` shorthand is
|
|
24
|
+
Commander's default build command, not a second hand-written parser.
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
task-builder --help
|
|
28
|
+
task-builder build --help
|
|
29
|
+
task-builder help car
|
|
30
|
+
task-builder --version
|
|
31
|
+
task-builder check bundle.car --format text
|
|
32
|
+
task-builder --format json check bundle.car
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Commander provides required arguments, allowed choices, option parsing and help.
|
|
36
|
+
Duplicate options are rejected through Commander option events.
|
|
37
|
+
`--format json|text` works before or after a subcommand. Results/errors default
|
|
38
|
+
to JSON for compatibility with the original CLI; `--format text` selects
|
|
39
|
+
human-readable summaries. Help/version remain text.
|
|
40
|
+
|
|
41
|
+
Success result shapes are unchanged:
|
|
42
|
+
|
|
43
|
+
| Command | JSON result |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| init | `{ directory, files, nextSteps }` |
|
|
46
|
+
| build | `{ directory, files }` |
|
|
47
|
+
| car | `{ car, cid, cidFile? }` |
|
|
48
|
+
| check | `{ cid, declaration, bytes, files }` |
|
|
49
|
+
|
|
50
|
+
Failures go to stderr, never success-shaped stdout. JSON errors use
|
|
51
|
+
`{ error: { code, message } }`. Exit codes are 0 for success/help/version,
|
|
52
|
+
2 for Commander usage errors, 1 for operation errors, 130 for SIGINT and
|
|
53
|
+
143 for SIGTERM. There is no automatic install, overwrite, upload, pin or publish.
|
|
54
|
+
|
|
55
|
+
## Init composition
|
|
56
|
+
|
|
57
|
+
Core init returns a package-manager-neutral template tree with Task sources,
|
|
58
|
+
JSON contract, shared text Schema, greeting resource and private SDK package.
|
|
59
|
+
The CLI adds:
|
|
60
|
+
|
|
61
|
+
- build/CAR/check npm scripts referencing the `task-builder` binary;
|
|
62
|
+
- direct dev dependencies on **both** CLI and core;
|
|
63
|
+
- the pnpm version, scoped esbuild approval and release-age exceptions.
|
|
64
|
+
|
|
65
|
+
Default CLI/core versions come from the installed package metadata, not a moving
|
|
66
|
+
`canary` tag. `--cli-version` selects the CLI dependency. An explicit
|
|
67
|
+
`--builder-version` also adds a scoped pnpm override so a local core tarball is
|
|
68
|
+
used by the CLI's transitive dependency as well. This is useful before publication
|
|
69
|
+
and avoids accidentally mixing the new CLI with the old published core.
|
|
70
|
+
The override and scoped release-age exceptions live in `pnpm-workspace.yaml`,
|
|
71
|
+
not the obsolete `package.json#pnpm` configuration. Exemptions use selected
|
|
72
|
+
package names, so local `file:` specs are not incorrectly treated as npm versions.
|
|
73
|
+
|
|
74
|
+
Init only writes into a new directory whose parent exists and is canonical.
|
|
75
|
+
It does not merge with an existing project or modify an ancestor package.
|
|
76
|
+
`--name` defaults to `task-project`. Additional Task template settings are
|
|
77
|
+
available through the library's `createCliTaskProject` options, not new CLI flags.
|
|
78
|
+
|
|
79
|
+
## Reusable runner
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { runTaskBuilderCli } from "@silvermoon-work/task-builder-cli";
|
|
83
|
+
|
|
84
|
+
const exitCode = await runTaskBuilderCli(
|
|
85
|
+
["build", "task.build.yaml", "--format", "json"],
|
|
86
|
+
{
|
|
87
|
+
cwd: projectDirectory,
|
|
88
|
+
signal,
|
|
89
|
+
stdout: { write: (text) => output.write(text) },
|
|
90
|
+
stderr: { write: (text) => diagnostics.write(text) },
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Each invocation has its own Commander instance and returns an exit code.
|
|
96
|
+
Importing the library does not run a command, change `process.exitCode`, install
|
|
97
|
+
signal handlers or start a service. Programmatic abort returns 130; only `bin.js`
|
|
98
|
+
owns process SIGINT/SIGTERM and their corresponding executable exit codes.
|
|
99
|
+
`createCliTaskProject(options)` can be used independently to decorate a template
|
|
100
|
+
without writing it to disk or installing packages.
|
|
101
|
+
|
|
102
|
+
## Node adapters
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { buildTaskBundle } from "@silvermoon-work/task-builder";
|
|
106
|
+
import {
|
|
107
|
+
directoryTree,
|
|
108
|
+
writeDirectory,
|
|
109
|
+
writeStreamFile,
|
|
110
|
+
} from "@silvermoon-work/task-builder-cli/node";
|
|
111
|
+
|
|
112
|
+
const input = await directoryTree(projectDirectory);
|
|
113
|
+
const output = await buildTaskBundle(input, options);
|
|
114
|
+
await writeDirectory(output, newOutputDirectory);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The directory adapter is a live view, not an atomic snapshot or OS sandbox.
|
|
118
|
+
Confined links support pnpm's virtual store; escaping links and special files
|
|
119
|
+
are rejected. Writes use backpressure, cancellation and exclusive file creation.
|
|
120
|
+
Only newly created files/directories are removed on failure; existing output
|
|
121
|
+
is never overwritten. CAR and CID paths cannot be inside the Bundle directory
|
|
122
|
+
or equal each other. A failed CID sidecar write removes the newly created CAR.
|
|
123
|
+
|
|
124
|
+
## Repository development
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
pnpm --filter @silvermoon-work/task-builder-cli... build
|
|
128
|
+
node packages/task-builder-cli/dist/bin.js --help
|
|
129
|
+
node packages/task-builder-cli/dist/bin.js build packages/task-builder/examples/echo/task.build.yaml
|
|
130
|
+
pnpm --filter @silvermoon-work/task-builder-cli test
|
|
131
|
+
pnpm check
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The example build fails explicitly if its output already exists.
|
|
135
|
+
CLI and core are separately mapped publishable libraries. Publish the exact
|
|
136
|
+
core dependency before tagging this CLI; this package needs its own npm package
|
|
137
|
+
identity and Trusted Publisher configuration. No release is performed by build.
|
|
138
|
+
The modified core must receive a new version first: do not publish this CLI
|
|
139
|
+
against the old `task-builder@0.1.0-canary-261109-1`, which lacks `./tree` and
|
|
140
|
+
the current init/CAR APIs.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runTaskBuilderCli } from "./index.js";
|
|
3
|
+
const controller = new AbortController();
|
|
4
|
+
let interrupted;
|
|
5
|
+
const interrupt = () => {
|
|
6
|
+
interrupted = 130;
|
|
7
|
+
controller.abort(new Error("Task builder interrupted by SIGINT."));
|
|
8
|
+
};
|
|
9
|
+
const terminate = () => {
|
|
10
|
+
interrupted = 143;
|
|
11
|
+
controller.abort(new Error("Task builder interrupted by SIGTERM."));
|
|
12
|
+
};
|
|
13
|
+
process.once("SIGINT", interrupt);
|
|
14
|
+
process.once("SIGTERM", terminate);
|
|
15
|
+
try {
|
|
16
|
+
const code = await runTaskBuilderCli(process.argv.slice(2), { signal: controller.signal });
|
|
17
|
+
process.exitCode = interrupted ?? code;
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
process.removeListener("SIGINT", interrupt);
|
|
21
|
+
process.removeListener("SIGTERM", terminate);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;AACzC,IAAI,WAA+B,CAAC;AACpC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,WAAW,GAAG,GAAG,CAAC;IAClB,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC;AACF,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,WAAW,GAAG,GAAG,CAAC;IAClB,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC;AACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAClC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACnC,IAAI,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3F,OAAO,CAAC,QAAQ,GAAG,WAAW,IAAI,IAAI,CAAC;AACzC,CAAC;QAAS,CAAC;IACT,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC5C,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReadOptions } from "@silvermoon-work/task-builder/tree";
|
|
2
|
+
export { createCliTaskProject, type CliTaskProjectOptions } from "./project.js";
|
|
3
|
+
export interface CliWriter {
|
|
4
|
+
write(text: string): void | boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface TaskBuilderCliOptions extends ReadOptions {
|
|
7
|
+
readonly cwd?: string;
|
|
8
|
+
readonly stdout?: CliWriter;
|
|
9
|
+
readonly stderr?: CliWriter;
|
|
10
|
+
}
|
|
11
|
+
/** Run one invocation without starting listeners, installing signal handlers or exiting the process. */
|
|
12
|
+
export declare function runTaskBuilderCli(argv: readonly string[], options?: TaskBuilderCliOptions): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAIlF,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAEhF,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;CACrC;AACD,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AAuBD,wGAAwG;AACxG,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CAsNjB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
2
|
+
import { unlink } from "node:fs/promises";
|
|
3
|
+
import { Command, CommanderError, InvalidArgumentError, Option } from "commander";
|
|
4
|
+
import { memoryFile } from "@silvermoon-work/task-builder/tree";
|
|
5
|
+
import { directoryTree, writeDirectory, writeStreamFile } from "./node.js";
|
|
6
|
+
import { cliVersion, createCliTaskProject } from "./project.js";
|
|
7
|
+
export { createCliTaskProject } from "./project.js";
|
|
8
|
+
function singleOption(command, option) {
|
|
9
|
+
let seen = false;
|
|
10
|
+
command.addOption(option);
|
|
11
|
+
command.on(`option:${option.name()}`, () => {
|
|
12
|
+
if (seen)
|
|
13
|
+
throw new InvalidArgumentError(`Duplicate option --${option.name()}.`);
|
|
14
|
+
seen = true;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/** Run one invocation without starting listeners, installing signal handlers or exiting the process. */
|
|
18
|
+
export async function runTaskBuilderCli(argv, options = {}) {
|
|
19
|
+
const stdout = options.stdout ?? process.stdout;
|
|
20
|
+
const stderr = options.stderr ?? process.stderr;
|
|
21
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
22
|
+
const readOptions = options.signal ? { signal: options.signal } : {};
|
|
23
|
+
let diagnostics = "";
|
|
24
|
+
const program = new Command();
|
|
25
|
+
let activeCommand = program;
|
|
26
|
+
const render = (command, result, text) => {
|
|
27
|
+
stdout.write(command.optsWithGlobals().format === "text"
|
|
28
|
+
? `${text}\n`
|
|
29
|
+
: `${JSON.stringify(result)}\n`);
|
|
30
|
+
};
|
|
31
|
+
const formatOption = () => new Option("--format <format>", "Output format for results and errors").choices([
|
|
32
|
+
"json",
|
|
33
|
+
"text",
|
|
34
|
+
]);
|
|
35
|
+
const buildOptions = (command) => {
|
|
36
|
+
singleOption(command, new Option("--root <directory>", "Read-only input root (default: current directory)"));
|
|
37
|
+
singleOption(command, new Option("--trusted-contract", "Allow execution of trusted code contracts"));
|
|
38
|
+
};
|
|
39
|
+
const build = async (config, command) => {
|
|
40
|
+
const flags = command.optsWithGlobals();
|
|
41
|
+
const root = resolve(cwd, flags.root ?? cwd);
|
|
42
|
+
const input = await directoryTree(root);
|
|
43
|
+
const file = (isAbsolute(config) ? relative(root, config) : config).split(sep).join("/");
|
|
44
|
+
const { buildTaskBundle, readTaskBuild } = await import("@silvermoon-work/task-builder");
|
|
45
|
+
const definition = await readTaskBuild(input, file, {
|
|
46
|
+
...readOptions,
|
|
47
|
+
allowContractExecution: flags.trustedContract === true,
|
|
48
|
+
});
|
|
49
|
+
const tree = await buildTaskBundle(input, definition.options);
|
|
50
|
+
const directory = resolve(root, ...definition.outDirectory.split("/"));
|
|
51
|
+
const files = await writeDirectory(tree, directory, readOptions);
|
|
52
|
+
render(command, { directory, files }, `Built ${files.length} files into ${directory}`);
|
|
53
|
+
};
|
|
54
|
+
try {
|
|
55
|
+
options.signal?.throwIfAborted();
|
|
56
|
+
program
|
|
57
|
+
.name("task-builder")
|
|
58
|
+
.description("Initialize, build, encode and verify Task Bundles using read-only file trees.")
|
|
59
|
+
.version(await cliVersion(), "-v, --version")
|
|
60
|
+
.exitOverride()
|
|
61
|
+
.configureOutput({
|
|
62
|
+
writeOut: (text) => {
|
|
63
|
+
stdout.write(text);
|
|
64
|
+
},
|
|
65
|
+
writeErr: (text) => {
|
|
66
|
+
diagnostics += text;
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
program.addHelpText("after", "\nLegacy shorthand: task-builder <task.build.yaml> [build options]");
|
|
70
|
+
program.hook("preSubcommand", (_parent, command) => {
|
|
71
|
+
activeCommand = command;
|
|
72
|
+
});
|
|
73
|
+
singleOption(program, formatOption().default("json"));
|
|
74
|
+
const init = program
|
|
75
|
+
.command("init")
|
|
76
|
+
.description("Create a new task project; never install, overwrite or edit ancestor packages.")
|
|
77
|
+
.argument("<directory>", "New project directory (parent must exist)");
|
|
78
|
+
singleOption(init, formatOption());
|
|
79
|
+
singleOption(init, new Option("--name <name>", "Lowercase npm project name").default("task-project"));
|
|
80
|
+
singleOption(init, new Option("--cli-version <specifier>", "CLI dependency specifier (default: installed CLI version)"));
|
|
81
|
+
singleOption(init, new Option("--builder-version <specifier>", "Select and override the core builder dependency (default: installed version)"));
|
|
82
|
+
init.action(async (directory, _flags, command) => {
|
|
83
|
+
const flags = command.optsWithGlobals();
|
|
84
|
+
const tree = await createCliTaskProject({
|
|
85
|
+
...(flags.name !== undefined ? { name: flags.name } : {}),
|
|
86
|
+
...(flags.cliVersion !== undefined ? { cliVersion: flags.cliVersion } : {}),
|
|
87
|
+
...(flags.builderVersion !== undefined ? { builderVersion: flags.builderVersion } : {}),
|
|
88
|
+
});
|
|
89
|
+
const output = resolve(cwd, directory);
|
|
90
|
+
const files = await writeDirectory(tree, output, readOptions);
|
|
91
|
+
const nextSteps = ["pnpm install", "pnpm build", "pnpm car", "pnpm check"];
|
|
92
|
+
render(command, { directory: output, files, nextSteps }, `Created ${output}\nNext: enter that directory and run ${nextSteps.join(", ")}`);
|
|
93
|
+
});
|
|
94
|
+
const buildCommand = program
|
|
95
|
+
.command("build", { isDefault: true })
|
|
96
|
+
.description("Compile a task build declaration into a new Bundle directory.")
|
|
97
|
+
.argument("<config>", "Build YAML path within --root");
|
|
98
|
+
singleOption(buildCommand, formatOption());
|
|
99
|
+
buildOptions(buildCommand);
|
|
100
|
+
buildCommand.action(async (config, _flags, command) => build(config, command));
|
|
101
|
+
const car = program
|
|
102
|
+
.command("car")
|
|
103
|
+
.description("Stream a canonical CAR v1 from a Bundle directory with bounded block staging.")
|
|
104
|
+
.argument("<directory>", "Input Bundle directory")
|
|
105
|
+
.argument("<output>", "New CAR output file");
|
|
106
|
+
singleOption(car, formatOption());
|
|
107
|
+
singleOption(car, new Option("--cid-file <path>", "Also write the root CID into a new file"));
|
|
108
|
+
car.action(async (directory, output, _flags, command) => {
|
|
109
|
+
const flags = command.optsWithGlobals();
|
|
110
|
+
const input = resolve(cwd, directory);
|
|
111
|
+
const destination = resolve(cwd, output);
|
|
112
|
+
const cidFile = flags.cidFile === undefined ? undefined : resolve(cwd, flags.cidFile);
|
|
113
|
+
if (cidFile === destination)
|
|
114
|
+
throw new Error("CAR and CID output paths must differ.");
|
|
115
|
+
for (const path of [destination, ...(cidFile === undefined ? [] : [cidFile])]) {
|
|
116
|
+
const distance = relative(input, path);
|
|
117
|
+
if (!distance ||
|
|
118
|
+
(distance !== ".." && !distance.startsWith(`..${sep}`) && !distance.includes(":")))
|
|
119
|
+
throw new Error("CAR outputs must not be inside the input Bundle directory.");
|
|
120
|
+
}
|
|
121
|
+
const { encodeTaskBundleCar } = await import("@silvermoon-work/task-builder/car");
|
|
122
|
+
const archive = await encodeTaskBundleCar(await directoryTree(input), readOptions);
|
|
123
|
+
let installed = false;
|
|
124
|
+
try {
|
|
125
|
+
await writeStreamFile(archive.stream, destination, readOptions);
|
|
126
|
+
installed = true;
|
|
127
|
+
if (cidFile !== undefined)
|
|
128
|
+
await writeStreamFile(memoryFile(Buffer.from(`${archive.cid}\n`), readOptions), cidFile, readOptions);
|
|
129
|
+
render(command, { car: destination, cid: archive.cid, ...(cidFile !== undefined ? { cidFile } : {}) }, `Wrote ${destination}\nRoot CID: ${archive.cid}`);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (installed)
|
|
133
|
+
await unlink(destination);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
await archive.close();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const check = program
|
|
141
|
+
.command("check")
|
|
142
|
+
.description("Verify a complete CAR, canonical file tree, manifest, Schemas and resource bytes.")
|
|
143
|
+
.argument("<car>", "CAR file to inspect");
|
|
144
|
+
singleOption(check, formatOption());
|
|
145
|
+
singleOption(check, new Option("--expected-cid <cid>", "Require this exact Bundle root CID"));
|
|
146
|
+
check.action(async (carFile, _flags, command) => {
|
|
147
|
+
const flags = command.optsWithGlobals();
|
|
148
|
+
const path = resolve(cwd, carFile);
|
|
149
|
+
const input = await directoryTree(dirname(path));
|
|
150
|
+
const { readTaskBundleCar } = await import("@silvermoon-work/task-builder/car");
|
|
151
|
+
const archive = await readTaskBundleCar(await input.read(basename(path), readOptions), {
|
|
152
|
+
...readOptions,
|
|
153
|
+
...(flags.expectedCid !== undefined ? { expectedCid: flags.expectedCid } : {}),
|
|
154
|
+
});
|
|
155
|
+
try {
|
|
156
|
+
render(command, {
|
|
157
|
+
cid: archive.cid,
|
|
158
|
+
declaration: archive.declaration,
|
|
159
|
+
bytes: archive.bytes,
|
|
160
|
+
files: archive.files,
|
|
161
|
+
}, `Verified ${archive.files} files (${archive.bytes} bytes)\nRoot CID: ${archive.cid}`);
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
await archive.close();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
if (argv.length === 0)
|
|
168
|
+
program.outputHelp();
|
|
169
|
+
else
|
|
170
|
+
await program.parseAsync([...argv], { from: "user" });
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error instanceof CommanderError && error.exitCode === 0)
|
|
175
|
+
return 0;
|
|
176
|
+
const usage = error instanceof CommanderError;
|
|
177
|
+
const code = usage
|
|
178
|
+
? "invalid_arguments"
|
|
179
|
+
: error instanceof Error && "code" in error && typeof error.code === "string"
|
|
180
|
+
? error.code
|
|
181
|
+
: options.signal?.aborted
|
|
182
|
+
? "interrupted"
|
|
183
|
+
: "operation_failed";
|
|
184
|
+
const message = diagnostics.trim() || (error instanceof Error ? error.message : String(error));
|
|
185
|
+
stderr.write(activeCommand.optsWithGlobals().format === "text"
|
|
186
|
+
? `${message}\n`
|
|
187
|
+
: `${JSON.stringify({ error: { code, message } })}\n`);
|
|
188
|
+
return options.signal?.aborted ? 130 : usage ? 2 : 1;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ReadonlyFileTree, type ReadOptions } from "@silvermoon-work/task-builder/tree";
|
|
2
|
+
/** Consume one stream with backpressure; remove only the newly created file on failure. */
|
|
3
|
+
export declare function writeStreamFile(stream: ReadableStream<Uint8Array>, file: string, options?: ReadOptions): Promise<void>;
|
|
4
|
+
/** A live read-only view, not an atomic snapshot. Confined dependency links are followed. */
|
|
5
|
+
export declare function directoryTree(directory: string): Promise<ReadonlyFileTree>;
|
|
6
|
+
/** Write sequentially into a new directory; never replace an existing output. */
|
|
7
|
+
export declare function writeDirectory(tree: ReadonlyFileTree, directory: string, options?: ReadOptions): Promise<readonly string[]>;
|
|
8
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAIA,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEjB,MAAM,oCAAoC,CAAC;AAS5C,2FAA2F;AAC3F,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED,6FAA6F;AAC7F,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2ChF;AAED,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,IAAI,EAAE,gBAAgB,EACtB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CA6C5B"}
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { mkdir, open, readdir, realpath, rmdir, stat, unlink } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { Readable } from "node:stream";
|
|
5
|
+
import { checkTreePath, listTree, streamChunks, treeError, } from "@silvermoon-work/task-builder/tree";
|
|
6
|
+
function inside(root, path) {
|
|
7
|
+
const distance = relative(root, path);
|
|
8
|
+
return (!distance || (!distance.startsWith(`..${sep}`) && distance !== ".." && !distance.includes(":")));
|
|
9
|
+
}
|
|
10
|
+
/** Consume one stream with backpressure; remove only the newly created file on failure. */
|
|
11
|
+
export async function writeStreamFile(stream, file, options = {}) {
|
|
12
|
+
let handle;
|
|
13
|
+
try {
|
|
14
|
+
options.signal?.throwIfAborted();
|
|
15
|
+
handle = await open(file, "wx");
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
await stream.cancel(error);
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
for await (const chunk of streamChunks(stream, options)) {
|
|
23
|
+
let offset = 0;
|
|
24
|
+
while (offset < chunk.byteLength) {
|
|
25
|
+
options.signal?.throwIfAborted();
|
|
26
|
+
const { bytesWritten } = await handle.write(chunk, offset);
|
|
27
|
+
if (!bytesWritten)
|
|
28
|
+
throw new Error(`Output write made no progress: ${file}`);
|
|
29
|
+
offset += bytesWritten;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await handle.close();
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const errors = [error];
|
|
36
|
+
try {
|
|
37
|
+
await handle.close();
|
|
38
|
+
}
|
|
39
|
+
catch (cleanupError) {
|
|
40
|
+
errors.push(cleanupError);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
await unlink(file);
|
|
44
|
+
}
|
|
45
|
+
catch (cleanupError) {
|
|
46
|
+
errors.push(cleanupError);
|
|
47
|
+
}
|
|
48
|
+
if (errors.length > 1)
|
|
49
|
+
throw new AggregateError(errors, "Stream write and cleanup failed.");
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** A live read-only view, not an atomic snapshot. Confined dependency links are followed. */
|
|
54
|
+
export async function directoryTree(directory) {
|
|
55
|
+
const root = await realpath(resolve(directory));
|
|
56
|
+
if (!(await stat(root)).isDirectory())
|
|
57
|
+
throw treeError("ENOTDIR", root, "Input must be a directory");
|
|
58
|
+
const locate = async (path) => {
|
|
59
|
+
checkTreePath(path);
|
|
60
|
+
const target = await realpath(join(root, ...path.split("/")));
|
|
61
|
+
if (!inside(root, target))
|
|
62
|
+
throw treeError("EINVAL", path, "Link escapes input tree");
|
|
63
|
+
return target;
|
|
64
|
+
};
|
|
65
|
+
return Object.freeze({
|
|
66
|
+
async list(path, options = {}) {
|
|
67
|
+
options.signal?.throwIfAborted();
|
|
68
|
+
const entries = [];
|
|
69
|
+
for (const entry of await readdir(await locate(path), { withFileTypes: true })) {
|
|
70
|
+
options.signal?.throwIfAborted();
|
|
71
|
+
const child = path ? `${path}/${entry.name}` : entry.name;
|
|
72
|
+
const target = entry.isSymbolicLink() ? await locate(child) : undefined;
|
|
73
|
+
const info = target ? await stat(target) : entry;
|
|
74
|
+
if (!info.isFile() && !info.isDirectory())
|
|
75
|
+
throw treeError("EINVAL", child, "Tree contains a special file");
|
|
76
|
+
entries.push({
|
|
77
|
+
name: entry.name,
|
|
78
|
+
kind: info.isDirectory() ? "directory" : "file",
|
|
79
|
+
...(target !== undefined ? { target: relative(root, target).split(sep).join("/") } : {}),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
83
|
+
},
|
|
84
|
+
async read(path, options = {}) {
|
|
85
|
+
options.signal?.throwIfAborted();
|
|
86
|
+
const target = await locate(path);
|
|
87
|
+
if (!(await stat(target)).isFile())
|
|
88
|
+
throw treeError("EISDIR", path, "Expected a regular file");
|
|
89
|
+
const handle = await open(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
90
|
+
return Readable.toWeb(handle.createReadStream({
|
|
91
|
+
highWaterMark: 65_536,
|
|
92
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
93
|
+
}));
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/** Write sequentially into a new directory; never replace an existing output. */
|
|
98
|
+
export async function writeDirectory(tree, directory, options = {}) {
|
|
99
|
+
options.signal?.throwIfAborted();
|
|
100
|
+
const output = resolve(directory);
|
|
101
|
+
const parent = await realpath(dirname(output));
|
|
102
|
+
if (parent !== dirname(output))
|
|
103
|
+
throw new Error("Output parent must be canonical, without links.");
|
|
104
|
+
await mkdir(output, { recursive: false });
|
|
105
|
+
const files = [];
|
|
106
|
+
const directories = [output];
|
|
107
|
+
const write = async (path) => {
|
|
108
|
+
for (const entry of await listTree(tree, path, options)) {
|
|
109
|
+
options.signal?.throwIfAborted();
|
|
110
|
+
const child = path ? `${path}/${entry.name}` : entry.name;
|
|
111
|
+
const target = join(output, ...child.split("/"));
|
|
112
|
+
if (entry.kind === "directory") {
|
|
113
|
+
await mkdir(target);
|
|
114
|
+
directories.push(target);
|
|
115
|
+
await write(child);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
await writeStreamFile(await tree.read(child, options), target, options);
|
|
119
|
+
files.push(target);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
try {
|
|
124
|
+
await write("");
|
|
125
|
+
return files.map((file) => relative(output, file).split(sep).join("/")).sort();
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
const errors = [error];
|
|
129
|
+
for (const file of [...files].reverse())
|
|
130
|
+
try {
|
|
131
|
+
await unlink(file);
|
|
132
|
+
}
|
|
133
|
+
catch (cleanupError) {
|
|
134
|
+
errors.push(cleanupError);
|
|
135
|
+
}
|
|
136
|
+
for (const directory of [...directories].reverse())
|
|
137
|
+
try {
|
|
138
|
+
await rmdir(directory);
|
|
139
|
+
}
|
|
140
|
+
catch (cleanupError) {
|
|
141
|
+
errors.push(cleanupError);
|
|
142
|
+
}
|
|
143
|
+
if (errors.length > 1)
|
|
144
|
+
throw new AggregateError(errors, "Build failed and output cleanup failed.");
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TaskProjectOptions } from "@silvermoon-work/task-builder/init";
|
|
2
|
+
import { type ReadonlyFileTree } from "@silvermoon-work/task-builder/tree";
|
|
3
|
+
export interface CliTaskProjectOptions extends TaskProjectOptions {
|
|
4
|
+
readonly cliVersion?: string;
|
|
5
|
+
readonly builderVersion?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function cliVersion(): Promise<string>;
|
|
8
|
+
/** Add CLI scripts and installation policy to the core's package-manager-neutral template. */
|
|
9
|
+
export declare function createCliTaskProject(options?: CliTaskProjectOptions): Promise<ReadonlyFileTree>;
|
|
10
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,oCAAoC,CAAC;AAE5C,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAiBD,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAK5C;AAED,8FAA8F;AAC9F,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAqE3B"}
|
package/dist/project.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { fileTree, listTree, memoryFile, readBytes, } from "@silvermoon-work/task-builder/tree";
|
|
3
|
+
async function packageVersion(url, name) {
|
|
4
|
+
const value = JSON.parse(await readFile(url, "utf8"));
|
|
5
|
+
if (!value ||
|
|
6
|
+
typeof value !== "object" ||
|
|
7
|
+
Array.isArray(value) ||
|
|
8
|
+
!("name" in value) ||
|
|
9
|
+
value.name !== name ||
|
|
10
|
+
!("version" in value) ||
|
|
11
|
+
typeof value.version !== "string")
|
|
12
|
+
throw new Error(`Invalid installed package metadata: ${name}`);
|
|
13
|
+
return value.version;
|
|
14
|
+
}
|
|
15
|
+
export function cliVersion() {
|
|
16
|
+
return packageVersion(new URL("../package.json", import.meta.url), "@silvermoon-work/task-builder-cli");
|
|
17
|
+
}
|
|
18
|
+
/** Add CLI scripts and installation policy to the core's package-manager-neutral template. */
|
|
19
|
+
export async function createCliTaskProject(options = {}) {
|
|
20
|
+
const { cliVersion: selectedCliVersion, builderVersion: selectedBuilderVersion, ...coreOptions } = options;
|
|
21
|
+
const { createTaskProject } = await import("@silvermoon-work/task-builder/init");
|
|
22
|
+
const template = createTaskProject(coreOptions);
|
|
23
|
+
const cli = selectedCliVersion ?? (await cliVersion());
|
|
24
|
+
const builder = selectedBuilderVersion ??
|
|
25
|
+
(await packageVersion(new URL("../package.json", import.meta.resolve("@silvermoon-work/task-builder")), "@silvermoon-work/task-builder"));
|
|
26
|
+
for (const specifier of [cli, builder])
|
|
27
|
+
if (!specifier.trim() || [...specifier].some((char) => char.charCodeAt(0) < 32))
|
|
28
|
+
throw new Error("Dependency specifiers must be nonempty without control characters.");
|
|
29
|
+
const value = JSON.parse(Buffer.from(await readBytes(template, "package.json", 65_536)).toString());
|
|
30
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
31
|
+
throw new Error("Core template package.json must contain an object.");
|
|
32
|
+
const manifest = {
|
|
33
|
+
...value,
|
|
34
|
+
packageManager: "pnpm@11.22.0",
|
|
35
|
+
scripts: {
|
|
36
|
+
build: "task-builder build task.build.yaml",
|
|
37
|
+
car: "task-builder car dist bundle.car --cid-file bundle.cid",
|
|
38
|
+
check: "task-builder check bundle.car",
|
|
39
|
+
},
|
|
40
|
+
devDependencies: {
|
|
41
|
+
"@silvermoon-work/task-builder-cli": cli,
|
|
42
|
+
"@silvermoon-work/task-builder": builder,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const readers = new Map();
|
|
46
|
+
const walk = async (path) => {
|
|
47
|
+
for (const entry of await listTree(template, path)) {
|
|
48
|
+
const child = path ? `${path}/${entry.name}` : entry.name;
|
|
49
|
+
if (entry.kind === "directory")
|
|
50
|
+
await walk(child);
|
|
51
|
+
else
|
|
52
|
+
readers.set(child, (readOptions) => template.read(child, readOptions));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
await walk("");
|
|
56
|
+
const { stringify } = await import("yaml");
|
|
57
|
+
const files = new Map([
|
|
58
|
+
["package.json", `${JSON.stringify(manifest, null, 2)}\n`],
|
|
59
|
+
[
|
|
60
|
+
"pnpm-workspace.yaml",
|
|
61
|
+
stringify({
|
|
62
|
+
allowBuilds: { esbuild: true },
|
|
63
|
+
...(selectedBuilderVersion !== undefined
|
|
64
|
+
? { overrides: { "@silvermoon-work/task-builder": builder } }
|
|
65
|
+
: {}),
|
|
66
|
+
minimumReleaseAgeExclude: [
|
|
67
|
+
"@silvermoon-work/task-builder-cli",
|
|
68
|
+
"@silvermoon-work/task-builder",
|
|
69
|
+
"@potential-guide/task-sdk",
|
|
70
|
+
"@potential-guide/task-protocol@0.1.0-rc.2",
|
|
71
|
+
],
|
|
72
|
+
}),
|
|
73
|
+
],
|
|
74
|
+
]);
|
|
75
|
+
for (const [path, contents] of files) {
|
|
76
|
+
const bytes = Buffer.from(contents);
|
|
77
|
+
readers.set(path, (readOptions) => memoryFile(bytes, readOptions));
|
|
78
|
+
}
|
|
79
|
+
return fileTree(readers);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silvermoon-work/task-builder-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-canary-261109-1",
|
|
4
|
+
"description": "Commander-based Task Builder CLI and reusable command runner.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./node": {
|
|
15
|
+
"types": "./dist/node.d.ts",
|
|
16
|
+
"import": "./dist/node.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"task-builder": "./dist/bin.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22.13.0"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"registry": "https://registry.npmjs.org/"
|
|
33
|
+
},
|
|
5
34
|
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"commander": "14.0.3",
|
|
37
|
+
"yaml": "2.9.1",
|
|
38
|
+
"@silvermoon-work/task-builder": "0.1.0-canary-261109-2"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@potential-guide/task-sdk": "0.1.0-rc.2",
|
|
42
|
+
"@silvermoon-work/task-protocol": "0.1.0-canary-261109-2"
|
|
43
|
+
},
|
|
6
44
|
"repository": {
|
|
7
45
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/silvermoon-work/task-engine.git"
|
|
46
|
+
"url": "git+https://github.com/silvermoon-work/task-engine.git",
|
|
47
|
+
"directory": "packages/task-builder-cli"
|
|
9
48
|
},
|
|
10
|
-
"homepage": "https://github.com/silvermoon-work/task-engine#readme",
|
|
49
|
+
"homepage": "https://github.com/silvermoon-work/task-engine/tree/main/packages/task-builder-cli#readme",
|
|
11
50
|
"bugs": {
|
|
12
51
|
"url": "https://github.com/silvermoon-work/task-engine/issues"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc -b",
|
|
55
|
+
"clean": "node -e \"for (const path of ['dist', '.cache']) require('node:fs').rmSync(path, { recursive: true, force: true })\"",
|
|
56
|
+
"lint": "biome lint .",
|
|
57
|
+
"test": "tsx --test \"test/*.test.ts\"",
|
|
58
|
+
"typecheck": "tsc -b --pretty false"
|
|
13
59
|
}
|
|
14
60
|
}
|