echogarden 0.11.11 → 0.11.13

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 (130) hide show
  1. package/data/schemas/options.json +16 -0
  2. package/dist/alignment/DTWMfccSequenceAlignment.js +2 -2
  3. package/dist/alignment/DTWMfccSequenceAlignment.js.map +1 -1
  4. package/dist/alignment/SpeechAlignment.d.ts +1 -1
  5. package/dist/alignment/SpeechAlignment.js +15 -3
  6. package/dist/alignment/SpeechAlignment.js.map +1 -1
  7. package/dist/api/Alignment.js +3 -3
  8. package/dist/api/Alignment.js.map +1 -1
  9. package/dist/api/LanguageDetection.js +1 -1
  10. package/dist/api/LanguageDetection.js.map +1 -1
  11. package/dist/api/Recognition.js +3 -3
  12. package/dist/api/Recognition.js.map +1 -1
  13. package/dist/api/Synthesis.js +7 -6
  14. package/dist/api/Synthesis.js.map +1 -1
  15. package/dist/api/Translation.js +3 -3
  16. package/dist/api/Translation.js.map +1 -1
  17. package/dist/audio/AudioUtilities.d.ts +5 -2
  18. package/dist/audio/AudioUtilities.js +50 -22
  19. package/dist/audio/AudioUtilities.js.map +1 -1
  20. package/dist/cli/CLI.js +2 -2
  21. package/dist/cli/CLI.js.map +1 -1
  22. package/dist/dsp/SpeexResampler.js +1 -1
  23. package/dist/recognition/WhisperSTT.js +2 -2
  24. package/dist/recognition/WhisperSTT.js.map +1 -1
  25. package/dist/subtitles/Subtitles.d.ts +10 -7
  26. package/dist/subtitles/Subtitles.js +268 -207
  27. package/dist/subtitles/Subtitles.js.map +1 -1
  28. package/docs/Options.md +4 -2
  29. package/package.json +12 -11
  30. package/src/alignment/DTWMfccSequenceAlignment.ts +43 -0
  31. package/src/alignment/DTWSequenceAlignment.ts +121 -0
  32. package/src/alignment/DTWSequenceAlignmentWindowed.ts +210 -0
  33. package/src/alignment/LevenshteinSequenceAlignment.ts +126 -0
  34. package/src/alignment/SpeechAlignment.ts +488 -0
  35. package/src/api/API.ts +12 -0
  36. package/src/api/APIOptions.ts +15 -0
  37. package/src/api/Alignment.ts +329 -0
  38. package/src/api/Common.ts +16 -0
  39. package/src/api/Denoising.ts +120 -0
  40. package/src/api/LanguageDetection.ts +286 -0
  41. package/src/api/Recognition.ts +344 -0
  42. package/src/api/Synthesis.ts +1735 -0
  43. package/src/api/Translation.ts +143 -0
  44. package/src/api/Vad.ts +172 -0
  45. package/src/audio/AudioBufferConversion.ts +248 -0
  46. package/src/audio/AudioPlayer.ts +358 -0
  47. package/src/audio/AudioRecorder.ts +91 -0
  48. package/src/audio/AudioUtilities.ts +392 -0
  49. package/src/audio/SoxPath.ts +24 -0
  50. package/src/cli/CLI.ts +1360 -0
  51. package/src/cli/CLIConfigFile.ts +91 -0
  52. package/src/cli/CLILauncher.ts +26 -0
  53. package/src/cli/CLIOptionsSchema.ts +54 -0
  54. package/src/cli/CLIParser.ts +41 -0
  55. package/src/cli/CLIStarter.ts +40 -0
  56. package/src/codecs/FFMpegTranscoder.ts +214 -0
  57. package/src/codecs/TIMITCodec.ts +17 -0
  58. package/src/codecs/WaveCodec.ts +260 -0
  59. package/src/denoising/RNNoise.ts +95 -0
  60. package/src/dsp/BiquadFilter.ts +488 -0
  61. package/src/dsp/FFT.ts +187 -0
  62. package/src/dsp/MFCC.ts +227 -0
  63. package/src/dsp/MelSpectogram.ts +145 -0
  64. package/src/dsp/Rubberband.ts +249 -0
  65. package/src/dsp/Sonic.ts +59 -0
  66. package/src/dsp/SpeexResampler.ts +79 -0
  67. package/src/math/VectorMath.ts +812 -0
  68. package/src/nlp/ChineseSegmentation.ts +68 -0
  69. package/src/nlp/CompromiseNLP.ts +113 -0
  70. package/src/nlp/EspeakPhonemizer.ts +168 -0
  71. package/src/nlp/IPA.ts +139 -0
  72. package/src/nlp/JapaneseSegmentation.ts +53 -0
  73. package/src/nlp/Lexicon.ts +119 -0
  74. package/src/nlp/PhoneConversion.ts +508 -0
  75. package/src/nlp/Segmentation.ts +237 -0
  76. package/src/nlp/TextNormalizer.ts +160 -0
  77. package/src/recognition/AmazonTranscribeSTT.ts +112 -0
  78. package/src/recognition/AzureCognitiveServicesSTT.ts +76 -0
  79. package/src/recognition/GoogleCloudSTT.ts +92 -0
  80. package/src/recognition/SileroSTT.ts +173 -0
  81. package/src/recognition/VoskSTT.ts +112 -0
  82. package/src/recognition/WhisperSTT.ts +1518 -0
  83. package/src/server/Client.ts +297 -0
  84. package/src/server/Server.ts +178 -0
  85. package/src/server/ServerStarter.ts +12 -0
  86. package/src/server/Worker.ts +400 -0
  87. package/src/server/WorkerStarter.ts +38 -0
  88. package/src/speech-language-detection/SileroLanguageDetection.ts +105 -0
  89. package/src/subtitles/Subtitles.ts +478 -0
  90. package/src/synthesis/AwsPollyTTS.ts +78 -0
  91. package/src/synthesis/AzureCognitiveServicesTTS.ts +146 -0
  92. package/src/synthesis/CoquiServerTTS.ts +29 -0
  93. package/src/synthesis/ElevenLabsTTS.ts +104 -0
  94. package/src/synthesis/EspeakTTS.ts +552 -0
  95. package/src/synthesis/FliteTTS.ts +387 -0
  96. package/src/synthesis/GoogleCloudTTS.ts +112 -0
  97. package/src/synthesis/GoogleTranslateTTS.ts +210 -0
  98. package/src/synthesis/MicrosoftEdgeTTS.ts +298 -0
  99. package/src/synthesis/SamTTS.ts +30 -0
  100. package/src/synthesis/SapiTTS.ts +222 -0
  101. package/src/synthesis/StreamlabsPollyTTS.ts +114 -0
  102. package/src/synthesis/SvoxPicoTTS.ts +318 -0
  103. package/src/synthesis/VitsTTS.ts +734 -0
  104. package/src/tests/Test.ts +24 -0
  105. package/src/text-language-detection/FastTextLanguageDetection.ts +53 -0
  106. package/src/text-language-detection/TinyLDLanguageDetection.ts +16 -0
  107. package/src/typings/Fillers.d.ts +41 -0
  108. package/src/utilities/BinaryArrayConversion.ts +159 -0
  109. package/src/utilities/Compression.ts +91 -0
  110. package/src/utilities/FileDownloader.ts +201 -0
  111. package/src/utilities/FileSystem.ts +265 -0
  112. package/src/utilities/Hashing.ts +230 -0
  113. package/src/utilities/Locale.ts +119 -0
  114. package/src/utilities/Logger.ts +72 -0
  115. package/src/utilities/NdArrayUtilities.ts +31 -0
  116. package/src/utilities/ObjectUtilities.ts +169 -0
  117. package/src/utilities/OpenPromise.ts +13 -0
  118. package/src/utilities/PackageManager.ts +97 -0
  119. package/src/utilities/Queue.ts +17 -0
  120. package/src/utilities/RandomGenerator.ts +237 -0
  121. package/src/utilities/SignalChannel.ts +22 -0
  122. package/src/utilities/TarballMaker.ts +68 -0
  123. package/src/utilities/Timeline.ts +231 -0
  124. package/src/utilities/Timer.ts +93 -0
  125. package/src/utilities/Utilities.ts +574 -0
  126. package/src/utilities/WasmMemoryManager.ts +516 -0
  127. package/src/utilities/WebReader.ts +55 -0
  128. package/src/utilities/WikipediaReader.ts +41 -0
  129. package/src/voice-activity-detection/SileroVAD.ts +86 -0
  130. package/src/voice-activity-detection/WebRtcVAD.ts +76 -0
@@ -0,0 +1,169 @@
1
+ export function extendDeep(base: any, extension: any): any {
2
+ const baseClone = deepClone(base)
3
+
4
+ if (isPlainObject(base) && extension === undefined) {
5
+ return baseClone
6
+ }
7
+
8
+ const extensionClone = deepClone(extension)
9
+ if (!isPlainObject(base) || !isPlainObject(extension)) {
10
+ return extensionClone
11
+ }
12
+
13
+ for (const propName in extensionClone) {
14
+ if (!extensionClone.hasOwnProperty(propName)) {
15
+ continue
16
+ }
17
+
18
+ baseClone[propName] = extendDeep(baseClone[propName], extensionClone[propName])
19
+ }
20
+
21
+ return baseClone
22
+ }
23
+
24
+ export function shallowClone<T>(val: T) {
25
+ return clone(val, false)
26
+ }
27
+
28
+ export function deepClone<T>(val: T) {
29
+ return clone(val, true)
30
+ }
31
+
32
+ function clone<T>(val: T, deep = true, seenObjects: any[] = []): T {
33
+ if (val == null || typeof val !== "object") {
34
+ return val
35
+ }
36
+
37
+ const obj = <any>val
38
+ const prototypeIdentifier = toString.call(obj)
39
+
40
+ switch (prototypeIdentifier) {
41
+ case "[object Array]": {
42
+ if (seenObjects.includes(obj)) {
43
+ throw new Error("deepClone: encountered a cyclic object")
44
+ }
45
+
46
+ seenObjects.push(obj)
47
+
48
+ const clonedArray = new Array(obj.length)
49
+
50
+ for (let i = 0; i < obj.length; i++) {
51
+ if (deep) {
52
+ clonedArray[i] = clone(obj[i], true, seenObjects)
53
+ } else {
54
+ clonedArray[i] = obj[i]
55
+ }
56
+ }
57
+
58
+ seenObjects.pop()
59
+
60
+ return <any>clonedArray
61
+ }
62
+
63
+ case "[object ArrayBuffer]": {
64
+ const clonedArray = new Uint8Array(obj.byteLength)
65
+ clonedArray.set(new Uint8Array(obj))
66
+ return <any>clonedArray.buffer
67
+ }
68
+
69
+ case "[object Int8Array]": {
70
+ const clonedArray = new Int8Array(obj.length)
71
+ clonedArray.set(obj)
72
+ return <any>clonedArray
73
+ }
74
+
75
+ case "[object Uint8Array]": {
76
+ const clonedArray = new Uint8Array(obj.length)
77
+ clonedArray.set(obj)
78
+ return <any>clonedArray
79
+ }
80
+
81
+ case "[object Uint8ClampedArray]": {
82
+ const clonedArray = new Uint8ClampedArray(obj.length)
83
+ clonedArray.set(obj)
84
+ return <any>clonedArray
85
+ }
86
+
87
+ case "[object Int16Array]": {
88
+ const clonedArray = new Int16Array(obj.length)
89
+ clonedArray.set(obj)
90
+ return <any>clonedArray
91
+ }
92
+
93
+ case "[object Uint16Array]": {
94
+ const clonedArray = new Uint16Array(obj.length)
95
+ clonedArray.set(obj)
96
+ return <any>clonedArray
97
+ }
98
+
99
+ case "[object Int32Array]": {
100
+ const clonedArray = new Int32Array(obj.length)
101
+ clonedArray.set(obj)
102
+ return <any>clonedArray
103
+ }
104
+
105
+ case "[object Uint32Array]": {
106
+ const clonedArray = new Uint32Array(obj.length)
107
+ clonedArray.set(obj)
108
+ return <any>clonedArray
109
+ }
110
+
111
+ case "[object Float32Array]": {
112
+ const clonedArray = new Float32Array(obj.length)
113
+ clonedArray.set(obj)
114
+ return <any>clonedArray
115
+ }
116
+
117
+ case "[object Float64Array]": {
118
+ const clonedArray = new Float64Array(obj.length)
119
+ clonedArray.set(obj)
120
+ return <any>clonedArray
121
+ }
122
+
123
+ case "[object Date]": {
124
+ return <any>new Date(obj.valueOf())
125
+ }
126
+
127
+ case "[object RegExp]": {
128
+ return obj
129
+ }
130
+
131
+ case "[object Function]": {
132
+ return obj
133
+ }
134
+
135
+ case "[object Object]": {
136
+ if (seenObjects.includes(obj)) {
137
+ throw new Error("deepClone: encountered a cyclic object")
138
+ }
139
+
140
+ seenObjects.push(obj)
141
+
142
+ const clonedObj: any = {}
143
+
144
+ for (const propName in obj) {
145
+ if (!obj.hasOwnProperty(propName)) {
146
+ continue
147
+ }
148
+
149
+ if (deep) {
150
+ clonedObj[propName] = clone(obj[propName], true, seenObjects)
151
+ } else {
152
+ clonedObj[propName] = obj[propName]
153
+ }
154
+ }
155
+
156
+ seenObjects.pop()
157
+
158
+ return clonedObj
159
+ }
160
+
161
+ default: {
162
+ throw new Error(`Cloning of type ${prototypeIdentifier} is not supported`)
163
+ }
164
+ }
165
+ }
166
+
167
+ export function isPlainObject(val: any) {
168
+ return val != null && typeof val === "object" && toString.call(val) === "[object Object]"
169
+ }
@@ -0,0 +1,13 @@
1
+ export class OpenPromise<T = void>
2
+ {
3
+ promise: Promise<T>
4
+ resolve: (value: T) => void = () => { throw new Error("OpenPromise resolved before initialization") }
5
+ reject: (reason?: any) => void = () => { throw new Error("OpenPromise rejected before initialization") }
6
+
7
+ constructor() {
8
+ this.promise = new Promise<T>((resolve, reject) => {
9
+ this.resolve = resolve
10
+ this.reject = reject
11
+ })
12
+ }
13
+ }
@@ -0,0 +1,97 @@
1
+ import path from "node:path"
2
+ import { downloadAndExtractTarball } from "./FileDownloader.js"
3
+ import { getAppDataDir, getAppTempDir, ensureDir, existsSync, remove } from "./FileSystem.js"
4
+ import { appName } from "../api/Common.js"
5
+ import { GaxiosOptions } from "gaxios"
6
+
7
+ export async function loadPackage(packageName: string) {
8
+ packageName = resolveToVersionedPackageNameIfNeeded(packageName)
9
+
10
+ const packagesPath = await ensureAndGetPackagesDir()
11
+
12
+ const packagePath = path.join(packagesPath, packageName)
13
+
14
+ if (existsSync(packagePath)) {
15
+ return packagePath
16
+ }
17
+
18
+ const tempPath = getAppTempDir(appName)
19
+
20
+ const headers = {
21
+ }
22
+
23
+ const options: GaxiosOptions = {
24
+ url: `${basePackageUrl}${packageName}.tar.gz`,
25
+ headers
26
+ }
27
+
28
+ await downloadAndExtractTarball(
29
+ options,
30
+ packagesPath,
31
+ tempPath,
32
+ packageName,
33
+ )
34
+
35
+ return packagePath
36
+ }
37
+
38
+ export async function removePackage(packageName: string) {
39
+ packageName = resolveToVersionedPackageNameIfNeeded(packageName)
40
+
41
+ const packagesPath = await ensureAndGetPackagesDir()
42
+
43
+ const packagePath = path.join(packagesPath, packageName)
44
+
45
+ await remove(packagePath)
46
+ }
47
+
48
+ export async function ensureAndGetPackagesDir() {
49
+ const dataPath = getAppDataDir(appName)
50
+
51
+ const packagesPath = path.join(dataPath, "packages")
52
+
53
+ await ensureDir(packagesPath)
54
+
55
+ return packagesPath
56
+ }
57
+
58
+ export function resolveToVersionedPackageNameIfNeeded(packageName: string) {
59
+ const versionTag = getVersionTagFromPackageName(packageName)
60
+
61
+ if (versionTag) {
62
+ return packageName
63
+ }
64
+
65
+ const resolvedVersionTag = resolveVersionTagForUnversionedPackageName(packageName)
66
+
67
+ return packageName = `${packageName}-${resolvedVersionTag}`
68
+ }
69
+
70
+ export function getVersionTagFromPackageName(packageName: string) {
71
+ return packageName.match(/.*\-([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9](_[0-9]+)?)$/)?.[1]
72
+ }
73
+
74
+ export function resolveVersionTagForUnversionedPackageName(unversionedPackageName: string) {
75
+ return packageVersionTagResolutionLookup[unversionedPackageName] || defaultVersionTag
76
+ }
77
+
78
+ const basePackageUrl = "https://huggingface.co/echogarden/echogarden-packages/resolve/main/"
79
+
80
+ const defaultVersionTag = "20230718"
81
+
82
+ const packageVersionTagResolutionLookup: { [packageName: string]: string } = {
83
+ "sox-14.4.2-linux-minimal": "20230802",
84
+ "vits-de_DE-thorsten_emotional-medium": "20230808",
85
+ "vits-en_GB-semaine-medium": "20230808",
86
+ "vits-fr_FR-upmc-medium": "20230808",
87
+ "vits-lb_LU-marylux-medium": "20230808",
88
+ "vits-ro_RO-mihai-medium": "20230808",
89
+ "vits-sr_RS-serbski_institut-medium": "20230808",
90
+ "vits-tr_TR-dfki-medium": "20230808",
91
+ "vits-cs_CZ-jirka-medium": "20230824",
92
+ "vits-de_DE-thorsten-high": "20230824",
93
+ "vits-hu_HU-anna-medium": "20230824",
94
+ "vits-pt_PT-tugao-medium": "20230824",
95
+ "vits-sk_SK-lili-medium": "20230824",
96
+ "vits-tr_TR-fahrettin-medium": "20230824",
97
+ }
@@ -0,0 +1,17 @@
1
+ export class Queue<T> {
2
+ list: T[] = []
3
+
4
+ constructor() {
5
+ }
6
+
7
+ enqueue(item: T) {
8
+ this.list.push(item)
9
+ }
10
+
11
+ dequeue(): T | undefined {
12
+ return this.list.shift()
13
+ }
14
+
15
+ get isEmpty() { return this.list.length == 0 }
16
+ get isNonempty() { return !this.isEmpty }
17
+ }
@@ -0,0 +1,237 @@
1
+ import { sumVector } from "../math/VectorMath.js"
2
+ import { logToStderr } from "./Utilities.js"
3
+
4
+ export abstract class RandomGenerator {
5
+ getIntInRange(min: number, max: number) {
6
+ return Math.floor(this.getFloatInRange(min, max))
7
+ }
8
+
9
+ getFloatInRange(min = 0, max = 1) {
10
+ return min + (this.nextFloat() * (max - min))
11
+ }
12
+
13
+ getFloats(length: number, min = 0, max = 1) {
14
+ const result = []
15
+
16
+ for (let i = 0; i < length; i++) {
17
+ result.push(this.getFloatInRange(min, max))
18
+ }
19
+
20
+ return result
21
+ }
22
+
23
+ getInts(length: number, min: number, max: number) {
24
+ const result = []
25
+
26
+ for (let i = 0; i < length; i++) {
27
+ result.push(this.getIntInRange(min, max))
28
+ }
29
+
30
+ return result
31
+ }
32
+
33
+ getNormallyDistributedVector(featureCount: number, meanVector: number[], standardDeviationVector: number[]) {
34
+ const features = this.getNormallyDistributedValues(featureCount)
35
+
36
+ for (let i = 0; i < features.length; i++) {
37
+ features[i] = meanVector[i] + (features[i] * standardDeviationVector[i])
38
+ }
39
+
40
+ return features
41
+ }
42
+
43
+ getNormallyDistributedValues(count: number, mean = 0, standardDeviation = 1) {
44
+ const result: number[] = []
45
+
46
+ for (let i = 0; i < count; i += 2) {
47
+ const [n1, n2] = this.getNormallyDistributedPair()
48
+
49
+ result.push(mean + (n1 * standardDeviation))
50
+
51
+ if (i + 1 < count) {
52
+ result.push(mean + (n2 * standardDeviation))
53
+ }
54
+ }
55
+
56
+ return result
57
+ }
58
+
59
+ getNormallyDistributedPair() {
60
+ // Using Marsaglia polar method
61
+ // https://en.wikipedia.org/wiki/Marsaglia_polar_method
62
+
63
+ let x: number
64
+ let y: number
65
+ let s: number
66
+
67
+ do {
68
+ x = (this.nextFloat() * 2) - 1
69
+ y = (this.nextFloat() * 2) - 1
70
+
71
+ s = (x ** 2) + (y ** 2)
72
+ } while (s <= 0 || s >= 1)
73
+
74
+ const m = Math.sqrt((-2 * Math.log(s)) / s)
75
+
76
+ const n1 = x * m
77
+ const n2 = y * m
78
+
79
+ return [n1, n2]
80
+ }
81
+
82
+ selectRandomIndexFromDistribution(distribution: number[]) {
83
+ const sum = sumVector(distribution)
84
+
85
+ const randomTarget = this.getFloatInRange(0, sum)
86
+
87
+ let cumSum = 0
88
+
89
+ for (let i = 0; i < distribution.length; i++) {
90
+ const element = distribution[i]
91
+
92
+ if (randomTarget < cumSum + element) {
93
+ return i
94
+ }
95
+
96
+ cumSum += element
97
+ }
98
+
99
+ return distribution.length - 1
100
+ }
101
+
102
+ abstract nextFloat(): number
103
+ abstract nextUint32(): number
104
+ abstract nextInt32(): number
105
+ }
106
+
107
+ export class MurmurRNG extends RandomGenerator {
108
+ state: number
109
+
110
+ constructor(seed: number) {
111
+ super()
112
+
113
+ this.state = seed
114
+ }
115
+
116
+ nextFloat() {
117
+ return this.nextUint32() / 4294967296
118
+ }
119
+
120
+ nextUint32() {
121
+ return this.nextInt32() >>> 0
122
+ }
123
+
124
+ nextInt32() {
125
+ const multiplier = 3332679571
126
+
127
+ let s = this.state
128
+
129
+ s = Math.imul(s, multiplier)
130
+ s ^= s >>> 16
131
+
132
+ s = Math.imul(s, multiplier)
133
+ s ^= s >>> 10
134
+
135
+ s = Math.imul(s, multiplier)
136
+ s ^= s >>> 17
137
+
138
+ this.state = s
139
+
140
+ return s
141
+ }
142
+
143
+ static hashInt32(val: number, seed = 234928357) {
144
+ const rng = new MurmurRNG(seed ^ val)
145
+ return rng.nextUint32()
146
+ }
147
+ }
148
+
149
+ export class XorShift32RNG extends RandomGenerator {
150
+ state: number
151
+
152
+ constructor(seed: number) {
153
+ super()
154
+
155
+ this.state = seed
156
+ }
157
+
158
+ nextFloat() {
159
+ return this.nextUint32() / 4294967296
160
+ }
161
+
162
+ nextUint32() {
163
+ return this.nextInt32() >>> 0
164
+ }
165
+
166
+ nextInt32() {
167
+ let s = this.state
168
+
169
+ s ^= s << 13
170
+ s ^= s >>> 17
171
+ s ^= s << 5
172
+
173
+ this.state = s
174
+
175
+ return s
176
+ }
177
+ }
178
+
179
+ export class LehmerRNG extends RandomGenerator {
180
+ state: number
181
+
182
+ constructor(seed: number) {
183
+ super()
184
+
185
+ this.state = seed
186
+ }
187
+
188
+ nextFloat() {
189
+ return this.nextUint32() / 4294967296
190
+ }
191
+
192
+ nextUint32() {
193
+ return this.nextInt32() >>> 0
194
+ }
195
+
196
+ nextInt32() {
197
+ let s = this.state
198
+
199
+ s = s * 48271 % 0x7fffffff
200
+
201
+ this.state = s
202
+
203
+ return s
204
+ }
205
+ }
206
+
207
+ const log = logToStderr
208
+
209
+ export function testRngCycleLength() {
210
+ const seed = 1
211
+
212
+ const rng = new XorShift32RNG(seed)
213
+
214
+ const bucketCount = 1000000
215
+ const seen: number[][] = []
216
+
217
+ for (let i = 0; i < bucketCount; i++) {
218
+ seen[i] = []
219
+ }
220
+
221
+ for (let i = 0; i < 4294967296; i++) {
222
+ if (i % 1000000 == 0) {
223
+ log(`${i} iterations`)
224
+ }
225
+
226
+ const r = rng.nextUint32()
227
+
228
+ const bucket = seen[r % bucketCount]
229
+
230
+ if (bucket.includes(r)) {
231
+ log(`Cycles at iteration ${i}`)
232
+ return
233
+ }
234
+
235
+ bucket.push(r)
236
+ }
237
+ }
@@ -0,0 +1,22 @@
1
+ export class SignalChannel {
2
+ channel: MessageChannel
3
+
4
+ constructor() {
5
+ this.channel = new MessageChannel()
6
+
7
+ }
8
+
9
+ on(signalName: string, handler: (data?: any) => void) {
10
+ this.channel.port2.onmessage = (event: MessageEvent) => {
11
+ if (event.data.signalName != signalName) {
12
+ return
13
+ }
14
+
15
+ handler(event.data.data)
16
+ }
17
+ }
18
+
19
+ send(signalName: string, data?: any) {
20
+ this.channel.port1.postMessage({ signalName, data })
21
+ }
22
+ }
@@ -0,0 +1,68 @@
1
+ import path from "path"
2
+ import { createTarball } from "./Compression.js"
3
+ import { ensureDir, existsSync, getAppTempDir, move, readdir, stat } from "./FileSystem.js"
4
+ import { ensureAndGetPackagesDir } from "./PackageManager.js"
5
+ import { appName } from "../api/Common.js"
6
+ import { getRandomHexString } from "./Utilities.js"
7
+
8
+ const tarballDir = "../resources/tarballs"
9
+
10
+ export async function makeTarballsForInstalledPackages(skipIfExists = false) {
11
+ const packagesDir = await ensureAndGetPackagesDir()
12
+ const packageList = await readdir(packagesDir)
13
+
14
+ for (const packageName of packageList) {
15
+ if (skipIfExists && existsSync(path.join(tarballDir, `${packageName}.tar.gz`))) {
16
+ continue
17
+ }
18
+
19
+ const packagePath = path.join(packagesDir, packageName)
20
+ await createNamedTarball(packagePath, packageName)
21
+ }
22
+ }
23
+
24
+ export async function createNamedTarball(inputPath: string, name: string) {
25
+ const tempDir = getAppTempDir(appName)
26
+ await ensureDir(tempDir)
27
+ const tempFilename = path.join(tempDir, getRandomHexString(16))
28
+
29
+ await createTarball(inputPath, tempFilename, name)
30
+
31
+ const targetFilname = path.join(tarballDir, `${name}.tar.gz`)
32
+
33
+ await move(tempFilename, targetFilname)
34
+ }
35
+
36
+ export async function createTarballForEachDirIn(baseDir: string, namePrefix: String) {
37
+ for (const dirName of await readdir(baseDir)) {
38
+ const dirPath = path.join(baseDir, dirName)
39
+
40
+ const fileStat = await stat(dirPath)
41
+
42
+ if (!fileStat.isDirectory()) {
43
+ continue
44
+ }
45
+
46
+ const archiveName = `${namePrefix}-${dirName}`
47
+
48
+ await createNamedTarball(dirPath, archiveName)
49
+ }
50
+ }
51
+
52
+ export async function createTarballForEachFileIn(baseDir: string, namePrefix: String) {
53
+ for (const filename of await readdir(baseDir)) {
54
+ const filenameWithoutExtension = path.parse(filename).name
55
+
56
+ const filePath = path.join(baseDir, filename)
57
+
58
+ const fileStat = await stat(filePath)
59
+
60
+ if (!fileStat.isFile()) {
61
+ continue
62
+ }
63
+
64
+ const archiveName = `${namePrefix}-${filenameWithoutExtension}`
65
+
66
+ await createNamedTarball(filePath, archiveName)
67
+ }
68
+ }