@fgv/ts-res-cli 5.0.0-9 → 5.0.1-1

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/CHANGELOG.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@fgv/ts-res-cli",
3
+ "entries": [
4
+ {
5
+ "version": "5.0.1",
6
+ "tag": "@fgv/ts-res-cli_v5.0.1",
7
+ "date": "Tue, 23 Sep 2025 03:13:55 GMT",
8
+ "comments": {}
9
+ },
10
+ {
11
+ "version": "5.0.0",
12
+ "tag": "@fgv/ts-res-cli_v5.0.0",
13
+ "date": "Tue, 23 Sep 2025 02:54:20 GMT",
14
+ "comments": {
15
+ "none": [
16
+ {
17
+ "comment": "initial checkin"
18
+ }
19
+ ]
20
+ }
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,16 @@
1
+ // ESLint 9 flat config
2
+ const nodeProfile = require('@rushstack/eslint-config/flat/profile/node');
3
+ const packletsPlugin = require('@rushstack/eslint-config/flat/mixins/packlets');
4
+ const tsdocPlugin = require('@rushstack/eslint-config/flat/mixins/tsdoc');
5
+
6
+ module.exports = [
7
+ ...nodeProfile,
8
+ packletsPlugin,
9
+ ...tsdocPlugin,
10
+ {
11
+ // Override specific rules if needed
12
+ rules: {
13
+ '@rushstack/packlets/mechanics': 'warn'
14
+ }
15
+ }
16
+ ];
package/lib/cli.d.ts CHANGED
@@ -28,9 +28,53 @@ export declare class TsResCliApp {
28
28
  * Handles the config command
29
29
  */
30
30
  private _handleConfigCommand;
31
+ /**
32
+ * Handles the delta command
33
+ */
34
+ private _handleDeltaCommand;
35
+ /**
36
+ * Handles the archive command
37
+ */
38
+ private _handleArchiveCommand;
39
+ /**
40
+ * Parses and validates delta options
41
+ */
42
+ private _parseDeltaOptions;
31
43
  /**
32
44
  * Parses and validates compile options
33
45
  */
34
46
  private _parseCompileOptions;
47
+ /**
48
+ * Generates delta between baseline and target resources
49
+ */
50
+ private _generateDelta;
51
+ /**
52
+ * Loads system configuration (reused from ResourceCompiler pattern)
53
+ */
54
+ private _loadSystemConfiguration;
55
+ /**
56
+ * Creates a resource manager from a path (reused from ResourceCompiler pattern)
57
+ */
58
+ private _createResourceManager;
59
+ /**
60
+ * Imports resources from a file path (reused from ResourceCompiler pattern)
61
+ */
62
+ private _importResourcesFromPath;
63
+ /**
64
+ * Creates a resource resolver from a resource manager and system configuration
65
+ */
66
+ private _createResourceResolver;
67
+ /**
68
+ * Generates output blob for delta resources
69
+ */
70
+ private _generateDeltaBlob;
71
+ /**
72
+ * Generates resource information for delta output
73
+ */
74
+ private _generateDeltaResourceInfo;
75
+ /**
76
+ * Writes delta output to file
77
+ */
78
+ private _writeDeltaOutput;
35
79
  }
36
80
  //# sourceMappingURL=cli.d.ts.map
package/lib/cli.js CHANGED
@@ -142,6 +142,35 @@ class TsResCliApp {
142
142
  .action(async (options) => {
143
143
  await this._handleConfigCommand(options);
144
144
  });
145
+ this._program
146
+ .command('archive')
147
+ .description('Create ZIP archive of resources and configuration')
148
+ .option('-i, --input <path>', 'Input file or directory path')
149
+ .option('--config <path>', 'Configuration file path')
150
+ .requiredOption('-o, --output <path>', 'Output ZIP file path')
151
+ .option('-v, --verbose', 'Verbose output', false)
152
+ .option('-q, --quiet', 'Quiet output', false)
153
+ .action(async (options) => {
154
+ await this._handleArchiveCommand(options);
155
+ });
156
+ this._program
157
+ .command('delta')
158
+ .description('Generate delta between baseline and target resources')
159
+ .requiredOption('--baseline <path>', 'Baseline resource file or directory path')
160
+ .requiredOption('--target <path>', 'Target resource file or directory path')
161
+ .requiredOption('-o, --output <path>', 'Output file path')
162
+ .option('--config <name|path>', 'Predefined configuration name or system configuration file path (JSON, ISystemConfiguration format)')
163
+ .option('--context-filter <token>', 'Context filter token (pipe-separated, e.g., "language=en-US|territory=US")')
164
+ .option('--qualifier-defaults <token>', 'Qualifier default values token (pipe-separated, e.g., "language=en-US,en-CA|territory=US")')
165
+ .option('--resource-ids <ids>', 'Comma-separated list of specific resource IDs to include in delta generation')
166
+ .option('--skip-unchanged', 'Skip resources that have not changed between baseline and target', true)
167
+ .option('-f, --format <format>', 'Output format (compiled, source, js, ts, binary, bundle)', 'compiled')
168
+ .option('-v, --verbose', 'Verbose output', false)
169
+ .option('-q, --quiet', 'Quiet output', false)
170
+ .option('--include-metadata', 'Include resource metadata in output', false)
171
+ .action(async (options) => {
172
+ await this._handleDeltaCommand(options);
173
+ });
145
174
  }
146
175
  /**
147
176
  * Handles the compile command
@@ -413,6 +442,120 @@ class TsResCliApp {
413
442
  process.exit(1);
414
443
  }
415
444
  }
445
+ /**
446
+ * Handles the delta command
447
+ */
448
+ async _handleDeltaCommand(options) {
449
+ const deltaOptions = this._parseDeltaOptions(options);
450
+ if (deltaOptions.isFailure()) {
451
+ console.error(`Error: ${deltaOptions.message}`);
452
+ process.exit(1);
453
+ }
454
+ const result = await this._generateDelta(deltaOptions.value);
455
+ if (result.isFailure()) {
456
+ console.error(`Error: ${result.message}`);
457
+ process.exit(1);
458
+ }
459
+ if (!options.quiet) {
460
+ console.log(`Successfully generated delta to ${options.output}`);
461
+ }
462
+ }
463
+ /**
464
+ * Handles the archive command
465
+ */
466
+ async _handleArchiveCommand(options) {
467
+ try {
468
+ // Import ZipArchive dynamically to avoid loading if not needed
469
+ const { ZipArchive } = await Promise.resolve().then(() => __importStar(require('@fgv/ts-res')));
470
+ if (!options.input && !options.config) {
471
+ console.error('Error: At least one of --input or --config must be specified');
472
+ process.exit(1);
473
+ }
474
+ if (!options.quiet) {
475
+ console.log('Creating ZIP archive...');
476
+ if (options.input)
477
+ console.log(`Input: ${options.input}`);
478
+ if (options.config)
479
+ console.log(`Config: ${options.config}`);
480
+ console.log(`Output: ${options.output}`);
481
+ }
482
+ // Create ZIP archive using the new zip-archive packlet
483
+ const creator = new ZipArchive.ZipArchiveCreator();
484
+ const createResult = await creator.createFromBuffer({
485
+ inputPath: options.input,
486
+ configPath: options.config
487
+ }, options.verbose
488
+ ? (phase, progress, message) => {
489
+ console.log(`[${phase}] ${progress}% - ${message}`);
490
+ }
491
+ : undefined);
492
+ if (createResult.isFailure()) {
493
+ console.error(`Error: Failed to create ZIP archive: ${createResult.message}`);
494
+ process.exit(1);
495
+ }
496
+ const { zipBuffer, manifest, size } = createResult.value;
497
+ // Write the ZIP buffer to the specified output file
498
+ const fs = await Promise.resolve().then(() => __importStar(require('fs'))).then((m) => m.promises);
499
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
500
+ const outputPath = path.resolve(options.output);
501
+ const outputDir = path.dirname(outputPath);
502
+ // Ensure output directory exists
503
+ await fs.mkdir(outputDir, { recursive: true });
504
+ // Write ZIP file
505
+ await fs.writeFile(outputPath, zipBuffer);
506
+ if (!options.quiet) {
507
+ console.log(`ZIP archive created successfully: ${outputPath}`);
508
+ console.log(`Archive size: ${(size / 1024).toFixed(2)} KB`);
509
+ console.log(`Manifest:`);
510
+ console.log(JSON.stringify(manifest, null, 2));
511
+ }
512
+ }
513
+ catch (error) {
514
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
515
+ process.exit(1);
516
+ }
517
+ }
518
+ /**
519
+ * Parses and validates delta options
520
+ */
521
+ _parseDeltaOptions(options) {
522
+ var _a;
523
+ try {
524
+ const format = options.format;
525
+ if (!['compiled', 'source', 'js', 'ts', 'binary', 'bundle'].includes(format)) {
526
+ return (0, ts_utils_1.fail)(`Invalid format: ${format}`);
527
+ }
528
+ // Parse resource IDs if provided
529
+ let resourceIds;
530
+ if (options.resourceIds) {
531
+ resourceIds = options.resourceIds
532
+ .split(',')
533
+ .map((id) => id.trim())
534
+ .filter((id) => id.length > 0);
535
+ if (resourceIds.length === 0) {
536
+ return (0, ts_utils_1.fail)('Resource IDs list cannot be empty');
537
+ }
538
+ }
539
+ const deltaOptions = {
540
+ baseline: options.baseline,
541
+ target: options.target,
542
+ output: options.output,
543
+ config: options.config,
544
+ contextFilter: options.contextFilter,
545
+ qualifierDefaults: options.qualifierDefaults,
546
+ resourceIds,
547
+ skipUnchanged: (_a = options.skipUnchanged) !== null && _a !== void 0 ? _a : true,
548
+ format,
549
+ verbose: options.verbose || false,
550
+ quiet: options.quiet || false,
551
+ includeMetadata: options.includeMetadata || false
552
+ };
553
+ return (0, ts_utils_1.succeed)(deltaOptions);
554
+ }
555
+ catch (error) {
556
+ return (0, ts_utils_1.fail)(`Failed to parse delta options: ${error}`);
557
+ }
558
+ }
416
559
  /**
417
560
  * Parses and validates compile options
418
561
  */
@@ -459,6 +602,426 @@ class TsResCliApp {
459
602
  return (0, ts_utils_1.fail)(`Failed to parse options: ${error}`);
460
603
  }
461
604
  }
605
+ /**
606
+ * Generates delta between baseline and target resources
607
+ */
608
+ async _generateDelta(options) {
609
+ try {
610
+ if (options.verbose) {
611
+ console.error('Starting delta generation...');
612
+ console.error(`Baseline: ${options.baseline}`);
613
+ console.error(`Target: ${options.target}`);
614
+ console.error(`Output: ${options.output}`);
615
+ }
616
+ // Load system configuration
617
+ const config = await this._loadSystemConfiguration(options.config, options.verbose);
618
+ if (config.isFailure()) {
619
+ return (0, ts_utils_1.fail)(`Failed to load configuration: ${config.message}`);
620
+ }
621
+ if (options.verbose) {
622
+ console.error('Configuration loaded successfully');
623
+ }
624
+ // Create resource managers for baseline and target
625
+ const baselineManager = await this._createResourceManager(config.value, options.baseline, options.qualifierDefaults, options.verbose);
626
+ if (baselineManager.isFailure()) {
627
+ return (0, ts_utils_1.fail)(`Failed to load baseline resources: ${baselineManager.message}`);
628
+ }
629
+ const targetManager = await this._createResourceManager(config.value, options.target, options.qualifierDefaults, options.verbose);
630
+ if (targetManager.isFailure()) {
631
+ return (0, ts_utils_1.fail)(`Failed to load target resources: ${targetManager.message}`);
632
+ }
633
+ if (options.verbose) {
634
+ console.error(`Baseline loaded: ${baselineManager.value.numResources} resources, ${baselineManager.value.numCandidates} candidates`);
635
+ console.error(`Target loaded: ${targetManager.value.numResources} resources, ${targetManager.value.numCandidates} candidates`);
636
+ }
637
+ // Create resource resolvers
638
+ const baselineResolver = await this._createResourceResolver(baselineManager.value, options.contextFilter, options.verbose, config.value);
639
+ if (baselineResolver.isFailure()) {
640
+ return (0, ts_utils_1.fail)(`Failed to create baseline resolver: ${baselineResolver.message}`);
641
+ }
642
+ const targetResolver = await this._createResourceResolver(targetManager.value, options.contextFilter, options.verbose, config.value);
643
+ if (targetResolver.isFailure()) {
644
+ return (0, ts_utils_1.fail)(`Failed to create target resolver: ${targetResolver.message}`);
645
+ }
646
+ // Create delta generator
647
+ const deltaGenerator = TsRes.Resources.DeltaGenerator.create({
648
+ baselineResolver: baselineResolver.value,
649
+ deltaResolver: targetResolver.value,
650
+ resourceManager: baselineManager.value,
651
+ logger: options.verbose ? new ts_utils_1.Logging.ConsoleLogger() : undefined
652
+ });
653
+ if (deltaGenerator.isFailure()) {
654
+ return (0, ts_utils_1.fail)(`Failed to create delta generator: ${deltaGenerator.message}`);
655
+ }
656
+ // Parse context filter for delta generation options
657
+ let context;
658
+ if (options.contextFilter) {
659
+ const contextTokens = new TsRes.Context.ContextTokens(baselineManager.value.qualifiers);
660
+ const contextResult = contextTokens.contextTokenToPartialContext(options.contextFilter);
661
+ if (contextResult.isFailure()) {
662
+ return (0, ts_utils_1.fail)(`Failed to parse context filter: ${contextResult.message}`);
663
+ }
664
+ context = contextResult.value;
665
+ }
666
+ // Generate delta
667
+ const deltaOptions = {
668
+ context,
669
+ resourceIds: options.resourceIds,
670
+ skipUnchanged: options.skipUnchanged
671
+ };
672
+ if (options.verbose) {
673
+ console.error('Generating delta...');
674
+ }
675
+ const deltaResult = deltaGenerator.value.generate(deltaOptions);
676
+ if (deltaResult.isFailure()) {
677
+ return (0, ts_utils_1.fail)(`Delta generation failed: ${deltaResult.message}`);
678
+ }
679
+ const deltaManager = deltaResult.value;
680
+ if (options.verbose) {
681
+ console.error(`Delta generated: ${deltaManager.numResources} resources, ${deltaManager.numCandidates} candidates`);
682
+ }
683
+ // Generate output blob
684
+ const blob = await this._generateDeltaBlob(deltaManager, options, config.value);
685
+ if (blob.isFailure()) {
686
+ return (0, ts_utils_1.fail)(`Failed to generate output blob: ${blob.message}`);
687
+ }
688
+ // Write output
689
+ const writeResult = await this._writeDeltaOutput(blob.value, options);
690
+ if (writeResult.isFailure()) {
691
+ return (0, ts_utils_1.fail)(`Failed to write output: ${writeResult.message}`);
692
+ }
693
+ if (options.verbose) {
694
+ console.error(`Delta output written to: ${options.output}`);
695
+ }
696
+ return (0, ts_utils_1.succeed)(undefined);
697
+ }
698
+ catch (error) {
699
+ return (0, ts_utils_1.fail)(`Delta generation failed: ${error}`);
700
+ }
701
+ }
702
+ /**
703
+ * Loads system configuration (reused from ResourceCompiler pattern)
704
+ */
705
+ async _loadSystemConfiguration(configOption, verbose) {
706
+ try {
707
+ if (configOption) {
708
+ // Check if it's a predefined configuration name
709
+ const predefinedNames = [
710
+ 'default',
711
+ 'language-priority',
712
+ 'territory-priority',
713
+ 'extended-example'
714
+ ];
715
+ if (predefinedNames.includes(configOption)) {
716
+ const predefinedResult = TsRes.Config.getPredefinedDeclaration(configOption);
717
+ if (predefinedResult.isSuccess()) {
718
+ if (verbose) {
719
+ console.error(`Using predefined configuration: ${predefinedResult.value.name}`);
720
+ }
721
+ return (0, ts_utils_1.succeed)(predefinedResult.value);
722
+ }
723
+ }
724
+ // Try to load as file path
725
+ try {
726
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
727
+ const fs = await Promise.resolve().then(() => __importStar(require('fs'))).then((m) => m.promises);
728
+ const configPath = path.resolve(configOption);
729
+ const configContent = await fs.readFile(configPath, 'utf-8');
730
+ const configData = JSON.parse(configContent);
731
+ const configResult = TsRes.Config.Convert.systemConfiguration.convert(configData);
732
+ if (configResult.isFailure()) {
733
+ return (0, ts_utils_1.fail)(`Invalid configuration file: ${configResult.message}`);
734
+ }
735
+ if (verbose) {
736
+ console.error(`Using custom configuration: ${configResult.value.name}`);
737
+ }
738
+ return (0, ts_utils_1.succeed)(configResult.value);
739
+ }
740
+ catch (fileError) {
741
+ return (0, ts_utils_1.fail)(`Configuration '${configOption}' is not a predefined configuration name and failed to load as file: ${fileError}`);
742
+ }
743
+ }
744
+ else {
745
+ // Use default configuration
746
+ const defaultResult = TsRes.Config.getPredefinedDeclaration('default');
747
+ if (defaultResult.isSuccess()) {
748
+ if (verbose) {
749
+ console.error(`Using default configuration: ${defaultResult.value.name}`);
750
+ }
751
+ return (0, ts_utils_1.succeed)(defaultResult.value);
752
+ }
753
+ else {
754
+ return (0, ts_utils_1.fail)('Failed to load default configuration');
755
+ }
756
+ }
757
+ }
758
+ catch (error) {
759
+ return (0, ts_utils_1.fail)(`Failed to load system configuration: ${error}`);
760
+ }
761
+ }
762
+ /**
763
+ * Creates a resource manager from a path (reused from ResourceCompiler pattern)
764
+ */
765
+ async _createResourceManager(systemConfig, inputPath, qualifierDefaults, verbose) {
766
+ try {
767
+ // Parse qualifier defaults if provided
768
+ let qualifierDefaultValues;
769
+ if (qualifierDefaults) {
770
+ const tempSystemConfigResult = TsRes.Config.SystemConfiguration.create(systemConfig);
771
+ if (tempSystemConfigResult.isFailure()) {
772
+ return (0, ts_utils_1.fail)(`Failed to create temporary system configuration: ${tempSystemConfigResult.message}`);
773
+ }
774
+ const tokens = new TsRes.Qualifiers.QualifierDefaultValueTokens(tempSystemConfigResult.value.qualifiers);
775
+ const defaultsResult = tokens.qualifierDefaultValuesTokenToDecl(qualifierDefaults);
776
+ if (defaultsResult.isFailure()) {
777
+ return (0, ts_utils_1.fail)(`Failed to parse qualifier defaults: ${defaultsResult.message}`);
778
+ }
779
+ qualifierDefaultValues = defaultsResult.value;
780
+ }
781
+ // Create system configuration
782
+ const systemConfigResult = TsRes.Config.SystemConfiguration.create(systemConfig, qualifierDefaultValues ? { qualifierDefaultValues } : undefined);
783
+ if (systemConfigResult.isFailure()) {
784
+ return (0, ts_utils_1.fail)(`Failed to create system configuration: ${systemConfigResult.message}`);
785
+ }
786
+ const config = systemConfigResult.value;
787
+ // Create resource manager
788
+ const manager = TsRes.Resources.ResourceManagerBuilder.create({
789
+ qualifiers: config.qualifiers,
790
+ resourceTypes: config.resourceTypes
791
+ });
792
+ if (manager.isFailure()) {
793
+ return (0, ts_utils_1.fail)(`Failed to create resource manager: ${manager.message}`);
794
+ }
795
+ // Import resources from path
796
+ const importResult = await this._importResourcesFromPath(manager.value, inputPath, verbose);
797
+ if (importResult.isFailure()) {
798
+ return (0, ts_utils_1.fail)(`Failed to import resources from ${inputPath}: ${importResult.message}`);
799
+ }
800
+ return (0, ts_utils_1.succeed)(manager.value);
801
+ }
802
+ catch (error) {
803
+ return (0, ts_utils_1.fail)(`Failed to create resource manager: ${error}`);
804
+ }
805
+ }
806
+ /**
807
+ * Imports resources from a file path (reused from ResourceCompiler pattern)
808
+ */
809
+ async _importResourcesFromPath(manager, inputPath, verbose) {
810
+ try {
811
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
812
+ const { FileTree } = await Promise.resolve().then(() => __importStar(require('@fgv/ts-json-base')));
813
+ const resolvedPath = path.resolve(inputPath);
814
+ // Create FileTree for file system operations
815
+ const fileTree = FileTree.forFilesystem();
816
+ if (fileTree.isFailure()) {
817
+ return (0, ts_utils_1.fail)(`Failed to create file tree: ${fileTree.message}`);
818
+ }
819
+ // Create ImportManager
820
+ const importManager = TsRes.Import.ImportManager.create({
821
+ resources: manager,
822
+ fileTree: fileTree.value
823
+ });
824
+ if (importManager.isFailure()) {
825
+ return (0, ts_utils_1.fail)(`Failed to create import manager: ${importManager.message}`);
826
+ }
827
+ // Import resources
828
+ if (verbose) {
829
+ console.error(`Importing resources from: ${resolvedPath}`);
830
+ }
831
+ const importResult = importManager.value.importFromFileSystem(resolvedPath);
832
+ if (importResult.isFailure()) {
833
+ return (0, ts_utils_1.fail)(`Failed to import from ${resolvedPath}: ${importResult.message}`);
834
+ }
835
+ if (verbose) {
836
+ console.error(`Successfully imported resources from: ${resolvedPath}`);
837
+ }
838
+ return (0, ts_utils_1.succeed)(undefined);
839
+ }
840
+ catch (error) {
841
+ return (0, ts_utils_1.fail)(`Failed to import resources: ${error}`);
842
+ }
843
+ }
844
+ /**
845
+ * Creates a resource resolver from a resource manager and system configuration
846
+ */
847
+ async _createResourceResolver(manager, contextFilter, verbose, systemConfig) {
848
+ try {
849
+ // Apply context filtering if specified
850
+ let finalManager = manager;
851
+ if (contextFilter) {
852
+ const contextTokens = new TsRes.Context.ContextTokens(manager.qualifiers);
853
+ const contextResult = contextTokens.contextTokenToPartialContext(contextFilter);
854
+ if (contextResult.isFailure()) {
855
+ return (0, ts_utils_1.fail)(`Failed to parse context filter: ${contextResult.message}`);
856
+ }
857
+ const filteredManagerResult = manager.clone({
858
+ filterForContext: contextResult.value,
859
+ reduceQualifiers: false // Don't reduce qualifiers for delta generation
860
+ });
861
+ if (filteredManagerResult.isFailure()) {
862
+ return (0, ts_utils_1.fail)(`Failed to apply context filter: ${filteredManagerResult.message}`);
863
+ }
864
+ finalManager = filteredManagerResult.value;
865
+ if (verbose) {
866
+ console.error(`After context filtering: ${finalManager.numResources} resources, ${finalManager.numCandidates} candidates`);
867
+ }
868
+ }
869
+ // Build the manager to create the resolver
870
+ const builtManager = finalManager.build();
871
+ if (builtManager.isFailure()) {
872
+ return (0, ts_utils_1.fail)(`Failed to build resource manager: ${builtManager.message}`);
873
+ }
874
+ // Create qualifier types from system config or use default
875
+ const qualifierTypesResult = systemConfig
876
+ ? TsRes.Config.SystemConfiguration.create(systemConfig).onSuccess((config) => (0, ts_utils_1.succeed)(config.qualifierTypes))
877
+ : TsRes.QualifierTypes.QualifierTypeCollector.create({
878
+ qualifierTypes: [
879
+ TsRes.QualifierTypes.LanguageQualifierType.create().orThrow(),
880
+ TsRes.QualifierTypes.TerritoryQualifierType.create().orThrow()
881
+ ]
882
+ });
883
+ if (qualifierTypesResult.isFailure()) {
884
+ return (0, ts_utils_1.fail)(`Failed to create qualifier types: ${qualifierTypesResult.message}`);
885
+ }
886
+ // Create context provider - use empty context for default
887
+ const contextProvider = TsRes.Runtime.ValidatingSimpleContextQualifierProvider.create({
888
+ qualifiers: finalManager.qualifiers,
889
+ qualifierValues: {} // Empty context for most general resolution
890
+ });
891
+ if (contextProvider.isFailure()) {
892
+ return (0, ts_utils_1.fail)(`Failed to create context provider: ${contextProvider.message}`);
893
+ }
894
+ // Create resolver with required parameters
895
+ const resolver = TsRes.Runtime.ResourceResolver.create({
896
+ resourceManager: builtManager.value,
897
+ qualifierTypes: qualifierTypesResult.value,
898
+ contextQualifierProvider: contextProvider.value
899
+ });
900
+ if (resolver.isFailure()) {
901
+ return (0, ts_utils_1.fail)(`Failed to create resource resolver: ${resolver.message}`);
902
+ }
903
+ return (0, ts_utils_1.succeed)(resolver.value);
904
+ }
905
+ catch (error) {
906
+ return (0, ts_utils_1.fail)(`Failed to create resource resolver: ${error}`);
907
+ }
908
+ }
909
+ /**
910
+ * Generates output blob for delta resources
911
+ */
912
+ async _generateDeltaBlob(deltaManager, options, systemConfig) {
913
+ try {
914
+ if (options.format === 'compiled') {
915
+ return deltaManager.getCompiledResourceCollection().onSuccess((compiled) => {
916
+ const blob = {
917
+ compiledCollection: compiled
918
+ };
919
+ if (options.includeMetadata) {
920
+ blob.metadata = this._generateDeltaResourceInfo(deltaManager);
921
+ }
922
+ return (0, ts_utils_1.succeed)(blob);
923
+ });
924
+ }
925
+ else if (options.format === 'bundle') {
926
+ // Create bundle using BundleBuilder
927
+ const systemConfigResult = TsRes.Config.SystemConfiguration.create(systemConfig);
928
+ if (systemConfigResult.isFailure()) {
929
+ return (0, ts_utils_1.fail)(`Failed to create system configuration for bundle: ${systemConfigResult.message}`);
930
+ }
931
+ const bundleParams = {
932
+ version: '1.0.0',
933
+ description: 'Generated delta bundle from ts-res-cli',
934
+ normalize: true
935
+ };
936
+ return TsRes.Bundle.BundleBuilder.create(deltaManager, systemConfigResult.value, bundleParams).onSuccess((bundle) => {
937
+ const blob = {
938
+ bundle
939
+ };
940
+ if (options.includeMetadata) {
941
+ blob.metadata = this._generateDeltaResourceInfo(deltaManager);
942
+ }
943
+ return (0, ts_utils_1.succeed)(blob);
944
+ });
945
+ }
946
+ else {
947
+ // Source format
948
+ return deltaManager.getResourceCollectionDecl().onSuccess((resources) => {
949
+ const blob = {
950
+ resources
951
+ };
952
+ if (options.includeMetadata) {
953
+ blob.metadata = this._generateDeltaResourceInfo(deltaManager);
954
+ }
955
+ return (0, ts_utils_1.succeed)(blob);
956
+ });
957
+ }
958
+ }
959
+ catch (error) {
960
+ return (0, ts_utils_1.fail)(`Failed to generate delta blob: ${error}`);
961
+ }
962
+ }
963
+ /**
964
+ * Generates resource information for delta output
965
+ */
966
+ _generateDeltaResourceInfo(deltaManager) {
967
+ const resourceTypes = Array.from(new Set(deltaManager
968
+ .getAllCandidates()
969
+ .map((c) => { var _a; return (_a = c.resourceType) === null || _a === void 0 ? void 0 : _a.key; })
970
+ .filter(Boolean)));
971
+ const qualifiers = Array.from(deltaManager.qualifiers.keys());
972
+ return {
973
+ totalResources: deltaManager.numResources,
974
+ totalCandidates: deltaManager.numCandidates,
975
+ resourceTypes,
976
+ qualifiers
977
+ };
978
+ }
979
+ /**
980
+ * Writes delta output to file
981
+ */
982
+ async _writeDeltaOutput(blob, options) {
983
+ try {
984
+ const path = await Promise.resolve().then(() => __importStar(require('path')));
985
+ const fs = await Promise.resolve().then(() => __importStar(require('fs'))).then((m) => m.promises);
986
+ const outputPath = path.resolve(options.output);
987
+ const outputDir = path.dirname(outputPath);
988
+ // Ensure output directory exists
989
+ await fs.mkdir(outputDir, { recursive: true });
990
+ let content;
991
+ switch (options.format) {
992
+ case 'compiled':
993
+ const compiledData = options.includeMetadata ? blob : blob.compiledCollection;
994
+ content = JSON.stringify(compiledData, null, 2);
995
+ break;
996
+ case 'source':
997
+ content = JSON.stringify(blob, null, 2);
998
+ break;
999
+ case 'js':
1000
+ const jsData = blob.compiledCollection || blob;
1001
+ content = `module.exports = ${JSON.stringify(jsData, null, 2)};`;
1002
+ break;
1003
+ case 'ts':
1004
+ const tsData = blob.compiledCollection || blob;
1005
+ content = `export const resources = ${JSON.stringify(tsData, null, 2)} as const;`;
1006
+ break;
1007
+ case 'binary':
1008
+ const binaryData = blob.compiledCollection || blob;
1009
+ content = JSON.stringify(binaryData);
1010
+ break;
1011
+ case 'bundle':
1012
+ const bundleData = options.includeMetadata ? blob : blob.bundle;
1013
+ content = JSON.stringify(bundleData, null, 2);
1014
+ break;
1015
+ default:
1016
+ return (0, ts_utils_1.fail)(`Unsupported output format: ${options.format}`);
1017
+ }
1018
+ await fs.writeFile(outputPath, content, 'utf-8');
1019
+ return (0, ts_utils_1.succeed)(undefined);
1020
+ }
1021
+ catch (error) {
1022
+ return (0, ts_utils_1.fail)(`Failed to write delta output: ${error}`);
1023
+ }
1024
+ }
462
1025
  }
463
1026
  exports.TsResCliApp = TsResCliApp;
464
1027
  //# sourceMappingURL=cli.js.map