From 9e734a23a6e1756165b3de763a2a7bac637672ae Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 2 Apr 2026 13:20:53 +0200 Subject: [PATCH 1/4] fix(config): do not throw on missing ObjectTTL config --- src/collections/config/classes.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/collections/config/classes.ts b/src/collections/config/classes.ts index fdf28501..97cd8b18 100644 --- a/src/collections/config/classes.ts +++ b/src/collections/config/classes.ts @@ -76,10 +76,10 @@ export class MergeWithExisting { update.vectorizers?.vectorIndex.name === 'hnsw' ? MergeWithExisting.hnsw(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) : update.vectorizers?.vectorIndex.name === 'hfresh' - ? MergeWithExisting.hfresh(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) - : update.vectorizers?.vectorIndex.name === 'dynamic' - ? MergeWithExisting.dynamic(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) - : MergeWithExisting.flat(current.vectorIndexConfig, update.vectorizers.vectorIndex.config); + ? MergeWithExisting.hfresh(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) + : update.vectorizers?.vectorIndex.name === 'dynamic' + ? MergeWithExisting.dynamic(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) + : MergeWithExisting.flat(current.vectorIndexConfig, update.vectorizers.vectorIndex.config); } } return current; @@ -148,7 +148,7 @@ export class MergeWithExisting { } static objectTTL(current: WeaviateObjectTTLConfig, update: ObjectTTLConfigUpdate): WeaviateObjectTTLConfig { - if (current === undefined) throw Error('Object TTL config is missing from the class schema.'); + if (current === undefined) return current; return { enabled: update.enabled ?? current.enabled, deleteOn: update.deleteOn ?? current.deleteOn, @@ -184,10 +184,10 @@ export class MergeWithExisting { v.vectorIndex.name === 'hnsw' ? MergeWithExisting.hnsw(existing.vectorIndexConfig, v.vectorIndex.config) : v.vectorIndex.name === 'hfresh' - ? MergeWithExisting.hfresh(existing.vectorIndexConfig, v.vectorIndex.config) - : v.vectorIndex.name === 'dynamic' - ? MergeWithExisting.dynamic(existing.vectorIndexConfig, v.vectorIndex.config) - : MergeWithExisting.flat(existing.vectorIndexConfig, v.vectorIndex.config); + ? MergeWithExisting.hfresh(existing.vectorIndexConfig, v.vectorIndex.config) + : v.vectorIndex.name === 'dynamic' + ? MergeWithExisting.dynamic(existing.vectorIndexConfig, v.vectorIndex.config) + : MergeWithExisting.flat(existing.vectorIndexConfig, v.vectorIndex.config); } }); return current; From 37f2dee9a5b129050841a27f7a3d82fdf1207c4c Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 2 Apr 2026 14:11:30 +0200 Subject: [PATCH 2/4] fix(config): map object TTL deleteOn property names --- src/collections/config/utils.ts | 46 +++++++++++---------- test/collections/config/integration.test.ts | 10 ++--- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/collections/config/utils.ts b/src/collections/config/utils.ts index 9af0fe66..d377a74e 100644 --- a/src/collections/config/utils.ts +++ b/src/collections/config/utils.ts @@ -243,11 +243,11 @@ export const makeVectorsConfig = ( const vectorizersConfig = Array.isArray(configVectorizers) ? configVectorizers : [ - { - ...configVectorizers, - name: configVectorizers.name || 'default', - }, - ]; + { + ...configVectorizers, + name: configVectorizers.name || 'default', + }, + ]; vectorizersConfig.forEach((v) => { const vectorConfig: any = { vectorIndexConfig: parseVectorIndex(v.vectorIndex), @@ -367,18 +367,18 @@ class ConfigMapping { vectorizer: v.vectorizer === 'none' ? { - name: 'none', - config: undefined, - } + name: 'none', + config: undefined, + } : { - name: v.vectorizer, - config: v.moduleConfig - ? ({ - ...(v.moduleConfig[v.vectorizer] as any), - vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName, - } as VectorizerConfig) - : undefined, - }, + name: v.vectorizer, + config: v.moduleConfig + ? ({ + ...(v.moduleConfig[v.vectorizer] as any), + vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName, + } as VectorizerConfig) + : undefined, + }, indexConfig: ConfigMapping.vectorIndex(v.vectorIndexConfig, v.vectorIndexType), indexType: ConfigMapping.vectorIndexType(v.vectorIndexType), }, @@ -403,11 +403,15 @@ class ConfigMapping { return { enabled: false }; } return { + ...v, enabled: v.enabled ?? false, - deleteOn: v.deleteOn, + deleteOn: v.deleteOn == '_creationTimeUnix' + ? 'creationTime' + : v.deleteOn == '_lastUpdateTimeUnix' + ? 'updateTime' + : v.deleteOn, defaultTTLSeconds: v.defaultTtl, filterExpiredObjects: v.filterExpiredObjects, - ...v, }; } static multiTenancy(v?: WeaviateMultiTenancyConfig): MultiTenancyConfig { @@ -574,9 +578,9 @@ class ConfigMapping { ) { encoding = v.muvera.enabled ? { - type: 'muvera', - ...v.muvera, - } + type: 'muvera', + ...v.muvera, + } : undefined; } return { diff --git a/test/collections/config/integration.test.ts b/test/collections/config/integration.test.ts index ecb16447..8434a284 100644 --- a/test/collections/config/integration.test.ts +++ b/test/collections/config/integration.test.ts @@ -685,8 +685,8 @@ describe('Testing of the collection.config namespace', () => { .update({ propertyDescriptions: supportsUpdatingPropertyDescriptions ? { - testProp: 'This is a test property', - } + testProp: 'This is a test property', + } : undefined, vectorizers: weaviate.reconfigure.vectors.update({ vectorIndexConfig: weaviate.reconfigure.vectorIndex.hnsw({ @@ -1085,7 +1085,7 @@ describe('Testing of the collection.config namespace', () => { }); }); - requireAtLeast(1, 35, 0).it('should create and update Object TTL configuration', async () => { + requireAtLeast(1, 35, 0).it.only('should create and update Object TTL configuration', async () => { const collectionName = 'TestObjectTTL'; const collection = await client.collections.create({ name: collectionName, @@ -1095,7 +1095,7 @@ describe('Testing of the collection.config namespace', () => { const created = await collection.config.get(); expect(created.objectTTL).toBeDefined(); expect(created.objectTTL.enabled).toEqual(true); - expect(created.objectTTL.deleteOn).toEqual('_creationTimeUnix'); + expect(created.objectTTL.deleteOn).toEqual('creationTime'); expect(created.objectTTL.defaultTTLSeconds).toEqual(120); await collection.config.update({ @@ -1105,7 +1105,7 @@ describe('Testing of the collection.config namespace', () => { const updated = await collection.config.get(); expect(updated.objectTTL).toBeDefined(); expect(updated.objectTTL.enabled).toEqual(true); - expect(updated.objectTTL.deleteOn).toEqual('_lastUpdateTimeUnix'); + expect(updated.objectTTL.deleteOn).toEqual('updateTime'); expect(updated.objectTTL.defaultTTLSeconds).toEqual(400); await collection.config.update({ From ffaae60800d5475f9d54113f866f9252d6b2ead1 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 2 Apr 2026 14:16:51 +0200 Subject: [PATCH 3/4] chore: lint & format --- src/collections/config/classes.ts | 16 ++++---- src/collections/config/utils.ts | 45 +++++++++++---------- test/collections/config/integration.test.ts | 4 +- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/collections/config/classes.ts b/src/collections/config/classes.ts index 97cd8b18..58af2c4e 100644 --- a/src/collections/config/classes.ts +++ b/src/collections/config/classes.ts @@ -76,10 +76,10 @@ export class MergeWithExisting { update.vectorizers?.vectorIndex.name === 'hnsw' ? MergeWithExisting.hnsw(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) : update.vectorizers?.vectorIndex.name === 'hfresh' - ? MergeWithExisting.hfresh(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) - : update.vectorizers?.vectorIndex.name === 'dynamic' - ? MergeWithExisting.dynamic(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) - : MergeWithExisting.flat(current.vectorIndexConfig, update.vectorizers.vectorIndex.config); + ? MergeWithExisting.hfresh(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) + : update.vectorizers?.vectorIndex.name === 'dynamic' + ? MergeWithExisting.dynamic(current.vectorIndexConfig, update.vectorizers.vectorIndex.config) + : MergeWithExisting.flat(current.vectorIndexConfig, update.vectorizers.vectorIndex.config); } } return current; @@ -184,10 +184,10 @@ export class MergeWithExisting { v.vectorIndex.name === 'hnsw' ? MergeWithExisting.hnsw(existing.vectorIndexConfig, v.vectorIndex.config) : v.vectorIndex.name === 'hfresh' - ? MergeWithExisting.hfresh(existing.vectorIndexConfig, v.vectorIndex.config) - : v.vectorIndex.name === 'dynamic' - ? MergeWithExisting.dynamic(existing.vectorIndexConfig, v.vectorIndex.config) - : MergeWithExisting.flat(existing.vectorIndexConfig, v.vectorIndex.config); + ? MergeWithExisting.hfresh(existing.vectorIndexConfig, v.vectorIndex.config) + : v.vectorIndex.name === 'dynamic' + ? MergeWithExisting.dynamic(existing.vectorIndexConfig, v.vectorIndex.config) + : MergeWithExisting.flat(existing.vectorIndexConfig, v.vectorIndex.config); } }); return current; diff --git a/src/collections/config/utils.ts b/src/collections/config/utils.ts index d377a74e..69ad19df 100644 --- a/src/collections/config/utils.ts +++ b/src/collections/config/utils.ts @@ -243,11 +243,11 @@ export const makeVectorsConfig = ( const vectorizersConfig = Array.isArray(configVectorizers) ? configVectorizers : [ - { - ...configVectorizers, - name: configVectorizers.name || 'default', - }, - ]; + { + ...configVectorizers, + name: configVectorizers.name || 'default', + }, + ]; vectorizersConfig.forEach((v) => { const vectorConfig: any = { vectorIndexConfig: parseVectorIndex(v.vectorIndex), @@ -367,18 +367,18 @@ class ConfigMapping { vectorizer: v.vectorizer === 'none' ? { - name: 'none', - config: undefined, - } + name: 'none', + config: undefined, + } : { - name: v.vectorizer, - config: v.moduleConfig - ? ({ - ...(v.moduleConfig[v.vectorizer] as any), - vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName, - } as VectorizerConfig) - : undefined, - }, + name: v.vectorizer, + config: v.moduleConfig + ? ({ + ...(v.moduleConfig[v.vectorizer] as any), + vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName, + } as VectorizerConfig) + : undefined, + }, indexConfig: ConfigMapping.vectorIndex(v.vectorIndexConfig, v.vectorIndexType), indexType: ConfigMapping.vectorIndexType(v.vectorIndexType), }, @@ -405,9 +405,10 @@ class ConfigMapping { return { ...v, enabled: v.enabled ?? false, - deleteOn: v.deleteOn == '_creationTimeUnix' - ? 'creationTime' - : v.deleteOn == '_lastUpdateTimeUnix' + deleteOn: + v.deleteOn == '_creationTimeUnix' + ? 'creationTime' + : v.deleteOn == '_lastUpdateTimeUnix' ? 'updateTime' : v.deleteOn, defaultTTLSeconds: v.defaultTtl, @@ -578,9 +579,9 @@ class ConfigMapping { ) { encoding = v.muvera.enabled ? { - type: 'muvera', - ...v.muvera, - } + type: 'muvera', + ...v.muvera, + } : undefined; } return { diff --git a/test/collections/config/integration.test.ts b/test/collections/config/integration.test.ts index 8434a284..690d5585 100644 --- a/test/collections/config/integration.test.ts +++ b/test/collections/config/integration.test.ts @@ -685,8 +685,8 @@ describe('Testing of the collection.config namespace', () => { .update({ propertyDescriptions: supportsUpdatingPropertyDescriptions ? { - testProp: 'This is a test property', - } + testProp: 'This is a test property', + } : undefined, vectorizers: weaviate.reconfigure.vectors.update({ vectorIndexConfig: weaviate.reconfigure.vectorIndex.hnsw({ From edc7f2b2360565013722df15e927c60c352fad13 Mon Sep 17 00:00:00 2001 From: dyma solovei Date: Thu, 2 Apr 2026 14:36:21 +0200 Subject: [PATCH 4/4] fix(config): apply update if no current is present --- src/collections/config/classes.ts | 2 +- test/collections/config/integration.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/collections/config/classes.ts b/src/collections/config/classes.ts index 58af2c4e..7eff288c 100644 --- a/src/collections/config/classes.ts +++ b/src/collections/config/classes.ts @@ -148,7 +148,7 @@ export class MergeWithExisting { } static objectTTL(current: WeaviateObjectTTLConfig, update: ObjectTTLConfigUpdate): WeaviateObjectTTLConfig { - if (current === undefined) return current; + if (current === undefined) return update; return { enabled: update.enabled ?? current.enabled, deleteOn: update.deleteOn ?? current.deleteOn, diff --git a/test/collections/config/integration.test.ts b/test/collections/config/integration.test.ts index 690d5585..69964789 100644 --- a/test/collections/config/integration.test.ts +++ b/test/collections/config/integration.test.ts @@ -1085,7 +1085,7 @@ describe('Testing of the collection.config namespace', () => { }); }); - requireAtLeast(1, 35, 0).it.only('should create and update Object TTL configuration', async () => { + requireAtLeast(1, 35, 0).it('should create and update Object TTL configuration', async () => { const collectionName = 'TestObjectTTL'; const collection = await client.collections.create({ name: collectionName,