@venizia/ignis-docs 0.1.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 (148) 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 +83 -67
  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 +31 -17
  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 +98 -0
  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 -607
  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/datasources.md +13 -20
  89. package/content/guides/core-concepts/persistent/index.md +2 -4
  90. package/content/guides/core-concepts/persistent/models.md +1 -1
  91. package/content/guides/core-concepts/persistent/postgres-drivers.md +59 -25
  92. package/content/guides/core-concepts/persistent/search-meilisearch.md +3 -1
  93. package/content/guides/core-concepts/persistent/search-typesense.md +7 -5
  94. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  95. package/content/guides/core-concepts/secrets-vault.md +177 -0
  96. package/content/guides/core-concepts/services.md +1 -1
  97. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  98. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  99. package/content/guides/tutorials/building-a-crud-api.md +9 -13
  100. package/content/guides/tutorials/ecommerce-api.md +10 -15
  101. package/content/guides/tutorials/realtime-chat.md +7 -7
  102. package/content/references/base/application.md +1 -1
  103. package/content/references/base/connectors.md +79 -136
  104. package/content/references/base/datasources-reference.md +599 -0
  105. package/content/references/base/datasources.md +85 -447
  106. package/content/references/base/dependency-injection.md +17 -39
  107. package/content/references/base/filter-system/application-usage.md +69 -121
  108. package/content/references/base/filter-system/array-operators.md +12 -0
  109. package/content/references/base/filter-system/comparison-operators.md +12 -0
  110. package/content/references/base/filter-system/default-filter.md +136 -348
  111. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  112. package/content/references/base/filter-system/index.md +106 -257
  113. package/content/references/base/filter-system/json-filtering.md +12 -2
  114. package/content/references/base/filter-system/list-operators.md +16 -2
  115. package/content/references/base/filter-system/logical-operators.md +13 -0
  116. package/content/references/base/filter-system/null-operators.md +13 -0
  117. package/content/references/base/filter-system/pattern-matching.md +12 -0
  118. package/content/references/base/filter-system/quick-reference.md +11 -2
  119. package/content/references/base/filter-system/range-operators.md +12 -0
  120. package/content/references/base/filter-system/tips.md +70 -133
  121. package/content/references/base/filter-system/use-cases.md +156 -233
  122. package/content/references/base/middlewares.md +35 -21
  123. package/content/references/base/models-reference.md +886 -0
  124. package/content/references/base/models.md +80 -1452
  125. package/content/references/base/repositories/advanced.md +156 -192
  126. package/content/references/base/repositories/index.md +77 -650
  127. package/content/references/base/repositories/mixins.md +22 -18
  128. package/content/references/base/repositories/relations.md +123 -171
  129. package/content/references/base/repositories/soft-deletable.md +58 -56
  130. package/content/references/base/secrets.md +263 -0
  131. package/content/references/base/services.md +2 -2
  132. package/content/references/configuration/environment-variables.md +51 -5
  133. package/content/references/configuration/index.md +49 -31
  134. package/content/references/quick-reference.md +3 -16
  135. package/content/references/utilities/crypto.md +35 -76
  136. package/content/references/utilities/date.md +33 -73
  137. package/content/references/utilities/index.md +1 -1
  138. package/content/references/utilities/jsx-reference.md +298 -0
  139. package/content/references/utilities/jsx.md +82 -525
  140. package/content/references/utilities/module.md +29 -62
  141. package/content/references/utilities/parse.md +34 -64
  142. package/content/references/utilities/performance.md +33 -58
  143. package/content/references/utilities/promise.md +28 -62
  144. package/content/references/utilities/request.md +57 -218
  145. package/content/references/utilities/schema.md +43 -137
  146. package/content/references/utilities/statuses-reference.md +361 -0
  147. package/content/references/utilities/statuses.md +63 -667
  148. package/package.json +8 -8
@@ -268,7 +268,7 @@ import {
268
268
  datasource,
269
269
  ValueOrPromise,
270
270
  } from '@venizia/ignis';
271
- import { drizzle } from 'drizzle-orm/node-postgres';
271
+ import { NodePostgresDriver } from '@venizia/ignis/postgres/node-postgres';
272
272
  import { Pool } from 'pg';
273
273
 
274
274
  interface IDSConfigs {
@@ -279,7 +279,7 @@ interface IDSConfigs {
279
279
  password: string;
280
280
  }
281
281
 
282
- @datasource({ driver: 'node-postgres' })
282
+ @datasource({ driver: NodePostgresDriver })
283
283
  export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
284
284
  constructor() {
285
285
  super({
@@ -295,18 +295,18 @@ export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
295
295
  }
296
296
 
297
297
  override configure(): ValueOrPromise<void> {
298
- const schema = this.getSchema();
298
+ const schema = Object.keys(this.getSchema());
299
299
 
300
300
  this.logger.debug(
301
301
  '[configure] Auto-discovered schema | Schema + Relations (%s): %o',
302
- Object.keys(schema).length,
303
- Object.keys(schema),
302
+ schema.length,
303
+ schema,
304
304
  );
305
305
 
306
306
  // The client must land on this.client - a local would leave beginTransaction() with nothing
307
- // to resolve a driver from, and it would throw `No driver and no client`.
307
+ // to resolve a driver from, and it would throw `No driver and no client`. NodePostgresDriver
308
+ // named in @datasource above is what wires the driver and Drizzle connector from it.
308
309
  this.client = new Pool(this.settings);
309
- this.connector = drizzle({ client: this.client, schema });
310
310
  }
311
311
  }
312
312
  ```
@@ -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 contract plus `resolveDatabaseDriver`. 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`. `resolveDatabaseDriver({ client })` structurally detects which client the app built and lazily `import()`s only the matching driver. 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