sonamu 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.swcrc.project-default +18 -0
- package/bin/cli.js +24 -0
- package/dist/ai/agents/agent.d.ts +11 -0
- package/dist/ai/agents/agent.d.ts.map +1 -0
- package/dist/ai/agents/agent.js +65 -0
- package/dist/ai/agents/index.d.ts +3 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +4 -0
- package/dist/ai/agents/types.d.ts +43 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +3 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/providers/rtzr/api.d.ts +22 -0
- package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/api.js +28 -0
- package/dist/ai/providers/rtzr/error.d.ts +18 -0
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/error.js +29 -0
- package/dist/ai/providers/rtzr/index.d.ts +5 -0
- package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/index.js +6 -0
- package/dist/ai/providers/rtzr/model.d.ts +52 -0
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/model.js +137 -0
- package/dist/ai/providers/rtzr/options.d.ts +7 -0
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/options.js +47 -0
- package/dist/ai/providers/rtzr/provider.d.ts +18 -0
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/provider.js +54 -0
- package/dist/ai/providers/rtzr/utils.d.ts +19 -0
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/utils.js +88 -0
- package/dist/api/base-frame.d.ts +2 -2
- package/dist/api/base-frame.d.ts.map +1 -1
- package/dist/api/base-frame.js +2 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +6 -1
- package/dist/api/code-converters.d.ts +58 -14
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +178 -409
- package/dist/api/config.d.ts +27 -13
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +19 -26
- package/dist/api/context.d.ts +4 -3
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +111 -18
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -3
- package/dist/api/sonamu.d.ts +7 -7
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +83 -51
- package/dist/api/validator.d.ts +6 -0
- package/dist/api/validator.d.ts.map +1 -0
- package/dist/api/validator.js +81 -0
- package/dist/bin/build-config.d.ts +5 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +5 -2
- package/dist/bin/cli.js +165 -64
- package/dist/bin/loader-register.d.ts +2 -0
- package/dist/bin/loader-register.d.ts.map +1 -0
- package/dist/bin/loader-register.js +34 -0
- package/dist/database/_batch_update.d.ts +5 -3
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +30 -13
- package/dist/database/base-model.d.ts +96 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +232 -89
- package/dist/database/base-model.types.d.ts +93 -0
- package/dist/database/base-model.types.d.ts.map +1 -0
- package/dist/database/base-model.types.js +10 -0
- package/dist/database/code-generator.d.ts +1 -1
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +11 -10
- package/dist/database/db.d.ts +5 -6
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +22 -25
- package/dist/database/puri-subset.test-d.js +81 -0
- package/dist/database/puri-subset.types.d.ts +123 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -0
- package/dist/database/puri-subset.types.js +16 -0
- package/dist/database/puri-wrapper.d.ts +13 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +2 -2
- package/dist/database/puri.d.ts +25 -14
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +83 -21
- package/dist/database/puri.types.d.ts +21 -7
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +4 -1
- package/dist/database/transaction-context.d.ts +1 -1
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +1 -1
- package/dist/database/upsert-builder.d.ts +9 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +227 -78
- package/dist/entity/entity-manager.d.ts +165 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +26 -10
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +153 -54
- package/dist/exceptions/error-handler.d.ts +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +1 -1
- package/dist/exceptions/so-exceptions.d.ts +1 -1
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +1 -1
- package/dist/file-storage/driver.d.ts +1 -1
- package/dist/file-storage/driver.d.ts.map +1 -1
- package/dist/file-storage/driver.js +1 -1
- package/dist/file-storage/file-storage.js +2 -2
- package/dist/index.d.ts +18 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -13
- package/dist/migration/code-generation.d.ts +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +123 -67
- package/dist/migration/migration-set.d.ts +2 -10
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +67 -218
- package/dist/migration/migrator.d.ts +24 -73
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +121 -301
- package/dist/migration/postgresql-schema-reader.d.ts +51 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
- package/dist/migration/postgresql-schema-reader.js +245 -0
- package/dist/migration/types.d.ts +6 -38
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +1 -1
- package/dist/naite/messaging-types.d.ts +43 -0
- package/dist/naite/messaging-types.d.ts.map +1 -0
- package/dist/naite/messaging-types.js +7 -0
- package/dist/naite/naite-reporter.d.ts +41 -0
- package/dist/naite/naite-reporter.d.ts.map +1 -0
- package/dist/naite/naite-reporter.js +102 -0
- package/dist/naite/naite.d.ts +91 -8
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +285 -41
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +1 -1
- package/dist/syncer/api-parser.d.ts +3 -13
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +67 -56
- package/dist/syncer/checksum.d.ts +2 -2
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +11 -11
- package/dist/syncer/code-generator.d.ts +3 -3
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +37 -17
- package/dist/syncer/entity-operations.d.ts +2 -2
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +9 -8
- package/dist/syncer/file-patterns.d.ts +1 -1
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +1 -1
- package/dist/syncer/index.d.ts +4 -4
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +5 -5
- package/dist/syncer/module-loader.d.ts +4 -4
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +17 -12
- package/dist/syncer/syncer.d.ts +31 -24
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +92 -45
- package/dist/template/entity-converter.d.ts +1 -1
- package/dist/template/entity-converter.d.ts.map +1 -1
- package/dist/template/entity-converter.js +15 -8
- package/dist/template/helpers.d.ts +2 -2
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +3 -3
- package/dist/template/implementations/entity.template.d.ts +2 -2
- package/dist/template/implementations/entity.template.d.ts.map +1 -1
- package/dist/template/implementations/entity.template.js +4 -5
- package/dist/template/implementations/generated.template.d.ts +2 -3
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +46 -29
- package/dist/template/implementations/generated_http.template.d.ts +2 -3
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +9 -9
- package/dist/template/implementations/generated_sso.template.d.ts +3 -4
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +54 -25
- package/dist/template/implementations/init_types.template.d.ts +2 -2
- package/dist/template/implementations/init_types.template.d.ts.map +1 -1
- package/dist/template/implementations/init_types.template.js +2 -2
- package/dist/template/implementations/model.template.d.ts +2 -2
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +47 -37
- package/dist/template/implementations/model_test.template.d.ts +2 -2
- package/dist/template/implementations/model_test.template.d.ts.map +1 -1
- package/dist/template/implementations/model_test.template.js +2 -2
- package/dist/template/implementations/service.template.d.ts +4 -4
- package/dist/template/implementations/service.template.d.ts.map +1 -1
- package/dist/template/implementations/service.template.js +24 -16
- package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_select.template.js +2 -2
- package/dist/template/implementations/view_form.template.d.ts +2 -2
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +4 -4
- package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_all_select.template.js +1 -1
- package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_async_select.template.js +1 -1
- package/dist/template/implementations/view_list.template.d.ts +2 -2
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +29 -19
- package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list_columns.template.js +1 -1
- package/dist/template/implementations/view_search_input.template.d.ts +2 -2
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
- package/dist/template/implementations/view_search_input.template.js +1 -1
- package/dist/template/index.d.ts +4 -2
- package/dist/template/index.d.ts.map +1 -1
- package/dist/template/index.js +5 -3
- package/dist/template/template-manager.d.ts +56 -0
- package/dist/template/template-manager.d.ts.map +1 -0
- package/dist/template/template-manager.js +125 -0
- package/dist/template/template-types.d.ts +16 -0
- package/dist/template/template-types.d.ts.map +1 -0
- package/dist/template/template-types.js +7 -0
- package/dist/template/template.d.ts +12 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +19 -6
- package/dist/template/zod-converter.d.ts +40 -7
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +386 -58
- package/dist/testing/_relation-graph.d.ts +1 -1
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +12 -3
- package/dist/testing/fixture-manager.d.ts +42 -11
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +338 -236
- package/dist/types/types.d.ts +709 -104
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +309 -52
- package/dist/typings/knex.d.js +2 -2
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +3 -3
- package/dist/utils/console-util.js +1 -1
- package/dist/utils/controller.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +4 -1
- package/dist/utils/esm-utils.d.ts +0 -6
- package/dist/utils/esm-utils.d.ts.map +1 -1
- package/dist/utils/esm-utils.js +2 -9
- package/dist/utils/formatter.d.ts +3 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +110 -0
- package/dist/utils/fs-utils.d.ts +1 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +1 -1
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +1 -1
- package/dist/utils/object-utils.d.ts +44 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +191 -0
- package/dist/utils/path-utils.d.ts +1 -1
- package/dist/utils/path-utils.d.ts.map +1 -1
- package/dist/utils/path-utils.js +3 -3
- package/dist/utils/process-utils.js +1 -1
- package/dist/utils/sql-parser.d.ts +5 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +14 -3
- package/dist/utils/type-utils.d.ts +23 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +45 -0
- package/dist/utils/utils.d.ts +7 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +44 -5
- package/dist/utils/zod-error.d.ts +1 -1
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +1 -1
- package/package.json +55 -30
- package/src/ai/agents/agent.ts +87 -0
- package/src/ai/agents/index.ts +2 -0
- package/src/ai/agents/types.ts +47 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/providers/rtzr/api.ts +37 -0
- package/src/ai/providers/rtzr/error.ts +34 -0
- package/src/ai/providers/rtzr/index.ts +4 -0
- package/src/ai/providers/rtzr/model.ts +201 -0
- package/src/ai/providers/rtzr/options.ts +49 -0
- package/src/ai/providers/rtzr/provider.ts +91 -0
- package/src/ai/providers/rtzr/utils.ts +127 -0
- package/src/api/base-frame.ts +4 -2
- package/src/api/caster.ts +17 -23
- package/src/api/code-converters.ts +176 -533
- package/src/api/config.ts +39 -56
- package/src/api/context.ts +7 -18
- package/src/api/decorators.ts +175 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +133 -124
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +7 -1
- package/src/bin/cli.ts +192 -110
- package/src/bin/loader-register.ts +38 -0
- package/src/database/_batch_update.ts +46 -31
- package/src/database/base-model.ts +390 -182
- package/src/database/base-model.types.ts +155 -0
- package/src/database/code-generator.ts +13 -32
- package/src/database/db.ts +36 -50
- package/src/database/puri-subset.test-d.ts +471 -0
- package/src/database/puri-subset.types.ts +195 -0
- package/src/database/puri-wrapper.ts +58 -67
- package/src/database/puri.ts +182 -126
- package/src/database/puri.types.ts +64 -31
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +261 -132
- package/src/entity/entity-manager.ts +36 -28
- package/src/entity/entity.ts +330 -249
- package/src/exceptions/error-handler.ts +3 -3
- package/src/exceptions/so-exceptions.ts +11 -11
- package/src/file-storage/driver.ts +5 -5
- package/src/file-storage/file-storage.ts +2 -2
- package/src/index.ts +18 -12
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +182 -425
- package/src/migration/mysql-schema-reader.ts.txt +272 -0
- package/src/migration/postgresql-schema-reader.ts +310 -0
- package/src/migration/types.ts +6 -39
- package/src/naite/messaging-types.ts +51 -0
- package/src/naite/naite-reporter.ts +128 -0
- package/src/naite/naite.ts +378 -33
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +52 -69
- package/src/syncer/checksum.ts +25 -37
- package/src/syncer/code-generator.ts +58 -62
- package/src/syncer/entity-operations.ts +12 -15
- package/src/syncer/file-patterns.ts +2 -2
- package/src/syncer/index.ts +4 -4
- package/src/syncer/module-loader.ts +28 -25
- package/src/syncer/syncer.ts +155 -162
- package/src/template/entity-converter.ts +18 -27
- package/src/template/helpers.ts +8 -11
- package/src/template/implementations/entity.template.ts +6 -6
- package/src/template/implementations/generated.template.ts +99 -99
- package/src/template/implementations/generated_http.template.ts +21 -54
- package/src/template/implementations/generated_sso.template.ts +78 -65
- package/src/template/implementations/init_types.template.ts +4 -6
- package/src/template/implementations/model.template.ts +47 -38
- package/src/template/implementations/model_test.template.ts +3 -3
- package/src/template/implementations/service.template.ts +56 -80
- package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
- package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
- package/src/template/implementations/view_enums_select.template.ts +3 -3
- package/src/template/implementations/view_form.template.ts +34 -75
- package/src/template/implementations/view_id_all_select.template.ts +2 -2
- package/src/template/implementations/view_id_async_select.template.ts +9 -23
- package/src/template/implementations/view_list.template.ts +54 -95
- package/src/template/implementations/view_list_columns.template.ts +4 -10
- package/src/template/implementations/view_search_input.template.ts +2 -2
- package/src/template/index.ts +4 -2
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +29 -10
- package/src/template/zod-converter.ts +459 -101
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +468 -362
- package/src/types/types.ts +516 -248
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +8 -12
- package/src/utils/console-util.ts +1 -1
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +8 -18
- package/src/utils/formatter.ts +109 -0
- package/src/utils/fs-utils.ts +1 -1
- package/src/utils/lodash-able.ts +1 -4
- package/src/utils/object-utils.ts +217 -0
- package/src/utils/path-utils.ts +3 -6
- package/src/utils/process-utils.ts +1 -1
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +58 -9
- package/src/utils/zod-error.ts +3 -3
- package/dist/bin/cli-wrapper.d.ts +0 -3
- package/dist/bin/cli-wrapper.d.ts.map +0 -1
- package/dist/bin/cli-wrapper.js +0 -72
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
- package/dist/entity/entity-utils.d.ts +0 -61
- package/dist/entity/entity-utils.d.ts.map +0 -1
- package/dist/entity/entity-utils.js +0 -210
- package/src/bin/cli-wrapper.ts +0 -82
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Knex } from "knex";
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
2
|
type TableData = {
|
|
3
3
|
references: Set<string>;
|
|
4
|
-
rows:
|
|
4
|
+
rows: Record<string, unknown>[];
|
|
5
5
|
uniqueIndexes: {
|
|
6
6
|
name?: string;
|
|
7
7
|
columns: string[];
|
|
@@ -13,7 +13,7 @@ export type UBRef = {
|
|
|
13
13
|
of: string;
|
|
14
14
|
use?: string;
|
|
15
15
|
};
|
|
16
|
-
export declare function isRefField(field:
|
|
16
|
+
export declare function isRefField(field: unknown): field is UBRef;
|
|
17
17
|
export declare class UpsertBuilder {
|
|
18
18
|
tables: Map<string, TableData>;
|
|
19
19
|
constructor();
|
|
@@ -29,6 +29,12 @@ export declare class UpsertBuilder {
|
|
|
29
29
|
chunkSize?: number;
|
|
30
30
|
where?: string | string[];
|
|
31
31
|
}): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* rows를 의존성 순서에 따라 레벨별로 그룹화
|
|
34
|
+
* - 자기 참조 없는 경우 : 모든 rows가 Level 0
|
|
35
|
+
* - 자기 참조 있는 경우 : 자기 참조 관계를 위상 정렬하여 레벨별로 그룹화
|
|
36
|
+
*/
|
|
37
|
+
private buildInsertLevels;
|
|
32
38
|
}
|
|
33
39
|
export {};
|
|
34
40
|
//# sourceMappingURL=upsert-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsert-builder.d.ts","sourceRoot":"","sources":["../../src/database/upsert-builder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upsert-builder.d.ts","sourceRoot":"","sources":["../../src/database/upsert-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAOjC,KAAK,SAAS,GAAG;IACf,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,aAAa,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACtD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AACF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAOzD;AAED,qBAAa,aAAa;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;;IAK/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAwBtC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIpC,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE;SACF,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO;KAClF,GACA,KAAK;IAqFF,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAG3E,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/E,cAAc,CAClB,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GAAG,QAAQ,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC;IAoKd,WAAW,CACf,GAAG,EAAE,IAAI,EACT,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;IAyChB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CA8D1B"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
-
import
|
|
2
|
+
import { unique } from "radashi";
|
|
3
3
|
import { EntityManager } from "../entity/entity-manager.js";
|
|
4
|
-
import {
|
|
4
|
+
import { Naite } from "../naite/naite.js";
|
|
5
|
+
import { assertDefined, chunk, nonNullable } from "../utils/utils.js";
|
|
5
6
|
import { batchUpdate } from "./_batch_update.js";
|
|
6
7
|
export function isRefField(field) {
|
|
7
|
-
return field !== undefined && field !== null && field
|
|
8
|
+
return field !== undefined && field !== null && field?.of !== undefined && field?.uuid !== undefined;
|
|
8
9
|
}
|
|
9
10
|
export class UpsertBuilder {
|
|
10
11
|
tables;
|
|
@@ -13,22 +14,24 @@ export class UpsertBuilder {
|
|
|
13
14
|
}
|
|
14
15
|
getTable(tableName) {
|
|
15
16
|
const table = this.tables.get(tableName);
|
|
16
|
-
if (table
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
return EntityManager.getTableSpec(tableName);
|
|
20
|
-
} catch {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
})();
|
|
24
|
-
this.tables.set(tableName, {
|
|
25
|
-
references: new Set(),
|
|
26
|
-
rows: [],
|
|
27
|
-
uniqueIndexes: tableSpec?.uniqueIndexes ?? [],
|
|
28
|
-
uniquesMap: new Map()
|
|
29
|
-
});
|
|
17
|
+
if (table) {
|
|
18
|
+
return table;
|
|
30
19
|
}
|
|
31
|
-
|
|
20
|
+
const tableSpec = (()=>{
|
|
21
|
+
try {
|
|
22
|
+
return EntityManager.getTableSpec(tableName);
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
27
|
+
const tableData = {
|
|
28
|
+
references: new Set(),
|
|
29
|
+
rows: [],
|
|
30
|
+
uniqueIndexes: tableSpec?.uniqueIndexes ?? [],
|
|
31
|
+
uniquesMap: new Map()
|
|
32
|
+
};
|
|
33
|
+
this.tables.set(tableName, tableData);
|
|
34
|
+
return tableData;
|
|
32
35
|
}
|
|
33
36
|
hasTable(tableName) {
|
|
34
37
|
return this.tables.has(tableName);
|
|
@@ -52,17 +55,23 @@ export class UpsertBuilder {
|
|
|
52
55
|
return uniqueKeyArray.join("---delimiter--");
|
|
53
56
|
}).filter(nonNullable);
|
|
54
57
|
// uuid 생성 로직
|
|
55
|
-
const uuid = (()=>{
|
|
58
|
+
const { uuid, isReused } = (()=>{
|
|
56
59
|
// 키를 순회하여 이미 존재하는 키가 있는지 확인
|
|
57
60
|
if (uniqueKeys.length > 0) {
|
|
58
61
|
for (const uniqueKey of uniqueKeys){
|
|
59
62
|
if (table.uniquesMap.has(uniqueKey)) {
|
|
60
|
-
return
|
|
63
|
+
return {
|
|
64
|
+
uuid: assertDefined(table.uniquesMap.get(uniqueKey), "Unique key not found"),
|
|
65
|
+
isReused: true
|
|
66
|
+
};
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
// 찾을 수 없는 경우 생성
|
|
65
|
-
return
|
|
71
|
+
return {
|
|
72
|
+
uuid: randomUUID(),
|
|
73
|
+
isReused: false
|
|
74
|
+
};
|
|
66
75
|
})();
|
|
67
76
|
// 모든 유니크키에 대해 유니크맵에 uuid 저장
|
|
68
77
|
if (uniqueKeys.length > 0) {
|
|
@@ -72,28 +81,42 @@ export class UpsertBuilder {
|
|
|
72
81
|
}
|
|
73
82
|
// 이 테이블에 사용된 RefField를 순회하여, 현재 테이블 정보에 어떤 필드를 참조하는지 추가
|
|
74
83
|
// 이 정보를 나중에 치환할 때 사용
|
|
75
|
-
row = Object.
|
|
76
|
-
const rowValue = row[rowKey];
|
|
84
|
+
row = Object.fromEntries(Object.entries(row).map(([rowKey, rowValue])=>{
|
|
77
85
|
if (isRefField(rowValue)) {
|
|
78
86
|
rowValue.use ??= "id";
|
|
79
|
-
table.references.add(rowValue.of
|
|
80
|
-
|
|
87
|
+
table.references.add(`${rowValue.of}.${rowValue.use}`);
|
|
88
|
+
return [
|
|
89
|
+
rowKey,
|
|
90
|
+
rowValue
|
|
91
|
+
];
|
|
81
92
|
} else if (typeof rowValue === "object" && !(rowValue instanceof Date)) {
|
|
82
93
|
// object인 경우 JSON으로 변환
|
|
83
|
-
|
|
94
|
+
return [
|
|
95
|
+
rowKey,
|
|
96
|
+
rowValue === null ? null : JSON.stringify(rowValue)
|
|
97
|
+
];
|
|
84
98
|
} else {
|
|
85
|
-
|
|
99
|
+
return [
|
|
100
|
+
rowKey,
|
|
101
|
+
rowValue
|
|
102
|
+
];
|
|
86
103
|
}
|
|
87
|
-
|
|
88
|
-
}, {});
|
|
104
|
+
}));
|
|
89
105
|
table.rows.push({
|
|
90
106
|
uuid,
|
|
91
107
|
...row
|
|
92
108
|
});
|
|
93
|
-
|
|
109
|
+
const result = {
|
|
94
110
|
of: tableName,
|
|
95
111
|
uuid: row.uuid ?? uuid
|
|
96
112
|
};
|
|
113
|
+
Naite.t("puri:ub-register", {
|
|
114
|
+
tableName,
|
|
115
|
+
uuid: result.uuid,
|
|
116
|
+
isUuidReused: isReused,
|
|
117
|
+
row
|
|
118
|
+
});
|
|
119
|
+
return result;
|
|
97
120
|
}
|
|
98
121
|
async upsert(wdb, tableName, chunkSize) {
|
|
99
122
|
return this.upsertOrInsert(wdb, tableName, "upsert", chunkSize);
|
|
@@ -116,7 +139,7 @@ export class UpsertBuilder {
|
|
|
116
139
|
}
|
|
117
140
|
// 전체 테이블 순회하여 현재 테이블 참조하는 모든 테이블 추출
|
|
118
141
|
const { references, refTables } = Array.from(this.tables).reduce((r, [, table])=>{
|
|
119
|
-
const reference = Array.from(table.references.values()).find((ref)=>ref.includes(tableName
|
|
142
|
+
const reference = Array.from(table.references.values()).find((ref)=>ref.includes(`${tableName}.`));
|
|
120
143
|
if (reference) {
|
|
121
144
|
r.references.push(reference);
|
|
122
145
|
r.refTables.push(table);
|
|
@@ -126,90 +149,216 @@ export class UpsertBuilder {
|
|
|
126
149
|
references: [],
|
|
127
150
|
refTables: []
|
|
128
151
|
});
|
|
129
|
-
const extractFields =
|
|
130
|
-
//
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
const extractFields = unique(references).map((reference)=>reference.split(".")[1]).filter((field)=>field !== undefined);
|
|
153
|
+
// 의존성 순서에 따라 레벨별 그룹화 (자기 참조가 없으면 Level 0 하나)
|
|
154
|
+
const { levels, hasCircular } = this.buildInsertLevels(table.rows, tableName);
|
|
155
|
+
if (hasCircular) {
|
|
156
|
+
throw new Error(`${tableName}에 순환 자기 참조가 있습니다.`);
|
|
157
|
+
}
|
|
158
|
+
// upsert 모드일 때 유니크 인덱스가 없으면 에러
|
|
159
|
+
if (mode === "upsert" && table.uniqueIndexes.length === 0) {
|
|
160
|
+
throw new Error(`${tableName}에 unique index가 정의되지 않아 upsert를 할 수 없습니다.`);
|
|
161
|
+
}
|
|
137
162
|
const uuidMap = new Map();
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
163
|
+
const allIds = [];
|
|
164
|
+
// 레벨별로 순차 처리
|
|
165
|
+
for (const levelRows of levels){
|
|
166
|
+
// 이전 레벨에서 얻은 ID로 자기 참조 해결
|
|
167
|
+
const resolvedRows = levelRows.map((row)=>{
|
|
168
|
+
const resolved = {
|
|
169
|
+
...row
|
|
170
|
+
};
|
|
171
|
+
for (const [key, value] of Object.entries(row)){
|
|
172
|
+
if (isRefField(value) && value.of === tableName) {
|
|
173
|
+
const parent = uuidMap.get(value.uuid);
|
|
174
|
+
if (!parent) throw new Error(`존재하지 않는 uuid ${value.uuid} -- in ${tableName}`);
|
|
175
|
+
resolved[key] = parent[value.use ?? "id"];
|
|
176
|
+
Naite.t("puri:ub-ref-resolved", {
|
|
177
|
+
tableName,
|
|
178
|
+
field: key,
|
|
179
|
+
from: {
|
|
180
|
+
of: value.of,
|
|
181
|
+
uuid: value.uuid,
|
|
182
|
+
use: value.use ?? "id"
|
|
183
|
+
},
|
|
184
|
+
to: resolved[key]
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return resolved;
|
|
189
|
+
});
|
|
190
|
+
// 현재 레벨 upsert
|
|
191
|
+
const levelChunks = chunkSize ? chunk(resolvedRows, chunkSize) : [
|
|
192
|
+
resolvedRows
|
|
193
|
+
];
|
|
194
|
+
const selectFields = unique([
|
|
148
195
|
"uuid",
|
|
149
196
|
"id",
|
|
150
197
|
...extractFields
|
|
151
|
-
])
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
198
|
+
]);
|
|
199
|
+
for (const dataChunk of levelChunks){
|
|
200
|
+
if (dataChunk.length === 0) continue;
|
|
201
|
+
let resultRows;
|
|
202
|
+
if (mode === "insert") {
|
|
203
|
+
// INSERT 모드
|
|
204
|
+
await wdb.insert(dataChunk).into(tableName);
|
|
205
|
+
const uuids = dataChunk.map((r)=>r.uuid);
|
|
206
|
+
resultRows = await wdb(tableName).select(selectFields).whereIn("uuid", uuids);
|
|
207
|
+
} else {
|
|
208
|
+
// UPSERT 모드: onConflict로 중복 처리
|
|
209
|
+
const conflictColumns = table.uniqueIndexes[0].columns;
|
|
210
|
+
const updateColumns = Object.keys(dataChunk[0]).filter((col)=>col !== "uuid" && !conflictColumns.includes(col));
|
|
211
|
+
const query = wdb.insert(dataChunk).into(tableName).onConflict(conflictColumns);
|
|
212
|
+
// updateColumns 유무에 따라 ignore/merge 선택하고 RETURNING으로 결과 받기
|
|
213
|
+
if (updateColumns.length === 0) {
|
|
214
|
+
resultRows = await query.ignore().returning(selectFields);
|
|
215
|
+
} else {
|
|
216
|
+
resultRows = await query.merge(updateColumns).returning(selectFields);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// 양쪽 모드 공통 처리
|
|
220
|
+
for (const row of resultRows){
|
|
221
|
+
uuidMap.set(row.uuid, row);
|
|
222
|
+
allIds.push(row.id);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
155
225
|
}
|
|
156
226
|
// 해당 테이블 참조를 실제 밸류로 변경
|
|
157
|
-
|
|
227
|
+
for (const table of refTables){
|
|
158
228
|
table.rows = table.rows.map((row)=>{
|
|
159
|
-
Object.keys(row)
|
|
229
|
+
for (const key of Object.keys(row)){
|
|
160
230
|
const prop = row[key];
|
|
161
231
|
if (isRefField(prop) && prop.of === tableName) {
|
|
162
232
|
const parent = uuidMap.get(prop.uuid);
|
|
163
|
-
if (parent
|
|
233
|
+
if (!parent) {
|
|
164
234
|
console.error(prop);
|
|
165
235
|
throw new Error(`존재하지 않는 uuid ${prop.uuid} -- in ${tableName}`);
|
|
166
236
|
}
|
|
167
|
-
|
|
237
|
+
const resolvedValue = parent[prop.use ?? "id"];
|
|
238
|
+
row[key] = resolvedValue;
|
|
239
|
+
Naite.t("puri:ub-ref-resolved", {
|
|
240
|
+
tableName,
|
|
241
|
+
field: key,
|
|
242
|
+
from: {
|
|
243
|
+
of: prop.of,
|
|
244
|
+
uuid: prop.uuid,
|
|
245
|
+
use: prop.use ?? "id"
|
|
246
|
+
},
|
|
247
|
+
to: resolvedValue
|
|
248
|
+
});
|
|
168
249
|
}
|
|
169
|
-
}
|
|
250
|
+
}
|
|
170
251
|
return row;
|
|
171
252
|
});
|
|
172
|
-
});
|
|
173
|
-
const allIds = Array.from(uuidMap.values()).map((row)=>row.id);
|
|
174
|
-
// 자기 참조가 있는 경우 재귀적으로 upsert
|
|
175
|
-
if (selfRefRows.length > 0) {
|
|
176
|
-
// 처리된 데이터를 제외하고 다시 upsert
|
|
177
|
-
table.rows = selfRefRows;
|
|
178
|
-
const selfRefIds = await this.upsert(wdb, tableName, chunkSize);
|
|
179
|
-
allIds.push(...selfRefIds);
|
|
180
|
-
} else {
|
|
181
|
-
// 자기 참조가 없으면 해당 테이블의 데이터 초기화
|
|
182
|
-
table.rows = [];
|
|
183
|
-
table.references.clear();
|
|
184
|
-
table.uniquesMap.clear();
|
|
185
253
|
}
|
|
254
|
+
// 해당 테이블의 데이터 초기화
|
|
255
|
+
table.rows = [];
|
|
256
|
+
table.references.clear();
|
|
257
|
+
table.uniquesMap.clear();
|
|
258
|
+
Naite.t("puri:ub-upserted", {
|
|
259
|
+
tableName,
|
|
260
|
+
mode,
|
|
261
|
+
rowCount: allIds.length,
|
|
262
|
+
returnedIds: allIds
|
|
263
|
+
});
|
|
186
264
|
return allIds;
|
|
187
265
|
}
|
|
188
266
|
async updateBatch(wdb, tableName, options) {
|
|
189
|
-
options =
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
267
|
+
options = {
|
|
268
|
+
...options,
|
|
269
|
+
chunkSize: options?.chunkSize ?? 500,
|
|
270
|
+
where: options?.where ?? "id"
|
|
271
|
+
};
|
|
193
272
|
if (this.hasTable(tableName) === false) {
|
|
194
273
|
return;
|
|
195
274
|
}
|
|
196
275
|
const table = this.tables.get(tableName);
|
|
197
|
-
if (table
|
|
276
|
+
if (!table) {
|
|
277
|
+
throw new Error(`등록되지 않은 테이블 ${tableName}에 updateBatch 요청`);
|
|
278
|
+
} else if (table.rows.length === 0) {
|
|
198
279
|
return;
|
|
199
280
|
}
|
|
200
281
|
const whereColumns = Array.isArray(options.where) ? options.where : [
|
|
201
282
|
options.where ?? "id"
|
|
202
283
|
];
|
|
203
284
|
const rows = table.rows.map((_row)=>{
|
|
204
|
-
const { uuid, ...row } = _row;
|
|
285
|
+
const { uuid: _, ...row } = _row; // uuid 제외
|
|
205
286
|
return row;
|
|
206
287
|
});
|
|
207
288
|
await batchUpdate(wdb, tableName, whereColumns, rows, options.chunkSize);
|
|
289
|
+
Naite.t("puri:ub-batch-updated", {
|
|
290
|
+
tableName,
|
|
291
|
+
rowCount: rows.length,
|
|
292
|
+
whereColumns
|
|
293
|
+
});
|
|
208
294
|
// updateBatch 완료 후 처리된 데이터 제거
|
|
209
295
|
table.rows = [];
|
|
210
296
|
table.references.clear();
|
|
211
297
|
table.uniquesMap.clear();
|
|
212
298
|
}
|
|
299
|
+
// ============================================================================
|
|
300
|
+
// Private Helpers
|
|
301
|
+
// ============================================================================
|
|
302
|
+
/**
|
|
303
|
+
* rows를 의존성 순서에 따라 레벨별로 그룹화
|
|
304
|
+
* - 자기 참조 없는 경우 : 모든 rows가 Level 0
|
|
305
|
+
* - 자기 참조 있는 경우 : 자기 참조 관계를 위상 정렬하여 레벨별로 그룹화
|
|
306
|
+
*/ buildInsertLevels(rows, tableName) {
|
|
307
|
+
// 1. 자기 참조가 없으면 한 레벨로 처리
|
|
308
|
+
const hasSelfRef = rows.flatMap((row)=>Object.values(row)).some((value)=>isRefField(value) && value.of === tableName);
|
|
309
|
+
if (!hasSelfRef) return {
|
|
310
|
+
levels: [
|
|
311
|
+
rows
|
|
312
|
+
],
|
|
313
|
+
hasCircular: false
|
|
314
|
+
};
|
|
315
|
+
// 2. uuid → row 매핑 (중복 uuid 방지)
|
|
316
|
+
const rowByUuid = new Map();
|
|
317
|
+
for (const row of rows){
|
|
318
|
+
const uuid = row.uuid;
|
|
319
|
+
if (!uuid) throw new Error(`buildInsertLevels: uuid가 없는 row -- in ${tableName}`);
|
|
320
|
+
rowByUuid.set(uuid, row);
|
|
321
|
+
}
|
|
322
|
+
let pending = Array.from(rowByUuid.values());
|
|
323
|
+
const levels = [];
|
|
324
|
+
const inserted = new Set();
|
|
325
|
+
// 3. 레벨별 분류
|
|
326
|
+
while(pending.length > 0){
|
|
327
|
+
const currentLevel = [];
|
|
328
|
+
const nextPending = [];
|
|
329
|
+
for (const row of pending){
|
|
330
|
+
// 이 row가 참조하는 자기 참조들
|
|
331
|
+
const selfRefs = Object.values(row).filter((value)=>isRefField(value) && value.of === tableName);
|
|
332
|
+
// 참조하는 모든 uuid가 이미 inserted에 있어야 이번 레벨에 포함
|
|
333
|
+
const canInsert = selfRefs.every((ref)=>{
|
|
334
|
+
if (!rowByUuid.has(ref.uuid)) {
|
|
335
|
+
throw new Error(`존재하지 않는 uuid ${ref.uuid} -- in ${tableName}`);
|
|
336
|
+
}
|
|
337
|
+
return inserted.has(ref.uuid);
|
|
338
|
+
});
|
|
339
|
+
if (canInsert) {
|
|
340
|
+
currentLevel.push(row);
|
|
341
|
+
} else {
|
|
342
|
+
nextPending.push(row);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// 순환 참조 감지
|
|
346
|
+
if (currentLevel.length === 0) return {
|
|
347
|
+
levels: [],
|
|
348
|
+
hasCircular: true
|
|
349
|
+
};
|
|
350
|
+
// 레벨 확정 + inserted 갱신
|
|
351
|
+
levels.push(currentLevel);
|
|
352
|
+
for (const row of currentLevel){
|
|
353
|
+
inserted.add(row.uuid);
|
|
354
|
+
}
|
|
355
|
+
pending = nextPending;
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
levels,
|
|
359
|
+
hasCircular: false
|
|
360
|
+
};
|
|
361
|
+
}
|
|
213
362
|
}
|
|
214
363
|
|
|
215
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS91cHNlcnQtYnVpbGRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0ICogYXMgXyBmcm9tIFwibG9kYXNoLWVzXCI7XG5pbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBub25OdWxsYWJsZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgUm93V2l0aElkLCBiYXRjaFVwZGF0ZSB9IGZyb20gXCIuL19iYXRjaF91cGRhdGVcIjtcblxudHlwZSBUYWJsZURhdGEgPSB7XG4gIHJlZmVyZW5jZXM6IFNldDxzdHJpbmc+O1xuICByb3dzOiBhbnlbXTtcbiAgdW5pcXVlSW5kZXhlczogeyBuYW1lPzogc3RyaW5nOyBjb2x1bW5zOiBzdHJpbmdbXSB9W107XG4gIHVuaXF1ZXNNYXA6IE1hcDxzdHJpbmcsIHN0cmluZz47XG59O1xuZXhwb3J0IHR5cGUgVUJSZWYgPSB7XG4gIHV1aWQ6IHN0cmluZztcbiAgb2Y6IHN0cmluZztcbiAgdXNlPzogc3RyaW5nO1xufTtcbmV4cG9ydCBmdW5jdGlvbiBpc1JlZkZpZWxkKGZpZWxkOiBhbnkpOiBmaWVsZCBpcyBVQlJlZiB7XG4gIHJldHVybiAoXG4gICAgZmllbGQgIT09IHVuZGVmaW5lZCAmJlxuICAgIGZpZWxkICE9PSBudWxsICYmXG4gICAgZmllbGQub2YgIT09IHVuZGVmaW5lZCAmJlxuICAgIGZpZWxkLnV1aWQgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG5leHBvcnQgY2xhc3MgVXBzZXJ0QnVpbGRlciB7XG4gIHRhYmxlczogTWFwPHN0cmluZywgVGFibGVEYXRhPjtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy50YWJsZXMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBnZXRUYWJsZSh0YWJsZU5hbWU6IHN0cmluZyk6IFRhYmxlRGF0YSB7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlcy5nZXQodGFibGVOYW1lKTtcbiAgICBpZiAodGFibGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgdGFibGVTcGVjID0gKCgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRUYWJsZVNwZWModGFibGVOYW1lKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0pKCk7XG5cbiAgICAgIHRoaXMudGFibGVzLnNldCh0YWJsZU5hbWUsIHtcbiAgICAgICAgcmVmZXJlbmNlczogbmV3IFNldCgpLFxuICAgICAgICByb3dzOiBbXSxcbiAgICAgICAgdW5pcXVlSW5kZXhlczogdGFibGVTcGVjPy51bmlxdWVJbmRleGVzID8/IFtdLFxuICAgICAgICB1bmlxdWVzTWFwOiBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpITtcbiAgfVxuXG4gIGhhc1RhYmxlKHRhYmxlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudGFibGVzLmhhcyh0YWJsZU5hbWUpO1xuICB9XG5cbiAgcmVnaXN0ZXI8VCBleHRlbmRzIHN0cmluZz4oXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgcm93OiB7XG4gICAgICBba2V5IGluIFRdPzpcbiAgICAgICAgfCBVQlJlZlxuICAgICAgICB8IHN0cmluZ1xuICAgICAgICB8IG51bWJlclxuICAgICAgICB8IGJvb2xlYW5cbiAgICAgICAgfCBiaWdpbnRcbiAgICAgICAgfCBudWxsXG4gICAgICAgIHwgb2JqZWN0XG4gICAgICAgIHwgdW5rbm93bjtcbiAgICB9XG4gICk6IFVCUmVmIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuZ2V0VGFibGUodGFibGVOYW1lKTtcblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJTsnZggdW5pcXVlIOyduOuNseyKpOulvCDsiJztmoztlZjrqbAg7YKkIOyDneyEsVxuICAgIGNvbnN0IHVuaXF1ZUtleXMgPSB0YWJsZS51bmlxdWVJbmRleGVzXG4gICAgICAubWFwKCh1bnFJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1bmlxdWVLZXlBcnJheSA9IHVucUluZGV4LmNvbHVtbnMubWFwKCh1bnFDb2wpID0+IHtcbiAgICAgICAgICBjb25zdCB2YWwgPSByb3dbdW5xQ29sIGFzIGtleW9mIHR5cGVvZiByb3ddO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwudXVpZDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJvd1t1bnFDb2wgYXMga2V5b2YgdHlwZW9mIHJvd10gPz8gcmFuZG9tVVVJRCgpOyAvLyBudWxsYWJsZeyduCDqsr3smrAgdXVpZOuhnCDrnpzrjaTqsJIg7IK97J6FXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDqsJLsnbQg66qo65GQIG51bGzsnbgg6rK97JqwIO2CpCDsg53shLEg7Yyo7IqkXG4gICAgICAgIGlmICh1bmlxdWVLZXlBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5pcXVlS2V5QXJyYXkuam9pbihcIi0tLWRlbGltaXRlci0tXCIpO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIobm9uTnVsbGFibGUpO1xuXG4gICAgLy8gdXVpZCDsg53shLEg66Gc7KeBXG4gICAgY29uc3QgdXVpZDogc3RyaW5nID0gKCgpID0+IHtcbiAgICAgIC8vIO2CpOulvCDsiJztmoztlZjsl6wg7J2066+4IOyhtOyerO2VmOuKlCDtgqTqsIAg7J6I64qU7KeAIO2ZleyduFxuICAgICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgICAgaWYgKHRhYmxlLnVuaXF1ZXNNYXAuaGFzKHVuaXF1ZUtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0YWJsZS51bmlxdWVzTWFwLmdldCh1bmlxdWVLZXkpITsgLy8g7J2066+4IGhhcyDssrTtgazrpbwg7ZaI7Jy866+A66GcIHVuZGVmaW5lZCDrtojqsIDriqVcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8g7LC+7J2EIOyImCDsl4bripQg6rK97JqwIOyDneyEsVxuICAgICAgcmV0dXJuIHJhbmRvbVVVSUQoKTtcbiAgICB9KSgpO1xuXG4gICAgLy8g66qo65OgIOycoOuLiO2BrO2CpOyXkCDrjIDtlbQg7Jyg64uI7YGs66e17JeQIHV1aWQg7KCA7J6lXG4gICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgZm9yIChjb25zdCB1bmlxdWVLZXkgb2YgdW5pcXVlS2V5cykge1xuICAgICAgICB0YWJsZS51bmlxdWVzTWFwLnNldCh1bmlxdWVLZXksIHV1aWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOydtCDthYzsnbTruJTsl5Ag7IKs7Jqp65CcIFJlZkZpZWxk66W8IOyInO2ajO2VmOyXrCwg7ZiE7J6sIO2FjOydtOu4lCDsoJXrs7Tsl5Ag7Ja065akIO2VhOuTnOulvCDssLjsobDtlZjripTsp4Ag7LaU6rCAXG4gICAgLy8g7J20IOygleuztOulvCDrgpjspJHsl5Ag7LmY7ZmY7ZWgIOuVjCDsgqzsmqlcbiAgICByb3cgPSBPYmplY3Qua2V5cyhyb3cpLnJlZHVjZSgociwgcm93S2V5KSA9PiB7XG4gICAgICBjb25zdCByb3dWYWx1ZSA9IHJvd1tyb3dLZXkgYXMga2V5b2YgdHlwZW9mIHJvd107XG5cbiAgICAgIGlmIChpc1JlZkZpZWxkKHJvd1ZhbHVlKSkge1xuICAgICAgICByb3dWYWx1ZS51c2UgPz89IFwiaWRcIjtcbiAgICAgICAgdGFibGUucmVmZXJlbmNlcy5hZGQocm93VmFsdWUub2YgKyBcIi5cIiArIHJvd1ZhbHVlLnVzZSk7XG4gICAgICAgIHJbcm93S2V5XSA9IHJvd1ZhbHVlO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygcm93VmFsdWUgPT09IFwib2JqZWN0XCIgJiYgIShyb3dWYWx1ZSBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgIC8vIG9iamVjdOyduCDqsr3smrAgSlNPTuycvOuhnCDrs4DtmZhcbiAgICAgICAgcltyb3dLZXldID0gcm93VmFsdWUgPT09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkocm93VmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcltyb3dLZXldID0gcm93VmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcjtcbiAgICB9LCB7fSBhcyBhbnkpO1xuXG4gICAgdGFibGUucm93cy5wdXNoKHtcbiAgICAgIHV1aWQsXG4gICAgICAuLi5yb3csXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgb2Y6IHRhYmxlTmFtZSxcbiAgICAgIHV1aWQ6IChyb3cgYXMgeyB1dWlkPzogc3RyaW5nIH0pLnV1aWQgPz8gdXVpZCxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgdXBzZXJ0KFxuICAgIHdkYjogS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBjaHVua1NpemU/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcInVwc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG4gIGFzeW5jIGluc2VydE9ubHkoXG4gICAgd2RiOiBLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIGNodW5rU2l6ZT86IG51bWJlclxuICApOiBQcm9taXNlPG51bWJlcltdPiB7XG4gICAgcmV0dXJuIHRoaXMudXBzZXJ0T3JJbnNlcnQod2RiLCB0YWJsZU5hbWUsIFwiaW5zZXJ0XCIsIGNodW5rU2l6ZSk7XG4gIH1cblxuICBhc3luYyB1cHNlcnRPckluc2VydChcbiAgICB3ZGI6IEtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgbW9kZTogXCJ1cHNlcnRcIiB8IFwiaW5zZXJ0XCIsXG4gICAgY2h1bmtTaXplPzogbnVtYmVyXG4gICk6IFByb21pc2U8bnVtYmVyW10+IHtcbiAgICBpZiAodGhpcy5oYXNUYWJsZSh0YWJsZU5hbWUpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZXMuZ2V0KHRhYmxlTmFtZSk7XG4gICAgaWYgKHRhYmxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihg7KG07J6s7ZWY7KeAIOyViuuKlCDthYzsnbTruJQgJHt0YWJsZU5hbWV97JeQIHVwc2VydCDsmpTssq1gKTtcbiAgICB9IGVsc2UgaWYgKHRhYmxlLnJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGFibGVOYW1lfeyXkCB1cHNlcnQg7ZWgIOuNsOydtO2EsOqwgCDsl4bsirXri4jri6QuYCk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGFibGUucm93cy5zb21lKChyb3cpID0+XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKHJvdykuc29tZShcbiAgICAgICAgICAoWywgdmFsdWVdKSA9PiBpc1JlZkZpZWxkKHZhbHVlKSAmJiB2YWx1ZS5vZiAhPT0gdGFibGVOYW1lXG4gICAgICAgIClcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV9IO2VtOqysOuQmOyngCDslYrsnYAg7LC47KGw6rCAIOyeiOyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICAvLyDsoITssrQg7YWM7J2067iUIOyInO2ajO2VmOyXrCDtmITsnqwg7YWM7J2067iUIOywuOyhsO2VmOuKlCDrqqjrk6Ag7YWM7J2067iUIOy2lOy2nFxuICAgIGNvbnN0IHsgcmVmZXJlbmNlcywgcmVmVGFibGVzIH0gPSBBcnJheS5mcm9tKHRoaXMudGFibGVzKS5yZWR1Y2UoXG4gICAgICAociwgWywgdGFibGVdKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlZmVyZW5jZSA9IEFycmF5LmZyb20odGFibGUucmVmZXJlbmNlcy52YWx1ZXMoKSkuZmluZCgocmVmKSA9PlxuICAgICAgICAgIHJlZi5pbmNsdWRlcyh0YWJsZU5hbWUgKyBcIi5cIilcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHJlZmVyZW5jZSkge1xuICAgICAgICAgIHIucmVmZXJlbmNlcy5wdXNoKHJlZmVyZW5jZSk7XG4gICAgICAgICAgci5yZWZUYWJsZXMucHVzaCh0YWJsZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHJlZmVyZW5jZXM6IFtdIGFzIHN0cmluZ1tdLFxuICAgICAgICByZWZUYWJsZXM6IFtdIGFzIFRhYmxlRGF0YVtdLFxuICAgICAgfVxuICAgICk7XG4gICAgY29uc3QgZXh0cmFjdEZpZWxkcyA9IF8udW5pcShyZWZlcmVuY2VzKS5tYXAoXG4gICAgICAocmVmZXJlbmNlKSA9PiByZWZlcmVuY2Uuc3BsaXQoXCIuXCIpWzFdXG4gICAgKTtcblxuICAgIC8vIOuCtOu2gCDssLjsobAg7J6I64qUIOqyveyasCDtlYTthLDtlZjsl6wg67aE66asXG4gICAgY29uc3QgZ3JvdXBzID0gXy5ncm91cEJ5KHRhYmxlLnJvd3MsIChyb3cpID0+XG4gICAgICBPYmplY3QuZW50cmllcyhyb3cpLnNvbWUoKFssIHZhbHVlXSkgPT4gaXNSZWZGaWVsZCh2YWx1ZSkpXG4gICAgICAgID8gXCJzZWxmUmVmXCJcbiAgICAgICAgOiBcIm5vcm1hbFwiXG4gICAgKTtcbiAgICBjb25zdCBub3JtYWxSb3dzID0gZ3JvdXBzLm5vcm1hbCA/PyBbXTtcbiAgICBjb25zdCBzZWxmUmVmUm93cyA9IGdyb3Vwcy5zZWxmUmVmID8/IFtdO1xuXG4gICAgY29uc3QgY2h1bmtzID0gY2h1bmtTaXplID8gXy5jaHVuayhub3JtYWxSb3dzLCBjaHVua1NpemUpIDogW25vcm1hbFJvd3NdO1xuICAgIGNvbnN0IHV1aWRNYXAgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuXG4gICAgZm9yIChjb25zdCBjaHVuayBvZiBjaHVua3MpIHtcbiAgICAgIGNvbnN0IHEgPSB3ZGIuaW5zZXJ0KGNodW5rKS5pbnRvKHRhYmxlTmFtZSk7XG4gICAgICBpZiAobW9kZSA9PT0gXCJpbnNlcnRcIikge1xuICAgICAgICBhd2FpdCBxO1xuICAgICAgfSBlbHNlIGlmIChtb2RlID09PSBcInVwc2VydFwiKSB7XG4gICAgICAgIGF3YWl0IHEub25EdXBsaWNhdGVVcGRhdGUuYXBwbHkocSwgT2JqZWN0LmtleXMobm9ybWFsUm93c1swXSkpO1xuICAgICAgfVxuXG4gICAgICAvLyB1cHNlcnTrkJwgcm9365Ok7J2EIOuLpOyLnCDsobDtmoztlZjsl6wgdXVpZE1hcOyXkCDsoIDsnqVcbiAgICAgIGNvbnN0IHV1aWRzID0gY2h1bmsubWFwKChyb3cpID0+IHJvdy51dWlkKTtcbiAgICAgIGNvbnN0IHVwc2VydGVkUm93cyA9IGF3YWl0IHdkYih0YWJsZU5hbWUpXG4gICAgICAgIC5zZWxlY3QoXy51bmlxKFtcInV1aWRcIiwgXCJpZFwiLCAuLi5leHRyYWN0RmllbGRzXSkpXG4gICAgICAgIC53aGVyZUluKFwidXVpZFwiLCB1dWlkcyk7XG4gICAgICB1cHNlcnRlZFJvd3MuZm9yRWFjaCgocm93OiBhbnkpID0+IHtcbiAgICAgICAgdXVpZE1hcC5zZXQocm93LnV1aWQsIHJvdyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyDtlbTri7kg7YWM7J2067iUIOywuOyhsOulvCDsi6TsoJwg67C466WY66GcIOuzgOqyvVxuICAgIHJlZlRhYmxlcy5tYXAoKHRhYmxlKSA9PiB7XG4gICAgICB0YWJsZS5yb3dzID0gdGFibGUucm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICBPYmplY3Qua2V5cyhyb3cpLm1hcCgoa2V5KSA9PiB7XG4gICAgICAgICAgY29uc3QgcHJvcCA9IHJvd1trZXldO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHByb3ApICYmIHByb3Aub2YgPT09IHRhYmxlTmFtZSkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gdXVpZE1hcC5nZXQocHJvcC51dWlkKTtcbiAgICAgICAgICAgIGlmIChwYXJlbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKHByb3ApO1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgYOyhtOyerO2VmOyngCDslYrripQgdXVpZCAke3Byb3AudXVpZH0gLS0gaW4gJHt0YWJsZU5hbWV9YFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcm93W2tleV0gPSBwYXJlbnRbcHJvcC51c2UgPz8gXCJpZFwiXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcm93O1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBhbGxJZHMgPSBBcnJheS5mcm9tKHV1aWRNYXAudmFsdWVzKCkpLm1hcCgocm93KSA9PiByb3cuaWQpO1xuXG4gICAgLy8g7J6Q6riwIOywuOyhsOqwgCDsnojripQg6rK97JqwIOyerOq3gOyggeycvOuhnCB1cHNlcnRcbiAgICBpZiAoc2VsZlJlZlJvd3MubGVuZ3RoID4gMCkge1xuICAgICAgLy8g7LKY66as65CcIOuNsOydtO2EsOulvCDsoJzsmbjtlZjqs6Ag64uk7IucIHVwc2VydFxuICAgICAgdGFibGUucm93cyA9IHNlbGZSZWZSb3dzO1xuICAgICAgY29uc3Qgc2VsZlJlZklkcyA9IGF3YWl0IHRoaXMudXBzZXJ0KHdkYiwgdGFibGVOYW1lLCBjaHVua1NpemUpO1xuICAgICAgYWxsSWRzLnB1c2goLi4uc2VsZlJlZklkcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIOyekOq4sCDssLjsobDqsIAg7JeG7Jy866m0IO2VtOuLuSDthYzsnbTruJTsnZgg642w7J207YSwIOy0iOq4sO2ZlFxuICAgICAgdGFibGUucm93cyA9IFtdO1xuICAgICAgdGFibGUucmVmZXJlbmNlcy5jbGVhcigpO1xuICAgICAgdGFibGUudW5pcXVlc01hcC5jbGVhcigpO1xuICAgIH1cblxuICAgIHJldHVybiBhbGxJZHM7XG4gIH1cblxuICBhc3luYyB1cGRhdGVCYXRjaChcbiAgICB3ZGI6IEtuZXgsXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGNodW5rU2l6ZT86IG51bWJlcjtcbiAgICAgIHdoZXJlPzogc3RyaW5nIHwgc3RyaW5nW107XG4gICAgfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBvcHRpb25zID0gXy5kZWZhdWx0cyhvcHRpb25zLCB7XG4gICAgICBjaHVua1NpemU6IDUwMCxcbiAgICAgIHdoZXJlOiBcImlkXCIsXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5oYXNUYWJsZSh0YWJsZU5hbWUpID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpITtcbiAgICBpZiAodGFibGUucm93cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB3aGVyZUNvbHVtbnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMud2hlcmUpXG4gICAgICA/IG9wdGlvbnMud2hlcmVcbiAgICAgIDogW29wdGlvbnMud2hlcmUgPz8gXCJpZFwiXTtcbiAgICBjb25zdCByb3dzID0gdGFibGUucm93cy5tYXAoKF9yb3cpID0+IHtcbiAgICAgIGNvbnN0IHsgdXVpZCwgLi4ucm93IH0gPSBfcm93O1xuICAgICAgcmV0dXJuIHJvdyBhcyBSb3dXaXRoSWQ8c3RyaW5nPjtcbiAgICB9KTtcblxuICAgIGF3YWl0IGJhdGNoVXBkYXRlKHdkYiwgdGFibGVOYW1lLCB3aGVyZUNvbHVtbnMsIHJvd3MsIG9wdGlvbnMuY2h1bmtTaXplKTtcblxuICAgIC8vIHVwZGF0ZUJhdGNoIOyZhOujjCDtm4Qg7LKY66as65CcIOuNsOydtO2EsCDsoJzqsbBcbiAgICB0YWJsZS5yb3dzID0gW107XG4gICAgdGFibGUucmVmZXJlbmNlcy5jbGVhcigpO1xuICAgIHRhYmxlLnVuaXF1ZXNNYXAuY2xlYXIoKTtcbiAgfVxufVxuIl0sIm5hbWVzIjpbInJhbmRvbVVVSUQiLCJfIiwiRW50aXR5TWFuYWdlciIsIm5vbk51bGxhYmxlIiwiYmF0Y2hVcGRhdGUiLCJpc1JlZkZpZWxkIiwiZmllbGQiLCJ1bmRlZmluZWQiLCJvZiIsInV1aWQiLCJVcHNlcnRCdWlsZGVyIiwidGFibGVzIiwiTWFwIiwiZ2V0VGFibGUiLCJ0YWJsZU5hbWUiLCJ0YWJsZSIsImdldCIsInRhYmxlU3BlYyIsImdldFRhYmxlU3BlYyIsInNldCIsInJlZmVyZW5jZXMiLCJTZXQiLCJyb3dzIiwidW5pcXVlSW5kZXhlcyIsInVuaXF1ZXNNYXAiLCJoYXNUYWJsZSIsImhhcyIsInJlZ2lzdGVyIiwicm93IiwidW5pcXVlS2V5cyIsIm1hcCIsInVucUluZGV4IiwidW5pcXVlS2V5QXJyYXkiLCJjb2x1bW5zIiwidW5xQ29sIiwidmFsIiwibGVuZ3RoIiwiam9pbiIsImZpbHRlciIsInVuaXF1ZUtleSIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJyIiwicm93S2V5Iiwicm93VmFsdWUiLCJ1c2UiLCJhZGQiLCJEYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsInB1c2giLCJ1cHNlcnQiLCJ3ZGIiLCJjaHVua1NpemUiLCJ1cHNlcnRPckluc2VydCIsImluc2VydE9ubHkiLCJtb2RlIiwiRXJyb3IiLCJzb21lIiwiZW50cmllcyIsInZhbHVlIiwicmVmVGFibGVzIiwiQXJyYXkiLCJmcm9tIiwicmVmZXJlbmNlIiwidmFsdWVzIiwiZmluZCIsInJlZiIsImluY2x1ZGVzIiwiZXh0cmFjdEZpZWxkcyIsInVuaXEiLCJzcGxpdCIsImdyb3VwcyIsImdyb3VwQnkiLCJub3JtYWxSb3dzIiwibm9ybWFsIiwic2VsZlJlZlJvd3MiLCJzZWxmUmVmIiwiY2h1bmtzIiwiY2h1bmsiLCJ1dWlkTWFwIiwicSIsImluc2VydCIsImludG8iLCJvbkR1cGxpY2F0ZVVwZGF0ZSIsImFwcGx5IiwidXVpZHMiLCJ1cHNlcnRlZFJvd3MiLCJzZWxlY3QiLCJ3aGVyZUluIiwiZm9yRWFjaCIsImtleSIsInByb3AiLCJwYXJlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhbGxJZHMiLCJpZCIsInNlbGZSZWZJZHMiLCJjbGVhciIsInVwZGF0ZUJhdGNoIiwib3B0aW9ucyIsImRlZmF1bHRzIiwid2hlcmUiLCJ3aGVyZUNvbHVtbnMiLCJpc0FycmF5IiwiX3JvdyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsVUFBVSxRQUFRLFNBQVM7QUFDcEMsWUFBWUMsT0FBTyxZQUFZO0FBRS9CLFNBQVNDLGFBQWEsUUFBUSw4QkFBMkI7QUFDekQsU0FBU0MsV0FBVyxRQUFRLG9CQUFpQjtBQUM3QyxTQUFvQkMsV0FBVyxRQUFRLHFCQUFrQjtBQWF6RCxPQUFPLFNBQVNDLFdBQVdDLEtBQVU7SUFDbkMsT0FDRUEsVUFBVUMsYUFDVkQsVUFBVSxRQUNWQSxNQUFNRSxFQUFFLEtBQUtELGFBQ2JELE1BQU1HLElBQUksS0FBS0Y7QUFFbkI7QUFFQSxPQUFPLE1BQU1HO0lBQ1hDLE9BQStCO0lBQy9CLGFBQWM7UUFDWixJQUFJLENBQUNBLE1BQU0sR0FBRyxJQUFJQztJQUNwQjtJQUVBQyxTQUFTQyxTQUFpQixFQUFhO1FBQ3JDLE1BQU1DLFFBQVEsSUFBSSxDQUFDSixNQUFNLENBQUNLLEdBQUcsQ0FBQ0Y7UUFDOUIsSUFBSUMsVUFBVVIsV0FB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
|
|
364
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS91cHNlcnQtYnVpbGRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IHR5cGUgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB7IGFzc2VydERlZmluZWQsIGNodW5rLCBub25OdWxsYWJsZSB9IGZyb20gXCIuLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgYmF0Y2hVcGRhdGUsIHR5cGUgUm93V2l0aElkIH0gZnJvbSBcIi4vX2JhdGNoX3VwZGF0ZVwiO1xuXG50eXBlIFRhYmxlRGF0YSA9IHtcbiAgcmVmZXJlbmNlczogU2V0PHN0cmluZz47XG4gIHJvd3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gIHVuaXF1ZUluZGV4ZXM6IHsgbmFtZT86IHN0cmluZzsgY29sdW1uczogc3RyaW5nW10gfVtdO1xuICB1bmlxdWVzTWFwOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xufTtcbmV4cG9ydCB0eXBlIFVCUmVmID0ge1xuICB1dWlkOiBzdHJpbmc7XG4gIG9mOiBzdHJpbmc7XG4gIHVzZT86IHN0cmluZztcbn07XG5leHBvcnQgZnVuY3Rpb24gaXNSZWZGaWVsZChmaWVsZDogdW5rbm93bik6IGZpZWxkIGlzIFVCUmVmIHtcbiAgcmV0dXJuIChcbiAgICBmaWVsZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgZmllbGQgIT09IG51bGwgJiZcbiAgICAoZmllbGQgYXMgVUJSZWYpPy5vZiAhPT0gdW5kZWZpbmVkICYmXG4gICAgKGZpZWxkIGFzIFVCUmVmKT8udXVpZCAhPT0gdW5kZWZpbmVkXG4gICk7XG59XG5cbmV4cG9ydCBjbGFzcyBVcHNlcnRCdWlsZGVyIHtcbiAgdGFibGVzOiBNYXA8c3RyaW5nLCBUYWJsZURhdGE+O1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnRhYmxlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIGdldFRhYmxlKHRhYmxlTmFtZTogc3RyaW5nKTogVGFibGVEYXRhIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMudGFibGVzLmdldCh0YWJsZU5hbWUpO1xuICAgIGlmICh0YWJsZSkge1xuICAgICAgcmV0dXJuIHRhYmxlO1xuICAgIH1cblxuICAgIGNvbnN0IHRhYmxlU3BlYyA9ICgoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gRW50aXR5TWFuYWdlci5nZXRUYWJsZVNwZWModGFibGVOYW1lKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgY29uc3QgdGFibGVEYXRhID0ge1xuICAgICAgcmVmZXJlbmNlczogbmV3IFNldDxzdHJpbmc+KCksXG4gICAgICByb3dzOiBbXSxcbiAgICAgIHVuaXF1ZUluZGV4ZXM6IHRhYmxlU3BlYz8udW5pcXVlSW5kZXhlcyA/PyBbXSxcbiAgICAgIHVuaXF1ZXNNYXA6IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCksXG4gICAgfTtcbiAgICB0aGlzLnRhYmxlcy5zZXQodGFibGVOYW1lLCB0YWJsZURhdGEpO1xuICAgIHJldHVybiB0YWJsZURhdGE7XG4gIH1cblxuICBoYXNUYWJsZSh0YWJsZU5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRhYmxlcy5oYXModGFibGVOYW1lKTtcbiAgfVxuXG4gIHJlZ2lzdGVyPFQgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHJvdzoge1xuICAgICAgW2tleSBpbiBUXT86IFVCUmVmIHwgc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IGJpZ2ludCB8IG51bGwgfCBvYmplY3QgfCB1bmtub3duO1xuICAgIH0sXG4gICk6IFVCUmVmIHtcbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuZ2V0VGFibGUodGFibGVOYW1lKTtcblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJTsnZggdW5pcXVlIOyduOuNseyKpOulvCDsiJztmoztlZjrqbAg7YKkIOyDneyEsVxuICAgIGNvbnN0IHVuaXF1ZUtleXMgPSB0YWJsZS51bmlxdWVJbmRleGVzXG4gICAgICAubWFwKCh1bnFJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1bmlxdWVLZXlBcnJheSA9IHVucUluZGV4LmNvbHVtbnMubWFwKCh1bnFDb2wpID0+IHtcbiAgICAgICAgICBjb25zdCB2YWwgPSByb3dbdW5xQ29sIGFzIGtleW9mIHR5cGVvZiByb3ddO1xuICAgICAgICAgIGlmIChpc1JlZkZpZWxkKHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwudXVpZDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJvd1t1bnFDb2wgYXMga2V5b2YgdHlwZW9mIHJvd10gPz8gcmFuZG9tVVVJRCgpOyAvLyBudWxsYWJsZeyduCDqsr3smrAgdXVpZOuhnCDrnpzrjaTqsJIg7IK97J6FXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDqsJLsnbQg66qo65GQIG51bGzsnbgg6rK97JqwIO2CpCDsg53shLEg7Yyo7IqkXG4gICAgICAgIGlmICh1bmlxdWVLZXlBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5pcXVlS2V5QXJyYXkuam9pbihcIi0tLWRlbGltaXRlci0tXCIpO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIobm9uTnVsbGFibGUpO1xuXG4gICAgLy8gdXVpZCDsg53shLEg66Gc7KeBXG4gICAgY29uc3QgeyB1dWlkLCBpc1JldXNlZCB9ID0gKCgpID0+IHtcbiAgICAgIC8vIO2CpOulvCDsiJztmoztlZjsl6wg7J2066+4IOyhtOyerO2VmOuKlCDtgqTqsIAg7J6I64qU7KeAIO2ZleyduFxuICAgICAgaWYgKHVuaXF1ZUtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgICAgaWYgKHRhYmxlLnVuaXF1ZXNNYXAuaGFzKHVuaXF1ZUtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHV1aWQ6IGFzc2VydERlZmluZWQodGFibGUudW5pcXVlc01hcC5nZXQodW5pcXVlS2V5KSwgXCJVbmlxdWUga2V5IG5vdCBmb3VuZFwiKSxcbiAgICAgICAgICAgICAgaXNSZXVzZWQ6IHRydWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDssL7snYQg7IiYIOyXhuuKlCDqsr3smrAg7IOd7ISxXG4gICAgICByZXR1cm4geyB1dWlkOiByYW5kb21VVUlEKCksIGlzUmV1c2VkOiBmYWxzZSB9O1xuICAgIH0pKCk7XG5cbiAgICAvLyDrqqjrk6Ag7Jyg64uI7YGs7YKk7JeQIOuMgO2VtCDsnKDri4jtgazrp7Xsl5AgdXVpZCDsoIDsnqVcbiAgICBpZiAodW5pcXVlS2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IHVuaXF1ZUtleSBvZiB1bmlxdWVLZXlzKSB7XG4gICAgICAgIHRhYmxlLnVuaXF1ZXNNYXAuc2V0KHVuaXF1ZUtleSwgdXVpZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g7J20IO2FjOydtOu4lOyXkCDsgqzsmqnrkJwgUmVmRmllbGTrpbwg7Iic7ZqM7ZWY7JesLCDtmITsnqwg7YWM7J2067iUIOygleuztOyXkCDslrTrlqQg7ZWE65Oc66W8IOywuOyhsO2VmOuKlOyngCDstpTqsIBcbiAgICAvLyDsnbQg7KCV67O066W8IOuCmOykkeyXkCDsuZjtmZjtlaAg65WMIOyCrOyaqVxuICAgIHJvdyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKHJvdykubWFwKChbcm93S2V5LCByb3dWYWx1ZV0pID0+IHtcbiAgICAgICAgaWYgKGlzUmVmRmllbGQocm93VmFsdWUpKSB7XG4gICAgICAgICAgcm93VmFsdWUudXNlID8/PSBcImlkXCI7XG4gICAgICAgICAgdGFibGUucmVmZXJlbmNlcy5hZGQoYCR7cm93VmFsdWUub2Z9LiR7cm93VmFsdWUudXNlfWApO1xuICAgICAgICAgIHJldHVybiBbcm93S2V5LCByb3dWYWx1ZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJvd1ZhbHVlID09PSBcIm9iamVjdFwiICYmICEocm93VmFsdWUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgIC8vIG9iamVjdOyduCDqsr3smrAgSlNPTuycvOuhnCDrs4DtmZhcbiAgICAgICAgICByZXR1cm4gW3Jvd0tleSwgcm93VmFsdWUgPT09IG51bGwgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkocm93VmFsdWUpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gW3Jvd0tleSwgcm93VmFsdWVdO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApIGFzIHsgW2tleSBpbiBUXT86IHVua25vd24gfTtcblxuICAgIHRhYmxlLnJvd3MucHVzaCh7XG4gICAgICB1dWlkLFxuICAgICAgLi4ucm93LFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0OiBVQlJlZiA9IHtcbiAgICAgIG9mOiB0YWJsZU5hbWUsXG4gICAgICB1dWlkOiAocm93IGFzIHsgdXVpZD86IHN0cmluZyB9KS51dWlkID8/IHV1aWQsXG4gICAgfTtcblxuICAgIE5haXRlLnQoXCJwdXJpOnViLXJlZ2lzdGVyXCIsIHtcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIHV1aWQ6IHJlc3VsdC51dWlkLFxuICAgICAgaXNVdWlkUmV1c2VkOiBpc1JldXNlZCxcbiAgICAgIHJvdyxcbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhc3luYyB1cHNlcnQod2RiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZywgY2h1bmtTaXplPzogbnVtYmVyKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcInVwc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG4gIGFzeW5jIGluc2VydE9ubHkod2RiOiBLbmV4LCB0YWJsZU5hbWU6IHN0cmluZywgY2h1bmtTaXplPzogbnVtYmVyKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIHJldHVybiB0aGlzLnVwc2VydE9ySW5zZXJ0KHdkYiwgdGFibGVOYW1lLCBcImluc2VydFwiLCBjaHVua1NpemUpO1xuICB9XG5cbiAgYXN5bmMgdXBzZXJ0T3JJbnNlcnQoXG4gICAgd2RiOiBLbmV4LFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIG1vZGU6IFwidXBzZXJ0XCIgfCBcImluc2VydFwiLFxuICAgIGNodW5rU2l6ZT86IG51bWJlcixcbiAgKTogUHJvbWlzZTxudW1iZXJbXT4ge1xuICAgIGlmICh0aGlzLmhhc1RhYmxlKHRhYmxlTmFtZSkgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlcy5nZXQodGFibGVOYW1lKTtcbiAgICBpZiAodGFibGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIO2FjOydtOu4lCAke3RhYmxlTmFtZX3sl5AgdXBzZXJ0IOyalOyyrWApO1xuICAgIH0gZWxzZSBpZiAodGFibGUucm93cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV97JeQIHVwc2VydCDtlaAg642w7J207YSw6rCAIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICB0YWJsZS5yb3dzLnNvbWUoKHJvdykgPT5cbiAgICAgICAgT2JqZWN0LmVudHJpZXMocm93KS5zb21lKChbLCB2YWx1ZV0pID0+IGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mICE9PSB0YWJsZU5hbWUpLFxuICAgICAgKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RhYmxlTmFtZX0g7ZW06rKw65CY7KeAIOyViuydgCDssLjsobDqsIAg7J6I7Iq164uI64ukLmApO1xuICAgIH1cblxuICAgIC8vIOyghOyytCDthYzsnbTruJQg7Iic7ZqM7ZWY7JesIO2YhOyerCDthYzsnbTruJQg7LC47KGw7ZWY64qUIOuqqOuToCDthYzsnbTruJQg7LaU7LacXG4gICAgY29uc3QgeyByZWZlcmVuY2VzLCByZWZUYWJsZXMgfSA9IEFycmF5LmZyb20odGhpcy50YWJsZXMpLnJlZHVjZShcbiAgICAgIChyLCBbLCB0YWJsZV0pID0+IHtcbiAgICAgICAgY29uc3QgcmVmZXJlbmNlID0gQXJyYXkuZnJvbSh0YWJsZS5yZWZlcmVuY2VzLnZhbHVlcygpKS5maW5kKChyZWYpID0+XG4gICAgICAgICAgcmVmLmluY2x1ZGVzKGAke3RhYmxlTmFtZX0uYCksXG4gICAgICAgICk7XG4gICAgICAgIGlmIChyZWZlcmVuY2UpIHtcbiAgICAgICAgICByLnJlZmVyZW5jZXMucHVzaChyZWZlcmVuY2UpO1xuICAgICAgICAgIHIucmVmVGFibGVzLnB1c2godGFibGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LFxuICAgICAge1xuICAgICAgICByZWZlcmVuY2VzOiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgICAgcmVmVGFibGVzOiBbXSBhcyBUYWJsZURhdGFbXSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICBjb25zdCBleHRyYWN0RmllbGRzID0gdW5pcXVlKHJlZmVyZW5jZXMpXG4gICAgICAubWFwKChyZWZlcmVuY2UpID0+IHJlZmVyZW5jZS5zcGxpdChcIi5cIilbMV0pXG4gICAgICAuZmlsdGVyKChmaWVsZCk6IGZpZWxkIGlzIHN0cmluZyA9PiBmaWVsZCAhPT0gdW5kZWZpbmVkKTtcblxuICAgIC8vIOydmOyhtOyEsSDsiJzshJzsl5Ag65Sw6528IOugiOuyqOuzhCDqt7jro7ntmZQgKOyekOq4sCDssLjsobDqsIAg7JeG7Jy866m0IExldmVsIDAg7ZWY64KYKVxuICAgIGNvbnN0IHsgbGV2ZWxzLCBoYXNDaXJjdWxhciB9ID0gdGhpcy5idWlsZEluc2VydExldmVscyh0YWJsZS5yb3dzLCB0YWJsZU5hbWUpO1xuXG4gICAgaWYgKGhhc0NpcmN1bGFyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGFibGVOYW1lfeyXkCDsiJztmZgg7J6Q6riwIOywuOyhsOqwgCDsnojsirXri4jri6QuYCk7XG4gICAgfVxuXG4gICAgLy8gdXBzZXJ0IOuqqOuTnOydvCDrlYwg7Jyg64uI7YGsIOyduOuNseyKpOqwgCDsl4bsnLzrqbQg7JeQ65+sXG4gICAgaWYgKG1vZGUgPT09IFwidXBzZXJ0XCIgJiYgdGFibGUudW5pcXVlSW5kZXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0YWJsZU5hbWV97JeQIHVuaXF1ZSBpbmRleOqwgCDsoJXsnZjrkJjsp4Ag7JWK7JWEIHVwc2VydOulvCDtlaAg7IiYIOyXhuyKteuLiOuLpC5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1dWlkTWFwID0gbmV3IE1hcDxzdHJpbmcsIHVua25vd24+KCk7XG4gICAgY29uc3QgYWxsSWRzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgLy8g66CI67Ko67OE66GcIOyInOywqCDsspjrpqxcbiAgICBmb3IgKGNvbnN0IGxldmVsUm93cyBvZiBsZXZlbHMpIHtcbiAgICAgIC8vIOydtOyghCDroIjrsqjsl5DshJwg7Ja77J2AIElE66GcIOyekOq4sCDssLjsobAg7ZW06rKwXG4gICAgICBjb25zdCByZXNvbHZlZFJvd3MgPSBsZXZlbFJvd3MubWFwKChyb3cpID0+IHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSB7IC4uLnJvdyB9O1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyb3cpKSB7XG4gICAgICAgICAgaWYgKGlzUmVmRmllbGQodmFsdWUpICYmIHZhbHVlLm9mID09PSB0YWJsZU5hbWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IHV1aWRNYXAuZ2V0KHZhbHVlLnV1aWQpO1xuXG4gICAgICAgICAgICBpZiAoIXBhcmVudCkgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIHV1aWQgJHt2YWx1ZS51dWlkfSAtLSBpbiAke3RhYmxlTmFtZX1gKTtcblxuICAgICAgICAgICAgcmVzb2x2ZWRba2V5XSA9IChwYXJlbnQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3ZhbHVlLnVzZSA/PyBcImlkXCJdO1xuXG4gICAgICAgICAgICBOYWl0ZS50KFwicHVyaTp1Yi1yZWYtcmVzb2x2ZWRcIiwge1xuICAgICAgICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgICAgICAgIGZpZWxkOiBrZXksXG4gICAgICAgICAgICAgIGZyb206IHsgb2Y6IHZhbHVlLm9mLCB1dWlkOiB2YWx1ZS51dWlkLCB1c2U6IHZhbHVlLnVzZSA/PyBcImlkXCIgfSxcbiAgICAgICAgICAgICAgdG86IHJlc29sdmVkW2tleV0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc29sdmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIO2YhOyerCDroIjrsqggdXBzZXJ0XG4gICAgICBjb25zdCBsZXZlbENodW5rcyA9IGNodW5rU2l6ZSA/IGNodW5rKHJlc29sdmVkUm93cywgY2h1bmtTaXplKSA6IFtyZXNvbHZlZFJvd3NdO1xuICAgICAgY29uc3Qgc2VsZWN0RmllbGRzID0gdW5pcXVlKFtcInV1aWRcIiwgXCJpZFwiLCAuLi5leHRyYWN0RmllbGRzXSk7XG5cbiAgICAgIGZvciAoY29uc3QgZGF0YUNodW5rIG9mIGxldmVsQ2h1bmtzKSB7XG4gICAgICAgIGlmIChkYXRhQ2h1bmsubGVuZ3RoID09PSAwKSBjb250aW51ZTtcblxuICAgICAgICBsZXQgcmVzdWx0Um93czogeyB1dWlkOiBzdHJpbmc7IGlkOiBudW1iZXI7IFtrZXk6IHN0cmluZ106IHVua25vd24gfVtdO1xuXG4gICAgICAgIGlmIChtb2RlID09PSBcImluc2VydFwiKSB7XG4gICAgICAgICAgLy8gSU5TRVJUIOuqqOuTnFxuICAgICAgICAgIGF3YWl0IHdkYi5pbnNlcnQoZGF0YUNodW5rKS5pbnRvKHRhYmxlTmFtZSk7XG5cbiAgICAgICAgICBjb25zdCB1dWlkcyA9IGRhdGFDaHVuay5tYXAoKHIpID0+IHIudXVpZCk7XG4gICAgICAgICAgcmVzdWx0Um93cyA9IGF3YWl0IHdkYih0YWJsZU5hbWUpXG4gICAgICAgICAgICAuc2VsZWN0KHNlbGVjdEZpZWxkcylcbiAgICAgICAgICAgIC53aGVyZUluKFwidXVpZFwiLCB1dWlkcyBhcyByZWFkb25seSBzdHJpbmdbXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVVBTRVJUIOuqqOuTnDogb25Db25mbGljdOuhnCDspJHrs7Ug7LKY66asXG4gICAgICAgICAgY29uc3QgY29uZmxpY3RDb2x1bW5zID0gdGFibGUudW5pcXVlSW5kZXhlc1swXS5jb2x1bW5zO1xuICAgICAgICAgIGNvbnN0IHVwZGF0ZUNvbHVtbnMgPSBPYmplY3Qua2V5cyhkYXRhQ2h1bmtbMF0pLmZpbHRlcihcbiAgICAgICAgICAgIChjb2wpID0+IGNvbCAhPT0gXCJ1dWlkXCIgJiYgIWNvbmZsaWN0Q29sdW1ucy5pbmNsdWRlcyhjb2wpLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBxdWVyeSA9IHdkYi5pbnNlcnQoZGF0YUNodW5rKS5pbnRvKHRhYmxlTmFtZSkub25Db25mbGljdChjb25mbGljdENvbHVtbnMpO1xuXG4gICAgICAgICAgLy8gdXBkYXRlQ29sdW1ucyDsnKDrrLTsl5Ag65Sw6528IGlnbm9yZS9tZXJnZSDshKDtg53tlZjqs6AgUkVUVVJOSU5H7Jy866GcIOqysOqzvCDrsJvquLBcbiAgICAgICAgICBpZiAodXBkYXRlQ29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJlc3VsdFJvd3MgPSBhd2FpdCBxdWVyeS5pZ25vcmUoKS5yZXR1cm5pbmcoc2VsZWN0RmllbGRzKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0Um93cyA9IGF3YWl0IHF1ZXJ5Lm1lcmdlKHVwZGF0ZUNvbHVtbnMpLnJldHVybmluZyhzZWxlY3RGaWVsZHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOyWkeyqvSDrqqjrk5wg6rO17Ya1IOyymOumrFxuICAgICAgICBmb3IgKGNvbnN0IHJvdyBvZiByZXN1bHRSb3dzKSB7XG4gICAgICAgICAgdXVpZE1hcC5zZXQocm93LnV1aWQsIHJvdyk7XG4gICAgICAgICAgYWxsSWRzLnB1c2gocm93LmlkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIO2VtOuLuSDthYzsnbTruJQg7LC47KGw66W8IOyLpOygnCDrsLjrpZjroZwg67OA6rK9XG4gICAgZm9yIChjb25zdCB0YWJsZSBvZiByZWZUYWJsZXMpIHtcbiAgICAgIHRhYmxlLnJvd3MgPSB0YWJsZS5yb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHJvdykpIHtcbiAgICAgICAgICBjb25zdCBwcm9wID0gcm93W2tleV07XG4gICAgICAgICAgaWYgKGlzUmVmRmllbGQocHJvcCkgJiYgcHJvcC5vZiA9PT0gdGFibGVOYW1lKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnQgPSB1dWlkTWFwLmdldChwcm9wLnV1aWQpO1xuICAgICAgICAgICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihwcm9wKTtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGDsobTsnqztlZjsp4Ag7JWK64qUIHV1aWQgJHtwcm9wLnV1aWR9IC0tIGluICR7dGFibGVOYW1lfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRWYWx1ZSA9IChwYXJlbnQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3Byb3AudXNlID8/IFwiaWRcIl07XG4gICAgICAgICAgICByb3dba2V5XSA9IHJlc29sdmVkVmFsdWU7XG5cbiAgICAgICAgICAgIE5haXRlLnQoXCJwdXJpOnViLXJlZi1yZXNvbHZlZFwiLCB7XG4gICAgICAgICAgICAgIHRhYmxlTmFtZSxcbiAgICAgICAgICAgICAgZmllbGQ6IGtleSxcbiAgICAgICAgICAgICAgZnJvbTogeyBvZjogcHJvcC5vZiwgdXVpZDogcHJvcC51dWlkLCB1c2U6IHByb3AudXNlID8/IFwiaWRcIiB9LFxuICAgICAgICAgICAgICB0bzogcmVzb2x2ZWRWYWx1ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm93O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8g7ZW064u5IO2FjOydtOu4lOydmCDrjbDsnbTthLAg7LSI6riw7ZmUXG4gICAgdGFibGUucm93cyA9IFtdO1xuICAgIHRhYmxlLnJlZmVyZW5jZXMuY2xlYXIoKTtcbiAgICB0YWJsZS51bmlxdWVzTWFwLmNsZWFyKCk7XG5cbiAgICBOYWl0ZS50KFwicHVyaTp1Yi11cHNlcnRlZFwiLCB7XG4gICAgICB0YWJsZU5hbWUsXG4gICAgICBtb2RlLFxuICAgICAgcm93Q291bnQ6IGFsbElkcy5sZW5ndGgsXG4gICAgICByZXR1cm5lZElkczogYWxsSWRzLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGFsbElkcztcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZUJhdGNoKFxuICAgIHdkYjogS25leCxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgY2h1bmtTaXplPzogbnVtYmVyO1xuICAgICAgd2hlcmU/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgICB9LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBvcHRpb25zID0ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGNodW5rU2l6ZTogb3B0aW9ucz8uY2h1bmtTaXplID8/IDUwMCxcbiAgICAgIHdoZXJlOiBvcHRpb25zPy53aGVyZSA/PyBcImlkXCIsXG4gICAgfTtcblxuICAgIGlmICh0aGlzLmhhc1RhYmxlKHRhYmxlTmFtZSkgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZXMuZ2V0KHRhYmxlTmFtZSk7XG4gICAgaWYgKCF0YWJsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGDrk7HroZ3rkJjsp4Ag7JWK7J2AIO2FjOydtOu4lCAke3RhYmxlTmFtZX3sl5AgdXBkYXRlQmF0Y2gg7JqU7LKtYCk7XG4gICAgfSBlbHNlIGlmICh0YWJsZS5yb3dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHdoZXJlQ29sdW1ucyA9IEFycmF5LmlzQXJyYXkob3B0aW9ucy53aGVyZSkgPyBvcHRpb25zLndoZXJlIDogW29wdGlvbnMud2hlcmUgPz8gXCJpZFwiXTtcbiAgICBjb25zdCByb3dzID0gdGFibGUucm93cy5tYXAoKF9yb3cpID0+IHtcbiAgICAgIGNvbnN0IHsgdXVpZDogXywgLi4ucm93IH0gPSBfcm93OyAvLyB1dWlkIOygnOyZuFxuICAgICAgcmV0dXJuIHJvdyBhcyBSb3dXaXRoSWQ8c3RyaW5nPjtcbiAgICB9KTtcblxuICAgIGF3YWl0IGJhdGNoVXBkYXRlKHdkYiwgdGFibGVOYW1lLCB3aGVyZUNvbHVtbnMsIHJvd3MsIG9wdGlvbnMuY2h1bmtTaXplKTtcblxuICAgIE5haXRlLnQoXCJwdXJpOnViLWJhdGNoLXVwZGF0ZWRcIiwge1xuICAgICAgdGFibGVOYW1lLFxuICAgICAgcm93Q291bnQ6IHJvd3MubGVuZ3RoLFxuICAgICAgd2hlcmVDb2x1bW5zLFxuICAgIH0pO1xuXG4gICAgLy8gdXBkYXRlQmF0Y2gg7JmE66OMIO2bhCDsspjrpqzrkJwg642w7J207YSwIOygnOqxsFxuICAgIHRhYmxlLnJvd3MgPSBbXTtcbiAgICB0YWJsZS5yZWZlcmVuY2VzLmNsZWFyKCk7XG4gICAgdGFibGUudW5pcXVlc01hcC5jbGVhcigpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBQcml2YXRlIEhlbHBlcnNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiByb3dz66W8IOydmOyhtOyEsSDsiJzshJzsl5Ag65Sw6528IOugiOuyqOuzhOuhnCDqt7jro7ntmZRcbiAgICogLSDsnpDquLAg7LC47KGwIOyXhuuKlCDqsr3smrAgOiDrqqjrk6Agcm93c+qwgCBMZXZlbCAwXG4gICAqIC0g7J6Q6riwIOywuOyhsCDsnojripQg6rK97JqwIDog7J6Q6riwIOywuOyhsCDqtIDqs4Trpbwg7JyE7IOBIOygleugrO2VmOyXrCDroIjrsqjrs4TroZwg6re466O57ZmUXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkSW5zZXJ0TGV2ZWxzKFxuICAgIHJvd3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICk6IHsgbGV2ZWxzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdW107IGhhc0NpcmN1bGFyOiBib29sZWFuIH0ge1xuICAgIC8vIDEuIOyekOq4sCDssLjsobDqsIAg7JeG7Jy866m0IO2VnCDroIjrsqjroZwg7LKY66asXG4gICAgY29uc3QgaGFzU2VsZlJlZiA9IHJvd3NcbiAgICAgIC5mbGF0TWFwKChyb3cpID0+IE9iamVjdC52YWx1ZXMocm93KSlcbiAgICAgIC5zb21lKCh2YWx1ZSkgPT4gaXNSZWZGaWVsZCh2YWx1ZSkgJiYgdmFsdWUub2YgPT09IHRhYmxlTmFtZSk7XG4gICAgaWYgKCFoYXNTZWxmUmVmKSByZXR1cm4geyBsZXZlbHM6IFtyb3dzXSwgaGFzQ2lyY3VsYXI6IGZhbHNlIH07XG5cbiAgICAvLyAyLiB1dWlkIOKGkiByb3cg66ek7ZWRICjspJHrs7UgdXVpZCDrsKnsp4ApXG4gICAgY29uc3Qgcm93QnlVdWlkID0gbmV3IE1hcDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHVua25vd24+PigpO1xuICAgIGZvciAoY29uc3Qgcm93IG9mIHJvd3MpIHtcbiAgICAgIGNvbnN0IHV1aWQgPSByb3cudXVpZCBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoIXV1aWQpIHRocm93IG5ldyBFcnJvcihgYnVpbGRJbnNlcnRMZXZlbHM6IHV1aWTqsIAg7JeG64qUIHJvdyAtLSBpbiAke3RhYmxlTmFtZX1gKTtcbiAgICAgIHJvd0J5VXVpZC5zZXQodXVpZCwgcm93KTtcbiAgICB9XG5cbiAgICBsZXQgcGVuZGluZyA9IEFycmF5LmZyb20ocm93QnlVdWlkLnZhbHVlcygpKTtcbiAgICBjb25zdCBsZXZlbHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W11bXSA9IFtdO1xuICAgIGNvbnN0IGluc2VydGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICAvLyAzLiDroIjrsqjrs4Qg67aE66WYXG4gICAgd2hpbGUgKHBlbmRpbmcubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgY3VycmVudExldmVsOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdID0gW107XG4gICAgICBjb25zdCBuZXh0UGVuZGluZzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXSA9IFtdO1xuXG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiBwZW5kaW5nKSB7XG4gICAgICAgIC8vIOydtCByb3fqsIAg7LC47KGw7ZWY64qUIOyekOq4sCDssLjsobDrk6RcbiAgICAgICAgY29uc3Qgc2VsZlJlZnMgPSBPYmplY3QudmFsdWVzKHJvdykuZmlsdGVyKFxuICAgICAgICAgICh2YWx1ZSkgPT4gaXNSZWZGaWVsZCh2YWx1ZSkgJiYgdmFsdWUub2YgPT09IHRhYmxlTmFtZSxcbiAgICAgICAgKSBhcyBVQlJlZltdO1xuXG4gICAgICAgIC8vIOywuOyhsO2VmOuKlCDrqqjrk6AgdXVpZOqwgCDsnbTrr7ggaW5zZXJ0ZWTsl5Ag7J6I7Ja07JW8IOydtOuyiCDroIjrsqjsl5Ag7Y+s7ZWoXG4gICAgICAgIGNvbnN0IGNhbkluc2VydCA9IHNlbGZSZWZzLmV2ZXJ5KChyZWYpID0+IHtcbiAgICAgICAgICBpZiAoIXJvd0J5VXVpZC5oYXMocmVmLnV1aWQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYOyhtOyerO2VmOyngCDslYrripQgdXVpZCAke3JlZi51dWlkfSAtLSBpbiAke3RhYmxlTmFtZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGluc2VydGVkLmhhcyhyZWYudXVpZCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChjYW5JbnNlcnQpIHtcbiAgICAgICAgICBjdXJyZW50TGV2ZWwucHVzaChyb3cpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHRQZW5kaW5nLnB1c2gocm93KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyDsiJztmZgg7LC47KGwIOqwkOyngFxuICAgICAgaWYgKGN1cnJlbnRMZXZlbC5sZW5ndGggPT09IDApIHJldHVybiB7IGxldmVsczogW10sIGhhc0NpcmN1bGFyOiB0cnVlIH07XG5cbiAgICAgIC8vIOugiOuyqCDtmZXsoJUgKyBpbnNlcnRlZCDqsLHsi6BcbiAgICAgIGxldmVscy5wdXNoKGN1cnJlbnRMZXZlbCk7XG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiBjdXJyZW50TGV2ZWwpIHtcbiAgICAgICAgaW5zZXJ0ZWQuYWRkKHJvdy51dWlkIGFzIHN0cmluZyk7XG4gICAgICB9XG5cbiAgICAgIHBlbmRpbmcgPSBuZXh0UGVuZGluZztcbiAgICB9XG5cbiAgICByZXR1cm4geyBsZXZlbHMsIGhhc0NpcmN1bGFyOiBmYWxzZSB9O1xuICB9XG59XG4iXSwibmFtZXMiOlsicmFuZG9tVVVJRCIsInVuaXF1ZSIsIkVudGl0eU1hbmFnZXIiLCJOYWl0ZSIsImFzc2VydERlZmluZWQiLCJjaHVuayIsIm5vbk51bGxhYmxlIiwiYmF0Y2hVcGRhdGUiLCJpc1JlZkZpZWxkIiwiZmllbGQiLCJ1bmRlZmluZWQiLCJvZiIsInV1aWQiLCJVcHNlcnRCdWlsZGVyIiwidGFibGVzIiwiTWFwIiwiZ2V0VGFibGUiLCJ0YWJsZU5hbWUiLCJ0YWJsZSIsImdldCIsInRhYmxlU3BlYyIsImdldFRhYmxlU3BlYyIsInRhYmxlRGF0YSIsInJlZmVyZW5jZXMiLCJTZXQiLCJyb3dzIiwidW5pcXVlSW5kZXhlcyIsInVuaXF1ZXNNYXAiLCJzZXQiLCJoYXNUYWJsZSIsImhhcyIsInJlZ2lzdGVyIiwicm93IiwidW5pcXVlS2V5cyIsIm1hcCIsInVucUluZGV4IiwidW5pcXVlS2V5QXJyYXkiLCJjb2x1bW5zIiwidW5xQ29sIiwidmFsIiwibGVuZ3RoIiwiam9pbiIsImZpbHRlciIsImlzUmV1c2VkIiwidW5pcXVlS2V5IiwiT2JqZWN0IiwiZnJvbUVudHJpZXMiLCJlbnRyaWVzIiwicm93S2V5Iiwicm93VmFsdWUiLCJ1c2UiLCJhZGQiLCJEYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsInB1c2giLCJyZXN1bHQiLCJ0IiwiaXNVdWlkUmV1c2VkIiwidXBzZXJ0Iiwid2RiIiwiY2h1bmtTaXplIiwidXBzZXJ0T3JJbnNlcnQiLCJpbnNlcnRPbmx5IiwibW9kZSIsIkVycm9yIiwic29tZSIsInZhbHVlIiwicmVmVGFibGVzIiwiQXJyYXkiLCJmcm9tIiwicmVkdWNlIiwiciIsInJlZmVyZW5jZSIsInZhbHVlcyIsImZpbmQiLCJyZWYiLCJpbmNsdWRlcyIsImV4dHJhY3RGaWVsZHMiLCJzcGxpdCIsImxldmVscyIsImhhc0NpcmN1bGFyIiwiYnVpbGRJbnNlcnRMZXZlbHMiLCJ1dWlkTWFwIiwiYWxsSWRzIiwibGV2ZWxSb3dzIiwicmVzb2x2ZWRSb3dzIiwicmVzb2x2ZWQiLCJrZXkiLCJwYXJlbnQiLCJ0byIsImxldmVsQ2h1bmtzIiwic2VsZWN0RmllbGRzIiwiZGF0YUNodW5rIiwicmVzdWx0Um93cyIsImluc2VydCIsImludG8iLCJ1dWlkcyIsInNlbGVjdCIsIndoZXJlSW4iLCJjb25mbGljdENvbHVtbnMiLCJ1cGRhdGVDb2x1bW5zIiwia2V5cyIsImNvbCIsInF1ZXJ5Iiwib25Db25mbGljdCIsImlnbm9yZSIsInJldHVybmluZyIsIm1lcmdlIiwiaWQiLCJwcm9wIiwiY29uc29sZSIsImVycm9yIiwicmVzb2x2ZWRWYWx1ZSIsImNsZWFyIiwicm93Q291bnQiLCJyZXR1cm5lZElkcyIsInVwZGF0ZUJhdGNoIiwib3B0aW9ucyIsIndoZXJlIiwid2hlcmVDb2x1bW5zIiwiaXNBcnJheSIsIl9yb3ciLCJfIiwiaGFzU2VsZlJlZiIsImZsYXRNYXAiLCJyb3dCeVV1aWQiLCJwZW5kaW5nIiwiaW5zZXJ0ZWQiLCJjdXJyZW50TGV2ZWwiLCJuZXh0UGVuZGluZyIsInNlbGZSZWZzIiwiY2FuSW5zZXJ0IiwiZXZlcnkiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFVBQVUsUUFBUSxTQUFTO0FBRXBDLFNBQVNDLE1BQU0sUUFBUSxVQUFVO0FBQ2pDLFNBQVNDLGFBQWEsUUFBUSw4QkFBMkI7QUFDekQsU0FBU0MsS0FBSyxRQUFRLG9CQUFpQjtBQUN2QyxTQUFTQyxhQUFhLEVBQUVDLEtBQUssRUFBRUMsV0FBVyxRQUFRLG9CQUFpQjtBQUNuRSxTQUFTQyxXQUFXLFFBQXdCLHFC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
|