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,145 +1,130 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { __esmMin } from "../_virtual/rolldown_runtime.js";
|
|
2
2
|
import { group } from "radashi";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
*/ mapConstraintAction(action) {
|
|
129
|
-
const actionMap = {
|
|
130
|
-
"NO ACTION": "NO ACTION",
|
|
131
|
-
RESTRICT: "RESTRICT",
|
|
132
|
-
CASCADE: "CASCADE",
|
|
133
|
-
"SET NULL": "SET NULL",
|
|
134
|
-
"SET DEFAULT": "SET DEFAULT"
|
|
135
|
-
};
|
|
136
|
-
return actionMap[action] ?? "NO ACTION";
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* 기존 테이블 읽어서 cols, indexes, foreigns 반환
|
|
140
|
-
*/ async readTable(compareDB, tableName) {
|
|
141
|
-
// Columns 조회 (Generated Column 정보 포함)
|
|
142
|
-
const columnsQuery = `
|
|
3
|
+
import assert from "assert";
|
|
4
|
+
|
|
5
|
+
//#region src/migration/postgresql-schema-reader.ts
|
|
6
|
+
var PostgreSQLSchemaReaderClass, PostgreSQLSchemaReader;
|
|
7
|
+
var init_postgresql_schema_reader = __esmMin((() => {
|
|
8
|
+
PostgreSQLSchemaReaderClass = class {
|
|
9
|
+
genericIndexTypes = new Set([
|
|
10
|
+
"btree",
|
|
11
|
+
"hash",
|
|
12
|
+
"gin",
|
|
13
|
+
"gist",
|
|
14
|
+
"pgroonga"
|
|
15
|
+
]);
|
|
16
|
+
/**
|
|
17
|
+
* DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.
|
|
18
|
+
* @param compareDB Knex 인스턴스
|
|
19
|
+
* @param table 테이블 이름
|
|
20
|
+
* @returns MigrationSet 객체
|
|
21
|
+
*/
|
|
22
|
+
async getMigrationSetFromDB(compareDB, table) {
|
|
23
|
+
let dbColumns, dbIndexes, dbForeigns;
|
|
24
|
+
try {
|
|
25
|
+
[dbColumns, dbIndexes, dbForeigns] = await this.readTable(compareDB, table);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
if (e instanceof Error && e.message.includes("Table not found")) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
console.error(e);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const vectorDimensions = await this.getVectorDimensions(compareDB, table);
|
|
34
|
+
const columns = dbColumns.map((dbColumn) => {
|
|
35
|
+
const dbColType = this.resolveDBColType(dbColumn);
|
|
36
|
+
if (dbColType.type === "vector") {
|
|
37
|
+
dbColType.dimensions = vectorDimensions[dbColumn.column_name] ?? 0;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
name: dbColumn.column_name,
|
|
41
|
+
nullable: dbColumn.is_nullable === "YES",
|
|
42
|
+
...dbColType,
|
|
43
|
+
...(() => {
|
|
44
|
+
if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
|
|
45
|
+
return { generated: {
|
|
46
|
+
type: dbColumn.is_generated === "s" ? "STORED" : "VIRTUAL",
|
|
47
|
+
expression: dbColumn.generation_expression ?? ""
|
|
48
|
+
} };
|
|
49
|
+
}
|
|
50
|
+
return {};
|
|
51
|
+
})(),
|
|
52
|
+
...(() => {
|
|
53
|
+
if (dbColumn.is_generated === "s" || dbColumn.is_generated === "v") {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
if (dbColumn.column_default !== null) {
|
|
57
|
+
let defaultValue = dbColumn.column_default;
|
|
58
|
+
if (defaultValue.startsWith("nextval(")) {
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
defaultValue = defaultValue.replace(/::[\w\s]+$/g, "");
|
|
62
|
+
if (defaultValue.startsWith("'") && defaultValue.endsWith("'")) {
|
|
63
|
+
defaultValue = defaultValue.replaceAll("'", "\"");
|
|
64
|
+
}
|
|
65
|
+
return { defaultTo: defaultValue };
|
|
66
|
+
}
|
|
67
|
+
return {};
|
|
68
|
+
})()
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
const dbIndexesGroup = group(dbIndexes.filter((dbIndex) => !dbIndex.is_primary && !dbForeigns.find((dbForeign) => dbIndex.index_name.includes(dbForeign.constraint_name))), (dbIndex) => dbIndex.index_name);
|
|
72
|
+
const indexes = Object.keys(dbIndexesGroup).map((indexName) => {
|
|
73
|
+
const currentIndexes = dbIndexesGroup[indexName]?.toSorted((left, right) => left.column_order - right.column_order);
|
|
74
|
+
assert(currentIndexes);
|
|
75
|
+
const firstIndex = currentIndexes[0];
|
|
76
|
+
const parsedIndexDefinition = this.parseIndexDefinition(firstIndex.index_definition);
|
|
77
|
+
const restoredIndexType = this.restoreMigrationIndexType(firstIndex, parsedIndexDefinition.accessMethod);
|
|
78
|
+
const using = this.restoreGenericUsing(parsedIndexDefinition.accessMethod ?? firstIndex.index_type);
|
|
79
|
+
return {
|
|
80
|
+
type: restoredIndexType,
|
|
81
|
+
name: indexName,
|
|
82
|
+
columns: currentIndexes.map((idx) => ({
|
|
83
|
+
name: idx.column_name,
|
|
84
|
+
...this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1]) ? { opclass: this.extractIndexColumnOpclass(parsedIndexDefinition.columnDefinitions[idx.column_order - 1]) } : {},
|
|
85
|
+
...using === "btree" ? {
|
|
86
|
+
sortOrder: idx.sort_order,
|
|
87
|
+
nullsFirst: idx.nulls_first
|
|
88
|
+
} : {}
|
|
89
|
+
})),
|
|
90
|
+
nullsNotDistinct: firstIndex.nulls_not_distinct,
|
|
91
|
+
...using ? { using } : {},
|
|
92
|
+
...this.parseVectorIndexOptions(restoredIndexType, parsedIndexDefinition.withOptions)
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
const foreigns = dbForeigns.map((dbForeign) => {
|
|
96
|
+
return {
|
|
97
|
+
columns: [dbForeign.column_name],
|
|
98
|
+
to: `${dbForeign.foreign_table_name}.${dbForeign.foreign_column_name}`,
|
|
99
|
+
onUpdate: this.mapConstraintAction(dbForeign.update_rule),
|
|
100
|
+
onDelete: this.mapConstraintAction(dbForeign.delete_rule)
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
table,
|
|
105
|
+
columns,
|
|
106
|
+
indexes,
|
|
107
|
+
foreigns
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* PostgreSQL의 constraint action을 Knex 형식으로 변환
|
|
112
|
+
*/
|
|
113
|
+
mapConstraintAction(action) {
|
|
114
|
+
const actionMap = {
|
|
115
|
+
"NO ACTION": "NO ACTION",
|
|
116
|
+
RESTRICT: "RESTRICT",
|
|
117
|
+
CASCADE: "CASCADE",
|
|
118
|
+
"SET NULL": "SET NULL",
|
|
119
|
+
"SET DEFAULT": "SET DEFAULT"
|
|
120
|
+
};
|
|
121
|
+
return actionMap[action] ?? "NO ACTION";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 기존 테이블 읽어서 cols, indexes, foreigns 반환
|
|
125
|
+
*/
|
|
126
|
+
async readTable(compareDB, tableName) {
|
|
127
|
+
const columnsQuery = `
|
|
143
128
|
SELECT
|
|
144
129
|
c.column_name,
|
|
145
130
|
c.data_type,
|
|
@@ -167,14 +152,11 @@ class PostgreSQLSchemaReaderClass {
|
|
|
167
152
|
AND c.table_schema = 'public'
|
|
168
153
|
ORDER BY c.ordinal_position
|
|
169
154
|
`;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
// Indexes 조회 (PGroonga 표현식 인덱스 포함)
|
|
177
|
-
const indexesQuery = `
|
|
155
|
+
const columns = (await compareDB.raw(columnsQuery, [tableName])).rows;
|
|
156
|
+
if (columns.length === 0) {
|
|
157
|
+
throw new Error(`Table not found: ${tableName}`);
|
|
158
|
+
}
|
|
159
|
+
const indexesQuery = `
|
|
178
160
|
SELECT
|
|
179
161
|
i.relname AS index_name,
|
|
180
162
|
CASE
|
|
@@ -234,11 +216,8 @@ class PostgreSQLSchemaReaderClass {
|
|
|
234
216
|
AND (u.attnum > 0 OR (am.amname = 'pgroonga' AND u.attnum = 0))
|
|
235
217
|
ORDER BY i.relname, u.ord;
|
|
236
218
|
`;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
])).rows;
|
|
240
|
-
// Foreign Keys 조회
|
|
241
|
-
const foreignsQuery = `
|
|
219
|
+
const indexes = (await compareDB.raw(indexesQuery, [tableName])).rows;
|
|
220
|
+
const foreignsQuery = `
|
|
242
221
|
SELECT
|
|
243
222
|
tc.constraint_name,
|
|
244
223
|
kcu.column_name,
|
|
@@ -259,277 +238,268 @@ class PostgreSQLSchemaReaderClass {
|
|
|
259
238
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
260
239
|
AND tc.table_name = ?
|
|
261
240
|
`;
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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
|
-
|
|
499
|
-
|
|
500
|
-
|
|
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
|
-
return -1;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* 특정 테이블의 PK를 참조하는 다른 테이블의 FK 목록을 조회합니다.
|
|
530
|
-
* PK 타입 변경 시 관련 FK 제약조건을 삭제/복구하기 위해 사용됩니다.
|
|
531
|
-
*/ async getReferencingForeignKeys(db, tableName) {
|
|
532
|
-
const query = `
|
|
241
|
+
const foreigns = (await compareDB.raw(foreignsQuery, [tableName])).rows;
|
|
242
|
+
return [
|
|
243
|
+
columns,
|
|
244
|
+
indexes,
|
|
245
|
+
foreigns
|
|
246
|
+
];
|
|
247
|
+
}
|
|
248
|
+
restoreMigrationIndexType(index, accessMethod) {
|
|
249
|
+
const resolvedAccessMethod = (accessMethod ?? index.index_type).toLowerCase();
|
|
250
|
+
if (resolvedAccessMethod === "hnsw" || resolvedAccessMethod === "ivfflat") {
|
|
251
|
+
return resolvedAccessMethod;
|
|
252
|
+
}
|
|
253
|
+
return index.is_unique ? "unique" : "index";
|
|
254
|
+
}
|
|
255
|
+
restoreGenericUsing(accessMethod) {
|
|
256
|
+
if (!accessMethod) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
const normalized = accessMethod.toLowerCase();
|
|
260
|
+
if (!this.genericIndexTypes.has(normalized)) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
return normalized;
|
|
264
|
+
}
|
|
265
|
+
parseVectorIndexOptions(type, withOptions) {
|
|
266
|
+
if (type === "hnsw") {
|
|
267
|
+
return {
|
|
268
|
+
...this.parseIntegerOption(withOptions.m) !== undefined ? { m: this.parseIntegerOption(withOptions.m) } : {},
|
|
269
|
+
...this.parseIntegerOption(withOptions.ef_construction) !== undefined ? { efConstruction: this.parseIntegerOption(withOptions.ef_construction) } : {}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (type === "ivfflat") {
|
|
273
|
+
return this.parseIntegerOption(withOptions.lists) !== undefined ? { lists: this.parseIntegerOption(withOptions.lists) } : {};
|
|
274
|
+
}
|
|
275
|
+
return {};
|
|
276
|
+
}
|
|
277
|
+
parseIntegerOption(value) {
|
|
278
|
+
if (!value) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
const parsed = Number.parseInt(value, 10);
|
|
282
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
283
|
+
}
|
|
284
|
+
extractIndexColumnOpclass(columnDefinition) {
|
|
285
|
+
if (!columnDefinition) {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
const trimmed = columnDefinition.replace(/\s+NULLS\s+(FIRST|LAST)\s*$/i, "").replace(/\s+(ASC|DESC)\s*$/i, "").trim();
|
|
289
|
+
const tokens = this.tokenizeTopLevel(trimmed);
|
|
290
|
+
if (tokens.length < 2) {
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
if (tokens[tokens.length - 2]?.toUpperCase() === "COLLATE") {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
return tokens.at(-1);
|
|
297
|
+
}
|
|
298
|
+
parseIndexDefinition(indexDefinition) {
|
|
299
|
+
const accessMethod = indexDefinition.match(/\bUSING\s+([a-z_][\w]*)/i)?.[1]?.toLowerCase();
|
|
300
|
+
const usingMatchIndex = indexDefinition.search(/\bUSING\b/i);
|
|
301
|
+
const columnsStart = usingMatchIndex >= 0 ? indexDefinition.indexOf("(", usingMatchIndex) : -1;
|
|
302
|
+
const columnsEnd = columnsStart >= 0 ? this.findMatchingParenthesis(indexDefinition, columnsStart) : -1;
|
|
303
|
+
const columnDefinitions = columnsStart >= 0 && columnsEnd > columnsStart ? this.splitTopLevel(indexDefinition.slice(columnsStart + 1, columnsEnd), ",") : [];
|
|
304
|
+
const withMatch = /\bWITH\s*\(/i.exec(indexDefinition);
|
|
305
|
+
const withStart = withMatch ? indexDefinition.indexOf("(", withMatch.index) : -1;
|
|
306
|
+
const withEnd = withStart >= 0 ? this.findMatchingParenthesis(indexDefinition, withStart) : -1;
|
|
307
|
+
const withOptions = withStart >= 0 && withEnd > withStart ? this.parseIndexOptionEntries(indexDefinition.slice(withStart + 1, withEnd)) : {};
|
|
308
|
+
return {
|
|
309
|
+
accessMethod,
|
|
310
|
+
columnDefinitions,
|
|
311
|
+
withOptions
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
parseIndexOptionEntries(optionSource) {
|
|
315
|
+
return this.splitTopLevel(optionSource, ",").reduce((result, entry) => {
|
|
316
|
+
const matched = entry.trim().match(/^([a-z_][\w]*)\s*=\s*(.+)$/i);
|
|
317
|
+
if (!matched) {
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
const [, key, rawValue] = matched;
|
|
321
|
+
result[key.toLowerCase()] = rawValue.trim().replace(/^['"]|['"]$/g, "");
|
|
322
|
+
return result;
|
|
323
|
+
}, {});
|
|
324
|
+
}
|
|
325
|
+
splitTopLevel(source, delimiter) {
|
|
326
|
+
const items = [];
|
|
327
|
+
let start = 0;
|
|
328
|
+
let parenDepth = 0;
|
|
329
|
+
let bracketDepth = 0;
|
|
330
|
+
let inSingleQuote = false;
|
|
331
|
+
let inDoubleQuote = false;
|
|
332
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
333
|
+
const char = source[index];
|
|
334
|
+
const nextChar = source[index + 1];
|
|
335
|
+
if (char === "'" && !inDoubleQuote) {
|
|
336
|
+
if (inSingleQuote && nextChar === "'") {
|
|
337
|
+
index += 1;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
inSingleQuote = !inSingleQuote;
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (char === "\"" && !inSingleQuote) {
|
|
344
|
+
if (inDoubleQuote && nextChar === "\"") {
|
|
345
|
+
index += 1;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
inDoubleQuote = !inDoubleQuote;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (char === "(") {
|
|
355
|
+
parenDepth += 1;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (char === ")") {
|
|
359
|
+
parenDepth -= 1;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (char === "[") {
|
|
363
|
+
bracketDepth += 1;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (char === "]") {
|
|
367
|
+
bracketDepth -= 1;
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
if (char === delimiter && parenDepth === 0 && bracketDepth === 0) {
|
|
371
|
+
items.push(source.slice(start, index).trim());
|
|
372
|
+
start = index + 1;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const tail = source.slice(start).trim();
|
|
376
|
+
if (tail.length > 0) {
|
|
377
|
+
items.push(tail);
|
|
378
|
+
}
|
|
379
|
+
return items;
|
|
380
|
+
}
|
|
381
|
+
tokenizeTopLevel(source) {
|
|
382
|
+
const tokens = [];
|
|
383
|
+
let start = -1;
|
|
384
|
+
let parenDepth = 0;
|
|
385
|
+
let bracketDepth = 0;
|
|
386
|
+
let inSingleQuote = false;
|
|
387
|
+
let inDoubleQuote = false;
|
|
388
|
+
const pushToken = (endIndex) => {
|
|
389
|
+
if (start < 0) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const token = source.slice(start, endIndex).trim();
|
|
393
|
+
if (token.length > 0) {
|
|
394
|
+
tokens.push(token);
|
|
395
|
+
}
|
|
396
|
+
start = -1;
|
|
397
|
+
};
|
|
398
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
399
|
+
const char = source[index];
|
|
400
|
+
const nextChar = source[index + 1];
|
|
401
|
+
if (char === "'" && !inDoubleQuote) {
|
|
402
|
+
if (start < 0) {
|
|
403
|
+
start = index;
|
|
404
|
+
}
|
|
405
|
+
if (inSingleQuote && nextChar === "'") {
|
|
406
|
+
index += 1;
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
inSingleQuote = !inSingleQuote;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (char === "\"" && !inSingleQuote) {
|
|
413
|
+
if (start < 0) {
|
|
414
|
+
start = index;
|
|
415
|
+
}
|
|
416
|
+
if (inDoubleQuote && nextChar === "\"") {
|
|
417
|
+
index += 1;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
inDoubleQuote = !inDoubleQuote;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
if (!inSingleQuote && !inDoubleQuote) {
|
|
424
|
+
if (char === "(") {
|
|
425
|
+
if (start < 0) {
|
|
426
|
+
start = index;
|
|
427
|
+
}
|
|
428
|
+
parenDepth += 1;
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (char === ")") {
|
|
432
|
+
parenDepth -= 1;
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (char === "[") {
|
|
436
|
+
if (start < 0) {
|
|
437
|
+
start = index;
|
|
438
|
+
}
|
|
439
|
+
bracketDepth += 1;
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (char === "]") {
|
|
443
|
+
bracketDepth -= 1;
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
if (/\s/.test(char) && parenDepth === 0 && bracketDepth === 0) {
|
|
447
|
+
pushToken(index);
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (start < 0) {
|
|
452
|
+
start = index;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
pushToken(source.length);
|
|
456
|
+
return tokens;
|
|
457
|
+
}
|
|
458
|
+
findMatchingParenthesis(source, openIndex) {
|
|
459
|
+
let depth = 0;
|
|
460
|
+
let inSingleQuote = false;
|
|
461
|
+
let inDoubleQuote = false;
|
|
462
|
+
for (let index = openIndex; index < source.length; index += 1) {
|
|
463
|
+
const char = source[index];
|
|
464
|
+
const nextChar = source[index + 1];
|
|
465
|
+
if (char === "'" && !inDoubleQuote) {
|
|
466
|
+
if (inSingleQuote && nextChar === "'") {
|
|
467
|
+
index += 1;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
inSingleQuote = !inSingleQuote;
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
if (char === "\"" && !inSingleQuote) {
|
|
474
|
+
if (inDoubleQuote && nextChar === "\"") {
|
|
475
|
+
index += 1;
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
inDoubleQuote = !inDoubleQuote;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
if (char === "(") {
|
|
485
|
+
depth += 1;
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (char === ")") {
|
|
489
|
+
depth -= 1;
|
|
490
|
+
if (depth === 0) {
|
|
491
|
+
return index;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return -1;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* 특정 테이블의 PK를 참조하는 다른 테이블의 FK 목록을 조회합니다.
|
|
499
|
+
* PK 타입 변경 시 관련 FK 제약조건을 삭제/복구하기 위해 사용됩니다.
|
|
500
|
+
*/
|
|
501
|
+
async getReferencingForeignKeys(db, tableName) {
|
|
502
|
+
const query = `
|
|
533
503
|
SELECT
|
|
534
504
|
tc.table_name,
|
|
535
505
|
tc.constraint_name,
|
|
@@ -552,24 +522,23 @@ class PostgreSQLSchemaReaderClass {
|
|
|
552
522
|
AND ccu.table_name = ?
|
|
553
523
|
AND tc.table_schema = 'public'
|
|
554
524
|
`;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
const query = `
|
|
525
|
+
const result = await db.raw(query, [tableName]);
|
|
526
|
+
return result.rows.map((row) => ({
|
|
527
|
+
tableName: row.table_name,
|
|
528
|
+
constraintName: row.constraint_name,
|
|
529
|
+
columnName: row.column_name,
|
|
530
|
+
referencedTableName: row.referenced_table_name,
|
|
531
|
+
referencedColumnName: row.referenced_column_name,
|
|
532
|
+
onUpdate: this.mapConstraintAction(row.update_rule),
|
|
533
|
+
onDelete: this.mapConstraintAction(row.delete_rule)
|
|
534
|
+
}));
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* vector 컬럼의 dimensions를 조회합니다.
|
|
538
|
+
* pg_attribute의 atttypmod에서 차원 수를 추출합니다.
|
|
539
|
+
*/
|
|
540
|
+
async getVectorDimensions(compareDB, tableName) {
|
|
541
|
+
const query = `
|
|
573
542
|
SELECT
|
|
574
543
|
a.attname as column_name,
|
|
575
544
|
a.atttypmod as dimensions
|
|
@@ -580,125 +549,98 @@ class PostgreSQLSchemaReaderClass {
|
|
|
580
549
|
AND t.typname = 'vector'
|
|
581
550
|
AND a.attnum > 0
|
|
582
551
|
`;
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
...precision !== null && {
|
|
674
|
-
precision: precision
|
|
675
|
-
}
|
|
676
|
-
}; // DateProp → timestamptz
|
|
677
|
-
}
|
|
678
|
-
// JSON
|
|
679
|
-
if (udt_name === "json" || udt_name === "jsonb") {
|
|
680
|
-
return {
|
|
681
|
-
type: "json"
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
// Vector (pgvector)
|
|
685
|
-
if (udt_name === "vector") {
|
|
686
|
-
// vector 타입의 차원 수는 column_default나 별도 쿼리로 확인해야 함
|
|
687
|
-
// 현재는 기본값 0으로 설정 (실제 dimensions는 getMigrationSetFromDB에서 별도 쿼리로 확인)
|
|
688
|
-
return {
|
|
689
|
-
type: `vector${singleOrArray}`,
|
|
690
|
-
dimensions: 0
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
// tsvector (PostgreSQL 전문 검색용 타입)
|
|
694
|
-
if (udt_name === "tsvector") {
|
|
695
|
-
return {
|
|
696
|
-
type: "tsvector"
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
throw new Error(`resolve 불가능한 PostgreSQL 컬럼 타입: ${udt_name}`);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
export const PostgreSQLSchemaReader = new PostgreSQLSchemaReaderClass();
|
|
552
|
+
const result = await compareDB.raw(query, [tableName]);
|
|
553
|
+
const dimensions = {};
|
|
554
|
+
for (const row of result.rows) {
|
|
555
|
+
dimensions[row.column_name] = row.dimensions > 0 ? row.dimensions : 0;
|
|
556
|
+
}
|
|
557
|
+
return dimensions;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* PostgreSQL 컬럼 타입을 분석하여 MigrationColumn 객체로 변환합니다.
|
|
561
|
+
*/
|
|
562
|
+
resolveDBColType(dbColumn) {
|
|
563
|
+
const { udt_name: _udt_name, character_maximum_length, precision, numeric_scale } = dbColumn;
|
|
564
|
+
const { udt_name, singleOrArray } = (() => {
|
|
565
|
+
if (_udt_name.startsWith("_")) {
|
|
566
|
+
return {
|
|
567
|
+
udt_name: _udt_name.substring(1),
|
|
568
|
+
singleOrArray: "[]"
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
return {
|
|
572
|
+
udt_name: _udt_name,
|
|
573
|
+
singleOrArray: ""
|
|
574
|
+
};
|
|
575
|
+
})();
|
|
576
|
+
if (udt_name === "uuid") {
|
|
577
|
+
return { type: `uuid${singleOrArray}` };
|
|
578
|
+
}
|
|
579
|
+
if (udt_name === "int4") {
|
|
580
|
+
return { type: `integer${singleOrArray}` };
|
|
581
|
+
}
|
|
582
|
+
if (udt_name === "int8") {
|
|
583
|
+
return { type: `bigInteger${singleOrArray}` };
|
|
584
|
+
}
|
|
585
|
+
if (udt_name === "varchar") {
|
|
586
|
+
return {
|
|
587
|
+
type: `string${singleOrArray}`,
|
|
588
|
+
...character_maximum_length && { length: character_maximum_length }
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
if (udt_name === "text") {
|
|
592
|
+
return { type: `string${singleOrArray}` };
|
|
593
|
+
}
|
|
594
|
+
if (udt_name === "numeric") {
|
|
595
|
+
return {
|
|
596
|
+
type: `numberOrNumeric${singleOrArray}`,
|
|
597
|
+
numberType: "numeric",
|
|
598
|
+
...precision !== null && numeric_scale !== null && {
|
|
599
|
+
precision,
|
|
600
|
+
scale: numeric_scale
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
if (udt_name === "float4") {
|
|
605
|
+
return {
|
|
606
|
+
type: `numberOrNumeric${singleOrArray}`,
|
|
607
|
+
numberType: "real"
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
if (udt_name === "float8") {
|
|
611
|
+
return {
|
|
612
|
+
type: `numberOrNumeric${singleOrArray}`,
|
|
613
|
+
numberType: "double precision"
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (udt_name === "bool") {
|
|
617
|
+
return { type: `boolean${singleOrArray}` };
|
|
618
|
+
}
|
|
619
|
+
if (udt_name === "timestamptz") {
|
|
620
|
+
return {
|
|
621
|
+
type: `date${singleOrArray}`,
|
|
622
|
+
...precision !== null && { precision }
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
if (udt_name === "json" || udt_name === "jsonb") {
|
|
626
|
+
return { type: "json" };
|
|
627
|
+
}
|
|
628
|
+
if (udt_name === "vector") {
|
|
629
|
+
return {
|
|
630
|
+
type: `vector${singleOrArray}`,
|
|
631
|
+
dimensions: 0
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
if (udt_name === "tsvector") {
|
|
635
|
+
return { type: "tsvector" };
|
|
636
|
+
}
|
|
637
|
+
throw new Error(`resolve 불가능한 PostgreSQL 컬럼 타입: ${udt_name}`);
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
PostgreSQLSchemaReader = new PostgreSQLSchemaReaderClass();
|
|
641
|
+
}));
|
|
703
642
|
|
|
704
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24vcG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHR5cGUgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGdyb3VwIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB0eXBlIHtcbiAgTWlncmF0aW9uQ29sdW1uLFxuICBNaWdyYXRpb25Gb3JlaWduLFxuICBNaWdyYXRpb25JbmRleCxcbiAgTWlncmF0aW9uU2V0LFxuICBSZWxhdGlvbk9uLFxufSBmcm9tIFwiLi4vdHlwZXMvdHlwZXNcIjtcblxuLyoqXG4gKiDtirnsoJUg7YWM7J2067iU7J2YIFBL66W8IOywuOyhsO2VmOuKlCDri6Trpbgg7YWM7J2067iU7J2YIEZLIOygleuztOyeheuLiOuLpC5cbiAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOq0gOugqCBGSyDsoJzslb3sobDqsbTsnYQg7LKY66as7ZWY6riwIOychO2VtCDsgqzsmqnrkKnri4jri6QuXG4gKi9cbmV4cG9ydCB0eXBlIFJlZmVyZW5jaW5nRm9yZWlnbktleSA9IHtcbiAgLyoqIEZL6rCAIOygleydmOuQnCDthYzsnbTruJTrqoUgKi9cbiAgdGFibGVOYW1lOiBzdHJpbmc7XG4gIC8qKiBGSyDsoJzslb3sobDqsbQg7J2066aEICovXG4gIGNvbnN0cmFpbnROYW1lOiBzdHJpbmc7XG4gIC8qKiBGSyDsu6zrn7zrqoUgKi9cbiAgY29sdW1uTmFtZTogc3RyaW5nO1xuICAvKiog7LC47KGw7ZWY64qUIO2FjOydtOu4lOuqhSAoUEvqsIAg7J6I64qUIO2FjOydtOu4lCkgKi9cbiAgcmVmZXJlbmNlZFRhYmxlTmFtZTogc3RyaW5nO1xuICAvKiog7LC47KGw7ZWY64qUIOy7rOufvOuqhSAo67O07Ya1ICdpZCcpICovXG4gIHJlZmVyZW5jZWRDb2x1bW5OYW1lOiBzdHJpbmc7XG4gIC8qKiBPTiBVUERBVEUg7JWh7IWYICovXG4gIG9uVXBkYXRlOiBSZWxhdGlvbk9uO1xuICAvKiogT04gREVMRVRFIOyVoeyFmCAqL1xuICBvbkRlbGV0ZTogUmVsYXRpb25Pbjtcbn07XG5cbmV4cG9ydCB0eXBlIFBnQ29sdW1uID0ge1xuICBjb2x1bW5fbmFtZTogc3RyaW5nO1xuICBkYXRhX3R5cGU6IHN0cmluZztcbiAgdWR0X25hbWU6IHN0cmluZztcbiAgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoOiBudW1iZXIgfCBudWxsO1xuICBwcmVjaXNpb246IG51bWJlciB8IG51bGw7XG4gIG51bWVyaWNfc2NhbGU6IG51bWJlciB8IG51bGw7XG4gIGlzX251bGxhYmxlOiBzdHJpbmc7XG4gIGNvbHVtbl9kZWZhdWx0OiBzdHJpbmcgfCBudWxsO1xuICBpc19nZW5lcmF0ZWQ6IHN0cmluZzsgLy8gJ3MnID0gU1RPUkVELCAndicgPSBWSVJUVUFMLCAnJyA9IG5vbmVcbiAgZ2VuZXJhdGlvbl9leHByZXNzaW9uOiBzdHJpbmcgfCBudWxsO1xufTtcblxudHlwZSBQZ0luZGV4ID0ge1xuICBpbmRleF9uYW1lOiBzdHJpbmc7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGlzX3VuaXF1ZTogYm9vbGVhbjtcbiAgaXNfcHJpbWFyeTogYm9vbGVhbjtcbiAgaW5kZXhfdHlwZTogc3RyaW5nO1xuICBudWxsc19maXJzdDogYm9vbGVhbjtcbiAgc29ydF9vcmRlcjogXCJBU0NcIiB8IFwiREVTQ1wiO1xuICBudWxsc19ub3RfZGlzdGluY3Q6IGJvb2xlYW47XG4gIGNvbHVtbl9vcmRlcjogbnVtYmVyO1xuICBpbmRleF9kZWZpbml0aW9uOiBzdHJpbmc7XG59O1xuXG50eXBlIFBnRm9yZWlnbiA9IHtcbiAgY29uc3RyYWludF9uYW1lOiBzdHJpbmc7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGZvcmVpZ25fdGFibGVfbmFtZTogc3RyaW5nO1xuICBmb3JlaWduX2NvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIHVwZGF0ZV9ydWxlOiBzdHJpbmc7XG4gIGRlbGV0ZV9ydWxlOiBzdHJpbmc7XG59O1xuXG50eXBlIFJhd0NhcGFibGVLbmV4ID0gUGljazxLbmV4LCBcInJhd1wiPjtcblxuY2xhc3MgUG9zdGdyZVNRTFNjaGVtYVJlYWRlckNsYXNzIHtcbiAgcHJpdmF0ZSByZWFkb25seSBnZW5lcmljSW5kZXhUeXBlcyA9IG5ldyBTZXQoW1wiYnRyZWVcIiwgXCJoYXNoXCIsIFwiZ2luXCIsIFwiZ2lzdFwiLCBcInBncm9vbmdhXCJdKTtcblxuICAvKipcbiAgICogRELsl5DshJwg7YWM7J2067iUIOygleuztOulvCDsnb3slrTshJwgTWlncmF0aW9uU2V07J2EIOunjOuTpOyWtOyYteuLiOuLpC5cbiAgICogQHBhcmFtIGNvbXBhcmVEQiBLbmV4IOyduOyKpO2EtOyKpFxuICAgKiBAcGFyYW0gdGFibGUg7YWM7J2067iUIOydtOumhFxuICAgKiBAcmV0dXJucyBNaWdyYXRpb25TZXQg6rCd7LK0XG4gICAqL1xuICBhc3luYyBnZXRNaWdyYXRpb25TZXRGcm9tREIoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZTogc3RyaW5nLFxuICApOiBQcm9taXNlPE1pZ3JhdGlvblNldCB8IG51bGw+IHtcbiAgICBsZXQgZGJDb2x1bW5zOiBQZ0NvbHVtbltdLCBkYkluZGV4ZXM6IFBnSW5kZXhbXSwgZGJGb3JlaWduczogUGdGb3JlaWduW107XG4gICAgdHJ5IHtcbiAgICAgIFtkYkNvbHVtbnMsIGRiSW5kZXhlcywgZGJGb3JlaWduc10gPSBhd2FpdCB0aGlzLnJlYWRUYWJsZShjb21wYXJlREIsIHRhYmxlKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yICYmIGUubWVzc2FnZS5pbmNsdWRlcyhcIlRhYmxlIG5vdCBmb3VuZFwiKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyB2ZWN0b3Ig7Lus65+87J2YIGRpbWVuc2lvbnMg7KGw7ZqMXG4gICAgY29uc3QgdmVjdG9yRGltZW5zaW9ucyA9IGF3YWl0IHRoaXMuZ2V0VmVjdG9yRGltZW5zaW9ucyhjb21wYXJlREIsIHRhYmxlKTtcblxuICAgIGNvbnN0IGNvbHVtbnM6IE1pZ3JhdGlvbkNvbHVtbltdID0gZGJDb2x1bW5zLm1hcCgoZGJDb2x1bW4pID0+IHtcbiAgICAgIGNvbnN0IGRiQ29sVHlwZSA9IHRoaXMucmVzb2x2ZURCQ29sVHlwZShkYkNvbHVtbik7XG5cbiAgICAgIC8vIHZlY3RvciDtg4DsnoXsnbgg6rK97JqwIGRpbWVuc2lvbnMg7ISk7KCVXG4gICAgICBpZiAoZGJDb2xUeXBlLnR5cGUgPT09IFwidmVjdG9yXCIpIHtcbiAgICAgICAgZGJDb2xUeXBlLmRpbWVuc2lvbnMgPSB2ZWN0b3JEaW1lbnNpb25zW2RiQ29sdW1uLmNvbHVtbl9uYW1lXSA/PyAwO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBkYkNvbHVtbi5jb2x1bW5fbmFtZSxcbiAgICAgICAgbnVsbGFibGU6IGRiQ29sdW1uLmlzX251bGxhYmxlID09PSBcIllFU1wiLFxuICAgICAgICAuLi5kYkNvbFR5cGUsXG4gICAgICAgIC8vIEdlbmVyYXRlZCBDb2x1bW4g7LKY66asXG4gICAgICAgIC4uLigoKSA9PiB7XG4gICAgICAgICAgaWYgKGRiQ29sdW1uLmlzX2dlbmVyYXRlZCA9PT0gXCJzXCIgfHwgZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInZcIikge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZ2VuZXJhdGVkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiA/IFwiU1RPUkVEXCIgOiBcIlZJUlRVQUxcIixcbiAgICAgICAgICAgICAgICBleHByZXNzaW9uOiBkYkNvbHVtbi5nZW5lcmF0aW9uX2V4cHJlc3Npb24gPz8gXCJcIixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfSkoKSxcbiAgICAgICAgLy8gRGVmYXVsdCDqsJIg7LKY66asIChHZW5lcmF0ZWQgQ29sdW1u7J20IOyVhOuLjCDqsr3smrDrp4wpXG4gICAgICAgIC4uLigoKSA9PiB7XG4gICAgICAgICAgLy8gR2VuZXJhdGVkIENvbHVtbuydgCBkZWZhdWx0IOqwkuydtCDsl4bsnYxcbiAgICAgICAgICBpZiAoZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiB8fCBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwidlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGRiQ29sdW1uLmNvbHVtbl9kZWZhdWx0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBQb3N0Z3JlU1FMIGRlZmF1bHQg6rCSIOygleumrCAobmV4dHZhbCwgQ1VSUkVOVF9USU1FU1RBTVAg65OxKVxuICAgICAgICAgICAgbGV0IGRlZmF1bHRWYWx1ZSA9IGRiQ29sdW1uLmNvbHVtbl9kZWZhdWx0O1xuXG4gICAgICAgICAgICAvLyBuZXh0dmFsIOygnOqxsCAoU0VSSUFMIO2DgOyehSlcbiAgICAgICAgICAgIGlmIChkZWZhdWx0VmFsdWUuc3RhcnRzV2l0aChcIm5leHR2YWwoXCIpKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8g7YOA7J6FIOy6kOyKpO2MhSDsoJzqsbAgKOyYiDogJzEnOjppbnRlZ2VyIOKGkiAxKVxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlID0gZGVmYXVsdFZhbHVlLnJlcGxhY2UoLzo6W1xcd1xcc10rJC9nLCBcIlwiKTtcblxuICAgICAgICAgICAgLy8g65Sw7Ji07ZGc6rCAIHNpbmdsZSBxdW90ZeyduCDqsr3smrAgZG91YmxlIHF1b3Rl66GcIOuzgO2ZmFxuICAgICAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZS5zdGFydHNXaXRoKFwiJ1wiKSAmJiBkZWZhdWx0VmFsdWUuZW5kc1dpdGgoXCInXCIpKSB7XG4gICAgICAgICAgICAgIGRlZmF1bHRWYWx1ZSA9IGRlZmF1bHRWYWx1ZS5yZXBsYWNlQWxsKFwiJ1wiLCAnXCInKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgZGVmYXVsdFRvOiBkZWZhdWx0VmFsdWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH0pKCksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gUFJJTUFSWSBLRVnsmYAgZm9yZWlnbiBrZXnsmqkg7J24642x7IqkIOygnOyZuFxuICAgIGNvbnN0IGRiSW5kZXhlc0dyb3VwID0gZ3JvdXAoXG4gICAgICBkYkluZGV4ZXMuZmlsdGVyKFxuICAgICAgICAoZGJJbmRleCkgPT5cbiAgICAgICAgICAhZGJJbmRleC5pc19wcmltYXJ5ICYmXG4gICAgICAgICAgIWRiRm9yZWlnbnMuZmluZCgoZGJGb3JlaWduKSA9PiBkYkluZGV4LmluZGV4X25hbWUuaW5jbHVkZXMoZGJGb3JlaWduLmNvbnN0cmFpbnRfbmFtZSkpLFxuICAgICAgKSxcbiAgICAgIChkYkluZGV4KSA9PiBkYkluZGV4LmluZGV4X25hbWUsXG4gICAgKTtcblxuICAgIC8vIGluZGV4ZXMg7LKY66asXG4gICAgY29uc3QgaW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSA9IE9iamVjdC5rZXlzKGRiSW5kZXhlc0dyb3VwKS5tYXAoKGluZGV4TmFtZSkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudEluZGV4ZXMgPSBkYkluZGV4ZXNHcm91cFtpbmRleE5hbWVdPy50b1NvcnRlZChcbiAgICAgICAgKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LmNvbHVtbl9vcmRlciAtIHJpZ2h0LmNvbHVtbl9vcmRlcixcbiAgICAgICk7XG4gICAgICBhc3NlcnQoY3VycmVudEluZGV4ZXMpO1xuXG4gICAgICBjb25zdCBmaXJzdEluZGV4ID0gY3VycmVudEluZGV4ZXNbMF07XG4gICAgICBjb25zdCBwYXJzZWRJbmRleERlZmluaXRpb24gPSB0aGlzLnBhcnNlSW5kZXhEZWZpbml0aW9uKGZpcnN0SW5kZXguaW5kZXhfZGVmaW5pdGlvbik7XG4gICAgICBjb25zdCByZXN0b3JlZEluZGV4VHlwZSA9IHRoaXMucmVzdG9yZU1pZ3JhdGlvbkluZGV4VHlwZShcbiAgICAgICAgZmlyc3RJbmRleCxcbiAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmFjY2Vzc01ldGhvZCxcbiAgICAgICk7XG4gICAgICBjb25zdCB1c2luZyA9IHRoaXMucmVzdG9yZUdlbmVyaWNVc2luZyhcbiAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmFjY2Vzc01ldGhvZCA/PyBmaXJzdEluZGV4LmluZGV4X3R5cGUsXG4gICAgICApO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiByZXN0b3JlZEluZGV4VHlwZSxcbiAgICAgICAgbmFtZTogaW5kZXhOYW1lLFxuICAgICAgICBjb2x1bW5zOiBjdXJyZW50SW5kZXhlcy5tYXAoKGlkeCkgPT4gKHtcbiAgICAgICAgICBuYW1lOiBpZHguY29sdW1uX25hbWUsXG4gICAgICAgICAgLi4uKHRoaXMuZXh0cmFjdEluZGV4Q29sdW1uT3BjbGFzcyhcbiAgICAgICAgICAgIHBhcnNlZEluZGV4RGVmaW5pdGlvbi5jb2x1bW5EZWZpbml0aW9uc1tpZHguY29sdW1uX29yZGVyIC0gMV0sXG4gICAgICAgICAgKVxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgb3BjbGFzczogdGhpcy5leHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKFxuICAgICAgICAgICAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmNvbHVtbkRlZmluaXRpb25zW2lkeC5jb2x1bW5fb3JkZXIgLSAxXSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAuLi4odXNpbmcgPT09IFwiYnRyZWVcIlxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgc29ydE9yZGVyOiBpZHguc29ydF9vcmRlcixcbiAgICAgICAgICAgICAgICBudWxsc0ZpcnN0OiBpZHgubnVsbHNfZmlyc3QsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KSksXG5cbiAgICAgICAgbnVsbHNOb3REaXN0aW5jdDogZmlyc3RJbmRleC5udWxsc19ub3RfZGlzdGluY3QsXG4gICAgICAgIC4uLih1c2luZyA/IHsgdXNpbmcgfSA6IHt9KSxcbiAgICAgICAgLi4udGhpcy5wYXJzZVZlY3RvckluZGV4T3B0aW9ucyhyZXN0b3JlZEluZGV4VHlwZSwgcGFyc2VkSW5kZXhEZWZpbml0aW9uLndpdGhPcHRpb25zKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBmb3JlaWducyDsspjrpqxcbiAgICBjb25zdCBmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdID0gZGJGb3JlaWducy5tYXAoKGRiRm9yZWlnbikgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29sdW1uczogW2RiRm9yZWlnbi5jb2x1bW5fbmFtZV0sXG4gICAgICAgIHRvOiBgJHtkYkZvcmVpZ24uZm9yZWlnbl90YWJsZV9uYW1lfS4ke2RiRm9yZWlnbi5mb3JlaWduX2NvbHVtbl9uYW1lfWAsXG4gICAgICAgIG9uVXBkYXRlOiB0aGlzLm1hcENvbnN0cmFpbnRBY3Rpb24oZGJGb3JlaWduLnVwZGF0ZV9ydWxlKSxcbiAgICAgICAgb25EZWxldGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihkYkZvcmVpZ24uZGVsZXRlX3J1bGUpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0YWJsZSxcbiAgICAgIGNvbHVtbnMsXG4gICAgICBpbmRleGVzLFxuICAgICAgZm9yZWlnbnMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3N0Z3JlU1FM7J2YIGNvbnN0cmFpbnQgYWN0aW9u7J2EIEtuZXgg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgKi9cbiAgcHJpdmF0ZSBtYXBDb25zdHJhaW50QWN0aW9uKGFjdGlvbjogc3RyaW5nKTogUmVsYXRpb25PbiB7XG4gICAgY29uc3QgYWN0aW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBSZWxhdGlvbk9uPiA9IHtcbiAgICAgIFwiTk8gQUNUSU9OXCI6IFwiTk8gQUNUSU9OXCIsXG4gICAgICBSRVNUUklDVDogXCJSRVNUUklDVFwiLFxuICAgICAgQ0FTQ0FERTogXCJDQVNDQURFXCIsXG4gICAgICBcIlNFVCBOVUxMXCI6IFwiU0VUIE5VTExcIixcbiAgICAgIFwiU0VUIERFRkFVTFRcIjogXCJTRVQgREVGQVVMVFwiLFxuICAgIH07XG4gICAgcmV0dXJuIGFjdGlvbk1hcFthY3Rpb25dID8/IFwiTk8gQUNUSU9OXCI7XG4gIH1cblxuICAvKipcbiAgICog6riw7KG0IO2FjOydtOu4lCDsnb3slrTshJwgY29scywgaW5kZXhlcywgZm9yZWlnbnMg67CY7ZmYXG4gICAqL1xuICBhc3luYyByZWFkVGFibGUoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxbUGdDb2x1bW5bXSwgUGdJbmRleFtdLCBQZ0ZvcmVpZ25bXV0+IHtcbiAgICAvLyBDb2x1bW5zIOyhsO2ajCAoR2VuZXJhdGVkIENvbHVtbiDsoJXrs7Qg7Y+s7ZWoKVxuICAgIGNvbnN0IGNvbHVtbnNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICBjLmNvbHVtbl9uYW1lLFxuICAgICAgICBjLmRhdGFfdHlwZSxcbiAgICAgICAgYy51ZHRfbmFtZSxcbiAgICAgICAgQ09BTEVTQ0UoXG4gICAgICAgICAgYy5jaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsXG4gICAgICAgICAgQ0FTRSBXSEVOIGMuZGF0YV90eXBlID0gJ0FSUkFZJyBBTkQgYS5hdHR0eXBtb2QgPiAwXG4gICAgICAgICAgICBUSEVOIGEuYXR0dHlwbW9kIC0gNFxuICAgICAgICAgICAgRUxTRSBOVUxMXG4gICAgICAgICAgRU5EXG4gICAgICAgICkgQVMgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLFxuICAgICAgICBDT0FMRVNDRShjLmRhdGV0aW1lX3ByZWNpc2lvbiwgYy5udW1lcmljX3ByZWNpc2lvbikgQVMgcHJlY2lzaW9uLFxuICAgICAgICBjLm51bWVyaWNfc2NhbGUsXG4gICAgICAgIGMuaXNfbnVsbGFibGUsXG4gICAgICAgIGMuY29sdW1uX2RlZmF1bHQsXG4gICAgICAgIENPQUxFU0NFKGEuYXR0Z2VuZXJhdGVkLCAnJykgYXMgaXNfZ2VuZXJhdGVkLFxuICAgICAgICBjLmdlbmVyYXRpb25fZXhwcmVzc2lvblxuICAgICAgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEuY29sdW1ucyBjXG4gICAgICBMRUZUIEpPSU4gcGdfYXR0cmlidXRlIGEgT04gYS5hdHRuYW1lID0gYy5jb2x1bW5fbmFtZVxuICAgICAgICBBTkQgYS5hdHRyZWxpZCA9IChcbiAgICAgICAgICBTRUxFQ1Qgb2lkIEZST00gcGdfY2xhc3MgV0hFUkUgcmVsbmFtZSA9IGMudGFibGVfbmFtZVxuICAgICAgICAgIEFORCByZWxuYW1lc3BhY2UgPSAoU0VMRUNUIG9pZCBGUk9NIHBnX25hbWVzcGFjZSBXSEVSRSBuc3BuYW1lID0gYy50YWJsZV9zY2hlbWEpXG4gICAgICAgIClcbiAgICAgIFdIRVJFIGMudGFibGVfbmFtZSA9ID9cbiAgICAgICAgQU5EIGMudGFibGVfc2NoZW1hID0gJ3B1YmxpYydcbiAgICAgIE9SREVSIEJZIGMub3JkaW5hbF9wb3NpdGlvblxuICAgIGA7XG4gICAgY29uc3QgY29sdW1ucyA9IChhd2FpdCBjb21wYXJlREIucmF3KGNvbHVtbnNRdWVyeSwgW3RhYmxlTmFtZV0pKS5yb3dzIGFzIFBnQ29sdW1uW107XG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlIG5vdCBmb3VuZDogJHt0YWJsZU5hbWV9YCk7XG4gICAgfVxuXG4gICAgLy8gSW5kZXhlcyDsobDtmowgKFBHcm9vbmdhIO2RnO2YhOyLnSDsnbjrjbHsiqQg7Y+s7ZWoKVxuICAgIGNvbnN0IGluZGV4ZXNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICAgIGkucmVsbmFtZSBBUyBpbmRleF9uYW1lLFxuICAgICAgICAgIENBU0VcbiAgICAgICAgICAgICAgV0hFTiBhbS5hbW5hbWUgPSAncGdyb29uZ2EnIEFORCB1LmF0dG51bSA9IDAgVEhFTlxuICAgICAgICAgICAgICAgICAgcmVnZXhwX3JlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAgICAgcmVnZXhwX3JlcGxhY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFRSSU0ocGdyb29uZ2FfY29sLmNvbHVtbl9leHByKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJzo6dGV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnZydcbiAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICdbKCldJyxcbiAgICAgICAgICAgICAgICAgICAgICAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAnZydcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgRUxTRSBhLmF0dG5hbWVcbiAgICAgICAgICBFTkQgQVMgY29sdW1uX25hbWUsXG4gICAgICAgICAgaXguaW5kaXN1bmlxdWUgQVMgaXNfdW5pcXVlLFxuICAgICAgICAgIGl4LmluZGlzcHJpbWFyeSBBUyBpc19wcmltYXJ5LFxuICAgICAgICAgIGFtLmFtbmFtZSBBUyBpbmRleF90eXBlLFxuICAgICAgICAgIENPQUxFU0NFKCh1Lm9wdCAmIDIpID0gMiwgRkFMU0UpIEFTIG51bGxzX2ZpcnN0LFxuICAgICAgICAgIENBU0UgXG4gICAgICAgICAgICAgIFdIRU4gKHUub3B0ICYgMSkgPSAxIFRIRU4gJ0RFU0MnXG4gICAgICAgICAgICAgIEVMU0UgJ0FTQydcbiAgICAgICAgICBFTkQgQVMgc29ydF9vcmRlcixcbiAgICAgICAgICBpeC5pbmRudWxsc25vdGRpc3RpbmN0IEFTIG51bGxzX25vdF9kaXN0aW5jdCxcbiAgICAgICAgICB1Lm9yZCBBUyBjb2x1bW5fb3JkZXIsXG4gICAgICAgICAgcGdfZ2V0X2luZGV4ZGVmKGl4LmluZGV4cmVsaWQpIEFTIGluZGV4X2RlZmluaXRpb25cbiAgICAgIEZST00gcGdfY2xhc3MgdFxuICAgICAgSk9JTiBwZ19pbmRleCBpeCBPTiB0Lm9pZCA9IGl4LmluZHJlbGlkXG4gICAgICBKT0lOIHBnX2NsYXNzIGkgT04gaS5vaWQgPSBpeC5pbmRleHJlbGlkXG4gICAgICBKT0lOIHBnX2FtIGFtIE9OIGkucmVsYW0gPSBhbS5vaWRcbiAgICAgIEpPSU4gTEFURVJBTCB1bm5lc3QoaXguaW5ka2V5LCBpeC5pbmRvcHRpb24pXG4gICAgICAgICAgV0lUSCBPUkRJTkFMSVRZIEFTIHUoYXR0bnVtLCBvcHQsIG9yZCkgT04gdHJ1ZVxuICAgICAgTEVGVCBKT0lOIHBnX2F0dHJpYnV0ZSBhIE9OIGEuYXR0cmVsaWQgPSB0Lm9pZCBcbiAgICAgICAgICBBTkQgYS5hdHRudW0gPSB1LmF0dG51bSBcbiAgICAgICAgICBBTkQgdS5hdHRudW0gPiAwXG4gICAgICBMRUZUIEpPSU4gTEFURVJBTCAoXG4gICAgICAgICAgU0VMRUNUIFxuICAgICAgICAgICAgICB1bm5lc3QoXG4gICAgICAgICAgICAgICAgICBDQVNFIFxuICAgICAgICAgICAgICAgICAgICAgIFdIRU4gcGdfZ2V0X2V4cHIoaXguaW5kZXhwcnMsIGl4LmluZHJlbGlkKSB+ICdeQVJSQVlcXFxcWycgVEhFTlxuICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdfdG9fYXJyYXkoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZ19nZXRfZXhwcihpeC5pbmRleHBycywgaXguaW5kcmVsaWQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdeQVJSQVlcXFxcWyguKilcXFxcXSQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcXFxcMSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLCAnXG4gICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICBFTFNFXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEFSUkFZW3BnX2dldF9leHByKGl4LmluZGV4cHJzLCBpeC5pbmRyZWxpZCldXG4gICAgICAgICAgICAgICAgICBFTkRcbiAgICAgICAgICAgICAgKSBhcyBjb2x1bW5fZXhwclxuICAgICAgKSBwZ3Jvb25nYV9jb2wgT04gYW0uYW1uYW1lID0gJ3Bncm9vbmdhJyBBTkQgdS5hdHRudW0gPSAwXG4gICAgICBXSEVSRSB0LnJlbG5hbWUgPSA/XG4gICAgICAgICAgQU5EICh1LmF0dG51bSA+IDAgT1IgKGFtLmFtbmFtZSA9ICdwZ3Jvb25nYScgQU5EIHUuYXR0bnVtID0gMCkpXG4gICAgICBPUkRFUiBCWSBpLnJlbG5hbWUsIHUub3JkO1xuYDtcbiAgICBjb25zdCBpbmRleGVzID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoaW5kZXhlc1F1ZXJ5LCBbdGFibGVOYW1lXSkpLnJvd3M7XG5cbiAgICAvLyBGb3JlaWduIEtleXMg7KGw7ZqMXG4gICAgY29uc3QgZm9yZWlnbnNRdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICB0Yy5jb25zdHJhaW50X25hbWUsXG4gICAgICAgIGtjdS5jb2x1bW5fbmFtZSxcbiAgICAgICAgY2N1LnRhYmxlX25hbWUgQVMgZm9yZWlnbl90YWJsZV9uYW1lLFxuICAgICAgICBjY3UuY29sdW1uX25hbWUgQVMgZm9yZWlnbl9jb2x1bW5fbmFtZSxcbiAgICAgICAgcmMudXBkYXRlX3J1bGUsXG4gICAgICAgIHJjLmRlbGV0ZV9ydWxlXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZV9jb25zdHJhaW50cyBBUyB0Y1xuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEua2V5X2NvbHVtbl91c2FnZSBBUyBrY3VcbiAgICAgICAgT04gdGMuY29uc3RyYWludF9uYW1lID0ga2N1LmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0ga2N1LnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEuY29uc3RyYWludF9jb2x1bW5fdXNhZ2UgQVMgY2N1XG4gICAgICAgIE9OIGNjdS5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIGNjdS50YWJsZV9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLnJlZmVyZW50aWFsX2NvbnN0cmFpbnRzIEFTIHJjXG4gICAgICAgIE9OIHJjLmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgcmMuY29uc3RyYWludF9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIFdIRVJFIHRjLmNvbnN0cmFpbnRfdHlwZSA9ICdGT1JFSUdOIEtFWSdcbiAgICAgICAgQU5EIHRjLnRhYmxlX25hbWUgPSA/XG4gICAgYDtcbiAgICBjb25zdCBmb3JlaWducyA9IChhd2FpdCBjb21wYXJlREIucmF3KGZvcmVpZ25zUXVlcnksIFt0YWJsZU5hbWVdKSkucm93cztcblxuICAgIHJldHVybiBbY29sdW1ucywgaW5kZXhlcywgZm9yZWlnbnNdO1xuICB9XG5cbiAgcHJpdmF0ZSByZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlKFxuICAgIGluZGV4OiBQaWNrPFBnSW5kZXgsIFwiaXNfdW5pcXVlXCIgfCBcImluZGV4X3R5cGVcIj4sXG4gICAgYWNjZXNzTWV0aG9kPzogc3RyaW5nLFxuICApOiBNaWdyYXRpb25JbmRleFtcInR5cGVcIl0ge1xuICAgIGNvbnN0IHJlc29sdmVkQWNjZXNzTWV0aG9kID0gKGFjY2Vzc01ldGhvZCA/PyBpbmRleC5pbmRleF90eXBlKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgaWYgKHJlc29sdmVkQWNjZXNzTWV0aG9kID09PSBcImhuc3dcIiB8fCByZXNvbHZlZEFjY2Vzc01ldGhvZCA9PT0gXCJpdmZmbGF0XCIpIHtcbiAgICAgIHJldHVybiByZXNvbHZlZEFjY2Vzc01ldGhvZDtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5kZXguaXNfdW5pcXVlID8gXCJ1bmlxdWVcIiA6IFwiaW5kZXhcIjtcbiAgfVxuXG4gIHByaXZhdGUgcmVzdG9yZUdlbmVyaWNVc2luZyhcbiAgICBhY2Nlc3NNZXRob2Q6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgKTogTWlncmF0aW9uSW5kZXhbXCJ1c2luZ1wiXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFhY2Nlc3NNZXRob2QpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IGFjY2Vzc01ldGhvZC50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5nZW5lcmljSW5kZXhUeXBlcy5oYXMobm9ybWFsaXplZCkpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQgYXMgTWlncmF0aW9uSW5kZXhbXCJ1c2luZ1wiXTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VWZWN0b3JJbmRleE9wdGlvbnMoXG4gICAgdHlwZTogTWlncmF0aW9uSW5kZXhbXCJ0eXBlXCJdLFxuICAgIHdpdGhPcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICApOiBQaWNrPE1pZ3JhdGlvbkluZGV4LCBcIm1cIiB8IFwiZWZDb25zdHJ1Y3Rpb25cIiB8IFwibGlzdHNcIj4ge1xuICAgIGlmICh0eXBlID09PSBcImhuc3dcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLm0pICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgbTogdGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubSkgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMuZWZfY29uc3RydWN0aW9uKSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyB7IGVmQ29uc3RydWN0aW9uOiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5lZl9jb25zdHJ1Y3Rpb24pIH1cbiAgICAgICAgICA6IHt9KSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgPT09IFwiaXZmZmxhdFwiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubGlzdHMpICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgbGlzdHM6IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmxpc3RzKSB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJbnRlZ2VyT3B0aW9uKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VkID0gTnVtYmVyLnBhcnNlSW50KHZhbHVlLCAxMCk7XG4gICAgcmV0dXJuIE51bWJlci5pc05hTihwYXJzZWQpID8gdW5kZWZpbmVkIDogcGFyc2VkO1xuICB9XG5cbiAgcHJpdmF0ZSBleHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKGNvbHVtbkRlZmluaXRpb246IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFjb2x1bW5EZWZpbml0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHRyaW1tZWQgPSBjb2x1bW5EZWZpbml0aW9uXG4gICAgICAucmVwbGFjZSgvXFxzK05VTExTXFxzKyhGSVJTVHxMQVNUKVxccyokL2ksIFwiXCIpXG4gICAgICAucmVwbGFjZSgvXFxzKyhBU0N8REVTQylcXHMqJC9pLCBcIlwiKVxuICAgICAgLnRyaW0oKTtcbiAgICBjb25zdCB0b2tlbnMgPSB0aGlzLnRva2VuaXplVG9wTGV2ZWwodHJpbW1lZCk7XG5cbiAgICBpZiAodG9rZW5zLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKHRva2Vuc1t0b2tlbnMubGVuZ3RoIC0gMl0/LnRvVXBwZXJDYXNlKCkgPT09IFwiQ09MTEFURVwiKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0b2tlbnMuYXQoLTEpO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUluZGV4RGVmaW5pdGlvbihpbmRleERlZmluaXRpb246IHN0cmluZyk6IHtcbiAgICBhY2Nlc3NNZXRob2Q/OiBzdHJpbmc7XG4gICAgY29sdW1uRGVmaW5pdGlvbnM6IHN0cmluZ1tdO1xuICAgIHdpdGhPcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICB9IHtcbiAgICBjb25zdCBhY2Nlc3NNZXRob2QgPSBpbmRleERlZmluaXRpb24ubWF0Y2goL1xcYlVTSU5HXFxzKyhbYS16X11bXFx3XSopL2kpPy5bMV0/LnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgdXNpbmdNYXRjaEluZGV4ID0gaW5kZXhEZWZpbml0aW9uLnNlYXJjaCgvXFxiVVNJTkdcXGIvaSk7XG4gICAgY29uc3QgY29sdW1uc1N0YXJ0ID0gdXNpbmdNYXRjaEluZGV4ID49IDAgPyBpbmRleERlZmluaXRpb24uaW5kZXhPZihcIihcIiwgdXNpbmdNYXRjaEluZGV4KSA6IC0xO1xuICAgIGNvbnN0IGNvbHVtbnNFbmQgPVxuICAgICAgY29sdW1uc1N0YXJ0ID49IDAgPyB0aGlzLmZpbmRNYXRjaGluZ1BhcmVudGhlc2lzKGluZGV4RGVmaW5pdGlvbiwgY29sdW1uc1N0YXJ0KSA6IC0xO1xuICAgIGNvbnN0IGNvbHVtbkRlZmluaXRpb25zID1cbiAgICAgIGNvbHVtbnNTdGFydCA+PSAwICYmIGNvbHVtbnNFbmQgPiBjb2x1bW5zU3RhcnRcbiAgICAgICAgPyB0aGlzLnNwbGl0VG9wTGV2ZWwoaW5kZXhEZWZpbml0aW9uLnNsaWNlKGNvbHVtbnNTdGFydCArIDEsIGNvbHVtbnNFbmQpLCBcIixcIilcbiAgICAgICAgOiBbXTtcblxuICAgIGNvbnN0IHdpdGhNYXRjaCA9IC9cXGJXSVRIXFxzKlxcKC9pLmV4ZWMoaW5kZXhEZWZpbml0aW9uKTtcbiAgICBjb25zdCB3aXRoU3RhcnQgPSB3aXRoTWF0Y2ggPyBpbmRleERlZmluaXRpb24uaW5kZXhPZihcIihcIiwgd2l0aE1hdGNoLmluZGV4KSA6IC0xO1xuICAgIGNvbnN0IHdpdGhFbmQgPSB3aXRoU3RhcnQgPj0gMCA/IHRoaXMuZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoaW5kZXhEZWZpbml0aW9uLCB3aXRoU3RhcnQpIDogLTE7XG4gICAgY29uc3Qgd2l0aE9wdGlvbnMgPVxuICAgICAgd2l0aFN0YXJ0ID49IDAgJiYgd2l0aEVuZCA+IHdpdGhTdGFydFxuICAgICAgICA/IHRoaXMucGFyc2VJbmRleE9wdGlvbkVudHJpZXMoaW5kZXhEZWZpbml0aW9uLnNsaWNlKHdpdGhTdGFydCArIDEsIHdpdGhFbmQpKVxuICAgICAgICA6IHt9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY2Vzc01ldGhvZCxcbiAgICAgIGNvbHVtbkRlZmluaXRpb25zLFxuICAgICAgd2l0aE9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJbmRleE9wdGlvbkVudHJpZXMob3B0aW9uU291cmNlOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5zcGxpdFRvcExldmVsKG9wdGlvblNvdXJjZSwgXCIsXCIpLnJlZHVjZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PigocmVzdWx0LCBlbnRyeSkgPT4ge1xuICAgICAgY29uc3QgbWF0Y2hlZCA9IGVudHJ5LnRyaW0oKS5tYXRjaCgvXihbYS16X11bXFx3XSopXFxzKj1cXHMqKC4rKSQvaSk7XG4gICAgICBpZiAoIW1hdGNoZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgWywga2V5LCByYXdWYWx1ZV0gPSBtYXRjaGVkO1xuICAgICAgcmVzdWx0W2tleS50b0xvd2VyQ2FzZSgpXSA9IHJhd1ZhbHVlLnRyaW0oKS5yZXBsYWNlKC9eWydcIl18WydcIl0kL2csIFwiXCIpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCB7fSk7XG4gIH1cblxuICBwcml2YXRlIHNwbGl0VG9wTGV2ZWwoc291cmNlOiBzdHJpbmcsIGRlbGltaXRlcjogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGl0ZW1zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IHBhcmVuRGVwdGggPSAwO1xuICAgIGxldCBicmFja2V0RGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBzb3VyY2UubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICBjb25zdCBjaGFyID0gc291cmNlW2luZGV4XTtcbiAgICAgIGNvbnN0IG5leHRDaGFyID0gc291cmNlW2luZGV4ICsgMV07XG5cbiAgICAgIGlmIChjaGFyID09PSBcIidcIiAmJiAhaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBpZiAoaW5TaW5nbGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gXCInXCIpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluU2luZ2xlUXVvdGUgPSAhaW5TaW5nbGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSAnXCInICYmICFpblNpbmdsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpbkRvdWJsZVF1b3RlICYmIG5leHRDaGFyID09PSAnXCInKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpbkRvdWJsZVF1b3RlID0gIWluRG91YmxlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5TaW5nbGVRdW90ZSB8fCBpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gXCIoXCIpIHtcbiAgICAgICAgcGFyZW5EZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFyID09PSBcIilcIikge1xuICAgICAgICBwYXJlbkRlcHRoIC09IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiW1wiKSB7XG4gICAgICAgIGJyYWNrZXREZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFyID09PSBcIl1cIikge1xuICAgICAgICBicmFja2V0RGVwdGggLT0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBkZWxpbWl0ZXIgJiYgcGFyZW5EZXB0aCA9PT0gMCAmJiBicmFja2V0RGVwdGggPT09IDApIHtcbiAgICAgICAgaXRlbXMucHVzaChzb3VyY2Uuc2xpY2Uoc3RhcnQsIGluZGV4KS50cmltKCkpO1xuICAgICAgICBzdGFydCA9IGluZGV4ICsgMTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0YWlsID0gc291cmNlLnNsaWNlKHN0YXJ0KS50cmltKCk7XG4gICAgaWYgKHRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgaXRlbXMucHVzaCh0YWlsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cblxuICBwcml2YXRlIHRva2VuaXplVG9wTGV2ZWwoc291cmNlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgdG9rZW5zOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBzdGFydCA9IC0xO1xuICAgIGxldCBwYXJlbkRlcHRoID0gMDtcbiAgICBsZXQgYnJhY2tldERlcHRoID0gMDtcbiAgICBsZXQgaW5TaW5nbGVRdW90ZSA9IGZhbHNlO1xuICAgIGxldCBpbkRvdWJsZVF1b3RlID0gZmFsc2U7XG5cbiAgICBjb25zdCBwdXNoVG9rZW4gPSAoZW5kSW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRva2VuID0gc291cmNlLnNsaWNlKHN0YXJ0LCBlbmRJbmRleCkudHJpbSgpO1xuICAgICAgaWYgKHRva2VuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdG9rZW5zLnB1c2godG9rZW4pO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSAtMTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghaW5TaW5nbGVRdW90ZSAmJiAhaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBpZiAoY2hhciA9PT0gXCIoXCIpIHtcbiAgICAgICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJlbkRlcHRoICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgICAgcGFyZW5EZXB0aCAtPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFyID09PSBcIltcIikge1xuICAgICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyYWNrZXREZXB0aCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFyID09PSBcIl1cIikge1xuICAgICAgICAgIGJyYWNrZXREZXB0aCAtPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKC9cXHMvLnRlc3QoY2hhcikgJiYgcGFyZW5EZXB0aCA9PT0gMCAmJiBicmFja2V0RGVwdGggPT09IDApIHtcbiAgICAgICAgICBwdXNoVG9rZW4oaW5kZXgpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwdXNoVG9rZW4oc291cmNlLmxlbmd0aCk7XG4gICAgcmV0dXJuIHRva2VucztcbiAgfVxuXG4gIHByaXZhdGUgZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoc291cmNlOiBzdHJpbmcsIG9wZW5JbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgZGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gb3BlbkluZGV4OyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpblNpbmdsZVF1b3RlIHx8IGluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICBkZXB0aCArPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgIGRlcHRoIC09IDE7XG4gICAgICAgIGlmIChkZXB0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiDtirnsoJUg7YWM7J2067iU7J2YIFBL66W8IOywuOyhsO2VmOuKlCDri6Trpbgg7YWM7J2067iU7J2YIEZLIOuqqeuhneydhCDsobDtmoztlanri4jri6QuXG4gICAqIFBLIO2DgOyehSDrs4Dqsr0g7IucIOq0gOugqCBGSyDsoJzslb3sobDqsbTsnYQg7IKt7KCcL+uzteq1rO2VmOq4sCDsnITtlbQg7IKs7Jqp65Cp64uI64ukLlxuICAgKi9cbiAgYXN5bmMgZ2V0UmVmZXJlbmNpbmdGb3JlaWduS2V5cyhkYjogS25leCwgdGFibGVOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFJlZmVyZW5jaW5nRm9yZWlnbktleVtdPiB7XG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBTRUxFQ1RcbiAgICAgICAgdGMudGFibGVfbmFtZSxcbiAgICAgICAgdGMuY29uc3RyYWludF9uYW1lLFxuICAgICAgICBrY3UuY29sdW1uX25hbWUsXG4gICAgICAgIGNjdS50YWJsZV9uYW1lIEFTIHJlZmVyZW5jZWRfdGFibGVfbmFtZSxcbiAgICAgICAgY2N1LmNvbHVtbl9uYW1lIEFTIHJlZmVyZW5jZWRfY29sdW1uX25hbWUsXG4gICAgICAgIHJjLnVwZGF0ZV9ydWxlLFxuICAgICAgICByYy5kZWxldGVfcnVsZVxuICAgICAgRlJPTSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVfY29uc3RyYWludHMgQVMgdGNcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLmtleV9jb2x1bW5fdXNhZ2UgQVMga2N1XG4gICAgICAgIE9OIHRjLmNvbnN0cmFpbnRfbmFtZSA9IGtjdS5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIHRjLnRhYmxlX3NjaGVtYSA9IGtjdS50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLmNvbnN0cmFpbnRfY29sdW1uX3VzYWdlIEFTIGNjdVxuICAgICAgICBPTiBjY3UuY29uc3RyYWludF9uYW1lID0gdGMuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCBjY3UudGFibGVfc2NoZW1hID0gdGMudGFibGVfc2NoZW1hXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5yZWZlcmVudGlhbF9jb25zdHJhaW50cyBBUyByY1xuICAgICAgICBPTiByYy5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIHJjLmNvbnN0cmFpbnRfc2NoZW1hID0gdGMudGFibGVfc2NoZW1hXG4gICAgICBXSEVSRSB0Yy5jb25zdHJhaW50X3R5cGUgPSAnRk9SRUlHTiBLRVknXG4gICAgICAgIEFORCBjY3UudGFibGVfbmFtZSA9ID9cbiAgICAgICAgQU5EIHRjLnRhYmxlX3NjaGVtYSA9ICdwdWJsaWMnXG4gICAgYDtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRiLnJhdyhxdWVyeSwgW3RhYmxlTmFtZV0pO1xuICAgIHJldHVybiByZXN1bHQucm93cy5tYXAoXG4gICAgICAocm93OiB7XG4gICAgICAgIHRhYmxlX25hbWU6IHN0cmluZztcbiAgICAgICAgY29uc3RyYWludF9uYW1lOiBzdHJpbmc7XG4gICAgICAgIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHJlZmVyZW5jZWRfdGFibGVfbmFtZTogc3RyaW5nO1xuICAgICAgICByZWZlcmVuY2VkX2NvbHVtbl9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHVwZGF0ZV9ydWxlOiBzdHJpbmc7XG4gICAgICAgIGRlbGV0ZV9ydWxlOiBzdHJpbmc7XG4gICAgICB9KSA9PiAoe1xuICAgICAgICB0YWJsZU5hbWU6IHJvdy50YWJsZV9uYW1lLFxuICAgICAgICBjb25zdHJhaW50TmFtZTogcm93LmNvbnN0cmFpbnRfbmFtZSxcbiAgICAgICAgY29sdW1uTmFtZTogcm93LmNvbHVtbl9uYW1lLFxuICAgICAgICByZWZlcmVuY2VkVGFibGVOYW1lOiByb3cucmVmZXJlbmNlZF90YWJsZV9uYW1lLFxuICAgICAgICByZWZlcmVuY2VkQ29sdW1uTmFtZTogcm93LnJlZmVyZW5jZWRfY29sdW1uX25hbWUsXG4gICAgICAgIG9uVXBkYXRlOiB0aGlzLm1hcENvbnN0cmFpbnRBY3Rpb24ocm93LnVwZGF0ZV9ydWxlKSxcbiAgICAgICAgb25EZWxldGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihyb3cuZGVsZXRlX3J1bGUpLFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiB2ZWN0b3Ig7Lus65+87J2YIGRpbWVuc2lvbnPrpbwg7KGw7ZqM7ZWp64uI64ukLlxuICAgKiBwZ19hdHRyaWJ1dGXsnZggYXR0dHlwbW9k7JeQ7IScIOywqOybkCDsiJjrpbwg7LaU7Lac7ZWp64uI64ukLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRWZWN0b3JEaW1lbnNpb25zKFxuICAgIGNvbXBhcmVEQjogUmF3Q2FwYWJsZUtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgbnVtYmVyPj4ge1xuICAgIGNvbnN0IHF1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIGEuYXR0bmFtZSBhcyBjb2x1bW5fbmFtZSxcbiAgICAgICAgYS5hdHR0eXBtb2QgYXMgZGltZW5zaW9uc1xuICAgICAgRlJPTSBwZ19hdHRyaWJ1dGUgYVxuICAgICAgSk9JTiBwZ19jbGFzcyBjIE9OIGEuYXR0cmVsaWQgPSBjLm9pZFxuICAgICAgSk9JTiBwZ190eXBlIHQgT04gYS5hdHR0eXBpZCA9IHQub2lkXG4gICAgICBXSEVSRSBjLnJlbG5hbWUgPSA/XG4gICAgICAgIEFORCB0LnR5cG5hbWUgPSAndmVjdG9yJ1xuICAgICAgICBBTkQgYS5hdHRudW0gPiAwXG4gICAgYDtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb21wYXJlREIucmF3KHF1ZXJ5LCBbdGFibGVOYW1lXSk7XG4gICAgY29uc3QgZGltZW5zaW9uczogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIGZvciAoY29uc3Qgcm93IG9mIHJlc3VsdC5yb3dzKSB7XG4gICAgICAvLyBhdHR0eXBtb2Tsl5DshJwg7Iuk7KCcIGRpbWVuc2lvbnMg6rCSIOy2lOy2nFxuICAgICAgZGltZW5zaW9uc1tyb3cuY29sdW1uX25hbWVdID0gcm93LmRpbWVuc2lvbnMgPiAwID8gcm93LmRpbWVuc2lvbnMgOiAwO1xuICAgIH1cbiAgICByZXR1cm4gZGltZW5zaW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3N0Z3JlU1FMIOy7rOufvCDtg4DsnoXsnYQg67aE7ISd7ZWY7JesIE1pZ3JhdGlvbkNvbHVtbiDqsJ3ssrTroZwg67OA7ZmY7ZWp64uI64ukLlxuICAgKi9cbiAgcmVzb2x2ZURCQ29sVHlwZShcbiAgICBkYkNvbHVtbjogUGdDb2x1bW4sXG4gICk6IFBpY2s8XG4gICAgTWlncmF0aW9uQ29sdW1uLFxuICAgIFwidHlwZVwiIHwgXCJsZW5ndGhcIiB8IFwicHJlY2lzaW9uXCIgfCBcInNjYWxlXCIgfCBcIm51bWJlclR5cGVcIiB8IFwiZGltZW5zaW9uc1wiXG4gID4ge1xuICAgIGNvbnN0IHsgdWR0X25hbWU6IF91ZHRfbmFtZSwgY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLCBwcmVjaXNpb24sIG51bWVyaWNfc2NhbGUgfSA9IGRiQ29sdW1uO1xuXG4gICAgY29uc3QgeyB1ZHRfbmFtZSwgc2luZ2xlT3JBcnJheSB9ID0gKCgpID0+IHtcbiAgICAgIGlmIChfdWR0X25hbWUuc3RhcnRzV2l0aChcIl9cIikpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB1ZHRfbmFtZTogX3VkdF9uYW1lLnN1YnN0cmluZygxKSxcbiAgICAgICAgICBzaW5nbGVPckFycmF5OiBcIltdXCIgYXMgY29uc3QsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB1ZHRfbmFtZTogX3VkdF9uYW1lLFxuICAgICAgICBzaW5nbGVPckFycmF5OiBcIlwiIGFzIGNvbnN0LFxuICAgICAgfTtcbiAgICB9KSgpO1xuXG4gICAgLy8gVVVJRFxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ1dWlkXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGB1dWlkJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBJbnRlZ2VyIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcImludDRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYGludGVnZXIke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiaW50OFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgYmlnSW50ZWdlciR7c2luZ2xlT3JBcnJheX1gIH07XG4gICAgfVxuXG4gICAgLy8gU3RyaW5nIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInZhcmNoYXJcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYHN0cmluZyR7c2luZ2xlT3JBcnJheX1gLFxuICAgICAgICAuLi4oY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoICYmIHtcbiAgICAgICAgICBsZW5ndGg6IGNoYXJhY3Rlcl9tYXhpbXVtX2xlbmd0aCxcbiAgICAgICAgfSksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwidGV4dFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgc3RyaW5nJHtzaW5nbGVPckFycmF5fWAgfTsgLy8gU3RyaW5nUHJvcCB3aXRob3V0IGxlbmd0aFxuICAgIH1cblxuICAgIC8vIE51bWJlck9yTnVtZXJpYyB0eXBlc1xuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJudW1lcmljXCIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCxcbiAgICAgICAgbnVtYmVyVHlwZTogXCJudW1lcmljXCIsXG4gICAgICAgIC4uLihwcmVjaXNpb24gIT09IG51bGwgJiZcbiAgICAgICAgICBudW1lcmljX3NjYWxlICE9PSBudWxsICYmIHtcbiAgICAgICAgICAgIHByZWNpc2lvbjogcHJlY2lzaW9uLFxuICAgICAgICAgICAgc2NhbGU6IG51bWVyaWNfc2NhbGUsXG4gICAgICAgICAgfSksXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiZmxvYXQ0XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCwgbnVtYmVyVHlwZTogXCJyZWFsXCIgfTtcbiAgICB9XG4gICAgaWYgKHVkdF9uYW1lID09PSBcImZsb2F0OFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgbnVtYmVyT3JOdW1lcmljJHtzaW5nbGVPckFycmF5fWAsIG51bWJlclR5cGU6IFwiZG91YmxlIHByZWNpc2lvblwiIH07XG4gICAgfVxuXG4gICAgLy8gQm9vbGVhblxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJib29sXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBib29sZWFuJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBUaW1lc3RhbXB6IHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInRpbWVzdGFtcHR6XCIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IGBkYXRlJHtzaW5nbGVPckFycmF5fWAsXG4gICAgICAgIC4uLihwcmVjaXNpb24gIT09IG51bGwgJiYge1xuICAgICAgICAgIHByZWNpc2lvbjogcHJlY2lzaW9uLFxuICAgICAgICB9KSxcbiAgICAgIH07IC8vIERhdGVQcm9wIOKGkiB0aW1lc3RhbXB0elxuICAgIH1cblxuICAgIC8vIEpTT05cbiAgICBpZiAodWR0X25hbWUgPT09IFwianNvblwiIHx8IHVkdF9uYW1lID09PSBcImpzb25iXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwianNvblwiIH07XG4gICAgfVxuXG4gICAgLy8gVmVjdG9yIChwZ3ZlY3RvcilcbiAgICBpZiAodWR0X25hbWUgPT09IFwidmVjdG9yXCIpIHtcbiAgICAgIC8vIHZlY3RvciDtg4DsnoXsnZgg7LCo7JuQIOyImOuKlCBjb2x1bW5fZGVmYXVsdOuCmCDrs4Trj4Qg7L+866as66GcIO2ZleyduO2VtOyVvCDtlahcbiAgICAgIC8vIO2YhOyerOuKlCDquLDrs7jqsJIgMOycvOuhnCDshKTsoJUgKOyLpOygnCBkaW1lbnNpb25z64qUIGdldE1pZ3JhdGlvblNldEZyb21EQuyXkOyEnCDrs4Trj4Qg7L+866as66GcIO2ZleyduClcbiAgICAgIHJldHVybiB7IHR5cGU6IGB2ZWN0b3Ike3NpbmdsZU9yQXJyYXl9YCwgZGltZW5zaW9uczogMCB9O1xuICAgIH1cblxuICAgIC8vIHRzdmVjdG9yIChQb3N0Z3JlU1FMIOyghOusuCDqsoDsg4nsmqkg7YOA7J6FKVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ0c3ZlY3RvclwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBcInRzdmVjdG9yXCIgfTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJlc29sdmUg67aI6rCA64ql7ZWcIFBvc3RncmVTUUwg7Lus65+8IO2DgOyehTogJHt1ZHRfbmFtZX1gKTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciA9IG5ldyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyQ2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJhc3NlcnQiLCJncm91cCIsIlBvc3RncmVTUUxTY2hlbWFSZWFkZXJDbGFzcyIsImdlbmVyaWNJbmRleFR5cGVzIiwiU2V0IiwiZ2V0TWlncmF0aW9uU2V0RnJvbURCIiwiY29tcGFyZURCIiwidGFibGUiLCJkYkNvbHVtbnMiLCJkYkluZGV4ZXMiLCJkYkZvcmVpZ25zIiwicmVhZFRhYmxlIiwiZSIsIkVycm9yIiwibWVzc2FnZSIsImluY2x1ZGVzIiwiY29uc29sZSIsImVycm9yIiwidmVjdG9yRGltZW5zaW9ucyIsImdldFZlY3RvckRpbWVuc2lvbnMiLCJjb2x1bW5zIiwibWFwIiwiZGJDb2x1bW4iLCJkYkNvbFR5cGUiLCJyZXNvbHZlREJDb2xUeXBlIiwidHlwZSIsImRpbWVuc2lvbnMiLCJjb2x1bW5fbmFtZSIsIm5hbWUiLCJudWxsYWJsZSIsImlzX251bGxhYmxlIiwiaXNfZ2VuZXJhdGVkIiwiZ2VuZXJhdGVkIiwiZXhwcmVzc2lvbiIsImdlbmVyYXRpb25fZXhwcmVzc2lvbiIsImNvbHVtbl9kZWZhdWx0IiwiZGVmYXVsdFZhbHVlIiwic3RhcnRzV2l0aCIsInJlcGxhY2UiLCJlbmRzV2l0aCIsInJlcGxhY2VBbGwiLCJkZWZhdWx0VG8iLCJkYkluZGV4ZXNHcm91cCIsImZpbHRlciIsImRiSW5kZXgiLCJpc19wcmltYXJ5IiwiZmluZCIsImRiRm9yZWlnbiIsImluZGV4X25hbWUiLCJjb25zdHJhaW50X25hbWUiLCJpbmRleGVzIiwiT2JqZWN0Iiwia2V5cyIsImluZGV4TmFtZSIsImN1cnJlbnRJbmRleGVzIiwidG9Tb3J0ZWQiLCJsZWZ0IiwicmlnaHQiLCJjb2x1bW5fb3JkZXIiLCJmaXJzdEluZGV4IiwicGFyc2VkSW5kZXhEZWZpbml0aW9uIiwicGFyc2VJbmRleERlZmluaXRpb24iLCJpbmRleF9kZWZpbml0aW9uIiwicmVzdG9yZWRJbmRleFR5cGUiLCJyZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlIiwiYWNjZXNzTWV0aG9kIiwidXNpbmciLCJyZXN0b3JlR2VuZXJpY1VzaW5nIiwiaW5kZXhfdHlwZSIsImlkeCIsImV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MiLCJjb2x1bW5EZWZpbml0aW9ucyIsIm9wY2xhc3MiLCJzb3J0T3JkZXIiLCJzb3J0X29yZGVyIiwibnVsbHNGaXJzdCIsIm51bGxzX2ZpcnN0IiwibnVsbHNOb3REaXN0aW5jdCIsIm51bGxzX25vdF9kaXN0aW5jdCIsInBhcnNlVmVjdG9ySW5kZXhPcHRpb25zIiwid2l0aE9wdGlvbnMiLCJmb3JlaWducyIsInRvIiwiZm9yZWlnbl90YWJsZV9uYW1lIiwiZm9yZWlnbl9jb2x1bW5fbmFtZSIsIm9uVXBkYXRlIiwibWFwQ29uc3RyYWludEFjdGlvbiIsInVwZGF0ZV9ydWxlIiwib25EZWxldGUiLCJkZWxldGVfcnVsZSIsImFjdGlvbiIsImFjdGlvbk1hcCIsIlJFU1RSSUNUIiwiQ0FTQ0FERSIsInRhYmxlTmFtZSIsImNvbHVtbnNRdWVyeSIsInJhdyIsInJvd3MiLCJsZW5ndGgiLCJpbmRleGVzUXVlcnkiLCJmb3JlaWduc1F1ZXJ5IiwiaW5kZXgiLCJyZXNvbHZlZEFjY2Vzc01ldGhvZCIsInRvTG93ZXJDYXNlIiwiaXNfdW5pcXVlIiwidW5kZWZpbmVkIiwibm9ybWFsaXplZCIsImhhcyIsInBhcnNlSW50ZWdlck9wdGlvbiIsIm0iLCJlZl9jb25zdHJ1Y3Rpb24iLCJlZkNvbnN0cnVjdGlvbiIsImxpc3RzIiwidmFsdWUiLCJwYXJzZWQiLCJOdW1iZXIiLCJwYXJzZUludCIsImlzTmFOIiwiY29sdW1uRGVmaW5pdGlvbiIsInRyaW1tZWQiLCJ0cmltIiwidG9rZW5zIiwidG9rZW5pemVUb3BMZXZlbCIsInRvVXBwZXJDYXNlIiwiYXQiLCJpbmRleERlZmluaXRpb24iLCJtYXRjaCIsInVzaW5nTWF0Y2hJbmRleCIsInNlYXJjaCIsImNvbHVtbnNTdGFydCIsImluZGV4T2YiLCJjb2x1bW5zRW5kIiwiZmluZE1hdGNoaW5nUGFyZW50aGVzaXMiLCJzcGxpdFRvcExldmVsIiwic2xpY2UiLCJ3aXRoTWF0Y2giLCJleGVjIiwid2l0aFN0YXJ0Iiwid2l0aEVuZCIsInBhcnNlSW5kZXhPcHRpb25FbnRyaWVzIiwib3B0aW9uU291cmNlIiwicmVkdWNlIiwicmVzdWx0IiwiZW50cnkiLCJtYXRjaGVkIiwia2V5IiwicmF3VmFsdWUiLCJzb3VyY2UiLCJkZWxpbWl0ZXIiLCJpdGVtcyIsInN0YXJ0IiwicGFyZW5EZXB0aCIsImJyYWNrZXREZXB0aCIsImluU2luZ2xlUXVvdGUiLCJpbkRvdWJsZVF1b3RlIiwiY2hhciIsIm5leHRDaGFyIiwicHVzaCIsInRhaWwiLCJwdXNoVG9rZW4iLCJlbmRJbmRleCIsInRva2VuIiwidGVzdCIsIm9wZW5JbmRleCIsImRlcHRoIiwiZ2V0UmVmZXJlbmNpbmdGb3JlaWduS2V5cyIsImRiIiwicXVlcnkiLCJyb3ciLCJ0YWJsZV9uYW1lIiwiY29uc3RyYWludE5hbWUiLCJjb2x1bW5OYW1lIiwicmVmZXJlbmNlZFRhYmxlTmFtZSIsInJlZmVyZW5jZWRfdGFibGVfbmFtZSIsInJlZmVyZW5jZWRDb2x1bW5OYW1lIiwicmVmZXJlbmNlZF9jb2x1bW5fbmFtZSIsInVkdF9uYW1lIiwiX3VkdF9uYW1lIiwiY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoIiwicHJlY2lzaW9uIiwibnVtZXJpY19zY2FsZSIsInNpbmdsZU9yQXJyYXkiLCJzdWJzdHJpbmciLCJudW1iZXJUeXBlIiwic2NhbGUiLCJQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFFNUIsU0FBU0MsS0FBSyxRQUFRLFVBQVU7QUFtRWhDLE1BQU1DO0lBQ2FDLG9CQUFvQixJQUFJQyxJQUFJO1FBQUM7UUFBUztRQUFRO1FBQU87UUFBUTtLQUFXLEVBQUU7SUFFM0Y7Ozs7O0dBS0MsR0FDRCxNQUFNQyxzQkFDSkMsU0FBeUIsRUFDekJDLEtBQWEsRUFDaUI7UUFDOUIsSUFBSUMsV0FBdUJDLFdBQXNCQztRQUNqRCxJQUFJO1lBQ0YsQ0FBQ0YsV0FBV0MsV0FBV0MsV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDQyxTQUFTLENBQUNMLFdBQVdDO1FBQ3ZFLEVBQUUsT0FBT0ssR0FBWTtZQUNuQixJQUFJQSxhQUFhQyxTQUFTRCxFQUFFRSxPQUFPLENBQUNDLFFBQVEsQ0FBQyxvQkFBb0I7Z0JBQy9ELE9BQU87WUFDVDtZQUNBQyxRQUFRQyxLQUFLLENBQUNMO1lBQ2QsT0FBTztRQUNUO1FBRUEsMkJBQTJCO1FBQzNCLE1BQU1NLG1CQUFtQixNQUFNLElBQUksQ0FBQ0MsbUJBQW1CLENBQUNiLFdBQVdDO1FBRW5FLE1BQU1hLFVBQTZCWixVQUFVYSxHQUFHLENBQUMsQ0FBQ0M7WUFDaEQsTUFBTUMsWUFBWSxJQUFJLENBQUNDLGdCQUFnQixDQUFDRjtZQUV4Qyw4QkFBOEI7WUFDOUIs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
|
|
643
|
+
//#endregion
|
|
644
|
+
init_postgresql_schema_reader();
|
|
645
|
+
export { PostgreSQLSchemaReader, init_postgresql_schema_reader };
|
|
646
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXNxbC1zY2hlbWEtcmVhZGVyLmpzIiwibmFtZXMiOlsiZGJDb2x1bW5zOiBQZ0NvbHVtbltdIiwiZGJJbmRleGVzOiBQZ0luZGV4W10iLCJkYkZvcmVpZ25zOiBQZ0ZvcmVpZ25bXSIsImU6IHVua25vd24iLCJjb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXSIsImluZGV4ZXM6IE1pZ3JhdGlvbkluZGV4W10iLCJmb3JlaWduczogTWlncmF0aW9uRm9yZWlnbltdIiwiYWN0aW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBSZWxhdGlvbk9uPiIsIml0ZW1zOiBzdHJpbmdbXSIsInRva2Vuczogc3RyaW5nW10iLCJkaW1lbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21pZ3JhdGlvbi9wb3N0Z3Jlc3FsLXNjaGVtYS1yZWFkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5cbmltcG9ydCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgeyBncm91cCB9IGZyb20gXCJyYWRhc2hpXCI7XG5cbmltcG9ydCB7XG4gIHR5cGUgTWlncmF0aW9uQ29sdW1uLFxuICB0eXBlIE1pZ3JhdGlvbkZvcmVpZ24sXG4gIHR5cGUgTWlncmF0aW9uSW5kZXgsXG4gIHR5cGUgTWlncmF0aW9uU2V0LFxuICB0eXBlIFJlbGF0aW9uT24sXG59IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuXG4vKipcbiAqIO2KueyglSDthYzsnbTruJTsnZggUEvrpbwg7LC47KGw7ZWY64qUIOuLpOuluCDthYzsnbTruJTsnZggRksg7KCV67O07J6F64uI64ukLlxuICogUEsg7YOA7J6FIOuzgOqyvSDsi5wg6rSA66CoIEZLIOygnOyVveyhsOqxtOydhCDsspjrpqztlZjquLAg7JyE7ZW0IOyCrOyaqeuQqeuLiOuLpC5cbiAqL1xuZXhwb3J0IHR5cGUgUmVmZXJlbmNpbmdGb3JlaWduS2V5ID0ge1xuICAvKiogRkvqsIAg7KCV7J2Y65CcIO2FjOydtOu4lOuqhSAqL1xuICB0YWJsZU5hbWU6IHN0cmluZztcbiAgLyoqIEZLIOygnOyVveyhsOqxtCDsnbTrpoQgKi9cbiAgY29uc3RyYWludE5hbWU6IHN0cmluZztcbiAgLyoqIEZLIOy7rOufvOuqhSAqL1xuICBjb2x1bW5OYW1lOiBzdHJpbmc7XG4gIC8qKiDssLjsobDtlZjripQg7YWM7J2067iU66qFIChQS+qwgCDsnojripQg7YWM7J2067iUKSAqL1xuICByZWZlcmVuY2VkVGFibGVOYW1lOiBzdHJpbmc7XG4gIC8qKiDssLjsobDtlZjripQg7Lus65+866qFICjrs7TthrUgJ2lkJykgKi9cbiAgcmVmZXJlbmNlZENvbHVtbk5hbWU6IHN0cmluZztcbiAgLyoqIE9OIFVQREFURSDslaHshZggKi9cbiAgb25VcGRhdGU6IFJlbGF0aW9uT247XG4gIC8qKiBPTiBERUxFVEUg7JWh7IWYICovXG4gIG9uRGVsZXRlOiBSZWxhdGlvbk9uO1xufTtcblxuZXhwb3J0IHR5cGUgUGdDb2x1bW4gPSB7XG4gIGNvbHVtbl9uYW1lOiBzdHJpbmc7XG4gIGRhdGFfdHlwZTogc3RyaW5nO1xuICB1ZHRfbmFtZTogc3RyaW5nO1xuICBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGg6IG51bWJlciB8IG51bGw7XG4gIHByZWNpc2lvbjogbnVtYmVyIHwgbnVsbDtcbiAgbnVtZXJpY19zY2FsZTogbnVtYmVyIHwgbnVsbDtcbiAgaXNfbnVsbGFibGU6IHN0cmluZztcbiAgY29sdW1uX2RlZmF1bHQ6IHN0cmluZyB8IG51bGw7XG4gIGlzX2dlbmVyYXRlZDogc3RyaW5nOyAvLyAncycgPSBTVE9SRUQsICd2JyA9IFZJUlRVQUwsICcnID0gbm9uZVxuICBnZW5lcmF0aW9uX2V4cHJlc3Npb246IHN0cmluZyB8IG51bGw7XG59O1xuXG50eXBlIFBnSW5kZXggPSB7XG4gIGluZGV4X25hbWU6IHN0cmluZztcbiAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgaXNfdW5pcXVlOiBib29sZWFuO1xuICBpc19wcmltYXJ5OiBib29sZWFuO1xuICBpbmRleF90eXBlOiBzdHJpbmc7XG4gIG51bGxzX2ZpcnN0OiBib29sZWFuO1xuICBzb3J0X29yZGVyOiBcIkFTQ1wiIHwgXCJERVNDXCI7XG4gIG51bGxzX25vdF9kaXN0aW5jdDogYm9vbGVhbjtcbiAgY29sdW1uX29yZGVyOiBudW1iZXI7XG4gIGluZGV4X2RlZmluaXRpb246IHN0cmluZztcbn07XG5cbnR5cGUgUGdGb3JlaWduID0ge1xuICBjb25zdHJhaW50X25hbWU6IHN0cmluZztcbiAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgZm9yZWlnbl90YWJsZV9uYW1lOiBzdHJpbmc7XG4gIGZvcmVpZ25fY29sdW1uX25hbWU6IHN0cmluZztcbiAgdXBkYXRlX3J1bGU6IHN0cmluZztcbiAgZGVsZXRlX3J1bGU6IHN0cmluZztcbn07XG5cbnR5cGUgUmF3Q2FwYWJsZUtuZXggPSBQaWNrPEtuZXgsIFwicmF3XCI+O1xuXG5jbGFzcyBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyQ2xhc3Mge1xuICBwcml2YXRlIHJlYWRvbmx5IGdlbmVyaWNJbmRleFR5cGVzID0gbmV3IFNldChbXCJidHJlZVwiLCBcImhhc2hcIiwgXCJnaW5cIiwgXCJnaXN0XCIsIFwicGdyb29uZ2FcIl0pO1xuXG4gIC8qKlxuICAgKiBEQuyXkOyEnCDthYzsnbTruJQg7KCV67O066W8IOydveyWtOyEnCBNaWdyYXRpb25TZXTsnYQg66eM65Ok7Ja07Ji164uI64ukLlxuICAgKiBAcGFyYW0gY29tcGFyZURCIEtuZXgg7J247Iqk7YS07IqkXG4gICAqIEBwYXJhbSB0YWJsZSDthYzsnbTruJQg7J2066aEXG4gICAqIEByZXR1cm5zIE1pZ3JhdGlvblNldCDqsJ3ssrRcbiAgICovXG4gIGFzeW5jIGdldE1pZ3JhdGlvblNldEZyb21EQihcbiAgICBjb21wYXJlREI6IFJhd0NhcGFibGVLbmV4LFxuICAgIHRhYmxlOiBzdHJpbmcsXG4gICk6IFByb21pc2U8TWlncmF0aW9uU2V0IHwgbnVsbD4ge1xuICAgIGxldCBkYkNvbHVtbnM6IFBnQ29sdW1uW10sIGRiSW5kZXhlczogUGdJbmRleFtdLCBkYkZvcmVpZ25zOiBQZ0ZvcmVpZ25bXTtcbiAgICB0cnkge1xuICAgICAgW2RiQ29sdW1ucywgZGJJbmRleGVzLCBkYkZvcmVpZ25zXSA9IGF3YWl0IHRoaXMucmVhZFRhYmxlKGNvbXBhcmVEQiwgdGFibGUpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IgJiYgZS5tZXNzYWdlLmluY2x1ZGVzKFwiVGFibGUgbm90IGZvdW5kXCIpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIHZlY3RvciDsu6zrn7zsnZggZGltZW5zaW9ucyDsobDtmoxcbiAgICBjb25zdCB2ZWN0b3JEaW1lbnNpb25zID0gYXdhaXQgdGhpcy5nZXRWZWN0b3JEaW1lbnNpb25zKGNvbXBhcmVEQiwgdGFibGUpO1xuXG4gICAgY29uc3QgY29sdW1uczogTWlncmF0aW9uQ29sdW1uW10gPSBkYkNvbHVtbnMubWFwKChkYkNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZGJDb2xUeXBlID0gdGhpcy5yZXNvbHZlREJDb2xUeXBlKGRiQ29sdW1uKTtcblxuICAgICAgLy8gdmVjdG9yIO2DgOyeheyduCDqsr3smrAgZGltZW5zaW9ucyDshKTsoJVcbiAgICAgIGlmIChkYkNvbFR5cGUudHlwZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgICAgICBkYkNvbFR5cGUuZGltZW5zaW9ucyA9IHZlY3RvckRpbWVuc2lvbnNbZGJDb2x1bW4uY29sdW1uX25hbWVdID8/IDA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IGRiQ29sdW1uLmNvbHVtbl9uYW1lLFxuICAgICAgICBudWxsYWJsZTogZGJDb2x1bW4uaXNfbnVsbGFibGUgPT09IFwiWUVTXCIsXG4gICAgICAgIC4uLmRiQ29sVHlwZSxcbiAgICAgICAgLy8gR2VuZXJhdGVkIENvbHVtbiDsspjrpqxcbiAgICAgICAgLi4uKCgpID0+IHtcbiAgICAgICAgICBpZiAoZGJDb2x1bW4uaXNfZ2VuZXJhdGVkID09PSBcInNcIiB8fCBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwidlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBnZW5lcmF0ZWQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwic1wiID8gXCJTVE9SRURcIiA6IFwiVklSVFVBTFwiLFxuICAgICAgICAgICAgICAgIGV4cHJlc3Npb246IGRiQ29sdW1uLmdlbmVyYXRpb25fZXhwcmVzc2lvbiA/PyBcIlwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9KSgpLFxuICAgICAgICAvLyBEZWZhdWx0IOqwkiDsspjrpqwgKEdlbmVyYXRlZCBDb2x1bW7snbQg7JWE64uMIOqyveyasOunjClcbiAgICAgICAgLi4uKCgpID0+IHtcbiAgICAgICAgICAvLyBHZW5lcmF0ZWQgQ29sdW1u7J2AIGRlZmF1bHQg6rCS7J20IOyXhuydjFxuICAgICAgICAgIGlmIChkYkNvbHVtbi5pc19nZW5lcmF0ZWQgPT09IFwic1wiIHx8IGRiQ29sdW1uLmlzX2dlbmVyYXRlZCA9PT0gXCJ2XCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZGJDb2x1bW4uY29sdW1uX2RlZmF1bHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFBvc3RncmVTUUwgZGVmYXVsdCDqsJIg7KCV66asIChuZXh0dmFsLCBDVVJSRU5UX1RJTUVTVEFNUCDrk7EpXG4gICAgICAgICAgICBsZXQgZGVmYXVsdFZhbHVlID0gZGJDb2x1bW4uY29sdW1uX2RlZmF1bHQ7XG5cbiAgICAgICAgICAgIC8vIG5leHR2YWwg7KCc6rGwIChTRVJJQUwg7YOA7J6FKVxuICAgICAgICAgICAgaWYgKGRlZmF1bHRWYWx1ZS5zdGFydHNXaXRoKFwibmV4dHZhbChcIikpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyDtg4DsnoUg7LqQ7Iqk7YyFIOygnOqxsCAo7JiIOiAnMSc6OmludGVnZXIg4oaSIDEpXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWUgPSBkZWZhdWx0VmFsdWUucmVwbGFjZSgvOjpbXFx3XFxzXSskL2csIFwiXCIpO1xuXG4gICAgICAgICAgICAvLyDrlLDsmLTtkZzqsIAgc2luZ2xlIHF1b3Rl7J24IOqyveyasCBkb3VibGUgcXVvdGXroZwg67OA7ZmYXG4gICAgICAgICAgICBpZiAoZGVmYXVsdFZhbHVlLnN0YXJ0c1dpdGgoXCInXCIpICYmIGRlZmF1bHRWYWx1ZS5lbmRzV2l0aChcIidcIikpIHtcbiAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlID0gZGVmYXVsdFZhbHVlLnJlcGxhY2VBbGwoXCInXCIsICdcIicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBkZWZhdWx0VG86IGRlZmF1bHRWYWx1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgfSkoKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBQUklNQVJZIEtFWeyZgCBmb3JlaWduIGtleeyaqSDsnbjrjbHsiqQg7KCc7Jm4XG4gICAgY29uc3QgZGJJbmRleGVzR3JvdXAgPSBncm91cChcbiAgICAgIGRiSW5kZXhlcy5maWx0ZXIoXG4gICAgICAgIChkYkluZGV4KSA9PlxuICAgICAgICAgICFkYkluZGV4LmlzX3ByaW1hcnkgJiZcbiAgICAgICAgICAhZGJGb3JlaWducy5maW5kKChkYkZvcmVpZ24pID0+IGRiSW5kZXguaW5kZXhfbmFtZS5pbmNsdWRlcyhkYkZvcmVpZ24uY29uc3RyYWludF9uYW1lKSksXG4gICAgICApLFxuICAgICAgKGRiSW5kZXgpID0+IGRiSW5kZXguaW5kZXhfbmFtZSxcbiAgICApO1xuXG4gICAgLy8gaW5kZXhlcyDsspjrpqxcbiAgICBjb25zdCBpbmRleGVzOiBNaWdyYXRpb25JbmRleFtdID0gT2JqZWN0LmtleXMoZGJJbmRleGVzR3JvdXApLm1hcCgoaW5kZXhOYW1lKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50SW5kZXhlcyA9IGRiSW5kZXhlc0dyb3VwW2luZGV4TmFtZV0/LnRvU29ydGVkKFxuICAgICAgICAobGVmdCwgcmlnaHQpID0+IGxlZnQuY29sdW1uX29yZGVyIC0gcmlnaHQuY29sdW1uX29yZGVyLFxuICAgICAgKTtcbiAgICAgIGFzc2VydChjdXJyZW50SW5kZXhlcyk7XG5cbiAgICAgIGNvbnN0IGZpcnN0SW5kZXggPSBjdXJyZW50SW5kZXhlc1swXTtcbiAgICAgIGNvbnN0IHBhcnNlZEluZGV4RGVmaW5pdGlvbiA9IHRoaXMucGFyc2VJbmRleERlZmluaXRpb24oZmlyc3RJbmRleC5pbmRleF9kZWZpbml0aW9uKTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkSW5kZXhUeXBlID0gdGhpcy5yZXN0b3JlTWlncmF0aW9uSW5kZXhUeXBlKFxuICAgICAgICBmaXJzdEluZGV4LFxuICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uYWNjZXNzTWV0aG9kLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHVzaW5nID0gdGhpcy5yZXN0b3JlR2VuZXJpY1VzaW5nKFxuICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uYWNjZXNzTWV0aG9kID8/IGZpcnN0SW5kZXguaW5kZXhfdHlwZSxcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IHJlc3RvcmVkSW5kZXhUeXBlLFxuICAgICAgICBuYW1lOiBpbmRleE5hbWUsXG4gICAgICAgIGNvbHVtbnM6IGN1cnJlbnRJbmRleGVzLm1hcCgoaWR4KSA9PiAoe1xuICAgICAgICAgIG5hbWU6IGlkeC5jb2x1bW5fbmFtZSxcbiAgICAgICAgICAuLi4odGhpcy5leHRyYWN0SW5kZXhDb2x1bW5PcGNsYXNzKFxuICAgICAgICAgICAgcGFyc2VkSW5kZXhEZWZpbml0aW9uLmNvbHVtbkRlZmluaXRpb25zW2lkeC5jb2x1bW5fb3JkZXIgLSAxXSxcbiAgICAgICAgICApXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBvcGNsYXNzOiB0aGlzLmV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MoXG4gICAgICAgICAgICAgICAgICBwYXJzZWRJbmRleERlZmluaXRpb24uY29sdW1uRGVmaW5pdGlvbnNbaWR4LmNvbHVtbl9vcmRlciAtIDFdLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgIC4uLih1c2luZyA9PT0gXCJidHJlZVwiXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBzb3J0T3JkZXI6IGlkeC5zb3J0X29yZGVyLFxuICAgICAgICAgICAgICAgIG51bGxzRmlyc3Q6IGlkeC5udWxsc19maXJzdCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0pKSxcblxuICAgICAgICBudWxsc05vdERpc3RpbmN0OiBmaXJzdEluZGV4Lm51bGxzX25vdF9kaXN0aW5jdCxcbiAgICAgICAgLi4uKHVzaW5nID8geyB1c2luZyB9IDoge30pLFxuICAgICAgICAuLi50aGlzLnBhcnNlVmVjdG9ySW5kZXhPcHRpb25zKHJlc3RvcmVkSW5kZXhUeXBlLCBwYXJzZWRJbmRleERlZmluaXRpb24ud2l0aE9wdGlvbnMpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIGZvcmVpZ25zIOyymOumrFxuICAgIGNvbnN0IGZvcmVpZ25zOiBNaWdyYXRpb25Gb3JlaWduW10gPSBkYkZvcmVpZ25zLm1hcCgoZGJGb3JlaWduKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW5zOiBbZGJGb3JlaWduLmNvbHVtbl9uYW1lXSxcbiAgICAgICAgdG86IGAke2RiRm9yZWlnbi5mb3JlaWduX3RhYmxlX25hbWV9LiR7ZGJGb3JlaWduLmZvcmVpZ25fY29sdW1uX25hbWV9YCxcbiAgICAgICAgb25VcGRhdGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihkYkZvcmVpZ24udXBkYXRlX3J1bGUpLFxuICAgICAgICBvbkRlbGV0ZTogdGhpcy5tYXBDb25zdHJhaW50QWN0aW9uKGRiRm9yZWlnbi5kZWxldGVfcnVsZSksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRhYmxlLFxuICAgICAgY29sdW1ucyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBmb3JlaWducyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFBvc3RncmVTUUzsnZggY29uc3RyYWludCBhY3Rpb27snYQgS25leCDtmJXsi53snLzroZwg67OA7ZmYXG4gICAqL1xuICBwcml2YXRlIG1hcENvbnN0cmFpbnRBY3Rpb24oYWN0aW9uOiBzdHJpbmcpOiBSZWxhdGlvbk9uIHtcbiAgICBjb25zdCBhY3Rpb25NYXA6IFJlY29yZDxzdHJpbmcsIFJlbGF0aW9uT24+ID0ge1xuICAgICAgXCJOTyBBQ1RJT05cIjogXCJOTyBBQ1RJT05cIixcbiAgICAgIFJFU1RSSUNUOiBcIlJFU1RSSUNUXCIsXG4gICAgICBDQVNDQURFOiBcIkNBU0NBREVcIixcbiAgICAgIFwiU0VUIE5VTExcIjogXCJTRVQgTlVMTFwiLFxuICAgICAgXCJTRVQgREVGQVVMVFwiOiBcIlNFVCBERUZBVUxUXCIsXG4gICAgfTtcbiAgICByZXR1cm4gYWN0aW9uTWFwW2FjdGlvbl0gPz8gXCJOTyBBQ1RJT05cIjtcbiAgfVxuXG4gIC8qKlxuICAgKiDquLDsobQg7YWM7J2067iUIOydveyWtOyEnCBjb2xzLCBpbmRleGVzLCBmb3JlaWducyDrsJjtmZhcbiAgICovXG4gIGFzeW5jIHJlYWRUYWJsZShcbiAgICBjb21wYXJlREI6IFJhd0NhcGFibGVLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICApOiBQcm9taXNlPFtQZ0NvbHVtbltdLCBQZ0luZGV4W10sIFBnRm9yZWlnbltdXT4ge1xuICAgIC8vIENvbHVtbnMg7KGw7ZqMIChHZW5lcmF0ZWQgQ29sdW1uIOygleuztCDtj6ztlagpXG4gICAgY29uc3QgY29sdW1uc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIGMuY29sdW1uX25hbWUsXG4gICAgICAgIGMuZGF0YV90eXBlLFxuICAgICAgICBjLnVkdF9uYW1lLFxuICAgICAgICBDT0FMRVNDRShcbiAgICAgICAgICBjLmNoYXJhY3Rlcl9tYXhpbXVtX2xlbmd0aCxcbiAgICAgICAgICBDQVNFIFdIRU4gYy5kYXRhX3R5cGUgPSAnQVJSQVknIEFORCBhLmF0dHR5cG1vZCA+IDBcbiAgICAgICAgICAgIFRIRU4gYS5hdHR0eXBtb2QgLSA0XG4gICAgICAgICAgICBFTFNFIE5VTExcbiAgICAgICAgICBFTkRcbiAgICAgICAgKSBBUyBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsXG4gICAgICAgIENPQUxFU0NFKGMuZGF0ZXRpbWVfcHJlY2lzaW9uLCBjLm51bWVyaWNfcHJlY2lzaW9uKSBBUyBwcmVjaXNpb24sXG4gICAgICAgIGMubnVtZXJpY19zY2FsZSxcbiAgICAgICAgYy5pc19udWxsYWJsZSxcbiAgICAgICAgYy5jb2x1bW5fZGVmYXVsdCxcbiAgICAgICAgQ09BTEVTQ0UoYS5hdHRnZW5lcmF0ZWQsICcnKSBhcyBpc19nZW5lcmF0ZWQsXG4gICAgICAgIGMuZ2VuZXJhdGlvbl9leHByZXNzaW9uXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS5jb2x1bW5zIGNcbiAgICAgIExFRlQgSk9JTiBwZ19hdHRyaWJ1dGUgYSBPTiBhLmF0dG5hbWUgPSBjLmNvbHVtbl9uYW1lXG4gICAgICAgIEFORCBhLmF0dHJlbGlkID0gKFxuICAgICAgICAgIFNFTEVDVCBvaWQgRlJPTSBwZ19jbGFzcyBXSEVSRSByZWxuYW1lID0gYy50YWJsZV9uYW1lXG4gICAgICAgICAgQU5EIHJlbG5hbWVzcGFjZSA9IChTRUxFQ1Qgb2lkIEZST00gcGdfbmFtZXNwYWNlIFdIRVJFIG5zcG5hbWUgPSBjLnRhYmxlX3NjaGVtYSlcbiAgICAgICAgKVxuICAgICAgV0hFUkUgYy50YWJsZV9uYW1lID0gP1xuICAgICAgICBBTkQgYy50YWJsZV9zY2hlbWEgPSAncHVibGljJ1xuICAgICAgT1JERVIgQlkgYy5vcmRpbmFsX3Bvc2l0aW9uXG4gICAgYDtcbiAgICBjb25zdCBjb2x1bW5zID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoY29sdW1uc1F1ZXJ5LCBbdGFibGVOYW1lXSkpLnJvd3MgYXMgUGdDb2x1bW5bXTtcbiAgICBpZiAoY29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgbm90IGZvdW5kOiAke3RhYmxlTmFtZX1gKTtcbiAgICB9XG5cbiAgICAvLyBJbmRleGVzIOyhsO2ajCAoUEdyb29uZ2Eg7ZGc7ZiE7IudIOyduOuNseyKpCDtj6ztlagpXG4gICAgY29uc3QgaW5kZXhlc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgICAgaS5yZWxuYW1lIEFTIGluZGV4X25hbWUsXG4gICAgICAgICAgQ0FTRVxuICAgICAgICAgICAgICBXSEVOIGFtLmFtbmFtZSA9ICdwZ3Jvb25nYScgQU5EIHUuYXR0bnVtID0gMCBUSEVOXG4gICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICByZWdleHBfcmVwbGFjZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJJTShwZ3Jvb25nYV9jb2wuY29sdW1uX2V4cHIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnOjp0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnJ1xuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgJ1soKV0nLFxuICAgICAgICAgICAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgICAgICAgICAgICdnJ1xuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICBFTFNFIGEuYXR0bmFtZVxuICAgICAgICAgIEVORCBBUyBjb2x1bW5fbmFtZSxcbiAgICAgICAgICBpeC5pbmRpc3VuaXF1ZSBBUyBpc191bmlxdWUsXG4gICAgICAgICAgaXguaW5kaXNwcmltYXJ5IEFTIGlzX3ByaW1hcnksXG4gICAgICAgICAgYW0uYW1uYW1lIEFTIGluZGV4X3R5cGUsXG4gICAgICAgICAgQ09BTEVTQ0UoKHUub3B0ICYgMikgPSAyLCBGQUxTRSkgQVMgbnVsbHNfZmlyc3QsXG4gICAgICAgICAgQ0FTRSBcbiAgICAgICAgICAgICAgV0hFTiAodS5vcHQgJiAxKSA9IDEgVEhFTiAnREVTQydcbiAgICAgICAgICAgICAgRUxTRSAnQVNDJ1xuICAgICAgICAgIEVORCBBUyBzb3J0X29yZGVyLFxuICAgICAgICAgIGl4LmluZG51bGxzbm90ZGlzdGluY3QgQVMgbnVsbHNfbm90X2Rpc3RpbmN0LFxuICAgICAgICAgIHUub3JkIEFTIGNvbHVtbl9vcmRlcixcbiAgICAgICAgICBwZ19nZXRfaW5kZXhkZWYoaXguaW5kZXhyZWxpZCkgQVMgaW5kZXhfZGVmaW5pdGlvblxuICAgICAgRlJPTSBwZ19jbGFzcyB0XG4gICAgICBKT0lOIHBnX2luZGV4IGl4IE9OIHQub2lkID0gaXguaW5kcmVsaWRcbiAgICAgIEpPSU4gcGdfY2xhc3MgaSBPTiBpLm9pZCA9IGl4LmluZGV4cmVsaWRcbiAgICAgIEpPSU4gcGdfYW0gYW0gT04gaS5yZWxhbSA9IGFtLm9pZFxuICAgICAgSk9JTiBMQVRFUkFMIHVubmVzdChpeC5pbmRrZXksIGl4LmluZG9wdGlvbilcbiAgICAgICAgICBXSVRIIE9SRElOQUxJVFkgQVMgdShhdHRudW0sIG9wdCwgb3JkKSBPTiB0cnVlXG4gICAgICBMRUZUIEpPSU4gcGdfYXR0cmlidXRlIGEgT04gYS5hdHRyZWxpZCA9IHQub2lkIFxuICAgICAgICAgIEFORCBhLmF0dG51bSA9IHUuYXR0bnVtIFxuICAgICAgICAgIEFORCB1LmF0dG51bSA+IDBcbiAgICAgIExFRlQgSk9JTiBMQVRFUkFMIChcbiAgICAgICAgICBTRUxFQ1QgXG4gICAgICAgICAgICAgIHVubmVzdChcbiAgICAgICAgICAgICAgICAgIENBU0UgXG4gICAgICAgICAgICAgICAgICAgICAgV0hFTiBwZ19nZXRfZXhwcihpeC5pbmRleHBycywgaXguaW5kcmVsaWQpIH4gJ15BUlJBWVxcXFxbJyBUSEVOXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ190b19hcnJheShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2V4cF9yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBnX2dldF9leHByKGl4LmluZGV4cHJzLCBpeC5pbmRyZWxpZCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ15BUlJBWVxcXFxbKC4qKVxcXFxdJCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1xcXFwxJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsICdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgIEVMU0VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgQVJSQVlbcGdfZ2V0X2V4cHIoaXguaW5kZXhwcnMsIGl4LmluZHJlbGlkKV1cbiAgICAgICAgICAgICAgICAgIEVORFxuICAgICAgICAgICAgICApIGFzIGNvbHVtbl9leHByXG4gICAgICApIHBncm9vbmdhX2NvbCBPTiBhbS5hbW5hbWUgPSAncGdyb29uZ2EnIEFORCB1LmF0dG51bSA9IDBcbiAgICAgIFdIRVJFIHQucmVsbmFtZSA9ID9cbiAgICAgICAgICBBTkQgKHUuYXR0bnVtID4gMCBPUiAoYW0uYW1uYW1lID0gJ3Bncm9vbmdhJyBBTkQgdS5hdHRudW0gPSAwKSlcbiAgICAgIE9SREVSIEJZIGkucmVsbmFtZSwgdS5vcmQ7XG5gO1xuICAgIGNvbnN0IGluZGV4ZXMgPSAoYXdhaXQgY29tcGFyZURCLnJhdyhpbmRleGVzUXVlcnksIFt0YWJsZU5hbWVdKSkucm93cztcblxuICAgIC8vIEZvcmVpZ24gS2V5cyDsobDtmoxcbiAgICBjb25zdCBmb3JlaWduc1F1ZXJ5ID0gYFxuICAgICAgU0VMRUNUXG4gICAgICAgIHRjLmNvbnN0cmFpbnRfbmFtZSxcbiAgICAgICAga2N1LmNvbHVtbl9uYW1lLFxuICAgICAgICBjY3UudGFibGVfbmFtZSBBUyBmb3JlaWduX3RhYmxlX25hbWUsXG4gICAgICAgIGNjdS5jb2x1bW5fbmFtZSBBUyBmb3JlaWduX2NvbHVtbl9uYW1lLFxuICAgICAgICByYy51cGRhdGVfcnVsZSxcbiAgICAgICAgcmMuZGVsZXRlX3J1bGVcbiAgICAgIEZST00gaW5mb3JtYXRpb25fc2NoZW1hLnRhYmxlX2NvbnN0cmFpbnRzIEFTIHRjXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5rZXlfY29sdW1uX3VzYWdlIEFTIGtjdVxuICAgICAgICBPTiB0Yy5jb25zdHJhaW50X25hbWUgPSBrY3UuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCB0Yy50YWJsZV9zY2hlbWEgPSBrY3UudGFibGVfc2NoZW1hXG4gICAgICBKT0lOIGluZm9ybWF0aW9uX3NjaGVtYS5jb25zdHJhaW50X2NvbHVtbl91c2FnZSBBUyBjY3VcbiAgICAgICAgT04gY2N1LmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgY2N1LnRhYmxlX3NjaGVtYSA9IHRjLnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEucmVmZXJlbnRpYWxfY29uc3RyYWludHMgQVMgcmNcbiAgICAgICAgT04gcmMuY29uc3RyYWludF9uYW1lID0gdGMuY29uc3RyYWludF9uYW1lXG4gICAgICAgIEFORCByYy5jb25zdHJhaW50X3NjaGVtYSA9IHRjLnRhYmxlX3NjaGVtYVxuICAgICAgV0hFUkUgdGMuY29uc3RyYWludF90eXBlID0gJ0ZPUkVJR04gS0VZJ1xuICAgICAgICBBTkQgdGMudGFibGVfbmFtZSA9ID9cbiAgICBgO1xuICAgIGNvbnN0IGZvcmVpZ25zID0gKGF3YWl0IGNvbXBhcmVEQi5yYXcoZm9yZWlnbnNRdWVyeSwgW3RhYmxlTmFtZV0pKS5yb3dzO1xuXG4gICAgcmV0dXJuIFtjb2x1bW5zLCBpbmRleGVzLCBmb3JlaWduc107XG4gIH1cblxuICBwcml2YXRlIHJlc3RvcmVNaWdyYXRpb25JbmRleFR5cGUoXG4gICAgaW5kZXg6IFBpY2s8UGdJbmRleCwgXCJpc191bmlxdWVcIiB8IFwiaW5kZXhfdHlwZVwiPixcbiAgICBhY2Nlc3NNZXRob2Q/OiBzdHJpbmcsXG4gICk6IE1pZ3JhdGlvbkluZGV4W1widHlwZVwiXSB7XG4gICAgY29uc3QgcmVzb2x2ZWRBY2Nlc3NNZXRob2QgPSAoYWNjZXNzTWV0aG9kID8/IGluZGV4LmluZGV4X3R5cGUpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAocmVzb2x2ZWRBY2Nlc3NNZXRob2QgPT09IFwiaG5zd1wiIHx8IHJlc29sdmVkQWNjZXNzTWV0aG9kID09PSBcIml2ZmZsYXRcIikge1xuICAgICAgcmV0dXJuIHJlc29sdmVkQWNjZXNzTWV0aG9kO1xuICAgIH1cblxuICAgIHJldHVybiBpbmRleC5pc191bmlxdWUgPyBcInVuaXF1ZVwiIDogXCJpbmRleFwiO1xuICB9XG5cbiAgcHJpdmF0ZSByZXN0b3JlR2VuZXJpY1VzaW5nKFxuICAgIGFjY2Vzc01ldGhvZDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICApOiBNaWdyYXRpb25JbmRleFtcInVzaW5nXCJdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWFjY2Vzc01ldGhvZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBub3JtYWxpemVkID0gYWNjZXNzTWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKCF0aGlzLmdlbmVyaWNJbmRleFR5cGVzLmhhcyhub3JtYWxpemVkKSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZCBhcyBNaWdyYXRpb25JbmRleFtcInVzaW5nXCJdO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVZlY3RvckluZGV4T3B0aW9ucyhcbiAgICB0eXBlOiBNaWdyYXRpb25JbmRleFtcInR5cGVcIl0sXG4gICAgd2l0aE9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICk6IFBpY2s8TWlncmF0aW9uSW5kZXgsIFwibVwiIHwgXCJlZkNvbnN0cnVjdGlvblwiIHwgXCJsaXN0c1wiPiB7XG4gICAgaWYgKHR5cGUgPT09IFwiaG5zd1wiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi4odGhpcy5wYXJzZUludGVnZXJPcHRpb24od2l0aE9wdGlvbnMubSkgIT09IHVuZGVmaW5lZFxuICAgICAgICAgID8geyBtOiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5tKSB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICAgIC4uLih0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5lZl9jb25zdHJ1Y3Rpb24pICE9PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHsgZWZDb25zdHJ1Y3Rpb246IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmVmX2NvbnN0cnVjdGlvbikgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gXCJpdmZmbGF0XCIpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlSW50ZWdlck9wdGlvbih3aXRoT3B0aW9ucy5saXN0cykgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IHsgbGlzdHM6IHRoaXMucGFyc2VJbnRlZ2VyT3B0aW9uKHdpdGhPcHRpb25zLmxpc3RzKSB9XG4gICAgICAgIDoge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUludGVnZXJPcHRpb24odmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZWQgPSBOdW1iZXIucGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHBhcnNlZCkgPyB1bmRlZmluZWQgOiBwYXJzZWQ7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RJbmRleENvbHVtbk9wY2xhc3MoY29sdW1uRGVmaW5pdGlvbjogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWNvbHVtbkRlZmluaXRpb24pIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgdHJpbW1lZCA9IGNvbHVtbkRlZmluaXRpb25cbiAgICAgIC5yZXBsYWNlKC9cXHMrTlVMTFNcXHMrKEZJUlNUfExBU1QpXFxzKiQvaSwgXCJcIilcbiAgICAgIC5yZXBsYWNlKC9cXHMrKEFTQ3xERVNDKVxccyokL2ksIFwiXCIpXG4gICAgICAudHJpbSgpO1xuICAgIGNvbnN0IHRva2VucyA9IHRoaXMudG9rZW5pemVUb3BMZXZlbCh0cmltbWVkKTtcblxuICAgIGlmICh0b2tlbnMubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAodG9rZW5zW3Rva2Vucy5sZW5ndGggLSAyXT8udG9VcHBlckNhc2UoKSA9PT0gXCJDT0xMQVRFXCIpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRva2Vucy5hdCgtMSk7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlSW5kZXhEZWZpbml0aW9uKGluZGV4RGVmaW5pdGlvbjogc3RyaW5nKToge1xuICAgIGFjY2Vzc01ldGhvZD86IHN0cmluZztcbiAgICBjb2x1bW5EZWZpbml0aW9uczogc3RyaW5nW107XG4gICAgd2l0aE9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIH0ge1xuICAgIGNvbnN0IGFjY2Vzc01ldGhvZCA9IGluZGV4RGVmaW5pdGlvbi5tYXRjaCgvXFxiVVNJTkdcXHMrKFthLXpfXVtcXHddKikvaSk/LlsxXT8udG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCB1c2luZ01hdGNoSW5kZXggPSBpbmRleERlZmluaXRpb24uc2VhcmNoKC9cXGJVU0lOR1xcYi9pKTtcbiAgICBjb25zdCBjb2x1bW5zU3RhcnQgPSB1c2luZ01hdGNoSW5kZXggPj0gMCA/IGluZGV4RGVmaW5pdGlvbi5pbmRleE9mKFwiKFwiLCB1c2luZ01hdGNoSW5kZXgpIDogLTE7XG4gICAgY29uc3QgY29sdW1uc0VuZCA9XG4gICAgICBjb2x1bW5zU3RhcnQgPj0gMCA/IHRoaXMuZmluZE1hdGNoaW5nUGFyZW50aGVzaXMoaW5kZXhEZWZpbml0aW9uLCBjb2x1bW5zU3RhcnQpIDogLTE7XG4gICAgY29uc3QgY29sdW1uRGVmaW5pdGlvbnMgPVxuICAgICAgY29sdW1uc1N0YXJ0ID49IDAgJiYgY29sdW1uc0VuZCA+IGNvbHVtbnNTdGFydFxuICAgICAgICA/IHRoaXMuc3BsaXRUb3BMZXZlbChpbmRleERlZmluaXRpb24uc2xpY2UoY29sdW1uc1N0YXJ0ICsgMSwgY29sdW1uc0VuZCksIFwiLFwiKVxuICAgICAgICA6IFtdO1xuXG4gICAgY29uc3Qgd2l0aE1hdGNoID0gL1xcYldJVEhcXHMqXFwoL2kuZXhlYyhpbmRleERlZmluaXRpb24pO1xuICAgIGNvbnN0IHdpdGhTdGFydCA9IHdpdGhNYXRjaCA/IGluZGV4RGVmaW5pdGlvbi5pbmRleE9mKFwiKFwiLCB3aXRoTWF0Y2guaW5kZXgpIDogLTE7XG4gICAgY29uc3Qgd2l0aEVuZCA9IHdpdGhTdGFydCA+PSAwID8gdGhpcy5maW5kTWF0Y2hpbmdQYXJlbnRoZXNpcyhpbmRleERlZmluaXRpb24sIHdpdGhTdGFydCkgOiAtMTtcbiAgICBjb25zdCB3aXRoT3B0aW9ucyA9XG4gICAgICB3aXRoU3RhcnQgPj0gMCAmJiB3aXRoRW5kID4gd2l0aFN0YXJ0XG4gICAgICAgID8gdGhpcy5wYXJzZUluZGV4T3B0aW9uRW50cmllcyhpbmRleERlZmluaXRpb24uc2xpY2Uod2l0aFN0YXJ0ICsgMSwgd2l0aEVuZCkpXG4gICAgICAgIDoge307XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWNjZXNzTWV0aG9kLFxuICAgICAgY29sdW1uRGVmaW5pdGlvbnMsXG4gICAgICB3aXRoT3B0aW9ucyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUluZGV4T3B0aW9uRW50cmllcyhvcHRpb25Tb3VyY2U6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnNwbGl0VG9wTGV2ZWwob3B0aW9uU291cmNlLCBcIixcIikucmVkdWNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+KChyZXN1bHQsIGVudHJ5KSA9PiB7XG4gICAgICBjb25zdCBtYXRjaGVkID0gZW50cnkudHJpbSgpLm1hdGNoKC9eKFthLXpfXVtcXHddKilcXHMqPVxccyooLispJC9pKTtcbiAgICAgIGlmICghbWF0Y2hlZCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBbLCBrZXksIHJhd1ZhbHVlXSA9IG1hdGNoZWQ7XG4gICAgICByZXN1bHRba2V5LnRvTG93ZXJDYXNlKCldID0gcmF3VmFsdWUudHJpbSgpLnJlcGxhY2UoL15bJ1wiXXxbJ1wiXSQvZywgXCJcIik7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3BsaXRUb3BMZXZlbChzb3VyY2U6IHN0cmluZywgZGVsaW1pdGVyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgaXRlbXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHN0YXJ0ID0gMDtcbiAgICBsZXQgcGFyZW5EZXB0aCA9IDA7XG4gICAgbGV0IGJyYWNrZXREZXB0aCA9IDA7XG4gICAgbGV0IGluU2luZ2xlUXVvdGUgPSBmYWxzZTtcbiAgICBsZXQgaW5Eb3VibGVRdW90ZSA9IGZhbHNlO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaW5kZXhdO1xuICAgICAgY29uc3QgbmV4dENoYXIgPSBzb3VyY2VbaW5kZXggKyAxXTtcblxuICAgICAgaWYgKGNoYXIgPT09IFwiJ1wiICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChpblNpbmdsZVF1b3RlICYmIG5leHRDaGFyID09PSBcIidcIikge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5TaW5nbGVRdW90ZSA9ICFpblNpbmdsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09ICdcIicgJiYgIWluU2luZ2xlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluRG91YmxlUXVvdGUgJiYgbmV4dENoYXIgPT09ICdcIicpIHtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGluRG91YmxlUXVvdGUgPSAhaW5Eb3VibGVRdW90ZTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpblNpbmdsZVF1b3RlIHx8IGluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICBwYXJlbkRlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiKVwiKSB7XG4gICAgICAgIHBhcmVuRGVwdGggLT0gMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoY2hhciA9PT0gXCJbXCIpIHtcbiAgICAgICAgYnJhY2tldERlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09IFwiXVwiKSB7XG4gICAgICAgIGJyYWNrZXREZXB0aCAtPSAxO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IGRlbGltaXRlciAmJiBwYXJlbkRlcHRoID09PSAwICYmIGJyYWNrZXREZXB0aCA9PT0gMCkge1xuICAgICAgICBpdGVtcy5wdXNoKHNvdXJjZS5zbGljZShzdGFydCwgaW5kZXgpLnRyaW0oKSk7XG4gICAgICAgIHN0YXJ0ID0gaW5kZXggKyAxO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRhaWwgPSBzb3VyY2Uuc2xpY2Uoc3RhcnQpLnRyaW0oKTtcbiAgICBpZiAodGFpbC5sZW5ndGggPiAwKSB7XG4gICAgICBpdGVtcy5wdXNoKHRhaWwpO1xuICAgIH1cblxuICAgIHJldHVybiBpdGVtcztcbiAgfVxuXG4gIHByaXZhdGUgdG9rZW5pemVUb3BMZXZlbChzb3VyY2U6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0b2tlbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHN0YXJ0ID0gLTE7XG4gICAgbGV0IHBhcmVuRGVwdGggPSAwO1xuICAgIGxldCBicmFja2V0RGVwdGggPSAwO1xuICAgIGxldCBpblNpbmdsZVF1b3RlID0gZmFsc2U7XG4gICAgbGV0IGluRG91YmxlUXVvdGUgPSBmYWxzZTtcblxuICAgIGNvbnN0IHB1c2hUb2tlbiA9IChlbmRJbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdG9rZW4gPSBzb3VyY2Uuc2xpY2Uoc3RhcnQsIGVuZEluZGV4KS50cmltKCk7XG4gICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICB0b2tlbnMucHVzaCh0b2tlbik7XG4gICAgICB9XG4gICAgICBzdGFydCA9IC0xO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgc291cmNlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgY2hhciA9IHNvdXJjZVtpbmRleF07XG4gICAgICBjb25zdCBuZXh0Q2hhciA9IHNvdXJjZVtpbmRleCArIDFdO1xuXG4gICAgICBpZiAoY2hhciA9PT0gXCInXCIgJiYgIWluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGluU2luZ2xlUXVvdGUgJiYgbmV4dENoYXIgPT09IFwiJ1wiKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpblNpbmdsZVF1b3RlID0gIWluU2luZ2xlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gJ1wiJyAmJiAhaW5TaW5nbGVRdW90ZSkge1xuICAgICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5Eb3VibGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gJ1wiJykge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5Eb3VibGVRdW90ZSA9ICFpbkRvdWJsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpblNpbmdsZVF1b3RlICYmICFpbkRvdWJsZVF1b3RlKSB7XG4gICAgICAgIGlmIChjaGFyID09PSBcIihcIikge1xuICAgICAgICAgIGlmIChzdGFydCA8IDApIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBhcmVuRGVwdGggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhciA9PT0gXCIpXCIpIHtcbiAgICAgICAgICBwYXJlbkRlcHRoIC09IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiW1wiKSB7XG4gICAgICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICAgICAgc3RhcnQgPSBpbmRleDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJhY2tldERlcHRoICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09IFwiXVwiKSB7XG4gICAgICAgICAgYnJhY2tldERlcHRoIC09IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoL1xccy8udGVzdChjaGFyKSAmJiBwYXJlbkRlcHRoID09PSAwICYmIGJyYWNrZXREZXB0aCA9PT0gMCkge1xuICAgICAgICAgIHB1c2hUb2tlbihpbmRleCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IGluZGV4O1xuICAgICAgfVxuICAgIH1cblxuICAgIHB1c2hUb2tlbihzb3VyY2UubGVuZ3RoKTtcbiAgICByZXR1cm4gdG9rZW5zO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTWF0Y2hpbmdQYXJlbnRoZXNpcyhzb3VyY2U6IHN0cmluZywgb3BlbkluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBkZXB0aCA9IDA7XG4gICAgbGV0IGluU2luZ2xlUXVvdGUgPSBmYWxzZTtcbiAgICBsZXQgaW5Eb3VibGVRdW90ZSA9IGZhbHNlO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSBvcGVuSW5kZXg7IGluZGV4IDwgc291cmNlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgY2hhciA9IHNvdXJjZVtpbmRleF07XG4gICAgICBjb25zdCBuZXh0Q2hhciA9IHNvdXJjZVtpbmRleCArIDFdO1xuXG4gICAgICBpZiAoY2hhciA9PT0gXCInXCIgJiYgIWluRG91YmxlUXVvdGUpIHtcbiAgICAgICAgaWYgKGluU2luZ2xlUXVvdGUgJiYgbmV4dENoYXIgPT09IFwiJ1wiKSB7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpblNpbmdsZVF1b3RlID0gIWluU2luZ2xlUXVvdGU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gJ1wiJyAmJiAhaW5TaW5nbGVRdW90ZSkge1xuICAgICAgICBpZiAoaW5Eb3VibGVRdW90ZSAmJiBuZXh0Q2hhciA9PT0gJ1wiJykge1xuICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaW5Eb3VibGVRdW90ZSA9ICFpbkRvdWJsZVF1b3RlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGluU2luZ2xlUXVvdGUgfHwgaW5Eb3VibGVRdW90ZSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNoYXIgPT09IFwiKFwiKSB7XG4gICAgICAgIGRlcHRoICs9IDE7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhciA9PT0gXCIpXCIpIHtcbiAgICAgICAgZGVwdGggLT0gMTtcbiAgICAgICAgaWYgKGRlcHRoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIO2KueyglSDthYzsnbTruJTsnZggUEvrpbwg7LC47KGw7ZWY64qUIOuLpOuluCDthYzsnbTruJTsnZggRksg66qp66Gd7J2EIOyhsO2ajO2VqeuLiOuLpC5cbiAgICogUEsg7YOA7J6FIOuzgOqyvSDsi5wg6rSA66CoIEZLIOygnOyVveyhsOqxtOydhCDsgq3soJwv67O16rWs7ZWY6riwIOychO2VtCDsgqzsmqnrkKnri4jri6QuXG4gICAqL1xuICBhc3luYyBnZXRSZWZlcmVuY2luZ0ZvcmVpZ25LZXlzKGRiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZyk6IFByb21pc2U8UmVmZXJlbmNpbmdGb3JlaWduS2V5W10+IHtcbiAgICBjb25zdCBxdWVyeSA9IGBcbiAgICAgIFNFTEVDVFxuICAgICAgICB0Yy50YWJsZV9uYW1lLFxuICAgICAgICB0Yy5jb25zdHJhaW50X25hbWUsXG4gICAgICAgIGtjdS5jb2x1bW5fbmFtZSxcbiAgICAgICAgY2N1LnRhYmxlX25hbWUgQVMgcmVmZXJlbmNlZF90YWJsZV9uYW1lLFxuICAgICAgICBjY3UuY29sdW1uX25hbWUgQVMgcmVmZXJlbmNlZF9jb2x1bW5fbmFtZSxcbiAgICAgICAgcmMudXBkYXRlX3J1bGUsXG4gICAgICAgIHJjLmRlbGV0ZV9ydWxlXG4gICAgICBGUk9NIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZV9jb25zdHJhaW50cyBBUyB0Y1xuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEua2V5X2NvbHVtbl91c2FnZSBBUyBrY3VcbiAgICAgICAgT04gdGMuY29uc3RyYWludF9uYW1lID0ga2N1LmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0ga2N1LnRhYmxlX3NjaGVtYVxuICAgICAgSk9JTiBpbmZvcm1hdGlvbl9zY2hlbWEuY29uc3RyYWludF9jb2x1bW5fdXNhZ2UgQVMgY2N1XG4gICAgICAgIE9OIGNjdS5jb25zdHJhaW50X25hbWUgPSB0Yy5jb25zdHJhaW50X25hbWVcbiAgICAgICAgQU5EIGNjdS50YWJsZV9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIEpPSU4gaW5mb3JtYXRpb25fc2NoZW1hLnJlZmVyZW50aWFsX2NvbnN0cmFpbnRzIEFTIHJjXG4gICAgICAgIE9OIHJjLmNvbnN0cmFpbnRfbmFtZSA9IHRjLmNvbnN0cmFpbnRfbmFtZVxuICAgICAgICBBTkQgcmMuY29uc3RyYWludF9zY2hlbWEgPSB0Yy50YWJsZV9zY2hlbWFcbiAgICAgIFdIRVJFIHRjLmNvbnN0cmFpbnRfdHlwZSA9ICdGT1JFSUdOIEtFWSdcbiAgICAgICAgQU5EIGNjdS50YWJsZV9uYW1lID0gP1xuICAgICAgICBBTkQgdGMudGFibGVfc2NoZW1hID0gJ3B1YmxpYydcbiAgICBgO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGIucmF3KHF1ZXJ5LCBbdGFibGVOYW1lXSk7XG4gICAgcmV0dXJuIHJlc3VsdC5yb3dzLm1hcChcbiAgICAgIChyb3c6IHtcbiAgICAgICAgdGFibGVfbmFtZTogc3RyaW5nO1xuICAgICAgICBjb25zdHJhaW50X25hbWU6IHN0cmluZztcbiAgICAgICAgY29sdW1uX25hbWU6IHN0cmluZztcbiAgICAgICAgcmVmZXJlbmNlZF90YWJsZV9uYW1lOiBzdHJpbmc7XG4gICAgICAgIHJlZmVyZW5jZWRfY29sdW1uX25hbWU6IHN0cmluZztcbiAgICAgICAgdXBkYXRlX3J1bGU6IHN0cmluZztcbiAgICAgICAgZGVsZXRlX3J1bGU6IHN0cmluZztcbiAgICAgIH0pID0+ICh7XG4gICAgICAgIHRhYmxlTmFtZTogcm93LnRhYmxlX25hbWUsXG4gICAgICAgIGNvbnN0cmFpbnROYW1lOiByb3cuY29uc3RyYWludF9uYW1lLFxuICAgICAgICBjb2x1bW5OYW1lOiByb3cuY29sdW1uX25hbWUsXG4gICAgICAgIHJlZmVyZW5jZWRUYWJsZU5hbWU6IHJvdy5yZWZlcmVuY2VkX3RhYmxlX25hbWUsXG4gICAgICAgIHJlZmVyZW5jZWRDb2x1bW5OYW1lOiByb3cucmVmZXJlbmNlZF9jb2x1bW5fbmFtZSxcbiAgICAgICAgb25VcGRhdGU6IHRoaXMubWFwQ29uc3RyYWludEFjdGlvbihyb3cudXBkYXRlX3J1bGUpLFxuICAgICAgICBvbkRlbGV0ZTogdGhpcy5tYXBDb25zdHJhaW50QWN0aW9uKHJvdy5kZWxldGVfcnVsZSksXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIHZlY3RvciDsu6zrn7zsnZggZGltZW5zaW9uc+ulvCDsobDtmoztlanri4jri6QuXG4gICAqIHBnX2F0dHJpYnV0ZeydmCBhdHR0eXBtb2Tsl5DshJwg7LCo7JuQIOyImOulvCDstpTstpztlanri4jri6QuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFZlY3RvckRpbWVuc2lvbnMoXG4gICAgY29tcGFyZURCOiBSYXdDYXBhYmxlS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PiB7XG4gICAgY29uc3QgcXVlcnkgPSBgXG4gICAgICBTRUxFQ1RcbiAgICAgICAgYS5hdHRuYW1lIGFzIGNvbHVtbl9uYW1lLFxuICAgICAgICBhLmF0dHR5cG1vZCBhcyBkaW1lbnNpb25zXG4gICAgICBGUk9NIHBnX2F0dHJpYnV0ZSBhXG4gICAgICBKT0lOIHBnX2NsYXNzIGMgT04gYS5hdHRyZWxpZCA9IGMub2lkXG4gICAgICBKT0lOIHBnX3R5cGUgdCBPTiBhLmF0dHR5cGlkID0gdC5vaWRcbiAgICAgIFdIRVJFIGMucmVsbmFtZSA9ID9cbiAgICAgICAgQU5EIHQudHlwbmFtZSA9ICd2ZWN0b3InXG4gICAgICAgIEFORCBhLmF0dG51bSA+IDBcbiAgICBgO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbXBhcmVEQi5yYXcocXVlcnksIFt0YWJsZU5hbWVdKTtcbiAgICBjb25zdCBkaW1lbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gICAgZm9yIChjb25zdCByb3cgb2YgcmVzdWx0LnJvd3MpIHtcbiAgICAgIC8vIGF0dHR5cG1vZOyXkOyEnCDsi6TsoJwgZGltZW5zaW9ucyDqsJIg7LaU7LacXG4gICAgICBkaW1lbnNpb25zW3Jvdy5jb2x1bW5fbmFtZV0gPSByb3cuZGltZW5zaW9ucyA+IDAgPyByb3cuZGltZW5zaW9ucyA6IDA7XG4gICAgfVxuICAgIHJldHVybiBkaW1lbnNpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvc3RncmVTUUwg7Lus65+8IO2DgOyeheydhCDrtoTshJ3tlZjsl6wgTWlncmF0aW9uQ29sdW1uIOqwneyytOuhnCDrs4DtmZjtlanri4jri6QuXG4gICAqL1xuICByZXNvbHZlREJDb2xUeXBlKFxuICAgIGRiQ29sdW1uOiBQZ0NvbHVtbixcbiAgKTogUGljazxcbiAgICBNaWdyYXRpb25Db2x1bW4sXG4gICAgXCJ0eXBlXCIgfCBcImxlbmd0aFwiIHwgXCJwcmVjaXNpb25cIiB8IFwic2NhbGVcIiB8IFwibnVtYmVyVHlwZVwiIHwgXCJkaW1lbnNpb25zXCJcbiAgPiB7XG4gICAgY29uc3QgeyB1ZHRfbmFtZTogX3VkdF9uYW1lLCBjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGgsIHByZWNpc2lvbiwgbnVtZXJpY19zY2FsZSB9ID0gZGJDb2x1bW47XG5cbiAgICBjb25zdCB7IHVkdF9uYW1lLCBzaW5nbGVPckFycmF5IH0gPSAoKCkgPT4ge1xuICAgICAgaWYgKF91ZHRfbmFtZS5zdGFydHNXaXRoKFwiX1wiKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHVkdF9uYW1lOiBfdWR0X25hbWUuc3Vic3RyaW5nKDEpLFxuICAgICAgICAgIHNpbmdsZU9yQXJyYXk6IFwiW11cIiBhcyBjb25zdCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHVkdF9uYW1lOiBfdWR0X25hbWUsXG4gICAgICAgIHNpbmdsZU9yQXJyYXk6IFwiXCIgYXMgY29uc3QsXG4gICAgICB9O1xuICAgIH0pKCk7XG5cbiAgICAvLyBVVUlEXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInV1aWRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYHV1aWQke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cblxuICAgIC8vIEludGVnZXIgdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwiaW50NFwiKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiBgaW50ZWdlciR7c2luZ2xlT3JBcnJheX1gIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJpbnQ4XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBiaWdJbnRlZ2VyJHtzaW5nbGVPckFycmF5fWAgfTtcbiAgICB9XG5cbiAgICAvLyBTdHJpbmcgdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwidmFyY2hhclwiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBgc3RyaW5nJHtzaW5nbGVPckFycmF5fWAsXG4gICAgICAgIC4uLihjaGFyYWN0ZXJfbWF4aW11bV9sZW5ndGggJiYge1xuICAgICAgICAgIGxlbmd0aDogY2hhcmFjdGVyX21heGltdW1fbGVuZ3RoLFxuICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ0ZXh0XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBzdHJpbmcke3NpbmdsZU9yQXJyYXl9YCB9OyAvLyBTdHJpbmdQcm9wIHdpdGhvdXQgbGVuZ3RoXG4gICAgfVxuXG4gICAgLy8gTnVtYmVyT3JOdW1lcmljIHR5cGVzXG4gICAgaWYgKHVkdF9uYW1lID09PSBcIm51bWVyaWNcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYG51bWJlck9yTnVtZXJpYyR7c2luZ2xlT3JBcnJheX1gLFxuICAgICAgICBudW1iZXJUeXBlOiBcIm51bWVyaWNcIixcbiAgICAgICAgLi4uKHByZWNpc2lvbiAhPT0gbnVsbCAmJlxuICAgICAgICAgIG51bWVyaWNfc2NhbGUgIT09IG51bGwgJiYge1xuICAgICAgICAgICAgcHJlY2lzaW9uOiBwcmVjaXNpb24sXG4gICAgICAgICAgICBzY2FsZTogbnVtZXJpY19zY2FsZSxcbiAgICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJmbG9hdDRcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYG51bWJlck9yTnVtZXJpYyR7c2luZ2xlT3JBcnJheX1gLCBudW1iZXJUeXBlOiBcInJlYWxcIiB9O1xuICAgIH1cbiAgICBpZiAodWR0X25hbWUgPT09IFwiZmxvYXQ4XCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IGBudW1iZXJPck51bWVyaWMke3NpbmdsZU9yQXJyYXl9YCwgbnVtYmVyVHlwZTogXCJkb3VibGUgcHJlY2lzaW9uXCIgfTtcbiAgICB9XG5cbiAgICAvLyBCb29sZWFuXG4gICAgaWYgKHVkdF9uYW1lID09PSBcImJvb2xcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogYGJvb2xlYW4ke3NpbmdsZU9yQXJyYXl9YCB9O1xuICAgIH1cblxuICAgIC8vIFRpbWVzdGFtcHogdHlwZXNcbiAgICBpZiAodWR0X25hbWUgPT09IFwidGltZXN0YW1wdHpcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogYGRhdGUke3NpbmdsZU9yQXJyYXl9YCxcbiAgICAgICAgLi4uKHByZWNpc2lvbiAhPT0gbnVsbCAmJiB7XG4gICAgICAgICAgcHJlY2lzaW9uOiBwcmVjaXNpb24sXG4gICAgICAgIH0pLFxuICAgICAgfTsgLy8gRGF0ZVByb3Ag4oaSIHRpbWVzdGFtcHR6XG4gICAgfVxuXG4gICAgLy8gSlNPTlxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJqc29uXCIgfHwgdWR0X25hbWUgPT09IFwianNvbmJcIikge1xuICAgICAgcmV0dXJuIHsgdHlwZTogXCJqc29uXCIgfTtcbiAgICB9XG5cbiAgICAvLyBWZWN0b3IgKHBndmVjdG9yKVxuICAgIGlmICh1ZHRfbmFtZSA9PT0gXCJ2ZWN0b3JcIikge1xuICAgICAgLy8gdmVjdG9yIO2DgOyeheydmCDssKjsm5Ag7IiY64qUIGNvbHVtbl9kZWZhdWx064KYIOuzhOuPhCDsv7zrpqzroZwg7ZmV7J247ZW07JW8IO2VqFxuICAgICAgLy8g7ZiE7J6s64qUIOq4sOuzuOqwkiAw7Jy866GcIOyEpOyglSAo7Iuk7KCcIGRpbWVuc2lvbnPripQgZ2V0TWlncmF0aW9uU2V0RnJvbURC7JeQ7IScIOuzhOuPhCDsv7zrpqzroZwg7ZmV7J24KVxuICAgICAgcmV0dXJuIHsgdHlwZTogYHZlY3RvciR7c2luZ2xlT3JBcnJheX1gLCBkaW1lbnNpb25zOiAwIH07XG4gICAgfVxuXG4gICAgLy8gdHN2ZWN0b3IgKFBvc3RncmVTUUwg7KCE66y4IOqygOyDieyaqSDtg4DsnoUpXG4gICAgaWYgKHVkdF9uYW1lID09PSBcInRzdmVjdG9yXCIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwidHN2ZWN0b3JcIiB9O1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgcmVzb2x2ZSDrtojqsIDriqXtlZwgUG9zdGdyZVNRTCDsu6zrn7wg7YOA7J6FOiAke3VkdF9uYW1lfWApO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyID0gbmV3IFBvc3RncmVTUUxTY2hlbWFSZWFkZXJDbGFzcygpO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0NBdUVN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
|