chore: initialize from frontend template 4dc033c
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { readFile, readdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
function requiredPnpmCli(): string {
|
||||
const executable = process.env.npm_execpath;
|
||||
if (!executable) {
|
||||
throw new Error(
|
||||
"check:browser-file-storage-boundaries must run through pnpm",
|
||||
);
|
||||
}
|
||||
return executable;
|
||||
}
|
||||
|
||||
function runEslint(path: string) {
|
||||
return spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
requiredPnpmCli(),
|
||||
"exec",
|
||||
"eslint",
|
||||
path,
|
||||
"--no-ignore",
|
||||
"--max-warnings=0",
|
||||
],
|
||||
{ encoding: "utf8" },
|
||||
);
|
||||
}
|
||||
|
||||
function runEslintSource(source: string, virtualPath: string) {
|
||||
return spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
requiredPnpmCli(),
|
||||
"exec",
|
||||
"eslint",
|
||||
"--stdin",
|
||||
"--stdin-filename",
|
||||
virtualPath,
|
||||
"--no-ignore",
|
||||
"--max-warnings=0",
|
||||
],
|
||||
{ encoding: "utf8", input: source },
|
||||
);
|
||||
}
|
||||
|
||||
const allowed = runEslint(
|
||||
"tests/fixtures/browser-file-storage-boundaries/allowed",
|
||||
);
|
||||
const forbiddenRoot =
|
||||
"tests/fixtures/browser-file-storage-boundaries/forbidden";
|
||||
const forbiddenFiles = (
|
||||
await readdir(forbiddenRoot, { withFileTypes: true })
|
||||
)
|
||||
.filter((entry) => entry.isFile() && /\.tsx?$/u.test(entry.name))
|
||||
.map((entry) => path.join(forbiddenRoot, entry.name));
|
||||
const forbiddenResults = forbiddenFiles.map((file) => ({
|
||||
file,
|
||||
result: runEslint(file),
|
||||
}));
|
||||
const acceptedForbidden = forbiddenResults.filter(
|
||||
({ result }) => result.status === 0,
|
||||
);
|
||||
const indexedDbBypassSource = await readFile(
|
||||
path.join(forbiddenRoot, "direct-indexeddb.ts"),
|
||||
"utf8",
|
||||
);
|
||||
const objectUrlBypassSource = await readFile(
|
||||
path.join(forbiddenRoot, "object-url.ts"),
|
||||
"utf8",
|
||||
);
|
||||
const blobBypassSource = await readFile(
|
||||
path.join(forbiddenRoot, "direct-blob.ts"),
|
||||
"utf8",
|
||||
);
|
||||
const crossContextAdapterSource = await readFile(
|
||||
"tests/fixtures/browser-file-storage-boundaries/allowed/cross-context-host.ts",
|
||||
"utf8",
|
||||
);
|
||||
const browserStorageAdapterSource = await readFile(
|
||||
"tests/fixtures/browser-file-storage-boundaries/allowed/browser-storage-host.ts",
|
||||
"utf8",
|
||||
);
|
||||
const protectedSourceFixtureNames = [
|
||||
"aliased-globalthis.ts",
|
||||
"class-field-alias.ts",
|
||||
"constructor-root-escape.ts",
|
||||
"default-parameter-alias.ts",
|
||||
"direct-blob.ts",
|
||||
"dynamic-capability-key.ts",
|
||||
"global-object-container.ts",
|
||||
"identity-wrapped-global.ts",
|
||||
"instance-property-alias.ts",
|
||||
"property-descriptor-access.ts",
|
||||
] as const;
|
||||
const protectedSourceFixtures = await Promise.all(
|
||||
protectedSourceFixtureNames.map(async (file) => ({
|
||||
file,
|
||||
source: await readFile(path.join(forbiddenRoot, file), "utf8"),
|
||||
})),
|
||||
);
|
||||
const approvedAdapterResults = [
|
||||
{
|
||||
file: "src/adapters/storage/indexeddb/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
indexedDbBypassSource,
|
||||
"src/adapters/storage/indexeddb/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/adapters/cross-context-invalidation/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
crossContextAdapterSource,
|
||||
"src/adapters/cross-context-invalidation/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/adapters/storage/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
browserStorageAdapterSource,
|
||||
"src/adapters/storage/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/adapters/browser-transfer/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
blobBypassSource,
|
||||
"src/adapters/browser-transfer/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
];
|
||||
const rejectedApprovedAdapters = approvedAdapterResults.filter(
|
||||
({ result }) => result.status !== 0,
|
||||
);
|
||||
const misplacedAdapterResults = [
|
||||
{
|
||||
file: "src/adapters/http/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
indexedDbBypassSource,
|
||||
"src/adapters/http/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/features/reference-feature/adapters/boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
objectUrlBypassSource,
|
||||
"src/features/reference-feature/adapters/boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/adapters/http/cross-context-boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
crossContextAdapterSource,
|
||||
"src/adapters/http/cross-context-boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
{
|
||||
file: "src/adapters/http/browser-storage-boundary-fixture.ts",
|
||||
result: runEslintSource(
|
||||
browserStorageAdapterSource,
|
||||
"src/adapters/http/browser-storage-boundary-fixture.ts",
|
||||
),
|
||||
},
|
||||
...protectedSourceFixtures.map(({ file, source }) => {
|
||||
const virtualPath = `src/presentation/${file}`;
|
||||
return {
|
||||
file: virtualPath,
|
||||
result: runEslintSource(source, virtualPath),
|
||||
};
|
||||
}),
|
||||
];
|
||||
const acceptedMisplacedAdapters = misplacedAdapterResults.filter(
|
||||
({ result }) => result.status === 0,
|
||||
);
|
||||
|
||||
if (
|
||||
allowed.status !== 0 ||
|
||||
rejectedApprovedAdapters.length > 0 ||
|
||||
forbiddenFiles.length === 0 ||
|
||||
acceptedForbidden.length > 0 ||
|
||||
acceptedMisplacedAdapters.length > 0
|
||||
) {
|
||||
process.stderr.write(allowed.stderr || allowed.stdout);
|
||||
for (const { file, result } of rejectedApprovedAdapters) {
|
||||
process.stderr.write(
|
||||
`${file}: owned browser capability adapter was rejected\n`,
|
||||
);
|
||||
process.stderr.write(result.stderr || result.stdout);
|
||||
}
|
||||
for (const { file, result } of acceptedForbidden) {
|
||||
process.stderr.write(
|
||||
`${file}: forbidden browser API fixture was accepted\n`,
|
||||
);
|
||||
process.stderr.write(result.stderr || result.stdout);
|
||||
}
|
||||
for (const { file, result } of acceptedMisplacedAdapters) {
|
||||
process.stderr.write(
|
||||
`${file}: native browser storage access outside its owned adapter was accepted\n`,
|
||||
);
|
||||
process.stderr.write(result.stderr || result.stdout);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
`Browser file/storage boundaries: PASS (owned adapter allowed, ${forbiddenFiles.length + misplacedAdapterResults.length} direct or misplaced native access cases rejected)\n`,
|
||||
);
|
||||
Reference in New Issue
Block a user