@miyaoka/fsss 0.2.2 → 0.3.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/dist/cli.d.ts CHANGED
@@ -5,6 +5,7 @@ interface CLIOptions {
5
5
  name: string;
6
6
  commandsDir?: string;
7
7
  autoEnv?: AutoEnvConfig;
8
+ defaultCommand?: string;
8
9
  }
9
10
  interface CLI {
10
11
  run: () => Promise<void>;
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAaA,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,GAAG;IACX,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAgFD,iBAAS,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,GAAG,CA4G3C;AAED,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAkBA,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,GAAG;IACX,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAgFD,iBAAS,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,GAAG,CAgJ3C;AAED,OAAO,EAAE,SAAS,EAAE,CAAC;AACrB,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC"}
package/dist/codegen.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { join, relative } from "node:path";
3
- import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
4
- import { parseArgs } from "node:util";
5
- var PLUGINS_DIR_NAME = "_plugins", PLUGIN_FILE_EXTENSION = ".ts", INTERFACE_NAME_PATTERN = /export\s+interface\s+(\w+)/g;
6
- async function findAllPluginFiles(t) {
2
+ import { join as e, relative as t } from "node:path";
3
+ import { mkdir as n, readFile as r, readdir as i, writeFile as a } from "node:fs/promises";
4
+ import { parseArgs as o } from "node:util";
5
+ var s = "_plugins", c = ".ts", l = /export\s+interface\s+(\w+)/g;
6
+ async function u(t) {
7
7
  let n = [];
8
8
  async function r(t) {
9
- let a = await readdir(t, { withFileTypes: !0 });
9
+ let a = await i(t, { withFileTypes: !0 });
10
10
  for (let o of a) {
11
11
  if (!o.isDirectory()) continue;
12
- let a = join(t, o.name);
13
- if (o.name === PLUGINS_DIR_NAME) {
14
- let t = await readdir(a, { withFileTypes: !0 });
15
- for (let r of t) r.isFile() && r.name.endsWith(PLUGIN_FILE_EXTENSION) && n.push(join(a, r.name));
12
+ let a = e(t, o.name);
13
+ if (o.name === s) {
14
+ let t = await i(a, { withFileTypes: !0 });
15
+ for (let r of t) r.isFile() && r.name.endsWith(c) && n.push(e(a, r.name));
16
16
  continue;
17
17
  }
18
18
  await r(a);
@@ -20,17 +20,17 @@ async function findAllPluginFiles(t) {
20
20
  }
21
21
  return await r(t), n.sort();
22
22
  }
23
- async function extractInterfaceNames(e) {
24
- let t = await readFile(e, "utf-8"), n = [], i = INTERFACE_NAME_PATTERN.exec(t);
25
- for (; i !== null;) n.push(i[1]), i = INTERFACE_NAME_PATTERN.exec(t);
23
+ async function d(e) {
24
+ let t = await r(e, "utf-8"), n = [], i = l.exec(t);
25
+ for (; i !== null;) n.push(i[1]), i = l.exec(t);
26
26
  return n;
27
27
  }
28
- async function generateExtensionsType(r, i) {
29
- let o = await findAllPluginFiles(r), s = [];
28
+ async function f(r, i) {
29
+ let o = await u(r), s = [];
30
30
  for (let e of o) {
31
- let n = await extractInterfaceNames(e);
31
+ let n = await d(e);
32
32
  if (n.length === 0) continue;
33
- let r = relative(i, e).replace(/\.ts$/, ""), a = r.startsWith(".") ? r : `./${r}`;
33
+ let r = t(i, e).replace(/\.ts$/, ""), a = r.startsWith(".") ? r : `./${r}`;
34
34
  s.push({
35
35
  importPath: a,
36
36
  interfaceNames: n
@@ -46,12 +46,12 @@ async function generateExtensionsType(r, i) {
46
46
  let e = s.flatMap((e) => e.interfaceNames);
47
47
  c.push("", "declare module \"@miyaoka/fsss\" {", ` interface Extensions extends ${e.join(", ")} {}`, "}", "");
48
48
  }
49
- await mkdir(i, { recursive: !0 });
50
- let l = join(i, "extensions.d.ts");
51
- await writeFile(l, c.join("\n"), "utf-8"), console.log(`Generated ${l}`);
49
+ await n(i, { recursive: !0 });
50
+ let l = e(i, "extensions.d.ts");
51
+ await a(l, c.join("\n"), "utf-8"), console.log(`Generated ${l}`);
52
52
  }
53
- var { values } = parseArgs({ options: {
53
+ var { values: p } = o({ options: {
54
54
  commandsDir: { type: "string" },
55
55
  outDir: { type: "string" }
56
56
  } });
57
- (values.commandsDir === void 0 || values.outDir === void 0) && (console.error("Usage: bun run codegen.ts --commandsDir <path> --outDir <path>"), process.exit(1)), await generateExtensionsType(values.commandsDir, values.outDir);
57
+ (p.commandsDir === void 0 || p.outDir === void 0) && (console.error("Usage: bun run codegen.ts --commandsDir <path> --outDir <path>"), process.exit(1)), await f(p.commandsDir, p.outDir);
package/dist/help.d.ts CHANGED
@@ -15,6 +15,16 @@ interface SubcommandHelpConfig {
15
15
  }
16
16
  declare function generateSubcommandHelp(config: SubcommandHelpConfig): string;
17
17
  declare function generateValidationErrorHelp(helpText: string, errors: string[]): string;
18
- export { generateHelp, generateSubcommandHelp, generateValidationErrorHelp };
19
- export type { HelpConfig, SubcommandHelpConfig };
18
+ interface DefaultCommandHelpConfig {
19
+ programName: string;
20
+ defaultCommandName: string;
21
+ commandPath: string[];
22
+ description?: string;
23
+ argsDefs?: ArgsDefs;
24
+ envPrefix?: string;
25
+ availableEntries: AvailableEntry[];
26
+ }
27
+ declare function generateDefaultCommandHelp(config: DefaultCommandHelpConfig): string;
28
+ export { generateDefaultCommandHelp, generateHelp, generateSubcommandHelp, generateValidationErrorHelp, };
29
+ export type { DefaultCommandHelpConfig, HelpConfig, SubcommandHelpConfig };
20
30
  //# sourceMappingURL=help.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAU,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGhD,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkED,iBAAS,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA8DhD;AAGD,UAAU,oBAAoB;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,iBAAS,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAuBpE;AAID,iBAAS,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAG/E;AAED,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,CAAC;AAC7E,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAU,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGhD,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkED,iBAAS,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA8DhD;AAGD,UAAU,oBAAoB;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,iBAAS,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAuBpE;AAID,iBAAS,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAG/E;AAID,UAAU,wBAAwB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,cAAc,EAAE,CAAC;CACpC;AAED,iBAAS,0BAA0B,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAiE5E;AAED,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,GAC5B,CAAC;AACF,YAAY,EAAE,wBAAwB,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,95 +1,95 @@
1
- import { join, relative, resolve } from "node:path";
2
- import { ZodBoolean, ZodError, ZodNumber, z } from "zod";
3
- import { readFile, readdir, stat } from "node:fs/promises";
4
- import { homedir } from "node:os";
5
- function isRecord(e) {
1
+ import { join as e, relative as t, resolve as n } from "node:path";
2
+ import { ZodBoolean as r, ZodError as i, ZodNumber as a, z as o } from "zod";
3
+ import { readFile as s, readdir as c, stat as l } from "node:fs/promises";
4
+ import { homedir as u } from "node:os";
5
+ function d(e) {
6
6
  return typeof e == "object" && !!e;
7
7
  }
8
- function getByDotPath(e, t) {
8
+ function f(e, t) {
9
9
  let n = t.split("."), r = e;
10
10
  for (let e of n) {
11
- if (!isRecord(r)) return;
11
+ if (!d(r)) return;
12
12
  r = r[e];
13
13
  }
14
14
  return r;
15
15
  }
16
- async function loadConfig(e) {
16
+ async function p(e) {
17
17
  try {
18
- let t = await readFile(e, "utf-8");
18
+ let t = await s(e, "utf-8");
19
19
  return JSON.parse(t);
20
20
  } catch {
21
21
  return;
22
22
  }
23
23
  }
24
- function deepMerge(e, t) {
24
+ function m(e, t) {
25
25
  let n = { ...e };
26
26
  for (let [e, r] of Object.entries(t)) {
27
27
  let t = n[e];
28
- if (isRecord(t) && isRecord(r)) {
29
- n[e] = deepMerge(t, r);
28
+ if (d(t) && d(r)) {
29
+ n[e] = m(t, r);
30
30
  continue;
31
31
  }
32
32
  n[e] = r;
33
33
  }
34
34
  return n;
35
35
  }
36
- function resolveConfigPaths(t, n) {
36
+ function h(t, n) {
37
37
  let r = [];
38
- return r.push(join(homedir(), ".config", t, "config.json")), r.push(join(process.cwd(), `${t}.config.json`)), n !== void 0 && r.push(n), r;
38
+ return r.push(e(u(), ".config", t, "config.json")), r.push(e(process.cwd(), `${t}.config.json`)), n !== void 0 && r.push(n), r;
39
39
  }
40
- async function loadMergedConfig(e, t) {
41
- let n = resolveConfigPaths(e, t), r;
40
+ async function ee(e, t) {
41
+ let n = h(e, t), r;
42
42
  for (let e of n) {
43
- let t = await loadConfig(e);
43
+ let t = await p(e);
44
44
  if (t !== void 0) {
45
45
  if (r === void 0) {
46
46
  r = t;
47
47
  continue;
48
48
  }
49
- r = deepMerge(r, t);
49
+ r = m(r, t);
50
50
  }
51
51
  }
52
52
  return r;
53
53
  }
54
- function deriveEnvName(e, t, n) {
54
+ function g(e, t, n) {
55
55
  return [
56
56
  e,
57
57
  ...t,
58
58
  n
59
59
  ].join("_").toUpperCase();
60
60
  }
61
- function deriveConfigPath(e, t) {
61
+ function _(e, t) {
62
62
  return [...e, t].join(".");
63
63
  }
64
- function isBooleanSchema(e) {
65
- return e instanceof ZodBoolean;
64
+ function v(e) {
65
+ return e instanceof r;
66
66
  }
67
- function isNumberSchema(e) {
68
- return e instanceof ZodNumber;
67
+ function te(e) {
68
+ return e instanceof a;
69
69
  }
70
- var INDENT = " ", COLUMN_GAP = 2;
71
- function resolveEnvNameForHelp(e, t, n, r) {
70
+ var y = " ", b = 2;
71
+ function x(e, t, n, r) {
72
72
  if (e.env !== void 0) return e.env;
73
- if (t !== void 0) return deriveEnvName(t, n, r);
73
+ if (t !== void 0) return g(t, n, r);
74
74
  }
75
- function formatOptionMeta(e, t) {
75
+ function S(e, t) {
76
76
  let n = [];
77
77
  return t !== void 0 && n.push(`env: ${t}`), "default" in e && e.default !== void 0 && n.push(`default: ${String(e.default)}`), n.length === 0 ? "" : ` (${n.join(", ")})`;
78
78
  }
79
- function formatOptionLine(e, t, n, r) {
80
- let i = isBooleanSchema(t.type) ? "" : ` <${e}>`, a = `${t.alias === void 0 ? " " : `-${t.alias}, `}--${e}${i}`, o = resolveEnvNameForHelp(t, n, r, e);
79
+ function C(e, t, n, r) {
80
+ let i = v(t.type) ? "" : ` <${e}>`, a = `${t.alias === void 0 ? " " : `-${t.alias}, `}--${e}${i}`, o = x(t, n, r, e);
81
81
  return {
82
82
  left: a,
83
- right: `${t.description}${formatOptionMeta(t, o)}`
83
+ right: `${t.description}${S(t, o)}`
84
84
  };
85
85
  }
86
- function formatHelpLine() {
86
+ function w() {
87
87
  return {
88
88
  left: "-h, --help",
89
89
  right: "ヘルプを表示する"
90
90
  };
91
91
  }
92
- function generateHelp(e) {
92
+ function T(e) {
93
93
  let { programName: t, commandPath: n, description: r, argsDefs: i, envPrefix: a } = e, o = [];
94
94
  r !== void 0 && (o.push(r), o.push(""));
95
95
  let s = [t, ...n];
@@ -105,41 +105,70 @@ function generateHelp(e) {
105
105
  let c = Object.entries(i).filter(([, e]) => e.positional !== !0);
106
106
  if (c.length === 0) {
107
107
  o.push("Options:");
108
- let e = formatHelpLine();
109
- return o.push(`${INDENT}${e.left} ${e.right}`), o.join("\n");
108
+ let e = w();
109
+ return o.push(`${y}${e.left} ${e.right}`), o.join("\n");
110
110
  }
111
111
  o.push("Options:");
112
- let l = c.map(([e, t]) => formatOptionLine(e, t, a, n));
113
- l.push(formatHelpLine());
112
+ let l = c.map(([e, t]) => C(e, t, a, n));
113
+ l.push(w());
114
114
  let u = Math.max(...l.map((e) => e.left.length));
115
115
  for (let e of l) {
116
- let t = " ".repeat(u - e.left.length + COLUMN_GAP);
117
- o.push(`${INDENT}${e.left}${t}${e.right}`);
116
+ let t = " ".repeat(u - e.left.length + b);
117
+ o.push(`${y}${e.left}${t}${e.right}`);
118
118
  }
119
119
  return o.join("\n");
120
120
  }
121
- function generateSubcommandHelp(e) {
121
+ function E(e) {
122
122
  let { programName: t, commandPath: n, availableEntries: r } = e, i = [], a = [t, ...n].join(" ");
123
123
  if (i.push(`Usage: ${a} <command>`), i.push(""), r.length === 0) return i.push("No available commands."), i.join("\n");
124
124
  i.push("Available commands:");
125
125
  for (let e of r) {
126
126
  if (e.isDynamic) {
127
- i.push(`${INDENT}<${e.paramName}>`);
127
+ i.push(`${y}<${e.paramName}>`);
128
128
  continue;
129
129
  }
130
- i.push(`${INDENT}${e.name}`);
130
+ i.push(`${y}${e.name}`);
131
131
  }
132
132
  return i.join("\n");
133
133
  }
134
- function generateValidationErrorHelp(e, t) {
134
+ function D(e, t) {
135
135
  return [
136
136
  `Error: ${t.join(", ")}`,
137
137
  "",
138
138
  e
139
139
  ].join("\n");
140
140
  }
141
- var LONG_FLAG_PREFIX = "--", SHORT_FLAG_PREFIX = "-", DOUBLE_DASH = "--", NEGATION_PREFIX = "--no-", BOOLEAN_TRUE = "true", BOOLEAN_FALSE = "false";
142
- function addFlag(e, t, n) {
141
+ function O(e) {
142
+ let { programName: t, defaultCommandName: n, commandPath: r, description: i, argsDefs: a, envPrefix: o, availableEntries: s } = e, c = [];
143
+ if (i !== void 0 && (c.push(i), c.push("")), a !== void 0 && Object.entries(a).some(([, e]) => e.positional !== !0) ? c.push(`Usage: ${t} [options]`) : c.push(`Usage: ${t}`), c.push(` ${t} <command>`), c.push(""), a !== void 0) {
144
+ let e = Object.entries(a).filter(([, e]) => e.positional !== !0);
145
+ if (e.length > 0) {
146
+ c.push("Options:");
147
+ let t = e.map(([e, t]) => C(e, t, o, r));
148
+ t.push(w());
149
+ let n = Math.max(...t.map((e) => e.left.length));
150
+ for (let e of t) {
151
+ let t = " ".repeat(n - e.left.length + b);
152
+ c.push(`${y}${e.left}${t}${e.right}`);
153
+ }
154
+ c.push("");
155
+ }
156
+ }
157
+ if (s.length > 0) {
158
+ c.push("Available commands:");
159
+ for (let e of s) {
160
+ if (e.isDynamic) {
161
+ c.push(`${y}<${e.paramName}>`);
162
+ continue;
163
+ }
164
+ let t = e.name === n ? " (default)" : "";
165
+ c.push(`${y}${e.name}${t}`);
166
+ }
167
+ }
168
+ return c.join("\n");
169
+ }
170
+ var k = "--", A = "-", ne = "--", re = "--no-", j = "true", M = "false";
171
+ function N(e, t, n) {
143
172
  let r = e.get(t);
144
173
  if (r) {
145
174
  r.push(n);
@@ -147,51 +176,51 @@ function addFlag(e, t, n) {
147
176
  }
148
177
  e.set(t, [n]);
149
178
  }
150
- function isNextTokenAvailable(e, t) {
151
- return t + 1 >= e.length ? !1 : !e[t + 1].startsWith(SHORT_FLAG_PREFIX);
179
+ function P(e, t) {
180
+ return t + 1 >= e.length ? !1 : !e[t + 1].startsWith(A);
152
181
  }
153
- function parseTokens(e, t) {
154
- let n = /* @__PURE__ */ new Map(), r = [], i = [], a = 0;
182
+ function F(e, t) {
183
+ let n = new Map(), r = [], i = [], a = 0;
155
184
  for (; a < e.length;) {
156
185
  let o = e[a];
157
- if (o === DOUBLE_DASH) {
186
+ if (o === ne) {
158
187
  i = e.slice(a + 1);
159
188
  break;
160
189
  }
161
- if (o.startsWith(NEGATION_PREFIX)) {
162
- addFlag(n, o.slice(5), BOOLEAN_FALSE), a++;
190
+ if (o.startsWith(re)) {
191
+ N(n, o.slice(5), M), a++;
163
192
  continue;
164
193
  }
165
- if (o.startsWith(LONG_FLAG_PREFIX) && o.includes("=")) {
194
+ if (o.startsWith(k) && o.includes("=")) {
166
195
  let e = o.indexOf("=");
167
- addFlag(n, o.slice(2, e), o.slice(e + 1)), a++;
196
+ N(n, o.slice(2, e), o.slice(e + 1)), a++;
168
197
  continue;
169
198
  }
170
- if (o.startsWith(LONG_FLAG_PREFIX)) {
199
+ if (o.startsWith(k)) {
171
200
  let r = o.slice(2);
172
201
  if (t.booleanFlags.has(r)) {
173
- addFlag(n, r, BOOLEAN_TRUE), a++;
202
+ N(n, r, j), a++;
174
203
  continue;
175
204
  }
176
- if (isNextTokenAvailable(e, a)) {
177
- addFlag(n, r, e[a + 1]), a += 2;
205
+ if (P(e, a)) {
206
+ N(n, r, e[a + 1]), a += 2;
178
207
  continue;
179
208
  }
180
209
  throw Error(`Flag --${r} requires a value`);
181
210
  }
182
- if (o.startsWith(SHORT_FLAG_PREFIX) && !o.startsWith(LONG_FLAG_PREFIX) && o.includes("=")) {
211
+ if (o.startsWith(A) && !o.startsWith(k) && o.includes("=")) {
183
212
  let e = o.indexOf("="), r = o.slice(1, e), i = o.slice(e + 1);
184
- addFlag(n, t.aliases.get(r) ?? r, i), a++;
213
+ N(n, t.aliases.get(r) ?? r, i), a++;
185
214
  continue;
186
215
  }
187
- if (o.startsWith(SHORT_FLAG_PREFIX) && !o.startsWith(LONG_FLAG_PREFIX)) {
216
+ if (o.startsWith(A) && !o.startsWith(k)) {
188
217
  let r = o.slice(1), i = t.aliases.get(r) ?? r;
189
218
  if (t.booleanFlags.has(i)) {
190
- addFlag(n, i, BOOLEAN_TRUE), a++;
219
+ N(n, i, j), a++;
191
220
  continue;
192
221
  }
193
- if (isNextTokenAvailable(e, a)) {
194
- addFlag(n, i, e[a + 1]), a += 2;
222
+ if (P(e, a)) {
223
+ N(n, i, e[a + 1]), a += 2;
195
224
  continue;
196
225
  }
197
226
  throw Error(`Flag -${r} requires a value`);
@@ -204,11 +233,11 @@ function parseTokens(e, t) {
204
233
  doubleDashArgs: i
205
234
  };
206
235
  }
207
- var PLUGINS_DIR_NAME = "_plugins", PLUGIN_FILE_EXTENSION = ".ts";
208
- function definePlugin(e) {
236
+ var I = "_plugins", L = ".ts";
237
+ function R(e) {
209
238
  return e;
210
239
  }
211
- async function resolvePlugins(e, t) {
240
+ async function z(e, t) {
212
241
  let n = {}, r = [];
213
242
  for (let i of e) {
214
243
  let e = await i(t);
@@ -219,7 +248,7 @@ async function resolvePlugins(e, t) {
219
248
  middlewares: r
220
249
  };
221
250
  }
222
- function buildMiddlewareChain(e, t) {
251
+ function B(e, t) {
223
252
  let n = t;
224
253
  for (let t = e.length - 1; t >= 0; t--) {
225
254
  let r = e[t], i = n;
@@ -227,29 +256,29 @@ function buildMiddlewareChain(e, t) {
227
256
  }
228
257
  return n;
229
258
  }
230
- async function scanPluginsAlongPath(t, n) {
259
+ async function V(t, n) {
231
260
  let r = [];
232
261
  for (let n of t) {
233
- let t = join(n, PLUGINS_DIR_NAME), i;
262
+ let t = e(n, I), i;
234
263
  try {
235
- i = await readdir(t, { withFileTypes: !0 });
264
+ i = await c(t, { withFileTypes: !0 });
236
265
  } catch {
237
266
  continue;
238
267
  }
239
- let a = i.filter((e) => e.isFile() && e.name.endsWith(PLUGIN_FILE_EXTENSION)).sort((e, t) => e.name.localeCompare(t.name));
268
+ let a = i.filter((e) => e.isFile() && e.name.endsWith(L)).sort((e, t) => e.name.localeCompare(t.name));
240
269
  for (let n of a) {
241
- let i = join(t, n.name), a = (await import(i)).default;
270
+ let i = e(t, n.name), a = (await import(i)).default;
242
271
  if (a === void 0) throw Error(`Plugin file ${i} does not have a default export`);
243
272
  r.push(a);
244
273
  }
245
274
  }
246
- return resolvePlugins(r, n);
275
+ return z(r, n);
247
276
  }
248
- function resolveEnvName(e, t, n, r) {
277
+ function H(e, t, n, r) {
249
278
  if (e !== void 0) return e;
250
- if (t !== void 0) return deriveEnvName(t, n, r);
279
+ if (t !== void 0) return g(t, n, r);
251
280
  }
252
- function resolveValues(e) {
281
+ function U(e) {
253
282
  let { argsDefs: t, parsedTokens: n, env: r, config: i, commandPath: a, envPrefix: o } = e, s = {}, c = 0;
254
283
  for (let [e, l] of Object.entries(t)) {
255
284
  let t = n.flags.get(e);
@@ -265,7 +294,7 @@ function resolveValues(e) {
265
294
  s[e] = n.positionals[c], c++;
266
295
  continue;
267
296
  }
268
- let u = resolveEnvName(l.env, o, a, e);
297
+ let u = H(l.env, o, a, e);
269
298
  if (u !== void 0) {
270
299
  let t = r[u];
271
300
  if (t !== void 0) {
@@ -274,7 +303,7 @@ function resolveValues(e) {
274
303
  }
275
304
  }
276
305
  if (i !== void 0) {
277
- let t = getByDotPath(i, l.config ?? deriveConfigPath(a, e));
306
+ let t = f(i, l.config ?? _(a, e));
278
307
  if (t !== void 0) {
279
308
  s[e] = t;
280
309
  continue;
@@ -287,21 +316,21 @@ function resolveValues(e) {
287
316
  }
288
317
  return s;
289
318
  }
290
- var DYNAMIC_SEGMENT_PATTERN = /^\[(.+)]$/, COMMAND_FILE_EXTENSION = ".ts", INDEX_FILE_NAME = "index", INTERNAL_PREFIX = "_";
291
- async function fileExists(e) {
319
+ var W = /^\[(.+)]$/, G = ".ts", K = "index", q = "_";
320
+ async function J(e) {
292
321
  try {
293
- return (await stat(e)).isFile();
322
+ return (await l(e)).isFile();
294
323
  } catch {
295
324
  return !1;
296
325
  }
297
326
  }
298
- async function listAvailableEntries(e) {
327
+ async function Y(e) {
299
328
  try {
300
- let t = await readdir(e, { withFileTypes: !0 }), n = [];
301
- for (let e of t) if (!e.name.startsWith(INTERNAL_PREFIX)) {
302
- if (e.isFile() && e.name.endsWith(COMMAND_FILE_EXTENSION)) {
329
+ let t = await c(e, { withFileTypes: !0 }), n = [];
330
+ for (let e of t) if (!e.name.startsWith(q)) {
331
+ if (e.isFile() && e.name.endsWith(G)) {
303
332
  let t = e.name.slice(0, -3);
304
- if (t === INDEX_FILE_NAME) continue;
333
+ if (t === K) continue;
305
334
  n.push({
306
335
  name: t,
307
336
  isDynamic: !1
@@ -309,7 +338,7 @@ async function listAvailableEntries(e) {
309
338
  continue;
310
339
  }
311
340
  if (e.isDirectory()) {
312
- let t = e.name.match(DYNAMIC_SEGMENT_PATTERN);
341
+ let t = e.name.match(W);
313
342
  if (t !== null) {
314
343
  n.push({
315
344
  name: e.name,
@@ -329,82 +358,82 @@ async function listAvailableEntries(e) {
329
358
  return [];
330
359
  }
331
360
  }
332
- async function resolveRoute(t, r) {
333
- let i = resolve(t), a = {}, o = [i], s = 0;
361
+ async function X(t, r) {
362
+ let i = n(t), a = {}, o = [i], s = 0;
334
363
  for (let t = 0; t < r.length; t++) {
335
364
  let n = r[t];
336
365
  if (n.startsWith("-")) break;
337
- let l = await readdir(i, { withFileTypes: !0 }), u = n + COMMAND_FILE_EXTENSION, d = l.find((e) => e.isFile() && e.name === u);
366
+ let l = await c(i, { withFileTypes: !0 }), u = n + G, d = l.find((e) => e.isFile() && e.name === u);
338
367
  if (d) return s = t + 1, {
339
368
  kind: "resolved",
340
- filePath: join(i, d.name),
369
+ filePath: e(i, d.name),
341
370
  params: a,
342
371
  remainingTokens: r.slice(s),
343
372
  traversedDirs: o
344
373
  };
345
374
  let f = l.find((e) => e.isDirectory() && e.name === n);
346
375
  if (f) {
347
- i = join(i, f.name), o.push(i), s = t + 1;
376
+ i = e(i, f.name), o.push(i), s = t + 1;
348
377
  continue;
349
378
  }
350
379
  let p, m = l.find((e) => {
351
380
  if (!e.isDirectory()) return !1;
352
- let t = e.name.match(DYNAMIC_SEGMENT_PATTERN);
381
+ let t = e.name.match(W);
353
382
  return t === null ? !1 : (p = t[1], !0);
354
383
  });
355
384
  if (m && p !== void 0) {
356
- a[p] = n, i = join(i, m.name), o.push(i), s = t + 1;
385
+ a[p] = n, i = e(i, m.name), o.push(i), s = t + 1;
357
386
  continue;
358
387
  }
359
388
  break;
360
389
  }
361
- let l = join(i, INDEX_FILE_NAME + COMMAND_FILE_EXTENSION);
362
- if (await fileExists(l)) return {
390
+ let l = e(i, K + G);
391
+ if (await J(l)) return {
363
392
  kind: "resolved",
364
393
  filePath: l,
365
394
  params: a,
366
395
  remainingTokens: r.slice(s),
367
396
  traversedDirs: o
368
397
  };
369
- let u = await listAvailableEntries(i);
398
+ let u = await Y(i);
370
399
  return {
371
400
  kind: "unresolved",
372
401
  stoppedDir: i,
373
402
  availableEntries: u
374
403
  };
375
404
  }
376
- function wrapWithStringPreprocess(e) {
377
- return isBooleanSchema(e) ? z.preprocess((e) => typeof e == "string" ? e === "true" || e === "1" : e, e) : isNumberSchema(e) ? z.preprocess((e) => typeof e == "string" ? Number(e) : e, e) : e;
405
+ function ie(e) {
406
+ return v(e) ? o.preprocess((e) => typeof e == "string" ? e === "true" || e === "1" : e, e) : te(e) ? o.preprocess((e) => typeof e == "string" ? Number(e) : e, e) : e;
378
407
  }
379
- function validateArgs(e, t) {
408
+ function ae(e, t) {
380
409
  let n = {};
381
410
  for (let [t, r] of Object.entries(e)) {
382
- let e = wrapWithStringPreprocess(r.type);
411
+ let e = ie(r.type);
383
412
  if (r.multiple === !0) {
384
- n[t] = z.array(e);
413
+ n[t] = o.array(e);
385
414
  continue;
386
415
  }
387
416
  n[t] = e;
388
417
  }
389
- return z.object(n).parse(t);
418
+ return o.object(n).parse(t);
390
419
  }
391
- var DEFAULT_COMMANDS_DIR = "commands", ARGV_SKIP = 2, EXIT_CODE_ERROR = 1;
392
- function buildParserConfig(e) {
393
- let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map();
394
- for (let [r, i] of Object.entries(e)) isBooleanSchema(i.type) && t.add(r), i.alias !== void 0 && n.set(i.alias, r);
420
+ var oe = "commands", se = 2, Z = 1;
421
+ function Q(e) {
422
+ let t = new Set(), n = new Map();
423
+ for (let [r, i] of Object.entries(e)) v(i.type) && t.add(r), i.alias !== void 0 && n.set(i.alias, r);
395
424
  return {
396
425
  booleanFlags: t,
397
426
  aliases: n
398
427
  };
399
428
  }
400
- function extractCommandPath(e, r) {
401
- return relative(resolve(e), r).replace(/\.ts$/, "").split("/").filter((e) => e !== "index" && !e.startsWith("["));
429
+ function $(e, r) {
430
+ return t(n(e), r).replace(/\.ts$/, "").split("/").filter((e) => e !== "index" && !e.startsWith("["));
402
431
  }
403
- function extractPartialCommandPath(e, r) {
404
- let i = relative(resolve(e), r);
432
+ function ce(e, r) {
433
+ let i = t(n(e), r);
405
434
  return i === "" || i === "." ? [] : i.split("/").filter((e) => !e.startsWith("["));
406
435
  }
407
- function extractFrameworkFlags(e) {
436
+ function le(e) {
408
437
  let t, n = [];
409
438
  for (let r = 0; r < e.length; r++) {
410
439
  let i = e[r];
@@ -425,65 +454,84 @@ function extractFrameworkFlags(e) {
425
454
  remainingTokens: n
426
455
  };
427
456
  }
428
- function createCLI(e) {
429
- let t = e.commandsDir ?? DEFAULT_COMMANDS_DIR, n = e.name, r = e.autoEnv?.prefix;
430
- async function a() {
431
- let { configPath: e, remainingTokens: a } = extractFrameworkFlags(process.argv.slice(ARGV_SKIP)), o = await resolveRoute(t, a);
432
- if (o.kind === "unresolved") {
433
- let e = generateSubcommandHelp({
434
- programName: n,
435
- commandPath: extractPartialCommandPath(t, o.stoppedDir),
436
- availableEntries: o.availableEntries
457
+ function ue(e) {
458
+ let t = e.commandsDir ?? oe, r = e.name, a = e.autoEnv?.prefix, o = e.defaultCommand;
459
+ async function s() {
460
+ let { configPath: e, remainingTokens: s } = le(process.argv.slice(se)), c = await X(t, s);
461
+ if (c.kind === "unresolved") if (n(c.stoppedDir) === n(t) && o !== void 0) {
462
+ if (s.includes("--help") || s.includes("-h")) {
463
+ let e = await X(t, [o]);
464
+ if (e.kind === "unresolved") throw Error(`defaultCommand "${o}" does not match any command file`);
465
+ let n = (await import(e.filePath)).default, i = n.args ?? {}, s = O({
466
+ programName: r,
467
+ defaultCommandName: o,
468
+ commandPath: $(t, e.filePath),
469
+ description: n.description,
470
+ argsDefs: Object.keys(i).length > 0 ? i : void 0,
471
+ envPrefix: a,
472
+ availableEntries: c.availableEntries
473
+ });
474
+ console.log(s);
475
+ return;
476
+ }
477
+ let e = await X(t, [o, ...s]);
478
+ if (e.kind === "unresolved") throw Error(`defaultCommand "${o}" does not match any command file`);
479
+ c = e;
480
+ } else {
481
+ let e = E({
482
+ programName: r,
483
+ commandPath: ce(t, c.stoppedDir),
484
+ availableEntries: c.availableEntries
437
485
  });
438
486
  console.log(e);
439
487
  return;
440
488
  }
441
- let s = (await import(o.filePath)).default, c = s.args ?? {}, l = extractCommandPath(t, o.filePath), u = generateHelp({
442
- programName: n,
443
- commandPath: l,
444
- description: s.description,
445
- argsDefs: Object.keys(c).length > 0 ? c : void 0,
446
- envPrefix: r
489
+ let l = (await import(c.filePath)).default, u = l.args ?? {}, d = $(t, c.filePath), f = T({
490
+ programName: r,
491
+ commandPath: d,
492
+ description: l.description,
493
+ argsDefs: Object.keys(u).length > 0 ? u : void 0,
494
+ envPrefix: a
447
495
  });
448
- if (o.remainingTokens.includes("--help") || o.remainingTokens.includes("-h")) {
449
- console.log(u);
496
+ if (c.remainingTokens.includes("--help") || c.remainingTokens.includes("-h")) {
497
+ console.log(f);
450
498
  return;
451
499
  }
452
- let d = buildParserConfig(c), f;
500
+ let p = Q(u), m;
453
501
  try {
454
- let t = parseTokens(o.remainingTokens, d), i = await loadMergedConfig(n, e);
455
- f = validateArgs(c, resolveValues({
456
- argsDefs: c,
502
+ let t = F(c.remainingTokens, p), n = await ee(r, e);
503
+ m = ae(u, U({
504
+ argsDefs: u,
457
505
  parsedTokens: t,
458
506
  env: process.env,
459
- config: i,
460
- commandPath: l,
461
- envPrefix: r
507
+ config: n,
508
+ commandPath: d,
509
+ envPrefix: a
462
510
  }));
463
511
  } catch (e) {
464
- if (e instanceof ZodError) {
512
+ if (e instanceof i) {
465
513
  let t = e.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
466
- console.error(generateValidationErrorHelp(u, t)), process.exit(EXIT_CODE_ERROR);
514
+ console.error(D(f, t)), process.exit(Z);
467
515
  }
468
- throw e instanceof Error && (console.error(generateValidationErrorHelp(u, [e.message])), process.exit(EXIT_CODE_ERROR)), e;
516
+ throw e instanceof Error && (console.error(D(f, [e.message])), process.exit(Z)), e;
469
517
  }
470
- let { extensions: p, middlewares: m } = await scanPluginsAlongPath(o.traversedDirs, { cliName: n }), h = {
471
- commandPath: l,
472
- params: o.params,
473
- args: f,
474
- extensions: p
518
+ let { extensions: h, middlewares: g } = await V(c.traversedDirs, { cliName: r }), _ = {
519
+ commandPath: d,
520
+ params: c.params,
521
+ args: m,
522
+ extensions: h
475
523
  };
476
- await buildMiddlewareChain(m, async (e) => {
477
- await s.run({
524
+ await B(g, async (e) => {
525
+ await l.run({
478
526
  params: e.params,
479
527
  args: e.args,
480
528
  extensions: e.extensions
481
529
  });
482
- })(h);
530
+ })(_);
483
531
  }
484
- return { run: a };
532
+ return { run: s };
485
533
  }
486
- function defineCommand(e) {
534
+ function de(e) {
487
535
  return e;
488
536
  }
489
- export { createCLI, defineCommand, definePlugin };
537
+ export { ue as createCLI, de as defineCommand, R as definePlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miyaoka/fsss",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "A CLI framework where your file structure becomes your command structure, and a single schema gives you typed values whether they come from flags, env vars, or config files.",
5
5
  "type": "module",
6
6
  "author": "miyaoka",
@@ -37,13 +37,13 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@tsconfig/node24": "24.0.4",
40
- "@types/bun": "1.3.9",
41
- "oxfmt": "0.31.0",
42
- "oxlint": "1.46.0",
43
- "oxlint-tsgolint": "0.12.0",
40
+ "@types/bun": "1.3.10",
41
+ "oxfmt": "0.36.0",
42
+ "oxlint": "1.51.0",
43
+ "oxlint-tsgolint": "0.16.0",
44
44
  "typescript": "5.9.3",
45
45
  "unplugin-dts": "1.0.0-beta.6",
46
- "vite": "8.0.0-beta.13"
46
+ "vite": "8.0.0-beta.16"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "vite build",