@sfmc-bds/devkit 2.0.0 → 2.0.1

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.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/module-root.ts", "../src/sfmc-cli.ts", "../src/sfmc-root.ts", "../src/module-toggle.ts", "../src/paths.ts", "../src/rebuild.ts", "../src/registry-command.ts", "../src/registry-submit.ts", "../src/watch.ts"],
4
- "sourcesContent": ["/**\n * \u6709\u6548\u6A21\u5757\u6839\u5224\u5B9A\uFF08\u6269\u5C55\u4E0E CLI \u5171\u7528\u6743\u5A01\uFF09\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ModuleRootInfo = {\n root: string;\n id: string;\n name?: string;\n schemaVersion: number;\n};\n\n/** \u76EE\u5F55\u662F\u5426\u4E3A\u6709\u6548 SFMC \u6A21\u5757\u6839\uFF1Apackage.json + sapi/manifest.json schemaVersion===2 + \u975E\u7A7A id */\nexport function isValidModuleRoot(dir: string): boolean {\n return readModuleRootInfo(dir) !== null;\n}\n\nexport function readModuleRootInfo(dir: string): ModuleRootInfo | null {\n const pkg = path.join(dir, \"package.json\");\n const manifestPath = path.join(dir, \"sapi\", \"manifest.json\");\n if (!fs.existsSync(pkg) || !fs.existsSync(manifestPath)) return null;\n try {\n const m = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n schemaVersion?: number;\n id?: string;\n name?: string;\n };\n if (m.schemaVersion !== 2) return null;\n if (typeof m.id !== \"string\" || !m.id.trim()) return null;\n return {\n root: path.resolve(dir),\n id: m.id.trim(),\n name: typeof m.name === \"string\" ? m.name : undefined,\n schemaVersion: 2,\n };\n } catch {\n return null;\n }\n}\n\n/** \u81EA filePath \u5411\u4E0A\u627E\u6700\u8FD1\u6709\u6548\u6A21\u5757\u6839\uFF1B\u627E\u4E0D\u5230\u8FD4\u56DE null */\nexport function findModuleRootFromFile(filePath: string): string | null {\n let cur = path.dirname(path.resolve(filePath));\n const root = path.parse(cur).root;\n while (true) {\n if (isValidModuleRoot(cur)) return cur;\n if (cur === root) return null;\n const parent = path.dirname(cur);\n if (parent === cur) return null;\n cur = parent;\n }\n}\n", "/**\n * \u89E3\u6790\u5E76 spawn sfmc CLI\u3002\n * CLI \u4E0E SFMC \u5DE5\u4F5C\u76EE\u5F55\u65E0\u5173\uFF1A\u4ECE\u672C\u5305/\u6269\u5C55\u5B89\u88C5\u6811\u3001PATH \u6216\u663E\u5F0F\u914D\u7F6E\u89E3\u6790\uFF1B\n * \u5DE5\u4F5C\u76EE\u5F55\u53EA\u4F5C\u4E3A spawn \u7684 cwd \u4E0E SFMC_ROOT\u3002\n */\n\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { isValidSfmcRoot } from \"./sfmc-root.js\";\n\n/** chalk.hex(\"#e06c75\") \u7684\u771F\u5F69\u5E8F\u5217\uFF1BCLI \u5931\u8D25\u6587\u6848\u7ECF c.red() \u5305\u88C5\u3002 */\nconst CLI_ANSI_RED = \"\\u001b[38;2;224;108;117m\";\n\nexport interface ResolveSfmcCliOptions {\n /** \u663E\u5F0F CLI \u5165\u53E3\uFF08.js/.mjs\uFF09\uFF1B\u4E5F\u53EF\u7528\u73AF\u5883\u53D8\u91CF SFMC_CLI\u3002 */\n cliPath?: string;\n}\n\nfunction tryRequireCli(from: string): string | null {\n try {\n const resolved = createRequire(from).resolve(\"@sfmc-bds/cli/cli\");\n return fs.existsSync(resolved) ? resolved : null;\n } catch {\n return null;\n }\n}\n\n/** \u81EA PATH \u4E0A\u7684 sfmc \u53EF\u6267\u884C\u6587\u4EF6\u65C1\u89E3\u6790 @sfmc-bds/cli\uFF08npm global / \u672C\u5730 .bin\uFF09\u3002 */\nfunction resolveCliFromPathEnv(): string | null {\n const pathEnv = process.env.PATH ?? \"\";\n const names =\n process.platform === \"win32\" ? [\"sfmc.cmd\", \"sfmc.exe\", \"sfmc.ps1\", \"sfmc\"] : [\"sfmc\"];\n for (const dir of pathEnv.split(path.delimiter)) {\n if (!dir) continue;\n let hit = false;\n for (const name of names) {\n if (fs.existsSync(path.join(dir, name))) {\n hit = true;\n break;\n }\n }\n if (!hit) continue;\n const nearCli = path.join(dir, \"..\", \"@sfmc-bds\", \"cli\", \"dist\", \"main.js\");\n if (fs.existsSync(nearCli)) return nearCli;\n const nearMeta = path.join(dir, \"..\", \"@sfmc-bds\", \"sfmc\", \"bin\", \"sfmc.mjs\");\n if (fs.existsSync(nearMeta)) return nearMeta;\n const fromBin = tryRequireCli(path.join(dir, \"..\", \"package.json\"));\n if (fromBin) return fromBin;\n }\n return null;\n}\n\n/**\n * \u89E3\u6790 sfmc CLI \u811A\u672C\u8DEF\u5F84\u3002\n * \u987A\u5E8F\uFF1A\u663E\u5F0F cliPath / SFMC_CLI \u2192 \u672C\u5305\u5B89\u88C5\u6811\uFF08@sfmc-bds/cli\uFF09\u2192 cwd \u7684 node_modules \u2192 PATH\u3002\n */\nexport function resolveSfmcCli(opts: ResolveSfmcCliOptions = {}): string {\n const explicit = (opts.cliPath || process.env.SFMC_CLI || \"\").trim();\n if (explicit) {\n const p = path.resolve(explicit);\n if (!fs.existsSync(p)) {\n throw new Error(`\u6307\u5B9A\u7684 sfmc CLI \u4E0D\u5B58\u5728\uFF1A${p}\uFF08\u68C0\u67E5 SFMC_CLI / sfmc.cliPath\uFF09`);\n }\n return p;\n }\n\n const here = fileURLToPath(import.meta.url);\n const fromInstall = tryRequireCli(here);\n if (fromInstall) return fromInstall;\n\n const fromCwd = tryRequireCli(path.join(process.cwd(), \"package.json\"));\n if (fromCwd) return fromCwd;\n\n const fromPath = resolveCliFromPathEnv();\n if (fromPath) return fromPath;\n\n throw new Error(\n \"\u65E0\u6CD5\u89E3\u6790 sfmc CLI\u3002\u8BF7\u5B89\u88C5 @sfmc-bds/cli\uFF08\u6216\u786E\u4FDD PATH \u4E0A\u6709 sfmc\uFF09\uFF0C\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF SFMC_CLI / \u6269\u5C55\u914D\u7F6E sfmc.cliPath\u3002\"\n );\n}\n\nfunction looksLikeCliFailure(output: string): boolean {\n if (output.includes(CLI_ANSI_RED)) return true;\n if (/\\[pack-manager\\].*required/.test(output)) return true;\n if (/^Error:/m.test(output)) return true;\n return false;\n}\n\nexport interface RunSfmcCliResult {\n ok: boolean;\n output: string;\n}\n\nexport interface RunSfmcCliOptions {\n cliPath?: string;\n}\n\n/** \u5728 SFMC \u5DE5\u4F5C\u76EE\u5F55\u4E0B\u6267\u884C `node <sfmc-cli> ...args`\uFF08env.SFMC_ROOT = \u5DE5\u4F5C\u76EE\u5F55\uFF09\u3002 */\nexport async function runSfmcCli(\n sfmcRoot: string,\n args: string[],\n opts: RunSfmcCliOptions = {}\n): Promise<RunSfmcCliResult> {\n const root = path.resolve(sfmcRoot);\n if (!isValidSfmcRoot(root)) {\n return {\n ok: false,\n output: `\u65E0\u6548\u7684 SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF1A${root}\uFF08\u9700\u8981\u542B configs/ \u4E0E modules/\uFF0C\u4E0D\u5FC5\u542B\u6E90\u7801\u4ED3\u5E93\uFF09`,\n };\n }\n\n let script: string;\n try {\n script = resolveSfmcCli({ cliPath: opts.cliPath });\n } catch (e) {\n return { ok: false, output: e instanceof Error ? e.message : String(e) };\n }\n\n const r = await new Promise<{ code: number | null; output: string }>((resolve) => {\n const proc = spawn(process.execPath, [script, ...args], {\n cwd: root,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: root },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output: out }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: e.message }));\n });\n\n const ok = r.code === 0 && !looksLikeCliFailure(r.output);\n return { ok, output: r.output };\n}\n", "/**\n * SFMC \u5DE5\u4F5C\u76EE\u5F55\u5224\u5B9A\uFF08\u8FD0\u884C\u65F6\u6839\uFF1Aconfigs/\u3001modules/\uFF1B\u4E0D\u662F\u6E90\u7801\u4ED3\u5E93\u6839\uFF09\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/** \u76EE\u5F55\u662F\u5426\u4E3A\u6709\u6548 SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B configs/ \u4E0E modules/\uFF09\u3002 */\nexport function isValidSfmcRoot(dir: string): boolean {\n if (!dir || !dir.trim()) return false;\n const root = path.resolve(dir);\n try {\n return (\n fs.statSync(path.join(root, \"configs\")).isDirectory() &&\n fs.statSync(path.join(root, \"modules\")).isDirectory()\n );\n } catch {\n return false;\n }\n}\n", "/**\n * \u6A21\u5757\u542F\u505C\uFF1Aspawn `sfmc mod enable|disable`\uFF08\u5199 module-lock + best-effort \u70ED\u540C\u6B65\uFF09\u3002\n */\n\nimport { runSfmcCli, type RunSfmcCliResult } from \"./sfmc-cli.js\";\n\nexport interface SetModuleEnabledOptions {\n /** SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B modules/module-lock.json\uFF09\u3002 */\n sfmcRoot: string;\n /** \u6A21\u5757 logicalId / folderId / configKey\uFF08\u4E0E CLI `mod enable` \u4E00\u81F4\uFF09\u3002 */\n moduleId: string;\n enabled: boolean;\n /** \u53EF\u9009\uFF1A\u663E\u5F0F sfmc CLI \u5165\u53E3\uFF1B\u9ED8\u8BA4\u7531\u5B89\u88C5\u6811 / PATH / SFMC_CLI \u89E3\u6790\u3002 */\n cliPath?: string;\n}\n\nexport type SetModuleEnabledResult = RunSfmcCliResult;\n\n/** \u542F\u7528\u6216\u5173\u95ED\u6A21\u5757\uFF08\u4E0E CLI `mod enable|disable` \u540C\u6E90\uFF09\u3002 */\nexport async function setModuleEnabled(opts: SetModuleEnabledOptions): Promise<SetModuleEnabledResult> {\n const id = String(opts.moduleId || \"\").trim();\n if (!id) {\n return { ok: false, output: \"moduleId \u4E3A\u7A7A\" };\n }\n const action = opts.enabled ? \"enable\" : \"disable\";\n return runSfmcCli(opts.sfmcRoot, [\"mod\", action, id], { cliPath: opts.cliPath });\n}\n", "import path from \"node:path\";\n\n/** \u89E3\u6790 `--from local[:path]` / `dir:` \u6216 cwd \u4E3A\u6A21\u5757\u6839\u3002 */\nexport function resolveLocalModuleRoot(args: { from?: string | null; cwd: string }): string {\n const raw = (args.from ?? \"\").trim();\n if (!raw) return path.resolve(args.cwd);\n if (raw === \"local\") return path.resolve(args.cwd);\n if (raw.startsWith(\"local:\")) {\n const p = raw.slice(\"local:\".length).trim();\n if (!p) return path.resolve(args.cwd);\n return path.isAbsolute(p) ? path.resolve(p) : path.resolve(args.cwd, p);\n }\n if (raw.startsWith(\"dir:\")) {\n const p = raw.slice(\"dir:\".length).trim();\n return path.isAbsolute(p) ? path.resolve(p) : path.resolve(args.cwd, p);\n }\n return path.resolve(args.cwd);\n}\n", "/**\n * \u7EC4\u88C5\u5E76\u90E8\u7F72\u884C\u4E3A\u5305\uFF1A\u5728 SFMC_ROOT \u4E0B spawn `sfmc mod reload`\n * \uFF08\u4E0E CLI \u540C\u4E00\u5165\u53E3\uFF0C\u5B8C\u6574\u4F20\u53C2\uFF1B\u52FF\u76F4\u63A5\u88F8\u8C03 pack-manager verb\uFF09\u3002\n */\n\nimport { runSfmcCli } from \"./sfmc-cli.js\";\n\nexport interface RebuildOptions {\n /** SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B configs/\u3001modules/\uFF09\u3002 */\n sfmcRoot: string;\n /** \u4EC5\u6784\u5EFA\u90E8\u7F72\uFF0C\u4E0D\u5411 BDS \u53D1 reload\uFF08\u5BF9\u5E94 `mod reload --build-only`\uFF09\u3002 */\n buildOnly?: boolean;\n /** \u53EF\u9009\uFF1A\u663E\u5F0F sfmc CLI \u5165\u53E3\uFF1B\u9ED8\u8BA4\u7531\u5B89\u88C5\u6811 / PATH / SFMC_CLI \u89E3\u6790\u3002 */\n cliPath?: string;\n}\n\nexport interface RebuildResult {\n ok: boolean;\n output: string;\n}\n\nexport async function rebuildAndDeploy(opts: RebuildOptions): Promise<RebuildResult> {\n const args = [\"mod\", \"reload\"];\n if (opts.buildOnly) args.push(\"--build-only\");\n return runSfmcCli(opts.sfmcRoot, args, { cliPath: opts.cliPath });\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { submitModuleToRegistry, type RegistryModule, type RegistrySubmitOptions } from \"./registry-submit.js\";\n\n/** CLI \u4E0E CI \u5171\u7528\u53C2\u6570\u89E3\u6790\uFF0C\u672A\u77E5\u53C2\u6570\u8FD4\u56DE\u5931\u8D25\uFF0C\u907F\u514D\u8BEF\u63D0\u4EA4\u3002 */\nexport async function runRegistrySubmitCommand(args: string[]): Promise<string> {\n const options: RegistrySubmitOptions = {};\n let entryFile: string | undefined;\n const help =\n \"sfmc mod submit [\u6A21\u5757\u76EE\u5F55] [--dry-run] [--no-fork] [--wait-for-publish] [--registry owner/repo]\\nCI\uFF1Asfmc-module-submit --entry-file <JSON>\uFF08\u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\uFF09\";\n if (args.includes(\"--help\") || args.includes(\"-h\")) return help;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--dry-run\") options.dryRun = true;\n else if (arg === \"--no-fork\") options.noFork = true;\n else if (arg === \"--wait-for-publish\") options.waitForPublish = true;\n else if (arg === \"--registry\" || arg === \"--entry-file\") {\n const value = args[++i];\n if (!value || value.startsWith(\"-\")) throw new Error(`\u7F3A\u5C11 ${arg} \u7684\u503C`);\n if (arg === \"--registry\") options.registryRepo = value;\n else entryFile = value;\n } else if (arg.startsWith(\"-\") || options.moduleRoot) throw new Error(`\u672A\u77E5\u6216\u91CD\u590D\u53C2\u6570\uFF1A${arg}\\n${help}`);\n else options.moduleRoot = path.resolve(arg);\n }\n if (entryFile) {\n if (options.moduleRoot) throw new Error(\"--entry-file \u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\");\n options.entry = JSON.parse(await fs.readFile(path.resolve(entryFile), \"utf8\")) as RegistryModule;\n }\n const result = await submitModuleToRegistry(options);\n if (result.status === \"preview\")\n return `\u9884\u89C8\uFF1A${result.registryRepo}/${result.path}\\n\u539F\u6761\u76EE\uFF1A\\n${JSON.stringify(result.previous, null, 2)}\\n\u62DF\u63D0\u4EA4\uFF1A\\n${JSON.stringify(result.entry, null, 2)}\\n\u6821\u9A8C\u901A\u8FC7\uFF0C\u672A\u5199\u5165\u8FDC\u7AEF\u3002`;\n return `${{ unchanged: \"\u5185\u5BB9\u76F8\u540C\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\", created: \"\u5DF2\u521B\u5EFA\u7D22\u5F15 PR\", updated: \"\u5DF2\u66F4\u65B0\u7D22\u5F15 PR\" }[result.status]}${result.prUrl ? `\uFF1A${result.prUrl}` : \"\"}`;\n}\n", "/** \u6A21\u5757\u7D22\u5F15\u63D0\u4EA4\u6838\u5FC3\u3002\u4EC5\u5199\u5165\u4E13\u7528\u5206\u652F\u4E2D\u7684\u5355\u4E2A\u5206\u7247\uFF0C\u4E0D\u64CD\u4F5C\u4F5C\u8005\u5DE5\u4F5C\u6811\u3002 */\nimport { Ajv, type AnySchema } from \"ajv\";\nimport { execFile } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport semver from \"semver\";\n\nexport const MODULE_REGISTRY_REPO = \"DogeLakeDev/sfmc-modules\";\ntype Json = Record<string, unknown>;\nexport interface RegistryMetadata {\n name?: string;\n description?: string;\n category?: \"gameplay\" | \"utility\" | \"system\" | \"economy\" | \"social\";\n tags?: string[];\n authors?: string[];\n}\nexport interface RegistryModule extends RegistryMetadata {\n id: string;\n name: string;\n description: string;\n npm: string;\n version: string;\n sdk: string;\n license: string;\n official: boolean;\n repo?: string;\n requires: string[];\n}\nexport interface RegistrySubmitOptions {\n moduleRoot?: string;\n /** \u8868\u5355\u7B49\u5165\u53E3\u63D0\u4F9B\u539F\u59CB\u5B57\u6BB5\uFF0C\u4ECD\u987B\u7ECF\u8FC7\u76F8\u540C npm\u3001Schema \u548C\u7D22\u5F15\u6821\u9A8C\u3002 */\n entry?: RegistryModule;\n registryRepo?: string;\n dryRun?: boolean;\n /** \u7EF4\u62A4\u8005 / GitHub App \u5728\u7D22\u5F15\u4ED3\u5EFA\u5206\u652F\uFF0C\u987B\u6709 Contents \u548C Pull requests \u5199\u6743\u9650\u3002 */\n noFork?: boolean;\n token?: string;\n /** \u7B49\u5F85\u521A\u53D1\u5E03\u7684\u7CBE\u786E\u7248\u672C\u53EF\u89C1\uFF1B\u4EC5\u91CD\u8BD5 404\uFF0C\u6700\u957F 60 \u79D2\u3002 */\n waitForPublish?: boolean;\n log?: (message: string) => void;\n}\nexport interface RegistrySubmitResult {\n status: \"preview\" | \"unchanged\" | \"created\" | \"updated\";\n entry: RegistryModule;\n previous: RegistryModule | null;\n path: string;\n prUrl?: string;\n registryRepo: string;\n}\nfunction object(value: unknown, label: string): Json {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} \u987B\u4E3A JSON \u5BF9\u8C61`);\n return value as Json;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`\u7F3A\u5C11 ${label}`);\n return value.trim();\n}\nfunction sourceRepo(value: unknown): string | undefined {\n if (value === undefined) return undefined;\n const raw = typeof value === \"string\" ? value : object(value, \"repository\").url;\n const repo = text(raw, \"repository.url\")\n .replace(/^git\\+/, \"\")\n .replace(/\\.git$/, \"\");\n const url = new URL(repo);\n if (url.protocol !== \"https:\" || url.username || url.password)\n throw new Error(\"repository \u987B\u4E3A\u4E0D\u542B\u51ED\u636E\u7684 HTTPS \u5730\u5740\");\n return url.href.replace(/\\/$/, \"\");\n}\n\n/** \u4F5C\u8005\u914D\u7F6E\u53EA\u8865\u5145\u5C55\u793A\u5B57\u6BB5\uFF1B\u5305\u3001\u7248\u672C\u3001SDK \u548C\u4F9D\u8D56\u6765\u81EA\u5DF2\u6709\u5951\u7EA6\u3002 */\nexport function createRegistryEntry(\n pkgValue: unknown,\n manifestValue: unknown,\n metadataValue: unknown = {}\n): RegistryModule {\n const pkg = object(pkgValue, \"package.json\");\n const manifest = object(manifestValue, \"sapi/manifest.json\");\n const metadata = object(metadataValue, \"sfmc.registry.json\");\n const allowed = new Set([\"$schema\", \"name\", \"description\", \"category\", \"tags\", \"authors\"]);\n for (const key of Object.keys(metadata))\n if (!allowed.has(key)) throw new Error(`sfmc.registry.json \u4E0D\u652F\u6301\u5B57\u6BB5 ${key}`);\n if (pkg.private === true) throw new Error(\"private \u6A21\u5757\u4E0D\u80FD\u63D0\u4EA4\u516C\u5171\u7D22\u5F15\");\n if (manifest.schemaVersion !== 2) throw new Error(\"\u9700\u8981 schemaVersion=2 \u7684\u6A21\u5757\u6E05\u5355\");\n const peers = object(pkg.peerDependencies ?? {}, \"peerDependencies\");\n const entry: RegistryModule = {\n id: text(manifest.id, \"manifest.id\"),\n name: text(metadata.name ?? manifest.name, \"\u5C55\u793A\u540D\u79F0\uFF08name\uFF09\"),\n description: text(metadata.description ?? pkg.description, \"\u529F\u80FD\u4ECB\u7ECD\uFF08description\uFF09\"),\n npm: text(pkg.name, \"package.name\"),\n version: text(pkg.version, \"package.version\"),\n sdk: text(peers[\"@sfmc-bds/sdk\"], \"peerDependencies.@sfmc-bds/sdk\"),\n license: text(pkg.license, \"package.license\"),\n official: false,\n requires: (manifest.requires ?? []) as string[],\n };\n const repo = sourceRepo(pkg.repository);\n if (repo) entry.repo = repo;\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (metadata[key] !== undefined) Object.assign(entry, { [key]: metadata[key] });\n }\n return entry;\n}\n\nasync function readLocalEntry(root: string): Promise<{ entry: RegistryModule; overrides: Set<string> }> {\n const realRoot = await fs.realpath(root);\n const read = async (file: string) => {\n const target = await fs.realpath(path.join(realRoot, file));\n const relative = path.relative(realRoot, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))\n throw new Error(`${file} \u987B\u4F4D\u4E8E\u6A21\u5757\u76EE\u5F55\u5185`);\n const raw = await fs.readFile(target, \"utf8\");\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new Error(`${file} \u5305\u542B\u65E0\u6548 JSON`);\n }\n };\n let metadata: unknown = {};\n try {\n metadata = await read(\"sfmc.registry.json\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n return {\n entry: createRegistryEntry(await read(\"package.json\"), await read(\"sapi/manifest.json\"), metadata),\n overrides: new Set(Object.keys(object(metadata, \"sfmc.registry.json\"))),\n };\n}\n\nclass GitHubError extends Error {\n constructor(\n public status: number,\n endpoint: string,\n rateLimited = false\n ) {\n super(\n `GitHub ${status}: ${endpoint}${rateLimited ? \"\uFF08API \u914D\u989D\u5DF2\u7528\u5C3D\uFF0C\u8BF7\u767B\u5F55\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u914D\u989D\u6062\u590D\uFF09\" : status === 401 || status === 403 ? \"\uFF08\u68C0\u67E5\u767B\u5F55\u53CA Contents / Pull requests \u6743\u9650\uFF09\" : \"\"}`\n );\n }\n}\nasync function resolveToken(required: boolean): Promise<string | undefined> {\n const configured = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n if (configured) return configured;\n try {\n const { stdout } = await promisify(execFile)(\"gh\", [\"auth\", \"token\", \"--hostname\", \"github.com\"], {\n timeout: 10000,\n windowsHide: true,\n });\n return stdout.trim() || undefined;\n } catch {\n if (required) throw new Error(\"\u63D0\u4EA4\u9700\u8981 GitHub \u767B\u5F55\uFF1A\u6267\u884C gh auth login\uFF0C\u6216\u8BBE\u7F6E GH_TOKEN\u3002\");\n return undefined;\n }\n}\nfunction github(token?: string) {\n return async function api<T>(endpoint: string, method = \"GET\", body?: unknown): Promise<T> {\n const response = await fetch(`https://api.github.com/${endpoint}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"sfmc-devkit\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(15000),\n });\n // \u4E0D\u56DE\u663E\u670D\u52A1\u5668\u6B63\u6587\u6216\u8BA4\u8BC1\u4FE1\u606F\u3002\n if (!response.ok)\n throw new GitHubError(\n response.status,\n endpoint,\n response.status === 429 || response.headers.get(\"x-ratelimit-remaining\") === \"0\"\n );\n return response.status === 204 ? (undefined as T) : ((await response.json()) as T);\n };\n}\ntype Api = ReturnType<typeof github>;\ninterface GitHubRepository {\n id: number;\n full_name: string;\n default_branch: string;\n fork: boolean;\n permissions?: { push?: boolean };\n parent?: { id: number; full_name: string };\n source?: { id: number; full_name: string };\n}\ninterface Content {\n type: string;\n encoding: string;\n content: string;\n sha: string;\n}\nfunction decode(file: Content): unknown {\n if (file.type !== \"file\" || file.encoding !== \"base64\") throw new Error(\"\u7D22\u5F15\u5185\u5BB9\u987B\u4E3A\u666E\u901A JSON \u6587\u4EF6\");\n return JSON.parse(Buffer.from(file.content, \"base64\").toString(\"utf8\"));\n}\nasync function content(api: Api, repo: string, file: string, ref: string): Promise<Content | null> {\n try {\n return await api<Content>(`repos/${repo}/contents/${file}?ref=${encodeURIComponent(ref)}`);\n } catch (error) {\n if (error instanceof GitHubError && error.status === 404) return null;\n throw error;\n }\n}\nfunction same(a: unknown, b: unknown): boolean {\n const stable = (value: unknown): unknown =>\n Array.isArray(value)\n ? value.map(stable)\n : value && typeof value === \"object\"\n ? Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => [key, stable(item)])\n )\n : value;\n return JSON.stringify(stable(a)) === JSON.stringify(stable(b));\n}\nasync function checkPublished(entry: RegistryModule, wait: boolean): Promise<void> {\n const deadline = Date.now() + (wait ? 60000 : 0);\n while (true) {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(entry.npm)}/${encodeURIComponent(entry.version)}`,\n {\n signal: AbortSignal.timeout(15000),\n headers: { Accept: \"application/json\" },\n }\n );\n if (response.status === 404 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 3000));\n continue;\n }\n if (!response.ok)\n throw new Error(\n `\u516C\u5171 npm \u5C1A\u65E0\u53EF\u7528\u7684 ${entry.npm}@${entry.version}\uFF08HTTP ${response.status}\uFF09\uFF1B\u5148\u53D1\u5E03\u8BE5\u7CBE\u786E\u7248\u672C\u3002`\n );\n const pkg = object(await response.json(), \"npm \u5143\u6570\u636E\");\n const peers = object(pkg.peerDependencies ?? {}, \"npm peerDependencies\");\n if (\n pkg.name !== entry.npm ||\n pkg.version !== entry.version ||\n pkg.license !== entry.license ||\n peers[\"@sfmc-bds/sdk\"] !== entry.sdk\n ) {\n throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u540D\u79F0\u3001\u7248\u672C\u3001\u8BB8\u53EF\u8BC1\u6216 SDK \u517C\u5BB9\u8303\u56F4\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n }\n if (sourceRepo(pkg.repository) !== entry.repo) throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u6E90\u7801\u5730\u5740\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n return;\n }\n}\n\n/** \u6240\u6709\u5165\u53E3\u5171\u7528\uFF1A\u9884\u89C8\u4E5F\u9A8C\u8BC1\u5DF2\u53D1\u5E03\u7248\u672C\u4E0E\u6700\u65B0\u5206\u7247\uFF1B\u9884\u89C8\u9636\u6BB5\u4E0D\u4EA7\u751F\u8FDC\u7AEF\u5199\u5165\u3002 */\nexport async function submitModuleToRegistry(options: RegistrySubmitOptions = {}): Promise<RegistrySubmitResult> {\n const repo = options.registryRepo ?? MODULE_REGISTRY_REPO;\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) throw new Error(\"registryRepo \u987B\u4E3A owner/repo\");\n const local = options.entry ? null : await readLocalEntry(path.resolve(options.moduleRoot ?? process.cwd()));\n const entry = options.entry ? structuredClone(options.entry) : local!.entry;\n entry.requires ??= [];\n const token = options.token ?? (await resolveToken(!options.dryRun));\n if (!options.dryRun && !token) throw new Error(\"\u63D0\u4EA4\u9700\u8981\u6709\u6548\u7684 GitHub \u767B\u5F55\u6216 GH_TOKEN\");\n const api = github(token);\n const upstream = await api<GitHubRepository>(`repos/${repo}`);\n const canonicalRepo = upstream.full_name;\n const base = upstream.default_branch;\n const baseRef = await api<{ object: { sha: string } }>(\n `repos/${canonicalRepo}/git/ref/heads/${encodeURIComponent(base)}`\n );\n const baseSha = baseRef.object.sha;\n const schemaFile = await content(api, canonicalRepo, \"schemas/registry-module.schema.json\", baseSha);\n if (!schemaFile) throw new Error(\"\u7D22\u5F15\u4ED3\u7F3A\u5C11 registry-module.schema.json\");\n const ajv = new Ajv({ allErrors: true, strict: true });\n ajv.addFormat(\"semver-range\", (value: string) => !!value.trim() && semver.validRange(value) !== null);\n const validate = ajv.compile(decode(schemaFile) as AnySchema);\n entry.official = false; // \u9996\u6B21\u6536\u5F55\u6C38\u4E0D\u81EA\u884C\u58F0\u660E\u5B98\u65B9\u8EAB\u4EFD\u3002\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n if (!semver.valid(entry.version)) throw new Error(\"\u7248\u672C\u987B\u4E3A\u6709\u6548\u7684\u7CBE\u786E SemVer\");\n const file = `modules/${entry.id}.json`;\n options.log?.(`\u6821\u9A8C ${entry.npm}@${entry.version} \u4E0E\u6700\u65B0\u7D22\u5F15\u5206\u7247`);\n const tree = await api<{ truncated: boolean; tree: Array<{ path: string; type: string; sha: string }> }>(\n `repos/${canonicalRepo}/git/trees/${baseSha}?recursive=1`\n );\n if (tree.truncated) throw new Error(\"\u7D22\u5F15\u6811\u8FC7\u5927\uFF0C\u65E0\u6CD5\u5B8C\u6574\u68C0\u67E5\u4F9D\u8D56\");\n const shards = tree.tree.filter((item) => /^modules\\/[^/]+\\.json$/.test(item.path) && item.type === \"blob\");\n const modules: Record<string, RegistryModule> = Object.create(null) as Record<string, RegistryModule>;\n // \u53EA\u8BFB\u53D6\u8BE5\u6A21\u5757\u548C\u4F9D\u8D56\u95ED\u5305\uFF0C\u907F\u514D\u6BCF\u6B21\u63D0\u4EA4\u626B\u63CF\u6574\u4E2A\u7D22\u5F15\u5E76\u8017\u5C3D API \u914D\u989D\u3002\n const shardByPath = new Map(shards.map((item) => [item.path, item]));\n async function load(id: string): Promise<RegistryModule | null> {\n const shard = shardByPath.get(`modules/${id}.json`);\n if (!shard) return null;\n const blob = await api<{ encoding: string; content: string }>(`repos/${canonicalRepo}/git/blobs/${shard.sha}`);\n if (blob.encoding !== \"base64\") throw new Error(\"\u65E0\u6548\u7D22\u5F15 blob \u7F16\u7801\");\n const module = object(\n JSON.parse(Buffer.from(blob.content, \"base64\").toString(\"utf8\")),\n shard.path\n ) as unknown as RegistryModule;\n if (module.id !== id) throw new Error(`\u7D22\u5F15\u5206\u7247 ID \u4E0D\u4E00\u81F4\uFF1A${shard.path}`);\n return module;\n }\n const previous = await load(entry.id);\n if (previous) {\n if (previous.npm !== entry.npm || (previous.repo && sourceRepo(previous.repo) !== entry.repo))\n throw new Error(\"\u8BE5 ID \u5DF2\u5C5E\u4E8E\u5176\u4ED6 npm \u5305\u6216\u6E90\u7801\u4ED3\uFF1B\u8BF7\u7531\u7EF4\u62A4\u8005\u5904\u7406\u8FC1\u79FB\");\n if (!semver.valid(previous.version) || semver.lt(entry.version, previous.version))\n throw new Error(\"\u4E0D\u80FD\u964D\u4F4E\u5DF2\u6536\u5F55\u7248\u672C\");\n entry.official = previous.official; // \u4EC5\u7EE7\u627F\u7D22\u5F15\u4ED3\u5DF2\u5BA1\u6838\u8EAB\u4EFD\u3002\n // \u5355\u7EAF\u66F4\u65B0\u7248\u672C\u4FDD\u7559\u5DF2\u6574\u7406\u7684\u5C55\u793A\u4FE1\u606F\uFF1B\u4F5C\u8005\u914D\u7F6E\u53EF\u663E\u5F0F\u8986\u76D6\u3002\n if (local) {\n if (!local.overrides.has(\"name\")) entry.name = previous.name;\n if (!local.overrides.has(\"description\")) entry.description = previous.description;\n }\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (entry[key] === undefined && previous[key] !== undefined)\n Object.assign(entry, { [key]: structuredClone(previous[key]) });\n }\n }\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u8EAB\u4EFD\u6216\u5B57\u6BB5\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n modules[entry.id] = entry;\n const queue = [...entry.requires];\n const loaded = new Set([entry.id]);\n while (queue.length) {\n const batch = queue.splice(0, 4).filter((id) => {\n if (loaded.has(id)) return false;\n loaded.add(id);\n return true;\n });\n await Promise.all(\n batch.map(async (id) => {\n const dependency = await load(id);\n if (!dependency) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n if (!validate(dependency)) throw new Error(`\u4F9D\u8D56 ${id} \u7684\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4`);\n modules[id] = dependency;\n queue.push(...(dependency.requires ?? []));\n })\n );\n }\n const visited = new Set<string>();\n const visiting = new Set<string>();\n function visit(id: string): void {\n if (visiting.has(id)) throw new Error(`\u6A21\u5757\u4F9D\u8D56\u5B58\u5728\u5FAA\u73AF\uFF1A${id}`);\n if (visited.has(id)) return;\n const module = modules[id];\n if (!module) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n visiting.add(id);\n for (const dependency of module.requires ?? []) visit(dependency);\n visiting.delete(id);\n visited.add(id);\n }\n visit(entry.id);\n await checkPublished(entry, Boolean(options.waitForPublish));\n const result = { entry, previous, path: file, registryRepo: canonicalRepo };\n if (options.dryRun) return { ...result, status: \"preview\" };\n if (same(entry, previous)) return { ...result, status: \"unchanged\" };\n\n let headRepo = canonicalRepo;\n if (!options.noFork && upstream.permissions?.push !== true) {\n const user = await api<{ login: string }>(\"user\");\n const forkName = `${user.login}/${canonicalRepo.split(\"/\")[1]}`;\n let fork: GitHubRepository | undefined;\n try {\n fork = await api(`repos/${forkName}`);\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n }\n if (!fork)\n fork = await api<GitHubRepository>(`repos/${canonicalRepo}/forks`, \"POST\", { default_branch_only: true });\n if (fork.id === upstream.id) {\n // \u5019\u9009\u5730\u5740\u4E0E\u76EE\u6807\u5730\u5740\u53EF\u80FD\u56E0\u91CD\u5B9A\u5411\u6307\u5411\u540C\u4E00\u4ED3\u5E93\uFF0C\u6309\u5B9E\u9645\u6743\u9650\u5904\u7406\u3002\n if (fork.permissions?.push !== true)\n throw new Error(\n `${forkName} \u5DF2\u91CD\u5B9A\u5411\u5230 ${canonicalRepo}\uFF0C\u5F53\u524D\u51ED\u636E\u6CA1\u6709\u5199\u6743\u9650\uFF1B\u8BF7\u68C0\u67E5 GitHub \u767B\u5F55\u4E0E Contents \u6743\u9650\u3002`\n );\n } else {\n const networkId = upstream.source?.id ?? upstream.id;\n if (!fork.fork || (fork.parent?.id !== upstream.id && fork.source?.id !== networkId))\n throw new Error(\n `${fork.full_name} \u672A\u4E0E\u76EE\u6807\u7D22\u5F15\u4ED3\u5173\u8054\uFF0C\u65E0\u6CD5\u4F5C\u4E3A\u8BE5 PR \u7684\u6765\u6E90\uFF1B\u8BF7\u4F7F\u7528\u76EE\u6807\u4ED3\u7684 fork\uFF0C\u6216\u6709\u5199\u6743\u9650\u65F6\u4F7F\u7528 --no-fork\u3002`\n );\n headRepo = fork.full_name;\n }\n }\n type Pull = { number: number; html_url: string; head: { ref: string; repo: { full_name: string } | null } };\n let pull: Pull | undefined;\n const prefix = `sfmc-submit/${entry.id}/`;\n for (let page = 1; ; page++) {\n const pagePulls = await api<Pull[]>(\n `repos/${canonicalRepo}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100&page=${page}`\n );\n const matches = pagePulls.filter(\n (item) => item.head.ref.startsWith(prefix) && item.head.repo?.full_name.toLowerCase() === headRepo.toLowerCase()\n );\n if (matches.length > 1 || (pull && matches.length)) throw new Error(\"\u8BE5\u6A21\u5757\u6709\u591A\u4E2A\u63D0\u4EA4 PR\uFF0C\u8BF7\u5148\u5408\u5E76\u6216\u5173\u95ED\u591A\u4F59 PR\");\n pull ??= matches[0];\n if (pagePulls.length < 100) break;\n }\n // \u5DF2\u5408\u5E76\u7684\u5206\u652F\u65E0\u9700\u91CD\u7F6E\uFF1B\u65B0\u4E00\u8F6E\u63D0\u4EA4\u4EE5\u6700\u65B0 main \u7684 SHA \u6807\u8BC6\u3002\n const branch = pull?.head.ref ?? `${prefix}${baseSha.slice(0, 12)}`;\n const head = `${headRepo.split(\"/\")[0]}:${branch}`;\n let branchRef: { object: { sha: string } } | null = null;\n // \u65B0 fork \u7684\u521B\u5EFA\u662F\u5F02\u6B65\u64CD\u4F5C\uFF0C\u6700\u591A\u7B49\u5F85 15 \u79D2\u3002\n for (let attempt = 0; attempt < 6; attempt++) {\n try {\n branchRef = await api(`repos/${headRepo}/git/ref/heads/${encodeURIComponent(branch)}`);\n break;\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n try {\n branchRef = await api(`repos/${headRepo}/git/refs`, \"POST\", { ref: `refs/heads/${branch}`, sha: baseSha });\n break;\n } catch (createError) {\n if (!(createError instanceof GitHubError && [404, 422].includes(createError.status)) || attempt === 5)\n throw createError;\n await new Promise((resolve) => setTimeout(resolve, 3000));\n }\n }\n }\n if (!branchRef) throw new Error(\"\u63D0\u4EA4\u5206\u652F\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5\");\n const comparison = await api<{ files: Array<{ filename: string }> }>(\n `repos/${canonicalRepo}/compare/${baseSha}...${encodeURIComponent(`${headRepo.split(\"/\")[0]}:${branchRef.object.sha}`)}`\n );\n if (comparison.files.some((item) => item.filename !== file))\n throw new Error(\"\u4E13\u7528\u63D0\u4EA4\u5206\u652F\u5305\u542B\u5176\u4ED6\u6587\u4EF6\u6539\u52A8\uFF0C\u8BF7\u5148\u7531\u4F5C\u8005\u5904\u7406\");\n const oldFile = await content(api, headRepo, file, branchRef.object.sha);\n const oldEntry = oldFile ? decode(oldFile) : null;\n if (oldEntry) {\n const pending = object(oldEntry, file);\n if (\n pending.npm !== entry.npm ||\n (pending.repo && sourceRepo(pending.repo) !== entry.repo) ||\n typeof pending.version !== \"string\" ||\n !semver.valid(pending.version) ||\n semver.lt(entry.version, pending.version)\n ) {\n throw new Error(\"\u5DF2\u6709\u63D0\u4EA4\u7684\u6765\u6E90\u6216\u7248\u672C\u51B2\u7A81\uFF1B\u62D2\u7EDD\u8986\u76D6\");\n }\n }\n if (!same(entry, oldEntry)) {\n await api(`repos/${headRepo}/contents/${file}`, \"PUT\", {\n message: `chore(registry): ${entry.id} ${entry.version}`,\n content: Buffer.from(`${JSON.stringify(entry, null, 2)}\\n`).toString(\"base64\"),\n branch,\n ...(oldFile ? { sha: oldFile.sha } : {}),\n });\n }\n const title = `\u6536\u5F55 ${entry.id}@${entry.version}`;\n const body = `\u66F4\u65B0 \\`${file}\\`\u3002\\n\\n- npm\uFF1A\\`${entry.npm}@${entry.version}\\`\uFF08\u516C\u5171\u6E90\u7CBE\u786E\u7248\u672C\u5DF2\u6838\u5BF9\uFF09\\n- \u6E90\u7801\uFF1A${entry.repo ?? \"\u672A\u63D0\u4F9B\"}\\n- \u8BB8\u53EF\u8BC1\uFF1A\\`${entry.license}\\`\\n- SDK\uFF1A\\`${entry.sdk}\\`\\n- \u4F9D\u8D56\uFF1A${entry.requires.join(\", \") || \"\u65E0\"}\\n\\n\u5DF2\u68C0\u67E5\u5F53\u524D\u7D22\u5F15 Schema\u3001ID \u6765\u6E90\u3001\u7248\u672C\u4E0E\u4F9D\u8D56\u5173\u7CFB\u3002\u5B98\u65B9\u8EAB\u4EFD\u6CBF\u7528\u7EF4\u62A4\u8005\u5BA1\u6838\u7ED3\u679C\uFF1B\u8BF7\u68C0\u67E5 PR \u95E8\u7981\u540E\u5408\u5E76\u3002`;\n if (pull) {\n if (same(entry, oldEntry)) return { ...result, status: \"unchanged\", prUrl: pull.html_url };\n await api(`repos/${canonicalRepo}/pulls/${pull.number}`, \"PATCH\", { title, body });\n return { ...result, status: \"updated\", prUrl: pull.html_url };\n }\n const created = await api<{ html_url: string }>(`repos/${canonicalRepo}/pulls`, \"POST\", { title, body, base, head });\n return { ...result, status: \"created\", prUrl: created.html_url };\n}\n", "/**\n * \u76D1\u542C\u6A21\u5757 sapi/src\uFF0C\u9632\u6296\u540E\u56DE\u8C03 onRebuild\uFF08\u7531\u8C03\u7528\u65B9\u6CE8\u5165 rebuildAndDeploy / \u5176\u5B83\uFF09\u3002\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface ModuleWatchOptions {\n moduleRoot: string;\n debounceMs?: number;\n log?: (line: string) => void;\n onRebuild: () => Promise<{ ok: boolean; message?: string }>;\n}\n\nexport function startModuleWatch(opts: ModuleWatchOptions): { stop: () => void } {\n const log = opts.log ?? ((line: string) => console.log(line));\n const debounceMs = opts.debounceMs ?? 200;\n const sapiDir = path.join(opts.moduleRoot, \"sapi\");\n const srcDir = path.join(sapiDir, \"src\");\n\n if (!fs.existsSync(sapiDir)) {\n log(`[devkit:watch] \u65E0 sapi \u76EE\u5F55: ${sapiDir}`);\n return { stop: () => {} };\n }\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let pending = new Set<string>();\n let running = false;\n let stopped = false;\n\n log(`[devkit:watch] \u76D1\u542C ${opts.moduleRoot}`);\n\n const runOnce = async () => {\n if (running || stopped) return;\n running = true;\n const changed = [...pending];\n pending = new Set();\n const t0 = Date.now();\n log(`[devkit:watch] rebuild (${changed.length})\u2026`);\n try {\n const r = await opts.onRebuild();\n const ms = Date.now() - t0;\n if (r.ok) log(`[devkit:watch] ok ${ms}ms`);\n else log(`[devkit:watch] fail ${ms}ms ${r.message ?? \"\"}`);\n } catch (e) {\n log(`[devkit:watch] error ${(e as Error).message}`);\n } finally {\n running = false;\n }\n };\n\n const onSrc = (rel: string) => {\n if (stopped) return;\n if (rel.includes(\"node_modules\") || rel.includes(\"dist\") || rel.endsWith(\".tgz\")) return;\n pending.add(rel);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => void runOnce(), debounceMs);\n };\n\n const watchers: fs.FSWatcher[] = [];\n if (fs.existsSync(srcDir)) {\n try {\n watchers.push(\n fs.watch(srcDir, { recursive: true, persistent: true }, (_e, filename) => {\n if (filename) onSrc(filename.toString());\n })\n );\n } catch {\n watchers.push(\n fs.watch(srcDir, { persistent: true }, (_e, filename) => {\n if (filename) onSrc(filename.toString());\n })\n );\n }\n }\n\n const watchMeta = (file: string, kind: string) => {\n if (!fs.existsSync(file)) return;\n watchers.push(\n fs.watch(file, { persistent: true }, (event) => {\n if (event === \"change\") log(`[devkit:watch] ${kind} \u5DF2\u6539\uFF0C\u9700\u91CD\u542F BDS\uFF08SAPI \u542F\u52A8\u671F\u7F13\u5B58\uFF09`);\n })\n );\n };\n watchMeta(path.join(sapiDir, \"manifest.json\"), \"manifest\");\n watchMeta(path.join(sapiDir, \"tsconfig.json\"), \"tsconfig\");\n\n return {\n stop() {\n stopped = true;\n if (debounceTimer) clearTimeout(debounceTimer);\n for (const w of watchers) {\n try {\n w.close();\n } catch {\n /* ignore */\n }\n }\n log(\"[devkit:watch] stopped\");\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * \u6709\u6548\u6A21\u5757\u6839\u5224\u5B9A\uFF08\u6269\u5C55\u4E0E CLI \u5171\u7528\u6743\u5A01\uFF09\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type ModuleRootInfo = {\n root: string;\n id: string;\n name?: string;\n schemaVersion: number;\n};\n\n/** \u76EE\u5F55\u662F\u5426\u4E3A\u6709\u6548 SFMC \u6A21\u5757\u6839\uFF1Apackage.json + sapi/manifest.json schemaVersion===2 + \u975E\u7A7A id */\nexport function isValidModuleRoot(dir: string): boolean {\n return readModuleRootInfo(dir) !== null;\n}\n\nexport function readModuleRootInfo(dir: string): ModuleRootInfo | null {\n const pkg = path.join(dir, \"package.json\");\n const manifestPath = path.join(dir, \"sapi\", \"manifest.json\");\n if (!fs.existsSync(pkg) || !fs.existsSync(manifestPath)) return null;\n try {\n const m = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n schemaVersion?: number;\n id?: string;\n name?: string;\n };\n if (m.schemaVersion !== 2) return null;\n if (typeof m.id !== \"string\" || !m.id.trim()) return null;\n return {\n root: path.resolve(dir),\n id: m.id.trim(),\n name: typeof m.name === \"string\" ? m.name : undefined,\n schemaVersion: 2,\n };\n } catch {\n return null;\n }\n}\n\n/** \u81EA filePath \u5411\u4E0A\u627E\u6700\u8FD1\u6709\u6548\u6A21\u5757\u6839\uFF1B\u627E\u4E0D\u5230\u8FD4\u56DE null */\nexport function findModuleRootFromFile(filePath: string): string | null {\n let cur = path.dirname(path.resolve(filePath));\n const root = path.parse(cur).root;\n while (true) {\n if (isValidModuleRoot(cur)) return cur;\n if (cur === root) return null;\n const parent = path.dirname(cur);\n if (parent === cur) return null;\n cur = parent;\n }\n}\n", "/**\n * \u89E3\u6790\u5E76 spawn sfmc CLI\u3002\n * CLI \u4E0E SFMC \u5DE5\u4F5C\u76EE\u5F55\u65E0\u5173\uFF1A\u4ECE\u672C\u5305/\u6269\u5C55\u5B89\u88C5\u6811\u3001PATH \u6216\u663E\u5F0F\u914D\u7F6E\u89E3\u6790\uFF1B\n * \u5DE5\u4F5C\u76EE\u5F55\u53EA\u4F5C\u4E3A spawn \u7684 cwd \u4E0E SFMC_ROOT\u3002\n */\n\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { isValidSfmcRoot } from \"./sfmc-root.js\";\n\n/** chalk.hex(\"#e06c75\") \u7684\u771F\u5F69\u5E8F\u5217\uFF1BCLI \u5931\u8D25\u6587\u6848\u7ECF c.red() \u5305\u88C5\u3002 */\nconst CLI_ANSI_RED = \"\\u001b[38;2;224;108;117m\";\n\nexport interface ResolveSfmcCliOptions {\n /** \u663E\u5F0F CLI \u5165\u53E3\uFF08.js/.mjs\uFF09\uFF1B\u4E5F\u53EF\u7528\u73AF\u5883\u53D8\u91CF SFMC_CLI\u3002 */\n cliPath?: string;\n}\n\nfunction tryRequireCli(from: string): string | null {\n try {\n const resolved = createRequire(from).resolve(\"@sfmc-bds/cli/cli\");\n return fs.existsSync(resolved) ? resolved : null;\n } catch {\n return null;\n }\n}\n\n/** \u81EA PATH \u4E0A\u7684 sfmc \u53EF\u6267\u884C\u6587\u4EF6\u65C1\u89E3\u6790 @sfmc-bds/cli\uFF08npm global / \u672C\u5730 .bin\uFF09\u3002 */\nfunction resolveCliFromPathEnv(): string | null {\n const pathEnv = process.env.PATH ?? \"\";\n const names =\n process.platform === \"win32\" ? [\"sfmc.cmd\", \"sfmc.exe\", \"sfmc.ps1\", \"sfmc\"] : [\"sfmc\"];\n for (const dir of pathEnv.split(path.delimiter)) {\n if (!dir) continue;\n let hit = false;\n for (const name of names) {\n if (fs.existsSync(path.join(dir, name))) {\n hit = true;\n break;\n }\n }\n if (!hit) continue;\n const nearCli = path.join(dir, \"..\", \"@sfmc-bds\", \"cli\", \"dist\", \"main.js\");\n if (fs.existsSync(nearCli)) return nearCli;\n const nearMeta = path.join(dir, \"..\", \"@sfmc-bds\", \"sfmc\", \"bin\", \"sfmc.mjs\");\n if (fs.existsSync(nearMeta)) return nearMeta;\n const fromBin = tryRequireCli(path.join(dir, \"..\", \"package.json\"));\n if (fromBin) return fromBin;\n }\n return null;\n}\n\n/**\n * \u89E3\u6790 sfmc CLI \u811A\u672C\u8DEF\u5F84\u3002\n * \u987A\u5E8F\uFF1A\u663E\u5F0F cliPath / SFMC_CLI \u2192 \u672C\u5305\u5B89\u88C5\u6811\uFF08@sfmc-bds/cli\uFF09\u2192 cwd \u7684 node_modules \u2192 PATH\u3002\n */\nexport function resolveSfmcCli(opts: ResolveSfmcCliOptions = {}): string {\n const explicit = (opts.cliPath || process.env.SFMC_CLI || \"\").trim();\n if (explicit) {\n const p = path.resolve(explicit);\n if (!fs.existsSync(p)) {\n throw new Error(`\u6307\u5B9A\u7684 sfmc CLI \u4E0D\u5B58\u5728\uFF1A${p}\uFF08\u68C0\u67E5 SFMC_CLI / sfmc.cliPath\uFF09`);\n }\n return p;\n }\n\n const here = fileURLToPath(import.meta.url);\n const fromInstall = tryRequireCli(here);\n if (fromInstall) return fromInstall;\n\n const fromCwd = tryRequireCli(path.join(process.cwd(), \"package.json\"));\n if (fromCwd) return fromCwd;\n\n const fromPath = resolveCliFromPathEnv();\n if (fromPath) return fromPath;\n\n throw new Error(\n \"\u65E0\u6CD5\u89E3\u6790 sfmc CLI\u3002\u8BF7\u5B89\u88C5 @sfmc-bds/cli\uFF08\u6216\u786E\u4FDD PATH \u4E0A\u6709 sfmc\uFF09\uFF0C\u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF SFMC_CLI / \u6269\u5C55\u914D\u7F6E sfmc.cliPath\u3002\"\n );\n}\n\nfunction looksLikeCliFailure(output: string): boolean {\n if (output.includes(CLI_ANSI_RED)) return true;\n if (/\\[pack-manager\\].*required/.test(output)) return true;\n if (/^Error:/m.test(output)) return true;\n return false;\n}\n\nexport interface RunSfmcCliResult {\n ok: boolean;\n output: string;\n}\n\nexport interface RunSfmcCliOptions {\n cliPath?: string;\n}\n\n/** \u5728 SFMC \u5DE5\u4F5C\u76EE\u5F55\u4E0B\u6267\u884C `node <sfmc-cli> ...args`\uFF08env.SFMC_ROOT = \u5DE5\u4F5C\u76EE\u5F55\uFF09\u3002 */\nexport async function runSfmcCli(\n sfmcRoot: string,\n args: string[],\n opts: RunSfmcCliOptions = {}\n): Promise<RunSfmcCliResult> {\n const root = path.resolve(sfmcRoot);\n if (!isValidSfmcRoot(root)) {\n return {\n ok: false,\n output: `\u65E0\u6548\u7684 SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF1A${root}\uFF08\u9700\u8981\u542B configs/ \u4E0E modules/\uFF0C\u4E0D\u5FC5\u542B\u6E90\u7801\u4ED3\u5E93\uFF09`,\n };\n }\n\n let script: string;\n try {\n script = resolveSfmcCli({ cliPath: opts.cliPath });\n } catch (e) {\n return { ok: false, output: e instanceof Error ? e.message : String(e) };\n }\n\n const r = await new Promise<{ code: number | null; output: string }>((resolve) => {\n const proc = spawn(process.execPath, [script, ...args], {\n cwd: root,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, SFMC_ROOT: root },\n });\n let out = \"\";\n proc.stdout?.on(\"data\", (d) => {\n out += d.toString();\n });\n proc.stderr?.on(\"data\", (d) => {\n out += d.toString();\n });\n proc.on(\"exit\", (code) => resolve({ code, output: out }));\n proc.on(\"error\", (e) => resolve({ code: 1, output: e.message }));\n });\n\n const ok = r.code === 0 && !looksLikeCliFailure(r.output);\n return { ok, output: r.output };\n}\n", "/**\n * SFMC \u5DE5\u4F5C\u76EE\u5F55\u5224\u5B9A\uFF08\u8FD0\u884C\u65F6\u6839\uFF1Aconfigs/\u3001modules/\uFF1B\u4E0D\u662F\u6E90\u7801\u4ED3\u5E93\u6839\uFF09\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n/** \u76EE\u5F55\u662F\u5426\u4E3A\u6709\u6548 SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B configs/ \u4E0E modules/\uFF09\u3002 */\nexport function isValidSfmcRoot(dir: string): boolean {\n if (!dir || !dir.trim()) return false;\n const root = path.resolve(dir);\n try {\n return (\n fs.statSync(path.join(root, \"configs\")).isDirectory() &&\n fs.statSync(path.join(root, \"modules\")).isDirectory()\n );\n } catch {\n return false;\n }\n}\n", "/**\n * \u6A21\u5757\u542F\u505C\uFF1Aspawn `sfmc mod enable|disable`\uFF08\u5199 module-lock + best-effort \u70ED\u540C\u6B65\uFF09\u3002\n */\n\nimport { runSfmcCli, type RunSfmcCliResult } from \"./sfmc-cli.js\";\n\nexport interface SetModuleEnabledOptions {\n /** SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B modules/module-lock.json\uFF09\u3002 */\n sfmcRoot: string;\n /** \u6A21\u5757 logicalId / folderId / configKey\uFF08\u4E0E CLI `mod enable` \u4E00\u81F4\uFF09\u3002 */\n moduleId: string;\n enabled: boolean;\n /** \u53EF\u9009\uFF1A\u663E\u5F0F sfmc CLI \u5165\u53E3\uFF1B\u9ED8\u8BA4\u7531\u5B89\u88C5\u6811 / PATH / SFMC_CLI \u89E3\u6790\u3002 */\n cliPath?: string;\n}\n\nexport type SetModuleEnabledResult = RunSfmcCliResult;\n\n/** \u542F\u7528\u6216\u5173\u95ED\u6A21\u5757\uFF08\u4E0E CLI `mod enable|disable` \u540C\u6E90\uFF09\u3002 */\nexport async function setModuleEnabled(opts: SetModuleEnabledOptions): Promise<SetModuleEnabledResult> {\n const id = String(opts.moduleId || \"\").trim();\n if (!id) {\n return { ok: false, output: \"moduleId \u4E3A\u7A7A\" };\n }\n const action = opts.enabled ? \"enable\" : \"disable\";\n return runSfmcCli(opts.sfmcRoot, [\"mod\", action, id], { cliPath: opts.cliPath });\n}\n", "import path from \"node:path\";\n\n/** \u89E3\u6790 `--from local[:path]` / `dir:` \u6216 cwd \u4E3A\u6A21\u5757\u6839\u3002 */\nexport function resolveLocalModuleRoot(args: { from?: string | null; cwd: string }): string {\n const raw = (args.from ?? \"\").trim();\n if (!raw) return path.resolve(args.cwd);\n if (raw === \"local\") return path.resolve(args.cwd);\n if (raw.startsWith(\"local:\")) {\n const p = raw.slice(\"local:\".length).trim();\n if (!p) return path.resolve(args.cwd);\n return path.isAbsolute(p) ? path.resolve(p) : path.resolve(args.cwd, p);\n }\n if (raw.startsWith(\"dir:\")) {\n const p = raw.slice(\"dir:\".length).trim();\n return path.isAbsolute(p) ? path.resolve(p) : path.resolve(args.cwd, p);\n }\n return path.resolve(args.cwd);\n}\n", "/**\n * \u7EC4\u88C5\u5E76\u90E8\u7F72\u884C\u4E3A\u5305\uFF1A\u5728 SFMC_ROOT \u4E0B spawn `sfmc mod reload`\n * \uFF08\u4E0E CLI \u540C\u4E00\u5165\u53E3\uFF0C\u5B8C\u6574\u4F20\u53C2\uFF1B\u52FF\u76F4\u63A5\u88F8\u8C03 pack-manager verb\uFF09\u3002\n */\n\nimport { runSfmcCli } from \"./sfmc-cli.js\";\n\nexport interface RebuildOptions {\n /** SFMC \u5DE5\u4F5C\u76EE\u5F55\uFF08\u542B configs/\u3001modules/\uFF09\u3002 */\n sfmcRoot: string;\n /** \u4EC5\u6784\u5EFA\u90E8\u7F72\uFF0C\u4E0D\u5411 BDS \u53D1 reload\uFF08\u5BF9\u5E94 `mod reload --build-only`\uFF09\u3002 */\n buildOnly?: boolean;\n /** \u53EF\u9009\uFF1A\u663E\u5F0F sfmc CLI \u5165\u53E3\uFF1B\u9ED8\u8BA4\u7531\u5B89\u88C5\u6811 / PATH / SFMC_CLI \u89E3\u6790\u3002 */\n cliPath?: string;\n}\n\nexport interface RebuildResult {\n ok: boolean;\n output: string;\n}\n\nexport async function rebuildAndDeploy(opts: RebuildOptions): Promise<RebuildResult> {\n const args = [\"mod\", \"reload\"];\n if (opts.buildOnly) args.push(\"--build-only\");\n return runSfmcCli(opts.sfmcRoot, args, { cliPath: opts.cliPath });\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { submitModuleToRegistry, type RegistryModule, type RegistrySubmitOptions } from \"./registry-submit.js\";\n\n/** CLI \u4E0E CI \u5171\u7528\u53C2\u6570\u89E3\u6790\uFF0C\u672A\u77E5\u53C2\u6570\u8FD4\u56DE\u5931\u8D25\uFF0C\u907F\u514D\u8BEF\u63D0\u4EA4\u3002 */\nexport async function runRegistrySubmitCommand(args: string[]): Promise<string> {\n const options: RegistrySubmitOptions = {};\n let entryFile: string | undefined;\n const help =\n \"sfmc mod submit [\u6A21\u5757\u76EE\u5F55] [--dry-run] [--no-fork] [--wait-for-publish] [--registry owner/repo]\\nCI\uFF1Asfmc-module-submit --entry-file <JSON>\uFF08\u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\uFF09\";\n if (args.includes(\"--help\") || args.includes(\"-h\")) return help;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--dry-run\") options.dryRun = true;\n else if (arg === \"--no-fork\") options.noFork = true;\n else if (arg === \"--wait-for-publish\") options.waitForPublish = true;\n else if (arg === \"--registry\" || arg === \"--entry-file\") {\n const value = args[++i];\n if (!value || value.startsWith(\"-\")) throw new Error(`\u7F3A\u5C11 ${arg} \u7684\u503C`);\n if (arg === \"--registry\") options.registryRepo = value;\n else entryFile = value;\n } else if (arg.startsWith(\"-\") || options.moduleRoot) throw new Error(`\u672A\u77E5\u6216\u91CD\u590D\u53C2\u6570\uFF1A${arg}\\n${help}`);\n else options.moduleRoot = path.resolve(arg);\n }\n if (entryFile) {\n if (options.moduleRoot) throw new Error(\"--entry-file \u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\");\n options.entry = JSON.parse(await fs.readFile(path.resolve(entryFile), \"utf8\")) as RegistryModule;\n }\n const result = await submitModuleToRegistry(options);\n if (result.status === \"preview\")\n return `\u9884\u89C8\uFF1A${result.registryRepo}/${result.path}\\n\u539F\u6761\u76EE\uFF1A\\n${JSON.stringify(result.previous, null, 2)}\\n\u62DF\u63D0\u4EA4\uFF1A\\n${JSON.stringify(result.entry, null, 2)}\\n\u6821\u9A8C\u901A\u8FC7\uFF0C\u672A\u5199\u5165\u8FDC\u7AEF\u3002`;\n return `${{ unchanged: \"\u5185\u5BB9\u76F8\u540C\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\", created: \"\u5DF2\u521B\u5EFA\u7D22\u5F15 PR\", updated: \"\u5DF2\u66F4\u65B0\u7D22\u5F15 PR\" }[result.status]}${result.prUrl ? `\uFF1A${result.prUrl}` : \"\"}`;\n}\n", "/** \u6A21\u5757\u7D22\u5F15\u63D0\u4EA4\u6838\u5FC3\u3002\u4EC5\u5199\u5165\u4E13\u7528\u5206\u652F\u4E2D\u7684\u5355\u4E2A\u5206\u7247\uFF0C\u4E0D\u64CD\u4F5C\u4F5C\u8005\u5DE5\u4F5C\u6811\u3002 */\nimport { Ajv, type AnySchema } from \"ajv\";\nimport { execFile } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport semver from \"semver\";\n\nexport const MODULE_REGISTRY_REPO = \"DogeLakeDev/sfmc-modules\";\ntype Json = Record<string, unknown>;\nexport interface RegistryMetadata {\n name?: string;\n description?: string;\n category?: \"gameplay\" | \"utility\" | \"system\" | \"economy\" | \"social\";\n tags?: string[];\n authors?: string[];\n}\nexport interface RegistryModule extends RegistryMetadata {\n id: string;\n name: string;\n description: string;\n npm: string;\n version: string;\n sdk: string;\n license: string;\n official: boolean;\n repo?: string;\n requires: string[];\n}\nexport interface RegistrySubmitOptions {\n moduleRoot?: string;\n /** \u8868\u5355\u7B49\u5165\u53E3\u63D0\u4F9B\u539F\u59CB\u5B57\u6BB5\uFF0C\u4ECD\u987B\u7ECF\u8FC7\u76F8\u540C npm\u3001Schema \u548C\u7D22\u5F15\u6821\u9A8C\u3002 */\n entry?: RegistryModule;\n registryRepo?: string;\n dryRun?: boolean;\n /** \u7EF4\u62A4\u8005 / GitHub App \u5728\u7D22\u5F15\u4ED3\u5EFA\u5206\u652F\uFF0C\u987B\u6709 Contents \u548C Pull requests \u5199\u6743\u9650\u3002 */\n noFork?: boolean;\n token?: string;\n /** \u7B49\u5F85\u521A\u53D1\u5E03\u7684\u7CBE\u786E\u7248\u672C\u53EF\u89C1\uFF1B\u4EC5\u91CD\u8BD5 404\uFF0C\u6700\u957F 60 \u79D2\u3002 */\n waitForPublish?: boolean;\n log?: (message: string) => void;\n}\nexport interface RegistrySubmitResult {\n status: \"preview\" | \"unchanged\" | \"created\" | \"updated\";\n entry: RegistryModule;\n previous: RegistryModule | null;\n path: string;\n prUrl?: string;\n registryRepo: string;\n}\nfunction object(value: unknown, label: string): Json {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} \u987B\u4E3A JSON \u5BF9\u8C61`);\n return value as Json;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`\u7F3A\u5C11 ${label}`);\n return value.trim();\n}\nfunction sourceRepo(value: unknown): string | undefined {\n if (value === undefined) return undefined;\n const raw = typeof value === \"string\" ? value : object(value, \"repository\").url;\n const repo = text(raw, \"repository.url\")\n .replace(/^git\\+/, \"\")\n .replace(/\\.git$/, \"\");\n const url = new URL(repo);\n if (url.protocol !== \"https:\" || url.username || url.password)\n throw new Error(\"repository \u987B\u4E3A\u4E0D\u542B\u51ED\u636E\u7684 HTTPS \u5730\u5740\");\n return url.href.replace(/\\/$/, \"\");\n}\n\n/** \u4F5C\u8005\u914D\u7F6E\u53EA\u8865\u5145\u5C55\u793A\u5B57\u6BB5\uFF1B\u5305\u3001\u7248\u672C\u3001SDK \u548C\u4F9D\u8D56\u6765\u81EA\u5DF2\u6709\u5951\u7EA6\u3002 */\nexport function createRegistryEntry(\n pkgValue: unknown,\n manifestValue: unknown,\n metadataValue: unknown = {}\n): RegistryModule {\n const pkg = object(pkgValue, \"package.json\");\n const manifest = object(manifestValue, \"sapi/manifest.json\");\n const metadata = object(metadataValue, \"sfmc.registry.json\");\n const allowed = new Set([\"$schema\", \"name\", \"description\", \"category\", \"tags\", \"authors\"]);\n for (const key of Object.keys(metadata))\n if (!allowed.has(key)) throw new Error(`sfmc.registry.json \u4E0D\u652F\u6301\u5B57\u6BB5 ${key}`);\n if (pkg.private === true) throw new Error(\"private \u6A21\u5757\u4E0D\u80FD\u63D0\u4EA4\u516C\u5171\u7D22\u5F15\");\n if (manifest.schemaVersion !== 2) throw new Error(\"\u9700\u8981 schemaVersion=2 \u7684\u6A21\u5757\u6E05\u5355\");\n const peers = object(pkg.peerDependencies ?? {}, \"peerDependencies\");\n const description = metadata.description ?? pkg.description ?? \"\";\n if (typeof description !== \"string\") throw new Error(\"\u529F\u80FD\u4ECB\u7ECD\uFF08description\uFF09\u987B\u4E3A\u5B57\u7B26\u4E32\uFF0C\u53EF\u7559\u7A7A\");\n const entry: RegistryModule = {\n id: text(manifest.id, \"manifest.id\"),\n name: text(metadata.name ?? manifest.name, \"\u5C55\u793A\u540D\u79F0\uFF08name\uFF09\"),\n description: description.trim(),\n npm: text(pkg.name, \"package.name\"),\n version: text(pkg.version, \"package.version\"),\n sdk: text(peers[\"@sfmc-bds/sdk\"], \"peerDependencies.@sfmc-bds/sdk\"),\n license: text(pkg.license, \"package.license\"),\n official: false,\n requires: (manifest.requires ?? []) as string[],\n };\n const repo = sourceRepo(pkg.repository);\n if (repo) entry.repo = repo;\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (metadata[key] !== undefined) Object.assign(entry, { [key]: metadata[key] });\n }\n return entry;\n}\n\nasync function readLocalEntry(root: string): Promise<{ entry: RegistryModule; overrides: Set<string> }> {\n const realRoot = await fs.realpath(root);\n const read = async (file: string) => {\n const target = await fs.realpath(path.join(realRoot, file));\n const relative = path.relative(realRoot, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))\n throw new Error(`${file} \u987B\u4F4D\u4E8E\u6A21\u5757\u76EE\u5F55\u5185`);\n const raw = await fs.readFile(target, \"utf8\");\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new Error(`${file} \u5305\u542B\u65E0\u6548 JSON`);\n }\n };\n let metadata: unknown = {};\n try {\n metadata = await read(\"sfmc.registry.json\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n return {\n entry: createRegistryEntry(await read(\"package.json\"), await read(\"sapi/manifest.json\"), metadata),\n overrides: new Set(Object.keys(object(metadata, \"sfmc.registry.json\"))),\n };\n}\n\nclass GitHubError extends Error {\n constructor(\n public status: number,\n endpoint: string,\n rateLimited = false\n ) {\n super(\n `GitHub ${status}: ${endpoint}${rateLimited ? \"\uFF08API \u914D\u989D\u5DF2\u7528\u5C3D\uFF0C\u8BF7\u767B\u5F55\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u914D\u989D\u6062\u590D\uFF09\" : status === 401 || status === 403 ? \"\uFF08\u68C0\u67E5\u767B\u5F55\u53CA Contents / Pull requests \u6743\u9650\uFF09\" : \"\"}`\n );\n }\n}\nasync function resolveToken(required: boolean): Promise<string | undefined> {\n const configured = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n if (configured) return configured;\n try {\n const { stdout } = await promisify(execFile)(\"gh\", [\"auth\", \"token\", \"--hostname\", \"github.com\"], {\n timeout: 10000,\n windowsHide: true,\n });\n return stdout.trim() || undefined;\n } catch {\n if (required) throw new Error(\"\u63D0\u4EA4\u9700\u8981 GitHub \u767B\u5F55\uFF1A\u6267\u884C gh auth login\uFF0C\u6216\u8BBE\u7F6E GH_TOKEN\u3002\");\n return undefined;\n }\n}\nfunction github(token?: string) {\n return async function api<T>(endpoint: string, method = \"GET\", body?: unknown): Promise<T> {\n const response = await fetch(`https://api.github.com/${endpoint}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"sfmc-devkit\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(15000),\n });\n // \u4E0D\u56DE\u663E\u670D\u52A1\u5668\u6B63\u6587\u6216\u8BA4\u8BC1\u4FE1\u606F\u3002\n if (!response.ok)\n throw new GitHubError(\n response.status,\n endpoint,\n response.status === 429 || response.headers.get(\"x-ratelimit-remaining\") === \"0\"\n );\n return response.status === 204 ? (undefined as T) : ((await response.json()) as T);\n };\n}\ntype Api = ReturnType<typeof github>;\ninterface GitHubRepository {\n id: number;\n full_name: string;\n default_branch: string;\n fork: boolean;\n permissions?: { push?: boolean };\n parent?: { id: number; full_name: string };\n source?: { id: number; full_name: string };\n}\ninterface Content {\n type: string;\n encoding: string;\n content: string;\n sha: string;\n}\nfunction decode(file: Content): unknown {\n if (file.type !== \"file\" || file.encoding !== \"base64\") throw new Error(\"\u7D22\u5F15\u5185\u5BB9\u987B\u4E3A\u666E\u901A JSON \u6587\u4EF6\");\n return JSON.parse(Buffer.from(file.content, \"base64\").toString(\"utf8\"));\n}\nasync function content(api: Api, repo: string, file: string, ref: string): Promise<Content | null> {\n try {\n return await api<Content>(`repos/${repo}/contents/${file}?ref=${encodeURIComponent(ref)}`);\n } catch (error) {\n if (error instanceof GitHubError && error.status === 404) return null;\n throw error;\n }\n}\nfunction same(a: unknown, b: unknown): boolean {\n const stable = (value: unknown): unknown =>\n Array.isArray(value)\n ? value.map(stable)\n : value && typeof value === \"object\"\n ? Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => [key, stable(item)])\n )\n : value;\n return JSON.stringify(stable(a)) === JSON.stringify(stable(b));\n}\nasync function checkPublished(entry: RegistryModule, wait: boolean): Promise<void> {\n const deadline = Date.now() + (wait ? 60000 : 0);\n while (true) {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(entry.npm)}/${encodeURIComponent(entry.version)}`,\n {\n signal: AbortSignal.timeout(15000),\n headers: { Accept: \"application/json\" },\n }\n );\n if (response.status === 404 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 3000));\n continue;\n }\n if (!response.ok)\n throw new Error(\n `\u516C\u5171 npm \u5C1A\u65E0\u53EF\u7528\u7684 ${entry.npm}@${entry.version}\uFF08HTTP ${response.status}\uFF09\uFF1B\u5148\u53D1\u5E03\u8BE5\u7CBE\u786E\u7248\u672C\u3002`\n );\n const pkg = object(await response.json(), \"npm \u5143\u6570\u636E\");\n const peers = object(pkg.peerDependencies ?? {}, \"npm peerDependencies\");\n if (\n pkg.name !== entry.npm ||\n pkg.version !== entry.version ||\n pkg.license !== entry.license ||\n peers[\"@sfmc-bds/sdk\"] !== entry.sdk\n ) {\n throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u540D\u79F0\u3001\u7248\u672C\u3001\u8BB8\u53EF\u8BC1\u6216 SDK \u517C\u5BB9\u8303\u56F4\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n }\n if (sourceRepo(pkg.repository) !== entry.repo) throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u6E90\u7801\u5730\u5740\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n return;\n }\n}\n\n/** \u6240\u6709\u5165\u53E3\u5171\u7528\uFF1A\u9884\u89C8\u4E5F\u9A8C\u8BC1\u5DF2\u53D1\u5E03\u7248\u672C\u4E0E\u6700\u65B0\u5206\u7247\uFF1B\u9884\u89C8\u9636\u6BB5\u4E0D\u4EA7\u751F\u8FDC\u7AEF\u5199\u5165\u3002 */\nexport async function submitModuleToRegistry(options: RegistrySubmitOptions = {}): Promise<RegistrySubmitResult> {\n const repo = options.registryRepo ?? MODULE_REGISTRY_REPO;\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) throw new Error(\"registryRepo \u987B\u4E3A owner/repo\");\n const local = options.entry ? null : await readLocalEntry(path.resolve(options.moduleRoot ?? process.cwd()));\n const entry = options.entry ? structuredClone(options.entry) : local!.entry;\n entry.requires ??= [];\n const token = options.token ?? (await resolveToken(!options.dryRun));\n if (!options.dryRun && !token) throw new Error(\"\u63D0\u4EA4\u9700\u8981\u6709\u6548\u7684 GitHub \u767B\u5F55\u6216 GH_TOKEN\");\n const api = github(token);\n const upstream = await api<GitHubRepository>(`repos/${repo}`);\n const canonicalRepo = upstream.full_name;\n const base = upstream.default_branch;\n const baseRef = await api<{ object: { sha: string } }>(\n `repos/${canonicalRepo}/git/ref/heads/${encodeURIComponent(base)}`\n );\n const baseSha = baseRef.object.sha;\n const schemaFile = await content(api, canonicalRepo, \"schemas/registry-module.schema.json\", baseSha);\n if (!schemaFile) throw new Error(\"\u7D22\u5F15\u4ED3\u7F3A\u5C11 registry-module.schema.json\");\n const ajv = new Ajv({ allErrors: true, strict: true });\n ajv.addFormat(\"semver-range\", (value: string) => !!value.trim() && semver.validRange(value) !== null);\n const validate = ajv.compile(decode(schemaFile) as AnySchema);\n entry.official = false; // \u9996\u6B21\u6536\u5F55\u6C38\u4E0D\u81EA\u884C\u58F0\u660E\u5B98\u65B9\u8EAB\u4EFD\u3002\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n if (!semver.valid(entry.version)) throw new Error(\"\u7248\u672C\u987B\u4E3A\u6709\u6548\u7684\u7CBE\u786E SemVer\");\n const file = `modules/${entry.id}.json`;\n options.log?.(`\u6821\u9A8C ${entry.npm}@${entry.version} \u4E0E\u6700\u65B0\u7D22\u5F15\u5206\u7247`);\n const tree = await api<{ truncated: boolean; tree: Array<{ path: string; type: string; sha: string }> }>(\n `repos/${canonicalRepo}/git/trees/${baseSha}?recursive=1`\n );\n if (tree.truncated) throw new Error(\"\u7D22\u5F15\u6811\u8FC7\u5927\uFF0C\u65E0\u6CD5\u5B8C\u6574\u68C0\u67E5\u4F9D\u8D56\");\n const shards = tree.tree.filter((item) => /^modules\\/[^/]+\\.json$/.test(item.path) && item.type === \"blob\");\n const modules: Record<string, RegistryModule> = Object.create(null) as Record<string, RegistryModule>;\n // \u53EA\u8BFB\u53D6\u8BE5\u6A21\u5757\u548C\u4F9D\u8D56\u95ED\u5305\uFF0C\u907F\u514D\u6BCF\u6B21\u63D0\u4EA4\u626B\u63CF\u6574\u4E2A\u7D22\u5F15\u5E76\u8017\u5C3D API \u914D\u989D\u3002\n const shardByPath = new Map(shards.map((item) => [item.path, item]));\n async function load(id: string): Promise<RegistryModule | null> {\n const shard = shardByPath.get(`modules/${id}.json`);\n if (!shard) return null;\n const blob = await api<{ encoding: string; content: string }>(`repos/${canonicalRepo}/git/blobs/${shard.sha}`);\n if (blob.encoding !== \"base64\") throw new Error(\"\u65E0\u6548\u7D22\u5F15 blob \u7F16\u7801\");\n const module = object(\n JSON.parse(Buffer.from(blob.content, \"base64\").toString(\"utf8\")),\n shard.path\n ) as unknown as RegistryModule;\n if (module.id !== id) throw new Error(`\u7D22\u5F15\u5206\u7247 ID \u4E0D\u4E00\u81F4\uFF1A${shard.path}`);\n return module;\n }\n const previous = await load(entry.id);\n if (previous) {\n if (previous.npm !== entry.npm || (previous.repo && sourceRepo(previous.repo) !== entry.repo))\n throw new Error(\"\u8BE5 ID \u5DF2\u5C5E\u4E8E\u5176\u4ED6 npm \u5305\u6216\u6E90\u7801\u4ED3\uFF1B\u8BF7\u7531\u7EF4\u62A4\u8005\u5904\u7406\u8FC1\u79FB\");\n if (!semver.valid(previous.version) || semver.lt(entry.version, previous.version))\n throw new Error(\"\u4E0D\u80FD\u964D\u4F4E\u5DF2\u6536\u5F55\u7248\u672C\");\n entry.official = previous.official; // \u4EC5\u7EE7\u627F\u7D22\u5F15\u4ED3\u5DF2\u5BA1\u6838\u8EAB\u4EFD\u3002\n // \u5355\u7EAF\u66F4\u65B0\u7248\u672C\u4FDD\u7559\u5DF2\u6574\u7406\u7684\u5C55\u793A\u4FE1\u606F\uFF1B\u4F5C\u8005\u914D\u7F6E\u53EF\u663E\u5F0F\u8986\u76D6\u3002\n if (local) {\n if (!local.overrides.has(\"name\")) entry.name = previous.name;\n if (!local.overrides.has(\"description\")) entry.description = previous.description;\n }\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (entry[key] === undefined && previous[key] !== undefined)\n Object.assign(entry, { [key]: structuredClone(previous[key]) });\n }\n }\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u8EAB\u4EFD\u6216\u5B57\u6BB5\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n modules[entry.id] = entry;\n const queue = [...entry.requires];\n const loaded = new Set([entry.id]);\n while (queue.length) {\n const batch = queue.splice(0, 4).filter((id) => {\n if (loaded.has(id)) return false;\n loaded.add(id);\n return true;\n });\n await Promise.all(\n batch.map(async (id) => {\n const dependency = await load(id);\n if (!dependency) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n if (!validate(dependency)) throw new Error(`\u4F9D\u8D56 ${id} \u7684\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4`);\n modules[id] = dependency;\n queue.push(...(dependency.requires ?? []));\n })\n );\n }\n const visited = new Set<string>();\n const visiting = new Set<string>();\n function visit(id: string): void {\n if (visiting.has(id)) throw new Error(`\u6A21\u5757\u4F9D\u8D56\u5B58\u5728\u5FAA\u73AF\uFF1A${id}`);\n if (visited.has(id)) return;\n const module = modules[id];\n if (!module) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n visiting.add(id);\n for (const dependency of module.requires ?? []) visit(dependency);\n visiting.delete(id);\n visited.add(id);\n }\n visit(entry.id);\n await checkPublished(entry, Boolean(options.waitForPublish));\n const result = { entry, previous, path: file, registryRepo: canonicalRepo };\n if (options.dryRun) return { ...result, status: \"preview\" };\n if (same(entry, previous)) return { ...result, status: \"unchanged\" };\n\n let headRepo = canonicalRepo;\n if (!options.noFork && upstream.permissions?.push !== true) {\n const user = await api<{ login: string }>(\"user\");\n const forkName = `${user.login}/${canonicalRepo.split(\"/\")[1]}`;\n let fork: GitHubRepository | undefined;\n try {\n fork = await api(`repos/${forkName}`);\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n }\n if (!fork)\n fork = await api<GitHubRepository>(`repos/${canonicalRepo}/forks`, \"POST\", { default_branch_only: true });\n if (fork.id === upstream.id) {\n // \u5019\u9009\u5730\u5740\u4E0E\u76EE\u6807\u5730\u5740\u53EF\u80FD\u56E0\u91CD\u5B9A\u5411\u6307\u5411\u540C\u4E00\u4ED3\u5E93\uFF0C\u6309\u5B9E\u9645\u6743\u9650\u5904\u7406\u3002\n if (fork.permissions?.push !== true)\n throw new Error(\n `${forkName} \u5DF2\u91CD\u5B9A\u5411\u5230 ${canonicalRepo}\uFF0C\u5F53\u524D\u51ED\u636E\u6CA1\u6709\u5199\u6743\u9650\uFF1B\u8BF7\u68C0\u67E5 GitHub \u767B\u5F55\u4E0E Contents \u6743\u9650\u3002`\n );\n } else {\n const networkId = upstream.source?.id ?? upstream.id;\n if (!fork.fork || (fork.parent?.id !== upstream.id && fork.source?.id !== networkId))\n throw new Error(\n `${fork.full_name} \u672A\u4E0E\u76EE\u6807\u7D22\u5F15\u4ED3\u5173\u8054\uFF0C\u65E0\u6CD5\u4F5C\u4E3A\u8BE5 PR \u7684\u6765\u6E90\uFF1B\u8BF7\u4F7F\u7528\u76EE\u6807\u4ED3\u7684 fork\uFF0C\u6216\u6709\u5199\u6743\u9650\u65F6\u4F7F\u7528 --no-fork\u3002`\n );\n headRepo = fork.full_name;\n }\n }\n type Pull = { number: number; html_url: string; head: { ref: string; repo: { full_name: string } | null } };\n let pull: Pull | undefined;\n const prefix = `sfmc-submit/${entry.id}/`;\n for (let page = 1; ; page++) {\n const pagePulls = await api<Pull[]>(\n `repos/${canonicalRepo}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100&page=${page}`\n );\n const matches = pagePulls.filter(\n (item) => item.head.ref.startsWith(prefix) && item.head.repo?.full_name.toLowerCase() === headRepo.toLowerCase()\n );\n if (matches.length > 1 || (pull && matches.length)) throw new Error(\"\u8BE5\u6A21\u5757\u6709\u591A\u4E2A\u63D0\u4EA4 PR\uFF0C\u8BF7\u5148\u5408\u5E76\u6216\u5173\u95ED\u591A\u4F59 PR\");\n pull ??= matches[0];\n if (pagePulls.length < 100) break;\n }\n // \u5DF2\u5408\u5E76\u7684\u5206\u652F\u65E0\u9700\u91CD\u7F6E\uFF1B\u65B0\u4E00\u8F6E\u63D0\u4EA4\u4EE5\u6700\u65B0 main \u7684 SHA \u6807\u8BC6\u3002\n const branch = pull?.head.ref ?? `${prefix}${baseSha.slice(0, 12)}`;\n const head = `${headRepo.split(\"/\")[0]}:${branch}`;\n let branchRef: { object: { sha: string } } | null = null;\n // \u65B0 fork \u7684\u521B\u5EFA\u662F\u5F02\u6B65\u64CD\u4F5C\uFF0C\u6700\u591A\u7B49\u5F85 15 \u79D2\u3002\n for (let attempt = 0; attempt < 6; attempt++) {\n try {\n branchRef = await api(`repos/${headRepo}/git/ref/heads/${encodeURIComponent(branch)}`);\n break;\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n try {\n branchRef = await api(`repos/${headRepo}/git/refs`, \"POST\", { ref: `refs/heads/${branch}`, sha: baseSha });\n break;\n } catch (createError) {\n if (!(createError instanceof GitHubError && [404, 422].includes(createError.status)) || attempt === 5)\n throw createError;\n await new Promise((resolve) => setTimeout(resolve, 3000));\n }\n }\n }\n if (!branchRef) throw new Error(\"\u63D0\u4EA4\u5206\u652F\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5\");\n const comparison = await api<{ files: Array<{ filename: string }> }>(\n `repos/${canonicalRepo}/compare/${baseSha}...${encodeURIComponent(`${headRepo.split(\"/\")[0]}:${branchRef.object.sha}`)}`\n );\n if (comparison.files.some((item) => item.filename !== file))\n throw new Error(\"\u4E13\u7528\u63D0\u4EA4\u5206\u652F\u5305\u542B\u5176\u4ED6\u6587\u4EF6\u6539\u52A8\uFF0C\u8BF7\u5148\u7531\u4F5C\u8005\u5904\u7406\");\n const oldFile = await content(api, headRepo, file, branchRef.object.sha);\n const oldEntry = oldFile ? decode(oldFile) : null;\n if (oldEntry) {\n const pending = object(oldEntry, file);\n if (\n pending.npm !== entry.npm ||\n (pending.repo && sourceRepo(pending.repo) !== entry.repo) ||\n typeof pending.version !== \"string\" ||\n !semver.valid(pending.version) ||\n semver.lt(entry.version, pending.version)\n ) {\n throw new Error(\"\u5DF2\u6709\u63D0\u4EA4\u7684\u6765\u6E90\u6216\u7248\u672C\u51B2\u7A81\uFF1B\u62D2\u7EDD\u8986\u76D6\");\n }\n }\n if (!same(entry, oldEntry)) {\n await api(`repos/${headRepo}/contents/${file}`, \"PUT\", {\n message: `chore(registry): ${entry.id} ${entry.version}`,\n content: Buffer.from(`${JSON.stringify(entry, null, 2)}\\n`).toString(\"base64\"),\n branch,\n ...(oldFile ? { sha: oldFile.sha } : {}),\n });\n }\n const title = `\u6536\u5F55 ${entry.id}@${entry.version}`;\n const body = `\u66F4\u65B0 \\`${file}\\`\u3002\\n\\n- npm\uFF1A\\`${entry.npm}@${entry.version}\\`\uFF08\u516C\u5171\u6E90\u7CBE\u786E\u7248\u672C\u5DF2\u6838\u5BF9\uFF09\\n- \u6E90\u7801\uFF1A${entry.repo ?? \"\u672A\u63D0\u4F9B\"}\\n- \u8BB8\u53EF\u8BC1\uFF1A\\`${entry.license}\\`\\n- SDK\uFF1A\\`${entry.sdk}\\`\\n- \u4F9D\u8D56\uFF1A${entry.requires.join(\", \") || \"\u65E0\"}\\n\\n\u5DF2\u68C0\u67E5\u5F53\u524D\u7D22\u5F15 Schema\u3001ID \u6765\u6E90\u3001\u7248\u672C\u4E0E\u4F9D\u8D56\u5173\u7CFB\u3002\u5B98\u65B9\u8EAB\u4EFD\u6CBF\u7528\u7EF4\u62A4\u8005\u5BA1\u6838\u7ED3\u679C\uFF1B\u8BF7\u68C0\u67E5 PR \u95E8\u7981\u540E\u5408\u5E76\u3002`;\n if (pull) {\n if (same(entry, oldEntry)) return { ...result, status: \"unchanged\", prUrl: pull.html_url };\n await api(`repos/${canonicalRepo}/pulls/${pull.number}`, \"PATCH\", { title, body });\n return { ...result, status: \"updated\", prUrl: pull.html_url };\n }\n const created = await api<{ html_url: string }>(`repos/${canonicalRepo}/pulls`, \"POST\", { title, body, base, head });\n return { ...result, status: \"created\", prUrl: created.html_url };\n}\n", "/**\n * \u76D1\u542C\u6A21\u5757 sapi/src\uFF0C\u9632\u6296\u540E\u56DE\u8C03 onRebuild\uFF08\u7531\u8C03\u7528\u65B9\u6CE8\u5165 rebuildAndDeploy / \u5176\u5B83\uFF09\u3002\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface ModuleWatchOptions {\n moduleRoot: string;\n debounceMs?: number;\n log?: (line: string) => void;\n onRebuild: () => Promise<{ ok: boolean; message?: string }>;\n}\n\nexport function startModuleWatch(opts: ModuleWatchOptions): { stop: () => void } {\n const log = opts.log ?? ((line: string) => console.log(line));\n const debounceMs = opts.debounceMs ?? 200;\n const sapiDir = path.join(opts.moduleRoot, \"sapi\");\n const srcDir = path.join(sapiDir, \"src\");\n\n if (!fs.existsSync(sapiDir)) {\n log(`[devkit:watch] \u65E0 sapi \u76EE\u5F55: ${sapiDir}`);\n return { stop: () => {} };\n }\n\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let pending = new Set<string>();\n let running = false;\n let stopped = false;\n\n log(`[devkit:watch] \u76D1\u542C ${opts.moduleRoot}`);\n\n const runOnce = async () => {\n if (running || stopped) return;\n running = true;\n const changed = [...pending];\n pending = new Set();\n const t0 = Date.now();\n log(`[devkit:watch] rebuild (${changed.length})\u2026`);\n try {\n const r = await opts.onRebuild();\n const ms = Date.now() - t0;\n if (r.ok) log(`[devkit:watch] ok ${ms}ms`);\n else log(`[devkit:watch] fail ${ms}ms ${r.message ?? \"\"}`);\n } catch (e) {\n log(`[devkit:watch] error ${(e as Error).message}`);\n } finally {\n running = false;\n }\n };\n\n const onSrc = (rel: string) => {\n if (stopped) return;\n if (rel.includes(\"node_modules\") || rel.includes(\"dist\") || rel.endsWith(\".tgz\")) return;\n pending.add(rel);\n if (debounceTimer) clearTimeout(debounceTimer);\n debounceTimer = setTimeout(() => void runOnce(), debounceMs);\n };\n\n const watchers: fs.FSWatcher[] = [];\n if (fs.existsSync(srcDir)) {\n try {\n watchers.push(\n fs.watch(srcDir, { recursive: true, persistent: true }, (_e, filename) => {\n if (filename) onSrc(filename.toString());\n })\n );\n } catch {\n watchers.push(\n fs.watch(srcDir, { persistent: true }, (_e, filename) => {\n if (filename) onSrc(filename.toString());\n })\n );\n }\n }\n\n const watchMeta = (file: string, kind: string) => {\n if (!fs.existsSync(file)) return;\n watchers.push(\n fs.watch(file, { persistent: true }, (event) => {\n if (event === \"change\") log(`[devkit:watch] ${kind} \u5DF2\u6539\uFF0C\u9700\u91CD\u542F BDS\uFF08SAPI \u542F\u52A8\u671F\u7F13\u5B58\uFF09`);\n })\n );\n };\n watchMeta(path.join(sapiDir, \"manifest.json\"), \"manifest\");\n watchMeta(path.join(sapiDir, \"tsconfig.json\"), \"tsconfig\");\n\n return {\n stop() {\n stopped = true;\n if (debounceTimer) clearTimeout(debounceTimer);\n for (const w of watchers) {\n try {\n w.close();\n } catch {\n /* ignore */\n }\n }\n log(\"[devkit:watch] stopped\");\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["fs", "path", "fs", "path", "fs", "path", "path", "fs", "path", "fs", "path", "a", "b", "path", "fs", "fs", "path"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/registry-command.ts", "../src/registry-submit.ts", "../src/registry-cli.ts"],
4
- "sourcesContent": ["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { submitModuleToRegistry, type RegistryModule, type RegistrySubmitOptions } from \"./registry-submit.js\";\n\n/** CLI \u4E0E CI \u5171\u7528\u53C2\u6570\u89E3\u6790\uFF0C\u672A\u77E5\u53C2\u6570\u8FD4\u56DE\u5931\u8D25\uFF0C\u907F\u514D\u8BEF\u63D0\u4EA4\u3002 */\nexport async function runRegistrySubmitCommand(args: string[]): Promise<string> {\n const options: RegistrySubmitOptions = {};\n let entryFile: string | undefined;\n const help =\n \"sfmc mod submit [\u6A21\u5757\u76EE\u5F55] [--dry-run] [--no-fork] [--wait-for-publish] [--registry owner/repo]\\nCI\uFF1Asfmc-module-submit --entry-file <JSON>\uFF08\u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\uFF09\";\n if (args.includes(\"--help\") || args.includes(\"-h\")) return help;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--dry-run\") options.dryRun = true;\n else if (arg === \"--no-fork\") options.noFork = true;\n else if (arg === \"--wait-for-publish\") options.waitForPublish = true;\n else if (arg === \"--registry\" || arg === \"--entry-file\") {\n const value = args[++i];\n if (!value || value.startsWith(\"-\")) throw new Error(`\u7F3A\u5C11 ${arg} \u7684\u503C`);\n if (arg === \"--registry\") options.registryRepo = value;\n else entryFile = value;\n } else if (arg.startsWith(\"-\") || options.moduleRoot) throw new Error(`\u672A\u77E5\u6216\u91CD\u590D\u53C2\u6570\uFF1A${arg}\\n${help}`);\n else options.moduleRoot = path.resolve(arg);\n }\n if (entryFile) {\n if (options.moduleRoot) throw new Error(\"--entry-file \u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\");\n options.entry = JSON.parse(await fs.readFile(path.resolve(entryFile), \"utf8\")) as RegistryModule;\n }\n const result = await submitModuleToRegistry(options);\n if (result.status === \"preview\")\n return `\u9884\u89C8\uFF1A${result.registryRepo}/${result.path}\\n\u539F\u6761\u76EE\uFF1A\\n${JSON.stringify(result.previous, null, 2)}\\n\u62DF\u63D0\u4EA4\uFF1A\\n${JSON.stringify(result.entry, null, 2)}\\n\u6821\u9A8C\u901A\u8FC7\uFF0C\u672A\u5199\u5165\u8FDC\u7AEF\u3002`;\n return `${{ unchanged: \"\u5185\u5BB9\u76F8\u540C\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\", created: \"\u5DF2\u521B\u5EFA\u7D22\u5F15 PR\", updated: \"\u5DF2\u66F4\u65B0\u7D22\u5F15 PR\" }[result.status]}${result.prUrl ? `\uFF1A${result.prUrl}` : \"\"}`;\n}\n", "/** \u6A21\u5757\u7D22\u5F15\u63D0\u4EA4\u6838\u5FC3\u3002\u4EC5\u5199\u5165\u4E13\u7528\u5206\u652F\u4E2D\u7684\u5355\u4E2A\u5206\u7247\uFF0C\u4E0D\u64CD\u4F5C\u4F5C\u8005\u5DE5\u4F5C\u6811\u3002 */\nimport { Ajv, type AnySchema } from \"ajv\";\nimport { execFile } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport semver from \"semver\";\n\nexport const MODULE_REGISTRY_REPO = \"DogeLakeDev/sfmc-modules\";\ntype Json = Record<string, unknown>;\nexport interface RegistryMetadata {\n name?: string;\n description?: string;\n category?: \"gameplay\" | \"utility\" | \"system\" | \"economy\" | \"social\";\n tags?: string[];\n authors?: string[];\n}\nexport interface RegistryModule extends RegistryMetadata {\n id: string;\n name: string;\n description: string;\n npm: string;\n version: string;\n sdk: string;\n license: string;\n official: boolean;\n repo?: string;\n requires: string[];\n}\nexport interface RegistrySubmitOptions {\n moduleRoot?: string;\n /** \u8868\u5355\u7B49\u5165\u53E3\u63D0\u4F9B\u539F\u59CB\u5B57\u6BB5\uFF0C\u4ECD\u987B\u7ECF\u8FC7\u76F8\u540C npm\u3001Schema \u548C\u7D22\u5F15\u6821\u9A8C\u3002 */\n entry?: RegistryModule;\n registryRepo?: string;\n dryRun?: boolean;\n /** \u7EF4\u62A4\u8005 / GitHub App \u5728\u7D22\u5F15\u4ED3\u5EFA\u5206\u652F\uFF0C\u987B\u6709 Contents \u548C Pull requests \u5199\u6743\u9650\u3002 */\n noFork?: boolean;\n token?: string;\n /** \u7B49\u5F85\u521A\u53D1\u5E03\u7684\u7CBE\u786E\u7248\u672C\u53EF\u89C1\uFF1B\u4EC5\u91CD\u8BD5 404\uFF0C\u6700\u957F 60 \u79D2\u3002 */\n waitForPublish?: boolean;\n log?: (message: string) => void;\n}\nexport interface RegistrySubmitResult {\n status: \"preview\" | \"unchanged\" | \"created\" | \"updated\";\n entry: RegistryModule;\n previous: RegistryModule | null;\n path: string;\n prUrl?: string;\n registryRepo: string;\n}\nfunction object(value: unknown, label: string): Json {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} \u987B\u4E3A JSON \u5BF9\u8C61`);\n return value as Json;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`\u7F3A\u5C11 ${label}`);\n return value.trim();\n}\nfunction sourceRepo(value: unknown): string | undefined {\n if (value === undefined) return undefined;\n const raw = typeof value === \"string\" ? value : object(value, \"repository\").url;\n const repo = text(raw, \"repository.url\")\n .replace(/^git\\+/, \"\")\n .replace(/\\.git$/, \"\");\n const url = new URL(repo);\n if (url.protocol !== \"https:\" || url.username || url.password)\n throw new Error(\"repository \u987B\u4E3A\u4E0D\u542B\u51ED\u636E\u7684 HTTPS \u5730\u5740\");\n return url.href.replace(/\\/$/, \"\");\n}\n\n/** \u4F5C\u8005\u914D\u7F6E\u53EA\u8865\u5145\u5C55\u793A\u5B57\u6BB5\uFF1B\u5305\u3001\u7248\u672C\u3001SDK \u548C\u4F9D\u8D56\u6765\u81EA\u5DF2\u6709\u5951\u7EA6\u3002 */\nexport function createRegistryEntry(\n pkgValue: unknown,\n manifestValue: unknown,\n metadataValue: unknown = {}\n): RegistryModule {\n const pkg = object(pkgValue, \"package.json\");\n const manifest = object(manifestValue, \"sapi/manifest.json\");\n const metadata = object(metadataValue, \"sfmc.registry.json\");\n const allowed = new Set([\"$schema\", \"name\", \"description\", \"category\", \"tags\", \"authors\"]);\n for (const key of Object.keys(metadata))\n if (!allowed.has(key)) throw new Error(`sfmc.registry.json \u4E0D\u652F\u6301\u5B57\u6BB5 ${key}`);\n if (pkg.private === true) throw new Error(\"private \u6A21\u5757\u4E0D\u80FD\u63D0\u4EA4\u516C\u5171\u7D22\u5F15\");\n if (manifest.schemaVersion !== 2) throw new Error(\"\u9700\u8981 schemaVersion=2 \u7684\u6A21\u5757\u6E05\u5355\");\n const peers = object(pkg.peerDependencies ?? {}, \"peerDependencies\");\n const entry: RegistryModule = {\n id: text(manifest.id, \"manifest.id\"),\n name: text(metadata.name ?? manifest.name, \"\u5C55\u793A\u540D\u79F0\uFF08name\uFF09\"),\n description: text(metadata.description ?? pkg.description, \"\u529F\u80FD\u4ECB\u7ECD\uFF08description\uFF09\"),\n npm: text(pkg.name, \"package.name\"),\n version: text(pkg.version, \"package.version\"),\n sdk: text(peers[\"@sfmc-bds/sdk\"], \"peerDependencies.@sfmc-bds/sdk\"),\n license: text(pkg.license, \"package.license\"),\n official: false,\n requires: (manifest.requires ?? []) as string[],\n };\n const repo = sourceRepo(pkg.repository);\n if (repo) entry.repo = repo;\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (metadata[key] !== undefined) Object.assign(entry, { [key]: metadata[key] });\n }\n return entry;\n}\n\nasync function readLocalEntry(root: string): Promise<{ entry: RegistryModule; overrides: Set<string> }> {\n const realRoot = await fs.realpath(root);\n const read = async (file: string) => {\n const target = await fs.realpath(path.join(realRoot, file));\n const relative = path.relative(realRoot, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))\n throw new Error(`${file} \u987B\u4F4D\u4E8E\u6A21\u5757\u76EE\u5F55\u5185`);\n const raw = await fs.readFile(target, \"utf8\");\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new Error(`${file} \u5305\u542B\u65E0\u6548 JSON`);\n }\n };\n let metadata: unknown = {};\n try {\n metadata = await read(\"sfmc.registry.json\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n return {\n entry: createRegistryEntry(await read(\"package.json\"), await read(\"sapi/manifest.json\"), metadata),\n overrides: new Set(Object.keys(object(metadata, \"sfmc.registry.json\"))),\n };\n}\n\nclass GitHubError extends Error {\n constructor(\n public status: number,\n endpoint: string,\n rateLimited = false\n ) {\n super(\n `GitHub ${status}: ${endpoint}${rateLimited ? \"\uFF08API \u914D\u989D\u5DF2\u7528\u5C3D\uFF0C\u8BF7\u767B\u5F55\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u914D\u989D\u6062\u590D\uFF09\" : status === 401 || status === 403 ? \"\uFF08\u68C0\u67E5\u767B\u5F55\u53CA Contents / Pull requests \u6743\u9650\uFF09\" : \"\"}`\n );\n }\n}\nasync function resolveToken(required: boolean): Promise<string | undefined> {\n const configured = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n if (configured) return configured;\n try {\n const { stdout } = await promisify(execFile)(\"gh\", [\"auth\", \"token\", \"--hostname\", \"github.com\"], {\n timeout: 10000,\n windowsHide: true,\n });\n return stdout.trim() || undefined;\n } catch {\n if (required) throw new Error(\"\u63D0\u4EA4\u9700\u8981 GitHub \u767B\u5F55\uFF1A\u6267\u884C gh auth login\uFF0C\u6216\u8BBE\u7F6E GH_TOKEN\u3002\");\n return undefined;\n }\n}\nfunction github(token?: string) {\n return async function api<T>(endpoint: string, method = \"GET\", body?: unknown): Promise<T> {\n const response = await fetch(`https://api.github.com/${endpoint}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"sfmc-devkit\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(15000),\n });\n // \u4E0D\u56DE\u663E\u670D\u52A1\u5668\u6B63\u6587\u6216\u8BA4\u8BC1\u4FE1\u606F\u3002\n if (!response.ok)\n throw new GitHubError(\n response.status,\n endpoint,\n response.status === 429 || response.headers.get(\"x-ratelimit-remaining\") === \"0\"\n );\n return response.status === 204 ? (undefined as T) : ((await response.json()) as T);\n };\n}\ntype Api = ReturnType<typeof github>;\ninterface GitHubRepository {\n id: number;\n full_name: string;\n default_branch: string;\n fork: boolean;\n permissions?: { push?: boolean };\n parent?: { id: number; full_name: string };\n source?: { id: number; full_name: string };\n}\ninterface Content {\n type: string;\n encoding: string;\n content: string;\n sha: string;\n}\nfunction decode(file: Content): unknown {\n if (file.type !== \"file\" || file.encoding !== \"base64\") throw new Error(\"\u7D22\u5F15\u5185\u5BB9\u987B\u4E3A\u666E\u901A JSON \u6587\u4EF6\");\n return JSON.parse(Buffer.from(file.content, \"base64\").toString(\"utf8\"));\n}\nasync function content(api: Api, repo: string, file: string, ref: string): Promise<Content | null> {\n try {\n return await api<Content>(`repos/${repo}/contents/${file}?ref=${encodeURIComponent(ref)}`);\n } catch (error) {\n if (error instanceof GitHubError && error.status === 404) return null;\n throw error;\n }\n}\nfunction same(a: unknown, b: unknown): boolean {\n const stable = (value: unknown): unknown =>\n Array.isArray(value)\n ? value.map(stable)\n : value && typeof value === \"object\"\n ? Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => [key, stable(item)])\n )\n : value;\n return JSON.stringify(stable(a)) === JSON.stringify(stable(b));\n}\nasync function checkPublished(entry: RegistryModule, wait: boolean): Promise<void> {\n const deadline = Date.now() + (wait ? 60000 : 0);\n while (true) {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(entry.npm)}/${encodeURIComponent(entry.version)}`,\n {\n signal: AbortSignal.timeout(15000),\n headers: { Accept: \"application/json\" },\n }\n );\n if (response.status === 404 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 3000));\n continue;\n }\n if (!response.ok)\n throw new Error(\n `\u516C\u5171 npm \u5C1A\u65E0\u53EF\u7528\u7684 ${entry.npm}@${entry.version}\uFF08HTTP ${response.status}\uFF09\uFF1B\u5148\u53D1\u5E03\u8BE5\u7CBE\u786E\u7248\u672C\u3002`\n );\n const pkg = object(await response.json(), \"npm \u5143\u6570\u636E\");\n const peers = object(pkg.peerDependencies ?? {}, \"npm peerDependencies\");\n if (\n pkg.name !== entry.npm ||\n pkg.version !== entry.version ||\n pkg.license !== entry.license ||\n peers[\"@sfmc-bds/sdk\"] !== entry.sdk\n ) {\n throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u540D\u79F0\u3001\u7248\u672C\u3001\u8BB8\u53EF\u8BC1\u6216 SDK \u517C\u5BB9\u8303\u56F4\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n }\n if (sourceRepo(pkg.repository) !== entry.repo) throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u6E90\u7801\u5730\u5740\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n return;\n }\n}\n\n/** \u6240\u6709\u5165\u53E3\u5171\u7528\uFF1A\u9884\u89C8\u4E5F\u9A8C\u8BC1\u5DF2\u53D1\u5E03\u7248\u672C\u4E0E\u6700\u65B0\u5206\u7247\uFF1B\u9884\u89C8\u9636\u6BB5\u4E0D\u4EA7\u751F\u8FDC\u7AEF\u5199\u5165\u3002 */\nexport async function submitModuleToRegistry(options: RegistrySubmitOptions = {}): Promise<RegistrySubmitResult> {\n const repo = options.registryRepo ?? MODULE_REGISTRY_REPO;\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) throw new Error(\"registryRepo \u987B\u4E3A owner/repo\");\n const local = options.entry ? null : await readLocalEntry(path.resolve(options.moduleRoot ?? process.cwd()));\n const entry = options.entry ? structuredClone(options.entry) : local!.entry;\n entry.requires ??= [];\n const token = options.token ?? (await resolveToken(!options.dryRun));\n if (!options.dryRun && !token) throw new Error(\"\u63D0\u4EA4\u9700\u8981\u6709\u6548\u7684 GitHub \u767B\u5F55\u6216 GH_TOKEN\");\n const api = github(token);\n const upstream = await api<GitHubRepository>(`repos/${repo}`);\n const canonicalRepo = upstream.full_name;\n const base = upstream.default_branch;\n const baseRef = await api<{ object: { sha: string } }>(\n `repos/${canonicalRepo}/git/ref/heads/${encodeURIComponent(base)}`\n );\n const baseSha = baseRef.object.sha;\n const schemaFile = await content(api, canonicalRepo, \"schemas/registry-module.schema.json\", baseSha);\n if (!schemaFile) throw new Error(\"\u7D22\u5F15\u4ED3\u7F3A\u5C11 registry-module.schema.json\");\n const ajv = new Ajv({ allErrors: true, strict: true });\n ajv.addFormat(\"semver-range\", (value: string) => !!value.trim() && semver.validRange(value) !== null);\n const validate = ajv.compile(decode(schemaFile) as AnySchema);\n entry.official = false; // \u9996\u6B21\u6536\u5F55\u6C38\u4E0D\u81EA\u884C\u58F0\u660E\u5B98\u65B9\u8EAB\u4EFD\u3002\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n if (!semver.valid(entry.version)) throw new Error(\"\u7248\u672C\u987B\u4E3A\u6709\u6548\u7684\u7CBE\u786E SemVer\");\n const file = `modules/${entry.id}.json`;\n options.log?.(`\u6821\u9A8C ${entry.npm}@${entry.version} \u4E0E\u6700\u65B0\u7D22\u5F15\u5206\u7247`);\n const tree = await api<{ truncated: boolean; tree: Array<{ path: string; type: string; sha: string }> }>(\n `repos/${canonicalRepo}/git/trees/${baseSha}?recursive=1`\n );\n if (tree.truncated) throw new Error(\"\u7D22\u5F15\u6811\u8FC7\u5927\uFF0C\u65E0\u6CD5\u5B8C\u6574\u68C0\u67E5\u4F9D\u8D56\");\n const shards = tree.tree.filter((item) => /^modules\\/[^/]+\\.json$/.test(item.path) && item.type === \"blob\");\n const modules: Record<string, RegistryModule> = Object.create(null) as Record<string, RegistryModule>;\n // \u53EA\u8BFB\u53D6\u8BE5\u6A21\u5757\u548C\u4F9D\u8D56\u95ED\u5305\uFF0C\u907F\u514D\u6BCF\u6B21\u63D0\u4EA4\u626B\u63CF\u6574\u4E2A\u7D22\u5F15\u5E76\u8017\u5C3D API \u914D\u989D\u3002\n const shardByPath = new Map(shards.map((item) => [item.path, item]));\n async function load(id: string): Promise<RegistryModule | null> {\n const shard = shardByPath.get(`modules/${id}.json`);\n if (!shard) return null;\n const blob = await api<{ encoding: string; content: string }>(`repos/${canonicalRepo}/git/blobs/${shard.sha}`);\n if (blob.encoding !== \"base64\") throw new Error(\"\u65E0\u6548\u7D22\u5F15 blob \u7F16\u7801\");\n const module = object(\n JSON.parse(Buffer.from(blob.content, \"base64\").toString(\"utf8\")),\n shard.path\n ) as unknown as RegistryModule;\n if (module.id !== id) throw new Error(`\u7D22\u5F15\u5206\u7247 ID \u4E0D\u4E00\u81F4\uFF1A${shard.path}`);\n return module;\n }\n const previous = await load(entry.id);\n if (previous) {\n if (previous.npm !== entry.npm || (previous.repo && sourceRepo(previous.repo) !== entry.repo))\n throw new Error(\"\u8BE5 ID \u5DF2\u5C5E\u4E8E\u5176\u4ED6 npm \u5305\u6216\u6E90\u7801\u4ED3\uFF1B\u8BF7\u7531\u7EF4\u62A4\u8005\u5904\u7406\u8FC1\u79FB\");\n if (!semver.valid(previous.version) || semver.lt(entry.version, previous.version))\n throw new Error(\"\u4E0D\u80FD\u964D\u4F4E\u5DF2\u6536\u5F55\u7248\u672C\");\n entry.official = previous.official; // \u4EC5\u7EE7\u627F\u7D22\u5F15\u4ED3\u5DF2\u5BA1\u6838\u8EAB\u4EFD\u3002\n // \u5355\u7EAF\u66F4\u65B0\u7248\u672C\u4FDD\u7559\u5DF2\u6574\u7406\u7684\u5C55\u793A\u4FE1\u606F\uFF1B\u4F5C\u8005\u914D\u7F6E\u53EF\u663E\u5F0F\u8986\u76D6\u3002\n if (local) {\n if (!local.overrides.has(\"name\")) entry.name = previous.name;\n if (!local.overrides.has(\"description\")) entry.description = previous.description;\n }\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (entry[key] === undefined && previous[key] !== undefined)\n Object.assign(entry, { [key]: structuredClone(previous[key]) });\n }\n }\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u8EAB\u4EFD\u6216\u5B57\u6BB5\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n modules[entry.id] = entry;\n const queue = [...entry.requires];\n const loaded = new Set([entry.id]);\n while (queue.length) {\n const batch = queue.splice(0, 4).filter((id) => {\n if (loaded.has(id)) return false;\n loaded.add(id);\n return true;\n });\n await Promise.all(\n batch.map(async (id) => {\n const dependency = await load(id);\n if (!dependency) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n if (!validate(dependency)) throw new Error(`\u4F9D\u8D56 ${id} \u7684\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4`);\n modules[id] = dependency;\n queue.push(...(dependency.requires ?? []));\n })\n );\n }\n const visited = new Set<string>();\n const visiting = new Set<string>();\n function visit(id: string): void {\n if (visiting.has(id)) throw new Error(`\u6A21\u5757\u4F9D\u8D56\u5B58\u5728\u5FAA\u73AF\uFF1A${id}`);\n if (visited.has(id)) return;\n const module = modules[id];\n if (!module) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n visiting.add(id);\n for (const dependency of module.requires ?? []) visit(dependency);\n visiting.delete(id);\n visited.add(id);\n }\n visit(entry.id);\n await checkPublished(entry, Boolean(options.waitForPublish));\n const result = { entry, previous, path: file, registryRepo: canonicalRepo };\n if (options.dryRun) return { ...result, status: \"preview\" };\n if (same(entry, previous)) return { ...result, status: \"unchanged\" };\n\n let headRepo = canonicalRepo;\n if (!options.noFork && upstream.permissions?.push !== true) {\n const user = await api<{ login: string }>(\"user\");\n const forkName = `${user.login}/${canonicalRepo.split(\"/\")[1]}`;\n let fork: GitHubRepository | undefined;\n try {\n fork = await api(`repos/${forkName}`);\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n }\n if (!fork)\n fork = await api<GitHubRepository>(`repos/${canonicalRepo}/forks`, \"POST\", { default_branch_only: true });\n if (fork.id === upstream.id) {\n // \u5019\u9009\u5730\u5740\u4E0E\u76EE\u6807\u5730\u5740\u53EF\u80FD\u56E0\u91CD\u5B9A\u5411\u6307\u5411\u540C\u4E00\u4ED3\u5E93\uFF0C\u6309\u5B9E\u9645\u6743\u9650\u5904\u7406\u3002\n if (fork.permissions?.push !== true)\n throw new Error(\n `${forkName} \u5DF2\u91CD\u5B9A\u5411\u5230 ${canonicalRepo}\uFF0C\u5F53\u524D\u51ED\u636E\u6CA1\u6709\u5199\u6743\u9650\uFF1B\u8BF7\u68C0\u67E5 GitHub \u767B\u5F55\u4E0E Contents \u6743\u9650\u3002`\n );\n } else {\n const networkId = upstream.source?.id ?? upstream.id;\n if (!fork.fork || (fork.parent?.id !== upstream.id && fork.source?.id !== networkId))\n throw new Error(\n `${fork.full_name} \u672A\u4E0E\u76EE\u6807\u7D22\u5F15\u4ED3\u5173\u8054\uFF0C\u65E0\u6CD5\u4F5C\u4E3A\u8BE5 PR \u7684\u6765\u6E90\uFF1B\u8BF7\u4F7F\u7528\u76EE\u6807\u4ED3\u7684 fork\uFF0C\u6216\u6709\u5199\u6743\u9650\u65F6\u4F7F\u7528 --no-fork\u3002`\n );\n headRepo = fork.full_name;\n }\n }\n type Pull = { number: number; html_url: string; head: { ref: string; repo: { full_name: string } | null } };\n let pull: Pull | undefined;\n const prefix = `sfmc-submit/${entry.id}/`;\n for (let page = 1; ; page++) {\n const pagePulls = await api<Pull[]>(\n `repos/${canonicalRepo}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100&page=${page}`\n );\n const matches = pagePulls.filter(\n (item) => item.head.ref.startsWith(prefix) && item.head.repo?.full_name.toLowerCase() === headRepo.toLowerCase()\n );\n if (matches.length > 1 || (pull && matches.length)) throw new Error(\"\u8BE5\u6A21\u5757\u6709\u591A\u4E2A\u63D0\u4EA4 PR\uFF0C\u8BF7\u5148\u5408\u5E76\u6216\u5173\u95ED\u591A\u4F59 PR\");\n pull ??= matches[0];\n if (pagePulls.length < 100) break;\n }\n // \u5DF2\u5408\u5E76\u7684\u5206\u652F\u65E0\u9700\u91CD\u7F6E\uFF1B\u65B0\u4E00\u8F6E\u63D0\u4EA4\u4EE5\u6700\u65B0 main \u7684 SHA \u6807\u8BC6\u3002\n const branch = pull?.head.ref ?? `${prefix}${baseSha.slice(0, 12)}`;\n const head = `${headRepo.split(\"/\")[0]}:${branch}`;\n let branchRef: { object: { sha: string } } | null = null;\n // \u65B0 fork \u7684\u521B\u5EFA\u662F\u5F02\u6B65\u64CD\u4F5C\uFF0C\u6700\u591A\u7B49\u5F85 15 \u79D2\u3002\n for (let attempt = 0; attempt < 6; attempt++) {\n try {\n branchRef = await api(`repos/${headRepo}/git/ref/heads/${encodeURIComponent(branch)}`);\n break;\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n try {\n branchRef = await api(`repos/${headRepo}/git/refs`, \"POST\", { ref: `refs/heads/${branch}`, sha: baseSha });\n break;\n } catch (createError) {\n if (!(createError instanceof GitHubError && [404, 422].includes(createError.status)) || attempt === 5)\n throw createError;\n await new Promise((resolve) => setTimeout(resolve, 3000));\n }\n }\n }\n if (!branchRef) throw new Error(\"\u63D0\u4EA4\u5206\u652F\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5\");\n const comparison = await api<{ files: Array<{ filename: string }> }>(\n `repos/${canonicalRepo}/compare/${baseSha}...${encodeURIComponent(`${headRepo.split(\"/\")[0]}:${branchRef.object.sha}`)}`\n );\n if (comparison.files.some((item) => item.filename !== file))\n throw new Error(\"\u4E13\u7528\u63D0\u4EA4\u5206\u652F\u5305\u542B\u5176\u4ED6\u6587\u4EF6\u6539\u52A8\uFF0C\u8BF7\u5148\u7531\u4F5C\u8005\u5904\u7406\");\n const oldFile = await content(api, headRepo, file, branchRef.object.sha);\n const oldEntry = oldFile ? decode(oldFile) : null;\n if (oldEntry) {\n const pending = object(oldEntry, file);\n if (\n pending.npm !== entry.npm ||\n (pending.repo && sourceRepo(pending.repo) !== entry.repo) ||\n typeof pending.version !== \"string\" ||\n !semver.valid(pending.version) ||\n semver.lt(entry.version, pending.version)\n ) {\n throw new Error(\"\u5DF2\u6709\u63D0\u4EA4\u7684\u6765\u6E90\u6216\u7248\u672C\u51B2\u7A81\uFF1B\u62D2\u7EDD\u8986\u76D6\");\n }\n }\n if (!same(entry, oldEntry)) {\n await api(`repos/${headRepo}/contents/${file}`, \"PUT\", {\n message: `chore(registry): ${entry.id} ${entry.version}`,\n content: Buffer.from(`${JSON.stringify(entry, null, 2)}\\n`).toString(\"base64\"),\n branch,\n ...(oldFile ? { sha: oldFile.sha } : {}),\n });\n }\n const title = `\u6536\u5F55 ${entry.id}@${entry.version}`;\n const body = `\u66F4\u65B0 \\`${file}\\`\u3002\\n\\n- npm\uFF1A\\`${entry.npm}@${entry.version}\\`\uFF08\u516C\u5171\u6E90\u7CBE\u786E\u7248\u672C\u5DF2\u6838\u5BF9\uFF09\\n- \u6E90\u7801\uFF1A${entry.repo ?? \"\u672A\u63D0\u4F9B\"}\\n- \u8BB8\u53EF\u8BC1\uFF1A\\`${entry.license}\\`\\n- SDK\uFF1A\\`${entry.sdk}\\`\\n- \u4F9D\u8D56\uFF1A${entry.requires.join(\", \") || \"\u65E0\"}\\n\\n\u5DF2\u68C0\u67E5\u5F53\u524D\u7D22\u5F15 Schema\u3001ID \u6765\u6E90\u3001\u7248\u672C\u4E0E\u4F9D\u8D56\u5173\u7CFB\u3002\u5B98\u65B9\u8EAB\u4EFD\u6CBF\u7528\u7EF4\u62A4\u8005\u5BA1\u6838\u7ED3\u679C\uFF1B\u8BF7\u68C0\u67E5 PR \u95E8\u7981\u540E\u5408\u5E76\u3002`;\n if (pull) {\n if (same(entry, oldEntry)) return { ...result, status: \"unchanged\", prUrl: pull.html_url };\n await api(`repos/${canonicalRepo}/pulls/${pull.number}`, \"PATCH\", { title, body });\n return { ...result, status: \"updated\", prUrl: pull.html_url };\n }\n const created = await api<{ html_url: string }>(`repos/${canonicalRepo}/pulls`, \"POST\", { title, body, base, head });\n return { ...result, status: \"created\", prUrl: created.html_url };\n}\n", "#!/usr/bin/env node\nimport { runRegistrySubmitCommand } from \"./registry-command.js\";\n\nrunRegistrySubmitCommand(process.argv.slice(2))\n .then(console.log)\n .catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n });\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { submitModuleToRegistry, type RegistryModule, type RegistrySubmitOptions } from \"./registry-submit.js\";\n\n/** CLI \u4E0E CI \u5171\u7528\u53C2\u6570\u89E3\u6790\uFF0C\u672A\u77E5\u53C2\u6570\u8FD4\u56DE\u5931\u8D25\uFF0C\u907F\u514D\u8BEF\u63D0\u4EA4\u3002 */\nexport async function runRegistrySubmitCommand(args: string[]): Promise<string> {\n const options: RegistrySubmitOptions = {};\n let entryFile: string | undefined;\n const help =\n \"sfmc mod submit [\u6A21\u5757\u76EE\u5F55] [--dry-run] [--no-fork] [--wait-for-publish] [--registry owner/repo]\\nCI\uFF1Asfmc-module-submit --entry-file <JSON>\uFF08\u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\uFF09\";\n if (args.includes(\"--help\") || args.includes(\"-h\")) return help;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === \"--dry-run\") options.dryRun = true;\n else if (arg === \"--no-fork\") options.noFork = true;\n else if (arg === \"--wait-for-publish\") options.waitForPublish = true;\n else if (arg === \"--registry\" || arg === \"--entry-file\") {\n const value = args[++i];\n if (!value || value.startsWith(\"-\")) throw new Error(`\u7F3A\u5C11 ${arg} \u7684\u503C`);\n if (arg === \"--registry\") options.registryRepo = value;\n else entryFile = value;\n } else if (arg.startsWith(\"-\") || options.moduleRoot) throw new Error(`\u672A\u77E5\u6216\u91CD\u590D\u53C2\u6570\uFF1A${arg}\\n${help}`);\n else options.moduleRoot = path.resolve(arg);\n }\n if (entryFile) {\n if (options.moduleRoot) throw new Error(\"--entry-file \u4E0E\u6A21\u5757\u76EE\u5F55\u4E92\u65A5\");\n options.entry = JSON.parse(await fs.readFile(path.resolve(entryFile), \"utf8\")) as RegistryModule;\n }\n const result = await submitModuleToRegistry(options);\n if (result.status === \"preview\")\n return `\u9884\u89C8\uFF1A${result.registryRepo}/${result.path}\\n\u539F\u6761\u76EE\uFF1A\\n${JSON.stringify(result.previous, null, 2)}\\n\u62DF\u63D0\u4EA4\uFF1A\\n${JSON.stringify(result.entry, null, 2)}\\n\u6821\u9A8C\u901A\u8FC7\uFF0C\u672A\u5199\u5165\u8FDC\u7AEF\u3002`;\n return `${{ unchanged: \"\u5185\u5BB9\u76F8\u540C\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\", created: \"\u5DF2\u521B\u5EFA\u7D22\u5F15 PR\", updated: \"\u5DF2\u66F4\u65B0\u7D22\u5F15 PR\" }[result.status]}${result.prUrl ? `\uFF1A${result.prUrl}` : \"\"}`;\n}\n", "/** \u6A21\u5757\u7D22\u5F15\u63D0\u4EA4\u6838\u5FC3\u3002\u4EC5\u5199\u5165\u4E13\u7528\u5206\u652F\u4E2D\u7684\u5355\u4E2A\u5206\u7247\uFF0C\u4E0D\u64CD\u4F5C\u4F5C\u8005\u5DE5\u4F5C\u6811\u3002 */\nimport { Ajv, type AnySchema } from \"ajv\";\nimport { execFile } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport semver from \"semver\";\n\nexport const MODULE_REGISTRY_REPO = \"DogeLakeDev/sfmc-modules\";\ntype Json = Record<string, unknown>;\nexport interface RegistryMetadata {\n name?: string;\n description?: string;\n category?: \"gameplay\" | \"utility\" | \"system\" | \"economy\" | \"social\";\n tags?: string[];\n authors?: string[];\n}\nexport interface RegistryModule extends RegistryMetadata {\n id: string;\n name: string;\n description: string;\n npm: string;\n version: string;\n sdk: string;\n license: string;\n official: boolean;\n repo?: string;\n requires: string[];\n}\nexport interface RegistrySubmitOptions {\n moduleRoot?: string;\n /** \u8868\u5355\u7B49\u5165\u53E3\u63D0\u4F9B\u539F\u59CB\u5B57\u6BB5\uFF0C\u4ECD\u987B\u7ECF\u8FC7\u76F8\u540C npm\u3001Schema \u548C\u7D22\u5F15\u6821\u9A8C\u3002 */\n entry?: RegistryModule;\n registryRepo?: string;\n dryRun?: boolean;\n /** \u7EF4\u62A4\u8005 / GitHub App \u5728\u7D22\u5F15\u4ED3\u5EFA\u5206\u652F\uFF0C\u987B\u6709 Contents \u548C Pull requests \u5199\u6743\u9650\u3002 */\n noFork?: boolean;\n token?: string;\n /** \u7B49\u5F85\u521A\u53D1\u5E03\u7684\u7CBE\u786E\u7248\u672C\u53EF\u89C1\uFF1B\u4EC5\u91CD\u8BD5 404\uFF0C\u6700\u957F 60 \u79D2\u3002 */\n waitForPublish?: boolean;\n log?: (message: string) => void;\n}\nexport interface RegistrySubmitResult {\n status: \"preview\" | \"unchanged\" | \"created\" | \"updated\";\n entry: RegistryModule;\n previous: RegistryModule | null;\n path: string;\n prUrl?: string;\n registryRepo: string;\n}\nfunction object(value: unknown, label: string): Json {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} \u987B\u4E3A JSON \u5BF9\u8C61`);\n return value as Json;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`\u7F3A\u5C11 ${label}`);\n return value.trim();\n}\nfunction sourceRepo(value: unknown): string | undefined {\n if (value === undefined) return undefined;\n const raw = typeof value === \"string\" ? value : object(value, \"repository\").url;\n const repo = text(raw, \"repository.url\")\n .replace(/^git\\+/, \"\")\n .replace(/\\.git$/, \"\");\n const url = new URL(repo);\n if (url.protocol !== \"https:\" || url.username || url.password)\n throw new Error(\"repository \u987B\u4E3A\u4E0D\u542B\u51ED\u636E\u7684 HTTPS \u5730\u5740\");\n return url.href.replace(/\\/$/, \"\");\n}\n\n/** \u4F5C\u8005\u914D\u7F6E\u53EA\u8865\u5145\u5C55\u793A\u5B57\u6BB5\uFF1B\u5305\u3001\u7248\u672C\u3001SDK \u548C\u4F9D\u8D56\u6765\u81EA\u5DF2\u6709\u5951\u7EA6\u3002 */\nexport function createRegistryEntry(\n pkgValue: unknown,\n manifestValue: unknown,\n metadataValue: unknown = {}\n): RegistryModule {\n const pkg = object(pkgValue, \"package.json\");\n const manifest = object(manifestValue, \"sapi/manifest.json\");\n const metadata = object(metadataValue, \"sfmc.registry.json\");\n const allowed = new Set([\"$schema\", \"name\", \"description\", \"category\", \"tags\", \"authors\"]);\n for (const key of Object.keys(metadata))\n if (!allowed.has(key)) throw new Error(`sfmc.registry.json \u4E0D\u652F\u6301\u5B57\u6BB5 ${key}`);\n if (pkg.private === true) throw new Error(\"private \u6A21\u5757\u4E0D\u80FD\u63D0\u4EA4\u516C\u5171\u7D22\u5F15\");\n if (manifest.schemaVersion !== 2) throw new Error(\"\u9700\u8981 schemaVersion=2 \u7684\u6A21\u5757\u6E05\u5355\");\n const peers = object(pkg.peerDependencies ?? {}, \"peerDependencies\");\n const description = metadata.description ?? pkg.description ?? \"\";\n if (typeof description !== \"string\") throw new Error(\"\u529F\u80FD\u4ECB\u7ECD\uFF08description\uFF09\u987B\u4E3A\u5B57\u7B26\u4E32\uFF0C\u53EF\u7559\u7A7A\");\n const entry: RegistryModule = {\n id: text(manifest.id, \"manifest.id\"),\n name: text(metadata.name ?? manifest.name, \"\u5C55\u793A\u540D\u79F0\uFF08name\uFF09\"),\n description: description.trim(),\n npm: text(pkg.name, \"package.name\"),\n version: text(pkg.version, \"package.version\"),\n sdk: text(peers[\"@sfmc-bds/sdk\"], \"peerDependencies.@sfmc-bds/sdk\"),\n license: text(pkg.license, \"package.license\"),\n official: false,\n requires: (manifest.requires ?? []) as string[],\n };\n const repo = sourceRepo(pkg.repository);\n if (repo) entry.repo = repo;\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (metadata[key] !== undefined) Object.assign(entry, { [key]: metadata[key] });\n }\n return entry;\n}\n\nasync function readLocalEntry(root: string): Promise<{ entry: RegistryModule; overrides: Set<string> }> {\n const realRoot = await fs.realpath(root);\n const read = async (file: string) => {\n const target = await fs.realpath(path.join(realRoot, file));\n const relative = path.relative(realRoot, target);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))\n throw new Error(`${file} \u987B\u4F4D\u4E8E\u6A21\u5757\u76EE\u5F55\u5185`);\n const raw = await fs.readFile(target, \"utf8\");\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new Error(`${file} \u5305\u542B\u65E0\u6548 JSON`);\n }\n };\n let metadata: unknown = {};\n try {\n metadata = await read(\"sfmc.registry.json\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n return {\n entry: createRegistryEntry(await read(\"package.json\"), await read(\"sapi/manifest.json\"), metadata),\n overrides: new Set(Object.keys(object(metadata, \"sfmc.registry.json\"))),\n };\n}\n\nclass GitHubError extends Error {\n constructor(\n public status: number,\n endpoint: string,\n rateLimited = false\n ) {\n super(\n `GitHub ${status}: ${endpoint}${rateLimited ? \"\uFF08API \u914D\u989D\u5DF2\u7528\u5C3D\uFF0C\u8BF7\u767B\u5F55\u540E\u91CD\u8BD5\u6216\u7B49\u5F85\u914D\u989D\u6062\u590D\uFF09\" : status === 401 || status === 403 ? \"\uFF08\u68C0\u67E5\u767B\u5F55\u53CA Contents / Pull requests \u6743\u9650\uFF09\" : \"\"}`\n );\n }\n}\nasync function resolveToken(required: boolean): Promise<string | undefined> {\n const configured = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n if (configured) return configured;\n try {\n const { stdout } = await promisify(execFile)(\"gh\", [\"auth\", \"token\", \"--hostname\", \"github.com\"], {\n timeout: 10000,\n windowsHide: true,\n });\n return stdout.trim() || undefined;\n } catch {\n if (required) throw new Error(\"\u63D0\u4EA4\u9700\u8981 GitHub \u767B\u5F55\uFF1A\u6267\u884C gh auth login\uFF0C\u6216\u8BBE\u7F6E GH_TOKEN\u3002\");\n return undefined;\n }\n}\nfunction github(token?: string) {\n return async function api<T>(endpoint: string, method = \"GET\", body?: unknown): Promise<T> {\n const response = await fetch(`https://api.github.com/${endpoint}`, {\n method,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"sfmc-devkit\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: AbortSignal.timeout(15000),\n });\n // \u4E0D\u56DE\u663E\u670D\u52A1\u5668\u6B63\u6587\u6216\u8BA4\u8BC1\u4FE1\u606F\u3002\n if (!response.ok)\n throw new GitHubError(\n response.status,\n endpoint,\n response.status === 429 || response.headers.get(\"x-ratelimit-remaining\") === \"0\"\n );\n return response.status === 204 ? (undefined as T) : ((await response.json()) as T);\n };\n}\ntype Api = ReturnType<typeof github>;\ninterface GitHubRepository {\n id: number;\n full_name: string;\n default_branch: string;\n fork: boolean;\n permissions?: { push?: boolean };\n parent?: { id: number; full_name: string };\n source?: { id: number; full_name: string };\n}\ninterface Content {\n type: string;\n encoding: string;\n content: string;\n sha: string;\n}\nfunction decode(file: Content): unknown {\n if (file.type !== \"file\" || file.encoding !== \"base64\") throw new Error(\"\u7D22\u5F15\u5185\u5BB9\u987B\u4E3A\u666E\u901A JSON \u6587\u4EF6\");\n return JSON.parse(Buffer.from(file.content, \"base64\").toString(\"utf8\"));\n}\nasync function content(api: Api, repo: string, file: string, ref: string): Promise<Content | null> {\n try {\n return await api<Content>(`repos/${repo}/contents/${file}?ref=${encodeURIComponent(ref)}`);\n } catch (error) {\n if (error instanceof GitHubError && error.status === 404) return null;\n throw error;\n }\n}\nfunction same(a: unknown, b: unknown): boolean {\n const stable = (value: unknown): unknown =>\n Array.isArray(value)\n ? value.map(stable)\n : value && typeof value === \"object\"\n ? Object.fromEntries(\n Object.entries(value)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, item]) => [key, stable(item)])\n )\n : value;\n return JSON.stringify(stable(a)) === JSON.stringify(stable(b));\n}\nasync function checkPublished(entry: RegistryModule, wait: boolean): Promise<void> {\n const deadline = Date.now() + (wait ? 60000 : 0);\n while (true) {\n const response = await fetch(\n `https://registry.npmjs.org/${encodeURIComponent(entry.npm)}/${encodeURIComponent(entry.version)}`,\n {\n signal: AbortSignal.timeout(15000),\n headers: { Accept: \"application/json\" },\n }\n );\n if (response.status === 404 && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 3000));\n continue;\n }\n if (!response.ok)\n throw new Error(\n `\u516C\u5171 npm \u5C1A\u65E0\u53EF\u7528\u7684 ${entry.npm}@${entry.version}\uFF08HTTP ${response.status}\uFF09\uFF1B\u5148\u53D1\u5E03\u8BE5\u7CBE\u786E\u7248\u672C\u3002`\n );\n const pkg = object(await response.json(), \"npm \u5143\u6570\u636E\");\n const peers = object(pkg.peerDependencies ?? {}, \"npm peerDependencies\");\n if (\n pkg.name !== entry.npm ||\n pkg.version !== entry.version ||\n pkg.license !== entry.license ||\n peers[\"@sfmc-bds/sdk\"] !== entry.sdk\n ) {\n throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u540D\u79F0\u3001\u7248\u672C\u3001\u8BB8\u53EF\u8BC1\u6216 SDK \u517C\u5BB9\u8303\u56F4\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n }\n if (sourceRepo(pkg.repository) !== entry.repo) throw new Error(\"\u5DF2\u53D1\u5E03\u5305\u7684\u6E90\u7801\u5730\u5740\u4E0E\u63D0\u4EA4\u4FE1\u606F\u4E0D\u4E00\u81F4\");\n return;\n }\n}\n\n/** \u6240\u6709\u5165\u53E3\u5171\u7528\uFF1A\u9884\u89C8\u4E5F\u9A8C\u8BC1\u5DF2\u53D1\u5E03\u7248\u672C\u4E0E\u6700\u65B0\u5206\u7247\uFF1B\u9884\u89C8\u9636\u6BB5\u4E0D\u4EA7\u751F\u8FDC\u7AEF\u5199\u5165\u3002 */\nexport async function submitModuleToRegistry(options: RegistrySubmitOptions = {}): Promise<RegistrySubmitResult> {\n const repo = options.registryRepo ?? MODULE_REGISTRY_REPO;\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) throw new Error(\"registryRepo \u987B\u4E3A owner/repo\");\n const local = options.entry ? null : await readLocalEntry(path.resolve(options.moduleRoot ?? process.cwd()));\n const entry = options.entry ? structuredClone(options.entry) : local!.entry;\n entry.requires ??= [];\n const token = options.token ?? (await resolveToken(!options.dryRun));\n if (!options.dryRun && !token) throw new Error(\"\u63D0\u4EA4\u9700\u8981\u6709\u6548\u7684 GitHub \u767B\u5F55\u6216 GH_TOKEN\");\n const api = github(token);\n const upstream = await api<GitHubRepository>(`repos/${repo}`);\n const canonicalRepo = upstream.full_name;\n const base = upstream.default_branch;\n const baseRef = await api<{ object: { sha: string } }>(\n `repos/${canonicalRepo}/git/ref/heads/${encodeURIComponent(base)}`\n );\n const baseSha = baseRef.object.sha;\n const schemaFile = await content(api, canonicalRepo, \"schemas/registry-module.schema.json\", baseSha);\n if (!schemaFile) throw new Error(\"\u7D22\u5F15\u4ED3\u7F3A\u5C11 registry-module.schema.json\");\n const ajv = new Ajv({ allErrors: true, strict: true });\n ajv.addFormat(\"semver-range\", (value: string) => !!value.trim() && semver.validRange(value) !== null);\n const validate = ajv.compile(decode(schemaFile) as AnySchema);\n entry.official = false; // \u9996\u6B21\u6536\u5F55\u6C38\u4E0D\u81EA\u884C\u58F0\u660E\u5B98\u65B9\u8EAB\u4EFD\u3002\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n if (!semver.valid(entry.version)) throw new Error(\"\u7248\u672C\u987B\u4E3A\u6709\u6548\u7684\u7CBE\u786E SemVer\");\n const file = `modules/${entry.id}.json`;\n options.log?.(`\u6821\u9A8C ${entry.npm}@${entry.version} \u4E0E\u6700\u65B0\u7D22\u5F15\u5206\u7247`);\n const tree = await api<{ truncated: boolean; tree: Array<{ path: string; type: string; sha: string }> }>(\n `repos/${canonicalRepo}/git/trees/${baseSha}?recursive=1`\n );\n if (tree.truncated) throw new Error(\"\u7D22\u5F15\u6811\u8FC7\u5927\uFF0C\u65E0\u6CD5\u5B8C\u6574\u68C0\u67E5\u4F9D\u8D56\");\n const shards = tree.tree.filter((item) => /^modules\\/[^/]+\\.json$/.test(item.path) && item.type === \"blob\");\n const modules: Record<string, RegistryModule> = Object.create(null) as Record<string, RegistryModule>;\n // \u53EA\u8BFB\u53D6\u8BE5\u6A21\u5757\u548C\u4F9D\u8D56\u95ED\u5305\uFF0C\u907F\u514D\u6BCF\u6B21\u63D0\u4EA4\u626B\u63CF\u6574\u4E2A\u7D22\u5F15\u5E76\u8017\u5C3D API \u914D\u989D\u3002\n const shardByPath = new Map(shards.map((item) => [item.path, item]));\n async function load(id: string): Promise<RegistryModule | null> {\n const shard = shardByPath.get(`modules/${id}.json`);\n if (!shard) return null;\n const blob = await api<{ encoding: string; content: string }>(`repos/${canonicalRepo}/git/blobs/${shard.sha}`);\n if (blob.encoding !== \"base64\") throw new Error(\"\u65E0\u6548\u7D22\u5F15 blob \u7F16\u7801\");\n const module = object(\n JSON.parse(Buffer.from(blob.content, \"base64\").toString(\"utf8\")),\n shard.path\n ) as unknown as RegistryModule;\n if (module.id !== id) throw new Error(`\u7D22\u5F15\u5206\u7247 ID \u4E0D\u4E00\u81F4\uFF1A${shard.path}`);\n return module;\n }\n const previous = await load(entry.id);\n if (previous) {\n if (previous.npm !== entry.npm || (previous.repo && sourceRepo(previous.repo) !== entry.repo))\n throw new Error(\"\u8BE5 ID \u5DF2\u5C5E\u4E8E\u5176\u4ED6 npm \u5305\u6216\u6E90\u7801\u4ED3\uFF1B\u8BF7\u7531\u7EF4\u62A4\u8005\u5904\u7406\u8FC1\u79FB\");\n if (!semver.valid(previous.version) || semver.lt(entry.version, previous.version))\n throw new Error(\"\u4E0D\u80FD\u964D\u4F4E\u5DF2\u6536\u5F55\u7248\u672C\");\n entry.official = previous.official; // \u4EC5\u7EE7\u627F\u7D22\u5F15\u4ED3\u5DF2\u5BA1\u6838\u8EAB\u4EFD\u3002\n // \u5355\u7EAF\u66F4\u65B0\u7248\u672C\u4FDD\u7559\u5DF2\u6574\u7406\u7684\u5C55\u793A\u4FE1\u606F\uFF1B\u4F5C\u8005\u914D\u7F6E\u53EF\u663E\u5F0F\u8986\u76D6\u3002\n if (local) {\n if (!local.overrides.has(\"name\")) entry.name = previous.name;\n if (!local.overrides.has(\"description\")) entry.description = previous.description;\n }\n for (const key of [\"category\", \"tags\", \"authors\"] as const) {\n if (entry[key] === undefined && previous[key] !== undefined)\n Object.assign(entry, { [key]: structuredClone(previous[key]) });\n }\n }\n if (!validate(entry)) throw new Error(`\u7D22\u5F15\u8EAB\u4EFD\u6216\u5B57\u6BB5\u4E0D\u5408\u89C4\uFF1A${ajv.errorsText(validate.errors)}`);\n modules[entry.id] = entry;\n const queue = [...entry.requires];\n const loaded = new Set([entry.id]);\n while (queue.length) {\n const batch = queue.splice(0, 4).filter((id) => {\n if (loaded.has(id)) return false;\n loaded.add(id);\n return true;\n });\n await Promise.all(\n batch.map(async (id) => {\n const dependency = await load(id);\n if (!dependency) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n if (!validate(dependency)) throw new Error(`\u4F9D\u8D56 ${id} \u7684\u7D22\u5F15\u5143\u6570\u636E\u4E0D\u5408\u89C4`);\n modules[id] = dependency;\n queue.push(...(dependency.requires ?? []));\n })\n );\n }\n const visited = new Set<string>();\n const visiting = new Set<string>();\n function visit(id: string): void {\n if (visiting.has(id)) throw new Error(`\u6A21\u5757\u4F9D\u8D56\u5B58\u5728\u5FAA\u73AF\uFF1A${id}`);\n if (visited.has(id)) return;\n const module = modules[id];\n if (!module) throw new Error(`\u4F9D\u8D56 ${id} \u5C1A\u672A\u6536\u5F55\uFF0C\u8BF7\u5148\u63D0\u4EA4\u4F9D\u8D56\u6A21\u5757`);\n visiting.add(id);\n for (const dependency of module.requires ?? []) visit(dependency);\n visiting.delete(id);\n visited.add(id);\n }\n visit(entry.id);\n await checkPublished(entry, Boolean(options.waitForPublish));\n const result = { entry, previous, path: file, registryRepo: canonicalRepo };\n if (options.dryRun) return { ...result, status: \"preview\" };\n if (same(entry, previous)) return { ...result, status: \"unchanged\" };\n\n let headRepo = canonicalRepo;\n if (!options.noFork && upstream.permissions?.push !== true) {\n const user = await api<{ login: string }>(\"user\");\n const forkName = `${user.login}/${canonicalRepo.split(\"/\")[1]}`;\n let fork: GitHubRepository | undefined;\n try {\n fork = await api(`repos/${forkName}`);\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n }\n if (!fork)\n fork = await api<GitHubRepository>(`repos/${canonicalRepo}/forks`, \"POST\", { default_branch_only: true });\n if (fork.id === upstream.id) {\n // \u5019\u9009\u5730\u5740\u4E0E\u76EE\u6807\u5730\u5740\u53EF\u80FD\u56E0\u91CD\u5B9A\u5411\u6307\u5411\u540C\u4E00\u4ED3\u5E93\uFF0C\u6309\u5B9E\u9645\u6743\u9650\u5904\u7406\u3002\n if (fork.permissions?.push !== true)\n throw new Error(\n `${forkName} \u5DF2\u91CD\u5B9A\u5411\u5230 ${canonicalRepo}\uFF0C\u5F53\u524D\u51ED\u636E\u6CA1\u6709\u5199\u6743\u9650\uFF1B\u8BF7\u68C0\u67E5 GitHub \u767B\u5F55\u4E0E Contents \u6743\u9650\u3002`\n );\n } else {\n const networkId = upstream.source?.id ?? upstream.id;\n if (!fork.fork || (fork.parent?.id !== upstream.id && fork.source?.id !== networkId))\n throw new Error(\n `${fork.full_name} \u672A\u4E0E\u76EE\u6807\u7D22\u5F15\u4ED3\u5173\u8054\uFF0C\u65E0\u6CD5\u4F5C\u4E3A\u8BE5 PR \u7684\u6765\u6E90\uFF1B\u8BF7\u4F7F\u7528\u76EE\u6807\u4ED3\u7684 fork\uFF0C\u6216\u6709\u5199\u6743\u9650\u65F6\u4F7F\u7528 --no-fork\u3002`\n );\n headRepo = fork.full_name;\n }\n }\n type Pull = { number: number; html_url: string; head: { ref: string; repo: { full_name: string } | null } };\n let pull: Pull | undefined;\n const prefix = `sfmc-submit/${entry.id}/`;\n for (let page = 1; ; page++) {\n const pagePulls = await api<Pull[]>(\n `repos/${canonicalRepo}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100&page=${page}`\n );\n const matches = pagePulls.filter(\n (item) => item.head.ref.startsWith(prefix) && item.head.repo?.full_name.toLowerCase() === headRepo.toLowerCase()\n );\n if (matches.length > 1 || (pull && matches.length)) throw new Error(\"\u8BE5\u6A21\u5757\u6709\u591A\u4E2A\u63D0\u4EA4 PR\uFF0C\u8BF7\u5148\u5408\u5E76\u6216\u5173\u95ED\u591A\u4F59 PR\");\n pull ??= matches[0];\n if (pagePulls.length < 100) break;\n }\n // \u5DF2\u5408\u5E76\u7684\u5206\u652F\u65E0\u9700\u91CD\u7F6E\uFF1B\u65B0\u4E00\u8F6E\u63D0\u4EA4\u4EE5\u6700\u65B0 main \u7684 SHA \u6807\u8BC6\u3002\n const branch = pull?.head.ref ?? `${prefix}${baseSha.slice(0, 12)}`;\n const head = `${headRepo.split(\"/\")[0]}:${branch}`;\n let branchRef: { object: { sha: string } } | null = null;\n // \u65B0 fork \u7684\u521B\u5EFA\u662F\u5F02\u6B65\u64CD\u4F5C\uFF0C\u6700\u591A\u7B49\u5F85 15 \u79D2\u3002\n for (let attempt = 0; attempt < 6; attempt++) {\n try {\n branchRef = await api(`repos/${headRepo}/git/ref/heads/${encodeURIComponent(branch)}`);\n break;\n } catch (error) {\n if (!(error instanceof GitHubError && error.status === 404)) throw error;\n try {\n branchRef = await api(`repos/${headRepo}/git/refs`, \"POST\", { ref: `refs/heads/${branch}`, sha: baseSha });\n break;\n } catch (createError) {\n if (!(createError instanceof GitHubError && [404, 422].includes(createError.status)) || attempt === 5)\n throw createError;\n await new Promise((resolve) => setTimeout(resolve, 3000));\n }\n }\n }\n if (!branchRef) throw new Error(\"\u63D0\u4EA4\u5206\u652F\u5C1A\u672A\u5C31\u7EEA\uFF0C\u8BF7\u91CD\u8BD5\");\n const comparison = await api<{ files: Array<{ filename: string }> }>(\n `repos/${canonicalRepo}/compare/${baseSha}...${encodeURIComponent(`${headRepo.split(\"/\")[0]}:${branchRef.object.sha}`)}`\n );\n if (comparison.files.some((item) => item.filename !== file))\n throw new Error(\"\u4E13\u7528\u63D0\u4EA4\u5206\u652F\u5305\u542B\u5176\u4ED6\u6587\u4EF6\u6539\u52A8\uFF0C\u8BF7\u5148\u7531\u4F5C\u8005\u5904\u7406\");\n const oldFile = await content(api, headRepo, file, branchRef.object.sha);\n const oldEntry = oldFile ? decode(oldFile) : null;\n if (oldEntry) {\n const pending = object(oldEntry, file);\n if (\n pending.npm !== entry.npm ||\n (pending.repo && sourceRepo(pending.repo) !== entry.repo) ||\n typeof pending.version !== \"string\" ||\n !semver.valid(pending.version) ||\n semver.lt(entry.version, pending.version)\n ) {\n throw new Error(\"\u5DF2\u6709\u63D0\u4EA4\u7684\u6765\u6E90\u6216\u7248\u672C\u51B2\u7A81\uFF1B\u62D2\u7EDD\u8986\u76D6\");\n }\n }\n if (!same(entry, oldEntry)) {\n await api(`repos/${headRepo}/contents/${file}`, \"PUT\", {\n message: `chore(registry): ${entry.id} ${entry.version}`,\n content: Buffer.from(`${JSON.stringify(entry, null, 2)}\\n`).toString(\"base64\"),\n branch,\n ...(oldFile ? { sha: oldFile.sha } : {}),\n });\n }\n const title = `\u6536\u5F55 ${entry.id}@${entry.version}`;\n const body = `\u66F4\u65B0 \\`${file}\\`\u3002\\n\\n- npm\uFF1A\\`${entry.npm}@${entry.version}\\`\uFF08\u516C\u5171\u6E90\u7CBE\u786E\u7248\u672C\u5DF2\u6838\u5BF9\uFF09\\n- \u6E90\u7801\uFF1A${entry.repo ?? \"\u672A\u63D0\u4F9B\"}\\n- \u8BB8\u53EF\u8BC1\uFF1A\\`${entry.license}\\`\\n- SDK\uFF1A\\`${entry.sdk}\\`\\n- \u4F9D\u8D56\uFF1A${entry.requires.join(\", \") || \"\u65E0\"}\\n\\n\u5DF2\u68C0\u67E5\u5F53\u524D\u7D22\u5F15 Schema\u3001ID \u6765\u6E90\u3001\u7248\u672C\u4E0E\u4F9D\u8D56\u5173\u7CFB\u3002\u5B98\u65B9\u8EAB\u4EFD\u6CBF\u7528\u7EF4\u62A4\u8005\u5BA1\u6838\u7ED3\u679C\uFF1B\u8BF7\u68C0\u67E5 PR \u95E8\u7981\u540E\u5408\u5E76\u3002`;\n if (pull) {\n if (same(entry, oldEntry)) return { ...result, status: \"unchanged\", prUrl: pull.html_url };\n await api(`repos/${canonicalRepo}/pulls/${pull.number}`, \"PATCH\", { title, body });\n return { ...result, status: \"updated\", prUrl: pull.html_url };\n }\n const created = await api<{ html_url: string }>(`repos/${canonicalRepo}/pulls`, \"POST\", { title, body, base, head });\n return { ...result, status: \"created\", prUrl: created.html_url };\n}\n", "#!/usr/bin/env node\nimport { runRegistrySubmitCommand } from \"./registry-command.js\";\n\nrunRegistrySubmitCommand(process.argv.slice(2))\n .then(console.log)\n .catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n });\n"],
5
+ "mappings": "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",
6
6
  "names": ["fs", "path", "a", "b", "path", "fs"]
7
7
  }
@@ -42,10 +42,13 @@ export function createRegistryEntry(pkgValue, manifestValue, metadataValue = {})
42
42
  if (manifest.schemaVersion !== 2)
43
43
  throw new Error("需要 schemaVersion=2 的模块清单");
44
44
  const peers = object(pkg.peerDependencies ?? {}, "peerDependencies");
45
+ const description = metadata.description ?? pkg.description ?? "";
46
+ if (typeof description !== "string")
47
+ throw new Error("功能介绍(description)须为字符串,可留空");
45
48
  const entry = {
46
49
  id: text(manifest.id, "manifest.id"),
47
50
  name: text(metadata.name ?? manifest.name, "展示名称(name)"),
48
- description: text(metadata.description ?? pkg.description, "功能介绍(description)"),
51
+ description: description.trim(),
49
52
  npm: text(pkg.name, "package.name"),
50
53
  version: text(pkg.version, "package.version"),
51
54
  sdk: text(peers["@sfmc-bds/sdk"], "peerDependencies.@sfmc-bds/sdk"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sfmc-bds/devkit",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "SFMC module authoring toolkit — watch, rebuild, enable/disable (for VS Code extension & tooling)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -6,7 +6,7 @@
6
6
  "properties": {
7
7
  "$schema": { "type": "string" },
8
8
  "name": { "type": "string", "minLength": 1, "pattern": "\\S" },
9
- "description": { "type": "string", "minLength": 1, "pattern": "\\S" },
9
+ "description": { "type": "string" },
10
10
  "category": { "enum": ["gameplay", "utility", "system", "economy", "social"] },
11
11
  "tags": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1, "pattern": "\\S" } },
12
12
  "authors": {