Skip to content

Commit 95da8d2

Browse files
authored
feat(server): migrate rest api handler (#337)
* feat(server): migrate rest api handler * addressing PR comments * update lock file * fix pg string json handling * update
1 parent 9fe6f73 commit 95da8d2

File tree

18 files changed

+5479
-167
lines changed

18 files changed

+5479
-167
lines changed

BREAKINGCHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
1. `update` and `delete` policy rejection throws `NotFoundError`
22
1. `check()` ORM api has been removed
33
1. non-optional to-one relation doesn't automatically filter parent read when evaluating access policies
4+
1. `@omit` and `@password` attributes have been removed

packages/orm/src/utils/clone.ts renamed to packages/common-helpers/src/clone.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isPlainObject } from '@zenstackhq/common-helpers';
1+
import { isPlainObject } from './is-plain-object';
22

33
/**
44
* Clones the given object. Only arrays and plain objects are cloned. Other values are returned as is.
File renamed without changes.

packages/common-helpers/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export * from './clone';
2+
export * from './enumerable';
13
export * from './is-plain-object';
24
export * from './lower-case-first';
35
export * from './param-case';

packages/orm/src/client/crud/dialects/base-dialect.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { invariant, isPlainObject } from '@zenstackhq/common-helpers';
1+
import { enumerate, invariant, isPlainObject } from '@zenstackhq/common-helpers';
22
import type { Expression, ExpressionBuilder, ExpressionWrapper, SqlBool, ValueNode } from 'kysely';
33
import { expressionBuilder, sql, type SelectQueryBuilder } from 'kysely';
44
import { match, P } from 'ts-pattern';
55
import type { BuiltinType, DataSourceProviderType, FieldDef, GetModels, ModelDef, SchemaDef } from '../../../schema';
6-
import { enumerate } from '../../../utils/enumerate';
76
import type { OrArray } from '../../../utils/type-utils';
87
import { AGGREGATE_OPERATORS, DELEGATE_JOINED_FIELD_PREFIX, LOGICAL_COMBINATORS } from '../../constants';
98
import type {
@@ -755,7 +754,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
755754
: this.fieldRef(model, field, modelAlias);
756755
};
757756

758-
enumerate(orderBy).forEach((orderBy) => {
757+
enumerate(orderBy).forEach((orderBy, index) => {
759758
for (const [field, value] of Object.entries<any>(orderBy)) {
760759
if (!value) {
761760
continue;
@@ -841,15 +840,16 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
841840
}
842841
} else {
843842
// order by to-one relation
844-
result = result.leftJoin(relationModel, (join) => {
845-
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, relationModel);
843+
const joinAlias = `${modelAlias}$orderBy$${index}`;
844+
result = result.leftJoin(`${relationModel} as ${joinAlias}`, (join) => {
845+
const joinPairs = buildJoinPairs(this.schema, model, modelAlias, field, joinAlias);
846846
return join.on((eb) =>
847847
this.and(
848848
...joinPairs.map(([left, right]) => eb(this.eb.ref(left), '=', this.eb.ref(right))),
849849
),
850850
);
851851
});
852-
result = this.buildOrderBy(result, fieldDef.type, relationModel, value, negated);
852+
result = this.buildOrderBy(result, relationModel, joinAlias, value, negated);
853853
}
854854
}
855855
}

packages/orm/src/client/crud/dialects/postgresql.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDiale
5858
: value,
5959
)
6060
.with('Decimal', () => (value !== null ? value.toString() : value))
61+
.with('Json', () => {
62+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
63+
// postgres requires simple JSON values to be stringified
64+
return JSON.stringify(value);
65+
} else {
66+
return value;
67+
}
68+
})
6169
.otherwise(() => value);
6270
}
6371
}

packages/orm/src/client/crud/operations/base.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createId } from '@paralleldrive/cuid2';
2-
import { invariant, isPlainObject } from '@zenstackhq/common-helpers';
2+
import { clone, enumerate, invariant, isPlainObject } from '@zenstackhq/common-helpers';
33
import {
44
DeleteResult,
55
expressionBuilder,
@@ -17,8 +17,6 @@ import * as uuid from 'uuid';
1717
import type { ClientContract } from '../..';
1818
import type { BuiltinType, Expression, FieldDef } from '../../../schema';
1919
import { ExpressionUtils, type GetModels, type ModelDef, type SchemaDef } from '../../../schema';
20-
import { clone } from '../../../utils/clone';
21-
import { enumerate } from '../../../utils/enumerate';
2220
import { extractFields, fieldsToSelectObject } from '../../../utils/object-utils';
2321
import { NUMERIC_FIELD_TYPES } from '../../constants';
2422
import { TransactionIsolationLevel, type CRUD } from '../../contract';

packages/orm/src/client/crud/validator/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { invariant } from '@zenstackhq/common-helpers';
1+
import { enumerate, invariant } from '@zenstackhq/common-helpers';
22
import Decimal from 'decimal.js';
33
import stableStringify from 'json-stable-stringify';
44
import { match, P } from 'ts-pattern';
@@ -12,7 +12,6 @@ import {
1212
type ModelDef,
1313
type SchemaDef,
1414
} from '../../../schema';
15-
import { enumerate } from '../../../utils/enumerate';
1615
import { extractFields } from '../../../utils/object-utils';
1716
import { formatError } from '../../../utils/zod-utils';
1817
import { AGGREGATE_OPERATORS, LOGICAL_COMBINATORS, NUMERIC_FIELD_TYPES } from '../../constants';

packages/server/package.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@
5555
"@zenstackhq/orm": "workspace:*",
5656
"decimal.js": "catalog:",
5757
"superjson": "^2.2.3",
58-
"ts-pattern": "catalog:"
58+
"ts-japi": "^1.12.0",
59+
"ts-pattern": "catalog:",
60+
"url-pattern": "^1.0.3",
61+
"zod-validation-error": "catalog:"
5962
},
6063
"devDependencies": {
6164
"@types/body-parser": "^1.19.6",
@@ -66,13 +69,15 @@
6669
"@zenstackhq/typescript-config": "workspace:*",
6770
"@zenstackhq/vitest-config": "workspace:*",
6871
"body-parser": "^2.2.0",
69-
"supertest": "^7.1.4",
7072
"express": "^5.0.0",
71-
"next": "^15.0.0"
73+
"next": "^15.0.0",
74+
"supertest": "^7.1.4",
75+
"zod": "~3.25.0"
7276
},
7377
"peerDependencies": {
7478
"express": "^5.0.0",
75-
"next": "^15.0.0"
79+
"next": "^15.0.0",
80+
"zod": "catalog:"
7681
},
7782
"peerDependenciesMeta": {
7883
"express": {

packages/server/src/api/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export { RPCApiHandler } from './rpc';
1+
export { RestApiHandler, type RestApiHandlerOptions } from './rest';
2+
export { RPCApiHandler, type RPCApiHandlerOptions } from './rpc';

0 commit comments

Comments
 (0)