CI / format (pull_request) Successful in 1m58s
CI / lint (pull_request) Successful in 2m0s
CI / install (pull_request) Successful in 5m26s
CI / typetest (pull_request) Successful in 1m27s
CI / node-tests (pull_request) Successful in 1m48s
CI / typecheck (pull_request) Successful in 1m49s
CI / browser-tests (pull_request) Successful in 3m10s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
82 lines
3.0 KiB
JavaScript
82 lines
3.0 KiB
JavaScript
import assert from "node:assert/strict"
|
|
import path from "node:path"
|
|
import { test } from "node:test"
|
|
import { ESLint } from "eslint"
|
|
|
|
const eslint = new ESLint()
|
|
|
|
async function messages(
|
|
source,
|
|
filePath = "packages/sftp/src/package-boundary-check.ts",
|
|
instance = eslint,
|
|
) {
|
|
const [result] = await instance.lintText(source, { filePath })
|
|
return result.messages.map(({ message, ruleId }) => ({ message, ruleId }))
|
|
}
|
|
|
|
test("rejects cross-package internal imports", async () => {
|
|
for (const specifier of [
|
|
"@webnet/ssh/_internals",
|
|
"@webnet/ssh/_internals.js",
|
|
"@webnet/transport/loopback/_internals",
|
|
"@webnet/transport/loopback/_internals.js",
|
|
]) {
|
|
const result = await messages(`import { Reader } from "${specifier}"; void Reader`)
|
|
assert.ok(result.some(({ ruleId }) => ruleId === "no-restricted-imports"))
|
|
}
|
|
})
|
|
|
|
test("rejects dynamic cross-package internal imports", async () => {
|
|
const result = await messages('await import("@webnet/ssh/_internals.js")')
|
|
assert.ok(result.some(({ ruleId }) => ruleId === "no-restricted-syntax"))
|
|
})
|
|
|
|
test("rejects relative cross-package source escapes", async () => {
|
|
for (const [source, filePath] of [
|
|
['import { Reader } from "../../ssh/src/cursor.js"; void Reader'],
|
|
[
|
|
'await import("../../../ssh/src/cursor.js")',
|
|
"packages/sftp/src/server/package-boundary-check.ts",
|
|
],
|
|
['export { Reader } from "../../ssh/src/cursor.js"'],
|
|
['import { Reader } from "../../ssh/./src/cursor.js"; void Reader'],
|
|
['await import("../.././ssh/src/cursor.js")'],
|
|
['export { Reader } from "../../ssh/other/../src/cursor.js"'],
|
|
['import "../../ssh/dist/index.js"'],
|
|
]) {
|
|
const result = await messages(source, filePath)
|
|
assert.ok(
|
|
result.some(
|
|
({ message, ruleId }) =>
|
|
ruleId === "package-boundary/no-relative-source-escapes" &&
|
|
message.includes("Relative cross-package"),
|
|
),
|
|
)
|
|
}
|
|
})
|
|
|
|
test("rejects relative source escapes when invoked from a package directory", async () => {
|
|
const packageEslint = new ESLint({ cwd: path.resolve("packages/sftp") })
|
|
const result = await messages(
|
|
'import { Reader } from "../../ssh/src/cursor.js"; void Reader',
|
|
"src/package-boundary-check.ts",
|
|
packageEslint,
|
|
)
|
|
assert.ok(result.some(({ ruleId }) => ruleId === "package-boundary/no-relative-source-escapes"))
|
|
})
|
|
|
|
test("rejects wildcard and cross-package re-exports", async () => {
|
|
const wildcard = await messages('export * from "./local.js"')
|
|
assert.ok(wildcard.some(({ message }) => message.includes("Wildcard exports")))
|
|
|
|
const crossPackage = await messages('export { VFSError } from "@webnet/vfs"')
|
|
assert.ok(crossPackage.some(({ message }) => message.includes("Cross-package re-exports")))
|
|
})
|
|
|
|
test("allows public imports and explicit package-local exports", async () => {
|
|
const result = await messages(
|
|
'import { SSHClientConnection } from "@webnet/ssh"; import { Reader } from "./sftp/cursor.js"; export { SSHClientConnection, Reader }',
|
|
)
|
|
assert.deepEqual(result, [])
|
|
})
|