@travetto/model-indexed 8.0.0-alpha.13 → 8.0.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/indexes.ts +25 -2
- package/support/test/indexed.ts +30 -2
package/package.json
CHANGED
package/src/indexes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ModelType, ModelRegistryIndex } from '@travetto/model';
|
|
2
|
-
import { type Class, type Any, castTo } from '@travetto/runtime';
|
|
1
|
+
import { type IndexConfig, type ModelType, ModelRegistryIndex } from '@travetto/model';
|
|
2
|
+
import { type Class, type Any, castTo, type ClassInstance } from '@travetto/runtime';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
type AllIndexes, type KeyedIndexSelection, type KeyedIndex,
|
|
@@ -81,3 +81,26 @@ export function sortedIndex<
|
|
|
81
81
|
|
|
82
82
|
export const isModelIndexedIndex = <T extends ModelType>(idx: Any): idx is AllIndexes<T> =>
|
|
83
83
|
typeof idx === 'object' && idx !== null && 'type' in idx && typeof idx.type === 'string' && idx.type.startsWith('indexed:');
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
export const warnIfIndexedUniqueIndex = (service: ClassInstance, cls: Class<ModelType>, indexes: IndexConfig[]): boolean => {
|
|
87
|
+
let warned = false;
|
|
88
|
+
for (const idx of indexes) {
|
|
89
|
+
if (isModelIndexedIndex(idx) && 'unique' in idx && idx.unique) {
|
|
90
|
+
console.debug('Unique indices are not supported', { cls: cls.Ⲑid, idx: idx.name, service: service.constructor.Ⲑid });
|
|
91
|
+
warned = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return warned;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const warnIfNonIndexedIndex = (service: ClassInstance, cls: Class<ModelType>, indexes: IndexConfig[]): boolean => {
|
|
98
|
+
let warned = false;
|
|
99
|
+
for (const idx of indexes) {
|
|
100
|
+
if (!isModelIndexedIndex(idx)) {
|
|
101
|
+
console.debug('Non-indexed indices are not supported', { cls: cls.Ⲑid, idx: idx.name, service: service.constructor.Ⲑid });
|
|
102
|
+
warned = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return warned;
|
|
106
|
+
};
|
package/support/test/indexed.ts
CHANGED
|
@@ -4,11 +4,11 @@ import timers from 'node:timers/promises';
|
|
|
4
4
|
import { Suite, Test } from '@travetto/test';
|
|
5
5
|
import { Schema } from '@travetto/schema';
|
|
6
6
|
import { castTo, TimeUtil } from '@travetto/runtime';
|
|
7
|
-
import { Model, NotFoundError } from '@travetto/model';
|
|
7
|
+
import { ExistsError, Model, NotFoundError } from '@travetto/model';
|
|
8
8
|
import { BaseModelSuite } from '@travetto/model/support/test/base.ts';
|
|
9
9
|
|
|
10
10
|
import type { ModelIndexedSupport } from '../../src/types/service.ts';
|
|
11
|
-
import { keyedIndex, sortedIndex } from '../../src/indexes.ts';
|
|
11
|
+
import { keyedIndex, sortedIndex, uniqueIndex } from '../../src/indexes.ts';
|
|
12
12
|
import { IndexedFieldError } from '../../src/types/error.ts';
|
|
13
13
|
|
|
14
14
|
@Model('index_user')
|
|
@@ -22,6 +22,17 @@ const userNameIndex = keyedIndex(User, {
|
|
|
22
22
|
key: { name: true }
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
@Model('index_unique_user')
|
|
26
|
+
class UniqueUser {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const userUniqueNameIndex = uniqueIndex(UniqueUser, {
|
|
32
|
+
name: 'userUniqueName',
|
|
33
|
+
key: { name: true }
|
|
34
|
+
});
|
|
35
|
+
|
|
25
36
|
@Model('index_user_2')
|
|
26
37
|
class User2 {
|
|
27
38
|
id: string;
|
|
@@ -82,6 +93,7 @@ export abstract class ModelIndexedSuite extends BaseModelSuite<ModelIndexedSuppo
|
|
|
82
93
|
|
|
83
94
|
indexLimitSkew = 0;
|
|
84
95
|
supportsDeepIndexes = true;
|
|
96
|
+
supportsUniqueIndexes = true;
|
|
85
97
|
|
|
86
98
|
@Test()
|
|
87
99
|
async writeAndRead() {
|
|
@@ -103,6 +115,22 @@ export abstract class ModelIndexedSuite extends BaseModelSuite<ModelIndexedSuppo
|
|
|
103
115
|
assert(found2.name === 'bob2');
|
|
104
116
|
}
|
|
105
117
|
|
|
118
|
+
@Test({ skip: (self) => !castTo<ModelIndexedSuite>(self).supportsUniqueIndexes })
|
|
119
|
+
async writeRejectsDuplicateUniqueIndex() {
|
|
120
|
+
const service = await this.service;
|
|
121
|
+
|
|
122
|
+
const created = await service.create(UniqueUser, UniqueUser.from({ name: 'sam' }));
|
|
123
|
+
|
|
124
|
+
await assert.rejects(
|
|
125
|
+
() => service.create(UniqueUser, UniqueUser.from({ name: 'sam' })),
|
|
126
|
+
err => err instanceof ExistsError
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const found = await service.getByIndex(UniqueUser, userUniqueNameIndex, { name: 'sam' });
|
|
130
|
+
assert(found.id === created.id);
|
|
131
|
+
assert(found.name === 'sam');
|
|
132
|
+
}
|
|
133
|
+
|
|
106
134
|
@Test()
|
|
107
135
|
async readByKeyedIndexUsingId() {
|
|
108
136
|
const service = await this.service;
|