@venizia/ignis-docs 0.2.0 → 0.2.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 (142) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +22 -11
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +6 -2
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +182 -93
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -16,7 +16,7 @@ IGNIS core was restructured around ONE engine-neutral repository family:
16
16
  - `src/base` now holds a single `AbstractRepository` / `AbstractDataSource` / `AbstractEntity` family. Every engine implements it under `src/connectors/{postgres,typesense}`.
17
17
  - Postgres remains re-exported from the root barrel - **your imports keep working unchanged**. Every connector is also addressable explicitly: `@venizia/ignis/postgres`, `@venizia/ignis/typesense` (typesense is subpath-only; its client is an optional peer).
18
18
  - Canonical class names are the paradigm-family names (`BaseRelationalDataSource`, `BaseRelationalEntity`, `DefaultRelationalRepository`, ...); the engine name appears only at the concrete datasource (`TypesenseDataSource`) and the query dialect (`PostgresQueryOperators`). The historical names (`BaseDataSource`, `BaseEntity`, `BasePostgresDataSource`, `BasePostgresEntity`, `RDBQueryOperators`, `DefaultCRUDRepository`, ...) all remain as alias re-exports of the SAME classes - `instanceof`, metadata, and bindings are unaffected. No action required; prefer the family names in new code.
19
- - New capabilities model: `dataSource.getCapabilities()` and a standardized NotSupported error (HTTP 501, messageCode `core.not_supported`) for engine gaps (e.g. transactions on search engines).
19
+ - New capabilities model: `dataSource.getCapabilities()` and a standardized NotSupported error (HTTP 501, `normalized.code` `core.not_supported`) for engine gaps (e.g. transactions on search engines).
20
20
  - New engine: the **Typesense search branch** (`BaseSearchEntity`, `defineSearchCollection`, typed `TSearchDocument`, `DefaultSearchRepository`). It does not affect existing postgres code.
21
21
 
22
22
  ## Required migrations (in order)
@@ -78,7 +78,7 @@ Run this once after the version bump, before trusting the first `tsc` run.
78
78
 
79
79
  ### 4. Auth endpoint error contract (only if you assert on it)
80
80
 
81
- The three auth endpoints backed by unimplemented service methods (`refreshToken`, `getUserInformation`) now return the standardized NotSupported error: HTTP 501 with messageCode `core.not_supported` and message `[AuthController] <feature> is not supported.` (previously a plain `Method not implemented`). BANA was scanned: no code asserts on the old string - listed for completeness.
81
+ The three auth endpoints backed by unimplemented service methods (`refreshToken`, `getUserInformation`) now return the standardized NotSupported error: HTTP 501 with `normalized.code` `core.not_supported` and message `[AuthController] <feature> is not supported.` (previously a plain `Method not implemented`). BANA was scanned: no code asserts on the old string - listed for completeness.
82
82
 
83
83
  ## Strongly recommended (not compile-blocking)
84
84
 
@@ -526,12 +526,11 @@ export class OrderRepository extends DefaultCRUDRepository<typeof Order.schema>
526
526
 
527
527
  ```typescript
528
528
  // src/services/product.service.ts
529
- import { injectable, inject } from '@venizia/ignis';
529
+ import { inject } from '@venizia/ignis';
530
530
  import { BaseService } from '@venizia/ignis';
531
531
  import { ProductRepository } from '../repositories/product.repository';
532
532
  import { getError } from '@venizia/ignis-helpers';
533
533
 
534
- @injectable({})
535
534
  export class ProductService extends BaseService {
536
535
  constructor(
537
536
  @inject({ key: 'repositories.ProductRepository' })
@@ -595,7 +594,7 @@ export class ProductService extends BaseService {
595
594
 
596
595
  ```typescript
597
596
  // src/services/cart.service.ts
598
- import { injectable, inject } from '@venizia/ignis';
597
+ import { inject } from '@venizia/ignis';
599
598
  import { BaseService } from '@venizia/ignis';
600
599
  import { CartRepository } from '../repositories/cart.repository';
601
600
  import { ProductService } from './product.service';
@@ -606,7 +605,6 @@ interface ICartItem {
606
605
  quantity: number;
607
606
  }
608
607
 
609
- @injectable({})
610
608
  export class CartService extends BaseService {
611
609
  constructor(
612
610
  @inject({ key: 'repositories.CartRepository' })
@@ -733,7 +731,7 @@ export class CartService extends BaseService {
733
731
 
734
732
  ```typescript
735
733
  // src/services/order.service.ts
736
- import { injectable, inject } from '@venizia/ignis';
734
+ import { inject } from '@venizia/ignis';
737
735
  import { BaseService } from '@venizia/ignis';
738
736
  import { OrderRepository } from '../repositories/order.repository';
739
737
  import { CartService } from './cart.service';
@@ -758,7 +756,6 @@ interface ICreateOrderInput {
758
756
  billingAddress?: IOrderAddress;
759
757
  }
760
758
 
761
- @injectable({})
762
759
  export class OrderService extends BaseService {
763
760
  constructor(
764
761
  @inject({ key: 'repositories.OrderRepository' })
@@ -906,12 +903,10 @@ export class OrderService extends BaseService {
906
903
 
907
904
  ```typescript
908
905
  // src/services/payment.service.ts
909
- import { injectable } from '@venizia/ignis';
910
906
  import { BaseService } from '@venizia/ignis';
911
907
  import Stripe from 'stripe';
912
908
  import { applicationEnvironment } from '@venizia/ignis-helpers';
913
909
 
914
- @injectable({})
915
910
  export class PaymentService extends BaseService {
916
911
  private _stripe: Stripe;
917
912
 
@@ -266,7 +266,7 @@ graph TD
266
266
 
267
267
  Automatically registers these default middlewares during `initialize()`:
268
268
 
269
- 1. **Error handler** (`appErrorHandler`) - with optional `rootKey` from `configs.error.rootKey`
269
+ 1. **Error handler** (`AppErrorMiddleware`) - with optional `rootKey` from `configs.error.rootKey`
270
270
  2. **Async context storage** (`contextStorage`) - enabled by default via `configs.asyncContext.enable`
271
271
  3. **Not-found handler** (`notFoundHandler`)
272
272
  4. **RequestTrackerComponent** - assigns `x-request-id` to every request, includes request body parsing
@@ -1,178 +1,121 @@
1
1
  ---
2
- title: Connectors Reference
3
- description: How IGNIS separates engine-neutral base classes from per-engine connectors, dual-door exports, and adding a new engine
4
- difficulty: advanced
2
+ title: Connectors
3
+ description: How IGNIS supports multiple database and search engines behind one engine-neutral contract
4
+ difficulty: intermediate
5
5
  ---
6
6
 
7
- # Deep Dive: Connectors
7
+ # Connectors
8
8
 
9
- IGNIS's persistence layer is split into two layers: an **engine-neutral root** and a set of **connectors**, one per storage engine. This page documents that architecture, the dual-door export strategy, naming symmetry between engines, and how to add a new connector.
9
+ A connector is how IGNIS adds a storage engine - PostgreSQL, Typesense, Meilisearch - behind one engine-neutral contract, so `DataSource`, `Entity`, and `Repository` mean the same thing no matter which engine backs them.
10
10
 
11
- **Files:** `packages/core/src/base/**` (neutral) and `packages/core/src/connectors/{postgres,typesense,meilisearch,search}/**` (per-engine)
11
+ "A connector" (this page) means an engine-integration module; "the connector" means the Drizzle instance exposed as `this.connector` on a datasource or repository - the two senses are unrelated despite the shared word.
12
12
 
13
- ## Why the split
13
+ ## In one example
14
14
 
15
- Before the restructure, `AbstractDataSource`/`AbstractRepository`/`AbstractEntity` were PostgreSQL-and-Drizzle-aware from the start - `pool`, `connector` (Drizzle instance), and SQL-shaped `TWhere`/`TFilter` lived directly in `src/base`. Adding typesense (a document search engine, not a relational database) exposed the coupling: it has no connection pool, doesn't speak SQL, and doesn't support transactions or row-level locking.
16
-
17
- The fix moves everything engine-specific out of `src/base` and into `src/connectors/<engine>/`, leaving `src/base` with only what every engine can implement:
18
-
19
- | Concept | Neutral (`src/base`) | PostgreSQL (`connectors/postgres`) | Typesense (`connectors/typesense`) |
20
- |---|---|---|---|
21
- | DataSource | `AbstractDataSource` | `AbstractPostgresDataSource` → `BasePostgresDataSource` | `AbstractSearchDataSource` → `BaseSearchDataSource` → `TypesenseDataSource` |
22
- | Entity | `AbstractEntity` | `BasePostgresEntity` (alias `BaseEntity`) | `BaseSearchEntity` |
23
- | Repository | `AbstractRepository` | `PostgresBaseRepository` → `ReadableRepository`/`PersistableRepository`/`DefaultCRUDRepository`/`SoftDeletableRepository` | `TypesenseBaseRepository` → `ReadableSearchRepository`/`PersistableSearchRepository`/`DefaultSearchRepository` |
24
- | Transactions | throws `NotSupported` by default | real transactions, 3 isolation levels | throws `NotSupported` |
25
- | Filtering | neutral `TWhere`/`TFilter` | SQL WHERE via Drizzle | typesense query DSL via `TypesenseQueryDialect` |
26
-
27
- ## The neutral contract
28
-
29
- ### `AbstractDataSource`
30
-
31
- `packages/core/src/base/datasources/abstract.ts` declares:
15
+ The neutral `AbstractDataSource` has no SQL, no pool, no Drizzle - the postgres connector's `BasePostgresDataSource` adds all of that, and `@datasource({ driver })` names the concrete client class:
32
16
 
33
17
  ```typescript
34
- abstract class AbstractDataSource<
35
- Settings extends object = {},
36
- Schema extends TAnyDataSourceSchema = TAnyDataSourceSchema,
37
- ConfigurableOptions extends object = {},
38
- > extends BaseHelper implements IDataSource<Settings, Schema, ConfigurableOptions> {
39
- abstract configure(opts?: ConfigurableOptions): ValueOrPromise<void>;
40
-
41
- getCapabilities(): IDataSourceCapabilities {
42
- return { transactions: false };
43
- }
44
-
45
- async beginTransaction(_opts?: ITransactionOptions): Promise<ITransaction> {
46
- return throwNotSupported({
47
- scope: this.constructor.name,
48
- feature: 'Transactions',
49
- logger: this.logger,
50
- });
51
- }
18
+ import { Pool } from 'pg';
19
+ import { datasource } from '@venizia/ignis';
20
+ import { BasePostgresDataSource } from '@venizia/ignis/postgres';
21
+ import { NodePostgresDriver } from '@venizia/ignis/postgres/node-postgres';
22
+
23
+ interface IDataSourceConfigs {
24
+ host: string;
25
+ port: number;
26
+ database: string;
27
+ user: string;
28
+ password: string;
52
29
  }
53
- ```
54
-
55
- No `pool`, no `connector`, no SQL types. Every engine either overrides `getCapabilities()`/`beginTransaction()` (PostgreSQL) or accepts the neutral default (typesense).
56
-
57
- ### `AbstractEntity`
58
30
 
59
- `packages/core/src/base/models/base.ts` declares the minimal entity contract, including `getIdType()`:
31
+ @datasource({ driver: NodePostgresDriver })
32
+ export class PostgresDataSource extends BasePostgresDataSource<IDataSourceConfigs> {
33
+ override configure(): void {
34
+ this.client = new Pool(this.settings);
35
+ }
60
36
 
61
- ```typescript
62
- abstract class AbstractEntity extends BaseHelper {
63
- getIdType(): TIdSchemaType {
64
- return 'string';
37
+ override getConnectionString(): string {
38
+ const { host, port, user, password, database } = this.settings;
39
+ return `postgresql://${user}:${password}@${host}:${port}/${database}`;
65
40
  }
66
41
  }
67
42
  ```
68
43
 
69
- `BasePostgresEntity` overrides `getIdType()` based on the Drizzle column's actual data type; other engines can override it per their own ID representation.
44
+ A Typesense datasource follows the same shape but extends the search connector's `BaseSearchDataSource` instead - no pool, no `getConnectionString()`, no transactions.
70
45
 
71
- ### `AbstractRepository`
46
+ ## How it works
72
47
 
73
- `packages/core/src/base/repositories/core/abstract.ts`:
74
-
75
- ```typescript
76
- abstract class AbstractRepository<
77
- TDataObject extends object,
78
- TPersistObject extends object = TDataObject,
79
- TOptions extends IExtraOptions = IExtraOptions,
80
- > extends BaseHelper implements IPersistableRepository<TDataObject, TPersistObject, TOptions>
81
- ```
48
+ - **Three engine-neutral roots.** `packages/core/src/base` declares three roots every connector implements:
82
49
 
83
- Notice the generic parameters are named for their role (`TDataObject`, `TPersistObject`, `TOptions`), not for Drizzle concepts (`EntitySchema`, `TTableObject`) - those Drizzle-flavored names now belong to `PostgresBaseRepository` and its subclasses, which narrow `AbstractRepository`'s generics into a `TTableSchemaWithId`-based signature. `AbstractRepository` does **not** compose `FieldsVisibilityMixin`/`DefaultFilterMixin` - see [Repository Mixins](./repositories/mixins) for what happened to those.
50
+ | Root | Purpose | Neutral default |
51
+ |---|---|---|
52
+ | `AbstractDataSource` | Connection ownership | No `pool`, no Drizzle `connector`; `beginTransaction()` throws `NotSupported` |
53
+ | `AbstractEntity` | Model/schema contract | `name`, `getSchema()`, `getIdType()` |
54
+ | `AbstractRepository` | Data access contract | Generics named for role (data/persist/options), not any one engine's vocabulary |
84
55
 
85
- ### Neutral `TFilter`/`TWhere` and `ITransaction`
56
+ - **Connectors narrow the roots into a real engine.** `packages/core/src/connectors/<engine>` adds engine-specific members:
86
57
 
87
- `packages/core/src/base/repositories/common/types.ts` and `packages/core/src/base/datasources/common/types.ts` define engine-neutral filter and transaction shapes shared by both connectors. `ITransaction` has no `connector` field - each engine that supports transactions (currently only PostgreSQL) narrows it with `IDatabaseTransaction`, whose `connector` is a `TRelationalConnector<Schema>` bound to the transaction's dedicated connection (the older `TNodePostgresTransactionConnector` name is kept as a `@deprecated` alias). Its `commit()`/`rollback()` **throw** on failure (a failed `COMMIT` no longer resolves as success) and destroy the poisoned connection rather than pooling it under the `node-postgres` driver; a failed `BEGIN` likewise destroys the acquired connection instead of leaking it. See [Transactions](/guides/core-concepts/persistent/transactions).
58
+ | Connector | Adds | `getCapabilities()` |
59
+ |---|---|---|
60
+ | **postgres** (`connectors/postgres`) | `pool`, Drizzle `connector`, SQL-shaped `TWhere`/`TFilter`, real transactions with isolation levels | `{ transactions: true }` |
61
+ | **search** (`connectors/search`) | Engine-neutral search base - no SQL, no transactions. Both typesense and meilisearch extend it (not `AbstractDataSource` directly), sharing one query-dialect and capability shape | inherited neutral default |
88
62
 
89
- ## Dual-door exports
63
+ - **`@datasource({ driver })` picks the concrete client, within an engine.** Postgres takes a driver **class** (`NodePostgresDriver` or `PostgresJsDriver`), never a driver-name string - a bundler packages values, not text, so a string would leave the peer dependency uninstalled.
64
+ - **All engine clients stay optional peer dependencies.** Importing `@venizia/ignis/postgres` alone loads zero client libraries.
65
+ - **Search connectors are subpath-only.** `@venizia/ignis/typesense` and `@venizia/ignis/meilisearch` are excluded from the root `@venizia/ignis` barrel, so an app that never touches search never pulls a search client into its bundle.
90
66
 
91
- IGNIS ships both a **root barrel** (backward-compatible default) and **per-engine subpaths** (opt-in, tree-shakeable). Both resolve to the exact same compiled classes - there is no duplicated implementation.
67
+ **Canonical names and aliases**
92
68
 
93
- ```json
94
- // packages/core/package.json - exports map (persistence-relevant entries)
95
- {
96
- ".": "dist/index.js", // framework + postgres (compatibility default)
97
- "./postgres": "dist/connectors/postgres/index.js", // relational connector - loads ZERO client library
98
- "./postgres/node-postgres": "dist/connectors/postgres/drivers/node-postgres.js", // concrete driver (value-imports `pg`)
99
- "./postgres/postgres-js": "dist/connectors/postgres/drivers/postgres-js.js", // concrete driver (value-imports `postgres`)
100
- "./postgres/supabase": "dist/connectors/postgres/supabase/index.js", // Supabase pooler + RLS helpers
101
- "./search": "dist/connectors/search/index.js", // engine-neutral search paradigm (no engine client)
102
- "./typesense": "dist/connectors/typesense/index.js", // subpath-only, optional peer
103
- "./meilisearch": "dist/connectors/meilisearch/index.js" // subpath-only, optional peer
104
- }
105
- ```
69
+ | Layer | Canonical (`Relational` paradigm) | Compatibility alias (`Postgres`-prefixed) |
70
+ |---|---|---|
71
+ | DataSource | `BaseRelationalDataSource` | `BasePostgresDataSource` |
72
+ | Entity | `BaseRelationalEntity` | `BasePostgresEntity` |
73
+ | Repository | `RelationalBaseRepository` | `PostgresBaseRepository` |
106
74
 
107
- > [!IMPORTANT] Concrete Postgres drivers are sub-path only
108
- > `pg` and `postgres` are **both optional peer dependencies** (`peerDependenciesMeta.pg.optional` / `.postgres.optional`). The root barrel, `@venizia/ignis/postgres`, and the drivers barrel (`connectors/postgres/drivers/index.ts`) load **zero** `pg`/`postgres` modules - the drivers barrel exports only the neutral `IRelationalDriver` contract. A concrete driver value-imports its own client, so reach it by its own sub-path only: `@venizia/ignis/postgres/node-postgres` or `@venizia/ignis/postgres/postgres-js`. There is no structural client sniffing: `@datasource({ driver })` names the driver **class** directly (`NodePostgresDriver`/`PostgresJsDriver`), and the base datasource's `wireDriverFromMetadata()` instantiates that named class over `this.client` lazily, on first `getConnector()`/`beginTransaction()`. Naming a class rather than a driver-name string is what carries `pg`/`postgres` into the app's bundle - a bundler only packages a real value reference, never text, and a bare side-effect import would not survive `sideEffects: false`. This is what keeps IGNIS from forcing a database client on a project that does not use one. See [Postgres Drivers & Supabase](/guides/core-concepts/persistent/postgres-drivers).
75
+ Both names resolve to the same class - existing imports keep working.
109
76
 
110
- > [!NOTE] `internal/` modules are not public API
111
- > The search connectors (`search`/`typesense`/`meilisearch`) no longer re-export their `internal/` barrels (`SearchConnectorInternal`, `TypesenseInternal`, `MeilisearchInternal`) from the connector barrel. There is no sub-path export for them either, and package `exports` blocks deep imports - so no specifier reaches them from outside the package. They are implementation detail; if you need what they do, ask for a supported API.
77
+ ## Common tasks
112
78
 
113
- ```typescript
114
- // packages/core/src/index.ts - root barrel
115
- export * from './base';
116
- export * from './common';
117
- export * from './components';
118
- export * from './connectors'; // -> connectors/index.ts: export * from './postgres';
119
- export * from './helpers';
120
- export * from './utilities';
121
- ```
79
+ ### Pick an engine
122
80
 
123
- - **Root (`@venizia/ignis`)** re-exports the framework plus the `postgres` connector - existing code that imports `BaseDataSource`/`DefaultCRUDRepository` from the root keeps working unchanged.
124
- - **`@venizia/ignis/postgres`** re-exports the same connector in isolation, for code that wants to be explicit about which engine it depends on.
125
- - **`@venizia/ignis/typesense`** is **subpath-only** - it is deliberately excluded from the root barrel because `typesense` is an optional peer dependency (`"peerDependenciesMeta": { "typesense": { "optional": true } }`). Importing from the root must never force-install the typesense client for apps that don't use search.
81
+ Import the connector for the engine you need - `@venizia/ignis/postgres` for a relational database with transactions, `@venizia/ignis/typesense` or `@venizia/ignis/meilisearch` for document search. The root `@venizia/ignis` barrel re-exports postgres for backward compatibility; search engines are always subpath-only:
126
82
 
127
83
  ```typescript
128
- // Both of these resolve to the same BasePostgresDataSource class:
84
+ // Postgres: available at the root or the subpath - same class either way
129
85
  import { BaseDataSource } from '@venizia/ignis';
130
86
  import { BasePostgresDataSource } from '@venizia/ignis/postgres';
131
87
 
132
- // Typesense must be imported from its subpath - not available at the root:
133
- import { TypesenseDataSource, defineSearchCollection } from '@venizia/ignis/typesense';
88
+ // Search engines: subpath only, never at the root
89
+ import { TypesenseDataSource } from '@venizia/ignis/typesense';
90
+ import { MeilisearchDataSource } from '@venizia/ignis/meilisearch';
134
91
  ```
135
92
 
136
- ## Naming symmetry and compatibility aliases
137
-
138
- Each connector's canonical class names carry the engine name (`BasePostgresDataSource`, `BasePostgresEntity`), matching the pattern typesense follows (`TypesenseDataSource`). PostgreSQL additionally re-exports the pre-restructure names as aliases, so existing imports do not break:
139
-
140
- ```typescript
141
- // packages/core/src/connectors/postgres/datasources/index.ts
142
- export { BasePostgresDataSource as BaseDataSource } from './base-datasource';
143
-
144
- // packages/core/src/connectors/postgres/models/index.ts
145
- export { BasePostgresEntity as BaseEntity } from './base';
146
- ```
147
-
148
- | Canonical (new, engine-carrying) | Alias (compatibility) | Notes |
149
- |---|---|---|
150
- | `BasePostgresDataSource` | `BaseDataSource` | Same class, re-exported |
151
- | `BasePostgresEntity` | `BaseEntity` | Same class, re-exported |
152
-
153
- Write new code against the canonical names - they make it unambiguous which engine a class belongs to once you have more than one connector in play. Existing code using the aliases needs no changes.
93
+ ### Know what lives in base vs a connector
154
94
 
155
- ## Adding a new engine connector
95
+ - **Engine-specific -> connector.** A connection pool, query dialect, isolation level, or transaction lives in a connector, not `src/base`.
96
+ - **Engine-universal -> base.** `src/base` only ever grows members every engine can implement, such as `getSchema()` or `getIdType()`.
97
+ - **Litmus test.** Could typesense (no pool, no SQL, no transactions) implement it? If not, it belongs in the postgres connector, not the neutral root.
156
98
 
157
- To add a third connector (e.g. a Redis-backed cache connector), follow the shape the two existing connectors share:
99
+ ### Add a new engine connector
158
100
 
159
- 1. **`src/connectors/<engine>/datasources/`** - `Abstract<Engine>DataSource extends AbstractDataSource`, then `Base<Engine>DataSource` (or a single concrete `<Engine>DataSource` if there's no useful abstract/base split) implementing `configure()`/`getConnectionString()`. Override `getCapabilities()` and `beginTransaction()` only if the engine truly supports transactions - otherwise inherit the neutral `NotSupported` default.
160
- 2. **`src/connectors/<engine>/models/`** (if the engine needs entity definitions beyond plain objects) - extend `AbstractEntity`, override `getIdType()` if the engine's ID representation differs from the neutral default.
161
- 3. **`src/connectors/<engine>/repositories/core/`** - `<Engine>BaseRepository extends AbstractRepository`, narrowing the generics to the engine's data/persist/options shapes, followed by a `Readable`/`Persistable`/`DefaultCRUD`-style tier ladder mirroring the postgres and typesense connectors. Any operation the engine cannot support (transactions, locks) should call `throwNotSupported({ scope, feature, logger: this.logger })` for consistency.
162
- 4. **`src/connectors/<engine>/index.ts`** - barrel export for the connector.
163
- 5. **`src/connectors/index.ts`** - add `export * from './<engine>'` **only if** the engine has no optional runtime peer dependency (mirroring `postgres`). If the engine driver is an optional peer (like `typesense`), leave it out of `connectors/index.ts` and register it as a subpath-only export in `package.json`.
164
- 6. **`package.json` `exports`** - add `"./​<engine>": "dist/connectors/<engine>/index.js"`. If the driver is an optional peer, add it to `peerDependencies` + `peerDependenciesMeta.<driver>.optional: true`.
101
+ - **Mirror the shape.** Under `src/connectors/<engine>/`: a `datasources/` extending `AbstractDataSource`, a `models/` extending `AbstractEntity` (if the engine needs entity definitions), and a `repositories/core/` extending `AbstractRepository` with a `Readable`/`Persistable`/`DefaultCRUD`-style tier ladder.
102
+ - **Override transactions only if supported.** Override `getCapabilities()` and `beginTransaction()` only if the engine truly supports transactions - otherwise inherit the neutral `NotSupported` default.
103
+ - **Export as a subpath.** Add the connector to `package.json` `exports` as `./<engine>`; if its driver is an optional peer dependency, keep it out of `connectors/index.ts` and register it as a subpath-only export instead, mirroring typesense and meilisearch.
165
104
 
166
- ## See Also
105
+ ## See also
167
106
 
168
- - **Related Concepts:**
169
- - [DataSources](./datasources) - Full DataSource reference (neutral contract + PostgreSQL connector)
170
- - [Models & Enrichers](./models) - Entity reference (neutral `AbstractEntity` + PostgreSQL `BasePostgresEntity`)
171
- - [Repositories](./repositories/) - Repository hierarchy reference
172
- - [Repository Mixins](./repositories/mixins) - Legacy mixins, now orphaned from the public API
107
+ - [DataSources](./datasources) - the engine-neutral contract and the PostgreSQL connector in depth
108
+ - [Models & Enrichers](./models) - the engine-neutral entity contract and the PostgreSQL connector's entity
109
+ - [Repositories](/references/base/repositories/) - the CRUD layer built on top of a connector's datasource
110
+ - [Filter System](/references/base/filter-system/) - querying through a connector's repository
111
+ - [Persistent Layer](/guides/core-concepts/persistent/) - the guide these reference pages support
112
+ - [Search & Typesense](/guides/core-concepts/persistent/search-typesense) - the typesense connector in depth
113
+ - [Search & Meilisearch](/guides/core-concepts/persistent/search-meilisearch) - the meilisearch connector in depth
173
114
 
174
- - **Guides:**
175
- - [Search & Typesense](/guides/core-concepts/persistent/search-typesense) - The typesense connector in depth
115
+ **Files:**
176
116
 
177
- - **Best Practices:**
178
- - [Architectural Patterns](/best-practices/architectural-patterns) - Layered architecture and separation of concerns
117
+ - [`packages/core/src/base/datasources/abstract.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/datasources/abstract.ts) - neutral `AbstractDataSource`
118
+ - [`packages/core/src/base/models/base.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/models/base.ts) - neutral `AbstractEntity`
119
+ - [`packages/core/src/base/repositories/core/abstract.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/repositories/core/abstract.ts) - neutral `AbstractRepository`
120
+ - [`packages/core/src/connectors/postgres/datasources/base.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/datasources/base.ts) - `BaseRelationalDataSource` (alias `BasePostgresDataSource`)
121
+ - [`packages/core/src/connectors/search/datasources/base.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/search/datasources/base.ts) - `BaseSearchDataSource`, shared by typesense and meilisearch