From 0d072b1147e87e9108ae207b8dc8918e2aa9e26a Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 8 Apr 2026 15:29:08 +0100 Subject: [PATCH 1/4] fix: check that a replacement is not mapped to itself --- scripts/validate-manifests.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/validate-manifests.js b/scripts/validate-manifests.js index 158c61c..9795f7c 100644 --- a/scripts/validate-manifests.js +++ b/scripts/validate-manifests.js @@ -65,11 +65,20 @@ export async function validateManifests() { } for (const replacementId of mapping.replacements) { - if (!manifest.replacements[replacementId]) { + const replacement = manifest.replacements[replacementId]; + + if (!replacement) { throw new Error( `${manifestPath}: mapping "${key}" references unknown replacement "${replacementId}"` ); } + + if (replacement.replacementModule === key) { + throw new Error( + `${manifestPath}: mapping "${key}" defines a replacementModule that is identical to itself.` + ); + } + usedReplacementIds.add(replacementId); } } From d326f86717b7e7aa99925b48d5f4fa6440ed6302 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 8 Apr 2026 15:47:33 +0100 Subject: [PATCH 2/4] feat: add `dottie` to preferred manifest --- docs/modules/dot-prop.md | 23 +++++++---------------- manifests/preferred.json | 26 ++++++++++++++++---------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/docs/modules/dot-prop.md b/docs/modules/dot-prop.md index c947578..7bbd4c8 100644 --- a/docs/modules/dot-prop.md +++ b/docs/modules/dot-prop.md @@ -20,23 +20,14 @@ setProperty(obj, 'foo.bar.baz', 'value') // [!code --] dset(obj, 'foo.bar.baz', 'value') // [!code ++] ``` -## `object-path` +## `.reduce` (native) -[`object-path`](https://github.com/mariocasciaro/object-path) provides get/set/has/delete operations plus array methods like push, insert, and empty. +If you only need to get a nested value you can use a simple function: -```ts -import { deleteProperty, getProperty, hasProperty, setProperty } from 'dot-prop' // [!code --] -import objectPath from 'object-path' // [!code ++] - -const value = getProperty(obj, 'foo.bar.baz') // [!code --] -const value = objectPath.get(obj, 'foo.bar.baz') // [!code ++] - -setProperty(obj, 'foo.bar.baz', 'value') // [!code --] -objectPath.set(obj, 'foo.bar.baz', 'value') // [!code ++] - -const exists = hasProperty(obj, 'foo.bar.baz') // [!code --] -const exists = objectPath.has(obj, 'foo.bar.baz') // [!code ++] +```js +function getProperty(obj, key) { + return key.split('.').reduce((acc, k) => acc?.[k], obj) +} -deleteProperty(obj, 'foo.bar.baz') // [!code --] -objectPath.del(obj, 'foo.bar.baz') // [!code ++] +const value = getProperty(obj, 'foo.bar.baz') ``` diff --git a/manifests/preferred.json b/manifests/preferred.json index c06ac71..7b44db7 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -183,7 +183,7 @@ "dot-prop": { "type": "module", "moduleName": "dot-prop", - "replacements": ["dlv", "object-path"], + "replacements": ["dlv", "dset"], "url": {"type": "e18e", "id": "dot-prop"} }, "dotenv": { @@ -192,6 +192,12 @@ "replacements": ["--env-file"], "url": {"type": "e18e", "id": "dotenv"} }, + "dottie": { + "type": "module", + "moduleName": "dottie", + "replacements": ["dlv", "dset"], + "url": {"type": "e18e", "id": "dot-prop"} + }, "duplexer": { "type": "module", "moduleName": "duplexer", @@ -345,7 +351,7 @@ "get-value": { "type": "module", "moduleName": "get-value", - "replacements": ["dlv", "object-path"], + "replacements": ["dlv"], "url": {"type": "e18e", "id": "dot-prop"} }, "glob": { @@ -2427,7 +2433,7 @@ "object-path": { "type": "module", "moduleName": "object-path", - "replacements": ["dlv", "object-path"], + "replacements": ["dlv", "dset"], "url": {"type": "e18e", "id": "dot-prop"} }, "ora": { @@ -2575,7 +2581,7 @@ "set-value": { "type": "module", "moduleName": "set-value", - "replacements": ["dlv", "object-path"], + "replacements": ["dset"], "url": {"type": "e18e", "id": "dot-prop"} }, "shortid": { @@ -2982,6 +2988,12 @@ "url": {"type": "e18e", "id": "dot-prop"}, "replacementModule": "dlv" }, + "dset": { + "id": "dset", + "type": "documented", + "url": {"type": "e18e", "id": "dot-prop"}, + "replacementModule": "dset" + }, "elysia": { "id": "elysia", "type": "documented", @@ -3294,12 +3306,6 @@ "url": {"type": "e18e", "id": "npm-run-all"}, "replacementModule": "npm-run-all2" }, - "object-path": { - "id": "object-path", - "type": "documented", - "url": {"type": "e18e", "id": "dot-prop"}, - "replacementModule": "object-path" - }, "obug": { "id": "obug", "type": "documented", From a126ff52d721200fc03c1c226c72d1097f2b6eb1 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 8 Apr 2026 17:15:38 +0100 Subject: [PATCH 3/4] update doc --- docs/modules/dot-prop.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/modules/dot-prop.md b/docs/modules/dot-prop.md index 7bbd4c8..8f754f7 100644 --- a/docs/modules/dot-prop.md +++ b/docs/modules/dot-prop.md @@ -20,7 +20,7 @@ setProperty(obj, 'foo.bar.baz', 'value') // [!code --] dset(obj, 'foo.bar.baz', 'value') // [!code ++] ``` -## `.reduce` (native) +## `String.prototype.split` + `Array.prototype.reduce` (native) If you only need to get a nested value you can use a simple function: @@ -31,3 +31,7 @@ function getProperty(obj, key) { const value = getProperty(obj, 'foo.bar.baz') ``` + +> [!NOTE] +> This assumes that you do not consume dot paths as user input. +> If you do, ensure you sanitize keys before accessing them (e.g. through `Object.hasOwn`). From a1fa728f4b5e7962062267d81ce35060bc9a9690 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 9 Apr 2026 20:59:08 +0100 Subject: [PATCH 4/4] Update preferred.json --- manifests/preferred.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/preferred.json b/manifests/preferred.json index 7b44db7..7f19236 100644 --- a/manifests/preferred.json +++ b/manifests/preferred.json @@ -183,7 +183,7 @@ "dot-prop": { "type": "module", "moduleName": "dot-prop", - "replacements": ["dlv", "dset"], + "replacements": ["dlv"], "url": {"type": "e18e", "id": "dot-prop"} }, "dotenv": {