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.
- package/dist/cli.js +48 -8
- 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((
|
|
84
|
-
`.claude/commands/${
|
|
85
|
-
render(tpl(`modules/linkedin/commands/${
|
|
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
|
|
997
|
-
|
|
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
|
-
}
|
|
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
|
+
"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": {
|