@powerhousedao/vetra 6.0.0-dev.108 → 6.0.0-dev.109
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/{codegen-jdqm9gNO.js → codegen-DOq2xhy3.js} +103 -116
- package/dist/codegen-DOq2xhy3.js.map +1 -0
- package/dist/{index-BUrUCk3m.d.ts → index-COsHJRmm.d.ts} +2 -2
- package/dist/{index-BUrUCk3m.d.ts.map → index-COsHJRmm.d.ts.map} +1 -1
- package/dist/processors/codegen/index.d.ts.map +1 -1
- package/dist/processors/codegen/index.js +1 -1
- package/dist/processors/index.d.ts +2 -31
- package/dist/processors/index.d.ts.map +1 -1
- package/dist/processors/index.js +4 -171
- package/dist/processors/index.js.map +1 -1
- package/dist/processors/vetra-read-model/index.d.ts +1 -1
- package/package.json +10 -10
- package/dist/codegen-jdqm9gNO.js.map +0 -1
|
@@ -5,8 +5,8 @@ import { createInterface } from "readline";
|
|
|
5
5
|
import { generateDriveEditor, generateEditor, generateFromDocument, generateManifest, generateProcessor, generateSubgraph, validateDocumentModelState } from "@powerhousedao/codegen";
|
|
6
6
|
import { kebabCase } from "change-case";
|
|
7
7
|
import { baseMinimalSaveToFile } from "document-model/node";
|
|
8
|
-
import { mkdir } from "
|
|
9
|
-
import { join } from "
|
|
8
|
+
import { mkdir } from "fs/promises";
|
|
9
|
+
import { join } from "path";
|
|
10
10
|
//#region processors/codegen/document-handlers/base-document-gen.ts
|
|
11
11
|
/**
|
|
12
12
|
* Abstract base class for document generators
|
|
@@ -376,25 +376,24 @@ async function minimalBackupDocument(data, workingDir, extension) {
|
|
|
376
376
|
var AppGenerator = class extends BaseDocumentGen {
|
|
377
377
|
supportedDocumentTypes = "powerhouse/app";
|
|
378
378
|
/**
|
|
379
|
-
*
|
|
379
|
+
* Parse and extract the global state from the serialized state string
|
|
380
380
|
*/
|
|
381
|
-
extractGlobalState(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return fullState.global;
|
|
381
|
+
extractGlobalState(input) {
|
|
382
|
+
if (!input.state) return;
|
|
383
|
+
return input.state.global;
|
|
385
384
|
}
|
|
386
385
|
/**
|
|
387
386
|
* Validate if this app strand should be processed
|
|
388
387
|
*/
|
|
389
|
-
shouldProcess(
|
|
390
|
-
if (!super.shouldProcess(
|
|
391
|
-
const state = this.extractGlobalState(
|
|
388
|
+
shouldProcess(input) {
|
|
389
|
+
if (!super.shouldProcess(input)) return false;
|
|
390
|
+
const state = this.extractGlobalState(input);
|
|
392
391
|
if (!state) {
|
|
393
|
-
logger.debug(`No state found for app: ${
|
|
392
|
+
logger.debug(`No state found for app: ${input.documentId}`);
|
|
394
393
|
return false;
|
|
395
394
|
}
|
|
396
395
|
if (!state.name) {
|
|
397
|
-
logger.debug(`No name found for app: ${
|
|
396
|
+
logger.debug(`No name found for app: ${input.documentId}`);
|
|
398
397
|
return false;
|
|
399
398
|
}
|
|
400
399
|
if (state.status !== "CONFIRMED") {
|
|
@@ -403,10 +402,10 @@ var AppGenerator = class extends BaseDocumentGen {
|
|
|
403
402
|
}
|
|
404
403
|
return true;
|
|
405
404
|
}
|
|
406
|
-
async generate(
|
|
407
|
-
const state = this.extractGlobalState(
|
|
405
|
+
async generate(input) {
|
|
406
|
+
const state = this.extractGlobalState(input);
|
|
408
407
|
if (!state) {
|
|
409
|
-
logger.error(`No state found for app: ${
|
|
408
|
+
logger.error(`No state found for app: ${input.documentId}`);
|
|
410
409
|
return;
|
|
411
410
|
}
|
|
412
411
|
if (state.name && state.status === "CONFIRMED") {
|
|
@@ -433,11 +432,12 @@ var AppGenerator = class extends BaseDocumentGen {
|
|
|
433
432
|
} catch (manifestError) {
|
|
434
433
|
logger.error(`⚠️ Failed to update manifest for app ${state.name}:`, manifestError);
|
|
435
434
|
}
|
|
435
|
+
const fullState = input.state;
|
|
436
436
|
await minimalBackupDocument({
|
|
437
|
-
documentId:
|
|
438
|
-
documentType:
|
|
439
|
-
branch:
|
|
440
|
-
state:
|
|
437
|
+
documentId: input.documentId,
|
|
438
|
+
documentType: input.documentType,
|
|
439
|
+
branch: input.branch,
|
|
440
|
+
state: fullState,
|
|
441
441
|
name: state.name
|
|
442
442
|
}, this.config.CURRENT_WORKING_DIR);
|
|
443
443
|
} catch (error) {
|
|
@@ -461,25 +461,24 @@ var AppGenerator = class extends BaseDocumentGen {
|
|
|
461
461
|
var DocumentEditorGenerator = class extends BaseDocumentGen {
|
|
462
462
|
supportedDocumentTypes = "powerhouse/document-editor";
|
|
463
463
|
/**
|
|
464
|
-
*
|
|
464
|
+
* Parse and extract the global state from the serialized state string
|
|
465
465
|
*/
|
|
466
|
-
extractGlobalState(
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
return fullState.global;
|
|
466
|
+
extractGlobalState(input) {
|
|
467
|
+
if (!input.state) return;
|
|
468
|
+
return input.state.global;
|
|
470
469
|
}
|
|
471
470
|
/**
|
|
472
471
|
* Validate if this document editor strand should be processed
|
|
473
472
|
*/
|
|
474
|
-
shouldProcess(
|
|
475
|
-
if (!super.shouldProcess(
|
|
476
|
-
const state = this.extractGlobalState(
|
|
473
|
+
shouldProcess(input) {
|
|
474
|
+
if (!super.shouldProcess(input)) return false;
|
|
475
|
+
const state = this.extractGlobalState(input);
|
|
477
476
|
if (!state) {
|
|
478
|
-
logger.debug(`No state found for document editor: ${
|
|
477
|
+
logger.debug(`No state found for document editor: ${input.documentId}`);
|
|
479
478
|
return false;
|
|
480
479
|
}
|
|
481
480
|
if (!state.name) {
|
|
482
|
-
logger.debug(`No name found for document editor: ${
|
|
481
|
+
logger.debug(`No name found for document editor: ${input.documentId}`);
|
|
483
482
|
return false;
|
|
484
483
|
}
|
|
485
484
|
if (!state.documentTypes || state.documentTypes.length === 0) {
|
|
@@ -492,10 +491,10 @@ var DocumentEditorGenerator = class extends BaseDocumentGen {
|
|
|
492
491
|
}
|
|
493
492
|
return true;
|
|
494
493
|
}
|
|
495
|
-
async generate(
|
|
496
|
-
const state = this.extractGlobalState(
|
|
494
|
+
async generate(input) {
|
|
495
|
+
const state = this.extractGlobalState(input);
|
|
497
496
|
if (!state) {
|
|
498
|
-
logger.error(`No state found for document editor: ${
|
|
497
|
+
logger.error(`No state found for document editor: ${input.documentId}`);
|
|
499
498
|
return;
|
|
500
499
|
}
|
|
501
500
|
logger.info(`🔄 Starting editor generation for: ${state.name}`);
|
|
@@ -521,11 +520,12 @@ var DocumentEditorGenerator = class extends BaseDocumentGen {
|
|
|
521
520
|
} catch (manifestError) {
|
|
522
521
|
logger.error(`⚠️ Failed to update manifest for editor ${state.name}:`, manifestError);
|
|
523
522
|
}
|
|
523
|
+
const fullState = input.state;
|
|
524
524
|
await minimalBackupDocument({
|
|
525
|
-
documentId:
|
|
526
|
-
documentType:
|
|
527
|
-
branch:
|
|
528
|
-
state:
|
|
525
|
+
documentId: input.documentId,
|
|
526
|
+
documentType: input.documentType,
|
|
527
|
+
branch: input.branch,
|
|
528
|
+
state: fullState,
|
|
529
529
|
name: state.name
|
|
530
530
|
}, this.config.CURRENT_WORKING_DIR);
|
|
531
531
|
} catch (error) {
|
|
@@ -543,36 +543,35 @@ var DocumentEditorGenerator = class extends BaseDocumentGen {
|
|
|
543
543
|
var DocumentModelGenerator = class extends BaseDocumentGen {
|
|
544
544
|
supportedDocumentTypes = "powerhouse/document-model";
|
|
545
545
|
/**
|
|
546
|
-
*
|
|
546
|
+
* Parse and extract the global state from the serialized state string
|
|
547
547
|
*/
|
|
548
|
-
extractGlobalState(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
return fullState.global;
|
|
548
|
+
extractGlobalState(input) {
|
|
549
|
+
if (!input.state) return;
|
|
550
|
+
return input.state.global;
|
|
552
551
|
}
|
|
553
552
|
/**
|
|
554
553
|
* Validate if this document model strand should be processed
|
|
555
554
|
*/
|
|
556
|
-
shouldProcess(
|
|
557
|
-
if (!super.shouldProcess(
|
|
558
|
-
const globalState = this.extractGlobalState(
|
|
555
|
+
shouldProcess(input) {
|
|
556
|
+
if (!super.shouldProcess(input)) return false;
|
|
557
|
+
const globalState = this.extractGlobalState(input);
|
|
559
558
|
if (!globalState) {
|
|
560
|
-
logger.debug(`>>> No global state found for document model: ${
|
|
559
|
+
logger.debug(`>>> No global state found for document model: ${input.documentId}`);
|
|
561
560
|
return false;
|
|
562
561
|
}
|
|
563
562
|
const validationResult = validateDocumentModelState(globalState);
|
|
564
563
|
if (!validationResult.isValid) {
|
|
565
564
|
const errorList = validationResult.errors.map((error) => ` - ${error}`).join("\n");
|
|
566
|
-
logger.info(`⚠️ Skipped code generation for '${globalState.name ||
|
|
565
|
+
logger.info(`⚠️ Skipped code generation for '${globalState.name || input.documentId}' due to validation errors:\n${errorList}`);
|
|
567
566
|
return false;
|
|
568
567
|
}
|
|
569
568
|
logger.info(`Document model ${globalState.name} is valid, proceeding with code generation`);
|
|
570
569
|
return true;
|
|
571
570
|
}
|
|
572
|
-
async generate(
|
|
573
|
-
const globalState = this.extractGlobalState(
|
|
571
|
+
async generate(input) {
|
|
572
|
+
const globalState = this.extractGlobalState(input);
|
|
574
573
|
if (!globalState) {
|
|
575
|
-
logger.error(`❌ No global state found for document model: ${
|
|
574
|
+
logger.error(`❌ No global state found for document model: ${input.documentId}`);
|
|
576
575
|
return;
|
|
577
576
|
}
|
|
578
577
|
logger.debug(`🔄 Starting code generation for document model: ${globalState.name}`);
|
|
@@ -594,12 +593,13 @@ var DocumentModelGenerator = class extends BaseDocumentGen {
|
|
|
594
593
|
} catch (manifestError) {
|
|
595
594
|
logger.error(`⚠️ Failed to update manifest for document model ${globalState.name}:`, manifestError);
|
|
596
595
|
}
|
|
596
|
+
const fullState = input.state;
|
|
597
597
|
const extension = globalState.extension?.replace(/^\.+|\.+$/g, "") || "";
|
|
598
598
|
await minimalBackupDocument({
|
|
599
|
-
documentId:
|
|
600
|
-
documentType:
|
|
601
|
-
branch:
|
|
602
|
-
state:
|
|
599
|
+
documentId: input.documentId,
|
|
600
|
+
documentType: input.documentType,
|
|
601
|
+
branch: input.branch,
|
|
602
|
+
state: fullState,
|
|
603
603
|
name: globalState.name
|
|
604
604
|
}, this.config.CURRENT_WORKING_DIR, extension);
|
|
605
605
|
} catch (error) {
|
|
@@ -616,30 +616,19 @@ var DocumentModelGenerator = class extends BaseDocumentGen {
|
|
|
616
616
|
var PackageGenerator = class extends BaseDocumentGen {
|
|
617
617
|
supportedDocumentTypes = "powerhouse/package";
|
|
618
618
|
/**
|
|
619
|
-
* Extract the global state from the full document state
|
|
620
|
-
*/
|
|
621
|
-
extractGlobalState(strand) {
|
|
622
|
-
const fullState = strand.state;
|
|
623
|
-
if (!fullState) return;
|
|
624
|
-
return fullState.global;
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
619
|
* Validate if this package strand should be processed
|
|
628
620
|
*/
|
|
629
|
-
shouldProcess(
|
|
630
|
-
if (!super.shouldProcess(
|
|
631
|
-
if (!
|
|
632
|
-
logger.debug(`>>> No state found for package: ${
|
|
621
|
+
shouldProcess(input) {
|
|
622
|
+
if (!super.shouldProcess(input)) return false;
|
|
623
|
+
if (!input.state) {
|
|
624
|
+
logger.debug(`>>> No state found for package: ${input.documentId}`);
|
|
633
625
|
return false;
|
|
634
626
|
}
|
|
635
627
|
return true;
|
|
636
628
|
}
|
|
637
|
-
async generate(
|
|
638
|
-
const
|
|
639
|
-
|
|
640
|
-
logger.error(`❌ No global state found for package: ${strand.documentId}`);
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
629
|
+
async generate(input) {
|
|
630
|
+
const fullState = input.state;
|
|
631
|
+
const state = fullState;
|
|
643
632
|
logger.info("🔄 Generating manifest for package");
|
|
644
633
|
generateManifest({
|
|
645
634
|
name: state.name ?? "",
|
|
@@ -652,10 +641,10 @@ var PackageGenerator = class extends BaseDocumentGen {
|
|
|
652
641
|
}, this.config.CURRENT_WORKING_DIR);
|
|
653
642
|
logger.info("✅ Manifest generated successfully");
|
|
654
643
|
await minimalBackupDocument({
|
|
655
|
-
documentId:
|
|
656
|
-
documentType:
|
|
657
|
-
branch:
|
|
658
|
-
state:
|
|
644
|
+
documentId: input.documentId,
|
|
645
|
+
documentType: input.documentType,
|
|
646
|
+
branch: input.branch,
|
|
647
|
+
state: fullState,
|
|
659
648
|
name: "vetra-package"
|
|
660
649
|
}, this.config.CURRENT_WORKING_DIR);
|
|
661
650
|
}
|
|
@@ -668,25 +657,24 @@ var PackageGenerator = class extends BaseDocumentGen {
|
|
|
668
657
|
var ProcessorGenerator = class extends BaseDocumentGen {
|
|
669
658
|
supportedDocumentTypes = "powerhouse/processor";
|
|
670
659
|
/**
|
|
671
|
-
*
|
|
660
|
+
* Parse and extract the global state from the serialized state string
|
|
672
661
|
*/
|
|
673
|
-
extractGlobalState(
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
return fullState.global;
|
|
662
|
+
extractGlobalState(input) {
|
|
663
|
+
if (!input.state) return;
|
|
664
|
+
return input.state.global;
|
|
677
665
|
}
|
|
678
666
|
/**
|
|
679
667
|
* Validate if this processor strand should be processed
|
|
680
668
|
*/
|
|
681
|
-
shouldProcess(
|
|
682
|
-
if (!super.shouldProcess(
|
|
683
|
-
const state = this.extractGlobalState(
|
|
669
|
+
shouldProcess(input) {
|
|
670
|
+
if (!super.shouldProcess(input)) return false;
|
|
671
|
+
const state = this.extractGlobalState(input);
|
|
684
672
|
if (!state) {
|
|
685
|
-
logger.debug(`No state found for processor: ${
|
|
673
|
+
logger.debug(`No state found for processor: ${input.documentId}`);
|
|
686
674
|
return false;
|
|
687
675
|
}
|
|
688
676
|
if (!state.name) {
|
|
689
|
-
logger.debug(`No name found for processor: ${
|
|
677
|
+
logger.debug(`No name found for processor: ${input.documentId}`);
|
|
690
678
|
return false;
|
|
691
679
|
}
|
|
692
680
|
if (!state.type) {
|
|
@@ -707,10 +695,10 @@ var ProcessorGenerator = class extends BaseDocumentGen {
|
|
|
707
695
|
}
|
|
708
696
|
return true;
|
|
709
697
|
}
|
|
710
|
-
async generate(
|
|
711
|
-
const state = this.extractGlobalState(
|
|
698
|
+
async generate(input) {
|
|
699
|
+
const state = this.extractGlobalState(input);
|
|
712
700
|
if (!state) {
|
|
713
|
-
logger.error(`No state found for processor: ${
|
|
701
|
+
logger.error(`No state found for processor: ${input.documentId}`);
|
|
714
702
|
return;
|
|
715
703
|
}
|
|
716
704
|
if (state.name && state.type && state.documentTypes.length > 0 && state.processorApps.length > 0 && state.status === "CONFIRMED") {
|
|
@@ -738,11 +726,12 @@ var ProcessorGenerator = class extends BaseDocumentGen {
|
|
|
738
726
|
processorApps
|
|
739
727
|
});
|
|
740
728
|
logger.info(`✅ Processor generation completed successfully for: ${state.name}`);
|
|
729
|
+
const fullState = input.state;
|
|
741
730
|
await minimalBackupDocument({
|
|
742
|
-
documentId:
|
|
743
|
-
documentType:
|
|
744
|
-
branch:
|
|
745
|
-
state:
|
|
731
|
+
documentId: input.documentId,
|
|
732
|
+
documentType: input.documentType,
|
|
733
|
+
branch: input.branch,
|
|
734
|
+
state: fullState,
|
|
746
735
|
name: state.name
|
|
747
736
|
}, this.config.CURRENT_WORKING_DIR);
|
|
748
737
|
} catch (error) {
|
|
@@ -778,25 +767,24 @@ function isProcessorApps(input) {
|
|
|
778
767
|
var SubgraphGenerator = class extends BaseDocumentGen {
|
|
779
768
|
supportedDocumentTypes = "powerhouse/subgraph";
|
|
780
769
|
/**
|
|
781
|
-
*
|
|
770
|
+
* Parse and extract the global state from the serialized state string
|
|
782
771
|
*/
|
|
783
|
-
extractGlobalState(
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
return fullState.global;
|
|
772
|
+
extractGlobalState(input) {
|
|
773
|
+
if (!input.state) return;
|
|
774
|
+
return input.state.global;
|
|
787
775
|
}
|
|
788
776
|
/**
|
|
789
777
|
* Validate if this subgraph strand should be processed
|
|
790
778
|
*/
|
|
791
|
-
shouldProcess(
|
|
792
|
-
if (!super.shouldProcess(
|
|
793
|
-
const state = this.extractGlobalState(
|
|
779
|
+
shouldProcess(input) {
|
|
780
|
+
if (!super.shouldProcess(input)) return false;
|
|
781
|
+
const state = this.extractGlobalState(input);
|
|
794
782
|
if (!state) {
|
|
795
|
-
logger.debug(`No state found for subgraph: ${
|
|
783
|
+
logger.debug(`No state found for subgraph: ${input.documentId}`);
|
|
796
784
|
return false;
|
|
797
785
|
}
|
|
798
786
|
if (!state.name) {
|
|
799
|
-
logger.debug(`No name found for subgraph: ${
|
|
787
|
+
logger.debug(`No name found for subgraph: ${input.documentId}`);
|
|
800
788
|
return false;
|
|
801
789
|
}
|
|
802
790
|
if (state.status !== "CONFIRMED") {
|
|
@@ -805,10 +793,10 @@ var SubgraphGenerator = class extends BaseDocumentGen {
|
|
|
805
793
|
}
|
|
806
794
|
return true;
|
|
807
795
|
}
|
|
808
|
-
async generate(
|
|
809
|
-
const state = this.extractGlobalState(
|
|
796
|
+
async generate(input) {
|
|
797
|
+
const state = this.extractGlobalState(input);
|
|
810
798
|
if (!state) {
|
|
811
|
-
logger.error(`No state found for subgraph: ${
|
|
799
|
+
logger.error(`No state found for subgraph: ${input.documentId}`);
|
|
812
800
|
return;
|
|
813
801
|
}
|
|
814
802
|
if (state.name && state.status === "CONFIRMED") {
|
|
@@ -828,11 +816,12 @@ var SubgraphGenerator = class extends BaseDocumentGen {
|
|
|
828
816
|
} catch (manifestError) {
|
|
829
817
|
logger.error(`⚠️ Failed to update manifest for subgraph ${state.name}:`, manifestError);
|
|
830
818
|
}
|
|
819
|
+
const fullState = input.state;
|
|
831
820
|
await minimalBackupDocument({
|
|
832
|
-
documentId:
|
|
833
|
-
documentType:
|
|
834
|
-
branch:
|
|
835
|
-
state:
|
|
821
|
+
documentId: input.documentId,
|
|
822
|
+
documentType: input.documentType,
|
|
823
|
+
branch: input.branch,
|
|
824
|
+
state: fullState,
|
|
836
825
|
name: state.name
|
|
837
826
|
}, this.config.CURRENT_WORKING_DIR);
|
|
838
827
|
} catch (error) {
|
|
@@ -908,22 +897,20 @@ var CodegenProcessor = class {
|
|
|
908
897
|
}
|
|
909
898
|
async onOperations(operations) {
|
|
910
899
|
logger.info("CodegenProcessor.onOperations()");
|
|
911
|
-
for (const {
|
|
900
|
+
for (const { context } of operations) {
|
|
912
901
|
const generator = this.manager.getGenerator(context.documentType);
|
|
913
902
|
if (!generator) {
|
|
914
903
|
logger.debug(`No generator found for document type: ${context.documentType}`);
|
|
915
904
|
continue;
|
|
916
905
|
}
|
|
917
|
-
const
|
|
906
|
+
const input = {
|
|
918
907
|
documentId: context.documentId,
|
|
919
908
|
documentType: context.documentType,
|
|
920
909
|
scope: context.scope,
|
|
921
910
|
branch: context.branch,
|
|
922
|
-
driveId: "",
|
|
923
|
-
operations: [operation],
|
|
924
911
|
state: context.resultingState ? JSON.parse(context.resultingState) : void 0
|
|
925
912
|
};
|
|
926
|
-
if (generator.shouldProcess(
|
|
913
|
+
if (generator.shouldProcess(input)) await this.manager.routeAndGenerate(input);
|
|
927
914
|
}
|
|
928
915
|
}
|
|
929
916
|
async onDisconnect() {}
|
|
@@ -938,6 +925,6 @@ var CodegenProcessor = class {
|
|
|
938
925
|
}
|
|
939
926
|
};
|
|
940
927
|
//#endregion
|
|
941
|
-
export {
|
|
928
|
+
export { CodegenProcessor as t };
|
|
942
929
|
|
|
943
|
-
//# sourceMappingURL=codegen-
|
|
930
|
+
//# sourceMappingURL=codegen-DOq2xhy3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen-DOq2xhy3.js","names":[],"sources":["../processors/codegen/document-handlers/base-document-gen.ts","../processors/codegen/interactive-manager.ts","../processors/codegen/document-handlers/document-codegen-manager.ts","../processors/codegen/document-handlers/generators/utils.ts","../processors/codegen/document-handlers/generators/app-generator.ts","../processors/codegen/document-handlers/generators/document-editor-generator.ts","../processors/codegen/document-handlers/generators/document-model-generator.ts","../processors/codegen/document-handlers/generators/package-generator.ts","../processors/codegen/document-handlers/generators/processor-generator.ts","../processors/codegen/document-handlers/generators/subgraph-generator.ts","../processors/codegen/document-handlers/document-codegen-factory.ts","../processors/codegen/index.ts"],"sourcesContent":["import type { CodegenInput, Config } from \"./types.js\";\n\n/**\n * Abstract base class for document generators\n * Defines the interface that all document-type handlers must implement\n */\nexport abstract class BaseDocumentGen {\n /**\n * The document type(s) this generator supports\n * Can be a single string or an array of strings for generators that handle multiple types\n */\n abstract readonly supportedDocumentTypes: string | string[];\n\n constructor(protected config: Config) {}\n\n /**\n * Generate code for the given document\n * Must be implemented by each specific document generator\n */\n abstract generate(strand: CodegenInput): Promise<void>;\n\n /**\n * Check if this generator supports the given document type\n */\n supportsDocumentType(documentType: string): boolean {\n if (typeof this.supportedDocumentTypes === \"string\") {\n return this.supportedDocumentTypes === documentType;\n }\n return this.supportedDocumentTypes.includes(documentType);\n }\n\n /**\n * Get all supported document types as an array\n */\n getSupportedDocumentTypes(): string[] {\n if (typeof this.supportedDocumentTypes === \"string\") {\n return [this.supportedDocumentTypes];\n }\n return [...this.supportedDocumentTypes];\n }\n\n /**\n * Validate if this strand should be processed\n * Override this method in specific generators to add custom validation logic\n */\n shouldProcess(strand: CodegenInput): boolean {\n // Basic validation: ensure strand has required properties\n if (!strand.documentId || !strand.documentType) {\n return false;\n }\n\n // Basic validation: check if document type is supported\n if (!this.supportsDocumentType(strand.documentType)) {\n return false;\n }\n\n // Default to processing if basic validation passes\n return true;\n }\n}\n","import { createInterface } from \"readline\";\nimport type { CodegenInput } from \"./document-handlers/types.js\";\nimport { logger } from \"./logger.js\";\n\nexport interface QueuedStrand {\n strand: CodegenInput;\n timestamp: number;\n}\n\n/**\n * InteractiveManager handles user interaction for code generation confirmation\n * Supports both individual strand processing and queue-based batch processing\n */\nexport class InteractiveManager {\n private isInteractiveMode: boolean;\n private processingConfirmation = false;\n private strandQueue = new Map<string, QueuedStrand>();\n\n constructor(interactiveMode = false) {\n this.isInteractiveMode = interactiveMode;\n }\n\n private getDocumentKey(documentType: string, documentId: string): string {\n return `${documentType}:${documentId}`;\n }\n\n /**\n * Add a strand to the queue, replacing any existing strand for the same document\n */\n public queueStrand(strand: CodegenInput): void {\n const documentKey = this.getDocumentKey(\n strand.documentType,\n strand.documentId,\n );\n\n this.strandQueue.set(documentKey, {\n strand,\n timestamp: Date.now(),\n });\n\n logger.debug(\n `>>> Queued strand for ${documentKey}, queue size: ${this.strandQueue.size}`,\n );\n }\n\n /**\n * Get all queued strands\n */\n public getQueuedStrands(): QueuedStrand[] {\n return Array.from(this.strandQueue.values());\n }\n\n /**\n * Clear and return all queued strands\n */\n public clearQueue(): QueuedStrand[] {\n const queuedStrands = Array.from(this.strandQueue.values());\n this.strandQueue.clear();\n return queuedStrands;\n }\n\n /**\n * Get the current queue size\n */\n public getQueueSize(): number {\n return this.strandQueue.size;\n }\n\n private async promptUserConfirmation(): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(\"🔄 Code generation ready to run.\");\n console.log(\"=\".repeat(50));\n\n process.stdout.write(\n \"Do you want to proceed with code generation? (y/n): \\n\\n\",\n );\n\n rl.on(\"line\", (answer: string) => {\n rl.close();\n console.log(\"\"); // Add blank line after user input\n resolve(answer.toLowerCase() === \"y\" || answer.toLowerCase() === \"yes\");\n });\n });\n }\n\n /**\n * Process generation with user confirmation (legacy single-strand method)\n * This method assumes interactive mode is already enabled (checked by caller)\n */\n public async processWithConfirmation<T>(\n documentType: string,\n generator: () => Promise<T>,\n ): Promise<T | null> {\n if (this.processingConfirmation) {\n logger.debug(\"Already processing confirmation, skipping\");\n return null;\n }\n\n this.processingConfirmation = true;\n\n try {\n // Always prompt user since this method only called in interactive mode\n const shouldProceed = await this.promptUserConfirmation();\n\n if (!shouldProceed) {\n logger.info(`❌ Code generation cancelled by user for ${documentType}`);\n return null;\n }\n\n logger.info(`✅ User approved code generation for ${documentType}`);\n\n const result = await generator();\n return result;\n } catch (error) {\n logger.error(\n `❌ Error during interactive code generation for ${documentType}:`,\n error,\n );\n throw error;\n } finally {\n this.processingConfirmation = false;\n }\n }\n\n /**\n * Process all queued strands with a single user confirmation\n * This is the main method for queue-based interactive processing\n */\n public async processQueueWithConfirmation(\n processor: (strands: QueuedStrand[]) => Promise<void>,\n ): Promise<void> {\n if (this.processingConfirmation) {\n logger.debug(\n \"Already processing confirmation, skipping queue processing\",\n );\n return;\n }\n\n // Check if there are any strands to process\n let queuedStrands = this.getQueuedStrands();\n if (queuedStrands.length === 0) {\n logger.debug(\"No strands in queue to process\");\n return;\n }\n\n this.processingConfirmation = true;\n\n try {\n // Prompt user for confirmation\n const shouldProceed = await this.promptUserConfirmation();\n\n if (!shouldProceed) {\n logger.info(\"❌ Code generation cancelled by user\");\n // Clear the queue since user cancelled\n this.clearQueue();\n return;\n }\n\n // Get and clear the final queue state right before processing\n // (in case new strands were added while waiting for user input)\n queuedStrands = this.clearQueue();\n if (queuedStrands.length === 0) {\n logger.info(\"ℹ️ No documents to process\");\n return;\n }\n\n logger.info(\n `✅ User approved code generation for ${queuedStrands.length} document(s)`,\n );\n\n // Process all queued strands\n await processor(queuedStrands);\n logger.info(\"✅ Code generation completed\");\n } catch (error) {\n logger.error(\"❌ Error during interactive queue processing:\", error);\n throw error;\n } finally {\n this.processingConfirmation = false;\n }\n }\n\n public setInteractiveMode(enabled: boolean): void {\n this.isInteractiveMode = enabled;\n logger.debug(`Interactive mode set to: ${enabled}`);\n }\n\n public isInteractive(): boolean {\n return this.isInteractiveMode;\n }\n\n public isProcessing(): boolean {\n return this.processingConfirmation;\n }\n}\n","import type { QueuedStrand } from \"../interactive-manager.js\";\nimport { InteractiveManager } from \"../interactive-manager.js\";\nimport { logger } from \"../logger.js\";\nimport type { BaseDocumentGen } from \"./base-document-gen.js\";\nimport type { CodegenInput, Config } from \"./types.js\";\n\nconst DEFAULT_DEBOUNCE_TIME = 3000; // 3 seconds\n\n/**\n * Manager class responsible for routing documents to the correct generator\n * and managing generator registration and instantiation\n */\nexport class DocumentCodegenManager {\n private generators = new Map<string, BaseDocumentGen>();\n private debounceTimers = new Map<string, NodeJS.Timeout>();\n private processingQueue: Promise<void> = Promise.resolve();\n private interactiveManager: InteractiveManager;\n\n constructor(\n private config: Config,\n interactiveMode = false,\n ) {\n this.interactiveManager = new InteractiveManager(interactiveMode);\n }\n\n /**\n * Register a generator class for a specific document type\n */\n registerGenerator(\n documentType: string,\n generatorClass: new (config: Config) => BaseDocumentGen,\n ): void {\n if (this.generators.has(documentType)) {\n logger.warn(\n `⚠️ Generator for document type \"${documentType}\" is already registered. Overwriting.`,\n );\n }\n\n this.generators.set(documentType, new generatorClass(this.config));\n logger.debug(`✅ Registered generator for document type: ${documentType}`);\n }\n\n /**\n * Register a generator class that supports multiple document types\n */\n registerMultiTypeGenerator(\n generatorClass: new (config: Config) => BaseDocumentGen,\n ): void {\n const generator = new generatorClass(this.config);\n const supportedTypes = generator.getSupportedDocumentTypes();\n\n for (const documentType of supportedTypes) {\n if (this.generators.has(documentType)) {\n logger.warn(\n `⚠️ Generator for document type \"${documentType}\" is already registered. Overwriting.`,\n );\n }\n this.generators.set(documentType, generator);\n }\n\n logger.debug(\n `✅ Registered multi-type generator for document types: ${supportedTypes.join(\", \")}`,\n );\n }\n\n /**\n * Get a generator instance for the given document type\n * Public method to allow external access for validation\n */\n public getGenerator(documentType: string): BaseDocumentGen | undefined {\n return this.generators.get(documentType);\n }\n\n /**\n * Get all registered document types\n */\n getRegisteredDocumentTypes(): string[] {\n return Array.from(this.generators.keys());\n }\n\n /**\n * Check if a document type is supported\n */\n isDocumentTypeSupported(documentType: string): boolean {\n return this.generators.has(documentType);\n }\n\n /**\n * Route a document to the appropriate generator and handle the generation\n * Handles both interactive and non-interactive modes with queue-based processing\n */\n async routeAndGenerate(strand: CodegenInput): Promise<void> {\n const documentType = strand.documentType;\n\n if (!documentType) {\n logger.error(\"❌ Document type is missing from strand state\");\n throw new Error(\"Document type is missing from strand state\");\n }\n\n const generator = this.getGenerator(documentType);\n\n if (!generator) {\n logger.warn(`⚠️ No generator found for document type: ${documentType}`);\n logger.warn(\n `ℹ️ Supported document types: ${this.getRegisteredDocumentTypes().join(\", \")}`,\n );\n throw new Error(`Unsupported document type: ${documentType}`);\n }\n\n // Validate if this strand should be processed\n if (!generator.shouldProcess(strand)) {\n logger.debug(\n `>>> Generator validation failed for ${documentType}:${strand.documentId}, skipping processing`,\n );\n return;\n }\n\n // Different flow for interactive vs non-interactive mode\n if (this.interactiveManager.isInteractive()) {\n // Interactive mode: queue strands and use debounce timer to trigger batch processing\n logger.debug(\n `>>> Queueing strand for interactive processing: ${documentType}:${strand.documentId}`,\n );\n\n // Add strand to queue (will replace any existing strand for same document)\n this.interactiveManager.queueStrand(strand);\n\n // Clear any existing debounce timer for interactive processing\n const existingTimer = this.debounceTimers.get(\"interactive\");\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set up debounce timer for batch interactive processing\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n const debounceTimer = setTimeout(async () => {\n try {\n await this.interactiveManager.processQueueWithConfirmation(\n async (queuedStrands: QueuedStrand[]) => {\n await this.processQueuedStrands(queuedStrands);\n },\n );\n } catch (error) {\n logger.error(\"❌ Error during interactive batch processing:\", error);\n } finally {\n // Clean up the timer reference\n this.debounceTimers.delete(\"interactive\");\n }\n }, DEFAULT_DEBOUNCE_TIME);\n\n // Store the timer reference using 'interactive' key\n this.debounceTimers.set(\"interactive\", debounceTimer);\n } else {\n // Non-interactive mode: use debouncing per document instance\n // Create unique key for this specific document instance\n const timerKey = `${documentType}:${strand.documentId}`;\n\n // Clear any existing debounce timer for this document instance\n const existingTimer = this.debounceTimers.get(timerKey);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set up new debounced generation (no interactive confirmation)\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n const debounceTimer = setTimeout(async () => {\n try {\n logger.debug(\n `🔄 Routing document type \"${documentType}\" to generator (debounced)`,\n );\n\n // Direct generation, no interactive confirmation\n await generator.generate(strand);\n logger.debug(\n `✅ Successfully generated code for document type: ${documentType}`,\n );\n } catch (error) {\n logger.error(\n `❌ Error generating code for document type \"${documentType}\":`,\n error,\n );\n // Don't throw - let codegen continue with other documents\n } finally {\n // Clean up the timer reference\n this.debounceTimers.delete(documentType);\n }\n }, DEFAULT_DEBOUNCE_TIME);\n\n // Store the timer reference\n this.debounceTimers.set(timerKey, debounceTimer);\n }\n }\n\n /**\n * Process multiple strands in priority order (document-model types first)\n */\n private async processQueuedStrands(\n queuedStrands: QueuedStrand[],\n ): Promise<void> {\n logger.debug(`🔄 Processing ${queuedStrands.length} queued strand(s)`);\n\n // Sort by priority (document-model first to ensure dependencies exist)\n const documentModelStrands = queuedStrands.filter(\n (qs: QueuedStrand) =>\n qs.strand.documentType === \"powerhouse/document-model\",\n );\n const otherStrands = queuedStrands.filter(\n (qs: QueuedStrand) =>\n qs.strand.documentType !== \"powerhouse/document-model\",\n );\n\n // Process document models first\n for (const queuedStrand of documentModelStrands) {\n await this.processStrand(queuedStrand.strand);\n }\n\n // Then process other document types\n for (const queuedStrand of otherStrands) {\n await this.processStrand(queuedStrand.strand);\n }\n\n logger.debug(\n `✅ Successfully processed all ${queuedStrands.length} queued strand(s)`,\n );\n }\n\n /**\n * Process a single strand (used internally by processQueuedStrands)\n */\n private async processStrand(strand: CodegenInput): Promise<void> {\n const documentType = strand.documentType;\n const generator = this.getGenerator(documentType);\n\n if (!generator) {\n logger.warn(`⚠️ No generator found for document type: ${documentType}`);\n return;\n }\n\n try {\n logger.debug(`🔄 Generating code for document type: ${documentType}`);\n await generator.generate(strand);\n logger.debug(\n `✅ Successfully generated code for document type: ${documentType}`,\n );\n } catch (error) {\n logger.error(\n `❌ Error generating code for document type \"${documentType}\":`,\n error,\n );\n // Don't throw here to allow other strands to be processed\n }\n }\n\n /**\n * Clear all registered generators\n */\n clearGenerators(): void {\n this.generators.clear();\n logger.debug(\"🧹 Cleared all registered generators\");\n }\n\n /**\n * Get statistics about registered generators\n */\n getStats(): { totalGenerators: number; supportedTypes: string[] } {\n return {\n totalGenerators: this.generators.size,\n supportedTypes: this.getRegisteredDocumentTypes(),\n };\n }\n\n /**\n * Set interactive mode for code generation\n */\n setInteractiveMode(enabled: boolean): void {\n this.interactiveManager.setInteractiveMode(enabled);\n }\n\n /**\n * Check if interactive mode is enabled\n */\n isInteractiveMode(): boolean {\n return this.interactiveManager.isInteractive();\n }\n\n /**\n * Check if the manager is currently processing an interactive confirmation\n */\n isProcessingInteractive(): boolean {\n return this.interactiveManager.isProcessing();\n }\n}\n","import type {\n MinimalBackupData,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { baseMinimalSaveToFile, baseSaveToFile } from \"document-model/node\";\nimport { mkdir } from \"fs/promises\";\nimport { join } from \"path\";\nimport { logger } from \"../../logger.js\";\n\nconst BACKUP_FOLDER = \"backup-documents\";\n\n/**\n * Exports a document to the backup directory.\n * Creates the backup directory if it doesn't exist.\n *\n * @param document - The document to backup\n * @param workingDir - Current working directory\n * @param extension - File extension for the document type (without dot)\n * @param name - Name of the document to use for the backup file (optional)\n * @returns Promise resolving to the backup file path, or undefined if backup failed\n */\nexport async function backupDocument(\n document: PHDocument,\n workingDir: string,\n extension: string = \"\",\n name?: string,\n): Promise<string | undefined> {\n const docName = name ?? document.header.name;\n\n try {\n const backupPath = join(workingDir, BACKUP_FOLDER);\n await mkdir(backupPath, { recursive: true });\n\n const filePath = await baseSaveToFile(\n document,\n backupPath,\n extension,\n docName,\n );\n\n logger.debug(`📁 Document backed up to: ${filePath}`);\n return filePath;\n } catch (error) {\n logger.warn(`⚠️ Failed to backup document \"${docName}\":`, error);\n return undefined;\n }\n}\n\n/**\n * Creates a minimal backup of a document from strand data.\n * Used when the full document is not available (e.g., in onOperations handler).\n */\nexport async function minimalBackupDocument(\n data: MinimalBackupData,\n workingDir: string,\n extension?: string,\n): Promise<string | undefined> {\n try {\n const backupPath = join(workingDir, BACKUP_FOLDER);\n await mkdir(backupPath, { recursive: true });\n\n const filePath = await baseMinimalSaveToFile(\n data,\n backupPath,\n extension ?? \"\",\n );\n\n logger.debug(`Document backed up to: ${filePath}`);\n return filePath;\n } catch (error) {\n logger.warn(`Failed to backup document \"${data.name}\":`, error);\n return undefined;\n }\n}\n","import { generateDriveEditor, generateManifest } from \"@powerhousedao/codegen\";\nimport type {\n AppModuleGlobalState,\n AppModulePHState,\n} from \"@powerhousedao/vetra/document-models/app-module\";\nimport { kebabCase } from \"change-case\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for app documents\n */\nexport class AppGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/app\";\n\n /**\n * Parse and extract the global state from the serialized state string\n */\n private extractGlobalState(\n input: CodegenInput,\n ): AppModuleGlobalState | undefined {\n if (!input.state) {\n return undefined;\n }\n const fullState = input.state as AppModulePHState;\n return fullState.global;\n }\n\n /**\n * Validate if this app strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.debug(`No state found for app: ${input.documentId}`);\n return false;\n }\n\n // Check if we have a valid app name and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for app: ${input.documentId}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `App not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.error(`No state found for app: ${input.documentId}`);\n return;\n }\n\n // Check if we have a valid app name and it's confirmed\n if (state.name && state.status === \"CONFIRMED\") {\n logger.info(`🔄 Starting drive editor generation for app: ${state.name}`);\n try {\n // Generate app ID using kebabCase\n const appId: string = kebabCase(state.name);\n // Generate the drive editor using the codegen function\n await generateDriveEditor({\n ...this.config.PH_CONFIG,\n driveEditorName: state.name,\n driveEditorId: appId,\n allowedDocumentTypes: state.allowedDocumentTypes ?? [],\n isDragAndDropEnabled: state.isDragAndDropEnabled,\n useTsMorph: USE_TS_MORPH,\n });\n\n logger.info(\n `✅ Drive editor generation completed successfully for app: ${state.name}`,\n );\n\n // Update the manifest with the new app\n try {\n logger.debug(\n `🔄 Updating manifest with app: ${state.name} (ID: ${appId})`,\n );\n\n generateManifest(\n {\n apps: [\n {\n id: appId,\n name: state.name,\n driveEditor: appId,\n } as any,\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for app: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for app ${state.name}:`,\n manifestError,\n );\n // Don't throw here - drive editor generation was successful\n }\n\n // Backup the document\n const fullState = input.state as AppModulePHState;\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during drive editor generation for app ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping drive editor generation - missing name for app`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping drive editor generation - app \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n","import { generateEditor, generateManifest } from \"@powerhousedao/codegen\";\nimport { kebabCase } from \"change-case\";\nimport type {\n DocumentEditorPHState,\n DocumentEditorState,\n} from \"../../../../document-models/document-editor/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for document editor documents\n */\nexport class DocumentEditorGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/document-editor\";\n\n /**\n * Parse and extract the global state from the serialized state string\n */\n private extractGlobalState(\n input: CodegenInput,\n ): DocumentEditorState | undefined {\n if (!input.state) {\n return undefined;\n }\n const fullState = input.state as DocumentEditorPHState;\n return fullState.global;\n }\n\n /**\n * Validate if this document editor strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.debug(`No state found for document editor: ${input.documentId}`);\n return false;\n }\n\n // Check if we have a valid editor name, document types, and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for document editor: ${input.documentId}`);\n return false;\n }\n\n if (!state.documentTypes || state.documentTypes.length === 0) {\n logger.debug(\n `No document types found for document editor: ${state.name}`,\n );\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Document editor not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.error(`No state found for document editor: ${input.documentId}`);\n return;\n }\n\n // Validation is already done in shouldProcess, so we can proceed directly\n logger.info(`🔄 Starting editor generation for: ${state.name}`);\n try {\n // Extract document types from the state\n const documentTypes = state.documentTypes.map((dt) => dt.documentType);\n\n // Generate editor ID using kebabCase\n const editorId: string = kebabCase(state.name);\n\n // Generate the editor using the codegen function\n await generateEditor({\n ...this.config.PH_CONFIG,\n editorName: state.name,\n documentTypes: documentTypes,\n editorId: editorId,\n useTsMorph: USE_TS_MORPH,\n });\n\n logger.info(\n `✅ Editor generation completed successfully for: ${state.name}`,\n );\n\n // Update the manifest with the new editor\n try {\n logger.debug(\n `🔄 Updating manifest with editor: ${state.name} (ID: ${editorId})`,\n );\n\n generateManifest(\n {\n editors: [\n {\n id: editorId,\n name: state.name,\n documentTypes: documentTypes,\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for editor: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for editor ${state.name}:`,\n manifestError,\n );\n // Don't throw here - editor generation was successful\n }\n\n // Backup the document\n const fullState = input.state as DocumentEditorPHState;\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during editor generation for ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n // Don't throw - let codegen continue with other documents\n return;\n }\n }\n}\n","import {\n generateFromDocument,\n generateManifest,\n validateDocumentModelState,\n} from \"@powerhousedao/codegen\";\nimport type {\n DocumentModelGlobalState,\n DocumentModelPHState,\n} from \"@powerhousedao/shared/document-model\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { USE_TS_MORPH, USE_VERSIONING } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for document model documents\n */\nexport class DocumentModelGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/document-model\";\n\n /**\n * Parse and extract the global state from the serialized state string\n */\n private extractGlobalState(\n input: CodegenInput,\n ): DocumentModelGlobalState | undefined {\n if (!input.state) {\n return undefined;\n }\n const fullState = input.state as DocumentModelPHState;\n return fullState.global;\n }\n\n /**\n * Validate if this document model strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n // Extract the global state from the full document state\n const globalState = this.extractGlobalState(input);\n if (!globalState) {\n logger.debug(\n `>>> No global state found for document model: ${input.documentId}`,\n );\n return false;\n }\n\n const validationResult = validateDocumentModelState(globalState);\n if (!validationResult.isValid) {\n const errorList = validationResult.errors\n .map((error) => ` - ${error}`)\n .join(\"\\n\");\n logger.info(\n `⚠️ Skipped code generation for '${globalState.name || input.documentId}' due to validation errors:\\n${errorList}`,\n );\n return false;\n }\n\n logger.info(\n `Document model ${globalState.name} is valid, proceeding with code generation`,\n );\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const globalState = this.extractGlobalState(input);\n if (!globalState) {\n logger.error(\n `❌ No global state found for document model: ${input.documentId}`,\n );\n return;\n }\n // Validation is already done in shouldProcess, so we can proceed directly\n logger.debug(\n `🔄 Starting code generation for document model: ${globalState.name}`,\n );\n try {\n await generateFromDocument({\n documentModelState: globalState,\n config: this.config.PH_CONFIG,\n useTsMorph: USE_TS_MORPH,\n useVersioning: USE_VERSIONING,\n });\n logger.info(\n `✅ Code generation completed successfully for: ${globalState.name}`,\n );\n\n // Update the manifest with the new document model\n try {\n logger.debug(\n `🔄 Updating manifest with document model: ${globalState.name} (ID: ${globalState.id})`,\n );\n\n generateManifest(\n {\n documentModels: [\n {\n id: globalState.id,\n name: globalState.name,\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for document model: ${globalState.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for document model ${globalState.name}:`,\n manifestError,\n );\n // Don't throw here - code generation was successful\n }\n\n // Backup the document\n const fullState = input.state as DocumentModelPHState;\n const extension = globalState.extension?.replace(/^\\.+|\\.+$/g, \"\") || \"\";\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: globalState.name,\n },\n this.config.CURRENT_WORKING_DIR,\n extension,\n );\n } catch (error) {\n logger.error(\n `❌ Error during code generation for ${globalState.name}:`,\n error,\n );\n // Don't throw - let codegen continue with other documents\n return;\n }\n }\n}\n","import { generateManifest } from \"@powerhousedao/codegen\";\nimport type {\n VetraPackagePHState,\n VetraPackageState,\n} from \"../../../../document-models/vetra-package/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for package documents\n */\nexport class PackageGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/package\";\n\n /**\n * Validate if this package strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n if (!input.state) {\n logger.debug(`>>> No state found for package: ${input.documentId}`);\n return false;\n }\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const fullState = input.state as VetraPackagePHState;\n const state = fullState as unknown as VetraPackageState;\n\n logger.info(\"🔄 Generating manifest for package\");\n generateManifest(\n {\n name: state.name ?? \"\",\n category: state.category ?? \"\",\n description: state.description ?? \"\",\n publisher: {\n name: state.author?.name ?? \"\",\n url: state.author?.website ?? \"\",\n },\n },\n this.config.CURRENT_WORKING_DIR,\n );\n logger.info(\"✅ Manifest generated successfully\");\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: \"vetra-package\",\n },\n this.config.CURRENT_WORKING_DIR,\n );\n }\n}\n","import { generateProcessor } from \"@powerhousedao/codegen\";\nimport {\n PROCESSOR_APPS,\n type ProcessorApp,\n type ProcessorApps,\n} from \"@powerhousedao/shared/processors\";\nimport type {\n ProcessorModulePHState,\n ProcessorModuleState,\n} from \"../../../../document-models/processor-module/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for processor documents\n */\nexport class ProcessorGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/processor\";\n\n /**\n * Parse and extract the global state from the serialized state string\n */\n private extractGlobalState(\n input: CodegenInput,\n ): ProcessorModuleState | undefined {\n if (!input.state) {\n return undefined;\n }\n const fullState = input.state as ProcessorModulePHState;\n return fullState.global;\n }\n\n /**\n * Validate if this processor strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.debug(`No state found for processor: ${input.documentId}`);\n return false;\n }\n\n // Check if we have a valid processor name, type, document types, and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for processor: ${input.documentId}`);\n return false;\n }\n\n if (!state.type) {\n logger.debug(`No type found for processor: ${state.name}`);\n return false;\n }\n\n if (!state.documentTypes || state.documentTypes.length === 0) {\n logger.debug(`No document types found for processor: ${state.name}`);\n return false;\n }\n\n if (!state.processorApps || state.processorApps.length === 0) {\n logger.debug(`No processor apps found for processor: ${state.name}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Processor not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.error(`No state found for processor: ${input.documentId}`);\n return;\n }\n\n // Check if we have a valid processor name, type, document types, and it's confirmed\n if (\n state.name &&\n state.type &&\n state.documentTypes.length > 0 &&\n state.processorApps.length > 0 &&\n state.status === \"CONFIRMED\"\n ) {\n logger.info(`🔄 Starting processor generation for: ${state.name}`);\n try {\n // Map the type value from document state to generateProcessor expected values\n let processorType: \"analytics\" | \"relationalDb\";\n if (state.type === \"analytics\") {\n processorType = \"analytics\";\n } else if (state.type === \"relational\") {\n processorType = \"relationalDb\";\n } else {\n logger.error(`❌ Unsupported processor type: ${state.type}`);\n return;\n }\n\n // Extract document types from the state\n const documentTypes = state.documentTypes.map((dt) => dt.documentType);\n\n const processorApps = state.processorApps;\n\n if (!isProcessorApps(processorApps)) {\n logger.error(\n `❌ Unsupported processor apps: ${processorApps.join(\", \")}`,\n );\n return;\n }\n\n // Generate the processor using the codegen function\n await generateProcessor({\n processorName: state.name,\n processorType,\n documentTypes,\n skipFormat: this.config.PH_CONFIG.skipFormat,\n useTsMorph: USE_TS_MORPH,\n processorApps,\n });\n\n logger.info(\n `✅ Processor generation completed successfully for: ${state.name}`,\n );\n\n // Backup the document\n const fullState = input.state as ProcessorModulePHState;\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during processor generation for ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping processor generation - missing name for processor`,\n );\n return;\n } else if (!state.type) {\n logger.error(\n `❌ Skipping processor generation - missing type for processor \"${state.name}\"`,\n );\n return;\n } else if (state.documentTypes.length === 0) {\n logger.error(\n `❌ Skipping processor generation - missing document types for processor \"${state.name}\"`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping processor generation - processor \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n\nfunction isProcessorApps(input: readonly string[]): input is ProcessorApps {\n if (input.length === 0) return false;\n if (new Set(input).size !== input.length) {\n return false;\n }\n if (!input.every((i) => PROCESSOR_APPS.includes(i as ProcessorApp)))\n return false;\n\n return true;\n}\n","import { generateManifest, generateSubgraph } from \"@powerhousedao/codegen\";\nimport { kebabCase } from \"change-case\";\nimport type {\n SubgraphModulePHState,\n SubgraphModuleState,\n} from \"../../../../document-models/subgraph-module/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport type { CodegenInput } from \"../types.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for subgraph documents\n */\nexport class SubgraphGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/subgraph\";\n\n /**\n * Parse and extract the global state from the serialized state string\n */\n private extractGlobalState(\n input: CodegenInput,\n ): SubgraphModuleState | undefined {\n if (!input.state) {\n return undefined;\n }\n const fullState = input.state as SubgraphModulePHState;\n return fullState.global;\n }\n\n /**\n * Validate if this subgraph strand should be processed\n */\n shouldProcess(input: CodegenInput): boolean {\n // First run base validation\n if (!super.shouldProcess(input)) {\n return false;\n }\n\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.debug(`No state found for subgraph: ${input.documentId}`);\n return false;\n }\n\n // Check if we have a valid subgraph name and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for subgraph: ${input.documentId}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Subgraph not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(input: CodegenInput): Promise<void> {\n const state = this.extractGlobalState(input);\n if (!state) {\n logger.error(`No state found for subgraph: ${input.documentId}`);\n return;\n }\n\n // Check if we have a valid subgraph name and it's confirmed\n if (state.name && state.status === \"CONFIRMED\") {\n logger.info(`🔄 Starting subgraph generation for: ${state.name}`);\n try {\n // Generate subgraph ID using kebabCase\n const subgraphId: string = kebabCase(state.name);\n\n await generateSubgraph(state.name, null, this.config.PH_CONFIG);\n logger.info(\n `✅ Subgraph generation completed successfully for: ${state.name}`,\n );\n\n // Update the manifest with the new subgraph\n try {\n logger.debug(\n `🔄 Updating manifest with subgraph: ${state.name} (ID: ${subgraphId})`,\n );\n\n generateManifest(\n {\n subgraphs: [\n {\n id: subgraphId,\n name: state.name,\n documentTypes: [],\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for subgraph: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for subgraph ${state.name}:`,\n manifestError,\n );\n // Don't throw here - subgraph generation was successful\n }\n\n // Backup the document\n const fullState = input.state as SubgraphModulePHState;\n await minimalBackupDocument(\n {\n documentId: input.documentId,\n documentType: input.documentType,\n branch: input.branch,\n state: fullState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during subgraph generation for ${state.name}:`,\n error,\n );\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping subgraph generation - missing name for subgraph`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping subgraph generation - subgraph \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n","import type { BaseDocumentGen } from \"./base-document-gen.js\";\nimport { DocumentCodegenManager } from \"./document-codegen-manager.js\";\nimport {\n AppGenerator,\n DocumentEditorGenerator,\n DocumentModelGenerator,\n PackageGenerator,\n ProcessorGenerator,\n SubgraphGenerator,\n} from \"./generators/index.js\";\nimport type { Config } from \"./types.js\";\n\n/**\n * Factory class for creating and configuring DocumentCodegenManager instances\n * with all the standard generators pre-registered\n */\nexport class DocumentCodegenFactory {\n /**\n * Create a DocumentCodegenManager with all standard generators registered\n */\n static createManager(\n config: Config,\n interactiveMode: boolean = false,\n ): DocumentCodegenManager {\n const manager = new DocumentCodegenManager(config, interactiveMode);\n\n // Register all the standard generators\n manager.registerGenerator(\n \"powerhouse/document-model\",\n DocumentModelGenerator,\n );\n manager.registerGenerator(\"powerhouse/package\", PackageGenerator);\n manager.registerGenerator(\"powerhouse/app\", AppGenerator);\n manager.registerGenerator(\n \"powerhouse/document-editor\",\n DocumentEditorGenerator,\n );\n manager.registerGenerator(\"powerhouse/subgraph\", SubgraphGenerator);\n manager.registerGenerator(\"powerhouse/processor\", ProcessorGenerator);\n\n return manager;\n }\n\n /**\n * Create a DocumentCodegenManager with only specific generators\n */\n static createManagerWithGenerators(\n config: Config,\n generators: Array<new (config: Config) => any>,\n interactiveMode: boolean = false,\n ): DocumentCodegenManager {\n const manager = new DocumentCodegenManager(config, interactiveMode);\n\n for (const generatorClass of generators) {\n const generator = new generatorClass(config) as BaseDocumentGen;\n const supportedTypes = generator.getSupportedDocumentTypes();\n\n for (const documentType of supportedTypes) {\n manager.registerGenerator(documentType, generatorClass);\n }\n }\n\n return manager;\n }\n\n /**\n * Get all available generator classes\n */\n static getAvailableGenerators() {\n return {\n DocumentModelGenerator,\n PackageGenerator,\n AppGenerator,\n DocumentEditorGenerator,\n SubgraphGenerator,\n ProcessorGenerator,\n };\n }\n}\n","import { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n IProcessor,\n OperationWithContext,\n} from \"@powerhousedao/reactor-browser\";\nimport type { DocumentCodegenManager } from \"./document-handlers/document-codegen-manager.js\";\nimport { DocumentCodegenFactory } from \"./document-handlers/index.js\";\nimport type { CodegenInput } from \"./document-handlers/types.js\";\nimport { logger } from \"./logger.js\";\n\nconst PH_CONFIG = getConfig();\nconst CURRENT_WORKING_DIR = process.cwd();\n\nexport class CodegenProcessor implements IProcessor {\n private manager: DocumentCodegenManager;\n\n constructor(interactiveMode = false) {\n this.manager = DocumentCodegenFactory.createManager(\n {\n PH_CONFIG,\n CURRENT_WORKING_DIR,\n },\n interactiveMode,\n );\n\n if (interactiveMode) {\n logger.info(`CodegenProcessor initialized with interactive mode enabled`);\n } else {\n logger.debug(\n `CodegenProcessor initialized with interactive mode disabled`,\n );\n }\n }\n\n async onOperations(operations: OperationWithContext[]): Promise<void> {\n logger.info(\"CodegenProcessor.onOperations()\");\n\n for (const { context } of operations) {\n const generator = this.manager.getGenerator(context.documentType);\n if (!generator) {\n logger.debug(\n `No generator found for document type: ${context.documentType}`,\n );\n continue;\n }\n\n const input: CodegenInput = {\n documentId: context.documentId,\n documentType: context.documentType,\n scope: context.scope,\n branch: context.branch,\n state: context.resultingState\n ? JSON.parse(context.resultingState)\n : undefined,\n };\n\n const shouldProcess = generator.shouldProcess(input);\n if (shouldProcess) {\n await this.manager.routeAndGenerate(input);\n }\n }\n }\n\n async onDisconnect() {}\n\n // Utility methods for external configuration and monitoring\n public setInteractiveMode(enabled: boolean): void {\n this.manager.setInteractiveMode(enabled);\n }\n\n public isInteractive(): boolean {\n return this.manager.isInteractiveMode();\n }\n\n public isProcessingInteractive(): boolean {\n return this.manager.isProcessingInteractive();\n }\n}\n"],"mappings":"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"}
|
|
@@ -33,5 +33,5 @@ declare class VetraReadModelProcessor implements IProcessor {
|
|
|
33
33
|
onDisconnect(): Promise<void>;
|
|
34
34
|
}
|
|
35
35
|
//#endregion
|
|
36
|
-
export {
|
|
37
|
-
//# sourceMappingURL=index-
|
|
36
|
+
export { VetraReadModelProcessor as t };
|
|
37
|
+
//# sourceMappingURL=index-COsHJRmm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-COsHJRmm.d.ts","names":[],"sources":["../processors/vetra-read-model/schema.ts","../processors/vetra-read-model/index.ts"],"mappings":";;;;KAEY,SAAA,MACV,CAAA,SAAU,UAAA,8BACN,UAAA,CAAW,CAAA,EAAG,CAAA,cAAe,CAAA,IAC7B,UAAA,CAAW,CAAA,EAAG,CAAA,cAAe,CAAA;AAAA,KAEvB,SAAA,GAAY,UAAA,CAAW,IAAA,EAAM,IAAA,WAAe,IAAA;AAAA,UAEvC,YAAA;EACf,WAAA;EACA,cAAA;EACA,QAAA;EACA,UAAA,EAAY,SAAA,CAAU,SAAA;EACtB,WAAA;EACA,WAAA;EACA,UAAA;EACA,QAAA;EACA,mBAAA;EACA,oBAAA;EACA,wBAAA,EAA0B,SAAA;EAC1B,IAAA;EACA,OAAA;EACA,UAAA,EAAY,SAAA,CAAU,SAAA;EACtB,QAAA;AAAA;AAAA,UAGe,EAAA;EACf,aAAA,EAAe,YAAA;AAAA;;;cCjBJ,uBAAA,YAAmC,UAAA;EAAA,QACtC,YAAA;cAEI,YAAA,EAAc,MAAA,CAAO,EAAA;EAI3B,YAAA,CAAa,UAAA,EAAY,oBAAA,KAAyB,OAAA;EA0DlD,YAAA,CAAA,GAAY,OAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../processors/codegen/index.ts"],"mappings":";;;cAaa,gBAAA,YAA4B,UAAA;EAAA,QAC/B,OAAA;cAEI,eAAA;EAkBN,YAAA,CAAa,UAAA,EAAY,oBAAA,KAAyB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../processors/codegen/index.ts"],"mappings":";;;cAaa,gBAAA,YAA4B,UAAA;EAAA,QAC/B,OAAA;cAEI,eAAA;EAkBN,YAAA,CAAa,UAAA,EAAY,oBAAA,KAAyB,OAAA;EA6BlD,YAAA,CAAA,GAAY,OAAA;EAGX,kBAAA,CAAmB,OAAA;EAInB,aAAA,CAAA;EAIA,uBAAA,CAAA;AAAA"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { CodegenProcessor } from "./codegen/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { t as VetraReadModelProcessor } from "../index-COsHJRmm.js";
|
|
3
3
|
import { PHDocumentHeader } from "@powerhousedao/shared/document-model";
|
|
4
4
|
import { IProcessorHostModule, ProcessorRecord } from "@powerhousedao/reactor-browser";
|
|
5
|
-
import { IProcessorHostModuleLegacy, IProcessorLegacy, InternalTransmitterUpdate, ProcessorRecordLegacy, RelationalDbProcessorLegacy } from "document-drive";
|
|
6
5
|
|
|
7
6
|
//#region processors/codegen/factory.d.ts
|
|
8
7
|
declare const codegenProcessorFactory: (module: IProcessorHostModule) => (driveHeader: PHDocumentHeader) => ProcessorRecord[];
|
|
@@ -16,33 +15,5 @@ declare const vetraReadModelProcessorFactory: (module: IProcessorHostModule) =>
|
|
|
16
15
|
*/
|
|
17
16
|
declare const processorFactory: (module: IProcessorHostModule) => (driveHeader: PHDocumentHeader) => Promise<ProcessorRecord[]>;
|
|
18
17
|
//#endregion
|
|
19
|
-
|
|
20
|
-
declare class CodegenProcessorLegacy implements IProcessorLegacy {
|
|
21
|
-
private manager;
|
|
22
|
-
constructor(interactiveMode?: boolean);
|
|
23
|
-
onStrands(strands: InternalTransmitterUpdate[]): Promise<void>;
|
|
24
|
-
onDisconnect(): Promise<void>;
|
|
25
|
-
setInteractiveMode(enabled: boolean): void;
|
|
26
|
-
isInteractive(): boolean;
|
|
27
|
-
isProcessingInteractive(): boolean;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region processors/codegen/factory.legacy.d.ts
|
|
31
|
-
declare const codegenProcessorFactoryLegacy: (module: IProcessorHostModuleLegacy) => (driveHeader: PHDocumentHeader) => ProcessorRecordLegacy[];
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region processors/vetra-read-model/index.legacy.d.ts
|
|
34
|
-
declare class VetraReadModelProcessorLegacy extends RelationalDbProcessorLegacy<DB> {
|
|
35
|
-
static getNamespace(driveId: string): string;
|
|
36
|
-
initAndUpgrade(): Promise<void>;
|
|
37
|
-
onStrands(strands: InternalTransmitterUpdate[]): Promise<void>;
|
|
38
|
-
onDisconnect(): Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
//#endregion
|
|
41
|
-
//#region processors/vetra-read-model/factory.legacy.d.ts
|
|
42
|
-
declare const vetraReadModelProcessorFactoryLegacy: (module: IProcessorHostModuleLegacy) => (driveHeader: PHDocumentHeader) => Promise<ProcessorRecordLegacy[]>;
|
|
43
|
-
//#endregion
|
|
44
|
-
//#region processors/factory.legacy.d.ts
|
|
45
|
-
declare const processorFactoryLegacy: (module: IProcessorHostModuleLegacy) => (driveHeader: PHDocumentHeader) => Promise<ProcessorRecordLegacy[]>;
|
|
46
|
-
//#endregion
|
|
47
|
-
export { CodegenProcessor, CodegenProcessorLegacy, VetraReadModelProcessor, VetraReadModelProcessorLegacy, codegenProcessorFactory, codegenProcessorFactoryLegacy, processorFactory, processorFactoryLegacy, vetraReadModelProcessorFactory, vetraReadModelProcessorFactoryLegacy };
|
|
18
|
+
export { CodegenProcessor, VetraReadModelProcessor, codegenProcessorFactory, processorFactory, vetraReadModelProcessorFactory };
|
|
48
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../processors/codegen/factory.ts","../../processors/vetra-read-model/factory.ts","../../processors/factory.ts"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../processors/codegen/factory.ts","../../processors/vetra-read-model/factory.ts","../../processors/factory.ts"],"mappings":";;;;;;cAsCa,uBAAA,GACV,MAAA,EAAQ,oBAAA,MACR,WAAA,EAAa,gBAAA,KAAmB,eAAA;;;cC/BtB,8BAAA,GACV,MAAA,EAAQ,oBAAA,MACF,WAAA,EAAa,gBAAA,KAAmB,OAAA,CAAQ,eAAA;;;;;;cCEpC,gBAAA,GAAoB,MAAA,EAAQ,oBAAA,MASzB,WAAA,EAAa,gBAAA,KAAgB,OAAA,CAAA,eAAA"}
|
package/dist/processors/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as CodegenProcessor } from "../codegen-DOq2xhy3.js";
|
|
2
2
|
import { t as logger } from "../logger-BLNtquAC.js";
|
|
3
3
|
import { VetraReadModelProcessor } from "./vetra-read-model/index.js";
|
|
4
|
-
import { getConfig } from "@powerhousedao/config/node";
|
|
5
4
|
import { VETRA_PROCESSOR_CONFIG_KEY } from "@powerhousedao/config";
|
|
6
|
-
import { RelationalDbProcessorLegacy } from "document-drive";
|
|
7
5
|
//#region processors/codegen/factory.ts
|
|
8
6
|
/**
|
|
9
7
|
* Determines if a drive header matches the Vetra drive criteria.
|
|
@@ -11,7 +9,7 @@ import { RelationalDbProcessorLegacy } from "document-drive";
|
|
|
11
9
|
* @param explicitDriveId - Optional explicit drive ID from config (if set, uses exact match)
|
|
12
10
|
* @returns true if the drive is a Vetra drive, false otherwise
|
|
13
11
|
*/
|
|
14
|
-
function isDriveVetra
|
|
12
|
+
function isDriveVetra(driveHeader, driveIdFromConfig) {
|
|
15
13
|
if (driveIdFromConfig) return driveHeader.slug === driveIdFromConfig || driveHeader.id === driveIdFromConfig;
|
|
16
14
|
const matchesPattern = (identifier) => {
|
|
17
15
|
const lower = identifier.toLowerCase();
|
|
@@ -21,7 +19,7 @@ function isDriveVetra$1(driveHeader, driveIdFromConfig) {
|
|
|
21
19
|
}
|
|
22
20
|
const codegenProcessorFactory = (module) => (driveHeader) => {
|
|
23
21
|
const vetraConfig = (module.config ?? /* @__PURE__ */ new Map()).get(VETRA_PROCESSOR_CONFIG_KEY);
|
|
24
|
-
if (!isDriveVetra
|
|
22
|
+
if (!isDriveVetra(driveHeader, vetraConfig?.driveId)) {
|
|
25
23
|
logger.info(`Drive ${driveHeader.slug} is not a Vetra drive, skipping codegen processor`);
|
|
26
24
|
return [];
|
|
27
25
|
}
|
|
@@ -82,171 +80,6 @@ const processorFactory = (module) => {
|
|
|
82
80
|
};
|
|
83
81
|
};
|
|
84
82
|
//#endregion
|
|
85
|
-
|
|
86
|
-
const PH_CONFIG = getConfig();
|
|
87
|
-
const CURRENT_WORKING_DIR = process.cwd();
|
|
88
|
-
var CodegenProcessorLegacy = class {
|
|
89
|
-
manager;
|
|
90
|
-
constructor(interactiveMode = false) {
|
|
91
|
-
this.manager = DocumentCodegenFactory.createManager({
|
|
92
|
-
PH_CONFIG,
|
|
93
|
-
CURRENT_WORKING_DIR
|
|
94
|
-
}, interactiveMode);
|
|
95
|
-
if (interactiveMode) logger.info(`CodegenProcessorLegacy initialized with interactive mode enabled`);
|
|
96
|
-
else logger.debug(`CodegenProcessorLegacy initialized with interactive mode disabled`);
|
|
97
|
-
}
|
|
98
|
-
async onStrands(strands) {
|
|
99
|
-
logger.info(">>> CodegenProcessorLegacy.onStrands()");
|
|
100
|
-
const validStrands = strands.filter((strand) => {
|
|
101
|
-
const generator = this.manager.getGenerator(strand.documentType);
|
|
102
|
-
if (!generator) {
|
|
103
|
-
logger.debug(`>>> No generator found for document type: ${strand.documentType}`);
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
const shouldProcessResult = generator.shouldProcess(strand);
|
|
107
|
-
if (!shouldProcessResult) logger.debug(`>>> Generator validation failed for ${strand.documentType}:${strand.documentId}, skipping processing`);
|
|
108
|
-
return shouldProcessResult;
|
|
109
|
-
});
|
|
110
|
-
if (validStrands.length > 0) {
|
|
111
|
-
logger.debug(`>>> Processing ${validStrands.length} valid strands (out of ${strands.length} total)`);
|
|
112
|
-
for (const strand of validStrands) await this.manager.routeAndGenerate(strand);
|
|
113
|
-
} else logger.debug(`>>> No valid strands to process (${strands.length} strands received)`);
|
|
114
|
-
}
|
|
115
|
-
async onDisconnect() {}
|
|
116
|
-
setInteractiveMode(enabled) {
|
|
117
|
-
this.manager.setInteractiveMode(enabled);
|
|
118
|
-
}
|
|
119
|
-
isInteractive() {
|
|
120
|
-
return this.manager.isInteractiveMode();
|
|
121
|
-
}
|
|
122
|
-
isProcessingInteractive() {
|
|
123
|
-
return this.manager.isProcessingInteractive();
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
//#endregion
|
|
127
|
-
//#region processors/codegen/factory.legacy.ts
|
|
128
|
-
/**
|
|
129
|
-
* Determines if a drive header matches the Vetra drive criteria.
|
|
130
|
-
* @param driveHeader - The drive header to check
|
|
131
|
-
* @param explicitDriveId - Optional explicit drive ID from config (if set, uses exact match)
|
|
132
|
-
* @returns true if the drive is a Vetra drive, false otherwise
|
|
133
|
-
*/
|
|
134
|
-
function isDriveVetra(driveHeader, driveIdFromConfig) {
|
|
135
|
-
if (driveIdFromConfig) return driveHeader.slug === driveIdFromConfig || driveHeader.id === driveIdFromConfig;
|
|
136
|
-
const matchesPattern = (identifier) => {
|
|
137
|
-
const lower = identifier.toLowerCase();
|
|
138
|
-
return lower === "vetra" || lower.startsWith("vetra-");
|
|
139
|
-
};
|
|
140
|
-
return matchesPattern(driveHeader.slug) || matchesPattern(driveHeader.id);
|
|
141
|
-
}
|
|
142
|
-
const codegenProcessorFactoryLegacy = (module) => (driveHeader) => {
|
|
143
|
-
const vetraConfig = (module.config ?? /* @__PURE__ */ new Map()).get(VETRA_PROCESSOR_CONFIG_KEY);
|
|
144
|
-
if (!isDriveVetra(driveHeader, vetraConfig?.driveId)) {
|
|
145
|
-
logger.info(`Drive ${driveHeader.slug} is not a Vetra drive, skipping codegen processor`);
|
|
146
|
-
return [];
|
|
147
|
-
}
|
|
148
|
-
logger.info(`Drive ${driveHeader.slug} is a Vetra drive, using codegen processor (legacy)`);
|
|
149
|
-
return [{
|
|
150
|
-
processor: new CodegenProcessorLegacy(vetraConfig?.interactive),
|
|
151
|
-
filter: {
|
|
152
|
-
branch: ["main"],
|
|
153
|
-
documentId: ["*"],
|
|
154
|
-
documentType: [
|
|
155
|
-
"powerhouse/document-model",
|
|
156
|
-
"powerhouse/package",
|
|
157
|
-
"powerhouse/document-editor",
|
|
158
|
-
"powerhouse/subgraph",
|
|
159
|
-
"powerhouse/processor",
|
|
160
|
-
"powerhouse/app"
|
|
161
|
-
],
|
|
162
|
-
scope: ["global"]
|
|
163
|
-
}
|
|
164
|
-
}];
|
|
165
|
-
};
|
|
166
|
-
//#endregion
|
|
167
|
-
//#region processors/vetra-read-model/index.legacy.ts
|
|
168
|
-
var VetraReadModelProcessorLegacy = class extends RelationalDbProcessorLegacy {
|
|
169
|
-
static getNamespace(driveId) {
|
|
170
|
-
return super.getNamespace("vetra-packages");
|
|
171
|
-
}
|
|
172
|
-
async initAndUpgrade() {
|
|
173
|
-
await up(this.relationalDb);
|
|
174
|
-
}
|
|
175
|
-
async onStrands(strands) {
|
|
176
|
-
if (strands.length === 0) return;
|
|
177
|
-
for (const strand of strands) {
|
|
178
|
-
if (strand.operations.length === 0) continue;
|
|
179
|
-
if (strand.documentType !== "powerhouse/package") continue;
|
|
180
|
-
const lastOperation = strand.operations[strand.operations.length - 1];
|
|
181
|
-
if (!lastOperation) continue;
|
|
182
|
-
const state = strand.state;
|
|
183
|
-
const getString = (val) => typeof val === "string" ? val : null;
|
|
184
|
-
const now = /* @__PURE__ */ new Date();
|
|
185
|
-
const operationTimestamp = new Date(parseInt(lastOperation.timestampUtcMs, 10));
|
|
186
|
-
await this.relationalDb.insertInto("vetra_package").values({
|
|
187
|
-
document_id: strand.documentId,
|
|
188
|
-
name: getString(state?.name),
|
|
189
|
-
description: getString(state?.description),
|
|
190
|
-
category: getString(state?.category),
|
|
191
|
-
author_name: getString(state?.author?.name),
|
|
192
|
-
author_website: getString(state?.author?.website),
|
|
193
|
-
keywords: state?.keywords ? JSON.stringify(state.keywords) : null,
|
|
194
|
-
github_url: getString(state?.githubUrl),
|
|
195
|
-
npm_url: getString(state?.npmUrl),
|
|
196
|
-
last_operation_index: lastOperation.index,
|
|
197
|
-
last_operation_hash: lastOperation.hash,
|
|
198
|
-
last_operation_timestamp: operationTimestamp,
|
|
199
|
-
drive_id: strand.driveId,
|
|
200
|
-
created_at: now,
|
|
201
|
-
updated_at: now
|
|
202
|
-
}).onConflict((oc) => oc.column("document_id").doUpdateSet({
|
|
203
|
-
name: getString(state?.name),
|
|
204
|
-
description: getString(state?.description),
|
|
205
|
-
category: getString(state?.category),
|
|
206
|
-
author_name: getString(state?.author?.name),
|
|
207
|
-
author_website: getString(state?.author?.website),
|
|
208
|
-
keywords: state?.keywords ? JSON.stringify(state.keywords) : null,
|
|
209
|
-
github_url: getString(state?.githubUrl),
|
|
210
|
-
npm_url: getString(state?.npmUrl),
|
|
211
|
-
last_operation_index: lastOperation.index,
|
|
212
|
-
last_operation_hash: lastOperation.hash,
|
|
213
|
-
last_operation_timestamp: operationTimestamp,
|
|
214
|
-
drive_id: strand.driveId,
|
|
215
|
-
updated_at: now
|
|
216
|
-
})).execute();
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async onDisconnect() {}
|
|
220
|
-
};
|
|
221
|
-
//#endregion
|
|
222
|
-
//#region processors/vetra-read-model/factory.legacy.ts
|
|
223
|
-
const vetraReadModelProcessorFactoryLegacy = (module) => async (driveHeader) => {
|
|
224
|
-
const namespace = VetraReadModelProcessorLegacy.getNamespace(driveHeader.id);
|
|
225
|
-
const store = await module.relationalDb.createNamespace(namespace);
|
|
226
|
-
const filter = {
|
|
227
|
-
branch: ["main"],
|
|
228
|
-
documentId: ["*"],
|
|
229
|
-
documentType: ["powerhouse/package"],
|
|
230
|
-
scope: ["global"]
|
|
231
|
-
};
|
|
232
|
-
return [{
|
|
233
|
-
processor: new VetraReadModelProcessorLegacy(namespace, filter, store),
|
|
234
|
-
filter
|
|
235
|
-
}];
|
|
236
|
-
};
|
|
237
|
-
//#endregion
|
|
238
|
-
//#region processors/factory.legacy.ts
|
|
239
|
-
const processorFactoryLegacy = (module) => {
|
|
240
|
-
const factories = [];
|
|
241
|
-
factories.push(vetraReadModelProcessorFactoryLegacy(module));
|
|
242
|
-
factories.push(codegenProcessorFactoryLegacy(module));
|
|
243
|
-
return async (driveHeader) => {
|
|
244
|
-
const processors = [];
|
|
245
|
-
for (const factory of factories) processors.push(...await factory(driveHeader));
|
|
246
|
-
return processors;
|
|
247
|
-
};
|
|
248
|
-
};
|
|
249
|
-
//#endregion
|
|
250
|
-
export { CodegenProcessor, CodegenProcessorLegacy, VetraReadModelProcessor, VetraReadModelProcessorLegacy, codegenProcessorFactory, codegenProcessorFactoryLegacy, processorFactory, processorFactoryLegacy, vetraReadModelProcessorFactory, vetraReadModelProcessorFactoryLegacy };
|
|
83
|
+
export { CodegenProcessor, VetraReadModelProcessor, codegenProcessorFactory, processorFactory, vetraReadModelProcessorFactory };
|
|
251
84
|
|
|
252
85
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isDriveVetra"],"sources":["../../processors/codegen/factory.ts","../../processors/vetra-read-model/migrations.ts","../../processors/vetra-read-model/factory.ts","../../processors/factory.ts","../../processors/codegen/index.legacy.ts","../../processors/codegen/factory.legacy.ts","../../processors/vetra-read-model/index.legacy.ts","../../processors/vetra-read-model/factory.legacy.ts","../../processors/factory.legacy.ts"],"sourcesContent":["import type { VetraProcessorConfigType } from \"@powerhousedao/config\";\nimport { VETRA_PROCESSOR_CONFIG_KEY } from \"@powerhousedao/config\";\nimport type {\n IProcessorHostModule,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { CodegenProcessor } from \"./index.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Determines if a drive header matches the Vetra drive criteria.\n * @param driveHeader - The drive header to check\n * @param explicitDriveId - Optional explicit drive ID from config (if set, uses exact match)\n * @returns true if the drive is a Vetra drive, false otherwise\n */\nfunction isDriveVetra(\n driveHeader: PHDocumentHeader,\n driveIdFromConfig?: string,\n): boolean {\n // If explicit drive ID is configured, use exact match\n if (driveIdFromConfig) {\n return (\n driveHeader.slug === driveIdFromConfig ||\n driveHeader.id === driveIdFromConfig\n );\n }\n\n // Otherwise, check if slug/id matches Vetra pattern\n // Matches \"vetra\" exactly or IDs starting with \"vetra-\" (case-insensitive)\n const matchesPattern = (identifier: string): boolean => {\n const lower = identifier.toLowerCase();\n return lower === \"vetra\" || lower.startsWith(\"vetra-\");\n };\n\n return matchesPattern(driveHeader.slug) || matchesPattern(driveHeader.id);\n}\n\nexport const codegenProcessorFactory =\n (module: IProcessorHostModule) =>\n (driveHeader: PHDocumentHeader): ProcessorRecord[] => {\n // Create the processor\n const processorsConfig = module.config ?? new Map<string, unknown>();\n const vetraConfig = processorsConfig.get(VETRA_PROCESSOR_CONFIG_KEY) as\n | VetraProcessorConfigType\n | undefined;\n\n // Check if this drive should use the Vetra processor\n if (!isDriveVetra(driveHeader, vetraConfig?.driveId)) {\n logger.info(\n `Drive ${driveHeader.slug} is not a Vetra drive, skipping codegen processor`,\n );\n return [];\n }\n\n logger.info(\n `Drive ${driveHeader.slug} is a Vetra drive, using codegen processor`,\n );\n\n const processor = new CodegenProcessor(vetraConfig?.interactive);\n return [\n {\n processor,\n filter: {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\n \"powerhouse/document-model\",\n \"powerhouse/package\",\n \"powerhouse/document-editor\",\n \"powerhouse/subgraph\",\n \"powerhouse/processor\",\n \"powerhouse/app\",\n ],\n scope: [\"global\"],\n },\n },\n ];\n };\n","import { type IRelationalDbLegacy } from \"document-drive\";\n\nexport async function up(db: IRelationalDbLegacy<any>): Promise<void> {\n // Create vetra_package table to store VetraPackage document state\n await db.schema\n .createTable(\"vetra_package\")\n .addColumn(\"document_id\", \"varchar(255)\", (col) => col.primaryKey()) // VetraPackage state fields\n .addColumn(\"name\", \"varchar(255)\")\n .addColumn(\"description\", \"text\")\n .addColumn(\"category\", \"varchar(255)\")\n .addColumn(\"author_name\", \"varchar(255)\")\n .addColumn(\"author_website\", \"varchar(512)\")\n .addColumn(\"keywords\", \"text\") // JSON array of {id, label}\n .addColumn(\"github_url\", \"varchar(512)\")\n .addColumn(\"npm_url\", \"varchar(512)\")\n .addColumn(\"drive_id\", \"varchar(255)\")\n // Document metadata\n .addColumn(\"last_operation_index\", \"integer\", (col) => col.notNull())\n .addColumn(\"last_operation_hash\", \"varchar(255)\", (col) => col.notNull())\n .addColumn(\"last_operation_timestamp\", \"timestamptz\", (col) =>\n col.notNull(),\n )\n .addColumn(\"created_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(\"now()\"),\n )\n .addColumn(\"updated_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(\"now()\"),\n )\n .ifNotExists()\n .execute();\n\n // Create indexes for common queries\n await db.schema\n .createIndex(\"idx_vetra_package_document_id\")\n .on(\"vetra_package\")\n .column(\"document_id\")\n .ifNotExists()\n .execute();\n\n await db.schema\n .createIndex(\"idx_vetra_package_name\")\n .on(\"vetra_package\")\n .column(\"name\")\n .ifNotExists()\n .execute();\n\n await db.schema\n .createIndex(\"idx_vetra_package_category\")\n .on(\"vetra_package\")\n .column(\"category\")\n .ifNotExists()\n .execute();\n}\n\nexport async function down(db: IRelationalDbLegacy<any>): Promise<void> {\n // Drop indexes first\n await db.schema.dropIndex(\"idx_vetra_package_category\").ifExists().execute();\n await db.schema.dropIndex(\"idx_vetra_package_name\").ifExists().execute();\n await db.schema\n .dropIndex(\"idx_vetra_package_document_id\")\n .ifExists()\n .execute();\n\n // Drop table\n await db.schema.dropTable(\"vetra_package\").ifExists().execute();\n}\n","import type {\n IProcessorHostModule,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { IRelationalDbLegacy } from \"document-drive\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { VetraReadModelProcessor } from \"./index.js\";\nimport { up } from \"./migrations.js\";\nimport type { DB } from \"./schema.js\";\n\nexport const vetraReadModelProcessorFactory =\n (module: IProcessorHostModule) =>\n async (driveHeader: PHDocumentHeader): Promise<ProcessorRecord[]> => {\n // Create namespace (same as legacy - all vetra packages share one namespace)\n const db = await module.relationalDb.createNamespace<DB>(\"vetra-packages\");\n\n // Run migrations (idempotent - uses ifNotExists)\n await up(db as IRelationalDbLegacy<DB>);\n\n // Create the processor with the relational database\n const processor = new VetraReadModelProcessor(db);\n return [\n {\n processor,\n filter: {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\"powerhouse/package\"],\n scope: [\"global\"],\n },\n },\n ];\n };\n","import type {\n IProcessorHostModule,\n ProcessorFactory,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { codegenProcessorFactory } from \"./codegen/factory.js\";\nimport { vetraReadModelProcessorFactory } from \"./vetra-read-model/factory.js\";\n\n/**\n * This file aggregates all processor factories for the new reactor\n */\n\nexport const processorFactory = (module: IProcessorHostModule) => {\n // Initialize all processor factories once with the module\n const factories: Array<ProcessorFactory> = [];\n\n // Add all processor factories\n factories.push(vetraReadModelProcessorFactory(module));\n factories.push(codegenProcessorFactory(module));\n\n // Return the inner function that will be called for each drive\n return async (driveHeader: PHDocumentHeader) => {\n const processors: ProcessorRecord[] = [];\n\n // Call each cached factory with the driveHeader\n for (const factory of factories) {\n processors.push(...(await factory(driveHeader, module.processorApp)));\n }\n\n return processors;\n };\n};\n","import { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n InternalTransmitterUpdate,\n IProcessorLegacy,\n} from \"document-drive\";\nimport type { DocumentCodegenManager } from \"./document-handlers/document-codegen-manager.js\";\nimport { DocumentCodegenFactory } from \"./document-handlers/index.js\";\nimport { logger } from \"./logger.js\";\n\nconst PH_CONFIG = getConfig();\nconst CURRENT_WORKING_DIR = process.cwd();\n\nexport class CodegenProcessorLegacy implements IProcessorLegacy {\n private manager: DocumentCodegenManager;\n\n constructor(interactiveMode = false) {\n this.manager = DocumentCodegenFactory.createManager(\n {\n PH_CONFIG,\n CURRENT_WORKING_DIR,\n },\n interactiveMode,\n );\n\n if (interactiveMode) {\n logger.info(\n `CodegenProcessorLegacy initialized with interactive mode enabled`,\n );\n } else {\n logger.debug(\n `CodegenProcessorLegacy initialized with interactive mode disabled`,\n );\n }\n }\n\n async onStrands(strands: InternalTransmitterUpdate[]): Promise<void> {\n logger.info(\">>> CodegenProcessorLegacy.onStrands()\");\n\n // Filter strands to only include those that should be processed\n const validStrands = strands.filter((strand) => {\n const generator = this.manager.getGenerator(strand.documentType);\n if (!generator) {\n logger.debug(\n `>>> No generator found for document type: ${strand.documentType}`,\n );\n return false;\n }\n\n // Use the required shouldProcess method for validation\n const shouldProcessResult = generator.shouldProcess(strand);\n if (!shouldProcessResult) {\n logger.debug(\n `>>> Generator validation failed for ${strand.documentType}:${strand.documentId}, skipping processing`,\n );\n }\n return shouldProcessResult;\n });\n\n if (validStrands.length > 0) {\n logger.debug(\n `>>> Processing ${validStrands.length} valid strands (out of ${strands.length} total)`,\n );\n for (const strand of validStrands) {\n await this.manager.routeAndGenerate(strand);\n }\n } else {\n logger.debug(\n `>>> No valid strands to process (${strands.length} strands received)`,\n );\n }\n }\n\n async onDisconnect() {}\n\n // Utility methods for external configuration and monitoring\n public setInteractiveMode(enabled: boolean): void {\n this.manager.setInteractiveMode(enabled);\n }\n\n public isInteractive(): boolean {\n return this.manager.isInteractiveMode();\n }\n\n public isProcessingInteractive(): boolean {\n return this.manager.isProcessingInteractive();\n }\n}\n","import type { VetraProcessorConfigType } from \"@powerhousedao/config\";\nimport { VETRA_PROCESSOR_CONFIG_KEY } from \"@powerhousedao/config\";\nimport type {\n IProcessorHostModuleLegacy,\n ProcessorRecordLegacy,\n} from \"document-drive\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { CodegenProcessorLegacy } from \"./index.legacy.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Determines if a drive header matches the Vetra drive criteria.\n * @param driveHeader - The drive header to check\n * @param explicitDriveId - Optional explicit drive ID from config (if set, uses exact match)\n * @returns true if the drive is a Vetra drive, false otherwise\n */\nfunction isDriveVetra(\n driveHeader: PHDocumentHeader,\n driveIdFromConfig?: string,\n): boolean {\n // If explicit drive ID is configured, use exact match\n if (driveIdFromConfig) {\n return (\n driveHeader.slug === driveIdFromConfig ||\n driveHeader.id === driveIdFromConfig\n );\n }\n\n // Otherwise, check if slug/id matches Vetra pattern\n // Matches \"vetra\" exactly or IDs starting with \"vetra-\" (case-insensitive)\n const matchesPattern = (identifier: string): boolean => {\n const lower = identifier.toLowerCase();\n return lower === \"vetra\" || lower.startsWith(\"vetra-\");\n };\n\n return matchesPattern(driveHeader.slug) || matchesPattern(driveHeader.id);\n}\n\nexport const codegenProcessorFactoryLegacy =\n (module: IProcessorHostModuleLegacy) =>\n (driveHeader: PHDocumentHeader): ProcessorRecordLegacy[] => {\n // Create the processor\n const processorsConfig = module.config ?? new Map<string, unknown>();\n const vetraConfig = processorsConfig.get(VETRA_PROCESSOR_CONFIG_KEY) as\n | VetraProcessorConfigType\n | undefined;\n\n // Check if this drive should use the Vetra processor\n if (!isDriveVetra(driveHeader, vetraConfig?.driveId)) {\n logger.info(\n `Drive ${driveHeader.slug} is not a Vetra drive, skipping codegen processor`,\n );\n return [];\n }\n\n logger.info(\n `Drive ${driveHeader.slug} is a Vetra drive, using codegen processor (legacy)`,\n );\n\n const processor = new CodegenProcessorLegacy(vetraConfig?.interactive);\n return [\n {\n processor,\n filter: {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\n \"powerhouse/document-model\",\n \"powerhouse/package\",\n \"powerhouse/document-editor\",\n \"powerhouse/subgraph\",\n \"powerhouse/processor\",\n \"powerhouse/app\",\n ],\n scope: [\"global\"],\n },\n },\n ];\n };\n","import {\n RelationalDbProcessorLegacy,\n type InternalTransmitterUpdate,\n} from \"document-drive\";\nimport type { VetraPackageState } from \"../../document-models/vetra-package/gen/schema/types.js\";\nimport { up } from \"./migrations.js\";\nimport { type DB } from \"./schema.js\";\n\ninterface VetraPackageGlobalState extends VetraPackageState {}\n\nexport class VetraReadModelProcessorLegacy extends RelationalDbProcessorLegacy<DB> {\n static override getNamespace(driveId: string): string {\n // Default namespace: `${this.name}_${driveId.replaceAll(\"-\", \"_\")}`\n // we keep all vetra packages in the same namespace even if they are stored in different drives\n return super.getNamespace(\"vetra-packages\");\n }\n\n override async initAndUpgrade(): Promise<void> {\n await up(this.relationalDb);\n }\n\n override async onStrands(\n strands: InternalTransmitterUpdate[],\n ): Promise<void> {\n if (strands.length === 0) {\n return;\n }\n\n for (const strand of strands) {\n if (strand.operations.length === 0) {\n continue;\n }\n\n // Only process VetraPackage documents\n if (strand.documentType !== \"powerhouse/package\") {\n continue;\n }\n\n // Get the last operation to extract the most recent state\n const lastOperation = strand.operations[strand.operations.length - 1];\n if (!lastOperation) continue;\n\n // Extract VetraPackage state fields with proper typing\n const state = strand.state as VetraPackageGlobalState | undefined;\n\n // Helper to safely get string values\n const getString = (val: unknown): string | null =>\n typeof val === \"string\" ? val : null;\n\n const now = new Date();\n const operationTimestamp = new Date(\n parseInt(lastOperation.timestampUtcMs, 10),\n );\n\n await this.relationalDb\n .insertInto(\"vetra_package\")\n .values({\n document_id: strand.documentId,\n // VetraPackage state fields\n name: getString(state?.name),\n description: getString(state?.description),\n category: getString(state?.category),\n author_name: getString(state?.author?.name),\n author_website: getString(state?.author?.website),\n keywords: state?.keywords ? JSON.stringify(state.keywords) : null,\n github_url: getString(state?.githubUrl),\n npm_url: getString(state?.npmUrl),\n // Document metadata\n last_operation_index: lastOperation.index,\n last_operation_hash: lastOperation.hash,\n last_operation_timestamp: operationTimestamp,\n drive_id: strand.driveId,\n created_at: now,\n updated_at: now,\n })\n .onConflict((oc) =>\n oc.column(\"document_id\").doUpdateSet({\n name: getString(state?.name),\n description: getString(state?.description),\n category: getString(state?.category),\n author_name: getString(state?.author?.name),\n author_website: getString(state?.author?.website),\n keywords: state?.keywords ? JSON.stringify(state.keywords) : null,\n github_url: getString(state?.githubUrl),\n npm_url: getString(state?.npmUrl),\n last_operation_index: lastOperation.index,\n last_operation_hash: lastOperation.hash,\n last_operation_timestamp: operationTimestamp,\n drive_id: strand.driveId,\n updated_at: now,\n }),\n )\n .execute();\n }\n }\n\n async onDisconnect() {}\n}\n","import type { IProcessorHostModuleLegacy } from \"document-drive\";\nimport {\n type ProcessorRecordLegacy,\n type RelationalDbProcessorFilterLegacy,\n} from \"document-drive\";\nimport { type PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { VetraReadModelProcessorLegacy } from \"./index.legacy.js\";\n\nexport const vetraReadModelProcessorFactoryLegacy =\n (module: IProcessorHostModuleLegacy) =>\n async (driveHeader: PHDocumentHeader): Promise<ProcessorRecordLegacy[]> => {\n // Create a namespace for the processor and the provided drive id\n const namespace = VetraReadModelProcessorLegacy.getNamespace(\n driveHeader.id,\n );\n\n // Create a namespaced db for the processor\n const store =\n await module.relationalDb.createNamespace<VetraReadModelProcessorLegacy>(\n namespace,\n );\n\n // Create a filter for the processor\n const filter: RelationalDbProcessorFilterLegacy = {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\"powerhouse/package\"],\n scope: [\"global\"],\n };\n\n // Create the processor\n const processor = new VetraReadModelProcessorLegacy(\n namespace,\n filter,\n store,\n );\n return [\n {\n processor,\n filter,\n },\n ];\n };\n","import { vetraReadModelProcessorFactoryLegacy } from \"./vetra-read-model/factory.legacy.js\";\n/**\n * This file aggregates all legacy processor factories\n */\n\nimport type {\n IProcessorHostModuleLegacy,\n ProcessorFactoryLegacy,\n ProcessorRecordLegacy,\n} from \"document-drive\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\n\nimport { codegenProcessorFactoryLegacy } from \"./codegen/factory.legacy.js\";\n\nexport const processorFactoryLegacy = (module: IProcessorHostModuleLegacy) => {\n // Initialize all processor factories once with the module\n const factories: Array<ProcessorFactoryLegacy> = [];\n\n // Add all processor factories\n factories.push(vetraReadModelProcessorFactoryLegacy(module));\n\n // Add other processors here as they are generated\n factories.push(codegenProcessorFactoryLegacy(module));\n\n // Return the inner function that will be called for each drive\n return async (driveHeader: PHDocumentHeader) => {\n const processors: ProcessorRecordLegacy[] = [];\n\n // Call each cached factory with the driveHeader\n for (const factory of factories) {\n processors.push(...(await factory(driveHeader)));\n }\n\n return processors;\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../processors/codegen/factory.ts","../../processors/vetra-read-model/migrations.ts","../../processors/vetra-read-model/factory.ts","../../processors/factory.ts"],"sourcesContent":["import type { VetraProcessorConfigType } from \"@powerhousedao/config\";\nimport { VETRA_PROCESSOR_CONFIG_KEY } from \"@powerhousedao/config\";\nimport type {\n IProcessorHostModule,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { CodegenProcessor } from \"./index.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Determines if a drive header matches the Vetra drive criteria.\n * @param driveHeader - The drive header to check\n * @param explicitDriveId - Optional explicit drive ID from config (if set, uses exact match)\n * @returns true if the drive is a Vetra drive, false otherwise\n */\nfunction isDriveVetra(\n driveHeader: PHDocumentHeader,\n driveIdFromConfig?: string,\n): boolean {\n // If explicit drive ID is configured, use exact match\n if (driveIdFromConfig) {\n return (\n driveHeader.slug === driveIdFromConfig ||\n driveHeader.id === driveIdFromConfig\n );\n }\n\n // Otherwise, check if slug/id matches Vetra pattern\n // Matches \"vetra\" exactly or IDs starting with \"vetra-\" (case-insensitive)\n const matchesPattern = (identifier: string): boolean => {\n const lower = identifier.toLowerCase();\n return lower === \"vetra\" || lower.startsWith(\"vetra-\");\n };\n\n return matchesPattern(driveHeader.slug) || matchesPattern(driveHeader.id);\n}\n\nexport const codegenProcessorFactory =\n (module: IProcessorHostModule) =>\n (driveHeader: PHDocumentHeader): ProcessorRecord[] => {\n // Create the processor\n const processorsConfig = module.config ?? new Map<string, unknown>();\n const vetraConfig = processorsConfig.get(VETRA_PROCESSOR_CONFIG_KEY) as\n | VetraProcessorConfigType\n | undefined;\n\n // Check if this drive should use the Vetra processor\n if (!isDriveVetra(driveHeader, vetraConfig?.driveId)) {\n logger.info(\n `Drive ${driveHeader.slug} is not a Vetra drive, skipping codegen processor`,\n );\n return [];\n }\n\n logger.info(\n `Drive ${driveHeader.slug} is a Vetra drive, using codegen processor`,\n );\n\n const processor = new CodegenProcessor(vetraConfig?.interactive);\n return [\n {\n processor,\n filter: {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\n \"powerhouse/document-model\",\n \"powerhouse/package\",\n \"powerhouse/document-editor\",\n \"powerhouse/subgraph\",\n \"powerhouse/processor\",\n \"powerhouse/app\",\n ],\n scope: [\"global\"],\n },\n },\n ];\n };\n","import type { IRelationalDb } from \"@powerhousedao/shared/processors\";\n\nexport async function up(db: IRelationalDb<any>): Promise<void> {\n // Create vetra_package table to store VetraPackage document state\n await db.schema\n .createTable(\"vetra_package\")\n .addColumn(\"document_id\", \"varchar(255)\", (col) => col.primaryKey()) // VetraPackage state fields\n .addColumn(\"name\", \"varchar(255)\")\n .addColumn(\"description\", \"text\")\n .addColumn(\"category\", \"varchar(255)\")\n .addColumn(\"author_name\", \"varchar(255)\")\n .addColumn(\"author_website\", \"varchar(512)\")\n .addColumn(\"keywords\", \"text\") // JSON array of {id, label}\n .addColumn(\"github_url\", \"varchar(512)\")\n .addColumn(\"npm_url\", \"varchar(512)\")\n .addColumn(\"drive_id\", \"varchar(255)\")\n // Document metadata\n .addColumn(\"last_operation_index\", \"integer\", (col) => col.notNull())\n .addColumn(\"last_operation_hash\", \"varchar(255)\", (col) => col.notNull())\n .addColumn(\"last_operation_timestamp\", \"timestamptz\", (col) =>\n col.notNull(),\n )\n .addColumn(\"created_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(\"now()\"),\n )\n .addColumn(\"updated_at\", \"timestamptz\", (col) =>\n col.notNull().defaultTo(\"now()\"),\n )\n .ifNotExists()\n .execute();\n\n // Create indexes for common queries\n await db.schema\n .createIndex(\"idx_vetra_package_document_id\")\n .on(\"vetra_package\")\n .column(\"document_id\")\n .ifNotExists()\n .execute();\n\n await db.schema\n .createIndex(\"idx_vetra_package_name\")\n .on(\"vetra_package\")\n .column(\"name\")\n .ifNotExists()\n .execute();\n\n await db.schema\n .createIndex(\"idx_vetra_package_category\")\n .on(\"vetra_package\")\n .column(\"category\")\n .ifNotExists()\n .execute();\n}\n\nexport async function down(db: IRelationalDb<any>): Promise<void> {\n // Drop indexes first\n await db.schema.dropIndex(\"idx_vetra_package_category\").ifExists().execute();\n await db.schema.dropIndex(\"idx_vetra_package_name\").ifExists().execute();\n await db.schema\n .dropIndex(\"idx_vetra_package_document_id\")\n .ifExists()\n .execute();\n\n // Drop table\n await db.schema.dropTable(\"vetra_package\").ifExists().execute();\n}\n","import type {\n IProcessorHostModule,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { VetraReadModelProcessor } from \"./index.js\";\nimport { up } from \"./migrations.js\";\nimport type { DB } from \"./schema.js\";\n\nexport const vetraReadModelProcessorFactory =\n (module: IProcessorHostModule) =>\n async (driveHeader: PHDocumentHeader): Promise<ProcessorRecord[]> => {\n // Create namespace (same as legacy - all vetra packages share one namespace)\n const db = await module.relationalDb.createNamespace<DB>(\"vetra-packages\");\n\n // Run migrations (idempotent - uses ifNotExists)\n await up(db);\n\n // Create the processor with the relational database\n const processor = new VetraReadModelProcessor(db);\n return [\n {\n processor,\n filter: {\n branch: [\"main\"],\n documentId: [\"*\"],\n documentType: [\"powerhouse/package\"],\n scope: [\"global\"],\n },\n },\n ];\n };\n","import type {\n IProcessorHostModule,\n ProcessorFactory,\n ProcessorRecord,\n} from \"@powerhousedao/reactor-browser\";\nimport type { PHDocumentHeader } from \"@powerhousedao/shared/document-model\";\nimport { codegenProcessorFactory } from \"./codegen/factory.js\";\nimport { vetraReadModelProcessorFactory } from \"./vetra-read-model/factory.js\";\n\n/**\n * This file aggregates all processor factories for the new reactor\n */\n\nexport const processorFactory = (module: IProcessorHostModule) => {\n // Initialize all processor factories once with the module\n const factories: Array<ProcessorFactory> = [];\n\n // Add all processor factories\n factories.push(vetraReadModelProcessorFactory(module));\n factories.push(codegenProcessorFactory(module));\n\n // Return the inner function that will be called for each drive\n return async (driveHeader: PHDocumentHeader) => {\n const processors: ProcessorRecord[] = [];\n\n // Call each cached factory with the driveHeader\n for (const factory of factories) {\n processors.push(...(await factory(driveHeader, module.processorApp)));\n }\n\n return processors;\n };\n};\n"],"mappings":";;;;;;;;;;;AAgBA,SAAS,aACP,aACA,mBACS;AAET,KAAI,kBACF,QACE,YAAY,SAAS,qBACrB,YAAY,OAAO;CAMvB,MAAM,kBAAkB,eAAgC;EACtD,MAAM,QAAQ,WAAW,aAAa;AACtC,SAAO,UAAU,WAAW,MAAM,WAAW,SAAS;;AAGxD,QAAO,eAAe,YAAY,KAAK,IAAI,eAAe,YAAY,GAAG;;AAG3E,MAAa,2BACV,YACA,gBAAqD;CAGpD,MAAM,eADmB,OAAO,0BAAU,IAAI,KAAsB,EAC/B,IAAI,2BAA2B;AAKpE,KAAI,CAAC,aAAa,aAAa,aAAa,QAAQ,EAAE;AACpD,SAAO,KACL,SAAS,YAAY,KAAK,mDAC3B;AACD,SAAO,EAAE;;AAGX,QAAO,KACL,SAAS,YAAY,KAAK,4CAC3B;AAGD,QAAO,CACL;EACE,WAHc,IAAI,iBAAiB,aAAa,YAAY;EAI5D,QAAQ;GACN,QAAQ,CAAC,OAAO;GAChB,YAAY,CAAC,IAAI;GACjB,cAAc;IACZ;IACA;IACA;IACA;IACA;IACA;IACD;GACD,OAAO,CAAC,SAAS;GAClB;EACF,CACF;;;;AC3EL,eAAsB,GAAG,IAAuC;AAE9D,OAAM,GAAG,OACN,YAAY,gBAAgB,CAC5B,UAAU,eAAe,iBAAiB,QAAQ,IAAI,YAAY,CAAC,CACnE,UAAU,QAAQ,eAAe,CACjC,UAAU,eAAe,OAAO,CAChC,UAAU,YAAY,eAAe,CACrC,UAAU,eAAe,eAAe,CACxC,UAAU,kBAAkB,eAAe,CAC3C,UAAU,YAAY,OAAO,CAC7B,UAAU,cAAc,eAAe,CACvC,UAAU,WAAW,eAAe,CACpC,UAAU,YAAY,eAAe,CAErC,UAAU,wBAAwB,YAAY,QAAQ,IAAI,SAAS,CAAC,CACpE,UAAU,uBAAuB,iBAAiB,QAAQ,IAAI,SAAS,CAAC,CACxE,UAAU,4BAA4B,gBAAgB,QACrD,IAAI,SAAS,CACd,CACA,UAAU,cAAc,gBAAgB,QACvC,IAAI,SAAS,CAAC,UAAU,QAAQ,CACjC,CACA,UAAU,cAAc,gBAAgB,QACvC,IAAI,SAAS,CAAC,UAAU,QAAQ,CACjC,CACA,aAAa,CACb,SAAS;AAGZ,OAAM,GAAG,OACN,YAAY,gCAAgC,CAC5C,GAAG,gBAAgB,CACnB,OAAO,cAAc,CACrB,aAAa,CACb,SAAS;AAEZ,OAAM,GAAG,OACN,YAAY,yBAAyB,CACrC,GAAG,gBAAgB,CACnB,OAAO,OAAO,CACd,aAAa,CACb,SAAS;AAEZ,OAAM,GAAG,OACN,YAAY,6BAA6B,CACzC,GAAG,gBAAgB,CACnB,OAAO,WAAW,CAClB,aAAa,CACb,SAAS;;;;AC1Cd,MAAa,kCACV,WACD,OAAO,gBAA8D;CAEnE,MAAM,KAAK,MAAM,OAAO,aAAa,gBAAoB,iBAAiB;AAG1E,OAAM,GAAG,GAAG;AAIZ,QAAO,CACL;EACE,WAHc,IAAI,wBAAwB,GAAG;EAI7C,QAAQ;GACN,QAAQ,CAAC,OAAO;GAChB,YAAY,CAAC,IAAI;GACjB,cAAc,CAAC,qBAAqB;GACpC,OAAO,CAAC,SAAS;GAClB;EACF,CACF;;;;;;;ACjBL,MAAa,oBAAoB,WAAiC;CAEhE,MAAM,YAAqC,EAAE;AAG7C,WAAU,KAAK,+BAA+B,OAAO,CAAC;AACtD,WAAU,KAAK,wBAAwB,OAAO,CAAC;AAG/C,QAAO,OAAO,gBAAkC;EAC9C,MAAM,aAAgC,EAAE;AAGxC,OAAK,MAAM,WAAW,UACpB,YAAW,KAAK,GAAI,MAAM,QAAQ,aAAa,OAAO,aAAa,CAAE;AAGvE,SAAO"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as VetraReadModelProcessor } from "../../index-
|
|
1
|
+
import { t as VetraReadModelProcessor } from "../../index-COsHJRmm.js";
|
|
2
2
|
export { VetraReadModelProcessor };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/vetra",
|
|
3
|
-
"version": "6.0.0-dev.
|
|
3
|
+
"version": "6.0.0-dev.109",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"zod": "4.3.6",
|
|
53
53
|
"react": "19.2.4",
|
|
54
54
|
"react-dom": "19.2.4",
|
|
55
|
-
"@powerhousedao/
|
|
56
|
-
"@powerhousedao/
|
|
57
|
-
"@powerhousedao/
|
|
58
|
-
"@powerhousedao/
|
|
59
|
-
"@powerhousedao/
|
|
60
|
-
"
|
|
61
|
-
"document-model": "6.0.0-dev.
|
|
62
|
-
"@powerhousedao/
|
|
63
|
-
"
|
|
55
|
+
"@powerhousedao/common": "6.0.0-dev.109",
|
|
56
|
+
"@powerhousedao/config": "6.0.0-dev.109",
|
|
57
|
+
"@powerhousedao/design-system": "6.0.0-dev.109",
|
|
58
|
+
"@powerhousedao/reactor-browser": "6.0.0-dev.109",
|
|
59
|
+
"@powerhousedao/shared": "6.0.0-dev.109",
|
|
60
|
+
"document-drive": "6.0.0-dev.109",
|
|
61
|
+
"document-model": "6.0.0-dev.109",
|
|
62
|
+
"@powerhousedao/builder-tools": "6.0.0-dev.109",
|
|
63
|
+
"@powerhousedao/codegen": "6.0.0-dev.109"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@tailwindcss/cli": "4.1.18",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codegen-jdqm9gNO.js","names":[],"sources":["../processors/codegen/document-handlers/base-document-gen.ts","../processors/codegen/interactive-manager.ts","../processors/codegen/document-handlers/document-codegen-manager.ts","../processors/codegen/document-handlers/generators/utils.ts","../processors/codegen/document-handlers/generators/app-generator.ts","../processors/codegen/document-handlers/generators/document-editor-generator.ts","../processors/codegen/document-handlers/generators/document-model-generator.ts","../processors/codegen/document-handlers/generators/package-generator.ts","../processors/codegen/document-handlers/generators/processor-generator.ts","../processors/codegen/document-handlers/generators/subgraph-generator.ts","../processors/codegen/document-handlers/document-codegen-factory.ts","../processors/codegen/index.ts"],"sourcesContent":["import type { InternalTransmitterUpdate } from \"document-drive\";\nimport type { Config } from \"./types.js\";\n\n/**\n * Abstract base class for document generators\n * Defines the interface that all document-type handlers must implement\n */\nexport abstract class BaseDocumentGen {\n /**\n * The document type(s) this generator supports\n * Can be a single string or an array of strings for generators that handle multiple types\n */\n abstract readonly supportedDocumentTypes: string | string[];\n\n constructor(protected config: Config) {}\n\n /**\n * Generate code for the given document\n * Must be implemented by each specific document generator\n */\n abstract generate(strand: InternalTransmitterUpdate): Promise<void>;\n\n /**\n * Check if this generator supports the given document type\n */\n supportsDocumentType(documentType: string): boolean {\n if (typeof this.supportedDocumentTypes === \"string\") {\n return this.supportedDocumentTypes === documentType;\n }\n return this.supportedDocumentTypes.includes(documentType);\n }\n\n /**\n * Get all supported document types as an array\n */\n getSupportedDocumentTypes(): string[] {\n if (typeof this.supportedDocumentTypes === \"string\") {\n return [this.supportedDocumentTypes];\n }\n return [...this.supportedDocumentTypes];\n }\n\n /**\n * Validate if this strand should be processed\n * Override this method in specific generators to add custom validation logic\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // Basic validation: ensure strand has required properties\n if (!strand.documentId || !strand.documentType) {\n return false;\n }\n\n // Basic validation: check if document type is supported\n if (!this.supportsDocumentType(strand.documentType)) {\n return false;\n }\n\n // Default to processing if basic validation passes\n return true;\n }\n}\n","import type { InternalTransmitterUpdate } from \"document-drive\";\nimport { createInterface } from \"readline\";\nimport { logger } from \"./logger.js\";\n\nexport interface QueuedStrand {\n strand: InternalTransmitterUpdate;\n timestamp: number;\n}\n\n/**\n * InteractiveManager handles user interaction for code generation confirmation\n * Supports both individual strand processing and queue-based batch processing\n */\nexport class InteractiveManager {\n private isInteractiveMode: boolean;\n private processingConfirmation = false;\n private strandQueue = new Map<string, QueuedStrand>();\n\n constructor(interactiveMode = false) {\n this.isInteractiveMode = interactiveMode;\n }\n\n private getDocumentKey(documentType: string, documentId: string): string {\n return `${documentType}:${documentId}`;\n }\n\n /**\n * Add a strand to the queue, replacing any existing strand for the same document\n */\n public queueStrand(strand: InternalTransmitterUpdate): void {\n const documentKey = this.getDocumentKey(\n strand.documentType,\n strand.documentId,\n );\n\n this.strandQueue.set(documentKey, {\n strand,\n timestamp: Date.now(),\n });\n\n logger.debug(\n `>>> Queued strand for ${documentKey}, queue size: ${this.strandQueue.size}`,\n );\n }\n\n /**\n * Get all queued strands\n */\n public getQueuedStrands(): QueuedStrand[] {\n return Array.from(this.strandQueue.values());\n }\n\n /**\n * Clear and return all queued strands\n */\n public clearQueue(): QueuedStrand[] {\n const queuedStrands = Array.from(this.strandQueue.values());\n this.strandQueue.clear();\n return queuedStrands;\n }\n\n /**\n * Get the current queue size\n */\n public getQueueSize(): number {\n return this.strandQueue.size;\n }\n\n private async promptUserConfirmation(): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(\"🔄 Code generation ready to run.\");\n console.log(\"=\".repeat(50));\n\n process.stdout.write(\n \"Do you want to proceed with code generation? (y/n): \\n\\n\",\n );\n\n rl.on(\"line\", (answer: string) => {\n rl.close();\n console.log(\"\"); // Add blank line after user input\n resolve(answer.toLowerCase() === \"y\" || answer.toLowerCase() === \"yes\");\n });\n });\n }\n\n /**\n * Process generation with user confirmation (legacy single-strand method)\n * This method assumes interactive mode is already enabled (checked by caller)\n */\n public async processWithConfirmation<T>(\n documentType: string,\n generator: () => Promise<T>,\n ): Promise<T | null> {\n if (this.processingConfirmation) {\n logger.debug(\"Already processing confirmation, skipping\");\n return null;\n }\n\n this.processingConfirmation = true;\n\n try {\n // Always prompt user since this method only called in interactive mode\n const shouldProceed = await this.promptUserConfirmation();\n\n if (!shouldProceed) {\n logger.info(`❌ Code generation cancelled by user for ${documentType}`);\n return null;\n }\n\n logger.info(`✅ User approved code generation for ${documentType}`);\n\n const result = await generator();\n return result;\n } catch (error) {\n logger.error(\n `❌ Error during interactive code generation for ${documentType}:`,\n error,\n );\n throw error;\n } finally {\n this.processingConfirmation = false;\n }\n }\n\n /**\n * Process all queued strands with a single user confirmation\n * This is the main method for queue-based interactive processing\n */\n public async processQueueWithConfirmation(\n processor: (strands: QueuedStrand[]) => Promise<void>,\n ): Promise<void> {\n if (this.processingConfirmation) {\n logger.debug(\n \"Already processing confirmation, skipping queue processing\",\n );\n return;\n }\n\n // Check if there are any strands to process\n let queuedStrands = this.getQueuedStrands();\n if (queuedStrands.length === 0) {\n logger.debug(\"No strands in queue to process\");\n return;\n }\n\n this.processingConfirmation = true;\n\n try {\n // Prompt user for confirmation\n const shouldProceed = await this.promptUserConfirmation();\n\n if (!shouldProceed) {\n logger.info(\"❌ Code generation cancelled by user\");\n // Clear the queue since user cancelled\n this.clearQueue();\n return;\n }\n\n // Get and clear the final queue state right before processing\n // (in case new strands were added while waiting for user input)\n queuedStrands = this.clearQueue();\n if (queuedStrands.length === 0) {\n logger.info(\"ℹ️ No documents to process\");\n return;\n }\n\n logger.info(\n `✅ User approved code generation for ${queuedStrands.length} document(s)`,\n );\n\n // Process all queued strands\n await processor(queuedStrands);\n logger.info(\"✅ Code generation completed\");\n } catch (error) {\n logger.error(\"❌ Error during interactive queue processing:\", error);\n throw error;\n } finally {\n this.processingConfirmation = false;\n }\n }\n\n public setInteractiveMode(enabled: boolean): void {\n this.isInteractiveMode = enabled;\n logger.debug(`Interactive mode set to: ${enabled}`);\n }\n\n public isInteractive(): boolean {\n return this.isInteractiveMode;\n }\n\n public isProcessing(): boolean {\n return this.processingConfirmation;\n }\n}\n","import type { InternalTransmitterUpdate } from \"document-drive\";\nimport type { QueuedStrand } from \"../interactive-manager.js\";\nimport { InteractiveManager } from \"../interactive-manager.js\";\nimport { logger } from \"../logger.js\";\nimport type { BaseDocumentGen } from \"./base-document-gen.js\";\nimport type { Config } from \"./types.js\";\n\nconst DEFAULT_DEBOUNCE_TIME = 3000; // 3 seconds\n\n/**\n * Manager class responsible for routing documents to the correct generator\n * and managing generator registration and instantiation\n */\nexport class DocumentCodegenManager {\n private generators = new Map<string, BaseDocumentGen>();\n private debounceTimers = new Map<string, NodeJS.Timeout>();\n private processingQueue: Promise<void> = Promise.resolve();\n private interactiveManager: InteractiveManager;\n\n constructor(\n private config: Config,\n interactiveMode = false,\n ) {\n this.interactiveManager = new InteractiveManager(interactiveMode);\n }\n\n /**\n * Register a generator class for a specific document type\n */\n registerGenerator(\n documentType: string,\n generatorClass: new (config: Config) => BaseDocumentGen,\n ): void {\n if (this.generators.has(documentType)) {\n logger.warn(\n `⚠️ Generator for document type \"${documentType}\" is already registered. Overwriting.`,\n );\n }\n\n this.generators.set(documentType, new generatorClass(this.config));\n logger.debug(`✅ Registered generator for document type: ${documentType}`);\n }\n\n /**\n * Register a generator class that supports multiple document types\n */\n registerMultiTypeGenerator(\n generatorClass: new (config: Config) => BaseDocumentGen,\n ): void {\n const generator = new generatorClass(this.config);\n const supportedTypes = generator.getSupportedDocumentTypes();\n\n for (const documentType of supportedTypes) {\n if (this.generators.has(documentType)) {\n logger.warn(\n `⚠️ Generator for document type \"${documentType}\" is already registered. Overwriting.`,\n );\n }\n this.generators.set(documentType, generator);\n }\n\n logger.debug(\n `✅ Registered multi-type generator for document types: ${supportedTypes.join(\", \")}`,\n );\n }\n\n /**\n * Get a generator instance for the given document type\n * Public method to allow external access for validation\n */\n public getGenerator(documentType: string): BaseDocumentGen | undefined {\n return this.generators.get(documentType);\n }\n\n /**\n * Get all registered document types\n */\n getRegisteredDocumentTypes(): string[] {\n return Array.from(this.generators.keys());\n }\n\n /**\n * Check if a document type is supported\n */\n isDocumentTypeSupported(documentType: string): boolean {\n return this.generators.has(documentType);\n }\n\n /**\n * Route a document to the appropriate generator and handle the generation\n * Handles both interactive and non-interactive modes with queue-based processing\n */\n async routeAndGenerate(strand: InternalTransmitterUpdate): Promise<void> {\n const documentType = strand.documentType;\n\n if (!documentType) {\n logger.error(\"❌ Document type is missing from strand state\");\n throw new Error(\"Document type is missing from strand state\");\n }\n\n const generator = this.getGenerator(documentType);\n\n if (!generator) {\n logger.warn(`⚠️ No generator found for document type: ${documentType}`);\n logger.warn(\n `ℹ️ Supported document types: ${this.getRegisteredDocumentTypes().join(\", \")}`,\n );\n throw new Error(`Unsupported document type: ${documentType}`);\n }\n\n // Validate if this strand should be processed\n if (!generator.shouldProcess(strand)) {\n logger.debug(\n `>>> Generator validation failed for ${documentType}:${strand.documentId}, skipping processing`,\n );\n return;\n }\n\n // Different flow for interactive vs non-interactive mode\n if (this.interactiveManager.isInteractive()) {\n // Interactive mode: queue strands and use debounce timer to trigger batch processing\n logger.debug(\n `>>> Queueing strand for interactive processing: ${documentType}:${strand.documentId}`,\n );\n\n // Add strand to queue (will replace any existing strand for same document)\n this.interactiveManager.queueStrand(strand);\n\n // Clear any existing debounce timer for interactive processing\n const existingTimer = this.debounceTimers.get(\"interactive\");\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set up debounce timer for batch interactive processing\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n const debounceTimer = setTimeout(async () => {\n try {\n await this.interactiveManager.processQueueWithConfirmation(\n async (queuedStrands: QueuedStrand[]) => {\n await this.processQueuedStrands(queuedStrands);\n },\n );\n } catch (error) {\n logger.error(\"❌ Error during interactive batch processing:\", error);\n } finally {\n // Clean up the timer reference\n this.debounceTimers.delete(\"interactive\");\n }\n }, DEFAULT_DEBOUNCE_TIME);\n\n // Store the timer reference using 'interactive' key\n this.debounceTimers.set(\"interactive\", debounceTimer);\n } else {\n // Non-interactive mode: use debouncing per document instance\n // Create unique key for this specific document instance\n const timerKey = `${documentType}:${strand.documentId}`;\n\n // Clear any existing debounce timer for this document instance\n const existingTimer = this.debounceTimers.get(timerKey);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n // Set up new debounced generation (no interactive confirmation)\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n const debounceTimer = setTimeout(async () => {\n try {\n logger.debug(\n `🔄 Routing document type \"${documentType}\" to generator (debounced)`,\n );\n\n // Direct generation, no interactive confirmation\n await generator.generate(strand);\n logger.debug(\n `✅ Successfully generated code for document type: ${documentType}`,\n );\n } catch (error) {\n logger.error(\n `❌ Error generating code for document type \"${documentType}\":`,\n error,\n );\n // Don't throw - let codegen continue with other documents\n } finally {\n // Clean up the timer reference\n this.debounceTimers.delete(documentType);\n }\n }, DEFAULT_DEBOUNCE_TIME);\n\n // Store the timer reference\n this.debounceTimers.set(timerKey, debounceTimer);\n }\n }\n\n /**\n * Process multiple strands in priority order (document-model types first)\n */\n private async processQueuedStrands(\n queuedStrands: QueuedStrand[],\n ): Promise<void> {\n logger.debug(`🔄 Processing ${queuedStrands.length} queued strand(s)`);\n\n // Sort by priority (document-model first to ensure dependencies exist)\n const documentModelStrands = queuedStrands.filter(\n (qs: QueuedStrand) =>\n qs.strand.documentType === \"powerhouse/document-model\",\n );\n const otherStrands = queuedStrands.filter(\n (qs: QueuedStrand) =>\n qs.strand.documentType !== \"powerhouse/document-model\",\n );\n\n // Process document models first\n for (const queuedStrand of documentModelStrands) {\n await this.processStrand(queuedStrand.strand);\n }\n\n // Then process other document types\n for (const queuedStrand of otherStrands) {\n await this.processStrand(queuedStrand.strand);\n }\n\n logger.debug(\n `✅ Successfully processed all ${queuedStrands.length} queued strand(s)`,\n );\n }\n\n /**\n * Process a single strand (used internally by processQueuedStrands)\n */\n private async processStrand(\n strand: InternalTransmitterUpdate,\n ): Promise<void> {\n const documentType = strand.documentType;\n const generator = this.getGenerator(documentType);\n\n if (!generator) {\n logger.warn(`⚠️ No generator found for document type: ${documentType}`);\n return;\n }\n\n try {\n logger.debug(`🔄 Generating code for document type: ${documentType}`);\n await generator.generate(strand);\n logger.debug(\n `✅ Successfully generated code for document type: ${documentType}`,\n );\n } catch (error) {\n logger.error(\n `❌ Error generating code for document type \"${documentType}\":`,\n error,\n );\n // Don't throw here to allow other strands to be processed\n }\n }\n\n /**\n * Clear all registered generators\n */\n clearGenerators(): void {\n this.generators.clear();\n logger.debug(\"🧹 Cleared all registered generators\");\n }\n\n /**\n * Get statistics about registered generators\n */\n getStats(): { totalGenerators: number; supportedTypes: string[] } {\n return {\n totalGenerators: this.generators.size,\n supportedTypes: this.getRegisteredDocumentTypes(),\n };\n }\n\n /**\n * Set interactive mode for code generation\n */\n setInteractiveMode(enabled: boolean): void {\n this.interactiveManager.setInteractiveMode(enabled);\n }\n\n /**\n * Check if interactive mode is enabled\n */\n isInteractiveMode(): boolean {\n return this.interactiveManager.isInteractive();\n }\n\n /**\n * Check if the manager is currently processing an interactive confirmation\n */\n isProcessingInteractive(): boolean {\n return this.interactiveManager.isProcessing();\n }\n}\n","import type {\n MinimalBackupData,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { baseMinimalSaveToFile, baseSaveToFile } from \"document-model/node\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { logger } from \"../../logger.js\";\n\nconst BACKUP_FOLDER = \"backup-documents\";\n\n/**\n * Exports a document to the backup directory.\n * Creates the backup directory if it doesn't exist.\n *\n * @param document - The document to backup\n * @param workingDir - Current working directory\n * @param extension - File extension for the document type (without dot)\n * @param name - Name of the document to use for the backup file (optional)\n * @returns Promise resolving to the backup file path, or undefined if backup failed\n */\nexport async function backupDocument(\n document: PHDocument,\n workingDir: string,\n extension: string = \"\",\n name?: string,\n): Promise<string | undefined> {\n const docName = name ?? document.header.name;\n\n try {\n const backupPath = join(workingDir, BACKUP_FOLDER);\n await mkdir(backupPath, { recursive: true });\n\n const filePath = await baseSaveToFile(\n document,\n backupPath,\n extension,\n docName,\n );\n\n logger.debug(`📁 Document backed up to: ${filePath}`);\n return filePath;\n } catch (error) {\n logger.warn(`⚠️ Failed to backup document \"${docName}\":`, error);\n return undefined;\n }\n}\n\n/**\n * Creates a minimal backup of a document from strand data.\n * Used when the full document is not available (e.g., in onOperations handler).\n */\nexport async function minimalBackupDocument(\n data: MinimalBackupData,\n workingDir: string,\n extension?: string,\n): Promise<string | undefined> {\n try {\n const backupPath = join(workingDir, BACKUP_FOLDER);\n await mkdir(backupPath, { recursive: true });\n\n const filePath = await baseMinimalSaveToFile(\n data,\n backupPath,\n extension ?? \"\",\n );\n\n logger.debug(`Document backed up to: ${filePath}`);\n return filePath;\n } catch (error) {\n logger.warn(`Failed to backup document \"${data.name}\":`, error);\n return undefined;\n }\n}\n","import { generateDriveEditor, generateManifest } from \"@powerhousedao/codegen\";\nimport type {\n AppModuleGlobalState,\n AppModulePHState,\n} from \"@powerhousedao/vetra/document-models/app-module\";\nimport { kebabCase } from \"change-case\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for app documents\n */\nexport class AppGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/app\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): AppModuleGlobalState | undefined {\n const fullState = strand.state as AppModulePHState | undefined;\n if (!fullState) {\n return undefined;\n }\n return fullState.global;\n }\n\n /**\n * Validate if this app strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.debug(`No state found for app: ${strand.documentId}`);\n return false;\n }\n\n // Check if we have a valid app name and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for app: ${strand.documentId}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `App not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.error(`No state found for app: ${strand.documentId}`);\n return;\n }\n\n // Check if we have a valid app name and it's confirmed\n if (state.name && state.status === \"CONFIRMED\") {\n logger.info(`🔄 Starting drive editor generation for app: ${state.name}`);\n try {\n // Generate app ID using kebabCase\n const appId: string = kebabCase(state.name);\n // Generate the drive editor using the codegen function\n await generateDriveEditor({\n ...this.config.PH_CONFIG,\n driveEditorName: state.name,\n driveEditorId: appId,\n allowedDocumentTypes: state.allowedDocumentTypes ?? [],\n isDragAndDropEnabled: state.isDragAndDropEnabled,\n useTsMorph: USE_TS_MORPH,\n });\n\n logger.info(\n `✅ Drive editor generation completed successfully for app: ${state.name}`,\n );\n\n // Update the manifest with the new app\n try {\n logger.debug(\n `🔄 Updating manifest with app: ${state.name} (ID: ${appId})`,\n );\n\n generateManifest(\n {\n apps: [\n {\n id: appId,\n name: state.name,\n driveEditor: appId,\n } as any,\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for app: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for app ${state.name}:`,\n manifestError,\n );\n // Don't throw here - drive editor generation was successful\n }\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as AppModulePHState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during drive editor generation for app ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping drive editor generation - missing name for app`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping drive editor generation - app \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n","import { generateEditor, generateManifest } from \"@powerhousedao/codegen\";\nimport { kebabCase } from \"change-case\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type {\n DocumentEditorPHState,\n DocumentEditorState,\n} from \"../../../../document-models/document-editor/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for document editor documents\n */\nexport class DocumentEditorGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/document-editor\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): DocumentEditorState | undefined {\n const fullState = strand.state as DocumentEditorPHState | undefined;\n if (!fullState) {\n return undefined;\n }\n return fullState.global;\n }\n\n /**\n * Validate if this document editor strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.debug(`No state found for document editor: ${strand.documentId}`);\n return false;\n }\n\n // Check if we have a valid editor name, document types, and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for document editor: ${strand.documentId}`);\n return false;\n }\n\n if (!state.documentTypes || state.documentTypes.length === 0) {\n logger.debug(\n `No document types found for document editor: ${state.name}`,\n );\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Document editor not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.error(`No state found for document editor: ${strand.documentId}`);\n return;\n }\n\n // Validation is already done in shouldProcess, so we can proceed directly\n logger.info(`🔄 Starting editor generation for: ${state.name}`);\n try {\n // Extract document types from the state\n const documentTypes = state.documentTypes.map((dt) => dt.documentType);\n\n // Generate editor ID using kebabCase\n const editorId: string = kebabCase(state.name);\n\n // Generate the editor using the codegen function\n await generateEditor({\n ...this.config.PH_CONFIG,\n editorName: state.name,\n documentTypes: documentTypes,\n editorId: editorId,\n useTsMorph: USE_TS_MORPH,\n });\n\n logger.info(\n `✅ Editor generation completed successfully for: ${state.name}`,\n );\n\n // Update the manifest with the new editor\n try {\n logger.debug(\n `🔄 Updating manifest with editor: ${state.name} (ID: ${editorId})`,\n );\n\n generateManifest(\n {\n editors: [\n {\n id: editorId,\n name: state.name,\n documentTypes: documentTypes,\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for editor: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for editor ${state.name}:`,\n manifestError,\n );\n // Don't throw here - editor generation was successful\n }\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as DocumentEditorPHState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during editor generation for ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n // Don't throw - let codegen continue with other documents\n return;\n }\n }\n}\n","import {\n generateFromDocument,\n generateManifest,\n validateDocumentModelState,\n} from \"@powerhousedao/codegen\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type {\n DocumentModelGlobalState,\n DocumentModelPHState,\n} from \"@powerhousedao/shared/document-model\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { USE_TS_MORPH, USE_VERSIONING } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for document model documents\n */\nexport class DocumentModelGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/document-model\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): DocumentModelGlobalState | undefined {\n const fullState = strand.state as DocumentModelPHState | undefined;\n if (!fullState) {\n return undefined;\n }\n // The state is the full document state with {auth, document, local, global, header}\n // We need the global property which contains the DocumentModelGlobalState\n return fullState.global;\n }\n\n /**\n * Validate if this document model strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n // Extract the global state from the full document state\n const globalState = this.extractGlobalState(strand);\n if (!globalState) {\n logger.debug(\n `>>> No global state found for document model: ${strand.documentId}`,\n );\n return false;\n }\n\n const validationResult = validateDocumentModelState(globalState);\n if (!validationResult.isValid) {\n const errorList = validationResult.errors\n .map((error) => ` - ${error}`)\n .join(\"\\n\");\n logger.info(\n `⚠️ Skipped code generation for '${globalState.name || strand.documentId}' due to validation errors:\\n${errorList}`,\n );\n return false;\n }\n\n logger.info(\n `Document model ${globalState.name} is valid, proceeding with code generation`,\n );\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const globalState = this.extractGlobalState(strand);\n if (!globalState) {\n logger.error(\n `❌ No global state found for document model: ${strand.documentId}`,\n );\n return;\n }\n // Validation is already done in shouldProcess, so we can proceed directly\n logger.debug(\n `🔄 Starting code generation for document model: ${globalState.name}`,\n );\n try {\n await generateFromDocument({\n documentModelState: globalState,\n config: this.config.PH_CONFIG,\n useTsMorph: USE_TS_MORPH,\n useVersioning: USE_VERSIONING,\n });\n logger.info(\n `✅ Code generation completed successfully for: ${globalState.name}`,\n );\n\n // Update the manifest with the new document model\n try {\n logger.debug(\n `🔄 Updating manifest with document model: ${globalState.name} (ID: ${globalState.id})`,\n );\n\n generateManifest(\n {\n documentModels: [\n {\n id: globalState.id,\n name: globalState.name,\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for document model: ${globalState.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for document model ${globalState.name}:`,\n manifestError,\n );\n // Don't throw here - code generation was successful\n }\n\n // Backup the document\n const extension = globalState.extension?.replace(/^\\.+|\\.+$/g, \"\") || \"\";\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as DocumentModelPHState,\n name: globalState.name,\n },\n this.config.CURRENT_WORKING_DIR,\n extension,\n );\n } catch (error) {\n logger.error(\n `❌ Error during code generation for ${globalState.name}:`,\n error,\n );\n // Don't throw - let codegen continue with other documents\n return;\n }\n }\n}\n","import { generateManifest } from \"@powerhousedao/codegen\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type {\n VetraPackagePHState,\n VetraPackageState,\n} from \"../../../../document-models/vetra-package/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for package documents\n */\nexport class PackageGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/package\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): VetraPackageState | undefined {\n const fullState = strand.state as VetraPackagePHState | undefined;\n if (!fullState) {\n return undefined;\n }\n return fullState.global;\n }\n\n /**\n * Validate if this package strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.debug(`>>> No state found for package: ${strand.documentId}`);\n return false;\n }\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.error(\n `❌ No global state found for package: ${strand.documentId}`,\n );\n return;\n }\n\n logger.info(\"🔄 Generating manifest for package\");\n generateManifest(\n {\n name: state.name ?? \"\",\n category: state.category ?? \"\",\n description: state.description ?? \"\",\n publisher: {\n name: state.author?.name ?? \"\",\n url: state.author?.website ?? \"\",\n },\n },\n this.config.CURRENT_WORKING_DIR,\n );\n logger.info(\"✅ Manifest generated successfully\");\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as VetraPackagePHState,\n name: \"vetra-package\",\n },\n this.config.CURRENT_WORKING_DIR,\n );\n }\n}\n","import { generateProcessor } from \"@powerhousedao/codegen\";\nimport {\n PROCESSOR_APPS,\n type ProcessorApp,\n type ProcessorApps,\n} from \"@powerhousedao/shared/processors\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type {\n ProcessorModulePHState,\n ProcessorModuleState,\n} from \"../../../../document-models/processor-module/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { USE_TS_MORPH } from \"./constants.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for processor documents\n */\nexport class ProcessorGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/processor\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): ProcessorModuleState | undefined {\n const fullState = strand.state as ProcessorModulePHState | undefined;\n if (!fullState) {\n return undefined;\n }\n return fullState.global;\n }\n\n /**\n * Validate if this processor strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.debug(`No state found for processor: ${strand.documentId}`);\n return false;\n }\n\n // Check if we have a valid processor name, type, document types, and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for processor: ${strand.documentId}`);\n return false;\n }\n\n if (!state.type) {\n logger.debug(`No type found for processor: ${state.name}`);\n return false;\n }\n\n if (!state.documentTypes || state.documentTypes.length === 0) {\n logger.debug(`No document types found for processor: ${state.name}`);\n return false;\n }\n\n if (!state.processorApps || state.processorApps.length === 0) {\n logger.debug(`No processor apps found for processor: ${state.name}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Processor not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.error(`No state found for processor: ${strand.documentId}`);\n return;\n }\n\n // Check if we have a valid processor name, type, document types, and it's confirmed\n if (\n state.name &&\n state.type &&\n state.documentTypes.length > 0 &&\n state.processorApps.length > 0 &&\n state.status === \"CONFIRMED\"\n ) {\n logger.info(`🔄 Starting processor generation for: ${state.name}`);\n try {\n // Map the type value from document state to generateProcessor expected values\n let processorType: \"analytics\" | \"relationalDb\";\n if (state.type === \"analytics\") {\n processorType = \"analytics\";\n } else if (state.type === \"relational\") {\n processorType = \"relationalDb\";\n } else {\n logger.error(`❌ Unsupported processor type: ${state.type}`);\n return;\n }\n\n // Extract document types from the state\n const documentTypes = state.documentTypes.map((dt) => dt.documentType);\n\n const processorApps = state.processorApps;\n\n if (!isProcessorApps(processorApps)) {\n logger.error(\n `❌ Unsupported processor apps: ${processorApps.join(\", \")}`,\n );\n return;\n }\n\n // Generate the processor using the codegen function\n await generateProcessor({\n processorName: state.name,\n processorType,\n documentTypes,\n skipFormat: this.config.PH_CONFIG.skipFormat,\n useTsMorph: USE_TS_MORPH,\n processorApps,\n });\n\n logger.info(\n `✅ Processor generation completed successfully for: ${state.name}`,\n );\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as ProcessorModulePHState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during processor generation for ${state.name}:`,\n error,\n );\n if (error instanceof Error) {\n logger.error(`❌ Error message: ${error.message}`);\n }\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping processor generation - missing name for processor`,\n );\n return;\n } else if (!state.type) {\n logger.error(\n `❌ Skipping processor generation - missing type for processor \"${state.name}\"`,\n );\n return;\n } else if (state.documentTypes.length === 0) {\n logger.error(\n `❌ Skipping processor generation - missing document types for processor \"${state.name}\"`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping processor generation - processor \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n\nfunction isProcessorApps(input: readonly string[]): input is ProcessorApps {\n if (input.length === 0) return false;\n if (new Set(input).size !== input.length) {\n return false;\n }\n if (!input.every((i) => PROCESSOR_APPS.includes(i as ProcessorApp)))\n return false;\n\n return true;\n}\n","import { generateManifest, generateSubgraph } from \"@powerhousedao/codegen\";\nimport { kebabCase } from \"change-case\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type {\n SubgraphModulePHState,\n SubgraphModuleState,\n} from \"../../../../document-models/subgraph-module/index.js\";\nimport { logger } from \"../../logger.js\";\nimport { BaseDocumentGen } from \"../base-document-gen.js\";\nimport { minimalBackupDocument } from \"./utils.js\";\n\n/**\n * Generator for subgraph documents\n */\nexport class SubgraphGenerator extends BaseDocumentGen {\n readonly supportedDocumentTypes = \"powerhouse/subgraph\";\n\n /**\n * Extract the global state from the full document state\n */\n private extractGlobalState(\n strand: InternalTransmitterUpdate,\n ): SubgraphModuleState | undefined {\n const fullState = strand.state as SubgraphModulePHState | undefined;\n if (!fullState) {\n return undefined;\n }\n return fullState.global;\n }\n\n /**\n * Validate if this subgraph strand should be processed\n */\n shouldProcess(strand: InternalTransmitterUpdate): boolean {\n // First run base validation\n if (!super.shouldProcess(strand)) {\n return false;\n }\n\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.debug(`No state found for subgraph: ${strand.documentId}`);\n return false;\n }\n\n // Check if we have a valid subgraph name and it's confirmed\n if (!state.name) {\n logger.debug(`No name found for subgraph: ${strand.documentId}`);\n return false;\n }\n\n if (state.status !== \"CONFIRMED\") {\n logger.debug(\n `Subgraph not confirmed: ${state.name} (status: ${state.status})`,\n );\n return false;\n }\n\n return true;\n }\n\n async generate(strand: InternalTransmitterUpdate): Promise<void> {\n const state = this.extractGlobalState(strand);\n if (!state) {\n logger.error(`No state found for subgraph: ${strand.documentId}`);\n return;\n }\n\n // Check if we have a valid subgraph name and it's confirmed\n if (state.name && state.status === \"CONFIRMED\") {\n logger.info(`🔄 Starting subgraph generation for: ${state.name}`);\n try {\n // Generate subgraph ID using kebabCase\n const subgraphId: string = kebabCase(state.name);\n\n await generateSubgraph(state.name, null, this.config.PH_CONFIG);\n logger.info(\n `✅ Subgraph generation completed successfully for: ${state.name}`,\n );\n\n // Update the manifest with the new subgraph\n try {\n logger.debug(\n `🔄 Updating manifest with subgraph: ${state.name} (ID: ${subgraphId})`,\n );\n\n generateManifest(\n {\n subgraphs: [\n {\n id: subgraphId,\n name: state.name,\n documentTypes: [],\n },\n ],\n },\n this.config.CURRENT_WORKING_DIR,\n );\n\n logger.debug(\n `✅ Manifest updated successfully for subgraph: ${state.name}`,\n );\n } catch (manifestError) {\n logger.error(\n `⚠️ Failed to update manifest for subgraph ${state.name}:`,\n manifestError,\n );\n // Don't throw here - subgraph generation was successful\n }\n\n // Backup the document\n await minimalBackupDocument(\n {\n documentId: strand.documentId,\n documentType: strand.documentType,\n branch: strand.branch,\n state: strand.state as SubgraphModulePHState,\n name: state.name,\n },\n this.config.CURRENT_WORKING_DIR,\n );\n } catch (error) {\n logger.error(\n `❌ Error during subgraph generation for ${state.name}:`,\n error,\n );\n }\n } else {\n if (!state.name) {\n logger.error(\n `❌ Skipping subgraph generation - missing name for subgraph`,\n );\n return;\n } else if (state.status !== \"CONFIRMED\") {\n logger.error(\n `❌ Skipping subgraph generation - subgraph \"${state.name}\" is not confirmed (status: ${state.status})`,\n );\n return;\n }\n }\n }\n}\n","import type { BaseDocumentGen } from \"./base-document-gen.js\";\nimport { DocumentCodegenManager } from \"./document-codegen-manager.js\";\nimport {\n AppGenerator,\n DocumentEditorGenerator,\n DocumentModelGenerator,\n PackageGenerator,\n ProcessorGenerator,\n SubgraphGenerator,\n} from \"./generators/index.js\";\nimport type { Config } from \"./types.js\";\n\n/**\n * Factory class for creating and configuring DocumentCodegenManager instances\n * with all the standard generators pre-registered\n */\nexport class DocumentCodegenFactory {\n /**\n * Create a DocumentCodegenManager with all standard generators registered\n */\n static createManager(\n config: Config,\n interactiveMode: boolean = false,\n ): DocumentCodegenManager {\n const manager = new DocumentCodegenManager(config, interactiveMode);\n\n // Register all the standard generators\n manager.registerGenerator(\n \"powerhouse/document-model\",\n DocumentModelGenerator,\n );\n manager.registerGenerator(\"powerhouse/package\", PackageGenerator);\n manager.registerGenerator(\"powerhouse/app\", AppGenerator);\n manager.registerGenerator(\n \"powerhouse/document-editor\",\n DocumentEditorGenerator,\n );\n manager.registerGenerator(\"powerhouse/subgraph\", SubgraphGenerator);\n manager.registerGenerator(\"powerhouse/processor\", ProcessorGenerator);\n\n return manager;\n }\n\n /**\n * Create a DocumentCodegenManager with only specific generators\n */\n static createManagerWithGenerators(\n config: Config,\n generators: Array<new (config: Config) => any>,\n interactiveMode: boolean = false,\n ): DocumentCodegenManager {\n const manager = new DocumentCodegenManager(config, interactiveMode);\n\n for (const generatorClass of generators) {\n const generator = new generatorClass(config) as BaseDocumentGen;\n const supportedTypes = generator.getSupportedDocumentTypes();\n\n for (const documentType of supportedTypes) {\n manager.registerGenerator(documentType, generatorClass);\n }\n }\n\n return manager;\n }\n\n /**\n * Get all available generator classes\n */\n static getAvailableGenerators() {\n return {\n DocumentModelGenerator,\n PackageGenerator,\n AppGenerator,\n DocumentEditorGenerator,\n SubgraphGenerator,\n ProcessorGenerator,\n };\n }\n}\n","import { getConfig } from \"@powerhousedao/config/node\";\nimport type {\n IProcessor,\n OperationWithContext,\n} from \"@powerhousedao/reactor-browser\";\nimport type { InternalTransmitterUpdate } from \"document-drive\";\nimport type { DocumentCodegenManager } from \"./document-handlers/document-codegen-manager.js\";\nimport { DocumentCodegenFactory } from \"./document-handlers/index.js\";\nimport { logger } from \"./logger.js\";\n\nconst PH_CONFIG = getConfig();\nconst CURRENT_WORKING_DIR = process.cwd();\n\nexport class CodegenProcessor implements IProcessor {\n private manager: DocumentCodegenManager;\n\n constructor(interactiveMode = false) {\n this.manager = DocumentCodegenFactory.createManager(\n {\n PH_CONFIG,\n CURRENT_WORKING_DIR,\n },\n interactiveMode,\n );\n\n if (interactiveMode) {\n logger.info(`CodegenProcessor initialized with interactive mode enabled`);\n } else {\n logger.debug(\n `CodegenProcessor initialized with interactive mode disabled`,\n );\n }\n }\n\n async onOperations(operations: OperationWithContext[]): Promise<void> {\n logger.info(\"CodegenProcessor.onOperations()\");\n\n for (const { operation, context } of operations) {\n const generator = this.manager.getGenerator(context.documentType);\n if (!generator) {\n logger.debug(\n `No generator found for document type: ${context.documentType}`,\n );\n continue;\n }\n\n // Create strand-like object for generator (using existing generator interface)\n // Cast to InternalTransmitterUpdate since generators only use a subset of fields\n const strand = {\n documentId: context.documentId,\n documentType: context.documentType,\n scope: context.scope,\n branch: context.branch,\n driveId: \"\", // Not available in new format\n operations: [operation],\n state: context.resultingState\n ? (JSON.parse(context.resultingState) as unknown)\n : undefined,\n } as InternalTransmitterUpdate;\n\n const shouldProcess = generator.shouldProcess(strand);\n if (shouldProcess) {\n await this.manager.routeAndGenerate(strand);\n }\n }\n }\n\n async onDisconnect() {}\n\n // Utility methods for external configuration and monitoring\n public setInteractiveMode(enabled: boolean): void {\n this.manager.setInteractiveMode(enabled);\n }\n\n public isInteractive(): boolean {\n return this.manager.isInteractiveMode();\n }\n\n public isProcessingInteractive(): boolean {\n return this.manager.isProcessingInteractive();\n }\n}\n"],"mappings":"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"}
|