capacitor-mobilecron 0.2.2 → 0.2.4
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/CapacitorMobilecron.podspec +19 -0
- package/dist/esm/definitions.d.ts +13 -0
- package/dist/esm/web.d.ts +13 -0
- package/dist/esm/web.js +12 -0
- package/ios/Plugin/MobileCronPlugin.swift +63 -4
- package/package.json +3 -1
- package/src/definitions.ts +6 -0
- package/src/web.ts +16 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(File.dirname(__FILE__), 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapacitorMobilecron'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = 'https://github.com/rogelioRuiz/capacitor-mobilecron'
|
|
11
|
+
s.author = 'Rogelio Ruiz'
|
|
12
|
+
s.source = { :git => 'https://github.com/rogelioRuiz/capacitor-mobilecron.git', :tag => s.version.to_s }
|
|
13
|
+
|
|
14
|
+
s.source_files = 'ios/Plugin/**/*.{swift,h,m}'
|
|
15
|
+
s.ios.deployment_target = '14.0'
|
|
16
|
+
|
|
17
|
+
s.dependency 'Capacitor'
|
|
18
|
+
s.swift_version = '5.9'
|
|
19
|
+
end
|
|
@@ -29,6 +29,19 @@ export interface MobileCronPlugin {
|
|
|
29
29
|
source: WakeSource;
|
|
30
30
|
paused?: boolean;
|
|
31
31
|
}) => void): Promise<PluginListenerHandle>;
|
|
32
|
+
testNativeEvaluate(): Promise<{
|
|
33
|
+
firedCount: number;
|
|
34
|
+
}>;
|
|
35
|
+
testSetNextDueAt(options: {
|
|
36
|
+
id: string;
|
|
37
|
+
nextDueAtMs: number;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
testInjectPendingEvent(options: {
|
|
40
|
+
event: Record<string, unknown>;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
testGetPendingCount(): Promise<{
|
|
43
|
+
count: number;
|
|
44
|
+
}>;
|
|
32
45
|
}
|
|
33
46
|
export interface CronJobOptions {
|
|
34
47
|
name: string;
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -33,4 +33,17 @@ export declare class MobileCronWeb extends WebPlugin implements MobileCronPlugin
|
|
|
33
33
|
source: WakeSource;
|
|
34
34
|
paused?: boolean;
|
|
35
35
|
}) => void): Promise<PluginListenerHandle>;
|
|
36
|
+
testNativeEvaluate(): Promise<{
|
|
37
|
+
firedCount: number;
|
|
38
|
+
}>;
|
|
39
|
+
testSetNextDueAt(_options: {
|
|
40
|
+
id: string;
|
|
41
|
+
nextDueAtMs: number;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
testInjectPendingEvent(_options: {
|
|
44
|
+
event: Record<string, unknown>;
|
|
45
|
+
}): Promise<void>;
|
|
46
|
+
testGetPendingCount(): Promise<{
|
|
47
|
+
count: number;
|
|
48
|
+
}>;
|
|
36
49
|
}
|
package/dist/esm/web.js
CHANGED
|
@@ -51,4 +51,16 @@ export class MobileCronWeb extends WebPlugin {
|
|
|
51
51
|
async addListener(eventName, listenerFunc) {
|
|
52
52
|
return super.addListener(eventName, listenerFunc);
|
|
53
53
|
}
|
|
54
|
+
async testNativeEvaluate() {
|
|
55
|
+
return { firedCount: 0 };
|
|
56
|
+
}
|
|
57
|
+
async testSetNextDueAt(_options) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
async testInjectPendingEvent(_options) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
async testGetPendingCount() {
|
|
64
|
+
return { count: 0 };
|
|
65
|
+
}
|
|
54
66
|
}
|
|
@@ -16,7 +16,10 @@ public class MobileCronPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
16
16
|
CAPPluginMethod(name: "resumeAll", returnType: CAPPluginReturnPromise),
|
|
17
17
|
CAPPluginMethod(name: "setMode", returnType: CAPPluginReturnPromise),
|
|
18
18
|
CAPPluginMethod(name: "getStatus", returnType: CAPPluginReturnPromise),
|
|
19
|
-
CAPPluginMethod(name: "
|
|
19
|
+
CAPPluginMethod(name: "testNativeEvaluate", returnType: CAPPluginReturnPromise),
|
|
20
|
+
CAPPluginMethod(name: "testSetNextDueAt", returnType: CAPPluginReturnPromise),
|
|
21
|
+
CAPPluginMethod(name: "testInjectPendingEvent", returnType: CAPPluginReturnPromise),
|
|
22
|
+
CAPPluginMethod(name: "testGetPendingCount", returnType: CAPPluginReturnPromise)
|
|
20
23
|
]
|
|
21
24
|
|
|
22
25
|
private static let storageKey = "mobilecron:state"
|
|
@@ -94,6 +97,8 @@ public class MobileCronPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
94
97
|
guard let data = try? JSONSerialization.data(withJSONObject: state),
|
|
95
98
|
let raw = String(data: data, encoding: .utf8) else { return }
|
|
96
99
|
UserDefaults.standard.set(raw, forKey: Self.storageKey)
|
|
100
|
+
// Force immediate disk flush so state survives simctl terminate / force-kill
|
|
101
|
+
UserDefaults.standard.synchronize()
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
// ── Background wake ───────────────────────────────────────────────────────
|
|
@@ -129,6 +134,7 @@ public class MobileCronPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
129
134
|
if let newData = try? JSONSerialization.data(withJSONObject: state),
|
|
130
135
|
let newRaw = String(data: newData, encoding: .utf8) {
|
|
131
136
|
UserDefaults.standard.set(newRaw, forKey: Self.storageKey)
|
|
137
|
+
UserDefaults.standard.synchronize()
|
|
132
138
|
}
|
|
133
139
|
}
|
|
134
140
|
|
|
@@ -255,14 +261,67 @@ public class MobileCronPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
255
261
|
call.resolve(buildStatus())
|
|
256
262
|
}
|
|
257
263
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
// ── E2E test hooks (not for production use) ───────────────────────────────
|
|
265
|
+
|
|
266
|
+
/// Calls NativeJobEvaluator.evaluate() directly and fires pending events.
|
|
267
|
+
@objc func testNativeEvaluate(_ call: CAPPluginCall) {
|
|
261
268
|
let events = NativeJobEvaluator.evaluate(source: "test_trigger")
|
|
262
269
|
firePendingNativeEvents()
|
|
263
270
|
call.resolve(["firedCount": events.count])
|
|
264
271
|
}
|
|
265
272
|
|
|
273
|
+
/// Sets a job's nextDueAt in memory and saves to UserDefaults.
|
|
274
|
+
/// Allows tests to mark a job as "due" without waiting for real time to pass.
|
|
275
|
+
@objc func testSetNextDueAt(_ call: CAPPluginCall) {
|
|
276
|
+
guard let id = call.getString("id"),
|
|
277
|
+
let nextDueAtMs = call.getInt("nextDueAtMs"),
|
|
278
|
+
jobs[id] != nil else {
|
|
279
|
+
call.reject("id or nextDueAtMs missing, or job not found")
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
jobs[id]?["nextDueAt"] = nextDueAtMs
|
|
283
|
+
saveState()
|
|
284
|
+
call.resolve()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/// Appends a pending native event to UserDefaults storage.
|
|
288
|
+
/// Allows tests to simulate what NativeJobEvaluator writes during background execution.
|
|
289
|
+
@objc func testInjectPendingEvent(_ call: CAPPluginCall) {
|
|
290
|
+
guard let event = call.getObject("event") else {
|
|
291
|
+
call.reject("event is required")
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
guard let raw = UserDefaults.standard.string(forKey: Self.storageKey),
|
|
295
|
+
let data = raw.data(using: .utf8),
|
|
296
|
+
var state = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] else {
|
|
297
|
+
call.reject("State not found in UserDefaults")
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
var pending = (state["pendingNativeEvents"] as? [[String: Any]]) ?? []
|
|
301
|
+
pending.append(event)
|
|
302
|
+
state["pendingNativeEvents"] = pending
|
|
303
|
+
guard let newData = try? JSONSerialization.data(withJSONObject: state),
|
|
304
|
+
let newRaw = String(data: newData, encoding: .utf8) else {
|
|
305
|
+
call.reject("Serialization failed")
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
UserDefaults.standard.set(newRaw, forKey: Self.storageKey)
|
|
309
|
+
UserDefaults.standard.synchronize()
|
|
310
|
+
call.resolve()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/// Returns the count of pendingNativeEvents currently in UserDefaults storage.
|
|
314
|
+
@objc func testGetPendingCount(_ call: CAPPluginCall) {
|
|
315
|
+
guard let raw = UserDefaults.standard.string(forKey: Self.storageKey),
|
|
316
|
+
let data = raw.data(using: .utf8),
|
|
317
|
+
let state = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] else {
|
|
318
|
+
call.resolve(["count": 0])
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
let count = (state["pendingNativeEvents"] as? [[String: Any]])?.count ?? 0
|
|
322
|
+
call.resolve(["count": count])
|
|
323
|
+
}
|
|
324
|
+
|
|
266
325
|
private func buildStatus() -> [String: Any] {
|
|
267
326
|
let diagnostics = bgManager?.status ?? .init()
|
|
268
327
|
return [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-mobilecron",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Capacitor scheduling primitive that emits job due events across web, Android, and iOS",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"ios",
|
|
21
21
|
"dist",
|
|
22
22
|
"src",
|
|
23
|
+
"CapacitorMobilecron.podspec",
|
|
23
24
|
"package.json",
|
|
24
25
|
"README.md"
|
|
25
26
|
],
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
"test:watch": "vitest",
|
|
60
61
|
"test:coverage": "vitest run --coverage",
|
|
61
62
|
"test:e2e": "node tests/e2e/test-e2e.mjs",
|
|
63
|
+
"test:e2e:ios": "node tests/e2e/test-e2e-ios.mjs",
|
|
62
64
|
"prepack": "npm run build"
|
|
63
65
|
},
|
|
64
66
|
"peerDependencies": {
|
package/src/definitions.ts
CHANGED
|
@@ -17,6 +17,12 @@ export interface MobileCronPlugin {
|
|
|
17
17
|
addListener(event: 'overdueJobs', handler: (data: OverdueEvent) => void): Promise<PluginListenerHandle>
|
|
18
18
|
addListener(event: 'statusChanged', handler: (data: CronStatus) => void): Promise<PluginListenerHandle>
|
|
19
19
|
addListener(event: 'nativeWake', handler: (data: { source: WakeSource; paused?: boolean }) => void): Promise<PluginListenerHandle>
|
|
20
|
+
|
|
21
|
+
// E2E test hooks (not for production use)
|
|
22
|
+
testNativeEvaluate(): Promise<{ firedCount: number }>
|
|
23
|
+
testSetNextDueAt(options: { id: string; nextDueAtMs: number }): Promise<void>
|
|
24
|
+
testInjectPendingEvent(options: { event: Record<string, unknown> }): Promise<void>
|
|
25
|
+
testGetPendingCount(): Promise<{ count: number }>
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
export interface CronJobOptions {
|
package/src/web.ts
CHANGED
|
@@ -83,4 +83,20 @@ export class MobileCronWeb extends WebPlugin implements MobileCronPlugin {
|
|
|
83
83
|
async addListener(eventName: string, listenerFunc: (data: any) => void): Promise<PluginListenerHandle> {
|
|
84
84
|
return super.addListener(eventName, listenerFunc)
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
async testNativeEvaluate(): Promise<{ firedCount: number }> {
|
|
88
|
+
return { firedCount: 0 }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async testSetNextDueAt(_options: { id: string; nextDueAtMs: number }): Promise<void> {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async testInjectPendingEvent(_options: { event: Record<string, unknown> }): Promise<void> {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async testGetPendingCount(): Promise<{ count: number }> {
|
|
100
|
+
return { count: 0 }
|
|
101
|
+
}
|
|
86
102
|
}
|