@zudojs/database 1.3.0 → 1.3.2

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.
package/README.md CHANGED
@@ -72,6 +72,11 @@ await withTransaction(client, async (tx) => {
72
72
  await client.disconnect();
73
73
  ```
74
74
 
75
+ A generated model delegate such as `prisma.user` is passed as-is, with no cast.
76
+ `RepositoryDelegate` accepts any Prisma-style delegate whose rows match the
77
+ entity type; `this.delegate` inside a subclass is typed with the arguments the
78
+ repository passes (`RepositoryDelegateOperations`).
79
+
75
80
  `createDatabaseClient` accepts either a pre-built `prisma` instance or an
76
81
  `adapter` (in which case it constructs the `PrismaClient` for you). It throws a
77
82
  `DatabaseError` if neither is supplied.
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { noopDatabaseLogger } from "./databaseType/index.js";
21
21
  export { DatabaseClient, DatabaseAbortError, createDatabaseClient, buildPrismaTransactionOptions, createAbortError, raceAbort, throwIfAborted, SUPPORTED_ISOLATION_LEVELS, normalizeDatabaseError, withDatabaseErrorMetadata, isPrismaError, isRetryableTransactionError, isConflictError, isNotFoundError, getDatabaseErrorCode, getDatabaseErrorKind, isDatabaseErrorLike, isNonDatabaseBaseError, toDatabaseErrorInfo, RETRYABLE_DATABASE_CODES, type DatabaseClientOptions, type DatabaseTransactionContext, type PrismaClientLike, type PrismaDriverAdapterLike, type PrismaQueryEvent, type PrismaTransactionOptions, type RawQueryOptions, type DatabaseErrorKind, type NormalizeDatabaseErrorOptions, type PrismaErrorLike, } from "./databaseClient/index.js";
22
22
  export { DatabaseConnectionManager, createConnectionManager, type DatabaseConnectionEvent, type DatabaseConnectionListener, type DatabaseConnectionEventDetails, type DatabaseConnectionManagerOptions, type DatabaseReconnectOptions, } from "./databaseConnection/index.js";
23
23
  export { Database, createDatabase, getDatabase, connectDatabase, disconnectDatabase, resetDatabase, } from "./database/index.js";
24
- export { BaseRepository, mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, type RepositoryDelegate, type BaseRepositoryOptions, type SoftDeleteOptions, type CursorQueryOptions, type TransactionClientLike, type RepositoryOperation, type RepositoryErrorContext, } from "./repository/index.js";
24
+ export { BaseRepository, mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, type RepositoryDelegate, type RepositoryDelegateOperations, type BaseRepositoryOptions, type SoftDeleteOptions, type CursorQueryOptions, type TransactionClientLike, type RepositoryOperation, type RepositoryErrorContext, } from "./repository/index.js";
25
25
  export { TransactionManager, createTransactionManager, withTransaction, withTransactionRetry, createTransactionContext, createTransactionId, getTransactionContextFromError, isTransactionActive, isTransactionCommitted, isTransactionFailed, type TransactionStatus, type TransactionContext, type TransactionOutcome, type TransactionRetryOptions, type ManagedTransactionOptions, } from "./transaction/index.js";
26
26
  export { DatabaseUnitOfWork, createUnitOfWork, executeUnitOfWork, type UnitOfWork, type UnitOfWorkOptions, } from "./unitOfWork/index.js";
27
27
  export { QueryBuilder, createQueryBuilder, toPrismaWhere, toPrismaArgs, toPrismaOrderBy, toPrismaSelect, toPrismaSkipTake, type QueryCondition, type QueryFilter, type QueryOperator, type RelationOperator, type QueryBuilderState, type PrismaWhere, type PrismaQueryArgs, type ToPrismaArgsOptions, } from "./queryBuilder/index.js";
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Generic repository pattern with Prisma delegate support.
5
5
  */
6
- export { BaseRepository, type RepositoryDelegate, type BaseRepositoryOptions, type SoftDeleteOptions, type CursorQueryOptions, type TransactionClientLike, } from "./repository.base.js";
6
+ export { BaseRepository, type BaseRepositoryOptions, type SoftDeleteOptions, type CursorQueryOptions, type TransactionClientLike, } from "./repository.base.js";
7
+ export { type RepositoryDelegate, type RepositoryDelegateOperations, } from "./repository.delegate.js";
7
8
  export { mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, toErrorMetadata, createAbortError, createTimeoutError, type RepositoryOperation, type RepositoryErrorContext, type PrismaErrorLike, } from "./repository.errors.js";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -4,5 +4,6 @@
4
4
  * Generic repository pattern with Prisma delegate support.
5
5
  */
6
6
  export { BaseRepository, } from "./repository.base.js";
7
+ export {} from "./repository.delegate.js";
7
8
  export { mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, toErrorMetadata, createAbortError, createTimeoutError, } from "./repository.errors.js";
8
9
  //# sourceMappingURL=index.js.map
@@ -3,59 +3,8 @@ import { type CursorPaginatedResult } from "../pagination/pagination.core.js";
3
3
  import type { QueryBuilder } from "../queryBuilder/queryBuilder.core.js";
4
4
  import type { QueryBuilderState } from "../queryBuilder/queryBuilder.type.js";
5
5
  import type { RelationLoadOptions, RelationRegistry } from "../relations/relations.definition.js";
6
+ import { type RepositoryDelegate, type RepositoryDelegateOperations } from "./repository.delegate.js";
6
7
  import { type RepositoryOperation } from "./repository.errors.js";
7
- /**
8
- * Generic Prisma-style delegate contract.
9
- *
10
- * This keeps the repository base class independent from generated
11
- * Prisma model types while still supporting standard CRUD operations.
12
- */
13
- export interface RepositoryDelegate<TEntity, TId = string, TCreateInput = Partial<TEntity>, TUpdateInput = Partial<TEntity>, TWhereInput = unknown> {
14
- findUnique(args: {
15
- where: unknown;
16
- }): Promise<TEntity | null>;
17
- findFirst(args: {
18
- where?: TWhereInput;
19
- orderBy?: unknown;
20
- select?: unknown;
21
- }): Promise<TEntity | null>;
22
- findMany(args?: {
23
- where?: TWhereInput;
24
- skip?: number;
25
- take?: number;
26
- orderBy?: unknown;
27
- select?: unknown;
28
- include?: unknown;
29
- }): Promise<readonly TEntity[]>;
30
- create(args: {
31
- data: TCreateInput;
32
- }): Promise<TEntity>;
33
- update(args: {
34
- where: unknown;
35
- data: TUpdateInput;
36
- }): Promise<TEntity>;
37
- delete(args: {
38
- where: unknown;
39
- }): Promise<TEntity>;
40
- count(args?: {
41
- where?: TWhereInput;
42
- }): Promise<number>;
43
- upsert?(args: {
44
- where: unknown;
45
- create: TCreateInput;
46
- update: TUpdateInput;
47
- }): Promise<TEntity>;
48
- createMany?(args: {
49
- data: readonly TCreateInput[];
50
- }): Promise<{
51
- count: number;
52
- }>;
53
- deleteMany?(args: {
54
- where?: TWhereInput;
55
- }): Promise<{
56
- count: number;
57
- }>;
58
- }
59
8
  /**
60
9
  * Soft-delete configuration.
61
10
  */
@@ -123,7 +72,7 @@ export type TransactionClientLike = Readonly<Record<string, unknown>>;
123
72
  * appropriate Prisma delegate plus any domain-specific behavior.
124
73
  */
125
74
  export declare abstract class BaseRepository<TEntity, TId = string, TCreateInput = Partial<TEntity>, TUpdateInput = Partial<TEntity>, TWhereInput = Record<string, unknown>> implements Repository<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>, SoftDeletableRepository<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput> {
126
- protected readonly delegate: RepositoryDelegate<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>;
75
+ protected readonly delegate: RepositoryDelegateOperations<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>;
127
76
  protected readonly modelName: string;
128
77
  protected readonly idField: string;
129
78
  protected readonly softDeleteField?: string;
@@ -3,6 +3,7 @@ import { createPaginationMeta, normalizeLimit, normalizePage, } from "../paginat
3
3
  import { buildKeysetWhere, createKeysetPage, decodeKeysetCursor, } from "../pagination/pagination.keyset.js";
4
4
  import { getKeysetDirection, keysetFetchSort, } from "../pagination/pagination.keysetDirection.js";
5
5
  import { toPrismaArgs, toPrismaOrderBy, } from "../queryBuilder/queryBuilder.prisma.js";
6
+ import { toDelegateOperations, } from "./repository.delegate.js";
6
7
  import { createAbortError, createTimeoutError, mapRepositoryError, } from "./repository.errors.js";
7
8
  const DEFAULT_SOFT_DELETE_FIELD = "deletedAt";
8
9
  const FIELD_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -29,7 +30,7 @@ export class BaseRepository {
29
30
  if (!delegate) {
30
31
  throw new TypeError("A repository delegate is required.");
31
32
  }
32
- this.delegate = delegate;
33
+ this.delegate = toDelegateOperations(delegate);
33
34
  this.modelName = options.modelName ?? "DatabaseEntity";
34
35
  this.idField = validateFieldName(options.idField ?? "id", "idField");
35
36
  if (options.softDelete) {
@@ -70,7 +71,7 @@ export class BaseRepository {
70
71
  if (!delegate) {
71
72
  throw new TypeError("A repository delegate is required.");
72
73
  }
73
- return this.rebind({ delegate });
74
+ return this.rebind({ delegate: toDelegateOperations(delegate) });
74
75
  }
75
76
  /**
76
77
  * Returns a copy of this repository whose reads include soft-deleted
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Model delegate accepted by `BaseRepository`: any object exposing
3
+ * Prisma-style CRUD methods, including a generated Prisma model delegate
4
+ * such as `prisma.user`.
5
+ *
6
+ * The parameters are declared loosely on purpose, the same way
7
+ * `PrismaClientLike.$transaction` is. A generated delegate's methods are
8
+ * generic (`findFirst<T extends UserFindFirstArgs>(args?: SelectSubset<T,
9
+ * …>)`) and their argument types (`select?: UserSelect | null`,
10
+ * `where?: UserWhereInput`) cannot be assigned from a single hand-written
11
+ * argument shape, so a real client failed to type-check against the
12
+ * previous signatures and needed a cast. Any argument list is accepted
13
+ * here; the return types are still checked, so a delegate whose rows do not
14
+ * match `TEntity` is rejected. The arguments the repository actually passes
15
+ * are described by {@link RepositoryDelegateOperations}.
16
+ */
17
+ export interface RepositoryDelegate<TEntity, TId = string, TCreateInput = Partial<TEntity>, TUpdateInput = Partial<TEntity>, TWhereInput = unknown> {
18
+ findUnique(...args: never[]): Promise<TEntity | null>;
19
+ findFirst(...args: never[]): Promise<TEntity | null>;
20
+ findMany(...args: never[]): Promise<readonly TEntity[]>;
21
+ create(...args: never[]): Promise<TEntity>;
22
+ update(...args: never[]): Promise<TEntity>;
23
+ delete(...args: never[]): Promise<TEntity>;
24
+ count(...args: never[]): Promise<number>;
25
+ upsert?(...args: never[]): Promise<TEntity>;
26
+ createMany?(...args: never[]): Promise<{
27
+ count: number;
28
+ }>;
29
+ deleteMany?(...args: never[]): Promise<{
30
+ count: number;
31
+ }>;
32
+ }
33
+ /**
34
+ * The calls `BaseRepository` makes on its delegate, with the arguments it
35
+ * passes. This is the type of `BaseRepository#delegate`, so subclasses can
36
+ * call the delegate directly.
37
+ */
38
+ export interface RepositoryDelegateOperations<TEntity, TId = string, TCreateInput = Partial<TEntity>, TUpdateInput = Partial<TEntity>, TWhereInput = unknown> {
39
+ findUnique(args: {
40
+ where: unknown;
41
+ }): Promise<TEntity | null>;
42
+ findFirst(args: {
43
+ where?: TWhereInput;
44
+ orderBy?: unknown;
45
+ select?: unknown;
46
+ }): Promise<TEntity | null>;
47
+ findMany(args?: {
48
+ where?: TWhereInput;
49
+ skip?: number;
50
+ take?: number;
51
+ orderBy?: unknown;
52
+ select?: unknown;
53
+ include?: unknown;
54
+ }): Promise<readonly TEntity[]>;
55
+ create(args: {
56
+ data: TCreateInput;
57
+ }): Promise<TEntity>;
58
+ update(args: {
59
+ where: unknown;
60
+ data: TUpdateInput;
61
+ }): Promise<TEntity>;
62
+ delete(args: {
63
+ where: unknown;
64
+ }): Promise<TEntity>;
65
+ count(args?: {
66
+ where?: TWhereInput;
67
+ }): Promise<number>;
68
+ upsert?(args: {
69
+ where: unknown;
70
+ create: TCreateInput;
71
+ update: TUpdateInput;
72
+ }): Promise<TEntity>;
73
+ createMany?(args: {
74
+ data: readonly TCreateInput[];
75
+ }): Promise<{
76
+ count: number;
77
+ }>;
78
+ deleteMany?(args: {
79
+ where?: TWhereInput;
80
+ }): Promise<{
81
+ count: number;
82
+ }>;
83
+ }
84
+ /**
85
+ * Views a delegate through the calls the repository makes on it.
86
+ *
87
+ * The assertion is the narrowing that `RepositoryDelegate`'s loose
88
+ * parameters defer: the repository only ever passes the Prisma argument
89
+ * shapes described by `RepositoryDelegateOperations`, which every generated
90
+ * model delegate accepts at runtime.
91
+ */
92
+ export declare function toDelegateOperations<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>(delegate: RepositoryDelegate<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>): RepositoryDelegateOperations<TEntity, TId, TCreateInput, TUpdateInput, TWhereInput>;
93
+ //# sourceMappingURL=repository.delegate.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Views a delegate through the calls the repository makes on it.
3
+ *
4
+ * The assertion is the narrowing that `RepositoryDelegate`'s loose
5
+ * parameters defer: the repository only ever passes the Prisma argument
6
+ * shapes described by `RepositoryDelegateOperations`, which every generated
7
+ * model delegate accepts at runtime.
8
+ */
9
+ export function toDelegateOperations(delegate) {
10
+ return delegate;
11
+ }
12
+ //# sourceMappingURL=repository.delegate.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zudojs/database",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Database abstraction layer with clients, repositories, transactions, and query building for Zudojs applications.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -41,8 +41,8 @@
41
41
  "!dist/.tsbuildinfo"
42
42
  ],
43
43
  "dependencies": {
44
- "@zudojs/errors": "1.3.0",
45
- "@zudojs/logger": "1.4.0",
44
+ "@zudojs/errors": "1.3.1",
45
+ "@zudojs/logger": "1.4.2",
46
46
  "@zudojs/types": "1.2.0"
47
47
  },
48
48
  "peerDependencies": {