turbine-orm 0.3.1 → 0.5.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/README.md CHANGED
@@ -46,6 +46,16 @@ npx turbine init --url postgres://user:pass@localhost:5432/mydb
46
46
  npx turbine generate
47
47
  ```
48
48
 
49
+ Works with both ESM and CommonJS:
50
+
51
+ ```typescript
52
+ // ESM
53
+ import { turbine } from './generated/turbine';
54
+
55
+ // CommonJS
56
+ const { turbine } = require('./generated/turbine');
57
+ ```
58
+
49
59
  This introspects your database and generates a fully-typed client at `./generated/turbine/`.
50
60
 
51
61
  ```typescript
@@ -167,6 +177,36 @@ const stats = await db.raw<{ day: Date; count: number }>`
167
177
  `;
168
178
  ```
169
179
 
180
+ ### Case-insensitive search
181
+
182
+ ```typescript
183
+ const users = await db.users.findMany({
184
+ where: {
185
+ email: { contains: 'alice', mode: 'insensitive' },
186
+ },
187
+ });
188
+ // Generates: WHERE email ILIKE '%alice%'
189
+ ```
190
+
191
+ ### Query timeout
192
+
193
+ ```typescript
194
+ const users = await db.users.findMany({
195
+ where: { orgId: 1 },
196
+ timeout: 5000, // 5 second timeout
197
+ });
198
+ ```
199
+
200
+ ### Default limit
201
+
202
+ ```typescript
203
+ // Set a default limit for all queries on a model
204
+ const db = turbine({
205
+ connectionString: process.env.DATABASE_URL,
206
+ defaultLimit: 100,
207
+ });
208
+ ```
209
+
170
210
  ### Middleware
171
211
 
172
212
  ```typescript
@@ -239,9 +279,17 @@ npx turbine generate # Regenerate typed client
239
279
  ### Migration workflow
240
280
 
241
281
  ```bash
282
+ # Create a new migration
242
283
  npx turbine migrate create add_users_table
243
- # Edit the generated .sql file with UP and DOWN sections
284
+ # -> Creates turbine/migrations/001_add_users_table.sql with UP/DOWN sections
285
+
286
+ # Apply all pending migrations
244
287
  npx turbine migrate up
288
+
289
+ # Rollback the last applied migration
290
+ npx turbine migrate down
291
+
292
+ # Check migration status (applied vs pending)
245
293
  npx turbine migrate status
246
294
  ```
247
295
 
@@ -287,8 +335,9 @@ This resolves the entire 3-level object graph in one database round-trip. Prisma
287
335
 
288
336
  ## Requirements
289
337
 
290
- - Node.js >= 22.0.0
338
+ - Node.js >= 18.0.0
291
339
  - PostgreSQL >= 14
340
+ - Works with both ESM (`import`) and CommonJS (`require`)
292
341
 
293
342
  ## License
294
343
 
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ /**
3
+ * turbine-orm CLI — Configuration file support
4
+ *
5
+ * Loads turbine.config.ts (or .js/.mjs) via dynamic import.
6
+ * Falls back to CLI args and environment variables.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.loadConfig = loadConfig;
43
+ exports.findConfigFile = findConfigFile;
44
+ exports.resolveConfig = resolveConfig;
45
+ exports.configTemplate = configTemplate;
46
+ const node_fs_1 = require("node:fs");
47
+ const node_path_1 = require("node:path");
48
+ const node_url_1 = require("node:url");
49
+ // ---------------------------------------------------------------------------
50
+ // Config file names, in priority order
51
+ // ---------------------------------------------------------------------------
52
+ const CONFIG_FILES = [
53
+ 'turbine.config.ts',
54
+ 'turbine.config.mts',
55
+ 'turbine.config.js',
56
+ 'turbine.config.mjs',
57
+ ];
58
+ // ---------------------------------------------------------------------------
59
+ // Load config
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Attempt to load a turbine config file from the current directory.
63
+ * Returns the config if found, or an empty object.
64
+ */
65
+ async function loadConfig(cwd) {
66
+ const dir = cwd ?? process.cwd();
67
+ for (const filename of CONFIG_FILES) {
68
+ const filePath = (0, node_path_1.join)(dir, filename);
69
+ if (!(0, node_fs_1.existsSync)(filePath))
70
+ continue;
71
+ try {
72
+ const absPath = (0, node_path_1.resolve)(filePath);
73
+ const fileUrl = (0, node_url_1.pathToFileURL)(absPath).href;
74
+ // For .ts files, we need to rely on Node's --experimental-strip-types
75
+ // or the tsx loader. Dynamic import handles .js/.mjs natively.
76
+ const mod = await Promise.resolve(`${fileUrl}`).then(s => __importStar(require(s)));
77
+ const config = mod.default ?? mod;
78
+ return config;
79
+ }
80
+ catch (err) {
81
+ // If importing a .ts file fails, try the next one
82
+ if (filename.endsWith('.ts') || filename.endsWith('.mts')) {
83
+ continue;
84
+ }
85
+ throw new Error(`Failed to load config from ${filename}: ${err instanceof Error ? err.message : String(err)}`);
86
+ }
87
+ }
88
+ return {};
89
+ }
90
+ /**
91
+ * Find the config file path (for display purposes).
92
+ * Returns null if no config file is found.
93
+ */
94
+ function findConfigFile(cwd) {
95
+ const dir = cwd ?? process.cwd();
96
+ for (const filename of CONFIG_FILES) {
97
+ const filePath = (0, node_path_1.join)(dir, filename);
98
+ if ((0, node_fs_1.existsSync)(filePath))
99
+ return filePath;
100
+ }
101
+ return null;
102
+ }
103
+ /**
104
+ * Merge config file values with CLI overrides and env vars.
105
+ * Priority: CLI flags > env vars > config file > defaults.
106
+ */
107
+ function resolveConfig(fileConfig, overrides) {
108
+ return {
109
+ url: overrides.url ??
110
+ process.env['DATABASE_URL'] ??
111
+ fileConfig.url ??
112
+ '',
113
+ out: overrides.out ?? fileConfig.out ?? './generated/turbine',
114
+ schema: overrides.schema ?? fileConfig.schema ?? 'public',
115
+ include: overrides.include ?? fileConfig.include ?? [],
116
+ exclude: overrides.exclude ?? fileConfig.exclude ?? [],
117
+ migrationsDir: fileConfig.migrationsDir ?? './turbine/migrations',
118
+ seedFile: fileConfig.seedFile ?? './turbine/seed.ts',
119
+ schemaFile: fileConfig.schemaFile ?? './turbine/schema.ts',
120
+ };
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Config file template (for `turbine init`)
124
+ // ---------------------------------------------------------------------------
125
+ function configTemplate(connectionString) {
126
+ const url = connectionString ?? 'process.env.DATABASE_URL';
127
+ const urlLine = connectionString
128
+ ? ` url: '${connectionString}',`
129
+ : ` url: process.env.DATABASE_URL,`;
130
+ return `import type { TurbineCliConfig } from 'turbine-orm/cli';
131
+
132
+ /**
133
+ * Turbine configuration
134
+ * @see https://batadata.com/docs/turbine/config
135
+ */
136
+ const config: TurbineCliConfig = {
137
+ /** Postgres connection string */
138
+ ${urlLine}
139
+
140
+ /** Output directory for generated types + client */
141
+ out: './generated/turbine',
142
+
143
+ /** Postgres schema to introspect (default: public) */
144
+ schema: 'public',
145
+
146
+ /** Tables to exclude from generation */
147
+ // exclude: ['_migrations', '_sessions'],
148
+
149
+ /** Directory for SQL migration files */
150
+ migrationsDir: './turbine/migrations',
151
+
152
+ /** Path to seed file */
153
+ seedFile: './turbine/seed.ts',
154
+
155
+ /** Path to schema builder file (for turbine push) */
156
+ schemaFile: './turbine/schema.ts',
157
+ };
158
+
159
+ export default config;
160
+ `;
161
+ }