@optique/discover 1.2.0-dev.2287 → 1.2.0-dev.2290

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 CHANGED
@@ -149,6 +149,8 @@ By default, Deno and Bun discover *.ts*, *.mts*, *.js*, and *.mjs* files.
149
149
  Node.js discovers *.js*, *.mjs*, and *.cjs* files, plus *.ts*, *.mts*, and
150
150
  *.cts* when it reports native TypeScript support or runs with a recognized
151
151
  TypeScript loader. TypeScript declaration files such as *.d.ts* are ignored.
152
+ Co-located test files whose names end in `.test` or `.spec` before the
153
+ extension (such as `user.test.ts`) are ignored too.
152
154
  Entry files named `index` map to their containing command path, so
153
155
  *commands/index.ts* defines the root command and *commands/user/index.ts*
154
156
  defines `user`. Use `entryFileName` to choose another entry name or disable
package/dist/cli.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  const require_chunk = require('./chunk-CUT6urMc.cjs');
3
3
  require('./command-C-NgG0KJ.cjs');
4
- require('./src-C3_a7SFM.cjs');
5
- const require_generator = require('./generator-CyGtPDkA.cjs');
4
+ require('./src-B4qtzrut.cjs');
5
+ const require_generator = require('./generator-DNRlBDyF.cjs');
6
6
  const require_main_check = require('./main-check-CwunSNpK.cjs');
7
7
  const __optique_core_constructs = require_chunk.__toESM(require("@optique/core/constructs"));
8
8
  const __optique_core_message = require_chunk.__toESM(require("@optique/core/message"));
@@ -15,7 +15,7 @@ const node_process = require_chunk.__toESM(require("node:process"));
15
15
 
16
16
  //#region deno.json
17
17
  var name = "@optique/discover";
18
- var version = "1.2.0-dev.2287+86d0fd20";
18
+ var version = "1.2.0-dev.2290+15f1cc9b";
19
19
  var license = "MIT";
20
20
  var exports$1 = {
21
21
  ".": "./src/index.ts",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import "./command-9sgrJtwh.js";
3
- import "./src-wHLRsXWK.js";
4
- import { watchCommandsModule, writeCommandsModule } from "./generator-DDSCS6PX.js";
3
+ import "./src-CKPihqEZ.js";
4
+ import { watchCommandsModule, writeCommandsModule } from "./generator-B-dPfnHz.js";
5
5
  import { isMainModuleUrl } from "./main-check-mMnKfUZs.js";
6
6
  import { object } from "@optique/core/constructs";
7
7
  import { message } from "@optique/core/message";
@@ -14,7 +14,7 @@ import process from "node:process";
14
14
 
15
15
  //#region deno.json
16
16
  var name = "@optique/discover";
17
- var version = "1.2.0-dev.2287+86d0fd20";
17
+ var version = "1.2.0-dev.2290+15f1cc9b";
18
18
  var license = "MIT";
19
19
  var exports = {
20
20
  ".": "./src/index.ts",
@@ -1,4 +1,4 @@
1
- import { getDefaultExtensions } from "./src-wHLRsXWK.js";
1
+ import { getDefaultExtensions } from "./src-CKPihqEZ.js";
2
2
  import { mkdir, readdir, realpath, stat, writeFile } from "node:fs/promises";
3
3
  import { dirname, posix, relative, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
@@ -170,7 +170,7 @@ async function collectCommandFiles(dir, extensions, excludedFile, activeDirs = /
170
170
  const path = resolve(dir, entry.name);
171
171
  const entryType = await getCommandFileEntryType(path, entry);
172
172
  if (entryType === "directory") files.push(...await collectCommandFiles(path, extensions, excludedFile, nextActiveDirs));
173
- else if (entryType === "file" && path !== excludedFile && !isDeclarationFile(entry.name) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
173
+ else if (entryType === "file" && path !== excludedFile && !isDeclarationFile(entry.name) && !isTestFile(entry.name, extensions) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
174
174
  }
175
175
  return files;
176
176
  }
@@ -190,6 +190,18 @@ async function getCommandFileEntryType(path, entry) {
190
190
  function isDeclarationFile(fileName) {
191
191
  return /\.d\.[cm]?ts$/.test(fileName);
192
192
  }
193
+ /**
194
+ * Checks whether a file name belongs to a co-located test or spec module, such
195
+ * as *hello.test.ts* or *hello.spec.js*. The `.test`/`.spec` marker is matched
196
+ * against the suffix that precedes the configured command extension, so a file
197
+ * named *test.ts* or *latest.ts* stays an ordinary command.
198
+ */
199
+ function isTestFile(fileName, extensions) {
200
+ const matchedExtension = extensions.find((ext) => fileName.endsWith(ext));
201
+ if (matchedExtension == null) return false;
202
+ const base = fileName.slice(0, -matchedExtension.length);
203
+ return base.endsWith(".test") || base.endsWith(".spec");
204
+ }
193
205
  function rejectDuplicateCommandPaths(files, options) {
194
206
  const entryFileName = options.entryFileName ?? "index";
195
207
  const seen = /* @__PURE__ */ new Map();
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_src = require('./src-C3_a7SFM.cjs');
2
+ const require_src = require('./src-B4qtzrut.cjs');
3
3
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
4
  const node_path = require_chunk.__toESM(require("node:path"));
5
5
  const node_url = require_chunk.__toESM(require("node:url"));
@@ -171,7 +171,7 @@ async function collectCommandFiles(dir, extensions, excludedFile, activeDirs = /
171
171
  const path = (0, node_path.resolve)(dir, entry.name);
172
172
  const entryType = await getCommandFileEntryType(path, entry);
173
173
  if (entryType === "directory") files.push(...await collectCommandFiles(path, extensions, excludedFile, nextActiveDirs));
174
- else if (entryType === "file" && path !== excludedFile && !isDeclarationFile(entry.name) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
174
+ else if (entryType === "file" && path !== excludedFile && !isDeclarationFile(entry.name) && !isTestFile(entry.name, extensions) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
175
175
  }
176
176
  return files;
177
177
  }
@@ -191,6 +191,18 @@ async function getCommandFileEntryType(path, entry) {
191
191
  function isDeclarationFile(fileName) {
192
192
  return /\.d\.[cm]?ts$/.test(fileName);
193
193
  }
194
+ /**
195
+ * Checks whether a file name belongs to a co-located test or spec module, such
196
+ * as *hello.test.ts* or *hello.spec.js*. The `.test`/`.spec` marker is matched
197
+ * against the suffix that precedes the configured command extension, so a file
198
+ * named *test.ts* or *latest.ts* stays an ordinary command.
199
+ */
200
+ function isTestFile(fileName, extensions) {
201
+ const matchedExtension = extensions.find((ext) => fileName.endsWith(ext));
202
+ if (matchedExtension == null) return false;
203
+ const base = fileName.slice(0, -matchedExtension.length);
204
+ return base.endsWith(".test") || base.endsWith(".spec");
205
+ }
194
206
  function rejectDuplicateCommandPaths(files, options) {
195
207
  const entryFileName = options.entryFileName ?? "index";
196
208
  const seen = /* @__PURE__ */ new Map();
@@ -1,6 +1,6 @@
1
1
  require('./command-C-NgG0KJ.cjs');
2
- require('./src-C3_a7SFM.cjs');
3
- const require_generator = require('./generator-CyGtPDkA.cjs');
2
+ require('./src-B4qtzrut.cjs');
3
+ const require_generator = require('./generator-DNRlBDyF.cjs');
4
4
 
5
5
  exports.generateCommandsModule = require_generator.generateCommandsModule;
6
6
  exports.watchCommandsModule = require_generator.watchCommandsModule;
package/dist/generator.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./command-9sgrJtwh.js";
2
- import "./src-wHLRsXWK.js";
3
- import { generateCommandsModule, watchCommandsModule, writeCommandsModule } from "./generator-DDSCS6PX.js";
2
+ import "./src-CKPihqEZ.js";
3
+ import { generateCommandsModule, watchCommandsModule, writeCommandsModule } from "./generator-B-dPfnHz.js";
4
4
 
5
5
  export { generateCommandsModule, watchCommandsModule, writeCommandsModule };
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  const require_command = require('./command-C-NgG0KJ.cjs');
2
- const require_src = require('./src-C3_a7SFM.cjs');
2
+ const require_src = require('./src-B4qtzrut.cjs');
3
3
 
4
4
  exports.commandsFromModules = require_src.commandsFromModules;
5
5
  exports.createProgramParser = require_src.createProgramParser;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { defineCommand, isCommand } from "./command-9sgrJtwh.js";
2
- import { commandsFromModules, createProgramParser, discoverCommands, getDefaultExtensions, runProgram } from "./src-wHLRsXWK.js";
2
+ import { commandsFromModules, createProgramParser, discoverCommands, getDefaultExtensions, runProgram } from "./src-CKPihqEZ.js";
3
3
 
4
4
  export { commandsFromModules, createProgramParser, defineCommand, discoverCommands, getDefaultExtensions, isCommand, runProgram };
@@ -99,7 +99,8 @@ function commandsFromModules(modules, options = {}) {
99
99
  const seen = /* @__PURE__ */ new Map();
100
100
  const discovered = [];
101
101
  for (const modulePath of modulePaths) {
102
- if (isDeclarationFile(node_path.posix.basename(modulePath)) || !extensions.some((ext) => modulePath.endsWith(ext))) continue;
102
+ const moduleBaseName = node_path.posix.basename(modulePath);
103
+ if (isDeclarationFile(moduleBaseName) || isTestFile(moduleBaseName, extensions) || !extensions.some((ext) => modulePath.endsWith(ext))) continue;
103
104
  const path = commandPathFromModulePath(base, modulePath, extensions, entryFileName);
104
105
  const key = commandPathKey(path);
105
106
  const previous = seen.get(key);
@@ -260,7 +261,7 @@ async function collectCommandFiles(dir, extensions, activeDirs = /* @__PURE__ */
260
261
  const path = (0, node_path.resolve)(dir, entry.name);
261
262
  const entryType = await getCommandFileEntryType(path, entry);
262
263
  if (entryType === "directory") files.push(...await collectCommandFiles(path, extensions, nextActiveDirs));
263
- else if (entryType === "file" && !isDeclarationFile(entry.name) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
264
+ else if (entryType === "file" && !isDeclarationFile(entry.name) && !isTestFile(entry.name, extensions) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
264
265
  }
265
266
  return files;
266
267
  }
@@ -280,6 +281,12 @@ async function getCommandFileEntryType(path, entry) {
280
281
  function isDeclarationFile(fileName) {
281
282
  return /\.d\.[cm]?ts$/.test(fileName);
282
283
  }
284
+ function isTestFile(fileName, extensions) {
285
+ const matchedExtension = extensions.find((ext) => fileName.endsWith(ext));
286
+ if (matchedExtension == null) return false;
287
+ const base = fileName.slice(0, -matchedExtension.length);
288
+ return base.endsWith(".test") || base.endsWith(".spec");
289
+ }
283
290
  function commandPathFromFile(rootDir, filePath, extensions, entryFileName) {
284
291
  const withoutExtension = stripCommandExtension(filePath, extensions);
285
292
  const relativePath = (0, node_path.relative)(rootDir, withoutExtension);
@@ -98,7 +98,8 @@ function commandsFromModules(modules, options = {}) {
98
98
  const seen = /* @__PURE__ */ new Map();
99
99
  const discovered = [];
100
100
  for (const modulePath of modulePaths) {
101
- if (isDeclarationFile(posix.basename(modulePath)) || !extensions.some((ext) => modulePath.endsWith(ext))) continue;
101
+ const moduleBaseName = posix.basename(modulePath);
102
+ if (isDeclarationFile(moduleBaseName) || isTestFile(moduleBaseName, extensions) || !extensions.some((ext) => modulePath.endsWith(ext))) continue;
102
103
  const path = commandPathFromModulePath(base, modulePath, extensions, entryFileName);
103
104
  const key = commandPathKey(path);
104
105
  const previous = seen.get(key);
@@ -259,7 +260,7 @@ async function collectCommandFiles(dir, extensions, activeDirs = /* @__PURE__ */
259
260
  const path = resolve(dir, entry.name);
260
261
  const entryType = await getCommandFileEntryType(path, entry);
261
262
  if (entryType === "directory") files.push(...await collectCommandFiles(path, extensions, nextActiveDirs));
262
- else if (entryType === "file" && !isDeclarationFile(entry.name) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
263
+ else if (entryType === "file" && !isDeclarationFile(entry.name) && !isTestFile(entry.name, extensions) && extensions.some((ext) => entry.name.endsWith(ext))) files.push(path);
263
264
  }
264
265
  return files;
265
266
  }
@@ -279,6 +280,12 @@ async function getCommandFileEntryType(path, entry) {
279
280
  function isDeclarationFile(fileName) {
280
281
  return /\.d\.[cm]?ts$/.test(fileName);
281
282
  }
283
+ function isTestFile(fileName, extensions) {
284
+ const matchedExtension = extensions.find((ext) => fileName.endsWith(ext));
285
+ if (matchedExtension == null) return false;
286
+ const base = fileName.slice(0, -matchedExtension.length);
287
+ return base.endsWith(".test") || base.endsWith(".spec");
288
+ }
282
289
  function commandPathFromFile(rootDir, filePath, extensions, entryFileName) {
283
290
  const withoutExtension = stripCommandExtension(filePath, extensions);
284
291
  const relativePath = relative(rootDir, withoutExtension);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/discover",
3
- "version": "1.2.0-dev.2287",
3
+ "version": "1.2.0-dev.2290",
4
4
  "description": "Runtime-aware command discovery for Optique CLI programs",
5
5
  "keywords": [
6
6
  "CLI",
@@ -83,8 +83,8 @@
83
83
  "optique-discover": "./dist/cli.js"
84
84
  },
85
85
  "dependencies": {
86
- "@optique/core": "1.2.0-dev.2287+86d0fd20",
87
- "@optique/run": "1.2.0-dev.2287+86d0fd20"
86
+ "@optique/core": "1.2.0-dev.2290+15f1cc9b",
87
+ "@optique/run": "1.2.0-dev.2290+15f1cc9b"
88
88
  },
89
89
  "devDependencies": {
90
90
  "@types/node": "^24.0.0",