@packmind/cli 0.4.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/main.cjs +968 -136
- package/package.json +1 -1
package/main.cjs
CHANGED
|
@@ -38,7 +38,7 @@ var require_package = __commonJS({
|
|
|
38
38
|
"apps/cli/package.json"(exports2, module2) {
|
|
39
39
|
module2.exports = {
|
|
40
40
|
name: "@packmind/cli",
|
|
41
|
-
version: "0.
|
|
41
|
+
version: "0.5.0",
|
|
42
42
|
description: "A command-line interface for Packmind linting and code quality checks",
|
|
43
43
|
private: false,
|
|
44
44
|
bin: {
|
|
@@ -259,38 +259,38 @@ var createRuleId = brandedIdFactory();
|
|
|
259
259
|
var createRuleExampleId = brandedIdFactory();
|
|
260
260
|
|
|
261
261
|
// packages/types/src/languages/ProgrammingLanguage.ts
|
|
262
|
-
var ProgrammingLanguage = /* @__PURE__ */ ((
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return
|
|
262
|
+
var ProgrammingLanguage = /* @__PURE__ */ ((ProgrammingLanguage4) => {
|
|
263
|
+
ProgrammingLanguage4["JAVASCRIPT"] = "JAVASCRIPT";
|
|
264
|
+
ProgrammingLanguage4["JAVASCRIPT_JSX"] = "JAVASCRIPT_JSX";
|
|
265
|
+
ProgrammingLanguage4["TYPESCRIPT"] = "TYPESCRIPT";
|
|
266
|
+
ProgrammingLanguage4["TYPESCRIPT_TSX"] = "TYPESCRIPT_TSX";
|
|
267
|
+
ProgrammingLanguage4["PYTHON"] = "PYTHON";
|
|
268
|
+
ProgrammingLanguage4["PHP"] = "PHP";
|
|
269
|
+
ProgrammingLanguage4["JAVA"] = "JAVA";
|
|
270
|
+
ProgrammingLanguage4["SCSS"] = "SCSS";
|
|
271
|
+
ProgrammingLanguage4["HTML"] = "HTML";
|
|
272
|
+
ProgrammingLanguage4["CSHARP"] = "CSHARP";
|
|
273
|
+
ProgrammingLanguage4["GENERIC"] = "GENERIC";
|
|
274
|
+
ProgrammingLanguage4["GO"] = "GO";
|
|
275
|
+
ProgrammingLanguage4["C"] = "C";
|
|
276
|
+
ProgrammingLanguage4["CPP"] = "CPP";
|
|
277
|
+
ProgrammingLanguage4["SQL"] = "SQL";
|
|
278
|
+
ProgrammingLanguage4["KOTLIN"] = "KOTLIN";
|
|
279
|
+
ProgrammingLanguage4["VUE"] = "VUE";
|
|
280
|
+
ProgrammingLanguage4["CSS"] = "CSS";
|
|
281
|
+
ProgrammingLanguage4["YAML"] = "YAML";
|
|
282
|
+
ProgrammingLanguage4["JSON"] = "JSON";
|
|
283
|
+
ProgrammingLanguage4["XML"] = "XML";
|
|
284
|
+
ProgrammingLanguage4["BASH"] = "BASH";
|
|
285
|
+
ProgrammingLanguage4["MARKDOWN"] = "MARKDOWN";
|
|
286
|
+
ProgrammingLanguage4["RUBY"] = "RUBY";
|
|
287
|
+
ProgrammingLanguage4["RUST"] = "RUST";
|
|
288
|
+
ProgrammingLanguage4["SAP_ABAP"] = "SAP_ABAP";
|
|
289
|
+
ProgrammingLanguage4["SAP_CDS"] = "SAP_CDS";
|
|
290
|
+
ProgrammingLanguage4["SAP_HANA_SQL"] = "SAP_HANA_SQL";
|
|
291
|
+
ProgrammingLanguage4["SWIFT"] = "SWIFT";
|
|
292
|
+
ProgrammingLanguage4["PROPERTIES"] = "PROPERTIES";
|
|
293
|
+
return ProgrammingLanguage4;
|
|
294
294
|
})(ProgrammingLanguage || {});
|
|
295
295
|
var ProgrammingLanguageDetails = {
|
|
296
296
|
["GENERIC" /* GENERIC */]: {
|
|
@@ -458,6 +458,262 @@ var createDetectionProgramId = brandedIdFactory();
|
|
|
458
458
|
// packages/types/src/linter/RuleDetectionAssessment.ts
|
|
459
459
|
var createRuleDetectionAssessmentId = brandedIdFactory();
|
|
460
460
|
|
|
461
|
+
// packages/types/src/llm/LLMProviderMetadata.ts
|
|
462
|
+
var DEFAULT_OPENAI_MODELS = {
|
|
463
|
+
model: "gpt-5.1",
|
|
464
|
+
fastestModel: "gpt-4.1-mini"
|
|
465
|
+
};
|
|
466
|
+
var DEFAULT_ANTHROPIC_MODELS = {
|
|
467
|
+
model: "claude-sonnet-4-5-20250929",
|
|
468
|
+
fastestModel: "claude-haiku-4-5-20251001"
|
|
469
|
+
};
|
|
470
|
+
var DEFAULT_GEMINI_MODELS = {
|
|
471
|
+
model: "gemini-3-pro-preview",
|
|
472
|
+
fastestModel: "gemini-2.5-flash"
|
|
473
|
+
};
|
|
474
|
+
var DEFAULT_AZURE_OPENAI_API_VERSION = "2024-12-01-preview";
|
|
475
|
+
var LLM_PROVIDER_METADATA = {
|
|
476
|
+
["openai" /* OPENAI */]: {
|
|
477
|
+
id: "openai" /* OPENAI */,
|
|
478
|
+
displayName: "OpenAI",
|
|
479
|
+
description: "OpenAI GPT models including GPT-4 and GPT-5. Requires an API key from OpenAI.",
|
|
480
|
+
defaultModel: DEFAULT_OPENAI_MODELS.model,
|
|
481
|
+
defaultFastModel: DEFAULT_OPENAI_MODELS.fastestModel,
|
|
482
|
+
documentationUrl: "https://platform.openai.com/docs",
|
|
483
|
+
fields: [
|
|
484
|
+
{
|
|
485
|
+
name: "apiKey",
|
|
486
|
+
label: "API Key",
|
|
487
|
+
type: "password",
|
|
488
|
+
defaultValue: "",
|
|
489
|
+
helpMessage: "Your OpenAI API key from platform.openai.com.",
|
|
490
|
+
optional: false,
|
|
491
|
+
placeholder: "sk-...",
|
|
492
|
+
secret: true
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: "model",
|
|
496
|
+
label: "Model",
|
|
497
|
+
type: "text",
|
|
498
|
+
defaultValue: DEFAULT_OPENAI_MODELS.model,
|
|
499
|
+
helpMessage: "The primary model to use for standard operations. Defaults to the latest recommended model.",
|
|
500
|
+
optional: true,
|
|
501
|
+
placeholder: "gpt-5.1",
|
|
502
|
+
secret: false
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
name: "fastestModel",
|
|
506
|
+
label: "Fast Model",
|
|
507
|
+
type: "text",
|
|
508
|
+
defaultValue: DEFAULT_OPENAI_MODELS.fastestModel,
|
|
509
|
+
helpMessage: "A faster, more economical model for less complex operations.",
|
|
510
|
+
optional: true,
|
|
511
|
+
placeholder: "gpt-4.1-mini",
|
|
512
|
+
secret: false
|
|
513
|
+
}
|
|
514
|
+
]
|
|
515
|
+
},
|
|
516
|
+
["anthropic" /* ANTHROPIC */]: {
|
|
517
|
+
id: "anthropic" /* ANTHROPIC */,
|
|
518
|
+
displayName: "Anthropic Claude",
|
|
519
|
+
description: "Anthropic Claude models known for safety and helpfulness. Requires an API key from Anthropic.",
|
|
520
|
+
defaultModel: DEFAULT_ANTHROPIC_MODELS.model,
|
|
521
|
+
defaultFastModel: DEFAULT_ANTHROPIC_MODELS.fastestModel,
|
|
522
|
+
documentationUrl: "https://docs.anthropic.com",
|
|
523
|
+
fields: [
|
|
524
|
+
{
|
|
525
|
+
name: "apiKey",
|
|
526
|
+
label: "API Key",
|
|
527
|
+
type: "password",
|
|
528
|
+
defaultValue: "",
|
|
529
|
+
helpMessage: "Your Anthropic API key from console.anthropic.com.",
|
|
530
|
+
optional: false,
|
|
531
|
+
placeholder: "sk-ant-...",
|
|
532
|
+
secret: true
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "model",
|
|
536
|
+
label: "Model",
|
|
537
|
+
type: "text",
|
|
538
|
+
defaultValue: DEFAULT_ANTHROPIC_MODELS.model,
|
|
539
|
+
helpMessage: "The primary Claude model to use. Defaults to the latest Sonnet model.",
|
|
540
|
+
optional: true,
|
|
541
|
+
placeholder: "claude-sonnet-4-5-20250929",
|
|
542
|
+
secret: false
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
name: "fastestModel",
|
|
546
|
+
label: "Fast Model",
|
|
547
|
+
type: "text",
|
|
548
|
+
defaultValue: DEFAULT_ANTHROPIC_MODELS.fastestModel,
|
|
549
|
+
helpMessage: "A faster Claude model for less complex operations. Defaults to Haiku.",
|
|
550
|
+
optional: true,
|
|
551
|
+
placeholder: "claude-haiku-4-5-20251001",
|
|
552
|
+
secret: false
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
},
|
|
556
|
+
["gemini" /* GEMINI */]: {
|
|
557
|
+
id: "gemini" /* GEMINI */,
|
|
558
|
+
displayName: "Google Gemini",
|
|
559
|
+
description: "Google's Gemini models with multimodal capabilities. Requires an API key from Google AI Studio.",
|
|
560
|
+
defaultModel: DEFAULT_GEMINI_MODELS.model,
|
|
561
|
+
defaultFastModel: DEFAULT_GEMINI_MODELS.fastestModel,
|
|
562
|
+
documentationUrl: "https://ai.google.dev/docs",
|
|
563
|
+
fields: [
|
|
564
|
+
{
|
|
565
|
+
name: "apiKey",
|
|
566
|
+
label: "API Key",
|
|
567
|
+
type: "password",
|
|
568
|
+
defaultValue: "",
|
|
569
|
+
helpMessage: "Your Google AI API key from aistudio.google.com.",
|
|
570
|
+
optional: false,
|
|
571
|
+
placeholder: "AIza...",
|
|
572
|
+
secret: true
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
name: "model",
|
|
576
|
+
label: "Model",
|
|
577
|
+
type: "text",
|
|
578
|
+
defaultValue: DEFAULT_GEMINI_MODELS.model,
|
|
579
|
+
helpMessage: "The primary Gemini model to use. Defaults to the latest Pro model.",
|
|
580
|
+
optional: true,
|
|
581
|
+
placeholder: "gemini-3-pro-preview",
|
|
582
|
+
secret: false
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
name: "fastestModel",
|
|
586
|
+
label: "Fast Model",
|
|
587
|
+
type: "text",
|
|
588
|
+
defaultValue: DEFAULT_GEMINI_MODELS.fastestModel,
|
|
589
|
+
helpMessage: "A faster Gemini model for less complex operations. Defaults to Flash.",
|
|
590
|
+
optional: true,
|
|
591
|
+
placeholder: "gemini-2.5-flash",
|
|
592
|
+
secret: false
|
|
593
|
+
}
|
|
594
|
+
]
|
|
595
|
+
},
|
|
596
|
+
["azure-openai" /* AZURE_OPENAI */]: {
|
|
597
|
+
id: "azure-openai" /* AZURE_OPENAI */,
|
|
598
|
+
displayName: "Azure OpenAI",
|
|
599
|
+
description: "Microsoft Azure-hosted OpenAI models. Requires Azure deployment names and credentials.",
|
|
600
|
+
defaultModel: "",
|
|
601
|
+
defaultFastModel: "",
|
|
602
|
+
documentationUrl: "https://learn.microsoft.com/en-us/azure/ai-services/openai/",
|
|
603
|
+
fields: [
|
|
604
|
+
{
|
|
605
|
+
name: "model",
|
|
606
|
+
label: "Model Deployment Name",
|
|
607
|
+
type: "text",
|
|
608
|
+
defaultValue: "",
|
|
609
|
+
helpMessage: "The Azure deployment name for the primary model. This is the name you gave your deployment in Azure Portal.",
|
|
610
|
+
optional: false,
|
|
611
|
+
placeholder: "my-gpt-4-deployment",
|
|
612
|
+
secret: false
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
name: "fastestModel",
|
|
616
|
+
label: "Fast Model Deployment Name",
|
|
617
|
+
type: "text",
|
|
618
|
+
defaultValue: "",
|
|
619
|
+
helpMessage: "The Azure deployment name for the fast/economical model.",
|
|
620
|
+
optional: false,
|
|
621
|
+
placeholder: "my-gpt-35-turbo-deployment",
|
|
622
|
+
secret: false
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
name: "endpoint",
|
|
626
|
+
label: "Endpoint URL",
|
|
627
|
+
type: "url",
|
|
628
|
+
defaultValue: "",
|
|
629
|
+
helpMessage: "Your Azure OpenAI endpoint URL.",
|
|
630
|
+
optional: false,
|
|
631
|
+
placeholder: "https://your-resource.openai.azure.com",
|
|
632
|
+
secret: false
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
name: "apiKey",
|
|
636
|
+
label: "API Key",
|
|
637
|
+
type: "password",
|
|
638
|
+
defaultValue: "",
|
|
639
|
+
helpMessage: "Your Azure OpenAI API key.",
|
|
640
|
+
optional: false,
|
|
641
|
+
placeholder: "",
|
|
642
|
+
secret: true
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
name: "apiVersion",
|
|
646
|
+
label: "API Version",
|
|
647
|
+
type: "text",
|
|
648
|
+
defaultValue: DEFAULT_AZURE_OPENAI_API_VERSION,
|
|
649
|
+
helpMessage: "The Azure OpenAI API version to use. Defaults to the latest stable version.",
|
|
650
|
+
optional: true,
|
|
651
|
+
placeholder: "2024-12-01-preview",
|
|
652
|
+
secret: false
|
|
653
|
+
}
|
|
654
|
+
]
|
|
655
|
+
},
|
|
656
|
+
["openai-compatible" /* OPENAI_COMPATIBLE */]: {
|
|
657
|
+
id: "openai-compatible" /* OPENAI_COMPATIBLE */,
|
|
658
|
+
displayName: "OpenAI-Compatible",
|
|
659
|
+
description: "Any OpenAI-compatible API endpoint. Use this for local models (Ollama, LM Studio) or other compatible providers.",
|
|
660
|
+
defaultModel: "",
|
|
661
|
+
defaultFastModel: "",
|
|
662
|
+
documentationUrl: void 0,
|
|
663
|
+
fields: [
|
|
664
|
+
{
|
|
665
|
+
name: "llmEndpoint",
|
|
666
|
+
label: "Endpoint URL",
|
|
667
|
+
type: "url",
|
|
668
|
+
defaultValue: "",
|
|
669
|
+
helpMessage: "The base URL of the OpenAI-compatible API endpoint (e.g., http://localhost:11434/v1 for Ollama).",
|
|
670
|
+
optional: false,
|
|
671
|
+
placeholder: "http://localhost:11434/v1",
|
|
672
|
+
secret: false
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
name: "llmApiKey",
|
|
676
|
+
label: "API Key",
|
|
677
|
+
type: "password",
|
|
678
|
+
defaultValue: "",
|
|
679
|
+
helpMessage: "API key for authentication. Some local providers may not require this.",
|
|
680
|
+
optional: false,
|
|
681
|
+
placeholder: "",
|
|
682
|
+
secret: true
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
name: "model",
|
|
686
|
+
label: "Model",
|
|
687
|
+
type: "text",
|
|
688
|
+
defaultValue: "",
|
|
689
|
+
helpMessage: "The model identifier to use for standard operations (e.g., llama3, mistral).",
|
|
690
|
+
optional: false,
|
|
691
|
+
placeholder: "llama3",
|
|
692
|
+
secret: false
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
name: "fastestModel",
|
|
696
|
+
label: "Fast Model",
|
|
697
|
+
type: "text",
|
|
698
|
+
defaultValue: "",
|
|
699
|
+
helpMessage: "A faster model for less complex operations. Can be the same as the primary model.",
|
|
700
|
+
optional: false,
|
|
701
|
+
placeholder: "llama3",
|
|
702
|
+
secret: false
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
},
|
|
706
|
+
["packmind" /* PACKMIND */]: {
|
|
707
|
+
id: "packmind" /* PACKMIND */,
|
|
708
|
+
displayName: "Packmind (SaaS)",
|
|
709
|
+
description: "Packmind managed LLM service. Uses the platform default provider configuration.",
|
|
710
|
+
defaultModel: DEFAULT_OPENAI_MODELS.model,
|
|
711
|
+
defaultFastModel: DEFAULT_OPENAI_MODELS.fastestModel,
|
|
712
|
+
documentationUrl: void 0,
|
|
713
|
+
fields: []
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
|
|
461
717
|
// packages/types/src/sse/SSEEvent.ts
|
|
462
718
|
function createProgramStatusChangeEvent(ruleId, language) {
|
|
463
719
|
return {
|
|
@@ -543,27 +799,34 @@ var GitService = class {
|
|
|
543
799
|
constructor(logger2 = new PackmindLogger(origin)) {
|
|
544
800
|
this.logger = logger2;
|
|
545
801
|
}
|
|
546
|
-
async getGitRepositoryRoot(
|
|
802
|
+
async getGitRepositoryRoot(path7) {
|
|
547
803
|
try {
|
|
548
804
|
const { stdout } = await execAsync("git rev-parse --show-toplevel", {
|
|
549
|
-
cwd:
|
|
805
|
+
cwd: path7
|
|
550
806
|
});
|
|
551
807
|
const gitRoot = stdout.trim();
|
|
552
808
|
this.logger.debug("Resolved git repository root", {
|
|
553
|
-
inputPath:
|
|
809
|
+
inputPath: path7,
|
|
554
810
|
gitRoot
|
|
555
811
|
});
|
|
556
812
|
return gitRoot;
|
|
557
813
|
} catch (error) {
|
|
558
814
|
if (error instanceof Error) {
|
|
559
815
|
throw new Error(
|
|
560
|
-
`Failed to get Git repository root. The path '${
|
|
816
|
+
`Failed to get Git repository root. The path '${path7}' does not appear to be inside a Git repository.
|
|
561
817
|
${error.message}`
|
|
562
818
|
);
|
|
563
819
|
}
|
|
564
820
|
throw new Error("Failed to get Git repository root: Unknown error");
|
|
565
821
|
}
|
|
566
822
|
}
|
|
823
|
+
async tryGetGitRepositoryRoot(path7) {
|
|
824
|
+
try {
|
|
825
|
+
return await this.getGitRepositoryRoot(path7);
|
|
826
|
+
} catch {
|
|
827
|
+
return null;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
567
830
|
async getCurrentBranches(repoPath) {
|
|
568
831
|
try {
|
|
569
832
|
const { stdout } = await execAsync("git branch -a --contains HEAD", {
|
|
@@ -581,7 +844,7 @@ ${error.message}`
|
|
|
581
844
|
throw new Error("Failed to get Git branches: Unknown error");
|
|
582
845
|
}
|
|
583
846
|
}
|
|
584
|
-
async getGitRemoteUrl(repoPath,
|
|
847
|
+
async getGitRemoteUrl(repoPath, origin11) {
|
|
585
848
|
try {
|
|
586
849
|
const { stdout } = await execAsync("git remote -v", {
|
|
587
850
|
cwd: repoPath
|
|
@@ -591,10 +854,10 @@ ${error.message}`
|
|
|
591
854
|
throw new Error("No Git remotes found in the repository");
|
|
592
855
|
}
|
|
593
856
|
let selectedRemote;
|
|
594
|
-
if (
|
|
595
|
-
const foundRemote = remotes.find((remote) => remote.name ===
|
|
857
|
+
if (origin11) {
|
|
858
|
+
const foundRemote = remotes.find((remote) => remote.name === origin11);
|
|
596
859
|
if (!foundRemote) {
|
|
597
|
-
throw new Error(`Remote '${
|
|
860
|
+
throw new Error(`Remote '${origin11}' not found in repository`);
|
|
598
861
|
}
|
|
599
862
|
selectedRemote = foundRemote.url;
|
|
600
863
|
} else if (remotes.length === 1) {
|
|
@@ -664,14 +927,14 @@ ${error.message}`
|
|
|
664
927
|
normalizeGitUrl(url) {
|
|
665
928
|
const sshMatch = url.match(/^git@([^:]+):(.+)$/);
|
|
666
929
|
if (sshMatch) {
|
|
667
|
-
const [, host,
|
|
668
|
-
const cleanPath =
|
|
930
|
+
const [, host, path7] = sshMatch;
|
|
931
|
+
const cleanPath = path7.replace(/\.git$/, "");
|
|
669
932
|
return `${host}/${cleanPath}`;
|
|
670
933
|
}
|
|
671
934
|
const httpsMatch = url.match(/^https?:\/\/([^/]+)\/(.+)$/);
|
|
672
935
|
if (httpsMatch) {
|
|
673
|
-
const [, host,
|
|
674
|
-
const cleanPath =
|
|
936
|
+
const [, host, path7] = httpsMatch;
|
|
937
|
+
const cleanPath = path7.replace(/\.git$/, "");
|
|
675
938
|
return `${host}/${cleanPath}`;
|
|
676
939
|
}
|
|
677
940
|
return url;
|
|
@@ -684,8 +947,8 @@ var GetGitRemoteUrlUseCase = class {
|
|
|
684
947
|
this.gitRemoteUrlService = gitRemoteUrlService;
|
|
685
948
|
}
|
|
686
949
|
async execute(command3) {
|
|
687
|
-
const { path: repoPath, origin:
|
|
688
|
-
return this.gitRemoteUrlService.getGitRemoteUrl(repoPath,
|
|
950
|
+
const { path: repoPath, origin: origin11 } = command3;
|
|
951
|
+
return this.gitRemoteUrlService.getGitRemoteUrl(repoPath, origin11);
|
|
689
952
|
}
|
|
690
953
|
};
|
|
691
954
|
|
|
@@ -1150,6 +1413,224 @@ var LintFilesInDirectoryUseCase = class {
|
|
|
1150
1413
|
}
|
|
1151
1414
|
};
|
|
1152
1415
|
|
|
1416
|
+
// apps/cli/src/application/useCases/LintFilesLocallyUseCase.ts
|
|
1417
|
+
var import_minimatch2 = require("minimatch");
|
|
1418
|
+
var path3 = __toESM(require("path"));
|
|
1419
|
+
var fs3 = __toESM(require("fs/promises"));
|
|
1420
|
+
var origin3 = "LintFilesLocallyUseCase";
|
|
1421
|
+
var LintFilesLocallyUseCase = class {
|
|
1422
|
+
constructor(services, repositories, logger2 = new PackmindLogger(origin3)) {
|
|
1423
|
+
this.services = services;
|
|
1424
|
+
this.repositories = repositories;
|
|
1425
|
+
this.logger = logger2;
|
|
1426
|
+
}
|
|
1427
|
+
fileMatchesTargetAndScope(filePath, targetPath, scopePatterns) {
|
|
1428
|
+
if (!scopePatterns || scopePatterns.length === 0) {
|
|
1429
|
+
const effectivePattern = this.buildEffectivePattern(targetPath, null);
|
|
1430
|
+
return (0, import_minimatch2.minimatch)(filePath, effectivePattern, { matchBase: false });
|
|
1431
|
+
}
|
|
1432
|
+
return scopePatterns.some((scopePattern) => {
|
|
1433
|
+
const effectivePattern = this.buildEffectivePattern(
|
|
1434
|
+
targetPath,
|
|
1435
|
+
scopePattern
|
|
1436
|
+
);
|
|
1437
|
+
return (0, import_minimatch2.minimatch)(filePath, effectivePattern, { matchBase: false });
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
buildEffectivePattern(targetPath, scope) {
|
|
1441
|
+
const normalizedTarget = targetPath === "/" ? "/" : targetPath.replace(/\/$/, "");
|
|
1442
|
+
if (!scope) {
|
|
1443
|
+
return normalizedTarget === "/" ? "/**" : normalizedTarget + "/**";
|
|
1444
|
+
}
|
|
1445
|
+
if (scope.startsWith(normalizedTarget + "/") || scope === normalizedTarget) {
|
|
1446
|
+
return scope.endsWith("/") ? scope + "**" : scope;
|
|
1447
|
+
}
|
|
1448
|
+
const cleanScope = scope.startsWith("/") ? scope.substring(1) : scope;
|
|
1449
|
+
let pattern;
|
|
1450
|
+
if (normalizedTarget === "/") {
|
|
1451
|
+
pattern = "/" + cleanScope;
|
|
1452
|
+
} else {
|
|
1453
|
+
pattern = normalizedTarget + "/" + cleanScope;
|
|
1454
|
+
}
|
|
1455
|
+
if (pattern.endsWith("/")) {
|
|
1456
|
+
pattern = pattern + "**";
|
|
1457
|
+
}
|
|
1458
|
+
return pattern;
|
|
1459
|
+
}
|
|
1460
|
+
async execute(command3) {
|
|
1461
|
+
const { path: userPath } = command3;
|
|
1462
|
+
this.logger.debug(`Starting local linting: path="${userPath}"`);
|
|
1463
|
+
const absoluteUserPath = path3.isAbsolute(userPath) ? userPath : path3.resolve(process.cwd(), userPath);
|
|
1464
|
+
let pathStats;
|
|
1465
|
+
try {
|
|
1466
|
+
pathStats = await fs3.stat(absoluteUserPath);
|
|
1467
|
+
} catch {
|
|
1468
|
+
throw new Error(
|
|
1469
|
+
`The path "${absoluteUserPath}" does not exist or cannot be accessed`
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
const isFile = pathStats.isFile();
|
|
1473
|
+
const directoryForConfig = isFile ? path3.dirname(absoluteUserPath) : absoluteUserPath;
|
|
1474
|
+
const gitRepoRoot = await this.services.gitRemoteUrlService.tryGetGitRepositoryRoot(
|
|
1475
|
+
directoryForConfig
|
|
1476
|
+
);
|
|
1477
|
+
const hierarchicalConfig = await this.repositories.configFileRepository.readHierarchicalConfig(
|
|
1478
|
+
directoryForConfig,
|
|
1479
|
+
gitRepoRoot
|
|
1480
|
+
);
|
|
1481
|
+
if (!hierarchicalConfig.hasConfigs) {
|
|
1482
|
+
const boundary = gitRepoRoot ?? "filesystem root";
|
|
1483
|
+
throw new Error(
|
|
1484
|
+
`No packmind.json found between ${directoryForConfig} and ${boundary}. Cannot use local linting.`
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
const basePath = gitRepoRoot ?? directoryForConfig;
|
|
1488
|
+
this.logger.debug(
|
|
1489
|
+
`Found ${hierarchicalConfig.configPaths.length} packmind.json file(s)`
|
|
1490
|
+
);
|
|
1491
|
+
for (const configPath of hierarchicalConfig.configPaths) {
|
|
1492
|
+
this.logger.debug(`Using config: ${configPath}`);
|
|
1493
|
+
}
|
|
1494
|
+
const packageSlugs = Object.keys(hierarchicalConfig.packages);
|
|
1495
|
+
this.logger.debug(
|
|
1496
|
+
`Merged ${packageSlugs.length} packages from configuration files`
|
|
1497
|
+
);
|
|
1498
|
+
const detectionPrograms = await this.repositories.packmindGateway.getDetectionProgramsForPackages({
|
|
1499
|
+
packagesSlugs: packageSlugs
|
|
1500
|
+
});
|
|
1501
|
+
this.logger.debug(
|
|
1502
|
+
`Retrieved detection programs: targetsCount=${detectionPrograms.targets.length}`
|
|
1503
|
+
);
|
|
1504
|
+
const files = isFile ? [{ path: absoluteUserPath }] : await this.services.listFiles.listFilesInDirectory(
|
|
1505
|
+
absoluteUserPath,
|
|
1506
|
+
[],
|
|
1507
|
+
["node_modules", "dist", ".min.", ".map.", ".git"]
|
|
1508
|
+
);
|
|
1509
|
+
this.logger.debug(`Found ${files.length} files to lint`);
|
|
1510
|
+
const violations = [];
|
|
1511
|
+
for (const file of files) {
|
|
1512
|
+
const fileViolations = [];
|
|
1513
|
+
const relativeFilePath = file.path.startsWith(basePath) ? file.path.substring(basePath.length) : file.path;
|
|
1514
|
+
const normalizedFilePath = relativeFilePath.startsWith("/") ? relativeFilePath : "/" + relativeFilePath;
|
|
1515
|
+
this.logger.debug(
|
|
1516
|
+
`Processing file: absolute="${file.path}", relative="${normalizedFilePath}"`
|
|
1517
|
+
);
|
|
1518
|
+
const fileExtension = this.extractExtensionFromFile(file.path);
|
|
1519
|
+
const fileLanguage = this.resolveProgrammingLanguage(fileExtension);
|
|
1520
|
+
if (!fileLanguage) {
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
const programsByLanguage = /* @__PURE__ */ new Map();
|
|
1524
|
+
for (const target of detectionPrograms.targets) {
|
|
1525
|
+
for (const standard of target.standards) {
|
|
1526
|
+
if (!this.fileMatchesTargetAndScope(
|
|
1527
|
+
normalizedFilePath,
|
|
1528
|
+
target.path,
|
|
1529
|
+
standard.scope
|
|
1530
|
+
)) {
|
|
1531
|
+
continue;
|
|
1532
|
+
}
|
|
1533
|
+
for (const rule of standard.rules) {
|
|
1534
|
+
for (const activeProgram of rule.activeDetectionPrograms) {
|
|
1535
|
+
try {
|
|
1536
|
+
const programLanguage = this.resolveProgrammingLanguage(
|
|
1537
|
+
activeProgram.language
|
|
1538
|
+
);
|
|
1539
|
+
if (!programLanguage || programLanguage !== fileLanguage) {
|
|
1540
|
+
continue;
|
|
1541
|
+
}
|
|
1542
|
+
const programsForLanguage = programsByLanguage.get(programLanguage) ?? [];
|
|
1543
|
+
programsForLanguage.push({
|
|
1544
|
+
code: activeProgram.detectionProgram.code,
|
|
1545
|
+
ruleContent: rule.content,
|
|
1546
|
+
standardSlug: standard.slug,
|
|
1547
|
+
sourceCodeState: activeProgram.detectionProgram.sourceCodeState,
|
|
1548
|
+
language: fileLanguage
|
|
1549
|
+
});
|
|
1550
|
+
programsByLanguage.set(programLanguage, programsForLanguage);
|
|
1551
|
+
} catch (error) {
|
|
1552
|
+
console.error(
|
|
1553
|
+
`Error preparing program for file ${file.path}: ${error}`
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
if (programsByLanguage.size > 0) {
|
|
1561
|
+
try {
|
|
1562
|
+
const fileContent = await this.services.listFiles.readFileContent(
|
|
1563
|
+
file.path
|
|
1564
|
+
);
|
|
1565
|
+
for (const [language, programs] of programsByLanguage.entries()) {
|
|
1566
|
+
try {
|
|
1567
|
+
const result = await this.executeProgramsForFile({
|
|
1568
|
+
filePath: file.path,
|
|
1569
|
+
fileContent,
|
|
1570
|
+
language,
|
|
1571
|
+
programs
|
|
1572
|
+
});
|
|
1573
|
+
fileViolations.push(...result);
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
console.error(
|
|
1576
|
+
`Error executing programs for file ${file.path} (${language}): ${error}`
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
} catch (error) {
|
|
1581
|
+
console.error(
|
|
1582
|
+
`Error reading file content for ${file.path}: ${error}`
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
if (fileViolations.length > 0) {
|
|
1587
|
+
violations.push({
|
|
1588
|
+
file: file.path,
|
|
1589
|
+
violations: fileViolations
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
const totalViolations = violations.reduce(
|
|
1594
|
+
(sum, violation) => sum + violation.violations.length,
|
|
1595
|
+
0
|
|
1596
|
+
);
|
|
1597
|
+
const standardsChecked = Array.from(
|
|
1598
|
+
new Set(
|
|
1599
|
+
detectionPrograms.targets.flatMap(
|
|
1600
|
+
(target) => target.standards.map((standard) => standard.slug)
|
|
1601
|
+
)
|
|
1602
|
+
)
|
|
1603
|
+
);
|
|
1604
|
+
return {
|
|
1605
|
+
violations,
|
|
1606
|
+
summary: {
|
|
1607
|
+
totalFiles: files.length,
|
|
1608
|
+
violatedFiles: violations.length,
|
|
1609
|
+
totalViolations,
|
|
1610
|
+
standardsChecked
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
resolveProgrammingLanguage(language) {
|
|
1615
|
+
try {
|
|
1616
|
+
return stringToProgrammingLanguage(language);
|
|
1617
|
+
} catch {
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
async executeProgramsForFile(command3) {
|
|
1622
|
+
const result = await this.services.linterExecutionUseCase.execute(command3);
|
|
1623
|
+
return result.violations;
|
|
1624
|
+
}
|
|
1625
|
+
extractExtensionFromFile(filePath) {
|
|
1626
|
+
const lastDotIndex = filePath.lastIndexOf(".");
|
|
1627
|
+
if (lastDotIndex === -1 || lastDotIndex === filePath.length - 1) {
|
|
1628
|
+
return "";
|
|
1629
|
+
}
|
|
1630
|
+
return filePath.substring(lastDotIndex + 1);
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1153
1634
|
// apps/cli/src/infra/repositories/PackmindGateway.ts
|
|
1154
1635
|
function decodeJwt(jwt) {
|
|
1155
1636
|
try {
|
|
@@ -1256,7 +1737,7 @@ var PackmindGateway = class {
|
|
|
1256
1737
|
);
|
|
1257
1738
|
}
|
|
1258
1739
|
throw new Error(
|
|
1259
|
-
`Failed to
|
|
1740
|
+
`Failed to fetch content: Error: ${err?.message || JSON.stringify(error)}`
|
|
1260
1741
|
);
|
|
1261
1742
|
}
|
|
1262
1743
|
};
|
|
@@ -1536,6 +2017,51 @@ var PackmindGateway = class {
|
|
|
1536
2017
|
);
|
|
1537
2018
|
}
|
|
1538
2019
|
};
|
|
2020
|
+
this.getDetectionProgramsForPackages = async (params) => {
|
|
2021
|
+
const decodedApiKey = decodeApiKey(this.apiKey);
|
|
2022
|
+
if (!decodedApiKey.isValid) {
|
|
2023
|
+
throw new Error(`Invalid API key: ${decodedApiKey.error}`);
|
|
2024
|
+
}
|
|
2025
|
+
const { host } = decodedApiKey.payload;
|
|
2026
|
+
const url = `${host}/api/v0/detection-programs-for-packages`;
|
|
2027
|
+
const payload = {
|
|
2028
|
+
packagesSlugs: params.packagesSlugs
|
|
2029
|
+
};
|
|
2030
|
+
try {
|
|
2031
|
+
const response = await fetch(url, {
|
|
2032
|
+
method: "POST",
|
|
2033
|
+
headers: {
|
|
2034
|
+
"Content-Type": "application/json",
|
|
2035
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
2036
|
+
},
|
|
2037
|
+
body: JSON.stringify(payload)
|
|
2038
|
+
});
|
|
2039
|
+
if (!response.ok) {
|
|
2040
|
+
let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
|
|
2041
|
+
try {
|
|
2042
|
+
const errorBody = await response.json();
|
|
2043
|
+
if (errorBody && errorBody.message) {
|
|
2044
|
+
errorMsg = `${errorBody.message}`;
|
|
2045
|
+
}
|
|
2046
|
+
} catch {
|
|
2047
|
+
}
|
|
2048
|
+
throw new Error(errorMsg);
|
|
2049
|
+
}
|
|
2050
|
+
const result = await response.json();
|
|
2051
|
+
return result;
|
|
2052
|
+
} catch (error) {
|
|
2053
|
+
const err = error;
|
|
2054
|
+
const code = err?.code || err?.cause?.code;
|
|
2055
|
+
if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
|
|
2056
|
+
throw new Error(
|
|
2057
|
+
`Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
throw new Error(
|
|
2061
|
+
`Failed to fetch detection programs for packages: Error: ${err?.message || JSON.stringify(error)}`
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
1539
2065
|
}
|
|
1540
2066
|
};
|
|
1541
2067
|
|
|
@@ -3208,9 +3734,9 @@ var LinterAstAdapter = class {
|
|
|
3208
3734
|
var TreeSitter17 = __toESM(require("web-tree-sitter"));
|
|
3209
3735
|
|
|
3210
3736
|
// packages/linter-execution/src/application/useCases/ExecuteLinterProgramsUseCase.ts
|
|
3211
|
-
var
|
|
3737
|
+
var origin4 = "ExecuteLinterProgramsUseCase";
|
|
3212
3738
|
var ExecuteLinterProgramsUseCase = class {
|
|
3213
|
-
constructor(linterAstAdapter = new LinterAstAdapter(), logger2 = new PackmindLogger(
|
|
3739
|
+
constructor(linterAstAdapter = new LinterAstAdapter(), logger2 = new PackmindLogger(origin4)) {
|
|
3214
3740
|
this.linterAstAdapter = linterAstAdapter;
|
|
3215
3741
|
this.logger = logger2;
|
|
3216
3742
|
}
|
|
@@ -3405,14 +3931,30 @@ var ExecuteLinterProgramsUseCase = class {
|
|
|
3405
3931
|
}
|
|
3406
3932
|
};
|
|
3407
3933
|
|
|
3408
|
-
// packages/node-utils/src/
|
|
3409
|
-
var
|
|
3934
|
+
// packages/node-utils/src/dataSources/local.ts
|
|
3935
|
+
var import_typeorm = require("typeorm");
|
|
3936
|
+
var dataSource = makeDatasource();
|
|
3937
|
+
function makeDatasource() {
|
|
3938
|
+
try {
|
|
3939
|
+
return new import_typeorm.DataSource({
|
|
3940
|
+
type: "postgres",
|
|
3941
|
+
url: process.env["DATABASE_URL"],
|
|
3942
|
+
entities: [],
|
|
3943
|
+
migrations: []
|
|
3944
|
+
});
|
|
3945
|
+
} catch {
|
|
3946
|
+
return {};
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3950
|
+
// packages/node-utils/src/cache/Cache.ts
|
|
3951
|
+
var import_ioredis = __toESM(require("ioredis"));
|
|
3410
3952
|
|
|
3411
3953
|
// packages/node-utils/src/config/infra/Infisical/InfisicalConfig.ts
|
|
3412
3954
|
var import_sdk = require("@infisical/sdk");
|
|
3413
|
-
var
|
|
3955
|
+
var origin5 = "InfisicalConfig";
|
|
3414
3956
|
var InfisicalConfig = class {
|
|
3415
|
-
constructor(clientId, clientSecret, env, projectId, logger2 = new PackmindLogger(
|
|
3957
|
+
constructor(clientId, clientSecret, env, projectId, logger2 = new PackmindLogger(origin5)) {
|
|
3416
3958
|
this.clientId = clientId;
|
|
3417
3959
|
this.clientSecret = clientSecret;
|
|
3418
3960
|
this.env = env;
|
|
@@ -3487,7 +4029,7 @@ var InfisicalConfig = class {
|
|
|
3487
4029
|
};
|
|
3488
4030
|
|
|
3489
4031
|
// packages/node-utils/src/config/config/Configuration.ts
|
|
3490
|
-
var
|
|
4032
|
+
var origin6 = "Configuration";
|
|
3491
4033
|
var Configuration = class _Configuration {
|
|
3492
4034
|
constructor() {
|
|
3493
4035
|
this.initialized = false;
|
|
@@ -3495,7 +4037,7 @@ var Configuration = class _Configuration {
|
|
|
3495
4037
|
}
|
|
3496
4038
|
static {
|
|
3497
4039
|
this.logger = new PackmindLogger(
|
|
3498
|
-
|
|
4040
|
+
origin6,
|
|
3499
4041
|
"info" /* INFO */
|
|
3500
4042
|
);
|
|
3501
4043
|
}
|
|
@@ -3642,8 +4184,7 @@ var Configuration = class _Configuration {
|
|
|
3642
4184
|
};
|
|
3643
4185
|
|
|
3644
4186
|
// packages/node-utils/src/cache/Cache.ts
|
|
3645
|
-
var
|
|
3646
|
-
var origin6 = "Cache";
|
|
4187
|
+
var origin7 = "Cache";
|
|
3647
4188
|
var Cache = class _Cache {
|
|
3648
4189
|
constructor() {
|
|
3649
4190
|
this.initialized = false;
|
|
@@ -3655,7 +4196,7 @@ var Cache = class _Cache {
|
|
|
3655
4196
|
}
|
|
3656
4197
|
static {
|
|
3657
4198
|
this.logger = new PackmindLogger(
|
|
3658
|
-
|
|
4199
|
+
origin7,
|
|
3659
4200
|
"info" /* INFO */
|
|
3660
4201
|
);
|
|
3661
4202
|
}
|
|
@@ -3837,14 +4378,14 @@ var import_common2 = require("@nestjs/common");
|
|
|
3837
4378
|
|
|
3838
4379
|
// packages/node-utils/src/sse/RedisSSEClient.ts
|
|
3839
4380
|
var import_ioredis2 = __toESM(require("ioredis"));
|
|
3840
|
-
var
|
|
4381
|
+
var origin8 = "RedisSSEClient";
|
|
3841
4382
|
var RedisSSEClient = class _RedisSSEClient {
|
|
3842
4383
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
3843
4384
|
constructor() {
|
|
3844
4385
|
this.initialized = false;
|
|
3845
4386
|
}
|
|
3846
4387
|
static {
|
|
3847
|
-
this.logger = new PackmindLogger(
|
|
4388
|
+
this.logger = new PackmindLogger(origin8);
|
|
3848
4389
|
}
|
|
3849
4390
|
static getInstance() {
|
|
3850
4391
|
_RedisSSEClient.logger.debug("Getting RedisSSEClient instance");
|
|
@@ -4028,10 +4569,10 @@ function serializeSSERedisMessage(message) {
|
|
|
4028
4569
|
}
|
|
4029
4570
|
|
|
4030
4571
|
// packages/node-utils/src/sse/SSEEventPublisher.ts
|
|
4031
|
-
var
|
|
4572
|
+
var origin9 = "SSEEventPublisher";
|
|
4032
4573
|
var SSEEventPublisher = class _SSEEventPublisher {
|
|
4033
4574
|
static {
|
|
4034
|
-
this.logger = new PackmindLogger(
|
|
4575
|
+
this.logger = new PackmindLogger(origin9);
|
|
4035
4576
|
}
|
|
4036
4577
|
/**
|
|
4037
4578
|
* Get the singleton instance
|
|
@@ -4270,25 +4811,9 @@ ${sectionBlock}
|
|
|
4270
4811
|
return result;
|
|
4271
4812
|
}
|
|
4272
4813
|
|
|
4273
|
-
// packages/node-utils/src/dataSources/local.ts
|
|
4274
|
-
var import_typeorm = require("typeorm");
|
|
4275
|
-
var dataSource = makeDatasource();
|
|
4276
|
-
function makeDatasource() {
|
|
4277
|
-
try {
|
|
4278
|
-
return new import_typeorm.DataSource({
|
|
4279
|
-
type: "postgres",
|
|
4280
|
-
url: process.env["DATABASE_URL"],
|
|
4281
|
-
entities: [],
|
|
4282
|
-
migrations: []
|
|
4283
|
-
});
|
|
4284
|
-
} catch {
|
|
4285
|
-
return {};
|
|
4286
|
-
}
|
|
4287
|
-
}
|
|
4288
|
-
|
|
4289
4814
|
// apps/cli/src/application/useCases/PullDataUseCase.ts
|
|
4290
|
-
var
|
|
4291
|
-
var
|
|
4815
|
+
var fs4 = __toESM(require("fs/promises"));
|
|
4816
|
+
var path4 = __toESM(require("path"));
|
|
4292
4817
|
var PullDataUseCase = class {
|
|
4293
4818
|
constructor(packmindGateway) {
|
|
4294
4819
|
this.packmindGateway = packmindGateway;
|
|
@@ -4299,13 +4824,27 @@ var PullDataUseCase = class {
|
|
|
4299
4824
|
filesCreated: 0,
|
|
4300
4825
|
filesUpdated: 0,
|
|
4301
4826
|
filesDeleted: 0,
|
|
4302
|
-
errors: []
|
|
4827
|
+
errors: [],
|
|
4828
|
+
recipesCount: 0,
|
|
4829
|
+
standardsCount: 0
|
|
4303
4830
|
};
|
|
4304
4831
|
const response = await this.packmindGateway.getPullData({
|
|
4305
4832
|
packagesSlugs: command3.packagesSlugs
|
|
4306
4833
|
});
|
|
4834
|
+
const uniqueFilesMap = /* @__PURE__ */ new Map();
|
|
4835
|
+
for (const file of response.fileUpdates.createOrUpdate) {
|
|
4836
|
+
uniqueFilesMap.set(file.path, file);
|
|
4837
|
+
}
|
|
4838
|
+
const uniqueFiles = Array.from(uniqueFilesMap.values());
|
|
4839
|
+
for (const file of uniqueFiles) {
|
|
4840
|
+
if (file.path.includes(".packmind/recipes/") && file.path.endsWith(".md")) {
|
|
4841
|
+
result.recipesCount++;
|
|
4842
|
+
} else if (file.path.includes(".packmind/standards/") && file.path.endsWith(".md")) {
|
|
4843
|
+
result.standardsCount++;
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4307
4846
|
try {
|
|
4308
|
-
for (const file of
|
|
4847
|
+
for (const file of uniqueFiles) {
|
|
4309
4848
|
try {
|
|
4310
4849
|
await this.createOrUpdateFile(baseDirectory, file, result);
|
|
4311
4850
|
} catch (error) {
|
|
@@ -4330,9 +4869,9 @@ var PullDataUseCase = class {
|
|
|
4330
4869
|
return result;
|
|
4331
4870
|
}
|
|
4332
4871
|
async createOrUpdateFile(baseDirectory, file, result) {
|
|
4333
|
-
const fullPath =
|
|
4334
|
-
const directory =
|
|
4335
|
-
await
|
|
4872
|
+
const fullPath = path4.join(baseDirectory, file.path);
|
|
4873
|
+
const directory = path4.dirname(fullPath);
|
|
4874
|
+
await fs4.mkdir(directory, { recursive: true });
|
|
4336
4875
|
const fileExists = await this.fileExists(fullPath);
|
|
4337
4876
|
if (file.content !== void 0) {
|
|
4338
4877
|
await this.handleFullContentUpdate(
|
|
@@ -4352,7 +4891,7 @@ var PullDataUseCase = class {
|
|
|
4352
4891
|
}
|
|
4353
4892
|
async handleFullContentUpdate(fullPath, content, fileExists, result) {
|
|
4354
4893
|
if (fileExists) {
|
|
4355
|
-
const existingContent = await
|
|
4894
|
+
const existingContent = await fs4.readFile(fullPath, "utf-8");
|
|
4356
4895
|
const commentMarker = this.extractCommentMarker(content);
|
|
4357
4896
|
let finalContent;
|
|
4358
4897
|
if (!commentMarker) {
|
|
@@ -4364,23 +4903,23 @@ var PullDataUseCase = class {
|
|
|
4364
4903
|
commentMarker
|
|
4365
4904
|
);
|
|
4366
4905
|
}
|
|
4367
|
-
await
|
|
4906
|
+
await fs4.writeFile(fullPath, finalContent, "utf-8");
|
|
4368
4907
|
result.filesUpdated++;
|
|
4369
4908
|
} else {
|
|
4370
|
-
await
|
|
4909
|
+
await fs4.writeFile(fullPath, content, "utf-8");
|
|
4371
4910
|
result.filesCreated++;
|
|
4372
4911
|
}
|
|
4373
4912
|
}
|
|
4374
4913
|
async handleSectionsUpdate(fullPath, sections, fileExists, result) {
|
|
4375
4914
|
let currentContent = "";
|
|
4376
4915
|
if (fileExists) {
|
|
4377
|
-
currentContent = await
|
|
4916
|
+
currentContent = await fs4.readFile(fullPath, "utf-8");
|
|
4378
4917
|
}
|
|
4379
4918
|
const mergedContent = mergeSectionsIntoFileContent(
|
|
4380
4919
|
currentContent,
|
|
4381
4920
|
sections
|
|
4382
4921
|
);
|
|
4383
|
-
await
|
|
4922
|
+
await fs4.writeFile(fullPath, mergedContent, "utf-8");
|
|
4384
4923
|
if (fileExists) {
|
|
4385
4924
|
result.filesUpdated++;
|
|
4386
4925
|
} else {
|
|
@@ -4388,16 +4927,16 @@ var PullDataUseCase = class {
|
|
|
4388
4927
|
}
|
|
4389
4928
|
}
|
|
4390
4929
|
async deleteFile(baseDirectory, filePath, result) {
|
|
4391
|
-
const fullPath =
|
|
4930
|
+
const fullPath = path4.join(baseDirectory, filePath);
|
|
4392
4931
|
const fileExists = await this.fileExists(fullPath);
|
|
4393
4932
|
if (fileExists) {
|
|
4394
|
-
await
|
|
4933
|
+
await fs4.unlink(fullPath);
|
|
4395
4934
|
result.filesDeleted++;
|
|
4396
4935
|
}
|
|
4397
4936
|
}
|
|
4398
4937
|
async fileExists(filePath) {
|
|
4399
4938
|
try {
|
|
4400
|
-
await
|
|
4939
|
+
await fs4.access(filePath);
|
|
4401
4940
|
return true;
|
|
4402
4941
|
} catch {
|
|
4403
4942
|
return false;
|
|
@@ -4470,6 +5009,126 @@ var GetPackageSummaryUseCase = class {
|
|
|
4470
5009
|
}
|
|
4471
5010
|
};
|
|
4472
5011
|
|
|
5012
|
+
// apps/cli/src/infra/repositories/ConfigFileRepository.ts
|
|
5013
|
+
var fs5 = __toESM(require("fs/promises"));
|
|
5014
|
+
var path5 = __toESM(require("path"));
|
|
5015
|
+
var ConfigFileRepository = class {
|
|
5016
|
+
constructor() {
|
|
5017
|
+
this.CONFIG_FILENAME = "packmind.json";
|
|
5018
|
+
this.EXCLUDED_DIRECTORIES = [
|
|
5019
|
+
"node_modules",
|
|
5020
|
+
".git",
|
|
5021
|
+
"dist",
|
|
5022
|
+
"build",
|
|
5023
|
+
"coverage",
|
|
5024
|
+
".nx"
|
|
5025
|
+
];
|
|
5026
|
+
}
|
|
5027
|
+
async writeConfig(baseDirectory, config) {
|
|
5028
|
+
const configPath = path5.join(baseDirectory, this.CONFIG_FILENAME);
|
|
5029
|
+
const configContent = JSON.stringify(config, null, 2) + "\n";
|
|
5030
|
+
await fs5.writeFile(configPath, configContent, "utf-8");
|
|
5031
|
+
}
|
|
5032
|
+
async readConfig(baseDirectory) {
|
|
5033
|
+
const configPath = path5.join(baseDirectory, this.CONFIG_FILENAME);
|
|
5034
|
+
try {
|
|
5035
|
+
const configContent = await fs5.readFile(configPath, "utf-8");
|
|
5036
|
+
const config = JSON.parse(configContent);
|
|
5037
|
+
if (!config.packages || typeof config.packages !== "object") {
|
|
5038
|
+
throw new Error(
|
|
5039
|
+
"Invalid packmind.json structure. Expected { packages: { ... } }"
|
|
5040
|
+
);
|
|
5041
|
+
}
|
|
5042
|
+
return config;
|
|
5043
|
+
} catch (error) {
|
|
5044
|
+
if (error.code === "ENOENT") {
|
|
5045
|
+
return null;
|
|
5046
|
+
}
|
|
5047
|
+
throw new Error(
|
|
5048
|
+
`Failed to read packmind.json: ${error.message}`
|
|
5049
|
+
);
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
/**
|
|
5053
|
+
* Recursively finds all directories containing packmind.json in descendant folders.
|
|
5054
|
+
* Excludes common build/dependency directories (node_modules, .git, dist, etc.)
|
|
5055
|
+
*
|
|
5056
|
+
* @param directory - The root directory to search from
|
|
5057
|
+
* @returns Array of directory paths that contain a packmind.json file
|
|
5058
|
+
*/
|
|
5059
|
+
async findDescendantConfigs(directory) {
|
|
5060
|
+
const normalizedDir = path5.resolve(directory);
|
|
5061
|
+
const results = [];
|
|
5062
|
+
const searchRecursively = async (currentDir) => {
|
|
5063
|
+
let entries;
|
|
5064
|
+
try {
|
|
5065
|
+
entries = await fs5.readdir(currentDir, { withFileTypes: true });
|
|
5066
|
+
} catch {
|
|
5067
|
+
return;
|
|
5068
|
+
}
|
|
5069
|
+
for (const entry of entries) {
|
|
5070
|
+
if (!entry.isDirectory()) {
|
|
5071
|
+
continue;
|
|
5072
|
+
}
|
|
5073
|
+
if (this.EXCLUDED_DIRECTORIES.includes(entry.name)) {
|
|
5074
|
+
continue;
|
|
5075
|
+
}
|
|
5076
|
+
const entryPath = path5.join(currentDir, entry.name);
|
|
5077
|
+
const config = await this.readConfig(entryPath);
|
|
5078
|
+
if (config) {
|
|
5079
|
+
results.push(entryPath);
|
|
5080
|
+
}
|
|
5081
|
+
await searchRecursively(entryPath);
|
|
5082
|
+
}
|
|
5083
|
+
};
|
|
5084
|
+
await searchRecursively(normalizedDir);
|
|
5085
|
+
return results;
|
|
5086
|
+
}
|
|
5087
|
+
/**
|
|
5088
|
+
* Reads all packmind.json files from startDirectory up to stopDirectory (inclusive)
|
|
5089
|
+
* and merges their package configurations.
|
|
5090
|
+
*
|
|
5091
|
+
* @param startDirectory - Directory to start searching from (typically the lint target)
|
|
5092
|
+
* @param stopDirectory - Directory to stop searching at (typically git repo root), or null to walk to filesystem root
|
|
5093
|
+
* @returns Merged configuration from all found packmind.json files
|
|
5094
|
+
*/
|
|
5095
|
+
async readHierarchicalConfig(startDirectory, stopDirectory) {
|
|
5096
|
+
const configs = [];
|
|
5097
|
+
const configPaths = [];
|
|
5098
|
+
const normalizedStart = path5.resolve(startDirectory);
|
|
5099
|
+
const normalizedStop = stopDirectory ? path5.resolve(stopDirectory) : null;
|
|
5100
|
+
let currentDir = normalizedStart;
|
|
5101
|
+
while (true) {
|
|
5102
|
+
const config = await this.readConfig(currentDir);
|
|
5103
|
+
if (config) {
|
|
5104
|
+
configs.push(config);
|
|
5105
|
+
configPaths.push(path5.join(currentDir, this.CONFIG_FILENAME));
|
|
5106
|
+
}
|
|
5107
|
+
if (normalizedStop !== null && currentDir === normalizedStop) {
|
|
5108
|
+
break;
|
|
5109
|
+
}
|
|
5110
|
+
const parentDir = path5.dirname(currentDir);
|
|
5111
|
+
if (parentDir === currentDir) {
|
|
5112
|
+
break;
|
|
5113
|
+
}
|
|
5114
|
+
currentDir = parentDir;
|
|
5115
|
+
}
|
|
5116
|
+
const mergedPackages = {};
|
|
5117
|
+
for (const config of configs) {
|
|
5118
|
+
for (const [slug, version] of Object.entries(config.packages)) {
|
|
5119
|
+
if (!(slug in mergedPackages)) {
|
|
5120
|
+
mergedPackages[slug] = version;
|
|
5121
|
+
}
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
return {
|
|
5125
|
+
packages: mergedPackages,
|
|
5126
|
+
configPaths,
|
|
5127
|
+
hasConfigs: configs.length > 0
|
|
5128
|
+
};
|
|
5129
|
+
}
|
|
5130
|
+
};
|
|
5131
|
+
|
|
4473
5132
|
// apps/cli/src/PackmindCliHexaFactory.ts
|
|
4474
5133
|
var PackmindCliHexaFactory = class {
|
|
4475
5134
|
constructor(logger2) {
|
|
@@ -4477,7 +5136,8 @@ var PackmindCliHexaFactory = class {
|
|
|
4477
5136
|
this.repositories = {
|
|
4478
5137
|
packmindGateway: new PackmindGateway(
|
|
4479
5138
|
process.env.PACKMIND_API_KEY_V3 || ""
|
|
4480
|
-
)
|
|
5139
|
+
),
|
|
5140
|
+
configFileRepository: new ConfigFileRepository()
|
|
4481
5141
|
};
|
|
4482
5142
|
this.services = {
|
|
4483
5143
|
listFiles: new ListFiles(),
|
|
@@ -4495,6 +5155,11 @@ var PackmindCliHexaFactory = class {
|
|
|
4495
5155
|
this.repositories,
|
|
4496
5156
|
this.logger
|
|
4497
5157
|
),
|
|
5158
|
+
lintFilesLocally: new LintFilesLocallyUseCase(
|
|
5159
|
+
this.services,
|
|
5160
|
+
this.repositories,
|
|
5161
|
+
this.logger
|
|
5162
|
+
),
|
|
4498
5163
|
pullData: new PullDataUseCase(this.repositories.packmindGateway),
|
|
4499
5164
|
listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
|
|
4500
5165
|
getPackageBySlug: new GetPackageSummaryUseCase(
|
|
@@ -4505,9 +5170,9 @@ var PackmindCliHexaFactory = class {
|
|
|
4505
5170
|
};
|
|
4506
5171
|
|
|
4507
5172
|
// apps/cli/src/PackmindCliHexa.ts
|
|
4508
|
-
var
|
|
5173
|
+
var origin10 = "PackmindCliHexa";
|
|
4509
5174
|
var PackmindCliHexa = class {
|
|
4510
|
-
constructor(logger2 = new PackmindLogger(
|
|
5175
|
+
constructor(logger2 = new PackmindLogger(origin10)) {
|
|
4511
5176
|
this.logger = logger2;
|
|
4512
5177
|
try {
|
|
4513
5178
|
this.hexa = new PackmindCliHexaFactory(this.logger);
|
|
@@ -4537,6 +5202,9 @@ var PackmindCliHexa = class {
|
|
|
4537
5202
|
async lintFilesInDirectory(command3) {
|
|
4538
5203
|
return this.hexa.useCases.lintFilesInDirectory.execute(command3);
|
|
4539
5204
|
}
|
|
5205
|
+
async lintFilesLocally(command3) {
|
|
5206
|
+
return this.hexa.useCases.lintFilesLocally.execute(command3);
|
|
5207
|
+
}
|
|
4540
5208
|
async pullData(command3) {
|
|
4541
5209
|
return this.hexa.useCases.pullData.execute(command3);
|
|
4542
5210
|
}
|
|
@@ -4546,6 +5214,57 @@ var PackmindCliHexa = class {
|
|
|
4546
5214
|
async getPackageBySlug(command3) {
|
|
4547
5215
|
return this.hexa.useCases.getPackageBySlug.execute(command3);
|
|
4548
5216
|
}
|
|
5217
|
+
async writeConfig(baseDirectory, packagesSlugs) {
|
|
5218
|
+
const config = {
|
|
5219
|
+
packages: packagesSlugs.reduce(
|
|
5220
|
+
(acc, slug) => {
|
|
5221
|
+
acc[slug] = "*";
|
|
5222
|
+
return acc;
|
|
5223
|
+
},
|
|
5224
|
+
{}
|
|
5225
|
+
)
|
|
5226
|
+
};
|
|
5227
|
+
await this.hexa.repositories.configFileRepository.writeConfig(
|
|
5228
|
+
baseDirectory,
|
|
5229
|
+
config
|
|
5230
|
+
);
|
|
5231
|
+
}
|
|
5232
|
+
async readConfig(baseDirectory) {
|
|
5233
|
+
const config = await this.hexa.repositories.configFileRepository.readConfig(
|
|
5234
|
+
baseDirectory
|
|
5235
|
+
);
|
|
5236
|
+
if (!config) return [];
|
|
5237
|
+
const hasNonWildcardVersions = Object.values(config.packages).some(
|
|
5238
|
+
(version) => version !== "*"
|
|
5239
|
+
);
|
|
5240
|
+
if (hasNonWildcardVersions) {
|
|
5241
|
+
console.log(
|
|
5242
|
+
"WARN: Package versions are not supported yet, getting the latest version"
|
|
5243
|
+
);
|
|
5244
|
+
}
|
|
5245
|
+
return Object.keys(config.packages);
|
|
5246
|
+
}
|
|
5247
|
+
async readHierarchicalConfig(startDirectory, stopDirectory) {
|
|
5248
|
+
return this.hexa.repositories.configFileRepository.readHierarchicalConfig(
|
|
5249
|
+
startDirectory,
|
|
5250
|
+
stopDirectory
|
|
5251
|
+
);
|
|
5252
|
+
}
|
|
5253
|
+
async findDescendantConfigs(directory) {
|
|
5254
|
+
return this.hexa.repositories.configFileRepository.findDescendantConfigs(
|
|
5255
|
+
directory
|
|
5256
|
+
);
|
|
5257
|
+
}
|
|
5258
|
+
async getGitRepositoryRoot(directory) {
|
|
5259
|
+
return this.hexa.services.gitRemoteUrlService.getGitRepositoryRoot(
|
|
5260
|
+
directory
|
|
5261
|
+
);
|
|
5262
|
+
}
|
|
5263
|
+
async tryGetGitRepositoryRoot(directory) {
|
|
5264
|
+
return this.hexa.services.gitRemoteUrlService.tryGetGitRepositoryRoot(
|
|
5265
|
+
directory
|
|
5266
|
+
);
|
|
5267
|
+
}
|
|
4549
5268
|
};
|
|
4550
5269
|
|
|
4551
5270
|
// apps/cli/src/infra/repositories/IDELintLogger.ts
|
|
@@ -4600,6 +5319,7 @@ var HumanReadableLogger = class {
|
|
|
4600
5319
|
};
|
|
4601
5320
|
|
|
4602
5321
|
// apps/cli/src/infra/commands/LinterCommand.ts
|
|
5322
|
+
var pathModule = __toESM(require("path"));
|
|
4603
5323
|
var Logger = {
|
|
4604
5324
|
from: async (input) => {
|
|
4605
5325
|
switch (input) {
|
|
@@ -4662,7 +5382,7 @@ var lintCommand = (0, import_cmd_ts.command)({
|
|
|
4662
5382
|
description: "Enable debug logging"
|
|
4663
5383
|
})
|
|
4664
5384
|
},
|
|
4665
|
-
handler: async ({ path:
|
|
5385
|
+
handler: async ({ path: path7, draft, rule, debug, language, logger: logger2 }) => {
|
|
4666
5386
|
if (draft && !rule) {
|
|
4667
5387
|
throw new Error("option --rule is required to use --draft mode");
|
|
4668
5388
|
}
|
|
@@ -4672,13 +5392,52 @@ var lintCommand = (0, import_cmd_ts.command)({
|
|
|
4672
5392
|
debug ? "debug" /* DEBUG */ : "info" /* INFO */
|
|
4673
5393
|
);
|
|
4674
5394
|
const packmindCliHexa = new PackmindCliHexa(packmindLogger);
|
|
4675
|
-
const
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
5395
|
+
const targetPath = path7 ?? ".";
|
|
5396
|
+
const hasArguments = !!(draft || rule || language);
|
|
5397
|
+
const absolutePath = pathModule.isAbsolute(targetPath) ? targetPath : pathModule.resolve(process.cwd(), targetPath);
|
|
5398
|
+
let useLocalLinting = false;
|
|
5399
|
+
let lintTargets = [];
|
|
5400
|
+
if (!hasArguments) {
|
|
5401
|
+
const stopDirectory = await packmindCliHexa.tryGetGitRepositoryRoot(absolutePath);
|
|
5402
|
+
const hierarchicalConfig = await packmindCliHexa.readHierarchicalConfig(
|
|
5403
|
+
absolutePath,
|
|
5404
|
+
stopDirectory
|
|
5405
|
+
);
|
|
5406
|
+
if (hierarchicalConfig.hasConfigs) {
|
|
5407
|
+
useLocalLinting = true;
|
|
5408
|
+
const rootConfig = await packmindCliHexa.readHierarchicalConfig(
|
|
5409
|
+
absolutePath,
|
|
5410
|
+
absolutePath
|
|
5411
|
+
);
|
|
5412
|
+
if (rootConfig.hasConfigs) {
|
|
5413
|
+
lintTargets.push(absolutePath);
|
|
5414
|
+
}
|
|
5415
|
+
const descendantTargets = await packmindCliHexa.findDescendantConfigs(absolutePath);
|
|
5416
|
+
lintTargets = [...lintTargets, ...descendantTargets];
|
|
5417
|
+
if (lintTargets.length === 0) {
|
|
5418
|
+
lintTargets.push(absolutePath);
|
|
5419
|
+
}
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
let violations = [];
|
|
5423
|
+
if (useLocalLinting && lintTargets.length > 0) {
|
|
5424
|
+
for (const target of lintTargets) {
|
|
5425
|
+
packmindLogger.debug(`Linting target: ${target}`);
|
|
5426
|
+
const result = await packmindCliHexa.lintFilesLocally({
|
|
5427
|
+
path: target
|
|
5428
|
+
});
|
|
5429
|
+
violations = [...violations, ...result.violations];
|
|
5430
|
+
}
|
|
5431
|
+
} else {
|
|
5432
|
+
const result = await packmindCliHexa.lintFilesInDirectory({
|
|
5433
|
+
path: targetPath,
|
|
5434
|
+
draftMode: draft,
|
|
5435
|
+
standardSlug: rule?.standardSlug,
|
|
5436
|
+
ruleId: rule?.ruleId,
|
|
5437
|
+
language
|
|
5438
|
+
});
|
|
5439
|
+
violations = result.violations;
|
|
5440
|
+
}
|
|
4682
5441
|
(logger2 === "ide" /* ide */ ? new IDELintLogger() : new HumanReadableLogger()).logViolations(violations);
|
|
4683
5442
|
const durationSeconds = (Date.now() - startedAt) / 1e3;
|
|
4684
5443
|
console.log(`Lint completed in ${durationSeconds.toFixed(2)}s`);
|
|
@@ -4746,8 +5505,8 @@ function extractWasmFiles() {
|
|
|
4746
5505
|
|
|
4747
5506
|
// apps/cli/src/main.ts
|
|
4748
5507
|
var import_dotenv = require("dotenv");
|
|
4749
|
-
var
|
|
4750
|
-
var
|
|
5508
|
+
var fs6 = __toESM(require("fs"));
|
|
5509
|
+
var path6 = __toESM(require("path"));
|
|
4751
5510
|
|
|
4752
5511
|
// apps/cli/src/infra/commands/PullCommand.ts
|
|
4753
5512
|
var import_cmd_ts2 = require("cmd-ts");
|
|
@@ -4784,7 +5543,11 @@ var pullCommand = (0, import_cmd_ts2.command)({
|
|
|
4784
5543
|
}
|
|
4785
5544
|
console.log("Available packages:");
|
|
4786
5545
|
packages.forEach((pkg) => {
|
|
4787
|
-
console.log(
|
|
5546
|
+
console.log(`- ${pkg.name} (${pkg.slug})`);
|
|
5547
|
+
if (pkg.description) {
|
|
5548
|
+
console.log(` ${pkg.description}`);
|
|
5549
|
+
console.log("");
|
|
5550
|
+
}
|
|
4788
5551
|
});
|
|
4789
5552
|
process.exit(0);
|
|
4790
5553
|
} catch (error) {
|
|
@@ -4841,30 +5604,59 @@ var pullCommand = (0, import_cmd_ts2.command)({
|
|
|
4841
5604
|
process.exit(1);
|
|
4842
5605
|
}
|
|
4843
5606
|
}
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
5607
|
+
let configPackages;
|
|
5608
|
+
let configExists = false;
|
|
5609
|
+
try {
|
|
5610
|
+
configPackages = await packmindCliHexa.readConfig(process.cwd());
|
|
5611
|
+
configExists = configPackages.length > 0;
|
|
5612
|
+
} catch (error) {
|
|
5613
|
+
console.error("ERROR Failed to parse packmind.json");
|
|
5614
|
+
if (error instanceof Error) {
|
|
5615
|
+
console.error(`ERROR ${error.message}`);
|
|
5616
|
+
} else {
|
|
5617
|
+
console.error(`ERROR ${String(error)}`);
|
|
5618
|
+
}
|
|
5619
|
+
console.error(
|
|
5620
|
+
"\n\u{1F4A1} Please fix the packmind.json file or delete it to continue."
|
|
5621
|
+
);
|
|
5622
|
+
process.exit(1);
|
|
5623
|
+
}
|
|
5624
|
+
const allPackages = [.../* @__PURE__ */ new Set([...configPackages, ...packagesSlugs])];
|
|
5625
|
+
if (allPackages.length === 0) {
|
|
5626
|
+
console.log("WARN config packmind.json not found");
|
|
5627
|
+
console.log(
|
|
5628
|
+
"Usage: packmind-cli install <package-slug> [package-slug...]"
|
|
5629
|
+
);
|
|
5630
|
+
console.log(" packmind-cli install --list");
|
|
4847
5631
|
console.log("");
|
|
4848
5632
|
console.log("Examples:");
|
|
4849
|
-
console.log(" packmind-cli
|
|
4850
|
-
console.log(" packmind-cli
|
|
4851
|
-
console.log(" packmind-cli
|
|
5633
|
+
console.log(" packmind-cli install backend");
|
|
5634
|
+
console.log(" packmind-cli install backend frontend");
|
|
5635
|
+
console.log(" packmind-cli install --list # Show available packages");
|
|
4852
5636
|
console.log("");
|
|
4853
|
-
console.log("
|
|
5637
|
+
console.log("Install recipes and standards from the specified packages.");
|
|
4854
5638
|
process.exit(0);
|
|
4855
5639
|
}
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
5640
|
+
if (!configExists && packagesSlugs.length > 0) {
|
|
5641
|
+
console.log("INFO initializing packmind.json");
|
|
5642
|
+
}
|
|
4859
5643
|
try {
|
|
5644
|
+
const packageCount = allPackages.length;
|
|
5645
|
+
const packageWord = packageCount === 1 ? "package" : "packages";
|
|
5646
|
+
console.log(
|
|
5647
|
+
`Fetching ${packageCount} ${packageWord}: ${allPackages.join(", ")}...`
|
|
5648
|
+
);
|
|
4860
5649
|
const result = await packmindCliHexa.pullData({
|
|
4861
5650
|
baseDirectory: process.cwd(),
|
|
4862
|
-
packagesSlugs
|
|
5651
|
+
packagesSlugs: allPackages
|
|
4863
5652
|
});
|
|
4864
|
-
console.log(
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
console.log(
|
|
5653
|
+
console.log(
|
|
5654
|
+
`Installing ${result.recipesCount} recipes and ${result.standardsCount} standards...`
|
|
5655
|
+
);
|
|
5656
|
+
console.log(
|
|
5657
|
+
`
|
|
5658
|
+
added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${result.filesDeleted} files`
|
|
5659
|
+
);
|
|
4868
5660
|
if (result.errors.length > 0) {
|
|
4869
5661
|
console.log("\n\u26A0\uFE0F Errors encountered:");
|
|
4870
5662
|
result.errors.forEach((error) => {
|
|
@@ -4872,15 +5664,54 @@ var pullCommand = (0, import_cmd_ts2.command)({
|
|
|
4872
5664
|
});
|
|
4873
5665
|
process.exit(1);
|
|
4874
5666
|
}
|
|
5667
|
+
await packmindCliHexa.writeConfig(process.cwd(), allPackages);
|
|
4875
5668
|
} catch (error) {
|
|
4876
|
-
console.error("\n\u274C Failed to
|
|
5669
|
+
console.error("\n\u274C Failed to install content:");
|
|
4877
5670
|
if (error instanceof Error) {
|
|
4878
5671
|
const errorObj = error;
|
|
4879
5672
|
if (errorObj.statusCode === 404) {
|
|
4880
5673
|
console.error(` ${errorObj.message}`);
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
5674
|
+
if (configExists && configPackages.length > 0) {
|
|
5675
|
+
const missingPackages = allPackages.filter(
|
|
5676
|
+
(pkg) => configPackages.includes(pkg)
|
|
5677
|
+
);
|
|
5678
|
+
if (missingPackages.length > 0) {
|
|
5679
|
+
console.error(
|
|
5680
|
+
"\n\u{1F4A1} Either remove the following package(s) from packmind.json:"
|
|
5681
|
+
);
|
|
5682
|
+
missingPackages.forEach((pkg) => {
|
|
5683
|
+
console.error(` "${pkg}"`);
|
|
5684
|
+
});
|
|
5685
|
+
console.error(" Or ensure that:");
|
|
5686
|
+
console.error(
|
|
5687
|
+
" - The package slug exists and is correctly spelled"
|
|
5688
|
+
);
|
|
5689
|
+
console.error(" - The package exists in your organization");
|
|
5690
|
+
console.error(" - You have the correct API key configured");
|
|
5691
|
+
} else {
|
|
5692
|
+
console.error("\n\u{1F4A1} Troubleshooting tips:");
|
|
5693
|
+
console.error(
|
|
5694
|
+
" - Check if the package slug exists and is correctly spelled"
|
|
5695
|
+
);
|
|
5696
|
+
console.error(
|
|
5697
|
+
" - Check that the package exists in your organization"
|
|
5698
|
+
);
|
|
5699
|
+
console.error(
|
|
5700
|
+
" - Ensure you have the correct API key configured"
|
|
5701
|
+
);
|
|
5702
|
+
}
|
|
5703
|
+
} else {
|
|
5704
|
+
console.error("\n\u{1F4A1} Troubleshooting tips:");
|
|
5705
|
+
console.error(
|
|
5706
|
+
" - Check if the package slug exists and is correctly spelled"
|
|
5707
|
+
);
|
|
5708
|
+
console.error(
|
|
5709
|
+
" - Check that the package exists in your organization"
|
|
5710
|
+
);
|
|
5711
|
+
console.error(
|
|
5712
|
+
" - Ensure you have the correct API key configured"
|
|
5713
|
+
);
|
|
5714
|
+
}
|
|
4884
5715
|
} else {
|
|
4885
5716
|
console.error(` ${errorObj.message}`);
|
|
4886
5717
|
const apiErrorObj = error;
|
|
@@ -4910,25 +5741,25 @@ function findEnvFile() {
|
|
|
4910
5741
|
const startDir = currentDir;
|
|
4911
5742
|
let gitRootFound = false;
|
|
4912
5743
|
let searchDir = currentDir;
|
|
4913
|
-
while (searchDir !==
|
|
4914
|
-
if (
|
|
5744
|
+
while (searchDir !== path6.parse(searchDir).root) {
|
|
5745
|
+
if (fs6.existsSync(path6.join(searchDir, ".git"))) {
|
|
4915
5746
|
gitRootFound = true;
|
|
4916
5747
|
break;
|
|
4917
5748
|
}
|
|
4918
|
-
searchDir =
|
|
5749
|
+
searchDir = path6.dirname(searchDir);
|
|
4919
5750
|
}
|
|
4920
|
-
while (currentDir !==
|
|
4921
|
-
const envPath2 =
|
|
4922
|
-
if (
|
|
5751
|
+
while (currentDir !== path6.parse(currentDir).root) {
|
|
5752
|
+
const envPath2 = path6.join(currentDir, ".env");
|
|
5753
|
+
if (fs6.existsSync(envPath2)) {
|
|
4923
5754
|
return envPath2;
|
|
4924
5755
|
}
|
|
4925
|
-
if (gitRootFound &&
|
|
5756
|
+
if (gitRootFound && fs6.existsSync(path6.join(currentDir, ".git"))) {
|
|
4926
5757
|
break;
|
|
4927
5758
|
}
|
|
4928
5759
|
if (!gitRootFound && currentDir !== startDir) {
|
|
4929
5760
|
break;
|
|
4930
5761
|
}
|
|
4931
|
-
currentDir =
|
|
5762
|
+
currentDir = path6.dirname(currentDir);
|
|
4932
5763
|
}
|
|
4933
5764
|
return null;
|
|
4934
5765
|
}
|
|
@@ -4953,7 +5784,8 @@ var app = (0, import_cmd_ts3.subcommands)({
|
|
|
4953
5784
|
description: "Packmind CLI tool",
|
|
4954
5785
|
cmds: {
|
|
4955
5786
|
lint: lintCommand,
|
|
4956
|
-
pull: pullCommand
|
|
5787
|
+
pull: pullCommand,
|
|
5788
|
+
install: pullCommand
|
|
4957
5789
|
}
|
|
4958
5790
|
});
|
|
4959
5791
|
(0, import_cmd_ts3.run)(app, args).catch((error) => {
|