@pnpm/workspace.project-manifest-reader 1100.1.1 → 1100.1.3
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/CHANGELOG.md +17 -0
- package/lib/index.d.ts +3 -8
- package/lib/index.js +16 -362
- package/lib/manifestExactReader.d.ts +24 -0
- package/lib/manifestExactReader.js +224 -0
- package/lib/manifestRuntime.d.ts +3 -0
- package/lib/manifestRuntime.js +107 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @pnpm/read-project-manifest
|
|
2
2
|
|
|
3
|
+
## 1100.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- @pnpm/error@1100.2.2
|
|
9
|
+
- @pnpm/fs.graceful-fs@1100.2.5
|
|
10
|
+
- @pnpm/pkg-manifest.utils@1100.4.9
|
|
11
|
+
- @pnpm/workspace.project-manifest-writer@1100.0.20
|
|
12
|
+
|
|
13
|
+
## 1100.1.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies:
|
|
18
|
+
- @pnpm/pkg-manifest.utils@1100.4.8
|
|
19
|
+
|
|
3
20
|
## 1100.1.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ProjectManifest } from '@pnpm/types';
|
|
2
|
-
|
|
2
|
+
import { readExactProjectManifest, type ReadExactProjectManifestResult, readExactProjectManifestSync, type WriteProjectManifest } from './manifestExactReader.js';
|
|
3
|
+
export type { ReadExactProjectManifestResult, WriteProjectManifest };
|
|
4
|
+
export { readExactProjectManifest, readExactProjectManifestSync };
|
|
3
5
|
export declare function safeReadProjectManifestOnly(projectDir: string): Promise<ProjectManifest | null>;
|
|
4
6
|
export declare function safeReadPublishManifest(projectDir: string): Promise<ProjectManifest | null>;
|
|
5
7
|
/**
|
|
@@ -18,10 +20,3 @@ export declare function tryReadProjectManifest(projectDir: string): Promise<{
|
|
|
18
20
|
manifest: ProjectManifest | null;
|
|
19
21
|
writeProjectManifest: WriteProjectManifest;
|
|
20
22
|
}>;
|
|
21
|
-
interface ReadExactProjectManifestResult {
|
|
22
|
-
manifest: ProjectManifest;
|
|
23
|
-
writeProjectManifest: WriteProjectManifest;
|
|
24
|
-
}
|
|
25
|
-
export declare function readExactProjectManifest(manifestPath: string): Promise<ReadExactProjectManifestResult>;
|
|
26
|
-
export declare function readExactProjectManifestSync(manifestPath: string): ReadExactProjectManifestResult;
|
|
27
|
-
export {};
|
package/lib/index.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { PnpmError } from '@pnpm/error';
|
|
4
|
-
import { convertEnginesRuntimeToDependencies } from '@pnpm/pkg-manifest.utils';
|
|
5
|
-
import { extractComments } from '@pnpm/text.comments-parser';
|
|
6
4
|
import { writeProjectManifest } from '@pnpm/workspace.project-manifest-writer';
|
|
7
|
-
import detectIndent from 'detect-indent';
|
|
8
|
-
import equal from 'fast-deep-equal';
|
|
9
5
|
import isWindows from 'is-windows';
|
|
10
6
|
import pLimit from 'p-limit';
|
|
11
|
-
import {
|
|
12
|
-
|
|
7
|
+
import { readExactProjectManifest, readExactProjectManifestSync, tryReadProjectManifestFromDir, } from './manifestExactReader.js';
|
|
8
|
+
export { readExactProjectManifest, readExactProjectManifestSync };
|
|
13
9
|
const limitProjectManifestReads = pLimit(4);
|
|
14
10
|
export async function safeReadProjectManifestOnly(projectDir) {
|
|
15
11
|
return limitProjectManifestReads(async () => {
|
|
@@ -35,7 +31,7 @@ export async function safeReadParentPublishManifest(publishDir) {
|
|
|
35
31
|
const normalizedTarget = path.resolve(publishDir);
|
|
36
32
|
let searchDir = path.dirname(normalizedTarget);
|
|
37
33
|
while (true) {
|
|
38
|
-
// eslint-disable-next-line no-await-in-loop
|
|
34
|
+
// eslint-disable-next-line no-await-in-loop -- the search climbs one ancestor at a time and stops at the first match
|
|
39
35
|
const parentManifest = await safeReadProjectManifestOnly(searchDir);
|
|
40
36
|
if (parentManifest?.publishConfig?.directory &&
|
|
41
37
|
path.resolve(searchDir, parentManifest.publishConfig.directory) === normalizedTarget) {
|
|
@@ -59,74 +55,10 @@ export async function readProjectManifestOnly(projectDir) {
|
|
|
59
55
|
return manifest;
|
|
60
56
|
}
|
|
61
57
|
export async function tryReadProjectManifest(projectDir) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
fileName: 'package.json',
|
|
68
|
-
manifest: convertManifestAfterRead(data),
|
|
69
|
-
writeProjectManifest: createManifestWriter({
|
|
70
|
-
...detectFileFormatting(text),
|
|
71
|
-
emptyDependencyFields,
|
|
72
|
-
initialManifest: data,
|
|
73
|
-
manifestPath,
|
|
74
|
-
}),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
catch (err) { // eslint-disable-line
|
|
78
|
-
if (err.code !== 'ENOENT')
|
|
79
|
-
throw err;
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
const manifestPath = path.join(projectDir, 'package.json5');
|
|
83
|
-
const { data, text } = await readJson5File(manifestPath);
|
|
84
|
-
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
85
|
-
return {
|
|
86
|
-
fileName: 'package.json5',
|
|
87
|
-
manifest: convertManifestAfterRead(data),
|
|
88
|
-
writeProjectManifest: createManifestWriter({
|
|
89
|
-
...detectFileFormattingAndComments(text),
|
|
90
|
-
emptyDependencyFields,
|
|
91
|
-
initialManifest: data,
|
|
92
|
-
manifestPath,
|
|
93
|
-
}),
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
catch (err) { // eslint-disable-line
|
|
97
|
-
if (err.code !== 'ENOENT')
|
|
98
|
-
throw err;
|
|
99
|
-
}
|
|
100
|
-
try {
|
|
101
|
-
const manifestPath = path.join(projectDir, 'package.yaml');
|
|
102
|
-
const manifest = await readPackageYaml(manifestPath);
|
|
103
|
-
const emptyDependencyFields = findEmptyDependencyFields(manifest);
|
|
104
|
-
return {
|
|
105
|
-
fileName: 'package.yaml',
|
|
106
|
-
manifest: convertManifestAfterRead(manifest),
|
|
107
|
-
writeProjectManifest: createManifestWriter({ emptyDependencyFields, initialManifest: manifest, manifestPath }),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
catch (err) { // eslint-disable-line
|
|
111
|
-
if (err.code !== 'ENOENT')
|
|
112
|
-
throw err;
|
|
113
|
-
}
|
|
114
|
-
if (isWindows()) {
|
|
115
|
-
// ENOTDIR isn't used on Windows, but pnpm expects it.
|
|
116
|
-
let s;
|
|
117
|
-
try {
|
|
118
|
-
s = await fs.stat(projectDir);
|
|
119
|
-
}
|
|
120
|
-
catch (err) { // eslint-disable-line
|
|
121
|
-
// Ignore
|
|
122
|
-
}
|
|
123
|
-
if ((s != null) && !s.isDirectory()) {
|
|
124
|
-
const err = new Error(`"${projectDir}" is not a directory`);
|
|
125
|
-
// @ts-expect-error
|
|
126
|
-
err['code'] = 'ENOTDIR';
|
|
127
|
-
throw err;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
58
|
+
const found = await tryReadProjectManifestFromDir(projectDir);
|
|
59
|
+
if (found)
|
|
60
|
+
return found;
|
|
61
|
+
await assertDirectoryExistsOnWindows(projectDir);
|
|
130
62
|
const filePath = path.join(projectDir, 'package.json');
|
|
131
63
|
return {
|
|
132
64
|
fileName: 'package.json',
|
|
@@ -134,297 +66,19 @@ export async function tryReadProjectManifest(projectDir) {
|
|
|
134
66
|
writeProjectManifest: async (manifest) => writeProjectManifest(filePath, manifest),
|
|
135
67
|
};
|
|
136
68
|
}
|
|
137
|
-
function
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
indent: detectIndent(newText).indent,
|
|
143
|
-
insertFinalNewline: hasFinalNewline,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function detectFileFormatting(text) {
|
|
147
|
-
return {
|
|
148
|
-
crlf: text.includes('\r\n'),
|
|
149
|
-
indent: detectIndent(text).indent,
|
|
150
|
-
insertFinalNewline: text.endsWith('\n'),
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
export async function readExactProjectManifest(manifestPath) {
|
|
154
|
-
const base = path.basename(manifestPath).toLowerCase();
|
|
155
|
-
switch (base) {
|
|
156
|
-
case 'package.json': {
|
|
157
|
-
const { data, text } = await readJsonFile(manifestPath);
|
|
158
|
-
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
159
|
-
return {
|
|
160
|
-
manifest: convertManifestAfterRead(data),
|
|
161
|
-
writeProjectManifest: createManifestWriter({
|
|
162
|
-
...detectFileFormatting(text),
|
|
163
|
-
emptyDependencyFields,
|
|
164
|
-
initialManifest: data,
|
|
165
|
-
manifestPath,
|
|
166
|
-
}),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
case 'package.json5': {
|
|
170
|
-
const { data, text } = await readJson5File(manifestPath);
|
|
171
|
-
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
172
|
-
return {
|
|
173
|
-
manifest: convertManifestAfterRead(data),
|
|
174
|
-
writeProjectManifest: createManifestWriter({
|
|
175
|
-
...detectFileFormattingAndComments(text),
|
|
176
|
-
emptyDependencyFields,
|
|
177
|
-
initialManifest: data,
|
|
178
|
-
manifestPath,
|
|
179
|
-
}),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
case 'package.yaml': {
|
|
183
|
-
const manifest = await readPackageYaml(manifestPath);
|
|
184
|
-
const emptyDependencyFields = findEmptyDependencyFields(manifest);
|
|
185
|
-
return {
|
|
186
|
-
manifest: convertManifestAfterRead(manifest),
|
|
187
|
-
writeProjectManifest: createManifestWriter({ emptyDependencyFields, initialManifest: manifest, manifestPath }),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
throw new Error(`Not supported manifest name "${base}"`);
|
|
192
|
-
}
|
|
193
|
-
export function readExactProjectManifestSync(manifestPath) {
|
|
194
|
-
const base = path.basename(manifestPath).toLowerCase();
|
|
195
|
-
switch (base) {
|
|
196
|
-
case 'package.json': {
|
|
197
|
-
const { data, text } = readJsonFileSync(manifestPath);
|
|
198
|
-
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
199
|
-
return {
|
|
200
|
-
manifest: convertManifestAfterRead(data),
|
|
201
|
-
writeProjectManifest: createManifestWriter({
|
|
202
|
-
...detectFileFormatting(text),
|
|
203
|
-
emptyDependencyFields,
|
|
204
|
-
initialManifest: data,
|
|
205
|
-
manifestPath,
|
|
206
|
-
}),
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
case 'package.json5': {
|
|
210
|
-
const { data, text } = readJson5FileSync(manifestPath);
|
|
211
|
-
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
212
|
-
return {
|
|
213
|
-
manifest: convertManifestAfterRead(data),
|
|
214
|
-
writeProjectManifest: createManifestWriter({
|
|
215
|
-
...detectFileFormattingAndComments(text),
|
|
216
|
-
emptyDependencyFields,
|
|
217
|
-
initialManifest: data,
|
|
218
|
-
manifestPath,
|
|
219
|
-
}),
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
case 'package.yaml': {
|
|
223
|
-
const manifest = readPackageYamlSync(manifestPath);
|
|
224
|
-
const emptyDependencyFields = findEmptyDependencyFields(manifest);
|
|
225
|
-
return {
|
|
226
|
-
manifest: convertManifestAfterRead(manifest),
|
|
227
|
-
writeProjectManifest: createManifestWriter({ emptyDependencyFields, initialManifest: manifest, manifestPath }),
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
throw new Error(`Not supported manifest name "${base}"`);
|
|
232
|
-
}
|
|
233
|
-
async function readPackageYaml(filePath) {
|
|
234
|
-
try {
|
|
235
|
-
return await readYamlFile(filePath);
|
|
236
|
-
}
|
|
237
|
-
catch (err) { // eslint-disable-line
|
|
238
|
-
if (err.name !== 'YAMLException')
|
|
239
|
-
throw err;
|
|
240
|
-
err.message = `${err.message}\nin ${filePath}`;
|
|
241
|
-
err.code = 'ERR_PNPM_YAML_PARSE';
|
|
242
|
-
throw err;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
function readPackageYamlSync(filePath) {
|
|
69
|
+
async function assertDirectoryExistsOnWindows(projectDir) {
|
|
70
|
+
if (!isWindows())
|
|
71
|
+
return;
|
|
72
|
+
// ENOTDIR isn't used on Windows, but pnpm expects it.
|
|
73
|
+
let projectDirStats;
|
|
246
74
|
try {
|
|
247
|
-
|
|
75
|
+
projectDirStats = await fs.stat(projectDir);
|
|
248
76
|
}
|
|
249
77
|
catch (err) { // eslint-disable-line
|
|
250
|
-
|
|
251
|
-
throw err;
|
|
252
|
-
err.message = `${err.message}\nin ${filePath}`;
|
|
253
|
-
err.code = 'ERR_PNPM_YAML_PARSE';
|
|
254
|
-
throw err;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function createManifestWriter(opts) {
|
|
258
|
-
let emptyDependencyFields = opts.emptyDependencyFields ?? findEmptyDependencyFields(opts.initialManifest);
|
|
259
|
-
let initialManifest = normalize(opts.initialManifest, emptyDependencyFields);
|
|
260
|
-
return async (updatedManifest, force) => {
|
|
261
|
-
updatedManifest = convertManifestBeforeWrite(normalize(updatedManifest, emptyDependencyFields));
|
|
262
|
-
if (force === true || !equal(initialManifest, updatedManifest)) {
|
|
263
|
-
await writeProjectManifest(opts.manifestPath, updatedManifest, {
|
|
264
|
-
comments: opts.comments,
|
|
265
|
-
crlf: opts.crlf,
|
|
266
|
-
indent: opts.indent,
|
|
267
|
-
insertFinalNewline: opts.insertFinalNewline,
|
|
268
|
-
});
|
|
269
|
-
emptyDependencyFields = findEmptyDependencyFields(updatedManifest);
|
|
270
|
-
initialManifest = normalize(updatedManifest, emptyDependencyFields);
|
|
271
|
-
return Promise.resolve(undefined);
|
|
272
|
-
}
|
|
273
|
-
return Promise.resolve(undefined);
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function convertManifestAfterRead(manifest) {
|
|
277
|
-
const cloned = cloneManifestForRuntimeConversion(manifest);
|
|
278
|
-
convertEnginesRuntimeToDependencies(cloned, 'devEngines', 'devDependencies');
|
|
279
|
-
convertEnginesRuntimeToDependencies(cloned, 'engines', 'dependencies');
|
|
280
|
-
return cloned;
|
|
281
|
-
}
|
|
282
|
-
function convertManifestBeforeWrite(manifest) {
|
|
283
|
-
const cloned = cloneManifestForRuntimeConversion(manifest);
|
|
284
|
-
convertDependenciesToEnginesRuntime(cloned, 'devDependencies', 'devEngines');
|
|
285
|
-
convertDependenciesToEnginesRuntime(cloned, 'dependencies', 'engines');
|
|
286
|
-
return cloned;
|
|
287
|
-
}
|
|
288
|
-
function cloneManifestForRuntimeConversion(manifest) {
|
|
289
|
-
const cloned = { ...manifest };
|
|
290
|
-
if (manifest.dependencies != null && typeof manifest.dependencies === 'object' && !Array.isArray(manifest.dependencies)) {
|
|
291
|
-
cloned.dependencies = { ...manifest.dependencies };
|
|
78
|
+
// Ignore
|
|
292
79
|
}
|
|
293
|
-
if (
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
if (manifest.engines != null && typeof manifest.engines === 'object' && !Array.isArray(manifest.engines)) {
|
|
297
|
-
cloned.engines = { ...manifest.engines };
|
|
298
|
-
}
|
|
299
|
-
if (manifest.devEngines != null && typeof manifest.devEngines === 'object' && !Array.isArray(manifest.devEngines)) {
|
|
300
|
-
cloned.devEngines = { ...manifest.devEngines };
|
|
301
|
-
}
|
|
302
|
-
return cloned;
|
|
303
|
-
}
|
|
304
|
-
function convertDependenciesToEnginesRuntime(manifest, dependenciesFieldName, enginesFieldName) {
|
|
305
|
-
const dependencies = readDependenciesField(manifest, dependenciesFieldName);
|
|
306
|
-
for (const runtimeName of ['node', 'deno', 'bun']) {
|
|
307
|
-
const dep = dependencies?.[runtimeName];
|
|
308
|
-
if (dependencies != null && typeof dep === 'string' && dep.startsWith('runtime:')) {
|
|
309
|
-
const version = dep.slice('runtime:'.length).trim();
|
|
310
|
-
manifest[enginesFieldName] ??= {};
|
|
311
|
-
const runtimeEntry = {
|
|
312
|
-
name: runtimeName,
|
|
313
|
-
version,
|
|
314
|
-
onFail: 'download',
|
|
315
|
-
};
|
|
316
|
-
const enginesField = manifest[enginesFieldName];
|
|
317
|
-
if (!enginesField.runtime) {
|
|
318
|
-
enginesField.runtime = runtimeEntry;
|
|
319
|
-
}
|
|
320
|
-
else if (Array.isArray(enginesField.runtime)) {
|
|
321
|
-
const existing = enginesField.runtime.find(({ name }) => name === runtimeName);
|
|
322
|
-
if (existing) {
|
|
323
|
-
Object.assign(existing, runtimeEntry);
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
enginesField.runtime.push(runtimeEntry);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else if (enginesField.runtime.name === runtimeName) {
|
|
330
|
-
Object.assign(enginesField.runtime, runtimeEntry);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
enginesField.runtime = [
|
|
334
|
-
enginesField.runtime,
|
|
335
|
-
runtimeEntry,
|
|
336
|
-
];
|
|
337
|
-
}
|
|
338
|
-
delete dependencies[runtimeName];
|
|
339
|
-
}
|
|
340
|
-
else if (dep === undefined) {
|
|
341
|
-
removeManagedRuntimeEntry(manifest[enginesFieldName], runtimeName);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
function readDependenciesField(manifest, dependenciesFieldName) {
|
|
346
|
-
const dependencies = manifest[dependenciesFieldName];
|
|
347
|
-
if (dependencies === undefined)
|
|
348
|
-
return undefined;
|
|
349
|
-
if (dependencies === null || typeof dependencies !== 'object' || Array.isArray(dependencies)) {
|
|
350
|
-
throw new PnpmError('INVALID_DEPENDENCIES_FIELD', `The "${dependenciesFieldName}" field must be an object.`);
|
|
351
|
-
}
|
|
352
|
-
return dependencies;
|
|
353
|
-
}
|
|
354
|
-
function removeManagedRuntimeEntry(enginesField, runtimeName) {
|
|
355
|
-
if (!enginesField?.runtime)
|
|
356
|
-
return;
|
|
357
|
-
if (Array.isArray(enginesField.runtime)) {
|
|
358
|
-
const runtimes = enginesField.runtime.filter((runtime) => !isManagedRuntimeEntry(runtime, runtimeName));
|
|
359
|
-
if (runtimes.length === 0) {
|
|
360
|
-
delete enginesField.runtime;
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
enginesField.runtime = runtimes;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else if (isManagedRuntimeEntry(enginesField.runtime, runtimeName)) {
|
|
367
|
-
delete enginesField.runtime;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
function isManagedRuntimeEntry(runtime, runtimeName) {
|
|
371
|
-
return runtime.name === runtimeName &&
|
|
372
|
-
runtime.onFail === 'download' &&
|
|
373
|
-
typeof runtime.version === 'string';
|
|
374
|
-
}
|
|
375
|
-
const dependencyKeys = new Set([
|
|
376
|
-
'dependencies',
|
|
377
|
-
'devDependencies',
|
|
378
|
-
'optionalDependencies',
|
|
379
|
-
'peerDependencies',
|
|
380
|
-
]);
|
|
381
|
-
/**
|
|
382
|
-
* The dependency fields the manifest declares as empty objects. A write
|
|
383
|
-
* keeps these in place; it only drops a field that pnpm itself emptied.
|
|
384
|
-
*/
|
|
385
|
-
function findEmptyDependencyFields(manifest) {
|
|
386
|
-
const fields = new Set();
|
|
387
|
-
for (const key of dependencyKeys) {
|
|
388
|
-
if (isEmptyDependencyObject(manifest[key])) {
|
|
389
|
-
fields.add(key);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
return fields;
|
|
393
|
-
}
|
|
394
|
-
function isEmptyDependencyObject(value) {
|
|
395
|
-
return typeof value === 'object' &&
|
|
396
|
-
value !== null &&
|
|
397
|
-
!Array.isArray(value) &&
|
|
398
|
-
Object.keys(value).length === 0;
|
|
399
|
-
}
|
|
400
|
-
function normalize(manifest, keepEmptyDependencyFields) {
|
|
401
|
-
const result = {};
|
|
402
|
-
for (const key in manifest) {
|
|
403
|
-
if (Object.hasOwn(manifest, key)) {
|
|
404
|
-
const value = manifest[key];
|
|
405
|
-
if (typeof value !== 'object' ||
|
|
406
|
-
value === null ||
|
|
407
|
-
!dependencyKeys.has(key) ||
|
|
408
|
-
Array.isArray(value)) {
|
|
409
|
-
result[key] = structuredClone(value);
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
const keys = Object.keys(value);
|
|
413
|
-
if (keys.length !== 0) {
|
|
414
|
-
keys.sort();
|
|
415
|
-
const sortedValue = {};
|
|
416
|
-
for (const k of keys) {
|
|
417
|
-
// @ts-expect-error this is fine
|
|
418
|
-
sortedValue[k] = value[k];
|
|
419
|
-
}
|
|
420
|
-
result[key] = sortedValue;
|
|
421
|
-
}
|
|
422
|
-
else if (keepEmptyDependencyFields.has(key)) {
|
|
423
|
-
result[key] = {};
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
80
|
+
if ((projectDirStats != null) && !projectDirStats.isDirectory()) {
|
|
81
|
+
throw Object.assign(new Error(`"${projectDir}" is not a directory`), { code: 'ENOTDIR' });
|
|
427
82
|
}
|
|
428
|
-
return result;
|
|
429
83
|
}
|
|
430
84
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CommentSpecifier } from '@pnpm/text.comments-parser';
|
|
2
|
+
import type { ProjectManifest } from '@pnpm/types';
|
|
3
|
+
export type WriteProjectManifest = (manifest: ProjectManifest, force?: boolean) => Promise<void>;
|
|
4
|
+
export interface ReadExactProjectManifestResult {
|
|
5
|
+
manifest: ProjectManifest;
|
|
6
|
+
writeProjectManifest: WriteProjectManifest;
|
|
7
|
+
}
|
|
8
|
+
export declare function readExactProjectManifest(manifestPath: string): Promise<ReadExactProjectManifestResult>;
|
|
9
|
+
export declare function readExactProjectManifestSync(manifestPath: string): ReadExactProjectManifestResult;
|
|
10
|
+
export declare function tryReadProjectManifestFromDir(projectDir: string): Promise<{
|
|
11
|
+
fileName: string;
|
|
12
|
+
manifest: ProjectManifest;
|
|
13
|
+
writeProjectManifest: WriteProjectManifest;
|
|
14
|
+
} | undefined>;
|
|
15
|
+
export declare function createManifestWriter(opts: {
|
|
16
|
+
initialManifest: ProjectManifest;
|
|
17
|
+
emptyDependencyFields?: ReadonlySet<string>;
|
|
18
|
+
comments?: CommentSpecifier[];
|
|
19
|
+
crlf?: boolean;
|
|
20
|
+
indent?: string | number | undefined;
|
|
21
|
+
insertFinalNewline?: boolean;
|
|
22
|
+
manifestPath: string;
|
|
23
|
+
}): WriteProjectManifest;
|
|
24
|
+
export declare function findEmptyDependencyFields(manifest: ProjectManifest): Set<string>;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { extractComments } from '@pnpm/text.comments-parser';
|
|
3
|
+
import { writeProjectManifest } from '@pnpm/workspace.project-manifest-writer';
|
|
4
|
+
import detectIndent from 'detect-indent';
|
|
5
|
+
import equal from 'fast-deep-equal';
|
|
6
|
+
import { readYamlFile, readYamlFileSync } from 'read-yaml-file';
|
|
7
|
+
import { convertManifestAfterRead, convertManifestBeforeWrite } from './manifestRuntime.js';
|
|
8
|
+
import { readJson5File, readJson5FileSync, readJsonFile, readJsonFileSync, } from './readFile.js';
|
|
9
|
+
export async function readExactProjectManifest(manifestPath) {
|
|
10
|
+
const base = path.basename(manifestPath).toLowerCase();
|
|
11
|
+
switch (base) {
|
|
12
|
+
case 'package.json':
|
|
13
|
+
return readExactPackageJson(manifestPath);
|
|
14
|
+
case 'package.json5':
|
|
15
|
+
return readExactPackageJson5(manifestPath);
|
|
16
|
+
case 'package.yaml':
|
|
17
|
+
return readExactPackageYaml(manifestPath);
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`Not supported manifest name "${base}"`);
|
|
20
|
+
}
|
|
21
|
+
export function readExactProjectManifestSync(manifestPath) {
|
|
22
|
+
const base = path.basename(manifestPath).toLowerCase();
|
|
23
|
+
switch (base) {
|
|
24
|
+
case 'package.json':
|
|
25
|
+
return readExactPackageJsonSync(manifestPath);
|
|
26
|
+
case 'package.json5':
|
|
27
|
+
return readExactPackageJson5Sync(manifestPath);
|
|
28
|
+
case 'package.yaml':
|
|
29
|
+
return readExactPackageYamlSync(manifestPath);
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Not supported manifest name "${base}"`);
|
|
32
|
+
}
|
|
33
|
+
export async function tryReadProjectManifestFromDir(projectDir) {
|
|
34
|
+
const jsonResult = await tryReadPackageJson(projectDir);
|
|
35
|
+
if (jsonResult)
|
|
36
|
+
return jsonResult;
|
|
37
|
+
const json5Result = await tryReadPackageJson5(projectDir);
|
|
38
|
+
if (json5Result)
|
|
39
|
+
return json5Result;
|
|
40
|
+
return tryReadPackageYaml(projectDir);
|
|
41
|
+
}
|
|
42
|
+
async function tryReadPackageJson(projectDir) {
|
|
43
|
+
try {
|
|
44
|
+
const manifestPath = path.join(projectDir, 'package.json');
|
|
45
|
+
const result = await readExactPackageJson(manifestPath);
|
|
46
|
+
return { fileName: 'package.json', ...result };
|
|
47
|
+
}
|
|
48
|
+
catch (err) { // eslint-disable-line
|
|
49
|
+
if (err.code !== 'ENOENT')
|
|
50
|
+
throw err;
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function tryReadPackageJson5(projectDir) {
|
|
55
|
+
try {
|
|
56
|
+
const manifestPath = path.join(projectDir, 'package.json5');
|
|
57
|
+
const result = await readExactPackageJson5(manifestPath);
|
|
58
|
+
return { fileName: 'package.json5', ...result };
|
|
59
|
+
}
|
|
60
|
+
catch (err) { // eslint-disable-line
|
|
61
|
+
if (err.code !== 'ENOENT')
|
|
62
|
+
throw err;
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function tryReadPackageYaml(projectDir) {
|
|
67
|
+
try {
|
|
68
|
+
const manifestPath = path.join(projectDir, 'package.yaml');
|
|
69
|
+
const result = await readExactPackageYaml(manifestPath);
|
|
70
|
+
return { fileName: 'package.yaml', ...result };
|
|
71
|
+
}
|
|
72
|
+
catch (err) { // eslint-disable-line
|
|
73
|
+
if (err.code !== 'ENOENT')
|
|
74
|
+
throw err;
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function readExactPackageJson(manifestPath) {
|
|
79
|
+
const { data, text } = await readJsonFile(manifestPath);
|
|
80
|
+
return createManifestResult(data, manifestPath, detectFileFormatting(text));
|
|
81
|
+
}
|
|
82
|
+
function readExactPackageJsonSync(manifestPath) {
|
|
83
|
+
const { data, text } = readJsonFileSync(manifestPath);
|
|
84
|
+
return createManifestResult(data, manifestPath, detectFileFormatting(text));
|
|
85
|
+
}
|
|
86
|
+
async function readExactPackageJson5(manifestPath) {
|
|
87
|
+
const { data, text } = await readJson5File(manifestPath);
|
|
88
|
+
return createManifestResult(data, manifestPath, detectFileFormattingAndComments(text));
|
|
89
|
+
}
|
|
90
|
+
function readExactPackageJson5Sync(manifestPath) {
|
|
91
|
+
const { data, text } = readJson5FileSync(manifestPath);
|
|
92
|
+
return createManifestResult(data, manifestPath, detectFileFormattingAndComments(text));
|
|
93
|
+
}
|
|
94
|
+
async function readExactPackageYaml(manifestPath) {
|
|
95
|
+
const manifest = await readPackageYaml(manifestPath);
|
|
96
|
+
return createManifestResult(manifest, manifestPath);
|
|
97
|
+
}
|
|
98
|
+
function readExactPackageYamlSync(manifestPath) {
|
|
99
|
+
const manifest = readPackageYamlSync(manifestPath);
|
|
100
|
+
return createManifestResult(manifest, manifestPath);
|
|
101
|
+
}
|
|
102
|
+
function createManifestResult(data, manifestPath, formatting) {
|
|
103
|
+
const emptyDependencyFields = findEmptyDependencyFields(data);
|
|
104
|
+
return {
|
|
105
|
+
manifest: convertManifestAfterRead(data),
|
|
106
|
+
writeProjectManifest: createManifestWriter({
|
|
107
|
+
...formatting,
|
|
108
|
+
emptyDependencyFields,
|
|
109
|
+
initialManifest: data,
|
|
110
|
+
manifestPath,
|
|
111
|
+
}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function detectFileFormatting(text) {
|
|
115
|
+
return {
|
|
116
|
+
crlf: text.includes('\r\n'),
|
|
117
|
+
indent: detectIndent(text).indent,
|
|
118
|
+
insertFinalNewline: text.endsWith('\n'),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function detectFileFormattingAndComments(text) {
|
|
122
|
+
const { comments, text: newText, hasFinalNewline } = extractComments(text);
|
|
123
|
+
return {
|
|
124
|
+
comments,
|
|
125
|
+
crlf: text.includes('\r\n'),
|
|
126
|
+
indent: detectIndent(newText).indent,
|
|
127
|
+
insertFinalNewline: hasFinalNewline,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
async function readPackageYaml(filePath) {
|
|
131
|
+
try {
|
|
132
|
+
return await readYamlFile(filePath);
|
|
133
|
+
}
|
|
134
|
+
catch (err) { // eslint-disable-line
|
|
135
|
+
if (err.name !== 'YAMLException')
|
|
136
|
+
throw err;
|
|
137
|
+
err.message = `${err.message}\nin ${filePath}`;
|
|
138
|
+
err.code = 'ERR_PNPM_YAML_PARSE';
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function readPackageYamlSync(filePath) {
|
|
143
|
+
try {
|
|
144
|
+
return readYamlFileSync(filePath);
|
|
145
|
+
}
|
|
146
|
+
catch (err) { // eslint-disable-line
|
|
147
|
+
if (err.name !== 'YAMLException')
|
|
148
|
+
throw err;
|
|
149
|
+
err.message = `${err.message}\nin ${filePath}`;
|
|
150
|
+
err.code = 'ERR_PNPM_YAML_PARSE';
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export function createManifestWriter(opts) {
|
|
155
|
+
let emptyDependencyFields = opts.emptyDependencyFields ?? findEmptyDependencyFields(opts.initialManifest);
|
|
156
|
+
let initialManifest = normalize(opts.initialManifest, emptyDependencyFields);
|
|
157
|
+
return async (updatedManifest, force) => {
|
|
158
|
+
updatedManifest = convertManifestBeforeWrite(normalize(updatedManifest, emptyDependencyFields));
|
|
159
|
+
if (force === true || !equal(initialManifest, updatedManifest)) {
|
|
160
|
+
await writeProjectManifest(opts.manifestPath, updatedManifest, {
|
|
161
|
+
comments: opts.comments,
|
|
162
|
+
crlf: opts.crlf,
|
|
163
|
+
indent: opts.indent,
|
|
164
|
+
insertFinalNewline: opts.insertFinalNewline,
|
|
165
|
+
});
|
|
166
|
+
emptyDependencyFields = findEmptyDependencyFields(updatedManifest);
|
|
167
|
+
initialManifest = normalize(updatedManifest, emptyDependencyFields);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const DEPENDENCY_KEYS = new Set([
|
|
172
|
+
'dependencies',
|
|
173
|
+
'devDependencies',
|
|
174
|
+
'optionalDependencies',
|
|
175
|
+
'peerDependencies',
|
|
176
|
+
]);
|
|
177
|
+
export function findEmptyDependencyFields(manifest) {
|
|
178
|
+
const fields = new Set();
|
|
179
|
+
for (const key of DEPENDENCY_KEYS) {
|
|
180
|
+
if (isEmptyDependencyObject(manifest[key])) {
|
|
181
|
+
fields.add(key);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return fields;
|
|
185
|
+
}
|
|
186
|
+
function isEmptyDependencyObject(value) {
|
|
187
|
+
return typeof value === 'object' &&
|
|
188
|
+
value !== null &&
|
|
189
|
+
!Array.isArray(value) &&
|
|
190
|
+
Object.keys(value).length === 0;
|
|
191
|
+
}
|
|
192
|
+
function normalize(manifest, keepEmptyDependencyFields) {
|
|
193
|
+
const result = {};
|
|
194
|
+
for (const key of Object.keys(manifest)) {
|
|
195
|
+
const value = manifest[key];
|
|
196
|
+
if (isDependencyObject(value, key)) {
|
|
197
|
+
const keys = Object.keys(value);
|
|
198
|
+
if (keys.length !== 0) {
|
|
199
|
+
result[key] = sortObjectKeys(value, keys.sort());
|
|
200
|
+
}
|
|
201
|
+
else if (keepEmptyDependencyFields.has(key)) {
|
|
202
|
+
result[key] = {};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
result[key] = structuredClone(value);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
function isDependencyObject(value, key) {
|
|
212
|
+
return typeof value === 'object' &&
|
|
213
|
+
value !== null &&
|
|
214
|
+
DEPENDENCY_KEYS.has(key) &&
|
|
215
|
+
!Array.isArray(value);
|
|
216
|
+
}
|
|
217
|
+
function sortObjectKeys(source, sortedKeys) {
|
|
218
|
+
const sorted = {};
|
|
219
|
+
for (const fieldName of sortedKeys) {
|
|
220
|
+
sorted[fieldName] = source[fieldName];
|
|
221
|
+
}
|
|
222
|
+
return sorted;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=manifestExactReader.js.map
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
|
+
import { convertEnginesRuntimeToDependencies } from '@pnpm/pkg-manifest.utils';
|
|
3
|
+
export function convertManifestAfterRead(manifest) {
|
|
4
|
+
const cloned = cloneManifestForRuntimeConversion(manifest);
|
|
5
|
+
convertEnginesRuntimeToDependencies(cloned, 'devEngines', 'devDependencies');
|
|
6
|
+
convertEnginesRuntimeToDependencies(cloned, 'engines', 'dependencies');
|
|
7
|
+
return cloned;
|
|
8
|
+
}
|
|
9
|
+
export function convertManifestBeforeWrite(manifest) {
|
|
10
|
+
const cloned = cloneManifestForRuntimeConversion(manifest);
|
|
11
|
+
convertDependenciesToEnginesRuntime(cloned, 'devDependencies', 'devEngines');
|
|
12
|
+
convertDependenciesToEnginesRuntime(cloned, 'dependencies', 'engines');
|
|
13
|
+
return cloned;
|
|
14
|
+
}
|
|
15
|
+
function cloneManifestForRuntimeConversion(manifest) {
|
|
16
|
+
const cloned = { ...manifest };
|
|
17
|
+
if (manifest.dependencies != null && typeof manifest.dependencies === 'object' && !Array.isArray(manifest.dependencies)) {
|
|
18
|
+
cloned.dependencies = { ...manifest.dependencies };
|
|
19
|
+
}
|
|
20
|
+
if (manifest.devDependencies != null && typeof manifest.devDependencies === 'object' && !Array.isArray(manifest.devDependencies)) {
|
|
21
|
+
cloned.devDependencies = { ...manifest.devDependencies };
|
|
22
|
+
}
|
|
23
|
+
if (manifest.engines != null && typeof manifest.engines === 'object' && !Array.isArray(manifest.engines)) {
|
|
24
|
+
cloned.engines = { ...manifest.engines };
|
|
25
|
+
}
|
|
26
|
+
if (manifest.devEngines != null && typeof manifest.devEngines === 'object' && !Array.isArray(manifest.devEngines)) {
|
|
27
|
+
cloned.devEngines = { ...manifest.devEngines };
|
|
28
|
+
}
|
|
29
|
+
return cloned;
|
|
30
|
+
}
|
|
31
|
+
function convertDependenciesToEnginesRuntime(manifest, dependenciesFieldName, enginesFieldName) {
|
|
32
|
+
const dependencies = readDependenciesField(manifest, dependenciesFieldName);
|
|
33
|
+
for (const runtimeName of ['node', 'deno', 'bun']) {
|
|
34
|
+
applyRuntimeConversion(manifest, enginesFieldName, dependencies, runtimeName);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function applyRuntimeConversion(manifest, enginesFieldName, dependencies, runtimeName) {
|
|
38
|
+
const dep = dependencies?.[runtimeName];
|
|
39
|
+
if (dependencies != null && typeof dep === 'string' && dep.startsWith('runtime:')) {
|
|
40
|
+
setManagedRuntimeEntry(manifest, enginesFieldName, runtimeName, dep.slice('runtime:'.length).trim());
|
|
41
|
+
delete dependencies[runtimeName];
|
|
42
|
+
}
|
|
43
|
+
else if (dep === undefined) {
|
|
44
|
+
removeManagedRuntimeEntry(manifest[enginesFieldName], runtimeName);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function setManagedRuntimeEntry(manifest, enginesFieldName, runtimeName, version) {
|
|
48
|
+
manifest[enginesFieldName] ??= {};
|
|
49
|
+
const runtimeEntry = {
|
|
50
|
+
name: runtimeName,
|
|
51
|
+
version,
|
|
52
|
+
onFail: 'download',
|
|
53
|
+
};
|
|
54
|
+
const enginesField = manifest[enginesFieldName];
|
|
55
|
+
if (!enginesField.runtime) {
|
|
56
|
+
enginesField.runtime = runtimeEntry;
|
|
57
|
+
}
|
|
58
|
+
else if (Array.isArray(enginesField.runtime)) {
|
|
59
|
+
updateRuntimeInList(enginesField.runtime, runtimeEntry);
|
|
60
|
+
}
|
|
61
|
+
else if (enginesField.runtime.name === runtimeName) {
|
|
62
|
+
Object.assign(enginesField.runtime, runtimeEntry);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
enginesField.runtime = [enginesField.runtime, runtimeEntry];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function updateRuntimeInList(runtimes, runtimeEntry) {
|
|
69
|
+
const existing = runtimes.find(({ name }) => name === runtimeEntry.name);
|
|
70
|
+
if (existing) {
|
|
71
|
+
Object.assign(existing, runtimeEntry);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
runtimes.push(runtimeEntry);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function readDependenciesField(manifest, dependenciesFieldName) {
|
|
78
|
+
const dependencies = manifest[dependenciesFieldName];
|
|
79
|
+
if (dependencies === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
if (dependencies === null || typeof dependencies !== 'object' || Array.isArray(dependencies)) {
|
|
82
|
+
throw new PnpmError('INVALID_DEPENDENCIES_FIELD', `The "${dependenciesFieldName}" field must be an object.`);
|
|
83
|
+
}
|
|
84
|
+
return dependencies;
|
|
85
|
+
}
|
|
86
|
+
function removeManagedRuntimeEntry(enginesField, runtimeName) {
|
|
87
|
+
if (!enginesField?.runtime)
|
|
88
|
+
return;
|
|
89
|
+
if (Array.isArray(enginesField.runtime)) {
|
|
90
|
+
const runtimes = enginesField.runtime.filter((runtime) => !isManagedRuntimeEntry(runtime, runtimeName));
|
|
91
|
+
if (runtimes.length === 0) {
|
|
92
|
+
delete enginesField.runtime;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
enginesField.runtime = runtimes;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (isManagedRuntimeEntry(enginesField.runtime, runtimeName)) {
|
|
99
|
+
delete enginesField.runtime;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function isManagedRuntimeEntry(runtime, runtimeName) {
|
|
103
|
+
return runtime.name === runtimeName &&
|
|
104
|
+
runtime.onFail === 'download' &&
|
|
105
|
+
typeof runtime.version === 'string';
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=manifestRuntime.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/workspace.project-manifest-reader",
|
|
3
|
-
"version": "1100.1.
|
|
3
|
+
"version": "1100.1.3",
|
|
4
4
|
"description": "Read a project manifest (called package.json in most cases)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"!*.map"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pnpm/error": "1100.2.
|
|
31
|
-
"@pnpm/fs.graceful-fs": "1100.2.
|
|
32
|
-
"@pnpm/pkg-manifest.utils": "1100.4.
|
|
30
|
+
"@pnpm/error": "1100.2.2",
|
|
31
|
+
"@pnpm/fs.graceful-fs": "1100.2.5",
|
|
32
|
+
"@pnpm/pkg-manifest.utils": "1100.4.9",
|
|
33
33
|
"@pnpm/text.comments-parser": "1100.0.1",
|
|
34
34
|
"@pnpm/types": "1102.1.1",
|
|
35
|
-
"@pnpm/workspace.project-manifest-writer": "1100.0.
|
|
35
|
+
"@pnpm/workspace.project-manifest-writer": "1100.0.20",
|
|
36
36
|
"detect-indent": "7.0.2",
|
|
37
37
|
"fast-deep-equal": "^3.1.3",
|
|
38
38
|
"is-windows": "^1.0.2",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@jest/globals": "30.4.1",
|
|
50
50
|
"@pnpm/test-fixtures": "1100.0.1",
|
|
51
|
-
"@pnpm/workspace.project-manifest-reader": "1100.1.
|
|
51
|
+
"@pnpm/workspace.project-manifest-reader": "1100.1.3",
|
|
52
52
|
"@types/is-windows": "^1.0.2",
|
|
53
53
|
"@types/parse-json": "^7.0.0",
|
|
54
54
|
"tempy": "3.0.0"
|