orchid-orm 1.5.28 → 1.5.30

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 (57) hide show
  1. package/dist/index.js +10 -10
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +10 -10
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +13 -22
  6. package/.env.example +0 -1
  7. package/.turbo/turbo-test.log +0 -26
  8. package/.turbo/turbo-test:ci.log +0 -26
  9. package/CHANGELOG.md +0 -375
  10. package/coverage/coverage-summary.json +0 -28
  11. package/jest-setup.ts +0 -11
  12. package/rollup.config.js +0 -18
  13. package/src/bin/bin.ts +0 -3
  14. package/src/bin/init.test.ts +0 -810
  15. package/src/bin/init.ts +0 -529
  16. package/src/codegen/appCodeUpdater.test.ts +0 -75
  17. package/src/codegen/appCodeUpdater.ts +0 -53
  18. package/src/codegen/createBaseTableFile.test.ts +0 -53
  19. package/src/codegen/createBaseTableFile.ts +0 -31
  20. package/src/codegen/fileChanges.ts +0 -41
  21. package/src/codegen/testUtils.ts +0 -56
  22. package/src/codegen/tsUtils.ts +0 -180
  23. package/src/codegen/updateMainFile.test.ts +0 -253
  24. package/src/codegen/updateMainFile.ts +0 -210
  25. package/src/codegen/updateTableFile/changeTable.test.ts +0 -804
  26. package/src/codegen/updateTableFile/changeTable.ts +0 -536
  27. package/src/codegen/updateTableFile/createTable.test.ts +0 -139
  28. package/src/codegen/updateTableFile/createTable.ts +0 -51
  29. package/src/codegen/updateTableFile/renameTable.test.ts +0 -124
  30. package/src/codegen/updateTableFile/renameTable.ts +0 -67
  31. package/src/codegen/updateTableFile/updateTableFile.ts +0 -22
  32. package/src/codegen/utils.ts +0 -13
  33. package/src/index.ts +0 -5
  34. package/src/orm.test.ts +0 -92
  35. package/src/orm.ts +0 -98
  36. package/src/relations/belongsTo.test.ts +0 -1122
  37. package/src/relations/belongsTo.ts +0 -352
  38. package/src/relations/hasAndBelongsToMany.test.ts +0 -1335
  39. package/src/relations/hasAndBelongsToMany.ts +0 -472
  40. package/src/relations/hasMany.test.ts +0 -2616
  41. package/src/relations/hasMany.ts +0 -401
  42. package/src/relations/hasOne.test.ts +0 -1701
  43. package/src/relations/hasOne.ts +0 -351
  44. package/src/relations/relations.test.ts +0 -37
  45. package/src/relations/relations.ts +0 -363
  46. package/src/relations/utils.ts +0 -162
  47. package/src/repo.test.ts +0 -200
  48. package/src/repo.ts +0 -119
  49. package/src/table.test.ts +0 -121
  50. package/src/table.ts +0 -184
  51. package/src/test-utils/test-db.ts +0 -32
  52. package/src/test-utils/test-tables.ts +0 -194
  53. package/src/test-utils/test-utils.ts +0 -119
  54. package/src/transaction.test.ts +0 -47
  55. package/src/transaction.ts +0 -27
  56. package/src/utils.ts +0 -9
  57. 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;