fix: validate sandbox plugin exports and fix plugin packaging (#363)
* fix(webhook-notifier): add build step and export built files
The webhook-notifier plugin exported raw TypeScript source from its
package.json exports (./sandbox pointed to src/sandbox-entry.ts).
When the Vite plugin resolved this at site build time, it embedded
unbuilt TypeScript into the sandbox module, causing "Unexpected token
'{'" errors at runtime.
Add a tsdown build step (matching sandboxed-test's pattern) and update
the exports map to point to dist/*.mjs.
Fixes #150
* fix(core): reject unbuilt source in sandbox module generator and bundle validator
Add two validation checks to prevent plugins with misconfigured exports
from silently breaking site builds:
1. generateSandboxedPluginsModule() now throws a clear error if a
sandbox entrypoint resolves to a TypeScript/JSX source file instead
of pre-built JavaScript. This catches the problem at site build time
with an actionable message.
2. The `emdash bundle` command now validates that all package.json
exports point to built files (.js/.mjs), not source (.ts/.tsx/.jsx).
This catches the misconfiguration at plugin publish time, before
consumers are affected.
Fixes #150
* chore: add changeset for sandbox source validation
* fix: use slash syntax for e18e rule override in oxlintrc
The test file override for e18e/prefer-static-regex used parenthesis
syntax ("e18e(prefer-static-regex)") which is the diagnostic display
format, not the config format. Changed to slash syntax to match the
top-level rule declarations so the override actually takes effect.
* test: add tests for sandbox source validation
Add tests for both validation checks:
- generateSandboxedPluginsModule: verifies it embeds pre-built JS,
rejects .ts/.tsx/.mts source files, and includes the plugin ID in
error messages.
- findSourceExports: verifies it flags .ts/.tsx/.mts/.cts/.jsx exports,
accepts .mjs/.js exports, and handles conditional export maps.
Also extracts findSourceExports() from the inline bundle.ts validation
into bundle-utils.ts so it can be tested without the CLI harness.
* fix(atproto, audit-log): add build step and export built files
Same issue as webhook-notifier — both plugins exported raw TypeScript
source from their package.json sandbox exports. Add tsdown build steps
and update exports to point to dist/*.mjs.
* refactor(smoke): replace sequential per-site astro builds with recursive pnpm build
The build verification section was running `astro build` individually
and sequentially for every demo and template (~12 sites). Replace with
a single `pnpm run --recursive --filter {./demos/*} --filter
{./templates/*} build` which pnpm parallelizes automatically.
This commit is contained in:
8
.changeset/major-boxes-juggle.md
Normal file
8
.changeset/major-boxes-juggle.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"emdash": patch
|
||||||
|
"@emdash-cms/plugin-webhook-notifier": patch
|
||||||
|
"@emdash-cms/plugin-atproto": patch
|
||||||
|
"@emdash-cms/plugin-audit-log": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes sandboxed plugin entries failing when package exports point to unbuilt TypeScript source. Adds build-time and bundle-time validation to catch misconfigured plugin exports early.
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"typescript/no-unsafe-type-assertion": "off",
|
"typescript/no-unsafe-type-assertion": "off",
|
||||||
"typescript/no-unnecessary-type-assertion": "off",
|
"typescript/no-unnecessary-type-assertion": "off",
|
||||||
"unicorn/consistent-function-scoping": "off",
|
"unicorn/consistent-function-scoping": "off",
|
||||||
"e18e(prefer-static-regex)": "off"
|
"e18e/prefer-static-regex": "off"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import type { MediaProviderDescriptor } from "../../media/types.js";
|
|||||||
import { defaultSeed } from "../../seed/default.js";
|
import { defaultSeed } from "../../seed/default.js";
|
||||||
import type { PluginDescriptor } from "./runtime.js";
|
import type { PluginDescriptor } from "./runtime.js";
|
||||||
|
|
||||||
|
const TS_SOURCE_EXT_RE = /^\.(ts|tsx|mts|cts|jsx)$/;
|
||||||
|
|
||||||
/** Pattern to remove scoped package prefix from plugin ID */
|
/** Pattern to remove scoped package prefix from plugin ID */
|
||||||
const SCOPED_PREFIX_PATTERN = /^@[^/]+\/plugin-/;
|
const SCOPED_PREFIX_PATTERN = /^@[^/]+\/plugin-/;
|
||||||
|
|
||||||
@@ -435,7 +437,17 @@ export const sandboxedPlugins = [];
|
|||||||
|
|
||||||
// Resolve the bundle to a file path using project's require context
|
// Resolve the bundle to a file path using project's require context
|
||||||
const filePath = resolveModulePathFromProject(bundleSpecifier, projectRoot);
|
const filePath = resolveModulePathFromProject(bundleSpecifier, projectRoot);
|
||||||
// Read the source code
|
|
||||||
|
const ext = filePath.slice(filePath.lastIndexOf("."));
|
||||||
|
if (TS_SOURCE_EXT_RE.test(ext)) {
|
||||||
|
throw new Error(
|
||||||
|
`Sandboxed plugin "${descriptor.id}" entrypoint "${bundleSpecifier}" resolves to ` +
|
||||||
|
`unbuilt source (${filePath}). Sandbox entries must be pre-built JavaScript. ` +
|
||||||
|
`Ensure the plugin's package.json exports point to built files (e.g. dist/*.mjs) ` +
|
||||||
|
`and run the plugin's build step before building the site.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const code = readFileSync(filePath, "utf-8");
|
const code = readFileSync(filePath, "utf-8");
|
||||||
|
|
||||||
// Create the plugin entry with embedded code and sandbox config
|
// Create the plugin entry with embedded code and sandbox config
|
||||||
|
|||||||
@@ -213,6 +213,32 @@ export async function resolveSourceEntry(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Export validation ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
const TS_SOURCE_EXPORT_RE = /\.(?:ts|tsx|mts|cts|jsx)$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find package.json exports that point to source files instead of built output.
|
||||||
|
* Returns an array of `{ exportPath, resolvedPath }` for each offending export.
|
||||||
|
*/
|
||||||
|
export function findSourceExports(
|
||||||
|
exports: Record<string, unknown>,
|
||||||
|
): Array<{ exportPath: string; resolvedPath: string }> {
|
||||||
|
const issues: Array<{ exportPath: string; resolvedPath: string }> = [];
|
||||||
|
for (const [exportPath, exportValue] of Object.entries(exports)) {
|
||||||
|
const resolved =
|
||||||
|
typeof exportValue === "string"
|
||||||
|
? exportValue
|
||||||
|
: exportValue && typeof exportValue === "object" && "import" in exportValue
|
||||||
|
? (exportValue as { import: string }).import
|
||||||
|
: null;
|
||||||
|
if (resolved && TS_SOURCE_EXPORT_RE.test(resolved)) {
|
||||||
|
issues.push({ exportPath, resolvedPath: resolved });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return issues;
|
||||||
|
}
|
||||||
|
|
||||||
// ── Directory helpers ────────────────────────────────────────────────────────
|
// ── Directory helpers ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
extractManifest,
|
extractManifest,
|
||||||
findNodeBuiltinImports,
|
findNodeBuiltinImports,
|
||||||
findBuildOutput,
|
findBuildOutput,
|
||||||
|
findSourceExports,
|
||||||
resolveSourceEntry,
|
resolveSourceEntry,
|
||||||
calculateDirectorySize,
|
calculateDirectorySize,
|
||||||
createTarball,
|
createTarball,
|
||||||
@@ -495,6 +496,20 @@ export const bundleCommand = defineCommand({
|
|||||||
consola.start("Validating bundle...");
|
consola.start("Validating bundle...");
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
|
|
||||||
|
// Check that package.json exports point to built files, not source.
|
||||||
|
// Plugins published to npm with source exports will break site builds
|
||||||
|
// because the sandbox module generator embeds the resolved file as-is.
|
||||||
|
if (pkg.exports) {
|
||||||
|
for (const issue of findSourceExports(pkg.exports as Record<string, unknown>)) {
|
||||||
|
consola.error(
|
||||||
|
`Export "${issue.exportPath}" points to source (${issue.resolvedPath}). ` +
|
||||||
|
`Package exports must point to built files (e.g. dist/*.mjs). ` +
|
||||||
|
`Add a build step and update the exports map.`,
|
||||||
|
);
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check for Node.js builtins in backend.js
|
// Check for Node.js builtins in backend.js
|
||||||
const backendPath = join(bundleDir, "backend.js");
|
const backendPath = join(bundleDir, "backend.js");
|
||||||
if (await fileExists(backendPath)) {
|
if (await fileExists(backendPath)) {
|
||||||
|
|||||||
@@ -181,39 +181,37 @@ async function fetchWithRetry(url: string, retries = 10, delayMs = 1500): Promis
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Build verification — runs `astro build` for every site to catch adapter
|
// Build verification — runs a single recursive `pnpm build` across all demos
|
||||||
// and bundling errors that dev mode doesn't surface.
|
// and templates in parallel, then verifies each site produced output.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
describe.sequential("Site build verification", () => {
|
describe("Site build verification", () => {
|
||||||
const BUILD_TIMEOUT = 120_000;
|
it("all demos and templates build successfully", { timeout: 300_000 }, async () => {
|
||||||
|
await ensureBuilt();
|
||||||
|
|
||||||
for (const site of SITE_MATRIX) {
|
try {
|
||||||
if (site.mode === "typecheck") continue;
|
await execAsync(
|
||||||
|
"pnpm",
|
||||||
it(`${site.name} builds successfully`, { timeout: BUILD_TIMEOUT + 30_000 }, async () => {
|
["run", "--recursive", "--filter", "{./demos/*}", "--filter", "{./templates/*}", "build"],
|
||||||
await ensureBuilt();
|
{
|
||||||
|
cwd: WORKSPACE_ROOT,
|
||||||
try {
|
timeout: 240_000,
|
||||||
await execAsync("pnpm", ["exec", "astro", "build"], {
|
|
||||||
cwd: site.dir,
|
|
||||||
timeout: BUILD_TIMEOUT,
|
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
CI: "true",
|
CI: "true",
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
} catch (error) {
|
);
|
||||||
const stderr =
|
} catch (error) {
|
||||||
error instanceof Error && "stderr" in error ? (error as { stderr: string }).stderr : "";
|
const stderr =
|
||||||
const stdout =
|
error instanceof Error && "stderr" in error ? (error as { stderr: string }).stderr : "";
|
||||||
error instanceof Error && "stdout" in error ? (error as { stdout: string }).stdout : "";
|
const stdout =
|
||||||
throw new Error(`${site.name} build failed:\n\n${stderr || stdout}`.slice(0, 5000), {
|
error instanceof Error && "stdout" in error ? (error as { stdout: string }).stdout : "";
|
||||||
cause: error,
|
throw new Error(`Site builds failed:\n\n${stderr || stdout}`.slice(0, 5000), {
|
||||||
});
|
cause: error,
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
113
packages/core/tests/unit/astro/virtual-modules-sandbox.test.ts
Normal file
113
packages/core/tests/unit/astro/virtual-modules-sandbox.test.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import { mkdtemp, rm, writeFile, mkdir } from "node:fs/promises";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
||||||
|
|
||||||
|
import type { PluginDescriptor } from "../../../src/astro/integration/runtime.js";
|
||||||
|
import { generateSandboxedPluginsModule } from "../../../src/astro/integration/virtual-modules.js";
|
||||||
|
|
||||||
|
function descriptor(overrides: Partial<PluginDescriptor> = {}): PluginDescriptor {
|
||||||
|
return {
|
||||||
|
id: "test-plugin",
|
||||||
|
version: "1.0.0",
|
||||||
|
entrypoint: "@test/plugin/sandbox",
|
||||||
|
format: "standard",
|
||||||
|
capabilities: [],
|
||||||
|
allowedHosts: [],
|
||||||
|
storage: {},
|
||||||
|
adminPages: [],
|
||||||
|
adminWidgets: [],
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("generateSandboxedPluginsModule", () => {
|
||||||
|
let tmpDir: string;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tmpDir = await mkdtemp(join(tmpdir(), "emdash-vm-test-"));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await rm(tmpDir, { recursive: true, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
async function setupFakeProject(exportPath: string, content: string) {
|
||||||
|
// Create a fake project root with package.json
|
||||||
|
await writeFile(join(tmpDir, "package.json"), JSON.stringify({ name: "test-project" }));
|
||||||
|
|
||||||
|
// Create the plugin package inside node_modules
|
||||||
|
const pluginDir = join(tmpDir, "node_modules", "@test", "plugin");
|
||||||
|
await mkdir(pluginDir, { recursive: true });
|
||||||
|
|
||||||
|
// Determine the directory for the export file
|
||||||
|
const fileParts = exportPath.split("/");
|
||||||
|
if (fileParts.length > 1) {
|
||||||
|
const dir = join(pluginDir, ...fileParts.slice(0, -1));
|
||||||
|
await mkdir(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFile(join(pluginDir, exportPath), content);
|
||||||
|
await writeFile(
|
||||||
|
join(pluginDir, "package.json"),
|
||||||
|
JSON.stringify({
|
||||||
|
name: "@test/plugin",
|
||||||
|
exports: { "./sandbox": `./${exportPath}` },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
it("returns empty module when no plugins configured", () => {
|
||||||
|
const result = generateSandboxedPluginsModule([], tmpDir);
|
||||||
|
expect(result).toContain("export const sandboxedPlugins = []");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("embeds pre-built JavaScript successfully", async () => {
|
||||||
|
await setupFakeProject("dist/sandbox-entry.mjs", "export default { hooks: {} };");
|
||||||
|
|
||||||
|
const result = generateSandboxedPluginsModule(
|
||||||
|
[descriptor({ entrypoint: "@test/plugin/sandbox" })],
|
||||||
|
tmpDir,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toContain("sandboxedPlugins");
|
||||||
|
expect(result).toContain("test-plugin");
|
||||||
|
expect(result).toContain("export default { hooks: {} };");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws for .ts source files", async () => {
|
||||||
|
await setupFakeProject("src/sandbox-entry.ts", "export default {};");
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
generateSandboxedPluginsModule([descriptor({ entrypoint: "@test/plugin/sandbox" })], tmpDir),
|
||||||
|
).toThrow(/unbuilt source/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws for .tsx source files", async () => {
|
||||||
|
await setupFakeProject("src/sandbox-entry.tsx", "export default {};");
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
generateSandboxedPluginsModule([descriptor({ entrypoint: "@test/plugin/sandbox" })], tmpDir),
|
||||||
|
).toThrow(/unbuilt source/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws for .mts source files", async () => {
|
||||||
|
await setupFakeProject("src/sandbox-entry.mts", "export default {};");
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
generateSandboxedPluginsModule([descriptor({ entrypoint: "@test/plugin/sandbox" })], tmpDir),
|
||||||
|
).toThrow(/unbuilt source/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("includes plugin id in error message", async () => {
|
||||||
|
await setupFakeProject("src/sandbox-entry.ts", "export default {};");
|
||||||
|
|
||||||
|
expect(() =>
|
||||||
|
generateSandboxedPluginsModule(
|
||||||
|
[descriptor({ id: "my-broken-plugin", entrypoint: "@test/plugin/sandbox" })],
|
||||||
|
tmpDir,
|
||||||
|
),
|
||||||
|
).toThrow(/my-broken-plugin/);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
resolveSourceEntry,
|
resolveSourceEntry,
|
||||||
findNodeBuiltinImports,
|
findNodeBuiltinImports,
|
||||||
findBuildOutput,
|
findBuildOutput,
|
||||||
|
findSourceExports,
|
||||||
} from "../../../src/cli/commands/bundle-utils.js";
|
} from "../../../src/cli/commands/bundle-utils.js";
|
||||||
import type { ResolvedPlugin } from "../../../src/plugins/types.js";
|
import type { ResolvedPlugin } from "../../../src/plugins/types.js";
|
||||||
|
|
||||||
@@ -298,3 +299,62 @@ describe("findNodeBuiltinImports", () => {
|
|||||||
expect(findNodeBuiltinImports(code)).toEqual(["fs"]);
|
expect(findNodeBuiltinImports(code)).toEqual(["fs"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("findSourceExports", () => {
|
||||||
|
it("flags .ts exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./src/index.ts" });
|
||||||
|
expect(issues).toEqual([{ exportPath: ".", resolvedPath: "./src/index.ts" }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("flags .tsx exports", () => {
|
||||||
|
const issues = findSourceExports({ "./admin": "./src/admin.tsx" });
|
||||||
|
expect(issues).toEqual([{ exportPath: "./admin", resolvedPath: "./src/admin.tsx" }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("flags .mts exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./src/index.mts" });
|
||||||
|
expect(issues).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("flags .cts exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./src/index.cts" });
|
||||||
|
expect(issues).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("flags .jsx exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./src/index.jsx" });
|
||||||
|
expect(issues).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts .mjs exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./dist/index.mjs" });
|
||||||
|
expect(issues).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts .js exports", () => {
|
||||||
|
const issues = findSourceExports({ ".": "./dist/index.js" });
|
||||||
|
expect(issues).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles conditional exports with import field", () => {
|
||||||
|
const issues = findSourceExports({
|
||||||
|
".": { import: "./src/index.ts", types: "./dist/index.d.mts" },
|
||||||
|
});
|
||||||
|
expect(issues).toEqual([{ exportPath: ".", resolvedPath: "./src/index.ts" }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts conditional exports pointing to built files", () => {
|
||||||
|
const issues = findSourceExports({
|
||||||
|
".": { import: "./dist/index.mjs", types: "./dist/index.d.mts" },
|
||||||
|
});
|
||||||
|
expect(issues).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("flags multiple bad exports", () => {
|
||||||
|
const issues = findSourceExports({
|
||||||
|
".": "./src/index.ts",
|
||||||
|
"./sandbox": "./src/sandbox-entry.ts",
|
||||||
|
});
|
||||||
|
expect(issues).toHaveLength(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "AT Protocol / standard.site syndication plugin for EmDash CMS",
|
"description": "AT Protocol / standard.site syndication plugin for EmDash CMS",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "dist/index.mjs",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": {
|
||||||
"./sandbox": "./src/sandbox-entry.ts"
|
"import": "./dist/index.mjs",
|
||||||
|
"types": "./dist/index.d.mts"
|
||||||
|
},
|
||||||
|
"./sandbox": "./dist/sandbox-entry.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src"
|
"dist"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"emdash",
|
"emdash",
|
||||||
@@ -23,13 +26,17 @@
|
|||||||
],
|
],
|
||||||
"author": "Matt Kane",
|
"author": "Matt Kane",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"dependencies": {
|
||||||
"emdash": "workspace:*"
|
"emdash": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"tsdown": "catalog:",
|
||||||
|
"typescript": "catalog:",
|
||||||
"vitest": "catalog:"
|
"vitest": "catalog:"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean",
|
||||||
|
"dev": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --watch",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Audit logging plugin for EmDash CMS - tracks content changes",
|
"description": "Audit logging plugin for EmDash CMS - tracks content changes",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "dist/index.mjs",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": {
|
||||||
"./sandbox": "./src/sandbox-entry.ts"
|
"import": "./dist/index.mjs",
|
||||||
|
"types": "./dist/index.d.mts"
|
||||||
|
},
|
||||||
|
"./sandbox": "./dist/sandbox-entry.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src"
|
"dist"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"emdash",
|
"emdash",
|
||||||
@@ -21,12 +24,16 @@
|
|||||||
],
|
],
|
||||||
"author": "Matt Kane",
|
"author": "Matt Kane",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {},
|
"dependencies": {
|
||||||
"peerDependencies": {
|
|
||||||
"emdash": "workspace:*"
|
"emdash": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {
|
||||||
|
"tsdown": "catalog:",
|
||||||
|
"typescript": "catalog:"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean",
|
||||||
|
"dev": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --watch",
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {},
|
"optionalDependencies": {},
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Webhook notification plugin for EmDash CMS - posts to external URLs on content changes",
|
"description": "Webhook notification plugin for EmDash CMS - posts to external URLs on content changes",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "dist/index.mjs",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": {
|
||||||
"./sandbox": "./src/sandbox-entry.ts"
|
"import": "./dist/index.mjs",
|
||||||
|
"types": "./dist/index.d.mts"
|
||||||
|
},
|
||||||
|
"./sandbox": "./dist/sandbox-entry.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src"
|
"dist"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"emdash",
|
"emdash",
|
||||||
@@ -21,14 +24,18 @@
|
|||||||
],
|
],
|
||||||
"author": "Matt Kane",
|
"author": "Matt Kane",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"dependencies": {
|
||||||
"emdash": "workspace:*"
|
"emdash": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {
|
||||||
|
"tsdown": "catalog:",
|
||||||
|
"typescript": "catalog:"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean",
|
||||||
|
"dev": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --watch",
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
|
||||||
"optionalDependencies": {},
|
"optionalDependencies": {},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -1109,6 +1109,12 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../core
|
version: link:../../core
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
tsdown:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 0.20.3(@arethetypeswrong/core@0.18.2)(@typescript/native-preview@7.0.0-dev.20260213.1)(oxc-resolver@11.16.4)(publint@0.3.17)(typescript@5.9.3)
|
||||||
|
typescript:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.9.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 4.0.18(@types/node@24.10.13)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)
|
version: 4.0.18(@types/node@24.10.13)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)
|
||||||
@@ -1118,6 +1124,13 @@ importers:
|
|||||||
emdash:
|
emdash:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../core
|
version: link:../../core
|
||||||
|
devDependencies:
|
||||||
|
tsdown:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 0.20.3(@arethetypeswrong/core@0.18.2)(@typescript/native-preview@7.0.0-dev.20260213.1)(oxc-resolver@11.16.4)(publint@0.3.17)(typescript@5.9.3)
|
||||||
|
typescript:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.9.3
|
||||||
|
|
||||||
packages/plugins/color:
|
packages/plugins/color:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1199,6 +1212,13 @@ importers:
|
|||||||
emdash:
|
emdash:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../core
|
version: link:../../core
|
||||||
|
devDependencies:
|
||||||
|
tsdown:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 0.20.3(@arethetypeswrong/core@0.18.2)(@typescript/native-preview@7.0.0-dev.20260213.1)(oxc-resolver@11.16.4)(publint@0.3.17)(typescript@5.9.3)
|
||||||
|
typescript:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.9.3
|
||||||
|
|
||||||
packages/x402:
|
packages/x402:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15756,7 +15776,7 @@ snapshots:
|
|||||||
rolldown: 1.0.0-rc.3
|
rolldown: 1.0.0-rc.3
|
||||||
rolldown-plugin-dts: 0.22.2(@typescript/native-preview@7.0.0-dev.20260213.1)(oxc-resolver@11.16.4)(rolldown@1.0.0-rc.3)(typescript@5.9.3)
|
rolldown-plugin-dts: 0.22.2(@typescript/native-preview@7.0.0-dev.20260213.1)(oxc-resolver@11.16.4)(rolldown@1.0.0-rc.3)(typescript@5.9.3)
|
||||||
semver: 7.7.4
|
semver: 7.7.4
|
||||||
tinyexec: 1.0.2
|
tinyexec: 1.0.4
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
tree-kill: 1.2.2
|
tree-kill: 1.2.2
|
||||||
unconfig-core: 7.4.2
|
unconfig-core: 7.4.2
|
||||||
|
|||||||
Reference in New Issue
Block a user