template-replacement 3.3.3 → 3.4.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.
Files changed (56) hide show
  1. package/.editorconfig +8 -0
  2. package/.oxfmtrc.jsonc +7 -0
  3. package/.oxlintrc.json +3 -0
  4. package/README.md +39 -9
  5. package/core/base.ts +54 -55
  6. package/core/general.ts +37 -9
  7. package/core/sign.ts +43 -8
  8. package/dispatcher/general.ts +2 -1
  9. package/dispatcher/sign.ts +2 -1
  10. package/dispatcher/workerGeneral.ts +1 -1
  11. package/dispatcher/workerSign.ts +1 -1
  12. package/dist/base-DQz39fXI.js +249 -0
  13. package/dist/index-oILo_kXG.js +46 -0
  14. package/dist/main/general.js +1334 -1384
  15. package/dist/main/sign.js +1476 -1514
  16. package/dist/replace/general.js +283 -313
  17. package/dist/replace/sign.js +309 -327
  18. package/download/index.ts +13 -13
  19. package/download/stream.ts +29 -28
  20. package/eslint.config.ts +28 -0
  21. package/fileSystem/db/index.ts +25 -25
  22. package/fileSystem/db/indexedDBCache.ts +145 -143
  23. package/fileSystem/index.ts +5 -8
  24. package/fileSystem/interface.ts +4 -5
  25. package/fileSystem/opfs/index.ts +40 -36
  26. package/helper/index.ts +136 -125
  27. package/index.ts +6 -6
  28. package/office/zip.ts +106 -97
  29. package/package.json +14 -8
  30. package/replace/base.ts +203 -222
  31. package/replace/general.ts +44 -24
  32. package/replace/image.ts +88 -90
  33. package/replace/interface.ts +29 -24
  34. package/replace/paramsData.ts +107 -95
  35. package/replace/sign.ts +79 -52
  36. package/task/urlDownloadTask.ts +53 -55
  37. package/temp/index.ts +139 -124
  38. package/temp/interface.ts +8 -8
  39. package/tsconfig.json +1 -1
  40. package/vite.config.ts +11 -14
  41. package/worker/child/agency.ts +49 -41
  42. package/worker/child/base.ts +125 -89
  43. package/worker/child/general.ts +2 -3
  44. package/worker/child/sign.ts +4 -4
  45. package/worker/index.ts +52 -53
  46. package/worker/interface.ts +9 -6
  47. package/worker/main/general.ts +5 -5
  48. package/worker/main/index.ts +191 -66
  49. package/worker/main/sign.ts +5 -5
  50. package/worker/type.ts +16 -15
  51. package/dist/assets/template_replacement_core_wasm_bg.wasm +0 -0
  52. package/dist/assets/template_replacement_sign_core_wasm_bg.wasm +0 -0
  53. package/dist/base-CJv023nf.js +0 -284
  54. package/dist/general.d.ts +0 -1
  55. package/dist/index-tFDVIkZX.js +0 -46
  56. package/dist/sign.d.ts +0 -1
@@ -1,17 +1,19 @@
1
- import { messageData, messageTypes, methodCall, methodCallReply } from '../type';
2
- import DispatcherInterface from '../interface';
3
- import { generateId, splitArrayIntoChunks } from '../../helper';
4
- import ReplaceInterface, { media } from '../../replace/interface';
5
- import paramsData from '../../replace/paramsData';
6
- import Temp, { transmitFileInfo } from '../../temp';
1
+ import { messageData, messageTypes, methodCall, methodCallReply } from '../type'
2
+ import DispatcherInterface from '../interface'
3
+ import { generateId, splitArrayIntoChunks } from '../../helper'
4
+ import ReplaceInterface, { media } from '../../replace/interface'
5
+ import paramsData from '../../replace/paramsData'
6
+ import Temp, { transmitFileInfo } from '../../temp'
7
+ import { Zip, ZipDeflate } from 'fflate'
7
8
 
8
9
  type methodKeys<T> = {
9
- [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
10
- }[keyof T];
10
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
11
+ [K in keyof T]: T[K] extends Function ? K : never
12
+ }[keyof T]
11
13
 
12
- const allowCallMethodNames: Partial<Record<methodKeys<ReplaceInterface>, boolean>> = {
13
- sign: true,
14
- }
14
+ type allMethodNames = methodKeys<ReplaceInterface>
15
+
16
+ const allowCallMethodNames: Set<allMethodNames> = new Set(["sign"])
15
17
 
16
18
  // 分片最小任务数量
17
19
  const chunkMinNum = 20
@@ -19,7 +21,10 @@ const chunkMinNum = 20
19
21
  export default class WorkerReplace implements ReplaceInterface {
20
22
  #files: Temp[] = []
21
23
  #dispatcher: DispatcherInterface
22
- #tasks = new Map<string, Function>()
24
+ #tasks = new Map<string, {
25
+ resolve: (value: unknown) => void,
26
+ reject: (reason?: unknown) => void,
27
+ }>()
23
28
  #concurrency: number = 1
24
29
 
25
30
  constructor(dispatcher: DispatcherInterface) {
@@ -28,8 +33,8 @@ export default class WorkerReplace implements ReplaceInterface {
28
33
  }
29
34
 
30
35
  setDispatcher(dispatcher: DispatcherInterface) {
31
- dispatcher.addListener(event => {
32
- const data = event.data as messageData
36
+ dispatcher.addListener<messageData>(event => {
37
+ const data = event.data
33
38
  switch (data.type) {
34
39
  case messageTypes.methodCallReply:
35
40
  const replyData = data.data as methodCallReply
@@ -37,33 +42,46 @@ export default class WorkerReplace implements ReplaceInterface {
37
42
  return
38
43
  }
39
44
  const fn = this.#tasks.get(replyData.replyId)
40
- if (fn) {
41
- fn(replyData.result)
42
- this.#tasks.delete(replyData.replyId)
45
+ if (!fn) {
46
+ return
47
+ }
48
+ if (replyData.error) {
49
+ fn.reject(replyData.error)
50
+ } else {
51
+ fn.resolve(replyData.result)
43
52
  }
44
- break;
53
+ this.#tasks.delete(replyData.replyId)
54
+ break
45
55
  case messageTypes.methodCall:
46
- const callData = data.data as methodCall
47
- const method = callData.method as methodKeys<ReplaceInterface>
48
- if (!allowCallMethodNames[method]) {
56
+ const callData = data.data as methodCall<allMethodNames>
57
+ const method = callData.method
58
+ if (!allowCallMethodNames.has(method)) {
49
59
  return
50
60
  }
61
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
51
62
  const fun = this[method] as Function | undefined
52
63
  if (!fun) {
53
64
  return
54
65
  }
66
+
55
67
  const callRes = fun.apply(this, callData.params)
56
68
  if (!callData.replyId) {
57
69
  return
58
70
  }
59
- return new Promise(async (resolve, reject) => {
60
- resolve({
61
- type: messageTypes.methodCallReply,
62
- data: {
63
- replyId: callData.replyId,
64
- result: await Promise.resolve(callRes)
65
- }
66
- })
71
+ return new Promise((resolve, reject) => {
72
+ try {
73
+ Promise.resolve(callRes).then(result => {
74
+ resolve({
75
+ type: messageTypes.methodCallReply,
76
+ data: {
77
+ replyId: callData.replyId,
78
+ result
79
+ },
80
+ })
81
+ }).catch(reject)
82
+ } catch (error) {
83
+ reject(error)
84
+ }
67
85
  })
68
86
  }
69
87
  })
@@ -72,8 +90,8 @@ export default class WorkerReplace implements ReplaceInterface {
72
90
  this.#concurrency = this.#dispatcher.concurrency()
73
91
  }
74
92
 
75
- #call(method: string, params: any[]): any {
76
- const transfer: any = []
93
+ #call<T>(method: allMethodNames, params: unknown[]): Promise<T> {
94
+ const transfer: Transferable[] = []
77
95
 
78
96
  for (const param of params) {
79
97
  if (param instanceof Array) {
@@ -84,39 +102,51 @@ export default class WorkerReplace implements ReplaceInterface {
84
102
  }
85
103
  }
86
104
  }
87
-
88
105
  const replyId = generateId()
89
- this.#dispatcher.postMessage({
90
- type: messageTypes.methodCall,
91
- data: {
92
- replyId,
93
- method,
94
- params
95
- }
96
- }, transfer.length ? { transfer } : undefined)
106
+ this.#dispatcher.postMessage(
107
+ {
108
+ type: messageTypes.methodCall,
109
+ data: {
110
+ replyId,
111
+ method,
112
+ params,
113
+ },
114
+ },
115
+ transfer.length ? { transfer } : undefined,
116
+ )
97
117
  return new Promise((resolve, reject) => {
98
- this.#tasks.set(replyId, resolve)
118
+ this.#tasks.set(replyId, {
119
+ resolve: resolve as (value: unknown) => void,
120
+ reject
121
+ })
99
122
  })
100
123
  }
101
124
 
102
125
  //分片
103
- #chunk<T>(data: T[], chunkPackage?: (chunkData: T[]) => any): (T[] | ((chunkData: T[]) => any))[] {
104
- let chunks
126
+ #chunk<T, Y = undefined>(
127
+ data: T[],
128
+ chunkPackage?: ((chunkData: T[]) => Y),
129
+ ): T[][] | Y[] {
130
+ let chunks: T[][];
105
131
  if (this.#concurrency > 1 && data.length > chunkMinNum) {
106
- const chunkSize = Math.ceil(data.length / (Math.round(data.length / chunkMinNum)))
132
+ const chunkSize = Math.ceil(
133
+ data.length / Math.round(data.length / chunkMinNum),
134
+ )
107
135
  chunks = splitArrayIntoChunks<T>(data, chunkSize)
108
136
  } else {
109
137
  chunks = [data]
110
138
  }
111
139
  if (chunkPackage) {
112
140
  for (const i in chunks) {
113
- chunks[i] = chunkPackage(chunks[i])
141
+ (chunks as Y[])[i] = chunkPackage(chunks[i])
114
142
  }
115
143
  }
116
144
  return chunks
117
145
  }
118
146
 
119
- async #getTempFileData(files: Temp[] | undefined): Promise<transmitFileInfo[]> {
147
+ async #getTempFileData(
148
+ files: Temp[] | undefined,
149
+ ): Promise<transmitFileInfo[]> {
120
150
  if (!files) {
121
151
  files = this.#files
122
152
  }
@@ -128,27 +158,29 @@ export default class WorkerReplace implements ReplaceInterface {
128
158
  return res.filter(item => !!item)
129
159
  }
130
160
 
131
-
132
161
  clear(): void {
133
162
  this.#files.length = 0
134
163
  }
135
164
 
136
- async #chunkCall(method: string, paramChunks: any[]): Promise<Record<string, any>> {
137
- const tasks: Promise<Record<string, any>>[] = []
165
+ async #chunkCall<T>(
166
+ method: allMethodNames,
167
+ paramChunks: unknown[][],
168
+ ): Promise<Record<string, T>> {
169
+ const tasks: Promise<Record<string, T>>[] = []
138
170
  for (const chunk of paramChunks) {
139
171
  tasks.push(this.#call(method, chunk))
140
172
  }
141
173
  const tasksRes = await Promise.all(tasks)
142
- return tasksRes.reduce((accumulator, current) => {
143
- return { ...accumulator, ...current }
144
- }, {})
174
+ return Object.assign({}, ...tasksRes)
145
175
  }
146
176
 
147
177
  addTempFile(tempFile: Temp): void {
148
178
  this.#files.push(tempFile)
149
179
  }
150
180
 
151
- async extractVariables(files: Temp[] | undefined): Promise<Record<string, string[]>> {
181
+ async extractVariables(
182
+ files: Temp[] | undefined,
183
+ ): Promise<Record<string, string[]>> {
152
184
  const fileData = await this.#getTempFileData(files)
153
185
  const chunks = this.#chunk(fileData, chunkData => {
154
186
  return [chunkData]
@@ -156,7 +188,9 @@ export default class WorkerReplace implements ReplaceInterface {
156
188
  return this.#chunkCall('extractVariables', chunks)
157
189
  }
158
190
 
159
- async extractMedias(files: Temp[] | undefined): Promise<Record<string, media[]>> {
191
+ async extractMedias(
192
+ files: Temp[] | undefined,
193
+ ): Promise<Record<string, media[]>> {
160
194
  const fileData = await this.#getTempFileData(files)
161
195
  const chunks = this.#chunk(fileData, chunkData => {
162
196
  return [chunkData]
@@ -164,11 +198,14 @@ export default class WorkerReplace implements ReplaceInterface {
164
198
  return this.#chunkCall('extractMedias', chunks)
165
199
  }
166
200
 
167
- async sign(data: any): Promise<string> {
201
+ async sign(_: unknown): Promise<string> {
168
202
  return ''
169
203
  }
170
204
 
171
- async execute(params: paramsData, files: Temp[] | undefined): Promise<Record<string, Uint8Array>> {
205
+ async execute(
206
+ params: paramsData,
207
+ files: Temp[] | undefined,
208
+ ): Promise<Record<string, Uint8Array>> {
172
209
  const fileData = await this.#getTempFileData(files)
173
210
  const chunks = this.#chunk(fileData, chunkData => {
174
211
  return [params, chunkData]
@@ -176,28 +213,116 @@ export default class WorkerReplace implements ReplaceInterface {
176
213
  return this.#chunkCall('execute', chunks)
177
214
  }
178
215
 
179
- async executeMultipleParams(params: paramsData[], files: Temp[] | undefined): Promise<Record<string, Uint8Array>[]> {
216
+ async executeToZip(
217
+ params: paramsData,
218
+ files: Temp[] | undefined,
219
+ ): Promise<Uint8Array> {
220
+ const fileData = await this.#getTempFileData(files)
221
+ return new Promise((resolve, reject) => {
222
+ const tasks: Promise<void>[] = []
223
+ const u8s: Uint8Array[] = [];
224
+ const _zip = new Zip((err, dat, final) => {
225
+ if (dat.length) {
226
+ u8s.push(dat)
227
+ }
228
+ if (final) {
229
+ const blob = new Blob(u8s as BlobPart[])
230
+ blob.arrayBuffer().then(res => {
231
+ resolve(new Uint8Array(res))
232
+ })
233
+ }
234
+ });
235
+ this.#chunk(fileData, chunkData => {
236
+ tasks.push(new Promise((resolve, reject) => {
237
+ //直接使用execute方法,无需解压再合并数据,性能更好
238
+ this.#call<Record<string, Uint8Array>>('execute', [params, chunkData]).then(res => {
239
+ for (const name of Object.keys(res)) {
240
+ const helloTxt = new ZipDeflate(name, {
241
+ level: 9,
242
+ });
243
+ _zip.add(helloTxt)
244
+ helloTxt.push(res[name] as Uint8Array, true);
245
+ }
246
+ resolve()
247
+ }).catch(reject)
248
+ }))
249
+ })
250
+ Promise.all(tasks).then(() => {
251
+ _zip.end()
252
+ })
253
+ })
254
+ }
255
+
256
+ async executeMultipleParams(
257
+ params: paramsData[],
258
+ files: Temp[] | undefined,
259
+ ): Promise<Record<string, Uint8Array>[]> {
180
260
  const fileData = await this.#getTempFileData(files)
181
- const tasks: Promise<Record<string, any>[]>[] = []
261
+ const tasks: Promise<Record<string, Uint8Array>[]>[] = []
182
262
  this.#chunk(fileData, chunkData => {
183
- tasks.push(this.#call('executeMultipleParams', [params, chunkData] as any))
263
+ tasks.push(
264
+ this.#call('executeMultipleParams', [params, chunkData]),
265
+ )
184
266
  })
185
- const tasksRes = (await Promise.all(tasks)) as Record<string, Uint8Array>[][]
186
- const res = new Array(params.length)
267
+ const tasksRes = await Promise.all(tasks)
268
+ const res = Array.from({ length: params.length }, () => ({}))
187
269
  for (const item of tasksRes) {
188
270
  for (let index = 0; index < item.length; index++) {
189
- res[index] = {...item[index], ...res[index]}
271
+ Object.assign(res[index], item[index])
190
272
  }
191
273
  }
192
274
  return res
193
275
  }
194
276
 
195
- async fileEncrypt(file: Uint8Array): Promise<Uint8Array> {
196
- return await this.#call('fileEncrypt', [file])
277
+ async executeMultipleParamsToZip(
278
+ params: paramsData[],
279
+ files: Temp[] | undefined,
280
+ ): Promise<Uint8Array> {
281
+ const fileData = await this.#getTempFileData(files)
282
+ return new Promise(resolve => {
283
+ const tasks: Promise<void>[] = []
284
+ const u8s: Uint8Array[] = [];
285
+ const _zip = new Zip((err, dat, final) => {
286
+ if (dat.length) {
287
+ u8s.push(dat)
288
+ }
289
+ if (final) {
290
+ const blob = new Blob(u8s as BlobPart[])
291
+ blob.arrayBuffer().then(res => {
292
+ resolve(new Uint8Array(res))
293
+ })
294
+ }
295
+ });
296
+
297
+ this.#chunk(fileData, chunkData => {
298
+ tasks.push(new Promise((resolve, reject) => {
299
+ this.#call<Record<string, Uint8Array>[]>('executeMultipleParams', [params, chunkData]).then(res => {
300
+ for (let index = 0; index < res.length; index++) {
301
+ const item = res[index];
302
+ for (const name of Object.keys(item)) {
303
+ const helloTxt = new ZipDeflate(index + "/" + name, {
304
+ level: 9,
305
+ });
306
+ _zip.add(helloTxt)
307
+ helloTxt.push(item[name] as Uint8Array, true);
308
+ }
309
+ }
310
+ resolve()
311
+ }).catch(reject)
312
+ }))
313
+ })
314
+ Promise.all(tasks).then(() => {
315
+ _zip.end()
316
+ })
317
+ })
318
+ }
319
+
320
+ fileEncrypt(file: Uint8Array): Promise<Uint8Array> {
321
+ return this.#call('fileEncrypt', [file])
197
322
  }
198
323
 
199
324
  async filesEncrypt(files: Uint8Array[]): Promise<Uint8Array[]> {
200
- const chunks = this.#chunk<Uint8Array>(files) as (Uint8Array[])[]
325
+ const chunks = this.#chunk<Uint8Array>(files)
201
326
 
202
327
  const tasks: Promise<Uint8Array[]>[] = []
203
328
  for (const chunk of chunks) {
@@ -206,4 +331,4 @@ export default class WorkerReplace implements ReplaceInterface {
206
331
  const tasksRes = await Promise.all(tasks)
207
332
  return tasksRes.flat()
208
333
  }
209
- }
334
+ }
@@ -1,8 +1,8 @@
1
- import webworker from "../child/sign.ts?worker&inline"
2
- import base from ".."
1
+ import webworker from '../child/sign.ts?worker&inline'
2
+ import base from '../index'
3
3
 
4
4
  export default class extends base {
5
- constructor(concurrency?: number) {
6
- super(webworker, concurrency)
7
- }
5
+ constructor(concurrency?: number) {
6
+ super(webworker, concurrency)
7
+ }
8
8
  }
package/worker/type.ts CHANGED
@@ -1,24 +1,25 @@
1
1
  export enum messageTypes {
2
- replace,
3
- replaceProgress,
4
- sign,
5
- signReply,
6
- methodCall,
7
- methodCallReply,
2
+ replace,
3
+ replaceProgress,
4
+ sign,
5
+ signReply,
6
+ methodCall,
7
+ methodCallReply,
8
8
  }
9
9
 
10
10
  export type messageData = {
11
- type: messageTypes,
12
- data: any | methodCall | methodCallReply
11
+ type: messageTypes
12
+ data: unknown | methodCall | methodCallReply
13
13
  }
14
14
 
15
- export type methodCall = {
16
- replyId?: string,
17
- method: string,
18
- params: any[]
15
+ export type methodCall<T = string> = {
16
+ replyId?: string
17
+ method: T
18
+ params: unknown[]
19
19
  }
20
20
 
21
21
  export type methodCallReply = {
22
- replyId: string,
23
- result: any
24
- }
22
+ replyId: string
23
+ result: unknown
24
+ error?: string
25
+ }