source: trip-planner-front/node_modules/read-package-json-fast/index.js@ eed0bf8

Last change on this file since eed0bf8 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 3.6 KB
Line 
1const {promisify} = require('util')
2const fs = require('fs')
3const readFile = promisify(fs.readFile)
4const lstat = promisify(fs.lstat)
5const readdir = promisify(fs.readdir)
6const parse = require('json-parse-even-better-errors')
7
8const { resolve, dirname, join, relative } = require('path')
9
10const rpj = path => readFile(path, 'utf8')
11 .then(data => readBinDir(path, normalize(stripUnderscores(parse(data)))))
12 .catch(er => {
13 er.path = path
14 throw er
15 })
16
17const normalizePackageBin = require('npm-normalize-package-bin')
18
19// load the directories.bin folder as a 'bin' object
20const readBinDir = async (path, data) => {
21 if (data.bin)
22 return data
23
24 const m = data.directories && data.directories.bin
25 if (!m || typeof m !== 'string')
26 return data
27
28 // cut off any monkey business, like setting directories.bin
29 // to ../../../etc/passwd or /etc/passwd or something like that.
30 const root = dirname(path)
31 const dir = join('.', join('/', m))
32 data.bin = await walkBinDir(root, dir, {})
33 return data
34}
35
36const walkBinDir = async (root, dir, obj) => {
37 const entries = await readdir(resolve(root, dir)).catch(() => [])
38 for (const entry of entries) {
39 if (entry.charAt(0) === '.')
40 continue
41 const f = resolve(root, dir, entry)
42 // ignore stat errors, weird file types, symlinks, etc.
43 const st = await lstat(f).catch(() => null)
44 if (!st)
45 continue
46 else if (st.isFile())
47 obj[entry] = relative(root, f)
48 else if (st.isDirectory())
49 await walkBinDir(root, join(dir, entry), obj)
50 }
51 return obj
52}
53
54// do not preserve _fields set in files, they are sus
55const stripUnderscores = data => {
56 for (const key of Object.keys(data).filter(k => /^_/.test(k)))
57 delete data[key]
58 return data
59}
60
61const normalize = data => {
62 add_id(data)
63 fixBundled(data)
64 pruneRepeatedOptionals(data)
65 fixScripts(data)
66 fixFunding(data)
67 normalizePackageBin(data)
68 return data
69}
70
71rpj.normalize = normalize
72
73const add_id = data => {
74 if (data.name && data.version)
75 data._id = `${data.name}@${data.version}`
76 return data
77}
78
79// it was once common practice to list deps both in optionalDependencies
80// and in dependencies, to support npm versions that did not know abbout
81// optionalDependencies. This is no longer a relevant need, so duplicating
82// the deps in two places is unnecessary and excessive.
83const pruneRepeatedOptionals = data => {
84 const od = data.optionalDependencies
85 const dd = data.dependencies || {}
86 if (od && typeof od === 'object') {
87 for (const name of Object.keys(od)) {
88 delete dd[name]
89 }
90 }
91 if (Object.keys(dd).length === 0)
92 delete data.dependencies
93 return data
94}
95
96const fixBundled = data => {
97 const bdd = data.bundledDependencies
98 const bd = data.bundleDependencies === undefined ? bdd
99 : data.bundleDependencies
100
101 if (bd === false)
102 data.bundleDependencies = []
103 else if (bd === true)
104 data.bundleDependencies = Object.keys(data.dependencies || {})
105 else if (bd && typeof bd === 'object') {
106 if (!Array.isArray(bd))
107 data.bundleDependencies = Object.keys(bd)
108 else
109 data.bundleDependencies = bd
110 } else
111 delete data.bundleDependencies
112
113 delete data.bundledDependencies
114 return data
115}
116
117const fixScripts = data => {
118 if (!data.scripts || typeof data.scripts !== 'object') {
119 delete data.scripts
120 return data
121 }
122
123 for (const [name, script] of Object.entries(data.scripts)) {
124 if (typeof script !== 'string')
125 delete data.scripts[name]
126 }
127 return data
128}
129
130const fixFunding = data => {
131 if (data.funding && typeof data.funding === 'string')
132 data.funding = { url: data.funding }
133 return data
134}
135
136module.exports = rpj
Note: See TracBrowser for help on using the repository browser.