sonamu 0.8.26 → 0.9.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/bin/cli.js +60 -13
- package/dist/_virtual/rolldown_runtime.js +39 -0
- package/dist/ai/agents/agent.d.ts +3 -3
- package/dist/ai/agents/agent.d.ts.map +1 -1
- package/dist/ai/agents/agent.js +76 -73
- package/dist/ai/agents/index.js +3 -3
- package/dist/ai/agents/types.d.ts +3 -3
- package/dist/ai/agents/types.d.ts.map +1 -1
- package/dist/ai/agents/types.js +1 -3
- package/dist/ai/index.js +3 -2
- package/dist/ai/providers/rtzr/api.js +25 -25
- package/dist/ai/providers/rtzr/error.js +25 -26
- package/dist/ai/providers/rtzr/index.js +5 -5
- package/dist/ai/providers/rtzr/model.d.ts +1 -1
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/model.js +117 -133
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/options.js +35 -41
- package/dist/ai/providers/rtzr/provider.d.ts +1 -1
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/provider.js +53 -51
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/utils.js +84 -84
- 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 +29 -19
- package/dist/api/caster.d.ts +1 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +51 -61
- package/dist/api/code-converters.d.ts +4 -3
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +226 -249
- package/dist/api/config.d.ts +17 -17
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +37 -30
- package/dist/api/context.d.ts +10 -10
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +8 -2
- package/dist/api/decorators.d.ts +8 -8
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +245 -268
- package/dist/api/index.js +39 -7
- package/dist/api/secret.js +22 -15
- package/dist/api/sonamu.d.ts +15 -15
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +1012 -1131
- package/dist/api/validator.js +88 -79
- package/dist/auth/auth-generator.d.ts.map +1 -1
- package/dist/auth/auth-generator.js +203 -200
- package/dist/auth/better-auth-entities.d.ts +2 -2
- package/dist/auth/better-auth-entities.d.ts.map +1 -1
- package/dist/auth/better-auth-entities.js +369 -429
- package/dist/auth/index.js +21 -6
- package/dist/auth/knex-adapter.d.ts +2 -2
- package/dist/auth/knex-adapter.d.ts.map +1 -1
- package/dist/auth/knex-adapter.js +153 -157
- package/dist/auth/plugins/entity-definitions/admin.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/admin.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/admin.js +58 -56
- package/dist/auth/plugins/entity-definitions/anonymous.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/anonymous.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/anonymous.js +20 -20
- package/dist/auth/plugins/entity-definitions/api-key.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/api-key.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/api-key.js +185 -196
- package/dist/auth/plugins/entity-definitions/index.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/index.js +26 -29
- package/dist/auth/plugins/entity-definitions/jwt.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/jwt.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/jwt.js +62 -64
- package/dist/auth/plugins/entity-definitions/organization.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/organization.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/organization.js +362 -421
- package/dist/auth/plugins/entity-definitions/passkey.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/passkey.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/passkey.js +115 -126
- package/dist/auth/plugins/entity-definitions/phone-number.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/phone-number.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/phone-number.js +31 -40
- package/dist/auth/plugins/entity-definitions/sso.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/sso.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/sso.js +94 -107
- package/dist/auth/plugins/entity-definitions/two-factor.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/two-factor.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/two-factor.js +78 -92
- package/dist/auth/plugins/entity-definitions/types.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/types.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/types.js +1 -10
- package/dist/auth/plugins/entity-definitions/username.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/username.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/username.js +31 -40
- package/dist/auth/plugins/index.js +12 -3
- package/dist/auth/plugins/wrappers/admin.d.ts +2 -2
- package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/admin.js +28 -29
- package/dist/auth/plugins/wrappers/anonymous.d.ts +2 -1
- package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/anonymous.js +23 -22
- package/dist/auth/plugins/wrappers/api-key.d.ts +2 -1
- package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/api-key.js +39 -34
- package/dist/auth/plugins/wrappers/index.js +11 -11
- package/dist/auth/plugins/wrappers/jwt.d.ts +2 -1
- package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/jwt.js +31 -26
- package/dist/auth/plugins/wrappers/organization.d.ts +2 -1
- package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/organization.js +65 -62
- package/dist/auth/plugins/wrappers/passkey.d.ts +2 -1
- package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/passkey.js +33 -28
- package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/phone-number.js +26 -23
- package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/sso.js +37 -31
- package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/two-factor.js +31 -28
- package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/username.js +23 -23
- package/dist/bin/build-config.js +31 -31
- package/dist/bin/cli.js +1063 -1204
- package/dist/bin/fixture.d.ts.map +1 -1
- package/dist/bin/fixture.js +266 -259
- package/dist/bin/hmr-hook-register.d.ts.map +1 -1
- package/dist/bin/hmr-hook-register.js +19 -18
- package/dist/bin/test-command.d.ts.map +1 -1
- package/dist/bin/test-command.js +180 -177
- package/dist/bin/ts-loader-register.js +13 -6
- package/dist/bin/ts-loader-registration.d.ts.map +1 -1
- package/dist/bin/ts-loader-registration.js +28 -38
- package/dist/cache/cache-manager.d.ts +1 -1
- package/dist/cache/cache-manager.d.ts.map +1 -1
- package/dist/cache/cache-manager.js +20 -15
- package/dist/cache/decorator.d.ts +1 -1
- package/dist/cache/decorator.d.ts.map +1 -1
- package/dist/cache/decorator.js +84 -76
- package/dist/cache/drivers.js +21 -34
- package/dist/cache/index.js +10 -7
- package/dist/cache/types.d.ts +2 -2
- package/dist/cache/types.d.ts.map +1 -1
- package/dist/cache/types.js +1 -6
- package/dist/cache-control/cache-control.d.ts +2 -2
- package/dist/cache-control/cache-control.d.ts.map +1 -1
- package/dist/cache-control/cache-control.js +106 -122
- package/dist/cache-control/types.d.ts +2 -2
- package/dist/cache-control/types.d.ts.map +1 -1
- package/dist/cache-control/types.js +1 -19
- package/dist/compress/compress.d.ts +1 -1
- package/dist/compress/compress.d.ts.map +1 -1
- package/dist/compress/compress.js +58 -56
- package/dist/compress/index.js +7 -2
- package/dist/compress/types.js +1 -11
- package/dist/cone/cone-generator.d.ts +1 -1
- package/dist/cone/cone-generator.d.ts.map +1 -1
- package/dist/cone/cone-generator.js +216 -219
- package/dist/database/_batch_update.d.ts +1 -1
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +107 -102
- package/dist/database/base-model.d.ts +8 -9
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +371 -392
- package/dist/database/base-model.types.d.ts +5 -5
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/base-model.types.js +1 -20
- package/dist/database/db.d.ts +5 -2
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +185 -171
- package/dist/database/knex.d.ts +1 -1
- package/dist/database/knex.d.ts.map +1 -1
- package/dist/database/knex.js +48 -42
- package/dist/database/puri-subset.types.d.ts +6 -7
- package/dist/database/puri-subset.types.d.ts.map +1 -1
- package/dist/database/puri-subset.types.js +1 -16
- package/dist/database/puri-wrapper.d.ts +6 -6
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +99 -101
- package/dist/database/puri.d.ts +4 -5
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +1021 -1227
- package/dist/database/puri.types.d.ts +6 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +15 -6
- package/dist/database/transaction-context.d.ts +2 -2
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +22 -13
- package/dist/database/upsert-builder.d.ts +3 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +405 -465
- package/dist/dict/en.js +72 -74
- package/dist/dict/index.js +13 -13
- package/dist/dict/ko.js +72 -74
- package/dist/dict/rc-keys.js +150 -168
- package/dist/dict/sd.d.ts +3 -1
- package/dist/dict/sd.d.ts.map +1 -1
- package/dist/dict/sd.js +54 -40
- package/dist/dict/sonamu-dictionary.d.ts +1 -1
- package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
- package/dist/dict/sonamu-dictionary.js +887 -955
- package/dist/dict/types.js +1 -7
- package/dist/dict/utils.js +26 -24
- package/dist/entity/entity-manager.d.ts +9 -9
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +226 -223
- package/dist/entity/entity-template-cone.d.ts +1 -1
- package/dist/entity/entity-template-cone.d.ts.map +1 -1
- package/dist/entity/entity-template-cone.js +152 -151
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +952 -1089
- 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 +32 -27
- 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 +61 -68
- package/dist/filter/index.js +9 -3
- package/dist/filter/types.js +92 -88
- package/dist/filter/utils.d.ts +1 -1
- package/dist/filter/utils.d.ts.map +1 -1
- package/dist/filter/utils.js +147 -161
- package/dist/index.js +87 -40
- package/dist/logger/category.d.ts.map +1 -1
- package/dist/logger/category.js +30 -29
- package/dist/logger/configure.d.ts.map +1 -1
- package/dist/logger/configure.js +83 -107
- package/dist/migration/code-generation.d.ts +2 -2
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +1385 -1578
- package/dist/migration/migration-set.d.ts +1 -1
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +177 -227
- package/dist/migration/migrator.d.ts +4 -3
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +340 -345
- package/dist/migration/postgresql-schema-reader.d.ts +2 -2
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +506 -564
- package/dist/migration/slack-confirm.d.ts +2 -2
- package/dist/migration/slack-confirm.d.ts.map +1 -1
- package/dist/migration/slack-confirm.js +205 -193
- package/dist/migration/types.d.ts +2 -2
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +1 -3
- package/dist/naite/messaging-types.d.ts +1 -0
- package/dist/naite/messaging-types.d.ts.map +1 -1
- package/dist/naite/messaging-types.js +1 -7
- package/dist/naite/naite-reporter.d.ts +2 -2
- package/dist/naite/naite-reporter.d.ts.map +1 -1
- package/dist/naite/naite-reporter.js +127 -120
- package/dist/naite/naite.d.ts +3 -2
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +266 -300
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.d.ts.map +1 -1
- package/dist/ssr/index.js +13 -3
- package/dist/ssr/registry.d.ts +1 -1
- package/dist/ssr/registry.d.ts.map +1 -1
- package/dist/ssr/registry.js +45 -37
- package/dist/ssr/renderer.d.ts +4 -4
- package/dist/ssr/renderer.d.ts.map +1 -1
- package/dist/ssr/renderer.js +84 -91
- package/dist/ssr/types.d.ts +2 -2
- package/dist/ssr/types.d.ts.map +1 -1
- package/dist/ssr/types.js +1 -3
- package/dist/storage/base-file.js +54 -41
- package/dist/storage/buffered-file.d.ts +2 -2
- package/dist/storage/buffered-file.d.ts.map +1 -1
- package/dist/storage/buffered-file.js +51 -44
- package/dist/storage/drivers.d.ts +2 -2
- package/dist/storage/drivers.d.ts.map +1 -1
- package/dist/storage/drivers.js +12 -7
- package/dist/storage/index.js +14 -7
- package/dist/storage/s3-driver.d.ts +2 -2
- package/dist/storage/s3-driver.d.ts.map +1 -1
- package/dist/storage/s3-driver.js +52 -48
- package/dist/storage/storage-manager.d.ts +2 -2
- package/dist/storage/storage-manager.d.ts.map +1 -1
- package/dist/storage/storage-manager.js +33 -25
- package/dist/storage/types.d.ts +2 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +1 -5
- package/dist/storage/uploaded-file.d.ts +1 -1
- package/dist/storage/uploaded-file.d.ts.map +1 -1
- package/dist/storage/uploaded-file.js +45 -35
- package/dist/stream/index.js +7 -2
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +72 -67
- package/dist/syncer/api-parser.d.ts +1 -1
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +224 -245
- package/dist/syncer/checksum.d.ts +1 -1
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +86 -72
- package/dist/syncer/code-generator.d.ts +2 -2
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +154 -160
- package/dist/syncer/entity-operations.d.ts +1 -1
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +63 -54
- 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 +38 -38
- package/dist/syncer/index.js +19 -8
- package/dist/syncer/module-loader.d.ts +5 -5
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +83 -78
- package/dist/syncer/syncer-actions.d.ts +2 -2
- package/dist/syncer/syncer-actions.d.ts.map +1 -1
- package/dist/syncer/syncer-actions.js +76 -91
- package/dist/syncer/syncer.d.ts +7 -6
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +426 -492
- package/dist/tasks/decorator.d.ts +3 -3
- package/dist/tasks/decorator.d.ts.map +1 -1
- package/dist/tasks/decorator.js +32 -28
- package/dist/tasks/step-wrapper.d.ts +1 -1
- package/dist/tasks/step-wrapper.d.ts.map +1 -1
- package/dist/tasks/step-wrapper.js +42 -41
- package/dist/tasks/workflow-manager.d.ts +2 -2
- package/dist/tasks/workflow-manager.d.ts.map +1 -1
- package/dist/tasks/workflow-manager.js +192 -221
- 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 +103 -103
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +163 -163
- package/dist/template/implementations/entity.template.d.ts +1 -1
- package/dist/template/implementations/entity.template.d.ts.map +1 -1
- package/dist/template/implementations/entity.template.js +76 -85
- package/dist/template/implementations/entry-server.template.d.ts +1 -1
- package/dist/template/implementations/entry-server.template.d.ts.map +1 -1
- package/dist/template/implementations/entry-server.template.js +32 -27
- package/dist/template/implementations/generated.template.d.ts +1 -1
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +254 -275
- package/dist/template/implementations/generated_http.template.d.ts +2 -2
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +114 -133
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +249 -275
- package/dist/template/implementations/init_types.template.d.ts +1 -1
- package/dist/template/implementations/init_types.template.d.ts.map +1 -1
- package/dist/template/implementations/init_types.template.js +40 -34
- package/dist/template/implementations/model.template.d.ts +1 -1
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +56 -53
- package/dist/template/implementations/model_test.template.d.ts +1 -1
- package/dist/template/implementations/model_test.template.d.ts.map +1 -1
- package/dist/template/implementations/model_test.template.js +32 -24
- package/dist/template/implementations/queries.template.d.ts +1 -1
- package/dist/template/implementations/queries.template.d.ts.map +1 -1
- package/dist/template/implementations/queries.template.js +84 -89
- package/dist/template/implementations/sd.template.d.ts +1 -1
- package/dist/template/implementations/sd.template.d.ts.map +1 -1
- package/dist/template/implementations/sd.template.js +137 -144
- package/dist/template/implementations/services.template.d.ts +1 -1
- package/dist/template/implementations/services.template.d.ts.map +1 -1
- package/dist/template/implementations/services.template.js +164 -189
- package/dist/template/implementations/view_form.template.d.ts +1 -1
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +258 -285
- package/dist/template/implementations/view_id_all_select.template.d.ts +1 -1
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_all_select.template.js +31 -25
- package/dist/template/implementations/view_list.template.d.ts +1 -1
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +304 -355
- package/dist/template/implementations/view_search_input.template.d.ts +1 -1
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
- package/dist/template/implementations/view_search_input.template.js +31 -27
- package/dist/template/index.js +21 -7
- package/dist/template/template-manager.d.ts +1 -1
- package/dist/template/template-manager.d.ts.map +1 -1
- package/dist/template/template-manager.js +132 -123
- package/dist/template/template-types.js +8 -6
- package/dist/template/template.d.ts +2 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +73 -68
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +603 -657
- 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 +93 -88
- package/dist/testing/bootstrap.d.ts +22 -13
- package/dist/testing/bootstrap.d.ts.map +1 -1
- package/dist/testing/bootstrap.js +114 -114
- package/dist/testing/data-explorer.d.ts +3 -3
- package/dist/testing/data-explorer.d.ts.map +1 -1
- package/dist/testing/data-explorer.js +237 -265
- package/dist/testing/dev-test-routes.d.ts +2 -2
- package/dist/testing/dev-test-routes.d.ts.map +1 -1
- package/dist/testing/dev-test-routes.js +258 -249
- package/dist/testing/dev-vitest-manager.d.ts +1 -1
- package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
- package/dist/testing/dev-vitest-manager.js +514 -539
- package/dist/testing/faker-mappings.js +422 -420
- package/dist/testing/fixture-generator.d.ts +3 -3
- package/dist/testing/fixture-generator.d.ts.map +1 -1
- package/dist/testing/fixture-generator.js +1216 -1346
- package/dist/testing/fixture-loader.js +26 -25
- package/dist/testing/fixture-manager.d.ts +3 -3
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +706 -776
- package/dist/testing/global-setup.js +53 -49
- package/dist/testing/index.js +19 -11
- package/dist/testing/naite-vitest-reporter.js +18 -13
- package/dist/testing/parallel-db-manager.d.ts +1 -1
- package/dist/testing/parallel-db-manager.d.ts.map +1 -1
- package/dist/testing/parallel-db-manager.js +63 -78
- package/dist/testing/vitest-helpers.d.ts +1 -1
- package/dist/testing/vitest-helpers.d.ts.map +1 -1
- package/dist/testing/vitest-helpers.js +37 -33
- package/dist/types/types.d.ts +28 -28
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +764 -890
- package/dist/ui/ai-api.d.ts +1 -1
- package/dist/ui/ai-api.d.ts.map +1 -1
- package/dist/ui/ai-api.js +52 -42
- package/dist/ui/ai-client.d.ts +1 -2
- package/dist/ui/ai-client.d.ts.map +1 -1
- package/dist/ui/ai-client.js +353 -388
- package/dist/ui/api.d.ts +1 -1
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +903 -1145
- package/dist/ui/cdd-service.d.ts +1 -1
- package/dist/ui/cdd-service.d.ts.map +1 -1
- package/dist/ui/cdd-service.js +406 -407
- package/dist/ui/cdd-types.js +1 -3
- package/dist/ui-web/assets/index-C-Zz-wYg.css +1 -0
- package/dist/ui-web/assets/index-DejDON8K.js +238 -0
- package/dist/ui-web/index.html +3 -3
- package/dist/utils/async-utils.js +57 -45
- package/dist/utils/console-util.d.ts.map +1 -1
- package/dist/utils/console-util.js +104 -87
- package/dist/utils/controller.js +26 -19
- package/dist/utils/esm-utils.js +49 -38
- package/dist/utils/formatter.d.ts +1 -2
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +89 -115
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +68 -65
- package/dist/utils/lodash-able.js +11 -4
- package/dist/utils/model.d.ts +1 -1
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +21 -19
- package/dist/utils/object-utils.js +148 -186
- package/dist/utils/path-utils.js +67 -57
- package/dist/utils/process-utils.d.ts.map +1 -1
- package/dist/utils/process-utils.js +37 -31
- package/dist/utils/sql-parser.d.ts +1 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +40 -40
- package/dist/utils/type-utils.js +44 -43
- package/dist/utils/utils.d.ts +2 -3
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +81 -93
- 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 +24 -17
- package/dist/vector/chunking.d.ts +1 -1
- package/dist/vector/chunking.d.ts.map +1 -1
- package/dist/vector/chunking.js +100 -94
- package/dist/vector/config.d.ts +1 -1
- package/dist/vector/config.d.ts.map +1 -1
- package/dist/vector/config.js +76 -78
- package/dist/vector/embedding.d.ts +1 -1
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +128 -125
- package/dist/vector/index.js +5 -5
- package/dist/vector/types.js +1 -5
- package/package.json +31 -36
- package/src/ai/agents/agent.ts +12 -5
- package/src/ai/agents/types.ts +5 -5
- package/src/ai/providers/rtzr/model.ts +8 -10
- package/src/ai/providers/rtzr/options.ts +2 -1
- package/src/ai/providers/rtzr/provider.ts +5 -3
- package/src/ai/providers/rtzr/utils.ts +2 -7
- package/src/api/__tests__/config.test.ts +15 -8
- package/src/api/base-frame.ts +5 -3
- package/src/api/caster.ts +7 -6
- package/src/api/code-converters.ts +23 -26
- package/src/api/config.ts +23 -17
- package/src/api/context.ts +18 -11
- package/src/api/decorators.ts +17 -18
- package/src/api/sonamu.ts +44 -49
- package/src/auth/auth-generator.ts +4 -6
- package/src/auth/better-auth-entities.ts +3 -2
- package/src/auth/knex-adapter.ts +6 -5
- package/src/auth/plugins/entity-definitions/admin.ts +1 -1
- package/src/auth/plugins/entity-definitions/anonymous.ts +1 -1
- package/src/auth/plugins/entity-definitions/api-key.ts +1 -1
- package/src/auth/plugins/entity-definitions/index.ts +1 -1
- package/src/auth/plugins/entity-definitions/jwt.ts +1 -1
- package/src/auth/plugins/entity-definitions/organization.ts +1 -1
- package/src/auth/plugins/entity-definitions/passkey.ts +1 -1
- package/src/auth/plugins/entity-definitions/phone-number.ts +1 -1
- package/src/auth/plugins/entity-definitions/sso.ts +1 -1
- package/src/auth/plugins/entity-definitions/two-factor.ts +1 -1
- package/src/auth/plugins/entity-definitions/types.ts +1 -1
- package/src/auth/plugins/entity-definitions/username.ts +1 -1
- package/src/auth/plugins/wrappers/admin.ts +3 -1
- package/src/auth/plugins/wrappers/anonymous.ts +3 -1
- package/src/auth/plugins/wrappers/api-key.ts +3 -1
- package/src/auth/plugins/wrappers/jwt.ts +3 -1
- package/src/auth/plugins/wrappers/organization.ts +3 -1
- package/src/auth/plugins/wrappers/passkey.ts +3 -1
- package/src/auth/plugins/wrappers/phone-number.ts +3 -1
- package/src/auth/plugins/wrappers/sso.ts +2 -1
- package/src/auth/plugins/wrappers/two-factor.ts +3 -1
- package/src/auth/plugins/wrappers/username.ts +3 -1
- package/src/bin/__tests__/ts-loader-register.test.ts +7 -12
- package/src/bin/build-config.ts +3 -3
- package/src/bin/cli.ts +27 -25
- package/src/bin/fixture.ts +4 -2
- package/src/bin/hmr-hook-register.ts +1 -0
- package/src/bin/test-command.ts +4 -2
- package/src/bin/ts-loader-registration.ts +6 -22
- package/src/cache/cache-manager.ts +2 -1
- package/src/cache/decorator.ts +2 -2
- package/src/cache/types.ts +3 -3
- package/src/cache-control/cache-control.ts +3 -2
- package/src/cache-control/types.ts +2 -2
- package/src/compress/compress.ts +1 -1
- package/src/cone/cone-generator.ts +5 -3
- package/src/database/_batch_update.ts +1 -1
- package/src/database/base-model.ts +20 -14
- package/src/database/base-model.types.ts +12 -11
- package/src/database/db.ts +56 -21
- package/src/database/knex.ts +2 -2
- package/src/database/puri-subset.test-d.ts +33 -32
- package/src/database/puri-subset.types.ts +6 -7
- package/src/database/puri-wrapper.ts +29 -26
- package/src/database/puri.ts +36 -34
- package/src/database/puri.types.test-d.ts +6 -5
- package/src/database/puri.types.ts +9 -12
- package/src/database/transaction-context.ts +2 -2
- package/src/database/upsert-builder.ts +17 -10
- package/src/dict/sd.ts +17 -4
- package/src/dict/sonamu-dictionary.ts +23 -17
- package/src/entity/entity-manager.ts +9 -7
- package/src/entity/entity-template-cone.ts +10 -3
- package/src/entity/entity.ts +20 -16
- package/src/exceptions/error-handler.ts +2 -1
- package/src/exceptions/so-exceptions.ts +1 -1
- package/src/filter/utils.ts +3 -2
- package/src/logger/category.ts +1 -0
- package/src/logger/configure.ts +5 -5
- package/src/migration/__tests__/code-generation.search-text.test.ts +2 -3
- package/src/migration/code-generation.ts +26 -25
- package/src/migration/migration-set.ts +16 -18
- package/src/migration/migrator.ts +38 -33
- package/src/migration/postgresql-schema-reader.ts +12 -12
- package/src/migration/slack-confirm.ts +5 -4
- package/src/migration/types.ts +2 -2
- package/src/naite/messaging-types.ts +1 -1
- package/src/naite/naite-reporter.ts +5 -3
- package/src/naite/naite.ts +12 -7
- package/src/shared/app.shared.ts.txt +2 -2
- package/src/shared/web.shared.ts.txt +2 -2
- package/src/skills/AGENTS.md +19 -18
- package/src/skills/commands/sonamu-skills.md +9 -9
- package/src/skills/sonamu/SKILL.md +111 -104
- package/src/skills/sonamu/ai-agents.md +27 -26
- package/src/skills/sonamu/api.md +81 -69
- package/src/skills/sonamu/auth-migration.md +13 -27
- package/src/skills/sonamu/auth-plugins.md +41 -31
- package/src/skills/sonamu/auth.md +30 -24
- package/src/skills/sonamu/cdd.md +26 -17
- package/src/skills/sonamu/cone.md +50 -50
- package/src/skills/sonamu/config.md +74 -51
- package/src/skills/sonamu/create-sonamu.md +31 -19
- package/src/skills/sonamu/database.md +43 -26
- package/src/skills/sonamu/entity-basic.md +61 -61
- package/src/skills/sonamu/entity-relations.md +84 -80
- package/src/skills/sonamu/entity-validation-checklist.md +19 -15
- package/src/skills/sonamu/fixture-cli.md +52 -30
- package/src/skills/sonamu/framework-change.md +9 -7
- package/src/skills/sonamu/frontend.md +64 -82
- package/src/skills/sonamu/i18n.md +45 -37
- package/src/skills/sonamu/migration.md +54 -31
- package/src/skills/sonamu/model.md +98 -66
- package/src/skills/sonamu/naite.md +34 -32
- package/src/skills/sonamu/project-init.md +28 -8
- package/src/skills/sonamu/puri.md +82 -91
- package/src/skills/sonamu/scaffolding.md +44 -32
- package/src/skills/sonamu/skill-contribution.md +50 -45
- package/src/skills/sonamu/subset.md +13 -13
- package/src/skills/sonamu/tasks.md +73 -58
- package/src/skills/sonamu/testing-devrunner.md +56 -36
- package/src/skills/sonamu/testing.md +23 -58
- package/src/skills/sonamu/upsert.md +32 -31
- package/src/skills/sonamu/vector.md +37 -36
- package/src/ssr/index.ts +2 -12
- package/src/ssr/registry.ts +1 -1
- package/src/ssr/renderer.ts +7 -5
- package/src/ssr/types.ts +2 -2
- package/src/storage/buffered-file.ts +4 -2
- package/src/storage/drivers.ts +3 -2
- package/src/storage/s3-driver.ts +7 -4
- package/src/storage/storage-manager.ts +3 -2
- package/src/storage/types.ts +3 -2
- package/src/storage/uploaded-file.ts +1 -1
- package/src/stream/sse.ts +2 -2
- package/src/syncer/api-parser.ts +8 -5
- package/src/syncer/checksum.ts +9 -5
- package/src/syncer/code-generator.ts +16 -8
- package/src/syncer/entity-operations.ts +5 -3
- package/src/syncer/file-patterns.ts +2 -1
- package/src/syncer/module-loader.ts +9 -6
- package/src/syncer/syncer-actions.ts +5 -3
- package/src/syncer/syncer.ts +18 -24
- package/src/tasks/decorator.ts +10 -8
- package/src/tasks/step-wrapper.ts +1 -1
- package/src/tasks/workflow-manager.ts +18 -15
- package/src/template/__tests__/generated.template.search-text.test.ts +1 -0
- package/src/template/entity-converter.ts +4 -2
- package/src/template/generated.template.test-d.ts +2 -1
- package/src/template/helpers.ts +5 -2
- package/src/template/implementations/entity.template.ts +9 -8
- package/src/template/implementations/entry-server.template.ts +1 -1
- package/src/template/implementations/generated.template.ts +21 -29
- package/src/template/implementations/generated_http.template.ts +9 -6
- package/src/template/implementations/generated_sso.template.ts +6 -4
- package/src/template/implementations/init_types.template.ts +3 -2
- package/src/template/implementations/model.template.ts +4 -2
- package/src/template/implementations/model_test.template.ts +3 -2
- package/src/template/implementations/queries.template.ts +6 -14
- package/src/template/implementations/sd.template.ts +4 -2
- package/src/template/implementations/services.template.ts +7 -11
- package/src/template/implementations/view_form.template.ts +5 -3
- package/src/template/implementations/view_id_all_select.template.ts +3 -2
- package/src/template/implementations/view_list.template.ts +7 -5
- package/src/template/implementations/view_search_input.template.ts +3 -2
- package/src/template/template-manager.ts +4 -3
- package/src/template/template.ts +4 -3
- package/src/template/zod-converter.ts +10 -7
- package/src/testing/__tests__/dev-test-routes.test.ts +3 -2
- package/src/testing/__tests__/dev-vitest-manager.test.ts +1 -0
- package/src/testing/_relation-graph.ts +2 -2
- package/src/testing/bootstrap.ts +55 -27
- package/src/testing/data-explorer.ts +5 -4
- package/src/testing/dev-test-routes.ts +8 -5
- package/src/testing/dev-vitest-manager.ts +13 -12
- package/src/testing/fixture-generator.ts +11 -17
- package/src/testing/fixture-manager.ts +21 -17
- package/src/testing/parallel-db-manager.ts +2 -1
- package/src/testing/vitest-helpers.ts +2 -1
- package/src/types/__tests__/entity-json-schema-search-text.test.ts +1 -0
- package/src/types/types.ts +8 -8
- package/src/typings/knex.d.ts +4 -4
- package/src/ui/ai-api.ts +5 -3
- package/src/ui/ai-client.ts +6 -5
- package/src/ui/api.ts +25 -23
- package/src/ui/cdd-service.ts +12 -11
- package/src/utils/console-util.ts +3 -1
- package/src/utils/formatter.ts +94 -102
- package/src/utils/fs-utils.ts +2 -1
- package/src/utils/model.ts +2 -2
- package/src/utils/object-utils.ts +3 -3
- package/src/utils/process-utils.ts +2 -1
- package/src/utils/sql-parser.ts +10 -1
- package/src/utils/type-utils.ts +3 -3
- package/src/utils/utils.ts +9 -7
- package/src/utils/zod-error.ts +1 -1
- package/src/vector/chunking.ts +1 -1
- package/src/vector/config.ts +1 -1
- package/src/vector/embedding.ts +11 -9
- package/tsdown.api.config.ts +50 -0
- package/.swcrc.project-default +0 -18
- package/dist/api/__tests__/config.test.js +0 -189
- package/dist/bin/__tests__/test-command.test.js +0 -112
- package/dist/bin/__tests__/ts-loader-register.test.js +0 -45
- package/dist/database/puri-subset.test-d.js +0 -89
- package/dist/database/puri.types.test-d.js +0 -129
- package/dist/migration/__tests__/code-generation.search-text.test.js +0 -435
- package/dist/template/__tests__/generated.template.search-text.test.js +0 -99
- package/dist/template/generated.template.test-d.js +0 -24
- package/dist/testing/__tests__/dev-test-routes.test.js +0 -144
- package/dist/testing/__tests__/dev-vitest-manager.test.js +0 -152
- package/dist/types/__tests__/entity-json-schema-search-text.test.js +0 -256
- package/dist/typings/knex.d.js +0 -3
- package/dist/ui-web/assets/index-CKo0Z2Iu.css +0 -1
- package/dist/ui-web/assets/index-DK-2aacv.js +0 -257
|
@@ -1,1660 +1,1467 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { __esmMin } from "../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { differenceWith, init_utils, intersectionBy } from "../utils/utils.js";
|
|
3
|
+
import { init_types, isSearchTextProp } from "../types/types.js";
|
|
4
|
+
import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
|
|
5
|
+
import { Naite, init_naite } from "../naite/naite.js";
|
|
6
|
+
import { formatCode, init_formatter } from "../utils/formatter.js";
|
|
7
|
+
import { PostgreSQLSchemaReader, init_postgresql_schema_reader } from "./postgresql-schema-reader.js";
|
|
2
8
|
import { alphabetical, diff } from "radashi";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { differenceWith, intersectionBy } from "../utils/utils.js";
|
|
7
|
-
import { PostgreSQLSchemaReader } from "./postgresql-schema-reader.js";
|
|
8
|
-
const SEARCH_TEXT_HELPER_DEFINITIONS = {
|
|
9
|
-
"text-array": `await knex.raw(\`CREATE OR REPLACE FUNCTION sonamu_text_array_agg(arr text[], ci boolean DEFAULT true)
|
|
10
|
-
RETURNS text
|
|
11
|
-
LANGUAGE sql IMMUTABLE PARALLEL SAFE RETURNS NULL ON NULL INPUT
|
|
12
|
-
AS $$
|
|
13
|
-
SELECT string_agg(
|
|
14
|
-
CASE WHEN ci THEN lower(value) ELSE value END,
|
|
15
|
-
' '
|
|
16
|
-
)
|
|
17
|
-
FROM unnest(arr) AS value
|
|
18
|
-
$$\`);`,
|
|
19
|
-
"jsonb-array": `await knex.raw(\`CREATE OR REPLACE FUNCTION sonamu_jsonb_array_agg(arr jsonb, ci boolean DEFAULT true)
|
|
20
|
-
RETURNS text
|
|
21
|
-
LANGUAGE sql IMMUTABLE PARALLEL SAFE RETURNS NULL ON NULL INPUT
|
|
22
|
-
AS $$
|
|
23
|
-
SELECT string_agg(
|
|
24
|
-
CASE WHEN ci THEN lower(value) ELSE value END,
|
|
25
|
-
' '
|
|
26
|
-
)
|
|
27
|
-
FROM jsonb_array_elements_text(arr)
|
|
28
|
-
$$\`);`
|
|
29
|
-
};
|
|
30
|
-
class SearchTextExpressionParser {
|
|
31
|
-
tokens;
|
|
32
|
-
index = 0;
|
|
33
|
-
constructor(tokens){
|
|
34
|
-
this.tokens = tokens;
|
|
35
|
-
}
|
|
36
|
-
isAtEnd() {
|
|
37
|
-
return this.index >= this.tokens.length;
|
|
38
|
-
}
|
|
39
|
-
parseExpression() {
|
|
40
|
-
return this.parseConcat();
|
|
41
|
-
}
|
|
42
|
-
parseConcat() {
|
|
43
|
-
const parts = [
|
|
44
|
-
this.parsePostfix()
|
|
45
|
-
];
|
|
46
|
-
while(this.matchOperator("||")){
|
|
47
|
-
parts.push(this.parsePostfix());
|
|
48
|
-
}
|
|
49
|
-
return parts.length === 1 ? parts[0] : {
|
|
50
|
-
type: "concat",
|
|
51
|
-
parts
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
parsePostfix() {
|
|
55
|
-
let node = this.parsePrimary();
|
|
56
|
-
while(true){
|
|
57
|
-
if (this.matchOperator("::")) {
|
|
58
|
-
node = {
|
|
59
|
-
type: "cast",
|
|
60
|
-
expr: node,
|
|
61
|
-
targetType: this.parseTypeName()
|
|
62
|
-
};
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
if (this.matchIdentifier("collate")) {
|
|
66
|
-
const token = this.consumeCollationToken();
|
|
67
|
-
node = {
|
|
68
|
-
type: "collate",
|
|
69
|
-
expr: node,
|
|
70
|
-
collation: token.value,
|
|
71
|
-
quoted: token.type === "quotedIdentifier"
|
|
72
|
-
};
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
return node;
|
|
78
|
-
}
|
|
79
|
-
parsePrimary() {
|
|
80
|
-
const token = this.consumeToken("표현식");
|
|
81
|
-
if (token.type === "symbol" && token.value === "(") {
|
|
82
|
-
const node = this.parseExpression();
|
|
83
|
-
this.expectSymbol(")");
|
|
84
|
-
return node;
|
|
85
|
-
}
|
|
86
|
-
if (token.type === "string") {
|
|
87
|
-
return {
|
|
88
|
-
type: "string",
|
|
89
|
-
value: token.value
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
if (token.type === "identifier" || token.type === "quotedIdentifier") {
|
|
93
|
-
const lowerName = token.value.toLowerCase();
|
|
94
|
-
if (token.type === "identifier" && (lowerName === "true" || lowerName === "false")) {
|
|
95
|
-
return {
|
|
96
|
-
type: "boolean",
|
|
97
|
-
value: lowerName === "true"
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
if (this.matchSymbol("(")) {
|
|
101
|
-
if (token.type === "identifier" && lowerName === "trim" && this.isTrimBothFromForm()) {
|
|
102
|
-
this.index += 2;
|
|
103
|
-
const arg = this.parseExpression();
|
|
104
|
-
this.expectSymbol(")");
|
|
105
|
-
return {
|
|
106
|
-
type: "function",
|
|
107
|
-
name: "trim",
|
|
108
|
-
args: [
|
|
109
|
-
arg
|
|
110
|
-
]
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
const args = this.parseFunctionArgs();
|
|
114
|
-
return {
|
|
115
|
-
type: "function",
|
|
116
|
-
name: token.value,
|
|
117
|
-
args
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
type: "identifier",
|
|
122
|
-
name: token.value,
|
|
123
|
-
quoted: token.type === "quotedIdentifier"
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
throw new Error(`지원되지 않는 searchText expression token: ${token.type}`);
|
|
127
|
-
}
|
|
128
|
-
parseFunctionArgs() {
|
|
129
|
-
if (this.matchSymbol(")")) {
|
|
130
|
-
return [];
|
|
131
|
-
}
|
|
132
|
-
const args = [];
|
|
133
|
-
do {
|
|
134
|
-
args.push(this.parseExpression());
|
|
135
|
-
}while (this.matchSymbol(","))
|
|
136
|
-
this.expectSymbol(")");
|
|
137
|
-
return args;
|
|
138
|
-
}
|
|
139
|
-
parseTypeName() {
|
|
140
|
-
const parts = [];
|
|
141
|
-
while(true){
|
|
142
|
-
const token = this.peek();
|
|
143
|
-
if (token?.type === "identifier" || token?.type === "quotedIdentifier" || token?.type === "symbol" && (token.value === "(" || token.value === ")" || token.value === ",")) {
|
|
144
|
-
if (token.type === "symbol") {
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
parts.push(token.value.toLowerCase());
|
|
148
|
-
this.index += 1;
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
if (parts.length === 0) {
|
|
154
|
-
throw new Error("타입 캐스팅 대상 타입을 찾을 수 없습니다.");
|
|
155
|
-
}
|
|
156
|
-
return parts.join(" ");
|
|
157
|
-
}
|
|
158
|
-
consumeCollationToken() {
|
|
159
|
-
const token = this.peek();
|
|
160
|
-
if (token?.type !== "identifier" && token?.type !== "quotedIdentifier") {
|
|
161
|
-
throw new Error("COLLATE 대상 식별자를 찾을 수 없습니다.");
|
|
162
|
-
}
|
|
163
|
-
this.index += 1;
|
|
164
|
-
return token;
|
|
165
|
-
}
|
|
166
|
-
isTrimBothFromForm() {
|
|
167
|
-
const bothToken = this.peek();
|
|
168
|
-
const fromToken = this.peek(1);
|
|
169
|
-
return bothToken?.type === "identifier" && bothToken.value.toLowerCase() === "both" && fromToken?.type === "identifier" && fromToken.value.toLowerCase() === "from";
|
|
170
|
-
}
|
|
171
|
-
expectSymbol(value) {
|
|
172
|
-
if (!this.matchSymbol(value)) {
|
|
173
|
-
throw new Error(`"${value}" 토큰이 필요합니다.`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
matchSymbol(value) {
|
|
177
|
-
const token = this.peek();
|
|
178
|
-
if (token?.type === "symbol" && token.value === value) {
|
|
179
|
-
this.index += 1;
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
matchOperator(value) {
|
|
185
|
-
const token = this.peek();
|
|
186
|
-
if (token?.type === "operator" && token.value === value) {
|
|
187
|
-
this.index += 1;
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
matchIdentifier(value) {
|
|
193
|
-
const token = this.peek();
|
|
194
|
-
if (token?.type === "identifier" && token.value.toLowerCase() === value.toLowerCase()) {
|
|
195
|
-
this.index += 1;
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
consumeToken(context) {
|
|
201
|
-
const token = this.peek();
|
|
202
|
-
if (!token) {
|
|
203
|
-
throw new Error(`${context} 토큰이 필요합니다.`);
|
|
204
|
-
}
|
|
205
|
-
this.index += 1;
|
|
206
|
-
return token;
|
|
207
|
-
}
|
|
208
|
-
peek(offset = 0) {
|
|
209
|
-
return this.tokens[this.index + offset];
|
|
210
|
-
}
|
|
211
|
-
}
|
|
9
|
+
import equal from "fast-deep-equal";
|
|
10
|
+
|
|
11
|
+
//#region src/migration/code-generation.ts
|
|
212
12
|
function getIndexColumnOpclass(column) {
|
|
213
|
-
|
|
13
|
+
return column.opclass ?? column.vectorOps;
|
|
214
14
|
}
|
|
215
15
|
function tokenizeSearchTextExpression(expression) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
16
|
+
const tokens = [];
|
|
17
|
+
let index = 0;
|
|
18
|
+
while (index < expression.length) {
|
|
19
|
+
const char = expression[index];
|
|
20
|
+
if (char === undefined) {
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
if (/\s/.test(char)) {
|
|
24
|
+
index += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (expression.startsWith("||", index)) {
|
|
28
|
+
tokens.push({
|
|
29
|
+
type: "operator",
|
|
30
|
+
value: "||"
|
|
31
|
+
});
|
|
32
|
+
index += 2;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (expression.startsWith("::", index)) {
|
|
36
|
+
tokens.push({
|
|
37
|
+
type: "operator",
|
|
38
|
+
value: "::"
|
|
39
|
+
});
|
|
40
|
+
index += 2;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (char === "(" || char === ")" || char === ",") {
|
|
44
|
+
tokens.push({
|
|
45
|
+
type: "symbol",
|
|
46
|
+
value: char
|
|
47
|
+
});
|
|
48
|
+
index += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (char === "'") {
|
|
52
|
+
let value = "";
|
|
53
|
+
index += 1;
|
|
54
|
+
while (index < expression.length) {
|
|
55
|
+
const current = expression[index];
|
|
56
|
+
if (current === "'") {
|
|
57
|
+
if (expression[index + 1] === "'") {
|
|
58
|
+
value += "'";
|
|
59
|
+
index += 2;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
index += 1;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
if (current === undefined) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
value += current;
|
|
69
|
+
index += 1;
|
|
70
|
+
}
|
|
71
|
+
tokens.push({
|
|
72
|
+
type: "string",
|
|
73
|
+
value
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (char === "\"") {
|
|
78
|
+
let value = "";
|
|
79
|
+
index += 1;
|
|
80
|
+
while (index < expression.length) {
|
|
81
|
+
const current = expression[index];
|
|
82
|
+
if (current === "\"") {
|
|
83
|
+
if (expression[index + 1] === "\"") {
|
|
84
|
+
value += "\"";
|
|
85
|
+
index += 2;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
index += 1;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
if (current === undefined) {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
value += current;
|
|
95
|
+
index += 1;
|
|
96
|
+
}
|
|
97
|
+
tokens.push({
|
|
98
|
+
type: "quotedIdentifier",
|
|
99
|
+
value
|
|
100
|
+
});
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (/[A-Za-z_]/.test(char)) {
|
|
104
|
+
let value = char;
|
|
105
|
+
index += 1;
|
|
106
|
+
while (index < expression.length) {
|
|
107
|
+
const current = expression[index];
|
|
108
|
+
if (current !== undefined && /[A-Za-z0-9_$]/.test(current)) {
|
|
109
|
+
value += current;
|
|
110
|
+
index += 1;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
tokens.push({
|
|
116
|
+
type: "identifier",
|
|
117
|
+
value
|
|
118
|
+
});
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
throw new Error(`지원되지 않는 searchText expression 문자: ${char}`);
|
|
122
|
+
}
|
|
123
|
+
return tokens;
|
|
324
124
|
}
|
|
325
125
|
function canonicalizeSearchTextGeneratedExpression(expression) {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
126
|
+
try {
|
|
127
|
+
const parser = new SearchTextExpressionParser(tokenizeSearchTextExpression(expression));
|
|
128
|
+
const parsedExpression = parser.parseExpression();
|
|
129
|
+
if (!parser.isAtEnd()) {
|
|
130
|
+
throw new Error("searchText expression 파싱이 끝나지 않았습니다.");
|
|
131
|
+
}
|
|
132
|
+
return renderSearchTextExpression(normalizeSearchTextExpressionNode(parsedExpression));
|
|
133
|
+
} catch {
|
|
134
|
+
return normalizeSearchTextExpressionFallback(expression);
|
|
135
|
+
}
|
|
336
136
|
}
|
|
337
137
|
function normalizeSearchTextExpressionNode(node) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
args[0]
|
|
394
|
-
];
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
type: "function",
|
|
398
|
-
name,
|
|
399
|
-
args
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
}
|
|
138
|
+
switch (node.type) {
|
|
139
|
+
case "identifier": return {
|
|
140
|
+
...node,
|
|
141
|
+
name: node.quoted ? node.name : node.name.toLowerCase()
|
|
142
|
+
};
|
|
143
|
+
case "string":
|
|
144
|
+
case "boolean": return node;
|
|
145
|
+
case "concat": {
|
|
146
|
+
const parts = node.parts.flatMap((part) => {
|
|
147
|
+
const normalizedPart = normalizeSearchTextExpressionNode(part);
|
|
148
|
+
return normalizedPart.type === "concat" ? normalizedPart.parts : [normalizedPart];
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
type: "concat",
|
|
152
|
+
parts
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
case "collate": return {
|
|
156
|
+
type: "collate",
|
|
157
|
+
expr: normalizeSearchTextExpressionNode(node.expr),
|
|
158
|
+
collation: node.collation.toUpperCase() === "C" ? "C" : node.collation,
|
|
159
|
+
quoted: node.quoted || node.collation.toUpperCase() === "C"
|
|
160
|
+
};
|
|
161
|
+
case "cast": {
|
|
162
|
+
const normalizedExpr = normalizeSearchTextExpressionNode(node.expr);
|
|
163
|
+
const targetType = node.targetType.replace(/\s+/g, " ").trim().toLowerCase();
|
|
164
|
+
if (targetType === "text" || targetType === "character varying" || targetType === "varchar") {
|
|
165
|
+
return normalizedExpr;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
type: "cast",
|
|
169
|
+
expr: normalizedExpr,
|
|
170
|
+
targetType
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
case "function": {
|
|
174
|
+
const name = node.name.toLowerCase();
|
|
175
|
+
let args = node.args.map((arg) => normalizeSearchTextExpressionNode(arg));
|
|
176
|
+
if ((name === "trim" || name === "btrim") && args.length === 1) {
|
|
177
|
+
return {
|
|
178
|
+
type: "function",
|
|
179
|
+
name: "trim",
|
|
180
|
+
args
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if ((name === "sonamu_text_array_agg" || name === "sonamu_jsonb_array_agg") && args.length === 2 && args[1]?.type === "boolean" && args[1].value) {
|
|
184
|
+
args = [args[0]];
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
type: "function",
|
|
188
|
+
name,
|
|
189
|
+
args
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
403
193
|
}
|
|
404
194
|
function renderSearchTextExpression(node, parentPrecedence = 0) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
return `${renderSearchTextExpression(node.expr, precedence)}::${node.targetType}`;
|
|
425
|
-
}
|
|
426
|
-
})();
|
|
427
|
-
if (precedence < parentPrecedence) {
|
|
428
|
-
return `(${rendered})`;
|
|
429
|
-
}
|
|
430
|
-
return rendered;
|
|
195
|
+
const precedence = getSearchTextExpressionPrecedence(node);
|
|
196
|
+
const rendered = (() => {
|
|
197
|
+
switch (node.type) {
|
|
198
|
+
case "identifier": return node.quoted ? `"${node.name.replaceAll("\"", "\"\"")}"` : node.name;
|
|
199
|
+
case "string": return `'${node.value.replaceAll("'", "''")}'`;
|
|
200
|
+
case "boolean": return node.value ? "true" : "false";
|
|
201
|
+
case "function": return `${node.name}(${node.args.map((arg) => renderSearchTextExpression(arg)).join(", ")})`;
|
|
202
|
+
case "concat": return node.parts.map((part) => renderSearchTextExpression(part, precedence)).join(" || ");
|
|
203
|
+
case "collate": {
|
|
204
|
+
const collation = node.quoted ? `"${node.collation.replaceAll("\"", "\"\"")}"` : node.collation;
|
|
205
|
+
return `${renderSearchTextExpression(node.expr, precedence)} COLLATE ${collation}`;
|
|
206
|
+
}
|
|
207
|
+
case "cast": return `${renderSearchTextExpression(node.expr, precedence)}::${node.targetType}`;
|
|
208
|
+
}
|
|
209
|
+
})();
|
|
210
|
+
if (precedence < parentPrecedence) {
|
|
211
|
+
return `(${rendered})`;
|
|
212
|
+
}
|
|
213
|
+
return rendered;
|
|
431
214
|
}
|
|
432
215
|
function getSearchTextExpressionPrecedence(node) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
default:
|
|
440
|
-
return 3;
|
|
441
|
-
}
|
|
216
|
+
switch (node.type) {
|
|
217
|
+
case "concat": return 1;
|
|
218
|
+
case "collate":
|
|
219
|
+
case "cast": return 2;
|
|
220
|
+
default: return 3;
|
|
221
|
+
}
|
|
442
222
|
}
|
|
443
223
|
function normalizeSearchTextExpressionFallback(expression) {
|
|
444
|
-
|
|
224
|
+
return expression.replace(/\s+/g, " ").replace(/\bTRIM\s*\(\s*BOTH\s+FROM\s+/gi, "trim(").replace(/::(?:text|character varying|varchar)\b/gi, "").replace(/,\s*true\b/gi, "").trim();
|
|
445
225
|
}
|
|
446
226
|
function visitSearchTextExpressionNode(node, visitor) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
227
|
+
visitor(node);
|
|
228
|
+
switch (node.type) {
|
|
229
|
+
case "concat":
|
|
230
|
+
node.parts.forEach((part) => {
|
|
231
|
+
visitSearchTextExpressionNode(part, visitor);
|
|
232
|
+
});
|
|
233
|
+
return;
|
|
234
|
+
case "collate":
|
|
235
|
+
case "cast":
|
|
236
|
+
visitSearchTextExpressionNode(node.expr, visitor);
|
|
237
|
+
return;
|
|
238
|
+
case "function":
|
|
239
|
+
node.args.forEach((arg) => {
|
|
240
|
+
visitSearchTextExpressionNode(arg, visitor);
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
243
|
+
case "identifier":
|
|
244
|
+
case "string":
|
|
245
|
+
case "boolean": return;
|
|
246
|
+
}
|
|
468
247
|
}
|
|
469
248
|
function getSearchTextHelperKindsFromExpression(expression) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
249
|
+
const helperKinds = new Set();
|
|
250
|
+
const addHelperKindFromName = (name) => {
|
|
251
|
+
const normalizedName = name.toLowerCase();
|
|
252
|
+
if (normalizedName === "sonamu_text_array_agg") {
|
|
253
|
+
helperKinds.add("text-array");
|
|
254
|
+
} else if (normalizedName === "sonamu_jsonb_array_agg") {
|
|
255
|
+
helperKinds.add("jsonb-array");
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
try {
|
|
259
|
+
const parser = new SearchTextExpressionParser(tokenizeSearchTextExpression(expression));
|
|
260
|
+
const parsedExpression = parser.parseExpression();
|
|
261
|
+
if (!parser.isAtEnd()) {
|
|
262
|
+
throw new Error("searchText helper expression 파싱이 끝나지 않았습니다.");
|
|
263
|
+
}
|
|
264
|
+
visitSearchTextExpressionNode(parsedExpression, (node) => {
|
|
265
|
+
if (node.type === "function") {
|
|
266
|
+
addHelperKindFromName(node.name);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
} catch {
|
|
270
|
+
if (/\bsonamu_text_array_agg\s*\(/i.test(expression)) {
|
|
271
|
+
helperKinds.add("text-array");
|
|
272
|
+
}
|
|
273
|
+
if (/\bsonamu_jsonb_array_agg\s*\(/i.test(expression)) {
|
|
274
|
+
helperKinds.add("jsonb-array");
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return helperKinds;
|
|
499
278
|
}
|
|
500
279
|
function resolveSearchTextColumns(table, columns) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
});
|
|
280
|
+
const entity = (() => {
|
|
281
|
+
try {
|
|
282
|
+
return EntityManager.getByTable(table);
|
|
283
|
+
} catch {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
})();
|
|
287
|
+
if (!entity) {
|
|
288
|
+
return columns;
|
|
289
|
+
}
|
|
290
|
+
const propsByName = new Map(entity.props.map((prop) => [prop.name, prop]));
|
|
291
|
+
return columns.map((column) => {
|
|
292
|
+
const prop = propsByName.get(column.name);
|
|
293
|
+
if (!prop || !isSearchTextProp(prop)) {
|
|
294
|
+
return column;
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
...column,
|
|
298
|
+
generated: {
|
|
299
|
+
type: "STORED",
|
|
300
|
+
expression: buildSearchTextGeneratedExpression(prop, propsByName)
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
});
|
|
528
304
|
}
|
|
529
305
|
function buildSearchTextGeneratedExpression(prop, propsByName) {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
306
|
+
const tokens = prop.sourceColumns.map((source) => {
|
|
307
|
+
const sourceProp = propsByName.get(source.name);
|
|
308
|
+
if (!sourceProp) {
|
|
309
|
+
throw new Error(`searchText source column "${source.name}"을(를) 찾을 수 없습니다.`);
|
|
310
|
+
}
|
|
311
|
+
if (sourceProp.type === "string") {
|
|
312
|
+
return source.caseInsensitive ? `lower(COALESCE(${source.name}, ''))` : `COALESCE(${source.name}, '')`;
|
|
313
|
+
}
|
|
314
|
+
if (sourceProp.type === "string[]") {
|
|
315
|
+
return source.caseInsensitive ? `COALESCE(sonamu_text_array_agg(${source.name}), '')` : `COALESCE(sonamu_text_array_agg(${source.name}, false), '')`;
|
|
316
|
+
}
|
|
317
|
+
if (sourceProp.type === "json") {
|
|
318
|
+
return source.caseInsensitive ? `COALESCE(sonamu_jsonb_array_agg(${source.name}), '')` : `COALESCE(sonamu_jsonb_array_agg(${source.name}, false), '')`;
|
|
319
|
+
}
|
|
320
|
+
throw new Error(`searchText source column "${source.name}"의 타입 "${sourceProp.type}"은(는) 지원되지 않습니다.`);
|
|
321
|
+
});
|
|
322
|
+
return `trim(${tokens.join(` || ' ' || `)})`;
|
|
547
323
|
}
|
|
548
324
|
function getSearchTextHelperDefinitions(table, columns) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
} else if (sourceProp?.type === "json") {
|
|
588
|
-
helperKinds.add("jsonb-array");
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
});
|
|
592
|
-
return [
|
|
593
|
-
"text-array",
|
|
594
|
-
"jsonb-array"
|
|
595
|
-
].filter((kind)=>helperKinds.has(kind)).map((kind)=>SEARCH_TEXT_HELPER_DEFINITIONS[kind]);
|
|
325
|
+
const helperKinds = new Set();
|
|
326
|
+
columns.forEach((column) => {
|
|
327
|
+
if (!column.generated) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
getSearchTextHelperKindsFromExpression(column.generated.expression).forEach((kind) => {
|
|
331
|
+
helperKinds.add(kind);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
if (helperKinds.size > 0) {
|
|
335
|
+
return ["text-array", "jsonb-array"].filter((kind) => helperKinds.has(kind)).map((kind) => SEARCH_TEXT_HELPER_DEFINITIONS[kind]);
|
|
336
|
+
}
|
|
337
|
+
const entity = (() => {
|
|
338
|
+
try {
|
|
339
|
+
return EntityManager.getByTable(table);
|
|
340
|
+
} catch {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
})();
|
|
344
|
+
if (!entity) {
|
|
345
|
+
return [];
|
|
346
|
+
}
|
|
347
|
+
const propsByName = new Map(entity.props.map((prop) => [prop.name, prop]));
|
|
348
|
+
columns.forEach((column) => {
|
|
349
|
+
const prop = propsByName.get(column.name);
|
|
350
|
+
if (!prop || !isSearchTextProp(prop)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
prop.sourceColumns.forEach((source) => {
|
|
354
|
+
const sourceProp = propsByName.get(source.name);
|
|
355
|
+
if (sourceProp?.type === "string[]") {
|
|
356
|
+
helperKinds.add("text-array");
|
|
357
|
+
} else if (sourceProp?.type === "json") {
|
|
358
|
+
helperKinds.add("jsonb-array");
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
return ["text-array", "jsonb-array"].filter((kind) => helperKinds.has(kind)).map((kind) => SEARCH_TEXT_HELPER_DEFINITIONS[kind]);
|
|
596
363
|
}
|
|
597
364
|
function getSearchTextColumnNames(table) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
365
|
+
const entity = (() => {
|
|
366
|
+
try {
|
|
367
|
+
return EntityManager.getByTable(table);
|
|
368
|
+
} catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
})();
|
|
372
|
+
if (!entity) {
|
|
373
|
+
return new Set();
|
|
374
|
+
}
|
|
375
|
+
return new Set(entity.props.filter(isSearchTextProp).map((prop) => prop.name));
|
|
609
376
|
}
|
|
610
377
|
/**
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
formatted: formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`)
|
|
640
|
-
};
|
|
378
|
+
* 테이블 생성하는 케이스 - 컬럼/인덱스 생성
|
|
379
|
+
*/
|
|
380
|
+
async function generateCreateCode_ColumnAndIndexes(table, columns, indexes) {
|
|
381
|
+
const resolvedColumns = resolveSearchTextColumns(table, columns);
|
|
382
|
+
const columnDefs = genColumnDefinitions(table, resolvedColumns);
|
|
383
|
+
const helperDefinitions = getSearchTextHelperDefinitions(table, resolvedColumns);
|
|
384
|
+
const lines = [
|
|
385
|
+
"import { Knex } from \"knex\";",
|
|
386
|
+
"",
|
|
387
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
388
|
+
...helperDefinitions,
|
|
389
|
+
`await knex.schema.createTable("${table}", (table) => {`,
|
|
390
|
+
...columnDefs.builder,
|
|
391
|
+
"});",
|
|
392
|
+
...columnDefs.raw,
|
|
393
|
+
...indexes.map((index) => genIndexDefinition(index, table)),
|
|
394
|
+
"}",
|
|
395
|
+
"",
|
|
396
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
397
|
+
` return knex.schema.dropTable("${table}");`,
|
|
398
|
+
"}"
|
|
399
|
+
];
|
|
400
|
+
return {
|
|
401
|
+
table,
|
|
402
|
+
type: "normal",
|
|
403
|
+
title: `create__${table}`,
|
|
404
|
+
formatted: await formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`)
|
|
405
|
+
};
|
|
641
406
|
}
|
|
642
407
|
/**
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
return result;
|
|
408
|
+
* MigrationColumn[] 읽어서 컬럼 정의하는 구문 생성
|
|
409
|
+
* @returns builder: table builder 메서드, raw: knex.raw() 구문
|
|
410
|
+
*/
|
|
411
|
+
function genColumnDefinitions(table, columns) {
|
|
412
|
+
const result = {
|
|
413
|
+
builder: [],
|
|
414
|
+
raw: []
|
|
415
|
+
};
|
|
416
|
+
for (const column of columns) {
|
|
417
|
+
if (column.generated) {
|
|
418
|
+
result.raw.push(genGeneratedColumnDefinition(table, column));
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
result.builder.push(genNormalColumnDefinition(column));
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
660
424
|
}
|
|
661
425
|
/**
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
426
|
+
* Generated Column 정의 생성 (ALTER TABLE ADD COLUMN 사용)
|
|
427
|
+
*/
|
|
428
|
+
function genGeneratedColumnDefinition(table, column) {
|
|
429
|
+
if (!column.generated) {
|
|
430
|
+
throw new Error("Generated column definition required");
|
|
431
|
+
}
|
|
432
|
+
const pgType = getPgTypeForColumn(column);
|
|
433
|
+
const storageType = column.generated.type === "VIRTUAL" ? " VIRTUAL" : " STORED";
|
|
434
|
+
const nullableClause = column.nullable ? "" : " NOT NULL";
|
|
435
|
+
return `await knex.raw(\`ALTER TABLE "${table}" ADD COLUMN "${column.name}" ${pgType} GENERATED ALWAYS AS (${column.generated.expression})${storageType}${nullableClause}\`);`;
|
|
671
436
|
}
|
|
672
437
|
/**
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// defaultTo
|
|
729
|
-
if (column.defaultTo !== undefined) {
|
|
730
|
-
if (typeof column.defaultTo === "string" && column.defaultTo.startsWith(`"`)) {
|
|
731
|
-
chains.push(`defaultTo(${column.defaultTo})`);
|
|
732
|
-
} else if (column.type === "json" && typeof column.defaultTo.startsWith('"')) {
|
|
733
|
-
chains.push(`defaultTo(knex.raw("${column.defaultTo.replaceAll('"', "'")}::jsonb"))`);
|
|
734
|
-
} else {
|
|
735
|
-
chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
return `table.${chains.join(".")};`;
|
|
438
|
+
* 일반 컬럼 정의 생성 (table.xxx() 체인)
|
|
439
|
+
*/
|
|
440
|
+
function genNormalColumnDefinition(column) {
|
|
441
|
+
const chains = [];
|
|
442
|
+
if (column.name === "id") {
|
|
443
|
+
if (column.type === "string") {
|
|
444
|
+
if (column.length !== undefined) {
|
|
445
|
+
return `table.string('id', ${column.length}).primary().notNullable();`;
|
|
446
|
+
}
|
|
447
|
+
return `table.text('id').primary().notNullable();`;
|
|
448
|
+
}
|
|
449
|
+
if (column.type === "uuid") {
|
|
450
|
+
return `table.uuid('id').primary().notNullable();`;
|
|
451
|
+
}
|
|
452
|
+
return `table.increments().primary();`;
|
|
453
|
+
}
|
|
454
|
+
if (column.type.endsWith("[]")) {
|
|
455
|
+
const elementType = column.type.slice(0, -2);
|
|
456
|
+
const pgType = getPgArrayType(column, elementType);
|
|
457
|
+
chains.push(`specificType('${column.name}', '${pgType}')`);
|
|
458
|
+
} else if (column.type === "vector") {
|
|
459
|
+
chains.push(`specificType('${column.name}', 'vector(${column.dimensions})')`);
|
|
460
|
+
} else if (column.type === "numberOrNumeric") {
|
|
461
|
+
if (column.numberType === "real") {
|
|
462
|
+
chains.push(`float('${column.name}')`);
|
|
463
|
+
} else if (column.numberType === "double precision") {
|
|
464
|
+
chains.push(`double('${column.name}')`);
|
|
465
|
+
} else if ((column.numberType ?? "numeric") === "numeric") {
|
|
466
|
+
chains.push(`decimal('${column.name}', ${column.precision}, ${column.scale})`);
|
|
467
|
+
}
|
|
468
|
+
} else if (column.type === "string") {
|
|
469
|
+
if (column.length !== undefined) {
|
|
470
|
+
chains.push(`string('${column.name}', ${column.length})`);
|
|
471
|
+
} else {
|
|
472
|
+
chains.push(`text('${column.name}')`);
|
|
473
|
+
}
|
|
474
|
+
} else if (column.type === "date") {
|
|
475
|
+
chains.push(`timestamp('${column.name}', { useTz: true, precision: ${column.precision ?? 3} })`);
|
|
476
|
+
} else if (column.type === "json") {
|
|
477
|
+
chains.push(`jsonb('${column.name}')`);
|
|
478
|
+
} else {
|
|
479
|
+
let extraType;
|
|
480
|
+
chains.push(`${column.type}('${column.name}'${column.length ? `, ${column.length}` : ""}${extraType ? `, '${extraType}'` : ""})`);
|
|
481
|
+
}
|
|
482
|
+
chains.push(column.nullable ? "nullable()" : "notNullable()");
|
|
483
|
+
if (column.defaultTo !== undefined) {
|
|
484
|
+
if (typeof column.defaultTo === "string" && column.defaultTo.startsWith(`"`)) {
|
|
485
|
+
chains.push(`defaultTo(${column.defaultTo})`);
|
|
486
|
+
} else if (column.type === "json" && typeof column.defaultTo.startsWith("\"")) {
|
|
487
|
+
chains.push(`defaultTo(knex.raw("${column.defaultTo.replaceAll("\"", "'")}::jsonb"))`);
|
|
488
|
+
} else {
|
|
489
|
+
chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return `table.${chains.join(".")};`;
|
|
739
493
|
}
|
|
740
494
|
/**
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
case "vector":
|
|
761
|
-
return `vector(${column.dimensions})`;
|
|
762
|
-
default:
|
|
763
|
-
return column.type;
|
|
764
|
-
}
|
|
495
|
+
* MigrationColumn의 타입을 PostgreSQL 타입 문자열로 변환
|
|
496
|
+
*/
|
|
497
|
+
function getPgTypeForColumn(column) {
|
|
498
|
+
if (column.type.endsWith("[]")) {
|
|
499
|
+
const elementType = column.type.slice(0, -2);
|
|
500
|
+
return getPgArrayType(column, elementType);
|
|
501
|
+
}
|
|
502
|
+
switch (column.type) {
|
|
503
|
+
case "string": return column.length !== undefined ? `varchar(${column.length})` : "text";
|
|
504
|
+
case "bigInteger": return "bigint";
|
|
505
|
+
case "numberOrNumeric":
|
|
506
|
+
if (column.numberType === "real") return "real";
|
|
507
|
+
if (column.numberType === "double precision") return "double precision";
|
|
508
|
+
return `numeric(${column.precision}, ${column.scale})`;
|
|
509
|
+
case "date": return "timestamptz";
|
|
510
|
+
case "json": return "jsonb";
|
|
511
|
+
case "vector": return `vector(${column.dimensions})`;
|
|
512
|
+
default: return column.type;
|
|
513
|
+
}
|
|
765
514
|
}
|
|
766
515
|
function getPgArrayType(column, elementType) {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
516
|
+
if (elementType === "numberOrNumeric") {
|
|
517
|
+
if (column.numberType === "real") return "real[]";
|
|
518
|
+
if (column.numberType === "double precision") return "double precision[]";
|
|
519
|
+
return `numeric(${column.precision}, ${column.scale})[]`;
|
|
520
|
+
}
|
|
521
|
+
if (elementType === "string") {
|
|
522
|
+
return column.length ? `varchar(${column.length})[]` : "text[]";
|
|
523
|
+
}
|
|
524
|
+
if (elementType === "date") return "timestamptz[]";
|
|
525
|
+
if (elementType === "integer") return "integer[]";
|
|
526
|
+
if (elementType === "bigInteger") return "bigint[]";
|
|
527
|
+
if (elementType === "boolean") return "boolean[]";
|
|
528
|
+
if (elementType === "uuid") return "uuid[]";
|
|
529
|
+
if (elementType === "enum") return "text[]";
|
|
530
|
+
if (elementType === "vector") return `vector(${column.dimensions})[]`;
|
|
531
|
+
throw new Error(`Unknown array element type: ${elementType}`);
|
|
783
532
|
}
|
|
784
533
|
/**
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
534
|
+
* 개별 인덱스 정의 생성
|
|
535
|
+
*/
|
|
536
|
+
function genIndexDefinition(index, table) {
|
|
537
|
+
if (index.type === "hnsw" || index.type === "ivfflat") {
|
|
538
|
+
return genVectorIndexDefinition(index, table);
|
|
539
|
+
}
|
|
540
|
+
if (index.using === "pgroonga") {
|
|
541
|
+
return genPgroongaIndexDefinition(index, table);
|
|
542
|
+
}
|
|
543
|
+
const methodMap = {
|
|
544
|
+
index: "INDEX",
|
|
545
|
+
unique: "UNIQUE INDEX"
|
|
546
|
+
};
|
|
547
|
+
const nullsNotDistinctClause = index.type === "unique" && index.nullsNotDistinct !== undefined ? ` NULLS ${index.nullsNotDistinct ? "NOT DISTINCT" : "DISTINCT"}` : "";
|
|
548
|
+
const usingClause = index.using === undefined ? "" : `USING ${index.using}`;
|
|
549
|
+
return `await knex.raw(
|
|
550
|
+
\`CREATE ${methodMap[index.type]} ${index.name} ON ${table} ${usingClause}(${index.columns.map((col) => {
|
|
551
|
+
const opclassClause = (() => {
|
|
552
|
+
const opclass = getIndexColumnOpclass(col);
|
|
553
|
+
return opclass ? ` ${opclass}` : "";
|
|
554
|
+
})();
|
|
555
|
+
if (index.using !== "btree" && index.using !== undefined) {
|
|
556
|
+
return `${col.name}${opclassClause}`;
|
|
557
|
+
}
|
|
558
|
+
const sortOrderClause = col.sortOrder === undefined ? "" : ` ${col.sortOrder}`;
|
|
559
|
+
const nullsFirstClause = col.nullsFirst === undefined ? "" : ` NULLS ${col.nullsFirst ? "FIRST" : "LAST"}`;
|
|
560
|
+
return `${col.name}${opclassClause}${sortOrderClause}${nullsFirstClause}`;
|
|
561
|
+
}).join(", ")})${nullsNotDistinctClause};\`
|
|
813
562
|
);`;
|
|
814
563
|
}
|
|
815
564
|
function genPgroongaIndexDefinition(index, table) {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
return `await knex.raw(
|
|
565
|
+
const entity = EntityManager.getByTable(table);
|
|
566
|
+
const columnClause = (() => {
|
|
567
|
+
if (index.columns.length === 1) {
|
|
568
|
+
const column = entity.propsDict[index.columns[0].name];
|
|
569
|
+
const option = getPgroongaColumnOption(column);
|
|
570
|
+
return `${index.columns[0].name}${option ? ` ${option}` : ""}`;
|
|
571
|
+
}
|
|
572
|
+
return `(ARRAY[${index.columns.map((col) => `${col.name}::text`).join(",")}])`;
|
|
573
|
+
})();
|
|
574
|
+
return `await knex.raw(
|
|
827
575
|
\`CREATE INDEX ${index.name} ON ${table} USING pgroonga (${columnClause}) WITH (tokenizer='TokenMecab');\`
|
|
828
576
|
)`;
|
|
829
577
|
}
|
|
830
578
|
/**
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
579
|
+
* PGroonga 컬럼 옵션 추출
|
|
580
|
+
*
|
|
581
|
+
* FullText 오퍼레이터를 지원하는 경우 우선 설정, 나머지는 디폴트 이용
|
|
582
|
+
* @link https://pgroonga.github.io/reference
|
|
583
|
+
*/
|
|
584
|
+
function getPgroongaColumnOption(column) {
|
|
585
|
+
if (column.type === "string" && column.length !== undefined) {
|
|
586
|
+
return "pgroonga_varchar_full_text_search_ops_v2";
|
|
587
|
+
} else if (column.type === "json") {
|
|
588
|
+
return "pgroonga_jsonb_full_text_search_ops_v2";
|
|
589
|
+
}
|
|
590
|
+
return null;
|
|
842
591
|
}
|
|
843
592
|
/**
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
throw new Error(`Unknown raw SQL index type: ${index.type}`);
|
|
593
|
+
* @description
|
|
594
|
+
* - HNSW (Hierarchical Navigable Small World): 느린 빌드, 빠른 검색 속도, 높은 메모리 및 정확도
|
|
595
|
+
* - IVFFlat (Inverted File with Flat Compression): 빠른 빌드, 중간 검색 속도, 낮은 메모리
|
|
596
|
+
*
|
|
597
|
+
* @example
|
|
598
|
+
* // HNSW 인덱스 (권장 - 빠른 검색, 높은 정확도)
|
|
599
|
+
* CREATE INDEX idx_embedding ON items USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);
|
|
600
|
+
*
|
|
601
|
+
* // IVFFlat 인덱스 (대용량 데이터, 비용 중요 시)
|
|
602
|
+
* CREATE INDEX idx_embedding ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
|
603
|
+
*/
|
|
604
|
+
function genVectorIndexDefinition(index, table) {
|
|
605
|
+
const column = index.columns[0];
|
|
606
|
+
const vectorOps = getIndexColumnOpclass(column) ?? "vector_cosine_ops";
|
|
607
|
+
if (index.type === "hnsw") {
|
|
608
|
+
const m = index.m ?? 16;
|
|
609
|
+
const efConstruction = index.efConstruction ?? 64;
|
|
610
|
+
return `await knex.raw(\`CREATE INDEX ${index.name} ON ${table} USING hnsw (${column.name} ${vectorOps}) WITH (m = ${m}, ef_construction = ${efConstruction})\`);`;
|
|
611
|
+
}
|
|
612
|
+
if (index.type === "ivfflat") {
|
|
613
|
+
const lists = index.lists ?? 100;
|
|
614
|
+
return `await knex.raw(\`CREATE INDEX ${index.name} ON ${table} USING ivfflat (${column.name} ${vectorOps}) WITH (lists = ${lists})\`);`;
|
|
615
|
+
}
|
|
616
|
+
throw new Error(`Unknown raw SQL index type: ${index.type}`);
|
|
869
617
|
}
|
|
870
618
|
/**
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
formatted: formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`)
|
|
906
|
-
}
|
|
907
|
-
];
|
|
619
|
+
* 테이블 생성하는 케이스 - FK 생성
|
|
620
|
+
*/
|
|
621
|
+
async function generateCreateCode_Foreign(table, foreigns) {
|
|
622
|
+
if (foreigns.length === 0) {
|
|
623
|
+
return [];
|
|
624
|
+
}
|
|
625
|
+
const { up, down } = genForeignDefinitions(table, foreigns);
|
|
626
|
+
if (up.length === 0 && down.length === 0) {
|
|
627
|
+
return [];
|
|
628
|
+
}
|
|
629
|
+
const lines = [
|
|
630
|
+
"import { Knex } from \"knex\";",
|
|
631
|
+
"",
|
|
632
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
633
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
634
|
+
"// create fk",
|
|
635
|
+
...up,
|
|
636
|
+
"});",
|
|
637
|
+
"}",
|
|
638
|
+
"",
|
|
639
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
640
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
641
|
+
"// drop fk",
|
|
642
|
+
...down,
|
|
643
|
+
"});",
|
|
644
|
+
"}"
|
|
645
|
+
];
|
|
646
|
+
const foreignKeysString = foreigns.map((foreign) => foreign.columns.join("_")).join("_");
|
|
647
|
+
return [{
|
|
648
|
+
table,
|
|
649
|
+
type: "foreign",
|
|
650
|
+
title: `foreign__${table}__${foreignKeysString}`,
|
|
651
|
+
formatted: await formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`)
|
|
652
|
+
}];
|
|
908
653
|
}
|
|
909
654
|
/**
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
655
|
+
* MigrationForeign[] 읽어서 외부키 constraint 정의하는 구문 생성
|
|
656
|
+
*/
|
|
657
|
+
function genForeignDefinitions(table, foreigns) {
|
|
658
|
+
return foreigns.reduce((r, foreign) => {
|
|
659
|
+
const columnsStringQuote = foreign.columns.map((col) => `'${col.replace(`${table}.`, "")}'`).join(",");
|
|
660
|
+
r.up.push(`table.foreign('${foreign.columns.join(",")}')
|
|
915
661
|
.references('${foreign.to}')
|
|
916
662
|
.onUpdate('${foreign.onUpdate}')
|
|
917
663
|
.onDelete('${foreign.onDelete}')`);
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
664
|
+
r.down.push(`table.dropForeign([${columnsStringQuote}])`);
|
|
665
|
+
return r;
|
|
666
|
+
}, {
|
|
667
|
+
up: [],
|
|
668
|
+
down: []
|
|
669
|
+
});
|
|
924
670
|
}
|
|
925
671
|
/**
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
const title = [
|
|
1033
|
-
"alter",
|
|
1034
|
-
table,
|
|
1035
|
-
...[
|
|
1036
|
-
"add",
|
|
1037
|
-
"drop",
|
|
1038
|
-
"alter"
|
|
1039
|
-
].map((action)=>{
|
|
1040
|
-
const len = alterColumnsTo[action].length;
|
|
1041
|
-
if (len > 0) {
|
|
1042
|
-
return action + len;
|
|
1043
|
-
}
|
|
1044
|
-
return null;
|
|
1045
|
-
}).filter((part)=>part !== null)
|
|
1046
|
-
].join("_");
|
|
1047
|
-
return [
|
|
1048
|
-
{
|
|
1049
|
-
table,
|
|
1050
|
-
title,
|
|
1051
|
-
formatted,
|
|
1052
|
-
type: "normal"
|
|
1053
|
-
}
|
|
1054
|
-
];
|
|
672
|
+
* 테이블 변경 케이스 - 컬럼/인덱스 변경
|
|
673
|
+
*/
|
|
674
|
+
async function generateAlterCode_ColumnAndIndexes(table, entityColumns, entityIndexes, dbColumns, dbIndexes, dbForeigns, compareDB) {
|
|
675
|
+
const resolvedEntityColumns = resolveSearchTextColumns(table, entityColumns);
|
|
676
|
+
const searchTextColumnNames = getSearchTextColumnNames(table);
|
|
677
|
+
const entityIdCol = resolvedEntityColumns.find((col) => col.name === "id");
|
|
678
|
+
const dbIdCol = dbColumns.find((col) => col.name === "id");
|
|
679
|
+
if (entityIdCol && dbIdCol && compareDB) {
|
|
680
|
+
const isPkTypeChanged = entityIdCol.type !== dbIdCol.type || entityIdCol.length !== dbIdCol.length;
|
|
681
|
+
if (isPkTypeChanged) {
|
|
682
|
+
return generatePkTypeChangeMigration(table, entityIdCol, dbIdCol, resolvedEntityColumns, entityIndexes, dbColumns, dbIndexes, dbForeigns, compareDB);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const alterColumnsTo = getAlterColumnsTo(resolvedEntityColumns, dbColumns, searchTextColumnNames);
|
|
686
|
+
const alterColumnLinesTo = getAlterColumnLinesTo(alterColumnsTo, resolvedEntityColumns, table, dbForeigns);
|
|
687
|
+
const alterIndexesTo = getAlterIndexesTo(entityIndexes, dbIndexes);
|
|
688
|
+
const recreatedSearchTextColumnNames = new Set(alterColumnsTo.alter.filter((dbColumn) => {
|
|
689
|
+
const entityColumn = resolvedEntityColumns.find((col) => col.name === dbColumn.name);
|
|
690
|
+
return searchTextColumnNames.has(dbColumn.name) && dbColumn.generated !== undefined && entityColumn?.generated !== undefined;
|
|
691
|
+
}).map((column) => column.name));
|
|
692
|
+
const recreatedSearchTextDbIndexes = dbIndexes.filter((index) => index.columns.some(({ name }) => recreatedSearchTextColumnNames.has(name)) && !alterIndexesTo.drop.some((dropIndex) => dropIndex.name === index.name));
|
|
693
|
+
const recreatedSearchTextEntityIndexes = entityIndexes.filter((index) => index.columns.some(({ name }) => recreatedSearchTextColumnNames.has(name)) && !alterIndexesTo.add.some((addIndex) => addIndex.name === index.name));
|
|
694
|
+
const implicitlyDroppedDbIndexes = alterIndexesTo.drop.filter((index) => index.columns.every(({ name }) => alterColumnsTo.drop.some((column) => column.name === name)));
|
|
695
|
+
const indexNeedsToDrop = alterIndexesTo.drop.filter((index) => !implicitlyDroppedDbIndexes.some((droppedIndex) => droppedIndex.name === index.name));
|
|
696
|
+
const hasUpChanges = alterColumnLinesTo.add.up.builder.length > 0 || alterColumnLinesTo.add.up.raw.length > 0 || alterColumnLinesTo.drop.up.builder.length > 0 || alterColumnLinesTo.alter.up.builder.length > 0 || alterColumnLinesTo.alter.up.raw.length > 0 || alterIndexesTo.add.length > 0 || indexNeedsToDrop.length > 0 || recreatedSearchTextDbIndexes.length > 0;
|
|
697
|
+
if (!hasUpChanges) {
|
|
698
|
+
return [];
|
|
699
|
+
}
|
|
700
|
+
Naite.t("migrator:generateAlterCode_ColumnAndIndexes:debug", {
|
|
701
|
+
"alterColumnsTo.add.length": alterColumnsTo.add.length,
|
|
702
|
+
"alterColumnsTo.drop.length": alterColumnsTo.drop.length,
|
|
703
|
+
"alterColumnsTo.alter.length": alterColumnsTo.alter.length,
|
|
704
|
+
"alterIndexesTo.add.length": alterIndexesTo.add.length,
|
|
705
|
+
"alterIndexesTo.drop.length": alterIndexesTo.drop.length,
|
|
706
|
+
"indexNeedsToDrop.length": indexNeedsToDrop.length
|
|
707
|
+
});
|
|
708
|
+
const upBuilderLines = [
|
|
709
|
+
...alterColumnLinesTo.drop.up.builder.length > 0 ? alterColumnLinesTo.drop.up.builder : [],
|
|
710
|
+
...alterColumnLinesTo.add.up.builder.length > 0 ? alterColumnLinesTo.add.up.builder : [],
|
|
711
|
+
...recreatedSearchTextDbIndexes.map(genIndexDropDefinition),
|
|
712
|
+
...alterColumnLinesTo.alter.up.builder.length > 0 ? alterColumnLinesTo.alter.up.builder : [],
|
|
713
|
+
...indexNeedsToDrop.map(genIndexDropDefinition)
|
|
714
|
+
];
|
|
715
|
+
const upRawLines = [
|
|
716
|
+
...alterColumnLinesTo.add.up.raw.length > 0 ? alterColumnLinesTo.add.up.raw : [],
|
|
717
|
+
...alterColumnLinesTo.alter.up.raw.length > 0 ? alterColumnLinesTo.alter.up.raw : [],
|
|
718
|
+
...recreatedSearchTextEntityIndexes.map((index) => genIndexDefinition(index, table)),
|
|
719
|
+
...alterIndexesTo.add.map((index) => genIndexDefinition(index, table))
|
|
720
|
+
];
|
|
721
|
+
const downBuilderLines = [
|
|
722
|
+
...alterColumnLinesTo.add.down.builder.length > 0 ? alterColumnLinesTo.add.down.builder : [],
|
|
723
|
+
...recreatedSearchTextEntityIndexes.map(genIndexDropDefinition),
|
|
724
|
+
...alterColumnLinesTo.alter.down.builder.length > 0 ? alterColumnLinesTo.alter.down.builder : [],
|
|
725
|
+
...alterColumnLinesTo.drop.down.builder.length > 0 ? alterColumnLinesTo.drop.down.builder : [],
|
|
726
|
+
...alterIndexesTo.add.filter((index) => !index.columns.every((indexCol) => alterColumnsTo.add.map((col) => col.name).includes(indexCol.name))).map(genIndexDropDefinition)
|
|
727
|
+
];
|
|
728
|
+
const downRawLines = [
|
|
729
|
+
...alterColumnLinesTo.drop.down.raw.length > 0 ? alterColumnLinesTo.drop.down.raw : [],
|
|
730
|
+
...alterColumnLinesTo.alter.down.raw.length > 0 ? alterColumnLinesTo.alter.down.raw : [],
|
|
731
|
+
...recreatedSearchTextDbIndexes.map((index) => genIndexDefinition(index, table)),
|
|
732
|
+
...implicitlyDroppedDbIndexes.map((index) => genIndexDefinition(index, table)),
|
|
733
|
+
...indexNeedsToDrop.map((index) => genIndexDefinition(index, table))
|
|
734
|
+
];
|
|
735
|
+
const lines = [
|
|
736
|
+
"import { Knex } from \"knex\";",
|
|
737
|
+
"",
|
|
738
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
739
|
+
...upBuilderLines.length > 0 ? [
|
|
740
|
+
`await knex.schema.alterTable("${table}", (table) => {`,
|
|
741
|
+
...upBuilderLines,
|
|
742
|
+
"});"
|
|
743
|
+
] : [],
|
|
744
|
+
...upRawLines,
|
|
745
|
+
"}",
|
|
746
|
+
"",
|
|
747
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
748
|
+
...downBuilderLines.length > 0 ? [
|
|
749
|
+
`await knex.schema.alterTable("${table}", (table) => {`,
|
|
750
|
+
...downBuilderLines,
|
|
751
|
+
"});"
|
|
752
|
+
] : [],
|
|
753
|
+
...downRawLines,
|
|
754
|
+
"}"
|
|
755
|
+
];
|
|
756
|
+
const formatted = await formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`);
|
|
757
|
+
const title = [
|
|
758
|
+
"alter",
|
|
759
|
+
table,
|
|
760
|
+
...[
|
|
761
|
+
"add",
|
|
762
|
+
"drop",
|
|
763
|
+
"alter"
|
|
764
|
+
].map((action) => {
|
|
765
|
+
const len = alterColumnsTo[action].length;
|
|
766
|
+
if (len > 0) {
|
|
767
|
+
return action + len;
|
|
768
|
+
}
|
|
769
|
+
return null;
|
|
770
|
+
}).filter((part) => part !== null)
|
|
771
|
+
].join("_");
|
|
772
|
+
return [{
|
|
773
|
+
table,
|
|
774
|
+
title,
|
|
775
|
+
formatted,
|
|
776
|
+
type: "normal"
|
|
777
|
+
}];
|
|
1055
778
|
}
|
|
1056
779
|
/**
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
780
|
+
* 컬럼 비교를 위해 Generated Column의 expression을 제외한 객체를 생성
|
|
781
|
+
*/
|
|
782
|
+
function normalizeColumnForComparison(col, searchTextColumnNames) {
|
|
783
|
+
if (!col.generated) {
|
|
784
|
+
return col;
|
|
785
|
+
}
|
|
786
|
+
if (!searchTextColumnNames.has(col.name)) {
|
|
787
|
+
return {
|
|
788
|
+
...col,
|
|
789
|
+
generated: undefined
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
return {
|
|
793
|
+
...col,
|
|
794
|
+
generated: {
|
|
795
|
+
...col.generated,
|
|
796
|
+
expression: canonicalizeSearchTextGeneratedExpression(col.generated.expression)
|
|
797
|
+
}
|
|
798
|
+
};
|
|
1075
799
|
}
|
|
1076
800
|
/**
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
columnsTo.drop = columnsTo.drop.concat(extraColumns.db);
|
|
1100
|
-
}
|
|
1101
|
-
// 동일 컬럼명의 세부 필드 비교
|
|
1102
|
-
const sameDbColumns = intersectionBy(dbColumns, entityColumns, (col)=>col.name);
|
|
1103
|
-
const sameMdColumns = intersectionBy(entityColumns, dbColumns, (col)=>col.name);
|
|
1104
|
-
columnsTo.alter = differenceWith(sameDbColumns, sameMdColumns, (a, b)=>equal(normalizeColumnForComparison(a, searchTextColumnNames), normalizeColumnForComparison(b, searchTextColumnNames)));
|
|
1105
|
-
return columnsTo;
|
|
801
|
+
* 각 컬럼 이름 기준으로 add, drop, alter 여부 확인
|
|
802
|
+
*/
|
|
803
|
+
function getAlterColumnsTo(entityColumns, dbColumns, searchTextColumnNames) {
|
|
804
|
+
const columnsTo = {
|
|
805
|
+
add: [],
|
|
806
|
+
drop: [],
|
|
807
|
+
alter: []
|
|
808
|
+
};
|
|
809
|
+
const extraColumns = {
|
|
810
|
+
db: diff(dbColumns, entityColumns, (col) => [col.name, col.generated?.type].join("///")),
|
|
811
|
+
entity: diff(entityColumns, dbColumns, (col) => [col.name, col.generated?.type].join("///"))
|
|
812
|
+
};
|
|
813
|
+
if (extraColumns.entity.length > 0) {
|
|
814
|
+
columnsTo.add = columnsTo.add.concat(extraColumns.entity);
|
|
815
|
+
}
|
|
816
|
+
if (extraColumns.db.length > 0) {
|
|
817
|
+
columnsTo.drop = columnsTo.drop.concat(extraColumns.db);
|
|
818
|
+
}
|
|
819
|
+
const sameDbColumns = intersectionBy(dbColumns, entityColumns, (col) => col.name);
|
|
820
|
+
const sameMdColumns = intersectionBy(entityColumns, dbColumns, (col) => col.name);
|
|
821
|
+
columnsTo.alter = differenceWith(sameDbColumns, sameMdColumns, (a, b) => equal(normalizeColumnForComparison(a, searchTextColumnNames), normalizeColumnForComparison(b, searchTextColumnNames)));
|
|
822
|
+
return columnsTo;
|
|
1106
823
|
}
|
|
1107
824
|
/**
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
"// rollback - alter generated column",
|
|
1236
|
-
genGeneratedColumnDefinition(table, dbColumn)
|
|
1237
|
-
];
|
|
1238
|
-
return r;
|
|
1239
|
-
}
|
|
1240
|
-
// 컬럼 변경사항
|
|
1241
|
-
const columnDiffUp = diff(genColumnDefinitions(table, [
|
|
1242
|
-
entityColumn
|
|
1243
|
-
]).builder, genColumnDefinitions(table, [
|
|
1244
|
-
dbColumn
|
|
1245
|
-
]).builder);
|
|
1246
|
-
const columnDiffDown = diff(genColumnDefinitions(table, [
|
|
1247
|
-
dbColumn
|
|
1248
|
-
]).builder, genColumnDefinitions(table, [
|
|
1249
|
-
entityColumn
|
|
1250
|
-
]).builder);
|
|
1251
|
-
if (columnDiffUp.length > 0) {
|
|
1252
|
-
r.up.builder = [
|
|
1253
|
-
...r.up.builder,
|
|
1254
|
-
"// alter column",
|
|
1255
|
-
...columnDiffUp.map((l)=>`${l.replace(";", "")}.alter();`)
|
|
1256
|
-
];
|
|
1257
|
-
r.down.builder = [
|
|
1258
|
-
...r.down.builder,
|
|
1259
|
-
"// rollback - alter column",
|
|
1260
|
-
...columnDiffDown.map((l)=>`${l.replace(";", "")}.alter();`)
|
|
1261
|
-
];
|
|
1262
|
-
}
|
|
1263
|
-
return r;
|
|
1264
|
-
}, {
|
|
1265
|
-
up: {
|
|
1266
|
-
builder: [],
|
|
1267
|
-
raw: []
|
|
1268
|
-
},
|
|
1269
|
-
down: {
|
|
1270
|
-
builder: [],
|
|
1271
|
-
raw: []
|
|
1272
|
-
}
|
|
1273
|
-
});
|
|
1274
|
-
return linesTo;
|
|
825
|
+
* 추출된 컬럼들을 기준으로 각각 라인 생성
|
|
826
|
+
*/
|
|
827
|
+
function getAlterColumnLinesTo(columnsTo, entityColumns, table, dbForeigns) {
|
|
828
|
+
const searchTextColumnNames = getSearchTextColumnNames(table);
|
|
829
|
+
const linesTo = {
|
|
830
|
+
add: {
|
|
831
|
+
up: {
|
|
832
|
+
builder: [],
|
|
833
|
+
raw: []
|
|
834
|
+
},
|
|
835
|
+
down: {
|
|
836
|
+
builder: [],
|
|
837
|
+
raw: []
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
drop: {
|
|
841
|
+
up: {
|
|
842
|
+
builder: [],
|
|
843
|
+
raw: []
|
|
844
|
+
},
|
|
845
|
+
down: {
|
|
846
|
+
builder: [],
|
|
847
|
+
raw: []
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
alter: {
|
|
851
|
+
up: {
|
|
852
|
+
builder: [],
|
|
853
|
+
raw: []
|
|
854
|
+
},
|
|
855
|
+
down: {
|
|
856
|
+
builder: [],
|
|
857
|
+
raw: []
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
const addColumnDefs = genColumnDefinitions(table, columnsTo.add);
|
|
862
|
+
linesTo.add.up = {
|
|
863
|
+
builder: addColumnDefs.builder.length > 0 ? ["// add", ...addColumnDefs.builder] : [],
|
|
864
|
+
raw: addColumnDefs.raw.length > 0 ? [
|
|
865
|
+
...getSearchTextHelperDefinitions(table, columnsTo.add),
|
|
866
|
+
"// add (generated)",
|
|
867
|
+
...addColumnDefs.raw
|
|
868
|
+
] : []
|
|
869
|
+
};
|
|
870
|
+
linesTo.add.down = {
|
|
871
|
+
builder: columnsTo.add.length > 0 ? ["// rollback - add", `table.dropColumns(${columnsTo.add.map((col) => `'${col.name}'`).join(", ")})`] : [],
|
|
872
|
+
raw: []
|
|
873
|
+
};
|
|
874
|
+
const dropColumnNames = columnsTo.drop.map((col) => col.name);
|
|
875
|
+
const fkToDropBeforeColumn = dbForeigns.filter((fk) => fk.columns.some((col) => dropColumnNames.includes(col)));
|
|
876
|
+
const dropFkLines = fkToDropBeforeColumn.map((fk) => {
|
|
877
|
+
const columnsStringQuote = fk.columns.map((col) => `'${col}'`).join(",");
|
|
878
|
+
return `table.dropForeign([${columnsStringQuote}])`;
|
|
879
|
+
});
|
|
880
|
+
const restoreFkLines = genForeignDefinitions(table, fkToDropBeforeColumn).up;
|
|
881
|
+
const dropColumnDefs = genColumnDefinitions(table, columnsTo.drop);
|
|
882
|
+
linesTo.drop = {
|
|
883
|
+
up: {
|
|
884
|
+
builder: [...dropFkLines.length > 0 ? ["// drop foreign keys on columns to be dropped", ...dropFkLines] : [], ...columnsTo.drop.length > 0 ? ["// drop columns", `table.dropColumns(${columnsTo.drop.map((col) => `'${col.name}'`).join(", ")})`] : []],
|
|
885
|
+
raw: []
|
|
886
|
+
},
|
|
887
|
+
down: {
|
|
888
|
+
builder: [...dropColumnDefs.builder.length > 0 ? ["// rollback - drop columns", ...dropColumnDefs.builder] : [], ...restoreFkLines.length > 0 ? ["// restore foreign keys", ...restoreFkLines] : []],
|
|
889
|
+
raw: dropColumnDefs.raw.length > 0 ? [
|
|
890
|
+
...getSearchTextHelperDefinitions(table, columnsTo.drop),
|
|
891
|
+
"// rollback - drop columns (generated)",
|
|
892
|
+
...dropColumnDefs.raw
|
|
893
|
+
] : []
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
linesTo.alter = columnsTo.alter.reduce((r, dbColumn) => {
|
|
897
|
+
const entityColumn = entityColumns.find((col) => col.name === dbColumn.name);
|
|
898
|
+
if (entityColumn === undefined) {
|
|
899
|
+
return r;
|
|
900
|
+
}
|
|
901
|
+
if (searchTextColumnNames.has(dbColumn.name) && dbColumn.generated !== undefined && entityColumn.generated !== undefined) {
|
|
902
|
+
r.up.builder = [
|
|
903
|
+
...r.up.builder,
|
|
904
|
+
"// alter generated column",
|
|
905
|
+
`table.dropColumns('${dbColumn.name}')`
|
|
906
|
+
];
|
|
907
|
+
r.up.raw = [
|
|
908
|
+
...r.up.raw,
|
|
909
|
+
...getSearchTextHelperDefinitions(table, [entityColumn]),
|
|
910
|
+
"// alter generated column",
|
|
911
|
+
genGeneratedColumnDefinition(table, entityColumn)
|
|
912
|
+
];
|
|
913
|
+
r.down.builder = [
|
|
914
|
+
...r.down.builder,
|
|
915
|
+
"// rollback - alter generated column",
|
|
916
|
+
`table.dropColumns('${dbColumn.name}')`
|
|
917
|
+
];
|
|
918
|
+
r.down.raw = [
|
|
919
|
+
...r.down.raw,
|
|
920
|
+
...getSearchTextHelperDefinitions(table, [dbColumn]),
|
|
921
|
+
"// rollback - alter generated column",
|
|
922
|
+
genGeneratedColumnDefinition(table, dbColumn)
|
|
923
|
+
];
|
|
924
|
+
return r;
|
|
925
|
+
}
|
|
926
|
+
const columnDiffUp = diff(genColumnDefinitions(table, [entityColumn]).builder, genColumnDefinitions(table, [dbColumn]).builder);
|
|
927
|
+
const columnDiffDown = diff(genColumnDefinitions(table, [dbColumn]).builder, genColumnDefinitions(table, [entityColumn]).builder);
|
|
928
|
+
if (columnDiffUp.length > 0) {
|
|
929
|
+
r.up.builder = [
|
|
930
|
+
...r.up.builder,
|
|
931
|
+
"// alter column",
|
|
932
|
+
...columnDiffUp.map((l) => `${l.replace(";", "")}.alter();`)
|
|
933
|
+
];
|
|
934
|
+
r.down.builder = [
|
|
935
|
+
...r.down.builder,
|
|
936
|
+
"// rollback - alter column",
|
|
937
|
+
...columnDiffDown.map((l) => `${l.replace(";", "")}.alter();`)
|
|
938
|
+
];
|
|
939
|
+
}
|
|
940
|
+
return r;
|
|
941
|
+
}, {
|
|
942
|
+
up: {
|
|
943
|
+
builder: [],
|
|
944
|
+
raw: []
|
|
945
|
+
},
|
|
946
|
+
down: {
|
|
947
|
+
builder: [],
|
|
948
|
+
raw: []
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
return linesTo;
|
|
1275
952
|
}
|
|
1276
953
|
/**
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
return indexesTo;
|
|
954
|
+
* 인덱스의 add, drop 여부 확인
|
|
955
|
+
*/
|
|
956
|
+
function getAlterIndexesTo(entityIndexes, dbIndexes) {
|
|
957
|
+
const indexesTo = {
|
|
958
|
+
add: [],
|
|
959
|
+
drop: []
|
|
960
|
+
};
|
|
961
|
+
const identity = (index) => {
|
|
962
|
+
const keys = Object.keys(index).filter((key) => key !== "name").toSorted();
|
|
963
|
+
return keys.map((key) => {
|
|
964
|
+
if (key === "name") {
|
|
965
|
+
return undefined;
|
|
966
|
+
}
|
|
967
|
+
if (key === "columns") {
|
|
968
|
+
return index[key].map((col) => {
|
|
969
|
+
return Object.keys(col).toSorted().map((k) => `${k}=${col[k]}`).join("//");
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
return `${key}=${index[key]}`;
|
|
973
|
+
}).join("//");
|
|
974
|
+
};
|
|
975
|
+
const extraIndexes = {
|
|
976
|
+
db: diff(dbIndexes, entityIndexes.map(setMigrationIndexDefaults), identity),
|
|
977
|
+
entity: diff(entityIndexes.map(setMigrationIndexDefaults), dbIndexes, identity)
|
|
978
|
+
};
|
|
979
|
+
if (extraIndexes.entity.length > 0) {
|
|
980
|
+
indexesTo.add = indexesTo.add.concat(extraIndexes.entity);
|
|
981
|
+
}
|
|
982
|
+
if (extraIndexes.db.length > 0) {
|
|
983
|
+
indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);
|
|
984
|
+
}
|
|
985
|
+
return indexesTo;
|
|
1310
986
|
}
|
|
1311
987
|
/**
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
988
|
+
* 인덱스 삭제 정의 생성
|
|
989
|
+
*/
|
|
990
|
+
function genIndexDropDefinition(index) {
|
|
991
|
+
return `table.dropIndex([${index.columns.map((column) => `'${column.name}'`).join(",")}], '${index.name}')`;
|
|
1315
992
|
}
|
|
1316
993
|
/**
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
using: normalizedUsing
|
|
1337
|
-
} : {}
|
|
1338
|
-
};
|
|
994
|
+
* DB 조회 결과와 비교하기 위한 인덱스 기본값 설정
|
|
995
|
+
*/
|
|
996
|
+
function setMigrationIndexDefaults(index) {
|
|
997
|
+
const isVectorIndex = index.type === "hnsw" || index.type === "ivfflat";
|
|
998
|
+
const supportsOrdering = !isVectorIndex && (!index.using || index.using === "btree");
|
|
999
|
+
const normalizedUsing = isVectorIndex ? index.using : index.using ?? "btree";
|
|
1000
|
+
return {
|
|
1001
|
+
...index,
|
|
1002
|
+
columns: index.columns.map((col) => ({
|
|
1003
|
+
name: col.name,
|
|
1004
|
+
...getIndexColumnOpclass(col) ? { opclass: getIndexColumnOpclass(col) } : {},
|
|
1005
|
+
...supportsOrdering ? {
|
|
1006
|
+
sortOrder: col.sortOrder ?? "ASC",
|
|
1007
|
+
nullsFirst: col.nullsFirst ?? col.sortOrder === "DESC"
|
|
1008
|
+
} : {}
|
|
1009
|
+
})),
|
|
1010
|
+
nullsNotDistinct: index.nullsNotDistinct ?? false,
|
|
1011
|
+
...normalizedUsing ? { using: normalizedUsing } : {}
|
|
1012
|
+
};
|
|
1339
1013
|
}
|
|
1340
1014
|
/**
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
table,
|
|
1427
|
-
"foreigns"
|
|
1428
|
-
].join("_");
|
|
1429
|
-
return [
|
|
1430
|
-
{
|
|
1431
|
-
table,
|
|
1432
|
-
title,
|
|
1433
|
-
formatted,
|
|
1434
|
-
type: "normal"
|
|
1435
|
-
}
|
|
1436
|
-
];
|
|
1015
|
+
* 테이블 변경 케이스 - Foreign Key 변경
|
|
1016
|
+
*/
|
|
1017
|
+
async function generateAlterCode_Foreigns(table, entityForeigns, dbForeigns, droppingColumns = []) {
|
|
1018
|
+
const getKey = (mf) => {
|
|
1019
|
+
return [mf.columns.join("-"), mf.to].join("///");
|
|
1020
|
+
};
|
|
1021
|
+
const droppingColumnNames = droppingColumns.map((col) => col.name);
|
|
1022
|
+
const fkTo = entityForeigns.reduce((result, entityF) => {
|
|
1023
|
+
const matchingDbF = dbForeigns.find((dbF) => getKey(entityF) === getKey(dbF));
|
|
1024
|
+
if (!matchingDbF) {
|
|
1025
|
+
result.add.push(entityF);
|
|
1026
|
+
return result;
|
|
1027
|
+
}
|
|
1028
|
+
if (!equal(entityF, matchingDbF)) {
|
|
1029
|
+
result.alterSrc.push(matchingDbF);
|
|
1030
|
+
result.alterDst.push(entityF);
|
|
1031
|
+
return result;
|
|
1032
|
+
}
|
|
1033
|
+
return result;
|
|
1034
|
+
}, {
|
|
1035
|
+
add: [],
|
|
1036
|
+
drop: [],
|
|
1037
|
+
alterSrc: [],
|
|
1038
|
+
alterDst: []
|
|
1039
|
+
});
|
|
1040
|
+
dbForeigns.forEach((dbF) => {
|
|
1041
|
+
const matchingEntityF = entityForeigns.find((entityF) => getKey(entityF) === getKey(dbF));
|
|
1042
|
+
if (!matchingEntityF) {
|
|
1043
|
+
const isColumnDropping = dbF.columns.some((col) => droppingColumnNames.includes(col));
|
|
1044
|
+
if (!isColumnDropping) {
|
|
1045
|
+
fkTo.drop.push(dbF);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
const linesTo = {
|
|
1050
|
+
add: genForeignDefinitions(table, fkTo.add),
|
|
1051
|
+
drop: genForeignDefinitions(table, fkTo.drop),
|
|
1052
|
+
alterSrc: genForeignDefinitions(table, fkTo.alterSrc),
|
|
1053
|
+
alterDst: genForeignDefinitions(table, fkTo.alterDst)
|
|
1054
|
+
};
|
|
1055
|
+
const hasLines = Object.values(linesTo).some((l) => l.up.length > 0 || l.down.length > 0);
|
|
1056
|
+
if (!hasLines) {
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
if (linesTo.add.up.length === 0 && linesTo.drop.up.length === 0 && linesTo.alterSrc.up.length === 0 && linesTo.alterDst.up.length === 0) {
|
|
1060
|
+
Naite.t("migrator:generateAlterCode_Foreigns:fkChangeCodeGenerationError", {
|
|
1061
|
+
table,
|
|
1062
|
+
entityForeigns,
|
|
1063
|
+
dbForeigns
|
|
1064
|
+
});
|
|
1065
|
+
throw new Error("FK 변경 코드 생성 오류");
|
|
1066
|
+
}
|
|
1067
|
+
const lines = [
|
|
1068
|
+
"import { Knex } from \"knex\";",
|
|
1069
|
+
"",
|
|
1070
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
1071
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
1072
|
+
...linesTo.drop.down,
|
|
1073
|
+
...linesTo.add.up,
|
|
1074
|
+
...linesTo.alterSrc.down,
|
|
1075
|
+
...linesTo.alterDst.up,
|
|
1076
|
+
"})",
|
|
1077
|
+
"}",
|
|
1078
|
+
"",
|
|
1079
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
1080
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
1081
|
+
...linesTo.add.down,
|
|
1082
|
+
...linesTo.alterDst.down,
|
|
1083
|
+
...linesTo.alterSrc.up,
|
|
1084
|
+
...linesTo.drop.up,
|
|
1085
|
+
"})",
|
|
1086
|
+
"}"
|
|
1087
|
+
];
|
|
1088
|
+
const formatted = await formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`);
|
|
1089
|
+
const title = [
|
|
1090
|
+
"alter",
|
|
1091
|
+
table,
|
|
1092
|
+
"foreigns"
|
|
1093
|
+
].join("_");
|
|
1094
|
+
return [{
|
|
1095
|
+
table,
|
|
1096
|
+
title,
|
|
1097
|
+
formatted,
|
|
1098
|
+
type: "normal"
|
|
1099
|
+
}];
|
|
1437
1100
|
}
|
|
1438
1101
|
/**
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
...await generateCreateCode_Foreign(entitySet.table, entitySet.foreigns)
|
|
1446
|
-
];
|
|
1102
|
+
* 주어진 EntitySet을 기반으로 테이블 CREATE 마이그레이션 코드를 생성합니다.
|
|
1103
|
+
* @param entitySet
|
|
1104
|
+
* @returns CREATE 마이그레이션 코드
|
|
1105
|
+
*/
|
|
1106
|
+
async function generateCreateCode(entitySet) {
|
|
1107
|
+
return [await generateCreateCode_ColumnAndIndexes(entitySet.table, entitySet.columns, entitySet.indexes), ...await generateCreateCode_Foreign(entitySet.table, entitySet.foreigns)];
|
|
1447
1108
|
}
|
|
1448
1109
|
/**
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
...a.columns.map((c)=>c.name)
|
|
1489
|
-
].join("-"));
|
|
1490
|
-
const dbIndexes = alphabetical(dbSet.indexes, (a)=>[
|
|
1491
|
-
a.type,
|
|
1492
|
-
...a.columns.map((c)=>c.name)
|
|
1493
|
-
].join("-"));
|
|
1494
|
-
const replaceNoActionOnMySQL = (f)=>{
|
|
1495
|
-
// MySQL에서 RESTRICT와 NO ACTION은 동일함
|
|
1496
|
-
const { onDelete, onUpdate } = f;
|
|
1497
|
-
return {
|
|
1498
|
-
...f,
|
|
1499
|
-
onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
|
|
1500
|
-
onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete
|
|
1501
|
-
};
|
|
1502
|
-
};
|
|
1503
|
-
const entityForeigns = alphabetical(entitySet.foreigns, (a)=>[
|
|
1504
|
-
a.to,
|
|
1505
|
-
...a.columns
|
|
1506
|
-
].join("-")).map((f)=>replaceNoActionOnMySQL(f));
|
|
1507
|
-
const dbForeigns = alphabetical(dbSet.foreigns, (a)=>[
|
|
1508
|
-
a.to,
|
|
1509
|
-
...a.columns
|
|
1510
|
-
].join("-")).map((f)=>replaceNoActionOnMySQL(f));
|
|
1511
|
-
// 삭제될 컬럼 목록 계산
|
|
1512
|
-
const droppingColumns = diff(dbColumns, entityColumns, (col)=>col.name);
|
|
1513
|
-
const alterCodes = [];
|
|
1514
|
-
// 1. columnsAndIndexes 처리
|
|
1515
|
-
const searchTextColumnNames = getSearchTextColumnNames(entitySet.table);
|
|
1516
|
-
const isEqualColumns = equal(entityColumns.map((column)=>normalizeColumnForComparison(column, searchTextColumnNames)), dbColumns.map((column)=>normalizeColumnForComparison(column, searchTextColumnNames)));
|
|
1517
|
-
const isEqualIndexes = equal(entityIndexes.map(setMigrationIndexDefaults), dbIndexes.map(setMigrationIndexDefaults));
|
|
1518
|
-
if (!isEqualColumns || !isEqualIndexes) {
|
|
1519
|
-
alterCodes.push(await generateAlterCode_ColumnAndIndexes(entitySet.table, entityColumns, entityIndexes, dbColumns, dbIndexes, dbSet.foreigns, compareDB));
|
|
1520
|
-
}
|
|
1521
|
-
// 2. foreigns 처리 (삭제될 컬럼 정보 전달)
|
|
1522
|
-
if (equal(entityForeigns, dbForeigns) === false) {
|
|
1523
|
-
alterCodes.push(await generateAlterCode_Foreigns(entitySet.table, entityForeigns, dbForeigns, droppingColumns));
|
|
1524
|
-
}
|
|
1525
|
-
if (alterCodes.every((alterCode)=>alterCode === null)) {
|
|
1526
|
-
return [];
|
|
1527
|
-
}
|
|
1528
|
-
return alterCodes.filter((alterCode)=>alterCode !== null).flat();
|
|
1110
|
+
* 주어진 entitySet을 목표로, dbSet을 현 상황으로 하여 테이블 ALTER 마이그레이션 코드를 생성합니다.
|
|
1111
|
+
* @param entitySet 현 상황의 MigrationSet
|
|
1112
|
+
* @param dbSet 목표 상황의 MigrationSet
|
|
1113
|
+
* @param compareDB PK 타입 변경 시 역참조 FK를 조회하기 위한 Knex 인스턴스 (선택)
|
|
1114
|
+
* @returns ALTER 마이그레이션 코드
|
|
1115
|
+
*/
|
|
1116
|
+
async function generateAlterCode(entitySet, dbSet, compareDB) {
|
|
1117
|
+
const replaceColumnDefaultTo = (col) => {
|
|
1118
|
+
return col;
|
|
1119
|
+
};
|
|
1120
|
+
const entityColumns = alphabetical(entitySet.columns, (a) => a.name).map(replaceColumnDefaultTo);
|
|
1121
|
+
const dbColumns = alphabetical(dbSet.columns, (a) => a.name).map(replaceColumnDefaultTo);
|
|
1122
|
+
const entityIndexes = alphabetical(entitySet.indexes, (a) => [a.type, ...a.columns.map((c) => c.name)].join("-"));
|
|
1123
|
+
const dbIndexes = alphabetical(dbSet.indexes, (a) => [a.type, ...a.columns.map((c) => c.name)].join("-"));
|
|
1124
|
+
const replaceNoActionOnMySQL = (f) => {
|
|
1125
|
+
const { onDelete, onUpdate } = f;
|
|
1126
|
+
return {
|
|
1127
|
+
...f,
|
|
1128
|
+
onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
|
|
1129
|
+
onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete
|
|
1130
|
+
};
|
|
1131
|
+
};
|
|
1132
|
+
const entityForeigns = alphabetical(entitySet.foreigns, (a) => [a.to, ...a.columns].join("-")).map((f) => replaceNoActionOnMySQL(f));
|
|
1133
|
+
const dbForeigns = alphabetical(dbSet.foreigns, (a) => [a.to, ...a.columns].join("-")).map((f) => replaceNoActionOnMySQL(f));
|
|
1134
|
+
const droppingColumns = diff(dbColumns, entityColumns, (col) => col.name);
|
|
1135
|
+
const alterCodes = [];
|
|
1136
|
+
const searchTextColumnNames = getSearchTextColumnNames(entitySet.table);
|
|
1137
|
+
const isEqualColumns = equal(entityColumns.map((column) => normalizeColumnForComparison(column, searchTextColumnNames)), dbColumns.map((column) => normalizeColumnForComparison(column, searchTextColumnNames)));
|
|
1138
|
+
const isEqualIndexes = equal(entityIndexes.map(setMigrationIndexDefaults), dbIndexes.map(setMigrationIndexDefaults));
|
|
1139
|
+
if (!isEqualColumns || !isEqualIndexes) {
|
|
1140
|
+
alterCodes.push(await generateAlterCode_ColumnAndIndexes(entitySet.table, entityColumns, entityIndexes, dbColumns, dbIndexes, dbSet.foreigns, compareDB));
|
|
1141
|
+
}
|
|
1142
|
+
if (!equal(entityForeigns, dbForeigns)) {
|
|
1143
|
+
alterCodes.push(await generateAlterCode_Foreigns(entitySet.table, entityForeigns, dbForeigns, droppingColumns));
|
|
1144
|
+
}
|
|
1145
|
+
if (alterCodes.every((alterCode) => alterCode === null)) {
|
|
1146
|
+
return [];
|
|
1147
|
+
}
|
|
1148
|
+
return alterCodes.filter((alterCode) => alterCode !== null).flat();
|
|
1529
1149
|
}
|
|
1530
1150
|
/**
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
downLines.push(` // ${fk.tableName}.${fk.columnName} FK 제약조건 복구`);
|
|
1623
|
-
downLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" ADD CONSTRAINT "${fk.constraintName}" FOREIGN KEY ("${fk.columnName}") REFERENCES "${table}"("id") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}');`);
|
|
1624
|
-
}
|
|
1625
|
-
const lines = [
|
|
1626
|
-
'import { Knex } from "knex";',
|
|
1627
|
-
"",
|
|
1628
|
-
"export async function up(knex: Knex): Promise<void> {",
|
|
1629
|
-
...upLines,
|
|
1630
|
-
"}",
|
|
1631
|
-
"",
|
|
1632
|
-
"export async function down(knex: Knex): Promise<void> {",
|
|
1633
|
-
...downLines,
|
|
1634
|
-
"}"
|
|
1635
|
-
];
|
|
1636
|
-
const formatted = formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`);
|
|
1637
|
-
return [
|
|
1638
|
-
{
|
|
1639
|
-
table,
|
|
1640
|
-
title: `alter_${table}_pk_type`,
|
|
1641
|
-
formatted,
|
|
1642
|
-
type: "normal"
|
|
1643
|
-
}
|
|
1644
|
-
];
|
|
1151
|
+
* PK 타입 변경 시 역참조 FK 제약조건을 처리하는 마이그레이션 코드를 생성합니다.
|
|
1152
|
+
*
|
|
1153
|
+
* PK 타입 변경 시 순서:
|
|
1154
|
+
* 1. FK 제약조건 삭제 (역참조 테이블들)
|
|
1155
|
+
* 2. 자기 참조 FK 삭제 (있는 경우)
|
|
1156
|
+
* 3. PK 제약조건 삭제
|
|
1157
|
+
* 4. PK 컬럼 타입 변경
|
|
1158
|
+
* 5. FK 컬럼 타입 변경 (역참조 테이블들)
|
|
1159
|
+
* 6. PK 제약조건 복구
|
|
1160
|
+
* 7. 자기 참조 FK 복구
|
|
1161
|
+
* 8. FK 제약조건 복구
|
|
1162
|
+
*/
|
|
1163
|
+
async function generatePkTypeChangeMigration(table, entityIdCol, dbIdCol, _entityColumns, _entityIndexes, _dbColumns, _dbIndexes, _dbForeigns, compareDB) {
|
|
1164
|
+
const referencingFKs = await PostgreSQLSchemaReader.getReferencingForeignKeys(compareDB, table);
|
|
1165
|
+
const selfReferencingFKs = referencingFKs.filter((fk) => fk.tableName === table);
|
|
1166
|
+
const externalReferencingFKs = referencingFKs.filter((fk) => fk.tableName !== table);
|
|
1167
|
+
const pkConstraintName = `${table}_pkey`;
|
|
1168
|
+
const newPkPgType = getPkPgType(entityIdCol);
|
|
1169
|
+
const oldPkPgType = getPkPgType(dbIdCol);
|
|
1170
|
+
const upLines = [];
|
|
1171
|
+
for (const fk of externalReferencingFKs) {
|
|
1172
|
+
upLines.push(` // ${fk.tableName}.${fk.columnName} FK 제약조건 삭제`);
|
|
1173
|
+
upLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" DROP CONSTRAINT "${fk.constraintName}"');`);
|
|
1174
|
+
}
|
|
1175
|
+
for (const fk of selfReferencingFKs) {
|
|
1176
|
+
upLines.push(` // 자기 참조 FK 삭제: ${fk.columnName}`);
|
|
1177
|
+
upLines.push(` await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${fk.constraintName}"');`);
|
|
1178
|
+
}
|
|
1179
|
+
upLines.push(` // PK 제약조건 삭제`);
|
|
1180
|
+
upLines.push(` await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${pkConstraintName}"');`);
|
|
1181
|
+
upLines.push(` // PK 컬럼 타입 변경`);
|
|
1182
|
+
upLines.push(` await knex.raw('ALTER TABLE "${table}" ALTER COLUMN "id" TYPE ${newPkPgType} USING "id"::${newPkPgType}');`);
|
|
1183
|
+
for (const fk of referencingFKs) {
|
|
1184
|
+
upLines.push(` // ${fk.tableName}.${fk.columnName} 컬럼 타입 변경`);
|
|
1185
|
+
upLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" ALTER COLUMN "${fk.columnName}" TYPE ${newPkPgType} USING "${fk.columnName}"::${newPkPgType}');`);
|
|
1186
|
+
}
|
|
1187
|
+
upLines.push(` // PK 제약조건 복구`);
|
|
1188
|
+
upLines.push(` await knex.raw('ALTER TABLE "${table}" ADD CONSTRAINT "${pkConstraintName}" PRIMARY KEY ("id")');`);
|
|
1189
|
+
for (const fk of selfReferencingFKs) {
|
|
1190
|
+
upLines.push(` // 자기 참조 FK 복구: ${fk.columnName}`);
|
|
1191
|
+
upLines.push(` await knex.raw('ALTER TABLE "${table}" ADD CONSTRAINT "${fk.constraintName}" FOREIGN KEY ("${fk.columnName}") REFERENCES "${table}"("id") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}');`);
|
|
1192
|
+
}
|
|
1193
|
+
for (const fk of externalReferencingFKs) {
|
|
1194
|
+
upLines.push(` // ${fk.tableName}.${fk.columnName} FK 제약조건 복구`);
|
|
1195
|
+
upLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" ADD CONSTRAINT "${fk.constraintName}" FOREIGN KEY ("${fk.columnName}") REFERENCES "${table}"("id") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}');`);
|
|
1196
|
+
}
|
|
1197
|
+
const downLines = [];
|
|
1198
|
+
for (const fk of externalReferencingFKs) {
|
|
1199
|
+
downLines.push(` // ${fk.tableName}.${fk.columnName} FK 제약조건 삭제`);
|
|
1200
|
+
downLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" DROP CONSTRAINT "${fk.constraintName}"');`);
|
|
1201
|
+
}
|
|
1202
|
+
for (const fk of selfReferencingFKs) {
|
|
1203
|
+
downLines.push(` // 자기 참조 FK 삭제: ${fk.columnName}`);
|
|
1204
|
+
downLines.push(` await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${fk.constraintName}"');`);
|
|
1205
|
+
}
|
|
1206
|
+
downLines.push(` // PK 제약조건 삭제`);
|
|
1207
|
+
downLines.push(` await knex.raw('ALTER TABLE "${table}" DROP CONSTRAINT "${pkConstraintName}"');`);
|
|
1208
|
+
downLines.push(` // PK 컬럼 타입 원복`);
|
|
1209
|
+
downLines.push(` await knex.raw('ALTER TABLE "${table}" ALTER COLUMN "id" TYPE ${oldPkPgType} USING "id"::${oldPkPgType}');`);
|
|
1210
|
+
for (const fk of referencingFKs) {
|
|
1211
|
+
downLines.push(` // ${fk.tableName}.${fk.columnName} 컬럼 타입 원복`);
|
|
1212
|
+
downLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" ALTER COLUMN "${fk.columnName}" TYPE ${oldPkPgType} USING "${fk.columnName}"::${oldPkPgType}');`);
|
|
1213
|
+
}
|
|
1214
|
+
downLines.push(` // PK 제약조건 복구`);
|
|
1215
|
+
downLines.push(` await knex.raw('ALTER TABLE "${table}" ADD CONSTRAINT "${pkConstraintName}" PRIMARY KEY ("id")');`);
|
|
1216
|
+
for (const fk of selfReferencingFKs) {
|
|
1217
|
+
downLines.push(` // 자기 참조 FK 복구: ${fk.columnName}`);
|
|
1218
|
+
downLines.push(` await knex.raw('ALTER TABLE "${table}" ADD CONSTRAINT "${fk.constraintName}" FOREIGN KEY ("${fk.columnName}") REFERENCES "${table}"("id") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}');`);
|
|
1219
|
+
}
|
|
1220
|
+
for (const fk of externalReferencingFKs) {
|
|
1221
|
+
downLines.push(` // ${fk.tableName}.${fk.columnName} FK 제약조건 복구`);
|
|
1222
|
+
downLines.push(` await knex.raw('ALTER TABLE "${fk.tableName}" ADD CONSTRAINT "${fk.constraintName}" FOREIGN KEY ("${fk.columnName}") REFERENCES "${table}"("id") ON UPDATE ${fk.onUpdate} ON DELETE ${fk.onDelete}');`);
|
|
1223
|
+
}
|
|
1224
|
+
const lines = [
|
|
1225
|
+
"import { Knex } from \"knex\";",
|
|
1226
|
+
"",
|
|
1227
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
1228
|
+
...upLines,
|
|
1229
|
+
"}",
|
|
1230
|
+
"",
|
|
1231
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
1232
|
+
...downLines,
|
|
1233
|
+
"}"
|
|
1234
|
+
];
|
|
1235
|
+
const formatted = await formatCode(lines.join("\n"), "typescript", `src/migration/${table}.ts`);
|
|
1236
|
+
return [{
|
|
1237
|
+
table,
|
|
1238
|
+
title: `alter_${table}_pk_type`,
|
|
1239
|
+
formatted,
|
|
1240
|
+
type: "normal"
|
|
1241
|
+
}];
|
|
1645
1242
|
}
|
|
1646
1243
|
/**
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
return "integer";
|
|
1244
|
+
* PK 컬럼의 PostgreSQL 타입 문자열을 반환합니다.
|
|
1245
|
+
*/
|
|
1246
|
+
function getPkPgType(col) {
|
|
1247
|
+
if (col.type === "string") {
|
|
1248
|
+
return col.length !== undefined ? `varchar(${col.length})` : "text";
|
|
1249
|
+
}
|
|
1250
|
+
if (col.type === "uuid") {
|
|
1251
|
+
return "uuid";
|
|
1252
|
+
}
|
|
1253
|
+
return "integer";
|
|
1658
1254
|
}
|
|
1255
|
+
var SEARCH_TEXT_HELPER_DEFINITIONS, SearchTextExpressionParser;
|
|
1256
|
+
var init_code_generation = __esmMin((() => {
|
|
1257
|
+
init_entity_manager();
|
|
1258
|
+
init_naite();
|
|
1259
|
+
init_types();
|
|
1260
|
+
init_formatter();
|
|
1261
|
+
init_utils();
|
|
1262
|
+
init_postgresql_schema_reader();
|
|
1263
|
+
SEARCH_TEXT_HELPER_DEFINITIONS = {
|
|
1264
|
+
"text-array": `await knex.raw(\`CREATE OR REPLACE FUNCTION sonamu_text_array_agg(arr text[], ci boolean DEFAULT true)
|
|
1265
|
+
RETURNS text
|
|
1266
|
+
LANGUAGE sql IMMUTABLE PARALLEL SAFE RETURNS NULL ON NULL INPUT
|
|
1267
|
+
AS $$
|
|
1268
|
+
SELECT string_agg(
|
|
1269
|
+
CASE WHEN ci THEN lower(value) ELSE value END,
|
|
1270
|
+
' '
|
|
1271
|
+
)
|
|
1272
|
+
FROM unnest(arr) AS value
|
|
1273
|
+
$$\`);`,
|
|
1274
|
+
"jsonb-array": `await knex.raw(\`CREATE OR REPLACE FUNCTION sonamu_jsonb_array_agg(arr jsonb, ci boolean DEFAULT true)
|
|
1275
|
+
RETURNS text
|
|
1276
|
+
LANGUAGE sql IMMUTABLE PARALLEL SAFE RETURNS NULL ON NULL INPUT
|
|
1277
|
+
AS $$
|
|
1278
|
+
SELECT string_agg(
|
|
1279
|
+
CASE WHEN ci THEN lower(value) ELSE value END,
|
|
1280
|
+
' '
|
|
1281
|
+
)
|
|
1282
|
+
FROM jsonb_array_elements_text(arr)
|
|
1283
|
+
$$\`);`
|
|
1284
|
+
};
|
|
1285
|
+
SearchTextExpressionParser = class {
|
|
1286
|
+
index = 0;
|
|
1287
|
+
constructor(tokens) {
|
|
1288
|
+
this.tokens = tokens;
|
|
1289
|
+
}
|
|
1290
|
+
isAtEnd() {
|
|
1291
|
+
return this.index >= this.tokens.length;
|
|
1292
|
+
}
|
|
1293
|
+
parseExpression() {
|
|
1294
|
+
return this.parseConcat();
|
|
1295
|
+
}
|
|
1296
|
+
parseConcat() {
|
|
1297
|
+
const parts = [this.parsePostfix()];
|
|
1298
|
+
while (this.matchOperator("||")) {
|
|
1299
|
+
parts.push(this.parsePostfix());
|
|
1300
|
+
}
|
|
1301
|
+
return parts.length === 1 ? parts[0] : {
|
|
1302
|
+
type: "concat",
|
|
1303
|
+
parts
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
parsePostfix() {
|
|
1307
|
+
let node = this.parsePrimary();
|
|
1308
|
+
while (true) {
|
|
1309
|
+
if (this.matchOperator("::")) {
|
|
1310
|
+
node = {
|
|
1311
|
+
type: "cast",
|
|
1312
|
+
expr: node,
|
|
1313
|
+
targetType: this.parseTypeName()
|
|
1314
|
+
};
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
if (this.matchIdentifier("collate")) {
|
|
1318
|
+
const token = this.consumeCollationToken();
|
|
1319
|
+
node = {
|
|
1320
|
+
type: "collate",
|
|
1321
|
+
expr: node,
|
|
1322
|
+
collation: token.value,
|
|
1323
|
+
quoted: token.type === "quotedIdentifier"
|
|
1324
|
+
};
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
return node;
|
|
1330
|
+
}
|
|
1331
|
+
parsePrimary() {
|
|
1332
|
+
const token = this.consumeToken("표현식");
|
|
1333
|
+
if (token.type === "symbol" && token.value === "(") {
|
|
1334
|
+
const node = this.parseExpression();
|
|
1335
|
+
this.expectSymbol(")");
|
|
1336
|
+
return node;
|
|
1337
|
+
}
|
|
1338
|
+
if (token.type === "string") {
|
|
1339
|
+
return {
|
|
1340
|
+
type: "string",
|
|
1341
|
+
value: token.value
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
if (token.type === "identifier" || token.type === "quotedIdentifier") {
|
|
1345
|
+
const lowerName = token.value.toLowerCase();
|
|
1346
|
+
if (token.type === "identifier" && (lowerName === "true" || lowerName === "false")) {
|
|
1347
|
+
return {
|
|
1348
|
+
type: "boolean",
|
|
1349
|
+
value: lowerName === "true"
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
if (this.matchSymbol("(")) {
|
|
1353
|
+
if (token.type === "identifier" && lowerName === "trim" && this.isTrimBothFromForm()) {
|
|
1354
|
+
this.index += 2;
|
|
1355
|
+
const arg = this.parseExpression();
|
|
1356
|
+
this.expectSymbol(")");
|
|
1357
|
+
return {
|
|
1358
|
+
type: "function",
|
|
1359
|
+
name: "trim",
|
|
1360
|
+
args: [arg]
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
const args = this.parseFunctionArgs();
|
|
1364
|
+
return {
|
|
1365
|
+
type: "function",
|
|
1366
|
+
name: token.value,
|
|
1367
|
+
args
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
return {
|
|
1371
|
+
type: "identifier",
|
|
1372
|
+
name: token.value,
|
|
1373
|
+
quoted: token.type === "quotedIdentifier"
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
throw new Error(`지원되지 않는 searchText expression token: ${token.type}`);
|
|
1377
|
+
}
|
|
1378
|
+
parseFunctionArgs() {
|
|
1379
|
+
if (this.matchSymbol(")")) {
|
|
1380
|
+
return [];
|
|
1381
|
+
}
|
|
1382
|
+
const args = [];
|
|
1383
|
+
do {
|
|
1384
|
+
args.push(this.parseExpression());
|
|
1385
|
+
} while (this.matchSymbol(","));
|
|
1386
|
+
this.expectSymbol(")");
|
|
1387
|
+
return args;
|
|
1388
|
+
}
|
|
1389
|
+
parseTypeName() {
|
|
1390
|
+
const parts = [];
|
|
1391
|
+
while (true) {
|
|
1392
|
+
const token = this.peek();
|
|
1393
|
+
if (token?.type === "identifier" || token?.type === "quotedIdentifier" || token?.type === "symbol" && (token.value === "(" || token.value === ")" || token.value === ",")) {
|
|
1394
|
+
if (token.type === "symbol") {
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
parts.push(token.value.toLowerCase());
|
|
1398
|
+
this.index += 1;
|
|
1399
|
+
continue;
|
|
1400
|
+
}
|
|
1401
|
+
break;
|
|
1402
|
+
}
|
|
1403
|
+
if (parts.length === 0) {
|
|
1404
|
+
throw new Error("타입 캐스팅 대상 타입을 찾을 수 없습니다.");
|
|
1405
|
+
}
|
|
1406
|
+
return parts.join(" ");
|
|
1407
|
+
}
|
|
1408
|
+
consumeCollationToken() {
|
|
1409
|
+
const token = this.peek();
|
|
1410
|
+
if (token?.type !== "identifier" && token?.type !== "quotedIdentifier") {
|
|
1411
|
+
throw new Error("COLLATE 대상 식별자를 찾을 수 없습니다.");
|
|
1412
|
+
}
|
|
1413
|
+
this.index += 1;
|
|
1414
|
+
return token;
|
|
1415
|
+
}
|
|
1416
|
+
isTrimBothFromForm() {
|
|
1417
|
+
const bothToken = this.peek();
|
|
1418
|
+
const fromToken = this.peek(1);
|
|
1419
|
+
return bothToken?.type === "identifier" && bothToken.value.toLowerCase() === "both" && fromToken?.type === "identifier" && fromToken.value.toLowerCase() === "from";
|
|
1420
|
+
}
|
|
1421
|
+
expectSymbol(value) {
|
|
1422
|
+
if (!this.matchSymbol(value)) {
|
|
1423
|
+
throw new Error(`"${value}" 토큰이 필요합니다.`);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
matchSymbol(value) {
|
|
1427
|
+
const token = this.peek();
|
|
1428
|
+
if (token?.type === "symbol" && token.value === value) {
|
|
1429
|
+
this.index += 1;
|
|
1430
|
+
return true;
|
|
1431
|
+
}
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
matchOperator(value) {
|
|
1435
|
+
const token = this.peek();
|
|
1436
|
+
if (token?.type === "operator" && token.value === value) {
|
|
1437
|
+
this.index += 1;
|
|
1438
|
+
return true;
|
|
1439
|
+
}
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
matchIdentifier(value) {
|
|
1443
|
+
const token = this.peek();
|
|
1444
|
+
if (token?.type === "identifier" && token.value.toLowerCase() === value.toLowerCase()) {
|
|
1445
|
+
this.index += 1;
|
|
1446
|
+
return true;
|
|
1447
|
+
}
|
|
1448
|
+
return false;
|
|
1449
|
+
}
|
|
1450
|
+
consumeToken(context) {
|
|
1451
|
+
const token = this.peek();
|
|
1452
|
+
if (!token) {
|
|
1453
|
+
throw new Error(`${context} 토큰이 필요합니다.`);
|
|
1454
|
+
}
|
|
1455
|
+
this.index += 1;
|
|
1456
|
+
return token;
|
|
1457
|
+
}
|
|
1458
|
+
peek(offset = 0) {
|
|
1459
|
+
return this.tokens[this.index + offset];
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
}));
|
|
1659
1463
|
|
|
1660
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24vY29kZS1nZW5lcmF0aW9uLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBlcXVhbCBmcm9tIFwiZmFzdC1kZWVwLWVxdWFsXCI7XG5pbXBvcnQgdHlwZSB7IEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgYWxwaGFiZXRpY2FsLCBkaWZmIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIsIE5haXRlIH0gZnJvbSBcIi4uXCI7XG5pbXBvcnQgdHlwZSB7XG4gIEVudGl0eVByb3AsXG4gIEdlbk1pZ3JhdGlvbkNvZGUsXG4gIE1pZ3JhdGlvbkNvbHVtbixcbiAgTWlncmF0aW9uRm9yZWlnbixcbiAgTWlncmF0aW9uSW5kZXgsXG4gIE1pZ3JhdGlvblNldCxcbn0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc1NlYXJjaFRleHRQcm9wIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBmb3JtYXRDb2RlIH0gZnJvbSBcIi4uL3V0aWxzL2Zvcm1hdHRlclwiO1xuaW1wb3J0IHsgZGlmZmVyZW5jZVdpdGgsIGludGVyc2VjdGlvbkJ5IH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyIH0gZnJvbSBcIi4vcG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyXCI7XG5cbi8qKlxuICog7Lus65+8IOygleydmCDqsrDqs7wg7YOA7J6FXG4gKiAtIGJ1aWxkZXI6IEtuZXggdGFibGUgYnVpbGRlciDrqZTshJzrk5zroZwg7Iuk7ZaJ7ZWgIOq1rOusuCAodGFibGUueHh4KCkpXG4gKiAtIHJhdzoga25leC5yYXcoKeuhnCDsi6TtlontlaAg6rWs66y4XG4gKi9cbnR5cGUgQ29sdW1uRGVmaW5pdGlvblJlc3VsdCA9IHtcbiAgYnVpbGRlcjogc3RyaW5nW107XG4gIHJhdzogc3RyaW5nW107XG59O1xuXG50eXBlIFNlYXJjaFRleHRIZWxwZXJLaW5kID0gXCJ0ZXh0LWFycmF5XCIgfCBcImpzb25iLWFycmF5XCI7XG5cbnR5cGUgU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbiA9XG4gIHwgeyB0eXBlOiBcImlkZW50aWZpZXJcIjsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiBcInF1b3RlZElkZW50aWZpZXJcIjsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiBcInN0cmluZ1wiOyB2YWx1ZTogc3RyaW5nIH1cbiAgfCB7IHR5cGU6IFwic3ltYm9sXCI7IHZhbHVlOiBcIihcIiB8IFwiKVwiIHwgXCIsXCIgfVxuICB8IHsgdHlwZTogXCJvcGVyYXRvclwiOyB2YWx1ZTogXCJ8fFwiIHwgXCI6OlwiIH07XG5cbnR5cGUgU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlID1cbiAgfCB7IHR5cGU6IFwiaWRlbnRpZmllclwiOyBuYW1lOiBzdHJpbmc7IHF1b3RlZDogYm9vbGVhbiB9XG4gIHwgeyB0eXBlOiBcInN0cmluZ1wiOyB2YWx1ZTogc3RyaW5nIH1cbiAgfCB7IHR5cGU6IFwiYm9vbGVhblwiOyB2YWx1ZTogYm9vbGVhbiB9XG4gIHwgeyB0eXBlOiBcImZ1bmN0aW9uXCI7IG5hbWU6IHN0cmluZzsgYXJnczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlW10gfVxuICB8IHsgdHlwZTogXCJjb25jYXRcIjsgcGFydHM6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZVtdIH1cbiAgfCB7IHR5cGU6IFwiY29sbGF0ZVwiOyBleHByOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGU7IGNvbGxhdGlvbjogc3RyaW5nOyBxdW90ZWQ6IGJvb2xlYW4gfVxuICB8IHsgdHlwZTogXCJjYXN0XCI7IGV4cHI6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZTsgdGFyZ2V0VHlwZTogc3RyaW5nIH07XG5cbmNvbnN0IFNFQVJDSF9URVhUX0hFTFBFUl9ERUZJTklUSU9OUzogUmVjb3JkPFNlYXJjaFRleHRIZWxwZXJLaW5kLCBzdHJpbmc+ID0ge1xuICBcInRleHQtYXJyYXlcIjogYGF3YWl0IGtuZXgucmF3KFxcYENSRUFURSBPUiBSRVBMQUNFIEZVTkNUSU9OIHNvbmFtdV90ZXh0X2FycmF5X2FnZyhhcnIgdGV4dFtdLCBjaSBib29sZWFuIERFRkFVTFQgdHJ1ZSlcblJFVFVSTlMgdGV4dFxuTEFOR1VBR0Ugc3FsIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFIFJFVFVSTlMgTlVMTCBPTiBOVUxMIElOUFVUXG5BUyAkJFxuICBTRUxFQ1Qgc3RyaW5nX2FnZyhcbiAgICBDQVNFIFdIRU4gY2kgVEhFTiBsb3dlcih2YWx1ZSkgRUxTRSB2YWx1ZSBFTkQsXG4gICAgJyAnXG4gIClcbiAgRlJPTSB1bm5lc3QoYXJyKSBBUyB2YWx1ZVxuJCRcXGApO2AsXG4gIFwianNvbmItYXJyYXlcIjogYGF3YWl0IGtuZXgucmF3KFxcYENSRUFURSBPUiBSRVBMQUNFIEZVTkNUSU9OIHNvbmFtdV9qc29uYl9hcnJheV9hZ2coYXJyIGpzb25iLCBjaSBib29sZWFuIERFRkFVTFQgdHJ1ZSlcblJFVFVSTlMgdGV4dFxuTEFOR1VBR0Ugc3FsIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFIFJFVFVSTlMgTlVMTCBPTiBOVUxMIElOUFVUXG5BUyAkJFxuICBTRUxFQ1Qgc3RyaW5nX2FnZyhcbiAgICBDQVNFIFdIRU4gY2kgVEhFTiBsb3dlcih2YWx1ZSkgRUxTRSB2YWx1ZSBFTkQsXG4gICAgJyAnXG4gIClcbiAgRlJPTSBqc29uYl9hcnJheV9lbGVtZW50c190ZXh0KGFycilcbiQkXFxgKTtgLFxufTtcblxuY2xhc3MgU2VhcmNoVGV4dEV4cHJlc3Npb25QYXJzZXIge1xuICBwcml2YXRlIGluZGV4ID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHRva2VuczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbltdKSB7fVxuXG4gIGlzQXRFbmQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZXggPj0gdGhpcy50b2tlbnMubGVuZ3RoO1xuICB9XG5cbiAgcGFyc2VFeHByZXNzaW9uKCk6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VDb25jYXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VDb25jYXQoKTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlIHtcbiAgICBjb25zdCBwYXJ0cyA9IFt0aGlzLnBhcnNlUG9zdGZpeCgpXTtcblxuICAgIHdoaWxlICh0aGlzLm1hdGNoT3BlcmF0b3IoXCJ8fFwiKSkge1xuICAgICAgcGFydHMucHVzaCh0aGlzLnBhcnNlUG9zdGZpeCgpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFydHMubGVuZ3RoID09PSAxID8gcGFydHNbMF0gOiB7IHR5cGU6IFwiY29uY2F0XCIsIHBhcnRzIH07XG4gIH1cblxuICBwcml2YXRlIHBhcnNlUG9zdGZpeCgpOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUge1xuICAgIGxldCBub2RlID0gdGhpcy5wYXJzZVByaW1hcnkoKTtcblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAodGhpcy5tYXRjaE9wZXJhdG9yKFwiOjpcIikpIHtcbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICB0eXBlOiBcImNhc3RcIixcbiAgICAgICAgICBleHByOiBub2RlLFxuICAgICAgICAgIHRhcmdldFR5cGU6IHRoaXMucGFyc2VUeXBlTmFtZSgpLFxuICAgICAgICB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubWF0Y2hJZGVudGlmaWVyKFwiY29sbGF0ZVwiKSkge1xuICAgICAgICBjb25zdCB0b2tlbiA9IHRoaXMuY29uc3VtZUNvbGxhdGlvblRva2VuKCk7XG4gICAgICAgIG5vZGUgPSB7XG4gICAgICAgICAgdHlwZTogXCJjb2xsYXRlXCIsXG4gICAgICAgICAgZXhwcjogbm9kZSxcbiAgICAgICAgICBjb2xsYXRpb246IHRva2VuLnZhbHVlLFxuICAgICAgICAgIHF1b3RlZDogdG9rZW4udHlwZSA9PT0gXCJxdW90ZWRJZGVudGlmaWVyXCIsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VQcmltYXJ5KCk6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLmNvbnN1bWVUb2tlbihcIu2RnO2YhOyLnVwiKTtcblxuICAgIGlmICh0b2tlbi50eXBlID09PSBcInN5bWJvbFwiICYmIHRva2VuLnZhbHVlID09PSBcIihcIikge1xuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMucGFyc2VFeHByZXNzaW9uKCk7XG4gICAgICB0aGlzLmV4cGVjdFN5bWJvbChcIilcIik7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG5cbiAgICBpZiAodG9rZW4udHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJzdHJpbmdcIiwgdmFsdWU6IHRva2VuLnZhbHVlIH07XG4gICAgfVxuXG4gICAgaWYgKHRva2VuLnR5cGUgPT09IFwiaWRlbnRpZmllclwiIHx8IHRva2VuLnR5cGUgPT09IFwicXVvdGVkSWRlbnRpZmllclwiKSB7XG4gICAgICBjb25zdCBsb3dlck5hbWUgPSB0b2tlbi52YWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKHRva2VuLnR5cGUgPT09IFwiaWRlbnRpZmllclwiICYmIChsb3dlck5hbWUgPT09IFwidHJ1ZVwiIHx8IGxvd2VyTmFtZSA9PT0gXCJmYWxzZVwiKSkge1xuICAgICAgICByZXR1cm4geyB0eXBlOiBcImJvb2xlYW5cIiwgdmFsdWU6IGxvd2VyTmFtZSA9PT0gXCJ0cnVlXCIgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubWF0Y2hTeW1ib2woXCIoXCIpKSB7XG4gICAgICAgIGlmICh0b2tlbi50eXBlID09PSBcImlkZW50aWZpZXJcIiAmJiBsb3dlck5hbWUgPT09IFwidHJpbVwiICYmIHRoaXMuaXNUcmltQm90aEZyb21Gb3JtKCkpIHtcbiAgICAgICAgICB0aGlzLmluZGV4ICs9IDI7XG4gICAgICAgICAgY29uc3QgYXJnID0gdGhpcy5wYXJzZUV4cHJlc3Npb24oKTtcbiAgICAgICAgICB0aGlzLmV4cGVjdFN5bWJvbChcIilcIik7XG4gICAgICAgICAgcmV0dXJuIHsgdHlwZTogXCJmdW5jdGlvblwiLCBuYW1lOiBcInRyaW1cIiwgYXJnczogW2FyZ10gfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFyZ3MgPSB0aGlzLnBhcnNlRnVuY3Rpb25BcmdzKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgICAgICAgIG5hbWU6IHRva2VuLnZhbHVlLFxuICAgICAgICAgIGFyZ3MsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiaWRlbnRpZmllclwiLFxuICAgICAgICBuYW1lOiB0b2tlbi52YWx1ZSxcbiAgICAgICAgcXVvdGVkOiB0b2tlbi50eXBlID09PSBcInF1b3RlZElkZW50aWZpZXJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGDsp4Dsm5DrkJjsp4Ag7JWK64qUIHNlYXJjaFRleHQgZXhwcmVzc2lvbiB0b2tlbjogJHt0b2tlbi50eXBlfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUZ1bmN0aW9uQXJncygpOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGVbXSB7XG4gICAgaWYgKHRoaXMubWF0Y2hTeW1ib2woXCIpXCIpKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgYXJnczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlW10gPSBbXTtcbiAgICBkbyB7XG4gICAgICBhcmdzLnB1c2godGhpcy5wYXJzZUV4cHJlc3Npb24oKSk7XG4gICAgfSB3aGlsZSAodGhpcy5tYXRjaFN5bWJvbChcIixcIikpO1xuXG4gICAgdGhpcy5leHBlY3RTeW1ib2woXCIpXCIpO1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVR5cGVOYW1lKCk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICAgIGlmIChcbiAgICAgICAgdG9rZW4/LnR5cGUgPT09IFwiaWRlbnRpZmllclwiIHx8XG4gICAgICAgIHRva2VuPy50eXBlID09PSBcInF1b3RlZElkZW50aWZpZXJcIiB8fFxuICAgICAgICAodG9rZW4/LnR5cGUgPT09IFwic3ltYm9sXCIgJiZcbiAgICAgICAgICAodG9rZW4udmFsdWUgPT09IFwiKFwiIHx8IHRva2VuLnZhbHVlID09PSBcIilcIiB8fCB0b2tlbi52YWx1ZSA9PT0gXCIsXCIpKVxuICAgICAgKSB7XG4gICAgICAgIGlmICh0b2tlbi50eXBlID09PSBcInN5bWJvbFwiKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJ0cy5wdXNoKHRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAocGFydHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCLtg4DsnoUg7LqQ7Iqk7YyFIOuMgOyDgSDtg4DsnoXsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJ0cy5qb2luKFwiIFwiKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3VtZUNvbGxhdGlvblRva2VuKCk6IEV4dHJhY3Q8XG4gICAgU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbixcbiAgICB7IHR5cGU6IFwiaWRlbnRpZmllclwiIHwgXCJxdW90ZWRJZGVudGlmaWVyXCIgfVxuICA+IHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMucGVlaygpO1xuICAgIGlmICh0b2tlbj8udHlwZSAhPT0gXCJpZGVudGlmaWVyXCIgJiYgdG9rZW4/LnR5cGUgIT09IFwicXVvdGVkSWRlbnRpZmllclwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDT0xMQVRFIOuMgOyDgSDsi53rs4TsnpDrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6QuXCIpO1xuICAgIH1cbiAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1RyaW1Cb3RoRnJvbUZvcm0oKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYm90aFRva2VuID0gdGhpcy5wZWVrKCk7XG4gICAgY29uc3QgZnJvbVRva2VuID0gdGhpcy5wZWVrKDEpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIGJvdGhUb2tlbj8udHlwZSA9PT0gXCJpZGVudGlmaWVyXCIgJiZcbiAgICAgIGJvdGhUb2tlbi52YWx1ZS50b0xvd2VyQ2FzZSgpID09PSBcImJvdGhcIiAmJlxuICAgICAgZnJvbVRva2VuPy50eXBlID09PSBcImlkZW50aWZpZXJcIiAmJlxuICAgICAgZnJvbVRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkgPT09IFwiZnJvbVwiXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZXhwZWN0U3ltYm9sKHZhbHVlOiBcIihcIiB8IFwiKVwiIHwgXCIsXCIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMubWF0Y2hTeW1ib2wodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFwiJHt2YWx1ZX1cIiDthqDtgbDsnbQg7ZWE7JqU7ZWp64uI64ukLmApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hTeW1ib2wodmFsdWU6IFwiKFwiIHwgXCIpXCIgfCBcIixcIik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5wZWVrKCk7XG4gICAgaWYgKHRva2VuPy50eXBlID09PSBcInN5bWJvbFwiICYmIHRva2VuLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgdGhpcy5pbmRleCArPSAxO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hPcGVyYXRvcih2YWx1ZTogXCJ8fFwiIHwgXCI6OlwiKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICBpZiAodG9rZW4/LnR5cGUgPT09IFwib3BlcmF0b3JcIiAmJiB0b2tlbi52YWx1ZSA9PT0gdmFsdWUpIHtcbiAgICAgIHRoaXMuaW5kZXggKz0gMTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIG1hdGNoSWRlbnRpZmllcih2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICBpZiAodG9rZW4/LnR5cGUgPT09IFwiaWRlbnRpZmllclwiICYmIHRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkgPT09IHZhbHVlLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIHRoaXMuaW5kZXggKz0gMTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGNvbnN1bWVUb2tlbihjb250ZXh0OiBzdHJpbmcpOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMucGVlaygpO1xuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fSDthqDtgbDsnbQg7ZWE7JqU7ZWp64uI64ukLmApO1xuICAgIH1cbiAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSBwZWVrKG9mZnNldCA9IDApOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbnNbdGhpcy5pbmRleCArIG9mZnNldF07XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbjogTWlncmF0aW9uSW5kZXhbXCJjb2x1bW5zXCJdW251bWJlcl0pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gY29sdW1uLm9wY2xhc3MgPz8gY29sdW1uLnZlY3Rvck9wcztcbn1cblxuZnVuY3Rpb24gdG9rZW5pemVTZWFyY2hUZXh0RXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuW10ge1xuICBjb25zdCB0b2tlbnM6IFNlYXJjaFRleHRFeHByZXNzaW9uVG9rZW5bXSA9IFtdO1xuICBsZXQgaW5kZXggPSAwO1xuXG4gIHdoaWxlIChpbmRleCA8IGV4cHJlc3Npb24ubGVuZ3RoKSB7XG4gICAgY29uc3QgY2hhciA9IGV4cHJlc3Npb25baW5kZXhdO1xuXG4gICAgaWYgKGNoYXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKC9cXHMvLnRlc3QoY2hhcikpIHtcbiAgICAgIGluZGV4ICs9IDE7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZXhwcmVzc2lvbi5zdGFydHNXaXRoKFwifHxcIiwgaW5kZXgpKSB7XG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwib3BlcmF0b3JcIiwgdmFsdWU6IFwifHxcIiB9KTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZXhwcmVzc2lvbi5zdGFydHNXaXRoKFwiOjpcIiwgaW5kZXgpKSB7XG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwib3BlcmF0b3JcIiwgdmFsdWU6IFwiOjpcIiB9KTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoY2hhciA9PT0gXCIoXCIgfHwgY2hhciA9PT0gXCIpXCIgfHwgY2hhciA9PT0gXCIsXCIpIHtcbiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogXCJzeW1ib2xcIiwgdmFsdWU6IGNoYXIgfSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKGNoYXIgPT09IFwiJ1wiKSB7XG4gICAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgZXhwcmVzc2lvbi5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IGV4cHJlc3Npb25baW5kZXhdO1xuICAgICAgICBpZiAoY3VycmVudCA9PT0gXCInXCIpIHtcbiAgICAgICAgICBpZiAoZXhwcmVzc2lvbltpbmRleCArIDFdID09PSBcIidcIikge1xuICAgICAgICAgICAgdmFsdWUgKz0gXCInXCI7XG4gICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlICs9IGN1cnJlbnQ7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG5cbiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogXCJzdHJpbmdcIiwgdmFsdWUgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoY2hhciA9PT0gJ1wiJykge1xuICAgICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgIHdoaWxlIChpbmRleCA8IGV4cHJlc3Npb24ubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSBleHByZXNzaW9uW2luZGV4XTtcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09ICdcIicpIHtcbiAgICAgICAgICBpZiAoZXhwcmVzc2lvbltpbmRleCArIDFdID09PSAnXCInKSB7XG4gICAgICAgICAgICB2YWx1ZSArPSAnXCInO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3VycmVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSArPSBjdXJyZW50O1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfVxuXG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwicXVvdGVkSWRlbnRpZmllclwiLCB2YWx1ZSB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICgvW0EtWmEtel9dLy50ZXN0KGNoYXIpKSB7XG4gICAgICBsZXQgdmFsdWUgPSBjaGFyO1xuICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgZXhwcmVzc2lvbi5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IGV4cHJlc3Npb25baW5kZXhdO1xuICAgICAgICBpZiAoY3VycmVudCAhPT0gdW5kZWZpbmVkICYmIC9bQS1aYS16MC05XyRdLy50ZXN0KGN1cnJlbnQpKSB7XG4gICAgICAgICAgdmFsdWUgKz0gY3VycmVudDtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwiaWRlbnRpZmllclwiLCB2YWx1ZSB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihg7KeA7JuQ65CY7KeAIOyViuuKlCBzZWFyY2hUZXh0IGV4cHJlc3Npb24g66y47J6QOiAke2NoYXJ9YCk7XG4gIH1cblxuICByZXR1cm4gdG9rZW5zO1xufVxuXG5mdW5jdGlvbiBjYW5vbmljYWxpemVTZWFyY2hUZXh0R2VuZXJhdGVkRXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTZWFyY2hUZXh0RXhwcmVzc2lvblBhcnNlcih0b2tlbml6ZVNlYXJjaFRleHRFeHByZXNzaW9uKGV4cHJlc3Npb24pKTtcbiAgICBjb25zdCBwYXJzZWRFeHByZXNzaW9uID0gcGFyc2VyLnBhcnNlRXhwcmVzc2lvbigpO1xuXG4gICAgaWYgKCFwYXJzZXIuaXNBdEVuZCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZWFyY2hUZXh0IGV4cHJlc3Npb24g7YyM7Iux7J20IOuBneuCmOyngCDslYrslZjsirXri4jri6QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiByZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFyc2VkRXhwcmVzc2lvbikpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25GYWxsYmFjayhleHByZXNzaW9uKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUoXG4gIG5vZGU6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSxcbik6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gIHN3aXRjaCAobm9kZS50eXBlKSB7XG4gICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm5vZGUsXG4gICAgICAgIG5hbWU6IG5vZGUucXVvdGVkID8gbm9kZS5uYW1lIDogbm9kZS5uYW1lLnRvTG93ZXJDYXNlKCksXG4gICAgICB9O1xuICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgY2FzZSBcImNvbmNhdFwiOiB7XG4gICAgICBjb25zdCBwYXJ0cyA9IG5vZGUucGFydHMuZmxhdE1hcCgocGFydCkgPT4ge1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUGFydCA9IG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShwYXJ0KTtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRQYXJ0LnR5cGUgPT09IFwiY29uY2F0XCIgPyBub3JtYWxpemVkUGFydC5wYXJ0cyA6IFtub3JtYWxpemVkUGFydF07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwiY29uY2F0XCIsIHBhcnRzIH07XG4gICAgfVxuICAgIGNhc2UgXCJjb2xsYXRlXCI6XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImNvbGxhdGVcIixcbiAgICAgICAgZXhwcjogbm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlKG5vZGUuZXhwciksXG4gICAgICAgIGNvbGxhdGlvbjogbm9kZS5jb2xsYXRpb24udG9VcHBlckNhc2UoKSA9PT0gXCJDXCIgPyBcIkNcIiA6IG5vZGUuY29sbGF0aW9uLFxuICAgICAgICBxdW90ZWQ6IG5vZGUucXVvdGVkIHx8IG5vZGUuY29sbGF0aW9uLnRvVXBwZXJDYXNlKCkgPT09IFwiQ1wiLFxuICAgICAgfTtcbiAgICBjYXNlIFwiY2FzdFwiOiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRXhwciA9IG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShub2RlLmV4cHIpO1xuICAgICAgY29uc3QgdGFyZ2V0VHlwZSA9IG5vZGUudGFyZ2V0VHlwZS5yZXBsYWNlKC9cXHMrL2csIFwiIFwiKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICh0YXJnZXRUeXBlID09PSBcInRleHRcIiB8fCB0YXJnZXRUeXBlID09PSBcImNoYXJhY3RlciB2YXJ5aW5nXCIgfHwgdGFyZ2V0VHlwZSA9PT0gXCJ2YXJjaGFyXCIpIHtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRFeHByO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjYXN0XCIsXG4gICAgICAgIGV4cHI6IG5vcm1hbGl6ZWRFeHByLFxuICAgICAgICB0YXJnZXRUeXBlLFxuICAgICAgfTtcbiAgICB9XG4gICAgY2FzZSBcImZ1bmN0aW9uXCI6IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBub2RlLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgIGxldCBhcmdzID0gbm9kZS5hcmdzLm1hcCgoYXJnKSA9PiBub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUoYXJnKSk7XG5cbiAgICAgIGlmICgobmFtZSA9PT0gXCJ0cmltXCIgfHwgbmFtZSA9PT0gXCJidHJpbVwiKSAmJiBhcmdzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiZnVuY3Rpb25cIixcbiAgICAgICAgICBuYW1lOiBcInRyaW1cIixcbiAgICAgICAgICBhcmdzLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIChuYW1lID09PSBcInNvbmFtdV90ZXh0X2FycmF5X2FnZ1wiIHx8IG5hbWUgPT09IFwic29uYW11X2pzb25iX2FycmF5X2FnZ1wiKSAmJlxuICAgICAgICBhcmdzLmxlbmd0aCA9PT0gMiAmJlxuICAgICAgICBhcmdzWzFdPy50eXBlID09PSBcImJvb2xlYW5cIiAmJlxuICAgICAgICBhcmdzWzFdLnZhbHVlID09PSB0cnVlXG4gICAgICApIHtcbiAgICAgICAgYXJncyA9IFthcmdzWzBdXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgICAgICBuYW1lLFxuICAgICAgICBhcmdzLFxuICAgICAgfTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyU2VhcmNoVGV4dEV4cHJlc3Npb24obm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlLCBwYXJlbnRQcmVjZWRlbmNlID0gMCk6IHN0cmluZyB7XG4gIGNvbnN0IHByZWNlZGVuY2UgPSBnZXRTZWFyY2hUZXh0RXhwcmVzc2lvblByZWNlZGVuY2Uobm9kZSk7XG4gIGNvbnN0IHJlbmRlcmVkID0gKCgpID0+IHtcbiAgICBzd2l0Y2ggKG5vZGUudHlwZSkge1xuICAgICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICAgICAgcmV0dXJuIG5vZGUucXVvdGVkID8gYFwiJHtub2RlLm5hbWUucmVwbGFjZUFsbCgnXCInLCAnXCJcIicpfVwiYCA6IG5vZGUubmFtZTtcbiAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgcmV0dXJuIGAnJHtub2RlLnZhbHVlLnJlcGxhY2VBbGwoXCInXCIsIFwiJydcIil9J2A7XG4gICAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgICByZXR1cm4gbm9kZS52YWx1ZSA/IFwidHJ1ZVwiIDogXCJmYWxzZVwiO1xuICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgIHJldHVybiBgJHtub2RlLm5hbWV9KCR7bm9kZS5hcmdzXG4gICAgICAgICAgLm1hcCgoYXJnKSA9PiByZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihhcmcpKVxuICAgICAgICAgIC5qb2luKFwiLCBcIil9KWA7XG4gICAgICBjYXNlIFwiY29uY2F0XCI6XG4gICAgICAgIHJldHVybiBub2RlLnBhcnRzLm1hcCgocGFydCkgPT4gcmVuZGVyU2VhcmNoVGV4dEV4cHJlc3Npb24ocGFydCwgcHJlY2VkZW5jZSkpLmpvaW4oXCIgfHwgXCIpO1xuICAgICAgY2FzZSBcImNvbGxhdGVcIjoge1xuICAgICAgICBjb25zdCBjb2xsYXRpb24gPSBub2RlLnF1b3RlZFxuICAgICAgICAgID8gYFwiJHtub2RlLmNvbGxhdGlvbi5yZXBsYWNlQWxsKCdcIicsICdcIlwiJyl9XCJgXG4gICAgICAgICAgOiBub2RlLmNvbGxhdGlvbjtcbiAgICAgICAgcmV0dXJuIGAke3JlbmRlclNlYXJjaFRleHRFeHByZXNzaW9uKG5vZGUuZXhwciwgcHJlY2VkZW5jZSl9IENPTExBVEUgJHtjb2xsYXRpb259YDtcbiAgICAgIH1cbiAgICAgIGNhc2UgXCJjYXN0XCI6XG4gICAgICAgIHJldHVybiBgJHtyZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihub2RlLmV4cHIsIHByZWNlZGVuY2UpfTo6JHtub2RlLnRhcmdldFR5cGV9YDtcbiAgICB9XG4gIH0pKCk7XG5cbiAgaWYgKHByZWNlZGVuY2UgPCBwYXJlbnRQcmVjZWRlbmNlKSB7XG4gICAgcmV0dXJuIGAoJHtyZW5kZXJlZH0pYDtcbiAgfVxuXG4gIHJldHVybiByZW5kZXJlZDtcbn1cblxuZnVuY3Rpb24gZ2V0U2VhcmNoVGV4dEV4cHJlc3Npb25QcmVjZWRlbmNlKG5vZGU6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSk6IG51bWJlciB7XG4gIHN3aXRjaCAobm9kZS50eXBlKSB7XG4gICAgY2FzZSBcImNvbmNhdFwiOlxuICAgICAgcmV0dXJuIDE7XG4gICAgY2FzZSBcImNvbGxhdGVcIjpcbiAgICBjYXNlIFwiY2FzdFwiOlxuICAgICAgcmV0dXJuIDI7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAzO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uRmFsbGJhY2soZXhwcmVzc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4cHJlc3Npb25cbiAgICAucmVwbGFjZSgvXFxzKy9nLCBcIiBcIilcbiAgICAucmVwbGFjZSgvXFxiVFJJTVxccypcXChcXHMqQk9USFxccytGUk9NXFxzKy9naSwgXCJ0cmltKFwiKVxuICAgIC5yZXBsYWNlKC86Oig/OnRleHR8Y2hhcmFjdGVyIHZhcnlpbmd8dmFyY2hhcilcXGIvZ2ksIFwiXCIpXG4gICAgLnJlcGxhY2UoLyxcXHMqdHJ1ZVxcYi9naSwgXCJcIilcbiAgICAudHJpbSgpO1xufVxuXG5mdW5jdGlvbiB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShcbiAgbm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlLFxuICB2aXNpdG9yOiAobm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlKSA9PiB2b2lkLFxuKTogdm9pZCB7XG4gIHZpc2l0b3Iobm9kZSk7XG5cbiAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICBjYXNlIFwiY29uY2F0XCI6XG4gICAgICBub2RlLnBhcnRzLmZvckVhY2goKHBhcnQpID0+IHtcbiAgICAgICAgdmlzaXRTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFydCwgdmlzaXRvcik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICBjYXNlIFwiY29sbGF0ZVwiOlxuICAgIGNhc2UgXCJjYXN0XCI6XG4gICAgICB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShub2RlLmV4cHIsIHZpc2l0b3IpO1xuICAgICAgcmV0dXJuO1xuICAgIGNhc2UgXCJmdW5jdGlvblwiOlxuICAgICAgbm9kZS5hcmdzLmZvckVhY2goKGFyZykgPT4ge1xuICAgICAgICB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShhcmcsIHZpc2l0b3IpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICBjYXNlIFwic3RyaW5nXCI6XG4gICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgIHJldHVybjtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTZWFyY2hUZXh0SGVscGVyS2luZHNGcm9tRXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBTZXQ8U2VhcmNoVGV4dEhlbHBlcktpbmQ+IHtcbiAgY29uc3QgaGVscGVyS2luZHMgPSBuZXcgU2V0PFNlYXJjaFRleHRIZWxwZXJLaW5kPigpO1xuICBjb25zdCBhZGRIZWxwZXJLaW5kRnJvbU5hbWUgPSAobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZE5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKG5vcm1hbGl6ZWROYW1lID09PSBcInNvbmFtdV90ZXh0X2FycmF5X2FnZ1wiKSB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoXCJ0ZXh0LWFycmF5XCIpO1xuICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZE5hbWUgPT09IFwic29uYW11X2pzb25iX2FycmF5X2FnZ1wiKSB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoXCJqc29uYi1hcnJheVwiKTtcbiAgICB9XG4gIH07XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZXIgPSBuZXcgU2VhcmNoVGV4dEV4cHJlc3Npb25QYXJzZXIodG9rZW5pemVTZWFyY2hUZXh0RXhwcmVzc2lvbihleHByZXNzaW9uKSk7XG4gICAgY29uc3QgcGFyc2VkRXhwcmVzc2lvbiA9IHBhcnNlci5wYXJzZUV4cHJlc3Npb24oKTtcblxuICAgIGlmICghcGFyc2VyLmlzQXRFbmQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VhcmNoVGV4dCBoZWxwZXIgZXhwcmVzc2lvbiDtjIzsi7HsnbQg64Gd64KY7KeAIOyViuyVmOyKteuLiOuLpC5cIik7XG4gICAgfVxuXG4gICAgdmlzaXRTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFyc2VkRXhwcmVzc2lvbiwgKG5vZGUpID0+IHtcbiAgICAgIGlmIChub2RlLnR5cGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBhZGRIZWxwZXJLaW5kRnJvbU5hbWUobm9kZS5uYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBjYXRjaCB7XG4gICAgaWYgKC9cXGJzb25hbXVfdGV4dF9hcnJheV9hZ2dcXHMqXFwoL2kudGVzdChleHByZXNzaW9uKSkge1xuICAgICAgaGVscGVyS2luZHMuYWRkKFwidGV4dC1hcnJheVwiKTtcbiAgICB9XG4gICAgaWYgKC9cXGJzb25hbXVfanNvbmJfYXJyYXlfYWdnXFxzKlxcKC9pLnRlc3QoZXhwcmVzc2lvbikpIHtcbiAgICAgIGhlbHBlcktpbmRzLmFkZChcImpzb25iLWFycmF5XCIpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBoZWxwZXJLaW5kcztcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVNlYXJjaFRleHRDb2x1bW5zKHRhYmxlOiBzdHJpbmcsIGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdKTogTWlncmF0aW9uQ29sdW1uW10ge1xuICBjb25zdCBlbnRpdHkgPSAoKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRCeVRhYmxlKHRhYmxlKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfSkoKTtcblxuICBpZiAoIWVudGl0eSkge1xuICAgIHJldHVybiBjb2x1bW5zO1xuICB9XG5cbiAgY29uc3QgcHJvcHNCeU5hbWUgPSBuZXcgTWFwKGVudGl0eS5wcm9wcy5tYXAoKHByb3ApID0+IFtwcm9wLm5hbWUsIHByb3BdKSk7XG5cbiAgcmV0dXJuIGNvbHVtbnMubWFwKChjb2x1bW4pID0+IHtcbiAgICBjb25zdCBwcm9wID0gcHJvcHNCeU5hbWUuZ2V0KGNvbHVtbi5uYW1lKTtcbiAgICBpZiAoIXByb3AgfHwgIWlzU2VhcmNoVGV4dFByb3AocHJvcCkpIHtcbiAgICAgIHJldHVybiBjb2x1bW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmNvbHVtbixcbiAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICB0eXBlOiBcIlNUT1JFRFwiLFxuICAgICAgICBleHByZXNzaW9uOiBidWlsZFNlYXJjaFRleHRHZW5lcmF0ZWRFeHByZXNzaW9uKHByb3AsIHByb3BzQnlOYW1lKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2VhcmNoVGV4dEdlbmVyYXRlZEV4cHJlc3Npb24oXG4gIHByb3A6IEV4dHJhY3Q8RW50aXR5UHJvcCwgeyB0eXBlOiBcInNlYXJjaFRleHRcIiB9PixcbiAgcHJvcHNCeU5hbWU6IE1hcDxzdHJpbmcsIEVudGl0eVByb3A+LFxuKTogc3RyaW5nIHtcbiAgY29uc3QgdG9rZW5zID0gcHJvcC5zb3VyY2VDb2x1bW5zLm1hcCgoc291cmNlKSA9PiB7XG4gICAgY29uc3Qgc291cmNlUHJvcCA9IHByb3BzQnlOYW1lLmdldChzb3VyY2UubmFtZSk7XG4gICAgaWYgKCFzb3VyY2VQcm9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHNlYXJjaFRleHQgc291cmNlIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCLsnYQo66W8KSDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlUHJvcC50eXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBsb3dlcihDT0FMRVNDRSgke3NvdXJjZS5uYW1lfSwgJycpKWBcbiAgICAgICAgOiBgQ09BTEVTQ0UoJHtzb3VyY2UubmFtZX0sICcnKWA7XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZVByb3AudHlwZSA9PT0gXCJzdHJpbmdbXVwiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBDT0FMRVNDRShzb25hbXVfdGV4dF9hcnJheV9hZ2coJHtzb3VyY2UubmFtZX0pLCAnJylgXG4gICAgICAgIDogYENPQUxFU0NFKHNvbmFtdV90ZXh0X2FycmF5X2FnZygke3NvdXJjZS5uYW1lfSwgZmFsc2UpLCAnJylgO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2VQcm9wLnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBDT0FMRVNDRShzb25hbXVfanNvbmJfYXJyYXlfYWdnKCR7c291cmNlLm5hbWV9KSwgJycpYFxuICAgICAgICA6IGBDT0FMRVNDRShzb25hbXVfanNvbmJfYXJyYXlfYWdnKCR7c291cmNlLm5hbWV9LCBmYWxzZSksICcnKWA7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHNlYXJjaFRleHQgc291cmNlIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCLsnZgg7YOA7J6FIFwiJHtzb3VyY2VQcm9wLnR5cGV9XCLsnYAo64qUKSDsp4Dsm5DrkJjsp4Ag7JWK7Iq164uI64ukLmAsXG4gICAgKTtcbiAgfSk7XG5cbiAgcmV0dXJuIGB0cmltKCR7dG9rZW5zLmpvaW4oYCB8fCAnICcgfHwgYCl9KWA7XG59XG5cbmZ1bmN0aW9uIGdldFNlYXJjaFRleHRIZWxwZXJEZWZpbml0aW9ucyh0YWJsZTogc3RyaW5nLCBjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgaGVscGVyS2luZHMgPSBuZXcgU2V0PFNlYXJjaFRleHRIZWxwZXJLaW5kPigpO1xuXG4gIGNvbHVtbnMuZm9yRWFjaCgoY29sdW1uKSA9PiB7XG4gICAgaWYgKCFjb2x1bW4uZ2VuZXJhdGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZ2V0U2VhcmNoVGV4dEhlbHBlcktpbmRzRnJvbUV4cHJlc3Npb24oY29sdW1uLmdlbmVyYXRlZC5leHByZXNzaW9uKS5mb3JFYWNoKChraW5kKSA9PiB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoa2luZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGlmIChoZWxwZXJLaW5kcy5zaXplID4gMCkge1xuICAgIHJldHVybiAoW1widGV4dC1hcnJheVwiLCBcImpzb25iLWFycmF5XCJdIGFzIGNvbnN0KVxuICAgICAgLmZpbHRlcigoa2luZCkgPT4gaGVscGVyS2luZHMuaGFzKGtpbmQpKVxuICAgICAgLm1hcCgoa2luZCkgPT4gU0VBUkNIX1RFWFRfSEVMUEVSX0RFRklOSVRJT05TW2tpbmRdKTtcbiAgfVxuXG4gIGNvbnN0IGVudGl0eSA9ICgoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBFbnRpdHlNYW5hZ2VyLmdldEJ5VGFibGUodGFibGUpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9KSgpO1xuXG4gIGlmICghZW50aXR5KSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IHByb3BzQnlOYW1lID0gbmV3IE1hcChlbnRpdHkucHJvcHMubWFwKChwcm9wKSA9PiBbcHJvcC5uYW1lLCBwcm9wXSkpO1xuXG4gIGNvbHVtbnMuZm9yRWFjaCgoY29sdW1uKSA9PiB7XG4gICAgY29uc3QgcHJvcCA9IHByb3BzQnlOYW1lLmdldChjb2x1bW4ubmFtZSk7XG4gICAgaWYgKCFwcm9wIHx8ICFpc1NlYXJjaFRleHRQcm9wKHByb3ApKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcHJvcC5zb3VyY2VDb2x1bW5zLmZvckVhY2goKHNvdXJjZSkgPT4ge1xuICAgICAgY29uc3Qgc291cmNlUHJvcCA9IHByb3BzQnlOYW1lLmdldChzb3VyY2UubmFtZSk7XG4gICAgICBpZiAoc291cmNlUHJvcD8udHlwZSA9PT0gXCJzdHJpbmdbXVwiKSB7XG4gICAgICAgIGhlbHBlcktpbmRzLmFkZChcInRleHQtYXJyYXlcIik7XG4gICAgICB9IGVsc2UgaWYgKHNvdXJjZVByb3A/LnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgICAgIGhlbHBlcktpbmRzLmFkZChcImpzb25iLWFycmF5XCIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gKFtcInRleHQtYXJyYXlcIiwgXCJqc29uYi1hcnJheVwiXSBhcyBjb25zdClcbiAgICAuZmlsdGVyKChraW5kKSA9PiBoZWxwZXJLaW5kcy5oYXMoa2luZCkpXG4gICAgLm1hcCgoa2luZCkgPT4gU0VBUkNIX1RFWFRfSEVMUEVSX0RFRklOSVRJT05TW2tpbmRdKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2VhcmNoVGV4dENvbHVtbk5hbWVzKHRhYmxlOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPiB7XG4gIGNvbnN0IGVudGl0eSA9ICgoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBFbnRpdHlNYW5hZ2VyLmdldEJ5VGFibGUodGFibGUpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9KSgpO1xuXG4gIGlmICghZW50aXR5KSB7XG4gICAgcmV0dXJuIG5ldyBTZXQoKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgU2V0KGVudGl0eS5wcm9wcy5maWx0ZXIoaXNTZWFyY2hUZXh0UHJvcCkubWFwKChwcm9wKSA9PiBwcm9wLm5hbWUpKTtcbn1cblxuLyoqXG4gKiDthYzsnbTruJQg7IOd7ISx7ZWY64qUIOy8gOydtOyKpCAtIOy7rOufvC/snbjrjbHsiqQg7IOd7ISxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQ3JlYXRlQ29kZV9Db2x1bW5BbmRJbmRleGVzKFxuICB0YWJsZTogc3RyaW5nLFxuICBjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgaW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbik6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZT4ge1xuICBjb25zdCByZXNvbHZlZENvbHVtbnMgPSByZXNvbHZlU2VhcmNoVGV4dENvbHVtbnModGFibGUsIGNvbHVtbnMpO1xuICBjb25zdCBjb2x1bW5EZWZzID0gZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIHJlc29sdmVkQ29sdW1ucyk7XG4gIGNvbnN0IGhlbHBlckRlZmluaXRpb25zID0gZ2V0U2VhcmNoVGV4dEhlbHBlckRlZmluaXRpb25zKHRhYmxlLCByZXNvbHZlZENvbHVtbnMpO1xuXG4gIC8vIOy7rOufvCwg7J24642x7IqkIOyymOumrFxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG4gICAgJ2ltcG9ydCB7IEtuZXggfSBmcm9tIFwia25leFwiOycsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cChrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4uaGVscGVyRGVmaW5pdGlvbnMsXG4gICAgYGF3YWl0IGtuZXguc2NoZW1hLmNyZWF0ZVRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCxcbiAgICAuLi5jb2x1bW5EZWZzLmJ1aWxkZXIsXG4gICAgXCJ9KTtcIixcbiAgICAvLyByYXcg6rWs66y4IChHZW5lcmF0ZWQgQ29sdW1uIOuTsSlcbiAgICAuLi5jb2x1bW5EZWZzLnJhdyxcbiAgICAvLyBpbmRleOuKlCBrbmV4LnJhd+uhnCDsspjrpqztlZjrr4DroZwgY3JlYXRlVGFibGUg67CW7JeQ7IScIOyLpO2WiVxuICAgIC4uLmluZGV4ZXMubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgYCByZXR1cm4ga25leC5zY2hlbWEuZHJvcFRhYmxlKFwiJHt0YWJsZX1cIik7YCxcbiAgICBcIn1cIixcbiAgXTtcbiAgcmV0dXJuIHtcbiAgICB0YWJsZSxcbiAgICB0eXBlOiBcIm5vcm1hbFwiLFxuICAgIHRpdGxlOiBgY3JlYXRlX18ke3RhYmxlfWAsXG4gICAgZm9ybWF0dGVkOiBmb3JtYXRDb2RlKGxpbmVzLmpvaW4oXCJcXG5cIiksIFwidHlwZXNjcmlwdFwiLCBgc3JjL21pZ3JhdGlvbi8ke3RhYmxlfS50c2ApLFxuICB9O1xufVxuXG4vKipcbiAqIE1pZ3JhdGlvbkNvbHVtbltdIOydveyWtOyEnCDsu6zrn7wg7KCV7J2Y7ZWY64qUIOq1rOusuCDsg53shLFcbiAqIEByZXR1cm5zIGJ1aWxkZXI6IHRhYmxlIGJ1aWxkZXIg66mU7ISc65OcLCByYXc6IGtuZXgucmF3KCkg6rWs66y4XG4gKi9cbmZ1bmN0aW9uIGdlbkNvbHVtbkRlZmluaXRpb25zKHRhYmxlOiBzdHJpbmcsIGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdKTogQ29sdW1uRGVmaW5pdGlvblJlc3VsdCB7XG4gIGNvbnN0IHJlc3VsdDogQ29sdW1uRGVmaW5pdGlvblJlc3VsdCA9IHtcbiAgICBidWlsZGVyOiBbXSxcbiAgICByYXc6IFtdLFxuICB9O1xuXG4gIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAvLyBHZW5lcmF0ZWQgQ29sdW1u7J2AIHJhd+uhnCDsspjrpqxcbiAgICBpZiAoY29sdW1uLmdlbmVyYXRlZCkge1xuICAgICAgcmVzdWx0LnJhdy5wdXNoKGdlbkdlbmVyYXRlZENvbHVtbkRlZmluaXRpb24odGFibGUsIGNvbHVtbikpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8g7J2867CYIOy7rOufvOydgCBidWlsZGVy66GcIOyymOumrFxuICAgIHJlc3VsdC5idWlsZGVyLnB1c2goZ2VuTm9ybWFsQ29sdW1uRGVmaW5pdGlvbihjb2x1bW4pKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogR2VuZXJhdGVkIENvbHVtbiDsoJXsnZgg7IOd7ISxIChBTFRFUiBUQUJMRSBBREQgQ09MVU1OIOyCrOyaqSlcbiAqL1xuZnVuY3Rpb24gZ2VuR2VuZXJhdGVkQ29sdW1uRGVmaW5pdGlvbih0YWJsZTogc3RyaW5nLCBjb2x1bW46IE1pZ3JhdGlvbkNvbHVtbik6IHN0cmluZyB7XG4gIGlmICghY29sdW1uLmdlbmVyYXRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRlZCBjb2x1bW4gZGVmaW5pdGlvbiByZXF1aXJlZFwiKTtcbiAgfVxuICBjb25zdCBwZ1R5cGUgPSBnZXRQZ1R5cGVGb3JDb2x1bW4oY29sdW1uKTtcbiAgY29uc3Qgc3RvcmFnZVR5cGUgPSBjb2x1bW4uZ2VuZXJhdGVkLnR5cGUgPT09IFwiVklSVFVBTFwiID8gXCIgVklSVFVBTFwiIDogXCIgU1RPUkVEXCI7XG4gIGNvbnN0IG51bGxhYmxlQ2xhdXNlID0gY29sdW1uLm51bGxhYmxlID8gXCJcIiA6IFwiIE5PVCBOVUxMXCI7XG4gIHJldHVybiBgYXdhaXQga25leC5yYXcoXFxgQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT0xVTU4gXCIke2NvbHVtbi5uYW1lfVwiICR7cGdUeXBlfSBHRU5FUkFURUQgQUxXQVlTIEFTICgke2NvbHVtbi5nZW5lcmF0ZWQuZXhwcmVzc2lvbn0pJHtzdG9yYWdlVHlwZX0ke251bGxhYmxlQ2xhdXNlfVxcYCk7YDtcbn1cblxuLyoqXG4gKiDsnbzrsJgg7Lus65+8IOygleydmCDsg53shLEgKHRhYmxlLnh4eCgpIOyytOyduClcbiAqL1xuZnVuY3Rpb24gZ2VuTm9ybWFsQ29sdW1uRGVmaW5pdGlvbihjb2x1bW46IE1pZ3JhdGlvbkNvbHVtbik6IHN0cmluZyB7XG4gIGNvbnN0IGNoYWluczogc3RyaW5nW10gPSBbXTtcblxuICBpZiAoY29sdW1uLm5hbWUgPT09IFwiaWRcIikge1xuICAgIC8vIFBLIO2DgOyeheyXkCDrlLDrpbgg67aE6riwIOyymOumrFxuICAgIGlmIChjb2x1bW4udHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgLy8gc3RyaW5nIFBLOiBsZW5ndGjqsIAg7J6I7Jy866m0IHZhcmNoYXIsIOyXhuycvOuptCB0ZXh0XG4gICAgICBpZiAoY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBgdGFibGUuc3RyaW5nKCdpZCcsICR7Y29sdW1uLmxlbmd0aH0pLnByaW1hcnkoKS5ub3ROdWxsYWJsZSgpO2A7XG4gICAgICB9XG4gICAgICByZXR1cm4gYHRhYmxlLnRleHQoJ2lkJykucHJpbWFyeSgpLm5vdE51bGxhYmxlKCk7YDtcbiAgICB9XG4gICAgaWYgKGNvbHVtbi50eXBlID09PSBcInV1aWRcIikge1xuICAgICAgcmV0dXJuIGB0YWJsZS51dWlkKCdpZCcpLnByaW1hcnkoKS5ub3ROdWxsYWJsZSgpO2A7XG4gICAgfVxuICAgIC8vIOq4sOyhtCBpbnRlZ2VyIFBLICjquLDrs7jqsJIpXG4gICAgcmV0dXJuIGB0YWJsZS5pbmNyZW1lbnRzKCkucHJpbWFyeSgpO2A7XG4gIH1cblxuICAvLyDrsLDsl7Qg7YOA7J6FIOyymOumrFxuICBpZiAoY29sdW1uLnR5cGUuZW5kc1dpdGgoXCJbXVwiKSkge1xuICAgIGNvbnN0IGVsZW1lbnRUeXBlID0gY29sdW1uLnR5cGUuc2xpY2UoMCwgLTIpOyAvLyBcImludGVnZXJbXVwiIC0+IFwiaW50ZWdlclwiXG4gICAgY29uc3QgcGdUeXBlID0gZ2V0UGdBcnJheVR5cGUoY29sdW1uLCBlbGVtZW50VHlwZSk7XG4gICAgY2hhaW5zLnB1c2goYHNwZWNpZmljVHlwZSgnJHtjb2x1bW4ubmFtZX0nLCAnJHtwZ1R5cGV9JylgKTtcbiAgfSBlbHNlIGlmIChjb2x1bW4udHlwZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgIC8vIEtuZXjripQgdmVjdG9yIO2DgOyeheydhCDsp4HsoJEg7KeA7JuQ7ZWY7KeAIOyViuycvOuvgOuhnCBzcGVjaWZpY1R5cGUg7IKs7JqpXG4gICAgY2hhaW5zLnB1c2goYHNwZWNpZmljVHlwZSgnJHtjb2x1bW4ubmFtZX0nLCAndmVjdG9yKCR7Y29sdW1uLmRpbWVuc2lvbnN9KScpYCk7XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwibnVtYmVyT3JOdW1lcmljXCIpIHtcbiAgICAvLyBudW1iZXJcbiAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwicmVhbFwiKSB7XG4gICAgICBjaGFpbnMucHVzaChgZmxvYXQoJyR7Y29sdW1uLm5hbWV9JylgKTtcbiAgICB9IGVsc2UgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcImRvdWJsZSBwcmVjaXNpb25cIikge1xuICAgICAgY2hhaW5zLnB1c2goYGRvdWJsZSgnJHtjb2x1bW4ubmFtZX0nKWApO1xuICAgIH0gZWxzZSBpZiAoKGNvbHVtbi5udW1iZXJUeXBlID8/IFwibnVtZXJpY1wiKSA9PT0gXCJudW1lcmljXCIpIHtcbiAgICAgIGNoYWlucy5wdXNoKGBkZWNpbWFsKCcke2NvbHVtbi5uYW1lfScsICR7Y29sdW1uLnByZWNpc2lvbn0sICR7Y29sdW1uLnNjYWxlfSlgKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAvLyBzdHJpbmdcbiAgICBpZiAoY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjaGFpbnMucHVzaChgc3RyaW5nKCcke2NvbHVtbi5uYW1lfScsICR7Y29sdW1uLmxlbmd0aH0pYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoYWlucy5wdXNoKGB0ZXh0KCcke2NvbHVtbi5uYW1lfScpYCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGNvbHVtbi50eXBlID09PSBcImRhdGVcIikge1xuICAgIC8vIGRhdGVcbiAgICBjaGFpbnMucHVzaChcbiAgICAgIGB0aW1lc3RhbXAoJyR7Y29sdW1uLm5hbWV9JywgeyB1c2VUejogdHJ1ZSwgcHJlY2lzaW9uOiAke2NvbHVtbi5wcmVjaXNpb24gPz8gM30gfSlgLFxuICAgICk7XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgLy8ganNvblxuICAgIGNoYWlucy5wdXNoKGBqc29uYignJHtjb2x1bW4ubmFtZX0nKWApO1xuICB9IGVsc2Uge1xuICAgIC8vIHR5cGUsIGxlbmd0aFxuICAgIGxldCBleHRyYVR5cGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBjaGFpbnMucHVzaChcbiAgICAgIGAke2NvbHVtbi50eXBlfSgnJHtjb2x1bW4ubmFtZX0nJHtcbiAgICAgICAgY29sdW1uLmxlbmd0aCA/IGAsICR7Y29sdW1uLmxlbmd0aH1gIDogXCJcIlxuICAgICAgfSR7ZXh0cmFUeXBlID8gYCwgJyR7ZXh0cmFUeXBlfSdgIDogXCJcIn0pYCxcbiAgICApO1xuICB9XG5cbiAgLy8gbnVsbGFibGVcbiAgY2hhaW5zLnB1c2goY29sdW1uLm51bGxhYmxlID8gXCJudWxsYWJsZSgpXCIgOiBcIm5vdE51bGxhYmxlKClcIik7XG5cbiAgLy8gZGVmYXVsdFRvXG4gIGlmIChjb2x1bW4uZGVmYXVsdFRvICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIGNvbHVtbi5kZWZhdWx0VG8gPT09IFwic3RyaW5nXCIgJiYgY29sdW1uLmRlZmF1bHRUby5zdGFydHNXaXRoKGBcImApKSB7XG4gICAgICBjaGFpbnMucHVzaChgZGVmYXVsdFRvKCR7Y29sdW1uLmRlZmF1bHRUb30pYCk7XG4gICAgfSBlbHNlIGlmIChjb2x1bW4udHlwZSA9PT0gXCJqc29uXCIgJiYgdHlwZW9mIGNvbHVtbi5kZWZhdWx0VG8uc3RhcnRzV2l0aCgnXCInKSkge1xuICAgICAgY2hhaW5zLnB1c2goYGRlZmF1bHRUbyhrbmV4LnJhdyhcIiR7Y29sdW1uLmRlZmF1bHRUby5yZXBsYWNlQWxsKCdcIicsIFwiJ1wiKX06Ompzb25iXCIpKWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjaGFpbnMucHVzaChgZGVmYXVsdFRvKGtuZXgucmF3KCcke2NvbHVtbi5kZWZhdWx0VG99JykpYCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGB0YWJsZS4ke2NoYWlucy5qb2luKFwiLlwiKX07YDtcbn1cblxuLyoqXG4gKiBNaWdyYXRpb25Db2x1bW7snZgg7YOA7J6F7J2EIFBvc3RncmVTUUwg7YOA7J6FIOusuOyekOyXtOuhnCDrs4DtmZhcbiAqL1xuZnVuY3Rpb24gZ2V0UGdUeXBlRm9yQ29sdW1uKGNvbHVtbjogTWlncmF0aW9uQ29sdW1uKTogc3RyaW5nIHtcbiAgaWYgKGNvbHVtbi50eXBlLmVuZHNXaXRoKFwiW11cIikpIHtcbiAgICBjb25zdCBlbGVtZW50VHlwZSA9IGNvbHVtbi50eXBlLnNsaWNlKDAsIC0yKTtcbiAgICByZXR1cm4gZ2V0UGdBcnJheVR5cGUoY29sdW1uLCBlbGVtZW50VHlwZSk7XG4gIH1cblxuICBzd2l0Y2ggKGNvbHVtbi50eXBlKSB7XG4gICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgcmV0dXJuIGNvbHVtbi5sZW5ndGggIT09IHVuZGVmaW5lZCA/IGB2YXJjaGFyKCR7Y29sdW1uLmxlbmd0aH0pYCA6IFwidGV4dFwiO1xuICAgIGNhc2UgXCJiaWdJbnRlZ2VyXCI6XG4gICAgICByZXR1cm4gXCJiaWdpbnRcIjtcbiAgICBjYXNlIFwibnVtYmVyT3JOdW1lcmljXCI6XG4gICAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwicmVhbFwiKSByZXR1cm4gXCJyZWFsXCI7XG4gICAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwiZG91YmxlIHByZWNpc2lvblwiKSByZXR1cm4gXCJkb3VibGUgcHJlY2lzaW9uXCI7XG4gICAgICByZXR1cm4gYG51bWVyaWMoJHtjb2x1bW4ucHJlY2lzaW9ufSwgJHtjb2x1bW4uc2NhbGV9KWA7XG4gICAgY2FzZSBcImRhdGVcIjpcbiAgICAgIHJldHVybiBcInRpbWVzdGFtcHR6XCI7XG4gICAgY2FzZSBcImpzb25cIjpcbiAgICAgIHJldHVybiBcImpzb25iXCI7XG4gICAgY2FzZSBcInZlY3RvclwiOlxuICAgICAgcmV0dXJuIGB2ZWN0b3IoJHtjb2x1bW4uZGltZW5zaW9uc30pYDtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGNvbHVtbi50eXBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFBnQXJyYXlUeXBlKGNvbHVtbjogTWlncmF0aW9uQ29sdW1uLCBlbGVtZW50VHlwZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcIm51bWJlck9yTnVtZXJpY1wiKSB7XG4gICAgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcInJlYWxcIikgcmV0dXJuIFwicmVhbFtdXCI7XG4gICAgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcImRvdWJsZSBwcmVjaXNpb25cIikgcmV0dXJuIFwiZG91YmxlIHByZWNpc2lvbltdXCI7XG4gICAgcmV0dXJuIGBudW1lcmljKCR7Y29sdW1uLnByZWNpc2lvbn0sICR7Y29sdW1uLnNjYWxlfSlbXWA7XG4gIH1cbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIGNvbHVtbi5sZW5ndGggPyBgdmFyY2hhcigke2NvbHVtbi5sZW5ndGh9KVtdYCA6IFwidGV4dFtdXCI7XG4gIH1cbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImRhdGVcIikgcmV0dXJuIFwidGltZXN0YW1wdHpbXVwiO1xuICBpZiAoZWxlbWVudFR5cGUgPT09IFwiaW50ZWdlclwiKSByZXR1cm4gXCJpbnRlZ2VyW11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImJpZ0ludGVnZXJcIikgcmV0dXJuIFwiYmlnaW50W11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImJvb2xlYW5cIikgcmV0dXJuIFwiYm9vbGVhbltdXCI7XG4gIGlmIChlbGVtZW50VHlwZSA9PT0gXCJ1dWlkXCIpIHJldHVybiBcInV1aWRbXVwiO1xuICBpZiAoZWxlbWVudFR5cGUgPT09IFwiZW51bVwiKSByZXR1cm4gXCJ0ZXh0W11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcInZlY3RvclwiKSByZXR1cm4gYHZlY3Rvcigke2NvbHVtbi5kaW1lbnNpb25zfSlbXWA7XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFycmF5IGVsZW1lbnQgdHlwZTogJHtlbGVtZW50VHlwZX1gKTtcbn1cblxuLyoqXG4gKiDqsJzrs4Qg7J24642x7IqkIOygleydmCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4OiBNaWdyYXRpb25JbmRleCwgdGFibGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChpbmRleC50eXBlID09PSBcImhuc3dcIiB8fCBpbmRleC50eXBlID09PSBcIml2ZmZsYXRcIikge1xuICAgIHJldHVybiBnZW5WZWN0b3JJbmRleERlZmluaXRpb24oaW5kZXgsIHRhYmxlKTtcbiAgfVxuXG4gIGlmIChpbmRleC51c2luZyA9PT0gXCJwZ3Jvb25nYVwiKSB7XG4gICAgcmV0dXJuIGdlblBncm9vbmdhSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSk7XG4gIH1cblxuICBjb25zdCBtZXRob2RNYXAgPSB7XG4gICAgaW5kZXg6IFwiSU5ERVhcIixcbiAgICB1bmlxdWU6IFwiVU5JUVVFIElOREVYXCIsXG4gIH07XG5cbiAgY29uc3QgbnVsbHNOb3REaXN0aW5jdENsYXVzZSA9XG4gICAgaW5kZXgudHlwZSA9PT0gXCJ1bmlxdWVcIiAmJiBpbmRleC5udWxsc05vdERpc3RpbmN0ICE9PSB1bmRlZmluZWRcbiAgICAgID8gYCBOVUxMUyAke2luZGV4Lm51bGxzTm90RGlzdGluY3QgPyBcIk5PVCBESVNUSU5DVFwiIDogXCJESVNUSU5DVFwifWBcbiAgICAgIDogXCJcIjtcblxuICBjb25zdCB1c2luZ0NsYXVzZSA9IGluZGV4LnVzaW5nID09PSB1bmRlZmluZWQgPyBcIlwiIDogYFVTSU5HICR7aW5kZXgudXNpbmd9YDtcblxuICByZXR1cm4gYGF3YWl0IGtuZXgucmF3KFxuICBcXGBDUkVBVEUgJHttZXRob2RNYXBbaW5kZXgudHlwZV19ICR7aW5kZXgubmFtZX0gT04gJHt0YWJsZX0gJHt1c2luZ0NsYXVzZX0oJHtpbmRleC5jb2x1bW5zXG4gICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICBjb25zdCBvcGNsYXNzQ2xhdXNlID0gKCgpID0+IHtcbiAgICAgICAgY29uc3Qgb3BjbGFzcyA9IGdldEluZGV4Q29sdW1uT3BjbGFzcyhjb2wpO1xuICAgICAgICByZXR1cm4gb3BjbGFzcyA/IGAgJHtvcGNsYXNzfWAgOiBcIlwiO1xuICAgICAgfSkoKTtcblxuICAgICAgLy8g7KCV66CsIOyYteyFmOydgCBidHJlZeunjCDsgqzsmqkg6rCA64qlXG4gICAgICBpZiAoaW5kZXgudXNpbmcgIT09IFwiYnRyZWVcIiAmJiBpbmRleC51c2luZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBgJHtjb2wubmFtZX0ke29wY2xhc3NDbGF1c2V9YDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc29ydE9yZGVyQ2xhdXNlID0gY29sLnNvcnRPcmRlciA9PT0gdW5kZWZpbmVkID8gXCJcIiA6IGAgJHtjb2wuc29ydE9yZGVyfWA7XG4gICAgICBjb25zdCBudWxsc0ZpcnN0Q2xhdXNlID1cbiAgICAgICAgY29sLm51bGxzRmlyc3QgPT09IHVuZGVmaW5lZCA/IFwiXCIgOiBgIE5VTExTICR7Y29sLm51bGxzRmlyc3QgPyBcIkZJUlNUXCIgOiBcIkxBU1RcIn1gO1xuICAgICAgcmV0dXJuIGAke2NvbC5uYW1lfSR7b3BjbGFzc0NsYXVzZX0ke3NvcnRPcmRlckNsYXVzZX0ke251bGxzRmlyc3RDbGF1c2V9YDtcbiAgICB9KVxuICAgIC5qb2luKFwiLCBcIil9KSR7bnVsbHNOb3REaXN0aW5jdENsYXVzZX07XFxgXG4gICk7YDtcbn1cblxuZnVuY3Rpb24gZ2VuUGdyb29uZ2FJbmRleERlZmluaXRpb24oaW5kZXg6IE1pZ3JhdGlvbkluZGV4LCB0YWJsZTogc3RyaW5nKSB7XG4gIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0QnlUYWJsZSh0YWJsZSk7XG5cbiAgLy8g67O17ZWpIOyduOuNseyKpOyduCDqsr3smrAgQVJSQVkg7IKs7JqpXG4gIGNvbnN0IGNvbHVtbkNsYXVzZSA9ICgoKSA9PiB7XG4gICAgaWYgKGluZGV4LmNvbHVtbnMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb25zdCBjb2x1bW4gPSBlbnRpdHkucHJvcHNEaWN0W2luZGV4LmNvbHVtbnNbMF0ubmFtZV07XG4gICAgICBjb25zdCBvcHRpb24gPSBnZXRQZ3Jvb25nYUNvbHVtbk9wdGlvbihjb2x1bW4pO1xuICAgICAgcmV0dXJuIGAke2luZGV4LmNvbHVtbnNbMF0ubmFtZX0ke29wdGlvbiA/IGAgJHtvcHRpb259YCA6IFwiXCJ9YDtcbiAgICB9XG5cbiAgICByZXR1cm4gYChBUlJBWVske2luZGV4LmNvbHVtbnMubWFwKChjb2wpID0+IGAke2NvbC5uYW1lfTo6dGV4dGApLmpvaW4oXCIsXCIpfV0pYDtcbiAgfSkoKTtcblxuICByZXR1cm4gYGF3YWl0IGtuZXgucmF3KFxuICBcXGBDUkVBVEUgSU5ERVggJHtpbmRleC5uYW1lfSBPTiAke3RhYmxlfSBVU0lORyBwZ3Jvb25nYSAoJHtjb2x1bW5DbGF1c2V9KSBXSVRIICh0b2tlbml6ZXI9J1Rva2VuTWVjYWInKTtcXGBcbiAgKWA7XG59XG5cbi8qKlxuICogUEdyb29uZ2Eg7Lus65+8IOyYteyFmCDstpTstpxcbiAqXG4gKiBGdWxsVGV4dCDsmKTtjbzroIjsnbTthLDrpbwg7KeA7JuQ7ZWY64qUIOqyveyasCDsmrDshKAg7ISk7KCVLCDrgpjrqLjsp4DripQg65SU7Y+07Yq4IOydtOyaqVxuICogQGxpbmsgaHR0cHM6Ly9wZ3Jvb25nYS5naXRodWIuaW8vcmVmZXJlbmNlXG4gKi9cbmZ1bmN0aW9uIGdldFBncm9vbmdhQ29sdW1uT3B0aW9uKGNvbHVtbjogRW50aXR5UHJvcCkge1xuICBpZiAoY29sdW1uLnR5cGUgPT09IFwic3RyaW5nXCIgJiYgY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIFwicGdyb29uZ2FfdmFyY2hhcl9mdWxsX3RleHRfc2VhcmNoX29wc192MlwiO1xuICB9IGVsc2UgaWYgKGNvbHVtbi50eXBlID09PSBcImpzb25cIikge1xuICAgIHJldHVybiBcInBncm9vbmdhX2pzb25iX2Z1bGxfdGV4dF9zZWFyY2hfb3BzX3YyXCI7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uXG4gKiAtIEhOU1cgKEhpZXJhcmNoaWNhbCBOYXZpZ2FibGUgU21hbGwgV29ybGQpOiDripDrprAg67mM65OcLCDruaDrpbgg6rKA7IOJIOyGjeuPhCwg64aS7J2AIOuplOuqqOumrCDrsI8g7KCV7ZmV64+EXG4gKiAtIElWRkZsYXQgKEludmVydGVkIEZpbGUgd2l0aCBGbGF0IENvbXByZXNzaW9uKTog67mg66W4IOu5jOuTnCwg7KSR6rCEIOqygOyDiSDsho3rj4QsIOuCruydgCDrqZTrqqjrpqxcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gSE5TVyDsnbjrjbHsiqQgKOq2jOyepSAtIOu5oOuluCDqsoDsg4ksIOuGkuydgCDsoJXtmZXrj4QpXG4gKiBDUkVBVEUgSU5ERVggaWR4X2VtYmVkZGluZyBPTiBpdGVtcyBVU0lORyBobnN3IChlbWJlZGRpbmcgdmVjdG9yX2Nvc2luZV9vcHMpIFdJVEggKG0gPSAxNiwgZWZfY29uc3RydWN0aW9uID0gNjQpO1xuICpcbiAqIC8vIElWRkZsYXQg7J24642x7IqkICjrjIDsmqnrn4kg642w7J207YSwLCDruYTsmqkg7KSR7JqUIOyLnClcbiAqIENSRUFURSBJTkRFWCBpZHhfZW1iZWRkaW5nIE9OIGl0ZW1zIFVTSU5HIGl2ZmZsYXQgKGVtYmVkZGluZyB2ZWN0b3JfY29zaW5lX29wcykgV0lUSCAobGlzdHMgPSAxMDApO1xuICovXG5mdW5jdGlvbiBnZW5WZWN0b3JJbmRleERlZmluaXRpb24oaW5kZXg6IE1pZ3JhdGlvbkluZGV4LCB0YWJsZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY29sdW1uID0gaW5kZXguY29sdW1uc1swXTtcbiAgY29uc3QgdmVjdG9yT3BzID0gZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbikgPz8gXCJ2ZWN0b3JfY29zaW5lX29wc1wiO1xuXG4gIC8vIEhOU1cgKEhpZXJhcmNoaWNhbCBOYXZpZ2FibGUgU21hbGwgV29ybGQpIC0g6raM7J6lOiDruaDrpbgg6rKA7IOJLCDrhpLsnYAg7KCV7ZmV64+EXG4gIGlmIChpbmRleC50eXBlID09PSBcImhuc3dcIikge1xuICAgIGNvbnN0IG0gPSBpbmRleC5tID8/IDE2O1xuICAgIGNvbnN0IGVmQ29uc3RydWN0aW9uID0gaW5kZXguZWZDb25zdHJ1Y3Rpb24gPz8gNjQ7XG4gICAgcmV0dXJuIGBhd2FpdCBrbmV4LnJhdyhcXGBDUkVBVEUgSU5ERVggJHtpbmRleC5uYW1lfSBPTiAke3RhYmxlfSBVU0lORyBobnN3ICgke2NvbHVtbi5uYW1lfSAke3ZlY3Rvck9wc30pIFdJVEggKG0gPSAke219LCBlZl9jb25zdHJ1Y3Rpb24gPSAke2VmQ29uc3RydWN0aW9ufSlcXGApO2A7XG4gIH1cblxuICAvLyBJVkZGbGF0IChJbnZlcnRlZCBGaWxlIHdpdGggRmxhdCBDb21wcmVzc2lvbikgLSDrjIDsmqnrn4ksIOu5hOyaqSDspJHsmpQg7IucXG4gIGlmIChpbmRleC50eXBlID09PSBcIml2ZmZsYXRcIikge1xuICAgIGNvbnN0IGxpc3RzID0gaW5kZXgubGlzdHMgPz8gMTAwO1xuICAgIHJldHVybiBgYXdhaXQga25leC5yYXcoXFxgQ1JFQVRFIElOREVYICR7aW5kZXgubmFtZX0gT04gJHt0YWJsZX0gVVNJTkcgaXZmZmxhdCAoJHtjb2x1bW4ubmFtZX0gJHt2ZWN0b3JPcHN9KSBXSVRIIChsaXN0cyA9ICR7bGlzdHN9KVxcYCk7YDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgVW5rbm93biByYXcgU1FMIGluZGV4IHR5cGU6ICR7aW5kZXgudHlwZX1gKTtcbn1cblxuLyoqXG4gKiDthYzsnbTruJQg7IOd7ISx7ZWY64qUIOy8gOydtOyKpCAtIEZLIOyDneyEsVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUNyZWF0ZUNvZGVfRm9yZWlnbihcbiAgdGFibGU6IHN0cmluZyxcbiAgZm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbik6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZVtdPiB7XG4gIGlmIChmb3JlaWducy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCB7IHVwLCBkb3duIH0gPSBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZvcmVpZ25zKTtcbiAgaWYgKHVwLmxlbmd0aCA9PT0gMCAmJiBkb3duLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIGZvcmVpZ25z6rCAIOyeiOuKlOuNsCDsg53shLHrkJwg7L2U65Oc6rCAIOyXhuuKlCDqsr3smrDripQg67mE7KCV7IOB7KCB7J24IOyDge2ZqeydtOyngOunjCxcbiAgICAvLyDrp4jsnbTqt7jroIjsnbTshZgg7IOd7ISx7J2EIOykkeuLqOyLnO2CpOyngCDslYrqs6Ag67mIIOuwsOyXtOydhCDrsJjtmZjtlanri4jri6QuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW1xuICAgICdpbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjsnLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gdXAoa25leDogS25leCk6IFByb21pc2U8dm9pZD4ge1wiLFxuICAgIGByZXR1cm4ga25leC5zY2hlbWEuYWx0ZXJUYWJsZShcIiR7dGFibGV9XCIsICh0YWJsZSkgPT4ge2AsXG4gICAgXCIvLyBjcmVhdGUgZmtcIixcbiAgICAuLi51cCxcbiAgICBcIn0pO1wiLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgYHJldHVybiBrbmV4LnNjaGVtYS5hbHRlclRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCxcbiAgICBcIi8vIGRyb3AgZmtcIixcbiAgICAuLi5kb3duLFxuICAgIFwifSk7XCIsXG4gICAgXCJ9XCIsXG4gIF07XG5cbiAgY29uc3QgZm9yZWlnbktleXNTdHJpbmcgPSBmb3JlaWducy5tYXAoKGZvcmVpZ24pID0+IGZvcmVpZ24uY29sdW1ucy5qb2luKFwiX1wiKSkuam9pbihcIl9cIik7XG4gIHJldHVybiBbXG4gICAge1xuICAgICAgdGFibGUsXG4gICAgICB0eXBlOiBcImZvcmVpZ25cIixcbiAgICAgIHRpdGxlOiBgZm9yZWlnbl9fJHt0YWJsZX1fXyR7Zm9yZWlnbktleXNTdHJpbmd9YCxcbiAgICAgIGZvcm1hdHRlZDogZm9ybWF0Q29kZShsaW5lcy5qb2luKFwiXFxuXCIpLCBcInR5cGVzY3JpcHRcIiwgYHNyYy9taWdyYXRpb24vJHt0YWJsZX0udHNgKSxcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIE1pZ3JhdGlvbkZvcmVpZ25bXSDsnb3slrTshJwg7Jm467aA7YKkIGNvbnN0cmFpbnQg7KCV7J2Y7ZWY64qUIOq1rOusuCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuRm9yZWlnbkRlZmluaXRpb25zKFxuICB0YWJsZTogc3RyaW5nLFxuICBmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdLFxuKTogeyB1cDogc3RyaW5nW107IGRvd246IHN0cmluZ1tdIH0ge1xuICByZXR1cm4gZm9yZWlnbnMucmVkdWNlKFxuICAgIChyLCBmb3JlaWduKSA9PiB7XG4gICAgICBjb25zdCBjb2x1bW5zU3RyaW5nUXVvdGUgPSBmb3JlaWduLmNvbHVtbnNcbiAgICAgICAgLm1hcCgoY29sKSA9PiBgJyR7Y29sLnJlcGxhY2UoYCR7dGFibGV9LmAsIFwiXCIpfSdgKVxuICAgICAgICAuam9pbihcIixcIik7XG4gICAgICByLnVwLnB1c2goXG4gICAgICAgIGB0YWJsZS5mb3JlaWduKCcke2ZvcmVpZ24uY29sdW1ucy5qb2luKFwiLFwiKX0nKVxuICAgICAgICAgICAgLnJlZmVyZW5jZXMoJyR7Zm9yZWlnbi50b30nKVxuICAgICAgICAgICAgLm9uVXBkYXRlKCcke2ZvcmVpZ24ub25VcGRhdGV9JylcbiAgICAgICAgICAgIC5vbkRlbGV0ZSgnJHtmb3JlaWduLm9uRGVsZXRlfScpYCxcbiAgICAgICk7XG4gICAgICByLmRvd24ucHVzaChgdGFibGUuZHJvcEZvcmVpZ24oWyR7Y29sdW1uc1N0cmluZ1F1b3RlfV0pYCk7XG4gICAgICByZXR1cm4gcjtcbiAgICB9LFxuICAgIHtcbiAgICAgIHVwOiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgIGRvd246IFtdIGFzIHN0cmluZ1tdLFxuICAgIH0sXG4gICk7XG59XG5cbi8qKlxuICog7YWM7J2067iUIOuzgOqyvSDsvIDsnbTsiqQgLSDsu6zrn7wv7J24642x7IqkIOuzgOqyvVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUFsdGVyQ29kZV9Db2x1bW5BbmRJbmRleGVzKFxuICB0YWJsZTogc3RyaW5nLFxuICBlbnRpdHlDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgZW50aXR5SW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbiAgZGJDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgZGJJbmRleGVzOiBNaWdyYXRpb25JbmRleFtdLFxuICBkYkZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10sXG4gIGNvbXBhcmVEQj86IEtuZXgsXG4pOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICBjb25zdCByZXNvbHZlZEVudGl0eUNvbHVtbnMgPSByZXNvbHZlU2VhcmNoVGV4dENvbHVtbnModGFibGUsIGVudGl0eUNvbHVtbnMpO1xuICBjb25zdCBzZWFyY2hUZXh0Q29sdW1uTmFtZXMgPSBnZXRTZWFyY2hUZXh0Q29sdW1uTmFtZXModGFibGUpO1xuICAvKlxuICAgIOyEuOu2gCDruYTqtZAg7ZuEIOuLpOuluOygkCDssL7slYTshJwg7L2U65OcIOyDneyEsVxuXG4gICAgMS4g7Lus65+86rCv7IiYIOuLpOumhDogTUTsl5Ag7J6I7Jy864KYLCBEQuyXkCDsl4bri6TrqbQg7LaU6rCAXG4gICAgMi4g7Lus65+86rCv7IiYIOuLpOumhDogTUTsl5Ag7JeG7Jy864KYLCBEQuyXkCDsnojri6TrqbQg7IKt7KCcXG4gICAgMy4g6re47Jm4IOy7rOufvCjsu6zrn7wg6rCv7IiY6rCAIOuPmeydvO2VmOqxsOuCmCwg64uk66W4IOqyveyasCDrj5nsnbztlZwg7Lus65+864G866asKSA9PiBhbHRlclxuICAgIDQuIOuLpOuluOqxsCDri6Qg64+Z7J287ZWY6rOgIGluZGV466eMIOuzgOqyveuQmOuKlCDqsr3smrBcblxuICAgICoqIOy7rOufvOuqheydhCDrs4Dqsr3tlZjripQg6rK97Jqw64qUIOuUsOuhnCDtlbjrk6Trp4HtlZjsp4Ag7JWK7J2MXG4gICAgPT4gZHJvcC9hZGQg7ZiV7YOc7J2YIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5zqsIAg7IOd7ISx65CY64qU642wLCDsiJjrj5nsnLzroZwgcmVuYW1lIOy9lOuTnOuhnCDsiJjsoJXtlZjsl6wg7LKY66asXG4gICovXG5cbiAgLy8gUEsoaWQpIOy7rOufvCDtg4DsnoUg67OA6rK9IOqwkOyngCDrsI8g7LKY66asXG4gIGNvbnN0IGVudGl0eUlkQ29sID0gcmVzb2x2ZWRFbnRpdHlDb2x1bW5zLmZpbmQoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwiaWRcIik7XG4gIGNvbnN0IGRiSWRDb2wgPSBkYkNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJpZFwiKTtcblxuICBpZiAoZW50aXR5SWRDb2wgJiYgZGJJZENvbCAmJiBjb21wYXJlREIpIHtcbiAgICBjb25zdCBpc1BrVHlwZUNoYW5nZWQgPVxuICAgICAgZW50aXR5SWRDb2wudHlwZSAhPT0gZGJJZENvbC50eXBlIHx8IGVudGl0eUlkQ29sLmxlbmd0aCAhPT0gZGJJZENvbC5sZW5ndGg7XG5cbiAgICBpZiAoaXNQa1R5cGVDaGFuZ2VkKSB7XG4gICAgICByZXR1cm4gZ2VuZXJhdGVQa1R5cGVDaGFuZ2VNaWdyYXRpb24oXG4gICAgICAgIHRhYmxlLFxuICAgICAgICBlbnRpdHlJZENvbCxcbiAgICAgICAgZGJJZENvbCxcbiAgICAgICAgcmVzb2x2ZWRFbnRpdHlDb2x1bW5zLFxuICAgICAgICBlbnRpdHlJbmRleGVzLFxuICAgICAgICBkYkNvbHVtbnMsXG4gICAgICAgIGRiSW5kZXhlcyxcbiAgICAgICAgZGJGb3JlaWducyxcbiAgICAgICAgY29tcGFyZURCLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyDqsIEg7Lus65+8IOydtOumhCDquLDspIDsnLzroZwgYWRkLCBkcm9wLCBhbHRlciDsl6zrtoAg7ZmV7J24XG4gIGNvbnN0IGFsdGVyQ29sdW1uc1RvID0gZ2V0QWx0ZXJDb2x1bW5zVG8ocmVzb2x2ZWRFbnRpdHlDb2x1bW5zLCBkYkNvbHVtbnMsIHNlYXJjaFRleHRDb2x1bW5OYW1lcyk7XG5cbiAgLy8g7LaU7Lac65CcIOy7rOufvOuTpOydhCDquLDspIDsnLzroZwg6rCB6rCBIOudvOyduCDsg53shLFcbiAgY29uc3QgYWx0ZXJDb2x1bW5MaW5lc1RvID0gZ2V0QWx0ZXJDb2x1bW5MaW5lc1RvKFxuICAgIGFsdGVyQ29sdW1uc1RvLFxuICAgIHJlc29sdmVkRW50aXR5Q29sdW1ucyxcbiAgICB0YWJsZSxcbiAgICBkYkZvcmVpZ25zLFxuICApO1xuXG4gIC8vIOyduOuNseyKpOydmCBhZGQsIGRyb3Ag7Jes67aAIO2ZleyduFxuICBjb25zdCBhbHRlckluZGV4ZXNUbyA9IGdldEFsdGVySW5kZXhlc1RvKGVudGl0eUluZGV4ZXMsIGRiSW5kZXhlcyk7XG4gIGNvbnN0IHJlY3JlYXRlZFNlYXJjaFRleHRDb2x1bW5OYW1lcyA9IG5ldyBTZXQoXG4gICAgYWx0ZXJDb2x1bW5zVG8uYWx0ZXJcbiAgICAgIC5maWx0ZXIoKGRiQ29sdW1uKSA9PiB7XG4gICAgICAgIGNvbnN0IGVudGl0eUNvbHVtbiA9IHJlc29sdmVkRW50aXR5Q29sdW1ucy5maW5kKChjb2wpID0+IGNvbC5uYW1lID09PSBkYkNvbHVtbi5uYW1lKTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBzZWFyY2hUZXh0Q29sdW1uTmFtZXMuaGFzKGRiQ29sdW1uLm5hbWUpICYmXG4gICAgICAgICAgZGJDb2x1bW4uZ2VuZXJhdGVkICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICBlbnRpdHlDb2x1bW4/LmdlbmVyYXRlZCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ubmFtZSksXG4gICk7XG4gIGNvbnN0IHJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMgPSBkYkluZGV4ZXMuZmlsdGVyKFxuICAgIChpbmRleCkgPT5cbiAgICAgIGluZGV4LmNvbHVtbnMuc29tZSgoeyBuYW1lIH0pID0+IHJlY3JlYXRlZFNlYXJjaFRleHRDb2x1bW5OYW1lcy5oYXMobmFtZSkpICYmXG4gICAgICBhbHRlckluZGV4ZXNUby5kcm9wLnNvbWUoKGRyb3BJbmRleCkgPT4gZHJvcEluZGV4Lm5hbWUgPT09IGluZGV4Lm5hbWUpID09PSBmYWxzZSxcbiAgKTtcbiAgY29uc3QgcmVjcmVhdGVkU2VhcmNoVGV4dEVudGl0eUluZGV4ZXMgPSBlbnRpdHlJbmRleGVzLmZpbHRlcihcbiAgICAoaW5kZXgpID0+XG4gICAgICBpbmRleC5jb2x1bW5zLnNvbWUoKHsgbmFtZSB9KSA9PiByZWNyZWF0ZWRTZWFyY2hUZXh0Q29sdW1uTmFtZXMuaGFzKG5hbWUpKSAmJlxuICAgICAgYWx0ZXJJbmRleGVzVG8uYWRkLnNvbWUoKGFkZEluZGV4KSA9PiBhZGRJbmRleC5uYW1lID09PSBpbmRleC5uYW1lKSA9PT0gZmFsc2UsXG4gICk7XG4gIGNvbnN0IGltcGxpY2l0bHlEcm9wcGVkRGJJbmRleGVzID0gYWx0ZXJJbmRleGVzVG8uZHJvcC5maWx0ZXIoKGluZGV4KSA9PlxuICAgIGluZGV4LmNvbHVtbnMuZXZlcnkoKHsgbmFtZSB9KSA9PiBhbHRlckNvbHVtbnNUby5kcm9wLnNvbWUoKGNvbHVtbikgPT4gY29sdW1uLm5hbWUgPT09IG5hbWUpKSxcbiAgKTtcblxuICAvLyDsnbjrjbHsiqTqsIAg7IKt7KCc65CY64qUIOqyveyasCwg7Lus65+86rO8IOqwmeydtCDsgq3soJzrkJwg7LyA7J207Iqk7JeQ64qUIGRyb3Dsl5DshJwg7KCc7Jm47ZW07JW87ZWoIVxuICBjb25zdCBpbmRleE5lZWRzVG9Ecm9wID0gYWx0ZXJJbmRleGVzVG8uZHJvcC5maWx0ZXIoXG4gICAgKGluZGV4KSA9PlxuICAgICAgaW1wbGljaXRseURyb3BwZWREYkluZGV4ZXMuc29tZSgoZHJvcHBlZEluZGV4KSA9PiBkcm9wcGVkSW5kZXgubmFtZSA9PT0gaW5kZXgubmFtZSkgPT09IGZhbHNlLFxuICApO1xuXG4gIC8vIOu5iCDsvZTrk5wg7IOd7ISxIOuwqeyngFxuICBjb25zdCBoYXNVcENoYW5nZXMgPVxuICAgIGFsdGVyQ29sdW1uTGluZXNUby5hZGQudXAuYnVpbGRlci5sZW5ndGggPiAwIHx8XG4gICAgYWx0ZXJDb2x1bW5MaW5lc1RvLmFkZC51cC5yYXcubGVuZ3RoID4gMCB8fFxuICAgIGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLnVwLmJ1aWxkZXIubGVuZ3RoID4gMCB8fFxuICAgIGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci51cC5idWlsZGVyLmxlbmd0aCA+IDAgfHxcbiAgICBhbHRlckNvbHVtbkxpbmVzVG8uYWx0ZXIudXAucmF3Lmxlbmd0aCA+IDAgfHxcbiAgICBhbHRlckluZGV4ZXNUby5hZGQubGVuZ3RoID4gMCB8fFxuICAgIGluZGV4TmVlZHNUb0Ryb3AubGVuZ3RoID4gMCB8fFxuICAgIHJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMubGVuZ3RoID4gMDtcbiAgaWYgKCFoYXNVcENoYW5nZXMpIHtcbiAgICAvLyDrs4Dqsr3sgqztla3snbQg7JeG7Jy866m0IOu5iCDrsLDsl7Qg67CY7ZmYXG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIE5haXRlLnQoXCJtaWdyYXRvcjpnZW5lcmF0ZUFsdGVyQ29kZV9Db2x1bW5BbmRJbmRleGVzOmRlYnVnXCIsIHtcbiAgICBcImFsdGVyQ29sdW1uc1RvLmFkZC5sZW5ndGhcIjogYWx0ZXJDb2x1bW5zVG8uYWRkLmxlbmd0aCxcbiAgICBcImFsdGVyQ29sdW1uc1RvLmRyb3AubGVuZ3RoXCI6IGFsdGVyQ29sdW1uc1RvLmRyb3AubGVuZ3RoLFxuICAgIFwiYWx0ZXJDb2x1bW5zVG8uYWx0ZXIubGVuZ3RoXCI6IGFsdGVyQ29sdW1uc1RvLmFsdGVyLmxlbmd0aCxcbiAgICBcImFsdGVySW5kZXhlc1RvLmFkZC5sZW5ndGhcIjogYWx0ZXJJbmRleGVzVG8uYWRkLmxlbmd0aCxcbiAgICBcImFsdGVySW5kZXhlc1RvLmRyb3AubGVuZ3RoXCI6IGFsdGVySW5kZXhlc1RvLmRyb3AubGVuZ3RoLFxuICAgIFwiaW5kZXhOZWVkc1RvRHJvcC5sZW5ndGhcIjogaW5kZXhOZWVkc1RvRHJvcC5sZW5ndGgsXG4gIH0pO1xuICAvLyBOYWl0ZS50KFwibWlncmF0b3I6Z2VuZXJhdGVBbHRlckNvZGVfQ29sdW1uQW5kSW5kZXhlczphbHRlckNvbHVtbnNUb1wiLCBhbHRlckNvbHVtbnNUbyk7XG5cbiAgLy8gVE9ETzog7J24642x7Iqk66qFIOuzgOqyveuQnCDqsr3smrAg7LKY66asXG5cbiAgLy8gdGFibGUgYnVpbGRlciDrqZTshJzrk5zroZwg7Iuk7ZaJ7ZWgIOy9lOuTnCAoZHJvcCDihpIgYWRkIOKGkiBhbHRlciDsiJzshJwpXG4gIGNvbnN0IHVwQnVpbGRlckxpbmVzID0gW1xuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uZHJvcC51cC5idWlsZGVyLmxlbmd0aCA+IDAgPyBhbHRlckNvbHVtbkxpbmVzVG8uZHJvcC51cC5idWlsZGVyIDogW10pLFxuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uYWRkLnVwLmJ1aWxkZXIubGVuZ3RoID4gMCA/IGFsdGVyQ29sdW1uTGluZXNUby5hZGQudXAuYnVpbGRlciA6IFtdKSxcbiAgICAuLi5yZWNyZWF0ZWRTZWFyY2hUZXh0RGJJbmRleGVzLm1hcChnZW5JbmRleERyb3BEZWZpbml0aW9uKSxcbiAgICAuLi4oYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLnVwLmJ1aWxkZXIubGVuZ3RoID4gMCA/IGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci51cC5idWlsZGVyIDogW10pLFxuICAgIC4uLmluZGV4TmVlZHNUb0Ryb3AubWFwKGdlbkluZGV4RHJvcERlZmluaXRpb24pLFxuICBdO1xuXG4gIC8vIGtuZXgucmF3KCnroZwg7Iuk7ZaJ7ZWgIOy9lOuTnFxuICBjb25zdCB1cFJhd0xpbmVzID0gW1xuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uYWRkLnVwLnJhdy5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFkZC51cC5yYXcgOiBbXSksXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci51cC5yYXcubGVuZ3RoID4gMCA/IGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci51cC5yYXcgOiBbXSksXG4gICAgLi4ucmVjcmVhdGVkU2VhcmNoVGV4dEVudGl0eUluZGV4ZXMubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICAgIC4uLmFsdGVySW5kZXhlc1RvLmFkZC5tYXAoKGluZGV4KSA9PiBnZW5JbmRleERlZmluaXRpb24oaW5kZXgsIHRhYmxlKSksXG4gIF07XG5cbiAgLy8gZG93buydgCB1cOydmCDsl63siJwgKGFkZC5kb3duID0gZHJvcCByb2xsYmFjaywgZHJvcC5kb3duID0gYWRkIHJvbGxiYWNrKVxuICBjb25zdCBkb3duQnVpbGRlckxpbmVzID0gW1xuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uYWRkLmRvd24uYnVpbGRlci5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFkZC5kb3duLmJ1aWxkZXIgOiBbXSksXG4gICAgLi4ucmVjcmVhdGVkU2VhcmNoVGV4dEVudGl0eUluZGV4ZXMubWFwKGdlbkluZGV4RHJvcERlZmluaXRpb24pLFxuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uYWx0ZXIuZG93bi5idWlsZGVyLmxlbmd0aCA+IDBcbiAgICAgID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLmRvd24uYnVpbGRlclxuICAgICAgOiBbXSksXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLmRvd24uYnVpbGRlci5sZW5ndGggPiAwXG4gICAgICA/IGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLmRvd24uYnVpbGRlclxuICAgICAgOiBbXSksXG4gICAgLi4uYWx0ZXJJbmRleGVzVG8uYWRkXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAoaW5kZXgpID0+XG4gICAgICAgICAgaW5kZXguY29sdW1ucy5ldmVyeSgoaW5kZXhDb2wpID0+XG4gICAgICAgICAgICBhbHRlckNvbHVtbnNUby5hZGQubWFwKChjb2wpID0+IGNvbC5uYW1lKS5pbmNsdWRlcyhpbmRleENvbC5uYW1lKSxcbiAgICAgICAgICApID09PSBmYWxzZSxcbiAgICAgIClcbiAgICAgIC5tYXAoZ2VuSW5kZXhEcm9wRGVmaW5pdGlvbiksXG4gIF07XG5cbiAgY29uc3QgZG93blJhd0xpbmVzID0gW1xuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uZHJvcC5kb3duLnJhdy5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmRyb3AuZG93bi5yYXcgOiBbXSksXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci5kb3duLnJhdy5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLmRvd24ucmF3IDogW10pLFxuICAgIC4uLnJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICAgIC4uLmltcGxpY2l0bHlEcm9wcGVkRGJJbmRleGVzLm1hcCgoaW5kZXgpID0+IGdlbkluZGV4RGVmaW5pdGlvbihpbmRleCwgdGFibGUpKSxcbiAgICAuLi5pbmRleE5lZWRzVG9Ecm9wLm1hcCgoaW5kZXgpID0+IGdlbkluZGV4RGVmaW5pdGlvbihpbmRleCwgdGFibGUpKSxcbiAgXTtcblxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG4gICAgJ2ltcG9ydCB7IEtuZXggfSBmcm9tIFwia25leFwiOycsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cChrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4uKHVwQnVpbGRlckxpbmVzLmxlbmd0aCA+IDBcbiAgICAgID8gW2Bhd2FpdCBrbmV4LnNjaGVtYS5hbHRlclRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCwgLi4udXBCdWlsZGVyTGluZXMsIFwifSk7XCJdXG4gICAgICA6IFtdKSxcbiAgICAuLi51cFJhd0xpbmVzLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4uKGRvd25CdWlsZGVyTGluZXMubGVuZ3RoID4gMFxuICAgICAgPyBbYGF3YWl0IGtuZXguc2NoZW1hLmFsdGVyVGFibGUoXCIke3RhYmxlfVwiLCAodGFibGUpID0+IHtgLCAuLi5kb3duQnVpbGRlckxpbmVzLCBcIn0pO1wiXVxuICAgICAgOiBbXSksXG4gICAgLi4uZG93blJhd0xpbmVzLFxuICAgIFwifVwiLFxuICBdO1xuXG4gIGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdENvZGUobGluZXMuam9pbihcIlxcblwiKSwgXCJ0eXBlc2NyaXB0XCIsIGBzcmMvbWlncmF0aW9uLyR7dGFibGV9LnRzYCk7XG4gIGNvbnN0IHRpdGxlID0gW1xuICAgIFwiYWx0ZXJcIixcbiAgICB0YWJsZSxcbiAgICAuLi4oW1wiYWRkXCIsIFwiZHJvcFwiLCBcImFsdGVyXCJdIGFzIGNvbnN0KVxuICAgICAgLm1hcCgoYWN0aW9uKSA9PiB7XG4gICAgICAgIGNvbnN0IGxlbiA9IGFsdGVyQ29sdW1uc1RvW2FjdGlvbl0ubGVuZ3RoO1xuICAgICAgICBpZiAobGVuID4gMCkge1xuICAgICAgICAgIHJldHVybiBhY3Rpb24gKyBsZW47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigocGFydCkgPT4gcGFydCAhPT0gbnVsbCksXG4gIF0uam9pbihcIl9cIik7XG5cbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICB0YWJsZSxcbiAgICAgIHRpdGxlLFxuICAgICAgZm9ybWF0dGVkLFxuICAgICAgdHlwZTogXCJub3JtYWxcIixcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIOy7rOufvCDruYTqtZDrpbwg7JyE7ZW0IEdlbmVyYXRlZCBDb2x1bW7snZggZXhwcmVzc2lvbuydhCDsoJzsmbjtlZwg6rCd7LK066W8IOyDneyEsVxuICovXG5mdW5jdGlvbiBub3JtYWxpemVDb2x1bW5Gb3JDb21wYXJpc29uKFxuICBjb2w6IE1pZ3JhdGlvbkNvbHVtbixcbiAgc2VhcmNoVGV4dENvbHVtbk5hbWVzOiBTZXQ8c3RyaW5nPixcbik6IE1pZ3JhdGlvbkNvbHVtbiB7XG4gIGlmICghY29sLmdlbmVyYXRlZCkge1xuICAgIHJldHVybiBjb2w7XG4gIH1cblxuICBpZiAoIXNlYXJjaFRleHRDb2x1bW5OYW1lcy5oYXMoY29sLm5hbWUpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmNvbCxcbiAgICAgIGdlbmVyYXRlZDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLmNvbCxcbiAgICBnZW5lcmF0ZWQ6IHtcbiAgICAgIC4uLmNvbC5nZW5lcmF0ZWQsXG4gICAgICBleHByZXNzaW9uOiBjYW5vbmljYWxpemVTZWFyY2hUZXh0R2VuZXJhdGVkRXhwcmVzc2lvbihjb2wuZ2VuZXJhdGVkLmV4cHJlc3Npb24pLFxuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICog6rCBIOy7rOufvCDsnbTrpoQg6riw7KSA7Jy866GcIGFkZCwgZHJvcCwgYWx0ZXIg7Jes67aAIO2ZleyduFxuICovXG5mdW5jdGlvbiBnZXRBbHRlckNvbHVtbnNUbyhcbiAgZW50aXR5Q29sdW1uczogTWlncmF0aW9uQ29sdW1uW10sXG4gIGRiQ29sdW1uczogTWlncmF0aW9uQ29sdW1uW10sXG4gIHNlYXJjaFRleHRDb2x1bW5OYW1lczogU2V0PHN0cmluZz4sXG4pIHtcbiAgY29uc3QgY29sdW1uc1RvID0ge1xuICAgIGFkZDogW10gYXMgTWlncmF0aW9uQ29sdW1uW10sXG4gICAgZHJvcDogW10gYXMgTWlncmF0aW9uQ29sdW1uW10sXG4gICAgYWx0ZXI6IFtdIGFzIE1pZ3JhdGlvbkNvbHVtbltdLFxuICB9O1xuXG4gIC8vIOy7rOufvOuqhSDquLDspIAg67mE6rWQXG4gIGNvbnN0IGV4dHJhQ29sdW1ucyA9IHtcbiAgICBkYjogZGlmZihkYkNvbHVtbnMsIGVudGl0eUNvbHVtbnMsIChjb2wpID0+IFtjb2wubmFtZSwgY29sLmdlbmVyYXRlZD8udHlwZV0uam9pbihcIi8vL1wiKSksXG4gICAgZW50aXR5OiBkaWZmKGVudGl0eUNvbHVtbnMsIGRiQ29sdW1ucywgKGNvbCkgPT4gW2NvbC5uYW1lLCBjb2wuZ2VuZXJhdGVkPy50eXBlXS5qb2luKFwiLy8vXCIpKSxcbiAgfTtcbiAgaWYgKGV4dHJhQ29sdW1ucy5lbnRpdHkubGVuZ3RoID4gMCkge1xuICAgIGNvbHVtbnNUby5hZGQgPSBjb2x1bW5zVG8uYWRkLmNvbmNhdChleHRyYUNvbHVtbnMuZW50aXR5KTtcbiAgfVxuICBpZiAoZXh0cmFDb2x1bW5zLmRiLmxlbmd0aCA+IDApIHtcbiAgICBjb2x1bW5zVG8uZHJvcCA9IGNvbHVtbnNUby5kcm9wLmNvbmNhdChleHRyYUNvbHVtbnMuZGIpO1xuICB9XG5cbiAgLy8g64+Z7J28IOy7rOufvOuqheydmCDshLjrtoAg7ZWE65OcIOu5hOq1kFxuICBjb25zdCBzYW1lRGJDb2x1bW5zID0gaW50ZXJzZWN0aW9uQnkoZGJDb2x1bW5zLCBlbnRpdHlDb2x1bW5zLCAoY29sKSA9PiBjb2wubmFtZSk7XG4gIGNvbnN0IHNhbWVNZENvbHVtbnMgPSBpbnRlcnNlY3Rpb25CeShlbnRpdHlDb2x1bW5zLCBkYkNvbHVtbnMsIChjb2wpID0+IGNvbC5uYW1lKTtcbiAgY29sdW1uc1RvLmFsdGVyID0gZGlmZmVyZW5jZVdpdGgoc2FtZURiQ29sdW1ucywgc2FtZU1kQ29sdW1ucywgKGEsIGIpID0+XG4gICAgZXF1YWwoXG4gICAgICBub3JtYWxpemVDb2x1bW5Gb3JDb21wYXJpc29uKGEsIHNlYXJjaFRleHRDb2x1bW5OYW1lcyksXG4gICAgICBub3JtYWxpemVDb2x1bW5Gb3JDb21wYXJpc29uKGIsIHNlYXJjaFRleHRDb2x1bW5OYW1lcyksXG4gICAgKSxcbiAgKTtcblxuICByZXR1cm4gY29sdW1uc1RvO1xufVxuXG4vKipcbiAqIOy2lOy2nOuQnCDsu6zrn7zrk6TsnYQg6riw7KSA7Jy866GcIOqwgeqwgSDrnbzsnbgg7IOd7ISxXG4gKi9cbmZ1bmN0aW9uIGdldEFsdGVyQ29sdW1uTGluZXNUbyhcbiAgY29sdW1uc1RvOiBSZXR1cm5UeXBlPHR5cGVvZiBnZXRBbHRlckNvbHVtbnNUbz4sXG4gIGVudGl0eUNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdLFxuICB0YWJsZTogc3RyaW5nLFxuICBkYkZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10sXG4pIHtcbiAgY29uc3Qgc2VhcmNoVGV4dENvbHVtbk5hbWVzID0gZ2V0U2VhcmNoVGV4dENvbHVtbk5hbWVzKHRhYmxlKTtcbiAgY29uc3QgbGluZXNUbyA9IHtcbiAgICBhZGQ6IHtcbiAgICAgIHVwOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgICBkb3duOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgfSxcbiAgICBkcm9wOiB7XG4gICAgICB1cDogeyBidWlsZGVyOiBbXSBhcyBzdHJpbmdbXSwgcmF3OiBbXSBhcyBzdHJpbmdbXSB9LFxuICAgICAgZG93bjogeyBidWlsZGVyOiBbXSBhcyBzdHJpbmdbXSwgcmF3OiBbXSBhcyBzdHJpbmdbXSB9LFxuICAgIH0sXG4gICAgYWx0ZXI6IHtcbiAgICAgIHVwOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgICBkb3duOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgfSxcbiAgfTtcblxuICAvLyBhZGQgY29sdW1uc1xuICBjb25zdCBhZGRDb2x1bW5EZWZzID0gZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIGNvbHVtbnNUby5hZGQpO1xuICBsaW5lc1RvLmFkZC51cCA9IHtcbiAgICBidWlsZGVyOiBhZGRDb2x1bW5EZWZzLmJ1aWxkZXIubGVuZ3RoID4gMCA/IFtcIi8vIGFkZFwiLCAuLi5hZGRDb2x1bW5EZWZzLmJ1aWxkZXJdIDogW10sXG4gICAgcmF3OlxuICAgICAgYWRkQ29sdW1uRGVmcy5yYXcubGVuZ3RoID4gMFxuICAgICAgICA/IFtcbiAgICAgICAgICAgIC4uLmdldFNlYXJjaFRleHRIZWxwZXJEZWZpbml0aW9ucyh0YWJsZSwgY29sdW1uc1RvLmFkZCksXG4gICAgICAgICAgICBcIi8vIGFkZCAoZ2VuZXJhdGVkKVwiLFxuICAgICAgICAgICAgLi4uYWRkQ29sdW1uRGVmcy5yYXcsXG4gICAgICAgICAgXVxuICAgICAgICA6IFtdLFxuICB9O1xuICBsaW5lc1RvLmFkZC5kb3duID0ge1xuICAgIGJ1aWxkZXI6XG4gICAgICBjb2x1bW5zVG8uYWRkLmxlbmd0aCA+IDBcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBcIi8vIHJvbGxiYWNrIC0gYWRkXCIsXG4gICAgICAgICAgICBgdGFibGUuZHJvcENvbHVtbnMoJHtjb2x1bW5zVG8uYWRkLm1hcCgoY29sKSA9PiBgJyR7Y29sLm5hbWV9J2ApLmpvaW4oXCIsIFwiKX0pYCxcbiAgICAgICAgICBdXG4gICAgICAgIDogW10sXG4gICAgcmF3OiBbXSxcbiAgfTtcblxuICAvLyBkcm9w7ZWgIOy7rOufvOyXkCDqsbjrprAgRksg7LC+6riwXG4gIGNvbnN0IGRyb3BDb2x1bW5OYW1lcyA9IGNvbHVtbnNUby5kcm9wLm1hcCgoY29sKSA9PiBjb2wubmFtZSk7XG4gIGNvbnN0IGZrVG9Ecm9wQmVmb3JlQ29sdW1uID0gZGJGb3JlaWducy5maWx0ZXIoKGZrKSA9PlxuICAgIGZrLmNvbHVtbnMuc29tZSgoY29sKSA9PiBkcm9wQ29sdW1uTmFtZXMuaW5jbHVkZXMoY29sKSksXG4gICk7XG5cbiAgY29uc3QgZHJvcEZrTGluZXMgPSBma1RvRHJvcEJlZm9yZUNvbHVtbi5tYXAoKGZrKSA9PiB7XG4gICAgY29uc3QgY29sdW1uc1N0cmluZ1F1b3RlID0gZmsuY29sdW1ucy5tYXAoKGNvbCkgPT4gYCcke2NvbH0nYCkuam9pbihcIixcIik7XG4gICAgcmV0dXJuIGB0YWJsZS5kcm9wRm9yZWlnbihbJHtjb2x1bW5zU3RyaW5nUXVvdGV9XSlgO1xuICB9KTtcblxuICBjb25zdCByZXN0b3JlRmtMaW5lcyA9IGdlbkZvcmVpZ25EZWZpbml0aW9ucyh0YWJsZSwgZmtUb0Ryb3BCZWZvcmVDb2x1bW4pLnVwO1xuXG4gIC8vIGRyb3DsnZggcm9sbGJhY2vsi5zsl5DripQgZ2VuZXJhdGVkIGNvbHVtbuuPhCDrs7Xsm5DtlbTslbwg7ZWoXG4gIGNvbnN0IGRyb3BDb2x1bW5EZWZzID0gZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIGNvbHVtbnNUby5kcm9wKTtcbiAgbGluZXNUby5kcm9wID0ge1xuICAgIHVwOiB7XG4gICAgICBidWlsZGVyOiBbXG4gICAgICAgIC4uLihkcm9wRmtMaW5lcy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBbXCIvLyBkcm9wIGZvcmVpZ24ga2V5cyBvbiBjb2x1bW5zIHRvIGJlIGRyb3BwZWRcIiwgLi4uZHJvcEZrTGluZXNdXG4gICAgICAgICAgOiBbXSksXG4gICAgICAgIC4uLihjb2x1bW5zVG8uZHJvcC5sZW5ndGggPiAwXG4gICAgICAgICAgPyBbXG4gICAgICAgICAgICAgIFwiLy8gZHJvcCBjb2x1bW5zXCIsXG4gICAgICAgICAgICAgIGB0YWJsZS5kcm9wQ29sdW1ucygke2NvbHVtbnNUby5kcm9wLm1hcCgoY29sKSA9PiBgJyR7Y29sLm5hbWV9J2ApLmpvaW4oXCIsIFwiKX0pYCxcbiAgICAgICAgICAgIF1cbiAgICAgICAgICA6IFtdKSxcbiAgICAgIF0sXG4gICAgICByYXc6IFtdLFxuICAgIH0sXG4gICAgZG93bjoge1xuICAgICAgYnVpbGRlcjogW1xuICAgICAgICAuLi4oZHJvcENvbHVtbkRlZnMuYnVpbGRlci5sZW5ndGggPiAwXG4gICAgICAgICAgPyBbXCIvLyByb2xsYmFjayAtIGRyb3AgY29sdW1uc1wiLCAuLi5kcm9wQ29sdW1uRGVmcy5idWlsZGVyXVxuICAgICAgICAgIDogW10pLFxuICAgICAgICAuLi4ocmVzdG9yZUZrTGluZXMubGVuZ3RoID4gMCA/IFtcIi8vIHJlc3RvcmUgZm9yZWlnbiBrZXlzXCIsIC4uLnJlc3RvcmVGa0xpbmVzXSA6IFtdKSxcbiAgICAgIF0sXG4gICAgICByYXc6XG4gICAgICAgIGRyb3BDb2x1bW5EZWZzLnJhdy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBbXG4gICAgICAgICAgICAgIC4uLmdldFNlYXJjaFRleHRIZWxwZXJEZWZpbml0aW9ucyh0YWJsZSwgY29sdW1uc1RvLmRyb3ApLFxuICAgICAgICAgICAgICBcIi8vIHJvbGxiYWNrIC0gZHJvcCBjb2x1bW5zIChnZW5lcmF0ZWQpXCIsXG4gICAgICAgICAgICAgIC4uLmRyb3BDb2x1bW5EZWZzLnJhdyxcbiAgICAgICAgICAgIF1cbiAgICAgICAgICA6IFtdLFxuICAgIH0sXG4gIH07XG5cbiAgLy8gYWx0ZXIgY29sdW1ucyAoR2VuZXJhdGVkIENvbHVtbuydgCBBTFRFUiDrtojqsIDtlZjrr4DroZwgZHJvcCDtm4Qg7J6s7IOd7ISxKVxuICBsaW5lc1RvLmFsdGVyID0gY29sdW1uc1RvLmFsdGVyLnJlZHVjZShcbiAgICAociwgZGJDb2x1bW4pID0+IHtcbiAgICAgIGNvbnN0IGVudGl0eUNvbHVtbiA9IGVudGl0eUNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gZGJDb2x1bW4ubmFtZSk7XG4gICAgICBpZiAoZW50aXR5Q29sdW1uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgc2VhcmNoVGV4dENvbHVtbk5hbWVzLmhhcyhkYkNvbHVtbi5uYW1lKSAmJlxuICAgICAgICBkYkNvbHVtbi5nZW5lcmF0ZWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBlbnRpdHlDb2x1bW4uZ2VuZXJhdGVkICE9PSB1bmRlZmluZWRcbiAgICAgICkge1xuICAgICAgICByLnVwLmJ1aWxkZXIgPSBbXG4gICAgICAgICAgLi4uci51cC5idWlsZGVyLFxuICAgICAgICAgIFwiLy8gYWx0ZXIgZ2VuZXJhdGVkIGNvbHVtblwiLFxuICAgICAgICAgIGB0YWJsZS5kcm9wQ29sdW1ucygnJHtkYkNvbHVtbi5uYW1lfScpYCxcbiAgICAgICAgXTtcbiAgICAgICAgci51cC5yYXcgPSBbXG4gICAgICAgICAgLi4uci51cC5yYXcsXG4gICAgICAgICAgLi4uZ2V0U2VhcmNoVGV4dEhlbHBlckRlZmluaXRpb25zKHRhYmxlLCBbZW50aXR5Q29sdW1uXSksXG4gICAgICAgICAgXCIvLyBhbHRlciBnZW5lcmF0ZWQgY29sdW1uXCIsXG4gICAgICAgICAgZ2VuR2VuZXJhdGVkQ29sdW1uRGVmaW5pdGlvbih0YWJsZSwgZW50aXR5Q29sdW1uKSxcbiAgICAgICAgXTtcbiAgICAgICAgci5kb3duLmJ1aWxkZXIgPSBbXG4gICAgICAgICAgLi4uci5kb3duLmJ1aWxkZXIsXG4gICAgICAgICAgXCIvLyByb2xsYmFjayAtIGFsdGVyIGdlbmVyYXRlZCBjb2x1bW5cIixcbiAgICAgICAgICBgdGFibGUuZHJvcENvbHVtbnMoJyR7ZGJDb2x1bW4ubmFtZX0nKWAsXG4gICAgICAgIF07XG4gICAgICAgIHIuZG93bi5yYXcgPSBbXG4gICAgICAgICAgLi4uci5kb3duLnJhdyxcbiAgICAgICAgICAuLi5nZXRTZWFyY2hUZXh0SGVscGVyRGVmaW5pdGlvbnModGFibGUsIFtkYkNvbHVtbl0pLFxuICAgICAgICAgIFwiLy8gcm9sbGJhY2sgLSBhbHRlciBnZW5lcmF0ZWQgY29sdW1uXCIsXG4gICAgICAgICAgZ2VuR2VuZXJhdGVkQ29sdW1uRGVmaW5pdGlvbih0YWJsZSwgZGJDb2x1bW4pLFxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH1cblxuICAgICAgLy8g7Lus65+8IOuzgOqyveyCrO2VrVxuICAgICAgY29uc3QgY29sdW1uRGlmZlVwID0gZGlmZihcbiAgICAgICAgZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIFtlbnRpdHlDb2x1bW5dKS5idWlsZGVyLFxuICAgICAgICBnZW5Db2x1bW5EZWZpbml0aW9ucyh0YWJsZSwgW2RiQ29sdW1uXSkuYnVpbGRlcixcbiAgICAgICk7XG4gICAgICBjb25zdCBjb2x1bW5EaWZmRG93biA9IGRpZmYoXG4gICAgICAgIGdlbkNvbHVtbkRlZmluaXRpb25zKHRhYmxlLCBbZGJDb2x1bW5dKS5idWlsZGVyLFxuICAgICAgICBnZW5Db2x1bW5EZWZpbml0aW9ucyh0YWJsZSwgW2VudGl0eUNvbHVtbl0pLmJ1aWxkZXIsXG4gICAgICApO1xuICAgICAgaWYgKGNvbHVtbkRpZmZVcC5sZW5ndGggPiAwKSB7XG4gICAgICAgIHIudXAuYnVpbGRlciA9IFtcbiAgICAgICAgICAuLi5yLnVwLmJ1aWxkZXIsXG4gICAgICAgICAgXCIvLyBhbHRlciBjb2x1bW5cIixcbiAgICAgICAgICAuLi5jb2x1bW5EaWZmVXAubWFwKChsKSA9PiBgJHtsLnJlcGxhY2UoXCI7XCIsIFwiXCIpfS5hbHRlcigpO2ApLFxuICAgICAgICBdO1xuICAgICAgICByLmRvd24uYnVpbGRlciA9IFtcbiAgICAgICAgICAuLi5yLmRvd24uYnVpbGRlcixcbiAgICAgICAgICBcIi8vIHJvbGxiYWNrIC0gYWx0ZXIgY29sdW1uXCIsXG4gICAgICAgICAgLi4uY29sdW1uRGlmZkRvd24ubWFwKChsKSA9PiBgJHtsLnJlcGxhY2UoXCI7XCIsIFwiXCIpfS5hbHRlcigpO2ApLFxuICAgICAgICBdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcjtcbiAgICB9LFxuICAgIHtcbiAgICAgIHVwOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgICBkb3duOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgfSxcbiAgKTtcblxuICByZXR1cm4gbGluZXNUbztcbn1cblxuLyoqXG4gKiDsnbjrjbHsiqTsnZggYWRkLCBkcm9wIOyXrOu2gCDtmZXsnbhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsdGVySW5kZXhlc1RvKGVudGl0eUluZGV4ZXM6IE1pZ3JhdGlvbkluZGV4W10sIGRiSW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSkge1xuICAvLyDsnbjrjbHsiqQg67mE6rWQXG4gIGNvbnN0IGluZGV4ZXNUbyA9IHtcbiAgICBhZGQ6IFtdIGFzIE1pZ3JhdGlvbkluZGV4W10sXG4gICAgZHJvcDogW10gYXMgTWlncmF0aW9uSW5kZXhbXSxcbiAgfTtcblxuICAvLyDsnbjrjbHsiqQg6rOg7JygIOyLneuzhOyekCDsg53shLEgKG5hbWXsnYQg7KCc7Jm47ZWcIOuqqOuToCDtlYTrk5zrpbwg66y47J6Q7Je066GcIOuzgO2ZmO2VmOyXrCDsobDtlakpXG4gIGNvbnN0IGlkZW50aXR5ID0gPFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oaW5kZXg6IFQpOiBzdHJpbmcgPT4ge1xuICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhpbmRleClcbiAgICAgIC5maWx0ZXIoKGtleSkgPT4ga2V5ICE9PSBcIm5hbWVcIilcbiAgICAgIC5zb3J0KCk7XG5cbiAgICByZXR1cm4ga2V5c1xuICAgICAgLm1hcCgoa2V5KSA9PiB7XG4gICAgICAgIGlmIChrZXkgPT09IFwibmFtZVwiKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5ID09PSBcImNvbHVtbnNcIikge1xuICAgICAgICAgIHJldHVybiAoaW5kZXhba2V5XSBhcyBNaWdyYXRpb25JbmRleFtcImNvbHVtbnNcIl0pLm1hcCgoY29sKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoY29sKVxuICAgICAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgICAgIC5tYXAoKGspID0+IGAke2t9PSR7Y29sW2sgYXMga2V5b2YgdHlwZW9mIGNvbF19YClcbiAgICAgICAgICAgICAgLmpvaW4oXCIvL1wiKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYCR7a2V5fT0ke2luZGV4W2tleSBhcyBrZXlvZiBNaWdyYXRpb25JbmRleF19YDtcbiAgICAgIH0pXG4gICAgICAuam9pbihcIi8vXCIpO1xuICB9O1xuXG4gIGNvbnN0IGV4dHJhSW5kZXhlcyA9IHtcbiAgICBkYjogZGlmZihkYkluZGV4ZXMsIGVudGl0eUluZGV4ZXMubWFwKHNldE1pZ3JhdGlvbkluZGV4RGVmYXVsdHMpLCBpZGVudGl0eSksXG4gICAgZW50aXR5OiBkaWZmKGVudGl0eUluZGV4ZXMubWFwKHNldE1pZ3JhdGlvbkluZGV4RGVmYXVsdHMpLCBkYkluZGV4ZXMsIGlkZW50aXR5KSxcbiAgfTtcbiAgaWYgKGV4dHJhSW5kZXhlcy5lbnRpdHkubGVuZ3RoID4gMCkge1xuICAgIGluZGV4ZXNUby5hZGQgPSBpbmRleGVzVG8uYWRkLmNvbmNhdChleHRyYUluZGV4ZXMuZW50aXR5KTtcbiAgfVxuICBpZiAoZXh0cmFJbmRleGVzLmRiLmxlbmd0aCA+IDApIHtcbiAgICBpbmRleGVzVG8uZHJvcCA9IGluZGV4ZXNUby5kcm9wLmNvbmNhdChleHRyYUluZGV4ZXMuZGIpO1xuICB9XG5cbiAgcmV0dXJuIGluZGV4ZXNUbztcbn1cblxuLyoqXG4gKiDsnbjrjbHsiqQg7IKt7KCcIOygleydmCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuSW5kZXhEcm9wRGVmaW5pdGlvbihpbmRleDogTWlncmF0aW9uSW5kZXgpIHtcbiAgcmV0dXJuIGB0YWJsZS5kcm9wSW5kZXgoWyR7aW5kZXguY29sdW1uc1xuICAgIC5tYXAoKGNvbHVtbikgPT4gYCcke2NvbHVtbi5uYW1lfSdgKVxuICAgIC5qb2luKFwiLFwiKX1dLCAnJHtpbmRleC5uYW1lfScpYDtcbn1cblxuLyoqXG4gKiBEQiDsobDtmowg6rKw6rO87JmAIOu5hOq1kO2VmOq4sCDsnITtlZwg7J24642x7IqkIOq4sOuzuOqwkiDshKTsoJVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldE1pZ3JhdGlvbkluZGV4RGVmYXVsdHMoaW5kZXg6IE1pZ3JhdGlvbkluZGV4KTogTWlncmF0aW9uSW5kZXgge1xuICBjb25zdCBpc1ZlY3RvckluZGV4ID0gaW5kZXgudHlwZSA9PT0gXCJobnN3XCIgfHwgaW5kZXgudHlwZSA9PT0gXCJpdmZmbGF0XCI7XG4gIGNvbnN0IHN1cHBvcnRzT3JkZXJpbmcgPSAhaXNWZWN0b3JJbmRleCAmJiAoIWluZGV4LnVzaW5nIHx8IGluZGV4LnVzaW5nID09PSBcImJ0cmVlXCIpO1xuICBjb25zdCBub3JtYWxpemVkVXNpbmcgPSBpc1ZlY3RvckluZGV4ID8gaW5kZXgudXNpbmcgOiAoaW5kZXgudXNpbmcgPz8gXCJidHJlZVwiKTtcblxuICByZXR1cm4ge1xuICAgIC4uLmluZGV4LFxuICAgIGNvbHVtbnM6IGluZGV4LmNvbHVtbnMubWFwKChjb2wpID0+ICh7XG4gICAgICBuYW1lOiBjb2wubmFtZSxcbiAgICAgIC4uLihnZXRJbmRleENvbHVtbk9wY2xhc3MoY29sKSA/IHsgb3BjbGFzczogZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbCkgfSA6IHt9KSxcbiAgICAgIC4uLihzdXBwb3J0c09yZGVyaW5nXG4gICAgICAgID8ge1xuICAgICAgICAgICAgc29ydE9yZGVyOiBjb2wuc29ydE9yZGVyID8/IFwiQVNDXCIsXG4gICAgICAgICAgICBudWxsc0ZpcnN0OiBjb2wubnVsbHNGaXJzdCA/PyBjb2wuc29ydE9yZGVyID09PSBcIkRFU0NcIixcbiAgICAgICAgICB9XG4gICAgICAgIDoge30pLFxuICAgIH0pKSxcbiAgICBudWxsc05vdERpc3RpbmN0OiBpbmRleC5udWxsc05vdERpc3RpbmN0ID8/IGZhbHNlLFxuICAgIC4uLihub3JtYWxpemVkVXNpbmcgPyB7IHVzaW5nOiBub3JtYWxpemVkVXNpbmcgfSA6IHt9KSxcbiAgfTtcbn1cblxuLyoqXG4gKiDthYzsnbTruJQg67OA6rK9IOy8gOydtOyKpCAtIEZvcmVpZ24gS2V5IOuzgOqyvVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUFsdGVyQ29kZV9Gb3JlaWducyhcbiAgdGFibGU6IHN0cmluZyxcbiAgZW50aXR5Rm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgZGJGb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdLFxuICBkcm9wcGluZ0NvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdID0gW10sXG4pOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICAvLyBjb25zb2xlLmxvZyh7IGVudGl0eUZvcmVpZ25zLCBkYkZvcmVpZ25zIH0pO1xuXG4gIGNvbnN0IGdldEtleSA9IChtZjogTWlncmF0aW9uRm9yZWlnbik6IHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIFttZi5jb2x1bW5zLmpvaW4oXCItXCIpLCBtZi50b10uam9pbihcIi8vL1wiKTtcbiAgfTtcblxuICAvLyDsgq3soJzrkKAg7Lus65+866qFIOuqqeuhnVxuICBjb25zdCBkcm9wcGluZ0NvbHVtbk5hbWVzID0gZHJvcHBpbmdDb2x1bW5zLm1hcCgoY29sKSA9PiBjb2wubmFtZSk7XG5cbiAgY29uc3QgZmtUbyA9IGVudGl0eUZvcmVpZ25zLnJlZHVjZShcbiAgICAocmVzdWx0LCBlbnRpdHlGKSA9PiB7XG4gICAgICBjb25zdCBtYXRjaGluZ0RiRiA9IGRiRm9yZWlnbnMuZmluZCgoZGJGKSA9PiBnZXRLZXkoZW50aXR5RikgPT09IGdldEtleShkYkYpKTtcbiAgICAgIGlmICghbWF0Y2hpbmdEYkYpIHtcbiAgICAgICAgcmVzdWx0LmFkZC5wdXNoKGVudGl0eUYpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBpZiAoZXF1YWwoZW50aXR5RiwgbWF0Y2hpbmdEYkYpID09PSBmYWxzZSkge1xuICAgICAgICByZXN1bHQuYWx0ZXJTcmMucHVzaChtYXRjaGluZ0RiRik7XG4gICAgICAgIHJlc3VsdC5hbHRlckRzdC5wdXNoKGVudGl0eUYpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuICAgIHtcbiAgICAgIGFkZDogW10gYXMgTWlncmF0aW9uRm9yZWlnbltdLFxuICAgICAgZHJvcDogW10gYXMgTWlncmF0aW9uRm9yZWlnbltdLFxuICAgICAgYWx0ZXJTcmM6IFtdIGFzIE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgICAgIGFsdGVyRHN0OiBbXSBhcyBNaWdyYXRpb25Gb3JlaWduW10sXG4gICAgfSxcbiAgKTtcblxuICAvLyBkYkZvcmVpZ25z7JeQ64qUIOyeiOyngOunjCBlbnRpdHlGb3JlaWduc+yXkOuKlCDsl4bripQg6rK97JqwICjsgq3soJzrkJwgRkspXG4gIC8vIOuLqCwg7IKt7KCc65CgIOy7rOufvOydmCBGS+uKlCDsoJzsmbggKGdlbmVyYXRlQWx0ZXJDb2RlX0NvbHVtbkFuZEluZGV4ZXPsl5DshJwg7LKY66asKVxuICBkYkZvcmVpZ25zLmZvckVhY2goKGRiRikgPT4ge1xuICAgIGNvbnN0IG1hdGNoaW5nRW50aXR5RiA9IGVudGl0eUZvcmVpZ25zLmZpbmQoKGVudGl0eUYpID0+IGdldEtleShlbnRpdHlGKSA9PT0gZ2V0S2V5KGRiRikpO1xuICAgIGlmICghbWF0Y2hpbmdFbnRpdHlGKSB7XG4gICAgICAvLyDsnbQgRkvsnZgg7Lus65+87J20IOyCreygnOuQoCDsu6zrn7wg66qp66Gd7JeQIOyeiOuKlOyngCDtmZXsnbhcbiAgICAgIGNvbnN0IGlzQ29sdW1uRHJvcHBpbmcgPSBkYkYuY29sdW1ucy5zb21lKChjb2wpID0+IGRyb3BwaW5nQ29sdW1uTmFtZXMuaW5jbHVkZXMoY29sKSk7XG4gICAgICAvLyDsu6zrn7zsnbQg7IKt7KCc65CY7KeAIOyViuuKlCDqsr3smrDsl5Drp4wgRksgZHJvcCDrqqnroZ3sl5Ag7LaU6rCAXG4gICAgICBpZiAoIWlzQ29sdW1uRHJvcHBpbmcpIHtcbiAgICAgICAgZmtUby5kcm9wLnB1c2goZGJGKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGxpbmVzVG8gPSB7XG4gICAgYWRkOiBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZrVG8uYWRkKSxcbiAgICBkcm9wOiBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZrVG8uZHJvcCksXG4gICAgYWx0ZXJTcmM6IGdlbkZvcmVpZ25EZWZpbml0aW9ucyh0YWJsZSwgZmtUby5hbHRlclNyYyksXG4gICAgYWx0ZXJEc3Q6IGdlbkZvcmVpZ25EZWZpbml0aW9ucyh0YWJsZSwgZmtUby5hbHRlckRzdCksXG4gIH07XG5cbiAgLy8gZHJvcCBmayBjb2x1bW5z7J24IOqyveyasCjsg53shLHrkKAg7L2U65OcIOyXhuuKlCDqsr3smrApIO2MqOyKpFxuICBjb25zdCBoYXNMaW5lcyA9IE9iamVjdC52YWx1ZXMobGluZXNUbykuc29tZSgobCkgPT4gbC51cC5sZW5ndGggPiAwIHx8IGwuZG93bi5sZW5ndGggPiAwKTtcbiAgaWYgKCFoYXNMaW5lcykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGlmIChcbiAgICBsaW5lc1RvLmFkZC51cC5sZW5ndGggPT09IDAgJiZcbiAgICBsaW5lc1RvLmRyb3AudXAubGVuZ3RoID09PSAwICYmXG4gICAgbGluZXNUby5hbHRlclNyYy51cC5sZW5ndGggPT09IDAgJiZcbiAgICBsaW5lc1RvLmFsdGVyRHN0LnVwLmxlbmd0aCA9PT0gMFxuICApIHtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2VuZXJhdGVBbHRlckNvZGVfRm9yZWlnbnM6ZmtDaGFuZ2VDb2RlR2VuZXJhdGlvbkVycm9yXCIsIHtcbiAgICAgIHRhYmxlLFxuICAgICAgZW50aXR5Rm9yZWlnbnMsXG4gICAgICBkYkZvcmVpZ25zLFxuICAgIH0pO1xuICAgIHRocm93IG5ldyBFcnJvcihcIkZLIOuzgOqyvSDsvZTrk5wg7IOd7ISxIOyYpOulmFwiKTtcbiAgfVxuXG4gIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtcbiAgICAnaW1wb3J0IHsgS25leCB9IGZyb20gXCJrbmV4XCI7JyxcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwKGtuZXg6IEtuZXgpOiBQcm9taXNlPHZvaWQ+IHtcIixcbiAgICBgcmV0dXJuIGtuZXguc2NoZW1hLmFsdGVyVGFibGUoXCIke3RhYmxlfVwiLCAodGFibGUpID0+IHtgLFxuICAgIC4uLmxpbmVzVG8uZHJvcC5kb3duLFxuICAgIC4uLmxpbmVzVG8uYWRkLnVwLFxuICAgIC4uLmxpbmVzVG8uYWx0ZXJTcmMuZG93bixcbiAgICAuLi5saW5lc1RvLmFsdGVyRHN0LnVwLFxuICAgIFwifSlcIixcbiAgICBcIn1cIixcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd24oa25leDogS25leCk6IFByb21pc2U8dm9pZD4ge1wiLFxuICAgIGByZXR1cm4ga25leC5zY2hlbWEuYWx0ZXJUYWJsZShcIiR7dGFibGV9XCIsICh0YWJsZSkgPT4ge2AsXG4gICAgLi4ubGluZXNUby5hZGQuZG93bixcbiAgICAuLi5saW5lc1RvLmFsdGVyRHN0LmRvd24sXG4gICAgLi4ubGluZXNUby5hbHRlclNyYy51cCxcbiAgICAuLi5saW5lc1RvLmRyb3AudXAsXG4gICAgXCJ9KVwiLFxuICAgIFwifVwiLFxuICBdO1xuXG4gIGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdENvZGUobGluZXMuam9pbihcIlxcblwiKSwgXCJ0eXBlc2NyaXB0XCIsIGBzcmMvbWlncmF0aW9uLyR7dGFibGV9LnRzYCk7XG4gIGNvbnN0IHRpdGxlID0gW1wiYWx0ZXJcIiwgdGFibGUsIFwiZm9yZWlnbnNcIl0uam9pbihcIl9cIik7XG5cbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICB0YWJsZSxcbiAgICAgIHRpdGxlLFxuICAgICAgZm9ybWF0dGVkLFxuICAgICAgdHlwZTogXCJub3JtYWxcIixcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIOyjvOyWtOynhCBFbnRpdHlTZXTsnYQg6riw67CY7Jy866GcIO2FjOydtOu4lCBDUkVBVEUg66eI7J206re466CI7J207IWYIOy9lOuTnOulvCDsg53shLHtlanri4jri6QuXG4gKiBAcGFyYW0gZW50aXR5U2V0XG4gKiBAcmV0dXJucyBDUkVBVEUg66eI7J206re466CI7J207IWYIOy9lOuTnFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVDcmVhdGVDb2RlKGVudGl0eVNldDogTWlncmF0aW9uU2V0KTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgcmV0dXJuIFtcbiAgICBhd2FpdCBnZW5lcmF0ZUNyZWF0ZUNvZGVfQ29sdW1uQW5kSW5kZXhlcyhcbiAgICAgIGVudGl0eVNldC50YWJsZSxcbiAgICAgIGVudGl0eVNldC5jb2x1bW5zLFxuICAgICAgZW50aXR5U2V0LmluZGV4ZXMsXG4gICAgKSxcbiAgICAuLi4oYXdhaXQgZ2VuZXJhdGVDcmVhdGVDb2RlX0ZvcmVpZ24oZW50aXR5U2V0LnRhYmxlLCBlbnRpdHlTZXQuZm9yZWlnbnMpKSxcbiAgXTtcbn1cblxuLyoqXG4gKiDso7zslrTsp4QgZW50aXR5U2V07J2EIOuqqe2RnOuhnCwgZGJTZXTsnYQg7ZiEIOyDge2ZqeycvOuhnCDtlZjsl6wg7YWM7J2067iUIEFMVEVSIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5zrpbwg7IOd7ISx7ZWp64uI64ukLlxuICogQHBhcmFtIGVudGl0eVNldCDtmIQg7IOB7Zmp7J2YIE1pZ3JhdGlvblNldFxuICogQHBhcmFtIGRiU2V0IOuqqe2RnCDsg4HtmansnZggTWlncmF0aW9uU2V0XG4gKiBAcGFyYW0gY29tcGFyZURCIFBLIO2DgOyehSDrs4Dqsr0g7IucIOyXreywuOyhsCBGS+ulvCDsobDtmoztlZjquLAg7JyE7ZWcIEtuZXgg7J247Iqk7YS07IqkICjshKDtg50pXG4gKiBAcmV0dXJucyBBTFRFUiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUFsdGVyQ29kZShcbiAgZW50aXR5U2V0OiBNaWdyYXRpb25TZXQsXG4gIGRiU2V0OiBNaWdyYXRpb25TZXQsXG4gIGNvbXBhcmVEQj86IEtuZXgsXG4pOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICBjb25zdCByZXBsYWNlQ29sdW1uRGVmYXVsdFRvID0gKGNvbDogTWlncmF0aW9uQ29sdW1uKSA9PiB7XG4gICAgLy8gZmxvYXTsnbgg6rK97JqwIOq4sOuzuOqwkuydhCAw7Jy866GcIOyngOygle2VmOuKlCDqsr3smrAgXCIwLjAwXCLsnLzroZwg67OA7ZmY65CY64qUIOy8gOydtOyKpCDrjIDsnZFcbiAgICAvLyBpZiAoY29sLnR5cGUgPT09IFwiZmxvYXRcIiAmJiBjb2wuZGVmYXVsdFRvICYmIFN0cmluZyhjb2wuZGVmYXVsdFRvKS5pbmNsdWRlcygnXCInKSA9PT0gZmFsc2UpIHtcbiAgICAvLyAgIGNvbC5kZWZhdWx0VG8gPSBgXCIke051bWJlcihjb2wuZGVmYXVsdFRvKS50b0ZpeGVkKGNvbC5zY2FsZSA/PyAyKX1cImA7XG4gICAgLy8gfVxuICAgIC8vIC8vIHN0cmluZ+yduCDqsr3smrAg6riw67O46rCS7J20IOu5iCDsiqTtirjrp4Hsnbgg6rK97JqwIOuMgOydkVxuICAgIC8vIGlmIChjb2wudHlwZSA9PT0gXCJzdHJpbmdcIiAmJiBjb2wuZGVmYXVsdFRvID09PSBcIlwiKSB7XG4gICAgLy8gICBjb2wuZGVmYXVsdFRvID0gJ1wiXCInO1xuICAgIC8vIH1cbiAgICAvLyAvLyBib29sZWFu7J24IOqyveyasCDquLDrs7jqsJIg7KCV6rec7ZmUIChNeVNRTOyXkOyEnOuKlCBUSU5ZSU5UKDEp66GcIOyggOyepeuQmOuvgOuhnCAwIOuYkOuKlCAx66GcIOygleq3nO2ZlClcbiAgICAvLyAvLyBUT0RPOiBkYi50c+yXkCB0eXBlQ2FzZSDshKTsoJUg7ZmV7J247ZWY7JesIOyymOumrO2VmOuPhOuhnSDsiJjsoJUg7ZWE7JqUXG4gICAgLy8gaWYgKGNvbC50eXBlID09PSBcImJvb2xlYW5cIiAmJiBjb2wuZGVmYXVsdFRvICE9PSB1bmRlZmluZWQpIHtcbiAgICAvLyAgIGlmIChjb2wuZGVmYXVsdFRvID09PSBcIjBcIiB8fCBjb2wuZGVmYXVsdFRvLnRvTG93ZXJDYXNlKCkgPT09IFwiZmFsc2VcIikge1xuICAgIC8vICAgICBjb2wuZGVmYXVsdFRvID0gXCIwXCI7XG4gICAgLy8gICB9IGVsc2UgaWYgKGNvbC5kZWZhdWx0VG8gPT09IFwiMVwiIHx8IGNvbC5kZWZhdWx0VG8udG9Mb3dlckNhc2UoKSA9PT0gXCJ0cnVlXCIpIHtcbiAgICAvLyAgICAgY29sLmRlZmF1bHRUbyA9IFwiMVwiO1xuICAgIC8vICAgfVxuICAgIC8vIH1cblxuICAgIC8vIEZJWE1FOiDsnbzri6ggTXlTUUwg7IOB7Zmp7JeQ7IScIOuwnOyDne2WiOuNmCDsnbTsiojsnZggd29ya2Fyb3VuZCDsnbTrr4DroZwgUGfsl5DshJwg7J6s7ZmV7J24IO2bhCDrjIDsnZEg7LaU6rCAXG4gICAgcmV0dXJuIGNvbDtcbiAgfTtcbiAgY29uc3QgZW50aXR5Q29sdW1ucyA9IGFscGhhYmV0aWNhbChlbnRpdHlTZXQuY29sdW1ucywgKGEpID0+IGEubmFtZSkubWFwKHJlcGxhY2VDb2x1bW5EZWZhdWx0VG8pO1xuICBjb25zdCBkYkNvbHVtbnMgPSBhbHBoYWJldGljYWwoZGJTZXQuY29sdW1ucywgKGEpID0+IGEubmFtZSkubWFwKHJlcGxhY2VDb2x1bW5EZWZhdWx0VG8pO1xuXG4gIC8qIOuUlOuyhOq5heyaqSDsvZTrk5wsIO2KueyglSDsu6zrn7zsl5DshJwg67aI7J287LmYIOuwnOyDne2VoCDrlYwg7ZmV7J24XG4gICAgICAgIGNvbnN0IGVudGl0eUNvbHVtbiA9IGVudGl0eVNldC5jb2x1bW5zLmZpbmQoXG4gICAgICAgICAgKGNvbCkgPT4gY29sLm5hbWUgPT09IFwicHJpY2Vfa3J3XCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZGJDb2x1bW4gPSBkYlNldC5jb2x1bW5zLmZpbmQoXG4gICAgICAgICAgKGNvbCkgPT4gY29sLm5hbWUgPT09IFwicHJpY2Vfa3J3XCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5kZWJ1Zyh7IGVudGl0eUNvbHVtbiwgZGJDb2x1bW4gfSk7XG4gICAgICAgICAqL1xuXG4gIGNvbnN0IGVudGl0eUluZGV4ZXMgPSBhbHBoYWJldGljYWwoZW50aXR5U2V0LmluZGV4ZXMsIChhKSA9PlxuICAgIFthLnR5cGUsIC4uLmEuY29sdW1ucy5tYXAoKGMpID0+IGMubmFtZSldLmpvaW4oXCItXCIpLFxuICApO1xuICBjb25zdCBkYkluZGV4ZXMgPSBhbHBoYWJldGljYWwoZGJTZXQuaW5kZXhlcywgKGEpID0+XG4gICAgW2EudHlwZSwgLi4uYS5jb2x1bW5zLm1hcCgoYykgPT4gYy5uYW1lKV0uam9pbihcIi1cIiksXG4gICk7XG5cbiAgY29uc3QgcmVwbGFjZU5vQWN0aW9uT25NeVNRTCA9IChmOiBNaWdyYXRpb25Gb3JlaWduKSA9PiB7XG4gICAgLy8gTXlTUUzsl5DshJwgUkVTVFJJQ1TsmYAgTk8gQUNUSU9O7J2AIOuPmeydvO2VqFxuICAgIGNvbnN0IHsgb25EZWxldGUsIG9uVXBkYXRlIH0gPSBmO1xuICAgIHJldHVybiB7XG4gICAgICAuLi5mLFxuICAgICAgb25VcGRhdGU6IG9uVXBkYXRlID09PSBcIlJFU1RSSUNUXCIgPyBcIk5PIEFDVElPTlwiIDogb25VcGRhdGUsXG4gICAgICBvbkRlbGV0ZTogb25EZWxldGUgPT09IFwiUkVTVFJJQ1RcIiA/IFwiTk8gQUNUSU9OXCIgOiBvbkRlbGV0ZSxcbiAgICB9O1xuICB9O1xuXG4gIGNvbnN0IGVudGl0eUZvcmVpZ25zID0gYWxwaGFiZXRpY2FsKGVudGl0eVNldC5mb3JlaWducywgKGEpID0+XG4gICAgW2EudG8sIC4uLmEuY29sdW1uc10uam9pbihcIi1cIiksXG4gICkubWFwKChmKSA9PiByZXBsYWNlTm9BY3Rpb25Pbk15U1FMKGYpKTtcbiAgY29uc3QgZGJGb3JlaWducyA9IGFscGhhYmV0aWNhbChkYlNldC5mb3JlaWducywgKGEpID0+IFthLnRvLCAuLi5hLmNvbHVtbnNdLmpvaW4oXCItXCIpKS5tYXAoKGYpID0+XG4gICAgcmVwbGFjZU5vQWN0aW9uT25NeVNRTChmKSxcbiAgKTtcblxuICAvLyDsgq3soJzrkKAg7Lus65+8IOuqqeuhnSDqs4TsgrBcbiAgY29uc3QgZHJvcHBpbmdDb2x1bW5zID0gZGlmZihkYkNvbHVtbnMsIGVudGl0eUNvbHVtbnMsIChjb2wpID0+IGNvbC5uYW1lKTtcblxuICBjb25zdCBhbHRlckNvZGVzOiAoR2VuTWlncmF0aW9uQ29kZSB8IEdlbk1pZ3JhdGlvbkNvZGVbXSB8IG51bGwpW10gPSBbXTtcblxuICAvLyAxLiBjb2x1bW5zQW5kSW5kZXhlcyDsspjrpqxcbiAgY29uc3Qgc2VhcmNoVGV4dENvbHVtbk5hbWVzID0gZ2V0U2VhcmNoVGV4dENvbHVtbk5hbWVzKGVudGl0eVNldC50YWJsZSk7XG4gIGNvbnN0IGlzRXF1YWxDb2x1bW5zID0gZXF1YWwoXG4gICAgZW50aXR5Q29sdW1ucy5tYXAoKGNvbHVtbikgPT4gbm9ybWFsaXplQ29sdW1uRm9yQ29tcGFyaXNvbihjb2x1bW4sIHNlYXJjaFRleHRDb2x1bW5OYW1lcykpLFxuICAgIGRiQ29sdW1ucy5tYXAoKGNvbHVtbikgPT4gbm9ybWFsaXplQ29sdW1uRm9yQ29tcGFyaXNvbihjb2x1bW4sIHNlYXJjaFRleHRDb2x1bW5OYW1lcykpLFxuICApO1xuICBjb25zdCBpc0VxdWFsSW5kZXhlcyA9IGVxdWFsKFxuICAgIGVudGl0eUluZGV4ZXMubWFwKHNldE1pZ3JhdGlvbkluZGV4RGVmYXVsdHMpLFxuICAgIGRiSW5kZXhlcy5tYXAoc2V0TWlncmF0aW9uSW5kZXhEZWZhdWx0cyksXG4gICk7XG4gIGlmICghaXNFcXVhbENvbHVtbnMgfHwgIWlzRXF1YWxJbmRleGVzKSB7XG4gICAgYWx0ZXJDb2Rlcy5wdXNoKFxuICAgICAgYXdhaXQgZ2VuZXJhdGVBbHRlckNvZGVfQ29sdW1uQW5kSW5kZXhlcyhcbiAgICAgICAgZW50aXR5U2V0LnRhYmxlLFxuICAgICAgICBlbnRpdHlDb2x1bW5zLFxuICAgICAgICBlbnRpdHlJbmRleGVzLFxuICAgICAgICBkYkNvbHVtbnMsXG4gICAgICAgIGRiSW5kZXhlcyxcbiAgICAgICAgZGJTZXQuZm9yZWlnbnMsXG4gICAgICAgIGNvbXBhcmVEQixcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIC8vIDIuIGZvcmVpZ25zIOyymOumrCAo7IKt7KCc65CgIOy7rOufvCDsoJXrs7Qg7KCE64usKVxuICBpZiAoZXF1YWwoZW50aXR5Rm9yZWlnbnMsIGRiRm9yZWlnbnMpID09PSBmYWxzZSkge1xuICAgIGFsdGVyQ29kZXMucHVzaChcbiAgICAgIGF3YWl0IGdlbmVyYXRlQWx0ZXJDb2RlX0ZvcmVpZ25zKFxuICAgICAgICBlbnRpdHlTZXQudGFibGUsXG4gICAgICAgIGVudGl0eUZvcmVpZ25zLFxuICAgICAgICBkYkZvcmVpZ25zLFxuICAgICAgICBkcm9wcGluZ0NvbHVtbnMsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBpZiAoYWx0ZXJDb2Rlcy5ldmVyeSgoYWx0ZXJDb2RlKSA9PiBhbHRlckNvZGUgPT09IG51bGwpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIGFsdGVyQ29kZXMuZmlsdGVyKChhbHRlckNvZGUpID0+IGFsdGVyQ29kZSAhPT0gbnVsbCkuZmxhdCgpO1xufVxuXG4vKipcbiAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOyXreywuOyhsCBGSyDsoJzslb3sobDqsbTsnYQg7LKY66as7ZWY64qUIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5zrpbwg7IOd7ISx7ZWp64uI64ukLlxuICpcbiAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOyInOyEnDpcbiAqIDEuIEZLIOygnOyVveyhsOqxtCDsgq3soJwgKOyXreywuOyhsCDthYzsnbTruJTrk6QpXG4gKiAyLiDsnpDquLAg7LC47KGwIEZLIOyCreygnCAo7J6I64qUIOqyveyasClcbiAqIDMuIFBLIOygnOyVveyhsOqxtCDsgq3soJxcbiAqIDQuIFBLIOy7rOufvCDtg4DsnoUg67OA6rK9XG4gKiA1LiBGSyDsu6zrn7wg7YOA7J6FIOuzgOqyvSAo7Jet7LC47KGwIO2FjOydtOu4lOuTpClcbiAqIDYuIFBLIOygnOyVveyhsOqxtCDrs7XqtaxcbiAqIDcuIOyekOq4sCDssLjsobAgRksg67O16rWsXG4gKiA4LiBGSyDsoJzslb3sobDqsbQg67O16rWsXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlUGtUeXBlQ2hhbmdlTWlncmF0aW9uKFxuICB0YWJsZTogc3RyaW5nLFxuICBlbnRpdHlJZENvbDogTWlncmF0aW9uQ29sdW1uLFxuICBkYklkQ29sOiBNaWdyYXRpb25Db2x1bW4sXG4gIF9lbnRpdHlDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgX2VudGl0eUluZGV4ZXM6IE1pZ3JhdGlvbkluZGV4W10sXG4gIF9kYkNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdLFxuICBfZGJJbmRleGVzOiBNaWdyYXRpb25JbmRleFtdLFxuICBfZGJGb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdLFxuICBjb21wYXJlREI6IEtuZXgsXG4pOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICAvLyDsl63ssLjsobAgRksg7KGw7ZqMICjsnbQg7YWM7J2067iU7J2YIFBL66W8IOywuOyhsO2VmOuKlCDri6Trpbgg7YWM7J2067iU7J2YIEZL65OkKVxuICBjb25zdCByZWZlcmVuY2luZ0ZLcyA9IGF3YWl0IFBvc3RncmVTUUxTY2hlbWFSZWFkZXIuZ2V0UmVmZXJlbmNpbmdGb3JlaWduS2V5cyhjb21wYXJlREIsIHRhYmxlKTtcblxuICAvLyDsnpDquLAg7LC47KGwIEZLIOu2hOumrCAo7JiIOiBEZXBhcnRtZW50LnBhcmVudF9pZCDihpIgRGVwYXJ0bWVudC5pZClcbiAgY29uc3Qgc2VsZlJlZmVyZW5jaW5nRktzID0gcmVmZXJlbmNpbmdGS3MuZmlsdGVyKChmaykgPT4gZmsudGFibGVOYW1lID09PSB0YWJsZSk7XG4gIGNvbnN0IGV4dGVybmFsUmVmZXJlbmNpbmdGS3MgPSByZWZlcmVuY2luZ0ZLcy5maWx0ZXIoKGZrKSA9PiBmay50YWJsZU5hbWUgIT09IHRhYmxlKTtcblxuICAvLyBQSyDsoJzslb3sobDqsbQg7J2066aEIOyhsO2ajFxuICBjb25zdCBwa0NvbnN0cmFpbnROYW1lID0gYCR7dGFibGV9X3BrZXlgO1xuXG4gIC8vIOyDiCBQSyDtg4DsnoXsl5Ag66ee64qUIFBvc3RncmVTUUwg7YOA7J6FIOusuOyekOyXtFxuICBjb25zdCBuZXdQa1BnVHlwZSA9IGdldFBrUGdUeXBlKGVudGl0eUlkQ29sKTtcbiAgY29uc3Qgb2xkUGtQZ1R5cGUgPSBnZXRQa1BnVHlwZShkYklkQ29sKTtcblxuICAvLyBVUCDsvZTrk5wg7IOd7ISxXG4gIGNvbnN0IHVwTGluZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gMS4g7Jm467aAIO2FjOydtOu4lOydmCBGSyDsoJzslb3sobDqsbQg7IKt7KCcXG4gIGZvciAoY29uc3QgZmsgb2YgZXh0ZXJuYWxSZWZlcmVuY2luZ0ZLcykge1xuICAgIHVwTGluZXMucHVzaChgICAvLyAke2ZrLnRhYmxlTmFtZX0uJHtmay5jb2x1bW5OYW1lfSBGSyDsoJzslb3sobDqsbQg7IKt7KCcYCk7XG4gICAgdXBMaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHtmay50YWJsZU5hbWV9XCIgRFJPUCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIicpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDIuIOyekOq4sCDssLjsobAgRksg7IKt7KCcXG4gIGZvciAoY29uc3QgZmsgb2Ygc2VsZlJlZmVyZW5jaW5nRktzKSB7XG4gICAgdXBMaW5lcy5wdXNoKGAgIC8vIOyekOq4sCDssLjsobAgRksg7IKt7KCcOiAke2ZrLmNvbHVtbk5hbWV9YCk7XG4gICAgdXBMaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHt0YWJsZX1cIiBEUk9QIENPTlNUUkFJTlQgXCIke2ZrLmNvbnN0cmFpbnROYW1lfVwiJyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gMy4gUEsg7KCc7JW97KGw6rG0IOyCreygnFxuICB1cExpbmVzLnB1c2goYCAgLy8gUEsg7KCc7JW97KGw6rG0IOyCreygnGApO1xuICB1cExpbmVzLnB1c2goYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHt0YWJsZX1cIiBEUk9QIENPTlNUUkFJTlQgXCIke3BrQ29uc3RyYWludE5hbWV9XCInKTtgKTtcblxuICAvLyA0LiBQSyDsu6zrn7wg7YOA7J6FIOuzgOqyvVxuICB1cExpbmVzLnB1c2goYCAgLy8gUEsg7Lus65+8IO2DgOyehSDrs4Dqsr1gKTtcbiAgdXBMaW5lcy5wdXNoKFxuICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgQUxURVIgQ09MVU1OIFwiaWRcIiBUWVBFICR7bmV3UGtQZ1R5cGV9IFVTSU5HIFwiaWRcIjo6JHtuZXdQa1BnVHlwZX0nKTtgLFxuICApO1xuXG4gIC8vIDUuIEZLIOy7rOufvCDtg4DsnoUg67OA6rK9ICjsl63ssLjsobAg7YWM7J2067iU65OkKSAtIOyekOq4sCDssLjsobAg7Y+s7ZWoXG4gIGZvciAoY29uc3QgZmsgb2YgcmVmZXJlbmNpbmdGS3MpIHtcbiAgICB1cExpbmVzLnB1c2goYCAgLy8gJHtmay50YWJsZU5hbWV9LiR7ZmsuY29sdW1uTmFtZX0g7Lus65+8IO2DgOyehSDrs4Dqsr1gKTtcbiAgICB1cExpbmVzLnB1c2goXG4gICAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke2ZrLnRhYmxlTmFtZX1cIiBBTFRFUiBDT0xVTU4gXCIke2ZrLmNvbHVtbk5hbWV9XCIgVFlQRSAke25ld1BrUGdUeXBlfSBVU0lORyBcIiR7ZmsuY29sdW1uTmFtZX1cIjo6JHtuZXdQa1BnVHlwZX0nKTtgLFxuICAgICk7XG4gIH1cblxuICAvLyA2LiBQSyDsoJzslb3sobDqsbQg67O16rWsXG4gIHVwTGluZXMucHVzaChgICAvLyBQSyDsoJzslb3sobDqsbQg67O16rWsYCk7XG4gIHVwTGluZXMucHVzaChcbiAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT05TVFJBSU5UIFwiJHtwa0NvbnN0cmFpbnROYW1lfVwiIFBSSU1BUlkgS0VZIChcImlkXCIpJyk7YCxcbiAgKTtcblxuICAvLyA3LiDsnpDquLAg7LC47KGwIEZLIOuzteq1rFxuICBmb3IgKGNvbnN0IGZrIG9mIHNlbGZSZWZlcmVuY2luZ0ZLcykge1xuICAgIHVwTGluZXMucHVzaChgICAvLyDsnpDquLAg7LC47KGwIEZLIOuzteq1rDogJHtmay5jb2x1bW5OYW1lfWApO1xuICAgIHVwTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgQUREIENPTlNUUkFJTlQgXCIke2ZrLmNvbnN0cmFpbnROYW1lfVwiIEZPUkVJR04gS0VZIChcIiR7ZmsuY29sdW1uTmFtZX1cIikgUkVGRVJFTkNFUyBcIiR7dGFibGV9XCIoXCJpZFwiKSBPTiBVUERBVEUgJHtmay5vblVwZGF0ZX0gT04gREVMRVRFICR7Zmsub25EZWxldGV9Jyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gOC4g7Jm467aAIO2FjOydtOu4lOydmCBGSyDsoJzslb3sobDqsbQg67O16rWsXG4gIGZvciAoY29uc3QgZmsgb2YgZXh0ZXJuYWxSZWZlcmVuY2luZ0ZLcykge1xuICAgIHVwTGluZXMucHVzaChgICAvLyAke2ZrLnRhYmxlTmFtZX0uJHtmay5jb2x1bW5OYW1lfSBGSyDsoJzslb3sobDqsbQg67O16rWsYCk7XG4gICAgdXBMaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHtmay50YWJsZU5hbWV9XCIgQUREIENPTlNUUkFJTlQgXCIke2ZrLmNvbnN0cmFpbnROYW1lfVwiIEZPUkVJR04gS0VZIChcIiR7ZmsuY29sdW1uTmFtZX1cIikgUkVGRVJFTkNFUyBcIiR7dGFibGV9XCIoXCJpZFwiKSBPTiBVUERBVEUgJHtmay5vblVwZGF0ZX0gT04gREVMRVRFICR7Zmsub25EZWxldGV9Jyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gRE9XTiDsvZTrk5wg7IOd7ISxICjsl63siJwpXG4gIGNvbnN0IGRvd25MaW5lczogc3RyaW5nW10gPSBbXTtcblxuICAvLyAxLiDsmbjrtoAg7YWM7J2067iU7J2YIEZLIOygnOyVveyhsOqxtCDsgq3soJxcbiAgZm9yIChjb25zdCBmayBvZiBleHRlcm5hbFJlZmVyZW5jaW5nRktzKSB7XG4gICAgZG93bkxpbmVzLnB1c2goYCAgLy8gJHtmay50YWJsZU5hbWV9LiR7ZmsuY29sdW1uTmFtZX0gRksg7KCc7JW97KGw6rG0IOyCreygnGApO1xuICAgIGRvd25MaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHtmay50YWJsZU5hbWV9XCIgRFJPUCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIicpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDIuIOyekOq4sCDssLjsobAgRksg7IKt7KCcXG4gIGZvciAoY29uc3QgZmsgb2Ygc2VsZlJlZmVyZW5jaW5nRktzKSB7XG4gICAgZG93bkxpbmVzLnB1c2goYCAgLy8g7J6Q6riwIOywuOyhsCBGSyDsgq3soJw6ICR7ZmsuY29sdW1uTmFtZX1gKTtcbiAgICBkb3duTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgRFJPUCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIicpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDMuIFBLIOygnOyVveyhsOqxtCDsgq3soJxcbiAgZG93bkxpbmVzLnB1c2goYCAgLy8gUEsg7KCc7JW97KGw6rG0IOyCreygnGApO1xuICBkb3duTGluZXMucHVzaChcbiAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIERST1AgQ09OU1RSQUlOVCBcIiR7cGtDb25zdHJhaW50TmFtZX1cIicpO2AsXG4gICk7XG5cbiAgLy8gNC4gUEsg7Lus65+8IO2DgOyehSDsm5Drs7VcbiAgZG93bkxpbmVzLnB1c2goYCAgLy8gUEsg7Lus65+8IO2DgOyehSDsm5Drs7VgKTtcbiAgZG93bkxpbmVzLnB1c2goXG4gICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHt0YWJsZX1cIiBBTFRFUiBDT0xVTU4gXCJpZFwiIFRZUEUgJHtvbGRQa1BnVHlwZX0gVVNJTkcgXCJpZFwiOjoke29sZFBrUGdUeXBlfScpO2AsXG4gICk7XG5cbiAgLy8gNS4gRksg7Lus65+8IO2DgOyehSDsm5Drs7UgKOyXreywuOyhsCDthYzsnbTruJTrk6QpXG4gIGZvciAoY29uc3QgZmsgb2YgcmVmZXJlbmNpbmdGS3MpIHtcbiAgICBkb3duTGluZXMucHVzaChgICAvLyAke2ZrLnRhYmxlTmFtZX0uJHtmay5jb2x1bW5OYW1lfSDsu6zrn7wg7YOA7J6FIOybkOuztWApO1xuICAgIGRvd25MaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHtmay50YWJsZU5hbWV9XCIgQUxURVIgQ09MVU1OIFwiJHtmay5jb2x1bW5OYW1lfVwiIFRZUEUgJHtvbGRQa1BnVHlwZX0gVVNJTkcgXCIke2ZrLmNvbHVtbk5hbWV9XCI6OiR7b2xkUGtQZ1R5cGV9Jyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gNi4gUEsg7KCc7JW97KGw6rG0IOuzteq1rFxuICBkb3duTGluZXMucHVzaChgICAvLyBQSyDsoJzslb3sobDqsbQg67O16rWsYCk7XG4gIGRvd25MaW5lcy5wdXNoKFxuICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgQUREIENPTlNUUkFJTlQgXCIke3BrQ29uc3RyYWludE5hbWV9XCIgUFJJTUFSWSBLRVkgKFwiaWRcIiknKTtgLFxuICApO1xuXG4gIC8vIDcuIOyekOq4sCDssLjsobAgRksg67O16rWsXG4gIGZvciAoY29uc3QgZmsgb2Ygc2VsZlJlZmVyZW5jaW5nRktzKSB7XG4gICAgZG93bkxpbmVzLnB1c2goYCAgLy8g7J6Q6riwIOywuOyhsCBGSyDrs7Xqtaw6ICR7ZmsuY29sdW1uTmFtZX1gKTtcbiAgICBkb3duTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgQUREIENPTlNUUkFJTlQgXCIke2ZrLmNvbnN0cmFpbnROYW1lfVwiIEZPUkVJR04gS0VZIChcIiR7ZmsuY29sdW1uTmFtZX1cIikgUkVGRVJFTkNFUyBcIiR7dGFibGV9XCIoXCJpZFwiKSBPTiBVUERBVEUgJHtmay5vblVwZGF0ZX0gT04gREVMRVRFICR7Zmsub25EZWxldGV9Jyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gOC4g7Jm467aAIO2FjOydtOu4lOydmCBGSyDsoJzslb3sobDqsbQg67O16rWsXG4gIGZvciAoY29uc3QgZmsgb2YgZXh0ZXJuYWxSZWZlcmVuY2luZ0ZLcykge1xuICAgIGRvd25MaW5lcy5wdXNoKGAgIC8vICR7ZmsudGFibGVOYW1lfS4ke2ZrLmNvbHVtbk5hbWV9IEZLIOygnOyVveyhsOqxtCDrs7XqtaxgKTtcbiAgICBkb3duTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7ZmsudGFibGVOYW1lfVwiIEFERCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIiBGT1JFSUdOIEtFWSAoXCIke2ZrLmNvbHVtbk5hbWV9XCIpIFJFRkVSRU5DRVMgXCIke3RhYmxlfVwiKFwiaWRcIikgT04gVVBEQVRFICR7Zmsub25VcGRhdGV9IE9OIERFTEVURSAke2ZrLm9uRGVsZXRlfScpO2AsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtcbiAgICAnaW1wb3J0IHsgS25leCB9IGZyb20gXCJrbmV4XCI7JyxcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwKGtuZXg6IEtuZXgpOiBQcm9taXNlPHZvaWQ+IHtcIixcbiAgICAuLi51cExpbmVzLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4uZG93bkxpbmVzLFxuICAgIFwifVwiLFxuICBdO1xuXG4gIGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdENvZGUobGluZXMuam9pbihcIlxcblwiKSwgXCJ0eXBlc2NyaXB0XCIsIGBzcmMvbWlncmF0aW9uLyR7dGFibGV9LnRzYCk7XG5cbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICB0YWJsZSxcbiAgICAgIHRpdGxlOiBgYWx0ZXJfJHt0YWJsZX1fcGtfdHlwZWAsXG4gICAgICBmb3JtYXR0ZWQsXG4gICAgICB0eXBlOiBcIm5vcm1hbFwiLFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICogUEsg7Lus65+87J2YIFBvc3RncmVTUUwg7YOA7J6FIOusuOyekOyXtOydhCDrsJjtmZjtlanri4jri6QuXG4gKi9cbmZ1bmN0aW9uIGdldFBrUGdUeXBlKGNvbDogTWlncmF0aW9uQ29sdW1uKTogc3RyaW5nIHtcbiAgaWYgKGNvbC50eXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIGNvbC5sZW5ndGggIT09IHVuZGVmaW5lZCA/IGB2YXJjaGFyKCR7Y29sLmxlbmd0aH0pYCA6IFwidGV4dFwiO1xuICB9XG4gIGlmIChjb2wudHlwZSA9PT0gXCJ1dWlkXCIpIHtcbiAgICByZXR1cm4gXCJ1dWlkXCI7XG4gIH1cbiAgLy8gaW50ZWdlcuydmCDqsr3smrAgc2VyaWFsL2ludGVnZXIg6rWs67aE7J20IO2VhOyalO2VmOyngOunjCxcbiAgLy8g7YOA7J6FIOuzgOqyvSDsi5zsl5DripQgaW50ZWdlcuuhnCDsspjrpqztlanri4jri6QuXG4gIHJldHVybiBcImludGVnZXJcIjtcbn1cbiJdLCJuYW1lcyI6WyJlcXVhbCIsImFscGhhYmV0aWNhbCIsImRpZmYiLCJFbnRpdHlNYW5hZ2VyIiwiTmFpdGUiLCJpc1NlYXJjaFRleHRQcm9wIiwiZm9ybWF0Q29kZSIsImRpZmZlcmVuY2VXaXRoIiwiaW50ZXJzZWN0aW9uQnkiLCJQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyIiwiU0VBUkNIX1RFWFRfSEVMUEVSX0RFRklOSVRJT05TIiwiU2VhcmNoVGV4dEV4cHJlc3Npb25QYXJzZXIiLCJpbmRleCIsInRva2VucyIsImlzQXRFbmQiLCJsZW5ndGgiLCJwYXJzZUV4cHJlc3Npb24iLCJwYXJzZUNvbmNhdCIsInBhcnRzIiwicGFyc2VQb3N0Zml4IiwibWF0Y2hPcGVyYXRvciIsInB1c2giLCJ0eXBlIiwibm9kZSIsInBhcnNlUHJpbWFyeSIsImV4cHIiLCJ0YXJnZXRUeXBlIiwicGFyc2VUeXBlTmFtZSIsIm1hdGNoSWRlbnRpZmllciIsInRva2VuIiwiY29uc3VtZUNvbGxhdGlvblRva2VuIiwiY29sbGF0aW9uIiwidmFsdWUiLCJxdW90ZWQiLCJjb25zdW1lVG9rZW4iLCJleHBlY3RTeW1ib2wiLCJsb3dlck5hbWUiLCJ0b0xvd2VyQ2FzZSIsIm1hdGNoU3ltYm9sIiwiaXNUcmltQm90aEZyb21Gb3JtIiwiYXJnIiwibmFtZSIsImFyZ3MiLCJwYXJzZUZ1bmN0aW9uQXJncyIsIkVycm9yIiwicGVlayIsImpvaW4iLCJib3RoVG9rZW4iLCJmcm9tVG9rZW4iLCJjb250ZXh0Iiwib2Zmc2V0IiwiZ2V0SW5kZXhDb2x1bW5PcGNsYXNzIiwiY29sdW1uIiwib3BjbGFzcyIsInZlY3Rvck9wcyIsInRva2VuaXplU2VhcmNoVGV4dEV4cHJlc3Npb24iLCJleHByZXNzaW9uIiwiY2hhciIsInVuZGVmaW5lZCIsInRlc3QiLCJzdGFydHNXaXRoIiwiY3VycmVudCIsImNhbm9uaWNhbGl6ZVNlYXJjaFRleHRHZW5lcmF0ZWRFeHByZXNzaW9uIiwicGFyc2VyIiwicGFyc2VkRXhwcmVzc2lvbiIsInJlbmRlclNlYXJjaFRleHRFeHByZXNzaW9uIiwibm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlIiwibm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25GYWxsYmFjayIsImZsYXRNYXAiLCJwYXJ0Iiwibm9ybWFsaXplZFBhcnQiLCJ0b1VwcGVyQ2FzZSIsIm5vcm1hbGl6ZWRFeHByIiwicmVwbGFjZSIsInRyaW0iLCJtYXAiLCJwYXJlbnRQcmVjZWRlbmNlIiwicHJlY2VkZW5jZSIsImdldFNlYXJjaFRleHRFeHByZXNzaW9uUHJlY2VkZW5jZSIsInJlbmRlcmVkIiwicmVwbGFjZUFsbCIsInZpc2l0U2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlIiwidmlzaXRvciIsImZvckVhY2giLCJnZXRTZWFyY2hUZXh0SGVscGVyS2luZHNGcm9tRXhwcmVzc2lvbiIsImhlbHBlcktpbmRzIiwiU2V0IiwiYWRkSGVscGVyS2luZEZyb21OYW1lIiwibm9ybWFsaXplZE5hbWUiLCJhZGQiLCJyZXNvbHZlU2VhcmNoVGV4dENvbHVtbnMiLCJ0YWJsZSIsImNvbHVtbnMiLCJlbnRpdHkiLCJnZXRCeVRhYmxlIiwicHJvcHNCeU5hbWUiLCJNYXAiLCJwcm9wcyIsInByb3AiLCJnZXQiLCJnZW5lcmF0ZWQiLCJidWlsZFNlYXJjaFRleHRHZW5lcmF0ZWRFeHByZXNzaW9uIiwic291cmNlQ29sdW1ucyIsInNvdXJjZSIsInNvdXJjZVByb3AiLCJjYXNlSW5zZW5zaXRpdmUiLCJnZXRTZWFyY2hUZXh0SGVscGVyRGVmaW5pdGlvbnMiLCJraW5kIiwic2l6ZSIsImZpbHRlciIsImhhcyIsImdldFNlYXJjaFRleHRDb2x1bW5OYW1lcyIsImdlbmVyYXRlQ3JlYXRlQ29kZV9Db2x1bW5BbmRJbmRleGVzIiwiaW5kZXhlcyIsInJlc29sdmVkQ29sdW1ucyIsImNvbHVtbkRlZnMiLCJnZW5Db2x1bW5EZWZpbml0aW9ucyIsImhlbHBlckRlZmluaXRpb25zIiwibGluZXMiLCJidWlsZGVyIiwicmF3IiwiZ2VuSW5kZXhEZWZpbml0aW9uIiwidGl0bGUiLCJmb3JtYXR0ZWQiLCJyZXN1bHQiLCJnZW5HZW5lcmF0ZWRDb2x1bW5EZWZpbml0aW9uIiwiZ2VuTm9ybWFsQ29sdW1uRGVmaW5pdGlvbiIsInBnVHlwZSIsImdldFBnVHlwZUZvckNvbHVtbiIsInN0b3JhZ2VUeXBlIiwibnVsbGFibGVDbGF1c2UiLCJudWxsYWJsZSIsImNoYWlucyIsImVuZHNXaXRoIiwiZWxlbWVudFR5cGUiLCJzbGljZSIsImdldFBnQXJyYXlUeXBlIiwiZGltZW5zaW9ucyIsIm51bWJlclR5cGUiLCJwcmVjaXNpb24iLCJzY2FsZSIsImV4dHJhVHlwZSIsImRlZmF1bHRUbyIsImdlblZlY3RvckluZGV4RGVmaW5pdGlvbiIsInVzaW5nIiwiZ2VuUGdyb29uZ2FJbmRleERlZmluaXRpb24iLCJtZXRob2RNYXAiLCJ1bmlxdWUiLCJudWxsc05vdERpc3RpbmN0Q2xhdXNlIiwibnVsbHNOb3REaXN0aW5jdCIsInVzaW5nQ2xhdXNlIiwiY29sIiwib3BjbGFzc0NsYXVzZSIsInNvcnRPcmRlckNsYXVzZSIsInNvcnRPcmRlciIsIm51bGxzRmlyc3RDbGF1c2UiLCJudWxsc0ZpcnN0IiwiY29sdW1uQ2xhdXNlIiwicHJvcHNEaWN0Iiwib3B0aW9uIiwiZ2V0UGdyb29uZ2FDb2x1bW5PcHRpb24iLCJtIiwiZWZDb25zdHJ1Y3Rpb24iLCJsaXN0cyIsImdlbmVyYXRlQ3JlYXRlQ29kZV9Gb3JlaWduIiwiZm9yZWlnbnMiLCJ1cCIsImRvd24iLCJnZW5Gb3JlaWduRGVmaW5pdGlvbnMiLCJmb3JlaWduS2V5c1N0cmluZyIsImZvcmVpZ24iLCJyZWR1Y2UiLCJyIiwiY29sdW1uc1N0cmluZ1F1b3RlIiwidG8iLCJvblVwZGF0ZSIsIm9uRGVsZXRlIiwiZ2VuZXJhdGVBbHRlckNvZGVfQ29sdW1uQW5kSW5kZXhlcyIsImVudGl0eUNvbHVtbnMiLCJlbnRpdHlJbmRleGVzIiwiZGJDb2x1bW5zIiwiZGJJbmRleGVzIiwiZGJGb3JlaWducyIsImNvbXBhcmVEQiIsInJlc29sdmVkRW50aXR5Q29sdW1ucyIsInNlYXJjaFRleHRDb2x1bW5OYW1lcyIsImVudGl0eUlkQ29sIiwiZmluZCIsImRiSWRDb2wiLCJpc1BrVHlwZUNoYW5nZWQiLCJnZW5lcmF0ZVBrVHlwZUNoYW5nZU1pZ3JhdGlvbiIsImFsdGVyQ29sdW1uc1RvIiwiZ2V0QWx0ZXJDb2x1bW5zVG8iLCJhbHRlckNvbHVtbkxpbmVzVG8iLCJnZXRBbHRlckNvbHVtbkxpbmVzVG8iLCJhbHRlckluZGV4ZXNUbyIsImdldEFsdGVySW5kZXhlc1RvIiwicmVjcmVhdGVkU2VhcmNoVGV4dENvbHVtbk5hbWVzIiwiYWx0ZXIiLCJkYkNvbHVtbiIsImVudGl0eUNvbHVtbiIsInJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMiLCJzb21lIiwiZHJvcCIsImRyb3BJbmRleCIsInJlY3JlYXRlZFNlYXJjaFRleHRFbnRpdHlJbmRleGVzIiwiYWRkSW5kZXgiLCJpbXBsaWNpdGx5RHJvcHBlZERiSW5kZXhlcyIsImV2ZXJ5IiwiaW5kZXhOZWVkc1RvRHJvcCIsImRyb3BwZWRJbmRleCIsImhhc1VwQ2hhbmdlcyIsInQiLCJ1cEJ1aWxkZXJMaW5lcyIsImdlbkluZGV4RHJvcERlZmluaXRpb24iLCJ1cFJhd0xpbmVzIiwiZG93bkJ1aWxkZXJMaW5lcyIsImluZGV4Q29sIiwiaW5jbHVkZXMiLCJkb3duUmF3TGluZXMiLCJhY3Rpb24iLCJsZW4iLCJub3JtYWxpemVDb2x1bW5Gb3JDb21wYXJpc29uIiwiY29sdW1uc1RvIiwiZXh0cmFDb2x1bW5zIiwiZGIiLCJjb25jYXQiLCJzYW1lRGJDb2x1bW5zIiwic2FtZU1kQ29sdW1ucyIsImEiLCJiIiwibGluZXNUbyIsImFkZENvbHVtbkRlZnMiLCJkcm9wQ29sdW1uTmFtZXMiLCJma1RvRHJvcEJlZm9yZUNvbHVtbiIsImZrIiwiZHJvcEZrTGluZXMiLCJyZXN0b3JlRmtMaW5lcyIsImRyb3BDb2x1bW5EZWZzIiwiY29sdW1uRGlmZlVwIiwiY29sdW1uRGlmZkRvd24iLCJsIiwiaW5kZXhlc1RvIiwiaWRlbnRpdHkiLCJrZXlzIiwiT2JqZWN0Iiwia2V5Iiwic29ydCIsImsiLCJleHRyYUluZGV4ZXMiLCJzZXRNaWdyYXRpb25JbmRleERlZmF1bHRzIiwiaXNWZWN0b3JJbmRleCIsInN1cHBvcnRzT3JkZXJpbmciLCJub3JtYWxpemVkVXNpbmciLCJnZW5lcmF0ZUFsdGVyQ29kZV9Gb3JlaWducyIsImVudGl0eUZvcmVpZ25zIiwiZHJvcHBpbmdDb2x1bW5zIiwiZ2V0S2V5IiwibWYiLCJkcm9wcGluZ0NvbHVtbk5hbWVzIiwiZmtUbyIsImVudGl0eUYiLCJtYXRjaGluZ0RiRiIsImRiRiIsImFsdGVyU3JjIiwiYWx0ZXJEc3QiLCJtYXRjaGluZ0VudGl0eUYiLCJpc0NvbHVtbkRyb3BwaW5nIiwiaGFzTGluZXMiLCJ2YWx1ZXMiLCJnZW5lcmF0ZUNyZWF0ZUNvZGUiLCJlbnRpdHlTZXQiLCJnZW5lcmF0ZUFsdGVyQ29kZSIsImRiU2V0IiwicmVwbGFjZUNvbHVtbkRlZmF1bHRUbyIsImMiLCJyZXBsYWNlTm9BY3Rpb25Pbk15U1FMIiwiZiIsImFsdGVyQ29kZXMiLCJpc0VxdWFsQ29sdW1ucyIsImlzRXF1YWxJbmRleGVzIiwiYWx0ZXJDb2RlIiwiZmxhdCIsIl9lbnRpdHlDb2x1bW5zIiwiX2VudGl0eUluZGV4ZXMiLCJfZGJDb2x1bW5zIiwiX2RiSW5kZXhlcyIsIl9kYkZvcmVpZ25zIiwicmVmZXJlbmNpbmdGS3MiLCJnZXRSZWZlcmVuY2luZ0ZvcmVpZ25LZXlzIiwic2VsZlJlZmVyZW5jaW5nRktzIiwidGFibGVOYW1lIiwiZXh0ZXJuYWxSZWZlcmVuY2luZ0ZLcyIsInBrQ29uc3RyYWludE5hbWUiLCJuZXdQa1BnVHlwZSIsImdldFBrUGdUeXBlIiwib2xkUGtQZ1R5cGUiLCJ1cExpbmVzIiwiY29sdW1uTmFtZSIsImNvbnN0cmFpbnROYW1lIiwiZG93bkxpbmVzIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxXQUFXLGtCQUFrQjtBQUVwQyxTQUFTQyxZQUFZLEVBQUVDLElBQUksUUFBUSxVQUFVO0FBQzdDLFNBQVNDLGFBQWEsRUFBRUMsS0FBSyxRQUFRLGNBQUs7QUFTMUMsU0FBU0MsZ0JBQWdCLFFBQVEsb0JBQWlCO0FBQ2xELFNBQVNDLFVBQVUsUUFBUSx3QkFBcUI7QUFDaEQsU0FBU0MsY0FBYyxFQUFFQyxjQUFjLFFBQVEsb0JBQWlCO0FBQ2hFLFNBQVNDLHNCQUFzQixRQUFRLGdDQUE2QjtBQThCcEUsTUFBTUMsaUNBQXVFO0lBQzNFLGNBQWMsQ0FBQzs7Ozs7Ozs7O01BU1gsQ0FBQztJQUNMLGVBQWUsQ0FBQzs7Ozs7Ozs7O01BU1osQ0FBQztBQUNQO0FBRUEsTUFBTUM7O0lBQ0lDLFFBQVEsRUFBRTtJQUVsQixZQUFZLEFBQWlCQyxNQUFtQyxDQUFFO2FBQXJDQSxTQUFBQTtJQUFzQztJQUVuRUMsVUFBbUI7UUFDakIsT0FBTyxJQUFJLENBQUNGLEtBQUssSUFBSSxJQUFJLENBQUNDLE1BQU0sQ0FBQ0UsTUFBTTtJQUN6QztJQUVBQyxrQkFBNEM7UUFDMUMsT0FBTyxJQUFJLENBQUNDLFdBQVc7SUFDekI7SUFFUUEsY0FBd0M7UUFDOUMsTUFBTUMsUUFBUTtZQUFDLElBQUksQ0FBQ0MsWUFBWTtTQUFHO1FBRW5DLE1BQU8sSUFBSSxDQUFDQyxhQUFhLENBQUMsTUFBTztZQUMvQkYsTUFBTUcsSUFBSSxDQUFDLElBQUksQ0FBQ0YsWUFBWTtRQUM5QjtRQUVBLE9BQU9ELE1BQU1I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
|
|
1464
|
+
//#endregion
|
|
1465
|
+
init_code_generation();
|
|
1466
|
+
export { generateAlterCode, generateCreateCode, getAlterIndexesTo, init_code_generation, setMigrationIndexDefaults };
|
|
1467
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZS1nZW5lcmF0aW9uLmpzIiwibmFtZXMiOlsidG9rZW5zOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuW10iLCJsaW5lczogc3RyaW5nW10iLCJyZXN1bHQ6IENvbHVtbkRlZmluaXRpb25SZXN1bHQiLCJjaGFpbnM6IHN0cmluZ1tdIiwiZXh0cmFUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQiLCJhbHRlckNvZGVzOiAoR2VuTWlncmF0aW9uQ29kZSB8IEdlbk1pZ3JhdGlvbkNvZGVbXSB8IG51bGwpW10iLCJ1cExpbmVzOiBzdHJpbmdbXSIsImRvd25MaW5lczogc3RyaW5nW10iLCJTRUFSQ0hfVEVYVF9IRUxQRVJfREVGSU5JVElPTlM6IFJlY29yZDxTZWFyY2hUZXh0SGVscGVyS2luZCwgc3RyaW5nPiIsImFyZ3M6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZVtdIiwicGFydHM6IHN0cmluZ1tdIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21pZ3JhdGlvbi9jb2RlLWdlbmVyYXRpb24udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGVxdWFsIGZyb20gXCJmYXN0LWRlZXAtZXF1YWxcIjtcbmltcG9ydCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBhbHBoYWJldGljYWwsIGRpZmYgfSBmcm9tIFwicmFkYXNoaVwiO1xuXG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB7XG4gIHR5cGUgRW50aXR5UHJvcCxcbiAgdHlwZSBHZW5NaWdyYXRpb25Db2RlLFxuICB0eXBlIE1pZ3JhdGlvbkNvbHVtbixcbiAgdHlwZSBNaWdyYXRpb25Gb3JlaWduLFxuICB0eXBlIE1pZ3JhdGlvbkluZGV4LFxuICB0eXBlIE1pZ3JhdGlvblNldCxcbn0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc1NlYXJjaFRleHRQcm9wIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBmb3JtYXRDb2RlIH0gZnJvbSBcIi4uL3V0aWxzL2Zvcm1hdHRlclwiO1xuaW1wb3J0IHsgZGlmZmVyZW5jZVdpdGgsIGludGVyc2VjdGlvbkJ5IH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyIH0gZnJvbSBcIi4vcG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyXCI7XG5cbi8qKlxuICog7Lus65+8IOygleydmCDqsrDqs7wg7YOA7J6FXG4gKiAtIGJ1aWxkZXI6IEtuZXggdGFibGUgYnVpbGRlciDrqZTshJzrk5zroZwg7Iuk7ZaJ7ZWgIOq1rOusuCAodGFibGUueHh4KCkpXG4gKiAtIHJhdzoga25leC5yYXcoKeuhnCDsi6TtlontlaAg6rWs66y4XG4gKi9cbnR5cGUgQ29sdW1uRGVmaW5pdGlvblJlc3VsdCA9IHtcbiAgYnVpbGRlcjogc3RyaW5nW107XG4gIHJhdzogc3RyaW5nW107XG59O1xuXG50eXBlIFNlYXJjaFRleHRIZWxwZXJLaW5kID0gXCJ0ZXh0LWFycmF5XCIgfCBcImpzb25iLWFycmF5XCI7XG5cbnR5cGUgU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbiA9XG4gIHwgeyB0eXBlOiBcImlkZW50aWZpZXJcIjsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiBcInF1b3RlZElkZW50aWZpZXJcIjsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiBcInN0cmluZ1wiOyB2YWx1ZTogc3RyaW5nIH1cbiAgfCB7IHR5cGU6IFwic3ltYm9sXCI7IHZhbHVlOiBcIihcIiB8IFwiKVwiIHwgXCIsXCIgfVxuICB8IHsgdHlwZTogXCJvcGVyYXRvclwiOyB2YWx1ZTogXCJ8fFwiIHwgXCI6OlwiIH07XG5cbnR5cGUgU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlID1cbiAgfCB7IHR5cGU6IFwiaWRlbnRpZmllclwiOyBuYW1lOiBzdHJpbmc7IHF1b3RlZDogYm9vbGVhbiB9XG4gIHwgeyB0eXBlOiBcInN0cmluZ1wiOyB2YWx1ZTogc3RyaW5nIH1cbiAgfCB7IHR5cGU6IFwiYm9vbGVhblwiOyB2YWx1ZTogYm9vbGVhbiB9XG4gIHwgeyB0eXBlOiBcImZ1bmN0aW9uXCI7IG5hbWU6IHN0cmluZzsgYXJnczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlW10gfVxuICB8IHsgdHlwZTogXCJjb25jYXRcIjsgcGFydHM6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZVtdIH1cbiAgfCB7IHR5cGU6IFwiY29sbGF0ZVwiOyBleHByOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGU7IGNvbGxhdGlvbjogc3RyaW5nOyBxdW90ZWQ6IGJvb2xlYW4gfVxuICB8IHsgdHlwZTogXCJjYXN0XCI7IGV4cHI6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZTsgdGFyZ2V0VHlwZTogc3RyaW5nIH07XG5cbmNvbnN0IFNFQVJDSF9URVhUX0hFTFBFUl9ERUZJTklUSU9OUzogUmVjb3JkPFNlYXJjaFRleHRIZWxwZXJLaW5kLCBzdHJpbmc+ID0ge1xuICBcInRleHQtYXJyYXlcIjogYGF3YWl0IGtuZXgucmF3KFxcYENSRUFURSBPUiBSRVBMQUNFIEZVTkNUSU9OIHNvbmFtdV90ZXh0X2FycmF5X2FnZyhhcnIgdGV4dFtdLCBjaSBib29sZWFuIERFRkFVTFQgdHJ1ZSlcblJFVFVSTlMgdGV4dFxuTEFOR1VBR0Ugc3FsIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFIFJFVFVSTlMgTlVMTCBPTiBOVUxMIElOUFVUXG5BUyAkJFxuICBTRUxFQ1Qgc3RyaW5nX2FnZyhcbiAgICBDQVNFIFdIRU4gY2kgVEhFTiBsb3dlcih2YWx1ZSkgRUxTRSB2YWx1ZSBFTkQsXG4gICAgJyAnXG4gIClcbiAgRlJPTSB1bm5lc3QoYXJyKSBBUyB2YWx1ZVxuJCRcXGApO2AsXG4gIFwianNvbmItYXJyYXlcIjogYGF3YWl0IGtuZXgucmF3KFxcYENSRUFURSBPUiBSRVBMQUNFIEZVTkNUSU9OIHNvbmFtdV9qc29uYl9hcnJheV9hZ2coYXJyIGpzb25iLCBjaSBib29sZWFuIERFRkFVTFQgdHJ1ZSlcblJFVFVSTlMgdGV4dFxuTEFOR1VBR0Ugc3FsIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFIFJFVFVSTlMgTlVMTCBPTiBOVUxMIElOUFVUXG5BUyAkJFxuICBTRUxFQ1Qgc3RyaW5nX2FnZyhcbiAgICBDQVNFIFdIRU4gY2kgVEhFTiBsb3dlcih2YWx1ZSkgRUxTRSB2YWx1ZSBFTkQsXG4gICAgJyAnXG4gIClcbiAgRlJPTSBqc29uYl9hcnJheV9lbGVtZW50c190ZXh0KGFycilcbiQkXFxgKTtgLFxufTtcblxuY2xhc3MgU2VhcmNoVGV4dEV4cHJlc3Npb25QYXJzZXIge1xuICBwcml2YXRlIGluZGV4ID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHRva2VuczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbltdKSB7fVxuXG4gIGlzQXRFbmQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZXggPj0gdGhpcy50b2tlbnMubGVuZ3RoO1xuICB9XG5cbiAgcGFyc2VFeHByZXNzaW9uKCk6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VDb25jYXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VDb25jYXQoKTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlIHtcbiAgICBjb25zdCBwYXJ0cyA9IFt0aGlzLnBhcnNlUG9zdGZpeCgpXTtcblxuICAgIHdoaWxlICh0aGlzLm1hdGNoT3BlcmF0b3IoXCJ8fFwiKSkge1xuICAgICAgcGFydHMucHVzaCh0aGlzLnBhcnNlUG9zdGZpeCgpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFydHMubGVuZ3RoID09PSAxID8gcGFydHNbMF0gOiB7IHR5cGU6IFwiY29uY2F0XCIsIHBhcnRzIH07XG4gIH1cblxuICBwcml2YXRlIHBhcnNlUG9zdGZpeCgpOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUge1xuICAgIGxldCBub2RlID0gdGhpcy5wYXJzZVByaW1hcnkoKTtcblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAodGhpcy5tYXRjaE9wZXJhdG9yKFwiOjpcIikpIHtcbiAgICAgICAgbm9kZSA9IHtcbiAgICAgICAgICB0eXBlOiBcImNhc3RcIixcbiAgICAgICAgICBleHByOiBub2RlLFxuICAgICAgICAgIHRhcmdldFR5cGU6IHRoaXMucGFyc2VUeXBlTmFtZSgpLFxuICAgICAgICB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubWF0Y2hJZGVudGlmaWVyKFwiY29sbGF0ZVwiKSkge1xuICAgICAgICBjb25zdCB0b2tlbiA9IHRoaXMuY29uc3VtZUNvbGxhdGlvblRva2VuKCk7XG4gICAgICAgIG5vZGUgPSB7XG4gICAgICAgICAgdHlwZTogXCJjb2xsYXRlXCIsXG4gICAgICAgICAgZXhwcjogbm9kZSxcbiAgICAgICAgICBjb2xsYXRpb246IHRva2VuLnZhbHVlLFxuICAgICAgICAgIHF1b3RlZDogdG9rZW4udHlwZSA9PT0gXCJxdW90ZWRJZGVudGlmaWVyXCIsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VQcmltYXJ5KCk6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLmNvbnN1bWVUb2tlbihcIu2RnO2YhOyLnVwiKTtcblxuICAgIGlmICh0b2tlbi50eXBlID09PSBcInN5bWJvbFwiICYmIHRva2VuLnZhbHVlID09PSBcIihcIikge1xuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMucGFyc2VFeHByZXNzaW9uKCk7XG4gICAgICB0aGlzLmV4cGVjdFN5bWJvbChcIilcIik7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9XG5cbiAgICBpZiAodG9rZW4udHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJzdHJpbmdcIiwgdmFsdWU6IHRva2VuLnZhbHVlIH07XG4gICAgfVxuXG4gICAgaWYgKHRva2VuLnR5cGUgPT09IFwiaWRlbnRpZmllclwiIHx8IHRva2VuLnR5cGUgPT09IFwicXVvdGVkSWRlbnRpZmllclwiKSB7XG4gICAgICBjb25zdCBsb3dlck5hbWUgPSB0b2tlbi52YWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKHRva2VuLnR5cGUgPT09IFwiaWRlbnRpZmllclwiICYmIChsb3dlck5hbWUgPT09IFwidHJ1ZVwiIHx8IGxvd2VyTmFtZSA9PT0gXCJmYWxzZVwiKSkge1xuICAgICAgICByZXR1cm4geyB0eXBlOiBcImJvb2xlYW5cIiwgdmFsdWU6IGxvd2VyTmFtZSA9PT0gXCJ0cnVlXCIgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubWF0Y2hTeW1ib2woXCIoXCIpKSB7XG4gICAgICAgIGlmICh0b2tlbi50eXBlID09PSBcImlkZW50aWZpZXJcIiAmJiBsb3dlck5hbWUgPT09IFwidHJpbVwiICYmIHRoaXMuaXNUcmltQm90aEZyb21Gb3JtKCkpIHtcbiAgICAgICAgICB0aGlzLmluZGV4ICs9IDI7XG4gICAgICAgICAgY29uc3QgYXJnID0gdGhpcy5wYXJzZUV4cHJlc3Npb24oKTtcbiAgICAgICAgICB0aGlzLmV4cGVjdFN5bWJvbChcIilcIik7XG4gICAgICAgICAgcmV0dXJuIHsgdHlwZTogXCJmdW5jdGlvblwiLCBuYW1lOiBcInRyaW1cIiwgYXJnczogW2FyZ10gfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFyZ3MgPSB0aGlzLnBhcnNlRnVuY3Rpb25BcmdzKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgICAgICAgIG5hbWU6IHRva2VuLnZhbHVlLFxuICAgICAgICAgIGFyZ3MsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiaWRlbnRpZmllclwiLFxuICAgICAgICBuYW1lOiB0b2tlbi52YWx1ZSxcbiAgICAgICAgcXVvdGVkOiB0b2tlbi50eXBlID09PSBcInF1b3RlZElkZW50aWZpZXJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGDsp4Dsm5DrkJjsp4Ag7JWK64qUIHNlYXJjaFRleHQgZXhwcmVzc2lvbiB0b2tlbjogJHt0b2tlbi50eXBlfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUZ1bmN0aW9uQXJncygpOiBTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGVbXSB7XG4gICAgaWYgKHRoaXMubWF0Y2hTeW1ib2woXCIpXCIpKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgYXJnczogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlW10gPSBbXTtcbiAgICBkbyB7XG4gICAgICBhcmdzLnB1c2godGhpcy5wYXJzZUV4cHJlc3Npb24oKSk7XG4gICAgfSB3aGlsZSAodGhpcy5tYXRjaFN5bWJvbChcIixcIikpO1xuXG4gICAgdGhpcy5leHBlY3RTeW1ib2woXCIpXCIpO1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVR5cGVOYW1lKCk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICAgIGlmIChcbiAgICAgICAgdG9rZW4/LnR5cGUgPT09IFwiaWRlbnRpZmllclwiIHx8XG4gICAgICAgIHRva2VuPy50eXBlID09PSBcInF1b3RlZElkZW50aWZpZXJcIiB8fFxuICAgICAgICAodG9rZW4/LnR5cGUgPT09IFwic3ltYm9sXCIgJiZcbiAgICAgICAgICAodG9rZW4udmFsdWUgPT09IFwiKFwiIHx8IHRva2VuLnZhbHVlID09PSBcIilcIiB8fCB0b2tlbi52YWx1ZSA9PT0gXCIsXCIpKVxuICAgICAgKSB7XG4gICAgICAgIGlmICh0b2tlbi50eXBlID09PSBcInN5bWJvbFwiKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJ0cy5wdXNoKHRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAocGFydHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCLtg4DsnoUg7LqQ7Iqk7YyFIOuMgOyDgSDtg4DsnoXsnYQg7LC+7J2EIOyImCDsl4bsirXri4jri6QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJ0cy5qb2luKFwiIFwiKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3VtZUNvbGxhdGlvblRva2VuKCk6IEV4dHJhY3Q8XG4gICAgU2VhcmNoVGV4dEV4cHJlc3Npb25Ub2tlbixcbiAgICB7IHR5cGU6IFwiaWRlbnRpZmllclwiIHwgXCJxdW90ZWRJZGVudGlmaWVyXCIgfVxuICA+IHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMucGVlaygpO1xuICAgIGlmICh0b2tlbj8udHlwZSAhPT0gXCJpZGVudGlmaWVyXCIgJiYgdG9rZW4/LnR5cGUgIT09IFwicXVvdGVkSWRlbnRpZmllclwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDT0xMQVRFIOuMgOyDgSDsi53rs4TsnpDrpbwg7LC+7J2EIOyImCDsl4bsirXri4jri6QuXCIpO1xuICAgIH1cbiAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1RyaW1Cb3RoRnJvbUZvcm0oKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYm90aFRva2VuID0gdGhpcy5wZWVrKCk7XG4gICAgY29uc3QgZnJvbVRva2VuID0gdGhpcy5wZWVrKDEpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIGJvdGhUb2tlbj8udHlwZSA9PT0gXCJpZGVudGlmaWVyXCIgJiZcbiAgICAgIGJvdGhUb2tlbi52YWx1ZS50b0xvd2VyQ2FzZSgpID09PSBcImJvdGhcIiAmJlxuICAgICAgZnJvbVRva2VuPy50eXBlID09PSBcImlkZW50aWZpZXJcIiAmJlxuICAgICAgZnJvbVRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkgPT09IFwiZnJvbVwiXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZXhwZWN0U3ltYm9sKHZhbHVlOiBcIihcIiB8IFwiKVwiIHwgXCIsXCIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMubWF0Y2hTeW1ib2wodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFwiJHt2YWx1ZX1cIiDthqDtgbDsnbQg7ZWE7JqU7ZWp64uI64ukLmApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hTeW1ib2wodmFsdWU6IFwiKFwiIHwgXCIpXCIgfCBcIixcIik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5wZWVrKCk7XG4gICAgaWYgKHRva2VuPy50eXBlID09PSBcInN5bWJvbFwiICYmIHRva2VuLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgdGhpcy5pbmRleCArPSAxO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hPcGVyYXRvcih2YWx1ZTogXCJ8fFwiIHwgXCI6OlwiKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICBpZiAodG9rZW4/LnR5cGUgPT09IFwib3BlcmF0b3JcIiAmJiB0b2tlbi52YWx1ZSA9PT0gdmFsdWUpIHtcbiAgICAgIHRoaXMuaW5kZXggKz0gMTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIG1hdGNoSWRlbnRpZmllcih2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICBpZiAodG9rZW4/LnR5cGUgPT09IFwiaWRlbnRpZmllclwiICYmIHRva2VuLnZhbHVlLnRvTG93ZXJDYXNlKCkgPT09IHZhbHVlLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIHRoaXMuaW5kZXggKz0gMTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGNvbnN1bWVUb2tlbihjb250ZXh0OiBzdHJpbmcpOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMucGVlaygpO1xuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fSDthqDtgbDsnbQg7ZWE7JqU7ZWp64uI64ukLmApO1xuICAgIH1cbiAgICB0aGlzLmluZGV4ICs9IDE7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG5cbiAgcHJpdmF0ZSBwZWVrKG9mZnNldCA9IDApOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbnNbdGhpcy5pbmRleCArIG9mZnNldF07XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbjogTWlncmF0aW9uSW5kZXhbXCJjb2x1bW5zXCJdW251bWJlcl0pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gY29sdW1uLm9wY2xhc3MgPz8gY29sdW1uLnZlY3Rvck9wcztcbn1cblxuZnVuY3Rpb24gdG9rZW5pemVTZWFyY2hUZXh0RXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBTZWFyY2hUZXh0RXhwcmVzc2lvblRva2VuW10ge1xuICBjb25zdCB0b2tlbnM6IFNlYXJjaFRleHRFeHByZXNzaW9uVG9rZW5bXSA9IFtdO1xuICBsZXQgaW5kZXggPSAwO1xuXG4gIHdoaWxlIChpbmRleCA8IGV4cHJlc3Npb24ubGVuZ3RoKSB7XG4gICAgY29uc3QgY2hhciA9IGV4cHJlc3Npb25baW5kZXhdO1xuXG4gICAgaWYgKGNoYXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKC9cXHMvLnRlc3QoY2hhcikpIHtcbiAgICAgIGluZGV4ICs9IDE7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZXhwcmVzc2lvbi5zdGFydHNXaXRoKFwifHxcIiwgaW5kZXgpKSB7XG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwib3BlcmF0b3JcIiwgdmFsdWU6IFwifHxcIiB9KTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoZXhwcmVzc2lvbi5zdGFydHNXaXRoKFwiOjpcIiwgaW5kZXgpKSB7XG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwib3BlcmF0b3JcIiwgdmFsdWU6IFwiOjpcIiB9KTtcbiAgICAgIGluZGV4ICs9IDI7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoY2hhciA9PT0gXCIoXCIgfHwgY2hhciA9PT0gXCIpXCIgfHwgY2hhciA9PT0gXCIsXCIpIHtcbiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogXCJzeW1ib2xcIiwgdmFsdWU6IGNoYXIgfSk7XG4gICAgICBpbmRleCArPSAxO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKGNoYXIgPT09IFwiJ1wiKSB7XG4gICAgICBsZXQgdmFsdWUgPSBcIlwiO1xuICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgZXhwcmVzc2lvbi5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IGV4cHJlc3Npb25baW5kZXhdO1xuICAgICAgICBpZiAoY3VycmVudCA9PT0gXCInXCIpIHtcbiAgICAgICAgICBpZiAoZXhwcmVzc2lvbltpbmRleCArIDFdID09PSBcIidcIikge1xuICAgICAgICAgICAgdmFsdWUgKz0gXCInXCI7XG4gICAgICAgICAgICBpbmRleCArPSAyO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjdXJyZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlICs9IGN1cnJlbnQ7XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG5cbiAgICAgIHRva2Vucy5wdXNoKHsgdHlwZTogXCJzdHJpbmdcIiwgdmFsdWUgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoY2hhciA9PT0gJ1wiJykge1xuICAgICAgbGV0IHZhbHVlID0gXCJcIjtcbiAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgIHdoaWxlIChpbmRleCA8IGV4cHJlc3Npb24ubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSBleHByZXNzaW9uW2luZGV4XTtcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09ICdcIicpIHtcbiAgICAgICAgICBpZiAoZXhwcmVzc2lvbltpbmRleCArIDFdID09PSAnXCInKSB7XG4gICAgICAgICAgICB2YWx1ZSArPSAnXCInO1xuICAgICAgICAgICAgaW5kZXggKz0gMjtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY3VycmVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSArPSBjdXJyZW50O1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfVxuXG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwicXVvdGVkSWRlbnRpZmllclwiLCB2YWx1ZSB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICgvW0EtWmEtel9dLy50ZXN0KGNoYXIpKSB7XG4gICAgICBsZXQgdmFsdWUgPSBjaGFyO1xuICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgd2hpbGUgKGluZGV4IDwgZXhwcmVzc2lvbi5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgY3VycmVudCA9IGV4cHJlc3Npb25baW5kZXhdO1xuICAgICAgICBpZiAoY3VycmVudCAhPT0gdW5kZWZpbmVkICYmIC9bQS1aYS16MC05XyRdLy50ZXN0KGN1cnJlbnQpKSB7XG4gICAgICAgICAgdmFsdWUgKz0gY3VycmVudDtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICB0b2tlbnMucHVzaCh7IHR5cGU6IFwiaWRlbnRpZmllclwiLCB2YWx1ZSB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihg7KeA7JuQ65CY7KeAIOyViuuKlCBzZWFyY2hUZXh0IGV4cHJlc3Npb24g66y47J6QOiAke2NoYXJ9YCk7XG4gIH1cblxuICByZXR1cm4gdG9rZW5zO1xufVxuXG5mdW5jdGlvbiBjYW5vbmljYWxpemVTZWFyY2hUZXh0R2VuZXJhdGVkRXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTZWFyY2hUZXh0RXhwcmVzc2lvblBhcnNlcih0b2tlbml6ZVNlYXJjaFRleHRFeHByZXNzaW9uKGV4cHJlc3Npb24pKTtcbiAgICBjb25zdCBwYXJzZWRFeHByZXNzaW9uID0gcGFyc2VyLnBhcnNlRXhwcmVzc2lvbigpO1xuXG4gICAgaWYgKCFwYXJzZXIuaXNBdEVuZCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZWFyY2hUZXh0IGV4cHJlc3Npb24g7YyM7Iux7J20IOuBneuCmOyngCDslYrslZjsirXri4jri6QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiByZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFyc2VkRXhwcmVzc2lvbikpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25GYWxsYmFjayhleHByZXNzaW9uKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUoXG4gIG5vZGU6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSxcbik6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSB7XG4gIHN3aXRjaCAobm9kZS50eXBlKSB7XG4gICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm5vZGUsXG4gICAgICAgIG5hbWU6IG5vZGUucXVvdGVkID8gbm9kZS5uYW1lIDogbm9kZS5uYW1lLnRvTG93ZXJDYXNlKCksXG4gICAgICB9O1xuICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgY2FzZSBcImNvbmNhdFwiOiB7XG4gICAgICBjb25zdCBwYXJ0cyA9IG5vZGUucGFydHMuZmxhdE1hcCgocGFydCkgPT4ge1xuICAgICAgICBjb25zdCBub3JtYWxpemVkUGFydCA9IG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShwYXJ0KTtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRQYXJ0LnR5cGUgPT09IFwiY29uY2F0XCIgPyBub3JtYWxpemVkUGFydC5wYXJ0cyA6IFtub3JtYWxpemVkUGFydF07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwiY29uY2F0XCIsIHBhcnRzIH07XG4gICAgfVxuICAgIGNhc2UgXCJjb2xsYXRlXCI6XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImNvbGxhdGVcIixcbiAgICAgICAgZXhwcjogbm9ybWFsaXplU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlKG5vZGUuZXhwciksXG4gICAgICAgIGNvbGxhdGlvbjogbm9kZS5jb2xsYXRpb24udG9VcHBlckNhc2UoKSA9PT0gXCJDXCIgPyBcIkNcIiA6IG5vZGUuY29sbGF0aW9uLFxuICAgICAgICBxdW90ZWQ6IG5vZGUucXVvdGVkIHx8IG5vZGUuY29sbGF0aW9uLnRvVXBwZXJDYXNlKCkgPT09IFwiQ1wiLFxuICAgICAgfTtcbiAgICBjYXNlIFwiY2FzdFwiOiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRXhwciA9IG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShub2RlLmV4cHIpO1xuICAgICAgY29uc3QgdGFyZ2V0VHlwZSA9IG5vZGUudGFyZ2V0VHlwZS5yZXBsYWNlKC9cXHMrL2csIFwiIFwiKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICh0YXJnZXRUeXBlID09PSBcInRleHRcIiB8fCB0YXJnZXRUeXBlID09PSBcImNoYXJhY3RlciB2YXJ5aW5nXCIgfHwgdGFyZ2V0VHlwZSA9PT0gXCJ2YXJjaGFyXCIpIHtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRFeHByO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjYXN0XCIsXG4gICAgICAgIGV4cHI6IG5vcm1hbGl6ZWRFeHByLFxuICAgICAgICB0YXJnZXRUeXBlLFxuICAgICAgfTtcbiAgICB9XG4gICAgY2FzZSBcImZ1bmN0aW9uXCI6IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBub2RlLm5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgIGxldCBhcmdzID0gbm9kZS5hcmdzLm1hcCgoYXJnKSA9PiBub3JtYWxpemVTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUoYXJnKSk7XG5cbiAgICAgIGlmICgobmFtZSA9PT0gXCJ0cmltXCIgfHwgbmFtZSA9PT0gXCJidHJpbVwiKSAmJiBhcmdzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiZnVuY3Rpb25cIixcbiAgICAgICAgICBuYW1lOiBcInRyaW1cIixcbiAgICAgICAgICBhcmdzLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIChuYW1lID09PSBcInNvbmFtdV90ZXh0X2FycmF5X2FnZ1wiIHx8IG5hbWUgPT09IFwic29uYW11X2pzb25iX2FycmF5X2FnZ1wiKSAmJlxuICAgICAgICBhcmdzLmxlbmd0aCA9PT0gMiAmJlxuICAgICAgICBhcmdzWzFdPy50eXBlID09PSBcImJvb2xlYW5cIiAmJlxuICAgICAgICBhcmdzWzFdLnZhbHVlXG4gICAgICApIHtcbiAgICAgICAgYXJncyA9IFthcmdzWzBdXTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJmdW5jdGlvblwiLFxuICAgICAgICBuYW1lLFxuICAgICAgICBhcmdzLFxuICAgICAgfTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyU2VhcmNoVGV4dEV4cHJlc3Npb24obm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlLCBwYXJlbnRQcmVjZWRlbmNlID0gMCk6IHN0cmluZyB7XG4gIGNvbnN0IHByZWNlZGVuY2UgPSBnZXRTZWFyY2hUZXh0RXhwcmVzc2lvblByZWNlZGVuY2Uobm9kZSk7XG4gIGNvbnN0IHJlbmRlcmVkID0gKCgpID0+IHtcbiAgICBzd2l0Y2ggKG5vZGUudHlwZSkge1xuICAgICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICAgICAgcmV0dXJuIG5vZGUucXVvdGVkID8gYFwiJHtub2RlLm5hbWUucmVwbGFjZUFsbCgnXCInLCAnXCJcIicpfVwiYCA6IG5vZGUubmFtZTtcbiAgICAgIGNhc2UgXCJzdHJpbmdcIjpcbiAgICAgICAgcmV0dXJuIGAnJHtub2RlLnZhbHVlLnJlcGxhY2VBbGwoXCInXCIsIFwiJydcIil9J2A7XG4gICAgICBjYXNlIFwiYm9vbGVhblwiOlxuICAgICAgICByZXR1cm4gbm9kZS52YWx1ZSA/IFwidHJ1ZVwiIDogXCJmYWxzZVwiO1xuICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgIHJldHVybiBgJHtub2RlLm5hbWV9KCR7bm9kZS5hcmdzXG4gICAgICAgICAgLm1hcCgoYXJnKSA9PiByZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihhcmcpKVxuICAgICAgICAgIC5qb2luKFwiLCBcIil9KWA7XG4gICAgICBjYXNlIFwiY29uY2F0XCI6XG4gICAgICAgIHJldHVybiBub2RlLnBhcnRzLm1hcCgocGFydCkgPT4gcmVuZGVyU2VhcmNoVGV4dEV4cHJlc3Npb24ocGFydCwgcHJlY2VkZW5jZSkpLmpvaW4oXCIgfHwgXCIpO1xuICAgICAgY2FzZSBcImNvbGxhdGVcIjoge1xuICAgICAgICBjb25zdCBjb2xsYXRpb24gPSBub2RlLnF1b3RlZFxuICAgICAgICAgID8gYFwiJHtub2RlLmNvbGxhdGlvbi5yZXBsYWNlQWxsKCdcIicsICdcIlwiJyl9XCJgXG4gICAgICAgICAgOiBub2RlLmNvbGxhdGlvbjtcbiAgICAgICAgcmV0dXJuIGAke3JlbmRlclNlYXJjaFRleHRFeHByZXNzaW9uKG5vZGUuZXhwciwgcHJlY2VkZW5jZSl9IENPTExBVEUgJHtjb2xsYXRpb259YDtcbiAgICAgIH1cbiAgICAgIGNhc2UgXCJjYXN0XCI6XG4gICAgICAgIHJldHVybiBgJHtyZW5kZXJTZWFyY2hUZXh0RXhwcmVzc2lvbihub2RlLmV4cHIsIHByZWNlZGVuY2UpfTo6JHtub2RlLnRhcmdldFR5cGV9YDtcbiAgICB9XG4gIH0pKCk7XG5cbiAgaWYgKHByZWNlZGVuY2UgPCBwYXJlbnRQcmVjZWRlbmNlKSB7XG4gICAgcmV0dXJuIGAoJHtyZW5kZXJlZH0pYDtcbiAgfVxuXG4gIHJldHVybiByZW5kZXJlZDtcbn1cblxuZnVuY3Rpb24gZ2V0U2VhcmNoVGV4dEV4cHJlc3Npb25QcmVjZWRlbmNlKG5vZGU6IFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZSk6IG51bWJlciB7XG4gIHN3aXRjaCAobm9kZS50eXBlKSB7XG4gICAgY2FzZSBcImNvbmNhdFwiOlxuICAgICAgcmV0dXJuIDE7XG4gICAgY2FzZSBcImNvbGxhdGVcIjpcbiAgICBjYXNlIFwiY2FzdFwiOlxuICAgICAgcmV0dXJuIDI7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAzO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVNlYXJjaFRleHRFeHByZXNzaW9uRmFsbGJhY2soZXhwcmVzc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4cHJlc3Npb25cbiAgICAucmVwbGFjZSgvXFxzKy9nLCBcIiBcIilcbiAgICAucmVwbGFjZSgvXFxiVFJJTVxccypcXChcXHMqQk9USFxccytGUk9NXFxzKy9naSwgXCJ0cmltKFwiKVxuICAgIC5yZXBsYWNlKC86Oig/OnRleHR8Y2hhcmFjdGVyIHZhcnlpbmd8dmFyY2hhcilcXGIvZ2ksIFwiXCIpXG4gICAgLnJlcGxhY2UoLyxcXHMqdHJ1ZVxcYi9naSwgXCJcIilcbiAgICAudHJpbSgpO1xufVxuXG5mdW5jdGlvbiB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShcbiAgbm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlLFxuICB2aXNpdG9yOiAobm9kZTogU2VhcmNoVGV4dEV4cHJlc3Npb25Ob2RlKSA9PiB2b2lkLFxuKTogdm9pZCB7XG4gIHZpc2l0b3Iobm9kZSk7XG5cbiAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICBjYXNlIFwiY29uY2F0XCI6XG4gICAgICBub2RlLnBhcnRzLmZvckVhY2goKHBhcnQpID0+IHtcbiAgICAgICAgdmlzaXRTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFydCwgdmlzaXRvcik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICBjYXNlIFwiY29sbGF0ZVwiOlxuICAgIGNhc2UgXCJjYXN0XCI6XG4gICAgICB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShub2RlLmV4cHIsIHZpc2l0b3IpO1xuICAgICAgcmV0dXJuO1xuICAgIGNhc2UgXCJmdW5jdGlvblwiOlxuICAgICAgbm9kZS5hcmdzLmZvckVhY2goKGFyZykgPT4ge1xuICAgICAgICB2aXNpdFNlYXJjaFRleHRFeHByZXNzaW9uTm9kZShhcmcsIHZpc2l0b3IpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgY2FzZSBcImlkZW50aWZpZXJcIjpcbiAgICBjYXNlIFwic3RyaW5nXCI6XG4gICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgIHJldHVybjtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTZWFyY2hUZXh0SGVscGVyS2luZHNGcm9tRXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcpOiBTZXQ8U2VhcmNoVGV4dEhlbHBlcktpbmQ+IHtcbiAgY29uc3QgaGVscGVyS2luZHMgPSBuZXcgU2V0PFNlYXJjaFRleHRIZWxwZXJLaW5kPigpO1xuICBjb25zdCBhZGRIZWxwZXJLaW5kRnJvbU5hbWUgPSAobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZE5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKG5vcm1hbGl6ZWROYW1lID09PSBcInNvbmFtdV90ZXh0X2FycmF5X2FnZ1wiKSB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoXCJ0ZXh0LWFycmF5XCIpO1xuICAgIH0gZWxzZSBpZiAobm9ybWFsaXplZE5hbWUgPT09IFwic29uYW11X2pzb25iX2FycmF5X2FnZ1wiKSB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoXCJqc29uYi1hcnJheVwiKTtcbiAgICB9XG4gIH07XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZXIgPSBuZXcgU2VhcmNoVGV4dEV4cHJlc3Npb25QYXJzZXIodG9rZW5pemVTZWFyY2hUZXh0RXhwcmVzc2lvbihleHByZXNzaW9uKSk7XG4gICAgY29uc3QgcGFyc2VkRXhwcmVzc2lvbiA9IHBhcnNlci5wYXJzZUV4cHJlc3Npb24oKTtcblxuICAgIGlmICghcGFyc2VyLmlzQXRFbmQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VhcmNoVGV4dCBoZWxwZXIgZXhwcmVzc2lvbiDtjIzsi7HsnbQg64Gd64KY7KeAIOyViuyVmOyKteuLiOuLpC5cIik7XG4gICAgfVxuXG4gICAgdmlzaXRTZWFyY2hUZXh0RXhwcmVzc2lvbk5vZGUocGFyc2VkRXhwcmVzc2lvbiwgKG5vZGUpID0+IHtcbiAgICAgIGlmIChub2RlLnR5cGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBhZGRIZWxwZXJLaW5kRnJvbU5hbWUobm9kZS5uYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBjYXRjaCB7XG4gICAgaWYgKC9cXGJzb25hbXVfdGV4dF9hcnJheV9hZ2dcXHMqXFwoL2kudGVzdChleHByZXNzaW9uKSkge1xuICAgICAgaGVscGVyS2luZHMuYWRkKFwidGV4dC1hcnJheVwiKTtcbiAgICB9XG4gICAgaWYgKC9cXGJzb25hbXVfanNvbmJfYXJyYXlfYWdnXFxzKlxcKC9pLnRlc3QoZXhwcmVzc2lvbikpIHtcbiAgICAgIGhlbHBlcktpbmRzLmFkZChcImpzb25iLWFycmF5XCIpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBoZWxwZXJLaW5kcztcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVNlYXJjaFRleHRDb2x1bW5zKHRhYmxlOiBzdHJpbmcsIGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdKTogTWlncmF0aW9uQ29sdW1uW10ge1xuICBjb25zdCBlbnRpdHkgPSAoKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRCeVRhYmxlKHRhYmxlKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfSkoKTtcblxuICBpZiAoIWVudGl0eSkge1xuICAgIHJldHVybiBjb2x1bW5zO1xuICB9XG5cbiAgY29uc3QgcHJvcHNCeU5hbWUgPSBuZXcgTWFwKGVudGl0eS5wcm9wcy5tYXAoKHByb3ApID0+IFtwcm9wLm5hbWUsIHByb3BdKSk7XG5cbiAgcmV0dXJuIGNvbHVtbnMubWFwKChjb2x1bW4pID0+IHtcbiAgICBjb25zdCBwcm9wID0gcHJvcHNCeU5hbWUuZ2V0KGNvbHVtbi5uYW1lKTtcbiAgICBpZiAoIXByb3AgfHwgIWlzU2VhcmNoVGV4dFByb3AocHJvcCkpIHtcbiAgICAgIHJldHVybiBjb2x1bW47XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmNvbHVtbixcbiAgICAgIGdlbmVyYXRlZDoge1xuICAgICAgICB0eXBlOiBcIlNUT1JFRFwiLFxuICAgICAgICBleHByZXNzaW9uOiBidWlsZFNlYXJjaFRleHRHZW5lcmF0ZWRFeHByZXNzaW9uKHByb3AsIHByb3BzQnlOYW1lKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2VhcmNoVGV4dEdlbmVyYXRlZEV4cHJlc3Npb24oXG4gIHByb3A6IEV4dHJhY3Q8RW50aXR5UHJvcCwgeyB0eXBlOiBcInNlYXJjaFRleHRcIiB9PixcbiAgcHJvcHNCeU5hbWU6IE1hcDxzdHJpbmcsIEVudGl0eVByb3A+LFxuKTogc3RyaW5nIHtcbiAgY29uc3QgdG9rZW5zID0gcHJvcC5zb3VyY2VDb2x1bW5zLm1hcCgoc291cmNlKSA9PiB7XG4gICAgY29uc3Qgc291cmNlUHJvcCA9IHByb3BzQnlOYW1lLmdldChzb3VyY2UubmFtZSk7XG4gICAgaWYgKCFzb3VyY2VQcm9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHNlYXJjaFRleHQgc291cmNlIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCLsnYQo66W8KSDssL7snYQg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlUHJvcC50eXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBsb3dlcihDT0FMRVNDRSgke3NvdXJjZS5uYW1lfSwgJycpKWBcbiAgICAgICAgOiBgQ09BTEVTQ0UoJHtzb3VyY2UubmFtZX0sICcnKWA7XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZVByb3AudHlwZSA9PT0gXCJzdHJpbmdbXVwiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBDT0FMRVNDRShzb25hbXVfdGV4dF9hcnJheV9hZ2coJHtzb3VyY2UubmFtZX0pLCAnJylgXG4gICAgICAgIDogYENPQUxFU0NFKHNvbmFtdV90ZXh0X2FycmF5X2FnZygke3NvdXJjZS5uYW1lfSwgZmFsc2UpLCAnJylgO1xuICAgIH1cblxuICAgIGlmIChzb3VyY2VQcm9wLnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgICByZXR1cm4gc291cmNlLmNhc2VJbnNlbnNpdGl2ZVxuICAgICAgICA/IGBDT0FMRVNDRShzb25hbXVfanNvbmJfYXJyYXlfYWdnKCR7c291cmNlLm5hbWV9KSwgJycpYFxuICAgICAgICA6IGBDT0FMRVNDRShzb25hbXVfanNvbmJfYXJyYXlfYWdnKCR7c291cmNlLm5hbWV9LCBmYWxzZSksICcnKWA7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYHNlYXJjaFRleHQgc291cmNlIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCLsnZgg7YOA7J6FIFwiJHtzb3VyY2VQcm9wLnR5cGV9XCLsnYAo64qUKSDsp4Dsm5DrkJjsp4Ag7JWK7Iq164uI64ukLmAsXG4gICAgKTtcbiAgfSk7XG5cbiAgcmV0dXJuIGB0cmltKCR7dG9rZW5zLmpvaW4oYCB8fCAnICcgfHwgYCl9KWA7XG59XG5cbmZ1bmN0aW9uIGdldFNlYXJjaFRleHRIZWxwZXJEZWZpbml0aW9ucyh0YWJsZTogc3RyaW5nLCBjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgaGVscGVyS2luZHMgPSBuZXcgU2V0PFNlYXJjaFRleHRIZWxwZXJLaW5kPigpO1xuXG4gIGNvbHVtbnMuZm9yRWFjaCgoY29sdW1uKSA9PiB7XG4gICAgaWYgKCFjb2x1bW4uZ2VuZXJhdGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZ2V0U2VhcmNoVGV4dEhlbHBlcktpbmRzRnJvbUV4cHJlc3Npb24oY29sdW1uLmdlbmVyYXRlZC5leHByZXNzaW9uKS5mb3JFYWNoKChraW5kKSA9PiB7XG4gICAgICBoZWxwZXJLaW5kcy5hZGQoa2luZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGlmIChoZWxwZXJLaW5kcy5zaXplID4gMCkge1xuICAgIHJldHVybiAoW1widGV4dC1hcnJheVwiLCBcImpzb25iLWFycmF5XCJdIGFzIGNvbnN0KVxuICAgICAgLmZpbHRlcigoa2luZCkgPT4gaGVscGVyS2luZHMuaGFzKGtpbmQpKVxuICAgICAgLm1hcCgoa2luZCkgPT4gU0VBUkNIX1RFWFRfSEVMUEVSX0RFRklOSVRJT05TW2tpbmRdKTtcbiAgfVxuXG4gIGNvbnN0IGVudGl0eSA9ICgoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBFbnRpdHlNYW5hZ2VyLmdldEJ5VGFibGUodGFibGUpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9KSgpO1xuXG4gIGlmICghZW50aXR5KSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IHByb3BzQnlOYW1lID0gbmV3IE1hcChlbnRpdHkucHJvcHMubWFwKChwcm9wKSA9PiBbcHJvcC5uYW1lLCBwcm9wXSkpO1xuXG4gIGNvbHVtbnMuZm9yRWFjaCgoY29sdW1uKSA9PiB7XG4gICAgY29uc3QgcHJvcCA9IHByb3BzQnlOYW1lLmdldChjb2x1bW4ubmFtZSk7XG4gICAgaWYgKCFwcm9wIHx8ICFpc1NlYXJjaFRleHRQcm9wKHByb3ApKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcHJvcC5zb3VyY2VDb2x1bW5zLmZvckVhY2goKHNvdXJjZSkgPT4ge1xuICAgICAgY29uc3Qgc291cmNlUHJvcCA9IHByb3BzQnlOYW1lLmdldChzb3VyY2UubmFtZSk7XG4gICAgICBpZiAoc291cmNlUHJvcD8udHlwZSA9PT0gXCJzdHJpbmdbXVwiKSB7XG4gICAgICAgIGhlbHBlcktpbmRzLmFkZChcInRleHQtYXJyYXlcIik7XG4gICAgICB9IGVsc2UgaWYgKHNvdXJjZVByb3A/LnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgICAgIGhlbHBlcktpbmRzLmFkZChcImpzb25iLWFycmF5XCIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gKFtcInRleHQtYXJyYXlcIiwgXCJqc29uYi1hcnJheVwiXSBhcyBjb25zdClcbiAgICAuZmlsdGVyKChraW5kKSA9PiBoZWxwZXJLaW5kcy5oYXMoa2luZCkpXG4gICAgLm1hcCgoa2luZCkgPT4gU0VBUkNIX1RFWFRfSEVMUEVSX0RFRklOSVRJT05TW2tpbmRdKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2VhcmNoVGV4dENvbHVtbk5hbWVzKHRhYmxlOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPiB7XG4gIGNvbnN0IGVudGl0eSA9ICgoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBFbnRpdHlNYW5hZ2VyLmdldEJ5VGFibGUodGFibGUpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9KSgpO1xuXG4gIGlmICghZW50aXR5KSB7XG4gICAgcmV0dXJuIG5ldyBTZXQoKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgU2V0KGVudGl0eS5wcm9wcy5maWx0ZXIoaXNTZWFyY2hUZXh0UHJvcCkubWFwKChwcm9wKSA9PiBwcm9wLm5hbWUpKTtcbn1cblxuLyoqXG4gKiDthYzsnbTruJQg7IOd7ISx7ZWY64qUIOy8gOydtOyKpCAtIOy7rOufvC/snbjrjbHsiqQg7IOd7ISxXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQ3JlYXRlQ29kZV9Db2x1bW5BbmRJbmRleGVzKFxuICB0YWJsZTogc3RyaW5nLFxuICBjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgaW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbik6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZT4ge1xuICBjb25zdCByZXNvbHZlZENvbHVtbnMgPSByZXNvbHZlU2VhcmNoVGV4dENvbHVtbnModGFibGUsIGNvbHVtbnMpO1xuICBjb25zdCBjb2x1bW5EZWZzID0gZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIHJlc29sdmVkQ29sdW1ucyk7XG4gIGNvbnN0IGhlbHBlckRlZmluaXRpb25zID0gZ2V0U2VhcmNoVGV4dEhlbHBlckRlZmluaXRpb25zKHRhYmxlLCByZXNvbHZlZENvbHVtbnMpO1xuXG4gIC8vIOy7rOufvCwg7J24642x7IqkIOyymOumrFxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG4gICAgJ2ltcG9ydCB7IEtuZXggfSBmcm9tIFwia25leFwiOycsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cChrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4uaGVscGVyRGVmaW5pdGlvbnMsXG4gICAgYGF3YWl0IGtuZXguc2NoZW1hLmNyZWF0ZVRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCxcbiAgICAuLi5jb2x1bW5EZWZzLmJ1aWxkZXIsXG4gICAgXCJ9KTtcIixcbiAgICAvLyByYXcg6rWs66y4IChHZW5lcmF0ZWQgQ29sdW1uIOuTsSlcbiAgICAuLi5jb2x1bW5EZWZzLnJhdyxcbiAgICAvLyBpbmRleOuKlCBrbmV4LnJhd+uhnCDsspjrpqztlZjrr4DroZwgY3JlYXRlVGFibGUg67CW7JeQ7IScIOyLpO2WiVxuICAgIC4uLmluZGV4ZXMubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgYCByZXR1cm4ga25leC5zY2hlbWEuZHJvcFRhYmxlKFwiJHt0YWJsZX1cIik7YCxcbiAgICBcIn1cIixcbiAgXTtcbiAgcmV0dXJuIHtcbiAgICB0YWJsZSxcbiAgICB0eXBlOiBcIm5vcm1hbFwiLFxuICAgIHRpdGxlOiBgY3JlYXRlX18ke3RhYmxlfWAsXG4gICAgZm9ybWF0dGVkOiBhd2FpdCBmb3JtYXRDb2RlKGxpbmVzLmpvaW4oXCJcXG5cIiksIFwidHlwZXNjcmlwdFwiLCBgc3JjL21pZ3JhdGlvbi8ke3RhYmxlfS50c2ApLFxuICB9O1xufVxuXG4vKipcbiAqIE1pZ3JhdGlvbkNvbHVtbltdIOydveyWtOyEnCDsu6zrn7wg7KCV7J2Y7ZWY64qUIOq1rOusuCDsg53shLFcbiAqIEByZXR1cm5zIGJ1aWxkZXI6IHRhYmxlIGJ1aWxkZXIg66mU7ISc65OcLCByYXc6IGtuZXgucmF3KCkg6rWs66y4XG4gKi9cbmZ1bmN0aW9uIGdlbkNvbHVtbkRlZmluaXRpb25zKHRhYmxlOiBzdHJpbmcsIGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdKTogQ29sdW1uRGVmaW5pdGlvblJlc3VsdCB7XG4gIGNvbnN0IHJlc3VsdDogQ29sdW1uRGVmaW5pdGlvblJlc3VsdCA9IHtcbiAgICBidWlsZGVyOiBbXSxcbiAgICByYXc6IFtdLFxuICB9O1xuXG4gIGZvciAoY29uc3QgY29sdW1uIG9mIGNvbHVtbnMpIHtcbiAgICAvLyBHZW5lcmF0ZWQgQ29sdW1u7J2AIHJhd+uhnCDsspjrpqxcbiAgICBpZiAoY29sdW1uLmdlbmVyYXRlZCkge1xuICAgICAgcmVzdWx0LnJhdy5wdXNoKGdlbkdlbmVyYXRlZENvbHVtbkRlZmluaXRpb24odGFibGUsIGNvbHVtbikpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8g7J2867CYIOy7rOufvOydgCBidWlsZGVy66GcIOyymOumrFxuICAgIHJlc3VsdC5idWlsZGVyLnB1c2goZ2VuTm9ybWFsQ29sdW1uRGVmaW5pdGlvbihjb2x1bW4pKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogR2VuZXJhdGVkIENvbHVtbiDsoJXsnZgg7IOd7ISxIChBTFRFUiBUQUJMRSBBREQgQ09MVU1OIOyCrOyaqSlcbiAqL1xuZnVuY3Rpb24gZ2VuR2VuZXJhdGVkQ29sdW1uRGVmaW5pdGlvbih0YWJsZTogc3RyaW5nLCBjb2x1bW46IE1pZ3JhdGlvbkNvbHVtbik6IHN0cmluZyB7XG4gIGlmICghY29sdW1uLmdlbmVyYXRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRlZCBjb2x1bW4gZGVmaW5pdGlvbiByZXF1aXJlZFwiKTtcbiAgfVxuICBjb25zdCBwZ1R5cGUgPSBnZXRQZ1R5cGVGb3JDb2x1bW4oY29sdW1uKTtcbiAgY29uc3Qgc3RvcmFnZVR5cGUgPSBjb2x1bW4uZ2VuZXJhdGVkLnR5cGUgPT09IFwiVklSVFVBTFwiID8gXCIgVklSVFVBTFwiIDogXCIgU1RPUkVEXCI7XG4gIGNvbnN0IG51bGxhYmxlQ2xhdXNlID0gY29sdW1uLm51bGxhYmxlID8gXCJcIiA6IFwiIE5PVCBOVUxMXCI7XG4gIHJldHVybiBgYXdhaXQga25leC5yYXcoXFxgQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT0xVTU4gXCIke2NvbHVtbi5uYW1lfVwiICR7cGdUeXBlfSBHRU5FUkFURUQgQUxXQVlTIEFTICgke2NvbHVtbi5nZW5lcmF0ZWQuZXhwcmVzc2lvbn0pJHtzdG9yYWdlVHlwZX0ke251bGxhYmxlQ2xhdXNlfVxcYCk7YDtcbn1cblxuLyoqXG4gKiDsnbzrsJgg7Lus65+8IOygleydmCDsg53shLEgKHRhYmxlLnh4eCgpIOyytOyduClcbiAqL1xuZnVuY3Rpb24gZ2VuTm9ybWFsQ29sdW1uRGVmaW5pdGlvbihjb2x1bW46IE1pZ3JhdGlvbkNvbHVtbik6IHN0cmluZyB7XG4gIGNvbnN0IGNoYWluczogc3RyaW5nW10gPSBbXTtcblxuICBpZiAoY29sdW1uLm5hbWUgPT09IFwiaWRcIikge1xuICAgIC8vIFBLIO2DgOyeheyXkCDrlLDrpbgg67aE6riwIOyymOumrFxuICAgIGlmIChjb2x1bW4udHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgLy8gc3RyaW5nIFBLOiBsZW5ndGjqsIAg7J6I7Jy866m0IHZhcmNoYXIsIOyXhuycvOuptCB0ZXh0XG4gICAgICBpZiAoY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBgdGFibGUuc3RyaW5nKCdpZCcsICR7Y29sdW1uLmxlbmd0aH0pLnByaW1hcnkoKS5ub3ROdWxsYWJsZSgpO2A7XG4gICAgICB9XG4gICAgICByZXR1cm4gYHRhYmxlLnRleHQoJ2lkJykucHJpbWFyeSgpLm5vdE51bGxhYmxlKCk7YDtcbiAgICB9XG4gICAgaWYgKGNvbHVtbi50eXBlID09PSBcInV1aWRcIikge1xuICAgICAgcmV0dXJuIGB0YWJsZS51dWlkKCdpZCcpLnByaW1hcnkoKS5ub3ROdWxsYWJsZSgpO2A7XG4gICAgfVxuICAgIC8vIOq4sOyhtCBpbnRlZ2VyIFBLICjquLDrs7jqsJIpXG4gICAgcmV0dXJuIGB0YWJsZS5pbmNyZW1lbnRzKCkucHJpbWFyeSgpO2A7XG4gIH1cblxuICAvLyDrsLDsl7Qg7YOA7J6FIOyymOumrFxuICBpZiAoY29sdW1uLnR5cGUuZW5kc1dpdGgoXCJbXVwiKSkge1xuICAgIGNvbnN0IGVsZW1lbnRUeXBlID0gY29sdW1uLnR5cGUuc2xpY2UoMCwgLTIpOyAvLyBcImludGVnZXJbXVwiIC0+IFwiaW50ZWdlclwiXG4gICAgY29uc3QgcGdUeXBlID0gZ2V0UGdBcnJheVR5cGUoY29sdW1uLCBlbGVtZW50VHlwZSk7XG4gICAgY2hhaW5zLnB1c2goYHNwZWNpZmljVHlwZSgnJHtjb2x1bW4ubmFtZX0nLCAnJHtwZ1R5cGV9JylgKTtcbiAgfSBlbHNlIGlmIChjb2x1bW4udHlwZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgIC8vIEtuZXjripQgdmVjdG9yIO2DgOyeheydhCDsp4HsoJEg7KeA7JuQ7ZWY7KeAIOyViuycvOuvgOuhnCBzcGVjaWZpY1R5cGUg7IKs7JqpXG4gICAgY2hhaW5zLnB1c2goYHNwZWNpZmljVHlwZSgnJHtjb2x1bW4ubmFtZX0nLCAndmVjdG9yKCR7Y29sdW1uLmRpbWVuc2lvbnN9KScpYCk7XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwibnVtYmVyT3JOdW1lcmljXCIpIHtcbiAgICAvLyBudW1iZXJcbiAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwicmVhbFwiKSB7XG4gICAgICBjaGFpbnMucHVzaChgZmxvYXQoJyR7Y29sdW1uLm5hbWV9JylgKTtcbiAgICB9IGVsc2UgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcImRvdWJsZSBwcmVjaXNpb25cIikge1xuICAgICAgY2hhaW5zLnB1c2goYGRvdWJsZSgnJHtjb2x1bW4ubmFtZX0nKWApO1xuICAgIH0gZWxzZSBpZiAoKGNvbHVtbi5udW1iZXJUeXBlID8/IFwibnVtZXJpY1wiKSA9PT0gXCJudW1lcmljXCIpIHtcbiAgICAgIGNoYWlucy5wdXNoKGBkZWNpbWFsKCcke2NvbHVtbi5uYW1lfScsICR7Y29sdW1uLnByZWNpc2lvbn0sICR7Y29sdW1uLnNjYWxlfSlgKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAvLyBzdHJpbmdcbiAgICBpZiAoY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjaGFpbnMucHVzaChgc3RyaW5nKCcke2NvbHVtbi5uYW1lfScsICR7Y29sdW1uLmxlbmd0aH0pYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoYWlucy5wdXNoKGB0ZXh0KCcke2NvbHVtbi5uYW1lfScpYCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGNvbHVtbi50eXBlID09PSBcImRhdGVcIikge1xuICAgIC8vIGRhdGVcbiAgICBjaGFpbnMucHVzaChcbiAgICAgIGB0aW1lc3RhbXAoJyR7Y29sdW1uLm5hbWV9JywgeyB1c2VUejogdHJ1ZSwgcHJlY2lzaW9uOiAke2NvbHVtbi5wcmVjaXNpb24gPz8gM30gfSlgLFxuICAgICk7XG4gIH0gZWxzZSBpZiAoY29sdW1uLnR5cGUgPT09IFwianNvblwiKSB7XG4gICAgLy8ganNvblxuICAgIGNoYWlucy5wdXNoKGBqc29uYignJHtjb2x1bW4ubmFtZX0nKWApO1xuICB9IGVsc2Uge1xuICAgIC8vIHR5cGUsIGxlbmd0aFxuICAgIGxldCBleHRyYVR5cGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBjaGFpbnMucHVzaChcbiAgICAgIGAke2NvbHVtbi50eXBlfSgnJHtjb2x1bW4ubmFtZX0nJHtcbiAgICAgICAgY29sdW1uLmxlbmd0aCA/IGAsICR7Y29sdW1uLmxlbmd0aH1gIDogXCJcIlxuICAgICAgfSR7ZXh0cmFUeXBlID8gYCwgJyR7ZXh0cmFUeXBlfSdgIDogXCJcIn0pYCxcbiAgICApO1xuICB9XG5cbiAgLy8gbnVsbGFibGVcbiAgY2hhaW5zLnB1c2goY29sdW1uLm51bGxhYmxlID8gXCJudWxsYWJsZSgpXCIgOiBcIm5vdE51bGxhYmxlKClcIik7XG5cbiAgLy8gZGVmYXVsdFRvXG4gIGlmIChjb2x1bW4uZGVmYXVsdFRvICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIGNvbHVtbi5kZWZhdWx0VG8gPT09IFwic3RyaW5nXCIgJiYgY29sdW1uLmRlZmF1bHRUby5zdGFydHNXaXRoKGBcImApKSB7XG4gICAgICBjaGFpbnMucHVzaChgZGVmYXVsdFRvKCR7Y29sdW1uLmRlZmF1bHRUb30pYCk7XG4gICAgfSBlbHNlIGlmIChjb2x1bW4udHlwZSA9PT0gXCJqc29uXCIgJiYgdHlwZW9mIGNvbHVtbi5kZWZhdWx0VG8uc3RhcnRzV2l0aCgnXCInKSkge1xuICAgICAgY2hhaW5zLnB1c2goYGRlZmF1bHRUbyhrbmV4LnJhdyhcIiR7Y29sdW1uLmRlZmF1bHRUby5yZXBsYWNlQWxsKCdcIicsIFwiJ1wiKX06Ompzb25iXCIpKWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjaGFpbnMucHVzaChgZGVmYXVsdFRvKGtuZXgucmF3KCcke2NvbHVtbi5kZWZhdWx0VG99JykpYCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGB0YWJsZS4ke2NoYWlucy5qb2luKFwiLlwiKX07YDtcbn1cblxuLyoqXG4gKiBNaWdyYXRpb25Db2x1bW7snZgg7YOA7J6F7J2EIFBvc3RncmVTUUwg7YOA7J6FIOusuOyekOyXtOuhnCDrs4DtmZhcbiAqL1xuZnVuY3Rpb24gZ2V0UGdUeXBlRm9yQ29sdW1uKGNvbHVtbjogTWlncmF0aW9uQ29sdW1uKTogc3RyaW5nIHtcbiAgaWYgKGNvbHVtbi50eXBlLmVuZHNXaXRoKFwiW11cIikpIHtcbiAgICBjb25zdCBlbGVtZW50VHlwZSA9IGNvbHVtbi50eXBlLnNsaWNlKDAsIC0yKTtcbiAgICByZXR1cm4gZ2V0UGdBcnJheVR5cGUoY29sdW1uLCBlbGVtZW50VHlwZSk7XG4gIH1cblxuICBzd2l0Y2ggKGNvbHVtbi50eXBlKSB7XG4gICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgcmV0dXJuIGNvbHVtbi5sZW5ndGggIT09IHVuZGVmaW5lZCA/IGB2YXJjaGFyKCR7Y29sdW1uLmxlbmd0aH0pYCA6IFwidGV4dFwiO1xuICAgIGNhc2UgXCJiaWdJbnRlZ2VyXCI6XG4gICAgICByZXR1cm4gXCJiaWdpbnRcIjtcbiAgICBjYXNlIFwibnVtYmVyT3JOdW1lcmljXCI6XG4gICAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwicmVhbFwiKSByZXR1cm4gXCJyZWFsXCI7XG4gICAgICBpZiAoY29sdW1uLm51bWJlclR5cGUgPT09IFwiZG91YmxlIHByZWNpc2lvblwiKSByZXR1cm4gXCJkb3VibGUgcHJlY2lzaW9uXCI7XG4gICAgICByZXR1cm4gYG51bWVyaWMoJHtjb2x1bW4ucHJlY2lzaW9ufSwgJHtjb2x1bW4uc2NhbGV9KWA7XG4gICAgY2FzZSBcImRhdGVcIjpcbiAgICAgIHJldHVybiBcInRpbWVzdGFtcHR6XCI7XG4gICAgY2FzZSBcImpzb25cIjpcbiAgICAgIHJldHVybiBcImpzb25iXCI7XG4gICAgY2FzZSBcInZlY3RvclwiOlxuICAgICAgcmV0dXJuIGB2ZWN0b3IoJHtjb2x1bW4uZGltZW5zaW9uc30pYDtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGNvbHVtbi50eXBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFBnQXJyYXlUeXBlKGNvbHVtbjogTWlncmF0aW9uQ29sdW1uLCBlbGVtZW50VHlwZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcIm51bWJlck9yTnVtZXJpY1wiKSB7XG4gICAgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcInJlYWxcIikgcmV0dXJuIFwicmVhbFtdXCI7XG4gICAgaWYgKGNvbHVtbi5udW1iZXJUeXBlID09PSBcImRvdWJsZSBwcmVjaXNpb25cIikgcmV0dXJuIFwiZG91YmxlIHByZWNpc2lvbltdXCI7XG4gICAgcmV0dXJuIGBudW1lcmljKCR7Y29sdW1uLnByZWNpc2lvbn0sICR7Y29sdW1uLnNjYWxlfSlbXWA7XG4gIH1cbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIGNvbHVtbi5sZW5ndGggPyBgdmFyY2hhcigke2NvbHVtbi5sZW5ndGh9KVtdYCA6IFwidGV4dFtdXCI7XG4gIH1cbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImRhdGVcIikgcmV0dXJuIFwidGltZXN0YW1wdHpbXVwiO1xuICBpZiAoZWxlbWVudFR5cGUgPT09IFwiaW50ZWdlclwiKSByZXR1cm4gXCJpbnRlZ2VyW11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImJpZ0ludGVnZXJcIikgcmV0dXJuIFwiYmlnaW50W11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcImJvb2xlYW5cIikgcmV0dXJuIFwiYm9vbGVhbltdXCI7XG4gIGlmIChlbGVtZW50VHlwZSA9PT0gXCJ1dWlkXCIpIHJldHVybiBcInV1aWRbXVwiO1xuICBpZiAoZWxlbWVudFR5cGUgPT09IFwiZW51bVwiKSByZXR1cm4gXCJ0ZXh0W11cIjtcbiAgaWYgKGVsZW1lbnRUeXBlID09PSBcInZlY3RvclwiKSByZXR1cm4gYHZlY3Rvcigke2NvbHVtbi5kaW1lbnNpb25zfSlbXWA7XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFycmF5IGVsZW1lbnQgdHlwZTogJHtlbGVtZW50VHlwZX1gKTtcbn1cblxuLyoqXG4gKiDqsJzrs4Qg7J24642x7IqkIOygleydmCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4OiBNaWdyYXRpb25JbmRleCwgdGFibGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChpbmRleC50eXBlID09PSBcImhuc3dcIiB8fCBpbmRleC50eXBlID09PSBcIml2ZmZsYXRcIikge1xuICAgIHJldHVybiBnZW5WZWN0b3JJbmRleERlZmluaXRpb24oaW5kZXgsIHRhYmxlKTtcbiAgfVxuXG4gIGlmIChpbmRleC51c2luZyA9PT0gXCJwZ3Jvb25nYVwiKSB7XG4gICAgcmV0dXJuIGdlblBncm9vbmdhSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSk7XG4gIH1cblxuICBjb25zdCBtZXRob2RNYXAgPSB7XG4gICAgaW5kZXg6IFwiSU5ERVhcIixcbiAgICB1bmlxdWU6IFwiVU5JUVVFIElOREVYXCIsXG4gIH07XG5cbiAgY29uc3QgbnVsbHNOb3REaXN0aW5jdENsYXVzZSA9XG4gICAgaW5kZXgudHlwZSA9PT0gXCJ1bmlxdWVcIiAmJiBpbmRleC5udWxsc05vdERpc3RpbmN0ICE9PSB1bmRlZmluZWRcbiAgICAgID8gYCBOVUxMUyAke2luZGV4Lm51bGxzTm90RGlzdGluY3QgPyBcIk5PVCBESVNUSU5DVFwiIDogXCJESVNUSU5DVFwifWBcbiAgICAgIDogXCJcIjtcblxuICBjb25zdCB1c2luZ0NsYXVzZSA9IGluZGV4LnVzaW5nID09PSB1bmRlZmluZWQgPyBcIlwiIDogYFVTSU5HICR7aW5kZXgudXNpbmd9YDtcblxuICByZXR1cm4gYGF3YWl0IGtuZXgucmF3KFxuICBcXGBDUkVBVEUgJHttZXRob2RNYXBbaW5kZXgudHlwZV19ICR7aW5kZXgubmFtZX0gT04gJHt0YWJsZX0gJHt1c2luZ0NsYXVzZX0oJHtpbmRleC5jb2x1bW5zXG4gICAgLm1hcCgoY29sKSA9PiB7XG4gICAgICBjb25zdCBvcGNsYXNzQ2xhdXNlID0gKCgpID0+IHtcbiAgICAgICAgY29uc3Qgb3BjbGFzcyA9IGdldEluZGV4Q29sdW1uT3BjbGFzcyhjb2wpO1xuICAgICAgICByZXR1cm4gb3BjbGFzcyA/IGAgJHtvcGNsYXNzfWAgOiBcIlwiO1xuICAgICAgfSkoKTtcblxuICAgICAgLy8g7KCV66CsIOyYteyFmOydgCBidHJlZeunjCDsgqzsmqkg6rCA64qlXG4gICAgICBpZiAoaW5kZXgudXNpbmcgIT09IFwiYnRyZWVcIiAmJiBpbmRleC51c2luZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBgJHtjb2wubmFtZX0ke29wY2xhc3NDbGF1c2V9YDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc29ydE9yZGVyQ2xhdXNlID0gY29sLnNvcnRPcmRlciA9PT0gdW5kZWZpbmVkID8gXCJcIiA6IGAgJHtjb2wuc29ydE9yZGVyfWA7XG4gICAgICBjb25zdCBudWxsc0ZpcnN0Q2xhdXNlID1cbiAgICAgICAgY29sLm51bGxzRmlyc3QgPT09IHVuZGVmaW5lZCA/IFwiXCIgOiBgIE5VTExTICR7Y29sLm51bGxzRmlyc3QgPyBcIkZJUlNUXCIgOiBcIkxBU1RcIn1gO1xuICAgICAgcmV0dXJuIGAke2NvbC5uYW1lfSR7b3BjbGFzc0NsYXVzZX0ke3NvcnRPcmRlckNsYXVzZX0ke251bGxzRmlyc3RDbGF1c2V9YDtcbiAgICB9KVxuICAgIC5qb2luKFwiLCBcIil9KSR7bnVsbHNOb3REaXN0aW5jdENsYXVzZX07XFxgXG4gICk7YDtcbn1cblxuZnVuY3Rpb24gZ2VuUGdyb29uZ2FJbmRleERlZmluaXRpb24oaW5kZXg6IE1pZ3JhdGlvbkluZGV4LCB0YWJsZTogc3RyaW5nKSB7XG4gIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0QnlUYWJsZSh0YWJsZSk7XG5cbiAgLy8g67O17ZWpIOyduOuNseyKpOyduCDqsr3smrAgQVJSQVkg7IKs7JqpXG4gIGNvbnN0IGNvbHVtbkNsYXVzZSA9ICgoKSA9PiB7XG4gICAgaWYgKGluZGV4LmNvbHVtbnMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb25zdCBjb2x1bW4gPSBlbnRpdHkucHJvcHNEaWN0W2luZGV4LmNvbHVtbnNbMF0ubmFtZV07XG4gICAgICBjb25zdCBvcHRpb24gPSBnZXRQZ3Jvb25nYUNvbHVtbk9wdGlvbihjb2x1bW4pO1xuICAgICAgcmV0dXJuIGAke2luZGV4LmNvbHVtbnNbMF0ubmFtZX0ke29wdGlvbiA/IGAgJHtvcHRpb259YCA6IFwiXCJ9YDtcbiAgICB9XG5cbiAgICByZXR1cm4gYChBUlJBWVske2luZGV4LmNvbHVtbnMubWFwKChjb2wpID0+IGAke2NvbC5uYW1lfTo6dGV4dGApLmpvaW4oXCIsXCIpfV0pYDtcbiAgfSkoKTtcblxuICByZXR1cm4gYGF3YWl0IGtuZXgucmF3KFxuICBcXGBDUkVBVEUgSU5ERVggJHtpbmRleC5uYW1lfSBPTiAke3RhYmxlfSBVU0lORyBwZ3Jvb25nYSAoJHtjb2x1bW5DbGF1c2V9KSBXSVRIICh0b2tlbml6ZXI9J1Rva2VuTWVjYWInKTtcXGBcbiAgKWA7XG59XG5cbi8qKlxuICogUEdyb29uZ2Eg7Lus65+8IOyYteyFmCDstpTstpxcbiAqXG4gKiBGdWxsVGV4dCDsmKTtjbzroIjsnbTthLDrpbwg7KeA7JuQ7ZWY64qUIOqyveyasCDsmrDshKAg7ISk7KCVLCDrgpjrqLjsp4DripQg65SU7Y+07Yq4IOydtOyaqVxuICogQGxpbmsgaHR0cHM6Ly9wZ3Jvb25nYS5naXRodWIuaW8vcmVmZXJlbmNlXG4gKi9cbmZ1bmN0aW9uIGdldFBncm9vbmdhQ29sdW1uT3B0aW9uKGNvbHVtbjogRW50aXR5UHJvcCkge1xuICBpZiAoY29sdW1uLnR5cGUgPT09IFwic3RyaW5nXCIgJiYgY29sdW1uLmxlbmd0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIFwicGdyb29uZ2FfdmFyY2hhcl9mdWxsX3RleHRfc2VhcmNoX29wc192MlwiO1xuICB9IGVsc2UgaWYgKGNvbHVtbi50eXBlID09PSBcImpzb25cIikge1xuICAgIHJldHVybiBcInBncm9vbmdhX2pzb25iX2Z1bGxfdGV4dF9zZWFyY2hfb3BzX3YyXCI7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uXG4gKiAtIEhOU1cgKEhpZXJhcmNoaWNhbCBOYXZpZ2FibGUgU21hbGwgV29ybGQpOiDripDrprAg67mM65OcLCDruaDrpbgg6rKA7IOJIOyGjeuPhCwg64aS7J2AIOuplOuqqOumrCDrsI8g7KCV7ZmV64+EXG4gKiAtIElWRkZsYXQgKEludmVydGVkIEZpbGUgd2l0aCBGbGF0IENvbXByZXNzaW9uKTog67mg66W4IOu5jOuTnCwg7KSR6rCEIOqygOyDiSDsho3rj4QsIOuCruydgCDrqZTrqqjrpqxcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gSE5TVyDsnbjrjbHsiqQgKOq2jOyepSAtIOu5oOuluCDqsoDsg4ksIOuGkuydgCDsoJXtmZXrj4QpXG4gKiBDUkVBVEUgSU5ERVggaWR4X2VtYmVkZGluZyBPTiBpdGVtcyBVU0lORyBobnN3IChlbWJlZGRpbmcgdmVjdG9yX2Nvc2luZV9vcHMpIFdJVEggKG0gPSAxNiwgZWZfY29uc3RydWN0aW9uID0gNjQpO1xuICpcbiAqIC8vIElWRkZsYXQg7J24642x7IqkICjrjIDsmqnrn4kg642w7J207YSwLCDruYTsmqkg7KSR7JqUIOyLnClcbiAqIENSRUFURSBJTkRFWCBpZHhfZW1iZWRkaW5nIE9OIGl0ZW1zIFVTSU5HIGl2ZmZsYXQgKGVtYmVkZGluZyB2ZWN0b3JfY29zaW5lX29wcykgV0lUSCAobGlzdHMgPSAxMDApO1xuICovXG5mdW5jdGlvbiBnZW5WZWN0b3JJbmRleERlZmluaXRpb24oaW5kZXg6IE1pZ3JhdGlvbkluZGV4LCB0YWJsZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY29sdW1uID0gaW5kZXguY29sdW1uc1swXTtcbiAgY29uc3QgdmVjdG9yT3BzID0gZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbikgPz8gXCJ2ZWN0b3JfY29zaW5lX29wc1wiO1xuXG4gIC8vIEhOU1cgKEhpZXJhcmNoaWNhbCBOYXZpZ2FibGUgU21hbGwgV29ybGQpIC0g6raM7J6lOiDruaDrpbgg6rKA7IOJLCDrhpLsnYAg7KCV7ZmV64+EXG4gIGlmIChpbmRleC50eXBlID09PSBcImhuc3dcIikge1xuICAgIGNvbnN0IG0gPSBpbmRleC5tID8/IDE2O1xuICAgIGNvbnN0IGVmQ29uc3RydWN0aW9uID0gaW5kZXguZWZDb25zdHJ1Y3Rpb24gPz8gNjQ7XG4gICAgcmV0dXJuIGBhd2FpdCBrbmV4LnJhdyhcXGBDUkVBVEUgSU5ERVggJHtpbmRleC5uYW1lfSBPTiAke3RhYmxlfSBVU0lORyBobnN3ICgke2NvbHVtbi5uYW1lfSAke3ZlY3Rvck9wc30pIFdJVEggKG0gPSAke219LCBlZl9jb25zdHJ1Y3Rpb24gPSAke2VmQ29uc3RydWN0aW9ufSlcXGApO2A7XG4gIH1cblxuICAvLyBJVkZGbGF0IChJbnZlcnRlZCBGaWxlIHdpdGggRmxhdCBDb21wcmVzc2lvbikgLSDrjIDsmqnrn4ksIOu5hOyaqSDspJHsmpQg7IucXG4gIGlmIChpbmRleC50eXBlID09PSBcIml2ZmZsYXRcIikge1xuICAgIGNvbnN0IGxpc3RzID0gaW5kZXgubGlzdHMgPz8gMTAwO1xuICAgIHJldHVybiBgYXdhaXQga25leC5yYXcoXFxgQ1JFQVRFIElOREVYICR7aW5kZXgubmFtZX0gT04gJHt0YWJsZX0gVVNJTkcgaXZmZmxhdCAoJHtjb2x1bW4ubmFtZX0gJHt2ZWN0b3JPcHN9KSBXSVRIIChsaXN0cyA9ICR7bGlzdHN9KVxcYCk7YDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgVW5rbm93biByYXcgU1FMIGluZGV4IHR5cGU6ICR7aW5kZXgudHlwZX1gKTtcbn1cblxuLyoqXG4gKiDthYzsnbTruJQg7IOd7ISx7ZWY64qUIOy8gOydtOyKpCAtIEZLIOyDneyEsVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUNyZWF0ZUNvZGVfRm9yZWlnbihcbiAgdGFibGU6IHN0cmluZyxcbiAgZm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbik6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZVtdPiB7XG4gIGlmIChmb3JlaWducy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCB7IHVwLCBkb3duIH0gPSBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZvcmVpZ25zKTtcbiAgaWYgKHVwLmxlbmd0aCA9PT0gMCAmJiBkb3duLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIGZvcmVpZ25z6rCAIOyeiOuKlOuNsCDsg53shLHrkJwg7L2U65Oc6rCAIOyXhuuKlCDqsr3smrDripQg67mE7KCV7IOB7KCB7J24IOyDge2ZqeydtOyngOunjCxcbiAgICAvLyDrp4jsnbTqt7jroIjsnbTshZgg7IOd7ISx7J2EIOykkeuLqOyLnO2CpOyngCDslYrqs6Ag67mIIOuwsOyXtOydhCDrsJjtmZjtlanri4jri6QuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW1xuICAgICdpbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjsnLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gdXAoa25leDogS25leCk6IFByb21pc2U8dm9pZD4ge1wiLFxuICAgIGByZXR1cm4ga25leC5zY2hlbWEuYWx0ZXJUYWJsZShcIiR7dGFibGV9XCIsICh0YWJsZSkgPT4ge2AsXG4gICAgXCIvLyBjcmVhdGUgZmtcIixcbiAgICAuLi51cCxcbiAgICBcIn0pO1wiLFxuICAgIFwifVwiLFxuICAgIFwiXCIsXG4gICAgXCJleHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bihrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgYHJldHVybiBrbmV4LnNjaGVtYS5hbHRlclRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCxcbiAgICBcIi8vIGRyb3AgZmtcIixcbiAgICAuLi5kb3duLFxuICAgIFwifSk7XCIsXG4gICAgXCJ9XCIsXG4gIF07XG5cbiAgY29uc3QgZm9yZWlnbktleXNTdHJpbmcgPSBmb3JlaWducy5tYXAoKGZvcmVpZ24pID0+IGZvcmVpZ24uY29sdW1ucy5qb2luKFwiX1wiKSkuam9pbihcIl9cIik7XG4gIHJldHVybiBbXG4gICAge1xuICAgICAgdGFibGUsXG4gICAgICB0eXBlOiBcImZvcmVpZ25cIixcbiAgICAgIHRpdGxlOiBgZm9yZWlnbl9fJHt0YWJsZX1fXyR7Zm9yZWlnbktleXNTdHJpbmd9YCxcbiAgICAgIGZvcm1hdHRlZDogYXdhaXQgZm9ybWF0Q29kZShsaW5lcy5qb2luKFwiXFxuXCIpLCBcInR5cGVzY3JpcHRcIiwgYHNyYy9taWdyYXRpb24vJHt0YWJsZX0udHNgKSxcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIE1pZ3JhdGlvbkZvcmVpZ25bXSDsnb3slrTshJwg7Jm467aA7YKkIGNvbnN0cmFpbnQg7KCV7J2Y7ZWY64qUIOq1rOusuCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2VuRm9yZWlnbkRlZmluaXRpb25zKFxuICB0YWJsZTogc3RyaW5nLFxuICBmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdLFxuKTogeyB1cDogc3RyaW5nW107IGRvd246IHN0cmluZ1tdIH0ge1xuICByZXR1cm4gZm9yZWlnbnMucmVkdWNlKFxuICAgIChyLCBmb3JlaWduKSA9PiB7XG4gICAgICBjb25zdCBjb2x1bW5zU3RyaW5nUXVvdGUgPSBmb3JlaWduLmNvbHVtbnNcbiAgICAgICAgLm1hcCgoY29sKSA9PiBgJyR7Y29sLnJlcGxhY2UoYCR7dGFibGV9LmAsIFwiXCIpfSdgKVxuICAgICAgICAuam9pbihcIixcIik7XG4gICAgICByLnVwLnB1c2goXG4gICAgICAgIGB0YWJsZS5mb3JlaWduKCcke2ZvcmVpZ24uY29sdW1ucy5qb2luKFwiLFwiKX0nKVxuICAgICAgICAgICAgLnJlZmVyZW5jZXMoJyR7Zm9yZWlnbi50b30nKVxuICAgICAgICAgICAgLm9uVXBkYXRlKCcke2ZvcmVpZ24ub25VcGRhdGV9JylcbiAgICAgICAgICAgIC5vbkRlbGV0ZSgnJHtmb3JlaWduLm9uRGVsZXRlfScpYCxcbiAgICAgICk7XG4gICAgICByLmRvd24ucHVzaChgdGFibGUuZHJvcEZvcmVpZ24oWyR7Y29sdW1uc1N0cmluZ1F1b3RlfV0pYCk7XG4gICAgICByZXR1cm4gcjtcbiAgICB9LFxuICAgIHtcbiAgICAgIHVwOiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgIGRvd246IFtdIGFzIHN0cmluZ1tdLFxuICAgIH0sXG4gICk7XG59XG5cbi8qKlxuICog7YWM7J2067iUIOuzgOqyvSDsvIDsnbTsiqQgLSDsu6zrn7wv7J24642x7IqkIOuzgOqyvVxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUFsdGVyQ29kZV9Db2x1bW5BbmRJbmRleGVzKFxuICB0YWJsZTogc3RyaW5nLFxuICBlbnRpdHlDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgZW50aXR5SW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbiAgZGJDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgZGJJbmRleGVzOiBNaWdyYXRpb25JbmRleFtdLFxuICBkYkZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10sXG4gIGNvbXBhcmVEQj86IEtuZXgsXG4pOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICBjb25zdCByZXNvbHZlZEVudGl0eUNvbHVtbnMgPSByZXNvbHZlU2VhcmNoVGV4dENvbHVtbnModGFibGUsIGVudGl0eUNvbHVtbnMpO1xuICBjb25zdCBzZWFyY2hUZXh0Q29sdW1uTmFtZXMgPSBnZXRTZWFyY2hUZXh0Q29sdW1uTmFtZXModGFibGUpO1xuICAvKlxuICAgIOyEuOu2gCDruYTqtZAg7ZuEIOuLpOuluOygkCDssL7slYTshJwg7L2U65OcIOyDneyEsVxuXG4gICAgMS4g7Lus65+86rCv7IiYIOuLpOumhDogTUTsl5Ag7J6I7Jy864KYLCBEQuyXkCDsl4bri6TrqbQg7LaU6rCAXG4gICAgMi4g7Lus65+86rCv7IiYIOuLpOumhDogTUTsl5Ag7JeG7Jy864KYLCBEQuyXkCDsnojri6TrqbQg7IKt7KCcXG4gICAgMy4g6re47Jm4IOy7rOufvCjsu6zrn7wg6rCv7IiY6rCAIOuPmeydvO2VmOqxsOuCmCwg64uk66W4IOqyveyasCDrj5nsnbztlZwg7Lus65+864G866asKSA9PiBhbHRlclxuICAgIDQuIOuLpOuluOqxsCDri6Qg64+Z7J287ZWY6rOgIGluZGV466eMIOuzgOqyveuQmOuKlCDqsr3smrBcblxuICAgICoqIOy7rOufvOuqheydhCDrs4Dqsr3tlZjripQg6rK97Jqw64qUIOuUsOuhnCDtlbjrk6Trp4HtlZjsp4Ag7JWK7J2MXG4gICAgPT4gZHJvcC9hZGQg7ZiV7YOc7J2YIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5zqsIAg7IOd7ISx65CY64qU642wLCDsiJjrj5nsnLzroZwgcmVuYW1lIOy9lOuTnOuhnCDsiJjsoJXtlZjsl6wg7LKY66asXG4gICovXG5cbiAgLy8gUEsoaWQpIOy7rOufvCDtg4DsnoUg67OA6rK9IOqwkOyngCDrsI8g7LKY66asXG4gIGNvbnN0IGVudGl0eUlkQ29sID0gcmVzb2x2ZWRFbnRpdHlDb2x1bW5zLmZpbmQoKGNvbCkgPT4gY29sLm5hbWUgPT09IFwiaWRcIik7XG4gIGNvbnN0IGRiSWRDb2wgPSBkYkNvbHVtbnMuZmluZCgoY29sKSA9PiBjb2wubmFtZSA9PT0gXCJpZFwiKTtcblxuICBpZiAoZW50aXR5SWRDb2wgJiYgZGJJZENvbCAmJiBjb21wYXJlREIpIHtcbiAgICBjb25zdCBpc1BrVHlwZUNoYW5nZWQgPVxuICAgICAgZW50aXR5SWRDb2wudHlwZSAhPT0gZGJJZENvbC50eXBlIHx8IGVudGl0eUlkQ29sLmxlbmd0aCAhPT0gZGJJZENvbC5sZW5ndGg7XG5cbiAgICBpZiAoaXNQa1R5cGVDaGFuZ2VkKSB7XG4gICAgICByZXR1cm4gZ2VuZXJhdGVQa1R5cGVDaGFuZ2VNaWdyYXRpb24oXG4gICAgICAgIHRhYmxlLFxuICAgICAgICBlbnRpdHlJZENvbCxcbiAgICAgICAgZGJJZENvbCxcbiAgICAgICAgcmVzb2x2ZWRFbnRpdHlDb2x1bW5zLFxuICAgICAgICBlbnRpdHlJbmRleGVzLFxuICAgICAgICBkYkNvbHVtbnMsXG4gICAgICAgIGRiSW5kZXhlcyxcbiAgICAgICAgZGJGb3JlaWducyxcbiAgICAgICAgY29tcGFyZURCLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyDqsIEg7Lus65+8IOydtOumhCDquLDspIDsnLzroZwgYWRkLCBkcm9wLCBhbHRlciDsl6zrtoAg7ZmV7J24XG4gIGNvbnN0IGFsdGVyQ29sdW1uc1RvID0gZ2V0QWx0ZXJDb2x1bW5zVG8ocmVzb2x2ZWRFbnRpdHlDb2x1bW5zLCBkYkNvbHVtbnMsIHNlYXJjaFRleHRDb2x1bW5OYW1lcyk7XG5cbiAgLy8g7LaU7Lac65CcIOy7rOufvOuTpOydhCDquLDspIDsnLzroZwg6rCB6rCBIOudvOyduCDsg53shLFcbiAgY29uc3QgYWx0ZXJDb2x1bW5MaW5lc1RvID0gZ2V0QWx0ZXJDb2x1bW5MaW5lc1RvKFxuICAgIGFsdGVyQ29sdW1uc1RvLFxuICAgIHJlc29sdmVkRW50aXR5Q29sdW1ucyxcbiAgICB0YWJsZSxcbiAgICBkYkZvcmVpZ25zLFxuICApO1xuXG4gIC8vIOyduOuNseyKpOydmCBhZGQsIGRyb3Ag7Jes67aAIO2ZleyduFxuICBjb25zdCBhbHRlckluZGV4ZXNUbyA9IGdldEFsdGVySW5kZXhlc1RvKGVudGl0eUluZGV4ZXMsIGRiSW5kZXhlcyk7XG4gIGNvbnN0IHJlY3JlYXRlZFNlYXJjaFRleHRDb2x1bW5OYW1lcyA9IG5ldyBTZXQoXG4gICAgYWx0ZXJDb2x1bW5zVG8uYWx0ZXJcbiAgICAgIC5maWx0ZXIoKGRiQ29sdW1uKSA9PiB7XG4gICAgICAgIGNvbnN0IGVudGl0eUNvbHVtbiA9IHJlc29sdmVkRW50aXR5Q29sdW1ucy5maW5kKChjb2wpID0+IGNvbC5uYW1lID09PSBkYkNvbHVtbi5uYW1lKTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICBzZWFyY2hUZXh0Q29sdW1uTmFtZXMuaGFzKGRiQ29sdW1uLm5hbWUpICYmXG4gICAgICAgICAgZGJDb2x1bW4uZ2VuZXJhdGVkICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICBlbnRpdHlDb2x1bW4/LmdlbmVyYXRlZCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICAgLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ubmFtZSksXG4gICk7XG4gIGNvbnN0IHJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMgPSBkYkluZGV4ZXMuZmlsdGVyKFxuICAgIChpbmRleCkgPT5cbiAgICAgIGluZGV4LmNvbHVtbnMuc29tZSgoeyBuYW1lIH0pID0+IHJlY3JlYXRlZFNlYXJjaFRleHRDb2x1bW5OYW1lcy5oYXMobmFtZSkpICYmXG4gICAgICAhYWx0ZXJJbmRleGVzVG8uZHJvcC5zb21lKChkcm9wSW5kZXgpID0+IGRyb3BJbmRleC5uYW1lID09PSBpbmRleC5uYW1lKSxcbiAgKTtcbiAgY29uc3QgcmVjcmVhdGVkU2VhcmNoVGV4dEVudGl0eUluZGV4ZXMgPSBlbnRpdHlJbmRleGVzLmZpbHRlcihcbiAgICAoaW5kZXgpID0+XG4gICAgICBpbmRleC5jb2x1bW5zLnNvbWUoKHsgbmFtZSB9KSA9PiByZWNyZWF0ZWRTZWFyY2hUZXh0Q29sdW1uTmFtZXMuaGFzKG5hbWUpKSAmJlxuICAgICAgIWFsdGVySW5kZXhlc1RvLmFkZC5zb21lKChhZGRJbmRleCkgPT4gYWRkSW5kZXgubmFtZSA9PT0gaW5kZXgubmFtZSksXG4gICk7XG4gIGNvbnN0IGltcGxpY2l0bHlEcm9wcGVkRGJJbmRleGVzID0gYWx0ZXJJbmRleGVzVG8uZHJvcC5maWx0ZXIoKGluZGV4KSA9PlxuICAgIGluZGV4LmNvbHVtbnMuZXZlcnkoKHsgbmFtZSB9KSA9PiBhbHRlckNvbHVtbnNUby5kcm9wLnNvbWUoKGNvbHVtbikgPT4gY29sdW1uLm5hbWUgPT09IG5hbWUpKSxcbiAgKTtcblxuICAvLyDsnbjrjbHsiqTqsIAg7IKt7KCc65CY64qUIOqyveyasCwg7Lus65+86rO8IOqwmeydtCDsgq3soJzrkJwg7LyA7J207Iqk7JeQ64qUIGRyb3Dsl5DshJwg7KCc7Jm47ZW07JW87ZWoIVxuICBjb25zdCBpbmRleE5lZWRzVG9Ecm9wID0gYWx0ZXJJbmRleGVzVG8uZHJvcC5maWx0ZXIoXG4gICAgKGluZGV4KSA9PiAhaW1wbGljaXRseURyb3BwZWREYkluZGV4ZXMuc29tZSgoZHJvcHBlZEluZGV4KSA9PiBkcm9wcGVkSW5kZXgubmFtZSA9PT0gaW5kZXgubmFtZSksXG4gICk7XG5cbiAgLy8g67mIIOy9lOuTnCDsg53shLEg67Cp7KeAXG4gIGNvbnN0IGhhc1VwQ2hhbmdlcyA9XG4gICAgYWx0ZXJDb2x1bW5MaW5lc1RvLmFkZC51cC5idWlsZGVyLmxlbmd0aCA+IDAgfHxcbiAgICBhbHRlckNvbHVtbkxpbmVzVG8uYWRkLnVwLnJhdy5sZW5ndGggPiAwIHx8XG4gICAgYWx0ZXJDb2x1bW5MaW5lc1RvLmRyb3AudXAuYnVpbGRlci5sZW5ndGggPiAwIHx8XG4gICAgYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLnVwLmJ1aWxkZXIubGVuZ3RoID4gMCB8fFxuICAgIGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci51cC5yYXcubGVuZ3RoID4gMCB8fFxuICAgIGFsdGVySW5kZXhlc1RvLmFkZC5sZW5ndGggPiAwIHx8XG4gICAgaW5kZXhOZWVkc1RvRHJvcC5sZW5ndGggPiAwIHx8XG4gICAgcmVjcmVhdGVkU2VhcmNoVGV4dERiSW5kZXhlcy5sZW5ndGggPiAwO1xuICBpZiAoIWhhc1VwQ2hhbmdlcykge1xuICAgIC8vIOuzgOqyveyCrO2VreydtCDsl4bsnLzrqbQg67mIIOuwsOyXtCDrsJjtmZhcbiAgICByZXR1cm4gW107XG4gIH1cbiAgTmFpdGUudChcIm1pZ3JhdG9yOmdlbmVyYXRlQWx0ZXJDb2RlX0NvbHVtbkFuZEluZGV4ZXM6ZGVidWdcIiwge1xuICAgIFwiYWx0ZXJDb2x1bW5zVG8uYWRkLmxlbmd0aFwiOiBhbHRlckNvbHVtbnNUby5hZGQubGVuZ3RoLFxuICAgIFwiYWx0ZXJDb2x1bW5zVG8uZHJvcC5sZW5ndGhcIjogYWx0ZXJDb2x1bW5zVG8uZHJvcC5sZW5ndGgsXG4gICAgXCJhbHRlckNvbHVtbnNUby5hbHRlci5sZW5ndGhcIjogYWx0ZXJDb2x1bW5zVG8uYWx0ZXIubGVuZ3RoLFxuICAgIFwiYWx0ZXJJbmRleGVzVG8uYWRkLmxlbmd0aFwiOiBhbHRlckluZGV4ZXNUby5hZGQubGVuZ3RoLFxuICAgIFwiYWx0ZXJJbmRleGVzVG8uZHJvcC5sZW5ndGhcIjogYWx0ZXJJbmRleGVzVG8uZHJvcC5sZW5ndGgsXG4gICAgXCJpbmRleE5lZWRzVG9Ecm9wLmxlbmd0aFwiOiBpbmRleE5lZWRzVG9Ecm9wLmxlbmd0aCxcbiAgfSk7XG4gIC8vIE5haXRlLnQoXCJtaWdyYXRvcjpnZW5lcmF0ZUFsdGVyQ29kZV9Db2x1bW5BbmRJbmRleGVzOmFsdGVyQ29sdW1uc1RvXCIsIGFsdGVyQ29sdW1uc1RvKTtcblxuICAvLyBUT0RPOiDsnbjrjbHsiqTrqoUg67OA6rK965CcIOqyveyasCDsspjrpqxcblxuICAvLyB0YWJsZSBidWlsZGVyIOuplOyEnOuTnOuhnCDsi6TtlontlaAg7L2U65OcIChkcm9wIOKGkiBhZGQg4oaSIGFsdGVyIOyInOyEnClcbiAgY29uc3QgdXBCdWlsZGVyTGluZXMgPSBbXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLnVwLmJ1aWxkZXIubGVuZ3RoID4gMCA/IGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLnVwLmJ1aWxkZXIgOiBbXSksXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hZGQudXAuYnVpbGRlci5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFkZC51cC5idWlsZGVyIDogW10pLFxuICAgIC4uLnJlY3JlYXRlZFNlYXJjaFRleHREYkluZGV4ZXMubWFwKGdlbkluZGV4RHJvcERlZmluaXRpb24pLFxuICAgIC4uLihhbHRlckNvbHVtbkxpbmVzVG8uYWx0ZXIudXAuYnVpbGRlci5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLnVwLmJ1aWxkZXIgOiBbXSksXG4gICAgLi4uaW5kZXhOZWVkc1RvRHJvcC5tYXAoZ2VuSW5kZXhEcm9wRGVmaW5pdGlvbiksXG4gIF07XG5cbiAgLy8ga25leC5yYXcoKeuhnCDsi6TtlontlaAg7L2U65OcXG4gIGNvbnN0IHVwUmF3TGluZXMgPSBbXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hZGQudXAucmF3Lmxlbmd0aCA+IDAgPyBhbHRlckNvbHVtbkxpbmVzVG8uYWRkLnVwLnJhdyA6IFtdKSxcbiAgICAuLi4oYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLnVwLnJhdy5sZW5ndGggPiAwID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLnVwLnJhdyA6IFtdKSxcbiAgICAuLi5yZWNyZWF0ZWRTZWFyY2hUZXh0RW50aXR5SW5kZXhlcy5tYXAoKGluZGV4KSA9PiBnZW5JbmRleERlZmluaXRpb24oaW5kZXgsIHRhYmxlKSksXG4gICAgLi4uYWx0ZXJJbmRleGVzVG8uYWRkLm1hcCgoaW5kZXgpID0+IGdlbkluZGV4RGVmaW5pdGlvbihpbmRleCwgdGFibGUpKSxcbiAgXTtcblxuICAvLyBkb3du7J2AIHVw7J2YIOyXreyInCAoYWRkLmRvd24gPSBkcm9wIHJvbGxiYWNrLCBkcm9wLmRvd24gPSBhZGQgcm9sbGJhY2spXG4gIGNvbnN0IGRvd25CdWlsZGVyTGluZXMgPSBbXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hZGQuZG93bi5idWlsZGVyLmxlbmd0aCA+IDAgPyBhbHRlckNvbHVtbkxpbmVzVG8uYWRkLmRvd24uYnVpbGRlciA6IFtdKSxcbiAgICAuLi5yZWNyZWF0ZWRTZWFyY2hUZXh0RW50aXR5SW5kZXhlcy5tYXAoZ2VuSW5kZXhEcm9wRGVmaW5pdGlvbiksXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5hbHRlci5kb3duLmJ1aWxkZXIubGVuZ3RoID4gMFxuICAgICAgPyBhbHRlckNvbHVtbkxpbmVzVG8uYWx0ZXIuZG93bi5idWlsZGVyXG4gICAgICA6IFtdKSxcbiAgICAuLi4oYWx0ZXJDb2x1bW5MaW5lc1RvLmRyb3AuZG93bi5idWlsZGVyLmxlbmd0aCA+IDBcbiAgICAgID8gYWx0ZXJDb2x1bW5MaW5lc1RvLmRyb3AuZG93bi5idWlsZGVyXG4gICAgICA6IFtdKSxcbiAgICAuLi5hbHRlckluZGV4ZXNUby5hZGRcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChpbmRleCkgPT5cbiAgICAgICAgICAhaW5kZXguY29sdW1ucy5ldmVyeSgoaW5kZXhDb2wpID0+XG4gICAgICAgICAgICBhbHRlckNvbHVtbnNUby5hZGQubWFwKChjb2wpID0+IGNvbC5uYW1lKS5pbmNsdWRlcyhpbmRleENvbC5uYW1lKSxcbiAgICAgICAgICApLFxuICAgICAgKVxuICAgICAgLm1hcChnZW5JbmRleERyb3BEZWZpbml0aW9uKSxcbiAgXTtcblxuICBjb25zdCBkb3duUmF3TGluZXMgPSBbXG4gICAgLi4uKGFsdGVyQ29sdW1uTGluZXNUby5kcm9wLmRvd24ucmF3Lmxlbmd0aCA+IDAgPyBhbHRlckNvbHVtbkxpbmVzVG8uZHJvcC5kb3duLnJhdyA6IFtdKSxcbiAgICAuLi4oYWx0ZXJDb2x1bW5MaW5lc1RvLmFsdGVyLmRvd24ucmF3Lmxlbmd0aCA+IDAgPyBhbHRlckNvbHVtbkxpbmVzVG8uYWx0ZXIuZG93bi5yYXcgOiBbXSksXG4gICAgLi4ucmVjcmVhdGVkU2VhcmNoVGV4dERiSW5kZXhlcy5tYXAoKGluZGV4KSA9PiBnZW5JbmRleERlZmluaXRpb24oaW5kZXgsIHRhYmxlKSksXG4gICAgLi4uaW1wbGljaXRseURyb3BwZWREYkluZGV4ZXMubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICAgIC4uLmluZGV4TmVlZHNUb0Ryb3AubWFwKChpbmRleCkgPT4gZ2VuSW5kZXhEZWZpbml0aW9uKGluZGV4LCB0YWJsZSkpLFxuICBdO1xuXG4gIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtcbiAgICAnaW1wb3J0IHsgS25leCB9IGZyb20gXCJrbmV4XCI7JyxcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwKGtuZXg6IEtuZXgpOiBQcm9taXNlPHZvaWQ+IHtcIixcbiAgICAuLi4odXBCdWlsZGVyTGluZXMubGVuZ3RoID4gMFxuICAgICAgPyBbYGF3YWl0IGtuZXguc2NoZW1hLmFsdGVyVGFibGUoXCIke3RhYmxlfVwiLCAodGFibGUpID0+IHtgLCAuLi51cEJ1aWxkZXJMaW5lcywgXCJ9KTtcIl1cbiAgICAgIDogW10pLFxuICAgIC4uLnVwUmF3TGluZXMsXG4gICAgXCJ9XCIsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3duKGtuZXg6IEtuZXgpOiBQcm9taXNlPHZvaWQ+IHtcIixcbiAgICAuLi4oZG93bkJ1aWxkZXJMaW5lcy5sZW5ndGggPiAwXG4gICAgICA/IFtgYXdhaXQga25leC5zY2hlbWEuYWx0ZXJUYWJsZShcIiR7dGFibGV9XCIsICh0YWJsZSkgPT4ge2AsIC4uLmRvd25CdWlsZGVyTGluZXMsIFwifSk7XCJdXG4gICAgICA6IFtdKSxcbiAgICAuLi5kb3duUmF3TGluZXMsXG4gICAgXCJ9XCIsXG4gIF07XG5cbiAgY29uc3QgZm9ybWF0dGVkID0gYXdhaXQgZm9ybWF0Q29kZShsaW5lcy5qb2luKFwiXFxuXCIpLCBcInR5cGVzY3JpcHRcIiwgYHNyYy9taWdyYXRpb24vJHt0YWJsZX0udHNgKTtcbiAgY29uc3QgdGl0bGUgPSBbXG4gICAgXCJhbHRlclwiLFxuICAgIHRhYmxlLFxuICAgIC4uLihbXCJhZGRcIiwgXCJkcm9wXCIsIFwiYWx0ZXJcIl0gYXMgY29uc3QpXG4gICAgICAubWFwKChhY3Rpb24pID0+IHtcbiAgICAgICAgY29uc3QgbGVuID0gYWx0ZXJDb2x1bW5zVG9bYWN0aW9uXS5sZW5ndGg7XG4gICAgICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgICAgcmV0dXJuIGFjdGlvbiArIGxlbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChwYXJ0KSA9PiBwYXJ0ICE9PSBudWxsKSxcbiAgXS5qb2luKFwiX1wiKTtcblxuICByZXR1cm4gW1xuICAgIHtcbiAgICAgIHRhYmxlLFxuICAgICAgdGl0bGUsXG4gICAgICBmb3JtYXR0ZWQsXG4gICAgICB0eXBlOiBcIm5vcm1hbFwiLFxuICAgIH0sXG4gIF07XG59XG5cbi8qKlxuICog7Lus65+8IOu5hOq1kOulvCDsnITtlbQgR2VuZXJhdGVkIENvbHVtbuydmCBleHByZXNzaW9u7J2EIOygnOyZuO2VnCDqsJ3ssrTrpbwg7IOd7ISxXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUNvbHVtbkZvckNvbXBhcmlzb24oXG4gIGNvbDogTWlncmF0aW9uQ29sdW1uLFxuICBzZWFyY2hUZXh0Q29sdW1uTmFtZXM6IFNldDxzdHJpbmc+LFxuKTogTWlncmF0aW9uQ29sdW1uIHtcbiAgaWYgKCFjb2wuZ2VuZXJhdGVkKSB7XG4gICAgcmV0dXJuIGNvbDtcbiAgfVxuXG4gIGlmICghc2VhcmNoVGV4dENvbHVtbk5hbWVzLmhhcyhjb2wubmFtZSkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uY29sLFxuICAgICAgZ2VuZXJhdGVkOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uY29sLFxuICAgIGdlbmVyYXRlZDoge1xuICAgICAgLi4uY29sLmdlbmVyYXRlZCxcbiAgICAgIGV4cHJlc3Npb246IGNhbm9uaWNhbGl6ZVNlYXJjaFRleHRHZW5lcmF0ZWRFeHByZXNzaW9uKGNvbC5nZW5lcmF0ZWQuZXhwcmVzc2lvbiksXG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiDqsIEg7Lus65+8IOydtOumhCDquLDspIDsnLzroZwgYWRkLCBkcm9wLCBhbHRlciDsl6zrtoAg7ZmV7J24XG4gKi9cbmZ1bmN0aW9uIGdldEFsdGVyQ29sdW1uc1RvKFxuICBlbnRpdHlDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgZGJDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgc2VhcmNoVGV4dENvbHVtbk5hbWVzOiBTZXQ8c3RyaW5nPixcbikge1xuICBjb25zdCBjb2x1bW5zVG8gPSB7XG4gICAgYWRkOiBbXSBhcyBNaWdyYXRpb25Db2x1bW5bXSxcbiAgICBkcm9wOiBbXSBhcyBNaWdyYXRpb25Db2x1bW5bXSxcbiAgICBhbHRlcjogW10gYXMgTWlncmF0aW9uQ29sdW1uW10sXG4gIH07XG5cbiAgLy8g7Lus65+866qFIOq4sOykgCDruYTqtZBcbiAgY29uc3QgZXh0cmFDb2x1bW5zID0ge1xuICAgIGRiOiBkaWZmKGRiQ29sdW1ucywgZW50aXR5Q29sdW1ucywgKGNvbCkgPT4gW2NvbC5uYW1lLCBjb2wuZ2VuZXJhdGVkPy50eXBlXS5qb2luKFwiLy8vXCIpKSxcbiAgICBlbnRpdHk6IGRpZmYoZW50aXR5Q29sdW1ucywgZGJDb2x1bW5zLCAoY29sKSA9PiBbY29sLm5hbWUsIGNvbC5nZW5lcmF0ZWQ/LnR5cGVdLmpvaW4oXCIvLy9cIikpLFxuICB9O1xuICBpZiAoZXh0cmFDb2x1bW5zLmVudGl0eS5sZW5ndGggPiAwKSB7XG4gICAgY29sdW1uc1RvLmFkZCA9IGNvbHVtbnNUby5hZGQuY29uY2F0KGV4dHJhQ29sdW1ucy5lbnRpdHkpO1xuICB9XG4gIGlmIChleHRyYUNvbHVtbnMuZGIubGVuZ3RoID4gMCkge1xuICAgIGNvbHVtbnNUby5kcm9wID0gY29sdW1uc1RvLmRyb3AuY29uY2F0KGV4dHJhQ29sdW1ucy5kYik7XG4gIH1cblxuICAvLyDrj5nsnbwg7Lus65+866qF7J2YIOyEuOu2gCDtlYTrk5wg67mE6rWQXG4gIGNvbnN0IHNhbWVEYkNvbHVtbnMgPSBpbnRlcnNlY3Rpb25CeShkYkNvbHVtbnMsIGVudGl0eUNvbHVtbnMsIChjb2wpID0+IGNvbC5uYW1lKTtcbiAgY29uc3Qgc2FtZU1kQ29sdW1ucyA9IGludGVyc2VjdGlvbkJ5KGVudGl0eUNvbHVtbnMsIGRiQ29sdW1ucywgKGNvbCkgPT4gY29sLm5hbWUpO1xuICBjb2x1bW5zVG8uYWx0ZXIgPSBkaWZmZXJlbmNlV2l0aChzYW1lRGJDb2x1bW5zLCBzYW1lTWRDb2x1bW5zLCAoYSwgYikgPT5cbiAgICBlcXVhbChcbiAgICAgIG5vcm1hbGl6ZUNvbHVtbkZvckNvbXBhcmlzb24oYSwgc2VhcmNoVGV4dENvbHVtbk5hbWVzKSxcbiAgICAgIG5vcm1hbGl6ZUNvbHVtbkZvckNvbXBhcmlzb24oYiwgc2VhcmNoVGV4dENvbHVtbk5hbWVzKSxcbiAgICApLFxuICApO1xuXG4gIHJldHVybiBjb2x1bW5zVG87XG59XG5cbi8qKlxuICog7LaU7Lac65CcIOy7rOufvOuTpOydhCDquLDspIDsnLzroZwg6rCB6rCBIOudvOyduCDsg53shLFcbiAqL1xuZnVuY3Rpb24gZ2V0QWx0ZXJDb2x1bW5MaW5lc1RvKFxuICBjb2x1bW5zVG86IFJldHVyblR5cGU8dHlwZW9mIGdldEFsdGVyQ29sdW1uc1RvPixcbiAgZW50aXR5Q29sdW1uczogTWlncmF0aW9uQ29sdW1uW10sXG4gIHRhYmxlOiBzdHJpbmcsXG4gIGRiRm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbikge1xuICBjb25zdCBzZWFyY2hUZXh0Q29sdW1uTmFtZXMgPSBnZXRTZWFyY2hUZXh0Q29sdW1uTmFtZXModGFibGUpO1xuICBjb25zdCBsaW5lc1RvID0ge1xuICAgIGFkZDoge1xuICAgICAgdXA6IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICAgIGRvd246IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICB9LFxuICAgIGRyb3A6IHtcbiAgICAgIHVwOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgICBkb3duOiB7IGJ1aWxkZXI6IFtdIGFzIHN0cmluZ1tdLCByYXc6IFtdIGFzIHN0cmluZ1tdIH0sXG4gICAgfSxcbiAgICBhbHRlcjoge1xuICAgICAgdXA6IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICAgIGRvd246IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICB9LFxuICB9O1xuXG4gIC8vIGFkZCBjb2x1bW5zXG4gIGNvbnN0IGFkZENvbHVtbkRlZnMgPSBnZW5Db2x1bW5EZWZpbml0aW9ucyh0YWJsZSwgY29sdW1uc1RvLmFkZCk7XG4gIGxpbmVzVG8uYWRkLnVwID0ge1xuICAgIGJ1aWxkZXI6IGFkZENvbHVtbkRlZnMuYnVpbGRlci5sZW5ndGggPiAwID8gW1wiLy8gYWRkXCIsIC4uLmFkZENvbHVtbkRlZnMuYnVpbGRlcl0gOiBbXSxcbiAgICByYXc6XG4gICAgICBhZGRDb2x1bW5EZWZzLnJhdy5sZW5ndGggPiAwXG4gICAgICAgID8gW1xuICAgICAgICAgICAgLi4uZ2V0U2VhcmNoVGV4dEhlbHBlckRlZmluaXRpb25zKHRhYmxlLCBjb2x1bW5zVG8uYWRkKSxcbiAgICAgICAgICAgIFwiLy8gYWRkIChnZW5lcmF0ZWQpXCIsXG4gICAgICAgICAgICAuLi5hZGRDb2x1bW5EZWZzLnJhdyxcbiAgICAgICAgICBdXG4gICAgICAgIDogW10sXG4gIH07XG4gIGxpbmVzVG8uYWRkLmRvd24gPSB7XG4gICAgYnVpbGRlcjpcbiAgICAgIGNvbHVtbnNUby5hZGQubGVuZ3RoID4gMFxuICAgICAgICA/IFtcbiAgICAgICAgICAgIFwiLy8gcm9sbGJhY2sgLSBhZGRcIixcbiAgICAgICAgICAgIGB0YWJsZS5kcm9wQ29sdW1ucygke2NvbHVtbnNUby5hZGQubWFwKChjb2wpID0+IGAnJHtjb2wubmFtZX0nYCkuam9pbihcIiwgXCIpfSlgLFxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXSxcbiAgICByYXc6IFtdLFxuICB9O1xuXG4gIC8vIGRyb3DtlaAg7Lus65+87JeQIOqxuOumsCBGSyDssL7quLBcbiAgY29uc3QgZHJvcENvbHVtbk5hbWVzID0gY29sdW1uc1RvLmRyb3AubWFwKChjb2wpID0+IGNvbC5uYW1lKTtcbiAgY29uc3QgZmtUb0Ryb3BCZWZvcmVDb2x1bW4gPSBkYkZvcmVpZ25zLmZpbHRlcigoZmspID0+XG4gICAgZmsuY29sdW1ucy5zb21lKChjb2wpID0+IGRyb3BDb2x1bW5OYW1lcy5pbmNsdWRlcyhjb2wpKSxcbiAgKTtcblxuICBjb25zdCBkcm9wRmtMaW5lcyA9IGZrVG9Ecm9wQmVmb3JlQ29sdW1uLm1hcCgoZmspID0+IHtcbiAgICBjb25zdCBjb2x1bW5zU3RyaW5nUXVvdGUgPSBmay5jb2x1bW5zLm1hcCgoY29sKSA9PiBgJyR7Y29sfSdgKS5qb2luKFwiLFwiKTtcbiAgICByZXR1cm4gYHRhYmxlLmRyb3BGb3JlaWduKFske2NvbHVtbnNTdHJpbmdRdW90ZX1dKWA7XG4gIH0pO1xuXG4gIGNvbnN0IHJlc3RvcmVGa0xpbmVzID0gZ2VuRm9yZWlnbkRlZmluaXRpb25zKHRhYmxlLCBma1RvRHJvcEJlZm9yZUNvbHVtbikudXA7XG5cbiAgLy8gZHJvcOydmCByb2xsYmFja+yLnOyXkOuKlCBnZW5lcmF0ZWQgY29sdW1u64+EIOuzteybkO2VtOyVvCDtlahcbiAgY29uc3QgZHJvcENvbHVtbkRlZnMgPSBnZW5Db2x1bW5EZWZpbml0aW9ucyh0YWJsZSwgY29sdW1uc1RvLmRyb3ApO1xuICBsaW5lc1RvLmRyb3AgPSB7XG4gICAgdXA6IHtcbiAgICAgIGJ1aWxkZXI6IFtcbiAgICAgICAgLi4uKGRyb3BGa0xpbmVzLmxlbmd0aCA+IDBcbiAgICAgICAgICA/IFtcIi8vIGRyb3AgZm9yZWlnbiBrZXlzIG9uIGNvbHVtbnMgdG8gYmUgZHJvcHBlZFwiLCAuLi5kcm9wRmtMaW5lc11cbiAgICAgICAgICA6IFtdKSxcbiAgICAgICAgLi4uKGNvbHVtbnNUby5kcm9wLmxlbmd0aCA+IDBcbiAgICAgICAgICA/IFtcbiAgICAgICAgICAgICAgXCIvLyBkcm9wIGNvbHVtbnNcIixcbiAgICAgICAgICAgICAgYHRhYmxlLmRyb3BDb2x1bW5zKCR7Y29sdW1uc1RvLmRyb3AubWFwKChjb2wpID0+IGAnJHtjb2wubmFtZX0nYCkuam9pbihcIiwgXCIpfSlgLFxuICAgICAgICAgICAgXVxuICAgICAgICAgIDogW10pLFxuICAgICAgXSxcbiAgICAgIHJhdzogW10sXG4gICAgfSxcbiAgICBkb3duOiB7XG4gICAgICBidWlsZGVyOiBbXG4gICAgICAgIC4uLihkcm9wQ29sdW1uRGVmcy5idWlsZGVyLmxlbmd0aCA+IDBcbiAgICAgICAgICA/IFtcIi8vIHJvbGxiYWNrIC0gZHJvcCBjb2x1bW5zXCIsIC4uLmRyb3BDb2x1bW5EZWZzLmJ1aWxkZXJdXG4gICAgICAgICAgOiBbXSksXG4gICAgICAgIC4uLihyZXN0b3JlRmtMaW5lcy5sZW5ndGggPiAwID8gW1wiLy8gcmVzdG9yZSBmb3JlaWduIGtleXNcIiwgLi4ucmVzdG9yZUZrTGluZXNdIDogW10pLFxuICAgICAgXSxcbiAgICAgIHJhdzpcbiAgICAgICAgZHJvcENvbHVtbkRlZnMucmF3Lmxlbmd0aCA+IDBcbiAgICAgICAgICA/IFtcbiAgICAgICAgICAgICAgLi4uZ2V0U2VhcmNoVGV4dEhlbHBlckRlZmluaXRpb25zKHRhYmxlLCBjb2x1bW5zVG8uZHJvcCksXG4gICAgICAgICAgICAgIFwiLy8gcm9sbGJhY2sgLSBkcm9wIGNvbHVtbnMgKGdlbmVyYXRlZClcIixcbiAgICAgICAgICAgICAgLi4uZHJvcENvbHVtbkRlZnMucmF3LFxuICAgICAgICAgICAgXVxuICAgICAgICAgIDogW10sXG4gICAgfSxcbiAgfTtcblxuICAvLyBhbHRlciBjb2x1bW5zIChHZW5lcmF0ZWQgQ29sdW1u7J2AIEFMVEVSIOu2iOqwgO2VmOuvgOuhnCBkcm9wIO2bhCDsnqzsg53shLEpXG4gIGxpbmVzVG8uYWx0ZXIgPSBjb2x1bW5zVG8uYWx0ZXIucmVkdWNlKFxuICAgIChyLCBkYkNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZW50aXR5Q29sdW1uID0gZW50aXR5Q29sdW1ucy5maW5kKChjb2wpID0+IGNvbC5uYW1lID09PSBkYkNvbHVtbi5uYW1lKTtcbiAgICAgIGlmIChlbnRpdHlDb2x1bW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBzZWFyY2hUZXh0Q29sdW1uTmFtZXMuaGFzKGRiQ29sdW1uLm5hbWUpICYmXG4gICAgICAgIGRiQ29sdW1uLmdlbmVyYXRlZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgIGVudGl0eUNvbHVtbi5nZW5lcmF0ZWQgIT09IHVuZGVmaW5lZFxuICAgICAgKSB7XG4gICAgICAgIHIudXAuYnVpbGRlciA9IFtcbiAgICAgICAgICAuLi5yLnVwLmJ1aWxkZXIsXG4gICAgICAgICAgXCIvLyBhbHRlciBnZW5lcmF0ZWQgY29sdW1uXCIsXG4gICAgICAgICAgYHRhYmxlLmRyb3BDb2x1bW5zKCcke2RiQ29sdW1uLm5hbWV9JylgLFxuICAgICAgICBdO1xuICAgICAgICByLnVwLnJhdyA9IFtcbiAgICAgICAgICAuLi5yLnVwLnJhdyxcbiAgICAgICAgICAuLi5nZXRTZWFyY2hUZXh0SGVscGVyRGVmaW5pdGlvbnModGFibGUsIFtlbnRpdHlDb2x1bW5dKSxcbiAgICAgICAgICBcIi8vIGFsdGVyIGdlbmVyYXRlZCBjb2x1bW5cIixcbiAgICAgICAgICBnZW5HZW5lcmF0ZWRDb2x1bW5EZWZpbml0aW9uKHRhYmxlLCBlbnRpdHlDb2x1bW4pLFxuICAgICAgICBdO1xuICAgICAgICByLmRvd24uYnVpbGRlciA9IFtcbiAgICAgICAgICAuLi5yLmRvd24uYnVpbGRlcixcbiAgICAgICAgICBcIi8vIHJvbGxiYWNrIC0gYWx0ZXIgZ2VuZXJhdGVkIGNvbHVtblwiLFxuICAgICAgICAgIGB0YWJsZS5kcm9wQ29sdW1ucygnJHtkYkNvbHVtbi5uYW1lfScpYCxcbiAgICAgICAgXTtcbiAgICAgICAgci5kb3duLnJhdyA9IFtcbiAgICAgICAgICAuLi5yLmRvd24ucmF3LFxuICAgICAgICAgIC4uLmdldFNlYXJjaFRleHRIZWxwZXJEZWZpbml0aW9ucyh0YWJsZSwgW2RiQ29sdW1uXSksXG4gICAgICAgICAgXCIvLyByb2xsYmFjayAtIGFsdGVyIGdlbmVyYXRlZCBjb2x1bW5cIixcbiAgICAgICAgICBnZW5HZW5lcmF0ZWRDb2x1bW5EZWZpbml0aW9uKHRhYmxlLCBkYkNvbHVtbiksXG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiByO1xuICAgICAgfVxuXG4gICAgICAvLyDsu6zrn7wg67OA6rK97IKs7ZWtXG4gICAgICBjb25zdCBjb2x1bW5EaWZmVXAgPSBkaWZmKFxuICAgICAgICBnZW5Db2x1bW5EZWZpbml0aW9ucyh0YWJsZSwgW2VudGl0eUNvbHVtbl0pLmJ1aWxkZXIsXG4gICAgICAgIGdlbkNvbHVtbkRlZmluaXRpb25zKHRhYmxlLCBbZGJDb2x1bW5dKS5idWlsZGVyLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IGNvbHVtbkRpZmZEb3duID0gZGlmZihcbiAgICAgICAgZ2VuQ29sdW1uRGVmaW5pdGlvbnModGFibGUsIFtkYkNvbHVtbl0pLmJ1aWxkZXIsXG4gICAgICAgIGdlbkNvbHVtbkRlZmluaXRpb25zKHRhYmxlLCBbZW50aXR5Q29sdW1uXSkuYnVpbGRlcixcbiAgICAgICk7XG4gICAgICBpZiAoY29sdW1uRGlmZlVwLmxlbmd0aCA+IDApIHtcbiAgICAgICAgci51cC5idWlsZGVyID0gW1xuICAgICAgICAgIC4uLnIudXAuYnVpbGRlcixcbiAgICAgICAgICBcIi8vIGFsdGVyIGNvbHVtblwiLFxuICAgICAgICAgIC4uLmNvbHVtbkRpZmZVcC5tYXAoKGwpID0+IGAke2wucmVwbGFjZShcIjtcIiwgXCJcIil9LmFsdGVyKCk7YCksXG4gICAgICAgIF07XG4gICAgICAgIHIuZG93bi5idWlsZGVyID0gW1xuICAgICAgICAgIC4uLnIuZG93bi5idWlsZGVyLFxuICAgICAgICAgIFwiLy8gcm9sbGJhY2sgLSBhbHRlciBjb2x1bW5cIixcbiAgICAgICAgICAuLi5jb2x1bW5EaWZmRG93bi5tYXAoKGwpID0+IGAke2wucmVwbGFjZShcIjtcIiwgXCJcIil9LmFsdGVyKCk7YCksXG4gICAgICAgIF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByO1xuICAgIH0sXG4gICAge1xuICAgICAgdXA6IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICAgIGRvd246IHsgYnVpbGRlcjogW10gYXMgc3RyaW5nW10sIHJhdzogW10gYXMgc3RyaW5nW10gfSxcbiAgICB9LFxuICApO1xuXG4gIHJldHVybiBsaW5lc1RvO1xufVxuXG4vKipcbiAqIOyduOuNseyKpOydmCBhZGQsIGRyb3Ag7Jes67aAIO2ZleyduFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWx0ZXJJbmRleGVzVG8oZW50aXR5SW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSwgZGJJbmRleGVzOiBNaWdyYXRpb25JbmRleFtdKSB7XG4gIC8vIOyduOuNseyKpCDruYTqtZBcbiAgY29uc3QgaW5kZXhlc1RvID0ge1xuICAgIGFkZDogW10gYXMgTWlncmF0aW9uSW5kZXhbXSxcbiAgICBkcm9wOiBbXSBhcyBNaWdyYXRpb25JbmRleFtdLFxuICB9O1xuXG4gIC8vIOyduOuNseyKpCDqs6DsnKAg7Iud67OE7J6QIOyDneyEsSAobmFtZeydhCDsoJzsmbjtlZwg66qo65OgIO2VhOuTnOulvCDrrLjsnpDsl7TroZwg67OA7ZmY7ZWY7JesIOyhsO2VqSlcbiAgY29uc3QgaWRlbnRpdHkgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihpbmRleDogVCk6IHN0cmluZyA9PiB7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGluZGV4KVxuICAgICAgLmZpbHRlcigoa2V5KSA9PiBrZXkgIT09IFwibmFtZVwiKVxuICAgICAgLnRvU29ydGVkKCk7XG5cbiAgICByZXR1cm4ga2V5c1xuICAgICAgLm1hcCgoa2V5KSA9PiB7XG4gICAgICAgIGlmIChrZXkgPT09IFwibmFtZVwiKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5ID09PSBcImNvbHVtbnNcIikge1xuICAgICAgICAgIHJldHVybiAoaW5kZXhba2V5XSBhcyBNaWdyYXRpb25JbmRleFtcImNvbHVtbnNcIl0pLm1hcCgoY29sKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoY29sKVxuICAgICAgICAgICAgICAudG9Tb3J0ZWQoKVxuICAgICAgICAgICAgICAubWFwKChrKSA9PiBgJHtrfT0ke2NvbFtrIGFzIGtleW9mIHR5cGVvZiBjb2xdfWApXG4gICAgICAgICAgICAgIC5qb2luKFwiLy9cIik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGAke2tleX09JHtpbmRleFtrZXkgYXMga2V5b2YgTWlncmF0aW9uSW5kZXhdfWA7XG4gICAgICB9KVxuICAgICAgLmpvaW4oXCIvL1wiKTtcbiAgfTtcblxuICBjb25zdCBleHRyYUluZGV4ZXMgPSB7XG4gICAgZGI6IGRpZmYoZGJJbmRleGVzLCBlbnRpdHlJbmRleGVzLm1hcChzZXRNaWdyYXRpb25JbmRleERlZmF1bHRzKSwgaWRlbnRpdHkpLFxuICAgIGVudGl0eTogZGlmZihlbnRpdHlJbmRleGVzLm1hcChzZXRNaWdyYXRpb25JbmRleERlZmF1bHRzKSwgZGJJbmRleGVzLCBpZGVudGl0eSksXG4gIH07XG4gIGlmIChleHRyYUluZGV4ZXMuZW50aXR5Lmxlbmd0aCA+IDApIHtcbiAgICBpbmRleGVzVG8uYWRkID0gaW5kZXhlc1RvLmFkZC5jb25jYXQoZXh0cmFJbmRleGVzLmVudGl0eSk7XG4gIH1cbiAgaWYgKGV4dHJhSW5kZXhlcy5kYi5sZW5ndGggPiAwKSB7XG4gICAgaW5kZXhlc1RvLmRyb3AgPSBpbmRleGVzVG8uZHJvcC5jb25jYXQoZXh0cmFJbmRleGVzLmRiKTtcbiAgfVxuXG4gIHJldHVybiBpbmRleGVzVG87XG59XG5cbi8qKlxuICog7J24642x7IqkIOyCreygnCDsoJXsnZgg7IOd7ISxXG4gKi9cbmZ1bmN0aW9uIGdlbkluZGV4RHJvcERlZmluaXRpb24oaW5kZXg6IE1pZ3JhdGlvbkluZGV4KSB7XG4gIHJldHVybiBgdGFibGUuZHJvcEluZGV4KFske2luZGV4LmNvbHVtbnNcbiAgICAubWFwKChjb2x1bW4pID0+IGAnJHtjb2x1bW4ubmFtZX0nYClcbiAgICAuam9pbihcIixcIil9XSwgJyR7aW5kZXgubmFtZX0nKWA7XG59XG5cbi8qKlxuICogREIg7KGw7ZqMIOqysOqzvOyZgCDruYTqtZDtlZjquLAg7JyE7ZWcIOyduOuNseyKpCDquLDrs7jqsJIg7ISk7KCVXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRNaWdyYXRpb25JbmRleERlZmF1bHRzKGluZGV4OiBNaWdyYXRpb25JbmRleCk6IE1pZ3JhdGlvbkluZGV4IHtcbiAgY29uc3QgaXNWZWN0b3JJbmRleCA9IGluZGV4LnR5cGUgPT09IFwiaG5zd1wiIHx8IGluZGV4LnR5cGUgPT09IFwiaXZmZmxhdFwiO1xuICBjb25zdCBzdXBwb3J0c09yZGVyaW5nID0gIWlzVmVjdG9ySW5kZXggJiYgKCFpbmRleC51c2luZyB8fCBpbmRleC51c2luZyA9PT0gXCJidHJlZVwiKTtcbiAgY29uc3Qgbm9ybWFsaXplZFVzaW5nID0gaXNWZWN0b3JJbmRleCA/IGluZGV4LnVzaW5nIDogKGluZGV4LnVzaW5nID8/IFwiYnRyZWVcIik7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5pbmRleCxcbiAgICBjb2x1bW5zOiBpbmRleC5jb2x1bW5zLm1hcCgoY29sKSA9PiAoe1xuICAgICAgbmFtZTogY29sLm5hbWUsXG4gICAgICAuLi4oZ2V0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbCkgPyB7IG9wY2xhc3M6IGdldEluZGV4Q29sdW1uT3BjbGFzcyhjb2wpIH0gOiB7fSksXG4gICAgICAuLi4oc3VwcG9ydHNPcmRlcmluZ1xuICAgICAgICA/IHtcbiAgICAgICAgICAgIHNvcnRPcmRlcjogY29sLnNvcnRPcmRlciA/PyBcIkFTQ1wiLFxuICAgICAgICAgICAgbnVsbHNGaXJzdDogY29sLm51bGxzRmlyc3QgPz8gY29sLnNvcnRPcmRlciA9PT0gXCJERVNDXCIsXG4gICAgICAgICAgfVxuICAgICAgICA6IHt9KSxcbiAgICB9KSksXG4gICAgbnVsbHNOb3REaXN0aW5jdDogaW5kZXgubnVsbHNOb3REaXN0aW5jdCA/PyBmYWxzZSxcbiAgICAuLi4obm9ybWFsaXplZFVzaW5nID8geyB1c2luZzogbm9ybWFsaXplZFVzaW5nIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICog7YWM7J2067iUIOuzgOqyvSDsvIDsnbTsiqQgLSBGb3JlaWduIEtleSDrs4Dqsr1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVBbHRlckNvZGVfRm9yZWlnbnMoXG4gIHRhYmxlOiBzdHJpbmcsXG4gIGVudGl0eUZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10sXG4gIGRiRm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgZHJvcHBpbmdDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSA9IFtdLFxuKTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgLy8gY29uc29sZS5sb2coeyBlbnRpdHlGb3JlaWducywgZGJGb3JlaWducyB9KTtcblxuICBjb25zdCBnZXRLZXkgPSAobWY6IE1pZ3JhdGlvbkZvcmVpZ24pOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiBbbWYuY29sdW1ucy5qb2luKFwiLVwiKSwgbWYudG9dLmpvaW4oXCIvLy9cIik7XG4gIH07XG5cbiAgLy8g7IKt7KCc65CgIOy7rOufvOuqhSDrqqnroZ1cbiAgY29uc3QgZHJvcHBpbmdDb2x1bW5OYW1lcyA9IGRyb3BwaW5nQ29sdW1ucy5tYXAoKGNvbCkgPT4gY29sLm5hbWUpO1xuXG4gIGNvbnN0IGZrVG8gPSBlbnRpdHlGb3JlaWducy5yZWR1Y2UoXG4gICAgKHJlc3VsdCwgZW50aXR5RikgPT4ge1xuICAgICAgY29uc3QgbWF0Y2hpbmdEYkYgPSBkYkZvcmVpZ25zLmZpbmQoKGRiRikgPT4gZ2V0S2V5KGVudGl0eUYpID09PSBnZXRLZXkoZGJGKSk7XG4gICAgICBpZiAoIW1hdGNoaW5nRGJGKSB7XG4gICAgICAgIHJlc3VsdC5hZGQucHVzaChlbnRpdHlGKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgaWYgKCFlcXVhbChlbnRpdHlGLCBtYXRjaGluZ0RiRikpIHtcbiAgICAgICAgcmVzdWx0LmFsdGVyU3JjLnB1c2gobWF0Y2hpbmdEYkYpO1xuICAgICAgICByZXN1bHQuYWx0ZXJEc3QucHVzaChlbnRpdHlGKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcbiAgICB7XG4gICAgICBhZGQ6IFtdIGFzIE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgICAgIGRyb3A6IFtdIGFzIE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgICAgIGFsdGVyU3JjOiBbXSBhcyBNaWdyYXRpb25Gb3JlaWduW10sXG4gICAgICBhbHRlckRzdDogW10gYXMgTWlncmF0aW9uRm9yZWlnbltdLFxuICAgIH0sXG4gICk7XG5cbiAgLy8gZGJGb3JlaWduc+yXkOuKlCDsnojsp4Drp4wgZW50aXR5Rm9yZWlnbnPsl5DripQg7JeG64qUIOqyveyasCAo7IKt7KCc65CcIEZLKVxuICAvLyDri6gsIOyCreygnOuQoCDsu6zrn7zsnZggRkvripQg7KCc7Jm4IChnZW5lcmF0ZUFsdGVyQ29kZV9Db2x1bW5BbmRJbmRleGVz7JeQ7IScIOyymOumrClcbiAgZGJGb3JlaWducy5mb3JFYWNoKChkYkYpID0+IHtcbiAgICBjb25zdCBtYXRjaGluZ0VudGl0eUYgPSBlbnRpdHlGb3JlaWducy5maW5kKChlbnRpdHlGKSA9PiBnZXRLZXkoZW50aXR5RikgPT09IGdldEtleShkYkYpKTtcbiAgICBpZiAoIW1hdGNoaW5nRW50aXR5Rikge1xuICAgICAgLy8g7J20IEZL7J2YIOy7rOufvOydtCDsgq3soJzrkKAg7Lus65+8IOuqqeuhneyXkCDsnojripTsp4Ag7ZmV7J24XG4gICAgICBjb25zdCBpc0NvbHVtbkRyb3BwaW5nID0gZGJGLmNvbHVtbnMuc29tZSgoY29sKSA9PiBkcm9wcGluZ0NvbHVtbk5hbWVzLmluY2x1ZGVzKGNvbCkpO1xuICAgICAgLy8g7Lus65+87J20IOyCreygnOuQmOyngCDslYrripQg6rK97Jqw7JeQ66eMIEZLIGRyb3Ag66qp66Gd7JeQIOy2lOqwgFxuICAgICAgaWYgKCFpc0NvbHVtbkRyb3BwaW5nKSB7XG4gICAgICAgIGZrVG8uZHJvcC5wdXNoKGRiRik7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBjb25zdCBsaW5lc1RvID0ge1xuICAgIGFkZDogZ2VuRm9yZWlnbkRlZmluaXRpb25zKHRhYmxlLCBma1RvLmFkZCksXG4gICAgZHJvcDogZ2VuRm9yZWlnbkRlZmluaXRpb25zKHRhYmxlLCBma1RvLmRyb3ApLFxuICAgIGFsdGVyU3JjOiBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZrVG8uYWx0ZXJTcmMpLFxuICAgIGFsdGVyRHN0OiBnZW5Gb3JlaWduRGVmaW5pdGlvbnModGFibGUsIGZrVG8uYWx0ZXJEc3QpLFxuICB9O1xuXG4gIC8vIGRyb3AgZmsgY29sdW1uc+yduCDqsr3smrAo7IOd7ISx65CgIOy9lOuTnCDsl4bripQg6rK97JqwKSDtjKjsiqRcbiAgY29uc3QgaGFzTGluZXMgPSBPYmplY3QudmFsdWVzKGxpbmVzVG8pLnNvbWUoKGwpID0+IGwudXAubGVuZ3RoID4gMCB8fCBsLmRvd24ubGVuZ3RoID4gMCk7XG4gIGlmICghaGFzTGluZXMpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBpZiAoXG4gICAgbGluZXNUby5hZGQudXAubGVuZ3RoID09PSAwICYmXG4gICAgbGluZXNUby5kcm9wLnVwLmxlbmd0aCA9PT0gMCAmJlxuICAgIGxpbmVzVG8uYWx0ZXJTcmMudXAubGVuZ3RoID09PSAwICYmXG4gICAgbGluZXNUby5hbHRlckRzdC51cC5sZW5ndGggPT09IDBcbiAgKSB7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdlbmVyYXRlQWx0ZXJDb2RlX0ZvcmVpZ25zOmZrQ2hhbmdlQ29kZUdlbmVyYXRpb25FcnJvclwiLCB7XG4gICAgICB0YWJsZSxcbiAgICAgIGVudGl0eUZvcmVpZ25zLFxuICAgICAgZGJGb3JlaWducyxcbiAgICB9KTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJGSyDrs4Dqsr0g7L2U65OcIOyDneyEsSDsmKTrpZhcIik7XG4gIH1cblxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG4gICAgJ2ltcG9ydCB7IEtuZXggfSBmcm9tIFwia25leFwiOycsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cChrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgYHJldHVybiBrbmV4LnNjaGVtYS5hbHRlclRhYmxlKFwiJHt0YWJsZX1cIiwgKHRhYmxlKSA9PiB7YCxcbiAgICAuLi5saW5lc1RvLmRyb3AuZG93bixcbiAgICAuLi5saW5lc1RvLmFkZC51cCxcbiAgICAuLi5saW5lc1RvLmFsdGVyU3JjLmRvd24sXG4gICAgLi4ubGluZXNUby5hbHRlckRzdC51cCxcbiAgICBcIn0pXCIsXG4gICAgXCJ9XCIsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3duKGtuZXg6IEtuZXgpOiBQcm9taXNlPHZvaWQ+IHtcIixcbiAgICBgcmV0dXJuIGtuZXguc2NoZW1hLmFsdGVyVGFibGUoXCIke3RhYmxlfVwiLCAodGFibGUpID0+IHtgLFxuICAgIC4uLmxpbmVzVG8uYWRkLmRvd24sXG4gICAgLi4ubGluZXNUby5hbHRlckRzdC5kb3duLFxuICAgIC4uLmxpbmVzVG8uYWx0ZXJTcmMudXAsXG4gICAgLi4ubGluZXNUby5kcm9wLnVwLFxuICAgIFwifSlcIixcbiAgICBcIn1cIixcbiAgXTtcblxuICBjb25zdCBmb3JtYXR0ZWQgPSBhd2FpdCBmb3JtYXRDb2RlKGxpbmVzLmpvaW4oXCJcXG5cIiksIFwidHlwZXNjcmlwdFwiLCBgc3JjL21pZ3JhdGlvbi8ke3RhYmxlfS50c2ApO1xuICBjb25zdCB0aXRsZSA9IFtcImFsdGVyXCIsIHRhYmxlLCBcImZvcmVpZ25zXCJdLmpvaW4oXCJfXCIpO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgdGFibGUsXG4gICAgICB0aXRsZSxcbiAgICAgIGZvcm1hdHRlZCxcbiAgICAgIHR5cGU6IFwibm9ybWFsXCIsXG4gICAgfSxcbiAgXTtcbn1cblxuLyoqXG4gKiDso7zslrTsp4QgRW50aXR5U2V07J2EIOq4sOuwmOycvOuhnCDthYzsnbTruJQgQ1JFQVRFIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5zrpbwg7IOd7ISx7ZWp64uI64ukLlxuICogQHBhcmFtIGVudGl0eVNldFxuICogQHJldHVybnMgQ1JFQVRFIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5xcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQ3JlYXRlQ29kZShlbnRpdHlTZXQ6IE1pZ3JhdGlvblNldCk6IFByb21pc2U8R2VuTWlncmF0aW9uQ29kZVtdPiB7XG4gIHJldHVybiBbXG4gICAgYXdhaXQgZ2VuZXJhdGVDcmVhdGVDb2RlX0NvbHVtbkFuZEluZGV4ZXMoXG4gICAgICBlbnRpdHlTZXQudGFibGUsXG4gICAgICBlbnRpdHlTZXQuY29sdW1ucyxcbiAgICAgIGVudGl0eVNldC5pbmRleGVzLFxuICAgICksXG4gICAgLi4uKGF3YWl0IGdlbmVyYXRlQ3JlYXRlQ29kZV9Gb3JlaWduKGVudGl0eVNldC50YWJsZSwgZW50aXR5U2V0LmZvcmVpZ25zKSksXG4gIF07XG59XG5cbi8qKlxuICog7KO87Ja07KeEIGVudGl0eVNldOydhCDrqqntkZzroZwsIGRiU2V07J2EIO2YhCDsg4HtmansnLzroZwg7ZWY7JesIO2FjOydtOu4lCBBTFRFUiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65Oc66W8IOyDneyEse2VqeuLiOuLpC5cbiAqIEBwYXJhbSBlbnRpdHlTZXQg7ZiEIOyDge2ZqeydmCBNaWdyYXRpb25TZXRcbiAqIEBwYXJhbSBkYlNldCDrqqntkZwg7IOB7Zmp7J2YIE1pZ3JhdGlvblNldFxuICogQHBhcmFtIGNvbXBhcmVEQiBQSyDtg4DsnoUg67OA6rK9IOyLnCDsl63ssLjsobAgRkvrpbwg7KGw7ZqM7ZWY6riwIOychO2VnCBLbmV4IOyduOyKpO2EtOyKpCAo7ISg7YOdKVxuICogQHJldHVybnMgQUxURVIg66eI7J206re466CI7J207IWYIOy9lOuTnFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVBbHRlckNvZGUoXG4gIGVudGl0eVNldDogTWlncmF0aW9uU2V0LFxuICBkYlNldDogTWlncmF0aW9uU2V0LFxuICBjb21wYXJlREI/OiBLbmV4LFxuKTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgY29uc3QgcmVwbGFjZUNvbHVtbkRlZmF1bHRUbyA9IChjb2w6IE1pZ3JhdGlvbkNvbHVtbikgPT4ge1xuICAgIC8vIGZsb2F07J24IOqyveyasCDquLDrs7jqsJLsnYQgMOycvOuhnCDsp4DsoJXtlZjripQg6rK97JqwIFwiMC4wMFwi7Jy866GcIOuzgO2ZmOuQmOuKlCDsvIDsnbTsiqQg64yA7J2RXG4gICAgLy8gaWYgKGNvbC50eXBlID09PSBcImZsb2F0XCIgJiYgY29sLmRlZmF1bHRUbyAmJiBTdHJpbmcoY29sLmRlZmF1bHRUbykuaW5jbHVkZXMoJ1wiJykgPT09IGZhbHNlKSB7XG4gICAgLy8gICBjb2wuZGVmYXVsdFRvID0gYFwiJHtOdW1iZXIoY29sLmRlZmF1bHRUbykudG9GaXhlZChjb2wuc2NhbGUgPz8gMil9XCJgO1xuICAgIC8vIH1cbiAgICAvLyAvLyBzdHJpbmfsnbgg6rK97JqwIOq4sOuzuOqwkuydtCDruYgg7Iqk7Yq466eB7J24IOqyveyasCDrjIDsnZFcbiAgICAvLyBpZiAoY29sLnR5cGUgPT09IFwic3RyaW5nXCIgJiYgY29sLmRlZmF1bHRUbyA9PT0gXCJcIikge1xuICAgIC8vICAgY29sLmRlZmF1bHRUbyA9ICdcIlwiJztcbiAgICAvLyB9XG4gICAgLy8gLy8gYm9vbGVhbuyduCDqsr3smrAg6riw67O46rCSIOygleq3nO2ZlCAoTXlTUUzsl5DshJzripQgVElOWUlOVCgxKeuhnCDsoIDsnqXrkJjrr4DroZwgMCDrmJDripQgMeuhnCDsoJXqt5ztmZQpXG4gICAgLy8gLy8gVE9ETzogZGIudHPsl5AgdHlwZUNhc2Ug7ISk7KCVIO2ZleyduO2VmOyXrCDsspjrpqztlZjrj4TroZ0g7IiY7KCVIO2VhOyalFxuICAgIC8vIGlmIChjb2wudHlwZSA9PT0gXCJib29sZWFuXCIgJiYgY29sLmRlZmF1bHRUbyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gICBpZiAoY29sLmRlZmF1bHRUbyA9PT0gXCIwXCIgfHwgY29sLmRlZmF1bHRUby50b0xvd2VyQ2FzZSgpID09PSBcImZhbHNlXCIpIHtcbiAgICAvLyAgICAgY29sLmRlZmF1bHRUbyA9IFwiMFwiO1xuICAgIC8vICAgfSBlbHNlIGlmIChjb2wuZGVmYXVsdFRvID09PSBcIjFcIiB8fCBjb2wuZGVmYXVsdFRvLnRvTG93ZXJDYXNlKCkgPT09IFwidHJ1ZVwiKSB7XG4gICAgLy8gICAgIGNvbC5kZWZhdWx0VG8gPSBcIjFcIjtcbiAgICAvLyAgIH1cbiAgICAvLyB9XG5cbiAgICAvLyBGSVhNRTog7J2864uoIE15U1FMIOyDge2ZqeyXkOyEnCDrsJzsg53tlojrjZgg7J207IqI7J2YIHdvcmthcm91bmQg7J2066+A66GcIFBn7JeQ7IScIOyerO2ZleyduCDtm4Qg64yA7J2RIOy2lOqwgFxuICAgIHJldHVybiBjb2w7XG4gIH07XG4gIGNvbnN0IGVudGl0eUNvbHVtbnMgPSBhbHBoYWJldGljYWwoZW50aXR5U2V0LmNvbHVtbnMsIChhKSA9PiBhLm5hbWUpLm1hcChyZXBsYWNlQ29sdW1uRGVmYXVsdFRvKTtcbiAgY29uc3QgZGJDb2x1bW5zID0gYWxwaGFiZXRpY2FsKGRiU2V0LmNvbHVtbnMsIChhKSA9PiBhLm5hbWUpLm1hcChyZXBsYWNlQ29sdW1uRGVmYXVsdFRvKTtcblxuICAvKiDrlJTrsoTquYXsmqkg7L2U65OcLCDtirnsoJUg7Lus65+87JeQ7IScIOu2iOydvOy5mCDrsJzsg53tlaAg65WMIO2ZleyduFxuICAgICAgICBjb25zdCBlbnRpdHlDb2x1bW4gPSBlbnRpdHlTZXQuY29sdW1ucy5maW5kKFxuICAgICAgICAgIChjb2wpID0+IGNvbC5uYW1lID09PSBcInByaWNlX2tyd1wiXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGRiQ29sdW1uID0gZGJTZXQuY29sdW1ucy5maW5kKFxuICAgICAgICAgIChjb2wpID0+IGNvbC5uYW1lID09PSBcInByaWNlX2tyd1wiXG4gICAgICAgICk7XG4gICAgICAgIGNvbnNvbGUuZGVidWcoeyBlbnRpdHlDb2x1bW4sIGRiQ29sdW1uIH0pO1xuICAgICAgICAgKi9cblxuICBjb25zdCBlbnRpdHlJbmRleGVzID0gYWxwaGFiZXRpY2FsKGVudGl0eVNldC5pbmRleGVzLCAoYSkgPT5cbiAgICBbYS50eXBlLCAuLi5hLmNvbHVtbnMubWFwKChjKSA9PiBjLm5hbWUpXS5qb2luKFwiLVwiKSxcbiAgKTtcbiAgY29uc3QgZGJJbmRleGVzID0gYWxwaGFiZXRpY2FsKGRiU2V0LmluZGV4ZXMsIChhKSA9PlxuICAgIFthLnR5cGUsIC4uLmEuY29sdW1ucy5tYXAoKGMpID0+IGMubmFtZSldLmpvaW4oXCItXCIpLFxuICApO1xuXG4gIGNvbnN0IHJlcGxhY2VOb0FjdGlvbk9uTXlTUUwgPSAoZjogTWlncmF0aW9uRm9yZWlnbikgPT4ge1xuICAgIC8vIE15U1FM7JeQ7IScIFJFU1RSSUNU7JmAIE5PIEFDVElPTuydgCDrj5nsnbztlahcbiAgICBjb25zdCB7IG9uRGVsZXRlLCBvblVwZGF0ZSB9ID0gZjtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZixcbiAgICAgIG9uVXBkYXRlOiBvblVwZGF0ZSA9PT0gXCJSRVNUUklDVFwiID8gXCJOTyBBQ1RJT05cIiA6IG9uVXBkYXRlLFxuICAgICAgb25EZWxldGU6IG9uRGVsZXRlID09PSBcIlJFU1RSSUNUXCIgPyBcIk5PIEFDVElPTlwiIDogb25EZWxldGUsXG4gICAgfTtcbiAgfTtcblxuICBjb25zdCBlbnRpdHlGb3JlaWducyA9IGFscGhhYmV0aWNhbChlbnRpdHlTZXQuZm9yZWlnbnMsIChhKSA9PlxuICAgIFthLnRvLCAuLi5hLmNvbHVtbnNdLmpvaW4oXCItXCIpLFxuICApLm1hcCgoZikgPT4gcmVwbGFjZU5vQWN0aW9uT25NeVNRTChmKSk7XG4gIGNvbnN0IGRiRm9yZWlnbnMgPSBhbHBoYWJldGljYWwoZGJTZXQuZm9yZWlnbnMsIChhKSA9PiBbYS50bywgLi4uYS5jb2x1bW5zXS5qb2luKFwiLVwiKSkubWFwKChmKSA9PlxuICAgIHJlcGxhY2VOb0FjdGlvbk9uTXlTUUwoZiksXG4gICk7XG5cbiAgLy8g7IKt7KCc65CgIOy7rOufvCDrqqnroZ0g6rOE7IKwXG4gIGNvbnN0IGRyb3BwaW5nQ29sdW1ucyA9IGRpZmYoZGJDb2x1bW5zLCBlbnRpdHlDb2x1bW5zLCAoY29sKSA9PiBjb2wubmFtZSk7XG5cbiAgY29uc3QgYWx0ZXJDb2RlczogKEdlbk1pZ3JhdGlvbkNvZGUgfCBHZW5NaWdyYXRpb25Db2RlW10gfCBudWxsKVtdID0gW107XG5cbiAgLy8gMS4gY29sdW1uc0FuZEluZGV4ZXMg7LKY66asXG4gIGNvbnN0IHNlYXJjaFRleHRDb2x1bW5OYW1lcyA9IGdldFNlYXJjaFRleHRDb2x1bW5OYW1lcyhlbnRpdHlTZXQudGFibGUpO1xuICBjb25zdCBpc0VxdWFsQ29sdW1ucyA9IGVxdWFsKFxuICAgIGVudGl0eUNvbHVtbnMubWFwKChjb2x1bW4pID0+IG5vcm1hbGl6ZUNvbHVtbkZvckNvbXBhcmlzb24oY29sdW1uLCBzZWFyY2hUZXh0Q29sdW1uTmFtZXMpKSxcbiAgICBkYkNvbHVtbnMubWFwKChjb2x1bW4pID0+IG5vcm1hbGl6ZUNvbHVtbkZvckNvbXBhcmlzb24oY29sdW1uLCBzZWFyY2hUZXh0Q29sdW1uTmFtZXMpKSxcbiAgKTtcbiAgY29uc3QgaXNFcXVhbEluZGV4ZXMgPSBlcXVhbChcbiAgICBlbnRpdHlJbmRleGVzLm1hcChzZXRNaWdyYXRpb25JbmRleERlZmF1bHRzKSxcbiAgICBkYkluZGV4ZXMubWFwKHNldE1pZ3JhdGlvbkluZGV4RGVmYXVsdHMpLFxuICApO1xuICBpZiAoIWlzRXF1YWxDb2x1bW5zIHx8ICFpc0VxdWFsSW5kZXhlcykge1xuICAgIGFsdGVyQ29kZXMucHVzaChcbiAgICAgIGF3YWl0IGdlbmVyYXRlQWx0ZXJDb2RlX0NvbHVtbkFuZEluZGV4ZXMoXG4gICAgICAgIGVudGl0eVNldC50YWJsZSxcbiAgICAgICAgZW50aXR5Q29sdW1ucyxcbiAgICAgICAgZW50aXR5SW5kZXhlcyxcbiAgICAgICAgZGJDb2x1bW5zLFxuICAgICAgICBkYkluZGV4ZXMsXG4gICAgICAgIGRiU2V0LmZvcmVpZ25zLFxuICAgICAgICBjb21wYXJlREIsXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvLyAyLiBmb3JlaWducyDsspjrpqwgKOyCreygnOuQoCDsu6zrn7wg7KCV67O0IOyghOuLrClcbiAgaWYgKCFlcXVhbChlbnRpdHlGb3JlaWducywgZGJGb3JlaWducykpIHtcbiAgICBhbHRlckNvZGVzLnB1c2goXG4gICAgICBhd2FpdCBnZW5lcmF0ZUFsdGVyQ29kZV9Gb3JlaWducyhcbiAgICAgICAgZW50aXR5U2V0LnRhYmxlLFxuICAgICAgICBlbnRpdHlGb3JlaWducyxcbiAgICAgICAgZGJGb3JlaWducyxcbiAgICAgICAgZHJvcHBpbmdDb2x1bW5zLFxuICAgICAgKSxcbiAgICApO1xuICB9XG5cbiAgaWYgKGFsdGVyQ29kZXMuZXZlcnkoKGFsdGVyQ29kZSkgPT4gYWx0ZXJDb2RlID09PSBudWxsKSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBhbHRlckNvZGVzLmZpbHRlcigoYWx0ZXJDb2RlKSA9PiBhbHRlckNvZGUgIT09IG51bGwpLmZsYXQoKTtcbn1cblxuLyoqXG4gKiBQSyDtg4DsnoUg67OA6rK9IOyLnCDsl63ssLjsobAgRksg7KCc7JW97KGw6rG07J2EIOyymOumrO2VmOuKlCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65Oc66W8IOyDneyEse2VqeuLiOuLpC5cbiAqXG4gKiBQSyDtg4DsnoUg67OA6rK9IOyLnCDsiJzshJw6XG4gKiAxLiBGSyDsoJzslb3sobDqsbQg7IKt7KCcICjsl63ssLjsobAg7YWM7J2067iU65OkKVxuICogMi4g7J6Q6riwIOywuOyhsCBGSyDsgq3soJwgKOyeiOuKlCDqsr3smrApXG4gKiAzLiBQSyDsoJzslb3sobDqsbQg7IKt7KCcXG4gKiA0LiBQSyDsu6zrn7wg7YOA7J6FIOuzgOqyvVxuICogNS4gRksg7Lus65+8IO2DgOyehSDrs4Dqsr0gKOyXreywuOyhsCDthYzsnbTruJTrk6QpXG4gKiA2LiBQSyDsoJzslb3sobDqsbQg67O16rWsXG4gKiA3LiDsnpDquLAg7LC47KGwIEZLIOuzteq1rFxuICogOC4gRksg7KCc7JW97KGw6rG0IOuzteq1rFxuICovXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZVBrVHlwZUNoYW5nZU1pZ3JhdGlvbihcbiAgdGFibGU6IHN0cmluZyxcbiAgZW50aXR5SWRDb2w6IE1pZ3JhdGlvbkNvbHVtbixcbiAgZGJJZENvbDogTWlncmF0aW9uQ29sdW1uLFxuICBfZW50aXR5Q29sdW1uczogTWlncmF0aW9uQ29sdW1uW10sXG4gIF9lbnRpdHlJbmRleGVzOiBNaWdyYXRpb25JbmRleFtdLFxuICBfZGJDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSxcbiAgX2RiSW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbiAgX2RiRm9yZWlnbnM6IE1pZ3JhdGlvbkZvcmVpZ25bXSxcbiAgY29tcGFyZURCOiBLbmV4LFxuKTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgLy8g7Jet7LC47KGwIEZLIOyhsO2ajCAo7J20IO2FjOydtOu4lOydmCBQS+ulvCDssLjsobDtlZjripQg64uk66W4IO2FjOydtOu4lOydmCBGS+uTpClcbiAgY29uc3QgcmVmZXJlbmNpbmdGS3MgPSBhd2FpdCBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyLmdldFJlZmVyZW5jaW5nRm9yZWlnbktleXMoY29tcGFyZURCLCB0YWJsZSk7XG5cbiAgLy8g7J6Q6riwIOywuOyhsCBGSyDrtoTrpqwgKOyYiDogRGVwYXJ0bWVudC5wYXJlbnRfaWQg4oaSIERlcGFydG1lbnQuaWQpXG4gIGNvbnN0IHNlbGZSZWZlcmVuY2luZ0ZLcyA9IHJlZmVyZW5jaW5nRktzLmZpbHRlcigoZmspID0+IGZrLnRhYmxlTmFtZSA9PT0gdGFibGUpO1xuICBjb25zdCBleHRlcm5hbFJlZmVyZW5jaW5nRktzID0gcmVmZXJlbmNpbmdGS3MuZmlsdGVyKChmaykgPT4gZmsudGFibGVOYW1lICE9PSB0YWJsZSk7XG5cbiAgLy8gUEsg7KCc7JW97KGw6rG0IOydtOumhCDsobDtmoxcbiAgY29uc3QgcGtDb25zdHJhaW50TmFtZSA9IGAke3RhYmxlfV9wa2V5YDtcblxuICAvLyDsg4ggUEsg7YOA7J6F7JeQIOunnuuKlCBQb3N0Z3JlU1FMIO2DgOyehSDrrLjsnpDsl7RcbiAgY29uc3QgbmV3UGtQZ1R5cGUgPSBnZXRQa1BnVHlwZShlbnRpdHlJZENvbCk7XG4gIGNvbnN0IG9sZFBrUGdUeXBlID0gZ2V0UGtQZ1R5cGUoZGJJZENvbCk7XG5cbiAgLy8gVVAg7L2U65OcIOyDneyEsVxuICBjb25zdCB1cExpbmVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIDEuIOyZuOu2gCDthYzsnbTruJTsnZggRksg7KCc7JW97KGw6rG0IOyCreygnFxuICBmb3IgKGNvbnN0IGZrIG9mIGV4dGVybmFsUmVmZXJlbmNpbmdGS3MpIHtcbiAgICB1cExpbmVzLnB1c2goYCAgLy8gJHtmay50YWJsZU5hbWV9LiR7ZmsuY29sdW1uTmFtZX0gRksg7KCc7JW97KGw6rG0IOyCreygnGApO1xuICAgIHVwTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7ZmsudGFibGVOYW1lfVwiIERST1AgQ09OU1RSQUlOVCBcIiR7ZmsuY29uc3RyYWludE5hbWV9XCInKTtgLFxuICAgICk7XG4gIH1cblxuICAvLyAyLiDsnpDquLAg7LC47KGwIEZLIOyCreygnFxuICBmb3IgKGNvbnN0IGZrIG9mIHNlbGZSZWZlcmVuY2luZ0ZLcykge1xuICAgIHVwTGluZXMucHVzaChgICAvLyDsnpDquLAg7LC47KGwIEZLIOyCreygnDogJHtmay5jb2x1bW5OYW1lfWApO1xuICAgIHVwTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgRFJPUCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIicpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDMuIFBLIOygnOyVveyhsOqxtCDsgq3soJxcbiAgdXBMaW5lcy5wdXNoKGAgIC8vIFBLIOygnOyVveyhsOqxtCDsgq3soJxgKTtcbiAgdXBMaW5lcy5wdXNoKGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgRFJPUCBDT05TVFJBSU5UIFwiJHtwa0NvbnN0cmFpbnROYW1lfVwiJyk7YCk7XG5cbiAgLy8gNC4gUEsg7Lus65+8IO2DgOyehSDrs4Dqsr1cbiAgdXBMaW5lcy5wdXNoKGAgIC8vIFBLIOy7rOufvCDtg4DsnoUg67OA6rK9YCk7XG4gIHVwTGluZXMucHVzaChcbiAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFMVEVSIENPTFVNTiBcImlkXCIgVFlQRSAke25ld1BrUGdUeXBlfSBVU0lORyBcImlkXCI6OiR7bmV3UGtQZ1R5cGV9Jyk7YCxcbiAgKTtcblxuICAvLyA1LiBGSyDsu6zrn7wg7YOA7J6FIOuzgOqyvSAo7Jet7LC47KGwIO2FjOydtOu4lOuTpCkgLSDsnpDquLAg7LC47KGwIO2PrO2VqFxuICBmb3IgKGNvbnN0IGZrIG9mIHJlZmVyZW5jaW5nRktzKSB7XG4gICAgdXBMaW5lcy5wdXNoKGAgIC8vICR7ZmsudGFibGVOYW1lfS4ke2ZrLmNvbHVtbk5hbWV9IOy7rOufvCDtg4DsnoUg67OA6rK9YCk7XG4gICAgdXBMaW5lcy5wdXNoKFxuICAgICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHtmay50YWJsZU5hbWV9XCIgQUxURVIgQ09MVU1OIFwiJHtmay5jb2x1bW5OYW1lfVwiIFRZUEUgJHtuZXdQa1BnVHlwZX0gVVNJTkcgXCIke2ZrLmNvbHVtbk5hbWV9XCI6OiR7bmV3UGtQZ1R5cGV9Jyk7YCxcbiAgICApO1xuICB9XG5cbiAgLy8gNi4gUEsg7KCc7JW97KGw6rG0IOuzteq1rFxuICB1cExpbmVzLnB1c2goYCAgLy8gUEsg7KCc7JW97KGw6rG0IOuzteq1rGApO1xuICB1cExpbmVzLnB1c2goXG4gICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHt0YWJsZX1cIiBBREQgQ09OU1RSQUlOVCBcIiR7cGtDb25zdHJhaW50TmFtZX1cIiBQUklNQVJZIEtFWSAoXCJpZFwiKScpO2AsXG4gICk7XG5cbiAgLy8gNy4g7J6Q6riwIOywuOyhsCBGSyDrs7XqtaxcbiAgZm9yIChjb25zdCBmayBvZiBzZWxmUmVmZXJlbmNpbmdGS3MpIHtcbiAgICB1cExpbmVzLnB1c2goYCAgLy8g7J6Q6riwIOywuOyhsCBGSyDrs7Xqtaw6ICR7ZmsuY29sdW1uTmFtZX1gKTtcbiAgICB1cExpbmVzLnB1c2goXG4gICAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIiBGT1JFSUdOIEtFWSAoXCIke2ZrLmNvbHVtbk5hbWV9XCIpIFJFRkVSRU5DRVMgXCIke3RhYmxlfVwiKFwiaWRcIikgT04gVVBEQVRFICR7Zmsub25VcGRhdGV9IE9OIERFTEVURSAke2ZrLm9uRGVsZXRlfScpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDguIOyZuOu2gCDthYzsnbTruJTsnZggRksg7KCc7JW97KGw6rG0IOuzteq1rFxuICBmb3IgKGNvbnN0IGZrIG9mIGV4dGVybmFsUmVmZXJlbmNpbmdGS3MpIHtcbiAgICB1cExpbmVzLnB1c2goYCAgLy8gJHtmay50YWJsZU5hbWV9LiR7ZmsuY29sdW1uTmFtZX0gRksg7KCc7JW97KGw6rG0IOuzteq1rGApO1xuICAgIHVwTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7ZmsudGFibGVOYW1lfVwiIEFERCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIiBGT1JFSUdOIEtFWSAoXCIke2ZrLmNvbHVtbk5hbWV9XCIpIFJFRkVSRU5DRVMgXCIke3RhYmxlfVwiKFwiaWRcIikgT04gVVBEQVRFICR7Zmsub25VcGRhdGV9IE9OIERFTEVURSAke2ZrLm9uRGVsZXRlfScpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIERPV04g7L2U65OcIOyDneyEsSAo7Jet7IicKVxuICBjb25zdCBkb3duTGluZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gMS4g7Jm467aAIO2FjOydtOu4lOydmCBGSyDsoJzslb3sobDqsbQg7IKt7KCcXG4gIGZvciAoY29uc3QgZmsgb2YgZXh0ZXJuYWxSZWZlcmVuY2luZ0ZLcykge1xuICAgIGRvd25MaW5lcy5wdXNoKGAgIC8vICR7ZmsudGFibGVOYW1lfS4ke2ZrLmNvbHVtbk5hbWV9IEZLIOygnOyVveyhsOqxtCDsgq3soJxgKTtcbiAgICBkb3duTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7ZmsudGFibGVOYW1lfVwiIERST1AgQ09OU1RSQUlOVCBcIiR7ZmsuY29uc3RyYWludE5hbWV9XCInKTtgLFxuICAgICk7XG4gIH1cblxuICAvLyAyLiDsnpDquLAg7LC47KGwIEZLIOyCreygnFxuICBmb3IgKGNvbnN0IGZrIG9mIHNlbGZSZWZlcmVuY2luZ0ZLcykge1xuICAgIGRvd25MaW5lcy5wdXNoKGAgIC8vIOyekOq4sCDssLjsobAgRksg7IKt7KCcOiAke2ZrLmNvbHVtbk5hbWV9YCk7XG4gICAgZG93bkxpbmVzLnB1c2goXG4gICAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIERST1AgQ09OU1RSQUlOVCBcIiR7ZmsuY29uc3RyYWludE5hbWV9XCInKTtgLFxuICAgICk7XG4gIH1cblxuICAvLyAzLiBQSyDsoJzslb3sobDqsbQg7IKt7KCcXG4gIGRvd25MaW5lcy5wdXNoKGAgIC8vIFBLIOygnOyVveyhsOqxtCDsgq3soJxgKTtcbiAgZG93bkxpbmVzLnB1c2goXG4gICAgYCAgYXdhaXQga25leC5yYXcoJ0FMVEVSIFRBQkxFIFwiJHt0YWJsZX1cIiBEUk9QIENPTlNUUkFJTlQgXCIke3BrQ29uc3RyYWludE5hbWV9XCInKTtgLFxuICApO1xuXG4gIC8vIDQuIFBLIOy7rOufvCDtg4DsnoUg7JuQ67O1XG4gIGRvd25MaW5lcy5wdXNoKGAgIC8vIFBLIOy7rOufvCDtg4DsnoUg7JuQ67O1YCk7XG4gIGRvd25MaW5lcy5wdXNoKFxuICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7dGFibGV9XCIgQUxURVIgQ09MVU1OIFwiaWRcIiBUWVBFICR7b2xkUGtQZ1R5cGV9IFVTSU5HIFwiaWRcIjo6JHtvbGRQa1BnVHlwZX0nKTtgLFxuICApO1xuXG4gIC8vIDUuIEZLIOy7rOufvCDtg4DsnoUg7JuQ67O1ICjsl63ssLjsobAg7YWM7J2067iU65OkKVxuICBmb3IgKGNvbnN0IGZrIG9mIHJlZmVyZW5jaW5nRktzKSB7XG4gICAgZG93bkxpbmVzLnB1c2goYCAgLy8gJHtmay50YWJsZU5hbWV9LiR7ZmsuY29sdW1uTmFtZX0g7Lus65+8IO2DgOyehSDsm5Drs7VgKTtcbiAgICBkb3duTGluZXMucHVzaChcbiAgICAgIGAgIGF3YWl0IGtuZXgucmF3KCdBTFRFUiBUQUJMRSBcIiR7ZmsudGFibGVOYW1lfVwiIEFMVEVSIENPTFVNTiBcIiR7ZmsuY29sdW1uTmFtZX1cIiBUWVBFICR7b2xkUGtQZ1R5cGV9IFVTSU5HIFwiJHtmay5jb2x1bW5OYW1lfVwiOjoke29sZFBrUGdUeXBlfScpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDYuIFBLIOygnOyVveyhsOqxtCDrs7XqtaxcbiAgZG93bkxpbmVzLnB1c2goYCAgLy8gUEsg7KCc7JW97KGw6rG0IOuzteq1rGApO1xuICBkb3duTGluZXMucHVzaChcbiAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT05TVFJBSU5UIFwiJHtwa0NvbnN0cmFpbnROYW1lfVwiIFBSSU1BUlkgS0VZIChcImlkXCIpJyk7YCxcbiAgKTtcblxuICAvLyA3LiDsnpDquLAg7LC47KGwIEZLIOuzteq1rFxuICBmb3IgKGNvbnN0IGZrIG9mIHNlbGZSZWZlcmVuY2luZ0ZLcykge1xuICAgIGRvd25MaW5lcy5wdXNoKGAgIC8vIOyekOq4sCDssLjsobAgRksg67O16rWsOiAke2ZrLmNvbHVtbk5hbWV9YCk7XG4gICAgZG93bkxpbmVzLnB1c2goXG4gICAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke3RhYmxlfVwiIEFERCBDT05TVFJBSU5UIFwiJHtmay5jb25zdHJhaW50TmFtZX1cIiBGT1JFSUdOIEtFWSAoXCIke2ZrLmNvbHVtbk5hbWV9XCIpIFJFRkVSRU5DRVMgXCIke3RhYmxlfVwiKFwiaWRcIikgT04gVVBEQVRFICR7Zmsub25VcGRhdGV9IE9OIERFTEVURSAke2ZrLm9uRGVsZXRlfScpO2AsXG4gICAgKTtcbiAgfVxuXG4gIC8vIDguIOyZuOu2gCDthYzsnbTruJTsnZggRksg7KCc7JW97KGw6rG0IOuzteq1rFxuICBmb3IgKGNvbnN0IGZrIG9mIGV4dGVybmFsUmVmZXJlbmNpbmdGS3MpIHtcbiAgICBkb3duTGluZXMucHVzaChgICAvLyAke2ZrLnRhYmxlTmFtZX0uJHtmay5jb2x1bW5OYW1lfSBGSyDsoJzslb3sobDqsbQg67O16rWsYCk7XG4gICAgZG93bkxpbmVzLnB1c2goXG4gICAgICBgICBhd2FpdCBrbmV4LnJhdygnQUxURVIgVEFCTEUgXCIke2ZrLnRhYmxlTmFtZX1cIiBBREQgQ09OU1RSQUlOVCBcIiR7ZmsuY29uc3RyYWludE5hbWV9XCIgRk9SRUlHTiBLRVkgKFwiJHtmay5jb2x1bW5OYW1lfVwiKSBSRUZFUkVOQ0VTIFwiJHt0YWJsZX1cIihcImlkXCIpIE9OIFVQREFURSAke2ZrLm9uVXBkYXRlfSBPTiBERUxFVEUgJHtmay5vbkRlbGV0ZX0nKTtgLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXG4gICAgJ2ltcG9ydCB7IEtuZXggfSBmcm9tIFwia25leFwiOycsXG4gICAgXCJcIixcbiAgICBcImV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cChrbmV4OiBLbmV4KTogUHJvbWlzZTx2b2lkPiB7XCIsXG4gICAgLi4udXBMaW5lcyxcbiAgICBcIn1cIixcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd24oa25leDogS25leCk6IFByb21pc2U8dm9pZD4ge1wiLFxuICAgIC4uLmRvd25MaW5lcyxcbiAgICBcIn1cIixcbiAgXTtcblxuICBjb25zdCBmb3JtYXR0ZWQgPSBhd2FpdCBmb3JtYXRDb2RlKGxpbmVzLmpvaW4oXCJcXG5cIiksIFwidHlwZXNjcmlwdFwiLCBgc3JjL21pZ3JhdGlvbi8ke3RhYmxlfS50c2ApO1xuXG4gIHJldHVybiBbXG4gICAge1xuICAgICAgdGFibGUsXG4gICAgICB0aXRsZTogYGFsdGVyXyR7dGFibGV9X3BrX3R5cGVgLFxuICAgICAgZm9ybWF0dGVkLFxuICAgICAgdHlwZTogXCJub3JtYWxcIixcbiAgICB9LFxuICBdO1xufVxuXG4vKipcbiAqIFBLIOy7rOufvOydmCBQb3N0Z3JlU1FMIO2DgOyehSDrrLjsnpDsl7TsnYQg67CY7ZmY7ZWp64uI64ukLlxuICovXG5mdW5jdGlvbiBnZXRQa1BnVHlwZShjb2w6IE1pZ3JhdGlvbkNvbHVtbik6IHN0cmluZyB7XG4gIGlmIChjb2wudHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiBjb2wubGVuZ3RoICE9PSB1bmRlZmluZWQgPyBgdmFyY2hhcigke2NvbC5sZW5ndGh9KWAgOiBcInRleHRcIjtcbiAgfVxuICBpZiAoY29sLnR5cGUgPT09IFwidXVpZFwiKSB7XG4gICAgcmV0dXJuIFwidXVpZFwiO1xuICB9XG4gIC8vIGludGVnZXLsnZgg6rK97JqwIHNlcmlhbC9pbnRlZ2VyIOq1rOu2hOydtCDtlYTsmpTtlZjsp4Drp4wsXG4gIC8vIO2DgOyehSDrs4Dqsr0g7Iuc7JeQ64qUIGludGVnZXLroZwg7LKY66as7ZWp64uI64ukLlxuICByZXR1cm4gXCJpbnRlZ2VyXCI7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBMlJBLFNBQVMsc0JBQXNCLFFBQStEO0FBQzVGLFFBQU8sT0FBTyxXQUFXLE9BQU87O0FBR2xDLFNBQVMsNkJBQTZCLFlBQWlEO0NBQ3JGLE1BQU1BLFNBQXNDLEVBQUU7Q0FDOUMsSUFBSSxRQUFRO0FBRVosUUFBTyxRQUFRLFdBQVcsUUFBUTtFQUNoQyxN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
|