@fenglimg/fabric-cli 1.1.0 → 1.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/README.md +24 -0
- package/dist/bootstrap-IUL4SAAK.js +14 -0
- package/dist/{config-PXEEXWLM.js → chunk-MDI7523D.js} +49 -17
- package/dist/{bootstrap-PMIA4W6G.js → chunk-RUQCZA2Q.js} +110 -33
- package/dist/chunk-YDZJRLHL.js +155 -0
- package/dist/config-3JBB77TX.js +15 -0
- package/dist/hooks-ZSWVH2JD.js +12 -0
- package/dist/index.js +29 -14
- package/dist/{init-R73E5YTG.js → init-3FPLOABB.js} +277 -58
- package/dist/{scan-JBGFRB7P.js → scan-WKDSKEBB.js} +2 -2
- package/package.json +5 -4
- package/dist/hooks-5S5IRVQE.js +0 -124
- package/dist/{chunk-JWUO6TIS.js → chunk-N4DCTOXW.js} +5 -5
- package/dist/{doctor-QTSG2RWF.js → doctor-5KJGOV2P.js} +3 -3
- package/dist/{pre-commit-BLSUMT3P.js → pre-commit-CJ7EDKJK.js} +6 -6
- package/dist/{serve-4J2CQY25.js → serve-MMN4GYLM.js} +4 -4
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @fenglimg/fabric-cli
|
|
2
|
+
|
|
3
|
+
`fabric` is the primary CLI binary for Fabric. `fab` is a permanent alias, so you can use either binary.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. Install dependencies from the monorepo root with `pnpm install`.
|
|
8
|
+
2. Build the CLI with `pnpm --filter @fenglimg/fabric-cli build`.
|
|
9
|
+
3. Run `fabric init` in the target project for the one-shot setup flow.
|
|
10
|
+
4. Start `fabric serve` and verify `fab_get_rules` in your client.
|
|
11
|
+
|
|
12
|
+
`fabric init` auto-runs `bootstrap install`, `config install`, and `hooks install`. Use them standalone only for targeted re-runs.
|
|
13
|
+
|
|
14
|
+
## Common Commands
|
|
15
|
+
|
|
16
|
+
- `fabric init`
|
|
17
|
+
- `fabric serve`
|
|
18
|
+
- `fabric doctor --audit`
|
|
19
|
+
|
|
20
|
+
## Advanced Commands
|
|
21
|
+
|
|
22
|
+
- `fabric bootstrap install`
|
|
23
|
+
- `fabric config install`
|
|
24
|
+
- `fabric hooks install`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
bootstrapCommand,
|
|
4
|
+
bootstrap_default,
|
|
5
|
+
installBootstrap
|
|
6
|
+
} from "./chunk-RUQCZA2Q.js";
|
|
7
|
+
import "./chunk-VMYPJPKV.js";
|
|
8
|
+
import "./chunk-AEOYCVBG.js";
|
|
9
|
+
import "./chunk-6ICJICVU.js";
|
|
10
|
+
export {
|
|
11
|
+
bootstrapCommand,
|
|
12
|
+
bootstrap_default as default,
|
|
13
|
+
installBootstrap
|
|
14
|
+
};
|
|
@@ -13,6 +13,7 @@ import { resolve } from "path";
|
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
14
|
import { defineCommand } from "citty";
|
|
15
15
|
var CLIENT_ALIASES = {
|
|
16
|
+
claude: "ClaudeCodeCLI",
|
|
16
17
|
claudecodecli: "ClaudeCodeCLI",
|
|
17
18
|
"claude-code-cli": "ClaudeCodeCLI",
|
|
18
19
|
claudecli: "ClaudeCodeCLI",
|
|
@@ -57,7 +58,8 @@ async function loadFabricConfig(workspaceRoot) {
|
|
|
57
58
|
}
|
|
58
59
|
return parsed;
|
|
59
60
|
}
|
|
60
|
-
function resolveServerPath() {
|
|
61
|
+
function resolveServerPath(override) {
|
|
62
|
+
if (override) return override;
|
|
61
63
|
if (process.env.FAB_SERVER_PATH) return resolve(process.env.FAB_SERVER_PATH);
|
|
62
64
|
return fileURLToPath(import.meta.resolve("@fenglimg/fabric-server"));
|
|
63
65
|
}
|
|
@@ -88,36 +90,66 @@ var configCmd = defineCommand({
|
|
|
88
90
|
}
|
|
89
91
|
},
|
|
90
92
|
async run({ args }) {
|
|
91
|
-
const workspaceRoot = process.cwd();
|
|
92
|
-
const fabricConfig = await loadFabricConfig(workspaceRoot);
|
|
93
93
|
const selectedClients = parseClientFilter(args.clients);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
98
|
-
if (
|
|
94
|
+
const result = await installMcpClients(process.cwd(), {
|
|
95
|
+
clients: selectedClients === null ? void 0 : Array.from(selectedClients),
|
|
96
|
+
dryRun: args["dry-run"]
|
|
97
|
+
});
|
|
98
|
+
if (result.details.length === 0) {
|
|
99
99
|
writeStderr(t("cli.config.install.no-configs"));
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
for (const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
writeStderr(t("cli.config.install.no-config-path", { client: writer.clientKind }));
|
|
102
|
+
for (const detail of result.details) {
|
|
103
|
+
if (detail.action === "skipped") {
|
|
104
|
+
writeStderr(t("cli.config.install.no-config-path", { client: detail.client }));
|
|
106
105
|
continue;
|
|
107
106
|
}
|
|
108
|
-
if (
|
|
109
|
-
writeStderr(t("cli.config.install.dry-run", { client:
|
|
107
|
+
if (detail.action === "dry-run" && detail.path !== null) {
|
|
108
|
+
writeStderr(t("cli.config.install.dry-run", { client: detail.client, path: detail.path }));
|
|
110
109
|
continue;
|
|
111
110
|
}
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
if (detail.path !== null) {
|
|
112
|
+
writeStderr(t("cli.config.install.wrote", { client: detail.client, path: detail.path }));
|
|
113
|
+
}
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
})
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
119
|
var config_default = configCmd;
|
|
120
|
+
async function installMcpClients(target, options = {}) {
|
|
121
|
+
const workspaceRoot = resolve(target);
|
|
122
|
+
const fabricConfig = await loadFabricConfig(workspaceRoot);
|
|
123
|
+
const selectedClients = options.clients === void 0 ? null : new Set(options.clients);
|
|
124
|
+
const serverPath = resolveServerPath(options.localServerPath);
|
|
125
|
+
const writers = resolveClients(workspaceRoot, fabricConfig).filter(
|
|
126
|
+
(writer) => selectedClients === null ? true : selectedClients.has(writer.clientKind)
|
|
127
|
+
);
|
|
128
|
+
const installed = [];
|
|
129
|
+
const skipped = [];
|
|
130
|
+
const details = [];
|
|
131
|
+
for (const writer of writers) {
|
|
132
|
+
const configPath = await writer.detect(workspaceRoot);
|
|
133
|
+
if (configPath === null) {
|
|
134
|
+
skipped.push(writer.clientKind);
|
|
135
|
+
details.push({ client: writer.clientKind, path: null, action: "skipped" });
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (options.dryRun) {
|
|
139
|
+
skipped.push(writer.clientKind);
|
|
140
|
+
details.push({ client: writer.clientKind, path: configPath, action: "dry-run" });
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
await writer.write(serverPath, workspaceRoot);
|
|
144
|
+
installed.push(writer.clientKind);
|
|
145
|
+
details.push({ client: writer.clientKind, path: configPath, action: "wrote" });
|
|
146
|
+
}
|
|
147
|
+
return { installed, skipped, details };
|
|
148
|
+
}
|
|
149
|
+
|
|
120
150
|
export {
|
|
151
|
+
parseClientFilter,
|
|
121
152
|
configCmd,
|
|
122
|
-
config_default
|
|
153
|
+
config_default,
|
|
154
|
+
installMcpClients
|
|
123
155
|
};
|
|
@@ -70,24 +70,53 @@ var bootstrapCommand = defineCommand({
|
|
|
70
70
|
async run({ args }) {
|
|
71
71
|
const workspaceRoot = process.cwd();
|
|
72
72
|
const selectedClients = parseClientFilter(args.clients);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (
|
|
73
|
+
const result = await installBootstrap(workspaceRoot, {
|
|
74
|
+
clients: selectedClients === null ? void 0 : Array.from(selectedClients, mapBootstrapClientToClientKind)
|
|
75
|
+
});
|
|
76
|
+
if (result.details.length === 0) {
|
|
77
77
|
process.stderr.write(
|
|
78
78
|
`${t("cli.bootstrap.install.no-targets")}
|
|
79
79
|
`
|
|
80
80
|
);
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
|
-
for (const
|
|
84
|
-
|
|
83
|
+
for (const detail of result.details) {
|
|
84
|
+
if (detail.action === "skipped") {
|
|
85
|
+
process.stderr.write(`${t("cli.bootstrap.install.skipped-header", { path: detail.path })}
|
|
86
|
+
`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (detail.action === "prepended") {
|
|
90
|
+
process.stderr.write(`${t("cli.bootstrap.install.prepended", { path: detail.path })}
|
|
91
|
+
`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
process.stderr.write(`${t("cli.bootstrap.install.installed", { path: detail.path })}
|
|
95
|
+
`);
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
98
|
})
|
|
88
99
|
}
|
|
89
100
|
});
|
|
90
101
|
var bootstrap_default = bootstrapCommand;
|
|
102
|
+
async function installBootstrap(target, options = {}) {
|
|
103
|
+
const workspaceRoot = resolve(target);
|
|
104
|
+
const fabricConfig = readFabricConfig(workspaceRoot);
|
|
105
|
+
const targets = resolveBootstrapTargets(workspaceRoot, fabricConfig, options.clients);
|
|
106
|
+
const installed = [];
|
|
107
|
+
const skipped = [];
|
|
108
|
+
const details = [];
|
|
109
|
+
for (const bootstrapTarget of targets) {
|
|
110
|
+
const detail = installBootstrapTarget(bootstrapTarget, workspaceRoot, options);
|
|
111
|
+
details.push(detail);
|
|
112
|
+
if (detail.action === "skipped") {
|
|
113
|
+
skipped.push(bootstrapTarget.client);
|
|
114
|
+
} else {
|
|
115
|
+
installed.push(bootstrapTarget.client);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { installed, skipped, details };
|
|
119
|
+
}
|
|
91
120
|
function parseClientFilter(value) {
|
|
92
121
|
if (value === void 0 || value.trim().length === 0) {
|
|
93
122
|
return null;
|
|
@@ -103,15 +132,19 @@ function parseClientFilter(value) {
|
|
|
103
132
|
}
|
|
104
133
|
return clients;
|
|
105
134
|
}
|
|
106
|
-
function
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
function resolveBootstrapTargets(workspaceRoot, fabricConfig, selectedClients) {
|
|
136
|
+
const targets = [];
|
|
137
|
+
const seenClients = /* @__PURE__ */ new Set();
|
|
138
|
+
const clientKinds = selectedClients ?? resolveClients(workspaceRoot, fabricConfig).map((writer) => writer.clientKind);
|
|
139
|
+
for (const clientKind of clientKinds) {
|
|
140
|
+
const bootstrapClient = mapClientKind(clientKind);
|
|
141
|
+
if (bootstrapClient === null || seenClients.has(bootstrapClient)) {
|
|
142
|
+
continue;
|
|
112
143
|
}
|
|
144
|
+
seenClients.add(bootstrapClient);
|
|
145
|
+
targets.push({ client: clientKind, bootstrapClient });
|
|
113
146
|
}
|
|
114
|
-
return
|
|
147
|
+
return targets;
|
|
115
148
|
}
|
|
116
149
|
function mapClientKind(clientKind) {
|
|
117
150
|
switch (clientKind) {
|
|
@@ -132,37 +165,79 @@ function mapClientKind(clientKind) {
|
|
|
132
165
|
return null;
|
|
133
166
|
}
|
|
134
167
|
}
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
168
|
+
function mapBootstrapClientToClientKind(client) {
|
|
169
|
+
switch (client) {
|
|
170
|
+
case "claude":
|
|
171
|
+
return "ClaudeCodeCLI";
|
|
172
|
+
case "cursor":
|
|
173
|
+
return "Cursor";
|
|
174
|
+
case "windsurf":
|
|
175
|
+
return "Windsurf";
|
|
176
|
+
case "roo":
|
|
177
|
+
return "RooCode";
|
|
178
|
+
case "gemini":
|
|
179
|
+
return "GeminiCLI";
|
|
180
|
+
case "codex":
|
|
181
|
+
return "CodexCLI";
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function installBootstrapTarget(target, workspaceRoot, options) {
|
|
185
|
+
const targetPath = resolve(workspaceRoot, CLIENT_TARGET_MAP[target.bootstrapClient]);
|
|
186
|
+
const templatePath = findTemplatePath(CLIENT_TEMPLATE_MAP[target.bootstrapClient]);
|
|
138
187
|
const template = readFileSync(templatePath, "utf8");
|
|
139
188
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
|
|
189
|
+
if (target.bootstrapClient === "codex") {
|
|
190
|
+
return {
|
|
191
|
+
client: target.client,
|
|
192
|
+
path: targetPath,
|
|
193
|
+
action: writeCodexBootstrap(targetPath, template, options.force)
|
|
194
|
+
};
|
|
143
195
|
}
|
|
196
|
+
const existed = existsSync(targetPath);
|
|
144
197
|
writeFileSync(targetPath, ensureTrailingNewline(template), "utf8");
|
|
145
|
-
|
|
146
|
-
|
|
198
|
+
return {
|
|
199
|
+
client: target.client,
|
|
200
|
+
path: targetPath,
|
|
201
|
+
action: existed ? "overwritten" : "installed"
|
|
202
|
+
};
|
|
147
203
|
}
|
|
148
|
-
function writeCodexBootstrap(targetPath, template) {
|
|
204
|
+
function writeCodexBootstrap(targetPath, template, force) {
|
|
149
205
|
const nextContent = ensureTrailingNewline(template);
|
|
150
206
|
if (!existsSync(targetPath)) {
|
|
151
207
|
writeFileSync(targetPath, nextContent, "utf8");
|
|
152
|
-
|
|
153
|
-
`);
|
|
154
|
-
return;
|
|
208
|
+
return "installed";
|
|
155
209
|
}
|
|
156
210
|
const existing = readFileSync(targetPath, "utf8");
|
|
157
211
|
if (existing.includes("# Fabric Bootstrap")) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
212
|
+
if (!force) {
|
|
213
|
+
return "skipped";
|
|
214
|
+
}
|
|
215
|
+
const remainder = stripExistingCodexBootstrap(existing, nextContent);
|
|
216
|
+
writeFileSync(targetPath, joinBootstrapSections(nextContent, remainder), "utf8");
|
|
217
|
+
return "overwritten";
|
|
161
218
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
219
|
+
writeFileSync(targetPath, joinBootstrapSections(nextContent, existing), "utf8");
|
|
220
|
+
return force ? "overwritten" : "prepended";
|
|
221
|
+
}
|
|
222
|
+
function stripExistingCodexBootstrap(existing, template) {
|
|
223
|
+
if (existing.startsWith(template)) {
|
|
224
|
+
return existing.slice(template.length).replace(/^\n+/, "");
|
|
225
|
+
}
|
|
226
|
+
if (!existing.startsWith("# Fabric Bootstrap")) {
|
|
227
|
+
return existing;
|
|
228
|
+
}
|
|
229
|
+
const nextTopLevelHeadingIndex = existing.indexOf("\n# ", "# Fabric Bootstrap".length);
|
|
230
|
+
if (nextTopLevelHeadingIndex === -1) {
|
|
231
|
+
return "";
|
|
232
|
+
}
|
|
233
|
+
return existing.slice(nextTopLevelHeadingIndex + 1).replace(/^\n+/, "");
|
|
234
|
+
}
|
|
235
|
+
function joinBootstrapSections(header, body) {
|
|
236
|
+
if (body.trim().length === 0) {
|
|
237
|
+
return header;
|
|
238
|
+
}
|
|
239
|
+
const separator = body.startsWith("\n") ? "" : "\n";
|
|
240
|
+
return `${header}${separator}${body}`;
|
|
166
241
|
}
|
|
167
242
|
function ensureTrailingNewline(content) {
|
|
168
243
|
return content.endsWith("\n") ? content : `${content}
|
|
@@ -194,7 +269,9 @@ function templateCandidatesFrom(start, relativePath) {
|
|
|
194
269
|
}
|
|
195
270
|
return candidates.reverse();
|
|
196
271
|
}
|
|
272
|
+
|
|
197
273
|
export {
|
|
198
274
|
bootstrapCommand,
|
|
199
|
-
bootstrap_default
|
|
275
|
+
bootstrap_default,
|
|
276
|
+
installBootstrap
|
|
200
277
|
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-6ICJICVU.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/hooks.ts
|
|
7
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
8
|
+
import { dirname, isAbsolute, join, parse, resolve } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
var hooksCommand = defineCommand({
|
|
12
|
+
meta: {
|
|
13
|
+
name: "hooks",
|
|
14
|
+
description: t("cli.hooks.description")
|
|
15
|
+
},
|
|
16
|
+
subCommands: {
|
|
17
|
+
install: defineCommand({
|
|
18
|
+
meta: {
|
|
19
|
+
name: "install",
|
|
20
|
+
description: t("cli.hooks.install.description")
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
target: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: t("cli.hooks.install.args.target.description"),
|
|
26
|
+
default: process.cwd()
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
async run({ args }) {
|
|
30
|
+
const result = await installHooks(args.target);
|
|
31
|
+
if (result.hookAction === "skipped") {
|
|
32
|
+
writeStderr(t("cli.hooks.install.hook-skipped", { path: result.hookPath }));
|
|
33
|
+
} else if (result.hookAction === "appended") {
|
|
34
|
+
writeStderr(t("cli.hooks.install.hook-appended", { path: result.hookPath }));
|
|
35
|
+
} else {
|
|
36
|
+
writeStderr(t("cli.hooks.install.hook-created", { path: result.hookPath }));
|
|
37
|
+
}
|
|
38
|
+
if (result.prepareAction === "left") {
|
|
39
|
+
writeStderr(t("cli.hooks.install.prepare-left", { path: result.packageJsonPath }));
|
|
40
|
+
} else {
|
|
41
|
+
writeStderr(t("cli.hooks.install.prepare-added", { path: result.packageJsonPath }));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
var hooks_default = hooksCommand;
|
|
48
|
+
async function installHooks(target, options = {}) {
|
|
49
|
+
const normalizedTarget = normalizeTarget(target);
|
|
50
|
+
assertExistingDirectory(normalizedTarget);
|
|
51
|
+
const huskyDir = join(normalizedTarget, ".husky");
|
|
52
|
+
const hookPath = join(huskyDir, "pre-commit");
|
|
53
|
+
const packageJsonPath = join(normalizedTarget, "package.json");
|
|
54
|
+
if (!existsSync(packageJsonPath)) {
|
|
55
|
+
throw new Error(t("cli.hooks.errors.package-json-required", { path: packageJsonPath }));
|
|
56
|
+
}
|
|
57
|
+
mkdirSync(huskyDir, { recursive: true });
|
|
58
|
+
const templateContent = readFileSync(findTemplatePath("templates/husky/pre-commit"), "utf8");
|
|
59
|
+
const hookAction = installHookFile(hookPath, templateContent, options.force);
|
|
60
|
+
chmodSync(hookPath, 493);
|
|
61
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
62
|
+
const scripts = packageJson.scripts && typeof packageJson.scripts === "object" && !Array.isArray(packageJson.scripts) ? packageJson.scripts : {};
|
|
63
|
+
const hadPrepare = typeof scripts.prepare === "string" && scripts.prepare.trim().length > 0;
|
|
64
|
+
let prepareAction = "left";
|
|
65
|
+
if (!hadPrepare) {
|
|
66
|
+
scripts.prepare = "husky install";
|
|
67
|
+
packageJson.scripts = scripts;
|
|
68
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
69
|
+
`, "utf8");
|
|
70
|
+
prepareAction = "added";
|
|
71
|
+
}
|
|
72
|
+
const installed = [];
|
|
73
|
+
const skipped = [];
|
|
74
|
+
if (hookAction === "skipped") {
|
|
75
|
+
skipped.push(hookPath);
|
|
76
|
+
} else {
|
|
77
|
+
installed.push(hookPath);
|
|
78
|
+
}
|
|
79
|
+
if (prepareAction === "left") {
|
|
80
|
+
skipped.push(packageJsonPath);
|
|
81
|
+
} else {
|
|
82
|
+
installed.push(packageJsonPath);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
installed,
|
|
86
|
+
skipped,
|
|
87
|
+
hookPath,
|
|
88
|
+
packageJsonPath,
|
|
89
|
+
hookAction,
|
|
90
|
+
prepareAction
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function normalizeTarget(targetInput) {
|
|
94
|
+
return isAbsolute(targetInput) ? targetInput : resolve(process.cwd(), targetInput);
|
|
95
|
+
}
|
|
96
|
+
function assertExistingDirectory(target) {
|
|
97
|
+
if (!existsSync(target) || !statSync(target).isDirectory()) {
|
|
98
|
+
throw new Error(t("cli.shared.target-invalid", { target }));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function installHookFile(hookPath, templateContent, force) {
|
|
102
|
+
if (existsSync(hookPath)) {
|
|
103
|
+
if (force) {
|
|
104
|
+
writeFileSync(hookPath, templateContent, "utf8");
|
|
105
|
+
return "overwritten";
|
|
106
|
+
}
|
|
107
|
+
const existing = readFileSync(hookPath, "utf8");
|
|
108
|
+
if (existing.includes("FAB_BIN=")) {
|
|
109
|
+
return "skipped";
|
|
110
|
+
}
|
|
111
|
+
const fabricBlock = templateContent.replace(/^#!\/bin\/sh\n/, "");
|
|
112
|
+
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
113
|
+
writeFileSync(hookPath, `${existing}${separator}# --- Fabric ---
|
|
114
|
+
${fabricBlock}`, "utf8");
|
|
115
|
+
return "appended";
|
|
116
|
+
}
|
|
117
|
+
writeFileSync(hookPath, templateContent, "utf8");
|
|
118
|
+
return "created";
|
|
119
|
+
}
|
|
120
|
+
function findTemplatePath(relativePath) {
|
|
121
|
+
const currentModuleDir = dirname(fileURLToPath(import.meta.url));
|
|
122
|
+
const candidates = [
|
|
123
|
+
...templateCandidatesFrom(process.cwd(), relativePath),
|
|
124
|
+
...templateCandidatesFrom(currentModuleDir, relativePath)
|
|
125
|
+
];
|
|
126
|
+
for (const candidate of candidates) {
|
|
127
|
+
if (existsSync(candidate)) {
|
|
128
|
+
return candidate;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
throw new Error(t("cli.shared.template-not-found", { path: relativePath }));
|
|
132
|
+
}
|
|
133
|
+
function templateCandidatesFrom(start, relativePath) {
|
|
134
|
+
const candidates = [];
|
|
135
|
+
let current = resolve(start);
|
|
136
|
+
while (true) {
|
|
137
|
+
candidates.push(join(current, ...relativePath.split("/")));
|
|
138
|
+
const parent = dirname(current);
|
|
139
|
+
if (parent === current || parse(current).root === current) {
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
current = parent;
|
|
143
|
+
}
|
|
144
|
+
return candidates.reverse();
|
|
145
|
+
}
|
|
146
|
+
function writeStderr(message) {
|
|
147
|
+
process.stderr.write(`${message}
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
hooksCommand,
|
|
153
|
+
hooks_default,
|
|
154
|
+
installHooks
|
|
155
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
configCmd,
|
|
4
|
+
config_default,
|
|
5
|
+
installMcpClients,
|
|
6
|
+
parseClientFilter
|
|
7
|
+
} from "./chunk-MDI7523D.js";
|
|
8
|
+
import "./chunk-VMYPJPKV.js";
|
|
9
|
+
import "./chunk-6ICJICVU.js";
|
|
10
|
+
export {
|
|
11
|
+
configCmd,
|
|
12
|
+
config_default as default,
|
|
13
|
+
installMcpClients,
|
|
14
|
+
parseClientFilter
|
|
15
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
t
|
|
4
|
-
} from "./chunk-6ICJICVU.js";
|
|
5
2
|
|
|
6
3
|
// src/index.ts
|
|
7
4
|
import { realpathSync } from "fs";
|
|
@@ -11,25 +8,43 @@ import { defineCommand, runMain } from "citty";
|
|
|
11
8
|
|
|
12
9
|
// src/commands/index.ts
|
|
13
10
|
var allCommands = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
serve: () => import("./serve-4J2CQY25.js").then((module) => module.default),
|
|
11
|
+
init: () => import("./init-3FPLOABB.js").then((module) => module.default),
|
|
12
|
+
scan: () => import("./scan-WKDSKEBB.js").then((module) => module.default),
|
|
13
|
+
serve: () => import("./serve-MMN4GYLM.js").then((module) => module.default),
|
|
14
|
+
doctor: () => import("./doctor-5KJGOV2P.js").then((module) => module.default),
|
|
19
15
|
"sync-meta": () => import("./sync-meta-THZSEM7Y.js").then((module) => module.default),
|
|
20
16
|
"human-lint": () => import("./human-lint-YSFOZHZ7.js").then((module) => module.default),
|
|
21
17
|
"ledger-append": () => import("./ledger-append-XZ5SX4O5.js").then((module) => module.default),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
"pre-commit": () => import("./pre-commit-CJ7EDKJK.js").then((module) => module.default),
|
|
19
|
+
bootstrap: () => import("./bootstrap-IUL4SAAK.js").then((module) => ({
|
|
20
|
+
...module.default,
|
|
21
|
+
meta: {
|
|
22
|
+
...module.default.meta,
|
|
23
|
+
hidden: true
|
|
24
|
+
}
|
|
25
|
+
})),
|
|
26
|
+
config: () => import("./config-3JBB77TX.js").then((module) => ({
|
|
27
|
+
...module.configCmd,
|
|
28
|
+
meta: {
|
|
29
|
+
...module.configCmd.meta,
|
|
30
|
+
hidden: true
|
|
31
|
+
}
|
|
32
|
+
})),
|
|
33
|
+
hooks: () => import("./hooks-ZSWVH2JD.js").then((module) => ({
|
|
34
|
+
...module.default,
|
|
35
|
+
meta: {
|
|
36
|
+
...module.default.meta,
|
|
37
|
+
hidden: true
|
|
38
|
+
}
|
|
39
|
+
}))
|
|
25
40
|
};
|
|
26
41
|
|
|
27
42
|
// src/index.ts
|
|
28
43
|
var main = defineCommand({
|
|
29
44
|
meta: {
|
|
30
|
-
name: "
|
|
31
|
-
version: "1.
|
|
32
|
-
description:
|
|
45
|
+
name: "fabric",
|
|
46
|
+
version: "1.2.0",
|
|
47
|
+
description: 'Initialize and manage Fabric projects. Use "fabric init" for one-shot setup.'
|
|
33
48
|
},
|
|
34
49
|
subCommands: allCommands
|
|
35
50
|
});
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
installBootstrap
|
|
4
|
+
} from "./chunk-RUQCZA2Q.js";
|
|
5
|
+
import {
|
|
6
|
+
installMcpClients
|
|
7
|
+
} from "./chunk-MDI7523D.js";
|
|
8
|
+
import "./chunk-VMYPJPKV.js";
|
|
9
|
+
import {
|
|
10
|
+
installHooks
|
|
11
|
+
} from "./chunk-YDZJRLHL.js";
|
|
2
12
|
import {
|
|
3
13
|
createScanReport,
|
|
4
14
|
detectFramework
|
|
5
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-N4DCTOXW.js";
|
|
16
|
+
import {
|
|
17
|
+
paint
|
|
18
|
+
} from "./chunk-WWNXR34K.js";
|
|
6
19
|
import {
|
|
7
20
|
createDebugLogger,
|
|
8
21
|
resolveDevMode
|
|
9
22
|
} from "./chunk-AEOYCVBG.js";
|
|
10
|
-
import {
|
|
11
|
-
paint
|
|
12
|
-
} from "./chunk-WWNXR34K.js";
|
|
13
23
|
import {
|
|
14
24
|
t
|
|
15
25
|
} from "./chunk-6ICJICVU.js";
|
|
16
26
|
|
|
17
27
|
// src/commands/init.ts
|
|
18
28
|
import { createHash } from "crypto";
|
|
19
|
-
import
|
|
29
|
+
import * as childProcess from "child_process";
|
|
30
|
+
import { chmodSync, copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, renameSync, rmSync, statSync as statSync2, writeFileSync } from "fs";
|
|
20
31
|
import { dirname, isAbsolute as isAbsolute2, join as join2, parse, resolve as resolve2 } from "path";
|
|
21
32
|
import { fileURLToPath } from "url";
|
|
22
33
|
import { defineCommand } from "citty";
|
|
@@ -841,7 +852,7 @@ function readProjectName(target) {
|
|
|
841
852
|
return basename(target);
|
|
842
853
|
}
|
|
843
854
|
function getCliVersion() {
|
|
844
|
-
return true ? "1.
|
|
855
|
+
return true ? "1.2.0" : "unknown";
|
|
845
856
|
}
|
|
846
857
|
function sortRecord(record) {
|
|
847
858
|
return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -859,6 +870,8 @@ var AGENTS_TEMPLATE_BY_FRAMEWORK = {
|
|
|
859
870
|
var CLAUDE_INIT_SKILL_TEMPLATE = "templates/claude-skills/agents-md-init/SKILL.md";
|
|
860
871
|
var CLAUDE_INIT_REMINDER_HOOK_TEMPLATE = "templates/claude-hooks/agents-md-init-reminder.cjs";
|
|
861
872
|
var CLAUDE_INIT_REMINDER_COMMAND = ".claude/hooks/agents-md-init-reminder.cjs";
|
|
873
|
+
var LOCAL_FABRIC_SERVER_PATH = join2("node_modules", "@fenglimg", "fabric-server", "dist", "index.js");
|
|
874
|
+
var FABRIC_SERVER_PACKAGE = "@fenglimg/fabric-server";
|
|
862
875
|
var initCommand = defineCommand({
|
|
863
876
|
meta: {
|
|
864
877
|
name: "init",
|
|
@@ -873,44 +886,148 @@ var initCommand = defineCommand({
|
|
|
873
886
|
type: "boolean",
|
|
874
887
|
description: t("cli.init.args.debug.description"),
|
|
875
888
|
default: false
|
|
889
|
+
},
|
|
890
|
+
force: {
|
|
891
|
+
type: "boolean",
|
|
892
|
+
description: t("cli.init.args.force.description"),
|
|
893
|
+
default: false
|
|
894
|
+
},
|
|
895
|
+
bootstrap: {
|
|
896
|
+
type: "boolean",
|
|
897
|
+
default: true,
|
|
898
|
+
negativeDescription: t("cli.init.args.no-bootstrap.description")
|
|
899
|
+
},
|
|
900
|
+
mcp: {
|
|
901
|
+
type: "boolean",
|
|
902
|
+
default: true,
|
|
903
|
+
negativeDescription: t("cli.init.args.no-mcp.description")
|
|
904
|
+
},
|
|
905
|
+
hooks: {
|
|
906
|
+
type: "boolean",
|
|
907
|
+
default: true,
|
|
908
|
+
negativeDescription: t("cli.init.args.no-hooks.description")
|
|
909
|
+
},
|
|
910
|
+
"mcp-install": {
|
|
911
|
+
type: "string",
|
|
912
|
+
default: "global",
|
|
913
|
+
description: t("cli.init.mcp.install.prompt")
|
|
876
914
|
}
|
|
877
915
|
},
|
|
878
916
|
async run({ args }) {
|
|
879
917
|
const logger = createDebugLogger(args.debug);
|
|
880
918
|
const resolution = resolveDevMode(args.target, process.cwd());
|
|
881
919
|
const target = normalizeTarget2(resolution.target);
|
|
920
|
+
const mcpInstallMode = resolveMcpInstallMode(args["mcp-install"]);
|
|
921
|
+
const options = {
|
|
922
|
+
force: args.force,
|
|
923
|
+
skipBootstrap: args.bootstrap === false ? true : args.skipBootstrap,
|
|
924
|
+
skipMcp: args.mcp === false ? true : args.skipMcp,
|
|
925
|
+
skipHooks: args.hooks === false ? true : args.skipHooks
|
|
926
|
+
};
|
|
882
927
|
logger(`init target source: ${resolution.source}`);
|
|
883
928
|
for (const step of resolution.chain) {
|
|
884
929
|
logger(step);
|
|
885
930
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
console.log(
|
|
931
|
+
if (options.force) {
|
|
932
|
+
writeStderr(t("cli.init.force.warning", { path: target }));
|
|
933
|
+
}
|
|
934
|
+
const created = initFabric(target, options);
|
|
935
|
+
console.log(formatInitPathAction(created.agentsPath, created.agentsAction));
|
|
936
|
+
console.log(formatInitPathAction(created.metaPath, created.metaAction));
|
|
937
|
+
console.log(formatInitPathAction(created.humanLockPath, created.humanLockAction));
|
|
938
|
+
console.log(formatInitPathAction(created.forensicPath, created.forensicAction));
|
|
891
939
|
writeStderr(
|
|
892
|
-
|
|
940
|
+
formatOptionalInitPathAction(created.claudeSkillPath, created.claudeSkillAction)
|
|
893
941
|
);
|
|
894
942
|
writeStderr(
|
|
895
|
-
|
|
943
|
+
formatOptionalInitPathAction(created.claudeHookPath, created.claudeHookAction)
|
|
896
944
|
);
|
|
897
945
|
writeStderr(formatClaudeSettingsAction(created.claudeSettingsPath, created.claudeSettingsAction));
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
946
|
+
const stageResults = [];
|
|
947
|
+
if (options.skipBootstrap) {
|
|
948
|
+
stageResults.push({ name: "bootstrap", disposition: "skipped" });
|
|
949
|
+
} else {
|
|
950
|
+
console.log(formatInitStageHeader(t("cli.init.stages.bootstrap")));
|
|
951
|
+
try {
|
|
952
|
+
const result = await installBootstrap(target, { force: options.force });
|
|
953
|
+
if (result.details.length === 0) {
|
|
954
|
+
console.log(formatInitStageResult("bootstrap", "skipped", 0, 0, t("cli.bootstrap.install.no-targets")));
|
|
955
|
+
stageResults.push({ name: "bootstrap", disposition: "skipped" });
|
|
956
|
+
} else {
|
|
957
|
+
console.log(
|
|
958
|
+
formatInitStageResult("bootstrap", "completed", result.installed.length, result.skipped.length)
|
|
959
|
+
);
|
|
960
|
+
stageResults.push({ name: "bootstrap", disposition: "ran" });
|
|
961
|
+
}
|
|
962
|
+
} catch (error) {
|
|
963
|
+
writeStderr(formatInitStageFailure("bootstrap", error));
|
|
964
|
+
stageResults.push({ name: "bootstrap", disposition: "failed" });
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (options.skipMcp) {
|
|
968
|
+
stageResults.push({ name: "mcp", disposition: "skipped" });
|
|
969
|
+
} else {
|
|
970
|
+
console.log(formatInitStageHeader(t("cli.init.stages.mcp")));
|
|
971
|
+
try {
|
|
972
|
+
let localServerPath;
|
|
973
|
+
if (mcpInstallMode === "local") {
|
|
974
|
+
const manager = detectPackageManager(target);
|
|
975
|
+
writeStderr(t("cli.init.mcp.install.local"));
|
|
976
|
+
writeStderr(t("cli.init.mcp.local.installing", { manager }));
|
|
977
|
+
installLocalFabricServer(target, manager);
|
|
978
|
+
writeStderr(t("cli.init.mcp.local.installed"));
|
|
979
|
+
localServerPath = LOCAL_FABRIC_SERVER_PATH;
|
|
980
|
+
} else {
|
|
981
|
+
writeStderr(t("cli.init.mcp.install.global"));
|
|
982
|
+
}
|
|
983
|
+
const result = await installMcpClients(target, {
|
|
984
|
+
force: options.force,
|
|
985
|
+
localServerPath
|
|
986
|
+
});
|
|
987
|
+
if (result.details.length === 0) {
|
|
988
|
+
console.log(formatInitStageResult("mcp", "skipped", 0, 0, t("cli.config.install.no-configs")));
|
|
989
|
+
stageResults.push({ name: "mcp", disposition: "skipped" });
|
|
990
|
+
} else {
|
|
991
|
+
console.log(formatInitStageResult("mcp", "completed", result.installed.length, result.skipped.length));
|
|
992
|
+
stageResults.push({ name: "mcp", disposition: "ran" });
|
|
993
|
+
}
|
|
994
|
+
} catch (error) {
|
|
995
|
+
writeStderr(formatInitStageFailure("mcp", error));
|
|
996
|
+
stageResults.push({ name: "mcp", disposition: "failed" });
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (options.skipHooks) {
|
|
1000
|
+
stageResults.push({ name: "hooks", disposition: "skipped" });
|
|
1001
|
+
} else {
|
|
1002
|
+
console.log(formatInitStageHeader(t("cli.init.stages.hooks")));
|
|
1003
|
+
try {
|
|
1004
|
+
const result = await installHooks(target, { force: options.force });
|
|
1005
|
+
console.log(formatInitStageResult("hooks", "completed", result.installed.length, result.skipped.length));
|
|
1006
|
+
stageResults.push({ name: "hooks", disposition: "ran" });
|
|
1007
|
+
} catch (error) {
|
|
1008
|
+
writeStderr(formatInitStageFailure("hooks", error));
|
|
1009
|
+
stageResults.push({ name: "hooks", disposition: "failed" });
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
if (shouldPrintHooksNextStep(options, stageResults)) {
|
|
1013
|
+
console.log(
|
|
1014
|
+
t("cli.init.next-step", {
|
|
1015
|
+
label: nextLabel(),
|
|
1016
|
+
message: paint.muted(t("cli.init.next-step.message"))
|
|
1017
|
+
})
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
904
1020
|
console.log(
|
|
905
1021
|
t("cli.init.reason-message", {
|
|
906
1022
|
label: reasonLabel(),
|
|
907
1023
|
message: paint.muted(t("cli.init.reason-message.body"))
|
|
908
1024
|
})
|
|
909
1025
|
);
|
|
1026
|
+
printInitStageSummary(stageResults);
|
|
910
1027
|
}
|
|
911
1028
|
});
|
|
912
1029
|
var init_default = initCommand;
|
|
913
|
-
function initFabric(target) {
|
|
1030
|
+
function initFabric(target, options) {
|
|
914
1031
|
assertExistingDirectory2(target);
|
|
915
1032
|
const agentsPath = join2(target, "AGENTS.md");
|
|
916
1033
|
const fabricDir = join2(target, ".fabric");
|
|
@@ -918,15 +1035,10 @@ function initFabric(target) {
|
|
|
918
1035
|
const claudeSkillPath = join2(target, ".claude", "skills", "agents-md-init", "SKILL.md");
|
|
919
1036
|
const claudeHookPath = join2(target, ".claude", "hooks", "agents-md-init-reminder.cjs");
|
|
920
1037
|
const claudeSettingsPath = join2(target, ".claude", "settings.json");
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
throw new Error(`ABORT: ${agentsPath} already exists. fab init is non-destructive.`);
|
|
926
|
-
}
|
|
927
|
-
if (existsSync2(fabricDir)) {
|
|
928
|
-
throw new Error(`ABORT: ${fabricDir} already exists. fab init is non-destructive.`);
|
|
929
|
-
}
|
|
1038
|
+
const forensicGuardAction = prepareFreshPath(forensicPath, options);
|
|
1039
|
+
const agentsAction = prepareFreshPath(agentsPath, options);
|
|
1040
|
+
const fabricDirAction = prepareFreshPath(fabricDir, options);
|
|
1041
|
+
const forensicAction = forensicGuardAction === "overwritten" || fabricDirAction === "overwritten" ? "overwritten" : "created";
|
|
930
1042
|
const scanReport = createScanReport(target);
|
|
931
1043
|
const forensicReport = buildForensicReport(target);
|
|
932
1044
|
const template = readFileSync2(findAgentsTemplatePath(scanReport.framework.kind), "utf8");
|
|
@@ -938,24 +1050,29 @@ function initFabric(target) {
|
|
|
938
1050
|
const metaPath = join2(fabricDir, "agents.meta.json");
|
|
939
1051
|
const humanLockPath = join2(fabricDir, "human-lock.json");
|
|
940
1052
|
mkdirSync(fabricDir, { recursive: false });
|
|
941
|
-
writeNewFile(agentsPath, agentsContent);
|
|
1053
|
+
writeNewFile(agentsPath, agentsContent, options);
|
|
942
1054
|
writeNewFile(metaPath, `${JSON.stringify(meta, null, 2)}
|
|
943
|
-
|
|
1055
|
+
`, options);
|
|
944
1056
|
writeNewFile(humanLockPath, humanLockTemplate.endsWith("\n") ? humanLockTemplate : `${humanLockTemplate}
|
|
945
|
-
|
|
1057
|
+
`, options);
|
|
946
1058
|
writeNewFile(forensicPath, `${JSON.stringify(forensicReport, null, 2)}
|
|
947
|
-
|
|
948
|
-
const claudeSkillAction = copyTemplateIfMissing(findTemplatePath(CLAUDE_INIT_SKILL_TEMPLATE), claudeSkillPath);
|
|
1059
|
+
`, options);
|
|
1060
|
+
const claudeSkillAction = copyTemplateIfMissing(findTemplatePath(CLAUDE_INIT_SKILL_TEMPLATE), claudeSkillPath, options);
|
|
949
1061
|
const claudeHookAction = copyExecutableTemplateIfMissing(
|
|
950
1062
|
findTemplatePath(CLAUDE_INIT_REMINDER_HOOK_TEMPLATE),
|
|
951
|
-
claudeHookPath
|
|
1063
|
+
claudeHookPath,
|
|
1064
|
+
options
|
|
952
1065
|
);
|
|
953
|
-
const claudeSettingsAction = mergeClaudeStopHook(claudeSettingsPath);
|
|
1066
|
+
const claudeSettingsAction = mergeClaudeStopHook(claudeSettingsPath, options);
|
|
954
1067
|
return {
|
|
955
1068
|
agentsPath,
|
|
1069
|
+
agentsAction,
|
|
956
1070
|
metaPath,
|
|
1071
|
+
metaAction: fabricDirAction,
|
|
957
1072
|
humanLockPath,
|
|
1073
|
+
humanLockAction: fabricDirAction,
|
|
958
1074
|
forensicPath,
|
|
1075
|
+
forensicAction,
|
|
959
1076
|
claudeSkillPath,
|
|
960
1077
|
claudeSkillAction,
|
|
961
1078
|
claudeHookPath,
|
|
@@ -976,6 +1093,34 @@ function assertExistingDirectory2(target) {
|
|
|
976
1093
|
throw new Error(`Target must be an existing directory: ${target}`);
|
|
977
1094
|
}
|
|
978
1095
|
}
|
|
1096
|
+
function detectPackageManager(cwd) {
|
|
1097
|
+
const workspaceRoot = resolve2(cwd);
|
|
1098
|
+
if (existsSync2(join2(workspaceRoot, "pnpm-lock.yaml"))) {
|
|
1099
|
+
return "pnpm";
|
|
1100
|
+
}
|
|
1101
|
+
if (existsSync2(join2(workspaceRoot, "yarn.lock"))) {
|
|
1102
|
+
return "yarn";
|
|
1103
|
+
}
|
|
1104
|
+
if (existsSync2(join2(workspaceRoot, "package-lock.json"))) {
|
|
1105
|
+
return "npm";
|
|
1106
|
+
}
|
|
1107
|
+
return "npm";
|
|
1108
|
+
}
|
|
1109
|
+
function resolveMcpInstallMode(rawMode) {
|
|
1110
|
+
if (rawMode === void 0 || rawMode === "global" || rawMode === "local") {
|
|
1111
|
+
return rawMode ?? "global";
|
|
1112
|
+
}
|
|
1113
|
+
writeStderr(t("cli.init.mcp.install.invalid", { value: rawMode }));
|
|
1114
|
+
return "global";
|
|
1115
|
+
}
|
|
1116
|
+
function installLocalFabricServer(target, manager) {
|
|
1117
|
+
const installArgs = manager === "npm" ? ["install", "-D", FABRIC_SERVER_PACKAGE] : ["add", "-D", FABRIC_SERVER_PACKAGE];
|
|
1118
|
+
childProcess.execFileSync(manager, installArgs, {
|
|
1119
|
+
cwd: target,
|
|
1120
|
+
stdio: "inherit",
|
|
1121
|
+
shell: process.platform === "win32"
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
979
1124
|
function createInitialMeta(agentsHash) {
|
|
980
1125
|
return {
|
|
981
1126
|
revision: sha256(agentsHash),
|
|
@@ -1030,28 +1175,41 @@ function templateCandidatesFrom(start, relativePath) {
|
|
|
1030
1175
|
}
|
|
1031
1176
|
return candidates.reverse();
|
|
1032
1177
|
}
|
|
1033
|
-
function
|
|
1034
|
-
if (existsSync2(path)) {
|
|
1035
|
-
|
|
1178
|
+
function prepareFreshPath(path, options) {
|
|
1179
|
+
if (!existsSync2(path)) {
|
|
1180
|
+
return "created";
|
|
1181
|
+
}
|
|
1182
|
+
if (!options?.force) {
|
|
1183
|
+
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1184
|
+
}
|
|
1185
|
+
rmSync(path, { recursive: true, force: true });
|
|
1186
|
+
return "overwritten";
|
|
1187
|
+
}
|
|
1188
|
+
function writeNewFile(path, content, options) {
|
|
1189
|
+
const existed = existsSync2(path);
|
|
1190
|
+
if (existed && !options?.force) {
|
|
1191
|
+
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1036
1192
|
}
|
|
1037
1193
|
writeFileSync(path, content, "utf8");
|
|
1194
|
+
return existed ? "overwritten" : "created";
|
|
1038
1195
|
}
|
|
1039
|
-
function copyTemplateIfMissing(templatePath, targetPath) {
|
|
1196
|
+
function copyTemplateIfMissing(templatePath, targetPath, options) {
|
|
1040
1197
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
1041
|
-
|
|
1198
|
+
const existed = existsSync2(targetPath);
|
|
1199
|
+
if (existed && !options?.force) {
|
|
1042
1200
|
return "skipped";
|
|
1043
1201
|
}
|
|
1044
1202
|
copyFileSync(templatePath, targetPath);
|
|
1045
|
-
return "created";
|
|
1203
|
+
return existed ? "overwritten" : "created";
|
|
1046
1204
|
}
|
|
1047
|
-
function copyExecutableTemplateIfMissing(templatePath, targetPath) {
|
|
1048
|
-
const action = copyTemplateIfMissing(templatePath, targetPath);
|
|
1049
|
-
if (action
|
|
1205
|
+
function copyExecutableTemplateIfMissing(templatePath, targetPath, options) {
|
|
1206
|
+
const action = copyTemplateIfMissing(templatePath, targetPath, options);
|
|
1207
|
+
if (action !== "skipped") {
|
|
1050
1208
|
chmodSync(targetPath, 493);
|
|
1051
1209
|
}
|
|
1052
1210
|
return action;
|
|
1053
1211
|
}
|
|
1054
|
-
function mergeClaudeStopHook(settingsPath) {
|
|
1212
|
+
function mergeClaudeStopHook(settingsPath, options) {
|
|
1055
1213
|
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
1056
1214
|
let settings;
|
|
1057
1215
|
let action = "updated";
|
|
@@ -1083,10 +1241,12 @@ function mergeClaudeStopHook(settingsPath) {
|
|
|
1083
1241
|
return "skipped-invalid";
|
|
1084
1242
|
}
|
|
1085
1243
|
const stopHooks = Array.isArray(stopHooksValue) ? stopHooksValue : [];
|
|
1086
|
-
|
|
1244
|
+
const hasExistingFabricHook = hasClaudeInitReminderHook(stopHooks);
|
|
1245
|
+
if (hasExistingFabricHook && !options?.force) {
|
|
1087
1246
|
return "skipped";
|
|
1088
1247
|
}
|
|
1089
|
-
stopHooks
|
|
1248
|
+
const nextStopHooks = hasExistingFabricHook && options?.force ? removeClaudeInitReminderHook(stopHooks) : [...stopHooks];
|
|
1249
|
+
nextStopHooks.push({
|
|
1090
1250
|
matcher: "*",
|
|
1091
1251
|
hooks: [
|
|
1092
1252
|
{
|
|
@@ -1097,20 +1257,24 @@ function mergeClaudeStopHook(settingsPath) {
|
|
|
1097
1257
|
});
|
|
1098
1258
|
settings.hooks = {
|
|
1099
1259
|
...hooks,
|
|
1100
|
-
Stop:
|
|
1260
|
+
Stop: nextStopHooks
|
|
1101
1261
|
};
|
|
1102
1262
|
writeJsonAtomically(settingsPath, settings);
|
|
1103
|
-
return action;
|
|
1263
|
+
return hasExistingFabricHook && options?.force ? "overwritten" : action;
|
|
1104
1264
|
}
|
|
1105
1265
|
function hasClaudeInitReminderHook(stopHooks) {
|
|
1106
|
-
return stopHooks.some((entry) =>
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1266
|
+
return stopHooks.some((entry) => isClaudeInitReminderStopEntry(entry));
|
|
1267
|
+
}
|
|
1268
|
+
function removeClaudeInitReminderHook(stopHooks) {
|
|
1269
|
+
return stopHooks.filter((entry) => !isClaudeInitReminderStopEntry(entry));
|
|
1270
|
+
}
|
|
1271
|
+
function isClaudeInitReminderStopEntry(entry) {
|
|
1272
|
+
if (!isRecord(entry) || !Array.isArray(entry.hooks)) {
|
|
1273
|
+
return false;
|
|
1274
|
+
}
|
|
1275
|
+
return entry.hooks.some(
|
|
1276
|
+
(hook) => isRecord(hook) && hook.type === "command" && typeof hook.command === "string" && hook.command.includes("agents-md-init-reminder.cjs")
|
|
1277
|
+
);
|
|
1114
1278
|
}
|
|
1115
1279
|
function writeJsonAtomically(path, value) {
|
|
1116
1280
|
const tempPath = `${path}.${process.pid}.tmp`;
|
|
@@ -1127,6 +1291,8 @@ function formatClaudeSettingsAction(settingsPath, action) {
|
|
|
1127
1291
|
return t("cli.init.claude-settings.created", { label: createdLabel(), path: settingsPath });
|
|
1128
1292
|
case "updated":
|
|
1129
1293
|
return t("cli.init.claude-settings.updated", { label: updatedLabel(), path: settingsPath });
|
|
1294
|
+
case "overwritten":
|
|
1295
|
+
return t("cli.init.claude-settings.updated", { label: overwrittenLabel(), path: settingsPath });
|
|
1130
1296
|
case "skipped":
|
|
1131
1297
|
return t("cli.init.claude-settings.skipped", { label: skippedLabel(), path: settingsPath });
|
|
1132
1298
|
case "skipped-invalid":
|
|
@@ -1135,6 +1301,46 @@ function formatClaudeSettingsAction(settingsPath, action) {
|
|
|
1135
1301
|
return t("cli.init.claude-settings.updated", { label: updatedLabel(), path: settingsPath });
|
|
1136
1302
|
}
|
|
1137
1303
|
}
|
|
1304
|
+
function formatInitStageHeader(message) {
|
|
1305
|
+
return `${nextLabel()} ${paint.muted(message)}`;
|
|
1306
|
+
}
|
|
1307
|
+
function formatInitStageResult(stage, status, installedCount, skippedCount, note) {
|
|
1308
|
+
const label = status === "completed" ? completedStageLabel() : skippedStageLabel();
|
|
1309
|
+
const counts = `installed=${installedCount} skipped=${skippedCount}`;
|
|
1310
|
+
const suffix = note ? ` ${paint.muted(`(${note})`)}` : "";
|
|
1311
|
+
return `${label} ${stage}: ${counts}${suffix}`;
|
|
1312
|
+
}
|
|
1313
|
+
function formatInitStageFailure(stage, error) {
|
|
1314
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1315
|
+
return `${failedStageLabel()} ${stage}: ${message}`;
|
|
1316
|
+
}
|
|
1317
|
+
function printInitStageSummary(stageResults) {
|
|
1318
|
+
console.log(formatInitStageSummaryLine("ran", collectInitStageNames(stageResults, "ran")));
|
|
1319
|
+
console.log(formatInitStageSummaryLine("skipped", collectInitStageNames(stageResults, "skipped")));
|
|
1320
|
+
console.log(formatInitStageSummaryLine("failed", collectInitStageNames(stageResults, "failed")));
|
|
1321
|
+
}
|
|
1322
|
+
function formatInitStageSummaryLine(disposition, stages) {
|
|
1323
|
+
const label = disposition === "ran" ? paint.success(t("cli.init.stages.summary.ran")) : disposition === "skipped" ? paint.muted(t("cli.init.stages.summary.skipped")) : paint.error(t("cli.init.stages.summary.failed"));
|
|
1324
|
+
return `${label}: ${stages.length > 0 ? stages.join(", ") : t("cli.shared.none")}`;
|
|
1325
|
+
}
|
|
1326
|
+
function collectInitStageNames(stageResults, disposition) {
|
|
1327
|
+
return stageResults.filter((stage) => stage.disposition === disposition).map((stage) => stage.name);
|
|
1328
|
+
}
|
|
1329
|
+
function shouldPrintHooksNextStep(options, stageResults) {
|
|
1330
|
+
return Boolean(options.skipHooks) || stageResults.some((stage) => stage.name === "hooks" && stage.disposition === "failed");
|
|
1331
|
+
}
|
|
1332
|
+
function formatInitPathAction(path, action) {
|
|
1333
|
+
return t("cli.init.created-path", { label: labelForInitWriteAction(action), path });
|
|
1334
|
+
}
|
|
1335
|
+
function formatOptionalInitPathAction(path, action) {
|
|
1336
|
+
if (action === "skipped") {
|
|
1337
|
+
return t("cli.init.skipped-existing-path", { label: skippedLabel(), path });
|
|
1338
|
+
}
|
|
1339
|
+
return formatInitPathAction(path, action);
|
|
1340
|
+
}
|
|
1341
|
+
function labelForInitWriteAction(action) {
|
|
1342
|
+
return action === "overwritten" ? overwrittenLabel() : createdLabel();
|
|
1343
|
+
}
|
|
1138
1344
|
function createdLabel() {
|
|
1139
1345
|
return paint.success(t("cli.shared.created"));
|
|
1140
1346
|
}
|
|
@@ -1150,6 +1356,18 @@ function reasonLabel() {
|
|
|
1150
1356
|
function updatedLabel() {
|
|
1151
1357
|
return paint.success(t("cli.shared.updated"));
|
|
1152
1358
|
}
|
|
1359
|
+
function overwrittenLabel() {
|
|
1360
|
+
return paint.warn(t("cli.init.force.overwritten"));
|
|
1361
|
+
}
|
|
1362
|
+
function completedStageLabel() {
|
|
1363
|
+
return paint.success(t("cli.init.stages.completed"));
|
|
1364
|
+
}
|
|
1365
|
+
function skippedStageLabel() {
|
|
1366
|
+
return paint.muted(t("cli.init.stages.skipped"));
|
|
1367
|
+
}
|
|
1368
|
+
function failedStageLabel() {
|
|
1369
|
+
return paint.error(t("cli.init.stages.failed"));
|
|
1370
|
+
}
|
|
1153
1371
|
function writeStderr(message) {
|
|
1154
1372
|
process.stderr.write(`${message}
|
|
1155
1373
|
`);
|
|
@@ -1159,6 +1377,7 @@ function sha256(content) {
|
|
|
1159
1377
|
}
|
|
1160
1378
|
export {
|
|
1161
1379
|
init_default as default,
|
|
1380
|
+
detectPackageManager,
|
|
1162
1381
|
initCommand,
|
|
1163
1382
|
initFabric
|
|
1164
1383
|
};
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
createScanReport,
|
|
4
4
|
scanCommand,
|
|
5
5
|
scan_default
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-AEOYCVBG.js";
|
|
6
|
+
} from "./chunk-N4DCTOXW.js";
|
|
8
7
|
import "./chunk-WWNXR34K.js";
|
|
8
|
+
import "./chunk-AEOYCVBG.js";
|
|
9
9
|
import "./chunk-6ICJICVU.js";
|
|
10
10
|
export {
|
|
11
11
|
createScanReport,
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fenglimg/fabric-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
|
-
"fab": "dist/index.js"
|
|
6
|
+
"fab": "dist/index.js",
|
|
7
|
+
"fabric": "dist/index.js"
|
|
7
8
|
},
|
|
8
9
|
"main": "./dist/index.js",
|
|
9
10
|
"types": "./dist/index.d.ts",
|
|
@@ -16,8 +17,8 @@
|
|
|
16
17
|
"citty": "^0.2.2",
|
|
17
18
|
"picocolors": "^1.1.1",
|
|
18
19
|
"string-width": "^7.2.0",
|
|
19
|
-
"@fenglimg/fabric-shared": "1.
|
|
20
|
-
"@fenglimg/fabric-server": "1.
|
|
20
|
+
"@fenglimg/fabric-shared": "1.2.0",
|
|
21
|
+
"@fenglimg/fabric-server": "1.2.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/iarna__toml": "^2.0.5",
|
package/dist/hooks-5S5IRVQE.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
t
|
|
4
|
-
} from "./chunk-6ICJICVU.js";
|
|
5
|
-
|
|
6
|
-
// src/commands/hooks.ts
|
|
7
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
8
|
-
import { dirname, isAbsolute, join, parse, resolve } from "path";
|
|
9
|
-
import { fileURLToPath } from "url";
|
|
10
|
-
import { defineCommand } from "citty";
|
|
11
|
-
var hooksCommand = defineCommand({
|
|
12
|
-
meta: {
|
|
13
|
-
name: "hooks",
|
|
14
|
-
description: t("cli.hooks.description")
|
|
15
|
-
},
|
|
16
|
-
subCommands: {
|
|
17
|
-
install: defineCommand({
|
|
18
|
-
meta: {
|
|
19
|
-
name: "install",
|
|
20
|
-
description: t("cli.hooks.install.description")
|
|
21
|
-
},
|
|
22
|
-
args: {
|
|
23
|
-
target: {
|
|
24
|
-
type: "string",
|
|
25
|
-
description: t("cli.hooks.install.args.target.description"),
|
|
26
|
-
default: process.cwd()
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
async run({ args }) {
|
|
30
|
-
const target = normalizeTarget(args.target);
|
|
31
|
-
assertExistingDirectory(target);
|
|
32
|
-
const huskyDir = join(target, ".husky");
|
|
33
|
-
const hookPath = join(huskyDir, "pre-commit");
|
|
34
|
-
const packageJsonPath = join(target, "package.json");
|
|
35
|
-
if (!existsSync(packageJsonPath)) {
|
|
36
|
-
throw new Error(t("cli.hooks.errors.package-json-required", { path: packageJsonPath }));
|
|
37
|
-
}
|
|
38
|
-
mkdirSync(huskyDir, { recursive: true });
|
|
39
|
-
const templateContent = readFileSync(findTemplatePath("templates/husky/pre-commit"), "utf8");
|
|
40
|
-
let hookAction;
|
|
41
|
-
if (existsSync(hookPath)) {
|
|
42
|
-
const existing = readFileSync(hookPath, "utf8");
|
|
43
|
-
if (existing.includes("FAB_BIN=")) {
|
|
44
|
-
hookAction = "skipped";
|
|
45
|
-
} else {
|
|
46
|
-
const fabricBlock = templateContent.replace(/^#!\/bin\/sh\n/, "");
|
|
47
|
-
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
48
|
-
writeFileSync(hookPath, `${existing}${separator}# --- Fabric ---
|
|
49
|
-
${fabricBlock}`, "utf8");
|
|
50
|
-
hookAction = "appended";
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
writeFileSync(hookPath, templateContent, "utf8");
|
|
54
|
-
hookAction = "created";
|
|
55
|
-
}
|
|
56
|
-
chmodSync(hookPath, 493);
|
|
57
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
58
|
-
const scripts = packageJson.scripts && typeof packageJson.scripts === "object" && !Array.isArray(packageJson.scripts) ? packageJson.scripts : {};
|
|
59
|
-
const hadPrepare = typeof scripts.prepare === "string" && scripts.prepare.trim().length > 0;
|
|
60
|
-
if (!hadPrepare) {
|
|
61
|
-
scripts.prepare = "husky install";
|
|
62
|
-
packageJson.scripts = scripts;
|
|
63
|
-
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
64
|
-
`, "utf8");
|
|
65
|
-
}
|
|
66
|
-
if (hookAction === "skipped") {
|
|
67
|
-
writeStderr(t("cli.hooks.install.hook-skipped", { path: hookPath }));
|
|
68
|
-
} else if (hookAction === "appended") {
|
|
69
|
-
writeStderr(t("cli.hooks.install.hook-appended", { path: hookPath }));
|
|
70
|
-
} else {
|
|
71
|
-
writeStderr(t("cli.hooks.install.hook-created", { path: hookPath }));
|
|
72
|
-
}
|
|
73
|
-
if (hadPrepare) {
|
|
74
|
-
writeStderr(t("cli.hooks.install.prepare-left", { path: packageJsonPath }));
|
|
75
|
-
} else {
|
|
76
|
-
writeStderr(t("cli.hooks.install.prepare-added", { path: packageJsonPath }));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
var hooks_default = hooksCommand;
|
|
83
|
-
function normalizeTarget(targetInput) {
|
|
84
|
-
return isAbsolute(targetInput) ? targetInput : resolve(process.cwd(), targetInput);
|
|
85
|
-
}
|
|
86
|
-
function assertExistingDirectory(target) {
|
|
87
|
-
if (!existsSync(target) || !statSync(target).isDirectory()) {
|
|
88
|
-
throw new Error(t("cli.shared.target-invalid", { target }));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function findTemplatePath(relativePath) {
|
|
92
|
-
const currentModuleDir = dirname(fileURLToPath(import.meta.url));
|
|
93
|
-
const candidates = [
|
|
94
|
-
...templateCandidatesFrom(process.cwd(), relativePath),
|
|
95
|
-
...templateCandidatesFrom(currentModuleDir, relativePath)
|
|
96
|
-
];
|
|
97
|
-
for (const candidate of candidates) {
|
|
98
|
-
if (existsSync(candidate)) {
|
|
99
|
-
return candidate;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
throw new Error(t("cli.shared.template-not-found", { path: relativePath }));
|
|
103
|
-
}
|
|
104
|
-
function templateCandidatesFrom(start, relativePath) {
|
|
105
|
-
const candidates = [];
|
|
106
|
-
let current = resolve(start);
|
|
107
|
-
while (true) {
|
|
108
|
-
candidates.push(join(current, ...relativePath.split("/")));
|
|
109
|
-
const parent = dirname(current);
|
|
110
|
-
if (parent === current || parse(current).root === current) {
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
current = parent;
|
|
114
|
-
}
|
|
115
|
-
return candidates.reverse();
|
|
116
|
-
}
|
|
117
|
-
function writeStderr(message) {
|
|
118
|
-
process.stderr.write(`${message}
|
|
119
|
-
`);
|
|
120
|
-
}
|
|
121
|
-
export {
|
|
122
|
-
hooks_default as default,
|
|
123
|
-
hooksCommand
|
|
124
|
-
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
createDebugLogger,
|
|
4
|
-
readFabricConfig,
|
|
5
|
-
resolveDevMode
|
|
6
|
-
} from "./chunk-AEOYCVBG.js";
|
|
7
2
|
import {
|
|
8
3
|
displayWidth,
|
|
9
4
|
padEnd,
|
|
10
5
|
paint,
|
|
11
6
|
symbol
|
|
12
7
|
} from "./chunk-WWNXR34K.js";
|
|
8
|
+
import {
|
|
9
|
+
createDebugLogger,
|
|
10
|
+
readFabricConfig,
|
|
11
|
+
resolveDevMode
|
|
12
|
+
} from "./chunk-AEOYCVBG.js";
|
|
13
13
|
import {
|
|
14
14
|
t
|
|
15
15
|
} from "./chunk-6ICJICVU.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
resolveDevMode
|
|
4
|
-
} from "./chunk-AEOYCVBG.js";
|
|
5
2
|
import {
|
|
6
3
|
padEnd,
|
|
7
4
|
paint,
|
|
8
5
|
symbol
|
|
9
6
|
} from "./chunk-WWNXR34K.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveDevMode
|
|
9
|
+
} from "./chunk-AEOYCVBG.js";
|
|
10
10
|
import {
|
|
11
11
|
t
|
|
12
12
|
} from "./chunk-6ICJICVU.js";
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
ledger_append_default
|
|
4
|
-
} from "./chunk-F2BXHPM5.js";
|
|
5
|
-
import {
|
|
6
|
-
resolveDevModeTarget
|
|
7
|
-
} from "./chunk-AEOYCVBG.js";
|
|
8
2
|
import {
|
|
9
3
|
sync_meta_default
|
|
10
4
|
} from "./chunk-6UUPKSDE.js";
|
|
11
5
|
import {
|
|
12
6
|
human_lint_default
|
|
13
7
|
} from "./chunk-L43IGJ6X.js";
|
|
8
|
+
import {
|
|
9
|
+
ledger_append_default
|
|
10
|
+
} from "./chunk-F2BXHPM5.js";
|
|
14
11
|
import "./chunk-WWNXR34K.js";
|
|
12
|
+
import {
|
|
13
|
+
resolveDevModeTarget
|
|
14
|
+
} from "./chunk-AEOYCVBG.js";
|
|
15
15
|
import {
|
|
16
16
|
t
|
|
17
17
|
} from "./chunk-6ICJICVU.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
createDebugLogger,
|
|
4
|
-
resolveDevMode
|
|
5
|
-
} from "./chunk-AEOYCVBG.js";
|
|
6
2
|
import {
|
|
7
3
|
paint,
|
|
8
4
|
symbol
|
|
9
5
|
} from "./chunk-WWNXR34K.js";
|
|
6
|
+
import {
|
|
7
|
+
createDebugLogger,
|
|
8
|
+
resolveDevMode
|
|
9
|
+
} from "./chunk-AEOYCVBG.js";
|
|
10
10
|
import {
|
|
11
11
|
t
|
|
12
12
|
} from "./chunk-6ICJICVU.js";
|