opencode-rules-md 0.7.0 → 0.8.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.
Files changed (47) hide show
  1. package/README.md +13 -3
  2. package/dist/src/active-rules-state.js +1 -1
  3. package/dist/src/active-rules-state.js.map +1 -1
  4. package/dist/src/rule-discovery.d.ts +1 -1
  5. package/dist/src/rule-discovery.d.ts.map +1 -1
  6. package/dist/src/rule-discovery.js +2 -2
  7. package/dist/src/rule-discovery.js.map +1 -1
  8. package/dist/tui/data/rules.d.ts +1 -1
  9. package/dist/tui/data/rules.d.ts.map +1 -1
  10. package/dist/tui/data/rules.js +2 -2
  11. package/dist/tui/data/rules.js.map +1 -1
  12. package/dist/tui/index.js +1 -1
  13. package/dist/tui/index.js.map +1 -1
  14. package/dist/tui/slots/sidebar-content.js +1 -1
  15. package/dist/tui/slots/sidebar-content.js.map +1 -1
  16. package/package.json +8 -12
  17. package/src/active-rules-state.ts +1 -1
  18. package/src/rule-discovery.ts +2 -2
  19. package/tui/data/rules.ts +3 -3
  20. package/tui/index.tsx +1 -1
  21. package/tui/slots/sidebar-content.tsx +1 -1
  22. package/dist/cli.mjs +0 -454
  23. package/dist/src/cli/config.d.ts +0 -74
  24. package/dist/src/cli/config.d.ts.map +0 -1
  25. package/dist/src/cli/config.js +0 -292
  26. package/dist/src/cli/config.js.map +0 -1
  27. package/dist/src/cli/install.d.ts +0 -33
  28. package/dist/src/cli/install.d.ts.map +0 -1
  29. package/dist/src/cli/install.js +0 -99
  30. package/dist/src/cli/install.js.map +0 -1
  31. package/dist/src/cli/main.d.ts +0 -19
  32. package/dist/src/cli/main.d.ts.map +0 -1
  33. package/dist/src/cli/main.js +0 -149
  34. package/dist/src/cli/main.js.map +0 -1
  35. package/dist/src/cli/real-fs.d.ts +0 -26
  36. package/dist/src/cli/real-fs.d.ts.map +0 -1
  37. package/dist/src/cli/real-fs.js +0 -42
  38. package/dist/src/cli/real-fs.js.map +0 -1
  39. package/dist/src/cli/status.d.ts +0 -34
  40. package/dist/src/cli/status.d.ts.map +0 -1
  41. package/dist/src/cli/status.js +0 -67
  42. package/dist/src/cli/status.js.map +0 -1
  43. package/src/cli/config.ts +0 -364
  44. package/src/cli/install.ts +0 -171
  45. package/src/cli/main.ts +0 -178
  46. package/src/cli/real-fs.ts +0 -65
  47. package/src/cli/status.ts +0 -99
@@ -1,292 +0,0 @@
1
- /**
2
- * CLI config helpers: discovery, JSONC-safe parsing, plugin normalization,
3
- * backup rotation, and atomic write.
4
- *
5
- * All filesystem access goes through the CliFs interface so tests can inject
6
- * an in-memory implementation without touching real disk.
7
- */
8
- import * as os from 'node:os';
9
- import * as path from 'node:path';
10
- // ---------------------------------------------------------------------------
11
- // Public constants
12
- // ---------------------------------------------------------------------------
13
- /** npm package name for this plugin. */
14
- export const PLUGIN_NAME = 'opencode-rules-md';
15
- /** Filename for the OpenCode server config. */
16
- export const SERVER_CONFIG_FILENAME = 'opencode.json';
17
- /** Filename for the OpenCode TUI config. */
18
- export const TUI_CONFIG_FILENAME = 'tui.json';
19
- // ---------------------------------------------------------------------------
20
- // JSONC comment stripper — two-pass
21
- // ---------------------------------------------------------------------------
22
- /**
23
- * Strip JSONC comments and trailing commas while preserving
24
- * comment-like sequences inside string literals.
25
- *
26
- * Pass 1: strip `//` and `/* * /` comments (string-aware).
27
- * Pass 2: strip trailing commas before `}` or `]`, skipping whitespace.
28
- */
29
- export function stripJsoncComments(content) {
30
- // Pass 1 — strip comments while preserving string contents
31
- let result = '';
32
- let i = 0;
33
- let inString = false;
34
- let escaped = false;
35
- const len = content.length;
36
- while (i < len) {
37
- const char = content[i];
38
- if (inString) {
39
- result += char;
40
- if (escaped) {
41
- escaped = false;
42
- }
43
- else if (char === '\\') {
44
- escaped = true;
45
- }
46
- else if (char === '"') {
47
- inString = false;
48
- }
49
- i++;
50
- continue;
51
- }
52
- if (char === '"') {
53
- inString = true;
54
- result += char;
55
- i++;
56
- continue;
57
- }
58
- // Line comment: // until newline
59
- if (char === '/' && content[i + 1] === '/') {
60
- i += 2;
61
- while (i < len && content[i] !== '\n')
62
- i++;
63
- continue;
64
- }
65
- // Block comment: /* until */
66
- if (char === '/' && content[i + 1] === '*') {
67
- i += 2;
68
- while (i < len && !(content[i] === '*' && content[i + 1] === '/'))
69
- i++;
70
- if (i < len)
71
- i += 2; // skip past */
72
- continue;
73
- }
74
- result += char;
75
- i++;
76
- }
77
- // Pass 2 — strip trailing commas (with whitespace skip) before } or ]
78
- let out = '';
79
- let inStr = false;
80
- let esc = false;
81
- let j = 0;
82
- const outLen = result.length;
83
- while (j < outLen) {
84
- const ch = result[j];
85
- if (inStr) {
86
- out += ch;
87
- if (esc) {
88
- esc = false;
89
- }
90
- else if (ch === '\\') {
91
- esc = true;
92
- }
93
- else if (ch === '"') {
94
- inStr = false;
95
- }
96
- j++;
97
- continue;
98
- }
99
- if (ch === '"') {
100
- inStr = true;
101
- out += ch;
102
- j++;
103
- continue;
104
- }
105
- if (ch === ',') {
106
- // Skip whitespace before checking for } or ]
107
- let k = j + 1;
108
- while (k < outLen && /\s/.test(result[k]))
109
- k++;
110
- if (k < outLen && /[}\]]/.test(result[k])) {
111
- // Drop the comma; jump to the bracket
112
- j = k;
113
- continue;
114
- }
115
- }
116
- out += ch;
117
- j++;
118
- }
119
- return out;
120
- }
121
- // ---------------------------------------------------------------------------
122
- // Config path resolution
123
- // ---------------------------------------------------------------------------
124
- /**
125
- * Resolve the global opencode config path using the same precedence as
126
- * opencode itself: OPENCODE_CONFIG_DIR → XDG_CONFIG_HOME → HOME fallback.
127
- *
128
- * On Windows, APPDATA is tried as a last resort when XDG_CONFIG_HOME and
129
- * HOME are both absent.
130
- */
131
- export function resolveGlobalConfigPath(fs, opts = {}) {
132
- const dir = resolveConfigDir();
133
- if (opts.ensureDir && !fs.existsSync(dir)) {
134
- fs.mkdirSync(dir, { recursive: true });
135
- }
136
- const filename = opts.filename ?? SERVER_CONFIG_FILENAME;
137
- return path.join(dir, filename);
138
- }
139
- function resolveConfigDir() {
140
- if (process.env.OPENCODE_CONFIG_DIR) {
141
- return process.env.OPENCODE_CONFIG_DIR;
142
- }
143
- if (process.env.XDG_CONFIG_HOME) {
144
- return path.join(process.env.XDG_CONFIG_HOME, 'opencode');
145
- }
146
- const home = process.env.HOME || os.homedir();
147
- if (home) {
148
- return path.join(home, '.config', 'opencode');
149
- }
150
- // Windows fallback
151
- const appdata = process.env.APPDATA;
152
- if (appdata) {
153
- return path.join(appdata, 'opencode');
154
- }
155
- throw new Error('Cannot resolve config dir: none of OPENCODE_CONFIG_DIR, XDG_CONFIG_HOME, HOME, or APPDATA is set');
156
- }
157
- // ---------------------------------------------------------------------------
158
- // JSONC-safe config load
159
- // ---------------------------------------------------------------------------
160
- /**
161
- * Load and parse a global OpenCode config file.
162
- * Treats a missing file as an empty config object (not an error).
163
- * Surfaces parse errors so callers can exit non-zero without corrupting data.
164
- */
165
- export function loadGlobalConfig(fs, opts = {}) {
166
- const configPath = resolveGlobalConfigPath(fs, opts.filename ? { filename: opts.filename } : {});
167
- if (!fs.existsSync(configPath)) {
168
- return { path: configPath, existed: false, config: {} };
169
- }
170
- try {
171
- const raw = fs.readFileSync(configPath);
172
- const stripped = stripJsoncComments(raw);
173
- // Empty after stripping means comment-only file — treat as {}
174
- if (stripped.trim() === '') {
175
- return { path: configPath, existed: true, config: {} };
176
- }
177
- const parsed = JSON.parse(stripped);
178
- return { path: configPath, existed: true, config: parsed };
179
- }
180
- catch (err) {
181
- const error = err instanceof Error ? err : new Error(String(err));
182
- return { path: configPath, existed: true, config: {}, parseError: error };
183
- }
184
- }
185
- // ---------------------------------------------------------------------------
186
- // Plugin normalization helpers
187
- // ---------------------------------------------------------------------------
188
- /**
189
- * Return the plugin array with opencode-rules-md* entries deduplicated by
190
- * name prefix, keeping the last occurrence of each unique prefix.
191
- */
192
- export function normalizePlugin(config) {
193
- const raw = Array.isArray(config['plugin']) ? config['plugin'] : [];
194
- const seen = new Map(); // prefix → last index
195
- const result = [];
196
- for (const item of raw) {
197
- if (typeof item !== 'string')
198
- continue;
199
- const prefix = getPluginPrefix(item);
200
- seen.set(prefix, result.length);
201
- result.push(item);
202
- }
203
- // Collapse entries sharing a prefix to only the last one
204
- return collapseByPrefix(result, seen);
205
- }
206
- /**
207
- * Remove all plugins matching the given prefix (used to dedupe before append).
208
- */
209
- export function removePlugin(config, prefix) {
210
- if (!Array.isArray(config['plugin']))
211
- return;
212
- const raw = config['plugin'];
213
- config['plugin'] = raw.filter(item => typeof item === 'string' && !item.startsWith(prefix));
214
- }
215
- /**
216
- * Add a plugin specifier, removing any existing entry with the same prefix first
217
- * so it ends up at the specified position (default: end). This makes the operation
218
- * idempotent — re-adding the same specifier just moves it to the end.
219
- */
220
- export function addPlugin(config, specifier) {
221
- if (!Array.isArray(config['plugin'])) {
222
- config['plugin'] = [];
223
- }
224
- const plugin = config['plugin'];
225
- const prefix = getPluginPrefix(specifier);
226
- // Remove any existing entry with the same prefix
227
- const removed = plugin.filter(p => getPluginPrefix(p) !== prefix);
228
- removed.push(specifier);
229
- config['plugin'] = removed;
230
- }
231
- // ---------------------------------------------------------------------------
232
- // Backup rotation
233
- // ---------------------------------------------------------------------------
234
- /**
235
- * Write a timestamped backup of the given config path and rotate so at most
236
- * 3 backups are retained (oldest deleted first).
237
- * Returns the path of the newly created backup, or null if no backup was created.
238
- */
239
- export function rotateBackups(fs, configPath, _pluginName) {
240
- if (!fs.existsSync(configPath)) {
241
- return null;
242
- }
243
- const dir = path.dirname(configPath);
244
- const base = path.basename(configPath);
245
- const timestamp = Date.now();
246
- const newBak = path.join(dir, `${base}.bak.${timestamp}`);
247
- fs.copyFileSync(configPath, newBak);
248
- // Collect existing backups sorted by timestamp (lexical sort on numeric suffix)
249
- const entries = fs.readdirSync(dir);
250
- const bakFiles = entries
251
- .filter(e => e.startsWith(base + '.bak.'))
252
- .sort();
253
- // Remove oldest until only 3 remain
254
- while (bakFiles.length > 3) {
255
- const oldest = bakFiles.shift();
256
- fs.unlinkSync(path.join(dir, oldest));
257
- }
258
- return newBak;
259
- }
260
- // ---------------------------------------------------------------------------
261
- // Atomic write
262
- // ---------------------------------------------------------------------------
263
- /**
264
- * Write content to a temporary sibling file then rename it into place.
265
- * The final path is never in a partially-written state.
266
- */
267
- export function writeAtomically(fs, configPath, content) {
268
- const dir = path.dirname(configPath);
269
- const base = path.basename(configPath);
270
- const tmpPath = path.join(dir, `.${base}.tmp.${Date.now()}-${process.pid}`);
271
- fs.writeFileSync(tmpPath, content, 'utf-8');
272
- fs.renameSync(tmpPath, configPath);
273
- }
274
- // ---------------------------------------------------------------------------
275
- // Internal helpers
276
- // ---------------------------------------------------------------------------
277
- /**
278
- * Extract the name part of a plugin specifier, stripping any version suffix.
279
- * e.g. "opencode-rules-md@0.1.0" → "opencode-rules-md"
280
- */
281
- function getPluginPrefix(specifier) {
282
- const atIdx = specifier.indexOf('@');
283
- return atIdx === -1 ? specifier : specifier.substring(0, atIdx);
284
- }
285
- /**
286
- * Collapse plugins by prefix, keeping only the last occurrence of each.
287
- */
288
- function collapseByPrefix(plugins, lastSeen) {
289
- const keptIndices = new Set([...lastSeen.values()]);
290
- return plugins.filter((_, idx) => keptIndices.has(idx));
291
- }
292
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/config.ts"],"names":[],"mappings":"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"}
@@ -1,33 +0,0 @@
1
- /**
2
- * install command: idempotently append opencode-rules-md to the global configs.
3
- *
4
- * Registers the plugin in BOTH:
5
- * - Server config: ~/.config/opencode/opencode.json
6
- * - TUI config: ~/.config/opencode/tui.json
7
- *
8
- * Pipeline (per config):
9
- * loadGlobalConfig → abort if parseError (throw) → normalizePlugin
10
- * → check no-op → (dry-run? print & return "planned")
11
- * → rotateBackups → writeAtomically → print & return "wrote"
12
- *
13
- * Errors are surfaced as exceptions instead of silent status returns so
14
- * the CLI dispatcher can print them.
15
- */
16
- import type { CliFs } from './real-fs.js';
17
- export interface ConfigUpdateResult {
18
- status: 'wrote' | 'planned' | 'noop';
19
- path: string;
20
- specifier: string;
21
- backup?: string;
22
- }
23
- export interface InstallResult {
24
- status: 'wrote' | 'planned' | 'noop';
25
- specifier: string;
26
- server: ConfigUpdateResult;
27
- tui: ConfigUpdateResult;
28
- }
29
- export declare function runInstall(opts: {
30
- version?: string;
31
- dryRun?: boolean;
32
- }, fs?: CliFs): InstallResult;
33
- //# sourceMappingURL=install.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAO1C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,GAAG,EAAE,kBAAkB,CAAC;CACzB;AAMD,wBAAgB,UAAU,CACxB,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAC5C,EAAE,GAAE,KAAc,GACjB,aAAa,CAkBf"}
@@ -1,99 +0,0 @@
1
- /**
2
- * install command: idempotently append opencode-rules-md to the global configs.
3
- *
4
- * Registers the plugin in BOTH:
5
- * - Server config: ~/.config/opencode/opencode.json
6
- * - TUI config: ~/.config/opencode/tui.json
7
- *
8
- * Pipeline (per config):
9
- * loadGlobalConfig → abort if parseError (throw) → normalizePlugin
10
- * → check no-op → (dry-run? print & return "planned")
11
- * → rotateBackups → writeAtomically → print & return "wrote"
12
- *
13
- * Errors are surfaced as exceptions instead of silent status returns so
14
- * the CLI dispatcher can print them.
15
- */
16
- import { loadGlobalConfig, normalizePlugin, removePlugin, addPlugin, rotateBackups, writeAtomically, TUI_CONFIG_FILENAME, } from './config.js';
17
- import { realFs } from './real-fs.js';
18
- // ---------------------------------------------------------------------------
19
- // Run install
20
- // ---------------------------------------------------------------------------
21
- export function runInstall(opts, fs = realFs) {
22
- const specifier = buildSpecifier(opts.version);
23
- const server = updateConfig(specifier, opts.dryRun ?? false, fs);
24
- const tui = updateConfig(specifier, opts.dryRun ?? false, fs, {
25
- filename: TUI_CONFIG_FILENAME,
26
- });
27
- const aggregate = server.status === 'wrote' || tui.status === 'wrote'
28
- ? 'wrote'
29
- : server.status === 'planned' || tui.status === 'planned'
30
- ? 'planned'
31
- : 'noop';
32
- printSummary(aggregate, specifier, server, tui);
33
- return { status: aggregate, specifier, server, tui };
34
- }
35
- function updateConfig(specifier, dryRun, fs, opts = {}) {
36
- const loadResult = loadGlobalConfig(fs, opts.filename ? { filename: opts.filename } : {});
37
- // Throw on parse error — better to fail fast than to silently corrupt config
38
- if (loadResult.parseError) {
39
- const filename = opts.filename ?? 'opencode.json';
40
- const err = new Error(`opencode-rules-md: ${filename} is malformed — aborting to avoid data loss.\n` +
41
- ` path: ${loadResult.path}\n` +
42
- ` error: ${loadResult.parseError.message}`);
43
- err.configPath = loadResult.path;
44
- throw err;
45
- }
46
- const configPath = loadResult.path;
47
- const config = loadResult.config;
48
- // Normalize plugin array (dedupe by prefix)
49
- config['plugin'] = normalizePlugin(config);
50
- // Check if already installed with the same specifier — no-op
51
- const existing = config['plugin'] ?? [];
52
- if (existing.includes(specifier)) {
53
- return { status: 'noop', path: configPath, specifier };
54
- }
55
- // Remove any existing opencode-rules-md* entries so this specifier is deduplicated
56
- removePlugin(config, 'opencode-rules-md');
57
- // Add the new (or re-added) specifier at the end
58
- addPlugin(config, specifier);
59
- // Dry-run: serialize and print planned content, make no changes
60
- if (dryRun) {
61
- const planned = JSON.stringify(config, null, 2);
62
- console.log(`Planned ${configPath}:\n${planned}`);
63
- return { status: 'planned', path: configPath, specifier };
64
- }
65
- // Write: rotate backups first, then atomic write
66
- const backup = rotateBackups(fs, configPath, 'opencode-rules-md');
67
- const serialized = JSON.stringify(config, null, 2);
68
- writeAtomically(fs, configPath, serialized);
69
- const result = { status: 'wrote', path: configPath, specifier };
70
- if (backup)
71
- result.backup = backup;
72
- return result;
73
- }
74
- // ---------------------------------------------------------------------------
75
- // Internal helpers
76
- // ---------------------------------------------------------------------------
77
- function buildSpecifier(version) {
78
- return version ? `opencode-rules-md@${version}` : 'opencode-rules-md';
79
- }
80
- function printSummary(status, specifier, server, tui) {
81
- if (status === 'noop') {
82
- console.log(`Already installed (${specifier})`);
83
- console.log(` server config: ${server.path}`);
84
- console.log(` tui config: ${tui.path}`);
85
- return;
86
- }
87
- if (status === 'planned') {
88
- console.log('Dry run complete — no files written.');
89
- return;
90
- }
91
- console.log(`Installed ${specifier}`);
92
- console.log(` server config: ${server.path}`);
93
- if (server.backup)
94
- console.log(` backup: ${server.backup}`);
95
- console.log(` tui config: ${tui.path}`);
96
- if (tui.backup)
97
- console.log(` backup: ${tui.backup}`);
98
- }
99
- //# sourceMappingURL=install.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/cli/install.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CLI entrypoint for opencode-rules-md installer.
4
- *
5
- * Supports:
6
- * install — add opencode-rules-md to the global opencode + tui configs
7
- * status — report whether opencode-rules-md is installed
8
- *
9
- * Flags:
10
- * --version <v> — specify a plugin version to install
11
- * --latest — install the latest version (default)
12
- * --dry-run — show what would be written, without changing files
13
- * --yes — skip confirmation prompts (future use)
14
- * -h, --help — show this help text
15
- */
16
- import type { CliFs } from './real-fs.js';
17
- export type ExitCode = 0 | 1 | 2;
18
- export declare function runMain(argv: string[], fs?: CliFs): Promise<ExitCode>;
19
- //# sourceMappingURL=main.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAyE1C,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjC,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoDnF"}
@@ -1,149 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CLI entrypoint for opencode-rules-md installer.
4
- *
5
- * Supports:
6
- * install — add opencode-rules-md to the global opencode + tui configs
7
- * status — report whether opencode-rules-md is installed
8
- *
9
- * Flags:
10
- * --version <v> — specify a plugin version to install
11
- * --latest — install the latest version (default)
12
- * --dry-run — show what would be written, without changing files
13
- * --yes — skip confirmation prompts (future use)
14
- * -h, --help — show this help text
15
- */
16
- import { parseArgs } from 'node:util';
17
- import { pathToFileURL } from 'node:url';
18
- import { realpathSync } from 'node:fs';
19
- import { runInstall } from './install.js';
20
- import { runStatus } from './status.js';
21
- import { realFs } from './real-fs.js';
22
- // ---------------------------------------------------------------------------
23
- // Help text
24
- // ---------------------------------------------------------------------------
25
- const HELP_TEXT = `opencode-rules-md CLI
26
-
27
- Usage: opencode-rules-md <command> [options]
28
-
29
- Commands:
30
- install Add opencode-rules-md to the global opencode + tui configs
31
- status Report whether opencode-rules-md is installed
32
-
33
- Options:
34
- --version <v> Specify a plugin version to install
35
- --latest Install the latest version (default)
36
- --dry-run Show what would be written, without changing files
37
- --yes Skip confirmation prompts (future use)
38
- -h, --help Show this help text
39
- `.trim();
40
- const USAGE_ERROR_TEXT = `Error: unknown command. Run 'opencode-rules-md --help' for usage.`.trim();
41
- function parseCliArgs(argv) {
42
- const { positionals, values } = parseArgs({
43
- args: argv,
44
- allowPositionals: true,
45
- options: {
46
- version: { type: 'string' },
47
- latest: { type: 'boolean' },
48
- 'dry-run': { type: 'boolean' },
49
- yes: { type: 'boolean' },
50
- h: { type: 'boolean' },
51
- help: { type: 'boolean' },
52
- },
53
- });
54
- // Extract command (first positional)
55
- const command = positionals[0] ?? null;
56
- // Extract options from parsed values
57
- // Note: -h sets key 'h', --help sets key 'help'
58
- const options = {
59
- ...(values.version !== undefined && { version: values.version }),
60
- ...(values.latest && { latest: true }),
61
- ...(values['dry-run'] && { dryRun: true }),
62
- ...(values.yes && { yes: true }),
63
- ...((values.help || values.h) && { help: true }),
64
- };
65
- const unknownFlags = [];
66
- return { command, options, unknownFlags };
67
- }
68
- export async function runMain(argv, fs = realFs) {
69
- try {
70
- const { command, options, unknownFlags } = parseCliArgs(argv);
71
- // Handle help flag at top level (before command dispatch)
72
- if (options.help) {
73
- console.log(HELP_TEXT);
74
- return 0;
75
- }
76
- // Handle unknown flags
77
- if (unknownFlags.length > 0) {
78
- console.error(`Error: unknown option(s): ${unknownFlags.join(', ')}`);
79
- console.error(USAGE_ERROR_TEXT);
80
- return 2;
81
- }
82
- // No command given
83
- if (!command) {
84
- console.error(USAGE_ERROR_TEXT);
85
- return 2;
86
- }
87
- switch (command) {
88
- case 'install': {
89
- const installOpts = {};
90
- if (options.version !== undefined)
91
- installOpts.version = options.version;
92
- if (options.dryRun)
93
- installOpts.dryRun = true;
94
- runInstall(installOpts, fs);
95
- return 0;
96
- }
97
- case 'status': {
98
- const statusResult = runStatus(fs);
99
- if (statusResult.installed) {
100
- const spec = statusResult.serverSpecifier ?? statusResult.tuiSpecifier;
101
- console.log(`opencode-rules-md is installed (${spec})`);
102
- }
103
- else {
104
- console.log('opencode-rules-md is not installed');
105
- }
106
- return 0;
107
- }
108
- default: {
109
- console.error(`Error: unknown command '${command}'`);
110
- console.error(USAGE_ERROR_TEXT);
111
- return 2;
112
- }
113
- }
114
- }
115
- catch (err) {
116
- const message = err instanceof Error ? err.message : String(err);
117
- console.error(`Error: ${message}`);
118
- return 1;
119
- }
120
- }
121
- // ---------------------------------------------------------------------------
122
- // Entry point
123
- // ---------------------------------------------------------------------------
124
- /**
125
- * Determine whether the current module is being executed as the main entry.
126
- * Uses realpathSync + pathToFileURL so symlinked invocations (e.g. npx)
127
- * are matched correctly.
128
- */
129
- function isInvokedAsMain() {
130
- if (!process.argv[1])
131
- return false;
132
- try {
133
- const realArgv = pathToFileURL(realpathSync(process.argv[1])).href;
134
- return import.meta.url === realArgv;
135
- }
136
- catch {
137
- try {
138
- return import.meta.url === pathToFileURL(process.argv[1]).href;
139
- }
140
- catch {
141
- return false;
142
- }
143
- }
144
- }
145
- // Only run if executed directly (not imported as a module)
146
- if (isInvokedAsMain()) {
147
- void runMain(process.argv.slice(2)).then(code => process.exit(code));
148
- }
149
- //# sourceMappingURL=main.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -1,26 +0,0 @@
1
- /**
2
- * Thin synchronous adapter over node:fs that implements the CliFs interface.
3
- * All production CLI disk I/O flows through this module — no direct node:fs
4
- * calls outside this file.
5
- */
6
- /**
7
- * Synchronous filesystem interface used by the CLI.
8
- * Tests supply an in-memory implementation; production uses this adapter.
9
- */
10
- export interface CliFs {
11
- readFileSync(path: string): string;
12
- writeFileSync(path: string, content: string, encoding?: string): void;
13
- renameSync(from: string, to: string): void;
14
- copyFileSync(from: string, to: string): void;
15
- unlinkSync(path: string): void;
16
- mkdirSync(path: string, opts?: {
17
- recursive?: boolean;
18
- }): void;
19
- readdirSync(path: string): string[];
20
- existsSync(path: string): boolean;
21
- }
22
- /**
23
- * Production CliFs implementation backed by node:fs (synchronous).
24
- */
25
- export declare const realFs: CliFs;
26
- //# sourceMappingURL=real-fs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"real-fs.d.ts","sourceRoot":"","sources":["../../../src/cli/real-fs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,KAqCpB,CAAC"}