@capgo/capacitor-persistent-uuid 8.1.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/CapgoCapacitorPersistentUuid.podspec +17 -0
- package/LICENSE +373 -0
- package/Package.swift +28 -0
- package/README.md +150 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/app/capgo/persistent_uuid/PersistentUuid.java +113 -0
- package/android/src/main/java/app/capgo/persistent_uuid/PersistentUuidPlugin.java +54 -0
- package/android/src/main/java/app/capgo/persistent_uuid/auth/Authenticator.java +60 -0
- package/android/src/main/java/app/capgo/persistent_uuid/auth/AuthenticatorService.java +21 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/main/res/xml/authenticator.xml +4 -0
- package/dist/docs.json +128 -0
- package/dist/esm/definitions.d.ts +56 -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/web.d.ts +7 -0
- package/dist/esm/web.js +75 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +89 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +92 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/PersistentUuidPlugin/PersistentUuid.swift +127 -0
- package/ios/Sources/PersistentUuidPlugin/PersistentUuidPlugin.swift +37 -0
- package/ios/Tests/PersistentUuidPluginTests/PersistentUuidTests.swift +20 -0
- package/package.json +88 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst PersistentUuid = registerPlugin('PersistentUuid', {\n web: () => import('./web').then((m) => new m.PersistentUuidWeb()),\n});\nexport * from './definitions';\nexport { PersistentUuid };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst STORAGE_PREFIX = 'capgo:persistent-uuid:';\nconst DEFAULT_SCOPE = 'web';\nconst memoryStore = new Map();\nconst normalizeScope = (options) => {\n var _a;\n const scope = (_a = options === null || options === void 0 ? void 0 : options.scope) === null || _a === void 0 ? void 0 : _a.trim();\n return scope && scope.length > 0 ? scope : DEFAULT_SCOPE;\n};\nconst createUuid = () => {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {\n const random = Math.floor(Math.random() * 16);\n const value = char === 'x' ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n};\nconst readValue = (key) => {\n var _a, _b, _c, _d;\n try {\n return (_c = (_b = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(key)) !== null && _b !== void 0 ? _b : memoryStore.get(key)) !== null && _c !== void 0 ? _c : null;\n }\n catch (_e) {\n return (_d = memoryStore.get(key)) !== null && _d !== void 0 ? _d : null;\n }\n};\nconst writeValue = (key, value) => {\n var _a;\n memoryStore.set(key, value);\n try {\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(key, value);\n }\n catch (_b) {\n // In-memory fallback already updated.\n }\n};\nexport class PersistentUuidWeb extends WebPlugin {\n async getId(options) {\n const scope = normalizeScope(options);\n const key = STORAGE_PREFIX + scope;\n const existing = readValue(key);\n if (existing) {\n return {\n id: existing,\n scope,\n created: false,\n };\n }\n const id = createUuid();\n writeValue(key, id);\n return {\n id,\n scope,\n created: true,\n };\n }\n async resetId(options) {\n const scope = normalizeScope(options);\n const id = createUuid();\n writeValue(STORAGE_PREFIX + scope, id);\n return {\n id,\n scope,\n created: true,\n };\n }\n async getPluginVersion() {\n return {\n version: 'web',\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var capacitorPersistentUuid = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const PersistentUuid = core.registerPlugin('PersistentUuid', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.PersistentUuidWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const STORAGE_PREFIX = 'capgo:persistent-uuid:';
|
|
9
|
+
const DEFAULT_SCOPE = 'web';
|
|
10
|
+
const memoryStore = new Map();
|
|
11
|
+
const normalizeScope = (options) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const scope = (_a = options === null || options === void 0 ? void 0 : options.scope) === null || _a === void 0 ? void 0 : _a.trim();
|
|
14
|
+
return scope && scope.length > 0 ? scope : DEFAULT_SCOPE;
|
|
15
|
+
};
|
|
16
|
+
const createUuid = () => {
|
|
17
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
18
|
+
return crypto.randomUUID();
|
|
19
|
+
}
|
|
20
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
21
|
+
const random = Math.floor(Math.random() * 16);
|
|
22
|
+
const value = char === 'x' ? random : (random & 0x3) | 0x8;
|
|
23
|
+
return value.toString(16);
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const readValue = (key) => {
|
|
27
|
+
var _a, _b, _c, _d;
|
|
28
|
+
try {
|
|
29
|
+
return (_c = (_b = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(key)) !== null && _b !== void 0 ? _b : memoryStore.get(key)) !== null && _c !== void 0 ? _c : null;
|
|
30
|
+
}
|
|
31
|
+
catch (_e) {
|
|
32
|
+
return (_d = memoryStore.get(key)) !== null && _d !== void 0 ? _d : null;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const writeValue = (key, value) => {
|
|
36
|
+
var _a;
|
|
37
|
+
memoryStore.set(key, value);
|
|
38
|
+
try {
|
|
39
|
+
(_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(key, value);
|
|
40
|
+
}
|
|
41
|
+
catch (_b) {
|
|
42
|
+
// In-memory fallback already updated.
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
class PersistentUuidWeb extends core.WebPlugin {
|
|
46
|
+
async getId(options) {
|
|
47
|
+
const scope = normalizeScope(options);
|
|
48
|
+
const key = STORAGE_PREFIX + scope;
|
|
49
|
+
const existing = readValue(key);
|
|
50
|
+
if (existing) {
|
|
51
|
+
return {
|
|
52
|
+
id: existing,
|
|
53
|
+
scope,
|
|
54
|
+
created: false,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const id = createUuid();
|
|
58
|
+
writeValue(key, id);
|
|
59
|
+
return {
|
|
60
|
+
id,
|
|
61
|
+
scope,
|
|
62
|
+
created: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async resetId(options) {
|
|
66
|
+
const scope = normalizeScope(options);
|
|
67
|
+
const id = createUuid();
|
|
68
|
+
writeValue(STORAGE_PREFIX + scope, id);
|
|
69
|
+
return {
|
|
70
|
+
id,
|
|
71
|
+
scope,
|
|
72
|
+
created: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async getPluginVersion() {
|
|
76
|
+
return {
|
|
77
|
+
version: 'web',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
83
|
+
__proto__: null,
|
|
84
|
+
PersistentUuidWeb: PersistentUuidWeb
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
exports.PersistentUuid = PersistentUuid;
|
|
88
|
+
|
|
89
|
+
return exports;
|
|
90
|
+
|
|
91
|
+
})({}, capacitorExports);
|
|
92
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst PersistentUuid = registerPlugin('PersistentUuid', {\n web: () => import('./web').then((m) => new m.PersistentUuidWeb()),\n});\nexport * from './definitions';\nexport { PersistentUuid };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst STORAGE_PREFIX = 'capgo:persistent-uuid:';\nconst DEFAULT_SCOPE = 'web';\nconst memoryStore = new Map();\nconst normalizeScope = (options) => {\n var _a;\n const scope = (_a = options === null || options === void 0 ? void 0 : options.scope) === null || _a === void 0 ? void 0 : _a.trim();\n return scope && scope.length > 0 ? scope : DEFAULT_SCOPE;\n};\nconst createUuid = () => {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {\n const random = Math.floor(Math.random() * 16);\n const value = char === 'x' ? random : (random & 0x3) | 0x8;\n return value.toString(16);\n });\n};\nconst readValue = (key) => {\n var _a, _b, _c, _d;\n try {\n return (_c = (_b = (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(key)) !== null && _b !== void 0 ? _b : memoryStore.get(key)) !== null && _c !== void 0 ? _c : null;\n }\n catch (_e) {\n return (_d = memoryStore.get(key)) !== null && _d !== void 0 ? _d : null;\n }\n};\nconst writeValue = (key, value) => {\n var _a;\n memoryStore.set(key, value);\n try {\n (_a = globalThis.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(key, value);\n }\n catch (_b) {\n // In-memory fallback already updated.\n }\n};\nexport class PersistentUuidWeb extends WebPlugin {\n async getId(options) {\n const scope = normalizeScope(options);\n const key = STORAGE_PREFIX + scope;\n const existing = readValue(key);\n if (existing) {\n return {\n id: existing,\n scope,\n created: false,\n };\n }\n const id = createUuid();\n writeValue(key, id);\n return {\n id,\n scope,\n created: true,\n };\n }\n async resetId(options) {\n const scope = normalizeScope(options);\n const id = createUuid();\n writeValue(STORAGE_PREFIX + scope, id);\n return {\n id,\n scope,\n created: true,\n };\n }\n async getPluginVersion() {\n return {\n version: 'web',\n };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Security
|
|
3
|
+
|
|
4
|
+
@objc public class PersistentUuid: NSObject {
|
|
5
|
+
private let service = "app.capgo.persistent_uuid"
|
|
6
|
+
private let accountPrefix = "PersistentUuid:"
|
|
7
|
+
private let fallbackScope = "default"
|
|
8
|
+
|
|
9
|
+
@objc public func getId(_ scope: String?) throws -> [String: Any] {
|
|
10
|
+
let normalizedScope = normalizeScope(scope)
|
|
11
|
+
if let existing = try readUuid(scope: normalizedScope) {
|
|
12
|
+
return [
|
|
13
|
+
"id": existing,
|
|
14
|
+
"scope": normalizedScope,
|
|
15
|
+
"created": false
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let id = createUuid()
|
|
20
|
+
try saveUuid(id, scope: normalizedScope)
|
|
21
|
+
return [
|
|
22
|
+
"id": id,
|
|
23
|
+
"scope": normalizedScope,
|
|
24
|
+
"created": true
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@objc public func resetId(_ scope: String?) throws -> [String: Any] {
|
|
29
|
+
let normalizedScope = normalizeScope(scope)
|
|
30
|
+
let id = createUuid()
|
|
31
|
+
try saveUuid(id, scope: normalizedScope)
|
|
32
|
+
return [
|
|
33
|
+
"id": id,
|
|
34
|
+
"scope": normalizedScope,
|
|
35
|
+
"created": true
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@objc public func getPluginVersion() -> String {
|
|
40
|
+
return "8.0.0"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private func normalizeScope(_ scope: String?) -> String {
|
|
44
|
+
if let trimmed = scope?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty {
|
|
45
|
+
return trimmed
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Bundle.main.bundleIdentifier ?? fallbackScope
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private func accountName(scope: String) -> String {
|
|
52
|
+
return "\(accountPrefix)\(scope)"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private func createUuid() -> String {
|
|
56
|
+
return UUID().uuidString.lowercased()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private func baseQuery(scope: String) -> [String: Any] {
|
|
60
|
+
return [
|
|
61
|
+
kSecClass as String: kSecClassGenericPassword,
|
|
62
|
+
kSecAttrService as String: service,
|
|
63
|
+
kSecAttrAccount as String: accountName(scope: scope)
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private func readUuid(scope: String) throws -> String? {
|
|
68
|
+
var query = baseQuery(scope: scope)
|
|
69
|
+
query[kSecReturnData as String] = true
|
|
70
|
+
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
|
71
|
+
|
|
72
|
+
var item: CFTypeRef?
|
|
73
|
+
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
|
74
|
+
if status == errSecItemNotFound {
|
|
75
|
+
return nil
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
guard status == errSecSuccess else {
|
|
79
|
+
throw NSError(
|
|
80
|
+
domain: NSOSStatusErrorDomain,
|
|
81
|
+
code: Int(status),
|
|
82
|
+
userInfo: [NSLocalizedDescriptionKey: "Keychain read failed: \(status)"]
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
guard let data = item as? Data else {
|
|
87
|
+
return nil
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return String(data: data, encoding: .utf8)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private func saveUuid(_ id: String, scope: String) throws {
|
|
94
|
+
let data = Data(id.utf8)
|
|
95
|
+
let query = baseQuery(scope: scope)
|
|
96
|
+
let update: [String: Any] = [
|
|
97
|
+
kSecValueData as String: data,
|
|
98
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
let updateStatus = SecItemUpdate(query as CFDictionary, update as CFDictionary)
|
|
102
|
+
if updateStatus == errSecSuccess {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
guard updateStatus == errSecItemNotFound else {
|
|
107
|
+
throw NSError(
|
|
108
|
+
domain: NSOSStatusErrorDomain,
|
|
109
|
+
code: Int(updateStatus),
|
|
110
|
+
userInfo: [NSLocalizedDescriptionKey: "Keychain update failed: \(updateStatus)"]
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
var attributes = query
|
|
115
|
+
attributes[kSecValueData as String] = data
|
|
116
|
+
attributes[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
|
|
117
|
+
|
|
118
|
+
let addStatus = SecItemAdd(attributes as CFDictionary, nil)
|
|
119
|
+
guard addStatus == errSecSuccess else {
|
|
120
|
+
throw NSError(
|
|
121
|
+
domain: NSOSStatusErrorDomain,
|
|
122
|
+
code: Int(addStatus),
|
|
123
|
+
userInfo: [NSLocalizedDescriptionKey: "Keychain save failed: \(addStatus)"]
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc(PersistentUuidPlugin)
|
|
5
|
+
public class PersistentUuidPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
6
|
+
public let identifier = "PersistentUuidPlugin"
|
|
7
|
+
public let jsName = "PersistentUuid"
|
|
8
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
9
|
+
CAPPluginMethod(name: "getId", returnType: CAPPluginReturnPromise),
|
|
10
|
+
CAPPluginMethod(name: "resetId", returnType: CAPPluginReturnPromise),
|
|
11
|
+
CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise)
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
private let implementation = PersistentUuid()
|
|
15
|
+
|
|
16
|
+
@objc func getId(_ call: CAPPluginCall) {
|
|
17
|
+
do {
|
|
18
|
+
call.resolve(try implementation.getId(call.getString("scope")))
|
|
19
|
+
} catch {
|
|
20
|
+
call.reject("Failed to get persistent UUID: \(error.localizedDescription)")
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@objc func resetId(_ call: CAPPluginCall) {
|
|
25
|
+
do {
|
|
26
|
+
call.resolve(try implementation.resetId(call.getString("scope")))
|
|
27
|
+
} catch {
|
|
28
|
+
call.reject("Failed to reset persistent UUID: \(error.localizedDescription)")
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc func getPluginVersion(_ call: CAPPluginCall) {
|
|
33
|
+
call.resolve([
|
|
34
|
+
"version": implementation.getPluginVersion()
|
|
35
|
+
])
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
@testable import PersistentUuidPlugin
|
|
3
|
+
|
|
4
|
+
class PersistentUuidTests: XCTestCase {
|
|
5
|
+
func testGetPluginVersion() {
|
|
6
|
+
let implementation = PersistentUuid()
|
|
7
|
+
let result = implementation.getPluginVersion()
|
|
8
|
+
|
|
9
|
+
XCTAssertEqual("8.0.0", result)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
func testResetIdCreatesUuid() throws {
|
|
13
|
+
let implementation = PersistentUuid()
|
|
14
|
+
let result = try implementation.resetId("test")
|
|
15
|
+
|
|
16
|
+
XCTAssertNotNil(result["id"] as? String)
|
|
17
|
+
XCTAssertEqual("test", result["scope"] as? String)
|
|
18
|
+
XCTAssertEqual(true, result["created"] as? Bool)
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/capacitor-persistent-uuid",
|
|
3
|
+
"version": "8.1.0",
|
|
4
|
+
"description": "Capacitor plugin for a persistent app UUID that survives reinstalls and updates.",
|
|
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/Sources",
|
|
14
|
+
"ios/Tests",
|
|
15
|
+
"Package.swift",
|
|
16
|
+
"CapgoCapacitorPersistentUuid.podspec"
|
|
17
|
+
],
|
|
18
|
+
"author": "Martin Donadieu <martin@capgo.app>",
|
|
19
|
+
"license": "MPL-2.0",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Cap-go/capacitor-persistent-uuid.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/Cap-go/capacitor-persistent-uuid/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://capgo.app/docs/plugins/persistent-uuid/",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"capacitor",
|
|
30
|
+
"uuid",
|
|
31
|
+
"persistent",
|
|
32
|
+
"identifier",
|
|
33
|
+
"device"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"verify": "bun run verify:ios && bun run verify:android && bun run verify:web",
|
|
37
|
+
"verify:ios": "xcodebuild -scheme CapgoCapacitorPersistentUuid -destination generic/platform=iOS",
|
|
38
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
39
|
+
"verify:web": "bun run build",
|
|
40
|
+
"lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
|
|
41
|
+
"fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
|
|
42
|
+
"eslint": "eslint \"**/*.ts\"",
|
|
43
|
+
"prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
44
|
+
"swiftlint": "node-swiftlint",
|
|
45
|
+
"docgen": "docgen --api PersistentUuidPlugin --output-readme README.md --output-json dist/docs.json",
|
|
46
|
+
"build": "bun run clean && bun run docgen && tsc && rollup -c rollup.config.mjs",
|
|
47
|
+
"clean": "rimraf ./dist",
|
|
48
|
+
"watch": "tsc --watch",
|
|
49
|
+
"prepublishOnly": "bun run build",
|
|
50
|
+
"check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@capacitor/android": "^8.3.4",
|
|
54
|
+
"@capacitor/cli": "^8.3.4",
|
|
55
|
+
"@capacitor/core": "^8.3.4",
|
|
56
|
+
"@capacitor/docgen": "^0.3.1",
|
|
57
|
+
"@capacitor/ios": "^8.3.4",
|
|
58
|
+
"@eslint/js": "^10.0.1",
|
|
59
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
60
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
61
|
+
"@types/node": "^25.9.1",
|
|
62
|
+
"eslint": "^10.4.0",
|
|
63
|
+
"eslint-config-prettier": "^10.1.8",
|
|
64
|
+
"eslint-plugin-import": "^2.32.0",
|
|
65
|
+
"husky": "^9.1.7",
|
|
66
|
+
"prettier": "^3.8.3",
|
|
67
|
+
"prettier-plugin-java": "^2.9.2",
|
|
68
|
+
"prettier-pretty-check": "^0.2.0",
|
|
69
|
+
"rimraf": "^6.1.3",
|
|
70
|
+
"rollup": "^4.60.4",
|
|
71
|
+
"swiftlint": "^2.0.0",
|
|
72
|
+
"typescript": "^6.0.3",
|
|
73
|
+
"typescript-eslint": "^8.59.4"
|
|
74
|
+
},
|
|
75
|
+
"peerDependencies": {
|
|
76
|
+
"@capacitor/core": ">=8.0.0"
|
|
77
|
+
},
|
|
78
|
+
"prettier": "@ionic/prettier-config",
|
|
79
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
80
|
+
"capacitor": {
|
|
81
|
+
"ios": {
|
|
82
|
+
"src": "ios"
|
|
83
|
+
},
|
|
84
|
+
"android": {
|
|
85
|
+
"src": "android"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|