Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.

Commit fc50deb

Browse files
authored
feat: add "loadPath" options to runtime API and server adapter options (zenstackhq#696)
1 parent e8f7a2d commit fc50deb

File tree

35 files changed

+2286
-2037
lines changed

35 files changed

+2286
-2037
lines changed

packages/plugins/swr/tests/swr.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ ${sharedModel}
5858
{
5959
provider: 'postgresql',
6060
pushDb: false,
61-
extraDependencies: [`${origDir}/dist`, 'react', '@types/react', 'swr'],
61+
extraDependencies: [`${origDir}/dist`, 'react@18.2.0', '@types/react@18.2.0', 'swr@^2'],
6262
compile: true,
6363
}
6464
);

packages/runtime/src/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Default path for loading CLI-generated code
3+
*/
4+
export const DEFAULT_RUNTIME_LOAD_PATH = '.zenstack';
5+
16
/**
27
* Default length of password hash salt (used by bcryptjs to hash password)
38
*/

packages/runtime/src/enhancements/enhance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getDefaultModelMeta } from './model-meta';
1+
import { getDefaultModelMeta } from '../loader';
22
import { withOmit, WithOmitOptions } from './omit';
33
import { withPassword, WithPasswordOptions } from './password';
44
import { withPolicy, WithPolicyContext, WithPolicyOptions } from './policy';
@@ -29,7 +29,7 @@ export function enhance<DbClient extends object>(
2929
let result = prisma;
3030

3131
if (hasPassword === undefined || hasOmit === undefined) {
32-
const modelMeta = options?.modelMeta ?? getDefaultModelMeta();
32+
const modelMeta = options?.modelMeta ?? getDefaultModelMeta(options?.loadPath);
3333
const allFields = Object.values(modelMeta.fields).flatMap((modelInfo) => Object.values(modelInfo));
3434
hasPassword = allFields.some((field) => field.attributes?.some((attr) => attr.name === '@password'));
3535
hasOmit = allFields.some((field) => field.attributes?.some((attr) => attr.name === '@omit'));

packages/runtime/src/enhancements/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export * from './model-meta';
2-
export * from './nested-write-vistor';
2+
export * from './nested-write-visitor';
33
export * from './omit';
44
export * from './password';
55
export * from './policy';

packages/runtime/src/enhancements/model-meta.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,8 @@
11
/* eslint-disable @typescript-eslint/no-var-requires */
22
import { lowerCaseFirst } from 'lower-case-first';
3-
import path from 'path';
43
import { FieldInfo } from '../types';
54
import { ModelMeta } from './types';
65

7-
/**
8-
* Load model meta from standard location.
9-
*/
10-
export function getDefaultModelMeta(): ModelMeta {
11-
try {
12-
// normal load
13-
return require('.zenstack/model-meta').default;
14-
} catch {
15-
if (process.env.ZENSTACK_TEST === '1') {
16-
try {
17-
// special handling for running as tests, try resolving relative to CWD
18-
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'model-meta')).default;
19-
} catch {
20-
throw new Error('Model meta cannot be loaded. Please make sure "zenstack generate" has been run.');
21-
}
22-
}
23-
throw new Error('Model meta cannot be loaded. Please make sure "zenstack generate" has been run.');
24-
}
25-
}
26-
276
/**
287
* Resolves a model field to its metadata. Returns undefined if not found.
298
*/

packages/runtime/src/enhancements/omit.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
/* eslint-disable @typescript-eslint/no-unused-vars */
22
/* eslint-disable @typescript-eslint/no-explicit-any */
33

4+
import { getDefaultModelMeta } from '../loader';
45
import { DbClientContract } from '../types';
5-
import { getDefaultModelMeta, resolveField } from './model-meta';
6+
import { resolveField } from './model-meta';
67
import { DefaultPrismaProxyHandler, makeProxy } from './proxy';
7-
import { ModelMeta } from './types';
8+
import { CommonEnhancementOptions, ModelMeta } from './types';
89
import { enumerate, getModelFields } from './utils';
910

1011
/**
1112
* Options for @see withOmit
1213
*/
13-
export type WithOmitOptions = {
14+
export interface WithOmitOptions extends CommonEnhancementOptions {
1415
/**
1516
* Model metadata
1617
*/
1718
modelMeta?: ModelMeta;
18-
};
19+
}
1920

2021
/**
2122
* Gets an enhanced Prisma client that supports @omit attribute.
2223
*/
2324
export function withOmit<DbClient extends object>(prisma: DbClient, options?: WithOmitOptions): DbClient {
24-
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta();
25+
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta(options?.loadPath);
2526
return makeProxy(
2627
prisma,
2728
_modelMeta,

packages/runtime/src/enhancements/password.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@
33

44
import { hash } from 'bcryptjs';
55
import { DEFAULT_PASSWORD_SALT_LENGTH } from '../constants';
6+
import { getDefaultModelMeta } from '../loader';
67
import { DbClientContract, PrismaWriteActionType } from '../types';
7-
import { getDefaultModelMeta } from './model-meta';
8-
import { NestedWriteVisitor } from './nested-write-vistor';
8+
import { NestedWriteVisitor } from './nested-write-visitor';
99
import { DefaultPrismaProxyHandler, PrismaProxyActions, makeProxy } from './proxy';
10-
import { ModelMeta } from './types';
10+
import { CommonEnhancementOptions, ModelMeta } from './types';
1111

1212
/**
1313
* Options for @see withPassword
1414
*/
15-
export type WithPasswordOptions = {
15+
export interface WithPasswordOptions extends CommonEnhancementOptions {
1616
/**
17-
* Model metatadata
17+
* Model metadata
1818
*/
1919
modelMeta?: ModelMeta;
20-
};
20+
}
2121

2222
/**
2323
* Gets an enhanced Prisma client that supports @password attribute.
2424
*/
2525
export function withPassword<DbClient extends object = any>(prisma: DbClient, options?: WithPasswordOptions): DbClient {
26-
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta();
26+
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta(options?.loadPath);
2727
return makeProxy(
2828
prisma,
2929
_modelMeta,

packages/runtime/src/enhancements/policy/handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { CrudFailureReason, PRISMA_TX_FLAG } from '../../constants';
77
import { AuthUser, DbClientContract, DbOperations, FieldInfo, PolicyOperationKind } from '../../types';
88
import { ModelDataVisitor } from '../model-data-visitor';
99
import { resolveField } from '../model-meta';
10-
import { NestedWriteVisitor, NestedWriteVisitorContext } from '../nested-write-vistor';
10+
import { NestedWriteVisitor, NestedWriteVisitorContext } from '../nested-write-visitor';
1111
import { PrismaProxyHandler } from '../proxy';
1212
import type { ModelMeta, PolicyDef, ZodSchemas } from '../types';
1313
import { enumerate, formatObject, getIdFields, prismaClientValidationError } from '../utils';

packages/runtime/src/enhancements/policy/index.ts

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
/* eslint-disable @typescript-eslint/no-var-requires */
22
/* eslint-disable @typescript-eslint/no-explicit-any */
33

4-
import path from 'path';
54
import semver from 'semver';
65
import { PRISMA_MINIMUM_VERSION } from '../../constants';
6+
import { getDefaultModelMeta, getDefaultPolicy, getDefaultZodSchemas } from '../../loader';
77
import { AuthUser, DbClientContract } from '../../types';
88
import { hasAllFields } from '../../validation';
9-
import { getDefaultModelMeta } from '../model-meta';
109
import { makeProxy } from '../proxy';
11-
import type { ModelMeta, PolicyDef, ZodSchemas } from '../types';
10+
import type { CommonEnhancementOptions, ModelMeta, PolicyDef, ZodSchemas } from '../types';
1211
import { getIdFields } from '../utils';
1312
import { PolicyProxyHandler } from './handler';
1413

@@ -22,7 +21,7 @@ export type WithPolicyContext = {
2221
/**
2322
* Options for @see withPolicy
2423
*/
25-
export type WithPolicyOptions = {
24+
export interface WithPolicyOptions extends CommonEnhancementOptions {
2625
/**
2726
* Policy definition
2827
*/
@@ -42,7 +41,7 @@ export type WithPolicyOptions = {
4241
* Whether to log Prisma query
4342
*/
4443
logPrismaQuery?: boolean;
45-
};
44+
}
4645

4746
/**
4847
* Gets an enhanced Prisma client with access policy check.
@@ -68,9 +67,9 @@ export function withPolicy<DbClient extends object>(
6867
);
6968
}
7069

71-
const _policy = options?.policy ?? getDefaultPolicy();
72-
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta();
73-
const _zodSchemas = options?.zodSchemas ?? getDefaultZodSchemas();
70+
const _policy = options?.policy ?? getDefaultPolicy(options?.loadPath);
71+
const _modelMeta = options?.modelMeta ?? getDefaultModelMeta(options?.loadPath);
72+
const _zodSchemas = options?.zodSchemas ?? getDefaultZodSchemas(options?.loadPath);
7473

7574
// validate user context
7675
if (context?.user) {
@@ -103,40 +102,3 @@ export function withPolicy<DbClient extends object>(
103102
'policy'
104103
);
105104
}
106-
107-
function getDefaultPolicy(): PolicyDef {
108-
try {
109-
return require('.zenstack/policy').default;
110-
} catch {
111-
if (process.env.ZENSTACK_TEST === '1') {
112-
try {
113-
// special handling for running as tests, try resolving relative to CWD
114-
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'policy')).default;
115-
} catch {
116-
throw new Error(
117-
'Policy definition cannot be loaded from default location. Please make sure "zenstack generate" has been run.'
118-
);
119-
}
120-
}
121-
throw new Error(
122-
'Policy definition cannot be loaded from default location. Please make sure "zenstack generate" has been run.'
123-
);
124-
}
125-
}
126-
127-
function getDefaultZodSchemas(): ZodSchemas | undefined {
128-
try {
129-
// eslint-disable-next-line @typescript-eslint/no-var-requires
130-
return require('.zenstack/zod');
131-
} catch {
132-
if (process.env.ZENSTACK_TEST === '1') {
133-
try {
134-
// special handling for running as tests, try resolving relative to CWD
135-
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'zod'));
136-
} catch {
137-
return undefined;
138-
}
139-
}
140-
return undefined;
141-
}
142-
}

0 commit comments

Comments
 (0)