@venizia/ignis-docs 0.0.1-7 → 0.0.1-9

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 (27) hide show
  1. package/package.json +12 -12
  2. package/wiki/changelogs/2025-12-17-refactor.md +22 -0
  3. package/wiki/changelogs/2025-12-18-performance-optimizations.md +192 -0
  4. package/wiki/changelogs/2025-12-18-repository-validation-security.md +445 -0
  5. package/wiki/changelogs/index.md +22 -0
  6. package/wiki/changelogs/v0.0.1-7-initial-architecture.md +137 -0
  7. package/wiki/changelogs/v0.0.1-8-model-repo-datasource-refactor.md +278 -0
  8. package/wiki/get-started/5-minute-quickstart.md +1 -1
  9. package/wiki/get-started/best-practices/api-usage-examples.md +12 -8
  10. package/wiki/get-started/best-practices/common-pitfalls.md +2 -2
  11. package/wiki/get-started/best-practices/data-modeling.md +14 -20
  12. package/wiki/get-started/building-a-crud-api.md +60 -75
  13. package/wiki/get-started/core-concepts/controllers.md +14 -14
  14. package/wiki/get-started/core-concepts/persistent.md +110 -130
  15. package/wiki/get-started/quickstart.md +1 -1
  16. package/wiki/references/base/controllers.md +40 -16
  17. package/wiki/references/base/datasources.md +195 -33
  18. package/wiki/references/base/dependency-injection.md +5 -5
  19. package/wiki/references/base/models.md +398 -28
  20. package/wiki/references/base/repositories.md +475 -22
  21. package/wiki/references/components/authentication.md +224 -7
  22. package/wiki/references/components/health-check.md +1 -1
  23. package/wiki/references/components/swagger.md +1 -1
  24. package/wiki/references/helpers/inversion.md +8 -3
  25. package/wiki/references/src-details/core.md +6 -5
  26. package/wiki/references/src-details/inversion.md +4 -4
  27. package/wiki/references/utilities/request.md +16 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venizia/ignis-docs",
3
- "version": "0.0.1-7",
3
+ "version": "0.0.1-9",
4
4
  "description": "Documentation and MCP Server for Ignis Framework",
5
5
  "keywords": [
6
6
  "ignis",
@@ -27,28 +27,28 @@
27
27
  "framework",
28
28
  "venizia"
29
29
  ],
30
- "main": "./mcp-server/dist/index.js",
31
- "types": "./mcp-server/dist/index.d.ts",
30
+ "main": "./dist/mcp-server/index.js",
31
+ "types": "./dist/mcp-server/index.d.ts",
32
32
  "exports": {
33
33
  ".": {
34
- "types": "./mcp-server/dist/index.d.ts",
35
- "default": "./mcp-server/dist/index.js"
34
+ "types": "./dist/mcp-server/index.d.ts",
35
+ "default": "./dist/mcp-server/index.js"
36
36
  },
37
37
  "./tools": {
38
- "types": "./mcp-server/dist/tools/index.d.ts",
39
- "default": "./mcp-server/dist/tools/index.js"
38
+ "types": "./dist/mcp-server/tools/index.d.ts",
39
+ "default": "./dist/mcp-server/tools/index.js"
40
40
  },
41
41
  "./helpers": {
42
- "types": "./mcp-server/dist/helpers/index.d.ts",
43
- "default": "./mcp-server/dist/helpers/index.js"
42
+ "types": "./dist/mcp-server/helpers/index.d.ts",
43
+ "default": "./dist/mcp-server/helpers/index.js"
44
44
  },
45
45
  "./common": {
46
- "types": "./mcp-server/dist/common/index.d.ts",
47
- "default": "./mcp-server/dist/common/index.js"
46
+ "types": "./dist/mcp-server/common/index.d.ts",
47
+ "default": "./dist/mcp-server/common/index.js"
48
48
  }
49
49
  },
50
50
  "bin": {
51
- "ignis-docs-mcp": "./mcp-server/dist/index.js"
51
+ "ignis-docs-mcp": "./dist/mcp-server/index.js"
52
52
  },
53
53
  "files": [
54
54
  "README.md",
@@ -0,0 +1,22 @@
1
+ # Changelog - 2025-12-17
2
+
3
+ ## Major Refactor: Inversion of Control
4
+
5
+ The Dependency Injection (DI) system has been extracted from `packages/helpers` into a standalone package `@venizia/ignis-inversion`.
6
+
7
+ ### Changes
8
+
9
+ - **New Package**: `@venizia/ignis-inversion` created.
10
+ - **Removed**: `packages/helpers/src/helpers/inversion` deleted.
11
+ - **Updated**: `packages/core` now imports DI primitives from `@venizia/ignis-inversion`.
12
+ - **Refactored**: `packages/core/src/helpers/inversion` now re-exports from the new package and adds core-specific extensions.
13
+
14
+ ### Impact
15
+
16
+ - **Imports**: Imports from `@venizia/ignis` or `@venizia/ignis-helpers` relating to `Binding`, `Container`, `inject` should generally remain compatible via re-exports, but deep imports to `helpers/inversion` will break.
17
+ - **Structure**: Clearer separation of concerns. `inversion` package has zero dependencies on the rest of the framework (except `lodash`, `reflect-metadata`, `zod`).
18
+
19
+ ## Other Changes
20
+
21
+ - **Mixins**: `server-config.mixin.ts` removed from `packages/core`.
22
+ - **Examples**: `examples/vert` updated to reflect latest core changes.
@@ -0,0 +1,192 @@
1
+ # Changelog - 2025-12-18
2
+
3
+ ## Performance Optimizations
4
+
5
+ This update focuses on performance improvements for the repository layer, reducing GC pressure and improving query execution speed.
6
+
7
+ ## Overview
8
+
9
+ - **WeakMap Cache**: `DrizzleFilterBuilder` now caches `getTableColumns()` results
10
+ - **Core API for Flat Queries**: `ReadableRepository` uses faster Drizzle Core API when possible
11
+ - **Static schemaFactory Singleton**: `BaseEntity` shares a single `schemaFactory` instance across all entities
12
+ - **Async/Await Refactor**: Removed redundant Promise wrappers from repository methods
13
+
14
+ ## Performance Improvements
15
+
16
+ ### 1. WeakMap Cache for Filter Builder
17
+
18
+ **File:** `packages/core/src/base/repositories/operators/filter.ts`
19
+
20
+ **Problem:** `getTableColumns()` was called on every filter operation, causing repeated reflection overhead.
21
+
22
+ **Solution:** Added static WeakMap cache that stores column metadata per schema:
23
+
24
+ ```typescript
25
+ export class DrizzleFilterBuilder extends BaseHelper {
26
+ // Static cache shared across all instances
27
+ private static columnCache = new WeakMap<
28
+ TTableSchemaWithId,
29
+ ReturnType<typeof getTableColumns>
30
+ >();
31
+
32
+ private getColumns<Schema extends TTableSchemaWithId>(schema: Schema) {
33
+ let columns = DrizzleFilterBuilder.columnCache.get(schema);
34
+ if (!columns) {
35
+ columns = getTableColumns(schema);
36
+ DrizzleFilterBuilder.columnCache.set(schema, columns);
37
+ }
38
+ return columns;
39
+ }
40
+ }
41
+ ```
42
+
43
+ **Benefits:**
44
+ - First call: `getTableColumns(schema)` → cached
45
+ - Subsequent calls: Retrieved from WeakMap (O(1) lookup)
46
+ - WeakMap allows garbage collection when schema is no longer referenced
47
+ - Especially beneficial for:
48
+ - High-concurrency environments
49
+ - Queries with nested AND/OR conditions (each recursion reuses cache)
50
+ - Multiple queries to the same table
51
+
52
+ ### 2. Core API for Flat Queries (~15-20% Faster)
53
+
54
+ **File:** `packages/core/src/base/repositories/core/readable.ts`
55
+
56
+ **Problem:** All queries used Drizzle's Query API, which has overhead for relational mapping even when not needed.
57
+
58
+ **Solution:** Automatically use Drizzle Core API for flat queries (no relations, no field selection):
59
+
60
+ ```typescript
61
+ // Automatic optimization - no code changes needed
62
+ const users = await repo.find({
63
+ filter: {
64
+ where: { status: 'active' },
65
+ limit: 10,
66
+ order: ['createdAt DESC'],
67
+ }
68
+ });
69
+ // Uses: db.select().from(table).where(...).orderBy(...).limit(10)
70
+ ```
71
+
72
+ **When Core API is used:**
73
+
74
+ | Filter Options | API Used | Reason |
75
+ |----------------|----------|--------|
76
+ | `where`, `limit`, `order`, `offset` only | Core API | Flat query, no overhead |
77
+ | Has `include` (relations) | Query API | Needs relational mapper |
78
+ | Has `fields` selection | Query API | Core API field syntax differs |
79
+
80
+ **New Protected Methods:**
81
+
82
+ ```typescript
83
+ // Check if Core API can be used
84
+ protected canUseCoreAPI(filter: TFilter<DataObject>): boolean;
85
+
86
+ // Execute flat query using Core API
87
+ protected async findWithCoreAPI(opts: {
88
+ filter: TFilter<DataObject>;
89
+ findOne?: boolean;
90
+ }): Promise<Array<DataObject>>;
91
+ ```
92
+
93
+ ### 3. Static schemaFactory Singleton
94
+
95
+ **File:** `packages/core/src/base/models/base.ts`
96
+
97
+ **Problem:** New `schemaFactory` was created for every `BaseEntity` instance:
98
+
99
+ ```typescript
100
+ // Before - created on every instantiation
101
+ constructor(opts?: { name?: string; schema?: Schema }) {
102
+ this.schemaFactory = createSchemaFactory(); // Memory overhead!
103
+ }
104
+ ```
105
+
106
+ **Solution:** Lazy singleton pattern shared across all instances:
107
+
108
+ ```typescript
109
+ // After - shared singleton
110
+ private static _schemaFactory?: ReturnType<typeof createSchemaFactory>;
111
+ protected static get schemaFactory(): ReturnType<typeof createSchemaFactory> {
112
+ return (BaseEntity._schemaFactory ??= createSchemaFactory());
113
+ }
114
+ ```
115
+
116
+ **Benefits:**
117
+ - Single instance for all entities
118
+ - Lazy initialization (created on first use)
119
+ - Reduced memory footprint
120
+
121
+ ### 4. Async/Await Refactor
122
+
123
+ **Files:**
124
+ - `packages/core/src/base/repositories/core/readable.ts`
125
+ - `packages/core/src/base/repositories/core/persistable.ts`
126
+
127
+ **Problem:** Every CRUD method wrapped existing promises in `new Promise()`:
128
+
129
+ ```typescript
130
+ // Before - Anti-pattern
131
+ return new Promise((resolve, reject) => {
132
+ this.connector.$count(this.entity.schema, where)
133
+ .then((count: number) => resolve({ count }))
134
+ .catch(reject);
135
+ });
136
+ ```
137
+
138
+ **Solution:** Direct async/await:
139
+
140
+ ```typescript
141
+ // After - Clean and efficient
142
+ const count = await this.connector.$count(this.entity.schema, where);
143
+ return { count };
144
+ ```
145
+
146
+ **Benefits:**
147
+ - Eliminates extra microtask queue entries
148
+ - Reduces ~200-400 bytes memory per Promise on V8
149
+ - Cleaner stack traces for debugging
150
+ - For bulk operations, overhead reduction multiplies
151
+
152
+ ## Implementation Details
153
+
154
+ ### Type Safety in Core API
155
+
156
+ The Core API implementation uses a controlled type assertion at the boundary:
157
+
158
+ ```typescript
159
+ // Type assertion to PgTable is safe: EntitySchema extends TTableSchemaWithId which extends PgTable
160
+ const table = schema as unknown as PgTable;
161
+ let query = this.connector.select().from(table).$dynamic();
162
+ ```
163
+
164
+ This approach:
165
+ - Maintains type safety within the method
166
+ - Uses `$dynamic()` for query building with proper types
167
+ - Returns correctly typed `Promise<Array<DataObject>>`
168
+
169
+ ## Files Changed
170
+
171
+ ### Core Package - Repositories
172
+ - `packages/core/src/base/repositories/operators/filter.ts` - WeakMap cache for `getTableColumns()`
173
+ - `packages/core/src/base/repositories/core/readable.ts` - Core API optimization, async/await refactor
174
+ - `packages/core/src/base/repositories/core/persistable.ts` - Async/await refactor
175
+
176
+ ### Core Package - Models
177
+ - `packages/core/src/base/models/base.ts` - Static schemaFactory singleton
178
+
179
+ ## Benchmarks
180
+
181
+ These optimizations target the following scenarios:
182
+
183
+ | Scenario | Improvement |
184
+ |----------|-------------|
185
+ | Simple `find()` queries | ~15-20% faster (Core API) |
186
+ | Repeated filter builds | Eliminates reflection overhead (WeakMap) |
187
+ | Entity instantiation | Reduced memory per instance (schemaFactory) |
188
+ | All CRUD operations | Reduced GC pressure (async/await) |
189
+
190
+ ## No Breaking Changes
191
+
192
+ All changes are internal optimizations. No API changes or migration required.