@wrongstack/techstack 0.309.1 → 0.310.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.
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier C
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class CppAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, _options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier A
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class DartAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier A
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class DotNetAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier B
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class ElixirAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, _options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier A
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class GoAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -1,6 +1,6 @@
1
1
  /** Gradle dependency inventory for Groovy/Kotlin DSL and dependency locking. */
2
2
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
3
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
3
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
4
4
  export declare class GradleAdapter implements EcosystemAdapter {
5
5
  readonly ecosystem: EcosystemId;
6
6
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -8,7 +8,6 @@
8
8
  * @see docs/specs/techstack-sdd.md §3.2, §6
9
9
  */
10
10
  import type { DependencyObservation, EcosystemId, Evidence, Workspace } from '../types.js';
11
- export { fileExists, fileExistsAsync, lockfileEvidence, manifestEvidence, resolveIn, workspaceRoot, } from './paths.js';
12
11
  /**
13
12
  * Options passed to inventory() controlling what data the adapter collects.
14
13
  */
@@ -8,7 +8,7 @@
8
8
  * @see docs/specs/techstack-sdd.md §6 Tier B
9
9
  */
10
10
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
11
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
11
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
12
12
  export declare class MavenAdapter implements EcosystemAdapter {
13
13
  readonly ecosystem: EcosystemId;
14
14
  inventory(workspace: Workspace, _options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -9,7 +9,7 @@
9
9
  * @see docs/specs/techstack-sdd.md §6 Tier A
10
10
  */
11
11
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
12
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
12
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
13
13
  export declare class NpmAdapter implements EcosystemAdapter {
14
14
  readonly ecosystem: EcosystemId;
15
15
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier A
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class PhpAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * Supports: pip, pipenv, poetry, uv — determined by manifest/lockfile presence.
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  /**
12
12
  * Parse poetry.lock to extract resolved versions.
13
13
  * Format:
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier B
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class RubyAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, _options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -7,7 +7,7 @@
7
7
  * @see docs/specs/techstack-sdd.md §6 Tier A
8
8
  */
9
9
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
10
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
10
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
11
11
  export declare class RustAdapter implements EcosystemAdapter {
12
12
  readonly ecosystem: EcosystemId;
13
13
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
@@ -1,6 +1,6 @@
1
1
  /** Swift Package Manager manifest and resolved-file adapter. */
2
2
  import type { DependencyObservation, EcosystemId, Workspace } from '../types.js';
3
- import { type EcosystemAdapter, type InventoryOptions } from './interface.js';
3
+ import type { EcosystemAdapter, InventoryOptions } from './interface.js';
4
4
  export declare class SwiftAdapter implements EcosystemAdapter {
5
5
  readonly ecosystem: EcosystemId;
6
6
  inventory(workspace: Workspace, options: InventoryOptions): Promise<readonly DependencyObservation[]>;
package/dist/index.js CHANGED
@@ -750,7 +750,8 @@ function parsePipfileLock(content) {
750
750
  const json = JSON.parse(content);
751
751
  for (const section of ["default", "develop"]) {
752
752
  for (const [name, entry] of Object.entries(json[section] ?? {})) {
753
- if (entry.version?.startsWith("==")) versions.set(normalizePkgName(name), entry.version.slice(2));
753
+ if (entry.version?.startsWith("=="))
754
+ versions.set(normalizePkgName(name), entry.version.slice(2));
754
755
  }
755
756
  }
756
757
  } catch {
@@ -850,7 +851,11 @@ var PythonAdapter = class {
850
851
  if (manifestEv) evidence.push(manifestEv);
851
852
  if (lockEv && locked) evidence.push(lockEv);
852
853
  if (evidence.length === 0) {
853
- evidence.push({ kind: "manifest", source: dep.source, retrievedAt: (/* @__PURE__ */ new Date()).toISOString() });
854
+ evidence.push({
855
+ kind: "manifest",
856
+ source: dep.source,
857
+ retrievedAt: (/* @__PURE__ */ new Date()).toISOString()
858
+ });
854
859
  }
855
860
  const status = dep.constraint && (dep.constraint.startsWith("file:") || dep.constraint.startsWith("-e")) ? "local_path" : dep.constraint?.startsWith("git+") ? "git_dependency" : "current";
856
861
  observations.push({
@@ -1229,7 +1234,7 @@ var GoAdapter = class {
1229
1234
  var goAdapter = new GoAdapter();
1230
1235
 
1231
1236
  // src/adapters/dotnet.ts
1232
- import { readFile as readFile3, readdir } from "node:fs/promises";
1237
+ import { readdir, readFile as readFile3 } from "node:fs/promises";
1233
1238
  import { join as join3 } from "node:path";
1234
1239
  function parseCsproj(content) {
1235
1240
  const refs = [];
@@ -1339,7 +1344,8 @@ function parseComposerLock(content) {
1339
1344
  }
1340
1345
  function statusForComposerSpec(spec) {
1341
1346
  if (spec.startsWith("file:") || spec.startsWith("path:")) return "local_path";
1342
- if (spec.startsWith("git@") || spec.startsWith("git:") || spec.startsWith("http")) return "git_dependency";
1347
+ if (spec.startsWith("git@") || spec.startsWith("git:") || spec.startsWith("http"))
1348
+ return "git_dependency";
1343
1349
  return "current";
1344
1350
  }
1345
1351
  function sourceTypeForComposerSpec(spec) {
@@ -1520,7 +1526,8 @@ var DartAdapter = class {
1520
1526
  for (const [name, constraint] of deps) {
1521
1527
  if (seen.has(name)) continue;
1522
1528
  seen.add(name);
1523
- if (constraint === "*" || constraint === "sdk:flutter" || constraint.startsWith("{")) continue;
1529
+ if (constraint === "*" || constraint === "sdk:flutter" || constraint.startsWith("{"))
1530
+ continue;
1524
1531
  const locked = lockVersions.get(name);
1525
1532
  let status = "current";
1526
1533
  let sourceType = "registry";
@@ -1535,7 +1542,11 @@ var DartAdapter = class {
1535
1542
  sourceType = "path";
1536
1543
  }
1537
1544
  const isRegistry = sourceType === "registry";
1538
- const purl = isRegistry && (locked || constraint) ? buildPurl({ type: "dart", name, version: locked || constraint.replace(/^[\^~>=<\s]+/, "") }) : isRegistry ? buildPurl({ type: "dart", name }) : void 0;
1545
+ const purl = isRegistry && (locked || constraint) ? buildPurl({
1546
+ type: "dart",
1547
+ name,
1548
+ version: locked || constraint.replace(/^[\^~>=<\s]+/, "")
1549
+ }) : isRegistry ? buildPurl({ type: "dart", name }) : void 0;
1539
1550
  const evidence = [manifestEv];
1540
1551
  if (lockEv && locked) evidence.push(lockEv);
1541
1552
  observations.push({
@@ -1602,7 +1613,10 @@ function parsePomDependencies(xml) {
1602
1613
  const groupId = xmlTagValue(block, "groupId");
1603
1614
  const artifactId = xmlTagValue(block, "artifactId");
1604
1615
  const rawVersion = xmlTagValue(block, "version") ?? (groupId && artifactId ? managed.get(`${groupId}:${artifactId}`) : void 0);
1605
- const version = rawVersion?.replace(/\$\{([^}]+)\}/g, (_whole, key) => properties.get(key) ?? `\${${key}}`);
1616
+ const version = rawVersion?.replace(
1617
+ /\$\{([^}]+)\}/g,
1618
+ (_whole, key) => properties.get(key) ?? `\${${key}}`
1619
+ );
1606
1620
  const scope = xmlTagValue(block, "scope");
1607
1621
  if (groupId && artifactId) {
1608
1622
  deps.push({ groupId, artifactId, version, scope });
@@ -1700,7 +1714,10 @@ function parseVersionCatalog(content) {
1700
1714
  if (!module) continue;
1701
1715
  const version = /\bversion\s*=\s*["']([^"']+)["']/.exec(value)?.[1];
1702
1716
  const ref = /\bversion\.ref\s*=\s*["']([^"']+)["']/.exec(value)?.[1];
1703
- libraries.set(key.replace(/-/g, "."), `${module}:${version ?? (ref ? versions.get(ref) ?? "" : "")}`.replace(/:$/, ""));
1717
+ libraries.set(
1718
+ key.replace(/-/g, "."),
1719
+ `${module}:${version ?? (ref ? versions.get(ref) ?? "" : "")}`.replace(/:$/, "")
1720
+ );
1704
1721
  }
1705
1722
  }
1706
1723
  return libraries;
@@ -1714,7 +1731,11 @@ function parseGradleManifest(content, catalog) {
1714
1731
  if (!configuration || !value) continue;
1715
1732
  const [group, artifact, version] = value.split(":");
1716
1733
  if (!group || !artifact) continue;
1717
- deps.push({ name: `${group}:${artifact}`, requested: version, scope: scopeForConfiguration(configuration) });
1734
+ deps.push({
1735
+ name: `${group}:${artifact}`,
1736
+ requested: version,
1737
+ scope: scopeForConfiguration(configuration)
1738
+ });
1718
1739
  }
1719
1740
  const aliasRegex = /\b(implementation|api|compileOnly|runtimeOnly|testImplementation|testRuntimeOnly)\s*\(\s*libs\.([\w.]+)\s*\)/g;
1720
1741
  for (const match of content.matchAll(aliasRegex)) {
@@ -1725,7 +1746,11 @@ function parseGradleManifest(content, catalog) {
1725
1746
  if (!coordinate) continue;
1726
1747
  const [group, artifact, version] = coordinate.split(":");
1727
1748
  if (!group || !artifact) continue;
1728
- deps.push({ name: `${group}:${artifact}`, requested: version, scope: scopeForConfiguration(configuration) });
1749
+ deps.push({
1750
+ name: `${group}:${artifact}`,
1751
+ requested: version,
1752
+ scope: scopeForConfiguration(configuration)
1753
+ });
1729
1754
  }
1730
1755
  return deps;
1731
1756
  }
@@ -1734,7 +1759,8 @@ function parseGradleLock(content) {
1734
1759
  for (const raw of content.split("\n")) {
1735
1760
  const line = raw.replace(/#.*/, "").trim();
1736
1761
  const coordinate = /^([^:\s=]+):([^:\s=]+):([^=\s]+)(?:=.*)?$/.exec(line);
1737
- if (coordinate?.[1] && coordinate[2] && coordinate[3]) locked.set(`${coordinate[1]}:${coordinate[2]}`, coordinate[3]);
1762
+ if (coordinate?.[1] && coordinate[2] && coordinate[3])
1763
+ locked.set(`${coordinate[1]}:${coordinate[2]}`, coordinate[3]);
1738
1764
  }
1739
1765
  return locked;
1740
1766
  }
@@ -1746,7 +1772,10 @@ var GradleAdapter = class {
1746
1772
  if (!await fileExistsAsync(resolveIn(root, manifestPath))) return [];
1747
1773
  const catalogPath = join6(root, "gradle", "libs.versions.toml");
1748
1774
  const catalog = await fileExistsAsync(catalogPath) ? parseVersionCatalog(await readFile4(catalogPath, "utf8")) : /* @__PURE__ */ new Map();
1749
- const direct = parseGradleManifest(await readFile4(resolveIn(root, manifestPath), "utf8"), catalog);
1775
+ const direct = parseGradleManifest(
1776
+ await readFile4(resolveIn(root, manifestPath), "utf8"),
1777
+ catalog
1778
+ );
1750
1779
  const lockPath = workspace.lockfiles.find((path) => path.endsWith("gradle.lockfile")) ?? join6(root, "gradle.lockfile");
1751
1780
  const locked = await fileExistsAsync(resolveIn(root, lockPath)) ? parseGradleLock(await readFile4(resolveIn(root, lockPath), "utf8")) : /* @__PURE__ */ new Map();
1752
1781
  const manifestEv = manifestEvidence(resolveIn(root, manifestPath));
@@ -1905,7 +1934,11 @@ function parsePackageResolved(content) {
1905
1934
  const json = JSON.parse(content);
1906
1935
  for (const pin of json.pins ?? json.object?.pins ?? []) {
1907
1936
  const identity = (pin.identity ?? pin.package ?? (pin.location ? identityFromLocation(pin.location) : void 0) ?? (pin.repositoryURL ? identityFromLocation(pin.repositoryURL) : void 0))?.toLowerCase();
1908
- if (identity) pins.set(identity, { ...pin.state?.version ? { version: pin.state.version } : {}, ...pin.state?.revision ? { revision: pin.state.revision } : {} });
1937
+ if (identity)
1938
+ pins.set(identity, {
1939
+ ...pin.state?.version ? { version: pin.state.version } : {},
1940
+ ...pin.state?.revision ? { revision: pin.state.revision } : {}
1941
+ });
1909
1942
  }
1910
1943
  } catch {
1911
1944
  }
@@ -4528,14 +4561,14 @@ function createToolSearch(options = {}) {
4528
4561
  }
4529
4562
 
4530
4563
  // src/store/sqlite.ts
4531
- import { createRequire } from "node:module";
4532
- import { mkdirSync, existsSync as existsSync2 } from "node:fs";
4564
+ import { existsSync as existsSync2, mkdirSync } from "node:fs";
4533
4565
  import { dirname as dirname2, join as join9 } from "node:path";
4534
4566
  import {
4535
4567
  SageCachePragmas,
4536
4568
  withSqliteExperimentalWarningSuppressed,
4537
4569
  wstackGlobalRoot
4538
4570
  } from "@wrongstack/core/utils";
4571
+ import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
4539
4572
 
4540
4573
  // src/store/schema.ts
4541
4574
  var SCHEMA_VERSION = 1;
@@ -4619,18 +4652,13 @@ function loadDatabaseSync() {
4619
4652
  if (DatabaseSyncCtor) return DatabaseSyncCtor;
4620
4653
  try {
4621
4654
  return withSqliteExperimentalWarningSuppressed(() => {
4622
- const require2 = createRequire(import.meta.url);
4623
- const sqliteModule = require2("node:sqlite");
4624
- if (typeof sqliteModule !== "object" || sqliteModule === null || !("DatabaseSync" in sqliteModule) || typeof sqliteModule.DatabaseSync !== "function") {
4625
- throw new Error("node:sqlite DatabaseSync unavailable");
4626
- }
4627
- DatabaseSyncCtor = sqliteModule.DatabaseSync;
4655
+ DatabaseSyncCtor = loadRuntimeDatabaseSync();
4628
4656
  return DatabaseSyncCtor;
4629
4657
  });
4630
4658
  } catch (error) {
4631
4659
  const message = error instanceof Error ? error.message : String(error);
4632
4660
  throw new Error(
4633
- `TechStack SQLite store needs Node's built-in SQLite (node:sqlite), available since Node 22.5. This runtime doesn't provide it: ${message}`,
4661
+ `TechStack SQLite store needs node:sqlite (Node >= 22.5) or bun:sqlite. This runtime doesn't provide it: ${message}`,
4634
4662
  { cause: error }
4635
4663
  );
4636
4664
  }
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @see docs/specs/techstack-sdd.md §3.2, §4.1
10
10
  */
11
- import type { DeliveryOutbox, DeliveryStatus, Finding, Snapshot, TechStackJob, TechStackJobStatus, TechStackJobProgress } from '../types.js';
11
+ import type { DeliveryOutbox, DeliveryStatus, Finding, Snapshot, TechStackJob, TechStackJobProgress, TechStackJobStatus } from '../types.js';
12
12
  export interface StoreOptions {
13
13
  /** Project slug used for the store directory path. */
14
14
  readonly projectSlug: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/techstack",
3
- "version": "0.309.1",
3
+ "version": "0.310.1",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack TechStack — cross-language dependency intelligence for the active target project: discover, inventory, enrich, analyze, and report.",
6
6
  "repository": {
@@ -26,8 +26,9 @@
26
26
  "!dist/**/*.map"
27
27
  ],
28
28
  "dependencies": {
29
- "@wrongstack/core": "0.309.1",
30
- "@wrongstack/tools": "0.309.1"
29
+ "@wrongstack/core": "0.310.1",
30
+ "@wrongstack/tools": "0.310.1",
31
+ "@wrongstack/persistence": "0.310.1"
31
32
  },
32
33
  "devDependencies": {
33
34
  "@types/node": "^26.2.0",