@intentset/architecture 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/dist/baseline.d.ts +39 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +104 -0
- package/dist/baseline.js.map +1 -0
- package/dist/boundaries.d.ts +63 -0
- package/dist/boundaries.d.ts.map +1 -0
- package/dist/boundaries.js +436 -0
- package/dist/boundaries.js.map +1 -0
- package/dist/check.d.ts +73 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +130 -0
- package/dist/check.js.map +1 -0
- package/dist/claims.d.ts +24 -0
- package/dist/claims.d.ts.map +1 -0
- package/dist/claims.js +201 -0
- package/dist/claims.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +159 -0
- package/dist/config.js.map +1 -0
- package/dist/dependencies.d.ts +30 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +179 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/exceptions.d.ts +43 -0
- package/dist/exceptions.d.ts.map +1 -0
- package/dist/exceptions.js +233 -0
- package/dist/exceptions.js.map +1 -0
- package/dist/extract.d.ts +24 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +316 -0
- package/dist/extract.js.map +1 -0
- package/dist/finding.d.ts +39 -0
- package/dist/finding.d.ts.map +1 -0
- package/dist/finding.js +29 -0
- package/dist/finding.js.map +1 -0
- package/dist/imports.d.ts +30 -0
- package/dist/imports.d.ts.map +1 -0
- package/dist/imports.js +48 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/layers.d.ts +38 -0
- package/dist/layers.d.ts.map +1 -0
- package/dist/layers.js +41 -0
- package/dist/layers.js.map +1 -0
- package/dist/ownership.d.ts +25 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/ownership.js +97 -0
- package/dist/ownership.js.map +1 -0
- package/dist/paths.d.ts +18 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +54 -0
- package/dist/paths.js.map +1 -0
- package/dist/patterns.d.ts +25 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +101 -0
- package/dist/patterns.js.map +1 -0
- package/dist/regions.d.ts +85 -0
- package/dist/regions.d.ts.map +1 -0
- package/dist/regions.js +144 -0
- package/dist/regions.js.map +1 -0
- package/dist/resolve.d.ts +53 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +268 -0
- package/dist/resolve.js.map +1 -0
- package/dist/tsconfig.d.ts +42 -0
- package/dist/tsconfig.d.ts.map +1 -0
- package/dist/tsconfig.js +186 -0
- package/dist/tsconfig.js.map +1 -0
- package/package.json +36 -0
- package/src/baseline.ts +126 -0
- package/src/boundaries.ts +499 -0
- package/src/check.ts +197 -0
- package/src/claims.ts +229 -0
- package/src/config.ts +212 -0
- package/src/dependencies.ts +211 -0
- package/src/exceptions.ts +269 -0
- package/src/extract.ts +344 -0
- package/src/finding.ts +64 -0
- package/src/imports.ts +77 -0
- package/src/index.ts +58 -0
- package/src/layers.ts +67 -0
- package/src/ownership.ts +135 -0
- package/src/paths.ts +53 -0
- package/src/patterns.ts +95 -0
- package/src/regions.ts +243 -0
- package/src/resolve.ts +283 -0
- package/src/tsconfig.ts +198 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,OAAO;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,qFAAqF;IACrF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,6DAA6D;IAC7D,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,2FAA2F;AAC3F,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAetD;AAED,4BAA4B;AAC5B,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,SAAa,GAAG,MAAM,CAE7E;AAED,mEAAmE;AACnE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,CAGpE"}
|
package/dist/finding.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** One diagnostic, members in contract order, optional members present only when known. */
|
|
2
|
+
export function finding(fields) {
|
|
3
|
+
const diagnostic = {
|
|
4
|
+
code: fields.code,
|
|
5
|
+
severity: fields.severity ?? "error",
|
|
6
|
+
origin: "architecture",
|
|
7
|
+
artifact: fields.artifact,
|
|
8
|
+
path: fields.path,
|
|
9
|
+
...(fields.location !== undefined ? { location: fields.location } : {}),
|
|
10
|
+
...(fields.field !== undefined ? { field: fields.field } : {}),
|
|
11
|
+
message: fields.message,
|
|
12
|
+
remediation: fields.remediation,
|
|
13
|
+
};
|
|
14
|
+
const paths = new Set(fields.paths ?? []);
|
|
15
|
+
if (fields.path !== null)
|
|
16
|
+
paths.add(fields.path);
|
|
17
|
+
return { diagnostic, paths: [...paths].sort(), edges: fields.edges ?? [] };
|
|
18
|
+
}
|
|
19
|
+
/** "1 file" / "3 files". */
|
|
20
|
+
export function plural(count, noun, many = `${noun}s`) {
|
|
21
|
+
return `${count} ${count === 1 ? noun : many}`;
|
|
22
|
+
}
|
|
23
|
+
/** At most `limit` items joined with commas, then "and N more". */
|
|
24
|
+
export function listSome(items, limit = 3) {
|
|
25
|
+
if (items.length <= limit)
|
|
26
|
+
return items.join(", ");
|
|
27
|
+
return `${items.slice(0, limit).join(", ")} and ${items.length - limit} more`;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=finding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAoCA,2FAA2F;AAC3F,MAAM,UAAU,OAAO,CAAC,MAAqB;IAC3C,MAAM,UAAU,GAAe;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,OAAO;QACpC,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED,4BAA4B;AAC5B,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,IAAY,EAAE,IAAI,GAAG,GAAG,IAAI,GAAG;IACnE,OAAO,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,QAAQ,CAAC,KAAwB,EAAE,KAAK,GAAG,CAAC;IAC1D,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,GAAG,KAAK,OAAO,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Resolver, Via } from "./resolve.ts";
|
|
2
|
+
export interface ImportEdge {
|
|
3
|
+
from: string;
|
|
4
|
+
/** Target file, or null for an external package. */
|
|
5
|
+
to: string | null;
|
|
6
|
+
specifier: string;
|
|
7
|
+
/** 1-based line of the specifier in `from`. */
|
|
8
|
+
line: number;
|
|
9
|
+
typeOnly: boolean;
|
|
10
|
+
dynamic: boolean;
|
|
11
|
+
reexport: boolean;
|
|
12
|
+
/** `export * from` or `export * as ns from`. */
|
|
13
|
+
wildcardExport: boolean;
|
|
14
|
+
via: Via;
|
|
15
|
+
/** Resolved through a `*` alias, an exports pattern or a package without exports (TS006). */
|
|
16
|
+
wildcardAlias: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface UnresolvedImport {
|
|
19
|
+
path: string;
|
|
20
|
+
line: number | null;
|
|
21
|
+
specifier: string | null;
|
|
22
|
+
message: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ImportGraph {
|
|
25
|
+
edges: ImportEdge[];
|
|
26
|
+
unresolved: UnresolvedImport[];
|
|
27
|
+
}
|
|
28
|
+
/** Build the graph over every code file in `files` (already filtered of ignored paths). */
|
|
29
|
+
export declare function buildImportGraph(files: ReadonlyMap<string, string>, resolver: Resolver): ImportGraph;
|
|
30
|
+
//# sourceMappingURL=imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,cAAc,EAAE,OAAO,CAAC;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,6FAA6F;IAC7F,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAmCpG"}
|
package/dist/imports.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The resolved import graph of a tree (VSA003–VSA006, profile TS004): one
|
|
3
|
+
* edge per module reference in every code file, with the target file or,
|
|
4
|
+
* for a package outside the repository, the specifier alone. What could not
|
|
5
|
+
* be read or resolved is returned beside the edges, never folded into them.
|
|
6
|
+
*/
|
|
7
|
+
import { extractImports } from "./extract.js";
|
|
8
|
+
import { isCode } from "./paths.js";
|
|
9
|
+
import { compareStrings } from "./patterns.js";
|
|
10
|
+
/** Build the graph over every code file in `files` (already filtered of ignored paths). */
|
|
11
|
+
export function buildImportGraph(files, resolver) {
|
|
12
|
+
const edges = [];
|
|
13
|
+
const unresolved = [];
|
|
14
|
+
for (const path of [...files.keys()].sort(compareStrings)) {
|
|
15
|
+
if (!isCode(path))
|
|
16
|
+
continue;
|
|
17
|
+
const { imports, problems } = extractImports(path, files.get(path));
|
|
18
|
+
for (const problem of problems) {
|
|
19
|
+
unresolved.push({ path, line: problem.line, specifier: null, message: problem.message });
|
|
20
|
+
}
|
|
21
|
+
for (const raw of imports) {
|
|
22
|
+
const resolution = resolver.resolve(path, raw.specifier);
|
|
23
|
+
if (resolution.problem !== undefined) {
|
|
24
|
+
unresolved.push({
|
|
25
|
+
path,
|
|
26
|
+
line: raw.line,
|
|
27
|
+
specifier: raw.specifier,
|
|
28
|
+
message: `the specifier "${raw.specifier}" ${resolution.problem}`,
|
|
29
|
+
});
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
edges.push({
|
|
33
|
+
from: path,
|
|
34
|
+
to: resolution.to,
|
|
35
|
+
specifier: raw.specifier,
|
|
36
|
+
line: raw.line,
|
|
37
|
+
typeOnly: raw.typeOnly,
|
|
38
|
+
dynamic: raw.dynamic,
|
|
39
|
+
reexport: raw.reexport,
|
|
40
|
+
wildcardExport: raw.wildcard,
|
|
41
|
+
via: resolution.via,
|
|
42
|
+
wildcardAlias: resolution.wildcard,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { edges, unresolved };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAgC/C,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAkC,EAAE,QAAkB;IACrF,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAuB,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAW,CAAC,CAAC;QAC9E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACrC,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI;oBACJ,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,SAAS,EAAE,GAAG,CAAC,SAAS;oBACxB,OAAO,EAAE,kBAAkB,GAAG,CAAC,SAAS,KAAK,UAAU,CAAC,OAAO,EAAE;iBAClE,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,IAAI;gBACV,EAAE,EAAE,UAAU,CAAC,EAAE;gBACjB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,cAAc,EAAE,GAAG,CAAC,QAAQ;gBAC5B,GAAG,EAAE,UAAU,CAAC,GAAG;gBACnB,aAAa,EAAE,UAAU,CAAC,QAAQ;aACnC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intentset/architecture: the Traceable VSA checker (spec/vsa-0.1.md) with
|
|
3
|
+
* the TypeScript + Amplify Gen 2 profile's boundaries
|
|
4
|
+
* (spec/profile-typescript-amplify-gen2-0.1.md). `checkArchitecture` is the
|
|
5
|
+
* whole check; the rest is exported for reports, tools and tests.
|
|
6
|
+
*/
|
|
7
|
+
export { applyBaseline, type BaselineEntry, fingerprint, type Mode, parseBaseline, plainMessage, writeBaseline, } from "./baseline.ts";
|
|
8
|
+
export { type BoundaryResult, checkBoundaries, checkUnclassified, type SliceEdge } from "./boundaries.ts";
|
|
9
|
+
export { type ArchitectureResult, type ArchitectureSummary, type CheckOptions, checkArchitecture, REVIEW_REQUIRED, } from "./check.ts";
|
|
10
|
+
export { checkClaims } from "./claims.ts";
|
|
11
|
+
export { ARCHITECTURE_CONFIG_PATH, type ArchitectureConfig, DEFAULT_ARCHITECTURE_CONFIG, readArchitectureConfig, resolveConfig, } from "./config.ts";
|
|
12
|
+
export { checkDependencies, shortestCycle, stronglyConnected } from "./dependencies.ts";
|
|
13
|
+
export { annotate, applyExceptions, covers, EXCEPTIONS_PATTERNS, type ExceptionRecord, readExceptionRecord, readExceptions, } from "./exceptions.ts";
|
|
14
|
+
export { type Extraction, extractImports, type RawImport } from "./extract.ts";
|
|
15
|
+
export type { Finding, SubjectEdge } from "./finding.ts";
|
|
16
|
+
export { buildImportGraph, type ImportEdge, type ImportGraph, type UnresolvedImport } from "./imports.ts";
|
|
17
|
+
export { inSeam, isPure, layerAllows, layerOf, purePatterns, seamPatterns } from "./layers.ts";
|
|
18
|
+
export { checkOwnership } from "./ownership.ts";
|
|
19
|
+
export { expandClaims, matchAny, matchPattern, validatePattern } from "./patterns.ts";
|
|
20
|
+
export { activeSlices, buildModel, type Model, type Region, type RegionKind, regionLabel, type SliceInfo, } from "./regions.ts";
|
|
21
|
+
export { type Resolution, Resolver, type Via } from "./resolve.ts";
|
|
22
|
+
export { matchAlias, stripJsonComments, type TsConfig, TsConfigs } from "./tsconfig.ts";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,aAAa,EACb,KAAK,aAAa,EAClB,WAAW,EACX,KAAK,IAAI,EACT,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,2BAA2B,EAC3B,sBAAsB,EACtB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EACL,QAAQ,EACR,eAAe,EACf,MAAM,EACN,mBAAmB,EACnB,KAAK,eAAe,EACpB,mBAAmB,EACnB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC/E,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACL,YAAY,EACZ,UAAU,EACV,KAAK,KAAK,EACV,KAAK,MAAM,EACX,KAAK,UAAU,EACf,WAAW,EACX,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intentset/architecture: the Traceable VSA checker (spec/vsa-0.1.md) with
|
|
3
|
+
* the TypeScript + Amplify Gen 2 profile's boundaries
|
|
4
|
+
* (spec/profile-typescript-amplify-gen2-0.1.md). `checkArchitecture` is the
|
|
5
|
+
* whole check; the rest is exported for reports, tools and tests.
|
|
6
|
+
*/
|
|
7
|
+
export { applyBaseline, fingerprint, parseBaseline, plainMessage, writeBaseline, } from "./baseline.js";
|
|
8
|
+
export { checkBoundaries, checkUnclassified } from "./boundaries.js";
|
|
9
|
+
export { checkArchitecture, REVIEW_REQUIRED, } from "./check.js";
|
|
10
|
+
export { checkClaims } from "./claims.js";
|
|
11
|
+
export { ARCHITECTURE_CONFIG_PATH, DEFAULT_ARCHITECTURE_CONFIG, readArchitectureConfig, resolveConfig, } from "./config.js";
|
|
12
|
+
export { checkDependencies, shortestCycle, stronglyConnected } from "./dependencies.js";
|
|
13
|
+
export { annotate, applyExceptions, covers, EXCEPTIONS_PATTERNS, readExceptionRecord, readExceptions, } from "./exceptions.js";
|
|
14
|
+
export { extractImports } from "./extract.js";
|
|
15
|
+
export { buildImportGraph } from "./imports.js";
|
|
16
|
+
export { inSeam, isPure, layerAllows, layerOf, purePatterns, seamPatterns } from "./layers.js";
|
|
17
|
+
export { checkOwnership } from "./ownership.js";
|
|
18
|
+
export { expandClaims, matchAny, matchPattern, validatePattern } from "./patterns.js";
|
|
19
|
+
export { activeSlices, buildModel, regionLabel, } from "./regions.js";
|
|
20
|
+
export { Resolver } from "./resolve.js";
|
|
21
|
+
export { matchAlias, stripJsonComments, TsConfigs } from "./tsconfig.js";
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,aAAa,EAEb,WAAW,EAEX,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAuB,eAAe,EAAE,iBAAiB,EAAkB,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EAIL,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,wBAAwB,EAExB,2BAA2B,EAC3B,sBAAsB,EACtB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EACL,QAAQ,EACR,eAAe,EACf,MAAM,EACN,mBAAmB,EAEnB,mBAAmB,EACnB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAmB,cAAc,EAAkB,MAAM,cAAc,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAA4D,MAAM,cAAc,CAAC;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EACL,YAAY,EACZ,UAAU,EAIV,WAAW,GAEZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAmB,QAAQ,EAAY,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAiB,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/layers.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A slice's internal layers (VSA006, profile §3). The slice declares its
|
|
3
|
+
* layers by pattern; the profile's matrix says which may import which:
|
|
4
|
+
*
|
|
5
|
+
* presentation -> application, policy, model
|
|
6
|
+
* application -> policy, model, external
|
|
7
|
+
* policy -> model
|
|
8
|
+
* model -> model
|
|
9
|
+
* external -> model
|
|
10
|
+
*
|
|
11
|
+
* each layer also importing itself. The same declaration names the slice's
|
|
12
|
+
* external-access seam (the `external` layer, VSA010 and AMP002) and its pure
|
|
13
|
+
* layers (`policy` and `model`, AMP006). A slice that declares no layers
|
|
14
|
+
* falls back to the reference layout's folders under an entrypoint's
|
|
15
|
+
* directory: client/, domain/policies/, domain/models/. A slice has one
|
|
16
|
+
* entrypoint per package, so a file uses the folders under the entrypoint
|
|
17
|
+
* directory nearest above it.
|
|
18
|
+
*/
|
|
19
|
+
import type { ArchitectureConfig } from "./config.ts";
|
|
20
|
+
import { type SliceInfo } from "./regions.ts";
|
|
21
|
+
export type LayerOf = {
|
|
22
|
+
layer: string;
|
|
23
|
+
} | {
|
|
24
|
+
layer: null;
|
|
25
|
+
reason: "none" | "ambiguous";
|
|
26
|
+
candidates: string[];
|
|
27
|
+
};
|
|
28
|
+
export declare function layerOf(slice: SliceInfo, path: string): LayerOf;
|
|
29
|
+
/** The slice's declared external-access seam; for a slice that declares none, the client/ folder under each entrypoint (or the one above `path`). */
|
|
30
|
+
export declare function seamPatterns(slice: SliceInfo, path?: string): string[];
|
|
31
|
+
/** The slice's pure layers: policies and models, which must stay free of clients and SDKs. */
|
|
32
|
+
export declare function purePatterns(slice: SliceInfo, path?: string): string[];
|
|
33
|
+
export declare function inSeam(slice: SliceInfo, path: string): boolean;
|
|
34
|
+
export declare function isPure(slice: SliceInfo, path: string): boolean;
|
|
35
|
+
/** May a file in layer `from` import one in layer `to`? Unknown layers are never allowed anything. */
|
|
36
|
+
export declare function layerAllows(config: ArchitectureConfig, from: string, to: string): boolean;
|
|
37
|
+
export declare function knownLayer(config: ArchitectureConfig, layer: string): boolean;
|
|
38
|
+
//# sourceMappingURL=layers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../src/layers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9G,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAM/D;AAQD,qJAAqJ;AACrJ,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAGtE;AAED,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAGtE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAGzF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7E"}
|
package/dist/layers.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { matchAny } from "./patterns.js";
|
|
2
|
+
import { rootOf } from "./regions.js";
|
|
3
|
+
export function layerOf(slice, path) {
|
|
4
|
+
const matches = Object.keys(slice.meta.layers)
|
|
5
|
+
.sort()
|
|
6
|
+
.filter((layer) => matchAny(slice.meta.layers[layer], path));
|
|
7
|
+
if (matches.length === 1)
|
|
8
|
+
return { layer: matches[0] };
|
|
9
|
+
return { layer: null, reason: matches.length === 0 ? "none" : "ambiguous", candidates: matches };
|
|
10
|
+
}
|
|
11
|
+
/** The fallback folders under the root a path belongs to, or under every root when no path is given. */
|
|
12
|
+
function under(slice, folders, path) {
|
|
13
|
+
const roots = path === undefined ? slice.roots : [rootOf(slice, path)].filter((root) => root !== null);
|
|
14
|
+
return roots.flatMap((root) => folders.map((folder) => (root === "" ? `${folder}/**` : `${root}/${folder}/**`)));
|
|
15
|
+
}
|
|
16
|
+
/** The slice's declared external-access seam; for a slice that declares none, the client/ folder under each entrypoint (or the one above `path`). */
|
|
17
|
+
export function seamPatterns(slice, path) {
|
|
18
|
+
const declared = slice.meta.layers.external ?? [];
|
|
19
|
+
return declared.length > 0 ? declared : under(slice, ["client"], path);
|
|
20
|
+
}
|
|
21
|
+
/** The slice's pure layers: policies and models, which must stay free of clients and SDKs. */
|
|
22
|
+
export function purePatterns(slice, path) {
|
|
23
|
+
const declared = [...(slice.meta.layers.policy ?? []), ...(slice.meta.layers.model ?? [])];
|
|
24
|
+
return declared.length > 0 ? declared : under(slice, ["domain/policies", "domain/models"], path);
|
|
25
|
+
}
|
|
26
|
+
export function inSeam(slice, path) {
|
|
27
|
+
return matchAny(seamPatterns(slice, path), path);
|
|
28
|
+
}
|
|
29
|
+
export function isPure(slice, path) {
|
|
30
|
+
return matchAny(purePatterns(slice, path), path);
|
|
31
|
+
}
|
|
32
|
+
/** May a file in layer `from` import one in layer `to`? Unknown layers are never allowed anything. */
|
|
33
|
+
export function layerAllows(config, from, to) {
|
|
34
|
+
if (from === to)
|
|
35
|
+
return true;
|
|
36
|
+
return (config.layerMatrix[from] ?? []).includes(to);
|
|
37
|
+
}
|
|
38
|
+
export function knownLayer(config, layer) {
|
|
39
|
+
return Object.hasOwn(config.layerMatrix, layer);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.js","sourceRoot":"","sources":["../src/layers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavior ownership and contract surfaces (VSA001, VSA002; Core §5).
|
|
3
|
+
*
|
|
4
|
+
* VSA001 at L2 and above: an approved, implemented, released or deprecated
|
|
5
|
+
* behavior has exactly one incoming `implements` from a product slice. Core
|
|
6
|
+
* reports the same condition as CORE006 from the graph alone; VSA001 is the
|
|
7
|
+
* architecture's own statement of it, so a VSA report stands by itself.
|
|
8
|
+
*
|
|
9
|
+
* VSA002: each of a slice's entrypoints is a file in the repository and lies
|
|
10
|
+
* inside one of the slice's own source claims, and no two lie in the same
|
|
11
|
+
* package (the nearest directory above holding a package.json, or the
|
|
12
|
+
* repository root): a slice has one public surface per package it spans. An
|
|
13
|
+
* empty entrypoint module is allowed for a leaf.
|
|
14
|
+
*
|
|
15
|
+
* VSA012 (deleting or splitting a slice dispositions its behavior, paths and
|
|
16
|
+
* contracts) is a diff between two snapshots. This check sees one snapshot,
|
|
17
|
+
* so it emits nothing for VSA012; what a deletion leaves behind still shows
|
|
18
|
+
* here as VSA001 for the orphaned behavior and VSA009 or AMP004 for the
|
|
19
|
+
* orphaned files.
|
|
20
|
+
*/
|
|
21
|
+
import type { Graph, Level } from "@intentset/core";
|
|
22
|
+
import { type Finding } from "./finding.ts";
|
|
23
|
+
import { type Model } from "./regions.ts";
|
|
24
|
+
export declare function checkOwnership(model: Model, graph: Graph, level: Level): Finding[];
|
|
25
|
+
//# sourceMappingURL=ownership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership.d.ts","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAY,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAW,MAAM,cAAc,CAAC;AAErD,OAAO,EAAmB,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAI3D,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,EAAE,CA0GlF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { LEVELS } from "@intentset/core";
|
|
2
|
+
import { finding } from "./finding.js";
|
|
3
|
+
import { compareStrings, matchPattern, validatePattern } from "./patterns.js";
|
|
4
|
+
import { describePackage } from "./regions.js";
|
|
5
|
+
const OWNED_STATUSES = new Set(["approved", "implemented", "released", "deprecated"]);
|
|
6
|
+
export function checkOwnership(model, graph, level) {
|
|
7
|
+
const findings = [];
|
|
8
|
+
if (LEVELS.indexOf(level) >= LEVELS.indexOf("L2")) {
|
|
9
|
+
const behaviors = [...graph.artifacts.values()]
|
|
10
|
+
.filter((artifact) => artifact.meta.type === "behavior" && OWNED_STATUSES.has(artifact.meta.status))
|
|
11
|
+
.sort((a, b) => compareStrings(a.meta.id, b.meta.id));
|
|
12
|
+
for (const behavior of behaviors) {
|
|
13
|
+
const id = behavior.meta.id;
|
|
14
|
+
const owners = (graph.in.get(id) ?? [])
|
|
15
|
+
.filter((edge) => edge.kind === "implements")
|
|
16
|
+
.map((edge) => graph.artifacts.get(edge.from))
|
|
17
|
+
.filter((slice) => slice?.meta.slice?.kind === "product")
|
|
18
|
+
.map((slice) => slice.meta.id)
|
|
19
|
+
.sort(compareStrings);
|
|
20
|
+
const unique = [...new Set(owners)];
|
|
21
|
+
if (unique.length === 1)
|
|
22
|
+
continue;
|
|
23
|
+
findings.push(finding({
|
|
24
|
+
code: "VSA001",
|
|
25
|
+
artifact: id,
|
|
26
|
+
path: behavior.path,
|
|
27
|
+
message: unique.length === 0
|
|
28
|
+
? `Behavior ${id} is ${behavior.meta.status} and no product slice implements it.`
|
|
29
|
+
: `Behavior ${id} is ${behavior.meta.status} and ${unique.length} product slices implement it: ${unique.join(", ")}.`,
|
|
30
|
+
remediation: unique.length === 0
|
|
31
|
+
? "Add it to the implements of the one product slice accountable for it, or retire it with replacedBy (VSA001)."
|
|
32
|
+
: "Keep implements on the one accountable slice and express the others through dependsOn and contracts (VSA001).",
|
|
33
|
+
paths: unique.map((owner) => graph.artifacts.get(owner).path),
|
|
34
|
+
edges: unique.map((owner) => ({ from: owner, to: id })),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const slice of model.slices) {
|
|
39
|
+
// The first entrypoint seen in each package; a second in the same package is reported against it.
|
|
40
|
+
const byPackage = new Map();
|
|
41
|
+
slice.meta.entrypoints.forEach((entrypoint, i) => {
|
|
42
|
+
const field = `/intentset/slice/entrypoints/${i}`;
|
|
43
|
+
if (entrypoint === "" || validatePattern(entrypoint) !== null || entrypoint.includes("*")) {
|
|
44
|
+
findings.push(finding({
|
|
45
|
+
code: "VSA002",
|
|
46
|
+
artifact: slice.id,
|
|
47
|
+
path: slice.path,
|
|
48
|
+
field,
|
|
49
|
+
message: `${slice.id} declares the entrypoint "${entrypoint}", which is not one repository-relative file path.`,
|
|
50
|
+
remediation: "Name the file that is the slice's public contract surface in its package, such as its index.ts (VSA002, TS001).",
|
|
51
|
+
}));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const pkg = model.packageOf(entrypoint);
|
|
55
|
+
const first = byPackage.get(pkg);
|
|
56
|
+
if (first !== undefined) {
|
|
57
|
+
findings.push(finding({
|
|
58
|
+
code: "VSA002",
|
|
59
|
+
artifact: slice.id,
|
|
60
|
+
path: slice.path,
|
|
61
|
+
field,
|
|
62
|
+
message: `${slice.id} declares two entrypoints in ${describePackage(pkg)}, ${first} and ${entrypoint}; a slice has one public surface per package it spans.`,
|
|
63
|
+
remediation: `Export what ${entrypoint} offers from ${first} and remove it from entrypoints, or move it into the package it serves (VSA002).`,
|
|
64
|
+
paths: [first, entrypoint],
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
else
|
|
68
|
+
byPackage.set(pkg, entrypoint);
|
|
69
|
+
if (!model.files.has(entrypoint)) {
|
|
70
|
+
findings.push(finding({
|
|
71
|
+
code: "VSA002",
|
|
72
|
+
artifact: slice.id,
|
|
73
|
+
path: slice.path,
|
|
74
|
+
field,
|
|
75
|
+
message: `The entrypoint ${entrypoint} of ${slice.id} is not a file in the repository.`,
|
|
76
|
+
remediation: "Create the entrypoint, empty if the slice exposes nothing yet, or correct the path (VSA002).",
|
|
77
|
+
paths: [entrypoint],
|
|
78
|
+
}));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const owned = slice.meta.claims.some((claim, k) => claim.kind === "source" && !slice.invalidClaims.includes(k) && matchPattern(claim.path, entrypoint));
|
|
82
|
+
if (!owned) {
|
|
83
|
+
findings.push(finding({
|
|
84
|
+
code: "VSA002",
|
|
85
|
+
artifact: slice.id,
|
|
86
|
+
path: slice.path,
|
|
87
|
+
field,
|
|
88
|
+
message: `The entrypoint ${entrypoint} of ${slice.id} lies outside every source claim of the slice.`,
|
|
89
|
+
remediation: "Move the entrypoint into the slice's source claim, or extend the claim to cover it (VSA002).",
|
|
90
|
+
paths: [entrypoint],
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return findings;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=ownership.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership.js","sourceRoot":"","sources":["../src/ownership.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository-relative POSIX path arithmetic. The repository root is "" and a
|
|
3
|
+
* path never starts with "/" or "./". Anything that climbs above the root is
|
|
4
|
+
* null, never clamped, because a path outside the repository is not a file
|
|
5
|
+
* this checker may attribute (VSA §3).
|
|
6
|
+
*/
|
|
7
|
+
/** Join and normalize; null when the result leaves the repository. */
|
|
8
|
+
export declare function joinPath(base: string, relative: string): string | null;
|
|
9
|
+
export declare function dirname(path: string): string;
|
|
10
|
+
export declare function basename(path: string): string;
|
|
11
|
+
/** The directory and each ancestor up to the root (""), nearest first. */
|
|
12
|
+
export declare function ancestors(directory: string): string[];
|
|
13
|
+
/** A path relative to a directory, or null when it is not inside it. */
|
|
14
|
+
export declare function within(directory: string, path: string): string | null;
|
|
15
|
+
export declare const CODE_EXTENSIONS: string[];
|
|
16
|
+
/** A file whose imports this checker reads. Declaration files included: their imports are type-only but still edges. */
|
|
17
|
+
export declare function isCode(path: string): boolean;
|
|
18
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAQrD;AAED,wEAAwE;AACxE,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIrE;AAED,eAAO,MAAM,eAAe,UAAiE,CAAC;AAE9F,wHAAwH;AACxH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5C"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository-relative POSIX path arithmetic. The repository root is "" and a
|
|
3
|
+
* path never starts with "/" or "./". Anything that climbs above the root is
|
|
4
|
+
* null, never clamped, because a path outside the repository is not a file
|
|
5
|
+
* this checker may attribute (VSA §3).
|
|
6
|
+
*/
|
|
7
|
+
/** Join and normalize; null when the result leaves the repository. */
|
|
8
|
+
export function joinPath(base, relative) {
|
|
9
|
+
const out = base === "" ? [] : base.split("/");
|
|
10
|
+
for (const segment of relative.split("/")) {
|
|
11
|
+
if (segment === "" || segment === ".")
|
|
12
|
+
continue;
|
|
13
|
+
if (segment === "..") {
|
|
14
|
+
if (out.length === 0)
|
|
15
|
+
return null;
|
|
16
|
+
out.pop();
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
out.push(segment);
|
|
20
|
+
}
|
|
21
|
+
return out.join("/");
|
|
22
|
+
}
|
|
23
|
+
export function dirname(path) {
|
|
24
|
+
const slash = path.lastIndexOf("/");
|
|
25
|
+
return slash === -1 ? "" : path.slice(0, slash);
|
|
26
|
+
}
|
|
27
|
+
export function basename(path) {
|
|
28
|
+
return path.slice(path.lastIndexOf("/") + 1);
|
|
29
|
+
}
|
|
30
|
+
/** The directory and each ancestor up to the root (""), nearest first. */
|
|
31
|
+
export function ancestors(directory) {
|
|
32
|
+
const out = [];
|
|
33
|
+
let current = directory;
|
|
34
|
+
for (;;) {
|
|
35
|
+
out.push(current);
|
|
36
|
+
if (current === "")
|
|
37
|
+
return out;
|
|
38
|
+
current = dirname(current);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** A path relative to a directory, or null when it is not inside it. */
|
|
42
|
+
export function within(directory, path) {
|
|
43
|
+
if (directory === "")
|
|
44
|
+
return path;
|
|
45
|
+
if (path === directory)
|
|
46
|
+
return "";
|
|
47
|
+
return path.startsWith(`${directory}/`) ? path.slice(directory.length + 1) : null;
|
|
48
|
+
}
|
|
49
|
+
export const CODE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
50
|
+
/** A file whose imports this checker reads. Declaration files included: their imports are type-only but still edges. */
|
|
51
|
+
export function isCode(path) {
|
|
52
|
+
return CODE_EXTENSIONS.some((extension) => path.endsWith(extension));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sEAAsE;AACtE,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB;IACrD,MAAM,GAAG,GAAa,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,GAAG;YAAE,SAAS;QAChD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAClC,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC;;YAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,SAAS,CAAC,SAAiB;IACzC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,OAAO,GAAG,SAAS,CAAC;IACxB,SAAS,CAAC;QACR,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClB,IAAI,OAAO,KAAK,EAAE;YAAE,OAAO,GAAG,CAAC;QAC/B,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,MAAM,CAAC,SAAiB,EAAE,IAAY;IACpD,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9F,wHAAwH;AACxH,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VSA §3 path patterns: repository-relative POSIX paths made of literal
|
|
3
|
+
* segments, `*` within one segment, and `**` across zero or more segments.
|
|
4
|
+
* Nothing else is special: `?`, `[` and `]` are literal characters, because
|
|
5
|
+
* real trees have directories named `[id]`. A `*` never matches `/`, so the
|
|
6
|
+
* only way to write a star that spans segments is `**` mixed with other
|
|
7
|
+
* characters, which validatePattern rejects.
|
|
8
|
+
*/
|
|
9
|
+
/** Why a pattern is not a v0.1 pattern, or null when it is one. */
|
|
10
|
+
export declare function validatePattern(pattern: string): string | null;
|
|
11
|
+
/** Does a repository-relative path match a VSA §3 pattern? Invalid patterns match nothing. */
|
|
12
|
+
export declare function matchPattern(pattern: string, path: string): boolean;
|
|
13
|
+
/** True when any of the patterns matches the path. */
|
|
14
|
+
export declare function matchAny(patterns: readonly string[], path: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve each claim against the repository's files: for claim i, the sorted
|
|
17
|
+
* files it matches, minus those any ignore pattern matches (VSA §3: source
|
|
18
|
+
* enumeration uses a versioned ignore list). An invalid pattern resolves to
|
|
19
|
+
* nothing; the caller reports it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function expandClaims(claims: readonly {
|
|
22
|
+
path: string;
|
|
23
|
+
}[], files: Iterable<string>, ignore: readonly string[]): string[][];
|
|
24
|
+
export declare function compareStrings(a: string, b: string): number;
|
|
25
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe9D;AAsBD,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBnE;AAED,sDAAsD;AACtD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,EACnC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,EAAE,EAAE,CAGZ;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D"}
|