projen 0.54.21 → 0.54.24

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 (140) hide show
  1. package/.jsii +256 -157
  2. package/changelog.md +1 -6
  3. package/docs/api/API.md +83 -34
  4. package/docs/node.md +30 -0
  5. package/lib/awscdk/auto-discover.js +4 -4
  6. package/lib/awscdk/awscdk-app-java.js +1 -1
  7. package/lib/awscdk/awscdk-app-py.js +1 -1
  8. package/lib/awscdk/awscdk-app-ts.js +1 -1
  9. package/lib/awscdk/awscdk-construct.js +2 -2
  10. package/lib/awscdk/awscdk-deps-java.js +1 -1
  11. package/lib/awscdk/awscdk-deps-js.js +1 -1
  12. package/lib/awscdk/awscdk-deps.js +1 -1
  13. package/lib/awscdk/cdk-config.js +1 -1
  14. package/lib/awscdk/cdk-tasks.js +1 -1
  15. package/lib/awscdk/integration-test.js +1 -1
  16. package/lib/awscdk/lambda-extension.js +1 -1
  17. package/lib/awscdk/lambda-function.js +2 -2
  18. package/lib/build/build-workflow.js +1 -1
  19. package/lib/cdk/auto-discover-base.js +2 -2
  20. package/lib/cdk/construct-lib.js +1 -1
  21. package/lib/cdk/integration-test-base.js +1 -1
  22. package/lib/cdk/jsii-docgen.js +1 -1
  23. package/lib/cdk/jsii-project.js +1 -1
  24. package/lib/cdk8s/auto-discover.js +2 -2
  25. package/lib/cdk8s/cdk8s-app-ts.js +1 -1
  26. package/lib/cdk8s/cdk8s-construct.js +1 -1
  27. package/lib/cdk8s/integration-test.js +1 -1
  28. package/lib/cdktf/cdktf-construct.js +1 -1
  29. package/lib/component.js +1 -1
  30. package/lib/dependencies.js +1 -1
  31. package/lib/dev-env.js +1 -1
  32. package/lib/docker-compose.js +2 -2
  33. package/lib/file.js +1 -1
  34. package/lib/gitattributes.js +1 -1
  35. package/lib/github/auto-approve.js +1 -1
  36. package/lib/github/auto-merge.js +1 -1
  37. package/lib/github/dependabot.js +1 -1
  38. package/lib/github/github-credentials.js +1 -1
  39. package/lib/github/github-project.js +1 -1
  40. package/lib/github/github.js +1 -1
  41. package/lib/github/mergify.js +1 -1
  42. package/lib/github/pr-template.js +1 -1
  43. package/lib/github/pull-request-lint.js +1 -1
  44. package/lib/github/stale.js +1 -1
  45. package/lib/github/task-workflow.js +1 -1
  46. package/lib/github/util.d.ts +1 -0
  47. package/lib/github/util.js +8 -0
  48. package/lib/github/workflows.js +1 -1
  49. package/lib/gitlab/configuration.js +1 -1
  50. package/lib/gitlab/gitlab-configuration.js +1 -1
  51. package/lib/gitlab/nested-configuration.js +1 -1
  52. package/lib/gitpod.js +1 -1
  53. package/lib/ignore-file.js +1 -1
  54. package/lib/ini.js +1 -1
  55. package/lib/java/java-project.js +1 -1
  56. package/lib/java/junit.js +1 -1
  57. package/lib/java/maven-compile.js +1 -1
  58. package/lib/java/maven-packaging.js +1 -1
  59. package/lib/java/maven-sample.js +1 -1
  60. package/lib/java/pom.js +1 -1
  61. package/lib/java/projenrc.js +1 -1
  62. package/lib/javascript/bundler.js +1 -1
  63. package/lib/javascript/eslint.js +1 -1
  64. package/lib/javascript/jest.js +1 -1
  65. package/lib/javascript/node-package.d.ts +33 -2
  66. package/lib/javascript/node-package.js +57 -6
  67. package/lib/javascript/node-project.d.ts +7 -0
  68. package/lib/javascript/node-project.js +60 -10
  69. package/lib/javascript/npm-config.js +1 -1
  70. package/lib/javascript/prettier.js +1 -1
  71. package/lib/javascript/projenrc.js +1 -1
  72. package/lib/javascript/typescript-config.js +1 -1
  73. package/lib/javascript/upgrade-dependencies.js +2 -2
  74. package/lib/javascript/util.d.ts +16 -0
  75. package/lib/javascript/util.js +21 -2
  76. package/lib/json.js +1 -1
  77. package/lib/license.js +1 -1
  78. package/lib/logger.js +1 -1
  79. package/lib/makefile.js +1 -1
  80. package/lib/object-file.js +1 -1
  81. package/lib/project-build.js +1 -1
  82. package/lib/project.js +1 -1
  83. package/lib/projects.js +1 -1
  84. package/lib/projenrc-json.js +1 -1
  85. package/lib/python/pip.js +1 -1
  86. package/lib/python/poetry.js +2 -2
  87. package/lib/python/projenrc.js +1 -1
  88. package/lib/python/pytest-sample.js +1 -1
  89. package/lib/python/pytest.js +1 -1
  90. package/lib/python/python-project.js +1 -1
  91. package/lib/python/python-sample.js +1 -1
  92. package/lib/python/requirements-file.js +1 -1
  93. package/lib/python/setuppy.js +1 -1
  94. package/lib/python/setuptools.js +1 -1
  95. package/lib/python/venv.js +1 -1
  96. package/lib/readme.js +1 -1
  97. package/lib/release/publisher.js +1 -1
  98. package/lib/release/release-trigger.js +1 -1
  99. package/lib/release/release.js +1 -1
  100. package/lib/run-task.js +1813 -0
  101. package/lib/sample-file.js +2 -2
  102. package/lib/semver.js +1 -1
  103. package/lib/source-code.js +1 -1
  104. package/lib/task-runtime.js +1 -1
  105. package/lib/task.js +1 -1
  106. package/lib/tasks.js +1 -1
  107. package/lib/testing.js +1 -1
  108. package/lib/textfile.js +1 -1
  109. package/lib/toml.js +1 -1
  110. package/lib/typescript/projenrc.js +1 -1
  111. package/lib/typescript/typescript-typedoc.js +1 -1
  112. package/lib/typescript/typescript.js +3 -3
  113. package/lib/version.js +1 -1
  114. package/lib/vscode/devcontainer.js +1 -1
  115. package/lib/vscode/launch-config.js +1 -1
  116. package/lib/vscode/vscode.js +1 -1
  117. package/lib/web/next.js +3 -3
  118. package/lib/web/postcss.js +1 -1
  119. package/lib/web/react.js +4 -4
  120. package/lib/web/tailwind.js +1 -1
  121. package/lib/xmlfile.js +1 -1
  122. package/lib/yaml.js +1 -1
  123. package/node_modules/semver/bin/semver.js +2 -1
  124. package/node_modules/semver/classes/semver.js +1 -1
  125. package/node_modules/semver/functions/inc.js +4 -1
  126. package/node_modules/{lru-cache → semver/node_modules/lru-cache}/LICENSE +1 -1
  127. package/node_modules/semver/node_modules/lru-cache/README.md +166 -0
  128. package/node_modules/semver/node_modules/lru-cache/index.js +334 -0
  129. package/node_modules/{lru-cache → semver/node_modules/lru-cache}/package.json +7 -21
  130. package/node_modules/semver/package.json +6 -5
  131. package/node_modules/yallist/LICENSE +15 -0
  132. package/node_modules/yallist/README.md +204 -0
  133. package/node_modules/yallist/iterator.js +8 -0
  134. package/node_modules/yallist/package.json +29 -0
  135. package/node_modules/yallist/yallist.js +426 -0
  136. package/package.json +3 -3
  137. package/releasetag.txt +1 -1
  138. package/version.txt +1 -1
  139. package/node_modules/lru-cache/README.md +0 -701
  140. package/node_modules/lru-cache/index.js +0 -823
@@ -1,823 +0,0 @@
1
- const perf = typeof performance === 'object' && performance &&
2
- typeof performance.now === 'function' ? performance : Date
3
-
4
- const hasAbortController = typeof AbortController !== 'undefined'
5
-
6
- // minimal backwards-compatibility polyfill
7
- const AC = hasAbortController ? AbortController : Object.assign(
8
- class AbortController {
9
- constructor () { this.signal = new AC.AbortSignal }
10
- abort () { this.signal.aborted = true }
11
- },
12
- { AbortSignal: class AbortSignal { constructor () { this.aborted = false }}}
13
- )
14
-
15
- const warned = new Set()
16
- const deprecatedOption = (opt, instead) => {
17
- const code = `LRU_CACHE_OPTION_${opt}`
18
- if (shouldWarn(code)) {
19
- warn(code, `${opt} option`, `options.${instead}`, LRUCache)
20
- }
21
- }
22
- const deprecatedMethod = (method, instead) => {
23
- const code = `LRU_CACHE_METHOD_${method}`
24
- if (shouldWarn(code)) {
25
- const { prototype } = LRUCache
26
- const { get } = Object.getOwnPropertyDescriptor(prototype, method)
27
- warn(code, `${method} method`, `cache.${instead}()`, get)
28
- }
29
- }
30
- const deprecatedProperty = (field, instead) => {
31
- const code = `LRU_CACHE_PROPERTY_${field}`
32
- if (shouldWarn(code)) {
33
- const { prototype } = LRUCache
34
- const { get } = Object.getOwnPropertyDescriptor(prototype, field)
35
- warn(code, `${field} property`, `cache.${instead}`, get)
36
- }
37
- }
38
-
39
- const emitWarning = (...a) => {
40
- typeof process === 'object' &&
41
- process &&
42
- typeof process.emitWarning === 'function'
43
- ? process.emitWarning(...a)
44
- : console.error(...a)
45
- }
46
-
47
- const shouldWarn = code => !warned.has(code)
48
-
49
- const warn = (code, what, instead, fn) => {
50
- warned.add(code)
51
- const msg = `The ${what} is deprecated. Please use ${instead} instead.`
52
- emitWarning(msg, 'DeprecationWarning', code, fn)
53
- }
54
-
55
- const isPosInt = n => n && n === Math.floor(n) && n > 0 && isFinite(n)
56
-
57
- /* istanbul ignore next - This is a little bit ridiculous, tbh.
58
- * The maximum array length is 2^32-1 or thereabouts on most JS impls.
59
- * And well before that point, you're caching the entire world, I mean,
60
- * that's ~32GB of just integers for the next/prev links, plus whatever
61
- * else to hold that many keys and values. Just filling the memory with
62
- * zeroes at init time is brutal when you get that big.
63
- * But why not be complete?
64
- * Maybe in the future, these limits will have expanded. */
65
- const getUintArray = max => !isPosInt(max) ? null
66
- : max <= Math.pow(2, 8) ? Uint8Array
67
- : max <= Math.pow(2, 16) ? Uint16Array
68
- : max <= Math.pow(2, 32) ? Uint32Array
69
- : max <= Number.MAX_SAFE_INTEGER ? ZeroArray
70
- : null
71
-
72
- class ZeroArray extends Array {
73
- constructor (size) {
74
- super(size)
75
- this.fill(0)
76
- }
77
- }
78
-
79
- class Stack {
80
- constructor (max) {
81
- if (max === 0) {
82
- return []
83
- }
84
- const UintArray = getUintArray(max)
85
- this.heap = new UintArray(max)
86
- this.length = 0
87
- }
88
- push (n) {
89
- this.heap[this.length++] = n
90
- }
91
- pop () {
92
- return this.heap[--this.length]
93
- }
94
- }
95
-
96
- class LRUCache {
97
- constructor (options = {}) {
98
- const {
99
- max = 0,
100
- ttl,
101
- ttlResolution = 1,
102
- ttlAutopurge,
103
- updateAgeOnGet,
104
- updateAgeOnHas,
105
- allowStale,
106
- dispose,
107
- disposeAfter,
108
- noDisposeOnSet,
109
- noUpdateTTL,
110
- maxSize = 0,
111
- sizeCalculation,
112
- fetchMethod,
113
- } = options
114
-
115
- // deprecated options, don't trigger a warning for getting them if
116
- // the thing being passed in is another LRUCache we're copying.
117
- const {
118
- length,
119
- maxAge,
120
- stale,
121
- } = options instanceof LRUCache ? {} : options
122
-
123
- if (max !== 0 && !isPosInt(max)) {
124
- throw new TypeError('max option must be a nonnegative integer')
125
- }
126
-
127
- const UintArray = max ? getUintArray(max) : Array
128
- if (!UintArray) {
129
- throw new Error('invalid max value: ' + max)
130
- }
131
-
132
- this.max = max
133
- this.maxSize = maxSize
134
- this.sizeCalculation = sizeCalculation || length
135
- if (this.sizeCalculation) {
136
- if (!this.maxSize) {
137
- throw new TypeError('cannot set sizeCalculation without setting maxSize')
138
- }
139
- if (typeof this.sizeCalculation !== 'function') {
140
- throw new TypeError('sizeCalculation set to non-function')
141
- }
142
- }
143
-
144
- this.fetchMethod = fetchMethod || null
145
- if (this.fetchMethod && typeof this.fetchMethod !== 'function') {
146
- throw new TypeError('fetchMethod must be a function if specified')
147
- }
148
-
149
- this.keyMap = new Map()
150
- this.keyList = new Array(max).fill(null)
151
- this.valList = new Array(max).fill(null)
152
- this.next = new UintArray(max)
153
- this.prev = new UintArray(max)
154
- this.head = 0
155
- this.tail = 0
156
- this.free = new Stack(max)
157
- this.initialFill = 1
158
- this.size = 0
159
-
160
- if (typeof dispose === 'function') {
161
- this.dispose = dispose
162
- }
163
- if (typeof disposeAfter === 'function') {
164
- this.disposeAfter = disposeAfter
165
- this.disposed = []
166
- } else {
167
- this.disposeAfter = null
168
- this.disposed = null
169
- }
170
- this.noDisposeOnSet = !!noDisposeOnSet
171
- this.noUpdateTTL = !!noUpdateTTL
172
-
173
- if (this.maxSize !== 0) {
174
- if (!isPosInt(this.maxSize)) {
175
- throw new TypeError('maxSize must be a positive integer if specified')
176
- }
177
- this.initializeSizeTracking()
178
- }
179
-
180
- this.allowStale = !!allowStale || !!stale
181
- this.updateAgeOnGet = !!updateAgeOnGet
182
- this.updateAgeOnHas = !!updateAgeOnHas
183
- this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0
184
- ? ttlResolution : 1
185
- this.ttlAutopurge = !!ttlAutopurge
186
- this.ttl = ttl || maxAge || 0
187
- if (this.ttl) {
188
- if (!isPosInt(this.ttl)) {
189
- throw new TypeError('ttl must be a positive integer if specified')
190
- }
191
- this.initializeTTLTracking()
192
- }
193
-
194
- // do not allow completely unbounded caches
195
- if (this.max === 0 && this.ttl === 0 && this.maxSize === 0) {
196
- throw new TypeError('At least one of max, maxSize, or ttl is required')
197
- }
198
- if (!this.ttlAutopurge && !this.max && !this.maxSize) {
199
- const code = 'LRU_CACHE_UNBOUNDED'
200
- if (shouldWarn(code)) {
201
- warned.add(code)
202
- const msg = 'TTL caching without ttlAutopurge, max, or maxSize can ' +
203
- 'result in unbounded memory consumption.'
204
- emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache)
205
- }
206
- }
207
-
208
- if (stale) {
209
- deprecatedOption('stale', 'allowStale')
210
- }
211
- if (maxAge) {
212
- deprecatedOption('maxAge', 'ttl')
213
- }
214
- if (length) {
215
- deprecatedOption('length', 'sizeCalculation')
216
- }
217
- }
218
-
219
- getRemainingTTL (key) {
220
- return this.has(key, { updateAgeOnHas: false }) ? Infinity : 0
221
- }
222
-
223
- initializeTTLTracking () {
224
- this.ttls = new ZeroArray(this.max)
225
- this.starts = new ZeroArray(this.max)
226
-
227
- this.setItemTTL = (index, ttl) => {
228
- this.starts[index] = ttl !== 0 ? perf.now() : 0
229
- this.ttls[index] = ttl
230
- if (ttl !== 0 && this.ttlAutopurge) {
231
- const t = setTimeout(() => {
232
- if (this.isStale(index)) {
233
- this.delete(this.keyList[index])
234
- }
235
- }, ttl + 1)
236
- /* istanbul ignore else - unref() not supported on all platforms */
237
- if (t.unref) {
238
- t.unref()
239
- }
240
- }
241
- }
242
-
243
- this.updateItemAge = (index) => {
244
- this.starts[index] = this.ttls[index] !== 0 ? perf.now() : 0
245
- }
246
-
247
- // debounce calls to perf.now() to 1s so we're not hitting
248
- // that costly call repeatedly.
249
- let cachedNow = 0
250
- const getNow = () => {
251
- const n = perf.now()
252
- if (this.ttlResolution > 0) {
253
- cachedNow = n
254
- const t = setTimeout(() => cachedNow = 0, this.ttlResolution)
255
- /* istanbul ignore else - not available on all platforms */
256
- if (t.unref) {
257
- t.unref()
258
- }
259
- }
260
- return n
261
- }
262
-
263
- this.getRemainingTTL = (key) => {
264
- const index = this.keyMap.get(key)
265
- if (index === undefined) {
266
- return 0
267
- }
268
- return this.ttls[index] === 0 || this.starts[index] === 0 ? Infinity
269
- : ((this.starts[index] + this.ttls[index]) - (cachedNow || getNow()))
270
- }
271
-
272
- this.isStale = (index) => {
273
- return this.ttls[index] !== 0 && this.starts[index] !== 0 &&
274
- ((cachedNow || getNow()) - this.starts[index] > this.ttls[index])
275
- }
276
- }
277
- updateItemAge (index) {}
278
- setItemTTL (index, ttl) {}
279
- isStale (index) { return false }
280
-
281
- initializeSizeTracking () {
282
- this.calculatedSize = 0
283
- this.sizes = new ZeroArray(this.max)
284
- this.removeItemSize = index => this.calculatedSize -= this.sizes[index]
285
- this.requireSize = (k, v, size, sizeCalculation) => {
286
- if (!isPosInt(size)) {
287
- if (sizeCalculation) {
288
- if (typeof sizeCalculation !== 'function') {
289
- throw new TypeError('sizeCalculation must be a function')
290
- }
291
- size = sizeCalculation(v, k)
292
- if (!isPosInt(size)) {
293
- throw new TypeError('sizeCalculation return invalid (expect positive integer)')
294
- }
295
- } else {
296
- throw new TypeError('invalid size value (must be positive integer)')
297
- }
298
- }
299
- return size
300
- }
301
- this.addItemSize = (index, v, k, size) => {
302
- this.sizes[index] = size
303
- const maxSize = this.maxSize - this.sizes[index]
304
- while (this.calculatedSize > maxSize) {
305
- this.evict(true)
306
- }
307
- this.calculatedSize += this.sizes[index]
308
- }
309
- this.delete = k => {
310
- if (this.size !== 0) {
311
- const index = this.keyMap.get(k)
312
- if (index !== undefined) {
313
- this.calculatedSize -= this.sizes[index]
314
- }
315
- }
316
- return LRUCache.prototype.delete.call(this, k)
317
- }
318
- }
319
- removeItemSize (index) {}
320
- addItemSize (index, v, k, size) {}
321
- requireSize (k, v, size, sizeCalculation) {
322
- if (size || sizeCalculation) {
323
- throw new TypeError('cannot set size without setting maxSize on cache')
324
- }
325
- }
326
-
327
- *indexes ({ allowStale = this.allowStale } = {}) {
328
- if (this.size) {
329
- for (let i = this.tail; true; ) {
330
- if (!this.isValidIndex(i)) {
331
- break
332
- }
333
- if (allowStale || !this.isStale(i)) {
334
- yield i
335
- }
336
- if (i === this.head) {
337
- break
338
- } else {
339
- i = this.prev[i]
340
- }
341
- }
342
- }
343
- }
344
-
345
- *rindexes ({ allowStale = this.allowStale } = {}) {
346
- if (this.size) {
347
- for (let i = this.head; true; ) {
348
- if (!this.isValidIndex(i)) {
349
- break
350
- }
351
- if (allowStale || !this.isStale(i)) {
352
- yield i
353
- }
354
- if (i === this.tail) {
355
- break
356
- } else {
357
- i = this.next[i]
358
- }
359
- }
360
- }
361
- }
362
-
363
- isValidIndex (index) {
364
- return this.keyMap.get(this.keyList[index]) === index
365
- }
366
-
367
- *entries () {
368
- for (const i of this.indexes()) {
369
- yield [this.keyList[i], this.valList[i]]
370
- }
371
- }
372
- *rentries () {
373
- for (const i of this.rindexes()) {
374
- yield [this.keyList[i], this.valList[i]]
375
- }
376
- }
377
-
378
- *keys () {
379
- for (const i of this.indexes()) {
380
- yield this.keyList[i]
381
- }
382
- }
383
- *rkeys () {
384
- for (const i of this.rindexes()) {
385
- yield this.keyList[i]
386
- }
387
- }
388
-
389
- *values () {
390
- for (const i of this.indexes()) {
391
- yield this.valList[i]
392
- }
393
- }
394
- *rvalues () {
395
- for (const i of this.rindexes()) {
396
- yield this.valList[i]
397
- }
398
- }
399
-
400
- [Symbol.iterator] () {
401
- return this.entries()
402
- }
403
-
404
- find (fn, getOptions = {}) {
405
- for (const i of this.indexes()) {
406
- if (fn(this.valList[i], this.keyList[i], this)) {
407
- return this.get(this.keyList[i], getOptions)
408
- }
409
- }
410
- }
411
-
412
- forEach (fn, thisp = this) {
413
- for (const i of this.indexes()) {
414
- fn.call(thisp, this.valList[i], this.keyList[i], this)
415
- }
416
- }
417
-
418
- rforEach (fn, thisp = this) {
419
- for (const i of this.rindexes()) {
420
- fn.call(thisp, this.valList[i], this.keyList[i], this)
421
- }
422
- }
423
-
424
- get prune () {
425
- deprecatedMethod('prune', 'purgeStale')
426
- return this.purgeStale
427
- }
428
-
429
- purgeStale () {
430
- let deleted = false
431
- for (const i of this.rindexes({ allowStale: true })) {
432
- if (this.isStale(i)) {
433
- this.delete(this.keyList[i])
434
- deleted = true
435
- }
436
- }
437
- return deleted
438
- }
439
-
440
- dump () {
441
- const arr = []
442
- for (const i of this.indexes()) {
443
- const key = this.keyList[i]
444
- const value = this.valList[i]
445
- const entry = { value }
446
- if (this.ttls) {
447
- entry.ttl = this.ttls[i]
448
- }
449
- if (this.sizes) {
450
- entry.size = this.sizes[i]
451
- }
452
- arr.unshift([key, entry])
453
- }
454
- return arr
455
- }
456
-
457
- load (arr) {
458
- this.clear()
459
- for (const [key, entry] of arr) {
460
- this.set(key, entry.value, entry)
461
- }
462
- }
463
-
464
- dispose (v, k, reason) {}
465
-
466
- set (k, v, {
467
- ttl = this.ttl,
468
- noDisposeOnSet = this.noDisposeOnSet,
469
- size = 0,
470
- sizeCalculation = this.sizeCalculation,
471
- noUpdateTTL = this.noUpdateTTL,
472
- } = {}) {
473
- size = this.requireSize(k, v, size, sizeCalculation)
474
- let index = this.size === 0 ? undefined : this.keyMap.get(k)
475
- if (index === undefined) {
476
- // addition
477
- index = this.newIndex()
478
- this.keyList[index] = k
479
- this.valList[index] = v
480
- this.keyMap.set(k, index)
481
- this.next[this.tail] = index
482
- this.prev[index] = this.tail
483
- this.tail = index
484
- this.size ++
485
- this.addItemSize(index, v, k, size)
486
- noUpdateTTL = false
487
- } else {
488
- // update
489
- const oldVal = this.valList[index]
490
- if (v !== oldVal) {
491
- if (this.isBackgroundFetch(oldVal)) {
492
- oldVal.__abortController.abort()
493
- } else {
494
- if (!noDisposeOnSet) {
495
- this.dispose(oldVal, k, 'set')
496
- if (this.disposeAfter) {
497
- this.disposed.push([oldVal, k, 'set'])
498
- }
499
- }
500
- }
501
- this.removeItemSize(index)
502
- this.valList[index] = v
503
- this.addItemSize(index, v, k, size)
504
- }
505
- this.moveToTail(index)
506
- }
507
- if (ttl !== 0 && this.ttl === 0 && !this.ttls) {
508
- this.initializeTTLTracking()
509
- }
510
- if (!noUpdateTTL) {
511
- this.setItemTTL(index, ttl)
512
- }
513
- if (this.disposeAfter) {
514
- while (this.disposed.length) {
515
- this.disposeAfter(...this.disposed.shift())
516
- }
517
- }
518
- return this
519
- }
520
-
521
- newIndex () {
522
- if (this.size === 0) {
523
- return this.tail
524
- }
525
- if (this.size === this.max && this.max !== 0) {
526
- return this.evict(false)
527
- }
528
- if (this.free.length !== 0) {
529
- return this.free.pop()
530
- }
531
- // initial fill, just keep writing down the list
532
- return this.initialFill++
533
- }
534
-
535
- pop () {
536
- if (this.size) {
537
- const val = this.valList[this.head]
538
- this.evict(true)
539
- return val
540
- }
541
- }
542
-
543
- evict (free) {
544
- const head = this.head
545
- const k = this.keyList[head]
546
- const v = this.valList[head]
547
- if (this.isBackgroundFetch(v)) {
548
- v.__abortController.abort()
549
- } else {
550
- this.dispose(v, k, 'evict')
551
- if (this.disposeAfter) {
552
- this.disposed.push([v, k, 'evict'])
553
- }
554
- }
555
- this.removeItemSize(head)
556
- // if we aren't about to use the index, then null these out
557
- if (free) {
558
- this.keyList[head] = null
559
- this.valList[head] = null
560
- this.free.push(head)
561
- }
562
- this.head = this.next[head]
563
- this.keyMap.delete(k)
564
- this.size --
565
- return head
566
- }
567
-
568
- has (k, { updateAgeOnHas = this.updateAgeOnHas } = {}) {
569
- const index = this.keyMap.get(k)
570
- if (index !== undefined) {
571
- if (!this.isStale(index)) {
572
- if (updateAgeOnHas) {
573
- this.updateItemAge(index)
574
- }
575
- return true
576
- }
577
- }
578
- return false
579
- }
580
-
581
- // like get(), but without any LRU updating or TTL expiration
582
- peek (k, { allowStale = this.allowStale } = {}) {
583
- const index = this.keyMap.get(k)
584
- if (index !== undefined && (allowStale || !this.isStale(index))) {
585
- return this.valList[index]
586
- }
587
- }
588
-
589
- backgroundFetch (k, index, options) {
590
- const v = index === undefined ? undefined : this.valList[index]
591
- if (this.isBackgroundFetch(v)) {
592
- return v
593
- }
594
- const ac = new AC()
595
- const fetchOpts = {
596
- signal: ac.signal,
597
- options,
598
- }
599
- const p = Promise.resolve(this.fetchMethod(k, v, fetchOpts)).then(v => {
600
- if (!ac.signal.aborted) {
601
- this.set(k, v, fetchOpts.options)
602
- }
603
- return v
604
- })
605
- p.__abortController = ac
606
- p.__staleWhileFetching = v
607
- if (index === undefined) {
608
- this.set(k, p, fetchOpts.options)
609
- index = this.keyMap.get(k)
610
- } else {
611
- this.valList[index] = p
612
- }
613
- return p
614
- }
615
-
616
- isBackgroundFetch (p) {
617
- return p && typeof p === 'object' && typeof p.then === 'function' &&
618
- Object.prototype.hasOwnProperty.call(p, '__staleWhileFetching')
619
- }
620
-
621
- // this takes the union of get() and set() opts, because it does both
622
- async fetch (k, {
623
- allowStale = this.allowStale,
624
- updateAgeOnGet = this.updateAgeOnGet,
625
- ttl = this.ttl,
626
- noDisposeOnSet = this.noDisposeOnSet,
627
- size = 0,
628
- sizeCalculation = this.sizeCalculation,
629
- noUpdateTTL = this.noUpdateTTL,
630
- } = {}) {
631
- if (!this.fetchMethod) {
632
- return this.get(k, {allowStale, updateAgeOnGet})
633
- }
634
-
635
- const options = {
636
- allowStale,
637
- updateAgeOnGet,
638
- ttl,
639
- noDisposeOnSet,
640
- size,
641
- sizeCalculation,
642
- noUpdateTTL,
643
- }
644
-
645
- let index = this.keyMap.get(k)
646
- if (index === undefined) {
647
- return this.backgroundFetch(k, index, options)
648
- } else {
649
- // in cache, maybe already fetching
650
- const v = this.valList[index]
651
- if (this.isBackgroundFetch(v)) {
652
- return allowStale && v.__staleWhileFetching !== undefined
653
- ? v.__staleWhileFetching : v
654
- }
655
-
656
- if (!this.isStale(index)) {
657
- this.moveToTail(index)
658
- if (updateAgeOnGet) {
659
- this.updateItemAge(index)
660
- }
661
- return v
662
- }
663
-
664
- // ok, it is stale, and not already fetching
665
- // refresh the cache.
666
- const p = this.backgroundFetch(k, index, options)
667
- return allowStale && p.__staleWhileFetching !== undefined
668
- ? p.__staleWhileFetching : p
669
- }
670
- }
671
-
672
- get (k, {
673
- allowStale = this.allowStale,
674
- updateAgeOnGet = this.updateAgeOnGet,
675
- } = {}) {
676
- const index = this.keyMap.get(k)
677
- if (index !== undefined) {
678
- const value = this.valList[index]
679
- const fetching = this.isBackgroundFetch(value)
680
- if (this.isStale(index)) {
681
- // delete only if not an in-flight background fetch
682
- if (!fetching) {
683
- this.delete(k)
684
- return allowStale ? value : undefined
685
- } else {
686
- return allowStale ? value.__staleWhileFetching : undefined
687
- }
688
- } else {
689
- // if we're currently fetching it, we don't actually have it yet
690
- // it's not stale, which means this isn't a staleWhileRefetching,
691
- // so we just return undefined
692
- if (fetching) {
693
- return undefined
694
- }
695
- this.moveToTail(index)
696
- if (updateAgeOnGet) {
697
- this.updateItemAge(index)
698
- }
699
- return value
700
- }
701
- }
702
- }
703
-
704
- connect (p, n) {
705
- this.prev[n] = p
706
- this.next[p] = n
707
- }
708
-
709
- moveToTail (index) {
710
- // if tail already, nothing to do
711
- // if head, move head to next[index]
712
- // else
713
- // move next[prev[index]] to next[index] (head has no prev)
714
- // move prev[next[index]] to prev[index]
715
- // prev[index] = tail
716
- // next[tail] = index
717
- // tail = index
718
- if (index !== this.tail) {
719
- if (index === this.head) {
720
- this.head = this.next[index]
721
- } else {
722
- this.connect(this.prev[index], this.next[index])
723
- }
724
- this.connect(this.tail, index)
725
- this.tail = index
726
- }
727
- }
728
-
729
- get del () {
730
- deprecatedMethod('del', 'delete')
731
- return this.delete
732
- }
733
- delete (k) {
734
- let deleted = false
735
- if (this.size !== 0) {
736
- const index = this.keyMap.get(k)
737
- if (index !== undefined) {
738
- deleted = true
739
- if (this.size === 1) {
740
- this.clear()
741
- } else {
742
- this.removeItemSize(index)
743
- const v = this.valList[index]
744
- if (this.isBackgroundFetch(v)) {
745
- v.__abortController.abort()
746
- } else {
747
- this.dispose(v, k, 'delete')
748
- if (this.disposeAfter) {
749
- this.disposed.push([v, k, 'delete'])
750
- }
751
- }
752
- this.keyMap.delete(k)
753
- this.keyList[index] = null
754
- this.valList[index] = null
755
- if (index === this.tail) {
756
- this.tail = this.prev[index]
757
- } else if (index === this.head) {
758
- this.head = this.next[index]
759
- } else {
760
- this.next[this.prev[index]] = this.next[index]
761
- this.prev[this.next[index]] = this.prev[index]
762
- }
763
- this.size --
764
- this.free.push(index)
765
- }
766
- }
767
- }
768
- if (this.disposed) {
769
- while (this.disposed.length) {
770
- this.disposeAfter(...this.disposed.shift())
771
- }
772
- }
773
- return deleted
774
- }
775
-
776
- clear () {
777
- for (const index of this.rindexes({ allowStale: true })) {
778
- const v = this.valList[index]
779
- if (this.isBackgroundFetch(v)) {
780
- v.__abortController.abort()
781
- } else {
782
- const k = this.keyList[index]
783
- this.dispose(v, k, 'delete')
784
- if (this.disposeAfter) {
785
- this.disposed.push([v, k, 'delete'])
786
- }
787
- }
788
- }
789
-
790
- this.keyMap.clear()
791
- this.valList.fill(null)
792
- this.keyList.fill(null)
793
- if (this.ttls) {
794
- this.ttls.fill(0)
795
- this.starts.fill(0)
796
- }
797
- if (this.sizes) {
798
- this.sizes.fill(0)
799
- }
800
- this.head = 0
801
- this.tail = 0
802
- this.initialFill = 1
803
- this.free.length = 0
804
- this.calculatedSize = 0
805
- this.size = 0
806
- if (this.disposed) {
807
- while (this.disposed.length) {
808
- this.disposeAfter(...this.disposed.shift())
809
- }
810
- }
811
- }
812
- get reset () {
813
- deprecatedMethod('reset', 'clear')
814
- return this.clear
815
- }
816
-
817
- get length () {
818
- deprecatedProperty('length', 'size')
819
- return this.size
820
- }
821
- }
822
-
823
- module.exports = LRUCache