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/database/puri.ts
CHANGED
|
@@ -1,137 +1,140 @@
|
|
|
1
1
|
import type { Knex } from "knex";
|
|
2
2
|
import type {
|
|
3
3
|
AvailableColumns,
|
|
4
|
+
SelectObject,
|
|
5
|
+
ParseSelectObject,
|
|
6
|
+
WhereCondition,
|
|
4
7
|
ComparisonOperator,
|
|
5
|
-
EmptyRecord,
|
|
6
|
-
Expand,
|
|
7
8
|
ExtractColumnType,
|
|
9
|
+
SqlExpression,
|
|
10
|
+
Expand,
|
|
8
11
|
FulltextColumns,
|
|
9
|
-
InsertData,
|
|
10
|
-
MergeJoined,
|
|
11
|
-
ParseSelectObject,
|
|
12
12
|
ResultAvailableColumns,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
WhereCondition,
|
|
13
|
+
InsertData,
|
|
14
|
+
SingleTableValue,
|
|
16
15
|
} from "./puri.types";
|
|
17
16
|
import chalk from "chalk";
|
|
17
|
+
import assert from "assert";
|
|
18
|
+
import { Naite } from "../naite/naite";
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
export class Puri<
|
|
21
|
-
TSchema,
|
|
22
|
-
TTable extends keyof TSchema | string,
|
|
23
|
-
TOriginal = TTable extends keyof TSchema ? TSchema[TTable] : unknown,
|
|
24
|
-
TResult = TTable extends keyof TSchema ? TSchema[TTable] : unknown,
|
|
25
|
-
TJoined = EmptyRecord,
|
|
26
|
-
> {
|
|
20
|
+
export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
|
|
27
21
|
private knexQuery: Knex.QueryBuilder;
|
|
28
22
|
|
|
29
23
|
// 생성자 시그니처들
|
|
24
|
+
constructor(knex: Knex, tableName: string);
|
|
30
25
|
constructor(
|
|
31
26
|
knex: Knex,
|
|
32
|
-
|
|
33
|
-
);
|
|
34
|
-
constructor(
|
|
35
|
-
knex: Knex,
|
|
36
|
-
subquery: Puri<TSchema, any, any, TOriginal, any>,
|
|
37
|
-
alias: TTable extends string ? TTable : never
|
|
27
|
+
tableSpec: Record<string, string | Puri<TSchema, any, any>>
|
|
38
28
|
);
|
|
39
29
|
constructor(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
alias?: TTable extends string ? TTable : never
|
|
30
|
+
public knex: Knex,
|
|
31
|
+
tableNameOrSpec: any
|
|
43
32
|
) {
|
|
44
|
-
if (typeof
|
|
45
|
-
//
|
|
46
|
-
this.knexQuery = knex(
|
|
33
|
+
if (typeof tableNameOrSpec === "string") {
|
|
34
|
+
// Case: new Puri(knex, "users")
|
|
35
|
+
this.knexQuery = this.knex(tableNameOrSpec).from(tableNameOrSpec);
|
|
36
|
+
} else if (typeof tableNameOrSpec === "object") {
|
|
37
|
+
const entries = Object.entries(tableNameOrSpec);
|
|
38
|
+
if (entries.length !== 1) {
|
|
39
|
+
throw new Error("Table spec must have exactly one entry");
|
|
40
|
+
}
|
|
41
|
+
assert(entries[0]);
|
|
42
|
+
const [alias, spec] = entries[0];
|
|
43
|
+
if (typeof spec === "string") {
|
|
44
|
+
this.knexQuery = this.knex(spec).from({ [alias]: spec });
|
|
45
|
+
} else if (spec instanceof Puri) {
|
|
46
|
+
const subqueryBuilder = spec.raw();
|
|
47
|
+
this.knexQuery = this.knex.from(subqueryBuilder.as(alias));
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error("Invalid table specification");
|
|
50
|
+
}
|
|
47
51
|
} else {
|
|
48
|
-
|
|
49
|
-
this.knexQuery = knex.from(tableNameOrSubquery.raw().as(alias));
|
|
52
|
+
throw new Error("Invalid table specification");
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
// Static SQL helper functions
|
|
54
|
-
static count(column: string = "*"):
|
|
56
|
+
// Static SQL helper functions for SELECT
|
|
57
|
+
static count(column: string = "*"): SqlExpression<"number"> {
|
|
55
58
|
return {
|
|
56
|
-
_type: "
|
|
59
|
+
_type: "sql_expression",
|
|
57
60
|
_return: "number",
|
|
58
61
|
_sql: `COUNT(${column})`,
|
|
59
62
|
};
|
|
60
63
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
static sum(column: string): SqlExpression<"number"> {
|
|
65
|
+
return {
|
|
66
|
+
_type: "sql_expression",
|
|
67
|
+
_return: "number",
|
|
68
|
+
_sql: `SUM(${column})`,
|
|
69
|
+
};
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
static avg(column: string): SqlExpression<"number"> {
|
|
72
|
+
return {
|
|
73
|
+
_type: "sql_expression",
|
|
74
|
+
_return: "number",
|
|
75
|
+
_sql: `AVG(${column})`,
|
|
76
|
+
};
|
|
68
77
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
static max(column: string): SqlExpression<"number"> {
|
|
79
|
+
return {
|
|
80
|
+
_type: "sql_expression",
|
|
81
|
+
_return: "number",
|
|
82
|
+
_sql: `MAX(${column})`,
|
|
83
|
+
};
|
|
72
84
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
static min(column: string): SqlExpression<"number"> {
|
|
86
|
+
return {
|
|
87
|
+
_type: "sql_expression",
|
|
88
|
+
_return: "number",
|
|
89
|
+
_sql: `MIN(${column})`,
|
|
90
|
+
};
|
|
76
91
|
}
|
|
77
|
-
|
|
78
|
-
static concat(...args: string[]): SqlFunction<"string"> {
|
|
92
|
+
static concat(...args: string[]): SqlExpression<"string"> {
|
|
79
93
|
return {
|
|
80
|
-
_type: "
|
|
94
|
+
_type: "sql_expression",
|
|
81
95
|
_return: "string",
|
|
82
96
|
_sql: `CONCAT(${args.join(", ")})`,
|
|
83
97
|
};
|
|
84
98
|
}
|
|
85
|
-
|
|
86
|
-
static upper(column: string): SqlFunction<"string"> {
|
|
99
|
+
static upper(column: string): SqlExpression<"string"> {
|
|
87
100
|
return {
|
|
88
|
-
_type: "
|
|
101
|
+
_type: "sql_expression",
|
|
89
102
|
_return: "string",
|
|
90
103
|
_sql: `UPPER(${column})`,
|
|
91
104
|
};
|
|
92
105
|
}
|
|
93
|
-
|
|
94
|
-
static lower(column: string): SqlFunction<"string"> {
|
|
106
|
+
static lower(column: string): SqlExpression<"string"> {
|
|
95
107
|
return {
|
|
96
|
-
_type: "
|
|
108
|
+
_type: "sql_expression",
|
|
97
109
|
_return: "string",
|
|
98
110
|
_sql: `LOWER(${column})`,
|
|
99
111
|
};
|
|
100
112
|
}
|
|
101
113
|
|
|
102
|
-
// Raw functions
|
|
103
|
-
static rawString(sql: string):
|
|
104
|
-
return { _type: "
|
|
114
|
+
// Raw functions for SELECT
|
|
115
|
+
static rawString(sql: string): SqlExpression<"string"> {
|
|
116
|
+
return { _type: "sql_expression", _return: "string", _sql: sql };
|
|
105
117
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return { _type: "sql_function", _return: "number", _sql: sql };
|
|
118
|
+
static rawNumber(sql: string): SqlExpression<"number"> {
|
|
119
|
+
return { _type: "sql_expression", _return: "number", _sql: sql };
|
|
109
120
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return { _type: "sql_function", _return: "boolean", _sql: sql };
|
|
121
|
+
static rawBoolean(sql: string): SqlExpression<"boolean"> {
|
|
122
|
+
return { _type: "sql_expression", _return: "boolean", _sql: sql };
|
|
113
123
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return { _type: "sql_function", _return: "date", _sql: sql };
|
|
124
|
+
static rawDate(sql: string): SqlExpression<"date"> {
|
|
125
|
+
return { _type: "sql_expression", _return: "date", _sql: sql };
|
|
117
126
|
}
|
|
118
127
|
|
|
119
|
-
//
|
|
120
|
-
select<TSelect extends SelectObject<
|
|
128
|
+
// SELECT (overwrite)
|
|
129
|
+
select<TSelect extends SelectObject<TTables>>(
|
|
121
130
|
selectObj: TSelect
|
|
122
|
-
): Puri<
|
|
123
|
-
TSchema,
|
|
124
|
-
TTable,
|
|
125
|
-
TOriginal,
|
|
126
|
-
ParseSelectObject<TSchema, TTable, TSelect, TOriginal, TJoined>,
|
|
127
|
-
TJoined
|
|
128
|
-
> {
|
|
131
|
+
): Puri<TSchema, TTables, ParseSelectObject<TTables, TSelect>> {
|
|
129
132
|
const selectClauses: (string | Knex.Raw)[] = [];
|
|
130
133
|
|
|
131
134
|
for (const [alias, columnOrFunction] of Object.entries(selectObj)) {
|
|
132
135
|
if (
|
|
133
136
|
typeof columnOrFunction === "object" &&
|
|
134
|
-
columnOrFunction._type === "
|
|
137
|
+
columnOrFunction._type === "sql_expression"
|
|
135
138
|
) {
|
|
136
139
|
// SQL 함수인 경우
|
|
137
140
|
selectClauses.push(
|
|
@@ -154,50 +157,211 @@ export class Puri<
|
|
|
154
157
|
return this as any;
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
> {
|
|
160
|
+
// SELECT (select는 overwrite, appendSelect는 append)
|
|
161
|
+
appendSelect<TSelect extends SelectObject<TTables>>(
|
|
162
|
+
selectObj: TSelect
|
|
163
|
+
): Puri<TSchema, TTables, TResult & ParseSelectObject<TTables, TSelect>> {
|
|
164
|
+
return this.select(selectObj) as any;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// SELECT *
|
|
168
|
+
selectAll(): this {
|
|
167
169
|
this.knexQuery.select("*");
|
|
168
170
|
return this as any;
|
|
169
171
|
}
|
|
170
172
|
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
// JOIN: 서브쿼리 + Alias
|
|
174
|
+
join<TJoinAlias extends string, TSubResult>(
|
|
175
|
+
tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
|
|
176
|
+
left: AvailableColumns<TTables>,
|
|
177
|
+
right: `${TJoinAlias}.${keyof TSubResult & string}`
|
|
178
|
+
): Puri<
|
|
179
|
+
TSchema,
|
|
180
|
+
TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult
|
|
181
|
+
TResult
|
|
182
|
+
>;
|
|
183
|
+
// JOIN: 테이블 + Alias
|
|
184
|
+
join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
|
|
185
|
+
tableSpec: { [K in TJoinAlias]: TJoinTable },
|
|
186
|
+
left: AvailableColumns<TTables>,
|
|
187
|
+
right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`
|
|
188
|
+
): Puri<
|
|
189
|
+
TSchema,
|
|
190
|
+
TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!
|
|
191
|
+
TResult
|
|
192
|
+
>;
|
|
193
|
+
// JOIN: 테이블명
|
|
194
|
+
join<TJoinTable extends keyof TSchema>(
|
|
195
|
+
tableName: TJoinTable,
|
|
196
|
+
left: AvailableColumns<TTables>,
|
|
197
|
+
right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`
|
|
198
|
+
): Puri<
|
|
199
|
+
TSchema,
|
|
200
|
+
TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키
|
|
201
|
+
TResult
|
|
202
|
+
>;
|
|
203
|
+
// JOIN: 서브쿼리 + Alias + 콜백
|
|
204
|
+
join<TJoinAlias extends string, TSubResult>(
|
|
205
|
+
tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
|
|
206
|
+
callback: (
|
|
207
|
+
j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>
|
|
208
|
+
) => void
|
|
209
|
+
): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;
|
|
210
|
+
// JOIN: 테이블 + Alias + 콜백
|
|
211
|
+
join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
|
|
212
|
+
tableSpec: { [K in TJoinAlias]: TJoinTable },
|
|
213
|
+
callback: (
|
|
214
|
+
j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>
|
|
215
|
+
) => void
|
|
216
|
+
): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;
|
|
217
|
+
// JOIN: 테이블명 + 콜백
|
|
218
|
+
join<TJoinTable extends keyof TSchema>(
|
|
219
|
+
tableName: TJoinTable,
|
|
220
|
+
callback: (
|
|
221
|
+
j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>
|
|
222
|
+
) => void
|
|
223
|
+
): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;
|
|
224
|
+
// JOIN 실제 구현
|
|
225
|
+
join(tableNameOrSpec: any, ...args: any[]): any {
|
|
226
|
+
return this.__commonJoin("join", tableNameOrSpec, ...args);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// LEFT JOIN: 서브쿼리 + Alias
|
|
230
|
+
leftJoin<TJoinAlias extends string, TSubResult>(
|
|
231
|
+
tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
|
|
232
|
+
left: AvailableColumns<TTables>,
|
|
233
|
+
right: `${TJoinAlias}.${keyof TSubResult & string}`
|
|
234
|
+
): Puri<
|
|
235
|
+
TSchema,
|
|
236
|
+
TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult
|
|
237
|
+
TResult
|
|
238
|
+
>;
|
|
239
|
+
// LEFT JOIN: 테이블 + Alias
|
|
240
|
+
leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
|
|
241
|
+
tableSpec: { [K in TJoinAlias]: TJoinTable },
|
|
242
|
+
left: AvailableColumns<TTables>,
|
|
243
|
+
right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`
|
|
244
|
+
): Puri<
|
|
245
|
+
TSchema,
|
|
246
|
+
TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!
|
|
247
|
+
TResult
|
|
248
|
+
>;
|
|
249
|
+
// LEFT JOIN: 테이블명
|
|
250
|
+
leftJoin<TJoinTable extends keyof TSchema>(
|
|
251
|
+
tableName: TJoinTable,
|
|
252
|
+
left: AvailableColumns<TTables>,
|
|
253
|
+
right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`
|
|
254
|
+
): Puri<
|
|
255
|
+
TSchema,
|
|
256
|
+
TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키
|
|
257
|
+
TResult
|
|
258
|
+
>;
|
|
259
|
+
// LEFT JOIN: 서브쿼리 + Alias + 콜백
|
|
260
|
+
leftJoin<TJoinAlias extends string, TSubResult>(
|
|
261
|
+
tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
|
|
262
|
+
callback: (
|
|
263
|
+
j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>
|
|
264
|
+
) => void
|
|
265
|
+
): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;
|
|
266
|
+
// LEFT JOIN: 테이블 + Alias + 콜백
|
|
267
|
+
leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
|
|
268
|
+
tableSpec: { [K in TJoinAlias]: TJoinTable },
|
|
269
|
+
callback: (
|
|
270
|
+
j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>
|
|
271
|
+
) => void
|
|
272
|
+
): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;
|
|
273
|
+
// LEFT JOIN: 테이블명 + 콜백
|
|
274
|
+
leftJoin<TJoinTable extends keyof TSchema>(
|
|
275
|
+
tableName: TJoinTable,
|
|
276
|
+
callback: (
|
|
277
|
+
j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>
|
|
278
|
+
) => void
|
|
279
|
+
): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;
|
|
280
|
+
// LEFT JOIN 실제 구현
|
|
281
|
+
leftJoin(tableNameOrSpec: any, ...args: any[]): any {
|
|
282
|
+
return this.__commonJoin("leftJoin", tableNameOrSpec, ...args);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
__commonJoin(
|
|
286
|
+
joinType: "join" | "leftJoin",
|
|
287
|
+
tableNameOrSpec: any,
|
|
288
|
+
...args: any[]
|
|
289
|
+
): this {
|
|
290
|
+
if (typeof tableNameOrSpec === "string") {
|
|
291
|
+
// Case 1: join("posts", ...)
|
|
292
|
+
const tableName = tableNameOrSpec;
|
|
293
|
+
|
|
294
|
+
if (args.length === 1 && typeof args[0] === "function") {
|
|
295
|
+
// join("posts", callback)
|
|
296
|
+
const callback = args[0];
|
|
297
|
+
this.knexQuery[joinType](tableName, (joinClause) => {
|
|
298
|
+
callback(new JoinClauseGroup(joinClause));
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
// join("posts", left, right)
|
|
302
|
+
const [left, right] = args;
|
|
303
|
+
this.knexQuery[joinType](tableName, left, right);
|
|
304
|
+
}
|
|
305
|
+
} else if (typeof tableNameOrSpec === "object") {
|
|
306
|
+
// Case 2: join({ alias: "table" }, ...) or join({ alias: subquery }, ...)
|
|
307
|
+
const entries = Object.entries(tableNameOrSpec);
|
|
308
|
+
if (entries.length !== 1) {
|
|
309
|
+
throw new Error("Table spec must have exactly one entry");
|
|
310
|
+
}
|
|
311
|
+
assert(entries[0]);
|
|
312
|
+
const [[alias, spec]] = entries;
|
|
313
|
+
|
|
314
|
+
if (typeof spec === "string") {
|
|
315
|
+
// 테이블: join({ p: "posts" }, ...)
|
|
316
|
+
if (args.length === 1 && typeof args[0] === "function") {
|
|
317
|
+
// Callback
|
|
318
|
+
const callback = args[0];
|
|
319
|
+
this.knexQuery[joinType]({ [alias]: spec }, (joinClause) => {
|
|
320
|
+
callback(new JoinClauseGroup(joinClause));
|
|
321
|
+
});
|
|
322
|
+
} else {
|
|
323
|
+
// Simple
|
|
324
|
+
const [left, right] = args;
|
|
325
|
+
this.knexQuery[joinType]({ [alias]: spec }, left, right);
|
|
326
|
+
}
|
|
327
|
+
} else if (spec instanceof Puri) {
|
|
328
|
+
// 서브쿼리: join({ sq: subquery }, ...)
|
|
329
|
+
if (args.length === 1 && typeof args[0] === "function") {
|
|
330
|
+
// Callback
|
|
331
|
+
const callback = args[0];
|
|
332
|
+
this.knexQuery[joinType](spec.raw().as(alias), (joinClause) => {
|
|
333
|
+
callback(new JoinClauseGroup(joinClause));
|
|
334
|
+
});
|
|
335
|
+
} else {
|
|
336
|
+
// Simple
|
|
337
|
+
const [left, right] = args;
|
|
338
|
+
this.knexQuery[joinType](spec.raw().as(alias), left, right);
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
throw new Error("Invalid table specification");
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
throw new Error("Invalid arguments");
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return this;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// WHERE: 객체 - 사용: .where({ "u.id": 1, "u.status": "active" })
|
|
351
|
+
where(conditions: WhereCondition<TTables>): this;
|
|
352
|
+
// WHERE: 컬럼 - 사용: .where("u.id", 1)
|
|
353
|
+
where<TColumn extends AvailableColumns<TTables>>(
|
|
176
354
|
column: TColumn,
|
|
177
|
-
value: ExtractColumnType<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
TOriginal,
|
|
182
|
-
TJoined
|
|
183
|
-
>
|
|
184
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
185
|
-
where<TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>>(
|
|
355
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
356
|
+
): this;
|
|
357
|
+
// WHERE: 컬럼 - 사용: .where("u.id", ">", 10)
|
|
358
|
+
where<TColumn extends AvailableColumns<TTables>>(
|
|
186
359
|
column: TColumn,
|
|
187
|
-
operator: ComparisonOperator | "like",
|
|
188
|
-
value: ExtractColumnType<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
TOriginal,
|
|
193
|
-
TJoined
|
|
194
|
-
>
|
|
195
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
196
|
-
where(
|
|
197
|
-
columnOrConditions: any,
|
|
198
|
-
operatorOrValue?: any,
|
|
199
|
-
value?: any
|
|
200
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
360
|
+
operator: ComparisonOperator | "like" | "not like",
|
|
361
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
362
|
+
): this;
|
|
363
|
+
// WHERE: 컬럼 - 사용: .where("u.id", "like", "%test%")
|
|
364
|
+
where(columnOrConditions: any, operatorOrValue?: any, value?: any): this {
|
|
201
365
|
if (typeof columnOrConditions === "object") {
|
|
202
366
|
this.knexQuery.where(columnOrConditions);
|
|
203
367
|
} else if (arguments.length === 2) {
|
|
@@ -223,386 +387,192 @@ export class Puri<
|
|
|
223
387
|
return this;
|
|
224
388
|
}
|
|
225
389
|
|
|
226
|
-
//
|
|
227
|
-
whereIn<
|
|
228
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
229
|
-
>(
|
|
390
|
+
// WHERE IN
|
|
391
|
+
whereIn<TColumn extends AvailableColumns<TTables>>(
|
|
230
392
|
column: TColumn,
|
|
231
|
-
values: ExtractColumnType<
|
|
232
|
-
|
|
233
|
-
TTable,
|
|
234
|
-
TColumn & string,
|
|
235
|
-
TOriginal,
|
|
236
|
-
TJoined
|
|
237
|
-
>[]
|
|
238
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
239
|
-
whereIn(
|
|
240
|
-
column: string,
|
|
241
|
-
values: any[]
|
|
242
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
393
|
+
values: ExtractColumnType<TTables, TColumn & string>[]
|
|
394
|
+
): Puri<TSchema, TTables, TResult> {
|
|
243
395
|
this.knexQuery.whereIn(column, values);
|
|
244
|
-
return this;
|
|
396
|
+
return this as any;
|
|
245
397
|
}
|
|
246
398
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
>(
|
|
399
|
+
// WHERE NOT IN
|
|
400
|
+
whereNotIn<TColumn extends AvailableColumns<TTables>>(
|
|
250
401
|
column: TColumn,
|
|
251
|
-
values: ExtractColumnType<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
TOriginal,
|
|
256
|
-
TJoined
|
|
257
|
-
>[]
|
|
258
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
259
|
-
whereNotIn(
|
|
260
|
-
column: string,
|
|
261
|
-
values: any[]
|
|
262
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
263
|
-
this.knexQuery.whereNotIn(column, values);
|
|
264
|
-
return this;
|
|
402
|
+
values: ExtractColumnType<TTables, TColumn & string>[]
|
|
403
|
+
): Puri<TSchema, TTables, TResult> {
|
|
404
|
+
this.knexQuery.whereIn(column, values);
|
|
405
|
+
return this as any;
|
|
265
406
|
}
|
|
266
407
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
>(
|
|
408
|
+
// WHERE MATCH
|
|
409
|
+
whereMatch<TColumn extends FulltextColumns<TTables>>(
|
|
270
410
|
column: TColumn,
|
|
271
411
|
value: string
|
|
272
|
-
):
|
|
412
|
+
): this {
|
|
273
413
|
this.knexQuery.whereRaw(`MATCH (${String(column)}) AGAINST (?)`, [value]);
|
|
274
414
|
return this;
|
|
275
415
|
}
|
|
276
416
|
|
|
277
|
-
//
|
|
278
|
-
whereGroup(
|
|
279
|
-
callback: (
|
|
280
|
-
group: WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
281
|
-
) => WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
282
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
417
|
+
// WHERE 괄호 그룹핑
|
|
418
|
+
whereGroup(callback: (g: WhereGroup<TTables>) => void): this {
|
|
283
419
|
this.knexQuery.where((builder) => {
|
|
284
|
-
const group = new WhereGroup<
|
|
285
|
-
builder
|
|
286
|
-
);
|
|
420
|
+
const group = new WhereGroup<TTables>(builder);
|
|
287
421
|
callback(group);
|
|
288
422
|
});
|
|
289
423
|
return this;
|
|
290
424
|
}
|
|
291
|
-
|
|
292
|
-
orWhereGroup(
|
|
293
|
-
callback: (
|
|
294
|
-
group: WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
295
|
-
) => WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
296
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
425
|
+
orWhereGroup(callback: (g: WhereGroup<TTables>) => void): this {
|
|
297
426
|
this.knexQuery.orWhere((builder) => {
|
|
298
|
-
const group = new WhereGroup<
|
|
299
|
-
builder
|
|
300
|
-
);
|
|
427
|
+
const group = new WhereGroup<TTables>(builder);
|
|
301
428
|
callback(group);
|
|
302
429
|
});
|
|
303
430
|
return this;
|
|
304
431
|
}
|
|
305
432
|
|
|
306
|
-
//
|
|
307
|
-
|
|
308
|
-
TJoinTable extends keyof TSchema,
|
|
309
|
-
TLColumn extends AvailableColumns<
|
|
310
|
-
TSchema,
|
|
311
|
-
TTable,
|
|
312
|
-
TOriginal,
|
|
313
|
-
TJoined & Record<TJoinTable, TSchema[TJoinTable]>
|
|
314
|
-
>,
|
|
315
|
-
TRColumn extends AvailableColumns<
|
|
316
|
-
TSchema,
|
|
317
|
-
TTable,
|
|
318
|
-
TOriginal,
|
|
319
|
-
TJoined & Record<TJoinTable, TSchema[TJoinTable]>
|
|
320
|
-
>,
|
|
321
|
-
>(
|
|
322
|
-
table: TJoinTable,
|
|
323
|
-
left: TLColumn,
|
|
324
|
-
right: TRColumn
|
|
325
|
-
): Puri<
|
|
326
|
-
TSchema,
|
|
327
|
-
TTable,
|
|
328
|
-
TOriginal,
|
|
329
|
-
TResult,
|
|
330
|
-
MergeJoined<TJoined, Record<TJoinTable, TSchema[TJoinTable]>>
|
|
331
|
-
>;
|
|
332
|
-
join<TJoinTable extends keyof TSchema>(
|
|
333
|
-
table: TJoinTable,
|
|
334
|
-
joinCallback: (
|
|
335
|
-
joinClause: JoinClauseGroup<TSchema, TTable, TOriginal, TJoined>
|
|
336
|
-
) => void
|
|
337
|
-
): Puri<
|
|
338
|
-
TSchema,
|
|
339
|
-
TTable,
|
|
340
|
-
TOriginal,
|
|
341
|
-
TResult,
|
|
342
|
-
MergeJoined<TJoined, Record<TJoinTable, TSchema[TJoinTable]>>
|
|
343
|
-
>;
|
|
344
|
-
join<TSubResult, TAlias extends string>(
|
|
345
|
-
subquery: Puri<TSchema, any, any, TSubResult, any>,
|
|
346
|
-
alias: TAlias,
|
|
347
|
-
left: string,
|
|
348
|
-
right: string
|
|
349
|
-
): Puri<
|
|
350
|
-
TSchema,
|
|
351
|
-
TTable,
|
|
352
|
-
TOriginal,
|
|
353
|
-
TResult,
|
|
354
|
-
TJoined & Record<TAlias, TSubResult>
|
|
355
|
-
>;
|
|
356
|
-
join(
|
|
357
|
-
table: string,
|
|
358
|
-
left: string,
|
|
359
|
-
right: string
|
|
360
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
361
|
-
join(
|
|
362
|
-
tableOrSubquery: string | keyof TSchema | Puri<TSchema, any, any, any, any>,
|
|
363
|
-
...args: any[]
|
|
364
|
-
): Puri<TSchema, TTable, TOriginal, TResult, any> {
|
|
365
|
-
if (tableOrSubquery instanceof Puri) {
|
|
366
|
-
// 서브쿼리 조인: join(subquery, alias, left, right)
|
|
367
|
-
const [alias, left, right] = args;
|
|
368
|
-
this.knexQuery.join(tableOrSubquery.raw().as(alias), left, right);
|
|
369
|
-
} else if (
|
|
370
|
-
args.length === 2 &&
|
|
371
|
-
typeof args[0] === "string" &&
|
|
372
|
-
typeof args[1] === "string"
|
|
373
|
-
) {
|
|
374
|
-
const [left, right] = args;
|
|
375
|
-
this.knexQuery.join(tableOrSubquery as string, left, right);
|
|
376
|
-
} else if (args.length === 1 && typeof args[0] === "function") {
|
|
377
|
-
const joinCallback = args[0];
|
|
378
|
-
this.knexQuery.join(tableOrSubquery as string, (joinClause) => {
|
|
379
|
-
joinCallback(new JoinClauseGroup(joinClause));
|
|
380
|
-
});
|
|
381
|
-
} else {
|
|
382
|
-
throw new Error("Invalid arguments");
|
|
383
|
-
}
|
|
384
|
-
return this as any;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
leftJoin<
|
|
388
|
-
TJoinTable extends keyof TSchema,
|
|
389
|
-
TLColumn extends AvailableColumns<
|
|
390
|
-
TSchema,
|
|
391
|
-
TTable,
|
|
392
|
-
TOriginal,
|
|
393
|
-
TJoined & Record<TJoinTable, TSchema[TJoinTable]>
|
|
394
|
-
>,
|
|
395
|
-
TRColumn extends AvailableColumns<
|
|
396
|
-
TSchema,
|
|
397
|
-
TTable,
|
|
398
|
-
TOriginal,
|
|
399
|
-
TJoined & Record<TJoinTable, TSchema[TJoinTable]>
|
|
400
|
-
>,
|
|
401
|
-
>(
|
|
402
|
-
table: TJoinTable,
|
|
403
|
-
left: TLColumn,
|
|
404
|
-
right: TRColumn
|
|
405
|
-
): Puri<
|
|
406
|
-
TSchema,
|
|
407
|
-
TTable,
|
|
408
|
-
TOriginal,
|
|
409
|
-
TResult,
|
|
410
|
-
TJoined & Record<TJoinTable, Partial<TSchema[TJoinTable]>>
|
|
411
|
-
>;
|
|
412
|
-
leftJoin<TSubResult, TAlias extends string>(
|
|
413
|
-
subquery: Puri<TSchema, any, any, TSubResult, any>,
|
|
414
|
-
alias: TAlias,
|
|
415
|
-
left: string,
|
|
416
|
-
right: string
|
|
417
|
-
): Puri<
|
|
418
|
-
TSchema,
|
|
419
|
-
TTable,
|
|
420
|
-
TOriginal,
|
|
421
|
-
TResult,
|
|
422
|
-
TJoined & Record<TAlias, Partial<TSubResult>>
|
|
423
|
-
>;
|
|
424
|
-
leftJoin(
|
|
425
|
-
table: string,
|
|
426
|
-
left: string,
|
|
427
|
-
right: string
|
|
428
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
429
|
-
leftJoin(
|
|
430
|
-
tableOrSubquery: string | keyof TSchema | Puri<TSchema, any, any, any, any>,
|
|
431
|
-
...args: any[]
|
|
432
|
-
): Puri<TSchema, TTable, TOriginal, TResult, any> {
|
|
433
|
-
if (tableOrSubquery instanceof Puri) {
|
|
434
|
-
// 서브쿼리 조인: leftJoin(subquery, alias, left, right)
|
|
435
|
-
const [alias, left, right] = args;
|
|
436
|
-
this.knexQuery.leftJoin(tableOrSubquery.raw().as(alias), left, right);
|
|
437
|
-
} else {
|
|
438
|
-
const [left, right] = args;
|
|
439
|
-
this.knexQuery.leftJoin(tableOrSubquery as string, left, right);
|
|
440
|
-
}
|
|
441
|
-
return this as any;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// OrderBy
|
|
445
|
-
orderBy<
|
|
446
|
-
TColumn extends ResultAvailableColumns<
|
|
447
|
-
TSchema,
|
|
448
|
-
TTable,
|
|
449
|
-
TOriginal,
|
|
450
|
-
TResult,
|
|
451
|
-
TJoined
|
|
452
|
-
>,
|
|
453
|
-
>(
|
|
433
|
+
// ORDER BY
|
|
434
|
+
orderBy<TColumn extends ResultAvailableColumns<TTables, TResult>>(
|
|
454
435
|
column: TColumn,
|
|
455
436
|
direction: "asc" | "desc"
|
|
456
|
-
):
|
|
457
|
-
orderBy(
|
|
458
|
-
column: string,
|
|
459
|
-
direction: "asc" | "desc" = "asc"
|
|
460
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
437
|
+
): this;
|
|
438
|
+
orderBy(column: string, direction: "asc" | "desc" = "asc"): this {
|
|
461
439
|
this.knexQuery.orderBy(column, direction);
|
|
462
440
|
return this;
|
|
463
441
|
}
|
|
464
442
|
|
|
465
443
|
// 기본 쿼리 메서드들
|
|
466
|
-
limit(count: number):
|
|
444
|
+
limit(count: number): this {
|
|
467
445
|
this.knexQuery.limit(count);
|
|
468
446
|
return this;
|
|
469
447
|
}
|
|
470
448
|
|
|
471
|
-
offset(count: number):
|
|
449
|
+
offset(count: number): this {
|
|
472
450
|
this.knexQuery.offset(count);
|
|
473
451
|
return this;
|
|
474
452
|
}
|
|
475
453
|
|
|
476
|
-
//
|
|
477
|
-
groupBy<
|
|
478
|
-
TColumns
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
TOriginal,
|
|
482
|
-
TResult,
|
|
483
|
-
TJoined
|
|
484
|
-
>,
|
|
485
|
-
>(...columns: TColumns[]): Puri<TSchema, TTable, TOriginal, TResult, TJoined>;
|
|
486
|
-
groupBy(
|
|
487
|
-
...columns: string[]
|
|
488
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
454
|
+
// GROUP BY
|
|
455
|
+
groupBy<TColumns extends ResultAvailableColumns<TTables, TResult>>(
|
|
456
|
+
...columns: TColumns[]
|
|
457
|
+
): this;
|
|
458
|
+
groupBy(...columns: string[]): this {
|
|
489
459
|
this.knexQuery.groupBy(...(columns as string[]));
|
|
490
460
|
return this;
|
|
491
461
|
}
|
|
492
462
|
|
|
493
|
-
|
|
494
|
-
having
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
TTable,
|
|
498
|
-
TOriginal,
|
|
499
|
-
TResult,
|
|
500
|
-
TJoined
|
|
501
|
-
>,
|
|
502
|
-
>(
|
|
503
|
-
condition: TColumn,
|
|
463
|
+
// HAVING
|
|
464
|
+
having(condition: string): this;
|
|
465
|
+
having<TColumn extends ResultAvailableColumns<TTables, TResult>>(
|
|
466
|
+
column: TColumn,
|
|
504
467
|
operator: ComparisonOperator,
|
|
505
468
|
value: any
|
|
506
|
-
):
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
469
|
+
): this;
|
|
470
|
+
// HAVING 구현
|
|
471
|
+
having(...conditions: any[]): this {
|
|
472
|
+
if (conditions.length === 1) {
|
|
473
|
+
// having("COUNT(*) > 10")
|
|
474
|
+
this.knexQuery.having(conditions[0]);
|
|
475
|
+
} else if (conditions.length === 3) {
|
|
476
|
+
// having("count", ">", 10)
|
|
477
|
+
this.knexQuery.having(conditions[0], conditions[1], conditions[2]);
|
|
478
|
+
} else {
|
|
479
|
+
throw new Error("Invalid having arguments");
|
|
480
|
+
}
|
|
511
481
|
return this;
|
|
512
482
|
}
|
|
483
|
+
|
|
513
484
|
// 실행 메서드들 - thenable 구현
|
|
514
|
-
then<TResult1, TResult2 = never>(
|
|
485
|
+
then<TResult1 = Expand<TResult>[], TResult2 = never>(
|
|
515
486
|
onfulfilled?:
|
|
516
|
-
| ((
|
|
517
|
-
value: Expand<TResult>[]
|
|
518
|
-
) => Expand<TResult1> | PromiseLike<Expand<TResult1>>)
|
|
487
|
+
| ((value: Expand<TResult>[]) => TResult1 | PromiseLike<TResult1>)
|
|
519
488
|
| null,
|
|
520
489
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
521
|
-
): Promise<
|
|
490
|
+
): Promise<TResult1 | TResult2> {
|
|
491
|
+
Naite.t("puri-query", this.toQuery());
|
|
522
492
|
return this.knexQuery.then(onfulfilled as any, onrejected);
|
|
523
493
|
}
|
|
524
|
-
|
|
525
494
|
catch<TResult2 = never>(
|
|
526
495
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
527
|
-
): Promise<
|
|
496
|
+
): Promise<TResult | TResult2> {
|
|
528
497
|
return this.knexQuery.catch(onrejected);
|
|
529
498
|
}
|
|
530
|
-
|
|
531
|
-
finally(onfinally?: (() => void) | null): Promise<Expand<TResult>> {
|
|
499
|
+
finally(onfinally?: (() => void) | null): Promise<TResult> {
|
|
532
500
|
return this.knexQuery.finally(onfinally);
|
|
533
501
|
}
|
|
534
502
|
|
|
535
|
-
//
|
|
536
|
-
|
|
537
|
-
|
|
503
|
+
// 하나만 쿼리
|
|
504
|
+
first(): ResolvedPuri<Expand<TResult>, never> {
|
|
505
|
+
this.knexQuery.first();
|
|
506
|
+
return new ResolvedPuri(this.knexQuery);
|
|
538
507
|
}
|
|
539
508
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
throw new Error("No results found");
|
|
544
|
-
}
|
|
545
|
-
return result as TResult;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
async at(index: number): Promise<Expand<TResult> | undefined> {
|
|
549
|
-
const results = await this;
|
|
550
|
-
return results[index] as Expand<TResult> | undefined;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
async assertAt(index: number): Promise<Expand<TResult>> {
|
|
554
|
-
const results = await this;
|
|
555
|
-
const result = results[index];
|
|
556
|
-
if (result === undefined) {
|
|
557
|
-
throw new Error(`No result found at index ${index}`);
|
|
558
|
-
}
|
|
559
|
-
return result;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Pluck
|
|
563
|
-
async pluck<
|
|
564
|
-
TColumn extends ResultAvailableColumns<
|
|
565
|
-
TSchema,
|
|
566
|
-
TTable,
|
|
567
|
-
TOriginal,
|
|
568
|
-
TResult,
|
|
569
|
-
TJoined
|
|
570
|
-
>,
|
|
509
|
+
// 쿼리한 레코드에서 특정 컬럼만 추출한 배열 리턴
|
|
510
|
+
pluck<
|
|
511
|
+
TColumn extends keyof TResult | ResultAvailableColumns<TTables, TResult>,
|
|
571
512
|
>(
|
|
572
513
|
column: TColumn
|
|
573
|
-
):
|
|
574
|
-
|
|
514
|
+
): ResolvedPuri<
|
|
515
|
+
TColumn extends keyof TResult
|
|
516
|
+
? TResult[TColumn][]
|
|
517
|
+
: ExtractColumnType<TTables, TColumn & string>[],
|
|
518
|
+
never
|
|
575
519
|
> {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
520
|
+
this.knexQuery.pluck(column as string);
|
|
521
|
+
return new ResolvedPuri(this.knexQuery);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// INSERT
|
|
525
|
+
insert(
|
|
526
|
+
data: InsertData<SingleTableValue<TTables>>
|
|
527
|
+
): ResolvedPuri<[number], never> {
|
|
528
|
+
this.knexQuery.insert(data);
|
|
529
|
+
return new ResolvedPuri(this.knexQuery);
|
|
579
530
|
}
|
|
580
531
|
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
): Promise<number[]> {
|
|
586
|
-
return this.knexQuery.insert(data);
|
|
532
|
+
// UPDATE
|
|
533
|
+
update(data: WhereCondition<TTables>): ResolvedPuri<TResult, number> {
|
|
534
|
+
this.knexQuery.update(data);
|
|
535
|
+
return new ResolvedPuri(this.knexQuery);
|
|
587
536
|
}
|
|
588
537
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
538
|
+
// Increment
|
|
539
|
+
increment<TColumn extends AvailableColumns<TTables>>(
|
|
540
|
+
column: TColumn,
|
|
541
|
+
value: number
|
|
542
|
+
): ResolvedPuri<number, never> {
|
|
543
|
+
if (value <= 0) {
|
|
544
|
+
throw new Error("Increment value must be greater than 0");
|
|
545
|
+
}
|
|
546
|
+
this.knexQuery.increment(column, value);
|
|
547
|
+
return new ResolvedPuri(this.knexQuery);
|
|
548
|
+
}
|
|
549
|
+
// Decrement
|
|
550
|
+
decrement<TColumn extends AvailableColumns<TTables>>(
|
|
551
|
+
column: TColumn,
|
|
552
|
+
value: number
|
|
553
|
+
): ResolvedPuri<number, never> {
|
|
554
|
+
if (value <= 0) {
|
|
555
|
+
throw new Error("Decrement value must be greater than 0");
|
|
556
|
+
}
|
|
557
|
+
this.knexQuery.decrement(column, value);
|
|
558
|
+
return new ResolvedPuri(this.knexQuery);
|
|
593
559
|
}
|
|
594
560
|
|
|
595
|
-
|
|
596
|
-
|
|
561
|
+
// DELETE
|
|
562
|
+
delete(): ResolvedPuri<number, never> {
|
|
563
|
+
this.knexQuery.delete();
|
|
564
|
+
return new ResolvedPuri(this.knexQuery);
|
|
597
565
|
}
|
|
598
566
|
|
|
567
|
+
// 확인 쿼리 리턴
|
|
599
568
|
toQuery(): string {
|
|
600
569
|
return this.knexQuery.toQuery();
|
|
601
570
|
}
|
|
602
571
|
|
|
603
|
-
|
|
572
|
+
// 쿼리 디버깅 로그 출력
|
|
573
|
+
debug(): this {
|
|
604
574
|
console.log(
|
|
605
|
-
`${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.
|
|
575
|
+
`${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`
|
|
606
576
|
);
|
|
607
577
|
return this;
|
|
608
578
|
}
|
|
@@ -718,174 +688,62 @@ export class Puri<
|
|
|
718
688
|
return indentedLines.join("\n").trim();
|
|
719
689
|
}
|
|
720
690
|
|
|
691
|
+
// Knex 쿼리 빌더 직접 접근
|
|
721
692
|
raw(): Knex.QueryBuilder {
|
|
722
693
|
return this.knexQuery;
|
|
723
694
|
}
|
|
724
|
-
|
|
725
|
-
increment<
|
|
726
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
727
|
-
>(
|
|
728
|
-
column: TColumn,
|
|
729
|
-
value: number
|
|
730
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
731
|
-
if (value <= 0) {
|
|
732
|
-
throw new Error("Increment value must be greater than 0");
|
|
733
|
-
}
|
|
734
|
-
this.knexQuery.increment(column, value);
|
|
735
|
-
return this;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
decrement<
|
|
739
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
740
|
-
>(
|
|
741
|
-
column: TColumn,
|
|
742
|
-
value: number
|
|
743
|
-
): Puri<TSchema, TTable, TOriginal, TResult, TJoined> {
|
|
744
|
-
if (value <= 0) {
|
|
745
|
-
throw new Error("Decrement value must be greater than 0");
|
|
746
|
-
}
|
|
747
|
-
this.knexQuery.decrement(column, value);
|
|
748
|
-
return this;
|
|
749
|
-
}
|
|
750
695
|
}
|
|
751
696
|
|
|
752
|
-
|
|
753
|
-
class WhereGroup<
|
|
754
|
-
TSchema,
|
|
755
|
-
TTable extends keyof TSchema | string,
|
|
756
|
-
TOriginal = any,
|
|
757
|
-
TJoined = EmptyRecord,
|
|
758
|
-
> {
|
|
697
|
+
export class WhereGroup<TTables extends Record<string, any>> {
|
|
759
698
|
constructor(private builder: Knex.QueryBuilder) {}
|
|
760
699
|
|
|
761
|
-
where
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
where<TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>>(
|
|
700
|
+
// where 메서드들
|
|
701
|
+
where(conditions: WhereCondition<TTables>): this;
|
|
702
|
+
where<TColumn extends AvailableColumns<TTables>>(
|
|
765
703
|
column: TColumn,
|
|
766
|
-
value: ExtractColumnType<
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
TColumn & string,
|
|
770
|
-
TOriginal,
|
|
771
|
-
TJoined
|
|
772
|
-
>
|
|
773
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
774
|
-
where<TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>>(
|
|
704
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
705
|
+
): this;
|
|
706
|
+
where<TColumn extends AvailableColumns<TTables>>(
|
|
775
707
|
column: TColumn,
|
|
776
|
-
operator: ComparisonOperator
|
|
777
|
-
value: ExtractColumnType<
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
TColumn & string,
|
|
781
|
-
TOriginal,
|
|
782
|
-
TJoined
|
|
783
|
-
>
|
|
784
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
785
|
-
where(raw: string): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
786
|
-
where(...args: any[]): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
708
|
+
operator: ComparisonOperator,
|
|
709
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
710
|
+
): this;
|
|
711
|
+
where(...args: any[]): WhereGroup<TTables> {
|
|
787
712
|
this.builder.where(args[0], ...args.slice(1));
|
|
788
713
|
return this;
|
|
789
714
|
}
|
|
790
715
|
|
|
791
|
-
orWhere
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
orWhere<
|
|
795
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
796
|
-
>(
|
|
716
|
+
// orWhere 메서드들
|
|
717
|
+
orWhere(conditions: WhereCondition<TTables>): this;
|
|
718
|
+
orWhere<TColumn extends AvailableColumns<TTables>>(
|
|
797
719
|
column: TColumn,
|
|
798
|
-
value: ExtractColumnType<
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
TColumn & string,
|
|
802
|
-
TOriginal,
|
|
803
|
-
TJoined
|
|
804
|
-
>
|
|
805
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
806
|
-
orWhere<
|
|
807
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
808
|
-
>(
|
|
720
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
721
|
+
): this;
|
|
722
|
+
orWhere<TColumn extends AvailableColumns<TTables>>(
|
|
809
723
|
column: TColumn,
|
|
810
|
-
operator: ComparisonOperator
|
|
811
|
-
value: ExtractColumnType<
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
TColumn & string,
|
|
815
|
-
TOriginal,
|
|
816
|
-
TJoined
|
|
817
|
-
>
|
|
818
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
819
|
-
orWhere(raw: string): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
820
|
-
orWhere(...args: any[]): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
724
|
+
operator: ComparisonOperator,
|
|
725
|
+
value: ExtractColumnType<TTables, TColumn & string>
|
|
726
|
+
): this;
|
|
727
|
+
orWhere(...args: any[]): WhereGroup<TTables> {
|
|
821
728
|
this.builder.orWhere(args[0], ...args.slice(1));
|
|
822
729
|
return this;
|
|
823
730
|
}
|
|
824
731
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
>
|
|
828
|
-
column: TColumn,
|
|
829
|
-
values: ExtractColumnType<
|
|
830
|
-
TSchema,
|
|
831
|
-
TTable,
|
|
832
|
-
TColumn & string,
|
|
833
|
-
TOriginal,
|
|
834
|
-
TJoined
|
|
835
|
-
>[]
|
|
836
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
837
|
-
whereIn(
|
|
838
|
-
column: string,
|
|
839
|
-
values: any[]
|
|
840
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
841
|
-
this.builder.whereIn(column, values);
|
|
842
|
-
return this;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
orWhereIn<
|
|
846
|
-
TColumn extends AvailableColumns<TSchema, TTable, TOriginal, TJoined>,
|
|
847
|
-
>(
|
|
848
|
-
column: TColumn,
|
|
849
|
-
values: ExtractColumnType<
|
|
850
|
-
TSchema,
|
|
851
|
-
TTable,
|
|
852
|
-
TColumn & string,
|
|
853
|
-
TOriginal,
|
|
854
|
-
TJoined
|
|
855
|
-
>[]
|
|
856
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined>;
|
|
857
|
-
orWhereIn(
|
|
858
|
-
column: string,
|
|
859
|
-
values: any[]
|
|
860
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
861
|
-
this.builder.orWhereIn(column, values);
|
|
862
|
-
return this;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// 중첩 그룹 지원
|
|
866
|
-
whereGroup(
|
|
867
|
-
callback: (
|
|
868
|
-
group: WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
869
|
-
) => WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
870
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
732
|
+
// 중첩 그룹
|
|
733
|
+
whereGroup(callback: (g: WhereGroup<TTables>) => void): this;
|
|
734
|
+
whereGroup(callback: (g: WhereGroup<TTables>) => void): WhereGroup<TTables> {
|
|
871
735
|
this.builder.where((subBuilder) => {
|
|
872
|
-
const subGroup = new WhereGroup<
|
|
873
|
-
subBuilder
|
|
874
|
-
);
|
|
736
|
+
const subGroup = new WhereGroup<TTables>(subBuilder);
|
|
875
737
|
callback(subGroup);
|
|
876
738
|
});
|
|
877
739
|
return this;
|
|
878
740
|
}
|
|
879
|
-
|
|
741
|
+
orWhereGroup(callback: (g: WhereGroup<TTables>) => void): this;
|
|
880
742
|
orWhereGroup(
|
|
881
|
-
callback: (
|
|
882
|
-
|
|
883
|
-
) => WhereGroup<TSchema, TTable, TOriginal, TJoined>
|
|
884
|
-
): WhereGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
743
|
+
callback: (g: WhereGroup<TTables>) => void
|
|
744
|
+
): WhereGroup<TTables> {
|
|
885
745
|
this.builder.orWhere((subBuilder) => {
|
|
886
|
-
const subGroup = new WhereGroup<
|
|
887
|
-
subBuilder
|
|
888
|
-
);
|
|
746
|
+
const subGroup = new WhereGroup<TTables>(subBuilder);
|
|
889
747
|
callback(subGroup);
|
|
890
748
|
});
|
|
891
749
|
return this;
|
|
@@ -893,38 +751,77 @@ class WhereGroup<
|
|
|
893
751
|
}
|
|
894
752
|
|
|
895
753
|
export class JoinClauseGroup<
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
TOriginal = any,
|
|
899
|
-
TJoined = EmptyRecord,
|
|
754
|
+
TLeft extends Record<string, any>,
|
|
755
|
+
TRight extends Record<string, any>,
|
|
900
756
|
> {
|
|
901
757
|
constructor(private callback: Knex.JoinClause) {}
|
|
902
758
|
|
|
759
|
+
// ON(AND): 컬럼 = 컬럼
|
|
760
|
+
on(left: AvailableColumns<TLeft>, right: AvailableColumns<TRight>): this;
|
|
761
|
+
// ON(AND): 컬럼 (연산자) 컬럼
|
|
903
762
|
on(
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
):
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
):
|
|
912
|
-
on(...args: any[]): JoinClauseGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
763
|
+
left: AvailableColumns<TLeft>,
|
|
764
|
+
operator: ComparisonOperator,
|
|
765
|
+
right: AvailableColumns<TRight>
|
|
766
|
+
): this;
|
|
767
|
+
// ON(AND): 콜백
|
|
768
|
+
on(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;
|
|
769
|
+
// ON(AND) 구현
|
|
770
|
+
on(...args: any[]): this {
|
|
913
771
|
this.callback.on(...(args as [string, string]));
|
|
914
772
|
return this;
|
|
915
773
|
}
|
|
916
774
|
|
|
775
|
+
// ON(OR): 컬럼 = 컬럼
|
|
776
|
+
orOn(left: AvailableColumns<TLeft>, right: AvailableColumns<TRight>): this;
|
|
777
|
+
// ON(OR): 컬럼 (연산자) 컬럼
|
|
917
778
|
orOn(
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
):
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
):
|
|
926
|
-
orOn(...args: any[]): JoinClauseGroup<TSchema, TTable, TOriginal, TJoined> {
|
|
779
|
+
left: AvailableColumns<TLeft>,
|
|
780
|
+
operator: ComparisonOperator,
|
|
781
|
+
right: AvailableColumns<TRight>
|
|
782
|
+
): this;
|
|
783
|
+
// ON(OR): 콜백
|
|
784
|
+
orOn(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;
|
|
785
|
+
// ON(OR) 구현
|
|
786
|
+
orOn(...args: any[]): this {
|
|
927
787
|
this.callback.orOn(...(args as [string, string]));
|
|
928
788
|
return this;
|
|
929
789
|
}
|
|
930
790
|
}
|
|
791
|
+
|
|
792
|
+
/*
|
|
793
|
+
TResolved: 쿼리 실행 후 반환될 결과 타입
|
|
794
|
+
_TReturning: 추후 RETURNING 절에 사용될 타입
|
|
795
|
+
*/
|
|
796
|
+
export class ResolvedPuri<TResolved, _TReturning> {
|
|
797
|
+
constructor(public knexQuery: Knex.QueryBuilder) {}
|
|
798
|
+
|
|
799
|
+
toQuery(): string {
|
|
800
|
+
return this.knexQuery.toQuery();
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
debug(): this {
|
|
804
|
+
console.log(
|
|
805
|
+
`${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`
|
|
806
|
+
);
|
|
807
|
+
return this;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
then<TResult1 = TResolved, TResult2 = never>(
|
|
811
|
+
onfulfilled?:
|
|
812
|
+
| ((value: TResolved) => TResult1 | PromiseLike<TResult1>)
|
|
813
|
+
| null,
|
|
814
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
815
|
+
): Promise<TResult1 | TResult2> {
|
|
816
|
+
Naite.t("puri-query", this.toQuery());
|
|
817
|
+
return this.knexQuery.then(onfulfilled as any, onrejected);
|
|
818
|
+
}
|
|
819
|
+
catch<TResult2 = never>(
|
|
820
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
821
|
+
): Promise<TResolved | TResult2> {
|
|
822
|
+
return this.knexQuery.catch(onrejected);
|
|
823
|
+
}
|
|
824
|
+
finally(onfinally?: (() => void) | null): Promise<TResolved> {
|
|
825
|
+
return this.knexQuery.finally(onfinally);
|
|
826
|
+
}
|
|
827
|
+
}
|