@fgv/ts-res-cli 5.0.1-0 → 5.0.1-10
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/lib/cli.d.ts +40 -0
- package/lib/cli.js +497 -0
- package/package.json +16 -19
package/lib/cli.d.ts
CHANGED
|
@@ -28,13 +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;
|
|
31
35
|
/**
|
|
32
36
|
* Handles the archive command
|
|
33
37
|
*/
|
|
34
38
|
private _handleArchiveCommand;
|
|
39
|
+
/**
|
|
40
|
+
* Parses and validates delta options
|
|
41
|
+
*/
|
|
42
|
+
private _parseDeltaOptions;
|
|
35
43
|
/**
|
|
36
44
|
* Parses and validates compile options
|
|
37
45
|
*/
|
|
38
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;
|
|
39
79
|
}
|
|
40
80
|
//# sourceMappingURL=cli.d.ts.map
|
package/lib/cli.js
CHANGED
|
@@ -153,6 +153,24 @@ class TsResCliApp {
|
|
|
153
153
|
.action(async (options) => {
|
|
154
154
|
await this._handleArchiveCommand(options);
|
|
155
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
|
+
});
|
|
156
174
|
}
|
|
157
175
|
/**
|
|
158
176
|
* Handles the compile command
|
|
@@ -424,6 +442,24 @@ class TsResCliApp {
|
|
|
424
442
|
process.exit(1);
|
|
425
443
|
}
|
|
426
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
|
+
}
|
|
427
463
|
/**
|
|
428
464
|
* Handles the archive command
|
|
429
465
|
*/
|
|
@@ -479,6 +515,47 @@ class TsResCliApp {
|
|
|
479
515
|
process.exit(1);
|
|
480
516
|
}
|
|
481
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
|
+
}
|
|
482
559
|
/**
|
|
483
560
|
* Parses and validates compile options
|
|
484
561
|
*/
|
|
@@ -525,6 +602,426 @@ class TsResCliApp {
|
|
|
525
602
|
return (0, ts_utils_1.fail)(`Failed to parse options: ${error}`);
|
|
526
603
|
}
|
|
527
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
|
+
}
|
|
528
1025
|
}
|
|
529
1026
|
exports.TsResCliApp = TsResCliApp;
|
|
530
1027
|
//# sourceMappingURL=cli.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-res-cli",
|
|
3
|
-
"version": "5.0.1-
|
|
3
|
+
"version": "5.0.1-10",
|
|
4
4
|
"description": "Command-line interface for ts-res resource compilation and management",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,30 +18,27 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"commander": "^11.0.0",
|
|
21
|
-
"@fgv/ts-res": "5.0.1-
|
|
22
|
-
"@fgv/ts-utils": "5.0.1-
|
|
23
|
-
"@fgv/ts-
|
|
24
|
-
"@fgv/ts-
|
|
25
|
-
"@fgv/ts-json-base": "5.0.1-
|
|
21
|
+
"@fgv/ts-res": "5.0.1-10",
|
|
22
|
+
"@fgv/ts-utils": "5.0.1-10",
|
|
23
|
+
"@fgv/ts-json": "5.0.1-10",
|
|
24
|
+
"@fgv/ts-extras": "5.0.1-10",
|
|
25
|
+
"@fgv/ts-json-base": "5.0.1-10"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@rushstack/heft": "
|
|
29
|
-
"@rushstack/heft-node-rig": "2.
|
|
30
|
-
"@rushstack/eslint-config": "4.
|
|
28
|
+
"@rushstack/heft": "1.1.3",
|
|
29
|
+
"@rushstack/heft-node-rig": "2.11.4",
|
|
30
|
+
"@rushstack/eslint-config": "4.5.3",
|
|
31
31
|
"@types/heft-jest": "1.0.6",
|
|
32
32
|
"@types/jest": "^29.5.14",
|
|
33
33
|
"@types/node": "^20.14.9",
|
|
34
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
35
|
-
"@typescript-eslint/parser": "^8.
|
|
36
|
-
"eslint": "^9.
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
35
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
36
|
+
"eslint": "^9.39.0",
|
|
37
37
|
"jest": "^29.7.0",
|
|
38
|
-
"ts-jest": "^29.4.
|
|
39
|
-
"typescript": "5.
|
|
40
|
-
"@rushstack/heft-jest-plugin": "
|
|
41
|
-
"@fgv/ts-utils-jest": "5.0.1-
|
|
42
|
-
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"typescript": "^5.7.3"
|
|
38
|
+
"ts-jest": "^29.4.5",
|
|
39
|
+
"typescript": "5.9.3",
|
|
40
|
+
"@rushstack/heft-jest-plugin": "1.1.3",
|
|
41
|
+
"@fgv/ts-utils-jest": "5.0.1-10"
|
|
45
42
|
},
|
|
46
43
|
"scripts": {
|
|
47
44
|
"build": "heft build --clean",
|