docbridge 0.5.2 → 0.6.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/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0] - 2026-07-13
11
+
12
+ ### Added
13
+
14
+ - The npm package now runs on Node.js (>= 22) in addition to Bun: the CLI is
15
+ built for the Node target with a `#!/usr/bin/env node` shebang, so
16
+ `npx docbridge` works without installing Bun. Packaging smoke tests exercise
17
+ the CLI under both runtimes.
18
+
10
19
  ## [0.5.2] - 2026-07-12
11
20
 
12
21
  ### Fixed
@@ -185,7 +194,8 @@ Initial release of the SpecLink CLI.
185
194
  - `speclink check` command with `--root`, `--json`, and `--audit` options.
186
195
  - `speclink --version` (alias `-v`) and `speclink --help` (alias `-h`).
187
196
 
188
- [Unreleased]: https://github.com/salan70/docbridge/compare/v0.5.2...HEAD
197
+ [Unreleased]: https://github.com/salan70/docbridge/compare/v0.6.0...HEAD
198
+ [0.6.0]: https://github.com/salan70/docbridge/releases/tag/v0.6.0
189
199
  [0.5.2]: https://github.com/salan70/docbridge/releases/tag/v0.5.2
190
200
  [0.5.1]: https://github.com/salan70/docbridge/releases/tag/v0.5.1
191
201
  [0.5.0]: https://github.com/salan70/docbridge/releases/tag/v0.5.0
package/README.md CHANGED
@@ -13,10 +13,12 @@ files.
13
13
 
14
14
  ## Installation
15
15
 
16
- DocBridge is distributed as the `docbridge` npm package and is intended to run
17
- with Bun:
16
+ DocBridge is distributed as the `docbridge` npm package and runs on Node.js
17
+ (>= 22) and Bun:
18
18
 
19
19
  ```sh
20
+ npx docbridge check
21
+ # or
20
22
  bunx docbridge check
21
23
  ```
22
24
 
@@ -24,8 +26,7 @@ The current release is
24
26
  [v0.5.0](https://github.com/salan70/docbridge/releases/tag/v0.5.0), published
25
27
  as `docbridge@0.5.0` on npm.
26
28
 
27
- The npm package is Bun-only; Node.js runtime compatibility is not part of the
28
- initial distribution. The package includes prebuilt Swift and Dart scanner
29
+ The package includes prebuilt Swift and Dart scanner
29
30
  binaries for `darwin-arm64` and `linux-x64`. TypeScript and Markdown checks run
30
31
  without scanner binaries. Configured Swift or Dart projects on unsupported
31
32
  platforms report `code_scanner_unavailable` and name the supported platform
@@ -1,2 +1,2 @@
1
- d77294651a19f091422cc25d67131abfcf4de06d56a7e06116fed66a1ddf4097 speclink-swift-scanner
2
- 9874f1a3e29f2c4ebf2ccd23d9d91e5bf74c9e6b0ca00a117b265418f7f12eb9 speclink_dart_scanner
1
+ 3906f1b665d3af642c6c46f7ac0c066dee93f8724a5dd139955becc7dac62d4f speclink-swift-scanner
2
+ 33711635bbf663db5497ae88ee0f9ae181cdefdff67fce021986c106d4327f67 speclink_dart_scanner
@@ -1,2 +1,2 @@
1
- 762934bad01b5a33a6b14ff22b579dcb03169436fb01a6a672ab30719c70c294 speclink-swift-scanner
1
+ 72d604680e80c5eb6c30d778dcd9d6b70e45b7a9da907723b5fd36b6a77ef882 speclink-swift-scanner
2
2
  cfc22c423afaa1e42bef7c0c6b7de42fa54a3e11ca5baad518cd19e0c9c1258d speclink_dart_scanner
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
3
3
  var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
@@ -31,7 +31,7 @@ var __toESM = (mod, isNodeMode, target) => {
31
31
  return to;
32
32
  };
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
- var __require = import.meta.require;
34
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
35
35
 
36
36
  // node_modules/typescript/lib/typescript.js
37
37
  var require_typescript = __commonJS((exports, module) => {
@@ -4391,17 +4391,17 @@ m2: ${this.mapper2.__debugToString().split(`
4391
4391
  }
4392
4392
  let BoxCharacter;
4393
4393
  ((BoxCharacter2) => {
4394
- BoxCharacter2["lr"] = "\u2500";
4395
- BoxCharacter2["ud"] = "\u2502";
4396
- BoxCharacter2["dr"] = "\u256D";
4397
- BoxCharacter2["dl"] = "\u256E";
4398
- BoxCharacter2["ul"] = "\u256F";
4399
- BoxCharacter2["ur"] = "\u2570";
4400
- BoxCharacter2["udr"] = "\u251C";
4401
- BoxCharacter2["udl"] = "\u2524";
4402
- BoxCharacter2["dlr"] = "\u252C";
4403
- BoxCharacter2["ulr"] = "\u2534";
4404
- BoxCharacter2["udlr"] = "\u256B";
4394
+ BoxCharacter2["lr"] = "─";
4395
+ BoxCharacter2["ud"] = "│";
4396
+ BoxCharacter2["dr"] = "╭";
4397
+ BoxCharacter2["dl"] = "╮";
4398
+ BoxCharacter2["ul"] = "╯";
4399
+ BoxCharacter2["ur"] = "╰";
4400
+ BoxCharacter2["udr"] = "├";
4401
+ BoxCharacter2["udl"] = "┤";
4402
+ BoxCharacter2["dlr"] = "┬";
4403
+ BoxCharacter2["ulr"] = "┴";
4404
+ BoxCharacter2["udlr"] = "╫";
4405
4405
  })(BoxCharacter || (BoxCharacter = {}));
4406
4406
  let Connection;
4407
4407
  ((Connection2) => {
@@ -4652,7 +4652,7 @@ m2: ${this.mapper2.__debugToString().split(`
4652
4652
  for (let column = 0;column < columnCount; column++) {
4653
4653
  for (let lane = 0;lane < lanes.length; lane++) {
4654
4654
  const connector = connectors[column][lane];
4655
- const fill2 = connector & 4 ? "\u2500" : " ";
4655
+ const fill2 = connector & 4 ? "─" : " ";
4656
4656
  const node = grid[column][lane];
4657
4657
  if (!node) {
4658
4658
  if (column < columnCount - 1) {
@@ -4666,7 +4666,7 @@ m2: ${this.mapper2.__debugToString().split(`
4666
4666
  }
4667
4667
  }
4668
4668
  writeLane(lane, getBoxCharacter(connector));
4669
- writeLane(lane, connector & 8 && column < columnCount - 1 && !grid[column + 1][lane] ? "\u2500" : " ");
4669
+ writeLane(lane, connector & 8 && column < columnCount - 1 && !grid[column + 1][lane] ? "─" : " ");
4670
4670
  }
4671
4671
  }
4672
4672
  return `
@@ -4680,27 +4680,27 @@ ${lanes.join(`
4680
4680
  function getBoxCharacter(connector) {
4681
4681
  switch (connector) {
4682
4682
  case 3:
4683
- return "\u2502";
4683
+ return "│";
4684
4684
  case 12:
4685
- return "\u2500";
4685
+ return "─";
4686
4686
  case 5:
4687
- return "\u256F";
4687
+ return "╯";
4688
4688
  case 9:
4689
- return "\u2570";
4689
+ return "╰";
4690
4690
  case 6:
4691
- return "\u256E";
4691
+ return "╮";
4692
4692
  case 10:
4693
- return "\u256D";
4693
+ return "╭";
4694
4694
  case 7:
4695
- return "\u2524";
4695
+ return "┤";
4696
4696
  case 11:
4697
- return "\u251C";
4697
+ return "├";
4698
4698
  case 13:
4699
- return "\u2534";
4699
+ return "┴";
4700
4700
  case 14:
4701
- return "\u252C";
4701
+ return "┬";
4702
4702
  case 15:
4703
- return "\u256B";
4703
+ return "╫";
4704
4704
  }
4705
4705
  return " ";
4706
4706
  }
@@ -11766,7 +11766,7 @@ ${lanes.join(`
11766
11766
  Object.defineProperty(scanner2, "__debugShowCurrentPositionInText", {
11767
11767
  get: () => {
11768
11768
  const text2 = scanner2.getText();
11769
- return text2.slice(0, scanner2.getTokenFullStart()) + "\u2551" + text2.slice(scanner2.getTokenFullStart());
11769
+ return text2.slice(0, scanner2.getTokenFullStart()) + "║" + text2.slice(scanner2.getTokenFullStart());
11770
11770
  }
11771
11771
  });
11772
11772
  }
@@ -19270,7 +19270,7 @@ ${lanes.join(`
19270
19270
  "`": "\\`",
19271
19271
  "\u2028": "\\u2028",
19272
19272
  "\u2029": "\\u2029",
19273
- "\x85": "\\u0085",
19273
+ "…": "\\u0085",
19274
19274
  "\r\n": "\\r\\n"
19275
19275
  }));
19276
19276
  function encodeUtf16EscapeSequence(charCode) {
@@ -113100,7 +113100,7 @@ ${lanes.join(`
113100
113100
  return contains(screenStartingMessageCodes, diagnostic.code) ? newLine + newLine : newLine;
113101
113101
  }
113102
113102
  function getLocaleTimeString(system) {
113103
- return !system.now ? (/* @__PURE__ */ new Date()).toLocaleTimeString() : system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace("\u202F", " ");
113103
+ return !system.now ? (/* @__PURE__ */ new Date()).toLocaleTimeString() : system.now().toLocaleTimeString("en-US", { timeZone: "UTC" }).replace(" ", " ");
113104
113104
  }
113105
113105
  function createWatchStatusReporter(system, pretty) {
113106
113106
  return pretty ? (diagnostic, newLine, options) => {
@@ -168755,13 +168755,13 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
168755
168755
  });
168756
168756
 
168757
168757
  // src/cli/index.ts
168758
- import { readFileSync as readFileSync5, statSync as statSync4 } from "fs";
168759
- import { resolve as resolve4 } from "path";
168758
+ import { readFileSync as readFileSync5, statSync as statSync4 } from "node:fs";
168759
+ import { resolve as resolve4 } from "node:path";
168760
168760
  // package.json
168761
168761
  var package_default = {
168762
168762
  name: "docbridge",
168763
- version: "0.5.2",
168764
- description: "A Bun CLI that links Markdown specifications and code declarations.",
168763
+ version: "0.6.0",
168764
+ description: "A CLI that links Markdown specifications and code declarations. Runs on Node.js and Bun.",
168765
168765
  license: "MIT",
168766
168766
  type: "module",
168767
168767
  bin: {
@@ -168780,10 +168780,12 @@ var package_default = {
168780
168780
  "markdown",
168781
168781
  "specification",
168782
168782
  "cli",
168783
+ "node",
168783
168784
  "bun",
168784
168785
  "lsp"
168785
168786
  ],
168786
168787
  engines: {
168788
+ node: ">=22",
168787
168789
  bun: ">=1.1.31"
168788
168790
  },
168789
168791
  files: [
@@ -168808,13 +168810,13 @@ var package_default = {
168808
168810
  };
168809
168811
 
168810
168812
  // src/core/code-language.ts
168811
- import { existsSync, realpathSync } from "fs";
168812
- import { dirname, join as join3, resolve } from "path";
168813
- import { fileURLToPath } from "url";
168813
+ import { existsSync, realpathSync } from "node:fs";
168814
+ import { dirname, join as join3, resolve } from "node:path";
168815
+ import { fileURLToPath } from "node:url";
168814
168816
 
168815
168817
  // src/core/glob.ts
168816
- import { lstatSync, readFileSync, readdirSync } from "fs";
168817
- import { join } from "path";
168818
+ import { lstatSync, readFileSync, readdirSync } from "node:fs";
168819
+ import { join } from "node:path";
168818
168820
  var IGNORED_SEGMENTS = new Set(["node_modules", ".git"]);
168819
168821
  function validateGlobPattern(pattern) {
168820
168822
  if (pattern.length === 0) {
@@ -168951,9 +168953,10 @@ function escapeRegExpChar(char) {
168951
168953
  }
168952
168954
 
168953
168955
  // src/core/scanner-worker.ts
168954
- import { mkdirSync } from "fs";
168955
- import { tmpdir } from "os";
168956
- import { join as join2 } from "path";
168956
+ import { spawnSync } from "node:child_process";
168957
+ import { mkdirSync } from "node:fs";
168958
+ import { tmpdir } from "node:os";
168959
+ import { join as join2 } from "node:path";
168957
168960
  function invokeScannerWorker(request, command, run = runScannerWorkerProcess) {
168958
168961
  const processResult = run({
168959
168962
  command,
@@ -169009,21 +169012,32 @@ function runScannerWorkerProcess(input) {
169009
169012
  try {
169010
169013
  const moduleCachePath = clangModuleCachePath();
169011
169014
  mkdirSync(moduleCachePath, { recursive: true });
169012
- const result = Bun.spawnSync({
169013
- cmd: input.command,
169015
+ const [executable = "", ...args] = input.command;
169016
+ const result = spawnSync(executable, args, {
169014
169017
  env: {
169015
- ...Bun.env,
169018
+ ...process.env,
169016
169019
  CLANG_MODULE_CACHE_PATH: moduleCachePath
169017
169020
  },
169018
- stdin: new TextEncoder().encode(input.stdin),
169019
- stdout: "pipe",
169020
- stderr: "pipe"
169021
+ input: input.stdin,
169022
+ encoding: "utf8",
169023
+ maxBuffer: 1024 * 1024 * 1024
169021
169024
  });
169025
+ const stderr = result.stderr ?? "";
169026
+ if (result.error !== undefined) {
169027
+ return { ok: false, error: result.error, stderr };
169028
+ }
169029
+ if (result.status === null) {
169030
+ return {
169031
+ ok: false,
169032
+ error: new Error(`worker terminated by signal ${result.signal ?? "unknown"}`),
169033
+ stderr
169034
+ };
169035
+ }
169022
169036
  return {
169023
169037
  ok: true,
169024
- exitCode: result.exitCode,
169025
- stdout: new TextDecoder().decode(result.stdout),
169026
- stderr: new TextDecoder().decode(result.stderr)
169038
+ exitCode: result.status,
169039
+ stdout: result.stdout ?? "",
169040
+ stderr
169027
169041
  };
169028
169042
  } catch (error) {
169029
169043
  return { ok: false, error, stderr: "" };
@@ -169716,8 +169730,8 @@ function scannerUnavailableDiagnostic2(language, reason) {
169716
169730
  }
169717
169731
 
169718
169732
  // src/core/config.ts
169719
- import { readFileSync as readFileSync2 } from "fs";
169720
- import { join as join4 } from "path";
169733
+ import { readFileSync as readFileSync2 } from "node:fs";
169734
+ import { join as join4 } from "node:path";
169721
169735
  var CONFIG_FILE_NAME = "docbridge.config.json";
169722
169736
  var EMPTY_CONFIG = {
169723
169737
  include: { code: {}, docs: [] }
@@ -170299,7 +170313,7 @@ function flushDanglingWith(pending, diagnostics, message) {
170299
170313
  }
170300
170314
 
170301
170315
  // src/core/related.ts
170302
- import { isAbsolute, relative } from "path";
170316
+ import { isAbsolute, relative } from "node:path";
170303
170317
  function normalizeChangedPaths(projectRoot, paths) {
170304
170318
  const normalized = new Set;
170305
170319
  for (const raw of paths) {
@@ -170607,7 +170621,7 @@ function relationshipDiagnostic(code, source, target, message, link) {
170607
170621
  var MAX_SECTION_LENGTH = 2000;
170608
170622
  var TRUNCATION_MARKER = `
170609
170623
 
170610
- \u2026`;
170624
+ …`;
170611
170625
  var atxHeadingPattern2 = /^ {0,3}(#{1,6})(?:[ \t]+.*)?$/;
170612
170626
  var fenceOpenPattern2 = /^ {0,3}(?:`{3,}|~{3,})/;
170613
170627
  function extractDocSection(content, headingLine) {
@@ -171214,7 +171228,7 @@ function comparePairs(left, right) {
171214
171228
  }
171215
171229
 
171216
171230
  // src/lsp/server.ts
171217
- import { fileURLToPath as fileURLToPath3 } from "url";
171231
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
171218
171232
 
171219
171233
  // src/lsp/transport.ts
171220
171234
  var HEADER_SEPARATOR = `\r
@@ -171604,8 +171618,8 @@ function emptyState() {
171604
171618
  }
171605
171619
 
171606
171620
  // src/lsp/paths.ts
171607
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "path";
171608
- import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
171621
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep } from "node:path";
171622
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
171609
171623
  function uriToRelativePath(projectRoot, uri) {
171610
171624
  let absolute;
171611
171625
  try {
@@ -171893,12 +171907,12 @@ import {
171893
171907
  readFileSync as readFileSync4,
171894
171908
  statSync as statSync3,
171895
171909
  writeFileSync
171896
- } from "fs";
171897
- import { join as join7, resolve as resolve3 } from "path";
171910
+ } from "node:fs";
171911
+ import { join as join7, resolve as resolve3 } from "node:path";
171898
171912
 
171899
171913
  // src/core/init-discovery.ts
171900
- import { existsSync as existsSync2, readdirSync as readdirSync2, statSync } from "fs";
171901
- import { basename, dirname as dirname2, join as join5 } from "path";
171914
+ import { existsSync as existsSync2, readdirSync as readdirSync2, statSync } from "node:fs";
171915
+ import { basename, dirname as dirname2, join as join5 } from "node:path";
171902
171916
  var HIGH_CONFIDENCE_DIR_NAMES = new Set([
171903
171917
  "docs/specs",
171904
171918
  "specs",
@@ -172154,9 +172168,9 @@ import {
172154
172168
  readFileSync as readFileSync3,
172155
172169
  realpathSync as realpathSync2,
172156
172170
  statSync as statSync2
172157
- } from "fs";
172158
- import { dirname as dirname3, join as join6, relative as relative4 } from "path";
172159
- import { fileURLToPath as fileURLToPath4 } from "url";
172171
+ } from "node:fs";
172172
+ import { dirname as dirname3, join as join6, relative as relative4 } from "node:path";
172173
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
172160
172174
  var CONFIG_FILE_NAME2 = "docbridge.config.json";
172161
172175
  var INIT_SKILL_NAMES = [
172162
172176
  "docbridge-adopt",
@@ -173137,8 +173151,8 @@ function run(argv, io = {
173137
173151
  return 1;
173138
173152
  }
173139
173153
  }
173140
- if (import.meta.main) {
173141
- process.exitCode = run(Bun.argv.slice(2));
173154
+ if (__require.main == __require.module) {
173155
+ process.exitCode = run(process.argv.slice(2));
173142
173156
  }
173143
173157
  export {
173144
173158
  run,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docbridge",
3
- "version": "0.5.2",
4
- "description": "A Bun CLI that links Markdown specifications and code declarations.",
3
+ "version": "0.6.0",
4
+ "description": "A CLI that links Markdown specifications and code declarations. Runs on Node.js and Bun.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
@@ -20,10 +20,12 @@
20
20
  "markdown",
21
21
  "specification",
22
22
  "cli",
23
+ "node",
23
24
  "bun",
24
25
  "lsp"
25
26
  ],
26
27
  "engines": {
28
+ "node": ">=22",
27
29
  "bun": ">=1.1.31"
28
30
  },
29
31
  "files": [