template-replacement 3.0.8 → 3.2.0
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/README.md +178 -0
- package/core/base.ts +28 -15
- package/core/general.ts +1 -1
- package/core/sign.ts +1 -1
- package/dispatcher/workerGeneral.ts +1 -0
- package/dispatcher/workerSign.ts +1 -0
- package/dist/assets/template_replacement_core_wasm_bg.wasm +0 -0
- package/dist/assets/template_replacement_sign_core_wasm_bg.wasm +0 -0
- package/dist/base-dj-SYiQI.js +193 -0
- package/dist/index-BlAsmv2Q.js +62 -0
- package/dist/main/general.js +15 -4536
- package/dist/main/sign.js +15 -4559
- package/dist/replace/general.js +340 -368
- package/dist/replace/sign.js +341 -367
- package/fileSystem/db/index.ts +37 -0
- package/{db → fileSystem/db}/indexedDBCache.ts +16 -0
- package/fileSystem/index.ts +13 -0
- package/fileSystem/interface.ts +8 -0
- package/fileSystem/opfs/index.ts +46 -0
- package/helper/index.ts +1 -3
- package/index.ts +10 -0
- package/package.json +9 -11
- package/pnpm-workspace.yaml +2 -0
- package/replace/base.ts +53 -26
- package/replace/general.ts +2 -2
- package/replace/interface.ts +5 -0
- package/replace/sign.ts +2 -2
- package/task/urlDownloadTask.ts +18 -8
- package/temp/index.ts +8 -2
- package/vite.config.ts +13 -1
- package/worker/child/agency.ts +9 -0
- package/worker/child/base.ts +14 -2
- package/worker/main/index.ts +28 -12
- package/db/index.ts +0 -5
- package/dist/base-CC-6cmrq.js +0 -189
- package/dist/index-BkwrGCka.js +0 -61
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import indexedDBCache from './indexedDBCache'
|
|
2
|
+
import FileSystem, {fileDataType} from '../interface'
|
|
3
|
+
|
|
4
|
+
const db = new indexedDBCache()
|
|
5
|
+
|
|
6
|
+
export default class DbFile implements FileSystem {
|
|
7
|
+
#name: string = ''
|
|
8
|
+
|
|
9
|
+
constructor(name: string){
|
|
10
|
+
this.#name = name
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async write(data: fileDataType): Promise<boolean> {
|
|
14
|
+
try {
|
|
15
|
+
await db.putData<File>({
|
|
16
|
+
url: this.#name,
|
|
17
|
+
data: new File([data], this.#name),
|
|
18
|
+
})
|
|
19
|
+
return true
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(error)
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async read(): Promise<File>{
|
|
27
|
+
const data = await db.getDataByKey<File>(this.#name)
|
|
28
|
+
if (data && data.data) {
|
|
29
|
+
return data.data
|
|
30
|
+
}
|
|
31
|
+
return new File([], this.#name)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
remove(): Promise<void> {
|
|
35
|
+
return db.deleteDataByKey(this.#name)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -111,6 +111,22 @@ export default class indexedDBCache {
|
|
|
111
111
|
})
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// 通过主键移除数据
|
|
115
|
+
deleteDataByKey<T>(key: string): Promise<void> {
|
|
116
|
+
return new Promise(async (resolve, reject) => {
|
|
117
|
+
// 通过主键读取数据
|
|
118
|
+
const request = (await this.store()).delete(key)
|
|
119
|
+
// 操作成功
|
|
120
|
+
request.onsuccess = () => {
|
|
121
|
+
resolve()
|
|
122
|
+
}
|
|
123
|
+
// 操作失败
|
|
124
|
+
request.onerror = (event) => {
|
|
125
|
+
reject(event)
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
// 清空数据库数据
|
|
115
131
|
clearDB(): Promise<any> {
|
|
116
132
|
return new Promise(async (resolve, reject) => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import FileSystem from './interface'
|
|
2
|
+
import OpfsFile from './opfs'
|
|
3
|
+
import DbFile from './db'
|
|
4
|
+
|
|
5
|
+
export default (name: string): FileSystem => {
|
|
6
|
+
if (navigator?.storage?.getDirectory) {
|
|
7
|
+
return new OpfsFile(name)
|
|
8
|
+
}
|
|
9
|
+
return new DbFile(name)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import FileSystem, {fileDataType} from '../interface'
|
|
2
|
+
|
|
3
|
+
let opfsRoot: Promise<FileSystemDirectoryHandle> | undefined = undefined
|
|
4
|
+
|
|
5
|
+
function getOpfsRoot(): Promise<FileSystemDirectoryHandle> {
|
|
6
|
+
if (!opfsRoot) {
|
|
7
|
+
opfsRoot = navigator.storage.getDirectory()
|
|
8
|
+
}
|
|
9
|
+
return opfsRoot
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default class OpfsFile implements FileSystem {
|
|
13
|
+
#name: string = ''
|
|
14
|
+
#handle: FileSystemFileHandle | undefined
|
|
15
|
+
|
|
16
|
+
constructor(name: string){
|
|
17
|
+
this.#name = name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async getHandle(): Promise<FileSystemFileHandle> {
|
|
21
|
+
if (!this.#handle) {
|
|
22
|
+
this.#handle = await (await getOpfsRoot()).getFileHandle(this.#name, { create: true })
|
|
23
|
+
}
|
|
24
|
+
return this.#handle
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async write(data: fileDataType): Promise<boolean> {
|
|
28
|
+
try {
|
|
29
|
+
const writable = await (await this.getHandle()).createWritable()
|
|
30
|
+
await writable.write(data)
|
|
31
|
+
await writable.close()
|
|
32
|
+
return true
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error(error)
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async read(): Promise<File>{
|
|
40
|
+
return (await this.getHandle()).getFile()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async remove(): Promise<void> {
|
|
44
|
+
return (await getOpfsRoot()).removeEntry(this.#name)
|
|
45
|
+
}
|
|
46
|
+
}
|
package/helper/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { nanoid } from 'nanoid'
|
|
2
1
|
import urlDownloadTask from '../task/urlDownloadTask'
|
|
3
2
|
import { fileTypeFromBuffer } from 'file-type'
|
|
4
3
|
|
|
@@ -57,7 +56,7 @@ export async function fileTypeByBuffer(buffer: Uint8Array|ArrayBuffer|Blob): Pro
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
export function generateId(): string {
|
|
60
|
-
return
|
|
59
|
+
return crypto.randomUUID()
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
export type fileArrayBufferData = {
|
|
@@ -67,7 +66,6 @@ export type fileArrayBufferData = {
|
|
|
67
66
|
|
|
68
67
|
export async function filesReaderArrayBuffer(files: File[]): Promise<fileArrayBufferData[]> {
|
|
69
68
|
const awaits = []
|
|
70
|
-
files.forEach
|
|
71
69
|
for (const file of files) {
|
|
72
70
|
awaits.push(new Promise(async (resolve, reject) => {
|
|
73
71
|
try {
|
package/index.ts
CHANGED
|
@@ -18,4 +18,14 @@ export function WorkerGeneral(concurrency?: number): ReplaceInterface {
|
|
|
18
18
|
|
|
19
19
|
export function WorkerSign(concurrency?: number): ReplaceInterface {
|
|
20
20
|
return workerSign(concurrency)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type signFun = (data: any) => Promise<string>;
|
|
24
|
+
|
|
25
|
+
export default (concurrency?: number, signFn?: signFun): ReplaceInterface => {
|
|
26
|
+
if (concurrency) {
|
|
27
|
+
return signFn ? workerSign(concurrency) : workerGeneral(concurrency)
|
|
28
|
+
}else {
|
|
29
|
+
return signFn ? sign() : general()
|
|
30
|
+
}
|
|
21
31
|
}
|
package/package.json
CHANGED
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "template-replacement",
|
|
3
3
|
"description": "模板文件替换",
|
|
4
|
-
"version": "3.0
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"author": "fushiliang <994301536@qq.com>",
|
|
6
|
-
"license": "ISC",
|
|
7
6
|
"type": "module",
|
|
8
7
|
"main": "index.ts",
|
|
9
8
|
"scripts": {
|
|
10
9
|
"build": "npx vite build --config vite.config.ts"
|
|
11
10
|
},
|
|
12
11
|
"dependencies": {
|
|
13
|
-
"@types/crypto-js": "^4.2.2",
|
|
14
12
|
"@types/streamsaver": "^2.0.5",
|
|
15
|
-
"axios": "^1.
|
|
13
|
+
"axios": "^1.10.0",
|
|
16
14
|
"fflate": "^0.8.2",
|
|
17
15
|
"file-type": "^19.6.0",
|
|
18
|
-
"
|
|
16
|
+
"rollup-plugin-terser": "^7.0.2",
|
|
19
17
|
"streamsaver": "^2.0.6",
|
|
20
|
-
"template-replacement-core-wasm": "^1.
|
|
21
|
-
"template-replacement-sign-core-wasm": "^1.
|
|
18
|
+
"template-replacement-core-wasm": "^1.1.1",
|
|
19
|
+
"template-replacement-sign-core-wasm": "^1.1.1",
|
|
22
20
|
"vite-plugin-wasm-pack": "^0.1.12"
|
|
23
21
|
},
|
|
24
22
|
"devDependencies": {
|
|
25
|
-
"
|
|
26
|
-
"typescript": "^5.
|
|
27
|
-
"vite": "^6.
|
|
28
|
-
"vite-plugin-dts": "^4.5.
|
|
23
|
+
"terser": "^5.43.1",
|
|
24
|
+
"typescript": "^5.8.3",
|
|
25
|
+
"vite": "^6.3.5",
|
|
26
|
+
"vite-plugin-dts": "^4.5.4"
|
|
29
27
|
},
|
|
30
28
|
"keywords": [
|
|
31
29
|
"template-replacement"
|
package/replace/base.ts
CHANGED
|
@@ -29,8 +29,8 @@ export default class Base implements Interface{
|
|
|
29
29
|
for (const file of files) {
|
|
30
30
|
tasks.push(new Promise<void>(async (resolve, reject) => {
|
|
31
31
|
const buffer = await file.getBuffer()
|
|
32
|
-
if (buffer && (await file.type()) !== fileTypes.unknown) {
|
|
33
|
-
data[file.name] = await this.#core.extract_one_file_variable_names(buffer)
|
|
32
|
+
if (buffer && (file.isDecode || (await file.type()) !== fileTypes.unknown)) {
|
|
33
|
+
data[file.name] = await this.#core.extract_one_file_variable_names(buffer, file.isDecode)
|
|
34
34
|
}
|
|
35
35
|
resolve()
|
|
36
36
|
}))
|
|
@@ -48,8 +48,8 @@ export default class Base implements Interface{
|
|
|
48
48
|
for (const file of files) {
|
|
49
49
|
tasks.push(new Promise<void>(async (resolve, reject) => {
|
|
50
50
|
const buffer = await file.getBuffer()
|
|
51
|
-
if (buffer && (await file.type()) !== fileTypes.unknown) {
|
|
52
|
-
let medias = await this.#core.extract_one_file_medias(buffer)
|
|
51
|
+
if (buffer && (file.isDecode || (await file.type()) !== fileTypes.unknown)) {
|
|
52
|
+
let medias = await this.#core.extract_one_file_medias(buffer, file.isDecode)
|
|
53
53
|
data[file.name] = []
|
|
54
54
|
if (medias && Array.isArray(medias)) {
|
|
55
55
|
medias.forEach(m => {
|
|
@@ -69,7 +69,7 @@ export default class Base implements Interface{
|
|
|
69
69
|
return data
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
async handle(paramsData: paramsData, files: Uint8Array[]): Promise<Uint8Array[]> {
|
|
72
|
+
async handle(paramsData: paramsData, files: Uint8Array[], isDecode: boolean = false): Promise<Uint8Array[]> {
|
|
73
73
|
return []
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -82,43 +82,70 @@ export default class Base implements Interface{
|
|
|
82
82
|
files = this.#files
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
names: [],
|
|
87
|
-
uint8Arrays: [],
|
|
88
|
-
}
|
|
89
|
-
|
|
85
|
+
//等待文件加载完成
|
|
90
86
|
const tasks = []
|
|
91
87
|
for (const file of files) {
|
|
92
|
-
tasks.push(
|
|
93
|
-
resolve(file.getBuffer())
|
|
94
|
-
}))
|
|
88
|
+
tasks.push(file.getBuffer())
|
|
95
89
|
}
|
|
96
90
|
await Promise.all(tasks)
|
|
97
91
|
|
|
92
|
+
const fileMap: { decode: { names: string[], uint8Arrays: Uint8Array[] }, noDecode: { names: string[], uint8Arrays: Uint8Array[] }} = {
|
|
93
|
+
//需要解密的文件
|
|
94
|
+
decode: {
|
|
95
|
+
names: [],
|
|
96
|
+
uint8Arrays: [],
|
|
97
|
+
},
|
|
98
|
+
//不需要解密的文件
|
|
99
|
+
noDecode: {
|
|
100
|
+
names: [],
|
|
101
|
+
uint8Arrays: [],
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
//整理出需要解密和不需要解密的文件
|
|
98
106
|
for (const file of files) {
|
|
99
|
-
if (file.uint8Array) {
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
if (!file.uint8Array) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (file.isDecode) {
|
|
111
|
+
fileMap.decode.names.push(file.name)
|
|
112
|
+
fileMap.decode.uint8Arrays.push(file.uint8Array)
|
|
113
|
+
} else {
|
|
114
|
+
fileMap.noDecode.names.push(file.name)
|
|
115
|
+
fileMap.noDecode.uint8Arrays.push(file.uint8Array)
|
|
102
116
|
}
|
|
103
117
|
}
|
|
118
|
+
//分别处理需要解密和不需要解密的文件
|
|
119
|
+
const res = await Promise.all([
|
|
120
|
+
this._execute(params, fileMap.noDecode.names, fileMap.noDecode.uint8Arrays, false),
|
|
121
|
+
this._execute(params, fileMap.decode.names, fileMap.decode.uint8Arrays, true),
|
|
122
|
+
])
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
|
|
124
|
+
return {
|
|
125
|
+
...res[0],
|
|
126
|
+
...res[1],
|
|
107
127
|
}
|
|
128
|
+
}
|
|
108
129
|
|
|
109
|
-
|
|
110
|
-
const finishStatusCount = {
|
|
111
|
-
success: 0,
|
|
112
|
-
total: fileData.uint8Arrays.length
|
|
113
|
-
} //完成状态统计
|
|
130
|
+
async _execute(params: paramsData, names: string[], uint8Arrays: Uint8Array[], isDecode: boolean = false): Promise<Record<string, Uint8Array>> {
|
|
114
131
|
const resData: Record<string, Uint8Array> = {}
|
|
115
|
-
|
|
132
|
+
if (!uint8Arrays.length) {
|
|
133
|
+
return resData
|
|
134
|
+
}
|
|
135
|
+
const res = await this.handle(params, uint8Arrays, isDecode)
|
|
116
136
|
res.forEach((file, i) => {
|
|
117
137
|
if (file.length) {
|
|
118
|
-
resData[
|
|
119
|
-
finishStatusCount.success++
|
|
138
|
+
resData[names[i]] = file
|
|
120
139
|
}
|
|
121
140
|
})
|
|
122
141
|
return resData
|
|
123
142
|
}
|
|
143
|
+
|
|
144
|
+
async fileEncrypt(file: Uint8Array): Promise<Uint8Array> {
|
|
145
|
+
return await this.#core.file_encrypt(file)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async filesEncrypt(files: (Uint8Array)[]): Promise<(Uint8Array)[]> {
|
|
149
|
+
return await this.#core.files_encrypt(files)
|
|
150
|
+
}
|
|
124
151
|
}
|
package/replace/general.ts
CHANGED
|
@@ -7,8 +7,8 @@ export default class General extends Base {
|
|
|
7
7
|
super(core())
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
async handle(paramsData: paramsData, files: Uint8Array[]): Promise<Uint8Array[]> {
|
|
10
|
+
async handle(paramsData: paramsData, files: Uint8Array[], isDecode: boolean = false): Promise<Uint8Array[]> {
|
|
11
11
|
const [params, mediaBuffers] = await paramsData.toReplaceParams()
|
|
12
|
-
return replace_batch(params, mediaBuffers, files)
|
|
12
|
+
return replace_batch(params, mediaBuffers, files, isDecode)
|
|
13
13
|
}
|
|
14
14
|
}
|
package/replace/interface.ts
CHANGED
|
@@ -26,4 +26,9 @@ export default interface ReplaceInterface {
|
|
|
26
26
|
//执行替换任务
|
|
27
27
|
execute(params: paramsData, files: Temp[] | undefined): Promise<Record<string, Uint8Array>>
|
|
28
28
|
|
|
29
|
+
//文件加密
|
|
30
|
+
fileEncrypt(file: Uint8Array): Promise<Uint8Array>
|
|
31
|
+
|
|
32
|
+
//文件批量加密
|
|
33
|
+
filesEncrypt(files: (Uint8Array)[]): Promise<(Uint8Array)[]>
|
|
29
34
|
}
|
package/replace/sign.ts
CHANGED
|
@@ -7,14 +7,14 @@ export default class Sign extends Base {
|
|
|
7
7
|
super(core())
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
async handle(paramsData: paramsData, files: Uint8Array[]): Promise<Uint8Array[]> {
|
|
10
|
+
async handle(paramsData: paramsData, files: Uint8Array[], isDecode: boolean = false): Promise<Uint8Array[]> {
|
|
11
11
|
paramsData.add_media = add_media
|
|
12
12
|
const [params] = await paramsData.toReplaceParams()
|
|
13
13
|
|
|
14
14
|
const addFileTasks: Promise<number>[] = []
|
|
15
15
|
files.forEach((file, i) => {
|
|
16
16
|
addFileTasks.push(new Promise<number>(async resolve => {
|
|
17
|
-
resolve(await add_template(file))
|
|
17
|
+
resolve(await add_template(file, isDecode))
|
|
18
18
|
}))
|
|
19
19
|
})
|
|
20
20
|
|
package/task/urlDownloadTask.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import axios, { AxiosProgressEvent } from "axios"
|
|
2
|
-
import
|
|
2
|
+
import file from "../fileSystem"
|
|
3
|
+
|
|
4
|
+
async function hashString(str: string): Promise<string> {
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
const data = encoder.encode(str);
|
|
7
|
+
const hashBuffer = await window.crypto.subtle.digest("SHA-1", data);
|
|
8
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
9
|
+
const hashHex = hashArray
|
|
10
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
11
|
+
.join("");
|
|
12
|
+
return hashHex;
|
|
13
|
+
}
|
|
3
14
|
|
|
4
15
|
export default class urlDownloadTask {
|
|
5
16
|
urls: string[]
|
|
@@ -21,18 +32,17 @@ export default class urlDownloadTask {
|
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
async getUrlData(url: string): Promise<Blob|undefined> {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
const hash = await hashString(url)
|
|
36
|
+
const fileObj = file(hash)
|
|
37
|
+
const data = await fileObj.read()
|
|
38
|
+
if (data.size) {
|
|
39
|
+
return data
|
|
27
40
|
}
|
|
28
41
|
const getData = await this.download(url)
|
|
29
42
|
if (!getData) {
|
|
30
43
|
return undefined
|
|
31
44
|
}
|
|
32
|
-
|
|
33
|
-
url: url,
|
|
34
|
-
data: getData,
|
|
35
|
-
})
|
|
45
|
+
fileObj.write(getData)
|
|
36
46
|
return getData
|
|
37
47
|
}
|
|
38
48
|
|
package/temp/index.ts
CHANGED
|
@@ -19,13 +19,17 @@ export enum status {
|
|
|
19
19
|
export type transmitFileInfo = {
|
|
20
20
|
name: string,
|
|
21
21
|
uint8Array: Uint8Array,
|
|
22
|
+
isDecode: boolean,
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
//将传递的文件信息转为模板对象
|
|
24
26
|
export function transmitFileInfoToTemp(data: transmitFileInfo) {
|
|
25
27
|
if (!data.uint8Array || !data.name) {
|
|
26
28
|
throw new Error("模板文件信息错误")
|
|
27
29
|
}
|
|
28
|
-
|
|
30
|
+
const temp = new Temp(undefined, undefined, data.uint8Array, data.name)
|
|
31
|
+
temp.isDecode = data.isDecode
|
|
32
|
+
return temp
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
export default class Temp implements TempInterface{
|
|
@@ -34,6 +38,7 @@ export default class Temp implements TempInterface{
|
|
|
34
38
|
uint8Array?: Uint8Array
|
|
35
39
|
url?: string
|
|
36
40
|
status = status.waitLoad // 0文件待加载,1文件已加载,2完成替换,3替换失败
|
|
41
|
+
isDecode: boolean = false //文件是否被加密
|
|
37
42
|
|
|
38
43
|
_output?: File|Blob
|
|
39
44
|
_type?: fileTypes
|
|
@@ -107,7 +112,7 @@ export default class Temp implements TempInterface{
|
|
|
107
112
|
}
|
|
108
113
|
if (!this.blob) {
|
|
109
114
|
if (this.uint8Array) {
|
|
110
|
-
this.blob = new Blob([ this.uint8Array ])
|
|
115
|
+
this.blob = new Blob([ this.uint8Array as BlobPart ])
|
|
111
116
|
}else if (this.url) {
|
|
112
117
|
const [ blob ] = await urlsToFileBlobs([ this.url ])
|
|
113
118
|
if (blob) {
|
|
@@ -152,6 +157,7 @@ export default class Temp implements TempInterface{
|
|
|
152
157
|
return {
|
|
153
158
|
name: this.getName(),
|
|
154
159
|
uint8Array: new Uint8Array(uint8Array.buffer.slice(0)),
|
|
160
|
+
isDecode: this.isDecode,
|
|
155
161
|
}
|
|
156
162
|
}
|
|
157
163
|
}
|
package/vite.config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import wasmPack from 'vite-plugin-wasm-pack';
|
|
3
3
|
import dts from 'vite-plugin-dts';
|
|
4
|
+
import { terser } from 'rollup-plugin-terser';
|
|
4
5
|
|
|
5
6
|
export default defineConfig({
|
|
6
7
|
plugins: [
|
|
@@ -18,9 +19,20 @@ export default defineConfig({
|
|
|
18
19
|
fileName: (format, entryName) => `${entryName}.js`,
|
|
19
20
|
formats: ['es'],
|
|
20
21
|
},
|
|
22
|
+
minify:"terser",
|
|
21
23
|
rollupOptions: {
|
|
24
|
+
plugins: [terser({
|
|
25
|
+
format: {
|
|
26
|
+
// 取消代码注释
|
|
27
|
+
comments: false,
|
|
28
|
+
},
|
|
29
|
+
mangle: {
|
|
30
|
+
keep_classnames: false,
|
|
31
|
+
reserved: [],
|
|
32
|
+
},
|
|
33
|
+
})],
|
|
22
34
|
output: {
|
|
23
|
-
entryFileNames: info => {
|
|
35
|
+
entryFileNames: (info: { facadeModuleId: string; }) => {
|
|
24
36
|
const modules = info.facadeModuleId?.split('/')
|
|
25
37
|
if (!modules?.length || modules?.length < 2) {
|
|
26
38
|
return '[name].js'
|
package/worker/child/agency.ts
CHANGED
|
@@ -75,4 +75,13 @@ export default class implements ReplaceInterface {
|
|
|
75
75
|
return this.replace.execute(new paramsData(text, media), files)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
//文件加密
|
|
79
|
+
fileEncrypt(file: Uint8Array): Promise<Uint8Array> {
|
|
80
|
+
return this.replace.fileEncrypt(file)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//文件批量加密
|
|
84
|
+
filesEncrypt(files: (Uint8Array)[]): Promise<(Uint8Array)[]> {
|
|
85
|
+
return this.replace.filesEncrypt(files)
|
|
86
|
+
}
|
|
78
87
|
}
|
package/worker/child/base.ts
CHANGED
|
@@ -2,7 +2,6 @@ import agency from './agency'
|
|
|
2
2
|
import { messageData, messageTypes, methodCall } from '../type';
|
|
3
3
|
import ReplaceInterface, { media } from '../../replace/interface';
|
|
4
4
|
import { generateId } from '../../helper';
|
|
5
|
-
import { c } from 'vite/dist/node/types.d-aGj9QkWt';
|
|
6
5
|
|
|
7
6
|
type methodKeys<T> = {
|
|
8
7
|
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
|
|
@@ -13,6 +12,8 @@ const allowCallMethodNames: Partial<Record<methodKeys<ReplaceInterface>, boolean
|
|
|
13
12
|
extractVariables: true,
|
|
14
13
|
extractMedias: true,
|
|
15
14
|
execute: true,
|
|
15
|
+
filesEncrypt: true,
|
|
16
|
+
fileEncrypt: true,
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
const tasks: Record<string, Function> = {} = {}
|
|
@@ -44,6 +45,7 @@ addEventListener('message', async event => {
|
|
|
44
45
|
const data = event.data as messageData
|
|
45
46
|
switch (data.type) {
|
|
46
47
|
case messageTypes.methodCall:
|
|
48
|
+
// 调用方法
|
|
47
49
|
const callData = data.data as methodCall
|
|
48
50
|
const method = callData.method as methodKeys<ReplaceInterface>
|
|
49
51
|
if (!allowCallMethodNames[method]) {
|
|
@@ -71,6 +73,15 @@ addEventListener('message', async event => {
|
|
|
71
73
|
transfer.push(media.data.buffer)
|
|
72
74
|
})
|
|
73
75
|
}
|
|
76
|
+
break;
|
|
77
|
+
case 'fileEncrypt':
|
|
78
|
+
(res as Uint8Array).length && transfer.push((res as Uint8Array).buffer)
|
|
79
|
+
break;
|
|
80
|
+
case 'filesEncrypt':
|
|
81
|
+
for (const item of (res as Uint8Array[])) {
|
|
82
|
+
transfer.push(item.buffer)
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
74
85
|
}
|
|
75
86
|
}
|
|
76
87
|
postMessage({
|
|
@@ -79,10 +90,11 @@ addEventListener('message', async event => {
|
|
|
79
90
|
replyId: callData.replyId,
|
|
80
91
|
result: res
|
|
81
92
|
}
|
|
82
|
-
}, { transfer })
|
|
93
|
+
}, transfer.length ? { transfer } : undefined)
|
|
83
94
|
}
|
|
84
95
|
break;
|
|
85
96
|
case messageTypes.methodCallReply:
|
|
97
|
+
// 方法调用的返回数据
|
|
86
98
|
tasks[data?.data?.replyId](data?.data?.result)
|
|
87
99
|
delete tasks[data?.data?.replyId]
|
|
88
100
|
}
|
package/worker/main/index.ts
CHANGED
|
@@ -16,7 +16,7 @@ const allowCallMethodNames: Partial<Record<methodKeys<ReplaceInterface>, boolean
|
|
|
16
16
|
// 分片最小任务数量
|
|
17
17
|
const chunkMinNum = 20
|
|
18
18
|
|
|
19
|
-
export default class WorkerReplace implements ReplaceInterface{
|
|
19
|
+
export default class WorkerReplace implements ReplaceInterface {
|
|
20
20
|
#files: Temp[] = []
|
|
21
21
|
#dispatcher: DispatcherInterface
|
|
22
22
|
#tasks: Record<string, Function> = {}
|
|
@@ -92,19 +92,19 @@ export default class WorkerReplace implements ReplaceInterface{
|
|
|
92
92
|
method,
|
|
93
93
|
params
|
|
94
94
|
}
|
|
95
|
-
}, { transfer })
|
|
95
|
+
}, transfer.length ? { transfer } : undefined)
|
|
96
96
|
return new Promise((resolve, reject) => {
|
|
97
97
|
this.#tasks[replyId] = resolve
|
|
98
98
|
})
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
//分片
|
|
102
|
-
#chunk<T>(files: T[], chunkPackage?: (chunkData:T[]) => any): any[] {
|
|
102
|
+
#chunk<T>(files: T[], chunkPackage?: (chunkData: T[]) => any): (T[] | ((chunkData: T[]) => any))[] {
|
|
103
103
|
let chunks = []
|
|
104
104
|
if (this.#concurrency > 1 && files.length > chunkMinNum) {
|
|
105
|
-
const chunkSize = Math.ceil(files.length/(Math.round(files.length/chunkMinNum)))
|
|
106
|
-
chunks = splitArrayIntoChunks(files, chunkSize)
|
|
107
|
-
}else {
|
|
105
|
+
const chunkSize = Math.ceil(files.length / (Math.round(files.length / chunkMinNum)))
|
|
106
|
+
chunks = splitArrayIntoChunks<T>(files, chunkSize)
|
|
107
|
+
} else {
|
|
108
108
|
chunks = [files]
|
|
109
109
|
}
|
|
110
110
|
if (chunkPackage) {
|
|
@@ -119,7 +119,7 @@ export default class WorkerReplace implements ReplaceInterface{
|
|
|
119
119
|
if (!files) {
|
|
120
120
|
files = this.#files
|
|
121
121
|
}
|
|
122
|
-
const tasks: Promise<transmitFileInfo|undefined>[] = []
|
|
122
|
+
const tasks: Promise<transmitFileInfo | undefined>[] = []
|
|
123
123
|
files.forEach(file => {
|
|
124
124
|
tasks.push(file.getTransmitFileInfo())
|
|
125
125
|
})
|
|
@@ -127,25 +127,26 @@ export default class WorkerReplace implements ReplaceInterface{
|
|
|
127
127
|
return res.filter(item => !!item)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
addTempFile(tempFile: Temp): void {
|
|
131
|
-
this.#files.push(tempFile)
|
|
132
|
-
}
|
|
133
130
|
|
|
134
131
|
clear(): void {
|
|
135
132
|
this.#files.length = 0
|
|
136
133
|
}
|
|
137
134
|
|
|
138
|
-
async #chunkCall(method: string, paramChunks: any[]): Promise<Record<string, any>>{
|
|
135
|
+
async #chunkCall(method: string, paramChunks: any[]): Promise<Record<string, any>> {
|
|
139
136
|
const tasks: Promise<Record<string, any>>[] = []
|
|
140
137
|
paramChunks.forEach(chunk => {
|
|
141
138
|
tasks.push(this.#call(method, chunk))
|
|
142
139
|
})
|
|
143
140
|
const tasksRes = await Promise.all(tasks)
|
|
144
141
|
return tasksRes.reduce((accumulator, current) => {
|
|
145
|
-
return {...accumulator, ...current}
|
|
142
|
+
return { ...accumulator, ...current }
|
|
146
143
|
}, {})
|
|
147
144
|
}
|
|
148
145
|
|
|
146
|
+
addTempFile(tempFile: Temp): void {
|
|
147
|
+
this.#files.push(tempFile)
|
|
148
|
+
}
|
|
149
|
+
|
|
149
150
|
async extractVariables(files: Temp[] | undefined): Promise<Record<string, string[]>> {
|
|
150
151
|
const fileData = await this.#getTempFileData(files)
|
|
151
152
|
const chunks = this.#chunk(fileData, chunkData => {
|
|
@@ -173,4 +174,19 @@ export default class WorkerReplace implements ReplaceInterface{
|
|
|
173
174
|
})
|
|
174
175
|
return this.#chunkCall('execute', chunks)
|
|
175
176
|
}
|
|
177
|
+
|
|
178
|
+
async fileEncrypt(file: Uint8Array): Promise<Uint8Array> {
|
|
179
|
+
return await this.#call('fileEncrypt', [file])
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async filesEncrypt(files: Uint8Array[]): Promise<Uint8Array[]> {
|
|
183
|
+
const chunks = this.#chunk<Uint8Array>(files) as (Uint8Array[])[]
|
|
184
|
+
|
|
185
|
+
const tasks: Promise<Uint8Array[]>[] = []
|
|
186
|
+
chunks.forEach(chunk => {
|
|
187
|
+
tasks.push(this.#call('filesEncrypt', [chunk]))
|
|
188
|
+
})
|
|
189
|
+
const tasksRes = await Promise.all(tasks)
|
|
190
|
+
return tasksRes.flat()
|
|
191
|
+
}
|
|
176
192
|
}
|