Merge public-gh/master into paperclip-company-import-export

This commit is contained in:
Dotta
2026-03-14 21:45:54 -05:00
198 changed files with 57956 additions and 448 deletions

View File

@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";
import { extractLegacyPlanBody } from "../services/documents.js";
describe("extractLegacyPlanBody", () => {
it("returns null when no plan block exists", () => {
expect(extractLegacyPlanBody("hello world")).toBeNull();
});
it("extracts plan body from legacy issue descriptions", () => {
expect(
extractLegacyPlanBody(`
intro
<plan>
# Plan
- one
- two
</plan>
`),
).toBe("# Plan\n\n- one\n- two");
});
it("ignores empty plan blocks", () => {
expect(extractLegacyPlanBody("<plan> </plan>")).toBeNull();
});
});

View File

@@ -0,0 +1,68 @@
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { resolvePluginWatchTargets } from "../services/plugin-dev-watcher.js";
const tempDirs: string[] = [];
afterEach(() => {
while (tempDirs.length > 0) {
const dir = tempDirs.pop();
if (dir) rmSync(dir, { recursive: true, force: true });
}
});
function makeTempPluginDir(): string {
const dir = mkdtempSync(path.join(os.tmpdir(), "paperclip-plugin-watch-"));
tempDirs.push(dir);
return dir;
}
describe("resolvePluginWatchTargets", () => {
it("watches package metadata plus concrete declared runtime files", () => {
const pluginDir = makeTempPluginDir();
mkdirSync(path.join(pluginDir, "dist", "ui"), { recursive: true });
writeFileSync(
path.join(pluginDir, "package.json"),
JSON.stringify({
name: "@acme/example",
paperclipPlugin: {
manifest: "./dist/manifest.js",
worker: "./dist/worker.js",
ui: "./dist/ui",
},
}),
);
writeFileSync(path.join(pluginDir, "dist", "manifest.js"), "export default {};\n");
writeFileSync(path.join(pluginDir, "dist", "worker.js"), "export default {};\n");
writeFileSync(path.join(pluginDir, "dist", "ui", "index.js"), "export default {};\n");
writeFileSync(path.join(pluginDir, "dist", "ui", "index.css"), "body {}\n");
const targets = resolvePluginWatchTargets(pluginDir);
expect(targets).toEqual([
{ path: path.join(pluginDir, "dist", "manifest.js"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "dist", "ui", "index.css"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "dist", "ui", "index.js"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "dist", "worker.js"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "package.json"), recursive: false, kind: "file" },
]);
});
it("falls back to dist when package metadata does not declare entrypoints", () => {
const pluginDir = makeTempPluginDir();
mkdirSync(path.join(pluginDir, "dist", "nested"), { recursive: true });
writeFileSync(path.join(pluginDir, "package.json"), JSON.stringify({ name: "@acme/example" }));
writeFileSync(path.join(pluginDir, "dist", "manifest.js"), "export default {};\n");
writeFileSync(path.join(pluginDir, "dist", "nested", "chunk.js"), "export default {};\n");
const targets = resolvePluginWatchTargets(pluginDir);
expect(targets).toEqual([
{ path: path.join(pluginDir, "package.json"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "dist", "manifest.js"), recursive: false, kind: "file" },
{ path: path.join(pluginDir, "dist", "nested", "chunk.js"), recursive: false, kind: "file" },
]);
});
});

View File

@@ -0,0 +1,43 @@
import { describe, expect, it } from "vitest";
import { appendStderrExcerpt, formatWorkerFailureMessage } from "../services/plugin-worker-manager.js";
describe("plugin-worker-manager stderr failure context", () => {
it("appends worker stderr context to failure messages", () => {
expect(
formatWorkerFailureMessage(
"Worker process exited (code=1, signal=null)",
"TypeError: Unknown file extension \".ts\"",
),
).toBe(
"Worker process exited (code=1, signal=null)\n\nWorker stderr:\nTypeError: Unknown file extension \".ts\"",
);
});
it("does not duplicate stderr that is already present", () => {
const message = [
"Worker process exited (code=1, signal=null)",
"",
"Worker stderr:",
"TypeError: Unknown file extension \".ts\"",
].join("\n");
expect(
formatWorkerFailureMessage(message, "TypeError: Unknown file extension \".ts\""),
).toBe(message);
});
it("keeps only the latest stderr excerpt", () => {
let excerpt = "";
excerpt = appendStderrExcerpt(excerpt, "first line");
excerpt = appendStderrExcerpt(excerpt, "second line");
expect(excerpt).toContain("first line");
expect(excerpt).toContain("second line");
excerpt = appendStderrExcerpt(excerpt, "x".repeat(9_000));
expect(excerpt).not.toContain("first line");
expect(excerpt).not.toContain("second line");
expect(excerpt.length).toBeLessThanOrEqual(8_000);
});
});