fix(build): update build and test tooling configuration, migrate project config to .smartconfig.json, and align TypeScript typings
This commit is contained in:
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
env:
|
||||
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@code.foss.global/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
env:
|
||||
IMAGE: code.foss.global/host.today/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@/${{gitea.repository}}.git
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@code.foss.global/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -16,4 +16,12 @@ node_modules/
|
||||
dist/
|
||||
dist_*/
|
||||
|
||||
#------# custom
|
||||
# rust
|
||||
rust/target/
|
||||
dist_rust/
|
||||
|
||||
# AI
|
||||
.claude/
|
||||
.serena/
|
||||
|
||||
#------# custom
|
||||
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["/npmextra.json"],
|
||||
"fileMatch": ["/.smartconfig.json"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -22,6 +22,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"deno.enable": false
|
||||
]
|
||||
}
|
||||
|
||||
111
changelog.md
111
changelog.md
@@ -1,6 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-03-24 - 7.1.1 - fix(build)
|
||||
update build and test tooling configuration, migrate project config to .smartconfig.json, and align TypeScript typings
|
||||
|
||||
- Switch the build script to tsbuild tsfolders and upgrade core build/test dependencies including @git.zone/tsbuild, @git.zone/tstest, and @git.zone/tsrun.
|
||||
- Replace npmextra.json with .smartconfig.json and update package packaging to include the new config file.
|
||||
- Update test files to import tapbundle from @git.zone/tstest/tapbundle and remove the standalone @push.rocks/tapbundle dependency.
|
||||
- Adjust TypeScript configuration and source typings for stricter compatibility, including node types and definite assignment/nullability fixes.
|
||||
- Fix Gitea workflow repository URLs for code.foss.global and expand .gitignore for generated Rust and local tooling directories.
|
||||
|
||||
## 2026-02-26 - 7.1.0 - feat(config)
|
||||
|
||||
normalize npmextra.json to namespaced keys and add CI/release configuration
|
||||
|
||||
- Replaced legacy keys (npmdocker, npmci, gitzone, tsdoc) with namespaced package keys (@git.zone/cli, @git.zone/tsdoc, @git.zone/tsdocker, @ship.zone/szci).
|
||||
@@ -10,6 +20,7 @@ normalize npmextra.json to namespaced keys and add CI/release configuration
|
||||
- Removed old top-level entries to consolidate tooling configuration under scoped keys.
|
||||
|
||||
## 2026-02-26 - 7.0.16 - fix(mongodb)
|
||||
|
||||
set default socketTimeoutMS to 30000ms in MongoClient options to prevent hung operations from holding connections
|
||||
|
||||
- Adds socketTimeoutMS: 30000 to MongoClient clientOptions in ts/classes.db.ts
|
||||
@@ -17,20 +28,23 @@ set default socketTimeoutMS to 30000ms in MongoClient options to prevent hung op
|
||||
- Non-breaking change (defaults only)
|
||||
|
||||
## 2025-12-01 - 7.0.15 - fix(classes.doc)
|
||||
|
||||
Avoid emitting instance fields for collection and manager to preserve decorator-defined prototype getters
|
||||
|
||||
- ts/classes.doc.ts: changed instance properties `collection` and `manager` to `declare` so TypeScript does not emit them as own properties — prevents ES2022 class fields from shadowing prototype getters created by @Collection and @managed decorators.
|
||||
- readme.hints.md: added documentation explaining the ES2022 class fields issue and recommending use of `declare` for type-only instance properties; marks the fix as v7.0.15.
|
||||
|
||||
## 2025-11-28 - 7.0.14 - fix(classes.collection)
|
||||
|
||||
Centralize TC39 decorator metadata initialization and use context.metadata in class decorators
|
||||
|
||||
- Add initializeDecoratorMetadata helper to initialize prototype and constructor properties from TC39 decorator metadata
|
||||
- Refactor Collection and managed decorators to call initializeDecoratorMetadata with context.metadata
|
||||
- Remove direct reliance on constructor[Symbol.metadata] in class decorators to avoid read-only assignment issues
|
||||
- Ensure consistent initialization of saveableProperties, globalSaveableProperties, uniqueIndexes, regularIndexes, searchableFields and _svDbOptions
|
||||
- Ensure consistent initialization of saveableProperties, globalSaveableProperties, uniqueIndexes, regularIndexes, searchableFields and \_svDbOptions
|
||||
|
||||
## 2025-11-28 - 7.0.13 - fix(classes.doc)
|
||||
|
||||
Remove noisy debug logging from decorators and serialization logic
|
||||
|
||||
- Removed debug logger calls from globalSvDb decorator initialization
|
||||
@@ -39,20 +53,23 @@ Remove noisy debug logging from decorators and serialization logic
|
||||
- Removed debug logging in createSavableObject to reduce console noise; no functional changes
|
||||
|
||||
## 2025-11-28 - 7.0.12 - fix(collection)
|
||||
|
||||
Ensure TC39 decorator metadata is initialized on both original and decorated constructors/prototypes and add debug logging
|
||||
|
||||
- Initialize metadata-driven prototype properties (globalSaveableProperties, saveableProperties, uniqueIndexes, regularIndexes) on both the decorated class prototype and the original constructor prototype to avoid closure/compatibility issues
|
||||
- Initialize searchableFields on both the decorated constructor and the original constructor so text-index creation and searches see the fields correctly
|
||||
- Forward and initialize _svDbOptions from decorator metadata onto the original constructor to preserve custom serialization options
|
||||
- Forward and initialize \_svDbOptions from decorator metadata onto the original constructor to preserve custom serialization options
|
||||
- Add debug logging in the Collection decorator and in createSavableObject to surface metadata and saveable-property counts for easier troubleshooting
|
||||
|
||||
## 2025-11-28 - 7.0.9 - fix(classes.collection)
|
||||
|
||||
Fix closure bug in Collection decorator by defining collection getter on original constructor and prototype
|
||||
|
||||
- Define the collection getter on the original constructor so class-level references (e.g. `User.collection`) resolve to the decorated collection instead of the original constructor's closure value.
|
||||
- Also define the getter on the original constructor's prototype to ensure instance access works consistently across runtimes (Deno/Node).
|
||||
|
||||
## 2025-11-28 - 7.0.8 - fix(classes.collection)
|
||||
|
||||
Fix closure issue in managed decorator so Class.collection/instance.collection resolve correctly
|
||||
|
||||
- Resolve closure bug in the managed() decorator where class methods referencing Class.collection (or instance.collection) could receive the original constructor's captured value and thus the wrong collection/manager.
|
||||
@@ -60,6 +77,7 @@ Fix closure issue in managed decorator so Class.collection/instance.collection r
|
||||
- Getters are defined as non-enumerable and configurable to preserve compatibility with existing consumers.
|
||||
|
||||
## 2025-11-28 - 7.0.7 - fix(decorators)
|
||||
|
||||
Fix decorator metadata initialization and Lucene query transformation
|
||||
|
||||
- Ensure TC39 decorator metadata is used to initialize prototype properties so decorators work reliably across runtimes (context.metadata / Symbol.metadata shim imported early).
|
||||
@@ -68,12 +86,14 @@ Fix decorator metadata initialization and Lucene query transformation
|
||||
- Improve collection initialization to auto-create compound text indexes from searchableFields and ensure index creation is idempotent.
|
||||
|
||||
## 2025-11-28 - 7.0.6 - fix(classes.collection)
|
||||
|
||||
Guard against missing collection before attaching document constructor in Collection decorator
|
||||
|
||||
- Added a truthy check for `coll` before setting `(coll as any).docCtor` in the Collection decorator (ts/classes.collection.ts).
|
||||
- Prevents a potential TypeError when `collectionFactory.getCollection` returns null/undefined during decorator initialization.
|
||||
|
||||
## 2025-11-28 - 7.0.5 - fix(package)
|
||||
|
||||
Add package exports entry and remove legacy main/typings fields
|
||||
|
||||
- Added an "exports" entry in package.json mapping "." to ./dist_ts/index.js to declare the package's ESM entrypoint.
|
||||
@@ -81,6 +101,7 @@ Add package exports entry and remove legacy main/typings fields
|
||||
- Improves Node/module resolution and modern bundler compatibility by using the package exports field.
|
||||
|
||||
## 2025-11-28 - 7.0.4 - fix(decorators)
|
||||
|
||||
Add Symbol.metadata polyfill and import it at entry to ensure decorator metadata is available
|
||||
|
||||
- Add ts/shim.ts: defines Symbol.metadata when missing (polyfill for TC39 Stage 3 decorator metadata).
|
||||
@@ -88,11 +109,13 @@ Add Symbol.metadata polyfill and import it at entry to ensure decorator metadata
|
||||
- Prevents runtime errors when decorators rely on Symbol.metadata and improves compatibility across runtimes/environments.
|
||||
|
||||
## 2025-11-28 - 7.0.3 - fix(build)
|
||||
|
||||
Bump devDependency @git.zone/tsbuild to ^3.1.2
|
||||
|
||||
- Updated @git.zone/tsbuild in devDependencies from ^3.1.1 to ^3.1.2
|
||||
|
||||
## 2025-11-28 - 7.0.2 - fix(collectionfactory)
|
||||
|
||||
Simplify CollectionFactory.getCollection: remove unnecessary IIFE and instantiate collection only when dbArg is SmartdataDb
|
||||
|
||||
- Remove redundant IIFE wrapper in getCollection for improved readability
|
||||
@@ -100,18 +123,21 @@ Simplify CollectionFactory.getCollection: remove unnecessary IIFE and instantiat
|
||||
- Avoid assigning undefined to the collections map by guarding instantiation and returning existing collection
|
||||
|
||||
## 2025-11-27 - 7.0.1 - fix(build)
|
||||
|
||||
Update build tooling and TypeScript compilation target
|
||||
|
||||
- Bump devDependency @git.zone/tsbuild from ^3.1.0 to ^3.1.1.
|
||||
- Update tsconfig.json compiler target from ES2022 to ES2024 (affects emitted JS language level).
|
||||
|
||||
## 2025-11-27 - 7.0.0 - BREAKING CHANGE(mongodb)
|
||||
|
||||
Upgrade dependencies: bump mongodb to ^7.0.0 and @git.zone/tstest to ^3.1.3
|
||||
|
||||
- Bump 'mongodb' dependency from ^6.20.0 to ^7.0.0 — major version upgrade; may introduce breaking API changes and require code updates or verification against the new driver.
|
||||
- Update devDependency '@git.zone/tstest' from ^2.8.1 to ^3.1.3 — test tooling updated.
|
||||
|
||||
## 2025-11-17 - 6.0.0 - BREAKING CHANGE(decorators)
|
||||
|
||||
Migrate to TC39 Stage 3 decorators and refactor decorator metadata handling; update class initialization, lucene adapter fixes and docs
|
||||
|
||||
- Switch all decorators to TC39 Stage 3 signatures and metadata usage (use context.metadata and context.addInitializer) — affects svDb, globalSvDb, searchable, unI, index, Collection and managed.
|
||||
@@ -123,24 +149,27 @@ Migrate to TC39 Stage 3 decorators and refactor decorator metadata handling; upd
|
||||
- Clean up project memory/config files related to the previous decorator approach and Deno configuration adjustments.
|
||||
|
||||
## 2025-11-17 - 5.16.7 - fix(classes.collection)
|
||||
Improve Deno and TypeScript compatibility: Collection decorator _svDbOptions forwarding and config cleanup
|
||||
|
||||
- Collection decorator: capture original constructor and forward _svDbOptions to ensure property decorator options (serialize/deserialize) remain accessible in Deno environments.
|
||||
Improve Deno and TypeScript compatibility: Collection decorator \_svDbOptions forwarding and config cleanup
|
||||
|
||||
- Collection decorator: capture original constructor and forward \_svDbOptions to ensure property decorator options (serialize/deserialize) remain accessible in Deno environments.
|
||||
- Collection decorator: keep instance getter defined on prototype for Deno compatibility (no behavior change, clarifies forwarding logic).
|
||||
- Build/config: removed experimentalDecorators and useDefineForClassFields from deno.json and tsconfig.json to avoid Deno/TS build issues and rely on default compilation settings.
|
||||
|
||||
## 2025-11-17 - 5.16.6 - fix(classes)
|
||||
|
||||
Add Deno compatibility, prototype-safe decorators and safe collection accessor; bump a few deps
|
||||
|
||||
- Add deno.json to enable experimentalDecorators and target ES2022/DOM for Deno builds.
|
||||
- Introduce getCollectionSafe() on SmartDataDbDoc and use it for save/update/delete/findOne to avoid runtime errors when instance 'collection' is not present.
|
||||
- Change several instance properties (globalSaveableProperties, uniqueIndexes, regularIndexes, saveableProperties) to 'declare' so decorator-set prototype properties are not shadowed (Deno compatibility).
|
||||
- Enhance @Collection decorator: capture original constructor/prototype for Deno, define prototype getter for collection on decorated class, attach docCtor for searchableFields, and forward _svDbOptions to the original constructor to preserve serializer metadata.
|
||||
- Enhance @Collection decorator: capture original constructor/prototype for Deno, define prototype getter for collection on decorated class, attach docCtor for searchableFields, and forward \_svDbOptions to the original constructor to preserve serializer metadata.
|
||||
- Improve text/search index handling by relying on docCtor.searchableFields and guarding text index creation.
|
||||
- Bump dependencies/devDependencies: @push.rocks/smartmongo -> ^2.0.14, @git.zone/tsbuild -> ^2.7.1, @git.zone/tstest -> ^2.8.1.
|
||||
- These are non-breaking runtime compatibility and developer-experience fixes; intended as a patch release.
|
||||
|
||||
## 2025-11-16 - 5.16.5 - fix(watcher)
|
||||
|
||||
Update dependencies, tooling and watcher import; add .serena cache ignore
|
||||
|
||||
- Bump runtime dependencies: @push.rocks/smartlog 3.1.8 → 3.1.10, @push.rocks/smartstring 4.0.15 → 4.1.0, @push.rocks/taskbuffer 3.1.7 → 3.4.0, @tsclass/tsclass 9.2.0 → 9.3.0, mongodb 6.18.0 → 6.20.0
|
||||
@@ -149,6 +178,7 @@ Update dependencies, tooling and watcher import; add .serena cache ignore
|
||||
- Add .serena/.gitignore to ignore /cache
|
||||
|
||||
## 2025-08-18 - 5.16.4 - fix(classes.doc (convertFilterForMongoDb))
|
||||
|
||||
Improve filter conversion: handle logical operators, merge operator objects, add nested filter tests and docs, and fix test script
|
||||
|
||||
- Fix package.json test script: remove stray dot in tstest --verbose argument to ensure tests run correctly
|
||||
@@ -159,6 +189,7 @@ Improve filter conversion: handle logical operators, merge operator objects, add
|
||||
- Expand README filtering section with detailed examples for basic filtering, deep nested filters, comparison operators, array operations, logical and element operators, and advanced patterns
|
||||
|
||||
## 2025-08-18 - 5.16.3 - fix(docs)
|
||||
|
||||
Add local Claude settings and remove outdated codex.md
|
||||
|
||||
- Added .claude/settings.local.json to store local Claude/assistant permissions and configuration.
|
||||
@@ -166,6 +197,7 @@ Add local Claude settings and remove outdated codex.md
|
||||
- No runtime/library code changes; documentation/configuration-only update, bump patch version.
|
||||
|
||||
## 2025-08-18 - 5.16.2 - fix(readme)
|
||||
|
||||
Update README: clarify examples, expand search/cursor/docs and add local Claude settings
|
||||
|
||||
- Refined README wording and structure: clearer Quick Start, improved examples and developer-focused phrasing
|
||||
@@ -174,6 +206,7 @@ Update README: clarify examples, expand search/cursor/docs and add local Claude
|
||||
- Added .claude/settings.local.json to provide local assistant/CI permission configuration
|
||||
|
||||
## 2025-08-12 - 5.16.1 - fix(core)
|
||||
|
||||
Improve error handling and logging; enhance search query sanitization; update dependency versions and documentation
|
||||
|
||||
- Replaced console.log and console.warn with structured logger.log calls throughout the core modules
|
||||
@@ -184,6 +217,7 @@ Improve error handling and logging; enhance search query sanitization; update de
|
||||
- Updated README with improved instructions, feature highlights, and quick start sections
|
||||
|
||||
## 2025-04-25 - 5.16.0 - feat(watcher)
|
||||
|
||||
Enhance change stream watchers with buffering and EventEmitter support; update dependency versions
|
||||
|
||||
- Bumped smartmongo from ^2.0.11 to ^2.0.12 and smartrx from ^3.0.7 to ^3.0.10
|
||||
@@ -192,6 +226,7 @@ Enhance change stream watchers with buffering and EventEmitter support; update d
|
||||
- Modified SmartdataDbWatcher to extend EventEmitter and support event notifications
|
||||
|
||||
## 2025-04-24 - 5.15.1 - fix(cursor)
|
||||
|
||||
Improve cursor usage documentation and refactor getCursor API to support native cursor modifiers
|
||||
|
||||
- Updated examples in readme.md to demonstrate manual iteration using cursor.next() and proper cursor closing.
|
||||
@@ -199,6 +234,7 @@ Improve cursor usage documentation and refactor getCursor API to support native
|
||||
- Added new tests in test/test.cursor.ts to verify cursor operations, including limits, sorting, and skipping.
|
||||
|
||||
## 2025-04-24 - 5.15.0 - feat(svDb)
|
||||
|
||||
Enhance svDb decorator to support custom serialization and deserialization options
|
||||
|
||||
- Added an optional options parameter to the svDb decorator to accept serialize/deserialize functions
|
||||
@@ -206,6 +242,7 @@ Enhance svDb decorator to support custom serialization and deserialization optio
|
||||
- Updated createSavableObject to use custom serialization when available
|
||||
|
||||
## 2025-04-23 - 5.14.1 - fix(db operations)
|
||||
|
||||
Update transaction API to consistently pass optional session parameters across database operations
|
||||
|
||||
- Revised transaction support in readme to use startSession without await and showcased session usage in getInstance and save calls
|
||||
@@ -214,14 +251,16 @@ Update transaction API to consistently pass optional session parameters across d
|
||||
- Improved overall consistency of transactional APIs across the library
|
||||
|
||||
## 2025-04-23 - 5.14.0 - feat(doc)
|
||||
|
||||
Implement support for beforeSave, afterSave, beforeDelete, and afterDelete lifecycle hooks in document save and delete operations to allow custom logic execution during these critical moments.
|
||||
|
||||
- Calls beforeSave hook if defined before performing insert or update.
|
||||
- Calls afterSave hook after a document is saved.
|
||||
- Calls beforeDelete hook before deletion and afterDelete hook afterward.
|
||||
- Ensures _updatedAt timestamp is refreshed during save operations.
|
||||
- Ensures \_updatedAt timestamp is refreshed during save operations.
|
||||
|
||||
## 2025-04-22 - 5.13.1 - fix(search)
|
||||
|
||||
Improve search query parsing for implicit AND queries by preserving quoted substrings and better handling free terms, quoted phrases, and field:value tokens.
|
||||
|
||||
- Replace previous implicit AND logic with tokenization that preserves quoted substrings
|
||||
@@ -229,6 +268,7 @@ Improve search query parsing for implicit AND queries by preserving quoted subst
|
||||
- Ensure errors are thrown for non-searchable fields in field-specific queries
|
||||
|
||||
## 2025-04-22 - 5.13.0 - feat(search)
|
||||
|
||||
Improve search query handling and update documentation
|
||||
|
||||
- Added 'codex.md' providing a high-level project overview and detailed search API documentation.
|
||||
@@ -237,12 +277,14 @@ Improve search query handling and update documentation
|
||||
- Updated tests in test/test.search.ts to cover new combined query scenarios and ensure robust behavior.
|
||||
|
||||
## 2025-04-22 - 5.12.2 - fix(search)
|
||||
|
||||
Fix handling of quoted wildcard patterns in field-specific search queries and add tests for location-based wildcard phrase searches
|
||||
|
||||
- Strip surrounding quotes from wildcard patterns in field queries to correctly transform them to regex
|
||||
- Introduce new tests in test/test.search.ts to validate exact quoted and unquoted wildcard searches on a location field
|
||||
|
||||
## 2025-04-22 - 5.12.1 - fix(search)
|
||||
|
||||
Improve implicit AND logic for mixed free term and field queries in search and enhance wildcard field handling.
|
||||
|
||||
- Updated regex for field:value parsing to capture full value with wildcards.
|
||||
@@ -251,6 +293,7 @@ Improve implicit AND logic for mixed free term and field queries in search and e
|
||||
- Extended tests to cover combined free term and wildcard field searches, including error cases.
|
||||
|
||||
## 2025-04-22 - 5.12.0 - feat(doc/search)
|
||||
|
||||
Enhance search functionality with filter and validate options for advanced query control
|
||||
|
||||
- Added 'filter' option to merge additional MongoDB query constraints in search
|
||||
@@ -259,6 +302,7 @@ Enhance search functionality with filter and validate options for advanced query
|
||||
- Updated tests to cover new search scenarios and fallback mechanisms
|
||||
|
||||
## 2025-04-22 - 5.11.4 - fix(search)
|
||||
|
||||
Implement implicit AND logic for mixed simple term and field:value queries in search
|
||||
|
||||
- Added a new branch to detect and handle search queries that mix field:value pairs with plain terms without explicit operators
|
||||
@@ -266,6 +310,7 @@ Implement implicit AND logic for mixed simple term and field:value queries in se
|
||||
- Ensures proper parsing and improved robustness of search filters
|
||||
|
||||
## 2025-04-22 - 5.11.3 - fix(lucene adapter and search tests)
|
||||
|
||||
Improve range query parsing in Lucene adapter and expand search test coverage
|
||||
|
||||
- Added a new 'testSearch' script in package.json to run search tests.
|
||||
@@ -274,12 +319,14 @@ Improve range query parsing in Lucene adapter and expand search test coverage
|
||||
- Fixed token validation in the parseRange method of the Lucene adapter to ensure proper error handling.
|
||||
|
||||
## 2025-04-21 - 5.11.2 - fix(readme)
|
||||
|
||||
Update readme to clarify usage of searchable fields retrieval
|
||||
|
||||
- Replaced getSearchableFields('Product') with Product.getSearchableFields()
|
||||
- Updated documentation to reference the static method Class.getSearchableFields()
|
||||
|
||||
## 2025-04-21 - 5.11.1 - fix(doc)
|
||||
|
||||
Refactor searchable fields API and improve collection registration.
|
||||
|
||||
- Removed the standalone getSearchableFields utility in favor of a static method on document classes.
|
||||
@@ -288,11 +335,13 @@ Refactor searchable fields API and improve collection registration.
|
||||
- Added try/catch in test cleanup to gracefully handle dropDatabase errors.
|
||||
|
||||
## 2025-04-21 - 5.11.0 - feat(ts/classes.lucene.adapter)
|
||||
|
||||
Expose luceneWildcardToRegex method to allow external usage and enhance regex transformation capabilities.
|
||||
|
||||
- Changed luceneWildcardToRegex from private to public in ts/classes.lucene.adapter.ts.
|
||||
|
||||
## 2025-04-21 - 5.10.0 - feat(search)
|
||||
|
||||
Improve search functionality: update documentation, refine Lucene query transformation, and add advanced search tests
|
||||
|
||||
- Updated readme.md with detailed Lucene‑style search examples and use cases
|
||||
@@ -301,6 +350,7 @@ Improve search functionality: update documentation, refine Lucene query transfor
|
||||
- Added new advanced search tests covering boolean operators, grouping, quoted phrases, and wildcard queries
|
||||
|
||||
## 2025-04-18 - 5.9.2 - fix(documentation)
|
||||
|
||||
Update search API documentation to replace deprecated searchWithLucene examples with the unified search(query) API and clarify its behavior.
|
||||
|
||||
- Replaced 'searchWithLucene' examples with 'search(query)' in the README.
|
||||
@@ -308,24 +358,28 @@ Update search API documentation to replace deprecated searchWithLucene examples
|
||||
- Clarified guidelines for creating MongoDB text indexes on searchable fields for optimized search performance.
|
||||
|
||||
## 2025-04-18 - 5.9.1 - fix(search)
|
||||
|
||||
Refactor search tests to use unified search API and update text index type casting
|
||||
|
||||
- Replaced all calls from searchWithLucene with search in test/search tests
|
||||
- Updated text index specification in the collection class to use proper type casting
|
||||
|
||||
## 2025-04-18 - 5.9.0 - feat(collections/search)
|
||||
|
||||
Improve text index creation and search fallback mechanisms in collections and document search methods
|
||||
|
||||
- Auto-create a compound text index on all searchable fields in SmartdataCollection with a one-time flag to prevent duplicate index creation.
|
||||
- Refine the search method in SmartDataDbDoc to support exact field matches and safe regex fallback for non-Lucene queries.
|
||||
|
||||
## 2025-04-17 - 5.8.4 - fix(core)
|
||||
|
||||
Update commit metadata with no functional code changes
|
||||
|
||||
- Commit info and documentation refreshed
|
||||
- No code or test changes detected in the diff
|
||||
|
||||
## 2025-04-17 - 5.8.3 - fix(readme)
|
||||
|
||||
Improve readme documentation on data models and connection management
|
||||
|
||||
- Clarify that data models use @Collection, @unI, @svDb, @index, and @searchable decorators
|
||||
@@ -334,12 +388,14 @@ Improve readme documentation on data models and connection management
|
||||
- Revise license section to reference the MIT License without including additional legal details
|
||||
|
||||
## 2025-04-14 - 5.8.2 - fix(classes.doc.ts)
|
||||
|
||||
Ensure collection initialization before creating a cursor in getCursorExtended
|
||||
|
||||
- Added 'await collection.init()' to guarantee that the MongoDB collection is initialized before using the cursor
|
||||
- Prevents potential runtime errors when accessing collection.mongoDbCollection
|
||||
|
||||
## 2025-04-14 - 5.8.1 - fix(cursor, doc)
|
||||
|
||||
Add explicit return types and casts to SmartdataDbCursor methods and update getCursorExtended signature in SmartDataDbDoc.
|
||||
|
||||
- Specify Promise<T> as return type for next() in SmartdataDbCursor and cast return value to T.
|
||||
@@ -347,12 +403,14 @@ Add explicit return types and casts to SmartdataDbCursor methods and update getC
|
||||
- Update getCursorExtended to return Promise<SmartdataDbCursor<T>> for clearer type safety.
|
||||
|
||||
## 2025-04-14 - 5.8.0 - feat(cursor)
|
||||
|
||||
Add toArray method to SmartdataDbCursor to convert raw MongoDB documents into initialized class instances
|
||||
|
||||
- Introduced asynchronous toArray method in SmartdataDbCursor which retrieves all documents from the MongoDB cursor
|
||||
- Maps each native document to a SmartDataDbDoc instance using createInstanceFromMongoDbNativeDoc for consistent API usage
|
||||
|
||||
## 2025-04-14 - 5.7.0 - feat(SmartDataDbDoc)
|
||||
|
||||
Add extended cursor method getCursorExtended for flexible cursor modifications
|
||||
|
||||
- Introduces getCursorExtended in classes.doc.ts to allow modifier functions for MongoDB cursors
|
||||
@@ -360,6 +418,7 @@ Add extended cursor method getCursorExtended for flexible cursor modifications
|
||||
- Enhances querying capabilities by enabling customized cursor transformations
|
||||
|
||||
## 2025-04-07 - 5.6.0 - feat(indexing)
|
||||
|
||||
Add support for regular index creation in documents and collections
|
||||
|
||||
- Implement new index decorator in classes.doc.ts to mark properties with regular indexing options
|
||||
@@ -367,6 +426,7 @@ Add support for regular index creation in documents and collections
|
||||
- Enhance document structure to store and utilize regular index configurations
|
||||
|
||||
## 2025-04-06 - 5.5.1 - fix(ci & formatting)
|
||||
|
||||
Minor fixes: update CI workflow image and npmci package references, adjust package.json and readme URLs, and apply consistent code formatting.
|
||||
|
||||
- Update image and repo URL in Gitea workflows from GitLab to code.foss.global
|
||||
@@ -376,6 +436,7 @@ Minor fixes: update CI workflow image and npmci package references, adjust packa
|
||||
- Minor update to .gitignore custom section label
|
||||
|
||||
## 2025-04-06 - 5.5.0 - feat(search)
|
||||
|
||||
Enhance search functionality with robust Lucene query transformation and reliable fallback mechanisms
|
||||
|
||||
- Improve Lucene adapter to properly structure $or queries for term, phrase, wildcard, and fuzzy search
|
||||
@@ -383,15 +444,17 @@ Enhance search functionality with robust Lucene query transformation and reliabl
|
||||
- Update readme and tests with extensive examples for @searchable fields and Lucene-based queries
|
||||
|
||||
## 2025-04-06 - 5.4.0 - feat(core)
|
||||
|
||||
Refactor file structure and update dependency versions
|
||||
|
||||
- Renamed files and modules from 'smartdata.classes.*' to 'classes.*' and adjusted corresponding import paths.
|
||||
- Renamed files and modules from 'smartdata.classes._' to 'classes._' and adjusted corresponding import paths.
|
||||
- Updated dependency versions: '@push.rocks/smartmongo' to ^2.0.11, '@tsclass/tsclass' to ^8.2.0, and 'mongodb' to ^6.15.0.
|
||||
- Renamed dev dependency packages from '@gitzone/...' to '@git.zone/...' and updated '@push.rocks/tapbundle' and '@types/node'.
|
||||
- Fixed YAML workflow command: replaced 'pnpm install -g @gitzone/tsdoc' with 'pnpm install -g @git.zone/tsdoc'.
|
||||
- Added package manager configuration and pnpm-workspace.yaml for built dependencies.
|
||||
|
||||
## 2025-03-10 - 5.3.0 - feat(docs)
|
||||
|
||||
Enhance documentation with updated installation instructions and comprehensive usage examples covering advanced features such as deep queries, automatic indexing, and distributed coordination.
|
||||
|
||||
- Added pnpm installation command
|
||||
@@ -401,11 +464,13 @@ Enhance documentation with updated installation instructions and comprehensive u
|
||||
- Included detailed examples for transactions, deep object queries, and document lifecycle hooks
|
||||
|
||||
## 2025-02-03 - 5.2.12 - fix(documentation)
|
||||
|
||||
Remove license badge from README
|
||||
|
||||
- Removed the license badge from the README file, ensuring compliance with branding guidelines.
|
||||
|
||||
## 2025-02-03 - 5.2.11 - fix(documentation)
|
||||
|
||||
Updated project documentation for accuracy and added advanced feature details
|
||||
|
||||
- Added details for EasyStore, Distributed Coordination, and Real-time Data Watching features.
|
||||
@@ -413,158 +478,188 @@ Updated project documentation for accuracy and added advanced feature details
|
||||
- Re-organized advanced usage section to showcase additional features separately.
|
||||
|
||||
## 2024-09-05 - 5.2.10 - fix(smartdata.classes.doc)
|
||||
|
||||
Fix issue with array handling in convertFilterForMongoDb function
|
||||
|
||||
- Corrected the logic to properly handle array filters in the convertFilterForMongoDb function to avoid incorrect assignments.
|
||||
|
||||
## 2024-09-05 - 5.2.9 - fix(smartdata.classes.doc)
|
||||
|
||||
Fixed issue with convertFilterForMongoDb to handle array operators.
|
||||
|
||||
- Updated the convertFilterForMongoDb function in smartdata.classes.doc.ts to properly handle array operators like $in and $all.
|
||||
|
||||
## 2024-09-05 - 5.2.8 - fix(smartdata.classes.doc)
|
||||
|
||||
Fix key handling in convertFilterForMongoDb function
|
||||
|
||||
- Fixed an issue in convertFilterForMongoDb that allowed keys with dots which could cause errors.
|
||||
|
||||
## 2024-09-05 - 5.2.7 - fix(core)
|
||||
|
||||
Fixed issue with handling filter keys containing dots in smartdata.classes.doc.ts
|
||||
|
||||
- Fixed an error in the convertFilterForMongoDb function which previously threw an error when keys contained dots.
|
||||
|
||||
## 2024-06-18 - 5.2.6 - Chore
|
||||
|
||||
Maintenance Release
|
||||
|
||||
- Release version 5.2.6
|
||||
|
||||
## 2024-05-31 - 5.2.2 - Bug Fixes
|
||||
|
||||
Fixes and Maintenance
|
||||
|
||||
- Fixed issue where `_createdAt` and `_updatedAt` registered saveableProperties for all document types
|
||||
|
||||
## 2024-04-15 - 5.1.2 - New Feature
|
||||
|
||||
Enhancements and Bug Fixes
|
||||
|
||||
- Added static `.getCount({})` method to `SmartDataDbDoc`
|
||||
- Changed fields `_createdAt` and `_updatedAt` to ISO format
|
||||
|
||||
## 2024-04-14 - 5.0.43 - New Feature
|
||||
|
||||
New Feature Addition
|
||||
|
||||
- Added default `_createdAt` and `_updatedAt` fields, fixes #1
|
||||
|
||||
## 2024-03-30 - 5.0.41 - Bug Fixes
|
||||
|
||||
Improvements and Fixes
|
||||
|
||||
- Improved `tsconfig.json` for ES Module use
|
||||
|
||||
## 2023-07-10 - 5.0.20 - Chore
|
||||
|
||||
Organizational Changes
|
||||
|
||||
- Switched to new org scheme
|
||||
|
||||
## 2023-07-21 - 5.0.21 to 5.0.26 - Fixes
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2023-07-21 - 5.0.20 - Chore
|
||||
|
||||
Organizational Changes
|
||||
|
||||
- Switch to the new org scheme
|
||||
|
||||
## 2023-06-25 - 5.0.14 to 5.0.19 - Fixes
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2022-05-17 - 5.0.0 - Major Update
|
||||
|
||||
Breaking Changes
|
||||
|
||||
- Switched to ESM
|
||||
|
||||
## 2022-05-18 - 5.0.2 - Bug Fixes
|
||||
|
||||
Bug Fixes
|
||||
|
||||
- The `watcher.changeSubject` now emits the correct type into observer functions
|
||||
|
||||
## 2022-05-17 - 5.0.1 - Chore
|
||||
|
||||
Testing Improvements
|
||||
|
||||
- Tests now use `@pushrocks/smartmongo` backed by `wiredTiger`
|
||||
|
||||
## 2022-05-17 to 2022-11-08 - 5.0.8 to 5.0.10
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2021-11-12 - 4.0.17 to 4.0.20
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2021-09-17 - 4.0.10 to 4.0.16
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2021-06-09 - 4.0.1 to 4.0.9
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2021-06-06 - 4.0.0 - Major Update
|
||||
|
||||
Major Release
|
||||
|
||||
- Maintenance and core updates
|
||||
|
||||
## 2021-05-17 - 3.1.56 - Chore
|
||||
|
||||
Maintenance Release
|
||||
|
||||
- Release version 3.1.56
|
||||
|
||||
## 2020-09-09 - 3.1.44 to 3.1.52
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2020-06-12 - 3.1.26 to 3.1.28
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2020-02-18 - 3.1.23 to 3.1.25
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2019-09-11 - 3.1.20 to 3.1.22
|
||||
|
||||
Multiple Fix Releases
|
||||
|
||||
- Various core updates and bug fixes
|
||||
|
||||
## 2018-07-10 - 3.0.5 - New Feature
|
||||
|
||||
Added Feature
|
||||
|
||||
- Added custom unique indexes to `SmartdataDoc`
|
||||
|
||||
## 2018-07-08 - 3.0.1 - Chore
|
||||
|
||||
Dependencies Update
|
||||
|
||||
- Updated mongodb dependencies
|
||||
|
||||
## 2018-07-08 - 3.0.0 - Major Update
|
||||
|
||||
Refactor and Cleanup
|
||||
|
||||
- Cleaned project structure
|
||||
|
||||
## 2018-01-16 - 2.0.7 - Breaking Change
|
||||
|
||||
Big Changes
|
||||
|
||||
- Switched to `@pushrocks` scope and moved from `rethinkdb` to `mongodb`
|
||||
|
||||
## 2018-01-12 - 2.0.0 - Major Release
|
||||
|
||||
Core Updates
|
||||
|
||||
- Updated CI configurations
|
||||
|
||||
|
||||
31
package.json
31
package.json
@@ -10,7 +10,7 @@
|
||||
"scripts": {
|
||||
"test": "tstest test/ --verbose --logfile --timeout 120",
|
||||
"testSearch": "tsx test/test.search.ts",
|
||||
"build": "tsbuild --web --allowimplicitany",
|
||||
"build": "tsbuild tsfolders",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
"repository": {
|
||||
@@ -24,25 +24,24 @@
|
||||
},
|
||||
"homepage": "https://code.foss.global/push.rocks/smartdata#readme",
|
||||
"dependencies": {
|
||||
"@push.rocks/lik": "^6.2.2",
|
||||
"@push.rocks/smartdelay": "^3.0.1",
|
||||
"@push.rocks/smartlog": "^3.1.10",
|
||||
"@push.rocks/smartmongo": "^2.0.14",
|
||||
"@push.rocks/smartpromise": "^4.0.2",
|
||||
"@push.rocks/lik": "^6.4.0",
|
||||
"@push.rocks/smartdelay": "^3.0.5",
|
||||
"@push.rocks/smartlog": "^3.2.1",
|
||||
"@push.rocks/smartmongo": "^5.1.0",
|
||||
"@push.rocks/smartpromise": "^4.2.3",
|
||||
"@push.rocks/smartrx": "^3.0.10",
|
||||
"@push.rocks/smartstring": "^4.1.0",
|
||||
"@push.rocks/smarttime": "^4.0.6",
|
||||
"@push.rocks/smartunique": "^3.0.8",
|
||||
"@push.rocks/taskbuffer": "^3.4.0",
|
||||
"@tsclass/tsclass": "^9.3.0",
|
||||
"mongodb": "^7.0.0"
|
||||
"@push.rocks/smarttime": "^4.2.3",
|
||||
"@push.rocks/smartunique": "^3.0.9",
|
||||
"@push.rocks/taskbuffer": "^8.0.2",
|
||||
"@tsclass/tsclass": "^9.5.0",
|
||||
"mongodb": "^7.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^3.1.2",
|
||||
"@git.zone/tsrun": "^2.0.0",
|
||||
"@git.zone/tstest": "^3.1.3",
|
||||
"@git.zone/tsbuild": "^4.4.0",
|
||||
"@git.zone/tsrun": "^2.0.1",
|
||||
"@git.zone/tstest": "^3.5.1",
|
||||
"@push.rocks/qenv": "^6.1.3",
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
"@types/node": "^22.15.2"
|
||||
},
|
||||
"files": [
|
||||
@@ -54,7 +53,7 @@
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
".smartconfig.json",
|
||||
"readme.md"
|
||||
],
|
||||
"browserslist": [
|
||||
|
||||
3384
pnpm-lock.yaml
generated
3384
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
- mongodb-memory-server
|
||||
- puppeteer
|
||||
@@ -3,9 +3,11 @@
|
||||
## TC39 Decorator Migration (v6.0.0) - ✅ COMPLETED
|
||||
|
||||
### Final Status: All Tests Passing (157/157)
|
||||
|
||||
Migration successfully completed on 2025-11-17.
|
||||
|
||||
### What Changed:
|
||||
|
||||
- ✅ Removed `experimentalDecorators` from tsconfig.json
|
||||
- ✅ Refactored all 7 decorators to TC39 Stage 3 syntax
|
||||
- 5 property decorators: @globalSvDb, @svDb, @unI, @index, @searchable
|
||||
@@ -14,13 +16,16 @@ Migration successfully completed on 2025-11-17.
|
||||
- ✅ All tests passing across Node.js and Deno runtimes
|
||||
|
||||
### Critical Discovery: TC39 Metadata Access Pattern
|
||||
|
||||
**THE KEY INSIGHT**: In TC39 decorators, metadata is NOT accessed via `constructor[Symbol.metadata]`. Instead:
|
||||
|
||||
- **Field decorators**: Write to `context.metadata`
|
||||
- **Class decorators**: Read from `context.metadata` (same shared object!)
|
||||
- The `context.metadata` object is shared between all decorators on the same class
|
||||
- Attempting to write to `constructor[Symbol.metadata]` throws: "Cannot assign to read only property"
|
||||
|
||||
### Implementation Pattern:
|
||||
|
||||
```typescript
|
||||
// Field decorator - stores metadata
|
||||
export function svDb() {
|
||||
@@ -46,25 +51,30 @@ export function Collection(dbArg: SmartdataDb) {
|
||||
```
|
||||
|
||||
### Runtime Compatibility:
|
||||
|
||||
- ✅ **Node.js v23.8.0**: Full TC39 support
|
||||
- ✅ **Deno v2.5.4**: Full TC39 support
|
||||
- ❌ **Bun v1.3.0**: No TC39 support (uses legacy decorators only)
|
||||
- Removed "+bun" from test filenames to skip Bun tests
|
||||
|
||||
### Key Technical Notes:
|
||||
|
||||
1. **Metadata Initialization Timing**: Class decorators run AFTER field decorators, allowing them to read accumulated metadata and initialize prototypes before any instances are created
|
||||
2. **Prototype vs Instance Properties**: Properties set on prototype are accessible via `this.propertyName` in instances
|
||||
3. **TypeScript Lib Support**: TypeScript 5.9.3 includes built-in decorator types (no custom lib configuration needed)
|
||||
4. **Interface Naming**: Used `ISmartdataDecoratorMetadata` extending `DecoratorMetadataObject` for type safety
|
||||
|
||||
### Files Modified:
|
||||
|
||||
- ts/classes.doc.ts (property decorators + metadata interface)
|
||||
- ts/classes.collection.ts (class decorators + prototype initialization)
|
||||
- tsconfig.json (removed experimentalDecorators flag)
|
||||
- test/*.ts (renamed files to remove "+bun" suffix)
|
||||
- test/\*.ts (renamed files to remove "+bun" suffix)
|
||||
|
||||
### Test Results:
|
||||
|
||||
All 157 tests passing across 10 test files:
|
||||
|
||||
- test.cursor.ts: 7/7
|
||||
- test.deno.ts: 11/11 (queries working correctly!)
|
||||
- test.search.advanced.ts: 41/41
|
||||
@@ -73,6 +83,7 @@ All 157 tests passing across 10 test files:
|
||||
- And 5 more test files
|
||||
|
||||
### Migration Learnings for Future Reference:
|
||||
|
||||
1. `context.metadata` is the ONLY way to share state between decorators
|
||||
2. Class decorators must initialize prototypes from metadata immediately
|
||||
3. `Symbol.metadata` on constructors is read-only (managed by runtime)
|
||||
@@ -82,10 +93,13 @@ All 157 tests passing across 10 test files:
|
||||
## ES2022 Class Fields & Prototype Getters - Fixed in v7.0.15
|
||||
|
||||
### Issue
|
||||
|
||||
ES2022 class fields (`useDefineForClassFields: true`) create own properties during construction that shadow prototype getters defined by decorators.
|
||||
|
||||
### Solution
|
||||
|
||||
Use `declare` keyword for instance properties that are accessed via prototype getters:
|
||||
|
||||
```typescript
|
||||
// In SmartDataDbDoc (ts/classes.doc.ts):
|
||||
declare public collection: SmartdataCollection<any>; // Type-only, no JS emitted
|
||||
@@ -93,6 +107,7 @@ declare public manager: TManager; // Type-only, no JS emitted
|
||||
```
|
||||
|
||||
### Key Insight
|
||||
|
||||
- `declare` tells TypeScript this is a type-only declaration
|
||||
- No JavaScript code is emitted for `declare` properties
|
||||
- Prototype getters defined by `@Collection` and `@managed` decorators are no longer shadowed
|
||||
|
||||
216
readme.md
216
readme.md
@@ -52,9 +52,9 @@ const db = new SmartdataDb({
|
||||
mongoDbPass: 'password',
|
||||
|
||||
// Optional: Advanced connection pooling
|
||||
maxPoolSize: 100, // Max connections in pool
|
||||
maxIdleTimeMS: 300000, // Max idle time before connection close
|
||||
serverSelectionTimeoutMS: 30000 // Connection timeout
|
||||
maxPoolSize: 100, // Max connections in pool
|
||||
maxIdleTimeMS: 300000, // Max idle time before connection close
|
||||
serverSelectionTimeoutMS: 30000, // Connection timeout
|
||||
});
|
||||
|
||||
// Initialize with automatic retry and health monitoring
|
||||
@@ -77,25 +77,25 @@ import { ObjectId } from 'mongodb';
|
||||
@Collection(() => db)
|
||||
class User extends SmartDataDbDoc<User, User> {
|
||||
@unI()
|
||||
public id: string; // Unique index with automatic ID generation
|
||||
public id: string; // Unique index with automatic ID generation
|
||||
|
||||
@svDb()
|
||||
@searchable() // Enable Lucene-style searching
|
||||
@searchable() // Enable Lucene-style searching
|
||||
public username: string;
|
||||
|
||||
@svDb()
|
||||
@searchable()
|
||||
@index({ unique: false }) // Performance index
|
||||
@index({ unique: false }) // Performance index
|
||||
public email: string;
|
||||
|
||||
@svDb()
|
||||
public status: 'active' | 'inactive' | 'pending'; // Full union type support
|
||||
public status: 'active' | 'inactive' | 'pending'; // Full union type support
|
||||
|
||||
@svDb()
|
||||
public organizationId: ObjectId; // Native MongoDB types
|
||||
public organizationId: ObjectId; // Native MongoDB types
|
||||
|
||||
@svDb()
|
||||
public profilePicture: Buffer; // Binary data support
|
||||
public profilePicture: Buffer; // Binary data support
|
||||
|
||||
@svDb({
|
||||
// Custom serialization for complex objects
|
||||
@@ -105,7 +105,7 @@ class User extends SmartDataDbDoc<User, User> {
|
||||
public preferences: Record<string, any>;
|
||||
|
||||
@svDb()
|
||||
public tags: string[]; // Array support with operators
|
||||
public tags: string[]; // Array support with operators
|
||||
|
||||
@svDb()
|
||||
public createdAt: Date = new Date();
|
||||
@@ -156,12 +156,12 @@ const john = await User.getInstances({ name: 'John Doe' });
|
||||
// Multiple fields (implicit AND)
|
||||
const activeAdults = await User.getInstances({
|
||||
status: 'active',
|
||||
age: { $gte: 18 }
|
||||
age: { $gte: 18 },
|
||||
});
|
||||
|
||||
// Union types work perfectly
|
||||
const users = await User.getInstances({
|
||||
status: { $in: ['active', 'pending'] } // TypeScript validates these values!
|
||||
status: { $in: ['active', 'pending'] }, // TypeScript validates these values!
|
||||
});
|
||||
```
|
||||
|
||||
@@ -173,19 +173,19 @@ SmartData supports **both** nested object notation and dot notation for querying
|
||||
// Nested object notation - natural TypeScript syntax
|
||||
const users = await User.getInstances({
|
||||
metadata: {
|
||||
loginCount: { $gte: 5 }
|
||||
}
|
||||
loginCount: { $gte: 5 },
|
||||
},
|
||||
});
|
||||
|
||||
// Dot notation - MongoDB style
|
||||
const sameUsers = await User.getInstances({
|
||||
'metadata.loginCount': { $gte: 5 }
|
||||
'metadata.loginCount': { $gte: 5 },
|
||||
});
|
||||
|
||||
// POWERFUL: Combine both notations - operators are merged!
|
||||
const filtered = await User.getInstances({
|
||||
metadata: { loginCount: { $gte: 3 } }, // Object notation
|
||||
'metadata.loginCount': { $lte: 10 } // Dot notation
|
||||
metadata: { loginCount: { $gte: 3 } }, // Object notation
|
||||
'metadata.loginCount': { $lte: 10 }, // Dot notation
|
||||
// Result: metadata.loginCount between 3 and 10
|
||||
});
|
||||
|
||||
@@ -195,10 +195,10 @@ const deepQuery = await User.getInstances({
|
||||
settings: {
|
||||
notifications: {
|
||||
email: true,
|
||||
frequency: { $in: ['daily', 'weekly'] }
|
||||
}
|
||||
}
|
||||
}
|
||||
frequency: { $in: ['daily', 'weekly'] },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Mix styles for complex queries
|
||||
@@ -206,11 +206,11 @@ const advanced = await User.getInstances({
|
||||
// Object notation for structure
|
||||
profile: {
|
||||
age: { $gte: 21 },
|
||||
verified: true
|
||||
verified: true,
|
||||
},
|
||||
// Dot notation for specific overrides
|
||||
'profile.settings.theme': 'dark',
|
||||
'profile.lastSeen': { $gte: new Date('2024-01-01') }
|
||||
'profile.lastSeen': { $gte: new Date('2024-01-01') },
|
||||
});
|
||||
```
|
||||
|
||||
@@ -219,17 +219,17 @@ const advanced = await User.getInstances({
|
||||
```typescript
|
||||
// Numeric comparisons with type checking
|
||||
const adults = await User.getInstances({
|
||||
age: { $gte: 18, $lt: 65 } // Type-safe numeric comparisons
|
||||
age: { $gte: 18, $lt: 65 }, // Type-safe numeric comparisons
|
||||
});
|
||||
|
||||
// Date comparisons
|
||||
const recentUsers = await User.getInstances({
|
||||
createdAt: { $gte: new Date('2024-01-01') }
|
||||
createdAt: { $gte: new Date('2024-01-01') },
|
||||
});
|
||||
|
||||
// Not equal
|
||||
const nonAdmins = await User.getInstances({
|
||||
role: { $ne: 'admin' }
|
||||
role: { $ne: 'admin' },
|
||||
});
|
||||
```
|
||||
|
||||
@@ -238,23 +238,24 @@ const nonAdmins = await User.getInstances({
|
||||
```typescript
|
||||
// Array operations with full type safety
|
||||
const experts = await User.getInstances({
|
||||
tags: { $all: ['typescript', 'mongodb'] }, // Must have all tags
|
||||
skills: { $size: 5 } // Exactly 5 skills
|
||||
tags: { $all: ['typescript', 'mongodb'] }, // Must have all tags
|
||||
skills: { $size: 5 }, // Exactly 5 skills
|
||||
});
|
||||
|
||||
// Array element matching
|
||||
const results = await Order.getInstances({
|
||||
items: {
|
||||
$elemMatch: { // Match array elements
|
||||
$elemMatch: {
|
||||
// Match array elements
|
||||
product: 'laptop',
|
||||
quantity: { $gte: 2 }
|
||||
}
|
||||
}
|
||||
quantity: { $gte: 2 },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Check if value exists in array field
|
||||
const nodeUsers = await User.getInstances({
|
||||
skills: { $in: ['nodejs'] } // Has nodejs in skills array
|
||||
skills: { $in: ['nodejs'] }, // Has nodejs in skills array
|
||||
});
|
||||
```
|
||||
|
||||
@@ -266,24 +267,18 @@ const results = await Order.getInstances({
|
||||
$and: [
|
||||
{ status: { $in: ['pending', 'processing'] } },
|
||||
{ 'items.price': { $gte: 100 } },
|
||||
{ customer: { verified: true } }
|
||||
]
|
||||
{ customer: { verified: true } },
|
||||
],
|
||||
});
|
||||
|
||||
// $or operator
|
||||
const urgentOrHighValue = await Order.getInstances({
|
||||
$or: [
|
||||
{ priority: 'urgent' },
|
||||
{ totalAmount: { $gte: 1000 } }
|
||||
]
|
||||
$or: [{ priority: 'urgent' }, { totalAmount: { $gte: 1000 } }],
|
||||
});
|
||||
|
||||
// $nor operator - none of the conditions
|
||||
const excluded = await User.getInstances({
|
||||
$nor: [
|
||||
{ status: 'banned' },
|
||||
{ role: 'guest' }
|
||||
]
|
||||
$nor: [{ status: 'banned' }, { role: 'guest' }],
|
||||
});
|
||||
|
||||
// Combine logical operators
|
||||
@@ -291,12 +286,9 @@ const complex = await Order.getInstances({
|
||||
$and: [
|
||||
{ status: 'active' },
|
||||
{
|
||||
$or: [
|
||||
{ priority: 'high' },
|
||||
{ value: { $gte: 1000 } }
|
||||
]
|
||||
}
|
||||
]
|
||||
$or: [{ priority: 'high' }, { value: { $gte: 1000 } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -305,12 +297,12 @@ const complex = await Order.getInstances({
|
||||
```typescript
|
||||
// Check field existence
|
||||
const withEmail = await User.getInstances({
|
||||
email: { $exists: true }
|
||||
email: { $exists: true },
|
||||
});
|
||||
|
||||
// Check for null or missing nested fields
|
||||
const noPreferences = await User.getInstances({
|
||||
'profile.preferences': { $exists: false }
|
||||
'profile.preferences': { $exists: false },
|
||||
});
|
||||
```
|
||||
|
||||
@@ -319,12 +311,12 @@ const noPreferences = await User.getInstances({
|
||||
```typescript
|
||||
// Regex patterns
|
||||
const gmailUsers = await User.getInstances({
|
||||
email: { $regex: '@gmail\\.com$', $options: 'i' }
|
||||
email: { $regex: '@gmail\\.com$', $options: 'i' },
|
||||
});
|
||||
|
||||
// Starts with pattern
|
||||
const johnUsers = await User.getInstances({
|
||||
name: { $regex: '^John' }
|
||||
name: { $regex: '^John' },
|
||||
});
|
||||
```
|
||||
|
||||
@@ -349,22 +341,21 @@ const advancedQuery = await User.getInstances({
|
||||
// Nested object with operators
|
||||
profile: {
|
||||
age: { $gte: 18, $lte: 65 },
|
||||
verified: true
|
||||
verified: true,
|
||||
},
|
||||
|
||||
// Dot notation for deep paths
|
||||
'settings.notifications.email': true,
|
||||
'metadata.lastLogin': { $gte: new Date(Date.now() - 30*24*60*60*1000) },
|
||||
'metadata.lastLogin': {
|
||||
$gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
|
||||
},
|
||||
|
||||
// Array operations
|
||||
roles: { $in: ['admin', 'moderator'] },
|
||||
tags: { $all: ['verified', 'premium'] },
|
||||
|
||||
// Logical grouping
|
||||
$or: [
|
||||
{ 'subscription.plan': 'premium' },
|
||||
{ 'subscription.trial': true }
|
||||
]
|
||||
$or: [{ 'subscription.plan': 'premium' }, { 'subscription.trial': true }],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -400,7 +391,7 @@ const exact = await Product.search('"MacBook Pro 16"');
|
||||
// Combined with filters for powerful queries
|
||||
const affordable = await Product.search('laptop', {
|
||||
filter: { price: { $lte: 1500 } },
|
||||
validate: async (p) => p.inStock === true
|
||||
validate: async (p) => p.inStock === true,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -427,7 +418,7 @@ const config = await db.createEasyStore<AppConfig>('app-config');
|
||||
// Write with full type checking
|
||||
await config.writeKey('features', {
|
||||
darkMode: true,
|
||||
notifications: false
|
||||
notifications: false,
|
||||
});
|
||||
|
||||
// Read with guaranteed types
|
||||
@@ -437,7 +428,7 @@ const features = await config.readKey('features');
|
||||
// Atomic updates
|
||||
await config.updateKey('limits', (current) => ({
|
||||
...current,
|
||||
maxUsers: current.maxUsers + 100
|
||||
maxUsers: current.maxUsers + 100,
|
||||
}));
|
||||
|
||||
// Delete keys
|
||||
@@ -454,11 +445,11 @@ React to database changes instantly with RxJS integration:
|
||||
```typescript
|
||||
// Watch for changes with automatic reconnection
|
||||
const watcher = await User.watch(
|
||||
{ status: 'active' }, // Filter which documents to watch
|
||||
{ status: 'active' }, // Filter which documents to watch
|
||||
{
|
||||
fullDocument: 'updateLookup', // Get full document on updates
|
||||
bufferTimeMs: 100 // Buffer changes for efficiency
|
||||
}
|
||||
fullDocument: 'updateLookup', // Get full document on updates
|
||||
bufferTimeMs: 100, // Buffer changes for efficiency
|
||||
},
|
||||
);
|
||||
|
||||
// Subscribe to changes with RxJS
|
||||
@@ -466,7 +457,7 @@ watcher.changeSubject.subscribe({
|
||||
next: (change) => {
|
||||
console.log('User changed:', change.fullDocument);
|
||||
|
||||
switch(change.operationType) {
|
||||
switch (change.operationType) {
|
||||
case 'insert':
|
||||
console.log('New user created');
|
||||
break;
|
||||
@@ -478,7 +469,7 @@ watcher.changeSubject.subscribe({
|
||||
break;
|
||||
}
|
||||
},
|
||||
error: (err) => console.error('Watch error:', err)
|
||||
error: (err) => console.error('Watch error:', err),
|
||||
});
|
||||
|
||||
// Advanced: Watch with aggregation pipeline
|
||||
@@ -487,9 +478,9 @@ const complexWatcher = await Order.watch(
|
||||
{
|
||||
pipeline: [
|
||||
{ $match: { 'fullDocument.totalAmount': { $gte: 1000 } } },
|
||||
{ $addFields: { isHighValue: true } }
|
||||
]
|
||||
}
|
||||
{ $addFields: { isHighValue: true } },
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
// Clean up when done
|
||||
@@ -522,7 +513,7 @@ const isLeader = coordinator.isLeader;
|
||||
const result = await coordinator.fireDistributedTaskRequest({
|
||||
taskName: 'process-payments',
|
||||
taskExecutionTime: Date.now(),
|
||||
requestResponseId: 'unique-id'
|
||||
requestResponseId: 'unique-id',
|
||||
});
|
||||
|
||||
// Graceful shutdown with leadership handoff
|
||||
@@ -539,11 +530,12 @@ const cursor = await User.getCursor(
|
||||
{ status: 'active' },
|
||||
{
|
||||
// Optional: Use MongoDB native cursor modifiers
|
||||
modifier: (cursor) => cursor
|
||||
.sort({ createdAt: -1 })
|
||||
.limit(10000)
|
||||
.project({ email: 1, username: 1 })
|
||||
}
|
||||
modifier: (cursor) =>
|
||||
cursor
|
||||
.sort({ createdAt: -1 })
|
||||
.limit(10000)
|
||||
.project({ email: 1, username: 1 }),
|
||||
},
|
||||
);
|
||||
|
||||
// Process one at a time
|
||||
@@ -574,16 +566,13 @@ try {
|
||||
// All operations in this block are atomic
|
||||
const sender = await User.getInstance(
|
||||
{ id: 'user-1' },
|
||||
{ session } // Pass session to all operations
|
||||
{ session }, // Pass session to all operations
|
||||
);
|
||||
|
||||
sender.balance -= 100;
|
||||
await sender.save({ session });
|
||||
|
||||
const receiver = await User.getInstance(
|
||||
{ id: 'user-2' },
|
||||
{ session }
|
||||
);
|
||||
const receiver = await User.getInstance({ id: 'user-2' }, { session });
|
||||
|
||||
receiver.balance += 100;
|
||||
await receiver.save({ session });
|
||||
@@ -609,28 +598,28 @@ class Document extends SmartDataDbDoc<Document, Document> {
|
||||
@svDb({
|
||||
// Encrypt sensitive data before storing
|
||||
serialize: async (value) => await encrypt(value),
|
||||
deserialize: async (value) => await decrypt(value)
|
||||
deserialize: async (value) => await decrypt(value),
|
||||
})
|
||||
public sensitiveData: string;
|
||||
|
||||
@svDb({
|
||||
// Compress large JSON objects
|
||||
serialize: (value) => compress(JSON.stringify(value)),
|
||||
deserialize: (value) => JSON.parse(decompress(value))
|
||||
deserialize: (value) => JSON.parse(decompress(value)),
|
||||
})
|
||||
public largePayload: any;
|
||||
|
||||
@svDb({
|
||||
// Store Sets as arrays
|
||||
serialize: (set) => Array.from(set),
|
||||
deserialize: (arr) => new Set(arr)
|
||||
deserialize: (arr) => new Set(arr),
|
||||
})
|
||||
public tags: Set<string>;
|
||||
|
||||
@svDb({
|
||||
// Handle custom date formats
|
||||
serialize: (date) => date?.toISOString(),
|
||||
deserialize: (str) => str ? new Date(str) : null
|
||||
deserialize: (str) => (str ? new Date(str) : null),
|
||||
})
|
||||
public scheduledAt: Date | null;
|
||||
}
|
||||
@@ -651,8 +640,9 @@ class Order extends SmartDataDbDoc<Order, Order> {
|
||||
// Called before saving (create or update)
|
||||
async beforeSave() {
|
||||
// Recalculate total
|
||||
this.totalAmount = this.items.reduce((sum, item) =>
|
||||
sum + (item.price * item.quantity), 0
|
||||
this.totalAmount = this.items.reduce(
|
||||
(sum, item) => sum + item.price * item.quantity,
|
||||
0,
|
||||
);
|
||||
|
||||
// Validate
|
||||
@@ -698,34 +688,37 @@ class Order extends SmartDataDbDoc<Order, Order> {
|
||||
|
||||
```typescript
|
||||
@Collection(() => db)
|
||||
class HighPerformanceDoc extends SmartDataDbDoc<HighPerformanceDoc, HighPerformanceDoc> {
|
||||
@unI() // Unique index
|
||||
class HighPerformanceDoc extends SmartDataDbDoc<
|
||||
HighPerformanceDoc,
|
||||
HighPerformanceDoc
|
||||
> {
|
||||
@unI() // Unique index
|
||||
public id: string;
|
||||
|
||||
@index() // Single field index
|
||||
@index() // Single field index
|
||||
public userId: string;
|
||||
|
||||
@index({ sparse: true }) // Sparse index for optional fields
|
||||
@index({ sparse: true }) // Sparse index for optional fields
|
||||
public deletedAt?: Date;
|
||||
|
||||
@index({
|
||||
unique: false,
|
||||
background: true, // Non-blocking index creation
|
||||
expireAfterSeconds: 86400 // TTL index
|
||||
background: true, // Non-blocking index creation
|
||||
expireAfterSeconds: 86400, // TTL index
|
||||
})
|
||||
public sessionToken: string;
|
||||
|
||||
// Compound indexes for complex queries
|
||||
static async createIndexes() {
|
||||
await this.collection.createIndex(
|
||||
{ userId: 1, createdAt: -1 }, // Compound index
|
||||
{ name: 'user_activity_idx' }
|
||||
{ userId: 1, createdAt: -1 }, // Compound index
|
||||
{ name: 'user_activity_idx' },
|
||||
);
|
||||
|
||||
// Text index for search
|
||||
await this.collection.createIndex(
|
||||
{ title: 'text', content: 'text' },
|
||||
{ weights: { title: 10, content: 5 } }
|
||||
{ weights: { title: 10, content: 5 } },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -739,18 +732,18 @@ const db = new SmartdataDb({
|
||||
mongoDbName: 'myapp',
|
||||
|
||||
// Connection pool optimization
|
||||
maxPoolSize: 100, // Maximum connections
|
||||
minPoolSize: 10, // Minimum connections to maintain
|
||||
maxIdleTimeMS: 300000, // Close idle connections after 5 minutes
|
||||
waitQueueTimeoutMS: 5000, // Max time to wait for available connection
|
||||
maxPoolSize: 100, // Maximum connections
|
||||
minPoolSize: 10, // Minimum connections to maintain
|
||||
maxIdleTimeMS: 300000, // Close idle connections after 5 minutes
|
||||
waitQueueTimeoutMS: 5000, // Max time to wait for available connection
|
||||
|
||||
// Server selection
|
||||
serverSelectionTimeoutMS: 30000, // Timeout for selecting a server
|
||||
heartbeatFrequencyMS: 10000, // How often to check server status
|
||||
serverSelectionTimeoutMS: 30000, // Timeout for selecting a server
|
||||
heartbeatFrequencyMS: 10000, // How often to check server status
|
||||
|
||||
// Socket settings
|
||||
socketTimeoutMS: 360000, // Socket timeout (6 minutes)
|
||||
family: 4, // Force IPv4
|
||||
socketTimeoutMS: 360000, // Socket timeout (6 minutes)
|
||||
family: 4, // Force IPv4
|
||||
});
|
||||
```
|
||||
|
||||
@@ -759,6 +752,7 @@ const db = new SmartdataDb({
|
||||
### 1. Always Use TypeScript
|
||||
|
||||
SmartData is built for TypeScript. Using JavaScript means missing out on:
|
||||
|
||||
- Compile-time query validation
|
||||
- IntelliSense for MongoDB operators
|
||||
- Type-safe document updates
|
||||
@@ -785,7 +779,7 @@ await session.withTransaction(async () => {
|
||||
});
|
||||
|
||||
// ❌ Bad: Multiple operations without transactions
|
||||
await debitAccount(fromAccount, amount); // What if this fails?
|
||||
await debitAccount(fromAccount, amount); // What if this fails?
|
||||
await creditAccount(toAccount, amount);
|
||||
```
|
||||
|
||||
@@ -799,7 +793,7 @@ await cursor.forEach(async (doc) => {
|
||||
});
|
||||
|
||||
// ❌ Bad: Loading everything into memory
|
||||
const allDocs = await LargeCollection.getInstances({}); // Could OOM!
|
||||
const allDocs = await LargeCollection.getInstances({}); // Could OOM!
|
||||
```
|
||||
|
||||
### 5. Implement Proper Error Handling
|
||||
@@ -819,7 +813,7 @@ try {
|
||||
|
||||
// ❌ Bad: Ignoring errors
|
||||
const user = await User.getInstance({ id: userId });
|
||||
await processUser(user); // What if user is null?
|
||||
await processUser(user); // What if user is null?
|
||||
```
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
@@ -854,17 +848,17 @@ Always clean up resources:
|
||||
// Watchers
|
||||
const watcher = await User.watch({});
|
||||
// ... use watcher
|
||||
await watcher.close(); // Always close!
|
||||
await watcher.close(); // Always close!
|
||||
|
||||
// Cursors
|
||||
const cursor = await User.getCursor({});
|
||||
// ... use cursor
|
||||
await cursor.close(); // Always close!
|
||||
await cursor.close(); // Always close!
|
||||
|
||||
// Sessions
|
||||
const session = db.startSession();
|
||||
// ... use session
|
||||
await session.endSession(); // Always end!
|
||||
await session.endSession(); // Always end!
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
import * as smartdata from '../ts/index.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// TODO: Decorator support during testing for bun and deno in @git.zone/tstest
|
||||
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { Qenv } from '@push.rocks/qenv';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import type * as taskbuffer from '@push.rocks/taskbuffer';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { Qenv } from '@push.rocks/qenv';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// TODO: Decorator support during testing for bun and deno in @git.zone/tstest
|
||||
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { Qenv } from '@push.rocks/qenv';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import * as smartdata from '../ts/index.js';
|
||||
import { searchable } from '../ts/classes.doc.js';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { Qenv } from '@push.rocks/qenv';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { tap, expect } from '@push.rocks/tapbundle';
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { Qenv } from '@push.rocks/qenv';
|
||||
import * as smartmongo from '@push.rocks/smartmongo';
|
||||
import { smartunique } from '../ts/plugins.js';
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartdata',
|
||||
version: '7.1.0',
|
||||
version: '7.1.1',
|
||||
description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.'
|
||||
}
|
||||
|
||||
@@ -174,8 +174,8 @@ export class SmartdataCollection<T> {
|
||||
/**
|
||||
* the collection that is used
|
||||
*/
|
||||
public mongoDbCollection: plugins.mongodb.Collection;
|
||||
public objectValidation: IDocValidationFunc<T> = null;
|
||||
public mongoDbCollection!: plugins.mongodb.Collection;
|
||||
public objectValidation: IDocValidationFunc<T> | null = null;
|
||||
public collectionName: string;
|
||||
public smartdataDb: SmartdataDb;
|
||||
public uniqueIndexes: string[] = [];
|
||||
@@ -330,7 +330,7 @@ export class SmartdataCollection<T> {
|
||||
);
|
||||
const smartdataWatcher = new SmartdataDbWatcher(
|
||||
changeStream,
|
||||
smartdataDbDocArg,
|
||||
smartdataDbDocArg!,
|
||||
{ bufferTimeMs },
|
||||
);
|
||||
await smartdataWatcher.readyDeferred.promise;
|
||||
@@ -353,7 +353,7 @@ export class SmartdataCollection<T> {
|
||||
this.createRegularIndexes(dbDocArg.regularIndexes);
|
||||
}
|
||||
|
||||
const saveableObject = await dbDocArg.createSavableObject();
|
||||
const saveableObject = await dbDocArg.createSavableObject() as any;
|
||||
const result = await this.mongoDbCollection.insertOne(saveableObject, { session: opts?.session });
|
||||
return result;
|
||||
}
|
||||
@@ -368,7 +368,7 @@ export class SmartdataCollection<T> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
const identifiableObject = await dbDocArg.createIdentifiableObject();
|
||||
const saveableObject = await dbDocArg.createSavableObject();
|
||||
const saveableObject = await dbDocArg.createSavableObject() as any;
|
||||
const updateableObject: any = {};
|
||||
for (const key of Object.keys(saveableObject)) {
|
||||
if (identifiableObject[key]) {
|
||||
|
||||
@@ -12,8 +12,8 @@ export type TConnectionStatus = 'initial' | 'disconnected' | 'connected' | 'fail
|
||||
|
||||
export class SmartdataDb {
|
||||
smartdataOptions: plugins.tsclass.database.IMongoDescriptor;
|
||||
mongoDbClient: plugins.mongodb.MongoClient;
|
||||
mongoDb: plugins.mongodb.Db;
|
||||
mongoDbClient!: plugins.mongodb.MongoClient;
|
||||
mongoDb!: plugins.mongodb.Db;
|
||||
status: TConnectionStatus;
|
||||
statusConnectedDeferred = plugins.smartpromise.defer();
|
||||
smartdataCollectionMap = new plugins.lik.ObjectMap<SmartdataCollection<any>>();
|
||||
@@ -51,8 +51,8 @@ export class SmartdataDb {
|
||||
.replace('<user>', encodedUser)
|
||||
.replace('<PASSWORD>', encodedPass)
|
||||
.replace('<password>', encodedPass)
|
||||
.replace('<DBNAME>', this.smartdataOptions.mongoDbName)
|
||||
.replace('<dbname>', this.smartdataOptions.mongoDbName);
|
||||
.replace('<DBNAME>', this.smartdataOptions.mongoDbName || '')
|
||||
.replace('<dbname>', this.smartdataOptions.mongoDbName || '');
|
||||
|
||||
const clientOptions: plugins.mongodb.MongoClientOptions = {
|
||||
maxPoolSize: (this.smartdataOptions as any).maxPoolSize ?? 100,
|
||||
@@ -70,7 +70,7 @@ export class SmartdataDb {
|
||||
} catch (error) {
|
||||
this.status = 'disconnected';
|
||||
this.statusConnectedDeferred.reject(error);
|
||||
logger.log('error', `Failed to connect to database ${this.smartdataOptions.mongoDbName}: ${error.message}`);
|
||||
logger.log('error', `Failed to connect to database ${this.smartdataOptions.mongoDbName}: ${(error as Error).message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import { logger } from './logging.js';
|
||||
export class DistributedClass extends SmartDataDbDoc<DistributedClass, DistributedClass> {
|
||||
// INSTANCE
|
||||
@unI()
|
||||
public id: string;
|
||||
public id!: string;
|
||||
|
||||
@svDb()
|
||||
public data: {
|
||||
public data!: {
|
||||
status: 'initializing' | 'bidding' | 'settled' | 'stopped';
|
||||
biddingShortcode?: string;
|
||||
biddingStartTime?: number;
|
||||
@@ -40,8 +40,8 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
||||
public readyPromise: Promise<any>;
|
||||
public db: SmartdataDb;
|
||||
private asyncExecutionStack = new plugins.lik.AsyncExecutionStack();
|
||||
public ownInstance: DistributedClass;
|
||||
public distributedWatcher: SmartdataDbWatcher<DistributedClass>;
|
||||
public ownInstance!: DistributedClass;
|
||||
public distributedWatcher!: SmartdataDbWatcher<DistributedClass>;
|
||||
|
||||
constructor(dbArg: SmartdataDb) {
|
||||
super();
|
||||
@@ -163,8 +163,8 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
||||
} else if (
|
||||
(await DistributedClass.getInstances({})).find((instanceArg) => {
|
||||
return instanceArg.data.status === 'bidding' &&
|
||||
instanceArg.data.biddingStartTime <= Date.now() - 4000 &&
|
||||
instanceArg.data.biddingStartTime >= Date.now() - 30000;
|
||||
instanceArg.data.biddingStartTime! <= Date.now() - 4000 &&
|
||||
instanceArg.data.biddingStartTime! >= Date.now() - 30000;
|
||||
})
|
||||
) {
|
||||
logger.log('info', 'too late to the bidding party... waiting for next round.');
|
||||
@@ -191,7 +191,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
||||
logger.log('info', `found ${biddingInstances.length} bidding instances...`);
|
||||
this.ownInstance.data.elected = true;
|
||||
for (const biddingInstance of biddingInstances) {
|
||||
if (biddingInstance.data.biddingShortcode < this.ownInstance.data.biddingShortcode) {
|
||||
if (biddingInstance.data.biddingShortcode! < this.ownInstance.data.biddingShortcode!) {
|
||||
this.ownInstance.data.elected = false;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +270,7 @@ export class SmartdataDistributedCoordinator extends plugins.taskbuffer.distribu
|
||||
});
|
||||
if (!result) {
|
||||
logger.log('warn', 'no result found for task request...');
|
||||
return null;
|
||||
return null as any;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
||||
convertFilterForMongoDb(filterArg),
|
||||
{ session: opts?.session },
|
||||
);
|
||||
const returnArray = [];
|
||||
const returnArray: T[] = [];
|
||||
for (const foundDoc of foundDocs) {
|
||||
const newInstance: T = (this as any).createInstanceFromMongoDbNativeDoc(foundDoc);
|
||||
returnArray.push(newInstance);
|
||||
@@ -510,7 +510,7 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
||||
const newInstance: T = (this as any).createInstanceFromMongoDbNativeDoc(foundDoc);
|
||||
return newInstance;
|
||||
} else {
|
||||
return null;
|
||||
return null as any;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,12 +833,12 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
||||
/**
|
||||
* name
|
||||
*/
|
||||
public name: string;
|
||||
public name!: string;
|
||||
|
||||
/**
|
||||
* primary id in the database
|
||||
*/
|
||||
public dbDocUniqueId: string;
|
||||
public dbDocUniqueId!: string;
|
||||
|
||||
/**
|
||||
* class constructor
|
||||
@@ -898,7 +898,7 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
public saveDeep(savedMapArg: plugins.lik.ObjectMap<SmartDataDbDoc<any, any>> = null) {
|
||||
public saveDeep(savedMapArg?: plugins.lik.ObjectMap<SmartDataDbDoc<any, any>>) {
|
||||
if (!savedMapArg) {
|
||||
savedMapArg = new plugins.lik.ObjectMap<SmartDataDbDoc<any, any>>();
|
||||
}
|
||||
|
||||
@@ -15,19 +15,19 @@ export class EasyStore<T> {
|
||||
@Collection(() => this.smartdataDbRef)
|
||||
class SmartdataEasyStore extends SmartDataDbDoc<SmartdataEasyStore, SmartdataEasyStore> {
|
||||
@unI()
|
||||
public nameId: string;
|
||||
public nameId!: string;
|
||||
|
||||
@svDb()
|
||||
public ephemeral: {
|
||||
public ephemeral!: {
|
||||
activated: boolean;
|
||||
timeout: number;
|
||||
};
|
||||
|
||||
@svDb()
|
||||
lastEdit: number;
|
||||
lastEdit!: number;
|
||||
|
||||
@svDb()
|
||||
public data: Partial<T>;
|
||||
public data!: Partial<T>;
|
||||
}
|
||||
return SmartdataEasyStore;
|
||||
})();
|
||||
@@ -37,7 +37,7 @@ export class EasyStore<T> {
|
||||
this.nameId = nameIdArg;
|
||||
}
|
||||
|
||||
private easyStorePromise: Promise<InstanceType<typeof this.easyStoreClass>>;
|
||||
private easyStorePromise!: Promise<InstanceType<typeof this.easyStoreClass>>;
|
||||
private async getEasyStore(): Promise<InstanceType<typeof this.easyStoreClass>> {
|
||||
if (this.easyStorePromise) {
|
||||
return this.easyStorePromise;
|
||||
|
||||
@@ -536,7 +536,7 @@ export class LuceneToMongoTransformer {
|
||||
const searchTerm = rightQuery.$text.$search.replace(/"/g, '');
|
||||
|
||||
// Determine the fields to apply the negation to
|
||||
const notConditions = [];
|
||||
const notConditions: any[] = [];
|
||||
|
||||
for (const field in leftQuery) {
|
||||
if (field !== '$or' && field !== '$and') {
|
||||
|
||||
@@ -13,7 +13,7 @@ export class SmartdataDbWatcher<T = any> extends EventEmitter {
|
||||
public readyDeferred = plugins.smartpromise.defer();
|
||||
|
||||
// INSTANCE
|
||||
private changeStream: plugins.mongodb.ChangeStream<T>;
|
||||
private changeStream: plugins.mongodb.ChangeStream<any>;
|
||||
private rawSubject: plugins.smartrx.rxjs.Subject<T>;
|
||||
/** Emits change documents (or arrays of documents if buffered) */
|
||||
public changeSubject: any;
|
||||
@@ -23,7 +23,7 @@ export class SmartdataDbWatcher<T = any> extends EventEmitter {
|
||||
* @param opts.bufferTimeMs optional milliseconds to buffer events via RxJS
|
||||
*/
|
||||
constructor(
|
||||
changeStreamArg: plugins.mongodb.ChangeStream<T>,
|
||||
changeStreamArg: plugins.mongodb.ChangeStream<any>,
|
||||
smartdataDbDocArg: typeof SmartDataDbDoc,
|
||||
opts?: { bufferTimeMs?: number },
|
||||
) {
|
||||
@@ -37,14 +37,14 @@ export class SmartdataDbWatcher<T = any> extends EventEmitter {
|
||||
}
|
||||
this.changeStream = changeStreamArg;
|
||||
this.changeStream.on('change', async (item: any) => {
|
||||
let docInstance: T = null;
|
||||
let docInstance: T | null = null;
|
||||
if (item.fullDocument) {
|
||||
docInstance = smartdataDbDocArg.createInstanceFromMongoDbNativeDoc(
|
||||
item.fullDocument
|
||||
) as any as T;
|
||||
}
|
||||
// Notify subscribers
|
||||
this.rawSubject.next(docInstance);
|
||||
this.rawSubject.next(docInstance as T);
|
||||
this.emit('change', docInstance);
|
||||
});
|
||||
// Signal readiness after one tick
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
"moduleResolution": "NodeNext",
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {}
|
||||
"types": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"dist_*/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
"exclude": ["dist_*/**/*.d.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user