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,393 +1,372 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { Sonamu } from "../api/
|
|
5
|
-
import { EntityManager } from "../entity/entity-manager.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
/**
|
|
14
|
-
* 모든 Model 클래스의 기본 클래스
|
|
15
|
-
*
|
|
16
|
-
* @template TSubsetKey - 서브셋 키 유니온 (예: "A" | "P" | "SS")
|
|
17
|
-
* @template TSubsetMapping - 서브셋별 최종 결과 타입 매핑
|
|
18
|
-
* @template TSubsetQueries - 서브셋 쿼리 함수 객체
|
|
19
|
-
* @template TLoaderQueries - 서브셋별 로더 쿼리 배열 객체
|
|
20
|
-
*/ export class BaseModelClass {
|
|
21
|
-
modelName;
|
|
22
|
-
subsetQueries;
|
|
23
|
-
loaderQueries;
|
|
24
|
-
logger;
|
|
25
|
-
constructor(modelName = this.constructor.name, subsetQueries, loaderQueries){
|
|
26
|
-
this.modelName = modelName;
|
|
27
|
-
this.subsetQueries = subsetQueries;
|
|
28
|
-
this.loaderQueries = loaderQueries;
|
|
29
|
-
this.logger = getLogger(convertDomainToCategory(this.modelName, "model"));
|
|
30
|
-
}
|
|
31
|
-
getDB(which) {
|
|
32
|
-
return DB.getDB(which);
|
|
33
|
-
}
|
|
34
|
-
getPuri(which) {
|
|
35
|
-
// 트랜잭션 컨텍스트에서 트랜잭션 획득
|
|
36
|
-
const trx = DB.getTransactionContext().getTransaction(which);
|
|
37
|
-
if (trx) {
|
|
38
|
-
return trx;
|
|
39
|
-
}
|
|
40
|
-
// 트랜잭션이 없으면 새로운 PuriWrapper 반환
|
|
41
|
-
const db = this.getDB(which);
|
|
42
|
-
return new PuriWrapper(db, new UpsertBuilder());
|
|
43
|
-
}
|
|
44
|
-
async destroy() {
|
|
45
|
-
return DB.destroy();
|
|
46
|
-
}
|
|
47
|
-
async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
|
|
48
|
-
if (!wdb) {
|
|
49
|
-
wdb = this.getDB("w");
|
|
50
|
-
}
|
|
51
|
-
let unqKeys;
|
|
52
|
-
let whereInField;
|
|
53
|
-
let selectField;
|
|
54
|
-
if (unqKeyFields.length > 1) {
|
|
55
|
-
whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
|
|
56
|
-
selectField = `${whereInField} as tmpUid`;
|
|
57
|
-
unqKeys = rows.map((row)=>unqKeyFields.map((field)=>row[field]).join("_"));
|
|
58
|
-
} else {
|
|
59
|
-
whereInField = unqKeyFields[0];
|
|
60
|
-
selectField = unqKeyFields[0];
|
|
61
|
-
unqKeys = rows.map((row)=>row[unqKeyFields[0]]);
|
|
62
|
-
}
|
|
63
|
-
let resultIds = [];
|
|
64
|
-
for (const items of chunk(unqKeys, chunkSize)){
|
|
65
|
-
const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
|
|
66
|
-
resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(String(dbRow.id))));
|
|
67
|
-
}
|
|
68
|
-
return resultIds;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* 특정 서브셋에 대한 쿼리 빌더 획득
|
|
72
|
-
*
|
|
73
|
-
* @returns qb - 쿼리 빌더 (조건 추가용)
|
|
74
|
-
* @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
|
|
75
|
-
*/ getSubsetQueries(subset) {
|
|
76
|
-
if (!this.subsetQueries) {
|
|
77
|
-
throw new Error("subsetQueries is not defined");
|
|
78
|
-
}
|
|
79
|
-
const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
|
|
80
|
-
const qb = this.subsetQueries[subset]?.(puriWrapper);
|
|
81
|
-
return {
|
|
82
|
-
qb: qb,
|
|
83
|
-
onSubset: (_subset)=>qb
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Enhancer 객체 생성 헬퍼
|
|
88
|
-
* 타입 검증 및 추론을 도와줌
|
|
89
|
-
*/ createEnhancers(enhancers) {
|
|
90
|
-
return enhancers;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* 서브셋 쿼리 실행
|
|
94
|
-
*
|
|
95
|
-
* 1. Sonamu 필터 적용 (타입 변환 포함)
|
|
96
|
-
* 2. 쿼리 실행 (pagination 적용)
|
|
97
|
-
* 3. 로더 실행 (1:N, N:M 관계 데이터 로딩)
|
|
98
|
-
* 4. Hydrate (flat → 중첩 객체)
|
|
99
|
-
* 5. Enhancer 적용 (virtual 필드 계산)
|
|
100
|
-
*/ async executeSubsetQuery(params) {
|
|
101
|
-
const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
|
|
102
|
-
if (!this.loaderQueries) {
|
|
103
|
-
throw new Error("loaderQueries is not defined");
|
|
104
|
-
}
|
|
105
|
-
// Sonamu Filter 적용
|
|
106
|
-
if (queryParams.sonamuFilter) {
|
|
107
|
-
const normalizedFilter = normalizeFilterQuery(queryParams.sonamuFilter);
|
|
108
|
-
this.applySonamuFilters(qb, normalizedFilter);
|
|
109
|
-
}
|
|
110
|
-
const { num, page } = queryParams;
|
|
111
|
-
// COUNT 쿼리 실행 (queryMode: list일 때는 0 리턴)
|
|
112
|
-
const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
|
|
113
|
-
if (queryParams?.queryMode === "count") {
|
|
114
|
-
return {
|
|
115
|
-
total
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
// LIST 쿼리 실행
|
|
119
|
-
const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
|
|
120
|
-
// Enhancer 적용
|
|
121
|
-
const enhancer = params.enhancers?.[subset];
|
|
122
|
-
const enhancedRows = await Promise.all(computedRows.map((row)=>enhancer?.(row) ?? row));
|
|
123
|
-
// Internal 필드 제거
|
|
124
|
-
const entity = EntityManager.get(this.modelName);
|
|
125
|
-
const internalFields = entity.subsetsInternal[subset] ?? [];
|
|
126
|
-
const rows = internalFields.length > 0 ? enhancedRows.map((row)=>this.omitInternalFields(row, internalFields)) : enhancedRows;
|
|
127
|
-
if (queryParams.queryMode === "list") {
|
|
128
|
-
// 리스트만 리턴
|
|
129
|
-
return {
|
|
130
|
-
rows
|
|
131
|
-
};
|
|
132
|
-
} else {
|
|
133
|
-
// 둘다 리턴
|
|
134
|
-
return {
|
|
135
|
-
rows,
|
|
136
|
-
total
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* 객체에서 internal 필드 제거
|
|
142
|
-
* 중첩 필드(예: "user.email") 및 배열(예: "employees.salary")도 처리
|
|
143
|
-
*/ omitInternalFields(row, fields) {
|
|
144
|
-
const result = cloneDeep(row);
|
|
145
|
-
for (const field of fields){
|
|
146
|
-
this.deleteField(result, field.split("."));
|
|
147
|
-
}
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* FilterQuery를 Puri QueryBuilder에 적용
|
|
152
|
-
*
|
|
153
|
-
* @param qb Puri QueryBuilder 인스턴스
|
|
154
|
-
* @param filters FilterQuery 객체
|
|
155
|
-
*/ applySonamuFilters(qb, filters) {
|
|
156
|
-
if (!filters) return;
|
|
157
|
-
const entity = EntityManager.get(this.modelName);
|
|
158
|
-
// 1. 필터 검증 (Entity 기반)
|
|
159
|
-
validateSonamuFilters(filters, entity);
|
|
160
|
-
// 2. 검증된 필터 적용
|
|
161
|
-
const puri = qb;
|
|
162
|
-
for (const [field, condition] of Object.entries(filters)){
|
|
163
|
-
if (condition === undefined || condition === null) continue;
|
|
164
|
-
// 테이블명.필드명 형식으로 변환
|
|
165
|
-
const fullField = entity.getFullFieldName(field);
|
|
166
|
-
// 직접 값 (eq와 동일)
|
|
167
|
-
if (typeof condition !== "object" || Array.isArray(condition)) {
|
|
168
|
-
puri.where(fullField, condition);
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
// 연산자 객체
|
|
172
|
-
for (const [operator, value] of Object.entries(condition)){
|
|
173
|
-
this.applyOperator(qb, fullField, operator, value);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* 단일 연산자를 QueryBuilder에 적용
|
|
179
|
-
*/ applyOperator(qb, field, operator, value) {
|
|
180
|
-
const puri = qb;
|
|
181
|
-
switch(operator){
|
|
182
|
-
case "eq":
|
|
183
|
-
puri.where(field, value);
|
|
184
|
-
break;
|
|
185
|
-
case "ne":
|
|
186
|
-
puri.where(field, "!=", value);
|
|
187
|
-
break;
|
|
188
|
-
case "gt":
|
|
189
|
-
puri.where(field, ">", value);
|
|
190
|
-
break;
|
|
191
|
-
case "gte":
|
|
192
|
-
puri.where(field, ">=", value);
|
|
193
|
-
break;
|
|
194
|
-
case "lt":
|
|
195
|
-
puri.where(field, "<", value);
|
|
196
|
-
break;
|
|
197
|
-
case "lte":
|
|
198
|
-
puri.where(field, "<=", value);
|
|
199
|
-
break;
|
|
200
|
-
case "in":
|
|
201
|
-
puri.whereIn(field, value);
|
|
202
|
-
break;
|
|
203
|
-
case "notIn":
|
|
204
|
-
puri.whereNotIn(field, value);
|
|
205
|
-
break;
|
|
206
|
-
case "contains":
|
|
207
|
-
puri.where(field, "like", `%${value}%`);
|
|
208
|
-
break;
|
|
209
|
-
case "startsWith":
|
|
210
|
-
puri.where(field, "like", `${value}%`);
|
|
211
|
-
break;
|
|
212
|
-
case "endsWith":
|
|
213
|
-
puri.where(field, "like", `%${value}`);
|
|
214
|
-
break;
|
|
215
|
-
case "isNull":
|
|
216
|
-
puri.where(field, null);
|
|
217
|
-
break;
|
|
218
|
-
case "isNotNull":
|
|
219
|
-
puri.where(field, "!=", null);
|
|
220
|
-
break;
|
|
221
|
-
case "before":
|
|
222
|
-
puri.where(field, "<", value);
|
|
223
|
-
break;
|
|
224
|
-
case "after":
|
|
225
|
-
puri.where(field, ">", value);
|
|
226
|
-
break;
|
|
227
|
-
case "between":
|
|
228
|
-
{
|
|
229
|
-
if (Array.isArray(value) && value.length === 2) {
|
|
230
|
-
const [min, max] = value;
|
|
231
|
-
puri.where(field, ">=", min).where(field, "<=", max);
|
|
232
|
-
}
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
default:
|
|
236
|
-
console.warn(`Unsupported operator: ${operator}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* 중첩 필드 삭제 (배열 내 객체도 처리)
|
|
241
|
-
*/ deleteField(obj, parts) {
|
|
242
|
-
if (!obj || typeof obj !== "object") {
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
if (parts.length === 1) {
|
|
246
|
-
if (Array.isArray(obj)) {
|
|
247
|
-
obj.forEach((item)=>{
|
|
248
|
-
if (item && typeof item === "object") {
|
|
249
|
-
delete item[parts[0]];
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
} else {
|
|
253
|
-
delete obj[parts[0]];
|
|
254
|
-
}
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
const [first, ...rest] = parts;
|
|
258
|
-
const next = obj[first];
|
|
259
|
-
if (Array.isArray(next)) {
|
|
260
|
-
next.map((item)=>this.deleteField(item, rest));
|
|
261
|
-
} else if (next && typeof next === "object") {
|
|
262
|
-
this.deleteField(next, rest);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* COUNT 쿼리 실행 (내부 메서드)
|
|
267
|
-
*/ async executeCountQuery(qb, params, debug, optimizeCountQuery) {
|
|
268
|
-
if (params.queryMode === "list") {
|
|
269
|
-
return 0;
|
|
270
|
-
}
|
|
271
|
-
const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
|
|
272
|
-
if (optimizeCountQuery) {
|
|
273
|
-
const { default: SqlParser } = await import("node-sql-parser");
|
|
274
|
-
const parser = new SqlParser.Parser();
|
|
275
|
-
const parsedQuery = parser.astify(countPuri.toQuery(), {
|
|
276
|
-
database: Sonamu.config.database.database
|
|
277
|
-
});
|
|
278
|
-
const leftJoinTables = getJoinTables(parsedQuery, [
|
|
279
|
-
"LEFT JOIN"
|
|
280
|
-
]);
|
|
281
|
-
const whereTables = getTableNamesFromWhere(parsedQuery);
|
|
282
|
-
const tablesToRemove = leftJoinTables.filter((j)=>!whereTables.includes(j));
|
|
283
|
-
tablesToRemove.forEach((table)=>{
|
|
284
|
-
countPuri.clearJoin(table);
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
// COUNT(*)로 전체 레코드 수를 계산
|
|
288
|
-
// TODO: qb의 DISTINCT가 있는 경우 처리해야 함
|
|
289
|
-
const countResult = await countPuri.clear("select").select({
|
|
290
|
-
total: Puri.rawNumber(`COUNT(*)::integer`)
|
|
291
|
-
}).first();
|
|
292
|
-
if (debug) {
|
|
293
|
-
countPuri.debug();
|
|
294
|
-
}
|
|
295
|
-
return countResult?.total ?? 0;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* LIST 쿼리 실행 (내부 메서드)
|
|
299
|
-
*/ async executeListQuery(subset, qb, params, num, page, debug) {
|
|
300
|
-
if (params.queryMode === "count") {
|
|
301
|
-
return [];
|
|
302
|
-
}
|
|
303
|
-
const limitedQb = (()=>{
|
|
304
|
-
if (num === 0) {
|
|
305
|
-
return qb;
|
|
306
|
-
} else {
|
|
307
|
-
return qb.limit(num).offset(num * (page - 1));
|
|
308
|
-
}
|
|
309
|
-
})();
|
|
310
|
-
let unloadedRows = await limitedQb;
|
|
311
|
-
if (debug) {
|
|
312
|
-
qb.debug();
|
|
313
|
-
}
|
|
314
|
-
// 로더 처리
|
|
315
|
-
const loaders = this.loaderQueries[subset];
|
|
316
|
-
if (loaders && Array.isArray(loaders)) {
|
|
317
|
-
unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
|
|
318
|
-
}
|
|
319
|
-
return this.hydrate(unloadedRows);
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* 재귀적 로더 처리
|
|
323
|
-
*/ async processLoaders(rows, loaders, debug) {
|
|
324
|
-
for (const resolveLoader of loaders){
|
|
325
|
-
const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
|
|
326
|
-
const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row)=>row[refId]));
|
|
327
|
-
if (debug) {
|
|
328
|
-
resolveLoaderQb.debug();
|
|
329
|
-
}
|
|
330
|
-
let loadedRows = await resolveLoaderQb;
|
|
331
|
-
// 중첩 loaders가 있으면 재귀 처리
|
|
332
|
-
if (nestedLoaders && nestedLoaders.length > 0) {
|
|
333
|
-
loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
|
|
334
|
-
}
|
|
335
|
-
const subRowGroups = group(loadedRows, (row)=>row.refId);
|
|
336
|
-
rows = rows.map((row)=>{
|
|
337
|
-
row[as] = (subRowGroups[row[refId]] ?? []).map((r)=>omit(r, [
|
|
338
|
-
"refId"
|
|
339
|
-
]));
|
|
340
|
-
return row;
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
return rows;
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Flat 레코드를 중첩 객체로 변환
|
|
347
|
-
*
|
|
348
|
-
* - `user__name` → `{ user: { name } }`
|
|
349
|
-
* - nullable relation의 경우 id 필드가 null이면 객체 자체를 null로
|
|
350
|
-
*/ hydrate(rows) {
|
|
351
|
-
return rows.map((row)=>{
|
|
352
|
-
// nullable relation 처리: 그룹의 id 필드가 null이면 객체 전체를 null로
|
|
353
|
-
const nestedKeys = Object.keys(row).filter((key)=>key.includes("__"));
|
|
354
|
-
const groups = Object.groupBy(nestedKeys, (key)=>key.split("__")[0]);
|
|
355
|
-
// id 필드가 null인 그룹 찾기 (예: parent__id가 null이면 parent 그룹 전체가 null)
|
|
356
|
-
const nullKeys = Object.entries(groups).filter(([groupKey, fields])=>{
|
|
357
|
-
if (!fields || fields.length === 0) return false;
|
|
358
|
-
// 그룹의 id 필드 찾기 (예: "parent__id")
|
|
359
|
-
const idField = `${groupKey}__id`;
|
|
360
|
-
if (idField in row) {
|
|
361
|
-
// id 필드가 null이면 객체 전체가 null
|
|
362
|
-
return row[idField] === null;
|
|
363
|
-
}
|
|
364
|
-
// id 필드가 없으면 기존 로직: 모든 필드가 null인지 확인
|
|
365
|
-
return fields.every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0);
|
|
366
|
-
}).map(([key])=>key);
|
|
367
|
-
const hydrated = Object.keys(row).reduce((r, field)=>{
|
|
368
|
-
if (!field.includes("__")) {
|
|
369
|
-
// 일반 필드: 배열 내 객체면 재귀 hydrate
|
|
370
|
-
if (Array.isArray(row[field]) && isObject(row[field][0])) {
|
|
371
|
-
r[field] = this.hydrate(row[field]);
|
|
372
|
-
} else {
|
|
373
|
-
r[field] = row[field];
|
|
374
|
-
}
|
|
375
|
-
return r;
|
|
376
|
-
}
|
|
377
|
-
// 중첩 필드 처리: user__name → user[name]
|
|
378
|
-
const parts = field.split("__");
|
|
379
|
-
const objPath = parts[0] + parts.slice(1).map((part)=>`[${part}]`).join("");
|
|
380
|
-
r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
|
|
381
|
-
return r;
|
|
382
|
-
}, {});
|
|
383
|
-
// null relation 처리
|
|
384
|
-
nullKeys.forEach((nullKey)=>{
|
|
385
|
-
hydrated[nullKey] = null;
|
|
386
|
-
});
|
|
387
|
-
return hydrated;
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
export const BaseModel = new BaseModelClass();
|
|
1
|
+
import { __esmMin } from "../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { convertDomainToCategory, init_category } from "../logger/category.js";
|
|
3
|
+
import { DB, init_db } from "./db.js";
|
|
4
|
+
import { Sonamu, init_sonamu } from "../api/sonamu.js";
|
|
5
|
+
import { EntityManager, init_entity_manager } from "../entity/entity-manager.js";
|
|
6
|
+
import { UpsertBuilder, init_upsert_builder } from "./upsert-builder.js";
|
|
7
|
+
import { init_utils, normalizeFilterQuery, validateSonamuFilters } from "../filter/utils.js";
|
|
8
|
+
import { getJoinTables, getTableNamesFromWhere, init_sql_parser } from "../utils/sql-parser.js";
|
|
9
|
+
import { Puri, init_puri } from "./puri.js";
|
|
10
|
+
import { PuriWrapper, init_puri_wrapper } from "./puri-wrapper.js";
|
|
11
|
+
import { getLogger } from "@logtape/logtape";
|
|
12
|
+
import { cloneDeep, cluster, group, isObject, omit, set } from "radashi";
|
|
392
13
|
|
|
393
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBiaW9tZS1pZ25vcmUtYWxsIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiBQdXJp7J2YIO2DgOyeheydgCDqsJzrs4Qg66qo64247JeQ7IScIO2ZleygleuQmOuvgOuhnCBCYXNlTW9kZWzsl5DshJzripQgYW5566W8IO2XiOyaqe2VqCAqL1xuaW1wb3J0IHsgZ2V0TG9nZ2VyLCB0eXBlIExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCI7XG5pbXBvcnQgdHlwZSB7IEtuZXggfSBmcm9tIFwia25leFwiO1xuaW1wb3J0IHsgY2xvbmVEZWVwLCBncm91cCwgaXNPYmplY3QsIG9taXQsIHNldCB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyB0eXBlIExpc3RSZXN1bHQsIG5vcm1hbGl6ZUZpbHRlclF1ZXJ5LCB2YWxpZGF0ZVNvbmFtdUZpbHRlcnMgfSBmcm9tIFwiLi5cIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IEVudGl0eU1hbmFnZXIgfSBmcm9tIFwiLi4vZW50aXR5L2VudGl0eS1tYW5hZ2VyXCI7XG5pbXBvcnQgdHlwZSB7IEZpbHRlck9wZXJhdG9yLCBGaWx0ZXJRdWVyeSB9IGZyb20gXCIuLi9maWx0ZXIvdHlwZXNcIjtcbmltcG9ydCB7IGNvbnZlcnREb21haW5Ub0NhdGVnb3J5IH0gZnJvbSBcIi4uL2xvZ2dlci9jYXRlZ29yeVwiO1xuaW1wb3J0IHR5cGUgeyBEYXRhYmFzZVNjaGVtYUV4dGVuZCwgU29uYW11UXVlcnlNb2RlIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBnZXRKb2luVGFibGVzLCBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlIH0gZnJvbSBcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIjtcbmltcG9ydCB7IGNodW5rIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IEVuaGFuY2VyTWFwLCBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uIH0gZnJvbSBcIi4vYmFzZS1tb2RlbC50eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBEQlByZXNldCB9IGZyb20gXCIuL2RiXCI7XG5pbXBvcnQgeyBEQiB9IGZyb20gXCIuL2RiXCI7XG5pbXBvcnQgeyBQdXJpIH0gZnJvbSBcIi4vcHVyaVwiO1xuaW1wb3J0IHR5cGUgeyBVbmlvbkV4dHJhY3RlZFRUYWJsZXMgfSBmcm9tIFwiLi9wdXJpLnR5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IEluZmVyQWxsU3Vic2V0cywgUHVyaUxvYWRlclF1ZXJpZXMsIFB1cmlTdWJzZXRGbiB9IGZyb20gXCIuL3B1cmktc3Vic2V0LnR5cGVzXCI7XG5pbXBvcnQgeyBQdXJpV3JhcHBlciB9IGZyb20gXCIuL3B1cmktd3JhcHBlclwiO1xuaW1wb3J0IHsgVXBzZXJ0QnVpbGRlciB9IGZyb20gXCIuL3Vwc2VydC1idWlsZGVyXCI7XG5cbnR5cGUgVW5rbm93bkRCUmVjb3JkID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbi8qKlxuICog66qo65OgIE1vZGVsIO2BtOuemOyKpOydmCDquLDrs7gg7YG0656Y7IqkXG4gKlxuICogQHRlbXBsYXRlIFRTdWJzZXRLZXkgLSDshJzruIzshYsg7YKkIOycoOuLiOyYqCAo7JiIOiBcIkFcIiB8IFwiUFwiIHwgXCJTU1wiKVxuICogQHRlbXBsYXRlIFRTdWJzZXRNYXBwaW5nIC0g7ISc67iM7IWL67OEIOy1nOyihSDqsrDqs7wg7YOA7J6FIOunpO2VkVxuICogQHRlbXBsYXRlIFRTdWJzZXRRdWVyaWVzIC0g7ISc67iM7IWLIOy/vOumrCDtlajsiJgg6rCd7LK0XG4gKiBAdGVtcGxhdGUgVExvYWRlclF1ZXJpZXMgLSDshJzruIzshYvrs4Qg66Gc642UIOy/vOumrCDrsLDsl7Qg6rCd7LK0XG4gKi9cbmV4cG9ydCBjbGFzcyBCYXNlTW9kZWxDbGFzczxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyA9IG5ldmVyLFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBuZXZlcixcbiAgVFN1YnNldFF1ZXJpZXMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgUHVyaVN1YnNldEZuPiA9IG5ldmVyLFxuICBUTG9hZGVyUXVlcmllcyBleHRlbmRzIFB1cmlMb2FkZXJRdWVyaWVzPFRTdWJzZXRLZXk+ID0gbmV2ZXIsXG4+IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZ2dlcjogTG9nZ2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBtb2RlbE5hbWU6IHN0cmluZyA9IHRoaXMuY29uc3RydWN0b3IubmFtZSxcbiAgICBwcm90ZWN0ZWQgc3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzLFxuICAgIHByb3RlY3RlZCBsb2FkZXJRdWVyaWVzPzogVExvYWRlclF1ZXJpZXMsXG4gICkge1xuICAgIHRoaXMubG9nZ2VyID0gZ2V0TG9nZ2VyKGNvbnZlcnREb21haW5Ub0NhdGVnb3J5KHRoaXMubW9kZWxOYW1lLCBcIm1vZGVsXCIpKTtcbiAgfVxuXG4gIGdldERCKHdoaWNoOiBEQlByZXNldCk6IEtuZXgge1xuICAgIHJldHVybiBEQi5nZXREQih3aGljaCk7XG4gIH1cblxuICBnZXRQdXJpKHdoaWNoOiBEQlByZXNldCk6IFB1cmlXcmFwcGVyIHtcbiAgICAvLyDtirjrnpzsnq3shZgg7Luo7YWN7Iqk7Yq47JeQ7IScIO2KuOuenOyereyFmCDtmo3rk51cbiAgICBjb25zdCB0cnggPSBEQi5nZXRUcmFuc2FjdGlvbkNvbnRleHQoKS5nZXRUcmFuc2FjdGlvbih3aGljaCk7XG4gICAgaWYgKHRyeCkge1xuICAgICAgcmV0dXJuIHRyeDtcbiAgICB9XG5cbiAgICAvLyDtirjrnpzsnq3shZjsnbQg7JeG7Jy866m0IOyDiOuhnOyatCBQdXJpV3JhcHBlciDrsJjtmZhcbiAgICBjb25zdCBkYiA9IHRoaXMuZ2V0REIod2hpY2gpO1xuICAgIHJldHVybiBuZXcgUHVyaVdyYXBwZXIoZGIsIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICB9XG5cbiAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICByZXR1cm4gREIuZGVzdHJveSgpO1xuICB9XG5cbiAgYXN5bmMgZ2V0SW5zZXJ0ZWRJZHMoXG4gICAgd2RiOiBLbmV4LFxuICAgIHJvd3M6IFVua25vd25EQlJlY29yZFtdLFxuICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgIHVucUtleUZpZWxkczogc3RyaW5nW10sXG4gICAgY2h1bmtTaXplOiBudW1iZXIgPSA1MDAsXG4gICkge1xuICAgIGlmICghd2RiKSB7XG4gICAgICB3ZGIgPSB0aGlzLmdldERCKFwid1wiKTtcbiAgICB9XG5cbiAgICBsZXQgdW5xS2V5czogc3RyaW5nW107XG4gICAgbGV0IHdoZXJlSW5GaWVsZDogc3RyaW5nIHwgS25leC5SYXc7XG4gICAgbGV0IHNlbGVjdEZpZWxkOiBzdHJpbmc7XG5cbiAgICBpZiAodW5xS2V5RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHdkYi5yYXcoYENPTkNBVF9XUygnXycsICcke3VucUtleUZpZWxkcy5qb2luKFwiLFwiKX0nKWApO1xuICAgICAgc2VsZWN0RmllbGQgPSBgJHt3aGVyZUluRmllbGR9IGFzIHRtcFVpZGA7XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT4gdW5xS2V5RmllbGRzLm1hcCgoZmllbGQpID0+IHJvd1tmaWVsZF0pLmpvaW4oXCJfXCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hlcmVJbkZpZWxkID0gdW5xS2V5RmllbGRzWzBdO1xuICAgICAgc2VsZWN0RmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT4gcm93W3VucUtleUZpZWxkc1swXV0gYXMgc3RyaW5nKTtcbiAgICB9XG5cbiAgICBsZXQgcmVzdWx0SWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaXRlbXMgb2YgY2h1bmsodW5xS2V5cywgY2h1bmtTaXplKSkge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQgYXMgc3RyaW5nLCBpdGVtcyk7XG4gICAgICByZXN1bHRJZHMgPSByZXN1bHRJZHMuY29uY2F0KFxuICAgICAgICBkYlJvd3MubWFwKChkYlJvdzogVW5rbm93bkRCUmVjb3JkKSA9PiBwYXJzZUludChTdHJpbmcoZGJSb3cuaWQpKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRJZHM7XG4gIH1cblxuICAvKipcbiAgICog7Yq57KCVIOyEnOu4jOyFi+yXkCDrjIDtlZwg7L+866asIOu5jOuNlCDtmo3rk51cbiAgICpcbiAgICogQHJldHVybnMgcWIgLSDsv7zrpqwg67mM642UICjsobDqsbQg7LaU6rCA7JqpKVxuICAgKiBAcmV0dXJucyBvblN1YnNldCAtIO2KueyglSDshJzruIzshYsg7KCE7JqpIO2DgOyeheydtCDtlYTsmpTtlaAg65WMIOyCrOyaqVxuICAgKi9cbiAgZ2V0U3Vic2V0UXVlcmllczxUIGV4dGVuZHMgVFN1YnNldEtleT4oc3Vic2V0OiBUKSB7XG4gICAgaWYgKCF0aGlzLnN1YnNldFF1ZXJpZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNldFF1ZXJpZXMgaXMgbm90IGRlZmluZWRcIik7XG4gICAgfVxuXG4gICAgY29uc3QgcHVyaVdyYXBwZXIgPSBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICAgIGNvbnN0IHFiID0gdGhpcy5zdWJzZXRRdWVyaWVzW3N1YnNldF0/LihwdXJpV3JhcHBlcik7XG5cbiAgICAvLyBOb25BbGxvd2VkQXNTaW5nbGVUYWJsZTog64uo7J28IO2FjOydtOu4lCDsu6zrn7wg7KCR6re8IOuwqeyngOyaqSDrp4jsu6RcbiAgICB0eXBlIFFCVGFibGVzID0gVW5pb25FeHRyYWN0ZWRUVGFibGVzPFRTdWJzZXRLZXksIFRTdWJzZXRRdWVyaWVzPiAmIHtcbiAgICAgIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiB7IF9fZnVsbHRleHRfXzogdHJ1ZSB9O1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcWI6IHFiIGFzIHVua25vd24gYXMgUHVyaTxEYXRhYmFzZVNjaGVtYUV4dGVuZCwgUUJUYWJsZXMsIHt9PixcbiAgICAgIG9uU3Vic2V0OiAoKF9zdWJzZXQ6IFRTdWJzZXRLZXkgfCByZWFkb25seSBUU3Vic2V0S2V5W10pID0+IHFiKSBhcyB7XG4gICAgICAgIC8vIOuLqOydvCDtgqRcbiAgICAgICAgPFMgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFMpOiBSZXR1cm5UeXBlPFRTdWJzZXRRdWVyaWVzW1NdPjtcbiAgICAgICAgLy8g7YKkIOuwsOyXtCAtPiDqtZDsp5Htlakg67CY7ZmYXG4gICAgICAgIDxBcnIgZXh0ZW5kcyByZWFkb25seSBUU3Vic2V0S2V5W10+KFxuICAgICAgICAgIHN1YnNldHM6IFsuLi5BcnJdLFxuICAgICAgICApOiBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uPEFyciwgVFN1YnNldFF1ZXJpZXM+O1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuaGFuY2VyIOqwneyytCDsg53shLEg7Zes7Y28XG4gICAqIO2DgOyehSDqsoDspp0g67CPIOy2lOuhoOydhCDrj4TsmYDspIxcbiAgICovXG4gIGNyZWF0ZUVuaGFuY2VyczxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxcbiAgICAgIFQsXG4gICAgICBJbmZlckFsbFN1YnNldHM8VFN1YnNldFF1ZXJpZXMsIFRMb2FkZXJRdWVyaWVzPixcbiAgICAgIFRTdWJzZXRNYXBwaW5nLFxuICAgICAgVFN1YnNldFF1ZXJpZXNcbiAgICA+LFxuICApIHtcbiAgICByZXR1cm4gZW5oYW5jZXJzO1xuICB9XG5cbiAgLyoqXG4gICAqIOyEnOu4jOyFiyDsv7zrpqwg7Iuk7ZaJXG4gICAqXG4gICAqIDEuIFNvbmFtdSDtlYTthLAg7KCB7JqpICjtg4DsnoUg67OA7ZmYIO2PrO2VqClcbiAgICogMi4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDMuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiA0LiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA1LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gICAgTFAgZXh0ZW5kcyB7XG4gICAgICBudW0/OiBudW1iZXI7XG4gICAgICBwYWdlPzogbnVtYmVyO1xuICAgICAgcXVlcnlNb2RlPzogU29uYW11UXVlcnlNb2RlO1xuICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfSxcbiAgPihcbiAgICBwYXJhbXM6IHtcbiAgICAgIHN1YnNldDogVDtcbiAgICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+O1xuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIG51bTogbnVtYmVyO1xuICAgICAgICBwYWdlOiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFNvbmFtdVF1ZXJ5TW9kZTtcbiAgICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+LFxuICApOiBQcm9taXNlPExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIC8vIFNvbmFtdSBGaWx0ZXIg7KCB7JqpXG4gICAgaWYgKHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcikge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbHRlciA9IG5vcm1hbGl6ZUZpbHRlclF1ZXJ5KHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcik7XG4gICAgICB0aGlzLmFwcGx5U29uYW11RmlsdGVycyhxYiwgbm9ybWFsaXplZEZpbHRlcik7XG4gICAgfVxuXG4gICAgY29uc3QgeyBudW0sIHBhZ2UgfSA9IHF1ZXJ5UGFyYW1zO1xuXG4gICAgLy8gQ09VTlQg7L+866asIOyLpO2WiSAocXVlcnlNb2RlOiBsaXN07J28IOuVjOuKlCAwIOumrO2EtClcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIGlmIChxdWVyeVBhcmFtcz8ucXVlcnlNb2RlID09PSBcImNvdW50XCIpIHtcbiAgICAgIHJldHVybiB7IHRvdGFsIH0gYXMgTGlzdFJlc3VsdDxMUCwgVFN1YnNldE1hcHBpbmdbVF0+O1xuICAgIH1cblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IGVuaGFuY2VkUm93cyA9IChhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGNvbXB1dGVkUm93cy5tYXAoKHJvdykgPT4gZW5oYW5jZXI/Lihyb3cpID8/IHJvdyksXG4gICAgKSkgYXMgVFN1YnNldE1hcHBpbmdbVF1bXTtcblxuICAgIC8vIEludGVybmFsIO2VhOuTnCDsoJzqsbBcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldCh0aGlzLm1vZGVsTmFtZSk7XG4gICAgY29uc3QgaW50ZXJuYWxGaWVsZHMgPSBlbnRpdHkuc3Vic2V0c0ludGVybmFsW3N1YnNldF0gPz8gW107XG4gICAgY29uc3Qgcm93cyA9XG4gICAgICBpbnRlcm5hbEZpZWxkcy5sZW5ndGggPiAwXG4gICAgICAgID8gZW5oYW5jZWRSb3dzLm1hcCgocm93KSA9PiB0aGlzLm9taXRJbnRlcm5hbEZpZWxkcyhyb3csIGludGVybmFsRmllbGRzKSlcbiAgICAgICAgOiBlbmhhbmNlZFJvd3M7XG5cbiAgICBpZiAocXVlcnlQYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgLy8g66as7Iqk7Yq466eMIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cyB9IGFzIExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8g65GY64ukIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cywgdG90YWwgfSBhcyBMaXN0UmVzdWx0PExQLCBUU3Vic2V0TWFwcGluZ1tUXT47XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOqwneyytOyXkOyEnCBpbnRlcm5hbCDtlYTrk5wg7KCc6rGwXG4gICAqIOykkeyyqSDtlYTrk5wo7JiIOiBcInVzZXIuZW1haWxcIikg67CPIOuwsOyXtCjsmIg6IFwiZW1wbG95ZWVzLnNhbGFyeVwiKeuPhCDsspjrpqxcbiAgICovXG4gIG9taXRJbnRlcm5hbEZpZWxkczxUIGV4dGVuZHMgb2JqZWN0Pihyb3c6IFQsIGZpZWxkczogc3RyaW5nW10pOiBUIHtcbiAgICBjb25zdCByZXN1bHQgPSBjbG9uZURlZXAocm93KTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xuICAgICAgdGhpcy5kZWxldGVGaWVsZChyZXN1bHQsIGZpZWxkLnNwbGl0KFwiLlwiKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRmlsdGVyUXVlcnnrpbwgUHVyaSBRdWVyeUJ1aWxkZXLsl5Ag7KCB7JqpXG4gICAqXG4gICAqIEBwYXJhbSBxYiBQdXJpIFF1ZXJ5QnVpbGRlciDsnbjsiqTthLTsiqRcbiAgICogQHBhcmFtIGZpbHRlcnMgRmlsdGVyUXVlcnkg6rCd7LK0XG4gICAqL1xuICBwcm90ZWN0ZWQgYXBwbHlTb25hbXVGaWx0ZXJzPFRFbnRpdHkgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgZmlsdGVycz86IEZpbHRlclF1ZXJ5PFRFbnRpdHk+LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWZpbHRlcnMpIHJldHVybjtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHRoaXMubW9kZWxOYW1lKTtcblxuICAgIC8vIDEuIO2VhO2EsCDqsoDspp0gKEVudGl0eSDquLDrsJgpXG4gICAgdmFsaWRhdGVTb25hbXVGaWx0ZXJzKGZpbHRlcnMsIGVudGl0eSk7XG5cbiAgICAvLyAyLiDqsoDspp3rkJwg7ZWE7YSwIOyggeyaqVxuICAgIGNvbnN0IHB1cmkgPSBxYiBhcyBhbnk7XG5cbiAgICBmb3IgKGNvbnN0IFtmaWVsZCwgY29uZGl0aW9uXSBvZiBPYmplY3QuZW50cmllcyhmaWx0ZXJzKSkge1xuICAgICAgaWYgKGNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGNvbmRpdGlvbiA9PT0gbnVsbCkgY29udGludWU7XG5cbiAgICAgIC8vIO2FjOydtOu4lOuqhS7tlYTrk5zrqoUg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgICAgY29uc3QgZnVsbEZpZWxkID0gZW50aXR5LmdldEZ1bGxGaWVsZE5hbWUoZmllbGQpO1xuXG4gICAgICAvLyDsp4HsoJEg6rCSIChlceyZgCDrj5nsnbwpXG4gICAgICBpZiAodHlwZW9mIGNvbmRpdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGNvbmRpdGlvbikpIHtcbiAgICAgICAgcHVyaS53aGVyZShmdWxsRmllbGQsIGNvbmRpdGlvbik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyDsl7DsgrDsnpAg6rCd7LK0XG4gICAgICBmb3IgKGNvbnN0IFtvcGVyYXRvciwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikpIHtcbiAgICAgICAgdGhpcy5hcHBseU9wZXJhdG9yKHFiLCBmdWxsRmllbGQsIG9wZXJhdG9yIGFzIEZpbHRlck9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOuLqOydvCDsl7DsgrDsnpDrpbwgUXVlcnlCdWlsZGVy7JeQIOyggeyaqVxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseU9wZXJhdG9yKFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIGZpZWxkOiBzdHJpbmcsXG4gICAgb3BlcmF0b3I6IEZpbHRlck9wZXJhdG9yLFxuICAgIHZhbHVlOiB1bmtub3duLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwdXJpID0gcWIgYXMgYW55O1xuXG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSBcImVxXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJuZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIiE9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJndFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj5cIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImd0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJsdFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjxcIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImx0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjw9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpblwiOlxuICAgICAgICBwdXJpLndoZXJlSW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJub3RJblwiOlxuICAgICAgICBwdXJpLndoZXJlTm90SW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJjb250YWluc1wiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcImxpa2VcIiwgYCUke3ZhbHVlfSVgKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJzdGFydHNXaXRoXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwibGlrZVwiLCBgJHt2YWx1ZX0lYCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZW5kc1dpdGhcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCJsaWtlXCIsIGAlJHt2YWx1ZX1gKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpc051bGxcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiaXNOb3ROdWxsXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiIT1cIiwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYmVmb3JlXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiPFwiLCB2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYWZ0ZXJcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCI+XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJiZXR3ZWVuXCI6IHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIGNvbnN0IFttaW4sIG1heF0gPSB2YWx1ZTtcbiAgICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIG1pbikud2hlcmUoZmllbGQsIFwiPD1cIiwgbWF4KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS53YXJuKGBVbnN1cHBvcnRlZCBvcGVyYXRvcjogJHtvcGVyYXRvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog7KSR7LKpIO2VhOuTnCDsgq3soJwgKOuwsOyXtCDrgrQg6rCd7LK064+EIOyymOumrClcbiAgICovXG4gIGRlbGV0ZUZpZWxkKG9iajogYW55LCBwYXJ0czogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBpZiAoIW9iaiB8fCB0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmouZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtICYmIHR5cGVvZiBpdGVtID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBkZWxldGUgaXRlbVtwYXJ0c1swXV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBvYmpbcGFydHNbMF1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBwYXJ0cztcbiAgICBjb25zdCBuZXh0ID0gb2JqW2ZpcnN0XTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG5leHQpKSB7XG4gICAgICBuZXh0Lm1hcCgoaXRlbSkgPT4gdGhpcy5kZWxldGVGaWVsZChpdGVtLCByZXN0KSk7XG4gICAgfSBlbHNlIGlmIChuZXh0ICYmIHR5cGVvZiBuZXh0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aGlzLmRlbGV0ZUZpZWxkKG5leHQsIHJlc3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDT1VOVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlQ291bnRRdWVyeShcbiAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PixcbiAgICBwYXJhbXM6IHsgcXVlcnlNb2RlPzogXCJsaXN0XCIgfCBcImNvdW50XCIgfCBcImJvdGhcIiB9LFxuICAgIGRlYnVnOiBib29sZWFuLFxuICAgIG9wdGltaXplQ291bnRRdWVyeTogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGNvbnN0IGNvdW50UHVyaSA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcImxpbWl0XCIpLmNsZWFyKFwib2Zmc2V0XCIpO1xuXG4gICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgY29uc3QgeyBkZWZhdWx0OiBTcWxQYXJzZXIgfSA9IGF3YWl0IGltcG9ydChcIm5vZGUtc3FsLXBhcnNlclwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG4gICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY291bnRQdXJpLnRvUXVlcnkoKSwge1xuICAgICAgICBkYXRhYmFzZTogU29uYW11LmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsZWZ0Sm9pblRhYmxlcyA9IGdldEpvaW5UYWJsZXMocGFyc2VkUXVlcnksIFtcIkxFRlQgSk9JTlwiXSk7XG4gICAgICBjb25zdCB3aGVyZVRhYmxlcyA9IGdldFRhYmxlTmFtZXNGcm9tV2hlcmUocGFyc2VkUXVlcnkpO1xuXG4gICAgICBjb25zdCB0YWJsZXNUb1JlbW92ZSA9IGxlZnRKb2luVGFibGVzLmZpbHRlcigoaikgPT4gIXdoZXJlVGFibGVzLmluY2x1ZGVzKGopKTtcbiAgICAgIHRhYmxlc1RvUmVtb3ZlLmZvckVhY2goKHRhYmxlKSA9PiB7XG4gICAgICAgIGNvdW50UHVyaS5jbGVhckpvaW4odGFibGUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ09VTlQoKinroZwg7KCE7LK0IOugiOy9lOuTnCDsiJjrpbwg6rOE7IKwXG4gICAgLy8gVE9ETzogcWLsnZggRElTVElOQ1TqsIAg7J6I64qUIOqyveyasCDsspjrpqztlbTslbwg7ZWoXG4gICAgY29uc3QgY291bnRSZXN1bHQ6IHsgdG90YWw/OiBudW1iZXIgfSA9IGF3YWl0IGNvdW50UHVyaVxuICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAuc2VsZWN0KHsgdG90YWw6IFB1cmkucmF3TnVtYmVyKGBDT1VOVCgqKTo6aW50ZWdlcmApIH0pXG4gICAgICAuZmlyc3QoKTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY291bnRQdXJpLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvdW50UmVzdWx0Py50b3RhbCA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIExJU1Qg7L+866asIOyLpO2WiSAo64K067aAIOuplOyEnOuTnClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXhlY3V0ZUxpc3RRdWVyeTxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgbnVtOiBudW1iZXIsXG4gICAgcGFnZTogbnVtYmVyLFxuICAgIGRlYnVnOiBib29sZWFuLFxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgaWYgKHBhcmFtcy5xdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGxpbWl0ZWRRYiA9ICgoKSA9PiB7XG4gICAgICBpZiAobnVtID09PSAwKSB7XG4gICAgICAgIHJldHVybiBxYjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIGxldCB1bmxvYWRlZFJvd3MgPSAoYXdhaXQgbGltaXRlZFFiKSBhcyBhbnlbXTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgcWIuZGVidWcoKTtcbiAgICB9XG5cbiAgICAvLyDroZzrjZQg7LKY66asXG4gICAgY29uc3QgbG9hZGVycyA9ICh0aGlzLmxvYWRlclF1ZXJpZXMgYXMgYW55KVtzdWJzZXRdO1xuICAgIGlmIChsb2FkZXJzICYmIEFycmF5LmlzQXJyYXkobG9hZGVycykpIHtcbiAgICAgIHVubG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnModW5sb2FkZWRSb3dzLCBsb2FkZXJzLCBkZWJ1Zyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaHlkcmF0ZSh1bmxvYWRlZFJvd3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIOyerOq3gOyggSDroZzrjZQg7LKY66asXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHByb2Nlc3NMb2FkZXJzKHJvd3M6IGFueVtdLCBsb2FkZXJzOiBhbnlbXSwgZGVidWc6IGJvb2xlYW4pOiBQcm9taXNlPGFueVtdPiB7XG4gICAgZm9yIChjb25zdCByZXNvbHZlTG9hZGVyIG9mIGxvYWRlcnMpIHtcbiAgICAgIGNvbnN0IHsgYXMsIHJlZklkLCBxYjogcmVzb2x2ZUxvYWRlclFiRm4sIGxvYWRlcnM6IG5lc3RlZExvYWRlcnMgfSA9IHJlc29sdmVMb2FkZXI7XG5cbiAgICAgIGNvbnN0IHJlc29sdmVMb2FkZXJRYiA9IHJlc29sdmVMb2FkZXJRYkZuKFxuICAgICAgICBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpLFxuICAgICAgICByb3dzLm1hcCgocm93KSA9PiByb3dbcmVmSWRdKSxcbiAgICAgICk7XG5cbiAgICAgIGlmIChkZWJ1Zykge1xuICAgICAgICByZXNvbHZlTG9hZGVyUWIuZGVidWcoKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGxvYWRlZFJvd3MgPSAoYXdhaXQgcmVzb2x2ZUxvYWRlclFiKSBhcyBhbnlbXTtcblxuICAgICAgLy8g7KSR7LKpIGxvYWRlcnPqsIAg7J6I7Jy866m0IOyerOq3gCDsspjrpqxcbiAgICAgIGlmIChuZXN0ZWRMb2FkZXJzICYmIG5lc3RlZExvYWRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICBsb2FkZWRSb3dzID0gYXdhaXQgdGhpcy5wcm9jZXNzTG9hZGVycyhsb2FkZWRSb3dzLCBuZXN0ZWRMb2FkZXJzLCBkZWJ1Zyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YlJvd0dyb3VwcyA9IGdyb3VwKGxvYWRlZFJvd3MsIChyb3cpID0+IHJvdy5yZWZJZCk7XG5cbiAgICAgIHJvd3MgPSByb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvd1thc10gPSAoc3ViUm93R3JvdXBzW3Jvd1tyZWZJZF1dID8/IFtdKS5tYXAoKHIpID0+IG9taXQociwgW1wicmVmSWRcIl0pKTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByb3dzO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYXQg66CI7L2U65Oc66W8IOykkeyyqSDqsJ3ssrTroZwg67OA7ZmYXG4gICAqXG4gICAqIC0gYHVzZXJfX25hbWVgIOKGkiBgeyB1c2VyOiB7IG5hbWUgfSB9YFxuICAgKiAtIG51bGxhYmxlIHJlbGF0aW9u7J2YIOqyveyasCBpZCDtlYTrk5zqsIAgbnVsbOydtOuptCDqsJ3ssrQg7J6Q7LK066W8IG51bGzroZxcbiAgICovXG4gIGh5ZHJhdGU8VCBleHRlbmRzIFVua25vd25EQlJlY29yZD4ocm93czogVFtdKTogVFtdIHtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdzogVCkgPT4ge1xuICAgICAgLy8gbnVsbGFibGUgcmVsYXRpb24g7LKY66asOiDqt7jro7nsnZggaWQg7ZWE65Oc6rCAIG51bGzsnbTrqbQg6rCd7LK0IOyghOyytOulvCBudWxs66GcXG4gICAgICBjb25zdCBuZXN0ZWRLZXlzID0gT2JqZWN0LmtleXMocm93KS5maWx0ZXIoKGtleSkgPT4ga2V5LmluY2x1ZGVzKFwiX19cIikpO1xuICAgICAgY29uc3QgZ3JvdXBzID0gT2JqZWN0Lmdyb3VwQnkobmVzdGVkS2V5cywgKGtleSkgPT4ga2V5LnNwbGl0KFwiX19cIilbMF0pO1xuXG4gICAgICAvLyBpZCDtlYTrk5zqsIAgbnVsbOyduCDqt7jro7kg7LC+6riwICjsmIg6IHBhcmVudF9faWTqsIAgbnVsbOydtOuptCBwYXJlbnQg6re466O5IOyghOyytOqwgCBudWxsKVxuICAgICAgY29uc3QgbnVsbEtleXMgPSBPYmplY3QuZW50cmllcyhncm91cHMpXG4gICAgICAgIC5maWx0ZXIoKFtncm91cEtleSwgZmllbGRzXSkgPT4ge1xuICAgICAgICAgIGlmICghZmllbGRzIHx8IGZpZWxkcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgIC8vIOq3uOujueydmCBpZCDtlYTrk5wg7LC+6riwICjsmIg6IFwicGFyZW50X19pZFwiKVxuICAgICAgICAgIGNvbnN0IGlkRmllbGQgPSBgJHtncm91cEtleX1fX2lkYDtcbiAgICAgICAgICBpZiAoaWRGaWVsZCBpbiByb3cpIHtcbiAgICAgICAgICAgIC8vIGlkIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsoITssrTqsIAgbnVsbFxuICAgICAgICAgICAgcmV0dXJuIHJvd1tpZEZpZWxkXSA9PT0gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBpZCDtlYTrk5zqsIAg7JeG7Jy866m0IOq4sOyhtCDroZzsp4E6IOuqqOuToCDtlYTrk5zqsIAgbnVsbOyduOyngCDtmZXsnbhcbiAgICAgICAgICByZXR1cm4gZmllbGRzLmV2ZXJ5KFxuICAgICAgICAgICAgKGZpZWxkKSA9PlxuICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8IChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKSxcbiAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgICAubWFwKChba2V5XSkgPT4ga2V5KTtcblxuICAgICAgY29uc3QgaHlkcmF0ZWQgPSBPYmplY3Qua2V5cyhyb3cpLnJlZHVjZSgociwgZmllbGQpID0+IHtcbiAgICAgICAgaWYgKCFmaWVsZC5pbmNsdWRlcyhcIl9fXCIpKSB7XG4gICAgICAgICAgLy8g7J2867CYIO2VhOuTnDog67Cw7Je0IOuCtCDqsJ3ssrTrqbQg7J6s6reAIGh5ZHJhdGVcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKSkge1xuICAgICAgICAgICAgcltmaWVsZF0gPSB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gcm93W2ZpZWxkXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDspJHssqkg7ZWE65OcIOyymOumrDogdXNlcl9fbmFtZSDihpIgdXNlcltuYW1lXVxuICAgICAgICBjb25zdCBwYXJ0cyA9IGZpZWxkLnNwbGl0KFwiX19cIik7XG4gICAgICAgIGNvbnN0IG9ialBhdGggPVxuICAgICAgICAgIHBhcnRzWzBdICtcbiAgICAgICAgICBwYXJ0c1xuICAgICAgICAgICAgLnNsaWNlKDEpXG4gICAgICAgICAgICAubWFwKChwYXJ0KSA9PiBgWyR7cGFydH1dYClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuXG4gICAgICAgIHIgPSBzZXQoXG4gICAgICAgICAgcixcbiAgICAgICAgICBvYmpQYXRoLFxuICAgICAgICAgIHJvd1tmaWVsZF0gJiYgQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKVxuICAgICAgICAgICAgPyB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSlcbiAgICAgICAgICAgIDogcm93W2ZpZWxkXSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gcjtcbiAgICAgIH0sIHt9IGFzIFVua25vd25EQlJlY29yZCk7XG5cbiAgICAgIC8vIG51bGwgcmVsYXRpb24g7LKY66asXG4gICAgICBudWxsS2V5cy5mb3JFYWNoKChudWxsS2V5KSA9PiB7XG4gICAgICAgIGh5ZHJhdGVkW251bGxLZXldID0gbnVsbDtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gaHlkcmF0ZWQ7XG4gICAgfSkgYXMgVFtdO1xuICB9XG59XG5cbi8qKlxuICogRW5oYW5jZXIg7YyM652866+47YSwIOyhsOqxtOu2gCDtg4DsnoVcbiAqIFJlcXVpcmVkRW5oYW5jZXJLZXlz6rCAIOyXhuycvOuptCBlbmhhbmNlcnMg7ISg7YOd7KCBLCDsnojsnLzrqbQg7ZWE7IiYXG4gKi9cbnR5cGUgRW5oYW5jZXJQYXJhbTxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0UXVlcmllcyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBQdXJpU3Vic2V0Rm4+LFxuPiA9IFtSZXF1aXJlZEVuaGFuY2VyS2V5czxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZz5dIGV4dGVuZHMgW25ldmVyXVxuICA/IHsgZW5oYW5jZXJzPzogRW5oYW5jZXJNYXA8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmcsIFRTdWJzZXRRdWVyaWVzPiB9XG4gIDogeyBlbmhhbmNlcnM6IEVuaGFuY2VyTWFwPFRTdWJzZXRLZXksIFRDb21wdXRlZFJlc3VsdHMsIFRTdWJzZXRNYXBwaW5nLCBUU3Vic2V0UXVlcmllcz4gfTtcblxudHlwZSBSZXF1aXJlZEVuaGFuY2VyS2V5czxcbiAgVFN1YnNldEtleSBleHRlbmRzIHN0cmluZyxcbiAgVENvbXB1dGVkUmVzdWx0cyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuICBUU3Vic2V0TWFwcGluZyBleHRlbmRzIFJlY29yZDxUU3Vic2V0S2V5LCBhbnk+LFxuPiA9IHtcbiAgW0sgaW4gVFN1YnNldEtleV06IFRDb21wdXRlZFJlc3VsdHNbS10gZXh0ZW5kcyBUU3Vic2V0TWFwcGluZ1tLXSA/IG5ldmVyIDogSztcbn1bVFN1YnNldEtleV07XG5cbmV4cG9ydCBjb25zdCBCYXNlTW9kZWwgPSBuZXcgQmFzZU1vZGVsQ2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJnZXRMb2dnZXIiLCJjbG9uZURlZXAiLCJncm91cCIsImlzT2JqZWN0Iiwib21pdCIsInNldCIsIm5vcm1hbGl6ZUZpbHRlclF1ZXJ5IiwidmFsaWRhdGVTb25hbXVGaWx0ZXJzIiwiU29uYW11IiwiRW50aXR5TWFuYWdlciIsImNvbnZlcnREb21haW5Ub0NhdGVnb3J5IiwiZ2V0Sm9pblRhYmxlcyIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJjaHVuayIsIkRCIiwiUHVyaSIsIlB1cmlXcmFwcGVyIiwiVXBzZXJ0QnVpbGRlciIsIkJhc2VNb2RlbENsYXNzIiwibG9nZ2VyIiwibW9kZWxOYW1lIiwibmFtZSIsInN1YnNldFF1ZXJpZXMiLCJsb2FkZXJRdWVyaWVzIiwiZ2V0REIiLCJ3aGljaCIsImdldFB1cmkiLCJ0cngiLCJnZXRUcmFuc2FjdGlvbkNvbnRleHQiLCJnZXRUcmFuc2FjdGlvbiIsImRiIiwiZGVzdHJveSIsImdldEluc2VydGVkSWRzIiwid2RiIiwicm93cyIsInRhYmxlTmFtZSIsInVucUtleUZpZWxkcyIsImNodW5rU2l6ZSIsInVucUtleXMiLCJ3aGVyZUluRmllbGQiLCJzZWxlY3RGaWVsZCIsImxlbmd0aCIsInJhdyIsImpvaW4iLCJtYXAiLCJyb3ciLCJmaWVsZCIsInJlc3VsdElkcyIsIml0ZW1zIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJTdHJpbmciLCJpZCIsImdldFN1YnNldFF1ZXJpZXMiLCJzdWJzZXQiLCJFcnJvciIsInB1cmlXcmFwcGVyIiwicWIiLCJvblN1YnNldCIsIl9zdWJzZXQiLCJjcmVhdGVFbmhhbmNlcnMiLCJlbmhhbmNlcnMiLCJleGVjdXRlU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJxdWVyeVBhcmFtcyIsImRlYnVnIiwib3B0aW1pemVDb3VudFF1ZXJ5Iiwic29uYW11RmlsdGVyIiwibm9ybWFsaXplZEZpbHRlciIsImFwcGx5U29uYW11RmlsdGVycyIsIm51bSIsInBhZ2UiLCJ0b3RhbCIsImV4ZWN1dGVDb3VudFF1ZXJ5IiwicXVlcnlNb2RlIiwiY29tcHV0ZWRSb3dzIiwiZXhlY3V0ZUxpc3RRdWVyeSIsImVuaGFuY2VyIiwiZW5oYW5jZWRSb3dzIiwiUHJvbWlzZSIsImFsbCIsImVudGl0eSIsImdldCIsImludGVybmFsRmllbGRzIiwic3Vic2V0c0ludGVybmFsIiwib21pdEludGVybmFsRmllbGRzIiwiZmllbGRzIiwicmVzdWx0IiwiZGVsZXRlRmllbGQiLCJzcGxpdCIsImZpbHRlcnMiLCJwdXJpIiwiY29uZGl0aW9uIiwiT2JqZWN0IiwiZW50cmllcyIsInVuZGVmaW5lZCIsImZ1bGxGaWVsZCIsImdldEZ1bGxGaWVsZE5hbWUiLCJBcnJheSIsImlzQXJyYXkiLCJ3aGVyZSIsIm9wZXJhdG9yIiwidmFsdWUiLCJhcHBseU9wZXJhdG9yIiwid2hlcmVOb3RJbiIsIm1pbiIsIm1heCIsImNvbnNvbGUiLCJ3YXJuIiwib2JqIiwicGFydHMiLCJmb3JFYWNoIiwiaXRlbSIsImZpcnN0IiwicmVzdCIsIm5leHQiLCJjb3VudFB1cmkiLCJjbG9uZSIsImNsZWFyIiwiZGVmYXVsdCIsIlNxbFBhcnNlciIsInBhcnNlciIsIlBhcnNlciIsInBhcnNlZFF1ZXJ5IiwiYXN0aWZ5IiwidG9RdWVyeSIsImRhdGFiYXNlIiwiY29uZmlnIiwibGVmdEpvaW5UYWJsZXMiLCJ3aGVyZVRhYmxlcyIsInRhYmxlc1RvUmVtb3ZlIiwiZmlsdGVyIiwiaiIsImluY2x1ZGVzIiwidGFibGUiLCJjbGVhckpvaW4iLCJjb3VudFJlc3VsdCIsInJhd051bWJlciIsImxpbWl0ZWRRYiIsImxpbWl0Iiwib2Zmc2V0IiwidW5sb2FkZWRSb3dzIiwibG9hZGVycyIsInByb2Nlc3NMb2FkZXJzIiwiaHlkcmF0ZSIsInJlc29sdmVMb2FkZXIiLCJhcyIsInJlZklkIiwicmVzb2x2ZUxvYWRlclFiRm4iLCJuZXN0ZWRMb2FkZXJzIiwicmVzb2x2ZUxvYWRlclFiIiwibG9hZGVkUm93cyIsInN1YlJvd0dyb3VwcyIsInIiLCJuZXN0ZWRLZXlzIiwia2V5cyIsImtleSIsImdyb3VwcyIsImdyb3VwQnkiLCJudWxsS2V5cyIsImdyb3VwS2V5IiwiaWRGaWVsZCIsImV2ZXJ5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJvYmpQYXRoIiwic2xpY2UiLCJwYXJ0IiwibnVsbEtleSIsIkJhc2VNb2RlbCJdLCJtYXBwaW5ncyI6IkFBQUEsa0dBQWtHLEdBQ2xHLFNBQVNBLFNBQVMsUUFBcUIsbUJBQW1CO0FBRTFELFNBQVNDLFNBQVMsRUFBRUMsS0FBSyxFQUFFQyxRQUFRLEVBQUVDLElBQUksRUFBRUMsR0FBRyxRQUFRLFVBQVU7QUFDaEUsU0FBMEJDLG9CQUFvQixFQUFFQyxxQkFBcUIsUUFBUSxjQUFLO0FBQ2xGLFNBQVNDLE1BQU0sUUFBUSxrQkFBUztBQUNoQyxTQUFTQyxhQUFhLFFBQVEsOEJBQTJCO0FBRXpELFNBQVNDLHVCQUF1QixRQUFRLHdCQUFxQjtBQUU3RCxTQUFTQyxhQUFhLEVBQUVDLHNCQUFzQixRQUFRLHlCQUFzQjtBQUM1RSxTQUFTQyxLQUFLLFFBQVEsb0JBQWlCO0FBR3ZDLFNBQVNDLEVBQUUsUUFBUSxVQUFPO0FBQzFCLFNBQVNDLElBQUksUUFBUSxZQUFTO0FBRzlCLFNBQVNDLFdBQVcsUUFBUSxvQkFBaUI7QUFDN0MsU0FBU0MsYUFBYSxRQUFRLHNCQUFtQjtBQUlqRDs7Ozs7OztDQU9DLEdBQ0QsT0FBTyxNQUFNQzs7OztJQU1RQyxPQUFlO0lBRWxDLFlBQ0UsQUFBZ0JDLFlBQW9CLElBQUksQ0FBQyxXQUFXLENBQUNDLElBQUksRUFDekQsQUFBVUMsYUFBOEIsRUFDeEMsQUFBVUMsYUFBOEIsQ0FDeEM7YUFIZ0JILFlBQUFBO2FBQ05FLGdCQUFBQTthQUNBQyxnQkFBQUE7UUFFVixJQUFJLENBQUNK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
|
|
14
|
+
//#region src/database/base-model.ts
|
|
15
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: Puri의 타입은 개별 모델에서 확정되므로 BaseModel에서는 any를 허용함 */
|
|
16
|
+
var BaseModelClass, BaseModel;
|
|
17
|
+
var init_base_model = __esmMin((() => {
|
|
18
|
+
init_sonamu();
|
|
19
|
+
init_entity_manager();
|
|
20
|
+
init_utils();
|
|
21
|
+
init_category();
|
|
22
|
+
init_sql_parser();
|
|
23
|
+
init_db();
|
|
24
|
+
init_puri();
|
|
25
|
+
init_puri_wrapper();
|
|
26
|
+
init_upsert_builder();
|
|
27
|
+
BaseModelClass = class {
|
|
28
|
+
logger;
|
|
29
|
+
constructor(modelName = this.constructor.name, subsetQueries, loaderQueries) {
|
|
30
|
+
this.modelName = modelName;
|
|
31
|
+
this.subsetQueries = subsetQueries;
|
|
32
|
+
this.loaderQueries = loaderQueries;
|
|
33
|
+
this.logger = getLogger(convertDomainToCategory(this.modelName, "model"));
|
|
34
|
+
}
|
|
35
|
+
getDB(which) {
|
|
36
|
+
return DB.getDB(which);
|
|
37
|
+
}
|
|
38
|
+
getPuri(which) {
|
|
39
|
+
const trx = DB.getTransactionContext().getTransaction(which);
|
|
40
|
+
if (trx) {
|
|
41
|
+
return trx;
|
|
42
|
+
}
|
|
43
|
+
const db = this.getDB(which);
|
|
44
|
+
return new PuriWrapper(db, new UpsertBuilder());
|
|
45
|
+
}
|
|
46
|
+
async destroy() {
|
|
47
|
+
return DB.destroy();
|
|
48
|
+
}
|
|
49
|
+
async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
|
|
50
|
+
if (!wdb) {
|
|
51
|
+
wdb = this.getDB("w");
|
|
52
|
+
}
|
|
53
|
+
let unqKeys;
|
|
54
|
+
let whereInField;
|
|
55
|
+
let selectField;
|
|
56
|
+
if (unqKeyFields.length > 1) {
|
|
57
|
+
whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
|
|
58
|
+
selectField = `${whereInField} as tmpUid`;
|
|
59
|
+
unqKeys = rows.map((row) => unqKeyFields.map((field) => row[field]).join("_"));
|
|
60
|
+
} else {
|
|
61
|
+
whereInField = unqKeyFields[0];
|
|
62
|
+
selectField = unqKeyFields[0];
|
|
63
|
+
unqKeys = rows.map((row) => row[unqKeyFields[0]]);
|
|
64
|
+
}
|
|
65
|
+
let resultIds = [];
|
|
66
|
+
for (const items of cluster(unqKeys, chunkSize)) {
|
|
67
|
+
const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, items);
|
|
68
|
+
resultIds = resultIds.concat(dbRows.map((dbRow) => parseInt(String(dbRow.id))));
|
|
69
|
+
}
|
|
70
|
+
return resultIds;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 특정 서브셋에 대한 쿼리 빌더 획득
|
|
74
|
+
*
|
|
75
|
+
* @returns qb - 쿼리 빌더 (조건 추가용)
|
|
76
|
+
* @returns onSubset - 특정 서브셋 전용 타입이 필요할 때 사용
|
|
77
|
+
*/
|
|
78
|
+
getSubsetQueries(subset) {
|
|
79
|
+
if (!this.subsetQueries) {
|
|
80
|
+
throw new Error("subsetQueries is not defined");
|
|
81
|
+
}
|
|
82
|
+
const puriWrapper = new PuriWrapper(this.getDB("r"), new UpsertBuilder());
|
|
83
|
+
const qb = this.subsetQueries[subset]?.(puriWrapper);
|
|
84
|
+
return {
|
|
85
|
+
qb,
|
|
86
|
+
onSubset: ((_subset) => qb)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Enhancer 객체 생성 헬퍼
|
|
91
|
+
* 타입 검증 및 추론을 도와줌
|
|
92
|
+
*/
|
|
93
|
+
createEnhancers(enhancers) {
|
|
94
|
+
return enhancers;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 서브셋 쿼리 실행
|
|
98
|
+
*
|
|
99
|
+
* 1. Sonamu 필터 적용 (타입 변환 포함)
|
|
100
|
+
* 2. 쿼리 실행 (pagination 적용)
|
|
101
|
+
* 3. 로더 실행 (1:N, N:M 관계 데이터 로딩)
|
|
102
|
+
* 4. Hydrate (flat → 중첩 객체)
|
|
103
|
+
* 5. Enhancer 적용 (virtual 필드 계산)
|
|
104
|
+
*/
|
|
105
|
+
async executeSubsetQuery(params) {
|
|
106
|
+
const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
|
|
107
|
+
if (!this.loaderQueries) {
|
|
108
|
+
throw new Error("loaderQueries is not defined");
|
|
109
|
+
}
|
|
110
|
+
if (queryParams.sonamuFilter) {
|
|
111
|
+
const normalizedFilter = normalizeFilterQuery(queryParams.sonamuFilter);
|
|
112
|
+
this.applySonamuFilters(qb, normalizedFilter);
|
|
113
|
+
}
|
|
114
|
+
const { num, page } = queryParams;
|
|
115
|
+
const total = await this.executeCountQuery(qb, queryParams, debug, optimizeCountQuery);
|
|
116
|
+
if (queryParams?.queryMode === "count") {
|
|
117
|
+
return { total };
|
|
118
|
+
}
|
|
119
|
+
const computedRows = await this.executeListQuery(subset, qb, queryParams, num, page, debug);
|
|
120
|
+
const enhancer = params.enhancers?.[subset];
|
|
121
|
+
const enhancedRows = await Promise.all(computedRows.map((row) => enhancer?.(row) ?? row));
|
|
122
|
+
const entity = EntityManager.get(this.modelName);
|
|
123
|
+
const internalFields = entity.subsetsInternal[subset] ?? [];
|
|
124
|
+
const rows = internalFields.length > 0 ? enhancedRows.map((row) => this.omitInternalFields(row, internalFields)) : enhancedRows;
|
|
125
|
+
if (queryParams.queryMode === "list") {
|
|
126
|
+
return { rows };
|
|
127
|
+
} else {
|
|
128
|
+
return {
|
|
129
|
+
rows,
|
|
130
|
+
total
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 객체에서 internal 필드 제거
|
|
136
|
+
* 중첩 필드(예: "user.email") 및 배열(예: "employees.salary")도 처리
|
|
137
|
+
*/
|
|
138
|
+
omitInternalFields(row, fields) {
|
|
139
|
+
const result = cloneDeep(row);
|
|
140
|
+
for (const field of fields) {
|
|
141
|
+
this.deleteField(result, field.split("."));
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* FilterQuery를 Puri QueryBuilder에 적용
|
|
147
|
+
*
|
|
148
|
+
* @param qb Puri QueryBuilder 인스턴스
|
|
149
|
+
* @param filters FilterQuery 객체
|
|
150
|
+
*/
|
|
151
|
+
applySonamuFilters(qb, filters) {
|
|
152
|
+
if (!filters) return;
|
|
153
|
+
const entity = EntityManager.get(this.modelName);
|
|
154
|
+
validateSonamuFilters(filters, entity);
|
|
155
|
+
const puri = qb;
|
|
156
|
+
for (const [field, condition] of Object.entries(filters)) {
|
|
157
|
+
if (condition === undefined || condition === null) continue;
|
|
158
|
+
const fullField = entity.getFullFieldName(field);
|
|
159
|
+
if (typeof condition !== "object" || Array.isArray(condition)) {
|
|
160
|
+
puri.where(fullField, condition);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
for (const [operator, value] of Object.entries(condition)) {
|
|
164
|
+
this.applyOperator(qb, fullField, operator, value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 단일 연산자를 QueryBuilder에 적용
|
|
170
|
+
*/
|
|
171
|
+
applyOperator(qb, field, operator, value) {
|
|
172
|
+
const puri = qb;
|
|
173
|
+
switch (operator) {
|
|
174
|
+
case "eq":
|
|
175
|
+
puri.where(field, value);
|
|
176
|
+
break;
|
|
177
|
+
case "ne":
|
|
178
|
+
puri.where(field, "!=", value);
|
|
179
|
+
break;
|
|
180
|
+
case "gt":
|
|
181
|
+
puri.where(field, ">", value);
|
|
182
|
+
break;
|
|
183
|
+
case "gte":
|
|
184
|
+
puri.where(field, ">=", value);
|
|
185
|
+
break;
|
|
186
|
+
case "lt":
|
|
187
|
+
puri.where(field, "<", value);
|
|
188
|
+
break;
|
|
189
|
+
case "lte":
|
|
190
|
+
puri.where(field, "<=", value);
|
|
191
|
+
break;
|
|
192
|
+
case "in":
|
|
193
|
+
puri.whereIn(field, value);
|
|
194
|
+
break;
|
|
195
|
+
case "notIn":
|
|
196
|
+
puri.whereNotIn(field, value);
|
|
197
|
+
break;
|
|
198
|
+
case "contains":
|
|
199
|
+
puri.where(field, "like", `%${value}%`);
|
|
200
|
+
break;
|
|
201
|
+
case "startsWith":
|
|
202
|
+
puri.where(field, "like", `${value}%`);
|
|
203
|
+
break;
|
|
204
|
+
case "endsWith":
|
|
205
|
+
puri.where(field, "like", `%${value}`);
|
|
206
|
+
break;
|
|
207
|
+
case "isNull":
|
|
208
|
+
puri.where(field, null);
|
|
209
|
+
break;
|
|
210
|
+
case "isNotNull":
|
|
211
|
+
puri.where(field, "!=", null);
|
|
212
|
+
break;
|
|
213
|
+
case "before":
|
|
214
|
+
puri.where(field, "<", value);
|
|
215
|
+
break;
|
|
216
|
+
case "after":
|
|
217
|
+
puri.where(field, ">", value);
|
|
218
|
+
break;
|
|
219
|
+
case "between": {
|
|
220
|
+
if (Array.isArray(value) && value.length === 2) {
|
|
221
|
+
const [min, max] = value;
|
|
222
|
+
puri.where(field, ">=", min).where(field, "<=", max);
|
|
223
|
+
}
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
default: console.warn(`Unsupported operator: ${operator}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* 중첩 필드 삭제 (배열 내 객체도 처리)
|
|
231
|
+
*/
|
|
232
|
+
deleteField(obj, parts) {
|
|
233
|
+
if (!obj || typeof obj !== "object") {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (parts.length === 1) {
|
|
237
|
+
if (Array.isArray(obj)) {
|
|
238
|
+
obj.forEach((item) => {
|
|
239
|
+
if (item && typeof item === "object") {
|
|
240
|
+
delete item[parts[0]];
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
delete obj[parts[0]];
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const [first, ...rest] = parts;
|
|
249
|
+
const next = obj[first];
|
|
250
|
+
if (Array.isArray(next)) {
|
|
251
|
+
next.map((item) => this.deleteField(item, rest));
|
|
252
|
+
} else if (next && typeof next === "object") {
|
|
253
|
+
this.deleteField(next, rest);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* COUNT 쿼리 실행 (내부 메서드)
|
|
258
|
+
*/
|
|
259
|
+
async executeCountQuery(qb, params, debug, optimizeCountQuery) {
|
|
260
|
+
if (params.queryMode === "list") {
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
const countPuri = qb.clone().clear("order").clear("limit").clear("offset");
|
|
264
|
+
if (optimizeCountQuery) {
|
|
265
|
+
const { default: SqlParser } = await import("node-sql-parser");
|
|
266
|
+
const parser = new SqlParser.Parser();
|
|
267
|
+
const parsedQuery = parser.astify(countPuri.toQuery(), { database: Sonamu.config.database.database });
|
|
268
|
+
const leftJoinTables = getJoinTables(parsedQuery, ["LEFT JOIN"]);
|
|
269
|
+
const whereTables = getTableNamesFromWhere(parsedQuery);
|
|
270
|
+
const tablesToRemove = leftJoinTables.filter((j) => !whereTables.includes(j));
|
|
271
|
+
tablesToRemove.forEach((table) => {
|
|
272
|
+
countPuri.clearJoin(table);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
const countResult = await countPuri.clear("select").select({ total: Puri.rawNumber(`COUNT(*)::integer`) }).first();
|
|
276
|
+
if (debug) {
|
|
277
|
+
countPuri.debug();
|
|
278
|
+
}
|
|
279
|
+
return countResult?.total ?? 0;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* LIST 쿼리 실행 (내부 메서드)
|
|
283
|
+
*/
|
|
284
|
+
async executeListQuery(subset, qb, params, num, page, debug) {
|
|
285
|
+
if (params.queryMode === "count") {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
const limitedQb = (() => {
|
|
289
|
+
if (num === 0) {
|
|
290
|
+
return qb;
|
|
291
|
+
} else {
|
|
292
|
+
return qb.limit(num).offset(num * (page - 1));
|
|
293
|
+
}
|
|
294
|
+
})();
|
|
295
|
+
let unloadedRows = await limitedQb;
|
|
296
|
+
if (debug) {
|
|
297
|
+
qb.debug();
|
|
298
|
+
}
|
|
299
|
+
const loaders = this.loaderQueries[subset];
|
|
300
|
+
if (loaders && Array.isArray(loaders)) {
|
|
301
|
+
unloadedRows = await this.processLoaders(unloadedRows, loaders, debug);
|
|
302
|
+
}
|
|
303
|
+
return this.hydrate(unloadedRows);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* 재귀적 로더 처리
|
|
307
|
+
*/
|
|
308
|
+
async processLoaders(rows, loaders, debug) {
|
|
309
|
+
for (const resolveLoader of loaders) {
|
|
310
|
+
const { as, refId, qb: resolveLoaderQbFn, loaders: nestedLoaders } = resolveLoader;
|
|
311
|
+
const resolveLoaderQb = resolveLoaderQbFn(new PuriWrapper(this.getDB("r"), new UpsertBuilder()), rows.map((row) => row[refId]));
|
|
312
|
+
if (debug) {
|
|
313
|
+
resolveLoaderQb.debug();
|
|
314
|
+
}
|
|
315
|
+
let loadedRows = await resolveLoaderQb;
|
|
316
|
+
if (nestedLoaders && nestedLoaders.length > 0) {
|
|
317
|
+
loadedRows = await this.processLoaders(loadedRows, nestedLoaders, debug);
|
|
318
|
+
}
|
|
319
|
+
const subRowGroups = group(loadedRows, (row) => row.refId);
|
|
320
|
+
rows = rows.map((row) => {
|
|
321
|
+
row[as] = (subRowGroups[row[refId]] ?? []).map((r) => omit(r, ["refId"]));
|
|
322
|
+
return row;
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
return rows;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Flat 레코드를 중첩 객체로 변환
|
|
329
|
+
*
|
|
330
|
+
* - `user__name` → `{ user: { name } }`
|
|
331
|
+
* - nullable relation의 경우 id 필드가 null이면 객체 자체를 null로
|
|
332
|
+
*/
|
|
333
|
+
hydrate(rows) {
|
|
334
|
+
return rows.map((row) => {
|
|
335
|
+
const nestedKeys = Object.keys(row).filter((key) => key.includes("__"));
|
|
336
|
+
const groups = Object.groupBy(nestedKeys, (key) => key.split("__")[0]);
|
|
337
|
+
const nullKeys = Object.entries(groups).filter(([groupKey, fields]) => {
|
|
338
|
+
if (!fields || fields.length === 0) return false;
|
|
339
|
+
const idField = `${groupKey}__id`;
|
|
340
|
+
if (idField in row) {
|
|
341
|
+
return row[idField] === null;
|
|
342
|
+
}
|
|
343
|
+
return fields.every((field) => row[field] === null || Array.isArray(row[field]) && row[field].length === 0);
|
|
344
|
+
}).map(([key]) => key);
|
|
345
|
+
const hydrated = Object.keys(row).reduce((r, field) => {
|
|
346
|
+
if (!field.includes("__")) {
|
|
347
|
+
if (Array.isArray(row[field]) && isObject(row[field][0])) {
|
|
348
|
+
r[field] = this.hydrate(row[field]);
|
|
349
|
+
} else {
|
|
350
|
+
r[field] = row[field];
|
|
351
|
+
}
|
|
352
|
+
return r;
|
|
353
|
+
}
|
|
354
|
+
const parts = field.split("__");
|
|
355
|
+
const objPath = parts[0] + parts.slice(1).map((part) => `[${part}]`).join("");
|
|
356
|
+
r = set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
|
|
357
|
+
return r;
|
|
358
|
+
}, {});
|
|
359
|
+
nullKeys.forEach((nullKey) => {
|
|
360
|
+
hydrated[nullKey] = null;
|
|
361
|
+
});
|
|
362
|
+
return hydrated;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
BaseModel = new BaseModelClass();
|
|
367
|
+
}));
|
|
368
|
+
|
|
369
|
+
//#endregion
|
|
370
|
+
init_base_model();
|
|
371
|
+
export { BaseModel, BaseModelClass, init_base_model };
|
|
372
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1tb2RlbC5qcyIsIm5hbWVzIjpbIm1vZGVsTmFtZTogc3RyaW5nIiwic3Vic2V0UXVlcmllcz86IFRTdWJzZXRRdWVyaWVzIiwibG9hZGVyUXVlcmllcz86IFRMb2FkZXJRdWVyaWVzIiwidW5xS2V5czogc3RyaW5nW10iLCJ3aGVyZUluRmllbGQ6IHN0cmluZyB8IEtuZXguUmF3Iiwic2VsZWN0RmllbGQ6IHN0cmluZyIsInJlc3VsdElkczogbnVtYmVyW10iLCJjb3VudFJlc3VsdDogeyB0b3RhbD86IG51bWJlciB9Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFiYXNlL2Jhc2UtbW9kZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIGJpb21lLWlnbm9yZS1hbGwgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IFB1cmnsnZgg7YOA7J6F7J2AIOqwnOuzhCDrqqjrjbjsl5DshJwg7ZmV7KCV65CY66+A66GcIEJhc2VNb2RlbOyXkOyEnOuKlCBhbnnrpbwg7ZeI7Jqp7ZWoICovXG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgdHlwZSBMb2dnZXIgfSBmcm9tIFwiQGxvZ3RhcGUvbG9ndGFwZVwiO1xuaW1wb3J0IHsgdHlwZSBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGNsb25lRGVlcCwgY2x1c3RlciwgZ3JvdXAsIGlzT2JqZWN0LCBvbWl0LCBzZXQgfSBmcm9tIFwicmFkYXNoaVwiO1xuXG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpL3NvbmFtdVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IHR5cGUgRmlsdGVyT3BlcmF0b3IsIHR5cGUgRmlsdGVyUXVlcnkgfSBmcm9tIFwiLi4vZmlsdGVyL3R5cGVzXCI7XG5pbXBvcnQgeyBub3JtYWxpemVGaWx0ZXJRdWVyeSwgdmFsaWRhdGVTb25hbXVGaWx0ZXJzIH0gZnJvbSBcIi4uL2ZpbHRlci91dGlsc1wiO1xuaW1wb3J0IHsgY29udmVydERvbWFpblRvQ2F0ZWdvcnkgfSBmcm9tIFwiLi4vbG9nZ2VyL2NhdGVnb3J5XCI7XG5pbXBvcnQgeyB0eXBlIERhdGFiYXNlU2NoZW1hRXh0ZW5kLCB0eXBlIFNvbmFtdVF1ZXJ5TW9kZSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHsgdHlwZSBMaXN0UmVzdWx0IH0gZnJvbSBcIi4uL3V0aWxzL21vZGVsXCI7XG5pbXBvcnQgeyBnZXRKb2luVGFibGVzLCBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlIH0gZnJvbSBcIi4uL3V0aWxzL3NxbC1wYXJzZXJcIjtcbmltcG9ydCB7IHR5cGUgRW5oYW5jZXJNYXAsIHR5cGUgUmVzb2x2ZVN1YnNldEludGVyc2VjdGlvbiB9IGZyb20gXCIuL2Jhc2UtbW9kZWwudHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgREJQcmVzZXQgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgREIgfSBmcm9tIFwiLi9kYlwiO1xuaW1wb3J0IHsgUHVyaSB9IGZyb20gXCIuL3B1cmlcIjtcbmltcG9ydCB7XG4gIHR5cGUgSW5mZXJBbGxTdWJzZXRzLFxuICB0eXBlIFB1cmlMb2FkZXJRdWVyaWVzLFxuICB0eXBlIFB1cmlTdWJzZXRGbixcbn0gZnJvbSBcIi4vcHVyaS1zdWJzZXQudHlwZXNcIjtcbmltcG9ydCB7IFB1cmlXcmFwcGVyIH0gZnJvbSBcIi4vcHVyaS13cmFwcGVyXCI7XG5pbXBvcnQgeyB0eXBlIFVuaW9uRXh0cmFjdGVkVFRhYmxlcyB9IGZyb20gXCIuL3B1cmkudHlwZXNcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi91cHNlcnQtYnVpbGRlclwiO1xuXG50eXBlIFVua25vd25EQlJlY29yZCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vKipcbiAqIOuqqOuToCBNb2RlbCDtgbTrnpjsiqTsnZgg6riw67O4IO2BtOuemOyKpFxuICpcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0S2V5IC0g7ISc67iM7IWLIO2CpCDsnKDri4jsmKggKOyYiDogXCJBXCIgfCBcIlBcIiB8IFwiU1NcIilcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0TWFwcGluZyAtIOyEnOu4jOyFi+uzhCDstZzsooUg6rKw6rO8IO2DgOyehSDrp6TtlZFcbiAqIEB0ZW1wbGF0ZSBUU3Vic2V0UXVlcmllcyAtIOyEnOu4jOyFiyDsv7zrpqwg7ZWo7IiYIOqwneyytFxuICogQHRlbXBsYXRlIFRMb2FkZXJRdWVyaWVzIC0g7ISc67iM7IWL67OEIOuhnOuNlCDsv7zrpqwg67Cw7Je0IOqwneyytFxuICovXG5leHBvcnQgY2xhc3MgQmFzZU1vZGVsQ2xhc3M8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlcixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbmV2ZXIsXG4gIFRTdWJzZXRRdWVyaWVzIGV4dGVuZHMgUmVjb3JkPFRTdWJzZXRLZXksIFB1cmlTdWJzZXRGbj4gPSBuZXZlcixcbiAgVExvYWRlclF1ZXJpZXMgZXh0ZW5kcyBQdXJpTG9hZGVyUXVlcmllczxUU3Vic2V0S2V5PiA9IG5ldmVyLFxuPiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBsb2dnZXI6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgbW9kZWxOYW1lOiBzdHJpbmcgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgcHJvdGVjdGVkIHN1YnNldFF1ZXJpZXM/OiBUU3Vic2V0UXVlcmllcyxcbiAgICBwcm90ZWN0ZWQgbG9hZGVyUXVlcmllcz86IFRMb2FkZXJRdWVyaWVzLFxuICApIHtcbiAgICB0aGlzLmxvZ2dlciA9IGdldExvZ2dlcihjb252ZXJ0RG9tYWluVG9DYXRlZ29yeSh0aGlzLm1vZGVsTmFtZSwgXCJtb2RlbFwiKSk7XG4gIH1cblxuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCBuZXcgVXBzZXJ0QnVpbGRlcigpKTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKSB7XG4gICAgcmV0dXJuIERCLmRlc3Ryb3koKTtcbiAgfVxuXG4gIGFzeW5jIGdldEluc2VydGVkSWRzKFxuICAgIHdkYjogS25leCxcbiAgICByb3dzOiBVbmtub3duREJSZWNvcmRbXSxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICB1bnFLZXlGaWVsZHM6IHN0cmluZ1tdLFxuICAgIGNodW5rU2l6ZTogbnVtYmVyID0gNTAwLFxuICApIHtcbiAgICBpZiAoIXdkYikge1xuICAgICAgd2RiID0gdGhpcy5nZXREQihcIndcIik7XG4gICAgfVxuXG4gICAgbGV0IHVucUtleXM6IHN0cmluZ1tdO1xuICAgIGxldCB3aGVyZUluRmllbGQ6IHN0cmluZyB8IEtuZXguUmF3O1xuICAgIGxldCBzZWxlY3RGaWVsZDogc3RyaW5nO1xuXG4gICAgaWYgKHVucUtleUZpZWxkcy5sZW5ndGggPiAxKSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB3ZGIucmF3KGBDT05DQVRfV1MoJ18nLCAnJHt1bnFLZXlGaWVsZHMuam9pbihcIixcIil9JylgKTtcbiAgICAgIHNlbGVjdEZpZWxkID0gYCR7d2hlcmVJbkZpZWxkfSBhcyB0bXBVaWRgO1xuICAgICAgdW5xS2V5cyA9IHJvd3MubWFwKChyb3cpID0+IHVucUtleUZpZWxkcy5tYXAoKGZpZWxkKSA9PiByb3dbZmllbGRdKS5qb2luKFwiX1wiKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHNlbGVjdEZpZWxkID0gdW5xS2V5RmllbGRzWzBdO1xuICAgICAgdW5xS2V5cyA9IHJvd3MubWFwKChyb3cpID0+IHJvd1t1bnFLZXlGaWVsZHNbMF1dIGFzIHN0cmluZyk7XG4gICAgfVxuXG4gICAgbGV0IHJlc3VsdElkczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGl0ZW1zIG9mIGNsdXN0ZXIodW5xS2V5cywgY2h1bmtTaXplKSkge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQgYXMgc3RyaW5nLCBpdGVtcyk7XG4gICAgICByZXN1bHRJZHMgPSByZXN1bHRJZHMuY29uY2F0KFxuICAgICAgICBkYlJvd3MubWFwKChkYlJvdzogVW5rbm93bkRCUmVjb3JkKSA9PiBwYXJzZUludChTdHJpbmcoZGJSb3cuaWQpKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRJZHM7XG4gIH1cblxuICAvKipcbiAgICog7Yq57KCVIOyEnOu4jOyFi+yXkCDrjIDtlZwg7L+866asIOu5jOuNlCDtmo3rk51cbiAgICpcbiAgICogQHJldHVybnMgcWIgLSDsv7zrpqwg67mM642UICjsobDqsbQg7LaU6rCA7JqpKVxuICAgKiBAcmV0dXJucyBvblN1YnNldCAtIO2KueyglSDshJzruIzshYsg7KCE7JqpIO2DgOyeheydtCDtlYTsmpTtlaAg65WMIOyCrOyaqVxuICAgKi9cbiAgZ2V0U3Vic2V0UXVlcmllczxUIGV4dGVuZHMgVFN1YnNldEtleT4oc3Vic2V0OiBUKSB7XG4gICAgaWYgKCF0aGlzLnN1YnNldFF1ZXJpZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNldFF1ZXJpZXMgaXMgbm90IGRlZmluZWRcIik7XG4gICAgfVxuXG4gICAgY29uc3QgcHVyaVdyYXBwZXIgPSBuZXcgUHVyaVdyYXBwZXIodGhpcy5nZXREQihcInJcIiksIG5ldyBVcHNlcnRCdWlsZGVyKCkpO1xuICAgIGNvbnN0IHFiID0gdGhpcy5zdWJzZXRRdWVyaWVzW3N1YnNldF0/LihwdXJpV3JhcHBlcik7XG5cbiAgICAvLyBOb25BbGxvd2VkQXNTaW5nbGVUYWJsZTog64uo7J28IO2FjOydtOu4lCDsu6zrn7wg7KCR6re8IOuwqeyngOyaqSDrp4jsu6RcbiAgICB0eXBlIFFCVGFibGVzID0gVW5pb25FeHRyYWN0ZWRUVGFibGVzPFRTdWJzZXRLZXksIFRTdWJzZXRRdWVyaWVzPiAmIHtcbiAgICAgIE5vbkFsbG93ZWRBc1NpbmdsZVRhYmxlOiB7IF9fZnVsbHRleHRfXzogdHJ1ZSB9O1xuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcWI6IHFiIGFzIHVua25vd24gYXMgUHVyaTxEYXRhYmFzZVNjaGVtYUV4dGVuZCwgUUJUYWJsZXMsIHt9PixcbiAgICAgIG9uU3Vic2V0OiAoKF9zdWJzZXQ6IFRTdWJzZXRLZXkgfCByZWFkb25seSBUU3Vic2V0S2V5W10pID0+IHFiKSBhcyB7XG4gICAgICAgIC8vIOuLqOydvCDtgqRcbiAgICAgICAgPFMgZXh0ZW5kcyBUU3Vic2V0S2V5PihzdWJzZXQ6IFMpOiBSZXR1cm5UeXBlPFRTdWJzZXRRdWVyaWVzW1NdPjtcbiAgICAgICAgLy8g7YKkIOuwsOyXtCAtPiDqtZDsp5Htlakg67CY7ZmYXG4gICAgICAgIDxBcnIgZXh0ZW5kcyByZWFkb25seSBUU3Vic2V0S2V5W10+KFxuICAgICAgICAgIHN1YnNldHM6IFsuLi5BcnJdLFxuICAgICAgICApOiBSZXNvbHZlU3Vic2V0SW50ZXJzZWN0aW9uPEFyciwgVFN1YnNldFF1ZXJpZXM+O1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEVuaGFuY2VyIOqwneyytCDsg53shLEg7Zes7Y28XG4gICAqIO2DgOyehSDqsoDspp0g67CPIOy2lOuhoOydhCDrj4TsmYDspIxcbiAgICovXG4gIGNyZWF0ZUVuaGFuY2VyczxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxcbiAgICAgIFQsXG4gICAgICBJbmZlckFsbFN1YnNldHM8VFN1YnNldFF1ZXJpZXMsIFRMb2FkZXJRdWVyaWVzPixcbiAgICAgIFRTdWJzZXRNYXBwaW5nLFxuICAgICAgVFN1YnNldFF1ZXJpZXNcbiAgICA+LFxuICApIHtcbiAgICByZXR1cm4gZW5oYW5jZXJzO1xuICB9XG5cbiAgLyoqXG4gICAqIOyEnOu4jOyFiyDsv7zrpqwg7Iuk7ZaJXG4gICAqXG4gICAqIDEuIFNvbmFtdSDtlYTthLAg7KCB7JqpICjtg4DsnoUg67OA7ZmYIO2PrO2VqClcbiAgICogMi4g7L+866asIOyLpO2WiSAocGFnaW5hdGlvbiDsoIHsmqkpXG4gICAqIDMuIOuhnOuNlCDsi6TtlokgKDE6TiwgTjpNIOq0gOqzhCDrjbDsnbTthLAg66Gc65SpKVxuICAgKiA0LiBIeWRyYXRlIChmbGF0IOKGkiDspJHssqkg6rCd7LK0KVxuICAgKiA1LiBFbmhhbmNlciDsoIHsmqkgKHZpcnR1YWwg7ZWE65OcIOqzhOyCsClcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGVTdWJzZXRRdWVyeTxcbiAgICBUIGV4dGVuZHMgVFN1YnNldEtleSxcbiAgICBUQ29tcHV0ZWRSZXN1bHRzIGV4dGVuZHMgSW5mZXJBbGxTdWJzZXRzPFRTdWJzZXRRdWVyaWVzLCBUTG9hZGVyUXVlcmllcz4sXG4gICAgTFAgZXh0ZW5kcyB7XG4gICAgICBudW0/OiBudW1iZXI7XG4gICAgICBwYWdlPzogbnVtYmVyO1xuICAgICAgcXVlcnlNb2RlPzogU29uYW11UXVlcnlNb2RlO1xuICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgfSxcbiAgPihcbiAgICBwYXJhbXM6IHtcbiAgICAgIHN1YnNldDogVDtcbiAgICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+O1xuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIG51bTogbnVtYmVyO1xuICAgICAgICBwYWdlOiBudW1iZXI7XG4gICAgICAgIHF1ZXJ5TW9kZT86IFNvbmFtdVF1ZXJ5TW9kZTtcbiAgICAgICAgc29uYW11RmlsdGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICB9O1xuICAgICAgZGVidWc/OiBib29sZWFuO1xuICAgICAgb3B0aW1pemVDb3VudFF1ZXJ5PzogYm9vbGVhbjtcbiAgICB9ICYgRW5oYW5jZXJQYXJhbTxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+LFxuICApOiBQcm9taXNlPExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPj4ge1xuICAgIGNvbnN0IHsgc3Vic2V0LCBxYiwgcGFyYW1zOiBxdWVyeVBhcmFtcywgZGVidWcgPSBmYWxzZSwgb3B0aW1pemVDb3VudFF1ZXJ5ID0gZmFsc2UgfSA9IHBhcmFtcztcblxuICAgIGlmICghdGhpcy5sb2FkZXJRdWVyaWVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsb2FkZXJRdWVyaWVzIGlzIG5vdCBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIC8vIFNvbmFtdSBGaWx0ZXIg7KCB7JqpXG4gICAgaWYgKHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcikge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbHRlciA9IG5vcm1hbGl6ZUZpbHRlclF1ZXJ5KHF1ZXJ5UGFyYW1zLnNvbmFtdUZpbHRlcik7XG4gICAgICB0aGlzLmFwcGx5U29uYW11RmlsdGVycyhxYiwgbm9ybWFsaXplZEZpbHRlcik7XG4gICAgfVxuXG4gICAgY29uc3QgeyBudW0sIHBhZ2UgfSA9IHF1ZXJ5UGFyYW1zO1xuXG4gICAgLy8gQ09VTlQg7L+866asIOyLpO2WiSAocXVlcnlNb2RlOiBsaXN07J28IOuVjOuKlCAwIOumrO2EtClcbiAgICBjb25zdCB0b3RhbCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNvdW50UXVlcnkocWIsIHF1ZXJ5UGFyYW1zLCBkZWJ1Zywgb3B0aW1pemVDb3VudFF1ZXJ5KTtcblxuICAgIGlmIChxdWVyeVBhcmFtcz8ucXVlcnlNb2RlID09PSBcImNvdW50XCIpIHtcbiAgICAgIHJldHVybiB7IHRvdGFsIH0gYXMgTGlzdFJlc3VsdDxMUCwgVFN1YnNldE1hcHBpbmdbVF0+O1xuICAgIH1cblxuICAgIC8vIExJU1Qg7L+866asIOyLpO2WiVxuICAgIGNvbnN0IGNvbXB1dGVkUm93cyA9IGF3YWl0IHRoaXMuZXhlY3V0ZUxpc3RRdWVyeShzdWJzZXQsIHFiLCBxdWVyeVBhcmFtcywgbnVtLCBwYWdlLCBkZWJ1Zyk7XG5cbiAgICAvLyBFbmhhbmNlciDsoIHsmqlcbiAgICBjb25zdCBlbmhhbmNlciA9IChwYXJhbXMgYXMgYW55KS5lbmhhbmNlcnM/LltzdWJzZXRdO1xuICAgIGNvbnN0IGVuaGFuY2VkUm93cyA9IChhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGNvbXB1dGVkUm93cy5tYXAoKHJvdykgPT4gZW5oYW5jZXI/Lihyb3cpID8/IHJvdyksXG4gICAgKSkgYXMgVFN1YnNldE1hcHBpbmdbVF1bXTtcblxuICAgIC8vIEludGVybmFsIO2VhOuTnCDsoJzqsbBcbiAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldCh0aGlzLm1vZGVsTmFtZSk7XG4gICAgY29uc3QgaW50ZXJuYWxGaWVsZHMgPSBlbnRpdHkuc3Vic2V0c0ludGVybmFsW3N1YnNldF0gPz8gW107XG4gICAgY29uc3Qgcm93cyA9XG4gICAgICBpbnRlcm5hbEZpZWxkcy5sZW5ndGggPiAwXG4gICAgICAgID8gZW5oYW5jZWRSb3dzLm1hcCgocm93KSA9PiB0aGlzLm9taXRJbnRlcm5hbEZpZWxkcyhyb3csIGludGVybmFsRmllbGRzKSlcbiAgICAgICAgOiBlbmhhbmNlZFJvd3M7XG5cbiAgICBpZiAocXVlcnlQYXJhbXMucXVlcnlNb2RlID09PSBcImxpc3RcIikge1xuICAgICAgLy8g66as7Iqk7Yq466eMIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cyB9IGFzIExpc3RSZXN1bHQ8TFAsIFRTdWJzZXRNYXBwaW5nW1RdPjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8g65GY64ukIOumrO2EtFxuICAgICAgcmV0dXJuIHsgcm93cywgdG90YWwgfSBhcyBMaXN0UmVzdWx0PExQLCBUU3Vic2V0TWFwcGluZ1tUXT47XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOqwneyytOyXkOyEnCBpbnRlcm5hbCDtlYTrk5wg7KCc6rGwXG4gICAqIOykkeyyqSDtlYTrk5wo7JiIOiBcInVzZXIuZW1haWxcIikg67CPIOuwsOyXtCjsmIg6IFwiZW1wbG95ZWVzLnNhbGFyeVwiKeuPhCDsspjrpqxcbiAgICovXG4gIG9taXRJbnRlcm5hbEZpZWxkczxUIGV4dGVuZHMgb2JqZWN0Pihyb3c6IFQsIGZpZWxkczogc3RyaW5nW10pOiBUIHtcbiAgICBjb25zdCByZXN1bHQgPSBjbG9uZURlZXAocm93KTtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykge1xuICAgICAgdGhpcy5kZWxldGVGaWVsZChyZXN1bHQsIGZpZWxkLnNwbGl0KFwiLlwiKSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRmlsdGVyUXVlcnnrpbwgUHVyaSBRdWVyeUJ1aWxkZXLsl5Ag7KCB7JqpXG4gICAqXG4gICAqIEBwYXJhbSBxYiBQdXJpIFF1ZXJ5QnVpbGRlciDsnbjsiqTthLTsiqRcbiAgICogQHBhcmFtIGZpbHRlcnMgRmlsdGVyUXVlcnkg6rCd7LK0XG4gICAqL1xuICBwcm90ZWN0ZWQgYXBwbHlTb25hbXVGaWx0ZXJzPFRFbnRpdHkgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgcWI6IFB1cmk8YW55LCBhbnksIGFueT4sXG4gICAgZmlsdGVycz86IEZpbHRlclF1ZXJ5PFRFbnRpdHk+LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIWZpbHRlcnMpIHJldHVybjtcblxuICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KHRoaXMubW9kZWxOYW1lKTtcblxuICAgIC8vIDEuIO2VhO2EsCDqsoDspp0gKEVudGl0eSDquLDrsJgpXG4gICAgdmFsaWRhdGVTb25hbXVGaWx0ZXJzKGZpbHRlcnMsIGVudGl0eSk7XG5cbiAgICAvLyAyLiDqsoDspp3rkJwg7ZWE7YSwIOyggeyaqVxuICAgIGNvbnN0IHB1cmkgPSBxYiBhcyBhbnk7XG5cbiAgICBmb3IgKGNvbnN0IFtmaWVsZCwgY29uZGl0aW9uXSBvZiBPYmplY3QuZW50cmllcyhmaWx0ZXJzKSkge1xuICAgICAgaWYgKGNvbmRpdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGNvbmRpdGlvbiA9PT0gbnVsbCkgY29udGludWU7XG5cbiAgICAgIC8vIO2FjOydtOu4lOuqhS7tlYTrk5zrqoUg7ZiV7Iud7Jy866GcIOuzgO2ZmFxuICAgICAgY29uc3QgZnVsbEZpZWxkID0gZW50aXR5LmdldEZ1bGxGaWVsZE5hbWUoZmllbGQpO1xuXG4gICAgICAvLyDsp4HsoJEg6rCSIChlceyZgCDrj5nsnbwpXG4gICAgICBpZiAodHlwZW9mIGNvbmRpdGlvbiAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGNvbmRpdGlvbikpIHtcbiAgICAgICAgcHVyaS53aGVyZShmdWxsRmllbGQsIGNvbmRpdGlvbik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyDsl7DsgrDsnpAg6rCd7LK0XG4gICAgICBmb3IgKGNvbnN0IFtvcGVyYXRvciwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbmRpdGlvbikpIHtcbiAgICAgICAgdGhpcy5hcHBseU9wZXJhdG9yKHFiLCBmdWxsRmllbGQsIG9wZXJhdG9yIGFzIEZpbHRlck9wZXJhdG9yLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOuLqOydvCDsl7DsgrDsnpDrpbwgUXVlcnlCdWlsZGVy7JeQIOyggeyaqVxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseU9wZXJhdG9yKFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIGZpZWxkOiBzdHJpbmcsXG4gICAgb3BlcmF0b3I6IEZpbHRlck9wZXJhdG9yLFxuICAgIHZhbHVlOiB1bmtub3duLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwdXJpID0gcWIgYXMgYW55O1xuXG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSBcImVxXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJuZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIiE9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJndFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj5cIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImd0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJsdFwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjxcIiwgdmFsdWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBcImx0ZVwiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIjw9XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpblwiOlxuICAgICAgICBwdXJpLndoZXJlSW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJub3RJblwiOlxuICAgICAgICBwdXJpLndoZXJlTm90SW4oZmllbGQsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJjb250YWluc1wiOlxuICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcImxpa2VcIiwgYCUke3ZhbHVlfSVgKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJzdGFydHNXaXRoXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwibGlrZVwiLCBgJHt2YWx1ZX0lYCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiZW5kc1dpdGhcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCJsaWtlXCIsIGAlJHt2YWx1ZX1gKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJpc051bGxcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiaXNOb3ROdWxsXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiIT1cIiwgbnVsbCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYmVmb3JlXCI6XG4gICAgICAgIHB1cmkud2hlcmUoZmllbGQsIFwiPFwiLCB2YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiYWZ0ZXJcIjpcbiAgICAgICAgcHVyaS53aGVyZShmaWVsZCwgXCI+XCIsIHZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJiZXR3ZWVuXCI6IHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIGNvbnN0IFttaW4sIG1heF0gPSB2YWx1ZTtcbiAgICAgICAgICBwdXJpLndoZXJlKGZpZWxkLCBcIj49XCIsIG1pbikud2hlcmUoZmllbGQsIFwiPD1cIiwgbWF4KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS53YXJuKGBVbnN1cHBvcnRlZCBvcGVyYXRvcjogJHtvcGVyYXRvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog7KSR7LKpIO2VhOuTnCDsgq3soJwgKOuwsOyXtCDrgrQg6rCd7LK064+EIOyymOumrClcbiAgICovXG4gIGRlbGV0ZUZpZWxkKG9iajogYW55LCBwYXJ0czogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBpZiAoIW9iaiB8fCB0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBvYmouZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtICYmIHR5cGVvZiBpdGVtID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBkZWxldGUgaXRlbVtwYXJ0c1swXV07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBvYmpbcGFydHNbMF1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBwYXJ0cztcbiAgICBjb25zdCBuZXh0ID0gb2JqW2ZpcnN0XTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG5leHQpKSB7XG4gICAgICBuZXh0Lm1hcCgoaXRlbSkgPT4gdGhpcy5kZWxldGVGaWVsZChpdGVtLCByZXN0KSk7XG4gICAgfSBlbHNlIGlmIChuZXh0ICYmIHR5cGVvZiBuZXh0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aGlzLmRlbGV0ZUZpZWxkKG5leHQsIHJlc3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDT1VOVCDsv7zrpqwg7Iuk7ZaJICjrgrTrtoAg66mU7ISc65OcKVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlQ291bnRRdWVyeShcbiAgICBxYjogUHVyaTxhbnksIGFueSwgYW55PixcbiAgICBwYXJhbXM6IHsgcXVlcnlNb2RlPzogXCJsaXN0XCIgfCBcImNvdW50XCIgfCBcImJvdGhcIiB9LFxuICAgIGRlYnVnOiBib29sZWFuLFxuICAgIG9wdGltaXplQ291bnRRdWVyeTogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBpZiAocGFyYW1zLnF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGNvbnN0IGNvdW50UHVyaSA9IHFiLmNsb25lKCkuY2xlYXIoXCJvcmRlclwiKS5jbGVhcihcImxpbWl0XCIpLmNsZWFyKFwib2Zmc2V0XCIpO1xuXG4gICAgaWYgKG9wdGltaXplQ291bnRRdWVyeSkge1xuICAgICAgY29uc3QgeyBkZWZhdWx0OiBTcWxQYXJzZXIgfSA9IGF3YWl0IGltcG9ydChcIm5vZGUtc3FsLXBhcnNlclwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG4gICAgICBjb25zdCBwYXJzZWRRdWVyeSA9IHBhcnNlci5hc3RpZnkoY291bnRQdXJpLnRvUXVlcnkoKSwge1xuICAgICAgICBkYXRhYmFzZTogU29uYW11LmNvbmZpZy5kYXRhYmFzZS5kYXRhYmFzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBsZWZ0Sm9pblRhYmxlcyA9IGdldEpvaW5UYWJsZXMocGFyc2VkUXVlcnksIFtcIkxFRlQgSk9JTlwiXSk7XG4gICAgICBjb25zdCB3aGVyZVRhYmxlcyA9IGdldFRhYmxlTmFtZXNGcm9tV2hlcmUocGFyc2VkUXVlcnkpO1xuXG4gICAgICBjb25zdCB0YWJsZXNUb1JlbW92ZSA9IGxlZnRKb2luVGFibGVzLmZpbHRlcigoaikgPT4gIXdoZXJlVGFibGVzLmluY2x1ZGVzKGopKTtcbiAgICAgIHRhYmxlc1RvUmVtb3ZlLmZvckVhY2goKHRhYmxlKSA9PiB7XG4gICAgICAgIGNvdW50UHVyaS5jbGVhckpvaW4odGFibGUpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ09VTlQoKinroZwg7KCE7LK0IOugiOy9lOuTnCDsiJjrpbwg6rOE7IKwXG4gICAgLy8gVE9ETzogcWLsnZggRElTVElOQ1TqsIAg7J6I64qUIOqyveyasCDsspjrpqztlbTslbwg7ZWoXG4gICAgY29uc3QgY291bnRSZXN1bHQ6IHsgdG90YWw/OiBudW1iZXIgfSA9IGF3YWl0IGNvdW50UHVyaVxuICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAuc2VsZWN0KHsgdG90YWw6IFB1cmkucmF3TnVtYmVyKGBDT1VOVCgqKTo6aW50ZWdlcmApIH0pXG4gICAgICAuZmlyc3QoKTtcblxuICAgIGlmIChkZWJ1Zykge1xuICAgICAgY291bnRQdXJpLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvdW50UmVzdWx0Py50b3RhbCA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIExJU1Qg7L+866asIOyLpO2WiSAo64K067aAIOuplOyEnOuTnClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXhlY3V0ZUxpc3RRdWVyeTxUIGV4dGVuZHMgVFN1YnNldEtleT4oXG4gICAgc3Vic2V0OiBULFxuICAgIHFiOiBQdXJpPGFueSwgYW55LCBhbnk+LFxuICAgIHBhcmFtczogeyBxdWVyeU1vZGU/OiBcImxpc3RcIiB8IFwiY291bnRcIiB8IFwiYm90aFwiIH0sXG4gICAgbnVtOiBudW1iZXIsXG4gICAgcGFnZTogbnVtYmVyLFxuICAgIGRlYnVnOiBib29sZWFuLFxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgaWYgKHBhcmFtcy5xdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGxpbWl0ZWRRYiA9ICgoKSA9PiB7XG4gICAgICBpZiAobnVtID09PSAwKSB7XG4gICAgICAgIHJldHVybiBxYjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBxYi5saW1pdChudW0pLm9mZnNldChudW0gKiAocGFnZSAtIDEpKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIGxldCB1bmxvYWRlZFJvd3MgPSBhd2FpdCBsaW1pdGVkUWI7XG5cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIHFiLmRlYnVnKCk7XG4gICAgfVxuXG4gICAgLy8g66Gc642UIOyymOumrFxuICAgIGNvbnN0IGxvYWRlcnMgPSAodGhpcy5sb2FkZXJRdWVyaWVzIGFzIGFueSlbc3Vic2V0XTtcbiAgICBpZiAobG9hZGVycyAmJiBBcnJheS5pc0FycmF5KGxvYWRlcnMpKSB7XG4gICAgICB1bmxvYWRlZFJvd3MgPSBhd2FpdCB0aGlzLnByb2Nlc3NMb2FkZXJzKHVubG9hZGVkUm93cywgbG9hZGVycywgZGVidWcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmh5ZHJhdGUodW5sb2FkZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDsnqzqt4DsoIEg66Gc642UIOyymOumrFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzTG9hZGVycyhyb3dzOiBhbnlbXSwgbG9hZGVyczogYW55W10sIGRlYnVnOiBib29sZWFuKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIGZvciAoY29uc3QgcmVzb2x2ZUxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBjb25zdCB7IGFzLCByZWZJZCwgcWI6IHJlc29sdmVMb2FkZXJRYkZuLCBsb2FkZXJzOiBuZXN0ZWRMb2FkZXJzIH0gPSByZXNvbHZlTG9hZGVyO1xuXG4gICAgICBjb25zdCByZXNvbHZlTG9hZGVyUWIgPSByZXNvbHZlTG9hZGVyUWJGbihcbiAgICAgICAgbmV3IFB1cmlXcmFwcGVyKHRoaXMuZ2V0REIoXCJyXCIpLCBuZXcgVXBzZXJ0QnVpbGRlcigpKSxcbiAgICAgICAgcm93cy5tYXAoKHJvdykgPT4gcm93W3JlZklkXSksXG4gICAgICApO1xuXG4gICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgcmVzb2x2ZUxvYWRlclFiLmRlYnVnKCk7XG4gICAgICB9XG5cbiAgICAgIGxldCBsb2FkZWRSb3dzID0gKGF3YWl0IHJlc29sdmVMb2FkZXJRYikgYXMgYW55W107XG5cbiAgICAgIC8vIOykkeyyqSBsb2FkZXJz6rCAIOyeiOycvOuptCDsnqzqt4Ag7LKY66asXG4gICAgICBpZiAobmVzdGVkTG9hZGVycyAmJiBuZXN0ZWRMb2FkZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbG9hZGVkUm93cyA9IGF3YWl0IHRoaXMucHJvY2Vzc0xvYWRlcnMobG9hZGVkUm93cywgbmVzdGVkTG9hZGVycywgZGVidWcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdWJSb3dHcm91cHMgPSBncm91cChsb2FkZWRSb3dzLCAocm93KSA9PiByb3cucmVmSWQpO1xuXG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbYXNdID0gKHN1YlJvd0dyb3Vwc1tyb3dbcmVmSWRdXSA/PyBbXSkubWFwKChyKSA9PiBvbWl0KHIsIFtcInJlZklkXCJdKSk7XG4gICAgICAgIHJldHVybiByb3c7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGF0IOugiOy9lOuTnOulvCDspJHssqkg6rCd7LK066GcIOuzgO2ZmFxuICAgKlxuICAgKiAtIGB1c2VyX19uYW1lYCDihpIgYHsgdXNlcjogeyBuYW1lIH0gfWBcbiAgICogLSBudWxsYWJsZSByZWxhdGlvbuydmCDqsr3smrAgaWQg7ZWE65Oc6rCAIG51bGzsnbTrqbQg6rCd7LK0IOyekOyytOulvCBudWxs66GcXG4gICAqL1xuICBoeWRyYXRlPFQgZXh0ZW5kcyBVbmtub3duREJSZWNvcmQ+KHJvd3M6IFRbXSk6IFRbXSB7XG4gICAgcmV0dXJuIHJvd3MubWFwKChyb3c6IFQpID0+IHtcbiAgICAgIC8vIG51bGxhYmxlIHJlbGF0aW9uIOyymOumrDog6re466O57J2YIGlkIO2VhOuTnOqwgCBudWxs7J2066m0IOqwneyytCDsoITssrTrpbwgbnVsbOuhnFxuICAgICAgY29uc3QgbmVzdGVkS2V5cyA9IE9iamVjdC5rZXlzKHJvdykuZmlsdGVyKChrZXkpID0+IGtleS5pbmNsdWRlcyhcIl9fXCIpKTtcbiAgICAgIGNvbnN0IGdyb3VwcyA9IE9iamVjdC5ncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcblxuICAgICAgLy8gaWQg7ZWE65Oc6rCAIG51bGzsnbgg6re466O5IOywvuq4sCAo7JiIOiBwYXJlbnRfX2lk6rCAIG51bGzsnbTrqbQgcGFyZW50IOq3uOujuSDsoITssrTqsIAgbnVsbClcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBzKVxuICAgICAgICAuZmlsdGVyKChbZ3JvdXBLZXksIGZpZWxkc10pID0+IHtcbiAgICAgICAgICBpZiAoIWZpZWxkcyB8fCBmaWVsZHMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAvLyDqt7jro7nsnZggaWQg7ZWE65OcIOywvuq4sCAo7JiIOiBcInBhcmVudF9faWRcIilcbiAgICAgICAgICBjb25zdCBpZEZpZWxkID0gYCR7Z3JvdXBLZXl9X19pZGA7XG4gICAgICAgICAgaWYgKGlkRmllbGQgaW4gcm93KSB7XG4gICAgICAgICAgICAvLyBpZCDtlYTrk5zqsIAgbnVsbOydtOuptCDqsJ3ssrQg7KCE7LK06rCAIG51bGxcbiAgICAgICAgICAgIHJldHVybiByb3dbaWRGaWVsZF0gPT09IG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gaWQg7ZWE65Oc6rCAIOyXhuycvOuptCDquLDsobQg66Gc7KeBOiDrqqjrk6Ag7ZWE65Oc6rCAIG51bGzsnbjsp4Ag7ZmV7J24XG4gICAgICAgICAgcmV0dXJuIGZpZWxkcy5ldmVyeShcbiAgICAgICAgICAgIChmaWVsZCkgPT5cbiAgICAgICAgICAgICAgcm93W2ZpZWxkXSA9PT0gbnVsbCB8fCAoQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiByb3dbZmllbGRdLmxlbmd0aCA9PT0gMCksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm1hcCgoW2tleV0pID0+IGtleSk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIC8vIOydvOuwmCDtlYTrk5w6IOuwsOyXtCDrgrQg6rCd7LK066m0IOyerOq3gCBoeWRyYXRlXG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSkpIHtcbiAgICAgICAgICAgIHJbZmllbGRdID0gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g7KSR7LKpIO2VhOuTnCDsspjrpqw6IHVzZXJfX25hbWUg4oaSIHVzZXJbbmFtZV1cbiAgICAgICAgY29uc3QgcGFydHMgPSBmaWVsZC5zcGxpdChcIl9fXCIpO1xuICAgICAgICBjb25zdCBvYmpQYXRoID1cbiAgICAgICAgICBwYXJ0c1swXSArXG4gICAgICAgICAgcGFydHNcbiAgICAgICAgICAgIC5zbGljZSgxKVxuICAgICAgICAgICAgLm1hcCgocGFydCkgPT4gYFske3BhcnR9XWApXG4gICAgICAgICAgICAuam9pbihcIlwiKTtcblxuICAgICAgICByID0gc2V0KFxuICAgICAgICAgIHIsXG4gICAgICAgICAgb2JqUGF0aCxcbiAgICAgICAgICByb3dbZmllbGRdICYmIEFycmF5LmlzQXJyYXkocm93W2ZpZWxkXSkgJiYgaXNPYmplY3Qocm93W2ZpZWxkXVswXSlcbiAgICAgICAgICAgID8gdGhpcy5oeWRyYXRlKHJvd1tmaWVsZF0pXG4gICAgICAgICAgICA6IHJvd1tmaWVsZF0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHI7XG4gICAgICB9LCB7fSBhcyBVbmtub3duREJSZWNvcmQpO1xuXG4gICAgICAvLyBudWxsIHJlbGF0aW9uIOyymOumrFxuICAgICAgbnVsbEtleXMuZm9yRWFjaCgobnVsbEtleSkgPT4ge1xuICAgICAgICBoeWRyYXRlZFtudWxsS2V5XSA9IG51bGw7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGh5ZHJhdGVkO1xuICAgIH0pIGFzIFRbXTtcbiAgfVxufVxuXG4vKipcbiAqIEVuaGFuY2VyIO2MjOudvOuvuO2EsCDsobDqsbTrtoAg7YOA7J6FXG4gKiBSZXF1aXJlZEVuaGFuY2VyS2V5c+qwgCDsl4bsnLzrqbQgZW5oYW5jZXJzIOyEoO2DneyggSwg7J6I7Jy866m0IO2VhOyImFxuICovXG50eXBlIEVuaGFuY2VyUGFyYW08XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldFF1ZXJpZXMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgUHVyaVN1YnNldEZuPixcbj4gPSBbUmVxdWlyZWRFbmhhbmNlcktleXM8VFN1YnNldEtleSwgVENvbXB1dGVkUmVzdWx0cywgVFN1YnNldE1hcHBpbmc+XSBleHRlbmRzIFtuZXZlcl1cbiAgPyB7IGVuaGFuY2Vycz86IEVuaGFuY2VyTWFwPFRTdWJzZXRLZXksIFRDb21wdXRlZFJlc3VsdHMsIFRTdWJzZXRNYXBwaW5nLCBUU3Vic2V0UXVlcmllcz4gfVxuICA6IHsgZW5oYW5jZXJzOiBFbmhhbmNlck1hcDxUU3Vic2V0S2V5LCBUQ29tcHV0ZWRSZXN1bHRzLCBUU3Vic2V0TWFwcGluZywgVFN1YnNldFF1ZXJpZXM+IH07XG5cbnR5cGUgUmVxdWlyZWRFbmhhbmNlcktleXM8XG4gIFRTdWJzZXRLZXkgZXh0ZW5kcyBzdHJpbmcsXG4gIFRDb21wdXRlZFJlc3VsdHMgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55PixcbiAgVFN1YnNldE1hcHBpbmcgZXh0ZW5kcyBSZWNvcmQ8VFN1YnNldEtleSwgYW55Pixcbj4gPSB7XG4gIFtLIGluIFRTdWJzZXRLZXldOiBUQ29tcHV0ZWRSZXN1bHRzW0tdIGV4dGVuZHMgVFN1YnNldE1hcHBpbmdbS10gPyBuZXZlciA6IEs7XG59W1RTdWJzZXRLZXldO1xuXG5leHBvcnQgY29uc3QgQmFzZU1vZGVsID0gbmV3IEJhc2VNb2RlbENsYXNzKCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBTXVDO3NCQUNrQjthQUVxQjtnQkFDakI7a0JBR2U7VUFHbEQ7WUFDSTtvQkFNZTtzQkFFSTtDQVlwQyxpQkFBYixNQUtFO0VBQ0EsQUFBbUI7RUFFbkIsWUFDRSxBQUFnQkEsWUFBb0IsS0FBSyxZQUFZLE1BQ3JELEFBQVVDLGVBQ1YsQUFBVUMsZUFDVjtHQUhnQjtHQUNOO0dBQ0E7QUFFVixRQUFLLFNBQVMsVUFBVSx3QkFBd0IsS0FBSyxXQUFXLFFBQVEsQ0FBQzs7RUFHM0UsTUFBTSxPQUF1QjtBQUMzQixVQUFPLEdBQUcsTUFBTSxNQUFNOztFQUd4QixRQUFRLE9BQThCO0dBRXBDLE1BQU0sTUFBTSxHQUFHLHVCQUF1QixDQUFDLGVBQWUsTUFBTTtBQUM1RCxPQUFJLEtBQUs7QUFDUCxXQUFPOztHQUlULE1BQU0sS0FBSyxLQUFLLE1BQU0sTUFBTTtBQUM1QixVQUFPLElBQUksWUFBWSxJQUFJLElBQUksZUFBZSxDQUFDOztFQUdqRCxNQUFNLFVBQVU7QUFD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
|