Skip to content

refactor: de-duplicate the stub/monolith structure — one real module per class (#47)#71

Merged
kalwalt merged 10 commits into
devfrom
feat/refactor-jsfeat-next
Jul 9, 2026
Merged

refactor: de-duplicate the stub/monolith structure — one real module per class (#47)#71
kalwalt merged 10 commits into
devfrom
feat/refactor-jsfeat-next

Conversation

@kalwalt

@kalwalt kalwalt commented Jul 8, 2026

Copy link
Copy Markdown
Member

The complete #47 integration: nine reviewed slices (#62#70) plus a one-shot artifact rebuild. Closes #47.

What this delivers

The audit's §4 target architecture for the module layer:

  • src/jsfeatNext.ts: ~3,900 lines → 59 lines — a thin aggregator that only imports modules and attaches them to the public namespace
  • Zero type-only stubs remain — every src/<module>/<module>.ts is now the real implementation (previously most threw "Method not implemented")
  • New src/core/core.ts — the shared base class (constants, cache/data-type helpers, precisely-typed static slots); every module extends it, no circular imports
  • New src/motion_model/motion_model.tsmotion_model/affine2d/homography2d kernels, previously trapped as module-local classes
  • Latent trap healedsrc/orb/rectify_patch.ts now resolves to the real imgproc instead of the throwing stub

Public API: unchanged

All 18 jsfeatNext.<module> attachments identical, instanceof chains and static-constant inheritance preserved, VERSION intact. The only signature change: math.median() now honestly accepts typed arrays (the stub hid this behind any; lmeds always passed a Float32Array).

Included artifact rebuild

Final commit rebuilds dist/ (UMD + ESM) and types/ from the refactored source, per the agreed convention (refactor PRs ship source only; artifacts rebuilt at integration points). types/ now mirrors the new layout (core/, motion_model/).

Verification (every slice + final state)

Review guide

Best reviewed per-slice (all previously reviewed and merged into this branch): #62 core+math · #63 imgproc · #64 fast_corners · #65 pyramid_t · #66 linalg · #67 orb · #68 yape06 · #69 motion_estimator+kernels · #70 optical_flow_lk+aggregator.

🤖 Generated with Claude Code

kalwalt and others added 9 commits July 8, 2026 13:57
Second de-duplication step of #47, following the pattern proven in #62.

- src/imgproc/imgproc.ts: replace the type-only stub with the REAL
  implementation moved verbatim from the monolith (grayscale, resample,
  box_blur_gray, gaussian_blur, hough_transform, pyrdown, scharr/sobel
  derivatives, compute_integral_image, equalize_histogram, canny,
  warp_perspective, warp_affine, skindetector). Only deliberate change:
  gaussian_blur instantiates the math module directly (import from
  ../math/math) instead of via the jsfeatNext.math static slot, removing
  an attach-order dependency on the aggregator.
- src/jsfeatNext.ts: shrinks by ~1050 lines; attaches imgproc from its
  module (jsfeatNext.imgproc = imgproc).
- Side effect: the latent trap in src/orb/rectify_patch.ts (it imports
  imgproc, which until now was the throwing stub) is healed — it resolves
  to the real implementation.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (14 of
those pin imgproc bit-for-bit vs original jsfeat); UMD build checked
(instanceof chain, static-constant inheritance, grayscale + gaussian_blur
smoke on the bundle).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Third de-duplication step of #47, following the #62/#63 pattern.

- src/fast_corners/fast_corners.ts: replace the type-only stub with the
  REAL implementation moved verbatim from the monolith (set_threshold,
  detect, _cmp_offsets; imports _cmp_score_16 from ./fast_private, which
  was already a real module).
- src/jsfeatNext.ts: shrinks by ~225 lines; attaches fast_corners from its
  module.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (detector
parity suite pins fast_corners.detect against original jsfeat); UMD bundle
smoke-checked (instanceof chain, static inheritance, corner detection on a
synthetic image).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fourth de-duplication step of #47, following the established pattern.

- src/pyramid_t/pyramid_t.ts: replace the type-only stub with the REAL
  implementation moved verbatim from the monolith (allocate, build). Only
  deliberate change: the constructor instantiates imgproc via direct module
  import instead of the jsfeatNext.imgproc static slot.
- src/jsfeatNext.ts: shrinks by ~43 lines.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (the
optical_flow_lk parity test exercises pyramid_t against the oracle); UMD
bundle smoke-checked (instanceof, allocate/build on a synthetic image with
correct per-level dimensions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fifth de-duplication step of #47, following the established pattern.

- src/linalg/linalg.ts: replace the type-only stub with the REAL
  implementation moved verbatim from the monolith (JacobiImpl, JacobiSVDImpl,
  lu_solve, cholesky_solve, svd_decompose, svd_solve, svd_invert, eigenVV).
  Imports swap/hypot from ./linalg_base and matmath — both already real
  modules.
- src/jsfeatNext.ts: shrinks by ~740 lines (largest single extraction).

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (6 parity
tests pin linalg: LU, Cholesky, SVD x3, eigenVV vs original jsfeat); UMD
bundle smoke-checked (instanceof, static inheritance, lu_solve on an SPD
system).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sixth de-duplication step of #47, following the established pattern.

- src/orb/orb.ts: replace the type-only stub with the REAL implementation
  moved verbatim from the monolith (describe). Imports bit_pattern_31 and
  rectify_patch from their existing real modules; the constructor now
  instantiates imgproc via direct module import instead of the
  jsfeatNext.imgproc static slot.
- src/jsfeatNext.ts: shrinks by ~107 lines.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (the orb
parity test pins describe() output byte-for-byte vs original jsfeat); UMD
bundle smoke-checked (instanceof, descriptor computation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seventh de-duplication step of #47, following the established pattern.

- src/yape06/yape06.ts: replace the type-only stub with the REAL
  implementation moved verbatim from the monolith (detect + laplacian /
  min-eigen-value thresholds). Imports compute_laplacian and
  hessian_min_eigen_value from ./yape06_utils (already a real module).
- src/jsfeatNext.ts: shrinks by ~85 lines.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (the yape06
parity test pins detect() against original jsfeat); UMD bundle smoke-checked
(instanceof, default thresholds, detection on a synthetic image).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… kernels (#47)

Eighth de-duplication step of #47 — the biggest structural win.

- NEW src/motion_model/motion_model.ts: motion_model + affine2d +
  homography2d kernel classes, moved verbatim from the monolith (they were
  module-local classes there). Kernels instantiate linalg via direct module
  import instead of the jsfeatNext.linalg static slot.
- src/motion_estimator/motion_estimator.ts: replace the type-only stub with
  the REAL implementation (get_subset, find_inliers, ransac, lmeds); lmeds
  instantiates math via direct module import.
- src/core/core.ts: the temporary any-typed affine2d/homography2d static
  slots (a known TODO since #62) now have precise typeof types via type-only
  imports.
- src/jsfeatNext.ts: down to ~380 lines — pure aggregator except for
  optical_flow_lk, the last inline module.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (3 parity
tests pin ransac/lmeds with identical models AND inlier masks vs original
jsfeat on seeded data); UMD bundle smoke-checked (instanceof for estimator
and both kernels, affine RANSAC recovers the synthetic model).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s is now a thin aggregator (#47)

Ninth and FINAL de-duplication step of #47.

- src/optical_flow_lk/optical_flow_lk.ts: replace the type-only stub with
  the REAL implementation moved verbatim from the monolith (track). The
  constructor instantiates imgproc via direct module import instead of the
  jsfeatNext.imgproc static slot.
- src/jsfeatNext.ts: now a 59-line THIN AGGREGATOR - it only imports the
  modules and attaches them to the public namespace. Unused helper imports
  (resample/convol kernels, linalg_base, fast_private, orb/yape06 utils,
  point_t, JSFEAT_CONSTANTS) pruned; they are consumed by the modules
  themselves now.

This completes the stub/monolith de-duplication: every algorithm lives in
its own real module under src/<module>/, extending the shared base from
src/core/core.ts. No type-only stubs remain; the audit's section-4 target
architecture (thin aggregator) is reached for the module layer.

Verified behavior-preserving: tsc --noEmit clean; npm test 57/57 (the
optical_flow_lk parity test pins track() vs original jsfeat across pyramid
levels); UMD bundle checked - all 18 public modules attach and instanceof
chains hold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-shot artifact rebuild for the integration of the stub/monolith
de-duplication (#62-#70) into dev, per the agreed convention (refactor PRs
ship source only; artifacts are rebuilt at integration/release points).

- dist/jsfeatNext.js (UMD) + dist/jsfeatNext.mjs (ESM) rebuilt from the
  refactored source
- types/ regenerated: now mirrors the new module layout, including
  types/src/core/core.d.ts and types/src/motion_model/motion_model.d.ts

Verified: npm test 57/57; all 18 public modules attach on the fresh UMD
bundle; VERSION 0.7.6 intact; no .d.ts files leak into dist/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kalwalt kalwalt added this to the Parity & Modernization milestone Jul 8, 2026
@kalwalt kalwalt self-assigned this Jul 8, 2026
@kalwalt kalwalt added enhancement New feature or request Typescript all about Typescript code design javascript tests labels Jul 8, 2026
Comprehensive documentation pass over all 34 source files: every class,
interface, method, property and standalone function now carries a TSDoc
block (summaries, @param/@returns, plus parity notes vs original jsfeat,
e.g. the fixed hough_transform, the transform calling-convention
difference and the per-instance cache).

Tooling:
- tsconfig: removeComments false, so the docs propagate into the
  generated .d.ts and consumers get hover documentation in their IDE
- typedoc devDependency + 'npm run docs' script + typedoc.json
  (all modules, HTML output to docs/api — gitignored, generated on demand;
  publishing/hosting is an org-wide decision tracked separately)
- dist/ + types/ rebuilt (JS behavior unchanged; declarations carry docs)

Verified: typedoc generates with zero warnings (86 pages); tsc --noEmit
clean; npm test 57/57; prettier clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kalwalt

kalwalt commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

📝 Documentation pass added (commit 9563db2): full TSDoc coverage across all 34 src/ files — every class, interface, method and property now documented, including parity notes vs original jsfeat (fixed hough_transform, transform calling convention, per-instance cache).

Tooling that came with it:

  • npm run docs → TypeDoc HTML site in docs/api/ (gitignored; zero warnings, 86 pages)
  • tsconfig now keeps comments, so the generated types/*.d.ts carry the docs — consumers get hover documentation in their IDE

Further doc improvements will land in a separate PR; hosting the generated API docs is an org-wide decision tracked in webarkit/webarkit.github.io#49.

@kalwalt kalwalt merged commit 36e2591 into dev Jul 9, 2026
4 checks passed
@kalwalt kalwalt deleted the feat/refactor-jsfeat-next branch July 10, 2026 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code design documentation Improvements or additions to documentation enhancement New feature or request javascript tests Typescript all about Typescript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant