Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions architecture.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,42 @@
"layer": "extensions",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/preflight.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "control"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/s3-credentials-resource.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "control"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/s3-credentials.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/s3-store.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/param.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/secret.ts",
"domain": "prisma-cloud",
"layer": "extensions",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/cron/src/scheduler-service.ts",
"domain": "prisma-cloud",
Expand Down Expand Up @@ -270,6 +306,114 @@
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/index.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/contract.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/storage-module.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/storage-service.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/store.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/storage-entrypoint.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/storage-server.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/handler.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/sigv4.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/pg-store.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/memory-store.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/storage/src/testing.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/index.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/contract.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/streams-module.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/streams-service.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/streams-entrypoint.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/1-prisma-cloud/2-shared-modules/streams/src/testing.ts",
"domain": "prisma-cloud",
"layer": "modules",
"plane": "execution"
},
{
"glob": "packages/9-public/composer/src/deploy.ts",
"domain": "public",
Expand Down Expand Up @@ -365,6 +509,30 @@
"domain": "public",
"layer": "public",
"plane": "shared"
},
{
"glob": "packages/9-public/composer-prisma-cloud/src/storage.ts",
"domain": "public",
"layer": "public",
"plane": "shared"
},
{
"glob": "packages/9-public/composer-prisma-cloud/src/streams.ts",
"domain": "public",
"layer": "public",
"plane": "shared"
},
{
"glob": "packages/9-public/composer-prisma-cloud/src/storage-testing.ts",
"domain": "public",
"layer": "public",
"plane": "execution"
},
{
"glob": "packages/9-public/composer-prisma-cloud/src/streams-testing.ts",
"domain": "public",
"layer": "public",
"plane": "execution"
}
],
"rules": {
Expand Down
26 changes: 3 additions & 23 deletions dependency-cruiser.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import config from './architecture.config.json' with { type: 'json' };
import { normalizeGlob } from './scripts/architecture-coverage.mjs';

const {
packages: packageConfigs,
Expand All @@ -25,28 +26,6 @@ const {
crossDomainRules,
} = config;

const normalizeGlob = (glob) => {
const DOUBLE_WILDCARD = '__DOUBLE_WILDCARD__';
const SINGLE_WILDCARD = '__SINGLE_WILDCARD__';
const hasWildcard = glob.includes('*');
const lastPathSegment = glob.split('/').pop() ?? '';
const isFileLikePattern = !hasWildcard && lastPathSegment.includes('.');

let pattern = glob
.replace(/\*\*/g, DOUBLE_WILDCARD)
.replace(/\*/g, SINGLE_WILDCARD)
.replaceAll(DOUBLE_WILDCARD, '.*')
.replaceAll(SINGLE_WILDCARD, '[^/]*');

if (isFileLikePattern) {
return `^${pattern}$`;
}
if (!hasWildcard && !pattern.endsWith('/')) {
pattern += '/.*';
}
return `^${pattern}`;
};

const moduleGroupMap = new Map();

for (const pkgConfig of packageConfigs) {
Expand Down Expand Up @@ -233,8 +212,9 @@ export default {
'node_modules',
'^packages/.*\\.test\\.',
'^packages/.*\\.test-d\\.',
'^packages/.*\\.vitest\\.',
'^packages/.*__tests__',
'vitest\\.config',
'vitest\\..*config',
'tsdown\\.config',
'next\\.config',
'\\.d\\.ts$',
Expand Down
3 changes: 3 additions & 0 deletions lint-staged.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ export default {
'{packages,examples,test}/**/*.{ts,tsx}': () => 'pnpm lint:deps',
'architecture.config.json': () => 'pnpm lint:deps',
'dependency-cruiser.config.mjs': () => 'pnpm lint:deps',
// Dropping a `paths` entry makes the cruiser resolve that import to built
// dist, which is excluded — the edge vanishes and no rule fires on it.
'tsconfig.depcruise.json': () => 'pnpm lint:deps',
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"typecheck": "turbo run typecheck",
"clean": "turbo run clean",
"prepare": "husky && skills add prisma/skills --skill '*' --agent universal claude-code -y && skills add ./skills-contrib --skill '*' --agent universal claude-code -y && node scripts/sync-agent-rules.mjs",
"lint:deps": "depcruise --config dependency-cruiser.config.mjs packages examples test website && node scripts/lint-publishable-location.mjs && node scripts/lint-framework-vocabulary.mjs"
"lint:deps": "depcruise --config dependency-cruiser.config.mjs packages examples test website && node scripts/lint-architecture-coverage.mjs && node scripts/lint-publishable-location.mjs && node scripts/lint-framework-vocabulary.mjs"
},
"devDependencies": {
"@biomejs/biome": "2.5.3",
Expand Down
56 changes: 56 additions & 0 deletions scripts/architecture-coverage.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Shared helpers for the architecture lint (ADR-0028).
*
* `normalizeGlob` is imported by both dependency-cruiser.config.mjs (which
* turns architecture.config.json into cruiser rules) and
* lint-architecture-coverage.mjs (which checks every source file is
* classified). If the check used its own matcher it could report a file as
* classified while the cruiser matched no group and applied no rule to it.
*/

export const normalizeGlob = (glob) => {
const DOUBLE_WILDCARD = '__DOUBLE_WILDCARD__';
const SINGLE_WILDCARD = '__SINGLE_WILDCARD__';
const hasWildcard = glob.includes('*');
const lastPathSegment = glob.split('/').pop() ?? '';
const isFileLikePattern = !hasWildcard && lastPathSegment.includes('.');

let pattern = glob
.replace(/\*\*/g, DOUBLE_WILDCARD)
.replace(/\*/g, SINGLE_WILDCARD)
.replaceAll(DOUBLE_WILDCARD, '.*')
.replaceAll(SINGLE_WILDCARD, '[^/]*');

if (isFileLikePattern) {
return `^${pattern}$`;
}
if (!hasWildcard && !pattern.endsWith('/')) {
pattern += '/.*';
}
return `^${pattern}`;
};

export const findUnclassifiedFiles = (files, packageConfigs) => {
const matchers = packageConfigs.map((pkgConfig) => new RegExp(normalizeGlob(pkgConfig.glob)));
return files.filter((file) => !matchers.some((matcher) => matcher.test(file)));
};

const IMPORT_SPECIFIER = /(?:from|import)\s*\(?\s*['"]([^'"]+)['"]/g;

export const readImportSpecifiers = (source) =>
[...source.matchAll(IMPORT_SPECIFIER)].map((match) => match[1]);

/**
* Workspace specifiers that `paths` does not alias to source. Their package
* `exports` maps point at built dist, which the cruiser excludes, so the edge
* is dropped and no rule can fire on it.
*/
export const findUnaliasedSpecifiers = (specifiers, workspacePackageNames, paths) => {
const belongsToWorkspace = (specifier) =>
workspacePackageNames.some((name) => specifier === name || specifier.startsWith(`${name}/`));

return [...new Set(specifiers)]
.filter(belongsToWorkspace)
.filter((specifier) => !Object.hasOwn(paths, specifier))
.sort();
};
Loading
Loading