capacitor-voice-recorder-wav-stereo 7.0.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/CapacitorVoiceRecorderWavStereo.podspec +17 -0
- package/README.md +213 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/CurrentRecordingStatus.java +7 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/CustomMediaRecorder.java +187 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/Messages.java +15 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/NotSupportedOsVersion.java +4 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/RecordData.java +51 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/ResponseGenerator.java +37 -0
- package/android/src/main/java/com/tchvu3/capacitorvoicerecorder/VoiceRecorder.java +217 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +174 -0
- package/dist/esm/VoiceRecorderImpl.d.ts +19 -0
- package/dist/esm/VoiceRecorderImpl.js +172 -0
- package/dist/esm/VoiceRecorderImpl.js.map +1 -0
- package/dist/esm/definitions.d.ts +24 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/predefined-web-responses.d.ts +12 -0
- package/dist/esm/predefined-web-responses.js +12 -0
- package/dist/esm/predefined-web-responses.js.map +1 -0
- package/dist/esm/web.d.ts +13 -0
- package/dist/esm/web.js +33 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +228 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +230 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/CurrentRecordingStatus.swift +9 -0
- package/ios/Plugin/CustomMediaRecorder.swift +82 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/Messages.swift +15 -0
- package/ios/Plugin/RecordData.swift +17 -0
- package/ios/Plugin/ResponseGenerator.swift +28 -0
- package/ios/Plugin/VoiceRecorder.swift +130 -0
- package/ios/Plugin/VoiceRecorderPlugin.h +10 -0
- package/ios/Plugin/VoiceRecorderPlugin.m +15 -0
- package/package.json +92 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import AVFoundation
|
|
3
|
+
|
|
4
|
+
class CustomMediaRecorder {
|
|
5
|
+
|
|
6
|
+
private var recordingSession: AVAudioSession!
|
|
7
|
+
private var audioRecorder: AVAudioRecorder!
|
|
8
|
+
private var audioFilePath: URL!
|
|
9
|
+
private var originalRecordingSessionCategory: AVAudioSession.Category!
|
|
10
|
+
private var status = CurrentRecordingStatus.NONE
|
|
11
|
+
|
|
12
|
+
private let settings = [
|
|
13
|
+
AVFormatIDKey: Int(kAudioFormatLinearPCM), // Changed to Linear PCM for WAV
|
|
14
|
+
AVSampleRateKey: 44100,
|
|
15
|
+
AVNumberOfChannelsKey: 2, // Stereo
|
|
16
|
+
AVLinearPCMBitDepthKey: 16, // Typical bit depth for WAV
|
|
17
|
+
AVLinearPCMIsBigEndianKey: false,
|
|
18
|
+
AVLinearPCMIsFloatKey: false,
|
|
19
|
+
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
|
|
20
|
+
] as [String : Any]
|
|
21
|
+
|
|
22
|
+
private func getDirectoryToSaveAudioFile() -> URL {
|
|
23
|
+
return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public func startRecording() -> Bool {
|
|
27
|
+
do {
|
|
28
|
+
recordingSession = AVAudioSession.sharedInstance()
|
|
29
|
+
originalRecordingSessionCategory = recordingSession.category
|
|
30
|
+
try recordingSession.setCategory(AVAudioSession.Category.playAndRecord, options: [.allowBluetoothA2DP, .defaultToSpeaker])
|
|
31
|
+
try recordingSession.setActive(true)
|
|
32
|
+
audioFilePath = getDirectoryToSaveAudioFile().appendingPathComponent("\(UUID().uuidString).wav")
|
|
33
|
+
audioRecorder = try AVAudioRecorder(url: audioFilePath, settings: settings)
|
|
34
|
+
audioRecorder.record()
|
|
35
|
+
status = CurrentRecordingStatus.RECORDING
|
|
36
|
+
return true
|
|
37
|
+
} catch {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public func stopRecording() {
|
|
43
|
+
do {
|
|
44
|
+
audioRecorder.stop()
|
|
45
|
+
try recordingSession.setActive(false)
|
|
46
|
+
try recordingSession.setCategory(originalRecordingSessionCategory)
|
|
47
|
+
originalRecordingSessionCategory = nil
|
|
48
|
+
audioRecorder = nil
|
|
49
|
+
recordingSession = nil
|
|
50
|
+
status = CurrentRecordingStatus.NONE
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public func getOutputFile() -> URL {
|
|
55
|
+
return audioFilePath
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public func pauseRecording() -> Bool {
|
|
59
|
+
if(status == CurrentRecordingStatus.RECORDING) {
|
|
60
|
+
audioRecorder.pause()
|
|
61
|
+
status = CurrentRecordingStatus.PAUSED
|
|
62
|
+
return true
|
|
63
|
+
} else {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public func resumeRecording() -> Bool {
|
|
69
|
+
if(status == CurrentRecordingStatus.PAUSED) {
|
|
70
|
+
audioRecorder.record()
|
|
71
|
+
status = CurrentRecordingStatus.RECORDING
|
|
72
|
+
return true
|
|
73
|
+
} else {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public func getCurrentStatus() -> CurrentRecordingStatus {
|
|
79
|
+
return status
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSPrincipalClass</key>
|
|
22
|
+
<string></string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
struct Messages {
|
|
5
|
+
|
|
6
|
+
static let MISSING_PERMISSION = "MISSING_PERMISSION"
|
|
7
|
+
static let CANNOT_RECORD_ON_THIS_PHONE = "CANNOT_RECORD_ON_THIS_PHONE"
|
|
8
|
+
static let FAILED_TO_RECORD = "FAILED_TO_RECORD"
|
|
9
|
+
static let RECORDING_HAS_NOT_STARTED = "RECORDING_HAS_NOT_STARTED"
|
|
10
|
+
static let FAILED_TO_FETCH_RECORDING = "FAILED_TO_FETCH_RECORDING"
|
|
11
|
+
static let EMPTY_RECORDING = "EMPTY_RECORDING"
|
|
12
|
+
static let ALREADY_RECORDING = "ALREADY_RECORDING"
|
|
13
|
+
static let MICROPHONE_BEING_USED = "MICROPHONE_BEING_USED"
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
struct RecordData {
|
|
4
|
+
|
|
5
|
+
public let recordDataBase64: String?
|
|
6
|
+
public let mimeType: String
|
|
7
|
+
public let msDuration: Int
|
|
8
|
+
|
|
9
|
+
public func toDictionary() -> Dictionary<String, Any> {
|
|
10
|
+
return [
|
|
11
|
+
"recordDataBase64": recordDataBase64 ?? "",
|
|
12
|
+
"msDuration": msDuration,
|
|
13
|
+
"mimeType": mimeType
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
struct ResponseGenerator {
|
|
4
|
+
|
|
5
|
+
private static let VALUE_RESPONSE_KEY = "value"
|
|
6
|
+
private static let STATUS_RESPONSE_KEY = "status"
|
|
7
|
+
|
|
8
|
+
public static func fromBoolean(_ value: Bool) -> Dictionary<String, Bool> {
|
|
9
|
+
return value ? successResponse() : failResponse()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public static func successResponse() -> Dictionary<String, Bool> {
|
|
13
|
+
return [VALUE_RESPONSE_KEY: true]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public static func failResponse() -> Dictionary<String, Bool> {
|
|
17
|
+
return [VALUE_RESPONSE_KEY: false]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static func dataResponse(_ data: Any) -> Dictionary<String, Any> {
|
|
21
|
+
return [VALUE_RESPONSE_KEY: data]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static func statusResponse(_ data: CurrentRecordingStatus) -> Dictionary<String, String> {
|
|
25
|
+
return [STATUS_RESPONSE_KEY: data.rawValue]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import AVFoundation
|
|
3
|
+
import Capacitor
|
|
4
|
+
|
|
5
|
+
@objc(VoiceRecorder)
|
|
6
|
+
public class VoiceRecorder: CAPPlugin {
|
|
7
|
+
|
|
8
|
+
private var customMediaRecorder: CustomMediaRecorder? = nil
|
|
9
|
+
|
|
10
|
+
@objc func canDeviceVoiceRecord(_ call: CAPPluginCall) {
|
|
11
|
+
call.resolve(ResponseGenerator.successResponse())
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@objc func requestAudioRecordingPermission(_ call: CAPPluginCall) {
|
|
15
|
+
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
16
|
+
if granted {
|
|
17
|
+
call.resolve(ResponseGenerator.successResponse())
|
|
18
|
+
} else {
|
|
19
|
+
call.resolve(ResponseGenerator.failResponse())
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@objc func hasAudioRecordingPermission(_ call: CAPPluginCall) {
|
|
25
|
+
call.resolve(ResponseGenerator.fromBoolean(doesUserGaveAudioRecordingPermission()))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@objc func startRecording(_ call: CAPPluginCall) {
|
|
30
|
+
if(!doesUserGaveAudioRecordingPermission()) {
|
|
31
|
+
call.reject(Messages.MISSING_PERMISSION)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if(customMediaRecorder != nil) {
|
|
36
|
+
call.reject(Messages.ALREADY_RECORDING)
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
customMediaRecorder = CustomMediaRecorder()
|
|
41
|
+
if(customMediaRecorder == nil) {
|
|
42
|
+
call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let successfullyStartedRecording = customMediaRecorder!.startRecording()
|
|
47
|
+
if successfullyStartedRecording == false {
|
|
48
|
+
call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
|
|
49
|
+
} else {
|
|
50
|
+
call.resolve(ResponseGenerator.successResponse())
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@objc func stopRecording(_ call: CAPPluginCall) {
|
|
55
|
+
if(customMediaRecorder == nil) {
|
|
56
|
+
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
customMediaRecorder?.stopRecording()
|
|
61
|
+
|
|
62
|
+
let audioFileUrl = customMediaRecorder?.getOutputFile()
|
|
63
|
+
if(audioFileUrl == nil) {
|
|
64
|
+
customMediaRecorder = nil
|
|
65
|
+
call.reject(Messages.FAILED_TO_FETCH_RECORDING)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
let recordData = RecordData(
|
|
69
|
+
recordDataBase64: readFileAsBase64(audioFileUrl),
|
|
70
|
+
mimeType: "audio/aac",
|
|
71
|
+
msDuration: getMsDurationOfAudioFile(audioFileUrl)
|
|
72
|
+
)
|
|
73
|
+
customMediaRecorder = nil
|
|
74
|
+
if recordData.recordDataBase64 == nil || recordData.msDuration < 0 {
|
|
75
|
+
call.reject(Messages.EMPTY_RECORDING)
|
|
76
|
+
} else {
|
|
77
|
+
call.resolve(ResponseGenerator.dataResponse(recordData.toDictionary()))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@objc func pauseRecording(_ call: CAPPluginCall) {
|
|
82
|
+
if(customMediaRecorder == nil) {
|
|
83
|
+
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
84
|
+
} else {
|
|
85
|
+
call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.pauseRecording() ?? false))
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@objc func resumeRecording(_ call: CAPPluginCall) {
|
|
90
|
+
if(customMediaRecorder == nil) {
|
|
91
|
+
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
92
|
+
} else {
|
|
93
|
+
call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.resumeRecording() ?? false))
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@objc func getCurrentStatus(_ call: CAPPluginCall) {
|
|
98
|
+
if(customMediaRecorder == nil) {
|
|
99
|
+
call.resolve(ResponseGenerator.statusResponse(CurrentRecordingStatus.NONE))
|
|
100
|
+
} else {
|
|
101
|
+
call.resolve(ResponseGenerator.statusResponse(customMediaRecorder?.getCurrentStatus() ?? CurrentRecordingStatus.NONE))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func doesUserGaveAudioRecordingPermission() -> Bool {
|
|
106
|
+
return AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func readFileAsBase64(_ filePath: URL?) -> String? {
|
|
110
|
+
if(filePath == nil) {
|
|
111
|
+
return nil
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
do {
|
|
115
|
+
let fileData = try Data.init(contentsOf: filePath!)
|
|
116
|
+
let fileStream = fileData.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
|
|
117
|
+
return fileStream
|
|
118
|
+
} catch {}
|
|
119
|
+
|
|
120
|
+
return nil
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
func getMsDurationOfAudioFile(_ filePath: URL?) -> Int {
|
|
124
|
+
if filePath == nil {
|
|
125
|
+
return -1
|
|
126
|
+
}
|
|
127
|
+
return Int(CMTimeGetSeconds(AVURLAsset(url: filePath!).duration) * 1000)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
//! Project version number for Plugin.
|
|
4
|
+
FOUNDATION_EXPORT double PluginVersionNumber;
|
|
5
|
+
|
|
6
|
+
//! Project version string for Plugin.
|
|
7
|
+
FOUNDATION_EXPORT const unsigned char PluginVersionString[];
|
|
8
|
+
|
|
9
|
+
// In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
|
|
10
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <Capacitor/Capacitor.h>
|
|
3
|
+
|
|
4
|
+
// Define the plugin using the CAP_PLUGIN Macro, and
|
|
5
|
+
// each method the plugin supports using the CAP_PLUGIN_METHOD macro.
|
|
6
|
+
CAP_PLUGIN(VoiceRecorder, "VoiceRecorder",
|
|
7
|
+
CAP_PLUGIN_METHOD(canDeviceVoiceRecord, CAPPluginReturnPromise);
|
|
8
|
+
CAP_PLUGIN_METHOD(requestAudioRecordingPermission, CAPPluginReturnPromise);
|
|
9
|
+
CAP_PLUGIN_METHOD(hasAudioRecordingPermission, CAPPluginReturnPromise);
|
|
10
|
+
CAP_PLUGIN_METHOD(startRecording, CAPPluginReturnPromise);
|
|
11
|
+
CAP_PLUGIN_METHOD(stopRecording, CAPPluginReturnPromise);
|
|
12
|
+
CAP_PLUGIN_METHOD(pauseRecording, CAPPluginReturnPromise);
|
|
13
|
+
CAP_PLUGIN_METHOD(resumeRecording, CAPPluginReturnPromise);
|
|
14
|
+
CAP_PLUGIN_METHOD(getCurrentStatus, CAPPluginReturnPromise);
|
|
15
|
+
)
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "capacitor-voice-recorder-wav-stereo",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Capacitor plugin for voice recording in wav format",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Plugin/",
|
|
14
|
+
"CapacitorVoiceRecorderWavStereo.podspec"
|
|
15
|
+
],
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Jun Murakami",
|
|
18
|
+
"email": "jun.murakami.dev@gmail.com"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo.git"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/Jun-Murakami/capacitor-voice-recorder-wav-stereo/issues"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"capacitor",
|
|
30
|
+
"plugin",
|
|
31
|
+
"native",
|
|
32
|
+
"voice",
|
|
33
|
+
"audio",
|
|
34
|
+
"record",
|
|
35
|
+
"recorder",
|
|
36
|
+
"ios",
|
|
37
|
+
"android"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
41
|
+
"verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin -destination generic/platform=iOS && cd ..",
|
|
42
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
43
|
+
"verify:web": "npm run build",
|
|
44
|
+
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
45
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
46
|
+
"eslint": "eslint . --ext ts",
|
|
47
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
48
|
+
"swiftlint": "node-swiftlint",
|
|
49
|
+
"docgen": "docgen --api VoiceRecorderPlugin --output-readme README.md --output-json dist/docs.json",
|
|
50
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
51
|
+
"clean": "rimraf ./dist",
|
|
52
|
+
"watch": "tsc --watch",
|
|
53
|
+
"prepublishOnly": "npm run build"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"get-blob-duration": "^1.2.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@capacitor/android": "^7.0.1",
|
|
60
|
+
"@capacitor/cli": "^7.0.1",
|
|
61
|
+
"@capacitor/core": "^7.0.1",
|
|
62
|
+
"@capacitor/docgen": "^0.3.0",
|
|
63
|
+
"@capacitor/ios": "^7.0.1",
|
|
64
|
+
"@ionic/eslint-config": "^0.4.0",
|
|
65
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
66
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^8.22.0",
|
|
68
|
+
"eslint": "^9.19.0",
|
|
69
|
+
"prettier": "~3.4.2",
|
|
70
|
+
"prettier-plugin-java": "~2.6.7",
|
|
71
|
+
"rimraf": "^6.0.1",
|
|
72
|
+
"rollup": "^4.32.1",
|
|
73
|
+
"swiftlint": "^2.0.0",
|
|
74
|
+
"typescript": "5.7.3"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@capacitor/core": "^6.0.0"
|
|
78
|
+
},
|
|
79
|
+
"prettier": "@ionic/prettier-config",
|
|
80
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
81
|
+
"eslintConfig": {
|
|
82
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
83
|
+
},
|
|
84
|
+
"capacitor": {
|
|
85
|
+
"ios": {
|
|
86
|
+
"src": "ios"
|
|
87
|
+
},
|
|
88
|
+
"android": {
|
|
89
|
+
"src": "android"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|