@dowel/dowel 0.0.1 → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SwiftCom
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,10 +1,55 @@
1
1
  # dowel
2
2
 
3
- An opinionated, compiled **architecture linter**. It enforces structural rules
4
- so a codebase stays consistent enough for humans *and* coding agents to extend
5
- safely a dowel is the pin that joins two structural members, and this tool
6
- holds a codebase's architecture together the same way.
3
+ A compiled, opinionated **architecture linter**. Rules surface diagnostics +
4
+ intent; the agent reading them applies the fix. Unlike a type-checker it also
5
+ validates raw SQL against a real schema it builds a shadow Postgres from your
6
+ migrations and `PREPARE`s every query against it.
7
7
 
8
- This `0.0.0` publish reserves the name. The real release is coming soon.
8
+ This package ships the Rust engine as a native Node addon plus a TypeScript
9
+ authoring API, so you write your codebase's architecture rules in TypeScript:
9
10
 
10
- Source: https://github.com/swiftcomza/arch-lint
11
+ ```ts
12
+ // rules/no-sql-outside-repos.ts
13
+ import { defineRule } from "@dowel/dowel";
14
+
15
+ export default defineRule({
16
+ id: "NO_SQL_OUTSIDE_REPOS",
17
+ intent: "raw SQL lives only in repos/ — services compose, repos query",
18
+ check(project) {
19
+ return project
20
+ .files()
21
+ .filter((f) => /\bselect\b/i.test(f.text) && !f.relPath.includes("/repos/"))
22
+ .map((f) => ({ severity: "error", file: f.path, line: 1, message: "move SQL into a repo" }));
23
+ },
24
+ });
25
+ ```
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ npm i -D @dowel/dowel
31
+ ```
32
+
33
+ npm pulls exactly one prebuilt native package for your platform
34
+ (`@dowel/dowel-<triple>`) via `optionalDependencies` — no Rust toolchain, no
35
+ post-install compile, no committed binary.
36
+
37
+ ## Use
38
+
39
+ Add an `arch-lint.toml` and a `rules/` dir, then:
40
+
41
+ ```jsonc
42
+ // package.json
43
+ "scripts": { "lint:arch": "dowel" }
44
+ ```
45
+
46
+ ```bash
47
+ npx dowel # lint cwd against ./arch-lint.toml + ./rules
48
+ dowel --root ../ --config arch-lint.toml --rules rules
49
+ ```
50
+
51
+ Exit code is non-zero on any `error`-severity diagnostic, so it gates CI.
52
+
53
+ ## License
54
+
55
+ MIT
package/bin/dowel.mjs ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ // dowel — the architecture linter CLI (plan 005 §2; the consumer-side runner).
3
+ //
4
+ // Loads every TS rule under the rules dir, runs the native packs + all TS rules
5
+ // through the native addon, prints diagnostics, and exits non-zero on any error.
6
+ //
7
+ // Usage (run from the dir holding arch-lint.toml + rules/, or pass flags):
8
+ // dowel [--root <project>] [--config <arch-lint.toml>] [--rules <dir>] [--no-db]
9
+ //
10
+ // Defaults: --config ./arch-lint.toml, --rules <dir-of-config>/rules,
11
+ // --root current working directory.
12
+
13
+ import { readdirSync, existsSync } from "node:fs";
14
+ import { dirname, isAbsolute, join, resolve } from "node:path";
15
+ import { fileURLToPath, pathToFileURL } from "node:url";
16
+
17
+ // Consumer rules are authored in TypeScript; importing them needs Node's
18
+ // type-stripping. It's unflagged on Node >= 22.18 / 23, flagged before that.
19
+ // If this process can't strip types, re-exec ourselves with the flag once.
20
+ if (!process.features?.typescript && !process.env.__DOWEL_TS) {
21
+ const { spawnSync } = await import("node:child_process");
22
+ const self = fileURLToPath(import.meta.url);
23
+ const r = spawnSync(
24
+ process.execPath,
25
+ ["--experimental-strip-types", self, ...process.argv.slice(2)],
26
+ { stdio: "inherit", env: { ...process.env, __DOWEL_TS: "1" } },
27
+ );
28
+ process.exit(r.status ?? 1);
29
+ }
30
+
31
+ const { runLint } = await import("../dist/runtime.js");
32
+
33
+ function parseArgs(argv) {
34
+ const opts = { root: null, config: null, rules: null, withOracle: true };
35
+ for (let i = 0; i < argv.length; i++) {
36
+ const a = argv[i];
37
+ if (a === "--root") opts.root = argv[++i];
38
+ else if (a === "--config") opts.config = argv[++i];
39
+ else if (a === "--rules") opts.rules = argv[++i];
40
+ else if (a === "--no-db") opts.withOracle = false;
41
+ else if (a === "-h" || a === "--help") {
42
+ console.log(
43
+ "dowel — architecture linter\n\n" +
44
+ "Usage: dowel [--root <project>] [--config <arch-lint.toml>] [--rules <dir>] [--no-db]\n",
45
+ );
46
+ process.exit(0);
47
+ } else if (!a.startsWith("-") && opts.root === null) {
48
+ // bare positional → project root (back-compat with run.ts argv[2])
49
+ opts.root = a;
50
+ } else {
51
+ console.error(`dowel: unknown argument '${a}'`);
52
+ process.exit(2);
53
+ }
54
+ }
55
+ return opts;
56
+ }
57
+
58
+ function abs(p) {
59
+ return isAbsolute(p) ? p : resolve(process.cwd(), p);
60
+ }
61
+
62
+ const opts = parseArgs(process.argv.slice(2));
63
+
64
+ const configPath = abs(opts.config ?? "arch-lint.toml");
65
+ if (!existsSync(configPath)) {
66
+ console.error(`dowel: config not found: ${configPath}`);
67
+ console.error(" pass --config <path/to/arch-lint.toml> or run from its directory");
68
+ process.exit(2);
69
+ }
70
+
71
+ const rulesDir = abs(opts.rules ?? join(dirname(configPath), "rules"));
72
+ const root = abs(opts.root ?? process.cwd());
73
+ const withOracle = opts.withOracle && process.env.ARCH_LINT_NO_DB !== "1";
74
+
75
+ async function loadRules() {
76
+ if (!existsSync(rulesDir)) return [];
77
+ const rules = [];
78
+ for (const name of readdirSync(rulesDir).sort()) {
79
+ if (!name.endsWith(".ts") || name.endsWith(".d.ts")) continue;
80
+ const mod = await import(pathToFileURL(join(rulesDir, name)).href);
81
+ if (mod.default) rules.push(mod.default);
82
+ }
83
+ return rules;
84
+ }
85
+
86
+ function format(d, root) {
87
+ const rel = d.file.startsWith(root) ? "." + d.file.slice(root.length) : d.file;
88
+ return `${d.severity}\t${rel}:${d.line}\t[${d.rule}] ${d.message}`;
89
+ }
90
+
91
+ const rules = await loadRules();
92
+ const diags = runLint({ root, configPath, withOracle, rules });
93
+ for (const d of diags) console.log(format(d, root));
94
+
95
+ const errors = diags.filter((d) => d.severity === "error").length;
96
+ const warnings = diags.filter((d) => d.severity === "warn").length;
97
+ console.log(`\narch-lint-ts: ${errors} error(s), ${warnings} warning(s) [${rules.length} TS rules]`);
98
+ process.exit(errors > 0 ? 1 : 0);
@@ -0,0 +1,3 @@
1
+ /** Resolve and load the native addon for the host triple. */
2
+ export declare function loadAddon(): unknown;
3
+ //# sourceMappingURL=binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../binding.ts"],"names":[],"mappings":"AAgDA,6DAA6D;AAC7D,wBAAgB,SAAS,IAAI,OAAO,CAuBnC"}
@@ -0,0 +1,68 @@
1
+ // binding.ts — platform-dispatch loader for the dowel native addon.
2
+ //
3
+ // The Rust crate is built with napi-derive v2 while we drive the build with
4
+ // @napi-rs/cli v3; that version split means the CLI does not emit its usual
5
+ // `index.js` dispatch table. This file reproduces that table by hand (the
6
+ // resolution is deterministic and stable): compute the host platform key,
7
+ // require the matching `@dowel/dowel-<key>` package's prebuilt `.node`, and
8
+ // fall back to a locally-built addon for development. One match wins; npm only
9
+ // installs the one platform package whose `os`/`cpu`/`libc` fit the host.
10
+ import { createRequire } from "node:module";
11
+ import { existsSync } from "node:fs";
12
+ import { dirname, join } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ const require = createRequire(import.meta.url);
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ /** True on musl libc (Alpine) — picks `-musl` over `-gnu` on linux. */
17
+ function isMusl() {
18
+ // node >= 18 exposes the runtime libc via process.report.
19
+ try {
20
+ const report = process.report?.getReport();
21
+ if (report && !report.header?.glibcVersionRuntime)
22
+ return true;
23
+ }
24
+ catch {
25
+ // ignore — fall through to false (assume glibc)
26
+ }
27
+ return false;
28
+ }
29
+ /** The napi platform key for the host (e.g. `darwin-arm64`, `linux-x64-musl`). */
30
+ function platformKey() {
31
+ const { platform, arch } = process;
32
+ switch (platform) {
33
+ case "darwin":
34
+ return arch === "x64" ? "darwin-x64" : "darwin-arm64";
35
+ case "win32":
36
+ return "win32-x64-msvc";
37
+ case "linux":
38
+ if (arch === "arm64")
39
+ return "linux-arm64-gnu";
40
+ return isMusl() ? "linux-x64-musl" : "linux-x64-gnu";
41
+ default:
42
+ throw new Error(`dowel: unsupported platform ${platform}-${arch}`);
43
+ }
44
+ }
45
+ /** Resolve and load the native addon for the host triple. */
46
+ export function loadAddon() {
47
+ const key = platformKey();
48
+ const file = `dowel.${key}.node`;
49
+ // 1. local build (dev): crate root, or sibling of this module.
50
+ for (const candidate of [
51
+ join(here, file),
52
+ join(here, "..", file),
53
+ join(here, "..", "npm", key, file),
54
+ ]) {
55
+ if (existsSync(candidate))
56
+ return require(candidate);
57
+ }
58
+ // 2. published per-platform package.
59
+ try {
60
+ return require(`@dowel/dowel-${key}`);
61
+ }
62
+ catch (cause) {
63
+ throw new Error(`dowel: failed to load the native addon for ${key}.\n` +
64
+ `Install the matching optional dependency (@dowel/dowel-${key}) or run \`napi build --release\`.\n` +
65
+ `Cause: ${cause.message}`);
66
+ }
67
+ }
68
+ //# sourceMappingURL=binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.js","sourceRoot":"","sources":["../binding.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,0EAA0E;AAC1E,4EAA4E;AAC5E,+EAA+E;AAC/E,0EAA0E;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAErD,uEAAuE;AACvE,SAAS,MAAM;IACb,0DAA0D;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,EAE3B,CAAC;QACd,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB;YAAE,OAAO,IAAI,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kFAAkF;AAClF,SAAS,WAAW;IAClB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACnC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;QACxD,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAC;QAC1B,KAAK,OAAO;YACV,IAAI,IAAI,KAAK,OAAO;gBAAE,OAAO,iBAAiB,CAAC;YAC/C,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,CAAC;QACvD;YACE,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC;IAEjC,+DAA+D;IAC/D,KAAK,MAAM,SAAS,IAAI;QACtB,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;QAChB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC;KACnC,EAAE,CAAC;QACF,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,8CAA8C,GAAG,KAAK;YACpD,0DAA0D,GAAG,sCAAsC;YACnG,UAAW,KAAe,CAAC,OAAO,EAAE,CACvC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { defineRule, loadProject, runLint, engineVersion, } from "./runtime.ts";
2
+ export type { Severity, Diagnostic, SourceFile, AstNode, PrepareResult, Project, Finding, RuleSpec, RunOptions, JsonSchema, Ctx, AllowlistLoad, RawAllowlist, } from "./runtime.ts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,UAAU,EACV,WAAW,EACX,OAAO,EACP,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,OAAO,EACP,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,UAAU,EAEV,UAAU,EACV,GAAG,EACH,aAAa,EACb,YAAY,GACb,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ // index.ts — the dowel TS authoring API (plan 005 §2).
2
+ //
3
+ // The package's main entry. Consumers author rules against this surface:
4
+ // import { defineRule } from "@dowel/dowel";
5
+ // It re-exports the rule-authoring primitives and every type a `check` touches.
6
+ // The lint runner itself lives in `bin/dowel.mjs` (run via the `dowel` bin);
7
+ // the lower-level engine driver is `@dowel/dowel/runtime`.
8
+ //
9
+ // NOTE (plan 004): when core-004 lands per-rule typed options + the allowlist
10
+ // primitive, the `optionsSchema`/`ctx.options`/`ctx.loadAllowlist` types are
11
+ // added to `RuleSpec`/the check context in runtime.ts and flow through this
12
+ // re-export automatically — no separate surface needed here.
13
+ export { defineRule, loadProject, runLint, engineVersion, } from "./runtime.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,yEAAyE;AACzE,+CAA+C;AAC/C,gFAAgF;AAChF,6EAA6E;AAC7E,2DAA2D;AAC3D,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,6DAA6D;AAE7D,OAAO,EACL,UAAU,EACV,WAAW,EACX,OAAO,EACP,aAAa,GACd,MAAM,cAAc,CAAC"}
@@ -0,0 +1,118 @@
1
+ export type Severity = "error" | "warn";
2
+ export interface Diagnostic {
3
+ rule: string;
4
+ severity: Severity;
5
+ file: string;
6
+ line: number;
7
+ message: string;
8
+ }
9
+ export interface SourceFile {
10
+ path: string;
11
+ relPath: string;
12
+ lang: string;
13
+ text: string;
14
+ }
15
+ export interface AstNode {
16
+ id: number;
17
+ kind: string;
18
+ kindId: number;
19
+ startByte: number;
20
+ endByte: number;
21
+ startRow: number;
22
+ endRow: number;
23
+ parent: number;
24
+ named: boolean;
25
+ }
26
+ export interface PrepareResult {
27
+ ok: boolean;
28
+ skipped: boolean;
29
+ error: string | null;
30
+ columns: {
31
+ name: string;
32
+ pgType: string;
33
+ tsType: string;
34
+ nullable: boolean;
35
+ }[];
36
+ }
37
+ /** Core's allowlist loader output: unnormalised tokens + `# reason` violations. */
38
+ export interface RawAllowlist {
39
+ tokens: string[];
40
+ violations: Finding[];
41
+ }
42
+ /** The compiled project + engine primitives a rule's `check` is handed. */
43
+ export interface Project {
44
+ root: string;
45
+ files(): SourceFile[];
46
+ read(rel: string): string | null;
47
+ glob(pattern: string): string[];
48
+ astOf(path: string): AstNode[];
49
+ /** Prepare SQL against the shadow DB — the SQL-drift signal. */
50
+ prepareSql(sql: string): PrepareResult;
51
+ /**
52
+ * Core's one allowlist loader (`arch_lint_core::allowlist::load_allowlist`):
53
+ * parses `token # reason` lines, enforcing the reason convention. Tokens are
54
+ * returned as written; [`Ctx.loadAllowlist`] applies the rule's `normalize`.
55
+ */
56
+ loadAllowlistRaw(rel: string): RawAllowlist;
57
+ }
58
+ /** A diagnostic a rule emits (its `rule` id is filled in by the runner). */
59
+ export type Finding = Omit<Diagnostic, "rule"> & {
60
+ rule?: string;
61
+ };
62
+ /**
63
+ * A minimal JSON-Schema subtree, enough to declare per-rule options and carry
64
+ * their defaults (plan 004 §2). Mirrors the `serde_json::Value` schemas core's
65
+ * native/declarative rules use, so a future `.d.ts` generator can share it.
66
+ */
67
+ export interface JsonSchema {
68
+ type?: "object" | "array" | "string" | "number" | "integer" | "boolean";
69
+ properties?: Record<string, JsonSchema>;
70
+ items?: JsonSchema;
71
+ default?: unknown;
72
+ [k: string]: unknown;
73
+ }
74
+ /** The result of [`Ctx.loadAllowlist`] — exempt tokens + `# reason` violations. */
75
+ export interface AllowlistLoad {
76
+ allow: Set<string>;
77
+ violations: Finding[];
78
+ }
79
+ /**
80
+ * The second argument to a rule's `check`. Carries the rule's validated options
81
+ * (schema defaults overlaid by the `[rules.<CODE>]` table) and the shared
82
+ * allowlist loader, so no rule re-implements config plumbing (plan 004).
83
+ */
84
+ export interface Ctx<O = Record<string, unknown>> {
85
+ /** Validated options: `optionsSchema` defaults overlaid by `[rules.<CODE>]`. */
86
+ options: O;
87
+ /**
88
+ * Load a sidecar allowlist (`token # reason` per line) by project-relative
89
+ * path. Enforces the `# reason` convention — a missing reason becomes a
90
+ * `violations` diagnostic (attributed to `violationRuleId`, else left for the
91
+ * runner to stamp with the calling rule's id). `normalize` canonicalises each
92
+ * token before it enters the `allow` set. Missing file ⇒ empty, no violations.
93
+ */
94
+ loadAllowlist(relPath: string, normalize?: (token: string) => string, violationRuleId?: string): AllowlistLoad;
95
+ }
96
+ export interface RuleSpec<O = Record<string, unknown>> {
97
+ id: string;
98
+ intent: string;
99
+ group?: string;
100
+ appliesTo?: string[];
101
+ /** Per-rule options schema; its property `default`s seed `ctx.options`. */
102
+ optionsSchema?: JsonSchema;
103
+ check(project: Project, ctx: Ctx<O>): Finding[];
104
+ }
105
+ export declare function defineRule<O = Record<string, unknown>>(spec: RuleSpec<O>): RuleSpec<O>;
106
+ /** Load a project handle and return the wrapped, rule-facing `Project`. The
107
+ * optional `rules` register their schemas so `[rules.<CODE>]` overrides resolve. */
108
+ export declare function loadProject(root: string, configPath: string, withOracle: boolean, rules?: RuleSpec[]): Project;
109
+ export interface RunOptions {
110
+ root: string;
111
+ configPath: string;
112
+ withOracle: boolean;
113
+ rules: RuleSpec[];
114
+ }
115
+ /** Run the native packs + every TS rule and return one merged, sorted stream. */
116
+ export declare function runLint(opts: RunOptions): Diagnostic[];
117
+ export declare const engineVersion: string;
118
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../runtime.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAChF;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,OAAO,EAAE,CAAC;CACvB;AAED,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,UAAU,EAAE,CAAC;IACtB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;IAC/B,gEAAgE;IAChE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC;CAC7C;AAED,4EAA4E;AAC5E,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,UAAU,EAAE,OAAO,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC9C,gFAAgF;IAChF,OAAO,EAAE,CAAC,CAAC;IACX;;;;;;OAMG;IACH,aAAa,CACX,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACrC,eAAe,CAAC,EAAE,MAAM,GACvB,aAAa,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAEtF;AA4GD;qFACqF;AACrF,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,OAAO,EACnB,KAAK,GAAE,QAAQ,EAAO,GACrB,OAAO,CAET;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAyCtD;AAED,eAAO,MAAM,aAAa,EAAE,MAAwB,CAAC"}
@@ -0,0 +1,136 @@
1
+ // runtime.ts — the TS-native rule tier for dowel (plan 003 §5c, plan 004, 005).
2
+ //
3
+ // Loads the compiled native addon (core's engine: Project, AST, shadow-DB
4
+ // Oracle) and drives the lint loop in JS, so domain rules are authored in
5
+ // TypeScript (`defineRule`) instead of a Rust rule-pack crate. The native rule
6
+ // packs still run via `lintNative` — their diagnostics merge with the TS ones.
7
+ //
8
+ // This is the published copy of the runner (plan 005 §2): the body is kept
9
+ // byte-for-byte identical to the consumer-side runtime.ts (the parity source of
10
+ // truth, owned by the plan-004 bridge) EXCEPT the addon is resolved through the
11
+ // platform-dispatch loader (binding.ts) instead of a hardcoded local `require`
12
+ // — so a published @dowel/dowel-<triple> package is found.
13
+ import { loadAddon } from "./binding.js";
14
+ const addon = loadAddon();
15
+ export function defineRule(spec) {
16
+ return spec;
17
+ }
18
+ /** Extract `{ key: default }` for every property declaring a `default`. */
19
+ function schemaDefaults(schema) {
20
+ const out = {};
21
+ if (!schema?.properties)
22
+ return out;
23
+ for (const [key, prop] of Object.entries(schema.properties)) {
24
+ if (prop && "default" in prop)
25
+ out[key] = prop.default;
26
+ }
27
+ return out;
28
+ }
29
+ /**
30
+ * Resolve a rule's options: schema defaults overlaid by any `[rules.<CODE>]`
31
+ * table the engine parsed. `tableJson` is the raw table as JSON (`{}` if none),
32
+ * so until a consumer adds a table the result is exactly the schema defaults —
33
+ * i.e. today's hardcoded-constant behaviour, byte-for-byte.
34
+ */
35
+ function resolveOptions(spec, tableJson) {
36
+ const defaults = schemaDefaults(spec.optionsSchema);
37
+ let table = {};
38
+ if (tableJson) {
39
+ try {
40
+ const parsed = JSON.parse(tableJson);
41
+ if (parsed && typeof parsed === "object")
42
+ table = parsed;
43
+ }
44
+ catch {
45
+ // A malformed table is the engine's problem; defaults keep the rule running.
46
+ }
47
+ }
48
+ return { ...defaults, ...table };
49
+ }
50
+ /**
51
+ * Build a rule's `ctx`. The allowlist loader delegates to core's single
52
+ * `arch_lint_core::allowlist::load_allowlist` (via the addon) — the `# reason`
53
+ * parse and canonical message live in Rust, shared by every tier. The bridge
54
+ * only applies the rule's `normalize` to the returned tokens and stamps the
55
+ * violation `rule` id (a shared-allowlist rule passes `violationRuleId`).
56
+ */
57
+ function makeCtx(project, options) {
58
+ return {
59
+ options,
60
+ loadAllowlist(relPath, normalize, violationRuleId) {
61
+ const { tokens, violations } = project.loadAllowlistRaw(relPath);
62
+ const allow = new Set(tokens.map((t) => (normalize ? normalize(t) : t)));
63
+ const stamped = violationRuleId
64
+ ? violations.map((v) => ({ ...v, rule: violationRuleId }))
65
+ : violations;
66
+ return { allow, violations: stamped };
67
+ },
68
+ };
69
+ }
70
+ function wrap(h) {
71
+ return {
72
+ root: h.root(),
73
+ files: () => h.files(),
74
+ read: (rel) => h.read(rel),
75
+ glob: (pattern) => h.glob(pattern),
76
+ astOf: (path) => h.astOf(path),
77
+ prepareSql: (sql) => h.oraclePrepare(sql),
78
+ loadAllowlistRaw: (rel) => {
79
+ const r = h.loadAllowlist(rel);
80
+ // Drop core's placeholder `rule`; the ctx caller stamps attribution.
81
+ const violations = r.violations.map((v) => ({
82
+ severity: v.severity,
83
+ file: v.file,
84
+ line: v.line,
85
+ message: v.message,
86
+ }));
87
+ return { tokens: r.tokens, violations };
88
+ },
89
+ };
90
+ }
91
+ /**
92
+ * Serialise the TS rules' `optionsSchema`s as `[{ code, schema }]` so the engine
93
+ * treats each TS-tier code as a first-class rule when validating `[rules.<CODE>]`
94
+ * tables — without this a consumer override of a TS rule's option is rejected as
95
+ * an unknown code. Rules with no schema are omitted (no options to resolve).
96
+ */
97
+ function tsSchemasJson(rules) {
98
+ return JSON.stringify(rules.filter((r) => r.optionsSchema).map((r) => ({ code: r.id, schema: r.optionsSchema })));
99
+ }
100
+ /** Load a project handle and return the wrapped, rule-facing `Project`. The
101
+ * optional `rules` register their schemas so `[rules.<CODE>]` overrides resolve. */
102
+ export function loadProject(root, configPath, withOracle, rules = []) {
103
+ return wrap(addon.ProjectHandle.load(root, configPath, withOracle, tsSchemasJson(rules)));
104
+ }
105
+ /** Run the native packs + every TS rule and return one merged, sorted stream. */
106
+ export function runLint(opts) {
107
+ const tsSchemas = tsSchemasJson(opts.rules);
108
+ const handle = addon.ProjectHandle.load(opts.root, opts.configPath, opts.withOracle, tsSchemas);
109
+ const project = wrap(handle);
110
+ const native = addon.lintNative(opts.root, opts.configPath, opts.withOracle, tsSchemas);
111
+ const ts = [];
112
+ for (const rule of opts.rules) {
113
+ const tableJson = handle.ruleOptions(rule.id);
114
+ const ctx = makeCtx(project, resolveOptions(rule, tableJson));
115
+ let found;
116
+ try {
117
+ found = rule.check(project, ctx) ?? [];
118
+ }
119
+ catch (e) {
120
+ // Panic isolation: a throwing rule becomes one diagnostic, not a crash.
121
+ ts.push({
122
+ rule: rule.id,
123
+ severity: "error",
124
+ file: "",
125
+ line: 0,
126
+ message: `rule '${rule.id}' threw: ${e.message}`,
127
+ });
128
+ continue;
129
+ }
130
+ for (const f of found)
131
+ ts.push({ ...f, rule: f.rule ?? rule.id });
132
+ }
133
+ return [...native, ...ts].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.rule.localeCompare(b.rule));
134
+ }
135
+ export const engineVersion = addon.version();
136
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../runtime.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,71 @@
1
1
  {
2
2
  "name": "@dowel/dowel",
3
- "version": "0.0.1",
4
- "description": "An opinionated, compiled architecture linter. Name placeholder real release coming soon.",
5
- "license": "MIT OR Apache-2.0",
3
+ "version": "0.1.0",
4
+ "description": "dowel a compiled, opinionated architecture linter. TS-native rule authoring over a Rust engine (Project, AST, shadow-DB SQL oracle).",
5
+ "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/swiftcomza/arch-lint.git"
9
9
  },
10
- "keywords": ["linter", "architecture", "static-analysis"],
11
- "files": ["README.md"]
12
- }
10
+ "type": "module",
11
+ "bin": {
12
+ "dowel": "./bin/dowel.mjs"
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./runtime": {
22
+ "types": "./dist/runtime.d.ts",
23
+ "default": "./dist/runtime.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist/",
28
+ "bin/",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "napi": {
33
+ "binaryName": "dowel",
34
+ "packageName": "@dowel/dowel",
35
+ "targets": [
36
+ "aarch64-apple-darwin",
37
+ "x86_64-apple-darwin",
38
+ "x86_64-unknown-linux-gnu",
39
+ "aarch64-unknown-linux-gnu",
40
+ "x86_64-unknown-linux-musl",
41
+ "x86_64-pc-windows-msvc"
42
+ ]
43
+ },
44
+ "engines": {
45
+ "node": ">= 20"
46
+ },
47
+ "scripts": {
48
+ "build": "napi build --platform --release --manifest-path Cargo.toml && tsc -p tsconfig.json",
49
+ "build:debug": "napi build --platform --manifest-path Cargo.toml && tsc -p tsconfig.json",
50
+ "build:ts": "tsc -p tsconfig.json",
51
+ "artifacts": "napi artifacts",
52
+ "create-npm-dirs": "napi create-npm-dirs",
53
+ "prepublishOnly": "napi prepublish -t npm"
54
+ },
55
+ "devDependencies": {
56
+ "@napi-rs/cli": "^3.0.0",
57
+ "typescript": "^5.6.0",
58
+ "@types/node": "^22.0.0"
59
+ },
60
+ "optionalDependencies": {
61
+ "@dowel/dowel-darwin-arm64": "0.1.0",
62
+ "@dowel/dowel-darwin-x64": "0.1.0",
63
+ "@dowel/dowel-linux-x64-gnu": "0.1.0",
64
+ "@dowel/dowel-linux-arm64-gnu": "0.1.0",
65
+ "@dowel/dowel-linux-x64-musl": "0.1.0",
66
+ "@dowel/dowel-win32-x64-msvc": "0.1.0"
67
+ },
68
+ "publishConfig": {
69
+ "access": "public"
70
+ }
71
+ }