@mostajs/orm-bridge 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.
Files changed (44) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +29 -0
  3. package/README.md +203 -0
  4. package/dist/core/dialect-registry.d.ts +11 -0
  5. package/dist/core/dialect-registry.d.ts.map +1 -0
  6. package/dist/core/dialect-registry.js +58 -0
  7. package/dist/core/dialect-registry.js.map +1 -0
  8. package/dist/core/types.d.ts +44 -0
  9. package/dist/core/types.d.ts.map +1 -0
  10. package/dist/core/types.js +5 -0
  11. package/dist/core/types.js.map +1 -0
  12. package/dist/index.d.ts +6 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +10 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/prisma/dispatcher.d.ts +12 -0
  17. package/dist/prisma/dispatcher.d.ts.map +1 -0
  18. package/dist/prisma/dispatcher.js +102 -0
  19. package/dist/prisma/dispatcher.js.map +1 -0
  20. package/dist/prisma/extension.d.ts +24 -0
  21. package/dist/prisma/extension.d.ts.map +1 -0
  22. package/dist/prisma/extension.js +78 -0
  23. package/dist/prisma/extension.js.map +1 -0
  24. package/dist/prisma/index.d.ts +6 -0
  25. package/dist/prisma/index.d.ts.map +1 -0
  26. package/dist/prisma/index.js +8 -0
  27. package/dist/prisma/index.js.map +1 -0
  28. package/dist/prisma/mappers/orderby.d.ts +12 -0
  29. package/dist/prisma/mappers/orderby.d.ts.map +1 -0
  30. package/dist/prisma/mappers/orderby.js +33 -0
  31. package/dist/prisma/mappers/orderby.js.map +1 -0
  32. package/dist/prisma/mappers/where.d.ts +18 -0
  33. package/dist/prisma/mappers/where.d.ts.map +1 -0
  34. package/dist/prisma/mappers/where.js +136 -0
  35. package/dist/prisma/mappers/where.js.map +1 -0
  36. package/dist/prisma/types.d.ts +8 -0
  37. package/dist/prisma/types.d.ts.map +1 -0
  38. package/dist/prisma/types.js +4 -0
  39. package/dist/prisma/types.js.map +1 -0
  40. package/dist/utils/case-conversion.d.ts +7 -0
  41. package/dist/utils/case-conversion.d.ts.map +1 -0
  42. package/dist/utils/case-conversion.js +23 -0
  43. package/dist/utils/case-conversion.js.map +1 -0
  44. package/package.json +73 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@mostajs/orm-bridge` will be documented in this file.
4
+
5
+ ## [0.1.0] — 2026-04-12
6
+
7
+ ### Added
8
+
9
+ - **Prisma Bridge** (`@mostajs/orm-bridge/prisma`) : runtime interception for Prisma Client via `$extends` API.
10
+ - **CRUD operations supported** :
11
+ - `findUnique`, `findUniqueOrThrow`
12
+ - `findFirst`, `findFirstOrThrow`
13
+ - `findMany` (with `where`, `orderBy`, `take`, `skip`)
14
+ - `count`
15
+ - `create`, `createMany`
16
+ - `update`, `updateMany`
17
+ - `upsert`
18
+ - `delete`, `deleteMany`
19
+ - **Where mapper** covers all major Prisma operators :
20
+ - equality (`equals`, shorthand field: value)
21
+ - comparison (`gt`, `gte`, `lt`, `lte`, `not`)
22
+ - sets (`in`, `notIn`)
23
+ - string ops (`contains`, `startsWith`, `endsWith` with `mode: 'insensitive'`)
24
+ - logical (`AND`, `OR`, `NOT`)
25
+ - **OrderBy mapper** : simple form + array form + nested sort objects
26
+ - **Lazy dialect registry** : caches connections by URI, idempotent schema init
27
+ - **Fallback mode** : unmapped models pass through to Prisma's default engine
28
+ - **Observability hook** (`onIntercept`) for logging/metrics
29
+
30
+ ### Package structure
31
+
32
+ - `@mostajs/orm-bridge` — root (shared core)
33
+ - `@mostajs/orm-bridge/prisma` — Prisma-specific bridge (this release)
34
+ - Future sub-modules : `/drizzle`, `/typeorm`, `/mongoose` (v0.3+)
35
+
36
+ ### Tests
37
+
38
+ 28 integration tests on SQLite `:memory:` covering all supported operations.
39
+
40
+ ### License
41
+
42
+ AGPL-3.0-or-later + commercial license option (drmdh@msn.com).
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (c) 2026 Dr Hamid MADANI <drmdh@msn.com>
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Affero General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Affero General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Affero General Public License
17
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+
19
+ COMMERCIAL LICENSE
20
+
21
+ For organizations that cannot comply with the AGPL open-source requirements,
22
+ a commercial license is available. Contact: drmdh@msn.com
23
+
24
+ The commercial license allows you to:
25
+ - Use the software in proprietary/closed-source projects
26
+ - Modify without publishing your source code
27
+ - Get priority support and SLA
28
+
29
+ Contact: Dr Hamid MADANI <drmdh@msn.com>
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # @mostajs/orm-bridge
2
+
3
+ > **Keep your Prisma code. Gain access to 13 databases.**
4
+ >
5
+ > Runtime bridges for third-party ORMs — intercept their calls and redirect them to [@mostajs/orm](https://github.com/apolocine/mosta-orm) without rewriting a single line of your existing code.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@mostajs/orm-bridge.svg)](https://www.npmjs.com/package/@mostajs/orm-bridge)
8
+ [![License: AGPL-3.0-or-later](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE)
9
+
10
+ ## Why
11
+
12
+ Prisma supports **7 databases** (PostgreSQL, MySQL, SQLite, SQL Server, MongoDB, CockroachDB, MariaDB).
13
+
14
+ @mostajs/orm supports **13** (all of the above plus Oracle, DB2, HANA, HSQLDB, Spanner, Sybase — with more coming).
15
+
16
+ **This bridge lets you use Prisma's API on any of these 13 databases** — zero code change other than PrismaClient construction.
17
+
18
+ ```ts
19
+ // Before
20
+ const prisma = new PrismaClient();
21
+ await prisma.user.findMany(); // only works on Prisma's 7 DBs
22
+
23
+ // After
24
+ const prisma = new PrismaClient({ datasourceUrl: 'sqlite::memory:' })
25
+ .$extends(mostaExtension({
26
+ models: {
27
+ User: { dialect: 'oracle', url: 'oracle://...', schema: UserSchema }
28
+ }
29
+ }));
30
+
31
+ await prisma.user.findMany(); // now runs on Oracle!
32
+ // Full Prisma types preserved, zero other changes.
33
+ ```
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ npm install @mostajs/orm-bridge @mostajs/orm @prisma/client
39
+ ```
40
+
41
+ ## Quick start
42
+
43
+ ```ts
44
+ import { PrismaClient } from '@prisma/client';
45
+ import { mostaExtension } from '@mostajs/orm-bridge/prisma';
46
+ import type { EntitySchema } from '@mostajs/orm';
47
+
48
+ const AuditLogSchema: EntitySchema = {
49
+ name: 'AuditLog',
50
+ collection: 'audit_logs',
51
+ fields: {
52
+ userId: { type: 'string', required: true },
53
+ action: { type: 'string', required: true },
54
+ timestamp: { type: 'date', required: true },
55
+ },
56
+ relations: {},
57
+ indexes: [{ fields: { userId: 'asc' } }],
58
+ timestamps: true,
59
+ };
60
+
61
+ const prisma = new PrismaClient({
62
+ datasourceUrl: 'sqlite::memory:', // no-op placeholder
63
+ }).$extends(mostaExtension({
64
+ models: {
65
+ AuditLog: {
66
+ dialect: 'mongodb',
67
+ url: process.env.MONGO_URL!,
68
+ schema: AuditLogSchema,
69
+ },
70
+ },
71
+ onIntercept: (e) => console.log(`[bridge] ${e.model}.${e.operation} → ${e.dialect} (${e.duration}ms)`),
72
+ }));
73
+
74
+ // Prisma → MongoDB via mosta-orm
75
+ await prisma.auditLog.create({
76
+ data: { userId: 'u1', action: 'login', timestamp: new Date() }
77
+ });
78
+
79
+ const logs = await prisma.auditLog.findMany({
80
+ where: { userId: 'u1', timestamp: { gte: new Date('2026-01-01') } },
81
+ orderBy: { timestamp: 'desc' },
82
+ take: 10,
83
+ });
84
+
85
+ // Other models NOT in config.models still go through Prisma's default engine
86
+ await prisma.user.findMany(); // unchanged behavior
87
+ ```
88
+
89
+ ## Architecture
90
+
91
+ ```
92
+ ┌────────────────────────┐
93
+ │ Your app (Prisma) │
94
+ │ prisma.user.findMany()│
95
+ └──────────┬──────────────┘
96
+
97
+
98
+ ┌────────────────────────┐
99
+ │ PrismaClient │
100
+ │ $extends($allModels) │
101
+ └──────────┬──────────────┘
102
+
103
+ ┌─────┴──────┐
104
+ │ │
105
+ mapped? no
106
+ │ │
107
+ ▼ ▼
108
+ mosta-orm Prisma default
109
+ dialect query engine
110
+
111
+
112
+ ┌──────────────────────┐
113
+ │ 13 databases │
114
+ │ PG / MySQL / Oracle │
115
+ │ MongoDB / DB2 / │
116
+ │ HANA / HSQLDB / │
117
+ │ Spanner / Sybase ...│
118
+ └──────────────────────┘
119
+ ```
120
+
121
+ ## Supported Prisma operations
122
+
123
+ | Operation | Supported | Notes |
124
+ |-----------|-----------|-------|
125
+ | `findUnique`, `findFirst`, `findUniqueOrThrow`, `findFirstOrThrow` | YES | Maps `where` to mosta FilterQuery |
126
+ | `findMany` | YES | Supports `where`, `orderBy`, `take`, `skip` |
127
+ | `count` | YES | |
128
+ | `create`, `createMany` | YES | |
129
+ | `update`, `updateMany` | YES | |
130
+ | `upsert` | YES | |
131
+ | `delete`, `deleteMany` | YES | |
132
+ | `aggregate`, `groupBy` | v0.2 | Planned |
133
+ | Nested `include` / `select` | v0.2 | Planned |
134
+ | Transactions | v0.3 | Planned |
135
+
136
+ ## Supported Prisma `where` operators
137
+
138
+ | Prisma | mosta-orm |
139
+ |--------|-----------|
140
+ | `{ field: value }` | direct equals |
141
+ | `equals` | `$eq` |
142
+ | `not` | `$ne` |
143
+ | `gt`, `gte`, `lt`, `lte` | `$gt`, `$gte`, `$lt`, `$lte` |
144
+ | `in`, `notIn` | `$in`, `$nin` |
145
+ | `contains` | `$regex` (escaped) |
146
+ | `startsWith`, `endsWith` | `$regex` (anchored) |
147
+ | `mode: 'insensitive'` | `$regexFlags: 'i'` |
148
+ | `AND`, `OR` | `$and`, `$or` |
149
+ | `NOT` | best-effort condition inversion |
150
+
151
+ ## Configuration reference
152
+
153
+ ```ts
154
+ interface PrismaBridgeConfig {
155
+ /** Model name → mosta-orm binding */
156
+ models: Record<string, ModelBinding>;
157
+
158
+ /** What to do when a model is not mapped (default: 'source') */
159
+ fallback?: 'source' | 'error';
160
+
161
+ /** Observability hook */
162
+ onIntercept?: (event: InterceptEvent) => void;
163
+ }
164
+
165
+ interface ModelBinding {
166
+ dialect: DialectType; // 'postgres', 'mongodb', 'oracle', ...
167
+ url?: string; // connection URI
168
+ connection?: ConnectionConfig; // full config alternative
169
+ collection?: string; // override table name
170
+ schema?: EntitySchema; // mosta-orm schema (recommended)
171
+ }
172
+ ```
173
+
174
+ ## Roadmap
175
+
176
+ - **v0.1.0** — Prisma bridge MVP (CRUD + filters + orderBy) ✅
177
+ - **v0.2.0** — aggregate / groupBy / nested include / transactions
178
+ - **v0.3.0** — Drizzle bridge (same pattern for Drizzle ORM)
179
+ - **v0.4.0** — TypeORM bridge
180
+ - **v0.5.0** — Mongoose bridge
181
+
182
+ ## How it works
183
+
184
+ We use Prisma's official [`$extends`](https://www.prisma.io/docs/orm/prisma-client/client-extensions/query) API — a stable extension point. The `$allOperations` handler intercepts every model call and decides whether to:
185
+
186
+ - **Forward to mosta-orm** (if the model is in `config.models`) — runs the query on the mapped dialect, returning the result in Prisma's expected shape.
187
+ - **Pass through to Prisma** (otherwise) — normal Prisma behavior.
188
+
189
+ No monkey-patching. No Prisma internals hacked. Works with Prisma 5.4+ (including the new rust-free `prisma-client` generator in Prisma 6.16+).
190
+
191
+ ## License
192
+
193
+ **AGPL-3.0-or-later** + commercial license available.
194
+
195
+ For commercial use in closed-source projects, contact: drmdh@msn.com
196
+
197
+ ## Author
198
+
199
+ Dr Hamid MADANI <drmdh@msn.com>
200
+
201
+ ---
202
+
203
+ Part of the [@mostajs ecosystem](https://github.com/apolocine) — 13 databases, 11 transports, one unified backend.
@@ -0,0 +1,11 @@
1
+ import { type IDialect } from '@mostajs/orm';
2
+ import type { ModelBinding } from './types.js';
3
+ /**
4
+ * Get (or create) a dialect instance for the given binding.
5
+ * Caches by URI so the same connection is reused across calls.
6
+ * Also lazily runs initSchema for each schema registered on the binding.
7
+ */
8
+ export declare function getOrCreateDialect(binding: ModelBinding): Promise<IDialect>;
9
+ /** Close all cached dialects (useful for tests/graceful shutdown) */
10
+ export declare function disposeAllDialects(): Promise<void>;
11
+ //# sourceMappingURL=dialect-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect-registry.d.ts","sourceRoot":"","sources":["../../src/core/dialect-registry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,QAAQ,EAAyB,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyBjF;AAiBD,qEAAqE;AACrE,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAUxD"}
@@ -0,0 +1,58 @@
1
+ // dialect-registry.ts
2
+ // Lazy-initializes and caches mosta-orm dialects per model binding.
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ import { getDialect } from '@mostajs/orm';
5
+ const cache = new Map();
6
+ const schemasInit = new Set(); // key = dialectKey + schema.name
7
+ /**
8
+ * Get (or create) a dialect instance for the given binding.
9
+ * Caches by URI so the same connection is reused across calls.
10
+ * Also lazily runs initSchema for each schema registered on the binding.
11
+ */
12
+ export async function getOrCreateDialect(binding) {
13
+ const key = cacheKey(binding);
14
+ if (!cache.has(key)) {
15
+ cache.set(key, initDialect(binding));
16
+ }
17
+ let dialect;
18
+ try {
19
+ dialect = await cache.get(key);
20
+ }
21
+ catch (err) {
22
+ cache.delete(key);
23
+ throw err;
24
+ }
25
+ // Idempotent schema init : run once per (connection, schema)
26
+ if (binding.schema) {
27
+ const schemaKey = key + '::' + binding.schema.name;
28
+ if (!schemasInit.has(schemaKey)) {
29
+ await dialect.initSchema([binding.schema]);
30
+ schemasInit.add(schemaKey);
31
+ }
32
+ }
33
+ return dialect;
34
+ }
35
+ async function initDialect(binding) {
36
+ const config = binding.connection ?? {
37
+ dialect: binding.dialect,
38
+ uri: binding.url ?? '',
39
+ };
40
+ if (!config.dialect)
41
+ config.dialect = binding.dialect;
42
+ const dialect = await getDialect(config);
43
+ return dialect;
44
+ }
45
+ function cacheKey(b) {
46
+ return `${b.dialect}::${b.url ?? b.connection?.uri ?? 'custom-conn'}`;
47
+ }
48
+ /** Close all cached dialects (useful for tests/graceful shutdown) */
49
+ export async function disposeAllDialects() {
50
+ const entries = [...cache.values()];
51
+ cache.clear();
52
+ schemasInit.clear();
53
+ const dialects = await Promise.all(entries.map(p => p.catch(() => null)));
54
+ await Promise.all(dialects
55
+ .filter((d) => d !== null)
56
+ .map(d => d.disconnect().catch(() => null)));
57
+ }
58
+ //# sourceMappingURL=dialect-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect-registry.js","sourceRoot":"","sources":["../../src/core/dialect-registry.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,oEAAoE;AACpE,wCAAwC;AAExC,OAAO,EAAE,UAAU,EAAwC,MAAM,cAAc,CAAC;AAGhF,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;AACnD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC,CAAE,iCAAiC;AAEzE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAqB;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,6DAA6D;IAC7D,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAqB;IAC9C,MAAM,MAAM,GAAqB,OAAO,CAAC,UAAU,IAAI;QACrD,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;KACvB,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEtD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,QAAQ,CAAC,CAAe;IAC/B,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,UAAU,EAAE,GAAG,IAAI,aAAa,EAAE,CAAC;AACxE,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACpC,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ;SACL,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SACxC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { DialectType, ConnectionConfig, EntitySchema } from '@mostajs/orm';
2
+ /**
3
+ * Per-model binding configuration.
4
+ * Tells the bridge which @mostajs/orm dialect backs each foreign-ORM model.
5
+ */
6
+ export interface ModelBinding {
7
+ /** Dialect name (e.g. 'postgres', 'mongodb', 'oracle') */
8
+ dialect: DialectType;
9
+ /** Connection URL or URI */
10
+ url?: string;
11
+ /** Full connection config (alternative to url) */
12
+ connection?: ConnectionConfig;
13
+ /** Optional collection/table name override (defaults to snake_case + plural of model name) */
14
+ collection?: string;
15
+ /** Optional EntitySchema pre-built (skip schema inference) */
16
+ schema?: EntitySchema;
17
+ }
18
+ /** Common bridge configuration shared by all source ORMs */
19
+ export interface BridgeConfig {
20
+ /**
21
+ * Map of model name → mosta-orm binding.
22
+ * Models NOT listed here fall back to the source ORM's default engine.
23
+ */
24
+ models: Record<string, ModelBinding>;
25
+ /**
26
+ * Behavior when a model is not mapped :
27
+ * - 'source' (default): let the source ORM handle the query normally
28
+ * - 'error': throw an error
29
+ */
30
+ fallback?: 'source' | 'error';
31
+ /**
32
+ * Hook called for every intercepted operation, for logging/metrics.
33
+ */
34
+ onIntercept?: (event: InterceptEvent) => void;
35
+ }
36
+ export interface InterceptEvent {
37
+ source: string;
38
+ model: string;
39
+ operation: string;
40
+ dialect: DialectType;
41
+ duration?: number;
42
+ error?: Error;
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,OAAO,EAAE,WAAW,CAAC;IAErB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,kDAAkD;IAClD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAErC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAE9B;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf"}
@@ -0,0 +1,5 @@
1
+ // @mostajs/orm-bridge — Shared core types
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // License: AGPL-3.0-or-later
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,wCAAwC;AACxC,6BAA6B"}
@@ -0,0 +1,6 @@
1
+ export type { BridgeConfig, ModelBinding, InterceptEvent } from './core/types.js';
2
+ export { getOrCreateDialect, disposeAllDialects } from './core/dialect-registry.js';
3
+ export { modelToCollection, pascalToCamel, toPascalCase } from './utils/case-conversion.js';
4
+ export { mostaExtension, dispatchPrismaOp, mapPrismaWhere, mapPrismaOrderBy, } from './prisma/index.js';
5
+ export type { PrismaBridgeConfig, PrismaOperation, } from './prisma/types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAK5F,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // @mostajs/orm-bridge — Root public API
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // License: AGPL-3.0-or-later
4
+ export { getOrCreateDialect, disposeAllDialects } from './core/dialect-registry.js';
5
+ export { modelToCollection, pascalToCamel, toPascalCase } from './utils/case-conversion.js';
6
+ // --- Prisma bridge (primary sub-module) ---
7
+ // Prefer `import { mostaExtension } from '@mostajs/orm-bridge/prisma'` for
8
+ // better tree-shaking and explicit intent.
9
+ export { mostaExtension, dispatchPrismaOp, mapPrismaWhere, mapPrismaOrderBy, } from './prisma/index.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,wCAAwC;AACxC,6BAA6B;AAI7B,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE5F,6CAA6C;AAC7C,2EAA2E;AAC3E,2CAA2C;AAC3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { IDialect } from '@mostajs/orm';
2
+ import type { ModelBinding } from '../core/types.js';
3
+ import type { PrismaOperation } from './types.js';
4
+ /**
5
+ * Execute a Prisma operation on a mosta-orm dialect.
6
+ * Returns data shaped to match Prisma's expected return contract.
7
+ *
8
+ * Requires `binding.schema` to be set — if absent, builds a minimal
9
+ * schema from the model name (best-effort; may fail on exotic fields).
10
+ */
11
+ export declare function dispatchPrismaOp(dialect: IDialect, binding: ModelBinding, modelName: string, operation: PrismaOperation, args: Record<string, unknown> | undefined): Promise<unknown>;
12
+ //# sourceMappingURL=dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/prisma/dispatcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACxC,OAAO,CAAC,OAAO,CAAC,CAkFlB"}
@@ -0,0 +1,102 @@
1
+ // Prisma dispatcher : route Prisma operations to @mostajs/orm dialect methods
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // License: AGPL-3.0-or-later
4
+ import { mapPrismaWhere } from './mappers/where.js';
5
+ import { mapPrismaOrderBy } from './mappers/orderby.js';
6
+ import { modelToCollection } from '../utils/case-conversion.js';
7
+ /**
8
+ * Execute a Prisma operation on a mosta-orm dialect.
9
+ * Returns data shaped to match Prisma's expected return contract.
10
+ *
11
+ * Requires `binding.schema` to be set — if absent, builds a minimal
12
+ * schema from the model name (best-effort; may fail on exotic fields).
13
+ */
14
+ export async function dispatchPrismaOp(dialect, binding, modelName, operation, args) {
15
+ const schema = resolveSchema(binding, modelName);
16
+ const a = args ?? {};
17
+ const where = 'where' in a ? mapPrismaWhere(a.where) : {};
18
+ const sort = 'orderBy' in a ? mapPrismaOrderBy(a.orderBy) : undefined;
19
+ const limit = typeof a.take === 'number' ? a.take : undefined;
20
+ const skip = typeof a.skip === 'number' ? a.skip : undefined;
21
+ const queryOpts = { sort, limit, skip };
22
+ switch (operation) {
23
+ case 'findUnique':
24
+ case 'findFirst':
25
+ return dialect.findOne(schema, where);
26
+ case 'findUniqueOrThrow':
27
+ case 'findFirstOrThrow': {
28
+ const res = await dialect.findOne(schema, where);
29
+ if (!res)
30
+ throw new Error(`${modelName} not found (where=${JSON.stringify(where)})`);
31
+ return res;
32
+ }
33
+ case 'findMany':
34
+ return dialect.find(schema, where, queryOpts);
35
+ case 'count':
36
+ return dialect.count(schema, where);
37
+ case 'create':
38
+ return dialect.create(schema, (a.data ?? {}));
39
+ case 'createMany': {
40
+ const rows = Array.isArray(a.data) ? a.data : [a.data];
41
+ let count = 0;
42
+ for (const row of rows) {
43
+ await dialect.create(schema, row);
44
+ count++;
45
+ }
46
+ return { count };
47
+ }
48
+ case 'update': {
49
+ const existing = await dialect.findOne(schema, where);
50
+ if (!existing)
51
+ throw new Error(`${modelName} not found for update`);
52
+ const id = String(existing.id ?? existing._id ?? '');
53
+ return dialect.update(schema, id, a.data);
54
+ }
55
+ case 'updateMany': {
56
+ const count = await dialect.updateMany(schema, where, a.data);
57
+ return { count };
58
+ }
59
+ case 'upsert': {
60
+ const existing = await dialect.findOne(schema, where);
61
+ if (existing) {
62
+ const id = String(existing.id ?? existing._id ?? '');
63
+ return dialect.update(schema, id, a.update);
64
+ }
65
+ return dialect.create(schema, a.create);
66
+ }
67
+ case 'delete': {
68
+ const existing = await dialect.findOne(schema, where);
69
+ if (!existing)
70
+ throw new Error(`${modelName} not found for delete`);
71
+ const id = String(existing.id ?? existing._id ?? '');
72
+ await dialect.delete(schema, id);
73
+ return existing;
74
+ }
75
+ case 'deleteMany': {
76
+ const count = await dialect.deleteMany(schema, where);
77
+ return { count };
78
+ }
79
+ case 'aggregate':
80
+ case 'groupBy':
81
+ default:
82
+ throw new Error(`Prisma operation "${operation}" not yet supported by @mostajs/orm-bridge v0.1. Planned for v0.2.0.`);
83
+ }
84
+ }
85
+ /**
86
+ * Resolve the EntitySchema for this model.
87
+ * Prefers binding.schema ; else constructs a permissive minimal schema.
88
+ */
89
+ function resolveSchema(binding, modelName) {
90
+ if (binding.schema)
91
+ return binding.schema;
92
+ // Minimal permissive schema — useful for read-only / pass-through use cases
93
+ return {
94
+ name: modelName,
95
+ collection: binding.collection ?? modelToCollection(modelName),
96
+ fields: {},
97
+ relations: {},
98
+ indexes: [],
99
+ timestamps: false,
100
+ };
101
+ }
102
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/prisma/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { PrismaBridgeConfig } from './types.js';
2
+ /**
3
+ * Build a Prisma Client `$extends` object that intercepts model operations
4
+ * and redirects them to @mostajs/orm for any model listed in `config.models`.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { PrismaClient } from '@prisma/client';
9
+ * import { mostaExtension } from '@mostajs/orm-bridge/prisma';
10
+ *
11
+ * const prisma = new PrismaClient({ datasourceUrl: 'sqlite::memory:' })
12
+ * .$extends(mostaExtension({
13
+ * models: {
14
+ * AuditLog: { dialect: 'mongodb', url: process.env.MONGO_URL },
15
+ * Inventory: { dialect: 'oracle', url: process.env.ORACLE_URL },
16
+ * },
17
+ * }));
18
+ *
19
+ * // prisma.auditLog.findMany() → executed by @mostajs/orm on MongoDB
20
+ * // prisma.user.findMany() → still handled by Prisma default engine (if not mapped)
21
+ * ```
22
+ */
23
+ export declare function mostaExtension(config: PrismaBridgeConfig): any;
24
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../../src/prisma/extension.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAmB,MAAM,YAAY,CAAC;AAItE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,OA+DxD"}
@@ -0,0 +1,78 @@
1
+ // Prisma Client $extends factory — main public API for Prisma Bridge
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // License: AGPL-3.0-or-later
4
+ import { getOrCreateDialect } from '../core/dialect-registry.js';
5
+ import { dispatchPrismaOp } from './dispatcher.js';
6
+ /**
7
+ * Build a Prisma Client `$extends` object that intercepts model operations
8
+ * and redirects them to @mostajs/orm for any model listed in `config.models`.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { PrismaClient } from '@prisma/client';
13
+ * import { mostaExtension } from '@mostajs/orm-bridge/prisma';
14
+ *
15
+ * const prisma = new PrismaClient({ datasourceUrl: 'sqlite::memory:' })
16
+ * .$extends(mostaExtension({
17
+ * models: {
18
+ * AuditLog: { dialect: 'mongodb', url: process.env.MONGO_URL },
19
+ * Inventory: { dialect: 'oracle', url: process.env.ORACLE_URL },
20
+ * },
21
+ * }));
22
+ *
23
+ * // prisma.auditLog.findMany() → executed by @mostajs/orm on MongoDB
24
+ * // prisma.user.findMany() → still handled by Prisma default engine (if not mapped)
25
+ * ```
26
+ */
27
+ export function mostaExtension(config) {
28
+ const fallback = config.fallback ?? 'source';
29
+ /**
30
+ * Return type is deliberately `any` because the structural shape matches
31
+ * Prisma's `defineExtension` input without requiring a hard import
32
+ * of @prisma/client types (optional peer dependency).
33
+ */
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ const extension = {
36
+ name: 'mosta-orm-bridge',
37
+ query: {
38
+ $allModels: {
39
+ async $allOperations({ model, operation, args, query }) {
40
+ const binding = model ? config.models[model] : undefined;
41
+ if (!binding) {
42
+ if (fallback === 'error') {
43
+ throw new Error(`[@mostajs/orm-bridge] Model "${model}" is not mapped to a mosta-orm dialect. ` +
44
+ `Add it to config.models, or set fallback: 'source' to let Prisma handle it.`);
45
+ }
46
+ return query(args); // let Prisma handle the query normally
47
+ }
48
+ const started = Date.now();
49
+ try {
50
+ const dialect = await getOrCreateDialect(binding);
51
+ const result = await dispatchPrismaOp(dialect, binding, model, operation, args);
52
+ config.onIntercept?.({
53
+ source: 'prisma',
54
+ model,
55
+ operation,
56
+ dialect: binding.dialect,
57
+ duration: Date.now() - started,
58
+ });
59
+ return result;
60
+ }
61
+ catch (err) {
62
+ config.onIntercept?.({
63
+ source: 'prisma',
64
+ model,
65
+ operation,
66
+ dialect: binding.dialect,
67
+ duration: Date.now() - started,
68
+ error: err,
69
+ });
70
+ throw err;
71
+ }
72
+ },
73
+ },
74
+ },
75
+ };
76
+ return extension;
77
+ }
78
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../src/prisma/extension.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,wCAAwC;AACxC,6BAA6B;AAG7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,cAAc,CAAC,MAA0B;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAE7C;;;;OAIG;IACH,8DAA8D;IAC9D,MAAM,SAAS,GAAQ;QACrB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE;YACL,UAAU,EAAE;gBACV,KAAK,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAMnD;oBACC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAEzD,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;4BACzB,MAAM,IAAI,KAAK,CACb,gCAAgC,KAAK,0CAA0C;gCAC/E,6EAA6E,CAC9E,CAAC;wBACJ,CAAC;wBACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,uCAAuC;oBAC9D,CAAC;oBAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBAC3B,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;wBAClD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAA4B,EAAE,IAAI,CAC5D,CAAC;wBACF,MAAM,CAAC,WAAW,EAAE,CAAC;4BACnB,MAAM,EAAE,QAAQ;4BAChB,KAAK;4BACL,SAAS;4BACT,OAAO,EAAE,OAAO,CAAC,OAAO;4BACxB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;yBAC/B,CAAC,CAAC;wBACH,OAAO,MAAM,CAAC;oBAChB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,CAAC,WAAW,EAAE,CAAC;4BACnB,MAAM,EAAE,QAAQ;4BAChB,KAAK;4BACL,SAAS;4BACT,OAAO,EAAE,OAAO,CAAC,OAAO;4BACxB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;4BAC9B,KAAK,EAAE,GAAY;yBACpB,CAAC,CAAC;wBACH,MAAM,GAAG,CAAC;oBACZ,CAAC;gBACH,CAAC;aACF;SACF;KACF,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { mostaExtension } from './extension.js';
2
+ export { dispatchPrismaOp } from './dispatcher.js';
3
+ export { mapPrismaWhere } from './mappers/where.js';
4
+ export { mapPrismaOrderBy } from './mappers/orderby.js';
5
+ export type { PrismaBridgeConfig, PrismaOperation, ModelBinding } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prisma/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ // Prisma sub-module public API
2
+ // Usage: import { mostaExtension } from '@mostajs/orm-bridge/prisma'
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ export { mostaExtension } from './extension.js';
5
+ export { dispatchPrismaOp } from './dispatcher.js';
6
+ export { mapPrismaWhere } from './mappers/where.js';
7
+ export { mapPrismaOrderBy } from './mappers/orderby.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prisma/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,qEAAqE;AACrE,wCAAwC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { SortDirection } from '@mostajs/orm';
2
+ /**
3
+ * Convert Prisma `orderBy` to mosta-orm QueryOptions.sort.
4
+ *
5
+ * Prisma accepts :
6
+ * - { field: 'asc' | 'desc' }
7
+ * - [{ field: 'asc' }, { other: 'desc' }]
8
+ * - { field: { sort: 'asc', nulls: 'first' } } — nulls ignored in v0.1
9
+ * - { relation: { field: 'asc' } } — flattened to dotted path
10
+ */
11
+ export declare function mapPrismaOrderBy(orderBy: unknown): Record<string, SortDirection> | undefined;
12
+ //# sourceMappingURL=orderby.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orderby.d.ts","sourceRoot":"","sources":["../../../src/prisma/mappers/orderby.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,SAAS,CAsB5F"}
@@ -0,0 +1,33 @@
1
+ // Prisma orderBy → @mostajs/orm sort
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ /**
4
+ * Convert Prisma `orderBy` to mosta-orm QueryOptions.sort.
5
+ *
6
+ * Prisma accepts :
7
+ * - { field: 'asc' | 'desc' }
8
+ * - [{ field: 'asc' }, { other: 'desc' }]
9
+ * - { field: { sort: 'asc', nulls: 'first' } } — nulls ignored in v0.1
10
+ * - { relation: { field: 'asc' } } — flattened to dotted path
11
+ */
12
+ export function mapPrismaOrderBy(orderBy) {
13
+ if (!orderBy)
14
+ return undefined;
15
+ const out = {};
16
+ const entries = Array.isArray(orderBy)
17
+ ? orderBy.flatMap(o => Object.entries(o))
18
+ : Object.entries(orderBy);
19
+ for (const [key, val] of entries) {
20
+ if (typeof val === 'string') {
21
+ out[key] = val === 'desc' ? -1 : 1;
22
+ }
23
+ else if (val && typeof val === 'object') {
24
+ const v = val;
25
+ if (v.sort === 'asc' || v.sort === 'desc') {
26
+ out[key] = v.sort === 'desc' ? -1 : 1;
27
+ }
28
+ // nested relation: skip for now (not trivial without schema info)
29
+ }
30
+ }
31
+ return Object.keys(out).length > 0 ? out : undefined;
32
+ }
33
+ //# sourceMappingURL=orderby.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orderby.js","sourceRoot":"","sources":["../../../src/prisma/mappers/orderby.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,wCAAwC;AAIxC;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,MAAM,GAAG,GAAkC,EAAE,CAAC;IAE9C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QACpC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAA4B,CAAC,CAAC;QACpE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAkC,CAAC,CAAC;IAEvD,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;QACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;aAAM,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,GAAwB,CAAC;YACnC,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,CAAC;YACD,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { FilterQuery } from '@mostajs/orm';
2
+ /**
3
+ * Convert Prisma `where` argument into mosta-orm FilterQuery.
4
+ *
5
+ * Supported :
6
+ * - equals: { field: value } or { field: { equals: value } }
7
+ * - Basic comparison : { gt, gte, lt, lte, not, in, notIn }
8
+ * - String ops : { contains, startsWith, endsWith, mode: 'insensitive' }
9
+ * - Logical : AND, OR, NOT
10
+ * - Nested : { relation: { field: value } } — flattened to dotted path (best effort)
11
+ *
12
+ * Not supported (v0.1) :
13
+ * - has, hasSome, hasEvery (array membership)
14
+ * - path/JSON filters
15
+ * - Relation filters with complex nesting
16
+ */
17
+ export declare function mapPrismaWhere(where: unknown): FilterQuery;
18
+ //# sourceMappingURL=where.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/prisma/mappers/where.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,cAAc,CAAC;AAEhE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAgC1D"}
@@ -0,0 +1,136 @@
1
+ // Prisma where clause → @mostajs/orm FilterQuery
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ /**
4
+ * Convert Prisma `where` argument into mosta-orm FilterQuery.
5
+ *
6
+ * Supported :
7
+ * - equals: { field: value } or { field: { equals: value } }
8
+ * - Basic comparison : { gt, gte, lt, lte, not, in, notIn }
9
+ * - String ops : { contains, startsWith, endsWith, mode: 'insensitive' }
10
+ * - Logical : AND, OR, NOT
11
+ * - Nested : { relation: { field: value } } — flattened to dotted path (best effort)
12
+ *
13
+ * Not supported (v0.1) :
14
+ * - has, hasSome, hasEvery (array membership)
15
+ * - path/JSON filters
16
+ * - Relation filters with complex nesting
17
+ */
18
+ export function mapPrismaWhere(where) {
19
+ if (!where || typeof where !== 'object')
20
+ return {};
21
+ const out = {};
22
+ for (const [key, value] of Object.entries(where)) {
23
+ if (key === 'AND') {
24
+ const arr = Array.isArray(value) ? value : [value];
25
+ out.$and = arr.map(v => mapPrismaWhere(v));
26
+ continue;
27
+ }
28
+ if (key === 'OR') {
29
+ const arr = Array.isArray(value) ? value : [value];
30
+ out.$or = arr.map(v => mapPrismaWhere(v));
31
+ continue;
32
+ }
33
+ if (key === 'NOT') {
34
+ // Best-effort: use $and with inverted ops — simplified to shallow
35
+ const arr = Array.isArray(value) ? value : [value];
36
+ for (const v of arr) {
37
+ const inverted = mapPrismaWhere(v);
38
+ for (const [field, condition] of Object.entries(inverted)) {
39
+ if (field.startsWith('$'))
40
+ continue;
41
+ out[field] = negateCondition(condition);
42
+ }
43
+ }
44
+ continue;
45
+ }
46
+ out[key] = mapValueOrCondition(value);
47
+ }
48
+ return out;
49
+ }
50
+ function mapValueOrCondition(value) {
51
+ // Primitive → equals
52
+ if (value === null ||
53
+ typeof value === 'string' ||
54
+ typeof value === 'number' ||
55
+ typeof value === 'boolean' ||
56
+ value instanceof Date) {
57
+ return value;
58
+ }
59
+ // Array — could be $in implicit (some Prisma patterns)
60
+ if (Array.isArray(value))
61
+ return value;
62
+ if (value && typeof value === 'object') {
63
+ return mapOperatorObject(value);
64
+ }
65
+ return value;
66
+ }
67
+ function mapOperatorObject(obj) {
68
+ const op = {};
69
+ if ('equals' in obj)
70
+ op.$eq = obj.equals;
71
+ if ('not' in obj)
72
+ op.$ne = obj.not;
73
+ if ('gt' in obj)
74
+ op.$gt = obj.gt;
75
+ if ('gte' in obj)
76
+ op.$gte = obj.gte;
77
+ if ('lt' in obj)
78
+ op.$lt = obj.lt;
79
+ if ('lte' in obj)
80
+ op.$lte = obj.lte;
81
+ if ('in' in obj)
82
+ op.$in = obj.in;
83
+ if ('notIn' in obj)
84
+ op.$nin = obj.notIn;
85
+ // String operators → regex
86
+ const caseInsensitive = (obj.mode === 'insensitive');
87
+ if ('contains' in obj) {
88
+ op.$regex = escapeRegex(String(obj.contains));
89
+ if (caseInsensitive)
90
+ op.$regexFlags = 'i';
91
+ }
92
+ if ('startsWith' in obj) {
93
+ op.$regex = '^' + escapeRegex(String(obj.startsWith));
94
+ if (caseInsensitive)
95
+ op.$regexFlags = 'i';
96
+ }
97
+ if ('endsWith' in obj) {
98
+ op.$regex = escapeRegex(String(obj.endsWith)) + '$';
99
+ if (caseInsensitive)
100
+ op.$regexFlags = 'i';
101
+ }
102
+ // If no operator keys matched, return original (probably a nested relation filter)
103
+ if (Object.keys(op).length === 0) {
104
+ return obj;
105
+ }
106
+ return op;
107
+ }
108
+ function negateCondition(condition) {
109
+ if (typeof condition === 'object' && condition !== null) {
110
+ // Best-effort swap : $eq ↔ $ne, $in ↔ $nin, $gt ↔ $lte, $gte ↔ $lt
111
+ const c = condition;
112
+ const n = {};
113
+ if ('$eq' in c)
114
+ n.$ne = c.$eq;
115
+ if ('$ne' in c)
116
+ n.$eq = c.$ne;
117
+ if ('$in' in c)
118
+ n.$nin = c.$in;
119
+ if ('$nin' in c)
120
+ n.$in = c.$nin;
121
+ if ('$gt' in c)
122
+ n.$lte = c.$gt;
123
+ if ('$gte' in c)
124
+ n.$lt = c.$gte;
125
+ if ('$lt' in c)
126
+ n.$gte = c.$lt;
127
+ if ('$lte' in c)
128
+ n.$gt = c.$lte;
129
+ return n;
130
+ }
131
+ return { $ne: condition };
132
+ }
133
+ function escapeRegex(s) {
134
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
135
+ }
136
+ //# sourceMappingURL=where.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"where.js","sourceRoot":"","sources":["../../../src/prisma/mappers/where.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { BridgeConfig, ModelBinding } from '../core/types.js';
2
+ export interface PrismaBridgeConfig extends BridgeConfig {
3
+ /** (optional) override default fallback to 'prisma' */
4
+ fallback?: 'source' | 'error';
5
+ }
6
+ export type PrismaOperation = 'findUnique' | 'findUniqueOrThrow' | 'findFirst' | 'findFirstOrThrow' | 'findMany' | 'count' | 'create' | 'createMany' | 'update' | 'updateMany' | 'upsert' | 'delete' | 'deleteMany' | 'aggregate' | 'groupBy';
7
+ export type { ModelBinding };
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/prisma/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEnE,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,uDAAuD;IACvD,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,MAAM,eAAe,GACvB,YAAY,GAAG,mBAAmB,GAClC,WAAW,GAAI,kBAAkB,GACjC,UAAU,GACV,OAAO,GACP,QAAQ,GAAO,YAAY,GAC3B,QAAQ,GAAO,YAAY,GAC3B,QAAQ,GACR,QAAQ,GAAO,YAAY,GAC3B,WAAW,GAAI,SAAS,CAAC;AAE7B,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Prisma-specific bridge types
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/prisma/types.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,wCAAwC"}
@@ -0,0 +1,7 @@
1
+ /** PascalCase (User) to snake_case plural (users) — naive pluralization */
2
+ export declare function modelToCollection(modelName: string): string;
3
+ /** PascalCase (User) to camelCase (user) */
4
+ export declare function pascalToCamel(modelName: string): string;
5
+ /** camelCase or PascalCase to PascalCase */
6
+ export declare function toPascalCase(name: string): string;
7
+ //# sourceMappingURL=case-conversion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"case-conversion.d.ts","sourceRoot":"","sources":["../../src/utils/case-conversion.ts"],"names":[],"mappings":"AAGA,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,23 @@
1
+ // case-conversion.ts
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ /** PascalCase (User) to snake_case plural (users) — naive pluralization */
4
+ export function modelToCollection(modelName) {
5
+ const snake = modelName
6
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
7
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
8
+ .toLowerCase();
9
+ if (/(s|x|z|ch|sh)$/.test(snake))
10
+ return snake + 'es';
11
+ if (/[^aeiou]y$/.test(snake))
12
+ return snake.slice(0, -1) + 'ies';
13
+ return snake + 's';
14
+ }
15
+ /** PascalCase (User) to camelCase (user) */
16
+ export function pascalToCamel(modelName) {
17
+ return modelName.charAt(0).toLowerCase() + modelName.slice(1);
18
+ }
19
+ /** camelCase or PascalCase to PascalCase */
20
+ export function toPascalCase(name) {
21
+ return name.charAt(0).toUpperCase() + name.slice(1);
22
+ }
23
+ //# sourceMappingURL=case-conversion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"case-conversion.js","sourceRoot":"","sources":["../../src/utils/case-conversion.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,wCAAwC;AAExC,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,MAAM,KAAK,GAAG,SAAS;SACpB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,WAAW,EAAE,CAAC;IACjB,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,GAAG,IAAI,CAAC;IACtD,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IAChE,OAAO,KAAK,GAAG,GAAG,CAAC;AACrB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@mostajs/orm-bridge",
3
+ "version": "0.1.0",
4
+ "description": "Runtime bridges for third-party ORMs (Prisma, Drizzle, TypeORM, Mongoose) — intercept their calls and redirect to @mostajs/orm for 13-database access without rewriting existing code",
5
+ "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
+ "license": "AGPL-3.0-or-later",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./prisma": {
17
+ "types": "./dist/prisma/index.d.ts",
18
+ "import": "./dist/prisma/index.js"
19
+ }
20
+ },
21
+ "files": ["dist", "LICENSE", "README.md", "CHANGELOG.md"],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "clean": "rm -rf dist",
26
+ "test": "npx tsx test-scripts/run-all.ts",
27
+ "test:prisma": "npx tsx test-scripts/test-prisma-bridge.ts",
28
+ "prepublishOnly": "npm run clean && npm run build"
29
+ },
30
+ "keywords": [
31
+ "mostajs",
32
+ "orm",
33
+ "bridge",
34
+ "prisma",
35
+ "drizzle",
36
+ "typeorm",
37
+ "mongoose",
38
+ "interception",
39
+ "runtime",
40
+ "proxy",
41
+ "multi-database",
42
+ "mongodb",
43
+ "oracle",
44
+ "db2"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/apolocine/mosta-orm-bridge.git"
49
+ },
50
+ "bugs": {
51
+ "url": "https://github.com/apolocine/mosta-orm-bridge/issues"
52
+ },
53
+ "homepage": "https://github.com/apolocine/mosta-orm-bridge#readme",
54
+ "peerDependencies": {
55
+ "@mostajs/orm": "^1.9.0",
56
+ "@prisma/client": ">=5.4.0"
57
+ },
58
+ "peerDependenciesMeta": {
59
+ "@prisma/client": { "optional": true }
60
+ },
61
+ "devDependencies": {
62
+ "@mostajs/orm": "^1.9.0",
63
+ "@prisma/client": "^5.20.0",
64
+ "@types/node": "^20.0.0",
65
+ "prisma": "^5.20.0",
66
+ "tsx": "^4.0.0",
67
+ "typescript": "^5.3.0",
68
+ "better-sqlite3": "^11.0.0"
69
+ },
70
+ "engines": {
71
+ "node": ">=18.0.0"
72
+ }
73
+ }