@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 +21 -0
- package/README.md +51 -6
- package/bin/dowel.mjs +98 -0
- package/dist/binding.d.ts +3 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +68 -0
- package/dist/binding.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +118 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +136 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +65 -6
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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
|
-
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../binding.ts"],"names":[],"mappings":"AAgDA,6DAA6D;AAC7D,wBAAgB,SAAS,IAAI,OAAO,CAuBnC"}
|
package/dist/binding.js
ADDED
|
@@ -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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/runtime.js
ADDED
|
@@ -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
|
|
4
|
-
"description": "
|
|
5
|
-
"license": "MIT
|
|
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
|
-
"
|
|
11
|
-
"
|
|
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
|
+
}
|