Skip to content

Commit 55d78c4

Browse files
fix(deps): deprecated jest, jest-diff and loadash-es with custom integration, and devDeps bumped to latest version
1 parent fcf1157 commit 55d78c4

File tree

17 files changed

+2521
-4035
lines changed

17 files changed

+2521
-4035
lines changed

dist/index.d.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
/**
2-
* Copyright 2020 Google LLC
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
161
import { VerifyReleaseContext as Context } from "semantic-release";
172
export type From = FromCallback | RegExp | string;
183
export type FromCallback = (filename: string, ...args: unknown[]) => RegExp | string;
@@ -46,7 +31,7 @@ export interface Replacement {
4631
/**
4732
* The replacement value using a template of variables.
4833
*
49-
* `__VERSION__ = "${nextRelease.version}"`
34+
* `__VERSION__ = "${context.nextRelease.version}"`
5035
*
5136
* The context object is used to render the template. Additional values
5237
* can be found at: https://semantic-release.gitbook.io/semantic-release/developer-guide/js-api#result
@@ -98,7 +83,7 @@ export interface Replacement {
9883
* {
9984
* "files": ["foo/__init__.py"],
10085
* "from": "__VERSION__ = \".*\"",
101-
* "to": "__VERSION__ = \"${nextRelease.version}\"",
86+
* "to": "__VERSION__ = \"${context.nextRelease.version}\"",
10287
* "results": [
10388
* {
10489
* "file": "foo/__init__.py",

dist/index.js

Lines changed: 156 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,4 @@
1-
/**
2-
* Copyright 2020 Google LLC
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
import replace from "replace-in-file";
17-
import { isEqual, template } from "lodash-es";
18-
import { diff } from "jest-diff";
1+
import { replaceInFile } from "replace-in-file";
192
/**
203
* Wraps the `callback` in a new function that passes the `context` as the
214
* final argument to the `callback` when it gets called.
@@ -32,7 +15,7 @@ function applyContextToCallback(callback, context) {
3215
function applyContextToReplacement(to, context) {
3316
return typeof to === "function"
3417
? applyContextToCallback(to, context)
35-
: template(to)({ ...context });
18+
: new Function(...Object.keys(context), `return \`${to}\`;`)(...Object.values(context));
3619
}
3720
/**
3821
* Normalizes a `value` into an array, making it more straightforward to apply
@@ -41,6 +24,156 @@ function applyContextToReplacement(to, context) {
4124
function normalizeToArray(value) {
4225
return value instanceof Array ? value : [value];
4326
}
27+
/**
28+
* Compares two values for deep equality.
29+
*
30+
* This function handles complex data types such as `RegExp`, `Date`, `Map`, `Set`,
31+
* and performs deep comparison of nested objects and arrays.
32+
*
33+
* @param {any} a - The first value to compare.
34+
* @param {any} b - The second value to compare.
35+
* @returns {boolean} `true` if the values are deeply equal, `false` otherwise.
36+
*
37+
* @example
38+
* const obj1 = { regex: /abc/g, date: new Date(), set: new Set([1, 2, 3]) };
39+
* const obj2 = { regex: /abc/g, date: new Date(), set: new Set([1, 2, 3]) };
40+
*
41+
* console.log(deepEqual(obj1, obj2)); // true
42+
*
43+
* @example
44+
* const obj1 = { regex: /abc/g, date: new Date(2022, 0, 1) };
45+
* const obj2 = { regex: /abc/g, date: new Date(2021, 0, 1) };
46+
*
47+
* console.log(deepEqual(obj1, obj2)); // false
48+
*/
49+
function deepEqual(a, b) {
50+
if (a === b)
51+
return true; // Handle primitives
52+
// Check for null or undefined
53+
if (a == null || b == null)
54+
return false;
55+
// Handle RegExp
56+
if (a instanceof RegExp && b instanceof RegExp) {
57+
return a.source === b.source && a.flags === b.flags;
58+
}
59+
// Handle Date
60+
if (a instanceof Date && b instanceof Date) {
61+
return a.getTime() === b.getTime();
62+
}
63+
// Handle Map and Set
64+
if (a instanceof Map && b instanceof Map) {
65+
if (a.size !== b.size)
66+
return false;
67+
for (let [key, value] of a) {
68+
if (!b.has(key) || !deepEqual(value, b.get(key)))
69+
return false;
70+
}
71+
return true;
72+
}
73+
if (a instanceof Set && b instanceof Set) {
74+
if (a.size !== b.size)
75+
return false;
76+
for (let item of a) {
77+
if (!b.has(item))
78+
return false;
79+
}
80+
return true;
81+
}
82+
// Handle objects and arrays
83+
if (typeof a === "object" && typeof b === "object") {
84+
const keysA = Object.keys(a);
85+
const keysB = Object.keys(b);
86+
if (keysA.length !== keysB.length)
87+
return false;
88+
for (let key of keysA) {
89+
if (!keysB.includes(key) || !deepEqual(a[key], b[key])) {
90+
return false;
91+
}
92+
}
93+
return true;
94+
}
95+
// If none of the checks match, return false
96+
return false;
97+
}
98+
/**
99+
* Recursively compares two objects and returns an array of differences.
100+
*
101+
* The function traverses the two objects (or arrays) and identifies differences
102+
* in their properties or elements. It supports complex types like `Date`, `RegExp`,
103+
* `Map`, `Set`, and checks nested objects and arrays.
104+
*
105+
* @param {any} obj1 - The first value to compare.
106+
* @param {any} obj2 - The second value to compare.
107+
* @param {string} [path=""] - The current path to the property or element being compared (used for recursion).
108+
* @returns {string[]} An array of strings representing the differences between the two values.
109+
*
110+
* @example
111+
* const obj1 = { a: 1, b: { c: 2 } };
112+
* const obj2 = { a: 1, b: { c: 3 } };
113+
*
114+
* const differences = deepDiff(obj1, obj2);
115+
* console.log(differences); // ['Difference at b.c: 2 !== 3']
116+
*
117+
* @example
118+
* const set1 = new Set([1, 2, 3]);
119+
* const set2 = new Set([1, 2, 4]);
120+
*
121+
* const differences = deepDiff(set1, set2);
122+
* console.log(differences); // ['Difference at : Set { 1, 2, 3 } !== Set { 1, 2, 4 }']
123+
*/
124+
function deepDiff(obj1, obj2, path = "") {
125+
let differences = [];
126+
if (typeof obj1 !== "object" || typeof obj2 !== "object" || obj1 === null || obj2 === null) {
127+
if (obj1 !== obj2) {
128+
differences.push(`Difference at ${path}: ${obj1} !== ${obj2}`);
129+
}
130+
return differences;
131+
}
132+
// Check for Map or Set
133+
if (obj1 instanceof Map && obj2 instanceof Map) {
134+
if (obj1.size !== obj2.size) {
135+
differences.push(`Difference at ${path}: Map sizes do not match`);
136+
}
137+
for (let [key, value] of obj1) {
138+
if (!obj2.has(key) || !deepEqual(value, obj2.get(key))) {
139+
differences.push(`Difference at ${path}.${key}: ${value} !== ${obj2.get(key)}`);
140+
}
141+
}
142+
return differences;
143+
}
144+
if (obj1 instanceof Set && obj2 instanceof Set) {
145+
if (obj1.size !== obj2.size) {
146+
differences.push(`Difference at ${path}: Set sizes do not match`);
147+
}
148+
for (let item of obj1) {
149+
if (!obj2.has(item)) {
150+
differences.push(`Difference at ${path}: Set items do not match`);
151+
}
152+
}
153+
return differences;
154+
}
155+
// Handle RegExp
156+
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
157+
if (obj1.source !== obj2.source || obj1.flags !== obj2.flags) {
158+
differences.push(`Difference at ${path}: RegExp ${obj1} !== ${obj2}`);
159+
}
160+
return differences;
161+
}
162+
// Handle Date
163+
if (obj1 instanceof Date && obj2 instanceof Date) {
164+
if (obj1.getTime() !== obj2.getTime()) {
165+
differences.push(`Difference at ${path}: Date ${obj1} !== ${obj2}`);
166+
}
167+
return differences;
168+
}
169+
// Handle objects and arrays
170+
const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
171+
for (const key of keys) {
172+
const newPath = path ? `${path}.${key}` : key;
173+
differences = differences.concat(deepDiff(obj1[key], obj2[key], newPath));
174+
}
175+
return differences;
176+
}
44177
export async function prepare(PluginConfig, context) {
45178
for (const replacement of PluginConfig.replacements) {
46179
let { results } = replacement;
@@ -50,18 +183,6 @@ export async function prepare(PluginConfig, context) {
50183
from: replacement.from ?? [],
51184
to: replacement.to ?? [],
52185
};
53-
// The `replace-in-file` package uses `String.replace` under the hood for
54-
// the actual replacement. If `from` is a string, this means only a
55-
// single occurrence will be replaced. This plugin intents to replace
56-
// _all_ occurrences when given a string to better support
57-
// configuration through JSON, this requires conversion into a `RegExp`.
58-
//
59-
// If `from` is a callback function, the `context` is passed as the final
60-
// parameter to the function. In all other cases, e.g. being a
61-
// `RegExp`, the `from` property does not require any modifications.
62-
//
63-
// The `from` property may either be a single value to match or an array of
64-
// values (in any of the previously described forms)
65186
replaceInFileConfig.from = normalizeToArray(replacement.from).map((from) => {
66187
switch (typeof from) {
67188
case "function":
@@ -76,12 +197,13 @@ export async function prepare(PluginConfig, context) {
76197
replacement.to instanceof Array
77198
? replacement.to.map((to) => applyContextToReplacement(to, context))
78199
: applyContextToReplacement(replacement.to, context);
79-
let actual = await replace(replaceInFileConfig);
200+
let actual = await replaceInFile(replaceInFileConfig);
80201
if (results) {
81202
results = results.sort();
82203
actual = actual.sort();
83-
if (!isEqual(actual.sort(), results.sort())) {
84-
throw new Error(`Expected match not found!\n${diff(actual, results)}`);
204+
if (!deepEqual([...actual].sort(), [...results].sort())) {
205+
const difference = deepDiff(actual, results);
206+
throw new Error(`Expected match not found!\n${difference.join("\n")}`);
85207
}
86208
}
87209
}

dist/index.test.d.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
1-
/**
2-
* Copyright 2020 Google LLC
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
161
export {};

dist/index.test.js

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
/**
2-
* Copyright 2020 Google LLC
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
161
import * as m from "./index.js";
172
import fs from "fs-extra";
183
import path from "path";
@@ -22,7 +7,7 @@ import { prepare } from "./index.js";
227
const context = {
238
stdout: process.stdout,
249
stderr: process.stderr,
25-
logger: {},
10+
logger: {}, // You might need to provide appropriate options to Signale constructor
2611
cwd: "/path/to/your/repository",
2712
env: process.env,
2813
envCi: {
@@ -97,6 +82,9 @@ const context = {
9782
channel: "main",
9883
notes: "These are the release notes for the next release.",
9984
},
85+
options: {
86+
ci: false,
87+
},
10088
};
10189
let d;
10290
beforeEach(() => {
@@ -242,7 +230,7 @@ test("prepare accepts callback functions for `from`", async () => {
242230
const replacements = [
243231
{
244232
files: [path.join(d.name, "/foo.md")],
245-
from: (filename) => `${path.basename(filename, ".md")}@1.0.0`,
233+
from: (filename) => `${path.basename(filename, ".md")}@1.0.0`, // Equivalent to "foo@1.0.0"
246234
to: `foo@${context.nextRelease?.version}`,
247235
},
248236
];

docs/.nojekyll

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)