Feature/v3#37
Merged
Merged
Conversation
Feature/v3 error migration
- Make Model<T> generic so _parseConditions returns FilterQuery<T>
without casts at each call site in MongooseConnector
- _parsePopulate converts plain strings to { path } objects to
satisfy Mongoose's populate() overload signatures cleanly
- Remove _methods dynamic dispatch; call countDocuments /
estimatedDocumentCount directly
- UpdateSet / UpdateOperators use unknown instead of any
- Controller and Hiroki body params typed as Record<string, unknown>
- Hiroki.process returns ProcessResponse; dead models field removed
- ErrorFactory facade and tests deleted
Covers the three Fase 1 test tasks from the roadmap. Also adds Hiroki importModels/setConfig coverage. Statement coverage 92.4% → 95.5%, branch 65.7% → 72.1%.
- Add HttpErrorResponse interface; toJSON() now returns it explicitly
- validateModel and validateDocumentExist<T> converted to assertion
functions (asserts) so TypeScript narrows types at call sites
- validatePutParams, validateIdRequired, validateConditionsString,
validateBody return void — return value was never used
- _parseConditions uses validateConditions return value, removing
duplicate JSON.parse logic
- updateByConditions parses conditions once upfront instead of twice
- delete() drops redundant validateDocumentExist (findById asserts it)
- Fallback error in hiroki.process uses
Static-only class is a namespace antipattern in TS — named exports
are treeshakeable, easier to import selectively, and remove the
indirection of call sites.
- Remove dead and (unused
in production, latter also had a typo in the name)
- Update all callers to named imports
- Update tests to match
- Add HirokiAdapter interface with canHandle, CRUD, and query methods - Add AdapterRegistry for pluggable adapter resolution - Extract MongooseAdapter from MongooseConnector (absorbs Model class) - Simplify model.ts to pure types — no class, no mongoose deps - Controller now depends on HirokiAdapter, defaults to MongooseAdapter - Remove mongoose-connector.ts Enables future adapters (SQL, Prisma, etc.) without touching core.
- tsup replaces tsc for build; mongoose and pluralize marked external
- exports field routes require → .cjs, import → .js
- CJS footer makes require('hiroki') return the singleton directly
- duck-type isMongooseModel to survive npm link / multiple mongoose copies
- InvalidModelError now shows modelName, not full function source
- smoke-test verifies both ESM and CJS paths
- New HirokiQuery AST: where/limit/offset/sort/select
- parseHirokiQuery maps URL params to typed filters —
where[field][$op]=val, sort=-field,other, select=a,b
- MongooseAdapter maps HirokiFilter[] to FilterQuery via
_mapQuery/_mapFilter/_mapSort; drops raw QueryParams
- HirokiAdapter interface updated to use HirokiQuery
- Legacy conditions= and conditions[field]= preserved as
escape hatch for raw DB filters
BREAKING CHANGE: limit/skip now parsed as numbers (not
strings); skip maps to offset; sort/select are arrays.
Consumers reading ExtendedQueryParams directly must update.
- Six hooks on ControllerConfig: beforeCreate/afterCreate,
beforeUpdate/afterUpdate, beforeDelete/afterDelete
- before-hooks receive body and can return a mutated copy;
after-hooks observe the persisted doc
- HirokiMiddleware[] chains via reduceRight (onion model);
throw to deny, return without next() to short-circuit
- HookContext carries modelName for all hook callbacks
- All hook/middleware types exported from package
- MemoryAdapter: zero-dep in-memory store implementing HirokiAdapter;
supports all HirokiQuery ops (where/sort/limit/offset/select),
legacy conditions, and clear() for test isolation
- ControllerConfig.adapter injects any HirokiAdapter directly,
bypassing MongooseAdapter and Mongoose model validation
- Controller resolution order: config.adapter →
adapterRegistry.resolve → MongooseAdapter fallback
- Enables Hiroki usage without Mongoose for testing/prototyping
…apters
- Controller logs operation type, id/keys at debug; create/update/delete
at info — gives visibility into request flow without sensitive data
- MongooseAdapter and MemoryAdapter log filter, options, and result
count at debug level on every query
- HirokiAdapter gains optional setLogger() so injected adapters
inherit the controller's logger automatically
- Adapters accept logger in constructor and via setLogger
allowedFields in ControllerConfig filters create/update body before hooks run — prevents mass-assignment attacks. parseHirokiQuery drops __proto__, constructor, prototype from where[] and conditions[] params — prevents prototype pollution. - fix: merge split afterAll hooks in setup.ts (topology error) - fix: silence dangling find() promise in controller isolation test - test: 40-case query parser suite, 6-case security suite
Covers importModel/importModels/process/setConfig, every ControllerConfig field, HirokiAdapter contract, parseHirokiQuery param reference, QueryLimits, and MemoryAdapter. Also adds query limit tests (8 cases) and exports QueryLimits type.
Completed sections collapsed (Fases 1–5, Observabilidad, Seguridad,
Testing, Build). Scattered [ ] items consolidated into:
- Fase 6: internal debt (types, naming, dedup)
- Fase 7: docs (getting started, examples, auth/rate-limit patterns)
- Fase 8: monorepo + sub-packages (hiroki-drizzle, hiroki-sequelize,
external loggers)
- Extract HttpMethod/ProcessParams/Request*/ParsedQuery to src/types.ts
- Simplify ResolvedControllerConfig: replace Required<Omit<>>& Pick<>
with explicit type literal
- Drop underscore prefix from private/protected members
(_disabledMethods, _filterBody, _getQueryParams)
- Remove FilterQuery<any> from validator.ts — ValidConditions now uses
Record<string,unknown>, eliminating mongoose dep from validator
Replace MkDocs (Python) with VitePress (Node.js) to eliminate external toolchain dependency. Docs source stays in mkdocs/, build outputs to docs/ for GitHub Pages compatibility. - mkdocs/.vitepress/config.ts: full nav/sidebar config, outDir ../docs - 13 new pages: guide (5), API reference (4), adapters (4) - package.json: add docs:dev / docs:build / docs:preview scripts - .gitignore: add mkdocs/.vitepress/cache - srcExclude legacy mkdocs/docs and mkdocs/v0.2.9 from VitePress build
Default was true (no pluralization) but the name implies disabled=false should be the default. Routes now pluralize by default; set disabledPluralize: true to opt out. - Default changed from true → false - Condition flipped: disabledPluralize ? baseName : pluralize(baseName) - JSDoc, guide/configuration.md, api/controller-config.md updated - Tests updated: two cases now cover default pluralize + explicit disable
Node 20/22 matrix, no MongoDB service needed (tests use MemoryAdapter). Removes legacy mongo container dependency from CI config.
Restructures the repo into a monorepo under packages/ to allow publishing adapter and logger integrations independently without bloating the core hiroki package. - packages/hiroki — core (all existing source, git mv) - packages/hiroki-drizzle — DrizzleAdapter skeleton, peer: drizzle-orm - packages/hiroki-sequelize — SequelizeAdapter skeleton, peer: sequelize - packages/hiroki-pino — PinoLogger implements HirokiLogger - packages/hiroki-winston — WinstonLogger implements HirokiLogger Exports HirokiLogger, ValidConditions, LogLevel, LoggerConfig from core index so ecosystem packages can import types from a single entry point. 316 tests across all packages (270 hiroki + 46 new). Docs updated: drizzle, sequelize, loggers pages added to VitePress.
drizzle/sequelize bumped to 0.1.0-beta.0 so npm install won't pull them by default — only via explicit @beta tag. Each package README covers install, usage, and links to full docs. Beta READMEs include implementation status checklist.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: Hiroki v3 — adapter system, monorepo, full ecosystem
Summary
Complete rewrite of hiroki from a Mongoose-coupled wrapper into a
database-agnostic CRUD engine with a pluggable adapter system,
published as an npm monorepo.
Phases completed
Phase 1–3 — Core modernization
anyin public surfaceHirokiAdapterinterface — decouples routing from data layerMongooseAdapterextracted from coreHirokiQueryAST — database-agnostic query representationparseHirokiQuery— parseswhere,sort,select,limit,offsetfrom URL query paramsHirokiFilteroperators:eq/ne/gt/gte/lt/lte/in/nin/regexPhase 4 — Hooks & middleware
beforeCreate,afterCreate,beforeUpdate,afterUpdate,beforeDelete,afterDeletewithout touching core
Phase 5 — New adapters
MemoryAdapter— zero deps, full operator support,clear()fortest resets
adapteroption onimportModel— inject any adapter directlyPhase 6 — Debt cleanup
ResolvedControllerConfigtypesrc/types.tsFilterQuery<any>dependency on mongoose in validatorPhase 7 — Documentation
adapters, API reference, changelog
Phase 8 — CI/CD
Phase 9 — Monorepo
packages/hiroki— core package (git mv, no history loss)hiroki-drizzle— DrizzleAdapter skeleton (beta, peer: drizzle-orm)hiroki-sequelize— SequelizeAdapter skeleton (beta, peer: sequelize)hiroki-pino— PinoLogger implements HirokiLoggerhiroki-winston— WinstonLogger implements HirokiLoggerSecurity
allowedFields)__proto__,constructor,prototypemaxFilters,maxInValues,maxRegexLengthBreaking changes
mongoose-connector.tsremoved — useMongooseAdapterdirectlymodel.tsno longer exports a class — types onlyTest plan
npm test— 316 tests, all greennpm run build— all 5 packages build clean (ESM + CJS + DTS)npm run docs:build— VitePress builds without errors