mirror of
https://github.com/morluto/rea.git
synced 2026-11-03 05:16:16 +00:00
Bind typed service creation, observed availability and retryable cleanup in one composition owner. Reuse selected CLI/MCP factories and canonical contract groups without copying provider operation inventories. Closes #8429. Refs #740. Validated paired real application workflows, actual local Codex CLI Terra/high use, complete Evidence and Unknown checkpoint parity, compiler-backed import boundaries, SDK schemas and final real mixed routing. Automated review findings were fixed at their producing owners. Existing exact-base CodeQL alerts are documented on the PR under the owner-authorized unrelated-check exception; no global alerts or security rules were changed. Assisted-by: Suika (gensokyo-skills:suika-scatter-gather-planning)
107 lines
4.2 KiB
TypeScript
107 lines
4.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { fileURLToPath } from "node:url";
|
|
import ts from "typescript6";
|
|
|
|
import {
|
|
importSpecifier,
|
|
readImportSpecifiers,
|
|
} from "../../scripts/lib/import-specifiers.mjs";
|
|
|
|
// Convert only compiler options; this does not discover or compile the project.
|
|
const configuration = ts.readConfigFile(
|
|
fileURLToPath(new URL("../../tsconfig.json", import.meta.url)),
|
|
ts.sys.readFile.bind(ts.sys),
|
|
);
|
|
if (configuration.error !== undefined)
|
|
throw new Error("Could not read repository compiler options");
|
|
const compilerOptions = ts.convertCompilerOptionsFromJson(
|
|
configuration.config.compilerOptions,
|
|
fileURLToPath(new URL("../../", import.meta.url)),
|
|
);
|
|
if (compilerOptions.errors.length > 0)
|
|
throw new Error("Could not convert repository compiler options");
|
|
|
|
describe("import specifier reader", () => {
|
|
it("reads side-effect imports and ignores import-like text", () => {
|
|
expect(
|
|
readImportSpecifiers(`
|
|
// from "./commented.js"
|
|
/* import "./block-comment.js"; */
|
|
const text = "from './string.js'";
|
|
import "./side-effect.js";
|
|
import { value } from "./named.js";
|
|
export { value as again } from "./reexported.js";
|
|
const loaded = import("./dynamic.js");
|
|
`).map(({ specifier }) => specifier),
|
|
).toEqual([
|
|
"./side-effect.js",
|
|
"./named.js",
|
|
"./reexported.js",
|
|
"./dynamic.js",
|
|
]);
|
|
});
|
|
|
|
it("reads type, namespace, and empty-template specifiers", () => {
|
|
const facts = readImportSpecifiers(`import type { Fact } from "./types.js";
|
|
export * from "./all.js";
|
|
import name = require("./equals.js");
|
|
type Query = import("./query.js").Query;
|
|
const dynamic = import(\`./template.js\`);
|
|
const computed = import(name);
|
|
import "node:fs";
|
|
`);
|
|
expect(facts).toEqual([
|
|
{ specifier: "./types.js", line: 1, typeOnly: true },
|
|
{ specifier: "./all.js", line: 2, typeOnly: false },
|
|
{ specifier: "./equals.js", line: 3, typeOnly: false },
|
|
{ specifier: "./query.js", line: 4, typeOnly: true },
|
|
{ specifier: "./template.js", line: 5, typeOnly: false },
|
|
{ specifier: "node:fs", line: 7, typeOnly: false },
|
|
]);
|
|
});
|
|
|
|
it.each([
|
|
['import type Default from "./owner.js";', true],
|
|
['import type * as Namespace from "./owner.js";', true],
|
|
['import { type Port, type Other as Alias } from "./owner.js";', false],
|
|
['import { type Port, Constructor as Alias } from "./owner.js";', false],
|
|
['import Default, { type Port } from "./owner.js";', false],
|
|
['import {} from "./owner.js";', false],
|
|
['import "./owner.js";', false],
|
|
['export type { Port } from "./owner.js";', true],
|
|
['export { type Port, type Other as Alias } from "./owner.js";', false],
|
|
['export { type Port, Constructor as Alias } from "./owner.js";', false],
|
|
['export {} from "./owner.js";', false],
|
|
['export type * from "./owner.js";', true],
|
|
['export type * as Namespace from "./owner.js";', true],
|
|
['export * as Namespace from "./owner.js";', false],
|
|
['import type Owner = require("./owner.js");', true],
|
|
['import Owner = require("./owner.js");', false],
|
|
['type Port = import("./owner.js").Port;', true],
|
|
['type Constructor = typeof import("./owner.js").Constructor;', true],
|
|
['const Owner = import("./owner.js");', false],
|
|
["const Owner = import(`./owner.js`);", false],
|
|
])("matches TypeScript's emitted runtime edge for %s", (source, typeOnly) => {
|
|
expect(readImportSpecifiers(source)).toEqual([
|
|
{ specifier: "./owner.js", line: 1, typeOnly },
|
|
]);
|
|
expect(compilerOptions.options.verbatimModuleSyntax).toBe(true);
|
|
const emitted = ts.transpileModule(source, {
|
|
compilerOptions: compilerOptions.options,
|
|
// NodeNext emits import-equals through createRequire in an ESM file.
|
|
fileName: fileURLToPath(new URL("./import-owner.mts", import.meta.url)),
|
|
reportDiagnostics: true,
|
|
});
|
|
expect(
|
|
emitted.diagnostics?.filter(
|
|
(diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error,
|
|
),
|
|
).toEqual([]);
|
|
expect(emitted.outputText.includes("./owner.js")).toBe(!typeOnly);
|
|
});
|
|
|
|
it("ignores nodes that are not static imports", () => {
|
|
expect(importSpecifier({ type: "Identifier" })).toBeUndefined();
|
|
});
|
|
});
|