@fgv/ts-res-cli 5.0.0-2 → 5.0.0-20
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/README.md +50 -2
- package/lib/cli.d.ts +4 -0
- package/lib/cli.js +68 -2
- package/lib/compiler.d.ts +5 -0
- package/lib/compiler.js +34 -0
- package/lib/options.d.ts +1 -1
- package/package.json +11 -11
- package/src/cli.ts +90 -2
- package/src/compiler.ts +41 -0
- package/src/options.ts +1 -1
- package/.eslintrc.js +0 -9
- package/.rush/temp/chunked-rush-logs/ts-res-cli.build.chunks.jsonl +0 -6
- package/.rush/temp/operation/build/log-chunks.jsonl +0 -6
- package/.rush/temp/operation/build/state.json +0 -3
- package/.rush/temp/shrinkwrap-deps.json +0 -649
- package/config/jest.config.json +0 -9
- package/lib/cli.d.ts.map +0 -1
- package/lib/cli.js.map +0 -1
- package/lib/compiler.d.ts.map +0 -1
- package/lib/compiler.js.map +0 -1
- package/lib/defaultConfiguration.d.ts.map +0 -1
- package/lib/defaultConfiguration.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/options.d.ts.map +0 -1
- package/lib/options.js.map +0 -1
- package/test/integration/cli-configuration.test.ts +0 -419
- package/test/integration/cli-context-filter-working.test.ts +0 -341
- package/test/integration/cli-integration.test.ts +0 -533
- package/test/unit/cli.test.ts +0 -413
- package/test/unit/compiler.test.ts +0 -1084
- package/tsconfig.json +0 -8
package/README.md
CHANGED
|
@@ -33,6 +33,13 @@ ts-res-compile compile \
|
|
|
33
33
|
-o ./dist/resources.ts \
|
|
34
34
|
--format ts \
|
|
35
35
|
--include-metadata
|
|
36
|
+
|
|
37
|
+
# Create a complete bundle with metadata and configuration
|
|
38
|
+
ts-res-compile compile \
|
|
39
|
+
-i ./resources \
|
|
40
|
+
-o ./dist/resources.bundle.json \
|
|
41
|
+
--format bundle \
|
|
42
|
+
--include-metadata
|
|
36
43
|
```
|
|
37
44
|
|
|
38
45
|
### Validate Resources
|
|
@@ -66,7 +73,7 @@ Compiles resources from input to output format.
|
|
|
66
73
|
|
|
67
74
|
**Optional Options:**
|
|
68
75
|
- `-c, --context <json>` - Context filter for resources (JSON string)
|
|
69
|
-
- `-f, --format <format>` - Output format (
|
|
76
|
+
- `-f, --format <format>` - Output format (compiled, source, js, ts, binary, bundle) [default: compiled]
|
|
70
77
|
- `--debug` - Include debug information [default: false]
|
|
71
78
|
- `-v, --verbose` - Verbose output [default: false]
|
|
72
79
|
- `-q, --quiet` - Quiet output [default: false]
|
|
@@ -134,7 +141,8 @@ The CLI supports the following input formats:
|
|
|
134
141
|
|
|
135
142
|
## Output Formats
|
|
136
143
|
|
|
137
|
-
###
|
|
144
|
+
### Compiled (default)
|
|
145
|
+
Compiled resource collection optimized for runtime use:
|
|
138
146
|
```json
|
|
139
147
|
{
|
|
140
148
|
"resources": {
|
|
@@ -145,6 +153,46 @@ The CLI supports the following input formats:
|
|
|
145
153
|
}
|
|
146
154
|
```
|
|
147
155
|
|
|
156
|
+
### Source
|
|
157
|
+
Original resource collection format:
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"resources": [
|
|
161
|
+
{
|
|
162
|
+
"id": "welcome.message",
|
|
163
|
+
"resourceTypeName": "json",
|
|
164
|
+
"candidates": [
|
|
165
|
+
{
|
|
166
|
+
"json": { "text": "Welcome!" },
|
|
167
|
+
"conditions": { "language": "en" }
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Bundle
|
|
176
|
+
Complete resource bundle with metadata, configuration, and compiled resources:
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"metadata": {
|
|
180
|
+
"dateBuilt": "2025-01-01T00:00:00.000Z",
|
|
181
|
+
"checksum": "abc12345",
|
|
182
|
+
"version": "1.0.0",
|
|
183
|
+
"description": "Generated bundle from ts-res-cli"
|
|
184
|
+
},
|
|
185
|
+
"config": {
|
|
186
|
+
"qualifierTypes": [...],
|
|
187
|
+
"qualifiers": [...],
|
|
188
|
+
"resourceTypes": [...]
|
|
189
|
+
},
|
|
190
|
+
"compiledCollection": {
|
|
191
|
+
"resources": {...}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
148
196
|
### JavaScript
|
|
149
197
|
```javascript
|
|
150
198
|
module.exports = {
|
package/lib/cli.d.ts
CHANGED
package/lib/cli.js
CHANGED
|
@@ -90,7 +90,7 @@ class TsResCliApp {
|
|
|
90
90
|
.option('-c, --context <json>', 'Context filter for resources (JSON string)')
|
|
91
91
|
.option('--context-filter <token>', 'Context filter token (pipe-separated, e.g., "language=en-US|territory=US")')
|
|
92
92
|
.option('--qualifier-defaults <token>', 'Qualifier default values token (pipe-separated, e.g., "language=en-US,en-CA|territory=US")')
|
|
93
|
-
.option('-f, --format <format>', 'Output format', 'compiled')
|
|
93
|
+
.option('-f, --format <format>', 'Output format (compiled, source, js, ts, binary, bundle)', 'compiled')
|
|
94
94
|
.option('--debug', 'Include debug information', false)
|
|
95
95
|
.option('-v, --verbose', 'Verbose output', false)
|
|
96
96
|
.option('-q, --quiet', 'Quiet output', false)
|
|
@@ -142,6 +142,17 @@ 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
|
+
});
|
|
145
156
|
}
|
|
146
157
|
/**
|
|
147
158
|
* Handles the compile command
|
|
@@ -413,13 +424,68 @@ class TsResCliApp {
|
|
|
413
424
|
process.exit(1);
|
|
414
425
|
}
|
|
415
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Handles the archive command
|
|
429
|
+
*/
|
|
430
|
+
async _handleArchiveCommand(options) {
|
|
431
|
+
try {
|
|
432
|
+
// Import ZipArchive dynamically to avoid loading if not needed
|
|
433
|
+
const { ZipArchive } = await Promise.resolve().then(() => __importStar(require('@fgv/ts-res')));
|
|
434
|
+
if (!options.input && !options.config) {
|
|
435
|
+
console.error('Error: At least one of --input or --config must be specified');
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
if (!options.quiet) {
|
|
439
|
+
console.log('Creating ZIP archive...');
|
|
440
|
+
if (options.input)
|
|
441
|
+
console.log(`Input: ${options.input}`);
|
|
442
|
+
if (options.config)
|
|
443
|
+
console.log(`Config: ${options.config}`);
|
|
444
|
+
console.log(`Output: ${options.output}`);
|
|
445
|
+
}
|
|
446
|
+
// Create ZIP archive using the new zip-archive packlet
|
|
447
|
+
const creator = new ZipArchive.ZipArchiveCreator();
|
|
448
|
+
const createResult = await creator.createFromBuffer({
|
|
449
|
+
inputPath: options.input,
|
|
450
|
+
configPath: options.config
|
|
451
|
+
}, options.verbose
|
|
452
|
+
? (phase, progress, message) => {
|
|
453
|
+
console.log(`[${phase}] ${progress}% - ${message}`);
|
|
454
|
+
}
|
|
455
|
+
: undefined);
|
|
456
|
+
if (createResult.isFailure()) {
|
|
457
|
+
console.error(`Error: Failed to create ZIP archive: ${createResult.message}`);
|
|
458
|
+
process.exit(1);
|
|
459
|
+
}
|
|
460
|
+
const { zipBuffer, manifest, size } = createResult.value;
|
|
461
|
+
// Write the ZIP buffer to the specified output file
|
|
462
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs'))).then((m) => m.promises);
|
|
463
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
464
|
+
const outputPath = path.resolve(options.output);
|
|
465
|
+
const outputDir = path.dirname(outputPath);
|
|
466
|
+
// Ensure output directory exists
|
|
467
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
468
|
+
// Write ZIP file
|
|
469
|
+
await fs.writeFile(outputPath, zipBuffer);
|
|
470
|
+
if (!options.quiet) {
|
|
471
|
+
console.log(`ZIP archive created successfully: ${outputPath}`);
|
|
472
|
+
console.log(`Archive size: ${(size / 1024).toFixed(2)} KB`);
|
|
473
|
+
console.log(`Manifest:`);
|
|
474
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
479
|
+
process.exit(1);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
416
482
|
/**
|
|
417
483
|
* Parses and validates compile options
|
|
418
484
|
*/
|
|
419
485
|
_parseCompileOptions(options) {
|
|
420
486
|
try {
|
|
421
487
|
const format = options.format;
|
|
422
|
-
if (!['compiled', 'source', 'js', 'ts', 'binary'].includes(format)) {
|
|
488
|
+
if (!['compiled', 'source', 'js', 'ts', 'binary', 'bundle'].includes(format)) {
|
|
423
489
|
return (0, ts_utils_1.fail)(`Invalid format: ${format}`);
|
|
424
490
|
}
|
|
425
491
|
// Convert JSON context to contextFilter if provided
|
package/lib/compiler.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface IFilteredManager {
|
|
|
25
25
|
export interface IResourceBlob {
|
|
26
26
|
resources?: TsRes.ResourceJson.Json.IResourceCollectionDecl;
|
|
27
27
|
compiledCollection?: TsRes.ResourceJson.Compiled.ICompiledResourceCollection;
|
|
28
|
+
bundle?: TsRes.Bundle.IBundle;
|
|
28
29
|
metadata?: IResourceInfo;
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
@@ -74,6 +75,10 @@ export declare class ResourceCompiler {
|
|
|
74
75
|
* Generates a source format blob (legacy format)
|
|
75
76
|
*/
|
|
76
77
|
private _generateSourceBlob;
|
|
78
|
+
/**
|
|
79
|
+
* Generates a bundle blob
|
|
80
|
+
*/
|
|
81
|
+
private _generateBundleBlob;
|
|
77
82
|
/**
|
|
78
83
|
* Generates resource information
|
|
79
84
|
*/
|
package/lib/compiler.js
CHANGED
|
@@ -319,6 +319,9 @@ class ResourceCompiler {
|
|
|
319
319
|
if (this._options.format === 'compiled') {
|
|
320
320
|
return this._generateCompiledBlob(filtered);
|
|
321
321
|
}
|
|
322
|
+
else if (this._options.format === 'bundle') {
|
|
323
|
+
return this._generateBundleBlob(filtered);
|
|
324
|
+
}
|
|
322
325
|
else {
|
|
323
326
|
return this._generateSourceBlob(filtered);
|
|
324
327
|
}
|
|
@@ -354,6 +357,32 @@ class ResourceCompiler {
|
|
|
354
357
|
return (0, ts_utils_1.succeed)(blob);
|
|
355
358
|
});
|
|
356
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Generates a bundle blob
|
|
362
|
+
*/
|
|
363
|
+
_generateBundleBlob(filtered) {
|
|
364
|
+
if (!this._systemConfiguration) {
|
|
365
|
+
return (0, ts_utils_1.fail)('System configuration is required for bundle generation');
|
|
366
|
+
}
|
|
367
|
+
// Create SystemConfiguration from the loaded configuration
|
|
368
|
+
return TsRes.Config.SystemConfiguration.create(this._systemConfiguration).onSuccess((systemConfig) => {
|
|
369
|
+
// Create bundle using BundleBuilder
|
|
370
|
+
const bundleParams = {
|
|
371
|
+
version: '1.0.0',
|
|
372
|
+
description: 'Generated bundle from ts-res-cli',
|
|
373
|
+
normalize: true // Use order-resilient normalization for consistent output
|
|
374
|
+
};
|
|
375
|
+
return TsRes.Bundle.BundleBuilder.create(filtered.manager, systemConfig, bundleParams).onSuccess((bundle) => {
|
|
376
|
+
const blob = {
|
|
377
|
+
bundle
|
|
378
|
+
};
|
|
379
|
+
if (this._options.includeMetadata) {
|
|
380
|
+
blob.metadata = this._generateResourceInfo(filtered);
|
|
381
|
+
}
|
|
382
|
+
return (0, ts_utils_1.succeed)(blob);
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
}
|
|
357
386
|
/**
|
|
358
387
|
* Generates resource information
|
|
359
388
|
*/
|
|
@@ -400,6 +429,11 @@ class ResourceCompiler {
|
|
|
400
429
|
const binaryData = blob.compiledCollection || blob;
|
|
401
430
|
content = JSON.stringify(binaryData);
|
|
402
431
|
break;
|
|
432
|
+
case 'bundle':
|
|
433
|
+
// Bundle format outputs the complete bundle with metadata, config, and compiled resources
|
|
434
|
+
const bundleData = this._options.includeMetadata ? blob : blob.bundle;
|
|
435
|
+
content = JSON.stringify(bundleData, null, 2);
|
|
436
|
+
break;
|
|
403
437
|
default:
|
|
404
438
|
return (0, ts_utils_1.fail)(`Unsupported output format: ${this._options.format}`);
|
|
405
439
|
}
|
package/lib/options.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Output format options for resource compilation
|
|
3
3
|
*/
|
|
4
|
-
export type OutputFormat = 'compiled' | 'source' | 'js' | 'ts' | 'binary';
|
|
4
|
+
export type OutputFormat = 'compiled' | 'source' | 'js' | 'ts' | 'binary' | 'bundle';
|
|
5
5
|
/**
|
|
6
6
|
* Options for resource compilation
|
|
7
7
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-res-cli",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-20",
|
|
4
4
|
"description": "Command-line interface for ts-res resource compilation and management",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"commander": "^11.0.0",
|
|
21
|
-
"@fgv/ts-res": "5.0.0-
|
|
22
|
-
"@fgv/ts-utils": "5.0.0-
|
|
23
|
-
"@fgv/ts-json": "5.0.0-
|
|
24
|
-
"@fgv/ts-extras": "5.0.0-
|
|
25
|
-
"@fgv/ts-json-base": "5.0.0-
|
|
21
|
+
"@fgv/ts-res": "5.0.0-20",
|
|
22
|
+
"@fgv/ts-utils": "5.0.0-20",
|
|
23
|
+
"@fgv/ts-json": "5.0.0-20",
|
|
24
|
+
"@fgv/ts-extras": "5.0.0-20",
|
|
25
|
+
"@fgv/ts-json-base": "5.0.0-20"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@rushstack/heft": "~0.74.
|
|
29
|
-
"@rushstack/heft-node-rig": "~2.9.
|
|
28
|
+
"@rushstack/heft": "~0.74.2",
|
|
29
|
+
"@rushstack/heft-node-rig": "~2.9.3",
|
|
30
30
|
"@rushstack/eslint-config": "~4.4.0",
|
|
31
31
|
"@types/heft-jest": "1.0.6",
|
|
32
32
|
"@types/jest": "^29.5.14",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"@typescript-eslint/parser": "^7.14.1",
|
|
36
36
|
"eslint": "^8.57.0",
|
|
37
37
|
"jest": "^29.7.0",
|
|
38
|
-
"ts-jest": "^29.4.
|
|
39
|
-
"typescript": "^5.
|
|
40
|
-
"@fgv/ts-utils-jest": "5.0.0-
|
|
38
|
+
"ts-jest": "^29.4.1",
|
|
39
|
+
"typescript": "^5.8.3",
|
|
40
|
+
"@fgv/ts-utils-jest": "5.0.0-20"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"typescript": "^5.7.3"
|
package/src/cli.ts
CHANGED
|
@@ -86,6 +86,17 @@ interface IConfigCommandOptions {
|
|
|
86
86
|
list?: boolean;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Command-line options for the archive command
|
|
91
|
+
*/
|
|
92
|
+
interface IArchiveCommandOptions {
|
|
93
|
+
input?: string;
|
|
94
|
+
config?: string;
|
|
95
|
+
output: string;
|
|
96
|
+
verbose?: boolean;
|
|
97
|
+
quiet?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
89
100
|
import { ResourceCompiler } from './compiler';
|
|
90
101
|
|
|
91
102
|
/**
|
|
@@ -133,7 +144,7 @@ export class TsResCliApp {
|
|
|
133
144
|
'--qualifier-defaults <token>',
|
|
134
145
|
'Qualifier default values token (pipe-separated, e.g., "language=en-US,en-CA|territory=US")'
|
|
135
146
|
)
|
|
136
|
-
.option('-f, --format <format>', 'Output format', 'compiled')
|
|
147
|
+
.option('-f, --format <format>', 'Output format (compiled, source, js, ts, binary, bundle)', 'compiled')
|
|
137
148
|
.option('--debug', 'Include debug information', false)
|
|
138
149
|
.option('-v, --verbose', 'Verbose output', false)
|
|
139
150
|
.option('-q, --quiet', 'Quiet output', false)
|
|
@@ -221,6 +232,18 @@ export class TsResCliApp {
|
|
|
221
232
|
.action(async (options) => {
|
|
222
233
|
await this._handleConfigCommand(options);
|
|
223
234
|
});
|
|
235
|
+
|
|
236
|
+
this._program
|
|
237
|
+
.command('archive')
|
|
238
|
+
.description('Create ZIP archive of resources and configuration')
|
|
239
|
+
.option('-i, --input <path>', 'Input file or directory path')
|
|
240
|
+
.option('--config <path>', 'Configuration file path')
|
|
241
|
+
.requiredOption('-o, --output <path>', 'Output ZIP file path')
|
|
242
|
+
.option('-v, --verbose', 'Verbose output', false)
|
|
243
|
+
.option('-q, --quiet', 'Quiet output', false)
|
|
244
|
+
.action(async (options) => {
|
|
245
|
+
await this._handleArchiveCommand(options);
|
|
246
|
+
});
|
|
224
247
|
}
|
|
225
248
|
|
|
226
249
|
/**
|
|
@@ -557,13 +580,78 @@ export class TsResCliApp {
|
|
|
557
580
|
}
|
|
558
581
|
}
|
|
559
582
|
|
|
583
|
+
/**
|
|
584
|
+
* Handles the archive command
|
|
585
|
+
*/
|
|
586
|
+
private async _handleArchiveCommand(options: IArchiveCommandOptions): Promise<void> {
|
|
587
|
+
try {
|
|
588
|
+
// Import ZipArchive dynamically to avoid loading if not needed
|
|
589
|
+
const { ZipArchive } = await import('@fgv/ts-res');
|
|
590
|
+
|
|
591
|
+
if (!options.input && !options.config) {
|
|
592
|
+
console.error('Error: At least one of --input or --config must be specified');
|
|
593
|
+
process.exit(1);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (!options.quiet) {
|
|
597
|
+
console.log('Creating ZIP archive...');
|
|
598
|
+
if (options.input) console.log(`Input: ${options.input}`);
|
|
599
|
+
if (options.config) console.log(`Config: ${options.config}`);
|
|
600
|
+
console.log(`Output: ${options.output}`);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Create ZIP archive using the new zip-archive packlet
|
|
604
|
+
const creator = new ZipArchive.ZipArchiveCreator();
|
|
605
|
+
const createResult = await creator.createFromBuffer(
|
|
606
|
+
{
|
|
607
|
+
inputPath: options.input,
|
|
608
|
+
configPath: options.config
|
|
609
|
+
},
|
|
610
|
+
options.verbose
|
|
611
|
+
? (phase, progress, message) => {
|
|
612
|
+
console.log(`[${phase}] ${progress}% - ${message}`);
|
|
613
|
+
}
|
|
614
|
+
: undefined
|
|
615
|
+
);
|
|
616
|
+
|
|
617
|
+
if (createResult.isFailure()) {
|
|
618
|
+
console.error(`Error: Failed to create ZIP archive: ${createResult.message}`);
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const { zipBuffer, manifest, size } = createResult.value;
|
|
623
|
+
|
|
624
|
+
// Write the ZIP buffer to the specified output file
|
|
625
|
+
const fs = await import('fs').then((m) => m.promises);
|
|
626
|
+
const path = await import('path');
|
|
627
|
+
const outputPath = path.resolve(options.output);
|
|
628
|
+
const outputDir = path.dirname(outputPath);
|
|
629
|
+
|
|
630
|
+
// Ensure output directory exists
|
|
631
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
632
|
+
|
|
633
|
+
// Write ZIP file
|
|
634
|
+
await fs.writeFile(outputPath, zipBuffer);
|
|
635
|
+
|
|
636
|
+
if (!options.quiet) {
|
|
637
|
+
console.log(`ZIP archive created successfully: ${outputPath}`);
|
|
638
|
+
console.log(`Archive size: ${(size / 1024).toFixed(2)} KB`);
|
|
639
|
+
console.log(`Manifest:`);
|
|
640
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
641
|
+
}
|
|
642
|
+
} catch (error) {
|
|
643
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
644
|
+
process.exit(1);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
560
648
|
/**
|
|
561
649
|
* Parses and validates compile options
|
|
562
650
|
*/
|
|
563
651
|
private _parseCompileOptions(options: ICompileCommandOptions): Result<ICompileOptions> {
|
|
564
652
|
try {
|
|
565
653
|
const format = options.format as OutputFormat;
|
|
566
|
-
if (!['compiled', 'source', 'js', 'ts', 'binary'].includes(format)) {
|
|
654
|
+
if (!['compiled', 'source', 'js', 'ts', 'binary', 'bundle'].includes(format)) {
|
|
567
655
|
return fail(`Invalid format: ${format}`);
|
|
568
656
|
}
|
|
569
657
|
|
package/src/compiler.ts
CHANGED
|
@@ -53,6 +53,7 @@ export interface IFilteredManager {
|
|
|
53
53
|
export interface IResourceBlob {
|
|
54
54
|
resources?: TsRes.ResourceJson.Json.IResourceCollectionDecl;
|
|
55
55
|
compiledCollection?: TsRes.ResourceJson.Compiled.ICompiledResourceCollection;
|
|
56
|
+
bundle?: TsRes.Bundle.IBundle;
|
|
56
57
|
metadata?: IResourceInfo;
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -387,6 +388,8 @@ export class ResourceCompiler {
|
|
|
387
388
|
try {
|
|
388
389
|
if (this._options.format === 'compiled') {
|
|
389
390
|
return this._generateCompiledBlob(filtered);
|
|
391
|
+
} else if (this._options.format === 'bundle') {
|
|
392
|
+
return this._generateBundleBlob(filtered);
|
|
390
393
|
} else {
|
|
391
394
|
return this._generateSourceBlob(filtered);
|
|
392
395
|
}
|
|
@@ -427,6 +430,39 @@ export class ResourceCompiler {
|
|
|
427
430
|
});
|
|
428
431
|
}
|
|
429
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Generates a bundle blob
|
|
435
|
+
*/
|
|
436
|
+
private _generateBundleBlob(filtered: IFilteredManager): Result<IResourceBlob> {
|
|
437
|
+
if (!this._systemConfiguration) {
|
|
438
|
+
return fail('System configuration is required for bundle generation');
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Create SystemConfiguration from the loaded configuration
|
|
442
|
+
return TsRes.Config.SystemConfiguration.create(this._systemConfiguration).onSuccess((systemConfig) => {
|
|
443
|
+
// Create bundle using BundleBuilder
|
|
444
|
+
const bundleParams: TsRes.Bundle.IBundleCreateParams = {
|
|
445
|
+
version: '1.0.0',
|
|
446
|
+
description: 'Generated bundle from ts-res-cli',
|
|
447
|
+
normalize: true // Use order-resilient normalization for consistent output
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
return TsRes.Bundle.BundleBuilder.create(filtered.manager, systemConfig, bundleParams).onSuccess(
|
|
451
|
+
(bundle) => {
|
|
452
|
+
const blob: IResourceBlob = {
|
|
453
|
+
bundle
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
if (this._options.includeMetadata) {
|
|
457
|
+
blob.metadata = this._generateResourceInfo(filtered);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return succeed(blob);
|
|
461
|
+
}
|
|
462
|
+
);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
430
466
|
/**
|
|
431
467
|
* Generates resource information
|
|
432
468
|
*/
|
|
@@ -491,6 +527,11 @@ export class ResourceCompiler {
|
|
|
491
527
|
const binaryData = blob.compiledCollection || blob;
|
|
492
528
|
content = JSON.stringify(binaryData);
|
|
493
529
|
break;
|
|
530
|
+
case 'bundle':
|
|
531
|
+
// Bundle format outputs the complete bundle with metadata, config, and compiled resources
|
|
532
|
+
const bundleData = this._options.includeMetadata ? blob : blob.bundle;
|
|
533
|
+
content = JSON.stringify(bundleData, null, 2);
|
|
534
|
+
break;
|
|
494
535
|
default:
|
|
495
536
|
return fail(`Unsupported output format: ${this._options.format}`);
|
|
496
537
|
}
|
package/src/options.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
/**
|
|
24
24
|
* Output format options for resource compilation
|
|
25
25
|
*/
|
|
26
|
-
export type OutputFormat = 'compiled' | 'source' | 'js' | 'ts' | 'binary';
|
|
26
|
+
export type OutputFormat = 'compiled' | 'source' | 'js' | 'ts' | 'binary' | 'bundle';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Options for resource compilation
|
package/.eslintrc.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// This is a workaround for https://github.com/eslint/eslint/issues/3458
|
|
2
|
-
require('@rushstack/eslint-config/patch/modern-module-resolution');
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
extends: ['@rushstack/eslint-config/profile/node'],
|
|
6
|
-
parserOptions: {
|
|
7
|
-
tsconfigRootDir: __dirname
|
|
8
|
-
}
|
|
9
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{"kind":"O","text":"Invoking: heft build --clean \n"}
|
|
2
|
-
{"kind":"O","text":" ---- build started ---- \n"}
|
|
3
|
-
{"kind":"O","text":"[build:typescript] Using TypeScript version 5.8.3\n"}
|
|
4
|
-
{"kind":"O","text":"[build:lint] Using ESLint version 8.57.0\n"}
|
|
5
|
-
{"kind":"O","text":" ---- build finished (7.653s) ---- \n"}
|
|
6
|
-
{"kind":"O","text":"-------------------- Finished (7.657s) --------------------\n"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{"kind":"O","text":"Invoking: heft build --clean \n"}
|
|
2
|
-
{"kind":"O","text":" ---- build started ---- \n"}
|
|
3
|
-
{"kind":"O","text":"[build:typescript] Using TypeScript version 5.8.3\n"}
|
|
4
|
-
{"kind":"O","text":"[build:lint] Using ESLint version 8.57.0\n"}
|
|
5
|
-
{"kind":"O","text":" ---- build finished (7.653s) ---- \n"}
|
|
6
|
-
{"kind":"O","text":"-------------------- Finished (7.657s) --------------------\n"}
|