alepha 0.14.0 → 0.14.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.
Files changed (149) hide show
  1. package/README.md +3 -3
  2. package/dist/api/audits/index.d.ts +80 -1
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js.map +1 -1
  5. package/dist/api/files/index.d.ts +80 -1
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/files/index.js.map +1 -1
  8. package/dist/api/jobs/index.d.ts +236 -157
  9. package/dist/api/jobs/index.d.ts.map +1 -1
  10. package/dist/api/jobs/index.js.map +1 -1
  11. package/dist/api/notifications/index.d.ts +21 -1
  12. package/dist/api/notifications/index.d.ts.map +1 -1
  13. package/dist/api/parameters/index.d.ts +451 -4
  14. package/dist/api/parameters/index.d.ts.map +1 -1
  15. package/dist/api/parameters/index.js.map +1 -1
  16. package/dist/api/users/index.d.ts +252 -249
  17. package/dist/api/users/index.d.ts.map +1 -1
  18. package/dist/api/users/index.js +4 -0
  19. package/dist/api/users/index.js.map +1 -1
  20. package/dist/api/verifications/index.d.ts +128 -128
  21. package/dist/api/verifications/index.d.ts.map +1 -1
  22. package/dist/batch/index.js.map +1 -1
  23. package/dist/cache/core/index.js.map +1 -1
  24. package/dist/cli/index.d.ts +304 -115
  25. package/dist/cli/index.d.ts.map +1 -1
  26. package/dist/cli/index.js +650 -531
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/command/index.d.ts +210 -13
  29. package/dist/command/index.d.ts.map +1 -1
  30. package/dist/command/index.js +306 -69
  31. package/dist/command/index.js.map +1 -1
  32. package/dist/core/index.browser.js.map +1 -1
  33. package/dist/core/index.d.ts +1 -1
  34. package/dist/core/index.d.ts.map +1 -1
  35. package/dist/core/index.js +7 -6
  36. package/dist/core/index.js.map +1 -1
  37. package/dist/core/index.native.js +7 -6
  38. package/dist/core/index.native.js.map +1 -1
  39. package/dist/datetime/index.js.map +1 -1
  40. package/dist/fake/index.js.map +1 -1
  41. package/dist/file/index.d.ts.map +1 -1
  42. package/dist/file/index.js.map +1 -1
  43. package/dist/lock/redis/index.js.map +1 -1
  44. package/dist/logger/index.js.map +1 -1
  45. package/dist/mcp/index.js.map +1 -1
  46. package/dist/orm/index.browser.js +26 -5
  47. package/dist/orm/index.browser.js.map +1 -1
  48. package/dist/orm/index.d.ts +294 -215
  49. package/dist/orm/index.d.ts.map +1 -1
  50. package/dist/orm/index.js +522 -523
  51. package/dist/orm/index.js.map +1 -1
  52. package/dist/queue/redis/index.js +2 -4
  53. package/dist/queue/redis/index.js.map +1 -1
  54. package/dist/redis/index.d.ts +400 -29
  55. package/dist/redis/index.d.ts.map +1 -1
  56. package/dist/redis/index.js +412 -21
  57. package/dist/redis/index.js.map +1 -1
  58. package/dist/retry/index.js.map +1 -1
  59. package/dist/router/index.js.map +1 -1
  60. package/dist/scheduler/index.js.map +1 -1
  61. package/dist/security/index.d.ts.map +1 -1
  62. package/dist/security/index.js.map +1 -1
  63. package/dist/server/auth/index.d.ts +155 -155
  64. package/dist/server/auth/index.js.map +1 -1
  65. package/dist/server/cache/index.js.map +1 -1
  66. package/dist/server/cookies/index.browser.js.map +1 -1
  67. package/dist/server/cookies/index.js.map +1 -1
  68. package/dist/server/core/index.browser.js.map +1 -1
  69. package/dist/server/core/index.d.ts +0 -1
  70. package/dist/server/core/index.d.ts.map +1 -1
  71. package/dist/server/core/index.js.map +1 -1
  72. package/dist/server/helmet/index.d.ts +4 -1
  73. package/dist/server/helmet/index.d.ts.map +1 -1
  74. package/dist/server/helmet/index.js.map +1 -1
  75. package/dist/server/links/index.browser.js.map +1 -1
  76. package/dist/server/links/index.js.map +1 -1
  77. package/dist/server/multipart/index.d.ts.map +1 -1
  78. package/dist/server/multipart/index.js.map +1 -1
  79. package/dist/server/proxy/index.js.map +1 -1
  80. package/dist/server/rate-limit/index.js.map +1 -1
  81. package/dist/server/security/index.d.ts +9 -9
  82. package/dist/server/security/index.js.map +1 -1
  83. package/dist/server/swagger/index.js.map +1 -1
  84. package/dist/thread/index.js.map +1 -1
  85. package/dist/topic/core/index.js.map +1 -1
  86. package/dist/topic/redis/index.js +3 -3
  87. package/dist/topic/redis/index.js.map +1 -1
  88. package/dist/vite/index.js +9 -6
  89. package/dist/vite/index.js.map +1 -1
  90. package/dist/websocket/index.browser.js.map +1 -1
  91. package/dist/websocket/index.d.ts +7 -7
  92. package/dist/websocket/index.js.map +1 -1
  93. package/package.json +3 -3
  94. package/src/api/users/index.ts +4 -0
  95. package/src/cli/apps/AlephaCli.ts +36 -14
  96. package/src/cli/apps/AlephaPackageBuilderCli.ts +5 -1
  97. package/src/cli/assets/appRouterTs.ts +1 -1
  98. package/src/cli/atoms/changelogOptions.ts +45 -0
  99. package/src/cli/commands/{ViteCommands.ts → build.ts} +4 -93
  100. package/src/cli/commands/changelog.ts +244 -0
  101. package/src/cli/commands/clean.ts +14 -0
  102. package/src/cli/commands/{DrizzleCommands.ts → db.ts} +37 -124
  103. package/src/cli/commands/deploy.ts +118 -0
  104. package/src/cli/commands/dev.ts +57 -0
  105. package/src/cli/commands/format.ts +17 -0
  106. package/src/cli/commands/{CoreCommands.ts → init.ts} +2 -40
  107. package/src/cli/commands/lint.ts +17 -0
  108. package/src/cli/commands/root.ts +32 -0
  109. package/src/cli/commands/run.ts +24 -0
  110. package/src/cli/commands/test.ts +42 -0
  111. package/src/cli/commands/typecheck.ts +19 -0
  112. package/src/cli/commands/{VerifyCommands.ts → verify.ts} +1 -13
  113. package/src/cli/defineConfig.ts +24 -0
  114. package/src/cli/index.ts +17 -5
  115. package/src/cli/services/AlephaCliUtils.ts +4 -21
  116. package/src/cli/services/GitMessageParser.ts +77 -0
  117. package/src/command/helpers/EnvUtils.ts +37 -0
  118. package/src/command/index.ts +3 -1
  119. package/src/command/primitives/$command.ts +172 -6
  120. package/src/command/providers/CliProvider.ts +424 -91
  121. package/src/core/Alepha.ts +8 -5
  122. package/src/file/providers/NodeFileSystemProvider.ts +3 -1
  123. package/src/orm/index.browser.ts +1 -1
  124. package/src/orm/index.ts +18 -10
  125. package/src/orm/interfaces/PgQueryWhere.ts +1 -26
  126. package/src/orm/providers/{PostgresTypeProvider.ts → DatabaseTypeProvider.ts} +25 -3
  127. package/src/orm/providers/drivers/BunPostgresProvider.ts +225 -0
  128. package/src/orm/providers/drivers/BunSqliteProvider.ts +180 -0
  129. package/src/orm/providers/drivers/DatabaseProvider.ts +25 -0
  130. package/src/orm/providers/drivers/NodePostgresProvider.ts +0 -25
  131. package/src/orm/services/QueryManager.ts +10 -125
  132. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -7
  133. package/src/redis/index.ts +65 -3
  134. package/src/redis/providers/BunRedisProvider.ts +304 -0
  135. package/src/redis/providers/BunRedisSubscriberProvider.ts +94 -0
  136. package/src/redis/providers/NodeRedisProvider.ts +280 -0
  137. package/src/redis/providers/NodeRedisSubscriberProvider.ts +94 -0
  138. package/src/redis/providers/RedisProvider.ts +134 -140
  139. package/src/redis/providers/RedisSubscriberProvider.ts +58 -49
  140. package/src/server/core/providers/BunHttpServerProvider.ts +0 -3
  141. package/src/server/core/providers/ServerBodyParserProvider.ts +3 -1
  142. package/src/server/core/providers/ServerProvider.ts +7 -4
  143. package/src/server/multipart/providers/ServerMultipartProvider.ts +3 -1
  144. package/src/server/proxy/providers/ServerProxyProvider.ts +1 -1
  145. package/src/topic/redis/providers/RedisTopicProvider.ts +3 -3
  146. package/src/vite/tasks/buildServer.ts +1 -0
  147. package/src/cli/commands/BiomeCommands.ts +0 -29
  148. package/src/cli/commands/ChangelogCommands.ts +0 -389
  149. package/src/orm/services/PgJsonQueryManager.ts +0 -511
package/dist/orm/index.js CHANGED
@@ -3,15 +3,15 @@ import { $atom, $context, $env, $hook, $inject, $module, $use, Alepha, AlephaErr
3
3
  import { AlephaDateTime, DateTimeProvider } from "alepha/datetime";
4
4
  import * as drizzle from "drizzle-orm";
5
5
  import { and, arrayContained, arrayContains, arrayOverlaps, asc, between, desc, eq, getTableName, gt, gte, ilike, inArray, isNotNull, isNull, isSQLWrapper, like, lt, lte, ne, not, notBetween, notIlike, notInArray, notLike, or, sql, sql as sql$1 } from "drizzle-orm";
6
- import * as pg$1 from "drizzle-orm/pg-core";
6
+ import * as pg$2 from "drizzle-orm/pg-core";
7
7
  import { alias, check, customType, foreignKey, index, pgEnum, pgSchema, pgTable, unique, uniqueIndex } from "drizzle-orm/pg-core";
8
8
  import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
9
9
  import { $logger } from "alepha/logger";
10
10
  import { isSQLWrapper as isSQLWrapper$1 } from "drizzle-orm/sql/sql";
11
+ import { $lock } from "alepha/lock";
11
12
  import { randomUUID } from "node:crypto";
12
- import * as pg$2 from "drizzle-orm/sqlite-core";
13
+ import * as pg$1 from "drizzle-orm/sqlite-core";
13
14
  import { check as check$1, foreignKey as foreignKey$1, index as index$1, sqliteTable, unique as unique$1, uniqueIndex as uniqueIndex$1 } from "drizzle-orm/sqlite-core";
14
- import { $lock } from "alepha/lock";
15
15
  import { drizzle as drizzle$1 } from "drizzle-orm/postgres-js";
16
16
  import { migrate } from "drizzle-orm/postgres-js/migrator";
17
17
  import postgres from "postgres";
@@ -289,6 +289,16 @@ var DatabaseProvider = class {
289
289
  throw new DbError(`Failed to synchronize ${this.dialect} database schema`, error);
290
290
  }
291
291
  }
292
+ /**
293
+ * For testing purposes, generate a unique schema name.
294
+ * The schema name will be generated based on the current date and time.
295
+ * It will be in the format of `test_YYYYMMDD_HHMMSS_randomSuffix`.
296
+ */
297
+ generateTestSchemaName() {
298
+ const pad = (n) => n.toString().padStart(2, "0");
299
+ const now = /* @__PURE__ */ new Date();
300
+ return `test_${`${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}_${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`}_${Math.random().toString(36).slice(2, 6)}`;
301
+ }
292
302
  };
293
303
 
294
304
  //#endregion
@@ -353,233 +363,9 @@ var PgRelationManager = class {
353
363
  }
354
364
  };
355
365
 
356
- //#endregion
357
- //#region ../../src/orm/services/PgJsonQueryManager.ts
358
- /**
359
- * Manages JSONB query generation for nested object and array queries in PostgreSQL.
360
- * This class handles complex nested queries using PostgreSQL's JSONB operators.
361
- */
362
- var PgJsonQueryManager = class {
363
- /**
364
- * Check if a query contains nested JSONB queries.
365
- * A nested query is when the value is an object with operator keys.
366
- */
367
- hasNestedQuery(where) {
368
- for (const [key, value] of Object.entries(where)) {
369
- if (key === "and" || key === "or" || key === "not") continue;
370
- if (value && typeof value === "object" && !Array.isArray(value)) {
371
- const keys = Object.keys(value);
372
- if (!keys.some((k) => [
373
- "eq",
374
- "ne",
375
- "gt",
376
- "gte",
377
- "lt",
378
- "lte",
379
- "like",
380
- "ilike",
381
- "isNull",
382
- "isNotNull",
383
- "inArray",
384
- "notInArray"
385
- ].includes(k)) && keys.length > 0) return true;
386
- }
387
- }
388
- return false;
389
- }
390
- /**
391
- * Build a JSONB query condition for nested object queries.
392
- * Supports deep nesting like: { profile: { contact: { email: { eq: "test@example.com" } } } }
393
- *
394
- * @param column The JSONB column
395
- * @param path The path to the nested property (e.g., ['profile', 'contact', 'email'])
396
- * @param operator The filter operator (e.g., { eq: "test@example.com" })
397
- * @param dialect Database dialect (postgresql or sqlite)
398
- * @param columnSchema Optional schema of the JSON column for type inference
399
- * @returns SQL condition
400
- */
401
- buildJsonbCondition(column, path, operator, dialect, columnSchema) {
402
- if (path.length === 0) return;
403
- const isArrayOperator = operator.arrayContains !== void 0 || operator.arrayContained !== void 0 || operator.arrayOverlaps !== void 0;
404
- let jsonValue;
405
- if (dialect === "sqlite") jsonValue = sql$1`json_extract(${column}, ${`$.${path.join(".")}`})`;
406
- else {
407
- let jsonPath = sql$1`${column}`;
408
- for (let i = 0; i < path.length - 1; i++) jsonPath = sql$1`${jsonPath}->${path[i]}`;
409
- const lastPath = path[path.length - 1];
410
- if (isArrayOperator) jsonValue = sql$1`${jsonPath}->${lastPath}`;
411
- else jsonValue = sql$1`${jsonPath}->>${lastPath}`;
412
- }
413
- const fieldType = columnSchema ? this.getFieldType(columnSchema, path) : void 0;
414
- return this.applyOperatorToJsonValue(jsonValue, operator, dialect, fieldType);
415
- }
416
- /**
417
- * Build JSONB array query conditions.
418
- * Supports queries like: { addresses: { city: { eq: "Wonderland" } } }
419
- * which translates to: EXISTS (SELECT 1 FROM jsonb_array_elements(addresses) elem WHERE elem->>'city' = 'Wonderland')
420
- *
421
- * @param dialect Database dialect (postgresql or sqlite)
422
- * Note: SQLite array queries are not yet supported
423
- */
424
- buildJsonbArrayCondition(column, path, arrayPath, operator, dialect) {
425
- if (dialect === "sqlite") throw new Error("Array queries in JSON columns are not yet supported for SQLite. Please use PostgreSQL for complex JSON array queries, or restructure your data.");
426
- if (path.length === 0) return;
427
- let jsonPath = sql$1`${column}`;
428
- if (arrayPath) jsonPath = sql$1`${jsonPath}->${arrayPath}`;
429
- const elemCondition = sql$1`elem->>${path[0]}`;
430
- const condition = this.applyOperatorToJsonValue(elemCondition, operator, dialect);
431
- if (!condition) return;
432
- return sql$1`EXISTS (SELECT 1 FROM jsonb_array_elements(${jsonPath}) AS elem WHERE ${condition})`;
433
- }
434
- /**
435
- * Apply a filter operator to a JSONB value.
436
- * @param dialect Database dialect for appropriate casting syntax
437
- * @param fieldType Optional field type from schema for smart casting
438
- */
439
- applyOperatorToJsonValue(jsonValue, operator, dialect, fieldType) {
440
- const castForNumeric = (value) => {
441
- if (dialect === "sqlite") {
442
- if (fieldType === "integer" || fieldType === "int") return sql$1`CAST(${value} AS INTEGER)`;
443
- return sql$1`CAST(${value} AS REAL)`;
444
- }
445
- return sql$1`(${value})::numeric`;
446
- };
447
- if (typeof operator !== "object") return sql$1`${jsonValue} = ${operator}`;
448
- const conditions = [];
449
- if (operator.eq !== void 0) conditions.push(sql$1`${jsonValue} = ${operator.eq}`);
450
- if (operator.ne !== void 0) conditions.push(sql$1`${jsonValue} != ${operator.ne}`);
451
- if (operator.gt !== void 0) conditions.push(sql$1`${castForNumeric(jsonValue)} > ${operator.gt}`);
452
- if (operator.gte !== void 0) conditions.push(sql$1`${castForNumeric(jsonValue)} >= ${operator.gte}`);
453
- if (operator.lt !== void 0) conditions.push(sql$1`${castForNumeric(jsonValue)} < ${operator.lt}`);
454
- if (operator.lte !== void 0) conditions.push(sql$1`${castForNumeric(jsonValue)} <= ${operator.lte}`);
455
- if (operator.like !== void 0) conditions.push(sql$1`${jsonValue} LIKE ${operator.like}`);
456
- if (operator.ilike !== void 0) if (dialect === "sqlite") conditions.push(sql$1`${jsonValue} LIKE ${operator.ilike}`);
457
- else conditions.push(sql$1`${jsonValue} ILIKE ${operator.ilike}`);
458
- if (operator.notLike !== void 0) conditions.push(sql$1`${jsonValue} NOT LIKE ${operator.notLike}`);
459
- if (operator.notIlike !== void 0) if (dialect === "sqlite") conditions.push(sql$1`${jsonValue} NOT LIKE ${operator.notIlike}`);
460
- else conditions.push(sql$1`${jsonValue} NOT ILIKE ${operator.notIlike}`);
461
- if (operator.isNull !== void 0) conditions.push(sql$1`${jsonValue} IS NULL`);
462
- if (operator.isNotNull !== void 0) conditions.push(sql$1`${jsonValue} IS NOT NULL`);
463
- if (operator.inArray !== void 0 && Array.isArray(operator.inArray)) conditions.push(sql$1`${jsonValue} IN (${sql$1.join(operator.inArray.map((v) => sql$1`${v}`), sql$1`, `)})`);
464
- if (operator.notInArray !== void 0 && Array.isArray(operator.notInArray)) conditions.push(sql$1`${jsonValue} NOT IN (${sql$1.join(operator.notInArray.map((v) => sql$1`${v}`), sql$1`, `)})`);
465
- if (operator.arrayContains !== void 0) {
466
- if (dialect === "postgresql") {
467
- const jsonArray = JSON.stringify(Array.isArray(operator.arrayContains) ? operator.arrayContains : [operator.arrayContains]);
468
- conditions.push(sql$1`${jsonValue} @> ${jsonArray}::jsonb`);
469
- }
470
- }
471
- if (operator.arrayContained !== void 0) {
472
- if (dialect === "postgresql") {
473
- const jsonArray = JSON.stringify(Array.isArray(operator.arrayContained) ? operator.arrayContained : [operator.arrayContained]);
474
- conditions.push(sql$1`${jsonValue} <@ ${jsonArray}::jsonb`);
475
- }
476
- }
477
- if (operator.arrayOverlaps !== void 0) {
478
- if (dialect === "postgresql") {
479
- const overlapConditions = (Array.isArray(operator.arrayOverlaps) ? operator.arrayOverlaps : [operator.arrayOverlaps]).map((val) => {
480
- return sql$1`${jsonValue} @> ${JSON.stringify(val)}::jsonb`;
481
- });
482
- if (overlapConditions.length > 0) conditions.push(sql$1`(${sql$1.join(overlapConditions, sql$1` OR `)})`);
483
- }
484
- }
485
- if (conditions.length === 0) return;
486
- if (conditions.length === 1) return conditions[0];
487
- return sql$1.join(conditions, sql$1` AND `);
488
- }
489
- /**
490
- * Parse a nested query object and extract the path and operator.
491
- * For example: { profile: { contact: { email: { eq: "test@example.com" } } } }
492
- * Returns: { path: ['profile', 'contact', 'email'], operator: { eq: "test@example.com" } }
493
- */
494
- parseNestedQuery(nestedQuery, currentPath = []) {
495
- const results = [];
496
- for (const [key, value] of Object.entries(nestedQuery)) if (value && typeof value === "object" && !Array.isArray(value)) if (Object.keys(value).some((k) => [
497
- "eq",
498
- "ne",
499
- "gt",
500
- "gte",
501
- "lt",
502
- "lte",
503
- "like",
504
- "ilike",
505
- "notLike",
506
- "notIlike",
507
- "isNull",
508
- "isNotNull",
509
- "inArray",
510
- "notInArray",
511
- "arrayContains",
512
- "arrayContained",
513
- "arrayOverlaps"
514
- ].includes(k))) results.push({
515
- path: [...currentPath, key],
516
- operator: value
517
- });
518
- else {
519
- const nestedResults = this.parseNestedQuery(value, [...currentPath, key]);
520
- results.push(...nestedResults);
521
- }
522
- return results;
523
- }
524
- /**
525
- * Determine if a property is a JSONB column based on the schema.
526
- * A column is JSONB if it's defined as an object or array in the TypeBox schema.
527
- */
528
- isJsonbColumn(schema$1, columnName) {
529
- const property = schema$1.properties[columnName];
530
- if (!property) return false;
531
- return property.type === "object" || property.type === "array";
532
- }
533
- /**
534
- * Check if an array property contains primitive types (string, number, boolean, etc.)
535
- * rather than objects. Primitive arrays should use native Drizzle operators.
536
- * @returns true if the array contains primitives, false if it contains objects
537
- */
538
- isPrimitiveArray(schema$1, columnName) {
539
- const property = schema$1.properties[columnName];
540
- if (!property || property.type !== "array") return false;
541
- const items = property.items;
542
- if (!items) return false;
543
- const itemType = items.type;
544
- return itemType === "string" || itemType === "number" || itemType === "integer" || itemType === "boolean" || itemType === "null";
545
- }
546
- /**
547
- * Get the type of a field by navigating through a schema path.
548
- * Used for smart type casting in SQL queries.
549
- *
550
- * @param columnSchema The schema of the JSON column (e.g., t.object({ age: t.integer() }))
551
- * @param path The path to navigate (e.g., ['contact', 'email'])
552
- * @returns The type string (e.g., 'integer', 'number', 'string') or undefined if not found
553
- */
554
- getFieldType(columnSchema, path) {
555
- let current = columnSchema;
556
- for (const segment of path) if (current.type === "object" && current.properties) {
557
- current = current.properties[segment];
558
- if (!current) return;
559
- } else return;
560
- return current.type;
561
- }
562
- /**
563
- * Check if a nested path points to an array property.
564
- */
565
- isArrayProperty(schema$1, path) {
566
- if (path.length === 0) return false;
567
- let currentSchema = schema$1.properties[path[0]];
568
- if (!currentSchema) return false;
569
- if (currentSchema.type === "array") return true;
570
- for (let i = 1; i < path.length; i++) if (currentSchema.type === "object" && currentSchema.properties) {
571
- currentSchema = currentSchema.properties[path[i]];
572
- if (!currentSchema) return false;
573
- if (currentSchema.type === "array") return true;
574
- } else return false;
575
- return false;
576
- }
577
- };
578
-
579
366
  //#endregion
580
367
  //#region ../../src/orm/services/QueryManager.ts
581
368
  var QueryManager = class {
582
- jsonQueryManager = $inject(PgJsonQueryManager);
583
369
  alepha = $inject(Alepha);
584
370
  /**
585
371
  * Convert a query object to a SQL query.
@@ -639,11 +425,7 @@ var QueryManager = class {
639
425
  });
640
426
  if (where) return not(where);
641
427
  }
642
- if (operator) if (this.jsonQueryManager.isJsonbColumn(schema$1, key) && !this.jsonQueryManager.isPrimitiveArray(schema$1, key) && typeof operator === "object" && !Array.isArray(operator) && this.jsonQueryManager.hasNestedQuery({ [key]: operator })) {
643
- const column = col(key);
644
- const jsonbSql = this.buildJsonbQuery(column, operator, schema$1, key, options.dialect);
645
- if (jsonbSql) conditions.push(jsonbSql);
646
- } else {
428
+ if (operator) {
647
429
  const column = col(key);
648
430
  const sql$2 = this.mapOperatorToSql(operator, column, schema$1, key, options.dialect);
649
431
  if (sql$2) conditions.push(sql$2);
@@ -654,32 +436,6 @@ var QueryManager = class {
654
436
  return and(...conditions);
655
437
  }
656
438
  /**
657
- * Build a JSONB query for nested object/array queries.
658
- */
659
- buildJsonbQuery(column, nestedQuery, schema$1, columnName, dialect) {
660
- const queries = this.jsonQueryManager.parseNestedQuery(nestedQuery);
661
- if (queries.length === 0) return;
662
- const columnSchema = schema$1.properties[columnName];
663
- const conditions = [];
664
- for (const { path, operator } of queries) {
665
- const isArrayOperator = operator.arrayContains !== void 0 || operator.arrayContained !== void 0 || operator.arrayOverlaps !== void 0;
666
- const isArrayProp = this.jsonQueryManager.isArrayProperty(schema$1, [columnName, ...path]);
667
- if (isArrayProp && isArrayOperator) {
668
- const condition = this.jsonQueryManager.buildJsonbCondition(column, path, operator, dialect, columnSchema);
669
- if (condition) conditions.push(condition);
670
- } else if (isArrayProp && !isArrayOperator) {
671
- const condition = this.jsonQueryManager.buildJsonbArrayCondition(column, path, "", operator, dialect);
672
- if (condition) conditions.push(condition);
673
- } else {
674
- const condition = this.jsonQueryManager.buildJsonbCondition(column, path, operator, dialect, columnSchema);
675
- if (condition) conditions.push(condition);
676
- }
677
- }
678
- if (conditions.length === 0) return;
679
- if (conditions.length === 1) return conditions[0];
680
- return and(...conditions);
681
- }
682
- /**
683
439
  * Check if an object has any filter operator properties.
684
440
  */
685
441
  hasFilterOperatorProperties(obj) {
@@ -947,11 +703,11 @@ var Repository = class {
947
703
  * Start a SELECT DISTINCT query on the table.
948
704
  */
949
705
  rawSelectDistinct(opts = {}, columns = []) {
950
- const db = opts.tx ?? this.db;
706
+ const db$1 = opts.tx ?? this.db;
951
707
  const table = this.table;
952
708
  const fields = {};
953
709
  for (const column of columns) if (typeof column === "string") fields[column] = this.col(column);
954
- return db.selectDistinct(fields).from(table);
710
+ return db$1.selectDistinct(fields).from(table);
955
711
  }
956
712
  /**
957
713
  * Start an INSERT query on the table.
@@ -1690,6 +1446,22 @@ const devMigrationsSchema = t.object({
1690
1446
  created_at: t.string()
1691
1447
  });
1692
1448
 
1449
+ //#endregion
1450
+ //#region ../../src/orm/errors/DbMigrationError.ts
1451
+ var DbMigrationError = class extends DbError {
1452
+ name = "DbMigrationError";
1453
+ constructor(cause) {
1454
+ super("Failed to migrate database", cause);
1455
+ }
1456
+ };
1457
+
1458
+ //#endregion
1459
+ //#region ../../src/orm/types/byte.ts
1460
+ /**
1461
+ * Postgres bytea type.
1462
+ */
1463
+ const byte = customType({ dataType: () => "bytea" });
1464
+
1693
1465
  //#endregion
1694
1466
  //#region ../../src/orm/services/ModelBuilder.ts
1695
1467
  /**
@@ -1783,39 +1555,52 @@ var ModelBuilder = class {
1783
1555
  };
1784
1556
 
1785
1557
  //#endregion
1786
- //#region ../../src/orm/services/SqliteModelBuilder.ts
1787
- var SqliteModelBuilder = class extends ModelBuilder {
1558
+ //#region ../../src/orm/services/PostgresModelBuilder.ts
1559
+ var PostgresModelBuilder = class extends ModelBuilder {
1560
+ schemas = /* @__PURE__ */ new Map();
1561
+ getPgSchema(name) {
1562
+ if (!this.schemas.has(name) && name !== "public") this.schemas.set(name, pgSchema(name));
1563
+ const nsp = name !== "public" ? this.schemas.get(name) : {
1564
+ enum: pgEnum,
1565
+ table: pgTable
1566
+ };
1567
+ if (!nsp) throw new AlephaError(`Postgres schema ${name} not found`);
1568
+ return nsp;
1569
+ }
1788
1570
  buildTable(entity, options) {
1789
1571
  const tableName = entity.name;
1790
1572
  if (options.tables.has(tableName)) return;
1791
- const table = sqliteTable(tableName, this.schemaToSqliteColumns(tableName, entity.schema, options.enums, options.tables), this.getTableConfig(entity, options.tables));
1573
+ const nsp = this.getPgSchema(options.schema);
1574
+ const columns = this.schemaToPgColumns(tableName, entity.schema, nsp, options.enums, options.tables);
1575
+ const configFn = this.getTableConfig(entity, options.tables);
1576
+ const table = nsp.table(tableName, columns, configFn);
1792
1577
  options.tables.set(tableName, table);
1793
1578
  }
1794
1579
  buildSequence(sequence, options) {
1795
- throw new AlephaError("SQLite does not support sequences");
1580
+ const sequenceName = sequence.name;
1581
+ if (options.sequences.has(sequenceName)) return;
1582
+ const nsp = this.getPgSchema(options.schema);
1583
+ options.sequences.set(sequenceName, nsp.sequence(sequenceName, sequence.options));
1796
1584
  }
1797
1585
  /**
1798
- * Get SQLite-specific config builder for the table.
1586
+ * Get PostgreSQL-specific config builder for the table.
1799
1587
  */
1800
1588
  getTableConfig(entity, tables) {
1801
- const sqliteBuilders = {
1802
- index: index$1,
1803
- uniqueIndex: uniqueIndex$1,
1804
- unique: unique$1,
1805
- check: check$1,
1806
- foreignKey: foreignKey$1
1589
+ const pgBuilders = {
1590
+ index,
1591
+ uniqueIndex,
1592
+ unique,
1593
+ check,
1594
+ foreignKey
1807
1595
  };
1808
1596
  const tableResolver = (entityName) => {
1809
1597
  return tables.get(entityName);
1810
1598
  };
1811
- return this.buildTableConfig(entity, sqliteBuilders, tableResolver, (config, self) => {
1812
- const customConfigs = config(self);
1813
- return Array.isArray(customConfigs) ? customConfigs : [];
1814
- });
1599
+ return this.buildTableConfig(entity, pgBuilders, tableResolver);
1815
1600
  }
1816
- schemaToSqliteColumns = (tableName, schema$1, enums, tables) => {
1601
+ schemaToPgColumns = (tableName, schema$1, nsp, enums, tables) => {
1817
1602
  return Object.entries(schema$1.properties).reduce((columns, [key, value]) => {
1818
- let col = this.mapFieldToSqliteColumn(tableName, key, value, enums);
1603
+ let col = this.mapFieldToColumn(tableName, key, value, nsp, enums);
1819
1604
  if ("default" in value && value.default != null) col = col.default(value.default);
1820
1605
  if (PG_PRIMARY_KEY in value) col = col.primaryKey();
1821
1606
  if (PG_REF in value) {
@@ -1836,219 +1621,255 @@ var SqliteModelBuilder = class extends ModelBuilder {
1836
1621
  };
1837
1622
  }, {});
1838
1623
  };
1839
- mapFieldToSqliteColumn = (tableName, fieldName, value, enums) => {
1624
+ mapFieldToColumn = (tableName, fieldName, value, nsp, enums) => {
1840
1625
  const key = this.toColumnName(fieldName);
1841
1626
  if ("anyOf" in value && Array.isArray(value.anyOf) && value.anyOf.length === 2 && value.anyOf.some((it) => t.schema.isNull(it))) value = value.anyOf.find((it) => !t.schema.isNull(it));
1842
1627
  if (t.schema.isInteger(value)) {
1843
- if (PG_SERIAL in value || PG_IDENTITY in value) return pg$2.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
1628
+ if (PG_SERIAL in value) return pg$2.serial(key);
1629
+ if (PG_IDENTITY in value) {
1630
+ const options = value[PG_IDENTITY];
1631
+ if (options.mode === "byDefault") return pg$2.integer().generatedByDefaultAsIdentity(options);
1632
+ return pg$2.integer().generatedAlwaysAsIdentity(options);
1633
+ }
1844
1634
  return pg$2.integer(key);
1845
1635
  }
1846
1636
  if (t.schema.isBigInt(value)) {
1847
- if (PG_PRIMARY_KEY in value || PG_IDENTITY in value) return pg$2.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
1848
- return pg$2.integer(key, { mode: "number" });
1637
+ if (PG_IDENTITY in value) {
1638
+ const options = value[PG_IDENTITY];
1639
+ if (options.mode === "byDefault") return pg$2.bigint({ mode: "bigint" }).generatedByDefaultAsIdentity(options);
1640
+ return pg$2.bigint({ mode: "bigint" }).generatedAlwaysAsIdentity(options);
1641
+ }
1849
1642
  }
1850
1643
  if (t.schema.isNumber(value)) {
1851
- if (PG_IDENTITY in value) return pg$2.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
1644
+ if (PG_IDENTITY in value) {
1645
+ const options = value[PG_IDENTITY];
1646
+ if (options.mode === "byDefault") return pg$2.bigint({ mode: "number" }).generatedByDefaultAsIdentity(options);
1647
+ return pg$2.bigint({ mode: "number" }).generatedAlwaysAsIdentity(options);
1648
+ }
1649
+ if (value.format === "int64") return pg$2.bigint(key, { mode: "number" });
1852
1650
  return pg$2.numeric(key);
1853
1651
  }
1854
- if (t.schema.isString(value)) return this.mapStringToSqliteColumn(key, value);
1855
- if (t.schema.isBoolean(value)) return this.sqliteBool(key, value);
1856
- if (t.schema.isObject(value)) return this.sqliteJson(key, value);
1857
- if (t.schema.isRecord(value)) return this.sqliteJson(key, value);
1858
- if (t.schema.isAny(value)) return this.sqliteJson(key, value);
1652
+ if (t.schema.isString(value)) return this.mapStringToColumn(key, value);
1653
+ if (t.schema.isBoolean(value)) return pg$2.boolean(key);
1654
+ if (t.schema.isObject(value)) return schema(key, value);
1655
+ if (t.schema.isRecord(value)) return schema(key, value);
1656
+ const isTypeEnum = (value$1) => t.schema.isUnsafe(value$1) && "type" in value$1 && value$1.type === "string" && "enum" in value$1 && Array.isArray(value$1.enum);
1859
1657
  if (t.schema.isArray(value)) {
1860
- if (t.schema.isObject(value.items)) return this.sqliteJson(key, value);
1861
- if (t.schema.isRecord(value.items)) return this.sqliteJson(key, value);
1862
- if (t.schema.isAny(value.items)) return this.sqliteJson(key, value);
1863
- if (t.schema.isString(value.items)) return this.sqliteJson(key, value);
1864
- if (t.schema.isInteger(value.items)) return this.sqliteJson(key, value);
1865
- if (t.schema.isNumber(value.items)) return this.sqliteJson(key, value);
1866
- if (t.schema.isBoolean(value.items)) return this.sqliteJson(key, value);
1658
+ if (t.schema.isObject(value.items)) return schema(key, value);
1659
+ if (t.schema.isRecord(value.items)) return schema(key, value);
1660
+ if (t.schema.isString(value.items)) return pg$2.text(key).array();
1661
+ if (t.schema.isInteger(value.items)) return pg$2.integer(key).array();
1662
+ if (t.schema.isNumber(value.items)) return pg$2.numeric(key).array();
1663
+ if (t.schema.isBoolean(value.items)) return pg$2.boolean(key).array();
1664
+ if (isTypeEnum(value.items)) return pg$2.text(key).array();
1867
1665
  }
1868
- if (t.schema.isUnsafe(value) && "type" in value && value.type === "string") return this.mapStringToSqliteColumn(key, value);
1869
- throw new Error(`Unsupported schema for field '${tableName}.${fieldName}' (schema: ${JSON.stringify(value)})`);
1870
- };
1871
- mapStringToSqliteColumn = (key, value) => {
1872
- if (value.format === "uuid") {
1873
- if (PG_PRIMARY_KEY in value) return pg$2.text(key).primaryKey().$defaultFn(() => randomUUID());
1874
- return pg$2.text(key);
1666
+ if (isTypeEnum(value)) {
1667
+ if (!value.enum.every((it) => typeof it === "string")) throw new AlephaError(`Enum for ${fieldName} must be an array of strings, got ${JSON.stringify(value.enum)}`);
1668
+ if (PG_ENUM in value && value[PG_ENUM]) {
1669
+ const enumName = value[PG_ENUM].name ?? `${tableName}_${key}_enum`;
1670
+ if (enums.has(enumName)) {
1671
+ const values = enums.get(enumName).enumValues.join(",");
1672
+ const newValues = value.enum.join(",");
1673
+ if (values !== newValues) throw new AlephaError(`Enum name conflict for ${enumName}: [${values}] vs [${newValues}]`);
1674
+ }
1675
+ enums.set(enumName, nsp.enum(enumName, value.enum));
1676
+ return enums.get(enumName)(key);
1677
+ }
1678
+ return this.mapStringToColumn(key, value);
1875
1679
  }
1876
- if (value.format === "byte") return this.sqliteJson(key, value);
1877
- if (value.format === "date-time") {
1878
- if (PG_CREATED_AT in value) return this.sqliteDateTime(key, {}).default(sql$1`(unixepoch('subsec') * 1000)`);
1879
- if (PG_UPDATED_AT in value) return this.sqliteDateTime(key, {}).default(sql$1`(unixepoch('subsec') * 1000)`);
1880
- return this.sqliteDateTime(key, {});
1680
+ throw new AlephaError(`Unsupported schema type for ${fieldName} as ${JSON.stringify(value)}`);
1681
+ };
1682
+ /**
1683
+ * Map a string to a PG column.
1684
+ *
1685
+ * @param key The key of the field.
1686
+ * @param value The value of the field.
1687
+ */
1688
+ mapStringToColumn = (key, value) => {
1689
+ if ("format" in value) {
1690
+ if (value.format === "uuid") {
1691
+ if (PG_PRIMARY_KEY in value) return pg$2.uuid(key).defaultRandom();
1692
+ return pg$2.uuid(key);
1693
+ }
1694
+ if (value.format === "byte") return byte(key);
1695
+ if (value.format === "date-time") {
1696
+ if (PG_CREATED_AT in value) return pg$2.timestamp(key, {
1697
+ mode: "string",
1698
+ withTimezone: true
1699
+ }).defaultNow();
1700
+ if (PG_UPDATED_AT in value) return pg$2.timestamp(key, {
1701
+ mode: "string",
1702
+ withTimezone: true
1703
+ }).defaultNow();
1704
+ return pg$2.timestamp(key, {
1705
+ mode: "string",
1706
+ withTimezone: true
1707
+ });
1708
+ }
1709
+ if (value.format === "date") return pg$2.date(key, { mode: "string" });
1881
1710
  }
1882
- if (value.format === "date") return this.sqliteDate(key, {});
1883
1711
  return pg$2.text(key);
1884
1712
  };
1885
- sqliteJson = (name, document) => pg$2.customType({
1886
- dataType: () => "text",
1887
- toDriver: (value) => JSON.stringify(value),
1888
- fromDriver: (value) => {
1889
- return value && typeof value === "string" ? JSON.parse(value) : value;
1890
- }
1891
- })(name, { document }).$type();
1892
- sqliteDateTime = pg$2.customType({
1893
- dataType: () => "integer",
1894
- toDriver: (value) => new Date(value).getTime(),
1895
- fromDriver: (value) => {
1896
- return new Date(value).toISOString();
1897
- }
1898
- });
1899
- sqliteBool = pg$2.customType({
1900
- dataType: () => "integer",
1901
- toDriver: (value) => value ? 1 : 0,
1902
- fromDriver: (value) => value === 1
1903
- });
1904
- sqliteDate = pg$2.customType({
1905
- dataType: () => "integer",
1906
- toDriver: (value) => new Date(value).getTime(),
1907
- fromDriver: (value) => {
1908
- return new Date(value).toISOString().split("T")[0];
1909
- }
1910
- });
1911
1713
  };
1912
1714
 
1913
1715
  //#endregion
1914
- //#region ../../src/orm/providers/drivers/CloudflareD1Provider.ts
1716
+ //#region ../../src/orm/providers/drivers/BunPostgresProvider.ts
1717
+ const envSchema$4 = t.object({
1718
+ DATABASE_URL: t.optional(t.text()),
1719
+ POSTGRES_SCHEMA: t.optional(t.text())
1720
+ });
1915
1721
  /**
1916
- * Cloudflare D1 SQLite provider using Drizzle ORM.
1722
+ * Bun PostgreSQL provider using Drizzle ORM with Bun's native SQL client.
1917
1723
  *
1918
- * This provider requires a D1 binding to be set via `cloudflareD1Options` before starting.
1919
- * The binding is typically obtained from the Cloudflare Workers environment.
1724
+ * This provider uses Bun's built-in SQL class for PostgreSQL connections,
1725
+ * which provides excellent performance on the Bun runtime.
1920
1726
  *
1921
1727
  * @example
1922
1728
  * ```ts
1923
- * // In your Cloudflare Worker
1924
- * alepha.set(cloudflareD1Options, { binding: env.DB });
1729
+ * // Set DATABASE_URL environment variable
1730
+ * // DATABASE_URL=postgres://user:password@localhost:5432/database
1731
+ *
1732
+ * // Or configure programmatically
1733
+ * alepha.with({
1734
+ * provide: DatabaseProvider,
1735
+ * use: BunPostgresProvider,
1736
+ * });
1925
1737
  * ```
1926
1738
  */
1927
- var CloudflareD1Provider = class extends DatabaseProvider {
1928
- kit = $inject(DrizzleKitProvider);
1739
+ var BunPostgresProvider = class extends DatabaseProvider {
1929
1740
  log = $logger();
1930
- builder = $inject(SqliteModelBuilder);
1931
- env = $env(t.object({ DATABASE_URL: t.string({ description: "Expect to be 'cloudflare-d1://name:id'" }) }));
1932
- d1;
1933
- drizzleDb;
1741
+ env = $env(envSchema$4);
1742
+ kit = $inject(DrizzleKitProvider);
1743
+ builder = $inject(PostgresModelBuilder);
1744
+ client;
1745
+ bunDb;
1746
+ dialect = "postgresql";
1934
1747
  get name() {
1935
- return "d1";
1748
+ return "bun-postgres";
1936
1749
  }
1937
- dialect = "sqlite";
1750
+ /**
1751
+ * In testing mode, the schema name will be generated and deleted after the test.
1752
+ */
1753
+ schemaForTesting = this.alepha.isTest() ? this.env.POSTGRES_SCHEMA?.startsWith("test_") ? this.env.POSTGRES_SCHEMA : this.generateTestSchemaName() : void 0;
1938
1754
  get url() {
1755
+ if (!this.env.DATABASE_URL) throw new AlephaError("DATABASE_URL is not defined in the environment");
1939
1756
  return this.env.DATABASE_URL;
1940
1757
  }
1758
+ /**
1759
+ * Execute a SQL statement.
1760
+ */
1761
+ execute(statement) {
1762
+ try {
1763
+ return this.db.execute(statement);
1764
+ } catch (error) {
1765
+ throw new DbError("Error executing statement", error);
1766
+ }
1767
+ }
1768
+ /**
1769
+ * Get Postgres schema used by this provider.
1770
+ */
1771
+ get schema() {
1772
+ if (this.schemaForTesting) return this.schemaForTesting;
1773
+ if (this.env.POSTGRES_SCHEMA) return this.env.POSTGRES_SCHEMA;
1774
+ return "public";
1775
+ }
1776
+ /**
1777
+ * Get the Drizzle Postgres database instance.
1778
+ */
1941
1779
  get db() {
1942
- if (!this.drizzleDb) throw new AlephaError("D1 database not initialized");
1943
- return this.drizzleDb;
1780
+ if (!this.bunDb) throw new AlephaError("Database not initialized");
1781
+ return this.bunDb;
1944
1782
  }
1945
- async execute(query) {
1946
- const { rows } = await this.db.run(query);
1947
- return rows;
1783
+ async executeMigrations(migrationsFolder) {
1784
+ const { migrate: migrate$3 } = await import("drizzle-orm/bun-sql/migrator");
1785
+ await migrate$3(this.bunDb, { migrationsFolder });
1948
1786
  }
1949
1787
  onStart = $hook({
1950
1788
  on: "start",
1951
1789
  handler: async () => {
1952
- const [bindingName] = this.env.DATABASE_URL.replace("cloudflare-d1://", "").split(":");
1953
- const cloudflareEnv = this.alepha.store.get("cloudflare.env");
1954
- if (!cloudflareEnv) throw new AlephaError("Cloudflare Workers environment not found in Alepha store under 'cloudflare.env'.");
1955
- const binding = cloudflareEnv[bindingName];
1956
- if (!binding) throw new AlephaError(`D1 binding '${bindingName}' not found in Cloudflare Workers environment.`);
1957
- this.d1 = binding;
1958
- const { drizzle: drizzle$3 } = await import("drizzle-orm/d1");
1959
- this.drizzleDb = drizzle$3(this.d1);
1960
- await this.migrateDatabase();
1961
- this.log.info("Using Cloudflare D1 database");
1790
+ await this.connect();
1791
+ if (!this.alepha.isServerless()) try {
1792
+ await this.migrate.run();
1793
+ } catch (error) {
1794
+ throw new DbMigrationError(error);
1795
+ }
1962
1796
  }
1963
1797
  });
1964
- async executeMigrations(migrationsFolder) {
1965
- const { migrate: migrate$3 } = await import("drizzle-orm/d1/migrator");
1966
- await migrate$3(this.db, { migrationsFolder });
1967
- }
1968
- /**
1969
- * Override development migration to skip sync (not supported on D1).
1970
- * D1 requires proper migrations to be applied.
1971
- */
1972
- async runDevelopmentMigration(migrationsFolder) {
1973
- await this.executeMigrations(migrationsFolder);
1974
- }
1975
- /**
1976
- * Override test migration to run migrations instead of sync.
1977
- * D1 doesn't support schema synchronization.
1978
- */
1979
- async runTestMigration() {
1980
- const migrationsFolder = this.getMigrationsFolder();
1981
- try {
1982
- await this.executeMigrations(migrationsFolder);
1983
- } catch {
1984
- this.log.warn("D1 migrations failed in test environment - ensure migrations exist");
1798
+ onStop = $hook({
1799
+ on: "stop",
1800
+ handler: async () => {
1801
+ if (this.alepha.isTest() && this.schemaForTesting && this.schemaForTesting.startsWith("test_")) {
1802
+ if (!/^test_[a-z0-9_]+$/i.test(this.schemaForTesting)) throw new AlephaError(`Invalid test schema name: ${this.schemaForTesting}. Must match pattern: test_[a-z0-9_]+`);
1803
+ this.log.warn(`Deleting test schema '${this.schemaForTesting}' ...`);
1804
+ await this.execute(sql$1`DROP SCHEMA IF EXISTS ${sql$1.raw(this.schemaForTesting)} CASCADE`);
1805
+ this.log.info(`Test schema '${this.schemaForTesting}' deleted`);
1806
+ }
1807
+ await this.close();
1985
1808
  }
1809
+ });
1810
+ async connect() {
1811
+ this.log.debug("Connect ..");
1812
+ if (typeof Bun === "undefined") throw new AlephaError("BunPostgresProvider requires the Bun runtime. Use NodePostgresProvider for Node.js.");
1813
+ const { drizzle: drizzle$3 } = await import("drizzle-orm/bun-sql");
1814
+ const { SQL: SQL$1 } = await import("bun");
1815
+ this.client = new SQL$1(this.url);
1816
+ await this.client.unsafe("SELECT 1");
1817
+ this.bunDb = drizzle$3({
1818
+ client: this.client,
1819
+ logger: { logQuery: (query, params) => {
1820
+ this.log.trace(query, { params });
1821
+ } }
1822
+ });
1823
+ this.log.info("Connection OK");
1986
1824
  }
1987
- };
1988
-
1989
- //#endregion
1990
- //#region ../../src/orm/errors/DbMigrationError.ts
1991
- var DbMigrationError = class extends DbError {
1992
- name = "DbMigrationError";
1993
- constructor(cause) {
1994
- super("Failed to migrate database", cause);
1825
+ async close() {
1826
+ if (this.client) {
1827
+ this.log.debug("Close...");
1828
+ await this.client.close();
1829
+ this.client = void 0;
1830
+ this.bunDb = void 0;
1831
+ this.log.info("Connection closed");
1832
+ }
1995
1833
  }
1834
+ migrate = $lock({ handler: async () => {
1835
+ await this.migrateDatabase();
1836
+ } });
1996
1837
  };
1997
1838
 
1998
1839
  //#endregion
1999
- //#region ../../src/orm/types/byte.ts
2000
- /**
2001
- * Postgres bytea type.
2002
- */
2003
- const byte = customType({ dataType: () => "bytea" });
2004
-
2005
- //#endregion
2006
- //#region ../../src/orm/services/PostgresModelBuilder.ts
2007
- var PostgresModelBuilder = class extends ModelBuilder {
2008
- schemas = /* @__PURE__ */ new Map();
2009
- getPgSchema(name) {
2010
- if (!this.schemas.has(name) && name !== "public") this.schemas.set(name, pgSchema(name));
2011
- const nsp = name !== "public" ? this.schemas.get(name) : {
2012
- enum: pgEnum,
2013
- table: pgTable
2014
- };
2015
- if (!nsp) throw new AlephaError(`Postgres schema ${name} not found`);
2016
- return nsp;
2017
- }
1840
+ //#region ../../src/orm/services/SqliteModelBuilder.ts
1841
+ var SqliteModelBuilder = class extends ModelBuilder {
2018
1842
  buildTable(entity, options) {
2019
1843
  const tableName = entity.name;
2020
1844
  if (options.tables.has(tableName)) return;
2021
- const nsp = this.getPgSchema(options.schema);
2022
- const columns = this.schemaToPgColumns(tableName, entity.schema, nsp, options.enums, options.tables);
2023
- const configFn = this.getTableConfig(entity, options.tables);
2024
- const table = nsp.table(tableName, columns, configFn);
1845
+ const table = sqliteTable(tableName, this.schemaToSqliteColumns(tableName, entity.schema, options.enums, options.tables), this.getTableConfig(entity, options.tables));
2025
1846
  options.tables.set(tableName, table);
2026
1847
  }
2027
1848
  buildSequence(sequence, options) {
2028
- const sequenceName = sequence.name;
2029
- if (options.sequences.has(sequenceName)) return;
2030
- const nsp = this.getPgSchema(options.schema);
2031
- options.sequences.set(sequenceName, nsp.sequence(sequenceName, sequence.options));
1849
+ throw new AlephaError("SQLite does not support sequences");
2032
1850
  }
2033
1851
  /**
2034
- * Get PostgreSQL-specific config builder for the table.
1852
+ * Get SQLite-specific config builder for the table.
2035
1853
  */
2036
1854
  getTableConfig(entity, tables) {
2037
- const pgBuilders = {
2038
- index,
2039
- uniqueIndex,
2040
- unique,
2041
- check,
2042
- foreignKey
1855
+ const sqliteBuilders = {
1856
+ index: index$1,
1857
+ uniqueIndex: uniqueIndex$1,
1858
+ unique: unique$1,
1859
+ check: check$1,
1860
+ foreignKey: foreignKey$1
2043
1861
  };
2044
1862
  const tableResolver = (entityName) => {
2045
1863
  return tables.get(entityName);
2046
1864
  };
2047
- return this.buildTableConfig(entity, pgBuilders, tableResolver);
1865
+ return this.buildTableConfig(entity, sqliteBuilders, tableResolver, (config, self) => {
1866
+ const customConfigs = config(self);
1867
+ return Array.isArray(customConfigs) ? customConfigs : [];
1868
+ });
2048
1869
  }
2049
- schemaToPgColumns = (tableName, schema$1, nsp, enums, tables) => {
1870
+ schemaToSqliteColumns = (tableName, schema$1, enums, tables) => {
2050
1871
  return Object.entries(schema$1.properties).reduce((columns, [key, value]) => {
2051
- let col = this.mapFieldToColumn(tableName, key, value, nsp, enums);
1872
+ let col = this.mapFieldToSqliteColumn(tableName, key, value, enums);
2052
1873
  if ("default" in value && value.default != null) col = col.default(value.default);
2053
1874
  if (PG_PRIMARY_KEY in value) col = col.primaryKey();
2054
1875
  if (PG_REF in value) {
@@ -2069,95 +1890,257 @@ var PostgresModelBuilder = class extends ModelBuilder {
2069
1890
  };
2070
1891
  }, {});
2071
1892
  };
2072
- mapFieldToColumn = (tableName, fieldName, value, nsp, enums) => {
1893
+ mapFieldToSqliteColumn = (tableName, fieldName, value, enums) => {
2073
1894
  const key = this.toColumnName(fieldName);
2074
1895
  if ("anyOf" in value && Array.isArray(value.anyOf) && value.anyOf.length === 2 && value.anyOf.some((it) => t.schema.isNull(it))) value = value.anyOf.find((it) => !t.schema.isNull(it));
2075
1896
  if (t.schema.isInteger(value)) {
2076
- if (PG_SERIAL in value) return pg$1.serial(key);
2077
- if (PG_IDENTITY in value) {
2078
- const options = value[PG_IDENTITY];
2079
- if (options.mode === "byDefault") return pg$1.integer().generatedByDefaultAsIdentity(options);
2080
- return pg$1.integer().generatedAlwaysAsIdentity(options);
2081
- }
1897
+ if (PG_SERIAL in value || PG_IDENTITY in value) return pg$1.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
2082
1898
  return pg$1.integer(key);
2083
1899
  }
2084
1900
  if (t.schema.isBigInt(value)) {
2085
- if (PG_IDENTITY in value) {
2086
- const options = value[PG_IDENTITY];
2087
- if (options.mode === "byDefault") return pg$1.bigint({ mode: "bigint" }).generatedByDefaultAsIdentity(options);
2088
- return pg$1.bigint({ mode: "bigint" }).generatedAlwaysAsIdentity(options);
2089
- }
1901
+ if (PG_PRIMARY_KEY in value || PG_IDENTITY in value) return pg$1.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
1902
+ return pg$1.integer(key, { mode: "number" });
2090
1903
  }
2091
1904
  if (t.schema.isNumber(value)) {
2092
- if (PG_IDENTITY in value) {
2093
- const options = value[PG_IDENTITY];
2094
- if (options.mode === "byDefault") return pg$1.bigint({ mode: "number" }).generatedByDefaultAsIdentity(options);
2095
- return pg$1.bigint({ mode: "number" }).generatedAlwaysAsIdentity(options);
2096
- }
2097
- if (value.format === "int64") return pg$1.bigint(key, { mode: "number" });
1905
+ if (PG_IDENTITY in value) return pg$1.integer(key, { mode: "number" }).primaryKey({ autoIncrement: true });
2098
1906
  return pg$1.numeric(key);
2099
1907
  }
2100
- if (t.schema.isString(value)) return this.mapStringToColumn(key, value);
2101
- if (t.schema.isBoolean(value)) return pg$1.boolean(key);
2102
- if (t.schema.isObject(value)) return schema(key, value);
2103
- if (t.schema.isRecord(value)) return schema(key, value);
2104
- const isTypeEnum = (value$1) => t.schema.isUnsafe(value$1) && "type" in value$1 && value$1.type === "string" && "enum" in value$1 && Array.isArray(value$1.enum);
1908
+ if (t.schema.isString(value)) return this.mapStringToSqliteColumn(key, value);
1909
+ if (t.schema.isBoolean(value)) return this.sqliteBool(key, value);
1910
+ if (t.schema.isObject(value)) return this.sqliteJson(key, value);
1911
+ if (t.schema.isRecord(value)) return this.sqliteJson(key, value);
1912
+ if (t.schema.isAny(value)) return this.sqliteJson(key, value);
2105
1913
  if (t.schema.isArray(value)) {
2106
- if (t.schema.isObject(value.items)) return schema(key, value);
2107
- if (t.schema.isRecord(value.items)) return schema(key, value);
2108
- if (t.schema.isString(value.items)) return pg$1.text(key).array();
2109
- if (t.schema.isInteger(value.items)) return pg$1.integer(key).array();
2110
- if (t.schema.isNumber(value.items)) return pg$1.numeric(key).array();
2111
- if (t.schema.isBoolean(value.items)) return pg$1.boolean(key).array();
2112
- if (isTypeEnum(value.items)) return pg$1.text(key).array();
1914
+ if (t.schema.isObject(value.items)) return this.sqliteJson(key, value);
1915
+ if (t.schema.isRecord(value.items)) return this.sqliteJson(key, value);
1916
+ if (t.schema.isAny(value.items)) return this.sqliteJson(key, value);
1917
+ if (t.schema.isString(value.items)) return this.sqliteJson(key, value);
1918
+ if (t.schema.isInteger(value.items)) return this.sqliteJson(key, value);
1919
+ if (t.schema.isNumber(value.items)) return this.sqliteJson(key, value);
1920
+ if (t.schema.isBoolean(value.items)) return this.sqliteJson(key, value);
2113
1921
  }
2114
- if (isTypeEnum(value)) {
2115
- if (!value.enum.every((it) => typeof it === "string")) throw new AlephaError(`Enum for ${fieldName} must be an array of strings, got ${JSON.stringify(value.enum)}`);
2116
- if (PG_ENUM in value && value[PG_ENUM]) {
2117
- const enumName = value[PG_ENUM].name ?? `${tableName}_${key}_enum`;
2118
- if (enums.has(enumName)) {
2119
- const values = enums.get(enumName).enumValues.join(",");
2120
- const newValues = value.enum.join(",");
2121
- if (values !== newValues) throw new AlephaError(`Enum name conflict for ${enumName}: [${values}] vs [${newValues}]`);
2122
- }
2123
- enums.set(enumName, nsp.enum(enumName, value.enum));
2124
- return enums.get(enumName)(key);
2125
- }
2126
- return this.mapStringToColumn(key, value);
1922
+ if (t.schema.isUnsafe(value) && "type" in value && value.type === "string") return this.mapStringToSqliteColumn(key, value);
1923
+ throw new Error(`Unsupported schema for field '${tableName}.${fieldName}' (schema: ${JSON.stringify(value)})`);
1924
+ };
1925
+ mapStringToSqliteColumn = (key, value) => {
1926
+ if (value.format === "uuid") {
1927
+ if (PG_PRIMARY_KEY in value) return pg$1.text(key).primaryKey().$defaultFn(() => randomUUID());
1928
+ return pg$1.text(key);
2127
1929
  }
2128
- throw new AlephaError(`Unsupported schema type for ${fieldName} as ${JSON.stringify(value)}`);
1930
+ if (value.format === "byte") return this.sqliteJson(key, value);
1931
+ if (value.format === "date-time") {
1932
+ if (PG_CREATED_AT in value) return this.sqliteDateTime(key, {}).default(sql$1`(unixepoch('subsec') * 1000)`);
1933
+ if (PG_UPDATED_AT in value) return this.sqliteDateTime(key, {}).default(sql$1`(unixepoch('subsec') * 1000)`);
1934
+ return this.sqliteDateTime(key, {});
1935
+ }
1936
+ if (value.format === "date") return this.sqliteDate(key, {});
1937
+ return pg$1.text(key);
2129
1938
  };
2130
- /**
2131
- * Map a string to a PG column.
2132
- *
2133
- * @param key The key of the field.
2134
- * @param value The value of the field.
2135
- */
2136
- mapStringToColumn = (key, value) => {
2137
- if ("format" in value) {
2138
- if (value.format === "uuid") {
2139
- if (PG_PRIMARY_KEY in value) return pg$1.uuid(key).defaultRandom();
2140
- return pg$1.uuid(key);
1939
+ sqliteJson = (name, document) => pg$1.customType({
1940
+ dataType: () => "text",
1941
+ toDriver: (value) => JSON.stringify(value),
1942
+ fromDriver: (value) => {
1943
+ return value && typeof value === "string" ? JSON.parse(value) : value;
1944
+ }
1945
+ })(name, { document }).$type();
1946
+ sqliteDateTime = pg$1.customType({
1947
+ dataType: () => "integer",
1948
+ toDriver: (value) => new Date(value).getTime(),
1949
+ fromDriver: (value) => {
1950
+ return new Date(value).toISOString();
1951
+ }
1952
+ });
1953
+ sqliteBool = pg$1.customType({
1954
+ dataType: () => "integer",
1955
+ toDriver: (value) => value ? 1 : 0,
1956
+ fromDriver: (value) => value === 1
1957
+ });
1958
+ sqliteDate = pg$1.customType({
1959
+ dataType: () => "integer",
1960
+ toDriver: (value) => new Date(value).getTime(),
1961
+ fromDriver: (value) => {
1962
+ return new Date(value).toISOString().split("T")[0];
1963
+ }
1964
+ });
1965
+ };
1966
+
1967
+ //#endregion
1968
+ //#region ../../src/orm/providers/drivers/BunSqliteProvider.ts
1969
+ const envSchema$3 = t.object({ DATABASE_URL: t.optional(t.text()) });
1970
+ /**
1971
+ * Configuration options for the Bun SQLite database provider.
1972
+ */
1973
+ const bunSqliteOptions = $atom({
1974
+ name: "alepha.postgres.bun-sqlite.options",
1975
+ schema: t.object({ path: t.optional(t.string({ description: "Filepath or :memory:. If empty, provider will use DATABASE_URL from env." })) }),
1976
+ default: {}
1977
+ });
1978
+ /**
1979
+ * Bun SQLite provider using Drizzle ORM with Bun's native SQLite client.
1980
+ *
1981
+ * This provider uses Bun's built-in `bun:sqlite` for SQLite connections,
1982
+ * which provides excellent performance on the Bun runtime.
1983
+ *
1984
+ * @example
1985
+ * ```ts
1986
+ * // Set DATABASE_URL environment variable
1987
+ * // DATABASE_URL=sqlite://./my-database.db
1988
+ *
1989
+ * // Or configure programmatically
1990
+ * alepha.with({
1991
+ * provide: DatabaseProvider,
1992
+ * use: BunSqliteProvider,
1993
+ * });
1994
+ *
1995
+ * // Or use options atom
1996
+ * alepha.store.mut(bunSqliteOptions, (old) => ({
1997
+ * ...old,
1998
+ * path: ":memory:",
1999
+ * }));
2000
+ * ```
2001
+ */
2002
+ var BunSqliteProvider = class extends DatabaseProvider {
2003
+ kit = $inject(DrizzleKitProvider);
2004
+ log = $logger();
2005
+ env = $env(envSchema$3);
2006
+ builder = $inject(SqliteModelBuilder);
2007
+ options = $use(bunSqliteOptions);
2008
+ sqlite;
2009
+ bunDb;
2010
+ get name() {
2011
+ return "bun-sqlite";
2012
+ }
2013
+ dialect = "sqlite";
2014
+ get url() {
2015
+ const path = this.options.path ?? this.env.DATABASE_URL;
2016
+ if (path) {
2017
+ if (path.startsWith("postgres://")) throw new AlephaError("Postgres URL is not supported for SQLite provider.");
2018
+ return path;
2019
+ }
2020
+ if (this.alepha.isTest() || this.alepha.isServerless()) return ":memory:";
2021
+ else return "node_modules/.alepha/bun-sqlite.db";
2022
+ }
2023
+ get db() {
2024
+ if (!this.bunDb) throw new AlephaError("Database not initialized");
2025
+ return this.bunDb;
2026
+ }
2027
+ async execute(query) {
2028
+ return this.bunDb.all(query);
2029
+ }
2030
+ onStart = $hook({
2031
+ on: "start",
2032
+ handler: async () => {
2033
+ if (typeof Bun === "undefined") throw new AlephaError("BunSqliteProvider requires the Bun runtime. Use NodeSqliteProvider for Node.js.");
2034
+ const { Database } = await import("bun:sqlite");
2035
+ const { drizzle: drizzle$3 } = await import("drizzle-orm/bun-sqlite");
2036
+ const filepath = this.url.replace("sqlite://", "").replace("sqlite:", "");
2037
+ if (filepath !== ":memory:" && filepath !== "") {
2038
+ const dirname = filepath.split("/").slice(0, -1).join("/");
2039
+ if (dirname) await mkdir(dirname, { recursive: true }).catch(() => null);
2141
2040
  }
2142
- if (value.format === "byte") return byte(key);
2143
- if (value.format === "date-time") {
2144
- if (PG_CREATED_AT in value) return pg$1.timestamp(key, {
2145
- mode: "string",
2146
- withTimezone: true
2147
- }).defaultNow();
2148
- if (PG_UPDATED_AT in value) return pg$1.timestamp(key, {
2149
- mode: "string",
2150
- withTimezone: true
2151
- }).defaultNow();
2152
- return pg$1.timestamp(key, {
2153
- mode: "string",
2154
- withTimezone: true
2155
- });
2041
+ this.sqlite = new Database(filepath);
2042
+ this.bunDb = drizzle$3({
2043
+ client: this.sqlite,
2044
+ logger: { logQuery: (query, params) => {
2045
+ this.log.trace(query, { params });
2046
+ } }
2047
+ });
2048
+ await this.migrateDatabase();
2049
+ this.log.info(`Using Bun SQLite database at ${filepath}`);
2050
+ }
2051
+ });
2052
+ onStop = $hook({
2053
+ on: "stop",
2054
+ handler: async () => {
2055
+ if (this.sqlite) {
2056
+ this.log.debug("Closing Bun SQLite connection...");
2057
+ this.sqlite.close();
2058
+ this.sqlite = void 0;
2059
+ this.bunDb = void 0;
2060
+ this.log.info("Bun SQLite connection closed");
2156
2061
  }
2157
- if (value.format === "date") return pg$1.date(key, { mode: "string" });
2158
2062
  }
2159
- return pg$1.text(key);
2160
- };
2063
+ });
2064
+ async executeMigrations(migrationsFolder) {
2065
+ const { migrate: migrate$3 } = await import("drizzle-orm/bun-sqlite/migrator");
2066
+ await migrate$3(this.bunDb, { migrationsFolder });
2067
+ }
2068
+ };
2069
+
2070
+ //#endregion
2071
+ //#region ../../src/orm/providers/drivers/CloudflareD1Provider.ts
2072
+ /**
2073
+ * Cloudflare D1 SQLite provider using Drizzle ORM.
2074
+ *
2075
+ * This provider requires a D1 binding to be set via `cloudflareD1Options` before starting.
2076
+ * The binding is typically obtained from the Cloudflare Workers environment.
2077
+ *
2078
+ * @example
2079
+ * ```ts
2080
+ * // In your Cloudflare Worker
2081
+ * alepha.set(cloudflareD1Options, { binding: env.DB });
2082
+ * ```
2083
+ */
2084
+ var CloudflareD1Provider = class extends DatabaseProvider {
2085
+ kit = $inject(DrizzleKitProvider);
2086
+ log = $logger();
2087
+ builder = $inject(SqliteModelBuilder);
2088
+ env = $env(t.object({ DATABASE_URL: t.string({ description: "Expect to be 'cloudflare-d1://name:id'" }) }));
2089
+ d1;
2090
+ drizzleDb;
2091
+ get name() {
2092
+ return "d1";
2093
+ }
2094
+ dialect = "sqlite";
2095
+ get url() {
2096
+ return this.env.DATABASE_URL;
2097
+ }
2098
+ get db() {
2099
+ if (!this.drizzleDb) throw new AlephaError("D1 database not initialized");
2100
+ return this.drizzleDb;
2101
+ }
2102
+ async execute(query) {
2103
+ const { rows } = await this.db.run(query);
2104
+ return rows;
2105
+ }
2106
+ onStart = $hook({
2107
+ on: "start",
2108
+ handler: async () => {
2109
+ const [bindingName] = this.env.DATABASE_URL.replace("cloudflare-d1://", "").split(":");
2110
+ const cloudflareEnv = this.alepha.store.get("cloudflare.env");
2111
+ if (!cloudflareEnv) throw new AlephaError("Cloudflare Workers environment not found in Alepha store under 'cloudflare.env'.");
2112
+ const binding = cloudflareEnv[bindingName];
2113
+ if (!binding) throw new AlephaError(`D1 binding '${bindingName}' not found in Cloudflare Workers environment.`);
2114
+ this.d1 = binding;
2115
+ const { drizzle: drizzle$3 } = await import("drizzle-orm/d1");
2116
+ this.drizzleDb = drizzle$3(this.d1);
2117
+ await this.migrateDatabase();
2118
+ this.log.info("Using Cloudflare D1 database");
2119
+ }
2120
+ });
2121
+ async executeMigrations(migrationsFolder) {
2122
+ const { migrate: migrate$3 } = await import("drizzle-orm/d1/migrator");
2123
+ await migrate$3(this.db, { migrationsFolder });
2124
+ }
2125
+ /**
2126
+ * Override development migration to skip sync (not supported on D1).
2127
+ * D1 requires proper migrations to be applied.
2128
+ */
2129
+ async runDevelopmentMigration(migrationsFolder) {
2130
+ await this.executeMigrations(migrationsFolder);
2131
+ }
2132
+ /**
2133
+ * Override test migration to run migrations instead of sync.
2134
+ * D1 doesn't support schema synchronization.
2135
+ */
2136
+ async runTestMigration() {
2137
+ const migrationsFolder = this.getMigrationsFolder();
2138
+ try {
2139
+ await this.executeMigrations(migrationsFolder);
2140
+ } catch {
2141
+ this.log.warn("D1 migrations failed in test environment - ensure migrations exist");
2142
+ }
2143
+ }
2161
2144
  };
2162
2145
 
2163
2146
  //#endregion
@@ -2283,16 +2266,6 @@ var NodePostgresProvider = class NodePostgresProvider extends DatabaseProvider {
2283
2266
  const mode = url.searchParams.get("sslmode");
2284
2267
  for (const it of NodePostgresProvider.SSL_MODES) if (mode === it) return it;
2285
2268
  }
2286
- /**
2287
- * For testing purposes, generate a unique schema name.
2288
- * The schema name will be generated based on the current date and time.
2289
- * It will be in the format of `test_YYYYMMDD_HHMMSS_randomSuffix`.
2290
- */
2291
- generateTestSchemaName() {
2292
- const pad = (n) => n.toString().padStart(2, "0");
2293
- const now = /* @__PURE__ */ new Date();
2294
- return `test_${`${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}_${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`}_${Math.random().toString(36).slice(2, 6)}`;
2295
- }
2296
2269
  };
2297
2270
 
2298
2271
  //#endregion
@@ -2788,8 +2761,8 @@ const $transaction = (opts) => {
2788
2761
  };
2789
2762
 
2790
2763
  //#endregion
2791
- //#region ../../src/orm/providers/PostgresTypeProvider.ts
2792
- var PostgresTypeProvider = class {
2764
+ //#region ../../src/orm/providers/DatabaseTypeProvider.ts
2765
+ var DatabaseTypeProvider = class {
2793
2766
  attr = pgAttr;
2794
2767
  /**
2795
2768
  * Creates a primary key with an identity column.
@@ -2872,13 +2845,34 @@ var PostgresTypeProvider = class {
2872
2845
  };
2873
2846
  /**
2874
2847
  * Creates a page schema for a given object schema.
2875
- * It's used by {@link RepositoryPrimitive#paginate} method.
2848
+ * It's used by {@link Repository#paginate} method.
2876
2849
  */
2877
2850
  page = (resource, options) => {
2878
2851
  return pageSchema$1(resource, options);
2879
2852
  };
2880
2853
  };
2881
- const pg = new PostgresTypeProvider();
2854
+ /**
2855
+ * Wrapper of TypeProvider (`t`) for database types.
2856
+ *
2857
+ * Use `db` for improve TypeBox schema definitions with database-specific attributes.
2858
+ *
2859
+ * @example
2860
+ * ```ts
2861
+ * import { t } from "alepha";
2862
+ * import { db } from "alepha/orm";
2863
+ *
2864
+ * const userSchema = t.object({
2865
+ * id: db.primaryKey(t.uuid()),
2866
+ * email: t.email(),
2867
+ * createdAt: db.createdAt(),
2868
+ * });
2869
+ * ```
2870
+ */
2871
+ const db = new DatabaseTypeProvider();
2872
+ /**
2873
+ * @deprecated Use `db` instead.
2874
+ */
2875
+ const pg = db;
2882
2876
 
2883
2877
  //#endregion
2884
2878
  //#region ../../src/orm/schemas/legacyIdSchema.ts
@@ -2893,21 +2887,25 @@ const legacyIdSchema = pgAttr(pgAttr(pgAttr(t.integer(), PG_PRIMARY_KEY), PG_SER
2893
2887
  * Postgres client based on Drizzle ORM, Alepha type-safe friendly.
2894
2888
  *
2895
2889
  * ```ts
2890
+ * import { t } from "alepha";
2891
+ * import { $entity, $repository, db } from "alepha/postgres";
2892
+ *
2896
2893
  * const users = $entity({
2897
2894
  * name: "users",
2898
2895
  * schema: t.object({
2899
- * id: pg.primaryKey(),
2896
+ * id: db.primaryKey(),
2900
2897
  * name: t.text(),
2901
2898
  * email: t.text(),
2902
2899
  * }),
2903
2900
  * });
2904
2901
  *
2905
- * class Db {
2902
+ * class App {
2906
2903
  * users = $repository(users);
2907
- * }
2908
2904
  *
2909
- * const db = alepha.inject(Db);
2910
- * const user = await db.users.one({ name: { eq: "John Doe" } });
2905
+ * getUserByName(name: string) {
2906
+ * return this.users.findOne({ name: { eq: name } });
2907
+ * }
2908
+ * }
2911
2909
  * ```
2912
2910
  *
2913
2911
  * This is not a full ORM, but rather a set of tools to work with Postgres databases in a type-safe way.
@@ -2937,6 +2935,8 @@ const AlephaPostgres = $module({
2937
2935
  NodePostgresProvider,
2938
2936
  PglitePostgresProvider,
2939
2937
  NodeSqliteProvider,
2938
+ BunPostgresProvider,
2939
+ BunSqliteProvider,
2940
2940
  CloudflareD1Provider,
2941
2941
  SqliteModelBuilder,
2942
2942
  PostgresModelBuilder,
@@ -2944,7 +2944,6 @@ const AlephaPostgres = $module({
2944
2944
  RepositoryProvider,
2945
2945
  Repository,
2946
2946
  PgRelationManager,
2947
- PgJsonQueryManager,
2948
2947
  QueryManager
2949
2948
  ],
2950
2949
  register: (alepha) => {
@@ -2977,18 +2976,18 @@ const AlephaPostgres = $module({
2977
2976
  alepha.with({
2978
2977
  optional: true,
2979
2978
  provide: DatabaseProvider,
2980
- use: NodePostgresProvider
2979
+ use: alepha.isBun() ? BunPostgresProvider : NodePostgresProvider
2981
2980
  });
2982
2981
  return;
2983
2982
  }
2984
2983
  alepha.with({
2985
2984
  optional: true,
2986
2985
  provide: DatabaseProvider,
2987
- use: NodeSqliteProvider
2986
+ use: alepha.isBun() ? BunSqliteProvider : NodeSqliteProvider
2988
2987
  });
2989
2988
  }
2990
2989
  });
2991
2990
 
2992
2991
  //#endregion
2993
- export { $entity, $repository, $sequence, $transaction, AlephaPostgres, CloudflareD1Provider, DatabaseProvider, DbConflictError, DbEntityNotFoundError, DbError, DbMigrationError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, NodePostgresProvider, NodeSqliteProvider, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_ENUM, PG_IDENTITY, PG_PRIMARY_KEY, PG_REF, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, PostgresTypeProvider, Repository, RepositoryProvider, SequencePrimitive, buildQueryString, drizzle, getAttrFields, insertSchema, legacyIdSchema, nodeSqliteOptions, pageQuerySchema, pageSchema, parseQueryString, pg, pgAttr, schema, sql, updateSchema };
2992
+ export { $entity, $repository, $sequence, $transaction, AlephaPostgres, BunPostgresProvider, BunSqliteProvider, CloudflareD1Provider, DatabaseProvider, DatabaseTypeProvider, DbConflictError, DbEntityNotFoundError, DbError, DbMigrationError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, NodePostgresProvider, NodeSqliteProvider, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_ENUM, PG_IDENTITY, PG_PRIMARY_KEY, PG_REF, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, Repository, RepositoryProvider, SequencePrimitive, buildQueryString, bunSqliteOptions, db, drizzle, getAttrFields, insertSchema, legacyIdSchema, nodeSqliteOptions, pageQuerySchema, pageSchema, parseQueryString, pg, pgAttr, schema, sql, updateSchema };
2994
2993
  //# sourceMappingURL=index.js.map