sonamu 0.5.7 → 0.7.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/.swcrc.project-default +18 -0
- package/bin/cli.js +24 -0
- package/dist/ai/agents/agent.d.ts +11 -0
- package/dist/ai/agents/agent.d.ts.map +1 -0
- package/dist/ai/agents/agent.js +65 -0
- package/dist/ai/agents/index.d.ts +3 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +4 -0
- package/dist/ai/agents/types.d.ts +43 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +3 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/providers/rtzr/api.d.ts +22 -0
- package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/api.js +28 -0
- package/dist/ai/providers/rtzr/error.d.ts +18 -0
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/error.js +29 -0
- package/dist/ai/providers/rtzr/index.d.ts +5 -0
- package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/index.js +6 -0
- package/dist/ai/providers/rtzr/model.d.ts +52 -0
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/model.js +137 -0
- package/dist/ai/providers/rtzr/options.d.ts +7 -0
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/options.js +47 -0
- package/dist/ai/providers/rtzr/provider.d.ts +18 -0
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/provider.js +54 -0
- package/dist/ai/providers/rtzr/utils.d.ts +19 -0
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/utils.js +88 -0
- package/dist/api/base-frame.d.ts +2 -2
- package/dist/api/base-frame.d.ts.map +1 -1
- package/dist/api/base-frame.js +13 -2
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +71 -2
- package/dist/api/code-converters.d.ts +58 -14
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +258 -2
- package/dist/api/config.d.ts +90 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +25 -0
- package/dist/api/context.d.ts +4 -2
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +3 -2
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +235 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +9 -2
- package/dist/api/sonamu.d.ts +10 -24
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +514 -2
- package/dist/api/validator.d.ts +6 -0
- package/dist/api/validator.d.ts.map +1 -0
- package/dist/api/validator.js +81 -0
- package/dist/bin/build-config.d.ts +6 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +15 -2
- package/dist/bin/cli.js +519 -2
- package/dist/bin/hot-hook-register.d.ts +11 -0
- package/dist/bin/hot-hook-register.d.ts.map +1 -0
- package/dist/bin/hot-hook-register.js +21 -0
- package/dist/bin/loader-register.d.ts +2 -0
- package/dist/bin/loader-register.d.ts.map +1 -0
- package/dist/bin/loader-register.js +34 -0
- package/dist/database/_batch_update.d.ts +5 -3
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +95 -2
- package/dist/database/base-model.d.ts +96 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +390 -2
- package/dist/database/base-model.types.d.ts +93 -0
- package/dist/database/base-model.types.d.ts.map +1 -0
- package/dist/database/base-model.types.js +10 -0
- package/dist/database/code-generator.d.ts +1 -1
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +54 -2
- package/dist/database/db.d.ts +6 -21
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +129 -2
- package/dist/database/puri-subset.test-d.js +81 -0
- package/dist/database/puri-subset.types.d.ts +123 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -0
- package/dist/database/puri-subset.types.js +16 -0
- package/dist/database/puri-wrapper.d.ts +13 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +41 -23
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +601 -2
- package/dist/database/puri.types.d.ts +25 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +6 -2
- package/dist/database/transaction-context.d.ts +1 -1
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +14 -2
- package/dist/database/upsert-builder.d.ts +9 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +365 -2
- package/dist/entity/entity-manager.d.ts +167 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +130 -2
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +750 -2
- 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 +29 -2
- 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 +85 -2
- package/dist/file-storage/driver.d.ts +1 -1
- package/dist/file-storage/driver.d.ts.map +1 -1
- package/dist/file-storage/driver.js +79 -2
- package/dist/file-storage/file-storage.js +75 -2
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -2
- package/dist/migration/code-generation.d.ts +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +614 -2
- package/dist/migration/migration-set.d.ts +2 -10
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +213 -2
- package/dist/migration/migrator.d.ts +24 -82
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +330 -2
- package/dist/migration/postgresql-schema-reader.d.ts +51 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
- package/dist/migration/postgresql-schema-reader.js +245 -0
- package/dist/migration/types.d.ts +6 -38
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +3 -2
- package/dist/naite/messaging-types.d.ts +43 -0
- package/dist/naite/messaging-types.d.ts.map +1 -0
- package/dist/naite/messaging-types.js +7 -0
- package/dist/naite/naite-reporter.d.ts +41 -0
- package/dist/naite/naite-reporter.d.ts.map +1 -0
- package/dist/naite/naite-reporter.js +102 -0
- package/dist/naite/naite.d.ts +95 -0
- package/dist/naite/naite.d.ts.map +1 -0
- package/dist/naite/naite.js +316 -0
- package/dist/stream/index.js +3 -2
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +38 -2
- package/dist/syncer/api-parser.d.ts +10 -0
- package/dist/syncer/api-parser.d.ts.map +1 -0
- package/dist/syncer/api-parser.js +240 -0
- package/dist/syncer/checksum.d.ts +21 -0
- package/dist/syncer/checksum.d.ts.map +1 -0
- package/dist/syncer/checksum.js +98 -0
- package/dist/syncer/code-generator.d.ts +20 -0
- package/dist/syncer/code-generator.d.ts.map +1 -0
- package/dist/syncer/code-generator.js +161 -0
- package/dist/syncer/entity-operations.d.ts +17 -0
- package/dist/syncer/entity-operations.d.ts.map +1 -0
- package/dist/syncer/entity-operations.js +59 -0
- package/dist/syncer/file-patterns.d.ts +29 -0
- package/dist/syncer/file-patterns.d.ts.map +1 -0
- package/dist/syncer/file-patterns.js +38 -0
- package/dist/syncer/index.d.ts +6 -0
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +9 -2
- package/dist/syncer/module-loader.d.ts +35 -0
- package/dist/syncer/module-loader.d.ts.map +1 -0
- package/dist/syncer/module-loader.js +87 -0
- package/dist/syncer/syncer.d.ts +98 -106
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +422 -2
- package/dist/template/entity-converter.d.ts +14 -0
- package/dist/template/entity-converter.d.ts.map +1 -0
- package/dist/template/entity-converter.js +108 -0
- package/dist/template/helpers.d.ts +23 -0
- package/dist/template/helpers.d.ts.map +1 -0
- package/dist/template/helpers.js +64 -0
- package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
- package/dist/template/implementations/entity.template.d.ts.map +1 -0
- package/dist/template/implementations/entity.template.js +86 -0
- package/dist/{templates → template/implementations}/generated.template.d.ts +3 -4
- package/dist/template/implementations/generated.template.d.ts.map +1 -0
- package/dist/template/implementations/generated.template.js +249 -0
- package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -4
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_http.template.js +131 -0
- package/dist/{templates → template/implementations}/generated_sso.template.d.ts +4 -5
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_sso.template.js +134 -0
- package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
- package/dist/template/implementations/init_types.template.d.ts.map +1 -0
- package/dist/template/implementations/init_types.template.js +38 -0
- package/dist/template/implementations/model.template.d.ts +17 -0
- package/dist/template/implementations/model.template.d.ts.map +1 -0
- package/dist/template/implementations/model.template.js +181 -0
- package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
- package/dist/template/implementations/model_test.template.d.ts.map +1 -0
- package/dist/template/implementations/model_test.template.js +35 -0
- package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
- package/dist/template/implementations/service.template.d.ts.map +1 -0
- package/dist/template/implementations/service.template.js +201 -0
- package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
- package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
- package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_select.template.js +55 -0
- package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
- package/dist/template/implementations/view_form.template.d.ts.map +1 -0
- package/dist/template/implementations/view_form.template.js +337 -0
- package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_all_select.template.js +31 -0
- package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_async_select.template.js +105 -0
- package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
- package/dist/template/implementations/view_list.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list.template.js +475 -0
- package/dist/template/implementations/view_list_columns.template.d.ts +17 -0
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list_columns.template.js +49 -0
- package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
- package/dist/template/implementations/view_search_input.template.js +64 -0
- package/dist/template/index.d.ts +7 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +8 -0
- package/dist/template/template-manager.d.ts +56 -0
- package/dist/template/template-manager.d.ts.map +1 -0
- package/dist/template/template-manager.js +125 -0
- package/dist/template/template-types.d.ts +16 -0
- package/dist/template/template-types.d.ts.map +1 -0
- package/dist/template/template-types.js +7 -0
- package/dist/template/template.d.ts +49 -0
- package/dist/template/template.d.ts.map +1 -0
- package/dist/template/template.js +60 -0
- package/dist/template/zod-converter.d.ts +51 -0
- package/dist/template/zod-converter.d.ts.map +1 -0
- package/dist/template/zod-converter.js +449 -0
- 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 +89 -2
- package/dist/testing/fixture-manager.d.ts +42 -11
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +623 -2
- package/dist/types/types.d.ts +747 -143
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +546 -2
- package/dist/typings/knex.d.js +3 -2
- package/dist/utils/async-utils.d.ts +7 -0
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +57 -2
- package/dist/utils/console-util.d.ts +2 -0
- package/dist/utils/console-util.d.ts.map +1 -0
- package/dist/utils/console-util.js +6 -0
- package/dist/utils/controller.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +29 -2
- package/dist/utils/esm-utils.d.ts +39 -0
- package/dist/utils/esm-utils.d.ts.map +1 -0
- package/dist/utils/esm-utils.js +49 -0
- package/dist/utils/formatter.d.ts +3 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +110 -0
- package/dist/utils/fs-utils.d.ts +1 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +17 -2
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +6 -2
- package/dist/utils/model.js +22 -2
- package/dist/utils/object-utils.d.ts +44 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +191 -0
- package/dist/utils/path-utils.d.ts +89 -0
- package/dist/utils/path-utils.d.ts.map +1 -0
- package/dist/utils/path-utils.js +60 -0
- package/dist/utils/process-utils.d.ts +13 -0
- package/dist/utils/process-utils.d.ts.map +1 -0
- package/dist/utils/process-utils.js +36 -0
- package/dist/utils/sql-parser.d.ts +5 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +46 -2
- package/dist/utils/type-utils.d.ts +23 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +45 -0
- package/dist/utils/utils.d.ts +10 -7
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +72 -2
- 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 +19 -2
- package/package.json +65 -27
- package/src/ai/agents/agent.ts +87 -0
- package/src/ai/agents/index.ts +2 -0
- package/src/ai/agents/types.ts +47 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/providers/rtzr/api.ts +37 -0
- package/src/ai/providers/rtzr/error.ts +34 -0
- package/src/ai/providers/rtzr/index.ts +4 -0
- package/src/ai/providers/rtzr/model.ts +201 -0
- package/src/ai/providers/rtzr/options.ts +49 -0
- package/src/ai/providers/rtzr/provider.ts +91 -0
- package/src/ai/providers/rtzr/utils.ts +127 -0
- package/src/api/base-frame.ts +4 -2
- package/src/api/caster.ts +17 -23
- package/src/api/code-converters.ts +178 -535
- package/src/api/config.ts +125 -0
- package/src/api/context.ts +7 -17
- package/src/api/decorators.ts +176 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +190 -167
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +8 -1
- package/src/bin/cli.ts +258 -124
- package/src/bin/hot-hook-register.ts +22 -0
- package/src/bin/loader-register.ts +38 -0
- package/src/database/_batch_update.ts +46 -31
- package/src/database/base-model.ts +390 -182
- package/src/database/base-model.types.ts +155 -0
- package/src/database/code-generator.ts +13 -32
- package/src/database/db.ts +40 -96
- package/src/database/puri-subset.test-d.ts +471 -0
- package/src/database/puri-subset.types.ts +195 -0
- package/src/database/puri-wrapper.ts +58 -67
- package/src/database/puri.ts +229 -148
- package/src/database/puri.types.ts +76 -30
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +262 -132
- package/src/entity/entity-manager.ts +48 -36
- package/src/entity/entity.ts +330 -248
- package/src/exceptions/error-handler.ts +3 -3
- package/src/exceptions/so-exceptions.ts +11 -11
- package/src/file-storage/driver.ts +5 -5
- package/src/file-storage/file-storage.ts +2 -2
- package/src/index.ts +18 -10
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +199 -571
- package/src/migration/mysql-schema-reader.ts.txt +272 -0
- package/src/migration/postgresql-schema-reader.ts +310 -0
- package/src/migration/types.ts +6 -39
- package/src/naite/messaging-types.ts +51 -0
- package/src/naite/naite-reporter.ts +128 -0
- package/src/naite/naite.ts +415 -0
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +282 -0
- package/src/syncer/checksum.ts +140 -0
- package/src/syncer/code-generator.ts +198 -0
- package/src/syncer/entity-operations.ts +65 -0
- package/src/syncer/file-patterns.ts +56 -0
- package/src/syncer/index.ts +6 -0
- package/src/syncer/module-loader.ts +128 -0
- package/src/syncer/syncer.ts +389 -1453
- package/src/template/entity-converter.ts +114 -0
- package/src/template/helpers.ts +81 -0
- package/src/{templates → template/implementations}/entity.template.ts +7 -7
- package/src/{templates → template/implementations}/generated.template.ts +101 -101
- package/src/{templates → template/implementations}/generated_http.template.ts +27 -57
- package/src/template/implementations/generated_sso.template.ts +151 -0
- package/src/{templates → template/implementations}/init_types.template.ts +5 -7
- package/src/{templates → template/implementations}/model.template.ts +52 -43
- package/src/{templates → template/implementations}/model_test.template.ts +5 -5
- package/src/{templates → template/implementations}/service.template.ts +66 -82
- package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
- package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +4 -20
- package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
- package/src/{templates → template/implementations}/view_form.template.ts +40 -83
- package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_id_async_select.template.ts +10 -24
- package/src/{templates → template/implementations}/view_list.template.ts +60 -152
- package/src/{templates → template/implementations}/view_list_columns.template.ts +5 -11
- package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
- package/src/template/index.ts +6 -0
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +105 -0
- package/src/template/zod-converter.ts +525 -0
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +472 -359
- package/src/types/types.ts +553 -308
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +23 -10
- package/src/utils/console-util.ts +4 -0
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +59 -0
- package/src/utils/formatter.ts +109 -0
- package/src/utils/fs-utils.ts +1 -1
- package/src/utils/lodash-able.ts +1 -4
- package/src/utils/object-utils.ts +217 -0
- package/src/utils/path-utils.ts +99 -0
- package/src/utils/process-utils.ts +46 -0
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +66 -43
- package/src/utils/zod-error.ts +3 -4
- package/dist/api/base-frame.js.map +0 -1
- package/dist/api/caster.js.map +0 -1
- package/dist/api/code-converters.js.map +0 -1
- package/dist/api/context.js.map +0 -1
- package/dist/api/decorators.js.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/sonamu.js.map +0 -1
- package/dist/bin/build-config.js.map +0 -1
- package/dist/bin/cli-wrapper.d.ts +0 -3
- package/dist/bin/cli-wrapper.d.ts.map +0 -1
- package/dist/bin/cli-wrapper.js +0 -3
- package/dist/bin/cli-wrapper.js.map +0 -1
- package/dist/bin/cli.js.map +0 -1
- package/dist/database/_batch_update.js.map +0 -1
- package/dist/database/base-model.js.map +0 -1
- package/dist/database/code-generator.js.map +0 -1
- package/dist/database/db.js.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
- package/dist/database/puri-wrapper.js.map +0 -1
- package/dist/database/puri.js.map +0 -1
- package/dist/database/puri.types.js.map +0 -1
- package/dist/database/transaction-context.js.map +0 -1
- package/dist/database/upsert-builder.js.map +0 -1
- package/dist/entity/entity-manager.js.map +0 -1
- package/dist/entity/entity-utils.d.ts +0 -61
- package/dist/entity/entity-utils.d.ts.map +0 -1
- package/dist/entity/entity-utils.js +0 -2
- package/dist/entity/entity-utils.js.map +0 -1
- package/dist/entity/entity.js.map +0 -1
- package/dist/exceptions/error-handler.js.map +0 -1
- package/dist/exceptions/so-exceptions.js.map +0 -1
- package/dist/file-storage/driver.js.map +0 -1
- package/dist/file-storage/file-storage.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migration/code-generation.js.map +0 -1
- package/dist/migration/migration-set.js.map +0 -1
- package/dist/migration/migrator.js.map +0 -1
- package/dist/migration/types.js.map +0 -1
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/sse.js.map +0 -1
- package/dist/syncer/index.js.map +0 -1
- package/dist/syncer/syncer.js.map +0 -1
- package/dist/templates/base-template.d.ts +0 -13
- package/dist/templates/base-template.d.ts.map +0 -1
- package/dist/templates/base-template.js +0 -2
- package/dist/templates/base-template.js.map +0 -1
- package/dist/templates/entity.template.d.ts.map +0 -1
- package/dist/templates/entity.template.js +0 -2
- package/dist/templates/entity.template.js.map +0 -1
- package/dist/templates/generated.template.d.ts.map +0 -1
- package/dist/templates/generated.template.js +0 -2
- package/dist/templates/generated.template.js.map +0 -1
- package/dist/templates/generated_http.template.d.ts.map +0 -1
- package/dist/templates/generated_http.template.js +0 -2
- package/dist/templates/generated_http.template.js.map +0 -1
- package/dist/templates/generated_sso.template.d.ts.map +0 -1
- package/dist/templates/generated_sso.template.js +0 -2
- package/dist/templates/generated_sso.template.js.map +0 -1
- package/dist/templates/index.d.ts +0 -2
- package/dist/templates/index.d.ts.map +0 -1
- package/dist/templates/index.js +0 -2
- package/dist/templates/index.js.map +0 -1
- package/dist/templates/init_types.template.d.ts.map +0 -1
- package/dist/templates/init_types.template.js +0 -2
- package/dist/templates/init_types.template.js.map +0 -1
- package/dist/templates/model.template.d.ts +0 -17
- package/dist/templates/model.template.d.ts.map +0 -1
- package/dist/templates/model.template.js +0 -2
- package/dist/templates/model.template.js.map +0 -1
- package/dist/templates/model_test.template.d.ts.map +0 -1
- package/dist/templates/model_test.template.js +0 -2
- package/dist/templates/model_test.template.js.map +0 -1
- package/dist/templates/service.template.d.ts.map +0 -1
- package/dist/templates/service.template.js +0 -2
- package/dist/templates/service.template.js.map +0 -1
- package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
- package/dist/templates/view_enums_buttonset.template.js +0 -2
- package/dist/templates/view_enums_buttonset.template.js.map +0 -1
- package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
- package/dist/templates/view_enums_dropdown.template.js +0 -2
- package/dist/templates/view_enums_dropdown.template.js.map +0 -1
- package/dist/templates/view_enums_select.template.d.ts.map +0 -1
- package/dist/templates/view_enums_select.template.js +0 -2
- package/dist/templates/view_enums_select.template.js.map +0 -1
- package/dist/templates/view_form.template.d.ts.map +0 -1
- package/dist/templates/view_form.template.js +0 -2
- package/dist/templates/view_form.template.js.map +0 -1
- package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_all_select.template.js +0 -2
- package/dist/templates/view_id_all_select.template.js.map +0 -1
- package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_async_select.template.js +0 -2
- package/dist/templates/view_id_async_select.template.js.map +0 -1
- package/dist/templates/view_list.template.d.ts.map +0 -1
- package/dist/templates/view_list.template.js +0 -2
- package/dist/templates/view_list.template.js.map +0 -1
- package/dist/templates/view_list_columns.template.d.ts +0 -17
- package/dist/templates/view_list_columns.template.d.ts.map +0 -1
- package/dist/templates/view_list_columns.template.js +0 -2
- package/dist/templates/view_list_columns.template.js.map +0 -1
- package/dist/templates/view_search_input.template.d.ts.map +0 -1
- package/dist/templates/view_search_input.template.js +0 -2
- package/dist/templates/view_search_input.template.js.map +0 -1
- package/dist/testing/_relation-graph.js.map +0 -1
- package/dist/testing/fixture-manager.js.map +0 -1
- package/dist/types/types.js.map +0 -1
- package/dist/typings/knex.d.js.map +0 -1
- package/dist/utils/async-utils.js.map +0 -1
- package/dist/utils/controller.js.map +0 -1
- package/dist/utils/fs-utils.js.map +0 -1
- package/dist/utils/lodash-able.js.map +0 -1
- package/dist/utils/model.js.map +0 -1
- package/dist/utils/sql-parser.js.map +0 -1
- package/dist/utils/utils.js.map +0 -1
- package/dist/utils/zod-error.js.map +0 -1
- package/src/bin/cli-wrapper.ts +0 -75
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
- package/src/templates/base-template.ts +0 -19
- package/src/templates/generated_sso.template.ts +0 -138
- package/src/templates/index.ts +0 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import inflection from "inflection";
|
|
4
|
+
import ts from "typescript";
|
|
5
|
+
import { registeredApis } from "../api/decorators.js";
|
|
6
|
+
import { validateMethodName } from "../api/validator.js";
|
|
7
|
+
/**
|
|
8
|
+
* TypeScript 파일을 파싱하여 API 메소드 정보를 추출합니다.
|
|
9
|
+
* @api 데코레이터가 붙은 메소드들의 타입 정보를 분석합니다.
|
|
10
|
+
* @param filePath - 파싱할 TypeScript 파일의 절대 경로
|
|
11
|
+
* @returns API 메소드 정보 배열 (타입 파라미터, 파라미터, 리턴 타입 등)
|
|
12
|
+
*/ export async function readApisFromFile(filePath) {
|
|
13
|
+
if (!filePath.endsWith(".ts")) {
|
|
14
|
+
throw new Error(`${filePath} does not seem to be a TypeScript file. Please check the file path. We only support parsing TypeScript files.`);
|
|
15
|
+
}
|
|
16
|
+
const sourceFile = ts.createSourceFile(filePath, (await readFile(filePath)).toString(), ts.ScriptTarget.Latest);
|
|
17
|
+
const methods = [];
|
|
18
|
+
let modelName = "UnknownModel";
|
|
19
|
+
let methodName = "unknownMethod";
|
|
20
|
+
const visitor = (node)=>{
|
|
21
|
+
if (ts.isClassDeclaration(node)) {
|
|
22
|
+
if (node.name && ts.isIdentifier(node.name)) {
|
|
23
|
+
modelName = node.name.escapedText.toString().replace(/Class$/, "");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (ts.isMethodDeclaration(node)) {
|
|
27
|
+
if (ts.isIdentifier(node.name)) {
|
|
28
|
+
methodName = node.name.escapedText.toString();
|
|
29
|
+
validateMethodName(methodName);
|
|
30
|
+
}
|
|
31
|
+
const typeParameters = (node.typeParameters ?? []).map((typeParam)=>{
|
|
32
|
+
const tp = typeParam;
|
|
33
|
+
return {
|
|
34
|
+
t: "type-param",
|
|
35
|
+
id: tp.name.escapedText.toString(),
|
|
36
|
+
constraint: tp.constraint ? resolveTypeNode(tp.constraint) : undefined
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
const parameters = node.parameters.map((paramDec, index)=>{
|
|
40
|
+
const defaultDef = printNode(paramDec.initializer, sourceFile);
|
|
41
|
+
// 기본값이 있는 경우 paramDec.type가 undefined로 나옴
|
|
42
|
+
return resolveParamDec({
|
|
43
|
+
name: paramDec.name,
|
|
44
|
+
type: paramDec.type,
|
|
45
|
+
optional: paramDec.questionToken !== undefined || paramDec.initializer !== undefined,
|
|
46
|
+
defaultDef
|
|
47
|
+
}, index);
|
|
48
|
+
});
|
|
49
|
+
if (node.type === undefined) {
|
|
50
|
+
throw new Error(`리턴 타입이 기재되지 않은 메소드 ${modelName}.${methodName}`);
|
|
51
|
+
}
|
|
52
|
+
const returnType = resolveTypeNode(node.type);
|
|
53
|
+
methods.push({
|
|
54
|
+
modelName,
|
|
55
|
+
methodName,
|
|
56
|
+
typeParameters,
|
|
57
|
+
parameters,
|
|
58
|
+
returnType
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
ts.forEachChild(node, visitor);
|
|
62
|
+
};
|
|
63
|
+
visitor(sourceFile);
|
|
64
|
+
if (methods.length === 0) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
// 현재 파일의 등록된 API 필터
|
|
68
|
+
const currentModelApis = registeredApis.filter((api)=>{
|
|
69
|
+
return methods.find((method)=>method.modelName === api.modelName && method.methodName === api.methodName);
|
|
70
|
+
});
|
|
71
|
+
if (currentModelApis.length === 0) {
|
|
72
|
+
// const p = path.join(tmpdir(), "sonamu-syncer-error.json");
|
|
73
|
+
// writeFileSync(p, JSON.stringify(registeredApis, null, 2));
|
|
74
|
+
// execSync(`open ${p}`);
|
|
75
|
+
throw new Error(`현재 파일에 사전 등록된 API가 없습니다. ${filePath}`);
|
|
76
|
+
}
|
|
77
|
+
// 등록된 API에 현재 메소드 타입 정보 확장
|
|
78
|
+
const extendedApis = currentModelApis.map((api)=>{
|
|
79
|
+
const foundMethod = methods.find((method)=>method.modelName === api.modelName && method.methodName === api.methodName);
|
|
80
|
+
if (!foundMethod) {
|
|
81
|
+
throw new Error(`API ${api.modelName}.${api.methodName} not found in ${filePath}`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
...api,
|
|
85
|
+
typeParameters: foundMethod?.typeParameters,
|
|
86
|
+
parameters: foundMethod?.parameters,
|
|
87
|
+
returnType: foundMethod?.returnType
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
return extendedApis;
|
|
91
|
+
}
|
|
92
|
+
function resolveTypeNode(typeNode) {
|
|
93
|
+
switch(typeNode?.kind){
|
|
94
|
+
case ts.SyntaxKind.AnyKeyword:
|
|
95
|
+
return "any";
|
|
96
|
+
case ts.SyntaxKind.UnknownKeyword:
|
|
97
|
+
return "unknown";
|
|
98
|
+
case ts.SyntaxKind.StringKeyword:
|
|
99
|
+
return "string";
|
|
100
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
101
|
+
return "number";
|
|
102
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
103
|
+
return "boolean";
|
|
104
|
+
case ts.SyntaxKind.UndefinedKeyword:
|
|
105
|
+
return "undefined";
|
|
106
|
+
case ts.SyntaxKind.NullKeyword:
|
|
107
|
+
return "null";
|
|
108
|
+
case ts.SyntaxKind.VoidKeyword:
|
|
109
|
+
return "void";
|
|
110
|
+
case ts.SyntaxKind.LiteralType:
|
|
111
|
+
{
|
|
112
|
+
const literal = typeNode.literal;
|
|
113
|
+
if (ts.isStringLiteral(literal)) {
|
|
114
|
+
return {
|
|
115
|
+
t: "string-literal",
|
|
116
|
+
value: literal.text
|
|
117
|
+
};
|
|
118
|
+
} else if (ts.isNumericLiteral(literal)) {
|
|
119
|
+
return {
|
|
120
|
+
t: "numeric-literal",
|
|
121
|
+
value: Number(literal.text)
|
|
122
|
+
};
|
|
123
|
+
} else {
|
|
124
|
+
if (literal.kind === ts.SyntaxKind.NullKeyword) {
|
|
125
|
+
return "null";
|
|
126
|
+
} else if (literal.kind === ts.SyntaxKind.UndefinedKeyword) {
|
|
127
|
+
return "undefined";
|
|
128
|
+
} else if (literal.kind === ts.SyntaxKind.TrueKeyword) {
|
|
129
|
+
return "true";
|
|
130
|
+
} else if (literal.kind === ts.SyntaxKind.FalseKeyword) {
|
|
131
|
+
return "false";
|
|
132
|
+
}
|
|
133
|
+
throw new Error("알 수 없는 리터럴");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
case ts.SyntaxKind.ArrayType:
|
|
137
|
+
{
|
|
138
|
+
const arrNode = typeNode;
|
|
139
|
+
return {
|
|
140
|
+
t: "array",
|
|
141
|
+
elementsType: resolveTypeNode(arrNode.elementType)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
case ts.SyntaxKind.TypeLiteral:
|
|
145
|
+
{
|
|
146
|
+
const literalNode = typeNode;
|
|
147
|
+
return {
|
|
148
|
+
t: "object",
|
|
149
|
+
props: literalNode.members.map((member)=>{
|
|
150
|
+
if (ts.isIndexSignatureDeclaration(member)) {
|
|
151
|
+
assert(member.parameters[0]);
|
|
152
|
+
const res = resolveParamDec({
|
|
153
|
+
name: member.parameters[0].name,
|
|
154
|
+
type: member.parameters[0].type
|
|
155
|
+
});
|
|
156
|
+
return resolveParamDec({
|
|
157
|
+
name: {
|
|
158
|
+
escapedText: `[${res.name}${res.optional ? "?" : ""}: ${res.type}]`
|
|
159
|
+
},
|
|
160
|
+
type: member.type
|
|
161
|
+
});
|
|
162
|
+
} else {
|
|
163
|
+
return resolveParamDec({
|
|
164
|
+
name: member.name,
|
|
165
|
+
type: member.type,
|
|
166
|
+
optional: member.questionToken !== undefined
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
case ts.SyntaxKind.TypeReference:
|
|
173
|
+
return {
|
|
174
|
+
t: "ref",
|
|
175
|
+
id: typeNode.typeName.escapedText.toString(),
|
|
176
|
+
args: typeNode.typeArguments?.map((typeArg)=>resolveTypeNode(typeArg))
|
|
177
|
+
};
|
|
178
|
+
case ts.SyntaxKind.UnionType:
|
|
179
|
+
return {
|
|
180
|
+
t: "union",
|
|
181
|
+
types: typeNode.types.map((type)=>resolveTypeNode(type))
|
|
182
|
+
};
|
|
183
|
+
case ts.SyntaxKind.IntersectionType:
|
|
184
|
+
return {
|
|
185
|
+
t: "intersection",
|
|
186
|
+
types: typeNode.types.map((type)=>resolveTypeNode(type))
|
|
187
|
+
};
|
|
188
|
+
case ts.SyntaxKind.IndexedAccessType:
|
|
189
|
+
return {
|
|
190
|
+
t: "indexed-access",
|
|
191
|
+
object: resolveTypeNode(typeNode.objectType),
|
|
192
|
+
index: resolveTypeNode(typeNode.indexType)
|
|
193
|
+
};
|
|
194
|
+
case ts.SyntaxKind.TupleType:
|
|
195
|
+
if (ts.isTupleTypeNode(typeNode)) {
|
|
196
|
+
return {
|
|
197
|
+
t: "tuple-type",
|
|
198
|
+
elements: typeNode.elements.map((elem)=>resolveTypeNode(elem))
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
case undefined:
|
|
203
|
+
throw new Error(`typeNode undefined`);
|
|
204
|
+
}
|
|
205
|
+
console.debug(typeNode);
|
|
206
|
+
throw new Error(`알 수 없는 SyntaxKind ${typeNode.kind}`);
|
|
207
|
+
}
|
|
208
|
+
function resolveParamDec(paramDec, index = 0) {
|
|
209
|
+
const name = paramDec.name;
|
|
210
|
+
const type = resolveTypeNode(paramDec.type);
|
|
211
|
+
if (name === undefined) {
|
|
212
|
+
console.debug({
|
|
213
|
+
name,
|
|
214
|
+
type,
|
|
215
|
+
paramDec
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
const result = {
|
|
219
|
+
name: name.escapedText ? name.escapedText.toString() : `nonameAt${index}`,
|
|
220
|
+
type,
|
|
221
|
+
optional: paramDec.optional === true,
|
|
222
|
+
defaultDef: paramDec?.defaultDef
|
|
223
|
+
};
|
|
224
|
+
// 구조분해할당의 경우 타입이름 사용
|
|
225
|
+
if (ts.isObjectBindingPattern(name) && ts.isTypeReferenceNode(paramDec.type) && ts.isIdentifier(paramDec.type.typeName)) {
|
|
226
|
+
result.name = inflection.camelize(paramDec.type.typeName.text, true);
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
function printNode(node, sourceFile) {
|
|
231
|
+
if (node === undefined) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
const printer = ts.createPrinter({
|
|
235
|
+
newLine: ts.NewLineKind.LineFeed
|
|
236
|
+
});
|
|
237
|
+
return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zeW5jZXIvYXBpLXBhcnNlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgaW5mbGVjdGlvbiBmcm9tIFwiaW5mbGVjdGlvblwiO1xuaW1wb3J0IHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5pbXBvcnQgeyB0eXBlIEV4dGVuZGVkQXBpLCByZWdpc3RlcmVkQXBpcyB9IGZyb20gXCIuLi9hcGkvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVNZXRob2ROYW1lIH0gZnJvbSBcIi4uL2FwaS92YWxpZGF0b3JcIjtcbmltcG9ydCB0eXBlIHsgQXBpUGFyYW0sIEFwaVBhcmFtVHlwZSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBBYnNvbHV0ZVBhdGggfSBmcm9tIFwiLi4vdXRpbHMvcGF0aC11dGlsc1wiO1xuXG4vKipcbiAqIFR5cGVTY3JpcHQg7YyM7J287J2EIO2MjOyLse2VmOyXrCBBUEkg66mU7IaM65OcIOygleuztOulvCDstpTstpztlanri4jri6QuXG4gKiBAYXBpIOuNsOy9lOugiOydtO2EsOqwgCDrtpnsnYAg66mU7IaM65Oc65Ok7J2YIO2DgOyehSDsoJXrs7Trpbwg67aE7ISd7ZWp64uI64ukLlxuICogQHBhcmFtIGZpbGVQYXRoIC0g7YyM7Iux7ZWgIFR5cGVTY3JpcHQg7YyM7J287J2YIOygiOuMgCDqsr3roZxcbiAqIEByZXR1cm5zIEFQSSDrqZTshozrk5wg7KCV67O0IOuwsOyXtCAo7YOA7J6FIO2MjOudvOuvuO2EsCwg7YyM652866+47YSwLCDrpqzthLQg7YOA7J6FIOuTsSlcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRBcGlzRnJvbUZpbGUoZmlsZVBhdGg6IEFic29sdXRlUGF0aCk6IFByb21pc2U8RXh0ZW5kZWRBcGlbXT4ge1xuICBpZiAoIWZpbGVQYXRoLmVuZHNXaXRoKFwiLnRzXCIpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7ZmlsZVBhdGh9IGRvZXMgbm90IHNlZW0gdG8gYmUgYSBUeXBlU2NyaXB0IGZpbGUuIFBsZWFzZSBjaGVjayB0aGUgZmlsZSBwYXRoLiBXZSBvbmx5IHN1cHBvcnQgcGFyc2luZyBUeXBlU2NyaXB0IGZpbGVzLmAsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHNvdXJjZUZpbGUgPSB0cy5jcmVhdGVTb3VyY2VGaWxlKFxuICAgIGZpbGVQYXRoLFxuICAgIChhd2FpdCByZWFkRmlsZShmaWxlUGF0aCkpLnRvU3RyaW5nKCksXG4gICAgdHMuU2NyaXB0VGFyZ2V0LkxhdGVzdCxcbiAgKTtcblxuICBjb25zdCBtZXRob2RzOiBPbWl0PEV4dGVuZGVkQXBpLCBcInBhdGhcIiB8IFwib3B0aW9uc1wiPltdID0gW107XG4gIGxldCBtb2RlbE5hbWU6IHN0cmluZyA9IFwiVW5rbm93bk1vZGVsXCI7XG4gIGxldCBtZXRob2ROYW1lOiBzdHJpbmcgPSBcInVua25vd25NZXRob2RcIjtcbiAgY29uc3QgdmlzaXRvciA9IChub2RlOiB0cy5Ob2RlKSA9PiB7XG4gICAgaWYgKHRzLmlzQ2xhc3NEZWNsYXJhdGlvbihub2RlKSkge1xuICAgICAgaWYgKG5vZGUubmFtZSAmJiB0cy5pc0lkZW50aWZpZXIobm9kZS5uYW1lKSkge1xuICAgICAgICBtb2RlbE5hbWUgPSBub2RlLm5hbWUuZXNjYXBlZFRleHQudG9TdHJpbmcoKS5yZXBsYWNlKC9DbGFzcyQvLCBcIlwiKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRzLmlzTWV0aG9kRGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgIGlmICh0cy5pc0lkZW50aWZpZXIobm9kZS5uYW1lKSkge1xuICAgICAgICBtZXRob2ROYW1lID0gbm9kZS5uYW1lLmVzY2FwZWRUZXh0LnRvU3RyaW5nKCk7XG4gICAgICAgIHZhbGlkYXRlTWV0aG9kTmFtZShtZXRob2ROYW1lKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHlwZVBhcmFtZXRlcnM6IEFwaVBhcmFtVHlwZS5UeXBlUGFyYW1bXSA9IChub2RlLnR5cGVQYXJhbWV0ZXJzID8/IFtdKS5tYXAoXG4gICAgICAgICh0eXBlUGFyYW0pID0+IHtcbiAgICAgICAgICBjb25zdCB0cCA9IHR5cGVQYXJhbSBhcyB0cy5UeXBlUGFyYW1ldGVyRGVjbGFyYXRpb247XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdDogXCJ0eXBlLXBhcmFtXCIsXG4gICAgICAgICAgICBpZDogdHAubmFtZS5lc2NhcGVkVGV4dC50b1N0cmluZygpLFxuICAgICAgICAgICAgY29uc3RyYWludDogdHAuY29uc3RyYWludCA/IHJlc29sdmVUeXBlTm9kZSh0cC5jb25zdHJhaW50KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHBhcmFtZXRlcnM6IEFwaVBhcmFtW10gPSBub2RlLnBhcmFtZXRlcnMubWFwKChwYXJhbURlYywgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgZGVmYXVsdERlZiA9IHByaW50Tm9kZShwYXJhbURlYy5pbml0aWFsaXplciwgc291cmNlRmlsZSk7XG5cbiAgICAgICAgLy8g6riw67O46rCS7J20IOyeiOuKlCDqsr3smrAgcGFyYW1EZWMudHlwZeqwgCB1bmRlZmluZWTroZwg64KY7Ji0XG5cbiAgICAgICAgcmV0dXJuIHJlc29sdmVQYXJhbURlYyhcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBwYXJhbURlYy5uYW1lLFxuICAgICAgICAgICAgdHlwZTogcGFyYW1EZWMudHlwZSBhcyB0cy5UeXBlTm9kZSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBwYXJhbURlYy5xdWVzdGlvblRva2VuICE9PSB1bmRlZmluZWQgfHwgcGFyYW1EZWMuaW5pdGlhbGl6ZXIgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGRlZmF1bHREZWYsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpbmRleCxcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgaWYgKG5vZGUudHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihg66as7YS0IO2DgOyeheydtCDquLDsnqzrkJjsp4Ag7JWK7J2AIOuplOyGjOuTnCAke21vZGVsTmFtZX0uJHttZXRob2ROYW1lfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgcmV0dXJuVHlwZSA9IHJlc29sdmVUeXBlTm9kZShub2RlLnR5cGUpO1xuXG4gICAgICBtZXRob2RzLnB1c2goe1xuICAgICAgICBtb2RlbE5hbWUsXG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIHR5cGVQYXJhbWV0ZXJzLFxuICAgICAgICBwYXJhbWV0ZXJzLFxuICAgICAgICByZXR1cm5UeXBlLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRzLmZvckVhY2hDaGlsZChub2RlLCB2aXNpdG9yKTtcbiAgfTtcbiAgdmlzaXRvcihzb3VyY2VGaWxlKTtcblxuICBpZiAobWV0aG9kcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvLyDtmITsnqwg7YyM7J287J2YIOuTseuhneuQnCBBUEkg7ZWE7YSwXG4gIGNvbnN0IGN1cnJlbnRNb2RlbEFwaXMgPSByZWdpc3RlcmVkQXBpcy5maWx0ZXIoKGFwaSkgPT4ge1xuICAgIHJldHVybiBtZXRob2RzLmZpbmQoXG4gICAgICAobWV0aG9kKSA9PiBtZXRob2QubW9kZWxOYW1lID09PSBhcGkubW9kZWxOYW1lICYmIG1ldGhvZC5tZXRob2ROYW1lID09PSBhcGkubWV0aG9kTmFtZSxcbiAgICApO1xuICB9KTtcbiAgaWYgKGN1cnJlbnRNb2RlbEFwaXMubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gY29uc3QgcCA9IHBhdGguam9pbih0bXBkaXIoKSwgXCJzb25hbXUtc3luY2VyLWVycm9yLmpzb25cIik7XG4gICAgLy8gd3JpdGVGaWxlU3luYyhwLCBKU09OLnN0cmluZ2lmeShyZWdpc3RlcmVkQXBpcywgbnVsbCwgMikpO1xuICAgIC8vIGV4ZWNTeW5jKGBvcGVuICR7cH1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYO2YhOyerCDtjIzsnbzsl5Ag7IKs7KCEIOuTseuhneuQnCBBUEnqsIAg7JeG7Iq164uI64ukLiAke2ZpbGVQYXRofWApO1xuICB9XG5cbiAgLy8g65Ox66Gd65CcIEFQSeyXkCDtmITsnqwg66mU7IaM65OcIO2DgOyehSDsoJXrs7Qg7ZmV7J6lXG4gIGNvbnN0IGV4dGVuZGVkQXBpcyA9IGN1cnJlbnRNb2RlbEFwaXMubWFwKChhcGkpID0+IHtcbiAgICBjb25zdCBmb3VuZE1ldGhvZCA9IG1ldGhvZHMuZmluZChcbiAgICAgIChtZXRob2QpID0+IG1ldGhvZC5tb2RlbE5hbWUgPT09IGFwaS5tb2RlbE5hbWUgJiYgbWV0aG9kLm1ldGhvZE5hbWUgPT09IGFwaS5tZXRob2ROYW1lLFxuICAgICk7XG4gICAgaWYgKCFmb3VuZE1ldGhvZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBUEkgJHthcGkubW9kZWxOYW1lfS4ke2FwaS5tZXRob2ROYW1lfSBub3QgZm91bmQgaW4gJHtmaWxlUGF0aH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmFwaSxcbiAgICAgIHR5cGVQYXJhbWV0ZXJzOiBmb3VuZE1ldGhvZD8udHlwZVBhcmFtZXRlcnMsXG4gICAgICBwYXJhbWV0ZXJzOiBmb3VuZE1ldGhvZD8ucGFyYW1ldGVycyxcbiAgICAgIHJldHVyblR5cGU6IGZvdW5kTWV0aG9kPy5yZXR1cm5UeXBlLFxuICAgIH07XG4gIH0pO1xuICByZXR1cm4gZXh0ZW5kZWRBcGlzO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZU5vZGUodHlwZU5vZGU6IHRzLlR5cGVOb2RlKTogQXBpUGFyYW1UeXBlIHtcbiAgc3dpdGNoICh0eXBlTm9kZT8ua2luZCkge1xuICAgIGNhc2UgdHMuU3ludGF4S2luZC5BbnlLZXl3b3JkOlxuICAgICAgcmV0dXJuIFwiYW55XCI7XG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlVua25vd25LZXl3b3JkOlxuICAgICAgcmV0dXJuIFwidW5rbm93blwiO1xuICAgIGNhc2UgdHMuU3ludGF4S2luZC5TdHJpbmdLZXl3b3JkOlxuICAgICAgcmV0dXJuIFwic3RyaW5nXCI7XG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLk51bWJlcktleXdvcmQ6XG4gICAgICByZXR1cm4gXCJudW1iZXJcIjtcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuQm9vbGVhbktleXdvcmQ6XG4gICAgICByZXR1cm4gXCJib29sZWFuXCI7XG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlVuZGVmaW5lZEtleXdvcmQ6XG4gICAgICByZXR1cm4gXCJ1bmRlZmluZWRcIjtcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuTnVsbEtleXdvcmQ6XG4gICAgICByZXR1cm4gXCJudWxsXCI7XG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlZvaWRLZXl3b3JkOlxuICAgICAgcmV0dXJuIFwidm9pZFwiO1xuICAgIGNhc2UgdHMuU3ludGF4S2luZC5MaXRlcmFsVHlwZToge1xuICAgICAgY29uc3QgbGl0ZXJhbCA9ICh0eXBlTm9kZSBhcyB0cy5MaXRlcmFsVHlwZU5vZGUpLmxpdGVyYWw7XG4gICAgICBpZiAodHMuaXNTdHJpbmdMaXRlcmFsKGxpdGVyYWwpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdDogXCJzdHJpbmctbGl0ZXJhbFwiLFxuICAgICAgICAgIHZhbHVlOiBsaXRlcmFsLnRleHQsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHRzLmlzTnVtZXJpY0xpdGVyYWwobGl0ZXJhbCkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0OiBcIm51bWVyaWMtbGl0ZXJhbFwiLFxuICAgICAgICAgIHZhbHVlOiBOdW1iZXIobGl0ZXJhbC50ZXh0KSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsaXRlcmFsLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuTnVsbEtleXdvcmQpIHtcbiAgICAgICAgICByZXR1cm4gXCJudWxsXCI7XG4gICAgICAgIH0gZWxzZSBpZiAobGl0ZXJhbC5raW5kID09PSB0cy5TeW50YXhLaW5kLlVuZGVmaW5lZEtleXdvcmQpIHtcbiAgICAgICAgICByZXR1cm4gXCJ1bmRlZmluZWRcIjtcbiAgICAgICAgfSBlbHNlIGlmIChsaXRlcmFsLmtpbmQgPT09IHRzLlN5bnRheEtpbmQuVHJ1ZUtleXdvcmQpIHtcbiAgICAgICAgICByZXR1cm4gXCJ0cnVlXCI7XG4gICAgICAgIH0gZWxzZSBpZiAobGl0ZXJhbC5raW5kID09PSB0cy5TeW50YXhLaW5kLkZhbHNlS2V5d29yZCkge1xuICAgICAgICAgIHJldHVybiBcImZhbHNlXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwi7JWMIOyImCDsl4bripQg66as7YSw65+0XCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuQXJyYXlUeXBlOiB7XG4gICAgICBjb25zdCBhcnJOb2RlID0gdHlwZU5vZGUgYXMgdHMuQXJyYXlUeXBlTm9kZTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHQ6IFwiYXJyYXlcIixcbiAgICAgICAgZWxlbWVudHNUeXBlOiByZXNvbHZlVHlwZU5vZGUoYXJyTm9kZS5lbGVtZW50VHlwZSksXG4gICAgICB9O1xuICAgIH1cbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuVHlwZUxpdGVyYWw6IHtcbiAgICAgIGNvbnN0IGxpdGVyYWxOb2RlID0gdHlwZU5vZGUgYXMgdHMuVHlwZUxpdGVyYWxOb2RlO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdDogXCJvYmplY3RcIixcbiAgICAgICAgcHJvcHM6IGxpdGVyYWxOb2RlLm1lbWJlcnMubWFwKChtZW1iZXIpID0+IHtcbiAgICAgICAgICBpZiAodHMuaXNJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uKG1lbWJlcikpIHtcbiAgICAgICAgICAgIGFzc2VydChtZW1iZXIucGFyYW1ldGVyc1swXSk7XG4gICAgICAgICAgICBjb25zdCByZXMgPSByZXNvbHZlUGFyYW1EZWMoe1xuICAgICAgICAgICAgICBuYW1lOiBtZW1iZXIucGFyYW1ldGVyc1swXS5uYW1lIGFzIHRzLklkZW50aWZpZXIsXG4gICAgICAgICAgICAgIHR5cGU6IG1lbWJlci5wYXJhbWV0ZXJzWzBdLnR5cGUgYXMgdHMuVHlwZU5vZGUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmVQYXJhbURlYyh7XG4gICAgICAgICAgICAgIG5hbWU6IHtcbiAgICAgICAgICAgICAgICBlc2NhcGVkVGV4dDogYFske3Jlcy5uYW1lfSR7cmVzLm9wdGlvbmFsID8gXCI/XCIgOiBcIlwifTogJHtyZXMudHlwZX1dYCxcbiAgICAgICAgICAgICAgfSBhcyB0cy5JZGVudGlmaWVyLFxuICAgICAgICAgICAgICB0eXBlOiBtZW1iZXIudHlwZSBhcyB0cy5UeXBlTm9kZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZVBhcmFtRGVjKHtcbiAgICAgICAgICAgICAgbmFtZTogKG1lbWJlciBhcyB0cy5Qcm9wZXJ0eVNpZ25hdHVyZSkubmFtZSBhcyB0cy5JZGVudGlmaWVyLFxuICAgICAgICAgICAgICB0eXBlOiAobWVtYmVyIGFzIHRzLlByb3BlcnR5U2lnbmF0dXJlKS50eXBlIGFzIHRzLlR5cGVOb2RlLFxuICAgICAgICAgICAgICBvcHRpb25hbDogKG1lbWJlciBhcyB0cy5Qcm9wZXJ0eVNpZ25hdHVyZSkucXVlc3Rpb25Ub2tlbiAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfVxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5UeXBlUmVmZXJlbmNlOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdDogXCJyZWZcIixcbiAgICAgICAgaWQ6ICgodHlwZU5vZGUgYXMgdHMuVHlwZVJlZmVyZW5jZU5vZGUpLnR5cGVOYW1lIGFzIHRzLklkZW50aWZpZXIpLmVzY2FwZWRUZXh0LnRvU3RyaW5nKCksXG4gICAgICAgIGFyZ3M6ICh0eXBlTm9kZSBhcyB0cy5UeXBlUmVmZXJlbmNlTm9kZSkudHlwZUFyZ3VtZW50cz8ubWFwKCh0eXBlQXJnKSA9PlxuICAgICAgICAgIHJlc29sdmVUeXBlTm9kZSh0eXBlQXJnKSxcbiAgICAgICAgKSxcbiAgICAgIH07XG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlVuaW9uVHlwZTpcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHQ6IFwidW5pb25cIixcbiAgICAgICAgdHlwZXM6ICh0eXBlTm9kZSBhcyB0cy5VbmlvblR5cGVOb2RlKS50eXBlcy5tYXAoKHR5cGUpID0+IHJlc29sdmVUeXBlTm9kZSh0eXBlKSksXG4gICAgICB9O1xuICAgIGNhc2UgdHMuU3ludGF4S2luZC5JbnRlcnNlY3Rpb25UeXBlOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdDogXCJpbnRlcnNlY3Rpb25cIixcbiAgICAgICAgdHlwZXM6ICh0eXBlTm9kZSBhcyB0cy5JbnRlcnNlY3Rpb25UeXBlTm9kZSkudHlwZXMubWFwKCh0eXBlKSA9PiByZXNvbHZlVHlwZU5vZGUodHlwZSkpLFxuICAgICAgfTtcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuSW5kZXhlZEFjY2Vzc1R5cGU6XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0OiBcImluZGV4ZWQtYWNjZXNzXCIsXG4gICAgICAgIG9iamVjdDogcmVzb2x2ZVR5cGVOb2RlKCh0eXBlTm9kZSBhcyB0cy5JbmRleGVkQWNjZXNzVHlwZU5vZGUpLm9iamVjdFR5cGUpLFxuICAgICAgICBpbmRleDogcmVzb2x2ZVR5cGVOb2RlKCh0eXBlTm9kZSBhcyB0cy5JbmRleGVkQWNjZXNzVHlwZU5vZGUpLmluZGV4VHlwZSksXG4gICAgICB9O1xuICAgIGNhc2UgdHMuU3ludGF4S2luZC5UdXBsZVR5cGU6XG4gICAgICBpZiAodHMuaXNUdXBsZVR5cGVOb2RlKHR5cGVOb2RlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHQ6IFwidHVwbGUtdHlwZVwiLFxuICAgICAgICAgIGVsZW1lbnRzOiB0eXBlTm9kZS5lbGVtZW50cy5tYXAoKGVsZW0pID0+IHJlc29sdmVUeXBlTm9kZShlbGVtKSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdHlwZU5vZGUgdW5kZWZpbmVkYCk7XG4gIH1cblxuICBjb25zb2xlLmRlYnVnKHR5cGVOb2RlKTtcbiAgdGhyb3cgbmV3IEVycm9yKGDslYwg7IiYIOyXhuuKlCBTeW50YXhLaW5kICR7dHlwZU5vZGUua2luZH1gKTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVBhcmFtRGVjKFxuICBwYXJhbURlYzoge1xuICAgIG5hbWU6IHRzLkJpbmRpbmdOYW1lO1xuICAgIHR5cGU6IHRzLlR5cGVOb2RlO1xuICAgIG9wdGlvbmFsPzogYm9vbGVhbjtcbiAgICBkZWZhdWx0RGVmPzogc3RyaW5nO1xuICB9LFxuICBpbmRleDogbnVtYmVyID0gMCxcbik6IEFwaVBhcmFtIHtcbiAgY29uc3QgbmFtZSA9IHBhcmFtRGVjLm5hbWUgYXMgdHMuSWRlbnRpZmllcjtcbiAgY29uc3QgdHlwZSA9IHJlc29sdmVUeXBlTm9kZShwYXJhbURlYy50eXBlKTtcblxuICBpZiAobmFtZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc29sZS5kZWJ1Zyh7IG5hbWUsIHR5cGUsIHBhcmFtRGVjIH0pO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBBcGlQYXJhbSA9IHtcbiAgICBuYW1lOiBuYW1lLmVzY2FwZWRUZXh0ID8gbmFtZS5lc2NhcGVkVGV4dC50b1N0cmluZygpIDogYG5vbmFtZUF0JHtpbmRleH1gLFxuICAgIHR5cGUsXG4gICAgb3B0aW9uYWw6IHBhcmFtRGVjLm9wdGlvbmFsID09PSB0cnVlLFxuICAgIGRlZmF1bHREZWY6IHBhcmFtRGVjPy5kZWZhdWx0RGVmLFxuICB9O1xuXG4gIC8vIOq1rOyhsOu2hO2VtO2VoOuLueydmCDqsr3smrAg7YOA7J6F7J2066aEIOyCrOyaqVxuICBpZiAoXG4gICAgdHMuaXNPYmplY3RCaW5kaW5nUGF0dGVybihuYW1lKSAmJlxuICAgIHRzLmlzVHlwZVJlZmVyZW5jZU5vZGUocGFyYW1EZWMudHlwZSkgJiZcbiAgICB0cy5pc0lkZW50aWZpZXIocGFyYW1EZWMudHlwZS50eXBlTmFtZSlcbiAgKSB7XG4gICAgcmVzdWx0Lm5hbWUgPSBpbmZsZWN0aW9uLmNhbWVsaXplKHBhcmFtRGVjLnR5cGUudHlwZU5hbWUudGV4dCwgdHJ1ZSk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBwcmludE5vZGUobm9kZTogdHMuTm9kZSB8IHVuZGVmaW5lZCwgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChub2RlID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcHJpbnRlciA9IHRzLmNyZWF0ZVByaW50ZXIoeyBuZXdMaW5lOiB0cy5OZXdMaW5lS2luZC5MaW5lRmVlZCB9KTtcbiAgcmV0dXJuIHByaW50ZXIucHJpbnROb2RlKHRzLkVtaXRIaW50LlVuc3BlY2lmaWVkLCBub2RlLCBzb3VyY2VGaWxlKTtcbn1cbiJdLCJuYW1lcyI6WyJhc3NlcnQiLCJyZWFkRmlsZSIsImluZmxlY3Rpb24iLCJ0cyIsInJlZ2lzdGVyZWRBcGlzIiwidmFsaWRhdGVNZXRob2ROYW1lIiwicmVhZEFwaXNGcm9tRmlsZSIsImZpbGVQYXRoIiwiZW5kc1dpdGgiLCJFcnJvciIsInNvdXJjZUZpbGUiLCJjcmVhdGVTb3VyY2VGaWxlIiwidG9TdHJpbmciLCJTY3JpcHRUYXJnZXQiLCJMYXRlc3QiLCJtZXRob2RzIiwibW9kZWxOYW1lIiwibWV0aG9kTmFtZSIsInZpc2l0b3IiLCJub2RlIiwiaXNDbGFzc0RlY2xhcmF0aW9uIiwibmFtZSIsImlzSWRlbnRpZmllciIsImVzY2FwZWRUZXh0IiwicmVwbGFjZSIsImlzTWV0aG9kRGVjbGFyYXRpb24iLCJ0eXBlUGFyYW1ldGVycyIsIm1hcCIsInR5cGVQYXJhbSIsInRwIiwidCIsImlkIiwiY29uc3RyYWludCIsInJlc29sdmVUeXBlTm9kZSIsInVuZGVmaW5lZCIsInBhcmFtZXRlcnMiLCJwYXJhbURlYyIsImluZGV4IiwiZGVmYXVsdERlZiIsInByaW50Tm9kZSIsImluaXRpYWxpemVyIiwicmVzb2x2ZVBhcmFtRGVjIiwidHlwZSIsIm9wdGlvbmFsIiwicXVlc3Rpb25Ub2tlbiIsInJldHVyblR5cGUiLCJwdXNoIiwiZm9yRWFjaENoaWxkIiwibGVuZ3RoIiwiY3VycmVudE1vZGVsQXBpcyIsImZpbHRlciIsImFwaSIsImZpbmQiLCJtZXRob2QiLCJleHRlbmRlZEFwaXMiLCJmb3VuZE1ldGhvZCIsInR5cGVOb2RlIiwia2luZCIsIlN5bnRheEtpbmQiLCJBbnlLZXl3b3JkIiwiVW5rbm93bktleXdvcmQiLCJTdHJpbmdLZXl3b3JkIiwiTnVtYmVyS2V5d29yZCIsIkJvb2xlYW5LZXl3b3JkIiwiVW5kZWZpbmVkS2V5d29yZCIsIk51bGxLZXl3b3JkIiwiVm9pZEtleXdvcmQiLCJMaXRlcmFsVHlwZSIsImxpdGVyYWwiLCJpc1N0cmluZ0xpdGVyYWwiLCJ2YWx1ZSIsInRleHQiLCJpc051bWVyaWNMaXRlcmFsIiwiTnVtYmVyIiwiVHJ1ZUtleXdvcmQiLCJGYWxzZUtleXdvcmQiLCJBcnJheVR5cGUiLCJhcnJOb2RlIiwiZWxlbWVudHNUeXBlIiwiZWxlbWVudFR5cGUiLCJUeXBlTGl0ZXJhbCIsImxpdGVyYWxOb2RlIiwicHJvcHMiLCJtZW1iZXJzIiwibWVtYmVyIiwiaXNJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uIiwicmVzIiwiVHlwZVJlZmVyZW5jZSIsInR5cGVOYW1lIiwiYXJncyIsInR5cGVBcmd1bWVudHMiLCJ0eXBlQXJnIiwiVW5pb25UeXBlIiwidHlwZXMiLCJJbnRlcnNlY3Rpb25UeXBlIiwiSW5kZXhlZEFjY2Vzc1R5cGUiLCJvYmplY3QiLCJvYmplY3RUeXBlIiwiaW5kZXhUeXBlIiwiVHVwbGVUeXBlIiwiaXNUdXBsZVR5cGVOb2RlIiwiZWxlbWVudHMiLCJlbGVtIiwiY29uc29sZSIsImRlYnVnIiwicmVzdWx0IiwiaXNPYmplY3RCaW5kaW5nUGF0dGVybiIsImlzVHlwZVJlZmVyZW5jZU5vZGUiLCJjYW1lbGl6ZSIsInByaW50ZXIiLCJjcmVhdGVQcmludGVyIiwibmV3TGluZSIsIk5ld0xpbmVLaW5kIiwiTGluZUZlZWQiLCJFbWl0SGludCIsIlVuc3BlY2lmaWVkIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFDNUIsU0FBU0MsUUFBUSxRQUFRLG1CQUFjO0FBQ3ZDLE9BQU9DLGdCQUFnQixhQUFhO0FBQ3BDLE9BQU9DLFFBQVEsYUFBYTtBQUM1QixTQUEyQkMsY0FBYyxRQUFRLHVCQUFvQjtBQUNyRSxTQUFTQyxrQkFBa0IsUUFBUSxzQkFBbUI7QUFJdEQ7Ozs7O0NBS0MsR0FDRCxPQUFPLGVBQWVDLGlCQUFpQkMsUUFBc0I7SUFDM0QsSUFBSSxDQUFDQSxTQUFTQyxRQUFRLENBQUMsUUFBUTtRQUM3QixNQUFNLElBQUlDLE1BQ1IsR0FBR0YsU0FBUyw2R0FBNkcsQ0FBQztJQUU5SDtJQUVBLE1BQU1HLGFBQWFQLEdBQUdRLGdCQUFnQixDQUNwQ0osVUFDQSxBQUFDLENBQUEsTUFBTU4sU0FBU00sU0FBUSxFQUFHSyxRQUFRLElBQ25DVCxHQUFHVSxZQUFZLENBQUNDLE1BQU07SUFHeEIsTUFBTUMsVUFBbUQsRUFBRTtJQUMzRCxJQUFJQyxZQUFvQjtJQUN4QixJQUFJQyxhQUFxQjtJQUN6QixNQUFNQyxVQUFVLENBQUND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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PathLike } from "fs";
|
|
2
|
+
import type { AbsolutePath } from "../utils/path-utils";
|
|
3
|
+
/**
|
|
4
|
+
* 체크섬 파일에 저장된 내용과 현재 실제 파일의 체크섬을 비교하여 변경된 파일을 찾습니다.
|
|
5
|
+
* @returns 변경된 파일 경로 배열. 프로젝트 루트부터 슬래시로 시작합니다. 예시: "/src/application/user/user.model.ts"
|
|
6
|
+
*/
|
|
7
|
+
export declare function findChangedFilesUsingChecksums(): Promise<AbsolutePath[]>;
|
|
8
|
+
/**
|
|
9
|
+
* 체크섬을 갱신합니다.
|
|
10
|
+
* 현재 파일들의 체크섬을 계산해서 구한 다음, 체크섬 파일에 저장된 내용과 다르면 체크섬 파일을 갱신합니다.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renewChecksums(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* 두 파일의 내용이 같은지 체크섬으로 비교합니다.
|
|
15
|
+
* 만약 파일이 둘 중 하나라도 없다면 비교 불가로 false 반환합니다.
|
|
16
|
+
* @param one 파일 경로
|
|
17
|
+
* @param two 파일 경로
|
|
18
|
+
* @returns boolean
|
|
19
|
+
*/
|
|
20
|
+
export declare function areFilesSame(one: PathLike, two: PathLike): Promise<boolean>;
|
|
21
|
+
//# sourceMappingURL=checksum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../../src/syncer/checksum.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,IAAI,CAAC;AAOrD,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AASzE;;;GAGG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAU9E;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAUpD;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CASjF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import equal from "fast-deep-equal";
|
|
3
|
+
import { createReadStream } from "fs";
|
|
4
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { isEqual } from "radashi";
|
|
7
|
+
import { Sonamu } from "../api/sonamu.js";
|
|
8
|
+
import { globAsync } from "../utils/async-utils.js";
|
|
9
|
+
import { exists } from "../utils/fs-utils.js";
|
|
10
|
+
import { differenceWith } from "../utils/utils.js";
|
|
11
|
+
import { getChecksumPatternGroupInAbsolutePath } from "./file-patterns.js";
|
|
12
|
+
/**
|
|
13
|
+
* 체크섬 파일에 저장된 내용과 현재 실제 파일의 체크섬을 비교하여 변경된 파일을 찾습니다.
|
|
14
|
+
* @returns 변경된 파일 경로 배열. 프로젝트 루트부터 슬래시로 시작합니다. 예시: "/src/application/user/user.model.ts"
|
|
15
|
+
*/ export async function findChangedFilesUsingChecksums() {
|
|
16
|
+
const calculatedChecksums = await getCurrentChecksums();
|
|
17
|
+
const savedChecksums = await getPreviousChecksums();
|
|
18
|
+
const isSame = equal(calculatedChecksums, savedChecksums);
|
|
19
|
+
if (isSame) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
return differenceWith(calculatedChecksums, savedChecksums, isEqual).map((r)=>r.path);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 체크섬을 갱신합니다.
|
|
26
|
+
* 현재 파일들의 체크섬을 계산해서 구한 다음, 체크섬 파일에 저장된 내용과 다르면 체크섬 파일을 갱신합니다.
|
|
27
|
+
*/ export async function renewChecksums() {
|
|
28
|
+
const calculatedChecksums = await getCurrentChecksums();
|
|
29
|
+
const savedChecksums = await getPreviousChecksums();
|
|
30
|
+
const isSame = equal(calculatedChecksums, savedChecksums);
|
|
31
|
+
if (isSame) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
await saveChecksums(calculatedChecksums);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 두 파일의 내용이 같은지 체크섬으로 비교합니다.
|
|
38
|
+
* 만약 파일이 둘 중 하나라도 없다면 비교 불가로 false 반환합니다.
|
|
39
|
+
* @param one 파일 경로
|
|
40
|
+
* @param two 파일 경로
|
|
41
|
+
* @returns boolean
|
|
42
|
+
*/ export async function areFilesSame(one, two) {
|
|
43
|
+
if (!await exists(one) || !await exists(two)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const oneChecksum = await getChecksumOfFile(one);
|
|
47
|
+
const twoChecksum = await getChecksumOfFile(two);
|
|
48
|
+
return oneChecksum === twoChecksum;
|
|
49
|
+
}
|
|
50
|
+
async function getCurrentChecksums() {
|
|
51
|
+
const filePaths = (await Promise.all(Object.entries(getChecksumPatternGroupInAbsolutePath()).map(async ([_fileType, pattern])=>{
|
|
52
|
+
return globAsync(pattern);
|
|
53
|
+
}))).flat().sort();
|
|
54
|
+
const fileChecksums = await Promise.all(filePaths.map(async (filePath)=>{
|
|
55
|
+
return {
|
|
56
|
+
path: filePath,
|
|
57
|
+
checksum: await getChecksumOfFile(filePath)
|
|
58
|
+
};
|
|
59
|
+
}));
|
|
60
|
+
return fileChecksums;
|
|
61
|
+
}
|
|
62
|
+
async function getPreviousChecksums() {
|
|
63
|
+
const checksumFilePath = getChecksumFilePath();
|
|
64
|
+
if (!await exists(checksumFilePath)) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const previousChecksums = JSON.parse(await readFile(checksumFilePath, "utf-8")).map((r)=>({
|
|
68
|
+
path: path.join(Sonamu.apiRootPath, r.path),
|
|
69
|
+
checksum: r.checksum
|
|
70
|
+
}));
|
|
71
|
+
return previousChecksums;
|
|
72
|
+
}
|
|
73
|
+
function getChecksumFilePath() {
|
|
74
|
+
return path.join(Sonamu.apiRootPath, "sonamu.lock");
|
|
75
|
+
}
|
|
76
|
+
async function saveChecksums(checksums) {
|
|
77
|
+
const checksumFilePath = getChecksumFilePath();
|
|
78
|
+
await writeFile(checksumFilePath, JSON.stringify(checksums.map((r)=>({
|
|
79
|
+
path: path.relative(Sonamu.apiRootPath, r.path),
|
|
80
|
+
checksum: r.checksum
|
|
81
|
+
})), null, 2), "utf-8");
|
|
82
|
+
console.log("checksum saved", checksumFilePath);
|
|
83
|
+
}
|
|
84
|
+
async function getChecksumOfFile(filePath) {
|
|
85
|
+
return new Promise((resolve, reject)=>{
|
|
86
|
+
const hash = crypto.createHash("sha1");
|
|
87
|
+
const input = createReadStream(filePath);
|
|
88
|
+
input.on("error", reject);
|
|
89
|
+
input.on("data", (chunk)=>{
|
|
90
|
+
hash.update(chunk);
|
|
91
|
+
});
|
|
92
|
+
input.on("close", ()=>{
|
|
93
|
+
resolve(hash.digest("hex"));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zeW5jZXIvY2hlY2tzdW0udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyeXB0bywgeyB0eXBlIEJpbmFyeUxpa2UgfSBmcm9tIFwiY3J5cHRvXCI7XG5pbXBvcnQgZXF1YWwgZnJvbSBcImZhc3QtZGVlcC1lcXVhbFwiO1xuaW1wb3J0IHsgY3JlYXRlUmVhZFN0cmVhbSwgdHlwZSBQYXRoTGlrZSB9IGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgcmVhZEZpbGUsIHdyaXRlRmlsZSB9IGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGlzRXF1YWwgfSBmcm9tIFwicmFkYXNoaVwiO1xuaW1wb3J0IHsgU29uYW11IH0gZnJvbSBcIi4uL2FwaS9zb25hbXVcIjtcbmltcG9ydCB7IGdsb2JBc3luYyB9IGZyb20gXCIuLi91dGlscy9hc3luYy11dGlsc1wiO1xuaW1wb3J0IHsgZXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgdHlwZSB7IEFic29sdXRlUGF0aCwgQXBpUmVsYXRpdmVQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3BhdGgtdXRpbHNcIjtcbmltcG9ydCB7IGRpZmZlcmVuY2VXaXRoIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBnZXRDaGVja3N1bVBhdHRlcm5Hcm91cEluQWJzb2x1dGVQYXRoIH0gZnJvbSBcIi4vZmlsZS1wYXR0ZXJuc1wiO1xuXG50eXBlIFBhdGhBbmRDaGVja3N1bSA9IHtcbiAgcGF0aDogQWJzb2x1dGVQYXRoO1xuICBjaGVja3N1bTogc3RyaW5nO1xufTtcblxuLyoqXG4gKiDssrTtgazshKwg7YyM7J287JeQIOyggOyepeuQnCDrgrTsmqnqs7wg7ZiE7J6sIOyLpOygnCDtjIzsnbzsnZgg7LK07YGs7ISs7J2EIOu5hOq1kO2VmOyXrCDrs4Dqsr3rkJwg7YyM7J287J2EIOywvuyKteuLiOuLpC5cbiAqIEByZXR1cm5zIOuzgOqyveuQnCDtjIzsnbwg6rK966GcIOuwsOyXtC4g7ZSE66Gc7KCd7Yq4IOujqO2KuOu2gO2EsCDsiqzrnpjsi5zroZwg7Iuc7J6R7ZWp64uI64ukLiDsmIjsi5w6IFwiL3NyYy9hcHBsaWNhdGlvbi91c2VyL3VzZXIubW9kZWwudHNcIlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZENoYW5nZWRGaWxlc1VzaW5nQ2hlY2tzdW1zKCk6IFByb21pc2U8QWJzb2x1dGVQYXRoW10+IHtcbiAgY29uc3QgY2FsY3VsYXRlZENoZWNrc3VtcyA9IGF3YWl0IGdldEN1cnJlbnRDaGVja3N1bXMoKTtcbiAgY29uc3Qgc2F2ZWRDaGVja3N1bXMgPSBhd2FpdCBnZXRQcmV2aW91c0NoZWNrc3VtcygpO1xuXG4gIGNvbnN0IGlzU2FtZSA9IGVxdWFsKGNhbGN1bGF0ZWRDaGVja3N1bXMsIHNhdmVkQ2hlY2tzdW1zKTtcbiAgaWYgKGlzU2FtZSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBkaWZmZXJlbmNlV2l0aChjYWxjdWxhdGVkQ2hlY2tzdW1zLCBzYXZlZENoZWNrc3VtcywgaXNFcXVhbCkubWFwKChyKSA9PiByLnBhdGgpO1xufVxuXG4vKipcbiAqIOyytO2BrOyErOydhCDqsLHsi6Dtlanri4jri6QuXG4gKiDtmITsnqwg7YyM7J2865Ok7J2YIOyytO2BrOyErOydhCDqs4TsgrDtlbTshJwg6rWs7ZWcIOuLpOydjCwg7LK07YGs7ISsIO2MjOydvOyXkCDsoIDsnqXrkJwg64K07Jqp6rO8IOuLpOultOuptCDssrTtgazshKwg7YyM7J287J2EIOqwseyLoO2VqeuLiOuLpC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbmV3Q2hlY2tzdW1zKCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWxjdWxhdGVkQ2hlY2tzdW1zID0gYXdhaXQgZ2V0Q3VycmVudENoZWNrc3VtcygpO1xuICBjb25zdCBzYXZlZENoZWNrc3VtcyA9IGF3YWl0IGdldFByZXZpb3VzQ2hlY2tzdW1zKCk7XG5cbiAgY29uc3QgaXNTYW1lID0gZXF1YWwoY2FsY3VsYXRlZENoZWNrc3Vtcywgc2F2ZWRDaGVja3N1bXMpO1xuICBpZiAoaXNTYW1lKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgYXdhaXQgc2F2ZUNoZWNrc3VtcyhjYWxjdWxhdGVkQ2hlY2tzdW1zKTtcbn1cblxuLyoqXG4gKiDrkZAg7YyM7J287J2YIOuCtOyaqeydtCDqsJnsnYDsp4Ag7LK07YGs7ISs7Jy866GcIOu5hOq1kO2VqeuLiOuLpC5cbiAqIOunjOyVvSDtjIzsnbzsnbQg65GYIOykkSDtlZjrgpjrnbzrj4Qg7JeG64uk66m0IOu5hOq1kCDrtojqsIDroZwgZmFsc2Ug67CY7ZmY7ZWp64uI64ukLlxuICogQHBhcmFtIG9uZSDtjIzsnbwg6rK966GcXG4gKiBAcGFyYW0gdHdvIO2MjOydvCDqsr3roZxcbiAqIEByZXR1cm5zIGJvb2xlYW5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFyZUZpbGVzU2FtZShvbmU6IFBhdGhMaWtlLCB0d286IFBhdGhMaWtlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGlmICghKGF3YWl0IGV4aXN0cyhvbmUpKSB8fCAhKGF3YWl0IGV4aXN0cyh0d28pKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG9uZUNoZWNrc3VtID0gYXdhaXQgZ2V0Q2hlY2tzdW1PZkZpbGUob25lKTtcbiAgY29uc3QgdHdvQ2hlY2tzdW0gPSBhd2FpdCBnZXRDaGVja3N1bU9mRmlsZSh0d28pO1xuXG4gIHJldHVybiBvbmVDaGVja3N1bSA9PT0gdHdvQ2hlY2tzdW07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEN1cnJlbnRDaGVja3N1bXMoKTogUHJvbWlzZTxQYXRoQW5kQ2hlY2tzdW1bXT4ge1xuICBjb25zdCBmaWxlUGF0aHMgPSAoXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBPYmplY3QuZW50cmllcyhnZXRDaGVja3N1bVBhdHRlcm5Hcm91cEluQWJzb2x1dGVQYXRoKCkpLm1hcChhc3luYyAoW19maWxlVHlwZSwgcGF0dGVybl0pID0+IHtcbiAgICAgICAgcmV0dXJuIGdsb2JBc3luYyhwYXR0ZXJuKSBhcyBQcm9taXNlPEFic29sdXRlUGF0aFtdPjtcbiAgICAgIH0pLFxuICAgIClcbiAgKVxuICAgIC5mbGF0KClcbiAgICAuc29ydCgpO1xuXG4gIGNvbnN0IGZpbGVDaGVja3N1bXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBmaWxlUGF0aHMubWFwKGFzeW5jIChmaWxlUGF0aCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICAgIGNoZWNrc3VtOiBhd2FpdCBnZXRDaGVja3N1bU9mRmlsZShmaWxlUGF0aCksXG4gICAgICB9O1xuICAgIH0pLFxuICApO1xuXG4gIHJldHVybiBmaWxlQ2hlY2tzdW1zO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRQcmV2aW91c0NoZWNrc3VtcygpOiBQcm9taXNlPFBhdGhBbmRDaGVja3N1bVtdPiB7XG4gIGNvbnN0IGNoZWNrc3VtRmlsZVBhdGggPSBnZXRDaGVja3N1bUZpbGVQYXRoKCk7XG4gIGlmICghKGF3YWl0IGV4aXN0cyhjaGVja3N1bUZpbGVQYXRoKSkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwcmV2aW91c0NoZWNrc3VtcyA9IEpTT04ucGFyc2UoYXdhaXQgcmVhZEZpbGUoY2hlY2tzdW1GaWxlUGF0aCwgXCJ1dGYtOFwiKSkubWFwKFxuICAgIChyOiB7IHBhdGg6IEFwaVJlbGF0aXZlUGF0aDsgY2hlY2tzdW06IHN0cmluZyB9KSA9PiAoe1xuICAgICAgcGF0aDogcGF0aC5qb2luKFNvbmFtdS5hcGlSb290UGF0aCwgci5wYXRoKSwgLy8g7LK07YGs7ISsIO2MjOydvOyXkOyEnCDsnb3snYQg65WMOiBBUEkg7IOB64yAIOqyveuhnCDihpIg7KCI64yAIOqyveuhnFxuICAgICAgY2hlY2tzdW06IHIuY2hlY2tzdW0sXG4gICAgfSksXG4gICkgYXMgUGF0aEFuZENoZWNrc3VtW107XG4gIHJldHVybiBwcmV2aW91c0NoZWNrc3Vtcztcbn1cblxuZnVuY3Rpb24gZ2V0Q2hlY2tzdW1GaWxlUGF0aCgpOiBBYnNvbHV0ZVBhdGgge1xuICByZXR1cm4gcGF0aC5qb2luKFNvbmFtdS5hcGlSb290UGF0aCwgXCJzb25hbXUubG9ja1wiKSBhcyBBYnNvbHV0ZVBhdGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNhdmVDaGVja3N1bXMoY2hlY2tzdW1zOiBQYXRoQW5kQ2hlY2tzdW1bXSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjaGVja3N1bUZpbGVQYXRoID0gZ2V0Q2hlY2tzdW1GaWxlUGF0aCgpO1xuICBhd2FpdCB3cml0ZUZpbGUoXG4gICAgY2hlY2tzdW1GaWxlUGF0aCxcbiAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgIGNoZWNrc3Vtcy5tYXAoKHIpID0+ICh7XG4gICAgICAgIHBhdGg6IHBhdGgucmVsYXRpdmUoU29uYW11LmFwaVJvb3RQYXRoLCByLnBhdGgpLCAvLyDssrTtgazshKwg7YyM7J287JeQIOyggOyepe2VoCDrlYw6IOygiOuMgCDqsr3roZwg4oaSIEFQSSDsg4HrjIAg6rK966GcXG4gICAgICAgIGNoZWNrc3VtOiByLmNoZWNrc3VtLFxuICAgICAgfSkpLFxuICAgICAgbnVsbCxcbiAgICAgIDIsXG4gICAgKSxcbiAgICBcInV0Zi04XCIsXG4gICk7XG4gIGNvbnNvbGUubG9nKFwiY2hlY2tzdW0gc2F2ZWRcIiwgY2hlY2tzdW1GaWxlUGF0aCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENoZWNrc3VtT2ZGaWxlKGZpbGVQYXRoOiBQYXRoTGlrZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBoYXNoID0gY3J5cHRvLmNyZWF0ZUhhc2goXCJzaGExXCIpO1xuICAgIGNvbnN0IGlucHV0ID0gY3JlYXRlUmVhZFN0cmVhbShmaWxlUGF0aCk7XG4gICAgaW5wdXQub24oXCJlcnJvclwiLCByZWplY3QpO1xuICAgIGlucHV0Lm9uKFwiZGF0YVwiLCAoY2h1bms6IEJpbmFyeUxpa2UpID0+IHtcbiAgICAgIGhhc2gudXBkYXRlKGNodW5rKTtcbiAgICB9KTtcbiAgICBpbnB1dC5vbihcImNsb3NlXCIsICgpID0+IHtcbiAgICAgIHJlc29sdmUoaGFzaC5kaWdlc3QoXCJoZXhcIikpO1xuICAgIH0pO1xuICB9KTtcbn1cbiJdLCJuYW1lcyI6WyJjcnlwdG8iLCJlcXVhbCIsImNyZWF0ZVJlYWRTdHJlYW0iLCJyZWFkRmlsZSIsIndyaXRlRmlsZSIsInBhdGgiLCJpc0VxdWFsIiwiU29uYW11IiwiZ2xvYkFzeW5jIiwiZXhpc3RzIiwiZGlmZmVyZW5jZVdpdGgiLCJnZXRDaGVja3N1bVBhdHRlcm5Hcm91cEluQWJzb2x1dGVQYXRoIiwiZmluZENoYW5nZWRGaWxlc1VzaW5nQ2hlY2tzdW1zIiwiY2FsY3VsYXRlZENoZWNrc3VtcyIsImdldEN1cnJlbnRDaGVja3N1bXMiLCJzYXZlZENoZWNrc3VtcyIsImdldFByZXZpb3VzQ2hlY2tzdW1zIiwiaXNTYW1lIiwibWFwIiwiciIsInJlbmV3Q2hlY2tzdW1zIiwic2F2ZUNoZWNrc3VtcyIsImFyZUZpbGVzU2FtZSIsIm9uZSIsInR3byIsIm9uZUNoZWNrc3VtIiwiZ2V0Q2hlY2tzdW1PZkZpbGUiLCJ0d29DaGVja3N1bSIsImZpbGVQYXRocyIsIlByb21pc2UiLCJhbGwiLCJPYmplY3QiLCJlbnRyaWVzIiwiX2ZpbGVUeXBlIiwicGF0dGVybiIsImZsYXQiLCJzb3J0IiwiZmlsZUNoZWNrc3VtcyIsImZpbGVQYXRoIiwiY2hlY2tzdW0iLCJjaGVja3N1bUZpbGVQYXRoIiwiZ2V0Q2hlY2tzdW1GaWxlUGF0aCIsInByZXZpb3VzQ2hlY2tzdW1zIiwiSlNPTiIsInBhcnNlIiwiam9pbiIsImFwaVJvb3RQYXRoIiwiY2hlY2tzdW1zIiwic3RyaW5naWZ5IiwicmVsYXRpdmUiLCJjb25zb2xlIiwibG9nIiwicmVzb2x2ZSIsInJlamVjdCIsImhhc2giLCJjcmVhdGVIYXNoIiwiaW5wdXQiLCJvbiIsImNodW5rIiwidXBkYXRlIiwiZGlnZXN0Il0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFpQyxTQUFTO0FBQ2pELE9BQU9DLFdBQVcsa0JBQWtCO0FBQ3BDLFNBQVNDLGdCQUFnQixRQUF1QixLQUFLO0FBQ3JELFNBQVNDLFFBQVEsRUFBRUMsU0FBUyxRQUFRLG1CQUFjO0FBQ2xELE9BQU9DLFVBQVUsT0FBTztBQUN4QixTQUFTQyxPQUFPLFFBQVEsVUFBVTtBQUNsQyxTQUFTQyxNQUFNLFFBQVEsbUJBQWdCO0FBQ3ZDLFNBQVNDLFNBQVMsUUFBUSwwQkFBdUI7QUFDakQsU0FBU0MsTUFBTSxRQUFRLHVCQUFvQjtBQUUzQyxTQUFTQyxjQUFjLFFBQVEsb0JBQWlCO0FBQ2hELFNBQVNDLHFDQUFxQyxRQUFRLHFCQUFrQjtBQU94RTs7O0NBR0MsR0FDRCxPQUFPLGVBQWVDO0lBQ3BCLE1BQU1DLHNCQUFzQixNQUFNQztJQUNsQyxNQUFNQyxpQkFBaUIsTUFBTUM7SUFFN0IsTUFBTUMsU0FBU2hCLE1BQU1ZLHFCQUFxQkU7SUFDMUMsSUFBSUUsUUFBUTtRQUNWLE9BQU8sRUFBRTtJQUNYO0lBRUEsT0FBT1AsZUFBZUcscUJBQXFCRSxnQkFBZ0JULFNBQVNZLEdBQUcsQ0FBQyxDQUFDQyxJQUFNQSxFQUFFZCxJQUFJO0FBQ3ZGO0FBRUE7OztDQUdDLEdBQ0QsT0FBTyxlQUFlZTtJQUNwQixNQUFNUCxzQkFBc0IsTUFBTUM7SUFDbEMsTUFBTUMsaUJBQWlCLE1BQU1DO0lBRTdCLE1BQU1DLFNBQVNoQixNQUFNWSxxQkFBcUJFO0lBQzFDLElBQUlFLFFBQVE7UUFDVjtJQUNGO0lBRUEsTUFBTUksY0FBY1I7QUFDdEI7QUFFQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLGVBQWVTLGFBQWFDLEdBQWEsRUFBRUMsR0FBYTtJQUM3RCxJQUFJLENBQUUsTUFBTWYsT0FBT2MsUUFBUyxDQUFFLE1BQU1kLE9BQU9lLE1BQU87UUFDaEQsT0FBTztJQUNUO0lBRUEsTUFBTUMsY0FBYyxNQUFNQyxrQkFBa0JIO0lBQzVDLE1BQU1JLGNBQWMsTUFBTUQsa0JBQWtCRjtJQUU1QyxPQUFPQyxnQkFBZ0JFO0FBQ3pCO0FBRUEsZUFBZWI7SUFDYixNQUFNYyxZQUFZLEFBQ2hCLENBQUEsTUFBTUMsUUFBUUMsR0FBRyxDQUNmQyxPQUFPQyxPQUFPLENBQUNyQix5Q0FBeUNPLEdBQUcsQ0FBQyxPQUFPLENBQUNlLFdBQVdDLFFBQVE7UUFDckYsT0FBTzFCLFVBQVUwQjtJQUNuQixHQUNGLEVBRUNDLElBQUksR0FDSkMsSUFBSTtJQUVQLE1BQU1DLGdCQUFnQixNQUFNUixRQUFRQyxHQUFHLENBQ3JDRixVQUFVVixHQUFHLENBQUMsT0FBT29CO1FBQ25CLE9BQU87WUFDTGpDLE1BQU1pQztZQUNOQyxVQUFVLE1BQU1iLGtCQUFrQlk7UUFDcEM7SUFDRjtJQUdGLE9BQU9EO0FBQ1Q7QUFFQSxlQUFlckI7SUFDYixNQUFNd0IsbUJBQW1CQztJQUN6QixJQUFJLENBQUUsTUFBTWhDLE9BQU8rQixtQkFBb0I7UUFDckMsT0FBTyxFQUFFO0lBQ1g7SUFFQSxNQUFNRSxvQkFBb0JDLEtBQUtDLEtBQUssQ0FBQyxNQUFNekMsU0FBU3FDLGtCQUFrQixVQUFVdEIsR0FBRyxDQUNqRixDQUFDQyxJQUFvRCxDQUFBO1lBQ25EZCxNQUFNQSxLQUFLd0MsSUFBSSxDQUFDdEMsT0FBT3VDLFdBQVcsRUFBRTNCLEVBQUVkLElBQUk7WUFDMUNrQyxVQUFVcEIsRUFBRW9CLFFBQVE7UUFDdEIsQ0FBQTtJQUVGLE9BQU9HO0FBQ1Q7QUFFQSxTQUFTRDtJQUNQLE9BQU9wQyxLQUFLd0MsSUFBSSxDQUFDdEMsT0FBT3VDLFdBQVcsRUFBRTtBQUN2QztBQUVBLGVBQWV6QixjQUFjMEIsU0FBNEI7SUFDdkQsTUFBTVAsbUJBQW1CQztJQUN6QixNQUFNckMsVUFDSm9DLGtCQUNBRyxLQUFLSyxTQUFTLENBQ1pELFVBQVU3QixHQUFHLENBQUMsQ0FBQ0MsSUFBTyxDQUFBO1lBQ3BCZCxNQUFNQSxLQUFLNEMsUUFBUSxDQUFDMUMsT0FBT3VDLFdBQVcsRUFBRTNCLEVBQUVkLElBQUk7WUFDOUNrQyxVQUFVcEIsRUFBRW9CLFFBQVE7UUFDdEIsQ0FBQSxJQUNBLE1BQ0EsSUFFRjtJQUVGVyxRQUFRQyxHQUFHLENBQUMsa0JBQWtCWDtBQUNoQztBQUVBLGVBQWVkLGtCQUFrQlksUUFBa0I7SUFDakQsT0FBTyxJQUFJVCxRQUFnQixDQUFDdUIsU0FBU0M7UUFDbkMsTUFBTUMsT0FBT3RELE9BQU91RCxVQUFVLENBQUM7UUFDL0IsTUFBTUMsUUFBUXRELGlCQUFpQm9DO1FBQy9Ca0IsTUFBTUMsRUFBRSxDQUFDLFNBQVNKO1FBQ2xCRyxNQUFNQyxFQUFFLENBQUMsUUFBUSxDQUFDQztZQUNoQkosS0FBS0ssTUFBTSxDQUFDRDtRQUNkO1FBQ0FGLE1BQU1DLEVBQUUsQ0FBQyxTQUFTO1lBQ2hCTCxRQUFRRSxLQUFLTSxNQUFNLENBQUM7UUFDdEI7SUFDRjtBQUNGIn0=
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { GenerateOptions, PathAndCode, TemplateKey, TemplateOptions } from "../types/types";
|
|
2
|
+
import type { AbsolutePath } from "../utils/path-utils";
|
|
3
|
+
/**
|
|
4
|
+
* 템플릿을 렌더링하고 파일로 생성합니다.
|
|
5
|
+
* overwrite 옵션이 false인 경우, 이미 존재하는 파일은 건너뜁니다.
|
|
6
|
+
* @param key - 템플릿 키 (예: "entity", "model", "service" 등)
|
|
7
|
+
* @param templateOptions - 템플릿 렌더링에 필요한 옵션
|
|
8
|
+
* @param _generateOptions - 생성 옵션 (overwrite 여부)
|
|
9
|
+
* @returns 생성된 파일 경로 배열
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateTemplate<T extends TemplateKey>(key: T, templateOptions: TemplateOptions[T], _generateOptions?: GenerateOptions): Promise<AbsolutePath[]>;
|
|
12
|
+
/**
|
|
13
|
+
* 템플릿을 렌더링하여 PathAndCode 객체를 반환합니다.
|
|
14
|
+
* 파일로 쓰지 않고 메모리상에서만 렌더링합니다.
|
|
15
|
+
* @param key - 템플릿 키
|
|
16
|
+
* @param options - 템플릿 렌더링 옵션
|
|
17
|
+
* @returns 경로와 코드 쌍의 배열
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderTemplate<T extends keyof TemplateOptions>(key: T, options: TemplateOptions[T]): Promise<PathAndCode[]>;
|
|
20
|
+
//# sourceMappingURL=code-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-generator.d.ts","sourceRoot":"","sources":["../../src/syncer/code-generator.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,WAAW,EAC1D,GAAG,EAAE,CAAC,EACN,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC,EACnC,gBAAgB,CAAC,EAAE,eAAe,GACjC,OAAO,CAAC,YAAY,EAAE,CAAC,CAyCzB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,MAAM,eAAe,EAClE,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBxB"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { unique } from "radashi";
|
|
5
|
+
import { Sonamu } from "../api/sonamu.js";
|
|
6
|
+
import { EntityManager } from "../entity/entity-manager.js";
|
|
7
|
+
import { AlreadyProcessedException } from "../exceptions/so-exceptions.js";
|
|
8
|
+
import { Naite } from "../naite/naite.js";
|
|
9
|
+
import { TemplateManager } from "../template/template-manager.js";
|
|
10
|
+
import { everyAsync, filterAsync } from "../utils/async-utils.js";
|
|
11
|
+
import { isTest } from "../utils/controller.js";
|
|
12
|
+
import { formatCode } from "../utils/formatter.js";
|
|
13
|
+
import { exists } from "../utils/fs-utils.js";
|
|
14
|
+
import { wrapIf } from "../utils/lodash-able.js";
|
|
15
|
+
/**
|
|
16
|
+
* 템플릿을 렌더링하고 파일로 생성합니다.
|
|
17
|
+
* overwrite 옵션이 false인 경우, 이미 존재하는 파일은 건너뜁니다.
|
|
18
|
+
* @param key - 템플릿 키 (예: "entity", "model", "service" 등)
|
|
19
|
+
* @param templateOptions - 템플릿 렌더링에 필요한 옵션
|
|
20
|
+
* @param _generateOptions - 생성 옵션 (overwrite 여부)
|
|
21
|
+
* @returns 생성된 파일 경로 배열
|
|
22
|
+
*/ export async function generateTemplate(key, templateOptions, _generateOptions) {
|
|
23
|
+
const generateOptions = {
|
|
24
|
+
overwrite: false,
|
|
25
|
+
..._generateOptions
|
|
26
|
+
};
|
|
27
|
+
Naite.t("generateTemplate", {
|
|
28
|
+
key,
|
|
29
|
+
templateOptions,
|
|
30
|
+
generateOptions
|
|
31
|
+
});
|
|
32
|
+
// 키 children
|
|
33
|
+
const keys = [
|
|
34
|
+
key
|
|
35
|
+
];
|
|
36
|
+
// 템플릿 렌더
|
|
37
|
+
const pathAndCodes = (await Promise.all(keys.map(async (key)=>{
|
|
38
|
+
return await renderTemplate(key, templateOptions);
|
|
39
|
+
}))).flat();
|
|
40
|
+
const filteredPathAndCodes = await (async ()=>{
|
|
41
|
+
if (generateOptions.overwrite === true) {
|
|
42
|
+
return pathAndCodes;
|
|
43
|
+
} else {
|
|
44
|
+
return await filterAsync(pathAndCodes, async (pathAndCode)=>{
|
|
45
|
+
const { targets } = Sonamu.config.sync;
|
|
46
|
+
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
47
|
+
const dstFilePaths = targets.map((target)=>filePath.replace("/:target/", `/${target}/`));
|
|
48
|
+
return await everyAsync(dstFilePaths, async (dstPath)=>!await exists(dstPath));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
52
|
+
if (filteredPathAndCodes.length === 0) {
|
|
53
|
+
throw new AlreadyProcessedException("이미 경로에 모든 파일이 존재합니다.");
|
|
54
|
+
}
|
|
55
|
+
return (await Promise.all(filteredPathAndCodes.map((pathAndCode)=>writeCodeToPathEachTarget(pathAndCode)))).flat();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 템플릿을 렌더링하여 PathAndCode 객체를 반환합니다.
|
|
59
|
+
* 파일로 쓰지 않고 메모리상에서만 렌더링합니다.
|
|
60
|
+
* @param key - 템플릿 키
|
|
61
|
+
* @param options - 템플릿 렌더링 옵션
|
|
62
|
+
* @returns 경로와 코드 쌍의 배열
|
|
63
|
+
*/ export async function renderTemplate(key, options) {
|
|
64
|
+
Naite.t("renderTemplate", {
|
|
65
|
+
key,
|
|
66
|
+
options
|
|
67
|
+
});
|
|
68
|
+
const template = TemplateManager.get(key);
|
|
69
|
+
const rendered = await template.render(options);
|
|
70
|
+
const resolved = await resolveRenderedTemplate(key, rendered);
|
|
71
|
+
let preTemplateResolved = [];
|
|
72
|
+
if (rendered.preTemplates) {
|
|
73
|
+
preTemplateResolved = (await Promise.all(rendered.preTemplates.map(({ key, options })=>{
|
|
74
|
+
return renderTemplate(key, options);
|
|
75
|
+
}))).flat();
|
|
76
|
+
}
|
|
77
|
+
return [
|
|
78
|
+
resolved,
|
|
79
|
+
...preTemplateResolved
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
async function resolveRenderedTemplate(key, result) {
|
|
83
|
+
Naite.t(`resolveRenderedTemplate${key}`, {
|
|
84
|
+
key,
|
|
85
|
+
result
|
|
86
|
+
});
|
|
87
|
+
const { target, path: filePath, body, importKeys, customHeaders } = result;
|
|
88
|
+
// import 할 대상의 대상 path 추출
|
|
89
|
+
const importDefs = importKeys.reduce((r, importKey)=>{
|
|
90
|
+
const modulePath = EntityManager.getModulePath(importKey);
|
|
91
|
+
let importPath = modulePath;
|
|
92
|
+
if (modulePath.includes("/") || modulePath.includes(".")) {
|
|
93
|
+
importPath = wrapIf(path.relative(path.dirname(filePath), modulePath), (p)=>[
|
|
94
|
+
p.startsWith(".") === false,
|
|
95
|
+
`./${p}`
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
// 같은 파일에서 import 하는 경우 keys 로 나열 처리
|
|
99
|
+
const existsOne = r.find((importDef)=>importDef.from === importPath);
|
|
100
|
+
if (existsOne) {
|
|
101
|
+
existsOne.keys = unique(existsOne.keys.concat(importKey));
|
|
102
|
+
} else {
|
|
103
|
+
r.push({
|
|
104
|
+
keys: [
|
|
105
|
+
importKey
|
|
106
|
+
],
|
|
107
|
+
from: importPath
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return r;
|
|
111
|
+
}, [])// 셀프 참조 방지
|
|
112
|
+
.filter((importDef)=>filePath.endsWith(`${importDef.from.replace("./", "")}.ts`) === false);
|
|
113
|
+
// 커스텀 헤더 포함하여 헤더 생성
|
|
114
|
+
const header = [
|
|
115
|
+
...customHeaders ?? [],
|
|
116
|
+
...importDefs.map((importDef)=>`import { ${importDef.keys.join(", ")} } from '${importDef.from}'`)
|
|
117
|
+
].join("\n");
|
|
118
|
+
const formatted = await (async ()=>{
|
|
119
|
+
if (key === "generated_http") {
|
|
120
|
+
return [
|
|
121
|
+
header,
|
|
122
|
+
body
|
|
123
|
+
].join("\n\n");
|
|
124
|
+
} else {
|
|
125
|
+
Naite.t("resolveRenderedTemplate:beforeFormat", {
|
|
126
|
+
key,
|
|
127
|
+
header,
|
|
128
|
+
body
|
|
129
|
+
});
|
|
130
|
+
const formatted = formatCode([
|
|
131
|
+
header,
|
|
132
|
+
body
|
|
133
|
+
].join("\n\n"), key === "entity" ? "json" : "typescript", `${Sonamu.appRootPath}/${filePath}`);
|
|
134
|
+
Naite.t(`resolveRenderedTemplate:formatted:${key}`, formatted);
|
|
135
|
+
return formatted;
|
|
136
|
+
}
|
|
137
|
+
})();
|
|
138
|
+
return {
|
|
139
|
+
path: `${target}/${filePath}`,
|
|
140
|
+
code: formatted
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function writeCodeToPathEachTarget(pathAndCode) {
|
|
144
|
+
const { targets } = Sonamu.config.sync;
|
|
145
|
+
const { appRootPath } = Sonamu;
|
|
146
|
+
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
147
|
+
const dstFilePaths = unique(targets.map((target)=>filePath.replace("/:target/", `/${target}/`)));
|
|
148
|
+
return await Promise.all(dstFilePaths.map(async (dstFilePath)=>{
|
|
149
|
+
const dir = path.dirname(dstFilePath);
|
|
150
|
+
if (!await exists(dir)) {
|
|
151
|
+
await mkdir(dir, {
|
|
152
|
+
recursive: true
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
await writeFile(dstFilePath, pathAndCode.code);
|
|
156
|
+
!isTest() && console.log(chalk.bold("Generated: ") + chalk.blue(`${dstFilePath.replace(`${appRootPath}/`, "")}`));
|
|
157
|
+
return dstFilePath;
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zeW5jZXIvY29kZS1nZW5lcmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHsgbWtkaXIsIHdyaXRlRmlsZSB9IGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHVuaXF1ZSB9IGZyb20gXCJyYWRhc2hpXCI7XG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vYXBpL3NvbmFtdVwiO1xuaW1wb3J0IHsgRW50aXR5TWFuYWdlciB9IGZyb20gXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIjtcbmltcG9ydCB7IEFscmVhZHlQcm9jZXNzZWRFeGNlcHRpb24gfSBmcm9tIFwiLi4vZXhjZXB0aW9ucy9zby1leGNlcHRpb25zXCI7XG5pbXBvcnQgeyBOYWl0ZSB9IGZyb20gXCIuLi9uYWl0ZS9uYWl0ZVwiO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJlZFRlbXBsYXRlIH0gZnJvbSBcIi4uL3RlbXBsYXRlL3RlbXBsYXRlXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZU1hbmFnZXIgfSBmcm9tIFwiLi4vdGVtcGxhdGUvdGVtcGxhdGUtbWFuYWdlclwiO1xuaW1wb3J0IHR5cGUgeyBHZW5lcmF0ZU9wdGlvbnMsIFBhdGhBbmRDb2RlLCBUZW1wbGF0ZUtleSwgVGVtcGxhdGVPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBldmVyeUFzeW5jLCBmaWx0ZXJBc3luYyB9IGZyb20gXCIuLi91dGlscy9hc3luYy11dGlsc1wiO1xuaW1wb3J0IHsgaXNUZXN0IH0gZnJvbSBcIi4uL3V0aWxzL2NvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGZvcm1hdENvZGUgfSBmcm9tIFwiLi4vdXRpbHMvZm9ybWF0dGVyXCI7XG5pbXBvcnQgeyBleGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCB7IHdyYXBJZiB9IGZyb20gXCIuLi91dGlscy9sb2Rhc2gtYWJsZVwiO1xuaW1wb3J0IHR5cGUgeyBBYnNvbHV0ZVBhdGggfSBmcm9tIFwiLi4vdXRpbHMvcGF0aC11dGlsc1wiO1xuXG4vKipcbiAqIO2FnO2UjOumv+ydhCDroIzrjZTrp4HtlZjqs6Ag7YyM7J2866GcIOyDneyEse2VqeuLiOuLpC5cbiAqIG92ZXJ3cml0ZSDsmLXshZjsnbQgZmFsc2Xsnbgg6rK97JqwLCDsnbTrr7gg7KG07J6s7ZWY64qUIO2MjOydvOydgCDqsbTrhIjrnIHri4jri6QuXG4gKiBAcGFyYW0ga2V5IC0g7YWc7ZSM66a/IO2CpCAo7JiIOiBcImVudGl0eVwiLCBcIm1vZGVsXCIsIFwic2VydmljZVwiIOuTsSlcbiAqIEBwYXJhbSB0ZW1wbGF0ZU9wdGlvbnMgLSDthZztlIzrpr8g66CM642U66eB7JeQIO2VhOyalO2VnCDsmLXshZhcbiAqIEBwYXJhbSBfZ2VuZXJhdGVPcHRpb25zIC0g7IOd7ISxIOyYteyFmCAob3ZlcndyaXRlIOyXrOu2gClcbiAqIEByZXR1cm5zIOyDneyEseuQnCDtjIzsnbwg6rK966GcIOuwsOyXtFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVUZW1wbGF0ZTxUIGV4dGVuZHMgVGVtcGxhdGVLZXk+KFxuICBrZXk6IFQsXG4gIHRlbXBsYXRlT3B0aW9uczogVGVtcGxhdGVPcHRpb25zW1RdLFxuICBfZ2VuZXJhdGVPcHRpb25zPzogR2VuZXJhdGVPcHRpb25zLFxuKTogUHJvbWlzZTxBYnNvbHV0ZVBhdGhbXT4ge1xuICBjb25zdCBnZW5lcmF0ZU9wdGlvbnMgPSB7XG4gICAgb3ZlcndyaXRlOiBmYWxzZSxcbiAgICAuLi5fZ2VuZXJhdGVPcHRpb25zLFxuICB9O1xuICBOYWl0ZS50KFwiZ2VuZXJhdGVUZW1wbGF0ZVwiLCB7IGtleSwgdGVtcGxhdGVPcHRpb25zLCBnZW5lcmF0ZU9wdGlvbnMgfSk7XG5cbiAgLy8g7YKkIGNoaWxkcmVuXG4gIGNvbnN0IGtleXM6IFRlbXBsYXRlS2V5W10gPSBba2V5XTtcblxuICAvLyDthZztlIzrpr8g66CM642UXG4gIGNvbnN0IHBhdGhBbmRDb2RlcyA9IChcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGtleXMubWFwKGFzeW5jIChrZXkpID0+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHJlbmRlclRlbXBsYXRlKGtleSwgdGVtcGxhdGVPcHRpb25zKTtcbiAgICAgIH0pLFxuICAgIClcbiAgKS5mbGF0KCk7XG5cbiAgY29uc3QgZmlsdGVyZWRQYXRoQW5kQ29kZXM6IFBhdGhBbmRDb2RlW10gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgIGlmIChnZW5lcmF0ZU9wdGlvbnMub3ZlcndyaXRlID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gcGF0aEFuZENvZGVzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYXdhaXQgZmlsdGVyQXN5bmMocGF0aEFuZENvZGVzLCBhc3luYyAocGF0aEFuZENvZGUpID0+IHtcbiAgICAgICAgY29uc3QgeyB0YXJnZXRzIH0gPSBTb25hbXUuY29uZmlnLnN5bmM7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gYCR7U29uYW11LmFwcFJvb3RQYXRofS8ke3BhdGhBbmRDb2RlLnBhdGh9YDtcbiAgICAgICAgY29uc3QgZHN0RmlsZVBhdGhzID0gdGFyZ2V0cy5tYXAoKHRhcmdldCkgPT4gZmlsZVBhdGgucmVwbGFjZShcIi86dGFyZ2V0L1wiLCBgLyR7dGFyZ2V0fS9gKSk7XG4gICAgICAgIHJldHVybiBhd2FpdCBldmVyeUFzeW5jKGRzdEZpbGVQYXRocywgYXN5bmMgKGRzdFBhdGgpID0+ICEoYXdhaXQgZXhpc3RzKGRzdFBhdGgpKSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgaWYgKGZpbHRlcmVkUGF0aEFuZENvZGVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBBbHJlYWR5UHJvY2Vzc2VkRXhjZXB0aW9uKFwi7J2066+4IOqyveuhnOyXkCDrqqjrk6Ag7YyM7J287J20IOyhtOyerO2VqeuLiOuLpC5cIik7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgZmlsdGVyZWRQYXRoQW5kQ29kZXMubWFwKChwYXRoQW5kQ29kZSkgPT4gd3JpdGVDb2RlVG9QYXRoRWFjaFRhcmdldChwYXRoQW5kQ29kZSkpLFxuICAgIClcbiAgKS5mbGF0KCk7XG59XG5cbi8qKlxuICog7YWc7ZSM66a/7J2EIOugjOuNlOunge2VmOyXrCBQYXRoQW5kQ29kZSDqsJ3ssrTrpbwg67CY7ZmY7ZWp64uI64ukLlxuICog7YyM7J2866GcIOyTsOyngCDslYrqs6Ag66mU66qo66as7IOB7JeQ7ISc66eMIOugjOuNlOunge2VqeuLiOuLpC5cbiAqIEBwYXJhbSBrZXkgLSDthZztlIzrpr8g7YKkXG4gKiBAcGFyYW0gb3B0aW9ucyAtIO2FnO2UjOumvyDroIzrjZTrp4Eg7Ji17IWYXG4gKiBAcmV0dXJucyDqsr3roZzsmYAg7L2U65OcIOyMjeydmCDrsLDsl7RcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbmRlclRlbXBsYXRlPFQgZXh0ZW5kcyBrZXlvZiBUZW1wbGF0ZU9wdGlvbnM+KFxuICBrZXk6IFQsXG4gIG9wdGlvbnM6IFRlbXBsYXRlT3B0aW9uc1tUXSxcbik6IFByb21pc2U8UGF0aEFuZENvZGVbXT4ge1xuICBOYWl0ZS50KFwicmVuZGVyVGVtcGxhdGVcIiwgeyBrZXksIG9wdGlvbnMgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZU1hbmFnZXIuZ2V0KGtleSk7XG5cbiAgY29uc3QgcmVuZGVyZWQgPSBhd2FpdCB0ZW1wbGF0ZS5yZW5kZXIob3B0aW9ucyk7XG4gIGNvbnN0IHJlc29sdmVkID0gYXdhaXQgcmVzb2x2ZVJlbmRlcmVkVGVtcGxhdGUoa2V5LCByZW5kZXJlZCk7XG5cbiAgbGV0IHByZVRlbXBsYXRlUmVzb2x2ZWQ6IFBhdGhBbmRDb2RlW10gPSBbXTtcbiAgaWYgKHJlbmRlcmVkLnByZVRlbXBsYXRlcykge1xuICAgIHByZVRlbXBsYXRlUmVzb2x2ZWQgPSAoXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgcmVuZGVyZWQucHJlVGVtcGxhdGVzLm1hcCgoeyBrZXksIG9wdGlvbnMgfSkgPT4ge1xuICAgICAgICAgIHJldHVybiByZW5kZXJUZW1wbGF0ZShrZXksIG9wdGlvbnMpO1xuICAgICAgICB9KSxcbiAgICAgIClcbiAgICApLmZsYXQoKTtcbiAgfVxuXG4gIHJldHVybiBbcmVzb2x2ZWQsIC4uLnByZVRlbXBsYXRlUmVzb2x2ZWRdO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlUmVuZGVyZWRUZW1wbGF0ZShcbiAga2V5OiBUZW1wbGF0ZUtleSxcbiAgcmVzdWx0OiBSZW5kZXJlZFRlbXBsYXRlLFxuKTogUHJvbWlzZTxQYXRoQW5kQ29kZT4ge1xuICBOYWl0ZS50KGByZXNvbHZlUmVuZGVyZWRUZW1wbGF0ZSR7a2V5fWAsIHsga2V5LCByZXN1bHQgfSk7XG5cbiAgY29uc3QgeyB0YXJnZXQsIHBhdGg6IGZpbGVQYXRoLCBib2R5LCBpbXBvcnRLZXlzLCBjdXN0b21IZWFkZXJzIH0gPSByZXN1bHQ7XG5cbiAgLy8gaW1wb3J0IO2VoCDrjIDsg4HsnZgg64yA7IOBIHBhdGgg7LaU7LacXG4gIGNvbnN0IGltcG9ydERlZnMgPSBpbXBvcnRLZXlzXG4gICAgLnJlZHVjZShcbiAgICAgIChyLCBpbXBvcnRLZXkpID0+IHtcbiAgICAgICAgY29uc3QgbW9kdWxlUGF0aCA9IEVudGl0eU1hbmFnZXIuZ2V0TW9kdWxlUGF0aChpbXBvcnRLZXkpO1xuICAgICAgICBsZXQgaW1wb3J0UGF0aCA9IG1vZHVsZVBhdGg7XG4gICAgICAgIGlmIChtb2R1bGVQYXRoLmluY2x1ZGVzKFwiL1wiKSB8fCBtb2R1bGVQYXRoLmluY2x1ZGVzKFwiLlwiKSkge1xuICAgICAgICAgIGltcG9ydFBhdGggPSB3cmFwSWYocGF0aC5yZWxhdGl2ZShwYXRoLmRpcm5hbWUoZmlsZVBhdGgpLCBtb2R1bGVQYXRoKSwgKHApID0+IFtcbiAgICAgICAgICAgIHAuc3RhcnRzV2l0aChcIi5cIikgPT09IGZhbHNlLFxuICAgICAgICAgICAgYC4vJHtwfWAsXG4gICAgICAgICAgXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyDqsJnsnYAg7YyM7J287JeQ7IScIGltcG9ydCDtlZjripQg6rK97JqwIGtleXMg66GcIOuCmOyXtCDsspjrpqxcbiAgICAgICAgY29uc3QgZXhpc3RzT25lID0gci5maW5kKChpbXBvcnREZWYpID0+IGltcG9ydERlZi5mcm9tID09PSBpbXBvcnRQYXRoKTtcbiAgICAgICAgaWYgKGV4aXN0c09uZSkge1xuICAgICAgICAgIGV4aXN0c09uZS5rZXlzID0gdW5pcXVlKGV4aXN0c09uZS5rZXlzLmNvbmNhdChpbXBvcnRLZXkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByLnB1c2goe1xuICAgICAgICAgICAga2V5czogW2ltcG9ydEtleV0sXG4gICAgICAgICAgICBmcm9tOiBpbXBvcnRQYXRoLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByO1xuICAgICAgfSxcbiAgICAgIFtdIGFzIHtcbiAgICAgICAga2V5czogc3RyaW5nW107XG4gICAgICAgIGZyb206IHN0cmluZztcbiAgICAgIH1bXSxcbiAgICApXG4gICAgLy8g7IWA7ZSEIOywuOyhsCDrsKnsp4BcbiAgICAuZmlsdGVyKChpbXBvcnREZWYpID0+IGZpbGVQYXRoLmVuZHNXaXRoKGAke2ltcG9ydERlZi5mcm9tLnJlcGxhY2UoXCIuL1wiLCBcIlwiKX0udHNgKSA9PT0gZmFsc2UpO1xuXG4gIC8vIOy7pOyKpO2FgCDtl6TrjZQg7Y+s7ZWo7ZWY7JesIO2XpOuNlCDsg53shLFcbiAgY29uc3QgaGVhZGVyID0gW1xuICAgIC4uLihjdXN0b21IZWFkZXJzID8/IFtdKSxcbiAgICAuLi5pbXBvcnREZWZzLm1hcChcbiAgICAgIChpbXBvcnREZWYpID0+IGBpbXBvcnQgeyAke2ltcG9ydERlZi5rZXlzLmpvaW4oXCIsIFwiKX0gfSBmcm9tICcke2ltcG9ydERlZi5mcm9tfSdgLFxuICAgICksXG4gIF0uam9pbihcIlxcblwiKTtcblxuICBjb25zdCBmb3JtYXR0ZWQgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgIGlmIChrZXkgPT09IFwiZ2VuZXJhdGVkX2h0dHBcIikge1xuICAgICAgcmV0dXJuIFtoZWFkZXIsIGJvZHldLmpvaW4oXCJcXG5cXG5cIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIE5haXRlLnQoXCJyZXNvbHZlUmVuZGVyZWRUZW1wbGF0ZTpiZWZvcmVGb3JtYXRcIiwgeyBrZXksIGhlYWRlciwgYm9keSB9KTtcbiAgICAgIGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdENvZGUoXG4gICAgICAgIFtoZWFkZXIsIGJvZHldLmpvaW4oXCJcXG5cXG5cIiksXG4gICAgICAgIGtleSA9PT0gXCJlbnRpdHlcIiA/IFwianNvblwiIDogXCJ0eXBlc2NyaXB0XCIsXG4gICAgICAgIGAke1NvbmFtdS5hcHBSb290UGF0aH0vJHtmaWxlUGF0aH1gLFxuICAgICAgKTtcbiAgICAgIE5haXRlLnQoYHJlc29sdmVSZW5kZXJlZFRlbXBsYXRlOmZvcm1hdHRlZDoke2tleX1gLCBmb3JtYXR0ZWQpO1xuICAgICAgcmV0dXJuIGZvcm1hdHRlZDtcbiAgICB9XG4gIH0pKCk7XG5cbiAgcmV0dXJuIHtcbiAgICBwYXRoOiBgJHt0YXJnZXR9LyR7ZmlsZVBhdGh9YCxcbiAgICBjb2RlOiBmb3JtYXR0ZWQsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlQ29kZVRvUGF0aEVhY2hUYXJnZXQocGF0aEFuZENvZGU6IFBhdGhBbmRDb2RlKTogUHJvbWlzZTxBYnNvbHV0ZVBhdGhbXT4ge1xuICBjb25zdCB7IHRhcmdldHMgfSA9IFNvbmFtdS5jb25maWcuc3luYztcbiAgY29uc3QgeyBhcHBSb290UGF0aCB9ID0gU29uYW11O1xuICBjb25zdCBmaWxlUGF0aCA9IGAke1NvbmFtdS5hcHBSb290UGF0aH0vJHtwYXRoQW5kQ29kZS5wYXRofWAgYXMgQWJzb2x1dGVQYXRoO1xuXG4gIGNvbnN0IGRzdEZpbGVQYXRocyA9IHVuaXF1ZShcbiAgICB0YXJnZXRzLm1hcCgodGFyZ2V0KSA9PiBmaWxlUGF0aC5yZXBsYWNlKFwiLzp0YXJnZXQvXCIsIGAvJHt0YXJnZXR9L2ApKSBhcyBBYnNvbHV0ZVBhdGhbXSxcbiAgKTtcbiAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGRzdEZpbGVQYXRocy5tYXAoYXN5bmMgKGRzdEZpbGVQYXRoKSA9PiB7XG4gICAgICBjb25zdCBkaXIgPSBwYXRoLmRpcm5hbWUoZHN0RmlsZVBhdGgpO1xuICAgICAgaWYgKCEoYXdhaXQgZXhpc3RzKGRpcikpKSB7XG4gICAgICAgIGF3YWl0IG1rZGlyKGRpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB3cml0ZUZpbGUoZHN0RmlsZVBhdGgsIHBhdGhBbmRDb2RlLmNvZGUpO1xuICAgICAgIWlzVGVzdCgpICYmXG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGNoYWxrLmJvbGQoXCJHZW5lcmF0ZWQ6IFwiKSArIGNoYWxrLmJsdWUoYCR7ZHN0RmlsZVBhdGgucmVwbGFjZShgJHthcHBSb290UGF0aH0vYCwgXCJcIil9YCksXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gZHN0RmlsZVBhdGg7XG4gICAgfSksXG4gICk7XG59XG4iXSwibmFtZXMiOlsiY2hhbGsiLCJta2RpciIsIndyaXRlRmlsZSIsInBhdGgiLCJ1bmlxdWUiLCJTb25hbXUiLCJFbnRpdHlNYW5hZ2VyIiwiQWxyZWFkeVByb2Nlc3NlZEV4Y2VwdGlvbiIsIk5haXRlIiwiVGVtcGxhdGVNYW5hZ2VyIiwiZXZlcnlBc3luYyIsImZpbHRlckFzeW5jIiwiaXNUZXN0IiwiZm9ybWF0Q29kZSIsImV4aXN0cyIsIndyYXBJZiIsImdlbmVyYXRlVGVtcGxhdGUiLCJrZXkiLCJ0ZW1wbGF0ZU9wdGlvbnMiLCJfZ2VuZXJhdGVPcHRpb25zIiwiZ2VuZXJhdGVPcHRpb25zIiwib3ZlcndyaXRlIiwidCIsImtleXMiLCJwYXRoQW5kQ29kZXMiLCJQcm9taXNlIiwiYWxsIiwibWFwIiwicmVuZGVyVGVtcGxhdGUiLCJmbGF0IiwiZmlsdGVyZWRQYXRoQW5kQ29kZXMiLCJwYXRoQW5kQ29kZSIsInRhcmdldHMiLCJjb25maWciLCJzeW5jIiwiZmlsZVBhdGgiLCJhcHBSb290UGF0aCIsImRzdEZpbGVQYXRocyIsInRhcmdldCIsInJlcGxhY2UiLCJkc3RQYXRoIiwibGVuZ3RoIiwid3JpdGVDb2RlVG9QYXRoRWFjaFRhcmdldCIsIm9wdGlvbnMiLCJ0ZW1wbGF0ZSIsImdldCIsInJlbmRlcmVkIiwicmVuZGVyIiwicmVzb2x2ZWQiLCJyZXNvbHZlUmVuZGVyZWRUZW1wbGF0ZSIsInByZVRlbXBsYXRlUmVzb2x2ZWQiLCJwcmVUZW1wbGF0ZXMiLCJyZXN1bHQiLCJib2R5IiwiaW1wb3J0S2V5cyIsImN1c3RvbUhlYWRlcnMiLCJpbXBvcnREZWZzIiwicmVkdWNlIiwiciIsImltcG9ydEtleSIsIm1vZHVsZVBhdGgiLCJnZXRNb2R1bGVQYXRoIiwiaW1wb3J0UGF0aCIsImluY2x1ZGVzIiwicmVsYXRpdmUiLCJkaXJuYW1lIiwicCIsInN0YXJ0c1dpdGgiLCJleGlzdHNPbmUiLCJmaW5kIiwiaW1wb3J0RGVmIiwiZnJvbSIsImNvbmNhdCIsInB1c2giLCJmaWx0ZXIiLCJlbmRzV2l0aCIsImhlYWRlciIsImpvaW4iLCJmb3JtYXR0ZWQiLCJjb2RlIiwiZHN0RmlsZVBhdGgiLCJkaXIiLCJyZWN1cnNpdmUiLCJjb25zb2xlIiwibG9nIiwiYm9sZCIsImJsdWUiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLFdBQVcsUUFBUTtBQUMxQixTQUFTQyxLQUFLLEVBQUVDLFNBQVMsUUFBUSxtQkFBYztBQUMvQyxPQUFPQyxVQUFVLE9BQU87QUFDeEIsU0FBU0MsTUFBTSxRQUFRLFVBQVU7QUFDakMsU0FB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
|