capacitor-camera-view 2.2.0-rc.1 → 2.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 +17 -202
- package/android/build.gradle +0 -1
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraView.kt +4 -287
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraViewPlugin.kt +8 -112
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/BarcodeDetectionResult.kt +1 -0
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/utils.kt +1 -21
- package/dist/docs.json +21 -201
- package/dist/esm/definitions.d.ts +23 -85
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +4 -20
- package/dist/esm/web.js +16 -151
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +16 -151
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +16 -151
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CameraViewPlugin/CameraError.swift +0 -28
- package/ios/Sources/CameraViewPlugin/CameraEvents.swift +27 -3
- package/ios/Sources/CameraViewPlugin/CameraSessionConfiguration.swift +8 -8
- package/ios/Sources/CameraViewPlugin/CameraViewManager+BarcodeScan.swift +34 -3
- package/ios/Sources/CameraViewPlugin/CameraViewManager+PhotoCapture.swift +14 -13
- package/ios/Sources/CameraViewPlugin/CameraViewManager.swift +150 -159
- package/ios/Sources/CameraViewPlugin/CameraViewPlugin.swift +15 -114
- package/ios/Sources/CameraViewPlugin/TempFileManager.swift +34 -68
- package/package.json +12 -12
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/VideoRecordingQuality.kt +0 -10
- package/ios/Sources/CameraViewPlugin/CameraViewManager+VideoRecording.swift +0 -302
|
@@ -29,8 +29,6 @@ public class CameraViewPlugin: CAPPlugin, CAPBridgedPlugin, CameraEventDelegate
|
|
|
29
29
|
CAPPluginMethod(name: "isRunning", returnType: CAPPluginReturnPromise),
|
|
30
30
|
CAPPluginMethod(name: "capture", returnType: CAPPluginReturnPromise),
|
|
31
31
|
CAPPluginMethod(name: "captureSample", returnType: CAPPluginReturnPromise),
|
|
32
|
-
CAPPluginMethod(name: "startRecording", returnType: CAPPluginReturnPromise),
|
|
33
|
-
CAPPluginMethod(name: "stopRecording", returnType: CAPPluginReturnPromise),
|
|
34
32
|
CAPPluginMethod(name: "getAvailableDevices", returnType: CAPPluginReturnPromise),
|
|
35
33
|
CAPPluginMethod(name: "flipCamera", returnType: CAPPluginReturnPromise),
|
|
36
34
|
CAPPluginMethod(name: "getZoom", returnType: CAPPluginReturnPromise),
|
|
@@ -205,63 +203,6 @@ public class CameraViewPlugin: CAPPlugin, CAPBridgedPlugin, CameraEventDelegate
|
|
|
205
203
|
}
|
|
206
204
|
}
|
|
207
205
|
|
|
208
|
-
@objc func startRecording(_ call: CAPPluginCall) {
|
|
209
|
-
let enableAudio = call.getBool("enableAudio") ?? false
|
|
210
|
-
let videoQuality = call.getString("videoQuality") ?? "highest"
|
|
211
|
-
|
|
212
|
-
guard let parsedVideoQuality = VideoRecordingQuality(rawValue: videoQuality) else {
|
|
213
|
-
call.reject("Invalid videoQuality. Use one of: lowest, sd, hd, fhd, uhd, highest")
|
|
214
|
-
return
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if enableAudio {
|
|
218
|
-
maybeRequestMicrophoneAccess { [weak self] granted in
|
|
219
|
-
guard granted else {
|
|
220
|
-
call.reject("Microphone access denied")
|
|
221
|
-
return
|
|
222
|
-
}
|
|
223
|
-
self?.doStartRecording(call: call, enableAudio: true, videoQuality: parsedVideoQuality)
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
doStartRecording(call: call, enableAudio: false, videoQuality: parsedVideoQuality)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private func doStartRecording(
|
|
231
|
-
call: CAPPluginCall,
|
|
232
|
-
enableAudio: Bool,
|
|
233
|
-
videoQuality: VideoRecordingQuality
|
|
234
|
-
) {
|
|
235
|
-
implementation.startRecording(enableAudio: enableAudio, videoQuality: videoQuality) { error in
|
|
236
|
-
if let error = error {
|
|
237
|
-
call.reject("Failed to start recording", nil, error)
|
|
238
|
-
return
|
|
239
|
-
}
|
|
240
|
-
call.resolve()
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
@objc func stopRecording(_ call: CAPPluginCall) {
|
|
245
|
-
implementation.stopRecording { [weak self] (outputURL, error) in
|
|
246
|
-
if let error = error {
|
|
247
|
-
call.reject("Failed to stop recording", nil, error)
|
|
248
|
-
return
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
guard let outputURL = outputURL else {
|
|
252
|
-
call.reject("No output file URL")
|
|
253
|
-
return
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
guard let webPath = self?.bridge?.portablePath(fromLocalURL: outputURL)?.absoluteString else {
|
|
257
|
-
call.reject("Failed to create web-accessible path")
|
|
258
|
-
return
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
call.resolve(["webPath": webPath])
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
206
|
@objc func getAvailableDevices(_ call: CAPPluginCall) {
|
|
266
207
|
let devices = implementation.getAvailableDevices()
|
|
267
208
|
|
|
@@ -390,53 +331,28 @@ public class CameraViewPlugin: CAPPlugin, CAPBridgedPlugin, CameraEventDelegate
|
|
|
390
331
|
}
|
|
391
332
|
|
|
392
333
|
@objc override public func checkPermissions(_ call: CAPPluginCall) {
|
|
334
|
+
let cameraState: String
|
|
335
|
+
|
|
336
|
+
switch AVCaptureDevice.authorizationStatus(for: .video) {
|
|
337
|
+
case .notDetermined:
|
|
338
|
+
cameraState = "prompt"
|
|
339
|
+
case .restricted, .denied:
|
|
340
|
+
cameraState = "denied"
|
|
341
|
+
case .authorized:
|
|
342
|
+
cameraState = "granted"
|
|
343
|
+
@unknown default:
|
|
344
|
+
cameraState = "prompt"
|
|
345
|
+
}
|
|
346
|
+
|
|
393
347
|
call.resolve([
|
|
394
|
-
"camera":
|
|
395
|
-
"microphone": authorizationStateString(for: .audio)
|
|
348
|
+
"camera": cameraState
|
|
396
349
|
])
|
|
397
350
|
}
|
|
398
351
|
|
|
399
352
|
@objc override public func requestPermissions(_ call: CAPPluginCall) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
let requestCamera = permissionsList.contains("camera")
|
|
403
|
-
let requestMicrophone = permissionsList.contains("microphone")
|
|
404
|
-
|
|
405
|
-
let completionHandler: () -> Void = { [weak self] in
|
|
353
|
+
AVCaptureDevice.requestAccess(for: .video) { [weak self] _ in
|
|
406
354
|
self?.checkPermissions(call)
|
|
407
355
|
}
|
|
408
|
-
|
|
409
|
-
if requestCamera {
|
|
410
|
-
AVCaptureDevice.requestAccess(for: .video) { _ in
|
|
411
|
-
if requestMicrophone {
|
|
412
|
-
AVCaptureDevice.requestAccess(for: .audio) { _ in
|
|
413
|
-
completionHandler()
|
|
414
|
-
}
|
|
415
|
-
} else {
|
|
416
|
-
completionHandler()
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
} else if requestMicrophone {
|
|
420
|
-
AVCaptureDevice.requestAccess(for: .audio) { _ in
|
|
421
|
-
completionHandler()
|
|
422
|
-
}
|
|
423
|
-
} else {
|
|
424
|
-
completionHandler()
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/// Maps AVFoundation authorization status to the Capacitor permission state string.
|
|
429
|
-
private func authorizationStateString(for mediaType: AVMediaType) -> String {
|
|
430
|
-
switch AVCaptureDevice.authorizationStatus(for: mediaType) {
|
|
431
|
-
case .notDetermined:
|
|
432
|
-
return "prompt"
|
|
433
|
-
case .restricted, .denied:
|
|
434
|
-
return "denied"
|
|
435
|
-
case .authorized:
|
|
436
|
-
return "granted"
|
|
437
|
-
@unknown default:
|
|
438
|
-
return "prompt"
|
|
439
|
-
}
|
|
440
356
|
}
|
|
441
357
|
|
|
442
358
|
private func maybeRequestCameraAccess(completion: @escaping (Bool) -> Void) {
|
|
@@ -453,19 +369,4 @@ public class CameraViewPlugin: CAPPlugin, CAPBridgedPlugin, CameraEventDelegate
|
|
|
453
369
|
completion(false)
|
|
454
370
|
}
|
|
455
371
|
}
|
|
456
|
-
|
|
457
|
-
private func maybeRequestMicrophoneAccess(completion: @escaping (Bool) -> Void) {
|
|
458
|
-
let status = AVCaptureDevice.authorizationStatus(for: .audio)
|
|
459
|
-
if status == .authorized {
|
|
460
|
-
completion(true)
|
|
461
|
-
} else if status == .notDetermined {
|
|
462
|
-
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
|
463
|
-
DispatchQueue.main.async {
|
|
464
|
-
completion(granted)
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
} else {
|
|
468
|
-
completion(false)
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
372
|
}
|
|
@@ -11,29 +11,29 @@ import UIKit
|
|
|
11
11
|
public final class TempFileManager: @unchecked Sendable {
|
|
12
12
|
/// Shared singleton instance
|
|
13
13
|
public static let shared = TempFileManager()
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
/// Serial queue for thread-safe file tracking
|
|
16
16
|
private let queue = DispatchQueue(label: "com.michaelwolz.capacitorcameraview.tempFileManager")
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
/// Set of tracked temporary file URLs
|
|
19
19
|
private var trackedFiles = Set<URL>()
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
/// Directory prefix used to identify camera capture temp files
|
|
22
22
|
private let tempFilePrefix = "camera_capture_"
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
/// Stale file threshold in seconds (30 minutes)
|
|
25
25
|
private let staleThresholdSeconds: TimeInterval = 1800
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
private init() {
|
|
28
28
|
setupAppLifecycleObservers()
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
deinit {
|
|
32
32
|
NotificationCenter.default.removeObserver(self)
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
// MARK: - Public API
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
/// Creates a temporary file URL for storing captured images and tracks it for cleanup.
|
|
38
38
|
///
|
|
39
39
|
/// - Returns: A URL pointing to the temporary file location
|
|
@@ -43,84 +43,50 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
43
43
|
let fileName = "\(tempFilePrefix)\(timestamp).jpg"
|
|
44
44
|
let tempDir = FileManager.default.temporaryDirectory
|
|
45
45
|
let fileURL = tempDir.appendingPathComponent(fileName)
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
queue.sync {
|
|
48
|
-
|
|
48
|
+
trackedFiles.insert(fileURL)
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
return fileURL
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
/// Creates a temporary file URL for storing recorded videos and tracks it for cleanup.
|
|
55
|
-
///
|
|
56
|
-
/// - Returns: A URL pointing to the temporary video file location
|
|
57
|
-
public func createTempVideoFile() -> URL {
|
|
58
|
-
let timestamp = Int(Date().timeIntervalSince1970 * 1000)
|
|
59
|
-
let fileName = "\(tempFilePrefix)\(timestamp).mp4"
|
|
60
|
-
let tempDir = FileManager.default.temporaryDirectory
|
|
61
|
-
let fileURL = tempDir.appendingPathComponent(fileName)
|
|
62
|
-
|
|
63
|
-
queue.sync {
|
|
64
|
-
_ = trackedFiles.insert(fileURL)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return fileURL
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/// Registers an externally created file for tracking.
|
|
71
|
-
///
|
|
72
|
-
/// - Parameter url: The URL of the file to track
|
|
73
|
-
public func trackFile(_ url: URL) {
|
|
74
|
-
queue.sync {
|
|
75
|
-
_ = trackedFiles.insert(url)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/// Removes a file from tracking without deleting it.
|
|
80
|
-
///
|
|
81
|
-
/// - Parameter url: The URL of the file to untrack
|
|
82
|
-
public func untrackFile(_ url: URL) {
|
|
83
|
-
queue.sync {
|
|
84
|
-
_ = trackedFiles.remove(url)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
53
|
+
|
|
88
54
|
/// Cleans up all tracked temporary files.
|
|
89
55
|
/// Call this when the camera session stops.
|
|
90
56
|
public func cleanupSessionFiles() {
|
|
91
57
|
queue.async { [weak self] in
|
|
92
58
|
guard let self = self else { return }
|
|
93
|
-
|
|
59
|
+
|
|
94
60
|
let filesToDelete = self.trackedFiles
|
|
95
61
|
self.trackedFiles.removeAll()
|
|
96
|
-
|
|
62
|
+
|
|
97
63
|
for fileURL in filesToDelete {
|
|
98
64
|
self.deleteFile(at: fileURL)
|
|
99
65
|
}
|
|
100
66
|
}
|
|
101
67
|
}
|
|
102
|
-
|
|
68
|
+
|
|
103
69
|
/// Cleans up stale temporary files that are older than the threshold.
|
|
104
70
|
/// This helps recover from cases where cleanup was missed.
|
|
105
71
|
public func cleanupStaleFiles() {
|
|
106
72
|
queue.async { [weak self] in
|
|
107
73
|
guard let self = self else { return }
|
|
108
|
-
|
|
74
|
+
|
|
109
75
|
let fileManager = FileManager.default
|
|
110
76
|
let tempDir = fileManager.temporaryDirectory
|
|
111
|
-
|
|
77
|
+
|
|
112
78
|
guard let contents = try? fileManager.contentsOfDirectory(
|
|
113
79
|
at: tempDir,
|
|
114
80
|
includingPropertiesForKeys: [.creationDateKey],
|
|
115
81
|
options: .skipsHiddenFiles
|
|
116
82
|
) else { return }
|
|
117
|
-
|
|
83
|
+
|
|
118
84
|
let staleDate = Date().addingTimeInterval(-self.staleThresholdSeconds)
|
|
119
|
-
|
|
85
|
+
|
|
120
86
|
for fileURL in contents {
|
|
121
87
|
// Only process our camera capture files
|
|
122
88
|
guard fileURL.lastPathComponent.hasPrefix(self.tempFilePrefix) else { continue }
|
|
123
|
-
|
|
89
|
+
|
|
124
90
|
// Check file age
|
|
125
91
|
if let attributes = try? fileManager.attributesOfItem(atPath: fileURL.path),
|
|
126
92
|
let creationDate = attributes[.creationDate] as? Date,
|
|
@@ -131,34 +97,34 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
131
97
|
}
|
|
132
98
|
}
|
|
133
99
|
}
|
|
134
|
-
|
|
100
|
+
|
|
135
101
|
/// Cleans up all camera capture temporary files in the temp directory.
|
|
136
102
|
/// Use this for aggressive cleanup on app termination.
|
|
137
103
|
public func cleanupAllCaptureFiles() {
|
|
138
104
|
queue.async { [weak self] in
|
|
139
105
|
guard let self = self else { return }
|
|
140
|
-
|
|
106
|
+
|
|
141
107
|
let fileManager = FileManager.default
|
|
142
108
|
let tempDir = fileManager.temporaryDirectory
|
|
143
|
-
|
|
109
|
+
|
|
144
110
|
guard let contents = try? fileManager.contentsOfDirectory(
|
|
145
111
|
at: tempDir,
|
|
146
112
|
includingPropertiesForKeys: nil,
|
|
147
113
|
options: .skipsHiddenFiles
|
|
148
114
|
) else { return }
|
|
149
|
-
|
|
115
|
+
|
|
150
116
|
for fileURL in contents {
|
|
151
117
|
if fileURL.lastPathComponent.hasPrefix(self.tempFilePrefix) {
|
|
152
118
|
self.deleteFile(at: fileURL)
|
|
153
119
|
}
|
|
154
120
|
}
|
|
155
|
-
|
|
121
|
+
|
|
156
122
|
self.trackedFiles.removeAll()
|
|
157
123
|
}
|
|
158
124
|
}
|
|
159
|
-
|
|
125
|
+
|
|
160
126
|
// MARK: - Private Methods
|
|
161
|
-
|
|
127
|
+
|
|
162
128
|
private func deleteFile(at url: URL) {
|
|
163
129
|
do {
|
|
164
130
|
try FileManager.default.removeItem(at: url)
|
|
@@ -166,7 +132,7 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
166
132
|
// Silently ignore - file may already be deleted or inaccessible
|
|
167
133
|
}
|
|
168
134
|
}
|
|
169
|
-
|
|
135
|
+
|
|
170
136
|
private func setupAppLifecycleObservers() {
|
|
171
137
|
NotificationCenter.default.addObserver(
|
|
172
138
|
self,
|
|
@@ -174,7 +140,7 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
174
140
|
name: UIApplication.didBecomeActiveNotification,
|
|
175
141
|
object: nil
|
|
176
142
|
)
|
|
177
|
-
|
|
143
|
+
|
|
178
144
|
NotificationCenter.default.addObserver(
|
|
179
145
|
self,
|
|
180
146
|
selector: #selector(handleAppWillTerminate),
|
|
@@ -182,21 +148,21 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
182
148
|
object: nil
|
|
183
149
|
)
|
|
184
150
|
}
|
|
185
|
-
|
|
151
|
+
|
|
186
152
|
@objc private func handleAppDidBecomeActive() {
|
|
187
153
|
// Clean up any stale files when app becomes active
|
|
188
154
|
cleanupStaleFiles()
|
|
189
155
|
}
|
|
190
|
-
|
|
156
|
+
|
|
191
157
|
@objc private func handleAppWillTerminate() {
|
|
192
158
|
// Clean up all capture files on termination
|
|
193
159
|
// Note: This is synchronous to ensure cleanup happens before termination
|
|
194
160
|
queue.sync { [weak self] in
|
|
195
161
|
guard let self = self else { return }
|
|
196
|
-
|
|
162
|
+
|
|
197
163
|
let fileManager = FileManager.default
|
|
198
164
|
let tempDir = fileManager.temporaryDirectory
|
|
199
|
-
|
|
165
|
+
|
|
200
166
|
if let contents = try? fileManager.contentsOfDirectory(
|
|
201
167
|
at: tempDir,
|
|
202
168
|
includingPropertiesForKeys: nil,
|
|
@@ -208,7 +174,7 @@ public final class TempFileManager: @unchecked Sendable {
|
|
|
208
174
|
}
|
|
209
175
|
}
|
|
210
176
|
}
|
|
211
|
-
|
|
177
|
+
|
|
212
178
|
self.trackedFiles.removeAll()
|
|
213
179
|
}
|
|
214
180
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-camera-view",
|
|
3
|
-
"version": "2.2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A Capacitor plugin for embedding a live camera feed directly into your app.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -48,32 +48,32 @@
|
|
|
48
48
|
"prepublishOnly": "npm run build"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@capacitor/android": "^8.1
|
|
52
|
-
"@capacitor/core": "^8.1
|
|
51
|
+
"@capacitor/android": "^8.3.1",
|
|
52
|
+
"@capacitor/core": "^8.3.1",
|
|
53
53
|
"@capacitor/docgen": "^0.3.1",
|
|
54
|
-
"@capacitor/ios": "^8.1
|
|
55
|
-
"@commitlint/config-conventional": "^20.
|
|
54
|
+
"@capacitor/ios": "^8.3.1",
|
|
55
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
56
56
|
"@ionic/prettier-config": "^4.0.0",
|
|
57
57
|
"@ionic/swiftlint-config": "^2.0.0",
|
|
58
58
|
"@semantic-release/changelog": "^6.0.3",
|
|
59
59
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
60
60
|
"@semantic-release/git": "^10.0.1",
|
|
61
61
|
"@semantic-release/github": "^12.0.6",
|
|
62
|
-
"@semantic-release/npm": "^13.1.
|
|
62
|
+
"@semantic-release/npm": "^13.1.5",
|
|
63
63
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
65
|
-
"@typescript-eslint/parser": "^8.
|
|
66
|
-
"commitlint": "^20.
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "^8.59.1",
|
|
65
|
+
"@typescript-eslint/parser": "^8.59.1",
|
|
66
|
+
"commitlint": "^20.5.2",
|
|
67
67
|
"eslint": "^9.39.2",
|
|
68
68
|
"eslint-config-prettier": "^10.1.8",
|
|
69
69
|
"eslint-plugin-prettier": "^5.5.5",
|
|
70
70
|
"husky": "^9.1.7",
|
|
71
|
-
"prettier": "^3.8.
|
|
71
|
+
"prettier": "^3.8.3",
|
|
72
72
|
"prettier-plugin-java": "^2.8.1",
|
|
73
73
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
74
|
-
"prettier-plugin-packagejson": "^3.0.
|
|
74
|
+
"prettier-plugin-packagejson": "^3.0.2",
|
|
75
75
|
"rimraf": "^6.1.3",
|
|
76
|
-
"rollup": "^4.
|
|
76
|
+
"rollup": "^4.60.2",
|
|
77
77
|
"semantic-release": "^25.0.3",
|
|
78
78
|
"swiftlint": "^2.0.0",
|
|
79
79
|
"typescript": "^5.9.3"
|