rswag-ui 2.15.0 → 3.0.0.pre

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -4
  3. data/lib/generators/rswag/ui/custom/custom_generator.rb +3 -1
  4. data/lib/generators/rswag/ui/install/install_generator.rb +3 -2
  5. data/lib/generators/rswag/ui/install/templates/rswag_ui.rb +3 -2
  6. data/lib/rswag/ui/configuration.rb +6 -12
  7. data/lib/rswag/ui/engine.rb +3 -1
  8. data/lib/rswag/ui/index.erb +0 -1
  9. data/lib/rswag/ui/middleware.rb +9 -7
  10. data/lib/rswag/ui.rb +2 -4
  11. data/lib/tasks/rswag-ui_tasks.rake +3 -2
  12. data/node_modules/@scarf/scarf/LICENSE +201 -0
  13. data/node_modules/@scarf/scarf/README.md +198 -0
  14. data/node_modules/@scarf/scarf/package.json +36 -0
  15. data/node_modules/@scarf/scarf/report.js +574 -0
  16. data/node_modules/swagger-ui-dist/README.md +18 -0
  17. data/node_modules/swagger-ui-dist/package.json +4 -2
  18. data/node_modules/swagger-ui-dist/swagger-ui-bundle.js +1 -2
  19. data/node_modules/swagger-ui-dist/swagger-ui-bundle.js.map +1 -1
  20. data/node_modules/swagger-ui-dist/swagger-ui-es-bundle-core.js +1 -1
  21. data/node_modules/swagger-ui-dist/swagger-ui-es-bundle-core.js.map +1 -1
  22. data/node_modules/swagger-ui-dist/swagger-ui-es-bundle.js +1 -2
  23. data/node_modules/swagger-ui-dist/swagger-ui-es-bundle.js.map +1 -1
  24. data/node_modules/swagger-ui-dist/swagger-ui-standalone-preset.js +1 -2
  25. data/node_modules/swagger-ui-dist/swagger-ui-standalone-preset.js.map +1 -1
  26. data/node_modules/swagger-ui-dist/swagger-ui.css +1 -1
  27. data/node_modules/swagger-ui-dist/swagger-ui.css.map +1 -1
  28. data/node_modules/swagger-ui-dist/swagger-ui.js +1 -1
  29. data/node_modules/swagger-ui-dist/swagger-ui.js.map +1 -1
  30. metadata +17 -12
@@ -0,0 +1,574 @@
1
+ const path = require('path')
2
+ const os = require('os')
3
+ const exec = require('child_process').exec
4
+ const localDevPort = process.env.SCARF_LOCAL_PORT
5
+ const https = localDevPort ? require('http') : require('https')
6
+ const fs = require('fs')
7
+ const fsAsync = fs.promises
8
+ const util = require('util')
9
+
10
+ const scarfHost = localDevPort ? 'localhost' : 'scarf.sh'
11
+ const scarfLibName = '@scarf/scarf'
12
+ const privatePackageRewrite = '@private/private'
13
+ const privateVersionRewrite = '0'
14
+
15
+ const rootPath = process.env.INIT_CWD
16
+
17
+ // Pulled into a function for test mocking
18
+ function tmpFileName () {
19
+ // throttle per user
20
+ const username = os.userInfo().username
21
+ return path.join(os.tmpdir(), `scarf-js-history-${username}.log`)
22
+ }
23
+
24
+ // Pulled into a function for test mocking
25
+ function dirName () {
26
+ return __dirname
27
+ }
28
+
29
+ function npmExecPath () {
30
+ return process.env.npm_execpath
31
+ }
32
+
33
+ const userMessageThrottleTime = 1000 * 60 // 1 minute
34
+
35
+ const execTimeout = 3000
36
+
37
+ // In general, these keys should never change to remain backwards compatible
38
+ // with previous versions of Scarf. If we need to update them, we'll need to
39
+ // make sure we can read the previous values as well
40
+ const optedInLogRateLimitKey = 'optedInLastLog'
41
+ const optedOutLogRateLimitKey = 'optedOutLastLog'
42
+
43
+ const makeDefaultSettings = () => {
44
+ return {
45
+ defaultOptIn: true
46
+ }
47
+ }
48
+
49
+ function logIfVerbose (toLog, stream) {
50
+ if (process.env.SCARF_VERBOSE === 'true') {
51
+ (stream || console.log)(toLog)
52
+ }
53
+ }
54
+
55
+ // SCARF_NO_ANALYTICS was the original variable, we'll get rid of it eventually
56
+ const userHasOptedOut = (rootPackage) => {
57
+ return (rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.enabled === false) ||
58
+ (process.env.SCARF_ANALYTICS === 'false' || process.env.SCARF_NO_ANALYTICS === 'true' || process.env.DO_NOT_TRACK === '1')
59
+ }
60
+
61
+ const userHasOptedIn = (rootPackage) => {
62
+ return (rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.enabled) || process.env.SCARF_ANALYTICS === 'true'
63
+ }
64
+
65
+ // Packages that depend on Scarf can configure whether to should fire when
66
+ // `npm install` is being run directly from within the package, rather than from a
67
+ // dependent package
68
+ function allowTopLevel (rootPackage) {
69
+ return rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.allowTopLevel
70
+ }
71
+
72
+ function skipTraversal (rootPackage) {
73
+ return rootPackage && rootPackage.scarfSettings && rootPackage.scarfSettings.skipTraversal
74
+ }
75
+
76
+ function parentIsRoot (dependencyToReport) {
77
+ const parent = dependencyToReport.parent
78
+ const rootPackage = dependencyToReport.rootPackage
79
+
80
+ return parent && rootPackage && parent.name === rootPackage.name && parent.version === rootPackage.version
81
+ }
82
+
83
+ function isTopLevel (dependencyToReport) {
84
+ return parentIsRoot(dependencyToReport) && !process.env.npm_config_global
85
+ }
86
+
87
+ function isGlobal (dependencyToReport) {
88
+ return parentIsRoot(dependencyToReport) && !!process.env.npm_config_global
89
+ }
90
+
91
+ function hashWithDefault (toHash, defaultReturn) {
92
+ let crypto
93
+ try {
94
+ crypto = require('crypto')
95
+ } catch (err) {
96
+ logIfVerbose('node crypto module unavailable')
97
+ }
98
+
99
+ if (crypto && toHash) {
100
+ return crypto.createHash('sha256').update(toHash, 'utf-8').digest('hex')
101
+ } else {
102
+ return defaultReturn
103
+ }
104
+ }
105
+
106
+ // We don't send any paths, hash package names and versions
107
+ function redactSensitivePackageInfo (dependencyInfo) {
108
+ if (dependencyInfo.grandparent && dependencyInfo.grandparent.name) {
109
+ dependencyInfo.grandparent.nameHash = hashWithDefault(dependencyInfo.grandparent.name, privatePackageRewrite)
110
+ dependencyInfo.grandparent.versionHash = hashWithDefault(dependencyInfo.grandparent.version, privateVersionRewrite)
111
+ }
112
+
113
+ if (dependencyInfo.rootPackage && dependencyInfo.rootPackage.name) {
114
+ dependencyInfo.rootPackage.nameHash = hashWithDefault(dependencyInfo.rootPackage.name, privatePackageRewrite)
115
+ dependencyInfo.rootPackage.versionHash = hashWithDefault(dependencyInfo.rootPackage.version, privateVersionRewrite)
116
+ }
117
+
118
+ delete (dependencyInfo.rootPackage.packageJsonPath)
119
+ delete (dependencyInfo.rootPackage.path)
120
+ delete (dependencyInfo.rootPackage.name)
121
+ delete (dependencyInfo.rootPackage.version)
122
+ delete (dependencyInfo.parent.path)
123
+ delete (dependencyInfo.scarf.path)
124
+ if (dependencyInfo.grandparent) {
125
+ delete (dependencyInfo.grandparent.path)
126
+ delete (dependencyInfo.grandparent.name)
127
+ delete (dependencyInfo.grandparent.version)
128
+ }
129
+ return dependencyInfo
130
+ }
131
+
132
+ /*
133
+ Scarf-js is automatically disabled when being run inside of a yarn install.
134
+ The `npm_execpath` environment variable tells us which package manager is
135
+ running our install
136
+ */
137
+ function isYarn () {
138
+ const execPath = module.exports.npmExecPath() || ''
139
+ return ['yarn', 'yarn.js', 'yarnpkg', 'yarn.cmd', 'yarnpkg.cmd']
140
+ .some(packageManBinName => execPath.endsWith(packageManBinName))
141
+ }
142
+
143
+ function processDependencyTreeOutput (resolve, reject) {
144
+ return function (error, stdout, stderr) {
145
+ if (error && !stdout) {
146
+ return reject(new Error(`Scarf received an error from npm -ls: ${error} | ${stderr}`))
147
+ }
148
+
149
+ try {
150
+ const output = JSON.parse(stdout)
151
+
152
+ const depsToScarf = findScarfInFullDependencyTree(output).filter(depChain => depChain.length >= 2)
153
+ if (!depsToScarf.length) {
154
+ return reject(new Error('No Scarf parent package found'))
155
+ }
156
+ const rootPackageDetails = rootPackageDepInfo(output)
157
+
158
+ const dependencyInfo = depsToScarf.map(depChain => {
159
+ return {
160
+ scarf: depChain[depChain.length - 1],
161
+ parent: depChain[depChain.length - 2],
162
+ grandparent: depChain[depChain.length - 3],
163
+ rootPackage: rootPackageDetails,
164
+ anyInChainDisabled: depChain.some(dep => {
165
+ return (dep.scarfSettings || {}).enabled === false
166
+ })
167
+ }
168
+ })
169
+
170
+ dependencyInfo.forEach(d => {
171
+ d.parent.scarfSettings = Object.assign(makeDefaultSettings(), d.parent.scarfSettings || {})
172
+ })
173
+
174
+ // Here, we find the dependency chain that corresponds to the scarf package we're currently in
175
+ const dependencyToReport = dependencyInfo.find(dep => (dep.scarf.path === module.exports.dirName())) || dependencyInfo[0]
176
+ if (!dependencyToReport) {
177
+ return reject(new Error(`Couldn't find dependency info for path ${module.exports.dirName()}`))
178
+ }
179
+
180
+ // If any intermediate dependency in the chain of deps that leads to scarf
181
+ // has disabled Scarf, we must respect that setting unless the user overrides it.
182
+ if (dependencyToReport.anyInChainDisabled && !userHasOptedIn(dependencyToReport.rootPackage)) {
183
+ return reject(new Error('Scarf has been disabled via a package.json in the dependency chain.'))
184
+ }
185
+
186
+ if (isTopLevel(dependencyToReport) && !isGlobal(dependencyToReport) && !allowTopLevel(rootPackageDetails)) {
187
+ return reject(new Error('The package depending on Scarf is the root package being installed, but Scarf is not configured to run in this case. To enable it, set `scarfSettings.allowTopLevel = true` in your package.json'))
188
+ }
189
+
190
+ return resolve(dependencyToReport)
191
+ } catch (err) {
192
+ logIfVerbose(err, console.error)
193
+ return reject(err)
194
+ }
195
+ }
196
+ }
197
+
198
+ function processGitRevParseOutput (resolve, reject) {
199
+ return function (error, stdout, stderr) {
200
+ if (error && !stdout) {
201
+ return reject(new Error(`Scarf received an error from git rev-parse: ${error} | ${stderr}`))
202
+ }
203
+
204
+ const output = String(stdout).trim()
205
+
206
+ if (output.length > 0) {
207
+ return resolve(output)
208
+ } else {
209
+ return reject(new Error('Scarf did not receive usable output from git rev-parse'))
210
+ }
211
+ }
212
+ }
213
+
214
+ // packageJSONOverride: a test convenience to set a packageJSON explicitly.
215
+ // Leave empty to use the actual root package.json.
216
+ async function getDependencyInfo (packageJSONOverride) {
217
+ try {
218
+ const rootPackageJSON = require(packageJSONOverride || path.join(rootPath, 'package.json'))
219
+ const scarfPackageJSON = require(path.join(dirName(), 'package.json'))
220
+
221
+ if (skipTraversal(rootPackageJSON)) {
222
+ logIfVerbose('skipping dependency tree traversal')
223
+ const rootInfoToReport = {
224
+ name: rootPackageJSON.name,
225
+ version: rootPackageJSON.version,
226
+ scarfSettings: { ...makeDefaultSettings(), ...rootPackageJSON.scarfSettings }
227
+ }
228
+ const shallowDepInfo = {
229
+ scarf: { name: '@scarf/scarf', version: scarfPackageJSON.version },
230
+ parent: { ...rootInfoToReport },
231
+ rootPackage: { ...rootInfoToReport },
232
+ anyInChainDisabled: false,
233
+ skippedTraversal: true
234
+ }
235
+ logIfVerbose(util.inspect(shallowDepInfo))
236
+ return shallowDepInfo
237
+ }
238
+ } catch (err) {
239
+ logIfVerbose(err, console.error)
240
+ }
241
+
242
+ return new Promise((resolve, reject) => {
243
+ exec(`cd ${rootPath} && npm ls @scarf/scarf --json --long`, { timeout: execTimeout, maxBuffer: 1024 * 1024 * 1024 }, processDependencyTreeOutput(resolve, reject))
244
+ })
245
+ }
246
+
247
+ async function getGitShaFromRootPath () {
248
+ const promise = new Promise((resolve, reject) => {
249
+ exec(`cd ${rootPath} && git rev-parse HEAD`, { timeout: execTimeout, maxBuffer: 1024 * 1024 * 1024 }, processGitRevParseOutput(resolve, reject))
250
+ })
251
+ try {
252
+ return await promise
253
+ } catch (e) {
254
+ logIfVerbose(e)
255
+ return undefined
256
+ }
257
+ }
258
+
259
+ async function reportPostInstall () {
260
+ const scarfApiToken = process.env.SCARF_API_TOKEN
261
+
262
+ const dependencyInfo = await module.exports.getDependencyInfo()
263
+ logIfVerbose(dependencyInfo)
264
+ if (!dependencyInfo.parent || !dependencyInfo.parent.name) {
265
+ return Promise.reject(new Error('No parent found, nothing to report'))
266
+ }
267
+
268
+ if (parentIsRoot(dependencyInfo) && allowTopLevel(dependencyInfo.rootPackage)) {
269
+ const gitSha = await getGitShaFromRootPath()
270
+ logIfVerbose(`Injecting sha to parent: ${gitSha}`)
271
+ dependencyInfo.parent.gitSha = gitSha
272
+ }
273
+
274
+ const rootPackage = dependencyInfo.rootPackage
275
+
276
+ if (!userHasOptedIn(rootPackage) && isYarn()) {
277
+ return Promise.reject(new Error('Package manager is yarn. scarf-js is unable to inform user of analytics. Aborting.'))
278
+ }
279
+
280
+ await new Promise((resolve, reject) => {
281
+ if (dependencyInfo.parent.scarfSettings.defaultOptIn) {
282
+ if (userHasOptedOut(rootPackage)) {
283
+ return reject(new Error('User has opted out'))
284
+ }
285
+
286
+ if (!userHasOptedIn(rootPackage)) {
287
+ rateLimitedUserLog(optedInLogRateLimitKey, `
288
+ The dependency '${dependencyInfo.parent.name}' is tracking installation
289
+ statistics using scarf-js (https://scarf.sh), which helps open-source developers
290
+ fund and maintain their projects. Scarf securely logs basic installation
291
+ details when this package is installed. The Scarf npm library is open source
292
+ and permissively licensed at https://github.com/scarf-sh/scarf-js. For more
293
+ details about your project's dependencies, try running 'npm ls'. To opt out of
294
+ analytics, set the environment variable 'SCARF_ANALYTICS=false'.
295
+ `)
296
+ }
297
+ resolve(dependencyInfo)
298
+ } else {
299
+ if (!userHasOptedIn(rootPackage)) {
300
+ if (!userHasOptedOut(rootPackage)) {
301
+ // We'll only print the 'please opt in' text if the user hasn't
302
+ // already opted out, and our logging rate limit hasn't been reached
303
+ if (hasHitRateLimit(optedOutLogRateLimitKey, getRateLimitedLogHistory())) {
304
+ return reject(new Error('Analytics are opt-out by default, but rate limit already hit for prompting opt-in.'))
305
+ }
306
+ rateLimitedUserLog(optedOutLogRateLimitKey, `
307
+ The dependency '${dependencyInfo.parent.name}' would like to track
308
+ installation statistics using scarf-js (https://scarf.sh), which helps
309
+ open-source developers fund and maintain their projects. Reporting is disabled
310
+ by default for this package. When enabled, Scarf securely logs basic
311
+ installation details when this package is installed. The Scarf npm library is
312
+ open source and permissively licensed at https://github.com/scarf-sh/scarf-js.
313
+ For more details about your project's dependencies, try running 'npm ls'.
314
+ `
315
+ )
316
+ const stdin = process.stdin
317
+ stdin.setEncoding('utf-8')
318
+
319
+ process.stdout.write(`Would you like to support ${dependencyInfo.parent.name} by sending analytics for this install? (y/N): `)
320
+
321
+ const timeout1 = setTimeout(() => {
322
+ console.log('')
323
+ console.log('No opt in received, skipping analytics')
324
+ reject(new Error('Timeout waiting for user opt in'))
325
+ }, 7000)
326
+
327
+ stdin.on('data', async function (data) {
328
+ clearTimeout(timeout1)
329
+ const enabled = data.trim().toLowerCase() === 'y'
330
+
331
+ const afterUserInput = (enabled, saved) => {
332
+ if (enabled) {
333
+ console.log('Thanks for enabling analytics!')
334
+ }
335
+
336
+ if (!saved) {
337
+ console.log('To prevent this message in the future, you can also set the `SCARF_ANALYTICS=true|false` environment variable')
338
+ }
339
+
340
+ if (enabled) {
341
+ return resolve(dependencyInfo)
342
+ } else {
343
+ return reject(new Error('Not enabled via cli'))
344
+ }
345
+ }
346
+
347
+ process.stdout.write('Save this preference to your project\'s package.json file? (y/N): ')
348
+
349
+ setTimeout(() => {
350
+ console.log('')
351
+ return afterUserInput(enabled, false)
352
+ }, 15000)
353
+
354
+ stdin.removeAllListeners('data')
355
+ stdin.on('data', async function (data) {
356
+ try {
357
+ const savePreference = data.trim().toLowerCase() === 'y'
358
+ if (savePreference) {
359
+ await savePreferencesToRootPackage(dependencyInfo.rootPackage.packageJsonPath, enabled)
360
+ }
361
+ return afterUserInput(enabled, savePreference)
362
+ } catch (err) {
363
+ logIfVerbose(err, console.error)
364
+ return reject(err)
365
+ }
366
+ })
367
+ })
368
+ }
369
+ } else {
370
+ resolve(dependencyInfo)
371
+ }
372
+ }
373
+ })
374
+
375
+ redactSensitivePackageInfo(dependencyInfo)
376
+
377
+ const infoPayload = {
378
+ libraryType: 'npm',
379
+ rawPlatform: os.platform(),
380
+ rawArch: os.arch(),
381
+ nodeVersion: process.versions.node,
382
+ dependencyInfo: dependencyInfo
383
+ }
384
+
385
+ const data = JSON.stringify(infoPayload)
386
+ logIfVerbose(`Scarf payload: ${data}`)
387
+
388
+ const reqOptions = {
389
+ host: scarfHost,
390
+ port: localDevPort,
391
+ method: 'POST',
392
+ path: '/package-event/install',
393
+ headers: {
394
+ 'Content-Type': 'application/json',
395
+ 'Content-Length': data.length
396
+ },
397
+ timeout: execTimeout
398
+ }
399
+
400
+ if (scarfApiToken) {
401
+ const authToken = Buffer.from(`n/a:${scarfApiToken}`).toString('base64')
402
+ reqOptions.headers.Authorization = `Basic ${authToken}`
403
+ }
404
+
405
+ await new Promise((resolve, reject) => {
406
+ const req = https.request(reqOptions, (res) => {
407
+ logIfVerbose(`Response status: ${res.statusCode}`)
408
+ resolve()
409
+ })
410
+
411
+ req.on('error', error => {
412
+ logIfVerbose(error, console.error)
413
+ reject(error)
414
+ })
415
+
416
+ req.on('timeout', error => {
417
+ logIfVerbose(error, console.error)
418
+ reject(error)
419
+ })
420
+
421
+ req.write(data)
422
+ req.end()
423
+ })
424
+ }
425
+
426
+ // Find all paths to Scarf from the json output of npm ls @scarf/scarf --json in
427
+ // the root package being installed by the user
428
+ //
429
+ // [{
430
+ // scarf: {name: `@scarf/scarf`, version: '0.0.1'},
431
+ // parent: { name: 'scarfed-library', version: '1.0.0', scarfSettings: { defaultOptIn: true } },
432
+ // grandparent: { name: 'scarfed-lib-consumer', version: '1.0.0' }
433
+ // }]
434
+ function findScarfInSubDepTree (pathToDep, deps) {
435
+ const depNames = Object.keys(deps || {})
436
+
437
+ if (!depNames) {
438
+ return []
439
+ }
440
+
441
+ const scarfFound = depNames.find(depName => depName === scarfLibName)
442
+ const output = []
443
+ if (scarfFound) {
444
+ output.push(pathToDep.concat([{ name: scarfLibName, version: deps[scarfLibName].version, path: deps[scarfLibName].path }]))
445
+ }
446
+ for (let i = 0; i < depNames.length; i++) {
447
+ const depName = depNames[i]
448
+ const newPathToDep = pathToDep.concat([
449
+ {
450
+ name: depName,
451
+ version: deps[depName].version,
452
+ scarfSettings: deps[depName].scarfSettings,
453
+ path: deps[depName].path
454
+ }
455
+ ])
456
+ const results = findScarfInSubDepTree(newPathToDep, deps[depName].dependencies)
457
+ if (results) {
458
+ for (let j = 0; j < results.length; j++) {
459
+ output.push(results[j])
460
+ }
461
+ }
462
+ }
463
+
464
+ return output
465
+ }
466
+
467
+ function findScarfInFullDependencyTree (tree) {
468
+ if (tree.name === scarfLibName) {
469
+ return [[{ name: scarfLibName, version: tree.version }]]
470
+ } else {
471
+ return findScarfInSubDepTree([packageDetailsFromDepInfo(tree)], tree.dependencies)
472
+ }
473
+ }
474
+
475
+ function packageDetailsFromDepInfo (tree) {
476
+ return {
477
+ name: tree.name,
478
+ version: tree.version,
479
+ scarfSettings: tree.scarfSettings,
480
+ path: tree.path
481
+ }
482
+ }
483
+
484
+ function rootPackageDepInfo (packageInfo) {
485
+ if (process.env.npm_config_global) {
486
+ packageInfo = Object.values(packageInfo.dependencies)[0]
487
+ }
488
+ const info = packageDetailsFromDepInfo(packageInfo)
489
+ info.packageJsonPath = `${packageInfo.path}/package.json`
490
+ return info
491
+ }
492
+
493
+ async function savePreferencesToRootPackage (path, optIn) {
494
+ const packageJsonString = await fsAsync.readFile(path)
495
+ const parsed = JSON.parse(packageJsonString)
496
+ parsed.scarfSettings = {
497
+ enabled: optIn
498
+ }
499
+ await fsAsync.writeFile(path, JSON.stringify(parsed, null, 2))
500
+ }
501
+
502
+ /*
503
+ If Scarf-js appears in many different spots in a package's dependency tree, we
504
+ want to avoid spamming the user with the same message informing them of
505
+ Scarf's analytics. Rate limited logs will record timestamps of logging in a
506
+ temp file. Before logging something to the user, we will verify we're not over
507
+ the rate limit.
508
+ */
509
+ function rateLimitedUserLog (rateLimitKey, toLog) {
510
+ const history = getRateLimitedLogHistory()
511
+ if (!hasHitRateLimit(rateLimitKey, history)) {
512
+ writeCurrentTimeToLogHistory(rateLimitKey, history)
513
+ console.log(toLog)
514
+ } else {
515
+ logIfVerbose(`[SUPPRESSED USER MESSAGE, RATE LIMIT HIT] ${toLog}`)
516
+ }
517
+ }
518
+
519
+ function getRateLimitedLogHistory () {
520
+ let history
521
+ try {
522
+ history = JSON.parse(fs.readFileSync(module.exports.tmpFileName()))
523
+ } catch (e) {
524
+ logIfVerbose(e)
525
+ }
526
+ return history || {}
527
+ }
528
+
529
+ // Current rate limit: 1/minute
530
+ function hasHitRateLimit (rateLimitKey, history) {
531
+ if (!history || !history[rateLimitKey]) {
532
+ return false
533
+ }
534
+
535
+ const lastLog = history[rateLimitKey]
536
+ return (new Date().getTime() - lastLog) < userMessageThrottleTime
537
+ }
538
+
539
+ function writeCurrentTimeToLogHistory (rateLimitKey, history) {
540
+ history[rateLimitKey] = new Date().getTime()
541
+ fs.writeFileSync(module.exports.tmpFileName(), JSON.stringify(history))
542
+ }
543
+
544
+ module.exports = {
545
+ redactSensitivePackageInfo,
546
+ hasHitRateLimit,
547
+ getRateLimitedLogHistory,
548
+ rateLimitedUserLog,
549
+ tmpFileName,
550
+ dirName,
551
+ processDependencyTreeOutput,
552
+ processGitRevParseOutput,
553
+ npmExecPath,
554
+ getDependencyInfo,
555
+ getGitShaFromRootPath,
556
+ reportPostInstall,
557
+ hashWithDefault,
558
+ findScarfInFullDependencyTree
559
+ }
560
+
561
+ if (require.main === module) {
562
+ try {
563
+ reportPostInstall().catch(e => {
564
+ // This is an optional, best effort attempt. If there are any errors in
565
+ // Scarf, we must not interfere with whatever the user is doing
566
+ logIfVerbose(`\n\n${e}`, console.error)
567
+ }).finally(() => {
568
+ process.exit(0)
569
+ })
570
+ } catch (e) {
571
+ logIfVerbose(`\n\nTop level error: ${e}`, console.error)
572
+ process.exit(0)
573
+ }
574
+ }
@@ -1,6 +1,24 @@
1
1
  # Swagger UI Dist
2
2
  [![NPM version](https://badge.fury.io/js/swagger-ui-dist.svg)](http://badge.fury.io/js/swagger-ui-dist)
3
3
 
4
+ ## Anonymized analytics
5
+
6
+ SwaggerUI Dist uses [Scarf](https://scarf.sh/) to collect [anonymized installation analytics](https://github.com/scarf-sh/scarf-js?tab=readme-ov-file#as-a-user-of-a-package-using-scarf-js-what-information-does-scarf-js-send-about-me). These analytics help support the maintainers of this library and ONLY run during installation. To [opt out](https://github.com/scarf-sh/scarf-js?tab=readme-ov-file#as-a-user-of-a-package-using-scarf-js-how-can-i-opt-out-of-analytics), you can set the `scarfSettings.enabled` field to `false` in your project's `package.json`:
7
+
8
+ ```
9
+ // package.json
10
+ {
11
+ // ...
12
+ "scarfSettings": {
13
+ "enabled": false
14
+ }
15
+ // ...
16
+ }
17
+ ```
18
+
19
+ Alternatively, you can set the environment variable `SCARF_ANALYTICS` to `false` as part of the environment that installs your npm packages, e.g., `SCARF_ANALYTICS=false npm install`.
20
+
21
+
4
22
  # API
5
23
 
6
24
  This module, `swagger-ui-dist`, exposes Swagger-UI's entire dist folder as a dependency-free npm module.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swagger-ui-dist",
3
- "version": "5.9.4",
3
+ "version": "5.20.6",
4
4
  "main": "index.js",
5
5
  "repository": "git@github.com:swagger-api/swagger-ui.git",
6
6
  "contributors": [
@@ -13,6 +13,8 @@
13
13
  "Sahar Jafari <shr.jafari@gmail.com>"
14
14
  ],
15
15
  "license": "Apache-2.0",
16
- "dependencies": {},
16
+ "dependencies": {
17
+ "@scarf/scarf": "=1.4.0"
18
+ },
17
19
  "devDependencies": {}
18
20
  }