orchid-orm 1.5.29 → 1.5.31

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 (59) hide show
  1. package/dist/index.d.ts +6 -14
  2. package/dist/index.js +26 -21
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +26 -21
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +12 -22
  7. package/.env.example +0 -1
  8. package/.turbo/turbo-check.log +0 -26
  9. package/.turbo/turbo-test.log +0 -26
  10. package/.turbo/turbo-test:ci.log +0 -26
  11. package/CHANGELOG.md +0 -382
  12. package/coverage/coverage-summary.json +0 -28
  13. package/jest-setup.ts +0 -11
  14. package/rollup.config.js +0 -18
  15. package/src/bin/bin.ts +0 -3
  16. package/src/bin/init.test.ts +0 -810
  17. package/src/bin/init.ts +0 -529
  18. package/src/codegen/appCodeUpdater.test.ts +0 -75
  19. package/src/codegen/appCodeUpdater.ts +0 -53
  20. package/src/codegen/createBaseTableFile.test.ts +0 -53
  21. package/src/codegen/createBaseTableFile.ts +0 -31
  22. package/src/codegen/fileChanges.ts +0 -41
  23. package/src/codegen/testUtils.ts +0 -56
  24. package/src/codegen/tsUtils.ts +0 -180
  25. package/src/codegen/updateMainFile.test.ts +0 -253
  26. package/src/codegen/updateMainFile.ts +0 -210
  27. package/src/codegen/updateTableFile/changeTable.test.ts +0 -804
  28. package/src/codegen/updateTableFile/changeTable.ts +0 -536
  29. package/src/codegen/updateTableFile/createTable.test.ts +0 -139
  30. package/src/codegen/updateTableFile/createTable.ts +0 -51
  31. package/src/codegen/updateTableFile/renameTable.test.ts +0 -124
  32. package/src/codegen/updateTableFile/renameTable.ts +0 -67
  33. package/src/codegen/updateTableFile/updateTableFile.ts +0 -22
  34. package/src/codegen/utils.ts +0 -13
  35. package/src/index.ts +0 -5
  36. package/src/orm.test.ts +0 -92
  37. package/src/orm.ts +0 -98
  38. package/src/relations/belongsTo.test.ts +0 -1122
  39. package/src/relations/belongsTo.ts +0 -352
  40. package/src/relations/hasAndBelongsToMany.test.ts +0 -1335
  41. package/src/relations/hasAndBelongsToMany.ts +0 -472
  42. package/src/relations/hasMany.test.ts +0 -2616
  43. package/src/relations/hasMany.ts +0 -401
  44. package/src/relations/hasOne.test.ts +0 -1701
  45. package/src/relations/hasOne.ts +0 -351
  46. package/src/relations/relations.test.ts +0 -37
  47. package/src/relations/relations.ts +0 -363
  48. package/src/relations/utils.ts +0 -162
  49. package/src/repo.test.ts +0 -200
  50. package/src/repo.ts +0 -119
  51. package/src/table.test.ts +0 -121
  52. package/src/table.ts +0 -184
  53. package/src/test-utils/test-db.ts +0 -32
  54. package/src/test-utils/test-tables.ts +0 -194
  55. package/src/test-utils/test-utils.ts +0 -119
  56. package/src/transaction.test.ts +0 -47
  57. package/src/transaction.ts +0 -27
  58. package/src/utils.ts +0 -9
  59. package/tsconfig.json +0 -14
package/src/repo.test.ts DELETED
@@ -1,200 +0,0 @@
1
- import { orchidORM } from './orm';
2
- import { pgConfig } from './test-utils/test-db';
3
- import { createBaseTable } from './table';
4
- import { assertType, expectSql } from './test-utils/test-utils';
5
- import { QueryReturnType } from 'pqb';
6
- import { createRepo } from './repo';
7
-
8
- const BaseTable = createBaseTable();
9
-
10
- class SomeTable extends BaseTable {
11
- table = 'someTable';
12
- columns = this.setColumns((t) => ({
13
- id: t.serial().primaryKey(),
14
- name: t.text(0, 100),
15
- }));
16
-
17
- relations = {
18
- other: this.hasMany(() => OtherTable, {
19
- primaryKey: 'id',
20
- foreignKey: 'someId',
21
- }),
22
- };
23
- }
24
-
25
- class OtherTable extends BaseTable {
26
- table = 'otherTable';
27
- columns = this.setColumns((t) => ({
28
- id: t.serial().primaryKey(),
29
- someId: t.integer().foreignKey(() => SomeTable, 'id'),
30
- anotherId: t.integer().foreignKey(() => AnotherTable, 'id'),
31
- }));
32
-
33
- relations = {
34
- some: this.belongsTo(() => SomeTable, {
35
- primaryKey: 'id',
36
- foreignKey: 'someId',
37
- }),
38
- another: this.belongsTo(() => AnotherTable, {
39
- primaryKey: 'id',
40
- foreignKey: 'anotherId',
41
- }),
42
- };
43
- }
44
-
45
- class AnotherTable extends BaseTable {
46
- table = 'another';
47
- columns = this.setColumns((t) => ({
48
- id: t.serial().primaryKey(),
49
- }));
50
- }
51
-
52
- const db = orchidORM(pgConfig, {
53
- some: SomeTable,
54
- other: OtherTable,
55
- another: AnotherTable,
56
- });
57
-
58
- describe('createRepo', () => {
59
- describe('queryMethods', () => {
60
- const repo = createRepo(db.some, {
61
- queryMethods: {
62
- one(q) {
63
- return q.select('id');
64
- },
65
- two(q) {
66
- return q.select('name');
67
- },
68
- three(q, id: number) {
69
- return q.where({ id });
70
- },
71
- },
72
- });
73
-
74
- it('should accept user defined methods and allow to use them on the table with chaining', async () => {
75
- const q = repo.one().two().three(123).take();
76
-
77
- assertType<Awaited<typeof q>, { id: number; name: string }>();
78
-
79
- expectSql(
80
- q.toSql(),
81
- `
82
- SELECT "someTable"."id", "someTable"."name"
83
- FROM "someTable"
84
- WHERE "someTable"."id" = $1
85
- LIMIT $2
86
- `,
87
- [123, 1],
88
- );
89
- });
90
-
91
- it('should have custom methods on relation queries inside of select', async () => {
92
- const q = db.other.select('id', {
93
- some: (q) => repo(q.some).one().two().three(123),
94
- });
95
-
96
- assertType<
97
- Awaited<typeof q>,
98
- { id: number; some: { id: number; name: string } | null }[]
99
- >();
100
-
101
- expectSql(
102
- q.toSql(),
103
- `
104
- SELECT
105
- "otherTable"."id",
106
- (
107
- SELECT row_to_json("t".*)
108
- FROM (
109
- SELECT "some"."id", "some"."name"
110
- FROM "someTable" AS "some"
111
- WHERE "some"."id" = $1
112
- AND "some"."id" = "otherTable"."someId"
113
- LIMIT $2
114
- ) AS "t"
115
- ) AS "some"
116
- FROM "otherTable"
117
- `,
118
- [123, 1],
119
- );
120
- });
121
- });
122
-
123
- describe('queryOneMethods', () => {
124
- const repo = createRepo(db.some, {
125
- queryOneMethods: {
126
- one(q) {
127
- const type: Exclude<QueryReturnType, 'all'> = q.returnType;
128
- return type;
129
- },
130
- },
131
- });
132
-
133
- it('should define methods which are available only after .take, .find, or similar', () => {
134
- // @ts-expect-error should prevent using method on query which returns multiple
135
- repo.one();
136
-
137
- repo.take().one();
138
- repo.find(1).one();
139
- });
140
- });
141
-
142
- describe('queryWithWhereMethods', () => {
143
- const repo = createRepo(db.some, {
144
- queryWithWhereMethods: {
145
- one(q) {
146
- const hasWhere: true = q.hasWhere;
147
- return hasWhere;
148
- },
149
- },
150
- });
151
-
152
- it('should define methods which are available only after .where, .find, or similar', () => {
153
- // @ts-expect-error should prevent using method on query without where conditions
154
- repo.one();
155
- // @ts-expect-error should prevent using method on query without where conditions
156
- repo.take().one();
157
-
158
- repo.where().one();
159
- repo.find(1).one();
160
- });
161
- });
162
-
163
- describe('queryOneWithWhere', () => {
164
- const repo = createRepo(db.some, {
165
- queryOneWithWhereMethods: {
166
- one(q) {
167
- const type: Exclude<QueryReturnType, 'all'> = q.returnType;
168
- const hasWhere: true = q.hasWhere;
169
- return [type, hasWhere];
170
- },
171
- },
172
- });
173
-
174
- it('should define methods which are available only after .where, .find, or similar', () => {
175
- // @ts-expect-error should prevent using method on query without where conditions
176
- repo.one();
177
- // @ts-expect-error should prevent using method on query without where conditions
178
- repo.take().one();
179
-
180
- // @ts-expect-error should prevent using method on query which returns multiple
181
- repo.where().one();
182
-
183
- repo.find(1).one();
184
- });
185
- });
186
-
187
- describe('methods', () => {
188
- const repo = createRepo(db.some, {
189
- methods: {
190
- one(a: number, b: string) {
191
- return a + b;
192
- },
193
- },
194
- });
195
-
196
- it('should assign methods as is to the repo', () => {
197
- expect(repo.take().one(1, '2')).toBe('12');
198
- });
199
- });
200
- });
package/src/repo.ts DELETED
@@ -1,119 +0,0 @@
1
- import {
2
- EmptyObject,
3
- getClonedQueryData,
4
- MergeQuery,
5
- Query,
6
- QueryReturnType,
7
- SetQueryReturns,
8
- WhereResult,
9
- } from 'pqb';
10
-
11
- export type QueryMethods<T extends Query> = Record<
12
- string,
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- (q: T, ...args: any[]) => any
15
- >;
16
-
17
- type QueryOne<T extends Query> = SetQueryReturns<
18
- T,
19
- Exclude<QueryReturnType, 'all'>
20
- >;
21
-
22
- export type MethodsBase<T extends Query> = {
23
- queryMethods?: QueryMethods<T>;
24
- queryOneMethods?: QueryMethods<QueryOne<T>>;
25
- queryWithWhereMethods?: QueryMethods<WhereResult<T>>;
26
- queryOneWithWhereMethods?: QueryMethods<QueryOne<WhereResult<T>>>;
27
- methods?: Record<string, unknown>;
28
- };
29
-
30
- export type MapQueryMethods<
31
- T extends Query,
32
- BaseQuery extends Query,
33
- Methods,
34
- > = Methods extends QueryMethods<T>
35
- ? {
36
- [K in keyof Methods]: Methods[K] extends (
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- q: any,
39
- ...args: infer Args
40
- ) => // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
- infer Result
42
- ? <T extends BaseQuery>(
43
- this: T,
44
- ...args: Args
45
- ) => Result extends Query ? MergeQuery<T, Result> : Result
46
- : never;
47
- }
48
- : EmptyObject;
49
-
50
- export type MapMethods<
51
- T extends Query,
52
- Methods extends MethodsBase<T>,
53
- > = MapQueryMethods<T, Query, Methods['queryMethods']> &
54
- MapQueryMethods<QueryOne<T>, QueryOne<Query>, Methods['queryOneMethods']> &
55
- MapQueryMethods<
56
- WhereResult<T>,
57
- WhereResult<Query>,
58
- Methods['queryWithWhereMethods']
59
- > &
60
- MapQueryMethods<
61
- QueryOne<WhereResult<T>>,
62
- QueryOne<WhereResult<Query>>,
63
- Methods['queryOneWithWhereMethods']
64
- > &
65
- (Methods['methods'] extends Record<string, unknown>
66
- ? Methods['methods']
67
- : EmptyObject);
68
-
69
- export type Repo<
70
- T extends Query,
71
- Methods extends MethodsBase<T>,
72
- Mapped = MapMethods<T, Methods>,
73
- > = (<Q extends { table: T['table']; shape: T['shape'] }>(q: Q) => Q & Mapped) &
74
- T &
75
- Mapped;
76
-
77
- export const createRepo = <T extends Query, Methods extends MethodsBase<T>>(
78
- table: T,
79
- methods: Methods,
80
- ): Repo<T, Methods> => {
81
- const queryMethods = {
82
- ...methods.queryMethods,
83
- ...methods.queryOneMethods,
84
- ...methods.queryWithWhereMethods,
85
- ...methods.queryOneWithWhereMethods,
86
- };
87
-
88
- const plainMethods = methods.methods;
89
-
90
- const repo = (q: Query) => {
91
- const proto = Object.create(q.__table);
92
- proto.__table = proto;
93
- const result = Object.create(proto);
94
- result.query = getClonedQueryData(q.query);
95
-
96
- if (plainMethods) {
97
- Object.assign(proto.__table, plainMethods);
98
- }
99
-
100
- for (const key in queryMethods) {
101
- const method = queryMethods[key] as (...args: unknown[]) => unknown;
102
- (proto.__table as unknown as Record<string, unknown>)[key] = function (
103
- ...args: unknown[]
104
- ) {
105
- return method(this, ...args);
106
- };
107
- }
108
-
109
- return result;
110
- };
111
-
112
- const q = repo(table);
113
-
114
- return new Proxy(repo, {
115
- get(_, key) {
116
- return q[key];
117
- },
118
- }) as unknown as Repo<T, Methods>;
119
- };
package/src/table.test.ts DELETED
@@ -1,121 +0,0 @@
1
- import { createBaseTable } from './table';
2
- import { orchidORM } from './orm';
3
- import { adapter, db } from './test-utils/test-db';
4
- import { assertType, userData, useTestDatabase } from './test-utils/test-utils';
5
- import { ColumnType, Operators } from 'pqb';
6
- import { BaseTable } from './test-utils/test-tables';
7
-
8
- describe('table', () => {
9
- useTestDatabase();
10
-
11
- describe('overriding column types', () => {
12
- it('should have .raw with overridden types', () => {
13
- class Type extends ColumnType {
14
- dataType = 'type';
15
- operators = Operators.any;
16
- toCode() {
17
- return '';
18
- }
19
- }
20
- const type = new Type();
21
- const BaseTable = createBaseTable({ columnTypes: { type: () => type } });
22
- class UserTable extends BaseTable {
23
- table = 'user';
24
- columns = this.setColumns((t) => ({
25
- id: t.type().primaryKey(),
26
- createdAt: t.type(),
27
- }));
28
- }
29
-
30
- const { user } = orchidORM(
31
- { adapter },
32
- {
33
- user: UserTable,
34
- },
35
- );
36
-
37
- const value = user.raw((t) => t.type(), '');
38
-
39
- expect(value.__column).toBe(type);
40
- });
41
-
42
- it('should return date as string by default', async () => {
43
- await db.user.create(userData);
44
-
45
- const BaseTable = createBaseTable();
46
- class UserTable extends BaseTable {
47
- table = 'user';
48
- columns = this.setColumns((t) => ({
49
- id: t.serial().primaryKey(),
50
- createdAt: t.timestamp(),
51
- }));
52
- }
53
-
54
- const { user } = orchidORM(
55
- { adapter },
56
- {
57
- user: UserTable,
58
- },
59
- );
60
-
61
- const result = await user.get('createdAt');
62
- expect(typeof result).toBe('string');
63
-
64
- assertType<typeof result, string>();
65
- });
66
-
67
- it('should return date as Date when overridden', async () => {
68
- await db.user.create(userData);
69
-
70
- const BaseTable = createBaseTable({
71
- columnTypes: (t) => ({
72
- serial: t.serial,
73
- timestamp() {
74
- return t.timestamp().parse((input) => new Date(input));
75
- },
76
- }),
77
- });
78
-
79
- class UserTable extends BaseTable {
80
- table = 'user';
81
- columns = this.setColumns((t) => ({
82
- id: t.serial().primaryKey(),
83
- createdAt: t.timestamp(),
84
- }));
85
- }
86
-
87
- const { user } = orchidORM(
88
- { adapter },
89
- {
90
- user: UserTable,
91
- },
92
- );
93
-
94
- const result = await user.get('createdAt');
95
- expect(result instanceof Date).toBe(true);
96
-
97
- assertType<typeof result, Date>();
98
- });
99
- });
100
-
101
- describe('noPrimaryKey', () => {
102
- it('should allow to the table to not have a primary key', () => {
103
- class UserTable extends BaseTable {
104
- table = 'user';
105
- noPrimaryKey = true;
106
- columns = this.setColumns((t) => ({
107
- name: t.text(),
108
- }));
109
- }
110
-
111
- orchidORM(
112
- {
113
- adapter,
114
- },
115
- {
116
- user: UserTable,
117
- },
118
- );
119
- });
120
- });
121
- });
package/src/table.ts DELETED
@@ -1,184 +0,0 @@
1
- import {
2
- ColumnShapeOutput,
3
- ColumnsShape,
4
- columnTypes,
5
- ColumnTypesBase,
6
- Db,
7
- DefaultColumnTypes,
8
- getColumnTypes,
9
- Query,
10
- } from 'pqb';
11
- import { MapRelations, Relation, RelationThunks } from './relations/relations';
12
- import { OrchidORM } from './orm';
13
-
14
- export type TableClass<T extends Table = Table> = new () => T;
15
-
16
- export type TableClasses = Record<string, TableClass>;
17
-
18
- export type TableToDb<T extends Table> = Db<
19
- T['table'],
20
- T['columns']['shape'],
21
- 'relations' extends keyof T
22
- ? T['relations'] extends RelationThunks
23
- ? {
24
- [K in keyof T['relations']]: Relation<T, T['relations'], K>;
25
- }
26
- : Query['relations']
27
- : Query['relations'],
28
- T['columnTypes']
29
- > & { definedAs: string; db: OrchidORM<TableClasses> };
30
-
31
- export type DbTable<T extends TableClass> = TableToDb<InstanceType<T>> &
32
- Omit<MapRelations<InstanceType<T>>, keyof Query>;
33
-
34
- type TableConfig = {
35
- shape: ColumnsShape;
36
- type: unknown;
37
- };
38
-
39
- type ScopeFn<Related extends TableClass, Scope extends Query> = (
40
- q: DbTable<Related>,
41
- ) => Scope;
42
-
43
- export type Table = {
44
- table: string;
45
- columns: TableConfig;
46
- schema?: string;
47
- columnTypes: ColumnTypesBase;
48
- noPrimaryKey?: boolean;
49
- };
50
-
51
- export const createBaseTable = <CT extends ColumnTypesBase>(
52
- options: {
53
- columnTypes?: CT | ((t: DefaultColumnTypes) => CT);
54
- } = { columnTypes: columnTypes as unknown as CT },
55
- ) => {
56
- const ct =
57
- typeof options.columnTypes === 'function'
58
- ? options.columnTypes(columnTypes)
59
- : options.columnTypes;
60
-
61
- return create(ct as ColumnTypesBase extends CT ? DefaultColumnTypes : CT);
62
- };
63
-
64
- const create = <CT extends ColumnTypesBase>(columnTypes: CT) => {
65
- return class BaseTable {
66
- table!: string;
67
- columns!: TableConfig;
68
- schema?: string;
69
- columnTypes: CT;
70
- noPrimaryKey?: boolean;
71
-
72
- constructor() {
73
- this.columnTypes = columnTypes;
74
- }
75
-
76
- setColumns = <T extends ColumnsShape>(
77
- fn: (t: CT) => T,
78
- ): { shape: T; type: ColumnShapeOutput<T> } => {
79
- const shape = getColumnTypes(columnTypes, fn);
80
-
81
- return {
82
- shape,
83
- type: undefined as unknown as ColumnShapeOutput<T>,
84
- };
85
- };
86
-
87
- belongsTo<
88
- Self extends this,
89
- Related extends TableClass,
90
- Scope extends Query,
91
- Options extends {
92
- primaryKey: keyof InstanceType<Related>['columns']['shape'];
93
- foreignKey: keyof Self['columns']['shape'];
94
- scope?: ScopeFn<Related, Scope>;
95
- required?: boolean;
96
- },
97
- >(this: Self, fn: () => Related, options: Options) {
98
- return {
99
- type: 'belongsTo' as const,
100
- returns: 'one' as const,
101
- fn,
102
- options,
103
- };
104
- }
105
-
106
- hasOne<
107
- Self extends this,
108
- Related extends TableClass,
109
- Scope extends Query,
110
- Through extends string,
111
- Source extends string,
112
- Options extends (
113
- | {
114
- primaryKey: keyof Self['columns']['shape'];
115
- foreignKey: keyof InstanceType<Related>['columns']['shape'];
116
- }
117
- | {
118
- through: Through;
119
- source: Source;
120
- }
121
- ) & {
122
- scope?: ScopeFn<Related, Scope>;
123
- required?: boolean;
124
- },
125
- >(this: Self, fn: () => Related, options: Options) {
126
- return {
127
- type: 'hasOne' as const,
128
- returns: 'one' as const,
129
- fn,
130
- options,
131
- };
132
- }
133
-
134
- hasMany<
135
- Self extends this,
136
- Related extends TableClass,
137
- Scope extends Query,
138
- Through extends string,
139
- Source extends string,
140
- Options extends (
141
- | {
142
- primaryKey: keyof Self['columns']['shape'];
143
- foreignKey: keyof InstanceType<Related>['columns']['shape'];
144
- }
145
- | {
146
- through: Through;
147
- source: Source;
148
- }
149
- ) & {
150
- scope?: ScopeFn<Related, Scope>;
151
- required?: boolean;
152
- },
153
- >(this: Self, fn: () => Related, options: Options) {
154
- return {
155
- type: 'hasMany' as const,
156
- returns: 'many' as const,
157
- fn,
158
- options,
159
- };
160
- }
161
-
162
- hasAndBelongsToMany<
163
- Self extends this,
164
- Related extends TableClass,
165
- Scope extends Query,
166
- Options extends {
167
- primaryKey: keyof Self['columns']['shape'];
168
- associationPrimaryKey: keyof InstanceType<Related>['columns']['shape'];
169
- foreignKey: string;
170
- associationForeignKey: string;
171
- joinTable: string;
172
- scope?: ScopeFn<Related, Scope>;
173
- required?: boolean;
174
- },
175
- >(this: Self, fn: () => Related, options: Options) {
176
- return {
177
- type: 'hasAndBelongsToMany' as const,
178
- returns: 'many' as const,
179
- fn,
180
- options,
181
- };
182
- }
183
- };
184
- };
@@ -1,32 +0,0 @@
1
- import { orchidORM } from '../orm';
2
- import {
3
- ChatTable,
4
- MessageTable,
5
- PostTable,
6
- PostTagTable,
7
- ProfileTable,
8
- TagTable,
9
- UserTable,
10
- } from './test-tables';
11
-
12
- export const pgConfig = {
13
- databaseURL: process.env.DATABASE_URL,
14
- };
15
-
16
- export const db = orchidORM(
17
- {
18
- ...pgConfig,
19
- log: false,
20
- },
21
- {
22
- user: UserTable,
23
- profile: ProfileTable,
24
- chat: ChatTable,
25
- message: MessageTable,
26
- post: PostTable,
27
- postTag: PostTagTable,
28
- tag: TagTable,
29
- },
30
- );
31
-
32
- export const adapter = db.$adapter;