@hyphaene/hexa-ts-kit 1.8.0 → 1.10.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.
@@ -840,6 +840,9 @@ var ContractsLintConfigSchema = z.object({
840
840
  }),
841
841
  disabledRules: z.array(z.string()).optional()
842
842
  });
843
+ var VaultLintConfigSchema = z.object({
844
+ disabledRules: z.array(z.string()).optional()
845
+ });
843
846
  var ContractsScaffoldConfigSchema = z.object({
844
847
  path: z.string(),
845
848
  // Absolute path to contracts lib
@@ -849,14 +852,20 @@ var ContractsScaffoldConfigSchema = z.object({
849
852
  var ProjectConfigSchema = z.object({
850
853
  type: z.enum(["contracts-lib", "nestjs-bff", "vue-frontend"])
851
854
  });
855
+ var VaultConfigSchema = z.object({
856
+ schemaPath: z.string()
857
+ // Path to vault.schema.json relative to repo root
858
+ });
852
859
  var HexaTsKitConfigSchema = z.object({
853
860
  project: ProjectConfigSchema,
854
861
  lint: z.object({
855
- contracts: ContractsLintConfigSchema.optional()
862
+ contracts: ContractsLintConfigSchema.optional(),
863
+ vault: VaultLintConfigSchema.optional()
856
864
  }).optional(),
857
865
  scaffold: z.object({
858
866
  contracts: ContractsScaffoldConfigSchema.optional()
859
- }).optional()
867
+ }).optional(),
868
+ vault: VaultConfigSchema.optional()
860
869
  });
861
870
  var CONFIG_FILE_NAME = ".hexa-ts-kit.yaml";
862
871
  function loadConfig(repoPath) {
@@ -917,6 +926,12 @@ function resolveConfigPath(repoPath, relativePath) {
917
926
  function getDisabledRules(config) {
918
927
  return config.lint?.contracts?.disabledRules ?? [];
919
928
  }
929
+ function getDisabledVaultRules(config) {
930
+ return config.lint?.vault?.disabledRules ?? [];
931
+ }
932
+ function getVaultConfig(config) {
933
+ return config.vault ?? null;
934
+ }
920
935
 
921
936
  // src/lib/contracts/permissions-extractor.ts
922
937
  import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
@@ -2485,6 +2500,8 @@ var vaultChecker = {
2485
2500
  if (!vault) {
2486
2501
  return results;
2487
2502
  }
2503
+ const configResult = loadConfig(ctx.cwd);
2504
+ const disabledRules = configResult.success ? getDisabledVaultRules(configResult.config) : [];
2488
2505
  const project = new Project({
2489
2506
  skipAddingFilesFromTsConfig: true,
2490
2507
  skipFileDependencyResolution: true
@@ -2499,7 +2516,12 @@ var vaultChecker = {
2499
2516
  }
2500
2517
  }
2501
2518
  for (const sourceFile of sourceFiles) {
2502
- results.push(...checkAstPatterns(sourceFile));
2519
+ const astResults = checkAstPatterns(sourceFile);
2520
+ for (const result of astResults) {
2521
+ if (!disabledRules.includes(result.ruleId)) {
2522
+ results.push(result);
2523
+ }
2524
+ }
2503
2525
  }
2504
2526
  return results;
2505
2527
  }
@@ -3302,6 +3324,8 @@ async function scaffoldCommand(type, path, options) {
3302
3324
  }
3303
3325
 
3304
3326
  export {
3327
+ loadConfig,
3328
+ getVaultConfig,
3305
3329
  lintCore,
3306
3330
  lintCommand,
3307
3331
  analyzeCore,
package/dist/cli.js CHANGED
@@ -1,9 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  analyzeCommand,
4
+ getVaultConfig,
4
5
  lintCommand,
6
+ loadConfig,
5
7
  scaffoldCommand
6
- } from "./chunk-QTZTVZQA.js";
8
+ } from "./chunk-IBVI6IS2.js";
7
9
 
8
10
  // src/cli.ts
9
11
  import { program } from "commander";
@@ -257,6 +259,533 @@ function padEnd(str, length) {
257
259
  return str.length >= length ? str.slice(0, length - 1) + " " : str + " ".repeat(length - str.length);
258
260
  }
259
261
 
262
+ // src/vault/extractors/json-schema.ts
263
+ import { execSync } from "child_process";
264
+ import { existsSync, readFileSync as readFileSync2 } from "fs";
265
+ import { join } from "path";
266
+ function extractFromJsonSchema(source, version, options) {
267
+ const { schemaPath, cwd = process.cwd() } = options;
268
+ let jsonContent;
269
+ const isGitRef = options.isGitRef ?? isLikelyGitRef(source);
270
+ if (isGitRef) {
271
+ jsonContent = readFromGit(source, schemaPath, cwd);
272
+ } else {
273
+ jsonContent = readFromFilesystem(source, schemaPath);
274
+ }
275
+ const jsonSchema = JSON.parse(jsonContent);
276
+ const root = convertJsonSchemaToSchemaNode(
277
+ jsonSchema,
278
+ jsonSchema.definitions
279
+ );
280
+ return {
281
+ root,
282
+ sourceFile: schemaPath,
283
+ version
284
+ };
285
+ }
286
+ function isLikelyGitRef(source) {
287
+ if (source === "HEAD" || source.startsWith("HEAD")) return true;
288
+ if (source === "main" || source === "master" || source === "develop")
289
+ return true;
290
+ if (source.startsWith("origin/")) return true;
291
+ if (source.startsWith("refs/")) return true;
292
+ if (source.match(/^[a-f0-9]{7,40}$/)) return true;
293
+ if (source.match(/^v?\d+\.\d+/)) return true;
294
+ if (source.startsWith(".") || source.startsWith("/") || source.startsWith("~"))
295
+ return false;
296
+ if (source.includes("/") && !source.startsWith("origin/")) return false;
297
+ return false;
298
+ }
299
+ function readFromGit(gitRef, schemaPath, cwd) {
300
+ let fullRef;
301
+ if (gitRef.includes(":") && gitRef.endsWith(".json")) {
302
+ fullRef = gitRef;
303
+ } else if (gitRef.includes(":")) {
304
+ fullRef = gitRef;
305
+ } else {
306
+ fullRef = `${gitRef}:${schemaPath}`;
307
+ }
308
+ try {
309
+ const content = execSync(`git show "${fullRef}"`, {
310
+ cwd,
311
+ encoding: "utf-8",
312
+ stdio: ["pipe", "pipe", "pipe"]
313
+ });
314
+ return content;
315
+ } catch (error) {
316
+ const errorMsg = error instanceof Error ? error.message : String(error);
317
+ throw new Error(
318
+ `Cannot read schema from git ref "${fullRef}": ${errorMsg}`
319
+ );
320
+ }
321
+ }
322
+ function readFromFilesystem(repoPath, schemaPath) {
323
+ const fullPath = join(repoPath, schemaPath);
324
+ if (!existsSync(fullPath)) {
325
+ throw new Error(
326
+ `Schema file not found: ${fullPath}
327
+ Run 'npm run vault:build' to generate it.`
328
+ );
329
+ }
330
+ return readFileSync2(fullPath, "utf-8");
331
+ }
332
+ function convertJsonSchemaToSchemaNode(schema, definitions) {
333
+ const localDefs = { ...definitions, ...schema.definitions };
334
+ if (schema.$ref) {
335
+ const refPath = schema.$ref.replace("#/definitions/", "");
336
+ const refSchema = localDefs?.[refPath];
337
+ if (refSchema) {
338
+ return convertJsonSchemaToSchemaNode(refSchema, localDefs);
339
+ }
340
+ return { type: "unknown" };
341
+ }
342
+ const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
343
+ switch (type) {
344
+ case "string":
345
+ if (schema.enum) {
346
+ return {
347
+ type: "enum",
348
+ enumValues: schema.enum.map(String)
349
+ };
350
+ }
351
+ return { type: "string" };
352
+ case "number":
353
+ case "integer":
354
+ return { type: "number" };
355
+ case "boolean":
356
+ return { type: "boolean" };
357
+ case "array":
358
+ if (schema.items) {
359
+ return {
360
+ type: "array",
361
+ arrayItemType: convertJsonSchemaToSchemaNode(schema.items, localDefs)
362
+ };
363
+ }
364
+ return { type: "array" };
365
+ case "object": {
366
+ const children = {};
367
+ const requiredSet = new Set(schema.required ?? []);
368
+ if (schema.properties) {
369
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
370
+ if (key.startsWith("$") || key === "definitions") continue;
371
+ const propDefs = { ...localDefs, ...propSchema.definitions };
372
+ const propNode = convertJsonSchemaToSchemaNode(propSchema, propDefs);
373
+ children[key] = requiredSet.has(key) ? propNode : { ...propNode, optional: true };
374
+ }
375
+ }
376
+ return { type: "object", children };
377
+ }
378
+ default: {
379
+ if (schema.properties) {
380
+ const children = {};
381
+ const requiredSet = new Set(schema.required ?? []);
382
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
383
+ if (key.startsWith("$") || key === "definitions") continue;
384
+ const propDefs = { ...localDefs, ...propSchema.definitions };
385
+ const propNode = convertJsonSchemaToSchemaNode(propSchema, propDefs);
386
+ children[key] = requiredSet.has(key) ? propNode : { ...propNode, optional: true };
387
+ }
388
+ return { type: "object", children };
389
+ }
390
+ return { type: "unknown" };
391
+ }
392
+ }
393
+ }
394
+ function gitRefExists(ref, cwd) {
395
+ try {
396
+ execSync(`git rev-parse --verify "${ref}"`, {
397
+ cwd,
398
+ encoding: "utf-8",
399
+ stdio: ["pipe", "pipe", "pipe"]
400
+ });
401
+ return true;
402
+ } catch {
403
+ return false;
404
+ }
405
+ }
406
+ function getCurrentBranch(cwd) {
407
+ try {
408
+ return execSync("git rev-parse --abbrev-ref HEAD", {
409
+ cwd,
410
+ encoding: "utf-8"
411
+ }).trim();
412
+ } catch {
413
+ return "HEAD";
414
+ }
415
+ }
416
+ function fileExistsAtRef(ref, filePath, cwd) {
417
+ try {
418
+ execSync(`git show "${ref}:${filePath}"`, {
419
+ cwd,
420
+ encoding: "utf-8",
421
+ stdio: ["pipe", "pipe", "pipe"]
422
+ });
423
+ return true;
424
+ } catch {
425
+ return false;
426
+ }
427
+ }
428
+
429
+ // src/vault/diff.ts
430
+ function diffSchemas(source, target, sourceVersion, targetVersion) {
431
+ const changes = [];
432
+ compareNodes(source, target, "", changes);
433
+ const hasBreakingChanges = changes.some(
434
+ (c) => c.type === "removed" || c.type === "changed"
435
+ );
436
+ return {
437
+ sourceVersion,
438
+ targetVersion,
439
+ changes,
440
+ hasBreakingChanges
441
+ };
442
+ }
443
+ function compareNodes(source, target, path, changes) {
444
+ if (!source && target) {
445
+ changes.push({
446
+ path: path || "(root)",
447
+ type: "added",
448
+ newValue: target
449
+ });
450
+ return;
451
+ }
452
+ if (source && !target) {
453
+ changes.push({
454
+ path: path || "(root)",
455
+ type: "removed",
456
+ oldValue: source
457
+ });
458
+ return;
459
+ }
460
+ if (!source || !target) {
461
+ return;
462
+ }
463
+ if (source.type !== target.type) {
464
+ changes.push({
465
+ path: path || "(root)",
466
+ type: "changed",
467
+ oldValue: source,
468
+ newValue: target
469
+ });
470
+ return;
471
+ }
472
+ if (source.type === "enum" && target.type === "enum") {
473
+ const sourceValues = new Set(source.enumValues ?? []);
474
+ const targetValues = new Set(target.enumValues ?? []);
475
+ for (const val of targetValues) {
476
+ if (!sourceValues.has(val)) {
477
+ changes.push({
478
+ path: `${path}[enum:${val}]`,
479
+ type: "added",
480
+ newValue: { type: "enum", enumValues: [val] }
481
+ });
482
+ }
483
+ }
484
+ for (const val of sourceValues) {
485
+ if (!targetValues.has(val)) {
486
+ changes.push({
487
+ path: `${path}[enum:${val}]`,
488
+ type: "removed",
489
+ oldValue: { type: "enum", enumValues: [val] }
490
+ });
491
+ }
492
+ }
493
+ return;
494
+ }
495
+ if (source.optional !== target.optional) {
496
+ changes.push({
497
+ path,
498
+ type: "changed",
499
+ oldValue: source,
500
+ newValue: target
501
+ });
502
+ }
503
+ if (source.type === "array" && target.type === "array") {
504
+ compareNodes(
505
+ source.arrayItemType,
506
+ target.arrayItemType,
507
+ `${path}[]`,
508
+ changes
509
+ );
510
+ return;
511
+ }
512
+ if (source.type === "object" && target.type === "object") {
513
+ const sourceKeys = new Set(Object.keys(source.children ?? {}));
514
+ const targetKeys = new Set(Object.keys(target.children ?? {}));
515
+ for (const key of targetKeys) {
516
+ const childPath = path ? `${path}.${key}` : key;
517
+ if (!sourceKeys.has(key)) {
518
+ changes.push({
519
+ path: childPath,
520
+ type: "added",
521
+ newValue: target.children[key]
522
+ });
523
+ } else {
524
+ compareNodes(
525
+ source.children[key],
526
+ target.children[key],
527
+ childPath,
528
+ changes
529
+ );
530
+ }
531
+ }
532
+ for (const key of sourceKeys) {
533
+ if (!targetKeys.has(key)) {
534
+ const childPath = path ? `${path}.${key}` : key;
535
+ changes.push({
536
+ path: childPath,
537
+ type: "removed",
538
+ oldValue: source.children[key]
539
+ });
540
+ }
541
+ }
542
+ }
543
+ }
544
+ function formatType(node) {
545
+ switch (node.type) {
546
+ case "string":
547
+ return "string";
548
+ case "number":
549
+ return "number";
550
+ case "boolean":
551
+ return "boolean";
552
+ case "array":
553
+ if (node.arrayItemType) {
554
+ return `${formatType(node.arrayItemType)}[]`;
555
+ }
556
+ return "array";
557
+ case "enum":
558
+ if (node.enumValues) {
559
+ return `enum(${node.enumValues.join(" | ")})`;
560
+ }
561
+ return "enum";
562
+ case "object":
563
+ if (node.children) {
564
+ const keys = Object.keys(node.children).filter((k) => k !== "__ref");
565
+ if (keys.length <= 3) {
566
+ return `{ ${keys.join(", ")} }`;
567
+ }
568
+ return `{ ${keys.slice(0, 3).join(", ")}, ... }`;
569
+ }
570
+ return "object";
571
+ default:
572
+ return "unknown";
573
+ }
574
+ }
575
+
576
+ // src/commands/vault-diff.ts
577
+ function getSchemaPath(cwd) {
578
+ const configResult = loadConfig(cwd);
579
+ if (!configResult.success) {
580
+ throw new Error(
581
+ `Cannot load .hexa-ts-kit.yaml: ${configResult.error}
582
+ Add vault.schemaPath to your config file.`
583
+ );
584
+ }
585
+ const vaultConfig = getVaultConfig(configResult.config);
586
+ if (!vaultConfig) {
587
+ throw new Error(
588
+ `Missing vault config in .hexa-ts-kit.yaml
589
+ Add:
590
+ vault:
591
+ schemaPath: path/to/vault.schema.json`
592
+ );
593
+ }
594
+ return vaultConfig.schemaPath;
595
+ }
596
+ async function vaultDiffCommand(sourceRef, targetRef, options) {
597
+ const format = options.format ?? "console";
598
+ const cwd = options.cwd ?? process.cwd();
599
+ let schemaPath;
600
+ try {
601
+ schemaPath = getSchemaPath(cwd);
602
+ } catch (error) {
603
+ console.error(
604
+ `Error: ${error instanceof Error ? error.message : String(error)}`
605
+ );
606
+ process.exit(1);
607
+ }
608
+ if (!gitRefExists(sourceRef, cwd)) {
609
+ console.error(`Error: Git ref "${sourceRef}" does not exist`);
610
+ process.exit(1);
611
+ }
612
+ if (!gitRefExists(targetRef, cwd)) {
613
+ console.error(`Error: Git ref "${targetRef}" does not exist`);
614
+ process.exit(1);
615
+ }
616
+ if (!fileExistsAtRef(sourceRef, schemaPath, cwd)) {
617
+ console.error(
618
+ `Error: vault.schema.json not found at "${sourceRef}:${schemaPath}"
619
+ The schema file may not exist in this version. Run 'npm run vault:build' on that branch first.`
620
+ );
621
+ process.exit(1);
622
+ }
623
+ if (!fileExistsAtRef(targetRef, schemaPath, cwd)) {
624
+ console.error(
625
+ `Error: vault.schema.json not found at "${targetRef}:${schemaPath}"
626
+ The schema file may not exist in this version. Run 'npm run vault:build' on that branch first.`
627
+ );
628
+ process.exit(1);
629
+ }
630
+ try {
631
+ const extractOpts = { schemaPath, isGitRef: true, cwd };
632
+ const sourceSchema = extractFromJsonSchema(
633
+ sourceRef,
634
+ sourceRef,
635
+ extractOpts
636
+ );
637
+ const targetSchema = extractFromJsonSchema(
638
+ targetRef,
639
+ targetRef,
640
+ extractOpts
641
+ );
642
+ const result = diffSchemas(
643
+ sourceSchema.root,
644
+ targetSchema.root,
645
+ sourceSchema.version,
646
+ targetSchema.version
647
+ );
648
+ if (format === "json") {
649
+ console.log(JSON.stringify(result, null, 2));
650
+ } else {
651
+ printConsoleOutput(result);
652
+ }
653
+ if (result.hasBreakingChanges) {
654
+ process.exit(1);
655
+ }
656
+ } catch (error) {
657
+ console.error(
658
+ `Error: ${error instanceof Error ? error.message : String(error)}`
659
+ );
660
+ process.exit(1);
661
+ }
662
+ }
663
+ async function vaultExtractCommand(source, options) {
664
+ const format = options.format ?? "json";
665
+ const cwd = options.cwd ?? process.cwd();
666
+ let schemaPath;
667
+ try {
668
+ schemaPath = getSchemaPath(cwd);
669
+ } catch (error) {
670
+ console.error(
671
+ `Error: ${error instanceof Error ? error.message : String(error)}`
672
+ );
673
+ process.exit(1);
674
+ }
675
+ try {
676
+ let schema;
677
+ if (source === ".") {
678
+ schema = extractFromJsonSchema(cwd, "local", {
679
+ schemaPath,
680
+ isGitRef: false
681
+ });
682
+ } else if (gitRefExists(source, cwd)) {
683
+ if (!fileExistsAtRef(source, schemaPath, cwd)) {
684
+ console.error(
685
+ `Error: vault.schema.json not found at "${source}:${schemaPath}"`
686
+ );
687
+ process.exit(1);
688
+ }
689
+ schema = extractFromJsonSchema(source, source, {
690
+ schemaPath,
691
+ isGitRef: true,
692
+ cwd
693
+ });
694
+ } else {
695
+ schema = extractFromJsonSchema(source, "path", {
696
+ schemaPath,
697
+ isGitRef: false
698
+ });
699
+ }
700
+ if (format === "json") {
701
+ console.log(JSON.stringify(schema, null, 2));
702
+ } else {
703
+ console.log(`Schema from ${schema.sourceFile} (${schema.version}):
704
+ `);
705
+ printSchemaTree(schema.root, 0);
706
+ }
707
+ } catch (error) {
708
+ console.error(
709
+ `Error: ${error instanceof Error ? error.message : String(error)}`
710
+ );
711
+ process.exit(1);
712
+ }
713
+ }
714
+ function printConsoleOutput(result) {
715
+ console.log(`
716
+ Vault Schema Diff`);
717
+ console.log(`Source: ${result.sourceVersion}`);
718
+ console.log(`Target: ${result.targetVersion}`);
719
+ console.log("\u2500".repeat(50));
720
+ if (result.changes.length === 0) {
721
+ console.log("\n\u2713 No changes detected");
722
+ return;
723
+ }
724
+ const added = result.changes.filter((c) => c.type === "added");
725
+ const removed = result.changes.filter((c) => c.type === "removed");
726
+ const changed = result.changes.filter((c) => c.type === "changed");
727
+ if (added.length > 0) {
728
+ console.log("\n+ Added:");
729
+ for (const change of added) {
730
+ const type = change.newValue ? formatType(change.newValue) : "unknown";
731
+ console.log(` ${change.path}: ${type}`);
732
+ }
733
+ }
734
+ if (removed.length > 0) {
735
+ console.log("\n- Removed:");
736
+ for (const change of removed) {
737
+ const type = change.oldValue ? formatType(change.oldValue) : "unknown";
738
+ console.log(` ${change.path}: ${type}`);
739
+ }
740
+ }
741
+ if (changed.length > 0) {
742
+ console.log("\n~ Changed:");
743
+ for (const change of changed) {
744
+ const oldType = change.oldValue ? formatType(change.oldValue) : "unknown";
745
+ const newType = change.newValue ? formatType(change.newValue) : "unknown";
746
+ console.log(` ${change.path}: ${oldType} \u2192 ${newType}`);
747
+ }
748
+ }
749
+ console.log("\n" + "\u2500".repeat(50));
750
+ console.log(
751
+ `Summary: +${added.length} -${removed.length} ~${changed.length}`
752
+ );
753
+ if (result.hasBreakingChanges) {
754
+ console.log("\n\u26A0 Breaking changes detected (removals or type changes)");
755
+ }
756
+ }
757
+ function printSchemaTree(node, indent) {
758
+ const prefix = " ".repeat(indent);
759
+ if (node.type === "object" && node.children) {
760
+ for (const [key, child] of Object.entries(node.children)) {
761
+ if (key === "__ref") continue;
762
+ const opt = child.optional ? "?" : "";
763
+ console.log(`${prefix}${key}${opt}: ${formatType(child)}`);
764
+ if (child.type === "object" && child.children) {
765
+ printSchemaTree(child, indent + 1);
766
+ }
767
+ }
768
+ } else {
769
+ console.log(`${prefix}${formatType(node)}`);
770
+ }
771
+ }
772
+ async function vaultQuickDiffCommand(options) {
773
+ const cwd = options.cwd ?? process.cwd();
774
+ const currentBranch = getCurrentBranch(cwd);
775
+ const baseBranch = gitRefExists("main", cwd) ? "main" : gitRefExists("master", cwd) ? "master" : null;
776
+ if (!baseBranch) {
777
+ console.error("Error: Cannot find main or master branch");
778
+ process.exit(1);
779
+ }
780
+ if (currentBranch === baseBranch) {
781
+ console.log(`Already on ${baseBranch}, nothing to diff`);
782
+ return;
783
+ }
784
+ console.log(`Comparing ${baseBranch} \u2192 ${currentBranch}
785
+ `);
786
+ await vaultDiffCommand(baseBranch, currentBranch, options);
787
+ }
788
+
260
789
  // src/cli.ts
261
790
  var require2 = createRequire(import.meta.url);
262
791
  var { version: VERSION } = require2("../package.json");
@@ -286,4 +815,9 @@ program.command("scaffold <type> <path>").description("Generate a colocated feat
286
815
  program.command("analyze-bff <bff-path>").description(
287
816
  "Analyze BFF to extract endpoint \u2192 permission \u2192 apiService mappings"
288
817
  ).option("-o, --output <file>", "Output JSON file path").option("--format <type>", "Output format: json, table", "json").action(analyzeBffCommand);
818
+ program.command("vault:diff <source-ref> <target-ref>").description(
819
+ "Compare Vault schemas between two git refs (branches, tags, commits)"
820
+ ).option("-f, --format <type>", "Output format: console, json", "console").option("--cwd <path>", "Working directory (git repo)").action(vaultDiffCommand);
821
+ program.command("vault:quick-diff").alias("vault:qd").description("Compare current branch vault schema against main/master").option("-f, --format <type>", "Output format: console, json", "console").option("--cwd <path>", "Working directory (git repo)").action(vaultQuickDiffCommand);
822
+ program.command("vault:extract <source>").description("Extract and display Vault schema from git ref or path").option("-f, --format <type>", "Output format: json, tree", "json").option("--cwd <path>", "Working directory (git repo)").action(vaultExtractCommand);
289
823
  program.parse();
@@ -3,7 +3,7 @@ import {
3
3
  analyzeCore,
4
4
  lintCore,
5
5
  scaffoldCore
6
- } from "./chunk-QTZTVZQA.js";
6
+ } from "./chunk-IBVI6IS2.js";
7
7
 
8
8
  // src/mcp-server.ts
9
9
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyphaene/hexa-ts-kit",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "TypeScript dev kit for Claude Code agents: architecture linting, scaffolding, knowledge analysis",
5
5
  "type": "module",
6
6
  "bin": {