@hoardodile/create-plugin 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/template/.github/ISSUE_TEMPLATE/bug_report.yml +57 -0
- package/dist/template/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
- package/dist/template/.github/dependabot.yml +10 -0
- package/dist/template/.github/workflows/ci.yml +47 -0
- package/dist/template/.github/workflows/release.yml +16 -5
- package/dist/template/.nvmrc +1 -0
- package/dist/template/CONTRIBUTING.md +63 -0
- package/dist/template/README.md +54 -13
- package/dist/template/SECURITY.md +26 -0
- package/dist/template/intro.en.md +18 -0
- package/dist/template/intro.zh.md +15 -0
- package/dist/template/manifest.json +1 -0
- package/dist/template/package.json +29 -2
- package/dist/template/scripts/release.mjs +54 -0
- package/dist/template/scripts/sync-version.mjs +38 -0
- package/dist/template/src/main.ts +15 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -22,12 +22,14 @@ var SDK_DEP_NAMES = [
|
|
|
22
22
|
|
|
23
23
|
// src/rewrite.ts
|
|
24
24
|
var THIRD_PARTY_VERSIONS = {
|
|
25
|
+
"@release-it/conventional-changelog": "^12.0.0",
|
|
25
26
|
"@types/node": "^26.2.0",
|
|
26
27
|
"@types/react": "^19.2.18",
|
|
27
28
|
"@types/react-dom": "^19.2.4",
|
|
28
29
|
jsdom: "^30.0.1",
|
|
29
30
|
react: "^19.2.8",
|
|
30
31
|
"react-dom": "^19.2.8",
|
|
32
|
+
"release-it": "^21.0.2",
|
|
31
33
|
typescript: "^7.0.2",
|
|
32
34
|
vite: "^8.2.2",
|
|
33
35
|
vitest: "^4.1.11"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sdk-deps.gen.ts","../src/rewrite.ts","../src/index.ts"],"names":["join"],"mappings":"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","file":"index.js","sourcesContent":["// GENERATED by scripts/gen-sdk-deps.mjs — never hand-edit.\n// The published SDK closure a scaffolded plugin can depend on; kept in\n// lockstep with scripts/lib/sdk-closure.mjs (see sdks:pack).\nexport const SDK_DEP_NAMES: readonly string[] = [\n\t\"@hoardodile/cli\",\n\t\"@hoardodile/host\",\n\t\"@hoardodile/host-web\",\n\t\"@hoardodile/i18n\",\n\t\"@hoardodile/sdk-react\",\n\t\"@hoardodile/sdk-server\",\n\t\"@hoardodile/sdk-types\",\n\t\"@hoardodile/sdk-web\",\n\t\"@hoardodile/ui\",\n\t\"@hoardodile/workbench\",\n]\n","/**\n * Scaffold-time rewrites applied to the embedded template copy: fresh\n * manifest identity and concrete dependency specs (the template uses\n * `workspace:*` / `catalog:` which only resolve inside the monorepo).\n */\nimport { join } from \"node:path\"\nimport { SDK_DEP_NAMES } from \"./sdk-deps.gen.ts\"\n\n/** Concrete versions for the catalog: specs the template uses. */\nexport const THIRD_PARTY_VERSIONS: Readonly<Record<string, string>> = {\n\t\"@types/node\": \"^26.2.0\",\n\t\"@types/react\": \"^19.2.18\",\n\t\"@types/react-dom\": \"^19.2.4\",\n\tjsdom: \"^30.0.1\",\n\treact: \"^19.2.8\",\n\t\"react-dom\": \"^19.2.8\",\n\ttypescript: \"^7.0.2\",\n\tvite: \"^8.2.2\",\n\tvitest: \"^4.1.11\",\n}\n\nexport type ManifestShape = {\n\tid: string\n\tname: string\n\tdescription: string\n\tversion: string\n\ti18n?: {\n\t\tname?: Record<string, string>\n\t\tdescription?: Record<string, string>\n\t}\n}\n\nexport function rewriteManifest(\n\tmanifest: ManifestShape,\n\tpluginName: string,\n): ManifestShape {\n\tmanifest.id = crypto.randomUUID()\n\tmanifest.name = pluginName\n\tmanifest.description = `Content plugin: ${pluginName}`\n\tif (manifest.i18n?.name !== undefined) {\n\t\tmanifest.i18n.name.en = pluginName\n\t}\n\tif (manifest.i18n?.description !== undefined) {\n\t\tmanifest.i18n.description.en = `Content plugin: ${pluginName}`\n\t}\n\tmanifest.version = \"0.0.1\"\n\treturn manifest\n}\n\nexport type PackageJson = {\n\tname: string\n\tversion?: string\n\tdependencies?: Record<string, string>\n\tdevDependencies?: Record<string, string>\n}\n\nexport function tarballSpec(\n\ttarballsDir: string,\n\tdep: string,\n\tversion: string,\n): string {\n\tconst fileName = dep.replace(\"@\", \"\").replace(\"/\", \"-\")\n\treturn `file:${join(tarballsDir, `${fileName}-${version}.tgz`).replaceAll(\"\\\\\", \"/\")}`\n}\n\nfunction rewriteDepBlock(\n\tdeps: Record<string, string> | undefined,\n\ttarballsDir: string | undefined,\n\tsdkVersion: string,\n): Record<string, string> {\n\tconst out = { ...deps }\n\tfor (const [dep, spec] of Object.entries(out)) {\n\t\tif (SDK_DEP_NAMES.includes(dep)) {\n\t\t\tout[dep] =\n\t\t\t\ttarballsDir !== undefined\n\t\t\t\t\t? tarballSpec(tarballsDir, dep, sdkVersion)\n\t\t\t\t\t: // `^0.2.0-alpha.3` would never match the 0.2.0 stable\n\t\t\t\t\t\t// release (semver keeps prereleases out of plain ranges),\n\t\t\t\t\t\t// so npm specs drop the prerelease suffix.\n\t\t\t\t\t\t`^${sdkVersion.split(\"-\")[0]}`\n\t\t} else if (spec === \"catalog:\") {\n\t\t\tconst version = THIRD_PARTY_VERSIONS[dep]\n\t\t\tif (version === undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`template dependency \"${dep}\" has no concrete version mapping`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tout[dep] = version\n\t\t}\n\t}\n\treturn out\n}\n\nexport function rewritePackageJson(\n\tpkg: PackageJson,\n\tpluginName: string,\n\topts: { readonly tarballsDir?: string; readonly sdkVersion: string },\n): PackageJson {\n\tpkg.name = pluginName\n\tdelete pkg.version\n\tpkg.version = \"0.0.1\"\n\tif (pkg.dependencies !== undefined) {\n\t\tpkg.dependencies = rewriteDepBlock(\n\t\t\tpkg.dependencies,\n\t\t\topts.tarballsDir,\n\t\t\topts.sdkVersion,\n\t\t)\n\t}\n\tif (pkg.devDependencies !== undefined) {\n\t\tpkg.devDependencies = rewriteDepBlock(\n\t\t\tpkg.devDependencies,\n\t\t\topts.tarballsDir,\n\t\t\topts.sdkVersion,\n\t\t)\n\t}\n\treturn pkg\n}\n\n/**\n * Install-script dependencies that land in a scaffolded plugin through\n * host's optionalDependencies (the same names as the root workspace's\n * allowBuilds). pnpm refuses to run their build scripts without an\n * explicit approval, so the generated workspace approves them up front.\n */\nconst ALLOWED_BUILDS = [\n\t\"@derhuerst/ffprobe-static\",\n\t\"@hoardodile/7z-bin\",\n\t\"ffmpeg-static\",\n]\n\nexport function tarballOverridesYaml(\n\ttarballsDir: string,\n\tsdkVersion: string,\n): string {\n\tconst lines = SDK_DEP_NAMES.map(\n\t\t(dep) => ` '${dep}': '${tarballSpec(tarballsDir, dep, sdkVersion)}'`,\n\t).join(\"\\n\")\n\tconst builds = ALLOWED_BUILDS.map((dep) => ` '${dep}': true`).join(\"\\n\")\n\treturn [\n\t\t\"# Redirect the cross-SDK 0.0.0 specs packed into the tarballs to the\",\n\t\t\"# sibling tarballs in this workspace; approve the install scripts of\",\n\t\t\"# host's optional binaries (ffmpeg/ffprobe/7-Zip) so pnpm runs them.\",\n\t\t\"overrides:\",\n\t\tlines,\n\t\t\"allowBuilds:\",\n\t\tbuilds,\n\t\t\"\",\n\t].join(\"\\n\")\n}\n","#!/usr/bin/env node\n/**\n * `create-hoardodile-plugin` — scaffold a new content plugin from the\n * embedded template copy (`src/template/`, kept in sync with\n * `plugins/template` by scripts/sync-template.mjs).\n *\n * Flow: interactive prompts (name, id auto-generated) → copy template →\n * rewrite manifest + package.json → install dependencies → validate the\n * manifest → print the dev loop entry points.\n *\n * create-hoardodile-plugin my-plugin\n * create-hoardodile-plugin my-plugin --tarballs ../hoardodile/tmp/sdks\n *\n * `--tarballs <dir>` rewires the SDK deps to packed tarballs plus a\n * pnpm-workspace.yaml with the cross-package overrides — used by the\n * release smoke test and for offline installs.\n */\nimport { spawn } from \"node:child_process\"\nimport {\n\tcpSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\twriteFileSync,\n} from \"node:fs\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport {\n\tcancel,\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\toutro,\n\ttext,\n} from \"@clack/prompts\"\nimport { pluginManifest } from \"@hoardodile/sdk-types/schema\"\nimport {\n\trewriteManifest,\n\trewritePackageJson,\n\ttarballOverridesYaml,\n} from \"./rewrite.ts\"\n\nconst ROOT = resolve(dirname(fileURLToPath(import.meta.url)), \"..\")\n// The template ships inside dist (dist/template) — the bin always runs\n// from the built artifact, so resolve relative to this module.\nconst TEMPLATE_DIR = resolve(\n\tdirname(fileURLToPath(import.meta.url)),\n\t\"template\",\n)\nconst SELF_VERSION = JSON.parse(\n\treadFileSync(join(ROOT, \"package.json\"), \"utf8\"),\n).version\n\nfunction writeJson(path: string, value: unknown): void {\n\twriteFileSync(path, `${JSON.stringify(value, null, \"\\t\")}\\n`)\n}\n\nfunction writeTarballOverrides(targetDir: string, tarballsDir: string): void {\n\twriteFileSync(\n\t\tjoin(targetDir, \"pnpm-workspace.yaml\"),\n\t\ttarballOverridesYaml(tarballsDir, SELF_VERSION),\n\t)\n}\n\nasync function runInstall(targetDir: string): Promise<void> {\n\tlog.step(\"Installing dependencies (pnpm install)\")\n\treturn new Promise<void>((resolveDone, reject) => {\n\t\tconst child = spawn(\"pnpm\", [\"install\"], {\n\t\t\tcwd: targetDir,\n\t\t\tstdio: \"inherit\",\n\t\t\tshell: process.platform === \"win32\",\n\t\t})\n\t\tchild.on(\"error\", reject)\n\t\tchild.on(\"exit\", (code) =>\n\t\t\tcode === 0\n\t\t\t\t? resolveDone()\n\t\t\t\t: reject(new Error(`pnpm install exited ${code}`)),\n\t\t)\n\t})\n}\n\nexport async function main() {\n\tconst positional = process.argv.slice(2).filter((a) => !a.startsWith(\"--\"))\n\tconst tarballsFlag = process.argv.indexOf(\"--tarballs\")\n\tconst tarballsDir =\n\t\ttarballsFlag !== -1\n\t\t\t? resolve(process.argv[tarballsFlag + 1] ?? \"\")\n\t\t\t: undefined\n\n\tintro(\"hoardodile plugin scaffold\")\n\n\tconst providedName = positional[0]\n\tconst pluginName =\n\t\tprovidedName ??\n\t\t(await text({\n\t\t\tmessage: \"Plugin name (also the directory name, npm-style):\",\n\t\t\tvalidate: (v) =>\n\t\t\t\t/^[a-z0-9][a-z0-9-]*$/.test(v ?? \"\")\n\t\t\t\t\t? undefined\n\t\t\t\t\t: \"lowercase letters, digits and dashes only\",\n\t\t}))\n\tif (isCancel(pluginName)) {\n\t\tcancel(\"scaffold cancelled\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst targetDir = resolve(pluginName)\n\tif (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n\t\tconst proceed = await confirm({\n\t\t\tmessage: `${targetDir} is not empty — scaffold into it anyway?`,\n\t\t\tinitialValue: false,\n\t\t})\n\t\tif (isCancel(proceed) || !proceed) {\n\t\t\tcancel(\"scaffold cancelled\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\tlog.step(`Copying template into ${targetDir}`)\n\tmkdirSync(targetDir, { recursive: true })\n\t// dist/template is a build artifact (already filtered when copied in);\n\t// copy it wholesale so template source dirs inside it survive.\n\tcpSync(TEMPLATE_DIR, targetDir, { recursive: true })\n\n\tlog.step(\"Rewriting manifest and package.json\")\n\tconst manifestPath = join(targetDir, \"manifest.json\")\n\tconst pkgPath = join(targetDir, \"package.json\")\n\twriteJson(\n\t\tmanifestPath,\n\t\trewriteManifest(JSON.parse(readFileSync(manifestPath, \"utf8\")), pluginName),\n\t)\n\twriteJson(\n\t\tpkgPath,\n\t\trewritePackageJson(JSON.parse(readFileSync(pkgPath, \"utf8\")), pluginName, {\n\t\t\ttarballsDir,\n\t\t\tsdkVersion: SELF_VERSION,\n\t\t}),\n\t)\n\n\tconst parsed = pluginManifest.safeParse(\n\t\tJSON.parse(readFileSync(manifestPath, \"utf8\")),\n\t)\n\tif (!parsed.success) {\n\t\tprocess.exitCode = 1\n\t\tlog.error(`generated manifest is invalid: ${parsed.error.message}`)\n\t\treturn\n\t}\n\n\tif (tarballsDir !== undefined) {\n\t\tlog.step(`Rewiring SDK deps to tarballs in ${tarballsDir}`)\n\t\twriteTarballOverrides(targetDir, tarballsDir)\n\t}\n\n\ttry {\n\t\tawait runInstall(targetDir)\n\t} catch (err) {\n\t\tprocess.exitCode = 1\n\t\tlog.error(\n\t\t\t`install failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t)\n\t\treturn\n\t}\n\n\toutro(\"Plugin scaffolded. Next steps:\")\n\tconsole.log(` cd ${targetDir}`)\n\tconsole.log(\n\t\t\" pnpm build # build dist/ (client + server bundle + manifest)\",\n\t)\n\tconsole.log(\n\t\t\" pnpm dev # watch-build + serve the workbench (http://127.0.0.1:5199)\",\n\t)\n\tconsole.log(\" pnpm test # unit tests against the fixture API\")\n\tconsole.log(\" hoardodile plugin run detect testdata --plugin-dir dist\")\n\tconsole.log(\n\t\t\" # Replace the manifest id? No — it was generated fresh. Zip dist/ contents and upload in Settings → Plugins.\",\n\t)\n}\n\nif (\n\tprocess.argv[1] !== undefined &&\n\tresolve(process.argv[1]) === fileURLToPath(import.meta.url)\n) {\n\tmain().catch((err) => {\n\t\tlog.error(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t})\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/sdk-deps.gen.ts","../src/rewrite.ts","../src/index.ts"],"names":["join"],"mappings":"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","file":"index.js","sourcesContent":["// GENERATED by scripts/gen-sdk-deps.mjs — never hand-edit.\n// The published SDK closure a scaffolded plugin can depend on; kept in\n// lockstep with scripts/lib/sdk-closure.mjs (see sdks:pack).\nexport const SDK_DEP_NAMES: readonly string[] = [\n\t\"@hoardodile/cli\",\n\t\"@hoardodile/host\",\n\t\"@hoardodile/host-web\",\n\t\"@hoardodile/i18n\",\n\t\"@hoardodile/sdk-react\",\n\t\"@hoardodile/sdk-server\",\n\t\"@hoardodile/sdk-types\",\n\t\"@hoardodile/sdk-web\",\n\t\"@hoardodile/ui\",\n\t\"@hoardodile/workbench\",\n]\n","/**\n * Scaffold-time rewrites applied to the embedded template copy: fresh\n * manifest identity and concrete dependency specs (the template uses\n * `workspace:*` / `catalog:` which only resolve inside the monorepo).\n */\nimport { join } from \"node:path\"\nimport { SDK_DEP_NAMES } from \"./sdk-deps.gen.ts\"\n\n/** Concrete versions for the catalog: specs the template uses. */\nexport const THIRD_PARTY_VERSIONS: Readonly<Record<string, string>> = {\n\t\"@release-it/conventional-changelog\": \"^12.0.0\",\n\t\"@types/node\": \"^26.2.0\",\n\t\"@types/react\": \"^19.2.18\",\n\t\"@types/react-dom\": \"^19.2.4\",\n\tjsdom: \"^30.0.1\",\n\treact: \"^19.2.8\",\n\t\"react-dom\": \"^19.2.8\",\n\t\"release-it\": \"^21.0.2\",\n\ttypescript: \"^7.0.2\",\n\tvite: \"^8.2.2\",\n\tvitest: \"^4.1.11\",\n}\n\nexport type ManifestShape = {\n\tid: string\n\tname: string\n\tdescription: string\n\tversion: string\n\ti18n?: {\n\t\tname?: Record<string, string>\n\t\tdescription?: Record<string, string>\n\t}\n}\n\nexport function rewriteManifest(\n\tmanifest: ManifestShape,\n\tpluginName: string,\n): ManifestShape {\n\tmanifest.id = crypto.randomUUID()\n\tmanifest.name = pluginName\n\tmanifest.description = `Content plugin: ${pluginName}`\n\tif (manifest.i18n?.name !== undefined) {\n\t\tmanifest.i18n.name.en = pluginName\n\t}\n\tif (manifest.i18n?.description !== undefined) {\n\t\tmanifest.i18n.description.en = `Content plugin: ${pluginName}`\n\t}\n\tmanifest.version = \"0.0.1\"\n\treturn manifest\n}\n\nexport type PackageJson = {\n\tname: string\n\tversion?: string\n\tdependencies?: Record<string, string>\n\tdevDependencies?: Record<string, string>\n}\n\nexport function tarballSpec(\n\ttarballsDir: string,\n\tdep: string,\n\tversion: string,\n): string {\n\tconst fileName = dep.replace(\"@\", \"\").replace(\"/\", \"-\")\n\treturn `file:${join(tarballsDir, `${fileName}-${version}.tgz`).replaceAll(\"\\\\\", \"/\")}`\n}\n\nfunction rewriteDepBlock(\n\tdeps: Record<string, string> | undefined,\n\ttarballsDir: string | undefined,\n\tsdkVersion: string,\n): Record<string, string> {\n\tconst out = { ...deps }\n\tfor (const [dep, spec] of Object.entries(out)) {\n\t\tif (SDK_DEP_NAMES.includes(dep)) {\n\t\t\tout[dep] =\n\t\t\t\ttarballsDir !== undefined\n\t\t\t\t\t? tarballSpec(tarballsDir, dep, sdkVersion)\n\t\t\t\t\t: // `^0.2.0-alpha.3` would never match the 0.2.0 stable\n\t\t\t\t\t\t// release (semver keeps prereleases out of plain ranges),\n\t\t\t\t\t\t// so npm specs drop the prerelease suffix.\n\t\t\t\t\t\t`^${sdkVersion.split(\"-\")[0]}`\n\t\t} else if (spec === \"catalog:\") {\n\t\t\tconst version = THIRD_PARTY_VERSIONS[dep]\n\t\t\tif (version === undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`template dependency \"${dep}\" has no concrete version mapping`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tout[dep] = version\n\t\t}\n\t}\n\treturn out\n}\n\nexport function rewritePackageJson(\n\tpkg: PackageJson,\n\tpluginName: string,\n\topts: { readonly tarballsDir?: string; readonly sdkVersion: string },\n): PackageJson {\n\tpkg.name = pluginName\n\tdelete pkg.version\n\tpkg.version = \"0.0.1\"\n\tif (pkg.dependencies !== undefined) {\n\t\tpkg.dependencies = rewriteDepBlock(\n\t\t\tpkg.dependencies,\n\t\t\topts.tarballsDir,\n\t\t\topts.sdkVersion,\n\t\t)\n\t}\n\tif (pkg.devDependencies !== undefined) {\n\t\tpkg.devDependencies = rewriteDepBlock(\n\t\t\tpkg.devDependencies,\n\t\t\topts.tarballsDir,\n\t\t\topts.sdkVersion,\n\t\t)\n\t}\n\treturn pkg\n}\n\n/**\n * Install-script dependencies that land in a scaffolded plugin through\n * host's optionalDependencies (the same names as the root workspace's\n * allowBuilds). pnpm refuses to run their build scripts without an\n * explicit approval, so the generated workspace approves them up front.\n */\nconst ALLOWED_BUILDS = [\n\t\"@derhuerst/ffprobe-static\",\n\t\"@hoardodile/7z-bin\",\n\t\"ffmpeg-static\",\n]\n\nexport function tarballOverridesYaml(\n\ttarballsDir: string,\n\tsdkVersion: string,\n): string {\n\tconst lines = SDK_DEP_NAMES.map(\n\t\t(dep) => ` '${dep}': '${tarballSpec(tarballsDir, dep, sdkVersion)}'`,\n\t).join(\"\\n\")\n\tconst builds = ALLOWED_BUILDS.map((dep) => ` '${dep}': true`).join(\"\\n\")\n\treturn [\n\t\t\"# Redirect the cross-SDK 0.0.0 specs packed into the tarballs to the\",\n\t\t\"# sibling tarballs in this workspace; approve the install scripts of\",\n\t\t\"# host's optional binaries (ffmpeg/ffprobe/7-Zip) so pnpm runs them.\",\n\t\t\"overrides:\",\n\t\tlines,\n\t\t\"allowBuilds:\",\n\t\tbuilds,\n\t\t\"\",\n\t].join(\"\\n\")\n}\n","#!/usr/bin/env node\n/**\n * `create-hoardodile-plugin` — scaffold a new content plugin from the\n * embedded template copy (`src/template/`, kept in sync with\n * `plugins/template` by scripts/sync-template.mjs).\n *\n * Flow: interactive prompts (name, id auto-generated) → copy template →\n * rewrite manifest + package.json → install dependencies → validate the\n * manifest → print the dev loop entry points.\n *\n * create-hoardodile-plugin my-plugin\n * create-hoardodile-plugin my-plugin --tarballs ../hoardodile/tmp/sdks\n *\n * `--tarballs <dir>` rewires the SDK deps to packed tarballs plus a\n * pnpm-workspace.yaml with the cross-package overrides — used by the\n * release smoke test and for offline installs.\n */\nimport { spawn } from \"node:child_process\"\nimport {\n\tcpSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\twriteFileSync,\n} from \"node:fs\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport {\n\tcancel,\n\tconfirm,\n\tintro,\n\tisCancel,\n\tlog,\n\toutro,\n\ttext,\n} from \"@clack/prompts\"\nimport { pluginManifest } from \"@hoardodile/sdk-types/schema\"\nimport {\n\trewriteManifest,\n\trewritePackageJson,\n\ttarballOverridesYaml,\n} from \"./rewrite.ts\"\n\nconst ROOT = resolve(dirname(fileURLToPath(import.meta.url)), \"..\")\n// The template ships inside dist (dist/template) — the bin always runs\n// from the built artifact, so resolve relative to this module.\nconst TEMPLATE_DIR = resolve(\n\tdirname(fileURLToPath(import.meta.url)),\n\t\"template\",\n)\nconst SELF_VERSION = JSON.parse(\n\treadFileSync(join(ROOT, \"package.json\"), \"utf8\"),\n).version\n\nfunction writeJson(path: string, value: unknown): void {\n\twriteFileSync(path, `${JSON.stringify(value, null, \"\\t\")}\\n`)\n}\n\nfunction writeTarballOverrides(targetDir: string, tarballsDir: string): void {\n\twriteFileSync(\n\t\tjoin(targetDir, \"pnpm-workspace.yaml\"),\n\t\ttarballOverridesYaml(tarballsDir, SELF_VERSION),\n\t)\n}\n\nasync function runInstall(targetDir: string): Promise<void> {\n\tlog.step(\"Installing dependencies (pnpm install)\")\n\treturn new Promise<void>((resolveDone, reject) => {\n\t\tconst child = spawn(\"pnpm\", [\"install\"], {\n\t\t\tcwd: targetDir,\n\t\t\tstdio: \"inherit\",\n\t\t\tshell: process.platform === \"win32\",\n\t\t})\n\t\tchild.on(\"error\", reject)\n\t\tchild.on(\"exit\", (code) =>\n\t\t\tcode === 0\n\t\t\t\t? resolveDone()\n\t\t\t\t: reject(new Error(`pnpm install exited ${code}`)),\n\t\t)\n\t})\n}\n\nexport async function main() {\n\tconst positional = process.argv.slice(2).filter((a) => !a.startsWith(\"--\"))\n\tconst tarballsFlag = process.argv.indexOf(\"--tarballs\")\n\tconst tarballsDir =\n\t\ttarballsFlag !== -1\n\t\t\t? resolve(process.argv[tarballsFlag + 1] ?? \"\")\n\t\t\t: undefined\n\n\tintro(\"hoardodile plugin scaffold\")\n\n\tconst providedName = positional[0]\n\tconst pluginName =\n\t\tprovidedName ??\n\t\t(await text({\n\t\t\tmessage: \"Plugin name (also the directory name, npm-style):\",\n\t\t\tvalidate: (v) =>\n\t\t\t\t/^[a-z0-9][a-z0-9-]*$/.test(v ?? \"\")\n\t\t\t\t\t? undefined\n\t\t\t\t\t: \"lowercase letters, digits and dashes only\",\n\t\t}))\n\tif (isCancel(pluginName)) {\n\t\tcancel(\"scaffold cancelled\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst targetDir = resolve(pluginName)\n\tif (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n\t\tconst proceed = await confirm({\n\t\t\tmessage: `${targetDir} is not empty — scaffold into it anyway?`,\n\t\t\tinitialValue: false,\n\t\t})\n\t\tif (isCancel(proceed) || !proceed) {\n\t\t\tcancel(\"scaffold cancelled\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\tlog.step(`Copying template into ${targetDir}`)\n\tmkdirSync(targetDir, { recursive: true })\n\t// dist/template is a build artifact (already filtered when copied in);\n\t// copy it wholesale so template source dirs inside it survive.\n\tcpSync(TEMPLATE_DIR, targetDir, { recursive: true })\n\n\tlog.step(\"Rewriting manifest and package.json\")\n\tconst manifestPath = join(targetDir, \"manifest.json\")\n\tconst pkgPath = join(targetDir, \"package.json\")\n\twriteJson(\n\t\tmanifestPath,\n\t\trewriteManifest(JSON.parse(readFileSync(manifestPath, \"utf8\")), pluginName),\n\t)\n\twriteJson(\n\t\tpkgPath,\n\t\trewritePackageJson(JSON.parse(readFileSync(pkgPath, \"utf8\")), pluginName, {\n\t\t\ttarballsDir,\n\t\t\tsdkVersion: SELF_VERSION,\n\t\t}),\n\t)\n\n\tconst parsed = pluginManifest.safeParse(\n\t\tJSON.parse(readFileSync(manifestPath, \"utf8\")),\n\t)\n\tif (!parsed.success) {\n\t\tprocess.exitCode = 1\n\t\tlog.error(`generated manifest is invalid: ${parsed.error.message}`)\n\t\treturn\n\t}\n\n\tif (tarballsDir !== undefined) {\n\t\tlog.step(`Rewiring SDK deps to tarballs in ${tarballsDir}`)\n\t\twriteTarballOverrides(targetDir, tarballsDir)\n\t}\n\n\ttry {\n\t\tawait runInstall(targetDir)\n\t} catch (err) {\n\t\tprocess.exitCode = 1\n\t\tlog.error(\n\t\t\t`install failed: ${err instanceof Error ? err.message : String(err)}`,\n\t\t)\n\t\treturn\n\t}\n\n\toutro(\"Plugin scaffolded. Next steps:\")\n\tconsole.log(` cd ${targetDir}`)\n\tconsole.log(\n\t\t\" pnpm build # build dist/ (client + server bundle + manifest)\",\n\t)\n\tconsole.log(\n\t\t\" pnpm dev # watch-build + serve the workbench (http://127.0.0.1:5199)\",\n\t)\n\tconsole.log(\" pnpm test # unit tests against the fixture API\")\n\tconsole.log(\" hoardodile plugin run detect testdata --plugin-dir dist\")\n\tconsole.log(\n\t\t\" # Replace the manifest id? No — it was generated fresh. Zip dist/ contents and upload in Settings → Plugins.\",\n\t)\n}\n\nif (\n\tprocess.argv[1] !== undefined &&\n\tresolve(process.argv[1]) === fileURLToPath(import.meta.url)\n) {\n\tmain().catch((err) => {\n\t\tlog.error(err instanceof Error ? err.message : String(err))\n\t\tprocess.exit(1)\n\t})\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: File a bug report against this hoardodile plugin
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to fill out this bug report.
|
|
10
|
+
Minimal reproduction steps first — the title can stay generic until the steps are clear.
|
|
11
|
+
- type: input
|
|
12
|
+
id: hoardodile-version
|
|
13
|
+
attributes:
|
|
14
|
+
label: hoardodile version
|
|
15
|
+
description: The version shown in Settings → About.
|
|
16
|
+
placeholder: 0.x.x
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: input
|
|
20
|
+
id: plugin-version
|
|
21
|
+
attributes:
|
|
22
|
+
label: Plugin version
|
|
23
|
+
description: The version in Settings → Plugins (vX.Y.Z), or the marketplace's latest release if installing fresh.
|
|
24
|
+
placeholder: 0.0.1
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: steps
|
|
29
|
+
attributes:
|
|
30
|
+
label: Steps to reproduce
|
|
31
|
+
description: Minimal, ordered steps — what did you do to get here?
|
|
32
|
+
placeholder: |
|
|
33
|
+
1. …
|
|
34
|
+
2. …
|
|
35
|
+
3. …
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
- type: textarea
|
|
39
|
+
id: expected
|
|
40
|
+
attributes:
|
|
41
|
+
label: Expected behavior
|
|
42
|
+
description: What did you expect to happen?
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
- type: textarea
|
|
46
|
+
id: actual
|
|
47
|
+
attributes:
|
|
48
|
+
label: Actual behavior
|
|
49
|
+
description: What actually happened instead?
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
- type: textarea
|
|
53
|
+
id: logs
|
|
54
|
+
attributes:
|
|
55
|
+
label: Logs / screenshots
|
|
56
|
+
description: Paste the relevant console or server logs, or attach screenshots.
|
|
57
|
+
render: shell
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an idea for this plugin
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for suggesting! Describe the problem you are solving, not just the feature.
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: problem
|
|
12
|
+
attributes:
|
|
13
|
+
label: Problem
|
|
14
|
+
description: What problem does this feature solve? What is the current pain?
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: textarea
|
|
18
|
+
id: solution
|
|
19
|
+
attributes:
|
|
20
|
+
label: Proposed solution
|
|
21
|
+
description: What would you expect to happen?
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: textarea
|
|
25
|
+
id: alternatives
|
|
26
|
+
attributes:
|
|
27
|
+
label: Alternatives
|
|
28
|
+
description: Workarounds or other plugins that get partway there.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- "**.md"
|
|
8
|
+
pull_request:
|
|
9
|
+
paths-ignore:
|
|
10
|
+
- "**.md"
|
|
11
|
+
|
|
12
|
+
# A superseded push cancels the stale run instead of queueing behind it.
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
# One leg is enough: lint, build and test against the SDK source.
|
|
22
|
+
checks:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 20
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
|
|
28
|
+
- uses: pnpm/action-setup@v6
|
|
29
|
+
with:
|
|
30
|
+
version: 11
|
|
31
|
+
|
|
32
|
+
- uses: actions/setup-node@v7
|
|
33
|
+
with:
|
|
34
|
+
node-version-file: .nvmrc
|
|
35
|
+
cache: pnpm
|
|
36
|
+
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: pnpm install
|
|
39
|
+
|
|
40
|
+
- name: Lint
|
|
41
|
+
run: pnpm lint
|
|
42
|
+
|
|
43
|
+
- name: Build
|
|
44
|
+
run: pnpm build
|
|
45
|
+
|
|
46
|
+
- name: Test
|
|
47
|
+
run: pnpm test
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
name: release
|
|
2
2
|
|
|
3
|
+
# Normally the tag is produced by `pnpm release <version>` (release-it bumps
|
|
4
|
+
# package.json + manifest.json, writes CHANGELOG.md, commits, tags and pushes).
|
|
5
|
+
# This workflow is the publisher: on tag push it builds, packages
|
|
6
|
+
# (`release/<id>-<version>.zip` + `.sha256`) and creates a *published* GitHub
|
|
7
|
+
# release the marketplace picks up — so no local GITHUB_TOKEN or `gh` CLI is
|
|
8
|
+
# needed. Pushing the tag manually (`git tag v<version> && git push origin
|
|
9
|
+
# v<version>`) still works as a fallback.
|
|
10
|
+
|
|
3
11
|
on:
|
|
4
12
|
push:
|
|
5
13
|
tags: ["v*"]
|
|
@@ -11,13 +19,13 @@ jobs:
|
|
|
11
19
|
release:
|
|
12
20
|
runs-on: ubuntu-latest
|
|
13
21
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v7
|
|
15
23
|
|
|
16
|
-
- uses: pnpm/action-setup@
|
|
24
|
+
- uses: pnpm/action-setup@v6
|
|
17
25
|
with:
|
|
18
26
|
version: 11
|
|
19
27
|
|
|
20
|
-
- uses: actions/setup-node@
|
|
28
|
+
- uses: actions/setup-node@v7
|
|
21
29
|
with:
|
|
22
30
|
node-version: 24
|
|
23
31
|
cache: pnpm
|
|
@@ -39,5 +47,8 @@ jobs:
|
|
|
39
47
|
env:
|
|
40
48
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
41
49
|
run: |
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
files=$(ls release/*)
|
|
51
|
+
if ls intro.*.md >/dev/null 2>&1; then
|
|
52
|
+
files="$files intro.*.md"
|
|
53
|
+
fi
|
|
54
|
+
gh release create "$GITHUB_REF_NAME" $files --generate-notes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Contributing to this plugin
|
|
2
|
+
|
|
3
|
+
Thanks for contributing! This is a hoardodile content plugin — sections below
|
|
4
|
+
cover the dev loop, quality gates, and how releases and the marketplace work.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
- Node.js ≥ 24, pnpm 11.
|
|
9
|
+
- Clone the repository, then:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm install
|
|
13
|
+
pnpm build # dist/ (client + server bundle + manifest)
|
|
14
|
+
pnpm dev # watch-build + workbench at http://127.0.0.1:5199
|
|
15
|
+
pnpm test # Vitest unit tests against the fixture API
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`pnpm exec hoardodile plugin run detect testdata --plugin-dir dist` runs the
|
|
19
|
+
detect hook through the same sandboxed worker the server uses.
|
|
20
|
+
|
|
21
|
+
## Code style
|
|
22
|
+
|
|
23
|
+
- TypeScript strict (`pnpm lint` = `tsc --noEmit`); no `any` without a comment.
|
|
24
|
+
- Prefer type guards and `satisfies` over `as`.
|
|
25
|
+
- Keep the plugin's own logic in `src/`; `manifest.json` at the repo root is
|
|
26
|
+
the single source of truth for the plugin's identity, permissions and UI
|
|
27
|
+
preferences.
|
|
28
|
+
- Add tests next to the code they cover; keep the fixture API usage minimal.
|
|
29
|
+
|
|
30
|
+
## Releases
|
|
31
|
+
|
|
32
|
+
Bump `version` in `manifest.json` on user-visible changes, then release with
|
|
33
|
+
one command:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm release <version>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
release-it bumps `package.json` **and** `manifest.json` (kept in lockstep by
|
|
40
|
+
`scripts/sync-version.mjs`), writes `CHANGELOG.md` from Conventional Commits,
|
|
41
|
+
commits `chore(release): v<version>`, tags and pushes. Run it on `main` with a
|
|
42
|
+
clean working tree. `.github/workflows/release.yml` then builds, runs
|
|
43
|
+
`hoardodile plugin package` (`release/<id>-<version>.zip` + `.sha256`) and
|
|
44
|
+
publishes the GitHub release. The tag must match `v<manifest.version>` — the
|
|
45
|
+
workflow fails otherwise. Your version is independent of the hoardodile app
|
|
46
|
+
version.
|
|
47
|
+
|
|
48
|
+
Pushing the tag by hand still works as a fallback:
|
|
49
|
+
`git tag v<version> && git push origin v<version>`.
|
|
50
|
+
|
|
51
|
+
## Marketplace publishing
|
|
52
|
+
|
|
53
|
+
1. Add the repository address to your registry repo's `registry.json`.
|
|
54
|
+
2. Ship `intro.<locale>.md` files (see the README) so each release carries a
|
|
55
|
+
version-pinned introduction the app can show.
|
|
56
|
+
|
|
57
|
+
## Issues and pull requests
|
|
58
|
+
|
|
59
|
+
- Bug reports and feature requests go through the issue templates
|
|
60
|
+
(**New issue** → bug report / feature request).
|
|
61
|
+
- Pull requests should stay focused: one cohesive change, a matching test,
|
|
62
|
+
and a description of the user-visible behavior.
|
|
63
|
+
- Security issues are **not** filed as public issues — see `SECURITY.md`.
|
package/dist/template/README.md
CHANGED
|
@@ -45,28 +45,69 @@ pnpm run detect:smoke # sandboxed detect against testdata (needs a build first)
|
|
|
45
45
|
`hoardodile plugin run` runs hooks through the same worker sandbox the
|
|
46
46
|
server uses — the exact production execution path.
|
|
47
47
|
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
- hoardodile **≥ 0.1.1** — the built-in plugin marketplace
|
|
51
|
+
(**Settings → Marketplace**) and the batched asset-download API
|
|
52
|
+
(`download([…])`) when the manifest declares `"download": true`.
|
|
53
|
+
The marketplace's Intro and Release notes tabs and release intro
|
|
54
|
+
assets are read by newer builds; older builds still list and install
|
|
55
|
+
the plugin normally.
|
|
56
|
+
- `"minAppVersion"` in `manifest.json` declares the lowest hoardodile
|
|
57
|
+
release this plugin runs on. Hosts below it refuse to install or update
|
|
58
|
+
the plugin (the marketplace gates the install/update entries and zip
|
|
59
|
+
uploads are blocked with an explanation), so bump it only when the
|
|
60
|
+
plugin really needs a newer app. Omit it for plugins that support every
|
|
61
|
+
release.
|
|
62
|
+
- The plugin's version is independent of the hoardodile release
|
|
63
|
+
version; bump it on user-visible changes.
|
|
64
|
+
- Dev loop: Node ≥ 24, pnpm 11.
|
|
65
|
+
|
|
48
66
|
## Deploying
|
|
49
67
|
|
|
50
|
-
Publish to the marketplace with
|
|
68
|
+
Publish to the marketplace with one command:
|
|
51
69
|
|
|
52
70
|
```bash
|
|
53
71
|
# 1. Add the repository address to your registry repo's registry.json:
|
|
54
72
|
# { "version": 1, "plugins": ["https://github.com/<owner>/<repo>"] }
|
|
55
73
|
|
|
56
|
-
# 2.
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
|
|
74
|
+
# 2. One-click release — release-it bumps the version in package.json AND
|
|
75
|
+
# manifest.json, writes CHANGELOG.md from Conventional Commits, commits,
|
|
76
|
+
# tags `v<version>` and pushes. The tag-triggered `.github/workflows/
|
|
77
|
+
# release.yml` then builds, packages (`release/<id>-<version>.zip` +
|
|
78
|
+
# `.sha256`) and publishes the GitHub release. No local `gh` CLI or token.
|
|
79
|
+
pnpm release <version>
|
|
60
80
|
```
|
|
61
81
|
|
|
62
|
-
The tag must match the manifest version
|
|
63
|
-
workflow fails otherwise. Then paste the registry
|
|
64
|
-
**Settings → Marketplace**. The app reads the registry,
|
|
65
|
-
manifest and its latest release — names, versions, permissions and
|
|
66
|
-
release notes come straight from GitHub, so the list never needs editing
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
On `main`, with a clean working tree. The tag must match the manifest version
|
|
83
|
+
(`v<manifest.version>`) — the workflow fails otherwise. Then paste the registry
|
|
84
|
+
repo address once in **Settings → Marketplace**. The app reads the registry,
|
|
85
|
+
each plugin's manifest and its latest release — names, versions, permissions and
|
|
86
|
+
release notes come straight from GitHub, so the list never needs editing again.
|
|
87
|
+
The zip asset is `<id>-<version>.zip` (produced by `hoardodile plugin package`);
|
|
88
|
+
before the first release the plugin shows up with a "no release" state.
|
|
89
|
+
|
|
90
|
+
Prefer pushing a tag manually (no release-it)? It still works — the workflow
|
|
91
|
+
does the same build/package/publish:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git tag v<version> && git push origin v<version>
|
|
95
|
+
```
|
|
70
96
|
|
|
71
97
|
Local installs (zip upload in **Settings → Plugins**) still work for
|
|
72
98
|
private packages.
|
|
99
|
+
|
|
100
|
+
## Publishing an introduction
|
|
101
|
+
|
|
102
|
+
The marketplace detail view shows a per-release **Intro** tab. Ship one
|
|
103
|
+
markdown file per supported language at the repository root, named
|
|
104
|
+
`intro.<locale>.md` (e.g. `intro.en.md`, `intro.zh.md`) — `release.yml`
|
|
105
|
+
uploads them alongside the zip, so **each release carries its own
|
|
106
|
+
introduction** and every version shows independent notes. Use the app's
|
|
107
|
+
supported language codes as file names (`en`, `zh`, `ja`, `de`, `es`) —
|
|
108
|
+
a region-coded name like `intro.zh-CN.md` only matches a UI language
|
|
109
|
+
resolved to that exact code, so `intro.zh.md` is what Chinese users see.
|
|
110
|
+
|
|
111
|
+
The app resolves the intro for the user's UI language (exact locale → base
|
|
112
|
+
language → `en` → the only shipped language); the release body always shows
|
|
113
|
+
in the **Release notes** tab.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
Hoardodile plugins run as **server-side code** inside the app's restricted
|
|
4
|
+
plugin sandbox — treat a plugin like any third-party dependency: only publish
|
|
5
|
+
or install from sources you trust. The manifest declares the capabilities the
|
|
6
|
+
sandbox grants; installs require explicit user consent.
|
|
7
|
+
|
|
8
|
+
## Reporting a vulnerability
|
|
9
|
+
|
|
10
|
+
Please report security issues **privately** — do **not** open a public issue,
|
|
11
|
+
pull request or discussion that reveals the details.
|
|
12
|
+
|
|
13
|
+
1. Open the repository's **Security** tab on GitHub.
|
|
14
|
+
2. Click **Report a vulnerability** to create a private advisory.
|
|
15
|
+
3. Include the affected hoardodile and plugin versions, a description of the
|
|
16
|
+
vulnerability, reproduction steps and any proof of concept.
|
|
17
|
+
|
|
18
|
+
Private advisories stay invisible to the public until you publish the fix; we
|
|
19
|
+
coordinate the disclosure timeline with you before anything goes public.
|
|
20
|
+
|
|
21
|
+
## What counts as a security issue
|
|
22
|
+
|
|
23
|
+
Anything that lets a crafted resource or plugin install break out of the
|
|
24
|
+
plugin sandbox, escape the plugin's vault, or read/delete data outside the
|
|
25
|
+
plugin's own scope. For usage questions and non-security bugs use the issue
|
|
26
|
+
templates instead.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# My plugin
|
|
2
|
+
|
|
3
|
+
_Replace this introduction with a real overview: what content the plugin
|
|
4
|
+
detects, how it renders it, and where users see it._
|
|
5
|
+
|
|
6
|
+
This introduction ships with **every GitHub release** — edit it per release so
|
|
7
|
+
each version presents its own notes in the marketplace.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Detects resources containing … and renders them inline.
|
|
12
|
+
- Declares the following permissions: _see `manifest.json`_.
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- hoardodile ≥ 0.1.1 (see the repository README for details).
|
|
17
|
+
- Trust the repository before installing — plugin code runs server-side in a
|
|
18
|
+
restricted sandbox.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 我的插件
|
|
2
|
+
|
|
3
|
+
_把这段介绍替换为真实内容:插件识别什么内容、如何渲染、用户在何处看到效果。_
|
|
4
|
+
|
|
5
|
+
本介绍随**每个 GitHub Release** 一同发布——请随版本更新,让每个版本在插件市场中呈现各自的介绍。
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
- 识别包含……的资源并以内嵌方式渲染。
|
|
10
|
+
- 声明的权限:_参见 `manifest.json`_。
|
|
11
|
+
|
|
12
|
+
## 要求
|
|
13
|
+
|
|
14
|
+
- hoardodile ≥ 0.1.1(详见仓库 README)。
|
|
15
|
+
- 安装前请确认信任该仓库——插件代码在受限沙箱中作为服务端代码运行。
|
|
@@ -10,7 +10,32 @@
|
|
|
10
10
|
"watch": "hoardodile plugin build --watch",
|
|
11
11
|
"detect:smoke": "hoardodile plugin run detect testdata --plugin-dir dist",
|
|
12
12
|
"lint": "tsc --noEmit",
|
|
13
|
-
"test": "vitest run"
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"release": "node scripts/release.mjs"
|
|
15
|
+
},
|
|
16
|
+
"release-it": {
|
|
17
|
+
"git": {
|
|
18
|
+
"commitMessage": "chore(release): v${version}",
|
|
19
|
+
"tagName": "v${version}",
|
|
20
|
+
"requireBranch": "main"
|
|
21
|
+
},
|
|
22
|
+
"github": {
|
|
23
|
+
"release": false
|
|
24
|
+
},
|
|
25
|
+
"npm": {
|
|
26
|
+
"publish": false
|
|
27
|
+
},
|
|
28
|
+
"plugins": {
|
|
29
|
+
"@release-it/conventional-changelog": {
|
|
30
|
+
"preset": {
|
|
31
|
+
"name": "conventionalcommits"
|
|
32
|
+
},
|
|
33
|
+
"infile": "CHANGELOG.md"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"hooks": {
|
|
37
|
+
"after:bump": "node scripts/sync-version.mjs"
|
|
38
|
+
}
|
|
14
39
|
},
|
|
15
40
|
"dependencies": {
|
|
16
41
|
"@hoardodile/sdk-react": "workspace:*",
|
|
@@ -29,6 +54,8 @@
|
|
|
29
54
|
"jsdom": "catalog:",
|
|
30
55
|
"typescript": "catalog:",
|
|
31
56
|
"vite": "catalog:",
|
|
32
|
-
"vitest": "catalog:"
|
|
57
|
+
"vitest": "catalog:",
|
|
58
|
+
"release-it": "catalog:",
|
|
59
|
+
"@release-it/conventional-changelog": "catalog:"
|
|
33
60
|
}
|
|
34
61
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `pnpm release <version>` — one-click release for this plugin.
|
|
4
|
+
*
|
|
5
|
+
* Runs release-it, which bumps `package.json`, syncs the new version into
|
|
6
|
+
* `manifest.json` (after:bump → scripts/sync-version.mjs), writes a
|
|
7
|
+
* Conventional-Commits `CHANGELOG.md`, commits `chore(release): v<version>`,
|
|
8
|
+
* tags `v<version>` and pushes. Publishing the GitHub release itself is CI's
|
|
9
|
+
* job: the pushed tag triggers `.github/workflows/release.yml`, which builds,
|
|
10
|
+
* packages (`release/<id>-<version>.zip` + `.sha256`) and creates the
|
|
11
|
+
* published release the marketplace picks up — so no local GITHUB_TOKEN or
|
|
12
|
+
* `gh` CLI is needed. Manual `git tag v<version> && git push origin v<version>`
|
|
13
|
+
* still works as a fallback.
|
|
14
|
+
*
|
|
15
|
+
* release-it is launched with process.execPath — on Windows the `pnpm`/`.cmd`
|
|
16
|
+
* shims are not reliably launchable, so invoking the JS entry is uniform.
|
|
17
|
+
*
|
|
18
|
+
* node scripts/release.mjs [release-it args...]
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { spawnSync } from "node:child_process"
|
|
22
|
+
import { existsSync } from "node:fs"
|
|
23
|
+
import { dirname, resolve } from "node:path"
|
|
24
|
+
import { fileURLToPath } from "node:url"
|
|
25
|
+
|
|
26
|
+
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..")
|
|
27
|
+
|
|
28
|
+
const releaseItBin = resolve(
|
|
29
|
+
ROOT,
|
|
30
|
+
"node_modules",
|
|
31
|
+
"release-it",
|
|
32
|
+
"bin",
|
|
33
|
+
"release-it.js",
|
|
34
|
+
)
|
|
35
|
+
if (!existsSync(releaseItBin)) {
|
|
36
|
+
console.error(
|
|
37
|
+
`release-it not found at ${releaseItBin} — run pnpm install first.`,
|
|
38
|
+
)
|
|
39
|
+
process.exit(1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const result = spawnSync(
|
|
43
|
+
process.execPath,
|
|
44
|
+
[releaseItBin, ...process.argv.slice(2)],
|
|
45
|
+
{
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
env: process.env,
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
if (result.error) {
|
|
51
|
+
console.error(`failed to launch release-it: ${result.error}`)
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
process.exit(result.status ?? 1)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sync the plugin version from `package.json` into `manifest.json`. Invoked by
|
|
4
|
+
* release-it's after:bump hook (the version was just bumped in package.json),
|
|
5
|
+
* so the tag `v<version>` and the packaged zip name match the manifest the
|
|
6
|
+
* marketplace reads. Idempotent; also safe to run standalone.
|
|
7
|
+
*
|
|
8
|
+
* `manifest.json` is biome-canonical, so patch only the version value —
|
|
9
|
+
* JSON.parse + JSON.stringify would reflow arrays and need a post-format pass.
|
|
10
|
+
*
|
|
11
|
+
* node scripts/sync-version.mjs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync, writeFileSync } from "node:fs"
|
|
15
|
+
|
|
16
|
+
const { version } = JSON.parse(readFileSync("package.json", "utf8"))
|
|
17
|
+
const path = "manifest.json"
|
|
18
|
+
|
|
19
|
+
let source
|
|
20
|
+
try {
|
|
21
|
+
source = readFileSync(path, "utf8")
|
|
22
|
+
} catch {
|
|
23
|
+
throw new Error(`could not read ${path} — is this the plugin root?`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const next = source.replace(/("version"\s*:\s*)"[^"]*"/, `$1"${version}"`)
|
|
27
|
+
if (next === source) {
|
|
28
|
+
console.log(`unchanged ${path} (${version})`)
|
|
29
|
+
process.exit(0)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Guard: the patch must stay valid JSON carrying the requested version.
|
|
33
|
+
const patched = JSON.parse(next)
|
|
34
|
+
if (patched.version !== version) {
|
|
35
|
+
throw new Error(`version field mismatch after syncing ${path}`)
|
|
36
|
+
}
|
|
37
|
+
writeFileSync(path, next)
|
|
38
|
+
console.log(`synced ${path} -> ${version}`)
|
|
@@ -21,6 +21,21 @@ export default definePlugin<TemplateSchema>({
|
|
|
21
21
|
// so sourceMeta never rescans.
|
|
22
22
|
{ ok: true, hdtplCount: hdtpl.length }
|
|
23
23
|
},
|
|
24
|
+
// Optional: the host runs this once after a successful install/update
|
|
25
|
+
// commit (marketplace install/update, zip uploads), with an
|
|
26
|
+
// install-scoped API — no resource is attached (the file surface is
|
|
27
|
+
// empty) but `download` still works behind the shared consent
|
|
28
|
+
// dialog. Best-effort by contract: a throw (or a denied consent)
|
|
29
|
+
// never fails the install, so re-check at runtime.
|
|
30
|
+
//
|
|
31
|
+
// onInstall: async (api) => {
|
|
32
|
+
// await api.download({
|
|
33
|
+
// url: "https://example.com/runtime.min.js",
|
|
34
|
+
// dest: "runtime/runtime.min.js",
|
|
35
|
+
// sha256: "…64 lowercase hex…",
|
|
36
|
+
// reason: "…shown in the consent dialog…",
|
|
37
|
+
// })
|
|
38
|
+
// },
|
|
24
39
|
sourceMeta: buildSourceMeta,
|
|
25
40
|
})
|
|
26
41
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoardodile/create-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Scaffold a hoardodile content plugin.",
|
|
6
6
|
"keywords": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@clack/prompts": "^1.7.0",
|
|
39
39
|
"zod": "^4.4.3",
|
|
40
|
-
"@hoardodile/sdk-types": "0.1.
|
|
40
|
+
"@hoardodile/sdk-types": "0.1.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^26.2.0",
|