Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 80eb234

Browse files
committed
fix: code review feedback
1 parent 2a9ca93 commit 80eb234

14 files changed

Lines changed: 83 additions & 107 deletions

File tree

packages/language/src/generated/ast.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,10 @@ export function isRegularID(item: unknown): item is RegularID {
158158
return item === 'model' || item === 'enum' || item === 'attribute' || item === 'datasource' || item === 'plugin' || item === 'abstract' || item === 'in' || item === 'view' || item === 'import' || item === 'type' || (typeof item === 'string' && (/[_a-zA-Z][\w_]*/.test(item)));
159159
}
160160

161-
export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Undefined' | 'Unsupported' | 'Void' | RegularID;
161+
export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Unsupported' | 'Void' | RegularID;
162162

163163
export function isRegularIDWithTypeNames(item: unknown): item is RegularIDWithTypeNames {
164-
return isRegularID(item) || item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Undefined' || item === 'Unsupported';
164+
return isRegularID(item) || item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Unsupported';
165165
}
166166

167167
export type TypeDeclaration = DataModel | Enum | TypeDef;

packages/language/src/generated/grammar.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,10 +3161,6 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
31613161
"$type": "Keyword",
31623162
"value": "Void"
31633163
},
3164-
{
3165-
"$type": "Keyword",
3166-
"value": "Undefined"
3167-
},
31683164
{
31693165
"$type": "Keyword",
31703166
"value": "Unsupported"
Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ValidationAcceptor } from 'langium';
2-
import type { Procedure, ProcedureParam } from '../generated/ast';
2+
import type { Procedure } from '../generated/ast';
33
import { validateAttributeApplication } from './attribute-application-validator';
44
import type { AstValidator } from './common';
55

@@ -15,8 +15,6 @@ const RESERVED_PROCEDURE_NAMES = new Set([
1515
export default class ProcedureValidator implements AstValidator<Procedure> {
1616
validate(proc: Procedure, accept: ValidationAcceptor): void {
1717
this.validateName(proc, accept);
18-
this.validateParams(proc, accept);
19-
this.validateReturnType(proc, accept);
2018
proc.attributes.forEach((attr) => validateAttributeApplication(attr, accept));
2119
}
2220

@@ -28,28 +26,4 @@ export default class ProcedureValidator implements AstValidator<Procedure> {
2826
});
2927
}
3028
}
31-
32-
private validateParams(proc: Procedure, accept: ValidationAcceptor): void {
33-
proc.params.forEach((param) => this.validateParamType(param, accept));
34-
}
35-
36-
private validateParamType(param: ProcedureParam, accept: ValidationAcceptor): void {
37-
const typeRef = param.type.reference;
38-
if (typeRef && !typeRef.ref) {
39-
accept('error', `Unknown type "${typeRef.$refText}"`, {
40-
node: param.type,
41-
property: 'reference',
42-
});
43-
}
44-
}
45-
46-
private validateReturnType(proc: Procedure, accept: ValidationAcceptor): void {
47-
const typeRef = proc.returnType.reference;
48-
if (typeRef && !typeRef.ref) {
49-
accept('error', `Unknown type "${typeRef.$refText}"`, {
50-
node: proc.returnType,
51-
property: 'reference',
52-
});
53-
}
54-
}
5529
}

packages/language/src/zmodel.langium

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ RegularID returns string:
234234
ID | 'model' | 'enum' | 'attribute' | 'datasource' | 'plugin' | 'abstract' | 'in' | 'view' | 'import' | 'type';
235235

236236
RegularIDWithTypeNames returns string:
237-
RegularID | 'String' | 'Boolean' | 'Int' | 'BigInt' | 'Float' | 'Decimal' | 'DateTime' | 'Json' | 'Bytes' | 'Null' | 'Object' | 'Any' | 'Void' | 'Undefined' | 'Unsupported';
237+
RegularID | 'String' | 'Boolean' | 'Int' | 'BigInt' | 'Float' | 'Decimal' | 'DateTime' | 'Json' | 'Bytes' | 'Null' | 'Object' | 'Any' | 'Void' | 'Unsupported';
238238

239239
// attribute
240240
Attribute:

packages/orm/src/client/client-impl.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,9 @@ export class ClientImpl {
248248

249249
const invokeWithClient = async (client: any, _input: unknown) => {
250250
let proceed = async (nextInput: unknown) => {
251-
// Handler signature: (client, input?)
252-
return handler.apply(client, [client, nextInput]);
251+
// Handler signature: (ctx)
252+
const args = nextInput && typeof nextInput === 'object' && 'args' in (nextInput as any) ? (nextInput as any).args : undefined;
253+
return handler({ client, args });
253254
};
254255

255256
// apply plugins

packages/orm/src/client/contract.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
type SchemaDef,
1313
} from '../schema';
1414
import type { AnyKysely } from '../utils/kysely-utils';
15-
import type { OrUndefinedIf, Simplify, UnwrapTuplePromises } from '../utils/type-utils';
15+
import type { MaybePromise, OrUndefinedIf, Simplify, UnwrapTuplePromises } from '../utils/type-utils';
1616
import type { TRANSACTION_UNSUPPORTED_METHODS } from './constants';
1717
import type {
1818
AggregateArgs,
@@ -297,16 +297,25 @@ type ProcedureCallParams<Schema extends SchemaDef, Params> = _HasRequiredProcedu
297297
? [input: ProcedureEnvelope<Schema, Params>]
298298
: [] | [input: ProcedureEnvelope<Schema, Params>];
299299

300+
type ProcedureArgs<Schema extends SchemaDef, Params> = _ProcedureParamNames<Params> extends never
301+
? Record<string, never>
302+
: MapProcedureArgsObject<Schema, Params>;
303+
304+
type ProcedureHandlerCtx<Schema extends SchemaDef, Params> = { client: ClientContract<Schema> } &
305+
(_HasRequiredProcedureParams<Params> extends true
306+
? { args: ProcedureArgs<Schema, Params> }
307+
: { args?: ProcedureArgs<Schema, Params> });
308+
300309
export type ProcedureFunc<Schema extends SchemaDef, Proc extends ProcedureDef> = (
301310
...args: ProcedureCallParams<Schema, Proc['params']>
302-
) => Promise<MapProcedureReturn<Schema, Proc>>;
311+
) => MaybePromise<MapProcedureReturn<Schema, Proc>>;
303312

304313
/**
305314
* Signature for procedure handlers configured via client options.
306315
*/
307316
export type ProcedureHandlerFunc<Schema extends SchemaDef, Proc extends ProcedureDef> = (
308-
...args: ProcedureCallParams<Schema, Proc['params']>
309-
) => Promise<MapProcedureReturn<Schema, Proc>>;
317+
ctx: ProcedureHandlerCtx<Schema, Proc['params']>
318+
) => MaybePromise<MapProcedureReturn<Schema, Proc>>;
310319

311320
type MapProcedureReturn<Schema extends SchemaDef, Proc extends ProcedureDef> = Proc extends { returnType: infer R }
312321
? Proc extends { returnArray: true }

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import {
4040
getEnum,
4141
getTypeDef,
4242
getUniqueFields,
43+
isEnum,
44+
isTypeDef,
4345
requireField,
4446
requireModel,
4547
} from '../../query-utils';
@@ -88,7 +90,7 @@ export class InputValidator<Schema extends SchemaDef> {
8890
throw createInvalidInputError('Missing procedure arguments', `$procs.${proc}`);
8991
}
9092

91-
if (!input || typeof input !== 'object' || Array.isArray(input)) {
93+
if (typeof input !== 'object' ) {
9294
throw createInvalidInputError('Procedure input must be an object', `$procs.${proc}`);
9395
}
9496

@@ -121,13 +123,6 @@ export class InputValidator<Schema extends SchemaDef> {
121123

122124
const obj = argsPayload as Record<string, unknown>;
123125

124-
// reject unknown keys to avoid silently ignoring user mistakes
125-
for (const key of Object.keys(obj)) {
126-
if (!params.some((p) => p.name === key)) {
127-
throw createInvalidInputError(`Unknown procedure argument: ${key}`, `$procs.${proc}`);
128-
}
129-
}
130-
131126
for (const param of params) {
132127
const value = (obj as any)[param.name];
133128

@@ -161,9 +156,9 @@ export class InputValidator<Schema extends SchemaDef> {
161156
private makeProcedureParamSchema(param: { type: string; array?: boolean; optional?: boolean }): z.ZodType {
162157
let schema: z.ZodType;
163158

164-
if (this.schema.typeDefs && param.type in this.schema.typeDefs) {
159+
if (isTypeDef(this.schema, param.type)) {
165160
schema = this.makeTypeDefSchema(param.type);
166-
} else if (this.schema.enums && param.type in this.schema.enums) {
161+
} else if (isEnum(this.schema, param.type)) {
167162
schema = this.makeEnumSchema(param.type);
168163
} else if (param.type in (this.schema.models ?? {})) {
169164
// For model-typed values, accept any object (no deep shape validation).

packages/orm/src/client/options.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,7 @@ export type ProceduresOptions<Schema extends SchemaDef> = Schema extends {
135135
procedures: Record<string, ProcedureDef>;
136136
}
137137
? {
138-
[Key in keyof Schema['procedures']]: PrependParameter<
139-
ClientContract<Schema>,
140-
ProcedureHandlerFunc<Schema, Schema['procedures'][Key]>
141-
>;
138+
[Key in keyof Schema['procedures']]: ProcedureHandlerFunc<Schema, Schema['procedures'][Key]>;
142139
}
143140
: {};
144141

packages/orm/src/client/plugin.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,17 @@ export type OnProcedureHookContext<Schema extends SchemaDef> = {
7777
mutation: boolean;
7878

7979
/**
80-
* Procedure invocation input (envelope).
81-
*
82-
* The canonical shape is `{ args?: Record<string, unknown> }`.
83-
* When a procedure has required params, `args` is required.
80+
* Procedure invocation input (envelope).
81+
*
82+
* The canonical shape is `{ args?: Record<string, unknown> }`.
83+
* When a procedure has required params, `args` is required.
8484
*/
85-
input: unknown;
85+
input: unknown;
8686

8787
/**
88-
* Continues the invocation. The input passed here is forwarded to the next handler.
88+
* Continues the invocation. The input passed here is forwarded to the next handler.
8989
*/
90-
proceed: (input: unknown) => Promise<unknown>;
90+
proceed: (input: unknown) => Promise<unknown>;
9191

9292
/**
9393
* The ZenStack client that is invoking the procedure.

packages/orm/test/procedures.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe('ORM procedures', () => {
2424
const client: any = new ZenStackClient(schema, {
2525
dialect: new SqliteDialect({ database: new SQLite(':memory:') }),
2626
procedures: {
27-
hello: async (_client: any) => 'ok',
27+
hello: async () => 'ok',
2828
},
2929
});
3030

@@ -77,7 +77,7 @@ describe('ORM procedures', () => {
7777
const client: any = new ZenStackClient(schema, {
7878
dialect: new SqliteDialect({ database: new SQLite(':memory:') }),
7979
procedures: {
80-
echoInt: async (_client: any, input: any) => input.args.n,
80+
echoInt: async ({ args }: any) => args.n,
8181
},
8282
});
8383

@@ -128,7 +128,7 @@ describe('ORM procedures', () => {
128128
dialect: new SqliteDialect({ database: new SQLite(':memory:') }),
129129
plugins: [p1, p2],
130130
procedures: {
131-
add: async (_client: any, input: any) => input.args.a + input.args.b,
131+
add: async ({ args }: any) => args.a + args.b,
132132
},
133133
});
134134

@@ -148,8 +148,8 @@ describe('ORM procedures', () => {
148148
const client: any = new ZenStackClient(schema, {
149149
dialect: new SqliteDialect({ database: new SQLite(':memory:') }),
150150
procedures: {
151-
mut: async (c: any) => c.isTransaction,
152-
qry: async (c: any) => c.isTransaction,
151+
mut: async ({ client }: any) => client.isTransaction,
152+
qry: async ({ client }: any) => client.isTransaction,
153153
},
154154
});
155155

0 commit comments

Comments
 (0)