Skip to content

Versions and Upgrading

m4bwav edited this page Sep 30, 2026 · 1 revision

The releases

Dates are the npm publish times in UTC; downloads are npm's per-version count for the last week, read on 2026-09-30 (518 in all).

Version Published What it was Downloads last week
1.0.0 2016-05-22 First release 5
1.0.1 2016-05-22 6
1.0.2 2016-05-22 7
1.0.3 2016-05-22 9
1.0.4 2016-05-22 The last 1.x: one ES5 file, module.exports = replaceStringAtPosition, no argument checks 70
2.0.0-beta.1 2026-09-26 Prerelease of 2.0.0 120
2.0.0 2026-09-26 TypeScript rewrite: ES module and CommonJS builds with types, argument checks, Node 20 or later 301

No version is deprecated. The latest tag points to 2.0.0 and there is no next tag. 1.0.4 still installs from npm and loads with require() on Node 24.18.0 and 20.20.2 (this wiki's run); 1.0.0 to 1.0.3 were not tested. The CHANGELOG dates 2.0.0 2026-09-25, the maintainer's local date of the same release. 2.0.0 was published from GitHub Actions with npm provenance.

Moving from 1.0.4 to 2.0.0

Calls with three strings (or String objects) and an integer position from 0 to the text's length give exactly the answer 1.0.4 gave, and require() still returns the function. Everything else changed:

  • Node 20 or later.
  • Only the package name can be imported; replace-string-at-position/index.js no longer resolves.
  • A call 1.0.4 answered with damaged text, or with an engine error, now throws a TypeError or RangeError naming the argument (Edge cases and errors).
  • A few calls that happened to work in 1.0.4 throw as well: a number as newString, true or a Number object as the position, an array as sourceString. Convert them with String() or Number() first.
  • The command-line tool the old README described is gone. It never installed, because 1.0.4's package.json had no bin.

The same CommonJS file, run against each version:

const replaceStringAtPosition = require('replace-string-at-position');

function attempt(...args) {
	try {
		return JSON.stringify(replaceStringAtPosition(...args));
	} catch (error) {
		return `${error.name}: ${error.message}`;
	}
}

console.log(attempt('222', '2', '3', 1));
console.log(attempt('hello world', 'world', 'there', 6));
console.log(attempt('abc', 'b', 'X'));
console.log(attempt('abcdef', 'b', 'X', '1'));
console.log(attempt('abcdef', 'b', 'X', -1));
console.log(attempt('abcdef', 'b', 'X', 1.5));
console.log(attempt('abc', 'x', 'Y', 10));
console.log(attempt('abcdef', 'b', null, 1));
console.log(attempt('item #0', '0', 5, 6));
console.log(attempt('abcdef', 'b', 'X', true));
console.log(attempt(null, 'a', 'X', 0));

1.0.4 prints:

"232"
"hello there"
"abcXabc"
"aX"
"Xabcdef"
"aXcdef"
"abcY"
"anullcdef"
"item #5"
"aXcdef"
TypeError: Cannot read properties of null (reading 'substring')

2.0.0 prints:

"232"
"hello there"
TypeError: Expected `position` to be a number, got undefined
TypeError: Expected `position` to be a number, got the string "1"
RangeError: Expected `position` to be an integer from 0 to 6, got -1
RangeError: Expected `position` to be an integer from 0 to 6, got 1.5
RangeError: Expected `position` to be an integer from 0 to 3, got 10
TypeError: Expected `newString` to be a string, got null
TypeError: Expected `newString` to be a string, got 5
TypeError: Expected `position` to be a number, got a boolean
TypeError: Expected `originalString` to be a string, got null

Line by line: a missing position made 1.0.4 return the text twice around newString. The string '1' became the end index '11' and dropped the tail. -1 was spliced at the start and 1.5 was truncated to 1. A position past the end appended, and null was written into the text. 5 and true happened to work, and a null text failed inside the engine.

Deep imports

try {
	require('replace-string-at-position/index.js');
	console.log('loaded');
} catch (error) {
	console.log(error.code);
}

On 1.0.4 it prints:

loaded

On 2.0.0 it prints:

ERR_PACKAGE_PATH_NOT_EXPORTED

The recorded 1.0.4 answers, replayed today

The repository keeps 71 calls recorded from the published 1.0.4 (test/golden/1.0.4.json, made by test/golden/capture-1.0.4.cjs with codec.cjs). For this wiki the capture script ran unchanged as a child process, first against 1.0.4 installed from npm today, then against 2.0.0. Both ran on Node 24.18.0 and again on Node 20.20.2.

  • 1.0.4 today gave all 71 recorded answers again, and its eight recorded quirks (the module's shape, symbol arguments, a detached call, the missing bin) were the same.
  • 2.0.0 gave the same answer in 26 cases, the well-formed calls. The other 45 now throw:
results: 26 identical, 45 differ
  now throws RangeError: 13
  now throws TypeError: 32

Of those 45, 34 returned text in 1.0.4 and 11 already threw one of the engine's TypeErrors (Cannot read properties of null (reading 'substring'), originalString.substring is not a function, Cannot convert a BigInt value to a number), which 2.0.0 replaces with its own message. Every difference matches a line in the CHANGELOG's 2.0.0 "Changed" section. Two quirks changed as documented: the CommonJS function now has the own keys default and replaceStringAtPosition, and a symbol as newString or position gets the package's message instead of the engine's.

A few of the 45, as 1.0.4 answered them:

Call 1.0.4 2.0.0
('abc', 'b', 'X') 'abcXabc' TypeError
('abc', 'b') 'abcundefinedabc' TypeError
('abcdef', 'b', 'X', [2]) 'abX' TypeError
('abcdef', 5, 'X', 1) 'aXabcdef' TypeError
('abcdef', {length: 3}, 'X', 1) 'aXef' TypeError
('abcdef', 'b', {}, 1) 'a[object Object]cdef' TypeError
('abcdef', 'b', 'X', NaN) 'Xabcdef' RangeError
('', '', 'X', 5) 'X' RangeError

Who depends on it

npm counts four dependents. Two were found in September 2026: markdown-plain-link-replacer (the same maintainer's, which moved to ^2.0.0 in its 2.0.0) and strip-mentions 1.0.0 (^1.0.4, so it stays on 1.x). Both pass a string found in the same text and its index, which 2.0.0 answers as 1.0.4 did.

Clone this wiki locally