@cogeotiff/cli 7.2.0 → 8.0.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +7 -490
  2. package/README.md +26 -34
  3. package/bin/cogeotiff.js +1 -2
  4. package/build/action.util.d.ts +2 -8
  5. package/build/action.util.js +7 -18
  6. package/build/action.util.js.map +1 -0
  7. package/build/bin.d.ts +1 -0
  8. package/build/bin.js +13 -0
  9. package/build/bin.js.map +1 -0
  10. package/build/cli.table.d.ts +0 -1
  11. package/build/cli.table.js +9 -4
  12. package/build/cli.table.js.map +1 -0
  13. package/build/commands/dump.d.ts +27 -0
  14. package/build/commands/dump.js +132 -0
  15. package/build/commands/dump.js.map +1 -0
  16. package/build/commands/info.d.ts +19 -0
  17. package/build/commands/info.js +185 -0
  18. package/build/commands/info.js.map +1 -0
  19. package/build/common.d.ts +16 -0
  20. package/build/common.js +19 -0
  21. package/build/common.js.map +1 -0
  22. package/build/fs.d.ts +6 -0
  23. package/build/fs.js +17 -0
  24. package/build/fs.js.map +1 -0
  25. package/build/index.d.ts +57 -2
  26. package/build/index.js +11 -8
  27. package/build/index.js.map +1 -0
  28. package/build/log.d.ts +11 -0
  29. package/build/log.js +37 -0
  30. package/build/log.js.map +1 -0
  31. package/build/util.bytes.d.ts +0 -1
  32. package/build/util.bytes.js +1 -1
  33. package/build/util.bytes.js.map +1 -0
  34. package/build/util.tile.d.ts +2 -3
  35. package/build/util.tile.js +20 -18
  36. package/build/util.tile.js.map +1 -0
  37. package/package.json +37 -37
  38. package/src/action.util.ts +22 -37
  39. package/src/bin.ts +14 -0
  40. package/src/cli.table.ts +27 -27
  41. package/src/commands/dump.ts +156 -0
  42. package/src/commands/info.ts +199 -0
  43. package/src/common.ts +20 -0
  44. package/src/fs.ts +18 -0
  45. package/src/index.ts +10 -7
  46. package/src/log.ts +43 -0
  47. package/src/util.bytes.ts +6 -6
  48. package/src/util.tile.ts +33 -33
  49. package/tsconfig.json +8 -10
  50. package/build/action.dump.tile.d.ts +0 -24
  51. package/build/action.dump.tile.d.ts.map +0 -1
  52. package/build/action.dump.tile.js +0 -194
  53. package/build/action.info.d.ts +0 -10
  54. package/build/action.info.d.ts.map +0 -1
  55. package/build/action.info.js +0 -183
  56. package/build/action.tile.d.ts +0 -9
  57. package/build/action.tile.d.ts.map +0 -1
  58. package/build/action.tile.js +0 -64
  59. package/build/action.util.d.ts.map +0 -1
  60. package/build/cli.cog.info.d.ts +0 -9
  61. package/build/cli.cog.info.d.ts.map +0 -1
  62. package/build/cli.cog.info.js +0 -42
  63. package/build/cli.log.d.ts +0 -3
  64. package/build/cli.log.d.ts.map +0 -1
  65. package/build/cli.log.js +0 -4
  66. package/build/cli.table.d.ts.map +0 -1
  67. package/build/index.d.ts.map +0 -1
  68. package/build/util.bytes.d.ts.map +0 -1
  69. package/build/util.tile.d.ts.map +0 -1
  70. package/src/action.dump.tile.ts +0 -240
  71. package/src/action.info.ts +0 -205
  72. package/src/action.tile.ts +0 -76
  73. package/src/cli.cog.info.ts +0 -45
  74. package/src/cli.log.ts +0 -4
@@ -0,0 +1,199 @@
1
+ import { fsa } from '@chunkd/fs';
2
+ import { CogTiff, TiffTag, TiffTagGeo, TiffTagId, TiffTagValueType, TiffVersion, toHex } from '@cogeotiff/core';
3
+ import { CogTiffImage } from '@cogeotiff/core/src/cog.tiff.image.js';
4
+ import c from 'ansi-colors';
5
+ import { command, flag, option, optional, restPositionals } from 'cmd-ts';
6
+ import { ActionUtil, CliResultMap } from '../action.util.js';
7
+ import { CliTable } from '../cli.table.js';
8
+ import { DefaultArgs, Url } from '../common.js';
9
+ import { FetchLog } from '../fs.js';
10
+ import { ensureS3fs, setupLogger } from '../log.js';
11
+ import { toByteSizeString } from '../util.bytes.js';
12
+
13
+ function round(num: number): number {
14
+ const opt = 10 ** 4;
15
+ return Math.floor(num * opt) / opt;
16
+ }
17
+
18
+ export const commandInfo = command({
19
+ name: 'info',
20
+ args: {
21
+ ...DefaultArgs,
22
+ path: option({ short: 'f', long: 'file', type: optional(Url) }),
23
+ tags: flag({ short: 't', long: 'tags', description: 'Dump tiff Tags' }),
24
+ offsets: flag({ short: 'o', long: 'offsets', description: 'Load byte offsets too' }),
25
+ paths: restPositionals({ type: Url, description: 'Files to process' }),
26
+ },
27
+ async handler(args) {
28
+ const logger = setupLogger(args);
29
+ const paths = [...args.paths, args.path].filter((f) => f != null) as URL[];
30
+
31
+ for (const path of paths) {
32
+ if (path.protocol === 's3:') await ensureS3fs();
33
+ logger.debug('Tiff:load', { path: path?.href });
34
+ FetchLog.reset();
35
+
36
+ const source = fsa.source(path);
37
+ const tiff = await new CogTiff(source).init();
38
+
39
+ const header = [
40
+ { key: 'Tiff type', value: `${TiffVersion[tiff.version]} (v${String(tiff.version)})` },
41
+ {
42
+ key: 'Bytes read',
43
+ value: `${toByteSizeString(FetchLog.bytesRead)} (${FetchLog.fetches.length} Chunk${
44
+ FetchLog.fetches.length === 1 ? '' : 's'
45
+ })`,
46
+ },
47
+ ];
48
+
49
+ const firstImage = tiff.images[0];
50
+ const isGeoLocated = firstImage.isGeoLocated;
51
+ const images = [
52
+ { key: 'Compression', value: firstImage.compression },
53
+ isGeoLocated ? { key: 'Origin', value: firstImage.origin.map(round).join(', ') } : null,
54
+ isGeoLocated ? { key: 'Resolution', value: firstImage.resolution.map(round).join(', ') } : null,
55
+ isGeoLocated ? { key: 'BoundingBox', value: firstImage.bbox.map(round).join(', ') } : null,
56
+ firstImage.epsg ? { key: 'EPSG', value: `EPSG:${firstImage.epsg} (https://epsg.io/${firstImage.epsg})` } : null,
57
+ { key: 'Images', value: '\n' + TiffImageInfoTable.print(tiff.images, '\t').join('\n') },
58
+ ];
59
+
60
+ const ghostOptions = [...(tiff.options?.options.entries() ?? [])];
61
+ const gdalMetadata = parseGdalMetadata(firstImage);
62
+ const gdal = [
63
+ {
64
+ key: 'COG optimized',
65
+ value: String(tiff.options?.isCogOptimized),
66
+ enabled: tiff.options?.isCogOptimized === true,
67
+ },
68
+ { key: 'COG broken', value: String(tiff.options?.isBroken), enabled: tiff.options?.isBroken === true },
69
+ {
70
+ key: 'Ghost Options',
71
+ value: '\n' + ghostOptions.map((c) => `\t\t${c[0]} = ${c[1]}`).join('\n'),
72
+ enabled: ghostOptions.length > 0,
73
+ },
74
+ {
75
+ key: 'Metadata',
76
+ value: '\n' + gdalMetadata?.map((c) => `\t\t${c}`).join('\n'),
77
+ enabled: gdalMetadata != null,
78
+ },
79
+ ];
80
+
81
+ const result: CliResultMap[] = [
82
+ { keys: header },
83
+ { title: 'Images', keys: images },
84
+ { title: 'GDAL', keys: gdal, enabled: gdal.filter((g) => g.enabled == null || g.enabled).length > 0 },
85
+ ];
86
+ if (args.tags) {
87
+ for (const img of tiff.images) {
88
+ const tiffTags = [...img.tags.values()];
89
+ // Load the first 25 values of offset arrays
90
+ if (args.offsets) {
91
+ for (const tag of tiffTags) {
92
+ if (tag.type !== 'offset') continue;
93
+ // for (let i = 0; i < Math.min(tag.count, 100); i++) tag.getValueAt(i);
94
+ }
95
+ }
96
+
97
+ result.push({
98
+ title: `Image: ${img.id} - Tiff tags`,
99
+ keys: tiffTags.map(formatTag),
100
+ });
101
+ await img.loadGeoTiffTags();
102
+ if (img.tagsGeo.size > 0) {
103
+ const tiffTagsGeo = [...img.tagsGeo.entries()];
104
+ const keys = tiffTagsGeo.map(([key, value]) => formatGeoTag(key, value));
105
+ if (keys.length > 0) {
106
+ result.push({ title: `Image: ${img.id} - Geo Tiff tags`, keys });
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ const msg = ActionUtil.formatResult(`\n${c.bold('COG File Info')} - ${c.bold(path.href)}`, result);
113
+ console.log(msg.join('\n'));
114
+
115
+ await source.close?.();
116
+ }
117
+ },
118
+ });
119
+
120
+ const TiffImageInfoTable = new CliTable<CogTiffImage>();
121
+ TiffImageInfoTable.add({ name: 'Id', width: 4, get: (_i, index) => String(index) });
122
+ TiffImageInfoTable.add({ name: 'Size', width: 20, get: (i) => `${i.size.width}x${i.size.height}` });
123
+ TiffImageInfoTable.add({
124
+ name: 'Tile Size',
125
+ width: 20,
126
+ get: (i) => `${i.tileSize.width}x${i.tileSize.height}`,
127
+ enabled: (i) => i.isTiled(),
128
+ });
129
+ TiffImageInfoTable.add({
130
+ name: 'Tile Count',
131
+ width: 20,
132
+ get: (i) => `${i.tileCount.x}x${i.tileCount.y} (${i.tileCount.x * i.tileCount.y})`,
133
+ enabled: (i) => i.isTiled(),
134
+ });
135
+ TiffImageInfoTable.add({
136
+ name: 'Strip Count',
137
+ width: 20,
138
+ get: (i) => `${i.tags.get(TiffTagId.StripOffsets)?.count}`,
139
+ enabled: (i) => !i.isTiled(),
140
+ });
141
+ TiffImageInfoTable.add({
142
+ name: 'Resolution',
143
+ width: 20,
144
+ get: (i) => `${round(i.resolution[0])}`,
145
+ enabled: (i) => i.isGeoLocated,
146
+ });
147
+
148
+ // Show compression only if it varies between images
149
+ TiffImageInfoTable.add({
150
+ name: 'Compression',
151
+ width: 20,
152
+ get: (i) => i.compression,
153
+ enabled: (i) => {
154
+ const formats = new Set();
155
+ i.tiff.images.forEach((f) => formats.add(f.compression));
156
+ return formats.size > 1;
157
+ },
158
+ });
159
+
160
+ /**
161
+ * Parse out the GDAL Metadata to be more friendly to read
162
+ *
163
+ * TODO using a XML Parser will make this even better
164
+ * @param img
165
+ */
166
+ function parseGdalMetadata(img: CogTiffImage): string[] | null {
167
+ const metadata = img.value(TiffTagId.GdalMetadata);
168
+ if (typeof metadata !== 'string') return null;
169
+ if (!metadata.startsWith('<GDALMetadata>')) return null;
170
+ return metadata
171
+ .replace('<GDALMetadata>\n', '')
172
+ .replace('</GDALMetadata>\n', '')
173
+ .replace('\n\x00', '')
174
+ .split('\n')
175
+ .map((c) => c.trim());
176
+ }
177
+
178
+ function formatTag(tag: TiffTag): { key: string; value: string } {
179
+ const tagName = TiffTagId[tag.id];
180
+ const tagDebug = `(${TiffTagValueType[tag.dataType]}${tag.count > 1 ? ' x' + tag.count : ''}`;
181
+ const key = `${c.dim(toHex(tag.id)).padEnd(7, ' ')} ${String(tagName)} ${c.dim(tagDebug)})`.padEnd(50, ' ');
182
+
183
+ if (Array.isArray(tag.value)) return { key, value: JSON.stringify(tag.value.slice(0, 250)) };
184
+
185
+ let tagString = JSON.stringify(tag.value) ?? c.dim('null');
186
+ if (tagString.length > 256) tagString = tagString.slice(0, 250) + '...';
187
+ return { key, value: tagString };
188
+ }
189
+
190
+ function formatGeoTag(tagId: TiffTagGeo, value: string | number): { key: string; value: string } {
191
+ const tagName = TiffTagGeo[tagId];
192
+ const key = `${c.dim(toHex(tagId)).padEnd(7, ' ')} ${String(tagName).padEnd(30)}`;
193
+
194
+ if (Array.isArray(value)) return { key, value: JSON.stringify(value.slice(0, 250)) };
195
+
196
+ let tagString = JSON.stringify(value) ?? c.dim('null');
197
+ if (tagString.length > 256) tagString = tagString.slice(0, 250) + '...';
198
+ return { key, value: tagString };
199
+ }
package/src/common.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { Type, flag } from 'cmd-ts';
2
+ import { pathToFileURL } from 'url';
3
+
4
+ export const verbose = flag({ long: 'verbose', description: 'Verbose logging', short: 'v' });
5
+ export const extraVerbose = flag({ long: 'extra-verbose', description: 'Extra verbose logging', short: 'V' });
6
+
7
+ export const DefaultArgs = {
8
+ verbose,
9
+ extraVerbose,
10
+ };
11
+
12
+ export const Url: Type<string, URL> = {
13
+ async from(s: string): Promise<URL> {
14
+ try {
15
+ return new URL(s);
16
+ } catch (e) {
17
+ return pathToFileURL(s);
18
+ }
19
+ },
20
+ };
package/src/fs.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { SourceCallback, SourceMiddleware, SourceRequest } from '@chunkd/source';
2
+ import { logger } from './log.js';
3
+
4
+ export const FetchLog: SourceMiddleware & { reset(): void; fetches: SourceRequest[]; bytesRead: number } = {
5
+ name: 'source:log',
6
+ fetch(req: SourceRequest, next: SourceCallback) {
7
+ this.fetches.push(req);
8
+ this.bytesRead += req.length ?? 0;
9
+ logger.info('Tiff:fetch', { href: req.source.url.href, offset: req.offset, length: req.length });
10
+ return next(req);
11
+ },
12
+ reset() {
13
+ this.fetches = [];
14
+ this.bytesRead = 0;
15
+ },
16
+ fetches: [],
17
+ bytesRead: 0,
18
+ };
package/src/index.ts CHANGED
@@ -1,9 +1,12 @@
1
- import 'source-map-support/register.js';
2
- import { CogInfoCommandLine } from './cli.cog.info.js';
3
- import { logger } from './cli.log.js';
1
+ import { subcommands } from 'cmd-ts';
2
+ import { commandInfo } from './commands/info.js';
3
+ import { commandDump } from './commands/dump.js';
4
4
 
5
- const cogInfo: CogInfoCommandLine = new CogInfoCommandLine();
6
- cogInfo.executeWithoutErrorHandling().catch((error) => {
7
- logger.fatal({ error }, 'Failed to run');
8
- process.exit(1);
5
+ export const cmd = subcommands({
6
+ name: 'cogeotiff',
7
+ description: 'COG utilities',
8
+ cmds: {
9
+ info: commandInfo,
10
+ dump: commandDump,
11
+ },
9
12
  });
package/src/log.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { FsHttp, fsa } from '@chunkd/fs';
2
+ import { SourceCache, SourceChunk } from '@chunkd/middleware';
3
+ import { log } from '@linzjs/tracing';
4
+ import { FetchLog } from './fs.js';
5
+
6
+ // Cache the last 10MB of chunks for reuse
7
+ export const sourceCache = new SourceCache({ size: 10 * 1024 * 1024 });
8
+ export const sourceChunk = new SourceChunk({ size: 32 * 1024 });
9
+
10
+ export function setupLogger(cfg: { verbose?: boolean; extraVerbose?: boolean }): typeof log {
11
+ if (cfg.verbose) {
12
+ log.level = 'debug';
13
+ } else if (cfg.extraVerbose) {
14
+ log.level = 'trace';
15
+ } else {
16
+ log.level = 'warn';
17
+ }
18
+
19
+ fsa.register('http://', new FsHttp());
20
+ fsa.register('https://', new FsHttp());
21
+
22
+ // Order of these are really important
23
+ // Chunk all requests into 32KB chunks
24
+ fsa.middleware.push(sourceChunk);
25
+ // Cache the last 10MB of chunks for reuse
26
+ fsa.middleware.push(sourceCache);
27
+
28
+ fsa.middleware.push(FetchLog);
29
+
30
+ return log;
31
+ }
32
+
33
+ export const logger = log;
34
+
35
+ /** S3 client adds approx 300ms to the cli startup time, so only register it if needed */
36
+ export async function ensureS3fs(): Promise<void> {
37
+ if (fsa.systems.find((f) => f.prefix.startsWith('s3'))) return;
38
+
39
+ const S3Client = await import('@aws-sdk/client-s3');
40
+ const FsAwsS3 = await import('@chunkd/fs-aws');
41
+
42
+ fsa.register('s3://', new FsAwsS3.FsAwsS3(new S3Client.S3Client({})));
43
+ }
package/src/util.bytes.ts CHANGED
@@ -8,11 +8,11 @@ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
8
8
  * @param bytes byte count to convert
9
9
  */
10
10
  export function toByteSizeString(bytes: number): string {
11
- if (bytes === 1) return '1 Byte';
12
- const i = Math.floor(Math.log(bytes) / Math.log(1024));
13
- const output = bytes / Math.pow(1024, i);
14
- const byteSize = sizes[i];
11
+ if (bytes === 1) return '1 Byte';
12
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
13
+ const output = bytes / Math.pow(1024, i);
14
+ const byteSize = sizes[i];
15
15
 
16
- if (i === 1) return `${Math.round(output)} ${byteSize}`;
17
- return `${Math.floor(output * 100) / 100} ${byteSize}`;
16
+ if (i === 1) return `${Math.round(output)} ${byteSize}`;
17
+ return `${Math.floor(output * 100) / 100} ${byteSize}`;
18
18
  }
package/src/util.tile.ts CHANGED
@@ -1,14 +1,18 @@
1
1
  import { CogTiff, TiffMimeType } from '@cogeotiff/core';
2
- import { promises as fs } from 'fs';
3
- import * as path from 'path';
4
- import type pino from 'pino';
2
+ import { log } from '@linzjs/tracing';
3
+ import { promises as fs } from 'node:fs';
5
4
 
6
- const FileExtension: { [key: string]: string } = {
7
- [TiffMimeType.JPEG]: 'jpeg',
8
- [TiffMimeType.JP2]: 'jp2',
9
- [TiffMimeType.WEBP]: 'webp',
10
- [TiffMimeType.LZW]: 'lzw',
11
- [TiffMimeType.DEFLATE]: 'deflate',
5
+ const FileExtension: Record<string, string> = {
6
+ [TiffMimeType.Jpeg]: 'jpeg',
7
+ [TiffMimeType.Jp2]: 'jp2',
8
+ [TiffMimeType.Webp]: 'webp',
9
+ [TiffMimeType.Lzw]: 'lzw',
10
+ [TiffMimeType.Deflate]: 'deflate',
11
+ [TiffMimeType.None]: 'bin',
12
+ [TiffMimeType.JpegXl]: 'jpeg',
13
+ [TiffMimeType.Zstd]: 'zstd',
14
+ [TiffMimeType.Lerc]: 'lerc',
15
+ [TiffMimeType.Lzma]: 'lzma',
12
16
  };
13
17
 
14
18
  /**
@@ -22,31 +26,27 @@ const FileExtension: { [key: string]: string } = {
22
26
  * @returns tile name eg `001_002_12.png`
23
27
  */
24
28
  export function getTileName(mimeType: string, index: number, x: number, y: number): string {
25
- const xS = `${x}`.padStart(3, '0');
26
- const yS = `${y}`.padStart(3, '0');
27
-
28
- const fileExt: string = FileExtension[mimeType];
29
- if (fileExt == null) {
30
- throw new Error(`Unable to process tile type:${mimeType}`);
31
- }
32
-
33
- return `${xS}_${yS}_${index}.${fileExt}`;
29
+ const xS = `${x}`.padStart(3, '0');
30
+ const yS = `${y}`.padStart(3, '0');
31
+ const fileExt = FileExtension[mimeType] ?? 'unknown';
32
+ return `${xS}_${yS}_${index}.${fileExt}`;
34
33
  }
35
34
 
36
35
  export async function writeTile(
37
- tif: CogTiff,
38
- x: number,
39
- y: number,
40
- index: number,
41
- outputPath: string,
42
- logger: pino.Logger,
43
- ): Promise<void> {
44
- const tile = await tif.getTile(x, y, index);
45
- if (tile == null) {
46
- logger.debug({ index, x, y }, 'TileEmpty');
47
- return;
48
- }
49
- const fileName = getTileName(tile.mimeType, index, x, y);
50
- await fs.writeFile(path.join(outputPath, fileName), tile.bytes);
51
- logger.debug({ index, x, y, fileName, bytes: tile.bytes.length }, 'TileWrite');
36
+ tiff: CogTiff,
37
+ x: number,
38
+ y: number,
39
+ index: number,
40
+ outputPath: URL,
41
+ logger: typeof log,
42
+ ): Promise<string | null> {
43
+ const tile = await tiff.images[index].getTile(x, y);
44
+ if (tile == null) {
45
+ logger.debug('Tile:Empty', { source: tiff.source.url.href, index, x, y });
46
+ return null;
47
+ }
48
+ const fileName = getTileName(tile.mimeType, index, x, y);
49
+ await fs.writeFile(new URL(fileName, outputPath), Buffer.from(tile.bytes));
50
+ logger.debug('Tile:Write', { source: tiff.source.url.href, index, x, y, fileName, bytes: tile.bytes.byteLength });
51
+ return fileName;
52
52
  }
package/tsconfig.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "rootDir": "./src",
5
- "outDir": "./build",
6
- "lib": ["es2018", "dom"]
7
- },
8
- "include": ["src/**/*"],
9
- "references": [
10
- { "path": "../core" }
11
- ]
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./build",
6
+ "lib": ["es2018", "dom"]
7
+ },
8
+ "include": ["src"],
9
+ "references": [{ "path": "../core" }]
12
10
  }
@@ -1,24 +0,0 @@
1
- import { CogTiff } from '@cogeotiff/core';
2
- import { CommandLineAction } from '@rushstack/ts-command-line';
3
- export interface GeoJsonPolygon {
4
- type: 'Feature';
5
- geometry: {
6
- type: 'Polygon';
7
- coordinates: [[[number, number], [number, number], [number, number], [number, number], [number, number]]];
8
- };
9
- properties: Record<string, unknown>;
10
- }
11
- export declare class ActionDumpTile extends CommandLineAction {
12
- private file;
13
- private imageIndex;
14
- private output;
15
- private outputCount;
16
- private logger;
17
- constructor();
18
- dumpBounds(tif: CogTiff, output: string, index: number): Promise<void>;
19
- dumpIndex(tif: CogTiff, output: string, index: number): Promise<void>;
20
- dumpTiles(tif: CogTiff, output: string, index: number): Promise<void>;
21
- onExecute(): Promise<void>;
22
- protected onDefineParameters(): void;
23
- }
24
- //# sourceMappingURL=action.dump.tile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"action.dump.tile.d.ts","sourceRoot":"","sources":["../src/action.dump.tile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAA2D,MAAM,4BAA4B,CAAC;AAoBxH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE;QACN,IAAI,EAAE,SAAS,CAAC;QAChB,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KAC7G,CAAC;IACF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAwBD,qBAAa,cAAe,SAAQ,iBAAiB;IACjD,OAAO,CAAC,IAAI,CAA2C;IACvD,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,MAAM,CAAc;;IAYtB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCtE,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BrE,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDhC,SAAS,CAAC,kBAAkB,IAAI,IAAI;CAyBvC"}