UNPKG

11.2 kBMarkdownView Raw
1<div align="center">
2
3# [![Jewire](logo.svg)](https://github.com/nktnet1/jewire)
4
5[![pipeline](https://github.com/nktnet1/jewire/actions/workflows/pipeline.yml/badge.svg)](https://github.com/nktnet1/jewire/actions/workflows/pipeline.yml)
6&nbsp;
7[![codecov](https://codecov.io/gh/nktnet1/jewire/branch/main/graph/badge.svg?token=RAC7SKJTGU)](https://codecov.io/gh/nktnet1/jewire)
8&nbsp;
9[![Maintainability](https://api.codeclimate.com/v1/badges/2cc2478a1b5a2f293149/maintainability)](https://codeclimate.com/github/nktnet1/jewire/maintainability)
10&nbsp;
11[![Snyk Security](https://snyk.io/test/github/nktnet1/jewire/badge.svg)](https://snyk.io/test/github/nktnet1/jewire)
12&nbsp;
13[![GitHub top language](https://img.shields.io/github/languages/top/nktnet1/jewire)](https://github.com/search?q=repo%3Anktnet1%2Fjewire++language%3ATypeScript&type=code)
14
15[![NPM Version](https://img.shields.io/npm/v/jewire?logo=npm)](https://www.npmjs.com/package/jewire?activeTab=versions)
16&nbsp;
17[![install size](https://packagephobia.com/badge?p=jewire)](https://packagephobia.com/result?p=jewire)
18&nbsp;
19[![Depfu Dependencies](https://badges.depfu.com/badges/6c4074c4d23ad57ee2bfd9ff90456090/overview.svg)](https://depfu.com/github/nktnet1/jewire?project_id=39032)
20&nbsp;
21[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnktnet1%2Fjewire.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnktnet1%2Fjewire?ref=badge_shield)
22&nbsp;
23[![NPM License](https://img.shields.io/npm/l/jewire)](https://opensource.org/license/mit/)
24&nbsp;
25[![GitHub issues](https://img.shields.io/github/issues/nktnet1/jewire.svg?style=social)](https://github.com/nktnet1/jewire/issues)
26
27[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=nktnet1_jewire&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=nktnet1_jewire)
28&nbsp;
29[![Codacy Badge](https://app.codacy.com/project/badge/Grade/65161ae4d1c646ed83c9ef47b0a11473)](https://app.codacy.com/gh/nktnet1/jewire/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
30&nbsp;
31[![DeepSource](https://app.deepsource.com/gh/nktnet1/jewire.svg/?label=active+issues&show_trend=true&token=OTP6tE2be4X1kvxZRsxRh25e)](https://app.deepsource.com/gh/nktnet1/jewire/)
32&nbsp;
33[![codebeat badge](https://codebeat.co/badges/8bdb4562-0492-4c1c-8b02-e69c94373d60)](https://codebeat.co/projects/github-com-nktnet1-jewire-main)
34&nbsp;
35[![GitHub stars](https://img.shields.io/github/stars/nktnet1/jewire.svg?style=social)](https://github.com/nktnet1/jewire/stargazers)
36
37[![Downloads Total](https://badgen.net/npm/dt/jewire)](https://moiva.io/?npm=jewire)
38&nbsp;
39[![Downloads Yearly](https://badgen.net/npm/dy/jewire)](https://moiva.io/?npm=jewire)
40&nbsp;
41[![Downloads Monthly](https://badgen.net/npm/dm/jewire)](https://moiva.io/?npm=jewire)
42&nbsp;
43[![Downloads Weekly](https://badgen.net/npm/dw/jewire)](https://moiva.io/?npm=jewire)
44&nbsp;
45[![Downloads Daily](https://badgen.net/npm/dd/jewire)](https://moiva.io/?npm=jewire)
46
47---
48
49Access private functions, variables and classes from CommonJS modules
50
51Enable named exports with relative paths identical to CommonJS [require](https://nodejs.org/api/modules.html#requireid)
52
53Clone objects at runtime to remove false negatives in expect[.toStrictEqual](https://jestjs.io/docs/expect#tostrictequalvalue)
54
55[![Try with Replit](https://replit.com/badge?caption=Try%20with%20Replit)](https://replit.com/@nktnet1/jewire-example#index.js)
56
57</div>
58
59---
60
61- [1. Installation](#1-installation)
62- [2. Usage](#2-usage)
63 - [2.1. relativePath](#21-relativepath)
64 - [2.2. options](#22-options)
65 - [2.3. return](#23-return)
66- [3. License](#3-license)
67- [4. Limitations](#4-limitations)
68- [5. Caveats](#5-caveats)
69 - [5.1. Purpose](#51-purpose)
70 - [5.2. Rationale](#52-rationale)
71 - [5.3. Rewire and Jest](#53-rewire-and-jest)
72
73## 1. Installation
74
75```
76npm install jewire
77```
78
79## 2. Usage
80
81Try with [Replit](https://replit.com/@nktnet1/jewire-example#index.js).
82
83```
84jewire(relativePath, options);
85```
86
87<details closed>
88<summary>Examples (click to view)</summary>
89
90<br/>
91
92Importing from the same directory
93
94```javascript
95const { privateVariable, privateFunction } = jewire('private-module');
96```
97
98Importing `.cjs` file from a different directory
99
100```javascript
101const { privateFunction } = jewire('../src/private-module.cjs');
102```
103
104Using a different basePath
105
106```javascript
107const { privateFunction } = jewire(
108 'private-module',
109 { basePath: process.cwd() }
110);
111```
112
113Using a different clone function from the default `clone.objectClone`:
114
115```javascript
116const { privateFunction } = jewire(
117 'private-module',
118 { objectClone: (obj) => JSON.parse(JSON.stringify(obj)) }
119);
120```
121
122</details>
123
124<br/>
125
126### 2.1. Parameter: relativePath
127
128Path to the module relative to the current file, similar to CommonJS [require](https://nodejs.org/api/modules.html#requireid). For example,
129- `'../animals/cats.js'`
130- `'./common.cjs'`
131- `'minimal'`
132 - `jewire` will look for `'./minimal.js'` before `'./minimal.cjs'`
133
134Note that `option.basePath` can be provided to alter this behaviour.
135
136### 2.2. Parameter: options
137
138<table>
139 <tr>
140 <th>Option</th>
141 <th>Description</th>
142 <th>Example</th>
143 <th>Default</th>
144 </tr>
145
146 <tr>
147 <td>basePath</td>
148 <td>Absolute path to the module's directory</td>
149 <td>
150<pre>
151process.cwd()
152</pre>
153 </td>
154 <td><code>__dirname</code></td>
155 </tr>
156
157 <td>
158 objectClone
159 </td>
160 <td>
161 Cloning function to apply to any objects or arrays that are global symbols, function return values or class method return values.
162 </td>
163 <td>
164<pre>
165o => JSON.parse(
166 JSON.stringify(
167 o
168 )
169)
170</pre>
171 </td>
172 <td>
173 <code>objectClone</code>
174 <br />
175 (see <a href='src/clone.ts'>clone.ts</a>)
176 </td>
177
178 </tr>
179</table>
180
181### 2.3. Return Object
182
183All named exports, including globally defined variables, functions and classes are returned as keys within an object.
184
185Additionally, the returned object contains the key `__jewireContext__` with the values being another object with the following properties:
186
1871. `rewire`: the return value of `rewire(modulePath)`. Please refer to the documentation for [rewire](https://github.com/jhnns/rewire) for further details.
1882. `hiddenExportInfo`: An object containing information about all hidden exports, of the form:
189
190 ```javascript
191 {
192 symbols: {
193 variables: string[],
194 functions: string[],
195 classes: string[],
196 }
197 ast: ASTProgram, // Abstract Syntax Tree from Meriyah parser
198 code: string, // return value of fs.readFileSync(filePath)
199 }
200 ```
2013. `jewireGetter`: the internal function used by jewire to retrieve objects. It has the same prototype as [`rewireModule.__get__`](https://github.com/jhnns/rewire?tab=readme-ov-file#rewiredmodule__get__name-string-), although objects are deep cloned using either jewire's default clone function or, if provided, `options.objectClone`.
202
203### 2.4. Errors
204
205If an unknown file path is provided, the given file is empty or the module contains invalid code such as syntax errors, a default [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error) object is thrown.
206
207## 3. License
208
209<details closed>
210<summary>
211 Massachusetts Institute of Technology
212 (<a href="https://opensource.org/license/mit" target="_blank">MIT</a>)
213</summary>
214
215<br/>
216
217```
218Copyright (c) 2023 Khiet Tam Nguyen
219
220Permission is hereby granted, free of charge, to any person obtaining a
221copy of this software and associated documentation files (the “Software”),
222to deal in the Software without restriction, including without limitation
223the rights to use, copy, modify, merge, publish, distribute, sublicense,
224and/or sell copies of the Software, and to permit persons to whom the
225Software is furnished to do so, subject to the following conditions:
226
227The above copyright notice and this permission notice shall be included in
228all copies or substantial portions of the Software.
229
230THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
231IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
232FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
233THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
234LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
235FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
236DEALINGS IN THE SOFTWARE.
237```
238
239[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnktnet1%2Fjewire.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnktnet1%2Fjewire?ref=badge_large)
240
241</details>
242
243## 4. Limitations
244
245As this library uses [rewire](https://github.com/jhnns/rewire) under the hood,
246it has the same limitations in that it can only import CommonJS modules. Please
247see the [limitations](https://github.com/jhnns/rewire#limitations) as described
248in the rewire module.
249
250## 5. Caveats
251
252### 5.1. Purpose
253
254**jewire** is a niche library designed to automark private functions in the
255submitted code of students using the Jest testing framework during the first
2562 weeks of their studies in
257[COMP1531 Software Engineering Fundamentals](https://webcms3.cse.unsw.edu.au/COMP1531/23T2/outline).
258
259This is because `npm` and module imports/exports are not introduced until week
2603, when students are considered to be more familiar with JavaScript as a
261programming language.
262
263### 5.2. Rationale
264
265**jewire** aims to simplify the process of using
266[rewire](https://github.com/jhnns/rewire)
267by removing the need to provide a file extension and absolute path, abstracting
268getter and setter methods and enabling relative module imports similar to CommonJS
269[require](https://nodejs.org/api/modules.html).
270
271This process requires reading the module twice - once to parse into an [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) using the [Meriyah](https://github.com/meriyah/meriyah) parser, and another from rewire as rewire's interface does not enable reusing the file content.
272
273### 5.3. Rewire and Jest
274
275**Jewire** reclones objects at runtime to allow the return values of rewired
276functions and class methods to be compared using
277[Jest](https://jestjs.io)'s
278expect[.toStrictEqual](https://jestjs.io/docs/expect#tostrictequalvalue) matcher,
279which in the rewire module would yield *"Received: serializes to the same
280string"*.
281
282The cause is Jest's utilisation of `node:vm` under the hood, which creates its own temporary context that overrides global classes such as `Array`, `Error` and `Date` to extend functionalities. These global classes differ from those that are returned from [rewire](https://github.com/jhnns/rewire)'s private functions, as depicted in the following GitHub issues made by [@geogezlei](https://github.com/georgezlei):
283- https://github.com/jhnns/rewire/issues/164
284- https://github.com/jestjs/jest/issues/8446
285
286For further details and explanation about this problem, please visit Manuel Spigolon's [article](https://backend.cafe/should-you-use-jest-as-a-testing-library) about the use of the `instanceof` operator in Jest.
287