@karmaniverous/entity-manager 6.14.0 → 6.14.2
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/README.md +330 -16
- package/dist/cjs/EntityManager/ParsedConfig.js +46 -55
- package/dist/cjs/EntityManager/addKeys.js +1 -0
- package/dist/cjs/EntityManager/decodeElement.js +2 -1
- package/dist/cjs/EntityManager/dehydratePageKeyMap.js +3 -1
- package/dist/cjs/EntityManager/encodeElement.js +2 -2
- package/dist/cjs/EntityManager/encodeGeneratedProperty.js +1 -1
- package/dist/cjs/EntityManager/getHashKeySpace.js +16 -3
- package/dist/cjs/EntityManager/rehydratePageKeyMap.js +3 -1
- package/dist/cjs/EntityManager/removeKeys.js +10 -8
- package/dist/cjs/EntityManager/updateItemHashKey.js +4 -1
- package/dist/index.d.ts +17 -208
- package/dist/mjs/EntityManager/ParsedConfig.js +46 -55
- package/dist/mjs/EntityManager/addKeys.js +1 -0
- package/dist/mjs/EntityManager/decodeElement.js +2 -1
- package/dist/mjs/EntityManager/dehydratePageKeyMap.js +3 -1
- package/dist/mjs/EntityManager/encodeElement.js +2 -2
- package/dist/mjs/EntityManager/encodeGeneratedProperty.js +1 -1
- package/dist/mjs/EntityManager/getHashKeySpace.js +16 -3
- package/dist/mjs/EntityManager/rehydratePageKeyMap.js +3 -1
- package/dist/mjs/EntityManager/removeKeys.js +10 -8
- package/dist/mjs/EntityManager/updateItemHashKey.js +4 -1
- package/package.json +44 -45
|
@@ -28,7 +28,7 @@ function encodeGeneratedProperty(entityManager, property, item) {
|
|
|
28
28
|
...(sharded
|
|
29
29
|
? [item[entityManager.config.hashKey]]
|
|
30
30
|
: []),
|
|
31
|
-
...elementMap.map(([element, value]) => [element,
|
|
31
|
+
...elementMap.map(([element, value]) => [element, `${value ?? ''}`].join(entityManager.config.generatedValueDelimiter)),
|
|
32
32
|
].join(entityManager.config.generatedKeyDelimiter);
|
|
33
33
|
entityManager.logger.debug('encoded generated property', {
|
|
34
34
|
property,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { range } from 'radash';
|
|
2
|
+
import stringHash from 'string-hash';
|
|
2
3
|
import { encodeGeneratedProperty } from './encodeGeneratedProperty.js';
|
|
3
4
|
import { validateGeneratedProperty } from './validateGeneratedProperty.js';
|
|
4
5
|
|
|
@@ -22,6 +23,9 @@ function getHashKeySpace(entityManager, entityToken, hashKeyToken, item, timesta
|
|
|
22
23
|
if (hashKeyToken !== entityManager.config.hashKey)
|
|
23
24
|
validateGeneratedProperty(entityManager, hashKeyToken, true);
|
|
24
25
|
const { shardBumps } = entityManager.config.entities[entityToken];
|
|
26
|
+
// Detect presence of the entity's unique property on the item.
|
|
27
|
+
const uniqueProp = entityManager.config.entities[entityToken].uniqueProperty;
|
|
28
|
+
const uniqueValue = item[uniqueProp];
|
|
25
29
|
const hashKeySpace = shardBumps
|
|
26
30
|
// Filter shard bumps by timestamp range.
|
|
27
31
|
.filter((bump, i) => (i === shardBumps.length - 1 ||
|
|
@@ -30,9 +34,18 @@ function getHashKeySpace(entityManager, entityToken, hashKeyToken, item, timesta
|
|
|
30
34
|
// Generate shard key space.
|
|
31
35
|
.flatMap(({ charBits, chars }) => {
|
|
32
36
|
const radix = 2 ** charBits;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
// If the item's unique property is present, deterministically
|
|
38
|
+
// compute exactly one shard suffix for this bump. Otherwise,
|
|
39
|
+
// enumerate the full shard space for the bump.
|
|
40
|
+
if (chars) {
|
|
41
|
+
if (uniqueValue) {
|
|
42
|
+
const space = radix ** chars;
|
|
43
|
+
const mod = stringHash(uniqueValue) % space;
|
|
44
|
+
return mod.toString(radix).padStart(chars, '0');
|
|
45
|
+
}
|
|
46
|
+
return [...range(0, radix ** chars - 1)].map((char) => char.toString(radix).padStart(chars, '0'));
|
|
47
|
+
}
|
|
48
|
+
return '';
|
|
36
49
|
})
|
|
37
50
|
// Map shard keys to hash keys.
|
|
38
51
|
.map((shardKey) => {
|
|
@@ -45,7 +45,9 @@ function rehydratePageKeyMap(entityManager, entityToken, indexTokens, item, dehy
|
|
|
45
45
|
if (hashKeys.length > 1)
|
|
46
46
|
throw new Error('inconsistent hashKeys');
|
|
47
47
|
const [hashKeyToken] = hashKeys;
|
|
48
|
-
indexTokens.map((index) =>
|
|
48
|
+
indexTokens.map((index) => {
|
|
49
|
+
validateIndexToken(entityManager, index);
|
|
50
|
+
});
|
|
49
51
|
// Shortcut empty dehydrated.
|
|
50
52
|
if (dehydrated && !dehydrated.length)
|
|
51
53
|
return [hashKeyToken, {}];
|
|
@@ -15,14 +15,16 @@ function removeKeys(entityManager, entityToken, item) {
|
|
|
15
15
|
try {
|
|
16
16
|
// Validate params.
|
|
17
17
|
validateEntityToken(entityManager, entityToken);
|
|
18
|
-
//
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
// Build a set of keys to strip (hash, range, and all generated properties).
|
|
19
|
+
const { hashKey, rangeKey, generatedProperties: { sharded, unsharded }, } = entityManager.config;
|
|
20
|
+
const keysToStrip = new Set([
|
|
21
|
+
hashKey,
|
|
22
|
+
rangeKey,
|
|
23
|
+
...Object.keys(sharded),
|
|
24
|
+
...Object.keys(unsharded),
|
|
25
|
+
]);
|
|
26
|
+
// Create a shallow copy of item omitting the keys above (no delete operator).
|
|
27
|
+
const newItem = Object.fromEntries(Object.entries(item).filter(([key]) => !keysToStrip.has(key)));
|
|
26
28
|
entityManager.logger.debug('stripped entity item generated properties', {
|
|
27
29
|
entityToken,
|
|
28
30
|
item,
|
|
@@ -40,12 +40,15 @@ function updateItemHashKey(entityManager, entityToken, item, overwrite = false)
|
|
|
40
40
|
if (chars) {
|
|
41
41
|
// Radix is the numerical base of the shardKey.
|
|
42
42
|
const radix = 2 ** charBits;
|
|
43
|
+
// Compute the full shard space for this bump. Use radix ** chars to ensure
|
|
44
|
+
// all placeholders are utilized (e.g., chars=2, charBits=2 => 16 combos).
|
|
45
|
+
const space = radix ** chars;
|
|
43
46
|
// Get item unique property & validate.
|
|
44
47
|
const uniqueId = item[entityManager.config.entities[entityToken]
|
|
45
48
|
.uniqueProperty];
|
|
46
49
|
if (isNil(uniqueId))
|
|
47
50
|
throw new Error(`missing item unique property`);
|
|
48
|
-
hashKey += (stringHash(uniqueId
|
|
51
|
+
hashKey += (stringHash(uniqueId) % space)
|
|
49
52
|
.toString(radix)
|
|
50
53
|
.padStart(chars, '0');
|
|
51
54
|
}
|
package/package.json
CHANGED
|
@@ -5,58 +5,52 @@
|
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@karmaniverous/batch-process": "^0.1.0",
|
|
8
|
-
"@karmaniverous/entity-tools": "^0.6.
|
|
8
|
+
"@karmaniverous/entity-tools": "^0.6.9",
|
|
9
9
|
"@karmaniverous/string-utilities": "^0.2.1",
|
|
10
10
|
"lz-string": "^1.5.0",
|
|
11
|
-
"radash": "^12.1.
|
|
11
|
+
"radash": "^12.1.1",
|
|
12
12
|
"string-hash": "^1.1.3",
|
|
13
|
-
"zod": "^
|
|
13
|
+
"zod": "^4.1.12"
|
|
14
14
|
},
|
|
15
15
|
"description": "Rational indexing & cross-shard querying at scale in your NoSQL database so you can focus on your application logic.",
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@dotenvx/dotenvx": "^1.
|
|
18
|
-
"@eslint/js": "^9.
|
|
19
|
-
"@faker-js/faker": "^
|
|
20
|
-
"@karmaniverous/mock-db": "^0.3.
|
|
21
|
-
"@rollup/plugin-alias": "^
|
|
22
|
-
"@rollup/plugin-commonjs": "^
|
|
17
|
+
"@dotenvx/dotenvx": "^1.51.1",
|
|
18
|
+
"@eslint/js": "^9.39.1",
|
|
19
|
+
"@faker-js/faker": "^10.1.0",
|
|
20
|
+
"@karmaniverous/mock-db": "^0.3.5",
|
|
21
|
+
"@rollup/plugin-alias": "^6.0.0",
|
|
22
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
23
23
|
"@rollup/plugin-json": "^6.1.0",
|
|
24
|
-
"@rollup/plugin-node-resolve": "^
|
|
24
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
25
25
|
"@rollup/plugin-strip": "^3.0.4",
|
|
26
|
-
"@rollup/plugin-typescript": "^12.
|
|
27
|
-
"@types/
|
|
28
|
-
"@types/eslint__js": "^8.42.3",
|
|
29
|
-
"@types/eslint-config-prettier": "^6.11.3",
|
|
30
|
-
"@types/eslint-plugin-mocha": "^10.4.0",
|
|
31
|
-
"@types/mocha": "^10.0.9",
|
|
32
|
-
"@types/node": "^22.9.0",
|
|
26
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
27
|
+
"@types/node": "^24.10.0",
|
|
33
28
|
"@types/string-hash": "^1.1.3",
|
|
34
29
|
"auto-changelog": "^2.5.0",
|
|
35
|
-
"
|
|
36
|
-
"eslint": "^9.
|
|
37
|
-
"eslint-config-prettier": "^
|
|
38
|
-
"eslint-plugin-
|
|
30
|
+
"cross-env": "^10.1.0",
|
|
31
|
+
"eslint": "^9.39.1",
|
|
32
|
+
"eslint-config-prettier": "^10.1.8",
|
|
33
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
39
34
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
40
|
-
"eslint-plugin-tsdoc": "^0.
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"rollup": "^4.26.0",
|
|
50
|
-
"rollup-plugin-dts": "^6.1.1",
|
|
51
|
-
"source-map-support": "^0.5.21",
|
|
52
|
-
"ts-node": "^10.9.2",
|
|
35
|
+
"eslint-plugin-tsdoc": "^0.4.0",
|
|
36
|
+
"knip": "^5.67.1",
|
|
37
|
+
"lefthook": "^2.0.2",
|
|
38
|
+
"prettier": "^3.6.2",
|
|
39
|
+
"release-it": "^19.0.5",
|
|
40
|
+
"rimraf": "^6.1.0",
|
|
41
|
+
"rollup": "^4.52.5",
|
|
42
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
43
|
+
"tsd": "^0.33.0",
|
|
53
44
|
"tslib": "^2.8.1",
|
|
54
|
-
"typedoc": "^0.
|
|
55
|
-
"typedoc-plugin-mdn-links": "^
|
|
56
|
-
"typedoc-plugin-replace-text": "^4.
|
|
57
|
-
"typedoc-plugin-zod": "^1.
|
|
58
|
-
"
|
|
59
|
-
"
|
|
45
|
+
"typedoc": "^0.28.14",
|
|
46
|
+
"typedoc-plugin-mdn-links": "^5.0.10",
|
|
47
|
+
"typedoc-plugin-replace-text": "^4.2.0",
|
|
48
|
+
"typedoc-plugin-zod": "^1.4.3",
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.6",
|
|
50
|
+
"@vitest/eslint-plugin": "^1.4.0",
|
|
51
|
+
"vitest": "^4.0.6",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"typescript-eslint": "^8.46.3"
|
|
60
54
|
},
|
|
61
55
|
"exports": {
|
|
62
56
|
".": {
|
|
@@ -122,15 +116,20 @@
|
|
|
122
116
|
},
|
|
123
117
|
"scripts": {
|
|
124
118
|
"build": "rimraf dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
|
|
119
|
+
"changelog": "auto-changelog",
|
|
125
120
|
"docs": "typedoc",
|
|
126
121
|
"knip": "knip",
|
|
127
|
-
"lint": "eslint
|
|
128
|
-
"lint:fix": "
|
|
122
|
+
"lint": "eslint .",
|
|
123
|
+
"lint:fix": "npm run lint -- --fix .",
|
|
129
124
|
"release": "dotenvx run -f .env.local -- release-it",
|
|
130
|
-
"release:pre": "
|
|
131
|
-
"test": "
|
|
125
|
+
"release:pre": "npm run release -- --no-git.requireBranch --github.prerelease --preRelease",
|
|
126
|
+
"test": "vitest --run --silent",
|
|
127
|
+
"typecheck": "tsc && tsd"
|
|
128
|
+
},
|
|
129
|
+
"tsd": {
|
|
130
|
+
"directory": "test/types"
|
|
132
131
|
},
|
|
133
132
|
"type": "module",
|
|
134
133
|
"types": "dist/index.d.ts",
|
|
135
|
-
"version": "6.14.
|
|
134
|
+
"version": "6.14.2"
|
|
136
135
|
}
|