sonamu 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.swcrc.project-default +18 -0
- package/bin/cli.js +24 -0
- package/dist/ai/agents/agent.d.ts +11 -0
- package/dist/ai/agents/agent.d.ts.map +1 -0
- package/dist/ai/agents/agent.js +65 -0
- package/dist/ai/agents/index.d.ts +3 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +4 -0
- package/dist/ai/agents/types.d.ts +43 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +3 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/providers/rtzr/api.d.ts +22 -0
- package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/api.js +28 -0
- package/dist/ai/providers/rtzr/error.d.ts +18 -0
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/error.js +29 -0
- package/dist/ai/providers/rtzr/index.d.ts +5 -0
- package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/index.js +6 -0
- package/dist/ai/providers/rtzr/model.d.ts +52 -0
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/model.js +137 -0
- package/dist/ai/providers/rtzr/options.d.ts +7 -0
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/options.js +47 -0
- package/dist/ai/providers/rtzr/provider.d.ts +18 -0
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/provider.js +54 -0
- package/dist/ai/providers/rtzr/utils.d.ts +19 -0
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/utils.js +88 -0
- package/dist/api/base-frame.d.ts +2 -2
- package/dist/api/base-frame.d.ts.map +1 -1
- package/dist/api/base-frame.js +2 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +6 -1
- package/dist/api/code-converters.d.ts +58 -14
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +178 -409
- package/dist/api/config.d.ts +27 -13
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +19 -26
- package/dist/api/context.d.ts +4 -3
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +111 -18
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -3
- package/dist/api/sonamu.d.ts +7 -7
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +83 -51
- package/dist/api/validator.d.ts +6 -0
- package/dist/api/validator.d.ts.map +1 -0
- package/dist/api/validator.js +81 -0
- package/dist/bin/build-config.d.ts +5 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +5 -2
- package/dist/bin/cli.js +165 -64
- package/dist/bin/loader-register.d.ts +2 -0
- package/dist/bin/loader-register.d.ts.map +1 -0
- package/dist/bin/loader-register.js +34 -0
- package/dist/database/_batch_update.d.ts +5 -3
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +30 -13
- package/dist/database/base-model.d.ts +96 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +232 -89
- package/dist/database/base-model.types.d.ts +93 -0
- package/dist/database/base-model.types.d.ts.map +1 -0
- package/dist/database/base-model.types.js +10 -0
- package/dist/database/code-generator.d.ts +1 -1
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +11 -10
- package/dist/database/db.d.ts +5 -6
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +22 -25
- package/dist/database/puri-subset.test-d.js +81 -0
- package/dist/database/puri-subset.types.d.ts +123 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -0
- package/dist/database/puri-subset.types.js +16 -0
- package/dist/database/puri-wrapper.d.ts +13 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +2 -2
- package/dist/database/puri.d.ts +25 -14
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +83 -21
- package/dist/database/puri.types.d.ts +21 -7
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +4 -1
- package/dist/database/transaction-context.d.ts +1 -1
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +1 -1
- package/dist/database/upsert-builder.d.ts +9 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +227 -78
- package/dist/entity/entity-manager.d.ts +165 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +26 -10
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +153 -54
- package/dist/exceptions/error-handler.d.ts +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +1 -1
- package/dist/exceptions/so-exceptions.d.ts +1 -1
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +1 -1
- package/dist/file-storage/driver.d.ts +1 -1
- package/dist/file-storage/driver.d.ts.map +1 -1
- package/dist/file-storage/driver.js +1 -1
- package/dist/file-storage/file-storage.js +2 -2
- package/dist/index.d.ts +18 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -13
- package/dist/migration/code-generation.d.ts +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +123 -67
- package/dist/migration/migration-set.d.ts +2 -10
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +67 -218
- package/dist/migration/migrator.d.ts +24 -73
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +121 -301
- package/dist/migration/postgresql-schema-reader.d.ts +51 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
- package/dist/migration/postgresql-schema-reader.js +245 -0
- package/dist/migration/types.d.ts +6 -38
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +1 -1
- package/dist/naite/messaging-types.d.ts +43 -0
- package/dist/naite/messaging-types.d.ts.map +1 -0
- package/dist/naite/messaging-types.js +7 -0
- package/dist/naite/naite-reporter.d.ts +41 -0
- package/dist/naite/naite-reporter.d.ts.map +1 -0
- package/dist/naite/naite-reporter.js +102 -0
- package/dist/naite/naite.d.ts +91 -8
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +285 -41
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +1 -1
- package/dist/syncer/api-parser.d.ts +3 -13
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +67 -56
- package/dist/syncer/checksum.d.ts +2 -2
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +11 -11
- package/dist/syncer/code-generator.d.ts +3 -3
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +37 -17
- package/dist/syncer/entity-operations.d.ts +2 -2
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +9 -8
- package/dist/syncer/file-patterns.d.ts +1 -1
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +1 -1
- package/dist/syncer/index.d.ts +4 -4
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +5 -5
- package/dist/syncer/module-loader.d.ts +4 -4
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +17 -12
- package/dist/syncer/syncer.d.ts +31 -24
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +92 -45
- package/dist/template/entity-converter.d.ts +1 -1
- package/dist/template/entity-converter.d.ts.map +1 -1
- package/dist/template/entity-converter.js +15 -8
- package/dist/template/helpers.d.ts +2 -2
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +3 -3
- package/dist/template/implementations/entity.template.d.ts +2 -2
- package/dist/template/implementations/entity.template.d.ts.map +1 -1
- package/dist/template/implementations/entity.template.js +4 -5
- package/dist/template/implementations/generated.template.d.ts +2 -3
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +46 -29
- package/dist/template/implementations/generated_http.template.d.ts +2 -3
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +9 -9
- package/dist/template/implementations/generated_sso.template.d.ts +3 -4
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +54 -25
- package/dist/template/implementations/init_types.template.d.ts +2 -2
- package/dist/template/implementations/init_types.template.d.ts.map +1 -1
- package/dist/template/implementations/init_types.template.js +2 -2
- package/dist/template/implementations/model.template.d.ts +2 -2
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +47 -37
- package/dist/template/implementations/model_test.template.d.ts +2 -2
- package/dist/template/implementations/model_test.template.d.ts.map +1 -1
- package/dist/template/implementations/model_test.template.js +2 -2
- package/dist/template/implementations/service.template.d.ts +4 -4
- package/dist/template/implementations/service.template.d.ts.map +1 -1
- package/dist/template/implementations/service.template.js +24 -16
- package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_select.template.js +2 -2
- package/dist/template/implementations/view_form.template.d.ts +2 -2
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +4 -4
- package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_all_select.template.js +1 -1
- package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_async_select.template.js +1 -1
- package/dist/template/implementations/view_list.template.d.ts +2 -2
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +29 -19
- package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list_columns.template.js +1 -1
- package/dist/template/implementations/view_search_input.template.d.ts +2 -2
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
- package/dist/template/implementations/view_search_input.template.js +1 -1
- package/dist/template/index.d.ts +4 -2
- package/dist/template/index.d.ts.map +1 -1
- package/dist/template/index.js +5 -3
- package/dist/template/template-manager.d.ts +56 -0
- package/dist/template/template-manager.d.ts.map +1 -0
- package/dist/template/template-manager.js +125 -0
- package/dist/template/template-types.d.ts +16 -0
- package/dist/template/template-types.d.ts.map +1 -0
- package/dist/template/template-types.js +7 -0
- package/dist/template/template.d.ts +12 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +19 -6
- package/dist/template/zod-converter.d.ts +40 -7
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +386 -58
- package/dist/testing/_relation-graph.d.ts +1 -1
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +12 -3
- package/dist/testing/fixture-manager.d.ts +42 -11
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +338 -236
- package/dist/types/types.d.ts +709 -104
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +309 -52
- package/dist/typings/knex.d.js +2 -2
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +3 -3
- package/dist/utils/console-util.js +1 -1
- package/dist/utils/controller.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +4 -1
- package/dist/utils/esm-utils.d.ts +0 -6
- package/dist/utils/esm-utils.d.ts.map +1 -1
- package/dist/utils/esm-utils.js +2 -9
- package/dist/utils/formatter.d.ts +3 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +110 -0
- package/dist/utils/fs-utils.d.ts +1 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +1 -1
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +1 -1
- package/dist/utils/object-utils.d.ts +44 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +191 -0
- package/dist/utils/path-utils.d.ts +1 -1
- package/dist/utils/path-utils.d.ts.map +1 -1
- package/dist/utils/path-utils.js +3 -3
- package/dist/utils/process-utils.js +1 -1
- package/dist/utils/sql-parser.d.ts +5 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +14 -3
- package/dist/utils/type-utils.d.ts +23 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +45 -0
- package/dist/utils/utils.d.ts +7 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +44 -5
- package/dist/utils/zod-error.d.ts +1 -1
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +1 -1
- package/package.json +55 -30
- package/src/ai/agents/agent.ts +87 -0
- package/src/ai/agents/index.ts +2 -0
- package/src/ai/agents/types.ts +47 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/providers/rtzr/api.ts +37 -0
- package/src/ai/providers/rtzr/error.ts +34 -0
- package/src/ai/providers/rtzr/index.ts +4 -0
- package/src/ai/providers/rtzr/model.ts +201 -0
- package/src/ai/providers/rtzr/options.ts +49 -0
- package/src/ai/providers/rtzr/provider.ts +91 -0
- package/src/ai/providers/rtzr/utils.ts +127 -0
- package/src/api/base-frame.ts +4 -2
- package/src/api/caster.ts +17 -23
- package/src/api/code-converters.ts +176 -533
- package/src/api/config.ts +39 -56
- package/src/api/context.ts +7 -18
- package/src/api/decorators.ts +175 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +133 -124
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +7 -1
- package/src/bin/cli.ts +192 -110
- package/src/bin/loader-register.ts +38 -0
- package/src/database/_batch_update.ts +46 -31
- package/src/database/base-model.ts +390 -182
- package/src/database/base-model.types.ts +155 -0
- package/src/database/code-generator.ts +13 -32
- package/src/database/db.ts +36 -50
- package/src/database/puri-subset.test-d.ts +471 -0
- package/src/database/puri-subset.types.ts +195 -0
- package/src/database/puri-wrapper.ts +58 -67
- package/src/database/puri.ts +182 -126
- package/src/database/puri.types.ts +64 -31
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +261 -132
- package/src/entity/entity-manager.ts +36 -28
- package/src/entity/entity.ts +330 -249
- package/src/exceptions/error-handler.ts +3 -3
- package/src/exceptions/so-exceptions.ts +11 -11
- package/src/file-storage/driver.ts +5 -5
- package/src/file-storage/file-storage.ts +2 -2
- package/src/index.ts +18 -12
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +182 -425
- package/src/migration/mysql-schema-reader.ts.txt +272 -0
- package/src/migration/postgresql-schema-reader.ts +310 -0
- package/src/migration/types.ts +6 -39
- package/src/naite/messaging-types.ts +51 -0
- package/src/naite/naite-reporter.ts +128 -0
- package/src/naite/naite.ts +378 -33
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +52 -69
- package/src/syncer/checksum.ts +25 -37
- package/src/syncer/code-generator.ts +58 -62
- package/src/syncer/entity-operations.ts +12 -15
- package/src/syncer/file-patterns.ts +2 -2
- package/src/syncer/index.ts +4 -4
- package/src/syncer/module-loader.ts +28 -25
- package/src/syncer/syncer.ts +155 -162
- package/src/template/entity-converter.ts +18 -27
- package/src/template/helpers.ts +8 -11
- package/src/template/implementations/entity.template.ts +6 -6
- package/src/template/implementations/generated.template.ts +99 -99
- package/src/template/implementations/generated_http.template.ts +21 -54
- package/src/template/implementations/generated_sso.template.ts +78 -65
- package/src/template/implementations/init_types.template.ts +4 -6
- package/src/template/implementations/model.template.ts +47 -38
- package/src/template/implementations/model_test.template.ts +3 -3
- package/src/template/implementations/service.template.ts +56 -80
- package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
- package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
- package/src/template/implementations/view_enums_select.template.ts +3 -3
- package/src/template/implementations/view_form.template.ts +34 -75
- package/src/template/implementations/view_id_all_select.template.ts +2 -2
- package/src/template/implementations/view_id_async_select.template.ts +9 -23
- package/src/template/implementations/view_list.template.ts +54 -95
- package/src/template/implementations/view_list_columns.template.ts +4 -10
- package/src/template/implementations/view_search_input.template.ts +2 -2
- package/src/template/index.ts +4 -2
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +29 -10
- package/src/template/zod-converter.ts +459 -101
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +468 -362
- package/src/types/types.ts +516 -248
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +8 -12
- package/src/utils/console-util.ts +1 -1
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +8 -18
- package/src/utils/formatter.ts +109 -0
- package/src/utils/fs-utils.ts +1 -1
- package/src/utils/lodash-able.ts +1 -4
- package/src/utils/object-utils.ts +217 -0
- package/src/utils/path-utils.ts +3 -6
- package/src/utils/process-utils.ts +1 -1
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +58 -9
- package/src/utils/zod-error.ts +3 -3
- package/dist/bin/cli-wrapper.d.ts +0 -3
- package/dist/bin/cli-wrapper.d.ts.map +0 -1
- package/dist/bin/cli-wrapper.js +0 -72
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
- package/dist/entity/entity-utils.d.ts +0 -61
- package/dist/entity/entity-utils.d.ts.map +0 -1
- package/dist/entity/entity-utils.js +0 -210
- package/src/bin/cli-wrapper.ts +0 -82
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { chunk, groupBy, isObject, omit, set, uniq } from "lodash-es";
|
|
3
|
-
import { DB } from "./db.js";
|
|
4
|
-
import { isCustomJoinClause } from "../types/types.js";
|
|
1
|
+
import assert from "assert";
|
|
5
2
|
import inflection from "inflection";
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
3
|
+
import { group, isObject, omit, set, unique } from "radashi";
|
|
4
|
+
import { Sonamu } from "../api/index.js";
|
|
5
|
+
import { isCustomJoinClause } from "../types/types.js";
|
|
6
|
+
import { getJoinTables, getTableNamesFromWhere } from "../utils/sql-parser.js";
|
|
7
|
+
import { chunk } from "../utils/utils.js";
|
|
8
|
+
import { DB } from "./db.js";
|
|
9
|
+
import { Puri } from "./puri.js";
|
|
10
10
|
import { PuriWrapper } from "./puri-wrapper.js";
|
|
11
|
-
|
|
11
|
+
import { UpsertBuilder } from "./upsert-builder.js";
|
|
12
|
+
/**
|
|
13
|
+
* 모든 Model 클래스의 기본 클래스
|
|
14
|
+
*
|
|
15
|
+
* @template TSubsetKey - 서브셋 키 유니온 (예: "A" | "P" | "SS")
|
|
16
|
+
* @template TSubsetMapping - 서브셋별 최종 결과 타입 매핑
|
|
17
|
+
* @template TSubsetQueries - 서브셋 쿼리 함수 객체
|
|
18
|
+
* @template TLoaderQueries - 서브셋별 로더 쿼리 배열 객체
|
|
19
|
+
*/ export class BaseModelClass {
|
|
20
|
+
subsetQueries;
|
|
21
|
+
loaderQueries;
|
|
12
22
|
modelName = "Unknown";
|
|
13
|
-
|
|
23
|
+
constructor(subsetQueries, loaderQueries){
|
|
24
|
+
this.subsetQueries = subsetQueries;
|
|
25
|
+
this.loaderQueries = loaderQueries;
|
|
26
|
+
}
|
|
27
|
+
getDB(which) {
|
|
14
28
|
return DB.getDB(which);
|
|
15
29
|
}
|
|
16
30
|
getPuri(which) {
|
|
@@ -26,16 +40,13 @@ export class BaseModelClass {
|
|
|
26
40
|
async destroy() {
|
|
27
41
|
return DB.destroy();
|
|
28
42
|
}
|
|
29
|
-
myNow(timestamp) {
|
|
30
|
-
const dt = timestamp === undefined ? DateTime.local() : DateTime.fromSeconds(timestamp);
|
|
31
|
-
return dt.toFormat("yyyy-MM-dd HH:mm:ss");
|
|
32
|
-
}
|
|
33
43
|
async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
|
|
34
44
|
if (!wdb) {
|
|
35
45
|
wdb = this.getDB("w");
|
|
36
46
|
}
|
|
37
47
|
let unqKeys;
|
|
38
|
-
let whereInField
|
|
48
|
+
let whereInField;
|
|
49
|
+
let selectField;
|
|
39
50
|
if (unqKeyFields.length > 1) {
|
|
40
51
|
whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
|
|
41
52
|
selectField = `${whereInField} as tmpUid`;
|
|
@@ -45,96 +56,175 @@ export class BaseModelClass {
|
|
|
45
56
|
selectField = unqKeyFields[0];
|
|
46
57
|
unqKeys = rows.map((row)=>row[unqKeyFields[0]]);
|
|
47
58
|
}
|
|
48
|
-
const chunks = chunk(unqKeys, chunkSize);
|
|
49
59
|
let resultIds = [];
|
|
50
|
-
for (
|
|
51
|
-
const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField,
|
|
52
|
-
resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(dbRow.id)));
|
|
60
|
+
for (const items of chunk(unqKeys, chunkSize)){
|
|
61
|
+
const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
|
|
62
|
+
resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(String(dbRow.id))));
|
|
53
63
|
}
|
|
54
64
|
return resultIds;
|
|
55
65
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
/**
|
|
67
|
+
* 특정 서브셋에 대한 쿼리 빌더 획득
|
|
68
|
+
*
|
|
69
|
+
* @returns qb - 쿼리 빌더 (조건 추가용)
|
|
70
|
+
* @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
|
|
71
|
+
*/ getSubsetQueries(subset) {
|
|
72
|
+
if (!this.subsetQueries) {
|
|
73
|
+
throw new Error("subsetQueries is not defined");
|
|
59
74
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
75
|
+
const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
|
|
76
|
+
const qb = this.subsetQueries[subset]?.(puriWrapper);
|
|
77
|
+
return {
|
|
78
|
+
qb: qb,
|
|
79
|
+
onSubset: (_subset)=>qb
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Enhancer 객체 생성 헬퍼
|
|
84
|
+
* 타입 검증 및 추론을 도와줌
|
|
85
|
+
*/ createEnhancers(enhancers) {
|
|
86
|
+
return enhancers;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 서브셋 쿼리 실행
|
|
90
|
+
*
|
|
91
|
+
* 1. 쿼리 실행 (pagination 적용)
|
|
92
|
+
* 2. 로더 실행 (1:N, N:M 관계 데이터 로딩)
|
|
93
|
+
* 3. Hydrate (flat → 중첩 객체)
|
|
94
|
+
* 4. Enhancer 적용 (virtual 필드 계산)
|
|
95
|
+
*/ async executeSubsetQuery(params) {
|
|
96
|
+
const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
|
|
97
|
+
if (!this.loaderQueries) {
|
|
98
|
+
throw new Error("loaderQueries is not defined");
|
|
99
|
+
}
|
|
100
|
+
if (!queryParams.num || !queryParams.page) {
|
|
101
|
+
throw new Error("num and page are required");
|
|
102
|
+
}
|
|
103
|
+
const { num, page } = queryParams;
|
|
104
|
+
// COUNT 쿼리 실행
|
|
105
|
+
const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
|
|
106
|
+
// LIST 쿼리 실행
|
|
107
|
+
const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
|
|
108
|
+
// Enhancer 적용
|
|
109
|
+
const enhancer = params.enhancers?.[subset];
|
|
110
|
+
const rows = await Promise.all(computedRows.map((row)=>enhancer?.(row) ?? row));
|
|
111
|
+
return {
|
|
112
|
+
rows,
|
|
113
|
+
total
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* COUNT 쿼리 실행 (내부 메서드)
|
|
118
|
+
*/ async executeCountQuery(qb, params, debug, optimizeCountQuery) {
|
|
119
|
+
if (params.queryMode === "list") {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
|
|
123
|
+
if (optimizeCountQuery) {
|
|
124
|
+
const { default: SqlParser } = await import("node-sql-parser");
|
|
125
|
+
const parser = new SqlParser.Parser();
|
|
126
|
+
const parsedQuery = parser.astify(countPuri.toQuery(), {
|
|
127
|
+
database: Sonamu.config.database.database
|
|
128
|
+
});
|
|
129
|
+
const leftJoinTables = getJoinTables(parsedQuery, [
|
|
130
|
+
"LEFT JOIN"
|
|
131
|
+
]);
|
|
132
|
+
const whereTables = getTableNamesFromWhere(parsedQuery);
|
|
133
|
+
const tablesToRemove = leftJoinTables.filter((j)=>!whereTables.includes(j));
|
|
134
|
+
tablesToRemove.forEach((table)=>{
|
|
135
|
+
countPuri.clearJoin(table);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// COUNT(*)로 전체 레코드 수를 계산
|
|
139
|
+
// TODO: qb의 DISTINCT가 있는 경우 처리해야 함
|
|
140
|
+
const countResult = await countPuri.clear("select").select({
|
|
141
|
+
total: Puri.rawNumber(`COUNT(*)::integer`)
|
|
142
|
+
}).first();
|
|
143
|
+
if (debug) {
|
|
144
|
+
countPuri.debug();
|
|
145
|
+
}
|
|
146
|
+
return countResult?.total ?? 0;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* LIST 쿼리 실행 (내부 메서드)
|
|
150
|
+
*/ async executeListQuery(subset, qb, params, num, page, debug) {
|
|
151
|
+
if (params.queryMode === "count") {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
let unloadedRows = await qb.limit(num).offset(num * (page - 1));
|
|
155
|
+
if (debug) {
|
|
156
|
+
qb.debug();
|
|
157
|
+
}
|
|
158
|
+
// 로더 처리
|
|
159
|
+
const loaders = this.loaderQueries[subset];
|
|
160
|
+
if (loaders && Array.isArray(loaders)) {
|
|
161
|
+
unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
|
|
162
|
+
}
|
|
163
|
+
return this.hydrate(unloadedRows);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 재귀적 로더 처리
|
|
167
|
+
*/ async processLoaders(rows, loaders, debug) {
|
|
168
|
+
for (const resolveLoader of loaders){
|
|
169
|
+
const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
|
|
170
|
+
const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row)=>row[refId]));
|
|
171
|
+
if (debug) {
|
|
172
|
+
resolveLoaderQb.debug();
|
|
97
173
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
174
|
+
let loadedRows = await resolveLoaderQb;
|
|
175
|
+
// 중첩 loaders가 있으면 재귀 처리
|
|
176
|
+
if (nestedLoaders && nestedLoaders.length > 0) {
|
|
177
|
+
loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
|
|
102
178
|
}
|
|
103
|
-
|
|
104
|
-
const subRowGroups = groupBy(subRows, toCol);
|
|
179
|
+
const subRowGroups = group(loadedRows, (row)=>row.refId);
|
|
105
180
|
rows = rows.map((row)=>{
|
|
106
|
-
row[
|
|
181
|
+
row[as] = (subRowGroups[row[refId]] ?? []).map((r)=>omit(r, [
|
|
182
|
+
"refId"
|
|
183
|
+
]));
|
|
107
184
|
return row;
|
|
108
185
|
});
|
|
109
186
|
}
|
|
110
187
|
return rows;
|
|
111
188
|
}
|
|
112
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Flat 레코드를 중첩 객체로 변환
|
|
191
|
+
*
|
|
192
|
+
* - `user__name` → `{ user: { name } }`
|
|
193
|
+
* - nullable relation의 경우 모든 필드가 null이면 객체 자체를 null로
|
|
194
|
+
*/ hydrate(rows) {
|
|
113
195
|
return rows.map((row)=>{
|
|
114
|
-
// nullable relation
|
|
196
|
+
// nullable relation 처리: 관련 필드가 전부 null인 경우 방지
|
|
115
197
|
const nestedKeys = Object.keys(row).filter((key)=>key.includes("__"));
|
|
116
|
-
const groups = groupBy(nestedKeys, (key)=>key.split("__")[0]);
|
|
117
|
-
const nullKeys = Object.
|
|
198
|
+
const groups = Object.groupBy(nestedKeys, (key)=>key.split("__")[0]);
|
|
199
|
+
const nullKeys = Object.entries(groups).filter(([_, data])=>data && data.length > 1 && data.every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0)).map(([key])=>key);
|
|
118
200
|
const hydrated = Object.keys(row).reduce((r, field)=>{
|
|
119
201
|
if (!field.includes("__")) {
|
|
202
|
+
// 일반 필드: 배열 내 객체면 재귀 hydrate
|
|
120
203
|
if (Array.isArray(row[field]) && isObject(row[field][0])) {
|
|
121
204
|
r[field] = this.hydrate(row[field]);
|
|
122
|
-
return r;
|
|
123
205
|
} else {
|
|
124
206
|
r[field] = row[field];
|
|
125
|
-
return r;
|
|
126
207
|
}
|
|
208
|
+
return r;
|
|
127
209
|
}
|
|
210
|
+
// 중첩 필드 처리: user__name → user[name]
|
|
128
211
|
const parts = field.split("__");
|
|
129
212
|
const objPath = parts[0] + parts.slice(1).map((part)=>`[${part}]`).join("");
|
|
130
|
-
set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
|
|
213
|
+
r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
|
|
131
214
|
return r;
|
|
132
215
|
}, {});
|
|
133
|
-
|
|
216
|
+
// null relation 처리
|
|
217
|
+
nullKeys.forEach((nullKey)=>{
|
|
218
|
+
hydrated[nullKey] = null;
|
|
219
|
+
});
|
|
134
220
|
return hydrated;
|
|
135
221
|
});
|
|
136
222
|
}
|
|
223
|
+
// Legacy SubsetQuery 실행 (Puri 도입 전 호환용)
|
|
137
224
|
async runSubsetQuery({ params, baseTable, subset, subsetQuery, build, afterBuild, debug, db: _db, optimizeCountQuery }) {
|
|
225
|
+
const chalk = (await import("chalk")).default;
|
|
226
|
+
const SqlParser = (await import("node-sql-parser")).default;
|
|
227
|
+
const { getTableName, getTableNamesFromWhere } = await import("../utils/sql-parser.js");
|
|
138
228
|
const db = _db ?? this.getDB(subset.startsWith("A") ? "w" : "r");
|
|
139
229
|
baseTable = baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));
|
|
140
230
|
const queryMode = params.queryMode ?? (params.id !== undefined ? "list" : "both");
|
|
@@ -147,10 +237,10 @@ export class BaseModelClass {
|
|
|
147
237
|
virtual
|
|
148
238
|
});
|
|
149
239
|
const applyJoinClause = (qb, joins)=>{
|
|
150
|
-
joins.
|
|
151
|
-
if (join.join
|
|
240
|
+
joins.forEach((join)=>{
|
|
241
|
+
if (join.join === "inner") {
|
|
152
242
|
qb.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
153
|
-
} else if (join.join
|
|
243
|
+
} else if (join.join === "outer") {
|
|
154
244
|
qb.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
155
245
|
}
|
|
156
246
|
});
|
|
@@ -162,12 +252,12 @@ export class BaseModelClass {
|
|
|
162
252
|
}
|
|
163
253
|
const clonedQb = qb.clone().clear("order").clear("offset").clear("limit");
|
|
164
254
|
const parser = new SqlParser.Parser();
|
|
165
|
-
// optmizeCountQuery가 true인 경우 다른 clause에 영향을 주지 않는 모든 join을 제외함
|
|
166
255
|
if (optimizeCountQuery) {
|
|
167
|
-
const parsedQuery = parser.astify(clonedQb.toQuery()
|
|
256
|
+
const parsedQuery = parser.astify(clonedQb.toQuery(), {
|
|
257
|
+
database: Sonamu.config.database.database
|
|
258
|
+
});
|
|
168
259
|
const tables = getTableNamesFromWhere(parsedQuery);
|
|
169
|
-
|
|
170
|
-
const needToJoin = uniq(tables.flatMap((table)=>table.split("__").map((t)=>inflection.pluralize(t))));
|
|
260
|
+
const needToJoin = unique(tables.flatMap((table)=>table.split("__").map((t)=>inflection.pluralize(t))));
|
|
171
261
|
applyJoinClause(clonedQb, joins.filter((j)=>needToJoin.includes(j.table)));
|
|
172
262
|
} else {
|
|
173
263
|
applyJoinClause(clonedQb, joins);
|
|
@@ -179,7 +269,9 @@ export class BaseModelClass {
|
|
|
179
269
|
joins,
|
|
180
270
|
virtual
|
|
181
271
|
}) ?? clonedQb;
|
|
182
|
-
const parsedQuery = parser.astify(processedQb.toQuery()
|
|
272
|
+
const parsedQuery = parser.astify(processedQb.toQuery(), {
|
|
273
|
+
database: Sonamu.config.database.database
|
|
274
|
+
});
|
|
183
275
|
const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;
|
|
184
276
|
if (q.type !== "select") {
|
|
185
277
|
throw new Error("Invalid query");
|
|
@@ -188,7 +280,6 @@ export class BaseModelClass {
|
|
|
188
280
|
as: "total"
|
|
189
281
|
}).first();
|
|
190
282
|
const countRow = await countQuery;
|
|
191
|
-
// debug: countQuery
|
|
192
283
|
if (debug === true || debug === "count") {
|
|
193
284
|
console.debug("DEBUG: count query", chalk.blue(countQuery.toQuery().toString()));
|
|
194
285
|
}
|
|
@@ -199,14 +290,12 @@ export class BaseModelClass {
|
|
|
199
290
|
if (queryMode === "count") {
|
|
200
291
|
return [];
|
|
201
292
|
}
|
|
202
|
-
// limit, offset
|
|
203
293
|
if (params.num !== 0) {
|
|
294
|
+
assert(params.num);
|
|
204
295
|
qb.limit(params.num);
|
|
205
|
-
qb.offset(params.num * (params.page - 1));
|
|
296
|
+
qb.offset(params.num * ((params.page ?? 1) - 1));
|
|
206
297
|
}
|
|
207
|
-
// select, rows
|
|
208
298
|
const clonedQb = qb.clone().select(select);
|
|
209
|
-
// join
|
|
210
299
|
applyJoinClause(clonedQb, joins);
|
|
211
300
|
const listQuery = afterBuild?.({
|
|
212
301
|
qb: clonedQb,
|
|
@@ -216,7 +305,6 @@ export class BaseModelClass {
|
|
|
216
305
|
virtual
|
|
217
306
|
}) ?? clonedQb;
|
|
218
307
|
let rows = await listQuery;
|
|
219
|
-
// debug: listQuery
|
|
220
308
|
if (debug === true || debug === "list") {
|
|
221
309
|
console.debug("DEBUG: list query", chalk.blue(listQuery.toQuery().toString()));
|
|
222
310
|
}
|
|
@@ -231,6 +319,61 @@ export class BaseModelClass {
|
|
|
231
319
|
qb
|
|
232
320
|
};
|
|
233
321
|
}
|
|
322
|
+
// Legacy Loader 처리 (Puri 도입 전 호환용)
|
|
323
|
+
async useLoaders(db, rows, loaders) {
|
|
324
|
+
if (loaders.length === 0) {
|
|
325
|
+
return rows;
|
|
326
|
+
}
|
|
327
|
+
for (const loader of loaders){
|
|
328
|
+
let subQ;
|
|
329
|
+
let subRows;
|
|
330
|
+
let toCol;
|
|
331
|
+
const fromIds = rows.map((row)=>row[loader.manyJoin.idField]);
|
|
332
|
+
if (loader.manyJoin.through === undefined) {
|
|
333
|
+
// HasMany
|
|
334
|
+
const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;
|
|
335
|
+
subQ = db(loader.manyJoin.toTable).whereIn(idColumn, fromIds).select([
|
|
336
|
+
...loader.select,
|
|
337
|
+
idColumn
|
|
338
|
+
]);
|
|
339
|
+
loader.oneJoins.forEach((join)=>{
|
|
340
|
+
if (join.join === "inner") {
|
|
341
|
+
subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
342
|
+
} else if (join.join === "outer") {
|
|
343
|
+
subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
toCol = loader.manyJoin.toCol;
|
|
347
|
+
} else {
|
|
348
|
+
// ManyToMany
|
|
349
|
+
const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;
|
|
350
|
+
subQ = db(loader.manyJoin.through.table).join(loader.manyJoin.toTable, `${loader.manyJoin.through.table}.${loader.manyJoin.through.toCol}`, `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`).whereIn(idColumn, fromIds).select(unique([
|
|
351
|
+
...loader.select,
|
|
352
|
+
idColumn
|
|
353
|
+
]));
|
|
354
|
+
loader.oneJoins.forEach((join)=>{
|
|
355
|
+
if (join.join === "inner") {
|
|
356
|
+
subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
357
|
+
} else if (join.join === "outer") {
|
|
358
|
+
subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
toCol = loader.manyJoin.through.fromCol;
|
|
362
|
+
}
|
|
363
|
+
subRows = await subQ;
|
|
364
|
+
if (loader.loaders) {
|
|
365
|
+
subRows = await this.useLoaders(db, subRows, loader.loaders);
|
|
366
|
+
}
|
|
367
|
+
const subRowGroups = group(subRows, (row)=>row[toCol]);
|
|
368
|
+
rows = rows.map((row)=>{
|
|
369
|
+
row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map((r)=>omit(r, [
|
|
370
|
+
toCol
|
|
371
|
+
]));
|
|
372
|
+
return row;
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
return rows;
|
|
376
|
+
}
|
|
234
377
|
getJoinClause(db, join) {
|
|
235
378
|
if (!isCustomJoinClause(join)) {
|
|
236
379
|
return db.raw(`${join.from} = ${join.to}`);
|
|
@@ -244,4 +387,4 @@ export class BaseModelClass {
|
|
|
244
387
|
}
|
|
245
388
|
export const BaseModel = new BaseModelClass();
|
|
246
389
|
|
|
247
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGVUaW1lIH0gZnJvbSBcImx1eG9uXCI7XG5pbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGNodW5rLCBncm91cEJ5LCBpc09iamVjdCwgb21pdCwgc2V0LCB1bmlxIH0gZnJvbSBcImxvZGFzaC1lc1wiO1xuaW1wb3J0IHsgREJQcmVzZXQsIERCIH0gZnJvbSBcIi4vZGJcIjtcbmltcG9ydCB7IGlzQ3VzdG9tSm9pbkNsYXVzZSwgdHlwZSBTdWJzZXRRdWVyeSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBCYXNlTGlzdFBhcmFtcyB9IGZyb20gXCIuLi91dGlscy9tb2RlbFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IFNxbFBhcnNlciBmcm9tIFwibm9kZS1zcWwtcGFyc2VyXCI7XG5pbXBvcnQgeyBnZXRUYWJsZU5hbWUsIGdldFRhYmxlTmFtZXNGcm9tV2hlcmUgfSBmcm9tIFwiLi4vdXRpbHMvc3FsLXBhcnNlclwiO1xuaW1wb3J0IHsgUHVyaVdyYXBwZXIgfSBmcm9tIFwiLi9wdXJpLXdyYXBwZXJcIjtcblxuZXhwb3J0IGNsYXNzIEJhc2VNb2RlbENsYXNzIHtcbiAgcHVibGljIG1vZGVsTmFtZTogc3RyaW5nID0gXCJVbmtub3duXCI7XG5cbiAgLyogREIg7J247Iqk7YS07IqkIGdldCwgZGVzdHJveSAqL1xuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCB0aGlzLmdldFVwc2VydEJ1aWxkZXIoKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCkge1xuICAgIHJldHVybiBEQi5kZXN0cm95KCk7XG4gIH1cblxuICBteU5vdyh0aW1lc3RhbXA/OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGR0OiBEYXRlVGltZSA9XG4gICAgICB0aW1lc3RhbXAgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IERhdGVUaW1lLmxvY2FsKClcbiAgICAgICAgOiBEYXRlVGltZS5mcm9tU2Vjb25kcyh0aW1lc3RhbXApO1xuICAgIHJldHVybiBkdC50b0Zvcm1hdChcInl5eXktTU0tZGQgSEg6bW06c3NcIik7XG4gIH1cblxuICBhc3luYyBnZXRJbnNlcnRlZElkcyhcbiAgICB3ZGI6IEtuZXgsXG4gICAgcm93czogYW55W10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgdW5xS2V5RmllbGRzOiBzdHJpbmdbXSxcbiAgICBjaHVua1NpemU6IG51bWJlciA9IDUwMFxuICApIHtcbiAgICBpZiAoIXdkYikge1xuICAgICAgd2RiID0gdGhpcy5nZXREQihcIndcIik7XG4gICAgfVxuXG4gICAgbGV0IHVucUtleXM6IHN0cmluZ1tdO1xuICAgIGxldCB3aGVyZUluRmllbGQ6IGFueSwgc2VsZWN0RmllbGQ6IHN0cmluZztcbiAgICBpZiAodW5xS2V5RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHdkYi5yYXcoYENPTkNBVF9XUygnXycsICcke3VucUtleUZpZWxkcy5qb2luKFwiLFwiKX0nKWApO1xuICAgICAgc2VsZWN0RmllbGQgPSBgJHt3aGVyZUluRmllbGR9IGFzIHRtcFVpZGA7XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT5cbiAgICAgICAgdW5xS2V5RmllbGRzLm1hcCgoZmllbGQpID0+IHJvd1tmaWVsZF0pLmpvaW4oXCJfXCIpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICBzZWxlY3RGaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbdW5xS2V5RmllbGRzWzBdXSk7XG4gICAgfVxuICAgIGNvbnN0IGNodW5rcyA9IGNodW5rKHVucUtleXMsIGNodW5rU2l6ZSk7XG5cbiAgICBsZXQgcmVzdWx0SWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGNodW5rIG9mIGNodW5rcykge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQsIGNodW5rKTtcbiAgICAgIHJlc3VsdElkcyA9IHJlc3VsdElkcy5jb25jYXQoXG4gICAgICAgIGRiUm93cy5tYXAoKGRiUm93OiBhbnkpID0+IHBhcnNlSW50KGRiUm93LmlkKSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdElkcztcbiAgfVxuXG4gIGFzeW5jIHVzZUxvYWRlcnMoZGI6IEtuZXgsIHJvd3M6IGFueVtdLCBsb2FkZXJzOiBTdWJzZXRRdWVyeVtcImxvYWRlcnNcIl0pIHtcbiAgICBpZiAobG9hZGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiByb3dzO1xuICAgIH1cblxuICAgIGZvciAobGV0IGxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBsZXQgc3ViUTogYW55O1xuICAgICAgbGV0IHN1YlJvd3M6IGFueVtdO1xuICAgICAgbGV0IHRvQ29sOiBzdHJpbmc7XG5cbiAgICAgIGNvbnN0IGZyb21JZHMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbbG9hZGVyLm1hbnlKb2luLmlkRmllbGRdKTtcblxuICAgICAgaWYgKGxvYWRlci5tYW55Sm9pbi50aHJvdWdoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gSGFzTWFueVxuICAgICAgICBjb25zdCBpZENvbHVtbiA9IGAke2xvYWRlci5tYW55Sm9pbi50b1RhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50b0NvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRvVGFibGUpXG4gICAgICAgICAgLndoZXJlSW4oaWRDb2x1bW4sIGZyb21JZHMpXG4gICAgICAgICAgLnNlbGVjdChbLi4ubG9hZGVyLnNlbGVjdCwgaWRDb2x1bW5dKTtcblxuICAgICAgICAvLyBIYXNNYW557JeQ7IScIE9uZUpvaW7snbQg7J6I64qUIOqyveyasFxuICAgICAgICBsb2FkZXIub25lSm9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgICAgaWYgKGpvaW4uam9pbiA9PSBcImlubmVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEuaW5uZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGpvaW4uam9pbiA9PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICAgIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbilcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udG9Db2w7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNYW55VG9NYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2guZnJvbUNvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGUpXG4gICAgICAgICAgLmpvaW4oXG4gICAgICAgICAgICBsb2FkZXIubWFueUpvaW4udG9UYWJsZSxcbiAgICAgICAgICAgIGAke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRvQ29sfWAsXG4gICAgICAgICAgICBgJHtsb2FkZXIubWFueUpvaW4udG9UYWJsZX0uJHtsb2FkZXIubWFueUpvaW4udG9Db2x9YFxuICAgICAgICAgIClcbiAgICAgICAgICAud2hlcmVJbihpZENvbHVtbiwgZnJvbUlkcylcbiAgICAgICAgICAuc2VsZWN0KHVuaXEoWy4uLmxvYWRlci5zZWxlY3QsIGlkQ29sdW1uXSkpO1xuXG4gICAgICAgIC8vIE1hbnlUb01hbnnsl5DshJwgT25lSm9pbuydtCDsnojripQg6rK97JqwXG4gICAgICAgIGxvYWRlci5vbmVKb2lucy5tYXAoKGpvaW4pID0+IHtcbiAgICAgICAgICBpZiAoam9pbi5qb2luID09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oXG4gICAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09IFwib3V0ZXJcIikge1xuICAgICAgICAgICAgc3ViUS5sZWZ0T3V0ZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0b0NvbCA9IGxvYWRlci5tYW55Sm9pbi50aHJvdWdoLmZyb21Db2w7XG4gICAgICB9XG4gICAgICBzdWJSb3dzID0gYXdhaXQgc3ViUTtcblxuICAgICAgaWYgKGxvYWRlci5sb2FkZXJzKSB7XG4gICAgICAgIC8vIOy2lOqwgCAtTWFueSDsvIDsnbTsiqTqsIAg7J6I64qUIOqyveyasCByZWN1cnNpb24g7LKY66asXG4gICAgICAgIHN1YlJvd3MgPSBhd2FpdCB0aGlzLnVzZUxvYWRlcnMoZGIsIHN1YlJvd3MsIGxvYWRlci5sb2FkZXJzKTtcbiAgICAgIH1cblxuICAgICAgLy8g67aI65+s7JioIHJvd+uTpOydhCDssLjsobBJRCDquLDspIDsnLzroZwg67aE66WYIOuwsOy5mFxuICAgICAgY29uc3Qgc3ViUm93R3JvdXBzID0gZ3JvdXBCeShzdWJSb3dzLCB0b0NvbCk7XG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbbG9hZGVyLmFzXSA9IChzdWJSb3dHcm91cHNbcm93W2xvYWRlci5tYW55Sm9pbi5pZEZpZWxkXV0gPz8gW10pLm1hcChcbiAgICAgICAgICAocikgPT4gb21pdChyLCB0b0NvbClcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIGh5ZHJhdGU8VD4ocm93czogVFtdKTogVFtdIHtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdzogYW55KSA9PiB7XG4gICAgICAvLyBudWxsYWJsZSByZWxhdGlvbuyduCDqsr3smrAg6rSA66Co65CcIO2VhOuTnOqwgCDsoITrtoAgbnVsbOuhnCDsg53shLHrkJjripQg6rKDIOuwqeyngO2VmOuKlCDsvZTrk5xcbiAgICAgIGNvbnN0IG5lc3RlZEtleXMgPSBPYmplY3Qua2V5cyhyb3cpLmZpbHRlcigoa2V5KSA9PiBrZXkuaW5jbHVkZXMoXCJfX1wiKSk7XG4gICAgICBjb25zdCBncm91cHMgPSBncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmtleXMoZ3JvdXBzKS5maWx0ZXIoXG4gICAgICAgIChrZXkpID0+XG4gICAgICAgICAgZ3JvdXBzW2tleV0ubGVuZ3RoID4gMSAmJlxuICAgICAgICAgIGdyb3Vwc1trZXldLmV2ZXJ5KFxuICAgICAgICAgICAgKGZpZWxkKSA9PlxuICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8XG4gICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKVxuICAgICAgICAgIClcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIGlzT2JqZWN0KHJvd1tmaWVsZF1bMF0pKSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHRoaXMuaHlkcmF0ZShyb3dbZmllbGRdKTtcbiAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJ0cyA9IGZpZWxkLnNwbGl0KFwiX19cIik7XG4gICAgICAgIGNvbnN0IG9ialBhdGggPVxuICAgICAgICAgIHBhcnRzWzBdICtcbiAgICAgICAgICBwYXJ0c1xuICAgICAgICAgICAgLnNsaWNlKDEpXG4gICAgICAgICAgICAubWFwKChwYXJ0KSA9PiBgWyR7cGFydH1dYClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuICAgICAgICBzZXQoXG4gICAgICAgICAgcixcbiAgICAgICAgICBvYmpQYXRoLFxuICAgICAgICAgIHJvd1tmaWVsZF0gJiYgQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKVxuICAgICAgICAgICAgPyB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSlcbiAgICAgICAgICAgIDogcm93W2ZpZWxkXVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiByO1xuICAgICAgfSwge30gYXMgYW55KTtcbiAgICAgIG51bGxLZXlzLm1hcCgobnVsbEtleSkgPT4gKGh5ZHJhdGVkW251bGxLZXldID0gbnVsbCkpO1xuXG4gICAgICByZXR1cm4gaHlkcmF0ZWQ7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBydW5TdWJzZXRRdWVyeTxUIGV4dGVuZHMgQmFzZUxpc3RQYXJhbXMsIFUgZXh0ZW5kcyBzdHJpbmc+KHtcbiAgICBwYXJhbXMsXG4gICAgYmFzZVRhYmxlLFxuICAgIHN1YnNldCxcbiAgICBzdWJzZXRRdWVyeSxcbiAgICBidWlsZCxcbiAgICBhZnRlckJ1aWxkLFxuICAgIGRlYnVnLFxuICAgIGRiOiBfZGIsXG4gICAgb3B0aW1pemVDb3VudFF1ZXJ5LFxuICB9OiB7XG4gICAgc3Vic2V0OiBVO1xuICAgIHBhcmFtczogVDtcbiAgICBzdWJzZXRRdWVyeTogU3Vic2V0UXVlcnk7XG4gICAgYnVpbGQ6IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYWZ0ZXJCdWlsZD86IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYmFzZVRhYmxlPzogc3RyaW5nO1xuICAgIGRlYnVnPzogYm9vbGVhbiB8IFwibGlzdFwiIHwgXCJjb3VudFwiO1xuICAgIGRiPzogS25leDtcbiAgICBvcHRpbWl6ZUNvdW50UXVlcnk/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx7XG4gICAgcm93czogYW55W107XG4gICAgdG90YWw/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgc3Vic2V0UXVlcnk6IFN1YnNldFF1ZXJ5O1xuICAgIHFiOiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGRiID0gX2RiID8/IHRoaXMuZ2V0REIoc3Vic2V0LnN0YXJ0c1dpdGgoXCJBXCIpID8gXCJ3XCIgOiBcInJcIik7XG4gICAgYmFzZVRhYmxlID1cbiAgICAgIGJhc2VUYWJsZSA/PyBpbmZsZWN0aW9uLnBsdXJhbGl6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGhpcy5tb2RlbE5hbWUpKTtcbiAgICBjb25zdCBxdWVyeU1vZGUgPVxuICAgICAgcGFyYW1zLnF1ZXJ5TW9kZSA/PyAocGFyYW1zLmlkICE9PSB1bmRlZmluZWQgPyBcImxpc3RcIiA6IFwiYm90aFwiKTtcblxuICAgIGNvbnN0IHsgc2VsZWN0LCB2aXJ0dWFsLCBqb2lucywgbG9hZGVycyB9ID0gc3Vic2V0UXVlcnk7XG4gICAgY29uc3QgcWIgPSBidWlsZCh7XG4gICAgICBxYjogZGIuZnJvbShiYXNlVGFibGUpLFxuICAgICAgZGIsXG4gICAgICBzZWxlY3QsXG4gICAgICBqb2lucyxcbiAgICAgIHZpcnR1YWwsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhcHBseUpvaW5DbGF1c2UgPSAoXG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXIsXG4gICAgICBqb2luczogU3Vic2V0UXVlcnlbXCJqb2luc1wiXVxuICAgICkgPT4ge1xuICAgICAgam9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgIGlmIChqb2luLmpvaW4gPT0gXCJpbm5lclwiKSB7XG4gICAgICAgICAgcWIuaW5uZXJKb2luKFxuICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChqb2luLmpvaW4gPT0gXCJvdXRlclwiKSB7XG4gICAgICAgICAgcWIubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBjb3VudFF1ZXJ5XG4gICAgY29uc3QgdG90YWwgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xvbmVkUWIgPSBxYi5jbG9uZSgpLmNsZWFyKFwib3JkZXJcIikuY2xlYXIoXCJvZmZzZXRcIikuY2xlYXIoXCJsaW1pdFwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG5cbiAgICAgIC8vIG9wdG1pemVDb3VudFF1ZXJ56rCAIHRydWXsnbgg6rK97JqwIOuLpOuluCBjbGF1c2Xsl5Ag7JiB7Zal7J2EIOyjvOyngCDslYrripQg66qo65OgIGpvaW7snYQg7KCc7Jm47ZWoXG4gICAgICBpZiAob3B0aW1pemVDb3VudFF1ZXJ5KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShjbG9uZWRRYi50b1F1ZXJ5KCkpO1xuICAgICAgICBjb25zdCB0YWJsZXMgPSBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlKHBhcnNlZFF1ZXJ5KTtcbiAgICAgICAgLy8gd2hlcmXsoIjsl5Ag7IKs7Jqp65CY64qUIO2FjOydtOu4lOydmCDsobDsnbjsnYQg7JyE7ZW0IOyCrOyaqeuQmOuKlCDthYzsnbTruJRcbiAgICAgICAgY29uc3QgbmVlZFRvSm9pbiA9IHVuaXEoXG4gICAgICAgICAgdGFibGVzLmZsYXRNYXAoKHRhYmxlKSA9PlxuICAgICAgICAgICAgdGFibGUuc3BsaXQoXCJfX1wiKS5tYXAoKHQpID0+IGluZmxlY3Rpb24ucGx1cmFsaXplKHQpKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgYXBwbHlKb2luQ2xhdXNlKFxuICAgICAgICAgIGNsb25lZFFiLFxuICAgICAgICAgIGpvaW5zLmZpbHRlcigoaikgPT4gbmVlZFRvSm9pbi5pbmNsdWRlcyhqLnRhYmxlKSlcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcm9jZXNzZWRRYiA9XG4gICAgICAgIGFmdGVyQnVpbGQ/Lih7XG4gICAgICAgICAgcWI6IGNsb25lZFFiLFxuICAgICAgICAgIGRiLFxuICAgICAgICAgIHNlbGVjdCxcbiAgICAgICAgICBqb2lucyxcbiAgICAgICAgICB2aXJ0dWFsLFxuICAgICAgICB9KSA/PyBjbG9uZWRRYjtcblxuICAgICAgY29uc3QgcGFyc2VkUXVlcnkgPSBwYXJzZXIuYXN0aWZ5KHByb2Nlc3NlZFFiLnRvUXVlcnkoKSk7XG4gICAgICBjb25zdCBxID0gQXJyYXkuaXNBcnJheShwYXJzZWRRdWVyeSkgPyBwYXJzZWRRdWVyeVswXSA6IHBhcnNlZFF1ZXJ5O1xuICAgICAgaWYgKHEudHlwZSAhPT0gXCJzZWxlY3RcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHF1ZXJ5XCIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb3VudFF1ZXJ5ID1cbiAgICAgICAgcS5kaXN0aW5jdCAhPT0gbnVsbFxuICAgICAgICAgID8gY2xvbmVkUWJcbiAgICAgICAgICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAgICAgICAgIC5zZWxlY3QoXG4gICAgICAgICAgICAgICAgZGIucmF3KFxuICAgICAgICAgICAgICAgICAgYENPVU5UKERJU1RJTkNUIFxcYCR7Z2V0VGFibGVOYW1lKHEuY29sdW1uc1swXS5leHByKX1cXGAuXFxgJHtxLmNvbHVtbnNbMF0uZXhwci5jb2x1bW59XFxgKSBhcyB0b3RhbGBcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLmZpcnN0KClcbiAgICAgICAgICA6IGNsb25lZFFiLmNsZWFyKFwic2VsZWN0XCIpLmNvdW50KFwiKlwiLCB7IGFzOiBcInRvdGFsXCIgfSkuZmlyc3QoKTtcbiAgICAgIGNvbnN0IGNvdW50Um93OiB7IHRvdGFsPzogbnVtYmVyIH0gPSBhd2FpdCBjb3VudFF1ZXJ5O1xuXG4gICAgICAvLyBkZWJ1ZzogY291bnRRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImNvdW50XCIpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcbiAgICAgICAgICBcIkRFQlVHOiBjb3VudCBxdWVyeVwiLFxuICAgICAgICAgIGNoYWxrLmJsdWUoY291bnRRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvdW50Um93Py50b3RhbCA/PyAwO1xuICAgIH0pKCk7XG5cbiAgICAvLyBsaXN0UXVlcnlcbiAgICBjb25zdCByb3dzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChxdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIC8vIGxpbWl0LCBvZmZzZXRcbiAgICAgIGlmIChwYXJhbXMubnVtICE9PSAwKSB7XG4gICAgICAgIHFiLmxpbWl0KHBhcmFtcy5udW0hKTtcbiAgICAgICAgcWIub2Zmc2V0KHBhcmFtcy5udW0hICogKHBhcmFtcy5wYWdlISAtIDEpKTtcbiAgICAgIH1cblxuICAgICAgLy8gc2VsZWN0LCByb3dzXG4gICAgICBjb25zdCBjbG9uZWRRYiA9IHFiLmNsb25lKCkuc2VsZWN0KHNlbGVjdCk7XG5cbiAgICAgIC8vIGpvaW5cbiAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuXG4gICAgICBjb25zdCBsaXN0UXVlcnkgPVxuICAgICAgICBhZnRlckJ1aWxkPy4oe1xuICAgICAgICAgIHFiOiBjbG9uZWRRYixcbiAgICAgICAgICBkYixcbiAgICAgICAgICBzZWxlY3QsXG4gICAgICAgICAgam9pbnMsXG4gICAgICAgICAgdmlydHVhbCxcbiAgICAgICAgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGxldCByb3dzID0gYXdhaXQgbGlzdFF1ZXJ5O1xuICAgICAgLy8gZGVidWc6IGxpc3RRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgICAgIFwiREVCVUc6IGxpc3QgcXVlcnlcIixcbiAgICAgICAgICBjaGFsay5ibHVlKGxpc3RRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcm93cyA9IGF3YWl0IHRoaXMudXNlTG9hZGVycyhkYiwgcm93cywgbG9hZGVycyk7XG4gICAgICByb3dzID0gdGhpcy5oeWRyYXRlKHJvd3MpO1xuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSkoKTtcblxuICAgIHJldHVybiB7IHJvd3MsIHRvdGFsLCBzdWJzZXRRdWVyeSwgcWIgfTtcbiAgfVxuXG4gIGdldEpvaW5DbGF1c2UoXG4gICAgZGI6IEtuZXg8YW55LCB1bmtub3duPixcbiAgICBqb2luOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdW251bWJlcl1cbiAgKTogS25leC5SYXc8YW55PiB7XG4gICAgaWYgKCFpc0N1c3RvbUpvaW5DbGF1c2Uoam9pbikpIHtcbiAgICAgIHJldHVybiBkYi5yYXcoYCR7am9pbi5mcm9tfSA9ICR7am9pbi50b31gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRiLnJhdyhqb2luLmN1c3RvbSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0VXBzZXJ0QnVpbGRlcigpOiBVcHNlcnRCdWlsZGVyIHtcbiAgICByZXR1cm4gbmV3IFVwc2VydEJ1aWxkZXIoKTtcbiAgfVxufVxuZXhwb3J0IGNvbnN0IEJhc2VNb2RlbCA9IG5ldyBCYXNlTW9kZWxDbGFzcygpO1xuIl0sIm5hbWVzIjpbIkRhdGVUaW1lIiwiY2h1bmsiLCJncm91cEJ5IiwiaXNPYmplY3QiLCJvbWl0Iiwic2V0IiwidW5pcSIsIkRCIiwiaXNDdXN0b21Kb2luQ2xhdXNlIiwiaW5mbGVjdGlvbiIsImNoYWxrIiwiVXBzZXJ0QnVpbGRlciIsIlNxbFBhcnNlciIsImdldFRhYmxlTmFtZSIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJQdXJpV3JhcHBlciIsIkJhc2VNb2RlbENsYXNzIiwibW9kZWxOYW1lIiwiZ2V0REIiLCJ3aGljaCIsImdldFB1cmkiLCJ0cngiLCJnZXRUcmFuc2FjdGlvbkNvbnRleHQiLCJnZXRUcmFuc2FjdGlvbiIsImRiIiwiZ2V0VXBzZXJ0QnVpbGRlciIsImRlc3Ryb3kiLCJteU5vdyIsInRpbWVzdGFtcCIsImR0IiwidW5kZWZpbmVkIiwibG9jYWwiLCJmcm9tU2Vjb25kcyIsInRvRm9ybWF0IiwiZ2V0SW5zZXJ0ZWRJZHMiLCJ3ZGIiLCJyb3dzIiwidGFibGVOYW1lIiwidW5xS2V5RmllbGRzIiwiY2h1bmtTaXplIiwidW5xS2V5cyIsIndoZXJlSW5GaWVsZCIsInNlbGVjdEZpZWxkIiwibGVuZ3RoIiwicmF3Iiwiam9pbiIsIm1hcCIsInJvdyIsImZpZWxkIiwiY2h1bmtzIiwicmVzdWx0SWRzIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJpZCIsInVzZUxvYWRlcnMiLCJsb2FkZXJzIiwibG9hZGVyIiwic3ViUSIsInN1YlJvd3MiLCJ0b0NvbCIsImZyb21JZHMiLCJtYW55Sm9pbiIsImlkRmllbGQiLCJ0aHJvdWdoIiwiaWRDb2x1bW4iLCJ0b1RhYmxlIiwib25lSm9pbnMiLCJpbm5lckpvaW4iLCJ0YWJsZSIsImFzIiwiZ2V0Sm9pbkNsYXVzZSIsImxlZnRPdXRlckpvaW4iLCJmcm9tQ29sIiwic3ViUm93R3JvdXBzIiwiciIsImh5ZHJhdGUiLCJuZXN0ZWRLZXlzIiwiT2JqZWN0Iiwia2V5cyIsImZpbHRlciIsImtleSIsImluY2x1ZGVzIiwiZ3JvdXBzIiwic3BsaXQiLCJudWxsS2V5cyIsImV2ZXJ5IiwiQXJyYXkiLCJpc0FycmF5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJwYXJ0cyIsIm9ialBhdGgiLCJzbGljZSIsInBhcnQiLCJudWxsS2V5IiwicnVuU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJiYXNlVGFibGUiLCJzdWJzZXQiLCJzdWJzZXRRdWVyeSIsImJ1aWxkIiwiYWZ0ZXJCdWlsZCIsImRlYnVnIiwiX2RiIiwib3B0aW1pemVDb3VudFF1ZXJ5Iiwic3RhcnRzV2l0aCIsInBsdXJhbGl6ZSIsInVuZGVyc2NvcmUiLCJxdWVyeU1vZGUiLCJ2aXJ0dWFsIiwiam9pbnMiLCJxYiIsImZyb20iLCJhcHBseUpvaW5DbGF1c2UiLCJ0b3RhbCIsImNsb25lZFFiIiwiY2xvbmUiLCJjbGVhciIsInBhcnNlciIsIlBhcnNlciIsInBhcnNlZFF1ZXJ5IiwiYXN0aWZ5IiwidG9RdWVyeSIsInRhYmxlcyIsIm5lZWRUb0pvaW4iLCJmbGF0TWFwIiwidCIsImoiLCJwcm9jZXNzZWRRYiIsInEiLCJ0eXBlIiwiRXJyb3IiLCJjb3VudFF1ZXJ5IiwiZGlzdGluY3QiLCJjb2x1bW5zIiwiZXhwciIsImNvbHVtbiIsImZpcnN0IiwiY291bnQiLCJjb3VudFJvdyIsImNvbnNvbGUiLCJibHVlIiwidG9TdHJpbmciLCJudW0iLCJsaW1pdCIsIm9mZnNldCIsInBhZ2UiLCJsaXN0UXVlcnkiLCJ0byIsImN1c3RvbSIsIkJhc2VNb2RlbCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsUUFBUSxRQUFRLFFBQVE7QUFFakMsU0FBU0MsS0FBSyxFQUFFQyxPQUFPLEVBQUVDLFFBQVEsRUFBRUMsSUFBSSxFQUFFQyxHQUFHLEVBQUVDLElBQUksUUFBUSxZQUFZO0FBQ3RFLFNBQW1CQyxFQUFFLFFBQVEsVUFBTztBQUNwQyxTQUFTQyxrQkFBa0IsUUFBMEIsb0JBQWlCO0FBRXRFLE9BQU9DLGdCQUFnQixhQUFhO0FBQ3BDLE9BQU9DLFdBQVcsUUFBUTtBQUMxQixTQUFTQyxhQUFhLFFBQVEsc0JBQW1CO0FBQ2pELE9BQU9DLGVBQWUsa0JBQWtCO0FBQ3hDLFNBQVNDLFlBQVksRUFBRUMsc0JBQXNCLFFBQVEseUJBQXNCO0FBQzNFLFNBQVNDLFdBQVcsUUFBUSxvQkFBaUI7QUFFN0MsT0FBTyxNQUFNQztJQUNKQyxZQUFvQixVQUFVO0lBRXJDLHdCQUF3QixHQUN4QkMsTUFBTUMsS0FBZSxFQUFRO1FBQzNCLE9BQU9aLEdBQUdXLEtBQUssQ0FB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
|
|
390
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCB0eXBlIHsgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBncm91cCwgaXNPYmplY3QsIG9taXQsIHNldCwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IHR5cGUgRGF0YWJhc2VTY2hlbWFFeHRlbmQsIGlzQ3VzdG9tSm9pbkNsYXVzZSwgdHlwZSBTdWJzZXRRdWVyeSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBCYXNlTGlzdFBhcmFtcyB9IGZyb20gXCIuLi91dGlscy9tb2RlbFwiO1xuaW1wb3J0IHsgZ2V0Sm9pblRhYmxlcywgZ2V0VGFibGVOYW1lc0Zyb21XaGVyZSB9IGZyb20gXCIuLi91dGlscy9zcWwtcGFyc2VyXCI7XG5pbXBvcnQgeyBjaHVuayB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHR5cGUge1xuICBFbmhhbmNlck1hcCxcbiAgRXhlY3V0ZVN1YnNldFF1ZXJ5UmVzdWx0LFxuICBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uLFxuICBVbmlvbkV4dHJhY3RlZFRUYWJsZXMsXG59IGZyb20gXCIuL2Jhc2UtbW9kZWwudHlwZXNcIjtcbmltcG9ydCB0eXBlIHsgREJQcmVzZXQgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgUHVyaSB9IGZyb20gXCIuL3B1cmlcIjtcbmltcG9ydCB0eXBlIHsgSW5mZXJBbGxTdWJzZXRzLCBQdXJpTG9hZGVyUXVlcmllcywgUHVyaVN1YnNldEZuIH0gZnJvbSBcIi4vcHVyaS1zdWJzZXQudHlwZXNcIjtcbmltcG9ydCB7IFB1cmlXcmFwcGVyIH0gZnJvbSBcIi4vcHVyaS13cmFwcGVyXCI7XG5pbXBvcnQgeyBVcHNlcnRCdWlsZGVyIH0gZnJvbSBcIi4vdXBzZXJ0LWJ1aWxkZXJcIjtcblxudHlwZSBVbmtub3duREJSZWNvcmQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLyoqXG4gKiDrqqjrk6AgTW9kZWwg7YG0656Y7Iqk7J2YIOq4sOuzuCDtgbTrnpjsiqRcbiAqXG4gKiBAdGVtcGxhdGUgVFN1YnNldEtleSAtIOyEnOu4jOyFiyDtgqQg7Jyg64uI7JioICjsmIg6IFwiQVwiIHwgXCJQXCIgfCBcIlNTXCIpXG4gKiBAdGVtcGxhdGUgVFN1YnNldE1hcHBpbmcgLSDshJzruIzshYvrs4Qg7LWc7KKFIOqysOqzvCDtg4DsnoUg66ek7ZWRXG4gKiBAdGVtcGxhdGUgVFN1YnNldFF1ZXJpZXMgLSDshJzruIzshYsg7L+866asIO2VqOyImCDqsJ3ssrRcbiAqIEB0ZW1wbGF0ZSBUTG9hZGVyUXVlcmllcyAtIOyEnOu4jOyFi+uzhCDroZzrjZQg7L+866asIOuwsOyXtCDqsJ3ssrRcbiAqL1xuZXhwb3J0IGNsYXNzIEJhc2VNb2RlbENsYXNzPFxuICBUU3Vic2V0S2V5IGV4dGVuZHMgc3RyaW5nID0gbmV2ZXIsXG4gIFRTdWJzZXRNYXBwaW5nIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IG5ldmVyLFxuICBUU3Vic2V0UXVlcmllcyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBQdXJpU3Vic2V0Rm4+ID0gbmV2ZXIsXG4gIFRMb2FkZXJRdWVyaWVzIGV4dGVuZHMgUHVyaUxvYWRlclF1ZXJpZXM8VFN1YnNldEtleT4gPSBuZXZlcixcbj4ge1xuICBwdWJsaWMgbW9kZWxOYW1lOiBzdHJpbmcgPSBcIlVua25vd25cIjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgc3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzLFxuICAgIHByb3RlY3RlZCBsb2FkZXJRdWVyaWVzPzogVExvYWRlclF1ZXJpZXMsXG4gICkge31cblxuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCB0aGlzLmdldFVwc2VydEJ1aWxkZXIoKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCkge1xuICAgIHJldHVybiBEQi5kZXN0cm95KCk7XG4gIH1cblxuICBhc3luYyBnZXRJbnNlcnRlZElkcyhcbiAgICB3ZGI6IEtuZXgsXG4gICAgcm93czogVW5rbm93bkRCUmVjb3JkW10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgdW5xS2V5RmllbGRzOiBzdHJpbmdbXSxcbiAgICBjaHVua1NpemU6IG51bWJlciA9IDUwMCxcbiAgKSB7XG4gICAgaWYgKCF3ZGIpIHtcbiAgICAgIHdkYiA9IHRoaXMuZ2V0REIoXCJ3XCIpO1xuICAgIH1cblxuICAgIGxldCB1bnFLZXlzOiBzdHJpbmdbXTtcbiAgICBsZXQgd2hlcmVJbkZpZWxkOiBzdHJpbmcgfCBLbmV4LlJhdztcbiAgICBsZXQgc2VsZWN0RmllbGQ6IHN0cmluZztcblxuICAgIGlmICh1bnFLZXlGaWVsZHMubGVuZ3RoID4gMSkge1xuICAgICAgd2hlcmVJbkZpZWxkID0gd2RiLnJhdyhgQ09OQ0FUX1dTKCdfJywgJyR7dW5xS2V5RmllbGRzLmpvaW4oXCIsXCIpfScpYCk7XG4gICAgICBzZWxlY3RGaWVsZCA9IGAke3doZXJlSW5GaWVsZH0gYXMgdG1wVWlkYDtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiB1bnFLZXlGaWVsZHMubWFwKChmaWVsZCkgPT4gcm93W2ZpZWxkXSkuam9pbihcIl9cIikpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICBzZWxlY3RGaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbdW5xS2V5RmllbGRzWzBdXSBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIGxldCByZXN1bHRJZHM6IG51bWJlcltdID0gW107XG4gICAgZm9yIChjb25zdCBpdGVtcyBvZiBjaHVuayh1bnFLZXlzLCBjaHVua1NpemUpKSB7XG4gICAgICBjb25zdCBkYlJvd3MgPSBhd2FpdCB3ZGIodGFibGVOYW1lKVxuICAgICAgICAuc2VsZWN0KFwiaWRcIiwgd2RiLnJhdyhzZWxlY3RGaWVsZCkpXG4gICAgICAgIC53aGVyZUluKHdoZXJlSW5GaWVsZCBhcyBzdHJpbmcsIGl0ZW1zKTtcbiAgICAgIHJlc3VsdElkcyA9IHJlc3VsdElkcy5jb25jYXQoXG4gICAgICAgIGRiUm93cy5tYXAoKGRiUm93OiBVbmtub3duREJSZWNvcmQpID0+IHBhcnNlSW50KFN0cmluZyhkYlJvdy5pZCkpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdElkcztcbiAgfVxuXG4gIC8qKlxuICAgKiDtirnsoJUg7ISc67iM7IWL7JeQIOuMgO2VnCDsv7zrpqwg67mM642UIO2ajeuTnVxuICAgKlxuICAgKiBAcmV0dXJucyBxYiAtIOy/vOumrCDruYzrjZQgKOyhsOqxtCDstpTqsIDsmqkpXG4gICAqIEByZXR1cm5zIG9uU3Vic2V0IC0g7Yq57KCVIOyEnOu4jOyFiyDsoITsmqkg7YOA7J6F7J20IO2VhOyalO2VoCDrlYwg7IKs7JqpXG4gICAqL1xuICBnZXRTdWJzZXRRdWVyaWVzPFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFQpIHtcbiAgICBpZiAoIXRoaXMuc3Vic2V0UXVlcmllcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3Vic2V0UXVlcmllcyBpcyBub3QgZGVmaW5lZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBwdXJpV3JhcHBlciA9IG5ldyBQdXJpV3JhcHBlcih0aGlzLmdldERCKFwiclwiKSwgbmV3IFVwc2VydEJ1aWxkZXIoKSk7XG4gICAgY29uc3QgcWIgPSB0aGlzLnN1YnNldFF1ZXJpZXNbc3Vic2V0XT8uKHB1cmlXcmFwcGVyKTtcblxuICAgIC8vIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiDri6jsnbwg7YWM7J2067iUIOy7rOufvCDsoJHqt7wg67Cp7KeA7JqpIOuniOy7pFxuICAgIHR5cGUgUUJUYWJsZXMgPSBVbmlvbkV4dHJhY3RlZFRUYWJsZXM8VFN1YnNldEtleSwgVFN1YnNldFF1ZXJpZXM+ICYge1xuICAgICAgTm9uQWxsb3dlZEFzU2luZ2xlVGFibGU6IHsgX19mdWxsdGV4dF9fOiB0cnVlIH07XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICBxYjogcWIgYXMgdW5rbm93biBhcyBQdXJpPERhdGFiYXNlU2NoZW1hRXh0ZW5kLCBRQlRhYmxlcywge30+LFxuICAgICAgb25TdWJzZXQ6ICgoX3N1YnNldDogVFN1YnNldEtleSB8IHJlYWRvbmx5IFRTdWJzZXRLZXlbXSkgPT4gcWIpIGFzIHtcbiAgICAgICAgLy8g64uo7J28IO2CpFxuICAgICAgICA8UyBleHRlbmRzIFRTdWJzZXRLZXk+KHN1YnNldDogUyk6IFJldHVyblR5cGU8VFN1YnNldFF1ZXJpZXNbU10+O1xuICAgICAgICAvLyDtgqQg67Cw7Je0IC0+IOq1kOynke2VqSDrsJjtmZhcbiAgICAgICAgPEFyciBleHRlbmRzIHJlYWRvbmx5IFRTdWJzZXRLZXlbXT4oXG4gICAgICAgICAgc3Vic2V0czogWy4uLkFycl0sXG4gICAgICAgICk6IFJlc29sdmVTdWJzZXRJbnRlcnNlY3Rpb248QXJyLCBUU3Vic2V0UXVlcmllcz47XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRW5oYW5jZXIg6rCd7LK0IOyDneyEsSDtl6ztjbxcbiAgICog7YOA7J6FIOqygOymnSDrsI8g7LaU66Gg7J2EIOuPhOyZgOykjFxuICAgKi9cbiAgY3JlYXRlRW5oYW5jZXJzPFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihcbiAgICBlbmhhbmNlcnM6IEVuaGFuY2VyTWFwPFQsIEluZmVyQWxsU3Vic2V0czxUU3Vic2V0UXVlcmllcywgVExvYWRlclF1ZXJpZXM+LCBUU3Vic2V0TWFwcGluZz4sXG4gICkge1xuICAgIHJldHVybiBlbmhhbmNlcnM7XG4gIH1cblxuICAvKipcbiAgICog7ISc67iM7IWLIOy/vOumrCDsi6TtlolcbiAgICpcbiAgICogMS4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDIuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiAzLiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA0LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gID4oXG4gICAgcGFyYW1zOiB7XG4gICAgICBzdWJzZXQ6IFQ7XG4gICAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PjtcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBudW0/OiBudW1iZXI7XG4gICAgICAgIHBhZ2U/OiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFwibGlzdFwiIHwgXCJjb3VudFwiIHwgXCJib3RoXCI7XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz4sXG4gICk6IFByb21pc2U8RXhlY3V0ZVN1YnNldFF1ZXJ5UmVzdWx0PFRTdWJzZXRNYXBwaW5nLCBUPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIGlmICghcXVlcnlQYXJhbXMubnVtIHx8ICFxdWVyeVBhcmFtcy5wYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJudW0gYW5kIHBhZ2UgYXJlIHJlcXVpcmVkXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgbnVtLCBwYWdlIH0gPSBxdWVyeVBhcmFtcztcblxuICAgIC8vIENPVU5UIOy/vOumrCDsi6TtlolcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IHJvd3MgPSAoYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb21wdXRlZFJvd3MubWFwKChyb3cpID0+IGVuaGFuY2VyPy4ocm93KSA/PyByb3cpLFxuICAgICkpIGFzIFRTdWJzZXRNYXBwaW5nW1RdW107XG5cbiAgICByZXR1cm4geyByb3dzLCB0b3RhbCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENPVU5UIOy/vOumrCDsi6TtlokgKOuCtOu2gCDrqZTshJzrk5wpXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVDb3VudFF1ZXJ5KFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgZGVidWc6IGJvb2xlYW4sXG4gICAgb3B0aW1pemVDb3VudFF1ZXJ5OiBib29sZWFuLFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGlmIChwYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgY29uc3QgY291bnRQdXJpID0gcWIuY2xvbmUoKS5jbGVhcihcIm9yZGVyXCIpLmNsZWFyKFwibGltaXRcIikuY2xlYXIoXCJvZmZzZXRcIik7XG5cbiAgICBpZiAob3B0aW1pemVDb3VudFF1ZXJ5KSB7XG4gICAgICBjb25zdCB7IGRlZmF1bHQ6IFNxbFBhcnNlciB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZS1zcWwtcGFyc2VyXCIpO1xuICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFNxbFBhcnNlci5QYXJzZXIoKTtcbiAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShjb3VudFB1cmkudG9RdWVyeSgpLCB7XG4gICAgICAgIGRhdGFiYXNlOiBTb25hbXUuY29uZmlnLmRhdGFiYXNlLmRhdGFiYXNlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGxlZnRKb2luVGFibGVzID0gZ2V0Sm9pblRhYmxlcyhwYXJzZWRRdWVyeSwgW1wiTEVGVCBKT0lOXCJdKTtcbiAgICAgIGNvbnN0IHdoZXJlVGFibGVzID0gZ2V0VGFibGVOYW1lc0Zyb21XaGVyZShwYXJzZWRRdWVyeSk7XG5cbiAgICAgIGNvbnN0IHRhYmxlc1RvUmVtb3ZlID0gbGVmdEpvaW5UYWJsZXMuZmlsdGVyKChqKSA9PiAhd2hlcmVUYWJsZXMuaW5jbHVkZXMoaikpO1xuICAgICAgdGFibGVzVG9SZW1vdmUuZm9yRWFjaCgodGFibGUpID0+IHtcbiAgICAgICAgY291bnRQdXJpLmNsZWFySm9pbih0YWJsZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBDT1VOVCgqKeuhnCDsoITssrQg66CI7L2U65OcIOyImOulvCDqs4TsgrBcbiAgICAvLyBUT0RPOiBxYuydmCBESVNUSU5DVOqwgCDsnojripQg6rK97JqwIOyymOumrO2VtOyVvCDtlahcbiAgICBjb25zdCBjb3VudFJlc3VsdDogeyB0b3RhbD86IG51bWJlciB9ID0gYXdhaXQgY291bnRQdXJpXG4gICAgICAuY2xlYXIoXCJzZWxlY3RcIilcbiAgICAgIC5zZWxlY3QoeyB0b3RhbDogUHVyaS5yYXdOdW1iZXIoYENPVU5UKCopOjppbnRlZ2VyYCkgfSlcbiAgICAgIC5maXJzdCgpO1xuXG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBjb3VudFB1cmkuZGVidWcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY291bnRSZXN1bHQ/LnRvdGFsID8/IDA7XG4gIH1cblxuICAvKipcbiAgICogTElTVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlTGlzdFF1ZXJ5PFQgZXh0ZW5kcyBUU3Vic2V0S2V5PihcbiAgICBzdWJzZXQ6IFQsXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgcGFyYW1zOiB7IHF1ZXJ5TW9kZT86IFwibGlzdFwiIHwgXCJjb3VudFwiIHwgXCJib3RoXCIgfSxcbiAgICBudW06IG51bWJlcixcbiAgICBwYWdlOiBudW1iZXIsXG4gICAgZGVidWc6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8YW55W10+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJjb3VudFwiKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgbGV0IHVubG9hZGVkUm93cyA9IChhd2FpdCBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKSkgYXMgYW55W107XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIHFiLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgLy8g66Gc642UIOyymOumrFxuICAgIGNvbnN0IGxvYWRlcnMgPSAodGhpcy5sb2FkZXJRdWVyaWVzIGFzIGFueSlbc3Vic2V0XTtcbiAgICBpZiAobG9hZGVycyAmJiBBcnJheS5pc0FycmF5KGxvYWRlcnMpKSB7XG4gICAgICB1bmxvYWRlZFJvd3MgPSBhd2FpdCB0aGlzLnByb2Nlc3NMb2FkZXJzKHVubG9hZGVkUm93cywgbG9hZGVycywgZGVidWcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmh5ZHJhdGUodW5sb2FkZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDsnqzqt4DsoIEg66Gc642UIOyymOumrFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTG9hZGVycyhyb3dzOiBhbnlbXSwgbG9hZGVyczogYW55W10sIGRlYnVnOiBib29sZWFuKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIGZvciAoY29uc3QgcmVzb2x2ZUxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBjb25zdCB7IGFzLCByZWZJZCwgcWI6IHJlc29sdmVMb2FkZXJRYkZuLCBsb2FkZXJzOiBuZXN0ZWRMb2FkZXJzIH0gPSByZXNvbHZlTG9hZGVyO1xuXG4gICAgICBjb25zdCByZXNvbHZlTG9hZGVyUWIgPSByZXNvbHZlTG9hZGVyUWJGbihcbiAgICAgICAgbmV3IFB1cmlXcmFwcGVyKHRoaXMuZ2V0REIoXCJyXCIpLCBuZXcgVXBzZXJ0QnVpbGRlcigpKSxcbiAgICAgICAgcm93cy5tYXAoKHJvdykgPT4gcm93W3JlZklkXSksXG4gICAgICApO1xuXG4gICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgcmVzb2x2ZUxvYWRlclFiLmRlYnVnKCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBsb2FkZWRSb3dzID0gKGF3YWl0IHJlc29sdmVMb2FkZXJRYikgYXMgYW55W107XG5cbiAgICAgIC8vIOykkeyyqSBsb2FkZXJz6rCAIOyeiOycvOuptCDsnqzqt4Ag7LKY66asXG4gICAgICBpZiAobmVzdGVkTG9hZGVycyAmJiBuZXN0ZWRMb2FkZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnMobG9hZGVkUm93cywgbmVzdGVkTG9hZGVycywgZGVidWcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdWJSb3dHcm91cHMgPSBncm91cChsb2FkZWRSb3dzLCAocm93KSA9PiByb3cucmVmSWQpO1xuXG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbcmVmSWRdXSA/PyBbXSkubWFwKChyKSA9PiBvbWl0KHIsIFtcInJlZklkXCJdKSk7XG4gICAgICAgIHJldHVybiByb3c7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGF0IOugiOy9lOuTnOulvCDspJHssqkg6rCd7LK066GcIOuzgO2ZmFxuICAgKlxuICAgKiAtIGB1c2VyX19uYW1lYCDihpIgYHsgdXNlcjogeyBuYW1lIH0gfWBcbiAgICogLSBudWxsYWJsZSByZWxhdGlvbuydmCDqsr3smrAg66qo65OgIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsnpDssrTrpbwgbnVsbOuhnFxuICAgKi9cbiAgaHlkcmF0ZTxUIGV4dGVuZHMgVW5rbm93bkRCUmVjb3JkPihyb3dzOiBUW10pOiBUW10ge1xuICAgIHJldHVybiByb3dzLm1hcCgocm93OiBUKSA9PiB7XG4gICAgICAvLyBudWxsYWJsZSByZWxhdGlvbiDsspjrpqw6IOq0gOugqCDtlYTrk5zqsIAg7KCE67aAIG51bGzsnbgg6rK97JqwIOuwqeyngFxuICAgICAgY29uc3QgbmVzdGVkS2V5cyA9IE9iamVjdC5rZXlzKHJvdykuZmlsdGVyKChrZXkpID0+IGtleS5pbmNsdWRlcyhcIl9fXCIpKTtcbiAgICAgIGNvbnN0IGdyb3VwcyA9IE9iamVjdC5ncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBzKVxuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgIChbXywgZGF0YV0pID0+XG4gICAgICAgICAgICBkYXRhICYmXG4gICAgICAgICAgICBkYXRhLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgICAgIGRhdGEuZXZlcnkoXG4gICAgICAgICAgICAgIChmaWVsZCkgPT5cbiAgICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8IChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKSxcbiAgICAgICAgICAgICksXG4gICAgICAgIClcbiAgICAgICAgLm1hcCgoW2tleV0pID0+IGtleSk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIC8vIOydvOuwmCDtlYTrk5w6IOuwsOyXtCDrgrQg6rCd7LK066m0IOyerOq3gCBoeWRyYXRlXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSkpIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7KSR7LKpIO2VhOuTnCDsspjrpqw6IHVzZXJfX25hbWUg4oaSIHVzZXJbbmFtZV1cbiAgICAgICAgY29uc3QgcGFydHMgPSBmaWVsZC5zcGxpdChcIl9fXCIpO1xuICAgICAgICBjb25zdCBvYmpQYXRoID1cbiAgICAgICAgICBwYXJ0c1swXSArXG4gICAgICAgICAgcGFydHNcbiAgICAgICAgICAgIC5zbGljZSgxKVxuICAgICAgICAgICAgLm1hcCgocGFydCkgPT4gYFske3BhcnR9XWApXG4gICAgICAgICAgICAuam9pbihcIlwiKTtcblxuICAgICAgICByID0gc2V0KFxuICAgICAgICAgIHIsXG4gICAgICAgICAgb2JqUGF0aCxcbiAgICAgICAgICByb3dbZmllbGRdICYmIEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSlcbiAgICAgICAgICAgID8gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pXG4gICAgICAgICAgICA6IHJvd1tmaWVsZF0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LCB7fSBhcyBVbmtub3duREJSZWNvcmQpO1xuXG4gICAgICAvLyBudWxsIHJlbGF0aW9uIOyymOumrFxuICAgICAgbnVsbEtleXMuZm9yRWFjaCgobnVsbEtleSkgPT4ge1xuICAgICAgICBoeWRyYXRlZFtudWxsS2V5XSA9IG51bGw7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGh5ZHJhdGVkO1xuICAgIH0pIGFzIFRbXTtcbiAgfVxuXG4gIC8vIExlZ2FjeSBTdWJzZXRRdWVyeSDsi6TtlokgKFB1cmkg64+E7J6FIOyghCDtmLjtmZjsmqkpXG4gIGFzeW5jIHJ1blN1YnNldFF1ZXJ5PFQgZXh0ZW5kcyBCYXNlTGlzdFBhcmFtcywgVSBleHRlbmRzIHN0cmluZz4oe1xuICAgIHBhcmFtcyxcbiAgICBiYXNlVGFibGUsXG4gICAgc3Vic2V0LFxuICAgIHN1YnNldFF1ZXJ5LFxuICAgIGJ1aWxkLFxuICAgIGFmdGVyQnVpbGQsXG4gICAgZGVidWcsXG4gICAgZGI6IF9kYixcbiAgICBvcHRpbWl6ZUNvdW50UXVlcnksXG4gIH06IHtcbiAgICBzdWJzZXQ6IFU7XG4gICAgcGFyYW1zOiBUO1xuICAgIHN1YnNldFF1ZXJ5OiBTdWJzZXRRdWVyeTtcbiAgICBidWlsZDogKGJ1aWxkUGFyYW1zOiB7XG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBkYjogS25leDtcbiAgICAgIHNlbGVjdDogKHN0cmluZyB8IEtuZXguUmF3KVtdO1xuICAgICAgam9pbnM6IFN1YnNldFF1ZXJ5W1wiam9pbnNcIl07XG4gICAgICB2aXJ0dWFsOiBzdHJpbmdbXTtcbiAgICB9KSA9PiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgICBhZnRlckJ1aWxkPzogKGJ1aWxkUGFyYW1zOiB7XG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBkYjogS25leDtcbiAgICAgIHNlbGVjdDogKHN0cmluZyB8IEtuZXguUmF3KVtdO1xuICAgICAgam9pbnM6IFN1YnNldFF1ZXJ5W1wiam9pbnNcIl07XG4gICAgICB2aXJ0dWFsOiBzdHJpbmdbXTtcbiAgICB9KSA9PiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgICBiYXNlVGFibGU/OiBzdHJpbmc7XG4gICAgZGVidWc/OiBib29sZWFuIHwgXCJsaXN0XCIgfCBcImNvdW50XCI7XG4gICAgZGI/OiBLbmV4O1xuICAgIG9wdGltaXplQ291bnRRdWVyeT86IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPHtcbiAgICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFB1cmkg64+E7J6FIOyghOq5jOyngCBhbnnroZwg7Jyg7KeAXG4gICAgcm93czogYW55W107XG4gICAgdG90YWw/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgc3Vic2V0UXVlcnk6IFN1YnNldFF1ZXJ5O1xuICAgIHFiOiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGNoYWxrID0gKGF3YWl0IGltcG9ydChcImNoYWxrXCIpKS5kZWZhdWx0O1xuICAgIGNvbnN0IFNxbFBhcnNlciA9IChhd2FpdCBpbXBvcnQoXCJub2RlLXNxbC1wYXJzZXJcIikpLmRlZmF1bHQ7XG4gICAgY29uc3QgeyBnZXRUYWJsZU5hbWUsIGdldFRhYmxlTmFtZXNGcm9tV2hlcmUgfSA9IGF3YWl0IGltcG9ydChcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIik7XG5cbiAgICBjb25zdCBkYiA9IF9kYiA/PyB0aGlzLmdldERCKHN1YnNldC5zdGFydHNXaXRoKFwiQVwiKSA/IFwid1wiIDogXCJyXCIpO1xuICAgIGJhc2VUYWJsZSA9IGJhc2VUYWJsZSA/PyBpbmZsZWN0aW9uLnBsdXJhbGl6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGhpcy5tb2RlbE5hbWUpKTtcbiAgICBjb25zdCBxdWVyeU1vZGUgPSBwYXJhbXMucXVlcnlNb2RlID8/IChwYXJhbXMuaWQgIT09IHVuZGVmaW5lZCA/IFwibGlzdFwiIDogXCJib3RoXCIpO1xuXG4gICAgY29uc3QgeyBzZWxlY3QsIHZpcnR1YWwsIGpvaW5zLCBsb2FkZXJzIH0gPSBzdWJzZXRRdWVyeTtcbiAgICBjb25zdCBxYiA9IGJ1aWxkKHtcbiAgICAgIHFiOiBkYi5mcm9tKGJhc2VUYWJsZSksXG4gICAgICBkYixcbiAgICAgIHNlbGVjdCxcbiAgICAgIGpvaW5zLFxuICAgICAgdmlydHVhbCxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFwcGx5Sm9pbkNsYXVzZSA9IChxYjogS25leC5RdWVyeUJ1aWxkZXIsIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdKSA9PiB7XG4gICAgICBqb2lucy5mb3JFYWNoKChqb2luKSA9PiB7XG4gICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgIHFiLmlubmVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICBxYi5sZWZ0T3V0ZXJKb2luKGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLCB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIGNvdW50UXVlcnlcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICBpZiAocXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjbG9uZWRRYiA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcIm9mZnNldFwiKS5jbGVhcihcImxpbWl0XCIpO1xuICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFNxbFBhcnNlci5QYXJzZXIoKTtcblxuICAgICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY2xvbmVkUWIudG9RdWVyeSgpLCB7XG4gICAgICAgICAgZGF0YWJhc2U6IFNvbmFtdS5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB0YWJsZXMgPSBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlKHBhcnNlZFF1ZXJ5KTtcbiAgICAgICAgY29uc3QgbmVlZFRvSm9pbiA9IHVuaXF1ZShcbiAgICAgICAgICB0YWJsZXMuZmxhdE1hcCgodGFibGUpID0+IHRhYmxlLnNwbGl0KFwiX19cIikubWFwKCh0KSA9PiBpbmZsZWN0aW9uLnBsdXJhbGl6ZSh0KSkpLFxuICAgICAgICApO1xuICAgICAgICBhcHBseUpvaW5DbGF1c2UoXG4gICAgICAgICAgY2xvbmVkUWIsXG4gICAgICAgICAgam9pbnMuZmlsdGVyKChqKSA9PiBuZWVkVG9Kb2luLmluY2x1ZGVzKGoudGFibGUpKSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcm9jZXNzZWRRYiA9IGFmdGVyQnVpbGQ/Lih7IHFiOiBjbG9uZWRRYiwgZGIsIHNlbGVjdCwgam9pbnMsIHZpcnR1YWwgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShwcm9jZXNzZWRRYi50b1F1ZXJ5KCksIHtcbiAgICAgICAgZGF0YWJhc2U6IFNvbmFtdS5jb25maWcuZGF0YWJhc2UuZGF0YWJhc2UsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHEgPSBBcnJheS5pc0FycmF5KHBhcnNlZFF1ZXJ5KSA/IHBhcnNlZFF1ZXJ5WzBdIDogcGFyc2VkUXVlcnk7XG4gICAgICBpZiAocS50eXBlICE9PSBcInNlbGVjdFwiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgcXVlcnlcIik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvdW50UXVlcnkgPVxuICAgICAgICBxLmRpc3RpbmN0ICE9PSBudWxsXG4gICAgICAgICAgPyBjbG9uZWRRYlxuICAgICAgICAgICAgICAuY2xlYXIoXCJzZWxlY3RcIilcbiAgICAgICAgICAgICAgLnNlbGVjdChcbiAgICAgICAgICAgICAgICBkYi5yYXcoXG4gICAgICAgICAgICAgICAgICBgQ09VTlQoRElTVElOQ1QgXFxgJHtnZXRUYWJsZU5hbWUocS5jb2x1bW5zWzBdLmV4cHIpfVxcYC5cXGAke3EuY29sdW1uc1swXS5leHByLmNvbHVtbn1cXGApIGFzIHRvdGFsYCxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5maXJzdCgpXG4gICAgICAgICAgOiBjbG9uZWRRYi5jbGVhcihcInNlbGVjdFwiKS5jb3VudChcIipcIiwgeyBhczogXCJ0b3RhbFwiIH0pLmZpcnN0KCk7XG4gICAgICBjb25zdCBjb3VudFJvdzogeyB0b3RhbD86IG51bWJlciB9ID0gYXdhaXQgY291bnRRdWVyeTtcblxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImNvdW50XCIpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkRFQlVHOiBjb3VudCBxdWVyeVwiLCBjaGFsay5ibHVlKGNvdW50UXVlcnkudG9RdWVyeSgpLnRvU3RyaW5nKCkpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvdW50Um93Py50b3RhbCA/PyAwO1xuICAgIH0pKCk7XG5cbiAgICAvLyBsaXN0UXVlcnlcbiAgICBjb25zdCByb3dzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChxdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMubnVtICE9PSAwKSB7XG4gICAgICAgIGFzc2VydChwYXJhbXMubnVtKTtcbiAgICAgICAgcWIubGltaXQocGFyYW1zLm51bSk7XG4gICAgICAgIHFiLm9mZnNldChwYXJhbXMubnVtICogKChwYXJhbXMucGFnZSA/PyAxKSAtIDEpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xvbmVkUWIgPSBxYi5jbG9uZSgpLnNlbGVjdChzZWxlY3QpO1xuICAgICAgYXBwbHlKb2luQ2xhdXNlKGNsb25lZFFiLCBqb2lucyk7XG5cbiAgICAgIGNvbnN0IGxpc3RRdWVyeSA9IGFmdGVyQnVpbGQ/Lih7IHFiOiBjbG9uZWRRYiwgZGIsIHNlbGVjdCwgam9pbnMsIHZpcnR1YWwgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGxldCByb3dzID0gYXdhaXQgbGlzdFF1ZXJ5O1xuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKFwiREVCVUc6IGxpc3QgcXVlcnlcIiwgY2hhbGsuYmx1ZShsaXN0UXVlcnkudG9RdWVyeSgpLnRvU3RyaW5nKCkpKTtcbiAgICAgIH1cblxuICAgICAgcm93cyA9IGF3YWl0IHRoaXMudXNlTG9hZGVycyhkYiwgcm93cywgbG9hZGVycyk7XG4gICAgICByb3dzID0gdGhpcy5oeWRyYXRlKHJvd3MpO1xuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSkoKTtcblxuICAgIHJldHVybiB7IHJvd3MsIHRvdGFsLCBzdWJzZXRRdWVyeSwgcWIgfTtcbiAgfVxuXG4gIC8vIExlZ2FjeSBMb2FkZXIg7LKY66asIChQdXJpIOuPhOyehSDsoIQg7Zi47ZmY7JqpKVxuICBhc3luYyB1c2VMb2FkZXJzKGRiOiBLbmV4LCByb3dzOiBVbmtub3duREJSZWNvcmRbXSwgbG9hZGVyczogU3Vic2V0UXVlcnlbXCJsb2FkZXJzXCJdKSB7XG4gICAgaWYgKGxvYWRlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gcm93cztcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBsZXQgc3ViUTogS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgICBsZXQgc3ViUm93czogVW5rbm93bkRCUmVjb3JkW107XG4gICAgICBsZXQgdG9Db2w6IHN0cmluZztcblxuICAgICAgY29uc3QgZnJvbUlkcyA9IHJvd3MubWFwKChyb3cpID0+IHJvd1tsb2FkZXIubWFueUpvaW4uaWRGaWVsZF0pO1xuXG4gICAgICBpZiAobG9hZGVyLm1hbnlKb2luLnRocm91Z2ggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBIYXNNYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRvVGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRvQ29sfWA7XG4gICAgICAgIHN1YlEgPSBkYihsb2FkZXIubWFueUpvaW4udG9UYWJsZSlcbiAgICAgICAgICAud2hlcmVJbihpZENvbHVtbiBhcyBzdHJpbmcsIGZyb21JZHMgYXMgc3RyaW5nW10pXG4gICAgICAgICAgLnNlbGVjdChbLi4ubG9hZGVyLnNlbGVjdCwgaWRDb2x1bW5dKTtcblxuICAgICAgICBsb2FkZXIub25lSm9pbnMuZm9yRWFjaCgoam9pbikgPT4ge1xuICAgICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbikpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udG9Db2w7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNYW55VG9NYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2guZnJvbUNvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGUpXG4gICAgICAgICAgLmpvaW4oXG4gICAgICAgICAgICBsb2FkZXIubWFueUpvaW4udG9UYWJsZSxcbiAgICAgICAgICAgIGAke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRvQ29sfWAsXG4gICAgICAgICAgICBgJHtsb2FkZXIubWFueUpvaW4udG9UYWJsZX0uJHtsb2FkZXIubWFueUpvaW4udG9Db2x9YCxcbiAgICAgICAgICApXG4gICAgICAgICAgLndoZXJlSW4oaWRDb2x1bW4gYXMgc3RyaW5nLCBmcm9tSWRzIGFzIHN0cmluZ1tdKVxuICAgICAgICAgIC5zZWxlY3QodW5pcXVlKFsuLi5sb2FkZXIuc2VsZWN0LCBpZENvbHVtbl0pKTtcblxuICAgICAgICBsb2FkZXIub25lSm9pbnMuZm9yRWFjaCgoam9pbikgPT4ge1xuICAgICAgICAgIGlmIChqb2luLmpvaW4gPT09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbikpO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCwgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udGhyb3VnaC5mcm9tQ29sO1xuICAgICAgfVxuICAgICAgc3ViUm93cyA9IGF3YWl0IHN1YlE7XG5cbiAgICAgIGlmIChsb2FkZXIubG9hZGVycykge1xuICAgICAgICBzdWJSb3dzID0gYXdhaXQgdGhpcy51c2VMb2FkZXJzKGRiLCBzdWJSb3dzLCBsb2FkZXIubG9hZGVycyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YlJvd0dyb3VwcyA9IGdyb3VwKHN1YlJvd3MsIChyb3cpID0+IHJvd1t0b0NvbF0gYXMgc3RyaW5nKTtcbiAgICAgIHJvd3MgPSByb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvd1tsb2FkZXIuYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbbG9hZGVyLm1hbnlKb2luLmlkRmllbGRdIGFzIHN0cmluZ10gPz8gW10pLm1hcCgocikgPT5cbiAgICAgICAgICBvbWl0KHIsIFt0b0NvbF0pLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcm93O1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiByb3dzO1xuICB9XG5cbiAgZ2V0Sm9pbkNsYXVzZShkYjogS25leDxhbnksIHVua25vd24+LCBqb2luOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdW251bWJlcl0pOiBLbmV4LlJhdzxhbnk+IHtcbiAgICBpZiAoIWlzQ3VzdG9tSm9pbkNsYXVzZShqb2luKSkge1xuICAgICAgcmV0dXJuIGRiLnJhdyhgJHtqb2luLmZyb219ID0gJHtqb2luLnRvfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZGIucmF3KGpvaW4uY3VzdG9tKTtcbiAgICB9XG4gIH1cblxuICBnZXRVcHNlcnRCdWlsZGVyKCk6IFVwc2VydEJ1aWxkZXIge1xuICAgIHJldHVybiBuZXcgVXBzZXJ0QnVpbGRlcigpO1xuICB9XG59XG5cbi8qKlxuICogRW5oYW5jZXIg7YyM652866+47YSwIOyhsOqxtOu2gCDtg4DsnoVcbiAqIFJlcXVpcmVkRW5oYW5jZXJLZXlz6rCAIOyXhuycvOuptCBlbmhhbmNlcnMg7ISg7YOd7KCBLCDsnojsnLzrqbQg7ZWE7IiYXG4gKi9cbnR5cGUgRW5oYW5jZXJQYXJhbTxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuPiA9IFtSZXF1aXJlZEVuaGFuY2VyS2V5czxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz5dIGV4dGVuZHMgW25ldmVyXVxuICA/IHsgZW5oYW5jZXJzPzogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+IH1cbiAgOiB7IGVuaGFuY2VyczogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+IH07XG5cbnR5cGUgUmVxdWlyZWRFbmhhbmNlcktleXM8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55Pixcbj4gPSB7XG4gIFtLIGluIFRTdWJzZXRLZXldOiBUQ29tcHV0ZWRSZXN1bHRzW0tdIGV4dGVuZHMgVFN1YnNldE1hcHBpbmdbS10gPyBuZXZlciA6IEs7XG59W1RTdWJzZXRLZXldO1xuXG5leHBvcnQgY29uc3QgQmFzZU1vZGVsID0gbmV3IEJhc2VNb2RlbENsYXNzKCk7XG4iXSwibmFtZXMiOlsiYXNzZXJ0IiwiaW5mbGVjdGlvbiIsImdyb3VwIiwiaXNPYmplY3QiLCJvbWl0Iiwic2V0IiwidW5pcXVlIiwiU29uYW11IiwiaXNDdXN0b21Kb2luQ2xhdXNlIiwiZ2V0Sm9pblRhYmxlcyIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJjaHVuayIsIkRCIiwiUHVyaSIsIlB1cmlXcmFwcGVyIiwiVXBzZXJ0QnVpbGRlciIsIkJhc2VNb2RlbENsYXNzIiwibW9kZWxOYW1lIiwic3Vic2V0UXVlcmllcyIsImxvYWRlclF1ZXJpZXMiLCJnZXREQiIsIndoaWNoIiwiZ2V0UHVyaSIsInRyeCIsImdldFRyYW5zYWN0aW9uQ29udGV4dCIsImdldFRyYW5zYWN0aW9uIiwiZGIiLCJnZXRVcHNlcnRCdWlsZGVyIiwiZGVzdHJveSIsImdldEluc2VydGVkSWRzIiwid2RiIiwicm93cyIsInRhYmxlTmFtZSIsInVucUtleUZpZWxkcyIsImNodW5rU2l6ZSIsInVucUtleXMiLCJ3aGVyZUluRmllbGQiLCJzZWxlY3RGaWVsZCIsImxlbmd0aCIsInJhdyIsImpvaW4iLCJtYXAiLCJyb3ciLCJmaWVsZCIsInJlc3VsdElkcyIsIml0ZW1zIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJTdHJpbmciLCJpZCIsImdldFN1YnNldFF1ZXJpZXMiLCJzdWJzZXQiLCJFcnJvciIsInB1cmlXcmFwcGVyIiwicWIiLCJvblN1YnNldCIsIl9zdWJzZXQiLCJjcmVhdGVFbmhhbmNlcnMiLCJlbmhhbmNlcnMiLCJleGVjdXRlU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJxdWVyeVBhcmFtcyIsImRlYnVnIiwib3B0aW1pemVDb3VudFF1ZXJ5IiwibnVtIiwicGFnZSIsInRvdGFsIiwiZXhlY3V0ZUNvdW50UXVlcnkiLCJjb21wdXRlZFJvd3MiLCJleGVjdXRlTGlzdFF1ZXJ5IiwiZW5oYW5jZXIiLCJQcm9taXNlIiwiYWxsIiwicXVlcnlNb2RlIiwiY291bnRQdXJpIiwiY2xvbmUiLCJjbGVhciIsImRlZmF1bHQiLCJTcWxQYXJzZXIiLCJwYXJzZXIiLCJQYXJzZXIiLCJwYXJzZWRRdWVyeSIsImFzdGlmeSIsInRvUXVlcnkiLCJkYXRhYmFzZSIsImNvbmZpZyIsImxlZnRKb2luVGFibGVzIiwid2hlcmVUYWJsZXMiLCJ0YWJsZXNUb1JlbW92ZSIsImZpbHRlciIsImoiLCJpbmNsdWRlcyIsImZvckVhY2giLCJ0YWJsZSIsImNsZWFySm9pbiIsImNvdW50UmVzdWx0IiwicmF3TnVtYmVyIiwiZmlyc3QiLCJ1bmxvYWRlZFJvd3MiLCJsaW1pdCIsIm9mZnNldCIsImxvYWRlcnMiLCJBcnJheSIsImlzQXJyYXkiLCJwcm9jZXNzTG9hZGVycyIsImh5ZHJhdGUiLCJyZXNvbHZlTG9hZGVyIiwiYXMiLCJyZWZJZCIsInJlc29sdmVMb2FkZXJRYkZuIiwibmVzdGVkTG9hZGVycyIsInJlc29sdmVMb2FkZXJRYiIsImxvYWRlZFJvd3MiLCJzdWJSb3dHcm91cHMiLCJyIiwibmVzdGVkS2V5cyIsIk9iamVjdCIsImtleXMiLCJrZXkiLCJncm91cHMiLCJncm91cEJ5Iiwic3BsaXQiLCJudWxsS2V5cyIsImVudHJpZXMiLCJfIiwiZGF0YSIsImV2ZXJ5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJwYXJ0cyIsIm9ialBhdGgiLCJzbGljZSIsInBhcnQiLCJudWxsS2V5IiwicnVuU3Vic2V0UXVlcnkiLCJiYXNlVGFibGUiLCJzdWJzZXRRdWVyeSIsImJ1aWxkIiwiYWZ0ZXJCdWlsZCIsIl9kYiIsImNoYWxrIiwiZ2V0VGFibGVOYW1lIiwic3RhcnRzV2l0aCIsInBsdXJhbGl6ZSIsInVuZGVyc2NvcmUiLCJ1bmRlZmluZWQiLCJ2aXJ0dWFsIiwiam9pbnMiLCJmcm9tIiwiYXBwbHlKb2luQ2xhdXNlIiwiaW5uZXJKb2luIiwiZ2V0Sm9pbkNsYXVzZSIsImxlZnRPdXRlckpvaW4iLCJjbG9uZWRRYiIsInRhYmxlcyIsIm5lZWRUb0pvaW4iLCJmbGF0TWFwIiwidCIsInByb2Nlc3NlZFFiIiwicSIsInR5cGUiLCJjb3VudFF1ZXJ5IiwiZGlzdGluY3QiLCJjb2x1bW5zIiwiZXhwciIsImNvbHVtbiIsImNvdW50IiwiY291bnRSb3ciLCJjb25zb2xlIiwiYmx1ZSIsInRvU3RyaW5nIiwibGlzdFF1ZXJ5IiwidXNlTG9hZGVycyIsImxvYWRlciIsInN1YlEiLCJzdWJSb3dzIiwidG9Db2wiLCJmcm9tSWRzIiwibWFueUpvaW4iLCJpZEZpZWxkIiwidGhyb3VnaCIsImlkQ29sdW1uIiwidG9UYWJsZSIsIm9uZUpvaW5zIiwiZnJvbUNvbCIsInRvIiwiY3VzdG9tIiwiQmFzZU1vZGVsIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFD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
|