@basemaps/cli 6.25.0 → 6.28.0
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.md +45 -0
- package/build/cli/base.cli.d.ts +0 -18
- package/build/cli/base.cli.d.ts.map +1 -1
- package/build/cli/base.cli.js +1 -60
- package/build/cli/cogify/__tests__/batch.job.test.d.ts +2 -0
- package/build/cli/cogify/__tests__/batch.job.test.d.ts.map +1 -0
- package/build/cli/cogify/__tests__/batch.job.test.js +69 -0
- package/build/cli/cogify/{__test__ → __tests__}/semver.test.d.ts +0 -0
- package/build/cli/cogify/__tests__/semver.test.d.ts.map +1 -0
- package/build/cli/cogify/{__test__ → __tests__}/semver.test.js +0 -0
- package/build/cli/cogify/action.cog.d.ts +1 -1
- package/build/cli/cogify/action.cog.d.ts.map +1 -1
- package/build/cli/cogify/action.cog.js +104 -54
- package/build/cli/cogify/action.job.d.ts +1 -0
- package/build/cli/cogify/action.job.d.ts.map +1 -1
- package/build/cli/cogify/action.job.js +11 -4
- package/build/cli/cogify/{action.batch.d.ts → batch.job.d.ts} +11 -13
- package/build/cli/cogify/batch.job.d.ts.map +1 -0
- package/build/cli/cogify/{action.batch.js → batch.job.js} +88 -62
- package/build/cli/cogify/imagery.config.d.ts +13 -0
- package/build/cli/cogify/imagery.config.d.ts.map +1 -0
- package/build/cli/cogify/imagery.config.js +46 -0
- package/build/cli/cogify/index.d.ts +1 -1
- package/build/cli/cogify/index.d.ts.map +1 -1
- package/build/cli/cogify/index.js +1 -3
- package/build/cli/folder.d.ts +2 -0
- package/build/cli/folder.d.ts.map +1 -1
- package/build/cli/folder.js +6 -0
- package/build/cli/util.d.ts +5 -0
- package/build/cli/util.d.ts.map +1 -1
- package/build/cli/util.js +15 -2
- package/build/cog/{__test__ → __tests__}/builder.test.d.ts +0 -0
- package/build/cog/__tests__/builder.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/builder.test.js +0 -0
- package/build/cog/{__test__ → __tests__}/cog.stac.job.test.d.ts +0 -0
- package/build/cog/__tests__/cog.stac.job.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/cog.stac.job.test.js +2 -1
- package/build/cog/{__test__ → __tests__}/cog.test.d.ts +0 -0
- package/build/cog/__tests__/cog.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/cog.test.js +0 -0
- package/build/cog/{__test__ → __tests__}/cog.vrt.test.d.ts +0 -0
- package/build/cog/__tests__/cog.vrt.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/cog.vrt.test.js +1 -1
- package/build/cog/{__test__ → __tests__}/cutline.test.d.ts +0 -0
- package/build/cog/__tests__/cutline.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/cutline.test.js +2 -1
- package/build/cog/{__test__ → __tests__}/projection.loader.test.d.ts +0 -0
- package/build/cog/__tests__/projection.loader.test.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/projection.loader.test.js +0 -0
- package/build/cog/{__test__ → __tests__}/source.tiff.testhelper.d.ts +0 -0
- package/build/cog/__tests__/source.tiff.testhelper.d.ts.map +1 -0
- package/build/cog/{__test__ → __tests__}/source.tiff.testhelper.js +0 -0
- package/build/cog/builder.d.ts +1 -5
- package/build/cog/builder.d.ts.map +1 -1
- package/build/cog/builder.js +4 -28
- package/build/cog/cog.stac.job.d.ts +11 -0
- package/build/cog/cog.stac.job.d.ts.map +1 -1
- package/build/cog/cog.stac.job.js +6 -5
- package/build/cog/constants.d.ts +1 -1
- package/build/cog/constants.d.ts.map +1 -1
- package/build/cog/constants.js +1 -1
- package/build/cog/cutline.d.ts +1 -1
- package/build/cog/cutline.d.ts.map +1 -1
- package/build/cog/cutline.js +2 -2
- package/build/cog/job.factory.d.ts.map +1 -1
- package/build/cog/job.factory.js +8 -9
- package/build/cog/types.d.ts +1 -0
- package/build/cog/types.d.ts.map +1 -1
- package/build/gdal/{__test__ → __tests__}/gdal.progress.test.d.ts +0 -0
- package/build/gdal/__tests__/gdal.progress.test.d.ts.map +1 -0
- package/build/gdal/{__test__ → __tests__}/gdal.progress.test.js +0 -0
- package/build/gdal/{__test__ → __tests__}/gdal.test.d.ts +0 -0
- package/build/gdal/__tests__/gdal.test.d.ts.map +1 -0
- package/build/gdal/{__test__ → __tests__}/gdal.test.js +0 -0
- package/package.json +6 -6
- package/build/cli/cogify/__test__/action.batch.test.d.ts +0 -2
- package/build/cli/cogify/__test__/action.batch.test.d.ts.map +0 -1
- package/build/cli/cogify/__test__/action.batch.test.js +0 -23
- package/build/cli/cogify/__test__/semver.test.d.ts.map +0 -1
- package/build/cli/cogify/action.batch.d.ts.map +0 -1
- package/build/cog/__test__/builder.test.d.ts.map +0 -1
- package/build/cog/__test__/cog.stac.job.test.d.ts.map +0 -1
- package/build/cog/__test__/cog.test.d.ts.map +0 -1
- package/build/cog/__test__/cog.vrt.test.d.ts.map +0 -1
- package/build/cog/__test__/cutline.test.d.ts.map +0 -1
- package/build/cog/__test__/projection.loader.test.d.ts.map +0 -1
- package/build/cog/__test__/source.tiff.testhelper.d.ts.map +0 -1
- package/build/gdal/__test__/gdal.progress.test.d.ts.map +0 -1
- package/build/gdal/__test__/gdal.test.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,51 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [6.28.0](https://github.com/linz/basemaps/compare/v6.27.0...v6.28.0) (2022-06-06)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **server:** bundle basemaps-server cli so its easier to install ([#2218](https://github.com/linz/basemaps/issues/2218)) ([8457b66](https://github.com/linz/basemaps/commit/8457b66be6d0f54decf43b515bb78853cefbc8ed))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [6.27.0](https://github.com/linz/basemaps/compare/v6.26.0...v6.27.0) (2022-05-29)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **cli:** Action Cog get processing Id after read job json. ([#2204](https://github.com/linz/basemaps/issues/2204)) ([e459d2a](https://github.com/linz/basemaps/commit/e459d2a12363ded2a825c4266c79357324d17b97))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* **cli:** allow overriding imagery names ([#2169](https://github.com/linz/basemaps/issues/2169)) ([5c3bdd8](https://github.com/linz/basemaps/commit/5c3bdd89b664dd85df2b48d709653b71bdc348f7))
|
|
28
|
+
* **cli:** Chunk batch job based on the size. ([#2217](https://github.com/linz/basemaps/issues/2217)) ([770430c](https://github.com/linz/basemaps/commit/770430ce388f13f2690fa680e113c4e830df312a))
|
|
29
|
+
* **cli:** Insert imagery and tileset config after cog creation complete ([#2191](https://github.com/linz/basemaps/issues/2191)) ([3ea5efd](https://github.com/linz/basemaps/commit/3ea5efd049b956f882a05c90471d764efb5d39fd))
|
|
30
|
+
* **cli:** Make a sseperate folder for each tiff for group cogs batch job. ([#2213](https://github.com/linz/basemaps/issues/2213)) ([e2aef5e](https://github.com/linz/basemaps/commit/e2aef5e460e059a7f8f59cc143a606255d7d77e0))
|
|
31
|
+
* **cli:** make cogs will update the process job status if exists. ([#2180](https://github.com/linz/basemaps/issues/2180)) ([855ce1c](https://github.com/linz/basemaps/commit/855ce1cb1f7b8bff575be342184e5ac387684f09))
|
|
32
|
+
* **cli:** Pass processingId to action job cli for the batch job. ([#2199](https://github.com/linz/basemaps/issues/2199)) ([f962fe2](https://github.com/linz/basemaps/commit/f962fe21859d44fe6ace79aed4611f3343a0d1bd))
|
|
33
|
+
* **cli:** Upgrade action cog to be able to group small jobs into a single batch job. ([#2210](https://github.com/linz/basemaps/issues/2210)) ([8a7de91](https://github.com/linz/basemaps/commit/8a7de912a3b633bfac631e61b0480f2839ceb2cc))
|
|
34
|
+
* **lambda-cog:** New lambda Cog for import api. ([#2207](https://github.com/linz/basemaps/issues/2207)) ([79f4ae7](https://github.com/linz/basemaps/commit/79f4ae70ea3fc16a37dd575b843a0b60a1365df4))
|
|
35
|
+
* **lambda-tiler:** Add file number limitation to import api. ([#2203](https://github.com/linz/basemaps/issues/2203)) ([4694e29](https://github.com/linz/basemaps/commit/4694e29a4444810391e72b290ec64f8b8541c369))
|
|
36
|
+
* **lambda-tiler:** Increase limit of total file size. ([#2205](https://github.com/linz/basemaps/issues/2205)) ([5246ea0](https://github.com/linz/basemaps/commit/5246ea0879a4bf6b20770fb633d63afac778d54d))
|
|
37
|
+
* **lambda-tiler:** Load MaxImagePixelSize from import api. ([#2206](https://github.com/linz/basemaps/issues/2206)) ([b851934](https://github.com/linz/basemaps/commit/b85193401bc5df2ecb689c3801f62af71696cdf5))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# [6.26.0](https://github.com/linz/basemaps/compare/v6.25.0...v6.26.0) (2022-05-12)
|
|
44
|
+
|
|
45
|
+
**Note:** Version bump only for package @basemaps/cli
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
6
51
|
# [6.25.0](https://github.com/linz/basemaps/compare/v6.24.2...v6.25.0) (2022-05-11)
|
|
7
52
|
|
|
8
53
|
**Note:** Version bump only for package @basemaps/cli
|
package/build/cli/base.cli.d.ts
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { CommandLineParser } from '@rushstack/ts-command-line';
|
|
3
|
-
import 'source-map-support/register.js';
|
|
4
|
-
/** Useful traceability information */
|
|
5
|
-
export declare const CliInfo: {
|
|
6
|
-
package: string;
|
|
7
|
-
version: string;
|
|
8
|
-
hash: string;
|
|
9
|
-
};
|
|
10
|
-
/** Unique Id for this instance of the cli being run */
|
|
11
|
-
export declare const CliId: string;
|
|
12
|
-
export declare abstract class BaseCommandLine extends CommandLineParser {
|
|
13
|
-
verbose: import("@rushstack/ts-command-line").CommandLineFlagParameter;
|
|
14
|
-
extraVerbose: import("@rushstack/ts-command-line").CommandLineFlagParameter;
|
|
15
|
-
protected onExecute(): Promise<void>;
|
|
16
|
-
protected onDefineParameters(): void;
|
|
17
|
-
run(): void;
|
|
18
|
-
}
|
|
19
1
|
//# sourceMappingURL=base.cli.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.cli.d.ts","sourceRoot":"","sources":["../../src/cli/base.cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.cli.d.ts","sourceRoot":"","sources":["../../src/cli/base.cli.ts"],"names":[],"mappings":""}
|
package/build/cli/base.cli.js
CHANGED
|
@@ -1,60 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var _a, _b;
|
|
3
|
-
import { LogConfig, LoggerFatalError } from '@basemaps/shared';
|
|
4
|
-
import { GitTag } from '@basemaps/shared/build/cli/git.tag.js';
|
|
5
|
-
import { CommandLineParser } from '@rushstack/ts-command-line';
|
|
6
|
-
import 'source-map-support/register.js';
|
|
7
|
-
import * as ulid from 'ulid';
|
|
8
|
-
/** Useful traceability information */
|
|
9
|
-
export const CliInfo = {
|
|
10
|
-
// Detect unlinked packages looks for this string since its a package name, slightly work around it
|
|
11
|
-
package: '@' + 'basemaps/cli',
|
|
12
|
-
version: (_a = process.env.GIT_VERSION) !== null && _a !== void 0 ? _a : GitTag().version,
|
|
13
|
-
hash: (_b = process.env.GIT_HASH) !== null && _b !== void 0 ? _b : GitTag().hash,
|
|
14
|
-
};
|
|
15
|
-
/** Unique Id for this instance of the cli being run */
|
|
16
|
-
export const CliId = ulid.ulid();
|
|
17
|
-
export class BaseCommandLine extends CommandLineParser {
|
|
18
|
-
constructor() {
|
|
19
|
-
super(...arguments);
|
|
20
|
-
this.verbose = this.defineFlagParameter({
|
|
21
|
-
parameterLongName: '--verbose',
|
|
22
|
-
parameterShortName: '-v',
|
|
23
|
-
description: 'Show extra logging detail',
|
|
24
|
-
});
|
|
25
|
-
this.extraVerbose = this.defineFlagParameter({
|
|
26
|
-
parameterLongName: '--vv',
|
|
27
|
-
parameterShortName: '-V',
|
|
28
|
-
description: 'Show extra extra logging detail',
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
onExecute() {
|
|
32
|
-
if (this.verbose.value) {
|
|
33
|
-
LogConfig.get().level = 'debug';
|
|
34
|
-
}
|
|
35
|
-
else if (this.extraVerbose.value) {
|
|
36
|
-
LogConfig.get().level = 'trace';
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
LogConfig.get().level = 'info';
|
|
40
|
-
}
|
|
41
|
-
const logger = LogConfig.get().child({ id: CliId });
|
|
42
|
-
logger.info(CliInfo, 'CliStart');
|
|
43
|
-
LogConfig.set(logger);
|
|
44
|
-
return super.onExecute();
|
|
45
|
-
}
|
|
46
|
-
onDefineParameters() {
|
|
47
|
-
// Nothing
|
|
48
|
-
}
|
|
49
|
-
run() {
|
|
50
|
-
this.executeWithoutErrorHandling().catch((err) => {
|
|
51
|
-
if (err instanceof LoggerFatalError) {
|
|
52
|
-
LogConfig.get().fatal(err.obj, err.message);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
LogConfig.get().fatal({ err }, 'Failed to run command');
|
|
56
|
-
}
|
|
57
|
-
process.exit(1);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.job.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/cogify/__tests__/batch.job.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import o from 'ospec';
|
|
2
|
+
import { BatchJob, extractResolutionFromName } from '../batch.job.js';
|
|
3
|
+
o.spec('action.batch', () => {
|
|
4
|
+
o('extractResolutionFromName', () => {
|
|
5
|
+
o(extractResolutionFromName('2013')).equals(-1);
|
|
6
|
+
o(extractResolutionFromName('new_zealand_sentinel_2018-19_10m')).equals(10000);
|
|
7
|
+
o(extractResolutionFromName('abc2017def_1.00m')).equals(1000);
|
|
8
|
+
o(extractResolutionFromName('wellington_urban_2017_0.10m')).equals(100);
|
|
9
|
+
o(extractResolutionFromName('wellington_urban_2017_0-10m')).equals(100);
|
|
10
|
+
o(extractResolutionFromName('wellington_urban_2017_1.00m')).equals(1000);
|
|
11
|
+
o(extractResolutionFromName('wellington_urban_2017_0.025m')).equals(25);
|
|
12
|
+
});
|
|
13
|
+
o('should create valid jobNames', () => {
|
|
14
|
+
const fakeJob = { id: '01FHRPYJ5FV1XAARZAC4T4K6MC', name: 'geographx_nz_texture_shade_2012_8-0m' };
|
|
15
|
+
o(BatchJob.id(fakeJob, ['0'])).equals('01FHRPYJ5FV1XAARZAC4T4K6MC-9af5e139bbb3e502-0');
|
|
16
|
+
fakeJob.name = 'ōtorohanga_urban_2021_0.1m_RGB';
|
|
17
|
+
o(BatchJob.id(fakeJob, ['0'])).equals('01FHRPYJ5FV1XAARZAC4T4K6MC-5294acface81c107-0');
|
|
18
|
+
});
|
|
19
|
+
o('should truncate job names to 128 characters', () => {
|
|
20
|
+
const fakeJob = { id: '01FHRPYJ5FV1XAARZAC4T4K6MC', name: 'geographx_nz_texture_shade_2012_8-0m' };
|
|
21
|
+
o(BatchJob.id(fakeJob, [
|
|
22
|
+
'this is a really long file name',
|
|
23
|
+
'it should over flow 128 characters',
|
|
24
|
+
'so it should be truncated at some point.tiff',
|
|
25
|
+
])).equals('01FHRPYJ5FV1XAARZAC4T4K6MC-9af5e139bbb3e502-it should over flow 128 characters_so it should be truncated at some point.tiff_this');
|
|
26
|
+
});
|
|
27
|
+
o('should prepare valid chunk jobs', async () => {
|
|
28
|
+
const fakeGsd = 0.9;
|
|
29
|
+
const ChunkJobSmall = 4097;
|
|
30
|
+
const ChunkJobMiddle = 8193;
|
|
31
|
+
const ChunkJobLarge = 16385;
|
|
32
|
+
const fakeFiles = [
|
|
33
|
+
{ name: '1-2-0', width: ChunkJobSmall * fakeGsd - 1 },
|
|
34
|
+
{ name: '1-2-1', width: ChunkJobSmall * fakeGsd - 1 },
|
|
35
|
+
{ name: '1-2-2', width: ChunkJobLarge * fakeGsd + 1 },
|
|
36
|
+
{ name: '1-2-3', width: ChunkJobMiddle * fakeGsd - 1 },
|
|
37
|
+
{ name: '1-2-4', width: ChunkJobMiddle * fakeGsd - 1 },
|
|
38
|
+
{ name: '1-2-5', width: ChunkJobLarge * fakeGsd + 0.1 },
|
|
39
|
+
{ name: '1-2-6', width: ChunkJobMiddle * fakeGsd - 1 },
|
|
40
|
+
{ name: '1-2-7', width: ChunkJobLarge * fakeGsd - 1 },
|
|
41
|
+
{ name: '1-2-8', width: ChunkJobLarge * fakeGsd - 1 },
|
|
42
|
+
{ name: '1-2-9', width: ChunkJobLarge * fakeGsd - 1 },
|
|
43
|
+
{ name: '1-2-10', width: ChunkJobLarge * fakeGsd - 1 },
|
|
44
|
+
{ name: '1-2-11', width: ChunkJobLarge * fakeGsd - 1 },
|
|
45
|
+
{ name: '1-2-12', width: ChunkJobSmall * fakeGsd - 1 },
|
|
46
|
+
{ name: '1-2-13', width: ChunkJobLarge * fakeGsd + 1 },
|
|
47
|
+
{ name: '1-2-14', width: ChunkJobMiddle * fakeGsd - 1 }, // Middle Job 70
|
|
48
|
+
];
|
|
49
|
+
const fakeJob = { id: '01FHRPYJ5FV1XAARZAC4T4K6MC', output: { files: fakeFiles, gsd: fakeGsd } };
|
|
50
|
+
o(await BatchJob.getJobs(fakeJob)).deepEquals([
|
|
51
|
+
[fakeFiles[2].name],
|
|
52
|
+
[fakeFiles[5].name],
|
|
53
|
+
[
|
|
54
|
+
fakeFiles[0].name,
|
|
55
|
+
fakeFiles[1].name,
|
|
56
|
+
fakeFiles[3].name,
|
|
57
|
+
fakeFiles[4].name,
|
|
58
|
+
fakeFiles[6].name,
|
|
59
|
+
fakeFiles[7].name,
|
|
60
|
+
fakeFiles[8].name,
|
|
61
|
+
fakeFiles[9].name,
|
|
62
|
+
fakeFiles[10].name,
|
|
63
|
+
fakeFiles[11].name,
|
|
64
|
+
],
|
|
65
|
+
[fakeFiles[13].name],
|
|
66
|
+
[fakeFiles[12].name, fakeFiles[14].name], // Second Chunk
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semver.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/cogify/__tests__/semver.test.ts"],"names":[],"mappings":""}
|
|
File without changes
|
|
@@ -8,7 +8,7 @@ export declare class ActionCogCreate extends CommandLineAction {
|
|
|
8
8
|
private commit?;
|
|
9
9
|
private cogIndex?;
|
|
10
10
|
constructor();
|
|
11
|
-
|
|
11
|
+
getNames(job: CogJob): Set<string> | null;
|
|
12
12
|
onExecute(): Promise<void>;
|
|
13
13
|
/** Check to see how many tiffs are remaining in the job */
|
|
14
14
|
checkJobStatus(job: CogStacJob, logger: LogType): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.cog.d.ts","sourceRoot":"","sources":["../../../src/cli/cogify/action.cog.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"action.cog.d.ts","sourceRoot":"","sources":["../../../src/cli/cogify/action.cog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE1F,OAAO,EACL,iBAAiB,EAKlB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGvD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ5C,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,OAAO,CAAC,GAAG,CAAC,CAA6B;IACzC,OAAO,CAAC,IAAI,CAAC,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAC,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAAC,CAAkC;;IAUnD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI;IA0CnC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAqFhC,2DAA2D;IACrD,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCrE,SAAS,CAAC,kBAAkB,IAAI,IAAI;CA4BrC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Env, fsa, LogConfig, LoggerFatalError } from '@basemaps/shared';
|
|
1
|
+
import { Config, Env, fsa, LogConfig, LoggerFatalError } from '@basemaps/shared';
|
|
2
|
+
import { CliId } from '@basemaps/shared/build/cli/base.js';
|
|
2
3
|
import { CommandLineAction, } from '@rushstack/ts-command-line';
|
|
3
4
|
import { createReadStream, promises as fs } from 'fs';
|
|
4
5
|
import { buildCogForName } from '../../cog/cog.js';
|
|
@@ -6,9 +7,11 @@ import { CogStacJob } from '../../cog/cog.stac.job.js';
|
|
|
6
7
|
import { CogVrt } from '../../cog/cog.vrt.js';
|
|
7
8
|
import { Cutline } from '../../cog/cutline.js';
|
|
8
9
|
import { Gdal } from '../../gdal/gdal.js';
|
|
9
|
-
import {
|
|
10
|
-
import { makeTempFolder } from '../folder.js';
|
|
10
|
+
import { makeTempFolder, makeTiffFolder } from '../folder.js';
|
|
11
11
|
import path from 'path';
|
|
12
|
+
import { insertConfigImagery, insertConfigTileSet } from './imagery.config.js';
|
|
13
|
+
import { JobStatus } from '@basemaps/config';
|
|
14
|
+
import { prepareUrl } from '../util.js';
|
|
12
15
|
export class ActionCogCreate extends CommandLineAction {
|
|
13
16
|
constructor() {
|
|
14
17
|
super({
|
|
@@ -17,8 +20,9 @@ export class ActionCogCreate extends CommandLineAction {
|
|
|
17
20
|
documentation: 'Create a COG for the specified cog name',
|
|
18
21
|
});
|
|
19
22
|
}
|
|
20
|
-
|
|
23
|
+
getNames(job) {
|
|
21
24
|
var _a, _b;
|
|
25
|
+
const output = new Set();
|
|
22
26
|
const { files } = job.output;
|
|
23
27
|
const batchIndex = Env.getNumber(Env.BatchIndex, -1);
|
|
24
28
|
if (batchIndex > -1) {
|
|
@@ -26,21 +30,29 @@ export class ActionCogCreate extends CommandLineAction {
|
|
|
26
30
|
if (name == null) {
|
|
27
31
|
throw new LoggerFatalError({ cogIndex: batchIndex, tileMax: files.length - 1 }, 'Failed to find cog name from batch index');
|
|
28
32
|
}
|
|
29
|
-
|
|
33
|
+
output.add(name);
|
|
34
|
+
return output;
|
|
30
35
|
}
|
|
31
|
-
const cogIndex = (_a = this.cogIndex) === null || _a === void 0 ? void 0 : _a.
|
|
32
|
-
if (cogIndex != null) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const cogIndex = (_a = this.cogIndex) === null || _a === void 0 ? void 0 : _a.values;
|
|
37
|
+
if (cogIndex != null && cogIndex.length > 0) {
|
|
38
|
+
for (const i of cogIndex) {
|
|
39
|
+
if (i < 0 || i >= files.length) {
|
|
40
|
+
throw new LoggerFatalError({ cogIndex: i, tileMax: files.length - 1 }, 'Failed to find cog name from index');
|
|
41
|
+
}
|
|
42
|
+
const { name } = files[i];
|
|
43
|
+
output.add(name);
|
|
36
44
|
}
|
|
37
|
-
return
|
|
45
|
+
return output;
|
|
38
46
|
}
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
throw new LoggerFatalError({
|
|
47
|
+
const names = (_b = this.name) === null || _b === void 0 ? void 0 : _b.values;
|
|
48
|
+
if (names == null)
|
|
49
|
+
throw new LoggerFatalError({ names }, 'Names cannot be null');
|
|
50
|
+
for (const name of names) {
|
|
51
|
+
if (!files.find((r) => r.name === name))
|
|
52
|
+
throw new LoggerFatalError({ name, names: files.map((r) => r.name).join(', ') }, 'Name does not exist inside job');
|
|
53
|
+
output.add(name);
|
|
42
54
|
}
|
|
43
|
-
return
|
|
55
|
+
return output;
|
|
44
56
|
}
|
|
45
57
|
async onExecute() {
|
|
46
58
|
var _a, _b, _c, _d;
|
|
@@ -58,44 +70,64 @@ export class ActionCogCreate extends CommandLineAction {
|
|
|
58
70
|
logger.info('CogCreate:Start');
|
|
59
71
|
const gdalVersion = await Gdal.version(logger);
|
|
60
72
|
logger.info({ version: gdalVersion }, 'CogCreate:GdalVersion');
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
return;
|
|
64
|
-
const targetPath = job.getJobPath(`${name}.tiff`);
|
|
65
|
-
fsa.configure(job.output.location);
|
|
66
|
-
const outputExists = await fsa.exists(targetPath);
|
|
67
|
-
logger.info({ targetPath, outputExists }, 'CogCreate:CheckExists');
|
|
68
|
-
// Output file exists don't try and overwrite it
|
|
69
|
-
if (outputExists) {
|
|
70
|
-
logger.warn({ targetPath }, 'CogCreate:OutputExists');
|
|
73
|
+
const names = this.getNames(job);
|
|
74
|
+
if (names == null || names.size === 0)
|
|
71
75
|
return;
|
|
72
|
-
}
|
|
73
76
|
const tmpFolder = await makeTempFolder(`basemaps-${job.id}-${CliId}`);
|
|
74
77
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
for (const name of names) {
|
|
79
|
+
const tiffFolder = await makeTiffFolder(tmpFolder, name);
|
|
80
|
+
const targetPath = job.getJobPath(`${name}.tiff`);
|
|
81
|
+
fsa.configure(job.output.location);
|
|
82
|
+
const outputExists = await fsa.exists(targetPath);
|
|
83
|
+
logger.info({ targetPath, outputExists }, 'CogCreate:CheckExists');
|
|
84
|
+
// Output file exists don't try and overwrite it
|
|
85
|
+
if (outputExists) {
|
|
86
|
+
logger.warn({ targetPath }, 'CogCreate:OutputExists');
|
|
87
|
+
await this.checkJobStatus(job, logger);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
let cutlineJson;
|
|
91
|
+
if (job.output.cutline != null) {
|
|
92
|
+
const cutlinePath = job.getJobPath('cutline.geojson.gz');
|
|
93
|
+
logger.info({ path: cutlinePath }, 'CogCreate:UsingCutLine');
|
|
94
|
+
cutlineJson = await Cutline.loadCutline(cutlinePath);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
logger.warn('NoCutLine');
|
|
98
|
+
}
|
|
99
|
+
const cutline = new Cutline(job.tileMatrix, cutlineJson, (_d = job.output.cutline) === null || _d === void 0 ? void 0 : _d.blend, job.output.oneCogCovering);
|
|
100
|
+
const tmpVrtPath = await CogVrt.buildVrt(tiffFolder, job, cutline, name, logger);
|
|
101
|
+
if (tmpVrtPath == null) {
|
|
102
|
+
logger.warn({ name }, 'CogCreate:NoMatchingSourceImagery');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const tmpTiff = fsa.join(tiffFolder, `${name}.tiff`);
|
|
106
|
+
await buildCogForName(job, name, tmpVrtPath, tmpTiff, logger, isCommit);
|
|
107
|
+
logger.info({ target: targetPath }, 'CogCreate:StoreTiff');
|
|
108
|
+
if (isCommit) {
|
|
109
|
+
await fsa.write(targetPath, createReadStream(tmpTiff));
|
|
110
|
+
await this.checkJobStatus(job, logger);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
logger.warn({ name }, 'DryRun:Done');
|
|
114
|
+
}
|
|
83
115
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
const processingId = job.json.processingId;
|
|
119
|
+
if (processingId != null) {
|
|
120
|
+
// Update job status if this is the processing job.
|
|
121
|
+
const jobConfig = await Config.ProcessingJob.get(processingId);
|
|
122
|
+
if (jobConfig == null)
|
|
123
|
+
throw new Error('Unable to find Job Processing Config:' + processingId);
|
|
124
|
+
const jobFailed = jobConfig;
|
|
125
|
+
jobFailed.status = JobStatus.Fail;
|
|
126
|
+
jobFailed.error = String(e);
|
|
127
|
+
if (Config.ProcessingJob.isWriteable())
|
|
128
|
+
await Config.ProcessingJob.put(jobFailed);
|
|
129
|
+
else
|
|
130
|
+
throw new Error('Unable update the Processing Job status:' + jobFailed.id);
|
|
99
131
|
}
|
|
100
132
|
}
|
|
101
133
|
finally {
|
|
@@ -118,7 +150,25 @@ export class ActionCogCreate extends CommandLineAction {
|
|
|
118
150
|
expectedTiffs.delete(basename);
|
|
119
151
|
}
|
|
120
152
|
if (expectedTiffs.size === 0) {
|
|
121
|
-
|
|
153
|
+
// Insert Imagery and TileSet Config
|
|
154
|
+
await insertConfigImagery(job, logger);
|
|
155
|
+
await insertConfigTileSet(job, logger);
|
|
156
|
+
// Update job status if this is the processing job.
|
|
157
|
+
const url = await prepareUrl(job);
|
|
158
|
+
const processingId = job.json.processingId;
|
|
159
|
+
if (processingId != null) {
|
|
160
|
+
const jobConfig = await Config.ProcessingJob.get(processingId);
|
|
161
|
+
if (jobConfig == null)
|
|
162
|
+
throw new Error('Unable to find Job Processing Config:' + processingId);
|
|
163
|
+
const jobComplete = jobConfig;
|
|
164
|
+
jobComplete.status = JobStatus.Complete;
|
|
165
|
+
jobComplete.url = url;
|
|
166
|
+
if (Config.ProcessingJob.isWriteable())
|
|
167
|
+
await Config.ProcessingJob.put(jobConfig);
|
|
168
|
+
else
|
|
169
|
+
throw new Error('Unable update the Processing Job status:' + jobConfig.id);
|
|
170
|
+
}
|
|
171
|
+
logger.info({ tiffCount: jobSize, tiffTotal: jobSize, url }, 'CogCreate:JobComplete');
|
|
122
172
|
}
|
|
123
173
|
else {
|
|
124
174
|
logger.info({ tiffCount: jobSize, tiffRemaining: expectedTiffs.size }, 'CogCreate:JobProgress');
|
|
@@ -131,16 +181,16 @@ export class ActionCogCreate extends CommandLineAction {
|
|
|
131
181
|
description: 'Job config source to access',
|
|
132
182
|
required: true,
|
|
133
183
|
});
|
|
134
|
-
this.name = this.
|
|
184
|
+
this.name = this.defineStringListParameter({
|
|
135
185
|
argumentName: 'NAME',
|
|
136
186
|
parameterLongName: '--name',
|
|
137
|
-
description: 'cog
|
|
187
|
+
description: 'list of cog names to process',
|
|
138
188
|
required: false,
|
|
139
189
|
});
|
|
140
|
-
this.cogIndex = this.
|
|
190
|
+
this.cogIndex = this.defineIntegerListParameter({
|
|
141
191
|
argumentName: 'COG_INDEX',
|
|
142
192
|
parameterLongName: '--cog-index',
|
|
143
|
-
description: '
|
|
193
|
+
description: 'list of cog indexes to process',
|
|
144
194
|
required: false,
|
|
145
195
|
});
|
|
146
196
|
this.commit = this.defineFlagParameter({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.job.d.ts","sourceRoot":"","sources":["../../../src/cli/cogify/action.job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAuB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,iBAAiB,EAGjB,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAMpC,qBAAa,YAAY;IACvB,IAAI,EAAE,0BAA0B,CAAC;IACjC,OAAO,EAAE,0BAA0B,CAAC;IACpC,UAAU,EAAE,0BAA0B,CAAC;gBAE3B,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM;CAsBtD;AAED,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAA6B;;
|
|
1
|
+
{"version":3,"file":"action.job.d.ts","sourceRoot":"","sources":["../../../src/cli/cogify/action.job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAuB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,iBAAiB,EAGjB,0BAA0B,EAC3B,MAAM,4BAA4B,CAAC;AAMpC,qBAAa,YAAY;IACvB,IAAI,EAAE,0BAA0B,CAAC;IACjC,OAAO,EAAE,0BAA0B,CAAC;IACpC,UAAU,EAAE,0BAA0B,CAAC;gBAE3B,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM;CAsBtD;AAED,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAA6B;;IAUjD,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU;IAkBpC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA0DhC,SAAS,CAAC,kBAAkB,IAAI,IAAI;CAyFrC"}
|
|
@@ -3,7 +3,7 @@ import { fsa } from '@basemaps/shared';
|
|
|
3
3
|
import { CommandLineAction, } from '@rushstack/ts-command-line';
|
|
4
4
|
import { CogJobFactory, MaxConcurrencyDefault } from '../../cog/job.factory.js';
|
|
5
5
|
import { GdalCogBuilderDefaults, GdalResamplingOptions } from '../../gdal/gdal.config.js';
|
|
6
|
-
import { CliId } from '
|
|
6
|
+
import { CliId } from '@basemaps/shared/build/cli/base.js';
|
|
7
7
|
export class CLiInputData {
|
|
8
8
|
constructor(parent, prefix) {
|
|
9
9
|
this.path = parent.defineStringParameter({
|
|
@@ -52,7 +52,7 @@ export class ActionJobCreate extends CommandLineAction {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
async onExecute() {
|
|
55
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
55
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
56
56
|
const sourceLocation = this.fsConfig(this.source);
|
|
57
57
|
const outputLocation = this.fsConfig(this.output);
|
|
58
58
|
fsa.configure(this.fsConfig(this.source));
|
|
@@ -95,9 +95,10 @@ export class ActionJobCreate extends CommandLineAction {
|
|
|
95
95
|
id: (_m = (_l = this.overrideId) === null || _l === void 0 ? void 0 : _l.value) !== null && _m !== void 0 ? _m : CliId,
|
|
96
96
|
projection: Epsg.tryGet((_o = this.sourceProjection) === null || _o === void 0 ? void 0 : _o.value),
|
|
97
97
|
resampling,
|
|
98
|
+
processingId: (_p = this.processingId) === null || _p === void 0 ? void 0 : _p.value,
|
|
98
99
|
},
|
|
99
|
-
batch: (
|
|
100
|
-
oneCogCovering: (
|
|
100
|
+
batch: (_r = (_q = this.submitBatch) === null || _q === void 0 ? void 0 : _q.value) !== null && _r !== void 0 ? _r : false,
|
|
101
|
+
oneCogCovering: (_t = (_s = this.oneCog) === null || _s === void 0 ? void 0 : _s.value) !== null && _t !== void 0 ? _t : false,
|
|
101
102
|
};
|
|
102
103
|
await CogJobFactory.create(ctx);
|
|
103
104
|
}
|
|
@@ -171,5 +172,11 @@ export class ActionJobCreate extends CommandLineAction {
|
|
|
171
172
|
description: 'supply a list of files to use as source imagery',
|
|
172
173
|
required: false,
|
|
173
174
|
});
|
|
175
|
+
this.processingId = this.defineStringParameter({
|
|
176
|
+
argumentName: 'PROCESSING_ID',
|
|
177
|
+
parameterLongName: '--processing-id',
|
|
178
|
+
description: 'pass the job processing id',
|
|
179
|
+
required: false,
|
|
180
|
+
});
|
|
174
181
|
}
|
|
175
182
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { LogType } from '@basemaps/shared';
|
|
2
|
-
import { CommandLineAction } from '@rushstack/ts-command-line';
|
|
3
2
|
import Batch from 'aws-sdk/clients/batch.js';
|
|
4
3
|
import { CogJob } from '../../cog/types.js';
|
|
5
4
|
/**
|
|
@@ -9,21 +8,17 @@ import { CogJob } from '../../cog/types.js';
|
|
|
9
8
|
* @returns resolution (millimeters), -1 for failure to parse
|
|
10
9
|
*/
|
|
11
10
|
export declare function extractResolutionFromName(name: string): number;
|
|
12
|
-
export declare class
|
|
13
|
-
private job?;
|
|
14
|
-
private commit?;
|
|
15
|
-
private oneCog?;
|
|
16
|
-
constructor();
|
|
11
|
+
export declare class BatchJob {
|
|
17
12
|
/**
|
|
18
13
|
* Create a id for a job
|
|
19
14
|
*
|
|
20
15
|
* This needs to be within `[a-Z_-]` upto 128 characters log
|
|
21
16
|
* @param job job to process
|
|
22
|
-
* @param
|
|
17
|
+
* @param fileNames output filename
|
|
23
18
|
* @returns job id
|
|
24
19
|
*/
|
|
25
|
-
static id(job: CogJob,
|
|
26
|
-
static batchOne(jobPath: string, job: CogJob, batch: Batch,
|
|
20
|
+
static id(job: CogJob, fileNames: string[]): string;
|
|
21
|
+
static batchOne(jobPath: string, job: CogJob, batch: Batch, names: string[], isCommit: boolean): Promise<{
|
|
27
22
|
jobName: string;
|
|
28
23
|
jobId: string;
|
|
29
24
|
memory: number;
|
|
@@ -33,8 +28,11 @@ export declare class ActionBatchJob extends CommandLineAction {
|
|
|
33
28
|
* @returns a map of JobName to if their status is "ok" (not failed)
|
|
34
29
|
*/
|
|
35
30
|
static getCurrentJobList(batch: Batch): Promise<Map<string, boolean>>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
static batchJob(job: CogJob, commit: boolean | undefined, logger: LogType): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Prepare the jobs from job files, and chunk the small images into single
|
|
34
|
+
* @returns List of jobs including single job and chunk jobs.
|
|
35
|
+
*/
|
|
36
|
+
static getJobs(job: CogJob): Promise<string[][]>;
|
|
39
37
|
}
|
|
40
|
-
//# sourceMappingURL=
|
|
38
|
+
//# sourceMappingURL=batch.job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.job.d.ts","sourceRoot":"","sources":["../../../src/cli/cogify/batch.job.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAC5E,OAAO,KAAK,MAAM,0BAA0B,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAa5C;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED,qBAAa,QAAQ;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM;WAOtC,QAAQ,CACnB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAmC9D;;;OAGG;WACU,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;WAqB9D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,qBAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAyElF;;;OAGG;WACU,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CA4BvD"}
|