sonamu 0.5.7 → 0.6.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/dist/api/base-frame.js +12 -2
- package/dist/api/caster.js +66 -2
- package/dist/api/code-converters.js +489 -2
- package/dist/api/config.d.ts +76 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +32 -0
- package/dist/api/context.d.ts +1 -0
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +3 -2
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +142 -2
- package/dist/api/index.js +9 -2
- package/dist/api/sonamu.d.ts +8 -22
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +482 -2
- package/dist/bin/build-config.d.ts +2 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +12 -2
- package/dist/bin/cli-wrapper.js +71 -2
- package/dist/bin/cli.js +418 -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/database/_batch_update.js +78 -2
- package/dist/database/base-model.js +247 -2
- package/dist/database/code-generator.js +53 -2
- package/dist/database/db.d.ts +2 -16
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +132 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +39 -2
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +23 -16
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +539 -2
- package/dist/database/puri.types.d.ts +8 -3
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +3 -2
- package/dist/database/transaction-context.js +14 -2
- package/dist/database/upsert-builder.js +215 -2
- package/dist/entity/entity-manager.d.ts +3 -1
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +114 -2
- package/dist/entity/entity-utils.js +210 -2
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +651 -2
- package/dist/exceptions/error-handler.js +29 -2
- package/dist/exceptions/so-exceptions.js +85 -2
- package/dist/file-storage/driver.js +79 -2
- package/dist/file-storage/file-storage.js +75 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/migration/code-generation.js +558 -2
- package/dist/migration/migration-set.js +364 -2
- package/dist/migration/migrator.d.ts +0 -9
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +510 -2
- package/dist/migration/types.js +3 -2
- package/dist/naite/naite.d.ts +12 -0
- package/dist/naite/naite.d.ts.map +1 -0
- package/dist/naite/naite.js +72 -0
- package/dist/stream/index.js +3 -2
- package/dist/stream/sse.js +38 -2
- package/dist/syncer/api-parser.d.ts +20 -0
- package/dist/syncer/api-parser.d.ts.map +1 -0
- package/dist/syncer/api-parser.js +229 -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 +141 -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 +58 -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 +82 -0
- package/dist/syncer/syncer.d.ts +93 -108
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +375 -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 +101 -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 +87 -0
- package/dist/{templates → template/implementations}/generated.template.d.ts +3 -3
- package/dist/template/implementations/generated.template.d.ts.map +1 -0
- package/dist/template/implementations/generated.template.js +232 -0
- package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -3
- 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 +3 -3
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_sso.template.js +105 -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 +171 -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 +193 -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 +465 -0
- package/dist/{templates → template/implementations}/view_list_columns.template.d.ts +3 -3
- 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 +5 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +6 -0
- package/dist/template/template.d.ts +39 -0
- package/dist/template/template.d.ts.map +1 -0
- package/dist/template/template.js +47 -0
- package/dist/template/zod-converter.d.ts +18 -0
- package/dist/template/zod-converter.d.ts.map +1 -0
- package/dist/template/zod-converter.js +166 -0
- package/dist/testing/_relation-graph.js +80 -2
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +521 -2
- package/dist/types/types.d.ts +39 -40
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +289 -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.js +26 -2
- package/dist/utils/esm-utils.d.ts +45 -0
- package/dist/utils/esm-utils.d.ts.map +1 -0
- package/dist/utils/esm-utils.js +56 -0
- package/dist/utils/fs-utils.js +17 -2
- package/dist/utils/lodash-able.js +6 -2
- package/dist/utils/model.js +22 -2
- 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.js +35 -2
- package/dist/utils/utils.d.ts +4 -7
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +33 -2
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +19 -2
- package/package.json +21 -8
- package/src/api/code-converters.ts +2 -2
- package/src/api/config.ts +142 -0
- package/src/api/context.ts +1 -0
- package/src/api/decorators.ts +1 -0
- package/src/api/sonamu.ts +81 -67
- package/src/bin/build-config.ts +2 -1
- package/src/bin/cli-wrapper.ts +10 -3
- package/src/bin/cli.ts +108 -56
- package/src/bin/hot-hook-register.ts +22 -0
- package/src/database/base-model.ts +1 -1
- package/src/database/code-generator.ts +1 -1
- package/src/database/db.ts +10 -52
- package/src/database/puri.ts +78 -53
- package/src/database/puri.types.ts +18 -5
- package/src/database/upsert-builder.ts +1 -1
- package/src/entity/entity-manager.ts +19 -15
- package/src/entity/entity.ts +4 -3
- package/src/index.ts +2 -0
- package/src/migration/code-generation.ts +1 -1
- package/src/migration/migration-set.ts +1 -1
- package/src/migration/migrator.ts +23 -152
- package/src/naite/naite.ts +70 -0
- package/src/syncer/api-parser.ts +299 -0
- package/src/syncer/checksum.ts +152 -0
- package/src/syncer/code-generator.ts +202 -0
- package/src/syncer/entity-operations.ts +68 -0
- package/src/syncer/file-patterns.ts +56 -0
- package/src/syncer/index.ts +6 -0
- package/src/syncer/module-loader.ts +125 -0
- package/src/syncer/syncer.ts +363 -1420
- package/src/template/entity-converter.ts +123 -0
- package/src/template/helpers.ts +84 -0
- package/src/{templates → template/implementations}/entity.template.ts +4 -4
- package/src/{templates → template/implementations}/generated.template.ts +9 -9
- package/src/{templates → template/implementations}/generated_http.template.ts +9 -6
- package/src/{templates → template/implementations}/generated_sso.template.ts +7 -7
- package/src/{templates → template/implementations}/init_types.template.ts +4 -4
- package/src/{templates → template/implementations}/model.template.ts +9 -9
- package/src/{templates → template/implementations}/model_test.template.ts +5 -5
- package/src/{templates → template/implementations}/service.template.ts +19 -11
- package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
- package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +5 -21
- package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
- package/src/{templates → template/implementations}/view_form.template.ts +11 -13
- package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_id_async_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_list.template.ts +13 -64
- package/src/{templates → template/implementations}/view_list_columns.template.ts +3 -3
- package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
- package/src/template/index.ts +4 -0
- package/src/template/template.ts +86 -0
- package/src/template/zod-converter.ts +219 -0
- package/src/testing/fixture-manager.ts +8 -1
- package/src/types/types.ts +38 -61
- package/src/utils/async-utils.ts +17 -0
- package/src/utils/console-util.ts +4 -0
- package/src/utils/esm-utils.ts +69 -0
- package/src/utils/path-utils.ts +102 -0
- package/src/utils/process-utils.ts +46 -0
- package/src/utils/sql-parser.ts +1 -1
- package/src/utils/utils.ts +14 -40
- package/src/utils/zod-error.ts +0 -1
- 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.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.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.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.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/templates/base-template.ts +0 -19
- package/src/templates/index.ts +0 -1
package/dist/api/sonamu.js
CHANGED
|
@@ -1,2 +1,482 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"Sonamu",{enumerable:true,get:function(){return Sonamu}});var _async_hooks=require("async_hooks");var _chalk=/*#__PURE__*/_interop_require_default(require("chalk"));var _fastify=/*#__PURE__*/_interop_require_default(require("fastify"));var _promises=require("fs/promises");var _path=/*#__PURE__*/_interop_require_default(require("path"));var _fsutils=require("../utils/fs-utils");var _datefnstz=require("date-fns-tz");var _zod=require("zod");var _db=require("../database/db");var _knexonduplicateupdate=require("../database/knex-plugins/knex-on-duplicate-update");var _soexceptions=require("../exceptions/so-exceptions");var _sse=require("../stream/sse");var _types=require("../types/types");var _controller=require("../utils/controller");var _utils=require("../utils/utils");var _zoderror=require("../utils/zod-error");var _caster=require("./caster");var _codeconverters=require("./code-converters");var _passport=/*#__PURE__*/_interop_require_default(require("@fastify/passport"));function _array_like_to_array(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _array_with_holes(arr){if(Array.isArray(arr))return arr}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _class_call_check(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}function _create_class(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor}function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _instanceof(left,right){if(right!=null&&typeof Symbol!=="undefined"&&right[Symbol.hasInstance]){return!!right[Symbol.hasInstance](left)}else{return left instanceof right}}function _interop_require_default(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap;var cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interop_require_wildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj}}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj)}var newObj={__proto__:null};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc)}else{newObj[key]=obj[key]}}}newObj.default=obj;if(cache){cache.set(obj,newObj)}return newObj}function _iterable_to_array_limit(arr,i){var _i=arr==null?null:typeof Symbol!=="undefined"&&arr[Symbol.iterator]||arr["@@iterator"];if(_i==null)return;var _arr=[];var _n=true;var _d=false;var _s,_e;try{for(_i=_i.call(arr);!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break}}catch(err){_d=true;_e=err}finally{try{if(!_n&&_i["return"]!=null)_i["return"]()}finally{if(_d)throw _e}}return _arr}function _non_iterable_rest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _object_spread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};var ownKeys=Object.keys(source);if(typeof Object.getOwnPropertySymbols==="function"){ownKeys=ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym){return Object.getOwnPropertyDescriptor(source,sym).enumerable}))}ownKeys.forEach(function(key){_define_property(target,key,source[key])})}return target}function _sliced_to_array(arr,i){return _array_with_holes(arr)||_iterable_to_array_limit(arr,i)||_unsupported_iterable_to_array(arr,i)||_non_iterable_rest()}function _unsupported_iterable_to_array(o,minLen){if(!o)return;if(typeof o==="string")return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(n);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}function _ts_generator(thisArg,body){var f,y,t,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},g=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return g.next=verb(0),g["throw"]=verb(1),g["return"]=verb(2),typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(g&&(g=0,op[0]&&(_=0)),_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}var SonamuClass=/*#__PURE__*/function(){"use strict";function SonamuClass(){_class_call_check(this,SonamuClass);_define_property(this,"isInitialized",false);_define_property(this,"asyncLocalStorage",new _async_hooks.AsyncLocalStorage);_define_property(this,"uploadStorage",new _async_hooks.AsyncLocalStorage);_define_property(this,"_apiRootPath",null);_define_property(this,"_dbConfig",null);_define_property(this,"_syncer",null);_define_property(this,"_config",null);_define_property(this,"_secrets",null);_define_property(this,"_storage",null);_define_property(this,"watcher",null);_define_property(this,"pendingFiles",[]);_define_property(this,"hmrStartTime",0);_define_property(this,"server",null)}_create_class(SonamuClass,[{key:"getContext",value:function getContext(){var store=this.asyncLocalStorage.getStore();if(store===null||store===void 0?void 0:store.context){return store.context}throw new Error("Sonamu cannot find context")}},{key:"getUploadContext",value:function getUploadContext(){var store=this.uploadStorage.getStore();if(store===null||store===void 0?void 0:store.uploadContext){return store.uploadContext}throw new Error("Sonamu cannot find upload context. Did you use @upload decorator?")}},{key:"apiRootPath",get:function get(){if(this._apiRootPath===null){throw new Error("Sonamu has not been initialized")}return this._apiRootPath},set:function set(apiRootPath){this._apiRootPath=apiRootPath}},{key:"appRootPath",get:function get(){return this.apiRootPath.split(_path.default.sep).slice(0,-1).join(_path.default.sep)}},{key:"dbConfig",get:function get(){if(this._dbConfig===null){throw new Error("Sonamu has not been initialized")}return this._dbConfig},set:function set(dbConfig){this._dbConfig=dbConfig}},{key:"syncer",get:function get(){if(this._syncer===null){throw new Error("Sonamu has not been initialized")}return this._syncer},set:function set(syncer){this._syncer=syncer}},{key:"config",get:function get(){if(this._config===null){throw new Error("Sonamu has not been initialized")}return this._config},set:function set(config){this._config=config}},{key:"secrets",get:function get(){return this._secrets},set:function set(secrets){this._secrets=secrets}},{key:"storage",get:function get(){return this._storage},set:function set(storage){this._storage=storage}},{key:"initForTesting",value:function initForTesting(){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.init(true,false,undefined,true)];case 1:_state.sent();return[2]}})}).call(this)}},{key:"init",value:function init(){var doSilent=arguments.length>0&&arguments[0]!==void 0?arguments[0]:false,enableSync=arguments.length>1&&arguments[1]!==void 0?arguments[1]:true,apiRootPath=arguments.length>2?arguments[2]:void 0,forTesting=arguments.length>3&&arguments[3]!==void 0?arguments[3]:false;return _async_to_generator(function(){var configPath,secretsPath,_,_1,_2,_3,_4,EntityManager,Syncer;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(this.isInitialized){return[2]}!doSilent&&console.time(_chalk.default.cyan("Sonamu.init".concat(forTesting?" for testing":"")));this.apiRootPath=apiRootPath!==null&&apiRootPath!==void 0?apiRootPath:(0,_utils.findApiRootPath)();configPath=_path.default.join(this.apiRootPath,"sonamu.config.json");secretsPath=_path.default.join(this.apiRootPath,"sonamu.secrets.json");return[4,(0,_fsutils.exists)(configPath)];case 1:if(!_state.sent()){throw new Error("Cannot find sonamu.config.json in ".concat(configPath))}_=this;_1=JSON.parse;return[4,(0,_promises.readFile)(configPath)];case 2:_.config=_1.apply(JSON,[_state.sent().toString()]);return[4,(0,_fsutils.exists)(secretsPath)];case 3:if(!_state.sent())return[3,5];_2=this;_3=JSON.parse;return[4,(0,_promises.readFile)(secretsPath)];case 4:_2.secrets=_3.apply(JSON,[_state.sent().toString()]);_state.label=5;case 5:_4=this;return[4,_db.DB.readKnexfile()];case 6:_4.dbConfig=_state.sent();!doSilent&&console.log(_chalk.default.green("DB Config Loaded!"));(0,_knexonduplicateupdate.attachOnDuplicateUpdate)();if(forTesting){this.isInitialized=true;return[2]}return[4,Promise.resolve().then(function(){return /*#__PURE__*/_interop_require_wildcard(require("../entity/entity-manager"))})];case 7:EntityManager=_state.sent().EntityManager;return[4,EntityManager.autoload(doSilent)];case 8:_state.sent();return[4,Promise.resolve().then(function(){return /*#__PURE__*/_interop_require_wildcard(require("../syncer/syncer"))})];case 9:Syncer=_state.sent().Syncer;this.syncer=new Syncer;return[4,this.syncer.autoloadModels()];case 10:_state.sent();return[4,this.syncer.autoloadTypes()];case 11:_state.sent();return[4,this.syncer.autoloadApis()];case 12:_state.sent();if(!((0,_controller.isLocal)()&&!(0,_controller.isTest)()&&enableSync))return[3,14];return[4,this.syncer.sync()];case 13:_state.sent();this.startWatcher();this.syncer.syncUI();_state.label=14;case 14:this.isInitialized=true;!doSilent&&console.timeEnd(_chalk.default.cyan("Sonamu.init"));return[2]}})}).call(this)}},{key:"createServer",value:function createServer(options,initOptions){return _async_to_generator(function(){var server,_options_plugins;return _ts_generator(this,function(_state){switch(_state.label){case 0:server=(0,_fastify.default)(options.fastify);this.server=server;if(options.storage){this.storage=options.storage}if(options.plugins){this.registerPlugins(server,options.plugins)}if(options.auth){;if(!((_options_plugins=options.plugins)===null||_options_plugins===void 0?void 0:_options_plugins.session)){throw new Error("Auth requires session plugin. Please add plugins.session configuration.")}this.registerAuth(server,options.auth)}return[4,this.withFastify(server,options.apiConfig,{enableSync:initOptions===null||initOptions===void 0?void 0:initOptions.enableSync,doSilent:initOptions===null||initOptions===void 0?void 0:initOptions.doSilent})];case 1:_state.sent();return[4,this.boot(server,options)];case 2:_state.sent();return[2,server]}})}).call(this)}},{key:"withFastify",value:function withFastify(server,config,options){return _async_to_generator(function(){var _this,timezone,DATE_FORMAT,ISO_DATE_REGEX;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;if(!(this.isInitialized===false))return[3,2];return[4,this.init(options===null||options===void 0?void 0:options.doSilent,options===null||options===void 0?void 0:options.enableSync)];case 1:_state.sent();_state.label=2;case 2:this.server=server;timezone=this.config.timezone;if(timezone){DATE_FORMAT="yyyy-MM-dd'T'HH:mm:ssXXX";ISO_DATE_REGEX=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;server.setReplySerializer(function(payload){return JSON.stringify(payload,function(_key,value){if(typeof value==="string"&&ISO_DATE_REGEX.test(value)){return(0,_datefnstz.formatInTimeZone)(new Date(value),timezone,DATE_FORMAT)}return value})});!(options===null||options===void 0?void 0:options.doSilent)&&console.log(_chalk.default.green("Timezone set to ".concat(timezone)))}server.get("".concat(this.config.route.prefix,"/routes"),function(_request,_reply){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,this.syncer.apis]})}).call(_this)});server.get("".concat(this.config.route.prefix,"/healthcheck"),function(_request,_reply){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,"ok"]})})()});if((0,_controller.isLocal)()){server.all("*",function(request,reply){var found=_this.syncer.apis.find(function(api){var _api_options_httpMethod;return _this.config.route.prefix+api.path===request.url.split("?")[0]&&((_api_options_httpMethod=api.options.httpMethod)!==null&&_api_options_httpMethod!==void 0?_api_options_httpMethod:"GET")===request.method.toUpperCase()});if(found){return _this.getApiHandler(found,config)(request,reply)}throw new _soexceptions.NotFoundException("존재하지 않는 API 접근입니다.")})}else{this.syncer.apis.map(function(api){if(_this.syncer.models[api.modelName]===undefined){throw new Error("정의되지 않은 모델에 접근 ".concat(api.modelName))}server.route({method:api.options.httpMethod,url:_this.config.route.prefix+api.path,handler:_this.getApiHandler(api,config)})})}return[2]}})}).call(this)}},{key:"getApiHandler",value:function getApiHandler(api,config){var _this=this;return function(request,reply){return _async_to_generator(function(){var _api_options_guards,ReqType,which,reqBody,_request_which,messages,_api_options_contentType,_ref,cacheKey,cacheTtl,cachedData,createSSE,_request_user,context,_tmp,model;return _ts_generator(this,function(_state){switch(_state.label){case 0:((_api_options_guards=api.options.guards)!==null&&_api_options_guards!==void 0?_api_options_guards:[]).every(function(guard){return config.guardHandler(guard,request,api)});ReqType=(0,_codeconverters.getZodObjectFromApi)(api,this.syncer.types);which=api.options.httpMethod==="GET"?"query":"body";try{;reqBody=(0,_caster.fastifyCaster)(ReqType).parse((_request_which=request[which])!==null&&_request_which!==void 0?_request_which:{})}catch(e){if(_instanceof(e,_zod.ZodError)){messages=(0,_zoderror.humanizeZodError)(e).map(function(issue){return issue.message}).join(" ");throw new _soexceptions.BadRequestException(messages,{zodError:e})}else{throw e}}reply.type((_api_options_contentType=api.options.contentType)!==null&&_api_options_contentType!==void 0?_api_options_contentType:"application/json");return[4,function(){return _async_to_generator(function(){var cacheKeyRes,cacheKey,cacheTtl,cachedData,e;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(!config.cache)return[3,5];_state.label=1;case 1:_state.trys.push([1,3,,4]);cacheKeyRes=config.cache.resolveKey(api.path,reqBody);if(cacheKeyRes.cache===false){return[2,{cacheKey:null,cachedData:null}]}cacheKey=cacheKeyRes.key;cacheTtl=cacheKeyRes.ttl;return[4,config.cache.get(cacheKey)];case 2:cachedData=_state.sent();return[2,{cacheKey:cacheKey,cacheTtl:cacheTtl,cachedData:cachedData}];case 3:e=_state.sent();console.error(e);return[3,4];case 4:return[2,{cacheKey:null,cachedData:null}];case 5:return[2,{cacheKey:null,cachedData:null}]}})})()}()];case 1:_ref=_state.sent(),cacheKey=_ref.cacheKey,cacheTtl=_ref.cacheTtl,cachedData=_ref.cachedData;if(cachedData!==null){return[2,cachedData]}createSSE=(function(_request,_reply,_events){return(0,_sse.createSSEFactory)(_request.socket,_reply,_events)}).bind(null,request,reply);_tmp=[{}];return[4,Promise.resolve(config.contextProvider({request:request,reply:reply,headers:request.headers,createSSE:createSSE,user:(_request_user=request.user)!==null&&_request_user!==void 0?_request_user:null,passport:{login:request.login.bind(request),logout:request.logout.bind(request)}},request,reply))];case 2:context=_object_spread.apply(void 0,_tmp.concat([_state.sent()]));model=this.syncer.models[api.modelName];return[2,this.asyncLocalStorage.run({context:context},function(){return _async_to_generator(function(){var result,_api_options_contentType;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,model[api.methodName].apply(model,api.parameters.map(function(param){if(_types.ApiParamType.isContext(param.type)){return context}else{return reqBody[param.name]}}))];case 1:result=_state.sent();reply.type((_api_options_contentType=api.options.contentType)!==null&&_api_options_contentType!==void 0?_api_options_contentType:"application/json");if(!(config.cache&&cacheKey))return[3,3];return[4,config.cache.put(cacheKey,result,cacheTtl)];case 2:_state.sent();_state.label=3;case 3:return[2,result]}})})()})]}})}).call(_this)}}},{key:"startWatcher",value:function startWatcher(){var _this=this;var watchPath=_path.default.join(this.apiRootPath,"src");var chokidar=require("chokidar");this.watcher=chokidar.watch(watchPath,{ignored:function(path,stats){return!!(stats===null||stats===void 0?void 0:stats.isFile())&&!path.endsWith(".ts")&&!path.endsWith(".json")||path.endsWith("src/index.ts")},persistent:true,ignoreInitial:true});this.watcher.on("all",function(event,filePath){return _async_to_generator(function(){var e;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(event!=="change"&&event!=="add"){return[2]}_state.label=1;case 1:_state.trys.push([1,3,,4]);return[4,this.handleFileChange(event,filePath)];case 2:_state.sent();return[3,4];case 3:e=_state.sent();console.error(e);return[3,4];case 4:return[2]}})}).call(_this)})}},{key:"runScript",value:function runScript(fn){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.init(true,false,undefined,false)];case 1:_state.sent();_state.label=2;case 2:_state.trys.push([2,,4,6]);return[4,fn()];case 3:_state.sent();return[3,6];case 4:return[4,this.destroy()];case 5:_state.sent();return[7];case 6:return[2]}})}).call(this)}},{key:"registerPlugins",value:function registerPlugins(server,plugins){if(!plugins){return}var pluginsModules={cors:"@fastify/cors",formbody:"@fastify/formbody",multipart:"@fastify/multipart",qs:"fastify-qs",sse:"fastify-sse-v2",static:"@fastify/static",session:"@fastify/secure-session"};var registerPlugin=function(key,pluginName){var option=plugins[key];if(!option)return;if(option===true){server.register(Promise.resolve(pluginName).then(function(p){return /*#__PURE__*/_interop_require_wildcard(require(p))}))}else{server.register(Promise.resolve(pluginName).then(function(p){return /*#__PURE__*/_interop_require_wildcard(require(p))}),option)}};Object.entries(pluginsModules).forEach(function(param){var _param=_sliced_to_array(param,2),key=_param[0],pluginName=_param[1];registerPlugin(key,pluginName)});if(plugins.custom){plugins.custom(server)}}},{key:"registerAuth",value:function registerAuth(server,options){return _async_to_generator(function(){return _ts_generator(this,function(_state){server.register(_passport.default.initialize());server.register(_passport.default.secureSession());if(typeof options==="boolean"){_passport.default.registerUserSerializer(function(user,_request){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,user]})})()});_passport.default.registerUserDeserializer(function(serialized,_request){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,serialized]})})()})}else{_passport.default.registerUserSerializer(options.userSerializer);_passport.default.registerUserDeserializer(options.userDeserializer)}return[2]})})()}},{key:"boot",value:function boot(server,options){return _async_to_generator(function(){var _this,_options_listen,_options_listen1,_options_lifecycle,_options_listen_port,port,_options_listen_host,host,shutdown,_options_lifecycle1;return _ts_generator(this,function(_state){_this=this;port=(_options_listen_port=(_options_listen=options.listen)===null||_options_listen===void 0?void 0:_options_listen.port)!==null&&_options_listen_port!==void 0?_options_listen_port:3e3;host=(_options_listen_host=(_options_listen1=options.listen)===null||_options_listen1===void 0?void 0:_options_listen1.host)!==null&&_options_listen_host!==void 0?_options_listen_host:"localhost";server.addHook("onClose",function(){return _async_to_generator(function(){var _options_lifecycle_onShutdown,_options_lifecycle;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(_options_lifecycle=options.lifecycle)===null||_options_lifecycle===void 0?void 0:(_options_lifecycle_onShutdown=_options_lifecycle.onShutdown)===null||_options_lifecycle_onShutdown===void 0?void 0:_options_lifecycle_onShutdown.call(_options_lifecycle,server)];case 1:_state.sent();return[4,this.destroy()];case 2:_state.sent();return[2]}})}).call(_this)});shutdown=function(){return _async_to_generator(function(){var err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,server.close()];case 1:_state.sent();process.exit(0);return[3,3];case 2:err=_state.sent();console.error("Error during shutdown:",err);process.exit(1);return[3,3];case 3:return[2]}})})()};process.on("SIGINT",shutdown);process.on("SIGTERM",shutdown);if((_options_lifecycle=options.lifecycle)===null||_options_lifecycle===void 0?void 0:_options_lifecycle.onError){;server.setErrorHandler((_options_lifecycle1=options.lifecycle)===null||_options_lifecycle1===void 0?void 0:_options_lifecycle1.onError)}server.listen({port:port,host:host}).then(function(){return _async_to_generator(function(){var _options_lifecycle_onStart,_options_lifecycle;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(_options_lifecycle=options.lifecycle)===null||_options_lifecycle===void 0?void 0:(_options_lifecycle_onStart=_options_lifecycle.onStart)===null||_options_lifecycle_onStart===void 0?void 0:_options_lifecycle_onStart.call(_options_lifecycle,server)];case 1:_state.sent();return[2]}})})()}).catch(function(err){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:console.error(_chalk.default.red("Failed to start server:",err));return[4,shutdown()];case 1:_state.sent();return[2]}})})()});return[2]})}).call(this)}},{key:"handleFileChange",value:function handleFileChange(event,filePath){return _async_to_generator(function(){var relativePath;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(this.pendingFiles.length===0){this.hmrStartTime=Date.now()}this.pendingFiles.push(filePath);relativePath=filePath.replace(this.apiRootPath,"api");console.log(_chalk.default.bold("Detected(".concat(event,"): ").concat(_chalk.default.blue(relativePath))));return[4,this.syncer.syncFromWatcher([filePath])];case 1:_state.sent();this.pendingFiles=this.pendingFiles.slice(1);if(!(this.pendingFiles.length===0))return[3,3];return[4,this.finishHMR()];case 2:_state.sent();_state.label=3;case 3:return[2]}})}).call(this)}},{key:"finishHMR",value:function finishHMR(){return _async_to_generator(function(){var _,_1,endTime,totalTime,msg,margin;return _ts_generator(this,function(_state){switch(_state.label){case 0:_1=(_=this.syncer).saveChecksums;return[4,this.syncer.getCurrentChecksums()];case 1:return[4,_1.apply(_,[_state.sent()])];case 2:_state.sent();endTime=Date.now();totalTime=endTime-this.hmrStartTime;msg="HMR Done! ".concat(_chalk.default.bold.white("".concat(totalTime,"ms")));margin=Math.max(0,(process.stdout.columns-msg.length)/2);console.log(_chalk.default.black.bgGreen(" ".repeat(margin)+msg+" ".repeat(margin)));return[2]}})}).call(this)}},{key:"destroy",value:function destroy(){return _async_to_generator(function(){var _this_watcher,_this_storage,BaseModel;return _ts_generator(this,function(_state){switch(_state.label){case 0:BaseModel=require("../database/base-model").BaseModel;return[4,BaseModel.destroy()];case 1:_state.sent();return[4,(_this_watcher=this.watcher)===null||_this_watcher===void 0?void 0:_this_watcher.close()];case 2:_state.sent();(_this_storage=this.storage)===null||_this_storage===void 0?void 0:_this_storage.destroy();return[2]}})}).call(this)}}]);return SonamuClass}();var Sonamu=new SonamuClass;
|
|
2
|
-
|
|
1
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import fastify from "fastify";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { exists } from "../utils/fs-utils.js";
|
|
7
|
+
import chokidar from "chokidar";
|
|
8
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
9
|
+
import { ZodError } from "zod";
|
|
10
|
+
import { DB } from "../database/db.js";
|
|
11
|
+
import { attachOnDuplicateUpdate } from "../database/knex-plugins/knex-on-duplicate-update.js";
|
|
12
|
+
import { BadRequestException, NotFoundException } from "../exceptions/so-exceptions.js";
|
|
13
|
+
import { createSSEFactory } from "../stream/sse.js";
|
|
14
|
+
import { ApiParamType } from "../types/types.js";
|
|
15
|
+
import { isLocal, isTest } from "../utils/controller.js";
|
|
16
|
+
import { findApiRootPath } from "../utils/utils.js";
|
|
17
|
+
import { humanizeZodError } from "../utils/zod-error.js";
|
|
18
|
+
import { fastifyCaster } from "./caster.js";
|
|
19
|
+
import { getZodObjectFromApi } from "./code-converters.js";
|
|
20
|
+
import fastifyPassport from "@fastify/passport";
|
|
21
|
+
import { loadConfig } from "./config.js";
|
|
22
|
+
import { isHotReloadServer } from "../utils/esm-utils.js";
|
|
23
|
+
import { Template } from "../template/index.js";
|
|
24
|
+
import assert from "assert";
|
|
25
|
+
import { centerText } from "../utils/console-util.js";
|
|
26
|
+
import { BaseModel } from "../database/base-model.js";
|
|
27
|
+
class SonamuClass {
|
|
28
|
+
isInitialized = false;
|
|
29
|
+
asyncLocalStorage = new AsyncLocalStorage();
|
|
30
|
+
uploadStorage = new AsyncLocalStorage();
|
|
31
|
+
getContext() {
|
|
32
|
+
const store = this.asyncLocalStorage.getStore();
|
|
33
|
+
if (store?.context) {
|
|
34
|
+
return store.context;
|
|
35
|
+
}
|
|
36
|
+
if (process.env.NODE_ENV === "test") {
|
|
37
|
+
// 테스팅 환경에서 컨텍스트가 주입되지 않은 경우 빈 컨텍스트 리턴
|
|
38
|
+
return {
|
|
39
|
+
request: null,
|
|
40
|
+
reply: null,
|
|
41
|
+
headers: {},
|
|
42
|
+
createSSE: ()=>{},
|
|
43
|
+
naiteStore: new Map()
|
|
44
|
+
};
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error("Sonamu cannot find context");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
getUploadContext() {
|
|
50
|
+
const store = this.uploadStorage.getStore();
|
|
51
|
+
if (store?.uploadContext) {
|
|
52
|
+
return store.uploadContext;
|
|
53
|
+
}
|
|
54
|
+
throw new Error("Sonamu cannot find upload context. Did you use @upload decorator?");
|
|
55
|
+
}
|
|
56
|
+
_apiRootPath = null;
|
|
57
|
+
set apiRootPath(apiRootPath) {
|
|
58
|
+
this._apiRootPath = apiRootPath;
|
|
59
|
+
}
|
|
60
|
+
get apiRootPath() {
|
|
61
|
+
if (this._apiRootPath === null) {
|
|
62
|
+
throw new Error("Sonamu has not been initialized");
|
|
63
|
+
}
|
|
64
|
+
return this._apiRootPath;
|
|
65
|
+
}
|
|
66
|
+
get appRootPath() {
|
|
67
|
+
return this.apiRootPath.split(path.sep).slice(0, -1).join(path.sep);
|
|
68
|
+
}
|
|
69
|
+
_dbConfig = null;
|
|
70
|
+
set dbConfig(dbConfig) {
|
|
71
|
+
this._dbConfig = dbConfig;
|
|
72
|
+
}
|
|
73
|
+
get dbConfig() {
|
|
74
|
+
if (this._dbConfig === null) {
|
|
75
|
+
throw new Error("Sonamu has not been initialized");
|
|
76
|
+
}
|
|
77
|
+
return this._dbConfig;
|
|
78
|
+
}
|
|
79
|
+
_syncer = null;
|
|
80
|
+
set syncer(syncer) {
|
|
81
|
+
this._syncer = syncer;
|
|
82
|
+
}
|
|
83
|
+
get syncer() {
|
|
84
|
+
if (this._syncer === null) {
|
|
85
|
+
throw new Error("Sonamu has not been initialized");
|
|
86
|
+
}
|
|
87
|
+
return this._syncer;
|
|
88
|
+
}
|
|
89
|
+
_config = null;
|
|
90
|
+
set config(config) {
|
|
91
|
+
this._config = config;
|
|
92
|
+
}
|
|
93
|
+
get config() {
|
|
94
|
+
if (this._config === null) {
|
|
95
|
+
throw new Error("Sonamu has not been initialized");
|
|
96
|
+
}
|
|
97
|
+
return this._config;
|
|
98
|
+
}
|
|
99
|
+
_secrets = null;
|
|
100
|
+
set secrets(secrets) {
|
|
101
|
+
this._secrets = secrets;
|
|
102
|
+
}
|
|
103
|
+
get secrets() {
|
|
104
|
+
return this._secrets;
|
|
105
|
+
}
|
|
106
|
+
_storage = null;
|
|
107
|
+
set storage(storage) {
|
|
108
|
+
this._storage = storage;
|
|
109
|
+
}
|
|
110
|
+
get storage() {
|
|
111
|
+
return this._storage;
|
|
112
|
+
}
|
|
113
|
+
// HMR 처리
|
|
114
|
+
watcher = null;
|
|
115
|
+
pendingFiles = [];
|
|
116
|
+
hmrStartTime = 0;
|
|
117
|
+
server = null;
|
|
118
|
+
async initForTesting() {
|
|
119
|
+
await this.init(true, false, undefined, true);
|
|
120
|
+
}
|
|
121
|
+
async init(doSilent = false, enableSync = true, apiRootPath, forTesting = false) {
|
|
122
|
+
if (this.isInitialized) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
!doSilent && console.time(chalk.cyan(`Sonamu.init${forTesting ? " for testing" : ""}`));
|
|
126
|
+
// API 루트 패스
|
|
127
|
+
this.apiRootPath = apiRootPath ?? findApiRootPath();
|
|
128
|
+
this.config = await loadConfig(this.apiRootPath);
|
|
129
|
+
const secretsPath = path.join(this.apiRootPath, "sonamu.secrets.json");
|
|
130
|
+
if (await exists(secretsPath)) {
|
|
131
|
+
this.secrets = JSON.parse((await readFile(secretsPath)).toString());
|
|
132
|
+
}
|
|
133
|
+
// DB 로드
|
|
134
|
+
this.dbConfig = DB.generateDBConfig(this.config.database);
|
|
135
|
+
!doSilent && console.log(chalk.green("DB Config Loaded!"));
|
|
136
|
+
attachOnDuplicateUpdate();
|
|
137
|
+
// 테스팅인 경우 엔티티 로드 & 싱크 없이 중단
|
|
138
|
+
if (forTesting) {
|
|
139
|
+
this.isInitialized = true;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// Entity 로드
|
|
143
|
+
const { EntityManager } = await import("../entity/entity-manager.js");
|
|
144
|
+
await EntityManager.autoload(doSilent);
|
|
145
|
+
// Syncer
|
|
146
|
+
const { Syncer } = await import("../syncer/syncer.js");
|
|
147
|
+
this.syncer = new Syncer();
|
|
148
|
+
// Autoload: Models / Types / APIs
|
|
149
|
+
await this.syncer.autoloadTypes();
|
|
150
|
+
await this.syncer.autoloadModels();
|
|
151
|
+
await this.syncer.autoloadApis();
|
|
152
|
+
await Template.autoload();
|
|
153
|
+
if (isLocal() && !isTest() && isHotReloadServer() && enableSync) {
|
|
154
|
+
await this.syncer.sync();
|
|
155
|
+
this.startWatcher();
|
|
156
|
+
this.syncer.syncUI();
|
|
157
|
+
}
|
|
158
|
+
this.isInitialized = true;
|
|
159
|
+
!doSilent && console.timeEnd(chalk.cyan("Sonamu.init"));
|
|
160
|
+
}
|
|
161
|
+
async createServer(initOptions) {
|
|
162
|
+
if (this.isInitialized === false) {
|
|
163
|
+
await this.init(initOptions?.doSilent, initOptions?.enableSync);
|
|
164
|
+
}
|
|
165
|
+
const options = this.config.server;
|
|
166
|
+
const server = fastify(options.fastify);
|
|
167
|
+
this.server = server;
|
|
168
|
+
// Storage 설정 저장
|
|
169
|
+
if (options.storage) {
|
|
170
|
+
this.storage = options.storage;
|
|
171
|
+
}
|
|
172
|
+
// 플러그인 등록
|
|
173
|
+
if (options.plugins) {
|
|
174
|
+
this.registerPlugins(server, options.plugins);
|
|
175
|
+
}
|
|
176
|
+
if (options.auth) {
|
|
177
|
+
if (!options.plugins?.session) {
|
|
178
|
+
throw new Error("Auth requires session plugin. Please add plugins.session configuration.");
|
|
179
|
+
}
|
|
180
|
+
this.registerAuth(server, options.auth);
|
|
181
|
+
}
|
|
182
|
+
// API 라우팅 설정
|
|
183
|
+
await this.withFastify(server, options.apiConfig, {
|
|
184
|
+
enableSync: initOptions?.enableSync,
|
|
185
|
+
doSilent: initOptions?.doSilent
|
|
186
|
+
});
|
|
187
|
+
// 서버 시작
|
|
188
|
+
await this.boot(server, options);
|
|
189
|
+
return server;
|
|
190
|
+
}
|
|
191
|
+
async withFastify(server, config, options) {
|
|
192
|
+
if (this.isInitialized === false) {
|
|
193
|
+
await this.init(options?.doSilent, options?.enableSync);
|
|
194
|
+
}
|
|
195
|
+
this.server = server;
|
|
196
|
+
// timezone 설정
|
|
197
|
+
const timezone = this.config.api.timezone;
|
|
198
|
+
if (timezone) {
|
|
199
|
+
const DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
|
|
200
|
+
// ISO 8601 날짜 형식 정규식 (예: 2024-01-15T09:30:00.000Z)
|
|
201
|
+
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;
|
|
202
|
+
server.setReplySerializer((payload)=>{
|
|
203
|
+
return JSON.stringify(payload, (_key, value)=>{
|
|
204
|
+
if (typeof value === "string" && ISO_DATE_REGEX.test(value)) {
|
|
205
|
+
return formatInTimeZone(new Date(value), timezone, DATE_FORMAT);
|
|
206
|
+
}
|
|
207
|
+
return value;
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
!options?.doSilent && console.log(chalk.green(`Timezone set to ${timezone}`));
|
|
211
|
+
}
|
|
212
|
+
// 전체 라우팅 리스트
|
|
213
|
+
server.get(`${this.config.api.route.prefix}/routes`, async (_request, _reply)=>{
|
|
214
|
+
return this.syncer.apis;
|
|
215
|
+
});
|
|
216
|
+
// Healthcheck API
|
|
217
|
+
server.get(`${this.config.api.route.prefix}/healthcheck`, async (_request, _reply)=>{
|
|
218
|
+
return "ok";
|
|
219
|
+
});
|
|
220
|
+
// API 라우팅 (로컬HMR 상태와 구분)
|
|
221
|
+
if (isLocal()) {
|
|
222
|
+
server.all("*", (request, reply)=>{
|
|
223
|
+
const found = this.syncer.apis.find((api)=>this.config.api.route.prefix + api.path === request.url.split("?")[0] && (api.options.httpMethod ?? "GET") === request.method.toUpperCase());
|
|
224
|
+
if (found) {
|
|
225
|
+
return this.getApiHandler(found, config)(request, reply);
|
|
226
|
+
}
|
|
227
|
+
throw new NotFoundException("존재하지 않는 API 접근입니다.");
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
this.syncer.apis.map((api)=>{
|
|
231
|
+
// model
|
|
232
|
+
if (this.syncer.models[api.modelName] === undefined) {
|
|
233
|
+
throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
|
|
234
|
+
}
|
|
235
|
+
// route
|
|
236
|
+
server.route({
|
|
237
|
+
method: api.options.httpMethod,
|
|
238
|
+
url: this.config.api.route.prefix + api.path,
|
|
239
|
+
handler: this.getApiHandler(api, config)
|
|
240
|
+
}); // END server.route
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
getApiHandler(api, config) {
|
|
245
|
+
return async (request, reply)=>{
|
|
246
|
+
(api.options.guards ?? []).every((guard)=>config.guardHandler(guard, request, api));
|
|
247
|
+
// 파라미터 정보로 zod 스키마 빌드
|
|
248
|
+
const ReqType = getZodObjectFromApi(api, this.syncer.types);
|
|
249
|
+
// request 파싱
|
|
250
|
+
const which = api.options.httpMethod === "GET" ? "query" : "body";
|
|
251
|
+
let reqBody;
|
|
252
|
+
try {
|
|
253
|
+
reqBody = fastifyCaster(ReqType).parse(request[which] ?? {});
|
|
254
|
+
} catch (e) {
|
|
255
|
+
if (e instanceof ZodError) {
|
|
256
|
+
const messages = humanizeZodError(e).map((issue)=>issue.message).join(" ");
|
|
257
|
+
throw new BadRequestException(messages, {
|
|
258
|
+
zodError: e
|
|
259
|
+
});
|
|
260
|
+
} else {
|
|
261
|
+
throw e;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Content-Type
|
|
265
|
+
reply.type(api.options.contentType ?? "application/json");
|
|
266
|
+
// 캐시
|
|
267
|
+
const { cacheKey, cacheTtl, cachedData } = await (async ()=>{
|
|
268
|
+
if (config.cache) {
|
|
269
|
+
try {
|
|
270
|
+
const cacheKeyRes = config.cache.resolveKey(api.path, reqBody);
|
|
271
|
+
if (cacheKeyRes.cache === false) {
|
|
272
|
+
return {
|
|
273
|
+
cacheKey: null,
|
|
274
|
+
cachedData: null
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const cacheKey = cacheKeyRes.key;
|
|
278
|
+
const cacheTtl = cacheKeyRes.ttl;
|
|
279
|
+
const cachedData = await config.cache.get(cacheKey);
|
|
280
|
+
return {
|
|
281
|
+
cacheKey,
|
|
282
|
+
cacheTtl,
|
|
283
|
+
cachedData
|
|
284
|
+
};
|
|
285
|
+
} catch (e) {
|
|
286
|
+
console.error(e);
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
cacheKey: null,
|
|
290
|
+
cachedData: null
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
cacheKey: null,
|
|
295
|
+
cachedData: null
|
|
296
|
+
};
|
|
297
|
+
})();
|
|
298
|
+
if (cachedData !== null) {
|
|
299
|
+
return cachedData;
|
|
300
|
+
}
|
|
301
|
+
// createSSEFactory 함수에 미리 request의 socket과 reply를 바인딩.
|
|
302
|
+
const createSSE = ((_request, _reply, _events)=>createSSEFactory(_request.socket, _reply, _events)).bind(null, request, reply);
|
|
303
|
+
const context = {
|
|
304
|
+
...await Promise.resolve(config.contextProvider({
|
|
305
|
+
request,
|
|
306
|
+
reply,
|
|
307
|
+
headers: request.headers,
|
|
308
|
+
createSSE,
|
|
309
|
+
naiteStore: new Map(),
|
|
310
|
+
// auth
|
|
311
|
+
user: request.user ?? null,
|
|
312
|
+
passport: {
|
|
313
|
+
login: request.login.bind(request),
|
|
314
|
+
logout: request.logout.bind(request)
|
|
315
|
+
}
|
|
316
|
+
}, request, reply))
|
|
317
|
+
};
|
|
318
|
+
const model = this.syncer.models[api.modelName];
|
|
319
|
+
return this.asyncLocalStorage.run({
|
|
320
|
+
context
|
|
321
|
+
}, async ()=>{
|
|
322
|
+
const result = await model[api.methodName].apply(model, api.parameters.map((param)=>{
|
|
323
|
+
// Context 인젝션
|
|
324
|
+
if (ApiParamType.isContext(param.type)) {
|
|
325
|
+
return context;
|
|
326
|
+
} else {
|
|
327
|
+
return reqBody[param.name];
|
|
328
|
+
}
|
|
329
|
+
}));
|
|
330
|
+
reply.type(api.options.contentType ?? "application/json");
|
|
331
|
+
// 캐시 키 있는 경우 갱신 후 저장
|
|
332
|
+
if (config.cache && cacheKey) {
|
|
333
|
+
await config.cache.put(cacheKey, result, cacheTtl);
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
startWatcher() {
|
|
340
|
+
const watchPath = [
|
|
341
|
+
path.join(this.apiRootPath, "src"),
|
|
342
|
+
path.join(this.apiRootPath, "sonamu.config.ts")
|
|
343
|
+
];
|
|
344
|
+
this.watcher = chokidar.watch(watchPath, {
|
|
345
|
+
ignored: (path, stats)=>!!stats?.isFile() && !path.endsWith(".ts") && !path.endsWith(".json"),
|
|
346
|
+
persistent: true,
|
|
347
|
+
ignoreInitial: true
|
|
348
|
+
});
|
|
349
|
+
this.watcher.on("all", async (event, filePath)=>{
|
|
350
|
+
const absolutePath = filePath;
|
|
351
|
+
assert(absolutePath.startsWith(this.apiRootPath), "File path is not within the API root path");
|
|
352
|
+
if (event !== "change" && event !== "add") {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
// sonamu.config.ts 변경 시 재시작
|
|
357
|
+
const isConfigTs = filePath === path.join(this.apiRootPath, "sonamu.config.ts");
|
|
358
|
+
if (isConfigTs) {
|
|
359
|
+
const relativePath = filePath.replace(this.apiRootPath, "api");
|
|
360
|
+
console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)} - Restarting...`));
|
|
361
|
+
process.kill(process.pid, "SIGUSR2");
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
await this.handleFileChange(event, absolutePath);
|
|
365
|
+
} catch (e) {
|
|
366
|
+
console.error(e);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/*
|
|
371
|
+
A function that automatically handles init and destroy when using Sonamu via scripts.
|
|
372
|
+
*/ async runScript(fn) {
|
|
373
|
+
await this.init(true, false, undefined, false);
|
|
374
|
+
try {
|
|
375
|
+
await fn();
|
|
376
|
+
} finally{
|
|
377
|
+
await this.destroy();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
registerPlugins(server, plugins) {
|
|
381
|
+
if (!plugins) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const pluginsModules = {
|
|
385
|
+
cors: "@fastify/cors",
|
|
386
|
+
formbody: "@fastify/formbody",
|
|
387
|
+
multipart: "@fastify/multipart",
|
|
388
|
+
qs: "fastify-qs",
|
|
389
|
+
sse: "fastify-sse-v2",
|
|
390
|
+
static: "@fastify/static",
|
|
391
|
+
session: "@fastify/secure-session"
|
|
392
|
+
};
|
|
393
|
+
const registerPlugin = (key, pluginName)=>{
|
|
394
|
+
const option = plugins[key];
|
|
395
|
+
if (!option) return;
|
|
396
|
+
if (option === true) {
|
|
397
|
+
server.register(import(pluginName));
|
|
398
|
+
} else {
|
|
399
|
+
server.register(import(pluginName), option);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
Object.entries(pluginsModules).forEach(([key, pluginName])=>{
|
|
403
|
+
registerPlugin(key, pluginName);
|
|
404
|
+
});
|
|
405
|
+
if (plugins.custom) {
|
|
406
|
+
plugins.custom(server);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
async registerAuth(server, options) {
|
|
410
|
+
server.register(fastifyPassport.initialize());
|
|
411
|
+
server.register(fastifyPassport.secureSession());
|
|
412
|
+
if (typeof options === "boolean") {
|
|
413
|
+
fastifyPassport.registerUserSerializer(async (user, _request)=>user);
|
|
414
|
+
fastifyPassport.registerUserDeserializer(async (serialized, _request)=>serialized);
|
|
415
|
+
} else {
|
|
416
|
+
fastifyPassport.registerUserSerializer(options.userSerializer);
|
|
417
|
+
fastifyPassport.registerUserDeserializer(options.userDeserializer);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async boot(server, options) {
|
|
421
|
+
const port = options.listen?.port ?? 3000;
|
|
422
|
+
const host = options.listen?.host ?? "localhost";
|
|
423
|
+
server.addHook("onClose", async ()=>{
|
|
424
|
+
await options.lifecycle?.onShutdown?.(server);
|
|
425
|
+
await this.destroy();
|
|
426
|
+
});
|
|
427
|
+
const shutdown = async ()=>{
|
|
428
|
+
try {
|
|
429
|
+
await server.close();
|
|
430
|
+
process.exit(0);
|
|
431
|
+
} catch (err) {
|
|
432
|
+
console.error("Error during shutdown:", err);
|
|
433
|
+
process.exit(1);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
process.on("SIGINT", shutdown);
|
|
437
|
+
process.on("SIGTERM", shutdown);
|
|
438
|
+
if (options.lifecycle?.onError) {
|
|
439
|
+
server.setErrorHandler(options.lifecycle?.onError);
|
|
440
|
+
}
|
|
441
|
+
server.listen({
|
|
442
|
+
port,
|
|
443
|
+
host
|
|
444
|
+
}).then(async ()=>{
|
|
445
|
+
await options.lifecycle?.onStart?.(server);
|
|
446
|
+
}).catch(async (err)=>{
|
|
447
|
+
console.error(chalk.red("Failed to start server:", err));
|
|
448
|
+
await shutdown();
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
async handleFileChange(event, filePath) {
|
|
452
|
+
// 첫 번째 파일이면 HMR 시작 시간 기록
|
|
453
|
+
if (this.pendingFiles.length === 0) {
|
|
454
|
+
this.hmrStartTime = Date.now();
|
|
455
|
+
}
|
|
456
|
+
this.pendingFiles.push(filePath);
|
|
457
|
+
const relativePath = path.relative(this.apiRootPath, filePath);
|
|
458
|
+
console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
|
|
459
|
+
await this.syncer.syncFromWatcher(event, filePath);
|
|
460
|
+
// 처리 완료된 파일을 대기 목록에서 제거
|
|
461
|
+
this.pendingFiles = this.pendingFiles.slice(1);
|
|
462
|
+
// 모든 파일 처리가 완료되면 최종 메시지 출력
|
|
463
|
+
if (this.pendingFiles.length === 0) {
|
|
464
|
+
await this.finishHMR();
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
async finishHMR() {
|
|
468
|
+
await this.syncer.renewChecksums();
|
|
469
|
+
const endTime = Date.now();
|
|
470
|
+
const totalTime = endTime - this.hmrStartTime;
|
|
471
|
+
const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
|
|
472
|
+
console.log(chalk.black.bgGreen(centerText(msg)));
|
|
473
|
+
}
|
|
474
|
+
async destroy() {
|
|
475
|
+
await BaseModel.destroy();
|
|
476
|
+
await this.watcher?.close();
|
|
477
|
+
this.storage?.destroy();
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
export const Sonamu = new SonamuClass();
|
|
481
|
+
|
|
482
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvc29uYW11LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFzeW5jTG9jYWxTdG9yYWdlIH0gZnJvbSBcImFzeW5jX2hvb2tzXCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgZmFzdGlmeSBmcm9tIFwiZmFzdGlmeVwiO1xuaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBleGlzdHMgfSBmcm9tIFwiLi4vdXRpbHMvZnMtdXRpbHNcIjtcbmltcG9ydCBjaG9raWRhciwgeyB0eXBlIEZTV2F0Y2hlciB9IGZyb20gXCJjaG9raWRhclwiO1xuaW1wb3J0IHsgZm9ybWF0SW5UaW1lWm9uZSB9IGZyb20gXCJkYXRlLWZucy10elwiO1xuaW1wb3J0IHR5cGUgeyBGYXN0aWZ5SW5zdGFuY2UsIEZhc3RpZnlSZXBseSwgRmFzdGlmeVJlcXVlc3QgfSBmcm9tIFwiZmFzdGlmeVwiO1xuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlciwgU2VydmVyUmVzcG9uc2UgfSBmcm9tIFwiaHR0cFwiO1xuaW1wb3J0IHsgWm9kRXJyb3IsIFpvZE9iamVjdCB9IGZyb20gXCJ6b2RcIjtcbmltcG9ydCB7IERCLCBTb25hbXVEQkNvbmZpZyB9IGZyb20gXCIuLi9kYXRhYmFzZS9kYlwiO1xuaW1wb3J0IHsgYXR0YWNoT25EdXBsaWNhdGVVcGRhdGUgfSBmcm9tIFwiLi4vZGF0YWJhc2Uva25leC1wbHVnaW5zL2tuZXgtb24tZHVwbGljYXRlLXVwZGF0ZVwiO1xuaW1wb3J0IHtcbiAgQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgTm90Rm91bmRFeGNlcHRpb24sXG59IGZyb20gXCIuLi9leGNlcHRpb25zL3NvLWV4Y2VwdGlvbnNcIjtcbmltcG9ydCB0eXBlIHsgRHJpdmVyIH0gZnJvbSBcIi4uL2ZpbGUtc3RvcmFnZS9kcml2ZXJcIjtcbmltcG9ydCB7IGNyZWF0ZVNTRUZhY3RvcnkgfSBmcm9tIFwiLi4vc3RyZWFtL3NzZVwiO1xuaW1wb3J0IHR5cGUgeyBTeW5jZXIgfSBmcm9tIFwiLi4vc3luY2VyL3N5bmNlclwiO1xuaW1wb3J0IHsgQXBpUGFyYW1UeXBlLCBTb25hbXVGYXN0aWZ5Q29uZmlnIH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc0xvY2FsLCBpc1Rlc3QgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZmluZEFwaVJvb3RQYXRoIH0gZnJvbSBcIi4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBodW1hbml6ZVpvZEVycm9yIH0gZnJvbSBcIi4uL3V0aWxzL3pvZC1lcnJvclwiO1xuaW1wb3J0IHsgZmFzdGlmeUNhc3RlciB9IGZyb20gXCIuL2Nhc3RlclwiO1xuaW1wb3J0IHsgZ2V0Wm9kT2JqZWN0RnJvbUFwaSB9IGZyb20gXCIuL2NvZGUtY29udmVydGVyc1wiO1xuaW1wb3J0IHR5cGUgeyBBdXRoQ29udGV4dCwgQ29udGV4dCwgVXBsb2FkQ29udGV4dCB9IGZyb20gXCIuL2NvbnRleHRcIjtcbmltcG9ydCB0eXBlIHsgRXh0ZW5kZWRBcGkgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgZmFzdGlmeVBhc3Nwb3J0IGZyb20gXCJAZmFzdGlmeS9wYXNzcG9ydFwiO1xuaW1wb3J0IHsgbG9hZENvbmZpZywgU29uYW11Q29uZmlnLCBTb25hbXVTZXJ2ZXJPcHRpb25zIH0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgeyBBYnNvbHV0ZVBhdGggfSBmcm9tIFwiLi4vdXRpbHMvcGF0aC11dGlsc1wiO1xuaW1wb3J0IHsgaXNIb3RSZWxvYWRTZXJ2ZXIgfSBmcm9tIFwiLi4vdXRpbHMvZXNtLXV0aWxzXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgeyBjZW50ZXJUZXh0IH0gZnJvbSBcIi4uL3V0aWxzL2NvbnNvbGUtdXRpbFwiO1xuaW1wb3J0IHsgQmFzZU1vZGVsIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2Jhc2UtbW9kZWxcIjtcblxuZXhwb3J0IHR5cGUgU29uYW11U2VjcmV0cyA9IHtcbiAgW2tleTogc3RyaW5nXTogc3RyaW5nO1xufTtcbmNsYXNzIFNvbmFtdUNsYXNzIHtcbiAgcHVibGljIGlzSW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHVibGljIGFzeW5jTG9jYWxTdG9yYWdlOiBBc3luY0xvY2FsU3RvcmFnZTx7XG4gICAgY29udGV4dDogQ29udGV4dDtcbiAgfT4gPSBuZXcgQXN5bmNMb2NhbFN0b3JhZ2UoKTtcblxuICBwdWJsaWMgdXBsb2FkU3RvcmFnZTogQXN5bmNMb2NhbFN0b3JhZ2U8e1xuICAgIHVwbG9hZENvbnRleHQ6IFVwbG9hZENvbnRleHQ7XG4gIH0+ID0gbmV3IEFzeW5jTG9jYWxTdG9yYWdlKCk7XG5cbiAgcHVibGljIGdldENvbnRleHQoKTogQ29udGV4dCB7XG4gICAgY29uc3Qgc3RvcmUgPSB0aGlzLmFzeW5jTG9jYWxTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy5jb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUuY29udGV4dDtcbiAgICB9XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09IFwidGVzdFwiKSB7XG4gICAgICAvLyDthYzsiqTtjIUg7ZmY6rK97JeQ7IScIOy7qO2FjeyKpO2KuOqwgCDso7zsnoXrkJjsp4Ag7JWK7J2AIOqyveyasCDruYgg7Luo7YWN7Iqk7Yq4IOumrO2EtFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVxdWVzdDogbnVsbCxcbiAgICAgICAgcmVwbHk6IG51bGwsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBjcmVhdGVTU0U6ICgpID0+IHt9LFxuICAgICAgICBuYWl0ZVN0b3JlOiBuZXcgTWFwPHN0cmluZywgYW55PigpLFxuICAgICAgfSBhcyB1bmtub3duIGFzIENvbnRleHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbmFtdSBjYW5ub3QgZmluZCBjb250ZXh0XCIpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRVcGxvYWRDb250ZXh0KCk6IFVwbG9hZENvbnRleHQge1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy51cGxvYWRTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKHN0b3JlPy51cGxvYWRDb250ZXh0KSB7XG4gICAgICByZXR1cm4gc3RvcmUudXBsb2FkQ29udGV4dDtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXCJTb25hbXUgY2Fubm90IGZpbmQgdXBsb2FkIGNvbnRleHQuIERpZCB5b3UgdXNlIEB1cGxvYWQgZGVjb3JhdG9yP1wiXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX2FwaVJvb3RQYXRoOiBBYnNvbHV0ZVBhdGggfCBudWxsID0gbnVsbDtcbiAgc2V0IGFwaVJvb3RQYXRoKGFwaVJvb3RQYXRoOiBBYnNvbHV0ZVBhdGgpIHtcbiAgICB0aGlzLl9hcGlSb290UGF0aCA9IGFwaVJvb3RQYXRoO1xuICB9XG4gIGdldCBhcGlSb290UGF0aCgpOiBBYnNvbHV0ZVBhdGgge1xuICAgIGlmICh0aGlzLl9hcGlSb290UGF0aCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FwaVJvb3RQYXRoITtcbiAgfVxuICBnZXQgYXBwUm9vdFBhdGgoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5hcGlSb290UGF0aC5zcGxpdChwYXRoLnNlcCkuc2xpY2UoMCwgLTEpLmpvaW4ocGF0aC5zZXApO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGJDb25maWc6IFNvbmFtdURCQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHNldCBkYkNvbmZpZyhkYkNvbmZpZzogU29uYW11REJDb25maWcpIHtcbiAgICB0aGlzLl9kYkNvbmZpZyA9IGRiQ29uZmlnO1xuICB9XG4gIGdldCBkYkNvbmZpZygpOiBTb25hbXVEQkNvbmZpZyB7XG4gICAgaWYgKHRoaXMuX2RiQ29uZmlnID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fZGJDb25maWchO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY2VyOiBTeW5jZXIgfCBudWxsID0gbnVsbDtcbiAgc2V0IHN5bmNlcihzeW5jZXI6IFN5bmNlcikge1xuICAgIHRoaXMuX3N5bmNlciA9IHN5bmNlcjtcbiAgfVxuICBnZXQgc3luY2VyKCk6IFN5bmNlciB7XG4gICAgaWYgKHRoaXMuX3N5bmNlciA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU29uYW11IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N5bmNlciE7XG4gIH1cblxuICBwcml2YXRlIF9jb25maWc6IFNvbmFtdUNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBzZXQgY29uZmlnKGNvbmZpZzogU29uYW11Q29uZmlnKSB7XG4gICAgdGhpcy5fY29uZmlnID0gY29uZmlnO1xuICB9XG4gIGdldCBjb25maWcoKTogU29uYW11Q29uZmlnIHtcbiAgICBpZiAodGhpcy5fY29uZmlnID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb25hbXUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29uZmlnO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2VjcmV0czogU29uYW11U2VjcmV0cyB8IG51bGwgPSBudWxsO1xuICBzZXQgc2VjcmV0cyhzZWNyZXRzOiBTb25hbXVTZWNyZXRzKSB7XG4gICAgdGhpcy5fc2VjcmV0cyA9IHNlY3JldHM7XG4gIH1cbiAgZ2V0IHNlY3JldHMoKTogU29uYW11U2VjcmV0cyB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9zZWNyZXRzO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3RvcmFnZTogRHJpdmVyIHwgbnVsbCA9IG51bGw7XG4gIHNldCBzdG9yYWdlKHN0b3JhZ2U6IERyaXZlcikge1xuICAgIHRoaXMuX3N0b3JhZ2UgPSBzdG9yYWdlO1xuICB9XG4gIGdldCBzdG9yYWdlKCk6IERyaXZlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9zdG9yYWdlO1xuICB9XG5cbiAgLy8gSE1SIOyymOumrFxuICBwdWJsaWMgd2F0Y2hlcjogRlNXYXRjaGVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGVuZGluZ0ZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIGhtclN0YXJ0VGltZTogbnVtYmVyID0gMDtcblxuICBwdWJsaWMgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UgfCBudWxsID0gbnVsbDtcblxuICBhc3luYyBpbml0Rm9yVGVzdGluZygpIHtcbiAgICBhd2FpdCB0aGlzLmluaXQodHJ1ZSwgZmFsc2UsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gIH1cblxuICBhc3luYyBpbml0KFxuICAgIGRvU2lsZW50OiBib29sZWFuID0gZmFsc2UsXG4gICAgZW5hYmxlU3luYzogYm9vbGVhbiA9IHRydWUsXG4gICAgYXBpUm9vdFBhdGg/OiBBYnNvbHV0ZVBhdGgsXG4gICAgZm9yVGVzdGluZzogYm9vbGVhbiA9IGZhbHNlXG4gICkge1xuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgIWRvU2lsZW50ICYmXG4gICAgICBjb25zb2xlLnRpbWUoXG4gICAgICAgIGNoYWxrLmN5YW4oYFNvbmFtdS5pbml0JHtmb3JUZXN0aW5nID8gXCIgZm9yIHRlc3RpbmdcIiA6IFwiXCJ9YClcbiAgICAgICk7XG5cbiAgICAvLyBBUEkg66Oo7Yq4IO2MqOyKpFxuICAgIHRoaXMuYXBpUm9vdFBhdGggPSBhcGlSb290UGF0aCA/PyBmaW5kQXBpUm9vdFBhdGgoKTtcbiAgICB0aGlzLmNvbmZpZyA9IGF3YWl0IGxvYWRDb25maWcodGhpcy5hcGlSb290UGF0aCk7XG4gICAgY29uc3Qgc2VjcmV0c1BhdGggPSBwYXRoLmpvaW4odGhpcy5hcGlSb290UGF0aCwgXCJzb25hbXUuc2VjcmV0cy5qc29uXCIpO1xuICAgIGlmIChhd2FpdCBleGlzdHMoc2VjcmV0c1BhdGgpKSB7XG4gICAgICB0aGlzLnNlY3JldHMgPSBKU09OLnBhcnNlKFxuICAgICAgICAoYXdhaXQgcmVhZEZpbGUoc2VjcmV0c1BhdGgpKS50b1N0cmluZygpXG4gICAgICApIGFzIFNvbmFtdVNlY3JldHM7XG4gICAgfVxuXG4gICAgLy8gREIg66Gc65OcXG4gICAgdGhpcy5kYkNvbmZpZyA9IERCLmdlbmVyYXRlREJDb25maWcodGhpcy5jb25maWcuZGF0YWJhc2UpO1xuICAgICFkb1NpbGVudCAmJiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIkRCIENvbmZpZyBMb2FkZWQhXCIpKTtcbiAgICBhdHRhY2hPbkR1cGxpY2F0ZVVwZGF0ZSgpO1xuXG4gICAgLy8g7YWM7Iqk7YyF7J24IOqyveyasCDsl5Tti7Dti7Ag66Gc65OcICYg7Iux7YGsIOyXhuydtCDspJHri6hcbiAgICBpZiAoZm9yVGVzdGluZykge1xuICAgICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBFbnRpdHkg66Gc65OcXG4gICAgY29uc3QgeyBFbnRpdHlNYW5hZ2VyIH0gPSBhd2FpdCBpbXBvcnQoXCIuLi9lbnRpdHkvZW50aXR5LW1hbmFnZXJcIik7XG4gICAgYXdhaXQgRW50aXR5TWFuYWdlci5hdXRvbG9hZChkb1NpbGVudCk7XG5cbiAgICAvLyBTeW5jZXJcbiAgICBjb25zdCB7IFN5bmNlciB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vc3luY2VyL3N5bmNlclwiKTtcbiAgICB0aGlzLnN5bmNlciA9IG5ldyBTeW5jZXIoKTtcblxuICAgIC8vIEF1dG9sb2FkOiBNb2RlbHMgLyBUeXBlcyAvIEFQSXNcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZFR5cGVzKCk7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIuYXV0b2xvYWRNb2RlbHMoKTtcbiAgICBhd2FpdCB0aGlzLnN5bmNlci5hdXRvbG9hZEFwaXMoKTtcblxuICAgIGF3YWl0IFRlbXBsYXRlLmF1dG9sb2FkKCk7XG5cbiAgICBpZiAoaXNMb2NhbCgpICYmICFpc1Rlc3QoKSAmJiBpc0hvdFJlbG9hZFNlcnZlcigpICYmIGVuYWJsZVN5bmMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3luY2VyLnN5bmMoKTtcblxuICAgICAgdGhpcy5zdGFydFdhdGNoZXIoKTtcblxuICAgICAgdGhpcy5zeW5jZXIuc3luY1VJKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAhZG9TaWxlbnQgJiYgY29uc29sZS50aW1lRW5kKGNoYWxrLmN5YW4oXCJTb25hbXUuaW5pdFwiKSk7XG4gIH1cblxuICBhc3luYyBjcmVhdGVTZXJ2ZXIoaW5pdE9wdGlvbnM/OiB7XG4gICAgZW5hYmxlU3luYz86IGJvb2xlYW47XG4gICAgZG9TaWxlbnQ/OiBib29sZWFuO1xuICB9KSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChpbml0T3B0aW9ucz8uZG9TaWxlbnQsIGluaXRPcHRpb25zPy5lbmFibGVTeW5jKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy5jb25maWcuc2VydmVyO1xuICAgIGNvbnN0IHNlcnZlciA9IGZhc3RpZnkob3B0aW9ucy5mYXN0aWZ5KTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcblxuICAgIC8vIFN0b3JhZ2Ug7ISk7KCVIOyggOyepVxuICAgIGlmIChvcHRpb25zLnN0b3JhZ2UpIHtcbiAgICAgIHRoaXMuc3RvcmFnZSA9IG9wdGlvbnMuc3RvcmFnZTtcbiAgICB9XG5cbiAgICAvLyDtlIzrn6zqt7jsnbgg65Ox66GdXG4gICAgaWYgKG9wdGlvbnMucGx1Z2lucykge1xuICAgICAgdGhpcy5yZWdpc3RlclBsdWdpbnMoc2VydmVyLCBvcHRpb25zLnBsdWdpbnMpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmF1dGgpIHtcbiAgICAgIGlmICghb3B0aW9ucy5wbHVnaW5zPy5zZXNzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBcIkF1dGggcmVxdWlyZXMgc2Vzc2lvbiBwbHVnaW4uIFBsZWFzZSBhZGQgcGx1Z2lucy5zZXNzaW9uIGNvbmZpZ3VyYXRpb24uXCJcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5yZWdpc3RlckF1dGgoc2VydmVyLCBvcHRpb25zLmF1dGgpO1xuICAgIH1cblxuICAgIC8vIEFQSSDrnbzsmrDtjIUg7ISk7KCVXG4gICAgYXdhaXQgdGhpcy53aXRoRmFzdGlmeShzZXJ2ZXIsIG9wdGlvbnMuYXBpQ29uZmlnLCB7XG4gICAgICBlbmFibGVTeW5jOiBpbml0T3B0aW9ucz8uZW5hYmxlU3luYyxcbiAgICAgIGRvU2lsZW50OiBpbml0T3B0aW9ucz8uZG9TaWxlbnQsXG4gICAgfSk7XG5cbiAgICAvLyDshJzrsoQg7Iuc7J6RXG4gICAgYXdhaXQgdGhpcy5ib290KHNlcnZlciwgb3B0aW9ucyk7XG5cbiAgICByZXR1cm4gc2VydmVyO1xuICB9XG5cbiAgYXN5bmMgd2l0aEZhc3RpZnkoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2U8U2VydmVyLCBJbmNvbWluZ01lc3NhZ2UsIFNlcnZlclJlc3BvbnNlPixcbiAgICBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGVuYWJsZVN5bmM/OiBib29sZWFuO1xuICAgICAgZG9TaWxlbnQ/OiBib29sZWFuO1xuICAgIH1cbiAgKSB7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdChvcHRpb25zPy5kb1NpbGVudCwgb3B0aW9ucz8uZW5hYmxlU3luYyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG5cbiAgICAvLyB0aW1lem9uZSDshKTsoJVcbiAgICBjb25zdCB0aW1lem9uZSA9IHRoaXMuY29uZmlnLmFwaS50aW1lem9uZTtcbiAgICBpZiAodGltZXpvbmUpIHtcbiAgICAgIGNvbnN0IERBVEVfRk9STUFUID0gXCJ5eXl5LU1NLWRkJ1QnSEg6bW06c3NYWFhcIjtcbiAgICAgIC8vIElTTyA4NjAxIOuCoOynnCDtmJXsi50g7KCV6rec7IudICjsmIg6IDIwMjQtMDEtMTVUMDk6MzA6MDAuMDAwWilcbiAgICAgIGNvbnN0IElTT19EQVRFX1JFR0VYID0gL15cXGR7NH0tXFxkezJ9LVxcZHsyfVRcXGR7Mn06XFxkezJ9OlxcZHsyfShcXC5cXGR7M30pP1okLztcblxuICAgICAgc2VydmVyLnNldFJlcGx5U2VyaWFsaXplcigocGF5bG9hZCkgPT4ge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgKF9rZXksIHZhbHVlKSA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiBJU09fREFURV9SRUdFWC50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUobmV3IERhdGUodmFsdWUpLCB0aW1lem9uZSwgREFURV9GT1JNQVQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICAhb3B0aW9ucz8uZG9TaWxlbnQgJiZcbiAgICAgICAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oYFRpbWV6b25lIHNldCB0byAke3RpbWV6b25lfWApKTtcbiAgICB9XG5cbiAgICAvLyDsoITssrQg65287Jqw7YyFIOumrOyKpO2KuFxuICAgIHNlcnZlci5nZXQoXG4gICAgICBgJHt0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4fS9yb3V0ZXNgLFxuICAgICAgYXN5bmMgKF9yZXF1ZXN0LCBfcmVwbHkpOiBQcm9taXNlPGFueT4gPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jZXIuYXBpcztcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gSGVhbHRoY2hlY2sgQVBJXG4gICAgc2VydmVyLmdldChcbiAgICAgIGAke3RoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXh9L2hlYWx0aGNoZWNrYCxcbiAgICAgIGFzeW5jIChfcmVxdWVzdCwgX3JlcGx5KTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICAgICAgcmV0dXJuIFwib2tcIjtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gQVBJIOudvOyasO2MhSAo66Gc7LusSE1SIOyDge2DnOyZgCDqtazrtoQpXG4gICAgaWYgKGlzTG9jYWwoKSkge1xuICAgICAgc2VydmVyLmFsbChcIipcIiwgKHJlcXVlc3QsIHJlcGx5KSA9PiB7XG4gICAgICAgIGNvbnN0IGZvdW5kID0gdGhpcy5zeW5jZXIuYXBpcy5maW5kKFxuICAgICAgICAgIChhcGkpID0+XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5hcGkucm91dGUucHJlZml4ICsgYXBpLnBhdGggPT09XG4gICAgICAgICAgICAgIHJlcXVlc3QudXJsLnNwbGl0KFwiP1wiKVswXSAmJlxuICAgICAgICAgICAgKGFwaS5vcHRpb25zLmh0dHBNZXRob2QgPz8gXCJHRVRcIikgPT09IHJlcXVlc3QubWV0aG9kLnRvVXBwZXJDYXNlKClcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXBpSGFuZGxlcihmb3VuZCwgY29uZmlnKShyZXF1ZXN0LCByZXBseSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXhjZXB0aW9uKFwi7KG07J6s7ZWY7KeAIOyViuuKlCBBUEkg7KCR6re87J6F64uI64ukLlwiKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN5bmNlci5hcGlzLm1hcCgoYXBpKSA9PiB7XG4gICAgICAgIC8vIG1vZGVsXG4gICAgICAgIGlmICh0aGlzLnN5bmNlci5tb2RlbHNbYXBpLm1vZGVsTmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihg7KCV7J2Y65CY7KeAIOyViuydgCDrqqjrjbjsl5Ag7KCR6re8ICR7YXBpLm1vZGVsTmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJvdXRlXG4gICAgICAgIHNlcnZlci5yb3V0ZSh7XG4gICAgICAgICAgbWV0aG9kOiBhcGkub3B0aW9ucy5odHRwTWV0aG9kISxcbiAgICAgICAgICB1cmw6IHRoaXMuY29uZmlnLmFwaS5yb3V0ZS5wcmVmaXggKyBhcGkucGF0aCxcbiAgICAgICAgICBoYW5kbGVyOiB0aGlzLmdldEFwaUhhbmRsZXIoYXBpLCBjb25maWcpLFxuICAgICAgICB9KTsgLy8gRU5EIHNlcnZlci5yb3V0ZVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0QXBpSGFuZGxlcihhcGk6IEV4dGVuZGVkQXBpLCBjb25maWc6IFNvbmFtdUZhc3RpZnlDb25maWcpIHtcbiAgICByZXR1cm4gYXN5bmMgKFxuICAgICAgcmVxdWVzdDogRmFzdGlmeVJlcXVlc3QsXG4gICAgICByZXBseTogRmFzdGlmeVJlcGx5XG4gICAgKTogUHJvbWlzZTx1bmtub3duPiA9PiB7XG4gICAgICAoYXBpLm9wdGlvbnMuZ3VhcmRzID8/IFtdKS5ldmVyeSgoZ3VhcmQpID0+XG4gICAgICAgIGNvbmZpZy5ndWFyZEhhbmRsZXIoZ3VhcmQsIHJlcXVlc3QsIGFwaSlcbiAgICAgICk7XG5cbiAgICAgIC8vIO2MjOudvOuvuO2EsCDsoJXrs7TroZwgem9kIOyKpO2CpOuniCDruYzrk5xcbiAgICAgIGNvbnN0IFJlcVR5cGUgPSBnZXRab2RPYmplY3RGcm9tQXBpKGFwaSwgdGhpcy5zeW5jZXIudHlwZXMpO1xuXG4gICAgICAvLyByZXF1ZXN0IO2MjOyLsVxuICAgICAgY29uc3Qgd2hpY2ggPSBhcGkub3B0aW9ucy5odHRwTWV0aG9kID09PSBcIkdFVFwiID8gXCJxdWVyeVwiIDogXCJib2R5XCI7XG4gICAgICBsZXQgcmVxQm9keToge1xuICAgICAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICAgICAgfTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlcUJvZHkgPSBmYXN0aWZ5Q2FzdGVyKFJlcVR5cGUpLnBhcnNlKHJlcXVlc3Rbd2hpY2hdID8/IHt9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBab2RFcnJvcikge1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gaHVtYW5pemVab2RFcnJvcihlKVxuICAgICAgICAgICAgLm1hcCgoaXNzdWUpID0+IGlzc3VlLm1lc3NhZ2UpXG4gICAgICAgICAgICAuam9pbihcIiBcIik7XG4gICAgICAgICAgdGhyb3cgbmV3IEJhZFJlcXVlc3RFeGNlcHRpb24obWVzc2FnZXMsIHtcbiAgICAgICAgICAgIHpvZEVycm9yOiBlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ29udGVudC1UeXBlXG4gICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgLy8g7LqQ7IucXG4gICAgICBjb25zdCB7IGNhY2hlS2V5LCBjYWNoZVR0bCwgY2FjaGVkRGF0YSB9ID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKGNvbmZpZy5jYWNoZSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjYWNoZUtleVJlcyA9IGNvbmZpZy5jYWNoZS5yZXNvbHZlS2V5KGFwaS5wYXRoLCByZXFCb2R5KTtcbiAgICAgICAgICAgIGlmIChjYWNoZUtleVJlcy5jYWNoZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgY2FjaGVLZXk6IG51bGwsIGNhY2hlZERhdGE6IG51bGwgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBjYWNoZUtleVJlcy5rZXk7XG4gICAgICAgICAgICBjb25zdCBjYWNoZVR0bCA9IGNhY2hlS2V5UmVzLnR0bDtcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlZERhdGEgPSBhd2FpdCBjb25maWcuY2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICAgICAgICAgIHJldHVybiB7IGNhY2hlS2V5LCBjYWNoZVR0bCwgY2FjaGVkRGF0YSB9O1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7IGNhY2hlS2V5OiBudWxsLCBjYWNoZWREYXRhOiBudWxsIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgY2FjaGVLZXk6IG51bGwsIGNhY2hlZERhdGE6IG51bGwgfTtcbiAgICAgIH0pKCk7XG4gICAgICBpZiAoY2FjaGVkRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gY2FjaGVkRGF0YTtcbiAgICAgIH1cblxuICAgICAgLy8gY3JlYXRlU1NFRmFjdG9yeSDtlajsiJjsl5Ag66+466asIHJlcXVlc3TsnZggc29ja2V06rO8IHJlcGx566W8IOuwlOyduOuUqS5cbiAgICAgIGNvbnN0IGNyZWF0ZVNTRSA9ICg8VCBleHRlbmRzIFpvZE9iamVjdD4oXG4gICAgICAgIF9yZXF1ZXN0OiBGYXN0aWZ5UmVxdWVzdCxcbiAgICAgICAgX3JlcGx5OiBGYXN0aWZ5UmVwbHksXG4gICAgICAgIF9ldmVudHM6IFRcbiAgICAgICkgPT4gY3JlYXRlU1NFRmFjdG9yeShfcmVxdWVzdC5zb2NrZXQsIF9yZXBseSwgX2V2ZW50cykpLmJpbmQoXG4gICAgICAgIG51bGwsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHJlcGx5XG4gICAgICApO1xuXG4gICAgICBjb25zdCBjb250ZXh0OiBDb250ZXh0ID0ge1xuICAgICAgICAuLi4oYXdhaXQgUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIGNvbmZpZy5jb250ZXh0UHJvdmlkZXIoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgICAgIHJlcGx5LFxuICAgICAgICAgICAgICBoZWFkZXJzOiByZXF1ZXN0LmhlYWRlcnMsXG4gICAgICAgICAgICAgIGNyZWF0ZVNTRSxcbiAgICAgICAgICAgICAgbmFpdGVTdG9yZTogbmV3IE1hcDxzdHJpbmcsIGFueT4oKSxcbiAgICAgICAgICAgICAgLy8gYXV0aFxuICAgICAgICAgICAgICB1c2VyOiByZXF1ZXN0LnVzZXIgPz8gbnVsbCxcbiAgICAgICAgICAgICAgcGFzc3BvcnQ6IHtcbiAgICAgICAgICAgICAgICBsb2dpbjogcmVxdWVzdC5sb2dpbi5iaW5kKFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdFxuICAgICAgICAgICAgICAgICkgYXMgQXV0aENvbnRleHRbXCJwYXNzcG9ydFwiXVtcImxvZ2luXCJdLFxuICAgICAgICAgICAgICAgIGxvZ291dDogcmVxdWVzdC5sb2dvdXQuYmluZChcbiAgICAgICAgICAgICAgICAgIHJlcXVlc3RcbiAgICAgICAgICAgICAgICApIGFzIEF1dGhDb250ZXh0W1wicGFzc3BvcnRcIl1bXCJsb2dvdXRcIl0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICAgIHJlcGx5XG4gICAgICAgICAgKVxuICAgICAgICApKSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG1vZGVsID0gdGhpcy5zeW5jZXIubW9kZWxzW2FwaS5tb2RlbE5hbWVdO1xuICAgICAgcmV0dXJuIHRoaXMuYXN5bmNMb2NhbFN0b3JhZ2UucnVuKHsgY29udGV4dCB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IChtb2RlbCBhcyBhbnkpW2FwaS5tZXRob2ROYW1lXS5hcHBseShcbiAgICAgICAgICBtb2RlbCxcbiAgICAgICAgICBhcGkucGFyYW1ldGVycy5tYXAoKHBhcmFtKSA9PiB7XG4gICAgICAgICAgICAvLyBDb250ZXh0IOyduOygneyFmFxuICAgICAgICAgICAgaWYgKEFwaVBhcmFtVHlwZS5pc0NvbnRleHQocGFyYW0udHlwZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVxQm9keVtwYXJhbS5uYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgICByZXBseS50eXBlKGFwaS5vcHRpb25zLmNvbnRlbnRUeXBlID8/IFwiYXBwbGljYXRpb24vanNvblwiKTtcblxuICAgICAgICAvLyDsupDsi5wg7YKkIOyeiOuKlCDqsr3smrAg6rCx7IugIO2bhCDsoIDsnqVcbiAgICAgICAgaWYgKGNvbmZpZy5jYWNoZSAmJiBjYWNoZUtleSkge1xuICAgICAgICAgIGF3YWl0IGNvbmZpZy5jYWNoZS5wdXQoY2FjaGVLZXksIHJlc3VsdCwgY2FjaGVUdGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG5cbiAgc3RhcnRXYXRjaGVyKCk6IHZvaWQge1xuICAgIGNvbnN0IHdhdGNoUGF0aCA9IFtcbiAgICAgIHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcInNyY1wiKSxcbiAgICAgIHBhdGguam9pbih0aGlzLmFwaVJvb3RQYXRoLCBcInNvbmFtdS5jb25maWcudHNcIiksXG4gICAgXTtcblxuICAgIHRoaXMud2F0Y2hlciA9IGNob2tpZGFyLndhdGNoKHdhdGNoUGF0aCwge1xuICAgICAgaWdub3JlZDogKHBhdGgsIHN0YXRzKSA9PlxuICAgICAgICAhIXN0YXRzPy5pc0ZpbGUoKSAmJiAhcGF0aC5lbmRzV2l0aChcIi50c1wiKSAmJiAhcGF0aC5lbmRzV2l0aChcIi5qc29uXCIpLFxuICAgICAgcGVyc2lzdGVudDogdHJ1ZSxcbiAgICAgIGlnbm9yZUluaXRpYWw6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLndhdGNoZXIub24oXCJhbGxcIiwgYXN5bmMgKGV2ZW50OiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IGZpbGVQYXRoIGFzIEFic29sdXRlUGF0aDtcbiAgICAgIGFzc2VydChcbiAgICAgICAgYWJzb2x1dGVQYXRoLnN0YXJ0c1dpdGgodGhpcy5hcGlSb290UGF0aCksXG4gICAgICAgIFwiRmlsZSBwYXRoIGlzIG5vdCB3aXRoaW4gdGhlIEFQSSByb290IHBhdGhcIlxuICAgICAgKTtcblxuICAgICAgaWYgKGV2ZW50ICE9PSBcImNoYW5nZVwiICYmIGV2ZW50ICE9PSBcImFkZFwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gc29uYW11LmNvbmZpZy50cyDrs4Dqsr0g7IucIOyerOyLnOyekVxuICAgICAgICBjb25zdCBpc0NvbmZpZ1RzID1cbiAgICAgICAgICBmaWxlUGF0aCA9PT0gcGF0aC5qb2luKHRoaXMuYXBpUm9vdFBhdGgsIFwic29uYW11LmNvbmZpZy50c1wiKTtcblxuICAgICAgICBpZiAoaXNDb25maWdUcykge1xuICAgICAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGZpbGVQYXRoLnJlcGxhY2UodGhpcy5hcGlSb290UGF0aCwgXCJhcGlcIik7XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICBjaGFsay5ib2xkKFxuICAgICAgICAgICAgICBgRGV0ZWN0ZWQoJHtldmVudH0pOiAke2NoYWxrLmJsdWUocmVsYXRpdmVQYXRoKX0gLSBSZXN0YXJ0aW5nLi4uYFxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgICAgcHJvY2Vzcy5raWxsKHByb2Nlc3MucGlkLCBcIlNJR1VTUjJcIik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlKGV2ZW50LCBhYnNvbHV0ZVBhdGgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLypcbiAgICAgQSBmdW5jdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBpbml0IGFuZCBkZXN0cm95IHdoZW4gdXNpbmcgU29uYW11IHZpYSBzY3JpcHRzLiAgICBcbiAgKi9cbiAgYXN5bmMgcnVuU2NyaXB0KGZuOiAoKSA9PiBQcm9taXNlPHZvaWQ+KSB7XG4gICAgYXdhaXQgdGhpcy5pbml0KHRydWUsIGZhbHNlLCB1bmRlZmluZWQsIGZhbHNlKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZm4oKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlclBsdWdpbnMoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsXG4gICAgcGx1Z2luczogU29uYW11U2VydmVyT3B0aW9uc1tcInBsdWdpbnNcIl1cbiAgKSB7XG4gICAgaWYgKCFwbHVnaW5zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcGx1Z2luc01vZHVsZXMgPSB7XG4gICAgICBjb3JzOiBcIkBmYXN0aWZ5L2NvcnNcIixcbiAgICAgIGZvcm1ib2R5OiBcIkBmYXN0aWZ5L2Zvcm1ib2R5XCIsXG4gICAgICBtdWx0aXBhcnQ6IFwiQGZhc3RpZnkvbXVsdGlwYXJ0XCIsXG4gICAgICBxczogXCJmYXN0aWZ5LXFzXCIsXG4gICAgICBzc2U6IFwiZmFzdGlmeS1zc2UtdjJcIixcbiAgICAgIHN0YXRpYzogXCJAZmFzdGlmeS9zdGF0aWNcIixcbiAgICAgIHNlc3Npb246IFwiQGZhc3RpZnkvc2VjdXJlLXNlc3Npb25cIixcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgY29uc3QgcmVnaXN0ZXJQbHVnaW4gPSA8SyBleHRlbmRzIGtleW9mIE5vbk51bGxhYmxlPHR5cGVvZiBwbHVnaW5zPj4oXG4gICAgICBrZXk6IEssXG4gICAgICBwbHVnaW5OYW1lOiBzdHJpbmdcbiAgICApID0+IHtcbiAgICAgIGNvbnN0IG9wdGlvbiA9IHBsdWdpbnNba2V5XTtcbiAgICAgIGlmICghb3B0aW9uKSByZXR1cm47XG5cbiAgICAgIGlmIChvcHRpb24gPT09IHRydWUpIHtcbiAgICAgICAgc2VydmVyLnJlZ2lzdGVyKGltcG9ydChwbHVnaW5OYW1lKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXJ2ZXIucmVnaXN0ZXIoaW1wb3J0KHBsdWdpbk5hbWUpLCBvcHRpb24pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBPYmplY3QuZW50cmllcyhwbHVnaW5zTW9kdWxlcykuZm9yRWFjaCgoW2tleSwgcGx1Z2luTmFtZV0pID0+IHtcbiAgICAgIHJlZ2lzdGVyUGx1Z2luKGtleSBhcyBrZXlvZiB0eXBlb2YgcGx1Z2lucywgcGx1Z2luTmFtZSk7XG4gICAgfSk7XG5cbiAgICBpZiAocGx1Z2lucy5jdXN0b20pIHtcbiAgICAgIHBsdWdpbnMuY3VzdG9tKHNlcnZlcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlckF1dGgoXG4gICAgc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsXG4gICAgb3B0aW9uczogTm9uTnVsbGFibGU8U29uYW11U2VydmVyT3B0aW9uc1tcImF1dGhcIl0+XG4gICkge1xuICAgIHNlcnZlci5yZWdpc3RlcihmYXN0aWZ5UGFzc3BvcnQuaW5pdGlhbGl6ZSgpKTtcbiAgICBzZXJ2ZXIucmVnaXN0ZXIoZmFzdGlmeVBhc3Nwb3J0LnNlY3VyZVNlc3Npb24oKSk7XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICBmYXN0aWZ5UGFzc3BvcnQucmVnaXN0ZXJVc2VyU2VyaWFsaXplcihhc3luYyAodXNlciwgX3JlcXVlc3QpID0+IHVzZXIpO1xuICAgICAgZmFzdGlmeVBhc3Nwb3J0LnJlZ2lzdGVyVXNlckRlc2VyaWFsaXplcihcbiAgICAgICAgYXN5bmMgKHNlcmlhbGl6ZWQsIF9yZXF1ZXN0KSA9PiBzZXJpYWxpemVkXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBmYXN0aWZ5UGFzc3BvcnQucmVnaXN0ZXJVc2VyU2VyaWFsaXplcihvcHRpb25zLnVzZXJTZXJpYWxpemVyKTtcbiAgICAgIGZhc3RpZnlQYXNzcG9ydC5yZWdpc3RlclVzZXJEZXNlcmlhbGl6ZXIob3B0aW9ucy51c2VyRGVzZXJpYWxpemVyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3Qoc2VydmVyOiBGYXN0aWZ5SW5zdGFuY2UsIG9wdGlvbnM6IFNvbmFtdVNlcnZlck9wdGlvbnMpIHtcbiAgICBjb25zdCBwb3J0ID0gb3B0aW9ucy5saXN0ZW4/LnBvcnQgPz8gMzAwMDtcbiAgICBjb25zdCBob3N0ID0gb3B0aW9ucy5saXN0ZW4/Lmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcblxuICAgIHNlcnZlci5hZGRIb29rKFwib25DbG9zZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TaHV0ZG93bj8uKHNlcnZlcik7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHNodXRkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgZHVyaW5nIHNodXRkb3duOlwiLCBlcnIpO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHByb2Nlc3Mub24oXCJTSUdJTlRcIiwgc2h1dGRvd24pO1xuICAgIHByb2Nlc3Mub24oXCJTSUdURVJNXCIsIHNodXRkb3duKTtcblxuICAgIGlmIChvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcikge1xuICAgICAgc2VydmVyLnNldEVycm9ySGFuZGxlcihvcHRpb25zLmxpZmVjeWNsZT8ub25FcnJvcik7XG4gICAgfVxuXG4gICAgc2VydmVyXG4gICAgICAubGlzdGVuKHsgcG9ydCwgaG9zdCB9KVxuICAgICAgLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBvcHRpb25zLmxpZmVjeWNsZT8ub25TdGFydD8uKHNlcnZlcik7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGFzeW5jIChlcnIpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoXCJGYWlsZWQgdG8gc3RhcnQgc2VydmVyOlwiLCBlcnIpKTtcbiAgICAgICAgYXdhaXQgc2h1dGRvd24oKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVGaWxlQ2hhbmdlKFxuICAgIGV2ZW50OiBzdHJpbmcsXG4gICAgZmlsZVBhdGg6IEFic29sdXRlUGF0aFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyDssqsg67KI7Ke4IO2MjOydvOydtOuptCBITVIg7Iuc7J6RIOyLnOqwhCDquLDroZ1cbiAgICBpZiAodGhpcy5wZW5kaW5nRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmhtclN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgfVxuICAgIHRoaXMucGVuZGluZ0ZpbGVzLnB1c2goZmlsZVBhdGgpO1xuXG4gICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZSh0aGlzLmFwaVJvb3RQYXRoLCBmaWxlUGF0aCk7XG4gICAgY29uc29sZS5sb2coY2hhbGsuYm9sZChgRGV0ZWN0ZWQoJHtldmVudH0pOiAke2NoYWxrLmJsdWUocmVsYXRpdmVQYXRoKX1gKSk7XG5cbiAgICBhd2FpdCB0aGlzLnN5bmNlci5zeW5jRnJvbVdhdGNoZXIoZXZlbnQsIGZpbGVQYXRoKTtcblxuICAgIC8vIOyymOumrCDsmYTro4zrkJwg7YyM7J287J2EIOuMgOq4sCDrqqnroZ3sl5DshJwg7KCc6rGwXG4gICAgdGhpcy5wZW5kaW5nRmlsZXMgPSB0aGlzLnBlbmRpbmdGaWxlcy5zbGljZSgxKTtcblxuICAgIC8vIOuqqOuToCDtjIzsnbwg7LKY66as6rCAIOyZhOujjOuQmOuptCDstZzsooUg66mU7Iuc7KeAIOy2nOugpVxuICAgIGlmICh0aGlzLnBlbmRpbmdGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGF3YWl0IHRoaXMuZmluaXNoSE1SKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5pc2hITVIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zeW5jZXIucmVuZXdDaGVja3N1bXMoKTtcblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHRvdGFsVGltZSA9IGVuZFRpbWUgLSB0aGlzLmhtclN0YXJ0VGltZTtcbiAgICBjb25zdCBtc2cgPSBgSE1SIERvbmUhICR7Y2hhbGsuYm9sZC53aGl0ZShgJHt0b3RhbFRpbWV9bXNgKX1gO1xuXG4gICAgY29uc29sZS5sb2coY2hhbGsuYmxhY2suYmdHcmVlbihjZW50ZXJUZXh0KG1zZykpKTtcbiAgfVxuXG4gIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgQmFzZU1vZGVsLmRlc3Ryb3koKTtcbiAgICBhd2FpdCB0aGlzLndhdGNoZXI/LmNsb3NlKCk7XG4gICAgdGhpcy5zdG9yYWdlPy5kZXN0cm95KCk7XG4gIH1cbn1cbmV4cG9ydCBjb25zdCBTb25hbXUgPSBuZXcgU29uYW11Q2xhc3MoKTtcbiJdLCJuYW1lcyI6WyJBc3luY0xvY2FsU3RvcmFnZSIsImNoYWxrIiwiZmFzdGlmeSIsInJlYWRGaWxlIiwicGF0aCIsImV4aXN0cyIsImNob2tpZGFyIiwiZm9ybWF0SW5UaW1lWm9uZSIsIlpvZEVycm9yIiwiREIiLCJhdHRhY2hPbkR1cGxpY2F0ZVVwZGF0ZSIsIkJhZFJlcXVlc3RFeGNlcHRpb24iLCJOb3RGb3VuZEV4Y2VwdGlvbiIsImNyZWF0ZVNTRUZhY3RvcnkiLCJBcGlQYXJhbVR5cGUiLCJpc0xvY2FsIiwiaXNUZXN0IiwiZmluZEFwaVJvb3RQYXRoIiwiaHVtYW5pemVab2RFcnJvciIsImZhc3RpZnlDYXN0ZXIiLCJnZXRab2RPYmplY3RGcm9tQXBpIiwiZmFzdGlmeVBhc3Nwb3J0IiwibG9hZENvbmZpZyIsImlzSG90UmVsb2FkU2VydmVyIiwiVGVtcGxhdGUiLCJhc3NlcnQiLCJjZW50ZXJUZXh0IiwiQmFzZU1vZGVsIiwiU29uYW11Q2xhc3MiLCJpc0luaXRpYWxpemVkIiwiYXN5bmNMb2NhbFN0b3JhZ2UiLCJ1cGxvYWRTdG9yYWdlIiwiZ2V0Q29udGV4dCIsInN0b3JlIiwiZ2V0U3RvcmUiLCJjb250ZXh0IiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicmVxdWVzdCIsInJlcGx5IiwiaGVhZGVycyIsImNyZWF0ZVNTRSIsIm5haXRlU3RvcmUiLCJNYXAiLCJFcnJvciIsImdldFVwbG9hZENvbnRleHQiLCJ1cGxvYWRDb250ZXh0IiwiX2FwaVJvb3RQYXRoIiwiYXBpUm9vdFBhdGgiLCJhcHBSb290UGF0aCIsInNwbGl0Iiwic2VwIiwic2xpY2UiLCJqb2luIiwiX2RiQ29uZmlnIiwiZGJDb25maWciLCJfc3luY2VyIiwic3luY2VyIiwiX2NvbmZpZyIsImNvbmZpZyIsIl9zZWNyZXRzIiwic2VjcmV0cyIsIl9zdG9yYWdlIiwic3RvcmFnZSIsIndhdGNoZXIiLCJwZW5kaW5nRmlsZXMiLCJobXJTdGFydFRpbWUiLCJzZXJ2ZXIiLCJpbml0Rm9yVGVzdGluZyIsImluaXQiLCJ1bmRlZmluZWQiLCJkb1NpbGVudCIsImVuYWJsZVN5bmMiLCJmb3JUZXN0aW5nIiwiY29uc29sZSIsInRpbWUiLCJjeWFuIiwic2VjcmV0c1BhdGgiLCJKU09OIiwicGFyc2UiLCJ0b1N0cmluZyIsImdlbmVyYXRlREJDb25maWciLCJkYXRhYmFzZSIsImxvZyIsImdyZWVuIiwiRW50aXR5TWFuYWdlciIsImF1dG9sb2FkIiwiU3luY2VyIiwiYXV0b2xvYWRUeXBlcyIsImF1dG9sb2FkTW9kZWxzIiwiYXV0b2xvYWRBcGlzIiwic3luYyIsInN0YXJ0V2F0Y2hlciIsInN5bmNVSSIsInRpbWVFbmQiLCJjcmVhdGVTZXJ2ZXIiLCJpbml0T3B0aW9ucyIsIm9wdGlvbnMiLCJwbHVnaW5zIiwicmVnaXN0ZXJQbHVnaW5zIiwiYXV0aCIsInNlc3Npb24iLCJyZWdpc3RlckF1dGgiLCJ3aXRoRmFzdGlmeSIsImFwaUNvbmZpZyIsImJvb3QiLCJ0aW1lem9uZSIsImFwaSIsIkRBVEVfRk9STUFUIiwiSVNPX0RBVEVfUkVHRVgiLCJzZXRSZXBseVNlcmlhbGl6ZXIiLCJwYXlsb2FkIiwic3RyaW5naWZ5IiwiX2tleSIsInZhbHVlIiwidGVzdCIsIkRhdGUiLCJnZXQiLCJyb3V0ZSIsInByZWZpeCIsIl9yZXF1ZXN0IiwiX3JlcGx5IiwiYXBpcyIsImFsbCIsImZvdW5kIiwiZmluZCIsInVybCIsImh0dHBNZXRob2QiLCJtZXRob2QiLCJ0b1VwcGVyQ2FzZSIsImdldEFwaUhhbmRsZXIiLCJtYXAiLCJtb2RlbHMiLCJtb2RlbE5hbWUiLCJoYW5kbGVyIiwiZ3VhcmRzIiwiZXZlcnkiLCJndWFyZCIsImd1YXJkSGFuZGxlciIsIlJlcVR5cGUiLCJ0eXBlcyIsIndoaWNoIiwicmVxQm9keSIsImUiLCJtZXNzYWdlcyIsImlzc3VlIiwibWVzc2FnZSIsInpvZEVycm9yIiwidHlwZSIsImNvbnRlbnRUeXBlIiwiY2FjaGVLZXkiLCJjYWNoZVR0bCIsImNhY2hlZERhdGEiLCJjYWNoZSIsImNhY2hlS2V5UmVzIiwicmVzb2x2ZUtleSIsImtleSIsInR0bCIsImVycm9yIiwiX2V2ZW50cyIsInNvY2tldCIsImJpbmQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImNvbnRleHRQcm92aWRlciIsInVzZXIiLCJwYXNzcG9ydCIsImxvZ2luIiwibG9nb3V0IiwibW9kZWwiLCJydW4iLCJyZXN1bHQiLCJtZXRob2ROYW1lIiwiYXBwbHkiLCJwYXJhbWV0ZXJzIiwicGFyYW0iLCJpc0NvbnRleHQiLCJuYW1lIiwicHV0Iiwid2F0Y2hQYXRoIiwid2F0Y2giLCJpZ25vcmVkIiwic3RhdHMiLCJpc0ZpbGUiLCJlbmRzV2l0aCIsInBlcnNpc3RlbnQiLCJpZ25vcmVJbml0aWFsIiwib24iLCJldmVudCIsImZpbGVQYXRoIiwiYWJzb2x1dGVQYXRoIiwic3RhcnRzV2l0aCIsImlzQ29uZmlnVHMiLCJyZWxhdGl2ZVBhdGgiLCJyZXBsYWNlIiwiYm9sZCIsImJsdWUiLCJraWxsIiwicGlkIiwiaGFuZGxlRmlsZUNoYW5nZSIsInJ1blNjcmlwdCIsImZuIiwiZGVzdHJveSIsInBsdWdpbnNNb2R1bGVzIiwiY29ycyIsImZvcm1ib2R5IiwibXVsdGlwYXJ0IiwicXMiLCJzc2UiLCJzdGF0aWMiLCJyZWdpc3RlclBsdWdpbiIsInBsdWdpbk5hbWUiLCJvcHRpb24iLCJyZWdpc3RlciIsIk9iamVjdCIsImVudHJpZXMiLCJmb3JFYWNoIiwiY3VzdG9tIiwiaW5pdGlhbGl6ZSIsInNlY3VyZVNlc3Npb24iLCJyZWdpc3RlclVzZXJTZXJpYWxpemVyIiwicmVnaXN0ZXJVc2VyRGVzZXJpYWxpemVyIiwic2VyaWFsaXplZCIsInVzZXJTZXJpYWxpemVyIiwidXNlckRlc2VyaWFsaXplciIsInBvcnQiLCJsaXN0ZW4iLCJob3N0IiwiYWRkSG9vayIsImxpZmVjeWNsZSIsIm9uU2h1dGRvd24iLCJzaHV0ZG93biIsImNsb3NlIiwiZXhpdCIsImVyciIsIm9uRXJyb3IiLCJzZXRFcnJvckhhbmRsZXIiLCJ0aGVuIiwib25TdGFydCIsImNhdGNoIiwicmVkIiwibGVuZ3RoIiwibm93IiwicHVzaCIsInJlbGF0aXZlIiwic3luY0Zyb21XYXRjaGVyIiwiZmluaXNoSE1SIiwicmVuZXdDaGVja3N1bXMiLCJlbmRUaW1lIiwidG90YWxUaW1lIiwibXNnIiwid2hpdGUiLCJibGFjayIsImJnR3JlZW4iLCJTb25hbXUiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGlCQUFpQixRQUFRLGNBQWM7QUFDaEQsT0FBT0MsV0FBVyxRQUFRO0FBQzFCLE9BQU9DLGFBQWEsVUFBVTtBQUM5QixTQUFTQyxRQUFRLFFBQVEsbUJBQWM7QUFDdkMsT0FBT0MsVUFBVSxPQUFPO0FBQ3hCLFNBQVNDLE1BQU0sUUFBUSx1QkFBb0I7QUFDM0MsT0FBT0MsY0FBa0MsV0FBVztBQUNwRCxTQUFTQyxnQkFBZ0IsUUFBUSxjQUFjO0FBRy9DLFNBQVNDLFFBQVEsUUFBbUIsTUFBTTtBQUMxQyxTQUFTQyxFQUFFLFFBQXdCLG9CQUFpQjtBQUNwRCxTQUFTQyx1QkFBdUIsUUFBUSx1REFBb0Q7QUFDNUYsU0FDRUMsbUJBQW1CLEVBQ25CQyxpQkFBaUIsUUFDWixpQ0FBOEI7QUFFckMsU0FBU0MsZ0JBQWdCLFFBQVEsbUJBQWdCO0FBRWpELFNBQVNDLFlBQVksUUFBNkIsb0JBQWlCO0FBQ25FLFNBQVNDLE9BQU8sRUFBRUMsTUFBTSxRQUFRLHlCQUFzQjtBQUN0RCxTQUFTQyxlQUFlLFFBQVEsb0JBQWlCO0FBQ2pELFNBQVNDLGdCQUFnQixRQUFRLHdCQUFxQjtBQUN0RCxTQUFTQyxhQUFhLFFBQVEsY0FBVztBQUN6QyxTQUFTQyxtQkFBbUIsUUFBUSx1QkFBb0I7QUFHeEQsT0FBT0MscUJBQXFCLG9CQUFvQjtBQUNoRCxT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
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
export declare const BUILD_DIR = "dist";
|
|
5
5
|
/**
|
|
6
6
|
* SWC 빌드 명령어
|
|
7
|
+
* .swcrc 설정 사용
|
|
7
8
|
*/
|
|
8
|
-
export declare const SWC_BUILD_COMMAND = "swc src -d dist --strip-leading-paths
|
|
9
|
+
export declare const SWC_BUILD_COMMAND = "swc src -d dist --strip-leading-paths";
|
|
9
10
|
/**
|
|
10
11
|
* TSC 타입 체크 명령어
|
|
11
12
|
*/
|