my-patina 0.3.0 → 0.5.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +48 -8
  2. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli.ts
4
+ import { Command } from "commander";
5
+
3
6
  // src/wizard.ts
4
7
  import * as p from "@clack/prompts";
5
8
  import chalk from "chalk";
@@ -80,9 +83,9 @@ var linkedinModule = {
80
83
  managedPaths: LI_MANAGED_PATHS,
81
84
  contentFileNames: CONTENT_FILE_NAMES,
82
85
  managedFiles(vars) {
83
- const files = LI_COMMANDS.map((cmd2) => [
84
- `.claude/commands/${cmd2}`,
85
- render(tpl(`modules/linkedin/commands/${cmd2}`), vars)
86
+ const files = LI_COMMANDS.map((cmd) => [
87
+ `.claude/commands/${cmd}`,
88
+ render(tpl(`modules/linkedin/commands/${cmd}`), vars)
86
89
  ]);
87
90
  files.push([
88
91
  ".claude/modules/linkedin/manifest.md",
@@ -239,6 +242,23 @@ function touch(targetDir, relativePath) {
239
242
  mkdirSync2(dirname3(full), { recursive: true });
240
243
  writeFileSync3(full, "", "utf8");
241
244
  }
245
+ var MANIFEST_REQUIRED_FIELDS = ["name", "label", "reflect_hook", "description", "installed"];
246
+ function extractFrontmatter(content) {
247
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
248
+ if (!match) return null;
249
+ const parsed = yaml2.load(match[1]);
250
+ if (typeof parsed !== "object" || parsed === null) return null;
251
+ return parsed;
252
+ }
253
+ function validateManifestFrontmatter(moduleName, content) {
254
+ const fm = extractFrontmatter(content);
255
+ if (!fm) throw new Error(`Module "${moduleName}" manifest has missing or unparseable frontmatter`);
256
+ for (const field of MANIFEST_REQUIRED_FIELDS) {
257
+ if (!fm[field]) {
258
+ throw new Error(`Module "${moduleName}" manifest is missing required field "${field}"`);
259
+ }
260
+ }
261
+ }
242
262
  function profileToVars(profile, liProfileUrl) {
243
263
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
244
264
  return {
@@ -326,6 +346,10 @@ async function scaffold(opts) {
326
346
  ...baseManagedFiles(vars, editor, targetDir),
327
347
  ...modules.flatMap((m) => moduleManagedFiles(m, vars))
328
348
  ];
349
+ for (const module of modules) {
350
+ const manifestEntry = managedFiles.find(([p2]) => p2 === `.claude/modules/${module}/manifest.md`);
351
+ if (manifestEntry) validateManifestFrontmatter(module, manifestEntry[1]);
352
+ }
329
353
  for (const [relativePath, content] of managedFiles) {
330
354
  const { checksum } = writeManagedFile(targetDir, relativePath, content, {});
331
355
  checksums[relativePath] = checksum;
@@ -991,10 +1015,15 @@ function onCancel() {
991
1015
  process.exit(0);
992
1016
  }
993
1017
 
1018
+ // src/commands/index.ts
1019
+ function registerCommands(_program) {
1020
+ }
1021
+
994
1022
  // src/cli.ts
995
1023
  import chalk2 from "chalk";
996
- var [cmd] = process.argv.slice(2);
997
- if (cmd === "validate") {
1024
+ var program = new Command();
1025
+ program.name("patina").description("Personal professional knowledge graph \u2014 setup and management");
1026
+ program.command("validate").description("Check your patina for broken links and excluded items").action(() => {
998
1027
  try {
999
1028
  const cwd = process.cwd();
1000
1029
  const root = findPatinaRoot(cwd);
@@ -1006,7 +1035,7 @@ if (cmd === "validate") {
1006
1035
  const result = validate(root, profile);
1007
1036
  const report = formatReport(result);
1008
1037
  const lines = report.split("\n");
1009
- const summary = lines.pop();
1038
+ const summary = lines.pop() ?? "";
1010
1039
  if (lines.length > 0) console.log(lines.join("\n"));
1011
1040
  console.log(result.ok ? chalk2.green(summary) : chalk2.red(summary));
1012
1041
  process.exit(result.ok ? 0 : 1);
@@ -1014,9 +1043,20 @@ if (cmd === "validate") {
1014
1043
  console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1015
1044
  process.exit(1);
1016
1045
  }
1017
- } else {
1046
+ });
1047
+ registerCommands(program);
1048
+ program.action(function() {
1049
+ if (this.args.length > 0) {
1050
+ console.error(chalk2.red(`Unknown command: ${this.args[0]}`));
1051
+ console.error(chalk2.dim("Run 'patina --help' for available commands."));
1052
+ process.exit(1);
1053
+ }
1018
1054
  main().catch((err) => {
1019
1055
  console.error(err.message);
1020
1056
  process.exit(1);
1021
1057
  });
1022
- }
1058
+ });
1059
+ program.parseAsync(process.argv).catch((err) => {
1060
+ console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1061
+ process.exit(1);
1062
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-patina",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Personal professional knowledge graph — setup and management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "dependencies": {
21
21
  "@clack/prompts": "^0.9.0",
22
22
  "chalk": "^5.3.0",
23
+ "commander": "^12.1.0",
23
24
  "js-yaml": "^4.1.0"
24
25
  },
25
26
  "devDependencies": {