@venizia/ignis-docs 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/content/best-practices/api-usage-examples.md +15 -12
- package/content/best-practices/architectural-patterns.md +70 -78
- package/content/best-practices/architecture-decisions.md +91 -60
- package/content/best-practices/code-style-standards/advanced-patterns.md +56 -44
- package/content/best-practices/code-style-standards/constants-configuration.md +11 -11
- package/content/best-practices/code-style-standards/control-flow.md +5 -2
- package/content/best-practices/code-style-standards/documentation.md +13 -13
- package/content/best-practices/code-style-standards/function-patterns.md +9 -10
- package/content/best-practices/code-style-standards/index.md +1 -1
- package/content/best-practices/code-style-standards/naming-conventions.md +10 -8
- package/content/best-practices/code-style-standards/route-definitions.md +30 -12
- package/content/best-practices/code-style-standards/tooling.md +8 -5
- package/content/best-practices/code-style-standards/type-safety.md +13 -12
- package/content/best-practices/common-pitfalls.md +56 -37
- package/content/best-practices/contribution-workflow.md +13 -14
- package/content/best-practices/data-modeling.md +44 -20
- package/content/best-practices/deployment-strategies.md +28 -27
- package/content/best-practices/error-handling.md +48 -24
- package/content/best-practices/index.md +5 -5
- package/content/best-practices/performance-optimization.md +36 -28
- package/content/best-practices/security-guidelines.md +52 -23
- package/content/best-practices/testing-strategies.md +65 -51
- package/content/best-practices/troubleshooting-tips.md +24 -24
- package/content/extensions/components/{swagger.md → api-reference.md} +40 -31
- package/content/extensions/components/authentication/api.md +19 -19
- package/content/extensions/components/authentication/errors.md +7 -7
- package/content/extensions/components/authentication/index.md +10 -8
- package/content/extensions/components/authentication/usage.md +101 -6
- package/content/extensions/components/authorization/api.md +45 -25
- package/content/extensions/components/authorization/errors.md +6 -6
- package/content/extensions/components/authorization/index.md +11 -10
- package/content/extensions/components/authorization/usage.md +21 -21
- package/content/extensions/components/health-check.md +1 -1
- package/content/extensions/components/index.md +5 -5
- package/content/extensions/components/mail/errors.md +15 -15
- package/content/extensions/components/mail/index.md +1 -2
- package/content/extensions/components/mail/usage.md +1 -1
- package/content/extensions/components/request-tracker.md +1 -1
- package/content/extensions/components/socket-io/api.md +9 -9
- package/content/extensions/components/socket-io/errors.md +5 -5
- package/content/extensions/components/socket-io/index.md +8 -8
- package/content/extensions/components/socket-io/usage.md +1 -1
- package/content/extensions/components/static-asset/api.md +17 -4
- package/content/extensions/components/static-asset/errors.md +4 -4
- package/content/extensions/components/static-asset/index.md +26 -28
- package/content/extensions/components/static-asset/usage.md +13 -12
- package/content/extensions/components/template/index.md +2 -2
- package/content/extensions/components/template/setup-page.md +1 -1
- package/content/extensions/components/websocket/api.md +3 -3
- package/content/extensions/components/websocket/errors.md +5 -5
- package/content/extensions/components/websocket/index.md +5 -5
- package/content/extensions/components/websocket/usage.md +3 -3
- package/content/extensions/helpers/cron/index.md +2 -2
- package/content/extensions/helpers/crypto/index.md +1 -1
- package/content/extensions/helpers/env/index.md +27 -12
- package/content/extensions/helpers/error/index.md +81 -25
- package/content/extensions/helpers/index.md +2 -3
- package/content/extensions/helpers/inversion/index.md +15 -7
- package/content/extensions/helpers/kafka/examples.md +1 -1
- package/content/extensions/helpers/logger/index.md +32 -2
- package/content/extensions/helpers/network/index.md +6 -0
- package/content/extensions/helpers/queue/index.md +14 -17
- package/content/extensions/helpers/redis/index.md +548 -323
- package/content/extensions/helpers/socket-io/index.md +14 -10
- package/content/extensions/helpers/storage/api.md +44 -8
- package/content/extensions/helpers/storage/index.md +43 -7
- package/content/extensions/helpers/template/index.md +6 -3
- package/content/extensions/helpers/types/index.md +11 -8
- package/content/extensions/helpers/websocket/api.md +9 -9
- package/content/extensions/helpers/websocket/index.md +7 -7
- package/content/extensions/helpers/worker-thread/index.md +2 -2
- package/content/extensions/index.md +3 -4
- package/content/extensions/src-details/mcp-server.md +18 -24
- package/content/guides/core-concepts/application/bootstrapping.md +11 -14
- package/content/guides/core-concepts/application/index.md +3 -3
- package/content/guides/core-concepts/components.md +19 -10
- package/content/guides/core-concepts/dependency-injection.md +6 -3
- package/content/guides/core-concepts/grpc-controllers.md +6 -5
- package/content/guides/core-concepts/persistent/datasources.md +33 -27
- package/content/guides/core-concepts/persistent/index.md +16 -5
- package/content/guides/core-concepts/persistent/models.md +24 -20
- package/content/guides/core-concepts/persistent/postgres-drivers.md +167 -0
- package/content/guides/core-concepts/persistent/repositories.md +40 -23
- package/content/guides/core-concepts/persistent/search-meilisearch.md +183 -0
- package/content/guides/core-concepts/persistent/search-typesense.md +429 -0
- package/content/guides/core-concepts/persistent/transactions.md +61 -25
- package/content/guides/core-concepts/rest-controllers.md +12 -9
- package/content/guides/core-concepts/services.md +330 -60
- package/content/guides/get-started/5-minute-quickstart.md +15 -15
- package/content/guides/get-started/philosophy.md +36 -36
- package/content/guides/get-started/setup.md +3 -3
- package/content/guides/index.md +3 -3
- package/content/guides/migrations/redis-helpers-migration.md +177 -0
- package/content/guides/migrations/scoped-rbac-migration.md +17 -17
- package/content/guides/migrations/unified-connectors-migration.md +113 -0
- package/content/guides/reference/glossary.md +19 -12
- package/content/guides/reference/mcp-docs-server.md +22 -18
- package/content/guides/tutorials/building-a-crud-api.md +30 -33
- package/content/guides/tutorials/complete-installation.md +17 -17
- package/content/guides/tutorials/ecommerce-api.md +158 -119
- package/content/guides/tutorials/realtime-chat.md +176 -130
- package/content/guides/tutorials/testing.md +65 -523
- package/content/index.md +2 -180
- package/content/public/apple-touch-icon.png +0 -0
- package/content/public/og-image.png +0 -0
- package/content/public/site.webmanifest +11 -0
- package/content/references/base/application.md +4 -5
- package/content/references/base/bootstrapping.md +18 -5
- package/content/references/base/components.md +149 -120
- package/content/references/base/connectors.md +178 -0
- package/content/references/base/controllers.md +41 -30
- package/content/references/base/datasources.md +154 -81
- package/content/references/base/dependency-injection.md +34 -22
- package/content/references/base/filter-system/application-usage.md +17 -14
- package/content/references/base/filter-system/array-operators.md +7 -2
- package/content/references/base/filter-system/comparison-operators.md +3 -0
- package/content/references/base/filter-system/default-filter.md +89 -71
- package/content/references/base/filter-system/fields-order-pagination.md +22 -22
- package/content/references/base/filter-system/index.md +6 -3
- package/content/references/base/filter-system/json-filtering.md +20 -1
- package/content/references/base/filter-system/list-operators.md +1 -1
- package/content/references/base/filter-system/logical-operators.md +33 -1
- package/content/references/base/filter-system/null-operators.md +30 -1
- package/content/references/base/filter-system/quick-reference.md +23 -4
- package/content/references/base/filter-system/tips.md +5 -5
- package/content/references/base/filter-system/use-cases.md +12 -12
- package/content/references/base/grpc-controllers.md +13 -13
- package/content/references/base/index.md +24 -12
- package/content/references/base/middlewares.md +265 -327
- package/content/references/base/models.md +63 -49
- package/content/references/base/providers.md +136 -130
- package/content/references/base/repositories/advanced.md +59 -58
- package/content/references/base/repositories/index.md +115 -91
- package/content/references/base/repositories/mixins.md +55 -291
- package/content/references/base/repositories/relations.md +54 -64
- package/content/references/base/repositories/soft-deletable.md +31 -30
- package/content/references/base/services.md +296 -93
- package/content/references/configuration/environment-variables.md +46 -30
- package/content/references/configuration/index.md +6 -6
- package/content/references/index.md +17 -12
- package/content/references/quick-reference.md +65 -106
- package/content/references/utilities/crypto.md +65 -23
- package/content/references/utilities/index.md +3 -3
- package/content/references/utilities/jsx.md +6 -4
- package/content/references/utilities/module.md +68 -20
- package/content/references/utilities/parse.md +4 -14
- package/content/references/utilities/promise.md +9 -7
- package/content/references/utilities/schema.md +5 -3
- package/dist/mcp-server/common/guards.d.ts +8 -0
- package/dist/mcp-server/common/guards.d.ts.map +1 -0
- package/dist/mcp-server/common/guards.js +14 -0
- package/dist/mcp-server/common/guards.js.map +1 -0
- package/dist/mcp-server/common/index.d.ts +1 -0
- package/dist/mcp-server/common/index.d.ts.map +1 -1
- package/dist/mcp-server/common/index.js +1 -0
- package/dist/mcp-server/common/index.js.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.js +4 -2
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
- package/dist/mcp-server/helpers/github.helper.js +1 -1
- package/dist/mcp-server/index.js +7 -2
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/mcp-server/tools/base.tool.d.ts +6 -2
- package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/base.tool.js.map +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
- package/package.json +9 -9
- package/content/extensions/helpers/testing/index.md +0 -510
- package/content/references/base/middleware.md +0 -347
|
@@ -1,28 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: DataSources Reference
|
|
3
|
-
description: Technical reference for DataSource
|
|
3
|
+
description: Technical reference for the engine-neutral DataSource contract and the PostgreSQL connector implementation
|
|
4
4
|
difficulty: intermediate
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Deep Dive: DataSources
|
|
8
8
|
|
|
9
|
-
Technical reference for DataSource classes - managing database connections in
|
|
9
|
+
Technical reference for DataSource classes - managing database and search engine connections in IGNIS.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> [!IMPORTANT] Base vs. Connectors
|
|
12
|
+
> IGNIS splits datasources into an **engine-neutral root** (`src/base/datasources/`) and **per-engine connectors** (`src/connectors/{postgres,typesense}/datasources/`). `AbstractDataSource` has no SQL, no Drizzle, and no `pool` - those live only in the PostgreSQL connector. See [Connectors](./connectors) for the full base-vs-connectors architecture, dual-door exports, and how to add a new engine. This page documents the neutral contract plus the PostgreSQL connector in depth; see [Search & Typesense](/guides/core-concepts/persistent/search-typesense) for the other engine.
|
|
13
|
+
|
|
14
|
+
**Files:** `packages/core/src/base/datasources/*.ts` (neutral) and `packages/core/src/connectors/postgres/datasources/*.ts` (PostgreSQL)
|
|
12
15
|
|
|
13
16
|
## Quick Reference
|
|
14
17
|
|
|
15
18
|
| Class/Interface | Purpose | Key Members |
|
|
16
19
|
|-----------------|---------|-------------|
|
|
17
|
-
| **IDataSource** |
|
|
18
|
-
| **AbstractDataSource** |
|
|
19
|
-
| **
|
|
20
|
-
| **
|
|
21
|
-
| **
|
|
20
|
+
| **IDataSource** | Engine-neutral contract for all datasources | `name`, `settings`, `schema`, `getSchema()`, `getSettings()`, `configure()` |
|
|
21
|
+
| **AbstractDataSource** | Engine-neutral base implementation with logging | Extends `BaseHelper`, `getCapabilities()` defaults to `{ transactions: false }`, `beginTransaction()` defaults to `throwNotSupported(...)` |
|
|
22
|
+
| **AbstractPostgresDataSource** | PostgreSQL-aware abstraction | Adds `connector`, `client`, `driver`, abstract `getConnectionString()`/`beginTransaction()` |
|
|
23
|
+
| **BasePostgresDataSource** | Concrete class to extend for PostgreSQL | Auto-discovery, real transaction support, constructor with config. Canonical name - `BaseDataSource` is a compatibility alias re-exporting the same class |
|
|
24
|
+
| **ITransaction** | Engine-neutral transaction contract | `isActive`, `commit()`, `rollback()` (no connector field) |
|
|
25
|
+
| **IDatabaseTransaction** | PostgreSQL transaction object | Extends `ITransaction`, adds `connector`, `isolationLevel` |
|
|
26
|
+
| **IsolationLevels** | Isolation level constants (PostgreSQL) | `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE` |
|
|
22
27
|
|
|
23
28
|
## `IDataSource` Interface
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
Engine-neutral contract implemented by every datasource in the framework, regardless of engine.
|
|
26
31
|
|
|
27
32
|
**File:** `packages/core/src/base/datasources/common/types.ts`
|
|
28
33
|
|
|
@@ -39,7 +44,7 @@ interface IDataSource<
|
|
|
39
44
|
| Type Parameter | Default | Description |
|
|
40
45
|
|----------------|---------|-------------|
|
|
41
46
|
| `Settings` | `{}` | Connection configuration type (host, port, etc.) |
|
|
42
|
-
| `Schema` | `TAnyDataSourceSchema` | Combined
|
|
47
|
+
| `Schema` | `TAnyDataSourceSchema` | Combined schema type (shape depends on the connector - Drizzle tables for PostgreSQL, collection definitions for typesense) |
|
|
43
48
|
| `ConfigurableOptions` | `{}` | Options passed to `configure()` |
|
|
44
49
|
|
|
45
50
|
### Properties & Methods
|
|
@@ -48,22 +53,19 @@ interface IDataSource<
|
|
|
48
53
|
|--------|------|-------------|
|
|
49
54
|
| `name` | `string` | Datasource name |
|
|
50
55
|
| `settings` | `Settings` | Configuration object |
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `getSchema()` | `Schema` | Returns combined Drizzle schema |
|
|
56
|
+
| `schema` | `Schema` | Combined schema (auto-discovered or manual) |
|
|
57
|
+
| `getSchema()` | `Schema` | Returns combined schema |
|
|
54
58
|
| `getSettings()` | `Settings` | Returns connection settings |
|
|
55
|
-
| `
|
|
56
|
-
| `getConnectionString()` | `ValueOrPromise<string>` | Returns connection string |
|
|
57
|
-
| `configure(opts?)` | `ValueOrPromise<void>` | Initializes pool and connector |
|
|
58
|
-
| `beginTransaction(opts?)` | `Promise<ITransaction<Schema>>` | Starts a new database transaction |
|
|
59
|
+
| `configure(opts?)` | `ValueOrPromise<void>` | Initializes the underlying connection (from `IConfigurable`) |
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
> [!NOTE]
|
|
62
|
+
> `getCapabilities()` and `beginTransaction()` are not part of the `IDataSource` interface - they are declared on `AbstractDataSource` (below), which every connector extends.
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
## `AbstractDataSource` (Engine-Neutral Root)
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
**File:** `packages/core/src/base/datasources/abstract.ts`
|
|
65
67
|
|
|
66
|
-
Top-level abstract class
|
|
68
|
+
Top-level abstract class implemented by every engine. Extends `BaseHelper` for scoped logging. Contains **no SQL, no Drizzle, and no connection-pool members** - those are added by each connector.
|
|
67
69
|
|
|
68
70
|
```typescript
|
|
69
71
|
abstract class AbstractDataSource<
|
|
@@ -79,45 +81,92 @@ abstract class AbstractDataSource<
|
|
|
79
81
|
|----------|------|------------|-------------|
|
|
80
82
|
| `name` | `string` | public | Datasource identifier |
|
|
81
83
|
| `settings` | `Settings` | public | Connection configuration |
|
|
82
|
-
| `
|
|
83
|
-
| `schema` | `Schema` | public | Combined schema (tables + relations) |
|
|
84
|
-
| `pool` | `Pool` | protected | node-postgres connection pool |
|
|
84
|
+
| `schema` | `Schema` | public | Combined schema |
|
|
85
85
|
|
|
86
|
-
**Abstract methods** (must be implemented by
|
|
86
|
+
**Abstract methods** (must be implemented by connectors):
|
|
87
87
|
|
|
88
88
|
| Method | Return Type | Description |
|
|
89
89
|
|--------|-------------|-------------|
|
|
90
|
-
| `configure(opts?)` | `ValueOrPromise<void>` | Initialize
|
|
91
|
-
| `getConnectionString()` | `ValueOrPromise<string>` | Return the
|
|
92
|
-
| `beginTransaction(opts?)` | `Promise<ITransaction<Schema>>` | Start a new transaction |
|
|
90
|
+
| `configure(opts?)` | `ValueOrPromise<void>` | Initialize the underlying connection |
|
|
91
|
+
| `getConnectionString()` | `ValueOrPromise<string>` | Return the connection URL |
|
|
93
92
|
|
|
94
|
-
**Concrete methods:**
|
|
93
|
+
**Concrete methods (defaults, overridable by connectors):**
|
|
95
94
|
|
|
96
|
-
| Method | Return Type |
|
|
97
|
-
|
|
95
|
+
| Method | Return Type | Default Behavior |
|
|
96
|
+
|--------|-------------|-------------------|
|
|
98
97
|
| `getSettings()` | `Settings` | Returns `this.settings` |
|
|
99
|
-
| `getConnector()` | `TNodePostgresConnector<Schema>` | Returns `this.connector` |
|
|
100
98
|
| `getSchema()` | `Schema` | Returns `this.schema` (throws if not initialized) |
|
|
99
|
+
| `getCapabilities()` | `IDataSourceCapabilities` | Returns `{ transactions: false }` |
|
|
100
|
+
| `beginTransaction(opts?)` | `Promise<ITransaction>` | Calls `throwNotSupported({ scope: this.constructor.name, feature: 'Transactions', logger: this.logger })` - throws HTTP 501 with `messageCode: 'core.not_supported'` |
|
|
101
|
+
|
|
102
|
+
> [!NOTE] NotSupported convention
|
|
103
|
+
> Every capability an engine doesn't implement - transactions, row-level locking - uses the same `throwNotSupported` utility (`packages/core/src/utilities/error.utility.ts`), producing a consistent `501 Not Implemented` with `messageCode: 'core.not_supported'`. This is how the typesense connector signals "not applicable to this engine" instead of silently no-op-ing.
|
|
104
|
+
|
|
105
|
+
### `IDataSourceCapabilities`
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
interface IDataSourceCapabilities {
|
|
109
|
+
transactions: boolean;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Only `BasePostgresDataSource` overrides `getCapabilities()` to return `{ transactions: true }`. The typesense datasources inherit the neutral default.
|
|
114
|
+
|
|
115
|
+
## PostgreSQL Connector: `AbstractPostgresDataSource` & `BasePostgresDataSource`
|
|
116
|
+
|
|
117
|
+
**Files:** `packages/core/src/connectors/postgres/datasources/abstract.ts`, `packages/core/src/connectors/postgres/datasources/base.ts`
|
|
101
118
|
|
|
102
|
-
### `
|
|
119
|
+
### `AbstractPostgresDataSource`
|
|
103
120
|
|
|
104
|
-
Extends `AbstractDataSource` with
|
|
121
|
+
Extends `AbstractDataSource` with PostgreSQL/Drizzle-specific members.
|
|
105
122
|
|
|
106
123
|
```typescript
|
|
107
|
-
abstract class
|
|
124
|
+
abstract class AbstractPostgresDataSource<
|
|
108
125
|
Settings extends object = {},
|
|
109
126
|
Schema extends TAnyDataSourceSchema = TAnyDataSourceSchema,
|
|
110
127
|
ConfigurableOptions extends object = {},
|
|
111
128
|
> extends AbstractDataSource<Settings, Schema, ConfigurableOptions>
|
|
112
129
|
```
|
|
113
130
|
|
|
131
|
+
**Additional properties:**
|
|
132
|
+
|
|
133
|
+
| Property | Type | Visibility | Description |
|
|
134
|
+
|----------|------|------------|-------------|
|
|
135
|
+
| `connector` | `TRelationalConnector<Schema>` | public | Drizzle ORM instance (any Drizzle pg driver satisfies this - see the driver seam below) |
|
|
136
|
+
| `driver` | `IRelationalDriver` | protected | The connection driver (`node-postgres` or `postgres-js`); built by `useDriver()` |
|
|
137
|
+
| `client` | `Client` (`Pool` by default) | protected | The raw driver client `configure()` built - a `pg.Pool`, or a postgres-js `Sql`. Assigning it alone is enough: a driver is resolved from it on first use. Absent once `useDriver()` wired a driver instead |
|
|
138
|
+
|
|
139
|
+
> [!NOTE] Driver seam
|
|
140
|
+
> `AbstractRelationalDataSource`/`BaseRelationalDataSource` (exported as `AbstractPostgresDataSource`/`BasePostgresDataSource`) now take a fourth generic - `<Settings, Schema, ConfigurableOptions, Client = Pool>` - so a `postgres-js` datasource can declare `Client = Sql` and keep `getClient()` honest. The protected `useDriver({ driver, schema? })` assigns `this.driver` **and** builds `this.connector` in one step. `pg` and `postgres` are both optional peer dependencies; concrete drivers live at `@venizia/ignis/postgres/node-postgres` and `@venizia/ignis/postgres/postgres-js`, and Supabase support at `@venizia/ignis/postgres/supabase`. See [Postgres Drivers & Supabase](/guides/core-concepts/persistent/postgres-drivers).
|
|
141
|
+
|
|
142
|
+
**Additional abstract method:**
|
|
143
|
+
|
|
144
|
+
| Method | Return Type | Description |
|
|
145
|
+
|--------|-------------|-------------|
|
|
146
|
+
| `beginTransaction(opts?)` | `Promise<IDatabaseTransaction<Schema>>` | Start a new PostgreSQL transaction |
|
|
147
|
+
|
|
148
|
+
### `BasePostgresDataSource` (canonical name; `BaseDataSource` is a compatibility alias)
|
|
149
|
+
|
|
150
|
+
Extends `AbstractPostgresDataSource` with a constructor, **schema auto-discovery**, and a real `beginTransaction()` implementation backed by the connection pool.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
abstract class BasePostgresDataSource<
|
|
154
|
+
Settings extends object = {},
|
|
155
|
+
Schema extends TAnyDataSourceSchema = TAnyDataSourceSchema,
|
|
156
|
+
ConfigurableOptions extends object = {},
|
|
157
|
+
> extends AbstractPostgresDataSource<Settings, Schema, ConfigurableOptions>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
> [!TIP] Naming
|
|
161
|
+
> `BasePostgresDataSource` is the canonical, engine-carrying name - prefer it in new code. `import { BaseDataSource } from '@venizia/ignis'` (or `@venizia/ignis/postgres`) still resolves to the exact same class via a re-export in `connectors/postgres/datasources/index.ts` (`export { BasePostgresDataSource as BaseDataSource } from './base-datasource'`), so existing code is unaffected.
|
|
162
|
+
|
|
114
163
|
#### Key Features
|
|
115
164
|
|
|
116
165
|
| Feature | Description |
|
|
117
|
-
|
|
166
|
+
|---------|--------------|
|
|
118
167
|
| **Schema Auto-Discovery** | Schema is automatically built from registered `@repository` decorators |
|
|
119
168
|
| **Manual Override** | You can manually provide schema in constructor for full control |
|
|
120
|
-
| **Built-in Transaction Support** | `beginTransaction()`
|
|
169
|
+
| **Built-in Transaction Support** | `beginTransaction()` acquires its connection from the resolved driver; overrides `getCapabilities()` to return `{ transactions: true }` |
|
|
121
170
|
|
|
122
171
|
> [!TIP]
|
|
123
172
|
> Set `autoDiscovery` to `false` in the `@datasource` decorator to disable automatic schema discovery. This is useful when you want to manually provide the schema.
|
|
@@ -154,8 +203,8 @@ When you use `@repository({ model: YourModel, dataSource: YourDataSource })`, th
|
|
|
154
203
|
|
|
155
204
|
3. **Your `configure()` method runs**:
|
|
156
205
|
- Call `this.getSchema()` to get the auto-discovered schema
|
|
157
|
-
- Create a `Pool` instance and assign it to `this.
|
|
158
|
-
- Create the Drizzle connector
|
|
206
|
+
- Create a `Pool` instance and assign it to `this.client` (required for transaction support)
|
|
207
|
+
- Create the Drizzle connector from that client and the schema
|
|
159
208
|
|
|
160
209
|
### Example Implementations
|
|
161
210
|
|
|
@@ -165,12 +214,12 @@ Simplest approach - schema is auto-discovered from repositories:
|
|
|
165
214
|
|
|
166
215
|
```typescript
|
|
167
216
|
// src/datasources/postgres.datasource.ts
|
|
168
|
-
import {
|
|
169
|
-
import { applicationEnvironment, int } from '@venizia/ignis-helpers';
|
|
217
|
+
import { BasePostgresDataSource, datasource } from '@venizia/ignis';
|
|
218
|
+
import { applicationEnvironment, int, ValueOrPromise } from '@venizia/ignis-helpers';
|
|
170
219
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
171
220
|
import { Pool } from 'pg';
|
|
172
221
|
|
|
173
|
-
interface
|
|
222
|
+
interface IDataSourceConfigs {
|
|
174
223
|
host: string;
|
|
175
224
|
port: number;
|
|
176
225
|
database: string;
|
|
@@ -188,7 +237,7 @@ interface IDSConfigs {
|
|
|
188
237
|
* 3. Drizzle is initialized with the auto-discovered schema
|
|
189
238
|
*/
|
|
190
239
|
@datasource({ driver: 'node-postgres' })
|
|
191
|
-
export class PostgresDataSource extends
|
|
240
|
+
export class PostgresDataSource extends BasePostgresDataSource<IDataSourceConfigs> {
|
|
192
241
|
private readonly protocol = 'postgresql';
|
|
193
242
|
|
|
194
243
|
constructor() {
|
|
@@ -210,16 +259,16 @@ export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
|
|
|
210
259
|
// getSchema() auto-discovers models from @repository bindings
|
|
211
260
|
const schema = this.getSchema();
|
|
212
261
|
|
|
213
|
-
const
|
|
262
|
+
const dataSourceSchema = Object.keys(schema);
|
|
214
263
|
this.logger.debug(
|
|
215
264
|
'[configure] Auto-discovered schema | Schema + Relations (%s): %o',
|
|
216
|
-
|
|
217
|
-
|
|
265
|
+
dataSourceSchema.length,
|
|
266
|
+
dataSourceSchema,
|
|
218
267
|
);
|
|
219
268
|
|
|
220
|
-
//
|
|
221
|
-
this.
|
|
222
|
-
this.connector = drizzle({ client: this.
|
|
269
|
+
// The client slot is what beginTransaction() resolves its driver from
|
|
270
|
+
this.client = new Pool(this.settings);
|
|
271
|
+
this.connector = drizzle({ client: this.client, schema });
|
|
223
272
|
}
|
|
224
273
|
|
|
225
274
|
override getConnectionString(): ValueOrPromise<string> {
|
|
@@ -252,7 +301,7 @@ import {
|
|
|
252
301
|
} from '@/models/entities';
|
|
253
302
|
|
|
254
303
|
@datasource({ driver: 'node-postgres' })
|
|
255
|
-
export class PostgresDataSource extends
|
|
304
|
+
export class PostgresDataSource extends BasePostgresDataSource<IDataSourceConfigs> {
|
|
256
305
|
constructor() {
|
|
257
306
|
super({
|
|
258
307
|
name: PostgresDataSource.name,
|
|
@@ -275,8 +324,8 @@ export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
|
|
|
275
324
|
|
|
276
325
|
override configure(): ValueOrPromise<void> {
|
|
277
326
|
// When schema is manually provided, getSchema() returns it directly
|
|
278
|
-
this.
|
|
279
|
-
this.connector = drizzle({ client: this.
|
|
327
|
+
this.client = new Pool(this.settings);
|
|
328
|
+
this.connector = drizzle({ client: this.client, schema: this.getSchema() });
|
|
280
329
|
}
|
|
281
330
|
|
|
282
331
|
override getConnectionString(): ValueOrPromise<string> {
|
|
@@ -286,7 +335,7 @@ export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
|
|
|
286
335
|
```
|
|
287
336
|
|
|
288
337
|
> [!IMPORTANT]
|
|
289
|
-
>
|
|
338
|
+
> Your `configure()` must leave the datasource with a way to reach the database: either assign the raw client to `this.client`, or wire a driver with `this.useDriver({ driver })`. `beginTransaction()` resolves a driver lazily from whichever you provided. With neither, it throws `No driver and no client`.
|
|
290
339
|
|
|
291
340
|
### `@datasource` Decorator
|
|
292
341
|
|
|
@@ -301,16 +350,16 @@ The `@datasource` decorator registers datasource metadata:
|
|
|
301
350
|
|
|
302
351
|
| Option | Type | Default | Description |
|
|
303
352
|
|--------|------|---------|-------------|
|
|
304
|
-
| `driver` | `TDataSourceDriver` | - |
|
|
353
|
+
| `driver` | `TDataSourceDriver` | - | Driver name - `DataSourceDrivers` defines four constants: `'node-postgres'` and `'postgres-js'` (relational), `'typesense'` and `'meilisearch'` (search); any other engine-driver string is also accepted |
|
|
305
354
|
| `autoDiscovery` | `boolean` | `true` | Enable/disable schema auto-discovery |
|
|
306
355
|
|
|
307
356
|
### Abstract Methods
|
|
308
357
|
|
|
309
|
-
When extending `
|
|
358
|
+
When extending `BasePostgresDataSource`, these methods must be implemented:
|
|
310
359
|
|
|
311
360
|
| Method | Return Type | Description |
|
|
312
361
|
|--------|-------------|-------------|
|
|
313
|
-
| `configure(opts?)` | `ValueOrPromise<void>` | Initialize
|
|
362
|
+
| `configure(opts?)` | `ValueOrPromise<void>` | Initialize the client and Drizzle connector. Must set `this.client` (or call `this.useDriver()`) and `this.connector`. |
|
|
314
363
|
| `getConnectionString()` | `ValueOrPromise<string>` | Return the database connection string. |
|
|
315
364
|
|
|
316
365
|
### Helper Methods
|
|
@@ -330,61 +379,78 @@ When extending `BaseDataSource`, these methods must be implemented:
|
|
|
330
379
|
|
|
331
380
|
## Connector Types
|
|
332
381
|
|
|
333
|
-
**File:** `packages/core/src/
|
|
382
|
+
**File:** `packages/core/src/connectors/postgres/datasources/common/types.ts`
|
|
334
383
|
|
|
335
384
|
| Type | Description |
|
|
336
385
|
|------|-------------|
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
386
|
+
| `TRelationalConnector<Schema>` | Canonical connector type - a Drizzle `PgDatabase` that **every** pg driver (`node-postgres`, `postgres-js`) satisfies. Use this in new code. |
|
|
387
|
+
| `TNodePostgresConnector<Schema>` | **`@deprecated`** compat alias for `TRelationalConnector<Schema>` |
|
|
388
|
+
| `TNodePostgresTransactionConnector<Schema>` | **`@deprecated`** compat alias - was the `PoolClient`-specific transaction connector; now aliases `TRelationalConnector<Schema>` |
|
|
389
|
+
| `TAnyConnector<Schema>` | Alias of `TRelationalConnector<Schema>` |
|
|
390
|
+
| `TAnyDataSourceSchema` | `Record<string, any>` - base type for all schema objects (defined in `src/base/datasources/common/types.ts`, shared across engines) |
|
|
341
391
|
|
|
342
392
|
### `DataSourceDrivers`
|
|
343
393
|
|
|
344
|
-
Static class for driver validation:
|
|
394
|
+
Static class for driver validation (defined in `src/base/datasources/common/types.ts`, shared across engines):
|
|
345
395
|
|
|
346
396
|
```typescript
|
|
347
397
|
DataSourceDrivers.NODE_POSTGRES // 'node-postgres'
|
|
398
|
+
DataSourceDrivers.POSTGRES_JS // 'postgres-js'
|
|
399
|
+
DataSourceDrivers.TYPESENSE // 'typesense'
|
|
400
|
+
DataSourceDrivers.MEILISEARCH // 'meilisearch'
|
|
348
401
|
DataSourceDrivers.isValid('node-postgres') // true
|
|
349
402
|
```
|
|
350
403
|
|
|
351
404
|
## Transaction Support
|
|
352
405
|
|
|
353
|
-
|
|
406
|
+
Only engines that declare `getCapabilities().transactions === true` implement real transactions - currently just the PostgreSQL connector. Calling `beginTransaction()` on the typesense connector throws `NotSupported` (HTTP 501).
|
|
354
407
|
|
|
355
408
|
### How It Works
|
|
356
409
|
|
|
357
|
-
`
|
|
410
|
+
`BasePostgresDataSource.beginTransaction()` does the following:
|
|
358
411
|
|
|
359
|
-
1.
|
|
412
|
+
1. Resolves a driver from `this.client` (or the one `useDriver()` wired) and acquires a connection from it
|
|
360
413
|
2. Executes `BEGIN TRANSACTION ISOLATION LEVEL <level>` on the client
|
|
361
414
|
3. Creates a separate Drizzle connector scoped to that client
|
|
362
|
-
4. Returns an `
|
|
415
|
+
4. Returns an `IDatabaseTransaction` object with `commit()`, `rollback()`, and the scoped `connector`
|
|
363
416
|
|
|
364
|
-
When `commit()` or `rollback()`
|
|
417
|
+
When `commit()` or `rollback()` succeeds, the client is released back to the pool.
|
|
365
418
|
|
|
366
|
-
|
|
419
|
+
> [!WARNING] `commit()`/`rollback()` throw on failure
|
|
420
|
+
> A failed `COMMIT` or `ROLLBACK` **throws** (a failed `COMMIT` no longer resolves as success), and the poisoned connection is **destroyed** rather than returned to the pool - under the `node-postgres` driver, which can discard a connection; `postgres-js` has no destroy semantics and pools it anyway. A failed `BEGIN` also destroys the acquired connection rather than leaking it. Because `rollback()` can throw and is normally called from a `catch`, nest it in its own `try...catch` so the rollback error does not replace the original cause. See [Transactions](/guides/core-concepts/persistent/transactions) and [Postgres Drivers & Supabase](/guides/core-concepts/persistent/postgres-drivers).
|
|
367
421
|
|
|
368
|
-
|
|
369
|
-
|------|-------------|
|
|
370
|
-
| `ITransaction<Schema>` | Transaction object with `commit()`, `rollback()`, and `connector` |
|
|
371
|
-
| `ITransactionOptions` | Options for starting a transaction (e.g., `isolationLevel`) |
|
|
372
|
-
| `TIsolationLevel` | Union type: `'READ COMMITTED'` \| `'REPEATABLE READ'` \| `'SERIALIZABLE'` |
|
|
373
|
-
| `IsolationLevels` | Static class with isolation level constants and validation |
|
|
422
|
+
### Neutral vs. PostgreSQL Transaction Types
|
|
374
423
|
|
|
375
|
-
|
|
424
|
+
`src/base` declares the engine-neutral shape; the PostgreSQL connector narrows it with connection details.
|
|
376
425
|
|
|
377
426
|
```typescript
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
isActive: boolean;
|
|
381
|
-
isolationLevel: TIsolationLevel;
|
|
382
|
-
|
|
427
|
+
// packages/core/src/base/datasources/common/types.ts - engine-neutral
|
|
428
|
+
interface ITransaction<_Schema = unknown> {
|
|
429
|
+
isActive: boolean;
|
|
383
430
|
commit(): Promise<void>;
|
|
384
431
|
rollback(): Promise<void>;
|
|
385
432
|
}
|
|
433
|
+
|
|
434
|
+
// packages/core/src/connectors/postgres/datasources/common/types.ts - PostgreSQL
|
|
435
|
+
interface IDatabaseTransaction<Schema extends TAnyDataSourceSchema = TAnyDataSourceSchema>
|
|
436
|
+
extends ITransaction<Schema> {
|
|
437
|
+
connector: TRelationalConnector<Schema>;
|
|
438
|
+
isolationLevel: TIsolationLevel;
|
|
439
|
+
}
|
|
386
440
|
```
|
|
387
441
|
|
|
442
|
+
| Type | Description |
|
|
443
|
+
|------|-------------|
|
|
444
|
+
| `ITransaction<Schema>` | Engine-neutral contract - `isActive`, `commit()`, `rollback()`. No connector field. |
|
|
445
|
+
| `IDatabaseTransaction<Schema>` | PostgreSQL transaction object - extends `ITransaction` with `connector` and `isolationLevel` |
|
|
446
|
+
| `IDatabaseTransactionOptions` | Options for starting a PostgreSQL transaction (`isolationLevel`); extends the neutral `ITransactionOptions` |
|
|
447
|
+
| `IDatabaseExtraOptions` | Extends the neutral `IExtraOptions`, narrowing `transaction?: IDatabaseTransaction` |
|
|
448
|
+
| `TIsolationLevel` | Union type: `'READ COMMITTED'` \| `'REPEATABLE READ'` \| `'SERIALIZABLE'` |
|
|
449
|
+
| `IsolationLevels` | Static class with isolation level constants and validation |
|
|
450
|
+
|
|
451
|
+
> [!NOTE]
|
|
452
|
+
> `AbstractRepository`, `PersistableRepository`, and every other engine-neutral repository type parameter is named `TOptions`/`IExtraOptions` in `src/base`. The PostgreSQL connector's `PostgresBaseRepository` narrows `ExtraOptions` to default to `IDatabaseExtraOptions`, so repository code written against a `PostgresBaseRepository` subclass sees `IDatabaseTransaction` (with `connector`/`isolationLevel`) rather than the bare neutral `ITransaction`.
|
|
453
|
+
|
|
388
454
|
### Isolation Levels
|
|
389
455
|
|
|
390
456
|
Use the `IsolationLevels` static class for type-safe isolation level constants:
|
|
@@ -420,7 +486,12 @@ try {
|
|
|
420
486
|
|
|
421
487
|
await tx.commit();
|
|
422
488
|
} catch (error) {
|
|
423
|
-
|
|
489
|
+
// rollback() throws if ROLLBACK itself fails - nest it so it never replaces the original cause
|
|
490
|
+
try {
|
|
491
|
+
await tx.rollback();
|
|
492
|
+
} catch (rollbackError) {
|
|
493
|
+
logger.error('Rollback failed | %s', rollbackError);
|
|
494
|
+
}
|
|
424
495
|
throw error;
|
|
425
496
|
}
|
|
426
497
|
```
|
|
@@ -432,10 +503,12 @@ This architecture ensures that datasources are configured consistently and that
|
|
|
432
503
|
## See Also
|
|
433
504
|
|
|
434
505
|
- **Related Concepts:**
|
|
506
|
+
- [Connectors](./connectors) - Base-vs-connectors architecture, dual-door exports, aliases
|
|
435
507
|
- [DataSources Guide](/guides/core-concepts/persistent/datasources) - Creating DataSources tutorial
|
|
436
508
|
- [Repositories](/guides/core-concepts/persistent/repositories) - Using DataSources for database access
|
|
437
509
|
- [Models](/guides/core-concepts/persistent/models) - Entity schemas loaded by DataSource
|
|
438
510
|
- [Transactions](/guides/core-concepts/persistent/transactions) - Multi-operation database transactions
|
|
511
|
+
- [Search & Typesense](/guides/core-concepts/persistent/search-typesense) - The typesense connector
|
|
439
512
|
|
|
440
513
|
- **References:**
|
|
441
514
|
- [Repositories API](/references/base/repositories/) - Data access layer
|
|
@@ -6,16 +6,16 @@ difficulty: advanced
|
|
|
6
6
|
|
|
7
7
|
# Deep Dive: Dependency Injection
|
|
8
8
|
|
|
9
|
-
Technical reference for the DI system in
|
|
9
|
+
Technical reference for the DI system in IGNIS - managing resource lifecycles and dependency resolution.
|
|
10
10
|
|
|
11
11
|
**Files:**
|
|
12
|
-
- `packages/inversion/src/container.ts`
|
|
13
|
-
- `packages/inversion/src/registry.ts`
|
|
14
|
-
- `packages/inversion/src/metadata/injectors.ts`
|
|
15
|
-
- `packages/inversion/src/common/types.ts`
|
|
16
|
-
- `packages/core/src/helpers/inversion/container.ts`
|
|
17
|
-
- `packages/core/src/helpers/inversion/registry.ts`
|
|
18
|
-
- `packages/core/src/base/metadata/injectors.ts`
|
|
12
|
+
- `packages/inversion/src/container.ts` - Base `Container` and `Binding` classes
|
|
13
|
+
- `packages/inversion/src/registry.ts` - Base `MetadataRegistry`
|
|
14
|
+
- `packages/inversion/src/metadata/injectors.ts` - Base `@inject` and `@injectable` decorators
|
|
15
|
+
- `packages/inversion/src/common/types.ts` - `BindingScopes`, `BindingValueTypes`, `BindingKeys`, `IProvider`
|
|
16
|
+
- `packages/core/src/helpers/inversion/container.ts` - Extended `Container` with `ApplicationLogger`
|
|
17
|
+
- `packages/core/src/helpers/inversion/registry.ts` - Extended `MetadataRegistry` (singleton, with model/repository/datasource mixins)
|
|
18
|
+
- `packages/core/src/base/metadata/injectors.ts` - Core `@inject` and `@injectable` (wired to extended registry)
|
|
19
19
|
|
|
20
20
|
## Quick Reference
|
|
21
21
|
|
|
@@ -25,7 +25,7 @@ Technical reference for the DI system in Ignis - managing resource lifecycles an
|
|
|
25
25
|
| **Binding** | Single registered dependency configuration | `toClass()`, `toValue()`, `toProvider()`, `setScope()`, `setTags()`, `getValue()`, `clearCache()` |
|
|
26
26
|
| **@inject** | Decorator marking injection points | Applied to constructor parameters and class properties |
|
|
27
27
|
| **@injectable** | Decorator marking a class as injectable | Stores scope and tag metadata |
|
|
28
|
-
| **MetadataRegistry** | Stores decorator metadata | Singleton
|
|
28
|
+
| **MetadataRegistry** | Stores decorator metadata | Singleton - base via `metadataRegistry` export, core via `MetadataRegistry.getInstance()` |
|
|
29
29
|
| **BindingKeys** | Utility for building namespaced keys | `BindingKeys.build({ namespace, key })` |
|
|
30
30
|
| **Boot System** | Automatic artifact discovery and binding | Integrates with Container via tags and bindings |
|
|
31
31
|
|
|
@@ -58,7 +58,7 @@ const container = new Container({ scope: 'MyApp' }); // scope is optional, defau
|
|
|
58
58
|
| :--- | :--- | :--- |
|
|
59
59
|
| **`bind`** | `bind<T>({ key: string \| symbol }): Binding<T>` | Creates and registers a new `Binding` for the given key. Returns the `Binding` for fluent configuration. |
|
|
60
60
|
| **`get`** | `get<T>({ key, isOptional? }): T` | Retrieves a resolved dependency. `key` can be a `string`, `symbol`, or `{ namespace, key }` object. Throws if not found and `isOptional` is `false` (default). Returns `undefined` if `isOptional` is `true` and not found. |
|
|
61
|
-
| **`gets`** | `gets<T>({ bindings }): T[]` | Resolves multiple dependencies at once. Each entry in `bindings` accepts `{ key, isOptional? }`.
|
|
61
|
+
| **`gets`** | `gets<T extends unknown[]>({ bindings }): { [K in keyof T]: T[K] \| undefined }` | Resolves multiple dependencies at once. Each entry in `bindings` accepts `{ key, isOptional? }`. Returns a tuple-preserving array where missing bindings resolve to `undefined`. |
|
|
62
62
|
| **`getBinding`** | `getBinding<T>({ key }): Binding<T> \| undefined` | Returns the raw `Binding` object without resolving it. `key` accepts `string`, `symbol`, or `{ namespace, key }`. |
|
|
63
63
|
| **`set`** | `set<T>({ binding: Binding<T> }): void` | Directly sets a pre-built `Binding` into the container. |
|
|
64
64
|
| **`isBound`** | `isBound({ key: string \| symbol }): boolean` | Checks if a binding exists for the given key. |
|
|
@@ -74,8 +74,8 @@ const container = new Container({ scope: 'MyApp' }); // scope is optional, defau
|
|
|
74
74
|
|
|
75
75
|
When `container.instantiate(MyClass)` is called:
|
|
76
76
|
|
|
77
|
-
1. **Constructor injection**
|
|
78
|
-
2. **Property injection**
|
|
77
|
+
1. **Constructor injection** - Reads `@inject` metadata from the class by parameter index (the `Reflect`-stored array is already index-keyed, so there is no sort step), resolves each dependency from the container, and passes them as constructor arguments. If any index in range has no `@inject` metadata, `instantiate()` throws immediately rather than passing `undefined`.
|
|
78
|
+
2. **Property injection** - After the instance is created, reads property metadata, resolves each dependency, and assigns them directly to the instance properties.
|
|
79
79
|
|
|
80
80
|
```typescript
|
|
81
81
|
// Both constructor and property injection in action
|
|
@@ -90,6 +90,18 @@ class UserController {
|
|
|
90
90
|
}
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
> [!IMPORTANT]
|
|
94
|
+
> **Every constructor parameter of a container-instantiated class must carry `@inject`.** Mixing decorated and undecorated parameters is forbidden - `@inject` stores its metadata at the parameter's index, so an undecorated parameter leaves a hole in that array, and there is no channel through which the container could supply it anyway (it would resolve to `undefined`). `instantiate()` refuses the shape by class name and parameter index instead of silently dereferencing the hole:
|
|
95
|
+
>
|
|
96
|
+
> ```
|
|
97
|
+
> [NoteController] Constructor parameter 0 has no @inject | Every parameter of a container-instantiated
|
|
98
|
+
> class must be decorated - the container cannot supply an undecorated one
|
|
99
|
+
> ```
|
|
100
|
+
>
|
|
101
|
+
> The check lives in `instantiate()`, not in the `@inject` decorator itself: parameter decorators run right-to-left, so when `@inject` on parameter 1 runs, parameter 0 has not been visited yet and nothing at that point can know whether it will end up decorated.
|
|
102
|
+
>
|
|
103
|
+
> This does not apply to `@repository`-decorated classes whose constructor appears undecorated at index 0 - the `@repository` decorator programmatically writes that inject metadata (`registry.setInjectMetadata({ target, index: 0, ... })`) even though no literal `@inject` appears in source. See [Repositories](./repositories/).
|
|
104
|
+
|
|
93
105
|
## `Binding` Class
|
|
94
106
|
|
|
95
107
|
A `Binding` represents a single registered dependency in the container. It provides a fluent API to configure *how* a dependency should be created and managed.
|
|
@@ -114,7 +126,7 @@ When a binding key contains a dot (e.g., `services.MyService`), the namespace po
|
|
|
114
126
|
| **`toValue`** | `toValue(value: T): this` | Binds to a constant value (e.g., a config object, string, number). |
|
|
115
127
|
| **`toProvider`** | `toProvider(value: ((container) => T) \| TClass<IProvider<T>>): this` | Binds to a factory function or a class implementing `IProvider<T>`. |
|
|
116
128
|
| **`setScope`** | `setScope(scope: TBindingScope): this` | Sets the lifecycle scope (`'singleton'` or `'transient'`). |
|
|
117
|
-
| **`setTags`** | `setTags(...tags: string[]): this` | Adds one or more tags to the binding. Tags are additive
|
|
129
|
+
| **`setTags`** | `setTags(...tags: string[]): this` | Adds one or more tags to the binding. Tags are additive - calling this multiple times adds more tags. |
|
|
118
130
|
| **`getValue`** | `getValue(container?: Container): T` | Resolves the binding's value. For `CLASS` and `PROVIDER` types, a `container` argument is required. Respects singleton caching. |
|
|
119
131
|
| **`clearCache`** | `clearCache(): void` | Clears the cached singleton instance (if any). Next `getValue()` call will re-create it. |
|
|
120
132
|
| **`hasTag`** | `hasTag(tag: string): boolean` | Checks if the binding has a specific tag. |
|
|
@@ -192,7 +204,7 @@ This is also used internally by `container.get()` and `container.getBinding()` w
|
|
|
192
204
|
|
|
193
205
|
## `@inject` Decorator
|
|
194
206
|
|
|
195
|
-
The `@inject` decorator marks where dependencies should be injected
|
|
207
|
+
The `@inject` decorator marks where dependencies should be injected - either on constructor parameters or class properties.
|
|
196
208
|
|
|
197
209
|
**File:** `packages/inversion/src/metadata/injectors.ts` (base) & `packages/core/src/base/metadata/injectors.ts` (core wrapper)
|
|
198
210
|
|
|
@@ -204,7 +216,7 @@ The `@inject` decorator marks where dependencies should be injected — either o
|
|
|
204
216
|
|
|
205
217
|
| Parameter | Type | Default | Description |
|
|
206
218
|
| :--- | :--- | :--- | :--- |
|
|
207
|
-
| `key` | `string \| symbol` |
|
|
219
|
+
| `key` | `string \| symbol` | - | The binding key to resolve from the container. |
|
|
208
220
|
| `isOptional` | `boolean` | `false` | If `true`, returns `undefined` instead of throwing when the binding is not found. |
|
|
209
221
|
|
|
210
222
|
### Constructor Parameter Injection
|
|
@@ -262,8 +274,8 @@ Marks a class as injectable and attaches optional metadata.
|
|
|
262
274
|
|
|
263
275
|
| Parameter | Type | Default | Description |
|
|
264
276
|
| :--- | :--- | :--- | :--- |
|
|
265
|
-
| `scope` | `'singleton' \| 'transient'` |
|
|
266
|
-
| `tags` | `Record<string, any>` |
|
|
277
|
+
| `scope` | `'singleton' \| 'transient'` | - | Optional scope hint for the binding. |
|
|
278
|
+
| `tags` | `Record<string, any>` | - | Optional metadata tags. |
|
|
267
279
|
|
|
268
280
|
### Example
|
|
269
281
|
|
|
@@ -272,7 +284,7 @@ Marks a class as injectable and attaches optional metadata.
|
|
|
272
284
|
class UserService extends BaseService {
|
|
273
285
|
constructor(
|
|
274
286
|
@inject({ key: 'repositories.UserRepository' })
|
|
275
|
-
private
|
|
287
|
+
private userRepository: UserRepository,
|
|
276
288
|
) {
|
|
277
289
|
super({ scope: UserService.name });
|
|
278
290
|
}
|
|
@@ -390,16 +402,16 @@ This pattern allows the `Bootstrapper` to automatically discover and execute all
|
|
|
390
402
|
Once artifacts are discovered and loaded, they're bound using consistent namespace patterns:
|
|
391
403
|
|
|
392
404
|
```typescript
|
|
393
|
-
// Controllers
|
|
405
|
+
// Controllers - auto-tagged with 'controllers'
|
|
394
406
|
this.bind({ key: 'controllers.UserController' }).toClass(UserController);
|
|
395
407
|
|
|
396
|
-
// Services
|
|
408
|
+
// Services - auto-tagged with 'services'
|
|
397
409
|
this.bind({ key: 'services.UserService' }).toClass(UserService);
|
|
398
410
|
|
|
399
|
-
// Repositories
|
|
411
|
+
// Repositories - auto-tagged with 'repositories'
|
|
400
412
|
this.bind({ key: 'repositories.UserRepository' }).toClass(UserRepository);
|
|
401
413
|
|
|
402
|
-
// Datasources
|
|
414
|
+
// Datasources - auto-tagged with 'datasources'
|
|
403
415
|
this.bind({ key: 'datasources.PostgresDataSource' }).toClass(PostgresDataSource);
|
|
404
416
|
```
|
|
405
417
|
|