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,353 +1,348 @@
|
|
|
1
|
+
import { __esmMin } from "../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { createKnexInstance, init_knex } from "../database/knex.js";
|
|
3
|
+
import { DB, init_db } from "../database/db.js";
|
|
4
|
+
import { SD, init_sd } from "../dict/sd.js";
|
|
5
|
+
import { ServiceUnavailableException, init_so_exceptions } from "../exceptions/so-exceptions.js";
|
|
6
|
+
import { init_controller, isTest } from "../utils/controller.js";
|
|
7
|
+
import { exists, init_fs_utils } from "../utils/fs-utils.js";
|
|
8
|
+
import { Sonamu, init_sonamu } from "../api/sonamu.js";
|
|
9
|
+
import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
|
|
10
|
+
import { Naite, init_naite } from "../naite/naite.js";
|
|
11
|
+
import { PostgreSQLSchemaReader, init_postgresql_schema_reader } from "./postgresql-schema-reader.js";
|
|
12
|
+
import { generateAlterCode, generateCreateCode, init_code_generation } from "./code-generation.js";
|
|
13
|
+
import { getMigrationSetFromEntity, init_migration_set } from "./migration-set.js";
|
|
14
|
+
import { group, sum, unique } from "radashi";
|
|
1
15
|
import assert from "assert";
|
|
2
|
-
import
|
|
3
|
-
import { mkdir, readdir, unlink, writeFile } from "node:fs/promises";
|
|
16
|
+
import { mkdir, readdir, unlink, writeFile } from "fs/promises";
|
|
4
17
|
import path from "path";
|
|
5
|
-
import
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
*/ async runShadowTest() {
|
|
288
|
-
const tdbConn = Sonamu.dbConfig.test.connection;
|
|
289
|
-
const shadowDatabase = `${tdbConn.database}__migration_shadow`;
|
|
290
|
-
// 테스트 상황에서는 트랜잭션을 초기화하고, 새 데이터베이스 커넥션을 가져와야 함
|
|
291
|
-
if (isTest()) {
|
|
292
|
-
await DB.clearTestTransaction();
|
|
293
|
-
// 병렬 테스트 모드에서는 worker DB 연결 유지
|
|
294
|
-
if (process.env.SONAMU_WORKER_DB !== "true") {
|
|
295
|
-
await DB.destroy();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
// 기존 Shadow DB 삭제 후 Shadow DB 생성
|
|
299
|
-
const tdb = createKnexInstance(Sonamu.dbConfig.test);
|
|
300
|
-
try {
|
|
301
|
-
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
302
|
-
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
303
|
-
await tdb.raw(`
|
|
18
|
+
import chalk from "chalk";
|
|
19
|
+
|
|
20
|
+
//#region src/migration/migrator.ts
|
|
21
|
+
var Migrator;
|
|
22
|
+
var init_migrator = __esmMin((() => {
|
|
23
|
+
init_sonamu();
|
|
24
|
+
init_db();
|
|
25
|
+
init_knex();
|
|
26
|
+
init_sd();
|
|
27
|
+
init_entity_manager();
|
|
28
|
+
init_so_exceptions();
|
|
29
|
+
init_naite();
|
|
30
|
+
init_controller();
|
|
31
|
+
init_fs_utils();
|
|
32
|
+
init_code_generation();
|
|
33
|
+
init_migration_set();
|
|
34
|
+
init_postgresql_schema_reader();
|
|
35
|
+
Migrator = class {
|
|
36
|
+
async runMigrationsSequentially(conns, action) {
|
|
37
|
+
const results = [];
|
|
38
|
+
for (const { connKey, knex } of conns) {
|
|
39
|
+
const [batchNo, applied] = action === "apply" ? await knex.migrate.latest() : await knex.migrate.rollback();
|
|
40
|
+
results.push({
|
|
41
|
+
connKey,
|
|
42
|
+
batchNo,
|
|
43
|
+
applied
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return results;
|
|
47
|
+
}
|
|
48
|
+
async getMigrationCodes() {
|
|
49
|
+
const srcMigrationsDir = path.join(Sonamu.apiRootPath, "src", "migrations");
|
|
50
|
+
if (!await exists(srcMigrationsDir)) {
|
|
51
|
+
await mkdir(srcMigrationsDir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
const codes = (await readdir(srcMigrationsDir)).filter((f) => f.endsWith(".ts")).map((f) => ({
|
|
54
|
+
name: f.replace(".ts", ""),
|
|
55
|
+
path: path.join(srcMigrationsDir, f)
|
|
56
|
+
})).toSorted((a, b) => a.name < b.name ? 1 : -1);
|
|
57
|
+
Naite.t("migrator:getMigrationCodes:results", codes);
|
|
58
|
+
return codes;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 타겟별 마이그레이션 상태와 코드 생성/준비 상태를 구해옵니다.
|
|
62
|
+
* 실제로 DB에 접근도 하고 마이그레이션 코드 파일도 확인하고,
|
|
63
|
+
* 필요하다면 적용할 수 있는 코드를 생성까지 해옵니다.
|
|
64
|
+
*
|
|
65
|
+
* CLI와 Sonamu UI에서 사용됩니다.
|
|
66
|
+
*
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
async getStatus() {
|
|
70
|
+
const codes = await this.getMigrationCodes();
|
|
71
|
+
Naite.t("migrator:getStatus:codes", codes);
|
|
72
|
+
const connKeys = Object.keys(Sonamu.dbConfig).filter((key) => !key.endsWith("_slave"));
|
|
73
|
+
let migrationStatusError;
|
|
74
|
+
const statuses = await Promise.all(connKeys.map(async (connKey) => {
|
|
75
|
+
const knexOptions = Sonamu.dbConfig[connKey];
|
|
76
|
+
const tConn = createKnexInstance(knexOptions);
|
|
77
|
+
try {
|
|
78
|
+
const status = await (async () => {
|
|
79
|
+
try {
|
|
80
|
+
return await tConn.migrate.status();
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.warn(chalk.yellow(`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n${JSON.stringify(knexOptions.connection, null, 2)}\n발생한 에러:\n${err}\n`));
|
|
83
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
84
|
+
return "error";
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
const pending = await (async () => {
|
|
88
|
+
try {
|
|
89
|
+
const [, fdList] = await tConn.migrate.list();
|
|
90
|
+
return fdList.map((fd) => fd.file.replace(".ts", ""));
|
|
91
|
+
} catch (err) {
|
|
92
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
})();
|
|
96
|
+
const currentVersion = await (async () => {
|
|
97
|
+
try {
|
|
98
|
+
return await tConn.migrate.currentVersion();
|
|
99
|
+
} catch (_err) {
|
|
100
|
+
migrationStatusError = _err instanceof Error ? _err.message : String(_err);
|
|
101
|
+
return "error";
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
104
|
+
Naite.t("migrator:getStatus:status", status);
|
|
105
|
+
const connection = knexOptions.connection;
|
|
106
|
+
return {
|
|
107
|
+
name: connKey.replace("_master", ""),
|
|
108
|
+
connKey,
|
|
109
|
+
connString: `pg://${connection.user ?? ""}@${connection.host}:${connection.port}/${connection.database}`,
|
|
110
|
+
currentVersion,
|
|
111
|
+
status,
|
|
112
|
+
pending
|
|
113
|
+
};
|
|
114
|
+
} finally {
|
|
115
|
+
await tConn.destroy();
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
Naite.t("migrator:getStatus:conns", statuses);
|
|
119
|
+
const preparedCodes = await (async () => {
|
|
120
|
+
const status0conn = statuses.find((status) => status.status === 0);
|
|
121
|
+
if (status0conn === undefined) {
|
|
122
|
+
console.warn(chalk.yellow(`While trying to prepare migration codes, we found that there is no database to compare migrations. We need at least one database where every migration is applied(status === 0). You might want to apply your existing migrations to one of the databases.`));
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
const compareDBconn = createKnexInstance(Sonamu.dbConfig[status0conn.connKey]);
|
|
126
|
+
try {
|
|
127
|
+
return await this.compareMigrations(compareDBconn);
|
|
128
|
+
} finally {
|
|
129
|
+
await compareDBconn.destroy();
|
|
130
|
+
}
|
|
131
|
+
})();
|
|
132
|
+
Naite.t("migrator:getStatus:preparedCodes", preparedCodes);
|
|
133
|
+
return {
|
|
134
|
+
conns: statuses,
|
|
135
|
+
codes,
|
|
136
|
+
preparedCodes,
|
|
137
|
+
error: migrationStatusError
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 마이그레이션을 적용하거나 롤백합니다.
|
|
142
|
+
* Sonamu UI에서 마이그레이션 작업을 수행할 때 사용됩니다.
|
|
143
|
+
*
|
|
144
|
+
* CLI와 Sonamu UI에서 사용됩니다.
|
|
145
|
+
*
|
|
146
|
+
* @param action 작업 유형 (apply/rollback)
|
|
147
|
+
* @param targets 작업 대상 DB 설정 키 (keyof SonamuDBConfig)
|
|
148
|
+
* @returns 작업 결과
|
|
149
|
+
*/
|
|
150
|
+
async runAction(action, targets) {
|
|
151
|
+
Naite.t("migrator:runAction:action", action);
|
|
152
|
+
Naite.t("migrator:runAction:targets", targets);
|
|
153
|
+
const configs = unique(targets.map((target) => ({
|
|
154
|
+
connKey: target,
|
|
155
|
+
options: Sonamu.dbConfig[target]
|
|
156
|
+
})).filter((c) => c.options !== undefined), ({ options }) => `${options.connection.host}:${options.connection.port ?? 5432}/${options.connection.database}`);
|
|
157
|
+
const conns = await Promise.all(configs.map(async (config) => ({
|
|
158
|
+
connKey: config.connKey,
|
|
159
|
+
knex: createKnexInstance(config.options)
|
|
160
|
+
})));
|
|
161
|
+
try {
|
|
162
|
+
const result = await (async () => {
|
|
163
|
+
switch (action) {
|
|
164
|
+
case "apply": return this.runMigrationsSequentially(conns, "apply");
|
|
165
|
+
case "rollback": return this.runMigrationsSequentially(conns, "rollback");
|
|
166
|
+
}
|
|
167
|
+
})();
|
|
168
|
+
Naite.t("migrator:runAction:result", result);
|
|
169
|
+
return result;
|
|
170
|
+
} finally {
|
|
171
|
+
await Promise.all(conns.map(({ knex }) => {
|
|
172
|
+
return knex.destroy();
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 삭제 가능한 마이그레이션 코드 파일을 검증합니다.
|
|
178
|
+
*
|
|
179
|
+
* @param conns 마이그레이션 상태 배열
|
|
180
|
+
* @param codeNames 삭제할 마이그레이션 코드 파일 이름 배열
|
|
181
|
+
* @returns 삭제 가능 여부 및 적용된 마이그레이션 코드 파일 이름
|
|
182
|
+
*/
|
|
183
|
+
validateDeletable(conns, codeNames) {
|
|
184
|
+
const appliedCodes = codeNames.filter((codeName) => conns.some((conn) => !conn.pending.includes(codeName)));
|
|
185
|
+
return {
|
|
186
|
+
canDelete: appliedCodes.length === 0,
|
|
187
|
+
appliedCodes
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 마이그레이션 코드 파일을 삭제합니다.
|
|
192
|
+
*
|
|
193
|
+
* Sonamu UI에서 사용됩니다.
|
|
194
|
+
*
|
|
195
|
+
* @param codeNames 삭제할 마이그레이션 코드 파일 이름 배열
|
|
196
|
+
* @returns 삭제된 마이그레이션 코드 파일 개수
|
|
197
|
+
*/
|
|
198
|
+
async delCodes(codeNames) {
|
|
199
|
+
const { conns } = await this.getStatus();
|
|
200
|
+
const { canDelete, appliedCodes } = this.validateDeletable(conns, codeNames);
|
|
201
|
+
if (!canDelete) {
|
|
202
|
+
throw new Error(`You cannot delete a migration file if there is already applied. Applied codes: ${appliedCodes.join(", ")}`);
|
|
203
|
+
}
|
|
204
|
+
return sum(await Promise.all(codeNames.map(async (codeName) => {
|
|
205
|
+
const filePath = `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`;
|
|
206
|
+
if (await exists(filePath)) {
|
|
207
|
+
await unlink(filePath);
|
|
208
|
+
return 1;
|
|
209
|
+
}
|
|
210
|
+
return 0;
|
|
211
|
+
})));
|
|
212
|
+
}
|
|
213
|
+
genDateTag(index, baseDate = new Date()) {
|
|
214
|
+
const date = new Date(baseDate.getTime() + index * 1e3);
|
|
215
|
+
const pad = (num, size = 2) => num.toString().padStart(size, "0");
|
|
216
|
+
return date.getFullYear().toString() + pad(date.getMonth() + 1) + pad(date.getDate()) + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* 마이그레이션 코드 파일을 생성합니다.
|
|
220
|
+
*
|
|
221
|
+
* Sonamu UI에서 사용됩니다.
|
|
222
|
+
*
|
|
223
|
+
* @returns 생성된 마이그레이션 코드 파일 개수
|
|
224
|
+
*/
|
|
225
|
+
async generatePreparedCodes() {
|
|
226
|
+
const { preparedCodes } = await this.getStatus();
|
|
227
|
+
Naite.t("migrator:generatePreparedCodes:preparedCodes", preparedCodes);
|
|
228
|
+
if (preparedCodes.length === 0) {
|
|
229
|
+
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
233
|
+
for (const [index, pcode] of preparedCodes.entries()) {
|
|
234
|
+
if (pcode.formatted) {
|
|
235
|
+
const dateTag = this.genDateTag(index);
|
|
236
|
+
const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;
|
|
237
|
+
await writeFile(filePath, pcode.formatted);
|
|
238
|
+
!isTest() && console.log(chalk.green(`MIGRATION CREATED ${filePath}`));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return preparedCodes.length;
|
|
242
|
+
}
|
|
243
|
+
async compareMigrations(compareDB) {
|
|
244
|
+
const entityIds = EntityManager.getAllIds();
|
|
245
|
+
const entitySetsWithJoinTable = entityIds.filter((entityId) => EntityManager.get(entityId).props.length > 0).map((entityId) => getMigrationSetFromEntity(EntityManager.get(entityId)));
|
|
246
|
+
const joinTablesWithDup = entitySetsWithJoinTable.flatMap((entitySet) => entitySet.joinTables);
|
|
247
|
+
const joinTables = Object.values(group(joinTablesWithDup, (jt) => jt.table)).map((tables) => {
|
|
248
|
+
assert(tables !== undefined, "tables is undefined");
|
|
249
|
+
if (tables.length === 1) {
|
|
250
|
+
return tables[0];
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
...tables[0],
|
|
254
|
+
indexes: unique(tables.flatMap((t) => t.indexes), (index) => [index.type, ...index.columns].join("-"))
|
|
255
|
+
};
|
|
256
|
+
});
|
|
257
|
+
const entitySets = [...entitySetsWithJoinTable, ...joinTables];
|
|
258
|
+
const codes = (await Promise.all(entitySets.map(async (entitySet) => {
|
|
259
|
+
const dbSet = await PostgreSQLSchemaReader.getMigrationSetFromDB(compareDB, entitySet.table);
|
|
260
|
+
Naite.t(`migrator:compareMigrations:entitySet:${entitySet.table}`, entitySet);
|
|
261
|
+
Naite.t(`migrator:compareMigrations:dbSet:${entitySet.table}`, dbSet);
|
|
262
|
+
if (dbSet === null) {
|
|
263
|
+
return await generateCreateCode(entitySet);
|
|
264
|
+
} else {
|
|
265
|
+
return await generateAlterCode(entitySet, dbSet, compareDB);
|
|
266
|
+
}
|
|
267
|
+
}))).flat();
|
|
268
|
+
codes.sort((codeA, codeB) => {
|
|
269
|
+
if (codeA.type === "foreign" && codeB.type === "normal") {
|
|
270
|
+
return 1;
|
|
271
|
+
} else if (codeA.type === "normal" && codeB.type === "foreign") {
|
|
272
|
+
return -1;
|
|
273
|
+
} else {
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return codes;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Shadow DB 테스트를 진행합니다.
|
|
281
|
+
*
|
|
282
|
+
* Sonamu UI에서 사용됩니다.
|
|
283
|
+
*
|
|
284
|
+
* @returns Shadow DB 테스트 결과
|
|
285
|
+
*/
|
|
286
|
+
async runShadowTest() {
|
|
287
|
+
const tdbConn = Sonamu.dbConfig.test.connection;
|
|
288
|
+
const shadowDatabase = `${tdbConn.database}__migration_shadow`;
|
|
289
|
+
if (isTest()) {
|
|
290
|
+
await DB.clearTestTransaction();
|
|
291
|
+
if (process.env.SONAMU_WORKER_DB !== "true") {
|
|
292
|
+
await DB.destroy();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const tdb = createKnexInstance(Sonamu.dbConfig.test);
|
|
296
|
+
try {
|
|
297
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
298
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
299
|
+
await tdb.raw(`
|
|
304
300
|
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
|
305
301
|
FROM pg_stat_activity
|
|
306
302
|
WHERE datname = '${tdbConn.database}'
|
|
307
303
|
AND pid <> pg_backend_pid();
|
|
308
304
|
`);
|
|
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
|
-
}
|
|
305
|
+
await tdb.raw(`CREATE DATABASE ${shadowDatabase} TEMPLATE ${tdbConn.database}`);
|
|
306
|
+
const sdb = createKnexInstance({
|
|
307
|
+
...Sonamu.dbConfig.test,
|
|
308
|
+
connection: {
|
|
309
|
+
...tdbConn,
|
|
310
|
+
database: shadowDatabase,
|
|
311
|
+
password: tdbConn.password
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
try {
|
|
315
|
+
const [batchNo, applied] = await sdb.migrate.latest();
|
|
316
|
+
!isTest() && console.log(chalk.green("Shadow DB 테스트에 성공했습니다!"), {
|
|
317
|
+
batchNo,
|
|
318
|
+
applied
|
|
319
|
+
});
|
|
320
|
+
return [{
|
|
321
|
+
connKey: "shadow",
|
|
322
|
+
batchNo,
|
|
323
|
+
applied
|
|
324
|
+
}];
|
|
325
|
+
} catch (e) {
|
|
326
|
+
console.error(e);
|
|
327
|
+
throw new ServiceUnavailableException(SD("sonamu.error.shadowDbTestFailed"));
|
|
328
|
+
} finally {
|
|
329
|
+
await sdb.destroy();
|
|
330
|
+
}
|
|
331
|
+
} finally {
|
|
332
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
333
|
+
try {
|
|
334
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
335
|
+
} catch (e) {
|
|
336
|
+
console.error("Shadow DB 정리 실패:", e);
|
|
337
|
+
} finally {
|
|
338
|
+
await tdb.destroy();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}));
|
|
352
344
|
|
|
353
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24vbWlncmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgeyBta2RpciwgcmVhZGRpciwgdW5saW5rLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB0eXBlIHsgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgZ3JvdXAsIHN1bSwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IERCLCB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBjcmVhdGVLbmV4SW5zdGFuY2UgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leFwiO1xuaW1wb3J0IHsgU0QgfSBmcm9tIFwiLi4vZGljdC9zZFwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IE5haXRlIH0gZnJvbSBcIi4uL25haXRlL25haXRlXCI7XG5pbXBvcnQgdHlwZSB7IEdlbk1pZ3JhdGlvbkNvZGUsIE1pZ3JhdGlvblNldCB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgaXNUZXN0IH0gZnJvbSBcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGV4aXN0cyB9IGZyb20gXCIuLi91dGlscy9mcy11dGlsc1wiO1xuaW1wb3J0IHsgZ2VuZXJhdGVBbHRlckNvZGUsIGdlbmVyYXRlQ3JlYXRlQ29kZSB9IGZyb20gXCIuL2NvZGUtZ2VuZXJhdGlvblwiO1xuaW1wb3J0IHsgZ2V0TWlncmF0aW9uU2V0RnJvbUVudGl0eSB9IGZyb20gXCIuL21pZ3JhdGlvbi1zZXRcIjtcbmltcG9ydCB7IFBvc3RncmVTUUxTY2hlbWFSZWFkZXIgfSBmcm9tIFwiLi9wb3N0Z3Jlc3FsLXNjaGVtYS1yZWFkZXJcIjtcbmltcG9ydCB0eXBlIHsgQ29ublN0cmluZywgTWlncmF0aW9uQ29kZSwgTWlncmF0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUgTWlncmF0aW9uUmVzdWx0ID0ge1xuICBjb25uS2V5OiBzdHJpbmc7XG4gIGJhdGNoTm86IG51bWJlcjtcbiAgYXBwbGllZDogc3RyaW5nW107XG59W107XG5cbmV4cG9ydCBjbGFzcyBNaWdyYXRvciB7XG4gIHByaXZhdGUgYXN5bmMgZ2V0TWlncmF0aW9uQ29kZXMoKTogUHJvbWlzZTxNaWdyYXRpb25Db2RlW10+IHtcbiAgICBjb25zdCBzcmNNaWdyYXRpb25zRGlyID0gcGF0aC5qb2luKFNvbmFtdS5hcGlSb290UGF0aCwgXCJzcmNcIiwgXCJtaWdyYXRpb25zXCIpOyAvLyDsnbTqsbQg7ZmY6rK97JeQIOq0gOqzhOyXhuydtCDtla3sg4Egc3Jj7JeQ7IScIOywvuyVhOyVvCDtlbTsmpQuXG5cbiAgICBpZiAoIShhd2FpdCBleGlzdHMoc3JjTWlncmF0aW9uc0RpcikpKSB7XG4gICAgICBhd2FpdCBta2RpcihzcmNNaWdyYXRpb25zRGlyLCB7XG4gICAgICAgIHJlY3Vyc2l2ZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGNvZGVzID0gKGF3YWl0IHJlYWRkaXIoc3JjTWlncmF0aW9uc0RpcikpXG4gICAgICAuZmlsdGVyKChmKSA9PiBmLmVuZHNXaXRoKFwiLnRzXCIpKVxuICAgICAgLm1hcCgoZikgPT4gKHtcbiAgICAgICAgbmFtZTogZi5yZXBsYWNlKFwiLnRzXCIsIFwiXCIpLFxuICAgICAgICBwYXRoOiBwYXRoLmpvaW4oc3JjTWlncmF0aW9uc0RpciwgZiksXG4gICAgICB9KSlcbiAgICAgIC5zb3J0KChhLCBiKSA9PiAoYS5uYW1lIDwgYi5uYW1lID8gMSA6IC0xKSk7IC8vIOydtOumhCDrgrTrprzssKjsiJwg7KCV66CsKOy1nOyLoOyInClcblxuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRNaWdyYXRpb25Db2RlczpyZXN1bHRzXCIsIGNvZGVzKTtcbiAgICByZXR1cm4gY29kZXM7XG4gIH1cblxuICAvKipcbiAgICog7YOA6rKf67OEIOuniOydtOq3uOugiOydtOyFmCDsg4Htg5zsmYAg7L2U65OcIOyDneyEsS/spIDruYQg7IOB7YOc66W8IOq1rO2VtOyYteuLiOuLpC5cbiAgICog7Iuk7KCc66GcIERC7JeQIOygkeq3vOuPhCDtlZjqs6Ag66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzrj4Qg7ZmV7J247ZWY6rOgLFxuICAgKiDtlYTsmpTtlZjri6TrqbQg7KCB7Jqp7ZWgIOyImCDsnojripQg7L2U65Oc66W8IOyDneyEseq5jOyngCDtlbTsmLXri4jri6QuXG4gICAqXG4gICAqIENMSeyZgCBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgYXN5bmMgZ2V0U3RhdHVzKCk6IFByb21pc2U8TWlncmF0aW9uU3RhdHVzPiB7XG4gICAgY29uc3QgY29kZXMgPSBhd2FpdCB0aGlzLmdldE1pZ3JhdGlvbkNvZGVzKCk7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpjb2Rlc1wiLCBjb2Rlcyk7XG5cbiAgICBjb25zdCBjb25uS2V5cyA9IE9iamVjdC5rZXlzKFNvbmFtdS5kYkNvbmZpZykuZmlsdGVyKFxuICAgICAgKGtleSkgPT4ga2V5LmVuZHNXaXRoKFwiX3NsYXZlXCIpID09PSBmYWxzZSxcbiAgICApIGFzIChrZXlvZiB0eXBlb2YgU29uYW11LmRiQ29uZmlnKVtdO1xuXG4gICAgbGV0IG1pZ3JhdGlvblN0YXR1c0Vycm9yOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgY29ubktleXMubWFwKGFzeW5jIChjb25uS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IGtuZXhPcHRpb25zID0gU29uYW11LmRiQ29uZmlnW2Nvbm5LZXldO1xuICAgICAgICBjb25zdCB0Q29ubiA9IGNyZWF0ZUtuZXhJbnN0YW5jZShrbmV4T3B0aW9ucyk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRDb25uLm1pZ3JhdGUuc3RhdHVzKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgIGNoYWxrLnllbGxvdyhcbiAgICAgICAgICAgICAgICAgIGAke2Nvbm5LZXl97J2YIOuniOydtOq3uOugiOydtOyFmCDsg4Htg5zrpbwg6rCA7KC47Jik64qUIOuNsOyXkCDsi6TtjKjtlZjsmIDsirXri4jri6QuIOuNsOydtO2EsOuyoOydtOyKpOqwgCDsmKzrsJTrpbTqsowg6rWs7ISx65CY7KeAIOyViuydgCDqsoMg6rCZ7Iq164uI64ukLiDtmZXsnbjtlZjsi5zqs6Ag64uk7IucIOyLnOuPhO2VtOyjvOyEuOyalC5cXG7si5zrj4TtlZwg7Jew6rKwIOyEpOyglTpcXG4ke0pTT04uc3RyaW5naWZ5KGtuZXhPcHRpb25zLmNvbm5lY3Rpb24sIG51bGwsIDIpfVxcbuuwnOyDne2VnCDsl5Drn6w6XFxuJHtlcnJ9XFxuYCxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiZXJyb3JcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpO1xuICAgICAgICAgIGNvbnN0IHBlbmRpbmc6IHN0cmluZ1tdID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IFssIGZkTGlzdF0gPSBhd2FpdCB0Q29ubi5taWdyYXRlLmxpc3QoKTtcbiAgICAgICAgICAgICAgcmV0dXJuIGZkTGlzdC5tYXAoKGZkOiB7IGZpbGU6IHN0cmluZyB9KSA9PiBmZC5maWxlLnJlcGxhY2UoXCIudHNcIiwgXCJcIikpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIG1pZ3JhdGlvblN0YXR1c0Vycm9yID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpO1xuICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKTtcbiAgICAgICAgICBjb25zdCBjdXJyZW50VmVyc2lvbiA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdENvbm4ubWlncmF0ZS5jdXJyZW50VmVyc2lvbigpO1xuICAgICAgICAgICAgfSBjYXRjaCAoX2Vycikge1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IF9lcnIgaW5zdGFuY2VvZiBFcnJvciA/IF9lcnIubWVzc2FnZSA6IFN0cmluZyhfZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiZXJyb3JcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpO1xuICAgICAgICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6c3RhdHVzXCIsIHN0YXR1cyk7XG5cbiAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0ga25leE9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuYW1lOiBjb25uS2V5LnJlcGxhY2UoXCJfbWFzdGVyXCIsIFwiXCIpLFxuICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgIGNvbm5TdHJpbmc6IGBwZzovLyR7Y29ubmVjdGlvbi51c2VyID8/IFwiXCJ9QCR7Y29ubmVjdGlvbi5ob3N0fToke1xuICAgICAgICAgICAgICBjb25uZWN0aW9uLnBvcnRcbiAgICAgICAgICAgIH0vJHtjb25uZWN0aW9uLmRhdGFiYXNlfWAgYXMgQ29ublN0cmluZyxcbiAgICAgICAgICAgIGN1cnJlbnRWZXJzaW9uLFxuICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMgYXMgbnVtYmVyIHwgXCJlcnJvclwiLFxuICAgICAgICAgICAgcGVuZGluZyxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGF3YWl0IHRDb25uLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgKTtcblxuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6Y29ubnNcIiwgc3RhdHVzZXMpO1xuXG4gICAgY29uc3QgcHJlcGFyZWRDb2RlczogR2VuTWlncmF0aW9uQ29kZVtdID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHN0YXR1czBjb25uID0gc3RhdHVzZXMuZmluZCgoc3RhdHVzKSA9PiBzdGF0dXMuc3RhdHVzID09PSAwKTtcbiAgICAgIGlmIChzdGF0dXMwY29ubiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICBgV2hpbGUgdHJ5aW5nIHRvIHByZXBhcmUgbWlncmF0aW9uIGNvZGVzLCB3ZSBmb3VuZCB0aGF0IHRoZXJlIGlzIG5vIGRhdGFiYXNlIHRvIGNvbXBhcmUgbWlncmF0aW9ucy4gV2UgbmVlZCBhdCBsZWFzdCBvbmUgZGF0YWJhc2Ugd2hlcmUgZXZlcnkgbWlncmF0aW9uIGlzIGFwcGxpZWQoc3RhdHVzID09PSAwKS4gWW91IG1pZ2h0IHdhbnQgdG8gYXBwbHkgeW91ciBleGlzdGluZyBtaWdyYXRpb25zIHRvIG9uZSBvZiB0aGUgZGF0YWJhc2VzLmAsXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb21wYXJlREJjb25uID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZ1tzdGF0dXMwY29ubi5jb25uS2V5XSk7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb21wYXJlTWlncmF0aW9ucyhjb21wYXJlREJjb25uKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGNvbXBhcmVEQmNvbm4uZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOnByZXBhcmVkQ29kZXNcIiwgcHJlcGFyZWRDb2Rlcyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29ubnM6IHN0YXR1c2VzLFxuICAgICAgY29kZXMsXG4gICAgICBwcmVwYXJlZENvZGVzLFxuICAgICAgZXJyb3I6IG1pZ3JhdGlvblN0YXR1c0Vycm9yLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICog66eI7J206re466CI7J207IWY7J2EIOyggeyaqe2VmOqxsOuCmCDroaTrsLHtlanri4jri6QuXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDrp4jsnbTqt7jroIjsnbTshZgg7J6R7JeF7J2EIOyImO2Wie2VoCDrlYwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBDTEnsmYAgU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHBhcmFtIGFjdGlvbiDsnpHsl4Ug7Jyg7ZiVIChhcHBseS9yb2xsYmFjaylcbiAgICogQHBhcmFtIHRhcmdldHMg7J6R7JeFIOuMgOyDgSBEQiDshKTsoJUg7YKkIChrZXlvZiBTb25hbXVEQkNvbmZpZylcbiAgICogQHJldHVybnMg7J6R7JeFIOqysOqzvFxuICAgKi9cbiAgYXN5bmMgcnVuQWN0aW9uKFxuICAgIGFjdGlvbjogXCJhcHBseVwiIHwgXCJyb2xsYmFja1wiLFxuICAgIHRhcmdldHM6IChrZXlvZiBTb25hbXVEQkNvbmZpZylbXSxcbiAgKTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+IHtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOmFjdGlvblwiLCBhY3Rpb24pO1xuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpydW5BY3Rpb246dGFyZ2V0c1wiLCB0YXJnZXRzKTtcblxuICAgIC8vIGdldCB1bmlxIGtuZXggY29uZmlnc1xuICAgIGNvbnN0IGNvbmZpZ3MgPSB1bmlxdWUoXG4gICAgICB0YXJnZXRzXG4gICAgICAgIC5tYXAoKHRhcmdldCkgPT4gKHtcbiAgICAgICAgICBjb25uS2V5OiB0YXJnZXQsXG4gICAgICAgICAgb3B0aW9uczogU29uYW11LmRiQ29uZmlnW3RhcmdldCBhcyBrZXlvZiB0eXBlb2YgU29uYW11LmRiQ29uZmlnXSxcbiAgICAgICAgfSkpXG4gICAgICAgIC5maWx0ZXIoKGMpID0+IGMub3B0aW9ucyAhPT0gdW5kZWZpbmVkKSxcbiAgICAgICh7IG9wdGlvbnMgfSkgPT5cbiAgICAgICAgYCR7KG9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZykuaG9zdH06JHtcbiAgICAgICAgICAob3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnKS5wb3J0ID8/IDU0MzJcbiAgICAgICAgfS8keyhvcHRpb25zLmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWcpLmRhdGFiYXNlfWAsXG4gICAgKTtcblxuICAgIC8vIGdldCBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGNvbm5zID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25maWdzLm1hcChhc3luYyAoY29uZmlnKSA9PiAoe1xuICAgICAgICBjb25uS2V5OiBjb25maWcuY29ubktleSxcbiAgICAgICAga25leDogY3JlYXRlS25leEluc3RhbmNlKGNvbmZpZy5vcHRpb25zKSxcbiAgICAgIH0pKSxcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGFjdGlvblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICBjYXNlIFwiYXBwbHlcIjpcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgY29ubnMubWFwKGFzeW5jICh7IGNvbm5LZXksIGtuZXggfSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtiYXRjaE5vLCBhcHBsaWVkXSA9IGF3YWl0IGtuZXgubWlncmF0ZS5sYXRlc3QoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgICAgICAgIGJhdGNoTm8sXG4gICAgICAgICAgICAgICAgICBhcHBsaWVkLCAvLyDsnbTrsoggbGF0ZXN0IO2YuOy2nOuhnCDsnbjtlbQgXCJ1cFwi7J20IOyggeyaqeuQnCDrp4jsnbTqt7jroIjsnbTshZgg7J2066aEKGUuZy4gXCIyMDI1MTEyNDIzMzU1N19jcmVhdGVfX2NvbXBhbmllcy50c1wiKeuTpOydmCDrsLDsl7TsnoXri4jri6QuIOywuOqzoDogaHR0cHM6Ly9naXRodWIuY29tL2tuZXgva25leC9ibG9iLzAxYjE3N2M0ODVkNjk2ZjFiNzI4NThkZWU3MjhiYTE0M2M0ZmFkNzYvbGliL21pZ3JhdGlvbnMvbWlncmF0ZS9NaWdyYXRvci5qcyNMNTYwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIGNhc2UgXCJyb2xsYmFja1wiOlxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICAgICAgICBjb25ucy5tYXAoYXN5bmMgKHsgY29ubktleSwga25leCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgW2JhdGNoTm8sIGFwcGxpZWRdID0gYXdhaXQga25leC5taWdyYXRlLnJvbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgIGNvbm5LZXksXG4gICAgICAgICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgICAgICAgYXBwbGllZCwgLy8g7J2067KIIHJvbGxiYWNrIO2YuOy2nOuhnCDsnbjtlbQgXCJkb3duXCLsnbQg7KCB7Jqp65CcKD3roaTrsLHrkJwpIOuniOydtOq3uOugiOydtOyFmCDsnbTrpoQoZS5nLiBcIjIwMjUxMTI0MjMzNTU3X2NyZWF0ZV9fY29tcGFuaWVzLnRzXCIp65Ok7J2YIOuwsOyXtOyeheuLiOuLpC4g7LC46rOgOiBodHRwczovL2dpdGh1Yi5jb20va25leC9rbmV4L2Jsb2IvMDFiMTc3YzQ4NWQ2OTZmMWI3Mjg1OGRlZTcyOGJhMTQzYzRmYWQ3Ni9saWIvbWlncmF0aW9ucy9taWdyYXRlL01pZ3JhdG9yLmpzI0w2MTFcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pKCk7XG5cbiAgICAgIE5haXRlLnQoXCJtaWdyYXRvcjpydW5BY3Rpb246cmVzdWx0XCIsIHJlc3VsdCk7XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBjb25ucy5tYXAoKHsga25leCB9KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGtuZXguZGVzdHJveSgpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOyCreygnCDqsIDriqXtlZwg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzsnYQg6rKA7Kad7ZWp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gY29ubnMg66eI7J206re466CI7J207IWYIOyDge2DnCDrsLDsl7RcbiAgICogQHBhcmFtIGNvZGVOYW1lcyDsgq3soJztlaAg66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbwg7J2066aEIOuwsOyXtFxuICAgKiBAcmV0dXJucyDsgq3soJwg6rCA64qlIOyXrOu2gCDrsI8g7KCB7Jqp65CcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOydtOumhFxuICAgKi9cbiAgdmFsaWRhdGVEZWxldGFibGUoY29ubnM6IE1pZ3JhdGlvblN0YXR1c1tcImNvbm5zXCJdLCBjb2RlTmFtZXM6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgYXBwbGllZENvZGVzID0gY29kZU5hbWVzLmZpbHRlcigoY29kZU5hbWUpID0+XG4gICAgICBjb25ucy5zb21lKChjb25uKSA9PiBjb25uLnBlbmRpbmcuaW5jbHVkZXMoY29kZU5hbWUpID09PSBmYWxzZSksXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjYW5EZWxldGU6IGFwcGxpZWRDb2Rlcy5sZW5ndGggPT09IDAsXG4gICAgICBhcHBsaWVkQ29kZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOydhCDsgq3soJztlanri4jri6QuXG4gICAqXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEBwYXJhbSBjb2RlTmFtZXMg7IKt7KCc7ZWgIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOydtOumhCDrsLDsl7RcbiAgICogQHJldHVybnMg7IKt7KCc65CcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOqwnOyImFxuICAgKi9cbiAgYXN5bmMgZGVsQ29kZXMoY29kZU5hbWVzOiBzdHJpbmdbXSk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBjb25ucyB9ID0gYXdhaXQgdGhpcy5nZXRTdGF0dXMoKTtcbiAgICBjb25zdCB7IGNhbkRlbGV0ZSwgYXBwbGllZENvZGVzIH0gPSB0aGlzLnZhbGlkYXRlRGVsZXRhYmxlKGNvbm5zLCBjb2RlTmFtZXMpO1xuICAgIGlmICghY2FuRGVsZXRlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBZb3UgY2Fubm90IGRlbGV0ZSBhIG1pZ3JhdGlvbiBmaWxlIGlmIHRoZXJlIGlzIGFscmVhZHkgYXBwbGllZC4gQXBwbGllZCBjb2RlczogJHthcHBsaWVkQ29kZXMuam9pbihcIiwgXCIpfWAsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBzdW0oXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgY29kZU5hbWVzLm1hcChhc3luYyAoY29kZU5hbWUpID0+IHtcbiAgICAgICAgICBjb25zdCBmaWxlUGF0aCA9IGAke1NvbmFtdS5hcGlSb290UGF0aH0vc3JjL21pZ3JhdGlvbnMvJHtjb2RlTmFtZX0udHNgO1xuICAgICAgICAgIGlmIChhd2FpdCBleGlzdHMoZmlsZVBhdGgpKSB7XG4gICAgICAgICAgICBhd2FpdCB1bmxpbmsoZmlsZVBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9KSxcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2VuRGF0ZVRhZyhpbmRleDogbnVtYmVyLCBiYXNlRGF0ZTogRGF0ZSA9IG5ldyBEYXRlKCkpOiBzdHJpbmcge1xuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShiYXNlRGF0ZS5nZXRUaW1lKCkgKyBpbmRleCAqIDEwMDApO1xuICAgIGNvbnN0IHBhZCA9IChudW06IG51bWJlciwgc2l6ZTogbnVtYmVyID0gMikgPT4gbnVtLnRvU3RyaW5nKCkucGFkU3RhcnQoc2l6ZSwgXCIwXCIpO1xuICAgIHJldHVybiAoXG4gICAgICBkYXRlLmdldEZ1bGxZZWFyKCkudG9TdHJpbmcoKSArXG4gICAgICBwYWQoZGF0ZS5nZXRNb250aCgpICsgMSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0RGF0ZSgpKSArXG4gICAgICBwYWQoZGF0ZS5nZXRIb3VycygpKSArXG4gICAgICBwYWQoZGF0ZS5nZXRNaW51dGVzKCkpICtcbiAgICAgIHBhZChkYXRlLmdldFNlY29uZHMoKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J287J2EIOyDneyEse2VqeuLiOuLpC5cbiAgICpcbiAgICogU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHJldHVybnMg7IOd7ISx65CcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOqwnOyImFxuICAgKi9cbiAgYXN5bmMgZ2VuZXJhdGVQcmVwYXJlZENvZGVzKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgeyBwcmVwYXJlZENvZGVzIH0gPSBhd2FpdCB0aGlzLmdldFN0YXR1cygpO1xuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZW5lcmF0ZVByZXBhcmVkQ29kZXM6cHJlcGFyZWRDb2Rlc1wiLCBwcmVwYXJlZENvZGVzKTtcbiAgICBpZiAocHJlcGFyZWRDb2Rlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKFwiXFxu7ZiE7J6sIOuqqOuRkCDsi7HtgazrkJwg7IOB7YOc7J6F64uI64ukLlwiKSk7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvLyDsi6TsoJwg7L2U65OcIOyDneyEsVxuICAgIGNvbnN0IG1pZ3JhdGlvbnNEaXIgPSBgJHtTb25hbXUuYXBpUm9vdFBhdGh9L3NyYy9taWdyYXRpb25zYDtcblxuICAgIGZvciAoY29uc3QgW2luZGV4LCBwY29kZV0gb2YgcHJlcGFyZWRDb2Rlcy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChwY29kZS5mb3JtYXR0ZWQpIHtcbiAgICAgICAgY29uc3QgZGF0ZVRhZyA9IHRoaXMuZ2VuRGF0ZVRhZyhpbmRleCk7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gYCR7bWlncmF0aW9uc0Rpcn0vJHtkYXRlVGFnfV8ke3Bjb2RlLnRpdGxlfS50c2A7XG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZShmaWxlUGF0aCwgcGNvZGUuZm9ybWF0dGVkKTtcbiAgICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKGBNSUdSQVRJT04gQ1JFQVRFRCAke2ZpbGVQYXRofWApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcHJlcGFyZWRDb2Rlcy5sZW5ndGg7XG4gIH1cblxuICBhc3luYyBjb21wYXJlTWlncmF0aW9ucyhjb21wYXJlREI6IEtuZXgpOiBQcm9taXNlPEdlbk1pZ3JhdGlvbkNvZGVbXT4ge1xuICAgIC8vIEVudGl0eSDsiJztmoztlZjsl6wg7Iux7YGsXG4gICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcblxuICAgIC8vIOyhsOyduO2FjOydtOu4lCDtj6ztlajtlZjsl6wgRW50aXR57JeQ7IScIE1pZ3JhdGlvblNldCDstpTstpxcbiAgICBjb25zdCBlbnRpdHlTZXRzV2l0aEpvaW5UYWJsZSA9IGVudGl0eUlkc1xuICAgICAgLmZpbHRlcigoZW50aXR5SWQpID0+IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKS5wcm9wcy5sZW5ndGggPiAwKVxuICAgICAgLm1hcCgoZW50aXR5SWQpID0+IGdldE1pZ3JhdGlvblNldEZyb21FbnRpdHkoRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpKSk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJTrp4wg7LaU7LacXG4gICAgY29uc3Qgam9pblRhYmxlc1dpdGhEdXAgPSBlbnRpdHlTZXRzV2l0aEpvaW5UYWJsZS5mbGF0TWFwKChlbnRpdHlTZXQpID0+IGVudGl0eVNldC5qb2luVGFibGVzKTtcbiAgICAvLyDspJHrs7Ug7KCc6rGwICjspJHrs7Xsnbgg6rK97JqwIGluZGV4ZXPrpbwg67OR7ZWpKVxuICAgIGNvbnN0IGpvaW5UYWJsZXMgPSBPYmplY3QudmFsdWVzKGdyb3VwKGpvaW5UYWJsZXNXaXRoRHVwLCAoanQpID0+IGp0LnRhYmxlKSkubWFwKCh0YWJsZXMpID0+IHtcbiAgICAgIGFzc2VydCh0YWJsZXMgIT09IHVuZGVmaW5lZCwgXCJ0YWJsZXMgaXMgdW5kZWZpbmVkXCIpO1xuICAgICAgaWYgKHRhYmxlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIHRhYmxlc1swXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnRhYmxlc1swXSxcbiAgICAgICAgaW5kZXhlczogdW5pcXVlKFxuICAgICAgICAgIHRhYmxlcy5mbGF0TWFwKCh0KSA9PiB0LmluZGV4ZXMpLFxuICAgICAgICAgIChpbmRleCkgPT4gW2luZGV4LnR5cGUsIC4uLmluZGV4LmNvbHVtbnNdLmpvaW4oXCItXCIpLFxuICAgICAgICApLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIOyhsOyduO2FjOydtOu4lCDtj6ztlajtlZjsl6wgTWlncmF0aW9uU2V0IOuwsOyXtFxuICAgIGNvbnN0IGVudGl0eVNldHM6IE1pZ3JhdGlvblNldFtdID0gWy4uLmVudGl0eVNldHNXaXRoSm9pblRhYmxlLCAuLi5qb2luVGFibGVzXTtcblxuICAgIGNvbnN0IGNvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10gPSAoXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZW50aXR5U2V0cy5tYXAoYXN5bmMgKGVudGl0eVNldCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRiU2V0ID0gYXdhaXQgUG9zdGdyZVNRTFNjaGVtYVJlYWRlci5nZXRNaWdyYXRpb25TZXRGcm9tREIoXG4gICAgICAgICAgICBjb21wYXJlREIsXG4gICAgICAgICAgICBlbnRpdHlTZXQudGFibGUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBOYWl0ZS50KGBtaWdyYXRvcjpjb21wYXJlTWlncmF0aW9uczplbnRpdHlTZXQ6JHtlbnRpdHlTZXQudGFibGV9YCwgZW50aXR5U2V0KTtcbiAgICAgICAgICBOYWl0ZS50KGBtaWdyYXRvcjpjb21wYXJlTWlncmF0aW9uczpkYlNldDoke2VudGl0eVNldC50YWJsZX1gLCBkYlNldCk7XG5cbiAgICAgICAgICBpZiAoZGJTZXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIOq4sOyhtCDthYzsnbTruJQg7JeG7J2MLCDsg4jroZwg7YWM7J2067iUIOyDneyEsVxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGdlbmVyYXRlQ3JlYXRlQ29kZShlbnRpdHlTZXQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyDquLDsobQg7YWM7J2067iUIOyhtOyerO2VmOuKlCDsvIDsnbTsiqRcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBnZW5lcmF0ZUFsdGVyQ29kZShlbnRpdHlTZXQsIGRiU2V0LCBjb21wYXJlREIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICApXG4gICAgKS5mbGF0KCk7XG5cbiAgICAvLyBub3JtYWwg7YOA7J6F7J20IOyVnuycvOuhnCwgZm9yZWlnbuydtCDrkqTroZxcbiAgICBjb2Rlcy5zb3J0KChjb2RlQSwgY29kZUIpID0+IHtcbiAgICAgIGlmIChjb2RlQS50eXBlID09PSBcImZvcmVpZ25cIiAmJiBjb2RlQi50eXBlID09PSBcIm5vcm1hbFwiKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfSBlbHNlIGlmIChjb2RlQS50eXBlID09PSBcIm5vcm1hbFwiICYmIGNvZGVCLnR5cGUgPT09IFwiZm9yZWlnblwiKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNoYWRvdyBEQiDthYzsiqTtirjrpbwg7KeE7ZaJ7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcmV0dXJucyBTaGFkb3cgREIg7YWM7Iqk7Yq4IOqysOqzvFxuICAgKi9cbiAgYXN5bmMgcnVuU2hhZG93VGVzdCgpOiBQcm9taXNlPE1pZ3JhdGlvblJlc3VsdD4ge1xuICAgIGNvbnN0IHRkYkNvbm4gPSBTb25hbXUuZGJDb25maWcudGVzdC5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnO1xuICAgIGNvbnN0IHNoYWRvd0RhdGFiYXNlID0gYCR7dGRiQ29ubi5kYXRhYmFzZX1fX21pZ3JhdGlvbl9zaGFkb3dgO1xuXG4gICAgLy8g7YWM7Iqk7Yq4IOyDge2ZqeyXkOyEnOuKlCDtirjrnpzsnq3shZjsnYQg7LSI6riw7ZmU7ZWY6rOgLCDsg4gg642w7J207YSw67Kg7J207IqkIOy7pOuEpeyFmOydhCDqsIDsoLjsmYDslbwg7ZWoXG4gICAgaWYgKGlzVGVzdCgpKSB7XG4gICAgICBhd2FpdCBEQi5jbGVhclRlc3RUcmFuc2FjdGlvbigpO1xuICAgICAgLy8g67OR66CsIO2FjOyKpO2KuCDrqqjrk5zsl5DshJzripQgd29ya2VyIERCIOyXsOqysCDsnKDsp4BcbiAgICAgIGlmIChwcm9jZXNzLmVudi5TT05BTVVfV09SS0VSX0RCICE9PSBcInRydWVcIikge1xuICAgICAgICBhd2FpdCBEQi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g6riw7KG0IFNoYWRvdyBEQiDsgq3soJwg7ZuEIFNoYWRvdyBEQiDsg53shLFcbiAgICBjb25zdCB0ZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnLnRlc3QpO1xuICAgIHRyeSB7XG4gICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsubWFnZW50YShgJHtzaGFkb3dEYXRhYmFzZX0g7IKt7KCcYCkpO1xuICAgICAgYXdhaXQgdGRiLnJhdyhgRFJPUCBEQVRBQkFTRSBJRiBFWElTVFMgJHtzaGFkb3dEYXRhYmFzZX1gKTtcbiAgICAgIGF3YWl0IHRkYi5yYXcoYFxuICAgICAgICBTRUxFQ1QgcGdfdGVybWluYXRlX2JhY2tlbmQocGdfc3RhdF9hY3Rpdml0eS5waWQpXG4gICAgICAgIEZST00gcGdfc3RhdF9hY3Rpdml0eVxuICAgICAgICBXSEVSRSBkYXRuYW1lID0gJyR7dGRiQ29ubi5kYXRhYmFzZX0nXG4gICAgICAgICAgQU5EIHBpZCA8PiBwZ19iYWNrZW5kX3BpZCgpO1xuICAgICAgYCk7XG4gICAgICBhd2FpdCB0ZGIucmF3KGBDUkVBVEUgREFUQUJBU0UgJHtzaGFkb3dEYXRhYmFzZX0gVEVNUExBVEUgJHt0ZGJDb25uLmRhdGFiYXNlfWApO1xuXG4gICAgICAvLyBTaGFkb3cgRELsl5Ag7Jew6rKwXG4gICAgICBjb25zdCBzZGIgPSBjcmVhdGVLbmV4SW5zdGFuY2Uoe1xuICAgICAgICAuLi5Tb25hbXUuZGJDb25maWcudGVzdCxcbiAgICAgICAgY29ubmVjdGlvbjoge1xuICAgICAgICAgIC4uLnRkYkNvbm4sXG4gICAgICAgICAgZGF0YWJhc2U6IHNoYWRvd0RhdGFiYXNlLFxuICAgICAgICAgIHBhc3N3b3JkOiB0ZGJDb25uLnBhc3N3b3JkLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIHNoYWRvdyBEQiDthYzsiqTtirgg7KeE7ZaJXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBbYmF0Y2hObywgYXBwbGllZF0gPSBhd2FpdCBzZGIubWlncmF0ZS5sYXRlc3QoKTtcbiAgICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oXCJTaGFkb3cgREIg7YWM7Iqk7Yq47JeQIOyEseqzte2WiOyKteuLiOuLpCFcIiksIHtcbiAgICAgICAgICAgIGJhdGNoTm8sXG4gICAgICAgICAgICBhcHBsaWVkLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgY29ubktleTogXCJzaGFkb3dcIixcbiAgICAgICAgICAgIGJhdGNoTm8sXG4gICAgICAgICAgICBhcHBsaWVkLFxuICAgICAgICAgIH0sXG4gICAgICAgIF07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIHRocm93IG5ldyBTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24oU0QoXCJzb25hbXUuZXJyb3Iuc2hhZG93RGJUZXN0RmFpbGVkXCIpKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IHNkYi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIC8vIFNoYWRvdyBEQiDsgq3soJxcbiAgICAgICFpc1Rlc3QoKSAmJiBjb25zb2xlLmxvZyhjaGFsay5tYWdlbnRhKGAke3NoYWRvd0RhdGFiYXNlfSDsgq3soJxgKSk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0ZGIucmF3KGBEUk9QIERBVEFCQVNFIElGIEVYSVNUUyAke3NoYWRvd0RhdGFiYXNlfWApO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiU2hhZG93IERCIOygleumrCDsi6TtjKg6XCIsIGUpOyAvLyDsnbTqsowg7JeG7Jy866m0IOyhsOyaqe2eiCDriITsiJhcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IHRkYi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXSwibmFtZXMiOlsiYXNzZXJ0IiwiY2hhbGsiLCJta2RpciIsInJlYWRkaXIiLCJ1bmxpbmsiLCJ3cml0ZUZpbGUiLCJwYXRoIiwiZ3JvdXAiLCJzdW0iLCJ1bmlxdWUiLCJTb25hbXUiLCJEQiIsImNyZWF0ZUtuZXhJbnN0YW5jZSIsIlNEIiwiRW50aXR5TWFuYWdlciIsIlNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiIsIk5haXRlIiwiaXNUZXN0IiwiZXhpc3RzIiwiZ2VuZXJhdGVBbHRlckNvZGUiLCJnZW5lcmF0ZUNyZWF0ZUNvZGUiLCJnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5IiwiUG9zdGdyZVNRTFNjaGVtYVJlYWRlciIsIk1pZ3JhdG9yIiwiZ2V0TWlncmF0aW9uQ29kZXMiLCJzcmNNaWdyYXRpb25zRGlyIiwiam9pbiIsImFwaVJvb3RQYXRoIiwicmVjdXJzaXZlIiwiY29kZXMiLCJmaWx0ZXIiLCJmIiwiZW5kc1dpdGgiLCJtYXAiLCJuYW1lIiwicmVwbGFjZSIsInNvcnQiLCJhIiwiYiIsInQiLCJnZXRTdGF0dXMiLCJjb25uS2V5cyIsIk9iamVjdCIsImtleXMiLCJkYkNvbmZpZyIsImtleSIsIm1pZ3JhdGlvblN0YXR1c0Vycm9yIiwic3RhdHVzZXMiLCJQcm9taXNlIiwiYWxsIiwiY29ubktleSIsImtuZXhPcHRpb25zIiwidENvbm4iLCJzdGF0dXMiLCJtaWdyYXRlIiwiZXJyIiwiY29uc29sZSIsIndhcm4iLCJ5ZWxsb3ciLCJKU09OIiwic3RyaW5naWZ5IiwiY29ubmVjdGlvbiIsIkVycm9yIiwibWVzc2FnZSIsIlN0cmluZyIsInBlbmRpbmciLCJmZExpc3QiLCJsaXN0IiwiZmQiLCJmaWxlIiwiY3VycmVudFZlcnNpb24iLCJfZXJyIiwiY29ublN0cmluZyIsInVzZXIiLCJob3N0IiwicG9ydCIsImRhdGFiYXNlIiwiZGVzdHJveSIsInByZXBhcmVkQ29kZXMiLCJzdGF0dXMwY29ubiIsImZpbmQiLCJ1bmRlZmluZWQiLCJjb21wYXJlREJjb25uIiwiY29tcGFyZU1pZ3JhdGlvbnMiLCJjb25ucyIsImVycm9yIiwicnVuQWN0aW9uIiwiYWN0aW9uIiwidGFyZ2V0cyIsImNvbmZpZ3MiLCJ0YXJnZXQiLCJvcHRpb25zIiwiYyIsImNvbmZpZyIsImtuZXgiLCJyZXN1bHQiLCJiYXRjaE5vIiwiYXBwbGllZCIsImxhdGVzdCIsInJvbGxiYWNrIiwidmFsaWRhdGVEZWxldGFibGUiLCJjb2RlTmFtZXMiLCJhcHBsaWVkQ29kZXMiLCJjb2RlTmFtZSIsInNvbWUiLCJjb25uIiwiaW5jbHVkZXMiLCJjYW5EZWxldGUiLCJsZW5ndGgiLCJkZWxDb2RlcyIsImZpbGVQYXRoIiwiZ2VuRGF0ZVRhZyIsImluZGV4IiwiYmFzZURhdGUiLCJEYXRlIiwiZGF0ZSIsImdldFRpbWUiLCJwYWQiLCJudW0iLCJzaXplIiwidG9TdHJpbmciLCJwYWRTdGFydCIsImdldEZ1bGxZZWFyIiwiZ2V0TW9udGgiLCJnZXREYXRlIiwiZ2V0SG91cnMiLCJnZXRNaW51dGVzIiwiZ2V0U2Vjb25kcyIsImdlbmVyYXRlUHJlcGFyZWRDb2RlcyIsImxvZyIsImdyZWVuIiwibWlncmF0aW9uc0RpciIsInBjb2RlIiwiZW50cmllcyIsImZvcm1hdHRlZCIsImRhdGVUYWciLCJ0aXRsZSIsImNvbXBhcmVEQiIsImVudGl0eUlkcyIsImdldEFsbElkcyIsImVudGl0eVNldHNXaXRoSm9pblRhYmxlIiwiZW50aXR5SWQiLCJnZXQiLCJwcm9wcyIsImpvaW5UYWJsZXNXaXRoRHVwIiwiZmxhdE1hcCIsImVudGl0eVNldCIsImpvaW5UYWJsZXMiLCJ2YWx1ZXMiLCJqdCIsInRhYmxlIiwidGFibGVzIiwiaW5kZXhlcyIsInR5cGUiLCJjb2x1bW5zIiwiZW50aXR5U2V0cyIsImRiU2V0IiwiZ2V0TWlncmF0aW9uU2V0RnJvbURCIiwiZmxhdCIsImNvZGVBIiwiY29kZUIiLCJydW5TaGFkb3dUZXN0IiwidGRiQ29ubiIsInRlc3QiLCJzaGFkb3dEYXRhYmFzZSIsImNsZWFyVGVzdFRyYW5zYWN0aW9uIiwicHJvY2VzcyIsImVudiIsIlNPTkFNVV9XT1JLRVJfREIiLCJ0ZGIiLCJtYWdlbnRhIiwicmF3Iiwic2RiIiwicGFzc3dvcmQiLCJl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
|
|
345
|
+
//#endregion
|
|
346
|
+
init_migrator();
|
|
347
|
+
export { Migrator, init_migrator };
|
|
348
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0b3IuanMiLCJuYW1lcyI6WyJyZXN1bHRzOiBNaWdyYXRpb25SZXN1bHQiLCJtaWdyYXRpb25TdGF0dXNFcnJvcjogc3RyaW5nIHwgdW5kZWZpbmVkIiwic3RhdHVzOiBudW1iZXIgfCBcImVycm9yXCIiLCJwZW5kaW5nOiBzdHJpbmdbXSIsImN1cnJlbnRWZXJzaW9uOiBzdHJpbmcgfCBcImVycm9yXCIiLCJwcmVwYXJlZENvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10iLCJlbnRpdHlTZXRzOiBNaWdyYXRpb25TZXRbXSIsImNvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlncmF0aW9uL21pZ3JhdG9yLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IHsgbWtkaXIsIHJlYWRkaXIsIHVubGluaywgd3JpdGVGaWxlIH0gZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgeyB0eXBlIEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgZ3JvdXAsIHN1bSwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcblxuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB7IERCIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBjcmVhdGVLbmV4SW5zdGFuY2UgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leFwiO1xuaW1wb3J0IHsgU0QgfSBmcm9tIFwiLi4vZGljdC9zZFwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IFNlcnZpY2VVbmF2YWlsYWJsZUV4Y2VwdGlvbiB9IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IE5haXRlIH0gZnJvbSBcIi4uL25haXRlL25haXRlXCI7XG5pbXBvcnQgeyB0eXBlIEdlbk1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU2V0IH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc1Rlc3QgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUFsdGVyQ29kZSwgZ2VuZXJhdGVDcmVhdGVDb2RlIH0gZnJvbSBcIi4vY29kZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5IH0gZnJvbSBcIi4vbWlncmF0aW9uLXNldFwiO1xuaW1wb3J0IHsgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciB9IGZyb20gXCIuL3Bvc3RncmVzcWwtc2NoZW1hLXJlYWRlclwiO1xuaW1wb3J0IHsgdHlwZSBDb25uU3RyaW5nLCB0eXBlIE1pZ3JhdGlvbkNvZGUsIHR5cGUgTWlncmF0aW9uU3RhdHVzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IHR5cGUgTWlncmF0aW9uUmVzdWx0ID0ge1xuICBjb25uS2V5OiBzdHJpbmc7XG4gIGJhdGNoTm86IG51bWJlcjtcbiAgYXBwbGllZDogc3RyaW5nW107XG59W107XG5cbmV4cG9ydCBjbGFzcyBNaWdyYXRvciB7XG4gIHByaXZhdGUgYXN5bmMgcnVuTWlncmF0aW9uc1NlcXVlbnRpYWxseShcbiAgICBjb25uczogeyBjb25uS2V5OiBrZXlvZiBTb25hbXVEQkNvbmZpZzsga25leDogS25leCB9W10sXG4gICAgYWN0aW9uOiBcImFwcGx5XCIgfCBcInJvbGxiYWNrXCIsXG4gICk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgcmVzdWx0czogTWlncmF0aW9uUmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHsgY29ubktleSwga25leCB9IG9mIGNvbm5zKSB7XG4gICAgICBjb25zdCBbYmF0Y2hObywgYXBwbGllZF0gPVxuICAgICAgICBhY3Rpb24gPT09IFwiYXBwbHlcIiA/IGF3YWl0IGtuZXgubWlncmF0ZS5sYXRlc3QoKSA6IGF3YWl0IGtuZXgubWlncmF0ZS5yb2xsYmFjaygpO1xuXG4gICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICBjb25uS2V5LFxuICAgICAgICBiYXRjaE5vLFxuICAgICAgICBhcHBsaWVkLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldE1pZ3JhdGlvbkNvZGVzKCk6IFByb21pc2U8TWlncmF0aW9uQ29kZVtdPiB7XG4gICAgY29uc3Qgc3JjTWlncmF0aW9uc0RpciA9IHBhdGguam9pbihTb25hbXUuYXBpUm9vdFBhdGgsIFwic3JjXCIsIFwibWlncmF0aW9uc1wiKTsgLy8g7J206rG0IO2ZmOqyveyXkCDqtIDqs4Tsl4bsnbQg7ZWt7IOBIHNyY+yXkOyEnCDssL7slYTslbwg7ZW07JqULlxuXG4gICAgaWYgKCEoYXdhaXQgZXhpc3RzKHNyY01pZ3JhdGlvbnNEaXIpKSkge1xuICAgICAgYXdhaXQgbWtkaXIoc3JjTWlncmF0aW9uc0Rpciwge1xuICAgICAgICByZWN1cnNpdmU6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlcyA9IChhd2FpdCByZWFkZGlyKHNyY01pZ3JhdGlvbnNEaXIpKVxuICAgICAgLmZpbHRlcigoZikgPT4gZi5lbmRzV2l0aChcIi50c1wiKSlcbiAgICAgIC5tYXAoKGYpID0+ICh7XG4gICAgICAgIG5hbWU6IGYucmVwbGFjZShcIi50c1wiLCBcIlwiKSxcbiAgICAgICAgcGF0aDogcGF0aC5qb2luKHNyY01pZ3JhdGlvbnNEaXIsIGYpLFxuICAgICAgfSkpXG4gICAgICAudG9Tb3J0ZWQoKGEsIGIpID0+IChhLm5hbWUgPCBiLm5hbWUgPyAxIDogLTEpKTsgLy8g7J2066aEIOuCtOumvOywqOyInCDsoJXroKwo7LWc7Iug7IicKVxuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldE1pZ3JhdGlvbkNvZGVzOnJlc3VsdHNcIiwgY29kZXMpO1xuICAgIHJldHVybiBjb2RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiDtg4Dqsp/rs4Qg66eI7J206re466CI7J207IWYIOyDge2DnOyZgCDsvZTrk5wg7IOd7ISxL+ykgOu5hCDsg4Htg5zrpbwg6rWs7ZW07Ji164uI64ukLlxuICAgKiDsi6TsoJzroZwgRELsl5Ag7KCR6re864+EIO2VmOqzoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOuPhCDtmZXsnbjtlZjqs6AsXG4gICAqIO2VhOyalO2VmOuLpOuptCDsoIHsmqntlaAg7IiYIOyeiOuKlCDsvZTrk5zrpbwg7IOd7ISx6rmM7KeAIO2VtOyYteuLiOuLpC5cbiAgICpcbiAgICogQ0xJ7JmAIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXRTdGF0dXMoKTogUHJvbWlzZTxNaWdyYXRpb25TdGF0dXM+IHtcbiAgICBjb25zdCBjb2RlcyA9IGF3YWl0IHRoaXMuZ2V0TWlncmF0aW9uQ29kZXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOmNvZGVzXCIsIGNvZGVzKTtcblxuICAgIGNvbnN0IGNvbm5LZXlzID0gT2JqZWN0LmtleXMoU29uYW11LmRiQ29uZmlnKS5maWx0ZXIoXG4gICAgICAoa2V5KSA9PiAha2V5LmVuZHNXaXRoKFwiX3NsYXZlXCIpLFxuICAgICkgYXMgKGtleW9mIHR5cGVvZiBTb25hbXUuZGJDb25maWcpW107XG5cbiAgICBsZXQgbWlncmF0aW9uU3RhdHVzRXJyb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHN0YXR1c2VzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25uS2V5cy5tYXAoYXN5bmMgKGNvbm5LZXkpID0+IHtcbiAgICAgICAgY29uc3Qga25leE9wdGlvbnMgPSBTb25hbXUuZGJDb25maWdbY29ubktleV07XG4gICAgICAgIGNvbnN0IHRDb25uID0gY3JlYXRlS25leEluc3RhbmNlKGtuZXhPcHRpb25zKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHN0YXR1czogbnVtYmVyIHwgXCJlcnJvclwiID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0Q29ubi5taWdyYXRlLnN0YXR1cygpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICBjaGFsay55ZWxsb3coXG4gICAgICAgICAgICAgICAgICBgJHtjb25uS2V5feydmCDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOc66W8IOqwgOyguOyYpOuKlCDrjbDsl5Ag7Iuk7Yyo7ZWY7JiA7Iq164uI64ukLiDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7Jis67CU66W06rKMIOq1rOyEseuQmOyngCDslYrsnYAg6rKDIOqwmeyKteuLiOuLpC4g7ZmV7J247ZWY7Iuc6rOgIOuLpOyLnCDsi5zrj4TtlbTso7zshLjsmpQuXFxu7Iuc64+E7ZWcIOyXsOqysCDshKTsoJU6XFxuJHtKU09OLnN0cmluZ2lmeShrbmV4T3B0aW9ucy5jb25uZWN0aW9uLCBudWxsLCAyKX1cXG7rsJzsg53tlZwg7JeQ65+sOlxcbiR7ZXJyfVxcbmAsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgbWlncmF0aW9uU3RhdHVzRXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICAgIHJldHVybiBcImVycm9yXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkoKTtcbiAgICAgICAgICBjb25zdCBwZW5kaW5nOiBzdHJpbmdbXSA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBbLCBmZExpc3RdID0gYXdhaXQgdENvbm4ubWlncmF0ZS5saXN0KCk7XG4gICAgICAgICAgICAgIHJldHVybiBmZExpc3QubWFwKChmZDogeyBmaWxlOiBzdHJpbmcgfSkgPT4gZmQuZmlsZS5yZXBsYWNlKFwiLnRzXCIsIFwiXCIpKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgY29uc3QgY3VycmVudFZlcnNpb246IHN0cmluZyB8IFwiZXJyb3JcIiA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdENvbm4ubWlncmF0ZS5jdXJyZW50VmVyc2lvbigpO1xuICAgICAgICAgICAgfSBjYXRjaCAoX2Vycikge1xuICAgICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IF9lcnIgaW5zdGFuY2VvZiBFcnJvciA/IF9lcnIubWVzc2FnZSA6IFN0cmluZyhfZXJyKTtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiZXJyb3JcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSgpO1xuICAgICAgICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6c3RhdHVzXCIsIHN0YXR1cyk7XG5cbiAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0ga25leE9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuYW1lOiBjb25uS2V5LnJlcGxhY2UoXCJfbWFzdGVyXCIsIFwiXCIpLFxuICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgIGNvbm5TdHJpbmc6IGBwZzovLyR7Y29ubmVjdGlvbi51c2VyID8/IFwiXCJ9QCR7Y29ubmVjdGlvbi5ob3N0fToke1xuICAgICAgICAgICAgICBjb25uZWN0aW9uLnBvcnRcbiAgICAgICAgICAgIH0vJHtjb25uZWN0aW9uLmRhdGFiYXNlfWAgYXMgQ29ublN0cmluZyxcbiAgICAgICAgICAgIGN1cnJlbnRWZXJzaW9uLFxuICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMsXG4gICAgICAgICAgICBwZW5kaW5nLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgYXdhaXQgdENvbm4uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpjb25uc1wiLCBzdGF0dXNlcyk7XG5cbiAgICBjb25zdCBwcmVwYXJlZENvZGVzOiBHZW5NaWdyYXRpb25Db2RlW10gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdHVzMGNvbm4gPSBzdGF0dXNlcy5maW5kKChzdGF0dXMpID0+IHN0YXR1cy5zdGF0dXMgPT09IDApO1xuICAgICAgaWYgKHN0YXR1czBjb25uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGNoYWxrLnllbGxvdyhcbiAgICAgICAgICAgIGBXaGlsZSB0cnlpbmcgdG8gcHJlcGFyZSBtaWdyYXRpb24gY29kZXMsIHdlIGZvdW5kIHRoYXQgdGhlcmUgaXMgbm8gZGF0YWJhc2UgdG8gY29tcGFyZSBtaWdyYXRpb25zLiBXZSBuZWVkIGF0IGxlYXN0IG9uZSBkYXRhYmFzZSB3aGVyZSBldmVyeSBtaWdyYXRpb24gaXMgYXBwbGllZChzdGF0dXMgPT09IDApLiBZb3UgbWlnaHQgd2FudCB0byBhcHBseSB5b3VyIGV4aXN0aW5nIG1pZ3JhdGlvbnMgdG8gb25lIG9mIHRoZSBkYXRhYmFzZXMuYCxcbiAgICAgICAgICApLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbXBhcmVEQmNvbm4gPSBjcmVhdGVLbmV4SW5zdGFuY2UoU29uYW11LmRiQ29uZmlnW3N0YXR1czBjb25uLmNvbm5LZXldKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvbXBhcmVNaWdyYXRpb25zKGNvbXBhcmVEQmNvbm4pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgY29tcGFyZURCY29ubi5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpnZXRTdGF0dXM6cHJlcGFyZWRDb2Rlc1wiLCBwcmVwYXJlZENvZGVzKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjb25uczogc3RhdHVzZXMsXG4gICAgICBjb2RlcyxcbiAgICAgIHByZXBhcmVkQ29kZXMsXG4gICAgICBlcnJvcjogbWlncmF0aW9uU3RhdHVzRXJyb3IsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZjsnYQg7KCB7Jqp7ZWY6rGw64KYIOuhpOuwse2VqeuLiOuLpC5cbiAgICogU29uYW11IFVJ7JeQ7IScIOuniOydtOq3uOugiOydtOyFmCDsnpHsl4XsnYQg7IiY7ZaJ7ZWgIOuVjCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIENMSeyZgCBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9uIOyekeyXhSDsnKDtmJUgKGFwcGx5L3JvbGxiYWNrKVxuICAgKiBAcGFyYW0gdGFyZ2V0cyDsnpHsl4Ug64yA7IOBIERCIOyEpOyglSDtgqQgKGtleW9mIFNvbmFtdURCQ29uZmlnKVxuICAgKiBAcmV0dXJucyDsnpHsl4Ug6rKw6rO8XG4gICAqL1xuICBhc3luYyBydW5BY3Rpb24oXG4gICAgYWN0aW9uOiBcImFwcGx5XCIgfCBcInJvbGxiYWNrXCIsXG4gICAgdGFyZ2V0czogKGtleW9mIFNvbmFtdURCQ29uZmlnKVtdLFxuICApOiBQcm9taXNlPE1pZ3JhdGlvblJlc3VsdD4ge1xuICAgIE5haXRlLnQoXCJtaWdyYXRvcjpydW5BY3Rpb246YWN0aW9uXCIsIGFjdGlvbik7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOnJ1bkFjdGlvbjp0YXJnZXRzXCIsIHRhcmdldHMpO1xuXG4gICAgLy8gZ2V0IHVuaXEga25leCBjb25maWdzXG4gICAgY29uc3QgY29uZmlncyA9IHVuaXF1ZShcbiAgICAgIHRhcmdldHNcbiAgICAgICAgLm1hcCgodGFyZ2V0KSA9PiAoe1xuICAgICAgICAgIGNvbm5LZXk6IHRhcmdldCxcbiAgICAgICAgICBvcHRpb25zOiBTb25hbXUuZGJDb25maWdbdGFyZ2V0XSxcbiAgICAgICAgfSkpXG4gICAgICAgIC5maWx0ZXIoKGMpID0+IGMub3B0aW9ucyAhPT0gdW5kZWZpbmVkKSxcbiAgICAgICh7IG9wdGlvbnMgfSkgPT5cbiAgICAgICAgYCR7KG9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZykuaG9zdH06JHtcbiAgICAgICAgICAob3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnKS5wb3J0ID8/IDU0MzJcbiAgICAgICAgfS8keyhvcHRpb25zLmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWcpLmRhdGFiYXNlfWAsXG4gICAgKTtcblxuICAgIC8vIGdldCBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGNvbm5zID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25maWdzLm1hcChhc3luYyAoY29uZmlnKSA9PiAoe1xuICAgICAgICBjb25uS2V5OiBjb25maWcuY29ubktleSxcbiAgICAgICAga25leDogY3JlYXRlS25leEluc3RhbmNlKGNvbmZpZy5vcHRpb25zKSxcbiAgICAgIH0pKSxcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIGFjdGlvblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICBjYXNlIFwiYXBwbHlcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJ1bk1pZ3JhdGlvbnNTZXF1ZW50aWFsbHkoY29ubnMsIFwiYXBwbHlcIik7XG4gICAgICAgICAgY2FzZSBcInJvbGxiYWNrXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ydW5NaWdyYXRpb25zU2VxdWVudGlhbGx5KGNvbm5zLCBcInJvbGxiYWNrXCIpO1xuICAgICAgICB9XG4gICAgICB9KSgpO1xuXG4gICAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOnJlc3VsdFwiLCByZXN1bHQpO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgY29ubnMubWFwKCh7IGtuZXggfSkgPT4ge1xuICAgICAgICAgIHJldHVybiBrbmV4LmRlc3Ryb3koKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDsgq3soJwg6rCA64ql7ZWcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J287J2EIOqygOymne2VqeuLiOuLpC5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5zIOuniOydtOq3uOugiOydtOyFmCDsg4Htg5wg67Cw7Je0XG4gICAqIEBwYXJhbSBjb2RlTmFtZXMg7IKt7KCc7ZWgIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOydtOumhCDrsLDsl7RcbiAgICogQHJldHVybnMg7IKt7KCcIOqwgOuKpSDsl6zrtoAg67CPIOyggeyaqeuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoRcbiAgICovXG4gIHZhbGlkYXRlRGVsZXRhYmxlKGNvbm5zOiBNaWdyYXRpb25TdGF0dXNbXCJjb25uc1wiXSwgY29kZU5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGFwcGxpZWRDb2RlcyA9IGNvZGVOYW1lcy5maWx0ZXIoKGNvZGVOYW1lKSA9PlxuICAgICAgY29ubnMuc29tZSgoY29ubikgPT4gIWNvbm4ucGVuZGluZy5pbmNsdWRlcyhjb2RlTmFtZSkpLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2FuRGVsZXRlOiBhcHBsaWVkQ29kZXMubGVuZ3RoID09PSAwLFxuICAgICAgYXBwbGllZENvZGVzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICog66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzsnYQg7IKt7KCc7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZU5hbWVzIOyCreygnO2VoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoQg67Cw7Je0XG4gICAqIEByZXR1cm5zIOyCreygnOuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGRlbENvZGVzKGNvZGVOYW1lczogc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY29ubnMgfSA9IGF3YWl0IHRoaXMuZ2V0U3RhdHVzKCk7XG4gICAgY29uc3QgeyBjYW5EZWxldGUsIGFwcGxpZWRDb2RlcyB9ID0gdGhpcy52YWxpZGF0ZURlbGV0YWJsZShjb25ucywgY29kZU5hbWVzKTtcbiAgICBpZiAoIWNhbkRlbGV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgWW91IGNhbm5vdCBkZWxldGUgYSBtaWdyYXRpb24gZmlsZSBpZiB0aGVyZSBpcyBhbHJlYWR5IGFwcGxpZWQuIEFwcGxpZWQgY29kZXM6ICR7YXBwbGllZENvZGVzLmpvaW4oXCIsIFwiKX1gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VtKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNvZGVOYW1lcy5tYXAoYXN5bmMgKGNvZGVOYW1lKSA9PiB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBgJHtTb25hbXUuYXBpUm9vdFBhdGh9L3NyYy9taWdyYXRpb25zLyR7Y29kZU5hbWV9LnRzYDtcbiAgICAgICAgICBpZiAoYXdhaXQgZXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICAgICAgYXdhaXQgdW5saW5rKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGdlbkRhdGVUYWcoaW5kZXg6IG51bWJlciwgYmFzZURhdGU6IERhdGUgPSBuZXcgRGF0ZSgpKTogc3RyaW5nIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoYmFzZURhdGUuZ2V0VGltZSgpICsgaW5kZXggKiAxMDAwKTtcbiAgICBjb25zdCBwYWQgPSAobnVtOiBudW1iZXIsIHNpemU6IG51bWJlciA9IDIpID0+IG51bS50b1N0cmluZygpLnBhZFN0YXJ0KHNpemUsIFwiMFwiKTtcbiAgICByZXR1cm4gKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TW9udGgoKSArIDEpICtcbiAgICAgIHBhZChkYXRlLmdldERhdGUoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0SG91cnMoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TWludXRlcygpKSArXG4gICAgICBwYWQoZGF0ZS5nZXRTZWNvbmRzKCkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOydhCDsg53shLHtlanri4jri6QuXG4gICAqXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zIOyDneyEseuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGdlbmVyYXRlUHJlcGFyZWRDb2RlcygpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgcHJlcGFyZWRDb2RlcyB9ID0gYXdhaXQgdGhpcy5nZXRTdGF0dXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2VuZXJhdGVQcmVwYXJlZENvZGVzOnByZXBhcmVkQ29kZXNcIiwgcHJlcGFyZWRDb2Rlcyk7XG4gICAgaWYgKHByZXBhcmVkQ29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIlxcbu2YhOyerCDrqqjrkZAg7Iux7YGs65CcIOyDge2DnOyeheuLiOuLpC5cIikpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8g7Iuk7KCcIOy9lOuTnCDsg53shLFcbiAgICBjb25zdCBtaWdyYXRpb25zRGlyID0gYCR7U29uYW11LmFwaVJvb3RQYXRofS9zcmMvbWlncmF0aW9uc2A7XG5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgcGNvZGVdIG9mIHByZXBhcmVkQ29kZXMuZW50cmllcygpKSB7XG4gICAgICBpZiAocGNvZGUuZm9ybWF0dGVkKSB7XG4gICAgICAgIGNvbnN0IGRhdGVUYWcgPSB0aGlzLmdlbkRhdGVUYWcoaW5kZXgpO1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IGAke21pZ3JhdGlvbnNEaXJ9LyR7ZGF0ZVRhZ31fJHtwY29kZS50aXRsZX0udHNgO1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIHBjb2RlLmZvcm1hdHRlZCk7XG4gICAgICAgICFpc1Rlc3QoKSAmJiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgTUlHUkFUSU9OIENSRUFURUQgJHtmaWxlUGF0aH1gKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHByZXBhcmVkQ29kZXMubGVuZ3RoO1xuICB9XG5cbiAgYXN5bmMgY29tcGFyZU1pZ3JhdGlvbnMoY29tcGFyZURCOiBLbmV4KTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgICAvLyBFbnRpdHkg7Iic7ZqM7ZWY7JesIOyLse2BrFxuICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJQg7Y+s7ZWo7ZWY7JesIEVudGl0eeyXkOyEnCBNaWdyYXRpb25TZXQg7LaU7LacXG4gICAgY29uc3QgZW50aXR5U2V0c1dpdGhKb2luVGFibGUgPSBlbnRpdHlJZHNcbiAgICAgIC5maWx0ZXIoKGVudGl0eUlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkucHJvcHMubGVuZ3RoID4gMClcbiAgICAgIC5tYXAoKGVudGl0eUlkKSA9PiBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5KEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKSkpO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iU66eMIOy2lOy2nFxuICAgIGNvbnN0IGpvaW5UYWJsZXNXaXRoRHVwID0gZW50aXR5U2V0c1dpdGhKb2luVGFibGUuZmxhdE1hcCgoZW50aXR5U2V0KSA9PiBlbnRpdHlTZXQuam9pblRhYmxlcyk7XG4gICAgLy8g7KSR67O1IOygnOqxsCAo7KSR67O17J24IOqyveyasCBpbmRleGVz66W8IOuzke2VqSlcbiAgICBjb25zdCBqb2luVGFibGVzID0gT2JqZWN0LnZhbHVlcyhncm91cChqb2luVGFibGVzV2l0aER1cCwgKGp0KSA9PiBqdC50YWJsZSkpLm1hcCgodGFibGVzKSA9PiB7XG4gICAgICBhc3NlcnQodGFibGVzICE9PSB1bmRlZmluZWQsIFwidGFibGVzIGlzIHVuZGVmaW5lZFwiKTtcbiAgICAgIGlmICh0YWJsZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB0YWJsZXNbMF07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi50YWJsZXNbMF0sXG4gICAgICAgIGluZGV4ZXM6IHVuaXF1ZShcbiAgICAgICAgICB0YWJsZXMuZmxhdE1hcCgodCkgPT4gdC5pbmRleGVzKSxcbiAgICAgICAgICAoaW5kZXgpID0+IFtpbmRleC50eXBlLCAuLi5pbmRleC5jb2x1bW5zXS5qb2luKFwiLVwiKSxcbiAgICAgICAgKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJQg7Y+s7ZWo7ZWY7JesIE1pZ3JhdGlvblNldCDrsLDsl7RcbiAgICBjb25zdCBlbnRpdHlTZXRzOiBNaWdyYXRpb25TZXRbXSA9IFsuLi5lbnRpdHlTZXRzV2l0aEpvaW5UYWJsZSwgLi4uam9pblRhYmxlc107XG5cbiAgICBjb25zdCBjb2RlczogR2VuTWlncmF0aW9uQ29kZVtdID0gKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGVudGl0eVNldHMubWFwKGFzeW5jIChlbnRpdHlTZXQpID0+IHtcbiAgICAgICAgICBjb25zdCBkYlNldCA9IGF3YWl0IFBvc3RncmVTUUxTY2hlbWFSZWFkZXIuZ2V0TWlncmF0aW9uU2V0RnJvbURCKFxuICAgICAgICAgICAgY29tcGFyZURCLFxuICAgICAgICAgICAgZW50aXR5U2V0LnRhYmxlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgTmFpdGUudChgbWlncmF0b3I6Y29tcGFyZU1pZ3JhdGlvbnM6ZW50aXR5U2V0OiR7ZW50aXR5U2V0LnRhYmxlfWAsIGVudGl0eVNldCk7XG4gICAgICAgICAgTmFpdGUudChgbWlncmF0b3I6Y29tcGFyZU1pZ3JhdGlvbnM6ZGJTZXQ6JHtlbnRpdHlTZXQudGFibGV9YCwgZGJTZXQpO1xuXG4gICAgICAgICAgaWYgKGRiU2V0ID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyDquLDsobQg7YWM7J2067iUIOyXhuydjCwg7IOI66GcIO2FjOydtOu4lCDsg53shLFcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBnZW5lcmF0ZUNyZWF0ZUNvZGUoZW50aXR5U2V0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8g6riw7KG0IO2FjOydtOu4lCDsobTsnqztlZjripQg7LyA7J207IqkXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2VuZXJhdGVBbHRlckNvZGUoZW50aXR5U2V0LCBkYlNldCwgY29tcGFyZURCKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgKVxuICAgICkuZmxhdCgpO1xuXG4gICAgLy8gbm9ybWFsIO2DgOyeheydtCDslZ7snLzroZwsIGZvcmVpZ27snbQg65Kk66GcXG4gICAgY29kZXMuc29ydCgoY29kZUEsIGNvZGVCKSA9PiB7XG4gICAgICBpZiAoY29kZUEudHlwZSA9PT0gXCJmb3JlaWduXCIgJiYgY29kZUIudHlwZSA9PT0gXCJub3JtYWxcIikge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0gZWxzZSBpZiAoY29kZUEudHlwZSA9PT0gXCJub3JtYWxcIiAmJiBjb2RlQi50eXBlID09PSBcImZvcmVpZ25cIikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBjb2RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTaGFkb3cgREIg7YWM7Iqk7Yq466W8IOynhO2Wie2VqeuLiOuLpC5cbiAgICpcbiAgICogU29uYW11IFVJ7JeQ7IScIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQHJldHVybnMgU2hhZG93IERCIO2FjOyKpO2KuCDqsrDqs7xcbiAgICovXG4gIGFzeW5jIHJ1blNoYWRvd1Rlc3QoKTogUHJvbWlzZTxNaWdyYXRpb25SZXN1bHQ+IHtcbiAgICBjb25zdCB0ZGJDb25uID0gU29uYW11LmRiQ29uZmlnLnRlc3QuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZztcbiAgICBjb25zdCBzaGFkb3dEYXRhYmFzZSA9IGAke3RkYkNvbm4uZGF0YWJhc2V9X19taWdyYXRpb25fc2hhZG93YDtcblxuICAgIC8vIO2FjOyKpO2KuCDsg4Htmansl5DshJzripQg7Yq4656c7J6t7IWY7J2EIOy0iOq4sO2ZlO2VmOqzoCwg7IOIIOuNsOydtO2EsOuyoOydtOyKpCDsu6TrhKXshZjsnYQg6rCA7KC47JmA7JW8IO2VqFxuICAgIGlmIChpc1Rlc3QoKSkge1xuICAgICAgYXdhaXQgREIuY2xlYXJUZXN0VHJhbnNhY3Rpb24oKTtcbiAgICAgIC8vIOuzkeugrCDthYzsiqTtirgg66qo65Oc7JeQ7ISc64qUIHdvcmtlciBEQiDsl7DqsrAg7Jyg7KeAXG4gICAgICBpZiAocHJvY2Vzcy5lbnYuU09OQU1VX1dPUktFUl9EQiAhPT0gXCJ0cnVlXCIpIHtcbiAgICAgICAgYXdhaXQgREIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOq4sOyhtCBTaGFkb3cgREIg7IKt7KCcIO2bhCBTaGFkb3cgREIg7IOd7ISxXG4gICAgY29uc3QgdGRiID0gY3JlYXRlS25leEluc3RhbmNlKFNvbmFtdS5kYkNvbmZpZy50ZXN0KTtcbiAgICB0cnkge1xuICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoYCR7c2hhZG93RGF0YWJhc2V9IOyCreygnGApKTtcbiAgICAgIGF3YWl0IHRkYi5yYXcoYERST1AgREFUQUJBU0UgSUYgRVhJU1RTICR7c2hhZG93RGF0YWJhc2V9YCk7XG4gICAgICBhd2FpdCB0ZGIucmF3KGBcbiAgICAgICAgU0VMRUNUIHBnX3Rlcm1pbmF0ZV9iYWNrZW5kKHBnX3N0YXRfYWN0aXZpdHkucGlkKVxuICAgICAgICBGUk9NIHBnX3N0YXRfYWN0aXZpdHlcbiAgICAgICAgV0hFUkUgZGF0bmFtZSA9ICcke3RkYkNvbm4uZGF0YWJhc2V9J1xuICAgICAgICAgIEFORCBwaWQgPD4gcGdfYmFja2VuZF9waWQoKTtcbiAgICAgIGApO1xuICAgICAgYXdhaXQgdGRiLnJhdyhgQ1JFQVRFIERBVEFCQVNFICR7c2hhZG93RGF0YWJhc2V9IFRFTVBMQVRFICR7dGRiQ29ubi5kYXRhYmFzZX1gKTtcblxuICAgICAgLy8gU2hhZG93IERC7JeQIOyXsOqysFxuICAgICAgY29uc3Qgc2RiID0gY3JlYXRlS25leEluc3RhbmNlKHtcbiAgICAgICAgLi4uU29uYW11LmRiQ29uZmlnLnRlc3QsXG4gICAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgICAuLi50ZGJDb25uLFxuICAgICAgICAgIGRhdGFiYXNlOiBzaGFkb3dEYXRhYmFzZSxcbiAgICAgICAgICBwYXNzd29yZDogdGRiQ29ubi5wYXNzd29yZCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBzaGFkb3cgREIg7YWM7Iqk7Yq4IOynhO2WiVxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgW2JhdGNoTm8sIGFwcGxpZWRdID0gYXdhaXQgc2RiLm1pZ3JhdGUubGF0ZXN0KCk7XG4gICAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKFwiU2hhZG93IERCIO2FjOyKpO2KuOyXkCDshLHqs7XtlojsirXri4jri6QhXCIpLCB7XG4gICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvbm5LZXk6IFwic2hhZG93XCIsXG4gICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB0aHJvdyBuZXcgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uKFNEKFwic29uYW11LmVycm9yLnNoYWRvd0RiVGVzdEZhaWxlZFwiKSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBzZGIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICAvLyBTaGFkb3cgREIg7IKt7KCcXG4gICAgICAhaXNUZXN0KCkgJiYgY29uc29sZS5sb2coY2hhbGsubWFnZW50YShgJHtzaGFkb3dEYXRhYmFzZX0g7IKt7KCcYCkpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGRiLnJhdyhgRFJPUCBEQVRBQkFTRSBJRiBFWElTVFMgJHtzaGFkb3dEYXRhYmFzZX1gKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlNoYWRvdyBEQiDsoJXrpqwg7Iuk7YyoOlwiLCBlKTsgLy8g7J206rKMIOyXhuycvOuptCDsobDsmqntnogg64iE7IiYXG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCB0ZGIuZGVzdHJveSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBUXVDO1VBQ0g7WUFFa0I7VUFDdEI7c0JBQ3lCO3FCQUNpQjthQUNuQztrQkFFTTtnQkFDRjt1QkFDK0I7cUJBQ2Q7Z0NBQ1E7Q0FTdkQsV0FBYixNQUFzQjtFQUNwQixNQUFjLDBCQUNaLE9BQ0EsUUFDMEI7R0FDMUIsTUFBTUEsVUFBMkIsRUFBRTtBQUVuQyxRQUFLLE1BQU0sRUFBRSxTQUFTLFVBQVUsT0FBTztJQUNyQyxNQUFNLENBQUMsU0FBUyxXQUNkLFdBQVcsVUFBVSxNQUFNLEtBQUssUUFBUSxRQUFRLEdBQUcsTUFBTSxLQUFLLFFBQVEsVUFBVTtBQUVsRixZQUFRLEtB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
|