@veloxts/orm 0.1.0
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/LICENSE +21 -0
- package/README.md +566 -0
- package/dist/client.d.ts +114 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +156 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +117 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +138 -0
- package/dist/plugin.js.map +1 -0
- package/dist/types.d.ts +146 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +35 -0
- package/dist/types.js.map +1 -0
- package/package.json +62 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database client wrapper for Prisma
|
|
3
|
+
*
|
|
4
|
+
* Provides lifecycle management and connection state tracking
|
|
5
|
+
* for Prisma clients in a type-safe manner.
|
|
6
|
+
*
|
|
7
|
+
* @module client
|
|
8
|
+
*/
|
|
9
|
+
import { ConfigurationError, VeloxError } from '@veloxts/core';
|
|
10
|
+
import { isDatabaseClient } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a database wrapper with connection lifecycle management
|
|
13
|
+
*
|
|
14
|
+
* This wrapper provides:
|
|
15
|
+
* - Connection state tracking
|
|
16
|
+
* - Controlled connect/disconnect methods
|
|
17
|
+
* - Type-safe access to the underlying client
|
|
18
|
+
*
|
|
19
|
+
* The client is NOT automatically connected - call `connect()` explicitly
|
|
20
|
+
* or use `createDatabasePlugin` for automatic lifecycle management.
|
|
21
|
+
*
|
|
22
|
+
* @template TClient - Type of the Prisma client
|
|
23
|
+
* @param config - Database configuration with client instance
|
|
24
|
+
* @returns Database wrapper with lifecycle management
|
|
25
|
+
*
|
|
26
|
+
* @throws {VeloxError} If config is invalid or client doesn't implement DatabaseClient
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { PrismaClient } from '@prisma/client';
|
|
31
|
+
* import { createDatabase } from '@veloxts/orm';
|
|
32
|
+
*
|
|
33
|
+
* const prisma = new PrismaClient();
|
|
34
|
+
* const db = createDatabase({ client: prisma });
|
|
35
|
+
*
|
|
36
|
+
* // Manual connection management
|
|
37
|
+
* await db.connect();
|
|
38
|
+
* const users = await db.client.user.findMany();
|
|
39
|
+
* await db.disconnect();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // Check connection status
|
|
45
|
+
* const db = createDatabase({ client: prisma });
|
|
46
|
+
*
|
|
47
|
+
* console.log(db.isConnected); // false
|
|
48
|
+
* console.log(db.status.state); // 'disconnected'
|
|
49
|
+
*
|
|
50
|
+
* await db.connect();
|
|
51
|
+
*
|
|
52
|
+
* console.log(db.isConnected); // true
|
|
53
|
+
* console.log(db.status.state); // 'connected'
|
|
54
|
+
* console.log(db.status.connectedAt); // Date
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function createDatabase(config) {
|
|
58
|
+
// Validate configuration
|
|
59
|
+
if (!config || typeof config !== 'object') {
|
|
60
|
+
throw new ConfigurationError('Database configuration is required');
|
|
61
|
+
}
|
|
62
|
+
if (!config.client) {
|
|
63
|
+
throw new ConfigurationError('Database client is required in configuration');
|
|
64
|
+
}
|
|
65
|
+
// Validate that the client implements DatabaseClient interface
|
|
66
|
+
if (!isDatabaseClient(config.client)) {
|
|
67
|
+
throw new ConfigurationError('Database client must implement $connect and $disconnect methods');
|
|
68
|
+
}
|
|
69
|
+
// Internal state
|
|
70
|
+
const state = {
|
|
71
|
+
connectionState: 'disconnected',
|
|
72
|
+
connectedAt: undefined,
|
|
73
|
+
};
|
|
74
|
+
// PERFORMANCE: Cached status object to avoid creating new objects on each access
|
|
75
|
+
// Updated only when connection state changes
|
|
76
|
+
let cachedStatus = buildStatusObject();
|
|
77
|
+
/**
|
|
78
|
+
* Builds a new status object from current state
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
function buildStatusObject() {
|
|
82
|
+
return {
|
|
83
|
+
state: state.connectionState,
|
|
84
|
+
isConnected: state.connectionState === 'connected',
|
|
85
|
+
connectedAt: state.connectedAt,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Updates the cached status object when state changes
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
92
|
+
function updateCachedStatus() {
|
|
93
|
+
cachedStatus = buildStatusObject();
|
|
94
|
+
}
|
|
95
|
+
// Connection method
|
|
96
|
+
async function connect() {
|
|
97
|
+
if (state.connectionState === 'connected') {
|
|
98
|
+
throw new VeloxError('Database is already connected', 500, 'DATABASE_ALREADY_CONNECTED');
|
|
99
|
+
}
|
|
100
|
+
if (state.connectionState === 'connecting') {
|
|
101
|
+
throw new VeloxError('Database connection is already in progress', 500, 'DATABASE_CONNECTION_IN_PROGRESS');
|
|
102
|
+
}
|
|
103
|
+
state.connectionState = 'connecting';
|
|
104
|
+
updateCachedStatus();
|
|
105
|
+
try {
|
|
106
|
+
await config.client.$connect();
|
|
107
|
+
state.connectionState = 'connected';
|
|
108
|
+
state.connectedAt = new Date();
|
|
109
|
+
updateCachedStatus();
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
state.connectionState = 'disconnected';
|
|
113
|
+
updateCachedStatus();
|
|
114
|
+
throw new VeloxError(`Failed to connect to database: ${error instanceof Error ? error.message : String(error)}`, 500, 'DATABASE_CONNECTION_ERROR');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Disconnection method
|
|
118
|
+
async function disconnect() {
|
|
119
|
+
if (state.connectionState === 'disconnected') {
|
|
120
|
+
throw new VeloxError('Database is not connected', 500, 'DATABASE_NOT_CONNECTED');
|
|
121
|
+
}
|
|
122
|
+
if (state.connectionState === 'disconnecting') {
|
|
123
|
+
throw new VeloxError('Database disconnection is already in progress', 500, 'DATABASE_DISCONNECTION_IN_PROGRESS');
|
|
124
|
+
}
|
|
125
|
+
state.connectionState = 'disconnecting';
|
|
126
|
+
updateCachedStatus();
|
|
127
|
+
try {
|
|
128
|
+
await config.client.$disconnect();
|
|
129
|
+
state.connectionState = 'disconnected';
|
|
130
|
+
state.connectedAt = undefined;
|
|
131
|
+
updateCachedStatus();
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// Even if disconnect fails, mark as disconnected
|
|
135
|
+
state.connectionState = 'disconnected';
|
|
136
|
+
state.connectedAt = undefined;
|
|
137
|
+
updateCachedStatus();
|
|
138
|
+
throw new VeloxError(`Failed to disconnect from database: ${error instanceof Error ? error.message : String(error)}`, 500, 'DATABASE_DISCONNECTION_ERROR');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Return the database wrapper object with proper getters for reactive properties
|
|
142
|
+
// PERFORMANCE: status getter returns cached object instead of creating new one
|
|
143
|
+
const database = {
|
|
144
|
+
client: config.client,
|
|
145
|
+
connect,
|
|
146
|
+
disconnect,
|
|
147
|
+
get status() {
|
|
148
|
+
return cachedStatus;
|
|
149
|
+
},
|
|
150
|
+
get isConnected() {
|
|
151
|
+
return state.connectionState === 'connected';
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
return database;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAQ/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA8E9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAsC;IAEtC,yBAAyB;IACzB,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,kBAAkB,CAAC,oCAAoC,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,kBAAkB,CAAC,8CAA8C,CAAC,CAAC;IAC/E,CAAC;IAED,+DAA+D;IAC/D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,kBAAkB,CAAC,iEAAiE,CAAC,CAAC;IAClG,CAAC;IAED,iBAAiB;IACjB,MAAM,KAAK,GAAkB;QAC3B,eAAe,EAAE,cAAc;QAC/B,WAAW,EAAE,SAAS;KACvB,CAAC;IAEF,iFAAiF;IACjF,6CAA6C;IAC7C,IAAI,YAAY,GAAqB,iBAAiB,EAAE,CAAC;IAEzD;;;OAGG;IACH,SAAS,iBAAiB;QACxB,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,eAAe;YAC5B,WAAW,EAAE,KAAK,CAAC,eAAe,KAAK,WAAW;YAClD,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,SAAS,kBAAkB;QACzB,YAAY,GAAG,iBAAiB,EAAE,CAAC;IACrC,CAAC;IAED,oBAAoB;IACpB,KAAK,UAAU,OAAO;QACpB,IAAI,KAAK,CAAC,eAAe,KAAK,WAAW,EAAE,CAAC;YAC1C,MAAM,IAAI,UAAU,CAAC,+BAA+B,EAAE,GAAG,EAAE,4BAA4B,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,KAAK,CAAC,eAAe,KAAK,YAAY,EAAE,CAAC;YAC3C,MAAM,IAAI,UAAU,CAClB,4CAA4C,EAC5C,GAAG,EACH,iCAAiC,CAClC,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,eAAe,GAAG,YAAY,CAAC;QACrC,kBAAkB,EAAE,CAAC;QAErB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC/B,KAAK,CAAC,eAAe,GAAG,WAAW,CAAC;YACpC,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;YAC/B,kBAAkB,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,eAAe,GAAG,cAAc,CAAC;YACvC,kBAAkB,EAAE,CAAC;YACrB,MAAM,IAAI,UAAU,CAClB,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC1F,GAAG,EACH,2BAA2B,CAC5B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,KAAK,UAAU,UAAU;QACvB,IAAI,KAAK,CAAC,eAAe,KAAK,cAAc,EAAE,CAAC;YAC7C,MAAM,IAAI,UAAU,CAAC,2BAA2B,EAAE,GAAG,EAAE,wBAAwB,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,KAAK,CAAC,eAAe,KAAK,eAAe,EAAE,CAAC;YAC9C,MAAM,IAAI,UAAU,CAClB,+CAA+C,EAC/C,GAAG,EACH,oCAAoC,CACrC,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,eAAe,GAAG,eAAe,CAAC;QACxC,kBAAkB,EAAE,CAAC;QAErB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAClC,KAAK,CAAC,eAAe,GAAG,cAAc,CAAC;YACvC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,kBAAkB,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,iDAAiD;YACjD,KAAK,CAAC,eAAe,GAAG,cAAc,CAAC;YACvC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,kBAAkB,EAAE,CAAC;YACrB,MAAM,IAAI,UAAU,CAClB,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC/F,GAAG,EACH,8BAA8B,CAC/B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iFAAiF;IACjF,+EAA+E;IAC/E,MAAM,QAAQ,GAAsB;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO;QACP,UAAU;QACV,IAAI,MAAM;YACR,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,IAAI,WAAW;YACb,OAAO,KAAK,CAAC,eAAe,KAAK,WAAW,CAAC;QAC/C,CAAC;KACF,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @veloxts/orm - Laravel-inspired Prisma wrapper for VeloxTS framework
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe database integration with:
|
|
5
|
+
* - Context-based database access (`ctx.db.user.findUnique(...)`)
|
|
6
|
+
* - VeloxApp plugin integration with automatic lifecycle management
|
|
7
|
+
* - Connection state tracking and error handling
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Setup
|
|
12
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
13
|
+
* import { PrismaClient } from '@prisma/client';
|
|
14
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
15
|
+
*
|
|
16
|
+
* const prisma = new PrismaClient();
|
|
17
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
18
|
+
*
|
|
19
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
20
|
+
* await app.start();
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Using ctx.db in procedure handlers
|
|
26
|
+
* getUser: procedure()
|
|
27
|
+
* .input(z.object({ id: z.string().uuid() }))
|
|
28
|
+
* .query(async ({ input, ctx }) => {
|
|
29
|
+
* return ctx.db.user.findUnique({ where: { id: input.id } });
|
|
30
|
+
* })
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @module @veloxts/orm
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* Package version
|
|
37
|
+
*/
|
|
38
|
+
export declare const ORM_VERSION: "0.1.0";
|
|
39
|
+
export type {
|
|
40
|
+
/**
|
|
41
|
+
* Connection state enum values
|
|
42
|
+
*/
|
|
43
|
+
ConnectionState,
|
|
44
|
+
/**
|
|
45
|
+
* Connection status information
|
|
46
|
+
*/
|
|
47
|
+
ConnectionStatus,
|
|
48
|
+
/**
|
|
49
|
+
* Base interface for Prisma clients
|
|
50
|
+
*/
|
|
51
|
+
DatabaseClient,
|
|
52
|
+
/**
|
|
53
|
+
* Configuration for database wrapper
|
|
54
|
+
*/
|
|
55
|
+
DatabaseWrapperConfig,
|
|
56
|
+
/**
|
|
57
|
+
* Infer client type from config
|
|
58
|
+
*/
|
|
59
|
+
InferClientType,
|
|
60
|
+
/**
|
|
61
|
+
* Infer database client type
|
|
62
|
+
*/
|
|
63
|
+
InferDatabaseClient,
|
|
64
|
+
/**
|
|
65
|
+
* Plugin configuration options
|
|
66
|
+
*/
|
|
67
|
+
OrmPluginConfig, } from './types.js';
|
|
68
|
+
export { isDatabaseClient } from './types.js';
|
|
69
|
+
export type {
|
|
70
|
+
/**
|
|
71
|
+
* Database wrapper interface with lifecycle management
|
|
72
|
+
*/
|
|
73
|
+
Database, } from './client.js';
|
|
74
|
+
export {
|
|
75
|
+
/**
|
|
76
|
+
* Create a database wrapper with connection lifecycle management
|
|
77
|
+
*
|
|
78
|
+
* Use this for manual connection management. For automatic lifecycle
|
|
79
|
+
* management with VeloxApp, use `createDatabasePlugin` instead.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const db = createDatabase({ client: new PrismaClient() });
|
|
84
|
+
* await db.connect();
|
|
85
|
+
*
|
|
86
|
+
* const users = await db.client.user.findMany();
|
|
87
|
+
*
|
|
88
|
+
* await db.disconnect();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
createDatabase, } from './client.js';
|
|
92
|
+
export {
|
|
93
|
+
/**
|
|
94
|
+
* Create a database plugin for VeloxApp integration
|
|
95
|
+
*
|
|
96
|
+
* This is the recommended way to integrate Prisma with VeloxTS.
|
|
97
|
+
* The plugin automatically:
|
|
98
|
+
* - Connects to the database when the app starts
|
|
99
|
+
* - Disconnects during graceful shutdown
|
|
100
|
+
* - Adds `ctx.db` to procedure handlers
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
105
|
+
* import { PrismaClient } from '@prisma/client';
|
|
106
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
107
|
+
*
|
|
108
|
+
* const prisma = new PrismaClient();
|
|
109
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
110
|
+
*
|
|
111
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
112
|
+
* await app.start();
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
createDatabasePlugin, } from './plugin.js';
|
|
116
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAMH;;GAEG;AACH,eAAO,MAAM,WAAW,EAAG,OAAgB,CAAC;AAM5C,YAAY;AACV;;GAEG;AACH,eAAe;AACf;;GAEG;AACH,gBAAgB;AAChB;;GAEG;AACH,cAAc;AACd;;GAEG;AACH,qBAAqB;AACrB;;GAEG;AACH,eAAe;AACf;;GAEG;AACH,mBAAmB;AACnB;;GAEG;AACH,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAM9C,YAAY;AACV;;GAEG;AACH,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,OAAO;AACL;;;;;;;;;;;;;;;GAeG;AACH,cAAc,GACf,MAAM,aAAa,CAAC;AAMrB,OAAO;AACL;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @veloxts/orm - Laravel-inspired Prisma wrapper for VeloxTS framework
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe database integration with:
|
|
5
|
+
* - Context-based database access (`ctx.db.user.findUnique(...)`)
|
|
6
|
+
* - VeloxApp plugin integration with automatic lifecycle management
|
|
7
|
+
* - Connection state tracking and error handling
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Setup
|
|
12
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
13
|
+
* import { PrismaClient } from '@prisma/client';
|
|
14
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
15
|
+
*
|
|
16
|
+
* const prisma = new PrismaClient();
|
|
17
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
18
|
+
*
|
|
19
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
20
|
+
* await app.start();
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Using ctx.db in procedure handlers
|
|
26
|
+
* getUser: procedure()
|
|
27
|
+
* .input(z.object({ id: z.string().uuid() }))
|
|
28
|
+
* .query(async ({ input, ctx }) => {
|
|
29
|
+
* return ctx.db.user.findUnique({ where: { id: input.id } });
|
|
30
|
+
* })
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @module @veloxts/orm
|
|
34
|
+
*/
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Version
|
|
37
|
+
// ============================================================================
|
|
38
|
+
/**
|
|
39
|
+
* Package version
|
|
40
|
+
*/
|
|
41
|
+
export const ORM_VERSION = '0.1.0';
|
|
42
|
+
export { isDatabaseClient } from './types.js';
|
|
43
|
+
export {
|
|
44
|
+
/**
|
|
45
|
+
* Create a database wrapper with connection lifecycle management
|
|
46
|
+
*
|
|
47
|
+
* Use this for manual connection management. For automatic lifecycle
|
|
48
|
+
* management with VeloxApp, use `createDatabasePlugin` instead.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const db = createDatabase({ client: new PrismaClient() });
|
|
53
|
+
* await db.connect();
|
|
54
|
+
*
|
|
55
|
+
* const users = await db.client.user.findMany();
|
|
56
|
+
*
|
|
57
|
+
* await db.disconnect();
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
createDatabase, } from './client.js';
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// Plugin
|
|
63
|
+
// ============================================================================
|
|
64
|
+
export {
|
|
65
|
+
/**
|
|
66
|
+
* Create a database plugin for VeloxApp integration
|
|
67
|
+
*
|
|
68
|
+
* This is the recommended way to integrate Prisma with VeloxTS.
|
|
69
|
+
* The plugin automatically:
|
|
70
|
+
* - Connects to the database when the app starts
|
|
71
|
+
* - Disconnects during graceful shutdown
|
|
72
|
+
* - Adds `ctx.db` to procedure handlers
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
77
|
+
* import { PrismaClient } from '@prisma/client';
|
|
78
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
79
|
+
*
|
|
80
|
+
* const prisma = new PrismaClient();
|
|
81
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
82
|
+
*
|
|
83
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
84
|
+
* await app.start();
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
createDatabasePlugin, } from './plugin.js';
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAgB,CAAC;AAoC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAY9C,OAAO;AACL;;;;;;;;;;;;;;;GAeG;AACH,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,+EAA+E;AAC/E,SAAS;AACT,+EAA+E;AAE/E,OAAO;AACL;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VeloxApp plugin for database integration
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic database lifecycle management via the VeloxTS plugin system.
|
|
5
|
+
* Connects on app start, disconnects on app shutdown.
|
|
6
|
+
*
|
|
7
|
+
* @module plugin
|
|
8
|
+
*/
|
|
9
|
+
import type { DatabaseClient, OrmPluginConfig } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Extend BaseContext to include the database client
|
|
12
|
+
*
|
|
13
|
+
* After registering the database plugin, `ctx.db` will be available
|
|
14
|
+
* in all procedure handlers with full type information.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // In your app setup
|
|
19
|
+
* import { PrismaClient } from '@prisma/client';
|
|
20
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
21
|
+
*
|
|
22
|
+
* const prisma = new PrismaClient();
|
|
23
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
24
|
+
*
|
|
25
|
+
* // In your procedure handlers
|
|
26
|
+
* getUser: procedure()
|
|
27
|
+
* .input(z.object({ id: z.string() }))
|
|
28
|
+
* .query(async ({ input, ctx }) => {
|
|
29
|
+
* // ctx.db is typed as your PrismaClient
|
|
30
|
+
* return ctx.db.user.findUnique({ where: { id: input.id } });
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* To get full type inference for your specific Prisma schema,
|
|
35
|
+
* add this to your app's declaration file:
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // In your app's types.d.ts or similar
|
|
40
|
+
* import type { PrismaClient } from '@prisma/client';
|
|
41
|
+
*
|
|
42
|
+
* declare module '@veloxts/core' {
|
|
43
|
+
* interface BaseContext {
|
|
44
|
+
* db: PrismaClient;
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
declare module '@veloxts/core' {
|
|
50
|
+
interface BaseContext {
|
|
51
|
+
/**
|
|
52
|
+
* Database client for executing queries
|
|
53
|
+
*
|
|
54
|
+
* This property is added by the @veloxts/orm plugin.
|
|
55
|
+
* The actual type depends on your Prisma schema.
|
|
56
|
+
*/
|
|
57
|
+
db: DatabaseClient;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Creates a database plugin for VeloxApp integration
|
|
62
|
+
*
|
|
63
|
+
* This plugin:
|
|
64
|
+
* - Wraps your Prisma client with connection management
|
|
65
|
+
* - Automatically connects when the app starts
|
|
66
|
+
* - Automatically disconnects during graceful shutdown
|
|
67
|
+
* - Adds `db` to the request context for use in procedure handlers
|
|
68
|
+
*
|
|
69
|
+
* @template TClient - Type of the Prisma client
|
|
70
|
+
* @param config - Plugin configuration with Prisma client
|
|
71
|
+
* @returns A VeloxPlugin that can be registered with `app.use()`
|
|
72
|
+
*
|
|
73
|
+
* @throws {ConfigurationError} If config is invalid or client is missing
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
78
|
+
* import { PrismaClient } from '@prisma/client';
|
|
79
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
80
|
+
*
|
|
81
|
+
* const prisma = new PrismaClient();
|
|
82
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
83
|
+
*
|
|
84
|
+
* // Register the database plugin
|
|
85
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
86
|
+
*
|
|
87
|
+
* // Start the app (database connects automatically)
|
|
88
|
+
* await app.start();
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // Using ctx.db in procedures
|
|
94
|
+
* import { defineProcedures, procedure } from '@veloxts/router';
|
|
95
|
+
* import { z } from '@veloxts/validation';
|
|
96
|
+
*
|
|
97
|
+
* export const userProcedures = defineProcedures('users', {
|
|
98
|
+
* getUser: procedure()
|
|
99
|
+
* .input(z.object({ id: z.string().uuid() }))
|
|
100
|
+
* .query(async ({ input, ctx }) => {
|
|
101
|
+
* // ctx.db is your Prisma client
|
|
102
|
+
* const user = await ctx.db.user.findUnique({
|
|
103
|
+
* where: { id: input.id }
|
|
104
|
+
* });
|
|
105
|
+
* return user;
|
|
106
|
+
* }),
|
|
107
|
+
*
|
|
108
|
+
* createUser: procedure()
|
|
109
|
+
* .input(z.object({ name: z.string(), email: z.string().email() }))
|
|
110
|
+
* .mutation(async ({ input, ctx }) => {
|
|
111
|
+
* return ctx.db.user.create({ data: input });
|
|
112
|
+
* }),
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function createDatabasePlugin<TClient extends DatabaseClient>(config: OrmPluginConfig<TClient>): import("@veloxts/core").VeloxPlugin<import("fastify").FastifyPluginOptions>;
|
|
117
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,WAAW;QACnB;;;;;WAKG;QACH,EAAE,EAAE,cAAc,CAAC;KACpB;CACF;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,cAAc,EACjE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,+EA2EjC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VeloxApp plugin for database integration
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic database lifecycle management via the VeloxTS plugin system.
|
|
5
|
+
* Connects on app start, disconnects on app shutdown.
|
|
6
|
+
*
|
|
7
|
+
* @module plugin
|
|
8
|
+
*/
|
|
9
|
+
import { ConfigurationError, definePlugin } from '@veloxts/core';
|
|
10
|
+
import { createDatabase } from './client.js';
|
|
11
|
+
import { isDatabaseClient } from './types.js';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Plugin Implementation
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Version of the ORM plugin
|
|
17
|
+
*/
|
|
18
|
+
const ORM_PLUGIN_VERSION = '0.1.0';
|
|
19
|
+
/**
|
|
20
|
+
* Default plugin name
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_PLUGIN_NAME = '@veloxts/orm';
|
|
23
|
+
/**
|
|
24
|
+
* Creates a database plugin for VeloxApp integration
|
|
25
|
+
*
|
|
26
|
+
* This plugin:
|
|
27
|
+
* - Wraps your Prisma client with connection management
|
|
28
|
+
* - Automatically connects when the app starts
|
|
29
|
+
* - Automatically disconnects during graceful shutdown
|
|
30
|
+
* - Adds `db` to the request context for use in procedure handlers
|
|
31
|
+
*
|
|
32
|
+
* @template TClient - Type of the Prisma client
|
|
33
|
+
* @param config - Plugin configuration with Prisma client
|
|
34
|
+
* @returns A VeloxPlugin that can be registered with `app.use()`
|
|
35
|
+
*
|
|
36
|
+
* @throws {ConfigurationError} If config is invalid or client is missing
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { createVeloxApp } from '@veloxts/core';
|
|
41
|
+
* import { PrismaClient } from '@prisma/client';
|
|
42
|
+
* import { createDatabasePlugin } from '@veloxts/orm';
|
|
43
|
+
*
|
|
44
|
+
* const prisma = new PrismaClient();
|
|
45
|
+
* const app = await createVeloxApp({ port: 3000 });
|
|
46
|
+
*
|
|
47
|
+
* // Register the database plugin
|
|
48
|
+
* await app.use(createDatabasePlugin({ client: prisma }));
|
|
49
|
+
*
|
|
50
|
+
* // Start the app (database connects automatically)
|
|
51
|
+
* await app.start();
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // Using ctx.db in procedures
|
|
57
|
+
* import { defineProcedures, procedure } from '@veloxts/router';
|
|
58
|
+
* import { z } from '@veloxts/validation';
|
|
59
|
+
*
|
|
60
|
+
* export const userProcedures = defineProcedures('users', {
|
|
61
|
+
* getUser: procedure()
|
|
62
|
+
* .input(z.object({ id: z.string().uuid() }))
|
|
63
|
+
* .query(async ({ input, ctx }) => {
|
|
64
|
+
* // ctx.db is your Prisma client
|
|
65
|
+
* const user = await ctx.db.user.findUnique({
|
|
66
|
+
* where: { id: input.id }
|
|
67
|
+
* });
|
|
68
|
+
* return user;
|
|
69
|
+
* }),
|
|
70
|
+
*
|
|
71
|
+
* createUser: procedure()
|
|
72
|
+
* .input(z.object({ name: z.string(), email: z.string().email() }))
|
|
73
|
+
* .mutation(async ({ input, ctx }) => {
|
|
74
|
+
* return ctx.db.user.create({ data: input });
|
|
75
|
+
* }),
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function createDatabasePlugin(config) {
|
|
80
|
+
// Validate configuration at plugin creation time
|
|
81
|
+
if (!config || typeof config !== 'object') {
|
|
82
|
+
throw new ConfigurationError('Database plugin configuration is required');
|
|
83
|
+
}
|
|
84
|
+
if (!config.client) {
|
|
85
|
+
throw new ConfigurationError('Database client is required. Provide a Prisma client instance in config.client');
|
|
86
|
+
}
|
|
87
|
+
if (!isDatabaseClient(config.client)) {
|
|
88
|
+
throw new ConfigurationError('Database client must implement $connect and $disconnect methods. ' +
|
|
89
|
+
'Ensure you are passing a valid Prisma client instance.');
|
|
90
|
+
}
|
|
91
|
+
const pluginName = config.name ?? DEFAULT_PLUGIN_NAME;
|
|
92
|
+
// Plugin state - holds the database wrapper
|
|
93
|
+
const state = {
|
|
94
|
+
database: null,
|
|
95
|
+
};
|
|
96
|
+
return definePlugin({
|
|
97
|
+
name: pluginName,
|
|
98
|
+
version: ORM_PLUGIN_VERSION,
|
|
99
|
+
async register(server) {
|
|
100
|
+
// Create the database wrapper
|
|
101
|
+
state.database = createDatabase({ client: config.client });
|
|
102
|
+
// Connect to the database
|
|
103
|
+
await state.database.connect();
|
|
104
|
+
// Add database client to request context via onRequest hook
|
|
105
|
+
server.addHook('onRequest', async (request) => {
|
|
106
|
+
// The context should be created by @veloxts/core's onRequest hook
|
|
107
|
+
// which runs before this hook (due to plugin registration order)
|
|
108
|
+
if (request.context) {
|
|
109
|
+
// Extend the context with the database client using Object.defineProperty
|
|
110
|
+
// for proper property definition without type assertion side effects
|
|
111
|
+
Object.defineProperty(request.context, 'db', {
|
|
112
|
+
value: config.client,
|
|
113
|
+
writable: false,
|
|
114
|
+
enumerable: true,
|
|
115
|
+
configurable: true, // Allow redefinition for testing
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Register shutdown hook using Fastify's onClose hook
|
|
120
|
+
// This ensures the database disconnects during graceful shutdown
|
|
121
|
+
server.addHook('onClose', async () => {
|
|
122
|
+
if (state.database?.isConnected) {
|
|
123
|
+
try {
|
|
124
|
+
await state.database.disconnect();
|
|
125
|
+
server.log.info('Database disconnected successfully during shutdown');
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
// Log error but don't rethrow - allow graceful shutdown to continue
|
|
129
|
+
server.log.error({ err: error instanceof Error ? error : new Error(String(error)) }, 'Failed to disconnect database during shutdown');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Log successful registration
|
|
134
|
+
server.log.info(`Database plugin "${pluginName}" registered successfully`);
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAyD9C,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC;;GAEG;AACH,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAY3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAgC;IAEhC,iDAAiD;IACjD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,kBAAkB,CAAC,2CAA2C,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,kBAAkB,CAC1B,gFAAgF,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,kBAAkB,CAC1B,mEAAmE;YACjE,wDAAwD,CAC3D,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,IAAI,mBAAmB,CAAC;IAEtD,4CAA4C;IAC5C,MAAM,KAAK,GAAyB;QAClC,QAAQ,EAAE,IAAI;KACf,CAAC;IAEF,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,kBAAkB;QAE3B,KAAK,CAAC,QAAQ,CAAC,MAAM;YACnB,8BAA8B;YAC9B,KAAK,CAAC,QAAQ,GAAG,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YAE3D,0BAA0B;YAC1B,MAAM,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAE/B,4DAA4D;YAC5D,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC5C,kEAAkE;gBAClE,iEAAiE;gBACjE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;oBACpB,0EAA0E;oBAC1E,qEAAqE;oBACrE,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;wBAC3C,KAAK,EAAE,MAAM,CAAC,MAAM;wBACpB,QAAQ,EAAE,KAAK;wBACf,UAAU,EAAE,IAAI;wBAChB,YAAY,EAAE,IAAI,EAAE,iCAAiC;qBACtD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,sDAAsD;YACtD,iEAAiE;YACjE,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;gBACnC,IAAI,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;oBAChC,IAAI,CAAC;wBACH,MAAM,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;wBAClC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;oBACxE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,oEAAoE;wBACpE,MAAM,CAAC,GAAG,CAAC,KAAK,CACd,EAAE,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAClE,+CAA+C,CAChD,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,8BAA8B;YAC9B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,UAAU,2BAA2B,CAAC,CAAC;QAC7E,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|