metal-orm 1.0.7 → 1.0.9

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.
Files changed (153) hide show
  1. package/README.md +133 -121
  2. package/dist/decorators/index.cjs +2564 -0
  3. package/dist/decorators/index.cjs.map +1 -0
  4. package/dist/decorators/index.d.cts +53 -0
  5. package/dist/decorators/index.d.ts +53 -0
  6. package/dist/decorators/index.js +2530 -0
  7. package/dist/decorators/index.js.map +1 -0
  8. package/dist/index.cjs +4227 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +701 -0
  11. package/dist/index.d.ts +701 -0
  12. package/dist/index.js +4131 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/select-654m4qy8.d.cts +1522 -0
  15. package/dist/select-654m4qy8.d.ts +1522 -0
  16. package/package.json +27 -20
  17. package/src/codegen/typescript.ts +405 -393
  18. package/src/core/ast/aggregate-functions.ts +30 -0
  19. package/src/core/ast/builders.ts +43 -0
  20. package/src/core/ast/expression-builders.ts +310 -0
  21. package/src/core/ast/expression-nodes.ts +211 -0
  22. package/src/core/ast/expression-visitor.ts +99 -0
  23. package/src/core/ast/expression.ts +5 -0
  24. package/src/{utils → core/ast}/join-node.ts +20 -20
  25. package/src/{ast → core/ast}/join.ts +18 -18
  26. package/src/{ast → core/ast}/query.ts +113 -113
  27. package/src/core/ast/window-functions.ts +140 -0
  28. package/src/{dialect → core/dialect}/abstract.ts +94 -94
  29. package/src/{dialect → core/dialect}/mssql/index.ts +31 -31
  30. package/src/{dialect → core/dialect}/mysql/index.ts +31 -31
  31. package/src/{dialect → core/dialect}/postgres/index.ts +45 -45
  32. package/src/{dialect → core/dialect}/sqlite/index.ts +45 -45
  33. package/src/{constants → core/sql}/sql-operator-config.ts +39 -39
  34. package/src/decorators/bootstrap.ts +126 -0
  35. package/src/decorators/column.ts +78 -0
  36. package/src/decorators/entity.ts +36 -0
  37. package/src/decorators/index.ts +4 -0
  38. package/src/decorators/relations.ts +107 -0
  39. package/src/global.d.ts +1 -0
  40. package/src/index.ts +22 -22
  41. package/src/orm/db-executor.ts +11 -0
  42. package/src/orm/domain-event-bus.ts +52 -0
  43. package/src/{runtime → orm}/entity-meta.ts +52 -52
  44. package/src/orm/entity-metadata.ts +140 -0
  45. package/src/{runtime → orm}/entity.ts +252 -252
  46. package/src/{runtime → orm}/execute.ts +36 -36
  47. package/src/{runtime → orm}/hydration.ts +103 -103
  48. package/src/orm/identity-map.ts +37 -0
  49. package/src/{runtime → orm}/lazy-batch.ts +205 -205
  50. package/src/orm/orm-context.ts +154 -0
  51. package/src/orm/relation-change-processor.ts +140 -0
  52. package/src/{runtime → orm}/relations/belongs-to.ts +92 -92
  53. package/src/{runtime → orm}/relations/has-many.ts +111 -111
  54. package/src/{runtime → orm}/relations/many-to-many.ts +149 -149
  55. package/src/orm/runtime-types.ts +39 -0
  56. package/src/orm/transaction-runner.ts +17 -0
  57. package/src/orm/unit-of-work.ts +232 -0
  58. package/src/{builder/operations → query-builder}/column-selector.ts +78 -78
  59. package/src/{builder → query-builder}/delete-query-state.ts +38 -42
  60. package/src/{builder → query-builder}/delete.ts +46 -57
  61. package/src/{builder → query-builder}/hydration-manager.ts +87 -87
  62. package/src/{builder → query-builder}/hydration-planner.ts +182 -182
  63. package/src/{builder → query-builder}/insert-query-state.ts +51 -62
  64. package/src/{builder → query-builder}/insert.ts +48 -59
  65. package/src/{builder → query-builder}/query-ast-service.ts +208 -226
  66. package/src/{utils → query-builder}/raw-column-parser.ts +32 -32
  67. package/src/{builder → query-builder}/relation-conditions.ts +112 -112
  68. package/src/{builder/operations → query-builder}/relation-manager.ts +82 -82
  69. package/src/{builder → query-builder}/relation-projection-helper.ts +101 -101
  70. package/src/{builder → query-builder}/relation-service.ts +284 -284
  71. package/src/{builder → query-builder}/relation-types.ts +21 -21
  72. package/src/{builder → query-builder}/relation-utils.ts +12 -12
  73. package/src/{builder → query-builder}/select-query-builder-deps.ts +112 -94
  74. package/src/{builder → query-builder}/select-query-state.ts +179 -179
  75. package/src/{builder → query-builder}/select.ts +78 -69
  76. package/src/{builder → query-builder}/update-query-state.ts +55 -59
  77. package/src/{builder → query-builder}/update.ts +50 -61
  78. package/src/schema/column.ts +25 -25
  79. package/src/schema/relation.ts +116 -116
  80. package/src/schema/table.ts +34 -34
  81. package/src/schema/types.ts +76 -76
  82. package/.github/workflows/publish-metal-orm.yml +0 -38
  83. package/ROADMAP.md +0 -125
  84. package/docs/CHANGES.md +0 -104
  85. package/docs/advanced-features.md +0 -176
  86. package/docs/api-reference.md +0 -31
  87. package/docs/dml-operations.md +0 -156
  88. package/docs/getting-started.md +0 -171
  89. package/docs/hydration.md +0 -115
  90. package/docs/index.md +0 -36
  91. package/docs/multi-dialect-support.md +0 -59
  92. package/docs/query-builder.md +0 -135
  93. package/docs/runtime.md +0 -105
  94. package/docs/schema-definition.md +0 -112
  95. package/metadata.json +0 -5
  96. package/playground/api/playground-api.ts +0 -94
  97. package/playground/index.html +0 -15
  98. package/playground/src/App.css +0 -1
  99. package/playground/src/App.tsx +0 -114
  100. package/playground/src/components/CodeDisplay.tsx +0 -43
  101. package/playground/src/components/QueryExecutor.tsx +0 -189
  102. package/playground/src/components/ResultsTable.tsx +0 -67
  103. package/playground/src/components/ResultsTabs.tsx +0 -105
  104. package/playground/src/components/ScenarioList.tsx +0 -56
  105. package/playground/src/components/logo.svg +0 -45
  106. package/playground/src/data/scenarios.ts +0 -2
  107. package/playground/src/main.tsx +0 -9
  108. package/playground/src/services/PlaygroundApiService.ts +0 -60
  109. package/postcss.config.cjs +0 -5
  110. package/sql_sql-ansi-cheatsheet-2025.md +0 -264
  111. package/src/ast/expression.ts +0 -658
  112. package/src/builder/operations/cte-manager.ts +0 -34
  113. package/src/builder/operations/filter-manager.ts +0 -68
  114. package/src/builder/operations/join-manager.ts +0 -36
  115. package/src/builder/operations/pagination-manager.ts +0 -36
  116. package/src/playground/features/playground/api/types.ts +0 -16
  117. package/src/playground/features/playground/clients/MockClient.ts +0 -17
  118. package/src/playground/features/playground/clients/SqliteClient.ts +0 -57
  119. package/src/playground/features/playground/common/IDatabaseClient.ts +0 -10
  120. package/src/playground/features/playground/data/scenarios/aggregation.ts +0 -36
  121. package/src/playground/features/playground/data/scenarios/basics.ts +0 -25
  122. package/src/playground/features/playground/data/scenarios/edge_cases.ts +0 -57
  123. package/src/playground/features/playground/data/scenarios/filtering.ts +0 -94
  124. package/src/playground/features/playground/data/scenarios/hydration.ts +0 -27
  125. package/src/playground/features/playground/data/scenarios/index.ts +0 -29
  126. package/src/playground/features/playground/data/scenarios/ordering.ts +0 -25
  127. package/src/playground/features/playground/data/scenarios/pagination.ts +0 -16
  128. package/src/playground/features/playground/data/scenarios/relationships.ts +0 -75
  129. package/src/playground/features/playground/data/scenarios/types.ts +0 -70
  130. package/src/playground/features/playground/data/schema.ts +0 -91
  131. package/src/playground/features/playground/data/seed.ts +0 -104
  132. package/src/playground/features/playground/services/QueryExecutionService.ts +0 -121
  133. package/src/runtime/orm-context.ts +0 -539
  134. package/tests/belongs-to-many.test.ts +0 -57
  135. package/tests/between.test.ts +0 -43
  136. package/tests/case-expression.test.ts +0 -58
  137. package/tests/complex-exists.test.ts +0 -230
  138. package/tests/cte.test.ts +0 -118
  139. package/tests/dml.test.ts +0 -206
  140. package/tests/exists.test.ts +0 -127
  141. package/tests/like.test.ts +0 -33
  142. package/tests/orm-runtime.test.ts +0 -254
  143. package/tests/postgres.test.ts +0 -30
  144. package/tests/right-join.test.ts +0 -89
  145. package/tests/subquery-having.test.ts +0 -193
  146. package/tests/window-function.test.ts +0 -151
  147. package/tsconfig.json +0 -30
  148. package/tsup.config.ts +0 -10
  149. package/vite.config.ts +0 -22
  150. package/vitest.config.ts +0 -14
  151. /package/src/{constants → core/sql}/sql.ts +0 -0
  152. /package/src/{runtime → orm}/als.ts +0 -0
  153. /package/src/{utils → query-builder}/relation-alias.ts +0 -0
@@ -1,151 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { SelectQueryBuilder } from '../src/builder/select';
3
- import { SqliteDialect } from '../src/dialect/sqlite';
4
- import { MySqlDialect } from '../src/dialect/mysql';
5
- import { SqlServerDialect } from '../src/dialect/mssql';
6
- import { PostgresDialect } from '../src/dialect/postgres';
7
- import { TableDef } from '../src/schema/table';
8
- import { rowNumber, rank, denseRank, lag, lead, ntile, firstValue, lastValue, windowFunction } from '../src/ast/expression';
9
-
10
- const table = (name: string): TableDef => ({ name, columns: {}, relations: {} });
11
- const col = (name: string, table?: string) => ({ type: 'Column', name, table: table || 'unknown' } as any);
12
- const lit = (value: any) => ({ type: 'Literal', value } as any);
13
-
14
- describe('Window Function Support', () => {
15
- const sqlite = new SqliteDialect();
16
- const mysql = new MySqlDialect();
17
- const mssql = new SqlServerDialect();
18
- const postgres = new PostgresDialect();
19
-
20
- it('should generate ROW_NUMBER() window function', () => {
21
- const users = table('users');
22
-
23
- const query = new SelectQueryBuilder(users)
24
- .select({
25
- id: col('id', 'users'),
26
- name: col('name', 'users'),
27
- row_num: rowNumber()
28
- });
29
-
30
- const expectedSqlite = 'SELECT "users"."id" AS "id", "users"."name" AS "name", ROW_NUMBER() OVER () AS "row_num" FROM "users";';
31
- const expectedMysql = 'SELECT `users`.`id` AS `id`, `users`.`name` AS `name`, ROW_NUMBER() OVER () AS `row_num` FROM `users`;';
32
- const expectedMssql = 'SELECT [users].[id] AS [id], [users].[name] AS [name], ROW_NUMBER() OVER () AS [row_num] FROM [users];';
33
- const expectedPostgres = 'SELECT "users"."id" AS "id", "users"."name" AS "name", ROW_NUMBER() OVER () AS "row_num" FROM "users";';
34
-
35
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
36
- expect(query.toSql(mysql)).toBe(expectedMysql);
37
- expect(query.toSql(mssql)).toBe(expectedMssql);
38
- expect(query.toSql(postgres)).toBe(expectedPostgres);
39
- });
40
-
41
- it('should generate RANK() with PARTITION BY and ORDER BY', () => {
42
- const orders = table('orders');
43
-
44
- const query = new SelectQueryBuilder(orders)
45
- .select({
46
- id: col('id', 'orders'),
47
- customer_id: col('customer_id', 'orders'),
48
- amount: col('amount', 'orders'),
49
- rank: windowFunction('RANK', [], [col('customer_id', 'orders')], [{ column: col('amount', 'orders'), direction: 'DESC' }])
50
- });
51
-
52
- const expectedSqlite = 'SELECT "orders"."id" AS "id", "orders"."customer_id" AS "customer_id", "orders"."amount" AS "amount", RANK() OVER (PARTITION BY "orders"."customer_id" ORDER BY "orders"."amount" DESC) AS "rank" FROM "orders";';
53
- const expectedMysql = 'SELECT `orders`.`id` AS `id`, `orders`.`customer_id` AS `customer_id`, `orders`.`amount` AS `amount`, RANK() OVER (PARTITION BY `orders`.`customer_id` ORDER BY `orders`.`amount` DESC) AS `rank` FROM `orders`;';
54
- const expectedMssql = 'SELECT [orders].[id] AS [id], [orders].[customer_id] AS [customer_id], [orders].[amount] AS [amount], RANK() OVER (PARTITION BY [orders].[customer_id] ORDER BY [orders].[amount] DESC) AS [rank] FROM [orders];';
55
- const expectedPostgres = 'SELECT "orders"."id" AS "id", "orders"."customer_id" AS "customer_id", "orders"."amount" AS "amount", RANK() OVER (PARTITION BY "orders"."customer_id" ORDER BY "orders"."amount" DESC) AS "rank" FROM "orders";';
56
-
57
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
58
- expect(query.toSql(mysql)).toBe(expectedMysql);
59
- expect(query.toSql(mssql)).toBe(expectedMssql);
60
- expect(query.toSql(postgres)).toBe(expectedPostgres);
61
- });
62
-
63
- it('should generate LAG function with offset and default value', () => {
64
- const sales = table('sales');
65
-
66
- const query = new SelectQueryBuilder(sales)
67
- .select({
68
- date: col('date', 'sales'),
69
- amount: col('amount', 'sales'),
70
- prev_amount: lag(col('amount', 'sales'), 1, 0)
71
- });
72
-
73
- const expectedSqlite = 'SELECT "sales"."date" AS "date", "sales"."amount" AS "amount", LAG("sales"."amount", ?, ?) OVER () AS "prev_amount" FROM "sales";';
74
- const expectedMysql = 'SELECT `sales`.`date` AS `date`, `sales`.`amount` AS `amount`, LAG(`sales`.`amount`, ?, ?) OVER () AS `prev_amount` FROM `sales`;';
75
- const expectedMssql = 'SELECT [sales].[date] AS [date], [sales].[amount] AS [amount], LAG([sales].[amount], @p1, @p2) OVER () AS [prev_amount] FROM [sales];';
76
- const expectedPostgres = 'SELECT "sales"."date" AS "date", "sales"."amount" AS "amount", LAG("sales"."amount", ?, ?) OVER () AS "prev_amount" FROM "sales";';
77
-
78
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
79
- expect(query.toSql(mysql)).toBe(expectedMysql);
80
- expect(query.toSql(mssql)).toBe(expectedMssql);
81
- expect(query.toSql(postgres)).toBe(expectedPostgres);
82
- });
83
-
84
- it('should generate LEAD function', () => {
85
- const sales = table('sales');
86
-
87
- const query = new SelectQueryBuilder(sales)
88
- .select({
89
- date: col('date', 'sales'),
90
- amount: col('amount', 'sales'),
91
- next_amount: lead(col('amount', 'sales'), 1)
92
- });
93
-
94
- const expectedSqlite = 'SELECT "sales"."date" AS "date", "sales"."amount" AS "amount", LEAD("sales"."amount", ?) OVER () AS "next_amount" FROM "sales";';
95
- const expectedMysql = 'SELECT `sales`.`date` AS `date`, `sales`.`amount` AS `amount`, LEAD(`sales`.`amount`, ?) OVER () AS `next_amount` FROM `sales`;';
96
- const expectedMssql = 'SELECT [sales].[date] AS [date], [sales].[amount] AS [amount], LEAD([sales].[amount], @p1) OVER () AS [next_amount] FROM [sales];';
97
- const expectedPostgres = 'SELECT "sales"."date" AS "date", "sales"."amount" AS "amount", LEAD("sales"."amount", ?) OVER () AS "next_amount" FROM "sales";';
98
-
99
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
100
- expect(query.toSql(mysql)).toBe(expectedMysql);
101
- expect(query.toSql(mssql)).toBe(expectedMssql);
102
- expect(query.toSql(postgres)).toBe(expectedPostgres);
103
- });
104
-
105
- it('should generate window function with both PARTITION BY and ORDER BY', () => {
106
- const employees = table('employees');
107
-
108
- const query = new SelectQueryBuilder(employees)
109
- .select({
110
- id: col('id', 'employees'),
111
- name: col('name', 'employees'),
112
- department: col('department', 'employees'),
113
- salary: col('salary', 'employees'),
114
- dept_rank: windowFunction('ROW_NUMBER', [], [col('department', 'employees')], [{ column: col('salary', 'employees'), direction: 'DESC' }])
115
- });
116
-
117
- const expectedSqlite = 'SELECT "employees"."id" AS "id", "employees"."name" AS "name", "employees"."department" AS "department", "employees"."salary" AS "salary", ROW_NUMBER() OVER (PARTITION BY "employees"."department" ORDER BY "employees"."salary" DESC) AS "dept_rank" FROM "employees";';
118
- const expectedMysql = 'SELECT `employees`.`id` AS `id`, `employees`.`name` AS `name`, `employees`.`department` AS `department`, `employees`.`salary` AS `salary`, ROW_NUMBER() OVER (PARTITION BY `employees`.`department` ORDER BY `employees`.`salary` DESC) AS `dept_rank` FROM `employees`;';
119
- const expectedMssql = 'SELECT [employees].[id] AS [id], [employees].[name] AS [name], [employees].[department] AS [department], [employees].[salary] AS [salary], ROW_NUMBER() OVER (PARTITION BY [employees].[department] ORDER BY [employees].[salary] DESC) AS [dept_rank] FROM [employees];';
120
- const expectedPostgres = 'SELECT "employees"."id" AS "id", "employees"."name" AS "name", "employees"."department" AS "department", "employees"."salary" AS "salary", ROW_NUMBER() OVER (PARTITION BY "employees"."department" ORDER BY "employees"."salary" DESC) AS "dept_rank" FROM "employees";';
121
-
122
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
123
- expect(query.toSql(mysql)).toBe(expectedMysql);
124
- expect(query.toSql(mssql)).toBe(expectedMssql);
125
- expect(query.toSql(postgres)).toBe(expectedPostgres);
126
- });
127
-
128
- it('should generate multiple window functions in one query', () => {
129
- const employees = table('employees');
130
-
131
- const query = new SelectQueryBuilder(employees)
132
- .select({
133
- id: col('id', 'employees'),
134
- name: col('name', 'employees'),
135
- salary: col('salary', 'employees'),
136
- row_num: rowNumber(),
137
- rank: rank(),
138
- dense_rank: denseRank()
139
- });
140
-
141
- const expectedSqlite = 'SELECT "employees"."id" AS "id", "employees"."name" AS "name", "employees"."salary" AS "salary", ROW_NUMBER() OVER () AS "row_num", RANK() OVER () AS "rank", DENSE_RANK() OVER () AS "dense_rank" FROM "employees";';
142
- const expectedMysql = 'SELECT `employees`.`id` AS `id`, `employees`.`name` AS `name`, `employees`.`salary` AS `salary`, ROW_NUMBER() OVER () AS `row_num`, RANK() OVER () AS `rank`, DENSE_RANK() OVER () AS `dense_rank` FROM `employees`;';
143
- const expectedMssql = 'SELECT [employees].[id] AS [id], [employees].[name] AS [name], [employees].[salary] AS [salary], ROW_NUMBER() OVER () AS [row_num], RANK() OVER () AS [rank], DENSE_RANK() OVER () AS [dense_rank] FROM [employees];';
144
- const expectedPostgres = 'SELECT "employees"."id" AS "id", "employees"."name" AS "name", "employees"."salary" AS "salary", ROW_NUMBER() OVER () AS "row_num", RANK() OVER () AS "rank", DENSE_RANK() OVER () AS "dense_rank" FROM "employees";';
145
-
146
- expect(query.toSql(sqlite)).toBe(expectedSqlite);
147
- expect(query.toSql(mysql)).toBe(expectedMysql);
148
- expect(query.toSql(mssql)).toBe(expectedMssql);
149
- expect(query.toSql(postgres)).toBe(expectedPostgres);
150
- });
151
- });
package/tsconfig.json DELETED
@@ -1,30 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "experimentalDecorators": true,
5
- "useDefineForClassFields": false,
6
- "module": "ESNext",
7
- "lib": [
8
- "DOM",
9
- "DOM.Iterable",
10
- "ES2022"
11
- ],
12
- "jsx": "react-jsx",
13
- "skipLibCheck": true,
14
- "types": [
15
- "node"
16
- ],
17
- "moduleResolution": "bundler",
18
- "isolatedModules": true,
19
- "moduleDetection": "force",
20
- "allowJs": true,
21
- "baseUrl": "./src",
22
- "paths": {
23
- "@orm/*": [
24
- "./*"
25
- ]
26
- },
27
- "allowImportingTsExtensions": true,
28
- "noEmit": true
29
- }
30
- }
package/tsup.config.ts DELETED
@@ -1,10 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['cjs', 'esm'],
6
- dts: true,
7
- splitting: false,
8
- sourcemap: true,
9
- clean: true,
10
- });
package/vite.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import 'tsconfig-paths/register';
2
- import { defineConfig } from 'vite';
3
- import react from '@vitejs/plugin-react';
4
- import path from 'path';
5
- import { fileURLToPath } from 'url';
6
- import { playgroundApiPlugin } from './playground/api/playground-api';
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
-
10
- export default defineConfig({
11
- plugins: [
12
- react(),
13
- playgroundApiPlugin(),
14
- ],
15
- resolve: {
16
- alias: {
17
- '@orm': path.resolve(__dirname, './src'),
18
- 'playground': path.resolve(__dirname, './playground'),
19
- },
20
- },
21
- root: './playground',
22
- });
package/vitest.config.ts DELETED
@@ -1,14 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
- import path from 'path';
3
-
4
- export default defineConfig({
5
- test: {
6
- globals: true,
7
- environment: 'node',
8
- },
9
- resolve: {
10
- alias: {
11
- '@': path.resolve(__dirname, './src'),
12
- },
13
- },
14
- });
File without changes
File without changes
File without changes