sonamu 0.5.6 → 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 +1 -0
- 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 +5 -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.d.ts +22 -10
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +105 -73
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +539 -2
- package/dist/database/puri.types.d.ts +33 -42
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +3 -2
- package/dist/database/transaction-context.d.ts +3 -3
- package/dist/database/transaction-context.d.ts.map +1 -1
- 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 -9
- 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 +15 -5
- package/src/api/sonamu.ts +102 -87
- 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 +53 -60
- package/src/database/puri-wrapper.ts +104 -26
- package/src/database/puri.ts +477 -580
- package/src/database/puri.types.ts +111 -201
- package/src/database/transaction-context.ts +4 -4
- 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 +29 -12
- 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 +39 -62
- 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/src/api/sonamu.ts
CHANGED
|
@@ -4,8 +4,7 @@ import fastify from "fastify";
|
|
|
4
4
|
import { readFile } from "fs/promises";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { exists } from "../utils/fs-utils";
|
|
7
|
-
|
|
8
|
-
import type { FSWatcher } from "chokidar";
|
|
7
|
+
import chokidar, { type FSWatcher } from "chokidar";
|
|
9
8
|
import { formatInTimeZone } from "date-fns-tz";
|
|
10
9
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
|
11
10
|
import type { IncomingMessage, Server, ServerResponse } from "http";
|
|
@@ -19,11 +18,7 @@ import {
|
|
|
19
18
|
import type { Driver } from "../file-storage/driver";
|
|
20
19
|
import { createSSEFactory } from "../stream/sse";
|
|
21
20
|
import type { Syncer } from "../syncer/syncer";
|
|
22
|
-
import {
|
|
23
|
-
ApiParamType,
|
|
24
|
-
SonamuFastifyConfig,
|
|
25
|
-
SonamuServerOptions,
|
|
26
|
-
} from "../types/types";
|
|
21
|
+
import { ApiParamType, SonamuFastifyConfig } from "../types/types";
|
|
27
22
|
import { isLocal, isTest } from "../utils/controller";
|
|
28
23
|
import { findApiRootPath } from "../utils/utils";
|
|
29
24
|
import { humanizeZodError } from "../utils/zod-error";
|
|
@@ -32,23 +27,14 @@ import { getZodObjectFromApi } from "./code-converters";
|
|
|
32
27
|
import type { AuthContext, Context, UploadContext } from "./context";
|
|
33
28
|
import type { ExtendedApi } from "./decorators";
|
|
34
29
|
import fastifyPassport from "@fastify/passport";
|
|
30
|
+
import { loadConfig, SonamuConfig, SonamuServerOptions } from "./config";
|
|
31
|
+
import { AbsolutePath } from "../utils/path-utils";
|
|
32
|
+
import { isHotReloadServer } from "../utils/esm-utils";
|
|
33
|
+
import { Template } from "../template";
|
|
34
|
+
import assert from "assert";
|
|
35
|
+
import { centerText } from "../utils/console-util";
|
|
36
|
+
import { BaseModel } from "../database/base-model";
|
|
35
37
|
|
|
36
|
-
export type SonamuConfig = {
|
|
37
|
-
projectName?: string;
|
|
38
|
-
api: {
|
|
39
|
-
dir: string;
|
|
40
|
-
};
|
|
41
|
-
sync: {
|
|
42
|
-
targets: string[];
|
|
43
|
-
};
|
|
44
|
-
route: {
|
|
45
|
-
prefix: string;
|
|
46
|
-
};
|
|
47
|
-
timezone?: string;
|
|
48
|
-
ui?: {
|
|
49
|
-
port: number;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
38
|
export type SonamuSecrets = {
|
|
53
39
|
[key: string]: string;
|
|
54
40
|
};
|
|
@@ -67,7 +53,19 @@ class SonamuClass {
|
|
|
67
53
|
if (store?.context) {
|
|
68
54
|
return store.context;
|
|
69
55
|
}
|
|
70
|
-
|
|
56
|
+
|
|
57
|
+
if (process.env.NODE_ENV === "test") {
|
|
58
|
+
// 테스팅 환경에서 컨텍스트가 주입되지 않은 경우 빈 컨텍스트 리턴
|
|
59
|
+
return {
|
|
60
|
+
request: null,
|
|
61
|
+
reply: null,
|
|
62
|
+
headers: {},
|
|
63
|
+
createSSE: () => {},
|
|
64
|
+
naiteStore: new Map<string, any>(),
|
|
65
|
+
} as unknown as Context;
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error("Sonamu cannot find context");
|
|
68
|
+
}
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
public getUploadContext(): UploadContext {
|
|
@@ -80,11 +78,11 @@ class SonamuClass {
|
|
|
80
78
|
);
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
private _apiRootPath:
|
|
84
|
-
set apiRootPath(apiRootPath:
|
|
81
|
+
private _apiRootPath: AbsolutePath | null = null;
|
|
82
|
+
set apiRootPath(apiRootPath: AbsolutePath) {
|
|
85
83
|
this._apiRootPath = apiRootPath;
|
|
86
84
|
}
|
|
87
|
-
get apiRootPath():
|
|
85
|
+
get apiRootPath(): AbsolutePath {
|
|
88
86
|
if (this._apiRootPath === null) {
|
|
89
87
|
throw new Error("Sonamu has not been initialized");
|
|
90
88
|
}
|
|
@@ -157,7 +155,7 @@ class SonamuClass {
|
|
|
157
155
|
async init(
|
|
158
156
|
doSilent: boolean = false,
|
|
159
157
|
enableSync: boolean = true,
|
|
160
|
-
apiRootPath?:
|
|
158
|
+
apiRootPath?: AbsolutePath,
|
|
161
159
|
forTesting: boolean = false
|
|
162
160
|
) {
|
|
163
161
|
if (this.isInitialized) {
|
|
@@ -170,14 +168,8 @@ class SonamuClass {
|
|
|
170
168
|
|
|
171
169
|
// API 루트 패스
|
|
172
170
|
this.apiRootPath = apiRootPath ?? findApiRootPath();
|
|
173
|
-
|
|
171
|
+
this.config = await loadConfig(this.apiRootPath);
|
|
174
172
|
const secretsPath = path.join(this.apiRootPath, "sonamu.secrets.json");
|
|
175
|
-
if (!(await exists(configPath))) {
|
|
176
|
-
throw new Error(`Cannot find sonamu.config.json in ${configPath}`);
|
|
177
|
-
}
|
|
178
|
-
this.config = JSON.parse(
|
|
179
|
-
(await readFile(configPath)).toString()
|
|
180
|
-
) as SonamuConfig;
|
|
181
173
|
if (await exists(secretsPath)) {
|
|
182
174
|
this.secrets = JSON.parse(
|
|
183
175
|
(await readFile(secretsPath)).toString()
|
|
@@ -185,7 +177,7 @@ class SonamuClass {
|
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
// DB 로드
|
|
188
|
-
this.dbConfig =
|
|
180
|
+
this.dbConfig = DB.generateDBConfig(this.config.database);
|
|
189
181
|
!doSilent && console.log(chalk.green("DB Config Loaded!"));
|
|
190
182
|
attachOnDuplicateUpdate();
|
|
191
183
|
|
|
@@ -204,14 +196,15 @@ class SonamuClass {
|
|
|
204
196
|
this.syncer = new Syncer();
|
|
205
197
|
|
|
206
198
|
// Autoload: Models / Types / APIs
|
|
207
|
-
await this.syncer.autoloadModels();
|
|
208
199
|
await this.syncer.autoloadTypes();
|
|
200
|
+
await this.syncer.autoloadModels();
|
|
209
201
|
await this.syncer.autoloadApis();
|
|
210
202
|
|
|
211
|
-
|
|
203
|
+
await Template.autoload();
|
|
204
|
+
|
|
205
|
+
if (isLocal() && !isTest() && isHotReloadServer() && enableSync) {
|
|
212
206
|
await this.syncer.sync();
|
|
213
207
|
|
|
214
|
-
// FIXME: hmr 설정된 경우만 워처 시작
|
|
215
208
|
this.startWatcher();
|
|
216
209
|
|
|
217
210
|
this.syncer.syncUI();
|
|
@@ -221,13 +214,15 @@ class SonamuClass {
|
|
|
221
214
|
!doSilent && console.timeEnd(chalk.cyan("Sonamu.init"));
|
|
222
215
|
}
|
|
223
216
|
|
|
224
|
-
async createServer(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
217
|
+
async createServer(initOptions?: {
|
|
218
|
+
enableSync?: boolean;
|
|
219
|
+
doSilent?: boolean;
|
|
220
|
+
}) {
|
|
221
|
+
if (this.isInitialized === false) {
|
|
222
|
+
await this.init(initOptions?.doSilent, initOptions?.enableSync);
|
|
229
223
|
}
|
|
230
|
-
|
|
224
|
+
|
|
225
|
+
const options = this.config.server;
|
|
231
226
|
const server = fastify(options.fastify);
|
|
232
227
|
this.server = server;
|
|
233
228
|
|
|
@@ -278,7 +273,7 @@ class SonamuClass {
|
|
|
278
273
|
this.server = server;
|
|
279
274
|
|
|
280
275
|
// timezone 설정
|
|
281
|
-
const timezone = this.config.timezone;
|
|
276
|
+
const timezone = this.config.api.timezone;
|
|
282
277
|
if (timezone) {
|
|
283
278
|
const DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
|
|
284
279
|
// ISO 8601 날짜 형식 정규식 (예: 2024-01-15T09:30:00.000Z)
|
|
@@ -298,7 +293,7 @@ class SonamuClass {
|
|
|
298
293
|
|
|
299
294
|
// 전체 라우팅 리스트
|
|
300
295
|
server.get(
|
|
301
|
-
`${this.config.route.prefix}/routes`,
|
|
296
|
+
`${this.config.api.route.prefix}/routes`,
|
|
302
297
|
async (_request, _reply): Promise<any> => {
|
|
303
298
|
return this.syncer.apis;
|
|
304
299
|
}
|
|
@@ -306,7 +301,7 @@ class SonamuClass {
|
|
|
306
301
|
|
|
307
302
|
// Healthcheck API
|
|
308
303
|
server.get(
|
|
309
|
-
`${this.config.route.prefix}/healthcheck`,
|
|
304
|
+
`${this.config.api.route.prefix}/healthcheck`,
|
|
310
305
|
async (_request, _reply): Promise<string> => {
|
|
311
306
|
return "ok";
|
|
312
307
|
}
|
|
@@ -317,7 +312,8 @@ class SonamuClass {
|
|
|
317
312
|
server.all("*", (request, reply) => {
|
|
318
313
|
const found = this.syncer.apis.find(
|
|
319
314
|
(api) =>
|
|
320
|
-
this.config.route.prefix + api.path ===
|
|
315
|
+
this.config.api.route.prefix + api.path ===
|
|
316
|
+
request.url.split("?")[0] &&
|
|
321
317
|
(api.options.httpMethod ?? "GET") === request.method.toUpperCase()
|
|
322
318
|
);
|
|
323
319
|
if (found) {
|
|
@@ -335,7 +331,7 @@ class SonamuClass {
|
|
|
335
331
|
// route
|
|
336
332
|
server.route({
|
|
337
333
|
method: api.options.httpMethod!,
|
|
338
|
-
url: this.config.route.prefix + api.path,
|
|
334
|
+
url: this.config.api.route.prefix + api.path,
|
|
339
335
|
handler: this.getApiHandler(api, config),
|
|
340
336
|
}); // END server.route
|
|
341
337
|
});
|
|
@@ -413,27 +409,29 @@ class SonamuClass {
|
|
|
413
409
|
);
|
|
414
410
|
|
|
415
411
|
const context: Context = {
|
|
416
|
-
...
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
request
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
request
|
|
431
|
-
|
|
412
|
+
...(await Promise.resolve(
|
|
413
|
+
config.contextProvider(
|
|
414
|
+
{
|
|
415
|
+
request,
|
|
416
|
+
reply,
|
|
417
|
+
headers: request.headers,
|
|
418
|
+
createSSE,
|
|
419
|
+
naiteStore: new Map<string, any>(),
|
|
420
|
+
// auth
|
|
421
|
+
user: request.user ?? null,
|
|
422
|
+
passport: {
|
|
423
|
+
login: request.login.bind(
|
|
424
|
+
request
|
|
425
|
+
) as AuthContext["passport"]["login"],
|
|
426
|
+
logout: request.logout.bind(
|
|
427
|
+
request
|
|
428
|
+
) as AuthContext["passport"]["logout"],
|
|
429
|
+
},
|
|
432
430
|
},
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
),
|
|
431
|
+
request,
|
|
432
|
+
reply
|
|
433
|
+
)
|
|
434
|
+
)),
|
|
437
435
|
};
|
|
438
436
|
|
|
439
437
|
const model = this.syncer.models[api.modelName];
|
|
@@ -461,24 +459,46 @@ class SonamuClass {
|
|
|
461
459
|
}
|
|
462
460
|
|
|
463
461
|
startWatcher(): void {
|
|
464
|
-
const watchPath =
|
|
465
|
-
|
|
462
|
+
const watchPath = [
|
|
463
|
+
path.join(this.apiRootPath, "src"),
|
|
464
|
+
path.join(this.apiRootPath, "sonamu.config.ts"),
|
|
465
|
+
];
|
|
466
|
+
|
|
466
467
|
this.watcher = chokidar.watch(watchPath, {
|
|
467
468
|
ignored: (path, stats) =>
|
|
468
|
-
|
|
469
|
-
!path.endsWith(".ts") &&
|
|
470
|
-
!path.endsWith(".json")) ||
|
|
471
|
-
path.endsWith("src/index.ts"),
|
|
469
|
+
!!stats?.isFile() && !path.endsWith(".ts") && !path.endsWith(".json"),
|
|
472
470
|
persistent: true,
|
|
473
471
|
ignoreInitial: true,
|
|
474
472
|
});
|
|
473
|
+
|
|
475
474
|
this.watcher.on("all", async (event: string, filePath: string) => {
|
|
475
|
+
const absolutePath = filePath as AbsolutePath;
|
|
476
|
+
assert(
|
|
477
|
+
absolutePath.startsWith(this.apiRootPath),
|
|
478
|
+
"File path is not within the API root path"
|
|
479
|
+
);
|
|
480
|
+
|
|
476
481
|
if (event !== "change" && event !== "add") {
|
|
477
482
|
return;
|
|
478
483
|
}
|
|
479
484
|
|
|
480
485
|
try {
|
|
481
|
-
|
|
486
|
+
// sonamu.config.ts 변경 시 재시작
|
|
487
|
+
const isConfigTs =
|
|
488
|
+
filePath === path.join(this.apiRootPath, "sonamu.config.ts");
|
|
489
|
+
|
|
490
|
+
if (isConfigTs) {
|
|
491
|
+
const relativePath = filePath.replace(this.apiRootPath, "api");
|
|
492
|
+
console.log(
|
|
493
|
+
chalk.bold(
|
|
494
|
+
`Detected(${event}): ${chalk.blue(relativePath)} - Restarting...`
|
|
495
|
+
)
|
|
496
|
+
);
|
|
497
|
+
process.kill(process.pid, "SIGUSR2");
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
await this.handleFileChange(event, absolutePath);
|
|
482
502
|
} catch (e) {
|
|
483
503
|
console.error(e);
|
|
484
504
|
}
|
|
@@ -595,19 +615,18 @@ class SonamuClass {
|
|
|
595
615
|
|
|
596
616
|
private async handleFileChange(
|
|
597
617
|
event: string,
|
|
598
|
-
filePath:
|
|
618
|
+
filePath: AbsolutePath
|
|
599
619
|
): Promise<void> {
|
|
600
620
|
// 첫 번째 파일이면 HMR 시작 시간 기록
|
|
601
621
|
if (this.pendingFiles.length === 0) {
|
|
602
622
|
this.hmrStartTime = Date.now();
|
|
603
623
|
}
|
|
604
|
-
|
|
605
624
|
this.pendingFiles.push(filePath);
|
|
606
625
|
|
|
607
|
-
const relativePath =
|
|
626
|
+
const relativePath = path.relative(this.apiRootPath, filePath);
|
|
608
627
|
console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
|
|
609
628
|
|
|
610
|
-
await this.syncer.syncFromWatcher(
|
|
629
|
+
await this.syncer.syncFromWatcher(event, filePath);
|
|
611
630
|
|
|
612
631
|
// 처리 완료된 파일을 대기 목록에서 제거
|
|
613
632
|
this.pendingFiles = this.pendingFiles.slice(1);
|
|
@@ -619,20 +638,16 @@ class SonamuClass {
|
|
|
619
638
|
}
|
|
620
639
|
|
|
621
640
|
private async finishHMR(): Promise<void> {
|
|
622
|
-
await this.syncer.
|
|
641
|
+
await this.syncer.renewChecksums();
|
|
623
642
|
|
|
624
643
|
const endTime = Date.now();
|
|
625
644
|
const totalTime = endTime - this.hmrStartTime;
|
|
626
645
|
const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
|
|
627
|
-
const margin = Math.max(0, (process.stdout.columns - msg.length) / 2);
|
|
628
646
|
|
|
629
|
-
console.log(
|
|
630
|
-
chalk.black.bgGreen(" ".repeat(margin) + msg + " ".repeat(margin))
|
|
631
|
-
);
|
|
647
|
+
console.log(chalk.black.bgGreen(centerText(msg)));
|
|
632
648
|
}
|
|
633
649
|
|
|
634
650
|
async destroy(): Promise<void> {
|
|
635
|
-
const { BaseModel } = require("../database/base-model");
|
|
636
651
|
await BaseModel.destroy();
|
|
637
652
|
await this.watcher?.close();
|
|
638
653
|
this.storage?.destroy();
|
package/src/bin/build-config.ts
CHANGED
|
@@ -5,8 +5,9 @@ export const BUILD_DIR = "dist";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* SWC 빌드 명령어
|
|
8
|
+
* .swcrc 설정 사용
|
|
8
9
|
*/
|
|
9
|
-
export const SWC_BUILD_COMMAND = `swc src -d ${BUILD_DIR} --strip-leading-paths
|
|
10
|
+
export const SWC_BUILD_COMMAND = `swc src -d ${BUILD_DIR} --strip-leading-paths`;
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* TSC 타입 체크 명령어
|
package/src/bin/cli-wrapper.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
TSC_TYPE_CHECK_COMMAND,
|
|
11
11
|
} from "./build-config";
|
|
12
12
|
|
|
13
|
-
const scriptPath = resolve(
|
|
13
|
+
const scriptPath = resolve(import.meta.dirname, "cli.js");
|
|
14
14
|
const args = process.argv.slice(2);
|
|
15
15
|
|
|
16
16
|
// build 명령어는 dist 없이도 실행 가능하도록 cli.ts 외부에서 처리(Sonamu.init에서 dist 필요)
|
|
@@ -56,7 +56,7 @@ if (args[0] === "build") {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (args[0] === "dev:serve") {
|
|
59
|
-
build();
|
|
59
|
+
// build();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (!existsSync(scriptPath)) {
|
|
@@ -66,7 +66,14 @@ if (!existsSync(scriptPath)) {
|
|
|
66
66
|
|
|
67
67
|
const result = spawnSync(
|
|
68
68
|
process.execPath,
|
|
69
|
-
[
|
|
69
|
+
[
|
|
70
|
+
"--import",
|
|
71
|
+
"@sonamu-kit/loader", // Sonamu UI도 syncer를 다루므로, ts 로드 능력이 필요합니다.
|
|
72
|
+
"--enable-source-maps",
|
|
73
|
+
"--no-warnings",
|
|
74
|
+
scriptPath,
|
|
75
|
+
...args
|
|
76
|
+
],
|
|
70
77
|
{
|
|
71
78
|
stdio: "inherit",
|
|
72
79
|
}
|
package/src/bin/cli.ts
CHANGED
|
@@ -3,25 +3,24 @@ import dotenv from "dotenv";
|
|
|
3
3
|
dotenv.config();
|
|
4
4
|
|
|
5
5
|
import path from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
6
7
|
import { tsicli } from "tsicli";
|
|
7
|
-
import { execSync } from "child_process";
|
|
8
|
-
import { mkdir, readdir,
|
|
8
|
+
import { execSync, spawn } from "child_process";
|
|
9
|
+
import { mkdir, readdir, writeFile } from "fs/promises";
|
|
9
10
|
import { exists } from "../utils/fs-utils";
|
|
10
11
|
import process from "process";
|
|
11
12
|
import { Sonamu } from "../api";
|
|
12
13
|
import knex, { Knex } from "knex";
|
|
13
|
-
import { findApiRootPath } from "../utils/utils";
|
|
14
14
|
import { EntityManager } from "../entity/entity-manager";
|
|
15
15
|
import { Migrator } from "../migration/migrator";
|
|
16
16
|
import { FixtureManager } from "../testing/fixture-manager";
|
|
17
|
-
|
|
18
|
-
import { NodemonSettings } from "nodemon";
|
|
17
|
+
import { findApiRootPath } from "../utils/utils";
|
|
19
18
|
|
|
20
19
|
let migrator: Migrator;
|
|
21
20
|
|
|
22
21
|
async function bootstrap() {
|
|
23
|
-
// dev
|
|
24
|
-
if (process.argv[2] !== "dev
|
|
22
|
+
// dev 명령어가 아닌 경우에만 Sonamu 초기화
|
|
23
|
+
if (process.argv[2] !== "dev") {
|
|
25
24
|
await Sonamu.init(false, false);
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -56,8 +55,8 @@ async function bootstrap() {
|
|
|
56
55
|
["scaffold", "view_list", "#entityId"],
|
|
57
56
|
["scaffold", "view_form", "#entityId"],
|
|
58
57
|
["ui"],
|
|
59
|
-
["dev
|
|
60
|
-
["
|
|
58
|
+
["dev"],
|
|
59
|
+
["start"],
|
|
61
60
|
],
|
|
62
61
|
runners: {
|
|
63
62
|
migrate_run,
|
|
@@ -76,8 +75,8 @@ async function bootstrap() {
|
|
|
76
75
|
ui,
|
|
77
76
|
// scaffold_view_list,
|
|
78
77
|
// scaffold_view_form,
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
dev,
|
|
79
|
+
start,
|
|
81
80
|
},
|
|
82
81
|
});
|
|
83
82
|
}
|
|
@@ -88,45 +87,57 @@ bootstrap().finally(async () => {
|
|
|
88
87
|
await FixtureManager.destroy();
|
|
89
88
|
});
|
|
90
89
|
|
|
91
|
-
async function
|
|
92
|
-
const
|
|
90
|
+
async function dev() {
|
|
91
|
+
const apiRoot = findApiRootPath();
|
|
92
|
+
const entryPoint = 'src/index.ts';
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
const projectNodemonPath = path.join(findApiRootPath(), "nodemon.json");
|
|
96
|
-
const hasProjectNodemon = await exists(projectNodemonPath);
|
|
94
|
+
console.log(chalk.yellow.bold('🚀 Starting Sonamu dev server...\n'));
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
const serverProcess = spawn(
|
|
97
|
+
"hot-runner",
|
|
98
|
+
[
|
|
99
|
+
"--clear-screen=false",
|
|
100
|
+
"--node-args=--import=@sonamu-kit/loader",
|
|
101
|
+
"--node-args=--import=sonamu/hot-hook-register",
|
|
102
|
+
"--node-args=--enable-source-maps",
|
|
103
|
+
entryPoint,
|
|
104
|
+
],
|
|
105
|
+
{
|
|
106
|
+
cwd: apiRoot,
|
|
107
|
+
stdio: "inherit",
|
|
108
|
+
env: {
|
|
109
|
+
...process.env,
|
|
110
|
+
NODE_ENV: "development",
|
|
111
|
+
HOT: "yes",
|
|
112
|
+
API_ROOT_PATH: apiRoot,
|
|
113
|
+
},
|
|
100
114
|
}
|
|
115
|
+
);
|
|
101
116
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// SWC_BUILD_COMMAND,
|
|
107
|
-
"node --no-warnings -r source-map-support/register -r dotenv/config dist/index.js",
|
|
108
|
-
].join(" && "),
|
|
109
|
-
} as NodemonSettings;
|
|
110
|
-
})();
|
|
111
|
-
nodemon.default(nodemonConfig);
|
|
112
|
-
|
|
113
|
-
// 프로세스 종료 처리
|
|
114
|
-
const cleanup = async () => {
|
|
115
|
-
await Sonamu.server?.close();
|
|
117
|
+
// 종료 처리
|
|
118
|
+
const cleanup = () => {
|
|
119
|
+
console.log(chalk.yellow('\n\n👋 Shutting down...'));
|
|
120
|
+
serverProcess.kill('SIGTERM');
|
|
116
121
|
process.exit(0);
|
|
117
122
|
};
|
|
118
123
|
|
|
119
|
-
process.on(
|
|
120
|
-
process.on(
|
|
121
|
-
|
|
124
|
+
process.on('SIGINT', cleanup);
|
|
125
|
+
process.on('SIGTERM', cleanup);
|
|
126
|
+
|
|
127
|
+
serverProcess.on('exit', (code) => {
|
|
128
|
+
if (code !== 0) {
|
|
129
|
+
console.error(chalk.red(`❌ Server exited with code ${code}`));
|
|
130
|
+
process.exit(code || 1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
122
133
|
}
|
|
123
134
|
|
|
124
|
-
async function
|
|
125
|
-
const
|
|
135
|
+
async function start() {
|
|
136
|
+
const entryPoint = 'dist/index.js';
|
|
126
137
|
|
|
127
|
-
if (!(await exists(
|
|
138
|
+
if (!(await exists(entryPoint))) {
|
|
128
139
|
console.log(
|
|
129
|
-
chalk.red(
|
|
140
|
+
chalk.red(`${entryPoint} not found. Please build your project first.`)
|
|
130
141
|
);
|
|
131
142
|
console.log(chalk.blue("Run: yarn sonamu build"));
|
|
132
143
|
return;
|
|
@@ -135,7 +146,7 @@ async function serve() {
|
|
|
135
146
|
const { spawn } = await import("child_process");
|
|
136
147
|
const serverProcess = spawn(
|
|
137
148
|
"node",
|
|
138
|
-
["-
|
|
149
|
+
["--enable-source-maps", "-r", "dotenv/config", entryPoint],
|
|
139
150
|
{
|
|
140
151
|
cwd: Sonamu.apiRootPath,
|
|
141
152
|
stdio: "inherit",
|
|
@@ -162,14 +173,12 @@ async function setupFixtureManager() {
|
|
|
162
173
|
async function migrate_run() {
|
|
163
174
|
await setupMigrator();
|
|
164
175
|
|
|
165
|
-
await migrator.cleanUpDist();
|
|
166
176
|
await migrator.run();
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
async function migrate_check() {
|
|
170
180
|
await setupMigrator();
|
|
171
181
|
|
|
172
|
-
await migrator.cleanUpDist();
|
|
173
182
|
await migrator.check();
|
|
174
183
|
}
|
|
175
184
|
|
|
@@ -347,7 +356,7 @@ async function stub_practice(name: string) {
|
|
|
347
356
|
|
|
348
357
|
execSync(`code ${dstPath}`);
|
|
349
358
|
|
|
350
|
-
const runCode = `yarn node -r dotenv/config -
|
|
359
|
+
const runCode = `yarn node -r dotenv/config --enable-source-maps dist/practices/${fileName.replace(
|
|
351
360
|
".ts",
|
|
352
361
|
".js"
|
|
353
362
|
)}`;
|
|
@@ -373,23 +382,66 @@ async function scaffold_model_test(entityId: string) {
|
|
|
373
382
|
|
|
374
383
|
async function ui() {
|
|
375
384
|
try {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
385
|
+
// @sonamu-kit/ui의 run-ui.ts 스크립트 경로 찾기
|
|
386
|
+
const uiModulePath = await import.meta.resolve("@sonamu-kit/ui");
|
|
387
|
+
const uiNodePath = path.join(
|
|
388
|
+
path.dirname(fileURLToPath(uiModulePath)),
|
|
389
|
+
"run-ui.js"
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
if (!(await exists(uiNodePath))) {
|
|
393
|
+
console.log(
|
|
394
|
+
chalk.red(
|
|
395
|
+
`UI runner script not found at ${uiNodePath}. Please rebuild @sonamu-kit/ui.`
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// UI를 별도 프로세스로 실행 (hot-hook 활성화)
|
|
402
|
+
const uiProcess = spawn(
|
|
403
|
+
process.execPath,
|
|
404
|
+
[
|
|
405
|
+
"--import", "@sonamu-kit/loader",
|
|
406
|
+
"--import", "sonamu/hot-hook-register",
|
|
407
|
+
"--enable-source-maps",
|
|
408
|
+
"--no-warnings",
|
|
409
|
+
uiNodePath,
|
|
410
|
+
],
|
|
411
|
+
{
|
|
412
|
+
stdio: "inherit",
|
|
413
|
+
env: {
|
|
414
|
+
...process.env,
|
|
415
|
+
HOT: "yes",
|
|
416
|
+
PROJECT_NAME:
|
|
417
|
+
Sonamu.config.projectName ?? path.basename(Sonamu.apiRootPath),
|
|
418
|
+
API_ROOT_PATH: Sonamu.apiRootPath,
|
|
419
|
+
UI_PORT: (Sonamu.config.ui?.port ?? 57000).toString(),
|
|
420
|
+
},
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
// 종료 처리
|
|
425
|
+
const cleanup = () => {
|
|
426
|
+
console.log(chalk.yellow("\n\n👋 Shutting down UI server..."));
|
|
427
|
+
uiProcess.kill("SIGTERM");
|
|
428
|
+
process.exit(0);
|
|
380
429
|
};
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
430
|
+
|
|
431
|
+
process.on("SIGINT", cleanup);
|
|
432
|
+
process.on("SIGTERM", cleanup);
|
|
433
|
+
|
|
434
|
+
uiProcess.on("exit", (code) => {
|
|
435
|
+
if (code !== 0) {
|
|
436
|
+
console.error(chalk.red(`❌ UI server exited with code ${code}`));
|
|
437
|
+
process.exit(code || 1);
|
|
438
|
+
}
|
|
389
439
|
});
|
|
390
440
|
} catch (e: unknown) {
|
|
391
441
|
if (e instanceof Error && e.message.includes("isn't declared")) {
|
|
392
|
-
console.log(
|
|
442
|
+
console.log(
|
|
443
|
+
`You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`
|
|
444
|
+
);
|
|
393
445
|
return;
|
|
394
446
|
}
|
|
395
447
|
throw e;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hot-hook 초기화하는 모듈입니다.
|
|
3
|
+
*
|
|
4
|
+
* 이 파일은 --import 플래그로 프로세스 시작 시 로드되어야 합니다.
|
|
5
|
+
*
|
|
6
|
+
* 환경변수:
|
|
7
|
+
* - API_ROOT_PATH: 사용자 프로젝트의 API 루트 경로
|
|
8
|
+
* - HOT: 'yes'일 때만 hot-hook 활성화
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
if (process.env.HOT === "yes" && process.env.API_ROOT_PATH) {
|
|
12
|
+
const { hot } = await import("@sonamu-kit/hot-hook");
|
|
13
|
+
|
|
14
|
+
await hot.init({
|
|
15
|
+
rootDirectory: process.env.API_ROOT_PATH, // 이 친구가 프로젝트 API 경로로 잘 설정되어야 아래 바운더리가 작동합니다.
|
|
16
|
+
boundaries: [`./src/**/*.ts`], // 프로젝트의 이 친구들이 바운더리가 됩니다.
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
console.log("🔥 Hot-hook initialized");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
2
|
import { Knex } from "knex";
|
|
3
|
-
import { chunk, groupBy, isObject, omit, set, uniq } from "lodash";
|
|
3
|
+
import { chunk, groupBy, isObject, omit, set, uniq } from "lodash-es";
|
|
4
4
|
import { DBPreset, DB } from "./db";
|
|
5
5
|
import { isCustomJoinClause, type SubsetQuery } from "../types/types";
|
|
6
6
|
import type { BaseListParams } from "../utils/model";
|