Compare commits

..

16 Commits

Author SHA1 Message Date
27c1500db5 v7.1.0
Some checks failed
Default (tags) / security (push) Successful in 30s
Default (tags) / test (push) Failing after 52s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-02-26 17:01:37 +00:00
3bbb78add8 feat(config): normalize npmextra.json to namespaced keys and add CI/release configuration 2026-02-26 17:01:37 +00:00
9d779329e1 v7.0.16
Some checks failed
Default (tags) / security (push) Successful in 48s
Default (tags) / test (push) Failing after 55s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2026-02-26 16:58:04 +00:00
cdc6b029af fix(mongodb): set default socketTimeoutMS to 30000ms in MongoClient options to prevent hung operations from holding connections 2026-02-26 16:58:04 +00:00
39c0ba7bea v7.0.15
Some checks failed
Default (tags) / security (push) Successful in 51s
Default (tags) / test (push) Failing after 51s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-12-01 11:48:28 +00:00
e4faca88ba fix(classes.doc): Avoid emitting instance fields for collection and manager to preserve decorator-defined prototype getters 2025-12-01 11:48:28 +00:00
40bc408d8f v7.0.14
Some checks failed
Default (tags) / security (push) Successful in 52s
Default (tags) / test (push) Failing after 50s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-11-28 15:45:15 +00:00
3c8308561e fix(classes.collection): Centralize TC39 decorator metadata initialization and use context.metadata in class decorators 2025-11-28 15:45:15 +00:00
49b121aa5b v7.0.13
Some checks failed
Default (tags) / security (push) Successful in 41s
Default (tags) / test (push) Failing after 49s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-11-28 11:40:52 +00:00
514d3dbd29 fix(classes.doc): Remove noisy debug logging from decorators and serialization logic 2025-11-28 11:40:52 +00:00
2b7316dc46 v7.0.12
Some checks failed
Default (tags) / security (push) Successful in 54s
Default (tags) / test (push) Failing after 1m16s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-11-28 11:27:36 +00:00
11a1345891 fix(collection): Ensure TC39 decorator metadata is initialized on both original and decorated constructors/prototypes and add debug logging 2025-11-28 11:27:36 +00:00
2fe3a72eaf 7.0.11
Some checks failed
Default (tags) / security (push) Successful in 56s
Default (tags) / test (push) Failing after 1m18s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-11-28 11:19:45 +00:00
fb7e82557b chore: Remove debug logging from Collection decorator 2025-11-28 11:19:44 +00:00
8a3425e554 7.0.10
Some checks failed
Default (tags) / security (push) Successful in 58s
Default (tags) / test (push) Failing after 1m20s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-11-28 11:17:25 +00:00
d2092cc5f3 chore(debug): Add metadata debug logging to Collection decorator 2025-11-28 11:17:25 +00:00
8 changed files with 160 additions and 216 deletions

View File

@@ -1,5 +1,51 @@
# Changelog # Changelog
## 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).
- Moved tsdoc legal text under @git.zone/tsdoc.
- Added release configuration with registries (https://verdaccio.lossless.digital and https://registry.npmjs.org) and accessLevel public under @git.zone/cli.
- Added @git.zone/tsdocker CI/docker settings and @ship.zone/szci npm registry/tooling settings.
- 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
- Helps prevent hung operations from indefinitely holding connections by enforcing a 30s socket timeout
- 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
## 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
- Removed debug logger calls from svDb decorator initialization and svDb options handling
- Removed debug logger calls from unI and index decorator initializers
- 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
- 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) ## 2025-11-28 - 7.0.9 - fix(classes.collection)
Fix closure bug in Collection decorator by defining collection getter on original constructor and prototype Fix closure bug in Collection decorator by defining collection getter on original constructor and prototype

View File

@@ -1,15 +1,5 @@
{ {
"npmdocker": { "@git.zone/cli": {
"baseImage": "hosttoday/ht-docker-node:mongo",
"command": "npmci test stable",
"dockerSock": false
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public",
"npmRegistryUrl": "registry.npmjs.org"
},
"gitzone": {
"projectType": "npm", "projectType": "npm",
"module": { "module": {
"githost": "code.foss.global", "githost": "code.foss.global",
@@ -28,9 +18,25 @@
"custom data types", "custom data types",
"ODM" "ODM"
] ]
},
"release": {
"registries": [
"https://verdaccio.lossless.digital",
"https://registry.npmjs.org"
],
"accessLevel": "public"
} }
}, },
"tsdoc": { "@git.zone/tsdoc": {
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n" "legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
},
"@git.zone/tsdocker": {
"baseImage": "hosttoday/ht-docker-node:mongo",
"command": "npmci test stable",
"dockerSock": false
},
"@ship.zone/szci": {
"npmGlobalTools": [],
"npmRegistryUrl": "registry.npmjs.org"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@push.rocks/smartdata", "name": "@push.rocks/smartdata",
"version": "7.0.9", "version": "7.1.0",
"private": false, "private": false,
"description": "An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.", "description": "An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.",
"exports": { "exports": {

View File

@@ -78,3 +78,21 @@ All 157 tests passing across 10 test files:
3. `Symbol.metadata` on constructors is read-only (managed by runtime) 3. `Symbol.metadata` on constructors is read-only (managed by runtime)
4. Field decorators run before class decorators (guaranteed order) 4. Field decorators run before class decorators (guaranteed order)
5. TypeScript 5.2+ has built-in TC39 decorator support 5. TypeScript 5.2+ has built-in TC39 decorator support
## 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
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

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartdata', name: '@push.rocks/smartdata',
version: '7.0.9', version: '7.1.0',
description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.' description: 'An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.'
} }

View File

@@ -21,6 +21,42 @@ export type TDelayed<TDelayedArg> = () => TDelayedArg;
const collectionFactory = new CollectionFactory(); const collectionFactory = new CollectionFactory();
/**
* Initialize prototype and constructor properties from TC39 decorator metadata.
* Shared by both Collection and managed decorators.
*/
function initializeDecoratorMetadata(
constructor: { new (...args: any[]): any; prototype: any },
metadata: any
): void {
if (!metadata) return;
const proto = constructor.prototype;
const ctor = constructor as any;
// Prototype properties (instance-level)
if (metadata.globalSaveableProperties && !proto.globalSaveableProperties) {
proto.globalSaveableProperties = [...metadata.globalSaveableProperties];
}
if (metadata.saveableProperties && !proto.saveableProperties) {
proto.saveableProperties = [...metadata.saveableProperties];
}
if (metadata.uniqueIndexes && !proto.uniqueIndexes) {
proto.uniqueIndexes = [...metadata.uniqueIndexes];
}
if (metadata.regularIndexes && !proto.regularIndexes) {
proto.regularIndexes = [...metadata.regularIndexes];
}
// Constructor properties (static-level)
if (metadata.searchableFields && !Array.isArray(ctor.searchableFields)) {
ctor.searchableFields = [...metadata.searchableFields];
}
if (metadata._svDbOptions && !ctor._svDbOptions) {
ctor._svDbOptions = { ...metadata._svDbOptions };
}
}
/** /**
* This is a decorator that will tell the decorated class what dbTable to use * This is a decorator that will tell the decorated class what dbTable to use
* @param dbArg * @param dbArg
@@ -31,9 +67,7 @@ export function Collection(dbArg: SmartdataDb | TDelayed<SmartdataDb>) {
throw new Error('Collection can only decorate classes'); throw new Error('Collection can only decorate classes');
} }
// Capture original constructor for _svDbOptions forwarding const constructor = value as { new (...args: any[]): any } & { className?: string };
const originalConstructor = value as any;
const constructor = value as { new (...args: any[]): any };
const getCollection = () => { const getCollection = () => {
if (!(dbArg instanceof SmartdataDb)) { if (!(dbArg instanceof SmartdataDb)) {
@@ -42,92 +76,30 @@ export function Collection(dbArg: SmartdataDb | TDelayed<SmartdataDb>) {
const coll = collectionFactory.getCollection(constructor.name, dbArg); const coll = collectionFactory.getCollection(constructor.name, dbArg);
// Attach document constructor for searchableFields lookup // Attach document constructor for searchableFields lookup
if (coll && !(coll as any).docCtor) { if (coll && !(coll as any).docCtor) {
(coll as any).docCtor = decoratedClass; (coll as any).docCtor = constructor;
} }
return coll; return coll;
}; };
const decoratedClass = class extends constructor { // Add static className property directly on the constructor
public static className = constructor.name; (constructor as any).className = constructor.name;
public static get collection() {
return getCollection();
}
public get collection() {
return getCollection();
}
};
// Ensure instance getter works in Deno by defining it on the prototype // Define collection getter on constructor (static access)
Object.defineProperty(decoratedClass.prototype, 'collection', {
get: getCollection,
enumerable: false,
configurable: true
});
// Closure fix: When class methods reference the class name (e.g., `User.collection`),
// they get the original constructor via closure, not the decorated class.
// Define collection getter on the original constructor.
Object.defineProperty(constructor, 'collection', { Object.defineProperty(constructor, 'collection', {
get: getCollection, get: getCollection,
enumerable: false, enumerable: false,
configurable: true configurable: true
}); });
// Define collection getter on prototype (instance access)
Object.defineProperty(constructor.prototype, 'collection', { Object.defineProperty(constructor.prototype, 'collection', {
get: getCollection, get: getCollection,
enumerable: false, enumerable: false,
configurable: true configurable: true
}); });
// Deno compatibility note: Property decorators set properties on the prototype. initializeDecoratorMetadata(constructor, context.metadata);
// Since we removed instance property declarations from SmartDataDbDoc, return constructor as any;
// the decorator-set prototype properties are now accessible without shadowing.
// No manual forwarding needed - natural prototype inheritance works!
// Point to original constructor's _svDbOptions
Object.defineProperty(decoratedClass, '_svDbOptions', {
get() { return originalConstructor._svDbOptions; },
set(value) { originalConstructor._svDbOptions = value; },
configurable: true
});
// Initialize prototype properties from context.metadata (TC39 decorator metadata)
// This ensures prototype properties are available before any instance is created
const metadata = context.metadata as any;
if (metadata) {
const proto = decoratedClass.prototype;
// Initialize globalSaveableProperties
if (metadata.globalSaveableProperties && !proto.globalSaveableProperties) {
proto.globalSaveableProperties = [...metadata.globalSaveableProperties];
}
// Initialize saveableProperties
if (metadata.saveableProperties && !proto.saveableProperties) {
proto.saveableProperties = [...metadata.saveableProperties];
}
// Initialize uniqueIndexes
if (metadata.uniqueIndexes && !proto.uniqueIndexes) {
proto.uniqueIndexes = [...metadata.uniqueIndexes];
}
// Initialize regularIndexes
if (metadata.regularIndexes && !proto.regularIndexes) {
proto.regularIndexes = [...metadata.regularIndexes];
}
// Initialize searchableFields on constructor (not prototype)
if (metadata.searchableFields && !Array.isArray((decoratedClass as any).searchableFields)) {
(decoratedClass as any).searchableFields = [...metadata.searchableFields];
}
// Initialize _svDbOptions from metadata
if (metadata._svDbOptions && !originalConstructor._svDbOptions) {
originalConstructor._svDbOptions = { ...metadata._svDbOptions };
}
}
return decoratedClass as any;
}; };
} }
@@ -150,133 +122,46 @@ export function managed<TManager extends IManager>(managerArg?: TManager | TDela
throw new Error('managed can only decorate classes'); throw new Error('managed can only decorate classes');
} }
const constructor = value as { new (...args: any[]): any }; const constructor = value as { new (...args: any[]): any } & { className?: string };
(constructor as any).className = constructor.name;
const decoratedClass = class extends constructor { // Resolution helpers (capture managerArg via closure)
public static className = constructor.name; const getManager = (defaultManagerFn: () => TManager): TManager => {
public static get collection() { if (!managerArg) return defaultManagerFn();
let dbArg: SmartdataDb; if (managerArg['db']) return managerArg as TManager;
if (!managerArg) { return (managerArg as TDelayed<TManager>)();
dbArg = this.prototype.defaultManager.db;
} else if (managerArg['db']) {
dbArg = (managerArg as TManager).db;
} else {
dbArg = (managerArg as TDelayed<TManager>)().db;
}
return collectionFactory.getCollection(constructor.name, dbArg);
}
public get collection() {
let dbArg: SmartdataDb;
if (!managerArg) {
//console.log(this.defaultManager.db);
//process.exit(0)
dbArg = this.defaultManager.db;
} else if (managerArg['db']) {
dbArg = (managerArg as TManager).db;
} else {
dbArg = (managerArg as TDelayed<TManager>)().db;
}
return collectionFactory.getCollection(constructor.name, dbArg);
}
public static get manager() {
let manager: TManager;
if (!managerArg) {
manager = this.prototype.defaultManager;
} else if (managerArg['db']) {
manager = managerArg as TManager;
} else {
manager = (managerArg as TDelayed<TManager>)();
}
return manager;
}
public get manager() {
let manager: TManager;
if (!managerArg) {
manager = this.defaultManager;
} else if (managerArg['db']) {
manager = managerArg as TManager;
} else {
manager = (managerArg as TDelayed<TManager>)();
}
return manager;
}
}; };
// Closure fix: When class methods reference the class name (e.g., `User.collection`), const getDb = (defaultManagerFn: () => TManager): SmartdataDb => {
// they get the original constructor via closure, not the decorated class. return getManager(defaultManagerFn).db;
// Define collection/manager getters on the original constructor.
const getCollectionStatic = function(this: any) {
let dbArg: SmartdataDb;
if (!managerArg) {
dbArg = this.prototype.defaultManager.db;
} else if (managerArg['db']) {
dbArg = (managerArg as TManager).db;
} else {
dbArg = (managerArg as TDelayed<TManager>)().db;
}
return collectionFactory.getCollection(constructor.name, dbArg);
};
const getCollectionInstance = function(this: any) {
let dbArg: SmartdataDb;
if (!managerArg) {
dbArg = this.defaultManager.db;
} else if (managerArg['db']) {
dbArg = (managerArg as TManager).db;
} else {
dbArg = (managerArg as TDelayed<TManager>)().db;
}
return collectionFactory.getCollection(constructor.name, dbArg);
}; };
// Static getters
Object.defineProperty(constructor, 'collection', { Object.defineProperty(constructor, 'collection', {
get: getCollectionStatic, get(this: any) { return collectionFactory.getCollection(constructor.name, getDb(() => this.prototype.defaultManager)); },
enumerable: false, enumerable: false,
configurable: true configurable: true
}); });
Object.defineProperty(constructor, 'manager', {
get(this: any) { return getManager(() => this.prototype.defaultManager); },
enumerable: false,
configurable: true
});
// Instance getters
Object.defineProperty(constructor.prototype, 'collection', { Object.defineProperty(constructor.prototype, 'collection', {
get: getCollectionInstance, get(this: any) { return collectionFactory.getCollection(constructor.name, getDb(() => this.defaultManager)); },
enumerable: false,
configurable: true
});
Object.defineProperty(constructor.prototype, 'manager', {
get(this: any) { return getManager(() => this.defaultManager); },
enumerable: false, enumerable: false,
configurable: true configurable: true
}); });
// Initialize prototype properties from context.metadata (TC39 decorator metadata) initializeDecoratorMetadata(constructor, context.metadata);
// This ensures prototype properties are available before any instance is created return constructor as any;
const originalConstructor = value as any;
const metadata = context.metadata as any;
if (metadata) {
const proto = decoratedClass.prototype;
// Initialize globalSaveableProperties
if (metadata.globalSaveableProperties && !proto.globalSaveableProperties) {
proto.globalSaveableProperties = [...metadata.globalSaveableProperties];
}
// Initialize saveableProperties
if (metadata.saveableProperties && !proto.saveableProperties) {
proto.saveableProperties = [...metadata.saveableProperties];
}
// Initialize uniqueIndexes
if (metadata.uniqueIndexes && !proto.uniqueIndexes) {
proto.uniqueIndexes = [...metadata.uniqueIndexes];
}
// Initialize regularIndexes
if (metadata.regularIndexes && !proto.regularIndexes) {
proto.regularIndexes = [...metadata.regularIndexes];
}
// Initialize searchableFields on constructor (not prototype)
if (metadata.searchableFields && !Array.isArray((decoratedClass as any).searchableFields)) {
(decoratedClass as any).searchableFields = [...metadata.searchableFields];
}
// Initialize _svDbOptions from metadata
if (metadata._svDbOptions && !originalConstructor._svDbOptions) {
originalConstructor._svDbOptions = { ...metadata._svDbOptions };
}
}
return decoratedClass as any;
}; };
} }

View File

@@ -58,6 +58,7 @@ export class SmartdataDb {
maxPoolSize: (this.smartdataOptions as any).maxPoolSize ?? 100, maxPoolSize: (this.smartdataOptions as any).maxPoolSize ?? 100,
maxIdleTimeMS: (this.smartdataOptions as any).maxIdleTimeMS ?? 300000, // 5 minutes default maxIdleTimeMS: (this.smartdataOptions as any).maxIdleTimeMS ?? 300000, // 5 minutes default
serverSelectionTimeoutMS: (this.smartdataOptions as any).serverSelectionTimeoutMS ?? 30000, serverSelectionTimeoutMS: (this.smartdataOptions as any).serverSelectionTimeoutMS ?? 30000,
socketTimeoutMS: (this.smartdataOptions as any).socketTimeoutMS ?? 30000, // 30 seconds default — prevents hung operations from holding connections
retryWrites: true, retryWrites: true,
}; };

View File

@@ -51,8 +51,6 @@ export function globalSvDb() {
} }
metadata.globalSaveableProperties.push(String(context.name)); metadata.globalSaveableProperties.push(String(context.name));
logger.log('debug', `called globalSvDb() on metadata for property ${String(context.name)}`);
// Use addInitializer to ensure prototype arrays are set up once // Use addInitializer to ensure prototype arrays are set up once
context.addInitializer(function(this: any) { context.addInitializer(function(this: any) {
const proto = this.constructor.prototype; const proto = this.constructor.prototype;
@@ -61,7 +59,6 @@ export function globalSvDb() {
if (metadata && metadata.globalSaveableProperties && !proto.globalSaveableProperties) { if (metadata && metadata.globalSaveableProperties && !proto.globalSaveableProperties) {
// Initialize prototype array from metadata (runs once per class) // Initialize prototype array from metadata (runs once per class)
proto.globalSaveableProperties = [...metadata.globalSaveableProperties]; proto.globalSaveableProperties = [...metadata.globalSaveableProperties];
logger.log('debug', `initialized globalSaveableProperties with ${proto.globalSaveableProperties.length} properties`);
} }
}); });
}; };
@@ -103,8 +100,6 @@ export function svDb(options?: SvDbOptions) {
metadata._svDbOptions[propName] = options; metadata._svDbOptions[propName] = options;
} }
logger.log('debug', `called svDb() on metadata for property ${propName}`);
// Use addInitializer to ensure prototype arrays are set up once // Use addInitializer to ensure prototype arrays are set up once
context.addInitializer(function(this: any) { context.addInitializer(function(this: any) {
const proto = this.constructor.prototype; const proto = this.constructor.prototype;
@@ -114,7 +109,6 @@ export function svDb(options?: SvDbOptions) {
if (metadata && metadata.saveableProperties && !proto.saveableProperties) { if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
// Initialize prototype array from metadata (runs once per class) // Initialize prototype array from metadata (runs once per class)
proto.saveableProperties = [...metadata.saveableProperties]; proto.saveableProperties = [...metadata.saveableProperties];
logger.log('debug', `initialized saveableProperties with ${proto.saveableProperties.length} properties`);
} }
// Initialize svDbOptions from metadata // Initialize svDbOptions from metadata
@@ -187,8 +181,6 @@ export function unI() {
metadata.saveableProperties.push(propName); metadata.saveableProperties.push(propName);
} }
logger.log('debug', `called unI on metadata for property ${propName}`);
// Use addInitializer to ensure prototype arrays are set up once // Use addInitializer to ensure prototype arrays are set up once
context.addInitializer(function(this: any) { context.addInitializer(function(this: any) {
const proto = this.constructor.prototype; const proto = this.constructor.prototype;
@@ -196,7 +188,6 @@ export function unI() {
if (metadata && metadata.uniqueIndexes && !proto.uniqueIndexes) { if (metadata && metadata.uniqueIndexes && !proto.uniqueIndexes) {
proto.uniqueIndexes = [...metadata.uniqueIndexes]; proto.uniqueIndexes = [...metadata.uniqueIndexes];
logger.log('debug', `initialized uniqueIndexes with ${proto.uniqueIndexes.length} properties`);
} }
if (metadata && metadata.saveableProperties && !proto.saveableProperties) { if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
@@ -246,8 +237,6 @@ export function index(options?: IIndexOptions) {
metadata.saveableProperties.push(propName); metadata.saveableProperties.push(propName);
} }
logger.log('debug', `called index() on metadata for property ${propName}`);
// Use addInitializer to ensure prototype arrays are set up once // Use addInitializer to ensure prototype arrays are set up once
context.addInitializer(function(this: any) { context.addInitializer(function(this: any) {
const proto = this.constructor.prototype; const proto = this.constructor.prototype;
@@ -255,7 +244,6 @@ export function index(options?: IIndexOptions) {
if (metadata && metadata.regularIndexes && !proto.regularIndexes) { if (metadata && metadata.regularIndexes && !proto.regularIndexes) {
proto.regularIndexes = [...metadata.regularIndexes]; proto.regularIndexes = [...metadata.regularIndexes];
logger.log('debug', `initialized regularIndexes with ${proto.regularIndexes.length} indexes`);
} }
if (metadata && metadata.saveableProperties && !proto.saveableProperties) { if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
@@ -448,10 +436,10 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
* the collection object an Doc belongs to * the collection object an Doc belongs to
*/ */
public static collection: SmartdataCollection<any>; public static collection: SmartdataCollection<any>;
public collection: SmartdataCollection<any>; declare public collection: SmartdataCollection<any>;
public static defaultManager; public static defaultManager;
public static manager; public static manager;
public manager: TManager; declare public manager: TManager;
/** /**
* Helper to get collection with fallback to static for Deno compatibility * Helper to get collection with fallback to static for Deno compatibility